]> cloud.milkyroute.net Git - dolphin.git/blobdiff - src/panels/terminal/terminalpanel.cpp
Switch to C++20
[dolphin.git] / src / panels / terminal / terminalpanel.cpp
index ac395d09df601350740532a0f811f988535feea9..92ba18bf513cee88a21b1c959e45f18576b248a5 100644 (file)
@@ -8,7 +8,7 @@
 
 #include <KActionCollection>
 #include <KIO/DesktopExecParser>
-#include <KIO/Job>
+#include <KIO/StatJob>
 #include <KJobWidgets>
 #include <KLocalizedString>
 #include <KMessageWidget>
@@ -47,6 +47,11 @@ TerminalPanel::TerminalPanel(QWidget *parent)
 
 TerminalPanel::~TerminalPanel()
 {
+    if (m_konsolePart) {
+        // Avoid when QObject cleanup, which comes after our destructor, deletes the konsolePart
+        // and subsequently calls back into our slot when the destructor has already run.
+        disconnect(m_konsolePart, &KParts::ReadOnlyPart::destroyed, this, &TerminalPanel::terminalExited);
+    }
 }
 
 void TerminalPanel::goHome()
@@ -65,6 +70,7 @@ bool TerminalPanel::currentWorkingDirectoryIsChildOf(const QString &path) const
 void TerminalPanel::terminalExited()
 {
     m_terminal = nullptr;
+    m_konsolePart = nullptr;
     Q_EMIT hideTerminalPanel();
 }
 
@@ -77,18 +83,22 @@ void TerminalPanel::dockVisibilityChanged()
 {
     // Only react when the DockWidget itself (not some parent) is hidden. This way we don't
     // respond when e.g. Dolphin is minimized.
-    if (isHiddenInVisibleWindow() && m_terminal && !hasProgramRunning()) {
-        // Make sure that the following "cd /" command will not affect the view.
-        disconnect(m_konsolePart, SIGNAL(currentDirectoryChanged(QString)), this, SLOT(slotKonsolePartCurrentDirectoryChanged(QString)));
-
-        // Make sure this terminal does not prevent unmounting any removable drives
-        changeDir(QUrl::fromLocalFile(QStringLiteral("/")));
-
-        // Because we have disconnected from the part's currentDirectoryChanged()
-        // signal, we have to update m_konsolePartCurrentDirectory manually. If this
-        // was not done, showing the panel again might not set the part's working
-        // directory correctly.
-        m_konsolePartCurrentDirectory = '/';
+    if (isHiddenInVisibleWindow()) {
+        if (m_konsolePartMissingMessage) {
+            m_konsolePartMissingMessage->hide();
+        } else if (m_terminal && !hasProgramRunning()) {
+            // Make sure that the following "cd /" command will not affect the view.
+            disconnect(m_konsolePart, SIGNAL(currentDirectoryChanged(QString)), this, SLOT(slotKonsolePartCurrentDirectoryChanged(QString)));
+
+            // Make sure this terminal does not prevent unmounting any removable drives
+            changeDir(QUrl::fromLocalFile(QStringLiteral("/")));
+
+            // Because we have disconnected from the part's currentDirectoryChanged()
+            // signal, we have to update m_konsolePartCurrentDirectory manually. If this
+            // was not done, showing the panel again might not set the part's working
+            // directory correctly.
+            m_konsolePartCurrentDirectory = '/';
+        }
     }
 }
 
@@ -168,25 +178,27 @@ void TerminalPanel::showEvent(QShowEvent *event)
                 });
             }
 
-        } else if (!m_konsolePartMissingMessage) {
-            const auto konsoleInstallUrl = QUrl("appstream://org.kde.konsole.desktop");
-            const auto konsoleNotInstalledText = i18n(
-                "Terminal cannot be shown because Konsole is not installed. "
-                "Please install it and then reopen the panel.");
-            m_konsolePartMissingMessage = new KMessageWidget(konsoleNotInstalledText, this);
-            m_konsolePartMissingMessage->setCloseButtonVisible(false);
-            m_konsolePartMissingMessage->hide();
-            if (KIO::DesktopExecParser::hasSchemeHandler(konsoleInstallUrl)) {
-                auto installKonsoleAction = new QAction(i18n("Install Konsole"), this);
-                connect(installKonsoleAction, &QAction::triggered, [konsoleInstallUrl]() {
-                    QDesktopServices::openUrl(konsoleInstallUrl);
-                });
-                m_konsolePartMissingMessage->addAction(installKonsoleAction);
-            }
-            m_layout->addWidget(m_konsolePartMissingMessage);
-            m_layout->addStretch();
-            QTimer::singleShot(0, m_konsolePartMissingMessage, &KMessageWidget::animatedShow);
         } else {
+            if (!m_konsolePartMissingMessage) {
+                const auto konsoleInstallUrl = QUrl("appstream://org.kde.konsole.desktop");
+                const auto konsoleNotInstalledText = i18n(
+                    "Terminal cannot be shown because Konsole is not installed. "
+                    "Please install it and then reopen the panel.");
+                m_konsolePartMissingMessage = new KMessageWidget(konsoleNotInstalledText, this);
+                m_konsolePartMissingMessage->setPosition(KMessageWidget::Footer);
+                m_konsolePartMissingMessage->setCloseButtonVisible(false);
+                m_konsolePartMissingMessage->hide();
+                if (KIO::DesktopExecParser::hasSchemeHandler(konsoleInstallUrl)) {
+                    auto installKonsoleAction = new QAction(i18n("Install Konsole"), this);
+                    connect(installKonsoleAction, &QAction::triggered, [konsoleInstallUrl]() {
+                        QDesktopServices::openUrl(konsoleInstallUrl);
+                    });
+                    m_konsolePartMissingMessage->addAction(installKonsoleAction);
+                }
+                m_layout->addWidget(m_konsolePartMissingMessage);
+                m_layout->setSizeConstraint(QLayout::SetMaximumSize);
+            }
+
             m_konsolePartMissingMessage->animatedShow();
         }
     }
@@ -207,6 +219,10 @@ void TerminalPanel::changeDir(const QUrl &url)
     delete m_mostLocalUrlJob;
     m_mostLocalUrlJob = nullptr;
 
+    if (url.isEmpty()) {
+        return;
+    }
+
     if (url.isLocalFile()) {
         sendCdToTerminal(url.toLocalFile());
         return;
@@ -262,7 +278,7 @@ void TerminalPanel::sendCdToTerminalKIOFuse(const QUrl &url)
     // 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) {
+    QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [=, this](QDBusPendingCallWatcher *watcher) {
         watcher->deleteLater();
         if (!reply.isError()) {
             // Successfully mounted, point to the KIOFuse equivalent path.
@@ -310,7 +326,7 @@ void TerminalPanel::slotKonsolePartCurrentDirectoryChanged(const QString &dir)
 
     auto reply = m_kiofuseInterface.remoteUrl(m_konsolePartCurrentDirectory);
     QDBusPendingCallWatcher *watcher = new QDBusPendingCallWatcher(reply, this);
-    QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [=](QDBusPendingCallWatcher *watcher) {
+    QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [=, this](QDBusPendingCallWatcher *watcher) {
         watcher->deleteLater();
         if (reply.isError()) {
             // KIOFuse errored out... just show the normal URL