]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/views/dolphinview.cpp
Merge remote-tracking branch 'fork/work/zakharafoniam/useful-groups'
[dolphin.git] / src / views / dolphinview.cpp
index 8302620e424480bcaf4e768d4140f9d9d7159dff..5c961b47b594c18d0710a3f408dd78668b5a7a64 100644 (file)
@@ -44,6 +44,7 @@
 #include <KIO/Paste>
 #include <KIO/PasteJob>
 #include <KIO/RenameFileDialog>
+#include <KJob>
 #include <KJobWidgets>
 #include <KLocalizedString>
 #include <KMessageBox>
@@ -123,8 +124,7 @@ DolphinView::DolphinView(const QUrl &url, QWidget *parent)
     applyModeToView();
 
     KItemListController *controller = new KItemListController(m_model, m_view, this);
-    const int delay = GeneralSettings::autoExpandFolders() ? 750 : -1;
-    controller->setAutoActivationDelay(delay);
+    controller->setAutoActivationEnabled(GeneralSettings::autoExpandFolders());
     connect(controller, &KItemListController::doubleClickViewBackground, this, &DolphinView::doubleClickViewBackground);
 
     // The EnlargeSmallPreviews setting can only be changed after the model
@@ -515,6 +515,42 @@ Qt::SortOrder DolphinView::sortOrder() const
     return m_model->sortOrder();
 }
 
+void DolphinView::setGroupRole(const QByteArray &role)
+{
+    if (role != groupRole()) {
+        ViewProperties props(viewPropertiesUrl());
+        props.setGroupRole(role);
+
+        KItemModelBase *model = m_container->controller()->model();
+        model->setGroupRole(role);
+
+        Q_EMIT groupRoleChanged(role);
+    }
+}
+
+QByteArray DolphinView::groupRole() const
+{
+    const KItemModelBase *model = m_container->controller()->model();
+    return model->groupRole();
+}
+
+void DolphinView::setGroupOrder(Qt::SortOrder order)
+{
+    if (groupOrder() != order) {
+        ViewProperties props(viewPropertiesUrl());
+        props.setGroupOrder(order);
+
+        m_model->setGroupOrder(order);
+
+        Q_EMIT groupOrderChanged(order);
+    }
+}
+
+Qt::SortOrder DolphinView::groupOrder() const
+{
+    return m_model->groupOrder();
+}
+
 void DolphinView::setSortFoldersFirst(bool foldersFirst)
 {
     if (sortFoldersFirst() != foldersFirst) {
@@ -578,8 +614,7 @@ void DolphinView::readSettings()
     m_view->readSettings();
     applyViewProperties();
 
-    const int delay = GeneralSettings::autoExpandFolders() ? 750 : -1;
-    m_container->controller()->setAutoActivationDelay(delay);
+    m_container->controller()->setAutoActivationEnabled(GeneralSettings::autoExpandFolders());
 
     const int newZoomLevel = m_view->zoomLevel();
     if (newZoomLevel != oldZoomLevel) {
@@ -812,7 +847,7 @@ void DolphinView::deleteSelectedItems()
 
     using Iface = KIO::AskUserActionInterface;
     auto *trashJob = new KIO::DeleteOrTrashJob(list, Iface::Delete, Iface::DefaultConfirmation, this);
-    connect(trashJob, &KJob::result, this, &DolphinView::slotTrashFileFinished);
+    connect(trashJob, &KJob::result, this, &DolphinView::slotDeleteFileFinished);
     m_selectNextItem = true;
     trashJob->start();
 }
@@ -848,6 +883,9 @@ void DolphinView::copySelectedItems(const KFileItemList &selection, const QUrl &
     connect(job, &KIO::CopyJob::result, this, &DolphinView::slotJobResult);
     connect(job, &KIO::CopyJob::copying, this, &DolphinView::slotItemCreatedFromJob);
     connect(job, &KIO::CopyJob::copyingDone, this, &DolphinView::slotItemCreatedFromJob);
+    connect(job, &KIO::CopyJob::warning, this, [this](KJob *job, const QString & /* warning */) {
+        Q_EMIT errorMessage(job->errorString(), job->error());
+    });
     KIO::FileUndoManager::self()->recordCopyJob(job);
 }
 
@@ -867,6 +905,9 @@ void DolphinView::moveSelectedItems(const KFileItemList &selection, const QUrl &
     connect(job, &KIO::CopyJob::result, this, &DolphinView::slotJobResult);
     connect(job, &KIO::CopyJob::moving, this, &DolphinView::slotItemCreatedFromJob);
     connect(job, &KIO::CopyJob::copyingDone, this, &DolphinView::slotItemCreatedFromJob);
+    connect(job, &KIO::CopyJob::warning, this, [this](KJob *job, const QString & /*warning */) {
+        Q_EMIT errorMessage(job->errorString(), job->error());
+    });
     KIO::FileUndoManager::self()->recordCopyJob(job);
 }
 
@@ -928,6 +969,9 @@ void DolphinView::duplicateSelectedItems()
         connect(job, &KIO::CopyJob::result, this, &DolphinView::slotJobResult);
         connect(job, &KIO::CopyJob::copyingDone, this, &DolphinView::slotItemCreatedFromJob);
         connect(job, &KIO::CopyJob::copyingLinkDone, this, &DolphinView::slotItemLinkCreatedFromJob);
+        connect(job, &KIO::CopyJob::warning, this, [this](KJob *job, const QString & /*warning*/) {
+            Q_EMIT errorMessage(job->errorString(), job->error());
+        });
         KIO::FileUndoManager::self()->recordCopyJob(job);
     }
 }
@@ -1174,6 +1218,9 @@ void DolphinView::slotItemContextMenuRequested(int index, const QPointF &pos)
     if (m_selectionChangedTimer->isActive()) {
         emitSelectionChangedSignal();
     }
+    if (m_twoClicksRenamingTimer->isActive()) {
+        abortTwoClicksRenaming();
+    }
 
     const KFileItem item = m_model->fileItem(index);
     Q_EMIT requestContextMenu(pos.toPoint(), item, selectedItems(), url());
@@ -1239,7 +1286,7 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF &pos)
 
     QAction *toggleSidePaddingAction = menu->addAction(i18nc("@action:inmenu", "Side Padding"));
     toggleSidePaddingAction->setCheckable(true);
-    toggleSidePaddingAction->setChecked(view->header()->sidePadding() > 0);
+    toggleSidePaddingAction->setChecked(layoutDirection() == Qt::LeftToRight ? view->header()->leftPadding() > 0 : view->header()->rightPadding() > 0);
 
     QAction *autoAdjustWidthsAction = menu->addAction(i18nc("@action:inmenu", "Automatic Column Widths"));
     autoAdjustWidthsAction->setCheckable(true);
@@ -1272,7 +1319,11 @@ void DolphinView::slotHeaderContextMenuRequested(const QPointF &pos)
             props.setHeaderColumnWidths(columnWidths);
             header->setAutomaticColumnResizing(false);
         } else if (action == toggleSidePaddingAction) {
-            header->setSidePadding(toggleSidePaddingAction->isChecked() ? 20 : 0);
+            if (toggleSidePaddingAction->isChecked()) {
+                header->setSidePadding(20, 20);
+            } else {
+                header->setSidePadding(0, 0);
+            }
         } else {
             // Show or hide the selected role
             const QByteArray selectedRole = action->data().toByteArray();
@@ -1325,10 +1376,11 @@ void DolphinView::slotHeaderColumnWidthChangeFinished(const QByteArray &role, qr
     props.setHeaderColumnWidths(columnWidths);
 }
 
-void DolphinView::slotSidePaddingWidthChanged(qreal width)
+void DolphinView::slotSidePaddingWidthChanged(qreal leftPaddingWidth, qreal rightPaddingWidth)
 {
     ViewProperties props(viewPropertiesUrl());
-    DetailsModeSettings::setSidePadding(int(width));
+    DetailsModeSettings::setLeftPadding(int(leftPaddingWidth));
+    DetailsModeSettings::setRightPadding(int(rightPaddingWidth));
     m_view->writeSettings();
 }
 
@@ -1395,6 +1447,9 @@ void DolphinView::dropUrls(const QUrl &destUrl, QDropEvent *dropEvent, QWidget *
             connect(job, &KIO::DropJob::copyJobStarted, this, [this](const KIO::CopyJob *copyJob) {
                 connect(copyJob, &KIO::CopyJob::copying, this, &DolphinView::slotItemCreatedFromJob);
                 connect(copyJob, &KIO::CopyJob::moving, this, &DolphinView::slotItemCreatedFromJob);
+                connect(copyJob, &KIO::CopyJob::warning, this, [this](KJob *job, const QString & /*warning*/) {
+                    Q_EMIT errorMessage(job->errorString(), job->error());
+                });
                 connect(copyJob, &KIO::CopyJob::linking, this, [this](KIO::Job *job, const QString &src, const QUrl &dest) {
                     Q_UNUSED(job)
                     Q_UNUSED(src)
@@ -1768,7 +1823,6 @@ void DolphinView::updateSelectionState()
             if (!selectedItems.isEmpty()) {
                 selectionManager->beginAnchoredSelection(selectionManager->currentItem());
                 selectionManager->setSelectedItems(selectedItems);
-                selectionManager->endAnchoredSelection();
                 if (shouldScrollToCurrentItem) {
                     m_view->scrollToItem(selectedItems.first());
                 }
@@ -1876,7 +1930,7 @@ void DolphinView::selectNextItem()
             Q_ASSERT_X(false, "DolphinView", "Selecting the next item failed.");
             return;
         }
-        const auto lastSelectedIndex = m_model->index(selectedItems().last());
+        const auto lastSelectedIndex = m_model->index(selectedItems().constLast());
         if (lastSelectedIndex < 0) {
             Q_ASSERT_X(false, "DolphinView", "Selecting the next item failed.");
             return;
@@ -1940,6 +1994,7 @@ void DolphinView::slotDirectoryLoadingCompleted()
 
     Q_EMIT directoryLoadingCompleted();
 
+    applyDynamicView();
     updatePlaceholderLabel();
     updateWritableState();
 }
@@ -2135,6 +2190,18 @@ void DolphinView::applyViewProperties(const ViewProperties &props)
         Q_EMIT sortOrderChanged(sortOrder);
     }
 
+    const QByteArray groupRole = props.groupRole();
+    if (groupRole != m_model->groupRole()) {
+        m_model->setGroupRole(groupRole);
+        Q_EMIT groupRoleChanged(groupRole);
+    }
+
+    const Qt::SortOrder groupOrder = props.groupOrder();
+    if (groupOrder != m_model->groupOrder()) {
+        m_model->setGroupOrder(groupOrder);
+        Q_EMIT groupOrderChanged(groupOrder);
+    }
+
     const bool sortFoldersFirst = props.sortFoldersFirst();
     if (sortFoldersFirst != m_model->sortDirectoriesFirst()) {
         m_model->setSortDirectoriesFirst(sortFoldersFirst);
@@ -2184,7 +2251,7 @@ void DolphinView::applyViewProperties(const ViewProperties &props)
         } else {
             header->setAutomaticColumnResizing(true);
         }
-        header->setSidePadding(DetailsModeSettings::sidePadding());
+        header->setSidePadding(DetailsModeSettings::leftPadding(), DetailsModeSettings::rightPadding());
     }
 
     m_view->endTransaction();
@@ -2208,6 +2275,51 @@ void DolphinView::applyModeToView()
     }
 }
 
+void DolphinView::applyDynamicView()
+{
+    ViewProperties props(viewPropertiesUrl());
+    /* return early if:
+     * - dynamic view is not enabled
+     * - the current view mode is already Icon View
+     * - dynamic view has previously changed the view mode
+     */
+    if (!GeneralSettings::dynamicView() || m_mode == IconsView || props.dynamicViewPassed()) {
+        return;
+    }
+
+    uint imageAndVideoCount = 0;
+    uint checkedItems = 0;
+    const uint totalItems = itemsCount();
+    const KFileItemList itemList = items();
+    bool applyDynamicView = false;
+
+    for (const auto &file : itemList) {
+        ++checkedItems;
+        const QString type = file.mimetype().slice(0, 5);
+
+        if (type == "image" || type == "video") {
+            ++imageAndVideoCount;
+            // if 2/3 or more of the items are images/videos, dynamic view should be applied
+            applyDynamicView = imageAndVideoCount >= (totalItems * 2 / 3);
+            if (applyDynamicView) {
+                break;
+            }
+        } else if (checkedItems - imageAndVideoCount > totalItems / 3) {
+            // if more than a third of the checked files are not media files, return
+            return;
+        }
+    }
+
+    if (!applyDynamicView) {
+        return;
+    }
+
+    props.setAutoSaveEnabled(!GeneralSettings::globalViewProps());
+    props.setDynamicViewPassed(true);
+    props.setViewMode(IconsView);
+    applyViewProperties(props);
+}
+
 void DolphinView::pasteToUrl(const QUrl &url)
 {
     KIO::PasteJob *job = KIO::paste(QApplication::clipboard()->mimeData(), url);
@@ -2219,6 +2331,9 @@ void DolphinView::pasteToUrl(const QUrl &url)
     connect(job, &KIO::PasteJob::copyJobStarted, this, [this](const KIO::CopyJob *copyJob) {
         connect(copyJob, &KIO::CopyJob::copying, this, &DolphinView::slotItemCreatedFromJob);
         connect(copyJob, &KIO::CopyJob::moving, this, &DolphinView::slotItemCreatedFromJob);
+        connect(copyJob, &KIO::CopyJob::warning, this, [this](KJob *job, const QString & /*warning*/) {
+            Q_EMIT errorMessage(job->errorString(), job->error());
+        });
         connect(copyJob, &KIO::CopyJob::linking, this, [this](KIO::Job *job, const QString &src, const QUrl &dest) {
             Q_UNUSED(job)
             Q_UNUSED(src)
@@ -2280,6 +2395,22 @@ bool DolphinView::isFolderWritable() const
     return m_isFolderWritable;
 }
 
+int DolphinView::horizontalScrollBarHeight() const
+{
+    if (m_container && m_container->horizontalScrollBar() && m_container->horizontalScrollBar()->isVisible()) {
+        return m_container->horizontalScrollBar()->height();
+    }
+    return 0;
+}
+
+void DolphinView::setStatusBarOffset(int offset)
+{
+    KItemListView *view = m_container->controller()->view();
+    if (view) {
+        view->setStatusBarOffset(offset);
+    }
+}
+
 QUrl DolphinView::viewPropertiesUrl() const
 {
     if (m_viewPropertiesContext.isEmpty()) {
@@ -2419,7 +2550,7 @@ bool DolphinView::tryShowNameToolTip(QHelpEvent *event)
             const KFileItem item = m_model->fileItem(index.value());
             const QString text = item.text();
             const QPoint pos = mapToGlobal(event->pos());
-            QToolTip::showText(pos, text);
+            QToolTip::showText(pos, text, this);
             return true;
         }
     }