X-Git-Url: https://cloud.milkyroute.net/gitweb/dolphin.git/blobdiff_plain/603ec47b8b1221c8fdf5ff2eaaae0a6a9fcc4880..b258dcbbe9daebb4166d583dfa794c69e52f1516:/src/panels/terminal/terminalpanel.cpp diff --git a/src/panels/terminal/terminalpanel.cpp b/src/panels/terminal/terminalpanel.cpp index b45be621a..63cc15553 100644 --- a/src/panels/terminal/terminalpanel.cpp +++ b/src/panels/terminal/terminalpanel.cpp @@ -23,13 +23,16 @@ #include #include -#include -#include +#include +#include +#include #include #include #include +#include #include +#include #include TerminalPanel::TerminalPanel(QWidget* parent) : @@ -38,7 +41,9 @@ TerminalPanel::TerminalPanel(QWidget* parent) : m_mostLocalUrlJob(0), m_layout(0), m_terminal(0), - m_terminalWidget(0) + m_terminalWidget(0), + m_konsolePart(0), + m_konsolePartCurrentDirectory() { m_layout = new QVBoxLayout(this); m_layout->setMargin(0); @@ -50,15 +55,28 @@ TerminalPanel::~TerminalPanel() void TerminalPanel::terminalExited() { - emit hideTerminalPanel(); m_terminal = 0; + emit hideTerminalPanel(); } -void TerminalPanel::visibilityChanged(bool visible) +void TerminalPanel::dockVisibilityChanged() { - if (!visible && m_terminal && (m_terminal->foregroundProcessId() == -1)) { + // Only react when the DockWidget itself (not some parent) is hidden. This way we don't + // respond when e.g. Dolphin is minimized. + if (parentWidget() && parentWidget()->isHidden() && + m_terminal && (m_terminal->foregroundProcessId() == -1)) { + // 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(KUrl::fromPath("/")); + + // 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 = '/'; } } @@ -85,16 +103,22 @@ void TerminalPanel::showEvent(QShowEvent* event) if (!m_terminal) { m_clearTerminal = true; - KPluginFactory* factory = KPluginLoader("libkonsolepart").factory(); - KParts::ReadOnlyPart* part = factory ? (factory->create(this)) : 0; - if (part) { - connect(part, SIGNAL(destroyed(QObject*)), this, SLOT(terminalExited())); - m_terminalWidget = part->widget(); + KPluginFactory* factory = 0; + KService::Ptr service = KService::serviceByDesktopName("konsolepart"); + if (service) { + factory = KPluginLoader(service->library()).factory(); + } + m_konsolePart = factory ? (factory->create(this)) : 0; + if (m_konsolePart) { + connect(m_konsolePart, &KParts::ReadOnlyPart::destroyed, this, &TerminalPanel::terminalExited); + m_terminalWidget = m_konsolePart->widget(); m_layout->addWidget(m_terminalWidget); - m_terminal = qobject_cast(part); + m_terminal = qobject_cast(m_konsolePart); } } if (m_terminal) { + connect(m_konsolePart, SIGNAL(currentDirectoryChanged(QString)), + this, SLOT(slotKonsolePartCurrentDirectoryChanged(QString))); m_terminal->showShellInDir(url().toLocalFile()); changeDir(url()); m_terminalWidget->setFocus(); @@ -112,25 +136,36 @@ void TerminalPanel::changeDir(const KUrl& url) sendCdToTerminal(url.toLocalFile()); } else { m_mostLocalUrlJob = KIO::mostLocalUrl(url, KIO::HideProgressInfo); - m_mostLocalUrlJob->ui()->setWindow(this); - connect(m_mostLocalUrlJob, SIGNAL(result(KJob*)), this, SLOT(slotMostLocalUrlResult(KJob*))); + if (m_mostLocalUrlJob->ui()) { + KJobWidgets::setWindow(m_mostLocalUrlJob, this); + } + connect(m_mostLocalUrlJob, &KIO::StatJob::result, this, &TerminalPanel::slotMostLocalUrlResult); } } void TerminalPanel::sendCdToTerminal(const QString& dir) { + if (dir == m_konsolePartCurrentDirectory) { + m_clearTerminal = false; + return; + } + 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. - kill(m_terminal->terminalProcessId(), SIGINT); + const int processId = m_terminal->terminalProcessId(); + if (processId > 0) { + kill(processId, SIGINT); + } } - m_terminal->sendInput("cd " + KShell::quoteArg(dir) + '\n'); + m_terminal->sendInput(" cd " + KShell::quoteArg(dir) + '\n'); + m_konsolePartCurrentDirectory = dir; if (m_clearTerminal) { - m_terminal->sendInput("clear\n"); + m_terminal->sendInput(" clear\n"); m_clearTerminal = false; } } @@ -146,4 +181,17 @@ void TerminalPanel::slotMostLocalUrlResult(KJob* job) m_mostLocalUrlJob = 0; } -#include "terminalpanel.moc" +void TerminalPanel::slotKonsolePartCurrentDirectoryChanged(const QString& dir) +{ + m_konsolePartCurrentDirectory = dir; + + // Only change the view URL if 'dir' is different from the current view URL. + // Note that the current view URL could also be a symbolic link to 'dir' + // -> use QDir::canonicalPath() to check that. + const KUrl oldUrl(url()); + const KUrl newUrl(dir); + if (newUrl != oldUrl && dir != QDir(oldUrl.path()).canonicalPath()) { + emit changeUrl(newUrl); + } +} +