diff --git a/src/ui/FortFirewallUI.pro b/src/ui/FortFirewallUI.pro index ab278a0b..7d37a852 100644 --- a/src/ui/FortFirewallUI.pro +++ b/src/ui/FortFirewallUI.pro @@ -96,6 +96,7 @@ SOURCES += \ model/applistmodel.cpp \ model/appstatmodel.cpp \ model/connlistmodel.cpp \ + model/policylistmodel.cpp \ model/servicelistmodel.cpp \ model/traflistmodel.cpp \ model/zonelistmodel.cpp \ @@ -251,6 +252,7 @@ HEADERS += \ model/applistmodel.h \ model/appstatmodel.h \ model/connlistmodel.h \ + model/policylistmodel.h \ model/servicelistmodel.h \ model/traflistmodel.h \ model/zonelistmodel.h \ diff --git a/src/ui/conf/migrations/1.sql b/src/ui/conf/migrations/1.sql index ab1c150a..ae6d9487 100644 --- a/src/ui/conf/migrations/1.sql +++ b/src/ui/conf/migrations/1.sql @@ -29,6 +29,7 @@ CREATE TABLE address_group( CREATE TABLE rule( rule_id INTEGER PRIMARY KEY, enabled BOOLEAN NOT NULL, + deleted BOOLEAN, -- to reuse the rule_id block BOOLEAN NOT NULL, report BOOLEAN NOT NULL, log BOOLEAN NOT NULL, @@ -43,13 +44,18 @@ CREATE TABLE rule( extra TEXT -- TCP flags, ICMP types, etc ); +CREATE INDEX rule_deleted_idx ON rule(deleted); + CREATE TABLE policy( policy_id INTEGER PRIMARY KEY, is_preset BOOLEAN NOT NULL, enabled BOOLEAN NOT NULL, + deleted BOOLEAN, -- to reuse the policy_id name TEXT NOT NULL ); +CREATE INDEX policy_deleted_idx ON policy(deleted); + CREATE TABLE policy_rule( policy_rule_id INTEGER PRIMARY KEY, policy_id INTEGER NOT NULL, @@ -69,14 +75,12 @@ CREATE TABLE policy_set( CREATE INDEX policy_set_policy_id_idx ON policy_set(policy_id); CREATE TABLE policy_list( - policy_list_id INTEGER PRIMARY KEY, + policy_id INTEGER PRIMARY KEY, type INTEGER NOT NULL, -- preset_lib, preset_app, global_before_app, global_after_app - policy_id INTEGER NOT NULL, order_index INTEGER NOT NULL -); +) WITHOUT ROWID; -CREATE INDEX policy_list_type_idx ON policy_list(type); -CREATE INDEX policy_list_policy_id_idx ON policy_list(policy_id); +CREATE INDEX policy_list_type_order_idx ON policy_list(type, order_index); CREATE TABLE policy_menu( policy_menu_id INTEGER PRIMARY KEY, diff --git a/src/ui/model/policylistmodel.cpp b/src/ui/model/policylistmodel.cpp new file mode 100644 index 00000000..96c428a9 --- /dev/null +++ b/src/ui/model/policylistmodel.cpp @@ -0,0 +1,141 @@ +#include "policylistmodel.h" + +#include +#include + +#include +#include + +PolicyListModel::PolicyListModel(PolicyListType type, QObject *parent) : + TableSqlModel(parent), m_type(type) +{ +} + +ConfManager *PolicyListModel::confManager() const +{ + return IoC(); +} + +SqliteDb *PolicyListModel::sqliteDb() const +{ + return confManager()->sqliteDb(); +} + +void PolicyListModel::initialize() +{ + connect(confManager(), &ConfManager::confChanged, this, &TableItemModel::reset); +} + +int PolicyListModel::columnCount(const QModelIndex &parent) const +{ + return parent.isValid() ? 0 : 1; +} + +QVariant PolicyListModel::data(const QModelIndex &index, int role) const +{ + if (!index.isValid()) + return QVariant(); + + switch (role) { + // Label + case Qt::DisplayRole: + case Qt::ToolTipRole: + return dataDisplay(index); + + // Enabled + case Qt::CheckStateRole: + return dataCheckState(index); + } + + return QVariant(); +} + +QVariant PolicyListModel::dataDisplay(const QModelIndex &index) const +{ + const int row = index.row(); + + const auto policyRow = policyRowAt(row); + + return policyRow.name; +} + +QVariant PolicyListModel::dataCheckState(const QModelIndex &index) const +{ + if (index.column() == 0) { + const auto policyRow = policyRowAt(index.row()); + return policyRow.enabled; + } + + return QVariant(); +} + +bool PolicyListModel::setData(const QModelIndex &index, const QVariant &value, int role) +{ + Q_UNUSED(value); + + if (!index.isValid()) + return false; + + switch (role) { + case Qt::CheckStateRole: + const auto policyRow = policyRowAt(index.row()); + return false; // confManager()->updatePolicyEnabled(policyRow.policyId, !policyRow.enabled); + } + + return false; +} + +Qt::ItemFlags PolicyListModel::flagIsUserCheckable(const QModelIndex &index) const +{ + return index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags; +} + +const PolicyRow &PolicyListModel::policyRowAt(int row) const +{ + updateRowCache(row); + + return m_policyRow; +} + +bool PolicyListModel::updateTableRow(int row) const +{ + return updatePolicyRow(sql(), { row }, m_policyRow); +} + +bool PolicyListModel::updatePolicyRow( + const QString &sql, const QVariantList &vars, PolicyRow &policyRow) const +{ + SqliteStmt stmt; + if (!(sqliteDb()->prepare(stmt, sql, vars) && stmt.step() == SqliteStmt::StepRow)) { + policyRow.invalidate(); + return false; + } + + policyRow.policyId = stmt.columnInt(0); + policyRow.isPreset = stmt.columnBool(1); + policyRow.enabled = stmt.columnBool(2); + policyRow.name = stmt.columnText(3); + + return true; +} + +QString PolicyListModel::sqlBase() const +{ + return "SELECT" + " t.policy_id," + " p.is_preset," + " p.enabled," + " p.name" + " FROM policy_list t" + " JOIN policy p ON p.policy_id = t.policy_id"; +} + +QString PolicyListModel::sqlOrder() const +{ + return " t.order_index"; +} + +QString PolicyListModel::sqlWhere() const +{ + return QString::fromLatin1(" WHERE t.type = %1").arg(type()); +} diff --git a/src/ui/model/policylistmodel.h b/src/ui/model/policylistmodel.h new file mode 100644 index 00000000..72964cb2 --- /dev/null +++ b/src/ui/model/policylistmodel.h @@ -0,0 +1,75 @@ +#ifndef POLICYLISTMODEL_H +#define POLICYLISTMODEL_H + +#include +#include + +#include + +class ConfManager; +class SqliteDb; + +struct PolicyRow : TableRow +{ + bool isPreset = false; + bool enabled = true; + + int policyId = 0; + + QString name; +}; + +class PolicyListModel : public TableSqlModel +{ + Q_OBJECT + +public: + enum PolicyListType { + PolicyListInvalid = -1, + PolicyListNone = 0, + PolicyListPresetLibrary, + PolicyListPresetApp, + PolicyListGlobalBeforeApp, + PolicyListGlobalAfterApp, + PolicyListCount + }; + + explicit PolicyListModel(PolicyListType type, QObject *parent = nullptr); + + PolicyListType type() const { return m_type; } + + ConfManager *confManager() const; + SqliteDb *sqliteDb() const override; + + void initialize(); + + int columnCount(const QModelIndex &parent = QModelIndex()) const override; + + QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; + bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; + + const PolicyRow &policyRowAt(int row) const; + +protected: + Qt::ItemFlags flagIsUserCheckable(const QModelIndex &index) const override; + + bool updateTableRow(int row) const override; + TableRow &tableRow() const override { return m_policyRow; } + + QString sqlBase() const override; + QString sqlOrder() const override; + QString sqlWhere() const override; + +private: + QVariant dataDisplay(const QModelIndex &index) const; + QVariant dataCheckState(const QModelIndex &index) const; + + bool updatePolicyRow(const QString &sql, const QVariantList &vars, PolicyRow &policyRow) const; + +private: + PolicyListType m_type = PolicyListNone; + + mutable PolicyRow m_policyRow; +}; + +#endif // POLICYLISTMODEL_H diff --git a/src/ui/model/zonelistmodel.cpp b/src/ui/model/zonelistmodel.cpp index ce02d825..a7cea67c 100644 --- a/src/ui/model/zonelistmodel.cpp +++ b/src/ui/model/zonelistmodel.cpp @@ -141,15 +141,9 @@ bool ZoneListModel::setData(const QModelIndex &index, const QVariant &value, int return false; } -Qt::ItemFlags ZoneListModel::flags(const QModelIndex &index) const +Qt::ItemFlags ZoneListModel::flagIsUserCheckable(const QModelIndex &index) const { - if (!index.isValid()) - return Qt::NoItemFlags; - - const int column = index.column(); - - return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren - | (column == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags); + return index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags; } const ZoneRow &ZoneListModel::zoneRowAt(int row) const diff --git a/src/ui/model/zonelistmodel.h b/src/ui/model/zonelistmodel.h index a9748089..275e97d4 100644 --- a/src/ui/model/zonelistmodel.h +++ b/src/ui/model/zonelistmodel.h @@ -52,8 +52,6 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - Qt::ItemFlags flags(const QModelIndex &index) const override; - const ZoneRow &zoneRowAt(int row) const; QString zoneNameById(int zoneId); @@ -64,6 +62,8 @@ public: const QVariantList &zoneSources() const { return m_zoneSources; } protected: + Qt::ItemFlags flagIsUserCheckable(const QModelIndex &index) const override; + bool updateTableRow(int row) const override; TableRow &tableRow() const override { return m_zoneRow; } diff --git a/src/ui/task/tasklistmodel.cpp b/src/ui/task/tasklistmodel.cpp index 5a72fc51..ed362543 100644 --- a/src/ui/task/tasklistmodel.cpp +++ b/src/ui/task/tasklistmodel.cpp @@ -131,15 +131,9 @@ bool TaskListModel::setData(const QModelIndex &index, const QVariant &value, int return false; } -Qt::ItemFlags TaskListModel::flags(const QModelIndex &index) const +Qt::ItemFlags TaskListModel::flagIsUserCheckable(const QModelIndex &index) const { - if (!index.isValid()) - return Qt::NoItemFlags; - - const int column = index.column(); - - return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren - | (column == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags); + return index.column() == 0 ? Qt::ItemIsUserCheckable : Qt::NoItemFlags; } void TaskListModel::setupTaskRows() diff --git a/src/ui/task/tasklistmodel.h b/src/ui/task/tasklistmodel.h index 96dbb8fb..8df7a79c 100644 --- a/src/ui/task/tasklistmodel.h +++ b/src/ui/task/tasklistmodel.h @@ -33,8 +33,6 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override; - Qt::ItemFlags flags(const QModelIndex &index) const override; - void setupTaskRows(); QVariant toVariant() const; @@ -43,6 +41,8 @@ signals: void dataEdited(); protected: + Qt::ItemFlags flagIsUserCheckable(const QModelIndex &index) const override; + bool updateTableRow(int /*row*/) const override { return true; } TableRow &tableRow() const override { return m_taskRow; } diff --git a/src/ui/util/model/tableitemmodel.cpp b/src/ui/util/model/tableitemmodel.cpp index 407f5377..a4eadc15 100644 --- a/src/ui/util/model/tableitemmodel.cpp +++ b/src/ui/util/model/tableitemmodel.cpp @@ -31,7 +31,13 @@ Qt::ItemFlags TableItemModel::flags(const QModelIndex &index) const if (!index.isValid()) return Qt::NoItemFlags; - return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren; + return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemNeverHasChildren + | flagIsUserCheckable(index); +} + +Qt::ItemFlags TableItemModel::flagIsUserCheckable(const QModelIndex & /*index*/) const +{ + return Qt::NoItemFlags; } void TableItemModel::reset() diff --git a/src/ui/util/model/tableitemmodel.h b/src/ui/util/model/tableitemmodel.h index 98c40786..fd2a9876 100644 --- a/src/ui/util/model/tableitemmodel.h +++ b/src/ui/util/model/tableitemmodel.h @@ -33,6 +33,8 @@ public slots: void refresh(); protected: + virtual Qt::ItemFlags flagIsUserCheckable(const QModelIndex &index) const; + virtual void invalidateRowCache(); void updateRowCache(int row) const; diff --git a/src/ui/util/model/tablesqlmodel.cpp b/src/ui/util/model/tablesqlmodel.cpp index 810913eb..2c05e4ad 100644 --- a/src/ui/util/model/tablesqlmodel.cpp +++ b/src/ui/util/model/tablesqlmodel.cpp @@ -40,7 +40,7 @@ int TableSqlModel::doSqlCount() const QString TableSqlModel::sqlCount() const { - return "SELECT COUNT(*) FROM (" + sqlBase() + ");"; + return "SELECT COUNT(*) FROM (" + sqlBase() + sqlWhere() + ");"; } QString TableSqlModel::sql() const