]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/dolphinmainwindow.cpp
DolphinMainWindow: show a banner when the user presses the shortcut of a disabled...
[dolphin.git] / src / dolphinmainwindow.cpp
index 56fc37e4c27d53f559265e7fe943dde632460be8..4cba465540cb4f8b43991e2682145ce2cf4bcbbe 100644 (file)
@@ -110,6 +110,7 @@ DolphinMainWindow::DolphinMainWindow()
     , m_remoteEncoding(nullptr)
     , m_settingsDialog()
     , m_bookmarkHandler(nullptr)
+    , m_disabledActionNotifier(nullptr)
     , m_lastHandleUrlOpenJob(nullptr)
     , m_terminalPanel(nullptr)
     , m_placesPanel(nullptr)
@@ -134,7 +135,9 @@ DolphinMainWindow::DolphinMainWindow()
 
     setStateConfigGroup("State");
 
-    new KColorSchemeManager(this);
+#if defined(Q_OS_WIN) || defined(Q_OS_MACOS)
+    new KColorSchemeManager(this); // Sets a sensible color scheme which fixes unreadable icons and text on Windows.
+#endif
 
     connect(&DolphinNewFileMenuObserver::instance(), &DolphinNewFileMenuObserver::errorMessage, this, &DolphinMainWindow::showErrorMessage);
 
@@ -176,6 +179,11 @@ DolphinMainWindow::DolphinMainWindow()
     m_remoteEncoding = new DolphinRemoteEncoding(this, m_actionHandler);
     connect(this, &DolphinMainWindow::urlChanged, m_remoteEncoding, &DolphinRemoteEncoding::slotAboutToOpenUrl);
 
+    m_disabledActionNotifier = new DisabledActionNotifier(this);
+    connect(m_disabledActionNotifier, &DisabledActionNotifier::disabledActionTriggered, this, [this](const QAction *, QString reason) {
+        m_activeViewContainer->showMessage(reason, DolphinViewContainer::Warning);
+    });
+
     setupDockWidgets();
 
     setupGUI(Save | Create | ToolBar);
@@ -851,6 +859,10 @@ void DolphinMainWindow::updatePasteAction()
     QAction *pasteAction = actionCollection()->action(KStandardAction::name(KStandardAction::Paste));
     QPair<bool, QString> pasteInfo = m_activeViewContainer->view()->pasteInfo();
     pasteAction->setEnabled(pasteInfo.first);
+    m_disabledActionNotifier->setDisabledReason(pasteAction,
+                                                m_activeViewContainer->rootItem().isWritable()
+                                                    ? i18nc("@info", "Could not paste: The clipboard is empty.")
+                                                    : i18nc("@info", "Could not paste: You do not have permission to write into this folder."));
     pasteAction->setText(pasteInfo.second);
 }
 
@@ -1381,6 +1393,11 @@ void DolphinMainWindow::slotWriteStateChanged(bool isFolderWritable)
     // trash:/ is writable but we don't want to create new items in it.
     // TODO: remove the trash check once https://phabricator.kde.org/T8234 is implemented
     newFileMenu()->setEnabled(isFolderWritable && m_activeViewContainer->url().scheme() != QLatin1String("trash"));
+    // When the menu is disabled, actions in it are disabled later in the event loop, and we need to set the disabled reason after that.
+    QTimer::singleShot(0, this, [this]() {
+        m_disabledActionNotifier->setDisabledReason(actionCollection()->action(QStringLiteral("create_dir")),
+                                                    i18nc("@info", "Could not create new folder: You do not have permission to create items in this folder."));
+    });
 }
 
 void DolphinMainWindow::openContextMenu(const QPoint &pos, const KFileItem &item, const KFileItemList &selectedItems, const QUrl &url)
@@ -2414,16 +2431,43 @@ void DolphinMainWindow::updateFileAndEditActions()
         const bool enableMoveToTrash = capabilitiesSource.isLocal() && capabilitiesSource.supportsMoving();
 
         renameAction->setEnabled(capabilitiesSource.supportsMoving());
-        moveToTrashAction->setEnabled(enableMoveToTrash);
+        m_disabledActionNotifier->setDisabledReason(renameAction,
+                                                    i18nc("@info", "Could not rename: You do not have permission to rename items in this folder."));
         deleteAction->setEnabled(capabilitiesSource.supportsDeleting());
-        deleteWithTrashShortcut->setEnabled(capabilitiesSource.supportsDeleting() && !enableMoveToTrash);
+        m_disabledActionNotifier->setDisabledReason(deleteAction,
+                                                    i18nc("@info", "Could not delete: You do not have permission to remove items from this folder."));
         cutAction->setEnabled(capabilitiesSource.supportsMoving());
+        m_disabledActionNotifier->setDisabledReason(cutAction, i18nc("@info", "Could not cut: You do not have permission to move items from this folder."));
         copyLocation->setEnabled(list.length() == 1);
         showTarget->setEnabled(list.length() == 1 && list.at(0).isLink());
         duplicateAction->setEnabled(capabilitiesSource.supportsWriting());
+        m_disabledActionNotifier->setDisabledReason(duplicateAction,
+                                                    i18nc("@info", "Could not duplicate here: You do not have permission to create items in this folder."));
+
+        if (enableMoveToTrash) {
+            moveToTrashAction->setEnabled(true);
+            deleteWithTrashShortcut->setEnabled(false);
+            m_disabledActionNotifier->clearDisabledReason(deleteWithTrashShortcut);
+        } else {
+            moveToTrashAction->setEnabled(false);
+            deleteWithTrashShortcut->setEnabled(capabilitiesSource.supportsDeleting());
+            m_disabledActionNotifier->setDisabledReason(deleteWithTrashShortcut,
+                                                        i18nc("@info", "Could not delete: You do not have permission to remove items from this folder."));
+        }
     }
 
-    if (m_tabWidget->currentTabPage()->splitViewEnabled() && !list.isEmpty()) {
+    if (!m_tabWidget->currentTabPage()->splitViewEnabled()) {
+        // No need to set the disabled reason here, as it's obvious to the user that the reason is the split view being disabled.
+        copyToOtherViewAction->setEnabled(false);
+        m_disabledActionNotifier->clearDisabledReason(copyToOtherViewAction);
+        moveToOtherViewAction->setEnabled(false);
+        m_disabledActionNotifier->clearDisabledReason(moveToOtherViewAction);
+    } else if (list.isEmpty()) {
+        copyToOtherViewAction->setEnabled(false);
+        m_disabledActionNotifier->setDisabledReason(copyToOtherViewAction, i18nc("@info", "Could not copy to other view: No files selected."));
+        moveToOtherViewAction->setEnabled(false);
+        m_disabledActionNotifier->setDisabledReason(moveToOtherViewAction, i18nc("@info", "Could not move to other view: No files selected."));
+    } else {
         DolphinTabPage *tabPage = m_tabWidget->currentTabPage();
         KFileItem capabilitiesDestination;
 
@@ -2438,12 +2482,29 @@ void DolphinMainWindow::updateFileAndEditActions()
             return item.url().adjusted(QUrl::RemoveFilename | QUrl::StripTrailingSlash) != destUrl;
         });
 
-        copyToOtherViewAction->setEnabled(capabilitiesDestination.isWritable() && allNotTargetOrigin);
-        moveToOtherViewAction->setEnabled((list.isEmpty() || capabilitiesSource.supportsMoving()) && capabilitiesDestination.isWritable()
-                                          && allNotTargetOrigin);
-    } else {
-        copyToOtherViewAction->setEnabled(false);
-        moveToOtherViewAction->setEnabled(false);
+        if (!allNotTargetOrigin) {
+            copyToOtherViewAction->setEnabled(false);
+            m_disabledActionNotifier->setDisabledReason(copyToOtherViewAction,
+                                                        i18nc("@info", "Could not copy to other view: The other view already contains these items."));
+            moveToOtherViewAction->setEnabled(false);
+            m_disabledActionNotifier->setDisabledReason(moveToOtherViewAction,
+                                                        i18nc("@info", "Could not move to other view: The other view already contains these items."));
+        } else if (!capabilitiesDestination.isWritable()) {
+            copyToOtherViewAction->setEnabled(false);
+            m_disabledActionNotifier->setDisabledReason(
+                copyToOtherViewAction,
+                i18nc("@info", "Could not copy to other view: You do not have permission to write into the destination folder."));
+            moveToOtherViewAction->setEnabled(false);
+            m_disabledActionNotifier->setDisabledReason(
+                moveToOtherViewAction,
+                i18nc("@info", "Could not move to other view: You do not have permission to write into the destination folder."));
+        } else {
+            copyToOtherViewAction->setEnabled(true);
+            moveToOtherViewAction->setEnabled(capabilitiesSource.supportsMoving());
+            m_disabledActionNotifier->setDisabledReason(
+                moveToOtherViewAction,
+                i18nc("@info", "Could not move to other view: You do not have permission to move items from this folder."));
+        }
     }
 }