diff --git a/src/ui/FortFirewallUI.pro b/src/ui/FortFirewallUI.pro index c142f622..ee93c6a1 100644 --- a/src/ui/FortFirewallUI.pro +++ b/src/ui/FortFirewallUI.pro @@ -52,6 +52,7 @@ SOURCES += \ form/opt/pages/rulespage.cpp \ form/opt/pages/schedulepage.cpp \ form/opt/pages/statisticspage.cpp \ + form/prog/programeditdialog.cpp \ form/prog/programscontroller.cpp \ form/prog/programswindow.cpp \ form/tray/traycontroller.cpp \ @@ -177,6 +178,7 @@ HEADERS += \ form/opt/pages/rulespage.h \ form/opt/pages/schedulepage.h \ form/opt/pages/statisticspage.h \ + form/prog/programeditdialog.h \ form/prog/programscontroller.h \ form/prog/programswindow.h \ form/tray/traycontroller.h \ diff --git a/src/ui/form/conn/connectionswindow.cpp b/src/ui/form/conn/connectionswindow.cpp index fce99596..0ac826a6 100644 --- a/src/ui/form/conn/connectionswindow.cpp +++ b/src/ui/form/conn/connectionswindow.cpp @@ -86,10 +86,9 @@ void ConnectionsWindow::restoreWindowState() void ConnectionsWindow::setupController() { - connect(ctrl(), &ConnectionsController::retranslateUi, this, - &ConnectionsWindow::onRetranslateUi); + connect(ctrl(), &ConnectionsController::retranslateUi, this, &ConnectionsWindow::retranslateUi); - emit ctrl()->retranslateUi(); + retranslateUi(); } void ConnectionsWindow::setupStateWatcher() @@ -97,7 +96,7 @@ void ConnectionsWindow::setupStateWatcher() m_stateWatcher->install(this); } -void ConnectionsWindow::onRetranslateUi() +void ConnectionsWindow::retranslateUi() { this->unsetLocale(); diff --git a/src/ui/form/conn/connectionswindow.h b/src/ui/form/conn/connectionswindow.h index 2cc2440a..38671d25 100644 --- a/src/ui/form/conn/connectionswindow.h +++ b/src/ui/form/conn/connectionswindow.h @@ -33,13 +33,12 @@ public: void saveWindowState(); void restoreWindowState(); -protected slots: - void onRetranslateUi(); - private: void setupController(); void setupStateWatcher(); + void retranslateUi(); + void setupUi(); QLayout *setupHeader(); void setupLogOptions(); diff --git a/src/ui/form/opt/optionswindow.cpp b/src/ui/form/opt/optionswindow.cpp index 0f73968b..e76bd8c8 100644 --- a/src/ui/form/opt/optionswindow.cpp +++ b/src/ui/form/opt/optionswindow.cpp @@ -45,7 +45,7 @@ void OptionsWindow::setupController() ctrl()->initialize(); connect(ctrl(), &OptionsController::editedChanged, this, &QWidget::setWindowModified); - connect(ctrl(), &OptionsController::retranslateUi, this, &OptionsWindow::onRetranslateUi); + connect(ctrl(), &OptionsController::retranslateUi, this, &OptionsWindow::retranslateUi); emit ctrl()->retranslateUi(); } @@ -71,7 +71,7 @@ void OptionsWindow::keyPressEvent(QKeyEvent *event) } } -void OptionsWindow::onRetranslateUi() +void OptionsWindow::retranslateUi() { this->unsetLocale(); diff --git a/src/ui/form/opt/optionswindow.h b/src/ui/form/opt/optionswindow.h index 4a30fe6e..255efdd8 100644 --- a/src/ui/form/opt/optionswindow.h +++ b/src/ui/form/opt/optionswindow.h @@ -22,9 +22,6 @@ public: void saveWindowState(); void restoreWindowState(); -protected slots: - void onRetranslateUi(); - protected: void keyPressEvent(QKeyEvent *event) override; @@ -32,6 +29,8 @@ private: void setupController(); void setupStateWatcher(); + void retranslateUi(); + void setupUi(); private: diff --git a/src/ui/form/prog/programeditdialog.cpp b/src/ui/form/prog/programeditdialog.cpp new file mode 100644 index 00000000..369333ff --- /dev/null +++ b/src/ui/form/prog/programeditdialog.cpp @@ -0,0 +1,416 @@ +#include "programeditdialog.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "../../conf/confmanager.h" +#include "../../fortmanager.h" +#include "../../util/app/appinfocache.h" +#include "../../util/iconcache.h" +#include "../controls/checkspincombo.h" +#include "../controls/controlutil.h" +#include "programscontroller.h" + +namespace { + +const ValuesList appBlockInHourValues = { 3, 1, 6, 12, 24, 24 * 7, 24 * 30 }; + +} + +ProgramEditDialog::ProgramEditDialog(ProgramsController *ctrl, QWidget *parent) : + QDialog(parent), m_ctrl(ctrl) +{ + setupUi(); + setupController(); +} + +FortManager *ProgramEditDialog::fortManager() const +{ + return ctrl()->fortManager(); +} + +ConfManager *ProgramEditDialog::confManager() const +{ + return ctrl()->confManager(); +} + +AppListModel *ProgramEditDialog::appListModel() const +{ + return fortManager()->appListModel(); +} + +AppInfoCache *ProgramEditDialog::appInfoCache() const +{ + return appListModel()->appInfoCache(); +} + +void ProgramEditDialog::initialize(const AppRow &appRow, const QVector &appIdList) +{ + m_appRow = appRow; + m_appIdList = appIdList; + + const bool isSingleSelection = (appIdList.size() <= 1); + const bool isPathEditable = isSingleSelection && appRow.appId == 0; + + m_editPath->setText(isSingleSelection ? appRow.appPath : "*"); + m_editPath->setReadOnly(!isPathEditable); + m_editPath->setClearButtonEnabled(isPathEditable); + m_editPath->setEnabled(isSingleSelection); + m_btSelectFile->setEnabled(isPathEditable); + m_editName->setText(isSingleSelection ? appRow.appName : QString()); + m_editName->setEnabled(isSingleSelection); + m_editName->setClearButtonEnabled(isSingleSelection); + m_btGetName->setEnabled(isSingleSelection); + m_comboAppGroup->setCurrentIndex(appRow.groupIndex); + m_cbUseGroupPerm->setChecked(appRow.useGroupPerm); + m_rbAllowApp->setChecked(!appRow.blocked); + m_rbBlockApp->setChecked(appRow.blocked); + m_cscBlockAppIn->checkBox()->setChecked(false); + m_cscBlockAppIn->spinBox()->setValue(1); + m_cbBlockAppAt->setChecked(!appRow.endTime.isNull()); + m_dteBlockAppAt->setDateTime(appRow.endTime); + m_dteBlockAppAt->setMinimumDateTime(QDateTime::currentDateTime()); + m_cbBlockAppNone->setChecked(appRow.endTime.isNull()); + + if (isSingleSelection && appRow.appName.isEmpty()) { + m_btGetName->click(); // Auto-fill the name + } +} + +void ProgramEditDialog::activate() +{ + this->raise(); + this->activateWindow(); + + m_editPath->selectAll(); + m_editPath->setFocus(); +} + +void ProgramEditDialog::setupController() +{ + connect(ctrl(), &ProgramsController::retranslateUi, this, &ProgramEditDialog::retranslateUi); + + retranslateUi(); +} + +void ProgramEditDialog::retranslateUi() +{ + this->unsetLocale(); + + m_labelEditPath->setText(tr("Program Path:")); + m_btSelectFile->setToolTip(tr("Select File")); + m_labelEditName->setText(tr("Program Name:")); + m_btGetName->setToolTip(tr("Get Program Name")); + + m_labelAppGroup->setText(tr("Application Group:")); + m_cbUseGroupPerm->setText(tr("Use Application Group's Enabled State")); + m_rbAllowApp->setText(tr("Allow")); + m_rbBlockApp->setText(tr("Block")); + + m_cscBlockAppIn->checkBox()->setText(tr("Block In:")); + retranslateAppBlockInHours(); + m_cbBlockAppAt->setText(tr("Block At:")); + m_dteBlockAppAt->unsetLocale(); + m_cbBlockAppNone->setText(tr("Forever")); + + m_btOk->setText(tr("OK")); + m_btCancel->setText(tr("Cancel")); + + this->setWindowTitle(tr("Edit Program")); +} + +void ProgramEditDialog::retranslateAppBlockInHours() +{ + const QStringList list = { tr("Custom"), tr("1 hour"), tr("6 hours"), tr("12 hours"), tr("Day"), + tr("Week"), tr("Month") }; + + m_cscBlockAppIn->setNames(list); + m_cscBlockAppIn->spinBox()->setSuffix(tr(" hour(s)")); +} + +void ProgramEditDialog::setupUi() +{ + // Form Layout + auto formLayout = setupAppLayout(); + + // Allow/Block + auto allowLayout = setupAllowLayout(); + + // Block at specified date & time + auto blockAtLayout = setupCheckDateTimeEdit(); + + // Eclusive End Time CheckBoxes Group + setupAllowEclusiveGroup(); + + // OK/Cancel + auto buttonsLayout = new QHBoxLayout(); + + m_btOk = ControlUtil::createButton(QString(), [&] { + if (save()) { + this->close(); + } + }); + m_btOk->setDefault(true); + + m_btCancel = new QPushButton(); + connect(m_btCancel, &QAbstractButton::clicked, this, &QWidget::close); + + buttonsLayout->addWidget(m_btOk, 1, Qt::AlignRight); + buttonsLayout->addWidget(m_btCancel); + + // Form + auto layout = new QVBoxLayout(); + layout->addLayout(formLayout); + layout->addWidget(ControlUtil::createSeparator()); + layout->addLayout(allowLayout); + layout->addWidget(m_cscBlockAppIn); + layout->addLayout(blockAtLayout); + layout->addWidget(m_cbBlockAppNone); + layout->addStretch(); + layout->addWidget(ControlUtil::createSeparator()); + layout->addLayout(buttonsLayout); + + this->setLayout(layout); + + // Font + this->setFont(QFont("Tahoma", 9)); + + // Modality & Size Grip + this->setWindowModality(Qt::WindowModal); + this->setSizeGripEnabled(true); + + // Size + this->setMinimumWidth(500); +} + +QLayout *ProgramEditDialog::setupAppLayout() +{ + auto layout = new QFormLayout(); + + // App Path + auto pathLayout = setupAppPathLayout(); + + layout->addRow("Program Path:", pathLayout); + m_labelEditPath = qobject_cast(layout->labelForField(pathLayout)); + + // App Name + auto nameLayout = setupAppNameLayout(); + + layout->addRow("Program Name:", nameLayout); + m_labelEditName = qobject_cast(layout->labelForField(nameLayout)); + + // App Group + setupComboAppGroups(); + + layout->addRow("Application Group:", m_comboAppGroup); + m_labelAppGroup = qobject_cast(layout->labelForField(m_comboAppGroup)); + + // Use Group Perm. + m_cbUseGroupPerm = new QCheckBox(); + + layout->addRow(QString(), m_cbUseGroupPerm); + + return layout; +} + +QLayout *ProgramEditDialog::setupAppPathLayout() +{ + auto layout = new QHBoxLayout(); + + m_editPath = new QLineEdit(); + + m_btSelectFile = ControlUtil::createFlatButton(":/icons/folder-open.png", [&] { + const auto filePath = ControlUtil::getOpenFileName( + m_labelEditPath->text(), tr("Programs (*.exe);;All files (*.*)")); + + if (!filePath.isEmpty()) { + m_editPath->setText(filePath); + m_btGetName->click(); // Auto-fill the name + } + }); + + layout->addWidget(m_editPath); + layout->addWidget(m_btSelectFile); + + return layout; +} + +QLayout *ProgramEditDialog::setupAppNameLayout() +{ + auto layout = new QHBoxLayout(); + + m_editName = new QLineEdit(); + + const auto updateAppName = [&] { + const auto appPath = m_editPath->text(); + if (appPath.isEmpty()) + return; + + const QString appName = appInfoCache()->appName(appPath); + m_editName->setText(appName); + }; + + m_btGetName = ControlUtil::createFlatButton(":/icons/sign-sync.png", updateAppName); + + layout->addWidget(m_editName); + layout->addWidget(m_btGetName); + + return layout; +} + +void ProgramEditDialog::setupComboAppGroups() +{ + m_comboAppGroup = new QComboBox(); + + const auto refreshComboAppGroups = [&](bool onlyFlags = false) { + if (onlyFlags) + return; + + m_comboAppGroup->clear(); + m_comboAppGroup->addItems(appListModel()->appGroupNames()); + m_comboAppGroup->setCurrentIndex(0); + }; + + refreshComboAppGroups(); + + connect(confManager(), &ConfManager::confSaved, this, refreshComboAppGroups); +} + +QLayout *ProgramEditDialog::setupAllowLayout() +{ + auto allowLayout = new QHBoxLayout(); + allowLayout->setSpacing(20); + + m_rbAllowApp = new QRadioButton(); + m_rbAllowApp->setIcon(IconCache::icon(":/icons/sign-check.png")); + m_rbAllowApp->setChecked(true); + + m_rbBlockApp = new QRadioButton(); + m_rbBlockApp->setIcon(IconCache::icon(":/icons/sign-ban.png")); + + allowLayout->addWidget(m_rbAllowApp, 1, Qt::AlignRight); + allowLayout->addWidget(m_rbBlockApp, 1, Qt::AlignLeft); + + // Block after N hours + m_cscBlockAppIn = new CheckSpinCombo(); + m_cscBlockAppIn->spinBox()->setRange(1, 24 * 30 * 12); // ~Year + m_cscBlockAppIn->setValues(appBlockInHourValues); + m_cscBlockAppIn->setNamesByValues(); + + // Allow Forever + m_cbBlockAppNone = new QCheckBox(); + + connect(m_rbAllowApp, &QRadioButton::toggled, this, [&](bool checked) { + m_cbBlockAppNone->setEnabled(checked); + m_cscBlockAppIn->setEnabled(checked); + m_cbBlockAppAt->setEnabled(checked); + m_dteBlockAppAt->setEnabled(checked); + }); + + return allowLayout; +} + +QLayout *ProgramEditDialog::setupCheckDateTimeEdit() +{ + m_cbBlockAppAt = new QCheckBox(); + + m_dteBlockAppAt = new QDateTimeEdit(); + m_dteBlockAppAt->setCalendarPopup(true); + + return ControlUtil::createRowLayout(m_cbBlockAppAt, m_dteBlockAppAt); +} + +void ProgramEditDialog::setupAllowEclusiveGroup() +{ + auto group = new QButtonGroup(this); + group->setExclusive(true); + group->addButton(m_cscBlockAppIn->checkBox()); + group->addButton(m_cbBlockAppAt); + group->addButton(m_cbBlockAppNone); +} + +bool ProgramEditDialog::save() +{ + const int appIdsCount = m_appIdList.size(); + const bool isSingleSelection = (appIdsCount <= 1); + + const QString appPath = m_editPath->text(); + if (isSingleSelection && appPath.isEmpty()) { + m_editPath->setFocus(); + return false; + } + + const QString appName = m_editName->text(); + if (isSingleSelection && appName.isEmpty()) { + m_editName->setFocus(); + return false; + } + + const int groupIndex = m_comboAppGroup->currentIndex(); + const bool useGroupPerm = m_cbUseGroupPerm->isChecked(); + const bool blocked = m_rbBlockApp->isChecked(); + + QDateTime endTime; + if (!blocked) { + if (m_cscBlockAppIn->checkBox()->isChecked()) { + const int hours = m_cscBlockAppIn->spinBox()->value(); + + endTime = QDateTime::currentDateTime().addSecs(hours * 60 * 60); + } else if (m_cbBlockAppAt->isChecked()) { + endTime = m_dteBlockAppAt->dateTime(); + } + } + + // Add new app or edit non-selected app + if (appIdsCount == 0) { + return appListModel()->addApp(appPath, appName, endTime, groupIndex, useGroupPerm, blocked); + } + + // Edit selected app + if (isSingleSelection) { + return saveApp(appPath, appName, endTime, groupIndex, useGroupPerm, blocked); + } + + // Edit selected apps + return saveMulti(endTime, groupIndex, useGroupPerm, blocked); +} + +bool ProgramEditDialog::saveApp(const QString &appPath, const QString &appName, + const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked) +{ + const bool appEdited = (appPath != m_appRow.appPath || groupIndex != m_appRow.groupIndex + || useGroupPerm != m_appRow.useGroupPerm || blocked != m_appRow.blocked + || endTime != m_appRow.endTime); + + if (appEdited) { + return appListModel()->updateApp( + m_appRow.appId, appPath, appName, endTime, groupIndex, useGroupPerm, blocked); + } + + if (appName == m_appRow.appName) + return true; + + return appListModel()->updateAppName(m_appRow.appId, appName); +} + +bool ProgramEditDialog::saveMulti( + const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked) +{ + for (qint64 appId : m_appIdList) { + const auto appRow = appListModel()->appRowById(appId); + + if (!appListModel()->updateApp(appId, appRow.appPath, appRow.appName, endTime, groupIndex, + useGroupPerm, blocked)) + return false; + } + + return true; +} diff --git a/src/ui/form/prog/programeditdialog.h b/src/ui/form/prog/programeditdialog.h new file mode 100644 index 00000000..525307f9 --- /dev/null +++ b/src/ui/form/prog/programeditdialog.h @@ -0,0 +1,84 @@ +#ifndef PROGRAMEDITDIALOG_H +#define PROGRAMEDITDIALOG_H + +#include + +#include "../../model/applistmodel.h" + +QT_FORWARD_DECLARE_CLASS(QCheckBox) +QT_FORWARD_DECLARE_CLASS(QComboBox) +QT_FORWARD_DECLARE_CLASS(QDateTimeEdit) +QT_FORWARD_DECLARE_CLASS(QLabel) +QT_FORWARD_DECLARE_CLASS(QLineEdit) +QT_FORWARD_DECLARE_CLASS(QPushButton) +QT_FORWARD_DECLARE_CLASS(QRadioButton) + +class AppInfoCache; +class CheckSpinCombo; +class ConfManager; +class FortManager; +class ProgramsController; + +class ProgramEditDialog : public QDialog +{ + Q_OBJECT + +public: + explicit ProgramEditDialog(ProgramsController *ctrl, QWidget *parent = nullptr); + + ProgramsController *ctrl() const { return m_ctrl; } + FortManager *fortManager() const; + ConfManager *confManager() const; + AppListModel *appListModel() const; + AppInfoCache *appInfoCache() const; + + void initialize(const AppRow &appRow, const QVector &appIdList); + + void activate(); + +private: + void setupController(); + + void retranslateUi(); + void retranslateAppBlockInHours(); + + void setupUi(); + QLayout *setupAppLayout(); + QLayout *setupAppPathLayout(); + QLayout *setupAppNameLayout(); + void setupComboAppGroups(); + QLayout *setupAllowLayout(); + QLayout *setupCheckDateTimeEdit(); + void setupAllowEclusiveGroup(); + + bool save(); + bool saveApp(const QString &appPath, const QString &appName, const QDateTime &endTime, + int groupIndex, bool useGroupPerm, bool blocked); + bool saveMulti(const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked); + +private: + ProgramsController *m_ctrl = nullptr; + + QLabel *m_labelEditPath = nullptr; + QLineEdit *m_editPath = nullptr; + QPushButton *m_btSelectFile = nullptr; + QLabel *m_labelEditName = nullptr; + QLineEdit *m_editName = nullptr; + QPushButton *m_btGetName = nullptr; + QLabel *m_labelAppGroup = nullptr; + QComboBox *m_comboAppGroup = nullptr; + QCheckBox *m_cbUseGroupPerm = nullptr; + QRadioButton *m_rbAllowApp = nullptr; + QRadioButton *m_rbBlockApp = nullptr; + CheckSpinCombo *m_cscBlockAppIn = nullptr; + QCheckBox *m_cbBlockAppAt = nullptr; + QDateTimeEdit *m_dteBlockAppAt = nullptr; + QCheckBox *m_cbBlockAppNone = nullptr; + QPushButton *m_btOk = nullptr; + QPushButton *m_btCancel = nullptr; + + AppRow m_appRow; + QVector m_appIdList; +}; + +#endif // PROGRAMEDITDIALOG_H diff --git a/src/ui/form/prog/programswindow.cpp b/src/ui/form/prog/programswindow.cpp index 4d2aabb3..1a4d6403 100644 --- a/src/ui/form/prog/programswindow.cpp +++ b/src/ui/form/prog/programswindow.cpp @@ -1,22 +1,11 @@ #include "programswindow.h" -#include #include -#include -#include -#include -#include #include -#include -#include #include #include -#include -#include #include -#include "../../conf/appgroup.h" -#include "../../conf/confmanager.h" #include "../../conf/firewallconf.h" #include "../../fortmanager.h" #include "../../fortsettings.h" @@ -26,17 +15,15 @@ #include "../../util/iconcache.h" #include "../../util/window/widgetwindowstatewatcher.h" #include "../controls/appinforow.h" -#include "../controls/checkspincombo.h" #include "../controls/controlutil.h" #include "../controls/tableview.h" +#include "programeditdialog.h" #include "programscontroller.h" namespace { #define APPS_HEADER_VERSION 3 -const ValuesList appBlockInHourValues = { 3, 1, 6, 12, 24, 24 * 7, 24 * 30 }; - } ProgramsWindow::ProgramsWindow(FortManager *fortManager, QWidget *parent) : @@ -45,6 +32,7 @@ ProgramsWindow::ProgramsWindow(FortManager *fortManager, QWidget *parent) : m_stateWatcher(new WidgetWindowStateWatcher(this)) { setupUi(); + setupAppEditForm(); setupController(); setupStateWatcher(); } @@ -59,11 +47,6 @@ FortSettings *ProgramsWindow::settings() const return ctrl()->settings(); } -ConfManager *ProgramsWindow::confManager() const -{ - return ctrl()->confManager(); -} - FirewallConf *ProgramsWindow::conf() const { return ctrl()->conf(); @@ -102,9 +85,9 @@ void ProgramsWindow::restoreWindowState() void ProgramsWindow::setupController() { - connect(ctrl(), &ProgramsController::retranslateUi, this, &ProgramsWindow::onRetranslateUi); + connect(ctrl(), &ProgramsController::retranslateUi, this, &ProgramsWindow::retranslateUi); - emit ctrl()->retranslateUi(); + retranslateUi(); } void ProgramsWindow::setupStateWatcher() @@ -112,7 +95,7 @@ void ProgramsWindow::setupStateWatcher() m_stateWatcher->install(this); } -void ProgramsWindow::onRetranslateUi() +void ProgramsWindow::retranslateUi() { this->unsetLocale(); @@ -128,26 +111,6 @@ void ProgramsWindow::onRetranslateUi() m_btBlockApp->setText(tr("Block")); m_btRemoveApp->setText(tr("Remove")); - m_formAppEdit->unsetLocale(); - m_formAppEdit->setWindowTitle(tr("Edit Program")); - - m_labelEditPath->setText(tr("Program Path:")); - m_btSelectFile->setToolTip(tr("Select File")); - m_labelEditName->setText(tr("Program Name:")); - m_btGetName->setToolTip(tr("Get Program Name")); - m_labelAppGroup->setText(tr("Application Group:")); - m_cbUseGroupPerm->setText(tr("Use Application Group's Enabled State")); - m_rbAllowApp->setText(tr("Allow")); - m_rbBlockApp->setText(tr("Block")); - m_cscBlockAppIn->checkBox()->setText(tr("Block In:")); - retranslateAppBlockInHours(); - m_cbBlockAppAt->setText(tr("Block At:")); - m_dteBlockAppAt->unsetLocale(); - m_cbBlockAppNone->setText(tr("Forever")); - - m_btEditOk->setText(tr("OK")); - m_btEditCancel->setText(tr("Cancel")); - m_btLogOptions->setText(tr("Options")); m_cbLogBlocked->setText(tr("Collect New Blocked Programs")); @@ -158,23 +121,11 @@ void ProgramsWindow::onRetranslateUi() this->setWindowTitle(tr("Programs")); } -void ProgramsWindow::retranslateAppBlockInHours() -{ - const QStringList list = { tr("Custom"), tr("1 hour"), tr("6 hours"), tr("12 hours"), tr("Day"), - tr("Week"), tr("Month") }; - - m_cscBlockAppIn->setNames(list); - m_cscBlockAppIn->spinBox()->setSuffix(tr(" hour(s)")); -} - void ProgramsWindow::setupUi() { auto layout = new QVBoxLayout(); layout->setContentsMargins(6, 6, 6, 6); - // App Add/Edit Form - setupAppEditForm(); - // Header auto header = setupHeader(); layout->addLayout(header); @@ -203,202 +154,6 @@ void ProgramsWindow::setupUi() this->setMinimumSize(500, 400); } -void ProgramsWindow::setupAppEditForm() -{ - // Dialog - m_formAppEdit = new QDialog(this); - m_formAppEdit->setWindowModality(Qt::WindowModal); - m_formAppEdit->setSizeGripEnabled(true); - m_formAppEdit->setMinimumWidth(500); - - // Form Layout - auto formLayout = setupAppEditFormAppLayout(); - - // Allow/Block - auto allowLayout = setupAppEditFormAllowLayout(); - - // Block at specified date & time - auto blockAtLayout = setupCheckDateTimeEdit(); - - // Eclusive End Time CheckBoxes Group - setupAllowEclusiveGroup(); - - // OK/Cancel - auto buttonsLayout = new QHBoxLayout(); - - m_btEditOk = ControlUtil::createButton(QString(), [&] { - if (saveAppEditForm()) { - m_formAppEdit->close(); - } - }); - m_btEditOk->setDefault(true); - - m_btEditCancel = new QPushButton(); - connect(m_btEditCancel, &QAbstractButton::clicked, m_formAppEdit, &QWidget::close); - - buttonsLayout->addWidget(m_btEditOk, 1, Qt::AlignRight); - buttonsLayout->addWidget(m_btEditCancel); - - // Form - auto layout = new QVBoxLayout(); - layout->addLayout(formLayout); - layout->addWidget(ControlUtil::createSeparator()); - layout->addLayout(allowLayout); - layout->addWidget(m_cscBlockAppIn); - layout->addLayout(blockAtLayout); - layout->addWidget(m_cbBlockAppNone); - layout->addStretch(); - layout->addWidget(ControlUtil::createSeparator()); - layout->addLayout(buttonsLayout); - - m_formAppEdit->setLayout(layout); -} - -QLayout *ProgramsWindow::setupAppEditFormAppLayout() -{ - auto layout = new QFormLayout(); - - // App Path - auto pathLayout = setupAppEditFormAppPathLayout(); - - layout->addRow("Program Path:", pathLayout); - m_labelEditPath = qobject_cast(layout->labelForField(pathLayout)); - - // App Name - auto nameLayout = setupAppEditFormAppNameLayout(); - - layout->addRow("Program Name:", nameLayout); - m_labelEditName = qobject_cast(layout->labelForField(nameLayout)); - - // App Group - setupComboAppGroups(); - - layout->addRow("Application Group:", m_comboAppGroup); - m_labelAppGroup = qobject_cast(layout->labelForField(m_comboAppGroup)); - - // Use Group Perm. - m_cbUseGroupPerm = new QCheckBox(); - - layout->addRow(QString(), m_cbUseGroupPerm); - - return layout; -} - -QLayout *ProgramsWindow::setupAppEditFormAppPathLayout() -{ - auto layout = new QHBoxLayout(); - - m_editPath = new QLineEdit(); - - m_btSelectFile = ControlUtil::createFlatButton(":/icons/folder-open.png", [&] { - const auto filePath = ControlUtil::getOpenFileName( - m_labelEditPath->text(), tr("Programs (*.exe);;All files (*.*)")); - - if (!filePath.isEmpty()) { - m_editPath->setText(filePath); - } - }); - - layout->addWidget(m_editPath); - layout->addWidget(m_btSelectFile); - - return layout; -} - -QLayout *ProgramsWindow::setupAppEditFormAppNameLayout() -{ - auto layout = new QHBoxLayout(); - - m_editName = new QLineEdit(); - - const auto updateAppName = [&] { - const auto appPath = m_editPath->text(); - if (appPath.isEmpty()) - return; - - const QString appName = appInfoCache()->appName(appPath); - m_editName->setText(appName); - }; - - m_btGetName = ControlUtil::createFlatButton(":/icons/sign-sync.png", updateAppName); - - layout->addWidget(m_editName); - layout->addWidget(m_btGetName); - - return layout; -} - -void ProgramsWindow::setupComboAppGroups() -{ - m_comboAppGroup = new QComboBox(); - - const auto refreshComboAppGroups = [&](bool onlyFlags = false) { - if (onlyFlags) - return; - - m_comboAppGroup->clear(); - m_comboAppGroup->addItems(appListModel()->appGroupNames()); - m_comboAppGroup->setCurrentIndex(0); - }; - - refreshComboAppGroups(); - - connect(confManager(), &ConfManager::confSaved, this, refreshComboAppGroups); -} - -QLayout *ProgramsWindow::setupAppEditFormAllowLayout() -{ - auto allowLayout = new QHBoxLayout(); - allowLayout->setSpacing(20); - - m_rbAllowApp = new QRadioButton(); - m_rbAllowApp->setIcon(IconCache::icon(":/icons/sign-check.png")); - m_rbAllowApp->setChecked(true); - - m_rbBlockApp = new QRadioButton(); - m_rbBlockApp->setIcon(IconCache::icon(":/icons/sign-ban.png")); - - allowLayout->addWidget(m_rbAllowApp, 1, Qt::AlignRight); - allowLayout->addWidget(m_rbBlockApp, 1, Qt::AlignLeft); - - // Block after N hours - m_cscBlockAppIn = new CheckSpinCombo(); - m_cscBlockAppIn->spinBox()->setRange(1, 24 * 30 * 12); // ~Year - m_cscBlockAppIn->setValues(appBlockInHourValues); - m_cscBlockAppIn->setNamesByValues(); - - // Allow Forever - m_cbBlockAppNone = new QCheckBox(); - - connect(m_rbAllowApp, &QRadioButton::toggled, this, [&](bool checked) { - m_cbBlockAppNone->setEnabled(checked); - m_cscBlockAppIn->setEnabled(checked); - m_cbBlockAppAt->setEnabled(checked); - m_dteBlockAppAt->setEnabled(checked); - }); - - return allowLayout; -} - -QLayout *ProgramsWindow::setupCheckDateTimeEdit() -{ - m_cbBlockAppAt = new QCheckBox(); - - m_dteBlockAppAt = new QDateTimeEdit(); - m_dteBlockAppAt->setCalendarPopup(true); - - return ControlUtil::createRowLayout(m_cbBlockAppAt, m_dteBlockAppAt); -} - -void ProgramsWindow::setupAllowEclusiveGroup() -{ - auto group = new QButtonGroup(this); - group->setExclusive(true); - group->addButton(m_cscBlockAppIn->checkBox()); - group->addButton(m_cbBlockAppAt); - group->addButton(m_cbBlockAppNone); -} - QLayout *ProgramsWindow::setupHeader() { auto layout = new QHBoxLayout(); @@ -429,8 +184,8 @@ QLayout *ProgramsWindow::setupHeader() connect(m_actAllowApp, &QAction::triggered, this, [&] { updateSelectedApps(false); }); connect(m_actBlockApp, &QAction::triggered, this, [&] { updateSelectedApps(true); }); - connect(m_actAddApp, &QAction::triggered, this, [&] { updateAppEditForm(false); }); - connect(m_actEditApp, &QAction::triggered, this, [&] { updateAppEditForm(true); }); + connect(m_actAddApp, &QAction::triggered, this, &ProgramsWindow::addNewProgram); + connect(m_actEditApp, &QAction::triggered, this, &ProgramsWindow::editSelectedPrograms); connect(m_actRemoveApp, &QAction::triggered, this, [&] { if (fortManager()->showQuestionBox(tr("Are you sure to remove selected program(s)?"))) { deleteSelectedApps(); @@ -567,162 +322,57 @@ void ProgramsWindow::setupTableAppsChanged() connect(m_appListView, &TableView::currentIndexChanged, this, refreshTableAppsChanged); } -bool ProgramsWindow::openAppEditFormByPath(const QString &appPath) +void ProgramsWindow::setupAppEditForm() +{ + m_formAppEdit = new ProgramEditDialog(ctrl(), this); +} + +bool ProgramsWindow::editProgramByPath(const QString &appPath) { if (m_formAppEdit->isVisible()) { - activateAppEditForm(); + m_formAppEdit->activate(); return false; } const auto appRow = appListModel()->appRowByPath(appPath); - openAppEditFormByRow(appRow, false, true); + openAppEditForm(appRow); return true; } -void ProgramsWindow::updateAppEditForm(bool editCurrentApp) +void ProgramsWindow::addNewProgram() { - bool isSingleSelection = true; - - AppRow appRow; - if (editCurrentApp) { - const auto rows = m_appListView->selectedRows(); - if (rows.isEmpty()) - return; - - isSingleSelection = (rows.size() == 1); - - const auto appIndex = appListCurrentIndex(); - appRow = appListModel()->appRowAt(appIndex); - } - - openAppEditFormByRow(appRow, editCurrentApp, isSingleSelection); + openAppEditForm({}); } -void ProgramsWindow::openAppEditFormByRow( - const AppRow &appRow, bool editCurrentApp, bool isSingleSelection) -{ - const bool isPathEditable = isSingleSelection && appRow.appId == 0; - - m_formAppForSelected = editCurrentApp; - - m_editPath->setText(isSingleSelection ? appRow.appPath : "*"); - m_editPath->setReadOnly(!isPathEditable); - m_editPath->setClearButtonEnabled(isPathEditable); - m_editPath->setEnabled(isSingleSelection); - m_btSelectFile->setEnabled(isPathEditable); - m_editName->setText(isSingleSelection ? appRow.appName : QString()); - m_editName->setEnabled(isSingleSelection); - m_editName->setClearButtonEnabled(isSingleSelection); - m_btGetName->setEnabled(isSingleSelection); - m_comboAppGroup->setCurrentIndex(appRow.groupIndex); - m_cbUseGroupPerm->setChecked(appRow.useGroupPerm); - m_rbAllowApp->setChecked(!appRow.blocked); - m_rbBlockApp->setChecked(appRow.blocked); - m_cscBlockAppIn->checkBox()->setChecked(false); - m_cscBlockAppIn->spinBox()->setValue(1); - m_cbBlockAppAt->setChecked(!appRow.endTime.isNull()); - m_dteBlockAppAt->setDateTime(appRow.endTime); - m_dteBlockAppAt->setMinimumDateTime(QDateTime::currentDateTime()); - m_cbBlockAppNone->setChecked(appRow.endTime.isNull()); - - if (isSingleSelection && appRow.appName.isEmpty()) { - m_btGetName->click(); // Auto-fill name - } - - m_formAppEdit->show(); - - activateAppEditForm(); -} - -void ProgramsWindow::activateAppEditForm() -{ - m_formAppEdit->activateWindow(); - m_editPath->selectAll(); - m_editPath->setFocus(); -} - -bool ProgramsWindow::saveAppEditForm() -{ - const QString appPath = m_editPath->text(); - if (appPath.isEmpty()) { - m_editPath->setFocus(); - return false; - } - - const QString appName = m_editName->text(); - if (appName.isEmpty()) { - m_editName->setFocus(); - return false; - } - - const int groupIndex = m_comboAppGroup->currentIndex(); - const bool useGroupPerm = m_cbUseGroupPerm->isChecked(); - const bool blocked = m_rbBlockApp->isChecked(); - - QDateTime endTime; - if (!blocked) { - if (m_cscBlockAppIn->checkBox()->isChecked()) { - const int hours = m_cscBlockAppIn->spinBox()->value(); - - endTime = QDateTime::currentDateTime().addSecs(hours * 60 * 60); - } else if (m_cbBlockAppAt->isChecked()) { - endTime = m_dteBlockAppAt->dateTime(); - } - } - - // Add new app or edit non-selected app - if (!m_formAppForSelected) { - return appListModel()->addApp(appPath, appName, endTime, groupIndex, useGroupPerm, blocked); - } - - // Edit selected apps - return saveAppEditFormMulti(appPath, appName, endTime, groupIndex, useGroupPerm, blocked); -} - -bool ProgramsWindow::saveAppEditFormMulti(const QString &appPath, const QString &appName, - const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked) +void ProgramsWindow::editSelectedPrograms() { const auto rows = m_appListView->selectedRows(); - const bool isSingleSelection = (rows.size() == 1); + if (rows.isEmpty()) + return; - if (isSingleSelection) { - bool ok; - if (!saveAppEditFormCheckEdited( - appPath, appName, endTime, groupIndex, useGroupPerm, blocked, ok)) - return ok; - } + bool isFirstAppRow = true; + AppRow firstAppRow; + QVector appIdList; for (int row : rows) { const auto appRow = appListModel()->appRowAt(row); - - const auto rowAppPath = isSingleSelection ? appPath : appRow.appPath; - const auto rowAppName = isSingleSelection ? appName : appRow.appName; - - if (!appListModel()->updateApp(appRow.appId, rowAppPath, rowAppName, endTime, groupIndex, - useGroupPerm, blocked)) - return false; + if (isFirstAppRow) { + isFirstAppRow = false; + firstAppRow = appRow; + } + appIdList.append(appRow.appId); } - return true; + openAppEditForm(firstAppRow, appIdList); } -bool ProgramsWindow::saveAppEditFormCheckEdited(const QString &appPath, const QString &appName, - const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked, bool &ok) +void ProgramsWindow::openAppEditForm(const AppRow &appRow, const QVector &appIdList) { - const int appIndex = appListCurrentIndex(); - const auto appRow = appListModel()->appRowAt(appIndex); + m_formAppEdit->initialize(appRow, appIdList); - const bool appNameEdited = (appName != appRow.appName); - const bool appEdited = (appPath != appRow.appPath || groupIndex != appRow.groupIndex - || useGroupPerm != appRow.useGroupPerm || blocked != appRow.blocked - || endTime != appRow.endTime); - - if (appEdited) - return true; - - ok = !appNameEdited || appListModel()->updateAppName(appRow.appId, appName); - return false; + m_formAppEdit->show(); + m_formAppEdit->activate(); } void ProgramsWindow::updateApp(int row, bool blocked) diff --git a/src/ui/form/prog/programswindow.h b/src/ui/form/prog/programswindow.h index f9c33488..fbf00575 100644 --- a/src/ui/form/prog/programswindow.h +++ b/src/ui/form/prog/programswindow.h @@ -4,22 +4,15 @@ #include "../../util/window/widgetwindow.h" QT_FORWARD_DECLARE_CLASS(QCheckBox) -QT_FORWARD_DECLARE_CLASS(QComboBox) -QT_FORWARD_DECLARE_CLASS(QDateTimeEdit) -QT_FORWARD_DECLARE_CLASS(QDialog) -QT_FORWARD_DECLARE_CLASS(QLabel) -QT_FORWARD_DECLARE_CLASS(QLineEdit) QT_FORWARD_DECLARE_CLASS(QPushButton) -QT_FORWARD_DECLARE_CLASS(QRadioButton) class AppInfoCache; class AppInfoRow; class AppListModel; -class CheckSpinCombo; -class ConfManager; class FirewallConf; class FortManager; class FortSettings; +class ProgramEditDialog; class ProgramsController; class TableView; class WidgetWindowStateWatcher; @@ -36,7 +29,6 @@ public: ProgramsController *ctrl() const { return m_ctrl; } FortManager *fortManager() const; FortSettings *settings() const; - ConfManager *confManager() const; FirewallConf *conf() const; AppListModel *appListModel() const; AppInfoCache *appInfoCache() const; @@ -44,26 +36,15 @@ public: void saveWindowState(); void restoreWindowState(); - bool openAppEditFormByPath(const QString &appPath); - -protected slots: - void onRetranslateUi(); + bool editProgramByPath(const QString &appPath); private: void setupController(); void setupStateWatcher(); - void retranslateAppBlockInHours(); + void retranslateUi(); void setupUi(); - void setupAppEditForm(); - QLayout *setupAppEditFormAppLayout(); - QLayout *setupAppEditFormAppPathLayout(); - QLayout *setupAppEditFormAppNameLayout(); - void setupComboAppGroups(); - QLayout *setupAppEditFormAllowLayout(); - QLayout *setupCheckDateTimeEdit(); - void setupAllowEclusiveGroup(); QLayout *setupHeader(); void setupLogOptions(); void setupLogBlocked(); @@ -72,15 +53,11 @@ private: void setupAppInfoRow(); void setupTableAppsChanged(); - void updateAppEditForm(bool editCurrentApp); - void openAppEditFormByRow(const AppRow &appRow, bool editCurrentApp, bool isSingleSelection); - void activateAppEditForm(); + void setupAppEditForm(); - bool saveAppEditForm(); - bool saveAppEditFormMulti(const QString &appPath, const QString &appName, - const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked); - bool saveAppEditFormCheckEdited(const QString &appPath, const QString &appName, - const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked, bool &ok); + void addNewProgram(); + void editSelectedPrograms(); + void openAppEditForm(const AppRow &appRow, const QVector &appIdList = {}); void updateApp(int row, bool blocked); void deleteApp(int row); @@ -92,12 +69,9 @@ private: QString appListCurrentPath() const; private: - bool m_formAppForSelected = false; - ProgramsController *m_ctrl = nullptr; WidgetWindowStateWatcher *m_stateWatcher = nullptr; - QPushButton *m_btEdit = nullptr; QAction *m_actAllowApp = nullptr; QAction *m_actBlockApp = nullptr; QAction *m_actAddApp = nullptr; @@ -107,26 +81,10 @@ private: QPushButton *m_btAllowApp = nullptr; QPushButton *m_btBlockApp = nullptr; QPushButton *m_btRemoveApp = nullptr; - QLabel *m_labelEditPath = nullptr; - QLineEdit *m_editPath = nullptr; - QPushButton *m_btSelectFile = nullptr; - QLabel *m_labelEditName = nullptr; - QLineEdit *m_editName = nullptr; - QPushButton *m_btGetName = nullptr; - QLabel *m_labelAppGroup = nullptr; - QComboBox *m_comboAppGroup = nullptr; - QCheckBox *m_cbUseGroupPerm = nullptr; - QRadioButton *m_rbAllowApp = nullptr; - QRadioButton *m_rbBlockApp = nullptr; - CheckSpinCombo *m_cscBlockAppIn = nullptr; - QCheckBox *m_cbBlockAppAt = nullptr; - QDateTimeEdit *m_dteBlockAppAt = nullptr; - QCheckBox *m_cbBlockAppNone = nullptr; - QPushButton *m_btEditOk = nullptr; - QPushButton *m_btEditCancel = nullptr; - QDialog *m_formAppEdit = nullptr; + QPushButton *m_btEdit = nullptr; QPushButton *m_btLogOptions = nullptr; QCheckBox *m_cbLogBlocked = nullptr; + ProgramEditDialog *m_formAppEdit = nullptr; TableView *m_appListView = nullptr; AppInfoRow *m_appInfoRow = nullptr; }; diff --git a/src/ui/form/tray/trayicon.cpp b/src/ui/form/tray/trayicon.cpp index cbb3415e..ace5d04f 100644 --- a/src/ui/form/tray/trayicon.cpp +++ b/src/ui/form/tray/trayicon.cpp @@ -131,7 +131,20 @@ void TrayIcon::updateTrayMenuFlags() } } -void TrayIcon::retranslateTrayMenu() +void TrayIcon::setupController() +{ + connect(fortManager(), &FortManager::optWindowChanged, this, &TrayIcon::updateTrayMenuFlags); + connect(fortManager(), &FortManager::graphWindowChanged, m_graphWindowAction, + &QAction::setChecked); + + connect(settings(), &FortSettings::passwordUnlockChanged, this, &TrayIcon::updateTrayMenuFlags); + + connect(ctrl(), &TrayController::retranslateUi, this, &TrayIcon::retranslateUi); + + retranslateUi(); +} + +void TrayIcon::retranslateUi() { m_programsAction->setText(tr("Programs")); m_optionsAction->setText(tr("Options")); @@ -147,24 +160,6 @@ void TrayIcon::retranslateTrayMenu() m_quitAction->setText(tr("Quit")); } -void TrayIcon::onRetranslateUi() -{ - retranslateTrayMenu(); -} - -void TrayIcon::setupController() -{ - connect(fortManager(), &FortManager::optWindowChanged, this, &TrayIcon::updateTrayMenuFlags); - connect(fortManager(), &FortManager::graphWindowChanged, m_graphWindowAction, - &QAction::setChecked); - - connect(settings(), &FortSettings::passwordUnlockChanged, this, &TrayIcon::updateTrayMenuFlags); - - connect(ctrl(), &TrayController::retranslateUi, this, &TrayIcon::onRetranslateUi); - - emit ctrl()->retranslateUi(); -} - void TrayIcon::setupUi() { this->setToolTip(QApplication::applicationDisplayName()); diff --git a/src/ui/form/tray/trayicon.h b/src/ui/form/tray/trayicon.h index 7d7499e7..314bfe91 100644 --- a/src/ui/form/tray/trayicon.h +++ b/src/ui/form/tray/trayicon.h @@ -33,15 +33,13 @@ public slots: void updateTrayMenuFlags(); protected slots: - void retranslateTrayMenu(); - - void onRetranslateUi(); - void saveTrayFlags(); private: void setupController(); + void retranslateUi(); + void setupUi(); void setupTrayMenu(); diff --git a/src/ui/fortmanager.cpp b/src/ui/fortmanager.cpp index ae9be31c..a7947486 100644 --- a/src/ui/fortmanager.cpp +++ b/src/ui/fortmanager.cpp @@ -428,7 +428,7 @@ bool FortManager::showProgramEditForm(const QString &appPath) if (!(m_progWindow && m_progWindow->isVisible())) return false; // May be not opened due to password checking - if (!m_progWindow->openAppEditFormByPath(appPath)) { + if (!m_progWindow->editProgramByPath(appPath)) { showErrorBox(tr("Please close already opened Edit Program window and try again.")); return false; } diff --git a/src/ui/model/applistmodel.cpp b/src/ui/model/applistmodel.cpp index 50570080..eff1c6b6 100644 --- a/src/ui/model/applistmodel.cpp +++ b/src/ui/model/applistmodel.cpp @@ -294,13 +294,19 @@ const AppRow &AppListModel::appRowAt(int row) const return m_appRow; } +AppRow AppListModel::appRowById(qint64 appId) const +{ + AppRow appRow; + updateAppRow(sqlBase() + " WHERE t.app_id = ?1;", { appId }, appRow); + return appRow; +} + AppRow AppListModel::appRowByPath(const QString &appPath) const { AppRow appRow; - appRow.appPath = appPath; - - updateAppRow(sqlBase() + " WHERE path = ?1;", { appPath }, appRow); - + if (!updateAppRow(sqlBase() + " WHERE t.path = ?1;", { appPath }, appRow)) { + appRow.appPath = appPath; + } return appRow; } @@ -321,11 +327,9 @@ bool AppListModel::addApp(const QString &appPath, const QString &appName, const } bool AppListModel::updateApp(qint64 appId, const QString &appPath, const QString &appName, - const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked, - bool updateDriver) + const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked) { - if (updateDriver - && !confManager()->updateDriverUpdateApp(appPath, groupIndex, useGroupPerm, blocked)) + if (!confManager()->updateDriverUpdateApp(appPath, groupIndex, useGroupPerm, blocked)) return false; const auto groupId = appGroupAt(groupIndex)->id(); diff --git a/src/ui/model/applistmodel.h b/src/ui/model/applistmodel.h index 571468e9..a9f5afaf 100644 --- a/src/ui/model/applistmodel.h +++ b/src/ui/model/applistmodel.h @@ -54,13 +54,13 @@ public: QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override; const AppRow &appRowAt(int row) const; + AppRow appRowById(qint64 appId) const; AppRow appRowByPath(const QString &appPath) const; bool addApp(const QString &appPath, const QString &appName, const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked); bool updateApp(qint64 appId, const QString &appPath, const QString &appName, - const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked, - bool updateDriver = true); + const QDateTime &endTime, int groupIndex, bool useGroupPerm, bool blocked); bool updateAppName(qint64 appId, const QString &appName); void deleteApp(qint64 appId, const QString &appPath, int row); void purgeApps();