aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVitaly Wool <vitaly.wool@konsulko.com>2019-04-08 12:45:42 +0200
committerVitaly Wool <vitaly.wool@konsulko.com>2019-04-08 12:47:51 +0200
commit22a7ffb93ee7ef8d0c05e86e99fb1c70efca0888 (patch)
tree9bd9dc211d5d72c9fa73db4e1835cc88df635344
parent122bcc295d054a733585996e859dea870ba5ca88 (diff)
Implement system load visualization
Implement system load visualization in TaskManager as a separate tab showing average system load graph basing on the info provided by the backend. Change-Id: I81359185516ebb1b6218bfd9ca53f1d76dfddeb4 Signed-off-by: Vitaly Wool <vitaly.wool@konsulko.com>
-rw-r--r--app/app.pro2
-rw-r--r--app/main.cpp5
-rw-r--r--app/main.qml252
-rw-r--r--app/taskmanager.cpp22
-rw-r--r--app/taskmanager.h4
5 files changed, 196 insertions, 89 deletions
diff --git a/app/app.pro b/app/app.pro
index 345fc5b..3607728 100644
--- a/app/app.pro
+++ b/app/app.pro
@@ -1,6 +1,6 @@
TARGET = taskmanager
-QT = quickcontrols2 websockets
+QT = quickcontrols2 websockets charts
SOURCES += \
main.cpp \
diff --git a/app/main.cpp b/app/main.cpp
index c4d4bba..9a3a1ce 100644
--- a/app/main.cpp
+++ b/app/main.cpp
@@ -7,6 +7,7 @@
#include <QtQml/qqml.h>
#include <QQuickWindow>
#include <QQmlApplicationEngine>
+#include <QApplication>
#include <libhomescreen.hpp>
#include <qlibwindowmanager.h>
#include <taskmanager.h>
@@ -17,8 +18,8 @@ int main(int argc, char *argv[])
{
QString graphic_role = QString("utility");
QString myname = QString("TaskManager");
-
- QGuiApplication app(argc, argv);
+
+ QApplication app(argc, argv);
QCommandLineParser parser;
parser.addPositionalArgument("port", app.translate("main", "port for binding"));
diff --git a/app/main.qml b/app/main.qml
index a76aaa8..7e76265 100644
--- a/app/main.qml
+++ b/app/main.qml
@@ -4,6 +4,7 @@ import QtQuick.Controls 1.4
import QtQuick.Controls 2.0 as NewControls
import QtQuick.Layouts 1.1
import TaskManager 1.0
+import QtCharts 2.2
Window {
id: root
@@ -43,7 +44,11 @@ Window {
}
onShowProcessInfo: {
- infoPopup.infoText = info_;
+ mainTabview.getTab(0).item.updateInfo(info_);
+ }
+
+ onUpdateLoadAverage: {
+ mainTabview.getTab(1).item.tempAdd(value_);
}
}
@@ -51,102 +56,177 @@ Window {
id: libraryModel
}
- Rectangle {
- id: mainview
- width: parent.width
- height: parent.height
-
- Row {
- id: buttonRow
- width: parent.width
- anchors.top: mainview.top
-
- RowLayout {
- id: buttonRowLayout
- spacing: 6
-
- NewControls.Popup {
- id: infoPopup
- x: 200
- y: 200
- width: 300
- height: 200
- modal: true
- focus: true
- closePolicy: NewControls.Popup.CloseOnPressOutsideParent
- property var infoText: "Getting extra information for process"
- function doOpen(tid) {
- taskmgr.getExtraInfo(tid)
- infoPopup.open()
- }
- contentItem: Text {
- text: infoPopup.infoText
- }
+ TabView {
+ id: mainTabview
+ currentIndex: 0
+ anchors.fill: parent
+
+ Tab {
+ id: processesTab
+ active: true
+ anchors.fill: parent
+ title: "Processes"
+
+ Rectangle {
+ id: procsView
+ width: parent.width
+ height: parent.height
+
+ function updateInfo(info_)
+ {
+ infoPopup.infoText = info_;
}
- Button {
- id: infoButton
- text: "Info"
- enabled: tableView.currentRow != -1
- onClicked: infoPopup.doOpen(libraryModel.get(tableView.currentRow).tid)
+ Row {
+ id: buttonRow
+ width: parent.width
+ anchors.top: mainTabview.top
+
+ RowLayout {
+ id: buttonRowLayout
+ spacing: 6
+
+ NewControls.Popup {
+ id: infoPopup
+ x: 200
+ y: 200
+ width: 300
+ height: 200
+ modal: true
+ focus: true
+ closePolicy: NewControls.Popup.CloseOnPressOutsideParent
+ property var infoText: "Getting extra information for process"
+ function doOpen(tid) {
+ taskmgr.getExtraInfo(tid)
+ infoPopup.open()
+ }
+ contentItem: Text {
+ text: infoPopup.infoText
+ }
+ }
+
+ Button {
+ id: infoButton
+ text: "Info"
+ enabled: tableView.currentRow != -1
+ onClicked: infoPopup.doOpen(libraryModel.get(tableView.currentRow).tid)
+ }
+
+ Button {
+ id: killButton
+ text: "Kill"
+ enabled: tableView.currentRow != -1
+ onClicked: {
+ tableView.selection.forEach( function(rowIndex) {
+ taskmgr.kill(libraryModel.get(rowIndex).tid)}
+ )
+ tableView.selection.clear()
+ }
+ }
+ }
}
- Button {
- id: killButton
- text: "Kill"
- enabled: tableView.currentRow != -1
- onClicked: {
- tableView.selection.forEach( function(rowIndex) {
- taskmgr.kill(libraryModel.get(rowIndex).tid)}
- )
- tableView.selection.clear()
+ TableView {
+ id: tableView
+ height: parent.height - buttonRow.height
+ width: parent.width
+ anchors.top: buttonRow.bottom
+
+ TableViewColumn {
+ role: "cmd"
+ title: "Process"
+ width: 150
+ }
+ TableViewColumn {
+ role: "tid"
+ title: "ID"
+ width: 80
+ }
+ TableViewColumn {
+ role: "user"
+ title: "User"
+ width: 80
}
+ TableViewColumn {
+ role: "system_cpu"
+ title: "System %"
+ width: 100
+ }
+ TableViewColumn {
+ role: "user_cpu"
+ title: "User %"
+ width: 100
+ }
+ TableViewColumn {
+ role: "resident_memory"
+ title: "Memory"
+ width: 100
+ }
+ TableViewColumn {
+ role: "state"
+ title: "State"
+ width: 90
+ }
+ model: libraryModel
}
}
}
- TableView {
- id: tableView
- height: parent.height - buttonRow.height
- width: parent.width
- anchors.top: buttonRow.bottom
+ Tab {
+ id: systemTab
+ active: true
+ anchors.fill: parent
+ title: "System"
+
+ ChartView {
+ id: chartView
+ title: "System load average"
+ width: parent.width
+ height: parent.height / 2
+ legend.visible: false
+ antialiasing: true
+
+ LineSeries {
+ id: loadSeries
+
+ axisX: DateTimeAxis {
+ id: timeAxis
+ labelsVisible: false
+ format: "hh:mm"
+ }
- TableViewColumn {
- role: "cmd"
- title: "Process"
- width: 150
- }
- TableViewColumn {
- role: "tid"
- title: "ID"
- width: 80
- }
- TableViewColumn {
- role: "user"
- title: "User"
- width: 80
- }
- TableViewColumn {
- role: "system_cpu"
- title: "System %"
- width: 100
- }
- TableViewColumn {
- role: "user_cpu"
- title: "User %"
- width: 100
- }
- TableViewColumn {
- role: "resident_memory"
- title: "Memory"
- width: 100
- }
- TableViewColumn {
- role: "state"
- title: "State"
- width: 90
+ axisY: ValueAxis {
+ id: valueAxis
+ max: 2
+ min: 0
+ tickCount: 3
+ }
+
+ XYPoint { x: new Date().getTime(); y: 0 }
+ XYPoint { x: (new Date().getTime()+ 10); y: 0 }
+
+ }
+
+ function tempAdd(value_)
+ {
+ var time_ = new Date();
+
+ if (value_ > valueAxis.max)
+ valueAxis.max = value_;
+
+ loadSeries.append(time_.getTime(), value_);
+ timeAxis.max = time_;
+
+ if (loadSeries.count > 1800)
+ {
+ loadSeries.remove(0);
+ time_.setMinutes(time_.getMinutes() - 30);
+ timeAxis.min = time_;
+ }
+
+ chartView.update();
+ }
}
- model: libraryModel
}
}
}
diff --git a/app/taskmanager.cpp b/app/taskmanager.cpp
index ece6d83..5726388 100644
--- a/app/taskmanager.cpp
+++ b/app/taskmanager.cpp
@@ -28,6 +28,11 @@ void TaskManager::onConnected()
timer = new QTimer();
connect(timer, SIGNAL(timeout()), this, SLOT(query()));
timer->start(3000);
+
+ loadAvg();
+ loadAvgTimer = new QTimer();
+ connect(loadAvgTimer, SIGNAL(timeout()), this, SLOT(loadAvg()));
+ loadAvgTimer->start(1000);
}
void TaskManager::kill(int tid) {
callService("kill_process", QJsonValue(tid));
@@ -37,6 +42,10 @@ void TaskManager::getExtraInfo(int tid) {
callService("get_extra_info", QJsonValue(tid));
}
+void TaskManager::loadAvg() {
+ callService("get_load_avg", QJsonValue());
+}
+
void TaskManager::query() {
callService("get_process_list",
QJsonValue(QJsonObject({{"processes", QJsonValue()}})));
@@ -71,6 +80,10 @@ void TaskManager::ProcessResponse(Message *message)
QJsonObject info = message->replyData()["info"].toObject();
ProcessResponseExtraInfo(info);
}
+ if (QString::compare(msgType, "loadAvgInfo") == 0) {
+ QJsonObject loadInfo = message->replyData()["loadInfo"].toObject();
+ ProcessResponseLoadAvg(loadInfo);
+ }
// more response types to follow
}
@@ -144,3 +157,12 @@ void TaskManager::ProcessResponseExtraInfo(QJsonObject &info)
emit showProcessInfo(infoString);
}
+
+void TaskManager::ProcessResponseLoadAvg(QJsonObject &loadInfo)
+{
+ if (loadInfo.size() == 0) {
+ return;
+ }
+
+ emit updateLoadAverage(loadInfo["value"].toDouble());
+}
diff --git a/app/taskmanager.h b/app/taskmanager.h
index 0bd53d5..180c379 100644
--- a/app/taskmanager.h
+++ b/app/taskmanager.h
@@ -22,18 +22,21 @@ public:
Q_INVOKABLE void kill(int tid);
Q_INVOKABLE void getExtraInfo(int tid);
QTimer *timer;
+ QTimer *loadAvgTimer;
signals:
void updateProcess(const QString& cmd_, int tid_, int euid_, double scpu_, double ucpu_, double resident_memory_, const QString& state_);
void addProcess(const QString& cmd_, int tid_, int euid_, double scpu_, double ucpu_, double resident_memory_, const QString& state_);
void removeProcess(int tid_);
void showProcessInfo(const QString info_);
+ void updateLoadAverage(double value_);
private slots:
void query();
void callService(const QString& ccommand, QJsonValue value);
void onConnected();
void onMessageReceived(MessageType type, Message *message);
+ void loadAvg();
private:
MessageEngine *m_loop;
@@ -42,6 +45,7 @@ private:
void ProcessResponse(Message *message);
void ProcessResponseTasklist(QJsonArray& processes);
void ProcessResponseExtraInfo(QJsonObject& info);
+ void ProcessResponseLoadAvg(QJsonObject& loadInfo);
};
#endif // TASKMANAGER_H