UI: Improve ZonesWindow.

This commit is contained in:
Nodir Temirkhodjaev 2020-02-04 09:17:07 +05:00
parent bfce24e510
commit 97f8f84324
33 changed files with 950 additions and 141 deletions

View File

@ -66,6 +66,8 @@ SOURCES += \
model/iplistmodel.cpp \
model/traflistmodel.cpp \
model/zonelistmodel.cpp \
model/zonesourcewrapper.cpp \
model/zonetypewrapper.cpp \
stat/quotamanager.cpp \
stat/statmanager.cpp \
stat/statsql.cpp \
@ -93,6 +95,8 @@ SOURCES += \
util/fileutil.cpp \
util/guiutil.cpp \
util/hotkeymanager.cpp \
util/json/jsonutil.cpp \
util/json/mapwrapper.cpp \
util/logger.cpp \
util/model/stringlistmodel.cpp \
util/model/tableitemmodel.cpp \
@ -172,6 +176,8 @@ HEADERS += \
model/iplistmodel.h \
model/traflistmodel.h \
model/zonelistmodel.h \
model/zonesourcewrapper.h \
model/zonetypewrapper.h \
stat/quotamanager.h \
stat/statmanager.h \
stat/statsql.h \
@ -200,6 +206,8 @@ HEADERS += \
util/fileutil.h \
util/guiutil.h \
util/hotkeymanager.h \
util/json/jsonutil.h \
util/json/mapwrapper.h \
util/logger.h \
util/model/stringlistmodel.h \
util/model/tableitemmodel.h \
@ -242,7 +250,7 @@ RESOURCES += \
# Zone
OTHER_FILES += conf/zone/*.json
RESOURCES += conf/zone/fort-conf-zone.qrc
RESOURCES += conf/conf-zone.qrc
# Shadow Build: Copy i18n/ to build path
!equals(PWD, $${OUT_PWD}) {

View File

@ -0,0 +1,6 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>zone/sources.json</file>
<file>zone/types.json</file>
</qresource>
</RCC>

View File

@ -174,6 +174,28 @@ const char * const sqlUpdateAppResetGroup =
" WHERE app_group_id = ?1;"
;
const char * const sqlInsertZone =
"INSERT INTO zone(name, enabled, custom_url, source_code, url, form_data)"
" VALUES(?1, ?2, ?3, ?4, ?5, ?6);"
;
const char * const sqlDeleteZone =
"DELETE FROM zone WHERE zone_id = ?1;"
;
const char * const sqlUpdateZone =
"UPDATE zone"
" SET name = ?2, enabled = ?3, custom_url = ?4,"
" source_code = ?5, url = ?6, form_data = ?7"
" WHERE zone_id = ?1;"
;
const char * const sqlUpdateZoneName =
"UPDATE zone"
" SET name = ?2"
" WHERE zone_id = ?1;"
;
bool saveAddressGroup(SqliteDb *db, AddressGroup *addrGroup, int orderIndex)
{
const bool rowExists = (addrGroup->id() != 0);
@ -592,6 +614,84 @@ void ConfManager::checkAppEndTimes()
}
}
bool ConfManager::addZone(const QString &zoneName, const QString &sourceCode,
const QString &url, const QString &formData,
bool enabled, bool customUrl)
{
bool ok = false;
const auto vars = QVariantList()
<< zoneName
<< enabled
<< customUrl
<< sourceCode
<< url
<< formData
;
m_sqliteDb->executeEx(sqlInsertZone, vars, 0, &ok);
if (!ok) {
showErrorMessage(m_sqliteDb->errorMessage());
}
return ok;
}
bool ConfManager::deleteZone(qint64 zoneId)
{
bool ok = false;
const auto vars = QVariantList() << zoneId;
m_sqliteDb->executeEx(sqlDeleteZone, vars, 0, &ok);
if (!ok) {
showErrorMessage(m_sqliteDb->errorMessage());
}
return ok;
}
bool ConfManager::updateZone(qint64 zoneId, const QString &zoneName,
const QString &sourceCode, const QString &url,
const QString &formData, bool enabled, bool customUrl)
{
bool ok = false;
const auto vars = QVariantList()
<< zoneId
<< zoneName
<< enabled
<< customUrl
<< sourceCode
<< url
<< formData
;
m_sqliteDb->executeEx(sqlUpdateZone, vars, 0, &ok);
if (!ok) {
showErrorMessage(m_sqliteDb->errorMessage());
}
return ok;
}
bool ConfManager::updateZoneName(qint64 zoneId, const QString &zoneName)
{
bool ok = false;
const auto vars = QVariantList()
<< zoneId
<< zoneName
;
m_sqliteDb->executeEx(sqlUpdateZoneName, vars, 0, &ok);
if (!ok) {
showErrorMessage(m_sqliteDb->errorMessage());
}
return ok;
}
bool ConfManager::validateDriver()
{
ConfUtil confUtil;

View File

@ -33,8 +33,6 @@ public:
FortSettings *settings() const;
SqliteDb *sqliteDb() const { return m_sqliteDb; }
bool isEditing() const { return confToEdit() != nullptr; }
FirewallConf *conf() const { return m_conf; }
FirewallConf *confToEdit() const { return m_confToEdit; }
@ -67,6 +65,15 @@ public:
void updateAppEndTimes();
void checkAppEndTimes();
bool addZone(const QString &zoneName, const QString &sourceCode,
const QString &url, const QString &formData,
bool enabled, bool customUrl);
bool deleteZone(qint64 zoneId);
bool updateZone(qint64 zoneId, const QString &zoneName,
const QString &sourceCode, const QString &url,
const QString &formData, bool enabled, bool customUrl);
bool updateZoneName(qint64 zoneId, const QString &zoneName);
bool validateDriver();
bool updateDriverConf(bool onlyFlags = false);
bool updateDriverDeleteApp(const QString &appPath);

View File

@ -1,8 +1,9 @@
CREATE TABLE zone(
zone_id INTEGER PRIMARY KEY,
name TEXT NOT NULL,
enabled BOOLEAN NOT NULL,
zone_type TEXT NOT NULL,
custom_url BOOLEAN NOT NULL,
name TEXT NOT NULL,
source_code TEXT NOT NULL,
url TEXT,
form_data TEXT,
last_run INTEGER,

View File

@ -1,6 +0,0 @@
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file>zone-types.json</file>
<file>zone-urls.json</file>
</qresource>
</RCC>

View File

@ -1,6 +1,8 @@
[
{
"code": "tasix",
"title": "TAS-IX Addresses",
"zoneType": "bgp",
"url": "http://mrlg.tas-ix.uz/index.cgi",
"formData": "router=cisco&pass1=&query=1&arg="
}

View File

@ -1,6 +1,6 @@
[
{
"id": "bgp",
"code": "bgp",
"title": "BGP",
"description": "BGP table",
"sort": true,

View File

@ -5,7 +5,6 @@
#include <QDialog>
#include <QFormLayout>
#include <QHeaderView>
#include <QKeyEvent>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
@ -150,7 +149,7 @@ void ProgramsWindow::setupUi()
setupAppInfoVersion();
layout->addWidget(m_appInfoRow);
// Actions on app table's current changed
// Actions on apps table's current changed
setupTableAppsChanged();
this->setLayout(layout);
@ -167,80 +166,6 @@ void ProgramsWindow::setupUi()
this->setMinimumSize(500, 400);
}
QLayout *ProgramsWindow::setupHeader()
{
auto layout = new QHBoxLayout();
// Edit Menu
auto editMenu = new QMenu(this);
m_actAllowApp = editMenu->addAction(QIcon(":/images/arrow_switch.png"), QString());
m_actAllowApp->setShortcut(Qt::Key_A);
m_actBlockApp = editMenu->addAction(QIcon(":/images/stop.png"), QString());
m_actBlockApp->setShortcut(Qt::Key_B);
editMenu->addSeparator();
m_actAddApp = editMenu->addAction(QIcon(":/images/application_add.png"), QString());
m_actAddApp->setShortcut(Qt::Key_Plus);
m_actEditApp = editMenu->addAction(QIcon(":/images/application_edit.png"), QString());
m_actEditApp->setShortcut(Qt::Key_Enter);
m_actRemoveApp = editMenu->addAction(QIcon(":/images/application_delete.png"), QString());
m_actRemoveApp->setShortcut(Qt::Key_Delete);
editMenu->addSeparator();
m_actPurgeApps = editMenu->addAction(QIcon(":/images/bin_empty.png"), QString());
connect(m_actAllowApp, &QAction::triggered, [&] {
updateSelectedApps(false);
});
connect(m_actBlockApp, &QAction::triggered, [&] {
updateSelectedApps(true);
});
connect(m_actAddApp, &QAction::triggered, [&] {
updateAppEditForm(false);
});
connect(m_actEditApp, &QAction::triggered, [&] {
updateAppEditForm(true);
});
connect(m_actRemoveApp, &QAction::triggered, [&] {
if (fortManager()->showQuestionBox(tr("Are you sure to remove selected program(s)?"))) {
deleteSelectedApps();
}
});
connect(m_actPurgeApps, &QAction::triggered, [&] {
if (fortManager()->showQuestionBox(tr("Are you sure to remove all non-existent programs?"))) {
appListModel()->purgeApps();
}
});
m_btEdit = new WideButton(QIcon(":/images/application_edit.png"));
m_btEdit->setMenu(editMenu);
// Allow/Block
m_btAllowApp = ControlUtil::createLinkButton(":/images/arrow_switch.png");
m_btBlockApp = ControlUtil::createLinkButton(":/images/stop.png");
connect(m_btAllowApp, &QAbstractButton::clicked, m_actAllowApp, &QAction::trigger);
connect(m_btBlockApp, &QAbstractButton::clicked, m_actBlockApp, &QAction::trigger);
// Log Options
setupLogOptions();
layout->addWidget(m_btEdit);
layout->addWidget(ControlUtil::createSeparator(Qt::Vertical));
layout->addWidget(m_btAllowApp);
layout->addWidget(m_btBlockApp);
layout->addStretch();
layout->addWidget(m_btLogOptions);
return layout;
}
void ProgramsWindow::setupAppEditForm()
{
auto formLayout = new QFormLayout();
@ -358,6 +283,80 @@ void ProgramsWindow::setupComboAppGroups()
connect(confManager(), &ConfManager::confSaved, this, refreshComboAppGroups);
}
QLayout *ProgramsWindow::setupHeader()
{
auto layout = new QHBoxLayout();
// Edit Menu
auto editMenu = new QMenu(this);
m_actAllowApp = editMenu->addAction(QIcon(":/images/arrow_switch.png"), QString());
m_actAllowApp->setShortcut(Qt::Key_A);
m_actBlockApp = editMenu->addAction(QIcon(":/images/stop.png"), QString());
m_actBlockApp->setShortcut(Qt::Key_B);
editMenu->addSeparator();
m_actAddApp = editMenu->addAction(QIcon(":/images/application_add.png"), QString());
m_actAddApp->setShortcut(Qt::Key_Plus);
m_actEditApp = editMenu->addAction(QIcon(":/images/application_edit.png"), QString());
m_actEditApp->setShortcut(Qt::Key_Enter);
m_actRemoveApp = editMenu->addAction(QIcon(":/images/application_delete.png"), QString());
m_actRemoveApp->setShortcut(Qt::Key_Delete);
editMenu->addSeparator();
m_actPurgeApps = editMenu->addAction(QIcon(":/images/bin_empty.png"), QString());
connect(m_actAllowApp, &QAction::triggered, [&] {
updateSelectedApps(false);
});
connect(m_actBlockApp, &QAction::triggered, [&] {
updateSelectedApps(true);
});
connect(m_actAddApp, &QAction::triggered, [&] {
updateAppEditForm(false);
});
connect(m_actEditApp, &QAction::triggered, [&] {
updateAppEditForm(true);
});
connect(m_actRemoveApp, &QAction::triggered, [&] {
if (fortManager()->showQuestionBox(tr("Are you sure to remove selected program(s)?"))) {
deleteSelectedApps();
}
});
connect(m_actPurgeApps, &QAction::triggered, [&] {
if (fortManager()->showQuestionBox(tr("Are you sure to remove all non-existent programs?"))) {
appListModel()->purgeApps();
}
});
m_btEdit = new WideButton(QIcon(":/images/application_edit.png"));
m_btEdit->setMenu(editMenu);
// Allow/Block
m_btAllowApp = ControlUtil::createLinkButton(":/images/arrow_switch.png");
m_btBlockApp = ControlUtil::createLinkButton(":/images/stop.png");
connect(m_btAllowApp, &QAbstractButton::clicked, m_actAllowApp, &QAction::trigger);
connect(m_btBlockApp, &QAbstractButton::clicked, m_actBlockApp, &QAction::trigger);
// Log Options
setupLogOptions();
layout->addWidget(m_btEdit);
layout->addWidget(ControlUtil::createSeparator(Qt::Vertical));
layout->addWidget(m_btAllowApp);
layout->addWidget(m_btBlockApp);
layout->addStretch();
layout->addWidget(m_btLogOptions);
return layout;
}
void ProgramsWindow::setupLogOptions()
{
setupLogBlocked();

View File

@ -13,6 +13,11 @@ ZonesController::ZonesController(FortManager *fortManager,
this, &ZonesController::retranslateUi);
}
FortSettings *ZonesController::settings() const
{
return fortManager()->settings();
}
ConfManager *ZonesController::confManager() const
{
return fortManager()->confManager();

View File

@ -6,6 +6,7 @@
QT_FORWARD_DECLARE_CLASS(ZoneListModel)
QT_FORWARD_DECLARE_CLASS(ConfManager)
QT_FORWARD_DECLARE_CLASS(FortManager)
QT_FORWARD_DECLARE_CLASS(FortSettings)
QT_FORWARD_DECLARE_CLASS(TranslationManager)
class ZonesController : public QObject
@ -17,6 +18,7 @@ public:
QObject *parent = nullptr);
FortManager *fortManager() const { return m_fortManager; }
FortSettings *settings() const;
ConfManager *confManager() const;
ZoneListModel *zoneListModel() const;
TranslationManager *translationManager() const;

View File

@ -1,13 +1,33 @@
#include "zoneswindow.h"
#include <QCheckBox>
#include <QComboBox>
#include <QDialog>
#include <QFormLayout>
#include <QHeaderView>
#include <QLabel>
#include <QLineEdit>
#include <QMenu>
#include <QPushButton>
#include <QVBoxLayout>
#include "../../conf/confmanager.h"
#include "../../fortmanager.h"
#include "../../fortsettings.h"
#include "../../model/zonelistmodel.h"
#include "../../model/zonesourcewrapper.h"
#include "../../util/guiutil.h"
#include "../controls/controlutil.h"
#include "../controls/tableview.h"
#include "../controls/widebutton.h"
#include "zonescontroller.h"
namespace {
#define ZONES_HEADER_VERSION 1
}
ZonesWindow::ZonesWindow(FortManager *fortManager,
QWidget *parent) :
WidgetWindow(parent),
@ -34,14 +54,40 @@ void ZonesWindow::setupController()
void ZonesWindow::onSaveWindowState()
{
auto header = m_zoneListView->horizontalHeader();
settings()->setZonesHeader(header->saveState());
settings()->setZonesHeaderVersion(ZONES_HEADER_VERSION);
}
void ZonesWindow::onRestoreWindowState()
{
if (settings()->zonesHeaderVersion() != ZONES_HEADER_VERSION)
return;
auto header = m_zoneListView->horizontalHeader();
header->restoreState(settings()->zonesHeader());
}
void ZonesWindow::onRetranslateUi()
{
m_btEdit->setText(tr("Edit"));
m_actAddZone->setText(tr("Add"));
m_actEditZone->setText(tr("Edit"));
m_actRemoveZone->setText(tr("Remove"));
m_labelZoneName->setText(tr("Zone Name:"));
m_labelSource->setText(tr("Source:"));
m_cbEnabled->setText(tr("Enabled"));
m_cbCustomUrl->setText(tr("Custom URL"));
m_labelUrl->setText(tr("URL:"));
m_labelFormData->setText(tr("Form Data:"));
m_btEditOk->setText(tr("OK"));
m_btEditCancel->setText(tr("Cancel"));
m_formZoneEdit->setWindowTitle(tr("Edit Zone"));
zoneListModel()->refresh();
this->setWindowTitle(tr("Zones"));
}
@ -50,6 +96,20 @@ void ZonesWindow::setupUi()
auto layout = new QVBoxLayout();
layout->setContentsMargins(6, 6, 6, 6);
// Zone Add/Edit Form
setupZoneEditForm();
// Header
auto header = setupHeader();
layout->addLayout(header);
// Table
setupTableZones();
setupTableZonesHeader();
layout->addWidget(m_zoneListView, 1);
// Actions on zones table's current changed
setupTableZonesChanged();
this->setLayout(layout);
@ -65,11 +125,295 @@ void ZonesWindow::setupUi()
this->setMinimumSize(500, 400);
}
void ZonesWindow::setupZoneEditForm()
{
auto formLayout = new QFormLayout();
// Zone Name
m_editZoneName = new QLineEdit();
formLayout->addRow("Zone Name:", m_editZoneName);
m_labelZoneName = qobject_cast<QLabel *>(formLayout->labelForField(m_editZoneName));
// Sources
setupComboSources();
formLayout->addRow("Source:", m_comboSources);
m_labelSource = qobject_cast<QLabel *>(formLayout->labelForField(m_comboSources));
// Enabled
m_cbEnabled = new QCheckBox();
formLayout->addRow(QString(), m_cbEnabled);
// Custom URL
m_cbCustomUrl = new QCheckBox();
formLayout->addRow(QString(), m_cbCustomUrl);
// URL
m_editUrl = new QLineEdit();
m_editUrl->setEnabled(false);
formLayout->addRow("URL:", m_editUrl);
m_labelUrl = qobject_cast<QLabel *>(formLayout->labelForField(m_editUrl));
// Form Data
m_editFormData = new QLineEdit();
m_editFormData->setEnabled(false);
formLayout->addRow("Form Data:", m_editFormData);
m_labelFormData = qobject_cast<QLabel *>(formLayout->labelForField(m_editFormData));
// OK/Cancel
auto buttonsLayout = new QHBoxLayout();
m_btEditOk = new QPushButton(QIcon(":/images/tick.png"), QString());
m_btEditOk->setDefault(true);
m_btEditCancel = new QPushButton(QIcon(":/images/cancel.png"), QString());
buttonsLayout->addWidget(m_btEditOk, 1, Qt::AlignRight);
buttonsLayout->addWidget(m_btEditCancel);
// Form
auto layout = new QVBoxLayout();
layout->addLayout(formLayout);
layout->addWidget(ControlUtil::createSeparator());
layout->addLayout(buttonsLayout);
m_formZoneEdit = new QDialog(this);
m_formZoneEdit->setWindowModality(Qt::WindowModal);
m_formZoneEdit->setSizeGripEnabled(true);
m_formZoneEdit->setLayout(layout);
m_formZoneEdit->setMinimumWidth(500);
connect(m_cbCustomUrl, &QCheckBox::toggled, [&](bool checked) {
m_editUrl->setEnabled(checked);
m_editFormData->setEnabled(checked);
});
connect(m_btEditOk, &QAbstractButton::clicked, [&] {
if (saveZoneEditForm()) {
m_formZoneEdit->close();
}
});
connect(m_btEditCancel, &QAbstractButton::clicked, m_formZoneEdit, &QWidget::close);
}
void ZonesWindow::setupComboSources()
{
m_comboSources = new QComboBox();
const auto refreshComboZoneTypes = [&](bool onlyFlags = false) {
if (onlyFlags) return;
m_comboSources->clear();
for (const auto &sourceVar : zoneListModel()->zoneSources()) {
const ZoneSourceWrapper zoneSource(sourceVar);
m_comboSources->addItem(zoneSource.title(), sourceVar);
}
m_comboSources->setCurrentIndex(0);
};
refreshComboZoneTypes();
}
QLayout *ZonesWindow::setupHeader()
{
auto layout = new QHBoxLayout();
// Edit Menu
auto editMenu = new QMenu(this);
m_actAddZone = editMenu->addAction(QIcon(":/images/map_add.png"), QString());
m_actAddZone->setShortcut(Qt::Key_Plus);
m_actEditZone = editMenu->addAction(QIcon(":/images/map_edit.png"), QString());
m_actEditZone->setShortcut(Qt::Key_Enter);
m_actRemoveZone = editMenu->addAction(QIcon(":/images/map_delete.png"), QString());
m_actRemoveZone->setShortcut(Qt::Key_Delete);
connect(m_actAddZone, &QAction::triggered, [&] {
updateZoneEditForm(false);
});
connect(m_actEditZone, &QAction::triggered, [&] {
updateZoneEditForm(true);
});
connect(m_actRemoveZone, &QAction::triggered, [&] {
if (fortManager()->showQuestionBox(tr("Are you sure to remove selected zone?"))) {
deleteSelectedZone();
}
});
m_btEdit = new WideButton(QIcon(":/images/map_edit.png"));
m_btEdit->setMenu(editMenu);
layout->addWidget(m_btEdit);
layout->addStretch();
return layout;
}
void ZonesWindow::setupTableZones()
{
m_zoneListView = new TableView();
m_zoneListView->setIconSize(QSize(24, 24));
m_zoneListView->setAlternatingRowColors(true);
m_zoneListView->setSelectionMode(QAbstractItemView::SingleSelection);
m_zoneListView->setSelectionBehavior(QAbstractItemView::SelectItems);
m_zoneListView->setModel(zoneListModel());
m_zoneListView->setMenu(m_btEdit->menu());
connect(m_zoneListView, &TableView::activated, m_actEditZone, &QAction::trigger);
}
void ZonesWindow::setupTableZonesHeader()
{
auto header = m_zoneListView->horizontalHeader();
header->setSectionResizeMode(0, QHeaderView::Interactive);
header->setSectionResizeMode(1, QHeaderView::Interactive);
header->setSectionResizeMode(2, QHeaderView::Stretch);
header->setSectionResizeMode(3, QHeaderView::Stretch);
header->resizeSection(0, 500);
header->resizeSection(1, 140);
}
void ZonesWindow::setupTableZonesChanged()
{
const auto refreshTableZonesChanged = [&] {
const int zoneIndex = zoneListCurrentIndex();
const bool zoneSelected = (zoneIndex >= 0);
m_actEditZone->setEnabled(zoneSelected);
m_actRemoveZone->setEnabled(zoneSelected);
};
refreshTableZonesChanged();
connect(m_zoneListView, &TableView::currentIndexChanged, this, refreshTableZonesChanged);
}
void ZonesWindow::updateZoneEditForm(bool editCurrentZone)
{
ZoneRow zoneRow;
if (editCurrentZone) {
const auto zoneIndex = zoneListCurrentIndex();
if (zoneIndex < 0) return;
zoneRow = zoneListModel()->zoneRowAt(zoneIndex);
}
const auto zoneSource = ZoneSourceWrapper(
zoneListModel()->zoneSourceByCode(zoneRow.sourceCode));
m_formZoneIsNew = !editCurrentZone;
m_editZoneName->setText(zoneRow.zoneName);
m_editZoneName->selectAll();
m_editZoneName->setFocus();
m_comboSources->setCurrentIndex(zoneSource.index());
m_cbEnabled->setChecked(zoneRow.enabled);
m_cbCustomUrl->setChecked(zoneRow.customUrl);
m_editUrl->setText(zoneRow.url);
m_editFormData->setText(zoneRow.formData);
m_formZoneEdit->show();
}
bool ZonesWindow::saveZoneEditForm()
{
const auto zoneName = m_editZoneName->text();
const bool enabled = m_cbEnabled->isChecked();
const bool customUrl = m_cbCustomUrl->isChecked();
const auto url = m_editUrl->text();
const auto formData = m_editFormData->text();
const auto zoneSource = ZoneSourceWrapper(m_comboSources->currentData());
const auto sourceCode = zoneSource.code();
// Check custom url
if (customUrl && url.isEmpty()) {
m_editUrl->setText(zoneSource.url());
m_editUrl->selectAll();
m_editUrl->setFocus();
m_editFormData->setText(zoneSource.formData());
return false;
}
// Add new zone
if (m_formZoneIsNew) {
return zoneListModel()->addZone(zoneName, sourceCode, url, formData,
enabled, customUrl);
}
// Edit selected zone
const int zoneIndex = zoneListCurrentIndex();
const auto zoneRow = zoneListModel()->zoneRowAt(zoneIndex);
const bool zoneNameEdited = (zoneName != zoneRow.zoneName);
const bool zoneEdited = (sourceCode != zoneRow.sourceCode
|| enabled != zoneRow.enabled
|| customUrl != zoneRow.customUrl
|| url != zoneRow.url
|| formData != zoneRow.formData);
if (!zoneEdited) {
if (zoneNameEdited) {
return zoneListModel()->updateZoneName(zoneRow.zoneId, zoneName);
}
return true;
}
return zoneListModel()->updateZone(zoneRow.zoneId, zoneName, sourceCode,
url, formData, enabled, customUrl,
zoneEdited);
}
void ZonesWindow::updateZone(int row, bool enabled)
{
const auto zoneRow = zoneListModel()->zoneRowAt(row);
zoneListModel()->updateZone(zoneRow.zoneId, zoneRow.zoneName,
zoneRow.sourceCode, zoneRow.url, zoneRow.formData,
enabled, zoneRow.customUrl);
}
void ZonesWindow::deleteZone(int row)
{
const auto zoneRow = zoneListModel()->zoneRowAt(row);
zoneListModel()->deleteZone(zoneRow.zoneId, row);
}
void ZonesWindow::updateSelectedZone(bool enabled)
{
updateZone(zoneListCurrentIndex(), enabled);
}
void ZonesWindow::deleteSelectedZone()
{
deleteZone(zoneListCurrentIndex());
}
int ZonesWindow::zoneListCurrentIndex() const
{
return m_zoneListView->currentIndex().row();
}
FortManager *ZonesWindow::fortManager() const
{
return ctrl()->fortManager();
}
FortSettings *ZonesWindow::settings() const
{
return ctrl()->settings();
}
ConfManager *ZonesWindow::confManager() const
{
return ctrl()->confManager();

View File

@ -4,12 +4,14 @@
#include "../../util/window/widgetwindow.h"
QT_FORWARD_DECLARE_CLASS(QCheckBox)
QT_FORWARD_DECLARE_CLASS(QComboBox)
QT_FORWARD_DECLARE_CLASS(QLabel)
QT_FORWARD_DECLARE_CLASS(QLineEdit)
QT_FORWARD_DECLARE_CLASS(QPushButton)
QT_FORWARD_DECLARE_CLASS(ConfManager)
QT_FORWARD_DECLARE_CLASS(FortManager)
QT_FORWARD_DECLARE_CLASS(FortSettings)
QT_FORWARD_DECLARE_CLASS(TableView)
QT_FORWARD_DECLARE_CLASS(ZoneListModel)
QT_FORWARD_DECLARE_CLASS(ZonesController)
@ -35,7 +37,7 @@ private:
void setupUi();
void setupZoneEditForm();
void setupComboZoneTypes();
void setupComboSources();
QLayout *setupHeader();
void setupTableZones();
void setupTableZonesHeader();
@ -47,16 +49,19 @@ private:
void updateZone(int row, bool enabled);
void deleteZone(int row);
void updateSelectedZone(bool enabled);
void deleteSelectedZone();
int zoneListCurrentIndex() const;
QString zoneListCurrentPath() const;
ZonesController *ctrl() const { return m_ctrl; }
FortManager *fortManager() const;
FortSettings *settings() const;
ConfManager *confManager() const;
ZoneListModel *zoneListModel() const;
private:
bool m_formAppIsNew = false;
bool m_formZoneIsNew = false;
ZonesController *m_ctrl = nullptr;
@ -64,11 +69,12 @@ private:
QAction *m_actAddZone = nullptr;
QAction *m_actEditZone = nullptr;
QAction *m_actRemoveZone = nullptr;
QCheckBox *m_cbEnabled = nullptr;
QLabel *m_labelZoneName = nullptr;
QLineEdit *m_editZoneName = nullptr;
QLabel *m_labelZoneType = nullptr;
QLineEdit *m_editZoneType = nullptr;
QLabel *m_labelSource = nullptr;
QCheckBox *m_cbEnabled = nullptr;
QCheckBox *m_cbCustomUrl = nullptr;
QComboBox *m_comboSources = nullptr;
QLabel *m_labelUrl = nullptr;
QLineEdit *m_editUrl = nullptr;
QLabel *m_labelFormData = nullptr;

View File

@ -34,6 +34,9 @@
<file>images/folder_user.png</file>
<file>images/link.png</file>
<file>images/map.png</file>
<file>images/map_add.png</file>
<file>images/map_delete.png</file>
<file>images/map_edit.png</file>
<file>images/page_copy.png</file>
<file>images/plugin.png</file>
<file>images/plugin_disabled.png</file>

View File

@ -2,7 +2,6 @@
#include <QCommandLineParser>
#include <QCoreApplication>
#include <QJsonDocument>
#include <QSettings>
#include "conf/addressgroup.h"

View File

@ -116,6 +116,12 @@ public:
bool zoneWindowMaximized() const { return iniBool("zoneWindow/maximized"); }
void setZoneWindowMaximized(bool on) { setIniValue("zoneWindow/maximized", on); }
int zonesHeaderVersion() const { return iniInt("zoneWindow/zonesHeaderVersion"); }
void setZonesHeaderVersion(int v) { setIniValue("zoneWindow/zonesHeaderVersion", v); }
QByteArray zonesHeader() const { return iniByteArray("zoneWindow/zonesHeader"); }
void setZonesHeader(const QByteArray &v) { setIniValue("zoneWindow/zonesHeader", v); }
bool graphWindowVisible() const { return iniBool("graphWindow/visible"); }
void setGraphWindowVisible(bool on) { setIniValue("graphWindow/visible", on); }

BIN
src/ui/images/map_add.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 836 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 835 B

BIN
src/ui/images/map_edit.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 876 B

View File

@ -237,12 +237,12 @@ bool AppListModel::addApp(const QString &appPath, const QString &appName,
const QDateTime &endTime, int groupIndex,
bool useGroupPerm, bool blocked)
{
const auto groupId = appGroupAt(groupIndex)->id();
if (!confManager()->updateDriverUpdateApp(
appPath, groupIndex, useGroupPerm, blocked, true))
return false;
const auto groupId = appGroupAt(groupIndex)->id();
if (confManager()->addApp(appPath, appName, endTime, groupId,
useGroupPerm, blocked)) {
reset();
@ -256,12 +256,12 @@ bool AppListModel::updateApp(qint64 appId, const QString &appPath, const QString
const QDateTime &endTime, int groupIndex,
bool useGroupPerm, bool blocked, bool updateDriver)
{
const auto groupId = appGroupAt(groupIndex)->id();
if (updateDriver && !confManager()->updateDriverUpdateApp(
appPath, groupIndex, useGroupPerm, blocked, false))
return false;
const auto groupId = appGroupAt(groupIndex)->id();
if (confManager()->updateApp(appId, appName, endTime, groupId,
useGroupPerm, blocked)) {
refresh();
@ -277,6 +277,7 @@ bool AppListModel::updateAppName(qint64 appId, const QString &appName)
refresh();
return true;
}
return false;
}

View File

@ -1,9 +1,15 @@
#include "zonelistmodel.h"
#include <QJsonDocument>
#include <sqlite/sqlitedb.h>
#include <sqlite/sqlitestmt.h>
#include "../conf/confmanager.h"
#include "../util/fileutil.h"
#include "../util/json/jsonutil.h"
#include "zonesourcewrapper.h"
#include "zonetypewrapper.h"
ZoneListModel::ZoneListModel(ConfManager *confManager,
QObject *parent) :
@ -19,6 +25,8 @@ SqliteDb *ZoneListModel::sqliteDb() const
void ZoneListModel::initialize()
{
initZoneTypes();
initZoneSources();
}
int ZoneListModel::columnCount(const QModelIndex &parent) const
@ -33,7 +41,7 @@ QVariant ZoneListModel::headerData(int section, Qt::Orientation orientation, int
case Qt::DisplayRole: {
switch (section) {
case 0: return tr("Zone");
case 1: return tr("Type");
case 1: return tr("Source");
case 2: return tr("Last Run");
case 3: return tr("Last Success");
}
@ -60,7 +68,11 @@ QVariant ZoneListModel::data(const QModelIndex &index, int role) const
switch (column) {
case 0: return zoneRow.zoneName;
case 1: return zoneRow.zoneType;
case 1: {
const auto zoneSource = ZoneSourceWrapper(
zoneSourceByCode(zoneRow.sourceCode));
return zoneSource.title();
}
case 2: return zoneRow.lastRun;
case 3: return zoneRow.lastSuccess;
}
@ -79,18 +91,58 @@ const ZoneRow &ZoneListModel::zoneRowAt(int row) const
return m_zoneRow;
}
bool ZoneListModel::addZone(const QString &zoneName, const QString &zoneType, const QString &url, const QString &formData, bool enabled)
bool ZoneListModel::addZone(const QString &zoneName, const QString &sourceCode,
const QString &url, const QString &formData,
bool enabled, bool customUrl)
{
if (confManager()->addZone(zoneName, sourceCode,
url, formData, enabled, customUrl)) {
reset();
return true;
}
return false;
}
bool ZoneListModel::updateZone(qint64 zoneId, const QString &zoneName, const QString &zoneType, const QString &url, const QString &formData, bool enabled, bool updateDriver)
bool ZoneListModel::updateZone(qint64 zoneId, const QString &zoneName,
const QString &sourceCode, const QString &url,
const QString &formData, bool enabled, bool customUrl,
bool updateDriver)
{
if (confManager()->updateZone(zoneId, zoneName, sourceCode,
url, formData, enabled, customUrl)) {
refresh();
return true;
}
return false;
}
bool ZoneListModel::updateZoneName(qint64 zoneId, const QString &zoneName)
{
if (confManager()->updateZoneName(zoneId, zoneName)) {
refresh();
return true;
}
return false;
}
void ZoneListModel::deleteZone(qint64 zoneId, int row)
{
beginRemoveRows(QModelIndex(), row, row);
if (confManager()->deleteZone(zoneId)) {
invalidateRowCache();
removeRow(row);
}
endRemoveRows();
}
QVariant ZoneListModel::zoneSourceByCode(const QString &sourceCode) const
{
return m_zoneSourcesMap.value(sourceCode);
}
bool ZoneListModel::updateTableRow(int row) const
@ -101,13 +153,14 @@ bool ZoneListModel::updateTableRow(int row) const
return false;
m_zoneRow.zoneId = stmt.columnInt64(0);
m_zoneRow.enabled = stmt.columnInt(1);
m_zoneRow.zoneName = stmt.columnText(2);
m_zoneRow.zoneType = stmt.columnText(3);
m_zoneRow.url = stmt.columnBool(4);
m_zoneRow.formData = stmt.columnBool(5);
m_zoneRow.lastRun = stmt.columnDateTime(6);
m_zoneRow.lastSuccess = stmt.columnDateTime(7);
m_zoneRow.enabled = stmt.columnBool(1);
m_zoneRow.customUrl = stmt.columnBool(2);
m_zoneRow.zoneName = stmt.columnText(3);
m_zoneRow.sourceCode = stmt.columnText(4);
m_zoneRow.url = stmt.columnText(5);
m_zoneRow.formData = stmt.columnText(6);
m_zoneRow.lastRun = stmt.columnDateTime(7);
m_zoneRow.lastSuccess = stmt.columnDateTime(8);
return true;
}
@ -118,8 +171,9 @@ QString ZoneListModel::sqlBase() const
"SELECT"
" zone_id,"
" enabled,"
" custom_url,"
" name,"
" zone_type,"
" source_code,"
" url,"
" form_data,"
" last_run,"
@ -127,3 +181,47 @@ QString ZoneListModel::sqlBase() const
" FROM zone"
;
}
void ZoneListModel::initZoneTypes()
{
const auto data = FileUtil::readFileData(":/zone/types.json");
if (data.isEmpty())
return;
QString errorString;
const auto zoneTypes = JsonUtil::jsonToVariant(data, errorString).toList();
if (!errorString.isEmpty()) {
qWarning() << "Zone Types: JSON error:" << errorString;
return;
}
int index = 0;
for (auto &typeVar : zoneTypes) {
ZoneTypeWrapper zoneType(typeVar);
zoneType.setIndex(index++);
m_zoneTypesMap.insert(zoneType.code(), typeVar);
m_zoneTypes.append(typeVar);
}
}
void ZoneListModel::initZoneSources()
{
const auto data = FileUtil::readFileData(":/zone/sources.json");
if (data.isEmpty())
return;
QString errorString;
const auto zoneSources = JsonUtil::jsonToVariant(data, errorString).toList();
if (!errorString.isEmpty()) {
qWarning() << "Zone Sources: JSON error:" << errorString;
return;
}
int index = 0;
for (auto &sourceVar : zoneSources) {
ZoneSourceWrapper zoneSource(sourceVar);
zoneSource.setIndex(index++);
m_zoneSourcesMap.insert(zoneSource.code(), sourceVar);
m_zoneSources.append(sourceVar);
}
}

View File

@ -7,14 +7,16 @@
QT_FORWARD_DECLARE_CLASS(ConfManager)
QT_FORWARD_DECLARE_CLASS(SqliteDb)
QT_FORWARD_DECLARE_CLASS(ZoneSourceWrapper)
struct ZoneRow : TableRow {
bool enabled = true;
bool customUrl = false;
qint64 zoneId = 0;
QString zoneName;
QString zoneType;
QString sourceCode;
QString url;
QString formData;
@ -44,24 +46,40 @@ public:
const ZoneRow &zoneRowAt(int row) const;
bool addZone(const QString &zoneName, const QString &zoneType,
bool addZone(const QString &zoneName, const QString &sourceCode,
const QString &url, const QString &formData,
bool enabled);
bool updateZone(qint64 zoneId, const QString &zoneName, const QString &zoneType,
const QString &url, const QString &formData,
bool enabled, bool updateDriver = true);
bool enabled, bool customUrl);
bool updateZone(qint64 zoneId, const QString &zoneName,
const QString &sourceCode, const QString &url,
const QString &formData, bool enabled, bool customUrl,
bool updateDriver = true);
bool updateZoneName(qint64 zoneId, const QString &zoneName);
void deleteZone(qint64 zoneId, int row);
QVariant zoneSourceByCode(const QString &sourceCode) const;
const QVariantList &zoneSources() const { return m_zoneSources; }
protected:
bool updateTableRow(int row) const override;
TableRow &tableRow() const override { return m_zoneRow; }
QString sqlBase() const override;
private:
void initZoneTypes();
void initZoneSources();
void initZoneSourceNames();
private:
ConfManager *m_confManager = nullptr;
mutable ZoneRow m_zoneRow;
QVariantList m_zoneTypes;
QVariantHash m_zoneTypesMap;
QVariantList m_zoneSources;
QVariantHash m_zoneSourcesMap;
};
#endif // ZONELISTMODEL_H

View File

@ -0,0 +1,41 @@
#include "zonesourcewrapper.h"
ZoneSourceWrapper::ZoneSourceWrapper(const QVariant &var) :
MapWrapper(var)
{
}
int ZoneSourceWrapper::index() const
{
return valueInt("index");
}
void ZoneSourceWrapper::setIndex(int index)
{
setValueInt("index", index);
}
QString ZoneSourceWrapper::code() const
{
return valueText("code");
}
QString ZoneSourceWrapper::title() const
{
return valueText("title");
}
QString ZoneSourceWrapper::zoneType() const
{
return valueText("zoneType");
}
QString ZoneSourceWrapper::url() const
{
return valueText("url");
}
QString ZoneSourceWrapper::formData() const
{
return valueText("formData");
}

View File

@ -0,0 +1,21 @@
#ifndef ZONESOURCEWRAPPER_H
#define ZONESOURCEWRAPPER_H
#include "../util/json/mapwrapper.h"
class ZoneSourceWrapper : public MapWrapper
{
public:
explicit ZoneSourceWrapper(const QVariant &var = QVariant());
int index() const;
void setIndex(int index);
QString code() const;
QString title() const;
QString zoneType() const;
QString url() const;
QString formData() const;
};
#endif // ZONESOURCEWRAPPER_H

View File

@ -0,0 +1,46 @@
#include "zonetypewrapper.h"
ZoneTypeWrapper::ZoneTypeWrapper(const QVariant &var) :
MapWrapper(var)
{
}
int ZoneTypeWrapper::index() const
{
return valueInt("index");
}
void ZoneTypeWrapper::setIndex(int index)
{
setValueInt("index", index);
}
QString ZoneTypeWrapper::code() const
{
return valueText("code");
}
QString ZoneTypeWrapper::title() const
{
return valueText("title");
}
QString ZoneTypeWrapper::description() const
{
return valueText("description");
}
bool ZoneTypeWrapper::sort() const
{
return valueBool("sort");
}
QString ZoneTypeWrapper::regex() const
{
return valueText("regex");
}
int ZoneTypeWrapper::emptyNetMask() const
{
return valueInt("emptyNetMask");
}

View File

@ -0,0 +1,22 @@
#ifndef ZONEWRAPPER_H
#define ZONEWRAPPER_H
#include "../util/json/mapwrapper.h"
class ZoneTypeWrapper : public MapWrapper
{
public:
explicit ZoneTypeWrapper(const QVariant &var = QVariant());
int index() const;
void setIndex(int index);
QString code() const;
QString title() const;
QString description() const;
bool sort() const;
QString regex() const;
int emptyNetMask() const;
};
#endif // ZONEWRAPPER_H

View File

@ -1,12 +1,13 @@
#include "taskupdatechecker.h"
#include <QDateTime>
#include <QJsonDocument>
#include <QDebug>
#include <QVariant>
#include "../../common/version.h"
#include "../util/net/netdownloader.h"
#include "../util/net/netutil.h"
#include "../util/json/jsonutil.h"
TaskUpdateChecker::TaskUpdateChecker(QObject *parent) :
TaskDownloader(parent)
@ -29,16 +30,13 @@ void TaskUpdateChecker::downloadFinished(bool success)
bool TaskUpdateChecker::parseBuffer(const QByteArray &buffer)
{
QJsonParseError jsonParseError{};
const QJsonDocument jsonDoc = QJsonDocument::fromJson(
buffer, &jsonParseError);
if (jsonParseError.error != QJsonParseError::NoError) {
// TODO: jsonParseError.errorString()
QString errorString;
const auto map = JsonUtil::jsonToVariant(buffer, errorString).toMap();
if (!errorString.isEmpty()) {
qWarning() << "Update Checker: JSON error:" << errorString;
return false;
}
const QVariantMap map = jsonDoc.toVariant().toMap();
// Version (eg. "v1.4.0")
const QString tagName = map["tag_name"].toString();
m_version = tagName.mid(1);

View File

@ -0,0 +1,15 @@
#include "jsonutil.h"
#include <QJsonDocument>
QVariant JsonUtil::jsonToVariant(const QByteArray &data, QString &errorString)
{
QJsonParseError jsonParseError{};
const QJsonDocument jsonDoc = QJsonDocument::fromJson(data, &jsonParseError);
if (jsonParseError.error != QJsonParseError::NoError) {
errorString = jsonParseError.errorString();
return QVariant();
}
return jsonDoc.toVariant();
}

View File

@ -0,0 +1,13 @@
#ifndef JSONUTIL_H
#define JSONUTIL_H
#include <QObject>
class JsonUtil
{
public:
static QVariant jsonToVariant(const QByteArray &data,
QString &errorString);
};
#endif // JSONUTIL_H

View File

@ -0,0 +1,36 @@
#include "mapwrapper.h"
MapWrapper::MapWrapper(const QVariant &var) :
m_map(var.toMap())
{
}
int MapWrapper::valueInt(const QString &key) const
{
return value(key).toInt();
}
bool MapWrapper::valueBool(const QString &key) const
{
return value(key).toBool();
}
QString MapWrapper::valueText(const QString &key) const
{
return value(key).toString();
}
QVariant MapWrapper::value(const QString &key) const
{
return map().value(key);
}
void MapWrapper::setValueInt(const QString &key, int v)
{
setValue(key, v);
}
void MapWrapper::setValue(const QString &key, const QVariant &v)
{
m_map[key] = v;
}

View File

@ -0,0 +1,27 @@
#ifndef JSONWRAPPER_H
#define JSONWRAPPER_H
#include <QObject>
#include <QVariantMap>
class MapWrapper
{
public:
explicit MapWrapper(const QVariant &var = QVariant());
const QVariantMap &map() const { return m_map; }
protected:
int valueInt(const QString &key) const;
bool valueBool(const QString &key) const;
QString valueText(const QString &key) const;
QVariant value(const QString &key) const;
void setValueInt(const QString &key, int v);
void setValue(const QString &key, const QVariant &v);
private:
QVariantMap m_map;
};
#endif // JSONWRAPPER_H

View File

@ -2,11 +2,6 @@
#include <QCryptographicHash>
StringUtil::StringUtil(QObject *parent) :
QObject(parent)
{
}
QString StringUtil::capitalize(const QString &text)
{
const QChar firstChar = text.at(0);

View File

@ -3,20 +3,16 @@
#include <QObject>
class StringUtil : public QObject
class StringUtil
{
Q_OBJECT
public:
explicit StringUtil(QObject *parent = nullptr);
static QString capitalize(const QString &text);
Q_INVOKABLE static QString capitalize(const QString &text);
static QString cryptoHash(const QString &text);
Q_INVOKABLE static QString cryptoHash(const QString &text);
Q_INVOKABLE static int lineStart(const QString &text, int pos,
static int lineStart(const QString &text, int pos,
int badPos = -1);
Q_INVOKABLE static int lineEnd(const QString &text, int pos,
static int lineEnd(const QString &text, int pos,
int badPos = -1);
};