[education/rkward] rkward/settings: Automate creating of dropbown boxes in settings
Thomas Friedrichsmeier
null at kde.org
Sat Mar 12 23:15:38 GMT 2022
Git commit 33be9e7c0b022b9cb84fa0d96e7ae464cfa10531 by Thomas Friedrichsmeier.
Committed on 12/03/2022 at 12:45.
Pushed by tfry into branch 'master'.
Automate creating of dropbown boxes in settings
M +25 -0 rkward/settings/rksettingsmodule.cpp
M +19 -0 rkward/settings/rksettingsmodule.h
M +13 -35 rkward/settings/rksettingsmodulecommandeditor.cpp
M +0 -4 rkward/settings/rksettingsmodulecommandeditor.h
M +3 -7 rkward/settings/rksettingsmoduleconsole.cpp
M +0 -1 rkward/settings/rksettingsmoduleconsole.h
M +6 -30 rkward/settings/rksettingsmoduler.cpp
M +0 -4 rkward/settings/rksettingsmoduler.h
https://invent.kde.org/education/rkward/commit/33be9e7c0b022b9cb84fa0d96e7ae464cfa10531
diff --git a/rkward/settings/rksettingsmodule.cpp b/rkward/settings/rksettingsmodule.cpp
index b615b23a..70808c94 100644
--- a/rkward/settings/rksettingsmodule.cpp
+++ b/rkward/settings/rksettingsmodule.cpp
@@ -17,9 +17,13 @@
#include "rksettingsmodule.h"
#include "../rkward.h"
+#include "../debug.h"
#include "rksettings.h"
#include <QCheckBox>
+#include <QComboBox>
+
+#include <functional>
//static
RCommandChain* RKSettingsModule::chain = 0;
@@ -53,6 +57,27 @@ template<typename TT, typename std::enable_if<std::is_same<TT, bool>::value>::ty
return ret;
}
+QComboBox* RKConfigBase::makeDropDownHelper(const LabelList &entries, RKSettingsModuleWidget* module, int initial, std::function<void(int)> setter) {
+ RK_TRACE(SETTINGS);
+
+ QComboBox *ret = new QComboBox();
+ int index = -1;
+ for (int i = 0; i < entries.size(); ++i) {
+ auto key = entries[i].key;
+ auto label = entries[i].label;
+ ret->addItem(label, key);
+ if (key == initial) index = i;
+ }
+ RK_ASSERT(index >= 0);
+ ret->setCurrentIndex(index);
+ QObject::connect(ret, QOverload<int>::of(&QComboBox::currentIndexChanged), [ret, setter, module]() {
+ module->change();
+ setter(ret->currentData().toInt());
+ });
+
+ return ret;
+}
+
void linkHelperDummy() {
RKConfigValue<bool>("", true).makeCheckbox(QString(), nullptr);
}
diff --git a/rkward/settings/rksettingsmodule.h b/rkward/settings/rksettingsmodule.h
index 40d5f7a0..5052d4e7 100644
--- a/rkward/settings/rksettingsmodule.h
+++ b/rkward/settings/rksettingsmodule.h
@@ -26,6 +26,7 @@ class KConfig;
class RKSettings;
class RCommandChain;
class QCheckBox;
+class QComboBox;
class RKSettingsModule;
class RKSettingsModuleWidget;
class RKSetupWizardItem;
@@ -47,10 +48,18 @@ public:
else loadConfig(cg);
};
const char *key() { return name; }
+
+ struct ValueLabel {
+ int key;
+ QString label;
+ };
+ typedef QList<ValueLabel> LabelList;
protected:
RKConfigBase(const char* name) : name(name) {};
virtual ~RKConfigBase() {};
const char* name;
+
+ static QComboBox* makeDropDownHelper(const LabelList &entries, RKSettingsModuleWidget* module, int initial, std::function<void(int)> setter);
};
/** A single value stored in the RKWard config file.
@@ -74,6 +83,16 @@ public:
/** Only for bool values: convenience function to create a fully connected checkbox for this option */
template<typename TT = T, typename std::enable_if<std::is_same<TT, bool>::value>::type* = nullptr> QCheckBox* makeCheckbox(const QString& label, RKSettingsModuleWidget* module);
+/** Currently only for boolean or int options: Make a dropdown selector (QComboBox). If bit_flag_mask is set, the selector operates on (part of) an OR-able set of flags, instead of
+ * plain values. */
+ QComboBox* makeDropDown(const LabelList &entries, RKSettingsModuleWidget* _module, int bit_flag_mask = 0) {
+ static_assert(std::is_same<STORAGE_T, int>::value || std::is_same<STORAGE_T, bool>::value, "makeDropDown can only be used for int or bool");
+ if (bit_flag_mask) {
+ return makeDropDownHelper(entries, _module, value & bit_flag_mask, [this, bit_flag_mask](int val){this->value = (T) ((this->value & ~bit_flag_mask) + val);});
+ } else {
+ return makeDropDownHelper(entries, _module, (std::is_same<STORAGE_T, bool>::value && value) ? 1 : (int) value, [this](int val){this->value = (T) val;});
+ }
+ }
private:
T value;
};
diff --git a/rkward/settings/rksettingsmodulecommandeditor.cpp b/rkward/settings/rksettingsmodulecommandeditor.cpp
index 14b4686a..02d38286 100644
--- a/rkward/settings/rksettingsmodulecommandeditor.cpp
+++ b/rkward/settings/rksettingsmodulecommandeditor.cpp
@@ -65,7 +65,7 @@ RKCodeCompletionSettingsWidget::RKCodeCompletionSettingsWidget(QWidget *parent,
auto_completion_min_chars_box = new RKSpinBox (auto_completion_enabled_box);
auto_completion_min_chars_box->setIntMode (1, INT_MAX, settings->auto_completion_min_chars);
connect (auto_completion_min_chars_box, static_cast<void (QSpinBox::*)(int)>(&QSpinBox::valueChanged), this, &RKCodeCompletionSettingsWidget::change);
- form_layout->addRow ("Minimum number of characters", auto_completion_min_chars_box);
+ form_layout->addRow (i18n("Minimum number of characters"), auto_completion_min_chars_box);
auto_completion_timeout_box = new RKSpinBox (auto_completion_enabled_box);
auto_completion_timeout_box->setIntMode (0, INT_MAX, settings->auto_completion_timeout);
@@ -81,38 +81,26 @@ RKCodeCompletionSettingsWidget::RKCodeCompletionSettingsWidget(QWidget *parent,
RKCommonFunctions::setTips(i18n("Note: Further shortcuts can be assigned, and by default, Ctlr+Space invokes completions, in addition to this. Further, pressing the Tab key, while completions are shown, performs partial completion (if possible), independent of this setting."), tabkey_invokes_completion_box);
form_layout->addRow(i18n("Tab key invokes code completion"), tabkey_invokes_completion_box);
- cursor_navigates_completions_box = new QComboBox(group);
- cursor_navigates_completions_box->addItem(i18n("Up/down cursor keys"));
- cursor_navigates_completions_box->addItem(i18n("Alt+Up/down cursor keys"));
- cursor_navigates_completions_box->setCurrentIndex(settings->cursor_navigates_completions ? 0 : 1);
+ auto cursor_navigates_completions_box = settings->cursor_navigates_completions.makeDropDown(RKConfigBase::LabelList(
+ {{1, i18n("Up/down cursor keys")}, {0, i18n("Alt+Up/down cursor keys")}}
+ ), this);
RKCommonFunctions::setTips (i18n ("If you wish to avoid ambiguity between navigation completion options and navigating the document, you can set the behavior such that completion items are navigate using Alt+up / Alt+down, instead of just the up/down cursor keys."), cursor_navigates_completions_box);
- connect (cursor_navigates_completions_box, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &RKCodeCompletionSettingsWidget::change);
form_layout->addRow (i18n ("Keyboard navigation of completion items"), cursor_navigates_completions_box);
if (show_common) {
- completion_list_member_operator_box = new QComboBox (group);
- completion_list_member_operator_box->addItem (i18n ("'$'-operator (list$member)"));
- completion_list_member_operator_box->addItem (i18n ("'[['-operator (list[[\"member\"]])"));
- completion_list_member_operator_box->setCurrentIndex ((settings->completion_options & RObject::DollarExpansion) ? 0 : 1);
- connect (completion_list_member_operator_box, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &RKCodeCompletionSettingsWidget::change);
+ auto completion_list_member_operator_box = settings->completion_options.makeDropDown(RKConfigBase::LabelList(
+ {{RObject::DollarExpansion, i18n("'$'-operator (list$member)")}, {0, i18n("'[['-operator (list[[\"member\"]])")}}
+ ), this, RObject::DollarExpansion);
form_layout->addRow (i18nc ("Note: list() and data.frame() are programming terms in R, and should not be translated, here", "Operator for access to members of list() and data.frame() objects"), completion_list_member_operator_box);
- completion_slot_operator_box = new QComboBox (group);
- completion_slot_operator_box->addItem (i18n ("'@'-operator (object at smember)"));
- completion_slot_operator_box->addItem (i18n ("'slot()'-function (slot(object, member))"));
- completion_slot_operator_box->setCurrentIndex ((settings->completion_options & RObject::ExplicitSlotsExpansion) ? 1 : 0);
- connect (completion_slot_operator_box, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &RKCodeCompletionSettingsWidget::change);
+ auto completion_slot_operator_box = settings->completion_options.makeDropDown(RKConfigBase::LabelList(
+ {{0, i18n("'@'-operator (object at member)")}, {RObject::ExplicitSlotsExpansion, i18n("'slot()'-function (slot(object, member))")}}
+ ), this, RObject::ExplicitSlotsExpansion);
form_layout->addRow (i18nc ("Note: S4-slot() is a programming term in R, and should not be translated, here", "Operator for access to S4-slot()s"), completion_slot_operator_box);
- completion_object_qualification_box = new QComboBox (group);
- completion_object_qualification_box->addItem (i18n ("For masked objects, only"));
- completion_object_qualification_box->addItem (i18n ("For objects outside of <i>.GlobalEnv</i>, only"));
- completion_object_qualification_box->addItem (i18n ("Always"));
- if (settings->completion_options & (RObject::IncludeEnvirIfNotGlobalEnv)) {
- if (settings->completion_options & (RObject::IncludeEnvirIfNotGlobalEnv)) completion_object_qualification_box->setCurrentIndex (2);
- else completion_object_qualification_box->setCurrentIndex (1);
- }
- connect (completion_object_qualification_box, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &RKCodeCompletionSettingsWidget::change);
+ auto completion_object_qualification_box = settings->completion_options.makeDropDown(RKConfigBase::LabelList(
+ {{RObject::IncludeEnvirIfMasked, i18n("For masked objects, only")}, {RObject::IncludeEnvirIfNotGlobalEnv, i18n("For objects outside of <i>.GlobalEnv</i>, only")}, {RObject::IncludeEnvirIfNotGlobalEnv | RObject::IncludeEnvirForGlobalEnv, i18n("Always")}}
+ ), this, RObject::IncludeEnvirIfNotGlobalEnv | RObject::IncludeEnvirForGlobalEnv | RObject::IncludeEnvirIfMasked);
form_layout->addRow (i18n ("Include environment for objects on the search path:"), completion_object_qualification_box);
} else {
box_layout->addWidget(RKCommonFunctions::linkedWrappedLabel(i18n("<b>Note: </b>Additional (common) completion options are available at the <a href=\"rkward://settings/editor\">script editor settings</a>")));
@@ -125,16 +113,6 @@ void RKCodeCompletionSettingsWidget::applyChanges() {
settings->auto_completion_enabled = auto_completion_enabled_box->isChecked ();
settings->auto_completion_min_chars = auto_completion_min_chars_box->intValue ();
settings->auto_completion_timeout = auto_completion_timeout_box->intValue ();
- settings->cursor_navigates_completions = (cursor_navigates_completions_box->currentIndex() == 0);
-
- if (show_common) {
- settings->completion_options = 0;
- if (completion_list_member_operator_box->currentIndex () == 0) settings->completion_options = settings->completion_options + RObject::DollarExpansion;
- if (completion_slot_operator_box->currentIndex () == 1) settings->completion_options = settings->completion_options + RObject::ExplicitSlotsExpansion;
- if (completion_object_qualification_box->currentIndex () == 2) settings->completion_options = settings->completion_options + (RObject::IncludeEnvirForGlobalEnv | RObject::IncludeEnvirIfNotGlobalEnv);
- else if (completion_object_qualification_box->currentIndex () == 1) settings->completion_options = settings->completion_options + RObject::IncludeEnvirIfNotGlobalEnv;
- else settings->completion_options = settings->completion_options + RObject::IncludeEnvirIfMasked;
- }
}
void RKCodeCompletionSettingsWidget::makeCompletionTypeBoxes(const QStringList& labels, QGridLayout* layout) {
diff --git a/rkward/settings/rksettingsmodulecommandeditor.h b/rkward/settings/rksettingsmodulecommandeditor.h
index 319fe07a..1dab15ac 100644
--- a/rkward/settings/rksettingsmodulecommandeditor.h
+++ b/rkward/settings/rksettingsmodulecommandeditor.h
@@ -80,10 +80,6 @@ private:
RKSpinBox* auto_completion_min_chars_box;
RKSpinBox* auto_completion_timeout_box;
QGroupBox* auto_completion_enabled_box;
- QComboBox* cursor_navigates_completions_box;
- QComboBox* completion_list_member_operator_box;
- QComboBox* completion_slot_operator_box;
- QComboBox* completion_object_qualification_box;
RKCodeCompletionSettings *settings;
bool show_common;
diff --git a/rkward/settings/rksettingsmoduleconsole.cpp b/rkward/settings/rksettingsmoduleconsole.cpp
index f6100c0b..bb24af33 100644
--- a/rkward/settings/rksettingsmoduleconsole.cpp
+++ b/rkward/settings/rksettingsmoduleconsole.cpp
@@ -77,12 +77,9 @@ RKSettingsModuleConsole::RKSettingsModuleConsole (RKSettings *gui, QWidget *pare
vbox->addWidget(pipe_user_commands_through_console_box);
vbox->addWidget (new QLabel (i18n ("Also add those commands to console history"), this));
- add_piped_commands_to_history_box = new QComboBox (this);
- add_piped_commands_to_history_box->insertItem ((int) DontAdd, i18n ("Do not add"));
- add_piped_commands_to_history_box->insertItem ((int) AddSingleLine, i18n ("Add only if single line"));
- add_piped_commands_to_history_box->insertItem ((int) AlwaysAdd, i18n ("Add all commands"));
- add_piped_commands_to_history_box->setCurrentIndex ((int) add_piped_commands_to_history);
- connect (add_piped_commands_to_history_box, static_cast<void (QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &RKSettingsModuleConsole::changedSetting);
+ auto add_piped_commands_to_history_box = add_piped_commands_to_history.makeDropDown(RKConfigBase::LabelList(
+ {{(int) DontAdd, i18n("Do not add")}, {(int) AddSingleLine, i18n("Add only if single line")}, {(int) AlwaysAdd, i18n("Add all commands")}}
+ ), this);
add_piped_commands_to_history_box->setEnabled(pipe_user_commands_through_console_box->isChecked());
connect(pipe_user_commands_through_console_box, &QCheckBox::stateChanged, add_piped_commands_to_history_box, &QCheckBox::setEnabled);
vbox->addWidget (add_piped_commands_to_history_box);
@@ -153,7 +150,6 @@ void RKSettingsModuleConsole::applyChanges () {
completion_settings_widget->applyChanges();
max_history_length = max_history_length_spinner->value ();
max_console_lines = max_console_lines_spinner->value ();
- add_piped_commands_to_history = (PipedCommandsHistoryMode) add_piped_commands_to_history_box->currentIndex ();
}
QString RKSettingsModuleConsole::caption () {
diff --git a/rkward/settings/rksettingsmoduleconsole.h b/rkward/settings/rksettingsmoduleconsole.h
index ada18bc6..8b04d753 100644
--- a/rkward/settings/rksettingsmoduleconsole.h
+++ b/rkward/settings/rksettingsmoduleconsole.h
@@ -75,7 +75,6 @@ private:
static RKConfigValue<bool> context_sensitive_history_by_default;
RKCodeCompletionSettingsWidget *completion_settings_widget;
- QComboBox *add_piped_commands_to_history_box;
QSpinBox *max_history_length_spinner;
QSpinBox *max_console_lines_spinner;
};
diff --git a/rkward/settings/rksettingsmoduler.cpp b/rkward/settings/rksettingsmoduler.cpp
index f2dd6ce0..afa23d30 100755
--- a/rkward/settings/rksettingsmoduler.cpp
+++ b/rkward/settings/rksettingsmoduler.cpp
@@ -79,14 +79,9 @@ RKSettingsModuleR::RKSettingsModuleR (RKSettings *gui, QWidget *parent) : RKSett
// options (warn)
grid->addWidget (new QLabel (i18n ("Display warnings"), this), ++row, 0);
- warn_input = new QComboBox (this);
- warn_input->setEditable (false);
- warn_input->insertItem (0, i18n ("Suppress warnings")); // do not change the order of options! See also: applyChanges ()
- warn_input->insertItem (1, i18n ("Print warnings later (default)"));
- warn_input->insertItem (2, i18n ("Print warnings immediately"));
- warn_input->insertItem (3, i18n ("Convert warnings to errors"));
- warn_input->setCurrentIndex (options_warn + 1);
- connect (warn_input, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &RKSettingsModuleR::settingChanged);
+ auto warn_input = options_warn.makeDropDown(RKConfigBase::LabelList(
+ {{-1, i18n("Suppress warnings")}, {0, i18n("Print warnings later (default)")}, {1, i18n("Print warnings immediately")}, {2, i18n ("Convert warnings to errors")}}
+ ), this);
grid->addWidget (warn_input, row, 1);
// options (OutDec)
@@ -128,22 +123,12 @@ RKSettingsModuleR::RKSettingsModuleR (RKSettings *gui, QWidget *parent) : RKSett
// options (keep.source)
grid->addWidget (new QLabel (i18n ("Keep comments in functions"), this), ++row, 0);
- keepsource_input = new QComboBox (this);
- keepsource_input->setEditable (false);
- keepsource_input->addItem (i18n ("TRUE (default)"), true);
- keepsource_input->addItem (i18n ("FALSE"), false);
- keepsource_input->setCurrentIndex (options_keepsource ? 0 : 1);
- connect (keepsource_input, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &RKSettingsModuleR::settingChanged);
+ auto keepsource_input = options_keepsource.makeDropDown(RKConfigBase::LabelList({{1, i18n("TRUE (default)")}, {0, i18n("FALSE")}}), this);
grid->addWidget (keepsource_input, row, 1);
// options (keep.source.pkgs)
grid->addWidget (new QLabel (i18n ("Keep comments in packages"), this), ++row, 0);
- keepsourcepkgs_input = new QComboBox (this);
- keepsourcepkgs_input->setEditable (false);
- keepsourcepkgs_input->addItem (i18n ("TRUE"), true);
- keepsourcepkgs_input->addItem (i18n ("FALSE (default)"), false);
- keepsourcepkgs_input->setCurrentIndex (options_keepsourcepkgs ? 0 : 1);
- connect (keepsourcepkgs_input, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &RKSettingsModuleR::settingChanged);
+ auto keepsourcepkgs_input = options_keepsourcepkgs.makeDropDown(RKConfigBase::LabelList({{1, i18n("TRUE")}, {0, i18n("FALSE (default)")}}), this);
grid->addWidget (keepsourcepkgs_input, row, 1);
// options (expressions)
@@ -168,12 +153,7 @@ RKSettingsModuleR::RKSettingsModuleR (RKSettings *gui, QWidget *parent) : RKSett
// options (check.bounds)
grid->addWidget (new QLabel (i18n ("Check vector bounds (warn)"), this), ++row, 0);
- checkbounds_input = new QComboBox (this);
- checkbounds_input->setEditable (false);
- checkbounds_input->addItem (i18n ("TRUE"), true);
- checkbounds_input->addItem (i18n ("FALSE (default)"), false);
- checkbounds_input->setCurrentIndex (options_checkbounds ? 0 : 1);
- connect (checkbounds_input, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &RKSettingsModuleR::settingChanged);
+ auto checkbounds_input = options_checkbounds.makeDropDown(RKConfigBase::LabelList({{1, i18n("TRUE")}, {0, i18n("FALSE (default)")}}), this);
grid->addWidget (checkbounds_input, row, 1);
grid->addWidget (new QLabel (i18n ("Editor command"), this), ++row, 0);
@@ -234,14 +214,10 @@ void RKSettingsModuleR::applyChanges () {
options_outdec = outdec_input->text ();
options_width = width_input->value ();
- options_warn = warn_input->currentIndex () - 1;
options_warningslength = warningslength_input->value ();
options_maxprint = maxprint_input->value ();
- options_keepsource = keepsource_input->itemData (keepsource_input->currentIndex ()).toBool ();
- options_keepsourcepkgs = keepsourcepkgs_input->itemData (keepsourcepkgs_input->currentIndex ()).toBool ();
options_expressions = expressions_input->value ();
options_digits = digits_input->value ();
- options_checkbounds = checkbounds_input->itemData (checkbounds_input->currentIndex ()).toBool ();
options_editor = editor_input->currentText ();
options_pager = pager_input->currentText ();
options_further = further_input->toPlainText ();
diff --git a/rkward/settings/rksettingsmoduler.h b/rkward/settings/rksettingsmoduler.h
index 62da874d..c5ebf66a 100644
--- a/rkward/settings/rksettingsmoduler.h
+++ b/rkward/settings/rksettingsmoduler.h
@@ -60,14 +60,10 @@ private slots:
private:
QLineEdit *outdec_input;
QSpinBox *width_input;
- QComboBox *warn_input;
QSpinBox *warningslength_input;
QSpinBox *maxprint_input;
- QComboBox *keepsource_input;
- QComboBox *keepsourcepkgs_input;
QSpinBox *expressions_input;
QSpinBox *digits_input;
- QComboBox *checkbounds_input;
QComboBox *editor_input;
QComboBox *pager_input;
QTextEdit *further_input;
More information about the rkward-tracker
mailing list