diff --git a/src/tests/db/test.cpp b/src/tests/db/test.cpp index ec0d8af1..fe64f9df 100644 --- a/src/tests/db/test.cpp +++ b/src/tests/db/test.cpp @@ -132,6 +132,26 @@ void Test::debugStatTrafStep(SqliteDb *sqliteDb, const char *name, qDebug() << "--"; } +void Test::activePeriod() +{ + const QDate d1(2018, 8, 31); + const QTime t1(15, 35, 24); + const QDateTime dt1(d1, t1); + + const qint64 unixTime = dt1.toSecsSinceEpoch(); + const qint32 unixDay = DateUtil::getUnixDay(unixTime); + const qint32 unixHour = DateUtil::getUnixHour(unixTime); + + QVERIFY(DateUtil::isHourBetween(unixHour, unixDay, 0, 24)); + QVERIFY(DateUtil::isHourBetween(unixHour, unixDay, 15, 15)); + QVERIFY(DateUtil::isHourBetween(unixHour, unixDay, 15, 16)); + QVERIFY(DateUtil::isHourBetween(unixHour, unixDay, 15, 10)); + QVERIFY(DateUtil::isHourBetween(unixHour, unixDay, 16, 15)); + QVERIFY(!DateUtil::isHourBetween(unixHour, unixDay, 24, 0)); + QVERIFY(!DateUtil::isHourBetween(unixHour, unixDay, 16, 14)); + QVERIFY(!DateUtil::isHourBetween(unixHour, unixDay, 16, 24)); +} + void Test::monthStart() { const QDate d1(2018, 1, 8); diff --git a/src/tests/db/test.h b/src/tests/db/test.h index 3bc4cf9e..b6c5592b 100644 --- a/src/tests/db/test.h +++ b/src/tests/db/test.h @@ -11,6 +11,7 @@ class Test : public QObject private slots: void dbWriteRead(); + void activePeriod(); void monthStart(); private: diff --git a/src/ui/conf/firewallconf.cpp b/src/ui/conf/firewallconf.cpp index cdf55d13..267e6ccf 100644 --- a/src/ui/conf/firewallconf.cpp +++ b/src/ui/conf/firewallconf.cpp @@ -18,6 +18,9 @@ FirewallConf::FirewallConf(QObject *parent) : m_logStat(false), m_appBlockAll(true), m_appAllowAll(false), + m_activePeriodEnabled(false), + m_activePeriodFrom(0), + m_activePeriodTo(0), m_monthStart(DEFAULT_MONTH_START), m_trafHourKeepDays(DEFAULT_TRAF_HOUR_KEEP_DAYS), m_trafDayKeepDays(DEFAULT_TRAF_DAY_KEEP_DAYS), @@ -110,6 +113,30 @@ void FirewallConf::setAppAllowAll(bool appAllowAll) } } +void FirewallConf::setActivePeriodEnabled(bool activePeriodEnabled) +{ + if (m_activePeriodEnabled != activePeriodEnabled) { + m_activePeriodEnabled = activePeriodEnabled; + emit activePeriodEnabledChanged(); + } +} + +void FirewallConf::setActivePeriodFrom(int activePeriodFrom) +{ + if (m_activePeriodFrom != activePeriodFrom) { + m_activePeriodFrom = uint(activePeriodFrom); + emit activePeriodFromChanged(); + } +} + +void FirewallConf::setActivePeriodTo(int activePeriodTo) +{ + if (m_activePeriodTo != activePeriodTo) { + m_activePeriodTo = uint(activePeriodTo); + emit activePeriodToChanged(); + } +} + void FirewallConf::setMonthStart(int monthStart) { if (m_monthStart != monthStart) { @@ -263,6 +290,10 @@ void FirewallConf::copyFlags(const FirewallConf &o) setPasswordHash(o.passwordHash()); setAppGroupBits(o.appGroupBits()); + setActivePeriodEnabled(o.activePeriodEnabled()); + setActivePeriodFrom(o.activePeriodFrom()); + setActivePeriodTo(o.activePeriodTo()); + setMonthStart(o.monthStart()); setTrafHourKeepDays(o.trafHourKeepDays()); setTrafDayKeepDays(o.trafDayKeepDays()); diff --git a/src/ui/conf/firewallconf.h b/src/ui/conf/firewallconf.h index 66c6bfca..de093166 100644 --- a/src/ui/conf/firewallconf.h +++ b/src/ui/conf/firewallconf.h @@ -27,6 +27,9 @@ class FirewallConf : public QObject Q_PROPERTY(bool logStat READ logStat WRITE setLogStat NOTIFY logStatChanged) Q_PROPERTY(bool appBlockAll READ appBlockAll WRITE setAppBlockAll NOTIFY appBlockAllChanged) Q_PROPERTY(bool appAllowAll READ appAllowAll WRITE setAppAllowAll NOTIFY appAllowAllChanged) + Q_PROPERTY(bool activePeriodEnabled READ activePeriodEnabled WRITE setActivePeriodEnabled NOTIFY activePeriodEnabledChanged) + Q_PROPERTY(int activePeriodFrom READ activePeriodFrom WRITE setActivePeriodFrom NOTIFY activePeriodFromChanged) + Q_PROPERTY(int activePeriodTo READ activePeriodTo WRITE setActivePeriodTo NOTIFY activePeriodToChanged) Q_PROPERTY(int monthStart READ monthStart WRITE setMonthStart NOTIFY monthStartChanged) Q_PROPERTY(int trafHourKeepDays READ trafHourKeepDays WRITE setTrafHourKeepDays NOTIFY trafHourKeepDaysChanged) Q_PROPERTY(int trafDayKeepDays READ trafDayKeepDays WRITE setTrafDayKeepDays NOTIFY trafDayKeepDaysChanged) @@ -84,6 +87,15 @@ public: bool appAllowAll() const { return m_appAllowAll; } void setAppAllowAll(bool appAllowAll); + bool activePeriodEnabled() const { return m_activePeriodEnabled; } + void setActivePeriodEnabled(bool activePeriodEnabled); + + int activePeriodFrom() const { return m_activePeriodFrom; } + void setActivePeriodFrom(int activePeriodFrom); + + int activePeriodTo() const { return m_activePeriodTo; } + void setActivePeriodTo(int activePeriodTo); + int monthStart() const { return m_monthStart; } void setMonthStart(int monthStart); @@ -142,6 +154,9 @@ signals: void logStatChanged(); void appBlockAllChanged(); void appAllowAllChanged(); + void activePeriodEnabledChanged(); + void activePeriodFromChanged(); + void activePeriodToChanged(); void monthStartChanged(); void trafHourKeepDaysChanged(); void trafDayKeepDaysChanged(); @@ -174,6 +189,10 @@ private: uint m_appBlockAll : 1; uint m_appAllowAll : 1; + uint m_activePeriodEnabled : 1; + uint m_activePeriodFrom : 5; + uint m_activePeriodTo : 5; + uint m_monthStart : 5; int m_trafHourKeepDays; diff --git a/src/ui/db/databasemanager.cpp b/src/ui/db/databasemanager.cpp index 030b1f0a..a907c8d4 100644 --- a/src/ui/db/databasemanager.cpp +++ b/src/ui/db/databasemanager.cpp @@ -182,7 +182,8 @@ void DatabaseManager::logProcNew(quint32 pid, const QString &appPath) qint64 appId = getAppId(appPath); if (appId == INVALID_APP_ID) { - appId = createAppId(appPath); + const qint64 unixTime = DateUtil::getUnixTime(); + appId = createAppId(appPath, unixTime); } m_sqliteDb->commitTransaction(); @@ -235,69 +236,77 @@ void DatabaseManager::logStatTraf(quint16 procCount, const quint32 *procTrafByte m_sqliteDb->beginTransaction(); - // Insert Statemets - const QStmtList insertTrafAppStmts = QStmtList() - << getTrafficStmt(DatabaseSql::sqlInsertTrafAppHour, trafHour) - << getTrafficStmt(DatabaseSql::sqlInsertTrafAppDay, trafDay) - << getTrafficStmt(DatabaseSql::sqlInsertTrafAppMonth, trafMonth) - << getTrafficStmt(DatabaseSql::sqlUpdateTrafAppTotal, -1); + // Store the data + const bool isActivePeriod = !m_conf->activePeriodEnabled() + || DateUtil::isHourBetween(trafHour, trafDay, + m_conf->activePeriodFrom(), + m_conf->activePeriodTo()); - const QStmtList insertTrafStmts = QStmtList() - << getTrafficStmt(DatabaseSql::sqlInsertTrafHour, trafHour) - << getTrafficStmt(DatabaseSql::sqlInsertTrafDay, trafDay) - << getTrafficStmt(DatabaseSql::sqlInsertTrafMonth, trafMonth); + if (isActivePeriod) { + // Insert Statements + const QStmtList insertTrafAppStmts = QStmtList() + << getTrafficStmt(DatabaseSql::sqlInsertTrafAppHour, trafHour) + << getTrafficStmt(DatabaseSql::sqlInsertTrafAppDay, trafDay) + << getTrafficStmt(DatabaseSql::sqlInsertTrafAppMonth, trafMonth) + << getTrafficStmt(DatabaseSql::sqlUpdateTrafAppTotal, -1); - // Update Statemets - const QStmtList updateTrafAppStmts = QStmtList() - << getTrafficStmt(DatabaseSql::sqlUpdateTrafAppHour, trafHour) - << getTrafficStmt(DatabaseSql::sqlUpdateTrafAppDay, trafDay) - << getTrafficStmt(DatabaseSql::sqlUpdateTrafAppMonth, trafMonth) - << getTrafficStmt(DatabaseSql::sqlUpdateTrafAppTotal, -1); + const QStmtList insertTrafStmts = QStmtList() + << getTrafficStmt(DatabaseSql::sqlInsertTrafHour, trafHour) + << getTrafficStmt(DatabaseSql::sqlInsertTrafDay, trafDay) + << getTrafficStmt(DatabaseSql::sqlInsertTrafMonth, trafMonth); - const QStmtList updateTrafStmts = QStmtList() - << getTrafficStmt(DatabaseSql::sqlUpdateTrafHour, trafHour) - << getTrafficStmt(DatabaseSql::sqlUpdateTrafDay, trafDay) - << getTrafficStmt(DatabaseSql::sqlUpdateTrafMonth, trafMonth); + // Update Statements + const QStmtList updateTrafAppStmts = QStmtList() + << getTrafficStmt(DatabaseSql::sqlUpdateTrafAppHour, trafHour) + << getTrafficStmt(DatabaseSql::sqlUpdateTrafAppDay, trafDay) + << getTrafficStmt(DatabaseSql::sqlUpdateTrafAppMonth, trafMonth) + << getTrafficStmt(DatabaseSql::sqlUpdateTrafAppTotal, -1); - for (int i = 0; i < procCount; ++i) { - quint32 pid = *procTrafBytes++; - const bool inactive = (pid & 1) != 0; - const quint32 inBytes = *procTrafBytes++; - const quint32 outBytes = *procTrafBytes++; + const QStmtList updateTrafStmts = QStmtList() + << getTrafficStmt(DatabaseSql::sqlUpdateTrafHour, trafHour) + << getTrafficStmt(DatabaseSql::sqlUpdateTrafDay, trafDay) + << getTrafficStmt(DatabaseSql::sqlUpdateTrafMonth, trafMonth); - if (inactive) { - pid ^= 1; - } + for (int i = 0; i < procCount; ++i) { + quint32 pid = *procTrafBytes++; + const bool inactive = (pid & 1) != 0; + const quint32 inBytes = *procTrafBytes++; + const quint32 outBytes = *procTrafBytes++; - const int procIndex = m_appIndexes.value(pid, INVALID_APP_INDEX); - if (procIndex == INVALID_APP_INDEX) { - qCritical(CLOG_DATABASE_MANAGER()) << "UI & Driver's states mismatch."; - abort(); - } - - if (inBytes || outBytes) { - qint64 appId = m_appIds.at(procIndex); - - // Was the app cleared? - if (appId == INVALID_APP_ID) { - appId = createAppId(m_appPaths.at(procIndex)); - replaceAppIdAt(procIndex, appId); + if (inactive) { + pid ^= 1; } - // Update or insert app bytes - updateTrafficList(insertTrafAppStmts, updateTrafAppStmts, - inBytes, outBytes, appId); + const int procIndex = m_appIndexes.value(pid, INVALID_APP_INDEX); + if (procIndex == INVALID_APP_INDEX) { + qCritical(CLOG_DATABASE_MANAGER()) << "UI & Driver's states mismatch."; + abort(); + } - // Update or insert total bytes - updateTrafficList(insertTrafStmts, updateTrafStmts, - inBytes, outBytes); + if (inBytes || outBytes) { + qint64 appId = m_appIds.at(procIndex); - // Update quota traffic bytes - m_quotaManager->addTraf(inBytes); - } + // Was the app cleared? + if (appId == INVALID_APP_ID) { + appId = createAppId(m_appPaths.at(procIndex), unixTime); + replaceAppIdAt(procIndex, appId); + } - if (inactive) { - logClearApp(pid, procIndex); + // Update or insert app bytes + updateTrafficList(insertTrafAppStmts, updateTrafAppStmts, + inBytes, outBytes, appId); + + // Update or insert total bytes + updateTrafficList(insertTrafStmts, updateTrafStmts, + inBytes, outBytes); + + // Update quota traffic bytes + m_quotaManager->addTraf(inBytes); + } + + if (inactive) { + logClearApp(pid, procIndex); + } } } @@ -361,7 +370,7 @@ void DatabaseManager::deleteApp(qint64 appId) { clearAppId(appId); - // Delete Statemets + // Delete Statements const QStmtList deleteAppStmts = QStmtList() << getAppStmt(DatabaseSql::sqlDeleteAppTrafHour, appId) << getAppStmt(DatabaseSql::sqlDeleteAppTrafDay, appId) @@ -401,12 +410,11 @@ qint64 DatabaseManager::getAppId(const QString &appPath) return appId; } -qint64 DatabaseManager::createAppId(const QString &appPath) +qint64 DatabaseManager::createAppId(const QString &appPath, qint64 unixTime) { qint64 appId = INVALID_APP_ID; SqliteStmt *stmt = getSqliteStmt(DatabaseSql::sqlInsertAppId); - const qint64 unixTime = DateUtil::getUnixTime(); stmt->bindText(1, appPath); stmt->bindInt64(2, unixTime); diff --git a/src/ui/db/databasemanager.h b/src/ui/db/databasemanager.h index 8a6cc002..02a9b4bb 100644 --- a/src/ui/db/databasemanager.h +++ b/src/ui/db/databasemanager.h @@ -67,7 +67,7 @@ private: void logClearApp(quint32 pid, int index); qint64 getAppId(const QString &appPath); - qint64 createAppId(const QString &appPath); + qint64 createAppId(const QString &appPath, qint64 unixTime); void updateTrafficList(const QStmtList &insertStmtList, const QStmtList &updateStmtList, diff --git a/src/ui/fort_qml.qrc b/src/ui/fort_qml.qrc index 6e83e669..6a3379b4 100644 --- a/src/ui/fort_qml.qrc +++ b/src/ui/fort_qml.qrc @@ -9,6 +9,8 @@ qml/controls/ScrollBarControl.qml qml/controls/SpinCombo.qml qml/controls/SpinComboRow.qml + qml/controls/SpinDouble.qml + qml/controls/SpinDoubleRow.qml qml/controls/SwipeViewControl.qml qml/controls/TextAreaFrame.qml qml/controls/TextContextMenu.qml diff --git a/src/ui/fortsettings.cpp b/src/ui/fortsettings.cpp index bc8a6a78..819f8417 100644 --- a/src/ui/fortsettings.cpp +++ b/src/ui/fortsettings.cpp @@ -238,6 +238,9 @@ bool FortSettings::readConfIni(FirewallConf &conf) const m_ini->endGroup(); m_ini->beginGroup("stat"); + conf.setActivePeriodEnabled(iniBool("activePeriodEnabled")); + conf.setActivePeriodFrom(iniInt("activePeriodFrom")); + conf.setActivePeriodTo(iniInt("activePeriodTo")); conf.setMonthStart(iniInt("monthStart", DEFAULT_MONTH_START)); conf.setTrafHourKeepDays(iniInt("trafHourKeepDays", DEFAULT_TRAF_HOUR_KEEP_DAYS)); conf.setTrafDayKeepDays(iniInt("trafDayKeepDays", DEFAULT_TRAF_DAY_KEEP_DAYS)); @@ -270,6 +273,9 @@ bool FortSettings::writeConfIni(const FirewallConf &conf) m_ini->endGroup(); m_ini->beginGroup("stat"); + setIniValue("activePeriodEnabled", conf.activePeriodEnabled()); + setIniValue("activePeriodFrom", conf.activePeriodFrom()); + setIniValue("activePeriodTo", conf.activePeriodTo()); setIniValue("monthStart", conf.monthStart(), DEFAULT_MONTH_START); setIniValue("trafHourKeepDays", conf.trafHourKeepDays(), DEFAULT_TRAF_HOUR_KEEP_DAYS); setIniValue("trafDayKeepDays", conf.trafDayKeepDays(), DEFAULT_TRAF_DAY_KEEP_DAYS); diff --git a/src/ui/i18n/i18n_ru.qm b/src/ui/i18n/i18n_ru.qm index edbe33e0..401bb8ab 100644 Binary files a/src/ui/i18n/i18n_ru.qm and b/src/ui/i18n/i18n_ru.qm differ diff --git a/src/ui/i18n/i18n_ru.ts b/src/ui/i18n/i18n_ru.ts index 54fe128b..1f57a93c 100644 --- a/src/ui/i18n/i18n_ru.ts +++ b/src/ui/i18n/i18n_ru.ts @@ -88,17 +88,17 @@ FortSettings - + Can't write .ini file Не удалось записать .ini файл - + Can't create .conf file Не удалось создать .conf файл - + Can't create backup .conf file Не удалось создать бэкап .conf файла @@ -158,12 +158,12 @@ TaskInfo - + Update Checker Проверка обновлений - + TAS-IX Addresses Downloader Загрузчик TAS-IX адресов @@ -511,32 +511,37 @@ 3 года - + + Active period, hours: + Активный период, часы + + + Month starts on: Месяц начинается с: - + Keep days for 'Hourly': Хранить дней для 'Почасовая': - + Keep days for 'Daily': Хранить дней для 'Ежедневная': - + Keep months for 'Monthly': Хранить месяцев для 'Ежемесячная': - + Day's Quota: Квота на день - + Month's Quota: Квота на месяц diff --git a/src/ui/qml/controls/SpinDouble.qml b/src/ui/qml/controls/SpinDouble.qml new file mode 100644 index 00000000..a9366456 --- /dev/null +++ b/src/ui/qml/controls/SpinDouble.qml @@ -0,0 +1,33 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.5 +import QtQuick.Layouts 1.3 + +RowLayout { + + readonly property alias field1: field1 + readonly property alias field2: field2 + + property real fieldPreferredWidth + + SpinBox { + id: field1 + Layout.fillWidth: true + Layout.preferredWidth: fieldPreferredWidth + Layout.minimumWidth: fieldPreferredWidth + + editable: true + from: 0 + to: 9999 + } + + SpinBox { + id: field2 + Layout.fillWidth: true + Layout.preferredWidth: fieldPreferredWidth + Layout.minimumWidth: fieldPreferredWidth + + editable: true + from: 0 + to: 9999 + } +} diff --git a/src/ui/qml/controls/SpinDoubleRow.qml b/src/ui/qml/controls/SpinDoubleRow.qml new file mode 100644 index 00000000..51e45f1e --- /dev/null +++ b/src/ui/qml/controls/SpinDoubleRow.qml @@ -0,0 +1,25 @@ +import QtQuick 2.12 +import QtQuick.Controls 2.5 +import QtQuick.Layouts 1.3 +import com.fortfirewall 1.0 + +RowLayout { + + Layout.fillWidth: true + + readonly property alias checkBox: checkBox + readonly property alias field1: spinDouble.field1 + readonly property alias field2: spinDouble.field2 + + CheckBox { + id: checkBox + Layout.fillWidth: true + } + + SpinDouble { + id: spinDouble + Layout.maximumWidth: implicitWidth + + fieldPreferredWidth: 140 + } +} diff --git a/src/ui/qml/pages/log/TrafOptionsButton.qml b/src/ui/qml/pages/log/TrafOptionsButton.qml index 8e55c549..b96abeb1 100644 --- a/src/ui/qml/pages/log/TrafOptionsButton.qml +++ b/src/ui/qml/pages/log/TrafOptionsButton.qml @@ -62,6 +62,51 @@ ButtonPopup { } ColumnLayout { + SpinDoubleRow { + checkBox { + text: translationManager.trTrigger + && qsTranslate("qml", "Active period, hours:") + checked: firewallConf.activePeriodEnabled + onCheckedChanged: { + const value = checkBox.checked; + if (firewallConf.activePeriodEnabled == value) + return; + + firewallConf.activePeriodEnabled = value; + + setConfFlagsEdited(); + } + } + field1 { + from: 0 + to: 24 + value: firewallConf.activePeriodFrom + onValueChanged: { + const value = field1.value; + if (firewallConf.activePeriodFrom == value) + return; + + firewallConf.activePeriodFrom = value; + + setConfFlagsEdited(); + } + } + field2 { + from: 0 + to: 24 + value: firewallConf.activePeriodTo + onValueChanged: { + const value = field2.value; + if (firewallConf.activePeriodTo == value) + return; + + firewallConf.activePeriodTo = value; + + setConfFlagsEdited(); + } + } + } + SpinComboRow { values: { var arr = []; diff --git a/src/ui/util/dateutil.cpp b/src/ui/util/dateutil.cpp index 6c45d0b6..83eeac65 100644 --- a/src/ui/util/dateutil.cpp +++ b/src/ui/util/dateutil.cpp @@ -80,3 +80,13 @@ QString DateUtil::formatDateTime(qint64 unixTime, const QString &format) const QDateTime dt = QDateTime::fromSecsSinceEpoch(unixTime); return QLocale().toString(dt, format); } + +bool DateUtil::isHourBetween(qint32 unixHour, qint32 unixDay, + int fromHour, int toHour) +{ + const int hour = unixHour - unixDay; + + return fromHour <= toHour + ? (hour >= fromHour && hour <= toHour) + : (hour == 0 || hour >= fromHour || hour <= toHour); +} diff --git a/src/ui/util/dateutil.h b/src/ui/util/dateutil.h index 47e020c7..5bb112f5 100644 --- a/src/ui/util/dateutil.h +++ b/src/ui/util/dateutil.h @@ -29,6 +29,9 @@ public: static QString formatMonth(qint64 unixTime); static QString formatDateTime(qint64 unixTime, const QString &format); + + static bool isHourBetween(qint32 unixHour, qint32 unixDay, + int fromHour, int toHour); }; #endif // DATEUTIL_H