forked from qt-creator/qt-creator
Device support: Let devices create project list model.
Now each device gets to decide in what way a process list is set up and how a process gets killed. This enables e.g. non-SSH based devices to provide process lists. The default implementation provides an empty list. Change-Id: Ibb352cd8a5ea556951b02ba512208daeb3b1e1a6 Reviewed-by: hjk <qthjk@ovi.com>
This commit is contained in:
@@ -210,7 +210,7 @@ void StartGdbServerDialog::attachToDevice()
|
|||||||
if (!device)
|
if (!device)
|
||||||
return;
|
return;
|
||||||
delete d->processList;
|
delete d->processList;
|
||||||
d->processList = new DeviceProcessList(device);
|
d->processList = device->createProcessListModel();
|
||||||
d->proxyModel.setSourceModel(d->processList);
|
d->proxyModel.setSourceModel(d->processList);
|
||||||
connect(d->processList, SIGNAL(error(QString)),
|
connect(d->processList, SIGNAL(error(QString)),
|
||||||
SLOT(handleRemoteError(QString)));
|
SLOT(handleRemoteError(QString)));
|
||||||
|
|||||||
@@ -111,12 +111,12 @@ void MaddeDevice::executeAction(Core::Id actionId, QWidget *parent) const
|
|||||||
if (actionId == Core::Id(MaddeDeviceTestActionId))
|
if (actionId == Core::Id(MaddeDeviceTestActionId))
|
||||||
d = new LinuxDeviceTestDialog(device, new MaddeDeviceTester, parent);
|
d = new LinuxDeviceTestDialog(device, new MaddeDeviceTester, parent);
|
||||||
else if (actionId == Core::Id(MaddeRemoteProcessesActionId))
|
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))
|
else if (actionId == Core::Id(Constants::GenericDeployKeyToDeviceActionId))
|
||||||
d = PublicKeyDeploymentDialog::createDialog(device, parent);
|
d = PublicKeyDeploymentDialog::createDialog(device, parent);
|
||||||
// FIXME: Leak?
|
|
||||||
if (d)
|
if (d)
|
||||||
d->exec();
|
d->exec();
|
||||||
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString MaddeDevice::maddeDisplayType(Core::Id type)
|
QString MaddeDevice::maddeDisplayType(Core::Id type)
|
||||||
|
|||||||
@@ -30,9 +30,6 @@
|
|||||||
#include "deviceprocesslist.h"
|
#include "deviceprocesslist.h"
|
||||||
|
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
#include <ssh/sshremoteprocessrunner.h>
|
|
||||||
|
|
||||||
using namespace QSsh;
|
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
@@ -48,9 +45,7 @@ public:
|
|||||||
{ }
|
{ }
|
||||||
|
|
||||||
const IDevice::ConstPtr device;
|
const IDevice::ConstPtr device;
|
||||||
SshRemoteProcessRunner process;
|
|
||||||
QList<DeviceProcess> remoteProcesses;
|
QList<DeviceProcess> remoteProcesses;
|
||||||
QString errorMsg;
|
|
||||||
State state;
|
State state;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -71,7 +66,7 @@ DeviceProcessList::~DeviceProcessList()
|
|||||||
void DeviceProcessList::update()
|
void DeviceProcessList::update()
|
||||||
{
|
{
|
||||||
QTC_ASSERT(d->state == Inactive, return);
|
QTC_ASSERT(d->state == Inactive, return);
|
||||||
QTC_ASSERT(d->device && d->device->processSupport(), return);
|
QTC_ASSERT(device(), return);
|
||||||
|
|
||||||
if (!d->remoteProcesses.isEmpty()) {
|
if (!d->remoteProcesses.isEmpty()) {
|
||||||
beginRemoveRows(QModelIndex(), 0, d->remoteProcesses.count() - 1);
|
beginRemoveRows(QModelIndex(), 0, d->remoteProcesses.count() - 1);
|
||||||
@@ -79,17 +74,46 @@ void DeviceProcessList::update()
|
|||||||
endRemoveRows();
|
endRemoveRows();
|
||||||
}
|
}
|
||||||
d->state = Listing;
|
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)
|
void DeviceProcessList::killProcess(int row)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(row >= 0 && row < d->remoteProcesses.count(), return);
|
QTC_ASSERT(row >= 0 && row < d->remoteProcesses.count(), return);
|
||||||
QTC_ASSERT(d->state == Inactive, return);
|
QTC_ASSERT(d->state == Inactive, return);
|
||||||
|
QTC_ASSERT(device(), return);
|
||||||
|
|
||||||
d->state = Killing;
|
d->state = Killing;
|
||||||
const int pid = d->remoteProcesses.at(row).pid;
|
doKillProcess(d->remoteProcesses.at(row));
|
||||||
startProcess(d->device->processSupport()->killProcessByPidCommandLine(pid));
|
}
|
||||||
|
|
||||||
|
void DeviceProcessList::doKillProcess(const DeviceProcess &)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(false, qDebug("Process list should be empty"); return);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceProcessList::reportProcessKilled()
|
||||||
|
{
|
||||||
|
QTC_ASSERT(d->state == Killing, return);
|
||||||
|
setFinished();
|
||||||
|
emit processKilled();
|
||||||
}
|
}
|
||||||
|
|
||||||
DeviceProcess DeviceProcessList::at(int row) const
|
DeviceProcess DeviceProcessList::at(int row) const
|
||||||
@@ -97,11 +121,6 @@ DeviceProcess DeviceProcessList::at(int row) const
|
|||||||
return d->remoteProcesses.at(row);
|
return d->remoteProcesses.at(row);
|
||||||
}
|
}
|
||||||
|
|
||||||
IDevice::ConstPtr DeviceProcessList::device() const
|
|
||||||
{
|
|
||||||
return d->device;
|
|
||||||
}
|
|
||||||
|
|
||||||
int DeviceProcessList::rowCount(const QModelIndex &parent) const
|
int DeviceProcessList::rowCount(const QModelIndex &parent) const
|
||||||
{
|
{
|
||||||
return parent.isValid() ? 0 : d->remoteProcesses.count();
|
return parent.isValid() ? 0 : d->remoteProcesses.count();
|
||||||
@@ -134,82 +153,23 @@ QVariant DeviceProcessList::data(const QModelIndex &index, int role) const
|
|||||||
return QVariant();
|
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)
|
|
||||||
{
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceProcessList::startProcess(const QString &cmdLine)
|
|
||||||
{
|
|
||||||
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());
|
|
||||||
}
|
|
||||||
|
|
||||||
void DeviceProcessList::setFinished()
|
void DeviceProcessList::setFinished()
|
||||||
{
|
{
|
||||||
disconnect(&d->process, 0, this, 0);
|
|
||||||
d->state = Inactive;
|
d->state = Inactive;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IDevice::ConstPtr DeviceProcessList::device() const
|
||||||
|
{
|
||||||
|
return d->device;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeviceProcessList::reportError(const QString &message)
|
||||||
|
{
|
||||||
|
QTC_ASSERT(d->state != Inactive, return);
|
||||||
|
setFinished();
|
||||||
|
emit error(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool DeviceProcess::operator <(const DeviceProcess &other) const
|
bool DeviceProcess::operator <(const DeviceProcess &other) const
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -40,6 +40,17 @@ namespace ProjectExplorer {
|
|||||||
|
|
||||||
namespace Internal { class DeviceProcessListPrivate; }
|
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
|
class PROJECTEXPLORER_EXPORT DeviceProcessList : public QAbstractTableModel
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
@@ -51,16 +62,18 @@ public:
|
|||||||
void update();
|
void update();
|
||||||
void killProcess(int row);
|
void killProcess(int row);
|
||||||
DeviceProcess at(int row) const;
|
DeviceProcess at(int row) const;
|
||||||
IDevice::ConstPtr device() const;
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void processListUpdated();
|
void processListUpdated();
|
||||||
void error(const QString &errorMsg);
|
void error(const QString &errorMsg);
|
||||||
void processKilled();
|
void processKilled();
|
||||||
|
|
||||||
private slots:
|
protected:
|
||||||
void handleConnectionError();
|
void reportError(const QString &message);
|
||||||
void handleRemoteProcessFinished(int exitStatus);
|
void reportProcessKilled();
|
||||||
|
void reportProcessListUpdated(const QList<DeviceProcess> &processes);
|
||||||
|
|
||||||
|
IDevice::ConstPtr device() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
int rowCount(const QModelIndex &parent = QModelIndex()) const;
|
||||||
@@ -69,7 +82,10 @@ private:
|
|||||||
int role = Qt::DisplayRole) const;
|
int role = Qt::DisplayRole) const;
|
||||||
QVariant data(const QModelIndex &index, 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();
|
void setFinished();
|
||||||
|
|
||||||
Internal::DeviceProcessListPrivate * const d;
|
Internal::DeviceProcessListPrivate * const d;
|
||||||
|
|||||||
@@ -30,6 +30,7 @@
|
|||||||
#include "idevice.h"
|
#include "idevice.h"
|
||||||
|
|
||||||
#include "devicemanager.h"
|
#include "devicemanager.h"
|
||||||
|
#include "deviceprocesslist.h"
|
||||||
|
|
||||||
#include <coreplugin/id.h>
|
#include <coreplugin/id.h>
|
||||||
#include <ssh/sshconnection.h>
|
#include <ssh/sshconnection.h>
|
||||||
@@ -259,6 +260,11 @@ PortsGatheringMethod::Ptr IDevice::portsGatheringMethod() const
|
|||||||
return PortsGatheringMethod::Ptr();
|
return PortsGatheringMethod::Ptr();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceProcessList *IDevice::createProcessListModel(QObject *parent) const
|
||||||
|
{
|
||||||
|
return new DeviceProcessList(sharedFromThis(), parent);
|
||||||
|
}
|
||||||
|
|
||||||
IDevice::DeviceState IDevice::deviceState() const
|
IDevice::DeviceState IDevice::deviceState() const
|
||||||
{
|
{
|
||||||
return d->deviceState;
|
return d->deviceState;
|
||||||
|
|||||||
@@ -40,6 +40,7 @@
|
|||||||
#include <QVariantMap>
|
#include <QVariantMap>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
class QObject;
|
||||||
class QWidget;
|
class QWidget;
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
|
||||||
@@ -47,30 +48,18 @@ namespace QSsh { class SshConnectionParameters; }
|
|||||||
namespace Utils { class PortList; }
|
namespace Utils { class PortList; }
|
||||||
|
|
||||||
namespace ProjectExplorer {
|
namespace ProjectExplorer {
|
||||||
|
class DeviceProcessList;
|
||||||
|
|
||||||
namespace Internal { class IDevicePrivate; }
|
namespace Internal { class IDevicePrivate; }
|
||||||
|
|
||||||
class IDeviceWidget;
|
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
|
class PROJECTEXPLORER_EXPORT DeviceProcessSupport
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
typedef QSharedPointer<const DeviceProcessSupport> Ptr;
|
typedef QSharedPointer<const DeviceProcessSupport> Ptr;
|
||||||
|
|
||||||
virtual ~DeviceProcessSupport();
|
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 killProcessByPidCommandLine(int pid) const = 0;
|
||||||
virtual QString killProcessByNameCommandLine(const QString &filePath) const = 0;
|
virtual QString killProcessByNameCommandLine(const QString &filePath) const = 0;
|
||||||
};
|
};
|
||||||
@@ -125,6 +114,7 @@ public:
|
|||||||
|
|
||||||
virtual DeviceProcessSupport::Ptr processSupport() const;
|
virtual DeviceProcessSupport::Ptr processSupport() const;
|
||||||
virtual PortsGatheringMethod::Ptr portsGatheringMethod() const;
|
virtual PortsGatheringMethod::Ptr portsGatheringMethod() const;
|
||||||
|
virtual DeviceProcessList *createProcessListModel(QObject *parent = 0) const;
|
||||||
|
|
||||||
enum DeviceState { DeviceReadyToUse, DeviceConnected, DeviceDisconnected, DeviceStateUnknown };
|
enum DeviceState { DeviceReadyToUse, DeviceConnected, DeviceDisconnected, DeviceStateUnknown };
|
||||||
DeviceState deviceState() const;
|
DeviceState deviceState() const;
|
||||||
|
|||||||
@@ -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
|
||||||
@@ -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
|
||||||
@@ -126,7 +126,8 @@ HEADERS += projectexplorer.h \
|
|||||||
devicesupport/devicesettingswidget.h \
|
devicesupport/devicesettingswidget.h \
|
||||||
devicesupport/devicesettingspage.h \
|
devicesupport/devicesettingspage.h \
|
||||||
devicesupport/deviceusedportsgatherer.h \
|
devicesupport/deviceusedportsgatherer.h \
|
||||||
devicesupport/deviceapplicationrunner.h
|
devicesupport/deviceapplicationrunner.h \
|
||||||
|
devicesupport/sshdeviceprocesslist.h
|
||||||
|
|
||||||
SOURCES += projectexplorer.cpp \
|
SOURCES += projectexplorer.cpp \
|
||||||
abi.cpp \
|
abi.cpp \
|
||||||
@@ -229,7 +230,8 @@ SOURCES += projectexplorer.cpp \
|
|||||||
devicesupport/devicesettingswidget.cpp \
|
devicesupport/devicesettingswidget.cpp \
|
||||||
devicesupport/devicesettingspage.cpp \
|
devicesupport/devicesettingspage.cpp \
|
||||||
devicesupport/deviceusedportsgatherer.cpp \
|
devicesupport/deviceusedportsgatherer.cpp \
|
||||||
devicesupport/deviceapplicationrunner.cpp
|
devicesupport/deviceapplicationrunner.cpp \
|
||||||
|
devicesupport/sshdeviceprocesslist.cpp
|
||||||
|
|
||||||
FORMS += processstep.ui \
|
FORMS += processstep.ui \
|
||||||
editorsettingspropertiespage.ui \
|
editorsettingspropertiespage.ui \
|
||||||
|
|||||||
@@ -298,6 +298,8 @@ QtcPlugin {
|
|||||||
"devicesupport/devicefactoryselectiondialog.ui",
|
"devicesupport/devicefactoryselectiondialog.ui",
|
||||||
"devicesupport/deviceprocesslist.cpp",
|
"devicesupport/deviceprocesslist.cpp",
|
||||||
"devicesupport/deviceprocesslist.h",
|
"devicesupport/deviceprocesslist.h",
|
||||||
|
"devicesupport/sshdeviceprocesslist.cpp",
|
||||||
|
"devicesupport/sshdeviceprocesslist.h",
|
||||||
"devicesupport/deviceprocessesdialog.cpp",
|
"devicesupport/deviceprocessesdialog.cpp",
|
||||||
"devicesupport/deviceprocessesdialog.h",
|
"devicesupport/deviceprocessesdialog.h",
|
||||||
"devicesupport/deviceprocessesdialog.ui",
|
"devicesupport/deviceprocessesdialog.ui",
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
#include "remotelinux_constants.h"
|
#include "remotelinux_constants.h"
|
||||||
|
|
||||||
#include <coreplugin/id.h>
|
#include <coreplugin/id.h>
|
||||||
#include <projectexplorer/devicesupport/deviceprocesslist.h>
|
#include <projectexplorer/devicesupport/sshdeviceprocesslist.h>
|
||||||
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
|
#include <projectexplorer/devicesupport/deviceprocessesdialog.h>
|
||||||
#include <ssh/sshconnection.h>
|
#include <ssh/sshconnection.h>
|
||||||
#include <utils/portlist.h>
|
#include <utils/portlist.h>
|
||||||
@@ -54,7 +54,16 @@ static QString visualizeNull(QString s)
|
|||||||
return s.replace(QLatin1Char('\0'), QLatin1String("<null>"));
|
return s.replace(QLatin1Char('\0'), QLatin1String("<null>"));
|
||||||
}
|
}
|
||||||
|
|
||||||
QString LinuxDeviceProcessSupport::listProcessesCommandLine() const
|
class LinuxDeviceProcessList : public SshDeviceProcessList
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LinuxDeviceProcessList(const IDevice::ConstPtr &device, QObject *parent)
|
||||||
|
: SshDeviceProcessList(device, parent)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
QString listProcessesCommandLine() const
|
||||||
{
|
{
|
||||||
return QString::fromLatin1(
|
return QString::fromLatin1(
|
||||||
"for dir in `ls -d /proc/[0123456789]*`; do "
|
"for dir in `ls -d /proc/[0123456789]*`; do "
|
||||||
@@ -67,7 +76,7 @@ QString LinuxDeviceProcessSupport::listProcessesCommandLine() const
|
|||||||
"done").arg(Delimiter0).arg(Delimiter1);
|
"done").arg(Delimiter0).arg(Delimiter1);
|
||||||
}
|
}
|
||||||
|
|
||||||
QList<DeviceProcess> LinuxDeviceProcessSupport::buildProcessList(const QString &listProcessesReply) const
|
QList<DeviceProcess> buildProcessList(const QString &listProcessesReply) const
|
||||||
{
|
{
|
||||||
QList<DeviceProcess> processes;
|
QList<DeviceProcess> processes;
|
||||||
const QStringList lines = listProcessesReply.split(QString::fromLatin1(Delimiter0)
|
const QStringList lines = listProcessesReply.split(QString::fromLatin1(Delimiter0)
|
||||||
@@ -109,6 +118,8 @@ QList<DeviceProcess> LinuxDeviceProcessSupport::buildProcessList(const QString &
|
|||||||
qSort(processes);
|
qSort(processes);
|
||||||
return processes;
|
return processes;
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
QString LinuxDeviceProcessSupport::killProcessByPidCommandLine(int pid) const
|
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))
|
if (actionId == Core::Id(Constants::GenericTestDeviceActionId))
|
||||||
d = new LinuxDeviceTestDialog(device, new GenericLinuxDeviceTester, parent);
|
d = new LinuxDeviceTestDialog(device, new GenericLinuxDeviceTester, parent);
|
||||||
else if (actionId == Core::Id(Constants::GenericRemoteProcessesActionId))
|
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))
|
else if (actionId == Core::Id(Constants::GenericDeployKeyToDeviceActionId))
|
||||||
d = PublicKeyDeploymentDialog::createDialog(device, parent);
|
d = PublicKeyDeploymentDialog::createDialog(device, parent);
|
||||||
if (d)
|
if (d)
|
||||||
d->exec();
|
d->exec();
|
||||||
|
delete d;
|
||||||
}
|
}
|
||||||
|
|
||||||
LinuxDevice::LinuxDevice(const QString &name, Core::Id type, MachineType machineType,
|
LinuxDevice::LinuxDevice(const QString &name, Core::Id type, MachineType machineType,
|
||||||
@@ -251,4 +263,9 @@ PortsGatheringMethod::Ptr LinuxDevice::portsGatheringMethod() const
|
|||||||
return LinuxPortsGatheringMethod::Ptr(new LinuxPortsGatheringMethod);
|
return LinuxPortsGatheringMethod::Ptr(new LinuxPortsGatheringMethod);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DeviceProcessList *LinuxDevice::createProcessListModel(QObject *parent) const
|
||||||
|
{
|
||||||
|
return new LinuxDeviceProcessList(sharedFromThis(), parent);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace RemoteLinux
|
} // namespace RemoteLinux
|
||||||
|
|||||||
@@ -46,8 +46,6 @@ namespace Internal { class LinuxDevicePrivate; }
|
|||||||
class REMOTELINUX_EXPORT LinuxDeviceProcessSupport : public ProjectExplorer::DeviceProcessSupport
|
class REMOTELINUX_EXPORT LinuxDeviceProcessSupport : public ProjectExplorer::DeviceProcessSupport
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
QString listProcessesCommandLine() const;
|
|
||||||
QList<ProjectExplorer::DeviceProcess> buildProcessList(const QString &listProcessesReply) const;
|
|
||||||
QString killProcessByPidCommandLine(int pid) const;
|
QString killProcessByPidCommandLine(int pid) const;
|
||||||
QString killProcessByNameCommandLine(const QString &filePath) const;
|
QString killProcessByNameCommandLine(const QString &filePath) const;
|
||||||
};
|
};
|
||||||
@@ -73,6 +71,7 @@ public:
|
|||||||
|
|
||||||
ProjectExplorer::DeviceProcessSupport::Ptr processSupport() const;
|
ProjectExplorer::DeviceProcessSupport::Ptr processSupport() const;
|
||||||
ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const;
|
ProjectExplorer::PortsGatheringMethod::Ptr portsGatheringMethod() const;
|
||||||
|
ProjectExplorer::DeviceProcessList *createProcessListModel(QObject *parent) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
LinuxDevice() {}
|
LinuxDevice() {}
|
||||||
|
|||||||
Reference in New Issue
Block a user