┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.kde-ci.yml2
-rw-r--r--CMakeLists.txt25
-rw-r--r--src/dolphincontextmenu.cpp4
-rw-r--r--src/dolphinmainwindow.cpp38
-rw-r--r--src/dolphinmainwindow.h10
-rw-r--r--src/dolphinnavigatorswidgetaction.h4
-rw-r--r--src/dolphinpart.cpp8
-rw-r--r--src/dolphintabpage.h2
-rw-r--r--src/dolphinurlnavigatorscontroller.h2
-rw-r--r--src/dolphinviewcontainer.cpp47
-rw-r--r--src/dolphinviewcontainer.h19
-rw-r--r--src/kitemviews/kfileitemmodel.cpp168
-rw-r--r--src/kitemviews/kfileitemmodel.h12
-rw-r--r--src/kitemviews/kfileitemmodelrolesupdater.cpp23
-rw-r--r--src/kitemviews/kitemlistcontroller.cpp10
-rw-r--r--src/kitemviews/kitemlistcontroller.h2
-rw-r--r--src/kitemviews/kitemlistview.cpp4
-rw-r--r--src/kitemviews/kitemlistview.h4
-rw-r--r--src/kitemviews/private/kitemlistheaderwidget.cpp2
-rw-r--r--src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp2
-rwxr-xr-xsrc/org.kde.dolphin.desktop18
-rw-r--r--src/panels/folders/folderspanel.cpp22
-rw-r--r--src/panels/folders/folderspanel.h3
-rw-r--r--src/panels/information/informationpanelcontent.cpp6
-rw-r--r--src/panels/information/informationpanelcontent.h2
-rw-r--r--src/panels/places/placesitem.cpp2
-rw-r--r--src/panels/places/placespanel.cpp74
-rw-r--r--src/panels/places/placespanel.h10
-rw-r--r--src/panels/terminal/terminalpanel.cpp4
-rw-r--r--src/search/dolphinfacetswidget.cpp2
-rw-r--r--src/settings/contextmenu/contextmenusettingspage.cpp6
-rw-r--r--src/settings/dolphinsettingsdialog.cpp2
-rw-r--r--src/settings/general/configurepreviewplugindialog.cpp4
-rw-r--r--src/settings/general/previewssettingspage.cpp4
-rw-r--r--src/settings/trash/trashsettingspage.cpp4
-rw-r--r--src/settings/viewmodes/dolphinfontrequester.cpp2
-rw-r--r--src/settings/viewmodes/viewsettingstab.cpp10
-rw-r--r--src/settings/viewpropertiesdialog.cpp6
-rw-r--r--src/tests/kfileitemmodeltest.cpp222
-rw-r--r--src/tests/testdir.cpp2
-rw-r--r--src/trash/dolphintrash.cpp2
-rw-r--r--src/views/dolphinremoteencoding.cpp3
-rw-r--r--src/views/dolphinview.cpp30
-rw-r--r--src/views/dolphinview.h18
-rw-r--r--src/views/dolphinviewactionhandler.cpp2
-rw-r--r--src/views/tooltips/dolphinfilemetadatawidget.cpp2
-rw-r--r--src/views/versioncontrol/kversioncontrolplugin.h5
-rw-r--r--src/views/versioncontrol/versioncontrolobserver.cpp11
-rw-r--r--src/views/versioncontrol/versioncontrolobserver.h2
49 files changed, 698 insertions, 170 deletions
diff --git a/.kde-ci.yml b/.kde-ci.yml
index bcf24537f..3f3b7f8bc 100644
--- a/.kde-ci.yml
+++ b/.kde-ci.yml
@@ -26,6 +26,6 @@ Dependencies:
'frameworks/baloo': '@stable'
'frameworks/kwindowsystem': '@stable'
'frameworks/kfilemetadata': '@stable'
- 'libraries/baloo-widgets': '@stable'
+ 'libraries/baloo-widgets': '@same'
'libraries/kuserfeedback': '@stable'
'libraries/phonon': '@stable'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 330e9b555..92b311bfc 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -1,22 +1,23 @@
cmake_minimum_required(VERSION 3.16)
# KDE Application Version, managed by release script
-set (RELEASE_SERVICE_VERSION_MAJOR "21")
-set (RELEASE_SERVICE_VERSION_MINOR "12")
-set (RELEASE_SERVICE_VERSION_MICRO "0")
+set (RELEASE_SERVICE_VERSION_MAJOR "22")
+set (RELEASE_SERVICE_VERSION_MINOR "03")
+set (RELEASE_SERVICE_VERSION_MICRO "70")
set (RELEASE_SERVICE_VERSION "${RELEASE_SERVICE_VERSION_MAJOR}.${RELEASE_SERVICE_VERSION_MINOR}.${RELEASE_SERVICE_VERSION_MICRO}")
project(Dolphin VERSION ${RELEASE_SERVICE_VERSION})
set(QT_MIN_VERSION "5.15.0")
-set(KF5_MIN_VERSION "5.83.0")
-
-set(CMAKE_CXX_STANDARD 17)
-set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(KF5_MIN_VERSION "5.89.0")
# ECM setup
find_package(ECM ${KF5_MIN_VERSION} CONFIG REQUIRED)
set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${CMAKE_SOURCE_DIR}/cmake)
+include(KDEInstallDirs)
+include(KDECMakeSettings)
+include(KDECompilerSettings NO_POLICY_SCOPE)
+
include(ECMSetupVersion)
include(ECMGenerateHeaders)
include(ECMGenerateDBusServiceFile)
@@ -24,9 +25,6 @@ include(ECMConfiguredInstall)
include(CMakePackageConfigHelpers)
include(GenerateExportHeader)
include(FeatureSummary)
-include(KDEInstallDirs)
-include(KDECMakeSettings)
-include(KDEFrameworkCompilerSettings NO_POLICY_SCOPE)
include(ECMQtDeclareLoggingCategory)
ecm_setup_version(${RELEASE_SERVICE_VERSION} VARIABLE_PREFIX DOLPHIN
@@ -140,6 +138,13 @@ else()
set(HAVE_TERMINAL TRUE)
endif()
+add_definitions(
+ -DQT_DISABLE_DEPRECATED_BEFORE=0x050f00
+ -DQT_DEPRECATED_WARNINGS_SINCE=0x060000
+ -DKF_DISABLE_DEPRECATED_BEFORE_AND_AT=0x055800
+ -DKF_DEPRECATED_WARNINGS_SINCE=0x060000
+)
+
add_subdirectory(src)
add_subdirectory(doc)
diff --git a/src/dolphincontextmenu.cpp b/src/dolphincontextmenu.cpp
index 41f03aa1a..028fd98bd 100644
--- a/src/dolphincontextmenu.cpp
+++ b/src/dolphincontextmenu.cpp
@@ -197,7 +197,6 @@ void DolphinContextMenu::addDirectoryItemContextMenu()
// set up 'Create New' menu
DolphinNewFileMenu* newFileMenu = new DolphinNewFileMenu(m_mainWindow->actionCollection(), m_mainWindow);
const DolphinView* view = m_mainWindow->activeViewContainer()->view();
- newFileMenu->setViewShowsHiddenFiles(view->hiddenFilesShown());
newFileMenu->checkUpToDate();
newFileMenu->setPopupFiles(QList<QUrl>() << m_fileInfo.url());
newFileMenu->setEnabled(selectedItemsProps.supportsWriting());
@@ -315,7 +314,6 @@ void DolphinContextMenu::openViewportContextMenu()
// Set up and insert 'Create New' menu
KNewFileMenu* newFileMenu = m_mainWindow->newFileMenu();
- newFileMenu->setViewShowsHiddenFiles(view->hiddenFilesShown());
newFileMenu->checkUpToDate();
newFileMenu->setPopupFiles(QList<QUrl>() << m_baseUrl);
addMenu(newFileMenu->menu());
@@ -477,7 +475,7 @@ KFileItem DolphinContextMenu::baseFileItem()
void DolphinContextMenu::addOpenWithActions()
{
// insert 'Open With...' action or sub menu
- m_fileItemActions->addOpenWithActionsTo(this, QStringLiteral("DesktopEntryName != '%1'").arg(qApp->desktopFileName()));
+ m_fileItemActions->insertOpenWithActionsTo(nullptr, this, QStringList{qApp->desktopFileName()});
}
void DolphinContextMenu::addCustomActions()
diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp
index fa105b15a..c03095c3c 100644
--- a/src/dolphinmainwindow.cpp
+++ b/src/dolphinmainwindow.cpp
@@ -133,7 +133,7 @@ DolphinMainWindow::DolphinMainWindow() :
KIO::FileUndoManager* undoManager = KIO::FileUndoManager::self();
undoManager->setUiInterface(new UndoUiInterface());
- connect(undoManager, QOverload<bool>::of(&KIO::FileUndoManager::undoAvailable),
+ connect(undoManager, &KIO::FileUndoManager::undoAvailable,
this, &DolphinMainWindow::slotUndoAvailable);
connect(undoManager, &KIO::FileUndoManager::undoTextChanged,
this, &DolphinMainWindow::slotUndoTextChanged);
@@ -211,7 +211,7 @@ DolphinMainWindow::DolphinMainWindow() :
setupWhatsThis();
- connect(KSycoca::self(), QOverload<>::of(&KSycoca::databaseChanged), this, &DolphinMainWindow::updateOpenPreferredSearchToolAction);
+ connect(KSycoca::self(), &KSycoca::databaseChanged, this, &DolphinMainWindow::updateOpenPreferredSearchToolAction);
QTimer::singleShot(0, this, &DolphinMainWindow::updateOpenPreferredSearchToolAction);
@@ -445,6 +445,16 @@ void DolphinMainWindow::openNewTab(const QUrl& url)
m_tabWidget->openNewTab(url, QUrl());
}
+void DolphinMainWindow::openNewTabAndActivate(const QUrl &url)
+{
+ m_tabWidget->openNewActivatedTab(url, QUrl());
+}
+
+void DolphinMainWindow::openNewWindow(const QUrl &url)
+{
+ Dolphin::openNewWindow({url}, this);
+}
+
void DolphinMainWindow::slotSplitViewChanged()
{
m_tabWidget->currentTabPage()->setSplitViewEnabled(GeneralSettings::splitView(), WithAnimation);
@@ -647,14 +657,12 @@ void DolphinMainWindow::readProperties(const KConfigGroup& group)
void DolphinMainWindow::updateNewMenu()
{
- m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown());
m_newFileMenu->checkUpToDate();
m_newFileMenu->setPopupFiles(QList<QUrl>() << activeViewContainer()->url());
}
void DolphinMainWindow::createDirectory()
{
- m_newFileMenu->setViewShowsHiddenFiles(activeViewContainer()->view()->hiddenFilesShown());
m_newFileMenu->setPopupFiles(QList<QUrl>() << activeViewContainer()->url());
m_newFileMenu->createDirectory();
}
@@ -1480,7 +1488,7 @@ void DolphinMainWindow::setupActions()
QAction* showFilterBar = actionCollection()->addAction(QStringLiteral("show_filter_bar"));
showFilterBar->setText(i18nc("@action:inmenu Tools", "Filter..."));
- showFilterBar->setToolTip(i18nc("@info:tooltip", "Toggle Filter Bar"));
+ showFilterBar->setToolTip(i18nc("@info:tooltip", "Show Filter Bar"));
showFilterBar->setWhatsThis(xi18nc("@info:whatsthis", "This opens the "
"<emphasis>Filter Bar</emphasis> at the bottom of the window.<nl/> "
"There you can enter a text to filter the files and folders currently displayed. "
@@ -1861,8 +1869,10 @@ void DolphinMainWindow::setupDockWidgets()
foldersPanel, &FoldersPanel::setUrl);
connect(foldersPanel, &FoldersPanel::folderActivated,
this, &DolphinMainWindow::changeUrl);
- connect(foldersPanel, &FoldersPanel::folderMiddleClicked,
+ connect(foldersPanel, &FoldersPanel::folderInNewTab,
this, &DolphinMainWindow::openNewTab);
+ connect(foldersPanel, &FoldersPanel::folderInNewActiveTab,
+ this, &DolphinMainWindow::openNewTabAndActivate);
connect(foldersPanel, &FoldersPanel::errorMessage,
this, &DolphinMainWindow::showErrorMessage);
@@ -1944,8 +1954,10 @@ void DolphinMainWindow::setupDockWidgets()
addDockWidget(Qt::LeftDockWidgetArea, placesDock);
connect(m_placesPanel, &PlacesPanel::placeActivated,
this, &DolphinMainWindow::slotPlaceActivated);
- connect(m_placesPanel, &PlacesPanel::placeMiddleClicked,
+ connect(m_placesPanel, &PlacesPanel::placeActivatedInNewTab,
this, &DolphinMainWindow::openNewTab);
+ connect(m_placesPanel, &PlacesPanel::placeActivatedInNewActiveTab,
+ this, &DolphinMainWindow::openNewTabAndActivate);
connect(m_placesPanel, &PlacesPanel::errorMessage,
this, &DolphinMainWindow::showErrorMessage);
connect(this, &DolphinMainWindow::urlChanged,
@@ -2136,6 +2148,10 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
this, &DolphinMainWindow::updateSearchAction);
connect(container, &DolphinViewContainer::captionChanged,
this, &DolphinMainWindow::updateWindowTitle);
+ connect(container, &DolphinViewContainer::tabRequested,
+ this, &DolphinMainWindow::openNewTab);
+ connect(container, &DolphinViewContainer::activeTabRequested,
+ this, &DolphinMainWindow::openNewTabAndActivate);
const QAction* toggleSearchAction = actionCollection()->action(QStringLiteral("toggle_search"));
connect(toggleSearchAction, &QAction::triggered, container, &DolphinViewContainer::setSearchModeEnabled);
@@ -2149,6 +2165,10 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
this, &DolphinMainWindow::fileItemsChanged);
connect(view, &DolphinView::tabRequested,
this, &DolphinMainWindow::openNewTab);
+ connect(view, &DolphinView::activeTabRequested,
+ this, &DolphinMainWindow::openNewTabAndActivate);
+ connect(view, &DolphinView::windowRequested,
+ this, &DolphinMainWindow::openNewWindow);
connect(view, &DolphinView::requestContextMenu,
this, &DolphinMainWindow::openContextMenu);
connect(view, &DolphinView::directoryLoadingStarted,
@@ -2183,6 +2203,10 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
this, &DolphinMainWindow::slotEditableStateChanged);
connect(navigator, &KUrlNavigator::tabRequested,
this, &DolphinMainWindow::openNewTab);
+ connect(navigator, &KUrlNavigator::activeTabRequested,
+ this, &DolphinMainWindow::openNewTabAndActivate);
+ connect(navigator, &KUrlNavigator::newWindowRequested,
+ this, &DolphinMainWindow::openNewWindow);
}
diff --git a/src/dolphinmainwindow.h b/src/dolphinmainwindow.h
index 46515cc8b..761766df8 100644
--- a/src/dolphinmainwindow.h
+++ b/src/dolphinmainwindow.h
@@ -171,6 +171,16 @@ public Q_SLOTS:
*/
void openNewTab(const QUrl& url);
+ /**
+ * Opens a new tab showing the URL \a url and activate it.
+ */
+ void openNewTabAndActivate(const QUrl &url);
+
+ /**
+ * Opens a new window showing the URL \a url.
+ */
+ void openNewWindow(const QUrl &url);
+
/** @see GeneralSettings::splitViewChanged() */
void slotSplitViewChanged();
diff --git a/src/dolphinnavigatorswidgetaction.h b/src/dolphinnavigatorswidgetaction.h
index 3f50728e9..d33482201 100644
--- a/src/dolphinnavigatorswidgetaction.h
+++ b/src/dolphinnavigatorswidgetaction.h
@@ -57,7 +57,7 @@ public:
* This method should preferably only be called when:
* - Split view is activated in the active tab
* OR
- * - A switch to a tab that is already in split view mode is occuring
+ * - A switch to a tab that is already in split view mode is occurring
*/
void createSecondaryUrlNavigator();
@@ -92,7 +92,7 @@ protected:
* this method always returns the same widget and reparents it.
* You normally don't have to use this method directly because
* QWidgetAction::requestWidget() is used to obtain the navigatorsWidget
- * and to steal it from whereever it was prior.
+ * and to steal it from wherever it was prior.
* @param parent the new parent of the navigatorsWidget.
*/
QWidget *createWidget(QWidget *parent) override;
diff --git a/src/dolphinpart.cpp b/src/dolphinpart.cpp
index 8d528f418..059508778 100644
--- a/src/dolphinpart.cpp
+++ b/src/dolphinpart.cpp
@@ -68,7 +68,7 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent,
connect(&DolphinNewFileMenuObserver::instance(), &DolphinNewFileMenuObserver::errorMessage,
this, &DolphinPart::slotErrorMessage);
- connect(m_view, &DolphinView::directoryLoadingCompleted, this, QOverload<>::of(&KParts::ReadOnlyPart::completed));
+ connect(m_view, &DolphinView::directoryLoadingCompleted, this, &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);
@@ -94,7 +94,7 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent,
connect(m_view, &DolphinView::requestContextMenu,
this, &DolphinPart::slotOpenContextMenu);
connect(m_view, &DolphinView::selectionChanged,
- m_extension, QOverload<const KFileItemList&>::of(&KParts::BrowserExtension::selectionInfo));
+ m_extension, &KParts::BrowserExtension::selectionInfo);
connect(m_view, &DolphinView::selectionChanged,
this, &DolphinPart::slotSelectionChanged);
connect(m_view, &DolphinView::requestItemInfo,
@@ -146,8 +146,6 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent,
// TODO there was a "always open a new window" (when clicking on a directory) setting in konqueror
// (sort of spacial navigation)
-
- loadPlugins(this, this, componentName());
}
DolphinPart::~DolphinPart()
@@ -593,7 +591,6 @@ void DolphinPart::updateNewMenu()
{
// As requested by KNewFileMenu :
m_newFileMenu->checkUpToDate();
- m_newFileMenu->setViewShowsHiddenFiles(m_view->hiddenFilesShown());
// And set the files that the menu apply on :
m_newFileMenu->setPopupFiles(QList<QUrl>() << url());
}
@@ -610,7 +607,6 @@ void DolphinPart::updateProgress(int percent)
void DolphinPart::createDirectory()
{
- m_newFileMenu->setViewShowsHiddenFiles(m_view->hiddenFilesShown());
m_newFileMenu->setPopupFiles(QList<QUrl>() << url());
m_newFileMenu->createDirectory();
}
diff --git a/src/dolphintabpage.h b/src/dolphintabpage.h
index f1a784eb7..a8c1ba311 100644
--- a/src/dolphintabpage.h
+++ b/src/dolphintabpage.h
@@ -46,7 +46,7 @@ public:
*
* @param enabled If true, creates a secondary viewContainer in this tab.
* Otherwise deletes it.
- * @param animated Decides wether the effects of this method call should
+ * @param animated Decides whether the effects of this method call should
* happen instantly or be transitioned to smoothly.
* @param secondaryUrl If \p enabled is true, the new viewContainer will be opened at this
* parameter. The default value will set the Url of the new viewContainer
diff --git a/src/dolphinurlnavigatorscontroller.h b/src/dolphinurlnavigatorscontroller.h
index 4f6802725..fec15f481 100644
--- a/src/dolphinurlnavigatorscontroller.h
+++ b/src/dolphinurlnavigatorscontroller.h
@@ -41,7 +41,7 @@ public Q_SLOTS:
private:
/**
- * @return wether the places selector of DolphinUrlNavigators should be visible.
+ * @return whether the places selector of DolphinUrlNavigators should be visible.
*/
static bool placesSelectorVisible();
diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp
index 5520bf794..48e73ca89 100644
--- a/src/dolphinviewcontainer.cpp
+++ b/src/dolphinviewcontainer.cpp
@@ -32,6 +32,7 @@
#include <KUrlComboBox>
#include <QDropEvent>
+#include <QGuiApplication>
#include <QLoggingCategory>
#include <QMimeData>
#include <QTimer>
@@ -151,6 +152,10 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) :
this, &DolphinViewContainer::slotUrlIsFileError);
connect(m_view, &DolphinView::activated,
this, &DolphinViewContainer::activate);
+ connect(m_view, &DolphinView::hiddenFilesShownChanged,
+ this, &DolphinViewContainer::slotHiddenFilesShownChanged);
+ connect(m_view, &DolphinView::sortHiddenLastChanged,
+ this, &DolphinViewContainer::slotSortHiddenLastChanged);
// Initialize status bar
m_statusBar = new DolphinStatusBar(this);
@@ -309,6 +314,8 @@ void DolphinViewContainer::connectUrlNavigator(DolphinUrlNavigator *urlNavigator
Q_CHECK_PTR(m_view);
urlNavigator->setLocationUrl(m_view->url());
+ urlNavigator->setShowHiddenFolders(m_view->hiddenFilesShown());
+ urlNavigator->setSortHiddenFoldersLast(m_view->sortHiddenLast());
if (m_urlNavigatorVisualState) {
urlNavigator->setVisualState(*m_urlNavigatorVisualState.get());
m_urlNavigatorVisualState.reset();
@@ -636,7 +643,7 @@ void DolphinViewContainer::slotUrlIsFileError(const QUrl& url)
}
}
-void DolphinViewContainer::slotItemActivated(const KFileItem& item)
+void DolphinViewContainer::slotItemActivated(const KFileItem &item)
{
// It is possible to activate items on inactive views by
// drag & drop operations. Assure that activating an item always
@@ -645,13 +652,24 @@ void DolphinViewContainer::slotItemActivated(const KFileItem& item)
const QUrl& url = DolphinView::openItemAsFolderUrl(item, GeneralSettings::browseThroughArchives());
if (!url.isEmpty()) {
- setUrl(url);
+ const auto modifiers = QGuiApplication::keyboardModifiers();
+ // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+ if (modifiers & Qt::ControlModifier && modifiers & Qt::ShiftModifier) {
+ Q_EMIT activeTabRequested(url);
+ } else if (modifiers & Qt::ControlModifier) {
+ Q_EMIT tabRequested(url);
+ } else if (modifiers & Qt::ShiftModifier) {
+ Dolphin::openNewWindow({KFilePlacesModel::convertedUrl(url)}, this);
+ } else {
+ setUrl(url);
+ }
return;
}
KIO::OpenUrlJob *job = new KIO::OpenUrlJob(item.targetUrl());
- job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, this));
+ job->setUiDelegate(new KIO::JobUiDelegate(KJobUiDelegate::AutoWarningHandlingEnabled, this));
job->setShowOpenOrExecuteDialog(true);
+ connect(job, &KIO::OpenUrlJob::finished, this, &DolphinViewContainer::slotOpenUrlFinished);
job->start();
}
@@ -660,7 +678,7 @@ void DolphinViewContainer::slotItemsActivated(const KFileItemList& items)
Q_ASSERT(items.count() >= 2);
KFileItemActions fileItemActions(this);
- fileItemActions.runPreferredApplications(items, QString());
+ fileItemActions.runPreferredApplications(items);
}
void DolphinViewContainer::showItemInfo(const KFileItem& item)
@@ -809,6 +827,27 @@ void DolphinViewContainer::slotPlacesModelChanged()
}
}
+void DolphinViewContainer::slotHiddenFilesShownChanged(bool showHiddenFiles)
+{
+ if (m_urlNavigatorConnected) {
+ m_urlNavigatorConnected->setShowHiddenFolders(showHiddenFiles);
+ }
+}
+
+void DolphinViewContainer::slotSortHiddenLastChanged(bool hiddenLast)
+{
+ if (m_urlNavigatorConnected) {
+ m_urlNavigatorConnected->setSortHiddenFoldersLast(hiddenLast);
+ }
+}
+
+void DolphinViewContainer::slotOpenUrlFinished(KJob *job)
+{
+ if (job->error() && job->error() != KIO::ERR_USER_CANCELED) {
+ showErrorMessage(job->errorString());
+ }
+}
+
bool DolphinViewContainer::isSearchUrl(const QUrl& url) const
{
return url.scheme().contains(QLatin1String("search"));
diff --git a/src/dolphinviewcontainer.h b/src/dolphinviewcontainer.h
index 304c9958d..f78f85e55 100644
--- a/src/dolphinviewcontainer.h
+++ b/src/dolphinviewcontainer.h
@@ -126,7 +126,7 @@ public:
void connectUrlNavigator(DolphinUrlNavigator *urlNavigator);
/**
- * Disconnects the navigator that is currently controling the view.
+ * Disconnects the navigator that is currently controlling the view.
* This method completely reverses connectUrlNavigator().
*/
void disconnectUrlNavigator();
@@ -229,6 +229,16 @@ Q_SIGNALS:
*/
void captionChanged();
+ /**
+ * Is emitted if a new tab should be opened in the background for the URL \a url.
+ */
+ void tabRequested(const QUrl &url);
+
+ /**
+ * Is emitted if a new tab should be opened for the URL \a url and set as active.
+ */
+ void activeTabRequested(const QUrl &url);
+
private Q_SLOTS:
/**
* Updates the number of items (= number of files + number of
@@ -281,7 +291,7 @@ private Q_SLOTS:
* directory is opened in the view. If the item is a file, the file
* gets started by the corresponding application.
*/
- void slotItemActivated(const KFileItem& item);
+ void slotItemActivated(const KFileItem &item);
/**
* Handles activation of multiple files. The files get started by
@@ -361,6 +371,11 @@ private Q_SLOTS:
*/
void slotPlacesModelChanged();
+ void slotHiddenFilesShownChanged(bool showHiddenFiles);
+ void slotSortHiddenLastChanged(bool hiddenLast);
+
+ void slotOpenUrlFinished(KJob* job);
+
private:
/**
* @return True if the URL protocol is a search URL (e. g. baloosearch:// or filenamesearch://).
diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp
index d12355100..07f8832ee 100644
--- a/src/kitemviews/kfileitemmodel.cpp
+++ b/src/kitemviews/kfileitemmodel.cpp
@@ -25,6 +25,7 @@
#include <QWidget>
#include <QRecursiveMutex>
#include <QIcon>
+#include <algorithm>
Q_GLOBAL_STATIC(QRecursiveMutex, s_collatorMutex)
@@ -64,15 +65,15 @@ KFileItemModel::KFileItemModel(QObject* parent) :
}
connect(m_dirLister, &KCoreDirLister::started, this, &KFileItemModel::directoryLoadingStarted);
- connect(m_dirLister, QOverload<>::of(&KCoreDirLister::canceled), this, &KFileItemModel::slotCanceled);
+ connect(m_dirLister, &KCoreDirLister::canceled, this, &KFileItemModel::slotCanceled);
connect(m_dirLister, &KCoreDirLister::itemsAdded, this, &KFileItemModel::slotItemsAdded);
connect(m_dirLister, &KCoreDirLister::itemsDeleted, this, &KFileItemModel::slotItemsDeleted);
connect(m_dirLister, &KCoreDirLister::refreshItems, this, &KFileItemModel::slotRefreshItems);
- connect(m_dirLister, QOverload<>::of(&KCoreDirLister::clear), this, &KFileItemModel::slotClear);
+ connect(m_dirLister, &KCoreDirLister::clear, this, &KFileItemModel::slotClear);
connect(m_dirLister, &KCoreDirLister::infoMessage, this, &KFileItemModel::infoMessage);
connect(m_dirLister, &KCoreDirLister::jobError, this, &KFileItemModel::slotListerError);
connect(m_dirLister, &KCoreDirLister::percent, this, &KFileItemModel::directoryLoadingProgress);
- connect(m_dirLister, QOverload<const QUrl&, const QUrl&>::of(&KCoreDirLister::redirection), this, &KFileItemModel::directoryRedirection);
+ connect(m_dirLister, &KCoreDirLister::redirection, this, &KFileItemModel::directoryRedirection);
connect(m_dirLister, &KCoreDirLister::listingDirCompleted, this, &KFileItemModel::slotCompleted);
// Apply default roles that should be determined
@@ -149,6 +150,18 @@ QHash<QByteArray, QVariant> KFileItemModel::data(int index) const
ItemData* data = m_itemData.at(index);
if (data->values.isEmpty()) {
data->values = retrieveData(data->item, data->parent);
+ } else if (data->values.count() <= 2 && data->values.value("isExpanded").toBool()) {
+ // Special case dealt by slotRefreshItems(), avoid losing the "isExpanded" and "expandedParentsCount" state when refreshing
+ // slotRefreshItems() makes sure folders keep the "isExpanded" and "expandedParentsCount" while clearing the remaining values
+ // so this special request of different behavior can be identified here.
+ bool hasExpandedParentsCount = false;
+ const int expandedParentsCount = data->values.value("expandedParentsCount").toInt(&hasExpandedParentsCount);
+
+ data->values = retrieveData(data->item, data->parent);
+ data->values.insert("isExpanded", true);
+ if (hasExpandedParentsCount) {
+ data->values.insert("expandedParentsCount", expandedParentsCount);
+ }
}
return data->values;
@@ -712,7 +725,7 @@ void KFileItemModel::applyFilters()
ItemData *itemData = m_itemData.at(index);
if (m_filter.matches(itemData->item)
- || (itemShownBelow && itemShownBelow->parent == itemData && itemData->values.value("isExpanded").toBool())) {
+ || (itemShownBelow && itemShownBelow->parent == itemData)) {
// We could've entered here for two reasons:
// 1. This item passes the filter itself
// 2. This is an expanded folder that doesn't pass the filter but sees a filter-passing child just below
@@ -1010,12 +1023,7 @@ void KFileItemModel::slotItemsAdded(const QUrl &directoryUrl, const KFileItemLis
{
Q_ASSERT(!items.isEmpty());
- QUrl parentUrl;
- if (m_expandedDirs.contains(directoryUrl)) {
- parentUrl = m_expandedDirs.value(directoryUrl);
- } else {
- parentUrl = directoryUrl.adjusted(QUrl::StripTrailingSlash);
- }
+ const QUrl parentUrl = m_expandedDirs.value(directoryUrl, directoryUrl.adjusted(QUrl::StripTrailingSlash));
if (m_requestRole[ExpandedParentsCountRole]) {
// If the expanding of items is enabled, the call
@@ -1049,16 +1057,28 @@ void KFileItemModel::slotItemsAdded(const QUrl &directoryUrl, const KFileItemLis
if (!m_filter.hasSetFilters()) {
m_pendingItemsToInsert.append(itemDataList);
} else {
+ QSet<ItemData *> parentsToEnsureVisible;
+
// The name or type filter is active. Hide filtered items
// before inserting them into the model and remember
// the filtered items in m_filteredItems.
for (ItemData* itemData : itemDataList) {
if (m_filter.matches(itemData->item)) {
m_pendingItemsToInsert.append(itemData);
+ if (itemData->parent) {
+ parentsToEnsureVisible.insert(itemData->parent);
+ }
} else {
m_filteredItems.insert(itemData->item, itemData);
}
}
+
+ // Entire parental chains must be shown
+ for (ItemData *parent : parentsToEnsureVisible) {
+ for (; parent && m_filteredItems.remove(parent->item); parent = parent->parent) {
+ m_pendingItemsToInsert.append(parent);
+ }
+ }
}
if (!m_maximumUpdateIntervalTimer->isActive()) {
@@ -1070,6 +1090,42 @@ void KFileItemModel::slotItemsAdded(const QUrl &directoryUrl, const KFileItemLis
Q_EMIT fileItemsChanged({KFileItem(directoryUrl)});
}
+int KFileItemModel::filterChildlessParents(KItemRangeList &removedItemRanges, const QSet<ItemData *> &parentsToEnsureVisible)
+{
+ int filteredParentsCount = 0;
+ // The childless parents not yet removed will always be right above the start of a removed range.
+ // We iterate backwards to ensure the deepest folders are processed before their parents
+ for (int i = removedItemRanges.size() - 1; i >= 0; i--) {
+ KItemRange itemRange = removedItemRanges.at(i);
+ const ItemData *const firstInRange = m_itemData.at(itemRange.index);
+ ItemData *itemAbove = itemRange.index - 1 >= 0 ? m_itemData.at(itemRange.index - 1) : nullptr;
+ const ItemData *const itemBelow = itemRange.index + itemRange.count < m_itemData.count() ? m_itemData.at(itemRange.index + itemRange.count) : nullptr;
+
+ if (itemAbove && firstInRange->parent == itemAbove && !m_filter.matches(itemAbove->item) && (!itemBelow || itemBelow->parent != itemAbove)
+ && !parentsToEnsureVisible.contains(itemAbove)) {
+ // The item above exists, is the parent, doesn't pass the filter, does not belong to parentsToEnsureVisible
+ // and this deleted range covers all of its descendents, so none will be left.
+ m_filteredItems.insert(itemAbove->item, itemAbove);
+ // This range's starting index will be extended to include the parent above:
+ --itemRange.index;
+ ++itemRange.count;
+ ++filteredParentsCount;
+ KItemRange previousRange = i > 0 ? removedItemRanges.at(i - 1) : KItemRange();
+ // We must check if this caused the range to touch the previous range, if that's the case they shall be merged
+ if (i > 0 && previousRange.index + previousRange.count == itemRange.index) {
+ previousRange.count += itemRange.count;
+ removedItemRanges.replace(i - 1, previousRange);
+ removedItemRanges.removeAt(i);
+ } else {
+ removedItemRanges.replace(i, itemRange);
+ // We must revisit this range in the next iteration since its starting index changed
+ ++i;
+ }
+ }
+ }
+ return filteredParentsCount;
+}
+
void KFileItemModel::slotItemsDeleted(const KFileItemList& items)
{
dispatchPendingItemsToInsert();
@@ -1119,9 +1175,17 @@ void KFileItemModel::slotItemsDeleted(const KFileItemList& items)
indexesToRemove = indexesToRemoveWithChildren;
}
- const KItemRangeList itemRanges = KItemRangeList::fromSortedContainer(indexesToRemove);
+ KItemRangeList itemRanges = KItemRangeList::fromSortedContainer(indexesToRemove);
removeFilteredChildren(itemRanges);
- removeItems(itemRanges, DeleteItemData);
+
+ // This call will update itemRanges to include the childless parents that have been filtered.
+ const int filteredParentsCount = filterChildlessParents(itemRanges);
+
+ // If any childless parents were filtered, then itemRanges got updated and now contains items that were really deleted
+ // mixed with expanded folders that are just being filtered out.
+ // If that's the case, we pass 'DeleteItemDataIfUnfiltered' as a hint
+ // so removeItems() will check m_filteredItems to differentiate which is which.
+ removeItems(itemRanges, filteredParentsCount > 0 ? DeleteItemDataIfUnfiltered : DeleteItemData);
Q_EMIT fileItemsChanged(dirsChanged);
}
@@ -1149,6 +1213,7 @@ void KFileItemModel::slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >&
QList<ItemData*> newVisibleItems;
QListIterator<QPair<KFileItem, KFileItem> > it(items);
+
while (it.hasNext()) {
const QPair<KFileItem, KFileItem>& itemPair = it.next();
const KFileItem& oldItem = itemPair.first;
@@ -1172,8 +1237,14 @@ void KFileItemModel::slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >&
}
m_items.remove(oldItem.url());
- if (newItemMatchesFilter) {
- m_items.insert(newItem.url(), indexForItem);
+ // We must maintain m_items consistent with m_itemData for now, this very loop is using it.
+ // We leave it to be cleared by removeItems() later, when m_itemData actually gets updated.
+ m_items.insert(newItem.url(), indexForItem);
+ if (newItemMatchesFilter
+ || (itemData->values.value("isExpanded").toBool()
+ && (indexForItem + 1 < m_itemData.count() && m_itemData.at(indexForItem + 1)->parent == itemData))) {
+ // We are lenient with expanded folders that originally had visible children.
+ // If they become childless now they will be caught by filterChildlessParents()
changedFiles.append(newItem);
indexes.append(indexForItem);
} else {
@@ -1184,12 +1255,23 @@ void KFileItemModel::slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >&
// Check if 'oldItem' is one of the filtered items.
QHash<KFileItem, ItemData*>::iterator it = m_filteredItems.find(oldItem);
if (it != m_filteredItems.end()) {
- ItemData* itemData = it.value();
+ ItemData *const itemData = it.value();
itemData->item = newItem;
// The data stored in 'values' might have changed. Therefore, we clear
// 'values' and re-populate it the next time it is requested via data(int).
+ // Before clearing, we must remember if it was expanded and the expanded parents count,
+ // otherwise these states would be lost. The data() method will deal with this special case.
+ const bool isExpanded = itemData->values.value("isExpanded").toBool();
+ bool hasExpandedParentsCount = false;
+ const int expandedParentsCount = itemData->values.value("expandedParentsCount").toInt(&hasExpandedParentsCount);
itemData->values.clear();
+ if (isExpanded) {
+ itemData->values.insert("isExpanded", true);
+ if (hasExpandedParentsCount) {
+ itemData->values.insert("expandedParentsCount", expandedParentsCount);
+ }
+ }
m_filteredItems.erase(it);
if (newItemMatchesFilter) {
@@ -1201,21 +1283,66 @@ void KFileItemModel::slotRefreshItems(const QList<QPair<KFileItem, KFileItem> >&
}
}
- // Hide items, previously visible that should get hidden
- const KItemRangeList removedRanges = KItemRangeList::fromSortedContainer(newFilteredIndexes);
+ std::sort(newFilteredIndexes.begin(), newFilteredIndexes.end());
+
+ // We must keep track of parents of new visible items since they must be shown no matter what
+ // They will be considered "immune" to filterChildlessParents()
+ QSet<ItemData *> parentsToEnsureVisible;
+
+ for (ItemData *item : newVisibleItems) {
+ for (ItemData *parent = item->parent; parent && !parentsToEnsureVisible.contains(parent); parent = parent->parent) {
+ parentsToEnsureVisible.insert(parent);
+ }
+ }
+ for (ItemData *parent : parentsToEnsureVisible) {
+ // We make sure they are all unfiltered.
+ if (m_filteredItems.remove(parent->item)) {
+ // If it is being unfiltered now, we mark it to be inserted by appending it to newVisibleItems
+ newVisibleItems.append(parent);
+ // It could be in newFilteredIndexes, we must remove it if it's there:
+ const int parentIndex = index(parent->item);
+ if (parentIndex >= 0) {
+ QVector<int>::iterator it = std::lower_bound(newFilteredIndexes.begin(), newFilteredIndexes.end(), parentIndex);
+ if (it != newFilteredIndexes.end() && *it == parentIndex) {
+ newFilteredIndexes.erase(it);
+ }
+ }
+ }
+ }
+
+ KItemRangeList removedRanges = KItemRangeList::fromSortedContainer(newFilteredIndexes);
+
+ // This call will update itemRanges to include the childless parents that have been filtered.
+ filterChildlessParents(removedRanges, parentsToEnsureVisible);
+
removeItems(removedRanges, KeepItemData);
// Show previously hidden items that should get visible
insertItems(newVisibleItems);
+ // Final step: we will emit 'itemsChanged' and 'fileItemsChanged' signals and trigger the asynchronous re-sorting logic.
+
// If the changed items have been created recently, they might not be in m_items yet.
// In that case, the list 'indexes' might be empty.
if (indexes.isEmpty()) {
return;
}
+ if (newVisibleItems.count() > 0 || removedRanges.count() > 0) {
+ // The original indexes have changed and are now worthless since items were removed and/or inserted.
+ indexes.clear();
+ // m_items is not yet rebuilt at this point, so we use our own means to resolve the new indexes.
+ const QSet<const KFileItem> changedFilesSet(changedFiles.cbegin(), changedFiles.cend());
+ for (int i = 0; i < m_itemData.count(); i++) {
+ if (changedFilesSet.contains(m_itemData.at(i)->item)) {
+ indexes.append(i);
+ }
+ }
+ } else {
+ std::sort(indexes.begin(), indexes.end());
+ }
+
// Extract the item-ranges out of the changed indexes
- std::sort(indexes.begin(), indexes.end());
const KItemRangeList itemRangeList = KItemRangeList::fromSortedContainer(indexes);
emitItemsChangedAndTriggerResorting(itemRangeList, changedRoles);
@@ -1380,7 +1507,7 @@ void KFileItemModel::removeItems(const KItemRangeList& itemRanges, RemoveItemsBe
removedItemsCount += range.count;
for (int index = range.index; index < range.index + range.count; ++index) {
- if (behavior == DeleteItemData) {
+ if (behavior == DeleteItemData || (behavior == DeleteItemDataIfUnfiltered && !m_filteredItems.contains(m_itemData.at(index)->item))) {
delete m_itemData.at(index);
}
@@ -1424,8 +1551,9 @@ QList<KFileItemModel::ItemData*> KFileItemModel::createItemDataList(const QUrl&
determineMimeTypes(items, 200);
}
+ // We search for the parent in m_itemData and then in m_filteredItems if necessary
const int parentIndex = index(parentUrl);
- ItemData* parentItem = parentIndex < 0 ? nullptr : m_itemData.at(parentIndex);
+ ItemData *parentItem = parentIndex < 0 ? m_filteredItems.value(KFileItem(parentUrl), nullptr) : m_itemData.at(parentIndex);
QList<ItemData*> itemDataList;
itemDataList.reserve(items.count());
diff --git a/src/kitemviews/kfileitemmodel.h b/src/kitemviews/kfileitemmodel.h
index 161f6a0e2..471cfc2d2 100644
--- a/src/kitemviews/kfileitemmodel.h
+++ b/src/kitemviews/kfileitemmodel.h
@@ -309,7 +309,8 @@ private:
enum RemoveItemsBehavior {
KeepItemData,
- DeleteItemData
+ DeleteItemData,
+ DeleteItemDataIfUnfiltered
};
void insertItems(QList<ItemData*>& items);
@@ -469,6 +470,15 @@ private:
*/
bool isConsistent() const;
+ /**
+ * Filters out the expanded folders that don't pass the filter themselves and don't have any filter-passing children.
+ * Will update the removedItemRanges arguments to include the parents that have been filtered.
+ * @returns the number of parents that have been filtered.
+ * @param removedItemRanges The ranges of items being deleted/filtered, will get updated
+ * @param parentsToEnsureVisible Parents that must be visible no matter what due to being ancestors of newly visible items
+ */
+ int filterChildlessParents(KItemRangeList &removedItemRanges, const QSet<ItemData *> &parentsToEnsureVisible = QSet<ItemData *>());
+
private:
KDirLister *m_dirLister = nullptr;
diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp
index 978f5df6e..49657a9b1 100644
--- a/src/kitemviews/kfileitemmodelrolesupdater.cpp
+++ b/src/kitemviews/kfileitemmodelrolesupdater.cpp
@@ -18,7 +18,7 @@
#include <KIconLoader>
#include <KJobWidgets>
#include <KOverlayIconPlugin>
-#include <KPluginLoader>
+#include <KPluginMetaData>
#include <KSharedConfig>
#ifdef HAVE_BALOO
@@ -30,6 +30,7 @@
#include <QApplication>
#include <QIcon>
#include <QPainter>
+#include <QPluginLoader>
#include <QElapsedTimer>
#include <QTimer>
@@ -120,15 +121,16 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO
connect(m_directoryContentsCounter, &KDirectoryContentsCounter::result,
this, &KFileItemModelRolesUpdater::slotDirectoryContentsCountReceived);
- const auto plugins = KPluginLoader::instantiatePlugins(QStringLiteral("kf5/overlayicon"), nullptr, qApp);
- for (QObject *it : plugins) {
- auto plugin = qobject_cast<KOverlayIconPlugin*>(it);
+ const auto plugins = KPluginMetaData::findPlugins(QStringLiteral("kf5/overlayicon"));
+ for (const KPluginMetaData &data : plugins) {
+ auto instance = QPluginLoader(data.fileName()).instance();
+ auto plugin = qobject_cast<KOverlayIconPlugin *>(instance);
if (plugin) {
m_overlayIconsPlugin.append(plugin);
connect(plugin, &KOverlayIconPlugin::overlaysChanged, this, &KFileItemModelRolesUpdater::slotOverlaysChanged);
} else {
// not our/valid plugin, so delete the created object
- it->deleteLater();
+ delete instance;
}
}
}
@@ -1405,10 +1407,19 @@ QList<int> KFileItemModelRolesUpdater::indexesToResolve() const
(2 * m_maximumVisibleItems)));
// Add visible items.
+ // Resolve files first, their previews are quicker.
+ QList<int> visibleDirs;
for (int i = m_firstVisibleIndex; i <= m_lastVisibleIndex; ++i) {
- result.append(i);
+ const KFileItem item = m_model->fileItem(i);
+ if (item.isDir()) {
+ visibleDirs.append(i);
+ } else {
+ result.append(i);
+ }
}
+ result.append(visibleDirs);
+
// We need a reasonable upper limit for number of items to resolve after
// and before the visible range. m_maximumVisibleItems can be quite large
// when using Compact View.
diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp
index 8687872ee..d0bcd6ceb 100644
--- a/src/kitemviews/kitemlistcontroller.cpp
+++ b/src/kitemviews/kitemlistcontroller.cpp
@@ -1583,14 +1583,10 @@ bool KItemListController::onRelease(const QPointF& pos, const Qt::KeyboardModifi
Q_EMIT itemExpansionToggleClicked(index);
emitItemActivated = false;
- } else if (shiftOrControlPressed) {
- // The mouse click should only update the selection, not trigger the item
+ } else if (shiftOrControlPressed && m_selectionBehavior != SingleSelection) {
+ // The mouse click should only update the selection, not trigger the item, except when
+ // we are in single selection mode
emitItemActivated = false;
- // When Ctrl-clicking an item when in single selection mode
- // i.e. where Ctrl won't change the selection, pretend it was middle clicked
- if (controlPressed && m_selectionBehavior == SingleSelection) {
- Q_EMIT itemMiddleClicked(index);
- }
} else if (!(m_view->style()->styleHint(QStyle::SH_ItemView_ActivateItemOnSingleClick) || m_singleClickActivationEnforced)) {
if (touch) {
emitItemActivated = true;
diff --git a/src/kitemviews/kitemlistcontroller.h b/src/kitemviews/kitemlistcontroller.h
index 24339134e..f4092576a 100644
--- a/src/kitemviews/kitemlistcontroller.h
+++ b/src/kitemviews/kitemlistcontroller.h
@@ -137,7 +137,7 @@ Q_SIGNALS:
* Is emitted if more than one item has been activated by pressing Return/Enter
* when having a selection.
*/
- void itemsActivated(const KItemSet& indexes);
+ void itemsActivated(const KItemSet &indexes);
void itemMiddleClicked(int index);
diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp
index 5c8c712e8..9492f6a44 100644
--- a/src/kitemviews/kitemlistview.cpp
+++ b/src/kitemviews/kitemlistview.cpp
@@ -2237,11 +2237,11 @@ QHash<QByteArray, qreal> KItemListView::preferredColumnWidths(const KItemRangeLi
const int headerMargin = m_headerWidget->style()->pixelMetric(QStyle::PM_HeaderMargin);
for (const QByteArray& visibleRole : qAsConst(m_visibleRoles)) {
const QString headerText = m_model->roleDescription(visibleRole);
- const qreal headerWidth = fontMetrics.width(headerText) + gripMargin + headerMargin * 2;
+ const qreal headerWidth = fontMetrics.horizontalAdvance(headerText) + gripMargin + headerMargin * 2;
widths.insert(visibleRole, headerWidth);
}
- // Calculate the preferred column withs for each item and ignore values
+ // Calculate the preferred column widths for each item and ignore values
// smaller than the width for showing the headline unclipped.
const KItemListWidgetCreatorBase* creator = widgetCreator();
int calculatedItemCount = 0;
diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h
index 760e0a415..e28487b27 100644
--- a/src/kitemviews/kitemlistview.h
+++ b/src/kitemviews/kitemlistview.h
@@ -597,7 +597,7 @@ private:
/**
* Resizes the column-widths of m_headerWidget based on the preferred widths
- * and the vailable view-size.
+ * and the available view-size.
*/
void applyAutomaticColumnWidths();
@@ -873,7 +873,7 @@ qreal KItemListWidgetCreator<T>::preferredRoleColumnWidth(const QByteArray& role
* @brief Base class for creating KItemListGroupHeaders.
*
* It is recommended that applications simply use the KItemListGroupHeaderCreator-template class.
- * For a custom implementation the methods create() and recyle() must be reimplemented.
+ * For a custom implementation the methods create() and recycle() must be reimplemented.
* The intention of the group-header creator is to prevent repetitive and expensive instantiations and
* deletions of KItemListGroupHeaders by recycling existing header instances.
*/
diff --git a/src/kitemviews/private/kitemlistheaderwidget.cpp b/src/kitemviews/private/kitemlistheaderwidget.cpp
index e5cbc602f..9a7e850a9 100644
--- a/src/kitemviews/private/kitemlistheaderwidget.cpp
+++ b/src/kitemviews/private/kitemlistheaderwidget.cpp
@@ -251,7 +251,7 @@ void KItemListHeaderWidget::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
case NoRoleOperation:
if ((event->pos() - m_pressedMousePos).manhattanLength() >= QApplication::startDragDistance()) {
// A role gets dragged by the user. Create a pixmap of the role that will get
- // synchronized on each furter mouse-move-event with the mouse-position.
+ // synchronized on each further mouse-move-event with the mouse-position.
m_roleOperation = MoveRoleOperation;
const int roleIndex = roleIndexAt(m_pressedMousePos);
m_movingRole.index = roleIndex;
diff --git a/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp b/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp
index 57a954adf..0e6280ede 100644
--- a/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp
+++ b/src/kitemviews/private/kitemlistkeyboardsearchmanager.cpp
@@ -55,7 +55,7 @@ void KItemListKeyboardSearchManager::addKeys(const QString& keys)
const bool searchFromNextItem = (!m_isSearchRestarted && newSearch) || sameKey;
// to remember not to searchFromNextItem if selection was deselected
- // loosing keyboard search context basically
+ // losing keyboard search context basically
m_isSearchRestarted = false;
Q_EMIT changeCurrentItem(sameKey ? firstKey : m_searchedString, searchFromNextItem);
diff --git a/src/org.kde.dolphin.desktop b/src/org.kde.dolphin.desktop
index 1d2f43f64..ad5ee3789 100755
--- a/src/org.kde.dolphin.desktop
+++ b/src/org.kde.dolphin.desktop
@@ -115,6 +115,24 @@ GenericName[zh_TW]=檔案管理員
Terminal=false
MimeType=inode/directory;
InitialPreference=10
+Keywords=files;file management;file browsing;samba;network shares;Explorer;Finder;
+Keywords[az]=fayllar;fayl idarəetməsi;fayl bələdçisi;smaba:şəbəkədə paylaşımlar;Araşdırmaq;Tapmaq;
+Keywords[ca]=fitxers;gestió de fitxers;explorar fitxers;samba;comparticions de xarxa;explorador;cercador;
+Keywords[ca@valencia]=fitxers;gestió de fitxers;explorar fitxers;samba;comparticions de xarxa;explorador;cercador;
+Keywords[es]=archivos;gestión de archivos;administración de archivos;exploración de archivos;samba;recursos compartidos de red;gestor de archivos;administrador de archivos;explorador;buscador;
+Keywords[fr]=fichiers ; gestion de fichiers ; navigation parmi les fichiers ; samba ; partages sur réseau ; explorateur ; chercheur ;
+Keywords[it]=file;gestione dei file;navigazione dei file;samba;condivisioni di rete;Explorer;Finder;
+Keywords[ko]=files;file management;file browsing;samba;network shares;Explorer;Finder;파일;파일 관리;파일 관리자;탐색;탐색기;삼바;네트워크 공유;
+Keywords[nl]=bestanden;bestandsbeheer;bladeren in bestanden;samba;netwerk-shares;verkenner;zoeksysteem;
+Keywords[nn]=filer;filhandsaming;filutforsking;samba;nettverksressursar;Explorer;Finder
+Keywords[pl]=pliki;zarządzenie plikami;przeglądanie plików;samba;udziały sieciowe;Przeglądarka;Finder;
+Keywords[pt_BR]=arquivo;gerenciamento de arquivos;navegação de arquivos;samba;compartilhamentos de rede;explorador;localizador;
+Keywords[sl]=datoteke;upravljanje z datotekami;brskanje po datotekah;samba;mrežni diski;Raziskovalec;Iskalec;
+Keywords[sv]=filer;filhantering;filbläddring;samba;delade nätverksresurser;Utforskare;Finder;
+Keywords[uk]=files;file management;file browsing;samba;network shares;Explorer;Finder;файли;керування файлами;навігація;самба;спільні ресурси;мережа;експлорер;провідник;файндер;
+Keywords[vi]=files;file management;file browsing;samba;network shares;Explorer;Finder;tệp;quản lí tệp;duyệt tệp;chia sẻ mạng;
+Keywords[x-test]=xxfilesxx;xxfile managementxx;xxfile browsingxx;xxsambaxx;xxnetwork sharesxx;xxExplorerxx;xxFinderxx;
+Keywords[zh_CN]=files;file management;file browsing;samba;network shares;文件;文件管理;文件浏览;共享;共享文件夹;网络共享;浏览器;访达;查找器;
X-DBUS-ServiceName=org.kde.dolphin
X-KDE-Shortcuts=Meta+E
StartupWMClass=dolphin
diff --git a/src/panels/folders/folderspanel.cpp b/src/panels/folders/folderspanel.cpp
index 19a05d2b6..d3d8b81f1 100644
--- a/src/panels/folders/folderspanel.cpp
+++ b/src/panels/folders/folderspanel.cpp
@@ -189,7 +189,19 @@ void FoldersPanel::slotItemActivated(int index)
{
const KFileItem item = m_model->fileItem(index);
if (!item.isNull()) {
- Q_EMIT folderActivated(item.url());
+ const auto modifiers = QGuiApplication::keyboardModifiers();
+ // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+ if (modifiers & Qt::ControlModifier && modifiers & Qt::ShiftModifier) {
+ Q_EMIT folderInNewActiveTab(item.url());
+ } else if (modifiers & Qt::ControlModifier) {
+ Q_EMIT folderInNewTab(item.url());
+ } else if (modifiers & Qt::ShiftModifier) {
+ // The shift modifier is not considered because it is used to expand the tree view without actually
+ // opening the folder
+ return;
+ } else {
+ Q_EMIT folderActivated(item.url());
+ }
}
}
@@ -197,7 +209,13 @@ void FoldersPanel::slotItemMiddleClicked(int index)
{
const KFileItem item = m_model->fileItem(index);
if (!item.isNull()) {
- Q_EMIT folderMiddleClicked(item.url());
+ const auto modifiers = QGuiApplication::keyboardModifiers();
+ // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+ if (modifiers & Qt::ShiftModifier) {
+ Q_EMIT folderInNewActiveTab(item.url());
+ } else {
+ Q_EMIT folderInNewTab(item.url());
+ }
}
}
diff --git a/src/panels/folders/folderspanel.h b/src/panels/folders/folderspanel.h
index 26c8e4cb9..3ce7870ff 100644
--- a/src/panels/folders/folderspanel.h
+++ b/src/panels/folders/folderspanel.h
@@ -42,7 +42,8 @@ public:
Q_SIGNALS:
void folderActivated(const QUrl& url);
- void folderMiddleClicked(const QUrl& url);
+ void folderInNewTab(const QUrl &url);
+ void folderInNewActiveTab(const QUrl &url);
void errorMessage(const QString& error);
protected:
diff --git a/src/panels/information/informationpanelcontent.cpp b/src/panels/information/informationpanelcontent.cpp
index 98c012243..bb5f793cd 100644
--- a/src/panels/information/informationpanelcontent.cpp
+++ b/src/panels/information/informationpanelcontent.cpp
@@ -23,9 +23,6 @@
#include <Baloo/FileMetaDataWidget>
-#include <panels/places/placesitem.h>
-#include <panels/places/placesitemmodel.h>
-
#include <Phonon/BackendCapabilities>
#include <Phonon/MediaObject>
@@ -60,7 +57,6 @@ InformationPanelContent::InformationPanelContent(QWidget* parent) :
m_nameLabel(nullptr),
m_metaDataWidget(nullptr),
m_metaDataArea(nullptr),
- m_placesItemModel(nullptr),
m_isVideo(false)
{
parent->installEventFilter(this);
@@ -151,8 +147,6 @@ InformationPanelContent::InformationPanelContent(QWidget* parent) :
layout->addWidget(m_configureButtons);
grabGesture(Qt::TapAndHoldGesture);
-
- m_placesItemModel = new PlacesItemModel(this);
}
InformationPanelContent::~InformationPanelContent()
diff --git a/src/panels/information/informationpanelcontent.h b/src/panels/information/informationpanelcontent.h
index 78fcf3cd0..38383bd41 100644
--- a/src/panels/information/informationpanelcontent.h
+++ b/src/panels/information/informationpanelcontent.h
@@ -17,7 +17,6 @@
class KFileItemList;
class PhononWidget;
class PixmapViewer;
-class PlacesItemModel;
class QPixmap;
class QDialogButtonBox;
class QString;
@@ -151,7 +150,6 @@ private:
QLabel* m_configureLabel;
QDialogButtonBox* m_configureButtons;
- PlacesItemModel* m_placesItemModel;
bool m_isVideo;
};
diff --git a/src/panels/places/placesitem.cpp b/src/panels/places/placesitem.cpp
index 9cac01f91..18f3f006e 100644
--- a/src/panels/places/placesitem.cpp
+++ b/src/panels/places/placesitem.cpp
@@ -264,7 +264,7 @@ QString PlacesItem::generateNewId()
// " (V2)" to indicate that the ID has been generated by
// a new version of the places view.
static int count = 0;
- return QString::number(QDateTime::currentDateTimeUtc().toTime_t()) +
+ return QString::number(QDateTime::currentDateTimeUtc().toSecsSinceEpoch()) +
'/' + QString::number(count++) + " (V2)";
}
diff --git a/src/panels/places/placespanel.cpp b/src/panels/places/placespanel.cpp
index 83e014a82..b9fc4a897 100644
--- a/src/panels/places/placespanel.cpp
+++ b/src/panels/places/placespanel.cpp
@@ -36,6 +36,7 @@
#include <KPropertiesDialog>
#include <QActionGroup>
+#include <QApplication>
#include <QGraphicsSceneDragDropEvent>
#include <QIcon>
#include <QMenu>
@@ -44,16 +45,16 @@
#include <QToolTip>
PlacesPanel::PlacesPanel(QWidget* parent) :
- Panel(parent),
- m_controller(nullptr),
- m_model(nullptr),
- m_view(nullptr),
- m_storageSetupFailedUrl(),
- m_triggerStorageSetupButton(),
- m_itemDropEventIndex(-1),
- m_itemDropEventMimeData(nullptr),
- m_itemDropEvent(nullptr),
- m_tooltipTimer()
+ Panel(parent),
+ m_controller(nullptr),
+ m_model(nullptr),
+ m_view(nullptr),
+ m_storageSetupFailedUrl(),
+ m_triggerStorageSetupModifier(),
+ m_itemDropEventIndex(-1),
+ m_itemDropEventMimeData(nullptr),
+ m_itemDropEvent(nullptr),
+ m_tooltipTimer()
{
m_tooltipTimer.setInterval(500);
m_tooltipTimer.setSingleShot(true);
@@ -163,12 +164,28 @@ bool PlacesPanel::eventFilter(QObject * /* obj */, QEvent *event)
void PlacesPanel::slotItemActivated(int index)
{
- triggerItem(index, Qt::LeftButton);
+ const auto modifiers = QGuiApplication::keyboardModifiers();
+ // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+ if (modifiers & Qt::ControlModifier && modifiers & Qt::ShiftModifier) {
+ triggerItem(index, TriggerItemModifier::ToNewActiveTab);
+ } else if (modifiers & Qt::ControlModifier) {
+ triggerItem(index, TriggerItemModifier::ToNewTab);
+ } else if (modifiers & Qt::ShiftModifier) {
+ triggerItem(index, TriggerItemModifier::ToNewWindow);
+ } else {
+ triggerItem(index, TriggerItemModifier::None);
+ }
}
void PlacesPanel::slotItemMiddleClicked(int index)
{
- triggerItem(index, Qt::MiddleButton);
+ const auto modifiers = QGuiApplication::keyboardModifiers();
+ // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+ if (modifiers & Qt::ShiftModifier) {
+ triggerItem(index, TriggerItemModifier::ToNewActiveTab);
+ } else {
+ triggerItem(index, TriggerItemModifier::ToNewTab);
+ }
}
void PlacesPanel::slotItemContextMenuRequested(int index, const QPointF& pos)
@@ -287,9 +304,7 @@ void PlacesPanel::slotItemContextMenuRequested(int index, const QPointF& pos)
} else if (action == openInNewWindowAction) {
Dolphin::openNewWindow({KFilePlacesModel::convertedUrl(m_model->data(index).value("url").toUrl())}, this);
} else if (action == openInNewTabAction) {
- // TriggerItem does set up the storage first and then it will
- // emit the slotItemMiddleClicked signal, because of Qt::MiddleButton.
- triggerItem(index, Qt::MiddleButton);
+ triggerItem(index, TriggerItemModifier::ToNewTab);
} else if (action == mountAction) {
m_model->requestStorageSetup(index);
} else if (action == teardownAction) {
@@ -480,14 +495,14 @@ void PlacesPanel::slotStorageSetupDone(int index, bool success)
disconnect(m_model, &PlacesItemModel::storageSetupDone,
this, &PlacesPanel::slotStorageSetupDone);
- if (m_triggerStorageSetupButton == Qt::NoButton) {
+ if (m_triggerStorageSetupModifier == TriggerItemModifier::None) {
return;
}
if (success) {
Q_ASSERT(!m_model->storageSetupNeeded(index));
- triggerItem(index, m_triggerStorageSetupButton);
- m_triggerStorageSetupButton = Qt::NoButton;
+ triggerItem(index, m_triggerStorageSetupModifier);
+ m_triggerStorageSetupModifier = TriggerItemModifier::None;
} else {
setUrl(m_storageSetupFailedUrl);
m_storageSetupFailedUrl = QUrl();
@@ -553,7 +568,7 @@ void PlacesPanel::selectItem()
}
}
-void PlacesPanel::triggerItem(int index, Qt::MouseButton button)
+void PlacesPanel::triggerItem(int index, TriggerItemModifier modifier)
{
const PlacesItem* item = m_model->placesItem(index);
if (!item) {
@@ -561,7 +576,7 @@ void PlacesPanel::triggerItem(int index, Qt::MouseButton button)
}
if (m_model->storageSetupNeeded(index)) {
- m_triggerStorageSetupButton = button;
+ m_triggerStorageSetupModifier = modifier;
m_storageSetupFailedUrl = url();
connect(m_model, &PlacesItemModel::storageSetupDone,
@@ -569,14 +584,23 @@ void PlacesPanel::triggerItem(int index, Qt::MouseButton button)
m_model->requestStorageSetup(index);
} else {
- m_triggerStorageSetupButton = Qt::NoButton;
+ m_triggerStorageSetupModifier = TriggerItemModifier::None;
const QUrl url = m_model->data(index).value("url").toUrl();
if (!url.isEmpty()) {
- if (button == Qt::MiddleButton) {
- Q_EMIT placeMiddleClicked(KFilePlacesModel::convertedUrl(url));
- } else {
- Q_EMIT placeActivated(KFilePlacesModel::convertedUrl(url));
+ switch (modifier) {
+ case TriggerItemModifier::ToNewTab:
+ Q_EMIT placeActivatedInNewTab(KFilePlacesModel::convertedUrl(url));
+ break;
+ case TriggerItemModifier::ToNewActiveTab:
+ Q_EMIT placeActivatedInNewActiveTab(KFilePlacesModel::convertedUrl(url));
+ break;
+ case TriggerItemModifier::ToNewWindow:
+ Dolphin::openNewWindow({KFilePlacesModel::convertedUrl(url)}, this);
+ break;
+ case TriggerItemModifier::None:
+ Q_EMIT placeActivated(KFilePlacesModel::convertedUrl(url));
+ break;
}
}
}
diff --git a/src/panels/places/placespanel.h b/src/panels/places/placespanel.h
index 39f8da365..ce28c8c08 100644
--- a/src/panels/places/placespanel.h
+++ b/src/panels/places/placespanel.h
@@ -35,7 +35,8 @@ public:
Q_SIGNALS:
void placeActivated(const QUrl& url);
- void placeMiddleClicked(const QUrl& url);
+ void placeActivatedInNewTab(const QUrl &url);
+ void placeActivatedInNewActiveTab(const QUrl &url);
void errorMessage(const QString& error);
void storageTearDownRequested(const QString& mountPath);
void storageTearDownExternallyRequested(const QString& mountPath);
@@ -64,6 +65,9 @@ private Q_SLOTS:
void slotShowTooltip();
private:
+ enum class TriggerItemModifier { None, ToNewTab, ToNewActiveTab, ToNewWindow };
+
+private:
void addEntry();
void editEntry(int index);
@@ -73,7 +77,7 @@ private:
*/
void selectItem();
- void triggerItem(int index, Qt::MouseButton button);
+ void triggerItem(int index, TriggerItemModifier modifier);
QAction* buildGroupContextMenu(QMenu* menu, int index);
@@ -83,7 +87,7 @@ private:
PlacesView* m_view;
QUrl m_storageSetupFailedUrl;
- Qt::MouseButton m_triggerStorageSetupButton;
+ TriggerItemModifier m_triggerStorageSetupModifier;
int m_itemDropEventIndex;
QMimeData* m_itemDropEventMimeData;
diff --git a/src/panels/terminal/terminalpanel.cpp b/src/panels/terminal/terminalpanel.cpp
index 3af2cdcad..9d30dcd62 100644
--- a/src/panels/terminal/terminalpanel.cpp
+++ b/src/panels/terminal/terminalpanel.cpp
@@ -15,7 +15,6 @@
#include <KMountPoint>
#include <KParts/ReadOnlyPart>
#include <KPluginFactory>
-#include <KPluginLoader>
#include <KProtocolInfo>
#include <KShell>
#include <kde_terminal_interface.h>
@@ -129,8 +128,7 @@ void TerminalPanel::showEvent(QShowEvent* event)
if (!m_terminal) {
m_clearTerminal = true;
- KPluginLoader loader(QStringLiteral("konsolepart"));
- KPluginFactory* factory = loader.factory();
+ KPluginFactory *factory = KPluginFactory::loadFactory(KPluginMetaData(QStringLiteral("konsolepart"))).plugin;
m_konsolePart = factory ? (factory->create<KParts::ReadOnlyPart>(this)) : nullptr;
if (m_konsolePart) {
connect(m_konsolePart, &KParts::ReadOnlyPart::destroyed, this, &TerminalPanel::terminalExited);
diff --git a/src/search/dolphinfacetswidget.cpp b/src/search/dolphinfacetswidget.cpp
index db53d595f..cc125a2d9 100644
--- a/src/search/dolphinfacetswidget.cpp
+++ b/src/search/dolphinfacetswidget.cpp
@@ -235,7 +235,7 @@ void DolphinFacetsWidget::initComboBox(QComboBox* combo)
combo->setFrame(false);
combo->setMinimumHeight(parentWidget()->height());
combo->setCurrentIndex(0);
- connect(combo, QOverload<int>::of(&QComboBox::activated), this, &DolphinFacetsWidget::facetChanged);
+ connect(combo, &QComboBox::activated, this, &DolphinFacetsWidget::facetChanged);
}
void DolphinFacetsWidget::updateTagsSelector()
diff --git a/src/settings/contextmenu/contextmenusettingspage.cpp b/src/settings/contextmenu/contextmenusettingspage.cpp
index 8ebac2e12..cfbfefe52 100644
--- a/src/settings/contextmenu/contextmenusettingspage.cpp
+++ b/src/settings/contextmenu/contextmenusettingspage.cpp
@@ -275,7 +275,7 @@ void ContextMenuSettingsPage::loadServices()
const KService::List entries = KServiceTypeTrader::self()->query(QStringLiteral("KonqPopupMenu/Plugin"));
for (const KService::Ptr &service : entries) {
const QString file = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "kservices5/" % service->entryPath());
- const QList<KServiceAction> serviceActions = KDesktopFileActions::userDefinedServices(file, true);
+ const QList<KServiceAction> serviceActions = KDesktopFileActions::userDefinedServices(KService(file), true);
const KDesktopFile desktopFile(file);
const QString subMenuName = desktopFile.desktopGroup().readEntry("X-KDE-Submenu");
@@ -307,7 +307,7 @@ void ContextMenuSettingsPage::loadServices()
#endif
// Load JSON-based plugins that implement the KFileItemActionPlugin interface
- const auto jsonPlugins = KPluginLoader::findPlugins(QStringLiteral("kf5/kfileitemaction"));
+ const auto jsonPlugins = KPluginMetaData::findPlugins(QStringLiteral("kf5/kfileitemaction"));
for (const auto &jsonMetadata : jsonPlugins) {
const QString desktopEntryName = jsonMetadata.pluginId();
@@ -328,7 +328,7 @@ void ContextMenuSettingsPage::loadVersionControlSystems()
// Create a checkbox for each available version control plugin
QSet<QString> loadedPlugins;
- const QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(QStringLiteral("dolphin/vcs"));
+ const QVector<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("dolphin/vcs"));
for (const auto &plugin : plugins) {
const QString pluginName = plugin.name();
addRow(QStringLiteral("code-class"),
diff --git a/src/settings/dolphinsettingsdialog.cpp b/src/settings/dolphinsettingsdialog.cpp
index 3b7d4b267..d699ef894 100644
--- a/src/settings/dolphinsettingsdialog.cpp
+++ b/src/settings/dolphinsettingsdialog.cpp
@@ -90,7 +90,7 @@ DolphinSettingsDialog::DolphinSettingsDialog(const QUrl& url, QWidget* parent, K
});
KPageWidgetItem* contextMenuSettingsFrame = addPage(contextMenuSettingsPage,
i18nc("@title:group", "Context Menu"));
- contextMenuSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("application-menu")));
+ contextMenuSettingsFrame->setIcon(QIcon::fromTheme(QStringLiteral("preferences-desktop-menu-edit")));
connect(contextMenuSettingsPage, &ContextMenuSettingsPage::changed, this, &DolphinSettingsDialog::enableApply);
// Trash
diff --git a/src/settings/general/configurepreviewplugindialog.cpp b/src/settings/general/configurepreviewplugindialog.cpp
index 26b7deb88..b60ba5a0c 100644
--- a/src/settings/general/configurepreviewplugindialog.cpp
+++ b/src/settings/general/configurepreviewplugindialog.cpp
@@ -11,7 +11,7 @@
#include <KIO/ThumbCreator>
#include <KJobWidgets>
#include <KLocalizedString>
-#include <KPluginLoader>
+#include <QPluginLoader>
#include <QDialogButtonBox>
#include <QPushButton>
@@ -25,7 +25,7 @@ ConfigurePreviewPluginDialog::ConfigurePreviewPluginDialog(const QString& plugin
QDialog(parent)
{
QSharedPointer<ThumbCreator> previewPlugin;
- const QString pluginPath = KPluginLoader::findPlugin(desktopEntryName);
+ const QString pluginPath = QPluginLoader(desktopEntryName).fileName();
if (!pluginPath.isEmpty()) {
newCreator create = (newCreator)QLibrary::resolve(pluginPath, "new_creator");
if (create) {
diff --git a/src/settings/general/previewssettingspage.cpp b/src/settings/general/previewssettingspage.cpp
index 564715ae3..5d176f465 100644
--- a/src/settings/general/previewssettingspage.cpp
+++ b/src/settings/general/previewssettingspage.cpp
@@ -94,8 +94,8 @@ PreviewsSettingsPage::PreviewsSettingsPage(QWidget* parent) :
loadSettings();
connect(m_listView, &QListView::clicked, this, &PreviewsSettingsPage::changed);
- connect(m_localFileSizeBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &PreviewsSettingsPage::changed);
- connect(m_remoteFileSizeBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &PreviewsSettingsPage::changed);
+ connect(m_localFileSizeBox, &QSpinBox::valueChanged, this, &PreviewsSettingsPage::changed);
+ connect(m_remoteFileSizeBox, &QSpinBox::valueChanged, this, &PreviewsSettingsPage::changed);
}
PreviewsSettingsPage::~PreviewsSettingsPage()
diff --git a/src/settings/trash/trashsettingspage.cpp b/src/settings/trash/trashsettingspage.cpp
index df627fa1c..048ee0e9a 100644
--- a/src/settings/trash/trashsettingspage.cpp
+++ b/src/settings/trash/trashsettingspage.cpp
@@ -15,12 +15,12 @@ TrashSettingsPage::TrashSettingsPage(QWidget* parent) :
{
QFormLayout* topLayout = new QFormLayout(this);
- m_proxy = new KCModuleProxy(QStringLiteral("kcmtrash"));
+ m_proxy = new KCModuleProxy(KPluginMetaData(QStringLiteral("kcm_trash")));
topLayout->addRow(m_proxy);
loadSettings();
- connect(m_proxy, QOverload<bool>::of(&KCModuleProxy::changed), this, &TrashSettingsPage::changed);
+ connect(m_proxy, &KCModuleProxy::changed, this, &TrashSettingsPage::changed);
}
TrashSettingsPage::~TrashSettingsPage()
diff --git a/src/settings/viewmodes/dolphinfontrequester.cpp b/src/settings/viewmodes/dolphinfontrequester.cpp
index cb66870af..a4663e94a 100644
--- a/src/settings/viewmodes/dolphinfontrequester.cpp
+++ b/src/settings/viewmodes/dolphinfontrequester.cpp
@@ -27,7 +27,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, QOverload<int>::of(&QComboBox::activated),
+ connect(m_modeCombo, &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 7ea8d5809..1e109aab0 100644
--- a/src/settings/viewmodes/viewsettingstab.cpp
+++ b/src/settings/viewmodes/viewsettingstab.cpp
@@ -112,7 +112,7 @@ ViewSettingsTab::ViewSettingsTab(Mode mode, QWidget* parent) :
sortingModeGroup->addButton(m_sizeOfContents);
m_recursiveDirectorySizeLimit = new QSpinBox();
- connect(m_recursiveDirectorySizeLimit, QOverload<int>::of(&QSpinBox::valueChanged), this, [this](int value) {
+ connect(m_recursiveDirectorySizeLimit, &QSpinBox::valueChanged, this, [this](int value) {
m_recursiveDirectorySizeLimit->setSuffix(i18np(" level deep", " levels deep", value));
});
m_recursiveDirectorySizeLimit->setRange(1, 20);
@@ -155,16 +155,16 @@ ViewSettingsTab::ViewSettingsTab(Mode mode, QWidget* parent) :
switch (m_mode) {
case IconsMode:
- connect(m_widthBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ViewSettingsTab::changed);
- connect(m_maxLinesBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ViewSettingsTab::changed);
+ connect(m_widthBox, &QComboBox::currentIndexChanged, this, &ViewSettingsTab::changed);
+ connect(m_maxLinesBox, &QComboBox::currentIndexChanged, this, &ViewSettingsTab::changed);
break;
case CompactMode:
- connect(m_widthBox, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ViewSettingsTab::changed);
+ connect(m_widthBox, &QComboBox::currentIndexChanged, this, &ViewSettingsTab::changed);
break;
case DetailsMode:
connect(m_expandableFolders, &QCheckBox::toggled, this, &ViewSettingsTab::changed);
#ifndef Q_OS_WIN
- connect(m_recursiveDirectorySizeLimit, QOverload<int>::of(&QSpinBox::valueChanged), this, &ViewSettingsTab::changed);
+ connect(m_recursiveDirectorySizeLimit, &QSpinBox::valueChanged, this, &ViewSettingsTab::changed);
connect(m_numberOfItems, &QRadioButton::toggled, this, &ViewSettingsTab::changed);
connect(m_sizeOfContents, &QRadioButton::toggled, this, [=]() {
m_recursiveDirectorySizeLimit->setEnabled(m_sizeOfContents->isChecked());
diff --git a/src/settings/viewpropertiesdialog.cpp b/src/settings/viewpropertiesdialog.cpp
index 6659d79b6..318c2e1cf 100644
--- a/src/settings/viewpropertiesdialog.cpp
+++ b/src/settings/viewpropertiesdialog.cpp
@@ -150,11 +150,11 @@ ViewPropertiesDialog::ViewPropertiesDialog(DolphinView* dolphinView) :
layout->addRow(QString(), m_showHiddenFiles);
layout->addRow(QString(), m_sortHiddenLast);
- connect(m_viewMode, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ connect(m_viewMode, &QComboBox::currentIndexChanged,
this, &ViewPropertiesDialog::slotViewModeChanged);
- connect(m_sorting, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ connect(m_sorting, &QComboBox::currentIndexChanged,
this, &ViewPropertiesDialog::slotSortingChanged);
- connect(m_sortOrder, QOverload<int>::of(&QComboBox::currentIndexChanged),
+ connect(m_sortOrder, &QComboBox::currentIndexChanged,
this, &ViewPropertiesDialog::slotSortOrderChanged);
connect(m_sortFoldersFirst, &QCheckBox::clicked,
this, &ViewPropertiesDialog::slotSortFoldersFirstChanged);
diff --git a/src/tests/kfileitemmodeltest.cpp b/src/tests/kfileitemmodeltest.cpp
index 7a22a1a7f..679b8ab3a 100644
--- a/src/tests/kfileitemmodeltest.cpp
+++ b/src/tests/kfileitemmodeltest.cpp
@@ -73,6 +73,10 @@ private Q_SLOTS:
void testNameFilter();
void testEmptyPath();
void testRefreshExpandedItem();
+ void testAddItemToFilteredExpandedFolder();
+ void testDeleteItemsWithExpandedFolderWithFilter();
+ void testRefreshItemsWithFilter();
+ void testRefreshExpandedFolderWithFilter();
void testRemoveHiddenItems();
void collapseParentOfHiddenItems();
void removeParentOfHiddenItems();
@@ -516,7 +520,7 @@ void KFileItemModelTest::testExpandItems()
// Test expanding subfolders in a folder with the items "a/", "a/a/", "a/a/1", "a/a-1/", "a/a-1/1".
// Besides testing the basic item expansion functionality, the test makes sure that
// KFileItemModel::expansionLevelsCompare(const KFileItem& a, const KFileItem& b)
- // yields the correct result for "a/a/1" and "a/a-1/", whis is non-trivial because they share the
+ // yields the correct result for "a/a/1" and "a/a-1/", which is non-trivial because they share the
// first three characters.
QSet<QByteArray> originalModelRoles = m_model->roles();
QSet<QByteArray> modelRoles = originalModelRoles;
@@ -1144,6 +1148,219 @@ void KFileItemModelTest::testRefreshExpandedItem()
}
/**
+ * Verifies that adding an item to an expanded folder that's filtered makes the parental chain visible.
+ */
+void KFileItemModelTest::testAddItemToFilteredExpandedFolder()
+{
+ QSignalSpy itemsInsertedSpy(m_model, &KFileItemModel::itemsInserted);
+ QSignalSpy fileItemsChangedSpy(m_model, &KFileItemModel::fileItemsChanged);
+
+ QSet<QByteArray> modelRoles = m_model->roles();
+ modelRoles << "isExpanded" << "isExpandable" << "expandedParentsCount";
+ m_model->setRoles(modelRoles);
+
+ m_testDir->createFile("a/b/file");
+
+ m_model->loadDirectory(m_testDir->url());
+ QVERIFY(itemsInsertedSpy.wait());
+ QCOMPARE(m_model->count(), 1); // "a
+
+ // Expand "a/".
+ m_model->setExpanded(0, true);
+ QVERIFY(itemsInsertedSpy.wait());
+
+ // Expand "a/b/".
+ m_model->setExpanded(1, true);
+ QVERIFY(itemsInsertedSpy.wait());
+
+ QCOMPARE(m_model->count(), 3); // 3 items: "a/", "a/b/", "a/b/file"
+
+ const QUrl urlB = m_model->fileItem(1).url();
+
+ // Set a filter that matches ".txt" extension
+ m_model->setNameFilter("*.txt");
+ QCOMPARE(m_model->count(), 0); // Everything got hidden since we don't have a .txt file yet
+
+ m_model->slotItemsAdded(urlB, KFileItemList() << KFileItem(QUrl("a/b/newItem.txt")));
+ m_model->slotCompleted();
+
+ // Entire parental chain should now be shown
+ QCOMPARE(m_model->count(), 3); // 3 items: "a/", "a/b/", "a/b/newItem.txt"
+ QCOMPARE(itemsInModel(), QStringList() << "a" << "b" << "newItem.txt");
+
+ // Items should be indented in hierarchy
+ QCOMPARE(m_model->expandedParentsCount(0), 0);
+ QCOMPARE(m_model->expandedParentsCount(1), 1);
+ QCOMPARE(m_model->expandedParentsCount(2), 2);
+}
+
+/**
+ * Verifies that deleting the last filter-passing child from expanded folders
+ * makes the parental chain hidden.
+ */
+void KFileItemModelTest::testDeleteItemsWithExpandedFolderWithFilter()
+{
+ QSignalSpy itemsInsertedSpy(m_model, &KFileItemModel::itemsInserted);
+ QSignalSpy itemsRemovedSpy(m_model, &KFileItemModel::itemsRemoved);
+
+ QSet<QByteArray> modelRoles = m_model->roles();
+ modelRoles << "isExpanded" << "isExpandable" << "expandedParentsCount";
+ m_model->setRoles(modelRoles);
+
+ m_testDir->createFile("a/b/file");
+
+ m_model->loadDirectory(m_testDir->url());
+ QVERIFY(itemsInsertedSpy.wait());
+ QCOMPARE(m_model->count(), 1); // "a
+
+ // Expand "a/".
+ m_model->setExpanded(0, true);
+ QVERIFY(itemsInsertedSpy.wait());
+
+ // Expand "a/b/".
+ m_model->setExpanded(1, true);
+ QVERIFY(itemsInsertedSpy.wait());
+
+ QCOMPARE(m_model->count(), 3); // 3 items: "a/", "a/b/", "a/b/file"
+
+ // Set a filter that matches "file" extension
+ m_model->setNameFilter("file");
+ QCOMPARE(m_model->count(), 3); // Everything is still shown
+
+ // Delete "file"
+ QCOMPARE(itemsRemovedSpy.count(), 0);
+ m_model->slotItemsDeleted(KFileItemList() << m_model->fileItem(2));
+ QCOMPARE(itemsRemovedSpy.count(), 1);
+
+ // Entire parental chain should now be filtered
+ QCOMPARE(m_model->count(), 0);
+ QCOMPARE(m_model->m_filteredItems.size(), 2);
+}
+
+/**
+ * Verifies that the fileItemsChanged signal is raised with the correct index after renaming files with filter set.
+ * The rename operation will cause one item to be filtered out and another item to be reordered.
+ */
+void KFileItemModelTest::testRefreshItemsWithFilter()
+{
+ QSignalSpy itemsInsertedSpy(m_model, &KFileItemModel::itemsInserted);
+ QSignalSpy itemsRemovedSpy(m_model, &KFileItemModel::itemsRemoved);
+ QSignalSpy itemsChangedSpy(m_model, &KFileItemModel::itemsChanged);
+ QSignalSpy itemsMovedSpy(m_model, &KFileItemModel::itemsMoved);
+
+ // Creates three .txt files
+ m_testDir->createFiles({"b.txt", "c.txt", "d.txt"});
+
+ m_model->loadDirectory(m_testDir->url());
+ QVERIFY(itemsInsertedSpy.wait());
+
+ QCOMPARE(m_model->count(), 3); // "b.txt", "c.txt", "d.txt"
+
+ // Set a filter that matches ".txt" extension
+ m_model->setNameFilter("*.txt");
+ QCOMPARE(m_model->count(), 3); // Still all items are shown
+ QCOMPARE(itemsInModel(), QStringList() << "b.txt" << "c.txt" << "d.txt");
+
+ // Objects used to rename
+ const KFileItem fileItemC_txt = m_model->fileItem(1);
+ KFileItem fileItemC_cfg = fileItemC_txt;
+ fileItemC_cfg.setUrl(QUrl("c.cfg"));
+
+ const KFileItem fileItemD_txt = m_model->fileItem(2);
+ KFileItem fileItemA_txt = fileItemD_txt;
+ fileItemA_txt.setUrl(QUrl("a.txt"));
+
+ // Rename "c.txt" to "c.cfg"; and rename "d.txt" to "a.txt"
+ QCOMPARE(itemsRemovedSpy.count(), 0);
+ QCOMPARE(itemsChangedSpy.count(), 0);
+ m_model->slotRefreshItems({qMakePair(fileItemC_txt, fileItemC_cfg), qMakePair(fileItemD_txt, fileItemA_txt)});
+ QCOMPARE(itemsRemovedSpy.count(), 1);
+ QCOMPARE(itemsChangedSpy.count(), 1);
+ QCOMPARE(m_model->count(), 2); // Only "a.txt" and "b.txt". "c.cfg" got filtered out
+
+ QList<QVariant> arguments = itemsChangedSpy.takeLast();
+ KItemRangeList itemRangeList = arguments.at(0).value<KItemRangeList>();
+
+ // We started with the order "b.txt", "c.txt", "d.txt"
+ // "d.txt" started with index "2"
+ // "c.txt" got renamed and got filtered out
+ // "d.txt" index shifted from index "2" to "1"
+ // So we expect index "1" in this argument, meaning "d.txt" was renamed
+ QCOMPARE(itemRangeList, KItemRangeList() << KItemRange(1, 1));
+
+ // Re-sorting is done asynchronously:
+ QCOMPARE(itemsInModel(), QStringList() << "b.txt" << "a.txt"); // Files should still be in the incorrect order
+ QVERIFY(itemsMovedSpy.wait());
+ QCOMPARE(itemsInModel(), QStringList() << "a.txt" << "b.txt"); // Files were re-sorted and should now be in the correct order
+}
+
+
+/**
+ * Verifies that parental chains are hidden and shown as needed while their children get filtered/unfiltered due to renaming.
+ * Also verifies that the "isExpanded" and "expandedParentsCount" values are kept for expanded folders that get refreshed.
+ */
+void KFileItemModelTest::testRefreshExpandedFolderWithFilter() {
+ QSignalSpy itemsInsertedSpy(m_model, &KFileItemModel::itemsInserted);
+ QSignalSpy itemsRemovedSpy(m_model, &KFileItemModel::itemsRemoved);
+
+ QSet<QByteArray> modelRoles = m_model->roles();
+ modelRoles << "isExpanded" << "isExpandable" << "expandedParentsCount";
+ m_model->setRoles(modelRoles);
+
+ m_testDir->createFile("a/b/someFolder/someFile");
+
+ m_model->loadDirectory(m_testDir->url());
+ QVERIFY(itemsInsertedSpy.wait());
+
+ QCOMPARE(m_model->count(), 1); // Only "a/"
+
+ // Expand "a/".
+ m_model->setExpanded(0, true);
+ QVERIFY(itemsInsertedSpy.wait());
+
+ // Expand "a/b/".
+ m_model->setExpanded(1, true);
+ QVERIFY(itemsInsertedSpy.wait());
+
+ // Expand "a/b/someFolder/".
+ m_model->setExpanded(2, true);
+ QVERIFY(itemsInsertedSpy.wait());
+ QCOMPARE(m_model->count(), 4); // 4 items: "a/", "a/b/", "a/b/someFolder", "a/b/someFolder/someFile"
+
+ // Set a filter that matches the expanded folder "someFolder"
+ m_model->setNameFilter("someFolder");
+ QCOMPARE(m_model->count(), 3); // 3 items: "a/", "a/b/", "a/b/someFolder"
+
+ // Objects used to rename
+ const KFileItem fileItemA = m_model->fileItem(0);
+ KFileItem fileItemARenamed = fileItemA;
+ fileItemARenamed.setUrl(QUrl("a_renamed"));
+
+ const KFileItem fileItemSomeFolder = m_model->fileItem(2);
+ KFileItem fileItemRenamedFolder = fileItemSomeFolder;
+ fileItemRenamedFolder.setUrl(QUrl("/a_renamed/b/renamedFolder"));
+
+ // Rename "a" to "a_renamed"
+ // This way we test if the algorithm is sane as to NOT hide "a_renamed" since it will have visible children
+ m_model->slotRefreshItems({qMakePair(fileItemA, fileItemARenamed)});
+ QCOMPARE(m_model->count(), 3); // Entire parental chain must still be shown
+ QCOMPARE(itemsInModel(), QStringList() << "a_renamed" << "b" << "someFolder");
+
+ // Rename "a_renamed" back to "a"; and "someFolder" to "renamedFolder"
+ m_model->slotRefreshItems({qMakePair(fileItemARenamed, fileItemA), qMakePair(fileItemSomeFolder, fileItemRenamedFolder)});
+ QCOMPARE(m_model->count(), 0); // Entire parental chain became hidden
+
+ // Rename "renamedFolder" back to "someFolder". Filter is passing again
+ m_model->slotRefreshItems({qMakePair(fileItemRenamedFolder, fileItemSomeFolder)});
+ QCOMPARE(m_model->count(), 3); // Entire parental chain is shown again
+ QCOMPARE(itemsInModel(), QStringList() << "a" << "b" << "someFolder");
+
+ // slotRefreshItems() should preserve "isExpanded" and "expandedParentsCount" values explicitly in this case
+ QCOMPARE(m_model->m_itemData.at(2)->values.value("isExpanded").toBool(), true);
+ QCOMPARE(m_model->m_itemData.at(2)->values.value("expandedParentsCount"), 2);
+}
+
+/**
* Verify that removing hidden files and folders from the model does not
* result in a crash, see https://bugs.kde.org/show_bug.cgi?id=314046
*/
@@ -1298,8 +1515,7 @@ void KFileItemModelTest::removeParentOfHiddenItems()
// Simulate the deletion of the directory "a/b/".
m_model->slotItemsDeleted(KFileItemList() << m_model->fileItem(1));
QCOMPARE(itemsRemovedSpy.count(), 2);
- QCOMPARE(m_model->count(), 1);
- QCOMPARE(itemsInModel(), QStringList() << "a");
+ QCOMPARE(m_model->count(), 0); // "a" will be filtered out since it doesn't pass the filter and doesn't have visible children
// Remove the filter -> only the file "a/1" should appear.
m_model->setNameFilter(QString());
diff --git a/src/tests/testdir.cpp b/src/tests/testdir.cpp
index 51dbdbc58..c05752171 100644
--- a/src/tests/testdir.cpp
+++ b/src/tests/testdir.cpp
@@ -31,7 +31,7 @@ static void setTimeStamp(const QString& path, const QDateTime& mtime)
{
#ifdef Q_OS_UNIX
struct utimbuf utbuf;
- utbuf.actime = mtime.toTime_t();
+ utbuf.actime = mtime.toSecsSinceEpoch();
utbuf.modtime = utbuf.actime;
utime(QFile::encodeName(path), &utbuf);
#elif defined(Q_OS_WIN)
diff --git a/src/trash/dolphintrash.cpp b/src/trash/dolphintrash.cpp
index df8834556..1446ab388 100644
--- a/src/trash/dolphintrash.cpp
+++ b/src/trash/dolphintrash.cpp
@@ -28,7 +28,7 @@ Trash::Trash()
bool isTrashEmpty = m_trashDirLister->items().isEmpty();
Q_EMIT emptinessChanged(isTrashEmpty);
};
- connect(m_trashDirLister, QOverload<>::of(&KCoreDirLister::completed), this, trashDirContentChanged);
+ connect(m_trashDirLister, &KCoreDirLister::completed, this, trashDirContentChanged);
connect(m_trashDirLister, &KDirLister::itemsDeleted, this, trashDirContentChanged);
m_trashDirLister->openUrl(QUrl(QStringLiteral("trash:/")));
}
diff --git a/src/views/dolphinremoteencoding.cpp b/src/views/dolphinremoteencoding.cpp
index 41b3b6890..c7c8b09d1 100644
--- a/src/views/dolphinremoteencoding.cpp
+++ b/src/views/dolphinremoteencoding.cpp
@@ -90,7 +90,7 @@ void DolphinRemoteEncoding::fillMenu()
QMenu* menu = m_menu->menu();
menu->clear();
-
+ menu->addAction(i18n("Default"), this, SLOT(slotDefault()), 0)->setCheckable(true);
for (int i = 0; i < m_encodingDescriptions.size();i++) {
QAction* action = new QAction(m_encodingDescriptions.at(i), this);
action->setCheckable(true);
@@ -100,7 +100,6 @@ void DolphinRemoteEncoding::fillMenu()
menu->addSeparator();
menu->addAction(i18n("Reload"), this, SLOT(slotReload()), 0);
- menu->addAction(i18n("Default"), this, SLOT(slotDefault()), 0)->setCheckable(true);
m_idDefault = m_encodingDescriptions.size() + 2;
connect(menu, &QMenu::triggered, this, &DolphinRemoteEncoding::slotItemSelected);
diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp
index 9a063d857..bb537b982 100644
--- a/src/views/dolphinview.cpp
+++ b/src/views/dolphinview.cpp
@@ -974,12 +974,14 @@ void DolphinView::slotItemActivated(int index)
}
}
-void DolphinView::slotItemsActivated(const KItemSet& indexes)
+void DolphinView::slotItemsActivated(const KItemSet &indexes)
{
Q_ASSERT(indexes.count() >= 2);
abortTwoClicksRenaming();
+ const auto modifiers = QGuiApplication::keyboardModifiers();
+
if (indexes.count() > 5) {
QString question = i18np("Are you sure you want to open 1 item?", "Are you sure you want to open %1 items?", indexes.count());
const int answer = KMessageBox::warningYesNo(this, question);
@@ -995,8 +997,15 @@ void DolphinView::slotItemsActivated(const KItemSet& indexes)
KFileItem item = m_model->fileItem(index);
const QUrl& url = openItemAsFolderUrl(item);
- if (!url.isEmpty()) { // Open folders in new tabs
- Q_EMIT tabRequested(url);
+ if (!url.isEmpty()) {
+ // Open folders in new tabs or in new windows depending on the modifier
+ // The ctrl+shift behavior is ignored because we are handling multiple items
+ // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+ if (modifiers & Qt::ShiftModifier && !(modifiers & Qt::ControlModifier)) {
+ Q_EMIT windowRequested(url);
+ } else {
+ Q_EMIT tabRequested(url);
+ }
} else {
items.append(item);
}
@@ -1013,10 +1022,21 @@ void DolphinView::slotItemMiddleClicked(int index)
{
const KFileItem& item = m_model->fileItem(index);
const QUrl& url = openItemAsFolderUrl(item);
+ const auto modifiers = QGuiApplication::keyboardModifiers();
if (!url.isEmpty()) {
- Q_EMIT tabRequested(url);
+ // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+ if (modifiers & Qt::ShiftModifier) {
+ Q_EMIT activeTabRequested(url);
+ } else {
+ Q_EMIT tabRequested(url);
+ }
} else if (isTabsForFilesEnabled()) {
- Q_EMIT tabRequested(item.url());
+ // keep in sync with KUrlNavigator::slotNavigatorButtonClicked
+ if (modifiers & Qt::ShiftModifier) {
+ Q_EMIT activeTabRequested(item.url());
+ } else {
+ Q_EMIT tabRequested(item.url());
+ }
}
}
diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h
index 75c9dd985..0f288f942 100644
--- a/src/views/dolphinview.h
+++ b/src/views/dolphinview.h
@@ -425,13 +425,13 @@ Q_SIGNALS:
/**
* Is emitted when clicking on an item with the left mouse button.
*/
- void itemActivated(const KFileItem& item);
+ void itemActivated(const KFileItem &item);
/**
* Is emitted when multiple items have been activated by e. g.
* context menu open with.
*/
- void itemsActivated(const KFileItemList& items);
+ void itemsActivated(const KFileItemList &items);
/**
* Is emitted if items have been added or deleted.
@@ -444,6 +444,16 @@ Q_SIGNALS:
void tabRequested(const QUrl& url);
/**
+ * Is emitted if a new tab should be opened for the URL \a url and set as active.
+ */
+ void activeTabRequested(const QUrl &url);
+
+ /**
+ * Is emitted if a new window should be opened for the URL \a url.
+ */
+ void windowRequested(const QUrl &url);
+
+ /**
* Is emitted if the view mode (IconsView, DetailsView,
* PreviewsView) has been changed.
*/
@@ -458,7 +468,7 @@ Q_SIGNALS:
/** Is emitted if the 'grouped sorting' property has been changed. */
void groupedSortingChanged(bool groupedSorting);
- /** Is emmited in reaction to a requestStatusBarText() call.
+ /** Is emitted in reaction to a requestStatusBarText() call.
* @see requestStatusBarText() */
void statusBarTextChanged(QString statusBarText);
@@ -619,7 +629,7 @@ private Q_SLOTS:
void activate();
void slotItemActivated(int index);
- void slotItemsActivated(const KItemSet& indexes);
+ void slotItemsActivated(const KItemSet &indexes);
void slotItemMiddleClicked(int index);
void slotItemContextMenuRequested(int index, const QPointF& pos);
void slotViewContextMenuRequested(const QPointF& pos);
diff --git a/src/views/dolphinviewactionhandler.cpp b/src/views/dolphinviewactionhandler.cpp
index 47247ec35..2e524f8f2 100644
--- a/src/views/dolphinviewactionhandler.cpp
+++ b/src/views/dolphinviewactionhandler.cpp
@@ -213,7 +213,7 @@ void DolphinViewActionHandler::createActions()
viewModeActions->addAction(compactAction);
viewModeActions->addAction(detailsAction);
viewModeActions->setToolBarMode(KSelectAction::MenuMode);
- connect(viewModeActions, QOverload<QAction*>::of(&KSelectAction::triggered), this, &DolphinViewActionHandler::slotViewModeActionTriggered);
+ connect(viewModeActions, &KSelectAction::triggered, this, &DolphinViewActionHandler::slotViewModeActionTriggered);
QAction* zoomInAction = KStandardAction::zoomIn(this,
&DolphinViewActionHandler::zoomIn,
diff --git a/src/views/tooltips/dolphinfilemetadatawidget.cpp b/src/views/tooltips/dolphinfilemetadatawidget.cpp
index b147135bf..e914593fb 100644
--- a/src/views/tooltips/dolphinfilemetadatawidget.cpp
+++ b/src/views/tooltips/dolphinfilemetadatawidget.cpp
@@ -66,7 +66,7 @@ DolphinFileMetaDataWidget::DolphinFileMetaDataWidget(QWidget* parent) :
QHBoxLayout* layout = new QHBoxLayout(this);
layout->addWidget(m_preview);
- layout->addSpacing(layout->margin());
+ layout->addSpacing(layout->contentsMargins().left());
layout->addLayout(textLayout);
}
diff --git a/src/views/versioncontrol/kversioncontrolplugin.h b/src/views/versioncontrol/kversioncontrolplugin.h
index c908be247..d3a39fbd6 100644
--- a/src/views/versioncontrol/kversioncontrolplugin.h
+++ b/src/views/versioncontrol/kversioncontrolplugin.h
@@ -45,7 +45,6 @@ class KFileItem;
* - Add the following lines at the top of fileviewsvnplugin.cpp:
* <code>
* #include <KPluginFactory>
- * #include <KPluginLoader>
* K_PLUGIN_CLASS_WITH_JSON(FileViewSvnPlugin, "fileviewsvnplugin.json")
* </code>
*
@@ -143,8 +142,8 @@ public:
virtual QString fileName() const = 0;
/**
- * Returns the path of the local repository root for the versionned directory
- * Returns an emtpy QString when directory is not part of a working copy
+ * Returns the path of the local repository root for the versioned directory
+ * Returns an empty QString when directory is not part of a working copy
*/
virtual QString localRepositoryRoot(const QString& directory) const;
diff --git a/src/views/versioncontrol/versioncontrolobserver.cpp b/src/views/versioncontrol/versioncontrolobserver.cpp
index 6766aa479..a773aef6b 100644
--- a/src/views/versioncontrol/versioncontrolobserver.cpp
+++ b/src/views/versioncontrol/versioncontrolobserver.cpp
@@ -14,7 +14,6 @@
#include <KLocalizedString>
#include <KPluginFactory>
-#include <KPluginLoader>
#include <KPluginMetaData>
#include <QTimer>
@@ -136,7 +135,7 @@ void VersionControlObserver::slotItemsChanged(const KItemRangeList& itemRanges,
{
Q_UNUSED(itemRanges)
- // Because "version" role is emitted by VCS plugin (ourselfs) we don't need to
+ // Because "version" role is emitted by VCS plugin (ourselves) we don't need to
// analyze it and update directory item states information. So lets check if
// there is only "version".
if ( !(roles.count() == 1 && roles.contains("version")) ) {
@@ -164,7 +163,7 @@ void VersionControlObserver::verifyDirectory()
// by an immediate verification.
m_dirVerificationTimer->setInterval(500);
} else {
- // View was versionned but should not be anymore
+ // View was versioned but should not be anymore
updateItemStates();
}
} else if ((m_plugin = searchPlugin(rootItem.url()))) {
@@ -280,15 +279,13 @@ void VersionControlObserver::initPlugins()
// all fileview version control plugins and remember them in 'plugins'.
const QStringList enabledPlugins = VersionControlSettings::enabledPlugins();
- const QVector<KPluginMetaData> plugins = KPluginLoader::findPlugins(QStringLiteral("dolphin/vcs"));
+ const QVector<KPluginMetaData> plugins = KPluginMetaData::findPlugins(QStringLiteral("dolphin/vcs"));
QSet<QString> loadedPlugins;
for (const auto &p : plugins) {
if (enabledPlugins.contains(p.name())) {
- KPluginLoader loader(p.fileName());
- KPluginFactory *factory = loader.factory();
- KVersionControlPlugin *plugin = factory->create<KVersionControlPlugin>();
+ auto plugin = KPluginFactory::instantiatePlugin<KVersionControlPlugin>(p).plugin;
if (plugin) {
m_plugins.append(plugin);
loadedPlugins += p.name();
diff --git a/src/views/versioncontrol/versioncontrolobserver.h b/src/views/versioncontrol/versioncontrolobserver.h
index 6e3977fb2..064a3088f 100644
--- a/src/views/versioncontrol/versioncontrolobserver.h
+++ b/src/views/versioncontrol/versioncontrolobserver.h
@@ -95,7 +95,7 @@ private Q_SLOTS:
/**
* Is invoked if the thread m_updateItemStatesThread has been finished
- * and applys the item states.
+ * and applies the item states.
*/
void slotThreadFinished();