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
|
||||
build
|
||||
Session.vim
|
||||
|
@ -10,7 +10,7 @@ add_executable(
|
||||
main.cpp
|
||||
mainwindow.cpp
|
||||
processdata.cpp
|
||||
procselector.cpp
|
||||
processselector.cpp
|
||||
server.cpp
|
||||
traceeventmodel.cpp
|
||||
traceview.cpp
|
||||
|
@ -13,11 +13,13 @@
|
||||
|
||||
int main(int argc, char **args) {
|
||||
QApplication app(argc, args);
|
||||
app.setApplicationName("Bullock");
|
||||
app.setOrganizationName("DrinkingTea");
|
||||
app.setOrganizationDomain("drinkingtea.net");
|
||||
|
||||
LogServer server;
|
||||
|
||||
MainWindow w;
|
||||
app.setApplicationName(w.windowTitle());
|
||||
w.show();
|
||||
|
||||
QObject::connect(&server, &LogServer::newDataFeed, &w, &MainWindow::addDataFeed);
|
||||
|
@ -14,8 +14,6 @@
|
||||
#include <QMenuBar>
|
||||
#include <QSplitter>
|
||||
|
||||
#include "traceview.hpp"
|
||||
|
||||
#include "mainwindow.hpp"
|
||||
|
||||
MainWindow::MainWindow() {
|
||||
@ -33,10 +31,12 @@ MainWindow::MainWindow() {
|
||||
auto leftPane = new QWidget(this);
|
||||
auto leftPaneSplitter = new QSplitter(Qt::Vertical, leftPane);
|
||||
m_procSelector = new ProcessSelector(leftPaneSplitter);
|
||||
connect(m_procSelector, &ProcessSelector::selectionChanged, this, &MainWindow::setProcess);
|
||||
leftPaneSplitter->addWidget(m_procSelector);
|
||||
|
||||
splitter->addWidget(leftPaneSplitter);
|
||||
splitter->addWidget(new TraceView(splitter));
|
||||
m_traceView = new TraceView(splitter);
|
||||
splitter->addWidget(m_traceView);
|
||||
splitter->setStretchFactor(1, 3);
|
||||
|
||||
setCentralWidget(splitter);
|
||||
@ -47,9 +47,19 @@ MainWindow::~MainWindow() {
|
||||
}
|
||||
|
||||
void MainWindow::addDataFeed(DataFeed *feed) {
|
||||
m_procData.push_back(feed->procData());
|
||||
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() {
|
||||
|
@ -8,15 +8,19 @@
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
#include "procselector.hpp"
|
||||
#include "processselector.hpp"
|
||||
#include "traceview.hpp"
|
||||
|
||||
#include "server.hpp"
|
||||
|
||||
class MainWindow: public QMainWindow {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QVector<QSharedPointer<ProcessData>> m_procData;
|
||||
QHash<QString, QSharedPointer<ProcessData>> m_procData;
|
||||
ProcessData *m_currentProc = nullptr;
|
||||
ProcessSelector *m_procSelector = nullptr;
|
||||
TraceView *m_traceView = nullptr;
|
||||
|
||||
public:
|
||||
MainWindow();
|
||||
@ -26,6 +30,9 @@ class MainWindow: public QMainWindow {
|
||||
public slots:
|
||||
void addDataFeed(DataFeed*);
|
||||
|
||||
private slots:
|
||||
void setProcess(QString procKey);
|
||||
|
||||
private:
|
||||
void setupMenu();
|
||||
|
||||
|
@ -6,6 +6,7 @@
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
#include <QJsonArray>
|
||||
|
||||
#include "processdata.hpp"
|
||||
@ -31,10 +32,19 @@ Frame::Frame(QJsonObject frame) {
|
||||
}
|
||||
|
||||
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();
|
||||
for (auto frame : frames) {
|
||||
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
|
||||
|
||||
#include <QJsonObject>
|
||||
#include <QObject>
|
||||
#include <QStringList>
|
||||
#include <QVector>
|
||||
|
||||
@ -39,9 +40,22 @@ struct TraceEvent {
|
||||
|
||||
TraceEvent(QJsonObject tp = {});
|
||||
|
||||
QString file() const;
|
||||
|
||||
int line() const;
|
||||
|
||||
};
|
||||
|
||||
struct ProcessData {
|
||||
struct ProcessData: public QObject {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QString cmd;
|
||||
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() {
|
||||
while (m_dev->bytesAvailable()) {
|
||||
auto doc = QJsonDocument::fromJson(m_dev->readLine());
|
||||
const auto doc = QJsonDocument::fromJson(m_dev->readLine());
|
||||
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/.
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include "traceeventmodel.hpp"
|
||||
|
||||
int TraceEventModel::rowCount(const QModelIndex &parent) const {
|
||||
if (m_procData) {
|
||||
return m_procData->traceEvents.size();
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
return m_traceEvents.size();
|
||||
}
|
||||
|
||||
int TraceEventModel::columnCount(const QModelIndex &parent) const {
|
||||
return Column::End;
|
||||
}
|
||||
|
||||
QVariant TraceEventModel::data(const QModelIndex &index, int role) const {
|
||||
return {};
|
||||
QVariant TraceEventModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
||||
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 <QAbstractItemModel>
|
||||
#include <QAbstractTableModel>
|
||||
|
||||
|
||||
class TraceEventModel: public QAbstractItemModel {
|
||||
class TraceEventModel: public QAbstractTableModel {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
public:
|
||||
enum Column {
|
||||
Channel,
|
||||
Channel = 0,
|
||||
Source,
|
||||
Message,
|
||||
End
|
||||
};
|
||||
|
||||
private:
|
||||
QVector<TraceEvent> m_traceEvents;
|
||||
ProcessData *m_procData = nullptr;
|
||||
|
||||
public:
|
||||
@ -30,5 +33,12 @@ class TraceEventModel: public QAbstractItemModel {
|
||||
|
||||
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;
|
||||
|
||||
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/.
|
||||
*/
|
||||
|
||||
#include <QDebug>
|
||||
#include <QHBoxLayout>
|
||||
#include <QTableView>
|
||||
#include <QHeaderView>
|
||||
#include <QSettings>
|
||||
|
||||
#include "traceview.hpp"
|
||||
|
||||
TraceView::TraceView(QWidget *parent): QWidget(parent) {
|
||||
auto lyt = new QHBoxLayout;
|
||||
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
|
||||
|
||||
#include <QTableView>
|
||||
#include <QWidget>
|
||||
|
||||
#include "traceeventmodel.hpp"
|
||||
|
||||
#include "processdata.hpp"
|
||||
|
||||
class TraceView: public QWidget {
|
||||
Q_OBJECT
|
||||
|
||||
private:
|
||||
QTableView *m_eventTable;
|
||||
TraceEventModel *m_model = nullptr;
|
||||
|
||||
public:
|
||||
TraceView(QWidget *parent = nullptr);
|
||||
|
||||
~TraceView();
|
||||
|
||||
void setProcessData(ProcessData *data);
|
||||
|
||||
private:
|
||||
void readState();
|
||||
|
||||
void writeState();
|
||||
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user