┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.arcconfig3
-rw-r--r--.gitignore1
-rw-r--r--CMakeLists.txt16
-rw-r--r--doc/index.docbook85
-rw-r--r--doc/preferences-startup.pngbin21970 -> 22072 bytes
-rw-r--r--src/CMakeLists.txt3
-rw-r--r--src/config-packagekit.h.cmake1
-rw-r--r--src/dbusinterface.h4
-rw-r--r--src/dolphinbookmarkhandler.cpp7
-rw-r--r--src/dolphinmainwindow.cpp77
-rw-r--r--src/dolphinpart.cpp11
-rw-r--r--src/dolphinpart_ext.cpp4
-rw-r--r--src/dolphintabwidget.cpp41
-rw-r--r--src/dolphintabwidget.h6
-rw-r--r--src/dolphinui.rc4
-rw-r--r--src/dolphinviewcontainer.cpp29
-rw-r--r--src/dolphinviewcontainer.h7
-rw-r--r--src/global.cpp82
-rw-r--r--src/global.h7
-rw-r--r--src/kitemviews/kfileitemlistwidget.cpp20
-rw-r--r--src/kitemviews/kfileitemmodel.cpp18
-rw-r--r--src/kitemviews/kfileitemmodelrolesupdater.cpp20
-rw-r--r--src/kitemviews/kfileitemmodelrolesupdater.h2
-rw-r--r--src/kitemviews/kitemlistcontroller.cpp2
-rw-r--r--src/kitemviews/kitemlistwidget.cpp1
-rw-r--r--src/kitemviews/private/kdirectorycontentscounter.cpp71
-rw-r--r--src/kitemviews/private/kdirectorycontentscounter.h21
-rw-r--r--src/kitemviews/private/kdirectorycontentscounterworker.cpp100
-rw-r--r--src/kitemviews/private/kdirectorycontentscounterworker.h14
-rw-r--r--src/kitemviews/private/kfileitemmodelfilter.cpp13
-rw-r--r--src/kitemviews/private/kfileitemmodelfilter.h4
-rw-r--r--src/main.cpp31
-rw-r--r--src/org.kde.dolphin.appdata.xml1
-rw-r--r--src/panels/information/informationpanel.cpp2
-rw-r--r--src/panels/information/informationpanelcontent.cpp39
-rw-r--r--src/panels/terminal/org.kde.KIOFuse.VFS.xml13
-rw-r--r--src/panels/terminal/terminalpanel.cpp45
-rw-r--r--src/panels/terminal/terminalpanel.h2
-rw-r--r--src/search/dolphinsearchbox.cpp17
-rw-r--r--src/search/dolphinsearchbox.h5
-rw-r--r--src/settings/dolphin_detailsmodesettings.kcfg8
-rw-r--r--src/settings/dolphin_generalsettings.kcfg4
-rw-r--r--src/settings/kcm/kcmdolphingeneral.cpp22
-rw-r--r--src/settings/kcm/kcmdolphingeneral.h2
-rw-r--r--src/settings/kcm/kcmdolphinnavigation.cpp10
-rw-r--r--src/settings/kcm/kcmdolphinnavigation.h4
-rw-r--r--src/settings/kcm/kcmdolphinservices.cpp8
-rw-r--r--src/settings/kcm/kcmdolphinservices.h2
-rw-r--r--src/settings/kcm/kcmdolphinviewmodes.cpp16
-rw-r--r--src/settings/kcm/kcmdolphinviewmodes.h2
-rw-r--r--src/settings/services/servicemenuinstaller/CMakeLists.txt5
-rw-r--r--src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp147
-rw-r--r--src/settings/services/servicessettingspage.cpp53
-rw-r--r--src/settings/services/servicessettingspage.h14
-rw-r--r--src/settings/startup/startupsettingspage.cpp90
-rw-r--r--src/settings/startup/startupsettingspage.h8
-rw-r--r--src/settings/viewmodes/viewsettingstab.cpp54
-rw-r--r--src/settings/viewmodes/viewsettingstab.h5
-rw-r--r--src/views/dolphinview.cpp58
-rw-r--r--src/views/dolphinview.h33
-rw-r--r--src/views/dolphinviewactionhandler.cpp2
-rw-r--r--src/views/versioncontrol/kversioncontrolplugin.h17
-rw-r--r--src/views/versioncontrol/versioncontrolobserver.cpp36
-rw-r--r--src/views/versioncontrol/versioncontrolobserver.h2
64 files changed, 1034 insertions, 397 deletions
diff --git a/.arcconfig b/.arcconfig
deleted file mode 100644
index 377c7ecb1..000000000
--- a/.arcconfig
+++ /dev/null
@@ -1,3 +0,0 @@
-{
- "phabricator.uri" : "https://phabricator.kde.org/"
-}
diff --git a/.gitignore b/.gitignore
index c48f92390..6c1df4de4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,4 @@ CMakeLists.txt.user
.directory
*.kdev4
/build*/
+.cmake/
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 21bf3e8f2..ee0082a87 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -2,13 +2,13 @@ cmake_minimum_required(VERSION 3.0)
# KDE Application Version, managed by release script
set (RELEASE_SERVICE_VERSION_MAJOR "20")
-set (RELEASE_SERVICE_VERSION_MINOR "04")
-set (RELEASE_SERVICE_VERSION_MICRO "1")
+set (RELEASE_SERVICE_VERSION_MINOR "07")
+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.11.0")
-set(KF5_MIN_VERSION "5.67.0")
+set(KF5_MIN_VERSION "5.70.0")
# ECM setup
find_package(ECM ${KF5_MIN_VERSION} CONFIG REQUIRED)
@@ -77,6 +77,16 @@ set_package_properties(KF5Activities PROPERTIES DESCRIPTION "KActivities librari
find_package(Phonon4Qt5 CONFIG REQUIRED)
+find_package(PackageKitQt5)
+set_package_properties(PackageKitQt5
+ PROPERTIES DESCRIPTION "Software Manager integration"
+ TYPE OPTIONAL
+ PURPOSE "Used in the service menu installer"
+ )
+if(PackageKitQt5_FOUND)
+ set(HAVE_PACKAGEKIT TRUE)
+endif()
+
find_package(KF5Baloo ${KF5_MIN_VERSION})
set_package_properties(KF5Baloo PROPERTIES DESCRIPTION "Baloo Core libraries"
URL "https://www.kde.org"
diff --git a/doc/index.docbook b/doc/index.docbook
index d1342d0d4..344ab8ac0 100644
--- a/doc/index.docbook
+++ b/doc/index.docbook
@@ -70,8 +70,8 @@
<legalnotice>&FDLNotice;</legalnotice>
-<date>2020-03-17</date>
-<releaseinfo>Applications 20.04</releaseinfo>
+<date>2020-05-05</date>
+<releaseinfo>Applications 20.08</releaseinfo>
<abstract>
<para>
@@ -1137,27 +1137,56 @@ This group contains settings which control the appearance of &dolphin; on startu
<itemizedlist>
<listitem><para>
-The <guilabel>Start in</guilabel> folder is the folder which is opened on startup. The
-location of the folder can be entered directly or chosen in a dialog which can
+The <guilabel>Show on startup</guilabel> option allows choosing the folder which is opened on startup.
+</para>
+<para>
+ If the <guimenuitem>Folders, tabs, and window state from last time</guimenuitem> item is selected then
+</para>
+<itemizedlist>
+ <listitem>
+ <para>When launched from the &GUI; or CLI without any &URL;s, &dolphin; restores session</para>
+ </listitem>
+ <listitem>
+ <para>When rebooting with &dolphin; open, it restores session normally after the system comes back</para>
+ </listitem>
+ <listitem>
+ <para>When launched with &URL;s, &dolphin; window is opened showing those &URL;s instead of restoring session</para>
+ </listitem>
+ <listitem>
+ <para>When &dolphin; is already running and a new window is opened, that new window shows a single tab with the same &URL; as was visible in the previously-open &dolphin; instance</para>
+ </listitem>
+</itemizedlist>
+<para>
+The location of the folder can also be entered directly or chosen in a dialog which can
be opened by clicking the button showing a <quote>folder</quote> icon. Moreover,
the current location or the default location (which is the user's home folder)
can be used as the startup folder by clicking the corresponding button.
</para></listitem>
<listitem><para>
-<guilabel>Split view mode</guilabel> controls if the
+<guilabel>Begin in split view mode</guilabel> controls if the
<link linkend="dolphin-view">&dolphin; view</link> is split on startup
-or not.
+or not for new windows.
+</para></listitem>
+
+<listitem><para>
+<guilabel>Show filter bar</guilabel> controls if the filter bar is shown on
+startup or not. See the <link linkend="filter-files">section on the filter bar</link>
+for details.
</para></listitem>
<listitem><para>
-<guilabel>Editable location bar</guilabel> controls if the location bar is in
+<guilabel>Make location bar editable</guilabel> controls if the location bar is in
editable mode on startup. The bread crumb mode of the location bar is used
otherwise. See the <link linkend="location-bar">section about the location bar</link>
for details about the two modes.
</para></listitem>
<listitem><para>
+<guilabel>Open new folders in tabs</guilabel> controls whether &dolphin; should open a new folder in a new tab of the current instance when called externally. If not enabled, the new folders will be opened in new instances of &dolphin;. By default this option is enabled.
+</para></listitem>
+
+<listitem><para>
If <guilabel>Show full path inside location bar</guilabel> is enabled, the full
path of the current location is shown in the bread crumb mode of the location bar.
Otherwise, a shortened version of the path is shown if it begins with the path of
@@ -1165,19 +1194,10 @@ one of the places in the <guilabel>Places</guilabel> panel.
</para></listitem>
<listitem><para>
-<guilabel>Show filter bar</guilabel> controls if the filter bar is shown on
-startup or not. See the <link linkend="filter-files">section on the filter bar</link>
-for details.
-</para></listitem>
-
-<listitem><para>
<guilabel>Show full path in title bar</guilabel> makes it easy to distinguish
between files or folders with the same name in different folders.
</para></listitem>
-<listitem><para>
-<guilabel>Open new folders in tabs</guilabel> controls whether &dolphin; should open a new folder in a new tab of the current instance when called externally. If not enabled, the new folders will be opened in new instances of &dolphin;. By default this option is enabled.
-</para></listitem>
</itemizedlist>
</para>
@@ -1272,7 +1292,11 @@ the text of a file item.
<guilabel>Expandable folders</guilabel> determines whether any folders that have subfolders
are displayed in a tree view, where the sub items can be expanded by &LMB; clicking the
<guiicon>&gt;</guiicon> icon and collapsed by clicking the <guiicon>v</guiicon> icon.
-</para></listitem>
+</para>
+<para>
+<guilabel>Folder size displays</guilabel> allows defining the property to use then sorting folders by their size. It is possible to sort folders by <guilabel>Number of items</guilabel> or <guilabel>Size of contents</guilabel> and choose a limit to the recursive level (can be useful to constrain unneeded iterations in the deep folder structures or on the slow file systems).
+</para>
+</listitem>
</itemizedlist>
</para>
</sect3>
@@ -1708,6 +1732,29 @@ The name of this file has to be entered in a dialog.
<varlistentry>
<term><menuchoice>
<shortcut>
+<keycombo action="simul">&Ctrl;<keycap>F5</keycap></keycombo>
+</shortcut>
+<guimenu>Edit</guimenu>
+<guimenuitem>Copy to inactive split view</guimenuitem>
+</menuchoice></term>
+<listitem><para><action>Copies the currently selected item(s) from the active split view to the inactive split view.</action></para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
+<keycombo action="simul">&Ctrl;<keycap>F6</keycap></keycombo>
+</shortcut>
+<guimenu>Edit</guimenu>
+<guimenuitem>Move to inactive split view</guimenuitem>
+</menuchoice></term>
+<listitem><para><action>Moves the currently selected item(s) from the active split view to the inactive split view.
+Is disabled if the current user does not have write permission on the selected item(s).</action></para></listitem>
+</varlistentry>
+
+<varlistentry>
+<term><menuchoice>
+<shortcut>
<keycombo action="simul">&Ctrl;<keycap>F</keycap></keycombo>
</shortcut>
<guimenu>Edit</guimenu>
@@ -2116,7 +2163,7 @@ project. If you wish to contribute to the documentation please email the
<para>
The official channel for submitting bug reports is via the &kde; bug tracking
system. The &kde; bug tracker can be found at
-<ulink url="http://bugs.kde.org">http://bugs.kde.org</ulink>.
+<ulink url="https://bugs.kde.org">https://bugs.kde.org</ulink>.
</para>
</answer>
</qandaentry>
@@ -2129,7 +2176,7 @@ system. The &kde; bug tracker can be found at
<para>
The official channel for submitting feature requests is via the &kde; bug
tracking system. The &kde; bug tracker can be found at
-<ulink url="http://bugs.kde.org">http://bugs.kde.org</ulink>.
+<ulink url="https://bugs.kde.org">https://bugs.kde.org</ulink>.
</para>
</answer>
diff --git a/doc/preferences-startup.png b/doc/preferences-startup.png
index 2b780a4c1..192efe193 100644
--- a/doc/preferences-startup.png
+++ b/doc/preferences-startup.png
Binary files differ
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 02a43a209..eabe80f61 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -4,6 +4,8 @@ configure_file(config-baloo.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-baloo.h)
configure_file(config-kactivities.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kactivities.h)
+configure_file(config-packagekit.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-packagekit.h)
+
configure_file(config-terminal.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-terminal.h)
add_definitions(
@@ -272,6 +274,7 @@ qt5_add_resources(dolphinstatic_SRCS dolphin.qrc)
qt5_generate_dbus_interface(${CMAKE_CURRENT_SOURCE_DIR}/dolphinmainwindow.h org.kde.DolphinMainWindow.xml)
qt5_add_dbus_adaptor(dolphinstatic_SRCS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.DolphinMainWindow.xml dolphinmainwindow.h DolphinMainWindow)
qt5_add_dbus_interface(dolphinstatic_SRCS ${CMAKE_CURRENT_BINARY_DIR}/org.kde.DolphinMainWindow.xml dolphinmainwindowinterface)
+qt5_add_dbus_interface(dolphinstatic_SRCS panels/terminal/org.kde.KIOFuse.VFS.xml kiofuse_interface)
add_library(dolphinstatic STATIC ${dolphinstatic_SRCS})
diff --git a/src/config-packagekit.h.cmake b/src/config-packagekit.h.cmake
new file mode 100644
index 000000000..780fff56e
--- /dev/null
+++ b/src/config-packagekit.h.cmake
@@ -0,0 +1 @@
+#cmakedefine HAVE_PACKAGEKIT
diff --git a/src/dbusinterface.h b/src/dbusinterface.h
index 391916d62..c1029ea23 100644
--- a/src/dbusinterface.h
+++ b/src/dbusinterface.h
@@ -34,12 +34,12 @@ public:
Q_SCRIPTABLE void ShowItemProperties(const QStringList& uriList, const QString& startUpId);
/**
- * Set whether this interface has been created by dolphin --deamon.
+ * Set whether this interface has been created by dolphin --daemon.
*/
void setAsDaemon();
/**
- * @return Whether this interface has been created by dolphin --deamon.
+ * @return Whether this interface has been created by dolphin --daemon.
*/
bool isDaemon() const;
diff --git a/src/dolphinbookmarkhandler.cpp b/src/dolphinbookmarkhandler.cpp
index ded83d6bb..0d31b8984 100644
--- a/src/dolphinbookmarkhandler.cpp
+++ b/src/dolphinbookmarkhandler.cpp
@@ -21,6 +21,7 @@
#include "dolphinmainwindow.h"
#include "dolphinviewcontainer.h"
#include "global.h"
+#include <KActionCollection>
#include <KBookmarkMenu>
#include <KIO/Global>
#include <QDebug>
@@ -47,7 +48,11 @@ DolphinBookmarkHandler::DolphinBookmarkHandler(DolphinMainWindow *mainWindow,
}
m_bookmarkManager = KBookmarkManager::managerForFile(bookmarksFile, QStringLiteral("dolphin"));
m_bookmarkManager->setUpdate(true);
- m_bookmarkMenu.reset(new KBookmarkMenu(m_bookmarkManager, this, menu, collection));
+ m_bookmarkMenu.reset(new KBookmarkMenu(m_bookmarkManager, this, menu));
+
+ collection->addAction(QStringLiteral("add_bookmark"), m_bookmarkMenu->addBookmarkAction());
+ collection->addAction(QStringLiteral("edit_bookmarks"), m_bookmarkMenu->editBookmarksAction());
+ collection->addAction(QStringLiteral("add_bookmarks_list"), m_bookmarkMenu->bookmarkTabsAsFolderAction());
}
DolphinBookmarkHandler::~DolphinBookmarkHandler()
diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp
index f374db41d..668f511ee 100644
--- a/src/dolphinmainwindow.cpp
+++ b/src/dolphinmainwindow.cpp
@@ -50,9 +50,11 @@
#include <KActionMenu>
#include <KAuthorized>
#include <KConfig>
+#include <KConfigGui>
#include <KDualAction>
#include <KFileItemListProperties>
#include <KHelpMenu>
+#include <KIO/CommandLauncherJob>
#include <KIO/JobUiDelegate>
#include <KIO/OpenFileManagerWindowJob>
#include <KJobWidgets>
@@ -579,6 +581,14 @@ void DolphinMainWindow::closeEvent(QCloseEvent* event)
}
}
+ if (GeneralSettings::rememberOpenedTabs()) {
+ KConfigGui::setSessionConfig(QStringLiteral("dolphin"), QStringLiteral("dolphin"));
+ KConfig *config = KConfigGui::sessionConfig();
+ saveGlobalProperties(config);
+ savePropertiesInternal(config, 1);
+ config->sync();
+ }
+
GeneralSettings::setVersion(CurrentDolphinVersion);
GeneralSettings::self()->save();
@@ -644,12 +654,12 @@ void DolphinMainWindow::undo()
void DolphinMainWindow::cut()
{
- m_activeViewContainer->view()->cutSelectedItems();
+ m_activeViewContainer->view()->cutSelectedItemsToClipboard();
}
void DolphinMainWindow::copy()
{
- m_activeViewContainer->view()->copySelectedItems();
+ m_activeViewContainer->view()->copySelectedItemsToClipboard();
}
void DolphinMainWindow::paste()
@@ -926,7 +936,10 @@ void DolphinMainWindow::compareFiles()
command.append("\" \"");
command.append(urlB.toDisplayString(QUrl::PreferLocalFile));
command.append('\"');
- KRun::runCommand(command, QStringLiteral("Kompare"), QStringLiteral("kompare"), this);
+
+ KIO::CommandLauncherJob *job = new KIO::CommandLauncherJob(command, this);
+ job->setDesktopName(QStringLiteral("org.kde.kompare"));
+ job->start();
}
void DolphinMainWindow::toggleShowMenuBar()
@@ -1136,6 +1149,8 @@ void DolphinMainWindow::updateControlMenu()
// Add "Edit" actions
bool added = addActionToMenu(ac->action(KStandardAction::name(KStandardAction::Undo)), menu) |
+ addActionToMenu(ac->action(QStringLiteral("copy_to_inactive_split_view")), menu) |
+ addActionToMenu(ac->action(QStringLiteral("move_to_inactive_split_view")), menu) |
addActionToMenu(ac->action(KStandardAction::name(KStandardAction::SelectAll)), menu) |
addActionToMenu(ac->action(QStringLiteral("invert_selection")), menu);
@@ -1265,7 +1280,7 @@ void DolphinMainWindow::tabCountChanged(int count)
void DolphinMainWindow::updateWindowTitle()
{
- const QString newTitle = m_activeViewContainer->caption();
+ const QString newTitle = m_activeViewContainer->captionWindowTitle();
if (windowTitle() != newTitle) {
setWindowTitle(newTitle);
}
@@ -1369,6 +1384,24 @@ void DolphinMainWindow::setupActions()
"If the items were added to the clipboard by the <emphasis>Cut</emphasis> "
"action they are removed from their old location.") + cutCopyPastePara);
+ QAction* copyToOtherViewAction = actionCollection()->addAction(QStringLiteral("copy_to_inactive_split_view"));
+ copyToOtherViewAction->setText(i18nc("@action:inmenu", "Copy to inactive split view"));
+ copyToOtherViewAction->setWhatsThis(xi18nc("@info:whatsthis Copy", "This copies the selected items from "
+ "the <emphasis>active</emphasis> view to the inactive split view."));
+ copyToOtherViewAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy")));
+ copyToOtherViewAction->setIconText(i18nc("@action:inmenu Edit", "Copy to inactive split view"));
+ actionCollection()->setDefaultShortcut(copyToOtherViewAction, Qt::SHIFT + Qt::Key_F5 );
+ connect(copyToOtherViewAction, &QAction::triggered, m_tabWidget, &DolphinTabWidget::copyToInactiveSplitView);
+
+ QAction* moveToOtherViewAction = actionCollection()->addAction(QStringLiteral("move_to_inactive_split_view"));
+ moveToOtherViewAction->setText(i18nc("@action:inmenu", "Move to inactive split view"));
+ moveToOtherViewAction->setWhatsThis(xi18nc("@info:whatsthis Move", "This moves the selected items from "
+ "the <emphasis>active</emphasis> view to the inactive split view."));
+ moveToOtherViewAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-cut")));
+ moveToOtherViewAction->setIconText(i18nc("@action:inmenu Edit", "Move to inactive split view"));
+ actionCollection()->setDefaultShortcut(moveToOtherViewAction, Qt::SHIFT + Qt::Key_F6 );
+ connect(moveToOtherViewAction, &QAction::triggered, m_tabWidget, &DolphinTabWidget::moveToInactiveSplitView);
+
QAction *searchAction = KStandardAction::find(this, &DolphinMainWindow::find, actionCollection());
searchAction->setText(i18n("Search..."));
searchAction->setToolTip(i18nc("@info:tooltip", "Search for files and folders"));
@@ -1894,12 +1927,18 @@ void DolphinMainWindow::updateFileAndEditActions()
{
const KFileItemList list = m_activeViewContainer->view()->selectedItems();
const KActionCollection* col = actionCollection();
+ KFileItemListProperties capabilitiesSource(list);
+
QAction* addToPlacesAction = col->action(QStringLiteral("add_to_places"));
+ QAction* copyToOtherViewAction = col->action(QStringLiteral("copy_to_inactive_split_view"));
+ QAction* moveToOtherViewAction = col->action(QStringLiteral("move_to_inactive_split_view"));
if (list.isEmpty()) {
stateChanged(QStringLiteral("has_no_selection"));
addToPlacesAction->setEnabled(true);
+ copyToOtherViewAction->setEnabled(false);
+ moveToOtherViewAction->setEnabled(false);
} else {
stateChanged(QStringLiteral("has_selection"));
@@ -1917,16 +1956,32 @@ void DolphinMainWindow::updateFileAndEditActions()
addToPlacesAction->setEnabled(false);
}
- KFileItemListProperties capabilities(list);
- const bool enableMoveToTrash = capabilities.isLocal() && capabilities.supportsMoving();
+ if (m_tabWidget->currentTabPage()->splitViewEnabled()) {
+ DolphinTabPage* tabPage = m_tabWidget->currentTabPage();
+ KFileItem capabilitiesDestination;
+
+ if (tabPage->primaryViewActive()) {
+ capabilitiesDestination = tabPage->secondaryViewContainer()->url();
+ } else {
+ capabilitiesDestination = tabPage->primaryViewContainer()->url();
+ }
+
+ copyToOtherViewAction->setEnabled(capabilitiesDestination.isWritable());
+ moveToOtherViewAction->setEnabled(capabilitiesSource.supportsMoving() && capabilitiesDestination.isWritable());
+ } else {
+ copyToOtherViewAction->setEnabled(false);
+ moveToOtherViewAction->setEnabled(false);
+ }
+
+ const bool enableMoveToTrash = capabilitiesSource.isLocal() && capabilitiesSource.supportsMoving();
- renameAction->setEnabled(capabilities.supportsMoving());
+ renameAction->setEnabled(capabilitiesSource.supportsMoving());
moveToTrashAction->setEnabled(enableMoveToTrash);
- deleteAction->setEnabled(capabilities.supportsDeleting());
- deleteWithTrashShortcut->setEnabled(capabilities.supportsDeleting() && !enableMoveToTrash);
- cutAction->setEnabled(capabilities.supportsMoving());
+ deleteAction->setEnabled(capabilitiesSource.supportsDeleting());
+ deleteWithTrashShortcut->setEnabled(capabilitiesSource.supportsDeleting() && !enableMoveToTrash);
+ cutAction->setEnabled(capabilitiesSource.supportsMoving());
showTarget->setEnabled(list.length() == 1 && list.at(0).isLink());
- duplicateAction->setEnabled(capabilities.supportsWriting());
+ duplicateAction->setEnabled(capabilitiesSource.supportsWriting());
}
}
diff --git a/src/dolphinpart.cpp b/src/dolphinpart.cpp
index 7e7425121..12c361011 100644
--- a/src/dolphinpart.cpp
+++ b/src/dolphinpart.cpp
@@ -34,6 +34,7 @@
#include <KActionCollection>
#include <KAuthorized>
#include <KConfigGroup>
+#include <KDialogJobUiDelegate>
#include <KFileItemListProperties>
#include <KIconLoader>
#include <KJobWidgets>
@@ -42,7 +43,7 @@
#include <KMimeTypeEditor>
#include <KNS3/KMoreToolsMenuFactory>
#include <KPluginFactory>
-#include <KRun>
+#include <KIO/CommandLauncherJob>
#include <KSharedConfig>
#include <KToolInvocation>
@@ -53,6 +54,7 @@
#include <QInputDialog>
#include <QKeyEvent>
#include <QMenu>
+#include <QRegularExpression>
#include <QStandardPaths>
#include <QTextDocument>
@@ -506,7 +508,7 @@ void DolphinPart::openSelectionDialog(const QString& title, const QString& text,
const QString pattern = QInputDialog::getText(m_view, title, text, QLineEdit::Normal, QStringLiteral("*"), &okClicked);
if (okClicked && !pattern.isEmpty()) {
- QRegExp patternRegExp(pattern, Qt::CaseSensitive, QRegExp::Wildcard);
+ const QRegularExpression patternRegExp(QRegularExpression::wildcardToRegularExpression(pattern));
m_view->selectItems(patternRegExp, selectItems);
}
}
@@ -546,7 +548,10 @@ void DolphinPart::slotFindFile()
if (!(actions.isEmpty())) {
actions.first()->trigger();
} else {
- KRun::run(QStringLiteral("kfind"), {url()}, widget());
+ KIO::CommandLauncherJob *job = new KIO::CommandLauncherJob(QStringLiteral("kfind"), {url().toString()}, this);
+ job->setDesktopName(QStringLiteral("org.kde.kfind"));
+ job->setUiDelegate(new KDialogJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, widget()));
+ job->start();
}
}
diff --git a/src/dolphinpart_ext.cpp b/src/dolphinpart_ext.cpp
index 8c6e9641a..83dfddb16 100644
--- a/src/dolphinpart_ext.cpp
+++ b/src/dolphinpart_ext.cpp
@@ -43,12 +43,12 @@ void DolphinPartBrowserExtension::saveState(QDataStream &stream)
void DolphinPartBrowserExtension::cut()
{
- m_part->view()->cutSelectedItems();
+ m_part->view()->cutSelectedItemsToClipboard();
}
void DolphinPartBrowserExtension::copy()
{
- m_part->view()->copySelectedItems();
+ m_part->view()->copySelectedItemsToClipboard();
}
void DolphinPartBrowserExtension::paste()
diff --git a/src/dolphintabwidget.cpp b/src/dolphintabwidget.cpp
index 89c54baf5..9fd600567 100644
--- a/src/dolphintabwidget.cpp
+++ b/src/dolphintabwidget.cpp
@@ -25,9 +25,9 @@
#include "dolphinviewcontainer.h"
#include <KConfigGroup>
-#include <KRun>
#include <KShell>
#include <kio/global.h>
+#include <KIO/CommandLauncherJob>
#include <KAcceleratorManager>
#include <QApplication>
@@ -320,6 +320,40 @@ void DolphinTabWidget::restoreClosedTab(const QByteArray& state)
currentTabPage()->restoreState(state);
}
+void DolphinTabWidget::copyToInactiveSplitView()
+{
+ const DolphinTabPage* tabPage = tabPageAt(currentIndex());
+ DolphinViewContainer* activeViewContainer = currentTabPage()->activeViewContainer();
+ if (!tabPage->splitViewEnabled() || activeViewContainer->view()->selectedItems().isEmpty()) {
+ return;
+ }
+
+ if (tabPage->primaryViewActive()) {
+ // copy from left panel to right
+ activeViewContainer->view()->copySelectedItemsToInactiveSplitView(activeViewContainer->view()->selectedItems(), tabPage->secondaryViewContainer()->url());
+ } else {
+ // copy from right panel to left
+ activeViewContainer->view()->copySelectedItemsToInactiveSplitView(activeViewContainer->view()->selectedItems(), tabPage->primaryViewContainer()->url());
+ }
+}
+
+void DolphinTabWidget::moveToInactiveSplitView()
+{
+ const DolphinTabPage* tabPage = tabPageAt(currentIndex());
+ DolphinViewContainer* activeViewContainer = currentTabPage()->activeViewContainer();
+ if (!tabPage->splitViewEnabled() || activeViewContainer->view()->selectedItems().isEmpty()) {
+ return;
+ }
+
+ if (tabPage->primaryViewActive()) {
+ // move from left panel to right
+ activeViewContainer->view()->moveSelectedItemsToInactiveSplitView(activeViewContainer->view()->selectedItems(), tabPage->secondaryViewContainer()->url());
+ } else {
+ // move from right panel to left
+ activeViewContainer->view()->moveSelectedItemsToInactiveSplitView(activeViewContainer->view()->selectedItems(), tabPage->primaryViewContainer()->url());
+ }
+}
+
void DolphinTabWidget::detachTab(int index)
{
Q_ASSERT(index >= 0);
@@ -334,8 +368,9 @@ void DolphinTabWidget::detachTab(int index)
}
args << QStringLiteral("--new-window");
- const QString command = QStringLiteral("dolphin %1").arg(KShell::joinArgs(args));
- KRun::runCommand(command, this);
+ KIO::CommandLauncherJob *job = new KIO::CommandLauncherJob("dolphin", args, this);
+ job->setDesktopName(QStringLiteral("org.kde.dolphin"));
+ job->start();
closeTab(index);
}
diff --git a/src/dolphintabwidget.h b/src/dolphintabwidget.h
index 746aec6c6..f0ce11ce8 100644
--- a/src/dolphintabwidget.h
+++ b/src/dolphintabwidget.h
@@ -189,6 +189,12 @@ public slots:
*/
void restoreClosedTab(const QByteArray& state);
+ /** Copies all selected items to the inactive view. */
+ void copyToInactiveSplitView();
+
+ /** Moves all selected items to the inactive view. */
+ void moveToInactiveSplitView();
+
private slots:
/**
* Opens the tab with the index \a index in a new Dolphin instance and closes
diff --git a/src/dolphinui.rc b/src/dolphinui.rc
index e717b67ae..acb2f1dcd 100644
--- a/src/dolphinui.rc
+++ b/src/dolphinui.rc
@@ -1,5 +1,5 @@
<!DOCTYPE kpartgui SYSTEM "kpartgui.dtd">
-<kpartgui name="dolphin" version="30">
+<kpartgui name="dolphin" version="31">
<MenuBar>
<Menu name="file">
<Action name="new_menu" />
@@ -20,6 +20,8 @@
<Action name="properties" />
</Menu>
<Menu name="edit">
+ <Action name="copy_to_inactive_split_view" />
+ <Action name="move_to_inactive_split_view" />
<Action name="edit_select_all" />
<Action name="invert_selection" />
</Menu>
diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp
index 3a17805ab..4ab34a06a 100644
--- a/src/dolphinviewcontainer.cpp
+++ b/src/dolphinviewcontainer.cpp
@@ -29,6 +29,8 @@
#include "trash/dolphintrash.h"
#include "views/viewmodecontroller.h"
#include "views/viewproperties.h"
+#include "dolphin_detailsmodesettings.h"
+#include "views/dolphinview.h"
#ifdef HAVE_KACTIVITIES
#include <KActivities/ResourceInstance>
@@ -119,7 +121,7 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) :
connect(m_searchBox, &DolphinSearchBox::activated, this, &DolphinViewContainer::activate);
connect(m_searchBox, &DolphinSearchBox::closeRequest, this, &DolphinViewContainer::closeSearchBox);
connect(m_searchBox, &DolphinSearchBox::searchRequest, this, &DolphinViewContainer::startSearching);
- connect(m_searchBox, &DolphinSearchBox::returnPressed, this, &DolphinViewContainer::requestFocus);
+ connect(m_searchBox, &DolphinSearchBox::focusViewRequest, this, &DolphinViewContainer::requestFocus);
m_searchBox->setWhatsThis(xi18nc("@info:whatsthis findbar",
"<para>This helps you find files and folders. Enter a <emphasis>"
"search term</emphasis> and specify search settings with the "
@@ -249,6 +251,12 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) :
setSearchModeEnabled(isSearchUrl(url));
+ connect(DetailsModeSettings::self(), &KCoreConfigSkeleton::configChanged, this, [=]() {
+ if (view()->mode() == DolphinView::Mode::DetailsView) {
+ view()->reload();
+ }
+ });
+
// Initialize kactivities resource instance
#ifdef HAVE_KACTIVITIES
@@ -449,6 +457,18 @@ void DolphinViewContainer::reload()
m_messageWidget->hide();
}
+QString DolphinViewContainer::captionWindowTitle() const
+{
+ if (GeneralSettings::showFullPathInTitlebar() && !isSearchModeEnabled()) {
+ if (!url().isLocalFile()) {
+ return url().adjusted(QUrl::StripTrailingSlash).toString();
+ }
+ return url().adjusted(QUrl::StripTrailingSlash).path();
+ } else {
+ return DolphinViewContainer::caption();
+ }
+}
+
QString DolphinViewContainer::caption() const
{
if (isSearchModeEnabled()) {
@@ -459,13 +479,6 @@ QString DolphinViewContainer::caption() const
}
}
- if (GeneralSettings::showFullPathInTitlebar()) {
- if (!url().isLocalFile()) {
- return url().adjusted(QUrl::StripTrailingSlash).toString();
- }
- return url().adjusted(QUrl::StripTrailingSlash).path();
- }
-
KFilePlacesModel *placesModel = DolphinPlacesModelSingleton::instance().placesModel();
const auto& matchedPlaces = placesModel->match(placesModel->index(0,0), KFilePlacesModel::UrlRole, QUrl(url().adjusted(QUrl::StripTrailingSlash).toString(QUrl::FullyEncoded).append("/?")), 1, Qt::MatchRegExp);
diff --git a/src/dolphinviewcontainer.h b/src/dolphinviewcontainer.h
index 5207d2d35..52e63cbe0 100644
--- a/src/dolphinviewcontainer.h
+++ b/src/dolphinviewcontainer.h
@@ -134,6 +134,13 @@ public:
void reload();
/**
+ * @return Returns a Caption suitable for display in the window title.
+ * It is calculated depending on GeneralSettings::showFullPathInTitlebar().
+ * If it's false, it calls caption().
+ */
+ QString captionWindowTitle() const;
+
+ /**
* @return Returns a Caption suitable for display to the user. It is
* calculated depending on settings, if a search is active and other
* factors.
diff --git a/src/global.cpp b/src/global.cpp
index 5236fa4d1..32a2d4ebb 100644
--- a/src/global.cpp
+++ b/src/global.cpp
@@ -23,7 +23,9 @@
#include "dolphindebug.h"
#include "dolphinmainwindowinterface.h"
-#include <KRun>
+#include <KDialogJobUiDelegate>
+#include <KIO/ApplicationLauncherJob>
+#include <KService>
#include <KWindowSystem>
#include <QApplication>
@@ -60,13 +62,11 @@ void Dolphin::openNewWindow(const QList<QUrl> &urls, QWidget *window, const Open
if (!urls.isEmpty()) {
command.append(QLatin1String(" %U"));
}
- KRun::run(
- command,
- urls,
- window,
- QApplication::applicationDisplayName(),
- QApplication::windowIcon().name()
- );
+ KService::Ptr service(new KService(QApplication::applicationDisplayName(), command, QApplication::windowIcon().name()));
+ auto *job = new KIO::ApplicationLauncherJob(service, window);
+ job->setUrls(urls);
+ job->setUiDelegate(new KDialogJobUiDelegate(KJobUiDelegate::AutoHandlingEnabled, window));
+ job->start();
}
bool Dolphin::attachToExistingInstance(const QList<QUrl>& inputUrls, bool openFiles, bool splitView, const QString& preferredService)
@@ -78,36 +78,7 @@ bool Dolphin::attachToExistingInstance(const QList<QUrl>& inputUrls, bool openFi
return false;
}
- QVector<QPair<QSharedPointer<OrgKdeDolphinMainWindowInterface>, QStringList>> dolphinInterfaces;
- if (!preferredService.isEmpty()) {
- QSharedPointer<OrgKdeDolphinMainWindowInterface> preferredInterface(
- new OrgKdeDolphinMainWindowInterface(preferredService,
- QStringLiteral("/dolphin/Dolphin_1"),
- QDBusConnection::sessionBus()));
- if (preferredInterface->isValid() && !preferredInterface->lastError().isValid()) {
- dolphinInterfaces.append(qMakePair(preferredInterface, QStringList()));
- }
- }
-
- // Look for dolphin instances among all available dbus services.
- const QStringList dbusServices = QDBusConnection::sessionBus().interface()->registeredServiceNames().value();
- // Don't match the service without trailing "-" (unique instance)
- const QString pattern = QStringLiteral("org.kde.dolphin-");
- // Don't match the pid without leading "-"
- const QString myPid = QLatin1Char('-') + QString::number(QCoreApplication::applicationPid());
- for (const QString& service : dbusServices) {
- if (service.startsWith(pattern) && !service.endsWith(myPid)) {
- // Check if instance can handle our URLs
- QSharedPointer<OrgKdeDolphinMainWindowInterface> interface(
- new OrgKdeDolphinMainWindowInterface(service,
- QStringLiteral("/dolphin/Dolphin_1"),
- QDBusConnection::sessionBus()));
- if (interface->isValid() && !interface->lastError().isValid()) {
- dolphinInterfaces.append(qMakePair(interface, QStringList()));
- }
- }
- }
-
+ auto dolphinInterfaces = dolphinGuiInstances(preferredService);
if (dolphinInterfaces.isEmpty()) {
return false;
}
@@ -145,3 +116,38 @@ bool Dolphin::attachToExistingInstance(const QList<QUrl>& inputUrls, bool openFi
}
return attached;
}
+
+QVector<QPair<QSharedPointer<OrgKdeDolphinMainWindowInterface>, QStringList>> Dolphin::dolphinGuiInstances(const QString& preferredService)
+{
+ QVector<QPair<QSharedPointer<OrgKdeDolphinMainWindowInterface>, QStringList>> dolphinInterfaces;
+ if (!preferredService.isEmpty()) {
+ QSharedPointer<OrgKdeDolphinMainWindowInterface> preferredInterface(
+ new OrgKdeDolphinMainWindowInterface(preferredService,
+ QStringLiteral("/dolphin/Dolphin_1"),
+ QDBusConnection::sessionBus()));
+ if (preferredInterface->isValid() && !preferredInterface->lastError().isValid()) {
+ dolphinInterfaces.append(qMakePair(preferredInterface, QStringList()));
+ }
+ }
+
+ // Look for dolphin instances among all available dbus services.
+ const QStringList dbusServices = QDBusConnection::sessionBus().interface()->registeredServiceNames().value();
+ // Don't match the service without trailing "-" (unique instance)
+ const QString pattern = QStringLiteral("org.kde.dolphin-");
+ // Don't match the pid without leading "-"
+ const QString myPid = QLatin1Char('-') + QString::number(QCoreApplication::applicationPid());
+ for (const QString& service : dbusServices) {
+ if (service.startsWith(pattern) && !service.endsWith(myPid)) {
+ // Check if instance can handle our URLs
+ QSharedPointer<OrgKdeDolphinMainWindowInterface> interface(
+ new OrgKdeDolphinMainWindowInterface(service,
+ QStringLiteral("/dolphin/Dolphin_1"),
+ QDBusConnection::sessionBus()));
+ if (interface->isValid() && !interface->lastError().isValid()) {
+ dolphinInterfaces.append(qMakePair(interface, QStringList()));
+ }
+ }
+ }
+
+ return dolphinInterfaces;
+}
diff --git a/src/global.h b/src/global.h
index 7ee564581..daf86134e 100644
--- a/src/global.h
+++ b/src/global.h
@@ -24,6 +24,8 @@
#include <QUrl>
#include <QWidget>
+class OrgKdeDolphinMainWindowInterface;
+
namespace Dolphin {
QList<QUrl> validateUris(const QStringList& uriList);
@@ -52,6 +54,11 @@ namespace Dolphin {
bool attachToExistingInstance(const QList<QUrl>& inputUrls, bool openFiles, bool splitView, const QString& preferredService = QString());
/**
+ * Returns a QVector with all GUI-capable Dolphin instances
+ */
+ QVector<QPair<QSharedPointer<OrgKdeDolphinMainWindowInterface>, QStringList>> dolphinGuiInstances(const QString& preferredService);
+
+ /**
* TODO: Move this somewhere global to all KDE apps, not just Dolphin
*/
const int VERTICAL_SPACER_HEIGHT = 18;
diff --git a/src/kitemviews/kfileitemlistwidget.cpp b/src/kitemviews/kfileitemlistwidget.cpp
index 40b8ccf37..a495a4c2f 100644
--- a/src/kitemviews/kfileitemlistwidget.cpp
+++ b/src/kitemviews/kfileitemlistwidget.cpp
@@ -21,6 +21,8 @@
#include "kfileitemmodel.h"
#include "kitemlistview.h"
+#include "dolphin_detailsmodesettings.h"
+
#include <KFormat>
#include <KLocalizedString>
@@ -64,14 +66,24 @@ QString KFileItemListWidgetInformant::roleText(const QByteArray& role,
if (role == "size") {
if (values.value("isDir").toBool()) {
- // The item represents a directory. Show the number of sub directories
- // instead of the file size of the directory.
+ // The item represents a directory.
if (!roleValue.isNull()) {
- const int count = roleValue.toInt();
+ const int count = values.value("count").toInt();
if (count < 0) {
text = i18nc("@item:intable", "Unknown");
} else {
- text = i18ncp("@item:intable", "%1 item", "%1 items", count);
+ if (DetailsModeSettings::directorySizeCount()) {
+ // Show the number of sub directories instead of the file size of the directory.
+ text = i18ncp("@item:intable", "%1 item", "%1 items", count);
+ } else {
+ // if we have directory size available
+ if (roleValue == -1) {
+ text = i18nc("@item:intable", "Unknown");
+ } else {
+ const KIO::filesize_t size = roleValue.value<KIO::filesize_t>();
+ text = KFormat().formatByteSize(size);
+ }
+ }
}
}
} else {
diff --git a/src/kitemviews/kfileitemmodel.cpp b/src/kitemviews/kfileitemmodel.cpp
index e4dca2734..ac3c33e22 100644
--- a/src/kitemviews/kfileitemmodel.cpp
+++ b/src/kitemviews/kfileitemmodel.cpp
@@ -22,6 +22,7 @@
#include "kfileitemmodel.h"
#include "dolphin_generalsettings.h"
+#include "dolphin_detailsmodesettings.h"
#include "dolphindebug.h"
#include "private/kfileitemmodeldirlister.h"
#include "private/kfileitemmodelsortalgorithm.h"
@@ -1767,8 +1768,15 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const
// See "if (m_sortFoldersFirst || m_sortRole == SizeRole)" in KFileItemModel::lessThan():
Q_ASSERT(itemB.isDir());
- const QVariant valueA = a->values.value("size");
- const QVariant valueB = b->values.value("size");
+ QVariant valueA, valueB;
+ if (DetailsModeSettings::directorySizeCount()) {
+ valueA = a->values.value("count");
+ valueB = b->values.value("count");
+ } else {
+ // use dir size then
+ valueA = a->values.value("size");
+ valueB = b->values.value("size");
+ }
if (valueA.isNull() && valueB.isNull()) {
result = 0;
} else if (valueA.isNull()) {
@@ -1776,7 +1784,11 @@ int KFileItemModel::sortRoleCompare(const ItemData* a, const ItemData* b, const
} else if (valueB.isNull()) {
result = +1;
} else {
- result = valueA.toInt() - valueB.toInt();
+ if (valueA < valueB) {
+ return -1;
+ } else {
+ return +1;
+ }
}
} else {
// See "if (m_sortFoldersFirst || m_sortRole == SizeRole)" in KFileItemModel::lessThan():
diff --git a/src/kitemviews/kfileitemmodelrolesupdater.cpp b/src/kitemviews/kfileitemmodelrolesupdater.cpp
index bf2c84c40..c28e240a5 100644
--- a/src/kitemviews/kfileitemmodelrolesupdater.cpp
+++ b/src/kitemviews/kfileitemmodelrolesupdater.cpp
@@ -44,7 +44,6 @@
#include <QElapsedTimer>
#include <QTimer>
-
// #define KFILEITEMMODELROLESUPDATER_DEBUG
namespace {
@@ -108,9 +107,9 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO
this, &KFileItemModelRolesUpdater::slotSortRoleChanged);
// Use a timer to prevent that each call of slotItemsChanged() results in a synchronous
- // resolving of the roles. Postpone the resolving until no update has been done for 1 second.
+ // resolving of the roles. Postpone the resolving until no update has been done for 100 ms.
m_recentlyChangedItemsTimer = new QTimer(this);
- m_recentlyChangedItemsTimer->setInterval(1000);
+ m_recentlyChangedItemsTimer->setInterval(100);
m_recentlyChangedItemsTimer->setSingleShot(true);
connect(m_recentlyChangedItemsTimer, &QTimer::timeout, this, &KFileItemModelRolesUpdater::resolveRecentlyChangedItems);
@@ -750,7 +749,7 @@ void KFileItemModelRolesUpdater::applyChangedBalooRolesForItem(const KFileItem &
#endif
}
-void KFileItemModelRolesUpdater::slotDirectoryContentsCountReceived(const QString& path, int count)
+void KFileItemModelRolesUpdater::slotDirectoryContentsCountReceived(const QString& path, int count, long size)
{
const bool getSizeRole = m_roles.contains("size");
const bool getIsExpandableRole = m_roles.contains("isExpandable");
@@ -761,17 +760,16 @@ void KFileItemModelRolesUpdater::slotDirectoryContentsCountReceived(const QStrin
QHash<QByteArray, QVariant> data;
if (getSizeRole) {
- data.insert("size", count);
+ data.insert("count", count);
+ if (size != -1) {
+ data.insert("size", QVariant::fromValue(size));
+ }
}
if (getIsExpandableRole) {
data.insert("isExpandable", count > 0);
}
- disconnect(m_model, &KFileItemModel::itemsChanged,
- this, &KFileItemModelRolesUpdater::slotItemsChanged);
m_model->setData(index, data);
- connect(m_model, &KFileItemModel::itemsChanged,
- this, &KFileItemModelRolesUpdater::slotItemsChanged);
}
}
}
@@ -997,7 +995,7 @@ void KFileItemModelRolesUpdater::applySortRole(int index)
data.insert("type", item.mimeComment());
} else if (m_model->sortRole() == "size" && item.isLocalFile() && item.isDir()) {
const QString path = item.localPath();
- data.insert("size", m_directoryContentsCounter->countDirectoryContentsSynchronously(path));
+ m_directoryContentsCounter->scanDirectory(path);
} else {
// Probably the sort role is a baloo role - just determine all roles.
data = rolesData(item);
@@ -1070,7 +1068,7 @@ QHash<QByteArray, QVariant> KFileItemModelRolesUpdater::rolesData(const KFileIte
// Tell m_directoryContentsCounter that we want to count the items
// inside the directory. The result will be received in slotDirectoryContentsCountReceived.
const QString path = item.localPath();
- m_directoryContentsCounter->addDirectory(path);
+ m_directoryContentsCounter->scanDirectory(path);
} else if (getSizeRole) {
data.insert("size", -1); // -1 indicates an unknown number of items
}
diff --git a/src/kitemviews/kfileitemmodelrolesupdater.h b/src/kitemviews/kfileitemmodelrolesupdater.h
index 9078c8e0d..e21cd30df 100644
--- a/src/kitemviews/kfileitemmodelrolesupdater.h
+++ b/src/kitemviews/kfileitemmodelrolesupdater.h
@@ -212,7 +212,7 @@ private slots:
void applyChangedBalooRoles(const QString& file);
void applyChangedBalooRolesForItem(const KFileItem& file);
- void slotDirectoryContentsCountReceived(const QString& path, int count);
+ void slotDirectoryContentsCountReceived(const QString& path, int count, long size);
private:
/**
diff --git a/src/kitemviews/kitemlistcontroller.cpp b/src/kitemviews/kitemlistcontroller.cpp
index 5ddf52e5f..0c25ebb8b 100644
--- a/src/kitemviews/kitemlistcontroller.cpp
+++ b/src/kitemviews/kitemlistcontroller.cpp
@@ -1219,7 +1219,7 @@ void KItemListController::startDragging()
const QPoint hotSpot((pixmap.width() / pixmap.devicePixelRatio()) / 2, 0);
drag->setHotSpot(hotSpot);
- drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::CopyAction);
+ drag->exec(Qt::MoveAction | Qt::CopyAction | Qt::LinkAction, Qt::MoveAction);
QAccessibleEvent accessibilityEvent(view(), QAccessible::DragDropStart);
QAccessible::updateAccessibility(&accessibilityEvent);
diff --git a/src/kitemviews/kitemlistwidget.cpp b/src/kitemviews/kitemlistwidget.cpp
index 49a13f68f..42bf9ebdc 100644
--- a/src/kitemviews/kitemlistwidget.cpp
+++ b/src/kitemviews/kitemlistwidget.cpp
@@ -378,7 +378,6 @@ QPixmap KItemListWidget::createDragPixmap(const QStyleOptionGraphicsItem* option
const bool wasHovered = m_hovered;
setAlternateBackground(false);
- setSelected(false);
setHovered(false);
paint(&painter, option, widget);
diff --git a/src/kitemviews/private/kdirectorycontentscounter.cpp b/src/kitemviews/private/kdirectorycontentscounter.cpp
index bd204fe8e..a19bce8b3 100644
--- a/src/kitemviews/private/kdirectorycontentscounter.cpp
+++ b/src/kitemviews/private/kdirectorycontentscounter.cpp
@@ -24,8 +24,14 @@
#include <KDirWatch>
#include <QFileInfo>
+#include <QDir>
#include <QThread>
+namespace {
+ /// cache of directory counting result
+ static QHash<QString, QPair<int, long>> *s_cache;
+}
+
KDirectoryContentsCounter::KDirectoryContentsCounter(KFileItemModel* model, QObject* parent) :
QObject(parent),
m_model(model),
@@ -43,9 +49,12 @@ KDirectoryContentsCounter::KDirectoryContentsCounter(KFileItemModel* model, QObj
m_workerThread->start();
}
+ if (s_cache == nullptr) {
+ s_cache = new QHash<QString, QPair<int, long>>();
+ }
+
m_worker = new KDirectoryContentsCounterWorker();
m_worker->moveToThread(m_workerThread);
- ++m_workersCount;
connect(this, &KDirectoryContentsCounter::requestDirectoryContentsCount,
m_worker, &KDirectoryContentsCounterWorker::countDirectoryContents);
@@ -58,9 +67,7 @@ KDirectoryContentsCounter::KDirectoryContentsCounter(KFileItemModel* model, QObj
KDirectoryContentsCounter::~KDirectoryContentsCounter()
{
- --m_workersCount;
-
- if (m_workersCount > 0) {
+ if (m_workerThread->isRunning()) {
// The worker thread will continue running. It could even be running
// a method of m_worker at the moment, so we delete it using
// deleteLater() to prevent a crash.
@@ -79,38 +86,17 @@ KDirectoryContentsCounter::~KDirectoryContentsCounter()
}
}
-void KDirectoryContentsCounter::addDirectory(const QString& path)
+void KDirectoryContentsCounter::scanDirectory(const QString& path)
{
startWorker(path);
}
-int KDirectoryContentsCounter::countDirectoryContentsSynchronously(const QString& path)
-{
- const QString resolvedPath = QFileInfo(path).canonicalFilePath();
-
- if (!m_dirWatcher->contains(resolvedPath)) {
- m_dirWatcher->addDir(resolvedPath);
- m_watchedDirs.insert(resolvedPath);
- }
-
- KDirectoryContentsCounterWorker::Options options;
-
- if (m_model->showHiddenFiles()) {
- options |= KDirectoryContentsCounterWorker::CountHiddenFiles;
- }
-
- if (m_model->showDirectoriesOnly()) {
- options |= KDirectoryContentsCounterWorker::CountDirectoriesOnly;
- }
-
- return KDirectoryContentsCounterWorker::subItemsCount(path, options);
-}
-
-void KDirectoryContentsCounter::slotResult(const QString& path, int count)
+void KDirectoryContentsCounter::slotResult(const QString& path, int count, long size)
{
m_workerIsBusy = false;
- const QString resolvedPath = QFileInfo(path).canonicalFilePath();
+ const QFileInfo info = QFileInfo(path);
+ const QString resolvedPath = info.canonicalFilePath();
if (!m_dirWatcher->contains(resolvedPath)) {
m_dirWatcher->addDir(resolvedPath);
@@ -121,7 +107,22 @@ void KDirectoryContentsCounter::slotResult(const QString& path, int count)
startWorker(m_queue.dequeue());
}
- emit result(path, count);
+ if (s_cache->contains(resolvedPath)) {
+ const auto pair = s_cache->value(resolvedPath);
+ if (pair.first == count && pair.second == size) {
+ // no change no need to send another result event
+ return;
+ }
+ }
+
+ if (info.dir().path() == m_model->rootItem().url().path()) {
+ // update cache or overwrite value
+ // when path is a direct children of the current model root
+ s_cache->insert(resolvedPath, QPair<int, long>(count, size));
+ }
+
+ // sends the results
+ emit result(resolvedPath, count, size);
}
void KDirectoryContentsCounter::slotDirWatchDirty(const QString& path)
@@ -146,7 +147,7 @@ void KDirectoryContentsCounter::slotItemsRemoved()
if (!m_watchedDirs.isEmpty()) {
// Don't let KDirWatch watch for removed items
if (allItemsRemoved) {
- foreach (const QString& path, m_watchedDirs) {
+ for (const QString& path : qAsConst(m_watchedDirs)) {
m_dirWatcher->removeDir(path);
}
m_watchedDirs.clear();
@@ -166,6 +167,13 @@ void KDirectoryContentsCounter::slotItemsRemoved()
void KDirectoryContentsCounter::startWorker(const QString& path)
{
+ if (s_cache->contains(path)) {
+ // fast path when in cache
+ // will be updated later if result has changed
+ const auto pair = s_cache->value(path);
+ emit result(path, pair.first, pair.second);
+ }
+
if (m_workerIsBusy) {
m_queue.enqueue(path);
} else {
@@ -185,4 +193,3 @@ void KDirectoryContentsCounter::startWorker(const QString& path)
}
QThread* KDirectoryContentsCounter::m_workerThread = nullptr;
-int KDirectoryContentsCounter::m_workersCount = 0;
diff --git a/src/kitemviews/private/kdirectorycontentscounter.h b/src/kitemviews/private/kdirectorycontentscounter.h
index 349860757..0c900ec64 100644
--- a/src/kitemviews/private/kdirectorycontentscounter.h
+++ b/src/kitemviews/private/kdirectorycontentscounter.h
@@ -25,6 +25,7 @@
#include <QQueue>
#include <QSet>
+#include <QHash>
class KDirWatch;
class KFileItemModel;
@@ -45,28 +46,23 @@ public:
*
* The directory \a path is watched for changes, and the signal is emitted
* again if a change occurs.
- */
- void addDirectory(const QString& path);
-
- /**
- * In contrast to \a addDirectory, this function counts the items inside
- * the directory \a path synchronously and returns the result.
*
- * The directory is watched for changes, and the signal \a result is
- * emitted if a change occurs.
+ * Uses a cache internally to speed up first result,
+ * but emit again result when the cache was updated
*/
- int countDirectoryContentsSynchronously(const QString& path);
+ void scanDirectory(const QString& path);
signals:
/**
- * Signals that the directory \a path contains \a count items.
+ * Signals that the directory \a path contains \a count items of size \a
+ * Size calculation depends on parameter DetailsModeSettings::recursiveDirectorySizeLimit
*/
- void result(const QString& path, int count);
+ void result(const QString& path, int count, long size);
void requestDirectoryContentsCount(const QString& path, KDirectoryContentsCounterWorker::Options options);
private slots:
- void slotResult(const QString& path, int count);
+ void slotResult(const QString& path, int count, long size);
void slotDirWatchDirty(const QString& path);
void slotItemsRemoved();
@@ -79,7 +75,6 @@ private:
QQueue<QString> m_queue;
static QThread* m_workerThread;
- static int m_workersCount;
KDirectoryContentsCounterWorker* m_worker;
bool m_workerIsBusy;
diff --git a/src/kitemviews/private/kdirectorycontentscounterworker.cpp b/src/kitemviews/private/kdirectorycontentscounterworker.cpp
index e9c954ed9..1e4a0b3b4 100644
--- a/src/kitemviews/private/kdirectorycontentscounterworker.cpp
+++ b/src/kitemviews/private/kdirectorycontentscounterworker.cpp
@@ -22,44 +22,34 @@
// Required includes for subItemsCount():
#ifdef Q_OS_WIN
- #include <QDir>
+#include <QDir>
#else
- #include <QFile>
- #include <qplatformdefs.h>
+#include <QFile>
+#include <qplatformdefs.h>
#endif
+#include "dolphin_detailsmodesettings.h"
+
KDirectoryContentsCounterWorker::KDirectoryContentsCounterWorker(QObject* parent) :
QObject(parent)
{
qRegisterMetaType<KDirectoryContentsCounterWorker::Options>();
}
-int KDirectoryContentsCounterWorker::subItemsCount(const QString& path, Options options)
+#ifndef Q_OS_WIN
+KDirectoryContentsCounterWorker::CountResult walkDir(const QString &dirPath,
+ const bool countHiddenFiles,
+ const bool countDirectoriesOnly,
+ QT_DIRENT *dirEntry,
+ const uint allowedRecursiveLevel)
{
- const bool countHiddenFiles = options & CountHiddenFiles;
- const bool countDirectoriesOnly = options & CountDirectoriesOnly;
-
-#ifdef Q_OS_WIN
- QDir dir(path);
- QDir::Filters filters = QDir::NoDotAndDotDot | QDir::System;
- if (countHiddenFiles) {
- filters |= QDir::Hidden;
- }
- if (countDirectoriesOnly) {
- filters |= QDir::Dirs;
- } else {
- filters |= QDir::AllEntries;
- }
- return dir.entryList(filters).count();
-#else
- // Taken from kio/src/widgets/kdirmodel.cpp
- // Copyright (C) 2006 David Faure <[email protected]>
-
int count = -1;
- auto dir = QT_OPENDIR(QFile::encodeName(path));
+ long size = -1;
+ auto dir = QT_OPENDIR(QFile::encodeName(dirPath));
if (dir) {
count = 0;
- QT_DIRENT *dirEntry = nullptr;
+ QT_STATBUF buf;
+
while ((dirEntry = QT_READDIR(dir))) {
if (dirEntry->d_name[0] == '.') {
if (dirEntry->d_name[1] == '\0' || !countHiddenFiles) {
@@ -76,20 +66,70 @@ int KDirectoryContentsCounterWorker::subItemsCount(const QString& path, Options
// as directory instead of trying to do an expensive stat()
// (see bugs 292642 and 299997).
const bool countEntry = !countDirectoriesOnly ||
- dirEntry->d_type == DT_DIR ||
- dirEntry->d_type == DT_LNK ||
- dirEntry->d_type == DT_UNKNOWN;
+ dirEntry->d_type == DT_DIR ||
+ dirEntry->d_type == DT_LNK ||
+ dirEntry->d_type == DT_UNKNOWN;
if (countEntry) {
++count;
}
+
+ if (allowedRecursiveLevel > 0) {
+
+ bool linkFound = false;
+ QString nameBuf = QStringLiteral("%1/%2").arg(dirPath, dirEntry->d_name);
+
+ if (dirEntry->d_type == DT_REG || dirEntry->d_type == DT_LNK) {
+ if (QT_STAT(nameBuf.toLocal8Bit(), &buf) == 0) {
+ if (S_ISDIR(buf.st_mode)) {
+ // was a dir link, recurse
+ linkFound = true;
+ }
+ size += buf.st_size;
+ }
+ }
+ if (dirEntry->d_type == DT_DIR || linkFound) {
+ // recursion for dirs and dir links
+ size += walkDir(nameBuf, countHiddenFiles, countDirectoriesOnly, dirEntry, allowedRecursiveLevel - 1).size;
+ }
+ }
}
QT_CLOSEDIR(dir);
}
- return count;
+ return KDirectoryContentsCounterWorker::CountResult{count, size};
+}
+#endif
+
+KDirectoryContentsCounterWorker::CountResult KDirectoryContentsCounterWorker::subItemsCount(const QString& path, Options options)
+{
+ const bool countHiddenFiles = options & CountHiddenFiles;
+ const bool countDirectoriesOnly = options & CountDirectoriesOnly;
+
+#ifdef Q_OS_WIN
+ QDir dir(path);
+ QDir::Filters filters = QDir::NoDotAndDotDot | QDir::System;
+ if (countHiddenFiles) {
+ filters |= QDir::Hidden;
+ }
+ if (countDirectoriesOnly) {
+ filters |= QDir::Dirs;
+ } else {
+ filters |= QDir::AllEntries;
+ }
+ return {dir.entryList(filters).count(), 0};
+#else
+
+ const uint maxRecursiveLevel = DetailsModeSettings::directorySizeCount() ? 1 : DetailsModeSettings::recursiveDirectorySizeLimit();
+
+ QT_DIRENT *dirEntry = nullptr;
+
+ auto res = walkDir(QFile::encodeName(path), countHiddenFiles, countDirectoriesOnly, dirEntry, maxRecursiveLevel);
+
+ return res;
#endif
}
void KDirectoryContentsCounterWorker::countDirectoryContents(const QString& path, Options options)
{
- emit result(path, subItemsCount(path, options));
+ auto res = subItemsCount(path, options);
+ emit result(path, res.count, res.size);
}
diff --git a/src/kitemviews/private/kdirectorycontentscounterworker.h b/src/kitemviews/private/kdirectorycontentscounterworker.h
index b40da6e87..fac9978d5 100644
--- a/src/kitemviews/private/kdirectorycontentscounterworker.h
+++ b/src/kitemviews/private/kdirectorycontentscounterworker.h
@@ -37,6 +37,14 @@ public:
};
Q_DECLARE_FLAGS(Options, Option)
+ struct CountResult {
+ /// number of elements in the directory
+ int count;
+ /// Recursive sum of the size of the directory content files and folders
+ /// Calculation depends on DetailsModeSettings::recursiveDirectorySizeLimit
+ long size;
+ };
+
explicit KDirectoryContentsCounterWorker(QObject* parent = nullptr);
/**
@@ -45,13 +53,13 @@ public:
*
* @return The number of items.
*/
- static int subItemsCount(const QString& path, Options options);
+ static CountResult subItemsCount(const QString& path, Options options);
signals:
/**
- * Signals that the directory \a path contains \a count items.
+ * Signals that the directory \a path contains \a count items and optionally the size of its content.
*/
- void result(const QString& path, int count);
+ void result(const QString& path, int count, long size);
public slots:
/**
diff --git a/src/kitemviews/private/kfileitemmodelfilter.cpp b/src/kitemviews/private/kfileitemmodelfilter.cpp
index fc56cc71d..bcd875132 100644
--- a/src/kitemviews/private/kfileitemmodelfilter.cpp
+++ b/src/kitemviews/private/kfileitemmodelfilter.cpp
@@ -20,8 +20,9 @@
#include "kfileitemmodelfilter.h"
-#include <KFileItem>
+#include <QRegularExpression>
+#include <KFileItem>
KFileItemModelFilter::KFileItemModelFilter() :
m_useRegExp(false),
@@ -44,12 +45,10 @@ void KFileItemModelFilter::setPattern(const QString& filter)
if (filter.contains('*') || filter.contains('?') || filter.contains('[')) {
if (!m_regExp) {
- m_regExp = new QRegExp();
- m_regExp->setCaseSensitivity(Qt::CaseInsensitive);
- m_regExp->setMinimal(false);
- m_regExp->setPatternSyntax(QRegExp::WildcardUnix);
+ m_regExp = new QRegularExpression();
+ m_regExp->setPatternOptions(QRegularExpression::CaseInsensitiveOption);
}
- m_regExp->setPattern(filter);
+ m_regExp->setPattern(QRegularExpression::wildcardToRegularExpression(filter));
m_useRegExp = m_regExp->isValid();
} else {
m_useRegExp = false;
@@ -103,7 +102,7 @@ bool KFileItemModelFilter::matches(const KFileItem& item) const
bool KFileItemModelFilter::matchesPattern(const KFileItem& item) const
{
if (m_useRegExp) {
- return m_regExp->exactMatch(item.text());
+ return m_regExp->match(item.text()).hasMatch();
} else {
return item.text().toLower().contains(m_lowerCasePattern);
}
diff --git a/src/kitemviews/private/kfileitemmodelfilter.h b/src/kitemviews/private/kfileitemmodelfilter.h
index f9f588aba..b56e0ad5b 100644
--- a/src/kitemviews/private/kfileitemmodelfilter.h
+++ b/src/kitemviews/private/kfileitemmodelfilter.h
@@ -26,7 +26,7 @@
#include <QStringList>
class KFileItem;
-class QRegExp;
+class QRegularExpression;
/**
* @brief Allows to check whether an item of the KFileItemModel
@@ -83,7 +83,7 @@ private:
bool m_useRegExp; // If true, m_regExp is used for filtering,
// otherwise m_lowerCaseFilter is used.
- QRegExp* m_regExp;
+ QRegularExpression *m_regExp;
QString m_lowerCasePattern; // Lowercase version of m_filter for
// faster comparison in matches().
QString m_pattern; // Property set by setPattern().
diff --git a/src/main.cpp b/src/main.cpp
index 5932df5ce..802e64d25 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -31,6 +31,7 @@
#include <KDBusService>
#include <KLocalizedString>
#include <Kdelibs4ConfigMigrator>
+#include <KConfigGui>
#include <QApplication>
#include <QCommandLineParser>
@@ -139,6 +140,9 @@ extern "C" Q_DECL_EXPORT int kdemain(int argc, char **argv)
const bool openFiles = parser.isSet(QStringLiteral("select"));
const QStringList args = parser.positionalArguments();
QList<QUrl> urls = Dolphin::validateUris(args);
+ // We later mutate urls, so we need to store if it was empty originally
+ const bool startedWithURLs = !urls.isEmpty();
+
if (parser.isSet(QStringLiteral("daemon"))) {
KDBusService dolphinDBusService;
@@ -154,7 +158,7 @@ extern "C" Q_DECL_EXPORT int kdemain(int argc, char **argv)
}
}
- if (urls.isEmpty()) {
+ if (!startedWithURLs) {
// We need at least one URL to open Dolphin
urls.append(Dolphin::homeUrl());
}
@@ -174,12 +178,25 @@ extern "C" Q_DECL_EXPORT int kdemain(int argc, char **argv)
mainWindow->show();
- if (app.isSessionRestored()) {
- const QString className = KXmlGuiWindow::classNameOfToplevel(1);
- if (className == QLatin1String("DolphinMainWindow")) {
- mainWindow->restore(1);
- } else {
- qCWarning(DolphinDebug) << "Unknown class " << className << " in session saved data!";
+ if (!app.isSessionRestored()) {
+ KConfigGui::setSessionConfig(QStringLiteral("dolphin"), QStringLiteral("dolphin"));
+ }
+
+ // Only restore session if:
+ // 1. Dolphin was not started with command line args
+ // 2. The "remember state" setting is enabled or session restoration after
+ // reboot is in use
+ // 3. There is a session available to restore
+ if (!startedWithURLs && (app.isSessionRestored() || GeneralSettings::rememberOpenedTabs()) ) {
+ // Get saved state data for the last-closed Dolphin instance
+ const QString serviceName = QStringLiteral("org.kde.dolphin-%1").arg(QCoreApplication::applicationPid());
+ if (Dolphin::dolphinGuiInstances(serviceName).size() > 0) {
+ const QString className = KXmlGuiWindow::classNameOfToplevel(1);
+ if (className == QLatin1String("DolphinMainWindow")) {
+ mainWindow->restore(1);
+ } else {
+ qCWarning(DolphinDebug) << "Unknown class " << className << " in session saved data!";
+ }
}
}
diff --git a/src/org.kde.dolphin.appdata.xml b/src/org.kde.dolphin.appdata.xml
index c77e4e12e..215e670fe 100644
--- a/src/org.kde.dolphin.appdata.xml
+++ b/src/org.kde.dolphin.appdata.xml
@@ -576,6 +576,7 @@
<caption xml:lang="pt-BR">Gerenciamento de arquivos no Dolphin</caption>
<caption xml:lang="ru">Управление файлами</caption>
<caption xml:lang="sk">Správa súborov v Dolphin</caption>
+ <caption xml:lang="sl">Upravljanje datotek v Dolphinu</caption>
<caption xml:lang="sv">Filhantering i Dolphin</caption>
<caption xml:lang="uk">Керування файлами у Dolphin</caption>
<caption xml:lang="x-test">xxFile management in Dolphinxx</caption>
diff --git a/src/panels/information/informationpanel.cpp b/src/panels/information/informationpanel.cpp
index 23e7f1922..4f0e4e5eb 100644
--- a/src/panels/information/informationpanel.cpp
+++ b/src/panels/information/informationpanel.cpp
@@ -248,7 +248,7 @@ void InformationPanel::showItemInfo()
if (item.isNull()) {
// No item is hovered and no selection has been done: provide
// an item for the currently shown directory.
- m_folderStatJob = KIO::stat(url(), KIO::HideProgressInfo);
+ m_folderStatJob = KIO::statDetails(url(), KIO::StatJob::SourceSide, KIO::StatDefaultDetails | KIO::StatRecursiveSize, KIO::HideProgressInfo);
if (m_folderStatJob->uiDelegate()) {
KJobWidgets::setWindow(m_folderStatJob, this);
}
diff --git a/src/panels/information/informationpanelcontent.cpp b/src/panels/information/informationpanelcontent.cpp
index 5c7c7c3f1..a0c872560 100644
--- a/src/panels/information/informationpanelcontent.cpp
+++ b/src/panels/information/informationpanelcontent.cpp
@@ -78,7 +78,7 @@ InformationPanelContent::InformationPanelContent(QWidget* parent) :
// delay. This prevents flickering if the new preview can be generated
// within a very small timeframe.
m_outdatedPreviewTimer = new QTimer(this);
- m_outdatedPreviewTimer->setInterval(300);
+ m_outdatedPreviewTimer->setInterval(100);
m_outdatedPreviewTimer->setSingleShot(true);
connect(m_outdatedPreviewTimer, &QTimer::timeout,
this, &InformationPanelContent::markOutdatedPreview);
@@ -189,12 +189,8 @@ void InformationPanelContent::refreshPixmapView()
// Mark the currently shown preview as outdated. This is done
// with a small delay to prevent a flickering when the next preview
- // can be shown within a short timeframe. This timer is not started
- // for directories, as directory previews might fail and return the
- // same icon.
- if (!m_item.isDir()) {
- m_outdatedPreviewTimer->start();
- }
+ // can be shown within a short timeframe.
+ m_outdatedPreviewTimer->start();
QStringList plugins = KIO::PreviewJob::availablePlugins();
m_previewJob = new KIO::PreviewJob(KFileItemList() << m_item,
@@ -221,7 +217,6 @@ void InformationPanelContent::refreshPreview()
}
m_preview->setCursor(Qt::ArrowCursor);
- bool usePhonon = false;
setNameLabelText(m_item.text());
if (InformationPanelSettings::previewsShown()) {
@@ -229,11 +224,12 @@ void InformationPanelContent::refreshPreview()
const bool isSearchUrl = itemUrl.scheme().contains(QLatin1String("search")) && m_item.localPath().isEmpty();
if (isSearchUrl) {
m_preview->show();
+ m_phononWidget->hide();
// in the case of a search-URL the URL is not readable for humans
// (at least not useful to show in the Information Panel)
m_preview->setPixmap(
- QIcon::fromTheme(QStringLiteral("baloo")).pixmap(KIconLoader::SizeEnormous, KIconLoader::SizeEnormous)
+ QIcon::fromTheme(QStringLiteral("baloo")).pixmap(m_preview->height(), m_preview->width())
);
} else {
@@ -242,12 +238,13 @@ void InformationPanelContent::refreshPreview()
const QString mimeType = m_item.mimetype();
const bool isAnimatedImage = m_preview->isAnimatedImage(itemUrl.toLocalFile());
m_isVideo = !isAnimatedImage && mimeType.startsWith(QLatin1String("video/"));
- usePhonon = m_isVideo || mimeType.startsWith(QLatin1String("audio/"));
+ bool usePhonon = m_isVideo || mimeType.startsWith(QLatin1String("audio/"));
if (usePhonon) {
// change the cursor of the preview
m_preview->setCursor(Qt::PointingHandCursor);
m_preview->installEventFilter(m_phononWidget);
+ m_phononWidget->show();
// if the video is playing, has been paused or stopped
// we don't need to update the preview/phonon widget states
@@ -267,7 +264,6 @@ void InformationPanelContent::refreshPreview()
m_preview->show();
}
- m_phononWidget->show();
m_phononWidget->setUrl(m_item.targetUrl(), m_isVideo ? PhononWidget::MediaKind::Video : PhononWidget::MediaKind::Audio);
adjustWidgetSizes(parentWidget()->width());
}
@@ -314,7 +310,7 @@ void InformationPanelContent::showItems(const KFileItemList& items)
m_preview->stopAnimatedImage();
m_preview->setPixmap(
- QIcon::fromTheme(QStringLiteral("dialog-information")).pixmap(KIconLoader::SizeEnormous, KIconLoader::SizeEnormous)
+ QIcon::fromTheme(QStringLiteral("dialog-information")).pixmap(m_preview->height(), m_preview->width())
);
setNameLabelText(i18ncp("@label", "%1 item selected", "%1 items selected", items.count()));
@@ -358,7 +354,7 @@ bool InformationPanelContent::eventFilter(QObject* obj, QEvent* event)
void InformationPanelContent::showIcon(const KFileItem& item)
{
m_outdatedPreviewTimer->stop();
- QPixmap pixmap = QIcon::fromTheme(item.iconName()).pixmap(KIconLoader::SizeEnormous, KIconLoader::SizeEnormous);
+ QPixmap pixmap = QIcon::fromTheme(item.iconName()).pixmap(m_preview->height(), m_preview->width());
KIconLoader::global()->drawOverlays(item.overlays(), pixmap, KIconLoader::Desktop);
m_preview->setPixmap(pixmap);
}
@@ -411,11 +407,18 @@ void InformationPanelContent::showPreview(const KFileItem& item,
void InformationPanelContent::markOutdatedPreview()
{
- KIconEffect *iconEffect = KIconLoader::global()->iconEffect();
- QPixmap disabledPixmap = iconEffect->apply(m_preview->pixmap(),
- KIconLoader::Desktop,
- KIconLoader::DisabledState);
- m_preview->setPixmap(disabledPixmap);
+ if (m_item.isDir()) {
+ // directory preview can be long
+ // but since we always have icons to display
+ // use it until the preview is done
+ showIcon(m_item);
+ } else {
+ KIconEffect *iconEffect = KIconLoader::global()->iconEffect();
+ QPixmap disabledPixmap = iconEffect->apply(m_preview->pixmap(),
+ KIconLoader::Desktop,
+ KIconLoader::DisabledState);
+ m_preview->setPixmap(disabledPixmap);
+ }
}
KFileItemList InformationPanelContent::items()
diff --git a/src/panels/terminal/org.kde.KIOFuse.VFS.xml b/src/panels/terminal/org.kde.KIOFuse.VFS.xml
new file mode 100644
index 000000000..56f753e41
--- /dev/null
+++ b/src/panels/terminal/org.kde.KIOFuse.VFS.xml
@@ -0,0 +1,13 @@
+<!DOCTYPE node PUBLIC "-//freedesktop//DTD D-BUS Object Introspection 1.0//EN" "http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd">
+<node>
+ <interface name="org.kde.KIOFuse.VFS">
+ <method name="mountUrl">
+ <arg name="remoteUrl" type="s" direction="in"/>
+ <arg type="s" direction="out"/>
+ </method>
+ <method name="remoteUrl">
+ <arg name="localUrl" type="s" direction="in"/>
+ <arg type="s" direction="out"/>
+ </method>
+ </interface>
+</node>
diff --git a/src/panels/terminal/terminalpanel.cpp b/src/panels/terminal/terminalpanel.cpp
index 59b2694fb..ac0bcd0fe 100644
--- a/src/panels/terminal/terminalpanel.cpp
+++ b/src/panels/terminal/terminalpanel.cpp
@@ -18,6 +18,7 @@
***************************************************************************/
#include "terminalpanel.h"
+#include "kiofuse_interface.h"
#include <KIO/DesktopExecParser>
#include <KIO/Job>
@@ -25,6 +26,7 @@
#include <KJobWidgets>
#include <KLocalizedString>
#include <KMessageWidget>
+#include <KMountPoint>
#include <KParts/ReadOnlyPart>
#include <KPluginFactory>
#include <KPluginLoader>
@@ -50,7 +52,10 @@ TerminalPanel::TerminalPanel(QWidget* parent) :
m_konsolePartMissingMessage(nullptr),
m_konsolePart(nullptr),
m_konsolePartCurrentDirectory(),
- m_sendCdToTerminalHistory()
+ m_sendCdToTerminalHistory(),
+ m_kiofuseInterface(QStringLiteral("org.kde.KIOFuse"),
+ QStringLiteral("/org/kde/KIOFuse"),
+ QDBusConnection::sessionBus())
{
m_layout = new QVBoxLayout(this);
m_layout->setContentsMargins(0, 0, 0, 0);
@@ -244,6 +249,19 @@ void TerminalPanel::slotMostLocalUrlResult(KJob* job)
const QUrl url = statJob->mostLocalUrl();
if (url.isLocalFile()) {
sendCdToTerminal(url.toLocalFile());
+ } else {
+ // URL isn't local, only hope for the terminal to be in sync with the
+ // DolphinView is to mount the remote URL in KIOFuse and point to it.
+ // If we can't do that for any reason, silently fail.
+ auto reply = m_kiofuseInterface.mountUrl(url.toString());
+ QDBusPendingCallWatcher * watcher = new QDBusPendingCallWatcher(reply, this);
+ QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [=] (QDBusPendingCallWatcher* watcher) {
+ watcher->deleteLater();
+ if (!reply.isError()) {
+ // Successfully mounted, point to the KIOFuse equivalent path.
+ sendCdToTerminal(reply.value());
+ }
+ });
}
m_mostLocalUrlJob = nullptr;
@@ -261,8 +279,31 @@ void TerminalPanel::slotKonsolePartCurrentDirectoryChanged(const QString& dir)
}
}
+ // User may potentially be browsing inside a KIOFuse mount.
+ // If so lets try and change the DolphinView to point to the remote URL equivalent.
+ // instead of into the KIOFuse mount itself (which can cause performance issues!)
const QUrl url(QUrl::fromLocalFile(dir));
- emit changeUrl(url);
+
+ KMountPoint::Ptr mountPoint = KMountPoint::currentMountPoints().findByPath(m_konsolePartCurrentDirectory);
+ if (mountPoint && mountPoint->mountType() != QStringLiteral("fuse.kio-fuse")) {
+ // Not in KIOFUse mount, so just switch to the corresponding URL.
+ emit changeUrl(url);
+ return;
+ }
+
+ auto reply = m_kiofuseInterface.remoteUrl(m_konsolePartCurrentDirectory);
+ QDBusPendingCallWatcher * watcher = new QDBusPendingCallWatcher(reply, this);
+ QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [=] (QDBusPendingCallWatcher* watcher) {
+ watcher->deleteLater();
+ if (reply.isError()) {
+ // KIOFuse errored out... just show the normal URL
+ emit changeUrl(url);
+ } else {
+ // Our location happens to be in a KIOFuse mount and is mounted.
+ // Let's change the DolphinView to point to the remote URL equivalent.
+ emit changeUrl(QUrl::fromUserInput(reply.value()));
+ }
+ });
}
bool TerminalPanel::terminalHasFocus() const
diff --git a/src/panels/terminal/terminalpanel.h b/src/panels/terminal/terminalpanel.h
index 6ab205fe3..661fee4d4 100644
--- a/src/panels/terminal/terminalpanel.h
+++ b/src/panels/terminal/terminalpanel.h
@@ -21,6 +21,7 @@
#define TERMINALPANEL_H
#include "panels/panel.h"
+#include "kiofuse_interface.h"
#include <QQueue>
@@ -101,6 +102,7 @@ private:
KParts::ReadOnlyPart* m_konsolePart;
QString m_konsolePartCurrentDirectory;
QQueue<QString> m_sendCdToTerminalHistory;
+ org::kde::KIOFuse::VFS m_kiofuseInterface;
};
#endif // TERMINALPANEL_H
diff --git a/src/search/dolphinsearchbox.cpp b/src/search/dolphinsearchbox.cpp
index 23f520de1..cdc0718df 100644
--- a/src/search/dolphinsearchbox.cpp
+++ b/src/search/dolphinsearchbox.cpp
@@ -136,6 +136,7 @@ QUrl DolphinSearchBox::urlForSearching() const
}
query.addQueryItem(QStringLiteral("url"), searchPath().url());
+ query.addQueryItem(QStringLiteral("title"), queryTitle(m_searchInput->text()));
url.setQuery(query);
}
@@ -219,6 +220,9 @@ void DolphinSearchBox::keyReleaseEvent(QKeyEvent* event)
m_searchInput->clear();
}
}
+ else if (event->key() == Qt::Key_Down) {
+ emit focusViewRequest();
+ }
}
bool DolphinSearchBox::eventFilter(QObject* obj, QEvent* event)
@@ -283,7 +287,7 @@ void DolphinSearchBox::slotSearchTextChanged(const QString& text)
void DolphinSearchBox::slotReturnPressed()
{
emitSearchRequest();
- emit returnPressed();
+ emit focusViewRequest();
}
void DolphinSearchBox::slotFacetChanged()
@@ -469,6 +473,12 @@ void DolphinSearchBox::init()
connect(m_startSearchTimer, &QTimer::timeout, this, &DolphinSearchBox::emitSearchRequest);
}
+QString DolphinSearchBox::queryTitle(const QString& text) const
+{
+ return i18nc("@title UDS_DISPLAY_NAME for a KIO directory listing. %1 is the query the user entered.",
+ "Query Results from '%1'", text);
+}
+
QUrl DolphinSearchBox::balooUrlForSearching() const
{
#ifdef HAVE_BALOO
@@ -491,8 +501,7 @@ QUrl DolphinSearchBox::balooUrlForSearching() const
query.setSearchString(queryStrings.join(QLatin1Char(' ')));
- return query.toSearchUrl(i18nc("@title UDS_DISPLAY_NAME for a KIO directory listing. %1 is the query the user entered.",
- "Query Results from '%1'", text));
+ return query.toSearchUrl(queryTitle(text));
#else
return QUrl();
#endif
@@ -541,7 +550,7 @@ bool DolphinSearchBox::isIndexingEnabled() const
{
#ifdef HAVE_BALOO
const Baloo::IndexerConfig searchInfo;
- return searchInfo.fileIndexingEnabled() && searchInfo.shouldBeIndexed(searchPath().toLocalFile());
+ return searchInfo.fileIndexingEnabled() && !searchPath().isEmpty() && searchInfo.shouldBeIndexed(searchPath().toLocalFile());
#else
return false;
#endif
diff --git a/src/search/dolphinsearchbox.h b/src/search/dolphinsearchbox.h
index 5fef4ec5a..4afd752bc 100644
--- a/src/search/dolphinsearchbox.h
+++ b/src/search/dolphinsearchbox.h
@@ -118,8 +118,6 @@ signals:
*/
void searchTextChanged(const QString& text);
- void returnPressed();
-
/**
* Emitted as soon as the search box should get closed.
*/
@@ -131,6 +129,7 @@ signals:
* @see DolphinSearchBox::setActive()
*/
void activated();
+ void focusViewRequest();
private slots:
void emitSearchRequest();
@@ -162,6 +161,8 @@ private:
bool isIndexingEnabled() const;
private:
+ QString queryTitle(const QString& text) const;
+
bool m_startedSearching;
bool m_active;
diff --git a/src/settings/dolphin_detailsmodesettings.kcfg b/src/settings/dolphin_detailsmodesettings.kcfg
index e9a8fb28d..9d05a8ab0 100644
--- a/src/settings/dolphin_detailsmodesettings.kcfg
+++ b/src/settings/dolphin_detailsmodesettings.kcfg
@@ -44,5 +44,13 @@
<label>Expandable folders</label>
<default>true</default>
</entry>
+ <entry name="DirectorySizeCount" type="Bool">
+ <label>Whether or not content count is used as directory size</label>
+ <default>true</default>
+ </entry>
+ <entry name="RecursiveDirectorySizeLimit" type="UInt">
+ <label>Recursive directory size limit</label>
+ <default>10</default>
+ </entry>
</group>
</kcfg>
diff --git a/src/settings/dolphin_generalsettings.kcfg b/src/settings/dolphin_generalsettings.kcfg
index fca70656d..c397b2945 100644
--- a/src/settings/dolphin_generalsettings.kcfg
+++ b/src/settings/dolphin_generalsettings.kcfg
@@ -42,6 +42,10 @@
<label>Home URL</label>
<default code="true">QUrl::fromLocalFile(QDir::homePath()).toDisplayString(QUrl::PreferLocalFile)</default>
</entry>
+ <entry name="RememberOpenedTabs" type="Bool">
+ <label>Remember open folders and tabs</label>
+ <default>true</default>
+ </entry>
<entry name="SplitView" type="Bool">
<label>Split the view into two panes</label>
<default>false</default>
diff --git a/src/settings/kcm/kcmdolphingeneral.cpp b/src/settings/kcm/kcmdolphingeneral.cpp
index a82cb3858..39eccff76 100644
--- a/src/settings/kcm/kcmdolphingeneral.cpp
+++ b/src/settings/kcm/kcmdolphingeneral.cpp
@@ -33,12 +33,10 @@
K_PLUGIN_FACTORY(KCMDolphinGeneralConfigFactory, registerPlugin<DolphinGeneralConfigModule>(QStringLiteral("dolphingeneral"));)
-DolphinGeneralConfigModule::DolphinGeneralConfigModule(QWidget* parent, const QVariantList& args) :
- KCModule(parent),
+DolphinGeneralConfigModule::DolphinGeneralConfigModule(QWidget *parent, const QVariantList &args) :
+ KCModule(parent, args),
m_pages()
{
- Q_UNUSED(args)
-
setButtons(KCModule::Default | KCModule::Help);
QVBoxLayout* topLayout = new QVBoxLayout(this);
@@ -49,29 +47,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"));
-#if KCONFIGWIDGETS_VERSION < QT_VERSION_CHECK(5, 64, 0)
- connect(behaviorPage, &BehaviorSettingsPage::changed, this, QOverload<>::of(&DolphinGeneralConfigModule::changed));
-#else
connect(behaviorPage, &BehaviorSettingsPage::changed, this, &DolphinGeneralConfigModule::markAsChanged);
-#endif
// initialize 'Previews' tab
PreviewsSettingsPage* previewsPage = new PreviewsSettingsPage(tabWidget);
tabWidget->addTab(previewsPage, i18nc("@title:tab Previews settings", "Previews"));
-#if KCONFIGWIDGETS_VERSION < QT_VERSION_CHECK(5, 64, 0)
- connect(previewsPage, &PreviewsSettingsPage::changed, this, QOverload<>::of(&DolphinGeneralConfigModule::changed));
-#else
connect(previewsPage, &PreviewsSettingsPage::changed, this, &DolphinGeneralConfigModule::markAsChanged);
-#endif
// initialize 'Confirmations' tab
ConfirmationsSettingsPage* confirmationsPage = new ConfirmationsSettingsPage(tabWidget);
tabWidget->addTab(confirmationsPage, i18nc("@title:tab Confirmations settings", "Confirmations"));
-#if KCONFIGWIDGETS_VERSION < QT_VERSION_CHECK(5, 64, 0)
- connect(confirmationsPage, &ConfirmationsSettingsPage::changed, this, QOverload<>::of(&DolphinGeneralConfigModule::changed));
-#else
connect(confirmationsPage, &ConfirmationsSettingsPage::changed, this, &DolphinGeneralConfigModule::markAsChanged);
-#endif
m_pages.append(behaviorPage);
m_pages.append(previewsPage);
m_pages.append(confirmationsPage);
@@ -85,14 +71,14 @@ DolphinGeneralConfigModule::~DolphinGeneralConfigModule()
void DolphinGeneralConfigModule::save()
{
- foreach (SettingsPageBase* page, m_pages) {
+ for (SettingsPageBase* page : qAsConst(m_pages)) {
page->applySettings();
}
}
void DolphinGeneralConfigModule::defaults()
{
- foreach (SettingsPageBase* page, m_pages) {
+ for (SettingsPageBase* page : qAsConst(m_pages)) {
page->applySettings();
}
}
diff --git a/src/settings/kcm/kcmdolphingeneral.h b/src/settings/kcm/kcmdolphingeneral.h
index c542c0139..2b60c7591 100644
--- a/src/settings/kcm/kcmdolphingeneral.h
+++ b/src/settings/kcm/kcmdolphingeneral.h
@@ -34,7 +34,7 @@ class DolphinGeneralConfigModule : public KCModule
Q_OBJECT
public:
- DolphinGeneralConfigModule(QWidget* parent, const QVariantList& args);
+ DolphinGeneralConfigModule(QWidget *parent, const QVariantList &args);
~DolphinGeneralConfigModule() override;
void save() override;
diff --git a/src/settings/kcm/kcmdolphinnavigation.cpp b/src/settings/kcm/kcmdolphinnavigation.cpp
index 2cdabdeee..f8de4eed2 100644
--- a/src/settings/kcm/kcmdolphinnavigation.cpp
+++ b/src/settings/kcm/kcmdolphinnavigation.cpp
@@ -29,23 +29,17 @@
K_PLUGIN_FACTORY(KCMDolphinNavigationConfigFactory, registerPlugin<DolphinNavigationConfigModule>(QStringLiteral("dolphinnavigation"));)
-DolphinNavigationConfigModule::DolphinNavigationConfigModule(QWidget* parent, const QVariantList& args) :
- KCModule(parent),
+DolphinNavigationConfigModule::DolphinNavigationConfigModule(QWidget *parent, const QVariantList &args) :
+ KCModule(parent, args),
m_navigation(nullptr)
{
- Q_UNUSED(args)
-
setButtons(KCModule::Default | KCModule::Help);
QVBoxLayout* topLayout = new QVBoxLayout(this);
topLayout->setContentsMargins(0, 0, 0, 0);
m_navigation = new NavigationSettingsPage(this);
-#if KCONFIGWIDGETS_VERSION < QT_VERSION_CHECK(5, 64, 0)
- connect(m_navigation, &NavigationSettingsPage::changed, this, QOverload<>::of(&DolphinNavigationConfigModule::changed));
-#else
connect(m_navigation, &NavigationSettingsPage::changed, this, &DolphinNavigationConfigModule::markAsChanged);
-#endif
topLayout->addWidget(m_navigation, 0, {});
}
diff --git a/src/settings/kcm/kcmdolphinnavigation.h b/src/settings/kcm/kcmdolphinnavigation.h
index 2bcc7abab..7eb6b26e7 100644
--- a/src/settings/kcm/kcmdolphinnavigation.h
+++ b/src/settings/kcm/kcmdolphinnavigation.h
@@ -32,14 +32,14 @@ class DolphinNavigationConfigModule : public KCModule
Q_OBJECT
public:
- DolphinNavigationConfigModule(QWidget* parent, const QVariantList& args);
+ DolphinNavigationConfigModule(QWidget *parent, const QVariantList &args);
~DolphinNavigationConfigModule() override;
void save() override;
void defaults() override;
private:
- NavigationSettingsPage* m_navigation;
+ NavigationSettingsPage *m_navigation;
};
#endif
diff --git a/src/settings/kcm/kcmdolphinservices.cpp b/src/settings/kcm/kcmdolphinservices.cpp
index e6a8867d7..92e71bae0 100644
--- a/src/settings/kcm/kcmdolphinservices.cpp
+++ b/src/settings/kcm/kcmdolphinservices.cpp
@@ -30,22 +30,16 @@
K_PLUGIN_FACTORY(KCMDolphinServicesConfigFactory, registerPlugin<DolphinServicesConfigModule>(QStringLiteral("dolphinservices"));)
DolphinServicesConfigModule::DolphinServicesConfigModule(QWidget* parent, const QVariantList& args) :
- KCModule(parent),
+ KCModule(parent, args),
m_services(nullptr)
{
- Q_UNUSED(args)
-
setButtons(KCModule::Default | KCModule::Help);
QVBoxLayout* topLayout = new QVBoxLayout(this);
topLayout->setContentsMargins(0, 0, 0, 0);
m_services = new ServicesSettingsPage(this);
-#if KCONFIGWIDGETS_VERSION < QT_VERSION_CHECK(5, 64, 0)
- connect(m_services, &ServicesSettingsPage::changed, this, QOverload<>::of(&DolphinServicesConfigModule::changed));
-#else
connect(m_services, &ServicesSettingsPage::changed, this, &DolphinServicesConfigModule::markAsChanged);
-#endif
topLayout->addWidget(m_services, 0, {});
}
diff --git a/src/settings/kcm/kcmdolphinservices.h b/src/settings/kcm/kcmdolphinservices.h
index 6c6af6728..a567450ca 100644
--- a/src/settings/kcm/kcmdolphinservices.h
+++ b/src/settings/kcm/kcmdolphinservices.h
@@ -39,7 +39,7 @@ public:
void defaults() override;
private:
- ServicesSettingsPage* m_services;
+ ServicesSettingsPage *m_services;
};
#endif
diff --git a/src/settings/kcm/kcmdolphinviewmodes.cpp b/src/settings/kcm/kcmdolphinviewmodes.cpp
index 4fac11600..91abe5cd4 100644
--- a/src/settings/kcm/kcmdolphinviewmodes.cpp
+++ b/src/settings/kcm/kcmdolphinviewmodes.cpp
@@ -33,12 +33,10 @@
K_PLUGIN_FACTORY(KCMDolphinViewModesConfigFactory, registerPlugin<DolphinViewModesConfigModule>(QStringLiteral("dolphinviewmodes"));)
-DolphinViewModesConfigModule::DolphinViewModesConfigModule(QWidget* parent, const QVariantList& args) :
- KCModule(parent),
+DolphinViewModesConfigModule::DolphinViewModesConfigModule(QWidget *parent, const QVariantList &args) :
+ KCModule(parent, args),
m_tabs()
{
- Q_UNUSED(args)
-
setButtons(KCModule::Default | KCModule::Help);
QVBoxLayout* topLayout = new QVBoxLayout(this);
@@ -74,7 +72,7 @@ DolphinViewModesConfigModule::~DolphinViewModesConfigModule()
void DolphinViewModesConfigModule::save()
{
- foreach (ViewSettingsTab* tab, m_tabs) {
+ for (ViewSettingsTab *tab : qAsConst(m_tabs)) {
tab->applySettings();
}
reparseConfiguration();
@@ -82,7 +80,7 @@ void DolphinViewModesConfigModule::save()
void DolphinViewModesConfigModule::defaults()
{
- foreach (ViewSettingsTab* tab, m_tabs) {
+ for (ViewSettingsTab *tab : qAsConst(m_tabs)) {
tab->restoreDefaultSettings();
}
reparseConfiguration();
@@ -90,13 +88,15 @@ void DolphinViewModesConfigModule::defaults()
void DolphinViewModesConfigModule::reparseConfiguration()
{
- QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KonqMain"), QStringLiteral("org.kde.Konqueror.Main"), QStringLiteral("reparseConfiguration"));
+ QDBusMessage message = QDBusMessage::createSignal(QStringLiteral("/KonqMain"),
+ QStringLiteral("org.kde.Konqueror.Main"),
+ QStringLiteral("reparseConfiguration"));
QDBusConnection::sessionBus().send(message);
}
void DolphinViewModesConfigModule::viewModeChanged()
{
- emit changed(true);
+ emit markAsChanged();
}
#include "kcmdolphinviewmodes.moc"
diff --git a/src/settings/kcm/kcmdolphinviewmodes.h b/src/settings/kcm/kcmdolphinviewmodes.h
index c3775adff..40965b0e6 100644
--- a/src/settings/kcm/kcmdolphinviewmodes.h
+++ b/src/settings/kcm/kcmdolphinviewmodes.h
@@ -32,7 +32,7 @@ class DolphinViewModesConfigModule : public KCModule
Q_OBJECT
public:
- DolphinViewModesConfigModule(QWidget* parent, const QVariantList& args);
+ DolphinViewModesConfigModule(QWidget *parent, const QVariantList &args);
~DolphinViewModesConfigModule() override;
void save() override;
diff --git a/src/settings/services/servicemenuinstaller/CMakeLists.txt b/src/settings/services/servicemenuinstaller/CMakeLists.txt
index 988899936..46b159079 100644
--- a/src/settings/services/servicemenuinstaller/CMakeLists.txt
+++ b/src/settings/services/servicemenuinstaller/CMakeLists.txt
@@ -6,5 +6,10 @@ target_link_libraries(servicemenuinstaller PRIVATE
Qt5::Core
Qt5::Gui
KF5::I18n
+ KF5::CoreAddons
)
+
+if(HAVE_PACKAGEKIT)
+ target_link_libraries(servicemenuinstaller PRIVATE PK::packagekitqt5)
+endif()
install(TARGETS servicemenuinstaller ${KDE_INSTALL_TARGETS_DEFAULT_ARGS})
diff --git a/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp b/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp
index 06f34c6b9..89f2545f8 100644
--- a/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp
+++ b/src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp
@@ -20,28 +20,42 @@
#include <QDebug>
#include <QProcess>
+#include <QTimer>
#include <QStandardPaths>
#include <QDir>
#include <QDirIterator>
#include <QCommandLineParser>
#include <QMimeDatabase>
#include <QUrl>
-#include <QDesktopServices>
#include <QGuiApplication>
-
#include <KLocalizedString>
+#include <KShell>
+
+#include "../../../config-packagekit.h"
+
+const static QStringList binaryPackages = {QStringLiteral("application/vnd.debian.binary-package"),
+ QStringLiteral("application/x-rpm"),
+ QStringLiteral("application/x-xz"),
+ QStringLiteral("application/zstd")};
+enum PackageOperation {
+ Install,
+ Uninstall
+};
+
+#ifdef HAVE_PACKAGEKIT
+#include <PackageKit/Daemon>
+#include <PackageKit/Details>
+#include <PackageKit/Transaction>
+#else
+#include <QDesktopServices>
+#endif
// @param msg Error that gets logged to CLI
Q_NORETURN void fail(const QString &str)
{
qCritical() << str;
-
- QProcess process;
- const QStringList args = {"--passivepopup", i18n("Dolphin service menu installation failed"), "15"};
- process.start("kdialog", args, QIODevice::ReadOnly);
- if (!process.waitForStarted()) {
- qFatal("Failed to run kdialog");
- }
+ const QStringList args = {"--detailederror" ,i18n("Dolphin service menu installation failed"), str};
+ QProcess::startDetached("kdialog", args);
exit(1);
}
@@ -52,6 +66,84 @@ QString getServiceMenusDir()
return QDir(dataLocation).absoluteFilePath("kservices5/ServiceMenus");
}
+#ifdef HAVE_PACKAGEKIT
+void packageKitInstall(const QString &fileName)
+{
+ PackageKit::Transaction *transaction = PackageKit::Daemon::installFile(fileName);
+
+ const auto exitWithError = [=](PackageKit::Transaction::Error, const QString &details) {
+ fail(details);
+ };
+
+ QObject::connect(transaction, &PackageKit::Transaction::finished,
+ [=](PackageKit::Transaction::Exit status, uint) {
+ if (status == PackageKit::Transaction::ExitSuccess) {
+ exit(0);
+ }
+ // Fallback error handling
+ QTimer::singleShot(500, [=](){
+ fail(i18n("Failed to install \"%1\", exited with status \"%2\"",
+ fileName, QVariant::fromValue(status).toString()));
+ });
+ });
+ QObject::connect(transaction, &PackageKit::Transaction::errorCode, exitWithError);
+}
+
+void packageKitUninstall(const QString &fileName)
+{
+ const auto exitWithError = [=](PackageKit::Transaction::Error, const QString &details) {
+ fail(details);
+ };
+ const auto uninstallLambda = [=](PackageKit::Transaction::Exit status, uint) {
+ if (status == PackageKit::Transaction::ExitSuccess) {
+ exit(0);
+ }
+ };
+
+ PackageKit::Transaction *transaction = PackageKit::Daemon::getDetailsLocal(fileName);
+ QObject::connect(transaction, &PackageKit::Transaction::details,
+ [=](const PackageKit::Details &details) {
+ PackageKit::Transaction *transaction = PackageKit::Daemon::removePackage(details.packageId());
+ QObject::connect(transaction, &PackageKit::Transaction::finished, uninstallLambda);
+ QObject::connect(transaction, &PackageKit::Transaction::errorCode, exitWithError);
+ });
+
+ QObject::connect(transaction, &PackageKit::Transaction::errorCode, exitWithError);
+ // Fallback error handling
+ QObject::connect(transaction, &PackageKit::Transaction::finished,
+ [=](PackageKit::Transaction::Exit status, uint) {
+ if (status != PackageKit::Transaction::ExitSuccess) {
+ QTimer::singleShot(500, [=]() {
+ fail(i18n("Failed to uninstall \"%1\", exited with status \"%2\"",
+ fileName, QVariant::fromValue(status).toString()));
+ });
+ }
+ });
+ }
+#endif
+
+Q_NORETURN void packageKit(PackageOperation operation, const QString &fileName)
+{
+#ifdef HAVE_PACKAGEKIT
+ QFileInfo fileInfo(fileName);
+ if (!fileInfo.exists()) {
+ fail(i18n("The file does not exist!"));
+ }
+ const QString absPath = fileInfo.absoluteFilePath();
+ if (operation == PackageOperation::Install) {
+ packageKitInstall(absPath);
+ } else {
+ packageKitUninstall(absPath);
+ }
+ QGuiApplication::exec(); // For event handling, no return after signals finish
+ fail(i18n("Unknown error when installing package"));
+#else
+ Q_UNUSED(operation)
+ QDesktopServices::openUrl(QUrl(fileName));
+ exit(0);
+#endif
+}
+
struct UncompressCommand
{
QString command;
@@ -59,6 +151,11 @@ struct UncompressCommand
QStringList args2;
};
+enum ScriptExecution{
+ Process,
+ Konsole
+};
+
void runUncompress(const QString &inputPath, const QString &outputPath)
{
QVector<QPair<QStringList, UncompressCommand>> mimeTypeToCommand;
@@ -126,12 +223,24 @@ QString findRecursive(const QString &dir, const QString &basename)
return QString();
}
-bool runScriptOnce(const QString &path, const QStringList &args)
+bool runScriptOnce(const QString &path, const QStringList &args, ScriptExecution execution)
{
QProcess process;
process.setWorkingDirectory(QFileInfo(path).absolutePath());
- process.start(path, args, QIODevice::NotOpen);
+ const static bool konsoleAvailable = !QStandardPaths::findExecutable("konsole").isEmpty();
+ if (konsoleAvailable && execution == ScriptExecution::Konsole) {
+ QString bashCommand = KShell::quoteArg(path) + ' ';
+ if (!args.isEmpty()) {
+ bashCommand.append(args.join(' '));
+ }
+ bashCommand.append("|| $SHELL");
+ // If the install script fails a shell opens and the user can fix the problem
+ // without an error konsole closes
+ process.start("konsole", QStringList() << "-e" << "bash" << "-c" << bashCommand, QIODevice::NotOpen);
+ } else {
+ process.start(path, args, QIODevice::NotOpen);
+ }
if (!process.waitForStarted()) {
fail(i18n("Failed to run installer script %1", path));
}
@@ -163,11 +272,11 @@ bool runScriptVariants(const QString &path, bool hasArgVariants, const QStringLi
qInfo() << "[servicemenuinstaller]: Trying to run installer/uninstaller" << path;
if (hasArgVariants) {
for (const auto &arg : argVariants) {
- if (runScriptOnce(path, {arg})) {
+ if (runScriptOnce(path, {arg}, ScriptExecution::Process)) {
return true;
}
}
- } else if (runScriptOnce(path, {})) {
+ } else if (runScriptOnce(path, {}, ScriptExecution::Konsole)) {
return true;
}
@@ -202,9 +311,8 @@ bool cmdInstall(const QString &archive, QString &errorText)
return false;
}
} else {
- const QStringList binaryPackages = {"application/vnd.debian.binary-package", "application/x-rpm"};
if (binaryPackages.contains(QMimeDatabase().mimeTypeForFile(archive).name())) {
- return QDesktopServices::openUrl(QUrl(archive));
+ packageKit(PackageOperation::Install, archive);
}
const QString dir = generateDirPath(archive);
if (QFile::exists(dir)) {
@@ -247,7 +355,11 @@ bool cmdInstall(const QString &archive, QString &errorText)
}
if (!installerPath.isEmpty()) {
- return runScriptVariants(installerPath, true, {"--local", "--local-install", "--install"}, errorText);
+ // Try to run script without variants first
+ if (!runScriptVariants(installerPath, false, {}, errorText)) {
+ return runScriptVariants(installerPath, true, {"--local", "--local-install", "--install"}, errorText);
+ }
+ return true;
}
fail(i18n("Failed to find an installation script in %1", dir));
@@ -268,6 +380,9 @@ bool cmdUninstall(const QString &archive, QString &errorText)
return false;
}
} else {
+ if (binaryPackages.contains(QMimeDatabase().mimeTypeForFile(archive).name())) {
+ packageKit(PackageOperation::Uninstall, archive);
+ }
const QString dir = generateDirPath(archive);
// Try "deinstall" first
diff --git a/src/settings/services/servicessettingspage.cpp b/src/settings/services/servicessettingspage.cpp
index fe900bc5c..e18bfb09e 100644
--- a/src/settings/services/servicessettingspage.cpp
+++ b/src/settings/services/servicessettingspage.cpp
@@ -38,6 +38,7 @@
#include <QListWidget>
#include <QShowEvent>
#include <QSortFilterProxyModel>
+#include <QLineEdit>
namespace
{
@@ -61,25 +62,33 @@ ServicesSettingsPage::ServicesSettingsPage(QWidget* parent) :
"Select which services should "
"be shown in the context menu:"), this);
label->setWordWrap(true);
+ m_searchLineEdit = new QLineEdit(this);
+ m_searchLineEdit->setPlaceholderText(i18nc("@label:textbox", "Search..."));
+ connect(m_searchLineEdit, &QLineEdit::textChanged, this, [this](const QString &filter){
+ m_sortModel->setFilterFixedString(filter);
+ });
m_listView = new QListView(this);
- ServiceItemDelegate* delegate = new ServiceItemDelegate(m_listView, m_listView);
+ auto *delegate = new ServiceItemDelegate(m_listView, m_listView);
m_serviceModel = new ServiceModel(this);
m_sortModel = new QSortFilterProxyModel(this);
m_sortModel->setSourceModel(m_serviceModel);
m_sortModel->setSortRole(Qt::DisplayRole);
m_sortModel->setSortLocaleAware(true);
+ m_sortModel->setFilterRole(Qt::DisplayRole);
+ m_sortModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
m_listView->setModel(m_sortModel);
m_listView->setItemDelegate(delegate);
m_listView->setVerticalScrollMode(QListView::ScrollPerPixel);
connect(m_listView, &QListView::clicked, this, &ServicesSettingsPage::changed);
- KNS3::Button* downloadButton = new KNS3::Button(i18nc("@action:button", "Download New Services..."),
- QStringLiteral("servicemenu.knsrc"),
- this);
+ auto *downloadButton = new KNS3::Button(i18nc("@action:button", "Download New Services..."),
+ QStringLiteral("servicemenu.knsrc"),
+ this);
connect(downloadButton, &KNS3::Button::dialogFinished, this, &ServicesSettingsPage::loadServices);
topLayout->addWidget(label);
+ topLayout->addWidget(m_searchLineEdit);
topLayout->addWidget(m_listView);
topLayout->addWidget(downloadButton);
@@ -87,9 +96,7 @@ ServicesSettingsPage::ServicesSettingsPage(QWidget* parent) :
std::sort(m_enabledVcsPlugins.begin(), m_enabledVcsPlugins.end());
}
-ServicesSettingsPage::~ServicesSettingsPage()
-{
-}
+ServicesSettingsPage::~ServicesSettingsPage() = default;
void ServicesSettingsPage::applySettings()
{
@@ -102,7 +109,7 @@ void ServicesSettingsPage::applySettings()
QStringList enabledPlugins;
- const QAbstractItemModel* model = m_listView->model();
+ const QAbstractItemModel *model = m_listView->model();
for (int i = 0; i < model->rowCount(); ++i) {
const QModelIndex index = model->index(i, 0);
const QString service = model->data(index, ServiceModel::DesktopEntryNameRole).toString();
@@ -188,19 +195,16 @@ void ServicesSettingsPage::loadServices()
// Load generic services
const KService::List entries = KServiceTypeTrader::self()->query(QStringLiteral("KonqPopupMenu/Plugin"));
- foreach (const KService::Ptr& service, entries) {
+ 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(file, true);
- KDesktopFile desktopFile(file);
+ const KDesktopFile desktopFile(file);
const QString subMenuName = desktopFile.desktopGroup().readEntry("X-KDE-Submenu");
- foreach (const KServiceAction& action, serviceActions) {
+ for (const KServiceAction &action : serviceActions) {
const QString serviceName = action.name();
- const bool addService = !action.noDisplay()
- && !action.isSeparator()
- && !isInServicesList(serviceName);
+ const bool addService = !action.noDisplay() && !action.isSeparator() && !isInServicesList(serviceName);
if (addService) {
const QString itemName = subMenuName.isEmpty()
@@ -214,7 +218,7 @@ void ServicesSettingsPage::loadServices()
// Load service plugins that implement the KFileItemActionPlugin interface
const KService::List pluginServices = KServiceTypeTrader::self()->query(QStringLiteral("KFileItemAction/Plugin"));
- foreach (const KService::Ptr& service, pluginServices) {
+ for (const KService::Ptr &service : pluginServices) {
const QString desktopEntryName = service->desktopEntryName();
if (!isInServicesList(desktopEntryName)) {
const bool checked = showGroup.readEntry(desktopEntryName, true);
@@ -227,7 +231,7 @@ void ServicesSettingsPage::loadServices()
return metaData.serviceTypes().contains(QLatin1String("KFileItemAction/Plugin"));
});
- foreach (const auto& jsonMetadata, jsonPlugins) {
+ for (const auto &jsonMetadata : jsonPlugins) {
const QString desktopEntryName = jsonMetadata.pluginId();
if (!isInServicesList(desktopEntryName)) {
const bool checked = showGroup.readEntry(desktopEntryName, true);
@@ -236,6 +240,7 @@ void ServicesSettingsPage::loadServices()
}
m_sortModel->sort(Qt::DisplayRole);
+ m_searchLineEdit->setFocus(Qt::OtherFocusReason);
}
void ServicesSettingsPage::loadVersionControlSystems()
@@ -244,8 +249,8 @@ void ServicesSettingsPage::loadVersionControlSystems()
// Create a checkbox for each available version control plugin
const KService::List pluginServices = KServiceTypeTrader::self()->query(QStringLiteral("FileViewVersionControlPlugin"));
- for (KService::List::ConstIterator it = pluginServices.constBegin(); it != pluginServices.constEnd(); ++it) {
- const QString pluginName = (*it)->name();
+ for (const auto &plugin : pluginServices) {
+ const QString pluginName = plugin->name();
addRow(QStringLiteral("code-class"),
pluginName,
VersionControlServicePrefix + pluginName,
@@ -255,7 +260,7 @@ void ServicesSettingsPage::loadVersionControlSystems()
m_sortModel->sort(Qt::DisplayRole);
}
-bool ServicesSettingsPage::isInServicesList(const QString& service) const
+bool ServicesSettingsPage::isInServicesList(const QString &service) const
{
for (int i = 0; i < m_serviceModel->rowCount(); ++i) {
const QModelIndex index = m_serviceModel->index(i, 0);
@@ -266,9 +271,9 @@ bool ServicesSettingsPage::isInServicesList(const QString& service) const
return false;
}
-void ServicesSettingsPage::addRow(const QString& icon,
- const QString& text,
- const QString& value,
+void ServicesSettingsPage::addRow(const QString &icon,
+ const QString &text,
+ const QString &value,
bool checked)
{
m_serviceModel->insertRow(0);
diff --git a/src/settings/services/servicessettingspage.h b/src/settings/services/servicessettingspage.h
index cd4cbe52f..8f507407b 100644
--- a/src/settings/services/servicessettingspage.h
+++ b/src/settings/services/servicessettingspage.h
@@ -26,6 +26,7 @@
class QListView;
class QSortFilterProxyModel;
class ServiceModel;
+class QLineEdit;
/**
* @brief Page for the 'Services' settings of the Dolphin settings dialog.
@@ -59,21 +60,22 @@ private:
*/
void loadVersionControlSystems();
- bool isInServicesList(const QString& service) const;
+ bool isInServicesList(const QString &service) const;
/**
* Adds a row to the model of m_listView.
*/
- void addRow(const QString& icon,
- const QString& text,
- const QString& value,
+ void addRow(const QString &icon,
+ const QString &text,
+ const QString &value,
bool checked);
private:
bool m_initialized;
- ServiceModel* m_serviceModel;
- QSortFilterProxyModel* m_sortModel;
+ ServiceModel *m_serviceModel;
+ QSortFilterProxyModel *m_sortModel;
QListView* m_listView;
+ QLineEdit *m_searchLineEdit;
QStringList m_enabledVcsPlugins;
};
diff --git a/src/settings/startup/startupsettingspage.cpp b/src/settings/startup/startupsettingspage.cpp
index d7d5fba4c..eb1495746 100644
--- a/src/settings/startup/startupsettingspage.cpp
+++ b/src/settings/startup/startupsettingspage.cpp
@@ -27,18 +27,24 @@
#include <KLocalizedString>
#include <KMessageBox>
+#include <QButtonGroup>
#include <QCheckBox>
#include <QFileDialog>
#include <QLineEdit>
#include <QPushButton>
+#include <QRadioButton>
#include <QFormLayout>
+#include <QGridLayout>
#include <QHBoxLayout>
-#include <QVBoxLayout>
StartupSettingsPage::StartupSettingsPage(const QUrl& url, QWidget* parent) :
SettingsPageBase(parent),
m_url(url),
m_homeUrl(nullptr),
+ m_homeUrlBoxLayoutContainer(nullptr),
+ m_buttonBoxLayoutContainer(nullptr),
+ m_rememberOpenedTabsRadioButton(nullptr),
+ m_homeUrlRadioButton(nullptr),
m_splitView(nullptr),
m_editableUrl(nullptr),
m_showFullPath(nullptr),
@@ -48,9 +54,19 @@ StartupSettingsPage::StartupSettingsPage(const QUrl& url, QWidget* parent) :
{
QFormLayout* topLayout = new QFormLayout(this);
+ m_rememberOpenedTabsRadioButton = new QRadioButton(i18nc("@option:radio Startup Settings", "Folders, tabs, and window state from last time"));
+ m_homeUrlRadioButton = new QRadioButton();
+ // HACK: otherwise the radio button has too much spacing in a grid layout
+ m_homeUrlRadioButton->setMaximumWidth(24);
+
+ QButtonGroup* initialViewGroup = new QButtonGroup(this);
+ initialViewGroup->addButton(m_rememberOpenedTabsRadioButton);
+ initialViewGroup->addButton(m_homeUrlRadioButton);
+
// create 'Home URL' editor
- QHBoxLayout* homeUrlBoxLayout = new QHBoxLayout();
+ m_homeUrlBoxLayoutContainer = new QWidget(this);
+ QHBoxLayout* homeUrlBoxLayout = new QHBoxLayout(m_homeUrlBoxLayoutContainer);
homeUrlBoxLayout->setContentsMargins(0, 0, 0, 0);
m_homeUrl = new QLineEdit();
@@ -67,7 +83,8 @@ StartupSettingsPage::StartupSettingsPage(const QUrl& url, QWidget* parent) :
connect(selectHomeUrlButton, &QPushButton::clicked,
this, &StartupSettingsPage::selectHomeUrl);
- QHBoxLayout* buttonBoxLayout = new QHBoxLayout();
+ m_buttonBoxLayoutContainer = new QWidget(this);
+ QHBoxLayout* buttonBoxLayout = new QHBoxLayout(m_buttonBoxLayoutContainer);
buttonBoxLayout->setContentsMargins(0, 0, 0, 0);
QPushButton* useCurrentButton = new QPushButton(i18nc("@action:button", "Use Current Location"));
@@ -79,41 +96,50 @@ StartupSettingsPage::StartupSettingsPage(const QUrl& url, QWidget* parent) :
connect(useDefaultButton, &QPushButton::clicked,
this, &StartupSettingsPage::useDefaultLocation);
- QVBoxLayout* homeBoxLayout = new QVBoxLayout();
- homeBoxLayout->setContentsMargins(0, 0, 0, 0);
- homeBoxLayout->addLayout(homeUrlBoxLayout);
- homeBoxLayout->addLayout(buttonBoxLayout);
+ QGridLayout* startInLocationLayout = new QGridLayout();
+ startInLocationLayout->setHorizontalSpacing(0);
+ startInLocationLayout->setContentsMargins(0, 0, 0, 0);
+ startInLocationLayout->addWidget(m_homeUrlRadioButton, 0, 0);
+ startInLocationLayout->addWidget(m_homeUrlBoxLayoutContainer, 0, 1);
+ startInLocationLayout->addWidget(m_buttonBoxLayoutContainer, 1, 1);
- topLayout->addRow(i18nc("@label:textbox", "Start in:"), homeBoxLayout);
+ topLayout->addRow(i18nc("@label:textbox", "Show on startup:"), m_rememberOpenedTabsRadioButton);
+ topLayout->addRow(QString(), startInLocationLayout);
topLayout->addItem(new QSpacerItem(0, Dolphin::VERTICAL_SPACER_HEIGHT, QSizePolicy::Fixed, QSizePolicy::Fixed));
-
- // create 'Split view', 'Show full path', 'Editable location' and 'Filter bar' checkboxes
- m_splitView = new QCheckBox(i18nc("@option:check Startup Settings", "Split view mode"));
- topLayout->addRow(i18nc("@label:checkbox", "Window options:"), m_splitView);
- m_editableUrl = new QCheckBox(i18nc("@option:check Startup Settings", "Editable location bar"));
+ m_splitView = new QCheckBox(i18nc("@option:check Startup Settings", "Begin in split view mode"));
+ topLayout->addRow(i18n("New windows:"), m_splitView);
+ m_filterBar = new QCheckBox(i18nc("@option:check Startup Settings", "Show filter bar"));
+ topLayout->addRow(QString(), m_filterBar);
+ m_editableUrl = new QCheckBox(i18nc("@option:check Startup Settings", "Make location bar editable"));
topLayout->addRow(QString(), m_editableUrl);
+
+ topLayout->addItem(new QSpacerItem(0, Dolphin::VERTICAL_SPACER_HEIGHT, QSizePolicy::Fixed, QSizePolicy::Fixed));
+
+ m_openExternallyCalledFolderInNewTab = new QCheckBox(i18nc("@option:check Startup Settings", "Open new folders in tabs"));
+ topLayout->addRow(i18nc("@label:checkbox", "General:"), m_openExternallyCalledFolderInNewTab);
m_showFullPath = new QCheckBox(i18nc("@option:check Startup Settings", "Show full path inside location bar"));
topLayout->addRow(QString(), m_showFullPath);
- m_filterBar = new QCheckBox(i18nc("@option:check Startup Settings", "Show filter bar"));
- topLayout->addRow(QString(), m_filterBar);
m_showFullPathInTitlebar = new QCheckBox(i18nc("@option:check Startup Settings", "Show full path in title bar"));
topLayout->addRow(QString(), m_showFullPathInTitlebar);
- m_openExternallyCalledFolderInNewTab = new QCheckBox(i18nc("@option:check Startup Settings", "Open new folders in tabs"));
- topLayout->addRow(QString(), m_openExternallyCalledFolderInNewTab);
-
loadSettings();
+ updateInitialViewOptions();
+
connect(m_homeUrl, &QLineEdit::textChanged, this, &StartupSettingsPage::slotSettingsChanged);
+ connect(m_rememberOpenedTabsRadioButton, &QRadioButton::toggled, this, &StartupSettingsPage::slotSettingsChanged);
+ connect(m_homeUrlRadioButton, &QRadioButton::toggled, this, &StartupSettingsPage::slotSettingsChanged);
+
connect(m_splitView, &QCheckBox::toggled, this, &StartupSettingsPage::slotSettingsChanged);
connect(m_editableUrl, &QCheckBox::toggled, this, &StartupSettingsPage::slotSettingsChanged);
- connect(m_showFullPath, &QCheckBox::toggled, this, &StartupSettingsPage::slotSettingsChanged);
connect(m_filterBar, &QCheckBox::toggled, this, &StartupSettingsPage::slotSettingsChanged);
- connect(m_showFullPathInTitlebar, &QCheckBox::toggled, this, &StartupSettingsPage::slotSettingsChanged);
+
connect(m_openExternallyCalledFolderInNewTab, &QCheckBox::toggled, this, &StartupSettingsPage::slotSettingsChanged);
+ connect(m_showFullPath, &QCheckBox::toggled, this, &StartupSettingsPage::slotSettingsChanged);
+ connect(m_showFullPathInTitlebar, &QCheckBox::toggled, this, &StartupSettingsPage::slotSettingsChanged);
}
StartupSettingsPage::~StartupSettingsPage()
@@ -132,12 +158,21 @@ void StartupSettingsPage::applySettings()
KMessageBox::error(this, i18nc("@info", "The location for the home folder is invalid or does not exist, it will not be applied."));
}
+ // Remove saved state if "remember open tabs" has been turned off
+ if (!m_rememberOpenedTabsRadioButton->isChecked()) {
+ KConfigGroup windowState{KSharedConfig::openConfig(QStringLiteral("dolphinrc")), "WindowState"};
+ if (windowState.exists()) {
+ windowState.deleteGroup();
+ }
+ }
+
+ settings->setRememberOpenedTabs(m_rememberOpenedTabsRadioButton->isChecked());
settings->setSplitView(m_splitView->isChecked());
settings->setEditableUrl(m_editableUrl->isChecked());
- settings->setShowFullPath(m_showFullPath->isChecked());
settings->setFilterBar(m_filterBar->isChecked());
- settings->setShowFullPathInTitlebar(m_showFullPathInTitlebar->isChecked());
settings->setOpenExternallyCalledFolderInNewTab(m_openExternallyCalledFolderInNewTab->isChecked());
+ settings->setShowFullPath(m_showFullPath->isChecked());
+ settings->setShowFullPathInTitlebar(m_showFullPathInTitlebar->isChecked());
settings->save();
}
@@ -155,9 +190,18 @@ void StartupSettingsPage::slotSettingsChanged()
// to apply the startup settings only if they have been explicitly changed by the user
// (see bug #254947).
GeneralSettings::setModifiedStartupSettings(true);
+
+ // Enable and disable home URL controls appropriately
+ updateInitialViewOptions();
emit changed();
}
+void StartupSettingsPage::updateInitialViewOptions()
+{
+ m_homeUrlBoxLayoutContainer->setEnabled(m_homeUrlRadioButton->isChecked());
+ m_buttonBoxLayoutContainer->setEnabled(m_homeUrlRadioButton->isChecked());
+}
+
void StartupSettingsPage::selectHomeUrl()
{
const QUrl homeUrl(QUrl::fromUserInput(m_homeUrl->text(), QString(), QUrl::AssumeLocalFile));
@@ -182,6 +226,8 @@ void StartupSettingsPage::loadSettings()
{
const QUrl url(Dolphin::homeUrl());
m_homeUrl->setText(url.toDisplayString(QUrl::PreferLocalFile));
+ m_rememberOpenedTabsRadioButton->setChecked(GeneralSettings::rememberOpenedTabs());
+ m_homeUrlRadioButton->setChecked(!GeneralSettings::rememberOpenedTabs());
m_splitView->setChecked(GeneralSettings::splitView());
m_editableUrl->setChecked(GeneralSettings::editableUrl());
m_showFullPath->setChecked(GeneralSettings::showFullPath());
diff --git a/src/settings/startup/startupsettingspage.h b/src/settings/startup/startupsettingspage.h
index a5e0b236f..d1c937f1f 100644
--- a/src/settings/startup/startupsettingspage.h
+++ b/src/settings/startup/startupsettingspage.h
@@ -23,8 +23,9 @@
#include <QUrl>
-class QLineEdit;
class QCheckBox;
+class QLineEdit;
+class QRadioButton;
/**
* @brief Page for the 'Startup' settings of the Dolphin settings dialog.
@@ -48,6 +49,7 @@ public:
private slots:
void slotSettingsChanged();
+ void updateInitialViewOptions();
void selectHomeUrl();
void useCurrentLocation();
void useDefaultLocation();
@@ -58,6 +60,10 @@ private:
private:
QUrl m_url;
QLineEdit* m_homeUrl;
+ QWidget* m_homeUrlBoxLayoutContainer;
+ QWidget* m_buttonBoxLayoutContainer;
+ QRadioButton* m_rememberOpenedTabsRadioButton;
+ QRadioButton* m_homeUrlRadioButton;
QCheckBox* m_splitView;
QCheckBox* m_editableUrl;
diff --git a/src/settings/viewmodes/viewsettingstab.cpp b/src/settings/viewmodes/viewsettingstab.cpp
index 06b0b8cf5..3e3f96ffc 100644
--- a/src/settings/viewmodes/viewsettingstab.cpp
+++ b/src/settings/viewmodes/viewsettingstab.cpp
@@ -33,6 +33,10 @@
#include <QComboBox>
#include <QHelpEvent>
#include <QFormLayout>
+#include <QSpinBox>
+#include <QRadioButton>
+#include <QButtonGroup>
+#include <QLabel>
ViewSettingsTab::ViewSettingsTab(Mode mode, QWidget* parent) :
QWidget(parent),
@@ -42,11 +46,11 @@ ViewSettingsTab::ViewSettingsTab(Mode mode, QWidget* parent) :
m_fontRequester(nullptr),
m_widthBox(nullptr),
m_maxLinesBox(nullptr),
- m_expandableFolders(nullptr)
+ m_expandableFolders(nullptr),
+ m_recursiveDirectorySizeLimit(nullptr)
{
QFormLayout* topLayout = new QFormLayout(this);
-
// Create "Icon Size" section
const int minRange = ZoomLevelInfo::minimumLevel();
const int maxRange = ZoomLevelInfo::maximumLevel();
@@ -75,7 +79,6 @@ ViewSettingsTab::ViewSettingsTab(Mode mode, QWidget* parent) :
m_fontRequester = new DolphinFontRequester(this);
topLayout->addRow(i18nc("@label:listbox", "Label font:"), m_fontRequester);
-
switch (m_mode) {
case IconsMode: {
m_widthBox = new QComboBox();
@@ -107,8 +110,30 @@ ViewSettingsTab::ViewSettingsTab(Mode mode, QWidget* parent) :
case DetailsMode:
m_expandableFolders = new QCheckBox(i18nc("@option:check", "Expandable"));
topLayout->addRow(i18nc("@label:checkbox", "Folders:"), m_expandableFolders);
- break;
- default:
+
+#ifndef Q_OS_WIN
+ // Sorting properties
+ m_numberOfItems = new QRadioButton(i18nc("option:radio", "Number of items"));
+ m_sizeOfContents = new QRadioButton(i18nc("option:radio", "Size of contents, up to "));
+
+ QButtonGroup* sortingModeGroup = new QButtonGroup(this);
+ sortingModeGroup->addButton(m_numberOfItems);
+ sortingModeGroup->addButton(m_sizeOfContents);
+
+ m_recursiveDirectorySizeLimit = new QSpinBox();
+ connect(m_recursiveDirectorySizeLimit, QOverload<int>::of(&QSpinBox::valueChanged), this, [this](int value) {
+ m_recursiveDirectorySizeLimit->setSuffix(i18np(" level deep", " levels deep", value));
+ });
+ m_recursiveDirectorySizeLimit->setRange(1, 20);
+ m_recursiveDirectorySizeLimit->setSingleStep(1);
+
+ QHBoxLayout *contentsSizeLayout = new QHBoxLayout();
+ contentsSizeLayout->addWidget(m_sizeOfContents);
+ contentsSizeLayout->addWidget(m_recursiveDirectorySizeLimit);
+
+ topLayout->addRow(i18nc("@title:group", "Folder size displays:"), m_numberOfItems);
+ topLayout->addRow(QString(), contentsSizeLayout);
+#endif
break;
}
@@ -128,6 +153,13 @@ ViewSettingsTab::ViewSettingsTab(Mode mode, QWidget* parent) :
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_numberOfItems, &QRadioButton::toggled, this, &ViewSettingsTab::changed);
+ connect(m_sizeOfContents, &QRadioButton::toggled, this, [=]() {
+ m_recursiveDirectorySizeLimit->setEnabled(m_sizeOfContents->isChecked());
+ });
+#endif
break;
default:
break;
@@ -153,6 +185,10 @@ void ViewSettingsTab::applySettings()
break;
case DetailsMode:
DetailsModeSettings::setExpandableFolders(m_expandableFolders->isChecked());
+#ifndef Q_OS_WIN
+ DetailsModeSettings::setDirectorySizeCount(m_numberOfItems->isChecked());
+ DetailsModeSettings::setRecursiveDirectorySizeLimit(m_recursiveDirectorySizeLimit->value());
+#endif
break;
default:
break;
@@ -201,6 +237,14 @@ void ViewSettingsTab::loadSettings()
break;
case DetailsMode:
m_expandableFolders->setChecked(DetailsModeSettings::expandableFolders());
+ if (DetailsModeSettings::directorySizeCount()) {
+ m_numberOfItems->setChecked(true);
+ m_recursiveDirectorySizeLimit->setEnabled(false);
+ } else {
+ m_sizeOfContents->setChecked(true);
+ m_recursiveDirectorySizeLimit->setEnabled(true);
+ }
+ m_recursiveDirectorySizeLimit->setValue(DetailsModeSettings::recursiveDirectorySizeLimit());
break;
default:
break;
diff --git a/src/settings/viewmodes/viewsettingstab.h b/src/settings/viewmodes/viewsettingstab.h
index fff882e5e..4d459fca2 100644
--- a/src/settings/viewmodes/viewsettingstab.h
+++ b/src/settings/viewmodes/viewsettingstab.h
@@ -28,6 +28,8 @@ class DolphinFontRequester;
class QComboBox;
class QCheckBox;
class QSlider;
+class QSpinBox;
+class QRadioButton;
/**
* @brief Represents one tab of the view-settings page.
@@ -72,6 +74,9 @@ private:
QComboBox* m_widthBox;
QComboBox* m_maxLinesBox;
QCheckBox* m_expandableFolders;
+ QRadioButton* m_numberOfItems;
+ QRadioButton* m_sizeOfContents;
+ QSpinBox* m_recursiveDirectorySizeLimit;
};
#endif
diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp
index d8f2aab93..aef0e85d6 100644
--- a/src/views/dolphinview.cpp
+++ b/src/views/dolphinview.cpp
@@ -364,7 +364,7 @@ void DolphinView::markUrlAsCurrent(const QUrl &url)
m_scrollToCurrentItem = true;
}
-void DolphinView::selectItems(const QRegExp& pattern, bool enabled)
+void DolphinView::selectItems(const QRegularExpression &regexp, bool enabled)
{
const KItemListSelectionManager::SelectionMode mode = enabled
? KItemListSelectionManager::Select
@@ -373,7 +373,7 @@ void DolphinView::selectItems(const QRegExp& pattern, bool enabled)
for (int index = 0; index < m_model->count(); index++) {
const KFileItem item = m_model->fileItem(index);
- if (pattern.exactMatch(item.text())) {
+ if (regexp.match(item.text()).hasMatch()) {
// An alternative approach would be to store the matching items in a KItemSet and
// select them in one go after the loop, but we'd need a new function
// KItemListSelectionManager::setSelected(KItemSet, SelectionMode mode)
@@ -679,19 +679,40 @@ void DolphinView::deleteSelectedItems()
}
}
-void DolphinView::cutSelectedItems()
+void DolphinView::cutSelectedItemsToClipboard()
{
QMimeData* mimeData = selectionMimeData();
KIO::setClipboardDataCut(mimeData, true);
QApplication::clipboard()->setMimeData(mimeData);
}
-void DolphinView::copySelectedItems()
+void DolphinView::copySelectedItemsToClipboard()
{
QMimeData* mimeData = selectionMimeData();
QApplication::clipboard()->setMimeData(mimeData);
}
+void DolphinView::copySelectedItemsToInactiveSplitView(const KFileItemList &selection, const QUrl &destinationUrl)
+{
+ KIO::CopyJob* job = KIO::copy(selection.urlList(), destinationUrl, KIO::DefaultFlags);
+ KJobWidgets::setWindow(job, this);
+
+ connect(job, &KIO::DropJob::result, this, &DolphinView::slotJobResult);
+ connect(job, &KIO::CopyJob::copyingDone, this, &DolphinView::slotCopyingDone);
+ KIO::FileUndoManager::self()->recordCopyJob(job);
+}
+
+void DolphinView::moveSelectedItemsToInactiveSplitView(const KFileItemList &selection, const QUrl &destinationUrl)
+{
+ KIO::CopyJob* job = KIO::move(selection.urlList(), destinationUrl, KIO::DefaultFlags);
+ KJobWidgets::setWindow(job, this);
+
+ connect(job, &KIO::DropJob::result, this, &DolphinView::slotJobResult);
+ connect(job, &KIO::CopyJob::copyingDone, this, &DolphinView::slotCopyingDone);
+ KIO::FileUndoManager::self()->recordCopyJob(job);
+
+}
+
void DolphinView::paste()
{
pasteToUrl(url());
@@ -1132,7 +1153,7 @@ void DolphinView::dropUrls(const QUrl &destUrl, QDropEvent *dropEvent, QWidget *
KIO::DropJob* job = DragAndDropHelper::dropUrls(destUrl, dropEvent, dropWidget);
if (job) {
- connect(job, &KIO::DropJob::result, this, &DolphinView::slotPasteJobResult);
+ connect(job, &KIO::DropJob::result, this, &DolphinView::slotJobResult);
if (destUrl == url()) {
// Mark the dropped urls as selected.
@@ -1185,6 +1206,11 @@ void DolphinView::slotSelectedItemTextPressed(int index)
}
}
+void DolphinView::slotCopyingDone(KIO::Job *, const QUrl &, const QUrl &to)
+{
+ slotItemCreated(to);
+}
+
void DolphinView::slotItemCreated(const QUrl& url)
{
if (m_markFirstNewlySelectedItemAsCurrent) {
@@ -1194,13 +1220,13 @@ void DolphinView::slotItemCreated(const QUrl& url)
m_selectedUrls << url;
}
-void DolphinView::slotPasteJobResult(KJob *job)
+void DolphinView::slotJobResult(KJob *job)
{
if (job->error()) {
emit errorMessage(job->errorString());
}
if (!m_selectedUrls.isEmpty()) {
- m_selectedUrls << KDirModel::simplifiedUrlList(m_selectedUrls);
+ m_selectedUrls = KDirModel::simplifiedUrlList(m_selectedUrls);
}
}
@@ -1493,13 +1519,27 @@ void DolphinView::calculateItemCount(int& fileCount,
KIO::filesize_t& totalFileSize) const
{
const int itemCount = m_model->count();
+
+ bool countFileSize = true;
+
+ // In case we have a precomputed value
+ const auto job = KIO::statDetails(m_model->rootItem().url(), KIO::StatJob::SourceSide, KIO::StatRecursiveSize);
+ job->exec();
+ const auto entry = job->statResult();
+ if (entry.contains(KIO::UDSEntry::UDS_RECURSIVE_SIZE)) {
+ totalFileSize = static_cast<KIO::filesize_t>(entry.numberValue(KIO::UDSEntry::UDS_RECURSIVE_SIZE));
+ countFileSize = false;
+ }
+
for (int i = 0; i < itemCount; ++i) {
const KFileItem item = m_model->fileItem(i);
if (item.isDir()) {
++folderCount;
} else {
++fileCount;
- totalFileSize += item.size();
+ if (countFileSize) {
+ totalFileSize += item.size();
+ }
}
}
}
@@ -1831,7 +1871,7 @@ void DolphinView::pasteToUrl(const QUrl& url)
m_clearSelectionBeforeSelectingNewItems = true;
m_markFirstNewlySelectedItemAsCurrent = true;
connect(job, &KIO::PasteJob::itemCreated, this, &DolphinView::slotItemCreated);
- connect(job, &KIO::PasteJob::result, this, &DolphinView::slotPasteJobResult);
+ connect(job, &KIO::PasteJob::result, this, &DolphinView::slotJobResult);
}
QList<QUrl> DolphinView::simplifiedSelectedUrls() const
diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h
index 83c5f92a4..0b2c0bce4 100644
--- a/src/views/dolphinview.h
+++ b/src/views/dolphinview.h
@@ -46,7 +46,7 @@ class ToolTipManager;
class VersionControlObserver;
class ViewProperties;
class QGraphicsSceneDragDropEvent;
-class QRegExp;
+class QRegularExpression;
/**
* @short Represents a view for the directory content.
@@ -183,10 +183,16 @@ public:
void markUrlAsCurrent(const QUrl& url);
/**
- * All items that match to the pattern \a pattern will get selected
- * if \a enabled is true and deselected if \a enabled is false.
+ * All items that match the regular expression \a regexp will get selected
+ * if \a enabled is true and deselected if \a enabled is false.
+ *
+ * Note that to match the whole string the pattern should be anchored:
+ * - you can anchor the pattern with QRegularExpression::anchoredPattern()
+ * - if you use QRegularExpresssion::wildcardToRegularExpression(), don't use
+ * QRegularExpression::anchoredPattern() as the former already returns an
+ * anchored pattern
*/
- void selectItems(const QRegExp& pattern, bool enabled);
+ void selectItems(const QRegularExpression &regexp, bool enabled);
/**
* Sets the zoom level to \a level. It is assured that the used
@@ -359,10 +365,22 @@ public slots:
* Copies all selected items to the clipboard and marks
* the items as cut.
*/
- void cutSelectedItems();
+ void cutSelectedItemsToClipboard();
/** Copies all selected items to the clipboard. */
- void copySelectedItems();
+ void copySelectedItemsToClipboard();
+
+ /**
+ * Copies all selected items to the inactive split view.
+ * Only used in Split View.
+ */
+ void copySelectedItemsToInactiveSplitView(const KFileItemList &selection, const QUrl &destinationUrl);
+
+ /**
+ * Moves all selected items to the inactive split view.
+ * Only used in Split View.
+ */
+ void moveSelectedItemsToInactiveSplitView(const KFileItemList &selection, const QUrl &destinationUrl);
/** Pastes the clipboard data to this view. */
void paste();
@@ -602,6 +620,7 @@ private slots:
void slotMouseButtonPressed(int itemIndex, Qt::MouseButtons buttons);
void slotRenameDialogRenamingFinished(const QList<QUrl>& urls);
void slotSelectedItemTextPressed(int index);
+ void slotCopyingDone(KIO::Job *, const QUrl &, const QUrl &to);
/*
* Is called when new items get pasted or dropped.
@@ -610,7 +629,7 @@ private slots:
/*
* Is called after all pasted or dropped items have been copied to destination.
*/
- void slotPasteJobResult(KJob *job);
+ void slotJobResult(KJob *job);
/**
* Emits the signal \a selectionChanged() with a small delay. This is
diff --git a/src/views/dolphinviewactionhandler.cpp b/src/views/dolphinviewactionhandler.cpp
index c61e1aaa9..e89e2e62c 100644
--- a/src/views/dolphinviewactionhandler.cpp
+++ b/src/views/dolphinviewactionhandler.cpp
@@ -283,7 +283,7 @@ void DolphinViewActionHandler::createActions()
"<para>Hidden items only differ from other ones in that their "
"name starts with a \".\". In general there is no need for "
"users to access them which is why they are hidden.</para>"));
- m_actionCollection->setDefaultShortcuts(showHiddenFiles, {Qt::ALT + Qt::Key_Period, Qt::CTRL + Qt::Key_H, Qt::Key_F8});
+ m_actionCollection->setDefaultShortcuts(showHiddenFiles, KStandardShortcut::showHideHiddenFiles());
connect(showHiddenFiles, &KToggleAction::triggered, this, &DolphinViewActionHandler::toggleShowHiddenFiles);
QAction* adjustViewProps = m_actionCollection->addAction(QStringLiteral("view_properties"));
diff --git a/src/views/versioncontrol/kversioncontrolplugin.h b/src/views/versioncontrol/kversioncontrolplugin.h
index 287974534..0d94a3fc8 100644
--- a/src/views/versioncontrol/kversioncontrolplugin.h
+++ b/src/views/versioncontrol/kversioncontrolplugin.h
@@ -180,14 +180,17 @@ public:
virtual ItemVersion itemVersion(const KFileItem& item) const = 0;
/**
- * @return List of actions that are available for the items \p items.
- * It is recommended to keep the number of returned actions small
- * in case if an item is an unversioned directory that is not
- * inside the hierarchy tree of the version control system. This
- * prevents having a cluttered context menu for directories
- * outside the version control system.
+ * @return List of actions that are available for the \p items in a version controlled
+ * path.
*/
- virtual QList<QAction*> actions(const KFileItemList& items) const = 0;
+ virtual QList<QAction*> versionControlActions(const KFileItemList& items) const = 0;
+
+ /**
+ * @return List of actions that are available for the out of version control
+ * items \p items. It's opposed to the \p versionedActions. Common usage
+ * is for clone/checkout actions.
+ */
+ virtual QList<QAction*> outOfVersionControlActions(const KFileItemList& items) const = 0;
Q_SIGNALS:
/**
diff --git a/src/views/versioncontrol/versioncontrolobserver.cpp b/src/views/versioncontrol/versioncontrolobserver.cpp
index 2d801686e..2f0632243 100644
--- a/src/views/versioncontrol/versioncontrolobserver.cpp
+++ b/src/views/versioncontrol/versioncontrolobserver.cpp
@@ -118,11 +118,19 @@ QList<QAction*> VersionControlObserver::actions(const KFileItemList& items) cons
}
}
- if (!m_model || hasNullItems || !isVersioned()) {
+ if (!m_model || hasNullItems) {
return {};
}
- return m_plugin->actions(items);
+ if (isVersionControlled()) {
+ return m_plugin->versionControlActions(items);
+ } else {
+ QList<QAction*> actions;
+ for (const auto &plugin : qAsConst(m_plugins)) {
+ actions << plugin.first->outOfVersionControlActions(items);
+ }
+ return actions;
+ }
}
void VersionControlObserver::delayedDirectoryVerification()
@@ -160,21 +168,8 @@ void VersionControlObserver::verifyDirectory()
return;
}
- if (m_plugin) {
- m_plugin->disconnect(this);
- }
-
m_plugin = searchPlugin(rootItem.url());
if (m_plugin) {
- connect(m_plugin, &KVersionControlPlugin::itemVersionsChanged,
- this, &VersionControlObserver::silentDirectoryVerification);
- connect(m_plugin, &KVersionControlPlugin::infoMessage,
- this, &VersionControlObserver::infoMessage);
- connect(m_plugin, &KVersionControlPlugin::errorMessage,
- this, &VersionControlObserver::errorMessage);
- connect(m_plugin, &KVersionControlPlugin::operationCompletedMessage,
- this, &VersionControlObserver::operationCompletedMessage);
-
if (!m_versionedDirectory) {
m_versionedDirectory = true;
@@ -303,6 +298,15 @@ KVersionControlPlugin* VersionControlObserver::searchPlugin(const QUrl& director
if (enabledPlugins.contains((*it)->name())) {
KVersionControlPlugin* plugin = (*it)->createInstance<KVersionControlPlugin>(this);
if (plugin) {
+ connect(plugin, &KVersionControlPlugin::itemVersionsChanged,
+ this, &VersionControlObserver::silentDirectoryVerification);
+ connect(plugin, &KVersionControlPlugin::infoMessage,
+ this, &VersionControlObserver::infoMessage);
+ connect(plugin, &KVersionControlPlugin::errorMessage,
+ this, &VersionControlObserver::errorMessage);
+ connect(plugin, &KVersionControlPlugin::operationCompletedMessage,
+ this, &VersionControlObserver::operationCompletedMessage);
+
m_plugins.append( qMakePair(plugin, plugin->fileName()) );
}
}
@@ -360,7 +364,7 @@ KVersionControlPlugin* VersionControlObserver::searchPlugin(const QUrl& director
return bestPlugin;
}
-bool VersionControlObserver::isVersioned() const
+bool VersionControlObserver::isVersionControlled() const
{
return m_versionedDirectory && m_plugin;
}
diff --git a/src/views/versioncontrol/versioncontrolobserver.h b/src/views/versioncontrol/versioncontrolobserver.h
index 66f992963..648c9d6fd 100644
--- a/src/views/versioncontrol/versioncontrolobserver.h
+++ b/src/views/versioncontrol/versioncontrolobserver.h
@@ -143,7 +143,7 @@ private:
/**
* Returns true, if the directory contains a version control information.
*/
- bool isVersioned() const;
+ bool isVersionControlled() const;
private:
bool m_pendingItemStatesUpdate;