Larger improvements

This commit is contained in:
2019-04-07 18:20:01 +02:00
parent b1ce4ecf64
commit 0704012542
22 changed files with 553 additions and 185 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View 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()];
switch (role)
{
auto &item = m_items[index.row()];
std::get<1>(item) = value.toBool();
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;
}

View File

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

View File

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

View File

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

View File

@@ -96,6 +96,7 @@ void TableCreatorThread::run()
return;
}
sleep(1);
emit someSignal(index++);
}
}

View File

@@ -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("brunner.ninja");
// setMysqlHostname("localhost");
// setMysqlUsername("logtest");
// setMysqlPassword("logtest");
// setMysqlDatabase("logtest");
}
DatabaseWidget::~DatabaseWidget() = default;

View File

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

View File

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

View File

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

View File

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