File 2001-new-welcomeview.patch of Package okular
diff --git a/CMakeLists.txt b/CMakeLists.txt
index a0bb9a545cf61367c5e2f2d39d41e698a065f993..c852dad587e46d98d8d820a900538d524e8d2370 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -412,6 +412,7 @@ install( FILES
interfaces/printinterface.h
interfaces/saveinterface.h
interfaces/viewerinterface.h
+ interfaces/bookmarksinterface.h
DESTINATION ${KDE_INSTALL_INCLUDEDIR}/okular/interfaces COMPONENT Devel)
ki18n_wrap_ui(okularcore_SRCS
diff --git a/aboutdata.h b/aboutdata.h
index 90cfa95328370528130b8d1d163d8a5f9b5c185c..aae106d60d7078a27eeff99577e8aada9fd3dd15 100644
--- a/aboutdata.h
+++ b/aboutdata.h
@@ -13,6 +13,8 @@
#include <KLocalizedString>
+#include <QIcon>
+
inline KAboutData okularAboutData()
{
KAboutData about(QStringLiteral("okular"),
@@ -28,6 +30,7 @@ inline KAboutData okularAboutData()
QString(),
QStringLiteral("https://okular.kde.org"));
+ about.setProgramLogo(QIcon(QStringLiteral(":/kxmlgui5/okular/okular.svgz")));
about.addAuthor(i18n("Pino Toscano"), i18n("Former maintainer"), QStringLiteral("pino@kde.org"));
about.addAuthor(i18n("Tobias Koenig"), i18n("Lots of framework work, FictionBook backend and former ODT backend"), QStringLiteral("tokoe@kde.org"));
about.addAuthor(i18n("Albert Astals Cid"), i18n("Developer"), QStringLiteral("aacid@kde.org"));
diff --git a/autotests/CMakeLists.txt b/autotests/CMakeLists.txt
index d0d63678ce22e44106bc0d0024eb36916090c7c4..51752be7ed1e4eaa6d0b05e3dc736ae1038e055e 100644
--- a/autotests/CMakeLists.txt
+++ b/autotests/CMakeLists.txt
@@ -119,7 +119,7 @@ ecm_add_test(check_distinguished_name_parser.cpp
LINK_LIBRARIES Qt6::Test)
if(PlasmaActivities_FOUND AND BUILD_DESKTOP)
- ecm_add_test(mainshelltest.cpp ../shell/okular_main.cpp ../shell/shellutils.cpp ../shell/shell.cpp ../shell/welcomescreen.cpp ../shell/recentitemsmodel.cpp closedialoghelper.cpp
+ ecm_add_test(mainshelltest.cpp ../shell/okular_main.cpp ../shell/shellutils.cpp ../shell/shell.cpp ../shell/welcomeview/welcomeview.cpp ../shell/welcomeview/recentfilesmodel.cpp ../shell/welcomeview/bookmarksmodel.cpp closedialoghelper.cpp
TEST_NAME "mainshelltest"
LINK_LIBRARIES Qt6::Test Plasma::Activities okularpart okularcore
)
@@ -131,7 +131,7 @@ if(PlasmaActivities_FOUND AND BUILD_DESKTOP)
endif()
if(BUILD_DESKTOP)
- ecm_add_test(annotationtoolbartest.cpp ../shell/okular_main.cpp ../shell/shellutils.cpp ../shell/shell.cpp ../shell/welcomescreen.cpp ../shell/recentitemsmodel.cpp closedialoghelper.cpp ../shell/welcomescreen.ui
+ ecm_add_test(annotationtoolbartest.cpp ../shell/okular_main.cpp ../shell/shellutils.cpp ../shell/shell.cpp ../shell/welcomeview/welcomeview.cpp ../shell/welcomeview/recentfilesmodel.cpp ../shell/welcomeview/bookmarksmodel.cpp closedialoghelper.cpp ../shell/welcomeview/welcomeview.ui
TEST_NAME "annotationtoolbartest"
LINK_LIBRARIES Qt6::Test okularpart
)
diff --git a/interfaces/bookmarksinterface.h b/interfaces/bookmarksinterface.h
new file mode 100644
index 0000000000000000000000000000000000000000..3ec5b380e63380d33e996e2b9118b8abf52e56b0
--- /dev/null
+++ b/interfaces/bookmarksinterface.h
@@ -0,0 +1,62 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Eugene Popov <popov895@ukr.net>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef _OKULAR_BOOKMARKSINTERFACE_H_
+#define _OKULAR_BOOKMARKSINTERFACE_H_
+
+#include "../core/okularcore_export.h"
+
+#include <QUrl>
+
+#ifdef Q_OS_WIN
+#define BOOKMARKSINTERFACE_EXPORT __declspec(dllexport)
+#else
+#define BOOKMARKSINTERFACE_EXPORT OKULARCORE_EXPORT
+#endif
+
+namespace Okular
+{
+/**
+ * @short Abstract interface for managing bookmarks
+ *
+ * This interface can be used to list and open bookmarks.
+ */
+class BOOKMARKSINTERFACE_EXPORT BookmarksInterface
+{
+public:
+ struct Bookmark {
+ QString title;
+ QUrl url;
+ };
+
+ BookmarksInterface() = default;
+ virtual ~BookmarksInterface() = default;
+
+ BookmarksInterface(const BookmarksInterface &) = delete;
+ BookmarksInterface &operator=(const BookmarksInterface &) = delete;
+
+ /**
+ * Returns bookmarks.
+ */
+ virtual QMultiMap<QUrl, Bookmark> getBookmarks() const = 0;
+
+ /**
+ * Open bookmark.
+ */
+ virtual void openBookmark(const QUrl &bookmark) = 0;
+
+ // SIGNALS
+
+ /**
+ * This signal is emitted whenever the bookmark list has changed.
+ */
+ void bookmarksChanged();
+};
+}
+
+Q_DECLARE_INTERFACE(Okular::BookmarksInterface, "org.kde.okular.BookmarksInterface/0.1")
+
+#endif // _OKULAR_BOOKMARKSINTERFACE_H_
diff --git a/part/part.cpp b/part/part.cpp
index 73f56dc55a5945c6beeb196ded3e4896ad392ee2..ae55eda1282b05ac1ac6e6ea24dd597d4b205370 100644
--- a/part/part.cpp
+++ b/part/part.cpp
@@ -359,6 +359,8 @@ Part::Part(QObject *parent, const QVariantList &args)
setWindowTitleFromDocument();
});
+ connect(m_document->bookmarkManager(), &Okular::BookmarkManager::bookmarksChanged, this, &Part::bookmarksChanged);
+
if (parent && parent->metaObject()->indexOfSlot(QMetaObject::normalizedSignature("slotQuit()").constData()) != -1) {
connect(m_document, SIGNAL(quit()), parent, SLOT(slotQuit())); // clazy:exclude=old-style-connect
} else {
@@ -468,8 +470,6 @@ Part::Part(QObject *parent, const QVariantList &args)
rightLayout->addWidget(m_signatureMessage);
m_pageView = new PageView(rightContainer, m_document);
rightContainer->setFocusProxy(m_pageView);
- QMetaObject::invokeMethod(m_pageView, "setFocus", Qt::QueuedConnection); // usability setting
- // m_splitter->setFocusProxy(m_pageView);
connect(m_pageView.data(), &PageView::rightClick, this, &Part::slotShowMenu);
connect(m_pageView, &PageView::triggerSearch, this, [this](const QString &searchText) {
m_findBar->startSearch(searchText);
@@ -1095,6 +1095,26 @@ void Part::setModified(bool modified)
}
}
+QMultiMap<QUrl, BookmarksInterface::Bookmark> Part::getBookmarks() const
+{
+ QMultiMap<QUrl, BookmarksInterface::Bookmark> bookmarks;
+
+ const QList<QUrl> files = m_document->bookmarkManager()->files();
+ for (const QUrl &file : files) {
+ const KBookmark::List &bookmarkList = m_document->bookmarkManager()->bookmarks(file);
+ for (const KBookmark &bookmark : bookmarkList) {
+ bookmarks.insert(file, {bookmark.text(), bookmark.url()});
+ }
+ }
+
+ return bookmarks;
+}
+
+void Part::openBookmark(const QUrl &bookmark)
+{
+ openUrlFromBookmarks(bookmark);
+}
+
void Part::slotHandleActivatedSourceReference(const QString &absFileName, int line, int col, bool *handled)
{
Q_EMIT openSourceReference(absFileName, line, col);
diff --git a/part/part.h b/part/part.h
index e54b01b0d4ab5cdb0561b30b3a1ba2e9bf14be08..f3f1733bbe985002b4c2663f32175b313afa9544 100644
--- a/part/part.h
+++ b/part/part.h
@@ -26,7 +26,6 @@
#include <QList>
#include <QPointer>
#include <QProcess>
-#include <QUrl>
#include <KCompressionDevice>
#include <KIO/Job>
@@ -36,6 +35,7 @@
#include "../core/document.h"
#include "../core/observer.h"
+#include "../interfaces/bookmarksinterface.h"
#include "../interfaces/viewerinterface.h"
#include "../kdocumentviewer.h"
@@ -110,12 +110,13 @@ enum EmbedMode {
* @author Wilco Greven <greven@kde.org>
* @version 0.2
*/
-class OKULARPART_EXPORT Part : public KParts::ReadWritePart, public Okular::DocumentObserver, public KDocumentViewer, public Okular::ViewerInterface
+class OKULARPART_EXPORT Part : public KParts::ReadWritePart, public Okular::DocumentObserver, public KDocumentViewer, public Okular::ViewerInterface, public Okular::BookmarksInterface
{
Q_OBJECT
Q_CLASSINFO("D-Bus Interface", "org.kde.okular")
Q_INTERFACES(KDocumentViewer)
Q_INTERFACES(Okular::ViewerInterface)
+ Q_INTERFACES(Okular::BookmarksInterface)
friend class PartTest;
@@ -161,6 +162,10 @@ public:
*/
QAbstractItemModel *annotationsModel() const;
+ // Okular::BookmarksInterface
+ QMultiMap<QUrl, BookmarksInterface::Bookmark> getBookmarks() const override;
+ void openBookmark(const QUrl &bookmark) override;
+
public Q_SLOTS: // dbus
Q_SCRIPTABLE Q_NOREPLY void goToPage(uint page) override;
Q_SCRIPTABLE Q_NOREPLY void openDocument(const QString &doc);
@@ -200,6 +205,9 @@ Q_SIGNALS:
*/
void requestOpenNewlySignedFile(const QString &path, int pageNumber);
+ // Okular::BookmarksInterface
+ void bookmarksChanged();
+
protected:
// reimplemented from KParts::ReadWritePart
bool openFile() override;
diff --git a/shell/CMakeLists.txt b/shell/CMakeLists.txt
index c481000c313ea6de9503c808ba7ba6fa6f58147a..e5b9682259ef23f4cc1c8877b5741ab295a95406 100644
--- a/shell/CMakeLists.txt
+++ b/shell/CMakeLists.txt
@@ -11,14 +11,15 @@ set(okular_SRCS
okular_main.cpp
shell.cpp
shellutils.cpp
- recentitemsmodel.cpp
- welcomescreen.cpp
+ welcomeview/welcomeview.cpp
+ welcomeview/recentfilesmodel.cpp
+ welcomeview/bookmarksmodel.cpp
shell.qrc
)
ki18n_wrap_ui(okular_SRCS
- welcomescreen.ui)
+ welcomeview/welcomeview.ui)
file(GLOB ICONS_SRCS "${CMAKE_CURRENT_SOURCE_DIR}/../icons/*-apps-okular.png")
ecm_add_app_icon(okular_SRCS ICONS ${ICONS_SRCS})
diff --git a/shell/recentitemsmodel.cpp b/shell/recentitemsmodel.cpp
deleted file mode 100644
index 7f4d15a4423494e40ee52445c7c6fbb820984c50..0000000000000000000000000000000000000000
--- a/shell/recentitemsmodel.cpp
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- SPDX-FileCopyrightText: 2021 Jiří Wolker <woljiri@gmail.com>
-
- SPDX-License-Identifier: GPL-2.0-or-later
-*/
-
-#include "recentitemsmodel.h"
-
-#include <QFile>
-#include <QFileIconProvider>
-#include <QFileInfo>
-#include <QIcon>
-
-#include <KConfigGroup>
-
-RecentItemsModel::RecentItemsModel()
-{
-}
-
-RecentItemsModel::~RecentItemsModel()
-{
-}
-
-void RecentItemsModel::loadEntries(const KConfigGroup &cg)
-{
- clearEntries();
-
- // Based on implementation of KRecentFilesAction::loadEntries.
-
- // read file list
- for (int i = 1; i <= maxItems(); i++) {
- const QString key = QStringLiteral("File%1").arg(i);
- const QString value = cg.readPathEntry(key, QString());
- if (value.isEmpty()) {
- continue;
- }
- const QUrl url = QUrl::fromUserInput(value);
-
- // Don't restore if file doesn't exist anymore
- if (url.isLocalFile() && !QFile::exists(url.toLocalFile())) {
- continue;
- }
-
- const QString nameKey = QStringLiteral("Name%1").arg(i);
- const QString nameValue = cg.readPathEntry(nameKey, url.fileName());
- m_recentItems.append(RecentItem {nameValue, url});
- }
-
- Q_EMIT layoutChanged();
-}
-
-void RecentItemsModel::clearEntries()
-{
- m_recentItems.clear();
-
- Q_EMIT layoutChanged();
-}
-
-int RecentItemsModel::rowCount(const QModelIndex &parent) const
-{
- Q_UNUSED(parent);
-
- return m_recentItems.size();
-}
-
-QVariant RecentItemsModel::data(const QModelIndex &index, int role) const
-{
- const RecentItemsModel::RecentItem *item = getItem(index);
-
- if (item != nullptr) {
- switch (role) {
- case Qt::ItemDataRole::DisplayRole:
- if (item->name.isEmpty()) {
- if (item->url.isLocalFile()) {
- return item->url.toLocalFile();
- } else {
- return item->url.toString();
- }
- } else {
- return item->name;
- }
-
- case Qt::ItemDataRole::ToolTipRole:
- if (item->url.isLocalFile()) {
- return item->url.toLocalFile();
- } else {
- return item->url.toString();
- }
-
- case Qt::ItemDataRole::DecorationRole:
- if (item->url.isLocalFile()) {
- return m_iconProvider.icon(QFileInfo(item->url.toLocalFile()));
- } else {
- // Fallback icon for remote files.
- return QIcon::fromTheme(QStringLiteral("network-server"));
- }
-
- default:
- return QVariant();
- }
- } else {
- return QVariant();
- }
-}
-
-RecentItemsModel::RecentItem const *RecentItemsModel::getItem(int index) const
-{
- if (m_recentItems.size() > index && index >= 0) {
- // We reverse the order of items.
- return &m_recentItems[m_recentItems.size() - index - 1];
- } else {
- return nullptr;
- }
-}
-
-RecentItemsModel::RecentItem const *RecentItemsModel::getItem(const QModelIndex &index) const
-{
- return getItem(index.row());
-}
diff --git a/shell/recentitemsmodel.h b/shell/recentitemsmodel.h
deleted file mode 100644
index 0725ca62943170195cec6a8bf79226a36184665a..0000000000000000000000000000000000000000
--- a/shell/recentitemsmodel.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- SPDX-FileCopyrightText: 2021 Jiří Wolker <woljiri@gmail.com>
-
- SPDX-License-Identifier: GPL-2.0-or-later
-*/
-
-#ifndef RECENTITEMSMODEL_H
-#define RECENTITEMSMODEL_H
-
-#include <QAbstractListModel>
-#include <QFileIconProvider>
-#include <QList>
-#include <QModelIndex>
-#include <QString>
-#include <QUrl>
-
-class KConfigGroup;
-
-/**
- * @todo write docs
- */
-class RecentItemsModel : public QAbstractListModel
-{
- Q_OBJECT
-
-public:
- struct RecentItem {
- QString name;
- QUrl url;
- };
-
- /**
- * Default constructor
- */
- RecentItemsModel();
-
- /**
- * Destructor
- */
- ~RecentItemsModel() override;
-
- void loadEntries(const KConfigGroup &cg);
- void clearEntries();
-
- int maxItems() const
- {
- return m_maxItems;
- }
-
- RecentItemsModel::RecentItem const *getItem(const QModelIndex &) const;
- RecentItemsModel::RecentItem const *getItem(int index) const;
-
- // Model implementation:
- int rowCount(const QModelIndex &parent = QModelIndex()) const override;
- QVariant data(const QModelIndex &index, int role = Qt::ItemDataRole::DisplayRole) const override;
-
-private:
- QList<RecentItemsModel::RecentItem> m_recentItems;
-
- int m_maxItems = 20;
- QFileIconProvider m_iconProvider;
-};
-
-#endif // RECENTITEMSMODEL_H
diff --git a/shell/shell.cpp b/shell/shell.cpp
index 0ff9efebd2618f64bb616b54b13715e6ba190dee..f69fe6384e95f63326e83b349f40a1d24a331b8d 100644
--- a/shell/shell.cpp
+++ b/shell/shell.cpp
@@ -61,9 +61,11 @@
#include <kxmlgui_version.h>
// local includes
+#include "../interfaces/bookmarksinterface.h"
#include "../interfaces/viewerinterface.h"
#include "kdocumentviewer.h"
#include "shellutils.h"
+#include "welcomeview/welcomeview.h"
static const char *shouldShowMenuBarComingFromFullScreen = "shouldShowMenuBarComingFromFullScreen";
static const char *shouldShowToolBarComingFromFullScreen = "shouldShowToolBarComingFromFullScreen";
@@ -220,16 +222,24 @@ Shell::Shell(const QString &serializedOptions)
m_centralStackedWidget = new ResizableStackedWidget();
setCentralWidget(m_centralStackedWidget);
+ m_sidebar = new Sidebar;
+ m_sidebar->setObjectName(QStringLiteral("okular_sidebar"));
+ m_sidebar->setContextMenuPolicy(Qt::ActionsContextMenu);
+ m_sidebar->setWindowTitle(i18n("Sidebar"));
+ connect(m_sidebar, &QDockWidget::visibilityChanged, this, [this](bool visible) {
+ // sync sidebar visibility with the m_showSidebarAction only if welcome screen is hidden
+ if (m_showSidebarAction && m_centralStackedWidget->currentWidget() != m_welcomeScreen) {
+ m_showSidebarAction->setChecked(visible);
+ }
+ });
+ addDockWidget(Qt::LeftDockWidgetArea, m_sidebar);
+
+ setupActions();
+
// Setup the welcome screen
- m_welcomeScreen = new WelcomeScreen(this);
- connect(m_welcomeScreen, &WelcomeScreen::openClicked, this, &Shell::fileOpen);
- connect(m_welcomeScreen, &WelcomeScreen::closeClicked, this, &Shell::hideWelcomeScreen);
- connect(m_welcomeScreen, &WelcomeScreen::recentItemClicked, this, [this](const QUrl &url) { openUrl(url); });
- connect(m_welcomeScreen, &WelcomeScreen::forgetRecentItem, this, &Shell::forgetRecentItem);
+ m_welcomeScreen = new WelcomeView(this, firstPart);
m_centralStackedWidget->addWidget(m_welcomeScreen);
- m_welcomeScreen->installEventFilter(this);
-
// Setup tab bar
m_tabWidget = new QTabWidget(this);
m_tabWidget->setTabsClosable(true);
@@ -239,34 +249,17 @@ Shell::Shell(const QString &serializedOptions)
m_tabWidget->setMovable(true);
m_tabWidget->setAcceptDrops(true);
+
+ m_welcomeScreen->installEventFilter(this);
m_tabWidget->tabBar()->installEventFilter(this);
m_centralStackedWidget->addWidget(m_tabWidget);
+ m_centralStackedWidget->setCurrentWidget(m_tabWidget);
connect(m_tabWidget, &QTabWidget::currentChanged, this, &Shell::setActiveTab);
connect(m_tabWidget, &QTabWidget::tabCloseRequested, this, &Shell::closeTab);
connect(m_tabWidget->tabBar(), &QTabBar::tabMoved, this, &Shell::moveTabData);
- m_sidebar = new Sidebar;
- m_sidebar->setObjectName(QStringLiteral("okular_sidebar"));
- m_sidebar->setContextMenuPolicy(Qt::ActionsContextMenu);
- m_sidebar->setWindowTitle(i18n("Sidebar"));
- connect(m_sidebar, &QDockWidget::visibilityChanged, this, [this](bool visible) {
- // sync sidebar visibility with the m_showSidebarAction only if welcome screen is hidden
- if (m_showSidebarAction && m_centralStackedWidget->currentWidget() != m_welcomeScreen) {
- m_showSidebarAction->setChecked(visible);
- }
- if (m_centralStackedWidget->currentWidget() == m_welcomeScreen) {
- // MainWindow tries hard to make its child dockwidgets shown, but during
- // welcome screen we don't want to see the sidebar,
- // so try a bit more to actually hide it.
- m_sidebar->hide();
- }
- });
- addDockWidget(Qt::LeftDockWidgetArea, m_sidebar);
-
- // then, setup our actions
- setupActions();
connect(QCoreApplication::instance(), &QCoreApplication::aboutToQuit, this, &QObject::deleteLater);
// and integrate the part's GUI with the shell's
setupGUI(Keys | ToolBar | Save);
@@ -411,6 +404,11 @@ bool Shell::openDocument(const QUrl &url, const QString &serializedOptions)
return true;
}
+KRecentFilesAction *Shell::recentFilesAction() const
+{
+ return m_recent;
+}
+
bool Shell::openDocument(const QString &urlString, const QString &serializedOptions)
{
return openDocument(QUrl(urlString), serializedOptions);
@@ -495,6 +493,18 @@ void Shell::openUrl(const QUrl &url, const QString &serializedOptions)
}
}
+void Shell::openBookmark(const QUrl &url)
+{
+ hideWelcomeScreen();
+
+ const int activeTab = m_tabWidget->currentIndex();
+ if (activeTab >= 0 && activeTab < m_tabs.size()) {
+ auto activePart = qobject_cast<Okular::BookmarksInterface *>(m_tabs[activeTab].part);
+ Q_ASSERT(activePart);
+ activePart->openBookmark(url);
+ }
+}
+
void Shell::closeUrl()
{
closeTab(m_tabWidget->currentIndex());
@@ -564,8 +574,6 @@ void Shell::setupActions()
m_recent = KStandardAction::openRecent(this, SLOT(openUrl(QUrl)), actionCollection());
m_recent->setToolBarMode(KRecentFilesAction::MenuMode);
connect(m_recent, &QAction::triggered, this, &Shell::showOpenRecentMenu);
- connect(m_recent, &KRecentFilesAction::recentListCleared, this, &Shell::refreshRecentsOnWelcomeScreen);
- connect(m_welcomeScreen, &WelcomeScreen::forgetAllRecents, m_recent, &KRecentFilesAction::clear);
m_recent->setToolTip(i18n("Click to open a file\nClick and hold to open a recent file"));
m_recent->setWhatsThis(i18n("<b>Click</b> to open a file or <b>Click and hold</b> to select a recent file"));
m_printAction = KStandardAction::print(this, SLOT(print()), actionCollection());
@@ -604,6 +612,12 @@ void Shell::setupActions()
m_lockSidebarAction->setText(i18n("Lock Sidebar"));
connect(m_lockSidebarAction, &QAction::triggered, m_sidebar, &Sidebar::setLocked);
m_sidebar->addAction(m_lockSidebarAction);
+
+ QAction *showWelcomeScreenAction = actionCollection()->addAction(QStringLiteral("help_welcome_page"));
+ showWelcomeScreenAction->setText(i18n("Welcome Page"));
+ showWelcomeScreenAction->setIcon(qApp->windowIcon());
+ showWelcomeScreenAction->setWhatsThis(i18n("Show the welcome page"));
+ connect(showWelcomeScreenAction, &QAction::triggered, this, [this]() { showWelcomeScreen(true); });
}
void Shell::saveProperties(KConfigGroup &group)
@@ -888,6 +902,8 @@ void Shell::setActiveTab(int tab)
}
m_sidebar->setCurrentWidget(sideContainer);
+ m_tabs[tab].part->widget()->setFocus();
+
m_showSidebarAction = m_tabs[tab].part->actionCollection()->action(QStringLiteral("show_leftpanel"));
Q_ASSERT(m_showSidebarAction);
m_showSidebarAction->disconnect();
@@ -1135,28 +1151,19 @@ void Shell::hideWelcomeScreen()
m_showSidebarAction->setEnabled(true);
}
-void Shell::showWelcomeScreen()
+void Shell::showWelcomeScreen(bool force)
{
+ if (!force) {
+ const KConfigGroup configGroup = KSharedConfig::openConfig()->group(QStringLiteral("General"));
+ if (!configGroup.readEntry("ShowWelcomeScreenOnStartup", true)) {
+ return;
+ }
+ }
+
m_showSidebarAction->setEnabled(false);
m_centralStackedWidget->setCurrentWidget(m_welcomeScreen);
+ m_welcomeScreen->findChild<QPushButton *>()->setFocus();
m_sidebar->setVisible(false);
-
- refreshRecentsOnWelcomeScreen();
-}
-
-void Shell::refreshRecentsOnWelcomeScreen()
-{
- saveRecents();
- m_welcomeScreen->loadRecents();
-}
-
-void Shell::forgetRecentItem(QUrl const &url)
-{
- if (m_recent != nullptr) {
- m_recent->removeUrl(url);
- saveRecents();
- refreshRecentsOnWelcomeScreen();
- }
}
#include "shell.moc"
diff --git a/shell/shell.h b/shell/shell.h
index 4e7738857ffb847d01363e12debeaef3ec05ecbc..020268fa8d386ce1d19bdd7ccdff3b70b38d497d 100644
--- a/shell/shell.h
+++ b/shell/shell.h
@@ -27,9 +27,8 @@
#endif
#include <QStackedWidget>
-#include "welcomescreen.h"
-
class Sidebar;
+class WelcomeView;
class KRecentFilesAction;
class KToggleAction;
class QTabWidget;
@@ -70,6 +69,7 @@ public:
bool isValid() const;
bool openDocument(const QUrl &url, const QString &serializedOptions);
+ KRecentFilesAction *recentFilesAction() const;
public Q_SLOTS:
Q_SCRIPTABLE Q_NOREPLY void tryRaise(const QString &startupId);
@@ -114,13 +114,18 @@ protected:
void showEvent(QShowEvent *event) override;
void keyPressEvent(QKeyEvent *) override;
-private Q_SLOTS:
+public Q_SLOTS:
void fileOpen();
+ void openUrl(const QUrl &url, const QString &serializedOptions = QString());
+ void openBookmark(const QUrl &url);
+
+ void hideWelcomeScreen();
+ void showWelcomeScreen(bool force = false);
+private Q_SLOTS:
void slotUpdateFullScreen();
void slotShowMenubar();
- void openUrl(const QUrl &url, const QString &serializedOptions = QString());
void showOpenRecentMenu();
void closeUrl();
void print();
@@ -151,12 +156,6 @@ private Q_SLOTS:
void slotFitWindowToPage(const QSize pageViewSize, const QSize pageSize);
- void hideWelcomeScreen();
- void showWelcomeScreen();
- void refreshRecentsOnWelcomeScreen();
-
- void forgetRecentItem(QUrl const &url);
-
Q_SIGNALS:
void moveSplitter(int sideWidgetSize);
@@ -186,7 +185,7 @@ private:
bool m_unique;
QTabWidget *m_tabWidget;
KToggleAction *m_openInTab;
- WelcomeScreen *m_welcomeScreen;
+ WelcomeView *m_welcomeScreen;
QStackedWidget *m_centralStackedWidget;
Sidebar *m_sidebar = nullptr;
diff --git a/shell/shell.qrc b/shell/shell.qrc
index 73705f2287fce8424c8f61ddcf91a9355dca11d5..a5637261819d6c69789a006a78e2559279eccf60 100644
--- a/shell/shell.qrc
+++ b/shell/shell.qrc
@@ -2,5 +2,6 @@
<RCC version="1.0">
<qresource prefix="/kxmlgui5/okular">
<file>shell.rc</file>
+ <file alias="okular.svgz">../icons/hisc-apps-okular.svgz</file>
</qresource>
</RCC>
diff --git a/shell/shell.rc b/shell/shell.rc
index d54f12715417e23fea2d240cdab733e35aefe295..81b230a41770062bc7476615bffc600948464452 100644
--- a/shell/shell.rc
+++ b/shell/shell.rc
@@ -18,6 +18,7 @@
<Merge/>
<Menu name="help">
<DefineGroup append="about_merge" name="about_merge" />
+ <Action name="help_welcome_page" group="about_merge"/>
</Menu>
</MenuBar>
<ToolBar noMerge="1" name="mainToolBar" >
diff --git a/shell/welcomescreen.cpp b/shell/welcomescreen.cpp
deleted file mode 100644
index e7b5f996307e007831a2e1f012254cd13396f35f..0000000000000000000000000000000000000000
--- a/shell/welcomescreen.cpp
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- SPDX-FileCopyrightText: 2021 Jiří Wolker <woljiri@gmail.com>
-
- SPDX-License-Identifier: GPL-2.0-or-later
-*/
-
-#include "welcomescreen.h"
-
-#include <KConfigGroup>
-#include <KIO/OpenFileManagerWindowJob>
-#include <KIconLoader>
-#include <KSharedConfig>
-
-#include <QAction>
-#include <QClipboard>
-#include <QGraphicsOpacityEffect>
-#include <QGuiApplication>
-#include <QMenu>
-#include <QResizeEvent>
-#include <QStyledItemDelegate>
-
-#include "recentitemsmodel.h"
-
-class RecentsListItemDelegate : public QStyledItemDelegate
-{
- Q_OBJECT
-
-public:
- explicit RecentsListItemDelegate(WelcomeScreen *welcomeScreen)
- : m_welcomeScreen(welcomeScreen)
- {
- }
-
- WelcomeScreen *welcomeScreen() const
- {
- return m_welcomeScreen;
- }
-
- bool editorEvent(QEvent *event, QAbstractItemModel *aModel, const QStyleOptionViewItem &styleOptionViewItem, const QModelIndex &index) override
- {
- const RecentItemsModel *model = static_cast<RecentItemsModel *>(aModel);
- const RecentItemsModel::RecentItem *item = model->getItem(index);
-
- QPoint menuPosition;
-
- if (item != nullptr) {
- bool willOpenMenu = false;
- if (event->type() == QEvent::ContextMenu) {
- willOpenMenu = true;
- menuPosition = static_cast<QContextMenuEvent *>(event)->globalPos();
- }
- if (event->type() == QEvent::MouseButtonPress) {
- if (static_cast<QMouseEvent *>(event)->button() == Qt::MouseButton::RightButton) {
- willOpenMenu = true;
- menuPosition = static_cast<QMouseEvent *>(event)->globalPosition().toPoint();
- }
- }
-
- if (willOpenMenu) {
- event->accept();
-
- QMenu menu;
-
- QAction *copyPathAction = new QAction(i18n("&Copy Path"));
- copyPathAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy")));
- connect(copyPathAction, &QAction::triggered, this, [item]() {
- QString path;
- if (item->url.isLocalFile()) {
- path = item->url.toLocalFile();
- } else {
- path = item->url.toString();
- }
- QGuiApplication::clipboard()->setText(path);
- });
- menu.addAction(copyPathAction);
-
- QAction *showDirectoryAction = new QAction(i18n("&Open Containing Folder"));
- showDirectoryAction->setIcon(QIcon::fromTheme(QStringLiteral("document-open-folder")));
- connect(showDirectoryAction, &QAction::triggered, this, [item]() {
- if (item->url.isLocalFile()) {
- KIO::highlightInFileManager({item->url});
- }
- });
- menu.addAction(showDirectoryAction);
- if (!item->url.isLocalFile()) {
- showDirectoryAction->setEnabled(false);
- }
-
- QAction *forgetItemAction = new QAction(i18nc("recent items context menu", "&Forget This Item"));
- forgetItemAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-clear-history")));
- connect(forgetItemAction, &QAction::triggered, this, [this, item]() { Q_EMIT welcomeScreen()->forgetRecentItem(item->url); });
- menu.addAction(forgetItemAction);
-
- menu.exec(menuPosition);
-
- return true;
- }
- }
-
- return QStyledItemDelegate::editorEvent(event, aModel, styleOptionViewItem, index);
- }
-
-private:
- WelcomeScreen *m_welcomeScreen;
-};
-
-WelcomeScreen::WelcomeScreen(QWidget *parent)
- : QWidget(parent)
- , m_recentsModel(new RecentItemsModel)
- , m_recentsItemDelegate(new RecentsListItemDelegate(this))
-{
- Q_ASSERT(parent);
-
- setupUi(this);
-
- connect(openButton, &QPushButton::clicked, this, &WelcomeScreen::openClicked);
- connect(closeButton, &QPushButton::clicked, this, &WelcomeScreen::closeClicked);
-
- recentsListView->setContextMenuPolicy(Qt::DefaultContextMenu);
- recentsListView->setModel(m_recentsModel);
- recentsListView->setItemDelegate(m_recentsItemDelegate);
- connect(recentsListView, &QListView::activated, this, &WelcomeScreen::recentsItemActivated);
-
- connect(m_recentsModel, &RecentItemsModel::layoutChanged, this, &WelcomeScreen::recentListChanged);
-
- QVBoxLayout *noRecentsLayout = new QVBoxLayout(recentsListView);
- recentsListView->setLayout(noRecentsLayout);
- m_noRecentsLabel = new QLabel(recentsListView);
- QFont placeholderLabelFont;
- // To match the size of a level 2 Heading/KTitleWidget
- placeholderLabelFont.setPointSize(qRound(placeholderLabelFont.pointSize() * 1.3));
- noRecentsLayout->addWidget(m_noRecentsLabel);
- m_noRecentsLabel->setFont(placeholderLabelFont);
- m_noRecentsLabel->setTextInteractionFlags(Qt::NoTextInteraction);
- m_noRecentsLabel->setWordWrap(true);
- m_noRecentsLabel->setAlignment(Qt::AlignCenter);
- m_noRecentsLabel->setText(i18nc("on welcome screen", "No recent documents"));
- // Match opacity of QML placeholder label component
- auto *effect = new QGraphicsOpacityEffect(m_noRecentsLabel);
- effect->setOpacity(0.5);
- m_noRecentsLabel->setGraphicsEffect(effect);
-
- connect(forgetAllButton, &QToolButton::clicked, this, &WelcomeScreen::forgetAllRecents);
-}
-
-WelcomeScreen::~WelcomeScreen()
-{
- delete m_recentsModel;
- delete m_recentsItemDelegate;
-}
-
-void WelcomeScreen::showEvent(QShowEvent *e)
-{
- if (appIcon->pixmap(Qt::ReturnByValue).isNull()) {
- appIcon->setPixmap(QIcon::fromTheme(QStringLiteral("okular")).pixmap(KIconLoader::SizeEnormous));
- }
-
- QWidget::showEvent(e);
-}
-
-void WelcomeScreen::loadRecents()
-{
- m_recentsModel->loadEntries(KSharedConfig::openConfig()->group(QStringLiteral("Recent Files")));
-}
-
-int WelcomeScreen::recentsCount()
-{
- return m_recentsModel->rowCount();
-}
-
-void WelcomeScreen::recentsItemActivated(const QModelIndex &index)
-{
- const RecentItemsModel::RecentItem *item = m_recentsModel->getItem(index);
- if (item != nullptr) {
- Q_EMIT recentItemClicked(item->url);
- }
-}
-
-void WelcomeScreen::recentListChanged()
-{
- if (recentsCount() == 0) {
- m_noRecentsLabel->show();
- forgetAllButton->setEnabled(false);
- } else {
- m_noRecentsLabel->hide();
- forgetAllButton->setEnabled(true);
- }
-}
-
-#include "welcomescreen.moc"
diff --git a/shell/welcomescreen.h b/shell/welcomescreen.h
deleted file mode 100644
index 6c404951c5d53f8d1654f8d40ae7c200c97fc249..0000000000000000000000000000000000000000
--- a/shell/welcomescreen.h
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- SPDX-FileCopyrightText: 2021 Jiří Wolker <woljiri@gmail.com>
-
- SPDX-License-Identifier: GPL-2.0-or-later
-*/
-
-#ifndef WELCOMESCREEN_H
-#define WELCOMESCREEN_H
-
-#include "shell/ui_welcomescreen.h"
-
-#include <QFrame>
-#include <QUrl>
-
-class KRecentFilesAction;
-class QListWidgetItem;
-class RecentItemsModel;
-class RecentsListItemDelegate;
-
-class WelcomeScreen : public QWidget, Ui::WelcomeScreen
-{
- Q_OBJECT
-public:
- explicit WelcomeScreen(QWidget *parent = nullptr);
- ~WelcomeScreen() override;
-
- void loadRecents();
-
-Q_SIGNALS:
- void openClicked();
- void closeClicked();
- void recentItemClicked(QUrl const &url);
- void forgetAllRecents();
- void forgetRecentItem(QUrl const &url);
-
-protected:
- void showEvent(QShowEvent *e) override;
-
-private Q_SLOTS:
- void recentsItemActivated(QModelIndex const &index);
- void recentListChanged();
-
-private:
- int recentsCount();
-
- RecentItemsModel *m_recentsModel;
- RecentsListItemDelegate *m_recentsItemDelegate;
-
- QLabel *m_noRecentsLabel;
-};
-
-#endif // WELCOMESCREEN_H
diff --git a/shell/welcomescreen.ui b/shell/welcomescreen.ui
deleted file mode 100644
index 5c087836f0204cc212526f5cf79c81a38da01fec..0000000000000000000000000000000000000000
--- a/shell/welcomescreen.ui
+++ /dev/null
@@ -1,524 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
-SPDX-FileCopyrightText: 2021 Jiří Wolker <woljiri@gmail.com>
-SPDX-License-Identifier: GPL-2.0-or-later
--->
-<ui version="4.0">
- <class>WelcomeScreen</class>
- <widget class="QWidget" name="WelcomeScreen">
- <property name="geometry">
- <rect>
- <x>0</x>
- <y>0</y>
- <width>1423</width>
- <height>850</height>
- </rect>
- </property>
- <property name="acceptDrops">
- <bool>true</bool>
- </property>
- <layout class="QGridLayout" name="gridLayout" rowstretch="3,5,0,3" columnstretch="1,4,1">
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <property name="spacing">
- <number>0</number>
- </property>
- <item row="1" column="0" rowspan="3">
- <spacer name="horizontalSpacer_8">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::MinimumExpanding</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>48</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="0" column="1">
- <spacer name="verticalSpacer_5">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::MinimumExpanding</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>48</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="1" column="1" rowspan="2">
- <widget class="QWidget" name="horizontalWidget" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>256</height>
- </size>
- </property>
- <property name="maximumSize">
- <size>
- <width>700</width>
- <height>16777215</height>
- </size>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout_2">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QFrame" name="verticalFrame">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Maximum" vsizetype="Expanding">
- <horstretch>1</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="maximumSize">
- <size>
- <width>192</width>
- <height>16777215</height>
- </size>
- </property>
- <property name="frameShape">
- <enum>QFrame::NoFrame</enum>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_5">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QLabel" name="label">
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>40</height>
- </size>
- </property>
- <property name="font">
- <font>
- <pointsize>12</pointsize>
- <weight>75</weight>
- <bold>true</bold>
- </font>
- </property>
- <property name="text">
- <string>Welcome to Okular</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- <property name="wordWrap">
- <bool>true</bool>
- </property>
- <property name="margin">
- <number>0</number>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_2">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::MinimumExpanding</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>12</width>
- <height>12</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QLabel" name="appIcon">
- <property name="text">
- <string notr="true"/>
- </property>
- <property name="alignment">
- <set>Qt::AlignCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <spacer name="verticalSpacer_3">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::MinimumExpanding</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>12</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <layout class="QHBoxLayout" name="horizontalLayout">
- <property name="sizeConstraint">
- <enum>QLayout::SetMinimumSize</enum>
- </property>
- <item>
- <spacer name="horizontalSpacer">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Expanding</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>48</width>
- <height>0</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QPushButton" name="openButton">
- <property name="text">
- <string comment="on welcome screen">Open Document...</string>
- </property>
- <property name="icon">
- <iconset theme="document-open" />
- </property>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_2">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Expanding</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>48</width>
- <height>0</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_4">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Maximum</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>48</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QWidget" name="verticalWidget" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Fixed" vsizetype="Preferred">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout" stretch="1">
- <property name="spacing">
- <number>0</number>
- </property>
- <item>
- <widget class="Line" name="line_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Minimum">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <spacer name="horizontalSpacer_3">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::Maximum</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>48</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item>
- <widget class="QWidget" name="recentsArea" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <layout class="QVBoxLayout" name="verticalLayout_3" stretch="0,1">
- <property name="spacing">
- <number>4</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="topMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <property name="bottomMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QWidget" name="horizontalWidget" native="true">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>0</width>
- <height>36</height>
- </size>
- </property>
- <layout class="QHBoxLayout" name="horizontalLayout_3">
- <property name="spacing">
- <number>0</number>
- </property>
- <property name="leftMargin">
- <number>0</number>
- </property>
- <property name="rightMargin">
- <number>0</number>
- </property>
- <item>
- <widget class="QLabel" name="label_2">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Preferred" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="font">
- <font>
- <pointsize>12</pointsize>
- </font>
- </property>
- <property name="text">
- <string comment="on welcome screen">Recent documents</string>
- </property>
- <property name="alignment">
- <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
- </property>
- </widget>
- </item>
- <item>
- <widget class="QToolButton" name="forgetAllButton">
- <property name="text">
- <string comment="on welcome screen (recent document list)">Forget All</string>
- </property>
- <property name="icon">
- <iconset theme="edit-clear-history"/>
- </property>
- <property name="toolButtonStyle">
- <enum>Qt::ToolButtonTextBesideIcon</enum>
- </property>
- <property name="autoRaise">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item>
- <widget class="QListView" name="recentsListView">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Expanding" vsizetype="Expanding">
- <horstretch>0</horstretch>
- <verstretch>1</verstretch>
- </sizepolicy>
- </property>
- <property name="minimumSize">
- <size>
- <width>200</width>
- <height>128</height>
- </size>
- </property>
- <property name="verticalScrollBarPolicy">
- <enum>Qt::ScrollBarAsNeeded</enum>
- </property>
- <property name="horizontalScrollBarPolicy">
- <enum>Qt::ScrollBarAsNeeded</enum>
- </property>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- </layout>
- </widget>
- </item>
- <item row="0" column="2">
- <layout class="QGridLayout" name="gridLayout_2">
- <item row="0" column="0">
- <spacer name="horizontalSpacer_5">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="0" column="1">
- <widget class="QPushButton" name="closeButton">
- <property name="sizePolicy">
- <sizepolicy hsizetype="Minimum" vsizetype="Fixed">
- <horstretch>0</horstretch>
- <verstretch>0</verstretch>
- </sizepolicy>
- </property>
- <property name="toolTip">
- <string>Hide welcome screen</string>
- </property>
- <property name="text">
- <string comment="on welcome screen"/>
- </property>
- <property name="icon">
- <iconset theme="window-close"/>
- </property>
- <property name="flat">
- <bool>true</bool>
- </property>
- </widget>
- </item>
- <item row="1" column="1">
- <spacer name="verticalSpacer">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>40</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </item>
- <item row="1" column="2" rowspan="3">
- <spacer name="horizontalSpacer_6">
- <property name="orientation">
- <enum>Qt::Horizontal</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>40</width>
- <height>20</height>
- </size>
- </property>
- </spacer>
- </item>
- <item row="3" column="1">
- <spacer name="verticalSpacer_6">
- <property name="orientation">
- <enum>Qt::Vertical</enum>
- </property>
- <property name="sizeType">
- <enum>QSizePolicy::MinimumExpanding</enum>
- </property>
- <property name="sizeHint" stdset="0">
- <size>
- <width>20</width>
- <height>48</height>
- </size>
- </property>
- </spacer>
- </item>
- </layout>
- </widget>
- <tabstops>
- <tabstop>openButton</tabstop>
- </tabstops>
- <resources/>
- <connections/>
-</ui>
diff --git a/shell/welcomeview/bookmarksmodel.cpp b/shell/welcomeview/bookmarksmodel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..6c5c513d0583735ec6bb48eca52cfe4cc40648b5
--- /dev/null
+++ b/shell/welcomeview/bookmarksmodel.cpp
@@ -0,0 +1,52 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Eugene Popov <popov895@ukr.net>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include "bookmarksmodel.h"
+
+#include <QFileInfo>
+#include <QIcon>
+#include <QMimeDatabase>
+
+BookmarksModel::BookmarksModel(QObject *parent)
+ : QStandardItemModel(parent)
+{
+}
+
+void BookmarksModel::refresh(const QMultiMap<QUrl, Okular::BookmarksInterface::Bookmark> &bookmarks)
+{
+ clear();
+
+ const QList<QUrl> files = bookmarks.uniqueKeys();
+ for (const QUrl &file : files) {
+ QStandardItem *item = new QStandardItem;
+ item->setData(file);
+ item->setToolTip(file.toString(QUrl::PreferLocalFile));
+
+ if (file.isLocalFile()) {
+ const QFileInfo fileInfo(file.toLocalFile());
+ item->setIcon(QIcon::fromTheme(QMimeDatabase().mimeTypeForFile(fileInfo).iconName()));
+ item->setText(fileInfo.fileName());
+ } else {
+ item->setIcon(QIcon::fromTheme(QStringLiteral("network-server")));
+ item->setText(file.toString());
+ }
+
+ const QList<Okular::BookmarksInterface::Bookmark> bookmarkList = bookmarks.values(file);
+ for (const Okular::BookmarksInterface::Bookmark &bookmark : bookmarkList) {
+ QStandardItem *childItem = new QStandardItem;
+ childItem->setData(bookmark.url);
+ childItem->setText(bookmark.title);
+
+ item->appendRow(childItem);
+ }
+
+ appendRow(item);
+ }
+
+ sort(0);
+
+ Q_EMIT itemChanged(invisibleRootItem());
+}
diff --git a/shell/welcomeview/bookmarksmodel.h b/shell/welcomeview/bookmarksmodel.h
new file mode 100644
index 0000000000000000000000000000000000000000..dba112de217ca24a2fbd9ee8585019e0ca6eb4fa
--- /dev/null
+++ b/shell/welcomeview/bookmarksmodel.h
@@ -0,0 +1,24 @@
+/*
+ * SPDX-FileCopyrightText: 2022 Eugene Popov <popov895@ukr.net>
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#ifndef BOOKMARKSMODEL_H
+#define BOOKMARKSMODEL_H
+
+#include <QStandardItemModel>
+
+#include <interfaces/bookmarksinterface.h>
+
+class BookmarksModel : public QStandardItemModel
+{
+ Q_OBJECT
+
+public:
+ explicit BookmarksModel(QObject *parent = nullptr);
+
+ void refresh(const QMultiMap<QUrl, Okular::BookmarksInterface::Bookmark> &bookmarks);
+};
+
+#endif // BOOKMARKSMODEL_H
diff --git a/shell/welcomeview/recentfilesmodel.cpp b/shell/welcomeview/recentfilesmodel.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..c68208d3ce13dcc7396614688b48c86398d0c2c8
--- /dev/null
+++ b/shell/welcomeview/recentfilesmodel.cpp
@@ -0,0 +1,82 @@
+/*
+ SPDX-FileCopyrightText: 2022 Jiří Wolker <woljiri@gmail.com>
+ SPDX-FileCopyrightText: 2022 Eugene Popov <popov895@ukr.net>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include "recentfilesmodel.h"
+
+#include <QFileInfo>
+#include <QMimeDatabase>
+
+RecentFilesModel::RecentFilesModel(QObject *parent)
+ : QAbstractListModel(parent)
+{
+}
+
+QVariant RecentFilesModel::data(const QModelIndex &index, int role) const
+{
+ if (index.isValid()) {
+ const int row = index.row();
+ if (row >= 0 && row < m_recentFiles.count()) {
+ const RecentFileInfo &recentFile = m_recentFiles.at(row);
+ switch (role) {
+ case Qt::DisplayRole:
+ return recentFile.name;
+ case Qt::DecorationRole:
+ return recentFile.icon;
+ case Qt::ToolTipRole:
+ return recentFile.url.toString(QUrl::PreferLocalFile);
+ default:
+ break;
+ }
+ }
+ }
+
+ return QVariant();
+}
+
+int RecentFilesModel::rowCount(const QModelIndex &parent) const
+{
+ Q_UNUSED(parent);
+
+ return m_recentFiles.count();
+}
+
+void RecentFilesModel::refresh(const QList<QUrl> &urls)
+{
+ QVector<RecentFileInfo> recentFiles;
+ recentFiles.reserve(urls.count());
+
+ QIcon icon;
+ QString name;
+ for (const QUrl &url : urls) {
+ if (url.isLocalFile()) {
+ const QFileInfo fileInfo(url.toLocalFile());
+ icon = QIcon::fromTheme(QMimeDatabase().mimeTypeForFile(fileInfo).iconName());
+ name = fileInfo.fileName();
+ } else {
+ icon = QIcon::fromTheme(QStringLiteral("network-server"));
+ name = url.toString();
+ }
+
+ recentFiles.append({icon, name, url});
+ }
+
+ beginResetModel();
+ m_recentFiles = std::move(recentFiles);
+ endResetModel();
+}
+
+QUrl RecentFilesModel::url(const QModelIndex &index) const
+{
+ if (index.isValid()) {
+ const int row = index.row();
+ if (row >= 0 && row < m_recentFiles.count()) {
+ return m_recentFiles.at(row).url;
+ }
+ }
+
+ return QUrl();
+}
diff --git a/shell/welcomeview/recentfilesmodel.h b/shell/welcomeview/recentfilesmodel.h
new file mode 100644
index 0000000000000000000000000000000000000000..de55f3fc6a894272f9f0aa82a6f1036f1356a6ac
--- /dev/null
+++ b/shell/welcomeview/recentfilesmodel.h
@@ -0,0 +1,38 @@
+/*
+ SPDX-FileCopyrightText: 2022 Jiří Wolker <woljiri@gmail.com>
+ SPDX-FileCopyrightText: 2022 Eugene Popov <popov895@ukr.net>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#ifndef RECENTFILESMODEL_H
+#define RECENTFILESMODEL_H
+
+#include <QAbstractListModel>
+#include <QIcon>
+#include <QUrl>
+
+class RecentFilesModel : public QAbstractListModel
+{
+ Q_OBJECT
+
+public:
+ explicit RecentFilesModel(QObject *parent = nullptr);
+
+ QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
+ int rowCount(const QModelIndex &parent = QModelIndex()) const override;
+
+ void refresh(const QList<QUrl> &urls);
+ QUrl url(const QModelIndex &index) const;
+
+private:
+ struct RecentFileInfo {
+ QIcon icon;
+ QString name;
+ QUrl url;
+ };
+
+ QVector<RecentFileInfo> m_recentFiles;
+};
+
+#endif // RECENTFILESMODEL_H
diff --git a/shell/welcomeview/welcomeview.cpp b/shell/welcomeview/welcomeview.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..94c29f9dc51b165efd5d8b14e731084b519e7697
--- /dev/null
+++ b/shell/welcomeview/welcomeview.cpp
@@ -0,0 +1,285 @@
+/*
+ SPDX-FileCopyrightText: 2022 Jiří Wolker <woljiri@gmail.com>
+ SPDX-FileCopyrightText: 2022 Eugene Popov <popov895@ukr.net>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include "welcomeview.h"
+
+#include "../shell.h"
+#include "bookmarksmodel.h"
+#include "recentfilesmodel.h"
+
+#include <KAboutData>
+#include <KConfigGroup>
+#include <KIO/OpenFileManagerWindowJob>
+#include <KIconLoader>
+#include <KRecentFilesAction>
+#include <KSharedConfig>
+
+#include <QClipboard>
+#include <QDesktopServices>
+#include <QGraphicsOpacityEffect>
+#include <QLabel>
+#include <QMenu>
+#include <QTimer>
+
+#include <interfaces/bookmarksinterface.h>
+
+class Placeholder : public QLabel // clazy:exclude=missing-qobject-macro
+{
+public:
+ explicit Placeholder(QWidget *parent = nullptr)
+ : QLabel(parent)
+ {
+ setAlignment(Qt::AlignCenter);
+ setMargin(20);
+ setWordWrap(true);
+ // Match opacity of QML placeholder label component
+ QGraphicsOpacityEffect *opacityEffect = new QGraphicsOpacityEffect;
+ opacityEffect->setOpacity(0.5);
+ setGraphicsEffect(opacityEffect);
+ }
+};
+
+WelcomeView::WelcomeView(Shell *shell, KParts::ReadWritePart *part, QWidget *parent)
+ : QScrollArea(parent)
+ , m_shell(shell)
+ , m_bookmarks(qobject_cast<Okular::BookmarksInterface *>(part))
+{
+ setupUi(this);
+
+ m_placeholderRecentFiles = new Placeholder;
+ m_placeholderRecentFiles->setText(i18n("No recent files"));
+
+ QVBoxLayout *layoutPlaceholderRecentFiles = new QVBoxLayout;
+ layoutPlaceholderRecentFiles->addWidget(m_placeholderRecentFiles);
+ listViewRecentFiles->setLayout(layoutPlaceholderRecentFiles);
+
+ m_recentFilesModel = new RecentFilesModel(this);
+ connect(m_recentFilesModel, &RecentFilesModel::modelReset, this, [this]() {
+ const bool noRecentFiles = m_recentFilesModel->rowCount() == 0;
+ buttonClearRecentFiles->setDisabled(noRecentFiles);
+ m_placeholderRecentFiles->setVisible(noRecentFiles);
+ });
+
+ KRecentFilesAction *recentFilesAction = m_shell->recentFilesAction();
+ m_recentFilesModel->refresh(recentFilesAction->urls());
+ recentFilesAction->menu()->installEventFilter(this);
+
+ listViewRecentFiles->setModel(m_recentFilesModel);
+ connect(listViewRecentFiles, &QListView::customContextMenuRequested, this, &WelcomeView::onRecentFilesContextMenuRequested);
+ connect(listViewRecentFiles, &QListView::activated, this, [this](const QModelIndex &index) {
+ if (index.isValid()) {
+ const QUrl url = m_recentFilesModel->url(index);
+ Q_ASSERT(url.isValid());
+ m_shell->openUrl(url);
+ }
+ });
+
+ connect(buttonOpenFile, &QPushButton::clicked, m_shell, &Shell::fileOpen);
+ connect(buttonImportPostScript, SIGNAL(clicked()), part, SLOT(slotImportPSFile())); // clazy:exclude=old-style-connect
+ connect(buttonClearRecentFiles, &QPushButton::clicked, recentFilesAction, &KRecentFilesAction::clear);
+
+ m_placeholderBookmarks = new Placeholder;
+ m_placeholderBookmarks->setText(i18n("No bookmarks"));
+
+ QVBoxLayout *layoutPlaceholderBookmarks = new QVBoxLayout;
+ layoutPlaceholderBookmarks->addWidget(m_placeholderBookmarks);
+ treeViewBookmarks->setLayout(layoutPlaceholderBookmarks);
+
+ m_bookmarksModel = new BookmarksModel(this);
+ connect(m_bookmarksModel, &BookmarksModel::itemChanged, this, [this]() {
+ const bool noBookmarks = m_bookmarksModel->rowCount() == 0;
+ m_placeholderBookmarks->setVisible(noBookmarks);
+ });
+
+ connect(part, SIGNAL(bookmarksChanged()), this, SLOT(onBookmarksChanged())); // clazy:exclude=old-style-connect
+ onBookmarksChanged();
+
+ treeViewBookmarks->setModel(m_bookmarksModel);
+ connect(treeViewBookmarks, &QListView::customContextMenuRequested, this, &WelcomeView::onBookmarksContextMenuRequested);
+ connect(treeViewBookmarks, &QTreeView::activated, this, [this](const QModelIndex &index) {
+ if (index.isValid()) {
+ const QStandardItem *item = m_bookmarksModel->itemFromIndex(index);
+ if (item && item->parent()) {
+ m_shell->openBookmark(item->data().toUrl());
+ }
+ }
+ });
+
+ connect(labelHomepage, qOverload<>(&KUrlLabel::leftClickedUrl), this, []() { QDesktopServices::openUrl(QUrl(KAboutData::applicationData().homepage())); });
+ connect(labelHandbook, qOverload<>(&KUrlLabel::leftClickedUrl), m_shell, &Shell::appHelpActivated);
+ connect(buttonClose, &QPushButton::clicked, m_shell, &Shell::hideWelcomeScreen);
+
+ static const char showOnStartupKey[] = "ShowWelcomeScreenOnStartup";
+ KConfigGroup configGroup = KSharedConfig::openConfig()->group(QStringLiteral("General"));
+ checkBoxShowOnStartup->setChecked(configGroup.readEntry(showOnStartupKey, true));
+ connect(checkBoxShowOnStartup, &QCheckBox::toggled, this, [configGroup](bool checked) mutable { configGroup.writeEntry(showOnStartupKey, checked); });
+
+ updateFonts();
+ updateButtons();
+}
+
+bool WelcomeView::event(QEvent *event)
+{
+ switch (event->type()) {
+ case QEvent::FontChange:
+ updateFonts();
+ updateButtons();
+ break;
+ case QEvent::Resize:
+ if (updateLayout() && isVisible()) {
+ return true;
+ }
+ break;
+ default:
+ break;
+ }
+
+ return QScrollArea::event(event);
+}
+
+bool WelcomeView::eventFilter(QObject *watched, QEvent *event)
+{
+ KRecentFilesAction *recentFilesAction = m_shell->recentFilesAction();
+ if (watched == recentFilesAction->menu()) {
+ switch (event->type()) {
+ case QEvent::ActionAdded:
+ case QEvent::ActionRemoved:
+ // since the KRecentFilesAction doesn't notify about adding or
+ // deleting items, we should use this workaround to find out
+ // the KRecentFilesAction has changed
+ QTimer::singleShot(0, this, [this, recentFilesAction]() { m_recentFilesModel->refresh(recentFilesAction->urls()); });
+ break;
+ default:
+ break;
+ }
+ }
+
+ return QScrollArea::eventFilter(watched, event);
+}
+
+void WelcomeView::onBookmarksChanged()
+{
+ m_bookmarksModel->refresh(m_bookmarks->getBookmarks());
+}
+
+void WelcomeView::onRecentFilesContextMenuRequested(QPoint pos)
+{
+ const QModelIndex index = listViewRecentFiles->indexAt(pos);
+ if (!index.isValid()) {
+ return;
+ }
+
+ const QUrl url = m_recentFilesModel->url(index);
+ Q_ASSERT(url.isValid());
+
+ QMenu contextMenu;
+
+ QAction *action = contextMenu.addAction(i18n("Copy &Location"));
+ action->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy-path")));
+ connect(action, &QAction::triggered, this, [url]() { qApp->clipboard()->setText(url.toString(QUrl::PreferLocalFile)); });
+
+ action = contextMenu.addAction(i18n("&Open Containing Folder"));
+ action->setEnabled(url.isLocalFile());
+ action->setIcon(QIcon::fromTheme(QStringLiteral("document-open-folder")));
+ connect(action, &QAction::triggered, this, [url]() { KIO::highlightInFileManager({url}); });
+
+ action = contextMenu.addAction(i18n("&Remove"));
+ action->setIcon(QIcon::fromTheme(QStringLiteral("edit-delete")));
+ connect(action, &QAction::triggered, this, [this, url]() {
+ KRecentFilesAction *recentFilesAction = m_shell->recentFilesAction();
+ recentFilesAction->removeUrl(url);
+ });
+
+ contextMenu.exec(listViewRecentFiles->mapToGlobal(pos));
+}
+
+void WelcomeView::onBookmarksContextMenuRequested(QPoint pos)
+{
+ if (m_bookmarksModel->rowCount() == 0) {
+ return;
+ }
+
+ QMenu contextMenu;
+
+ const QModelIndex index = treeViewBookmarks->indexAt(pos);
+ if (index.isValid()) {
+ const QStandardItem *item = m_bookmarksModel->itemFromIndex(index);
+ if (item && !item->parent()) {
+ const QUrl &url = item->data().toUrl();
+ Q_ASSERT(url.isValid());
+
+ QAction *action = contextMenu.addAction(i18n("Copy &Location"));
+ action->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy-path")));
+ connect(action, &QAction::triggered, this, [url]() { qApp->clipboard()->setText(url.toString(QUrl::PreferLocalFile)); });
+
+ action = contextMenu.addAction(i18n("&Open Containing Folder"));
+ action->setEnabled(url.isLocalFile());
+ action->setIcon(QIcon::fromTheme(QStringLiteral("document-open-folder")));
+ connect(action, &QAction::triggered, this, [url]() { KIO::highlightInFileManager({url}); });
+
+ contextMenu.addSeparator();
+ }
+ }
+
+ QAction *action = contextMenu.addAction(i18n("Expand All"));
+ action->setIcon(QIcon::fromTheme(QStringLiteral("arrow-down-double")));
+ connect(action, &QAction::triggered, treeViewBookmarks, &QTreeView::expandAll);
+
+ action = contextMenu.addAction(i18n("Collapse All"));
+ action->setIcon(QIcon::fromTheme(QStringLiteral("arrow-up-double")));
+ connect(action, &QAction::triggered, treeViewBookmarks, &QTreeView::collapseAll);
+
+ contextMenu.exec(treeViewBookmarks->mapToGlobal(pos));
+}
+
+void WelcomeView::updateButtons()
+{
+ QVector<QPushButton *> buttons {buttonOpenFile, buttonImportPostScript};
+ const int maxWidth = std::accumulate(buttons.cbegin(), buttons.cend(), 0, [](int maxWidth, const QPushButton *button) { return std::max(maxWidth, button->sizeHint().width()); });
+ for (QPushButton *button : qAsConst(buttons)) {
+ button->setFixedWidth(maxWidth);
+ }
+
+ layoutBookmarks->setContentsMargins(maxWidth + layoutRecentFiles->horizontalSpacing(), 0, 0, 0);
+}
+
+void WelcomeView::updateFonts()
+{
+ QFont panelTitleFont = font();
+ panelTitleFont.setPointSize(panelTitleFont.pointSize() + 2);
+ labelRecentFiles->setFont(panelTitleFont);
+ labelBookmarks->setFont(panelTitleFont);
+ labelHelp->setFont(panelTitleFont);
+
+ QFont placeholderFont = font();
+ placeholderFont.setPointSize(qRound(placeholderFont.pointSize() * 1.3));
+ m_placeholderRecentFiles->setFont(placeholderFont);
+ m_placeholderBookmarks->setFont(placeholderFont);
+}
+
+bool WelcomeView::updateLayout()
+{
+ // align labelHelp with labelRecentFiles
+ labelHelp->setMinimumHeight(labelRecentFiles->height());
+
+ // show/hide widgetHelp depending on the view width
+ int implicitWidth = layoutRoot->minimumSize().width();
+ if (widgetHelp->isVisible()) {
+ if (width() <= implicitWidth) {
+ widgetHelp->hide();
+ return true;
+ }
+ } else {
+ implicitWidth += widgetHelp->width() + layoutPanels->spacing();
+ if (width() > implicitWidth) {
+ widgetHelp->show();
+ return true;
+ }
+ }
+
+ return false;
+}
diff --git a/shell/welcomeview/welcomeview.h b/shell/welcomeview/welcomeview.h
new file mode 100644
index 0000000000000000000000000000000000000000..8b0c9fba8d3bb7146f9e735ed74e9a42f508bebb
--- /dev/null
+++ b/shell/welcomeview/welcomeview.h
@@ -0,0 +1,57 @@
+/*
+ SPDX-FileCopyrightText: 2022 Jiří Wolker <woljiri@gmail.com>
+ SPDX-FileCopyrightText: 2022 Eugene Popov <popov895@ukr.net>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#ifndef WELCOMEVIEW_H
+#define WELCOMEVIEW_H
+
+#include "shell/ui_welcomeview.h"
+
+class BookmarksModel;
+class Placeholder;
+class RecentFilesModel;
+class Shell;
+
+namespace KParts
+{
+class ReadWritePart;
+}
+
+namespace Okular
+{
+class BookmarksInterface;
+}
+
+class WelcomeView : public QScrollArea, Ui::WelcomeView
+{
+ Q_OBJECT
+
+public:
+ explicit WelcomeView(Shell *shell, KParts::ReadWritePart *part, QWidget *parent = nullptr);
+
+protected:
+ bool event(QEvent *event) override;
+ bool eventFilter(QObject *watched, QEvent *event) override;
+
+private Q_SLOTS:
+ void onBookmarksChanged();
+ void onRecentFilesContextMenuRequested(QPoint pos);
+ void onBookmarksContextMenuRequested(QPoint pos);
+
+private:
+ void updateButtons();
+ void updateFonts();
+ bool updateLayout();
+
+ Shell *m_shell = nullptr;
+ Okular::BookmarksInterface *m_bookmarks = nullptr;
+ RecentFilesModel *m_recentFilesModel = nullptr;
+ BookmarksModel *m_bookmarksModel = nullptr;
+ Placeholder *m_placeholderRecentFiles = nullptr;
+ Placeholder *m_placeholderBookmarks = nullptr;
+};
+
+#endif // WELCOMEVIEW_H
diff --git a/shell/welcomeview/welcomeview.ui b/shell/welcomeview/welcomeview.ui
new file mode 100644
index 0000000000000000000000000000000000000000..4c7d1e7af9b6465a9277407f07fef819b2c1ea61
--- /dev/null
+++ b/shell/welcomeview/welcomeview.ui
@@ -0,0 +1,415 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<ui version="4.0">
+ <class>WelcomeView</class>
+ <widget class="QScrollArea" name="WelcomeView">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1011</width>
+ <height>803</height>
+ </rect>
+ </property>
+ <property name="acceptDrops">
+ <bool>true</bool>
+ </property>
+ <property name="windowTitle">
+ <string>Welcome</string>
+ </property>
+ <property name="frameShape">
+ <enum>QFrame::NoFrame</enum>
+ </property>
+ <property name="widgetResizable">
+ <bool>true</bool>
+ </property>
+ <widget class="QWidget" name="scrollAreaWidgetContents">
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>1011</width>
+ <height>803</height>
+ </rect>
+ </property>
+ <layout class="QGridLayout" name="layoutRoot" rowstretch="1,6,1" columnstretch="1,3,1">
+ <item row="0" column="1">
+ <spacer name="spacer6">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="0">
+ <spacer name="spacer4">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="1" column="1">
+ <widget class="QFrame" name="frameContent">
+ <layout class="QVBoxLayout" name="layoutContent" stretch="1,0">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="spacing">
+ <number>20</number>
+ </property>
+ <item>
+ <layout class="QGridLayout" name="layoutPanels" columnstretch="1,0">
+ <property name="spacing">
+ <number>20</number>
+ </property>
+ <item row="0" column="0">
+ <widget class="QWidget" name="widgetRecentFiles" native="true">
+ <layout class="QGridLayout" name="layoutRecentFiles" rowstretch="0,0,0,1" columnstretch="0,1,0">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <property name="horizontalSpacing">
+ <number>20</number>
+ </property>
+ <item row="1" column="1" rowspan="3" colspan="2">
+ <widget class="QListView" name="listViewRecentFiles">
+ <property name="minimumSize">
+ <size>
+ <width>400</width>
+ <height>200</height>
+ </size>
+ </property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="textElideMode">
+ <enum>Qt::ElideMiddle</enum>
+ </property>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QPushButton" name="buttonOpenFile">
+ <property name="text">
+ <string>Open File...</string>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="2">
+ <widget class="QPushButton" name="buttonClearRecentFiles">
+ <property name="toolTip">
+ <string>Clear Recent Files</string>
+ </property>
+ <property name="icon">
+ <iconset theme="edit-clear-all">
+ <normaloff>.</normaloff>.</iconset>
+ </property>
+ </widget>
+ </item>
+ <item row="0" column="1">
+ <widget class="QLabel" name="labelRecentFiles">
+ <property name="text">
+ <string>Recent Files</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+ </property>
+ </widget>
+ </item>
+ <item row="3" column="0">
+ <spacer name="spacer3">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="0">
+ <widget class="QPushButton" name="buttonImportPostScript">
+ <property name="text">
+ <string>Import PostScript...</string>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="0" column="1" rowspan="2">
+ <widget class="QWidget" name="widgetHelp" native="true">
+ <layout class="QVBoxLayout" name="layoutHelp" stretch="0,0,0,1">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="labelHelp">
+ <property name="text">
+ <string>Help</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+ </property>
+ </widget>
+ </item>
+ <item alignment="Qt::AlignLeft">
+ <widget class="KUrlLabel" name="labelHomepage">
+ <property name="text">
+ <string>Visit homepage</string>
+ </property>
+ <property name="url">
+ <string/>
+ </property>
+ <property name="glowEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item alignment="Qt::AlignLeft">
+ <widget class="KUrlLabel" name="labelHandbook">
+ <property name="text">
+ <string>Read handbook</string>
+ </property>
+ <property name="url">
+ <string/>
+ </property>
+ <property name="glowEnabled">
+ <bool>false</bool>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="spacer11">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="0">
+ <widget class="QWidget" name="widgetBookmarks" native="true">
+ <layout class="QVBoxLayout" name="layoutBookmarks">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <widget class="QLabel" name="labelBookmarks">
+ <property name="text">
+ <string>Bookmarks</string>
+ </property>
+ <property name="alignment">
+ <set>Qt::AlignBottom|Qt::AlignLeading|Qt::AlignLeft</set>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <widget class="QTreeView" name="treeViewBookmarks">
+ <property name="minimumSize">
+ <size>
+ <width>0</width>
+ <height>200</height>
+ </size>
+ </property>
+ <property name="contextMenuPolicy">
+ <enum>Qt::CustomContextMenu</enum>
+ </property>
+ <property name="editTriggers">
+ <set>QAbstractItemView::NoEditTriggers</set>
+ </property>
+ <property name="alternatingRowColors">
+ <bool>true</bool>
+ </property>
+ <property name="horizontalScrollBarPolicy">
+ <enum>Qt::ScrollBarAlwaysOff</enum>
+ </property>
+ <property name="textElideMode">
+ <enum>Qt::ElideMiddle</enum>
+ </property>
+ <attribute name="headerVisible">
+ <bool>false</bool>
+ </attribute>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </item>
+ <item>
+ <widget class="QWidget" name="widgetFooter" native="true">
+ <layout class="QHBoxLayout" name="layoutFooter">
+ <property name="leftMargin">
+ <number>0</number>
+ </property>
+ <property name="topMargin">
+ <number>0</number>
+ </property>
+ <property name="rightMargin">
+ <number>0</number>
+ </property>
+ <property name="bottomMargin">
+ <number>0</number>
+ </property>
+ <item>
+ <spacer name="spacer9">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item>
+ <widget class="QCheckBox" name="checkBoxShowOnStartup">
+ <property name="text">
+ <string>Show on startup</string>
+ </property>
+ </widget>
+ </item>
+ <item>
+ <spacer name="spacer10">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </item>
+ <item row="1" column="2">
+ <spacer name="spacer5">
+ <property name="orientation">
+ <enum>Qt::Horizontal</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="2" column="1">
+ <spacer name="spacer7">
+ <property name="orientation">
+ <enum>Qt::Vertical</enum>
+ </property>
+ <property name="sizeHint" stdset="0">
+ <size>
+ <width>0</width>
+ <height>0</height>
+ </size>
+ </property>
+ </spacer>
+ </item>
+ <item row="0" column="2" alignment="Qt::AlignRight|Qt::AlignTop">
+ <widget class="QPushButton" name="buttonClose">
+ <property name="toolTip">
+ <string>Close Welcome Page</string>
+ </property>
+ <property name="icon">
+ <iconset theme="window-close"/>
+ </property>
+ <property name="flat">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </item>
+ </layout>
+ </widget>
+ </widget>
+ <customwidgets>
+ <customwidget>
+ <class>KUrlLabel</class>
+ <extends>QLabel</extends>
+ <header>kurllabel.h</header>
+ </customwidget>
+ </customwidgets>
+ <tabstops>
+ <tabstop>buttonOpenFile</tabstop>
+ <tabstop>buttonImportPostScript</tabstop>
+ <tabstop>listViewRecentFiles</tabstop>
+ <tabstop>buttonClearRecentFiles</tabstop>
+ <tabstop>treeViewBookmarks</tabstop>
+ </tabstops>
+ <resources/>
+ <connections/>
+</ui>