Larger improvements
This commit is contained in:
11
common.h
11
common.h
@@ -5,6 +5,8 @@
|
||||
#include <QDate>
|
||||
#include <QtGlobal>
|
||||
#include <QMetaType>
|
||||
#include <QMap>
|
||||
#include <QSqlDatabase>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
@@ -28,3 +30,12 @@ inline bool scanResultEmpty(const ScanResult &result)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
struct Project {
|
||||
QMap<int, QString> hosts;
|
||||
QMap<int, QString> processes;
|
||||
QMap<int, QString> filenames;
|
||||
QMap<int, QString> threads;
|
||||
QMap<int, QString> types;
|
||||
QSqlDatabase database;
|
||||
};
|
||||
|
@@ -4,6 +4,7 @@
|
||||
#include <QMessageBox>
|
||||
#include <QStringBuilder>
|
||||
#include <QSqlError>
|
||||
#include <QSqlQuery>
|
||||
|
||||
OpenDialog::OpenDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
@@ -16,21 +17,78 @@ OpenDialog::OpenDialog(QWidget *parent) :
|
||||
|
||||
OpenDialog::~OpenDialog() = default;
|
||||
|
||||
QSqlDatabase OpenDialog::database()
|
||||
std::unique_ptr<Project> &OpenDialog::project()
|
||||
{
|
||||
return m_database;
|
||||
return m_project;
|
||||
}
|
||||
|
||||
void OpenDialog::submit()
|
||||
{
|
||||
m_database = m_ui->databaseWidget->createConnection();
|
||||
auto project = std::make_unique<Project>();
|
||||
project->database = m_ui->databaseWidget->createConnection();
|
||||
|
||||
if (!m_database.open())
|
||||
if (!project->database.open())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not open database!"), tr("Could not open database!") % "\n\n" % m_database.lastError().text());
|
||||
m_database = {};
|
||||
QMessageBox::warning(this, tr("Could not open database!"), tr("Could not open database!") % "\n\n" % project->database.lastError().text());
|
||||
return;
|
||||
}
|
||||
|
||||
{
|
||||
QSqlQuery query("SELECT `ID`, `Name` FROM `Hosts`;", project->database);
|
||||
if (query.lastError().isValid())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not open database!"), tr("Could not open database!") % "\n\n" % query.lastError().text());
|
||||
return;
|
||||
}
|
||||
while(query.next())
|
||||
project->hosts.insert(query.value(0).toInt(), query.value(1).toString());
|
||||
}
|
||||
|
||||
{
|
||||
QSqlQuery query("SELECT `ID`, `Name` FROM `Processes`;", project->database);
|
||||
if (query.lastError().isValid())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not open database!"), tr("Could not open database!") % "\n\n" % query.lastError().text());
|
||||
return;
|
||||
}
|
||||
while(query.next())
|
||||
project->processes.insert(query.value(0).toInt(), query.value(1).toString());
|
||||
}
|
||||
|
||||
{
|
||||
QSqlQuery query("SELECT `ID`, `Name` FROM `Filenames`;", project->database);
|
||||
if (query.lastError().isValid())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not open database!"), tr("Could not open database!") % "\n\n" % query.lastError().text());
|
||||
return;
|
||||
}
|
||||
while(query.next())
|
||||
project->filenames.insert(query.value(0).toInt(), query.value(1).toString());
|
||||
}
|
||||
|
||||
{
|
||||
QSqlQuery query("SELECT `ID`, `Name` FROM `Threads`;", project->database);
|
||||
if (query.lastError().isValid())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not open database!"), tr("Could not open database!") % "\n\n" % query.lastError().text());
|
||||
return;
|
||||
}
|
||||
while(query.next())
|
||||
project->threads.insert(query.value(0).toInt(), query.value(1).toString());
|
||||
}
|
||||
|
||||
{
|
||||
QSqlQuery query("SELECT `ID`, `Name` FROM `Types`;", project->database);
|
||||
if (query.lastError().isValid())
|
||||
{
|
||||
QMessageBox::warning(this, tr("Could not open database!"), tr("Could not open database!") % "\n\n" % query.lastError().text());
|
||||
return;
|
||||
}
|
||||
while(query.next())
|
||||
project->types.insert(query.value(0).toInt(), query.value(1).toString());
|
||||
}
|
||||
|
||||
m_project = std::move(project);
|
||||
|
||||
accept();
|
||||
}
|
||||
|
@@ -5,6 +5,8 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
namespace Ui { class OpenDialog; }
|
||||
|
||||
class OpenDialog : public QDialog
|
||||
@@ -15,7 +17,7 @@ public:
|
||||
explicit OpenDialog(QWidget *parent = nullptr);
|
||||
~OpenDialog() override;
|
||||
|
||||
QSqlDatabase database();
|
||||
std::unique_ptr<Project> &project();
|
||||
|
||||
private slots:
|
||||
void submit();
|
||||
@@ -23,5 +25,5 @@ private slots:
|
||||
private:
|
||||
const std::unique_ptr<Ui::OpenDialog> m_ui;
|
||||
|
||||
QSqlDatabase m_database;
|
||||
std::unique_ptr<Project> m_project;
|
||||
};
|
||||
|
@@ -37,7 +37,8 @@ SOURCES += main.cpp \
|
||||
widgets/databasewidget.cpp \
|
||||
gzipdevice.cpp \
|
||||
dialogs/graphdialog.cpp \
|
||||
models/sqlrelationaltablemodel.cpp
|
||||
models/logmodel.cpp \
|
||||
models/progressmodel.cpp
|
||||
|
||||
HEADERS += \
|
||||
mainwindow.h \
|
||||
@@ -61,7 +62,8 @@ HEADERS += \
|
||||
widgets/databasewidget.h \
|
||||
gzipdevice.h \
|
||||
dialogs/graphdialog.h \
|
||||
models/sqlrelationaltablemodel.h
|
||||
models/logmodel.h \
|
||||
models/progressmodel.h
|
||||
|
||||
FORMS += \
|
||||
mainwindow.ui \
|
||||
@@ -70,7 +72,8 @@ FORMS += \
|
||||
widgets/databasewidget.ui \
|
||||
wizard/intropage.ui \
|
||||
wizard/databasepage.ui \
|
||||
dialogs/graphdialog.ui
|
||||
dialogs/graphdialog.ui \
|
||||
wizard/tablespage.ui
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc
|
||||
|
@@ -3,17 +3,16 @@
|
||||
|
||||
#include <QSqlQuery>
|
||||
#include <QSqlError>
|
||||
#include <QSqlRelationalTableModel>
|
||||
#include <QMessageBox>
|
||||
#include <QStringBuilder>
|
||||
#include <QMenu>
|
||||
#include <QAction>
|
||||
#include <QDateTime>
|
||||
#include <QDebug>
|
||||
|
||||
#include "wizard/importwizard.h"
|
||||
#include "dialogs/opendialog.h"
|
||||
#include "dialogs/graphdialog.h"
|
||||
#include "models/logmodel.h"
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
@@ -38,6 +37,10 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
connect(m_ui->pushButton, &QPushButton::pressed, this, &MainWindow::updateQuery);
|
||||
|
||||
connect(m_ui->tableView, &QWidget::customContextMenuRequested, this, &MainWindow::showContextMenu);
|
||||
|
||||
m_ui->tableView->horizontalHeader()->setSectionsClickable(true);
|
||||
QObject::connect(m_ui->tableView->horizontalHeader(), &QHeaderView::sectionClicked, [this](int index){
|
||||
});
|
||||
}
|
||||
|
||||
MainWindow::~MainWindow() = default;
|
||||
@@ -54,7 +57,7 @@ void MainWindow::newClicked()
|
||||
m_ui->lineEdit->setEnabled(true);
|
||||
m_ui->pushButton->setEnabled(true);
|
||||
|
||||
m_database = wizard.database();
|
||||
//m_project->database = wizard.database();
|
||||
setupModel();
|
||||
}
|
||||
}
|
||||
@@ -71,7 +74,7 @@ void MainWindow::openClicked()
|
||||
m_ui->lineEdit->setEnabled(true);
|
||||
m_ui->pushButton->setEnabled(true);
|
||||
|
||||
m_database = dialog.database();
|
||||
m_project = std::move(dialog.project());
|
||||
setupModel();
|
||||
}
|
||||
}
|
||||
@@ -87,13 +90,12 @@ void MainWindow::closeClicked()
|
||||
|
||||
m_ui->tableView->setModel(nullptr);
|
||||
m_model = nullptr;
|
||||
m_database.close();
|
||||
m_database = QSqlDatabase();
|
||||
m_project = nullptr;
|
||||
}
|
||||
|
||||
void MainWindow::graphClicked()
|
||||
{
|
||||
GraphDialog(m_database, this).exec();
|
||||
GraphDialog(m_project->database, this).exec();
|
||||
}
|
||||
|
||||
void MainWindow::updateQuery()
|
||||
@@ -138,9 +140,11 @@ void MainWindow::updateQuery()
|
||||
}
|
||||
|
||||
sql.append("ORDER BY "
|
||||
"`Logs`.`Timestamp` ASC;");
|
||||
"`Logs`.`Timestamp` ASC "
|
||||
"LIMIT "
|
||||
"0, 100;");
|
||||
|
||||
QSqlQuery query(sql, m_database);
|
||||
QSqlQuery query(sql, m_project->database);
|
||||
|
||||
if (query.lastError().isValid())
|
||||
{
|
||||
@@ -237,7 +241,7 @@ void MainWindow::showContextMenu(const QPoint &pos)
|
||||
void MainWindow::setupModel()
|
||||
{
|
||||
m_ui->tableView->setModel(nullptr);
|
||||
m_model = std::make_unique<QSqlQueryModel>(this);
|
||||
m_model = std::make_unique<LogModel>(this);
|
||||
updateQuery();
|
||||
m_ui->tableView->setModel(m_model.get());
|
||||
m_ui->tableView->setColumnHidden(ColumnID, true);
|
||||
|
@@ -5,7 +5,9 @@
|
||||
|
||||
#include <memory>
|
||||
|
||||
class QSqlQueryModel;
|
||||
#include "common.h"
|
||||
|
||||
class LogModel;
|
||||
|
||||
namespace Ui { class MainWindow; }
|
||||
|
||||
@@ -33,6 +35,6 @@ private:
|
||||
|
||||
const std::unique_ptr<Ui::MainWindow> m_ui;
|
||||
|
||||
QSqlDatabase m_database;
|
||||
std::unique_ptr<QSqlQueryModel> m_model;
|
||||
std::unique_ptr<Project> m_project;
|
||||
std::unique_ptr<LogModel> m_model;
|
||||
};
|
||||
|
@@ -50,6 +50,9 @@
|
||||
<property name="editTriggers">
|
||||
<set>QAbstractItemView::NoEditTriggers</set>
|
||||
</property>
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
<property name="showGrid">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
@@ -66,7 +69,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>965</width>
|
||||
<height>18</height>
|
||||
<height>20</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menu_File">
|
||||
|
@@ -9,23 +9,27 @@ ChecklistModel::ChecklistModel(const QStringList &items, QObject *parent) :
|
||||
QAbstractListModel(parent)
|
||||
{
|
||||
for (const auto &item : items)
|
||||
m_items.append(std::make_pair(item, true));
|
||||
m_items.append({ item, item, true });
|
||||
}
|
||||
|
||||
ChecklistModel::ChecklistModel(const QList<std::pair<QString, bool> > &items, QObject *parent) :
|
||||
ChecklistModel::ChecklistModel(const QList<ChecklistItem> &items, QObject *parent) :
|
||||
QAbstractListModel(parent),
|
||||
m_items(items)
|
||||
{
|
||||
}
|
||||
|
||||
QStringList ChecklistModel::items() const
|
||||
const QList<ChecklistModel::ChecklistItem> &ChecklistModel::items() const
|
||||
{
|
||||
QStringList items;
|
||||
return m_items;
|
||||
}
|
||||
|
||||
for (const auto &pair : m_items)
|
||||
items.append(std::get<0>(pair));
|
||||
void ChecklistModel::setItems(const QList<ChecklistItem> &items)
|
||||
{
|
||||
emit beginResetModel();
|
||||
|
||||
return items;
|
||||
m_items = items;
|
||||
|
||||
emit endResetModel();
|
||||
}
|
||||
|
||||
void ChecklistModel::setItems(const QStringList &items)
|
||||
@@ -35,38 +39,93 @@ void ChecklistModel::setItems(const QStringList &items)
|
||||
m_items.clear();
|
||||
|
||||
for (const auto &item : items)
|
||||
m_items.append(std::make_pair(item, true));
|
||||
m_items.append({ item, item, true });
|
||||
|
||||
emit endResetModel();
|
||||
}
|
||||
|
||||
void ChecklistModel::setItems(const QList<std::pair<QString, bool> > &items)
|
||||
{
|
||||
emit beginResetModel();
|
||||
|
||||
m_items = items;
|
||||
|
||||
emit endResetModel();
|
||||
}
|
||||
|
||||
QStringList ChecklistModel::enabledItems() const
|
||||
QStringList ChecklistModel::itemTexts() const
|
||||
{
|
||||
QStringList items;
|
||||
|
||||
for (const auto &pair : m_items)
|
||||
if (std::get<1>(pair))
|
||||
items.append(std::get<0>(pair));
|
||||
for (const auto &item : m_items)
|
||||
items.append(item.displayText);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
QStringList ChecklistModel::disabledItems() const
|
||||
QVariantList ChecklistModel::itemDatas() const
|
||||
{
|
||||
QVariantList items;
|
||||
|
||||
for (const auto &item : m_items)
|
||||
items.append(item.data);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
QList<ChecklistModel::ChecklistItem> ChecklistModel::enabledItems() const
|
||||
{
|
||||
QList<ChecklistModel::ChecklistItem> items;
|
||||
|
||||
for (const auto &item : m_items)
|
||||
if (item.checked)
|
||||
items.append(item);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
QList<ChecklistModel::ChecklistItem> ChecklistModel::disabledItems() const
|
||||
{
|
||||
QList<ChecklistModel::ChecklistItem> items;
|
||||
|
||||
for (const auto &item : m_items)
|
||||
if (!item.checked)
|
||||
items.append(item);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
QStringList ChecklistModel::enabledTexts() const
|
||||
{
|
||||
QStringList items;
|
||||
|
||||
for (const auto &pair : m_items)
|
||||
if (!std::get<1>(pair))
|
||||
items.append(std::get<0>(pair));
|
||||
for (const auto &item : m_items)
|
||||
if (item.checked)
|
||||
items.append(item.displayText);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
QStringList ChecklistModel::disabledTexts() const
|
||||
{
|
||||
QStringList items;
|
||||
|
||||
for (const auto &item : m_items)
|
||||
if (!item.checked)
|
||||
items.append(item.displayText);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
QVariantList ChecklistModel::enabledItemDatas() const
|
||||
{
|
||||
QVariantList items;
|
||||
|
||||
for (const auto &item : m_items)
|
||||
if (item.checked)
|
||||
items.append(item.data);
|
||||
|
||||
return items;
|
||||
}
|
||||
|
||||
QVariantList ChecklistModel::disabledItemDatas() const
|
||||
{
|
||||
QVariantList items;
|
||||
|
||||
for (const auto &item : m_items)
|
||||
if (!item.checked)
|
||||
items.append(item.data);
|
||||
|
||||
return items;
|
||||
}
|
||||
@@ -75,57 +134,38 @@ int ChecklistModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
|
||||
return m_items.count();
|
||||
}
|
||||
|
||||
QModelIndex ChecklistModel::sibling(int row, int column, const QModelIndex &idx) const
|
||||
{
|
||||
if (!idx.isValid() || column != 0 || row >= m_items.count() || row < 0)
|
||||
return QModelIndex();
|
||||
return createIndex(row, 0);
|
||||
}
|
||||
|
||||
QMap<int, QVariant> ChecklistModel::itemData(const QModelIndex &index) const
|
||||
{
|
||||
if (!checkIndex(index, CheckIndexOption::IndexIsValid | CheckIndexOption::ParentIsInvalid))
|
||||
return QMap<int, QVariant>{};
|
||||
const auto &item = m_items.at(index.row());
|
||||
return QMap<int, QVariant>{{
|
||||
std::make_pair<int>(Qt::DisplayRole, std::get<0>(item)),
|
||||
std::make_pair<int>(Qt::EditRole, std::get<0>(item)),
|
||||
std::make_pair<int>(Qt::CheckStateRole, std::get<1>(item) ? Qt::Checked : Qt::Unchecked)
|
||||
}};
|
||||
}
|
||||
|
||||
bool ChecklistModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
|
||||
{
|
||||
if (roles.isEmpty())
|
||||
return false;
|
||||
if (std::any_of(roles.keyBegin(), roles.keyEnd(), [](int role) { return role != Qt::CheckStateRole; }))
|
||||
return false;
|
||||
auto roleIter = roles.constFind(Qt::CheckStateRole);
|
||||
Q_ASSERT(roleIter != roles.constEnd());
|
||||
return setData(index, roleIter.value(), roleIter.key());
|
||||
}
|
||||
|
||||
QVariant ChecklistModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() < 0 || index.row() >= m_items.size())
|
||||
return QVariant();
|
||||
return {};
|
||||
|
||||
const auto &item = m_items.at(index.row());
|
||||
if (role == Qt::DisplayRole || role == Qt::EditRole)
|
||||
return std::get<0>(item);
|
||||
if (role == Qt::CheckStateRole)
|
||||
return std::get<1>(item) ? Qt::Checked : Qt::Unchecked;
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::DisplayRole: return item.displayText;
|
||||
case Qt::EditRole: return item.data;
|
||||
case Qt::CheckStateRole: return item.checked ? Qt::Checked : Qt::Unchecked;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool ChecklistModel::setData(const QModelIndex &index, const QVariant &value, int role)
|
||||
{
|
||||
if (index.row() >= 0 && index.row() < m_items.size() && role == Qt::CheckStateRole)
|
||||
{
|
||||
if (index.row() < 0 || index.row() >= m_items.size())
|
||||
return false;
|
||||
|
||||
auto &item = m_items[index.row()];
|
||||
std::get<1>(item) = value.toBool();
|
||||
|
||||
switch (role)
|
||||
{
|
||||
case Qt::CheckStateRole:
|
||||
item.checked = value.toBool();
|
||||
emit dataChanged(index, index, { Qt::CheckStateRole });
|
||||
return true;
|
||||
}
|
||||
@@ -137,5 +177,6 @@ Qt::ItemFlags ChecklistModel::flags(const QModelIndex &index) const
|
||||
{
|
||||
if (!index.isValid())
|
||||
return QAbstractListModel::flags(index);
|
||||
|
||||
return QAbstractListModel::flags(index) | Qt::ItemIsUserCheckable;
|
||||
}
|
||||
|
@@ -3,31 +3,40 @@
|
||||
#include <QAbstractListModel>
|
||||
#include <QList>
|
||||
|
||||
#include <utility>
|
||||
|
||||
class Q_CORE_EXPORT ChecklistModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct ChecklistItem
|
||||
{
|
||||
QString displayText;
|
||||
QVariant data;
|
||||
bool checked;
|
||||
};
|
||||
|
||||
explicit ChecklistModel(QObject *parent = nullptr);
|
||||
explicit ChecklistModel(const QStringList &items, QObject *parent = nullptr);
|
||||
explicit ChecklistModel(const QList<std::pair<QString, bool> > &strings, QObject *parent = nullptr);
|
||||
explicit ChecklistModel(const QList<ChecklistItem> &strings, QObject *parent = nullptr);
|
||||
|
||||
QStringList items() const;
|
||||
const QList<ChecklistItem> &items() const;
|
||||
void setItems(const QList<ChecklistItem> &items);
|
||||
void setItems(const QStringList &items);
|
||||
void setItems(const QList<std::pair<QString, bool> > &items);
|
||||
QStringList enabledItems() const;
|
||||
QStringList disabledItems() const;
|
||||
|
||||
QStringList itemTexts() const;
|
||||
QVariantList itemDatas() const;
|
||||
QList<ChecklistItem> enabledItems() const;
|
||||
QList<ChecklistItem> disabledItems() const;
|
||||
QStringList enabledTexts() const;
|
||||
QStringList disabledTexts() const;
|
||||
QVariantList enabledItemDatas() const;
|
||||
QVariantList disabledItemDatas() const;
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||
QModelIndex sibling(int row, int column, const QModelIndex &idx) const override;
|
||||
QMap<int, QVariant> itemData(const QModelIndex &index) const override;
|
||||
bool setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles) override;
|
||||
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
|
||||
bool setData(const QModelIndex &index, const QVariant &value, int role) override;
|
||||
Qt::ItemFlags flags(const QModelIndex &index) const override;
|
||||
|
||||
private:
|
||||
QList<std::pair<QString, bool> > m_items;
|
||||
QList<ChecklistItem> m_items;
|
||||
};
|
||||
|
14
models/logmodel.cpp
Normal file
14
models/logmodel.cpp
Normal file
@@ -0,0 +1,14 @@
|
||||
#include "logmodel.h"
|
||||
|
||||
LogModel::LogModel(QObject *parent) :
|
||||
QSqlQueryModel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant LogModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Vertical)
|
||||
return {};
|
||||
|
||||
return QSqlQueryModel::headerData(section, orientation, role);
|
||||
}
|
13
models/logmodel.h
Normal file
13
models/logmodel.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <QSqlQueryModel>
|
||||
|
||||
class LogModel : public QSqlQueryModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit LogModel(QObject *parent = nullptr);
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
};
|
148
models/progressmodel.cpp
Normal file
148
models/progressmodel.cpp
Normal file
@@ -0,0 +1,148 @@
|
||||
#include "progressmodel.h"
|
||||
|
||||
#include <QImage>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
ProgressModel::ProgressModel(QObject *parent) :
|
||||
QAbstractListModel(parent)
|
||||
{
|
||||
connect(&m_movieLoading, &QMovie::frameChanged, this, &ProgressModel::frameChanged);
|
||||
}
|
||||
|
||||
ProgressModel::ProgressModel(const QStringList &items, QObject *parent) :
|
||||
QAbstractListModel(parent)
|
||||
{
|
||||
connect(&m_movieLoading, &QMovie::frameChanged, this, &ProgressModel::frameChanged);
|
||||
|
||||
m_items.reserve(items.count());
|
||||
for (const auto &item : items)
|
||||
m_items.append({ item, Item::Status::None });
|
||||
}
|
||||
|
||||
ProgressModel::ProgressModel(const QVector<ProgressModel::Item> &items, QObject *parent) :
|
||||
QAbstractListModel(parent),
|
||||
m_items(items)
|
||||
{
|
||||
connect(&m_movieLoading, &QMovie::frameChanged, this, &ProgressModel::frameChanged);
|
||||
|
||||
if (anyLoading())
|
||||
m_movieLoading.start();
|
||||
}
|
||||
|
||||
const QVector<ProgressModel::Item> &ProgressModel::items() const
|
||||
{
|
||||
return m_items;
|
||||
}
|
||||
|
||||
void ProgressModel::setItems(const QStringList &items)
|
||||
{
|
||||
emit beginResetModel();
|
||||
m_items.clear();
|
||||
m_items.reserve(items.count());
|
||||
for (const auto &item : items)
|
||||
m_items.append({ item, Item::Status::None });
|
||||
emit endResetModel();
|
||||
|
||||
m_movieLoading.stop();
|
||||
}
|
||||
|
||||
void ProgressModel::setItems(const QVector<ProgressModel::Item> &items)
|
||||
{
|
||||
emit beginResetModel();
|
||||
m_items = items;
|
||||
emit endResetModel();
|
||||
|
||||
updateMovieStatus();
|
||||
}
|
||||
|
||||
void ProgressModel::setText(int row, const QString &text)
|
||||
{
|
||||
m_items[row].text = text;
|
||||
|
||||
const auto index = createIndex(row, 0);
|
||||
emit dataChanged(index, index, { Qt::DisplayRole, Qt::EditRole });
|
||||
}
|
||||
|
||||
void ProgressModel::setStatus(int row, ProgressModel::Item::Status status)
|
||||
{
|
||||
m_items[row].status = status;
|
||||
|
||||
const auto index = createIndex(row, 0);
|
||||
emit dataChanged(index, index, { Qt::DecorationRole });
|
||||
|
||||
if (status == Item::Status::Loading)
|
||||
m_movieLoading.start();
|
||||
else
|
||||
updateMovieStatus();
|
||||
}
|
||||
|
||||
void ProgressModel::clearItems()
|
||||
{
|
||||
emit beginResetModel();
|
||||
m_items.clear();
|
||||
emit endResetModel();
|
||||
|
||||
m_movieLoading.stop();
|
||||
}
|
||||
|
||||
int ProgressModel::rowCount(const QModelIndex &parent) const
|
||||
{
|
||||
if (parent.isValid())
|
||||
return 0;
|
||||
|
||||
return m_items.count();
|
||||
}
|
||||
|
||||
QVariant ProgressModel::data(const QModelIndex &index, int role) const
|
||||
{
|
||||
if (index.row() < 0 || index.row() >= m_items.size())
|
||||
return {};
|
||||
|
||||
const auto &item = m_items.at(index.row());
|
||||
|
||||
switch (role) {
|
||||
case Qt::DisplayRole:
|
||||
case Qt::EditRole:
|
||||
return item.text;
|
||||
case Qt::DecorationRole:
|
||||
switch (item.status)
|
||||
{
|
||||
case Item::Status::None:
|
||||
return m_pixmapEmpty;
|
||||
case Item::Status::Loading:
|
||||
return m_movieLoading.currentPixmap();
|
||||
case Item::Status::Succeeded:
|
||||
return m_pixmapSucceeded;
|
||||
case Item::Status::Failed:
|
||||
return m_pixmapFailed;
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void ProgressModel::frameChanged()
|
||||
{
|
||||
for (auto iter = m_items.constBegin(); iter != m_items.constEnd(); iter++)
|
||||
{
|
||||
if (iter->status == Item::Status::Loading)
|
||||
{
|
||||
const auto index = createIndex(std::distance(m_items.constBegin(), iter), 0);
|
||||
emit dataChanged(index, index, { Qt::DecorationRole });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ProgressModel::anyLoading() const
|
||||
{
|
||||
return std::any_of(m_items.constBegin(), m_items.constEnd(), [](const auto &item){ return item.status == Item::Status::Loading; });
|
||||
}
|
||||
|
||||
void ProgressModel::updateMovieStatus()
|
||||
{
|
||||
if (anyLoading())
|
||||
m_movieLoading.start();
|
||||
else
|
||||
m_movieLoading.stop();
|
||||
}
|
59
models/progressmodel.h
Normal file
59
models/progressmodel.h
Normal file
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QPixmap>
|
||||
#include <QMovie>
|
||||
|
||||
class ProgressModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
struct Item
|
||||
{
|
||||
enum class Status
|
||||
{
|
||||
None,
|
||||
Loading,
|
||||
Succeeded,
|
||||
Failed
|
||||
};
|
||||
|
||||
QString text;
|
||||
Status status;
|
||||
};
|
||||
|
||||
explicit ProgressModel(QObject *parent = nullptr);
|
||||
ProgressModel(const QStringList &items, QObject *parent = nullptr);
|
||||
ProgressModel(const QVector<Item> &items, QObject *parent = nullptr);
|
||||
|
||||
const QVector<Item> &items() const;
|
||||
void setItems(const QStringList &items);
|
||||
void setItems(const QVector<Item> &items);
|
||||
|
||||
void setText(int row, const QString &text);
|
||||
void setStatus(int row, Item::Status status);
|
||||
|
||||
void clearItems();
|
||||
|
||||
int rowCount(const QModelIndex &parent) const override;
|
||||
QVariant data(const QModelIndex &index, int role) const override;
|
||||
|
||||
private slots:
|
||||
void frameChanged();
|
||||
|
||||
private:
|
||||
bool anyLoading() const;
|
||||
void updateMovieStatus();
|
||||
|
||||
QVector<Item> m_items;
|
||||
|
||||
const QPixmap m_pixmapSucceeded { ":/loganalyzer/succeeded.png" };
|
||||
const QPixmap m_pixmapFailed { ":/loganalyzer/failed.png" };
|
||||
const QPixmap m_pixmapEmpty { [this](){
|
||||
QPixmap pixmap(m_pixmapSucceeded.size());
|
||||
pixmap.fill();
|
||||
return pixmap;
|
||||
}() };
|
||||
QMovie m_movieLoading { ":/loganalyzer/loading.gif" };
|
||||
};
|
@@ -1,14 +0,0 @@
|
||||
#include "sqlrelationaltablemodel.h"
|
||||
|
||||
SqlRelationalTableModel::SqlRelationalTableModel(QObject *parent, QSqlDatabase db) :
|
||||
QSqlRelationalTableModel(parent, db)
|
||||
{
|
||||
}
|
||||
|
||||
QVariant SqlRelationalTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (orientation == Qt::Vertical)
|
||||
return {};
|
||||
|
||||
return QSqlRelationalTableModel::headerData(section, orientation, role);
|
||||
}
|
@@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
|
||||
#include <QSqlRelationalTableModel>
|
||||
|
||||
class SqlRelationalTableModel : public QSqlRelationalTableModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit SqlRelationalTableModel(QObject *parent = nullptr, QSqlDatabase db = QSqlDatabase());
|
||||
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const override;
|
||||
};
|
@@ -96,6 +96,7 @@ void TableCreatorThread::run()
|
||||
return;
|
||||
}
|
||||
|
||||
sleep(1);
|
||||
emit someSignal(index++);
|
||||
}
|
||||
}
|
||||
|
@@ -12,16 +12,17 @@ DatabaseWidget::DatabaseWidget(QWidget *parent) :
|
||||
|
||||
// for debugging
|
||||
setDriver("QMYSQL");
|
||||
// setMysqlHostname("sql7.freemysqlhosting.net");
|
||||
// setMysqlUsername("sql7285815");
|
||||
// setMysqlPassword("BKhysrtqKl");
|
||||
// setMysqlDatabase("sql7285815");
|
||||
setMysqlHostname("sql7.freemysqlhosting.net");
|
||||
setMysqlUsername("sql7285815");
|
||||
setMysqlPassword("BKhysrtqKl");
|
||||
setMysqlDatabase("sql7285815");
|
||||
|
||||
// setMysqlHostname("brunner.ninja");
|
||||
setMysqlHostname("localhost");
|
||||
setMysqlUsername("logtest");
|
||||
setMysqlPassword("logtest");
|
||||
setMysqlDatabase("logtest");
|
||||
|
||||
// setMysqlHostname("localhost");
|
||||
// setMysqlUsername("logtest");
|
||||
// setMysqlPassword("logtest");
|
||||
// setMysqlDatabase("logtest");
|
||||
}
|
||||
|
||||
DatabaseWidget::~DatabaseWidget() = default;
|
||||
|
@@ -144,7 +144,7 @@ void LocalImportPage::updateSummary()
|
||||
|
||||
ScanResult LocalImportPage::filterResult(ScanResult result) const
|
||||
{
|
||||
const auto processes = m_model.enabledItems().toSet();
|
||||
const auto processes = m_model.enabledTexts().toSet();
|
||||
|
||||
for (auto hostsIter = result.begin(); hostsIter != result.end(); hostsIter++)
|
||||
{
|
||||
|
@@ -213,8 +213,8 @@ void RemoteImportOverviewPage::updateSummary()
|
||||
|
||||
ScanResult RemoteImportOverviewPage::filterResult(ScanResult result) const
|
||||
{
|
||||
const auto hosts = m_modelHosts.enabledItems().toSet();
|
||||
const auto processes = m_modelProcesses.enabledItems().toSet();
|
||||
const auto hosts = m_modelHosts.enabledTexts().toSet();
|
||||
const auto processes = m_modelProcesses.enabledTexts().toSet();
|
||||
|
||||
for (auto hostsIter = result.begin(); hostsIter != result.end(); )
|
||||
{
|
||||
|
@@ -1,4 +1,5 @@
|
||||
#include "tablespage.h"
|
||||
#include "ui_tablespage.h"
|
||||
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
@@ -7,27 +8,13 @@
|
||||
#include "threads/tablecreatorthread.h"
|
||||
|
||||
TablesPage::TablesPage(QWidget *parent) :
|
||||
QWizardPage(parent)
|
||||
QWizardPage(parent),
|
||||
m_ui(std::make_unique<Ui::TablesPage>()),
|
||||
m_model(this)
|
||||
{
|
||||
setTitle(tr("Tables"));
|
||||
setSubTitle(tr("TODO..."));
|
||||
m_ui->setupUi(this);
|
||||
|
||||
auto layout = new QGridLayout;
|
||||
|
||||
m_statusLabels.resize(TableCreatorThread::tables().size());
|
||||
|
||||
int index { 0 };
|
||||
for (const QString &tableName : TableCreatorThread::tables())
|
||||
{
|
||||
m_statusLabels[index] = new QLabel;
|
||||
layout->addWidget(m_statusLabels[index], index, 0);
|
||||
|
||||
auto label = new QLabel(tr("Create table %0").arg(tableName));
|
||||
label->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
layout->addWidget(label, index++, 1);
|
||||
}
|
||||
|
||||
setLayout(layout);
|
||||
m_ui->listView->setModel(&m_model);
|
||||
}
|
||||
|
||||
TablesPage::~TablesPage() = default;
|
||||
@@ -43,29 +30,25 @@ void TablesPage::initializePage()
|
||||
Q_ASSERT(importWizard);
|
||||
Q_ASSERT(importWizard->database().isOpen());
|
||||
|
||||
for (auto label : m_statusLabels)
|
||||
{
|
||||
label->setMovie(nullptr);
|
||||
label->setPixmap({});
|
||||
}
|
||||
QVector<ProgressModel::Item> items;
|
||||
items.reserve(TableCreatorThread::tables().size());
|
||||
|
||||
for (const QString &tableName : TableCreatorThread::tables())
|
||||
items.append({ tr("Create table %0").arg(tableName), ProgressModel::Item::Status::None });
|
||||
items.first().status = ProgressModel::Item::Status::Loading;
|
||||
|
||||
m_model.setItems(items);
|
||||
|
||||
m_thread = std::make_unique<TableCreatorThread>(importWizard->database(), this);
|
||||
connect(m_thread.get(), &TableCreatorThread::someSignal, this, &TablesPage::someSlot);
|
||||
|
||||
m_thread->start();
|
||||
m_statusLabels[0]->setMovie(&m_movieLoading);
|
||||
m_movieLoading.start();
|
||||
}
|
||||
|
||||
void TablesPage::cleanupPage()
|
||||
{
|
||||
if (m_thread)
|
||||
{
|
||||
m_thread->requestInterruption();
|
||||
m_thread->wait();
|
||||
m_thread = nullptr;
|
||||
}
|
||||
m_movieLoading.stop();
|
||||
stopThread();
|
||||
m_model.clearItems();
|
||||
}
|
||||
|
||||
bool TablesPage::isComplete() const
|
||||
@@ -75,15 +58,24 @@ bool TablesPage::isComplete() const
|
||||
|
||||
void TablesPage::someSlot(int index)
|
||||
{
|
||||
Q_ASSERT(index < m_statusLabels.size());
|
||||
Q_ASSERT(index < m_model.rowCount({}));
|
||||
|
||||
m_statusLabels[index]->setMovie(nullptr);
|
||||
m_statusLabels[index]->setPixmap(m_pixmapSucceeded);
|
||||
if (index < m_statusLabels.size() - 1)
|
||||
m_statusLabels[index+1]->setMovie(&m_movieLoading);
|
||||
m_model.setStatus(index, ProgressModel::Item::Status::Succeeded);
|
||||
if (index < m_model.rowCount({}) - 1)
|
||||
m_model.setStatus(index + 1, ProgressModel::Item::Status::Loading);
|
||||
else
|
||||
{
|
||||
cleanupPage();
|
||||
stopThread();
|
||||
emit completeChanged();
|
||||
}
|
||||
}
|
||||
|
||||
void TablesPage::stopThread()
|
||||
{
|
||||
if (m_thread)
|
||||
{
|
||||
m_thread->requestInterruption();
|
||||
m_thread->wait();
|
||||
m_thread = nullptr;
|
||||
}
|
||||
}
|
||||
|
@@ -1,25 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include <QWizardPage>
|
||||
#include <QPixmap>
|
||||
#include <QMovie>
|
||||
#include <QVector>
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "models/progressmodel.h"
|
||||
|
||||
class QLabel;
|
||||
class QSqlDatabase;
|
||||
|
||||
class TableCreatorThread;
|
||||
namespace Ui { class TablesPage; }
|
||||
|
||||
class TablesPage : public QWizardPage
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
const QPixmap m_pixmapSucceeded { ":/loganalyzer/succeeded.png" };
|
||||
const QPixmap m_pixmapFailed { ":/loganalyzer/failed.png" };
|
||||
QMovie m_movieLoading { ":/loganalyzer/loading.gif" };
|
||||
|
||||
public:
|
||||
explicit TablesPage(QWidget *parent = nullptr);
|
||||
~TablesPage() override;
|
||||
@@ -34,7 +30,11 @@ private slots:
|
||||
void someSlot(int index);
|
||||
|
||||
private:
|
||||
QVector<QLabel*> m_statusLabels;
|
||||
void stopThread();
|
||||
|
||||
const std::unique_ptr<Ui::TablesPage> m_ui;
|
||||
|
||||
ProgressModel m_model;
|
||||
|
||||
std::unique_ptr<TableCreatorThread> m_thread;
|
||||
};
|
||||
|
34
wizard/tablespage.ui
Normal file
34
wizard/tablespage.ui
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>TablesPage</class>
|
||||
<widget class="QWizardPage" name="TablesPage">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>400</width>
|
||||
<height>300</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>WizardPage</string>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Tables</string>
|
||||
</property>
|
||||
<property name="subTitle">
|
||||
<string>TODO...</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QListView" name="listView">
|
||||
<property name="selectionMode">
|
||||
<enum>QAbstractItemView::NoSelection</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
Reference in New Issue
Block a user