UI: Rules: Rule id per type

This commit is contained in:
Nodir Temirkhodjaev 2024-03-09 12:49:23 +03:00
parent e609352940
commit c1421f00b1
11 changed files with 117 additions and 35 deletions

View File

@ -18,17 +18,19 @@ namespace {
const QLoggingCategory LC("confRule"); const QLoggingCategory LC("confRule");
const char *const sqlInsertRule = "INSERT INTO rule(rule_id, enabled, blocked, exclusive, name," const char *const sqlInsertRule = "INSERT INTO rule(rule_id, enabled, blocked, exclusive,"
" notes, rule_text, accept_zones, reject_zones, mod_time)" " name, notes, rule_text, rule_type,"
" VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10);"; " accept_zones, reject_zones, mod_time)"
" VALUES(?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11);";
const char *const sqlUpdateRule = "UPDATE rule" const char *const sqlUpdateRule = "UPDATE rule"
" SET enabled = ?2, blocked = ?3, exclusive = ?4," " SET enabled = ?2, blocked = ?3, exclusive = ?4,"
" name = ?5, notes = ?6, rule_text = ?7," " name = ?5, notes = ?6, rule_text = ?7, rule_type = ?8,"
" accept_zones = ?8, reject_zones = ?9, mod_time = ?10" " accept_zones = ?9, reject_zones = ?10, mod_time = ?11"
" WHERE rule_id = ?1;"; " WHERE rule_id = ?1;";
const char *const sqlSelectRuleIds = "SELECT rule_id FROM rule ORDER BY rule_id;"; const char *const sqlSelectRuleIds = "SELECT rule_id FROM rule"
" WHERE rule_id >= ?1 ORDER BY rule_id;";
const char *const sqlDeleteRule = "DELETE FROM rule WHERE rule_id = ?1;"; const char *const sqlDeleteRule = "DELETE FROM rule WHERE rule_id = ?1;";
@ -83,7 +85,8 @@ bool ConfRuleManager::addOrUpdateRule(Rule &rule)
const bool isNew = (rule.ruleId == 0); const bool isNew = (rule.ruleId == 0);
if (isNew) { if (isNew) {
rule.ruleId = DbUtil::getFreeId(sqliteDb(), sqlSelectRuleIds, ConfUtil::ruleMaxCount(), ok); const auto range = Rule::getRuleIdRangeByType(rule.ruleType);
rule.ruleId = DbUtil::getFreeId(sqliteDb(), sqlSelectRuleIds, range.minId, range.maxId, ok);
} else { } else {
updateDriverRuleFlag(rule.ruleId, rule.enabled); updateDriverRuleFlag(rule.ruleId, rule.enabled);
} }
@ -96,6 +99,7 @@ bool ConfRuleManager::addOrUpdateRule(Rule &rule)
rule.ruleName, rule.ruleName,
rule.notes, rule.notes,
rule.ruleText, rule.ruleText,
rule.ruleType,
rule.acceptZones, rule.acceptZones,
rule.rejectZones, rule.rejectZones,
DateUtil::now(), DateUtil::now(),

View File

@ -27,7 +27,8 @@ const char *const sqlUpdateZone = "UPDATE zone"
" form_data = ?7, text_inline = ?8" " form_data = ?7, text_inline = ?8"
" WHERE zone_id = ?1;"; " WHERE zone_id = ?1;";
const char *const sqlSelectZoneIds = "SELECT zone_id FROM zone ORDER BY zone_id;"; const char *const sqlSelectZoneIds = "SELECT zone_id FROM zone"
" WHERE zone_id >= ?1 ORDER BY zone_id;";
const char *const sqlDeleteZone = "DELETE FROM zone WHERE zone_id = ?1;"; const char *const sqlDeleteZone = "DELETE FROM zone WHERE zone_id = ?1;";
@ -99,7 +100,8 @@ bool ConfZoneManager::addOrUpdateZone(Zone &zone)
const bool isNew = (zone.zoneId == 0); const bool isNew = (zone.zoneId == 0);
if (isNew) { if (isNew) {
zone.zoneId = DbUtil::getFreeId(sqliteDb(), sqlSelectZoneIds, ConfUtil::zoneMaxCount(), ok); zone.zoneId = DbUtil::getFreeId(sqliteDb(), sqlSelectZoneIds, /*minId=*/1,
/*maxId=*/ConfUtil::zoneMaxCount() - 1, ok);
} else { } else {
updateDriverZoneFlag(zone.zoneId, zone.enabled); updateDriverZoneFlag(zone.zoneId, zone.enabled);
} }

View File

@ -92,7 +92,7 @@ CREATE TABLE rule(
name TEXT NOT NULL, name TEXT NOT NULL,
notes TEXT, notes TEXT,
rule_text TEXT NOT NULL, rule_text TEXT NOT NULL,
rule_type INTEGER NOT NULL, -- app rules (1..64), global before/after apps (65..96, 97..128), preset rules (129..255) rule_type INTEGER NOT NULL, -- app rules, global before/after apps, preset rules
accept_zones INTEGER NOT NULL DEFAULT 0, -- zone indexes bit mask accept_zones INTEGER NOT NULL DEFAULT 0, -- zone indexes bit mask
reject_zones INTEGER NOT NULL DEFAULT 0, -- zone indexes bit mask reject_zones INTEGER NOT NULL DEFAULT 0, -- zone indexes bit mask
mod_time INTEGER NOT NULL mod_time INTEGER NOT NULL

View File

@ -11,3 +11,26 @@ bool Rule::isOptionsEqual(const Rule &o) const
&& acceptZones == o.acceptZones && rejectZones == o.rejectZones && acceptZones == o.acceptZones && rejectZones == o.rejectZones
&& ruleName == o.ruleName && notes == o.notes && ruleText == o.ruleText; && ruleName == o.ruleName && notes == o.notes && ruleText == o.ruleText;
} }
Rule::RuleType Rule::getRuleTypeById(int ruleId)
{
for (int i = 0; i < RuleTypeCount; ++i) {
const auto ruleType = RuleType(i);
const auto range = getRuleIdRangeByType(ruleType);
if (ruleId >= range.minId && ruleId <= range.maxId)
return ruleType;
}
Q_UNREACHABLE();
return AppRule;
}
RuleIdRange Rule::getRuleIdRangeByType(RuleType ruleType)
{
static const RuleIdRange ruleIdRanges[] = { { 1, 64 }, { 65, 96 }, { 97, 128 }, { 129, 255 } };
Q_ASSERT(ruleType >= 0 && ruleType < RuleTypeCount);
return ruleIdRanges[ruleType];
}

View File

@ -4,16 +4,35 @@
#include <QDateTime> #include <QDateTime>
#include <QObject> #include <QObject>
struct RuleIdRange
{
int minId;
int maxId;
};
class Rule class Rule
{ {
public: public:
enum RuleType : qint8 {
AppRule = 0, // 1..64
GlobalBeforeAppsRule, // 65..96
GlobalAfterAppsRule, // 97..128
PresetRule, // 129..255
RuleTypeCount
};
bool isNameEqual(const Rule &o) const; bool isNameEqual(const Rule &o) const;
bool isOptionsEqual(const Rule &o) const; bool isOptionsEqual(const Rule &o) const;
static RuleType getRuleTypeById(int ruleId);
static RuleIdRange getRuleIdRangeByType(RuleType ruleType);
public: public:
bool enabled = true; bool enabled : 1 = true;
bool blocked = false; bool blocked : 1 = false;
bool exclusive = false; bool exclusive : 1 = false;
RuleType ruleType = AppRule;
int ruleId = 0; int ruleId = 0;

View File

@ -37,11 +37,15 @@ void RuleEditDialog::initialize(const RuleRow &ruleRow)
retranslateUi(); retranslateUi();
m_editName->setText(m_ruleRow.ruleName); m_editName->setText(ruleRow.ruleName);
m_editName->setClearButtonEnabled(true); m_editName->setClearButtonEnabled(true);
m_editNotes->setText(m_ruleRow.notes);
m_labelEditNotes->setPixmap(IconCache::file(":/icons/script.png")); m_labelEditNotes->setPixmap(IconCache::file(":/icons/script.png"));
m_editNotes->setText(ruleRow.notes);
m_labelRuleType->setText(tr("Type:"));
m_comboRuleType->setCurrentIndex(ruleRow.ruleType);
m_comboRuleType->setEnabled(isEmpty());
m_cbEnabled->setChecked(ruleRow.enabled); m_cbEnabled->setChecked(ruleRow.enabled);
@ -75,6 +79,9 @@ void RuleEditDialog::retranslateUi()
m_labelEditName->setText(tr("Name:")); m_labelEditName->setText(tr("Name:"));
m_editNotes->setPlaceholderText(tr("Notes")); m_editNotes->setPlaceholderText(tr("Notes"));
retranslateComboRuleType();
m_cbEnabled->setText(tr("Enabled")); m_cbEnabled->setText(tr("Enabled"));
m_rbAllow->setText(tr("Allow")); m_rbAllow->setText(tr("Allow"));
@ -89,6 +96,15 @@ void RuleEditDialog::retranslateUi()
this->setWindowTitle(tr("Edit Rule")); this->setWindowTitle(tr("Edit Rule"));
} }
void RuleEditDialog::retranslateComboRuleType()
{
const QStringList list = { tr("Application Rules"),
tr("Global Rules, applied before App Rules"), tr("Global Rules, applied after App Rules"),
tr("Preset Rules") };
ControlUtil::setComboBoxTexts(m_comboRuleType, list);
}
void RuleEditDialog::setupUi() void RuleEditDialog::setupUi()
{ {
// Main Layout // Main Layout
@ -105,7 +121,7 @@ void RuleEditDialog::setupUi()
this->setSizeGripEnabled(true); this->setSizeGripEnabled(true);
// Size // Size
this->setMinimumSize(500, 300); this->setMinimumWidth(400);
} }
QLayout *RuleEditDialog::setupMainLayout() QLayout *RuleEditDialog::setupMainLayout()
@ -143,6 +159,7 @@ QLayout *RuleEditDialog::setupMainLayout()
QLayout *RuleEditDialog::setupFormLayout() QLayout *RuleEditDialog::setupFormLayout()
{ {
auto layout = new QFormLayout(); auto layout = new QFormLayout();
layout->setHorizontalSpacing(10);
// Name // Name
m_editName = new QLineEdit(); m_editName = new QLineEdit();
@ -160,6 +177,13 @@ QLayout *RuleEditDialog::setupFormLayout()
m_labelEditNotes->setScaledContents(true); m_labelEditNotes->setScaledContents(true);
m_labelEditNotes->setFixedSize(32, 32); m_labelEditNotes->setFixedSize(32, 32);
// Rule Type
m_comboRuleType = ControlUtil::createComboBox();
m_comboRuleType->setMinimumWidth(100);
layout->addRow("Type:", m_comboRuleType);
m_labelRuleType = ControlUtil::formRowLabel(layout, m_comboRuleType);
// Enabled // Enabled
m_cbEnabled = new QCheckBox(); m_cbEnabled = new QCheckBox();
@ -268,6 +292,8 @@ bool RuleEditDialog::validateFields() const
void RuleEditDialog::fillRule(Rule &rule) const void RuleEditDialog::fillRule(Rule &rule) const
{ {
rule.ruleType = Rule::RuleType(m_comboRuleType->currentIndex());
rule.enabled = m_cbEnabled->isChecked(); rule.enabled = m_cbEnabled->isChecked();
rule.blocked = !m_rbAllow->isChecked(); rule.blocked = !m_rbAllow->isChecked();
rule.exclusive = m_cbExclusive->isChecked(); rule.exclusive = m_cbExclusive->isChecked();

View File

@ -6,6 +6,7 @@
#include <model/rulelistmodel.h> #include <model/rulelistmodel.h>
QT_FORWARD_DECLARE_CLASS(QCheckBox) QT_FORWARD_DECLARE_CLASS(QCheckBox)
QT_FORWARD_DECLARE_CLASS(QComboBox)
QT_FORWARD_DECLARE_CLASS(QLabel) QT_FORWARD_DECLARE_CLASS(QLabel)
QT_FORWARD_DECLARE_CLASS(QLineEdit) QT_FORWARD_DECLARE_CLASS(QLineEdit)
QT_FORWARD_DECLARE_CLASS(QPushButton) QT_FORWARD_DECLARE_CLASS(QPushButton)
@ -37,6 +38,7 @@ private:
void setupController(); void setupController();
void retranslateUi(); void retranslateUi();
void retranslateComboRuleType();
void setupUi(); void setupUi();
QLayout *setupMainLayout(); QLayout *setupMainLayout();
@ -59,6 +61,8 @@ private:
QLineEdit *m_editName = nullptr; QLineEdit *m_editName = nullptr;
QLabel *m_labelEditNotes = nullptr; QLabel *m_labelEditNotes = nullptr;
PlainTextEdit *m_editNotes = nullptr; PlainTextEdit *m_editNotes = nullptr;
QLabel *m_labelRuleType = nullptr;
QComboBox *m_comboRuleType = nullptr;
QCheckBox *m_cbEnabled = nullptr; QCheckBox *m_cbEnabled = nullptr;
QRadioButton *m_rbAllow = nullptr; QRadioButton *m_rbAllow = nullptr;
QRadioButton *m_rbBlock = nullptr; QRadioButton *m_rbBlock = nullptr;

View File

@ -208,9 +208,10 @@ bool RuleListModel::updateRuleRow(
ruleRow.ruleName = stmt.columnText(4); ruleRow.ruleName = stmt.columnText(4);
ruleRow.notes = stmt.columnText(5); ruleRow.notes = stmt.columnText(5);
ruleRow.ruleText = stmt.columnText(6); ruleRow.ruleText = stmt.columnText(6);
ruleRow.acceptZones = stmt.columnUInt(7); ruleRow.ruleType = Rule::RuleType(stmt.columnInt(7));
ruleRow.rejectZones = stmt.columnUInt(8); ruleRow.acceptZones = stmt.columnUInt(8);
ruleRow.modTime = stmt.columnDateTime(9); ruleRow.rejectZones = stmt.columnUInt(9);
ruleRow.modTime = stmt.columnDateTime(10);
return true; return true;
} }
@ -225,6 +226,7 @@ QString RuleListModel::sqlBase() const
" name," " name,"
" notes," " notes,"
" rule_text," " rule_text,"
" rule_type,"
" accept_zones," " accept_zones,"
" reject_zones," " reject_zones,"
" mod_time" " mod_time"

View File

@ -94,8 +94,8 @@ bool ConfRuleManagerRpc::updateRuleEnabled(int ruleId, bool enabled)
QVariantList ConfRuleManagerRpc::ruleToVarList(const Rule &rule) QVariantList ConfRuleManagerRpc::ruleToVarList(const Rule &rule)
{ {
return { rule.enabled, rule.blocked, rule.exclusive, rule.ruleId, rule.acceptZones, return { rule.enabled, rule.blocked, rule.exclusive, rule.ruleType, rule.ruleId,
rule.rejectZones, rule.ruleName, rule.notes, rule.ruleText }; rule.acceptZones, rule.rejectZones, rule.ruleName, rule.notes, rule.ruleText };
} }
Rule ConfRuleManagerRpc::varListToRule(const QVariantList &v) Rule ConfRuleManagerRpc::varListToRule(const QVariantList &v)
@ -104,12 +104,13 @@ Rule ConfRuleManagerRpc::varListToRule(const QVariantList &v)
rule.enabled = v.value(0).toBool(); rule.enabled = v.value(0).toBool();
rule.blocked = v.value(1).toBool(); rule.blocked = v.value(1).toBool();
rule.exclusive = v.value(2).toBool(); rule.exclusive = v.value(2).toBool();
rule.ruleId = v.value(3).toInt(); rule.ruleType = Rule::RuleType(v.value(3).toInt());
rule.acceptZones = v.value(4).toUInt(); rule.ruleId = v.value(4).toInt();
rule.rejectZones = v.value(5).toUInt(); rule.acceptZones = v.value(5).toUInt();
rule.ruleName = v.value(6).toString(); rule.rejectZones = v.value(6).toUInt();
rule.notes = v.value(7).toString(); rule.ruleName = v.value(7).toString();
rule.ruleText = v.value(8).toString(); rule.notes = v.value(8).toString();
rule.ruleText = v.value(9).toString();
return rule; return rule;
} }

View File

@ -3,22 +3,22 @@
#include <sqlite/sqlitedb.h> #include <sqlite/sqlitedb.h>
#include <sqlite/sqlitestmt.h> #include <sqlite/sqlitestmt.h>
int DbUtil::getFreeId(SqliteDb *sqliteDb, const char *sqlSelectIds, int maxCount, bool &ok) int DbUtil::getFreeId(SqliteDb *sqliteDb, const char *sqlSelectIds, int minId, int maxId, bool &ok)
{ {
int freeId = 1;
SqliteStmt stmt; SqliteStmt stmt;
if (stmt.prepare(sqliteDb->db(), sqlSelectIds)) { if (stmt.prepare(sqliteDb->db(), sqlSelectIds)) {
stmt.bindInt(1, minId);
while (stmt.step() == SqliteStmt::StepRow) { while (stmt.step() == SqliteStmt::StepRow) {
const int id = stmt.columnInt(0); const int id = stmt.columnInt(0);
if (freeId < id) if (minId < id || id >= maxId)
break; break;
freeId = id + 1; minId = id + 1;
} }
} }
ok = (freeId < maxCount); ok = (minId <= maxId);
return freeId; return minId;
} }

View File

@ -8,7 +8,8 @@ class SqliteDb;
class DbUtil class DbUtil
{ {
public: public:
static int getFreeId(SqliteDb *sqliteDb, const char *sqlSelectIds, int maxCount, bool &ok); static int getFreeId(
SqliteDb *sqliteDb, const char *sqlSelectIds, int minId, int maxId, bool &ok);
}; };
#endif // DBUTIL_H #endif // DBUTIL_H