X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/4e40fe810d324e69eeb824e40011e509e6676aaf..954e8c47906c12edaaf6e6aebdd41516eceb0d44:/src/panels/terminal/terminalpanel.cpp diff --git a/src/panels/terminal/terminalpanel.cpp b/src/panels/terminal/terminalpanel.cpp index 849d3f8c9..131d16630 100644 --- a/src/panels/terminal/terminalpanel.cpp +++ b/src/panels/terminal/terminalpanel.cpp @@ -1,38 +1,32 @@ -/*************************************************************************** - * 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 -#include -#include -#include +#include #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include #include +#include #include +#include #include TerminalPanel::TerminalPanel(QWidget* parent) : @@ -42,12 +36,16 @@ TerminalPanel::TerminalPanel(QWidget* parent) : m_layout(nullptr), m_terminal(nullptr), m_terminalWidget(nullptr), + m_konsolePartMissingMessage(nullptr), m_konsolePart(nullptr), m_konsolePartCurrentDirectory(), - m_sendCdToTerminalHistory() + m_sendCdToTerminalHistory(), + m_kiofuseInterface(QStringLiteral("org.kde.KIOFuse"), + QStringLiteral("/org/kde/KIOFuse"), + QDBusConnection::sessionBus()) { m_layout = new QVBoxLayout(this); - m_layout->setMargin(0); + m_layout->setContentsMargins(0, 0, 0, 0); } TerminalPanel::~TerminalPanel() @@ -73,19 +71,17 @@ void TerminalPanel::terminalExited() emit hideTerminalPanel(); } -bool TerminalPanel::isHiddenInVisibleWindow() +bool TerminalPanel::isHiddenInVisibleWindow() const { return parentWidget() - && parentWidget()->isHidden() - && m_terminal - && (m_terminal->foregroundProcessId() == -1); + && parentWidget()->isHidden(); } 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()) { + 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))); @@ -101,13 +97,23 @@ void TerminalPanel::dockVisibilityChanged() } } +QString TerminalPanel::runningProgramName() const +{ + return m_terminal ? m_terminal->foregroundProcessName() : QString(); +} + +bool TerminalPanel::hasProgramRunning() const +{ + return m_terminal && (m_terminal->foregroundProcessId() != -1); +} + bool TerminalPanel::urlChanged() { if (!url().isValid()) { return false; } - const bool sendInput = m_terminal && (m_terminal->foregroundProcessId() == -1) && isVisible(); + const bool sendInput = m_terminal && !hasProgramRunning() && isVisible(); if (sendInput) { changeDir(url()); } @@ -133,13 +139,38 @@ void TerminalPanel::showEvent(QShowEvent* event) if (m_konsolePart) { connect(m_konsolePart, &KParts::ReadOnlyPart::destroyed, this, &TerminalPanel::terminalExited); m_terminalWidget = m_konsolePart->widget(); + setFocusProxy(m_terminalWidget); m_layout->addWidget(m_terminalWidget); + if (m_konsolePartMissingMessage) { + m_layout->removeWidget(m_konsolePartMissingMessage); + } m_terminal = qobject_cast(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. " + "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 { + m_konsolePartMissingMessage->animatedShow(); } } if (m_terminal) { m_terminal->showShellInDir(url().toLocalFile()); - changeDir(url()); + if(!hasProgramRunning()) { + changeDir(url()); + } m_terminalWidget->setFocus(); connect(m_konsolePart, SIGNAL(currentDirectoryChanged(QString)), this, SLOT(slotKonsolePartCurrentDirectoryChanged(QString))); @@ -171,16 +202,18 @@ void TerminalPanel::sendCdToTerminal(const QString& dir, HistoryPolicy addToHist return; } +#ifndef Q_OS_WIN if (!m_clearTerminal) { // The TerminalV2 interface does not provide a way to delete the // current line before sending a new input. This is mandatory, // otherwise sending a 'cd x' to a existing 'rm -rf *' might - // result in data loss. As workaround SIGINT is send. + // result in data loss. As workaround SIGINT is sent. const int processId = m_terminal->terminalProcessId(); if (processId > 0) { kill(processId, SIGINT); } } +#endif m_terminal->sendInput(" cd " + KShell::quoteArg(dir) + '\n'); @@ -203,6 +236,19 @@ void TerminalPanel::slotMostLocalUrlResult(KJob* job) const QUrl url = statJob->mostLocalUrl(); 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()); + } + }); } m_mostLocalUrlJob = nullptr; @@ -220,6 +266,38 @@ void TerminalPanel::slotKonsolePartCurrentDirectoryChanged(const QString& dir) } } + // User may potentially be browsing inside a KIOFuse mount. + // If so lets try and change the DolphinView to point to the remote URL equivalent. + // instead of into the KIOFuse mount itself (which can cause performance issues!) const QUrl url(QUrl::fromLocalFile(dir)); - emit changeUrl(url); + + 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); + return; + } + + auto reply = m_kiofuseInterface.remoteUrl(m_konsolePartCurrentDirectory); + QDBusPendingCallWatcher * watcher = new QDBusPendingCallWatcher(reply, this); + QObject::connect(watcher, &QDBusPendingCallWatcher::finished, this, [=] (QDBusPendingCallWatcher* watcher) { + watcher->deleteLater(); + if (reply.isError()) { + // KIOFuse errored out... just show the normal URL + 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())); + } + }); +} + +bool TerminalPanel::terminalHasFocus() const +{ + if (m_terminalWidget) { + return m_terminalWidget->hasFocus(); + } + + return hasFocus(); }