]> cloud.milkyroute.net Git - dolphin.git/commitdiff
Merge branch 'release/20.04'
authorAlexander Lohnau <alexander.lohnau@gmx.de>
Tue, 23 Jun 2020 15:42:06 +0000 (17:42 +0200)
committerAlexander Lohnau <alexander.lohnau@gmx.de>
Tue, 23 Jun 2020 15:42:06 +0000 (17:42 +0200)
92 files changed:
.gitignore
CMakeLists.txt
README.md [moved from README with 99% similarity]
doc/index.docbook
doc/preferences-startup.png
logo.png [new file with mode: 0644]
src/CMakeLists.txt
src/config-packagekit.h.cmake [new file with mode: 0644]
src/dbusinterface.h
src/dolphinbookmarkhandler.cpp
src/dolphinmainwindow.cpp
src/dolphinpart.cpp
src/dolphinpart.desktop
src/dolphinpart_ext.cpp
src/dolphintabwidget.cpp
src/dolphintabwidget.h
src/dolphinui.rc
src/dolphinviewcontainer.cpp
src/dolphinviewcontainer.h
src/filterbar/filterbar.cpp
src/global.cpp
src/global.h
src/kitemviews/kfileitemlistview.cpp
src/kitemviews/kfileitemlistview.h
src/kitemviews/kfileitemlistwidget.cpp
src/kitemviews/kfileitemmodel.cpp
src/kitemviews/kfileitemmodelrolesupdater.cpp
src/kitemviews/kfileitemmodelrolesupdater.h
src/kitemviews/kitemlistcontroller.cpp
src/kitemviews/kitemlistwidget.cpp
src/kitemviews/kstandarditemlistwidget.cpp
src/kitemviews/private/kdirectorycontentscounter.cpp
src/kitemviews/private/kdirectorycontentscounter.h
src/kitemviews/private/kdirectorycontentscounterworker.cpp
src/kitemviews/private/kdirectorycontentscounterworker.h
src/kitemviews/private/kfileitemmodelfilter.cpp
src/kitemviews/private/kfileitemmodelfilter.h
src/main.cpp
src/org.kde.dolphin.appdata.xml
src/org.kde.dolphin.desktop
src/panels/information/informationpanel.cpp
src/panels/information/informationpanelcontent.cpp
src/panels/information/pixmapviewer.cpp
src/panels/information/pixmapviewer.h
src/panels/places/placesitem.cpp
src/panels/terminal/org.kde.KIOFuse.VFS.xml [new file with mode: 0644]
src/panels/terminal/terminalpanel.cpp
src/panels/terminal/terminalpanel.h
src/search/dolphinquery.cpp
src/search/dolphinquery.h
src/search/dolphinsearchbox.cpp
src/search/dolphinsearchbox.h
src/settings/dolphin_detailsmodesettings.kcfg
src/settings/dolphin_generalsettings.kcfg
src/settings/general/previewssettingspage.cpp
src/settings/general/previewssettingspage.h
src/settings/kcm/kcmdolphingeneral.cpp
src/settings/kcm/kcmdolphingeneral.desktop
src/settings/kcm/kcmdolphingeneral.h
src/settings/kcm/kcmdolphinnavigation.cpp
src/settings/kcm/kcmdolphinnavigation.desktop
src/settings/kcm/kcmdolphinnavigation.h
src/settings/kcm/kcmdolphinservices.cpp
src/settings/kcm/kcmdolphinservices.desktop
src/settings/kcm/kcmdolphinservices.h
src/settings/kcm/kcmdolphinviewmodes.cpp
src/settings/kcm/kcmdolphinviewmodes.desktop
src/settings/kcm/kcmdolphinviewmodes.h
src/settings/services/servicemenuinstaller/CMakeLists.txt
src/settings/services/servicemenuinstaller/servicemenuinstaller.cpp
src/settings/services/servicessettingspage.cpp
src/settings/services/servicessettingspage.h
src/settings/startup/startupsettingspage.cpp
src/settings/startup/startupsettingspage.h
src/settings/viewmodes/viewsettingstab.cpp
src/settings/viewmodes/viewsettingstab.h
src/statusbar/dolphinstatusbar.cpp
src/statusbar/spaceinfoobserver.cpp
src/statusbar/spaceinfoobserver.h
src/statusbar/statusbarspaceinfo.cpp
src/statusbar/statusbarspaceinfo.h
src/tests/CMakeLists.txt
src/tests/dolphinquerytest.cpp
src/tests/kfileitemmodeltest.cpp
src/views/dolphinitemlistview.cpp
src/views/dolphinview.cpp
src/views/dolphinview.h
src/views/dolphinviewactionhandler.cpp
src/views/versioncontrol/fileviewversioncontrolplugin.desktop
src/views/versioncontrol/kversioncontrolplugin.h
src/views/versioncontrol/versioncontrolobserver.cpp
src/views/versioncontrol/versioncontrolobserver.h

index c48f92390db5edc685e822fdc67e9900d4765815..6c1df4de47c08cbf08b9eb3526c4e24e5cdd105b 100644 (file)
@@ -4,3 +4,4 @@ CMakeLists.txt.user
 .directory
 *.kdev4
 /build*/
+.cmake/
index 6ccd9f8f267a3e1b6de1a984d4659f0e4e308999..397f3161d55cf3eaee9bb33accf9c5e06915d50d 100644 (file)
@@ -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 "2")
+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.71.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"
similarity index 99%
rename from README
rename to README.md
index 970fa1d43117e98c4a6f5e94c2e23aae99039bdc..8335d40774f0cec9ceb2ccd6b83138477f82eaa1 100644 (file)
--- a/README
+++ b/README.md
@@ -14,7 +14,7 @@ To submit a patch to Dolphin, use https://phabricator.kde.org. See https://commu
 
 
 
-Development philosophy
+Development Philosophy
 ======================
 Dolphin is a file manager focusing on usability. When reading the term Usability people often assume that the focus is on newbies and only basic features are offered. This is not the case; Dolphin is quite full-featured, but the features are carefully chosen so as to not impede any of the users in the target user groups.
 
index d1342d0d479c60dcdf049e01e81762d4ea946580..50fc37d91182d68c84b86765bf1540c682b27c4a 100644 (file)
@@ -70,8 +70,8 @@
 
 <legalnotice>&FDLNotice;</legalnotice>
 
-<date>2020-03-17</date>
-<releaseinfo>Applications 20.04</releaseinfo>
+<date>2020-06-10</date>
+<releaseinfo>Applications 20.08</releaseinfo>
 
 <abstract>
 <para>
@@ -1066,7 +1066,7 @@ to close the inactive pane when you are turning off the split view mode, &eg; pr
 
 <para>
 In this tab, you can configure for which file types previews are shown.
-Moreover, the maximum size of remote files for which previews are generated can be chosen.
+Moreover, the maximum size of local and remote files for which previews are generated can be chosen.
 </para>
 <para>
 If previews are enabled for folders, previews of some files in the folder will
@@ -1137,26 +1137,55 @@ 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.
@@ -1164,20 +1193,11 @@ Otherwise, a shortened version of the path is shown if it begins with the path o
 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>
@@ -1705,6 +1729,29 @@ The name of this file has to be entered in a dialog.
 </action></para></listitem>
 </varlistentry>
 
+<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>
@@ -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>
index 2b780a4c1e6abff12f337bc12cd19b35807997d6..192efe193f74ee3ccdaf06622bac43802b92d492 100644 (file)
Binary files a/doc/preferences-startup.png and b/doc/preferences-startup.png differ
diff --git a/logo.png b/logo.png
new file mode 100644 (file)
index 0000000..de289b2
Binary files /dev/null and b/logo.png differ
index 02a43a2094270a53c572b2dc5bddf70862cbe4bf..eabe80f61187e3c7b696fd507920ee48a53df6fc 100644 (file)
@@ -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 (file)
index 0000000..780fff5
--- /dev/null
@@ -0,0 +1 @@
+#cmakedefine HAVE_PACKAGEKIT
index 391916d6271998150ed9566aa27bc12eeec6b708..c1029ea23c516a5dd3f92ed615224813a6c16964 100644 (file)
@@ -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;
 
index ded83d6bb9c87967a95980e1403be1825166201e..0d31b8984d56a76af46840027a8f70fb427f7593 100644 (file)
@@ -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()
index dd1dcdac5df78a3a579b7b81afd0a4b879a0cff2..d45b77676cd01626471ca4da370d91d629b0dca0 100644 (file)
 #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>
@@ -582,6 +584,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();
 
@@ -647,12 +657,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()
@@ -929,7 +939,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()
@@ -1116,6 +1129,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);
 
@@ -1244,7 +1259,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);
     }
@@ -1348,6 +1363,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"));
@@ -1873,12 +1906,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"));
 
@@ -1896,16 +1935,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());
     }
 }
 
index 7e7425121ca81105c7016630a2b6d9289550d5d6..12c361011dffd14330e62bae4ebf42c06997544a 100644 (file)
@@ -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();
     }
 }
 
index 13e267ad5df8e365e9d2f4cfdbeea5abb561982f..abd206d6a512c1aa58f610596e821fdc768a60c5 100644 (file)
@@ -3,6 +3,7 @@ Type=Service
 Name=Dolphin View
 Name[ar]=منظور دولفين
 Name[ast]=Vista de Dolphin
+Name[az]=Dolphin görünüşü
 Name[ca]=Vista del Dolphin
 Name[ca@valencia]=Vista del Dolphin
 Name[cs]=Pohled Dolphin
@@ -63,6 +64,7 @@ Actions=icons;details;compact;
 Name=Icons
 Name[ar]=الأيقونات
 Name[ast]=Iconos
+Name[az]=İkonlar
 Name[ca]=Icones
 Name[ca@valencia]=Icones
 Name[cs]=Ikony
@@ -115,6 +117,7 @@ Exec=dolphin
 Name=Compact
 Name[ar]=متراصّ
 Name[ast]=Compauta
+Name[az]=Yığcam
 Name[ca]=Compacta
 Name[ca@valencia]=Compacta
 Name[cs]=Kompaktní
@@ -166,6 +169,7 @@ Exec=dolphin
 Name=Details
 Name[ar]=التّفاصيل
 Name[ast]=Detalles
+Name[az]=Ətraflı
 Name[ca]=Detalls
 Name[ca@valencia]=Detalls
 Name[cs]=Podrobnosti
index 8c6e9641adec4e3e07a54dcf8f400a7bf5b48b77..83dfddb1640bf33bb891687873862f8c61261f50 100644 (file)
@@ -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()
index 89c54baf54b421611318eba1283ef513eeae9fa1..7a431152ed61a5f46ca4a99caef6359bd3978993 100644 (file)
@@ -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()->copySelectedItems(activeViewContainer->view()->selectedItems(), tabPage->secondaryViewContainer()->url());
+    } else {
+        // copy from right panel to left
+        activeViewContainer->view()->copySelectedItems(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()->moveSelectedItems(activeViewContainer->view()->selectedItems(), tabPage->secondaryViewContainer()->url());
+    } else {
+        // move from right panel to left
+        activeViewContainer->view()->moveSelectedItems(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);
 }
index 746aec6c64ec347fdb2611c22d8e01a115374958..f0ce11ce8994e4013df7bb9e3d7d0e3090de625c 100644 (file)
@@ -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
index e717b67ae96d9f3cfd1ce48ef8062a544faa13d9..acb2f1dcd75fe13b3d7d004bdce3acdf54e15ab9 100644 (file)
@@ -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>
index 3a17805ab8916667d15752c942c699fdcccc1b24..4ab34a06a85ef1632c6bdd8ed499489a1e03023b 100644 (file)
@@ -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);
 
index 5207d2d35d47cf39572d156916d8ce504d65809f..52e63cbe04f34e9e670c8c39232c0854fe45fbf5 100644 (file)
@@ -133,6 +133,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
index 50af2c6c7bd6e46b627afd67544576360fc6e895..93e929c4599e7ef4435484391f0d43696f256200 100644 (file)
 FilterBar::FilterBar(QWidget* parent) :
     QWidget(parent)
 {
-    // Create close button
-    QToolButton *closeButton = new QToolButton(this);
-    closeButton->setAutoRaise(true);
-    closeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close")));
-    closeButton->setToolTip(i18nc("@info:tooltip", "Hide Filter Bar"));
-    connect(closeButton, &QToolButton::clicked, this, &FilterBar::closeRequest);
-
     // Create button to lock text when changing folders
     m_lockButton = new QToolButton(this);
     m_lockButton->setAutoRaise(true);
@@ -57,12 +50,19 @@ FilterBar::FilterBar(QWidget* parent) :
             this, &FilterBar::filterChanged);
     setFocusProxy(m_filterInput);
 
+    // Create close button
+    QToolButton *closeButton = new QToolButton(this);
+    closeButton->setAutoRaise(true);
+    closeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close")));
+    closeButton->setToolTip(i18nc("@info:tooltip", "Hide Filter Bar"));
+    connect(closeButton, &QToolButton::clicked, this, &FilterBar::closeRequest);
+
     // Apply layout
     QHBoxLayout* hLayout = new QHBoxLayout(this);
     hLayout->setContentsMargins(0, 0, 0, 0);
-    hLayout->addWidget(closeButton);
     hLayout->addWidget(m_lockButton);
     hLayout->addWidget(m_filterInput);
+    hLayout->addWidget(closeButton);
 }
 
 FilterBar::~FilterBar()
index 5236fa4d102a9086367bfa61d62dd9eaafff3331..6a702cf43bacf08cd981b1f90f0012a19f1d3400 100644 (file)
@@ -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;
     }
@@ -133,7 +104,7 @@ bool Dolphin::attachToExistingInstance(const QList<QUrl>& inputUrls, bool openFi
     }
     dolphinInterfaces.front().second << newUrls;
 
-    for (const auto& interface: dolphinInterfaces) {
+    for (const auto& interface: qAsConst(dolphinInterfaces)) {
         if (!interface.second.isEmpty()) {
             auto reply = openFiles ? interface.first->openFiles(interface.second, splitView) : interface.first->openDirectories(interface.second, splitView);
             reply.waitForFinished();
@@ -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;
+}
index 7ee564581c6b7b1ff14e71610489ec7e0d8817db..daf86134e435265cc834de4bd49d7cef3c906ea8 100644 (file)
@@ -24,6 +24,8 @@
 #include <QUrl>
 #include <QWidget>
 
+class OrgKdeDolphinMainWindowInterface;
+
 namespace Dolphin {
     QList<QUrl> validateUris(const QStringList& uriList);
 
@@ -51,6 +53,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
      */
index 80d85aa2e1e8e3e8cb809d19c940d158bb7b72d1..4fffbcbfd208bebc17b5a0b33eb76a1e84b82c55 100644 (file)
@@ -116,6 +116,18 @@ QStringList KFileItemListView::enabledPlugins() const
     return m_modelRolesUpdater ? m_modelRolesUpdater->enabledPlugins() : QStringList();
 }
 
+void KFileItemListView::setLocalFileSizePreviewLimit(const qlonglong size)
+{
+    if (m_modelRolesUpdater) {
+        m_modelRolesUpdater->setLocalFileSizePreviewLimit(size);
+    }
+}
+
+qlonglong KFileItemListView::localFileSizePreviewLimit() const
+{
+    return m_modelRolesUpdater ? m_modelRolesUpdater->localFileSizePreviewLimit() : 0;
+}
+
 QPixmap KFileItemListView::createDragPixmap(const KItemSet& indexes) const
 {
     if (!model()) {
index c13ea5ef2d403395d96ee513a2e1bf781ffef609..92005c2df5105742e3b476ba4fe21a9a99515765 100644 (file)
@@ -71,6 +71,17 @@ public:
      */
     QStringList enabledPlugins() const;
 
+    /**
+     * Sets the maximum file size of local files for which
+     * previews will be generated (if enabled). A value of 0
+     * indicates no file size limit.
+     * Per default the value from KConfigGroup "PreviewSettings"
+     * MaximumSize is used, 0 otherwise.
+     * @param size
+     */
+    void setLocalFileSizePreviewLimit(qlonglong size);
+    qlonglong localFileSizePreviewLimit() const;
+
     QPixmap createDragPixmap(const KItemSet& indexes) const override;
 
 protected:
index 40b8ccf3717a4a10965cf8c361c8be7e743fb57a..a495a4c2ff63095511f421b740cc68c23f1e1388 100644 (file)
@@ -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 {
index e4dca2734871d3b0c9e0dc0da1375fab76d202e5..ac3c33e22e44af1a0680c1684c50dfd0139c084b 100644 (file)
@@ -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():
index bf2c84c4031ffa6346dc2e5813d6c7a0ea7b1007..eb2c1b64626c8d550cb8c1cc5b0fce349d51c9b8 100644 (file)
@@ -44,7 +44,6 @@
 #include <QElapsedTimer>
 #include <QTimer>
 
-
 // #define KFILEITEMMODELROLESUPDATER_DEBUG
 
 namespace {
@@ -86,7 +85,8 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO
     m_recentlyChangedItemsTimer(nullptr),
     m_recentlyChangedItems(),
     m_changedItems(),
-    m_directoryContentsCounter(nullptr)
+    m_directoryContentsCounter(nullptr),
+    m_localFileSizePreviewLimit(0)
   #ifdef HAVE_BALOO
   , m_balooFileMonitor(nullptr)
   #endif
@@ -95,6 +95,7 @@ KFileItemModelRolesUpdater::KFileItemModelRolesUpdater(KFileItemModel* model, QO
 
     const KConfigGroup globalConfig(KSharedConfig::openConfig(), "PreviewSettings");
     m_enabledPlugins = globalConfig.readEntry("Plugins", KIO::PreviewJob::defaultPlugins());
+    m_localFileSizePreviewLimit = static_cast<qulonglong>(globalConfig.readEntry("MaximumSize", 0));
 
     connect(m_model, &KFileItemModel::itemsInserted,
             this,    &KFileItemModelRolesUpdater::slotItemsInserted);
@@ -108,9 +109,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);
 
@@ -318,6 +319,16 @@ QStringList KFileItemModelRolesUpdater::enabledPlugins() const
     return m_enabledPlugins;
 }
 
+void KFileItemModelRolesUpdater::setLocalFileSizePreviewLimit(const qlonglong size)
+{
+    m_localFileSizePreviewLimit = size;
+}
+
+qlonglong KFileItemModelRolesUpdater::localFileSizePreviewLimit() const
+{
+    return m_localFileSizePreviewLimit;
+}
+
 void KFileItemModelRolesUpdater::slotItemsInserted(const KItemRangeList& itemRanges)
 {
     QElapsedTimer timer;
@@ -750,7 +761,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 +772,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);
         }
     }
 }
@@ -900,7 +910,7 @@ void KFileItemModelRolesUpdater::startPreviewJob()
 
     KIO::PreviewJob* job = new KIO::PreviewJob(itemSubSet, cacheSize, &m_enabledPlugins);
 
-    job->setIgnoreMaximumSize(itemSubSet.first().isLocalFile());
+    job->setIgnoreMaximumSize(itemSubSet.first().isLocalFile() && m_localFileSizePreviewLimit <= 0);
     if (job->uiDelegate()) {
         KJobWidgets::setWindow(job, qApp->activeWindow());
     }
@@ -997,7 +1007,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 +1080,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
         }
index 9078c8e0d64cdc89607b27b656c46967a919865d..b881b73e4b0b4e369bc89f3d4025a93f6aa43a3d 100644 (file)
@@ -154,6 +154,17 @@ public:
      */
     QStringList enabledPlugins() const;
 
+    /**
+     * Sets the maximum file size of local files for which
+     * previews will be generated (if enabled). A value of 0
+     * indicates no file size limit.
+     * Per default the value from KConfigGroup "PreviewSettings"
+     * MaximumSize is used, 0 otherwise.
+     * @param size
+     */
+    void setLocalFileSizePreviewLimit(qlonglong size);
+    qlonglong localFileSizePreviewLimit() const;
+
 private slots:
     void slotItemsInserted(const KItemRangeList& itemRanges);
     void slotItemsRemoved(const KItemRangeList& itemRanges);
@@ -212,7 +223,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:
     /**
@@ -313,6 +324,7 @@ private:
     QSet<QByteArray> m_roles;
     QSet<QByteArray> m_resolvableRoles;
     QStringList m_enabledPlugins;
+    qulonglong m_localFileSizePreviewLimit;
 
     // Items for which the sort role still has to be determined.
     QSet<KFileItem> m_pendingSortRoleItems;
index 5ddf52e5f193dc84671c3248696d74f2bbeb8bf3..0c25ebb8b9ace0f2703ffcb4dffdf64172cc21d5 100644 (file)
@@ -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);
index 49a13f68fa096ef549a069d6d30147602f673bb9..42bf9ebdcbb8397cf5feb23a19c766a9b4a36510 100644 (file)
@@ -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);
index 15a618207f286bcebff67a90a1c4603305021e77..4018b3c15747283be5575b5d2f94a75e2954a4dd 100644 (file)
@@ -88,7 +88,7 @@ qreal KStandardItemListWidgetInformant::preferredRoleColumnWidth(const QByteArra
         // If current item is a link, we use the customized link font metrics instead of the normal font metrics.
         const QFontMetrics& fontMetrics = itemIsLink(index, view) ? linkFontMetrics : normalFontMetrics;
 
-        width += fontMetrics.width(text);
+        width += fontMetrics.boundingRect(text).width();
 
         if (role == "text") {
             if (view->supportsItemExpanding()) {
@@ -214,12 +214,12 @@ void KStandardItemListWidgetInformant::calculateCompactLayoutItemSizeHints(QVect
         qreal maximumRequiredWidth = 0.0;
 
         if (showOnlyTextRole) {
-            maximumRequiredWidth = fontMetrics.width(itemText(index, view));
+            maximumRequiredWidth = fontMetrics.boundingRect(itemText(index, view)).width();
         } else {
             const QHash<QByteArray, QVariant>& values = view->model()->data(index);
             foreach (const QByteArray& role, visibleRoles) {
                 const QString& text = roleText(role, values);
-                const qreal requiredWidth = fontMetrics.width(text);
+                const qreal requiredWidth = fontMetrics.boundingRect(text).width();
                 maximumRequiredWidth = qMax(maximumRequiredWidth, requiredWidth);
             }
         }
@@ -478,7 +478,7 @@ QRectF KStandardItemListWidget::textFocusRect() const
         const KItemListStyleOption& option = styleOption();
         if (option.extendedSelectionRegion) {
             const QString text = textInfo->staticText.text();
-            rect.setWidth(m_customizedFontMetrics.width(text) + 2 * option.padding);
+            rect.setWidth(m_customizedFontMetrics.boundingRect(text).width() + 2 * option.padding);
         }
 
         return rect;
@@ -1115,11 +1115,11 @@ void KStandardItemListWidget::updateTextsCache()
 
 QString KStandardItemListWidget::elideRightKeepExtension(const QString &text, int elidingWidth) const
 {
-    auto extensionIndex = text.lastIndexOf('.');
+    const auto extensionIndex = text.lastIndexOf('.');
     if (extensionIndex != -1) {
         // has file extension
-        auto extensionLength = text.length() - extensionIndex;
-        auto extensionWidth = m_customizedFontMetrics.width(text.right(extensionLength));
+        const auto extensionLength = text.length() - extensionIndex;
+        const auto extensionWidth = m_customizedFontMetrics.boundingRect(text.right(extensionLength)).width();
         if (elidingWidth > extensionWidth && extensionLength < 6 && (float(extensionWidth) / float(elidingWidth)) < 0.3) {
             // if we have room to display the file extension and the extension is not too long
             QString ret = m_customizedFontMetrics.elidedText(text.chopped(extensionLength),
@@ -1241,7 +1241,7 @@ void KStandardItemListWidget::updateIconsLayoutTextCache()
             if (requiredWidth > maxWidth) {
                 const QString elidedText = elideRightKeepExtension(text, maxWidth);
                 textInfo->staticText.setText(elidedText);
-                requiredWidth = m_customizedFontMetrics.width(elidedText);
+                requiredWidth = m_customizedFontMetrics.boundingRect(elidedText).width();
             } else if (role == "rating") {
                 // Use the width of the rating pixmap, because the rating text is empty.
                 requiredWidth = m_rating.width();
@@ -1285,7 +1285,7 @@ void KStandardItemListWidget::updateCompactLayoutTextCache()
         TextInfo* textInfo = m_textInfo.value(role);
         textInfo->staticText.setText(text);
 
-        qreal requiredWidth = m_customizedFontMetrics.width(text);
+        qreal requiredWidth = m_customizedFontMetrics.boundingRect(text).width();
         if (requiredWidth > maxWidth) {
             requiredWidth = maxWidth;
             const QString elidedText = elideRightKeepExtension(text, maxWidth);
@@ -1335,7 +1335,7 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache()
         QString text = roleText(role, values);
 
         // Elide the text in case it does not fit into the available column-width
-        qreal requiredWidth = m_customizedFontMetrics.width(text);
+        qreal requiredWidth = m_customizedFontMetrics.boundingRect(text).width();
         const qreal roleWidth = columnWidth(role);
         qreal availableTextWidth = roleWidth - columnWidthInc;
 
@@ -1346,7 +1346,7 @@ void KStandardItemListWidget::updateDetailsLayoutTextCache()
 
         if (requiredWidth > availableTextWidth) {
             text = elideRightKeepExtension(text, availableTextWidth);
-            requiredWidth = m_customizedFontMetrics.width(text);
+            requiredWidth = m_customizedFontMetrics.boundingRect(text).width();
         }
 
         TextInfo* textInfo = m_textInfo.value(role);
@@ -1486,14 +1486,8 @@ QPixmap KStandardItemListWidget::pixmapForIcon(const QString& name, const QStrin
     const QString key = "KStandardItemListWidget:" % name % ":" % overlays.join(QLatin1Char(':')) % ":" % QString::number(size) % ":" % QString::number(mode);
     QPixmap pixmap;
 
-    if (!QPixmapCache::find(key, pixmap)) {
-        QIcon icon = QIcon::fromTheme(name);
-        if (icon.isNull()) {
-            icon = QIcon(name);
-        }
-        if (icon.isNull()) {
-            icon = fallbackIcon;
-        }
+    if (!QPixmapCache::find(key, &pixmap)) {
+        const QIcon icon = QIcon::fromTheme(name, fallbackIcon);
 
         pixmap = icon.pixmap(size / qApp->devicePixelRatio(), size / qApp->devicePixelRatio(), mode);
         if (pixmap.width() != size || pixmap.height() != size) {
index bd204fe8e24a353a16a0dccdc6ff821b668c8474..4d6a4861ca10ef3f3f69b7d0f0696ae18f3640e1 100644 (file)
 #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,49 +86,45 @@ KDirectoryContentsCounter::~KDirectoryContentsCounter()
     }
 }
 
-void KDirectoryContentsCounter::addDirectory(const QString& path)
+void KDirectoryContentsCounter::scanDirectory(const QString& path)
 {
     startWorker(path);
 }
 
-int KDirectoryContentsCounter::countDirectoryContentsSynchronously(const QString& path)
+void KDirectoryContentsCounter::slotResult(const QString& path, int count, long size)
 {
-    const QString resolvedPath = QFileInfo(path).canonicalFilePath();
+    m_workerIsBusy = false;
+
+    const QFileInfo info = QFileInfo(path);
+    const QString resolvedPath = info.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;
+    if (!m_priorityQueue.isEmpty()) {
+        startWorker(m_priorityQueue.takeFirst());
+    } else if (!m_queue.isEmpty()) {
+        startWorker(m_queue.takeFirst());
     }
 
-    return KDirectoryContentsCounterWorker::subItemsCount(path, options);
-}
-
-void KDirectoryContentsCounter::slotResult(const QString& path, int count)
-{
-    m_workerIsBusy = false;
-
-    const QString resolvedPath = QFileInfo(path).canonicalFilePath();
-
-    if (!m_dirWatcher->contains(resolvedPath)) {
-        m_dirWatcher->addDir(resolvedPath);
-        m_watchedDirs.insert(resolvedPath);
+    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 (!m_queue.isEmpty()) {
-        startWorker(m_queue.dequeue());
+    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));
     }
 
-    emit result(path, count);
+    // sends the results
+    emit result(resolvedPath, count, size);
 }
 
 void KDirectoryContentsCounter::slotDirWatchDirty(const QString& path)
@@ -146,7 +149,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,8 +169,23 @@ void KDirectoryContentsCounter::slotItemsRemoved()
 
 void KDirectoryContentsCounter::startWorker(const QString& path)
 {
+    const bool alreadyInCache = s_cache->contains(path);
+    if (alreadyInCache) {
+        // 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);
+        if (!m_queue.contains(path) && !m_priorityQueue.contains(path)) {
+            if (alreadyInCache) {
+                m_queue.append(path);
+            } else {
+                // append to priority queue
+                m_priorityQueue.append(path);
+            }
+        }
     } else {
         KDirectoryContentsCounterWorker::Options options;
 
@@ -185,4 +203,3 @@ void KDirectoryContentsCounter::startWorker(const QString& path)
 }
 
 QThread* KDirectoryContentsCounter::m_workerThread = nullptr;
-int KDirectoryContentsCounter::m_workersCount = 0;
index 349860757ac52bc6f5cfb8dbabe5d9fa3b61699d..65c4bcb1babc52e19c8012655204824512573d71 100644 (file)
@@ -23,8 +23,9 @@
 
 #include "kdirectorycontentscounterworker.h"
 
-#include <QQueue>
+#include <QLinkedList>
 #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();
 
@@ -76,10 +72,11 @@ private:
 private:
     KFileItemModel* m_model;
 
-    QQueue<QString> m_queue;
+    // Used as FIFO queues.
+    QLinkedList<QString> m_priorityQueue;
+    QLinkedList<QString> m_queue;
 
     static QThread* m_workerThread;
-    static int m_workersCount;
 
     KDirectoryContentsCounterWorker* m_worker;
     bool m_workerIsBusy;
index e9c954ed9ce32183716bf3f978f36a1ff4780a1b..1e4a0b3b47eb5d483be8139203b9e77a597d3964 100644 (file)
 
 // 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 <faure@kde.org>
-
     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);
 }
index b40da6e87b57f5f99eb48c57b302a012bdc8b2d5..fac9978d5fe357d08af1f68fd3ccb5367d12a94b 100644 (file)
@@ -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:
     /**
index fc56cc71d5e7aa38f27a4988f0ac6e1d09663f2e..bcd875132bb2f7e1138fdba12fe037f4bccc5617 100644 (file)
@@ -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);
     }
index f9f588aba2a024bdd3f6d9cbd6bfe52b2bc55d1a..b56e0ad5bff0430ffbd2b01e36de3af26bfb0178 100644 (file)
@@ -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().
index 5932df5ce0b66426e99ecc5d2f622e1cc4bb70bb..802e64d2579352b70a32752da732ffdb2d379fb4 100644 (file)
@@ -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!";
+            }
         }
     }
 
index 9f065199310b836dcb40194b803003e702dc53d7..31c11765a663559f6055330c9282e2e5a33e8a63 100644 (file)
@@ -6,6 +6,7 @@
   <name>Dolphin</name>
   <name xml:lang="ar">دولفين</name>
   <name xml:lang="ast">Dolphin</name>
+  <name xml:lang="az">Dolphin</name>
   <name xml:lang="bs">Dolphin</name>
   <name xml:lang="ca">Dolphin</name>
   <name xml:lang="ca-valencia">Dolphin</name>
@@ -52,6 +53,7 @@
   <summary>File Manager</summary>
   <summary xml:lang="ar">مدير ملفات</summary>
   <summary xml:lang="ast">Xestor de ficheros</summary>
+  <summary xml:lang="az">Fayl meneceri</summary>
   <summary xml:lang="bs">Upravitelj datoteka</summary>
   <summary xml:lang="ca">Gestor de fitxers</summary>
   <summary xml:lang="ca-valencia">Gestor de fitxers</summary>
     <p>Dolphin is a lightweight file manager. It has been designed with ease of use and simplicity in mind, while still allowing flexibility and customisation. This means that you can do your file management exactly the way you want to do it.</p>
     <p xml:lang="ar">دولفين هو مدير ملفات خفيف. صُمِّم دولفين مع أخذ سهولة الاستخدام والبساطة بعين الاعتبار، مع السماح بالمرونة والتخصيص. يعني هذا أنه يمكنك إدارة ملفاتك كما تريد تمامًا.</p>
     <p xml:lang="ast">Dolphin ye un xestor de ficheros llixeru. Diseñóse cola cenciellez y facilidá d'usu en mente, al empar que permite flexibilidá y personalización. Esto quier dicir que pues facer la xestión de ficheros del mou exautu que quieras.</p>
+    <p xml:lang="az">Dolphin yüngül bir fayl meneceridir. Bu tətbiq istifadə rahatlığı və sadələiyi ilə bərabər çevik və fərdi ayarlana bilmə üstünlükləri nəzərə alınaraq hazırlanmışdır. Bu o deməkdir ki, siz faylları istədiyiniz kimi idarə edə bilərsiniz.</p>
     <p xml:lang="bs">Dolphinje lagan file manager. On je bio dizajniran sa lakoćom korišćenja i jednostavnosti u vidu, još omogućavajući fleksibilnost i prilagođavanje. To znači da možete da radite svoje upravljanje datotekama onako kako želite da to uradi.</p>
     <p xml:lang="ca">El Dolphin és un gestor de fitxers lleuger. S'ha dissenyat pensant a facilitar el seu ús i que sigui simple, permetent la flexibilitat i la personalització. Això vol dir que podeu fer la gestió dels vostres fitxers de la manera exacta com ho vulgueu fer.</p>
     <p xml:lang="ca-valencia">El Dolphin és un gestor de fitxers lleuger. S'ha dissenyat pensant a facilitar el seu ús i que siga simple, permetent la flexibilitat i la personalització. Això vol dir que podeu fer la gestió dels vostres fitxers de la manera exacta com ho vulgueu fer.</p>
     <p>Features:</p>
     <p xml:lang="ar">المزايا:</p>
     <p xml:lang="ast">Carauterístiques:</p>
+    <p xml:lang="az">Xüsusiyyətləri:</p>
     <p xml:lang="bs">Svojstva:</p>
     <p xml:lang="ca">Característiques:</p>
     <p xml:lang="ca-valencia">Característiques:</p>
     <p xml:lang="zh-TW">功能:</p>
     <ul>
       <li>Navigation (or breadcrumb) bar for URLs, allowing you to quickly navigate through the hierarchy of files and folders.</li>
+      <li xml:lang="az">Ünvan sətri qovluqlar üzrə cəld hərəkət etməyə imkan verir.</li>
       <li xml:lang="bs">Navigacijska (ili mrvična) traka za URL, dopušta vam da se brzo krećete kroz hijerarhiju datoteka i direktorija.</li>
       <li xml:lang="ca">Barra de navegació (o fil d'Ariadna) pels URL, permetent una navegació ràpida per la jerarquia dels fitxers i carpetes.</li>
       <li xml:lang="ca-valencia">Barra de navegació (o fil d'Ariadna) pels URL, permetent una navegació ràpida per la jerarquia dels fitxers i carpetes.</li>
       <li>Supports several different kinds of view styles and properties and allows you to configure the view exactly how you want it.</li>
       <li xml:lang="ar">يدعم العديد من الأنواع المختلفة من الخصائص وأنماط العرض ويسمح لك بضبط العرض كما تريد تمامًا.</li>
       <li xml:lang="ast">Sofita estilos y propiedaes de vista diferentes, y permítete configurar la vista exautamente como quieras.</li>
+      <li xml:lang="az">Bir neçə fərqli görünüş tərzi və xüsusiyyətlərini dəstəkləyir və görünüşü tam olaraq istədiyiniz kimi tənzimləməyə imkan verir.</li>
       <li xml:lang="bs">Dopušta vište vrsta stilova pogleda i svojstava i dopšta vam da konfigurišete pogled baš kako želite.</li>
       <li xml:lang="ca">Accepta diferents classes diverses d'estils de visualització i propietats i us permet configurar la visualització exactament com la vulgueu.</li>
       <li xml:lang="ca-valencia">Accepta diferents classes diverses d'estils de visualització i propietats i vos permet configurar la visualització exactament com la vulgueu.</li>
       <li>Split view, allowing you to easily copy or move files between locations.</li>
       <li xml:lang="ar">العرض المقسوم، يسمح لك بنسخ ونقل الملفات بين مكانين بسهولة.</li>
       <li xml:lang="ast">La vista dixebrada permítete copiar o mover ficheros de mou fácil ente allugamientos.</li>
+      <li xml:lang="az">İkipanelli rejimdə faylları müxtəlif qovluqlar arasında cəld kopyalamq və köçürmək daha rahatdır.</li>
       <li xml:lang="bs">Razdvaja pogled, dopuštajući lako kopiranje ili pomijeranje datoteka između lokacija</li>
       <li xml:lang="ca">Divisió de visualització, permetent copiar o moure fitxers fàcilment entre les ubicacions.</li>
       <li xml:lang="ca-valencia">Divisió de visualització, permetent copiar o moure fitxers fàcilment entre les ubicacions.</li>
       <li>Additional information and shortcuts are available as dock-able panels, allowing you to move them around freely and display exactly what you want.</li>
       <li xml:lang="ar">تتوفر معلومات واختصارات إضافية كلوحات قابلة للرصف، مما يسمح لك بنقلها بحريّة وعرضها بالضبط كما تريد.</li>
       <li xml:lang="ast">La información adicional y los atayos tán disponibles como paneles anclables que pues mover ande quieras y amosar como exautamente quieras.</li>
+      <li xml:lang="az">Əlavə məlumatlar və yarlıqlar yeri dəyişdirilə bilən panellər kimidir və bu sizə onları istədiyiniz yerə daşımağa və görünüşünü istədiyiniz kimi dəyişməyə imkan verir.</li>
       <li xml:lang="bs">Dodatne informacije i kratice su dostupne kao usidreni paneli, dopuštajući vam da se krećete slobodno i prikažete šta želite.</li>
       <li xml:lang="ca">Hi ha informació addicional i dreceres disponibles com a plafons que es poden acoblar, permetent moure'ls lliurement i mostrar exactament el què vulgueu.</li>
       <li xml:lang="ca-valencia">Hi ha informació addicional i dreceres disponibles com a plafons que es poden acoblar, permetent moure'ls lliurement i mostrar exactament el què vulgueu.</li>
       <li>Multiple tab support</li>
       <li xml:lang="ar">دعم تعدّد الألسنة</li>
       <li xml:lang="ast">Sofitu pa munches llingüetes</li>
+      <li xml:lang="az">Birdən çox vərəqi dəstəkləyir</li>
       <li xml:lang="bs">Podrška za više kartica</li>
       <li xml:lang="ca">Admet pestanyes múltiples</li>
       <li xml:lang="ca-valencia">Admet pestanyes múltiples</li>
       <li>Informational dialogues are displayed in an unobtrusive way.</li>
       <li xml:lang="ar">حواريات المعلومات تُعرَض بطريقة غير مُزعجة.</li>
       <li xml:lang="ast">Los diálogos informativos amuésense d'un mou non intrusivu.</li>
+      <li xml:lang="az">İnformasiya pəncərələri maneə olmadan görünür.</li>
       <li xml:lang="bs">Informativni dijalozi su prikazani na nenametljiv način.</li>
       <li xml:lang="ca">Els diàlegs informatius es mostren d'una manera no molesta.</li>
       <li xml:lang="ca-valencia">Els diàlegs informatius es mostren d'una manera no molesta.</li>
       <li>Undo/redo support</li>
       <li xml:lang="ar">دعم التراجع والإعادة</li>
       <li xml:lang="ast">Sofitu pa la desfechura/refechura</li>
+      <li xml:lang="az">Geri qaytarmaq və təkrarlamaq dəstəyi</li>
       <li xml:lang="bs">Podrška za poništavanje/ponavljanje akcija</li>
       <li xml:lang="ca">Admet desfer/refer</li>
       <li xml:lang="ca-valencia">Admet desfer/refer</li>
       <li>Transparent network access through the KIO system.</li>
       <li xml:lang="ar">اتصال شبكيّ مباشر باستخدام نظام KIO.</li>
       <li xml:lang="ast">Accesu tresparente a la rede pente'l sistema KIO.</li>
+      <li xml:lang="az">KİO vasitəsi ilə şəbəkə fayl sisteminə şəffaf giriş.</li>
       <li xml:lang="bs">Transparentni mrežni pristup kroz KIO sistem.</li>
       <li xml:lang="ca">Accés transparent a la xarxa a través del sistema KIO.</li>
       <li xml:lang="ca-valencia">Accés transparent a la xarxa a través del sistema KIO.</li>
     <screenshot type="default">
       <caption>File management in Dolphin</caption>
       <caption xml:lang="ast">Xestión de ficheros en Dolphin</caption>
+      <caption xml:lang="az">Dolphində faylların idarə edilməsi</caption>
       <caption xml:lang="ca">Gestió de fitxers al Dolphin</caption>
       <caption xml:lang="ca-valencia">Gestió de fitxers al Dolphin</caption>
       <caption xml:lang="cs">Správa souborů v Dolphinu</caption>
       <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>
index 6404808eeccdf6e2312ce7c02c83c8a5f5e016d7..94682ce6d927549375153cecfae63391c2a415e2 100755 (executable)
@@ -2,6 +2,7 @@
 Name=Dolphin
 Name[ar]=دولفين
 Name[ast]=Dolphin
+Name[az]=Dolphin
 Name[ca]=Dolphin
 Name[ca@valencia]=Dolphin
 Name[cs]=Dolphin
@@ -53,6 +54,7 @@ Categories=Qt;KDE;System;FileTools;FileManager;
 GenericName=File Manager
 GenericName[ar]=مدير ملفّات
 GenericName[ast]=Xestor de ficheros
+GenericName[az]=Fayl meneceri
 GenericName[ca]=Gestor de fitxers
 GenericName[ca@valencia]=Gestor de fitxers
 GenericName[cs]=Správce souborů
index 23e7f1922b0b0625d719a60c26781d39721f509c..4f0e4e5eb80ff51e784f559f3a69991b66dd055d 100644 (file)
@@ -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);
             }
index 5c7c7c3f158936286b187716e9a2a4e688e3ff0e..9db7f8bb719d7438774c5547cc7608da307b78ec 100644 (file)
@@ -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,25 +224,27 @@ 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 {
 
             refreshPixmapView();
 
             const QString mimeType = m_item.mimetype();
-            const bool isAnimatedImage = m_preview->isAnimatedImage(itemUrl.toLocalFile());
+            const bool isAnimatedImage = m_preview->isAnimatedMimeType(mimeType);
             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()
index 2601e82ae50aba1915ada813f6f4453d3adbbc4f..39fedb1a1f6b8a4c9c209e8f7f364ce11f9ef3c8 100644 (file)
@@ -186,8 +186,9 @@ void PixmapViewer::stopAnimatedImage()
     }
 }
 
-bool PixmapViewer::isAnimatedImage(const QString &fileName)
+bool PixmapViewer::isAnimatedMimeType(const QString &mimeType)
 {
-    const QByteArray imageFormat = QImageReader::imageFormat(fileName);
-    return !imageFormat.isEmpty() && QMovie::supportedFormats().contains(imageFormat);
+    const QList<QByteArray> imageFormats = QImageReader::imageFormatsForMimeType(mimeType.toUtf8());
+    return std::any_of(imageFormats.begin(), imageFormats.end(),
+                       [](const QByteArray &format){ return QMovie::supportedFormats().contains(format); });
 }
index 37071045fb167359e734357cb82f1f9f384190eb..c231b590dbe81c579e0e9ef56f8197e87df5dca6 100644 (file)
@@ -80,9 +80,9 @@ public:
     void stopAnimatedImage();
 
     /**
-     * Checks if \a fileName contains an animated image supported by QMovie.
+     * Checks if \a mimeType has a format supported by QMovie.
      */
-    static bool isAnimatedImage(const QString &fileName);
+    static bool isAnimatedMimeType(const QString &mimeType);
 
 protected:
     void paintEvent(QPaintEvent* event) override;
index ea22700202d661e22f169204693e203f642ccaa8..b1f24e401f41a14c0b766f7b50a4a7b3fea19409 100644 (file)
@@ -209,7 +209,7 @@ void PlacesItem::initializeDevice(const QString& udi)
     m_disc = m_device.as<Solid::OpticalDisc>();
     m_player = m_device.as<Solid::PortableMediaPlayer>();
 
-    setText(m_device.description());
+    setText(m_device.displayName());
     setIcon(m_device.icon());
     setIconOverlays(m_device.emblems());
     setUdi(udi);
diff --git a/src/panels/terminal/org.kde.KIOFuse.VFS.xml b/src/panels/terminal/org.kde.KIOFuse.VFS.xml
new file mode 100644 (file)
index 0000000..56f753e
--- /dev/null
@@ -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>
index 59b2694fb01aaf03cb0fe01702df5489afc8122c..ac0bcd0fee5c1ef9fadd3ed0b2946da9dc4b3565 100644 (file)
@@ -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
index 6ab205fe32cb01828dff012bdfb49e6b8d59ad5e..661fee4d486d2374b6e9044819e6095cfa19a9d3 100644 (file)
@@ -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
index ab107f43fab736e3a39407017dd5a7dd28f2abbf..0581a02ece041fcc242ca13388d72131ca5e44d4 100644 (file)
@@ -27,6 +27,7 @@
 #endif
 
 namespace {
+#ifdef HAVE_BALOO
     /** Checks if a given term in the Baloo::Query::searchString() is a special search term
      * @return: the specific search token of the term, or an empty QString() if none is found
      */
@@ -67,20 +68,40 @@ namespace {
         }
         return textParts;
     }
+#endif
 }
 
-DolphinQuery DolphinQuery::fromBalooSearchUrl(const QUrl& searchUrl)
+
+DolphinQuery DolphinQuery::fromSearchUrl(const QUrl& searchUrl)
 {
     DolphinQuery model;
     model.m_searchUrl = searchUrl;
 
+    if (searchUrl.scheme() == QLatin1String("baloosearch")) {
+        model.parseBalooQuery();
+    }
+
+    return model;
+}
+
+bool DolphinQuery::supportsScheme(const QString& urlScheme)
+{
+    static const QStringList supportedSchemes = {
+        QStringLiteral("baloosearch"),
+    };
+
+    return supportedSchemes.contains(urlScheme);
+}
+
+void DolphinQuery::parseBalooQuery()
+{
 #ifdef HAVE_BALOO
-    const Baloo::Query query = Baloo::Query::fromSearchUrl(searchUrl);
+    const Baloo::Query query = Baloo::Query::fromSearchUrl(m_searchUrl);
 
-    model.m_includeFolder = query.includeFolder();
+    m_includeFolder = query.includeFolder();
 
     const QStringList types = query.types();
-    model.m_fileType = types.isEmpty() ? QString() : types.first();
+    m_fileType = types.isEmpty() ? QString() : types.first();
 
     QStringList textParts;
     QString fileName;
@@ -93,34 +114,33 @@ DolphinQuery DolphinQuery::fromBalooSearchUrl(const QUrl& searchUrl)
         if (token == QLatin1String("filename:")) {
             if (!value.isEmpty()) {
                 fileName = value;
-                model.m_hasFileName = true;
+                m_hasFileName = true;
             }
             continue;
         } else if (!token.isEmpty()) {
-            model.m_searchTerms << token + value;
+            m_searchTerms << token + value;
             continue;
         } else if (subTerm == QLatin1String("AND") && subTerm != subTerms.at(0) && subTerm != subTerms.back()) {
             continue;
         } else if (!value.isEmpty()) {
             textParts << value;
-            model.m_hasContentSearch = true;
+            m_hasContentSearch = true;
         }
     }
 
-    if (model.m_hasFileName) {
-        if (model.m_hasContentSearch) {
+    if (m_hasFileName) {
+        if (m_hasContentSearch) {
             textParts << QStringLiteral("filename:\"%1\"").arg(fileName);
         } else {
             textParts << fileName;
         }
     }
 
-    model.m_searchText = textParts.join(QLatin1Char(' '));
-
+    m_searchText = textParts.join(QLatin1Char(' '));
 #endif
-    return model;
 }
 
+
 QUrl DolphinQuery::searchUrl() const
 {
     return m_searchUrl;
index 544f246bcfe6bea0b184c982fead5df359d011c6..5032621a9e1d9569ae5f328f750dd5fd3d637a5c 100644 (file)
 class DolphinQuery
 {
 public:
-    /** Calls Baloo::Query::fromSearchUrl() with the given @p searchUrl
-     * and parses the result to extract its separate components */
-    static DolphinQuery fromBalooSearchUrl(const QUrl& searchUrl);
+    /** Parses the components of @p searchUrl for the supported schemes */
+    static DolphinQuery fromSearchUrl(const QUrl& searchUrl);
+    /** Checks whether the DolphinQuery supports the given @p urlScheme */
+    static bool supportsScheme(const QString& urlScheme);
 
     /** @return the \a searchUrl passed to Baloo::Query::fromSearchUrl() */
     QUrl searchUrl() const;
@@ -53,6 +54,11 @@ public:
     /** @return whether the query includes a filter by fileName */
     bool hasFileName() const;
 
+private:
+    /** Calls Baloo::Query::fromSearchUrl() on the current searchUrl
+     * and parses the result to extract its separate components */
+    void parseBalooQuery();
+
 private:
     QUrl m_searchUrl;
     QString m_searchText;
index 23f520de148a3f1ba710cb652828bb2de5830f81..239280280253f01e490fc98e7b6c87cbd0518046 100644 (file)
@@ -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);
     }
@@ -145,8 +146,8 @@ QUrl DolphinSearchBox::urlForSearching() const
 
 void DolphinSearchBox::fromSearchUrl(const QUrl& url)
 {
-    if (url.scheme() == QLatin1String("baloosearch")) {
-        const DolphinQuery query = DolphinQuery::fromBalooSearchUrl(url);
+    if (DolphinQuery::supportsScheme(url.scheme())) {
+        const DolphinQuery query = DolphinQuery::fromSearchUrl(url);
         updateFromQuery(query);
     } else if (url.scheme() == QLatin1String("filenamesearch")) {
         const QUrlQuery query(url);
@@ -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()
@@ -340,13 +344,6 @@ void DolphinSearchBox::saveSettings()
 
 void DolphinSearchBox::init()
 {
-    // Create close button
-    QToolButton* closeButton = new QToolButton(this);
-    closeButton->setAutoRaise(true);
-    closeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close")));
-    closeButton->setToolTip(i18nc("@info:tooltip", "Quit searching"));
-    connect(closeButton, &QToolButton::clicked, this, &DolphinSearchBox::emitCloseRequest);
-
     // Create search box
     m_searchInput = new QLineEdit(this);
     m_searchInput->setPlaceholderText(i18n("Search..."));
@@ -367,11 +364,18 @@ void DolphinSearchBox::init()
     m_searchInput->addAction(m_saveSearchAction, QLineEdit::TrailingPosition);
     connect(m_saveSearchAction, &QAction::triggered, this, &DolphinSearchBox::slotSearchSaved);
 
+    // Create close button
+    QToolButton* closeButton = new QToolButton(this);
+    closeButton->setAutoRaise(true);
+    closeButton->setIcon(QIcon::fromTheme(QStringLiteral("dialog-close")));
+    closeButton->setToolTip(i18nc("@info:tooltip", "Quit searching"));
+    connect(closeButton, &QToolButton::clicked, this, &DolphinSearchBox::emitCloseRequest);
+
     // Apply layout for the search input
     QHBoxLayout* searchInputLayout = new QHBoxLayout();
     searchInputLayout->setContentsMargins(0, 0, 0, 0);
-    searchInputLayout->addWidget(closeButton);
     searchInputLayout->addWidget(m_searchInput);
+    searchInputLayout->addWidget(closeButton);
 
     // Create "Filename" and "Content" button
     m_fileNameButton = new QToolButton(this);
@@ -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
index 5fef4ec5a7bdd5464e27818b762ea1456b754d6c..4afd752bc15b00680ffb65981a826eaabed3a61c 100644 (file)
@@ -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;
 
index e9a8fb28d26de61a0a3ba4e87a76491a902f3e50..9d05a8ab004e14bfefd4eeedb0e95c146c432ace 100644 (file)
             <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>
index fca70656d0dc651df1d058599db1fe11abe8de5c..c397b2945124a49ab4867ff608337842c8d75e3d 100644 (file)
             <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>
index 90a4211c0f971628755ad506dff733a595cff7d4..3e435b53c8b46d07475ca34c6e40358a09d74f8b 100644 (file)
@@ -38,7 +38,8 @@
 
 // default settings
 namespace {
-    const int MaxRemotePreviewSize = 0; // 0 MB
+    const int DefaultMaxLocalPreviewSize = 0; // 0 MB
+    const int DefaultMaxRemotePreviewSize = 0; // 0 MB
 }
 
 PreviewsSettingsPage::PreviewsSettingsPage(QWidget* parent) :
@@ -46,6 +47,7 @@ PreviewsSettingsPage::PreviewsSettingsPage(QWidget* parent) :
     m_initialized(false),
     m_listView(nullptr),
     m_enabledPreviewPlugins(),
+    m_localFileSizeBox(nullptr),
     m_remoteFileSizeBox(nullptr)
 {
     QVBoxLayout* topLayout = new QVBoxLayout(this);
@@ -68,24 +70,41 @@ PreviewsSettingsPage::PreviewsSettingsPage(QWidget* parent) :
     m_listView->setItemDelegate(delegate);
     m_listView->setVerticalScrollMode(QListView::ScrollPerPixel);
 
+    QLabel* localFileSizeLabel = new QLabel(i18n("Skip previews for local files above:"), this);
+
+    m_localFileSizeBox = new QSpinBox(this);
+    m_localFileSizeBox->setSingleStep(1);
+    m_localFileSizeBox->setSuffix(QStringLiteral(" MB"));
+    m_localFileSizeBox->setRange(0, 9999999); /* MB */
+    m_localFileSizeBox->setSpecialValueText(tr("No limit"));
+
+    QHBoxLayout* localFileSizeBoxLayout = new QHBoxLayout();
+    localFileSizeBoxLayout->addWidget(localFileSizeLabel);
+    localFileSizeBoxLayout->addStretch(0);
+    localFileSizeBoxLayout->addWidget(m_localFileSizeBox);
+
     QLabel* remoteFileSizeLabel = new QLabel(i18nc("@label", "Skip previews for remote files above:"), this);
 
     m_remoteFileSizeBox = new QSpinBox(this);
     m_remoteFileSizeBox->setSingleStep(1);
     m_remoteFileSizeBox->setSuffix(QStringLiteral(" MB"));
     m_remoteFileSizeBox->setRange(0, 9999999); /* MB */
+    m_remoteFileSizeBox->setSpecialValueText(tr("No previews"));
 
-    QHBoxLayout* fileSizeBoxLayout = new QHBoxLayout();
-    fileSizeBoxLayout->addWidget(remoteFileSizeLabel, 0, Qt::AlignRight);
-    fileSizeBoxLayout->addWidget(m_remoteFileSizeBox);
+    QHBoxLayout* remoteFileSizeBoxLayout = new QHBoxLayout();
+    remoteFileSizeBoxLayout->addWidget(remoteFileSizeLabel);
+    remoteFileSizeBoxLayout->addStretch(0);
+    remoteFileSizeBoxLayout->addWidget(m_remoteFileSizeBox);
 
     topLayout->addWidget(showPreviewsLabel);
     topLayout->addWidget(m_listView);
-    topLayout->addLayout(fileSizeBoxLayout);
+    topLayout->addLayout(localFileSizeBoxLayout);
+    topLayout->addLayout(remoteFileSizeBoxLayout);
 
     loadSettings();
 
     connect(m_listView, &QListView::clicked, this, &PreviewsSettingsPage::changed);
+    connect(m_localFileSizeBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &PreviewsSettingsPage::changed);
     connect(m_remoteFileSizeBox, QOverload<int>::of(&QSpinBox::valueChanged), this, &PreviewsSettingsPage::changed);
 }
 
@@ -112,6 +131,11 @@ void PreviewsSettingsPage::applySettings()
     KConfigGroup globalConfig(KSharedConfig::openConfig(), QStringLiteral("PreviewSettings"));
     globalConfig.writeEntry("Plugins", m_enabledPreviewPlugins);
 
+    const qulonglong maximumLocalSize = static_cast<qulonglong>(m_localFileSizeBox->value()) * 1024 * 1024;
+    globalConfig.writeEntry("MaximumSize",
+                            maximumLocalSize,
+                            KConfigBase::Normal | KConfigBase::Global);
+
     const qulonglong maximumRemoteSize = static_cast<qulonglong>(m_remoteFileSizeBox->value()) * 1024 * 1024;
     globalConfig.writeEntry("MaximumRemoteSize",
                             maximumRemoteSize,
@@ -121,7 +145,8 @@ void PreviewsSettingsPage::applySettings()
 
 void PreviewsSettingsPage::restoreDefaults()
 {
-    m_remoteFileSizeBox->setValue(MaxRemotePreviewSize);
+    m_localFileSizeBox->setValue(DefaultMaxLocalPreviewSize);
+    m_remoteFileSizeBox->setValue(DefaultMaxRemotePreviewSize);
 }
 
 void PreviewsSettingsPage::showEvent(QShowEvent* event)
@@ -169,9 +194,13 @@ void PreviewsSettingsPage::loadSettings()
     const KConfigGroup globalConfig(KSharedConfig::openConfig(), QStringLiteral("PreviewSettings"));
     m_enabledPreviewPlugins = globalConfig.readEntry("Plugins", KIO::PreviewJob::defaultPlugins());
 
-    const qulonglong defaultRemotePreview = static_cast<qulonglong>(MaxRemotePreviewSize) * 1024 * 1024;
+    const qulonglong defaultLocalPreview = static_cast<qulonglong>(DefaultMaxLocalPreviewSize) * 1024 * 1024;
+    const qulonglong maxLocalByteSize = globalConfig.readEntry("MaximumSize", defaultLocalPreview);
+    const int maxLocalMByteSize = maxLocalByteSize / (1024 * 1024);
+    m_localFileSizeBox->setValue(maxLocalMByteSize);
+
+    const qulonglong defaultRemotePreview = static_cast<qulonglong>(DefaultMaxRemotePreviewSize) * 1024 * 1024;
     const qulonglong maxRemoteByteSize = globalConfig.readEntry("MaximumRemoteSize", defaultRemotePreview);
     const int maxRemoteMByteSize = maxRemoteByteSize / (1024 * 1024);
     m_remoteFileSizeBox->setValue(maxRemoteMByteSize);
 }
-
index 957523710130c6a943fe407f70fd19719855bc43..a7f54f601166f4c286955079aae8b97c8bfd6de1 100644 (file)
@@ -61,6 +61,7 @@ private:
     bool m_initialized;
     QListView *m_listView;
     QStringList m_enabledPreviewPlugins;
+    QSpinBox* m_localFileSizeBox;
     QSpinBox* m_remoteFileSizeBox;
 };
 
index a82cb3858c409609fedb07b468ed34a7a427d39e..39eccff76fab0ab3df20bef6b0293c2978160afc 100644 (file)
 
 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();
     }
 }
index f46d5118b1df2275e241256dd75fc1df128b623e..ba8cdefde7782d2eaa33085051c1086e5744d2d1 100644 (file)
@@ -1,6 +1,7 @@
 Name=Dolphin General
 Name[ar]=دولفين العامّ
 Name[ast]=Axustes xenerales de Dolphin
+Name[az]=Əsas Dolphin parametrləri
 Name[ca]=General del Dolphin
 Name[ca@valencia]=General del Dolphin
 Name[cs]=Obecný Dolphin
@@ -47,6 +48,7 @@ Name[zh_TW]=Dolphin 一般
 Comment=This service allows configuration of general Dolphin settings.
 Comment[ar]=تسمح هذه الخدمة بضبط إعدادات دولفين العامّة.
 Comment[ast]=Esti serviciu permite la configuración de los axustes xenerales de Dolphin.
+Comment[az]=Bu xidmət əsas Dolphin parametrlərini ayarlamağa imkan verir.
 Comment[ca]=Aquest servei permet la configuració de l'arranjament general del Dolphin.
 Comment[ca@valencia]=Aquest servei permet la configuració de l'arranjament general del Dolphin.
 Comment[cs]=Tato služba umožňuje obecné nastavení Dolphinu.
@@ -104,6 +106,7 @@ X-DocPath=dolphin/index.html#preferences-dialog-general
 Name=General
 Name[ar]=عامّ
 Name[ast]=Xeneral
+Name[az]=Əsas
 Name[ca]=General
 Name[ca@valencia]=General
 Name[cs]=Obecné
@@ -150,6 +153,7 @@ Name[zh_TW]=一般
 Comment=Configure general file manager settings
 Comment[ar]=اضبط إعدادات مدير الملفّات العامّة
 Comment[ast]=Configura los axustes xenerales del xestor de ficheros
+Comment[az]=Fayl menecerinin ayarları
 Comment[ca]=Configura les opcions generals del gestor de fitxers
 Comment[ca@valencia]=Configura les opcions generals del gestor de fitxers
 Comment[cs]=Obecné nastavení správce souborů
@@ -195,6 +199,7 @@ Comment[zh_TW]=設定一般檔案管理員
 X-KDE-Keywords=file manager
 X-KDE-Keywords[ar]=مدير ملفّات ملفات الملفّات الملفات
 X-KDE-Keywords[ast]=xestor de ficheros
+X-KDE-Keywords[az]=fayl meneceri
 X-KDE-Keywords[ca]=gestor de fitxers
 X-KDE-Keywords[ca@valencia]=gestor de fitxers
 X-KDE-Keywords[cs]=správce souborů
index c542c0139545bcb9e6ad441832bc17467b3e47b0..2b60c7591d11e94fceda3f1603cbd3c8fdca310c 100644 (file)
@@ -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;
index 2cdabdeee0e22d124cb65b58356f1c4328a59f18..f8de4eed22e2c34ae0f9a18c00ca252c0b0fede9 100644 (file)
 
 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, {});
 }
 
index 503f163d1896cd28fda8ec6333a80fcc19ff51a3..fd649b54816305d7fc3655f8e6db2cb90e283870 100644 (file)
@@ -1,6 +1,7 @@
 Name=Dolphin Navigation
 Name[ar]=التّنقّل في دولفين
 Name[ast]=Navegación de Dolphin
+Name[az]=Dolphində hərəkət
 Name[ca]=Navegació del Dolphin
 Name[ca@valencia]=Navegació del Dolphin
 Name[cs]=Navigace Dolphinu
@@ -47,6 +48,7 @@ Name[zh_TW]=Dolphin 導覽
 Comment=This service allows configuration of the Dolphin navigation.
 Comment[ar]=تسمح هذه الخدمة بضبط التّنقّل في دولفين.
 Comment[ast]=Esti serviciu permite la configuración de la navegación del Dolphin.
+Comment[az]=Bu xidmət Dolphin üzrə hərəkəti tənzimləməyə imkan verir.
 Comment[ca]=Aquest servei permet la configuració de la navegació del Dolphin.
 Comment[ca@valencia]=Aquest servei permet la configuració de la navegació del Dolphin.
 Comment[cs]=Tato služba umožňuje nastavení navigace v Dolphinu.
@@ -103,6 +105,7 @@ X-DocPath=dolphin/index.html#preferences-dialog-navigation
 Name=Navigation
 Name[ar]=التّنقّل
 Name[ast]=Navegación
+Name[az]=Naviqasiy
 Name[ca]=Navegació
 Name[ca@valencia]=Navegació
 Name[cs]=Navigace
@@ -150,6 +153,7 @@ Name[zh_TW]=導覽
 Comment=Configure file manager navigation
 Comment[ar]=اضبط التّنقّل في مدير الملفّات
 Comment[ast]=Configura la navegación del xestor de ficheros
+Comment[az]=Fayl meneceri naviqasiyasını tənzimləmək
 Comment[ca]=Configura la navegació del gestor de fitxers
 Comment[ca@valencia]=Configura la navegació del gestor de fitxers
 Comment[cs]=Nastavení navigace správce souborů
@@ -196,6 +200,7 @@ Comment[zh_TW]=設定檔案管理員導覽
 X-KDE-Keywords=file manager
 X-KDE-Keywords[ar]=مدير ملفّات ملفات الملفّات الملفات
 X-KDE-Keywords[ast]=xestor de ficheros
+X-KDE-Keywords[az]=fayl meneceri
 X-KDE-Keywords[ca]=gestor de fitxers
 X-KDE-Keywords[ca@valencia]=gestor de fitxers
 X-KDE-Keywords[cs]=správce souborů
index 2bcc7ababe2ae7ac2315c1384188c5c0d72a9171..7eb6b26e78b044a73efdd9d9f0f7f02fe88aa393 100644 (file)
@@ -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:
-    NavigationSettingsPagem_navigation;
+    NavigationSettingsPage *m_navigation;
 };
 
 #endif
index e6a8867d7dde1754f0d9f88d368e308d0f098d14..92e71bae0eb8da71a2467533f529d760768a37c0 100644 (file)
 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, {});
 }
 
index 1187733a47331ee15471a7a615bedb951e1e00a2..10e806a817c7c2cd04392d71357ef0ae60b36ba6 100644 (file)
@@ -1,6 +1,7 @@
 Name=Dolphin Services
 Name[ar]=خدمات دولفين
 Name[ast]=Servicios de Dolphin
+Name[az]=Dolphin xidmətləri
 Name[ca]=Serveis del Dolphin
 Name[ca@valencia]=Serveis del Dolphin
 Name[cs]=Služby Dolphinu
@@ -57,6 +58,7 @@ X-DocPath=dolphin/index.html#preferences-dialog-services
 Name=Services
 Name[ar]=الخدمات
 Name[ast]=Servicios
+Name[az]=Xidmətlər
 Name[ca]=Serveis
 Name[ca@valencia]=Serveis
 Name[cs]=Služby
@@ -103,6 +105,7 @@ Name[zh_TW]=服務
 Comment=Configure file manager services
 Comment[ar]=اضبط خدمات مدير الملفّات
 Comment[ast]=Configura los servicios del xestor de ficheros
+Comment[az]=Fayl meneceri xidmətlərini tənzimləmək
 Comment[ca]=Configura els serveis del gestor de fitxers
 Comment[ca@valencia]=Configura els serveis del gestor de fitxers
 Comment[cs]=Nastavení služeb správce souborů
@@ -148,6 +151,7 @@ Comment[zh_TW]=設定檔案管理員服務
 X-KDE-Keywords=file manager
 X-KDE-Keywords[ar]=مدير ملفّات ملفات الملفّات الملفات
 X-KDE-Keywords[ast]=xestor de ficheros
+X-KDE-Keywords[az]=fayl meneceri
 X-KDE-Keywords[ca]=gestor de fitxers
 X-KDE-Keywords[ca@valencia]=gestor de fitxers
 X-KDE-Keywords[cs]=správce souborů
index 6c6af6728a12f8beee2a7ee4579089886515af98..a567450ca512d04e3a1647109b4afb4a185e32d1 100644 (file)
@@ -39,7 +39,7 @@ public:
     void defaults() override;
 
 private:
-    ServicesSettingsPagem_services;
+    ServicesSettingsPage *m_services;
 };
 
 #endif
index 4fac1160073a7128d47ee0258fcf06a33b8f3c2a..7077bac8aa6d6c689f9b015302dbbde08a3b401f 100644 (file)
 
 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);
+    markAsChanged();
 }
 
 #include "kcmdolphinviewmodes.moc"
index 16b3fd56818b80854024b66f57839b389593f336..b5ea5d047ad52e818895026cc2b0ca9c57f1894e 100644 (file)
@@ -1,6 +1,7 @@
 Name=Dolphin View Modes
 Name[ar]=أوضاع المنظور في دولفين
 Name[ast]=Moos de vista de Dolphin
+Name[az]=Dolphin baxış rejimi
 Name[ca]=Modes de vista del Dolphin
 Name[ca@valencia]=Modes de vista del Dolphin
 Name[cs]=Režimy pohledů Dolphinu
@@ -47,6 +48,7 @@ Name[zh_TW]=設定檔案管理員服務
 Comment=This service allows configuration of the Dolphin view modes.
 Comment[ar]=تسمح هذه الخدمة بضبط أوضاع المنظور في دولفين.
 Comment[ast]=Esti serviciu permite la configuración de los moos de vista de Dolphin.
+Comment[az]=Bu xidmət Dolphin baxış rejimini tənzimləməyə imkan verir
 Comment[ca]=Aquest servei permet la configuració dels modes de vista del Dolphin.
 Comment[ca@valencia]=Aquest servei permet la configuració dels modes de vista del Dolphin.
 Comment[cs]=Tato služba umožňuje nastavení režimů pohledu Dolphinu.
@@ -103,6 +105,7 @@ X-DocPath=dolphin/index.html#preferences-dialog-viewmodes
 Name=View Modes
 Name[ar]=أوضاع المنظور
 Name[ast]=Moos de vista
+Name[az]=Baxış rejimləri
 Name[ca]=Modes de vista
 Name[ca@valencia]=Modes de vista
 Name[cs]=Režimy pohledu
@@ -149,6 +152,7 @@ Name[zh_TW]=檢視模式
 Comment=Configure file manager view modes
 Comment[ar]=اضبط أوضاع المنظور في مدير الملفّات
 Comment[ast]=Configura los moos de vista del xestor de ficheros
+Comment[az]=Fayl meneceri baxış rejimlərini tənzimləmək
 Comment[ca]=Configura els modes de vista del gestor de fitxers
 Comment[ca@valencia]=Configura els modes de vista del gestor de fitxers
 Comment[cs]=Nastavení režimů pohledu správce souborů
@@ -195,6 +199,7 @@ Comment[zh_TW]=設定檔案管理員檢視模式
 X-KDE-Keywords=file manager
 X-KDE-Keywords[ar]=مدير ملفّات ملفات الملفّات الملفات
 X-KDE-Keywords[ast]=xestor de ficheros
+X-KDE-Keywords[az]=fayl meneceri
 X-KDE-Keywords[ca]=gestor de fitxers
 X-KDE-Keywords[ca@valencia]=gestor de fitxers
 X-KDE-Keywords[cs]=správce souborů
index c3775adff9d1b90c27ff719f7e918e4816aa4fe5..40965b0e6832e3441f9775631ffd513e86046efc 100644 (file)
@@ -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;
index 9888999368267e519553bc125e1d4c3adec2e440..46b1590794f6be249d49442f58576429c2531423 100644 (file)
@@ -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})
index 06f34c6b932be4a252ba5454fa35bb467082c3f7..89f2545f80b9de6982a97685fda1abbfdf0bd652 100644 (file)
 
 #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
index fe900bc5c9943ff50cc4ddcaf7777beb25e42a55..e18bfb09ec2c6476a62c66235f9e60092052460a 100644 (file)
@@ -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 QAbstractItemModelmodel = 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 QStringservice) 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 QStringicon,
-                                  const QStringtext,
-                                  const QStringvalue,
+void ServicesSettingsPage::addRow(const QString &icon,
+                                  const QString &text,
+                                  const QString &value,
                                   bool checked)
 {
     m_serviceModel->insertRow(0);
index cd4cbe52fcc5c463e640b67f53bed514ba2234e1..8f507407b9f165fc58d54a002be604ab2af2b980 100644 (file)
@@ -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 QStringservice) const;
+    bool isInServicesList(const QString &service) const;
 
     /**
      * Adds a row to the model of m_listView.
      */
-    void addRow(const QStringicon,
-                const QStringtext,
-                const QStringvalue,
+    void addRow(const QString &icon,
+                const QString &text,
+                const QString &value,
                 bool checked);
 
 private:
     bool m_initialized;
-    ServiceModelm_serviceModel;
-    QSortFilterProxyModelm_sortModel;
+    ServiceModel *m_serviceModel;
+    QSortFilterProxyModel *m_sortModel;
     QListView* m_listView;
+    QLineEdit *m_searchLineEdit;
     QStringList m_enabledVcsPlugins;
 };
 
index d7d5fba4cc1e954e925a4e6f7a9004439f56102d..eb149574659dfb82f9cf2cebe49c7330cd0fb254 100644 (file)
 #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());
index a5e0b236f415f7551da914074e80511188bfdd66..d1c937f1fde58c71d1b1303f4726f642a2f89562 100644 (file)
@@ -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;
index 06b0b8cf5ca191d80b5e2faef4560eb1374de559..3e3f96ffce66334dfa89a8cd69aabfa124cdf07d 100644 (file)
 #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;
index fff882e5e2794806f349ad16ff081d169c3b50f5..4d459fca2e27c3c9324fd8eea5355b04f45ffc91 100644 (file)
@@ -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
index 8a81960af20ac7ffdcac5b18803f39b47efcb206..6cd76bb60445f89c211d4fe8f1477ced2ec716b9 100644 (file)
@@ -115,7 +115,7 @@ DolphinStatusBar::DolphinStatusBar(QWidget* parent) :
 
     m_zoomSlider->setMaximumWidth(fontMetrics.averageCharWidth() * 25);
 
-    m_spaceInfo->setFixedHeight(zoomSliderHeight);
+    m_spaceInfo->setFixedHeight(contentHeight);
     m_spaceInfo->setMaximumWidth(fontMetrics.averageCharWidth() * 25);
     m_spaceInfo->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
 
@@ -229,7 +229,9 @@ QString DolphinStatusBar::defaultText() const
 
 void DolphinStatusBar::setUrl(const QUrl& url)
 {
-    m_spaceInfo->setUrl(url);
+    if (GeneralSettings::showSpaceInfo()) {
+        m_spaceInfo->setUrl(url);
+    }
 }
 
 QUrl DolphinStatusBar::url() const
@@ -332,7 +334,7 @@ void DolphinStatusBar::setExtensionsVisible(bool visible)
         showSpaceInfo = GeneralSettings::showSpaceInfo();
         showZoomSlider = GeneralSettings::showZoomSlider();
     }
-    m_spaceInfo->setVisible(showSpaceInfo);
+    m_spaceInfo->setShown(showSpaceInfo);
     m_zoomSlider->setVisible(showZoomSlider);
 }
 
index 692eba7e7a781d52aa5e59acf13426c3cb951cf8..0d8f5f2fe73f2e41d152891534c4439a8fe7ee1e 100644 (file)
@@ -24,6 +24,7 @@
 SpaceInfoObserver::SpaceInfoObserver(const QUrl& url, QObject* parent) :
     QObject(parent),
     m_mountPointObserver(nullptr),
+    m_hasData(false),
     m_dataSize(0),
     m_dataAvailable(0)
 {
@@ -81,7 +82,8 @@ void SpaceInfoObserver::update()
 void SpaceInfoObserver::spaceInfoChanged(quint64 size, quint64 available)
 {
     // Make sure that the size has actually changed
-    if (m_dataSize != size || m_dataAvailable != available) {
+    if (m_dataSize != size || m_dataAvailable != available || !m_hasData) {
+        m_hasData = true;
         m_dataSize = size;
         m_dataAvailable = available;
 
index 93f4c8c9146b6122be489264c58d7e04907b8111..67dbf15ec4801f472e0a23e307280565725f1f20 100644 (file)
@@ -55,6 +55,7 @@ private slots:
 private:
     MountPointObserver* m_mountPointObserver;
 
+    bool    m_hasData;
     quint64 m_dataSize;
     quint64 m_dataAvailable;
 };
index 3ac87925fcc3f4121018920f8becdfb3c1fa8751..acffcf69dba126a8cbf423ad708f74be111cbe8d 100644 (file)
@@ -38,12 +38,23 @@ StatusBarSpaceInfo::~StatusBarSpaceInfo()
 {
 }
 
+void StatusBarSpaceInfo::setShown(bool shown)
+{
+    m_shown = shown;
+    if (!m_shown) {
+        hide();
+        m_ready = false;
+    }
+}
+
 void StatusBarSpaceInfo::setUrl(const QUrl& url)
 {
     if (m_url != url) {
         m_url = url;
+        m_ready = false;
         if (m_observer) {
-            m_observer->setUrl(url);
+            m_observer.reset(new SpaceInfoObserver(m_url, this));
+            connect(m_observer.data(), &SpaceInfoObserver::valuesChanged, this, &StatusBarSpaceInfo::slotValuesChanged);
         }
     }
 }
@@ -62,15 +73,24 @@ void StatusBarSpaceInfo::update()
 
 void StatusBarSpaceInfo::showEvent(QShowEvent* event)
 {
-    KCapacityBar::showEvent(event);
-    m_observer.reset(new SpaceInfoObserver(m_url, this));
-    slotValuesChanged();
-    connect(m_observer.data(), &SpaceInfoObserver::valuesChanged, this, &StatusBarSpaceInfo::slotValuesChanged);
+    if (m_shown) {
+        if (m_ready) {
+            KCapacityBar::showEvent(event);
+        }
+
+        if (m_observer.isNull()) {
+            m_observer.reset(new SpaceInfoObserver(m_url, this));
+            connect(m_observer.data(), &SpaceInfoObserver::valuesChanged, this, &StatusBarSpaceInfo::slotValuesChanged);
+        }
+    }
 }
 
 void StatusBarSpaceInfo::hideEvent(QHideEvent* event)
 {
-    m_observer.reset();
+    if (m_ready) {
+        m_observer.reset();
+        m_ready = false;
+    }
     KCapacityBar::hideEvent(event);
 }
 
@@ -95,19 +115,26 @@ void StatusBarSpaceInfo::slotValuesChanged()
 {
     Q_ASSERT(m_observer);
     const quint64 size = m_observer->size();
-    if (size == 0) {
-        setText(i18nc("@info:status", "Unknown size"));
-        setValue(0);
-        update();
+
+    if (!m_shown || size == 0) {
+        hide();
+        return;
+    }
+
+    m_ready = true;
+
+    const quint64 available = m_observer->available();
+    const quint64 used = size - available;
+    const int percentUsed = qRound(100.0 * qreal(used) / qreal(size));
+
+    setText(i18nc("@info:status Free disk space", "%1 free", KIO::convertSize(available)));
+    setUpdatesEnabled(false);
+    setValue(percentUsed);
+    setUpdatesEnabled(true);
+
+    if (!isVisible()) {
+        show();
     } else {
-        const quint64 available = m_observer->available();
-        const quint64 used = size - available;
-        const int percentUsed = qRound(100.0 * qreal(used) / qreal(size));
-
-        setText(i18nc("@info:status Free disk space", "%1 free", KIO::convertSize(available)));
-        setUpdatesEnabled(false);
-        setValue(percentUsed);
-        setUpdatesEnabled(true);
         update();
     }
 }
index 24f8b7f29fb6b910c4fd0c9564eed7d207daead5..0b0d787dd4f76e18daf1930653dd602989986feb 100644 (file)
@@ -42,6 +42,10 @@ public:
     explicit StatusBarSpaceInfo(QWidget* parent = nullptr);
     ~StatusBarSpaceInfo() override;
 
+    /**
+     * Use this to set the widget visibility as it can hide itself
+     */
+    void setShown(bool);
     void setUrl(const QUrl& url);
     QUrl url() const;
 
@@ -58,6 +62,8 @@ private slots:
 private:
     QScopedPointer<SpaceInfoObserver> m_observer;
     QUrl m_url;
+    bool m_ready;
+    bool m_shown;
 };
 
 #endif
index 8d4498675881910ceeec68bcb137042b5b16b4a3..a6fbf7845c5ef0f487106de64a62444c61eee25a 100644 (file)
@@ -3,11 +3,7 @@ set( EXECUTABLE_OUTPUT_PATH ${CMAKE_CURRENT_BINARY_DIR} )
 find_package(Qt5Test CONFIG REQUIRED)
 include(ECMAddTests)
 
-include(FindGem)
-
-find_gem(test-unit REQUIRED)
-set_package_properties(Gem:test-unit PROPERTIES
-    DESCRIPTION "Ruby gem 'test-unit' required for testing of servicemenu helpers.")
+include(FindGem)  # For servicemenutest, see bottom of this file
 
 # KItemSetTest
 ecm_add_test(kitemsettest.cpp LINK_LIBRARIES dolphinprivate Qt5::Test)
@@ -44,16 +40,16 @@ ecm_add_test(kitemlistkeyboardsearchmanagertest.cpp LINK_LIBRARIES dolphinprivat
 
 # DolphinSearchBox
 if (KF5Baloo_FOUND)
-  ecm_add_test(dolphinsearchboxtest.cpp
-  TEST_NAME dolphinsearchboxtest
-  LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test)
+    ecm_add_test(dolphinsearchboxtest.cpp
+    TEST_NAME dolphinsearchboxtest
+    LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test)
 endif()
 
 # DolphinQuery
 if (KF5Baloo_FOUND)
-  ecm_add_test(dolphinquerytest.cpp
-  TEST_NAME dolphinquerytest
-  LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test)
+    ecm_add_test(dolphinquerytest.cpp
+    TEST_NAME dolphinquerytest
+    LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test)
 endif()
 
 # KStandardItemModelTest
@@ -84,5 +80,11 @@ if (KF5_VERSION VERSION_GREATER_EQUAL 5.63.0)
     LINK_LIBRARIES dolphinprivate dolphinstatic Qt5::Test)
 endif()
 
-add_test(NAME servicemenutest
- COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../settings/services/test/test_run.rb)
+find_gem(test-unit)
+set_package_properties(Gem:test-unit PROPERTIES
+    TYPE RECOMMENDED
+    DESCRIPTION "Ruby gem 'test-unit' required for testing of servicemenu helpers.")
+if (Gem:test-unit_FOUND)
+    add_test(NAME servicemenutest
+    COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/../settings/services/test/test_run.rb)
+endif()
index b65ee037fdcc343c6fc3af31589f074574fc0603..a0774e88c8f63a4a682ad06a72eda36ae228ce3d 100644 (file)
@@ -36,11 +36,40 @@ private slots:
     void testBalooSearchParsing();
 };
 
+/**
+ * Helper function to compose the baloo query URL used for searching
+ */
+QUrl balooQueryUrl(const QString& searchString)
+{
+    const QJsonObject jsonObject {
+        {"searchString", searchString}
+    };
+
+    const QJsonDocument doc(jsonObject);
+    const QString queryString = QString::fromUtf8(doc.toJson(QJsonDocument::Compact));
+
+    QUrlQuery urlQuery;
+    urlQuery.addQueryItem(QStringLiteral("json"), queryString);
+
+    QUrl searchUrl;
+    searchUrl.setScheme(QLatin1String("baloosearch"));
+    searchUrl.setQuery(urlQuery);
+
+    return searchUrl;
+}
+
 /**
  * Defines the parameters for the test cases in testBalooSearchParsing()
  */
 void DolphinSearchBoxTest::testBalooSearchParsing_data()
 {
+
+    QTest::addColumn<QUrl>("searchUrl");
+    QTest::addColumn<QString>("expectedText");
+    QTest::addColumn<QStringList>("expectedTerms");
+    QTest::addColumn<bool>("hasContent");
+    QTest::addColumn<bool>("hasFileName");
+
     const QString text = QStringLiteral("abc");
     const QString textS = QStringLiteral("abc xyz");
     const QString filename = QStringLiteral("filename:\"%1\"").arg(text);
@@ -53,115 +82,89 @@ void DolphinSearchBoxTest::testBalooSearchParsing_data()
     const QString tagS = QStringLiteral("tag:\"tagB with spaces\"");  // in search url
     const QString tagR = QStringLiteral("tag:tagB with spaces");      // in result term
 
-    QTest::addColumn<QString>("searchString");
-    QTest::addColumn<QString>("expectedText");
-    QTest::addColumn<QStringList>("expectedTerms");
-    QTest::addColumn<bool>("hasContent");
-    QTest::addColumn<bool>("hasFileName");
-
     // Test for "Content"
-    QTest::newRow("content")              << text    << text  << QStringList() << true  << false;
-    QTest::newRow("content/space")        << textS   << textS << QStringList() << true  << false;
-    QTest::newRow("content/empty")        << ""      << ""    << QStringList() << false << false;
-    QTest::newRow("content/single_quote") << "\""    << "\""  << QStringList() << true  << false;
-    QTest::newRow("content/double_quote") << "\"\""  << ""    << QStringList() << false << false;
+    QTest::newRow("content")              << balooQueryUrl(text)   << text  << QStringList() << true  << false;
+    QTest::newRow("content/space")        << balooQueryUrl(textS)  << textS << QStringList() << true  << false;
+    QTest::newRow("content/empty")        << balooQueryUrl("")     << ""    << QStringList() << false << false;
+    QTest::newRow("content/single_quote") << balooQueryUrl("\"")   << "\""  << QStringList() << true  << false;
+    QTest::newRow("content/double_quote") << balooQueryUrl("\"\"") << ""    << QStringList() << false << false;
 
     // Test for "FileName"
-    QTest::newRow("filename")              << filename        << text  << QStringList() << false << true;
-    QTest::newRow("filename/space")        << filenameS       << textS << QStringList() << false << true;
-    QTest::newRow("filename/empty")        << "filename:"     << ""    << QStringList() << false << false;
-    QTest::newRow("filename/single_quote") << "filename:\""   << "\""  << QStringList() << false << true;
-    QTest::newRow("filename/double_quote") << "filename:\"\"" << ""    << QStringList() << false << false;
+    QTest::newRow("filename")              << balooQueryUrl(filename)        << text  << QStringList() << false << true;
+    QTest::newRow("filename/space")        << balooQueryUrl(filenameS)       << textS << QStringList() << false << true;
+    QTest::newRow("filename/empty")        << balooQueryUrl("filename:")     << ""    << QStringList() << false << false;
+    QTest::newRow("filename/single_quote") << balooQueryUrl("filename:\"")   << "\""  << QStringList() << false << true;
+    QTest::newRow("filename/double_quote") << balooQueryUrl("filename:\"\"") << ""    << QStringList() << false << false;
 
     // Combined content and filename search
     QTest::newRow("content+filename")
-        << text + " " + filename
+        << balooQueryUrl(text + " " + filename)
         << text + " " + filename << QStringList() << true << true;
 
     // Test for rating
-    QTest::newRow("rating")          << rating                  << ""   << QStringList({rating}) << false << false;
-    QTest::newRow("rating+content")  << rating + " " + text     << text << QStringList({rating}) << true  << false;
-    QTest::newRow("rating+filename") << rating + " " + filename << text << QStringList({rating}) << false << true;
+    QTest::newRow("rating")          << balooQueryUrl(rating)                  << ""   << QStringList({rating}) << false << false;
+    QTest::newRow("rating+content")  << balooQueryUrl(rating + " " + text)     << text << QStringList({rating}) << true  << false;
+    QTest::newRow("rating+filename") << balooQueryUrl(rating + " " + filename) << text << QStringList({rating}) << false << true;
 
     // Test for modified date
-    QTest::newRow("modified")          << modified                  << ""   << QStringList({modified}) << false << false;
-    QTest::newRow("modified+content")  << modified + " " + text     << text << QStringList({modified}) << true  << false;
-    QTest::newRow("modified+filename") << modified + " " + filename << text << QStringList({modified}) << false << true;
+    QTest::newRow("modified")          << balooQueryUrl(modified)                  << ""   << QStringList({modified}) << false << false;
+    QTest::newRow("modified+content")  << balooQueryUrl(modified + " " + text)     << text << QStringList({modified}) << true  << false;
+    QTest::newRow("modified+filename") << balooQueryUrl(modified + " " + filename) << text << QStringList({modified}) << false << true;
 
     // Test for tags
-    QTest::newRow("tag")          << tag                  << ""   << QStringList({tag})       << false << false;
-    QTest::newRow("tag/space" )   << tagS                 << ""   << QStringList({tagR})      << false << false;
-    QTest::newRow("tag/double")   << tag + " " + tagS     << ""   << QStringList({tag, tagR}) << false << false;
-    QTest::newRow("tag+content")  << tag + " " + text     << text << QStringList({tag})       << true  << false;
-    QTest::newRow("tag+filename") << tag + " " + filename << text << QStringList({tag})       << false << true;
+    QTest::newRow("tag")          << balooQueryUrl(tag)                  << ""   << QStringList({tag})       << false << false;
+    QTest::newRow("tag/space" )   << balooQueryUrl(tagS)                 << ""   << QStringList({tagR})      << false << false;
+    QTest::newRow("tag/double")   << balooQueryUrl(tag + " " + tagS)     << ""   << QStringList({tag, tagR}) << false << false;
+    QTest::newRow("tag+content")  << balooQueryUrl(tag + " " + text)     << text << QStringList({tag})       << true  << false;
+    QTest::newRow("tag+filename") << balooQueryUrl(tag + " " + filename) << text << QStringList({tag})       << false << true;
 
     // Combined search terms
     QTest::newRow("searchTerms")
-        << rating + " AND " + modified + " AND " + tag + " AND " + tagS
+        << balooQueryUrl(rating + " AND " + modified + " AND " + tag + " AND " + tagS)
         << "" << QStringList({modified, rating, tag, tagR}) << false << false;
 
     QTest::newRow("searchTerms+content")
-        << rating + " AND " + modified + " " + text + " " + tag + " AND " + tagS
+        << balooQueryUrl(rating + " AND " + modified + " " + text + " " + tag + " AND " + tagS)
         << text << QStringList({modified, rating, tag, tagR}) << true << false;
 
     QTest::newRow("searchTerms+filename")
-        << rating + " AND " + modified + " " + filename + " " + tag + " AND " + tagS
+        << balooQueryUrl(rating + " AND " + modified + " " + filename + " " + tag + " AND " + tagS)
         << text << QStringList({modified, rating, tag, tagR}) << false << true;
 
     QTest::newRow("allTerms")
-        << text + " " + filename + " " + rating + " AND " + modified + " AND " + tag
+        << balooQueryUrl(text + " " + filename + " " + rating + " AND " + modified + " AND " + tag)
         << text + " " + filename << QStringList({modified, rating, tag}) << true << true;
 
     QTest::newRow("allTerms/space")
-        << textS + " " + filenameS + " " + rating + " AND " + modified + " AND " + tagS
+        << balooQueryUrl(textS + " " + filenameS + " " + rating + " AND " + modified + " AND " + tagS)
         << textS + " " + filenameS << QStringList({modified, rating, tagR}) << true << true;
 }
 
 /**
- * Helper function to compose the baloo query URL used for searching
- */
-QUrl composeQueryUrl(const QString& searchString)
-{
-    const QJsonObject jsonObject {
-        {"searchString", searchString}
-    };
-
-    const QJsonDocument doc(jsonObject);
-    const QString queryString = QString::fromUtf8(doc.toJson(QJsonDocument::Compact));
-
-    QUrlQuery urlQuery;
-    urlQuery.addQueryItem(QStringLiteral("json"), queryString);
-
-    QUrl searchUrl;
-    searchUrl.setScheme(QLatin1String("baloosearch"));
-    searchUrl.setQuery(urlQuery);
-
-    return searchUrl;
-}
-
-/**
- * The test verifies whether the different terms of a Baloo search URL ("baloosearch:") are
+ * The test verifies whether the different terms search URL (e.g. "baloosearch:/") are
  * properly handled by the searchbox, and only "user" or filename terms are added to the
  * text bar of the searchbox.
  */
 void DolphinSearchBoxTest::testBalooSearchParsing()
 {
-    QFETCH(QString, searchString);
+    QFETCH(QUrl, searchUrl);
     QFETCH(QString, expectedText);
     QFETCH(QStringList, expectedTerms);
     QFETCH(bool, hasContent);
     QFETCH(bool, hasFileName);
 
-    const QUrl testUrl = composeQueryUrl(searchString);
-    const DolphinQuery query = DolphinQuery::fromBalooSearchUrl(testUrl);
+    const DolphinQuery query = DolphinQuery::fromSearchUrl(searchUrl);
 
-    QStringList searchTerms = query.searchTerms();
-    searchTerms.sort();
+    // Checkt that the URL is supported
+    QVERIFY(DolphinQuery::supportsScheme(searchUrl.scheme()));
 
     // Check for parsed text (would be displayed on the input search bar)
     QCOMPARE(query.text(), expectedText);
 
     // Check for parsed search terms (would be displayed by the facetsWidget)
+    QStringList searchTerms = query.searchTerms();
+    searchTerms.sort();
+
     QCOMPARE(searchTerms.count(), expectedTerms.count());
     for (int i = 0; i < expectedTerms.count(); i++) {
         QCOMPARE(searchTerms.at(i), expectedTerms.at(i));
index 0c38f02bfd8de7b642ae6bf61ad6a8f87b3ee25c..7e949c34f71f5feb79558842c95b93b3dd431b4b 100644 (file)
@@ -18,6 +18,7 @@
  *   51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA            *
  ***************************************************************************/
 
+#include <QRandomGenerator>
 #include <QTest>
 #include <QSignalSpy>
 #include <QTimer>
@@ -450,9 +451,9 @@ void KFileItemModelTest::testModelConsistencyWhenInsertingItems()
         itemsInsertedSpy.clear();
 
         for (int j = 0; j < 10; ++j) {
-            int itemName = qrand();
+            int itemName = QRandomGenerator::global()->generate();
             while (insertedItems.contains(itemName)) {
-                itemName = qrand();
+                itemName = QRandomGenerator::global()->generate();
             }
             insertedItems.insert(itemName);
 
index 6397a48b70e60fdc2f583fb6efd741afaac7fc38..9e8fda650e37149f1a6d051d1514a2825ebbdb1d 100644 (file)
@@ -91,7 +91,7 @@ void DolphinItemListView::readSettings()
 
     const KConfigGroup globalConfig(KSharedConfig::openConfig(), "PreviewSettings");
     setEnabledPlugins(globalConfig.readEntry("Plugins", KIO::PreviewJob::defaultPlugins()));
-
+    setLocalFileSizePreviewLimit(globalConfig.readEntry("MaximumSize", 0));
     endTransaction();
 }
 
index 2caa8ec68185ec0a465cacd3f673c4cf6e8e02fe..9af6919277911779b9bbc74220bf5ad464a9f33f 100644 (file)
@@ -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::copySelectedItems(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::moveSelectedItems(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,31 @@ void DolphinView::calculateItemCount(int& fileCount,
                                      KIO::filesize_t& totalFileSize) const
 {
     const int itemCount = m_model->count();
+
+    bool countFileSize = true;
+
+    if (!m_model->rootItem().url().isValid()) {
+        return;
+    }
+
+    // In case we have a precomputed value
+    const auto job = KIO::statDetails(m_model->rootItem().url(), KIO::StatJob::SourceSide, KIO::StatRecursiveSize, KIO::HideProgressInfo);
+    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 +1875,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
index 83c5f92a4dbdd01040ba28155bf2a8930ce5fb27..4306b3eb73aa44ee43736bc58284bd0c726118c9 100644 (file)
@@ -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,20 @@ 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 @p destinationUrl.
+     */
+    void copySelectedItems(const KFileItemList &selection, const QUrl &destinationUrl);
+
+    /**
+     * Moves all selected items to @p destinationUrl.
+     */
+    void moveSelectedItems(const KFileItemList &selection, const QUrl &destinationUrl);
 
     /** Pastes the clipboard data to this view. */
     void paste();
@@ -602,6 +618,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 +627,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
index c61e1aaa9f46df99ef418e4059f83cc77a4e9c4a..e89e2e62c2b705e32223dca048334d6c22f7f224 100644 (file)
@@ -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"));
index c3d4d1837a1bc76ca44e698cf970e9d3ac792b8e..ec0bbbcd3afa58ef76ca52fedbc04be9f96f264b 100644 (file)
@@ -4,6 +4,7 @@ X-KDE-ServiceType=FileViewVersionControlPlugin
 Comment=Version Control Plugin for File Views
 Comment[ar]=ملحقة تحكّم بالإصدارات لمناظير الملفّات
 Comment[ast]=Complementu de control de versiones pa les vistes de ficheros
+Comment[az]=Fayl meneceri üçün versiyaya nəzarət əlavəsi
 Comment[ca]=Connector de control de versions per a les vistes de fitxers
 Comment[ca@valencia]=Connector de control de versions per a les vistes de fitxers
 Comment[cs]=Modul pro správu verzí pro pohledy na soubory
index 2879745349653126579ae2ebcff96222d221facd..0d94a3fc88fb0823738380420d68f726c27648b6 100644 (file)
@@ -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:
     /**
index 2d801686e259099a249a301b613f49109d41ca03..2f0632243ea0a01330cb813cac17915152b9499c 100644 (file)
@@ -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;
 }
index 66f992963c3532d5080f00844d01ea01d7a25798..648c9d6fdfd126b9fce238f8cd8302f9ae3a9483 100644 (file)
@@ -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;