UI: Extract ZoneSelector

This commit is contained in:
Nodir Temirkhodjaev 2023-12-16 08:10:07 +03:00
parent b66611e4ae
commit 5176bc46be
9 changed files with 262 additions and 225 deletions

View File

@ -55,6 +55,7 @@ SOURCES += \
form/controls/tableview.cpp \
form/controls/textarea2splitter.cpp \
form/controls/textarea2splitterhandle.cpp \
form/controls/zonesselector.cpp \
form/dialog/dialogutil.cpp \
form/dialog/passworddialog.cpp \
form/graph/axistickerspeed.cpp \
@ -249,6 +250,7 @@ HEADERS += \
form/controls/tableview.h \
form/controls/textarea2splitter.h \
form/controls/textarea2splitterhandle.h \
form/controls/zonesselector.h \
form/dialog/dialogutil.h \
form/dialog/passworddialog.h \
form/graph/axistickerspeed.h \

View File

@ -5,40 +5,6 @@ AddressGroup::AddressGroup(QObject *parent) :
{
}
void AddressGroup::addIncludeZone(int zoneId)
{
addZone(m_includeZones, zoneId);
}
void AddressGroup::removeIncludeZone(int zoneId)
{
removeZone(m_includeZones, zoneId);
}
void AddressGroup::addExcludeZone(int zoneId)
{
addZone(m_excludeZones, zoneId);
}
void AddressGroup::removeExcludeZone(int zoneId)
{
removeZone(m_excludeZones, zoneId);
}
void AddressGroup::addZone(quint32 &zones, int zoneId)
{
zones |= (quint32(1) << (zoneId - 1));
setEdited(true);
}
void AddressGroup::removeZone(quint32 &zones, int zoneId)
{
zones &= ~(quint32(1) << (zoneId - 1));
setEdited(true);
}
void AddressGroup::setIncludeAll(bool includeAll)
{
if (m_includeAll != includeAll) {
@ -55,6 +21,22 @@ void AddressGroup::setExcludeAll(bool excludeAll)
}
}
void AddressGroup::setIncludeZones(quint32 v)
{
if (m_includeZones != v) {
m_includeZones = v;
setEdited(true);
}
}
void AddressGroup::setExcludeZones(quint32 v)
{
if (m_excludeZones != v) {
m_excludeZones = v;
setEdited(true);
}
}
void AddressGroup::setIncludeText(const QString &includeText)
{
if (m_includeText != includeText) {

View File

@ -25,16 +25,10 @@ public:
void setId(qint64 id) { m_id = id; }
quint32 includeZones() const { return m_includeZones; }
void setIncludeZones(quint32 v) { m_includeZones = v; }
void setIncludeZones(quint32 v);
quint32 excludeZones() const { return m_excludeZones; }
void setExcludeZones(quint32 v) { m_excludeZones = v; }
void addIncludeZone(int zoneId);
void removeIncludeZone(int zoneId);
void addExcludeZone(int zoneId);
void removeExcludeZone(int zoneId);
void setExcludeZones(quint32 v);
QString includeText() const { return m_includeText; }
void setIncludeText(const QString &includeText);
@ -47,10 +41,6 @@ public:
QVariant toVariant() const;
void fromVariant(const QVariant &v);
private:
void addZone(quint32 &zones, int zoneId);
void removeZone(quint32 &zones, int zoneId);
private:
bool m_edited : 1;

View File

@ -0,0 +1,158 @@
#include "zonesselector.h"
#include <QMenu>
#include <conf/confmanager.h>
#include <driver/drivercommon.h>
#include <form/controls/controlutil.h>
#include <model/zonelistmodel.h>
#include <util/iconcache.h>
#include <util/ioc/ioccontainer.h>
namespace {
constexpr quint32 getZoneMask(int zoneId)
{
return quint32(1) << (zoneId - 1);
}
}
ZonesSelector::ZonesSelector(QWidget *parent) : QPushButton(parent)
{
setupUi();
}
void ZonesSelector::setZones(quint32 zones)
{
if (m_zones == zones)
return;
m_zones = zones;
retranslateZonesText();
}
int ZonesSelector::zonesCount() const
{
return DriverCommon::bitCount(m_zones);
}
void ZonesSelector::retranslateUi()
{
retranslateZonesText();
this->setToolTip(tr("Select Zones"));
}
void ZonesSelector::retranslateZonesText()
{
this->setText(tr("Zones") + QString(" (%1)").arg(zonesCount()));
}
void ZonesSelector::setupUi()
{
setIcon(IconCache::icon(":/icons/ip_class.png"));
setupZones();
}
void ZonesSelector::setupZones()
{
m_menuZones = ControlUtil::createMenu(this);
this->setMenu(m_menuZones);
connect(m_menuZones, &QMenu::aboutToShow, this, &ZonesSelector::updateZonesMenu);
auto confManager = IoC<ConfManager>();
connect(confManager, &ConfManager::zoneRemoved, this, [&](int zoneId) {
removeZone(zoneId);
retranslateZonesText();
});
auto zoneListModel = IoC<ZoneListModel>();
connect(zoneListModel, &ZoneListModel::modelChanged, this, [&] {
clearZonesMenu();
updateZonesMenuEnabled();
});
updateZonesMenuEnabled();
}
void ZonesSelector::clearZonesMenu()
{
m_menuZones->close();
m_menuZones->clear();
}
void ZonesSelector::createZonesMenu()
{
auto zoneListModel = IoC<ZoneListModel>();
const int zoneCount = zoneListModel->rowCount();
for (int row = 0; row < zoneCount; ++row) {
const auto zoneRow = zoneListModel->zoneRowAt(row);
auto action = new QAction(zoneRow.zoneName, m_menuZones);
action->setCheckable(true);
action->setData(zoneRow.zoneId);
connect(action, &QAction::triggered, this, &ZonesSelector::onZoneClicked);
m_menuZones->addAction(action);
}
}
void ZonesSelector::updateZonesMenu()
{
if (m_menuZones->isEmpty()) {
createZonesMenu();
}
const auto actions = m_menuZones->actions();
for (auto action : actions) {
const int zoneId = action->data().toInt();
const quint32 zoneMask = getZoneMask(zoneId);
const bool checked = (m_zones & zoneMask) != 0;
action->setChecked(checked);
}
}
void ZonesSelector::updateZonesMenuEnabled()
{
auto zoneListModel = IoC<ZoneListModel>();
const bool isZoneExist = (zoneListModel->rowCount() != 0);
this->setEnabled(isZoneExist);
}
void ZonesSelector::addZone(int zoneId)
{
m_zones |= getZoneMask(zoneId);
}
void ZonesSelector::removeZone(int zoneId)
{
m_zones &= ~getZoneMask(zoneId);
}
void ZonesSelector::onZoneClicked(bool checked)
{
auto action = qobject_cast<QAction *>(sender());
const int zoneId = action->data().toInt();
if (checked) {
addZone(zoneId);
} else {
removeZone(zoneId);
}
emit zonesChanged();
retranslateZonesText();
}

View File

@ -0,0 +1,45 @@
#ifndef ZONESSELECTOR_H
#define ZONESSELECTOR_H
#include <QPushButton>
class ZonesSelector : public QPushButton
{
Q_OBJECT
public:
explicit ZonesSelector(QWidget *parent = nullptr);
quint32 zones() const { return m_zones; }
void setZones(quint32 zones);
int zonesCount() const;
void retranslateUi();
signals:
void zonesChanged();
private:
void retranslateZonesText();
void setupUi();
void setupZones();
void clearZonesMenu();
void createZonesMenu();
void updateZonesMenu();
void updateZonesMenuEnabled();
void addZone(int zoneId);
void removeZone(int zoneId);
void onZoneClicked(bool checked);
private:
quint32 m_zones = 0;
QMenu *m_menuZones = nullptr;
};
#endif // ZONESSELECTOR_H

View File

@ -3,12 +3,12 @@
#include <QCheckBox>
#include <QHBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QToolButton>
#include <QVBoxLayout>
#include <form/controls/controlutil.h>
#include <form/controls/plaintextedit.h>
#include <form/controls/zonesselector.h>
#include <manager/windowmanager.h>
#include <util/ioc/ioccontainer.h>
@ -17,25 +17,9 @@ AddressesColumn::AddressesColumn(QWidget *parent) : QWidget(parent)
setupUi();
}
void AddressesColumn::setZonesCount(qint8 v)
{
if (m_zonesCount == v)
return;
m_zonesCount = v;
retranslateZonesText();
}
void AddressesColumn::retranslateUi()
{
retranslateZonesText();
m_btSelectZones->setToolTip(tr("Select Zones"));
}
void AddressesColumn::retranslateZonesText()
{
m_btSelectZones->setText(tr("Zones") + QString(" (%1)").arg(zonesCount()));
m_btSelectZones->retranslateUi();
}
void AddressesColumn::setupUi()
@ -64,7 +48,7 @@ QLayout *AddressesColumn::setupHeaderLayout()
m_cbUseAll = new QCheckBox();
// Select Zones
m_btSelectZones = ControlUtil::createButton(":/icons/ip_class.png");
m_btSelectZones = new ZonesSelector();
auto layout = new QHBoxLayout();
layout->addWidget(m_labelTitle);

View File

@ -5,9 +5,9 @@
QT_FORWARD_DECLARE_CLASS(QCheckBox)
QT_FORWARD_DECLARE_CLASS(QLabel)
QT_FORWARD_DECLARE_CLASS(QPushButton)
class PlainTextEdit;
class ZonesSelector;
class AddressesColumn : public QWidget
{
@ -16,29 +16,22 @@ class AddressesColumn : public QWidget
public:
explicit AddressesColumn(QWidget *parent = nullptr);
qint8 zonesCount() const { return m_zonesCount; }
void setZonesCount(qint8 v);
QLabel *labelTitle() const { return m_labelTitle; }
QCheckBox *cbUseAll() const { return m_cbUseAll; }
QPushButton *btSelectZones() const { return m_btSelectZones; }
ZonesSelector *btSelectZones() const { return m_btSelectZones; }
PlainTextEdit *editIpText() const { return m_editIpText; }
public slots:
void retranslateUi();
private:
void retranslateZonesText();
void setupUi();
QLayout *setupHeaderLayout();
private:
qint8 m_zonesCount = 0;
QLabel *m_labelTitle = nullptr;
QCheckBox *m_cbUseAll = nullptr;
QPushButton *m_btSelectZones = nullptr;
ZonesSelector *m_btSelectZones = nullptr;
PlainTextEdit *m_editIpText = nullptr;
};

View File

@ -4,7 +4,6 @@
#include <QHBoxLayout>
#include <QIcon>
#include <QLabel>
#include <QMenu>
#include <QPlainTextEdit>
#include <QPushButton>
#include <QTabBar>
@ -14,15 +13,14 @@
#include <conf/addressgroup.h>
#include <conf/confmanager.h>
#include <conf/firewallconf.h>
#include <driver/drivercommon.h>
#include <form/controls/controlutil.h>
#include <form/controls/plaintextedit.h>
#include <form/controls/textarea2splitter.h>
#include <form/controls/textarea2splitterhandle.h>
#include <form/controls/zonesselector.h>
#include <form/opt/optionscontroller.h>
#include <fortmanager.h>
#include <fortsettings.h>
#include <model/zonelistmodel.h>
#include <user/iniuser.h>
#include <util/iconcache.h>
#include <util/net/netutil.h>
@ -214,17 +212,6 @@ void AddressesPage::setupSplitterButtons()
layout->addWidget(m_btAddLocals, 0, Qt::AlignHCenter);
}
void AddressesPage::updateGroup()
{
m_includeAddresses->cbUseAll()->setChecked(addressGroup()->includeAll());
m_includeAddresses->editIpText()->setText(addressGroup()->includeText());
m_excludeAddresses->cbUseAll()->setChecked(addressGroup()->excludeAll());
m_excludeAddresses->editIpText()->setText(addressGroup()->excludeText());
updateZonesTextAll();
}
void AddressesPage::setupAddressGroup()
{
connect(this, &AddressesPage::addressGroupChanged, this, &AddressesPage::updateGroup);
@ -239,127 +226,43 @@ void AddressesPage::setupAddressGroup()
connect(m_tabBar, &QTabBar::currentChanged, this, refreshAddressGroup);
}
void AddressesPage::clearZonesMenu()
{
m_menuZones->close();
m_menuZones->clear();
}
void AddressesPage::createZonesMenu()
{
const auto onZoneActionTriggered = [&](bool checked) {
auto action = qobject_cast<QAction *>(sender());
const int zoneId = action->data().toInt();
const bool include = m_includeAddresses->btSelectZones()->isDown();
auto addrGroup = this->addressGroup();
if (checked) {
if (include) {
addrGroup->addIncludeZone(zoneId);
} else {
addrGroup->addExcludeZone(zoneId);
}
} else {
if (include) {
addrGroup->removeIncludeZone(zoneId);
} else {
addrGroup->removeExcludeZone(zoneId);
}
}
ctrl()->setOptEdited();
updateZonesText(include);
};
const int zoneCount = zoneListModel()->rowCount();
for (int row = 0; row < zoneCount; ++row) {
const auto zoneRow = zoneListModel()->zoneRowAt(row);
auto action = new QAction(zoneRow.zoneName, m_menuZones);
action->setCheckable(true);
action->setData(zoneRow.zoneId);
connect(action, &QAction::triggered, this, onZoneActionTriggered);
m_menuZones->addAction(action);
}
}
void AddressesPage::updateZonesMenu(bool include)
{
if (m_menuZones->isEmpty()) {
createZonesMenu();
}
const auto actions = m_menuZones->actions();
if (actions.isEmpty())
return;
const quint32 zonesMask = addressGroupZones(include);
for (auto action : actions) {
const int zoneId = action->data().toInt();
const quint32 zoneMask = (quint32(1) << (zoneId - 1));
const bool checked = (zonesMask & zoneMask) != 0;
action->setChecked(checked);
}
}
void AddressesPage::updateZonesMenuEnabled()
{
const bool isZoneExist = (zoneListModel()->rowCount() != 0);
m_includeAddresses->btSelectZones()->setEnabled(isZoneExist);
m_excludeAddresses->btSelectZones()->setEnabled(isZoneExist);
}
void AddressesPage::updateZonesText(bool include)
{
AddressesColumn *addressesColumn = include ? m_includeAddresses : m_excludeAddresses;
addressesColumn->setZonesCount(zonesCount(include));
}
void AddressesPage::updateZonesTextAll()
{
updateZonesText(/*include=*/true);
updateZonesText(/*include=*/false);
}
void AddressesPage::setupZones()
{
m_menuZones = ControlUtil::createMenu(this);
connect(m_includeAddresses->btSelectZones(), &ZonesSelector::zonesChanged, this, [&] {
const quint32 zones = m_includeAddresses->btSelectZones()->zones();
const auto refreshZonesMenu = [&] {
const bool include = (sender() == m_includeAddresses->btSelectZones());
if (addressGroup()->includeZones() == zones)
return;
updateZonesMenu(include);
};
addressGroup()->setIncludeZones(zones);
connect(m_includeAddresses->btSelectZones(), &QPushButton::pressed, this, refreshZonesMenu);
connect(m_excludeAddresses->btSelectZones(), &QPushButton::pressed, this, refreshZonesMenu);
m_includeAddresses->btSelectZones()->setMenu(m_menuZones);
m_excludeAddresses->btSelectZones()->setMenu(m_menuZones);
updateZonesMenuEnabled();
connect(confManager(), &ConfManager::zoneRemoved, this, [&](int zoneId) {
for (auto addrGroup : addressGroups()) {
addrGroup->removeIncludeZone(zoneId);
addrGroup->removeExcludeZone(zoneId);
}
updateZonesTextAll();
ctrl()->setOptEdited();
});
connect(zoneListModel(), &ZoneListModel::modelChanged, this, [&] {
clearZonesMenu();
updateZonesMenuEnabled();
updateZonesTextAll();
connect(m_excludeAddresses->btSelectZones(), &ZonesSelector::zonesChanged, this, [&] {
const quint32 zones = m_excludeAddresses->btSelectZones()->zones();
if (addressGroup()->excludeZones() == zones)
return;
addressGroup()->setExcludeZones(zones);
ctrl()->setOptEdited();
});
}
void AddressesPage::updateGroup()
{
m_includeAddresses->cbUseAll()->setChecked(addressGroup()->includeAll());
m_includeAddresses->editIpText()->setText(addressGroup()->includeText());
m_excludeAddresses->cbUseAll()->setChecked(addressGroup()->excludeAll());
m_excludeAddresses->editIpText()->setText(addressGroup()->excludeText());
m_includeAddresses->btSelectZones()->setZones(addressGroup()->includeZones());
m_excludeAddresses->btSelectZones()->setZones(addressGroup()->excludeZones());
}
const QList<AddressGroup *> &AddressesPage::addressGroups() const
{
return conf()->addressGroups();
@ -369,15 +272,3 @@ AddressGroup *AddressesPage::addressGroupByIndex(int index) const
{
return addressGroups().at(index);
}
quint32 AddressesPage::addressGroupZones(bool include) const
{
return include ? addressGroup()->includeZones() : addressGroup()->excludeZones();
}
qint8 AddressesPage::zonesCount(bool include) const
{
const quint32 zonesMask = addressGroupZones(include);
return DriverCommon::bitCount(zonesMask);
}

View File

@ -6,6 +6,7 @@
class AddressGroup;
class AddressesColumn;
class TextArea2Splitter;
class ZonesSelector;
class AddressesPage : public OptBasePage
{
@ -37,23 +38,15 @@ private:
void setupAddressesUseAllEnabled();
void setupSplitter();
void setupSplitterButtons();
void updateGroup();
void setupAddressGroup();
void clearZonesMenu();
void createZonesMenu();
void updateZonesMenu(bool include);
void updateZonesMenuEnabled();
void updateZonesText(bool include);
void updateZonesTextAll();
void setupZones();
void updateGroup();
const QList<AddressGroup *> &addressGroups() const;
AddressGroup *addressGroupByIndex(int index) const;
quint32 addressGroupZones(bool include) const;
qint8 zonesCount(bool include) const;
private:
int m_addressGroupIndex = -1;
@ -62,7 +55,6 @@ private:
AddressesColumn *m_excludeAddresses = nullptr;
TextArea2Splitter *m_splitter = nullptr;
QToolButton *m_btAddLocals = nullptr;
QMenu *m_menuZones = nullptr;
};
#endif // ADDRESSESPAGE_H