X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/fa3f3a475dd5e522acd40b7a31ec3aeb87400c69..e70e12e3bdf3ce4e9cca4c8f003655ea10b21d7e:/src/panels/terminal/terminalpanel.cpp diff --git a/src/panels/terminal/terminalpanel.cpp b/src/panels/terminal/terminalpanel.cpp index b0aff9a77..d87ae3b1e 100644 --- a/src/panels/terminal/terminalpanel.cpp +++ b/src/panels/terminal/terminalpanel.cpp @@ -1,25 +1,12 @@ -/*************************************************************************** - * Copyright (C) 2007-2010 by Peter Penz * - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - * This program is distributed in the hope that it will be useful, * - * but WITHOUT ANY WARRANTY; without even the implied warranty of * - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * - * GNU General Public License for more details. * - * * - * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * - ***************************************************************************/ +/* + * SPDX-FileCopyrightText: 2007-2010 Peter Penz + * + * SPDX-License-Identifier: GPL-2.0-or-later + */ #include "terminalpanel.h" -#include "kiofuse_interface.h" +#include #include #include #include @@ -29,9 +16,10 @@ #include #include #include -#include -#include +#include #include +#include +#include #include #include @@ -81,7 +69,7 @@ QString TerminalPanel::currentWorkingDirectory() void TerminalPanel::terminalExited() { m_terminal = nullptr; - emit hideTerminalPanel(); + Q_EMIT hideTerminalPanel(); } bool TerminalPanel::isHiddenInVisibleWindow() const @@ -115,6 +103,21 @@ QString TerminalPanel::runningProgramName() const return m_terminal ? m_terminal->foregroundProcessName() : QString(); } +KActionCollection *TerminalPanel::actionCollection() +{ + // m_terminal is the only reference reset to nullptr in case the terminal is + // closed again + if (m_terminal && m_konsolePart && m_terminalWidget) { + const auto guiClients = m_konsolePart->childClients(); + for (auto *client : guiClients) { + if (client->actionCollection()->associatedWidgets().contains(m_terminalWidget)) { + return client->actionCollection(); + } + } + } + return nullptr; +} + bool TerminalPanel::hasProgramRunning() const { return m_terminal && (m_terminal->foregroundProcessId() != -1); @@ -143,11 +146,7 @@ void TerminalPanel::showEvent(QShowEvent* event) if (!m_terminal) { m_clearTerminal = true; - KPluginFactory* factory = nullptr; - KService::Ptr service = KService::serviceByDesktopName(QStringLiteral("konsolepart")); - if (service) { - factory = KPluginLoader(service->library()).factory(); - } + KPluginFactory *factory = KPluginFactory::loadFactory(KPluginMetaData(QStringLiteral("konsolepart"))).plugin; m_konsolePart = factory ? (factory->create(this)) : nullptr; if (m_konsolePart) { connect(m_konsolePart, &KParts::ReadOnlyPart::destroyed, this, &TerminalPanel::terminalExited); @@ -158,6 +157,23 @@ void TerminalPanel::showEvent(QShowEvent* event) m_layout->removeWidget(m_konsolePartMissingMessage); } m_terminal = qobject_cast(m_konsolePart); + + // needed to collect the correct KonsolePart actionCollection + // namely the one of the single inner terminal and not the outer KonsolePart + if (!m_konsolePart->factory() && m_terminalWidget) { + if (!m_konsolePart->clientBuilder()) { + m_konsolePart->setClientBuilder(new KXMLGUIBuilder(m_terminalWidget)); + } + + auto factory = new KXMLGUIFactory(m_konsolePart->clientBuilder(), this); + factory->addClient(m_konsolePart); + + // Prevents the KXMLGui warning about removing the client + connect(m_terminalWidget, &QObject::destroyed, this, [factory, this] { + factory->removeClient(m_konsolePart); + }); + } + } 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. " @@ -199,18 +215,28 @@ void TerminalPanel::changeDir(const QUrl& url) if (url.isLocalFile()) { sendCdToTerminal(url.toLocalFile()); - } else { + return; + } + + // Try stat'ing the url; note that mostLocalUrl only works with ":local" protocols + if (KProtocolInfo::protocolClass(url.scheme()) == QLatin1String(":local")) { m_mostLocalUrlJob = KIO::mostLocalUrl(url, KIO::HideProgressInfo); if (m_mostLocalUrlJob->uiDelegate()) { KJobWidgets::setWindow(m_mostLocalUrlJob, this); } connect(m_mostLocalUrlJob, &KIO::StatJob::result, this, &TerminalPanel::slotMostLocalUrlResult); + return; } + + // Last chance, try KIOFuse + sendCdToTerminalKIOFuse(url); } void TerminalPanel::sendCdToTerminal(const QString& dir, HistoryPolicy addToHistory) { - if (dir == m_konsolePartCurrentDirectory) { + if (dir == m_konsolePartCurrentDirectory // We are already there + && m_sendCdToTerminalHistory.isEmpty() // …and that is not because the terminal couldn't keep up + ) { m_clearTerminal = false; return; } @@ -228,8 +254,6 @@ void TerminalPanel::sendCdToTerminal(const QString& dir, HistoryPolicy addToHist } #endif - m_terminal->sendInput(" cd " + KShell::quoteArg(dir) + '\n'); - // We want to ignore the currentDirectoryChanged(QString) signal, which we will receive after // the directory change, because this directory change is not caused by a "cd" command that the // user entered in the panel. Therefore, we have to remember 'dir'. Note that it could also be @@ -237,12 +261,29 @@ void TerminalPanel::sendCdToTerminal(const QString& dir, HistoryPolicy addToHist if (addToHistory == HistoryPolicy::AddToHistory) m_sendCdToTerminalHistory.enqueue(QDir(dir).canonicalPath()); + m_terminal->sendInput(" cd " + KShell::quoteArg(dir) + '\n'); + if (m_clearTerminal) { m_terminal->sendInput(QStringLiteral(" clear\n")); m_clearTerminal = false; } } +void TerminalPanel::sendCdToTerminalKIOFuse(const QUrl &url) { + // 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()); + } + }); +} + void TerminalPanel::slotMostLocalUrlResult(KJob* job) { KIO::StatJob* statJob = static_cast(job); @@ -250,18 +291,7 @@ void TerminalPanel::slotMostLocalUrlResult(KJob* job) 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()); - } - }); + sendCdToTerminalKIOFuse(url); } m_mostLocalUrlJob = nullptr; @@ -287,7 +317,7 @@ void TerminalPanel::slotKonsolePartCurrentDirectoryChanged(const QString& dir) 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); + Q_EMIT changeUrl(url); return; } @@ -297,16 +327,20 @@ void TerminalPanel::slotKonsolePartCurrentDirectoryChanged(const QString& dir) watcher->deleteLater(); if (reply.isError()) { // KIOFuse errored out... just show the normal URL - emit changeUrl(url); + Q_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())); + Q_EMIT changeUrl(QUrl::fromUserInput(reply.value())); } }); } bool TerminalPanel::terminalHasFocus() const { - return m_terminalWidget->hasFocus(); + if (m_terminalWidget) { + return m_terminalWidget->hasFocus(); + } + + return hasFocus(); }