diff options
author | Christian Kandeler <christian.kandeler@nokia.com> | 2011-07-22 11:21:20 +0200 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@nokia.com> | 2011-07-22 11:39:10 +0200 |
commit | 4bf65fe47b266b88c4587f504c2947e35e0f9695 (patch) | |
tree | e2573b8a8e145e01ce05f561073a4f3852d788c7 | |
parent | a1748e4bbed551e73a3f0cc7809bd81c5a013591 (diff) | |
download | qt-creator-4bf65fe47b266b88c4587f504c2947e35e0f9695.tar.gz |
RemoteLinux: Split up "remote processes" functionality...
... into generic and Maemo-specific parts.
Change-Id: If1f3664ed7320d3e51655cc092cea36be1a9fe66
Reviewed-on: http://codereview.qt.nokia.com/2026
Reviewed-by: Christian Kandeler <christian.kandeler@nokia.com>
15 files changed, 661 insertions, 490 deletions
diff --git a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp index 334cb4db94..bca87340b1 100644 --- a/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp +++ b/src/plugins/remotelinux/genericlinuxdeviceconfigurationfactory.cpp @@ -33,8 +33,9 @@ #include "genericlinuxdeviceconfigurationwizard.h" #include "linuxdevicetestdialog.h" -#include "maemoremoteprocessesdialog.h" #include "publickeydeploymentdialog.h" +#include "remotelinuxprocessesdialog.h" +#include "remotelinuxprocesslist.h" #include "remotelinux_constants.h" #include <utils/qtcassert.h> @@ -93,12 +94,12 @@ QDialog *GenericLinuxDeviceConfigurationFactory::createDeviceAction(const QStrin { Q_ASSERT(supportedDeviceActionIds().contains(actionId)); - if (actionId == QLatin1String(Constants::GenericTestDeviceActionId)) { - return new LinuxDeviceTestDialog(deviceConfig, new GenericLinuxDeviceTester(parent), + if (actionId == QLatin1String(Constants::GenericTestDeviceActionId)) + return new LinuxDeviceTestDialog(deviceConfig, new GenericLinuxDeviceTester, parent); + if (actionId == QLatin1String(Constants::GenericRemoteProcessesActionId)) { + return new RemoteLinuxProcessesDialog(new GenericRemoteLinuxProcessList(deviceConfig), parent); } - if (actionId == QLatin1String(Constants::GenericRemoteProcessesActionId)) - return new MaemoRemoteProcessesDialog(deviceConfig, parent); if (actionId == QLatin1String(Constants::GenericDeployKeyToDeviceActionId)) return new PublicKeyDeploymentDialog(deviceConfig, parent); return 0; // Can't happen. diff --git a/src/plugins/remotelinux/linuxdevicetestdialog.cpp b/src/plugins/remotelinux/linuxdevicetestdialog.cpp index 2639a9ce7e..f0e89306f5 100644 --- a/src/plugins/remotelinux/linuxdevicetestdialog.cpp +++ b/src/plugins/remotelinux/linuxdevicetestdialog.cpp @@ -35,56 +35,70 @@ #include <QtGui/QPushButton> namespace RemoteLinux { +namespace Internal { +class LinuxDeviceTestDialogPrivate { +public: + LinuxDeviceTestDialogPrivate(AbstractLinuxDeviceTester *tester) + : deviceTester(tester), finished(false) + { + } + + Ui::LinuxDeviceTestDialog ui; + AbstractLinuxDeviceTester * const deviceTester; + bool finished; +}; + +} // namespace Internal + +using namespace Internal; LinuxDeviceTestDialog::LinuxDeviceTestDialog(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, AbstractLinuxDeviceTester *deviceTester, QWidget *parent) - : QDialog(parent), - m_ui(new Ui::LinuxDeviceTestDialog), - m_deviceTester(deviceTester), - m_finished(false) + : QDialog(parent), m_d(new LinuxDeviceTestDialogPrivate(deviceTester)) { - m_ui->setupUi(this); + m_d->ui.setupUi(this); - connect(m_deviceTester, SIGNAL(progressMessage(QString)), SLOT(handleProgressMessage(QString))); - connect(m_deviceTester, SIGNAL(errorMessage(QString)), SLOT(handleErrorMessage(QString))); - connect(m_deviceTester, SIGNAL(finished(RemoteLinux::AbstractLinuxDeviceTester::TestResult)), + m_d->deviceTester->setParent(this); + connect(m_d->deviceTester, SIGNAL(progressMessage(QString)), SLOT(handleProgressMessage(QString))); + connect(m_d->deviceTester, SIGNAL(errorMessage(QString)), SLOT(handleErrorMessage(QString))); + connect(m_d->deviceTester, SIGNAL(finished(RemoteLinux::AbstractLinuxDeviceTester::TestResult)), SLOT(handleTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult))); - m_deviceTester->testDevice(deviceConfiguration); + m_d->deviceTester->testDevice(deviceConfiguration); } LinuxDeviceTestDialog::~LinuxDeviceTestDialog() { - delete m_ui; + delete m_d; } void LinuxDeviceTestDialog::reject() { - if (!m_finished) - m_deviceTester->stopTest(); + if (!m_d->finished) + m_d->deviceTester->stopTest(); QDialog::reject(); } void LinuxDeviceTestDialog::handleProgressMessage(const QString &message) { - m_ui->textEdit->appendPlainText(message); + m_d->ui.textEdit->appendPlainText(message); } void LinuxDeviceTestDialog::handleErrorMessage(const QString &message) { - m_ui->textEdit->appendHtml(QLatin1String("<font color=\"red\">") + message + m_d->ui.textEdit->appendHtml(QLatin1String("<font color=\"red\">") + message + QLatin1String("</font><p/><p/>")); } void LinuxDeviceTestDialog::handleTestFinished(AbstractLinuxDeviceTester::TestResult result) { - m_finished = true; - m_ui->buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Close")); + m_d->finished = true; + m_d->ui.buttonBox->button(QDialogButtonBox::Cancel)->setText(tr("Close")); if (result == AbstractLinuxDeviceTester::TestSuccess) { - m_ui->textEdit->appendHtml(QLatin1String("<b><font color=\"blue\">") + m_d->ui.textEdit->appendHtml(QLatin1String("<b><font color=\"blue\">") + tr("Device test finished successfully.") + QLatin1String("</font></b>")); } else { - m_ui->textEdit->appendHtml(QLatin1String("<b><font color=\"red\">") + m_d->ui.textEdit->appendHtml(QLatin1String("<b><font color=\"red\">") + tr("Device test failed.") + QLatin1String("</font></b><p/>")); } } diff --git a/src/plugins/remotelinux/linuxdevicetestdialog.h b/src/plugins/remotelinux/linuxdevicetestdialog.h index e14814a9ee..30377b0fae 100644 --- a/src/plugins/remotelinux/linuxdevicetestdialog.h +++ b/src/plugins/remotelinux/linuxdevicetestdialog.h @@ -37,18 +37,17 @@ #include <QtGui/QDialog> -QT_BEGIN_NAMESPACE -namespace Ui { -class LinuxDeviceTestDialog; -} -QT_END_NAMESPACE - namespace RemoteLinux { +namespace Internal { +class LinuxDeviceTestDialogPrivate; +} // namespace Internal class REMOTELINUX_EXPORT LinuxDeviceTestDialog : public QDialog { Q_OBJECT public: + + // Note: The dialog takes ownership of deviceTester explicit LinuxDeviceTestDialog(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration, AbstractLinuxDeviceTester * deviceTester, QWidget *parent = 0); ~LinuxDeviceTestDialog(); @@ -61,9 +60,7 @@ private slots: void handleTestFinished(RemoteLinux::AbstractLinuxDeviceTester::TestResult result); private: - Ui::LinuxDeviceTestDialog * const m_ui; - AbstractLinuxDeviceTester * const m_deviceTester; - bool m_finished; + Internal::LinuxDeviceTestDialogPrivate * const m_d; }; } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/maddedeviceconfigurationfactory.cpp b/src/plugins/remotelinux/maddedeviceconfigurationfactory.cpp index 245e34f383..31457faefd 100644 --- a/src/plugins/remotelinux/maddedeviceconfigurationfactory.cpp +++ b/src/plugins/remotelinux/maddedeviceconfigurationfactory.cpp @@ -33,10 +33,11 @@ #include "maddedevicetester.h" #include "maemodeviceconfigwizard.h" -#include "maemoremoteprocessesdialog.h" #include "publickeydeploymentdialog.h" +#include "madderemoteprocesslist.h" #include <remotelinux/linuxdevicetestdialog.h> +#include <remotelinux/remotelinuxprocessesdialog.h> #include <remotelinux/remotelinux_constants.h> #include <utils/qtcassert.h> @@ -44,6 +45,7 @@ namespace RemoteLinux { namespace Internal { namespace { const char MaddeDeviceTestActionId[] = "Madde.DeviceTestAction"; +const char MaddeRemoteProcessesActionId[] = "Madde.RemoteProcessesAction"; } // anonymous namespace MaddeDeviceConfigurationFactory::MaddeDeviceConfigurationFactory(QObject *parent) @@ -82,7 +84,7 @@ QStringList MaddeDeviceConfigurationFactory::supportedDeviceActionIds() const { return QStringList() << QLatin1String(MaddeDeviceTestActionId) << QLatin1String(Constants::GenericDeployKeyToDeviceActionId) - << QLatin1String(Constants::GenericRemoteProcessesActionId); + << QLatin1String(MaddeRemoteProcessesActionId); } QString MaddeDeviceConfigurationFactory::displayNameForActionId(const QString &actionId) const @@ -91,7 +93,7 @@ QString MaddeDeviceConfigurationFactory::displayNameForActionId(const QString &a if (actionId == QLatin1String(MaddeDeviceTestActionId)) return tr("Test"); - if (actionId == QLatin1String(Constants::GenericRemoteProcessesActionId)) + if (actionId == QLatin1String(MaddeRemoteProcessesActionId)) return tr("Remote Processes"); if (actionId == QLatin1String(Constants::GenericDeployKeyToDeviceActionId)) return tr("Deploy Public Key"); @@ -104,9 +106,9 @@ QDialog *MaddeDeviceConfigurationFactory::createDeviceAction(const QString &acti Q_ASSERT(supportedDeviceActionIds().contains(actionId)); if (actionId == QLatin1String(MaddeDeviceTestActionId)) - return new LinuxDeviceTestDialog(deviceConfig, new MaddeDeviceTester(parent), parent); - if (actionId == QLatin1String(Constants::GenericRemoteProcessesActionId)) - return new MaemoRemoteProcessesDialog(deviceConfig, parent); + return new LinuxDeviceTestDialog(deviceConfig, new MaddeDeviceTester, parent); + if (actionId == QLatin1String(MaddeRemoteProcessesActionId)) + return new RemoteLinuxProcessesDialog(new MaddeRemoteProcessList(deviceConfig), parent); if (actionId == QLatin1String(Constants::GenericDeployKeyToDeviceActionId)) return new PublicKeyDeploymentDialog(deviceConfig, parent); return 0; // Can't happen. diff --git a/src/plugins/remotelinux/maddedevicetester.h b/src/plugins/remotelinux/maddedevicetester.h index 5a14c4c235..77aa2242d4 100644 --- a/src/plugins/remotelinux/maddedevicetester.h +++ b/src/plugins/remotelinux/maddedevicetester.h @@ -47,7 +47,7 @@ class MaddeDeviceTester : public RemoteLinux::AbstractLinuxDeviceTester { Q_OBJECT public: - explicit MaddeDeviceTester(QObject *parent); + explicit MaddeDeviceTester(QObject *parent = 0); ~MaddeDeviceTester(); void testDevice(const QSharedPointer<const LinuxDeviceConfiguration> &deviceConfiguration); diff --git a/src/plugins/remotelinux/madderemoteprocesslist.cpp b/src/plugins/remotelinux/madderemoteprocesslist.cpp new file mode 100644 index 0000000000..d152377cc5 --- /dev/null +++ b/src/plugins/remotelinux/madderemoteprocesslist.cpp @@ -0,0 +1,83 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ +#include "madderemoteprocesslist.h" + +#include <remotelinux/linuxdeviceconfiguration.h> + +#include <QtCore/QString> + +namespace RemoteLinux { +namespace Internal { +namespace { + +const char FremantleLineSeparator1[] = "---"; +const char FremantleLineSeparator2[] = "QTCENDOFLINE---"; + +} // anonymous namespace + +MaddeRemoteProcessList::MaddeRemoteProcessList(const LinuxDeviceConfiguration::ConstPtr &devConfig, + QObject *parent) : GenericRemoteLinuxProcessList(devConfig, parent) +{ +} + +QString MaddeRemoteProcessList::listProcessesCommandLine() const +{ + // The ps command on Fremantle ignores all command line options, so + // we have to collect the information in /proc manually. + if (deviceConfiguration()->osType() == LinuxDeviceConfiguration::Maemo5OsType) { + return QLatin1String("sep1=") + QLatin1String(FremantleLineSeparator1) + QLatin1Char(';') + + QLatin1String("sep2=") + QLatin1String(FremantleLineSeparator2) + QLatin1Char(';') + + QLatin1String("pidlist=`ls /proc |grep -E '^[[:digit:]]+$' |sort -n`; " + "for pid in $pidlist;" + "do " + " echo -n \"$pid \";" + " tr '\\0' ' ' < /proc/$pid/cmdline;" + " echo -n \"$sep1$sep2\";" + "done;" + "echo ''"); + } + return GenericRemoteLinuxProcessList::listProcessesCommandLine(); +} + +QList<AbstractRemoteLinuxProcessList::RemoteProcess> MaddeRemoteProcessList::buildProcessList(const QString &listProcessesReply) const +{ + QString adaptedReply = listProcessesReply; + if (deviceConfiguration()->osType() == LinuxDeviceConfiguration::Maemo5OsType) { + adaptedReply.replace(QLatin1String(FremantleLineSeparator1) + + QLatin1String(FremantleLineSeparator2), QLatin1String("\n")); + adaptedReply.prepend(QLatin1String("dummy\n")); + } + + return GenericRemoteLinuxProcessList::buildProcessList(adaptedReply); +} + +} // namespace Internal +} // namespace RemoteLinux diff --git a/src/plugins/remotelinux/madderemoteprocesslist.h b/src/plugins/remotelinux/madderemoteprocesslist.h new file mode 100644 index 0000000000..b590415cd3 --- /dev/null +++ b/src/plugins/remotelinux/madderemoteprocesslist.h @@ -0,0 +1,54 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ +#ifndef MADDEREMOTEPROCESSLIST_H +#define MADDEREMOTEPROCESSLIST_H + +#include <remotelinux/remotelinuxprocesslist.h> + +namespace RemoteLinux { +namespace Internal { + +class MaddeRemoteProcessList : public RemoteLinux::GenericRemoteLinuxProcessList +{ + Q_OBJECT +public: + MaddeRemoteProcessList(const QSharedPointer<const LinuxDeviceConfiguration> &devConfig, + QObject *parent = 0); + +private: + QString listProcessesCommandLine() const; + QList<RemoteProcess> buildProcessList(const QString &listProcessesReply) const; +}; + +} // namespace Internal +} // namespace RemoteLinux + +#endif // MADDEREMOTEPROCESSLIST_H diff --git a/src/plugins/remotelinux/maemoremoteprocessesdialog.cpp b/src/plugins/remotelinux/maemoremoteprocessesdialog.cpp deleted file mode 100644 index b04b0d9217..0000000000 --- a/src/plugins/remotelinux/maemoremoteprocessesdialog.cpp +++ /dev/null @@ -1,131 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (info@qt.nokia.com) -** -** GNU Lesser General Public License Usage -** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at info@qt.nokia.com. -** -**************************************************************************/ - -#include "maemoremoteprocessesdialog.h" -#include "ui_maemoremoteprocessesdialog.h" - -#include "linuxdeviceconfiguration.h" -#include "maemoremoteprocesslist.h" - -#include <QtGui/QMessageBox> -#include <QtGui/QSortFilterProxyModel> - -namespace RemoteLinux { -namespace Internal { - -MaemoRemoteProcessesDialog::MaemoRemoteProcessesDialog(const LinuxDeviceConfiguration::ConstPtr &devConfig, - QWidget *parent): - QDialog(parent), - m_ui(new Ui::MaemoRemoteProcessesDialog), - m_processList(new MaemoRemoteProcessList(devConfig, this)), - m_proxyModel(new QSortFilterProxyModel(this)) -{ - m_ui->setupUi(this); - m_ui->tableView->setSelectionBehavior(QAbstractItemView::SelectRows); - m_proxyModel->setSourceModel(m_processList); - m_proxyModel->setDynamicSortFilter(true); - m_proxyModel->setFilterKeyColumn(1); - m_ui->tableView->setModel(m_proxyModel); - connect(m_ui->processFilterLineEdit, SIGNAL(textChanged(QString)), - m_proxyModel, SLOT(setFilterRegExp(QString))); - - // Manually gathered process information is missing the command line for - // some system processes. Dont's show these lines by default. - if (devConfig->osType() == LinuxDeviceConfiguration::Maemo5OsType) - m_ui->processFilterLineEdit->setText(QLatin1String("[^ ]+")); - - connect(m_ui->tableView->selectionModel(), - SIGNAL(selectionChanged(QItemSelection,QItemSelection)), - SLOT(handleSelectionChanged())); - connect(m_ui->updateListButton, SIGNAL(clicked()), - SLOT(updateProcessList())); - connect(m_ui->killProcessButton, SIGNAL(clicked()), SLOT(killProcess())); - connect(m_processList, SIGNAL(error(QString)), - SLOT(handleRemoteError(QString))); - connect(m_processList, SIGNAL(modelReset()), - SLOT(handleProcessListUpdated())); - connect(m_processList, SIGNAL(processKilled()), - SLOT(handleProcessKilled()), Qt::QueuedConnection); - connect(m_proxyModel, SIGNAL(layoutChanged()), - SLOT(handleProcessListUpdated())); - handleSelectionChanged(); - updateProcessList(); -} - -MaemoRemoteProcessesDialog::~MaemoRemoteProcessesDialog() -{ - delete m_ui; -} - -void MaemoRemoteProcessesDialog::handleRemoteError(const QString &errorMsg) -{ - QMessageBox::critical(this, tr("Remote Error"), errorMsg); - m_ui->updateListButton->setEnabled(true); - handleSelectionChanged(); -} - -void MaemoRemoteProcessesDialog::handleProcessListUpdated() -{ - m_ui->updateListButton->setEnabled(true); - m_ui->tableView->resizeRowsToContents(); - handleSelectionChanged(); -} - -void MaemoRemoteProcessesDialog::updateProcessList() -{ - m_ui->updateListButton->setEnabled(false); - m_ui->killProcessButton->setEnabled(false); - m_processList->update(); -} - -void MaemoRemoteProcessesDialog::killProcess() -{ - const QModelIndexList &indexes - = m_ui->tableView->selectionModel()->selectedIndexes(); - if (indexes.empty()) - return; - m_ui->updateListButton->setEnabled(false); - m_ui->killProcessButton->setEnabled(false); - m_processList->killProcess(m_proxyModel->mapToSource(indexes.first()).row()); -} - -void MaemoRemoteProcessesDialog::handleProcessKilled() -{ - updateProcessList(); -} - -void MaemoRemoteProcessesDialog::handleSelectionChanged() -{ - m_ui->killProcessButton->setEnabled(m_ui->tableView->selectionModel()->hasSelection()); -} - -} // namespace Internal -} // namespace RemoteLinux diff --git a/src/plugins/remotelinux/maemoremoteprocesslist.cpp b/src/plugins/remotelinux/maemoremoteprocesslist.cpp deleted file mode 100644 index d59846b820..0000000000 --- a/src/plugins/remotelinux/maemoremoteprocesslist.cpp +++ /dev/null @@ -1,253 +0,0 @@ -/************************************************************************** -** -** This file is part of Qt Creator -** -** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). -** -** Contact: Nokia Corporation (info@qt.nokia.com) -** -** GNU Lesser General Public License Usage -** -** This file may be used under the terms of the GNU Lesser General Public -** License version 2.1 as published by the Free Software Foundation and -** appearing in the file LICENSE.LGPL included in the packaging of this file. -** Please review the following information to ensure the GNU Lesser General -** Public License version 2.1 requirements will be met: -** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -** -** In addition, as a special exception, Nokia gives you certain additional -** rights. These rights are described in the Nokia Qt LGPL Exception -** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -** -** Other Usage -** -** Alternatively, this file may be used in accordance with the terms and -** conditions contained in a signed written agreement between you and Nokia. -** -** If you have questions regarding the use of this file, please contact -** Nokia at info@qt.nokia.com. -** -**************************************************************************/ - -#include "maemoremoteprocesslist.h" - -#include "linuxdeviceconfiguration.h" - -#include <utils/ssh/sshremoteprocessrunner.h> - -#include <QtCore/QStringList> - -using namespace Utils; - -namespace RemoteLinux { -namespace Internal { -namespace { -const QByteArray LineSeparator1("---"); -const QByteArray LineSeparator2("QTCENDOFLINE---"); -const QByteArray LineSeparator = LineSeparator1 + LineSeparator2; -} // anonymous namespace - -MaemoRemoteProcessList::MaemoRemoteProcessList(const LinuxDeviceConfiguration::ConstPtr &devConfig, - QObject *parent) - : QAbstractTableModel(parent), - m_process(SshRemoteProcessRunner::create(devConfig->sshParameters())), - m_state(Inactive), - m_devConfig(devConfig) -{ -} - -MaemoRemoteProcessList::~MaemoRemoteProcessList() {} - -void MaemoRemoteProcessList::update() -{ - if (m_state != Inactive) { - qDebug("%s: Did not expect state to be %d.", Q_FUNC_INFO, m_state); - stop(); - } - beginResetModel(); - m_remoteProcs.clear(); - QByteArray command; - - // The ps command on Fremantle ignores all command line options, so - // we have to collect the information in /proc manually. - if (m_devConfig->osType() == LinuxDeviceConfiguration::Maemo5OsType) { - command = "sep1=" + LineSeparator1 + '\n' - + "sep2=" + LineSeparator2 + '\n' - + "pidlist=`ls /proc |grep -E '^[[:digit:]]+$' |sort -n`; " - + "for pid in $pidlist\n" - + "do\n" - + " echo -n \"$pid \"\n" - + " tr '\\0' ' ' < /proc/$pid/cmdline\n" - + " echo -n \"$sep1$sep2\"\n" - + "done\n" - + "echo ''"; - } else { - command = "ps -eo pid,args"; - } - - startProcess(command, Listing); -} - -void MaemoRemoteProcessList::killProcess(int row) -{ - Q_ASSERT(row >= 0 && row < m_remoteProcs.count()); - const QByteArray command - = "kill -9 " + QByteArray::number(m_remoteProcs.at(row).pid); - startProcess(command, Killing); -} - -void MaemoRemoteProcessList::startProcess(const QByteArray &cmdLine, - State newState) -{ - if (m_state != Inactive) { - qDebug("%s: Did not expect state to be %d.", Q_FUNC_INFO, m_state); - stop(); - } - m_state = newState; - connect(m_process.data(), SIGNAL(connectionError(Utils::SshError)), - SLOT(handleConnectionError())); - connect(m_process.data(), SIGNAL(processOutputAvailable(QByteArray)), - SLOT(handleRemoteStdOut(QByteArray))); - connect(m_process.data(), - SIGNAL(processErrorOutputAvailable(QByteArray)), - SLOT(handleRemoteStdErr(QByteArray))); - connect(m_process.data(), SIGNAL(processClosed(int)), - SLOT(handleRemoteProcessFinished(int))); - m_remoteStdout.clear(); - m_remoteStderr.clear(); - m_errorMsg.clear(); - m_process->run(cmdLine); -} - -void MaemoRemoteProcessList::handleConnectionError() -{ - if (m_state == Inactive) - return; - - emit error(tr("Connection failure: %1") - .arg(m_process->connection()->errorString())); - stop(); -} - -void MaemoRemoteProcessList::handleRemoteStdOut(const QByteArray &output) -{ - if (m_state == Listing) - m_remoteStdout += output; -} - -void MaemoRemoteProcessList::handleRemoteStdErr(const QByteArray &output) -{ - if (m_state != Inactive) - m_remoteStderr += output; -} - -void MaemoRemoteProcessList::handleRemoteProcessFinished(int exitStatus) -{ - if (m_state == Inactive) - return; - - switch (exitStatus) { - case SshRemoteProcess::FailedToStart: - m_errorMsg = tr("Error: Remote process failed to start: %1") - .arg(m_process->process()->errorString()); - break; - case SshRemoteProcess::KilledBySignal: - m_errorMsg = tr("Error: Remote process crashed: %1") - .arg(m_process->process()->errorString()); - break; - case SshRemoteProcess::ExitedNormally: - if (m_process->process()->exitCode() == 0) { - if (m_state == Listing) - buildProcessList(); - } else { - m_errorMsg = tr("Remote process failed."); - } - break; - default: - Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status"); - } - - if (!m_errorMsg.isEmpty()) { - if (!m_remoteStderr.isEmpty()) { - m_errorMsg += tr("\nRemote stderr was: %1") - .arg(QString::fromUtf8(m_remoteStderr)); - } - emit error(m_errorMsg); - } - stop(); -} - -void MaemoRemoteProcessList::stop() -{ - if (m_state == Inactive) - return; - - disconnect(m_process.data(), 0, this, 0); - if (m_state == Listing) - endResetModel(); - else if (m_errorMsg.isEmpty()) - emit processKilled(); - m_state = Inactive; -} - -void MaemoRemoteProcessList::buildProcessList() -{ - const bool isFremantle = m_devConfig->osType() == LinuxDeviceConfiguration::Maemo5OsType; - const QString remoteOutput = QString::fromUtf8(m_remoteStdout); - const QByteArray lineSeparator = isFremantle ? LineSeparator : "\n"; - QStringList lines = remoteOutput.split(QString::fromUtf8(lineSeparator)); - if (!isFremantle) - lines.removeFirst(); // column headers - foreach (const QString &line, lines) { - const QString &trimmedLine = line.trimmed(); - const int pidEndPos = trimmedLine.indexOf(' '); - if (pidEndPos == -1) - continue; - bool isNumber; - const int pid = trimmedLine.left(pidEndPos).toInt(&isNumber); - if (!isNumber) { - qDebug("%s: Non-integer value where pid was expected. Line was: '%s'", - Q_FUNC_INFO, qPrintable(trimmedLine)); - continue; - } - m_remoteProcs << RemoteProc(pid, trimmedLine.mid(pidEndPos)); - } -} - -int MaemoRemoteProcessList::rowCount(const QModelIndex &parent) const -{ - return parent.isValid() ? 0 : m_remoteProcs.count(); -} - -int MaemoRemoteProcessList::columnCount(const QModelIndex &parent) const -{ - Q_UNUSED(parent); - return 2; -} - -QVariant MaemoRemoteProcessList::headerData(int section, - Qt::Orientation orientation, int role) const -{ - if (orientation != Qt::Horizontal || role != Qt::DisplayRole - || section < 0 || section >= columnCount()) - return QVariant(); - if (section == 0) - return tr("PID"); - else - return tr("Command Line"); -} - -QVariant MaemoRemoteProcessList::data(const QModelIndex &index, int role) const -{ - if (!index.isValid() || index.row() >= rowCount(index.parent()) - || index.column() >= columnCount() || role != Qt::DisplayRole) - return QVariant(); - const RemoteProc &proc = m_remoteProcs.at(index.row()); - if (index.column() == 0) - return proc.pid; - else - return proc.cmdLine; -} - -} // namespace Internal -} // namespace RemoteLinux diff --git a/src/plugins/remotelinux/remotelinux.pro b/src/plugins/remotelinux/remotelinux.pro index c6b981421a..b564ef7ebd 100644 --- a/src/plugins/remotelinux/remotelinux.pro +++ b/src/plugins/remotelinux/remotelinux.pro @@ -30,8 +30,6 @@ HEADERS += \ maemoremotemounter.h \ maemoprofilesupdatedialog.h \ maemousedportsgatherer.h \ - maemoremoteprocesslist.h \ - maemoremoteprocessesdialog.h \ maemopublishingwizardfactories.h \ maemopublishingbuildsettingspagefremantlefree.h \ maemopublishingfileselectiondialog.h \ @@ -95,7 +93,10 @@ HEADERS += \ linuxdevicetester.h \ maddedevicetester.h \ remotelinux_constants.h \ - linuxdevicetestdialog.h + linuxdevicetestdialog.h \ + remotelinuxprocesslist.h \ + madderemoteprocesslist.h \ + remotelinuxprocessesdialog.h SOURCES += \ remotelinuxplugin.cpp \ @@ -121,8 +122,6 @@ SOURCES += \ maemoremotemounter.cpp \ maemoprofilesupdatedialog.cpp \ maemousedportsgatherer.cpp \ - maemoremoteprocesslist.cpp \ - maemoremoteprocessesdialog.cpp \ maemopublishingwizardfactories.cpp \ maemopublishingbuildsettingspagefremantlefree.cpp \ maemopublishingfileselectiondialog.cpp \ @@ -183,14 +182,16 @@ SOURCES += \ packageuploader.cpp \ linuxdevicetester.cpp \ maddedevicetester.cpp \ - linuxdevicetestdialog.cpp + linuxdevicetestdialog.cpp \ + remotelinuxprocesslist.cpp \ + madderemoteprocesslist.cpp \ + remotelinuxprocessesdialog.cpp FORMS += \ maemodeviceconfigurationssettingswidget.ui \ maemosshconfigdialog.ui \ maemopackagecreationwidget.ui \ maemoprofilesupdatedialog.ui \ - maemoremoteprocessesdialog.ui \ maemopublishingbuildsettingspagefremantlefree.ui \ maemopublishingfileselectiondialog.ui \ maemopublishinguploadsettingspagefremantlefree.ui \ @@ -204,7 +205,8 @@ FORMS += \ maemodeployconfigurationwidget.ui \ linuxdevicefactoryselectiondialog.ui \ genericlinuxdeviceconfigurationwizardsetuppage.ui \ - linuxdevicetestdialog.ui + linuxdevicetestdialog.ui \ + remotelinuxprocessesdialog.ui RESOURCES += qt-maemo.qrc DEFINES += QT_NO_CAST_TO_ASCII diff --git a/src/plugins/remotelinux/remotelinuxprocessesdialog.cpp b/src/plugins/remotelinux/remotelinuxprocessesdialog.cpp new file mode 100644 index 0000000000..ce8000d420 --- /dev/null +++ b/src/plugins/remotelinux/remotelinuxprocessesdialog.cpp @@ -0,0 +1,139 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ + +#include "remotelinuxprocessesdialog.h" +#include "ui_remotelinuxprocessesdialog.h" + +#include "remotelinuxprocesslist.h" + +#include <QtGui/QMessageBox> +#include <QtGui/QSortFilterProxyModel> + +namespace RemoteLinux { +namespace Internal { +class RemoteLinuxProcessesDialogPrivate +{ +public: + RemoteLinuxProcessesDialogPrivate(AbstractRemoteLinuxProcessList *processList) + : processList(processList) + { + } + + Ui::RemoteLinuxProcessesDialog ui; + AbstractRemoteLinuxProcessList * const processList; + QSortFilterProxyModel proxyModel; +}; + +} // namespace Internal + +using namespace Internal; + +RemoteLinuxProcessesDialog::RemoteLinuxProcessesDialog(AbstractRemoteLinuxProcessList *processList, + QWidget *parent) + : QDialog(parent), m_d(new RemoteLinuxProcessesDialogPrivate(processList)) +{ + processList->setParent(this); + + m_d->ui.setupUi(this); + m_d->ui.tableView->setSelectionBehavior(QAbstractItemView::SelectRows); + m_d->proxyModel.setSourceModel(m_d->processList); + m_d->proxyModel.setDynamicSortFilter(true); + m_d->proxyModel.setFilterKeyColumn(1); + m_d->ui.tableView->setModel(&m_d->proxyModel); + connect(m_d->ui.processFilterLineEdit, SIGNAL(textChanged(QString)), + &m_d->proxyModel, SLOT(setFilterRegExp(QString))); + + connect(m_d->ui.tableView->selectionModel(), + SIGNAL(selectionChanged(QItemSelection,QItemSelection)), + SLOT(handleSelectionChanged())); + connect(m_d->ui.updateListButton, SIGNAL(clicked()), + SLOT(updateProcessList())); + connect(m_d->ui.killProcessButton, SIGNAL(clicked()), SLOT(killProcess())); + connect(m_d->processList, SIGNAL(error(QString)), + SLOT(handleRemoteError(QString))); + connect(m_d->processList, SIGNAL(modelReset()), + SLOT(handleProcessListUpdated())); + connect(m_d->processList, SIGNAL(processKilled()), + SLOT(handleProcessKilled()), Qt::QueuedConnection); + connect(&m_d->proxyModel, SIGNAL(layoutChanged()), + SLOT(handleProcessListUpdated())); + handleSelectionChanged(); + updateProcessList(); +} + +RemoteLinuxProcessesDialog::~RemoteLinuxProcessesDialog() +{ + delete m_d; +} + +void RemoteLinuxProcessesDialog::handleRemoteError(const QString &errorMsg) +{ + QMessageBox::critical(this, tr("Remote Error"), errorMsg); + m_d->ui.updateListButton->setEnabled(true); + handleSelectionChanged(); +} + +void RemoteLinuxProcessesDialog::handleProcessListUpdated() +{ + m_d->ui.updateListButton->setEnabled(true); + m_d->ui.tableView->resizeRowsToContents(); + handleSelectionChanged(); +} + +void RemoteLinuxProcessesDialog::updateProcessList() +{ + m_d->ui.updateListButton->setEnabled(false); + m_d->ui.killProcessButton->setEnabled(false); + m_d->processList->update(); +} + +void RemoteLinuxProcessesDialog::killProcess() +{ + const QModelIndexList &indexes + = m_d->ui.tableView->selectionModel()->selectedIndexes(); + if (indexes.empty()) + return; + m_d->ui.updateListButton->setEnabled(false); + m_d->ui.killProcessButton->setEnabled(false); + m_d->processList->killProcess(m_d->proxyModel.mapToSource(indexes.first()).row()); +} + +void RemoteLinuxProcessesDialog::handleProcessKilled() +{ + updateProcessList(); +} + +void RemoteLinuxProcessesDialog::handleSelectionChanged() +{ + m_d->ui.killProcessButton->setEnabled(m_d->ui.tableView->selectionModel()->hasSelection()); +} + +} // namespace RemoteLinux diff --git a/src/plugins/remotelinux/maemoremoteprocessesdialog.h b/src/plugins/remotelinux/remotelinuxprocessesdialog.h index 0042a61753..8458a84d67 100644 --- a/src/plugins/remotelinux/maemoremoteprocessesdialog.h +++ b/src/plugins/remotelinux/remotelinuxprocessesdialog.h @@ -28,34 +28,28 @@ ** Nokia at info@qt.nokia.com. ** **************************************************************************/ +#ifndef REMOTELINUXPROCESSESDIALOG_H +#define REMOTELINUXPROCESSESDIALOG_H -#ifndef MAEMOREMOTEPROCESSDIALOG_H -#define MAEMOREMOTEPROCESSDIALOG_H +#include "remotelinux_export.h" -#include <QtCore/QSharedPointer> #include <QtGui/QDialog> -QT_BEGIN_NAMESPACE -namespace Ui { - class MaemoRemoteProcessesDialog; -} -class QSortFilterProxyModel; -QT_END_NAMESPACE - namespace RemoteLinux { -class LinuxDeviceConfiguration; +class AbstractRemoteLinuxProcessList; namespace Internal { -class MaemoRemoteProcessList; +class RemoteLinuxProcessesDialogPrivate; +} // namespace Internal -class MaemoRemoteProcessesDialog : public QDialog +class RemoteLinuxProcessesDialog : public QDialog { Q_OBJECT - public: - explicit MaemoRemoteProcessesDialog(const QSharedPointer<const LinuxDeviceConfiguration> &devConfig, + // Note: The dialog takes ownership of processList. + explicit RemoteLinuxProcessesDialog(AbstractRemoteLinuxProcessList *processList, QWidget *parent = 0); - ~MaemoRemoteProcessesDialog(); + ~RemoteLinuxProcessesDialog(); private slots: void updateProcessList(); @@ -66,12 +60,9 @@ private slots: void handleSelectionChanged(); private: - Ui::MaemoRemoteProcessesDialog *m_ui; - MaemoRemoteProcessList *const m_processList; - QSortFilterProxyModel *const m_proxyModel; + Internal::RemoteLinuxProcessesDialogPrivate * const m_d; }; -} // namespace Internal } // namespace RemoteLinux -#endif // MAEMOREMOTEPROCESSDIALOG_H +#endif // REMOTELINUXPROCESSESDIALOG_H diff --git a/src/plugins/remotelinux/maemoremoteprocessesdialog.ui b/src/plugins/remotelinux/remotelinuxprocessesdialog.ui index 7e74791729..3ee7a59991 100644 --- a/src/plugins/remotelinux/maemoremoteprocessesdialog.ui +++ b/src/plugins/remotelinux/remotelinuxprocessesdialog.ui @@ -1,7 +1,7 @@ <?xml version="1.0" encoding="UTF-8"?> <ui version="4.0"> - <class>MaemoRemoteProcessesDialog</class> - <widget class="QDialog" name="MaemoRemoteProcessesDialog"> + <class>RemoteLinuxProcessesDialog</class> + <widget class="QDialog" name="RemoteLinuxProcessesDialog"> <property name="geometry"> <rect> <x>0</x> @@ -115,7 +115,7 @@ <connection> <sender>buttonBox</sender> <signal>accepted()</signal> - <receiver>MaemoRemoteProcessesDialog</receiver> + <receiver>RemoteLinuxProcessesDialog</receiver> <slot>accept()</slot> <hints> <hint type="sourcelabel"> @@ -131,7 +131,7 @@ <connection> <sender>buttonBox</sender> <signal>rejected()</signal> - <receiver>MaemoRemoteProcessesDialog</receiver> + <receiver>RemoteLinuxProcessesDialog</receiver> <slot>reject()</slot> <hints> <hint type="sourcelabel"> diff --git a/src/plugins/remotelinux/remotelinuxprocesslist.cpp b/src/plugins/remotelinux/remotelinuxprocesslist.cpp new file mode 100644 index 0000000000..ab58d94b87 --- /dev/null +++ b/src/plugins/remotelinux/remotelinuxprocesslist.cpp @@ -0,0 +1,259 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (info@qt.nokia.com) +** +** GNU Lesser General Public License Usage +** +** This file may be used under the terms of the GNU Lesser General Public +** License version 2.1 as published by the Free Software Foundation and +** appearing in the file LICENSE.LGPL included in the packaging of this file. +** Please review the following information to ensure the GNU Lesser General +** Public License version 2.1 requirements will be met: +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** Other Usage +** +** Alternatively, this file may be used in accordance with the terms and +** conditions contained in a signed written agreement between you and Nokia. +** +** If you have questions regarding the use of this file, please contact +** Nokia at info@qt.nokia.com. +** +**************************************************************************/ +#include "remotelinuxprocesslist.h" + +#include "linuxdeviceconfiguration.h" + +#include <utils/qtcassert.h> +#include <utils/ssh/sshremoteprocessrunner.h> + +#include <QtCore/QByteArray> +#include <QtCore/QString> + +using namespace Utils; + +namespace RemoteLinux { +namespace Internal { +namespace { +enum State { Inactive, Listing, Killing }; +} // anonymous namespace + +class AbstractRemoteLinuxProcessListPrivate +{ +public: + AbstractRemoteLinuxProcessListPrivate(const LinuxDeviceConfiguration::ConstPtr &devConf) + : deviceConfiguration(devConf), + process(SshRemoteProcessRunner::create(devConf->sshParameters())), + state(Inactive) + { + } + + const LinuxDeviceConfiguration::ConstPtr deviceConfiguration; + const SshRemoteProcessRunner::Ptr process; + QList<AbstractRemoteLinuxProcessList::RemoteProcess> remoteProcesses; + QByteArray remoteStdout; + QByteArray remoteStderr; + QString errorMsg; + State state; +}; + +} // namespace Internal + +using namespace Internal; + +AbstractRemoteLinuxProcessList::AbstractRemoteLinuxProcessList(const LinuxDeviceConfiguration::ConstPtr &devConfig, + QObject *parent) + : QAbstractTableModel(parent), m_d(new AbstractRemoteLinuxProcessListPrivate(devConfig)) +{ +} + +LinuxDeviceConfiguration::ConstPtr AbstractRemoteLinuxProcessList::deviceConfiguration() const +{ + return m_d->deviceConfiguration; +} + +AbstractRemoteLinuxProcessList::~AbstractRemoteLinuxProcessList() +{ + delete m_d; +} + +void AbstractRemoteLinuxProcessList::update() +{ + QTC_ASSERT(m_d->state == Inactive, return); + + beginResetModel(); + m_d->remoteProcesses.clear(); + m_d->state = Listing; + startProcess(listProcessesCommandLine()); +} + +void AbstractRemoteLinuxProcessList::killProcess(int row) +{ + QTC_ASSERT(row >= 0 && row < m_d->remoteProcesses.count(), return); + QTC_ASSERT(m_d->state == Inactive, return); + + m_d->state = Killing; + startProcess(killProcessCommandLine(m_d->remoteProcesses.at(row))); +} + +int AbstractRemoteLinuxProcessList::rowCount(const QModelIndex &parent) const +{ + return parent.isValid() ? 0 : m_d->remoteProcesses.count(); +} + +int AbstractRemoteLinuxProcessList::columnCount(const QModelIndex &) const { return 2; } + +QVariant AbstractRemoteLinuxProcessList::headerData(int section, Qt::Orientation orientation, + int role) const +{ + if (orientation != Qt::Horizontal || role != Qt::DisplayRole || section < 0 + || section >= columnCount()) + return QVariant(); + return section == 0? tr("PID") : tr("Command Line"); +} + +QVariant AbstractRemoteLinuxProcessList::data(const QModelIndex &index, int role) const +{ + if (!index.isValid() || index.row() >= rowCount(index.parent()) + || index.column() >= columnCount() || role != Qt::DisplayRole) + return QVariant(); + const RemoteProcess &proc = m_d->remoteProcesses.at(index.row()); + if (index.column() == 0) + return proc.pid; + else + return proc.cmdLine; +} + +void AbstractRemoteLinuxProcessList::handleRemoteStdOut(const QByteArray &output) +{ + if (m_d->state == Listing) + m_d->remoteStdout += output; +} + +void AbstractRemoteLinuxProcessList::handleRemoteStdErr(const QByteArray &output) +{ + if (m_d->state != Inactive) + m_d->remoteStderr += output; +} + +void AbstractRemoteLinuxProcessList::handleConnectionError() +{ + QTC_ASSERT(m_d->state != Inactive, return); + + emit error(tr("Connection failure: %1").arg(m_d->process->connection()->errorString())); + beginResetModel(); + m_d->remoteProcesses.clear(); + endResetModel(); + setFinished(); +} + +void AbstractRemoteLinuxProcessList::handleRemoteProcessFinished(int exitStatus) +{ + QTC_ASSERT(m_d->state != Inactive, return); + + switch (exitStatus) { + case SshRemoteProcess::FailedToStart: + m_d->errorMsg = tr("Error: Remote process failed to start: %1") + .arg(m_d->process->process()->errorString()); + break; + case SshRemoteProcess::KilledBySignal: + m_d->errorMsg = tr("Error: Remote process crashed: %1") + .arg(m_d->process->process()->errorString()); + break; + case SshRemoteProcess::ExitedNormally: + if (m_d->process->process()->exitCode() == 0) { + if (m_d->state == Listing) + m_d->remoteProcesses = buildProcessList(QString::fromUtf8(m_d->remoteStdout)); + } else { + m_d->errorMsg = tr("Remote process failed."); + } + break; + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status"); + } + + if (!m_d->errorMsg.isEmpty()) { + if (!m_d->remoteStderr.isEmpty()) + m_d->errorMsg += tr("\nRemote stderr was: %1").arg(QString::fromUtf8(m_d->remoteStderr)); + emit error(m_d->errorMsg); + } else if (m_d->state == Killing) { + emit processKilled(); + } + + if (m_d->state == Listing) + endResetModel(); + + setFinished(); +} + +void AbstractRemoteLinuxProcessList::startProcess(const QString &cmdLine) +{ + connect(m_d->process.data(), SIGNAL(connectionError(Utils::SshError)), + SLOT(handleConnectionError())); + connect(m_d->process.data(), SIGNAL(processOutputAvailable(QByteArray)), + SLOT(handleRemoteStdOut(QByteArray))); + connect(m_d->process.data(), SIGNAL(processErrorOutputAvailable(QByteArray)), + SLOT(handleRemoteStdErr(QByteArray))); + connect(m_d->process.data(), SIGNAL(processClosed(int)), + SLOT(handleRemoteProcessFinished(int))); + m_d->remoteStdout.clear(); + m_d->remoteStderr.clear(); + m_d->errorMsg.clear(); + m_d->process->run(cmdLine.toUtf8()); +} + +void AbstractRemoteLinuxProcessList::setFinished() +{ + disconnect(m_d->process.data(), 0, this, 0); + m_d->state = Inactive; +} + + +GenericRemoteLinuxProcessList::GenericRemoteLinuxProcessList(const LinuxDeviceConfiguration::ConstPtr &devConfig, + QObject *parent) + : AbstractRemoteLinuxProcessList(devConfig, parent) +{ +} + +QString GenericRemoteLinuxProcessList::listProcessesCommandLine() const +{ + return QLatin1String("ps -eo pid,args"); +} + +QString GenericRemoteLinuxProcessList::killProcessCommandLine(const RemoteProcess &process) const +{ + return QLatin1String("kill -9 ") + QString::number(process.pid); +} + +QList<AbstractRemoteLinuxProcessList::RemoteProcess> GenericRemoteLinuxProcessList::buildProcessList(const QString &listProcessesReply) const +{ + QList<RemoteProcess> processes; + QStringList lines = listProcessesReply.split(QLatin1Char('\n')); + lines.removeFirst(); // column headers + foreach (const QString &line, lines) { + const QString &trimmedLine = line.trimmed(); + const int pidEndPos = trimmedLine.indexOf(QLatin1Char(' ')); + if (pidEndPos == -1) + continue; + bool isNumber; + const int pid = trimmedLine.left(pidEndPos).toInt(&isNumber); + if (!isNumber) { + qDebug("%s: Non-integer value where pid was expected. Line was: '%s'", + Q_FUNC_INFO, qPrintable(trimmedLine)); + continue; + } + processes << RemoteProcess(pid, trimmedLine.mid(pidEndPos)); + } + + return processes; +} + +} // namespace RemoteLinux diff --git a/src/plugins/remotelinux/maemoremoteprocesslist.h b/src/plugins/remotelinux/remotelinuxprocesslist.h index 4fa9565f00..9391b55522 100644 --- a/src/plugins/remotelinux/maemoremoteprocesslist.h +++ b/src/plugins/remotelinux/remotelinuxprocesslist.h @@ -28,29 +28,29 @@ ** Nokia at info@qt.nokia.com. ** **************************************************************************/ +#ifndef REMOTELINUXPROCESSLIST_H +#define REMOTELINUXPROCESSLIST_H -#ifndef MAEMOREMOTEPROCESSLIST_H -#define MAEMOREMOTEPROCESSLIST_H +#include "remotelinux_export.h" #include <QtCore/QAbstractTableModel> -#include <QtCore/QByteArray> #include <QtCore/QList> #include <QtCore/QSharedPointer> -#include <QtCore/QString> -#include <utils/ssh/sshremoteprocessrunner.h> namespace RemoteLinux { class LinuxDeviceConfiguration; namespace Internal { +class AbstractRemoteLinuxProcessListPrivate; +} -class MaemoRemoteProcessList : public QAbstractTableModel +class REMOTELINUX_EXPORT AbstractRemoteLinuxProcessList : public QAbstractTableModel { Q_OBJECT + friend class Internal::AbstractRemoteLinuxProcessListPrivate; public: - explicit MaemoRemoteProcessList(const QSharedPointer<const LinuxDeviceConfiguration> &devConfig, - QObject *parent = 0); - ~MaemoRemoteProcessList(); + ~AbstractRemoteLinuxProcessList(); + void update(); void killProcess(int row); @@ -58,6 +58,19 @@ signals: void error(const QString &errorMsg); void processKilled(); +protected: + AbstractRemoteLinuxProcessList(const QSharedPointer<const LinuxDeviceConfiguration> &devConfig, + QObject *parent = 0); + + QSharedPointer<const LinuxDeviceConfiguration> deviceConfiguration() const; + + struct RemoteProcess { + RemoteProcess(int pid, const QString &cmdLine) : pid(pid), cmdLine(cmdLine) {} + + int pid; + QString cmdLine; + }; + private slots: void handleRemoteStdOut(const QByteArray &output); void handleRemoteStdErr(const QByteArray &output); @@ -65,36 +78,36 @@ private slots: void handleRemoteProcessFinished(int exitStatus); private: - enum State { Inactive, Listing, Killing }; - - virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; - virtual int columnCount(const QModelIndex &parent = QModelIndex()) const; - virtual QVariant data(const QModelIndex &index, - int role = Qt::DisplayRole) const; - virtual QVariant headerData(int section, Qt::Orientation orientation, + int rowCount(const QModelIndex &parent = QModelIndex()) const; + int columnCount(const QModelIndex &parent = QModelIndex()) const; + QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const; + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - void buildProcessList(); - void stop(); - void startProcess(const QByteArray &cmdLine, State newState); + virtual QString listProcessesCommandLine() const=0; + virtual QString killProcessCommandLine(const RemoteProcess &process) const=0; + virtual QList<RemoteProcess> buildProcessList(const QString &listProcessesReply) const=0; - const QSharedPointer<Utils::SshRemoteProcessRunner> m_process; - QByteArray m_remoteStdout; - QByteArray m_remoteStderr; - QString m_errorMsg; - State m_state; + void startProcess(const QString &cmdLine); + void setFinished(); - struct RemoteProc { - RemoteProc(int pid, const QString &cmdLine) - : pid(pid), cmdLine(cmdLine) {} - int pid; - QString cmdLine; - }; - QList<RemoteProc> m_remoteProcs; - const QSharedPointer<const LinuxDeviceConfiguration> m_devConfig; + Internal::AbstractRemoteLinuxProcessListPrivate * const m_d; +}; + + +class GenericRemoteLinuxProcessList : public AbstractRemoteLinuxProcessList +{ + Q_OBJECT +public: + GenericRemoteLinuxProcessList(const QSharedPointer<const LinuxDeviceConfiguration> &devConfig, + QObject *parent = 0); + +protected: + QString listProcessesCommandLine() const; + QString killProcessCommandLine(const RemoteProcess &process) const; + QList<RemoteProcess> buildProcessList(const QString &listProcessesReply) const; }; -} // namespace Internal } // namespace RemoteLinux -#endif // MAEMOREMOTEPROCESSLIST_H +#endif // REMOTELINUXPROCESSLIST_H |