From f2885d1ac237dcf1a3536e7a619275158fe2825d Mon Sep 17 00:00:00 2001 From: Peter Penz Date: Sun, 14 Mar 2010 16:21:35 +0000 Subject: [PATCH] Fix issue that the current terminal line does not get cleared before sending a cd command. The terminal interface does not provide an API for this, so as workaround backspaces are send. Not nice, but as the issue can lead to data loss, this solution is better than having nothing. BUG: 161637 svn path=/trunk/KDE/kdebase/apps/; revision=1103207 --- src/panels/terminal/terminalpanel.cpp | 48 +++++++++++++++++++-------- src/panels/terminal/terminalpanel.h | 13 ++++++-- 2 files changed, 45 insertions(+), 16 deletions(-) diff --git a/src/panels/terminal/terminalpanel.cpp b/src/panels/terminal/terminalpanel.cpp index 3b77cd92e..856eed4c0 100644 --- a/src/panels/terminal/terminalpanel.cpp +++ b/src/panels/terminal/terminalpanel.cpp @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2007 by Peter Penz * + * 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 * @@ -29,10 +29,10 @@ #include #include -#include - TerminalPanel::TerminalPanel(QWidget* parent) : Panel(parent), + m_clearTerminal(true), + m_mostLocalUrlJob(0), m_layout(0), m_terminal(0), m_terminalWidget(0) @@ -64,7 +64,7 @@ void TerminalPanel::setUrl(const KUrl& url) && (m_terminal->foregroundProcessId() == -1) && isVisible(); if (sendInput) { - cdUrl(url); + changeDir(url); } } @@ -82,6 +82,7 @@ void TerminalPanel::showEvent(QShowEvent* event) } if (m_terminal == 0) { + m_clearTerminal = true; KPluginFactory* factory = KPluginLoader("libkonsolepart").factory(); KParts::ReadOnlyPart* part = factory ? (factory->create(this)) : 0; if (part != 0) { @@ -93,28 +94,47 @@ void TerminalPanel::showEvent(QShowEvent* event) } if (m_terminal != 0) { m_terminal->showShellInDir(url().toLocalFile()); - cdUrl(url()); - m_terminal->sendInput("clear\n"); // TODO do clear after slotMostLocalUrlResult is called, for remote dirs? + changeDir(url()); m_terminalWidget->setFocus(); } Panel::showEvent(event); } -void TerminalPanel::cdUrl(const KUrl& url) +void TerminalPanel::changeDir(const KUrl& url) { + delete m_mostLocalUrlJob; + m_mostLocalUrlJob = 0; + if (url.isLocalFile()) { - cdDirectory(url.toLocalFile()); + sendCdToTerminal(url.toLocalFile()); } else { - KIO::StatJob* job = KIO::mostLocalUrl(url, KIO::HideProgressInfo); - job->ui()->setWindow(this); - connect(job, SIGNAL(result(KJob*)), this, SLOT(slotMostLocalUrlResult(KJob*))); + m_mostLocalUrlJob = KIO::mostLocalUrl(url, KIO::HideProgressInfo); + m_mostLocalUrlJob->ui()->setWindow(this); + connect(m_mostLocalUrlJob, SIGNAL(result(KJob*)), this, SLOT(slotMostLocalUrlResult(KJob*))); } } -void TerminalPanel::cdDirectory(const QString& dir) +void TerminalPanel::sendCdToTerminal(const QString& dir) { + 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 backspaces are send... + QString clearLine; + for (int i = 0; i < 256; ++i) { + clearLine.append(QChar(8)); + } + m_terminal->sendInput(clearLine); + } + m_terminal->sendInput("cd " + KShell::quoteArg(dir) + '\n'); + + if (m_clearTerminal) { + m_terminal->sendInput("clear\n"); + m_clearTerminal = false; + } } void TerminalPanel::slotMostLocalUrlResult(KJob* job) @@ -122,8 +142,10 @@ void TerminalPanel::slotMostLocalUrlResult(KJob* job) KIO::StatJob* statJob = static_cast(job); const KUrl url = statJob->mostLocalUrl(); if (url.isLocalFile()) { - cdDirectory(url.toLocalFile()); + sendCdToTerminal(url.toLocalFile()); } + + m_mostLocalUrlJob = 0; } #include "terminalpanel.moc" diff --git a/src/panels/terminal/terminalpanel.h b/src/panels/terminal/terminalpanel.h index 7b08483f6..36114995e 100644 --- a/src/panels/terminal/terminalpanel.h +++ b/src/panels/terminal/terminalpanel.h @@ -1,5 +1,5 @@ /*************************************************************************** - * Copyright (C) 2007 by Peter Penz * + * 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 * @@ -26,6 +26,10 @@ class TerminalInterfaceV2; class QVBoxLayout; class QWidget; +namespace KIO { + class StatJob; +}; + /** * @brief Shows the terminal which is synchronized with the URL of the * active view. @@ -57,10 +61,13 @@ private slots: void slotMostLocalUrlResult(KJob* job); private: - void cdUrl(const KUrl& url); - void cdDirectory(const QString& path); + void changeDir(const KUrl& url); + void sendCdToTerminal(const QString& path); private: + bool m_clearTerminal; + KIO::StatJob* m_mostLocalUrlJob; + QVBoxLayout* m_layout; TerminalInterfaceV2* m_terminal; QWidget* m_terminalWidget; -- 2.47.3