From e941cf9bb110f1219d352fdef8e16c54a3a5722b Mon Sep 17 00:00:00 2001 From: Torsten Paul Date: Wed, 28 Sep 2016 16:07:02 +0200 Subject: [PATCH] Add basic configuration GUI for axis and button mapping. --- icons/license.txt | 4 + icons/prefsInput.png | Bin 0 -> 33610 bytes openscad.qrc | 1 + src/Preferences.cc | 123 +++++++++++++++++++ src/Preferences.h | 17 +++ src/Preferences.ui | 207 ++++++++++++++++++++++++++++++-- src/input/InputDriverManager.cc | 5 + src/input/InputDriverManager.h | 3 + src/input/InputEventMapper.cc | 61 ++++++---- src/input/InputEventMapper.h | 4 + src/mainwin.cc | 1 + src/settings.cc | 129 +++++++++++++++++++- src/settings.h | 15 +++ 13 files changed, 532 insertions(+), 38 deletions(-) create mode 100644 icons/prefsInput.png diff --git a/icons/license.txt b/icons/license.txt index f73b0891..237c2b99 100644 --- a/icons/license.txt +++ b/icons/license.txt @@ -2,6 +2,10 @@ Taken from http://tango.freedesktop.org/Tango_Icon_Library, version 0.8.90 / pub - prefsFeatures.png (converted from preferences-system.svg) +https://openclipart.org/detail/35425/tango-desktop-peripherals / public domain: + +- prefsInput.png + https://openclipart.org/detail/2281/information-icons-set-by-kuba / public domain: - information-icons-error.png diff --git a/icons/prefsInput.png b/icons/prefsInput.png new file mode 100644 index 0000000000000000000000000000000000000000..efd746c7646e701e344e9a69b18af4534f9e27f4 GIT binary patch literal 33610 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 + icons/prefsInput.png images/zoom-text-in-white.png images/zoom-text-in.png images/zoom-text-out-white.png diff --git a/src/Preferences.cc b/src/Preferences.cc index 869ffd2a..11b8a355 100644 --- a/src/Preferences.cc +++ b/src/Preferences.cc @@ -182,6 +182,7 @@ void Preferences::init() { this->toolBar->removeAction(prefsActionFeatures); #endif addPrefPage(group, prefsActionAdvanced, pageAdvanced); + addPrefPage(group, prefsActionInput, pageInput); connect(group, SIGNAL(triggered(QAction*)), this, SLOT(actionTriggered(QAction*))); prefsAction3DView->setChecked(true); @@ -210,6 +211,22 @@ void Preferences::init() { initSpinBox(this->spinBoxShowWhitespaceSize, Settings::Settings::showWhitespaceSize); initSpinBox(this->spinBoxTabWidth, Settings::Settings::tabWidth); + initComboBox(this->comboBoxTranslationX, Settings::Settings::inputTranslationX); + initComboBox(this->comboBoxTranslationY, Settings::Settings::inputTranslationY); + initComboBox(this->comboBoxTranslationZ, Settings::Settings::inputTranslationZ); + initComboBox(this->comboBoxRotationX, Settings::Settings::inputRotateX); + initComboBox(this->comboBoxRotationY, Settings::Settings::inputRotateY); + initComboBox(this->comboBoxRotationZ, Settings::Settings::inputRotateZ); + initComboBox(this->comboBoxZoom, Settings::Settings::inputZoom); + initComboBox(this->comboBoxButton1, Settings::Settings::inputButton1); + initComboBox(this->comboBoxButton2, Settings::Settings::inputButton2); + initComboBox(this->comboBoxButton3, Settings::Settings::inputButton3); + initComboBox(this->comboBoxButton4, Settings::Settings::inputButton4); + initComboBox(this->comboBoxButton5, Settings::Settings::inputButton5); + initComboBox(this->comboBoxButton6, Settings::Settings::inputButton6); + initComboBox(this->comboBoxButton7, Settings::Settings::inputButton7); + initComboBox(this->comboBoxButton8, Settings::Settings::inputButton8); + SettingsReader settingsReader; Settings::Settings::inst()->visit(settingsReader); emit editorConfigChanged(); @@ -574,6 +591,96 @@ void Preferences::on_checkBoxEnableLineNumbers_toggled(bool checked) writeSettings(); } +void Preferences::on_comboBoxTranslationX_activated(int val) +{ + applyComboBox(comboBoxTranslationX, val, Settings::Settings::inputTranslationX); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxTranslationY_activated(int val) +{ + applyComboBox(comboBoxTranslationY, val, Settings::Settings::inputTranslationY); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxTranslationZ_activated(int val) +{ + applyComboBox(comboBoxTranslationZ, val, Settings::Settings::inputTranslationZ); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxRotationX_activated(int val) +{ + applyComboBox(comboBoxRotationX, val, Settings::Settings::inputRotateX); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxRotationY_activated(int val) +{ + applyComboBox(comboBoxRotationY, val, Settings::Settings::inputRotateY); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxRotationZ_activated(int val) +{ + applyComboBox(comboBoxRotationZ, val, Settings::Settings::inputRotateZ); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxZoom_activated(int val) +{ + applyComboBox(comboBoxZoom, val, Settings::Settings::inputZoom); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxButton1_activated(int val) +{ + applyComboBox(comboBoxButton1, val, Settings::Settings::inputButton1); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxButton2_activated(int val) +{ + applyComboBox(comboBoxButton2, val, Settings::Settings::inputButton2); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxButton3_activated(int val) +{ + applyComboBox(comboBoxButton3, val, Settings::Settings::inputButton3); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxButton4_activated(int val) +{ + applyComboBox(comboBoxButton4, val, Settings::Settings::inputButton4); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxButton5_activated(int val) +{ + applyComboBox(comboBoxButton5, val, Settings::Settings::inputButton5); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxButton6_activated(int val) +{ + applyComboBox(comboBoxButton6, val, Settings::Settings::inputButton6); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxButton7_activated(int val) +{ + applyComboBox(comboBoxButton7, val, Settings::Settings::inputButton7); + emit inputMappingChanged(); +} + +void Preferences::on_comboBoxButton8_activated(int val) +{ + applyComboBox(comboBoxButton8, val, Settings::Settings::inputButton8); + emit inputMappingChanged(); +} + void Preferences::writeSettings() { SettingsWriter settingsWriter; @@ -699,6 +806,22 @@ void Preferences::updateGUI() this->checkBoxShowWarningsIn3dView->setChecked(s->get(Settings::Settings::showWarningsIn3dView).toBool()); this->checkBoxEnableLineNumbers->setChecked(s->get(Settings::Settings::enableLineNumbers).toBool()); this->spinBoxLineWrapIndentationIndent->setDisabled(this->comboBoxLineWrapIndentationStyle->currentText() == "Same"); + + updateComboBox(this->comboBoxTranslationX, Settings::Settings::inputTranslationX); + updateComboBox(this->comboBoxTranslationY, Settings::Settings::inputTranslationY); + updateComboBox(this->comboBoxTranslationZ, Settings::Settings::inputTranslationZ); + updateComboBox(this->comboBoxRotationX, Settings::Settings::inputRotateX); + updateComboBox(this->comboBoxRotationY, Settings::Settings::inputRotateY); + updateComboBox(this->comboBoxRotationZ, Settings::Settings::inputRotateZ); + updateComboBox(this->comboBoxZoom, Settings::Settings::inputZoom); + updateComboBox(this->comboBoxButton1, Settings::Settings::inputButton1); + updateComboBox(this->comboBoxButton2, Settings::Settings::inputButton2); + updateComboBox(this->comboBoxButton3, Settings::Settings::inputButton3); + updateComboBox(this->comboBoxButton4, Settings::Settings::inputButton4); + updateComboBox(this->comboBoxButton5, Settings::Settings::inputButton5); + updateComboBox(this->comboBoxButton6, Settings::Settings::inputButton6); + updateComboBox(this->comboBoxButton7, Settings::Settings::inputButton7); + updateComboBox(this->comboBoxButton8, Settings::Settings::inputButton8); } void Preferences::initComboBox(QComboBox *comboBox, const Settings::SettingsEntry& entry) diff --git a/src/Preferences.h b/src/Preferences.h index af769b9c..21660ff8 100644 --- a/src/Preferences.h +++ b/src/Preferences.h @@ -73,6 +73,22 @@ public slots: void on_checkBoxEnableBraceMatching_toggled(bool); void on_checkBoxEnableLineNumbers_toggled(bool); + void on_comboBoxTranslationX_activated(int val); + void on_comboBoxTranslationY_activated(int val); + void on_comboBoxTranslationZ_activated(int val); + void on_comboBoxRotationX_activated(int val); + void on_comboBoxRotationY_activated(int val); + void on_comboBoxRotationZ_activated(int val); + void on_comboBoxZoom_activated(int val); + void on_comboBoxButton1_activated(int val); + void on_comboBoxButton2_activated(int val); + void on_comboBoxButton3_activated(int val); + void on_comboBoxButton4_activated(int val); + void on_comboBoxButton5_activated(int val); + void on_comboBoxButton6_activated(int val); + void on_comboBoxButton7_activated(int val); + void on_comboBoxButton8_activated(int val); + signals: void requestRedraw() const; void updateMdiMode(bool mdi) const; @@ -84,6 +100,7 @@ signals: void syntaxHighlightChanged(const QString &s) const; void editorTypeChanged(const QString &type); void editorConfigChanged() const; + void inputMappingChanged() const; private: Preferences(QWidget *parent = NULL); diff --git a/src/Preferences.ui b/src/Preferences.ui index 5b20fa99..1d33ec48 100644 --- a/src/Preferences.ui +++ b/src/Preferences.ui @@ -6,8 +6,8 @@ 0 0 - 675 - 476 + 689 + 480 @@ -23,11 +23,11 @@ true - - + + - 1 + 5 @@ -125,9 +125,9 @@ 0 - -262 - 639 - 653 + 0 + 677 + 784 @@ -244,7 +244,7 @@ - TeX Gyre Heros + Nimbus Sans L 12 @@ -1220,8 +1220,8 @@ 0 0 - 82 - 26 + 100 + 30 @@ -1283,8 +1283,8 @@ 0 0 - 490 - 383 + 612 + 510 @@ -1453,6 +1453,174 @@ + + + + 0 + + + + + true + + + + + 0 + 0 + 656 + 489 + + + + + + + Rotation + + + + + + + Button 6 + + + + + + + + + + + + + Button 7 + + + + + + + + + + Button 3 + + + + + + + Zoom + + + + + + + + + + + + + Button 4 + + + + + + + Button 5 + + + + + + + Button 8 + + + + + + + Button 1 + + + + + + + + + + Button 2 + + + + + + + + + + Translation + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + Qt::Horizontal + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1487,6 +1655,7 @@ + @@ -1551,6 +1720,18 @@ Enable/Disable experimental features + + + true + + + + :/icons/prefsInput.png:/icons/prefsInput.png + + + Input + + diff --git a/src/input/InputDriverManager.cc b/src/input/InputDriverManager.cc index 7eed88d9..6f939670 100644 --- a/src/input/InputDriverManager.cc +++ b/src/input/InputDriverManager.cc @@ -148,3 +148,8 @@ void InputDriverManager::onFocusChanged(QWidget *, QWidget *current) currentWindow = dynamic_cast(current->window()); } } + +void InputDriverManager::onInputMappingUpdated() +{ + mapper.onInputMappingUpdated(); +} diff --git a/src/input/InputDriverManager.h b/src/input/InputDriverManager.h index 4fd852d1..30b27e87 100644 --- a/src/input/InputDriverManager.h +++ b/src/input/InputDriverManager.h @@ -67,6 +67,9 @@ public: static InputDriverManager * instance(); +public slots: + void onInputMappingUpdated(); + private slots: void onTimeout(); void doOpen(bool firstOpen); diff --git a/src/input/InputEventMapper.cc b/src/input/InputEventMapper.cc index 22363127..9506155b 100644 --- a/src/input/InputEventMapper.cc +++ b/src/input/InputEventMapper.cc @@ -25,6 +25,7 @@ */ #include "InputEventMapper.h" #include "InputDriverManager.h" +#include "settings.h" #include #include @@ -39,29 +40,7 @@ InputEventMapper::InputEventMapper() connect(timer, SIGNAL(timeout()), this, SLOT(onTimer())); timer->start(30); - QSettings settings; - - if (settings.value("InputDriver/button/1").toString().isEmpty()) { - settings.setValue("InputDriver/button/1", "viewActionResetView"); - settings.setValue("InputDriver/button/2", "viewActionViewAll"); - settings.setValue("InputDriver/axis/translateX", "+1"); - settings.setValue("InputDriver/axis/translateY", "-2"); - settings.setValue("InputDriver/axis/translateZ", "-3"); - settings.setValue("InputDriver/axis/rotateX", "+4"); - settings.setValue("InputDriver/axis/rotateY", "-5"); - settings.setValue("InputDriver/axis/rotateZ", "-6"); - } - - for (int a = 0;a < 10;a++) { - QString key = QString("InputDriver/button/%1").arg(a + 1); - actions[a] = settings.value(key).toString(); - } - translate[0] = settings.value("InputDriver/axis/translateX").toInt(); - translate[1] = settings.value("InputDriver/axis/translateY").toInt(); - translate[2] = settings.value("InputDriver/axis/translateZ").toInt(); - rotate[0] = settings.value("InputDriver/axis/rotateX").toInt(); - rotate[1] = settings.value("InputDriver/axis/rotateY").toInt(); - rotate[2] = settings.value("InputDriver/axis/rotateZ").toInt(); + onInputMappingUpdated(); } InputEventMapper::~InputEventMapper() @@ -103,6 +82,12 @@ void InputEventMapper::onTimer() InputEvent *inputEvent = new InputEventRotate(rx, ry, rz); InputDriverManager::instance()->postEvent(inputEvent); } + + double z = getAxisValue(zoom); + if (fabs(z) > threshold) { + InputEvent *inputEvent = new InputEventZoom(z); + InputDriverManager::instance()->postEvent(inputEvent); + } } void InputEventMapper::onAxisChanged(InputEventAxisChanged *event) @@ -144,3 +129,33 @@ void InputEventMapper::onZoomEvent(InputEventZoom *event) { InputDriverManager::instance()->postEvent(event); } + +int InputEventMapper::parseSettingValue(const std::string val) +{ + if (val.length() != 2) { + return 0; + } + return atoi(val.c_str()); +} + +void InputEventMapper::onInputMappingUpdated() +{ + Settings::Settings *s = Settings::Settings::inst(); + + actions[0] = QString(s->get(Settings::Settings::inputButton1).toString().c_str()); + actions[1] = QString(s->get(Settings::Settings::inputButton2).toString().c_str()); + actions[2] = QString(s->get(Settings::Settings::inputButton3).toString().c_str()); + actions[3] = QString(s->get(Settings::Settings::inputButton4).toString().c_str()); + actions[4] = QString(s->get(Settings::Settings::inputButton5).toString().c_str()); + actions[5] = QString(s->get(Settings::Settings::inputButton6).toString().c_str()); + actions[6] = QString(s->get(Settings::Settings::inputButton7).toString().c_str()); + actions[7] = QString(s->get(Settings::Settings::inputButton8).toString().c_str()); + + translate[0] = parseSettingValue(s->get(Settings::Settings::inputTranslationX).toString()); + translate[1] = parseSettingValue(s->get(Settings::Settings::inputTranslationY).toString()); + translate[2] = parseSettingValue(s->get(Settings::Settings::inputTranslationZ).toString()); + rotate[0] = parseSettingValue(s->get(Settings::Settings::inputRotateX).toString()); + rotate[1] = parseSettingValue(s->get(Settings::Settings::inputRotateY).toString()); + rotate[2] = parseSettingValue(s->get(Settings::Settings::inputRotateZ).toString()); + zoom = parseSettingValue(s->get(Settings::Settings::inputZoom).toString()); +} diff --git a/src/input/InputEventMapper.h b/src/input/InputEventMapper.h index 7e907353..c37e8d71 100644 --- a/src/input/InputEventMapper.h +++ b/src/input/InputEventMapper.h @@ -40,9 +40,11 @@ private: QString actions[10]; int translate[3]; int rotate[3]; + int zoom; double scale(double val); double getAxisValue(int config); + int parseSettingValue(const std::string val); public: InputEventMapper(); @@ -56,6 +58,8 @@ public: void onActionEvent(class InputEventAction *event); void onZoomEvent(class InputEventZoom *event); + void onInputMappingUpdated(); + private slots: void onTimer(); }; diff --git a/src/mainwin.cc b/src/mainwin.cc index 306c98c3..81bf0c88 100644 --- a/src/mainwin.cc +++ b/src/mainwin.cc @@ -198,6 +198,7 @@ MainWindow::MainWindow(const QString &filename) editor = new LegacyEditor(editorDockContents); Preferences::create(editor->colorSchemes()); + connect(Preferences::inst(), SIGNAL(inputMappingChanged()), InputDriverManager::instance(), SLOT(onInputMappingUpdated()), Qt::UniqueConnection); #ifdef USE_SCINTILLA_EDITOR if (useScintilla) { diff --git a/src/settings.cc b/src/settings.cc index 85093288..16b64adb 100644 --- a/src/settings.cc +++ b/src/settings.cc @@ -43,10 +43,10 @@ bool SettingsEntry::is_default() const return _value == _default; } -static Value value(std::string s1, std::string s2) { +static ValuePtr value(std::string s1, std::string s2) { Value::VectorType v; v += ValuePtr(s1), ValuePtr(s2); - return v; + return ValuePtr(v); } static Value values(std::string s1, std::string s1disp, std::string s2, std::string s2disp) { @@ -67,6 +67,114 @@ static Value values(std::string s1, std::string s1disp, std::string s2, std::str return v; } +static Value axisValues() { + Value::VectorType v; + v += value("None", _("None")); + v += value("+1", _("Axis 1")); + v += value("-1", _("Axis 1 (inverted)")); + v += value("+2", _("Axis 2")); + v += value("-2", _("Axis 2 (inverted)")); + v += value("+3", _("Axis 3")); + v += value("-3", _("Axis 3 (inverted)")); + v += value("+4", _("Axis 4")); + v += value("-4", _("Axis 4 (inverted)")); + v += value("+5", _("Axis 5")); + v += value("-5", _("Axis 5 (inverted)")); + v += value("+6", _("Axis 6")); + v += value("-6", _("Axis 6 (inverted)")); + v += value("+7", _("Axis 7")); + v += value("-7", _("Axis 7 (inverted)")); + v += value("+8", _("Axis 8")); + v += value("-8", _("Axis 8 (inverted)")); + v += value("+9", _("Axis 9")); + v += value("-9", _("Axis 9 (inverted)")); + return v; +} + +static Value buttonValues() { + Value::VectorType v; + v += value("None", _("None")); + v += value("designActionAutoReload", _("designActionAutoReload")); + v += value("designActionDisplayAST", _("designActionDisplayAST")); + v += value("designActionDisplayCSGProducts", _("designActionDisplayCSGProducts")); + v += value("designActionDisplayCSGTree", _("designActionDisplayCSGTree")); + v += value("designActionFlushCaches", _("designActionFlushCaches")); + v += value("designActionPreview", _("designActionPreview")); + v += value("designActionReloadAndPreview", _("designActionReloadAndPreview")); + v += value("designActionRender", _("designActionRender")); + v += value("designCheckValidity", _("designCheckValidity")); + v += value("editActionComment", _("editActionComment")); + v += value("editActionConvertTabsToSpaces", _("editActionConvertTabsToSpaces")); + v += value("editActionCopy", _("editActionCopy")); + v += value("editActionCopyViewport", _("editActionCopyViewport")); + v += value("editActionCut", _("editActionCut")); + v += value("editActionFind", _("editActionFind")); + v += value("editActionFindAndReplace", _("editActionFindAndReplace")); + v += value("editActionFindNext", _("editActionFindNext")); + v += value("editActionFindPrevious", _("editActionFindPrevious")); + v += value("editActionIndent", _("editActionIndent")); + v += value("editActionPaste", _("editActionPaste")); + v += value("editActionPasteVPR", _("editActionPasteVPR")); + v += value("editActionPasteVPT", _("editActionPasteVPT")); + v += value("editActionPreferences", _("editActionPreferences")); + v += value("editActionRedo", _("editActionRedo")); + v += value("editActionUncomment", _("editActionUncomment")); + v += value("editActionUndo", _("editActionUndo")); + v += value("editActionUnindent", _("editActionUnindent")); + v += value("editActionUseSelectionForFind", _("editActionUseSelectionForFind")); + v += value("editActionZoomTextIn", _("editActionZoomTextIn")); + v += value("editActionZoomTextOut", _("editActionZoomTextOut")); + v += value("fileActionClearRecent", _("fileActionClearRecent")); + v += value("fileActionClose", _("fileActionClose")); + v += value("fileActionExportAMF", _("fileActionExportAMF")); + v += value("fileActionExportCSG", _("fileActionExportCSG")); + v += value("fileActionExportDXF", _("fileActionExportDXF")); + v += value("fileActionExportImage", _("fileActionExportImage")); + v += value("fileActionExportOFF", _("fileActionExportOFF")); + v += value("fileActionExportSTL", _("fileActionExportSTL")); + v += value("fileActionExportSVG", _("fileActionExportSVG")); + v += value("fileActionNew", _("fileActionNew")); + v += value("fileActionOpen", _("fileActionOpen")); + v += value("fileActionQuit", _("fileActionQuit")); + v += value("fileActionReload", _("fileActionReload")); + v += value("fileActionSave", _("fileActionSave")); + v += value("fileActionSaveAs", _("fileActionSaveAs")); + v += value("fileShowLibraryFolder", _("fileShowLibraryFolder")); + v += value("helpActionAbout", _("helpActionAbout")); + v += value("helpActionCheatSheet", _("helpActionCheatSheet")); + v += value("helpActionFontInfo", _("helpActionFontInfo")); + v += value("helpActionHomepage", _("helpActionHomepage")); + v += value("helpActionLibraryInfo", _("helpActionLibraryInfo")); + v += value("helpActionManual", _("helpActionManual")); + v += value("viewActionAnimate", _("viewActionAnimate")); + v += value("viewActionBack", _("viewActionBack")); + v += value("viewActionBottom", _("viewActionBottom")); + v += value("viewActionCenter", _("viewActionCenter")); + v += value("viewActionDiagonal", _("viewActionDiagonal")); + v += value("viewActionFront", _("viewActionFront")); + v += value("viewActionHideConsole", _("viewActionHideConsole")); + v += value("viewActionHideEditor", _("viewActionHideEditor")); + v += value("viewActionHideToolBars", _("viewActionHideToolBars")); + v += value("viewActionLeft", _("viewActionLeft")); + v += value("viewActionOrthogonal", _("viewActionOrthogonal")); + v += value("viewActionPerspective", _("viewActionPerspective")); + v += value("viewActionPreview", _("viewActionPreview")); + v += value("viewActionResetView", _("viewActionResetView")); + v += value("viewActionRight", _("viewActionRight")); + v += value("viewActionShowAxes", _("viewActionShowAxes")); + v += value("viewActionShowCrosshairs", _("viewActionShowCrosshairs")); + v += value("viewActionShowEdges", _("viewActionShowEdges")); + v += value("viewActionShowScaleProportional", _("viewActionShowScaleProportional")); + v += value("viewActionSurfaces", _("viewActionSurfaces")); + v += value("viewActionThrownTogether", _("viewActionThrownTogether")); + v += value("viewActionTop", _("viewActionTop")); + v += value("viewActionViewAll", _("viewActionViewAll")); + v += value("viewActionWireframe", _("viewActionWireframe")); + v += value("viewActionZoomIn", _("viewActionZoomIn")); + v += value("viewActionZoomOut", _("viewActionZoomOut")); + return v; +} + Settings *Settings::inst(bool erase) { static Settings *instance = new Settings; @@ -143,4 +251,21 @@ SettingsEntry Settings::tabKeyFunction("editor", "tabKeyFunction", values("Inden SettingsEntry Settings::highlightCurrentLine("editor", "highlightCurrentLine", Value(true), Value(true)); SettingsEntry Settings::enableBraceMatching("editor", "enableBraceMatching", Value(true), Value(true)); SettingsEntry Settings::enableLineNumbers("editor", "enableLineNumbers", Value(true), Value(true)); + +SettingsEntry Settings::inputTranslationX("input", "translationX", axisValues(), Value("+1")); +SettingsEntry Settings::inputTranslationY("input", "translationY", axisValues(), Value("-2")); +SettingsEntry Settings::inputTranslationZ("input", "translationZ", axisValues(), Value("-3")); +SettingsEntry Settings::inputRotateX("input", "rotateX", axisValues(), Value("+4")); +SettingsEntry Settings::inputRotateY("input", "rotateY", axisValues(), Value("-5")); +SettingsEntry Settings::inputRotateZ("input", "rotateZ", axisValues(), Value("-6")); +SettingsEntry Settings::inputZoom("input", "zoom", axisValues(), Value("None")); +SettingsEntry Settings::inputButton1("input", "button1", buttonValues(), Value("viewActionResetView")); +SettingsEntry Settings::inputButton2("input", "button2", buttonValues(), Value("None")); +SettingsEntry Settings::inputButton3("input", "button3", buttonValues(), Value("None")); +SettingsEntry Settings::inputButton4("input", "button4", buttonValues(), Value("None")); +SettingsEntry Settings::inputButton5("input", "button5", buttonValues(), Value("None")); +SettingsEntry Settings::inputButton6("input", "button6", buttonValues(), Value("None")); +SettingsEntry Settings::inputButton7("input", "button7", buttonValues(), Value("None")); +SettingsEntry Settings::inputButton8("input", "button8", buttonValues(), Value("None")); + } diff --git a/src/settings.h b/src/settings.h index 289114b9..2ee83921 100644 --- a/src/settings.h +++ b/src/settings.h @@ -52,6 +52,21 @@ public: static SettingsEntry highlightCurrentLine; static SettingsEntry enableBraceMatching; static SettingsEntry enableLineNumbers; + static SettingsEntry inputTranslationX; + static SettingsEntry inputTranslationY; + static SettingsEntry inputTranslationZ; + static SettingsEntry inputRotateX; + static SettingsEntry inputRotateY; + static SettingsEntry inputRotateZ; + static SettingsEntry inputZoom; + static SettingsEntry inputButton1; + static SettingsEntry inputButton2; + static SettingsEntry inputButton3; + static SettingsEntry inputButton4; + static SettingsEntry inputButton5; + static SettingsEntry inputButton6; + static SettingsEntry inputButton7; + static SettingsEntry inputButton8; static Settings *inst(bool erase = false);