┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/CMakeLists.txt12
-rw-r--r--src/dolphinbookmarkhandler.cpp135
-rw-r--r--src/dolphinbookmarkhandler.h61
-rw-r--r--src/dolphinmainwindow.cpp40
-rw-r--r--src/dolphinmainwindow.h28
-rw-r--r--src/dolphinpart.cpp4
-rw-r--r--src/dolphintabwidget.cpp4
-rw-r--r--src/dolphinui.rc5
-rw-r--r--src/filterbar/filterbar.cpp6
-rw-r--r--src/kitemviews/kfileitemmodel.cpp80
-rw-r--r--src/kitemviews/kfileitemmodel.h2
-rw-r--r--src/kitemviews/kitemlistcontroller.cpp16
-rw-r--r--src/kitemviews/kstandarditem.cpp33
-rw-r--r--src/kitemviews/kstandarditem.h14
-rw-r--r--src/kitemviews/kstandarditemlistwidget.cpp2
-rw-r--r--src/kitemviews/kstandarditemlistwidget.h2
-rw-r--r--src/kitemviews/kstandarditemmodel.cpp2
-rw-r--r--src/kitemviews/kstandarditemmodel.h2
-rw-r--r--src/kitemviews/private/kbaloorolesprovider.cpp2
-rw-r--r--src/kitemviews/private/kitemlistroleeditor.cpp17
-rwxr-xr-xsrc/org.kde.dolphin.desktop1
-rw-r--r--src/panels/information/filemetadataconfigurationdialog.cpp102
-rw-r--r--src/panels/information/filemetadataconfigurationdialog.h76
-rw-r--r--src/panels/information/informationpanel.cpp24
-rw-r--r--src/panels/information/informationpanel.h1
-rw-r--r--src/panels/information/informationpanelcontent.cpp68
-rw-r--r--src/panels/information/informationpanelcontent.h17
-rw-r--r--src/panels/information/pixmapviewer.cpp6
-rw-r--r--src/panels/places/placespanel.cpp4
-rw-r--r--src/search/dolphinsearchbox.cpp38
-rw-r--r--src/search/dolphinsearchbox.h1
-rw-r--r--src/settings/dolphinsettingsdialog.cpp35
-rw-r--r--src/settings/dolphinsettingsdialog.h4
-rw-r--r--src/settings/general/previewssettingspage.cpp2
-rw-r--r--src/settings/kcm/kcmdolphingeneral.cpp6
-rw-r--r--src/settings/kcm/kcmdolphinnavigation.cpp2
-rw-r--r--src/settings/kcm/kcmdolphinservices.cpp2
-rwxr-xr-xsrc/settings/services/servicemenudeinstallation95
-rwxr-xr-xsrc/settings/services/servicemenuinstallation204
-rw-r--r--src/settings/services/test/service_menu_deinstallation_test.rb121
-rw-r--r--src/settings/services/test/service_menu_installation_test.rb119
-rw-r--r--src/settings/services/test/test_helper.rb100
-rwxr-xr-xsrc/settings/services/test/test_run.rb24
-rw-r--r--src/settings/trash/trashsettingspage.cpp2
-rw-r--r--src/settings/viewmodes/dolphinfontrequester.cpp2
-rw-r--r--src/settings/viewmodes/viewsettingstab.cpp6
-rw-r--r--src/settings/viewpropertiesdialog.cpp6
-rw-r--r--src/settings/viewpropsprogressinfo.cpp2
-rw-r--r--src/tests/CMakeLists.txt14
-rw-r--r--src/tests/kfileitemmodeltest.cpp24
-rw-r--r--src/tests/placesitemmodeltest.cpp16
-rw-r--r--src/trash/dolphintrash.cpp2
-rw-r--r--src/views/dolphinviewactionhandler.cpp2
-rw-r--r--src/views/tooltips/tooltipmanager.cpp2
54 files changed, 1078 insertions, 519 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e0dd57679..f1b7534ae 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -190,6 +190,7 @@ install(FILES dolphinpart.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR})
##########################################
set(dolphinstatic_SRCS
+ dolphinbookmarkhandler.cpp
dolphindockwidget.cpp
dolphinmainwindow.cpp
dolphinviewcontainer.cpp
@@ -246,7 +247,6 @@ set(dolphinstatic_SRCS
if(HAVE_BALOO)
set(dolphinstatic_SRCS
${dolphinstatic_SRCS}
- panels/information/filemetadataconfigurationdialog.cpp
panels/information/informationpanel.cpp
panels/information/informationpanelcontent.cpp
panels/information/pixmapviewer.cpp
@@ -384,6 +384,13 @@ install(TARGETS kcm_dolphingeneral DESTINATION ${KDE_INSTALL_PLUGINDIR} )
########### install files ###############
install( PROGRAMS org.kde.dolphin.desktop DESTINATION ${KDE_INSTALL_APPDIR} )
+
+install( DIRECTORY DESTINATION "${KDE_INSTALL_FULL_DATAROOTDIR}/kglobalaccel" )
+
+install(
+ CODE "execute_process(COMMAND \"${CMAKE_COMMAND}\" -E create_symlink \"${KDE_INSTALL_FULL_APPDIR}/org.kde.dolphin.desktop\" \"\$ENV{DESTDIR}${KDE_INSTALL_FULL_DATAROOTDIR}/kglobalaccel/org.kde.dolphin.desktop\")"
+)
+
install( FILES settings/dolphin_directoryviewpropertysettings.kcfg
settings/dolphin_generalsettings.kcfg
settings/dolphin_compactmodesettings.kcfg
@@ -392,8 +399,7 @@ install( FILES settings/dolphin_directoryviewpropertysettings.kcfg
settings/dolphin_versioncontrolsettings.kcfg
DESTINATION ${KDE_INSTALL_KCFGDIR} )
install( FILES org.kde.dolphin.appdata.xml DESTINATION ${KDE_INSTALL_METAINFODIR} )
-install( FILES settings/kcm/kcmdolphinviewmodes.desktop DESTINATION
-${KDE_INSTALL_KSERVICES5DIR} )
+install( FILES settings/kcm/kcmdolphinviewmodes.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} )
install( FILES settings/kcm/kcmdolphinnavigation.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} )
install( FILES settings/kcm/kcmdolphinservices.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} )
install( FILES settings/kcm/kcmdolphingeneral.desktop DESTINATION ${KDE_INSTALL_KSERVICES5DIR} )
diff --git a/src/dolphinbookmarkhandler.cpp b/src/dolphinbookmarkhandler.cpp
new file mode 100644
index 000000000..bb8f641ec
--- /dev/null
+++ b/src/dolphinbookmarkhandler.cpp
@@ -0,0 +1,135 @@
+/***************************************************************************
+ * Copyright (C) 2019 by David Hallas <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#include "dolphinbookmarkhandler.h"
+#include "dolphinmainwindow.h"
+#include "dolphinviewcontainer.h"
+#include "global.h"
+#include <KBookmarkMenu>
+#include <KIO/Global>
+#include <QDebug>
+#include <QDir>
+#include <QStandardPaths>
+
+DolphinBookmarkHandler::DolphinBookmarkHandler(DolphinMainWindow *mainWindow,
+ KActionCollection* collection,
+ QMenu* menu,
+ QObject* parent) :
+ QObject(parent),
+ m_mainWindow(mainWindow)
+{
+ QString bookmarksFile = QStandardPaths::locate(QStandardPaths::GenericDataLocation,
+ QStringLiteral("kfile/bookmarks.xml"));
+ if (bookmarksFile.isEmpty()) {
+ QString genericDataLocation = QStandardPaths::writableLocation(QStandardPaths::GenericDataLocation);
+ if (genericDataLocation.isEmpty()) {
+ qWarning() << "GenericDataLocation is empty! Bookmarks will not be saved correctly.";
+ }
+ bookmarksFile = QStringLiteral("%1/dolphin").arg(genericDataLocation);
+ QDir().mkpath(bookmarksFile);
+ bookmarksFile += QLatin1String("/bookmarks.xml");
+ }
+ m_bookmarkManager = KBookmarkManager::managerForFile(bookmarksFile, QStringLiteral("dolphin"));
+ m_bookmarkManager->setUpdate(true);
+ m_bookmarkMenu.reset(new KBookmarkMenu(m_bookmarkManager, this, menu, collection));
+}
+
+DolphinBookmarkHandler::~DolphinBookmarkHandler()
+{
+}
+
+void DolphinBookmarkHandler::fillControlMenu(QMenu* menu, KActionCollection* collection)
+{
+ m_bookmarkControlMenu.reset(new KBookmarkMenu(m_bookmarkManager, this, menu, collection));
+}
+
+QString DolphinBookmarkHandler::currentTitle() const
+{
+ return title(m_mainWindow->activeViewContainer());
+}
+
+QUrl DolphinBookmarkHandler::currentUrl() const
+{
+ return url(m_mainWindow->activeViewContainer());
+}
+
+QString DolphinBookmarkHandler::currentIcon() const
+{
+ return icon(m_mainWindow->activeViewContainer());
+}
+
+bool DolphinBookmarkHandler::supportsTabs() const
+{
+ return true;
+}
+
+QList<KBookmarkOwner::FutureBookmark> DolphinBookmarkHandler::currentBookmarkList() const
+{
+ const auto viewContainers = m_mainWindow->viewContainers();
+ QList<FutureBookmark> bookmarks;
+ bookmarks.reserve(viewContainers.size());
+ for (const auto viewContainer : viewContainers) {
+ bookmarks << FutureBookmark(title(viewContainer), url(viewContainer), icon(viewContainer));
+ }
+ return bookmarks;
+}
+
+bool DolphinBookmarkHandler::enableOption(KBookmarkOwner::BookmarkOption option) const
+{
+ switch (option) {
+ case BookmarkOption::ShowAddBookmark: return true;
+ case BookmarkOption::ShowEditBookmark: return true;
+ }
+ return false;
+}
+
+void DolphinBookmarkHandler::openBookmark(const KBookmark& bookmark, Qt::MouseButtons, Qt::KeyboardModifiers)
+{
+ m_mainWindow->changeUrl(bookmark.url());
+}
+
+void DolphinBookmarkHandler::openFolderinTabs(const KBookmarkGroup& bookmarkGroup)
+{
+ m_mainWindow->openDirectories(bookmarkGroup.groupUrlList(), false);
+}
+
+void DolphinBookmarkHandler::openInNewTab(const KBookmark& bookmark)
+{
+ m_mainWindow->openNewTabAfterCurrentTab(bookmark.url());
+}
+
+void DolphinBookmarkHandler::openInNewWindow(const KBookmark& bookmark)
+{
+ Dolphin::openNewWindow({bookmark.url()}, m_mainWindow);
+}
+
+QString DolphinBookmarkHandler::title(DolphinViewContainer* viewContainer)
+{
+ return viewContainer->caption();
+}
+
+QUrl DolphinBookmarkHandler::url(DolphinViewContainer* viewContainer)
+{
+ return viewContainer->url();
+}
+
+QString DolphinBookmarkHandler::icon(DolphinViewContainer* viewContainer)
+{
+ return KIO::iconNameForUrl(viewContainer->url());
+}
diff --git a/src/dolphinbookmarkhandler.h b/src/dolphinbookmarkhandler.h
new file mode 100644
index 000000000..6fd511d80
--- /dev/null
+++ b/src/dolphinbookmarkhandler.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * Copyright (C) 2019 by David Hallas <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
+ ***************************************************************************/
+
+#ifndef DOLPHINBOOKMARKHANDLER_H
+#define DOLPHINBOOKMARKHANDLER_H
+
+#include <KBookmarkManager>
+#include <QObject>
+
+class DolphinMainWindow;
+class DolphinViewContainer;
+class KActionCollection;
+class KBookmarkManager;
+class KBookmarkMenu;
+class QMenu;
+
+class DolphinBookmarkHandler : public QObject, public KBookmarkOwner
+{
+ Q_OBJECT
+public:
+ DolphinBookmarkHandler(DolphinMainWindow *mainWindow, KActionCollection *collection, QMenu *menu, QObject *parent);
+ ~DolphinBookmarkHandler() override;
+ void fillControlMenu(QMenu *menu, KActionCollection *collection);
+private:
+ QString currentTitle() const override;
+ QUrl currentUrl() const override;
+ QString currentIcon() const override;
+ bool supportsTabs() const override;
+ QList<FutureBookmark> currentBookmarkList() const override;
+ bool enableOption(BookmarkOption option) const override;
+ void openBookmark(const KBookmark &bookmark, Qt::MouseButtons, Qt::KeyboardModifiers) override;
+ void openFolderinTabs(const KBookmarkGroup &bookmarkGroup) override;
+ void openInNewTab(const KBookmark &bookmark) override;
+ void openInNewWindow(const KBookmark &bookmark) override;
+ static QString title(DolphinViewContainer* viewContainer);
+ static QUrl url(DolphinViewContainer* viewContainer);
+ static QString icon(DolphinViewContainer* viewContainer);
+private:
+ DolphinMainWindow* m_mainWindow;
+ KBookmarkManager *m_bookmarkManager;
+ QScopedPointer<KBookmarkMenu> m_bookmarkMenu;
+ QScopedPointer<KBookmarkMenu> m_bookmarkControlMenu;
+};
+
+#endif // DOLPHINBOOKMARKHANDLER_H
diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp
index 7224c8ea9..b57ed4fc4 100644
--- a/src/dolphinmainwindow.cpp
+++ b/src/dolphinmainwindow.cpp
@@ -23,6 +23,7 @@
#include "config-terminal.h"
#include "global.h"
+#include "dolphinbookmarkhandler.h"
#include "dolphindockwidget.h"
#include "dolphincontextmenu.h"
#include "dolphinnewfilemenu.h"
@@ -94,6 +95,7 @@ DolphinMainWindow::DolphinMainWindow() :
m_actionHandler(nullptr),
m_remoteEncoding(nullptr),
m_settingsDialog(),
+ m_bookmarkHandler(nullptr),
m_controlButton(nullptr),
m_updateToolBarTimer(nullptr),
m_lastHandleUrlStatJob(nullptr),
@@ -111,7 +113,7 @@ DolphinMainWindow::DolphinMainWindow() :
KIO::FileUndoManager* undoManager = KIO::FileUndoManager::self();
undoManager->setUiInterface(new UndoUiInterface());
- connect(undoManager, static_cast<void(KIO::FileUndoManager::*)(bool)>(&KIO::FileUndoManager::undoAvailable),
+ connect(undoManager, QOverload<bool>::of(&KIO::FileUndoManager::undoAvailable),
this, &DolphinMainWindow::slotUndoAvailable);
connect(undoManager, &KIO::FileUndoManager::undoTextChanged,
this, &DolphinMainWindow::slotUndoTextChanged);
@@ -183,6 +185,16 @@ DolphinMainWindow::~DolphinMainWindow()
{
}
+QVector<DolphinViewContainer*> DolphinMainWindow::viewContainers() const
+{
+ QVector<DolphinViewContainer*> viewContainers;
+ viewContainers.reserve(m_tabWidget->count());
+ for (int i = 0; i < m_tabWidget->count(); ++i) {
+ viewContainers << m_tabWidget->tabPageAt(i)->activeViewContainer();
+ }
+ return viewContainers;
+}
+
void DolphinMainWindow::openDirectories(const QList<QUrl>& dirs, bool splitView)
{
m_tabWidget->openDirectories(dirs, splitView);
@@ -928,9 +940,13 @@ void DolphinMainWindow::updateControlMenu()
menu->addSeparator();
+ // Overwrite Find action to Search action
+ QAction *searchAction = ac->action(KStandardAction::name(KStandardAction::Find));
+ searchAction->setText(i18n("Search..."));
+
// Add "Edit" actions
bool added = addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Undo)), menu) |
- addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Find)), menu) |
+ addActionToMenu(searchAction, menu) |
addActionToMenu(ac->action(KStandardAction::name(KStandardAction::SelectAll)), menu) |
addActionToMenu(ac->action(QStringLiteral("invert_selection")), menu);
@@ -978,6 +994,9 @@ void DolphinMainWindow::updateControlMenu()
goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Up)));
goMenu->addAction(ac->action(KStandardAction::name(KStandardAction::Home)));
goMenu->addAction(ac->action(QStringLiteral("closed_tabs")));
+ KActionMenu *bookmarkMenu = new KActionMenu(i18nc("@title:menu", "&Bookmarks"), goMenu);
+ m_bookmarkHandler->fillControlMenu(bookmarkMenu->menu(), ac);
+ goMenu->addAction(bookmarkMenu);
menu->addMenu(goMenu);
// Add "Tool" menu
@@ -1118,10 +1137,9 @@ void DolphinMainWindow::setupActions()
newTab->setIcon(QIcon::fromTheme(QStringLiteral("tab-new")));
newTab->setText(i18nc("@action:inmenu File", "New Tab"));
actionCollection()->setDefaultShortcuts(newTab, {Qt::CTRL + Qt::Key_T, Qt::CTRL + Qt::SHIFT + Qt::Key_N});
- connect(newTab, &QAction::triggered, this, static_cast<void(DolphinMainWindow::*)()>(&DolphinMainWindow::openNewActivatedTab));
+ connect(newTab, &QAction::triggered, this, &DolphinMainWindow::openNewActivatedTab);
- QAction* closeTab = KStandardAction::close(
- m_tabWidget, static_cast<void(DolphinTabWidget::*)()>(&DolphinTabWidget::closeTab), actionCollection());
+ QAction* closeTab = KStandardAction::close(m_tabWidget, QOverload<>::of(&DolphinTabWidget::closeTab), actionCollection());
closeTab->setText(i18nc("@action:inmenu File", "Close Tab"));
KStandardAction::quit(this, &DolphinMainWindow::quit, actionCollection());
@@ -1140,7 +1158,8 @@ void DolphinMainWindow::setupActions()
// due to the long text, the text "Paste" is used:
paste->setIconText(i18nc("@action:inmenu Edit", "Paste"));
- KStandardAction::find(this, &DolphinMainWindow::find, actionCollection());
+ QAction *searchAction = KStandardAction::find(this, &DolphinMainWindow::find, actionCollection());
+ searchAction->setText(i18n("Search..."));
KStandardAction::selectAll(this, &DolphinMainWindow::selectAll, actionCollection());
@@ -1236,6 +1255,11 @@ void DolphinMainWindow::setupActions()
}
#endif
+ // setup 'Bookmarks' menu
+ KActionMenu *bookmarkMenu = new KActionMenu(i18nc("@title:menu", "&Bookmarks"), this);
+ m_bookmarkHandler = new DolphinBookmarkHandler(this, actionCollection(), bookmarkMenu->menu(), this);
+ actionCollection()->addAction(QStringLiteral("bookmarks"), bookmarkMenu);
+
// setup 'Settings' menu
KToggleAction* showMenuBar = KStandardAction::showMenubar(nullptr, nullptr, actionCollection());
connect(showMenuBar, &KToggleAction::triggered, // Fixes #286822
@@ -1596,9 +1620,9 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
connect(view, &DolphinView::directoryLoadingCompleted,
this, &DolphinMainWindow::slotDirectoryLoadingCompleted);
connect(view, &DolphinView::goBackRequested,
- this, static_cast<void(DolphinMainWindow::*)()>(&DolphinMainWindow::goBack));
+ this, &DolphinMainWindow::goBack);
connect(view, &DolphinView::goForwardRequested,
- this, static_cast<void(DolphinMainWindow::*)()>(&DolphinMainWindow::goForward));
+ this, &DolphinMainWindow::goForward);
connect(view, &DolphinView::urlActivated,
this, &DolphinMainWindow::handleUrl);
diff --git a/src/dolphinmainwindow.h b/src/dolphinmainwindow.h
index 1734d4ad4..1e2460768 100644
--- a/src/dolphinmainwindow.h
+++ b/src/dolphinmainwindow.h
@@ -32,9 +32,11 @@
#include <QList>
#include <QPointer>
#include <QUrl>
+#include <QVector>
typedef KIO::FileUndoManager::CommandType CommandType;
+class DolphinBookmarkHandler;
class DolphinViewActionHandler;
class DolphinSettingsDialog;
class DolphinViewContainer;
@@ -72,6 +74,11 @@ public:
DolphinViewContainer* activeViewContainer() const;
/**
+ * Returns view container for all tabs
+ */
+ QVector<DolphinViewContainer*> viewContainers() const;
+
+ /**
* Opens each directory in \p dirs in a separate tab. If \a splitView is set,
* 2 directories are collected within one tab.
* \pre \a dirs must contain at least one url.
@@ -118,6 +125,16 @@ public slots:
/** Stores all settings and quits Dolphin. */
void quit();
+ /**
+ * Opens a new tab and places it after the current tab
+ */
+ void openNewTabAfterCurrentTab(const QUrl& url);
+
+ /**
+ * Opens a new tab and places it as the last tab
+ */
+ void openNewTabAfterLastTab(const QUrl& url);
+
signals:
/**
* Is sent if the selection of the currently active view has
@@ -331,16 +348,6 @@ private slots:
void openNewTab(const QUrl& url, DolphinTabWidget::TabPlacement tabPlacement);
/**
- * Opens a new tab and places it after the current tab
- */
- void openNewTabAfterCurrentTab(const QUrl& url);
-
- /**
- * Opens a new tab and places it as the last tab
- */
- void openNewTabAfterLastTab(const QUrl& url);
-
- /**
* Opens the selected folder in a new tab.
*/
void openInNewTab();
@@ -522,6 +529,7 @@ private:
DolphinViewActionHandler* m_actionHandler;
DolphinRemoteEncoding* m_remoteEncoding;
QPointer<DolphinSettingsDialog> m_settingsDialog;
+ DolphinBookmarkHandler* m_bookmarkHandler;
// Members for the toolbar menu that is shown when the menubar is hidden:
QToolButton* m_controlButton;
diff --git a/src/dolphinpart.cpp b/src/dolphinpart.cpp
index f5d4f95b6..a4d7fdf78 100644
--- a/src/dolphinpart.cpp
+++ b/src/dolphinpart.cpp
@@ -76,7 +76,7 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent, const QVariantL
connect(&DolphinNewFileMenuObserver::instance(), &DolphinNewFileMenuObserver::errorMessage,
this, &DolphinPart::slotErrorMessage);
- connect(m_view, &DolphinView::directoryLoadingCompleted, this, static_cast<void(DolphinPart::*)()>(&DolphinPart::completed));
+ connect(m_view, &DolphinView::directoryLoadingCompleted, this, QOverload<>::of(&KParts::ReadOnlyPart::completed));
connect(m_view, &DolphinView::directoryLoadingCompleted, this, &DolphinPart::updatePasteAction);
connect(m_view, &DolphinView::directoryLoadingProgress, this, &DolphinPart::updateProgress);
connect(m_view, &DolphinView::errorMessage, this, &DolphinPart::slotErrorMessage);
@@ -98,7 +98,7 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent, const QVariantL
connect(m_view, &DolphinView::requestContextMenu,
this, &DolphinPart::slotOpenContextMenu);
connect(m_view, &DolphinView::selectionChanged,
- m_extension, static_cast<void(DolphinPartBrowserExtension::*)(const KFileItemList&)>(&DolphinPartBrowserExtension::selectionInfo));
+ m_extension, QOverload<const KFileItemList&>::of(&KParts::BrowserExtension::selectionInfo));
connect(m_view, &DolphinView::selectionChanged,
this, &DolphinPart::slotSelectionChanged);
connect(m_view, &DolphinView::requestItemInfo,
diff --git a/src/dolphintabwidget.cpp b/src/dolphintabwidget.cpp
index c677054d8..e54ab5ada 100644
--- a/src/dolphintabwidget.cpp
+++ b/src/dolphintabwidget.cpp
@@ -38,13 +38,13 @@ DolphinTabWidget::DolphinTabWidget(QWidget* parent) :
m_lastViewedTab(0)
{
connect(this, &DolphinTabWidget::tabCloseRequested,
- this, static_cast<void (DolphinTabWidget::*)(int)>(&DolphinTabWidget::closeTab));
+ this, QOverload<int>::of(&DolphinTabWidget::closeTab));
connect(this, &DolphinTabWidget::currentChanged,
this, &DolphinTabWidget::currentTabChanged);
DolphinTabBar* tabBar = new DolphinTabBar(this);
connect(tabBar, &DolphinTabBar::openNewActivatedTab,
- this, static_cast<void (DolphinTabWidget::*)(int)>(&DolphinTabWidget::openNewActivatedTab));
+ this, QOverload<int>::of(&DolphinTabWidget::openNewActivatedTab));
connect(tabBar, &DolphinTabBar::tabDropEvent,
this, &DolphinTabWidget::tabDropEvent);
connect(tabBar, &DolphinTabBar::tabDetachRequested,
diff --git a/src/dolphinui.rc b/src/dolphinui.rc
index 282ea63e5..b90321d05 100644
--- a/src/dolphinui.rc
+++ b/src/dolphinui.rc
@@ -1,12 +1,12 @@
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<kpartgui name="dolphin" version="21">
+<kpartgui name="dolphin" version="22">
<MenuBar>
<Menu name="file">
<Action name="new_menu" />
<Action name="file_new" />
<Action name="new_tab" />
<Action name="file_close" />
- <Action name="undo_close_tab" />
+ <Action name="undo_close_tab" />
<Separator/>
<Action name="renamefile" />
<Action name="movetotrash" />
@@ -43,6 +43,7 @@
<Action name="view_properties" />
</Menu>
<Menu name="go">
+ <Action name="bookmarks" />
<Action name="closed_tabs" />
</Menu>
<Menu name="tools">
diff --git a/src/filterbar/filterbar.cpp b/src/filterbar/filterbar.cpp
index b4fef22a8..68da73a71 100644
--- a/src/filterbar/filterbar.cpp
+++ b/src/filterbar/filterbar.cpp
@@ -47,13 +47,12 @@ FilterBar::FilterBar(QWidget* parent) :
m_lockButton->setToolTip(i18nc("@info:tooltip", "Keep Filter When Changing Folders"));
connect(m_lockButton, &QToolButton::toggled, this, &FilterBar::slotToggleLockButton);
- // Create label
- QLabel* filterLabel = new QLabel(i18nc("@label:textbox", "Filter:"), this);
// Create filter editor
m_filterInput = new QLineEdit(this);
m_filterInput->setLayoutDirection(Qt::LeftToRight);
m_filterInput->setClearButtonEnabled(true);
+ m_filterInput->setPlaceholderText(i18n("Filter..."));
connect(m_filterInput, &QLineEdit::textChanged,
this, &FilterBar::filterChanged);
setFocusProxy(m_filterInput);
@@ -62,11 +61,8 @@ FilterBar::FilterBar(QWidget* parent) :
QHBoxLayout* hLayout = new QHBoxLayout(this);
hLayout->setContentsMargins(0, 0, 0, 0);
hLayout->addWidget(closeButton);
- hLayout->addWidget(filterLabel);
hLayout->addWidget(m_filterInput);
hLayout->addWidget(m_lockButton);
-
- filterLabel->setBuddy(m_filterInput);
}
FilterBar::~FilterBar()
diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp
index fc14c79c1..8145a00f1 100644
--- a/src/kitemviews/kfileitemmodel.cpp
+++ b/src/kitemviews/kfileitemmodel.cpp
@@ -68,16 +68,16 @@ KFileItemModel::KFileItemModel(QObject* parent) :
}
connect(m_dirLister, &KFileItemModelDirLister::started, this, &KFileItemModel::directoryLoadingStarted);
- connect(m_dirLister, static_cast<void(KFileItemModelDirLister::*)()>(&KFileItemModelDirLister::canceled), this, &KFileItemModel::slotCanceled);
- connect(m_dirLister, static_cast<void(KFileItemModelDirLister::*)(const QUrl&)>(&KFileItemModelDirLister::completed), this, &KFileItemModel::slotCompleted);
+ connect(m_dirLister, QOverload<>::of(&KCoreDirLister::canceled), this, &KFileItemModel::slotCanceled);
+ connect(m_dirLister, QOverload<const QUrl&>::of(&KCoreDirLister::completed), this, &KFileItemModel::slotCompleted);
connect(m_dirLister, &KFileItemModelDirLister::itemsAdded, this, &KFileItemModel::slotItemsAdded);
connect(m_dirLister, &KFileItemModelDirLister::itemsDeleted, this, &KFileItemModel::slotItemsDeleted);
connect(m_dirLister, &KFileItemModelDirLister::refreshItems, this, &KFileItemModel::slotRefreshItems);
- connect(m_dirLister, static_cast<void(KFileItemModelDirLister::*)()>(&KFileItemModelDirLister::clear), this, &KFileItemModel::slotClear);
+ connect(m_dirLister, QOverload<>::of(&KCoreDirLister::clear), this, &KFileItemModel::slotClear);
connect(m_dirLister, &KFileItemModelDirLister::infoMessage, this, &KFileItemModel::infoMessage);
connect(m_dirLister, &KFileItemModelDirLister::errorMessage, this, &KFileItemModel::errorMessage);
connect(m_dirLister, &KFileItemModelDirLister::percent, this, &KFileItemModel::directoryLoadingProgress);
- connect(m_dirLister, static_cast<void(KFileItemModelDirLister::*)(const QUrl&, const QUrl&)>(&KFileItemModelDirLister::redirection), this, &KFileItemModel::directoryRedirection);
+ connect(m_dirLister, QOverload<const QUrl&, const QUrl&>::of(&KCoreDirLister::redirection), this, &KFileItemModel::directoryRedirection);
connect(m_dirLister, &KFileItemModelDirLister::urlIsFileError, this, &KFileItemModel::urlIsFileError);
// Apply default roles that should be determined
@@ -304,9 +304,9 @@ QString KFileItemModel::roleDescription(const QByteArray& role) const
int count = 0;
const RoleInfoMap* map = rolesInfoMap(count);
for (int i = 0; i < count; ++i) {
- if (!map[i].roleTranslation) {
- continue;
- }
+ if (!map[i].roleTranslation) {
+ continue;
+ }
description.insert(map[i].role, i18nc(map[i].roleTranslationContext, map[i].roleTranslation));
}
}
@@ -2297,38 +2297,40 @@ void KFileItemModel::emitSortProgress(int resolvedCount)
const KFileItemModel::RoleInfoMap* KFileItemModel::rolesInfoMap(int& count)
{
static const RoleInfoMap rolesInfoMap[] = {
- // | role | roleType | role translation | group translation | requires Baloo | requires indexer
- { nullptr, NoRole, nullptr, nullptr, nullptr, nullptr, false, false },
- { "text", NameRole, I18N_NOOP2_NOSTRIP("@label", "Name"), nullptr, nullptr, false, false },
- { "size", SizeRole, I18N_NOOP2_NOSTRIP("@label", "Size"), nullptr, nullptr, false, false },
- { "modificationtime", ModificationTimeRole, I18N_NOOP2_NOSTRIP("@label", "Modified"), nullptr, nullptr, false, false },
- { "creationtime", CreationTimeRole, I18N_NOOP2_NOSTRIP("@label", "Created"), nullptr, nullptr, false, false },
- { "accesstime", AccessTimeRole, I18N_NOOP2_NOSTRIP("@label", "Accessed"), nullptr, nullptr, false, false },
- { "type", TypeRole, I18N_NOOP2_NOSTRIP("@label", "Type"), nullptr, nullptr, false, false },
- { "rating", RatingRole, I18N_NOOP2_NOSTRIP("@label", "Rating"), nullptr, nullptr, true, false },
- { "tags", TagsRole, I18N_NOOP2_NOSTRIP("@label", "Tags"), nullptr, nullptr, true, false },
- { "comment", CommentRole, I18N_NOOP2_NOSTRIP("@label", "Comment"), nullptr, nullptr, true, false },
- { "title", TitleRole, I18N_NOOP2_NOSTRIP("@label", "Title"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true },
- { "wordCount", WordCountRole, I18N_NOOP2_NOSTRIP("@label", "Word Count"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true },
- { "lineCount", LineCountRole, I18N_NOOP2_NOSTRIP("@label", "Line Count"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true },
- { "imageDateTime", ImageDateTimeRole, I18N_NOOP2_NOSTRIP("@label", "Date Photographed"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
- { "width", WidthRole, I18N_NOOP2_NOSTRIP("@label", "Width"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
- { "height", HeightRole, I18N_NOOP2_NOSTRIP("@label", "Height"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
- { "orientation", OrientationRole, I18N_NOOP2_NOSTRIP("@label", "Orientation"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
- { "artist", ArtistRole, I18N_NOOP2_NOSTRIP("@label", "Artist"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
- { "genre", GenreRole, I18N_NOOP2_NOSTRIP("@label", "Genre"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
- { "album", AlbumRole, I18N_NOOP2_NOSTRIP("@label", "Album"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
- { "duration", DurationRole, I18N_NOOP2_NOSTRIP("@label", "Duration"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
- { "bitrate", BitrateRole, I18N_NOOP2_NOSTRIP("@label", "Bitrate"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
- { "track", TrackRole, I18N_NOOP2_NOSTRIP("@label", "Track"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
- { "releaseYear", ReleaseYearRole, I18N_NOOP2_NOSTRIP("@label", "Release Year"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
- { "path", PathRole, I18N_NOOP2_NOSTRIP("@label", "Path"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
- { "deletiontime",DeletionTimeRole,I18N_NOOP2_NOSTRIP("@label", "Deletion Time"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
- { "destination", DestinationRole, I18N_NOOP2_NOSTRIP("@label", "Link Destination"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
- { "originUrl", OriginUrlRole, I18N_NOOP2_NOSTRIP("@label", "Downloaded From"), I18N_NOOP2_NOSTRIP("@label", "Other"), true, false },
- { "permissions", PermissionsRole, I18N_NOOP2_NOSTRIP("@label", "Permissions"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
- { "owner", OwnerRole, I18N_NOOP2_NOSTRIP("@label", "Owner"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
- { "group", GroupRole, I18N_NOOP2_NOSTRIP("@label", "User Group"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
+ // | role | roleType | role translation | group translation | requires Baloo | requires indexer
+ { nullptr, NoRole, nullptr, nullptr, nullptr, nullptr, false, false },
+ { "text", NameRole, I18N_NOOP2_NOSTRIP("@label", "Name"), nullptr, nullptr, false, false },
+ { "size", SizeRole, I18N_NOOP2_NOSTRIP("@label", "Size"), nullptr, nullptr, false, false },
+ { "modificationtime", ModificationTimeRole, I18N_NOOP2_NOSTRIP("@label", "Modified"), nullptr, nullptr, false, false },
+ { "creationtime", CreationTimeRole, I18N_NOOP2_NOSTRIP("@label", "Created"), nullptr, nullptr, false, false },
+ { "accesstime", AccessTimeRole, I18N_NOOP2_NOSTRIP("@label", "Accessed"), nullptr, nullptr, false, false },
+ { "type", TypeRole, I18N_NOOP2_NOSTRIP("@label", "Type"), nullptr, nullptr, false, false },
+ { "rating", RatingRole, I18N_NOOP2_NOSTRIP("@label", "Rating"), nullptr, nullptr, true, false },
+ { "tags", TagsRole, I18N_NOOP2_NOSTRIP("@label", "Tags"), nullptr, nullptr, true, false },
+ { "comment", CommentRole, I18N_NOOP2_NOSTRIP("@label", "Comment"), nullptr, nullptr, true, false },
+ { "title", TitleRole, I18N_NOOP2_NOSTRIP("@label", "Title"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true },
+ { "wordCount", WordCountRole, I18N_NOOP2_NOSTRIP("@label", "Word Count"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true },
+ { "lineCount", LineCountRole, I18N_NOOP2_NOSTRIP("@label", "Line Count"), I18N_NOOP2_NOSTRIP("@label", "Document"), true, true },
+ { "imageDateTime", ImageDateTimeRole, I18N_NOOP2_NOSTRIP("@label", "Date Photographed"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
+ { "width", WidthRole, I18N_NOOP2_NOSTRIP("@label", "Width"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
+ { "height", HeightRole, I18N_NOOP2_NOSTRIP("@label", "Height"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
+ { "orientation", OrientationRole, I18N_NOOP2_NOSTRIP("@label", "Orientation"), I18N_NOOP2_NOSTRIP("@label", "Image"), true, true },
+ { "artist", ArtistRole, I18N_NOOP2_NOSTRIP("@label", "Artist"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "genre", GenreRole, I18N_NOOP2_NOSTRIP("@label", "Genre"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "album", AlbumRole, I18N_NOOP2_NOSTRIP("@label", "Album"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "duration", DurationRole, I18N_NOOP2_NOSTRIP("@label", "Duration"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "bitrate", BitrateRole, I18N_NOOP2_NOSTRIP("@label", "Bitrate"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "track", TrackRole, I18N_NOOP2_NOSTRIP("@label", "Track"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "releaseYear", ReleaseYearRole, I18N_NOOP2_NOSTRIP("@label", "Release Year"), I18N_NOOP2_NOSTRIP("@label", "Audio"), true, true },
+ { "aspectRatio", AspectRatioRole, I18N_NOOP2_NOSTRIP("@label", "Aspect Ratio"), I18N_NOOP2_NOSTRIP("@label", "Video"), true, true },
+ { "frameRate", FrameRateRole, I18N_NOOP2_NOSTRIP("@label", "Frame Rate"), I18N_NOOP2_NOSTRIP("@label", "Video"), true, true },
+ { "path", PathRole, I18N_NOOP2_NOSTRIP("@label", "Path"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
+ { "deletiontime", DeletionTimeRole, I18N_NOOP2_NOSTRIP("@label", "Deletion Time"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
+ { "destination", DestinationRole, I18N_NOOP2_NOSTRIP("@label", "Link Destination"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
+ { "originUrl", OriginUrlRole, I18N_NOOP2_NOSTRIP("@label", "Downloaded From"), I18N_NOOP2_NOSTRIP("@label", "Other"), true, false },
+ { "permissions", PermissionsRole, I18N_NOOP2_NOSTRIP("@label", "Permissions"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
+ { "owner", OwnerRole, I18N_NOOP2_NOSTRIP("@label", "Owner"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
+ { "group", GroupRole, I18N_NOOP2_NOSTRIP("@label", "User Group"), I18N_NOOP2_NOSTRIP("@label", "Other"), false, false },
};
count = sizeof(rolesInfoMap) / sizeof(RoleInfoMap);
diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h
index d15cfebc1..0f7926aae 100644
--- a/src/kitemviews/kfileitemmodel.h
+++ b/src/kitemviews/kfileitemmodel.h
@@ -288,7 +288,7 @@ private:
// User visible roles available with Baloo:
CommentRole, TagsRole, RatingRole, WidthRole, HeightRole, ImageDateTimeRole, OrientationRole,
WordCountRole, TitleRole, LineCountRole, ArtistRole, GenreRole, AlbumRole, DurationRole, TrackRole, ReleaseYearRole,
- BitrateRole, OriginUrlRole,
+ BitrateRole, OriginUrlRole, AspectRatioRole, FrameRateRole,
// Non-visible roles:
IsDirRole, IsLinkRole, IsHiddenRole, IsExpandedRole, IsExpandableRole, ExpandedParentsCountRole,
// Mandatory last entry:
diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp
index d3dbeb35c..6fb6a5132 100644
--- a/src/kitemviews/kitemlistcontroller.cpp
+++ b/src/kitemviews/kitemlistcontroller.cpp
@@ -231,6 +231,9 @@ bool KItemListController::keyPressEvent(QKeyEvent* event)
const bool shiftPressed = event->modifiers() & Qt::ShiftModifier;
const bool controlPressed = event->modifiers() & Qt::ControlModifier;
const bool shiftOrControlPressed = shiftPressed || controlPressed;
+ const bool navigationPressed = key == Qt::Key_Home || key == Qt::Key_End ||
+ key == Qt::Key_Up || key == Qt::Key_Down ||
+ key == Qt::Key_Left || key == Qt::Key_Right;
const int itemCount = m_model->count();
@@ -246,11 +249,8 @@ bool KItemListController::keyPressEvent(QKeyEvent* event)
}
}
- const bool selectSingleItem = m_selectionBehavior != NoSelection &&
- itemCount == 1 &&
- (key == Qt::Key_Home || key == Qt::Key_End ||
- key == Qt::Key_Up || key == Qt::Key_Down ||
- key == Qt::Key_Left || key == Qt::Key_Right);
+ const bool selectSingleItem = m_selectionBehavior != NoSelection && itemCount == 1 && navigationPressed;
+
if (selectSingleItem) {
const int current = m_selectionManager->currentItem();
m_selectionManager->setSelected(current);
@@ -458,8 +458,12 @@ bool KItemListController::keyPressEvent(QKeyEvent* event)
}
break;
}
+ }
- m_view->scrollToItem(index);
+ if (navigationPressed) {
+ if (index < m_view->firstVisibleIndex() || index > m_view->lastVisibleIndex()) {
+ m_view->scrollToItem(index);
+ }
}
return true;
}
diff --git a/src/kitemviews/kstandarditem.cpp b/src/kitemviews/kstandarditem.cpp
index 4fb3f8f98..b3bbcaa41 100644
--- a/src/kitemviews/kstandarditem.cpp
+++ b/src/kitemviews/kstandarditem.cpp
@@ -21,16 +21,14 @@
#include "kstandarditemmodel.h"
KStandardItem::KStandardItem(KStandardItem* parent) :
- m_parent(parent),
- m_children(),
+ QObject(parent),
m_model(nullptr),
m_data()
{
}
KStandardItem::KStandardItem(const QString& text, KStandardItem* parent) :
- m_parent(parent),
- m_children(),
+ QObject(parent),
m_model(nullptr),
m_data()
{
@@ -38,8 +36,7 @@ KStandardItem::KStandardItem(const QString& text, KStandardItem* parent) :
}
KStandardItem::KStandardItem(const QString& icon, const QString& text, KStandardItem* parent) :
- m_parent(parent),
- m_children(),
+ QObject(parent),
m_model(nullptr),
m_data()
{
@@ -47,14 +44,6 @@ KStandardItem::KStandardItem(const QString& icon, const QString& text, KStandard
setText(text);
}
-KStandardItem::KStandardItem(const KStandardItem& item) :
- m_parent(item.m_parent),
- m_children(item.m_children),
- m_model(item.m_model),
- m_data(item.m_data)
-{
-}
-
KStandardItem::~KStandardItem()
{
}
@@ -123,17 +112,6 @@ QVariant KStandardItem::dataValue(const QByteArray& role) const
return m_data[role];
}
-void KStandardItem::setParent(KStandardItem* parent)
-{
- // TODO: not implemented yet
- m_parent = parent;
-}
-
-KStandardItem* KStandardItem::parent() const
-{
- return m_parent;
-}
-
void KStandardItem::setData(const QHash<QByteArray, QVariant>& values)
{
const QHash<QByteArray, QVariant> previous = m_data;
@@ -146,11 +124,6 @@ QHash<QByteArray, QVariant> KStandardItem::data() const
return m_data;
}
-QList<KStandardItem*> KStandardItem::children() const
-{
- return m_children;
-}
-
void KStandardItem::onDataValueChanged(const QByteArray& role,
const QVariant& current,
const QVariant& previous)
diff --git a/src/kitemviews/kstandarditem.h b/src/kitemviews/kstandarditem.h
index fec197c06..ad3452d77 100644
--- a/src/kitemviews/kstandarditem.h
+++ b/src/kitemviews/kstandarditem.h
@@ -24,7 +24,7 @@
#include <QByteArray>
#include <QHash>
-#include <QList>
+#include <QObject>
#include <QVariant>
class KStandardItemModel;
@@ -36,14 +36,13 @@ class KStandardItemModel;
* used roles. It is possible to assign values for custom
* roles by using setDataValue().
*/
-class DOLPHIN_EXPORT KStandardItem
+class DOLPHIN_EXPORT KStandardItem : public QObject
{
-
+ Q_OBJECT
public:
explicit KStandardItem(KStandardItem* parent = nullptr);
explicit KStandardItem(const QString& text, KStandardItem* parent = nullptr);
KStandardItem(const QString& icon, const QString& text, KStandardItem* parent = nullptr);
- KStandardItem(const KStandardItem& item);
virtual ~KStandardItem();
/**
@@ -70,14 +69,9 @@ public:
void setDataValue(const QByteArray& role, const QVariant& value);
QVariant dataValue(const QByteArray& role) const;
- void setParent(KStandardItem* parent);
- KStandardItem* parent() const;
-
void setData(const QHash<QByteArray, QVariant>& values);
QHash<QByteArray, QVariant> data() const;
- QList<KStandardItem*> children() const;
-
protected:
virtual void onDataValueChanged(const QByteArray& role,
const QVariant& current,
@@ -87,8 +81,6 @@ protected:
const QHash<QByteArray, QVariant>& previous);
private:
- KStandardItem* m_parent;
- QList<KStandardItem*> m_children;
KStandardItemModel* m_model;
QHash<QByteArray, QVariant> m_data;
diff --git a/src/kitemviews/kstandarditemlistwidget.cpp b/src/kitemviews/kstandarditemlistwidget.cpp
index f56f68ac5..15c01726f 100644
--- a/src/kitemviews/kstandarditemlistwidget.cpp
+++ b/src/kitemviews/kstandarditemlistwidget.cpp
@@ -1225,7 +1225,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache()
textInfo->staticText.setText(elidedText);
requiredWidth = m_customizedFontMetrics.width(elidedText);
} else if (role == "rating") {
- // Use the width of the rating pixmap, because the rating text is empty.
+ // Use the width of the rating pixmap, because the rating text is empty.
requiredWidth = m_rating.width();
}
}
diff --git a/src/kitemviews/kstandarditemlistwidget.h b/src/kitemviews/kstandarditemlistwidget.h
index 220c0ebc3..c8102e421 100644
--- a/src/kitemviews/kstandarditemlistwidget.h
+++ b/src/kitemviews/kstandarditemlistwidget.h
@@ -80,7 +80,7 @@ protected:
};
/**
- * @brief Itemlist widget implementation for KStandardItemView and KStandardItemModel.
+ * @brief Itemlist widget implementation for KStandardItemListView and KStandardItemModel.
*/
class DOLPHIN_EXPORT KStandardItemListWidget : public KItemListWidget
{
diff --git a/src/kitemviews/kstandarditemmodel.cpp b/src/kitemviews/kstandarditemmodel.cpp
index a4d42b571..d7307c0bd 100644
--- a/src/kitemviews/kstandarditemmodel.cpp
+++ b/src/kitemviews/kstandarditemmodel.cpp
@@ -112,7 +112,7 @@ void KStandardItemModel::removeItem(int index)
onItemRemoved(index, item);
- delete item;
+ item->deleteLater();
item = nullptr;
emit itemsRemoved(KItemRangeList() << KItemRange(index, 1));
diff --git a/src/kitemviews/kstandarditemmodel.h b/src/kitemviews/kstandarditemmodel.h
index 6685a2038..8643d2e9e 100644
--- a/src/kitemviews/kstandarditemmodel.h
+++ b/src/kitemviews/kstandarditemmodel.h
@@ -29,7 +29,7 @@
class KStandardItem;
/**
- * @brief Model counterpart for KStandardItemView.
+ * @brief Model counterpart for KStandardItemListView.
*
* Allows to add items to the model in an easy way by the
* class KStandardItem.
diff --git a/src/kitemviews/private/kbaloorolesprovider.cpp b/src/kitemviews/private/kbaloorolesprovider.cpp
index 0eedf1806..469f07915 100644
--- a/src/kitemviews/private/kbaloorolesprovider.cpp
+++ b/src/kitemviews/private/kbaloorolesprovider.cpp
@@ -120,6 +120,8 @@ KBalooRolesProvider::KBalooRolesProvider() :
{ "album", "album" },
{ "duration", "duration" },
{ "bitRate", "bitrate" },
+ { "aspectRatio", "aspectRatio" },
+ { "frameRate", "frameRate" },
{ "releaseYear", "releaseYear" },
{ "trackNumber", "track" },
{ "originUrl", "originUrl" }
diff --git a/src/kitemviews/private/kitemlistroleeditor.cpp b/src/kitemviews/private/kitemlistroleeditor.cpp
index e79a9f9d1..eb6f1de76 100644
--- a/src/kitemviews/private/kitemlistroleeditor.cpp
+++ b/src/kitemviews/private/kitemlistroleeditor.cpp
@@ -107,6 +107,23 @@ void KItemListRoleEditor::keyPressEvent(QKeyEvent* event)
}
break;
}
+ case Qt::Key_Home:
+ case Qt::Key_End: {
+ if (event->modifiers() == Qt::NoModifier || event->modifiers() == Qt::ShiftModifier) {
+ const QTextCursor::MoveOperation op = event->key() == Qt::Key_Home
+ ? QTextCursor::Start
+ : QTextCursor::End;
+ const QTextCursor::MoveMode mode = event->modifiers() == Qt::NoModifier
+ ? QTextCursor::MoveAnchor
+ : QTextCursor::KeepAnchor;
+ QTextCursor cursor = textCursor();
+ cursor.movePosition(op, mode);
+ setTextCursor(cursor);
+ event->accept();
+ return;
+ }
+ break;
+ }
default:
break;
}
diff --git a/src/org.kde.dolphin.desktop b/src/org.kde.dolphin.desktop
index e5bfed010..060dd526e 100755
--- a/src/org.kde.dolphin.desktop
+++ b/src/org.kde.dolphin.desktop
@@ -97,4 +97,5 @@ Terminal=false
MimeType=inode/directory;
InitialPreference=10
X-DBUS-ServiceName=org.kde.dolphin
+X-KDE-Shortcuts=Meta+E
StartupWMClass=dolphin
diff --git a/src/panels/information/filemetadataconfigurationdialog.cpp b/src/panels/information/filemetadataconfigurationdialog.cpp
deleted file mode 100644
index f3ca819b7..000000000
--- a/src/panels/information/filemetadataconfigurationdialog.cpp
+++ /dev/null
@@ -1,102 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Peter Penz <[email protected]> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
- ***************************************************************************/
-
-#include "filemetadataconfigurationdialog.h"
-
-#include <Baloo/FileMetaDataConfigWidget>
-#include <KConfigGroup>
-#include <KLocalizedString>
-#include <KSharedConfig>
-#include <KWindowConfig>
-
-#include <QDialogButtonBox>
-#include <QLabel>
-#include <QPushButton>
-#include <QVBoxLayout>
-
-FileMetaDataConfigurationDialog::FileMetaDataConfigurationDialog(QWidget* parent) :
- QDialog(parent),
- m_descriptionLabel(nullptr),
- m_configWidget(nullptr)
-
-{
- setWindowTitle(i18nc("@title:window", "Configure Shown Data"));
- QDialogButtonBox *buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel);
- QVBoxLayout *mainLayout = new QVBoxLayout;
- setLayout(mainLayout);
- QPushButton *okButton = buttonBox->button(QDialogButtonBox::Ok);
- okButton->setDefault(true);
- okButton->setShortcut(Qt::CTRL + Qt::Key_Return);
- connect(buttonBox, &QDialogButtonBox::accepted, this, &FileMetaDataConfigurationDialog::slotAccepted);
- connect(buttonBox, &QDialogButtonBox::rejected, this, &FileMetaDataConfigurationDialog::reject);
- buttonBox->button(QDialogButtonBox::Ok)->setDefault(true);
-
- m_descriptionLabel = new QLabel(i18nc("@label::textbox",
- "Select which data should "
- "be shown:"), this);
- m_descriptionLabel->setWordWrap(true);
-
- m_configWidget = new Baloo::FileMetaDataConfigWidget(this);
-
- QWidget* mainWidget = new QWidget(this);
- QVBoxLayout* topLayout = new QVBoxLayout(mainWidget);
- topLayout->addWidget(m_descriptionLabel);
- topLayout->addWidget(m_configWidget);
- mainLayout->addWidget(mainWidget);
- mainLayout->addWidget(buttonBox);
-
-
- const KConfigGroup dialogConfig(KSharedConfig::openConfig(QStringLiteral("dolphinrc")),
- "FileMetaDataConfigurationDialog");
- KWindowConfig::restoreWindowSize(windowHandle(), dialogConfig);
-}
-
-FileMetaDataConfigurationDialog::~FileMetaDataConfigurationDialog()
-{
- KConfigGroup dialogConfig(KSharedConfig::openConfig(QStringLiteral("dolphinrc")),
- "FileMetaDataConfigurationDialog");
- KWindowConfig::saveWindowSize(windowHandle(), dialogConfig);
-}
-
-void FileMetaDataConfigurationDialog::setItems(const KFileItemList& items)
-{
- m_configWidget->setItems(items);
-}
-
-KFileItemList FileMetaDataConfigurationDialog::items() const
-{
- return m_configWidget->items();
-}
-
-void FileMetaDataConfigurationDialog::slotAccepted()
-{
- m_configWidget->save();
- accept();
-}
-
-void FileMetaDataConfigurationDialog::setDescription(const QString& description)
-{
- m_descriptionLabel->setText(description);
-}
-
-QString FileMetaDataConfigurationDialog::description() const
-{
- return m_descriptionLabel->text();
-}
-
diff --git a/src/panels/information/filemetadataconfigurationdialog.h b/src/panels/information/filemetadataconfigurationdialog.h
deleted file mode 100644
index 04357783c..000000000
--- a/src/panels/information/filemetadataconfigurationdialog.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/***************************************************************************
- * Copyright (C) 2010 by Peter Penz <[email protected]> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the *
- * Free Software Foundation, Inc., *
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
- ***************************************************************************/
-
-#ifndef FILEMETADATACONFIGURATIONDIALOG_H
-#define FILEMETADATACONFIGURATIONDIALOG_H
-
-#include <QDialog>
-
-#include <KFileItem>
-#include <config-baloo.h>
-#ifndef HAVE_BALOO
-class KFileMetaDataConfigurationWidget;
-#else
-namespace Baloo {
- class FileMetaDataConfigWidget;
-}
-#endif
-
-class QLabel;
-
-/**
- * @brief Dialog which allows to configure which meta data should be shown
- * in the KFileMetaDataWidget.
- */
-class FileMetaDataConfigurationDialog : public QDialog
-{
- Q_OBJECT
-
-public:
- explicit FileMetaDataConfigurationDialog(QWidget* parent = nullptr);
- ~FileMetaDataConfigurationDialog() override;
-
- /**
- * Sets the items, for which the visibility of the meta data should
- * be configured. Note that the visibility of the meta data is not
- * bound to the items itself, the items are only used to determine
- * which meta data should be configurable. For example when a JPEG image
- * is set as item, it will be configurable which EXIF data should be
- * shown. If an audio file is set as item, it will be configurable
- * whether the artist, album name, ... should be shown.
- */
- void setItems(const KFileItemList& items);
- KFileItemList items() const;
-
- /**
- * Sets the description that is shown above the list
- * of meta data. Per default the translated text for
- * "Select which data should be shown." is set.
- */
- void setDescription(const QString& description);
- QString description() const;
-
-protected slots:
- void slotAccepted();
-private:
- QLabel* m_descriptionLabel;
- Baloo::FileMetaDataConfigWidget* m_configWidget;
-};
-
-#endif
diff --git a/src/panels/information/informationpanel.cpp b/src/panels/information/informationpanel.cpp
index cd8b6b38d..9a0358df0 100644
--- a/src/panels/information/informationpanel.cpp
+++ b/src/panels/information/informationpanel.cpp
@@ -36,7 +36,6 @@
#include <QMenu>
#include "dolphin_informationpanelsettings.h"
-#include "filemetadataconfigurationdialog.h"
InformationPanel::InformationPanel(QWidget* parent) :
Panel(parent),
@@ -168,7 +167,8 @@ void InformationPanel::contextMenuEvent(QContextMenuEvent* event)
Panel::contextMenuEvent(event);
}
-void InformationPanel::showContextMenu(const QPoint &pos) {
+void InformationPanel::showContextMenu(const QPoint &pos)
+{
QMenu popup(this);
QAction* previewAction = popup.addAction(i18nc("@action:inmenu", "Preview"));
@@ -178,6 +178,9 @@ void InformationPanel::showContextMenu(const QPoint &pos) {
QAction* configureAction = popup.addAction(i18nc("@action:inmenu", "Configure..."));
configureAction->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
+ if (m_inConfigurationMode) {
+ configureAction->setEnabled(false);
+ }
QAction* dateformatAction = popup.addAction(i18nc("@action:inmenu", "Condensed Date"));
dateformatAction->setIcon(QIcon::fromTheme(QStringLiteral("change-date-symbolic")));
@@ -185,7 +188,8 @@ void InformationPanel::showContextMenu(const QPoint &pos) {
dateformatAction->setChecked(InformationPanelSettings::dateFormat() == static_cast<int>(Baloo::DateFormats::ShortFormat));
popup.addSeparator();
- foreach (QAction* action, customContextMenuActions()) {
+ const auto actions = customContextMenuActions();
+ for (QAction *action : actions) {
popup.addAction(action);
}
@@ -201,13 +205,8 @@ void InformationPanel::showContextMenu(const QPoint &pos) {
InformationPanelSettings::setPreviewsShown(isChecked);
m_content->refreshPreview();
} else if (action == configureAction) {
- FileMetaDataConfigurationDialog* dialog = new FileMetaDataConfigurationDialog(this);
- dialog->setDescription(i18nc("@label::textbox",
- "Select which data should be shown in the information panel:"));
- dialog->setItems(m_content->items());
- dialog->setAttribute(Qt::WA_DeleteOnClose);
- dialog->show();
- connect(dialog, &FileMetaDataConfigurationDialog::destroyed, m_content, &InformationPanelContent::refreshMetaData);
+ m_inConfigurationMode = true;
+ m_content->configureShownProperties();
}
if (action == dateformatAction) {
int dateFormat = static_cast<int>(isChecked ? Baloo::DateFormats::ShortFormat : Baloo::DateFormats::LongFormat);
@@ -311,7 +310,7 @@ void InformationPanel::slotFilesAdded(const QString& directory)
void InformationPanel::slotFilesChanged(const QStringList& files)
{
- foreach (const QString& fileName, files) {
+ for (const QString& fileName : files) {
if (m_shownUrl == QUrl::fromLocalFile(fileName)) {
showItemInfo();
break;
@@ -321,7 +320,7 @@ void InformationPanel::slotFilesChanged(const QStringList& files)
void InformationPanel::slotFilesRemoved(const QStringList& files)
{
- foreach (const QString& fileName, files) {
+ for (const QString& fileName : files) {
if (m_shownUrl == QUrl::fromLocalFile(fileName)) {
// the currently shown item has been removed, show
// the parent directory as fallback
@@ -410,6 +409,7 @@ void InformationPanel::init()
m_content = new InformationPanelContent(this);
connect(m_content, &InformationPanelContent::urlActivated, this, &InformationPanel::urlActivated);
+ connect(m_content, &InformationPanelContent::configurationFinished, this, [this]() { m_inConfigurationMode = false; });
QVBoxLayout* layout = new QVBoxLayout(this);
layout->setContentsMargins(0, 0, 0, 0);
diff --git a/src/panels/information/informationpanel.h b/src/panels/information/informationpanel.h
index f63af1e53..321827c5b 100644
--- a/src/panels/information/informationpanel.h
+++ b/src/panels/information/informationpanel.h
@@ -161,6 +161,7 @@ private:
KIO::Job* m_folderStatJob;
InformationPanelContent* m_content;
+ bool m_inConfigurationMode = false;
};
#endif // INFORMATIONPANEL_H
diff --git a/src/panels/information/informationpanelcontent.cpp b/src/panels/information/informationpanelcontent.cpp
index 0eaa125f1..5b7dbbfe9 100644
--- a/src/panels/information/informationpanelcontent.cpp
+++ b/src/panels/information/informationpanelcontent.cpp
@@ -40,6 +40,7 @@
#include <Phonon/MediaObject>
#include <QLabel>
+#include <QDialogButtonBox>
#include <QScrollArea>
#include <QTextLayout>
#include <QTimer>
@@ -107,18 +108,31 @@ InformationPanelContent::InformationPanelContent(QWidget* parent) :
m_metaDataWidget->setFont(QFontDatabase::systemFont(QFontDatabase::SmallestReadableFont));
m_metaDataWidget->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
- // Encapsulate the MetaDataWidget inside a container that has a dummy widget
- // at the bottom. This prevents that the meta data widget gets vertically stretched
- // in the case where the height of m_metaDataArea > m_metaDataWidget.
- QWidget* metaDataWidgetContainer = new QWidget(parent);
- QVBoxLayout* containerLayout = new QVBoxLayout(metaDataWidgetContainer);
- containerLayout->setContentsMargins(0, 0, 0, 0);
- containerLayout->setSpacing(0);
- containerLayout->addWidget(m_metaDataWidget);
- containerLayout->addStretch();
+ // Configuration
+ m_configureLabel = new QLabel(i18nc("@label::textbox",
+ "Select which data should be shown:"), this);
+ m_configureLabel->setWordWrap(true);
+ m_configureLabel->setVisible(false);
+
+ m_configureButtons = new QDialogButtonBox(QDialogButtonBox::Save | QDialogButtonBox::Cancel);
+ m_configureButtons->setVisible(false);
+ connect(m_configureButtons, &QDialogButtonBox::accepted, this, [this]() {
+ m_metaDataWidget->setConfigurationMode(Baloo::ConfigurationMode::Accept);
+ m_configureButtons->setVisible(false);
+ m_configureLabel->setVisible(false);
+ emit configurationFinished();
+ }
+ );
+ connect(m_configureButtons, &QDialogButtonBox::rejected, this, [this]() {
+ m_metaDataWidget->setConfigurationMode(Baloo::ConfigurationMode::Cancel);
+ m_configureButtons->setVisible(false);
+ m_configureLabel->setVisible(false);
+ emit configurationFinished();
+ }
+ );
m_metaDataArea = new QScrollArea(parent);
- m_metaDataArea->setWidget(metaDataWidgetContainer);
+ m_metaDataArea->setWidget(m_metaDataWidget);
m_metaDataArea->setWidgetResizable(true);
m_metaDataArea->setFrameShape(QFrame::NoFrame);
@@ -129,7 +143,9 @@ InformationPanelContent::InformationPanelContent(QWidget* parent) :
layout->addWidget(m_phononWidget);
layout->addWidget(m_nameLabel);
layout->addWidget(new KSeparator());
+ layout->addWidget(m_configureLabel);
layout->addWidget(m_metaDataArea);
+ layout->addWidget(m_configureButtons);
m_placesItemModel = new PlacesItemModel(this);
}
@@ -147,7 +163,8 @@ void InformationPanelContent::showItem(const KFileItem& item)
refreshMetaData();
}
-void InformationPanelContent::refreshPreview() {
+void InformationPanelContent::refreshPreview()
+{
// If there is a preview job, kill it to prevent that we have jobs for
// multiple items running, and thus a race condition (bug 250787).
if (m_previewJob) {
@@ -209,12 +226,18 @@ void InformationPanelContent::refreshPreview() {
}
}
-void InformationPanelContent::refreshMetaData() {
- if (m_metaDataWidget) {
- m_metaDataWidget->setDateFormat(static_cast<Baloo::DateFormats>(InformationPanelSettings::dateFormat()));
- m_metaDataWidget->show();
- m_metaDataWidget->setItems(KFileItemList() << m_item);
- }
+void InformationPanelContent::configureShownProperties()
+{
+ m_configureLabel->setVisible(true);
+ m_configureButtons->setVisible(true);
+ m_metaDataWidget->setConfigurationMode(Baloo::ConfigurationMode::ReStart);
+}
+
+void InformationPanelContent::refreshMetaData()
+{
+ m_metaDataWidget->setDateFormat(static_cast<Baloo::DateFormats>(InformationPanelSettings::dateFormat()));
+ m_metaDataWidget->show();
+ m_metaDataWidget->setItems(KFileItemList() << m_item);
}
void InformationPanelContent::showItems(const KFileItemList& items)
@@ -230,9 +253,7 @@ void InformationPanelContent::showItems(const KFileItemList& items)
);
setNameLabelText(i18ncp("@label", "%1 item selected", "%1 items selected", items.count()));
- if (m_metaDataWidget) {
- m_metaDataWidget->setItems(items);
- }
+ m_metaDataWidget->setItems(items);
m_phononWidget->hide();
@@ -297,7 +318,8 @@ void InformationPanelContent::markOutdatedPreview()
m_preview->setPixmap(disabledPixmap);
}
-KFileItemList InformationPanelContent::items() {
+KFileItemList InformationPanelContent::items()
+{
return m_metaDataWidget->items();
}
@@ -349,9 +371,7 @@ void InformationPanelContent::adjustWidgetSizes(int width)
// The metadata widget also contains a text widget which may return
// a large preferred width.
- if (m_metaDataWidget) {
- m_metaDataWidget->setMaximumWidth(maxWidth);
- }
+ m_metaDataWidget->setMaximumWidth(maxWidth);
// try to increase the preview as large as possible
m_preview->setSizeHint(QSize(maxWidth, maxWidth));
diff --git a/src/panels/information/informationpanelcontent.h b/src/panels/information/informationpanelcontent.h
index 83fb3d80b..43410ddfa 100644
--- a/src/panels/information/informationpanelcontent.h
+++ b/src/panels/information/informationpanelcontent.h
@@ -32,6 +32,7 @@ class PhononWidget;
class PixmapViewer;
class PlacesItemModel;
class QPixmap;
+class QDialogButtonBox;
class QString;
class QLabel;
class QScrollArea;
@@ -40,13 +41,9 @@ namespace KIO {
class PreviewJob;
}
-#ifndef HAVE_BALOO
-class KFileMetaDataWidget;
-#else
namespace Baloo {
class FileMetaDataWidget;
}
-#endif
/**
* @brief Manages the widgets that display the meta information
@@ -79,8 +76,14 @@ public:
*/
void refreshPreview();
+ /**
+ * Switch the metadatawidget into configuration mode
+ */
+ void configureShownProperties();
+
signals:
void urlActivated( const QUrl& url );
+ void configurationFinished();
public slots:
/**
@@ -138,12 +141,10 @@ private:
PixmapViewer* m_preview;
PhononWidget* m_phononWidget;
QLabel* m_nameLabel;
-#ifndef HAVE_BALOO
- KFileMetaDataWidget* m_metaDataWidget;
-#else
Baloo::FileMetaDataWidget* m_metaDataWidget;
-#endif
QScrollArea* m_metaDataArea;
+ QLabel* m_configureLabel;
+ QDialogButtonBox* m_configureButtons;
PlacesItemModel* m_placesItemModel;
};
diff --git a/src/panels/information/pixmapviewer.cpp b/src/panels/information/pixmapviewer.cpp
index 5828a37dd..311995ec2 100644
--- a/src/panels/information/pixmapviewer.cpp
+++ b/src/panels/information/pixmapviewer.cpp
@@ -37,7 +37,7 @@ PixmapViewer::PixmapViewer(QWidget* parent, Transition transition) :
m_animation.setCurveShape(QTimeLine::LinearCurve);
if (m_transition != NoTransition) {
- connect(&m_animation, &QTimeLine::valueChanged, this, static_cast<void(PixmapViewer::*)()>(&PixmapViewer::update));
+ connect(&m_animation, &QTimeLine::valueChanged, this, QOverload<>::of(&PixmapViewer::update));
connect(&m_animation, &QTimeLine::finished, this, &PixmapViewer::checkPendingPixmaps);
}
}
@@ -97,14 +97,14 @@ void PixmapViewer::paintEvent(QPaintEvent* event)
const bool useOldPixmap = (m_transition == SizeTransition) &&
(m_oldPixmap.width() > m_pixmap.width());
const QPixmap& largePixmap = useOldPixmap ? m_oldPixmap : m_pixmap;
- if (!largePixmap.isNull()) {
+ if (!largePixmap.isNull()) {
const QPixmap scaledPixmap = largePixmap.scaled(scaledWidth,
scaledHeight,
Qt::IgnoreAspectRatio,
Qt::FastTransformation);
style()->drawItemPixmap(&painter, rect(), Qt::AlignCenter, scaledPixmap);
- }
+ }
} else {
style()->drawItemPixmap(&painter, rect(), Qt::AlignCenter, m_pixmap);
}
diff --git a/src/panels/places/placespanel.cpp b/src/panels/places/placespanel.cpp
index 224eb0c64..41f50e740 100644
--- a/src/panels/places/placespanel.cpp
+++ b/src/panels/places/placespanel.cpp
@@ -93,8 +93,8 @@ bool PlacesPanel::urlChanged()
void PlacesPanel::readSettings()
{
if (m_controller) {
- const int delay = GeneralSettings::autoExpandFolders() ? 750 : -1;
- m_controller->setAutoActivationDelay(delay);
+ const int delay = GeneralSettings::autoExpandFolders() ? 750 : -1;
+ m_controller->setAutoActivationDelay(delay);
}
}
diff --git a/src/search/dolphinsearchbox.cpp b/src/search/dolphinsearchbox.cpp
index 9c41db9c5..d846e5b6c 100644
--- a/src/search/dolphinsearchbox.cpp
+++ b/src/search/dolphinsearchbox.cpp
@@ -49,7 +49,6 @@ DolphinSearchBox::DolphinSearchBox(QWidget* parent) :
m_startedSearching(false),
m_active(true),
m_topLayout(nullptr),
- m_searchLabel(nullptr),
m_searchInput(nullptr),
m_saveSearchAction(nullptr),
m_optionsScrollArea(nullptr),
@@ -87,22 +86,22 @@ void DolphinSearchBox::setSearchPath(const QUrl& url)
QFontMetrics metrics(m_fromHereButton->font());
const int maxWidth = metrics.height() * 8;
- QString location = url.fileName();
+ const QUrl cleanedUrl = url.adjusted(QUrl::RemoveUserInfo | QUrl::StripTrailingSlash);
+ QString location = cleanedUrl.fileName();
if (location.isEmpty()) {
- if (url.isLocalFile()) {
- location = QStringLiteral("/");
- } else {
- location = url.scheme() + QLatin1String(" - ") + url.host();
- }
+ location = cleanedUrl.toString(QUrl::PreferLocalFile);
+ }
+ if (m_fromHereButton->isChecked() && cleanedUrl.path() == QDir::homePath()) {
+ m_fromHereButton->setChecked(false);
+ m_everywhereButton->setChecked(true);
+ } else {
+ m_fromHereButton->setChecked(true);
+ m_everywhereButton->setChecked(false);
}
const QString elidedLocation = metrics.elidedText(location, Qt::ElideMiddle, maxWidth);
m_fromHereButton->setText(i18nc("action:button", "From Here (%1)", elidedLocation));
-
- const bool showSearchFromButtons = url.isLocalFile();
- m_separator->setVisible(showSearchFromButtons);
- m_fromHereButton->setVisible(showSearchFromButtons);
- m_everywhereButton->setVisible(showSearchFromButtons);
+ m_fromHereButton->setToolTip(i18nc("action:button", "Limit search to '%1' and its subfolders", cleanedUrl.toString(QUrl::PreferLocalFile)));
bool hasFacetsSupport = false;
#ifdef HAVE_BALOO
@@ -138,9 +137,6 @@ QUrl DolphinSearchBox::urlForSearching() const
QString encodedUrl;
if (m_everywhereButton->isChecked()) {
- // It is very unlikely, that the majority of Dolphins target users
- // mean "the whole harddisk" instead of "my home folder" when
- // selecting the "Everywhere" button.
encodedUrl = QDir::homePath();
} else {
encodedUrl = m_searchPath.url();
@@ -358,11 +354,9 @@ void DolphinSearchBox::init()
closeButton->setToolTip(i18nc("@info:tooltip", "Quit searching"));
connect(closeButton, &QToolButton::clicked, this, &DolphinSearchBox::emitCloseRequest);
- // Create search label
- m_searchLabel = new QLabel(this);
-
// Create search box
m_searchInput = new QLineEdit(this);
+ m_searchInput->setPlaceholderText(i18n("Search..."));
m_searchInput->installEventFilter(this);
m_searchInput->setClearButtonEnabled(true);
m_searchInput->setFont(QFontDatabase::systemFont(QFontDatabase::GeneralFont));
@@ -384,7 +378,6 @@ void DolphinSearchBox::init()
QHBoxLayout* searchInputLayout = new QHBoxLayout();
searchInputLayout->setContentsMargins(0, 0, 0, 0);
searchInputLayout->addWidget(closeButton);
- searchInputLayout->addWidget(m_searchLabel);
searchInputLayout->addWidget(m_searchInput);
// Create "Filename" and "Content" button
@@ -402,13 +395,16 @@ void DolphinSearchBox::init()
m_separator = new KSeparator(Qt::Vertical, this);
- // Create "From Here" and "Everywhere"button
+ // Create "From Here" and "Your files" buttons
m_fromHereButton = new QToolButton(this);
m_fromHereButton->setText(i18nc("action:button", "From Here"));
initButton(m_fromHereButton);
m_everywhereButton = new QToolButton(this);
- m_everywhereButton->setText(i18nc("action:button", "Everywhere"));
+ m_everywhereButton->setText(i18nc("action:button", "Your files"));
+ m_everywhereButton->setToolTip(i18nc("action:button", "Search in your home directory"));
+ m_everywhereButton->setIcon(QIcon::fromTheme(QStringLiteral("user-home")));
+ m_everywhereButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
initButton(m_everywhereButton);
QButtonGroup* searchLocationGroup = new QButtonGroup(this);
diff --git a/src/search/dolphinsearchbox.h b/src/search/dolphinsearchbox.h
index c138cfe7f..bb71049c7 100644
--- a/src/search/dolphinsearchbox.h
+++ b/src/search/dolphinsearchbox.h
@@ -166,7 +166,6 @@ private:
QVBoxLayout* m_topLayout;
- QLabel* m_searchLabel;
QLineEdit* m_searchInput;
QAction* m_saveSearchAction;
QScrollArea* m_optionsScrollArea;
diff --git a/src/settings/dolphinsettingsdialog.cpp b/src/settings/dolphinsettingsdialog.cpp
index 6bddb861f..f4da53c9d 100644
--- a/src/settings/dolphinsettingsdialog.cpp
+++ b/src/settings/dolphinsettingsdialog.cpp
@@ -32,12 +32,14 @@
#include <KAuthorized>
#include <KLocalizedString>
#include <KWindowConfig>
+#include <KMessageBox>
#include <QPushButton>
DolphinSettingsDialog::DolphinSettingsDialog(const QUrl& url, QWidget* parent) :
KPageDialog(parent),
- m_pages()
+ m_pages(),
+ m_unsavedChanges(false)
{
const QSize minSize = minimumSize();
@@ -121,6 +123,7 @@ DolphinSettingsDialog::~DolphinSettingsDialog()
void DolphinSettingsDialog::enableApply()
{
buttonBox()->button(QDialogButtonBox::Apply)->setEnabled(true);
+ m_unsavedChanges = true;
}
void DolphinSettingsDialog::applySettings()
@@ -139,6 +142,7 @@ void DolphinSettingsDialog::applySettings()
settings->save();
}
buttonBox()->button(QDialogButtonBox::Apply)->setEnabled(false);
+ m_unsavedChanges = false;
}
void DolphinSettingsDialog::restoreDefaults()
@@ -148,6 +152,35 @@ void DolphinSettingsDialog::restoreDefaults()
}
}
+void DolphinSettingsDialog::closeEvent(QCloseEvent* event)
+{
+ if (!m_unsavedChanges) {
+ event->accept();
+ return;
+ }
+
+ const auto response = KMessageBox::warningYesNoCancel(this,
+ i18n("You have unsaved changes. Do you want to apply the changes or discard them?"),
+ i18n("Warning"),
+ KStandardGuiItem::save(),
+ KStandardGuiItem::discard(),
+ KStandardGuiItem::cancel());
+ switch (response) {
+ case KMessageBox::Yes:
+ applySettings();
+ Q_FALLTHROUGH();
+ case KMessageBox::No:
+ event->accept();
+ break;
+ case KMessageBox::Cancel:
+ event->ignore();
+ break;
+ default:
+ break;
+ }
+}
+
+
SettingsPageBase *DolphinSettingsDialog::createTrashSettingsPage(QWidget *parent)
{
if (!KAuthorized::authorizeControlModule(QStringLiteral("kcmtrash.desktop"))) {
diff --git a/src/settings/dolphinsettingsdialog.h b/src/settings/dolphinsettingsdialog.h
index 4c8768fde..85871b12d 100644
--- a/src/settings/dolphinsettingsdialog.h
+++ b/src/settings/dolphinsettingsdialog.h
@@ -48,10 +48,14 @@ private slots:
void applySettings();
void restoreDefaults();
+protected:
+ void closeEvent(QCloseEvent* event) override;
+
private:
static SettingsPageBase *createTrashSettingsPage(QWidget *parent);
QList<SettingsPageBase*> m_pages;
+ bool m_unsavedChanges;
};
#endif
diff --git a/src/settings/general/previewssettingspage.cpp b/src/settings/general/previewssettingspage.cpp
index 187442ef9..30d71ff54 100644
--- a/src/settings/general/previewssettingspage.cpp
+++ b/src/settings/general/previewssettingspage.cpp
@@ -85,7 +85,7 @@ PreviewsSettingsPage::PreviewsSettingsPage(QWidget* parent) :
loadSettings();
connect(m_listView, &QListView::clicked, this, &PreviewsSettingsPage::changed);
- connect(m_remoteFileSizeBox, static_cast<void(QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &PreviewsSettingsPage::changed);
+ connect(m_remoteFileSizeBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &PreviewsSettingsPage::changed);
}
PreviewsSettingsPage::~PreviewsSettingsPage()
diff --git a/src/settings/kcm/kcmdolphingeneral.cpp b/src/settings/kcm/kcmdolphingeneral.cpp
index 0df806e41..032c2df4d 100644
--- a/src/settings/kcm/kcmdolphingeneral.cpp
+++ b/src/settings/kcm/kcmdolphingeneral.cpp
@@ -48,17 +48,17 @@ DolphinGeneralConfigModule::DolphinGeneralConfigModule(QWidget* parent, const QV
// initialize 'Behavior' tab
BehaviorSettingsPage* behaviorPage = new BehaviorSettingsPage(QUrl::fromLocalFile(QDir::homePath()), tabWidget);
tabWidget->addTab(behaviorPage, i18nc("@title:tab Behavior settings", "Behavior"));
- connect(behaviorPage, &BehaviorSettingsPage::changed, this, static_cast<void(DolphinGeneralConfigModule::*)()>(&DolphinGeneralConfigModule::changed));
+ connect(behaviorPage, &BehaviorSettingsPage::changed, this, QOverload<>::of(&DolphinGeneralConfigModule::changed));
// initialize 'Previews' tab
PreviewsSettingsPage* previewsPage = new PreviewsSettingsPage(tabWidget);
tabWidget->addTab(previewsPage, i18nc("@title:tab Previews settings", "Previews"));
- connect(previewsPage, &PreviewsSettingsPage::changed, this, static_cast<void(DolphinGeneralConfigModule::*)()>(&DolphinGeneralConfigModule::changed));
+ connect(previewsPage, &PreviewsSettingsPage::changed, this, QOverload<>::of(&DolphinGeneralConfigModule::changed));
// initialize 'Confirmations' tab
ConfirmationsSettingsPage* confirmationsPage = new ConfirmationsSettingsPage(tabWidget);
tabWidget->addTab(confirmationsPage, i18nc("@title:tab Confirmations settings", "Confirmations"));
- connect(confirmationsPage, &ConfirmationsSettingsPage::changed, this, static_cast<void(DolphinGeneralConfigModule::*)()>(&DolphinGeneralConfigModule::changed));
+ connect(confirmationsPage, &ConfirmationsSettingsPage::changed, this, QOverload<>::of(&DolphinGeneralConfigModule::changed));
m_pages.append(behaviorPage);
m_pages.append(previewsPage);
diff --git a/src/settings/kcm/kcmdolphinnavigation.cpp b/src/settings/kcm/kcmdolphinnavigation.cpp
index cc073247a..2cd9ff30c 100644
--- a/src/settings/kcm/kcmdolphinnavigation.cpp
+++ b/src/settings/kcm/kcmdolphinnavigation.cpp
@@ -40,7 +40,7 @@ DolphinNavigationConfigModule::DolphinNavigationConfigModule(QWidget* parent, co
topLayout->setContentsMargins(0, 0, 0, 0);
m_navigation = new NavigationSettingsPage(this);
- connect(m_navigation, &NavigationSettingsPage::changed, this, static_cast<void(DolphinNavigationConfigModule::*)()>(&DolphinNavigationConfigModule::changed));
+ connect(m_navigation, &NavigationSettingsPage::changed, this, QOverload<>::of(&DolphinNavigationConfigModule::changed));
topLayout->addWidget(m_navigation, 0, nullptr);
}
diff --git a/src/settings/kcm/kcmdolphinservices.cpp b/src/settings/kcm/kcmdolphinservices.cpp
index 91f4fd121..94494c184 100644
--- a/src/settings/kcm/kcmdolphinservices.cpp
+++ b/src/settings/kcm/kcmdolphinservices.cpp
@@ -40,7 +40,7 @@ DolphinServicesConfigModule::DolphinServicesConfigModule(QWidget* parent, const
topLayout->setContentsMargins(0, 0, 0, 0);
m_services = new ServicesSettingsPage(this);
- connect(m_services, &ServicesSettingsPage::changed, this, static_cast<void(DolphinServicesConfigModule::*)()>(&DolphinServicesConfigModule::changed));
+ connect(m_services, &ServicesSettingsPage::changed, this, QOverload<>::of(&DolphinServicesConfigModule::changed));
topLayout->addWidget(m_services, 0, nullptr);
}
diff --git a/src/settings/services/servicemenudeinstallation b/src/settings/services/servicemenudeinstallation
index 5e4234262..9e090e2cd 100755
--- a/src/settings/services/servicemenudeinstallation
+++ b/src/settings/services/servicemenudeinstallation
@@ -1,37 +1,72 @@
#!/usr/bin/env ruby
+
+# Copyright (C) 2009 Jonathan Schmidt-Dominé <[email protected]>
+# Copyright (C) 2019 Harald Sitter <[email protected]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
require 'fileutils'
-archive = ARGV[0]
-if archive[(archive.length - 8)..(archive.length)] == ".desktop"
- FileUtils.rm(`qtpaths --writable-path GenericDataLocation`.strip! + "/kservices5/ServiceMenus/" + File.basename(archive))
- exit(0)
+
+ARCHIVE = ARGV[0]
+
+# @param log_msg [String] error that gets logged to CLI
+def fail(log_msg: nil)
+ # FIXME: this is not translated...
+ msg = 'Dolphin service menu installation failed'
+ warn log_msg if log_msg
+ system('kdialog', '--passivepopup', msg, '15')
+ abort
end
-dir = archive + "-dir"
-# try: deinstall.sh
-# try: deinstall
-# try: installKDE4.sh
-# try: installKDE4
-# try: install.sh
-# try: install
-while true
- dd = Dir.new(dir)
- break if dd.count != 3
- odir = dir
- for entry in dd
- dir += "/" + entry if entry != "." && entry != ".."
- end
- if !File.directory? dir
- dir = odir
- break
- end
+
+if ARCHIVE.end_with?('.desktop')
+ data_location = `qtpaths --writable-path GenericDataLocation`.strip
+ unless $?.success?
+ fail(log_msg: "Could not get GenericDataLocation #{data_location}")
+ end
+ FileUtils.rm("#{data_location}/kservices5/ServiceMenus/#{File.basename(ARCHIVE)}")
+ exit(0)
end
-Dir.chdir(dir)
-def fail()
- system("kdialog --passivepopup \"Deinstallation failed\" 15")
- exit(-1)
+dir = "#{ARCHIVE}-dir"
+
+deinstaller = nil
+%w[deinstall.sh deinstall].find do |script|
+ deinstaller = Dir.glob("#{dir}/**/#{script}")[0]
end
-if !((File.exist?(file = "./deinstall.sh") || File.exist?(file = "./deinstall")) && system(file))
- fail() if !File.exist?(file = "./installKDE4.sh") && !File.exist?(file = "./installKDE4") && !File.exist?(file = "./install.sh") && !File.exist?(file = "./install")
-File.new(file).chmod(0700)
- fail() if !system(file + " --remove") && !system(file + " --delete") && !system(file + " --uninstall") && !system(file + " --deinstall")
+
+installer = nil
+%w[install-it.sh install-it installKDE4.sh installKDE4 install.sh install].find do |script|
+ installer = Dir.glob("#{dir}/**/#{script}")[0]
+end
+
+Dir.chdir(dir) do
+ deinstalled = false
+
+ [deinstaller, installer].uniq.compact.each { |f| File.chmod(0o700, f) }
+
+ if deinstaller
+ puts "[servicemenudeinstallation]: Trying to run deinstaller #{deinstaller}"
+ deinstalled = system(deinstaller)
+ elsif installer
+ puts "[servicemenudeinstallation]: Trying to run installer #{installer}"
+ %w[--remove --delete --uninstall --deinstall].any? do |arg|
+ deinstalled = system(installer, arg)
+ end
+ end
+
+ fail unless deinstalled
end
+
FileUtils.rm_r(dir)
diff --git a/src/settings/services/servicemenuinstallation b/src/settings/services/servicemenuinstallation
index 60b699bb6..e2d42bfbf 100755
--- a/src/settings/services/servicemenuinstallation
+++ b/src/settings/services/servicemenuinstallation
@@ -1,88 +1,136 @@
#!/usr/bin/env ruby
-require 'pathname'
+
+# Copyright (C) 2009 Jonathan Schmidt-Dominé <[email protected]>
+# Copyright (C) 2019 Harald Sitter <[email protected]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
require 'fileutils'
-archive = ARGV[0]
-$servicedir = `qtpaths --writable-path GenericDataLocation`.strip! + "/kservices5/ServiceMenus/"
-FileUtils.mkdir_p($servicedir) if !File.exist?($servicedir)
-if archive[(archive.length - 8)..(archive.length - 1)] == ".desktop"
- puts "Single-File Service-Menu"
- puts archive
- puts $servicedir
- FileUtils.cp(archive, $servicedir);
- exit(0)
+
+ARCHIVE_UNCOMPRESSORS = {
+ 'application/x-tar' => :"tar -xf %s -C %s",
+ 'application/tar' => :"tar -xf %s -C %s",
+ 'application/x-gzip' => :"tar -zxf %s -C %s",
+ 'application/gzip' => :"tar -zxf %s -C %s",
+ 'application/x-gzip-compressed-tar' => :"tar -zxf %s -C %s",
+ 'application/gzip-compressed-tar' => :"tar -zxf %s -C %s",
+ 'application/x-gzip-compressed' => :"tar -zxf %s -C %s",
+ 'application/gzip-compressed' => :"tar -zxf %s -C %s",
+ 'application/bzip' => :"tar -jxf %s -C %s",
+ 'application/bzip2' => :"tar -jxf %s -C %s",
+ 'application/x-bzip' => :"tar -jxf %s -C %s",
+ 'application/x-bzip2' => :"tar -jxf %s -C %s",
+ 'application/bzip-compressed' => :"tar -jxf %s -C %s",
+ 'application/bzip2-compressed' => :"tar -jxf %s -C %s",
+ 'application/x-bzip-compressed' => :"tar -jxf %s -C %s",
+ 'application/x-bzip2-compressed' => :"tar -jxf %s -C %s",
+ 'application/bzip-compressed-tar' => :"tar -jxf %s -C %s",
+ 'application/bzip2-compressed-tar' => :"tar -jxf %s -C %s",
+ 'application/x-bzip-compressed-tar' => :"tar -jxf %s -C %s",
+ 'application/x-bzip2-compressed-tar' => :"tar -jxf %s -C %s",
+ 'application/zip' => :"unzip %s -d %s",
+ 'application/x-zip' => :"unzip %s -d %s",
+ 'application/x-zip-compressed' => :"unzip %s -d %s",
+ 'multipart/x-zip' => :"unzip %s -d %s",
+ 'application/tgz' => :"tar -zxf %s -C %s",
+ 'application/x-compressed-gtar' => :"tar -zxf %s -C %s",
+ 'file/tgz' => :"tar -zxf %s -C %s",
+ 'multipart/x-tar-gz' => :"tar -zxf %s -C %s",
+ 'application/x-gunzip' => :"tar -zxf %s -C %s",
+ 'application/gzipped' => :"tar -zxf %s -C %s",
+ 'gzip/document' => :"tar -zxf %s -C %s",
+ 'application/x-bz2 ' => :"tar -jxf %s -C %s",
+ 'application/x-gtar' => :"tar -xf %s -C %s",
+ 'multipart/x-tar' => :"tar -xf %s -C %s"
+}
+
+ARCHIVE = ARGV[0]
+
+# @param log_msg [String] error that gets logged to CLI
+def fail(log_msg: nil)
+ # FIXME: this is not translated...
+ msg = 'Dolphin service menu installation failed'
+ warn log_msg if log_msg
+ system('kdialog', '--passivepopup', msg, '15')
+ abort
end
-def mimeType(filename)
- IO.popen("file --mime-type -b " + filename).gets().strip!()
+
+def mime_type(filename)
+ ret = `xdg-mime query filetype #{filename}`.strip
+ return ret if $?.success?
+
+ warn 'Failed to xdg-mime'
+ fail(log_msg: "Failed to xdg-mime #{filename}: #{ret}")
end
-$archivetypes = { "application/x-tar" => :"tar -xf %s -C %s",
- "application/tar" => :"tar -xf %s -C %s",
- "application/x-gzip" => :"tar -zxf %s -C %s",
- "application/gzip" => :"tar -zxf %s -C %s",
- "application/x-gzip-compressed-tar" => :"tar -zxf %s -C %s",
- "application/gzip-compressed-tar" => :"tar -zxf %s -C %s",
- "application/x-gzip-compressed" => :"tar -zxf %s -C %s",
- "application/gzip-compressed" => :"tar -zxf %s -C %s",
- "application/bzip" => :"tar -jxf %s -C %s",
- "application/bzip2" => :"tar -jxf %s -C %s",
- "application/x-bzip" => :"tar -jxf %s -C %s",
- "application/x-bzip2" => :"tar -jxf %s -C %s",
- "application/bzip-compressed" => :"tar -jxf %s -C %s",
- "application/bzip2-compressed" => :"tar -jxf %s -C %s",
- "application/x-bzip-compressed" => :"tar -jxf %s -C %s",
- "application/x-bzip2-compressed" => :"tar -jxf %s -C %s",
- "application/bzip-compressed-tar" => :"tar -jxf %s -C %s",
- "application/bzip2-compressed-tar" => :"tar -jxf %s -C %s",
- "application/x-bzip-compressed-tar" => :"tar -jxf %s -C %s",
- "application/x-bzip2-compressed-tar" => :"tar -jxf %s -C %s",
- "application/zip" => :"unzip %s -d %s",
- "application/x-zip" => :"unzip %s -d %s",
- "application/x-zip-compressed" => :"unzip %s -d %s",
- "multipart/x-zip" => :"unzip %s -d %s",
- "application/tgz" => :"tar -zxf %s -C %s",
- "application/x-compressed-gtar" => :"tar -zxf %s -C %s",
- "file/tgz" => :"tar -zxf %s -C %s",
- "multipart/x-tar-gz" => :"tar -zxf %s -C %s",
- "application/x-gunzip" => :"tar -zxf %s -C %s",
- "application/gzipped" => :"tar -zxf %s -C %s",
- "gzip/document" => :"tar -zxf %s -C %s",
- "application/x-bz2 " => :"tar -jxf %s -C %s",
- "application/x-gtar" => :"tar -xf %s -C %s",
- "multipart/x-tar" => :"tar -xf %s -C %s"
-}
+
def uncompress(filename, output)
- system(sprintf($archivetypes[mimeType(filename)].to_s, filename, output))
+ uncompressor = ARCHIVE_UNCOMPRESSORS.fetch(mime_type(filename)).to_s
+ system(format(uncompressor, filename, output))
+rescue KeyError => e
+ # If a mimetype doesn't have an uncompressor mapped we'll get a keyerror.
+ # we'll log the error but visually report the failure.
+ fail(log_msg: "Unmapped compression format #{filename}; #{e.message}")
end
-dir = archive + "-dir"
-if File.exist?(dir)
- FileUtils.rm_r(dir)
+
+data_location = `qtpaths --writable-path GenericDataLocation`.strip
+unless $?.success?
+ fail(log_msg: "Could not get GenericDataLocation #{data_location}")
end
+servicedir = "#{data_location}/kservices5/ServiceMenus/"
+
+FileUtils.mkdir_p(servicedir) unless File.exist?(servicedir)
+if ARCHIVE.end_with?('.desktop')
+ puts 'Single-File Service-Menu'
+ puts ARCHIVE
+ puts servicedir
+ FileUtils.cp(ARCHIVE, servicedir)
+ exit
+end
+
+dir = "#{ARCHIVE}-dir"
+
+FileUtils.rm_r(dir) if File.exist?(dir)
FileUtils.mkdir(dir)
-exit(-1) if !uncompress(archive, dir)
-# try: install-it.sh
-# try: install-it
-# try: installKDE4.sh
-# try: installKDE4
-# try: install.sh
-# try: install
-while true
- dd = Dir.new(dir)
- break if dd.count != 3
- odir = dir
- for entry in dd
- dir += "/" + entry if entry != "." && entry != ".."
- end
- if !File.directory? dir
- dir = odir
- break
- end
+
+fail(log_msg: 'uncompress failed') unless uncompress(ARCHIVE, dir)
+
+install_it = nil
+%w[install-it.sh install-it].find do |script|
+ install_it = Dir.glob("#{dir}/**/#{script}")[0]
+end
+
+installer = nil
+%w[installKDE4.sh installKDE4 install.sh install].find do |script|
+ installer = Dir.glob("#{dir}/**/#{script}")[0]
end
-Dir.chdir(dir)
-def fail()
- system("kdialog --passivepopup \"Installation failed\" 15")
- exit(-1)
+
+Dir.chdir(dir) do
+ installed = false
+
+ [install_it, installer].uniq.compact.each { |f| File.chmod(0o700, f) }
+
+ if install_it
+ puts "[servicemenuinstallation]: Trying to run install_it #{install_it}"
+ installed = system(install_it)
+ elsif installer
+ puts "[servicemenuinstallation]: Trying to run installer #{installer}"
+ %w[--local --local-install --install].any? do |arg|
+ installed = system(installer, arg)
+ end
+ end
+
+ fail unless installed
end
-if !((File.exist?(file = "./install-it.sh") || File.exist?(file = "./install-it")) && system(file))
- fail() if !File.exist?(file = "./installKDE4.sh") && !File.exist?(file = "./installKDE4") && !File.exist?(file = "./install.sh") && !File.exist?(file = "./install")
- File.new(file).chmod(0700)
- fail() if !system(file + " --local") && !system(file + "--local-install") && !system(file + " --install")
-end
diff --git a/src/settings/services/test/service_menu_deinstallation_test.rb b/src/settings/services/test/service_menu_deinstallation_test.rb
new file mode 100644
index 000000000..2b3514a65
--- /dev/null
+++ b/src/settings/services/test/service_menu_deinstallation_test.rb
@@ -0,0 +1,121 @@
+#!/usr/bin/env ruby
+
+# Copyright (C) 2019 Harald Sitter <[email protected]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+require_relative 'test_helper'
+
+require 'tmpdir'
+
+class ServiceMenuDeinstallationTest < Test::Unit::TestCase
+ def setup
+ @tmpdir = Dir.mktmpdir("dolphintest-#{self.class.to_s.tr(':', '_')}")
+ @pwdir = Dir.pwd
+ Dir.chdir(@tmpdir)
+
+ ENV['XDG_DATA_HOME'] = File.join(@tmpdir, 'data')
+ end
+
+ def teardown
+ Dir.chdir(@pwdir)
+ FileUtils.rm_rf(@tmpdir)
+
+ ENV.delete('XDG_DATA_HOME')
+ end
+
+ def test_run_deinstall
+ service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
+ archive_base = "#{service_dir}/foo.zip"
+ archive_dir = "#{archive_base}-dir/foo-1.1/"
+ FileUtils.mkpath(archive_dir)
+ File.write("#{archive_dir}/deinstall.sh", <<-DEINSTALL_SH)
+#!/bin/sh
+touch #{@tmpdir}/deinstall.sh-run
+ DEINSTALL_SH
+ File.write("#{archive_dir}/install.sh", <<-INSTALL_SH)
+#!/bin/sh
+touch #{@tmpdir}/install.sh-run
+ INSTALL_SH
+
+ assert(covered_system('servicemenudeinstallation', archive_base))
+
+ # deinstaller should be run
+ # installer should not be run
+ # archive_dir should have been correctly removed
+
+ assert_path_exist('deinstall.sh-run')
+ assert_path_not_exist('install.sh-run')
+ assert_path_not_exist(archive_dir)
+ end
+
+ def test_run_install_with_arg
+ service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
+ archive_base = "#{service_dir}/foo.zip"
+ archive_dir = "#{archive_base}-dir/foo-1.1/"
+ FileUtils.mkpath(archive_dir)
+
+ File.write("#{archive_dir}/install.sh", <<-INSTALL_SH)
+#!/bin/sh
+if [ "$@" = "--uninstall" ]; then
+ touch #{@tmpdir}/install.sh-run
+ exit 0
+fi
+exit 1
+ INSTALL_SH
+
+ assert(covered_system('servicemenudeinstallation', archive_base))
+
+ assert_path_not_exist('deinstall.sh-run')
+ assert_path_exist('install.sh-run')
+ assert_path_not_exist(archive_dir)
+ end
+
+ # no scripts in sight
+ def test_run_fail
+ service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
+ archive_base = "#{service_dir}/foo.zip"
+ archive_dir = "#{archive_base}-dir/foo-1.1/"
+ FileUtils.mkpath(archive_dir)
+
+ refute(covered_system('servicemenudeinstallation', archive_base))
+
+ # I am unsure if deinstallation really should keep the files around. But
+ # that's how it behaved originally so it's supposedly intentional
+ # - sitter, 2019
+ assert_path_exist(archive_dir)
+ end
+
+ # For desktop files things are a bit special. There is one in .local/share/servicemenu-download
+ # and another in the actual ServiceMenus dir. The latter gets removed by the
+ # script, the former by KNS.
+ def test_run_desktop
+ service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
+ downloaded_file = "#{service_dir}/foo.desktop"
+ FileUtils.mkpath(service_dir)
+ FileUtils.touch(downloaded_file)
+
+ menu_dir = "#{ENV['XDG_DATA_HOME']}/kservices5/ServiceMenus/"
+ installed_file = "#{menu_dir}/foo.desktop"
+ FileUtils.mkpath(menu_dir)
+ FileUtils.touch(installed_file)
+
+ assert(covered_system('servicemenudeinstallation', downloaded_file))
+
+ assert_path_exist(downloaded_file)
+ assert_path_not_exist(installed_file)
+ end
+end
diff --git a/src/settings/services/test/service_menu_installation_test.rb b/src/settings/services/test/service_menu_installation_test.rb
new file mode 100644
index 000000000..43f594969
--- /dev/null
+++ b/src/settings/services/test/service_menu_installation_test.rb
@@ -0,0 +1,119 @@
+#!/usr/bin/env ruby
+
+# Copyright (C) 2019 Harald Sitter <[email protected]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+require_relative 'test_helper'
+
+require 'tmpdir'
+
+class ServiceMenuInstallationTest < Test::Unit::TestCase
+ def setup
+ @tmpdir = Dir.mktmpdir("dolphintest-#{self.class.to_s.tr(':', '_')}")
+ @pwdir = Dir.pwd
+ Dir.chdir(@tmpdir)
+
+ ENV['XDG_DATA_HOME'] = File.join(@tmpdir, 'data')
+ end
+
+ def teardown
+ Dir.chdir(@pwdir)
+ FileUtils.rm_rf(@tmpdir)
+
+ ENV.delete('XDG_DATA_HOME')
+ end
+
+ def test_run_install
+ service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
+ FileUtils.mkpath(service_dir)
+ archive = "#{service_dir}/foo.tar"
+
+ archive_dir = 'foo' # relative so tar cf is relative without fuzz
+ FileUtils.mkpath(archive_dir)
+ File.write("#{archive_dir}/install-it.sh", <<-INSTALL_IT_SH)
+#!/bin/sh
+touch #{@tmpdir}/install-it.sh-run
+INSTALL_IT_SH
+ File.write("#{archive_dir}/install.sh", <<-INSTALL_SH)
+#!/bin/sh
+touch #{@tmpdir}/install.sh-run
+ INSTALL_SH
+ assert(system('tar', '-cf', archive, archive_dir))
+
+ assert(covered_system('servicemenuinstallation', archive))
+
+ tar_dir = "#{service_dir}/foo.tar-dir"
+ tar_extract_dir = "#{service_dir}/foo.tar-dir/foo"
+ assert_path_exist(tar_dir)
+ assert_path_exist(tar_extract_dir)
+ assert_path_exist("#{tar_extract_dir}/install-it.sh")
+ assert_path_exist("#{tar_extract_dir}/install.sh")
+ end
+
+ def test_run_install_with_arg
+ service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
+ FileUtils.mkpath(service_dir)
+ archive = "#{service_dir}/foo.tar"
+
+ archive_dir = 'foo' # relative so tar cf is relative without fuzz
+ FileUtils.mkpath(archive_dir)
+ File.write("#{archive_dir}/install.sh", <<-INSTALL_SH)
+#!/bin/sh
+if [ "$@" = "--install" ]; then
+ touch #{@tmpdir}/install.sh-run
+ exit 0
+fi
+exit 1
+ INSTALL_SH
+ assert(system('tar', '-cf', archive, archive_dir))
+
+ assert(covered_system('servicemenuinstallation', archive))
+
+ tar_dir = "#{service_dir}/foo.tar-dir"
+ tar_extract_dir = "#{service_dir}/foo.tar-dir/foo"
+ assert_path_exist(tar_dir)
+ assert_path_exist(tar_extract_dir)
+ assert_path_not_exist("#{tar_extract_dir}/install-it.sh")
+ assert_path_exist("#{tar_extract_dir}/install.sh")
+ end
+
+ def test_run_fail
+ service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
+ FileUtils.mkpath(service_dir)
+ archive = "#{service_dir}/foo.tar"
+
+ archive_dir = 'foo' # relative so tar cf is relative without fuzz
+ FileUtils.mkpath(archive_dir)
+ assert(system('tar', '-cf', archive, archive_dir))
+
+ refute(covered_system('servicemenuinstallation', archive))
+ end
+
+ def test_run_desktop
+ service_dir = File.join(Dir.pwd, 'share/servicemenu-download')
+ downloaded_file = "#{service_dir}/foo.desktop"
+ FileUtils.mkpath(service_dir)
+ FileUtils.touch(downloaded_file)
+
+ installed_file = "#{ENV['XDG_DATA_HOME']}/kservices5/ServiceMenus/foo.desktop"
+
+ assert(covered_system('servicemenuinstallation', downloaded_file))
+
+ assert_path_exist(downloaded_file)
+ assert_path_exist(installed_file)
+ end
+end
diff --git a/src/settings/services/test/test_helper.rb b/src/settings/services/test/test_helper.rb
new file mode 100644
index 000000000..9da5cf3c3
--- /dev/null
+++ b/src/settings/services/test/test_helper.rb
@@ -0,0 +1,100 @@
+# Copyright (C) 2019 Harald Sitter <[email protected]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+
+GLOBAL_COVERAGE_ROOT = File.dirname(__dir__) # ../
+
+# Simplecov is a bit meh and expects src and coverage to be under the
+# same root. Since we get run through cmake that assumption absolutely
+# doesn't hold true, so we'll need to figure out the coverage_dir relative
+# to the root and the root must always be the source :/
+# The relativity only works because internally the path gets expanded, this
+# isn't fully reliable, but oh well...
+# https://github.com/colszowka/simplecov/issues/716
+GLOBAL_COVERAGE_DIR = begin
+ require 'pathname'
+ src_path = Pathname.new(GLOBAL_COVERAGE_ROOT)
+ coverage_path = Pathname.new(File.join(Dir.pwd, 'coverage'))
+ coverage_path.relative_path_from(src_path).to_s
+end
+
+begin
+ require 'simplecov'
+
+ SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter.new(
+ [
+ SimpleCov::Formatter::HTMLFormatter
+ ]
+ )
+
+ SimpleCov.start do
+ root GLOBAL_COVERAGE_ROOT
+ coverage_dir GLOBAL_COVERAGE_DIR
+ end
+rescue LoadError
+ warn 'SimpleCov not loaded'
+end
+
+# FIXME: add coverage report for jenkins?
+
+$LOAD_PATH.unshift(File.absolute_path('../', __dir__)) # ../
+
+def __test_method_name__
+ return @method_name if defined?(:@method_name)
+ index = 0
+ caller = ''
+ until caller.start_with?('test_')
+ caller = caller_locations(index, 1)[0].label
+ index += 1
+ end
+ caller
+end
+
+# system() variant which sets up merge-coverage. simplecov supports merging
+# of multiple coverage sets. we use this to get coverage metrics on the
+# binaries without having to refactor the script into runnable classes.
+def covered_system(cmd, *argv)
+ pid = fork do
+ Kernel.module_exec do
+ alias_method(:real_system, :system)
+ define_method(:system) do |*args|
+ return true if args.include?('kdialog') # disable kdialog call
+ real_system(*args)
+ end
+ end
+
+ begin
+ require 'simplecov'
+ SimpleCov.start do
+ root GLOBAL_COVERAGE_ROOT
+ coverage_dir GLOBAL_COVERAGE_DIR
+ command_name "#{cmd}_#{__test_method_name__}"
+ end
+ rescue LoadError
+ warn 'SimpleCov not loaded'
+ end
+
+ ARGV.replace(argv)
+ load "#{__dir__}/../#{cmd}"
+ puts 'all good, fork ending!'
+ exit 0
+ end
+ waitedpid, status = Process.waitpid2(pid)
+ assert_equal(pid, waitedpid)
+ status.success? # behave like system and return the success only
+end
+
+require 'test/unit'
diff --git a/src/settings/services/test/test_run.rb b/src/settings/services/test/test_run.rb
new file mode 100755
index 000000000..b2149bbe0
--- /dev/null
+++ b/src/settings/services/test/test_run.rb
@@ -0,0 +1,24 @@
+#!/usr/bin/env ruby
+
+# Copyright (C) 2019 Harald Sitter <[email protected]>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the
+# Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+# This is a fancy wrapper around test_helper to prevent the collector from
+# loading the helper twice as it would occur if we ran the helper directly.
+
+require_relative 'test_helper'
+
+Test::Unit::AutoRunner.run(true, File.absolute_path(__dir__))
diff --git a/src/settings/trash/trashsettingspage.cpp b/src/settings/trash/trashsettingspage.cpp
index a9b8c734c..dd6038fb6 100644
--- a/src/settings/trash/trashsettingspage.cpp
+++ b/src/settings/trash/trashsettingspage.cpp
@@ -33,7 +33,7 @@ TrashSettingsPage::TrashSettingsPage(QWidget* parent) :
loadSettings();
- connect(m_proxy, static_cast<void(KCModuleProxy::*)(bool)>(&KCModuleProxy::changed), this, &TrashSettingsPage::changed);
+ connect(m_proxy, QOverload<bool>::of(&KCModuleProxy::changed), this, &TrashSettingsPage::changed);
}
TrashSettingsPage::~TrashSettingsPage()
diff --git a/src/settings/viewmodes/dolphinfontrequester.cpp b/src/settings/viewmodes/dolphinfontrequester.cpp
index e7b4589e3..09aacc3df 100644
--- a/src/settings/viewmodes/dolphinfontrequester.cpp
+++ b/src/settings/viewmodes/dolphinfontrequester.cpp
@@ -40,7 +40,7 @@ DolphinFontRequester::DolphinFontRequester(QWidget* parent) :
m_modeCombo = new QComboBox(this);
m_modeCombo->addItem(i18nc("@item:inlistbox Font", "System Font"));
m_modeCombo->addItem(i18nc("@item:inlistbox Font", "Custom Font"));
- connect(m_modeCombo, static_cast<void(QComboBox::*)(int)>(&QComboBox::activated),
+ connect(m_modeCombo, QOverload<int>::of(&QComboBox::activated),
this, &DolphinFontRequester::changeMode);
m_chooseFontButton = new QPushButton(i18nc("@action:button Choose font", "Choose..."), this);
diff --git a/src/settings/viewmodes/viewsettingstab.cpp b/src/settings/viewmodes/viewsettingstab.cpp
index 925a982d9..06b0b8cf5 100644
--- a/src/settings/viewmodes/viewsettingstab.cpp
+++ b/src/settings/viewmodes/viewsettingstab.cpp
@@ -120,11 +120,11 @@ ViewSettingsTab::ViewSettingsTab(Mode mode, QWidget* parent) :
switch (m_mode) {
case IconsMode:
- connect(m_widthBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ViewSettingsTab::changed);
- connect(m_maxLinesBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ViewSettingsTab::changed);
+ connect(m_widthBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ViewSettingsTab::changed);
+ connect(m_maxLinesBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ViewSettingsTab::changed);
break;
case CompactMode:
- connect(m_widthBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &ViewSettingsTab::changed);
+ connect(m_widthBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ViewSettingsTab::changed);
break;
case DetailsMode:
connect(m_expandableFolders, &QCheckBox::toggled, this, &ViewSettingsTab::changed);
diff --git a/src/settings/viewpropertiesdialog.cpp b/src/settings/viewpropertiesdialog.cpp
index 3ccf9a342..a1f9718fe 100644
--- a/src/settings/viewpropertiesdialog.cpp
+++ b/src/settings/viewpropertiesdialog.cpp
@@ -163,11 +163,11 @@ ViewPropertiesDialog::ViewPropertiesDialog(DolphinView* dolphinView) :
layout->addRow(QString(), m_showInGroups);
layout->addRow(QString(), m_showHiddenFiles);
- connect(m_viewMode, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_viewMode, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ViewPropertiesDialog::slotViewModeChanged);
- connect(m_sorting, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_sorting, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ViewPropertiesDialog::slotSortingChanged);
- connect(m_sortOrder, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged),
+ connect(m_sortOrder, QOverload<int>::of(&QComboBox::currentIndexChanged),
this, &ViewPropertiesDialog::slotSortOrderChanged);
connect(m_sortFoldersFirst, &QCheckBox::clicked,
this, &ViewPropertiesDialog::slotSortFoldersFirstChanged);
diff --git a/src/settings/viewpropsprogressinfo.cpp b/src/settings/viewpropsprogressinfo.cpp
index a6c0c6d58..44b7a4c8c 100644
--- a/src/settings/viewpropsprogressinfo.cpp
+++ b/src/settings/viewpropsprogressinfo.cpp
@@ -53,7 +53,7 @@ ViewPropsProgressInfo::ViewPropsProgressInfo(QWidget* parent,
m_viewProps = new ViewProperties(dir);
m_viewProps->setDirProperties(viewProps);
- // the view properties are stored by the ViewPropsApplierJob, so prevent
+ // the view properties are stored by the ApplyViewPropsJob, so prevent
// that the view properties are saved twice:
m_viewProps->setAutoSaveEnabled(false);
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 07e4257a0..8ef20cb83 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -3,6 +3,18 @@ set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} )
find_package(Qt5Test CONFIG REQUIRED)
include(ECMAddTests)
+include(FindGem)
+
+find_gem(test-unit REQUIRED)
+set_package_properties(Gem:test-unit PROPERTIES
+ DESCRIPTION "Ruby gem 'test-unit' required for testing of servicemenu helpers.")
+
+if(BUILD_COVERAGE)
+ find_gem(simplecov)
+ set_package_properties(Gem:simplecov PROPERTIES
+ DESCRIPTION "Ruby gem 'simplecov' used for coverage statistics.")
+endif()
+
# KItemSetTest
ecm_add_test(kitemsettest.cpp LINK_LIBRARIES dolphinprivate Qt5::Test)
@@ -69,3 +81,5 @@ ecm_add_test(placesitemmodeltest.cpp
TEST_NAME placesitemmodeltest
LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test)
+add_test(NAME servicemenutest
+ COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../settings/services/test/test_run.rb)
diff --git a/src/tests/kfileitemmodeltest.cpp b/src/tests/kfileitemmodeltest.cpp
index 2f258d17d..c53979970 100644
--- a/src/tests/kfileitemmodeltest.cpp
+++ b/src/tests/kfileitemmodeltest.cpp
@@ -1553,22 +1553,22 @@ void KFileItemModelTest::testChangeSortRoleWhileFiltering()
KIO::UDSEntry entry[3];
- entry[0].insert(KIO::UDSEntry::UDS_NAME, "a.txt");
- entry[0].insert(KIO::UDSEntry::UDS_USER, "user-b");
+ entry[0].fastInsert(KIO::UDSEntry::UDS_NAME, "a.txt");
+ entry[0].fastInsert(KIO::UDSEntry::UDS_USER, "user-b");
- entry[1].insert(KIO::UDSEntry::UDS_NAME, "b.txt");
- entry[1].insert(KIO::UDSEntry::UDS_USER, "user-c");
+ entry[1].fastInsert(KIO::UDSEntry::UDS_NAME, "b.txt");
+ entry[1].fastInsert(KIO::UDSEntry::UDS_USER, "user-c");
- entry[2].insert(KIO::UDSEntry::UDS_NAME, "c.txt");
- entry[2].insert(KIO::UDSEntry::UDS_USER, "user-a");
+ entry[2].fastInsert(KIO::UDSEntry::UDS_NAME, "c.txt");
+ entry[2].fastInsert(KIO::UDSEntry::UDS_USER, "user-a");
for (int i = 0; i < 3; ++i) {
- entry[i].insert(KIO::UDSEntry::UDS_FILE_TYPE, 0100000); // S_IFREG might not be defined on non-Unix platforms.
- entry[i].insert(KIO::UDSEntry::UDS_ACCESS, 07777);
- entry[i].insert(KIO::UDSEntry::UDS_SIZE, 0);
- entry[i].insert(KIO::UDSEntry::UDS_MODIFICATION_TIME, 0);
- entry[i].insert(KIO::UDSEntry::UDS_GROUP, "group");
- entry[i].insert(KIO::UDSEntry::UDS_ACCESS_TIME, 0);
+ entry[i].fastInsert(KIO::UDSEntry::UDS_FILE_TYPE, 0100000); // S_IFREG might not be defined on non-Unix platforms.
+ entry[i].fastInsert(KIO::UDSEntry::UDS_ACCESS, 07777);
+ entry[i].fastInsert(KIO::UDSEntry::UDS_SIZE, 0);
+ entry[i].fastInsert(KIO::UDSEntry::UDS_MODIFICATION_TIME, 0);
+ entry[i].fastInsert(KIO::UDSEntry::UDS_GROUP, "group");
+ entry[i].fastInsert(KIO::UDSEntry::UDS_ACCESS_TIME, 0);
items.append(KFileItem(entry[i], m_testDir->url(), false, true));
}
diff --git a/src/tests/placesitemmodeltest.cpp b/src/tests/placesitemmodeltest.cpp
index 7f0d498a7..78c5eabfe 100644
--- a/src/tests/placesitemmodeltest.cpp
+++ b/src/tests/placesitemmodeltest.cpp
@@ -292,12 +292,12 @@ void PlacesItemModelTest::testModelSort()
void PlacesItemModelTest::testGroups()
{
const auto groups = m_model->groups();
- int expectedGroupSize = 3;
+ int expectedRemoteIndex = 3;
if (m_hasDesktopFolder) {
- expectedGroupSize++;
+ expectedRemoteIndex++;
}
if (m_hasDownloadsFolder) {
- expectedGroupSize++;
+ expectedRemoteIndex++;
}
QCOMPARE(groups.size(), 6);
@@ -305,19 +305,19 @@ void PlacesItemModelTest::testGroups()
QCOMPARE(groups.at(0).first, 0);
QCOMPARE(groups.at(0).second.toString(), QStringLiteral("Places"));
- QCOMPARE(groups.at(1).first, expectedGroupSize);
+ QCOMPARE(groups.at(1).first, expectedRemoteIndex);
QCOMPARE(groups.at(1).second.toString(), QStringLiteral("Remote"));
- QCOMPARE(groups.at(2).first, expectedGroupSize + 2);
+ QCOMPARE(groups.at(2).first, expectedRemoteIndex + 2);
QCOMPARE(groups.at(2).second.toString(), QStringLiteral("Recently Saved"));
- QCOMPARE(groups.at(3).first, expectedGroupSize + 4);
+ QCOMPARE(groups.at(3).first, expectedRemoteIndex + 4);
QCOMPARE(groups.at(3).second.toString(), QStringLiteral("Search For"));
- QCOMPARE(groups.at(4).first, expectedGroupSize + 8);
+ QCOMPARE(groups.at(4).first, expectedRemoteIndex + 8);
QCOMPARE(groups.at(4).second.toString(), QStringLiteral("Devices"));
- QCOMPARE(groups.at(5).first, expectedGroupSize + 9);
+ QCOMPARE(groups.at(5).first, expectedRemoteIndex + 9);
QCOMPARE(groups.at(5).second.toString(), QStringLiteral("Removable Devices"));
}
diff --git a/src/trash/dolphintrash.cpp b/src/trash/dolphintrash.cpp
index e4a2d947c..957091e54 100644
--- a/src/trash/dolphintrash.cpp
+++ b/src/trash/dolphintrash.cpp
@@ -40,7 +40,7 @@ Trash::Trash()
bool isTrashEmpty = m_trashDirLister->items().isEmpty();
emit emptinessChanged(isTrashEmpty);
};
- connect(m_trashDirLister, static_cast<void(KDirLister::*)()>(&KDirLister::completed), this, trashDirContentChanged);
+ connect(m_trashDirLister, QOverload<>::of(&KCoreDirLister::completed), this, trashDirContentChanged);
connect(m_trashDirLister, &KDirLister::itemsDeleted, this, trashDirContentChanged);
m_trashDirLister->openUrl(QUrl(QStringLiteral("trash:/")));
}
diff --git a/src/views/dolphinviewactionhandler.cpp b/src/views/dolphinviewactionhandler.cpp
index f4fbddf60..6e5468cd5 100644
--- a/src/views/dolphinviewactionhandler.cpp
+++ b/src/views/dolphinviewactionhandler.cpp
@@ -144,7 +144,7 @@ void DolphinViewActionHandler::createActions()
viewModeActions->addAction(compactAction);
viewModeActions->addAction(detailsAction);
viewModeActions->setToolBarMode(KSelectAction::MenuMode);
- connect(viewModeActions, static_cast<void(KSelectAction::*)(QAction*)>(&KSelectAction::triggered), this, &DolphinViewActionHandler::slotViewModeActionTriggered);
+ connect(viewModeActions, QOverload<QAction*>::of(&KSelectAction::triggered), this, &DolphinViewActionHandler::slotViewModeActionTriggered);
KStandardAction::zoomIn(this,
&DolphinViewActionHandler::zoomIn,
diff --git a/src/views/tooltips/tooltipmanager.cpp b/src/views/tooltips/tooltipmanager.cpp
index 2990f4249..aae97458c 100644
--- a/src/views/tooltips/tooltipmanager.cpp
+++ b/src/views/tooltips/tooltipmanager.cpp
@@ -64,7 +64,7 @@ ToolTipManager::ToolTipManager(QWidget* parent) :
m_showToolTipTimer = new QTimer(this);
m_showToolTipTimer->setSingleShot(true);
m_showToolTipTimer->setInterval(500);
- connect(m_showToolTipTimer, &QTimer::timeout, this, static_cast<void(ToolTipManager::*)()>(&ToolTipManager::showToolTip));
+ connect(m_showToolTipTimer, &QTimer::timeout, this, QOverload<>::of(&ToolTipManager::showToolTip));
m_contentRetrievalTimer = new QTimer(this);
m_contentRetrievalTimer->setSingleShot(true);