Commit 33be9e7c authored by Thomas Friedrichsmeier's avatar Thomas Friedrichsmeier
Browse files

Automate creating of dropbown boxes in settings

parent 42df8238
......@@ -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);
}
......@@ -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;
};
......
......@@ -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@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@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) {
......
......@@ -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;
......
......@@ -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 () {
......
......@@ -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;
};
......
......@@ -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 ();
......
......@@ -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;
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment