Commit da0b6b81 authored by Christian Kandeler's avatar Christian Kandeler Committed by hjk
Browse files

Device support: Implement process listing for the Desktop device.



Unix only for now. Windows to follow later.

Change-Id: I2a5742373f8c849ba3852c933780f9bfa96ba2de
Reviewed-by: default avatarhjk <qthjk@ovi.com>
parent a0fa7fd3
......@@ -32,9 +32,18 @@
#include "projectexplorerconstants.h"
#include "deviceprocesslist.h"
#ifdef Q_OS_UNIX
#include "localunixprocesslist.h"
#endif
#include <QCoreApplication>
namespace ProjectExplorer {
namespace Internal {
} // namespace Internal
using namespace Internal;
DesktopDevice::DesktopDevice() : IDevice(Core::Id(Constants::DESKTOP_DEVICE_TYPE),
IDevice::AutoDetected,
......@@ -80,6 +89,24 @@ void DesktopDevice::executeAction(Core::Id actionId, QWidget *parent) const
Q_UNUSED(parent);
}
bool DesktopDevice::canCreateProcessModel() const
{
#ifdef Q_OS_UNIX
return true;
#else
return false;
#endif
}
DeviceProcessList *DesktopDevice::createProcessListModel(QObject *parent) const
{
#ifdef Q_OS_UNIX
return new Internal::LocalUnixProcessList(sharedFromThis(), parent);
#else
return 0;
#endif
}
IDevice::Ptr DesktopDevice::clone() const
{
return Ptr(new DesktopDevice(*this));
......
......@@ -51,6 +51,8 @@ public:
QList<Core::Id> actionIds() const;
QString displayNameForActionId(Core::Id actionId) const;
void executeAction(Core::Id actionId, QWidget *parent = 0) const;
bool canCreateProcessModel() const;
DeviceProcessList *createProcessListModel(QObject *parent) const;
IDevice::Ptr clone() const;
......
......@@ -50,9 +50,6 @@ public:
QSortFilterProxyModel proxyModel;
};
} // namespace Internal
using namespace Internal;
DeviceProcessesDialog::DeviceProcessesDialog(DeviceProcessList *processList, QWidget *parent)
: QDialog(parent), d(new DeviceProcessesDialogPrivate(processList))
......@@ -133,4 +130,5 @@ void DeviceProcessesDialog::handleSelectionChanged()
d->ui.killProcessButton->setEnabled(d->ui.treeView->selectionModel()->hasSelection());
}
} // namespace Internal
} // namespace RemoteLinux
......@@ -38,7 +38,8 @@ namespace ProjectExplorer {
class DeviceProcessList;
namespace Internal { class DeviceProcessesDialogPrivate; }
namespace Internal {
class DeviceProcessesDialogPrivate;
class DeviceProcessesDialog : public QDialog
{
......@@ -61,6 +62,7 @@ private:
Internal::DeviceProcessesDialogPrivate * const d;
};
} // namespace Internal
} // namespace RemoteLinux
#endif // REMOTELINUXPROCESSESDIALOG_H
/**************************************************************************
**
** 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 "localunixprocesslist.h"
#include <QProcess>
#include <QTimer>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <signal.h>
namespace ProjectExplorer {
namespace Internal {
const int PsFieldWidth = 50;
LocalUnixProcessList::LocalUnixProcessList(const IDevice::ConstPtr &device, QObject *parent)
: DeviceProcessList(device, parent),
m_psProcess(new QProcess(this))
{
connect(m_psProcess, SIGNAL(error(QProcess::ProcessError)), SLOT(handlePsError()));
connect(m_psProcess, SIGNAL(finished(int)), SLOT(handlePsFinished()));
}
void LocalUnixProcessList::doUpdate()
{
// We assume Desktop Unix systems to have a POSIX-compliant ps.
// We need the padding because the command field can contain spaces, so we cannot split on those.
m_psProcess->start(QString::fromLocal8Bit("ps -e -o pid=%1 -o comm=%1 -o args=%1")
.arg(QString(PsFieldWidth, QChar('x'))));
}
void LocalUnixProcessList::handlePsFinished()
{
QString errorString;
if (m_psProcess->exitStatus() == QProcess::CrashExit) {
errorString = tr("The ps process crashed.");
} else if (m_psProcess->exitCode() != 0) {
errorString = tr("The ps process failed with exit code %1.").arg(m_psProcess->exitCode());
} else {
const QString output = QString::fromLocal8Bit(m_psProcess->readAllStandardOutput());
QStringList lines = output.split(QLatin1Char('\n'), QString::SkipEmptyParts);
lines.removeFirst(); // Headers
QList<DeviceProcess> processes;
foreach (const QString &line, lines) {
if (line.count() < 2*PsFieldWidth) {
qDebug("%s: Ignoring malformed line", Q_FUNC_INFO);
continue;
}
DeviceProcess p;
p.pid = line.mid(0, PsFieldWidth).trimmed().toInt();
p.exe = line.mid(PsFieldWidth, PsFieldWidth).trimmed();
p.cmdLine = line.mid(2*PsFieldWidth).trimmed();
processes << p;
}
reportProcessListUpdated(processes);
return;
}
const QByteArray &stderrData = m_psProcess->readAllStandardError();
if (!stderrData.isEmpty()) {
errorString += QLatin1Char('\n') + tr("The stderr output was: '%1'")
.arg(QString::fromLocal8Bit(stderrData));
}
reportError(errorString);
}
void LocalUnixProcessList::handlePsError()
{
// Other errors are handled in the finished() handler.
if (m_psProcess->error() == QProcess::FailedToStart)
reportError(m_psProcess->errorString());
}
void LocalUnixProcessList::doKillProcess(const DeviceProcess &process)
{
if (kill(process.pid, SIGKILL) == -1)
m_error = QString::fromLocal8Bit(strerror(errno));
else
m_error.clear();
QTimer::singleShot(0, this, SLOT(reportDelayedKillStatus()));
}
void LocalUnixProcessList::reportDelayedKillStatus()
{
if (m_error.isEmpty())
reportProcessKilled();
else
reportError(m_error);
}
} // namespace Internal
} // namespace RemoteLinux
/**************************************************************************
**
** 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 LOCALUNIXPROCESSLIST_H
#define LOCALUNIXPROCESSLIST_H
#include "deviceprocesslist.h"
#include <QString>
QT_BEGIN_NAMESPACE
class QProcess;
QT_END_NAMESPACE
namespace ProjectExplorer {
namespace Internal {
class LocalUnixProcessList : public DeviceProcessList
{
Q_OBJECT
public:
LocalUnixProcessList(const IDevice::ConstPtr &device, QObject *parent = 0);
private slots:
void handlePsError();
void handlePsFinished();
void reportDelayedKillStatus();
private:
void doUpdate();
void doKillProcess(const DeviceProcess &process);
QProcess * const m_psProcess;
QString m_error;
};
} // namespace Internal
} // namespace RemoteLinux
#endif // LOCALUNIXPROCESSLIST_H
......@@ -272,6 +272,11 @@ equals(TEST, 1) {
outputparser_test.h
}
unix {
SOURCES += devicesupport/localunixprocesslist.cpp
HEADERS += devicesupport/localunixprocesslist.h
}
macx:LIBS += -framework Carbon
RESOURCES += projectexplorer.qrc
......
......@@ -331,6 +331,11 @@ QtcPlugin {
]
}
Group {
condition: qbs.targetOS === "linux" || qbs.targetOS === "mac"
files: [ "devicesupport/localunixprocesslist.h", "devicesupport/localunixprocesslist.cpp" ]
}
ProductModule {
Depends { name: "cpp" }
Depends { name: "Qt"; submodules: ["network"] }
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment