UI: Improve Traffic Graph.

This commit is contained in:
Nodir Temirkhodjaev 2019-02-10 20:55:23 +05:00
parent 02db06fa90
commit ffad054bad
27 changed files with 725 additions and 291 deletions

View File

@ -3,10 +3,13 @@
<file>qml/controls/ButtonMenu.qml</file>
<file>qml/controls/ButtonPopup.qml</file>
<file>qml/controls/HSeparator.qml</file>
<file>qml/controls/LabelColorRow.qml</file>
<file>qml/controls/LabelSpinRow.qml</file>
<file>qml/controls/LinkButton.qml</file>
<file>qml/controls/ListViewControl.qml</file>
<file>qml/controls/RoundButtonTip.qml</file>
<file>qml/controls/ScrollBarControl.qml</file>
<file>qml/controls/SpinBoxControl.qml</file>
<file>qml/controls/SpinCombo.qml</file>
<file>qml/controls/SpinComboRow.qml</file>
<file>qml/controls/SpinDouble.qml</file>
@ -31,6 +34,7 @@
<file>qml/pages/apps/AppsTextColumn.qml</file>
<file>qml/pages/apps/SpeedLimitButton.qml</file>
<file>qml/pages/log/AppListView.qml</file>
<file>qml/pages/log/GraphButton.qml</file>
<file>qml/pages/log/IpListView.qml</file>
<file>qml/pages/log/TrafOptionsButton.qml</file>
<file>qml/pages/schedule/TaskRow.qml</file>

View File

@ -41,7 +41,6 @@
FortManager::FortManager(FortSettings *fortSettings,
QObject *parent) :
QObject(parent),
m_exiting(false),
m_trayIcon(new QSystemTrayIcon(this)),
m_engine(nullptr),
m_appWindow(nullptr),
@ -221,8 +220,7 @@ void FortManager::launch()
{
showTrayIcon();
if (m_fortSettings->graphWindowEnabled()
&& m_fortSettings->graphWindowVisible()) {
if (m_fortSettings->graphWindowVisible()) {
showGraphWindow();
}
}
@ -285,8 +283,9 @@ void FortManager::showGraphWindow()
m_graphWindowState->install(m_graphWindow);
connect(m_graphWindow, &GraphWindow::aboutToClose,
this, &FortManager::closeGraphWindow);
connect(m_graphWindow, &GraphWindow::aboutToClose, [this] {
closeGraphWindow();
});
connect(m_graphWindow, &GraphWindow::mouseRightClick,
this, &FortManager::showTrayMenu);
@ -302,12 +301,12 @@ void FortManager::showGraphWindow()
restoreGraphWindowState();
}
void FortManager::closeGraphWindow()
void FortManager::closeGraphWindow(bool storeVisibility)
{
if (!m_graphWindow)
return;
saveGraphWindowState();
saveGraphWindowState(storeVisibility);
m_graphWindowState->uninstall(m_graphWindow);
@ -327,11 +326,18 @@ void FortManager::switchGraphWindow()
closeGraphWindow();
}
void FortManager::updateGraphWindow()
{
if (!m_graphWindow)
return;
m_graphWindow->updateColors();
m_graphWindow->updateWindowFlags();
}
void FortManager::exit(int retcode)
{
m_exiting = true;
closeGraphWindow();
closeGraphWindow(true);
closeWindow();
closeEngine();
@ -538,9 +544,9 @@ void FortManager::restoreWindowState()
m_fortSettings->windowMaximized());
}
void FortManager::saveGraphWindowState()
void FortManager::saveGraphWindowState(bool visible)
{
m_fortSettings->setGraphWindowVisible(m_exiting);
m_fortSettings->setGraphWindowVisible(visible);
m_fortSettings->setGraphWindowGeometry(m_graphWindowState->geometry());
m_fortSettings->setGraphWindowMaximized(m_graphWindowState->maximized());
}
@ -577,16 +583,14 @@ void FortManager::updateTrayMenu()
this, SLOT(showWindow()));
addHotKey(optionsAction, fortSettings()->hotKeyOptions(), hotKeyEnabled);
if (!conf.hasPassword() && !m_firewallConfToEdit) {
if (fortSettings()->graphWindowEnabled()) {
m_graphWindowAction = addAction(
menu, QIcon(":/images/chart_bar.png"), tr("Traffic Graph"),
this, SLOT(switchGraphWindow()), true,
(m_graphWindow != nullptr));
addHotKey(m_graphWindowAction, fortSettings()->hotKeyGraph(),
conf.logStat());
}
m_graphWindowAction = addAction(
menu, QIcon(":/images/chart_bar.png"), tr("Traffic Graph"),
this, SLOT(switchGraphWindow()), true,
(m_graphWindow != nullptr));
addHotKey(m_graphWindowAction, fortSettings()->hotKeyGraph(),
conf.logStat());
if (!conf.hasPassword() && !m_firewallConfToEdit) {
menu->addSeparator();
m_filterEnabledAction = addAction(

View File

@ -57,8 +57,9 @@ public slots:
void closeWindow();
void showGraphWindow();
void closeGraphWindow();
void closeGraphWindow(bool storeVisibility = false);
void switchGraphWindow();
void updateGraphWindow();
void exit(int retcode = 0);
@ -115,7 +116,7 @@ private:
void saveWindowState();
void restoreWindowState();
void saveGraphWindowState();
void saveGraphWindowState(bool visible);
void restoreGraphWindowState();
void updateLogger();
@ -133,8 +134,6 @@ private:
const QObject *receiver = nullptr, const char *member = nullptr);
private:
uint m_exiting : 1;
MainWindow m_window; // dummy window for tray icon
QSystemTrayIcon *m_trayIcon;

View File

@ -12,7 +12,9 @@
FortSettings::FortSettings(const QStringList &args,
QObject *parent) :
QObject(parent),
m_hasProvBoot(false)
m_hasProvBoot(false),
m_bulkUpdating(false),
m_bulkUpdatingEmit(false)
{
processArguments(args);
setupIni();
@ -396,12 +398,39 @@ QVariant FortSettings::iniValue(const QString &key,
void FortSettings::setIniValue(const QString &key, const QVariant &value,
const QVariant &defaultValue)
{
if (!defaultValue.isNull()
&& m_ini->value(key, defaultValue) == value)
const QVariant oldValue = m_ini->value(key, defaultValue);
if (oldValue == value)
return;
m_ini->setValue(key, value);
emit iniChanged();
if (m_bulkUpdating) {
m_bulkUpdatingEmit = true;
} else {
emit iniChanged();
}
}
void FortSettings::bulkUpdateBegin()
{
Q_ASSERT(!m_bulkUpdating);
m_bulkUpdating = true;
m_bulkUpdatingEmit = false;
}
void FortSettings::bulkUpdateEnd()
{
Q_ASSERT(m_bulkUpdating);
m_bulkUpdating = false;
const bool doEmit = m_bulkUpdatingEmit;
m_bulkUpdatingEmit = false;
if (doEmit) {
emit iniChanged();
}
}
void FortSettings::removeIniKey(const QString &key)

View File

@ -18,6 +18,21 @@ class FortSettings : public QObject
Q_OBJECT
Q_PROPERTY(bool debug READ debug WRITE setDebug NOTIFY iniChanged)
Q_PROPERTY(QString language READ language WRITE setLanguage NOTIFY iniChanged)
Q_PROPERTY(bool graphWindowVisible READ graphWindowVisible WRITE setGraphWindowVisible NOTIFY iniChanged)
Q_PROPERTY(bool graphWindowAlwaysOnTop READ graphWindowAlwaysOnTop WRITE setGraphWindowAlwaysOnTop NOTIFY iniChanged)
Q_PROPERTY(bool graphWindowFrameless READ graphWindowFrameless WRITE setGraphWindowFrameless NOTIFY iniChanged)
Q_PROPERTY(bool graphWindowClickThrough READ graphWindowClickThrough WRITE setGraphWindowClickThrough NOTIFY iniChanged)
Q_PROPERTY(bool graphWindowHideOnHover READ graphWindowHideOnHover WRITE setGraphWindowHideOnHover NOTIFY iniChanged)
Q_PROPERTY(int graphWindowOpacity READ graphWindowOpacity WRITE setGraphWindowOpacity NOTIFY iniChanged)
Q_PROPERTY(int graphWindowHoverOpacity READ graphWindowHoverOpacity WRITE setGraphWindowHoverOpacity NOTIFY iniChanged)
Q_PROPERTY(int graphWindowMaxSeconds READ graphWindowMaxSeconds WRITE setGraphWindowMaxSeconds NOTIFY iniChanged)
Q_PROPERTY(QColor graphWindowColor READ graphWindowColor WRITE setGraphWindowColor NOTIFY iniChanged)
Q_PROPERTY(QColor graphWindowColorIn READ graphWindowColorIn WRITE setGraphWindowColorIn NOTIFY iniChanged)
Q_PROPERTY(QColor graphWindowColorOut READ graphWindowColorOut WRITE setGraphWindowColorOut NOTIFY iniChanged)
Q_PROPERTY(QColor graphWindowAxisColor READ graphWindowAxisColor WRITE setGraphWindowAxisColor NOTIFY iniChanged)
Q_PROPERTY(QColor graphWindowTickLabelColor READ graphWindowTickLabelColor WRITE setGraphWindowTickLabelColor NOTIFY iniChanged)
Q_PROPERTY(QColor graphWindowLabelColor READ graphWindowLabelColor WRITE setGraphWindowLabelColor NOTIFY iniChanged)
Q_PROPERTY(QColor graphWindowGridColor READ graphWindowGridColor WRITE setGraphWindowGridColor NOTIFY iniChanged)
Q_PROPERTY(bool startWithWindows READ startWithWindows WRITE setStartWithWindows NOTIFY startWithWindowsChanged)
Q_PROPERTY(bool hotKeyEnabled READ hotKeyEnabled WRITE setHotKeyEnabled NOTIFY iniChanged)
Q_PROPERTY(QString logsPath READ logsPath CONSTANT)
@ -50,9 +65,6 @@ public:
bool windowMaximized() const { return iniBool("window/maximized"); }
void setWindowMaximized(bool on) { setIniValue("window/maximized", on); }
bool graphWindowEnabled() const { return iniBool("graphWindow/enabled"); }
void setGraphWindowEnabled(bool on) { setIniValue("graphWindow/enabled", on); }
bool graphWindowVisible() const { return iniBool("graphWindow/visible"); }
void setGraphWindowVisible(bool on) { setIniValue("graphWindow/visible", on); }
@ -71,6 +83,9 @@ public:
bool graphWindowClickThrough() const { return iniBool("graphWindow/clickThrough"); }
void setGraphWindowClickThrough(bool on) { setIniValue("graphWindow/clickThrough", on); }
bool graphWindowHideOnHover() const { return iniBool("graphWindow/hideOnHover"); }
void setGraphWindowHideOnHover(bool on) { setIniValue("graphWindow/hideOnHover", on); }
int graphWindowOpacity() const { return iniInt("graphWindow/opacity", 10); }
void setGraphWindowOpacity(int v) { setIniValue("graphWindow/opacity", v); }
@ -151,6 +166,9 @@ public slots:
bool readConfIni(FirewallConf &conf) const;
bool writeConfIni(const FirewallConf &conf);
void bulkUpdateBegin();
void bulkUpdateEnd();
private:
void processArguments(const QStringList &args);
void setupIni();
@ -190,7 +208,9 @@ private:
static QString startupShortcutPath();
private:
uint m_hasProvBoot : 1;
uint m_hasProvBoot : 1;
uint m_bulkUpdating : 1;
uint m_bulkUpdatingEmit : 1;
QString m_profilePath;
QString m_statPath;

View File

@ -17,14 +17,13 @@ GraphWindow::GraphWindow(FortSettings *fortSettings,
setupUi();
setupTimer();
setupWindow();
connect(m_fortSettings, &FortSettings::iniChanged, this, &GraphWindow::setupWindow);
updateWindowFlags();
updateColors();
setMinimumSize(QSize(100, 50));
}
void GraphWindow::setupWindow()
void GraphWindow::updateWindowFlags()
{
const bool visible = isVisible();
@ -38,13 +37,36 @@ void GraphWindow::setupWindow()
? Qt::WindowTransparentForInput : Qt::Widget)
);
if (visible) {
show(); // setWindowFlags() hides the window
}
}
void GraphWindow::updateColors()
{
setWindowOpacityPercent(m_fortSettings->graphWindowOpacity());
m_plot->setBackground(QBrush(m_fortSettings->graphWindowColor()));
if (visible) {
show(); // setWindowFlags() hides the window
}
// Axis
auto yAxis = m_plot->yAxis;
const QColor axisColor = m_fortSettings->graphWindowAxisColor();
yAxis->setBasePen(adjustPen(yAxis->basePen(), axisColor));
yAxis->setTickPen(adjustPen(yAxis->tickPen(), axisColor));
yAxis->setSubTickPen(adjustPen(yAxis->subTickPen(), axisColor));
yAxis->setTickLabelColor(m_fortSettings->graphWindowTickLabelColor());
yAxis->setLabelColor(m_fortSettings->graphWindowLabelColor());
yAxis->grid()->setPen(adjustPen(yAxis->grid()->pen(),
m_fortSettings->graphWindowGridColor()));
// Graph Inbound
m_graphIn->setPen(QPen(m_fortSettings->graphWindowColorIn()));
// Graph Outbound
m_graphOut->setPen(QPen(m_fortSettings->graphWindowColorOut()));
}
void GraphWindow::setupUi()
@ -70,17 +92,6 @@ void GraphWindow::setupUi()
yAxis->setPadding(1);
yAxis->setTickLabelPadding(2);
const QColor axisColor = m_fortSettings->graphWindowAxisColor();
yAxis->setBasePen(adjustPen(yAxis->basePen(), axisColor));
yAxis->setTickPen(adjustPen(yAxis->tickPen(), axisColor));
yAxis->setSubTickPen(adjustPen(yAxis->subTickPen(), axisColor));
yAxis->setTickLabelColor(m_fortSettings->graphWindowTickLabelColor());
yAxis->setLabelColor(m_fortSettings->graphWindowLabelColor());
yAxis->grid()->setPen(adjustPen(yAxis->grid()->pen(),
m_fortSettings->graphWindowGridColor()));
// Axis Rect
auto axisRect = m_plot->axisRect();
axisRect->setMinimumMargins(QMargins(1, 1, 1, 1));
@ -92,14 +103,12 @@ void GraphWindow::setupUi()
// Graph Inbound
m_graphIn = new QCPBars(m_plot->xAxis, m_plot->yAxis);
m_graphIn->setAntialiased(false);
m_graphIn->setPen(QPen(m_fortSettings->graphWindowColorIn()));
m_graphIn->setWidthType(QCPBars::wtAbsolute);
m_graphIn->setWidth(1);
// Graph Outbound
m_graphOut = new QCPBars(m_plot->xAxis, m_plot->yAxis);
m_graphOut->setAntialiased(false);
m_graphOut->setPen(QPen(m_fortSettings->graphWindowColorOut()));
m_graphOut->setWidthType(QCPBars::wtAbsolute);
m_graphOut->setWidth(1);
@ -118,9 +127,10 @@ void GraphWindow::setupUi()
void GraphWindow::setupTimer()
{
connect(&m_timer, &QTimer::timeout, this, &GraphWindow::addEmptyTraffic);
connect(&m_hoverTimer, &QTimer::timeout, this, &GraphWindow::checkHoverLeave);
connect(&m_updateTimer, &QTimer::timeout, this, &GraphWindow::addEmptyTraffic);
m_timer.start(1000); // 1 second
m_updateTimer.start(1000); // 1 second
}
void GraphWindow::onMouseDoubleClick(QMouseEvent *event)
@ -161,6 +171,12 @@ void GraphWindow::enterEvent(QEvent *event)
{
Q_UNUSED(event)
if (m_fortSettings->graphWindowHideOnHover()) {
hide();
m_hoverTimer.start(200);
return;
}
setWindowOpacityPercent(m_fortSettings->graphWindowHoverOpacity());
}
@ -171,6 +187,16 @@ void GraphWindow::leaveEvent(QEvent *event)
setWindowOpacityPercent(m_fortSettings->graphWindowOpacity());
}
void GraphWindow::checkHoverLeave()
{
const QPoint mousePos = QCursor::pos();
if (!geometry().contains(mousePos)) {
m_hoverTimer.stop();
show();
}
}
void GraphWindow::addTraffic(qint64 unixTime, quint32 inBytes, quint32 outBytes)
{
const qint64 rangeLower = unixTime - m_fortSettings->graphWindowMaxSeconds();

View File

@ -21,10 +21,13 @@ signals:
void mouseRightClick(QMouseEvent *event);
public slots:
void updateWindowFlags();
void updateColors();
void addTraffic(qint64 unixTime, quint32 inBytes, quint32 outBytes);
private slots:
void setupWindow();
void checkHoverLeave();
void addEmptyTraffic();
@ -59,7 +62,8 @@ private:
QPoint m_mousePressOffset;
QTimer m_timer;
QTimer m_updateTimer;
QTimer m_hoverTimer;
};
#endif // GRAPHWINDOW_H

Binary file not shown.

View File

@ -50,37 +50,42 @@
<context>
<name>FortManager</name>
<message>
<location filename="../fortmanager.cpp" line="317"/>
<location filename="../fortmanager.cpp" line="355"/>
<source>Password input</source>
<translation>Ввод пароля</translation>
</message>
<message>
<location filename="../fortmanager.cpp" line="317"/>
<location filename="../fortmanager.cpp" line="355"/>
<source>Please enter the password</source>
<translation>Наберите пароль пожалуйста</translation>
</message>
<message>
<location filename="../fortmanager.cpp" line="561"/>
<location filename="../fortmanager.cpp" line="582"/>
<source>Options</source>
<translation>Опции</translation>
</message>
<message>
<location filename="../fortmanager.cpp" line="574"/>
<location filename="../fortmanager.cpp" line="587"/>
<source>Traffic Graph</source>
<translation>График трафика</translation>
</message>
<message>
<location filename="../fortmanager.cpp" line="597"/>
<source>Filter Enabled</source>
<translation>Фильтр включен</translation>
</message>
<message>
<location filename="../fortmanager.cpp" line="585"/>
<location filename="../fortmanager.cpp" line="604"/>
<source>Stop Traffic</source>
<translation>Остановить трафик</translation>
</message>
<message>
<location filename="../fortmanager.cpp" line="592"/>
<location filename="../fortmanager.cpp" line="611"/>
<source>Stop Internet Traffic</source>
<translation>Остановить Интернет трафик</translation>
</message>
<message>
<location filename="../fortmanager.cpp" line="620"/>
<location filename="../fortmanager.cpp" line="639"/>
<source>Quit</source>
<translation>Выйти</translation>
</message>
@ -88,17 +93,17 @@
<context>
<name>FortSettings</name>
<message>
<location filename="../fortsettings.cpp" line="202"/>
<location filename="../fortsettings.cpp" line="204"/>
<source>Can&apos;t write .ini file</source>
<translation>Не удалось записать .ini файл</translation>
</message>
<message>
<location filename="../fortsettings.cpp" line="217"/>
<location filename="../fortsettings.cpp" line="219"/>
<source>Can&apos;t create .conf file</source>
<translation>Не удалось создать .conf файл</translation>
</message>
<message>
<location filename="../fortsettings.cpp" line="212"/>
<location filename="../fortsettings.cpp" line="214"/>
<source>Can&apos;t create backup .conf file</source>
<translation>Не удалось создать бэкап .conf файла</translation>
</message>
@ -208,19 +213,19 @@
</message>
<message>
<location filename="../qml/pages/BlockedPage.qml" line="32"/>
<location filename="../qml/pages/StatisticsPage.qml" line="55"/>
<location filename="../qml/pages/StatisticsPage.qml" line="75"/>
<source>Clear</source>
<translation>Очистить</translation>
</message>
<message>
<location filename="../qml/pages/BlockedPage.qml" line="37"/>
<location filename="../qml/pages/StatisticsPage.qml" line="60"/>
<location filename="../qml/pages/StatisticsPage.qml" line="80"/>
<source>Remove Application</source>
<translation>Удалить приложение</translation>
</message>
<message>
<location filename="../qml/pages/BlockedPage.qml" line="43"/>
<location filename="../qml/pages/StatisticsPage.qml" line="71"/>
<location filename="../qml/pages/StatisticsPage.qml" line="91"/>
<source>Clear All</source>
<translation>Очистить всё</translation>
</message>
@ -245,7 +250,7 @@
<translation>Преобразовать адреса</translation>
</message>
<message>
<location filename="../qml/pages/BlockedPage.qml" line="94"/>
<location filename="../qml/pages/BlockedPage.qml" line="91"/>
<source>Show Blocked Applications</source>
<translation>Показ блокированных приложений</translation>
</message>
@ -320,133 +325,133 @@
<translation>период, часы</translation>
</message>
<message>
<location filename="../qml/pages/apps/AppsColumn.qml" line="113"/>
<location filename="../qml/pages/apps/AppsColumn.qml" line="101"/>
<source>Block</source>
<translation>Блокировать</translation>
</message>
<message>
<location filename="../qml/pages/apps/AppsColumn.qml" line="133"/>
<location filename="../qml/pages/apps/AppsColumn.qml" line="121"/>
<source>Allow</source>
<translation>Разрешить</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="50"/>
<location filename="../qml/pages/MainPage.qml" line="81"/>
<source>Options</source>
<translation>Опции</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="55"/>
<location filename="../qml/pages/MainPage.qml" line="86"/>
<source>IPv4 Addresses</source>
<translation>Адреса IPv4</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="60"/>
<location filename="../qml/pages/MainPage.qml" line="91"/>
<source>Applications</source>
<translation>Приложения</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="75"/>
<location filename="../qml/pages/MainPage.qml" line="106"/>
<source>Schedule</source>
<translation>Расписание</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="65"/>
<location filename="../qml/pages/MainPage.qml" line="96"/>
<source>Blocked</source>
<translation>Блокировано</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="70"/>
<location filename="../qml/pages/OptionsPage.qml" line="184"/>
<location filename="../qml/pages/MainPage.qml" line="101"/>
<location filename="../qml/pages/OptionsPage.qml" line="198"/>
<source>Statistics</source>
<translation>Статистика</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="114"/>
<location filename="../qml/pages/OptionsPage.qml" line="128"/>
<source>Password:</source>
<translation>Пароль:</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="102"/>
<location filename="../qml/pages/MainPage.qml" line="133"/>
<source>OK</source>
<translation>OK</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="119"/>
<location filename="../qml/pages/MainPage.qml" line="140"/>
<source>Apply</source>
<translation>Применить</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="135"/>
<location filename="../qml/pages/MainPage.qml" line="146"/>
<source>Cancel</source>
<translation>Отмена</translation>
</message>
<message>
<location filename="../qml/pages/MainPage.qml" line="141"/>
<location filename="../qml/pages/MainPage.qml" line="152"/>
<source>Quit</source>
<translation>Выйти</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="32"/>
<location filename="../qml/pages/OptionsPage.qml" line="46"/>
<source>Start with Windows</source>
<translation>Запускать вместе с Windows</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="41"/>
<location filename="../qml/pages/OptionsPage.qml" line="53"/>
<source>Block access to network when Fort Firewall is not running</source>
<translation>Блокировать доступ к сети, когда Fort Firewall не запущен</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="52"/>
<location filename="../qml/pages/OptionsPage.qml" line="67"/>
<source>Filter Enabled</source>
<translation>Фильтр включен</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="63"/>
<location filename="../qml/pages/OptionsPage.qml" line="78"/>
<source>Filter Local Addresses</source>
<translation>Фильтр локальных адресов</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="77"/>
<location filename="../qml/pages/OptionsPage.qml" line="93"/>
<source>Stop Traffic</source>
<translation>Остановить трафик</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="88"/>
<location filename="../qml/pages/OptionsPage.qml" line="104"/>
<source>Stop Internet Traffic</source>
<translation>Остановить Интернет трафик</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="101"/>
<location filename="../qml/pages/OptionsPage.qml" line="117"/>
<source>Hot Keys</source>
<translation>Горячие клавиши</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="135"/>
<location filename="../qml/pages/OptionsPage.qml" line="149"/>
<source>Installed</source>
<translation>Установлен</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="136"/>
<location filename="../qml/pages/OptionsPage.qml" line="150"/>
<source>Not Installed</source>
<translation>Не установлен</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="146"/>
<location filename="../qml/pages/OptionsPage.qml" line="160"/>
<source>Language:</source>
<translation>Язык:</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="164"/>
<location filename="../qml/pages/OptionsPage.qml" line="178"/>
<source>Logs</source>
<translation>Логи</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="174"/>
<location filename="../qml/pages/OptionsPage.qml" line="188"/>
<source>Profile</source>
<translation>Профиль</translation>
</message>
<message>
<location filename="../qml/pages/OptionsPage.qml" line="194"/>
<location filename="../qml/pages/OptionsPage.qml" line="208"/>
<source>Releases</source>
<translation>Релизы</translation>
</message>
@ -471,12 +476,12 @@
<translation>Отключено</translation>
</message>
<message>
<location filename="../qml/pages/apps/SpeedLimitButton.qml" line="68"/>
<location filename="../qml/pages/apps/SpeedLimitButton.qml" line="67"/>
<source>Download speed limit, KiB/s:</source>
<translation>Ограничение скорости загрузки, KiB/s:</translation>
</message>
<message>
<location filename="../qml/pages/apps/SpeedLimitButton.qml" line="101"/>
<location filename="../qml/pages/apps/SpeedLimitButton.qml" line="92"/>
<source>Upload speed limit, KiB/s:</source>
<translation>Ограничение скорости выгрузки, KiB/s:</translation>
</message>
@ -521,32 +526,32 @@
<translation>Активный период, часы</translation>
</message>
<message>
<location filename="../qml/pages/log/TrafOptionsButton.qml" line="121"/>
<location filename="../qml/pages/log/TrafOptionsButton.qml" line="109"/>
<source>Month starts on:</source>
<translation>Месяц начинается с:</translation>
</message>
<message>
<location filename="../qml/pages/log/TrafOptionsButton.qml" line="147"/>
<location filename="../qml/pages/log/TrafOptionsButton.qml" line="131"/>
<source>Keep days for &apos;Hourly&apos;:</source>
<translation>Хранить дней для &apos;Почасовая&apos;:</translation>
</message>
<message>
<location filename="../qml/pages/log/TrafOptionsButton.qml" line="170"/>
<location filename="../qml/pages/log/TrafOptionsButton.qml" line="150"/>
<source>Keep days for &apos;Daily&apos;:</source>
<translation>Хранить дней для &apos;Ежедневная&apos;:</translation>
</message>
<message>
<location filename="../qml/pages/log/TrafOptionsButton.qml" line="193"/>
<location filename="../qml/pages/log/TrafOptionsButton.qml" line="169"/>
<source>Keep months for &apos;Monthly&apos;:</source>
<translation>Хранить месяцев для &apos;Ежемесячная&apos;:</translation>
</message>
<message>
<location filename="../qml/pages/log/TrafOptionsButton.qml" line="218"/>
<location filename="../qml/pages/log/TrafOptionsButton.qml" line="190"/>
<source>Day&apos;s Quota:</source>
<translation>Квота на день</translation>
</message>
<message>
<location filename="../qml/pages/log/TrafOptionsButton.qml" line="242"/>
<location filename="../qml/pages/log/TrafOptionsButton.qml" line="210"/>
<source>Month&apos;s Quota:</source>
<translation>Квота на месяц</translation>
</message>
@ -581,22 +586,22 @@
<translation>Каждый месяц</translation>
</message>
<message>
<location filename="../qml/pages/SchedulePage.qml" line="65"/>
<location filename="../qml/pages/SchedulePage.qml" line="77"/>
<source>Name</source>
<translation>Наименование</translation>
</message>
<message>
<location filename="../qml/pages/SchedulePage.qml" line="70"/>
<location filename="../qml/pages/SchedulePage.qml" line="82"/>
<source>Interval, hours</source>
<translation>Интервал, часов</translation>
</message>
<message>
<location filename="../qml/pages/SchedulePage.qml" line="76"/>
<location filename="../qml/pages/SchedulePage.qml" line="88"/>
<source>Last Run</source>
<translation>Последний запуск</translation>
</message>
<message>
<location filename="../qml/pages/SchedulePage.qml" line="82"/>
<location filename="../qml/pages/SchedulePage.qml" line="94"/>
<source>Last Success</source>
<translation>Успешный запуск</translation>
</message>
@ -631,71 +636,71 @@
<translation>TiB</translation>
</message>
<message>
<location filename="../qml/pages/StatisticsPage.qml" line="47"/>
<location filename="../qml/pages/StatisticsPage.qml" line="67"/>
<source>Refresh</source>
<translation>Обновить</translation>
</message>
<message>
<location filename="../qml/pages/StatisticsPage.qml" line="92"/>
<location filename="../qml/pages/StatisticsPage.qml" line="116"/>
<source>Units:</source>
<translation>Единицы:</translation>
</message>
<message>
<location filename="../qml/pages/StatisticsPage.qml" line="66"/>
<location filename="../qml/pages/StatisticsPage.qml" line="86"/>
<source>Reset Total</source>
<translation>Сбросить общую</translation>
</message>
<message>
<location filename="../qml/pages/StatisticsPage.qml" line="122"/>
<location filename="../qml/pages/StatisticsPage.qml" line="146"/>
<source>Collect Traffic Statistics</source>
<translation>Собирать статистику трафика</translation>
</message>
<message>
<location filename="../qml/pages/StatisticsPage.qml" line="153"/>
<location filename="../qml/pages/StatisticsPage.qml" line="177"/>
<source>All</source>
<translation>Все</translation>
</message>
<message>
<location filename="../qml/pages/StatisticsPage.qml" line="170"/>
<location filename="../qml/pages/StatisticsPage.qml" line="194"/>
<source>Hourly</source>
<comment>Stat</comment>
<translation>Почасовая</translation>
</message>
<message>
<location filename="../qml/pages/StatisticsPage.qml" line="174"/>
<location filename="../qml/pages/StatisticsPage.qml" line="198"/>
<source>Daily</source>
<comment>Stat</comment>
<translation>Ежедневная</translation>
</message>
<message>
<location filename="../qml/pages/StatisticsPage.qml" line="178"/>
<location filename="../qml/pages/StatisticsPage.qml" line="202"/>
<source>Monthly</source>
<comment>Stat</comment>
<translation>Ежемесячная</translation>
</message>
<message>
<location filename="../qml/pages/StatisticsPage.qml" line="182"/>
<location filename="../qml/pages/StatisticsPage.qml" line="206"/>
<source>Total</source>
<comment>Stat</comment>
<translation>Общая</translation>
</message>
<message>
<location filename="../qml/pages/StatisticsPage.qml" line="193"/>
<location filename="../qml/pages/StatisticsPage.qml" line="217"/>
<source>Date</source>
<translation>Дата</translation>
</message>
<message>
<location filename="../qml/pages/StatisticsPage.qml" line="198"/>
<location filename="../qml/pages/StatisticsPage.qml" line="222"/>
<source>Download</source>
<translation>Загрузка</translation>
</message>
<message>
<location filename="../qml/pages/StatisticsPage.qml" line="203"/>
<location filename="../qml/pages/StatisticsPage.qml" line="227"/>
<source>Upload</source>
<translation>Выгрузка</translation>
</message>
<message>
<location filename="../qml/pages/StatisticsPage.qml" line="208"/>
<location filename="../qml/pages/StatisticsPage.qml" line="232"/>
<source>Sum</source>
<translation>Сумма</translation>
</message>
@ -709,5 +714,80 @@
<source>Allowed Internet Addresses</source>
<translation>Разрешённые адреса Интернета</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="11"/>
<source>Graph</source>
<translation>График</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="39"/>
<source>Always on top</source>
<translation>Всегда сверху</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="47"/>
<source>Frameless</source>
<translation>Без рамок</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="55"/>
<source>Click through</source>
<translation>Сквозной режим</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="63"/>
<source>Hide on hover</source>
<translation>Скрыть при наведении</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="73"/>
<source>Opacity</source>
<translation>Прозрачность</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="85"/>
<source>Hover opacity</source>
<translation>Прозрачность при наведении</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="97"/>
<source>Max seconds</source>
<translation>Количество секунд</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="117"/>
<source>Background color</source>
<translation>Цвет фона</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="125"/>
<source>Download color</source>
<translation>Цвет загрузки</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="133"/>
<source>Upload color</source>
<translation>Цвет выгрузки</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="141"/>
<source>Axis color</source>
<translation>Цвет оси</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="149"/>
<source>Tick label color</source>
<translation>Цвет метки</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="157"/>
<source>Label color</source>
<translation>Цвет маркировки</translation>
</message>
<message>
<location filename="../qml/pages/log/GraphButton.qml" line="165"/>
<source>Grid color</source>
<translation>Цвет сетки</translation>
</message>
</context>
</TS>

View File

@ -0,0 +1,51 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import com.fortfirewall 1.0
RowLayout {
Layout.fillWidth: true
signal colorEdited()
readonly property alias label: label
readonly property alias button: button
property real buttonPreferredWidth: 40
property color defaultColor
property color selectedColor: defaultColor
Label {
id: label
Layout.fillWidth: true
}
Button {
id: button
Layout.fillWidth: true
Layout.preferredWidth: buttonPreferredWidth
Layout.minimumWidth: buttonPreferredWidth
Layout.maximumWidth: implicitWidth
Layout.preferredHeight: buttonPreferredWidth
flat: true
background: Rectangle {
implicitWidth: buttonPreferredWidth
implicitHeight: buttonPreferredWidth
border.width: 1
border.color: button.down ? "gray" : "black"
color: selectedColor
}
onClicked: {
const color = guiUtil.getColor(selectedColor);
if (!guiUtil.isValidColor(color) || color === selectedColor)
return;
selectedColor = color;
colorEdited();
}
}
}

View File

@ -0,0 +1,27 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import com.fortfirewall 1.0
RowLayout {
Layout.fillWidth: true
readonly property alias label: label
readonly property alias field: field
property real fieldPreferredWidth: 140
Label {
id: label
Layout.fillWidth: true
}
SpinBoxControl {
id: field
Layout.fillWidth: true
Layout.preferredWidth: fieldPreferredWidth
Layout.minimumWidth: fieldPreferredWidth
Layout.maximumWidth: implicitWidth
}
}

View File

@ -0,0 +1,24 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
SpinBox {
id: field
editable: true
from: 0
to: 9999
value: defaultValue
signal valueEdited()
property int defaultValue
onValueChanged: {
const value = field.value;
if (value === defaultValue)
return;
field.valueEdited();
}
}

View File

@ -12,16 +12,12 @@ RowLayout {
property var names: values
property var values
SpinBox {
SpinBoxControl {
id: field
Layout.fillWidth: true
Layout.preferredWidth: fieldPreferredWidth
Layout.minimumWidth: fieldPreferredWidth
editable: true
from: 0
to: 9999
onValueChanged: {
combo.updateIndex(value);
}

View File

@ -9,25 +9,17 @@ RowLayout {
property real fieldPreferredWidth
SpinBox {
SpinBoxControl {
id: field1
Layout.fillWidth: true
Layout.preferredWidth: fieldPreferredWidth
Layout.minimumWidth: fieldPreferredWidth
editable: true
from: 0
to: 9999
}
SpinBox {
SpinBoxControl {
id: field2
Layout.fillWidth: true
Layout.preferredWidth: fieldPreferredWidth
Layout.minimumWidth: fieldPreferredWidth
editable: true
from: 0
to: 9999
}
}

View File

@ -6,6 +6,9 @@ Pane {
bottomPadding: 0
function onEditResetted() {
}
function onAboutToSave() {
}
@ -14,6 +17,7 @@ Pane {
Connections {
target: mainPage
onEditResetted: page.onEditResetted()
onAboutToSave: page.onAboutToSave()
onSaved: page.onSaved()
}

View File

@ -73,9 +73,6 @@ BasePage {
&& qsTranslate("qml", "Resolve Addresses")
checked: firewallConf.resolveAddress
onToggled: {
if (firewallConf.resolveAddress === checked)
return;
firewallConf.resolveAddress = checked;
fortManager.applyConfImmediateFlags();

View File

@ -9,12 +9,13 @@ Page {
signal opened()
signal closed()
signal editResetted()
signal aboutToSave()
signal saved()
property bool confFlagsEdited
property bool confEdited
property bool scheduleEdited
property bool othersEdited
function setConfFlagsEdited() {
confFlagsEdited = true;
@ -24,14 +25,44 @@ Page {
confEdited = true;
}
function setScheduleEdited() {
scheduleEdited = true;
function setOthersEdited() {
othersEdited = true;
}
function resetEdited() {
confFlagsEdited = false;
confEdited = false;
scheduleEdited = false;
othersEdited = false;
editResetted();
}
function save(closeOnSuccess) {
fortSettings.bulkUpdateBegin();
mainPage.aboutToSave();
var confSaved = true;
if (confFlagsEdited || confEdited) {
const confFlagsOnly = confFlagsEdited && !confEdited;
confSaved = closeOnSuccess
? fortManager.saveConf(confFlagsOnly)
: fortManager.applyConf(confFlagsOnly);
}
if (confSaved) {
mainPage.saved();
}
fortSettings.bulkUpdateEnd();
if (confSaved) {
if (closeOnSuccess) {
closeWindow();
} else {
resetEdited();
}
}
}
onOpened: {
@ -96,38 +127,18 @@ Page {
anchors.right: parent.right
Button {
enabled: confFlagsEdited || confEdited || scheduleEdited
enabled: confFlagsEdited || confEdited || othersEdited
icon.source: "qrc:/images/tick.png"
text: translationManager.trTrigger
&& qsTranslate("qml", "OK")
onClicked: {
mainPage.aboutToSave();
if (confFlagsEdited || confEdited) {
if (!fortManager.saveConf(confFlagsEdited && !confEdited))
return;
}
mainPage.saved();
closeWindow();
}
onClicked: mainPage.save(true)
}
Button {
enabled: confFlagsEdited || confEdited || scheduleEdited
enabled: confFlagsEdited || confEdited || othersEdited
icon.source: "qrc:/images/accept.png"
text: translationManager.trTrigger
&& qsTranslate("qml", "Apply")
onClicked: {
mainPage.aboutToSave();
if (confFlagsEdited || confEdited) {
if (!fortManager.applyConf(confFlagsEdited && !confEdited))
return;
}
mainPage.saved();
resetEdited();
}
onClicked: mainPage.save(false)
}
Button {
icon.source: "qrc:/images/cancel.png"

View File

@ -6,6 +6,18 @@ import com.fortfirewall 1.0
BasePage {
property bool iniEdited
function setIniEdited() {
iniEdited = true;
setOthersEdited();
}
function onEditResetted() { // override
iniEdited = false;
}
function onAboutToSave() { // override
const password = editPassword.text;
if (password) {
@ -15,6 +27,8 @@ BasePage {
}
function onSaved() { // override
if (!iniEdited) return;
fortSettings.startWithWindows = cbStart.checked;
fortSettings.hotKeyEnabled = cbHotKeys.checked;
}
@ -31,9 +45,7 @@ BasePage {
text: translationManager.trTrigger
&& qsTranslate("qml", "Start with Windows")
checked: fortSettings.startWithWindows
onToggled: {
setConfFlagsEdited();
}
onToggled: setIniEdited()
}
CheckBox {
@ -104,9 +116,7 @@ BasePage {
text: translationManager.trTrigger
&& qsTranslate("qml", "Hot Keys")
checked: fortSettings.hotKeyEnabled
onToggled: {
setConfFlagsEdited();
}
onToggled: setIniEdited()
}
Row {

View File

@ -37,6 +37,18 @@ BasePage {
qsTranslate("qml", "Monthly")
]
property bool scheduleEdited
function setScheduleEdited() {
scheduleEdited = true;
setOthersEdited();
}
function onEditResetted() { // override
scheduleEdited = false;
}
function onSaved() { // override
if (!scheduleEdited) return;

View File

@ -35,6 +35,26 @@ BasePage {
qsTranslate("qml", "TiB")
]
property bool graphEdited
function setGraphEdited() {
graphEdited = true;
setOthersEdited();
}
function onEditResetted() { // override
graphEdited = false;
}
function onSaved() { // override
if (!graphEdited) return;
graphButton.save();
fortManager.updateGraphWindow();
}
ColumnLayout {
anchors.fill: parent
spacing: 10
@ -78,6 +98,10 @@ BasePage {
TrafOptionsButton {}
GraphButton {
id: graphButton
}
Row {
spacing: 5

View File

@ -61,12 +61,8 @@ ColumnLayout {
text: translationManager.trTrigger
&& qsTranslate("qml", "period, hours:")
checked: appGroup.periodEnabled
onCheckedChanged: {
const value = checkBox.checked;
if (appGroup.periodEnabled == value)
return;
appGroup.periodEnabled = value;
onToggled: {
appGroup.periodEnabled = checkBox.checked;
setConfEdited();
}
@ -74,13 +70,9 @@ ColumnLayout {
field1 {
from: 0
to: 24
value: appGroup.periodFrom
onValueChanged: {
const value = field1.value;
if (appGroup.periodFrom == value)
return;
appGroup.periodFrom = value;
defaultValue: appGroup.periodFrom
onValueEdited: {
appGroup.periodFrom = field1.value;
setConfEdited();
}
@ -88,13 +80,9 @@ ColumnLayout {
field2 {
from: 0
to: 24
value: appGroup.periodTo
onValueChanged: {
const value = field2.value;
if (appGroup.periodTo == value)
return;
appGroup.periodTo = value;
defaultValue: appGroup.periodTo
onValueEdited: {
appGroup.periodTo = field2.value;
setConfEdited();
}

View File

@ -66,12 +66,8 @@ ButtonPopup {
text: translationManager.trTrigger
&& qsTranslate("qml", "Download speed limit, KiB/s:")
checked: appGroup.limitInEnabled
onCheckedChanged: {
const value = checkBox.checked;
if (appGroup.limitInEnabled == value)
return;
appGroup.limitInEnabled = value;
onToggled: {
appGroup.limitInEnabled = checkBox.checked;
setConfEdited();
}
@ -79,13 +75,9 @@ ButtonPopup {
field {
from: 0
to: 99999
value: appGroup.speedLimitIn
onValueChanged: {
const value = field.value;
if (appGroup.speedLimitIn == value)
return;
appGroup.speedLimitIn = value;
defaultValue: appGroup.speedLimitIn
onValueEdited: {
appGroup.speedLimitIn = field.value;
setConfEdited();
}
@ -99,12 +91,8 @@ ButtonPopup {
text: translationManager.trTrigger
&& qsTranslate("qml", "Upload speed limit, KiB/s:")
checked: appGroup.limitOutEnabled
onCheckedChanged: {
const value = checkBox.checked;
if (appGroup.limitOutEnabled == value)
return;
appGroup.limitOutEnabled = value;
onToggled: {
appGroup.limitOutEnabled = checkBox.checked;
setConfEdited();
}
@ -112,13 +100,9 @@ ButtonPopup {
field {
from: 0
to: 99999
value: appGroup.speedLimitOut
onValueChanged: {
const value = field.value;
if (appGroup.speedLimitOut == value)
return;
appGroup.speedLimitOut = value;
defaultValue: appGroup.speedLimitOut
onValueEdited: {
appGroup.speedLimitOut = field.value;
setConfEdited();
}

View File

@ -0,0 +1,175 @@
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import "../../controls"
import com.fortfirewall 1.0
ButtonPopup {
icon.source: "qrc:/images/chart_bar.png"
text: translationManager.trTrigger
&& qsTranslate("qml", "Graph…")
function save() {
fortSettings.graphWindowAlwaysOnTop = cbAlwaysOnTop.checked;
fortSettings.graphWindowFrameless = cbFrameless.checked;
fortSettings.graphWindowClickThrough = cbClickThrough.checked;
fortSettings.graphWindowHideOnHover = cbHideOnHover.checked;
fortSettings.graphWindowOpacity = rowOpacity.field.value;
fortSettings.graphWindowHoverOpacity = rowHoverOpacity.field.value;
fortSettings.graphWindowMaxSeconds = rowMaxSeconds.field.value;
fortSettings.graphWindowColor = rowColor.selectedColor;
fortSettings.graphWindowColorIn = rowColorIn.selectedColor;
fortSettings.graphWindowColorOut = rowColorOut.selectedColor;
fortSettings.graphWindowAxisColor = rowAxisColor.selectedColor;
fortSettings.graphWindowTickLabelColor = rowTickLabelColor.selectedColor;
fortSettings.graphWindowLabelColor = rowLabelColor.selectedColor;
fortSettings.graphWindowGridColor = rowGridColor.selectedColor;
}
RowLayout {
spacing: 10
ColumnLayout {
CheckBox {
id: cbAlwaysOnTop
text: translationManager.trTrigger
&& qsTranslate("qml", "Always on top")
checked: fortSettings.graphWindowAlwaysOnTop
onToggled: setGraphEdited()
}
CheckBox {
id: cbFrameless
text: translationManager.trTrigger
&& qsTranslate("qml", "Frameless")
checked: fortSettings.graphWindowFrameless
onToggled: setGraphEdited()
}
CheckBox {
id: cbClickThrough
text: translationManager.trTrigger
&& qsTranslate("qml", "Click through")
checked: fortSettings.graphWindowClickThrough
onToggled: setGraphEdited()
}
CheckBox {
id: cbHideOnHover
text: translationManager.trTrigger
&& qsTranslate("qml", "Hide on hover")
checked: fortSettings.graphWindowHideOnHover
onToggled: setGraphEdited()
}
HSeparator {}
LabelSpinRow {
id: rowOpacity
label.text: (translationManager.trTrigger
&& qsTranslate("qml", "Opacity")) + ":"
field {
from: 0
to: 100
defaultValue: fortSettings.graphWindowOpacity
onValueEdited: setGraphEdited()
}
}
LabelSpinRow {
id: rowHoverOpacity
label.text: (translationManager.trTrigger
&& qsTranslate("qml", "Hover opacity")) + ":"
field {
from: 0
to: 100
defaultValue: fortSettings.graphWindowHoverOpacity
onValueEdited: setGraphEdited()
}
}
LabelSpinRow {
id: rowMaxSeconds
label.text: (translationManager.trTrigger
&& qsTranslate("qml", "Max seconds")) + ":"
field {
from: 0
to: 9999
defaultValue: fortSettings.graphWindowMaxSeconds
onValueEdited: setGraphEdited()
}
}
Item {
Layout.fillHeight: true
}
}
VSeparator {}
ColumnLayout {
LabelColorRow {
id: rowColor
label.text: (translationManager.trTrigger
&& qsTranslate("qml", "Background color")) + ":"
defaultColor: fortSettings.graphWindowColor
onColorEdited: setGraphEdited()
}
LabelColorRow {
id: rowColorIn
label.text: (translationManager.trTrigger
&& qsTranslate("qml", "Download color")) + ":"
defaultColor: fortSettings.graphWindowColorIn
onColorEdited: setGraphEdited()
}
LabelColorRow {
id: rowColorOut
label.text: (translationManager.trTrigger
&& qsTranslate("qml", "Upload color")) + ":"
defaultColor: fortSettings.graphWindowColorOut
onColorEdited: setGraphEdited()
}
LabelColorRow {
id: rowAxisColor
label.text: (translationManager.trTrigger
&& qsTranslate("qml", "Axis color")) + ":"
defaultColor: fortSettings.graphWindowAxisColor
onColorEdited: setGraphEdited()
}
LabelColorRow {
id: rowTickLabelColor
label.text: (translationManager.trTrigger
&& qsTranslate("qml", "Tick label color")) + ":"
defaultColor: fortSettings.graphWindowTickLabelColor
onColorEdited: setGraphEdited()
}
LabelColorRow {
id: rowLabelColor
label.text: (translationManager.trTrigger
&& qsTranslate("qml", "Label color")) + ":"
defaultColor: fortSettings.graphWindowLabelColor
onColorEdited: setGraphEdited()
}
LabelColorRow {
id: rowGridColor
label.text: (translationManager.trTrigger
&& qsTranslate("qml", "Grid color")) + ":"
defaultColor: fortSettings.graphWindowGridColor
onColorEdited: setGraphEdited()
}
Item {
Layout.fillHeight: true
}
}
}
}

View File

@ -67,12 +67,8 @@ ButtonPopup {
text: translationManager.trTrigger
&& qsTranslate("qml", "Active period, hours:")
checked: firewallConf.activePeriodEnabled
onCheckedChanged: {
const value = checkBox.checked;
if (firewallConf.activePeriodEnabled == value)
return;
firewallConf.activePeriodEnabled = value;
onToggled: {
firewallConf.activePeriodEnabled = checkBox.checked;
setConfFlagsEdited();
}
@ -80,13 +76,9 @@ ButtonPopup {
field1 {
from: 0
to: 24
value: firewallConf.activePeriodFrom
onValueChanged: {
const value = field1.value;
if (firewallConf.activePeriodFrom == value)
return;
firewallConf.activePeriodFrom = value;
defaultValue: firewallConf.activePeriodFrom
onValueEdited: {
firewallConf.activePeriodFrom = field1.value;
setConfFlagsEdited();
}
@ -94,13 +86,9 @@ ButtonPopup {
field2 {
from: 0
to: 24
value: firewallConf.activePeriodTo
onValueChanged: {
const value = field2.value;
if (firewallConf.activePeriodTo == value)
return;
firewallConf.activePeriodTo = value;
defaultValue: firewallConf.activePeriodTo
onValueEdited: {
firewallConf.activePeriodTo = field2.value;
setConfFlagsEdited();
}
@ -123,13 +111,9 @@ ButtonPopup {
field {
from: 1
to: 31
value: firewallConf.monthStart
onValueChanged: {
const value = field.value;
if (firewallConf.monthStart == value)
return;
firewallConf.monthStart = value;
defaultValue: firewallConf.monthStart
onValueEdited: {
firewallConf.monthStart = field.value;
setConfFlagsEdited();
}
@ -148,13 +132,9 @@ ButtonPopup {
}
field {
from: -1
value: firewallConf.trafHourKeepDays
onValueChanged: {
const value = field.value;
if (firewallConf.trafHourKeepDays == value)
return;
firewallConf.trafHourKeepDays = value;
defaultValue: firewallConf.trafHourKeepDays
onValueEdited: {
firewallConf.trafHourKeepDays = field.value;
setConfFlagsEdited();
}
@ -171,13 +151,9 @@ ButtonPopup {
}
field {
from: -1
value: firewallConf.trafDayKeepDays
onValueChanged: {
const value = field.value;
if (firewallConf.trafDayKeepDays == value)
return;
firewallConf.trafDayKeepDays = value;
defaultValue: firewallConf.trafDayKeepDays
onValueEdited: {
firewallConf.trafDayKeepDays = field.value;
setConfFlagsEdited();
}
@ -194,13 +170,9 @@ ButtonPopup {
}
field {
from: -1
value: firewallConf.trafMonthKeepMonths
onValueChanged: {
const value = field.value;
if (firewallConf.trafMonthKeepMonths == value)
return;
firewallConf.trafMonthKeepMonths = value;
defaultValue: firewallConf.trafMonthKeepMonths
onValueEdited: {
firewallConf.trafMonthKeepMonths = field.value;
setConfFlagsEdited();
}
@ -220,13 +192,9 @@ ButtonPopup {
field {
from: 0
to: 999 * 1024
value: firewallConf.quotaDayMb
onValueChanged: {
const value = field.value;
if (firewallConf.quotaDayMb == value)
return;
firewallConf.quotaDayMb = value;
defaultValue: firewallConf.quotaDayMb
onValueEdited: {
firewallConf.quotaDayMb = field.value;
setConfFlagsEdited();
}
@ -244,13 +212,9 @@ ButtonPopup {
field {
from: 0
to: 999 * 1024
value: firewallConf.quotaMonthMb
onValueChanged: {
const value = field.value;
if (firewallConf.quotaMonthMb == value)
return;
firewallConf.quotaMonthMb = value;
defaultValue: firewallConf.quotaMonthMb
onValueEdited: {
firewallConf.quotaMonthMb = field.value;
setConfFlagsEdited();
}

View File

@ -51,14 +51,8 @@ Row {
field {
from: 1
to: 24 * 30 * 12 // ~Year
value: taskInfo.intervalHours
onValueChanged: {
const value = field.value;
if (value != taskInfo.intervalHours) {
setScheduleEdited();
}
}
defaultValue: taskInfo.intervalHours
onValueEdited: setScheduleEdited()
}
}

View File

@ -1,6 +1,7 @@
#include "guiutil.h"
#include <QClipboard>
#include <QColorDialog>
#include <QGuiApplication>
#include <QPixmap>
#include <QImage>
@ -25,3 +26,13 @@ void GuiUtil::setClipboardData(const QVariant &data)
clipboard->setText(data.toString());
}
}
QColor GuiUtil::getColor(const QColor &initial)
{
return QColorDialog::getColor(initial);
}
bool GuiUtil::isValidColor(const QColor &color)
{
return color.isValid();
}

View File

@ -1,6 +1,7 @@
#ifndef GUIUTIL_H
#define GUIUTIL_H
#include <QColor>
#include <QObject>
#include <QVariant>
@ -12,6 +13,9 @@ public:
explicit GuiUtil(QObject *parent = nullptr);
Q_INVOKABLE static void setClipboardData(const QVariant &data);
Q_INVOKABLE static QColor getColor(const QColor &initial = Qt::white);
Q_INVOKABLE static bool isValidColor(const QColor &color);
};
#endif // GUIUTIL_H