feat: implement filter dialog for administrative templates (#39)

* feat: add template filter

* feat: implement filter

* chore: add policyelement includes

* chore: remove template filters form mainwindow

* feat: add platform model

* chore: refactor template filter dialog

* chore: refactor administrative template snapin

* feat: add translation for filters

* fix: fix tests
This commit is contained in:
august-alt 2023-06-20 19:11:59 +04:00 committed by GitHub
parent 1d36ccc503
commit 1908488b00
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 2070 additions and 64 deletions

View File

@ -28,7 +28,6 @@ set(SOURCES
listboxdialog.cpp
mainwindow.cpp
mainwindowsettings.cpp
presentationbuilder.cpp
treevieweventfilter.cpp
)
@ -36,7 +35,7 @@ set(UI_FORMS
aboutdialog.ui
contentwidget.ui
listboxdialog.ui
mainwindow.ui
mainwindow.ui
)
set(MOC_HEADERS

View File

@ -22,10 +22,11 @@
#include "ui_contentwidget.h"
#include "presentationbuilder.h"
#include "../plugins/administrative_templates/admx/policy.h"
#include "../plugins/administrative_templates/admx/policyelement.h"
#include "../plugins/administrative_templates/bundle/itemtype.h"
#include "../plugins/administrative_templates/bundle/policyroles.h"
#include "../plugins/administrative_templates/presentation/presentation.h"
#include "pluginwidgetinterface.h"

View File

@ -33,7 +33,7 @@ namespace Ui { class ListBoxDialog; }
QT_END_NAMESPACE
namespace gpui {
class ListBoxDialog : public QDialog
class GPUI_GUI_EXPORT ListBoxDialog : public QDialog
{
Q_OBJECT
public:

View File

@ -557,4 +557,9 @@ void MainWindow::loadTranslations(QString &language)
d->translatorStorage->loadQtTranslations(language, "qt_");
}
void MainWindow::updateFilterModel()
{
loadPolicyModel(d->manager);
}
} // namespace gpui

View File

@ -23,8 +23,8 @@
#include "gui.h"
#include <QtWidgets>
#include "../core/translatorstorage.h"
#include <QtWidgets>
#include "../ldap/ldapcontract.h"
#include "../ldap/ldapimpl.h"
@ -57,7 +57,10 @@ class GPUI_GUI_EXPORT MainWindow : public QMainWindow
Q_OBJECT
public:
// construction and destruction
MainWindow(CommandLineOptions &options, ISnapInManager *manager, TranslatorStorage *translatorStorage, QWidget *parent = 0);
MainWindow(CommandLineOptions &options,
ISnapInManager *manager,
TranslatorStorage *translatorStorage,
QWidget *parent = 0);
~MainWindow();
void setLanguage(const QString &language);
@ -72,6 +75,8 @@ signals:
public slots:
void updateStatusBar();
void updateFilterModel();
protected:
void closeEvent(QCloseEvent *event) override;

View File

@ -32,7 +32,7 @@
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<widget class="QWidget" name="">
<widget class="QWidget" name="layoutWidget">
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QLineEdit" name="searchLineEdit">
@ -93,7 +93,7 @@
<x>0</x>
<y>0</y>
<width>995</width>
<height>22</height>
<height>19</height>
</rect>
</property>
<widget class="QMenu" name="menu_File">

View File

@ -64,8 +64,13 @@ set(HEADERS
registry/registryentry.h
registry/registryentrytype.h
registry/registrysourcetype.h
ui/administrativetemplateswidget.h
ui/administrativetemplatesproxymodel.h
ui/administrativetemplateswidget.h
ui/presentationbuilder.h
ui/platformmodel.h
ui/templatefilterdialog.h
ui/templatefilter.h
ui/templatefiltermodel.h
)
set(SOURCES
@ -78,12 +83,17 @@ set(SOURCES
registry/abstractregistrysource.cpp
registry/policystatemanager.cpp
registry/polregistrysource.cpp
ui/administrativetemplateswidget.cpp
ui/administrativetemplatesproxymodel.cpp
ui/administrativetemplateswidget.cpp
ui/presentationbuilder.cpp
ui/platformmodel.cpp
ui/templatefilterdialog.cpp
ui/templatefiltermodel.cpp
)
set(UI_FORMS
ui/administrativetemplateswidget.ui
ui/templatefilterdialog.ui
)
set(SOURCES ${SOURCES} ${HEADERS} ${UI_FORMS})
@ -107,5 +117,5 @@ qt5_add_resources(LIB_RESOURCES ${RESOURCES_SRC} ${ICON_RESOURCES})
add_gpui_plugin(${PLUGIN_NAME} ${SOURCES} ${LIB_RESOURCES})
target_link_libraries(${PLUGIN_NAME} Qt5::Core)
target_link_libraries(${PLUGIN_NAME} ${GPUI_CORE_LIBRARY} ${GPUI_IO_LIBRARY})
target_link_libraries(${PLUGIN_NAME} ${GPUI_CORE_LIBRARY} ${GPUI_GUI_LIBRARY} ${GPUI_IO_LIBRARY})
target_link_libraries(${PLUGIN_NAME} smb-storage-static)

View File

@ -50,6 +50,12 @@
#include "ui/administrativetemplatesproxymodel.h"
#include "ui/templatefilter.h"
#include "ui/templatefilterdialog.h"
#include "ui/templatefiltermodel.h"
#include "ui/platformmodel.h"
#include <QAction>
#include <QApplication>
#include <QDebug>
@ -157,12 +163,21 @@ public:
std::unique_ptr<model::registry::AbstractRegistrySource> machineRegistrySource{};
QString machineRegistryPath{};
TemplateFilterDialog *filterDialog = nullptr;
std::unique_ptr<TemplateFilterModel> filterModel = nullptr;
std::unique_ptr<PlatformModel> platformModel = nullptr;
std::vector<std::unique_ptr<QTranslator>> translators{};
std::string admxPath = "/usr/share/PolicyDefinitions/";
std::string localeName = "en-US";
std::string policyPath = "";
QAction actionEditFilter{};
QAction actionEnableFilter{};
std::unique_ptr<QMenu> filterMenu = nullptr;
QAction *fileAction{};
AdministrativeTemplatesSnapInPrivate()
@ -228,6 +243,18 @@ public:
auto bundle = std::make_unique<model::bundle::PolicyBundle>();
model = bundle->loadFolder(admxPath, localeName);
proxyModel->setSourceModel(model.get());
filterModel = std::make_unique<gpui::TemplateFilterModel>(nullptr);
filterModel->setSourceModel(proxyModel.get());
}
void updateFilter()
{
if (filterModel != nullptr)
{
const gpui::TemplateFilter filter = filterDialog->getFilter();
const bool filterEnabled = actionEnableFilter.isChecked();
filterModel->setFilter(filter, filterEnabled);
}
}
private:
@ -309,17 +336,46 @@ void AdministrativeTemplatesSnapIn::onInitialize(QMainWindow *window)
d->localeName = mainWindow->getLanguage().toStdString();
qWarning() << "Setting default settings for administrative templates snap-in: " << d->admxPath.c_str()
<< d->localeName.c_str();
d->filterDialog = new gpui::TemplateFilterDialog();
d->actionEnableFilter.setText(QObject::tr("Enable &filter"));
d->actionEditFilter.setText(QObject::tr("&Edit filter"));
d->filterMenu = std::make_unique<QMenu>(QObject::tr("&Filter"));
d->filterMenu->addAction(&d->actionEditFilter);
d->filterMenu->addAction(&d->actionEnableFilter);
d->actionEnableFilter.setCheckable(true);
QMenu *viewMenu = mainWindow->menuBar()->findChild<QMenu *>("menu_View");
if (viewMenu)
{
viewMenu->addMenu(d->filterMenu.get());
QObject::connect(d->filterDialog, &QDialog::accepted, [&]() { d->updateFilter(); });
QObject::connect(d->filterDialog, &QDialog::accepted, mainWindow, &MainWindow::updateFilterModel);
QObject::connect(&d->actionEditFilter, &QAction::triggered, d->filterDialog, &QDialog::open);
QObject::connect(&d->actionEnableFilter, &QAction::toggled, [&]() { d->updateFilter(); });
QObject::connect(&d->actionEnableFilter, &QAction::toggled, mainWindow, &MainWindow::updateFilterModel);
}
}
d->proxyModel = std::make_unique<AdministrativeTemplatesProxyModel>();
d->policyBundleLoad();
d->platformModel = std::make_unique<PlatformModel>(d->model.get());
d->filterDialog->setPlatformModel(d->platformModel.get());
QObject::connect(d->proxyModel.get(), &AdministrativeTemplatesProxyModel::savePolicyChanges, [&]() {
d->onDataSave();
});
setRootNode(static_cast<QAbstractItemModel *>(d->proxyModel.get()));
setRootNode(static_cast<QAbstractItemModel *>(d->filterModel.get()));
if (mainWindow)
{
@ -359,12 +415,14 @@ void AdministrativeTemplatesSnapIn::onDataLoad(const std::string &policyPath, co
d->userRegistrySource,
[&](model::registry::AbstractRegistrySource *) noexcept {});
d->proxyModel->setUserRegistrySource(d->userRegistrySource.get());
d->filterModel->setUserRegistrySource(d->userRegistrySource.get());
onPolFileOpen(d->machineRegistryPath,
d->machineRegistry,
d->machineRegistrySource,
[&](model::registry::AbstractRegistrySource *) noexcept {});
d->proxyModel->setMachineRegistrySource(d->machineRegistrySource.get());
d->filterModel->setMachineRegistrySource(d->machineRegistrySource.get());
}
}
@ -377,7 +435,7 @@ void AdministrativeTemplatesSnapIn::onRetranslateUI(const std::string &locale)
{
d->localeName = locale;
d->policyBundleLoad();
setRootNode(static_cast<QAbstractItemModel *>(d->proxyModel.get()));
setRootNode(static_cast<QAbstractItemModel *>(d->filterModel.get()));
}
} // namespace gpui

View File

@ -26,7 +26,7 @@
#include <QDataWidgetMapper>
#include "../gui/presentationbuilder.h"
#include "presentationbuilder.h"
#include "../presentation/presentation.h"
#include "../registry/abstractregistrysource.h"
@ -240,7 +240,7 @@ void AdministrativeTemplatesWidget::setModelIndex(const QModelIndex &index)
ui->okPushButton->disconnect();
ui->cancelPushButton->disconnect();
auto layout = ::gui::PresentationBuilder::build(
auto layout = PresentationBuilder::build(
{*presentation, *policy, *source, *ui->okPushButton, d->dataChanged, d->stateEnabled});
connectDialogBoxSignals();

View File

@ -52,88 +52,258 @@
<context>
<name>QObject</name>
<message>
<location filename="../../administrativetemplatessnapin.cpp" line="95"/>
<location filename="../../administrativetemplatessnapin.cpp" line="101"/>
<source>Error</source>
<translation>Error</translation>
</message>
<message>
<location filename="../../administrativetemplatessnapin.cpp" line="96"/>
<location filename="../../administrativetemplatessnapin.cpp" line="102"/>
<source>Error writing file:</source>
<translation>Error writing file:</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="90"/>
<location filename="../../administrativetemplatessnapin.cpp" line="343"/>
<source>&amp;Edit filter</source>
<translation>&amp;Edit filter</translation>
</message>
<message>
<location filename="../../administrativetemplatessnapin.cpp" line="342"/>
<source>Enable &amp;filter</source>
<translation>Enable &amp;filter</translation>
</message>
<message>
<location filename="../../administrativetemplatessnapin.cpp" line="345"/>
<source>&amp;Filter</source>
<translation>&amp;Filter</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="92"/>
<source>[Local Group Policy]</source>
<translation>[Local Group Policy]</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="92"/>
<location filename="../../bundle/policybundle.cpp" line="94"/>
<source>Local group policies</source>
<translation>Local group policies</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="99"/>
<location filename="../../bundle/policybundle.cpp" line="101"/>
<source>Machine</source>
<translation>Machine</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="101"/>
<location filename="../../bundle/policybundle.cpp" line="103"/>
<source>Machine level policies</source>
<translation>Machine level policies</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="106"/>
<location filename="../../bundle/policybundle.cpp" line="119"/>
<location filename="../../bundle/policybundle.cpp" line="108"/>
<location filename="../../bundle/policybundle.cpp" line="121"/>
<source>Administrative Templates</source>
<translation>Administrative Templates</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="108"/>
<location filename="../../bundle/policybundle.cpp" line="110"/>
<source>Machine administrative templates</source>
<translation>Machine administrative templates</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="112"/>
<location filename="../../bundle/policybundle.cpp" line="114"/>
<source>User</source>
<translation>User</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="114"/>
<location filename="../../bundle/policybundle.cpp" line="116"/>
<source>User level policies</source>
<translation>User level policies</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="121"/>
<location filename="../../bundle/policybundle.cpp" line="123"/>
<source>User administrative templates</source>
<translation>User administrative templates</translation>
</message>
<message>
<location filename="../administrativetemplateswidget.cpp" line="247"/>
<location filename="../administrativetemplateswidget.cpp" line="256"/>
<source>Save settings dialog</source>
<translation>Save settings dialog</translation>
</message>
<message>
<location filename="../administrativetemplateswidget.cpp" line="248"/>
<location filename="../administrativetemplateswidget.cpp" line="257"/>
<source>Policy settings were modified do you want to save them?</source>
<translation>Policy settings were modified do you want to save them?</translation>
</message>
<message>
<location filename="../presentationbuilder.cpp" line="102"/>
<source>Description:</source>
<translation>Description:</translation>
</message>
<message>
<location filename="../presentationbuilder.cpp" line="103"/>
<source>Options:</source>
<translation>Options:</translation>
</message>
<message>
<location filename="../presentationbuilder.cpp" line="257"/>
<source>Edit</source>
<translation>Edit</translation>
</message>
</context>
<context>
<name>TemplateFilterDialog</name>
<message>
<location filename="../templatefilterdialog.ui" line="32"/>
<source>Template Filters Dialog</source>
<translation>Template Filters Dialog</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="57"/>
<source>Managed:</source>
<translation>Managed:</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="67"/>
<source>Configured:</source>
<translation>Configured:</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="80"/>
<source>Commented:</source>
<translation>Commented:</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="109"/>
<location filename="../templatefilterdialog.ui" line="156"/>
<location filename="../templatefilterdialog.ui" line="206"/>
<location filename="../templatefilterdialog.ui" line="450"/>
<source>Any</source>
<translation>Any</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="114"/>
<location filename="../templatefilterdialog.ui" line="161"/>
<location filename="../templatefilterdialog.ui" line="211"/>
<location filename="../templatefilterdialog.ui" line="455"/>
<source>Yes</source>
<translation>Yes</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="119"/>
<location filename="../templatefilterdialog.ui" line="166"/>
<location filename="../templatefilterdialog.ui" line="216"/>
<location filename="../templatefilterdialog.ui" line="460"/>
<source>No</source>
<translation>No</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="236"/>
<source>Enable Requirements Filters</source>
<translation>Enable Requirements Filters</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="47"/>
<source>Select the type of policy settings to display.</source>
<translation>Select the type of policy settings to display.</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="289"/>
<source>Select the desired platform and application filter(s):</source>
<translation>Select the desired platform and application filter(s):</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="303"/>
<source>Include settings that match any of the selected platforms.</source>
<translation>Include settings that match any of the selected platforms.</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="308"/>
<source>Include settings that match all of the selected platforms.</source>
<translation>Include settings that match all of the selected platforms.</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="316"/>
<source>Select All</source>
<translation>Select All</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="323"/>
<source>Clear All</source>
<translation>Clear All</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="345"/>
<source>Cancel</source>
<translation>Cancel</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="361"/>
<source>Enable Keyword Filters</source>
<translation>Enable Keyword Filters</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="416"/>
<source>Policy Settings Title</source>
<translation>Policy Settings Title</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="426"/>
<source>Filter for word(s):</source>
<translation>Filter for word(s):</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="436"/>
<source>Within:</source>
<translation>Within:</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="471"/>
<source>Comment</source>
<translation>Comment</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="490"/>
<source>Help Text</source>
<translation>Help Text</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="539"/>
<source>Select options below to enable and change or disable types of global filters that will be applied to the Administrative Templates nodes.</source>
<translation>Select options below to enable and change or disable types of global filters that will be applied to the Administrative Templates nodes.</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="549"/>
<source>OK</source>
<translation>OK</translation>
</message>
</context>
<context>
<name>gpui::AdministrativeTemplatesWidget</name>
<message>
<location filename="../administrativetemplateswidget.cpp" line="168"/>
<location filename="../administrativetemplateswidget.cpp" line="177"/>
<source>Policy: </source>
<translation>Policy: </translation>
</message>
<message>
<location filename="../administrativetemplateswidget.cpp" line="251"/>
<location filename="../administrativetemplateswidget.cpp" line="260"/>
<source>Yes</source>
<translation>Yes</translation>
</message>
<message>
<location filename="../administrativetemplateswidget.cpp" line="252"/>
<location filename="../administrativetemplateswidget.cpp" line="261"/>
<source>No</source>
<translation>No</translation>
</message>
</context>
<context>
<name>gpui::TemplateFilterDialog</name>
<message>
<location filename="../templatefilterdialog.cpp" line="206"/>
<source>Filter Error</source>
<translation>Filter Error</translation>
</message>
<message>
<location filename="../templatefilterdialog.cpp" line="207"/>
<source>Please select one or more keyword filter Within options.</source>
<translation>Please select one or more keyword filter Within options.</translation>
</message>
</context>
</TS>

View File

@ -52,88 +52,258 @@
<context>
<name>QObject</name>
<message>
<location filename="../../administrativetemplatessnapin.cpp" line="95"/>
<location filename="../../administrativetemplatessnapin.cpp" line="101"/>
<source>Error</source>
<translation>Ошибка</translation>
</message>
<message>
<location filename="../../administrativetemplatessnapin.cpp" line="96"/>
<location filename="../../administrativetemplatessnapin.cpp" line="102"/>
<source>Error writing file:</source>
<translation>Ошибка записи файла:</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="90"/>
<location filename="../../administrativetemplatessnapin.cpp" line="343"/>
<source>&amp;Edit filter</source>
<translation>&amp;Редактировать фильтры</translation>
</message>
<message>
<location filename="../../administrativetemplatessnapin.cpp" line="342"/>
<source>Enable &amp;filter</source>
<translation>Включить &amp;фильтр</translation>
</message>
<message>
<location filename="../../administrativetemplatessnapin.cpp" line="345"/>
<source>&amp;Filter</source>
<translation>&amp;Фильтр</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="92"/>
<source>[Local Group Policy]</source>
<translation>[Локальная групповая политика]</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="92"/>
<location filename="../../bundle/policybundle.cpp" line="94"/>
<source>Local group policies</source>
<translation>Локальные групповые политики</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="99"/>
<location filename="../../bundle/policybundle.cpp" line="101"/>
<source>Machine</source>
<translation>Компьютер</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="101"/>
<location filename="../../bundle/policybundle.cpp" line="103"/>
<source>Machine level policies</source>
<translation>Политики настройки компьютера</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="106"/>
<location filename="../../bundle/policybundle.cpp" line="119"/>
<location filename="../../bundle/policybundle.cpp" line="108"/>
<location filename="../../bundle/policybundle.cpp" line="121"/>
<source>Administrative Templates</source>
<translation>Административные шаблоны</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="108"/>
<location filename="../../bundle/policybundle.cpp" line="110"/>
<source>Machine administrative templates</source>
<translation>Административные шаблоны компьютера</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="112"/>
<location filename="../../bundle/policybundle.cpp" line="114"/>
<source>User</source>
<translation>Пользователь</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="114"/>
<location filename="../../bundle/policybundle.cpp" line="116"/>
<source>User level policies</source>
<translation>Политики настройки пользователя</translation>
</message>
<message>
<location filename="../../bundle/policybundle.cpp" line="121"/>
<location filename="../../bundle/policybundle.cpp" line="123"/>
<source>User administrative templates</source>
<translation>Пользовательские административные шаблоны</translation>
</message>
<message>
<location filename="../administrativetemplateswidget.cpp" line="247"/>
<location filename="../administrativetemplateswidget.cpp" line="256"/>
<source>Save settings dialog</source>
<translation>Диалог сохранения настроек</translation>
</message>
<message>
<location filename="../administrativetemplateswidget.cpp" line="248"/>
<location filename="../administrativetemplateswidget.cpp" line="257"/>
<source>Policy settings were modified do you want to save them?</source>
<translation>Настройки политики были изменены, хотите сохранить их?</translation>
</message>
<message>
<location filename="../presentationbuilder.cpp" line="102"/>
<source>Description:</source>
<translation>Описание:</translation>
</message>
<message>
<location filename="../presentationbuilder.cpp" line="103"/>
<source>Options:</source>
<translation>Настройки:</translation>
</message>
<message>
<location filename="../presentationbuilder.cpp" line="257"/>
<source>Edit</source>
<translation>Редактировать</translation>
</message>
</context>
<context>
<name>TemplateFilterDialog</name>
<message>
<location filename="../templatefilterdialog.ui" line="32"/>
<source>Template Filters Dialog</source>
<translation>Диалог Фильтров Административных Шаблонов</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="57"/>
<source>Managed:</source>
<translation>Настроен:</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="67"/>
<source>Configured:</source>
<translation>Сконфигурирован:</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="80"/>
<source>Commented:</source>
<translation>Содержит комментарий:</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="109"/>
<location filename="../templatefilterdialog.ui" line="156"/>
<location filename="../templatefilterdialog.ui" line="206"/>
<location filename="../templatefilterdialog.ui" line="450"/>
<source>Any</source>
<translation>Любой</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="114"/>
<location filename="../templatefilterdialog.ui" line="161"/>
<location filename="../templatefilterdialog.ui" line="211"/>
<location filename="../templatefilterdialog.ui" line="455"/>
<source>Yes</source>
<translation>Да</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="119"/>
<location filename="../templatefilterdialog.ui" line="166"/>
<location filename="../templatefilterdialog.ui" line="216"/>
<location filename="../templatefilterdialog.ui" line="460"/>
<source>No</source>
<translation>Нет</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="236"/>
<source>Enable Requirements Filters</source>
<translation>Включить фильтр требований</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="47"/>
<source>Select the type of policy settings to display.</source>
<translation>Выбрать тип настроек групповой политики для отображения.</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="289"/>
<source>Select the desired platform and application filter(s):</source>
<translation>Выберите желаемые фильтры для платформ и приложений:</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="303"/>
<source>Include settings that match any of the selected platforms.</source>
<translation>Включать настройки, которые совпадают с любой из выбранных платформ.</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="308"/>
<source>Include settings that match all of the selected platforms.</source>
<translation>Включать настройки, которые совпадают со всеми выбранными платформами.</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="316"/>
<source>Select All</source>
<translation>Выбрать всё</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="323"/>
<source>Clear All</source>
<translation>Очистить всё</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="345"/>
<source>Cancel</source>
<translation>Отмена</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="361"/>
<source>Enable Keyword Filters</source>
<translation>Включить фильтр ключевых слов</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="416"/>
<source>Policy Settings Title</source>
<translation>Заголовка</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="426"/>
<source>Filter for word(s):</source>
<translation>Фильтр слов:</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="436"/>
<source>Within:</source>
<translation>Внутри:</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="471"/>
<source>Comment</source>
<translation>Комментария</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="490"/>
<source>Help Text</source>
<translation>Текста помощи</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="539"/>
<source>Select options below to enable and change or disable types of global filters that will be applied to the Administrative Templates nodes.</source>
<translation>Выберите опции внизу, чтобы включить и изменить или отключить типы глобальных фильтров, которые будут применены к узлам Административных Шаблонов.</translation>
</message>
<message>
<location filename="../templatefilterdialog.ui" line="549"/>
<source>OK</source>
<translation>OK</translation>
</message>
</context>
<context>
<name>gpui::AdministrativeTemplatesWidget</name>
<message>
<location filename="../administrativetemplateswidget.cpp" line="168"/>
<location filename="../administrativetemplateswidget.cpp" line="177"/>
<source>Policy: </source>
<translation>Политика: </translation>
</message>
<message>
<location filename="../administrativetemplateswidget.cpp" line="251"/>
<location filename="../administrativetemplateswidget.cpp" line="260"/>
<source>Yes</source>
<translation>Да</translation>
</message>
<message>
<location filename="../administrativetemplateswidget.cpp" line="252"/>
<location filename="../administrativetemplateswidget.cpp" line="261"/>
<source>No</source>
<translation>Нет</translation>
</message>
</context>
<context>
<name>gpui::TemplateFilterDialog</name>
<message>
<location filename="../templatefilterdialog.cpp" line="206"/>
<source>Filter Error</source>
<translation>Ошибка фильтра</translation>
</message>
<message>
<location filename="../templatefilterdialog.cpp" line="207"/>
<source>Please select one or more keyword filter Within options.</source>
<translation>Пожалуйста, выберите один или более фильтров.</translation>
</message>
</context>
</TS>

View File

@ -0,0 +1,115 @@
/***********************************************************************************************************************
**
** Copyright (C) 2023 BaseALT Ltd. <org@basealt.ru>
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
***********************************************************************************************************************/
#include "platformmodel.h"
#include <memory>
#include <QSet>
#include <QStack>
#include <QString>
#include "bundle/policyroles.h"
namespace gpui
{
class PlatformModelPrivate
{
public:
QStandardItemModel *sourceModel = nullptr;
QSet<QString> uniqueItems{};
PlatformModelPrivate() {}
~PlatformModelPrivate() {}
PlatformModelPrivate(const PlatformModelPrivate &) = delete; // copy ctor
PlatformModelPrivate(PlatformModelPrivate &&) = delete; // move ctor
PlatformModelPrivate &operator=(const PlatformModelPrivate &) = delete; // copy assignment
PlatformModelPrivate &operator=(PlatformModelPrivate &&) = delete; // move assignment
};
PlatformModel::PlatformModel(QStandardItemModel *sourceModel)
: QStandardItemModel()
, d(new PlatformModelPrivate())
{
setSourceData(sourceModel);
}
PlatformModel::~PlatformModel()
{
delete d;
}
void PlatformModel::setSourceData(QStandardItemModel *sourceModel)
{
if (sourceModel && (sourceModel != d->sourceModel))
{
d->sourceModel = sourceModel;
populateModel(d->sourceModel);
}
}
void PlatformModel::populateModel(QStandardItemModel *sourceModel)
{
d->uniqueItems.clear();
clear();
std::unique_ptr<QStack<QModelIndex>> stack = std::make_unique<QStack<QModelIndex>>();
stack->push(sourceModel->invisibleRootItem()->index());
while (!stack->empty())
{
auto current = stack->top();
stack->pop();
auto supportedOn = current.data(model::bundle::PolicyRoles::SUPPORTED_ON).value<QString>().trimmed();
if (!supportedOn.isEmpty())
{
d->uniqueItems.insert(supportedOn);
}
for (int row = 0; row < sourceModel->rowCount(current); ++row)
{
QModelIndex index = sourceModel->index(row, 0, current);
if (sourceModel->hasChildren(index))
{
for (int childRow = 0; childRow < sourceModel->rowCount(index); ++childRow)
{
QModelIndex childIndex = sourceModel->index(childRow, 0, index);
stack->push(childIndex);
}
}
}
}
for (const auto &uniqueItem : d->uniqueItems)
{
auto listElement = new QStandardItem(uniqueItem);
listElement->setCheckable(true);
insertRow(rowCount(), listElement);
}
}
} // namespace gpui

View File

@ -0,0 +1,59 @@
/***********************************************************************************************************************
**
** Copyright (C) 2023 BaseALT Ltd. <org@basealt.ru>
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
***********************************************************************************************************************/
#ifndef GPUI_PLATFORM_MODEL_H
#define GPUI_PLATFORM_MODEL_H
#include <QStandardItemModel>
namespace gpui
{
class PlatformModelPrivate;
/*!
* \class PlatformModel
* \brief The PlatformModel class
*
* \ingroup gpui
*/
class PlatformModel final : public QStandardItemModel
{
public:
PlatformModel(QStandardItemModel *sourceModel = nullptr);
~PlatformModel();
void setSourceData(QStandardItemModel *sourceModel);
private:
void populateModel(QStandardItemModel *sourceModel);
private:
PlatformModel(const PlatformModel &) = delete; // copy ctor
PlatformModel(PlatformModel &&) = delete; // move ctor
PlatformModel &operator=(const PlatformModel &) = delete; // copy assignment
PlatformModel &operator=(PlatformModel &&) = delete; // move assignment
private:
PlatformModelPrivate *d;
};
} // namespace gpui
#endif // GPUI_PLATFORM_MODEL_H

View File

@ -47,9 +47,9 @@
#include "../plugins/administrative_templates/admx/policylistelement.h"
#include "../plugins/administrative_templates/admx/policylongdecimalelement.h"
#include "listboxdialog.h"
#include "../gui/listboxdialog.h"
#include "altspinbox.h"
#include "../gui/altspinbox.h"
#include <QVBoxLayout>
@ -74,7 +74,7 @@ using namespace model::admx;
using namespace model::registry;
using namespace model::command;
namespace gui
namespace gpui
{
template<typename TLayoutItem>
QLayoutItem *createAndAttachLabel(QWidget *buddy, const QString &text)
@ -570,7 +570,7 @@ private:
{
if (spin)
{
AltSpinBox *spinBox = new AltSpinBox();
::gui::AltSpinBox *spinBox = new ::gui::AltSpinBox();
spinBox->setMinimum(0);
spinBox->setMaximum(std::numeric_limits<int>::max());
spinBox->setSingleStep(step);
@ -781,9 +781,9 @@ private:
}
};
PresentationBuilderPrivate *PresentationBuilder::d = new PresentationBuilderPrivate();
PresentationBuilderPrivate *gpui::PresentationBuilder::d = new PresentationBuilderPrivate();
QVBoxLayout *PresentationBuilder::build(const PresentationBuilderParams &params)
QVBoxLayout *::gpui::PresentationBuilder::build(const ::gpui::PresentationBuilderParams &params)
{
QVBoxLayout *layout = new QVBoxLayout();
d->setLayout(layout);

View File

@ -21,8 +21,6 @@
#ifndef GPUI_PRESENTATIONBUILDER_H
#define GPUI_PRESENTATIONBUILDER_H
#include "gui.h"
#include <QWidget>
#include <QDialogButtonBox>
@ -43,9 +41,9 @@ namespace model {
}
}
namespace gui
namespace gpui
{
struct GPUI_GUI_EXPORT PresentationBuilderParams final
struct PresentationBuilderParams final
{
const model::presentation::Presentation& presentation;
const model::admx::Policy& policy;
@ -63,7 +61,7 @@ namespace gui
*
* \ingroup gui
*/
class GPUI_GUI_EXPORT PresentationBuilder
class PresentationBuilder
{
public:
/*!

View File

@ -0,0 +1,71 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
***********************************************************************************************************************/
#ifndef GPUI_TEMPLATEFILTER_H
#define GPUI_TEMPLATEFILTER_H
#include "../plugins/administrative_templates/registry/policystatemanager.h"
#include <QMetaType>
#include <QSet>
namespace gpui
{
enum KeywordFilterType
{
KeywordFilterType_ANY,
KeywordFilterType_EXACT,
KeywordFilterType_ALL,
};
enum PlatformFilterType
{
PlatformFilterType_ANY,
PlatformFilterType_ALL
};
/*!
* \class TemplateFilter
* \brief The TemplateFilter class
*
* \ingroup gpui
*/
class TemplateFilter final
{
public:
bool keywordEnabled = false;
bool titleEnabled = false;
bool helpEnabled = false;
bool commentEnabled = false;
bool platformEnabled = false;
KeywordFilterType keywordType = KeywordFilterType_ANY;
QString keywordText = "";
QSet<model::registry::PolicyStateManager::PolicyState> configured{};
PlatformFilterType platformType = PlatformFilterType_ANY;
QSet<QString> selectedPlatforms{};
};
} // namespace gpui
Q_DECLARE_METATYPE(gpui::TemplateFilter)
#endif // GPUI_TEMPLATEFILTER_H

View File

@ -0,0 +1,299 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
***********************************************************************************************************************/
#include "templatefilterdialog.h"
#include "ui_templatefilterdialog.h"
#include "templatefilter.h"
#include "platformmodel.h"
using namespace model;
using namespace model::registry;
namespace gpui
{
enum FilterComboValue
{
FilterComboValue_ANY,
FilterComboValue_YES,
FilterComboValue_NO,
};
class TemplateFilterDialogPrivate
{
public:
TemplateFilterDialogPrivate() {}
Ui::TemplateFilterDialog *ui = nullptr;
QHash<QWidget *, QVariant> originalState{};
QList<QWidget *> getWidgetList() const;
TemplateFilterDialogPrivate(const TemplateFilterDialogPrivate &) = delete; // copy ctor
TemplateFilterDialogPrivate(TemplateFilterDialogPrivate &&) = delete; // move ctor
TemplateFilterDialogPrivate &operator=(const TemplateFilterDialogPrivate &) = delete; // copy assignment
TemplateFilterDialogPrivate &operator=(TemplateFilterDialogPrivate &&) = delete; // move assignment
};
TemplateFilterDialog::TemplateFilterDialog(QWidget *parent)
: QDialog(parent)
, d(new TemplateFilterDialogPrivate())
{
d->ui = new Ui::TemplateFilterDialog();
d->ui->setupUi(this);
}
TemplateFilterDialog::~TemplateFilterDialog()
{
delete d->ui;
delete d;
}
TemplateFilter TemplateFilterDialog::getFilter() const
{
TemplateFilter out;
out.keywordEnabled = d->ui->keywordCheckBox->isChecked();
out.titleEnabled = d->ui->titleCheckBox->isChecked();
out.helpEnabled = d->ui->helpCheckBox->isChecked();
out.commentEnabled = d->ui->commentCheckBox->isChecked();
out.platformEnabled = d->ui->platformCheckBox->isChecked();
out.keywordText = d->ui->keywordLineEdit->text();
out.keywordType = static_cast<KeywordFilterType>(d->ui->keywordComboBox->currentIndex());
out.platformType = static_cast<PlatformFilterType>(d->ui->platformComboBox->currentIndex());
out.selectedPlatforms = [&]() {
QSet<QString> platforms;
auto sourceModel = d->ui->platformTreeView->model();
auto current = sourceModel->index(0, 1);
for (int row = 0; row < sourceModel->rowCount(current); ++row)
{
QModelIndex index = sourceModel->index(row, 0, current);
auto state = index.data(Qt::CheckStateRole).value<Qt::CheckState>();
if (state == Qt::Checked)
{
platforms.insert(index.data().value<QString>());
}
}
return platforms;
}();
out.configured = [&]() {
const FilterComboValue configuredState = static_cast<FilterComboValue>(
d->ui->configuredComboBox->currentIndex());
switch (configuredState)
{
case FilterComboValue_ANY:
return QSet<PolicyStateManager::PolicyState>({
PolicyStateManager::STATE_NOT_CONFIGURED,
PolicyStateManager::STATE_ENABLED,
PolicyStateManager::STATE_DISABLED,
});
case FilterComboValue_YES:
return QSet<PolicyStateManager::PolicyState>({
PolicyStateManager::STATE_ENABLED,
PolicyStateManager::STATE_DISABLED,
});
case FilterComboValue_NO:
return QSet<PolicyStateManager::PolicyState>({
PolicyStateManager::STATE_NOT_CONFIGURED,
});
}
return QSet<PolicyStateManager::PolicyState>();
}();
// TODO: save filters from managed and comment combo
// boxes. Not sure what kind of data that will be yet
return out;
}
void TemplateFilterDialog::setPlatformModel(PlatformModel *platformModel)
{
if (platformModel)
{
d->ui->platformTreeView->setModel(platformModel);
}
}
// Save state when opening, to restore it later if
// dialog is rejected
void TemplateFilterDialog::open()
{
const QList<QWidget *> widgetList = d->getWidgetList();
for (QWidget *widget : widgetList)
{
QComboBox *combo = qobject_cast<QComboBox *>(widget);
QCheckBox *check = qobject_cast<QCheckBox *>(widget);
QGroupBox *groupbox = qobject_cast<QGroupBox *>(widget);
QLineEdit *lineedit = qobject_cast<QLineEdit *>(widget);
if (combo != nullptr)
{
d->originalState[widget] = combo->currentIndex();
}
else if (check != nullptr)
{
d->originalState[widget] = check->isChecked();
}
else if (groupbox != nullptr)
{
d->originalState[widget] = groupbox->isChecked();
}
else if (lineedit != nullptr)
{
d->originalState[widget] = lineedit->text();
}
}
QDialog::open();
}
void TemplateFilterDialog::accept()
{
const bool keywordWithinIsValid = [&]() {
if (d->ui->keywordCheckBox->isChecked())
{
const QList<bool> keyword_enabled_list = {
d->ui->titleCheckBox->isChecked(),
d->ui->helpCheckBox->isChecked(),
d->ui->commentCheckBox->isChecked(),
};
const bool any_keyword_enabled = keyword_enabled_list.contains(true);
return any_keyword_enabled;
}
else
{
return true;
}
}();
if (keywordWithinIsValid)
{
QDialog::accept();
}
else
{
const QString title = tr("Filter Error");
const QString text = tr("Please select one or more keyword filter Within options.");
QMessageBox::warning(this, title, text);
}
}
// Restore original state
void TemplateFilterDialog::reject()
{
const QList<QWidget *> widgetList = d->getWidgetList();
for (QWidget *widget : widgetList)
{
QComboBox *combo = qobject_cast<QComboBox *>(widget);
QCheckBox *check = qobject_cast<QCheckBox *>(widget);
QGroupBox *groupbox = qobject_cast<QGroupBox *>(widget);
QLineEdit *lineedit = qobject_cast<QLineEdit *>(widget);
if (combo != nullptr)
{
const int index = d->originalState[widget].value<int>();
combo->setCurrentIndex(index);
}
else if (check != nullptr)
{
const bool isChecked = d->originalState[widget].value<bool>();
check->setChecked(isChecked);
}
else if (groupbox != nullptr)
{
const bool isChecked = d->originalState[widget].value<bool>();
groupbox->setChecked(isChecked);
}
else if (lineedit != nullptr)
{
const QString text = d->originalState[widget].value<QString>();
lineedit->setText(text);
}
}
QDialog::reject();
}
void TemplateFilterDialog::on_selectPushButton_clicked()
{
auto sourceModel = d->ui->platformTreeView->model();
auto current = sourceModel->index(0, 1);
for (int row = 0; row < sourceModel->rowCount(current); ++row)
{
QModelIndex index = sourceModel->index(row, 0, current);
sourceModel->setData(index, Qt::Checked, Qt::CheckStateRole);
}
}
void TemplateFilterDialog::on_clearPushButton_clicked()
{
auto sourceModel = d->ui->platformTreeView->model();
auto current = sourceModel->index(0, 1);
for (int row = 0; row < sourceModel->rowCount(current); ++row)
{
QModelIndex index = sourceModel->index(row, 0, current);
sourceModel->setData(index, Qt::Unchecked, Qt::CheckStateRole);
}
}
// NOTE: add any new widgets you add to this list so that
// their state is saved
QList<QWidget *> TemplateFilterDialogPrivate::getWidgetList() const
{
const QList<QWidget *> out = {
ui->managedComboBox,
ui->configuredComboBox,
ui->commentedComboBox,
ui->keywordCheckBox,
ui->keywordLineEdit,
ui->keywordComboBox,
ui->titleCheckBox,
ui->helpCheckBox,
ui->commentCheckBox,
};
return out;
}
} // namespace gpui
Q_DECLARE_METATYPE(gpui::FilterComboValue)
Q_DECLARE_METATYPE(gpui::KeywordFilterType)

View File

@ -0,0 +1,63 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
***********************************************************************************************************************/
#ifndef GPUI_TEMPLATEFILTERDIALOG_H
#define GPUI_TEMPLATEFILTERDIALOG_H
#include <QtWidgets>
namespace gpui
{
class TemplateFilterDialogPrivate;
class TemplateFilter;
class PlatformModel;
class TemplateFilterDialog final : public QDialog
{
Q_OBJECT
public:
TemplateFilterDialog(QWidget *parent = 0);
~TemplateFilterDialog();
TemplateFilter getFilter() const;
void setPlatformModel(PlatformModel *platformModel);
public slots:
void open() override;
void accept() override;
void reject() override;
private:
TemplateFilterDialogPrivate *const d;
private slots:
void on_selectPushButton_clicked();
void on_clearPushButton_clicked();
private:
TemplateFilterDialog(const TemplateFilterDialog &) = delete; // copy ctor
TemplateFilterDialog(TemplateFilterDialog &&) = delete; // move ctor
TemplateFilterDialog &operator=(const TemplateFilterDialog &) = delete; // copy assignment
TemplateFilterDialog &operator=(TemplateFilterDialog &&) = delete; // move assignment
};
} // namespace gpui
#endif // GPUI_TEMPLATEFILTERDIALOG_H

View File

@ -0,0 +1,636 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>TemplateFilterDialog</class>
<widget class="QDialog" name="TemplateFilterDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>598</width>
<height>546</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>598</width>
<height>546</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>598</width>
<height>546</height>
</size>
</property>
<property name="windowTitle">
<string>Template Filters Dialog</string>
</property>
<layout class="QGridLayout" name="gridLayout_4">
<item row="2" column="0" colspan="3">
<widget class="QFrame" name="selectFrame">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="displayLabel">
<property name="text">
<string>Select the type of policy settings to display.</string>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="managedLabel">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Managed:</string>
</property>
<property name="buddy">
<cstring>managedComboBox</cstring>
</property>
</widget>
</item>
<item row="1" column="2">
<widget class="QLabel" name="configLabel">
<property name="text">
<string>Configured:</string>
</property>
<property name="buddy">
<cstring>configuredComboBox</cstring>
</property>
</widget>
</item>
<item row="1" column="4">
<widget class="QLabel" name="commentLabel">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Commented:</string>
</property>
<property name="buddy">
<cstring>commentedComboBox</cstring>
</property>
</widget>
</item>
<item row="2" column="0">
<widget class="QComboBox" name="managedComboBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>130</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="editable">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>Any</string>
</property>
</item>
<item>
<property name="text">
<string>Yes</string>
</property>
</item>
<item>
<property name="text">
<string>No</string>
</property>
</item>
</widget>
</item>
<item row="2" column="1">
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>75</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="2">
<widget class="QComboBox" name="configuredComboBox">
<property name="minimumSize">
<size>
<width>130</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="editable">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>Any</string>
</property>
</item>
<item>
<property name="text">
<string>Yes</string>
</property>
</item>
<item>
<property name="text">
<string>No</string>
</property>
</item>
</widget>
</item>
<item row="2" column="3">
<spacer name="horizontalSpacer_3">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>75</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="2" column="4">
<widget class="QComboBox" name="commentedComboBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="minimumSize">
<size>
<width>130</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="editable">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>Any</string>
</property>
</item>
<item>
<property name="text">
<string>Yes</string>
</property>
</item>
<item>
<property name="text">
<string>No</string>
</property>
</item>
</widget>
</item>
</layout>
</widget>
</item>
<item row="4" column="0" colspan="3">
<widget class="QFrame" name="requireFrame">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout_6">
<item row="0" column="0">
<widget class="QCheckBox" name="platformCheckBox">
<property name="text">
<string>Enable Requirements Filters</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QFrame" name="requireGroup">
<property name="enabled">
<bool>false</bool>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QGridLayout" name="gridLayout_3">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item row="2" column="0" rowspan="3">
<widget class="QTreeView" name="platformTreeView">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<attribute name="headerVisible">
<bool>false</bool>
</attribute>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="platformLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Select the desired platform and application filter(s):</string>
</property>
<property name="buddy">
<cstring>platformComboBox</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QComboBox" name="platformComboBox">
<property name="editable">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>Include settings that match any of the selected platforms.</string>
</property>
</item>
<item>
<property name="text">
<string>Include settings that match all of the selected platforms.</string>
</property>
</item>
</widget>
</item>
<item row="1" column="1">
<widget class="QPushButton" name="selectPushButton">
<property name="text">
<string>Select All</string>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="QPushButton" name="clearPushButton">
<property name="text">
<string>Clear All</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
<zorder>requireGroup</zorder>
<zorder>platformCheckBox</zorder>
</widget>
</item>
<item row="1" column="0" colspan="3">
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item row="5" column="1">
<widget class="QPushButton" name="cancelPushButton">
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
<item row="3" column="0" colspan="3">
<widget class="QFrame" name="kwordFrame">
<property name="frameShape">
<enum>QFrame::Box</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<layout class="QGridLayout" name="gridLayout_5">
<item row="0" column="0">
<widget class="QCheckBox" name="keywordCheckBox">
<property name="text">
<string>Enable Keyword Filters</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QFrame" name="keywordFrame">
<property name="enabled">
<bool>false</bool>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<layout class="QGridLayout" name="gridLayout_2">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="horizontalSpacing">
<number>5</number>
</property>
<item row="1" column="1">
<widget class="QCheckBox" name="titleCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Maximum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>130</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>130</width>
<height>16777215</height>
</size>
</property>
<property name="text">
<string>Policy Settings Title</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
<item row="0" column="0">
<widget class="QLabel" name="keywordLabel">
<property name="text">
<string>Filter for word(s):</string>
</property>
<property name="buddy">
<cstring>keywordLineEdit</cstring>
</property>
</widget>
</item>
<item row="1" column="0">
<widget class="QLabel" name="withinLabel">
<property name="text">
<string>Within:</string>
</property>
<property name="buddy">
<cstring>titleCheckBox</cstring>
</property>
</widget>
</item>
<item row="0" column="4">
<widget class="QComboBox" name="keywordComboBox">
<property name="editable">
<bool>false</bool>
</property>
<item>
<property name="text">
<string>Any</string>
</property>
</item>
<item>
<property name="text">
<string>Yes</string>
</property>
</item>
<item>
<property name="text">
<string>No</string>
</property>
</item>
</widget>
</item>
<item row="1" column="3">
<widget class="QCheckBox" name="commentCheckBox">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Comment</string>
</property>
<property name="checked">
<bool>false</bool>
</property>
</widget>
</item>
<item row="0" column="1" colspan="3">
<widget class="QLineEdit" name="keywordLineEdit"/>
</item>
<item row="1" column="2">
<widget class="QCheckBox" name="helpCheckBox">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Help Text</string>
</property>
<property name="checked">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
<zorder>keywordFrame</zorder>
<zorder>keywordCheckBox</zorder>
</widget>
</item>
<item row="5" column="0">
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item row="0" column="0" colspan="3">
<widget class="QLabel" name="headLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
<horstretch>0</horstretch>
<verstretch>30</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>30</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>30</height>
</size>
</property>
<property name="text">
<string>Select options below to enable and change or disable types of global filters that will be applied to the Administrative Templates nodes.</string>
</property>
<property name="wordWrap">
<bool>true</bool>
</property>
</widget>
</item>
<item row="5" column="2">
<widget class="QPushButton" name="okPushButton">
<property name="text">
<string>OK</string>
</property>
</widget>
</item>
</layout>
</widget>
<tabstops>
<tabstop>managedComboBox</tabstop>
<tabstop>configuredComboBox</tabstop>
<tabstop>commentedComboBox</tabstop>
<tabstop>keywordCheckBox</tabstop>
<tabstop>keywordLineEdit</tabstop>
<tabstop>keywordComboBox</tabstop>
<tabstop>titleCheckBox</tabstop>
<tabstop>helpCheckBox</tabstop>
<tabstop>commentCheckBox</tabstop>
<tabstop>platformCheckBox</tabstop>
<tabstop>platformComboBox</tabstop>
<tabstop>platformTreeView</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>okPushButton</sender>
<signal>clicked()</signal>
<receiver>TemplateFilterDialog</receiver>
<slot>accept()</slot>
<hints>
<hint type="sourcelabel">
<x>550</x>
<y>528</y>
</hint>
<hint type="destinationlabel">
<x>298</x>
<y>272</y>
</hint>
</hints>
</connection>
<connection>
<sender>cancelPushButton</sender>
<signal>clicked()</signal>
<receiver>TemplateFilterDialog</receiver>
<slot>reject()</slot>
<hints>
<hint type="sourcelabel">
<x>465</x>
<y>528</y>
</hint>
<hint type="destinationlabel">
<x>298</x>
<y>272</y>
</hint>
</hints>
</connection>
<connection>
<sender>keywordCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>keywordFrame</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>298</x>
<y>159</y>
</hint>
<hint type="destinationlabel">
<x>298</x>
<y>200</y>
</hint>
</hints>
</connection>
<connection>
<sender>platformCheckBox</sender>
<signal>toggled(bool)</signal>
<receiver>requireGroup</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>116</x>
<y>258</y>
</hint>
<hint type="destinationlabel">
<x>297</x>
<y>385</y>
</hint>
</hints>
</connection>
</connections>
</ui>

View File

@ -0,0 +1,275 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
***********************************************************************************************************************/
#include "templatefiltermodel.h"
#include "templatefilter.h"
#include "../plugins/administrative_templates/admx/policy.h"
#include "../plugins/administrative_templates/admx/policyelement.h"
#include "../plugins/administrative_templates/bundle/policyroles.h"
#include "../plugins/administrative_templates/registry/abstractregistrysource.h"
#include "../plugins/administrative_templates/registry/policystatemanager.h"
#include <QDebug>
using namespace model::registry;
using namespace model::admx;
using namespace model::bundle;
namespace gpui
{
typedef std::shared_ptr<Policy> PolicyPtr;
class TemplateFilterModelPrivate
{
public:
// TODO: don't like these members, they are already in
// main window
AbstractRegistrySource *userSource = nullptr;
AbstractRegistrySource *machineSource = nullptr;
TemplateFilter filter{};
bool enabled = false;
};
TemplateFilterModel::TemplateFilterModel(QObject *parent)
: QSortFilterProxyModel(parent)
, d(new TemplateFilterModelPrivate())
{
d->filter.keywordEnabled = false;
d->filter.titleEnabled = false;
d->filter.helpEnabled = false;
d->filter.commentEnabled = false;
d->filter.keywordType = KeywordFilterType_ANY;
d->filter.keywordText = QString();
;
d->filter.configured = QSet<PolicyStateManager::PolicyState>();
d->enabled = false;
setRecursiveFilteringEnabled(true);
}
TemplateFilterModel::~TemplateFilterModel()
{
delete d;
}
void TemplateFilterModel::setFilter(const TemplateFilter &filter, const bool enabled)
{
d->filter = filter;
d->enabled = enabled;
invalidateFilter();
}
// NOTE: filterAcceptsRow() is split in 2 parts because the
// code to get policy state is too hard to mock so we avoid
// testing it.
bool TemplateFilterModel::filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
const QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
// TODO: this is very convoluted, also duplicating
// part of ContentWidget::onListItemClicked()
const PolicyStateManager::PolicyState state = [&]() {
const QAbstractItemModel *model = index.model();
auto policy = model->data(index, PolicyRoles::POLICY).value<PolicyPtr>();
if (policy == nullptr)
{
return PolicyStateManager::STATE_NOT_CONFIGURED;
}
const auto source = [&]() {
if (policy->policyType == PolicyType::Machine)
{
return d->machineSource;
}
else
{
return d->userSource;
}
}();
if (source == nullptr)
{
return PolicyStateManager::STATE_NOT_CONFIGURED;
}
const auto manager = std::make_unique<PolicyStateManager>(*source, *policy);
const PolicyStateManager::PolicyState curremtPolicyState = manager->determinePolicyState();
return curremtPolicyState;
}();
return filterAcceptsRow(index, state);
}
bool TemplateFilterModel::filterAcceptsRow(const QModelIndex &index, const PolicyStateManager::PolicyState state) const
{
if (!d->enabled)
{
return true;
}
// TODO: implement comment filter (comment data not
// stored in model yet)
const bool commentMatch = true;
auto checkKeywordMatch = [&](const QString &string) {
const QList<QString> keywordList = d->filter.keywordText.split(" ");
switch (d->filter.keywordType)
{
case KeywordFilterType_ANY: {
for (const QString &keyword : keywordList)
{
const bool match = string.contains(keyword);
if (match)
{
return true;
}
}
return false;
}
case KeywordFilterType_EXACT: {
const bool out = (string.contains(d->filter.keywordText));
return out;
}
case KeywordFilterType_ALL: {
for (const QString &keyword : keywordList)
{
const bool match = string.contains(keyword);
if (!match)
{
return false;
}
}
return true;
}
}
return false;
};
auto checkPlatformMatch = [&](const QString &string) {
switch (d->filter.platformType)
{
case PlatformFilterType_ANY: {
for (const QString &keyword : d->filter.selectedPlatforms)
{
return string.contains(keyword);
}
return false;
}
case PlatformFilterType_ALL: {
for (const QString &keyword : d->filter.selectedPlatforms)
{
if (!string.contains(keyword))
{
return false;
}
}
return true;
}
default:
return false;
}
return false;
};
const bool helpMatch = [&]() {
const QString helpText = index.data(PolicyRoles::EXPLAIN_TEXT).value<QString>();
const bool out = checkKeywordMatch(helpText);
return out;
}();
const bool titleMatch = [&]() {
const QString titleText = index.data(Qt::DisplayRole).value<QString>();
const bool out = checkKeywordMatch(titleText);
return out;
}();
const bool keywordMatch = [&]() {
if (d->filter.titleEnabled && titleMatch)
{
return true;
}
else if (d->filter.helpEnabled && helpMatch)
{
return true;
}
else if (d->filter.commentEnabled && commentMatch)
{
return true;
}
else
{
return false;
}
}();
if (d->filter.platformEnabled && !checkPlatformMatch(index.data(PolicyRoles::SUPPORTED_ON).value<QString>()))
{
return false;
}
const bool configuredMatch = d->filter.configured.contains(state);
if (d->filter.keywordEnabled && !keywordMatch)
{
return false;
}
if (!configuredMatch)
{
return false;
}
return true;
}
void TemplateFilterModel::setUserRegistrySource(AbstractRegistrySource *registrySource)
{
d->userSource = registrySource;
}
void TemplateFilterModel::setMachineRegistrySource(AbstractRegistrySource *registrySource)
{
d->machineSource = registrySource;
}
} // namespace gpui
Q_DECLARE_METATYPE(std::shared_ptr<Policy>)

View File

@ -0,0 +1,73 @@
/***********************************************************************************************************************
**
** Copyright (C) 2021 BaseALT Ltd. <org@basealt.ru>
**
** This program is free software; you can redistribute it and/or
** modify it under the terms of the GNU General Public License
** as published by the Free Software Foundation; either version 2
** of the License, or (at your option) any later version.
**
** This program is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with this program; if not, write to the Free Software
** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
**
***********************************************************************************************************************/
#ifndef GPUI_TEMPLATEFILTERMODEL_H
#define GPUI_TEMPLATEFILTERMODEL_H
#include "registry/policystatemanager.h"
#include <QSortFilterProxyModel>
namespace model
{
namespace registry
{
class AbstractRegistrySource;
}
} // namespace model
namespace gpui
{
class TemplateFilterModelPrivate;
class TemplateFilter;
/*!
* \class TemplateFilterModel
* \brief The TemplateFilterModel class
*
* \ingroup gpui
*/
class TemplateFilterModel final : public QSortFilterProxyModel
{
public:
TemplateFilterModel(QObject *parent);
~TemplateFilterModel();
void setFilter(const TemplateFilter &filter, const bool enabled);
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const override;
void setUserRegistrySource(model::registry::AbstractRegistrySource *registrySource);
void setMachineRegistrySource(model::registry::AbstractRegistrySource *registrySource);
bool filterAcceptsRow(const QModelIndex &index, const model::registry::PolicyStateManager::PolicyState state) const;
private:
TemplateFilterModel(const TemplateFilterModel &) = delete; // copy ctor
TemplateFilterModel(TemplateFilterModel &&) = delete; // move ctor
TemplateFilterModel &operator=(const TemplateFilterModel &) = delete; // copy assignment
TemplateFilterModel &operator=(TemplateFilterModel &&) = delete; // move assignment
private:
TemplateFilterModelPrivate *d;
};
} // namespace gpui
#endif // GPUI_TEMPLATEFILTERMODEL_H

View File

@ -32,7 +32,7 @@
#include "../../../../src/plugins/administrative_templates/presentation/text.h"
#include "../../../../src/plugins/administrative_templates/presentation/textbox.h"
#include "../../../../src/gui/presentationbuilder.h"
#include "../../../../src/plugins/administrative_templates/ui/presentationbuilder.h"
#include "../../../../src/plugins/administrative_templates/admx/policy.h"
#include "../../../../src/plugins/administrative_templates/admx/policyelement.h"
@ -48,7 +48,6 @@
namespace tests
{
using namespace gui;
using namespace model::presentation;
void PresentationBuilderTest::build()

View File

@ -26,7 +26,7 @@
#include "../../../../src/plugins/administrative_templates/presentation/presentationwidget.h"
#include "../../../../src/plugins/adml/admlformat.h"
#include "../../../../src/gui/presentationbuilder.h"
#include "../../../../src/plugins/administrative_templates/ui/presentationbuilder.h"
#include "../../../../src/plugins/administrative_templates/admx/policy.h"
#include "../../../../src/plugins/administrative_templates/admx/policyelement.h"