File 0001-Port-scripting-to-Qt-WebEngine.patch of Package libksysguard5

From 9c16eca77f731a12d2c9e1a2bcb668c0a5a22c54 Mon Sep 17 00:00:00 2001
From: Fabian Vogt <fabian@ritter-vogt.de>
Date: Sat, 1 Sep 2018 18:41:59 +0200
Subject: [PATCH] Port scripting to Qt WebEngine

Summary:
Unfortunately it relies on Qt WebKit features quite intensely, so a few
godawful hacks were necessary to make it work. Most of those are needed
to workaround restrictions of QWebChannel as bridge to the browser page.

We gain:
+ Independence from WebKit
+ Support for newer JS and HTML features in scripts

We lose:
- Performance (especially memory use)
- Independence from WebEngine
- Sanity

Test Plan:
Tested the detailed memory info pages on a few processes, info is
correct and the page seems to work fully.

Reviewers: #plasma, davidedmundson

Reviewed By: #plasma, davidedmundson

Subscribers: davidedmundson, plasma-devel

Tags: #plasma

Differential Revision: https://phabricator.kde.org/D15209
---
 CMakeLists.txt           |  10 +--
 config-ksysguard.h.cmake |   4 +-
 processui/CMakeLists.txt |   4 +-
 processui/scripting.cpp  | 182 +++++++++++++++++++++++++++++----------
 processui/scripting.h    | 109 ++++++++++++-----------
 5 files changed, 204 insertions(+), 105 deletions(-)

diff --git a/CMakeLists.txt b/CMakeLists.txt
index e5c73d6..4c39308 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -10,10 +10,10 @@ find_package(ECM 1.2.0 REQUIRED NO_MODULE)
 set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR})
 
 find_package(Qt5 REQUIRED CONFIG COMPONENTS DBus Network Widgets)
-find_package(Qt5WebKitWidgets CONFIG)
-set_package_properties(Qt5WebKitWidgets PROPERTIES
-                       URL "git://gitorious.org/qt/qtwebkit.git"
-                       DESCRIPTION "Qt Webkit module (web browsing engine)"
+find_package(Qt5WebEngineWidgets ${QT_MIN_VERSION} CONFIG)
+set_package_properties(Qt5WebEngineWidgets PROPERTIES
+                       URL "git://code.qt.org/qt/qtwebenginewidgets.git"
+                       DESCRIPTION "Qt WebEngine module (web browsing engine)"
                        TYPE OPTIONAL
                        PURPOSE "Used by the HTML-based GUI ksysguard library"
                       )
@@ -71,7 +71,7 @@ endif()
 
 set(HAVE_X11 ${X11_FOUND})
 set(HAVE_XRES ${X11_XRes_FOUND})
-set(HAVE_QTWEBKITWIDGETS ${Qt5WebKitWidgets_FOUND})
+set(HAVE_QTWEBENGINEWIDGETS ${Qt5WebEngineWidgets_FOUND})
 configure_file(config-ksysguard.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-ksysguard.h )
 
 add_subdirectory( lsofui )
diff --git a/config-ksysguard.h.cmake b/config-ksysguard.h.cmake
index e5b8609..ad648f1 100644
--- a/config-ksysguard.h.cmake
+++ b/config-ksysguard.h.cmake
@@ -10,8 +10,8 @@
 /* Define to 1 if you have the X11 xres file */
 #cmakedefine HAVE_XRES 1
 
-/* Define if you have QtWebKitWidgets */
-#cmakedefine01 HAVE_QTWEBKITWIDGETS
+/* Define if you have QtWebEngineWidgets */
+#cmakedefine01 HAVE_QTWEBENGINEWIDGETS
 
 /* Define if you have X11 at all */
 #cmakedefine01 HAVE_X11
diff --git a/processui/CMakeLists.txt b/processui/CMakeLists.txt
index 4dfcbd4..54faf93 100644
--- a/processui/CMakeLists.txt
+++ b/processui/CMakeLists.txt
@@ -53,8 +53,8 @@ if(X11_FOUND)
     target_link_libraries(processui PRIVATE Qt5::X11Extras KF5::WindowSystem)
 endif()
 
-if(Qt5WebKitWidgets_FOUND)
-    target_link_libraries(processui PRIVATE Qt5::WebKitWidgets)
+if(Qt5WebEngineWidgets_FOUND)
+    target_link_libraries(processui PRIVATE Qt5::WebEngineWidgets)
 endif()
 
 if(NOT HAVE_CLOCK_GETTIME_C)
diff --git a/processui/scripting.cpp b/processui/scripting.cpp
index 9cb1658..68aa579 100644
--- a/processui/scripting.cpp
+++ b/processui/scripting.cpp
@@ -1,7 +1,8 @@
 /*
     KSysGuard, the KDE System Guard
 
-	Copyright (c) 2009 John Tapsell <john.tapsell@kde.org>
+    Copyright (c) 2009 John Tapsell <john.tapsell@kde.org>
+    Copyright (c) 2018 Fabian Vogt <fabian@ritter-vogt.de>
 
     This library is free software; you can redistribute it and/or
     modify it under the terms of the GNU Library General Public
@@ -42,11 +43,32 @@
 #include <QMessageBox>
 #include <QDialogButtonBox>
 
-#if HAVE_QTWEBKITWIDGETS
-#include <QWebView>
-#include <QWebFrame>
+#if HAVE_QTWEBENGINEWIDGETS
+#include <QWebChannel>
+#include <QWebEngineSettings>
+#include <QWebEngineView>
+#include <QWebEngineProfile>
+#include <QWebEngineScriptCollection>
+#include <QWebEngineUrlRequestInterceptor>
 #endif
 
+class RemoteUrlInterceptor : public QWebEngineUrlRequestInterceptor {
+public:
+    RemoteUrlInterceptor(QObject *parent) : QWebEngineUrlRequestInterceptor(parent) {}
+    void interceptRequest(QWebEngineUrlRequestInfo &info) override
+    {
+        // Block non-GET/HEAD requests
+        if(!QStringList({QStringLiteral("GET"), QStringLiteral("HEAD")})
+           .contains(QString::fromLatin1(info.requestMethod())))
+            info.block(true);
+
+        // Block remote URLs
+        if(!QStringList({QStringLiteral("blob"), QStringLiteral("data"),
+                         QStringLiteral("file")}).contains(info.requestUrl().scheme()))
+            info.block(true);
+    }
+};
+
 class ScriptingHtmlDialog : public QDialog {
     public:
         ScriptingHtmlDialog(QWidget *parent) : QDialog(parent) {
@@ -56,44 +78,22 @@ class ScriptingHtmlDialog : public QDialog {
             connect(buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept);
             connect(buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject);
 
-#if HAVE_QTWEBKITWIDGETS
+#if HAVE_QTWEBENGINEWIDGETS
             QVBoxLayout *layout = new QVBoxLayout;
             layout->addWidget(&m_webView);
             layout->addWidget(buttonBox);
             setLayout(layout);
-            (void)minimumSizeHint(); //Force the dialog to be laid out now
             layout->setContentsMargins(0,0,0,0);
-            m_webView.settings()->setOfflineStoragePath(QString());
-            m_webView.settings()->setObjectCacheCapacities(0,0,0);
-            m_webView.settings()->setAttribute(QWebSettings::PluginsEnabled, false);
-            m_webView.settings()->setAttribute(QWebSettings::DeveloperExtrasEnabled, false);
-            m_webView.page()->setNetworkAccessManager(nullptr); //Disable talking to remote servers
-            m_webView.page()->mainFrame()->setScrollBarPolicy(Qt::Horizontal, Qt::ScrollBarAsNeeded);
-            m_webView.page()->mainFrame()->setScrollBarPolicy(Qt::Vertical, Qt::ScrollBarAsNeeded);
-
-            // inject a style sheet that follows system colors, otherwise we might end up with black text on dark gray background
-            const QString styleSheet = QStringLiteral(
-                "body { background: %1; color: %2; }" \
-                "a { color: %3; }" \
-                "a:visited { color: %4; } "
-            ).arg(palette().background().color().name(),
-                  palette().text().color().name(),
-                  palette().link().color().name(),
-                  palette().linkVisited().color().name());
-
-            // you can only provide a user style sheet url, so we turn it into a data url here
-            const QUrl dataUrl(QStringLiteral("data:text/css;charset=utf-8;base64,") + QString::fromLatin1(styleSheet.toUtf8().toBase64()));
-
-            m_webView.settings()->setUserStyleSheetUrl(dataUrl);
-
+            m_webView.settings()->setAttribute(QWebEngineSettings::PluginsEnabled, false);
+            m_webView.page()->profile()->setRequestInterceptor(new RemoteUrlInterceptor(this));
 #endif
         }
-#if HAVE_QTWEBKITWIDGETS
-        QWebView *webView() {
+#if HAVE_QTWEBENGINEWIDGETS
+        QWebEngineView *webView() {
             return &m_webView;
         }
     protected:
-        QWebView m_webView;
+        QWebEngineView m_webView;
 #endif
 };
 
@@ -127,11 +127,15 @@ void Scripting::runScript(const QString &path, const QString &name) {
     mScriptPath = path;
     mScriptName = name;
 
-#if HAVE_QTWEBKITWIDGETS
-    QUrl fileName = QUrl::fromLocalFile(path + "index.html");
+#if HAVE_QTWEBENGINEWIDGETS
+    QUrl fileName = QUrl::fromLocalFile(path + QStringLiteral("index.html"));
     if(!mScriptingHtmlDialog) {
         mScriptingHtmlDialog = new ScriptingHtmlDialog(this);
+        mWebChannel = new QWebChannel(mScriptingHtmlDialog);
         connect(mScriptingHtmlDialog, &QDialog::rejected, this, &Scripting::stopAllScripts);
+        // Only show after page loaded to allow for layouting
+        mScriptingHtmlDialog->connect(mScriptingHtmlDialog->webView(), &QWebEngineView::loadFinished,
+                                      mScriptingHtmlDialog, &ScriptingHtmlDialog::show);
 
         QAction *refreshAction = new QAction(QStringLiteral("refresh"), mScriptingHtmlDialog);
         refreshAction->setShortcut(QKeySequence::Refresh);
@@ -145,23 +149,107 @@ void Scripting::runScript(const QString &path, const QString &name) {
         mScriptingHtmlDialog->addAction(zoomOutAction);
     }
 
-    //Make the process information available to the script
-    mScriptingHtmlDialog->webView()->load(fileName);
-    mScriptingHtmlDialog->show();
-    connect(mScriptingHtmlDialog->webView()->page()->mainFrame(), &QWebFrame::javaScriptWindowObjectCleared, this, &Scripting::setupJavascriptObjects);
+    // Make the process information available to the script
+    QWebEngineProfile *profile = mScriptingHtmlDialog->webView()->page()->profile();
+    QFile webChannelJsFile(QStringLiteral(":/qtwebchannel/qwebchannel.js"));
+    webChannelJsFile.open(QIODevice::ReadOnly);
+    QString webChannelJs = QString::fromUtf8(webChannelJsFile.readAll());
+
+    /* Warning: Awful hack ahead!
+     * WebChannel does not allow synchonous calls so we need to make
+     * asynchronous calls synchronous.
+     * The conversion is achieved by caching the result of all readFile
+     * and fileExists calls and restarting the script on every result until
+     * all requests can be fulfilled synchronously.
+     * Another challenge is that WebEngine does not support reading
+     * files from /proc over file:// (they are always empty) so we need
+     * to keep using the ProcessObject helper methods.
+     */
+    webChannelJs.append(QStringLiteral(R"JS(
+new QWebChannel(window.qt.webChannelTransport, function(channel) {
+    window.process = channel.objects.process;
+    window.process.realReadFile = window.process.readFile;
+    window.process.realFileExists = window.process.fileExists;
+    var files = {}; // Map of all read files. null means does not exist
+    window.process.fileExists = function(name, cb) {
+        if(cb) return window.process.realFileExists(name, cb);
+        if (files[name] === null)
+            return false; // Definitely does not exist
+        if (typeof(files[name]) == 'string')
+            return true; // Definitely exists
+
+        window.process.realFileExists(name, function(r) {
+            if(!r) {
+                files[name] = null;
+                refresh();
+                return;
+            }
+            window.process.realReadFile(name, function(r) {
+                files[name] = r;
+                refresh();
+            });
+        });
+
+        return true; // Might exist
+    };
+    window.process.readFile = function(name,cb) {
+        if(cb) return window.process.realReadFile(name, cb);
+        if (typeof(files[name]) == 'string')
+            return files[name]; // From cache
+
+        window.process.fileExists(name); // Fill the cache
+        return '';
+    };
+    refresh && refresh();
+});)JS"));
+
+    QWebEngineScript webChannelScript;
+    webChannelScript.setSourceCode(webChannelJs);
+    webChannelScript.setName(QStringLiteral("qwebchannel.js"));
+    webChannelScript.setWorldId(QWebEngineScript::MainWorld);
+    webChannelScript.setInjectionPoint(QWebEngineScript::DocumentCreation);
+    webChannelScript.setRunsOnSubFrames(false);
+
+    profile->scripts()->insert(webChannelScript);
+
+    // Inject a style sheet that follows system colors, otherwise we might end up with black text on dark gray background
+    const QString styleSheet = QStringLiteral(
+        "body { background: %1; color: %2; }" \
+        "a { color: %3; }" \
+        "a:visited { color: %4; } "
+    ).arg(palette().background().color().name(),
+          palette().text().color().name(),
+          palette().link().color().name(),
+          palette().linkVisited().color().name());
+
+    QString styleSheetJs = QStringLiteral("\nvar node = document.createElement('style');"
+                        "node.innerHTML = '%1';"
+                        "document.body.appendChild(node);").arg(styleSheet);
+
+    QWebEngineScript styleSheetScript;
+    styleSheetScript.setSourceCode(styleSheetJs);
+    styleSheetScript.setName(QStringLiteral("stylesheet.js"));
+    styleSheetScript.setWorldId(QWebEngineScript::MainWorld);
+    styleSheetScript.setInjectionPoint(QWebEngineScript::DocumentReady);
+    styleSheetScript.setRunsOnSubFrames(false);
+
+    profile->scripts()->insert(styleSheetScript);
+
     setupJavascriptObjects();
+
+    mScriptingHtmlDialog->webView()->load(fileName);
 #else
-    QMessageBox::critical(this, i18n("QtWebKitWidgets not available"),
-            i18n("KSysGuard library was compiled without QtWebKitWidgets, please contact your distribution."));
+    QMessageBox::critical(this, i18n("QtWebEngineWidgets not available"),
+            i18n("KSysGuard library was compiled without QtWebEngineWidgets, please contact your distribution."));
 #endif
 }
-#if HAVE_QTWEBKITWIDGETS
+#if HAVE_QTWEBENGINEWIDGETS
 void Scripting::zoomIn() {
-    QWebView *webView = mScriptingHtmlDialog->webView();
+    QWebEngineView *webView = mScriptingHtmlDialog->webView();
     webView->setZoomFactor( webView->zoomFactor() * 1.1 );
 }
 void Scripting::zoomOut() {
-    QWebView *webView = mScriptingHtmlDialog->webView();
+    QWebEngineView *webView = mScriptingHtmlDialog->webView();
     if(webView->zoomFactor() > 0.1) //Prevent it getting too small
         webView->setZoomFactor( webView->zoomFactor() / 1.1 );
 }
@@ -169,14 +257,16 @@ void Scripting::zoomOut() {
 void Scripting::refreshScript() {
     //Call any refresh function, if it exists
     mProcessList->processModel()->update(0, KSysGuard::Processes::XMemory);
-    if(mScriptingHtmlDialog && mScriptingHtmlDialog->webView() && mScriptingHtmlDialog->webView()->page() && mScriptingHtmlDialog->webView()->page()->mainFrame()) {
-        mScriptingHtmlDialog->webView()->page()->mainFrame()->evaluateJavaScript(QStringLiteral("refresh();"));
+    mProcessObject->anythingChanged();
+    if(mScriptingHtmlDialog && mScriptingHtmlDialog->webView() && mScriptingHtmlDialog->webView()->page()) {
+        mScriptingHtmlDialog->webView()->page()->runJavaScript(QStringLiteral("refresh && refresh();"));
     }
 }
 void Scripting::setupJavascriptObjects() {
     mProcessList->processModel()->update(0, KSysGuard::Processes::XMemory);
     mProcessObject = new ProcessObject(mProcessList->processModel(), mPid);
-    mScriptingHtmlDialog->webView()->page()->mainFrame()->addToJavaScriptWindowObject(QStringLiteral("process"), mProcessObject, QWebFrame::ScriptOwnership);
+    mWebChannel->registerObject(QStringLiteral("process"), mProcessObject);
+    mScriptingHtmlDialog->webView()->page()->setWebChannel(mWebChannel);
 }
 #endif
 void Scripting::stopAllScripts()
diff --git a/processui/scripting.h b/processui/scripting.h
index 2a02f26..70fb2cb 100644
--- a/processui/scripting.h
+++ b/processui/scripting.h
@@ -34,6 +34,7 @@ class QAction;
 class ScriptingHtmlDialog; //Defined in scripting.cpp file
 class KSysGuardProcessList;
 class ProcessObject;
+class QWebChannel;
 
 class Scripting : public QWidget {
   Q_OBJECT
@@ -55,7 +56,7 @@ class Scripting : public QWidget {
   private Q_SLOTS:
     /** Run the script associated with the QAction that called this slot */
     void runScriptSlot();
-#if HAVE_QTWEBKITWIDGETS
+#if HAVE_QTWEBENGINEWIDGETS
     void setupJavascriptObjects();
     void refreshScript();
     void zoomIn();
@@ -64,6 +65,8 @@ class Scripting : public QWidget {
   private:
     /** This is created on the fly as needed, and deleted when no longer used */
     ScriptingHtmlDialog *mScriptingHtmlDialog;
+    /** Used to expose mProcessObject to the WebEnginePage */
+    QWebChannel *mWebChannel;
     /** The parent process list to script for */
     KSysGuardProcessList * const mProcessList;
     /** List of context menu actions that are created by loadContextMenu() */
@@ -75,60 +78,62 @@ class Scripting : public QWidget {
     qlonglong mPid;
 };
 
+// QWebChannel only reloads properties on demand, so we need a signal.
+#define P_PROPERTY(x) Q_PROPERTY(x NOTIFY anythingChanged)
 #define PROPERTY(Type,Name) Type Name() const { KSysGuard::Process *process = mModel->getProcess(mPid); if(process) return process->Name(); else return Type();}
 
 class ProcessObject : public QObject {
     Q_OBJECT
     public:
-       Q_PROPERTY(qlonglong pid READ pid WRITE setPid)                 /* Add functionality to 'set' the pid to change which process to read from */
-       Q_PROPERTY(qlonglong ppid READ parentPid)                       /* Map 'ppid' to 'parentPid' to give it a nicer scripting name */
-       Q_PROPERTY(QString name READ name)                              /* Defined below to return the first word of the name */
-       Q_PROPERTY(QString fullname READ fullname)                      /* Defined below to return 'name' */
-       Q_PROPERTY(qlonglong rss READ vmRSS)                            /* Map 'rss' to 'vmRSS' just to give it a nicer scripting name */
-       Q_PROPERTY(qlonglong urss READ vmURSS)                          /* Map 'urss' to 'vmURSS' just to give it a nicer scripting name */
-       Q_PROPERTY(int numThreads READ numThreads)                      PROPERTY(int, numThreads)
-       Q_PROPERTY(qlonglong fsgid READ fsgid)                          PROPERTY(qlonglong, fsgid)
-       Q_PROPERTY(qlonglong parentPid READ parentPid)                  PROPERTY(qlonglong, parentPid)
-       Q_PROPERTY(QString login READ login)                            PROPERTY(QString, login)
-       Q_PROPERTY(qlonglong uid READ uid)                              PROPERTY(qlonglong, uid)
-       Q_PROPERTY(qlonglong euid READ euid)                            PROPERTY(qlonglong, euid)
-       Q_PROPERTY(qlonglong suid READ suid)                            PROPERTY(qlonglong, suid)
-       Q_PROPERTY(qlonglong fsuid READ fsuid)                          PROPERTY(qlonglong, fsuid)
-       Q_PROPERTY(qlonglong gid READ gid)                              PROPERTY(qlonglong, gid)
-       Q_PROPERTY(qlonglong egid READ egid)                            PROPERTY(qlonglong, egid)
-       Q_PROPERTY(qlonglong sgid READ sgid)                            PROPERTY(qlonglong, sgid)
-       Q_PROPERTY(qlonglong tracerpid READ tracerpid)                  PROPERTY(qlonglong, tracerpid)
-       Q_PROPERTY(QByteArray tty READ tty)                             PROPERTY(QByteArray, tty)
-       Q_PROPERTY(qlonglong userTime READ userTime)                    PROPERTY(qlonglong, userTime)
-       Q_PROPERTY(qlonglong sysTime READ sysTime)                      PROPERTY(qlonglong, sysTime)
-       Q_PROPERTY(int userUsage READ userUsage)                        PROPERTY(int, userUsage)
-       Q_PROPERTY(int sysUsage READ sysUsage)                          PROPERTY(int, sysUsage)
-       Q_PROPERTY(int totalUserUsage READ totalUserUsage)              PROPERTY(int, totalUserUsage)
-       Q_PROPERTY(int totalSysUsage READ totalSysUsage)                PROPERTY(int, totalSysUsage)
-       Q_PROPERTY(int numChildren READ numChildren)                    PROPERTY(int, numChildren)
-       Q_PROPERTY(int niceLevel READ niceLevel)                        PROPERTY(int, niceLevel)
-       Q_PROPERTY(int scheduler READ scheduler)                        PROPERTY(int, scheduler)
-       Q_PROPERTY(int ioPriorityClass READ ioPriorityClass)            PROPERTY(int, ioPriorityClass)
-       Q_PROPERTY(int ioniceLevel READ ioniceLevel)                    PROPERTY(int, ioniceLevel)
-       Q_PROPERTY(qlonglong vmSize READ vmSize)                        PROPERTY(qlonglong, vmSize)
-       Q_PROPERTY(qlonglong vmRSS READ vmRSS)                          PROPERTY(qlonglong, vmRSS)
-       Q_PROPERTY(qlonglong vmURSS READ vmURSS)                        PROPERTY(qlonglong, vmURSS)
-       Q_PROPERTY(qlonglong pixmapBytes READ pixmapBytes)              PROPERTY(qlonglong, pixmapBytes)
-       Q_PROPERTY(bool hasManagedGuiWindow READ hasManagedGuiWindow)   PROPERTY(bool, hasManagedGuiWindow)
-       Q_PROPERTY(QString command READ command)                        PROPERTY(QString, command)
-       Q_PROPERTY(qlonglong status READ status)                        PROPERTY(qlonglong, status)
-       Q_PROPERTY(qlonglong ioCharactersRead READ ioCharactersRead)    PROPERTY(qlonglong, ioCharactersRead)
-       Q_PROPERTY(qlonglong ioCharactersWritten READ ioCharactersWritten)                  PROPERTY(qlonglong, ioCharactersWritten)
-       Q_PROPERTY(qlonglong ioReadSyscalls READ ioReadSyscalls)                            PROPERTY(qlonglong, ioReadSyscalls)
-       Q_PROPERTY(qlonglong ioWriteSyscalls READ ioWriteSyscalls)                          PROPERTY(qlonglong, ioWriteSyscalls)
-       Q_PROPERTY(qlonglong ioCharactersActuallyRead READ ioCharactersActuallyRead)        PROPERTY(qlonglong, ioCharactersActuallyRead)
-       Q_PROPERTY(qlonglong ioCharactersActuallyWritten READ ioCharactersActuallyWritten)  PROPERTY(qlonglong, ioCharactersActuallyWritten)
-       Q_PROPERTY(qlonglong ioCharactersReadRate READ ioCharactersReadRate)                PROPERTY(qlonglong, ioCharactersReadRate)
-       Q_PROPERTY(qlonglong ioCharactersWrittenRate READ ioCharactersWrittenRate)          PROPERTY(qlonglong, ioCharactersWrittenRate)
-       Q_PROPERTY(qlonglong ioReadSyscallsRate READ ioReadSyscallsRate)                    PROPERTY(qlonglong, ioReadSyscallsRate)
-       Q_PROPERTY(qlonglong ioWriteSyscallsRate READ ioWriteSyscallsRate)                  PROPERTY(qlonglong, ioWriteSyscallsRate)
-       Q_PROPERTY(qlonglong ioCharactersActuallyReadRate READ ioCharactersActuallyReadRate)        PROPERTY(qlonglong, ioCharactersActuallyReadRate)
-       Q_PROPERTY(qlonglong ioCharactersActuallyWrittenRate READ ioCharactersActuallyWrittenRate)  PROPERTY(qlonglong, ioCharactersActuallyWrittenRate)
+       P_PROPERTY(qlonglong pid READ pid WRITE setPid)                 /* Add functionality to 'set' the pid to change which process to read from */
+       P_PROPERTY(qlonglong ppid READ parentPid)                       /* Map 'ppid' to 'parentPid' to give it a nicer scripting name */
+       P_PROPERTY(QString name READ name)                              /* Defined below to return the first word of the name */
+       P_PROPERTY(QString fullname READ fullname)                      /* Defined below to return 'name' */
+       P_PROPERTY(qlonglong rss READ vmRSS)                            /* Map 'rss' to 'vmRSS' just to give it a nicer scripting name */
+       P_PROPERTY(qlonglong urss READ vmURSS)                          /* Map 'urss' to 'vmURSS' just to give it a nicer scripting name */
+       P_PROPERTY(int numThreads READ numThreads)                      PROPERTY(int, numThreads)
+       P_PROPERTY(qlonglong fsgid READ fsgid)                          PROPERTY(qlonglong, fsgid)
+       P_PROPERTY(qlonglong parentPid READ parentPid)                  PROPERTY(qlonglong, parentPid)
+       P_PROPERTY(QString login READ login)                            PROPERTY(QString, login)
+       P_PROPERTY(qlonglong uid READ uid)                              PROPERTY(qlonglong, uid)
+       P_PROPERTY(qlonglong euid READ euid)                            PROPERTY(qlonglong, euid)
+       P_PROPERTY(qlonglong suid READ suid)                            PROPERTY(qlonglong, suid)
+       P_PROPERTY(qlonglong fsuid READ fsuid)                          PROPERTY(qlonglong, fsuid)
+       P_PROPERTY(qlonglong gid READ gid)                              PROPERTY(qlonglong, gid)
+       P_PROPERTY(qlonglong egid READ egid)                            PROPERTY(qlonglong, egid)
+       P_PROPERTY(qlonglong sgid READ sgid)                            PROPERTY(qlonglong, sgid)
+       P_PROPERTY(qlonglong tracerpid READ tracerpid)                  PROPERTY(qlonglong, tracerpid)
+       P_PROPERTY(QByteArray tty READ tty)                             PROPERTY(QByteArray, tty)
+       P_PROPERTY(qlonglong userTime READ userTime)                    PROPERTY(qlonglong, userTime)
+       P_PROPERTY(qlonglong sysTime READ sysTime)                      PROPERTY(qlonglong, sysTime)
+       P_PROPERTY(int userUsage READ userUsage)                        PROPERTY(int, userUsage)
+       P_PROPERTY(int sysUsage READ sysUsage)                          PROPERTY(int, sysUsage)
+       P_PROPERTY(int totalUserUsage READ totalUserUsage)              PROPERTY(int, totalUserUsage)
+       P_PROPERTY(int totalSysUsage READ totalSysUsage)                PROPERTY(int, totalSysUsage)
+       P_PROPERTY(int numChildren READ numChildren)                    PROPERTY(int, numChildren)
+       P_PROPERTY(int niceLevel READ niceLevel)                        PROPERTY(int, niceLevel)
+       P_PROPERTY(int scheduler READ scheduler)                        PROPERTY(int, scheduler)
+       P_PROPERTY(int ioPriorityClass READ ioPriorityClass)            PROPERTY(int, ioPriorityClass)
+       P_PROPERTY(int ioniceLevel READ ioniceLevel)                    PROPERTY(int, ioniceLevel)
+       P_PROPERTY(qlonglong vmSize READ vmSize)                        PROPERTY(qlonglong, vmSize)
+       P_PROPERTY(qlonglong vmRSS READ vmRSS)                          PROPERTY(qlonglong, vmRSS)
+       P_PROPERTY(qlonglong vmURSS READ vmURSS)                        PROPERTY(qlonglong, vmURSS)
+       P_PROPERTY(qlonglong pixmapBytes READ pixmapBytes)              PROPERTY(qlonglong, pixmapBytes)
+       P_PROPERTY(bool hasManagedGuiWindow READ hasManagedGuiWindow)   PROPERTY(bool, hasManagedGuiWindow)
+       P_PROPERTY(QString command READ command)                        PROPERTY(QString, command)
+       P_PROPERTY(qlonglong status READ status)                        PROPERTY(qlonglong, status)
+       P_PROPERTY(qlonglong ioCharactersRead READ ioCharactersRead)    PROPERTY(qlonglong, ioCharactersRead)
+       P_PROPERTY(qlonglong ioCharactersWritten READ ioCharactersWritten)                  PROPERTY(qlonglong, ioCharactersWritten)
+       P_PROPERTY(qlonglong ioReadSyscalls READ ioReadSyscalls)                            PROPERTY(qlonglong, ioReadSyscalls)
+       P_PROPERTY(qlonglong ioWriteSyscalls READ ioWriteSyscalls)                          PROPERTY(qlonglong, ioWriteSyscalls)
+       P_PROPERTY(qlonglong ioCharactersActuallyRead READ ioCharactersActuallyRead)        PROPERTY(qlonglong, ioCharactersActuallyRead)
+       P_PROPERTY(qlonglong ioCharactersActuallyWritten READ ioCharactersActuallyWritten)  PROPERTY(qlonglong, ioCharactersActuallyWritten)
+       P_PROPERTY(qlonglong ioCharactersReadRate READ ioCharactersReadRate)                PROPERTY(qlonglong, ioCharactersReadRate)
+       P_PROPERTY(qlonglong ioCharactersWrittenRate READ ioCharactersWrittenRate)          PROPERTY(qlonglong, ioCharactersWrittenRate)
+       P_PROPERTY(qlonglong ioReadSyscallsRate READ ioReadSyscallsRate)                    PROPERTY(qlonglong, ioReadSyscallsRate)
+       P_PROPERTY(qlonglong ioWriteSyscallsRate READ ioWriteSyscallsRate)                  PROPERTY(qlonglong, ioWriteSyscallsRate)
+       P_PROPERTY(qlonglong ioCharactersActuallyReadRate READ ioCharactersActuallyReadRate)        PROPERTY(qlonglong, ioCharactersActuallyReadRate)
+       P_PROPERTY(qlonglong ioCharactersActuallyWrittenRate READ ioCharactersActuallyWrittenRate)  PROPERTY(qlonglong, ioCharactersActuallyWrittenRate)
 
         ProcessObject(ProcessModel * processModel, int pid);
         void update(KSysGuard::Process *process);
@@ -141,6 +146,10 @@ class ProcessObject : public QObject {
         public Q_SLOTS:
         bool fileExists(const QString &filename);
         QString readFile(const QString &filename);
+
+    Q_SIGNALS:
+        void anythingChanged();
+
     private:
         int mPid;
         ProcessModel *mModel;
-- 
2.18.0

openSUSE Build Service is sponsored by