Add process selector and get log messages displaying
This commit is contained in:
parent
4fb58b4324
commit
733350b143
1
.gitignore
vendored
1
.gitignore
vendored
@ -1,2 +1,3 @@
|
|||||||
dist
|
dist
|
||||||
build
|
build
|
||||||
|
Session.vim
|
||||||
|
@ -10,7 +10,7 @@ add_executable(
|
|||||||
main.cpp
|
main.cpp
|
||||||
mainwindow.cpp
|
mainwindow.cpp
|
||||||
processdata.cpp
|
processdata.cpp
|
||||||
procselector.cpp
|
processselector.cpp
|
||||||
server.cpp
|
server.cpp
|
||||||
traceeventmodel.cpp
|
traceeventmodel.cpp
|
||||||
traceview.cpp
|
traceview.cpp
|
||||||
|
@ -13,11 +13,13 @@
|
|||||||
|
|
||||||
int main(int argc, char **args) {
|
int main(int argc, char **args) {
|
||||||
QApplication app(argc, args);
|
QApplication app(argc, args);
|
||||||
|
app.setApplicationName("Bullock");
|
||||||
|
app.setOrganizationName("DrinkingTea");
|
||||||
|
app.setOrganizationDomain("drinkingtea.net");
|
||||||
|
|
||||||
LogServer server;
|
LogServer server;
|
||||||
|
|
||||||
MainWindow w;
|
MainWindow w;
|
||||||
app.setApplicationName(w.windowTitle());
|
|
||||||
w.show();
|
w.show();
|
||||||
|
|
||||||
QObject::connect(&server, &LogServer::newDataFeed, &w, &MainWindow::addDataFeed);
|
QObject::connect(&server, &LogServer::newDataFeed, &w, &MainWindow::addDataFeed);
|
||||||
|
@ -14,8 +14,6 @@
|
|||||||
#include <QMenuBar>
|
#include <QMenuBar>
|
||||||
#include <QSplitter>
|
#include <QSplitter>
|
||||||
|
|
||||||
#include "traceview.hpp"
|
|
||||||
|
|
||||||
#include "mainwindow.hpp"
|
#include "mainwindow.hpp"
|
||||||
|
|
||||||
MainWindow::MainWindow() {
|
MainWindow::MainWindow() {
|
||||||
@ -33,10 +31,12 @@ MainWindow::MainWindow() {
|
|||||||
auto leftPane = new QWidget(this);
|
auto leftPane = new QWidget(this);
|
||||||
auto leftPaneSplitter = new QSplitter(Qt::Vertical, leftPane);
|
auto leftPaneSplitter = new QSplitter(Qt::Vertical, leftPane);
|
||||||
m_procSelector = new ProcessSelector(leftPaneSplitter);
|
m_procSelector = new ProcessSelector(leftPaneSplitter);
|
||||||
|
connect(m_procSelector, &ProcessSelector::selectionChanged, this, &MainWindow::setProcess);
|
||||||
leftPaneSplitter->addWidget(m_procSelector);
|
leftPaneSplitter->addWidget(m_procSelector);
|
||||||
|
|
||||||
splitter->addWidget(leftPaneSplitter);
|
splitter->addWidget(leftPaneSplitter);
|
||||||
splitter->addWidget(new TraceView(splitter));
|
m_traceView = new TraceView(splitter);
|
||||||
|
splitter->addWidget(m_traceView);
|
||||||
splitter->setStretchFactor(1, 3);
|
splitter->setStretchFactor(1, 3);
|
||||||
|
|
||||||
setCentralWidget(splitter);
|
setCentralWidget(splitter);
|
||||||
@ -47,9 +47,19 @@ MainWindow::~MainWindow() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::addDataFeed(DataFeed *feed) {
|
void MainWindow::addDataFeed(DataFeed *feed) {
|
||||||
m_procData.push_back(feed->procData());
|
|
||||||
auto time = QDateTime::currentDateTime();
|
auto time = QDateTime::currentDateTime();
|
||||||
m_procSelector->addProcess(time.toString());
|
auto procKey = time.toString();
|
||||||
|
m_procData[procKey] = feed->procData();
|
||||||
|
m_procSelector->addProcess(procKey);
|
||||||
|
}
|
||||||
|
|
||||||
|
void MainWindow::setProcess(QString procKey) {
|
||||||
|
if (m_procData.contains(procKey)) {
|
||||||
|
m_currentProc = m_procData[procKey].data();
|
||||||
|
} else {
|
||||||
|
m_currentProc = nullptr;
|
||||||
|
}
|
||||||
|
m_traceView->setProcessData(m_currentProc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::setupMenu() {
|
void MainWindow::setupMenu() {
|
||||||
|
@ -8,15 +8,19 @@
|
|||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
|
|
||||||
#include "procselector.hpp"
|
#include "processselector.hpp"
|
||||||
|
#include "traceview.hpp"
|
||||||
|
|
||||||
#include "server.hpp"
|
#include "server.hpp"
|
||||||
|
|
||||||
class MainWindow: public QMainWindow {
|
class MainWindow: public QMainWindow {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QVector<QSharedPointer<ProcessData>> m_procData;
|
QHash<QString, QSharedPointer<ProcessData>> m_procData;
|
||||||
|
ProcessData *m_currentProc = nullptr;
|
||||||
ProcessSelector *m_procSelector = nullptr;
|
ProcessSelector *m_procSelector = nullptr;
|
||||||
|
TraceView *m_traceView = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
MainWindow();
|
MainWindow();
|
||||||
@ -26,6 +30,9 @@ class MainWindow: public QMainWindow {
|
|||||||
public slots:
|
public slots:
|
||||||
void addDataFeed(DataFeed*);
|
void addDataFeed(DataFeed*);
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void setProcess(QString procKey);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void setupMenu();
|
void setupMenu();
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
#include <QJsonArray>
|
#include <QJsonArray>
|
||||||
|
|
||||||
#include "processdata.hpp"
|
#include "processdata.hpp"
|
||||||
@ -31,10 +32,19 @@ Frame::Frame(QJsonObject frame) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
TraceEvent::TraceEvent(QJsonObject tp) {
|
TraceEvent::TraceEvent(QJsonObject tp) {
|
||||||
this->logMsg = tp["trace_msg"].toString();
|
this->channel = tp["channel"].toString();
|
||||||
|
this->logMsg = tp["log_msg"].toString();
|
||||||
auto frames = tp["frames"].toArray();
|
auto frames = tp["frames"].toArray();
|
||||||
for (auto frame : frames) {
|
for (auto frame : frames) {
|
||||||
this->frames.push_back(frame.toObject());
|
this->frames.push_back(frame.toObject());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString TraceEvent::file() const {
|
||||||
|
return this->frames[0].file;
|
||||||
|
}
|
||||||
|
|
||||||
|
int TraceEvent::line() const {
|
||||||
|
return this->frames[0].line;
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QJsonObject>
|
#include <QJsonObject>
|
||||||
|
#include <QObject>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
#include <QVector>
|
#include <QVector>
|
||||||
|
|
||||||
@ -39,9 +40,22 @@ struct TraceEvent {
|
|||||||
|
|
||||||
TraceEvent(QJsonObject tp = {});
|
TraceEvent(QJsonObject tp = {});
|
||||||
|
|
||||||
|
QString file() const;
|
||||||
|
|
||||||
|
int line() const;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ProcessData {
|
struct ProcessData: public QObject {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
QString cmd;
|
QString cmd;
|
||||||
QVector<TraceEvent> traceEvents;
|
QVector<TraceEvent> traceEvents;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
/**
|
||||||
|
* Emitted whenever a new TraceEvent is added.
|
||||||
|
*/
|
||||||
|
void traceEvent(const TraceEvent&);
|
||||||
};
|
};
|
||||||
|
35
src/processselector.cpp
Normal file
35
src/processselector.cpp
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2018 gtalent2@gmail.com
|
||||||
|
*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QLabel>
|
||||||
|
#include <QVBoxLayout>
|
||||||
|
|
||||||
|
#include "processselector.hpp"
|
||||||
|
|
||||||
|
ProcessSelector::ProcessSelector(QWidget *parent): QWidget(parent) {
|
||||||
|
const auto MostRecent = tr("Most Recent");
|
||||||
|
auto lyt = new QVBoxLayout(this);
|
||||||
|
lyt->addWidget(new QLabel(tr("Processes"), this));
|
||||||
|
lyt->addWidget(m_list);
|
||||||
|
m_list->addItem(MostRecent);
|
||||||
|
m_list->setCurrentRow(RowLatest);
|
||||||
|
connect(m_list, &QListWidget::currentTextChanged, [this, MostRecent](QString txt) {
|
||||||
|
if (txt == MostRecent && m_list->count() > 1) {
|
||||||
|
txt = m_list->item(1)->text();
|
||||||
|
}
|
||||||
|
emit this->selectionChanged(txt);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessSelector::addProcess(QString procKey) {
|
||||||
|
m_list->insertItem(1, procKey);
|
||||||
|
if (m_list->currentRow() == RowLatest) {
|
||||||
|
emit selectionChanged(procKey);
|
||||||
|
}
|
||||||
|
}
|
@ -1,20 +0,0 @@
|
|||||||
|
|
||||||
#include <QLabel>
|
|
||||||
#include <QVBoxLayout>
|
|
||||||
|
|
||||||
#include "procselector.hpp"
|
|
||||||
|
|
||||||
ProcessSelector::ProcessSelector(QWidget *parent): QWidget(parent) {
|
|
||||||
auto lyt = new QVBoxLayout(this);
|
|
||||||
lyt->addWidget(new QLabel(tr("Processes"), this));
|
|
||||||
lyt->addWidget(m_list);
|
|
||||||
m_list->addItem(tr("Most Recent"));
|
|
||||||
m_list->setCurrentRow(RowLatest);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ProcessSelector::addProcess(QString procKey) {
|
|
||||||
m_list->insertItem(1, procKey);
|
|
||||||
if (m_list->currentRow() == RowLatest) {
|
|
||||||
emit selectionChanged(procKey);
|
|
||||||
}
|
|
||||||
}
|
|
@ -32,9 +32,14 @@ void DataFeed::handleInit() {
|
|||||||
|
|
||||||
void DataFeed::read() {
|
void DataFeed::read() {
|
||||||
while (m_dev->bytesAvailable()) {
|
while (m_dev->bytesAvailable()) {
|
||||||
auto doc = QJsonDocument::fromJson(m_dev->readLine());
|
const auto doc = QJsonDocument::fromJson(m_dev->readLine());
|
||||||
if (m_procData) {
|
if (m_procData) {
|
||||||
m_procData->traceEvents.push_back(doc.object());
|
const auto msg = doc.object();
|
||||||
|
if (msg["type"] == "TraceEvent") {
|
||||||
|
const auto te = msg["data"].toObject();
|
||||||
|
m_procData->traceEvents.push_back(te);
|
||||||
|
emit m_procData->traceEvent(m_procData->traceEvents.last());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,20 +6,83 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
|
||||||
#include "traceeventmodel.hpp"
|
#include "traceeventmodel.hpp"
|
||||||
|
|
||||||
int TraceEventModel::rowCount(const QModelIndex &parent) const {
|
int TraceEventModel::rowCount(const QModelIndex &parent) const {
|
||||||
if (m_procData) {
|
return m_traceEvents.size();
|
||||||
return m_procData->traceEvents.size();
|
|
||||||
} else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int TraceEventModel::columnCount(const QModelIndex &parent) const {
|
int TraceEventModel::columnCount(const QModelIndex &parent) const {
|
||||||
return Column::End;
|
return Column::End;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVariant TraceEventModel::data(const QModelIndex &index, int role) const {
|
QVariant TraceEventModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
||||||
return {};
|
if (role != Qt::DisplayRole) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (orientation == Qt::Horizontal) {
|
||||||
|
switch (section) {
|
||||||
|
case Column::Channel:
|
||||||
|
return tr("Channel");
|
||||||
|
case Column::Source:
|
||||||
|
return tr("Source");
|
||||||
|
case Column::Message:
|
||||||
|
return tr("Message");
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant TraceEventModel::data(const QModelIndex &index, int role) const {
|
||||||
|
if (!index.isValid()) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (index.row() >= m_traceEvents.size() || index.row() < 0) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (role == Qt::DisplayRole) {
|
||||||
|
const auto &te = m_traceEvents[index.row()];
|
||||||
|
|
||||||
|
switch (index.column()) {
|
||||||
|
case Column::Channel:
|
||||||
|
return te.channel;
|
||||||
|
case Column::Source:
|
||||||
|
return QString("%1:%2").arg(te.file()).arg(te.line());
|
||||||
|
case Column::Message:
|
||||||
|
return te.logMsg;
|
||||||
|
default:
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TraceEventModel::setProcessData(ProcessData *data) {
|
||||||
|
beginResetModel();
|
||||||
|
m_traceEvents.clear();
|
||||||
|
if (m_procData) {
|
||||||
|
disconnect(m_procData, &ProcessData::traceEvent, this, &TraceEventModel::addEvent);
|
||||||
|
}
|
||||||
|
m_procData = data;
|
||||||
|
if (m_procData) {
|
||||||
|
for (const auto &te : m_procData->traceEvents) {
|
||||||
|
m_traceEvents.push_back(te);
|
||||||
|
}
|
||||||
|
connect(m_procData, &ProcessData::traceEvent, this, &TraceEventModel::addEvent);
|
||||||
|
}
|
||||||
|
endResetModel();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TraceEventModel::addEvent(const TraceEvent &event) {
|
||||||
|
auto index = m_traceEvents.size();
|
||||||
|
beginInsertRows(QModelIndex(), index, index);
|
||||||
|
m_traceEvents.push_back(event);
|
||||||
|
endInsertRows();
|
||||||
}
|
}
|
||||||
|
@ -10,19 +10,22 @@
|
|||||||
|
|
||||||
#include "processdata.hpp"
|
#include "processdata.hpp"
|
||||||
|
|
||||||
#include <QAbstractItemModel>
|
#include <QAbstractTableModel>
|
||||||
|
|
||||||
|
|
||||||
class TraceEventModel: public QAbstractItemModel {
|
class TraceEventModel: public QAbstractTableModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
private:
|
public:
|
||||||
enum Column {
|
enum Column {
|
||||||
Channel,
|
Channel = 0,
|
||||||
|
Source,
|
||||||
Message,
|
Message,
|
||||||
End
|
End
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
QVector<TraceEvent> m_traceEvents;
|
||||||
ProcessData *m_procData = nullptr;
|
ProcessData *m_procData = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -30,5 +33,12 @@ class TraceEventModel: public QAbstractItemModel {
|
|||||||
|
|
||||||
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
int columnCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
|
||||||
|
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||||
|
|
||||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||||
|
|
||||||
|
void setProcessData(ProcessData *data);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void addEvent(const TraceEvent &event);
|
||||||
};
|
};
|
||||||
|
@ -6,13 +6,46 @@
|
|||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
#include <QHBoxLayout>
|
#include <QHBoxLayout>
|
||||||
#include <QTableView>
|
#include <QHeaderView>
|
||||||
|
#include <QSettings>
|
||||||
|
|
||||||
#include "traceview.hpp"
|
#include "traceview.hpp"
|
||||||
|
|
||||||
TraceView::TraceView(QWidget *parent): QWidget(parent) {
|
TraceView::TraceView(QWidget *parent): QWidget(parent) {
|
||||||
auto lyt = new QHBoxLayout;
|
auto lyt = new QHBoxLayout;
|
||||||
setLayout(lyt);
|
setLayout(lyt);
|
||||||
lyt->addWidget(new QTableView(this));
|
m_eventTable = new QTableView(this);
|
||||||
|
m_model = new TraceEventModel;
|
||||||
|
m_eventTable->setModel(m_model);
|
||||||
|
m_eventTable->horizontalHeader()->setStretchLastSection(true);
|
||||||
|
m_eventTable->verticalHeader()->hide();
|
||||||
|
m_eventTable->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||||
|
lyt->addWidget(m_eventTable);
|
||||||
|
readState();
|
||||||
|
}
|
||||||
|
|
||||||
|
TraceView::~TraceView() {
|
||||||
|
writeState();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TraceView::readState() {
|
||||||
|
QSettings settings;
|
||||||
|
settings.beginGroup("TraceView");
|
||||||
|
m_eventTable->horizontalHeader()->restoreState(settings.value("eventTableState").toByteArray());
|
||||||
|
m_eventTable->horizontalHeader()->restoreGeometry(settings.value("eventTableGeometry").toByteArray());
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TraceView::writeState() {
|
||||||
|
QSettings settings;
|
||||||
|
settings.beginGroup("TraceView");
|
||||||
|
settings.setValue("eventTableState", m_eventTable->horizontalHeader()->saveState());
|
||||||
|
settings.setValue("eventTableGeometry", m_eventTable->horizontalHeader()->saveGeometry());
|
||||||
|
settings.endGroup();
|
||||||
|
}
|
||||||
|
|
||||||
|
void TraceView::setProcessData(ProcessData *data) {
|
||||||
|
m_model->setProcessData(data);
|
||||||
}
|
}
|
||||||
|
@ -8,12 +8,30 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include <QTableView>
|
||||||
#include <QWidget>
|
#include <QWidget>
|
||||||
|
|
||||||
|
#include "traceeventmodel.hpp"
|
||||||
|
|
||||||
|
#include "processdata.hpp"
|
||||||
|
|
||||||
class TraceView: public QWidget {
|
class TraceView: public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
private:
|
||||||
|
QTableView *m_eventTable;
|
||||||
|
TraceEventModel *m_model = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
TraceView(QWidget *parent = nullptr);
|
TraceView(QWidget *parent = nullptr);
|
||||||
|
|
||||||
|
~TraceView();
|
||||||
|
|
||||||
|
void setProcessData(ProcessData *data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void readState();
|
||||||
|
|
||||||
|
void writeState();
|
||||||
|
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user