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