1
0
mirror of https://github.com/altlinux/admc.git synced 2025-03-12 00:58:22 +03:00

rework settings

remove Settings class
don't need to keep around qsettings
remove usage of bool settings
rework creation of actions tied to settings
save state in dtor's, can do that now because qsettings is not tied to
\ Settings object anymore
This commit is contained in:
Dmitry Degtyarev 2021-07-26 12:29:25 +04:00
parent 890e6b6033
commit e6aefa5568
35 changed files with 417 additions and 437 deletions

View File

@ -69,8 +69,15 @@ CentralWidget::CentralWidget(AdInterface &ad)
console_actions = new ConsoleActions(this);
open_filter_action = new QAction(tr("&Filter objects"), this);
dev_mode_action = new QAction(tr("Dev mode"), this);
show_noncontainers_action = new QAction(tr("&Show non-container objects in Console tree"), this);
// NOTE: these actions are not connected here because
// they need to be connected to a custom slot
dev_mode_action = settings_make_action(BoolSetting_DevMode, tr("Dev mode"), this);
show_noncontainers_action = settings_make_action(BoolSetting_ShowNonContainersInConsoleTree, tr("&Show non-container objects in Console tree"), this);
advanced_features_action = settings_make_action(BoolSetting_AdvancedFeatures, tr("Advanced features"), this);
toggle_console_tree_action = settings_make_and_connect_action(BoolSetting_AdvancedFeatures, tr("Console Tree"), this);
toggle_description_bar_action = settings_make_and_connect_action(BoolSetting_ShowResultsHeader, tr("Description Bar"), this);
console = new ConsoleWidget();
@ -105,37 +112,28 @@ CentralWidget::CentralWidget(AdInterface &ad)
setLayout(layout);
layout->addWidget(console);
const QVariant console_widget_state = g_settings->get_variant(VariantSetting_ConsoleWidgetState);
const QVariant console_widget_state = settings_get_variant(VariantSetting_ConsoleWidgetState);
console->restore_state(console_widget_state);
const QVariant policy_results_state = g_settings->get_variant(VariantSetting_PolicyResultsState);
policy_results_widget->restore_state(policy_results_state);
const QVariant filter_dialog_state = g_settings->get_variant(VariantSetting_FilterDialogState);
filter_dialog->restore_state(filter_dialog_state);
// Refresh head when settings affecting the filter
// change. This reloads the model with an updated filter
const BoolSettingSignal *advanced_features = g_settings->get_bool_signal(BoolSetting_AdvancedFeatures);
connect(
advanced_features, &BoolSettingSignal::changed,
this, &CentralWidget::refresh_head);
const BoolSettingSignal *show_non_containers = g_settings->get_bool_signal(BoolSetting_ShowNonContainersInConsoleTree);
show_noncontainers_action, &QAction::toggled,
this, &CentralWidget::on_show_non_containers);
on_show_non_containers();
connect(
show_non_containers, &BoolSettingSignal::changed,
this, &CentralWidget::refresh_head);
dev_mode_action, &QAction::toggled,
this, &CentralWidget::on_dev_mode);
on_dev_mode();
const BoolSettingSignal *dev_mode_signal = g_settings->get_bool_signal(BoolSetting_DevMode);
connect(
dev_mode_signal, &BoolSettingSignal::changed,
this, &CentralWidget::refresh_head);
toggle_console_tree_action, &QAction::toggled,
this, &CentralWidget::on_toggle_console_tree);
on_toggle_console_tree();
g_settings->connect_toggle_widget(console->get_scope_view(), BoolSetting_ShowConsoleTree);
g_settings->connect_toggle_widget(console->get_description_bar(), BoolSetting_ShowResultsHeader);
g_settings->connect_action_to_bool_setting(dev_mode_action, BoolSetting_DevMode);
g_settings->connect_action_to_bool_setting(show_noncontainers_action, BoolSetting_ShowNonContainersInConsoleTree);
connect(
toggle_description_bar_action, &QAction::toggled,
this, &CentralWidget::on_toggle_description_bar);
on_toggle_description_bar();
connect(
open_filter_action, &QAction::triggered,
@ -262,15 +260,9 @@ CentralWidget::CentralWidget(AdInterface &ad)
console->set_current_scope(console_object_head()->index());
}
void CentralWidget::save_state() {
const QVariant console_widget_state = console->save_state();
g_settings->set_variant(VariantSetting_ConsoleWidgetState, console_widget_state);
const QVariant policy_results_state = policy_results_widget->save_state();
g_settings->set_variant(VariantSetting_PolicyResultsState, policy_results_state);
const QVariant filter_dialog_state = filter_dialog->save_state();
g_settings->set_variant(VariantSetting_FilterDialogState, filter_dialog_state);
CentralWidget::~CentralWidget() {
const QVariant state = console->save_state();
settings_set_variant(VariantSetting_ConsoleWidgetState, state);
}
void CentralWidget::object_delete() {
@ -722,6 +714,34 @@ void CentralWidget::on_object_properties_applied() {
update_actions_visibility();
}
void CentralWidget::on_show_non_containers() {
settings_set_bool(BoolSetting_ShowNonContainersInConsoleTree, show_noncontainers_action->isChecked());
refresh_head();
}
void CentralWidget::on_dev_mode() {
settings_set_bool(BoolSetting_DevMode, dev_mode_action->isChecked());
refresh_head();
}
void CentralWidget::on_advanced_features() {
settings_set_bool(BoolSetting_AdvancedFeatures, advanced_features_action->isChecked());
refresh_head();
}
void CentralWidget::on_toggle_console_tree() {
const bool visible = toggle_console_tree_action->isChecked();
console->get_scope_view()->setVisible(visible);
}
void CentralWidget::on_toggle_description_bar() {
const bool visible = toggle_description_bar_action->isChecked();
console->get_description_bar()->setVisible(visible);
}
void CentralWidget::refresh_head() {
show_busy_indicator();
@ -753,30 +773,34 @@ void CentralWidget::update_description_bar() {
console->set_description_bar_text(text);
}
void CentralWidget::add_actions_to_action_menu(QMenu *menu) {
console_actions->add_to_menu(menu);
void CentralWidget::add_actions_to_menus(QMenu *action_menu, QMenu *navigation_menu, QMenu *view_menu, QMenu *preferences_menu) {
// Action
console_actions->add_to_menu(action_menu);
menu->addSeparator();
action_menu->addSeparator();
console->add_actions_to_action_menu(menu);
}
console->add_actions_to_action_menu(action_menu);
void CentralWidget::add_actions_to_navigation_menu(QMenu *menu) {
console->add_actions_to_navigation_menu(menu);
}
// Navigation
console->add_actions_to_navigation_menu(navigation_menu);
void CentralWidget::add_actions_to_view_menu(QMenu *menu) {
console->add_actions_to_view_menu(menu);
// View
console->add_actions_to_view_menu(view_menu);
menu->addSeparator();
view_menu->addSeparator();
menu->addAction(open_filter_action);
view_menu->addAction(open_filter_action);
menu->addAction(show_noncontainers_action);
view_menu->addAction(show_noncontainers_action);
#ifdef QT_DEBUG
menu->addAction(dev_mode_action);
view_menu->addAction(dev_mode_action);
#endif
// Preferences
preferences_menu->addAction(advanced_features_action);
preferences_menu->addAction(toggle_console_tree_action);
preferences_menu->addAction(toggle_description_bar_action);
}
void CentralWidget::fetch_scope_node(const QModelIndex &index) {

View File

@ -63,11 +63,9 @@ class CentralWidget final : public QWidget {
public:
CentralWidget(AdInterface &ad);
void save_state();
~CentralWidget();
void add_actions_to_action_menu(QMenu *menu);
void add_actions_to_navigation_menu(QMenu *menu);
void add_actions_to_view_menu(QMenu *menu);
void add_actions_to_menus(QMenu *action_menu, QMenu *navigation_menu, QMenu *view_menu, QMenu *preferences_menu);
signals:
void context_menu(const QPoint pos);
@ -108,6 +106,12 @@ private slots:
void on_current_scope_changed();
void on_object_properties_applied();
void on_show_non_containers();
void on_dev_mode();
void on_advanced_features();
void on_toggle_console_tree();
void on_toggle_description_bar();
private:
ConsoleWidget *console;
FilterDialog *filter_dialog;
@ -118,6 +122,9 @@ private:
QAction *open_filter_action;
QAction *show_noncontainers_action;
QAction *dev_mode_action;
QAction *advanced_features_action;
QAction *toggle_console_tree_action;
QAction *toggle_description_bar_action;
void update_description_bar();
void enable_disable_helper(const bool disabled);

View File

@ -77,7 +77,7 @@ void ChangeDCDialog::accept() {
console_object_load_domain_head_text(domain_head_item);
if (save_dc_checkbox->isChecked()) {
g_settings->set_variant(VariantSetting_DC, current_dc);
settings_set_variant(VariantSetting_DC, current_dc);
}
QDialog::accept();

View File

@ -270,7 +270,7 @@ void console_object_create(ConsoleWidget *console, const QList<AdObject> &object
return filter_containers.contains(object_class);
}();
const bool show_non_containers_ON = g_settings->get_bool(BoolSetting_ShowNonContainersInConsoleTree);
const bool show_non_containers_ON = settings_get_bool(BoolSetting_ShowNonContainersInConsoleTree);
return (is_container || show_non_containers_ON);
}();
@ -377,7 +377,7 @@ void console_object_fetch(ConsoleWidget *console, const QString &current_filter,
// NOTE: do an extra search before real search for
// objects that should be visible in dev mode
const bool dev_mode = g_settings->get_bool(BoolSetting_DevMode);
const bool dev_mode = settings_get_bool(BoolSetting_DevMode);
if (dev_mode) {
AdInterface ad;
if (ad_connected(ad)) {

View File

@ -175,8 +175,8 @@ void console_query_tree_init(ConsoleWidget *console) {
query_tree_head->setDragEnabled(false);
// Add rest of tree
const QHash<QString, QVariant> folder_list = g_settings->get_variant(VariantSetting_QueryFolders).toHash();
const QHash<QString, QVariant> item_list = g_settings->get_variant(VariantSetting_QueryItems).toHash();
const QHash<QString, QVariant> folder_list = settings_get_variant(VariantSetting_QueryFolders).toHash();
const QHash<QString, QVariant> item_list = settings_get_variant(VariantSetting_QueryItems).toHash();
QStack<QPersistentModelIndex> folder_stack;
folder_stack.append(query_tree_head->index());
@ -274,8 +274,8 @@ void console_query_tree_save(ConsoleWidget *console) {
const QVariant folder_variant = QVariant(folder_list);
const QVariant item_variant = QVariant(item_list);
g_settings->set_variant(VariantSetting_QueryFolders, folder_variant);
g_settings->set_variant(VariantSetting_QueryItems, item_variant);
settings_set_variant(VariantSetting_QueryFolders, folder_variant);
settings_set_variant(VariantSetting_QueryItems, item_variant);
}
bool console_query_or_folder_name_is_good(ConsoleWidget *console, const QString &name, const QModelIndex &parent_index, QWidget *parent_widget, const QModelIndex &current_index) {

View File

@ -118,7 +118,7 @@ CreateObjectDialog::CreateObjectDialog(const QString &parent_dn_arg, const QStri
const QString first_name = first_name_edit->get_input();
const QString last_name = last_name_edit->get_input();
const bool last_name_first = g_settings->get_bool(BoolSetting_LastNameBeforeFirstName);
const bool last_name_first = settings_get_bool(BoolSetting_LastNameBeforeFirstName);
if (!first_name.isEmpty() && !last_name.isEmpty()) {
if (last_name_first) {
return last_name + " " + first_name;

View File

@ -89,7 +89,7 @@ FilterDialog::FilterDialog(QWidget *parent)
layout->addWidget(radio_buttons_frame);
layout->addWidget(button_box);
g_settings->setup_dialog_geometry(VariantSetting_FilterDialogGeometry, this);
settings_setup_dialog_geometry(VariantSetting_FilterDialogGeometry, this);
button_state_name_map = {
{"ALL_BUTTON_STATE", all_button},
@ -97,6 +97,18 @@ FilterDialog::FilterDialog(QWidget *parent)
{"CUSTOM_BUTTON_STATE", custom_button},
};
const QHash<QString, QVariant> state = settings_get_variant(VariantSetting_FilterDialogState).toHash();
filter_widget->restore_state(state[FILTER_WIDGET_STATE]);
filter_classes_widget->restore_state(state[FILTER_CLASSES_STATE]);
for (const QString &state_name : button_state_name_map.keys()) {
QRadioButton *button = button_state_name_map[state_name];
const QVariant button_state = state[state_name];
button->setChecked(button_state.toBool());
}
connect(
button_box, &QDialogButtonBox::accepted,
this, &QDialog::accept);
@ -119,7 +131,7 @@ bool FilterDialog::filtering_ON() const {
return !all_button->isChecked();
}
QVariant FilterDialog::save_state() const {
FilterDialog::~FilterDialog() {
QHash<QString, QVariant> state;
state[FILTER_WIDGET_STATE] = filter_widget->save_state();
@ -131,21 +143,7 @@ QVariant FilterDialog::save_state() const {
state[state_name] = button->isChecked();
}
return QVariant(state);
}
void FilterDialog::restore_state(const QVariant &state_variant) {
const QHash<QString, QVariant> state = state_variant.toHash();
filter_widget->restore_state(state[FILTER_WIDGET_STATE]);
filter_classes_widget->restore_state(state[FILTER_CLASSES_STATE]);
for (const QString &state_name : button_state_name_map.keys()) {
QRadioButton *button = button_state_name_map[state_name];
const QVariant button_state = state[state_name];
button->setChecked(button_state.toBool());
}
settings_set_variant(VariantSetting_FilterDialogState, state);
}
QString FilterDialog::get_filter() const {

View File

@ -40,13 +40,11 @@ class FilterDialog final : public QDialog {
public:
FilterDialog(QWidget *parent);
~FilterDialog();
QString get_filter() const;
bool filtering_ON() const;
QVariant save_state() const;
void restore_state(const QVariant &state);
private:
FilterCustomDialog *custom_dialog;
QRadioButton *all_button;

View File

@ -49,5 +49,5 @@ FindObjectDialog::FindObjectDialog(const QList<QString> classes, const QString d
find_widget->find_results->add_actions_to_action_menu(action_menu);
find_widget->find_results->add_actions_to_view_menu(view_menu);
g_settings->setup_dialog_geometry(VariantSetting_FindObjectDialogGeometry, this);
settings_setup_dialog_geometry(VariantSetting_FindObjectDialogGeometry, this);
}

View File

@ -71,7 +71,7 @@ FindResults::FindResults()
customize_columns_action = new QAction(tr("&Customize columns"), this);
const QVariant view_state = g_settings->get_variant(VariantSetting_FindResultsViewState);
const QVariant view_state = settings_get_variant(VariantSetting_FindResultsViewState);
view->restore_state(view_state, console_object_default_columns());
connect(
@ -121,7 +121,7 @@ FindResults::FindResults()
FindResults::~FindResults() {
const QVariant view_state = view->save_state();
g_settings->set_variant(VariantSetting_FindResultsViewState, view_state);
settings_set_variant(VariantSetting_FindResultsViewState, view_state);
}
void FindResults::add_actions_to_action_menu(QMenu *menu) {

View File

@ -21,11 +21,9 @@
#include "globals.h"
#include "adldap.h"
#include "settings.h"
#include "status.h"
AdConfig *g_adconfig = new AdConfig();
Settings *g_settings = new Settings();
// NOTE: status has to be in a function because it creates a
// widget so needs to be created after app is created

View File

@ -22,11 +22,9 @@
#define GLOBALS_H
class AdConfig;
class Settings;
class Status;
extern AdConfig *g_adconfig;
extern Settings *g_settings;
Status *g_status();
#endif /* GLOBALS_H */

View File

@ -45,7 +45,7 @@ int main(int argc, char **argv) {
app.setOrganizationName(ADMC_ORGANIZATION);
app.setOrganizationDomain(ADMC_ORGANIZATION_DOMAIN);
const QLocale saved_locale = g_settings->get_variant(VariantSetting_Locale).toLocale();
const QLocale saved_locale = settings_get_variant(VariantSetting_Locale).toLocale();
QTranslator translator;
const bool loaded_admc_translation = translator.load(saved_locale, "admc", "_", ":/admc");

View File

@ -41,8 +41,6 @@
MainWindow::MainWindow()
: QMainWindow() {
central_widget = nullptr;
setStatusBar(g_status()->status_bar());
message_log_dock = new QDockWidget();
@ -56,13 +54,13 @@ MainWindow::MainWindow()
setup_menubar();
const bool restored_geometry = g_settings->restore_geometry(VariantSetting_MainWindowGeometry, this);
const bool restored_geometry = settings_restore_geometry(VariantSetting_MainWindowGeometry, this);
if (!restored_geometry) {
resize(1024, 768);
}
if (g_settings->contains_variant(VariantSetting_MainWindowState)) {
const QByteArray state = g_settings->get_variant(VariantSetting_MainWindowState).toByteArray();
const QByteArray state = settings_get_variant(VariantSetting_MainWindowState).toByteArray();
if (!state.isEmpty()) {
restoreState(state);
} else {
message_log_dock->hide();
@ -72,14 +70,11 @@ MainWindow::MainWindow()
}
void MainWindow::closeEvent(QCloseEvent *event) {
g_settings->save_geometry(VariantSetting_MainWindowGeometry, this);
const QByteArray geometry = saveGeometry();
settings_set_variant(VariantSetting_MainWindowGeometry, geometry);
const QByteArray state = saveState();
g_settings->set_variant(VariantSetting_MainWindowState, state);
if (central_widget != nullptr) {
central_widget->save_state();
}
settings_set_variant(VariantSetting_MainWindowState, state);
QMainWindow::closeEvent(event);
}
@ -101,13 +96,10 @@ void MainWindow::setup_menubar() {
auto manual_action = new QAction(tr("&Manual"), this);
auto about_action = new QAction(tr("&About ADMC"), this);
auto advanced_features_action = new QAction(tr("&Advanced Features"), this);
auto confirm_actions_action = new QAction(tr("&Confirm actions"), this);
auto last_before_first_name_action = new QAction(tr("&Put last name before first name when creating users"), this);
auto log_searches_action = new QAction(tr("Log searches"), this);
auto timestamp_log_action = new QAction(tr("Timestamps in message log"), this);
auto toggle_console_tree_action = new QAction(tr("Console Tree"), this);
auto toggle_description_bar_action = new QAction(tr("Description Bar"), this);
auto confirm_actions_action = settings_make_and_connect_action(BoolSetting_ConfirmActions, tr("&Confirm actions"), this);
auto last_before_first_name_action = settings_make_and_connect_action(BoolSetting_LastNameBeforeFirstName, tr("&Put last name before first name when creating users"), this);
auto log_searches_action = settings_make_and_connect_action(BoolSetting_LogSearches, tr("Log searches"), this);
auto timestamp_log_action = settings_make_and_connect_action(BoolSetting_TimestampLog, tr("Timestamps in message log"), this);
const QList<QLocale::Language> language_list = {
QLocale::English,
@ -135,7 +127,7 @@ void MainWindow::setup_menubar() {
language_group->addAction(action);
const bool is_checked = [=]() {
const QLocale current_locale = g_settings->get_variant(VariantSetting_Locale).toLocale();
const QLocale current_locale = settings_get_variant(VariantSetting_Locale).toLocale();
return (current_locale == locale);
}();
@ -157,7 +149,7 @@ void MainWindow::setup_menubar() {
action_menu = menubar->addMenu(tr("&Action"));
navigation_menu = menubar->addMenu(tr("&Navigation"));
view_menu = menubar->addMenu(tr("&View"));
auto preferences_menu = menubar->addMenu(tr("&Preferences"));
preferences_menu = menubar->addMenu(tr("&Preferences"));
auto language_menu = new QMenu(tr("&Language"));
auto help_menu = menubar->addMenu(tr("&Help"));
@ -167,7 +159,6 @@ void MainWindow::setup_menubar() {
file_menu->addAction(connect_action);
file_menu->addAction(quit_action);
preferences_menu->addAction(advanced_features_action);
preferences_menu->addAction(confirm_actions_action);
preferences_menu->addAction(last_before_first_name_action);
preferences_menu->addAction(log_searches_action);
@ -175,8 +166,6 @@ void MainWindow::setup_menubar() {
preferences_menu->addMenu(language_menu);
preferences_menu->addSeparator();
preferences_menu->addAction(message_log_dock->toggleViewAction());
preferences_menu->addAction(toggle_console_tree_action);
preferences_menu->addAction(toggle_description_bar_action);
for (const auto language : language_list) {
QAction *language_action = language_actions[language];
@ -202,13 +191,6 @@ void MainWindow::setup_menubar() {
connect(
about_action, &QAction::triggered,
about_dialog, &QDialog::open);
g_settings->connect_action_to_bool_setting(advanced_features_action, BoolSetting_AdvancedFeatures);
g_settings->connect_action_to_bool_setting(confirm_actions_action, BoolSetting_ConfirmActions);
g_settings->connect_action_to_bool_setting(last_before_first_name_action, BoolSetting_LastNameBeforeFirstName);
g_settings->connect_action_to_bool_setting(log_searches_action, BoolSetting_LogSearches);
g_settings->connect_action_to_bool_setting(timestamp_log_action, BoolSetting_TimestampLog);
g_settings->connect_action_to_bool_setting(toggle_console_tree_action, BoolSetting_ShowConsoleTree);
g_settings->connect_action_to_bool_setting(toggle_description_bar_action, BoolSetting_ShowResultsHeader);
for (const auto language : language_actions.keys()) {
QAction *action = language_actions[language];
@ -217,7 +199,7 @@ void MainWindow::setup_menubar() {
action, &QAction::toggled,
[this, language](bool checked) {
if (checked) {
g_settings->set_variant(VariantSetting_Locale, QLocale(language));
settings_set_variant(VariantSetting_Locale, QLocale(language));
message_box_information(this, tr("Info"), tr("Restart the app to switch to the selected language."));
}
@ -225,19 +207,19 @@ void MainWindow::setup_menubar() {
}
connect(
g_settings->get_bool_signal(BoolSetting_LogSearches), &BoolSettingSignal::changed,
log_searches_action, &QAction::toggled,
this, &MainWindow::on_log_searches_changed);
on_log_searches_changed();
}
void MainWindow::connect_to_server() {
const QString saved_dc = g_settings->get_variant(VariantSetting_DC).toString();
const QString saved_dc = settings_get_variant(VariantSetting_DC).toString();
AdInterface::set_dc(saved_dc);
AdInterface ad;
if (ad_connected(ad)) {
// TODO: check for load failure
const QLocale locale = g_settings->get_variant(VariantSetting_Locale).toLocale();
const QLocale locale = settings_get_variant(VariantSetting_Locale).toLocale();
g_adconfig->load(ad, locale);
qDebug() << "domain =" << g_adconfig->domain();
@ -246,20 +228,17 @@ void MainWindow::connect_to_server() {
g_status()->display_ad_messages(ad, this);
central_widget = new CentralWidget(ad);
auto central_widget = new CentralWidget(ad);
setCentralWidget(central_widget);
central_widget->add_actions_to_action_menu(action_menu);
central_widget->add_actions_to_navigation_menu(navigation_menu);
central_widget->add_actions_to_view_menu(view_menu);
central_widget->add_actions_to_menus(action_menu, navigation_menu, view_menu, preferences_menu);
central_widget->setEnabled(true);
connect_action->setEnabled(false);
}
}
void MainWindow::on_log_searches_changed() {
const bool log_searches_ON = g_settings->get_bool(BoolSetting_LogSearches);
const bool log_searches_ON = settings_get_bool(BoolSetting_LogSearches);
AdInterface::set_log_searches(log_searches_ON);
}

View File

@ -24,7 +24,6 @@
#include <QMainWindow>
class QAction;
class CentralWidget;
class QDockWidget;
class QMenu;
@ -39,12 +38,12 @@ protected:
private:
QAction *connect_action;
CentralWidget *central_widget;
QDockWidget *message_log_dock;
QMenu *action_menu;
QMenu *navigation_menu;
QMenu *view_menu;
QMenu *preferences_menu;
void setup_menubar();
void connect_to_server();

View File

@ -80,7 +80,7 @@ ObjectMultiPropertiesDialog::ObjectMultiPropertiesDialog(const QList<QString> &t
add_tab(new OrganizationMultiTab(), tr("Organization"));
}
g_settings->setup_dialog_geometry(VariantSetting_ObjectMultiDialogGeometry, this);
settings_setup_dialog_geometry(VariantSetting_ObjectMultiDialogGeometry, this);
for (PropertiesMultiTab *tab : tab_list) {
connect(

View File

@ -29,6 +29,7 @@
#include "gplink.h"
#include "status.h"
#include "utils.h"
#include "settings.h"
#include <QAction>
#include <QHeaderView>
@ -97,6 +98,14 @@ PolicyResultsWidget::PolicyResultsWidget() {
layout->setSpacing(0);
layout->addWidget(view);
const QVariant state = settings_get_variant(VariantSetting_PolicyResultsState);
view->restore_state(state, {
PolicyResultsColumn_Name,
PolicyResultsColumn_Enforced,
PolicyResultsColumn_Disabled,
PolicyResultsColumn_Path,
});
connect(
model, &QStandardItemModel::itemChanged,
this, &PolicyResultsWidget::on_item_changed);
@ -108,19 +117,9 @@ PolicyResultsWidget::PolicyResultsWidget() {
this, &PolicyResultsWidget::delete_link);
}
QVariant PolicyResultsWidget::save_state() {
const QVariant view_state = view->save_state();
return view_state;
}
void PolicyResultsWidget::restore_state(const QVariant &state) {
view->restore_state(state, {
PolicyResultsColumn_Name,
PolicyResultsColumn_Enforced,
PolicyResultsColumn_Disabled,
PolicyResultsColumn_Path,
});
PolicyResultsWidget::~PolicyResultsWidget() {
const QVariant state = view->save_state();
settings_set_variant(VariantSetting_PolicyResultsState, state);
}
void PolicyResultsWidget::update(const QModelIndex &index) {

View File

@ -37,9 +37,7 @@ class PolicyResultsWidget final : public QWidget {
public:
PolicyResultsWidget();
QVariant save_state();
void restore_state(const QVariant &state);
~PolicyResultsWidget();
// Loads links for this policy. Nothing is done if given
// index is not a policy.

View File

@ -154,7 +154,7 @@ PropertiesDialog::PropertiesDialog(const QString &target_arg)
add_tab(new GeneralTab(object), tr("General"));
const bool advanced_view_ON = g_settings->get_bool(BoolSetting_AdvancedFeatures);
const bool advanced_view_ON = settings_get_bool(BoolSetting_AdvancedFeatures);
if (advanced_view_ON) {
add_tab(new ObjectTab(), tr("Object"));
@ -213,7 +213,7 @@ PropertiesDialog::PropertiesDialog(const QString &target_arg)
reset_internal(ad);
}
g_settings->setup_dialog_geometry(VariantSetting_PropertiesDialogGeometry, this);
settings_setup_dialog_geometry(VariantSetting_PropertiesDialogGeometry, this);
connect(
ok_button, &QPushButton::clicked,

View File

@ -93,7 +93,7 @@ SelectContainerDialog::SelectContainerDialog(QWidget *parent)
// NOTE: geometry is shared with the subclass
// MoveObjectDialog but that is intended.
g_settings->setup_dialog_geometry(VariantSetting_SelectContainerDialogGeometry, this);
settings_setup_dialog_geometry(VariantSetting_SelectContainerDialogGeometry, this);
connect(
button_box, &QDialogButtonBox::accepted,

View File

@ -122,9 +122,9 @@ SelectObjectDialog::SelectObjectDialog(const QList<QString> class_list_arg, cons
layout->addLayout(object_view_layout);
layout->addWidget(button_box);
g_settings->setup_dialog_geometry(VariantSetting_SelectObjectDialogGeometry, this);
settings_setup_dialog_geometry(VariantSetting_SelectObjectDialogGeometry, this);
g_settings->restore_header_state(VariantSetting_SelectObjectHeaderState, view->header());
settings_restore_header_state(VariantSetting_SelectObjectHeaderState, view->header());
connect(
add_button, &QPushButton::clicked,
@ -144,7 +144,7 @@ SelectObjectDialog::SelectObjectDialog(const QList<QString> class_list_arg, cons
}
SelectObjectDialog::~SelectObjectDialog() {
g_settings->save_header_state(VariantSetting_SelectObjectHeaderState, view->header());
settings_save_header_state(VariantSetting_SelectObjectHeaderState, view->header());
}
QList<QString> SelectObjectDialog::get_selected() const {

View File

@ -23,54 +23,46 @@
#include "config.h"
#include <QAction>
#include <QCheckBox>
#include <QHeaderView>
#include <QLocale>
#include <QDialog>
#include <QSettings>
bool bool_default_value(const BoolSetting setting);
QString bool_to_string(const BoolSetting setting);
QString variant_to_string(const VariantSetting setting);
Settings::Settings()
: qsettings(ADMC_ORGANIZATION, ADMC_APPLICATION_NAME) {
}
bool settings_get_bool(const BoolSetting setting) {
QSettings settings;
const BoolSettingSignal *Settings::get_bool_signal(const BoolSetting setting) const {
return &bools[setting];
}
bool Settings::get_bool(const BoolSetting setting) const {
const QString setting_str = bool_to_string(setting);
const bool default_value = bool_default_value(setting);
const bool value = qsettings.value(setting_str, default_value).toBool();
const bool value = settings.value(setting_str, default_value).toBool();
return value;
}
void Settings::set_bool(const BoolSetting setting, const bool value) {
void settings_set_bool(const BoolSetting setting, const bool value) {
QSettings settings;
const QString name = bool_to_string(setting);
qsettings.setValue(name, value);
settings.setValue(name, value);
}
void Settings::save_geometry(const VariantSetting setting, QWidget *widget) {
const QByteArray geometry = widget->saveGeometry();
set_variant(setting, geometry);
}
void Settings::setup_dialog_geometry(const VariantSetting setting, QDialog *dialog) {
restore_geometry(setting, dialog);
void settings_setup_dialog_geometry(const VariantSetting setting, QDialog *dialog) {
settings_restore_geometry(setting, dialog);
QDialog::connect(
dialog, &QDialog::finished,
[=]() {
save_geometry(setting, dialog);
const QByteArray geometry = dialog->saveGeometry();
settings_set_variant(setting, geometry);
});
}
bool Settings::restore_geometry(const VariantSetting setting, QWidget *widget) {
if (contains_variant(setting)) {
const QByteArray geometry = get_variant(setting).toByteArray();
bool settings_restore_geometry(const VariantSetting setting, QWidget *widget) {
const QByteArray geometry = settings_get_variant(setting).toByteArray();
if (!geometry.isEmpty()) {
widget->restoreGeometry(geometry);
return true;
@ -79,14 +71,14 @@ bool Settings::restore_geometry(const VariantSetting setting, QWidget *widget) {
}
}
void Settings::save_header_state(const VariantSetting setting, QHeaderView *header) {
void settings_save_header_state(const VariantSetting setting, QHeaderView *header) {
const QByteArray state = header->saveState();
set_variant(setting, state);
settings_set_variant(setting, state);
}
bool Settings::restore_header_state(const VariantSetting setting, QHeaderView *header) {
if (contains_variant(setting)) {
const QByteArray state = get_variant(setting).toByteArray();
bool settings_restore_header_state(const VariantSetting setting, QHeaderView *header) {
const QByteArray state = settings_get_variant(setting).toByteArray();
if (!state.isEmpty()) {
header->restoreState(state);
return true;
@ -95,69 +87,59 @@ bool Settings::restore_header_state(const VariantSetting setting, QHeaderView *h
}
}
QVariant Settings::get_variant(const VariantSetting setting) const {
QVariant settings_get_variant(const VariantSetting setting, const QVariant &default_value) {
QSettings settings;
const QString name = variant_to_string(setting);
const QVariant value = qsettings.value(name);
const QVariant value = settings.value(name, default_value);
return value;
}
void Settings::set_variant(const VariantSetting setting, const QVariant &value) {
void settings_set_variant(const VariantSetting setting, const QVariant &value) {
QSettings settings;
const QString name = variant_to_string(setting);
qsettings.setValue(name, value);
settings.setValue(name, value);
}
bool Settings::contains_variant(const VariantSetting setting) const {
const QString name = variant_to_string(setting);
return qsettings.contains(name);
}
void Settings::connect_action_to_bool_setting(QAction *action, const BoolSetting setting) {
void settings_connect_action_to_bool_setting(QAction *action, const BoolSetting setting) {
action->setCheckable(true);
// Init action state to saved value
const bool saved_value = get_bool(setting);
const bool saved_value = settings_get_bool(setting);
action->setChecked(saved_value);
// Update saved value when action is toggled
QObject::connect(
action, &QAction::toggled,
[this, setting](bool checked) {
set_bool(setting, checked);
emit bools[setting].changed();
[setting](bool checked) {
settings_set_bool(setting, checked);
});
}
void Settings::connect_checkbox_to_bool_setting(QCheckBox *check, const BoolSetting setting) {
QAction *settings_make_action(const BoolSetting setting, const QString &text, QObject *parent) {
auto action = new QAction(text, parent);
action->setCheckable(true);
// Init action state to saved value
const bool saved_value = get_bool(setting);
check->setChecked(saved_value);
const bool saved_value = settings_get_bool(setting);
action->setChecked(saved_value);
// Update saved value when checkbox is toggled
return action;
}
QAction *settings_make_and_connect_action(const BoolSetting setting, const QString &text, QObject *parent) {
auto action = settings_make_action(setting, text, parent);
// Update saved value when action is toggled
QObject::connect(
check, &QCheckBox::stateChanged,
[this, setting, check]() {
const bool checked = check->isChecked();
set_bool(setting, checked);
emit bools[setting].changed();
action, &QAction::toggled,
[setting](bool checked) {
settings_set_bool(setting, checked);
});
return action;
}
void Settings::connect_toggle_widget(QWidget *widget, const BoolSetting setting) {
const BoolSettingSignal *signal = get_bool_signal(setting);
auto on_changed = [=]() {
const bool visible = get_bool(setting);
widget->setVisible(visible);
};
QObject::connect(
signal, &BoolSettingSignal::changed,
on_changed);
on_changed();
}
// NOTE: DON'T define "default:" branch, want to be warned and forced to define a default value for all settings
bool bool_default_value(const BoolSetting setting) {
@ -179,14 +161,6 @@ bool bool_default_value(const BoolSetting setting) {
case BoolSetting_LogSearches: return false;
case BoolSetting_TimestampLog: return true;
case BoolSetting_AttributeFilterUnset: return true;
case BoolSetting_AttributeFilterReadOnly: return true;
case BoolSetting_AttributeFilterMandatory: return true;
case BoolSetting_AttributeFilterOptional: return true;
case BoolSetting_AttributeFilterSystemOnly: return true;
case BoolSetting_AttributeFilterConstructed: return true;
case BoolSetting_AttributeFilterBacklink: return true;
case BoolSetting_COUNT: break;
}
@ -194,7 +168,7 @@ bool bool_default_value(const BoolSetting setting) {
}
#define CASE_ENUM_TO_STRING(ENUM) \
case ENUM: return #ENUM
case ENUM: return #ENUM
// Convert enum to string literal via macro
// BoolSetting_Foo => "BoolSetting_Foo"
@ -210,13 +184,6 @@ QString bool_to_string(const BoolSetting setting) {
CASE_ENUM_TO_STRING(BoolSetting_LogSearches);
CASE_ENUM_TO_STRING(BoolSetting_TimestampLog);
CASE_ENUM_TO_STRING(BoolSetting_COUNT);
CASE_ENUM_TO_STRING(BoolSetting_AttributeFilterUnset);
CASE_ENUM_TO_STRING(BoolSetting_AttributeFilterReadOnly);
CASE_ENUM_TO_STRING(BoolSetting_AttributeFilterMandatory);
CASE_ENUM_TO_STRING(BoolSetting_AttributeFilterOptional);
CASE_ENUM_TO_STRING(BoolSetting_AttributeFilterSystemOnly);
CASE_ENUM_TO_STRING(BoolSetting_AttributeFilterConstructed);
CASE_ENUM_TO_STRING(BoolSetting_AttributeFilterBacklink);
}
return "";
}
@ -230,7 +197,7 @@ QString variant_to_string(const VariantSetting setting) {
CASE_ENUM_TO_STRING(VariantSetting_ResultsHeader);
CASE_ENUM_TO_STRING(VariantSetting_FindResultsHeader);
CASE_ENUM_TO_STRING(VariantSetting_AttributesTabHeaderState);
CASE_ENUM_TO_STRING(VariantSetting_AttributesTabFilter);
CASE_ENUM_TO_STRING(VariantSetting_AttributesTabFilterState);
CASE_ENUM_TO_STRING(VariantSetting_QueryFolders);
CASE_ENUM_TO_STRING(VariantSetting_QueryItems);
CASE_ENUM_TO_STRING(VariantSetting_PropertiesDialogGeometry);

View File

@ -22,27 +22,19 @@
#define SETTINGS_H
/**
* Provides access to settings via enums rather than plain
* strings. Settings are saved to file automatically when
* this object is destructed. Note that you shouldn't save
* settings in destructors that run close to app shutdown
* because they won't be saved to file. Instead use
* QMainWindow::closeEvent(). Settings of boolean type have
* BoolSettingSignal objects which emit changed() signal
* when setting is changed.
* Utility f-ns for saving and loading settings using
* QSettings.
*/
#include <QObject>
#include <QSettings>
#include <QVariant>
class QAction;
class QSettings;
class QVariant;
class QWidget;
class QCheckBox;
class QHeaderView;
class QDialog;
class QString;
class QObject;
enum VariantSetting {
VariantSetting_DC,
@ -52,7 +44,7 @@ enum VariantSetting {
VariantSetting_AttributesTabHeaderState,
VariantSetting_MainWindowGeometry,
VariantSetting_MainWindowState,
VariantSetting_AttributesTabFilter,
VariantSetting_AttributesTabFilterState,
VariantSetting_QueryFolders,
VariantSetting_QueryItems,
VariantSetting_PropertiesDialogGeometry,
@ -86,67 +78,40 @@ enum BoolSetting {
BoolSetting_LogSearches,
BoolSetting_TimestampLog,
BoolSetting_AttributeFilterUnset,
BoolSetting_AttributeFilterReadOnly,
BoolSetting_AttributeFilterMandatory,
BoolSetting_AttributeFilterOptional,
BoolSetting_AttributeFilterSystemOnly,
BoolSetting_AttributeFilterConstructed,
BoolSetting_AttributeFilterBacklink,
BoolSetting_COUNT,
};
class BoolSettingSignal final : public QObject {
Q_OBJECT
signals:
void changed();
};
QVariant settings_get_variant(const VariantSetting setting, const QVariant &default_value = QVariant());
void settings_set_variant(const VariantSetting setting, const QVariant &value);
class Settings {
// NOTE: returns default value if it's defined in
// settings.cpp
bool settings_get_bool(const BoolSetting setting);
void settings_set_bool(const BoolSetting setting, const bool value);
public:
Settings();
// Does two things. First it restores previously saved
// geometry, if it exists. Then it connects to dialogs
// finished() signal so that it's geometry is saved when
// dialog is finished.
void settings_setup_dialog_geometry(const VariantSetting setting, QDialog *dialog);
QVariant get_variant(const VariantSetting setting) const;
void set_variant(const VariantSetting setting, const QVariant &value);
bool contains_variant(const VariantSetting setting) const;
// NOTE: If setting is present, restore is performed,
// otherwise f-n does nothing and returns false. You
// should check for the return and perform default
// sizing in the false case.
bool settings_restore_geometry(const VariantSetting setting, QWidget *widget);
const BoolSettingSignal *get_bool_signal(const BoolSetting setting) const;
bool get_bool(const BoolSetting setting) const;
void set_bool(const BoolSetting setting, const bool value);
void settings_save_header_state(const VariantSetting setting, QHeaderView *header);
bool settings_restore_header_state(const VariantSetting setting, QHeaderView *header);
void save_geometry(const VariantSetting setting, QWidget *widget);
// Does two things. First it restores previously saved
// geometry, if it exists. Then it connects to dialogs
// finished() signal so that it's geometry is saved when
// dialog is finished.
void setup_dialog_geometry(const VariantSetting setting, QDialog *dialog);
// NOTE: If setting is present, restore is performed,
// otherwise f-n does nothing and returns false. You
// should check for the return and perform default
// sizing in the false case.
bool restore_geometry(const VariantSetting setting, QWidget *widget);
void save_header_state(const VariantSetting setting, QHeaderView *header);
bool restore_header_state(const VariantSetting setting, QHeaderView *header);
/**
* Connect action and bool setting so that toggling
* the action updates the setting value
* Action becomes checkable
*/
void connect_action_to_bool_setting(QAction *action, const BoolSetting setting);
void connect_checkbox_to_bool_setting(QCheckBox *check, const BoolSetting setting);
void connect_toggle_widget(QWidget *widget, const BoolSetting setting);
private:
QSettings qsettings;
BoolSettingSignal bools[BoolSetting_COUNT];
};
/**
* Make a checkable QAction that is connected to a bool
* setting. Action state will be initialized to the current
* setting value. The "connect" version of the f-n also
* connects the action for you so that when toggling the
* action modifies the setting.
*/
QAction *settings_make_action(const BoolSetting setting, const QString &text, QObject *parent);
QAction *settings_make_and_connect_action(const BoolSetting setting, const QString &text, QObject *parent);
#endif /* SETTINGS_H */

View File

@ -60,7 +60,7 @@ void Status::add_message(const QString &msg, const StatusType &type) {
const QString timestamped_msg = QString("%1 %2").arg(timestamp, msg);
const bool timestamps_ON = g_settings->get_bool(BoolSetting_TimestampLog);
const bool timestamps_ON = settings_get_bool(BoolSetting_TimestampLog);
const QColor color = [type]() {
switch (type) {

View File

@ -38,6 +38,7 @@
#include <QVBoxLayout>
#include <QMenu>
#include <QAction>
#include <QHeaderView>
enum AttributesColumn {
AttributesColumn_Name,
@ -57,13 +58,15 @@ AttributesTab::AttributesTab() {
{AttributesColumn_Type, tr("Type")},
});
auto filter_menu = new AttributesFilterMenu(this);
view = new QTreeView(this);
view->setEditTriggers(QAbstractItemView::NoEditTriggers);
view->setSelectionBehavior(QAbstractItemView::SelectRows);
view->setAllColumnsShowFocus(true);
view->setSortingEnabled(true);
proxy = new AttributesTabProxy(this);
proxy = new AttributesTabProxy(filter_menu, this);
proxy->setSourceModel(model);
view->setModel(proxy);
@ -77,27 +80,34 @@ AttributesTab::AttributesTab() {
buttons->addStretch();
buttons->addWidget(filter_button);
filter_button->setMenu(new AttributesFilterMenu(this));
filter_button->setMenu(filter_menu);
const auto layout = new QVBoxLayout();
setLayout(layout);
layout->addWidget(view);
layout->addLayout(buttons);
g_settings->restore_header_state(VariantSetting_AttributesTabHeaderState, view->header());
enable_widget_on_selection(edit_button, view);
settings_restore_header_state(VariantSetting_AttributesTabHeaderState, view->header());
const QHash<QString, QVariant> state = settings_get_variant(VariantSetting_AttributesTabHeaderState).toHash();
view->header()->restoreState(state["header"].toByteArray());
connect(
view, &QAbstractItemView::doubleClicked,
this, &AttributesTab::edit_attribute);
connect(
edit_button, &QAbstractButton::clicked,
this, &AttributesTab::edit_attribute);
connect(
filter_menu, &AttributesFilterMenu::filter_changed,
proxy, &AttributesTabProxy::invalidate);
}
AttributesTab::~AttributesTab() {
g_settings->save_header_state(VariantSetting_AttributesTabHeaderState, view->header());
settings_set_variant(VariantSetting_AttributesTabHeaderState, view->header()->saveState());
}
void AttributesTab::edit_attribute() {
@ -208,69 +218,96 @@ void AttributesTab::load_row(const QList<QStandardItem *> &row, const QString &a
AttributesFilterMenu::AttributesFilterMenu(QWidget *parent)
: QMenu(parent) {
auto add_filter_option = [&](const QString text, const BoolSetting setting) {
const QList<QVariant> state = settings_get_variant(VariantSetting_AttributesTabFilterState).toList();
auto add_filter_action = [&](const QString text, const AttributeFilter filter) {
QAction *action = addAction(text);
action->setText(text);
action->setObjectName(QString::number(setting));
action->setObjectName(QString::number(filter));
action->setCheckable(true);
g_settings->connect_action_to_bool_setting(action, setting);
const bool is_checked = [&]() {
if (filter < state.size()) {
return state[filter].toBool();
} else {
return true;
}
}();
action->setChecked(is_checked);
action_map.insert(setting, action);
action_map.insert(filter, action);
connect(
action, &QAction::toggled,
this, &AttributesFilterMenu::filter_changed);
};
add_filter_option(tr("Unset"), BoolSetting_AttributeFilterUnset);
add_filter_option(tr("Read-only"), BoolSetting_AttributeFilterReadOnly);
add_filter_action(tr("Unset"), AttributeFilter_Unset);
add_filter_action(tr("Read-only"), AttributeFilter_ReadOnly);
addSeparator();
add_filter_option(tr("Mandatory"), BoolSetting_AttributeFilterMandatory);
add_filter_option(tr("Optional"), BoolSetting_AttributeFilterOptional);
add_filter_action(tr("Mandatory"), AttributeFilter_Mandatory);
add_filter_action(tr("Optional"), AttributeFilter_Optional);
addSeparator();
add_filter_option(tr("System-only"), BoolSetting_AttributeFilterSystemOnly);
add_filter_option(tr("Constructed"), BoolSetting_AttributeFilterConstructed);
add_filter_option(tr("Backlink"), BoolSetting_AttributeFilterBacklink);
add_filter_action(tr("System-only"), AttributeFilter_SystemOnly);
add_filter_action(tr("Constructed"), AttributeFilter_Constructed);
add_filter_action(tr("Backlink"), AttributeFilter_Backlink);
const BoolSettingSignal *read_only_signal = g_settings->get_bool_signal(BoolSetting_AttributeFilterReadOnly);
connect(
read_only_signal, &BoolSettingSignal::changed,
action_map[AttributeFilter_ReadOnly], &QAction::toggled,
this, &AttributesFilterMenu::on_read_only_changed);
on_read_only_changed();
}
void AttributesFilterMenu::on_read_only_changed() {
const bool read_only_is_enabled = g_settings->get_bool(BoolSetting_AttributeFilterReadOnly);
AttributesFilterMenu::~AttributesFilterMenu() {
const QList<QVariant> state = [&]() {
QList<QVariant> out;
const QList<BoolSetting> read_only_sub_filters = {
BoolSetting_AttributeFilterSystemOnly,
BoolSetting_AttributeFilterConstructed,
BoolSetting_AttributeFilterBacklink,
for (int fitler_i = 0; fitler_i < AttributeFilter_COUNT; fitler_i++) {
const AttributeFilter filter = (AttributeFilter) fitler_i;
const QAction *action = action_map[filter];
const QVariant filter_state = QVariant(action->isChecked());
out.append(filter_state);
}
return out;
}();
settings_set_variant(VariantSetting_AttributesTabFilterState, state);
}
void AttributesFilterMenu::on_read_only_changed() {
const bool read_only_is_enabled = action_map[AttributeFilter_ReadOnly]->isChecked();
const QList<AttributeFilter> read_only_sub_filters = {
AttributeFilter_SystemOnly,
AttributeFilter_Constructed,
AttributeFilter_Backlink,
};
for (const BoolSetting &setting : read_only_sub_filters) {
action_map[setting]->setEnabled(read_only_is_enabled);
action_map[setting]->setChecked(read_only_is_enabled);
for (const AttributeFilter &filter : read_only_sub_filters) {
action_map[filter]->setEnabled(read_only_is_enabled);
// Turning off read only turns off the sub read only
// filters. Note that turning ON read only doesn't do
// the opposite.
if (!read_only_is_enabled) {
action_map[filter]->setChecked(false);
}
}
}
AttributesTabProxy::AttributesTabProxy(QObject *parent)
bool AttributesFilterMenu::filter_is_enabled(const AttributeFilter filter) const {
return action_map[filter]->isChecked();
}
AttributesTabProxy::AttributesTabProxy(AttributesFilterMenu *filter_menu_arg, QObject *parent)
: QSortFilterProxyModel(parent) {
const QList<BoolSetting> filter_setting_list = {
BoolSetting_AttributeFilterUnset,
BoolSetting_AttributeFilterReadOnly,
BoolSetting_AttributeFilterMandatory,
BoolSetting_AttributeFilterOptional,
BoolSetting_AttributeFilterSystemOnly,
BoolSetting_AttributeFilterConstructed,
BoolSetting_AttributeFilterBacklink,
};
for (const BoolSetting &setting : filter_setting_list) {
const BoolSettingSignal *signal = g_settings->get_bool_signal(setting);
connect(
signal, &BoolSettingSignal::changed,
this, &AttributesTabProxy::invalidate);
}
filter_menu = filter_menu_arg;
}
void AttributesTabProxy::load(const AdObject &object) {
@ -290,36 +327,36 @@ bool AttributesTabProxy::filterAcceptsRow(int source_row, const QModelIndex &sou
const bool mandatory = mandatory_attributes.contains(attribute);
const bool optional = optional_attributes.contains(attribute);
if (!g_settings->get_bool(BoolSetting_AttributeFilterUnset) && unset) {
if (!filter_menu->filter_is_enabled(AttributeFilter_Unset) && unset) {
return false;
}
if (!g_settings->get_bool(BoolSetting_AttributeFilterMandatory) && mandatory) {
if (!filter_menu->filter_is_enabled(AttributeFilter_Mandatory) && mandatory) {
return false;
}
if (!g_settings->get_bool(BoolSetting_AttributeFilterOptional) && optional) {
if (!filter_menu->filter_is_enabled(AttributeFilter_Optional) && optional) {
return false;
}
if (g_settings->get_bool(BoolSetting_AttributeFilterReadOnly) && system_only) {
if (filter_menu->filter_is_enabled(AttributeFilter_ReadOnly) && system_only) {
const bool constructed = g_adconfig->get_attribute_is_constructed(attribute);
const bool backlink = g_adconfig->get_attribute_is_backlink(attribute);
if (!g_settings->get_bool(BoolSetting_AttributeFilterSystemOnly) && !constructed && !backlink) {
if (!filter_menu->filter_is_enabled(AttributeFilter_SystemOnly) && !constructed && !backlink) {
return false;
}
if (!g_settings->get_bool(BoolSetting_AttributeFilterConstructed) && constructed) {
if (!filter_menu->filter_is_enabled(AttributeFilter_Constructed) && constructed) {
return false;
}
if (!g_settings->get_bool(BoolSetting_AttributeFilterBacklink) && backlink) {
if (!filter_menu->filter_is_enabled(AttributeFilter_Backlink) && backlink) {
return false;
}
}
if (!g_settings->get_bool(BoolSetting_AttributeFilterReadOnly) && system_only) {
if (!filter_menu->filter_is_enabled(AttributeFilter_ReadOnly) && system_only) {
return false;
}

View File

@ -28,14 +28,32 @@
#include <QSet>
#include <QHash>
enum AttributeFilter {
AttributeFilter_Unset,
AttributeFilter_ReadOnly,
AttributeFilter_Mandatory,
AttributeFilter_Optional,
AttributeFilter_SystemOnly,
AttributeFilter_Constructed,
AttributeFilter_Backlink,
AttributeFilter_COUNT,
};
class AttributesFilterMenu final : public QMenu {
Q_OBJECT
public:
AttributesFilterMenu(QWidget *parent);
~AttributesFilterMenu();
bool filter_is_enabled(const AttributeFilter filter) const;
signals:
void filter_changed();
private:
QHash<BoolSetting, QAction *> action_map;
QHash<AttributeFilter, QAction *> action_map;
void on_read_only_changed();
};
@ -43,11 +61,12 @@ private:
class AttributesTabProxy final : public QSortFilterProxyModel {
public:
AttributesTabProxy(QObject *parent);
AttributesTabProxy(AttributesFilterMenu *filter_menu, QObject *parent);
void load(const AdObject &object);
private:
AttributesFilterMenu *filter_menu;
QSet<QString> set_attributes;
QSet<QString> mandatory_attributes;
QSet<QString> optional_attributes;

View File

@ -62,11 +62,11 @@ GpoLinksTab::GpoLinksTab() {
PropertiesDialog::open_when_view_item_activated(view, GpoLinksRole_DN);
g_settings->restore_header_state(VariantSetting_GpoLinksTabHeaderState, view->header());
settings_restore_header_state(VariantSetting_GpoLinksTabHeaderState, view->header());
}
GpoLinksTab::~GpoLinksTab() {
g_settings->save_header_state(VariantSetting_GpoLinksTabHeaderState, view->header());
settings_save_header_state(VariantSetting_GpoLinksTabHeaderState, view->header());
}
void GpoLinksTab::load(AdInterface &ad, const AdObject &object) {

View File

@ -94,7 +94,7 @@ GroupPolicyTab::GroupPolicyTab() {
layout->addLayout(button_layout);
layout->addLayout(edits_layout);
g_settings->restore_header_state(VariantSetting_GroupPolicyTabHeaderState, view->header());
settings_restore_header_state(VariantSetting_GroupPolicyTabHeaderState, view->header());
enable_widget_on_selection(remove_button, view);
@ -113,7 +113,7 @@ GroupPolicyTab::GroupPolicyTab() {
}
GroupPolicyTab::~GroupPolicyTab() {
g_settings->save_header_state(VariantSetting_GroupPolicyTabHeaderState, view->header());
settings_save_header_state(VariantSetting_GroupPolicyTabHeaderState, view->header());
}
void GroupPolicyTab::load(AdInterface &ad, const AdObject &object) {

View File

@ -105,7 +105,7 @@ MembershipTab::MembershipTab(const MembershipTabType type_arg) {
layout->addWidget(primary_group_label);
layout->addLayout(button_layout);
g_settings->restore_header_state(VariantSetting_MembershipTabHeaderState, view->header());
settings_restore_header_state(VariantSetting_MembershipTabHeaderState, view->header());
enable_widget_on_selection(remove_button, view);
enable_widget_on_selection(properties_button, view);
@ -133,7 +133,7 @@ MembershipTab::MembershipTab(const MembershipTabType type_arg) {
}
MembershipTab::~MembershipTab() {
g_settings->save_header_state(VariantSetting_MembershipTabHeaderState, view->header());
settings_save_header_state(VariantSetting_MembershipTabHeaderState, view->header());
}
void MembershipTab::load(AdInterface &ad, const AdObject &object) {

View File

@ -78,11 +78,11 @@ OrganizationTab::OrganizationTab() {
layout->addRow(reports_label);
layout->addRow(reports_view);
g_settings->restore_header_state(VariantSetting_OrganizationTabHeaderState, reports_view->header());
settings_restore_header_state(VariantSetting_OrganizationTabHeaderState, reports_view->header());
}
OrganizationTab::~OrganizationTab() {
g_settings->save_header_state(VariantSetting_OrganizationTabHeaderState, reports_view->header());
settings_save_header_state(VariantSetting_OrganizationTabHeaderState, reports_view->header());
}
void OrganizationTab::load(AdInterface &ad, const AdObject &object) {

View File

@ -154,7 +154,7 @@ SecurityTab::SecurityTab() {
layout->addWidget(trustee_label);
layout->addWidget(ace_view);
g_settings->restore_header_state(VariantSetting_SecurityTabHeaderState, ace_view->header());
settings_restore_header_state(VariantSetting_SecurityTabHeaderState, ace_view->header());
connect(
trustee_view->selectionModel(), &QItemSelectionModel::currentChanged,
@ -174,7 +174,7 @@ SecurityTab::SecurityTab() {
}
SecurityTab::~SecurityTab() {
g_settings->save_header_state(VariantSetting_SecurityTabHeaderState, ace_view->header());
settings_save_header_state(VariantSetting_SecurityTabHeaderState, ace_view->header());
}
void SecurityTab::load(AdInterface &ad, const AdObject &object) {

View File

@ -78,22 +78,6 @@ void set_horizontal_header_labels_from_map(QStandardItemModel *model, const QMap
}
}
void show_only_in_dev_mode(QWidget *widget) {
const BoolSettingSignal *dev_mode_signal = g_settings->get_bool_signal(BoolSetting_DevMode);
const auto do_it = [widget]() {
const bool dev_mode = g_settings->get_bool(BoolSetting_DevMode);
widget->setVisible(dev_mode);
};
do_it();
QObject::connect(
dev_mode_signal, &BoolSettingSignal::changed,
[do_it]() {
do_it();
});
}
void set_line_edit_to_numbers_only(QLineEdit *edit) {
edit->setValidator(new QRegExpValidator(QRegExp("[0-9]*"), edit));
}
@ -121,7 +105,7 @@ void hide_busy_indicator() {
}
bool confirmation_dialog(const QString &text, QWidget *parent) {
const bool confirm_actions = g_settings->get_bool(BoolSetting_ConfirmActions);
const bool confirm_actions = settings_get_bool(BoolSetting_ConfirmActions);
if (!confirm_actions) {
return true;
}
@ -225,7 +209,7 @@ QList<QPersistentModelIndex> persistent_index_list(const QList<QModelIndex> &ind
// Hide advanced view only" objects if advanced view setting
// is off
void advanced_features_filter(QString &filter) {
const bool advanced_features_OFF = !g_settings->get_bool(BoolSetting_AdvancedFeatures);
const bool advanced_features_OFF = !settings_get_bool(BoolSetting_AdvancedFeatures);
if (advanced_features_OFF) {
const QString advanced_features = filter_CONDITION(Condition_NotEquals, ATTRIBUTE_SHOW_IN_ADVANCED_VIEW_ONLY, LDAP_BOOL_TRUE);
filter = filter_AND({filter, advanced_features});
@ -235,7 +219,7 @@ void advanced_features_filter(QString &filter) {
// OR filter with some dev mode object classes, so that they
// show up no matter what when dev mode is on
void dev_mode_filter(QString &filter) {
const bool dev_mode = g_settings->get_bool(BoolSetting_DevMode);
const bool dev_mode = settings_get_bool(BoolSetting_DevMode);
if (!dev_mode) {
return;
}
@ -259,7 +243,7 @@ void dev_mode_filter(QString &filter) {
// they don't show up in regular searches. Have to use
// search_object() and manually add them to search results.
void dev_mode_search_results(QHash<QString, AdObject> &results, AdInterface &ad, const QString &base) {
const bool dev_mode = g_settings->get_bool(BoolSetting_DevMode);
const bool dev_mode = settings_get_bool(BoolSetting_DevMode);
if (!dev_mode) {
return;
}

View File

@ -59,8 +59,6 @@ void exec_menu_from_view(QMenu *menu, const QAbstractItemView *view, const QPoin
// Columns not in the map get empty labels
void set_horizontal_header_labels_from_map(QStandardItemModel *model, const QMap<int, QString> &labels_map);
void show_only_in_dev_mode(QWidget *widget);
// Prohibits leading zeroes
void set_line_edit_to_numbers_only(QLineEdit *edit);

View File

@ -31,16 +31,18 @@
#include <QTreeView>
#include <QVBoxLayout>
Q_DECLARE_METATYPE(AttributeFilter)
// NOTE: can't be set because order is important. Read only
// has to be set first to enable other filters.
const QList<BoolSetting> all_filters = {
BoolSetting_AttributeFilterUnset,
BoolSetting_AttributeFilterReadOnly,
BoolSetting_AttributeFilterMandatory,
BoolSetting_AttributeFilterOptional,
BoolSetting_AttributeFilterSystemOnly,
BoolSetting_AttributeFilterConstructed,
BoolSetting_AttributeFilterBacklink,
const QList<AttributeFilter> all_filters = {
AttributeFilter_Unset,
AttributeFilter_ReadOnly,
AttributeFilter_Mandatory,
AttributeFilter_Optional,
AttributeFilter_SystemOnly,
AttributeFilter_Constructed,
AttributeFilter_Backlink,
};
void ADMCTestAttributesTab::init() {
@ -103,46 +105,55 @@ void ADMCTestAttributesTab::load() {
check_value("distinguishedName", dn);
}
// Test filters by checking that affected attributes are
// visible/hidden when their filters are checked/unchecked
void ADMCTestAttributesTab::filter() {
auto test_filter = [&](const BoolSetting filter, const QString &attribute) {
auto check_filtering = [&](const bool should_be_visible) {
const QList<QStandardItem *> item_list = model->findItems(attribute);
QVERIFY2((item_list.size() == 1), qPrintable(QString("Failed to find attribute %1)").arg(attribute)));
void ADMCTestAttributesTab::filter_data() {
QTest::addColumn<AttributeFilter>("filter");
QTest::addColumn<QString>("attribute");
QStandardItem *item = item_list[0];
const QModelIndex index = item->index();
const QModelIndex proxy_index = proxy->mapFromSource(index);
const bool is_visible = proxy_index.isValid();
const bool correct_filtering = (is_visible == should_be_visible);
QVERIFY2(correct_filtering, qPrintable(QString("filter = %1, attribute = %2, is_visible = %3, should_be_visible = %4").arg(filter).arg(attribute).arg(is_visible).arg(should_be_visible)));
};
set_filter({filter}, true);
check_filtering(true);
set_filter({filter}, false);
check_filtering(false);
set_filter({filter}, true);
};
set_filter(all_filters, true);
test_filter(BoolSetting_AttributeFilterUnset, ATTRIBUTE_HOME_PHONE);
test_filter(BoolSetting_AttributeFilterReadOnly, ATTRIBUTE_OBJECT_GUID);
test_filter(BoolSetting_AttributeFilterSystemOnly, ATTRIBUTE_WHEN_CREATED);
test_filter(BoolSetting_AttributeFilterConstructed, "allowedAttributes");
test_filter(BoolSetting_AttributeFilterBacklink, ATTRIBUTE_MEMBER_OF);
test_filter(BoolSetting_AttributeFilterMandatory, "instanceType");
test_filter(BoolSetting_AttributeFilterOptional, ATTRIBUTE_COUNTRY_CODE);
QTest::newRow("unset") << AttributeFilter_Unset << ATTRIBUTE_HOME_PHONE;
QTest::newRow("read only") << AttributeFilter_ReadOnly << ATTRIBUTE_OBJECT_GUID;
QTest::newRow("system only") << AttributeFilter_SystemOnly << ATTRIBUTE_WHEN_CREATED;
QTest::newRow("constructed") << AttributeFilter_Constructed << "allowedAttributes";
QTest::newRow("backlink") << AttributeFilter_Backlink << ATTRIBUTE_MEMBER_OF;
QTest::newRow("mandatory") << AttributeFilter_Mandatory << "instanceType";
QTest::newRow("optional") << AttributeFilter_Optional << ATTRIBUTE_COUNTRY_CODE;
// NOTE: read only also needs to affect these read only
// attributes
test_filter(BoolSetting_AttributeFilterReadOnly, "allowedAttributes");
test_filter(BoolSetting_AttributeFilterReadOnly, ATTRIBUTE_WHEN_CREATED);
test_filter(BoolSetting_AttributeFilterReadOnly, ATTRIBUTE_MEMBER_OF);
QTest::newRow("read only allowed") << AttributeFilter_ReadOnly << "allowedAttributes";
QTest::newRow("read only when created") << AttributeFilter_ReadOnly << ATTRIBUTE_WHEN_CREATED;
QTest::newRow("read only member of") << AttributeFilter_ReadOnly << ATTRIBUTE_MEMBER_OF;
}
// Test filters by checking that affected attributes are
// visible/hidden when their filters are checked/unchecked
void ADMCTestAttributesTab::filter() {
QFETCH(AttributeFilter, filter);
QFETCH(QString, attribute);
auto check_filtering = [&](const bool should_be_visible) {
const QList<QStandardItem *> item_list = model->findItems(attribute);
QVERIFY2((item_list.size() == 1), qPrintable(QString("Failed to find attribute %1)").arg(attribute)));
QStandardItem *item = item_list[0];
const QModelIndex index = item->index();
const QModelIndex proxy_index = proxy->mapFromSource(index);
const bool is_visible = proxy_index.isValid();
const bool correct_filtering = (is_visible == should_be_visible);
QVERIFY2(correct_filtering, qPrintable(QString("filter = %1, attribute = %2, is_visible = %3, should_be_visible = %4").arg(filter).arg(attribute).arg(is_visible).arg(should_be_visible)));
};
// Disable(check) all filters (to filter nothing) and
// check that attribute is shown
set_filter(all_filters, true);
check_filtering(true);
// Enable(uncheck) filter and check that attribute is
// hidden
set_filter({filter}, false);
check_filtering(false);
// Reset after test is done
set_filter(all_filters, true);
}
@ -180,8 +191,8 @@ void ADMCTestAttributesTab::apply() {
QVERIFY(description_value == correct_value);
}
void ADMCTestAttributesTab::set_filter(const QList<BoolSetting> &filter_list, const bool state) {
for (const BoolSetting &filter : filter_list) {
void ADMCTestAttributesTab::set_filter(const QList<AttributeFilter> &filter_list, const bool state) {
for (const AttributeFilter &filter : filter_list) {
QAction *action = filter_menu->findChild<QAction *>(QString::number(filter));
QVERIFY(action != nullptr);
action->setChecked(state);

View File

@ -41,6 +41,7 @@ private slots:
void apply();
void load();
void filter_data();
void filter();
private:
@ -53,7 +54,7 @@ private:
QPushButton *edit_button;
QString dn;
void set_filter(const QList<BoolSetting> &filter_list, const bool state);
void set_filter(const QList<AttributeFilter> &filter_list, const bool state);
};
#endif /* ADMC_TEST_ATTRIBUTES_TAB_H */