Add process selector and get log messages displaying

This commit is contained in:
Gary Talent 2018-10-16 21:39:46 -05:00
parent 4fb58b4324
commit 733350b143
15 changed files with 236 additions and 48 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
dist dist
build build
Session.vim

View File

@ -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

View File

@ -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);

View File

@ -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() {

View File

@ -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();

View File

@ -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;
}

View File

@ -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
View 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);
}
}

View File

@ -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);
}
}

View File

@ -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());
}
} }
} }
} }

View File

@ -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();
} }

View File

@ -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);
}; };

View File

@ -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);
} }

View File

@ -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();
}; };