diff --git a/src/ui/conf/appgroup.h b/src/ui/conf/appgroup.h index 1c39af28..98c3a0c0 100644 --- a/src/ui/conf/appgroup.h +++ b/src/ui/conf/appgroup.h @@ -7,6 +7,10 @@ class AppGroup : public QObject { Q_OBJECT + Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) + Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) + Q_PROPERTY(QString blockText READ blockText WRITE setBlockText NOTIFY blockTextChanged) + Q_PROPERTY(QString allowText READ allowText WRITE setAllowText NOTIFY allowTextChanged) public: explicit AppGroup(QObject *parent = nullptr); diff --git a/src/ui/conf/firewallconf.cpp b/src/ui/conf/firewallconf.cpp index 654cb39b..31384610 100644 --- a/src/ui/conf/firewallconf.cpp +++ b/src/ui/conf/firewallconf.cpp @@ -85,6 +85,13 @@ void FirewallConf::addAppGroup(AppGroup *appGroup, int to) emit appGroupsChanged(); } +void FirewallConf::addAppGroupByName(const QString &name) +{ + AppGroup *appGroup = new AppGroup(); + appGroup->setName(name); + addAppGroup(appGroup); +} + void FirewallConf::moveAppGroup(int from, int to) { m_appGroups.move(from, to); @@ -94,7 +101,9 @@ void FirewallConf::moveAppGroup(int from, int to) void FirewallConf::removeAppGroup(int from, int to) { for (int i = to; i >= from; --i) { - delete m_appGroups.at(i); + AppGroup *appGroup = m_appGroups.at(i); + appGroup->deleteLater(); + m_appGroups.removeAt(i); } emit appGroupsChanged(); diff --git a/src/ui/conf/firewallconf.h b/src/ui/conf/firewallconf.h index fc242984..452c540b 100644 --- a/src/ui/conf/firewallconf.h +++ b/src/ui/conf/firewallconf.h @@ -44,10 +44,6 @@ public: const QList &appGroupsList() const { return m_appGroups; } QQmlListProperty appGroups(); - void addAppGroup(AppGroup *appGroup, int to = -1); - void moveAppGroup(int from, int to); - void removeAppGroup(int from, int to); - QVariant toVariant() const; void fromVariant(const QVariant &v); @@ -59,6 +55,10 @@ signals: void appGroupsChanged(); public slots: + void addAppGroup(AppGroup *appGroup, int to = -1); + void addAppGroupByName(const QString &name); + void moveAppGroup(int from, int to); + void removeAppGroup(int from, int to); private: uint m_filterEnabled : 1; diff --git a/src/ui/fort_qml.qrc b/src/ui/fort_qml.qrc index 6bde235b..d7ae5175 100644 --- a/src/ui/fort_qml.qrc +++ b/src/ui/fort_qml.qrc @@ -1,5 +1,6 @@ + qml/controls/TextAreaFrame.qml qml/main.qml qml/pages/ActivityPage.qml qml/pages/AddressesPage.qml @@ -7,5 +8,7 @@ qml/pages/BasePage.qml qml/pages/OptionsPage.qml qml/pages/addresses/AddressesColumn.qml + qml/pages/apps/AppsColumn.qml + qml/pages/apps/AppsTextColumn.qml diff --git a/src/ui/fortmanager.cpp b/src/ui/fortmanager.cpp index 46b529aa..00337166 100644 --- a/src/ui/fortmanager.cpp +++ b/src/ui/fortmanager.cpp @@ -79,10 +79,10 @@ bool FortManager::saveConf() void FortManager::handleClosedWindow() { m_engine->deleteLater(); - m_engine = 0; + m_engine = nullptr; if (m_firewallConfToEdit && m_firewallConfToEdit != m_firewallConf) { m_firewallConfToEdit->deleteLater(); - m_firewallConfToEdit = 0; + m_firewallConfToEdit = nullptr; } } diff --git a/src/ui/qml/controls/TextAreaFrame.qml b/src/ui/qml/controls/TextAreaFrame.qml new file mode 100644 index 00000000..ec894f71 --- /dev/null +++ b/src/ui/qml/controls/TextAreaFrame.qml @@ -0,0 +1,21 @@ +import QtQuick 2.9 +import QtQuick.Controls 2.2 + +Frame { + id: frame + + signal editingFinished() // Workaround for QTBUG-59908 + + readonly property alias textArea: textArea + + padding: 0 + + ScrollView { + anchors.fill: parent + + TextArea { + id: textArea + onEditingFinished: frame.editingFinished() + } + } +} diff --git a/src/ui/qml/main.qml b/src/ui/qml/main.qml index abcc2853..400e3bab 100644 --- a/src/ui/qml/main.qml +++ b/src/ui/qml/main.qml @@ -13,8 +13,8 @@ ApplicationWindow { width: 800 height: 600 - minimumWidth: 400 - minimumHeight: 300 + minimumWidth: 540 + minimumHeight: 500 font.pixelSize: 16 diff --git a/src/ui/qml/pages/ApplicationsPage.qml b/src/ui/qml/pages/ApplicationsPage.qml index 6c7bd0be..6aaa08c1 100644 --- a/src/ui/qml/pages/ApplicationsPage.qml +++ b/src/ui/qml/pages/ApplicationsPage.qml @@ -1,19 +1,45 @@ import QtQuick 2.9 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 +import "apps" import com.fortfirewall 1.0 BasePage { + readonly property var appGroups: firewallConf.appGroups + + function resetGroupName() { + editGroupName.text = ""; + editGroupName.forceActiveFocus(); + } + ColumnLayout { anchors.fill: parent RowLayout { - Button { - text: QT_TRANSLATE_NOOP("qml", "Add Group") + TextField { + enabled: rptAppGroups.count < 16 + id: editGroupName + placeholderText: QT_TRANSLATE_NOOP("qml", "Group Name") } Button { - text: QT_TRANSLATE_NOOP("qml", "Remove Group") + enabled: editGroupName.text + text: QT_TRANSLATE_NOOP("qml", "Add Group") + onClicked: { + const lastIndex = appGroups.length; + firewallConf.addAppGroupByName(editGroupName.text); + barGroups.currentIndex = lastIndex; + resetGroupName(); + } + } + Button { + enabled: appsColumn.enabled + text: QT_TRANSLATE_NOOP("qml", "Rename Group") + onClicked: { + const appGroup = appsColumn.appGroup; + appGroup.name = editGroupName.text; + resetGroupName(); + } } Item { @@ -22,24 +48,53 @@ BasePage { CheckBox { text: QT_TRANSLATE_NOOP("qml", "Block All") + checked: firewallConf.appBlockAll + onToggled: { + firewallConf.appBlockAll = checked; + } } CheckBox { text: QT_TRANSLATE_NOOP("qml", "Allow All") + checked: firewallConf.appAllowAll + onToggled: { + firewallConf.appAllowAll = checked; + } } } TabBar { id: barGroups Layout.fillWidth: true + clip: true - TabButton { - text: QT_TRANSLATE_NOOP("qml", "Options") + Repeater { + id: rptAppGroups + model: appGroups + + TabButton { + width: Math.max(70, implicitWidth) + text: appGroup.name + + readonly property AppGroup appGroup: modelData + } } } - Item { + AppsColumn { + id: appsColumn Layout.fillWidth: true Layout.fillHeight: true + + enabled: index >= 0 + opacity: enabled ? 1.0 : 0 + + Behavior on opacity { NumberAnimation { duration: 150 } } + + index: barGroups.currentIndex + appGroup: enabled ? barGroups.currentItem.appGroup + : nullAppGroup + + readonly property AppGroup nullAppGroup: AppGroup {} } } } diff --git a/src/ui/qml/pages/BasePage.qml b/src/ui/qml/pages/BasePage.qml index 97d4857d..89af212f 100644 --- a/src/ui/qml/pages/BasePage.qml +++ b/src/ui/qml/pages/BasePage.qml @@ -2,5 +2,4 @@ import QtQuick 2.9 import QtQuick.Controls 2.2 Frame { - } diff --git a/src/ui/qml/pages/addresses/AddressesColumn.qml b/src/ui/qml/pages/addresses/AddressesColumn.qml index 001153af..088fec63 100644 --- a/src/ui/qml/pages/addresses/AddressesColumn.qml +++ b/src/ui/qml/pages/addresses/AddressesColumn.qml @@ -1,6 +1,7 @@ import QtQuick 2.9 import QtQuick.Layouts 1.3 import QtQuick.Controls 2.2 +import "../../controls" import com.fortfirewall 1.0 ColumnLayout { @@ -8,8 +9,8 @@ ColumnLayout { Layout.fillWidth: true Layout.fillHeight: true - property alias title: title - property alias checkBoxAll: checkBoxAll + readonly property alias title: title + readonly property alias checkBoxAll: checkBoxAll property AddressGroup addressGroup @@ -27,28 +28,23 @@ ColumnLayout { } } - Frame { + TextAreaFrame { Layout.fillWidth: true Layout.fillHeight: true - padding: 0 - - ScrollView { - anchors.fill: parent - - TextArea { - placeholderText: " + textArea { + placeholderText: " 10.0.0.0/24 127.0.0.0/24 169.254.0.0/16 172.16.0.0/16 192.168.0.0/16 " - text: addressGroup.text - onEditingFinished: { - addressGroup.text = text; - } - } + text: addressGroup.text + } + + onEditingFinished: { + addressGroup.text = textArea.text; } } } diff --git a/src/ui/qml/pages/apps/AppsColumn.qml b/src/ui/qml/pages/apps/AppsColumn.qml new file mode 100644 index 00000000..3eacec83 --- /dev/null +++ b/src/ui/qml/pages/apps/AppsColumn.qml @@ -0,0 +1,72 @@ +import QtQuick 2.9 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.2 +import com.fortfirewall 1.0 + +ColumnLayout { + + property int index + property AppGroup appGroup + + RowLayout { + Button { + text: QT_TRANSLATE_NOOP("qml", "Remove Group") + onClicked: { + firewallConf.removeAppGroup(index, index); + } + } + + Item { + Layout.fillWidth: true + } + + CheckBox { + text: QT_TRANSLATE_NOOP("qml", "Enabled") + checked: appGroup.enabled + onToggled: { + appGroup.enabled = checked; + } + } + } + + RowLayout { + Layout.fillWidth: true + Layout.fillHeight: true + spacing: 10 + + AppsTextColumn { + title { + text: QT_TRANSLATE_NOOP("qml", "Block") + } + + textArea { + placeholderText: " +System +C:\\Program Files\\Internet Explorer\\iexplore.exe +" + text: appGroup.blockText + } + + onEditingFinished: { + appGroup.blockText = textArea.text; + } + } + + AppsTextColumn { + title { + text: QT_TRANSLATE_NOOP("qml", "Allow") + } + + textArea { + placeholderText: " +C:\\Program Files\\Skype\\Phone\\Skype.exe +" + text: appGroup.allowText + } + + onEditingFinished: { + appGroup.allowText = textArea.text; + } + } + } +} diff --git a/src/ui/qml/pages/apps/AppsTextColumn.qml b/src/ui/qml/pages/apps/AppsTextColumn.qml new file mode 100644 index 00000000..41c7c0d7 --- /dev/null +++ b/src/ui/qml/pages/apps/AppsTextColumn.qml @@ -0,0 +1,29 @@ +import QtQuick 2.9 +import QtQuick.Layouts 1.3 +import QtQuick.Controls 2.2 +import "../../controls" +import com.fortfirewall 1.0 + +ColumnLayout { + id: container + Layout.preferredWidth: 100 + Layout.fillWidth: true + Layout.fillHeight: true + + signal editingFinished() // Workaround for QTBUG-59908 + + readonly property alias title: title + readonly property alias textArea: textAreaFrame.textArea + + Label { + id: title + } + + TextAreaFrame { + id: textAreaFrame + Layout.fillWidth: true + Layout.fillHeight: true + + onEditingFinished: container.editingFinished() + } +}