]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/views/dolphinview.cpp
DolphinView: Use SingleShot and Queued Connections
[dolphin.git] / src / views / dolphinview.cpp
index d0db814e4d404dee7bd3e36835e8bc6e8ac02db6..ae0aa903c02aee9382794c131a10f1465cf9ef94 100644 (file)
@@ -35,7 +35,7 @@
 #include <KFileItemListProperties>
 #include <KFormat>
 #include <KIO/CopyJob>
-#include <KIO/DeleteJob>
+#include <KIO/DeleteOrTrashJob>
 #include <KIO/DropJob>
 #include <KIO/JobUiDelegate>
 #include <KIO/Paste>
@@ -49,9 +49,6 @@
 
 #include <kwidgetsaddons_version.h>
 
-#include <KIO/DeleteOrTrashJob>
-#include <kio_version.h>
-
 #include <QAbstractItemView>
 #include <QActionGroup>
 #include <QApplication>
@@ -129,6 +126,9 @@ DolphinView::DolphinView(const QUrl &url, QWidget *parent)
 
     m_container = new KItemListContainer(controller, this);
     m_container->installEventFilter(this);
+#ifndef QT_NO_ACCESSIBILITY
+    m_view->setAccessibleParentsObject(m_container);
+#endif
     setFocusProxy(m_container);
     connect(m_container->horizontalScrollBar(), &QScrollBar::valueChanged, this, [=] {
         hideToolTip();
@@ -200,7 +200,8 @@ DolphinView::DolphinView(const QUrl &url, QWidget *parent)
     connect(m_model, &KFileItemModel::directoryRedirection, this, &DolphinView::slotDirectoryRedirection);
     connect(m_model, &KFileItemModel::urlIsFileError, this, &DolphinView::urlIsFileError);
     connect(m_model, &KFileItemModel::fileItemsChanged, this, &DolphinView::fileItemsChanged);
-    connect(m_model, &KFileItemModel::currentDirectoryRemoved, this, &DolphinView::currentDirectoryRemoved);
+    // #473377: Use a QueuedConnection to avoid modifying KCoreDirLister before KCoreDirListerCache::deleteDir() returns.
+    connect(m_model, &KFileItemModel::currentDirectoryRemoved, this, &DolphinView::currentDirectoryRemoved, Qt::QueuedConnection);
 
     connect(this, &DolphinView::itemCountChanged, this, &DolphinView::updatePlaceholderLabel);
 
@@ -267,7 +268,6 @@ void DolphinView::setActive(bool active)
     if (active) {
         m_container->setFocus();
         Q_EMIT activated();
-        Q_EMIT writeStateChanged(m_isFolderWritable);
     }
 }
 
@@ -309,8 +309,8 @@ void DolphinView::setSelectionModeEnabled(const bool enabled)
         m_view->setStyle(m_proxyStyle.get());
         m_view->setEnabledSelectionToggles(DolphinItemListView::SelectionTogglesEnabled::False);
     } else {
-        setStyle(QApplication::style());
-        m_view->setStyle(QApplication::style());
+        setStyle(nullptr);
+        m_view->setStyle(nullptr);
         m_view->setEnabledSelectionToggles(DolphinItemListView::SelectionTogglesEnabled::FollowSetting);
     }
     m_container->controller()->setSelectionModeEnabled(enabled);
@@ -471,7 +471,13 @@ int DolphinView::zoomLevel() const
 void DolphinView::setSortRole(const QByteArray &role)
 {
     if (role != sortRole()) {
-        updateSortRole(role);
+        ViewProperties props(viewPropertiesUrl());
+        props.setSortRole(role);
+
+        KItemModelBase *model = m_container->controller()->model();
+        model->setSortRole(role);
+
+        Q_EMIT sortRoleChanged(role);
     }
 }
 
@@ -484,7 +490,12 @@ QByteArray DolphinView::sortRole() const
 void DolphinView::setSortOrder(Qt::SortOrder order)
 {
     if (sortOrder() != order) {
-        updateSortOrder(order);
+        ViewProperties props(viewPropertiesUrl());
+        props.setSortOrder(order);
+
+        m_model->setSortOrder(order);
+
+        Q_EMIT sortOrderChanged(order);
     }
 }
 
@@ -626,7 +637,7 @@ void DolphinView::requestStatusBarText()
             return;
         }
 
-        m_statJobForStatusBarText = KIO::statDetails(m_model->rootItem().url(), KIO::StatJob::SourceSide, KIO::StatRecursiveSize, KIO::HideProgressInfo);
+        m_statJobForStatusBarText = KIO::stat(m_model->rootItem().url(), KIO::StatJob::SourceSide, KIO::StatRecursiveSize, KIO::HideProgressInfo);
         connect(m_statJobForStatusBarText, &KJob::result, this, &DolphinView::slotStatJobResult);
         m_statJobForStatusBarText->start();
     }
@@ -641,11 +652,11 @@ void DolphinView::emitStatusBarText(const int folderCount, const int fileCount,
     if (selection == HasSelection) {
         // At least 2 items are selected because the case of 1 selected item is handled in
         // DolphinView::requestStatusBarText().
-        foldersText = i18ncp("@info:status", "1 Folder selected", "%1 Folders selected", folderCount);
-        filesText = i18ncp("@info:status", "1 File selected", "%1 Files selected", fileCount);
+        foldersText = i18ncp("@info:status", "1 folder selected", "%1 folders selected", folderCount);
+        filesText = i18ncp("@info:status", "1 file selected", "%1 files selected", fileCount);
     } else {
-        foldersText = i18ncp("@info:status", "1 Folder", "%1 Folders", folderCount);
-        filesText = i18ncp("@info:status", "1 File", "%1 Files", fileCount);
+        foldersText = i18ncp("@info:status", "1 folder", "%1 folders", folderCount);
+        filesText = i18ncp("@info:status", "1 file", "%1 files", fileCount);
     }
 
     if (fileCount > 0 && folderCount > 0) {
@@ -655,7 +666,7 @@ void DolphinView::emitStatusBarText(const int folderCount, const int fileCount,
     } else if (folderCount > 0) {
         summary = foldersText;
     } else {
-        summary = i18nc("@info:status", "0 Folders, 0 Files");
+        summary = i18nc("@info:status", "0 folders, 0 files");
     }
     Q_EMIT statusBarTextChanged(summary);
 }
@@ -730,17 +741,18 @@ void DolphinView::renameSelectedItems()
     if (items.count() == 1 && GeneralSettings::renameInline()) {
         const int index = m_model->index(items.first());
 
-        QMetaObject::Connection *const connection = new QMetaObject::Connection;
-        *connection = connect(m_view, &KItemListView::scrollingStopped, this, [=]() {
-            QObject::disconnect(*connection);
-            delete connection;
-
-            m_view->editRole(index, "text");
+        connect(
+            m_view,
+            &KItemListView::scrollingStopped,
+            this,
+            [this, index]() {
+                m_view->editRole(index, "text");
 
-            hideToolTip();
+                hideToolTip();
 
-            connect(m_view, &DolphinItemListView::roleEditingFinished, this, &DolphinView::slotRoleEditingFinished);
-        });
+                connect(m_view, &DolphinItemListView::roleEditingFinished, this, &DolphinView::slotRoleEditingFinished);
+            },
+            Qt::SingleShotConnection);
         m_view->scrollToItem(index);
 
     } else {
@@ -853,9 +865,12 @@ void DolphinView::duplicateSelectedItems()
 
     const QMimeDatabase db;
 
+    m_clearSelectionBeforeSelectingNewItems = true;
+    m_markFirstNewlySelectedItemAsCurrent = true;
+    m_selectJobCreatedItems = true;
+
     // Duplicate all selected items and append "copy" to the end of the file name
     // but before the filename extension, if present
-    QList<QUrl> newSelection;
     for (const auto &item : itemList) {
         const QUrl originalURL = item.url();
         const QString originalDirectoryPath = originalURL.adjusted(QUrl::RemoveFilename).path();
@@ -880,15 +895,14 @@ void DolphinView::duplicateSelectedItems()
         }
 
         KIO::CopyJob *job = KIO::copyAs(originalURL, duplicateURL);
+        job->setAutoRename(true);
         KJobWidgets::setWindow(job, this);
 
-        if (job) {
-            newSelection << duplicateURL;
-            KIO::FileUndoManager::self()->recordCopyJob(job);
-        }
+        connect(job, &KIO::CopyJob::result, this, &DolphinView::slotJobResult);
+        connect(job, &KIO::CopyJob::copyingDone, this, &DolphinView::slotItemCreatedFromJob);
+        connect(job, &KIO::CopyJob::copyingLinkDone, this, &DolphinView::slotItemLinkCreatedFromJob);
+        KIO::FileUndoManager::self()->recordCopyJob(job);
     }
-
-    forceUrlsSelection(newSelection.first(), newSelection);
 }
 
 void DolphinView::stopLoading()
@@ -1148,7 +1162,7 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF &pos)
 {
     ViewProperties props(viewPropertiesUrl());
 
-    QPointer<QMenu> menu = new QMenu(QApplication::activeWindow());
+    QPointer<QMenu> menu = new QMenu(this);
 
     KItemListView *view = m_container->controller()->view();
     const QList<QByteArray> visibleRolesSet = view->visibleRoles();
@@ -1412,6 +1426,11 @@ void DolphinView::slotItemCreatedFromJob(KIO::Job *, const QUrl &, const QUrl &t
     slotItemCreated(to);
 }
 
+void DolphinView::slotItemLinkCreatedFromJob(KIO::Job *, const QUrl &, const QString &, const QUrl &to)
+{
+    slotItemCreated(to);
+}
+
 void DolphinView::slotItemCreated(const QUrl &url)
 {
     if (m_markFirstNewlySelectedItemAsCurrent) {
@@ -1423,10 +1442,12 @@ void DolphinView::slotItemCreated(const QUrl &url)
     }
 }
 
-void DolphinView::onDirectoryLoadingCompleted()
+void DolphinView::onDirectoryLoadingCompletedAfterJob()
 {
     // the model should now contain all the items created by the job
-    updateSelectionState();
+    m_selectJobCreatedItems = true; // to make sure we overwrite selection
+    // update the view: scroll into View and selection
+    updateViewState();
     m_selectJobCreatedItems = false;
     m_selectedUrls.clear();
 }
@@ -1446,7 +1467,7 @@ void DolphinView::slotJobResult(KJob *job)
         updateSelectionState();
         if (!m_selectedUrls.isEmpty()) {
             // not all urls were found, the model may not be up to date
-            connect(m_model, &KFileItemModel::directoryLoadingCompleted, this, &DolphinView::onDirectoryLoadingCompleted, Qt::UniqueConnection);
+            connect(m_model, &KFileItemModel::directoryLoadingCompleted, this, &DolphinView::onDirectoryLoadingCompletedAfterJob, Qt::SingleShotConnection);
         } else {
             m_selectJobCreatedItems = false;
             m_selectedUrls.clear();
@@ -1503,27 +1524,6 @@ void DolphinView::slotStatJobResult(KJob *job)
     emitStatusBarText(folderCount, fileCount, totalFileSize, NoSelection);
 }
 
-void DolphinView::updateSortRole(const QByteArray &role)
-{
-    ViewProperties props(viewPropertiesUrl());
-    props.setSortRole(role);
-
-    KItemModelBase *model = m_container->controller()->model();
-    model->setSortRole(role);
-
-    Q_EMIT sortRoleChanged(role);
-}
-
-void DolphinView::updateSortOrder(Qt::SortOrder order)
-{
-    ViewProperties props(viewPropertiesUrl());
-    props.setSortOrder(order);
-
-    m_model->setSortOrder(order);
-
-    Q_EMIT sortOrderChanged(order);
-}
-
 void DolphinView::updateSortFoldersFirst(bool foldersFirst)
 {
     ViewProperties props(viewPropertiesUrl());
@@ -1759,7 +1759,7 @@ void DolphinView::updateViewState()
 
                 // scroll to current item and reset the state
                 if (m_scrollToCurrentItem) {
-                    m_view->scrollToItem(currentIndex);
+                    m_view->scrollToItem(currentIndex, KItemListView::ViewItemPosition::Middle);
                     m_scrollToCurrentItem = false;
                 }
                 m_currentItemUrl = QUrl();
@@ -1939,10 +1939,7 @@ void DolphinView::slotSortRoleChangedByHeader(const QByteArray &current, const Q
     Q_UNUSED(previous)
     Q_ASSERT(m_model->sortRole() == current);
 
-    ViewProperties props(viewPropertiesUrl());
-    props.setSortRole(current);
-
-    Q_EMIT sortRoleChanged(current);
+    setSortRole(current);
 }
 
 void DolphinView::slotVisibleRolesChangedByHeader(const QList<QByteArray> &current, const QList<QByteArray> &previous)
@@ -2243,6 +2240,11 @@ void DolphinView::updateWritableState()
     }
 }
 
+bool DolphinView::isFolderWritable() const
+{
+    return m_isFolderWritable;
+}
+
 QUrl DolphinView::viewPropertiesUrl() const
 {
     if (m_viewPropertiesContext.isEmpty()) {
@@ -2283,7 +2285,7 @@ void DolphinView::copyPathToClipboard()
     if (clipboard == nullptr) {
         return;
     }
-    clipboard->setText(path);
+    clipboard->setText(QDir::toNativeSeparators(path));
 }
 
 void DolphinView::slotIncreaseZoom()