Files
DbLogAnalyzer/mainwindow.cpp

250 lines
8.1 KiB
C++
Raw Normal View History

2019-04-01 10:43:36 +02:00
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QSqlQuery>
#include <QSqlError>
#include <QMessageBox>
#include <QStringBuilder>
#include <QMenu>
#include <QAction>
#include <QDateTime>
#include "wizard/importwizard.h"
#include "dialogs/opendialog.h"
#include "dialogs/graphdialog.h"
2019-04-07 18:20:01 +02:00
#include "models/logmodel.h"
2019-04-01 10:43:36 +02:00
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
m_ui(std::make_unique<Ui::MainWindow>())
{
m_ui->setupUi(this);
m_ui->actionNew->setShortcut(QKeySequence::New);
m_ui->actionOpen->setShortcut(QKeySequence::Open);
m_ui->actionQuit->setShortcut(QKeySequence::Quit);
connect(m_ui->actionNew, &QAction::triggered, this, &MainWindow::newClicked);
connect(m_ui->actionOpen, &QAction::triggered, this, &MainWindow::openClicked);
connect(m_ui->actionClose, &QAction::triggered, this, &MainWindow::closeClicked);
connect(m_ui->actionQuit, &QAction::triggered, QCoreApplication::instance(), &QCoreApplication::quit);
connect(m_ui->actionGraph, &QAction::triggered, this, &MainWindow::graphClicked);
for (QAction *action : { m_ui->actionTimestamp, m_ui->actionHost, m_ui->actionProcess, m_ui->actionFilename, m_ui->actionThread, m_ui->actionType, m_ui->actionMessage })
connect(action, &QAction::toggled, this, &MainWindow::showColumns);
connect(m_ui->lineEdit, &QLineEdit::returnPressed, this, &MainWindow::updateQuery);
connect(m_ui->pushButton, &QPushButton::pressed, this, &MainWindow::updateQuery);
connect(m_ui->tableView, &QWidget::customContextMenuRequested, this, &MainWindow::showContextMenu);
2019-04-07 18:20:01 +02:00
m_ui->tableView->horizontalHeader()->setSectionsClickable(true);
QObject::connect(m_ui->tableView->horizontalHeader(), &QHeaderView::sectionClicked, [this](int index){
});
2019-04-01 10:43:36 +02:00
}
MainWindow::~MainWindow() = default;
void MainWindow::newClicked()
{
ImportWizard wizard(this);
if (wizard.exec() == QDialog::Accepted && wizard.field("open").toBool())
{
m_ui->actionNew->setVisible(false);
m_ui->actionOpen->setVisible(false);
m_ui->actionClose->setVisible(true);
m_ui->actionGraph->setEnabled(true);
m_ui->lineEdit->setEnabled(true);
m_ui->pushButton->setEnabled(true);
2019-04-07 18:20:01 +02:00
//m_project->database = wizard.database();
2019-04-01 10:43:36 +02:00
setupModel();
}
}
void MainWindow::openClicked()
{
OpenDialog dialog(this);
if (dialog.exec() == QDialog::Accepted)
{
m_ui->actionNew->setVisible(false);
m_ui->actionOpen->setVisible(false);
m_ui->actionClose->setVisible(true);
m_ui->actionGraph->setEnabled(true);
m_ui->lineEdit->setEnabled(true);
m_ui->pushButton->setEnabled(true);
2019-04-07 18:20:01 +02:00
m_project = std::move(dialog.project());
2019-04-01 10:43:36 +02:00
setupModel();
}
}
void MainWindow::closeClicked()
{
m_ui->actionNew->setVisible(true);
m_ui->actionOpen->setVisible(true);
m_ui->actionClose->setVisible(false);
m_ui->actionGraph->setEnabled(false);
m_ui->lineEdit->setEnabled(false);
m_ui->pushButton->setEnabled(false);
m_ui->tableView->setModel(nullptr);
m_model = nullptr;
2019-04-07 18:20:01 +02:00
m_project = nullptr;
2019-04-01 10:43:36 +02:00
}
void MainWindow::graphClicked()
{
2019-04-07 18:20:01 +02:00
GraphDialog(m_project->database, this).exec();
2019-04-01 10:43:36 +02:00
}
void MainWindow::updateQuery()
{
2019-04-05 21:19:08 +02:00
QString sql = "SELECT "
"`Logs`.`ID` AS ID, "
"`Logs`.`Timestamp` AS ID, "
"`Hosts`.`Name` AS Host, "
"`Processes`.`Name` AS Process, "
"`Filenames`.`Name` AS Filename, "
"`Threads`.`Name` AS Thread, "
"`Types`.`Name` AS Type, "
"`Logs`.`Message` AS Message "
"FROM "
"`Logs` "
"LEFT JOIN "
"`Hosts` "
"ON "
"`Logs`.`HostID` = `Hosts`.`ID` "
"LEFT JOIN "
"`Processes` "
"ON "
"`Logs`.`ProcessID` = `Processes`.`ID` "
"LEFT JOIN "
"`Filenames` "
"ON "
"`Logs`.`FilenameID` = `Filenames`.`ID` "
"LEFT JOIN "
"`Threads` "
"ON "
"`Logs`.`ThreadID` = `Threads`.`ID` "
"LEFT JOIN "
"`Types` "
"ON "
"`Logs`.`TypeID` = `Types`.`ID` ";
auto filter = m_ui->lineEdit->text().replace("||", "OR").replace("&&", "AND");
2019-04-01 10:43:36 +02:00
if (!filter.trimmed().isEmpty())
{
2019-04-05 21:19:08 +02:00
sql.append("WHERE ");
sql.append(filter);
}
sql.append("ORDER BY "
2019-04-07 18:20:01 +02:00
"`Logs`.`Timestamp` ASC "
"LIMIT "
"0, 100;");
2019-04-05 21:19:08 +02:00
2019-04-07 18:20:01 +02:00
QSqlQuery query(sql, m_project->database);
2019-04-05 21:19:08 +02:00
if (query.lastError().isValid())
{
QMessageBox::warning(this, tr("Query failed!"), tr("Query failed!") % "\n\n" % query.lastError().text());
return;
2019-04-01 10:43:36 +02:00
}
2019-04-05 21:19:08 +02:00
m_model->setQuery(query);
2019-04-01 10:43:36 +02:00
}
void MainWindow::showColumns()
{
for (const auto &pair : {
std::make_pair(m_ui->actionTimestamp, ColumnTimestamp),
std::make_pair(m_ui->actionHost, ColumnHost),
std::make_pair(m_ui->actionProcess, ColumnProcess),
std::make_pair(m_ui->actionFilename, ColumnFilename),
std::make_pair(m_ui->actionThread, ColumnThread),
std::make_pair(m_ui->actionType, ColumnType),
std::make_pair(m_ui->actionMessage, ColumnMessage)
})
m_ui->tableView->setColumnHidden(std::get<1>(pair), !std::get<0>(pair)->isChecked());
}
void MainWindow::showContextMenu(const QPoint &pos)
{
const auto index = m_ui->tableView->indexAt(pos);
if (!index.isValid())
return;
QMenu menu(this);
const auto exec = [this,&menu,&pos](){ return menu.exec(m_ui->tableView->viewport()->mapToGlobal(pos)); };
const auto data = m_model->data(index, Qt::EditRole).toString();
switch (index.column())
{
case ColumnTimestamp:
{
auto minute = menu.addAction(tr("Filter by minute"));
auto second = menu.addAction(tr("Filter by second"));
auto action = exec();
if (action == minute || action == second)
{
const auto format = QStringLiteral("yyyy-MM-dd HH:mm:ss.zzz");
auto dateTime = QDateTime::fromString(data, format);
auto time = dateTime.time();
time.setHMS(time.hour(), time.minute(), action==minute ? 0 : time.second());
dateTime.setTime(time);
m_ui->lineEdit->setText(QString("`Timestamp` BETWEEN \"%0\" AND \"%1\"").arg(dateTime.toString(format), dateTime.addMSecs(action==minute ? 59999 : 999).toString(format)));
updateQuery();
}
break;
}
case ColumnHost:
if (menu.addAction(tr("Filter by host")) == exec())
{
m_ui->lineEdit->setText(QString("`Hosts`.`Name` = \"%0\"").arg(data));
updateQuery();
}
break;
case ColumnProcess:
if (menu.addAction(tr("Filter by process")) == exec())
{
m_ui->lineEdit->setText(QString("`Processes`.`Name` = \"%0\"").arg(data));
updateQuery();
}
break;
case ColumnFilename:
if (menu.addAction(tr("Filter by filename")) == exec())
{
m_ui->lineEdit->setText(QString("`Filenames`.`Name` = \"%0\"").arg(data));
updateQuery();
}
break;
case ColumnThread:
if (menu.addAction(tr("Filter by thread")) == exec())
{
m_ui->lineEdit->setText(QString("`Threads`.`Name` = \"%0\"").arg(data));
updateQuery();
}
break;
case ColumnType:
if (menu.addAction(tr("Filter by type")) == exec())
{
m_ui->lineEdit->setText(QString("`Types`.`Name` = \"%0\"").arg(data));
updateQuery();
}
break;
}
}
void MainWindow::setupModel()
{
m_ui->tableView->setModel(nullptr);
2019-04-07 18:20:01 +02:00
m_model = std::make_unique<LogModel>(this);
2019-04-05 21:19:08 +02:00
updateQuery();
2019-04-01 10:43:36 +02:00
m_ui->tableView->setModel(m_model.get());
m_ui->tableView->setColumnHidden(ColumnID, true);
showColumns();
}