diff --git a/src/plugins/debugger/gdb/startgdbserverdialog.cpp b/src/plugins/debugger/gdb/startgdbserverdialog.cpp index f6a6b0d4a2d0d0262530d8bbaf32a489764bd170..a35ed5d2ac2e45e12efa086ea116cc92c014ffd3 100644 --- a/src/plugins/debugger/gdb/startgdbserverdialog.cpp +++ b/src/plugins/debugger/gdb/startgdbserverdialog.cpp @@ -210,7 +210,7 @@ void StartGdbServerDialog::attachToDevice() if (!device) return; delete d->processList; - d->processList = new DeviceProcessList(device); + d->processList = device->createProcessListModel(); d->proxyModel.setSourceModel(d->processList); connect(d->processList, SIGNAL(error(QString)), SLOT(handleRemoteError(QString))); diff --git a/src/plugins/madde/maddedevice.cpp b/src/plugins/madde/maddedevice.cpp index 3df7e4b201600f9bebdd2d515ce03106f488a2cb..c88ee1a5fe1ce09b14b5d0fcd52da2854283319c 100644 --- a/src/plugins/madde/maddedevice.cpp +++ b/src/plugins/madde/maddedevice.cpp @@ -111,12 +111,12 @@ void MaddeDevice::executeAction(Core::Id actionId, QWidget *parent) const if (actionId == Core::Id(MaddeDeviceTestActionId)) d = new LinuxDeviceTestDialog(device, new MaddeDeviceTester, parent); else if (actionId == Core::Id(MaddeRemoteProcessesActionId)) - d = new DeviceProcessesDialog(new DeviceProcessList(device), parent); + d = new DeviceProcessesDialog(createProcessListModel(parent)); else if (actionId == Core::Id(Constants::GenericDeployKeyToDeviceActionId)) d = PublicKeyDeploymentDialog::createDialog(device, parent); - // FIXME: Leak? if (d) d->exec(); + delete d; } QString MaddeDevice::maddeDisplayType(Core::Id type) diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp index be2be74cfdb892c2130745fa4cd626aab601709f..cf196610b6a396b34296acf53212e6d2fe3572df 100644 --- a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp +++ b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.cpp @@ -30,9 +30,6 @@ #include "deviceprocesslist.h" #include <utils/qtcassert.h> -#include <ssh/sshremoteprocessrunner.h> - -using namespace QSsh; namespace ProjectExplorer { namespace Internal { @@ -48,9 +45,7 @@ public: { } const IDevice::ConstPtr device; - SshRemoteProcessRunner process; QList<DeviceProcess> remoteProcesses; - QString errorMsg; State state; }; @@ -71,7 +66,7 @@ DeviceProcessList::~DeviceProcessList() void DeviceProcessList::update() { QTC_ASSERT(d->state == Inactive, return); - QTC_ASSERT(d->device && d->device->processSupport(), return); + QTC_ASSERT(device(), return); if (!d->remoteProcesses.isEmpty()) { beginRemoveRows(QModelIndex(), 0, d->remoteProcesses.count() - 1); @@ -79,27 +74,51 @@ void DeviceProcessList::update() endRemoveRows(); } d->state = Listing; - startProcess(d->device->processSupport()->listProcessesCommandLine()); + doUpdate(); +} + +void DeviceProcessList::doUpdate() +{ + reportProcessListUpdated(QList<DeviceProcess>()); +} + +void DeviceProcessList::reportProcessListUpdated(const QList<DeviceProcess> &processes) +{ + QTC_ASSERT(d->state == Listing, return); + setFinished(); + if (!processes.isEmpty()) { + beginInsertRows(QModelIndex(), 0, processes.count() - 1); + d->remoteProcesses = processes; + endInsertRows(); + } + emit processListUpdated(); } void DeviceProcessList::killProcess(int row) { QTC_ASSERT(row >= 0 && row < d->remoteProcesses.count(), return); QTC_ASSERT(d->state == Inactive, return); + QTC_ASSERT(device(), return); d->state = Killing; - const int pid = d->remoteProcesses.at(row).pid; - startProcess(d->device->processSupport()->killProcessByPidCommandLine(pid)); + doKillProcess(d->remoteProcesses.at(row)); } -DeviceProcess DeviceProcessList::at(int row) const +void DeviceProcessList::doKillProcess(const DeviceProcess &) { - return d->remoteProcesses.at(row); + QTC_ASSERT(false, qDebug("Process list should be empty"); return); } -IDevice::ConstPtr DeviceProcessList::device() const +void DeviceProcessList::reportProcessKilled() { - return d->device; + QTC_ASSERT(d->state == Killing, return); + setFinished(); + emit processKilled(); +} + +DeviceProcess DeviceProcessList::at(int row) const +{ + return d->remoteProcesses.at(row); } int DeviceProcessList::rowCount(const QModelIndex &parent) const @@ -134,80 +153,21 @@ QVariant DeviceProcessList::data(const QModelIndex &index, int role) const return QVariant(); } -void DeviceProcessList::handleConnectionError() -{ - QTC_ASSERT(d->state != Inactive, return); - - emit error(tr("Connection failure: %1").arg(d->process.lastConnectionErrorString())); - beginResetModel(); - d->remoteProcesses.clear(); - endResetModel(); - setFinished(); -} - -void DeviceProcessList::handleRemoteProcessFinished(int exitStatus) +void DeviceProcessList::setFinished() { - QTC_ASSERT(d->state != Inactive, return); - - switch (exitStatus) { - case SshRemoteProcess::FailedToStart: - d->errorMsg = tr("Error: Remote process failed to start: %1") - .arg(d->process.processErrorString()); - break; - case SshRemoteProcess::CrashExit: - d->errorMsg = tr("Error: Remote process crashed: %1") - .arg(d->process.processErrorString()); - break; - case SshRemoteProcess::NormalExit: - if (d->process.processExitCode() == 0) { - if (d->state == Listing) { - const QByteArray remoteStdout = d->process.readAllStandardOutput(); - const QString stdoutString - = QString::fromUtf8(remoteStdout.data(), remoteStdout.count()); - QList<DeviceProcess> processes - = d->device->processSupport()->buildProcessList(stdoutString); - if (!processes.isEmpty()) { - beginInsertRows(QModelIndex(), 0, processes.count()-1); - d->remoteProcesses = processes; - endInsertRows(); - } - } - } else { - d->errorMsg = tr("Remote process failed."); - } - break; - default: - Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status"); - } - - if (d->state == Listing) - emit processListUpdated(); - - if (!d->errorMsg.isEmpty()) { - const QByteArray remoteStderr = d->process.readAllStandardError(); - if (!remoteStderr.isEmpty()) - d->errorMsg += tr("\nRemote stderr was: %1").arg(QString::fromUtf8(remoteStderr)); - emit error(d->errorMsg); - } else if (d->state == Killing) { - emit processKilled(); - } - - setFinished(); + d->state = Inactive; } -void DeviceProcessList::startProcess(const QString &cmdLine) +IDevice::ConstPtr DeviceProcessList::device() const { - connect(&d->process, SIGNAL(connectionError()), SLOT(handleConnectionError())); - connect(&d->process, SIGNAL(processClosed(int)), - SLOT(handleRemoteProcessFinished(int))); - d->errorMsg.clear(); - d->process.run(cmdLine.toUtf8(), d->device->sshParameters()); + return d->device; } -void DeviceProcessList::setFinished() +void DeviceProcessList::reportError(const QString &message) { - disconnect(&d->process, 0, this, 0); - d->state = Inactive; + QTC_ASSERT(d->state != Inactive, return); + setFinished(); + emit error(message); } diff --git a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.h b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.h index 5bfb8f2bd138e7c826b6c07d8a92aca4f6acb402..fcbf8bacc2324031d51005515f2a1d1367c8e85e 100644 --- a/src/plugins/projectexplorer/devicesupport/deviceprocesslist.h +++ b/src/plugins/projectexplorer/devicesupport/deviceprocesslist.h @@ -40,6 +40,17 @@ namespace ProjectExplorer { namespace Internal { class DeviceProcessListPrivate; } +class PROJECTEXPLORER_EXPORT DeviceProcess +{ +public: + DeviceProcess() : pid(0) {} + bool operator<(const DeviceProcess &other) const; + + int pid; + QString cmdLine; + QString exe; +}; + class PROJECTEXPLORER_EXPORT DeviceProcessList : public QAbstractTableModel { Q_OBJECT @@ -51,16 +62,18 @@ public: void update(); void killProcess(int row); DeviceProcess at(int row) const; - IDevice::ConstPtr device() const; signals: void processListUpdated(); void error(const QString &errorMsg); void processKilled(); -private slots: - void handleConnectionError(); - void handleRemoteProcessFinished(int exitStatus); +protected: + void reportError(const QString &message); + void reportProcessKilled(); + void reportProcessListUpdated(const QList<DeviceProcess> &processes); + + IDevice::ConstPtr device() const; private: int rowCount(const QModelIndex &parent = QModelIndex()) const; @@ -69,7 +82,10 @@ private: int role = Qt::DisplayRole) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; - void startProcess(const QString &cmdLine); + // No-op implementations for devices without process listing abilities. + virtual void doUpdate(); + virtual void doKillProcess(const DeviceProcess &process); + void setFinished(); Internal::DeviceProcessListPrivate * const d; diff --git a/src/plugins/projectexplorer/devicesupport/idevice.cpp b/src/plugins/projectexplorer/devicesupport/idevice.cpp index 5a9430b1d3f5509355f0fb90b51d9296faf3f038..724cac12f1797d4ca45d8c672fa63caed52bd1c9 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.cpp +++ b/src/plugins/projectexplorer/devicesupport/idevice.cpp @@ -30,6 +30,7 @@ #include "idevice.h" #include "devicemanager.h" +#include "deviceprocesslist.h" #include <coreplugin/id.h> #include <ssh/sshconnection.h> @@ -259,6 +260,11 @@ PortsGatheringMethod::Ptr IDevice::portsGatheringMethod() const return PortsGatheringMethod::Ptr(); } +DeviceProcessList *IDevice::createProcessListModel(QObject *parent) const +{ + return new DeviceProcessList(sharedFromThis(), parent); +} + IDevice::DeviceState IDevice::deviceState() const { return d->deviceState; diff --git a/src/plugins/projectexplorer/devicesupport/idevice.h b/src/plugins/projectexplorer/devicesupport/idevice.h index c20ae330b22bf356df76b73ab8d28ae2984a5898..b7e91b65356e19f214b28703c5757791b600c846 100644 --- a/src/plugins/projectexplorer/devicesupport/idevice.h +++ b/src/plugins/projectexplorer/devicesupport/idevice.h @@ -40,6 +40,7 @@ #include <QVariantMap> QT_BEGIN_NAMESPACE +class QObject; class QWidget; QT_END_NAMESPACE @@ -47,30 +48,18 @@ namespace QSsh { class SshConnectionParameters; } namespace Utils { class PortList; } namespace ProjectExplorer { +class DeviceProcessList; namespace Internal { class IDevicePrivate; } class IDeviceWidget; -class PROJECTEXPLORER_EXPORT DeviceProcess -{ -public: - DeviceProcess() : pid(0) {} - bool operator<(const DeviceProcess &other) const; - - int pid; - QString cmdLine; - QString exe; -}; - class PROJECTEXPLORER_EXPORT DeviceProcessSupport { public: typedef QSharedPointer<const DeviceProcessSupport> Ptr; virtual ~DeviceProcessSupport(); - virtual QString listProcessesCommandLine() const = 0; - virtual QList<DeviceProcess> buildProcessList(const QString &listProcessesReply) const = 0; virtual QString killProcessByPidCommandLine(int pid) const = 0; virtual QString killProcessByNameCommandLine(const QString &filePath) const = 0; }; @@ -125,6 +114,7 @@ public: virtual DeviceProcessSupport::Ptr processSupport() const; virtual PortsGatheringMethod::Ptr portsGatheringMethod() const; + virtual DeviceProcessList *createProcessListModel(QObject *parent = 0) const; enum DeviceState { DeviceReadyToUse, DeviceConnected, DeviceDisconnected, DeviceStateUnknown }; DeviceState deviceState() const; diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp new file mode 100644 index 0000000000000000000000000000000000000000..98656e941dee25596a367c6bf7f19e59c8b7bdb4 --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.cpp @@ -0,0 +1,144 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: http://www.qt-project.org/ +** +** 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. +** +** +**************************************************************************/ +#include "sshdeviceprocesslist.h" + +#include <ssh/sshremoteprocessrunner.h> +#include <utils/qtcassert.h> + +using namespace QSsh; + +namespace ProjectExplorer { + +class SshDeviceProcessList::SshDeviceProcessListPrivate +{ +public: + SshRemoteProcessRunner process; +}; + +SshDeviceProcessList::SshDeviceProcessList(const IDevice::ConstPtr &device, QObject *parent) : + DeviceProcessList(device, parent), d(new SshDeviceProcessListPrivate) +{ +} + +SshDeviceProcessList::~SshDeviceProcessList() +{ + delete d; +} + +void SshDeviceProcessList::doUpdate() +{ + QTC_ASSERT(device()->processSupport(), return); + connect(&d->process, SIGNAL(connectionError()), SLOT(handleConnectionError())); + connect(&d->process, SIGNAL(processClosed(int)), SLOT(handleListProcessFinished(int))); + d->process.run(listProcessesCommandLine().toUtf8(), device()->sshParameters()); +} + +void SshDeviceProcessList::doKillProcess(const DeviceProcess &process) +{ + QTC_ASSERT(device()->processSupport(), return); + connect(&d->process, SIGNAL(connectionError()), SLOT(handleConnectionError())); + connect(&d->process, SIGNAL(processClosed(int)), SLOT(handleKillProcessFinished(int))); + d->process.run(device()->processSupport()->killProcessByPidCommandLine(process.pid).toUtf8(), + device()->sshParameters()); +} + +void SshDeviceProcessList::handleConnectionError() +{ + setFinished(); + reportError(tr("Connection failure: %1").arg(d->process.lastConnectionErrorString())); +} + +void SshDeviceProcessList::handleListProcessFinished(int exitStatus) +{ + setFinished(); + switch (exitStatus) { + case SshRemoteProcess::FailedToStart: + handleProcessError(tr("Error: Process listing command failed to start: %1") + .arg(d->process.processErrorString())); + break; + case SshRemoteProcess::CrashExit: + handleProcessError(tr("Error: Process listing command crashed: %1") + .arg(d->process.processErrorString())); + break; + case SshRemoteProcess::NormalExit: + if (d->process.processExitCode() == 0) { + const QByteArray remoteStdout = d->process.readAllStandardOutput(); + const QString stdoutString + = QString::fromUtf8(remoteStdout.data(), remoteStdout.count()); + reportProcessListUpdated(buildProcessList(stdoutString)); + } else { + handleProcessError(tr("Process listing command failed with exit code %1.") + .arg(d->process.processExitCode())); + } + break; + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status"); + } +} + +void SshDeviceProcessList::handleKillProcessFinished(int exitStatus) +{ + setFinished(); + switch (exitStatus) { + case SshRemoteProcess::FailedToStart: + handleProcessError(tr("Error: Kill process failed to start: %1") + .arg(d->process.processErrorString())); + break; + case SshRemoteProcess::CrashExit: + handleProcessError(tr("Error: Kill process crashed: %1") + .arg(d->process.processErrorString())); + break; + case SshRemoteProcess::NormalExit: { + const int exitCode = d->process.processExitCode(); + if (exitCode == 0) + reportProcessKilled(); + else + handleProcessError(tr("Kill process failed with exit code %1.").arg(exitCode)); + break; + } + default: + Q_ASSERT_X(false, Q_FUNC_INFO, "Invalid exit status"); + } +} + +void SshDeviceProcessList::handleProcessError(const QString &errorMessage) +{ + QString fullMessage = errorMessage; + const QByteArray remoteStderr = d->process.readAllStandardError(); + if (!remoteStderr.isEmpty()) + fullMessage += tr("\nRemote stderr was: %1").arg(QString::fromUtf8(remoteStderr)); + reportError(fullMessage); +} + +void SshDeviceProcessList::setFinished() +{ + d->process.disconnect(this); +} + +} // namespace ProjectExplorer diff --git a/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h new file mode 100644 index 0000000000000000000000000000000000000000..32331557f5751240531d9a5fd72b13d4c6fe6e0c --- /dev/null +++ b/src/plugins/projectexplorer/devicesupport/sshdeviceprocesslist.h @@ -0,0 +1,64 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: http://www.qt-project.org/ +** +** 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. +** +** +**************************************************************************/ +#ifndef SSHDEVICEPROCESSLIST_H +#define SSHDEVICEPROCESSLIST_H + +#include "deviceprocesslist.h" + +namespace ProjectExplorer { + +class PROJECTEXPLORER_EXPORT SshDeviceProcessList : public DeviceProcessList +{ + Q_OBJECT +public: + explicit SshDeviceProcessList(const IDevice::ConstPtr &device, QObject *parent = 0); + ~SshDeviceProcessList(); + +private slots: + void handleConnectionError(); + void handleListProcessFinished(int exitStatus); + void handleKillProcessFinished(int exitStatus); + +private: + virtual QString listProcessesCommandLine() const = 0; + virtual QList<DeviceProcess> buildProcessList(const QString &listProcessesReply) const = 0; + + void doUpdate(); + void doKillProcess(const DeviceProcess &process); + + void handleProcessError(const QString &errorMessage); + void setFinished(); + + class SshDeviceProcessListPrivate; + SshDeviceProcessListPrivate * const d; +}; + +} // namespace ProjectExplorer + +#endif // SSHDEVICEPROCESSLIST_H diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index d27b13f22c4725ca5995e1da1b1b6e93a76b90d2..c733c3cb570d87e980ff918c5e686a26ca97f5be 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -126,7 +126,8 @@ HEADERS += projectexplorer.h \ devicesupport/devicesettingswidget.h \ devicesupport/devicesettingspage.h \ devicesupport/deviceusedportsgatherer.h \ - devicesupport/deviceapplicationrunner.h + devicesupport/deviceapplicationrunner.h \ + devicesupport/sshdeviceprocesslist.h SOURCES += projectexplorer.cpp \ abi.cpp \ @@ -229,7 +230,8 @@ SOURCES += projectexplorer.cpp \ devicesupport/devicesettingswidget.cpp \ devicesupport/devicesettingspage.cpp \ devicesupport/deviceusedportsgatherer.cpp \ - devicesupport/deviceapplicationrunner.cpp + devicesupport/deviceapplicationrunner.cpp \ + devicesupport/sshdeviceprocesslist.cpp FORMS += processstep.ui \ editorsettingspropertiespage.ui \ diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs index d36076c1b506f2aa015081fcce8b6d1c860f5ce3..64fbeb8c2c313cb10cba3993ef0582c3429f6cd7 100644 --- a/src/plugins/projectexplorer/projectexplorer.qbs +++ b/src/plugins/projectexplorer/projectexplorer.qbs @@ -298,6 +298,8 @@ QtcPlugin { "devicesupport/devicefactoryselectiondialog.ui", "devicesupport/deviceprocesslist.cpp", "devicesupport/deviceprocesslist.h", + "devicesupport/sshdeviceprocesslist.cpp", + "devicesupport/sshdeviceprocesslist.h", "devicesupport/deviceprocessesdialog.cpp", "devicesupport/deviceprocessesdialog.h", "devicesupport/deviceprocessesdialog.ui", diff --git a/src/plugins/remotelinux/linuxdevice.cpp b/src/plugins/remotelinux/linuxdevice.cpp index 864e76d03380c612a9017bdfa82a7c402b8174a5..7715e9f3fdea5ceafc5376652fc275c8f86812b8 100644 --- a/src/plugins/remotelinux/linuxdevice.cpp +++ b/src/plugins/remotelinux/linuxdevice.cpp @@ -36,7 +36,7 @@ #include "remotelinux_constants.h" #include <coreplugin/id.h> -#include <projectexplorer/devicesupport/deviceprocesslist.h> +#include <projectexplorer/devicesupport/sshdeviceprocesslist.h> #include <projectexplorer/devicesupport/deviceprocessesdialog.h> #include <ssh/sshconnection.h> #include <utils/portlist.h> @@ -54,9 +54,18 @@ static QString visualizeNull(QString s) return s.replace(QLatin1Char('\0'), QLatin1String("<null>")); } -QString LinuxDeviceProcessSupport::listProcessesCommandLine() const +class LinuxDeviceProcessList : public SshDeviceProcessList { - return QString::fromLatin1( +public: + LinuxDeviceProcessList(const IDevice::ConstPtr &device, QObject *parent) + : SshDeviceProcessList(device, parent) + { + } + +private: + QString listProcessesCommandLine() const + { + return QString::fromLatin1( "for dir in `ls -d /proc/[0123456789]*`; do " "test -d $dir || continue;" // Decrease the likelihood of a race condition. "echo $dir;" @@ -65,50 +74,52 @@ QString LinuxDeviceProcessSupport::listProcessesCommandLine() const "readlink $dir/exe;" "printf '%1''%2';" "done").arg(Delimiter0).arg(Delimiter1); -} + } -QList<DeviceProcess> LinuxDeviceProcessSupport::buildProcessList(const QString &listProcessesReply) const -{ - QList<DeviceProcess> processes; - const QStringList lines = listProcessesReply.split(QString::fromLatin1(Delimiter0) - + QString::fromLatin1(Delimiter1), QString::SkipEmptyParts); - foreach (const QString &line, lines) { - const QStringList elements = line.split(QLatin1Char('\n')); - if (elements.count() < 4) { - qDebug("%s: Expected four list elements, got %d. Line was '%s'.", Q_FUNC_INFO, - elements.count(), qPrintable(visualizeNull(line))); - continue; - } - bool ok; - const int pid = elements.first().mid(6).toInt(&ok); - if (!ok) { - qDebug("%s: Expected number in %s. Line was '%s'.", Q_FUNC_INFO, - qPrintable(elements.first()), qPrintable(visualizeNull(line))); - continue; - } - QString command = elements.at(1); - command.replace(QLatin1Char('\0'), QLatin1Char(' ')); - if (command.isEmpty()) { - const QString &statString = elements.at(2); - const int openParenPos = statString.indexOf(QLatin1Char('(')); - const int closedParenPos = statString.indexOf(QLatin1Char(')'), openParenPos); - if (openParenPos == -1 || closedParenPos == -1) + QList<DeviceProcess> buildProcessList(const QString &listProcessesReply) const + { + QList<DeviceProcess> processes; + const QStringList lines = listProcessesReply.split(QString::fromLatin1(Delimiter0) + + QString::fromLatin1(Delimiter1), QString::SkipEmptyParts); + foreach (const QString &line, lines) { + const QStringList elements = line.split(QLatin1Char('\n')); + if (elements.count() < 4) { + qDebug("%s: Expected four list elements, got %d. Line was '%s'.", Q_FUNC_INFO, + elements.count(), qPrintable(visualizeNull(line))); continue; - command = QLatin1Char('[') - + statString.mid(openParenPos + 1, closedParenPos - openParenPos - 1) - + QLatin1Char(']'); + } + bool ok; + const int pid = elements.first().mid(6).toInt(&ok); + if (!ok) { + qDebug("%s: Expected number in %s. Line was '%s'.", Q_FUNC_INFO, + qPrintable(elements.first()), qPrintable(visualizeNull(line))); + continue; + } + QString command = elements.at(1); + command.replace(QLatin1Char('\0'), QLatin1Char(' ')); + if (command.isEmpty()) { + const QString &statString = elements.at(2); + const int openParenPos = statString.indexOf(QLatin1Char('(')); + const int closedParenPos = statString.indexOf(QLatin1Char(')'), openParenPos); + if (openParenPos == -1 || closedParenPos == -1) + continue; + command = QLatin1Char('[') + + statString.mid(openParenPos + 1, closedParenPos - openParenPos - 1) + + QLatin1Char(']'); + } + + DeviceProcess process; + process.pid = pid; + process.cmdLine = command; + process.exe = elements.at(3); + processes.append(process); } - DeviceProcess process; - process.pid = pid; - process.cmdLine = command; - process.exe = elements.at(3); - processes.append(process); + qSort(processes); + return processes; } +}; - qSort(processes); - return processes; -} QString LinuxDeviceProcessSupport::killProcessByPidCommandLine(int pid) const { @@ -212,11 +223,12 @@ void LinuxDevice::executeAction(Core::Id actionId, QWidget *parent) const if (actionId == Core::Id(Constants::GenericTestDeviceActionId)) d = new LinuxDeviceTestDialog(device, new GenericLinuxDeviceTester, parent); else if (actionId == Core::Id(Constants::GenericRemoteProcessesActionId)) - d = new DeviceProcessesDialog(new DeviceProcessList(device, parent)); + d = new DeviceProcessesDialog(createProcessListModel(parent)); else if (actionId == Core::Id(Constants::GenericDeployKeyToDeviceActionId)) d = PublicKeyDeploymentDialog::createDialog(device, parent); if (d) d->exec(); + delete d; } LinuxDevice::LinuxDevice(const QString &name, Core::Id type, MachineType machineType, @@ -251,4 +263,9 @@ PortsGatheringMethod::Ptr LinuxDevice::portsGatheringMethod() const return LinuxPortsGatheringMethod::Ptr(new LinuxPortsGatheringMethod); } +DeviceProcessList *LinuxDevice::createProcessListModel(QObject *parent) const +{ + return new LinuxDeviceProcessList(sharedFromThis(), parent); +} + } // namespace RemoteLinux diff --git a/src/plugins/remotelinux/linuxdevice.h b/src/plugins/remotelinux/linuxdevice.h index 60a05c85b813697018a2b3b04a09bd181f933dfa..498a79f1ea2a11c43a125667c1acce19e04bfe45 100644 --- a/src/plugins/remotelinux/linuxdevice.h +++ b/src/plugins/remotelinux/linuxdevice.h @@ -46,8 +46,6 @@ namespace Internal { class LinuxDevicePrivate; } class REMOTELINUX_EXPORT LinuxDeviceProcessSupport : public ProjectExplorer::DeviceProcessSupport { public: - QString listProcessesCommandLine() const; - QList<ProjectExplorer::DeviceProcess> buildProcessList(const QString &listProcessesReply) const; QString killProcessByPidCommandLine(int pid) const; QString killProcessByNameCommandLine(const QString &filePath) const; }; @@ -73,6 +71,7 @@ public: ProjectExplorer::DeviceProcessSupport::Ptr processSupport() const; ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const; + ProjectExplorer::DeviceProcessList *createProcessListModel(QObject *parent) const; protected: LinuxDevice() {}