diff --git a/src/ui/FortFirewall.pro b/src/ui/FortFirewall.pro
index 3a2d95fb..9c97ab9d 100644
--- a/src/ui/FortFirewall.pro
+++ b/src/ui/FortFirewall.pro
@@ -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}) {
diff --git a/src/ui/conf/conf-zone.qrc b/src/ui/conf/conf-zone.qrc
new file mode 100644
index 00000000..2e29ae9c
--- /dev/null
+++ b/src/ui/conf/conf-zone.qrc
@@ -0,0 +1,6 @@
+
+
+ zone/sources.json
+ zone/types.json
+
+
diff --git a/src/ui/conf/confmanager.cpp b/src/ui/conf/confmanager.cpp
index d2b31208..e665f029 100644
--- a/src/ui/conf/confmanager.cpp
+++ b/src/ui/conf/confmanager.cpp
@@ -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;
diff --git a/src/ui/conf/confmanager.h b/src/ui/conf/confmanager.h
index 025f29e8..3f45aaff 100644
--- a/src/ui/conf/confmanager.h
+++ b/src/ui/conf/confmanager.h
@@ -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);
diff --git a/src/ui/conf/migrations/1.sql b/src/ui/conf/migrations/1.sql
index e32f93c1..886bd3b4 100644
--- a/src/ui/conf/migrations/1.sql
+++ b/src/ui/conf/migrations/1.sql
@@ -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,
diff --git a/src/ui/conf/zone/fort-conf-zone.qrc b/src/ui/conf/zone/fort-conf-zone.qrc
deleted file mode 100644
index 26a61f12..00000000
--- a/src/ui/conf/zone/fort-conf-zone.qrc
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
- zone-types.json
- zone-urls.json
-
-
diff --git a/src/ui/conf/zone/zone-urls.json b/src/ui/conf/zone/sources.json
similarity index 75%
rename from src/ui/conf/zone/zone-urls.json
rename to src/ui/conf/zone/sources.json
index e1b35c65..0d2b77f5 100644
--- a/src/ui/conf/zone/zone-urls.json
+++ b/src/ui/conf/zone/sources.json
@@ -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="
}
diff --git a/src/ui/conf/zone/zone-types.json b/src/ui/conf/zone/types.json
similarity index 87%
rename from src/ui/conf/zone/zone-types.json
rename to src/ui/conf/zone/types.json
index bb8c17b1..6af61736 100644
--- a/src/ui/conf/zone/zone-types.json
+++ b/src/ui/conf/zone/types.json
@@ -1,6 +1,6 @@
[
{
- "id": "bgp",
+ "code": "bgp",
"title": "BGP",
"description": "BGP table",
"sort": true,
diff --git a/src/ui/form/prog/programswindow.cpp b/src/ui/form/prog/programswindow.cpp
index 439638e3..36345ba2 100644
--- a/src/ui/form/prog/programswindow.cpp
+++ b/src/ui/form/prog/programswindow.cpp
@@ -5,7 +5,6 @@
#include
#include
#include
-#include
#include
#include
#include
@@ -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();
diff --git a/src/ui/form/zone/zonescontroller.cpp b/src/ui/form/zone/zonescontroller.cpp
index 2211f14d..5f30439c 100644
--- a/src/ui/form/zone/zonescontroller.cpp
+++ b/src/ui/form/zone/zonescontroller.cpp
@@ -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();
diff --git a/src/ui/form/zone/zonescontroller.h b/src/ui/form/zone/zonescontroller.h
index c1f0360e..a18f3e07 100644
--- a/src/ui/form/zone/zonescontroller.h
+++ b/src/ui/form/zone/zonescontroller.h
@@ -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;
diff --git a/src/ui/form/zone/zoneswindow.cpp b/src/ui/form/zone/zoneswindow.cpp
index 645f6679..eb47265d 100644
--- a/src/ui/form/zone/zoneswindow.cpp
+++ b/src/ui/form/zone/zoneswindow.cpp
@@ -1,13 +1,33 @@
#include "zoneswindow.h"
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
#include
#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(formLayout->labelForField(m_editZoneName));
+
+ // Sources
+ setupComboSources();
+
+ formLayout->addRow("Source:", m_comboSources);
+ m_labelSource = qobject_cast(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(formLayout->labelForField(m_editUrl));
+
+ // Form Data
+ m_editFormData = new QLineEdit();
+ m_editFormData->setEnabled(false);
+
+ formLayout->addRow("Form Data:", m_editFormData);
+ m_labelFormData = qobject_cast(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();
diff --git a/src/ui/form/zone/zoneswindow.h b/src/ui/form/zone/zoneswindow.h
index 9ba2d7d7..12eb426a 100644
--- a/src/ui/form/zone/zoneswindow.h
+++ b/src/ui/form/zone/zoneswindow.h
@@ -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;
diff --git a/src/ui/fort-images.qrc b/src/ui/fort-images.qrc
index 302c309c..e3cc2643 100644
--- a/src/ui/fort-images.qrc
+++ b/src/ui/fort-images.qrc
@@ -34,6 +34,9 @@
images/folder_user.png
images/link.png
images/map.png
+ images/map_add.png
+ images/map_delete.png
+ images/map_edit.png
images/page_copy.png
images/plugin.png
images/plugin_disabled.png
diff --git a/src/ui/fortsettings.cpp b/src/ui/fortsettings.cpp
index 5d572841..d510e2b0 100644
--- a/src/ui/fortsettings.cpp
+++ b/src/ui/fortsettings.cpp
@@ -2,7 +2,6 @@
#include
#include
-#include
#include
#include "conf/addressgroup.h"
diff --git a/src/ui/fortsettings.h b/src/ui/fortsettings.h
index 21fc72bc..6590d606 100644
--- a/src/ui/fortsettings.h
+++ b/src/ui/fortsettings.h
@@ -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); }
diff --git a/src/ui/images/map_add.png b/src/ui/images/map_add.png
new file mode 100644
index 00000000..2b72da06
Binary files /dev/null and b/src/ui/images/map_add.png differ
diff --git a/src/ui/images/map_delete.png b/src/ui/images/map_delete.png
new file mode 100644
index 00000000..e74402f9
Binary files /dev/null and b/src/ui/images/map_delete.png differ
diff --git a/src/ui/images/map_edit.png b/src/ui/images/map_edit.png
new file mode 100644
index 00000000..93d4d7e5
Binary files /dev/null and b/src/ui/images/map_edit.png differ
diff --git a/src/ui/model/applistmodel.cpp b/src/ui/model/applistmodel.cpp
index 495c18b8..8737ebd0 100644
--- a/src/ui/model/applistmodel.cpp
+++ b/src/ui/model/applistmodel.cpp
@@ -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;
}
diff --git a/src/ui/model/zonelistmodel.cpp b/src/ui/model/zonelistmodel.cpp
index 6d397a57..3059e4ff 100644
--- a/src/ui/model/zonelistmodel.cpp
+++ b/src/ui/model/zonelistmodel.cpp
@@ -1,9 +1,15 @@
#include "zonelistmodel.h"
+#include
+
#include
#include
#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);
+ }
+}
diff --git a/src/ui/model/zonelistmodel.h b/src/ui/model/zonelistmodel.h
index a63908db..4ef92329 100644
--- a/src/ui/model/zonelistmodel.h
+++ b/src/ui/model/zonelistmodel.h
@@ -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
diff --git a/src/ui/model/zonesourcewrapper.cpp b/src/ui/model/zonesourcewrapper.cpp
new file mode 100644
index 00000000..78c6b530
--- /dev/null
+++ b/src/ui/model/zonesourcewrapper.cpp
@@ -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");
+}
diff --git a/src/ui/model/zonesourcewrapper.h b/src/ui/model/zonesourcewrapper.h
new file mode 100644
index 00000000..5244a5a7
--- /dev/null
+++ b/src/ui/model/zonesourcewrapper.h
@@ -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
diff --git a/src/ui/model/zonetypewrapper.cpp b/src/ui/model/zonetypewrapper.cpp
new file mode 100644
index 00000000..0a5f0009
--- /dev/null
+++ b/src/ui/model/zonetypewrapper.cpp
@@ -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");
+}
diff --git a/src/ui/model/zonetypewrapper.h b/src/ui/model/zonetypewrapper.h
new file mode 100644
index 00000000..10a7ed60
--- /dev/null
+++ b/src/ui/model/zonetypewrapper.h
@@ -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
diff --git a/src/ui/task/taskupdatechecker.cpp b/src/ui/task/taskupdatechecker.cpp
index 44fada30..16c0f021 100644
--- a/src/ui/task/taskupdatechecker.cpp
+++ b/src/ui/task/taskupdatechecker.cpp
@@ -1,12 +1,13 @@
#include "taskupdatechecker.h"
#include
-#include
+#include
#include
#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);
diff --git a/src/ui/util/json/jsonutil.cpp b/src/ui/util/json/jsonutil.cpp
new file mode 100644
index 00000000..12af97f3
--- /dev/null
+++ b/src/ui/util/json/jsonutil.cpp
@@ -0,0 +1,15 @@
+#include "jsonutil.h"
+
+#include
+
+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();
+}
diff --git a/src/ui/util/json/jsonutil.h b/src/ui/util/json/jsonutil.h
new file mode 100644
index 00000000..3bce7b9c
--- /dev/null
+++ b/src/ui/util/json/jsonutil.h
@@ -0,0 +1,13 @@
+#ifndef JSONUTIL_H
+#define JSONUTIL_H
+
+#include
+
+class JsonUtil
+{
+public:
+ static QVariant jsonToVariant(const QByteArray &data,
+ QString &errorString);
+};
+
+#endif // JSONUTIL_H
diff --git a/src/ui/util/json/mapwrapper.cpp b/src/ui/util/json/mapwrapper.cpp
new file mode 100644
index 00000000..dd691ab2
--- /dev/null
+++ b/src/ui/util/json/mapwrapper.cpp
@@ -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;
+}
diff --git a/src/ui/util/json/mapwrapper.h b/src/ui/util/json/mapwrapper.h
new file mode 100644
index 00000000..f0b5a31c
--- /dev/null
+++ b/src/ui/util/json/mapwrapper.h
@@ -0,0 +1,27 @@
+#ifndef JSONWRAPPER_H
+#define JSONWRAPPER_H
+
+#include
+#include
+
+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
diff --git a/src/ui/util/stringutil.cpp b/src/ui/util/stringutil.cpp
index ab7fcb76..95670d24 100644
--- a/src/ui/util/stringutil.cpp
+++ b/src/ui/util/stringutil.cpp
@@ -2,11 +2,6 @@
#include
-StringUtil::StringUtil(QObject *parent) :
- QObject(parent)
-{
-}
-
QString StringUtil::capitalize(const QString &text)
{
const QChar firstChar = text.at(0);
diff --git a/src/ui/util/stringutil.h b/src/ui/util/stringutil.h
index 340bf687..d1bcb54f 100644
--- a/src/ui/util/stringutil.h
+++ b/src/ui/util/stringutil.h
@@ -3,21 +3,17 @@
#include
-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,
- int badPos = -1);
- Q_INVOKABLE static int lineEnd(const QString &text, int pos,
- int badPos = -1);
+ static int lineStart(const QString &text, int pos,
+ int badPos = -1);
+ static int lineEnd(const QString &text, int pos,
+ int badPos = -1);
};
#endif // STRINGUTIL_H