From 71ae36f5c0a2d702502aa834e139ceb97b838b62 Mon Sep 17 00:00:00 2001
From: Brad Davis <bdavis@saintandreas.org>
Date: Fri, 22 Jan 2016 19:06:30 -0800
Subject: [PATCH] Button prefs and conditionally enabled prefs

---
 .../{Avatar.qml => AvatarPreference.qml}      |  2 +-
 ...{Browsable.qml => BrowsablePreference.qml} |  2 +-
 .../dialogs/preferences/ButtonPreference.qml  | 19 +++++++++++++++++
 .../{CheckBox.qml => CheckBoxPreference.qml}  |  1 +
 .../{Editable.qml => EditablePreference.qml}  |  1 +
 .../hifi/dialogs/preferences/Preference.qml   |  7 ++++++-
 .../qml/hifi/dialogs/preferences/Section.qml  | 17 +++++++++------
 .../{Slider.qml => SliderPreference.qml}      |  1 +
 .../{SpinBox.qml => SpinBoxPreference.qml}    |  1 +
 interface/src/ui/PreferencesDialog.cpp        | 11 +++++++---
 libraries/shared/src/Preferences.cpp          | 21 +++++++++++++++++++
 libraries/shared/src/Preferences.h            | 19 ++++++++++++++---
 tests/ui/qmlscratch.pro                       | 11 ++++++++--
 13 files changed, 96 insertions(+), 17 deletions(-)
 rename interface/resources/qml/hifi/dialogs/preferences/{Avatar.qml => AvatarPreference.qml} (97%)
 rename interface/resources/qml/hifi/dialogs/preferences/{Browsable.qml => BrowsablePreference.qml} (97%)
 create mode 100644 interface/resources/qml/hifi/dialogs/preferences/ButtonPreference.qml
 rename interface/resources/qml/hifi/dialogs/preferences/{CheckBox.qml => CheckBoxPreference.qml} (84%)
 rename interface/resources/qml/hifi/dialogs/preferences/{Editable.qml => EditablePreference.qml} (94%)
 rename interface/resources/qml/hifi/dialogs/preferences/{Slider.qml => SliderPreference.qml} (93%)
 rename interface/resources/qml/hifi/dialogs/preferences/{SpinBox.qml => SpinBoxPreference.qml} (93%)

diff --git a/interface/resources/qml/hifi/dialogs/preferences/Avatar.qml b/interface/resources/qml/hifi/dialogs/preferences/AvatarPreference.qml
similarity index 97%
rename from interface/resources/qml/hifi/dialogs/preferences/Avatar.qml
rename to interface/resources/qml/hifi/dialogs/preferences/AvatarPreference.qml
index c5f115e284..2bb3f2afd4 100644
--- a/interface/resources/qml/hifi/dialogs/preferences/Avatar.qml
+++ b/interface/resources/qml/hifi/dialogs/preferences/AvatarPreference.qml
@@ -1,7 +1,6 @@
 import QtQuick 2.5
 import QtQuick.Controls 1.4
 
-import "."
 import "../../../dialogs"
 
 Preference {
@@ -45,6 +44,7 @@ Preference {
 
     Text {
         id: labelText
+        color: enabled ? "black" : "gray"
         text:  root.label
     }
 
diff --git a/interface/resources/qml/hifi/dialogs/preferences/Browsable.qml b/interface/resources/qml/hifi/dialogs/preferences/BrowsablePreference.qml
similarity index 97%
rename from interface/resources/qml/hifi/dialogs/preferences/Browsable.qml
rename to interface/resources/qml/hifi/dialogs/preferences/BrowsablePreference.qml
index 811d61b714..ca42b3bec8 100644
--- a/interface/resources/qml/hifi/dialogs/preferences/Browsable.qml
+++ b/interface/resources/qml/hifi/dialogs/preferences/BrowsablePreference.qml
@@ -1,7 +1,6 @@
 import QtQuick 2.5
 import QtQuick.Controls 1.4
 
-import "."
 import "../../../dialogs"
 
 Preference {
@@ -23,6 +22,7 @@ Preference {
 
     Text {
         id: labelText
+        color: enabled ? "black" : "gray"
         text:  root.label
     }
 
diff --git a/interface/resources/qml/hifi/dialogs/preferences/ButtonPreference.qml b/interface/resources/qml/hifi/dialogs/preferences/ButtonPreference.qml
new file mode 100644
index 0000000000..51c2a31e79
--- /dev/null
+++ b/interface/resources/qml/hifi/dialogs/preferences/ButtonPreference.qml
@@ -0,0 +1,19 @@
+import QtQuick 2.5
+import QtQuick.Controls 1.4 as Original
+
+import "."
+import "../../../dialogs"
+
+Preference {
+    id: root
+    height: button.height
+
+    Component.onCompleted: button.text = preference.name;
+
+    function save() { }
+
+    Original.Button {
+        id: button
+        onClicked: preference.trigger()
+    }
+}
diff --git a/interface/resources/qml/hifi/dialogs/preferences/CheckBox.qml b/interface/resources/qml/hifi/dialogs/preferences/CheckBoxPreference.qml
similarity index 84%
rename from interface/resources/qml/hifi/dialogs/preferences/CheckBox.qml
rename to interface/resources/qml/hifi/dialogs/preferences/CheckBoxPreference.qml
index 23bd9a76a2..a17176bb07 100644
--- a/interface/resources/qml/hifi/dialogs/preferences/CheckBox.qml
+++ b/interface/resources/qml/hifi/dialogs/preferences/CheckBoxPreference.qml
@@ -8,6 +8,7 @@ Preference {
 
     Component.onCompleted: {
         checkBox.checked = preference.value;
+        preference.value = Qt.binding(function(){ return checkBox.checked; });
     }
 
     function save() {
diff --git a/interface/resources/qml/hifi/dialogs/preferences/Editable.qml b/interface/resources/qml/hifi/dialogs/preferences/EditablePreference.qml
similarity index 94%
rename from interface/resources/qml/hifi/dialogs/preferences/Editable.qml
rename to interface/resources/qml/hifi/dialogs/preferences/EditablePreference.qml
index 96d95b6815..53dc7ed5d0 100644
--- a/interface/resources/qml/hifi/dialogs/preferences/Editable.qml
+++ b/interface/resources/qml/hifi/dialogs/preferences/EditablePreference.qml
@@ -17,6 +17,7 @@ Preference {
 
     Text {
         id: labelText
+        color: enabled ? "black" : "gray"
         text: root.label
     }
 
diff --git a/interface/resources/qml/hifi/dialogs/preferences/Preference.qml b/interface/resources/qml/hifi/dialogs/preferences/Preference.qml
index d388f580b3..b119bcfcd1 100644
--- a/interface/resources/qml/hifi/dialogs/preferences/Preference.qml
+++ b/interface/resources/qml/hifi/dialogs/preferences/Preference.qml
@@ -6,7 +6,12 @@ Item {
     anchors { left: parent.left; right: parent.right }
     property var preference;
     property string label: preference ? preference.name : "";
-    Component.onCompleted: if (preference) { preference.load(); }
+    Component.onCompleted: {
+        if (preference) {
+            preference.load();
+            enabled = Qt.binding(function() { return preference.enabled; } );
+        }
+    }
 
     function restore() { }
 }
diff --git a/interface/resources/qml/hifi/dialogs/preferences/Section.qml b/interface/resources/qml/hifi/dialogs/preferences/Section.qml
index 49eb2d5c89..91eebdec01 100644
--- a/interface/resources/qml/hifi/dialogs/preferences/Section.qml
+++ b/interface/resources/qml/hifi/dialogs/preferences/Section.qml
@@ -70,12 +70,13 @@ Preference {
 
     QtObject {
         id: d
-        property var editableBuilder: Component { Editable { } }
-        property var browsableBuilder: Component { Browsable { } }
-        property var spinnerBuilder: Component { SpinBox { } }
-        property var checkboxBuilder: Component { CheckBox { } }
-        property var sliderBuilder: Component { Slider { } }
-        property var avatarBuilder: Component { Avatar { } }
+        property var editableBuilder: Component { EditablePreference { } }
+        property var browsableBuilder: Component { BrowsablePreference { } }
+        property var spinnerBuilder: Component { SpinBoxPreference { } }
+        property var checkboxBuilder: Component { CheckBoxPreference { } }
+        property var sliderBuilder: Component { SliderPreference { } }
+        property var avatarBuilder: Component { AvatarPreference { } }
+        property var buttonBuilder: Component { ButtonPreference { } }
         property var preferences: []
 
         function buildPreferences() {
@@ -115,6 +116,10 @@ Preference {
                 case Preference.Avatar:
                     builder = avatarBuilder;
                     break;
+
+                case Preference.Button:
+                    builder = buttonBuilder;
+                    break
             };
 
             if (builder) {
diff --git a/interface/resources/qml/hifi/dialogs/preferences/Slider.qml b/interface/resources/qml/hifi/dialogs/preferences/SliderPreference.qml
similarity index 93%
rename from interface/resources/qml/hifi/dialogs/preferences/Slider.qml
rename to interface/resources/qml/hifi/dialogs/preferences/SliderPreference.qml
index c11a9408e5..f2256b9245 100644
--- a/interface/resources/qml/hifi/dialogs/preferences/Slider.qml
+++ b/interface/resources/qml/hifi/dialogs/preferences/SliderPreference.qml
@@ -20,6 +20,7 @@ Preference {
 
     Text {
         text: root.label
+        color: enabled ? "black" : "gray"
         anchors.verticalCenter: slider.verticalCenter
     }
 
diff --git a/interface/resources/qml/hifi/dialogs/preferences/SpinBox.qml b/interface/resources/qml/hifi/dialogs/preferences/SpinBoxPreference.qml
similarity index 93%
rename from interface/resources/qml/hifi/dialogs/preferences/SpinBox.qml
rename to interface/resources/qml/hifi/dialogs/preferences/SpinBoxPreference.qml
index 9c19b80357..6de465284a 100644
--- a/interface/resources/qml/hifi/dialogs/preferences/SpinBox.qml
+++ b/interface/resources/qml/hifi/dialogs/preferences/SpinBoxPreference.qml
@@ -19,6 +19,7 @@ Preference {
 
     Text {
         text: root.label
+        color: root.enabled ? "black" : "gray"
         anchors.verticalCenter: spinner.verticalCenter
     }
 
diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp
index 4a877a719c..0194e41bc3 100644
--- a/interface/src/ui/PreferencesDialog.cpp
+++ b/interface/src/ui/PreferencesDialog.cpp
@@ -77,8 +77,9 @@ void setupPreferences() {
         preferences->addPreference(new BrowsePreference("Scripts", "Load scripts from this directory:", getter, setter));
     }
 
-    preferences->addPreference(new ButtonPreference("Scripts", "Load Default Scripts"));
-
+    preferences->addPreference(new ButtonPreference("Scripts", "Load Default Scripts", [] {
+        DependencyManager::get<ScriptEngines>()->loadDefaultScripts();
+    }));
 
     {
         auto getter = []()->bool {return !Menu::getInstance()->isOptionChecked(MenuOption::DisableActivityLogger); };
@@ -87,10 +88,11 @@ void setupPreferences() {
     }
     
     static const QString LOD_TUNING("Level of Detail Tuning");
+    CheckPreference* acuityToggle;
     {
         auto getter = []()->bool { return DependencyManager::get<LODManager>()->getUseAcuity(); };
         auto setter = [](bool value) { DependencyManager::get<LODManager>()->setUseAcuity(value); };
-        preferences->addPreference(new CheckPreference(LOD_TUNING, "Render based on visual acuity", getter, setter));
+        preferences->addPreference(acuityToggle = new CheckPreference(LOD_TUNING, "Render based on visual acuity", getter, setter));
     }
 
     {
@@ -100,6 +102,7 @@ void setupPreferences() {
         preference->setMin(0);
         preference->setMax(120);
         preference->setStep(1);
+        preference->setEnabler(acuityToggle);
         preferences->addPreference(preference);
     }
 
@@ -110,6 +113,7 @@ void setupPreferences() {
         preference->setMin(0);
         preference->setMax(120);
         preference->setStep(1);
+        preference->setEnabler(acuityToggle);
         preferences->addPreference(preference);
     }
 
@@ -120,6 +124,7 @@ void setupPreferences() {
         preference->setMin(5);
         preference->setMax(32768);
         preference->setStep(1);
+        preference->setEnabler(acuityToggle, true);
         preferences->addPreference(preference);
     }
 
diff --git a/libraries/shared/src/Preferences.cpp b/libraries/shared/src/Preferences.cpp
index db3b618f2d..4d1703bfea 100644
--- a/libraries/shared/src/Preferences.cpp
+++ b/libraries/shared/src/Preferences.cpp
@@ -28,3 +28,24 @@ void Preferences::addPreference(Preference* preference) {
     _preferencesByCategory[category] = categoryPreferences;
 }
 
+void Preference::setEnabler(BoolPreference* enabler, bool inverse) {
+    if (_enabler) {
+        disconnect(_enabler);
+        _enabler = nullptr;
+    }
+
+    _enabler = enabler;
+    _enablerInverted = inverse;
+    if (_enabler) {
+        connect(_enabler, &BoolPreference::valueChanged, this, &Preference::onEnablerValueChanged);
+        onEnablerValueChanged();
+    }
+}
+
+void Preference::onEnablerValueChanged() {
+    bool value = _enabler->getValue();
+    if (_enablerInverted) {
+        value = !value;
+    }
+    setEnabled(value);
+}
diff --git a/libraries/shared/src/Preferences.h b/libraries/shared/src/Preferences.h
index 84dd4995ea..5a04b37ca1 100644
--- a/libraries/shared/src/Preferences.h
+++ b/libraries/shared/src/Preferences.h
@@ -35,6 +35,8 @@ private:
     QList<QString> _categories;
 };
 
+class BoolPreference;
+
 class Preference : public QObject {
     Q_OBJECT
     Q_PROPERTY(QString category READ getCategory CONSTANT)
@@ -73,6 +75,8 @@ public:
         }
     }
 
+    void setEnabler(BoolPreference* enabler, bool inverse = false);
+
     virtual Type getType() { return Invalid; };
 
     Q_INVOKABLE virtual void load() {};
@@ -81,21 +85,30 @@ public:
 signals:
     void enabledChanged();
 
+private slots:
+    void onEnablerValueChanged();
+
 protected:
     virtual void emitValueChanged() {};
 
+    BoolPreference* _enabler { nullptr };
     const QString _category;
     const QString _name;
     bool _enabled { true };
+    bool _enablerInverted { false };
 };
 
 class ButtonPreference : public Preference {
     Q_OBJECT
 public:
-    ButtonPreference(const QString& category, const QString& name)
-        : Preference(category, name) { }
+    using Lambda = std::function<void()>;
+    ButtonPreference(const QString& category, const QString& name, Lambda triggerHandler)
+        : Preference(category, name), _triggerHandler(triggerHandler) { }
     Type getType() { return Button; }
+    Q_INVOKABLE void trigger() { _triggerHandler(); }
 
+protected:
+    const Lambda _triggerHandler;
 };
 
 
@@ -108,7 +121,7 @@ public:
     TypedPreference(const QString& category, const QString& name, Getter getter, Setter setter)
         : Preference(category, name), _getter(getter), _setter(setter) { }
 
-    T getValue() const { return _getter(); }
+    T getValue() const { return _value; }
     void setValue(const T& value) { if (_value != value) { _value = value; emitValueChanged(); } }
     void load() override { _value = _getter(); }
     void save() const override { 
diff --git a/tests/ui/qmlscratch.pro b/tests/ui/qmlscratch.pro
index 584a724c14..b3c8be0f22 100644
--- a/tests/ui/qmlscratch.pro
+++ b/tests/ui/qmlscratch.pro
@@ -96,12 +96,19 @@ DISTFILES += \
     ../../interface/resources/qml/hifi/dialogs/preferences/Editable.qml \
     ../../interface/resources/qml/hifi/dialogs/preferences/Slider.qml \
     ../../interface/resources/qml/hifi/dialogs/preferences/Preference.qml \
-    ../../interface/resources/qml/hifi/dialogs/preferences/SpinBox.qml \
     ../../interface/resources/qml/hifi/dialogs/preferences/CheckBox.qml \
     ../../interface/resources/qml/dialogs/fileDialog/FileTableView.qml \
     ../../interface/resources/qml/hifi/dialogs/preferences/Avatar.qml \
     ../../interface/resources/qml/hifi/dialogs/preferences/AvatarBrowser.qml \
-    ../../interface/resources/qml/dialogs/QueryDialog.qml
+    ../../interface/resources/qml/dialogs/QueryDialog.qml \
+    ../../interface/resources/qml/hifi/dialogs/preferences/Button.qml \
+    ../../interface/resources/qml/hifi/dialogs/preferences/AvatarPreference.qml \
+    ../../interface/resources/qml/hifi/dialogs/preferences/BrowsablePreference.qml \
+    ../../interface/resources/qml/hifi/dialogs/preferences/ButtonPreference.qml \
+    ../../interface/resources/qml/hifi/dialogs/preferences/CheckBoxPreference.qml \
+    ../../interface/resources/qml/hifi/dialogs/preferences/EditablePreference.qml \
+    ../../interface/resources/qml/hifi/dialogs/preferences/SliderPreference.qml \
+    ../../interface/resources/qml/hifi/dialogs/preferences/SpinBoxPreference.qml
 
 HEADERS += \
     ../../libraries/ui/src/FileDialogHelper.h