Overte C++ Documentation
Preferences.h
1 //
2 // Created by Bradley Austin Davis 2016/01/20
3 // Copyright 2015 High Fidelity, Inc.
4 //
5 // Distributed under the Apache License, Version 2.0.
6 // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
7 //
8 
9 #pragma once
10 #ifndef hifi_Shared_Preferences_h
11 #define hifi_Shared_Preferences_h
12 
13 #include <functional>
14 #include <QtCore/QObject>
15 #include <QtCore/QVariant>
16 #include <QtCore/QList>
17 #include <QtCore/QString>
18 #include <QtCore/QVariantMap>
19 
20 #include "DependencyManager.h"
21 
22 class Preference;
23 
24 class Preferences : public QObject, public Dependency {
25  Q_OBJECT
26  Q_PROPERTY(QVariantMap preferencesByCategory READ getPreferencesByCategory CONSTANT)
27  Q_PROPERTY(QList<QString> categories READ getCategories CONSTANT)
28 
29 public:
30  void addPreference(Preference* preference);
31  const QVariantMap& getPreferencesByCategory() { return _preferencesByCategory; }
32  const QList<QString>& getCategories() { return _categories; }
33 
34 private:
35  QVariantMap _preferencesByCategory;
36  QList<QString> _categories;
37 };
38 
39 class BoolPreference;
40 
41 class Preference : public QObject {
42  Q_OBJECT
43  Q_PROPERTY(QString category READ getCategory CONSTANT)
44  Q_PROPERTY(QString name READ getName CONSTANT)
45  Q_PROPERTY(Type type READ getType CONSTANT)
46  Q_PROPERTY(bool enabled READ isEnabled NOTIFY enabledChanged)
47  Q_ENUMS(Type)
48 
49 public:
50  enum Type {
51  Invalid,
52  Editable,
53  Browsable,
54  Slider,
55  Spinner,
56  SpinnerSlider,
57  Checkbox,
58  Button,
59  ComboBox,
60  PrimaryHand,
61  // Special casing for an unusual preference
62  Avatar,
63  RadioButtons
64  };
65 
66  explicit Preference(QObject* parent = nullptr) : QObject(parent) {}
67  Preference(const QString& category, const QString& name, QObject* parent = nullptr)
68  : QObject(parent), _category(category), _name(name) { }
69 
70  const QString& getCategory() const { return _category; }
71  const QString& getName() const { return _name; }
72  bool isEnabled() const {
73  return _enabled;
74  }
75 
76  void setEnabled(bool enabled) {
77  if (enabled != _enabled) {
78  _enabled = enabled;
79  emit enabledChanged();
80  }
81  }
82 
83  void setEnabler(BoolPreference* enabler, bool inverse = false);
84  virtual Type getType() { return Invalid; };
85 
86  Q_INVOKABLE virtual void load() {};
87  Q_INVOKABLE virtual void save() const {}
88 
89 signals:
90  void enabledChanged();
91 
92 private slots:
93  void onEnablerValueChanged();
94 
95 protected:
96  virtual void emitValueChanged() {};
97 
98  BoolPreference* _enabler { nullptr };
99  const QString _category;
100  const QString _name;
101  bool _enabled { true };
102  bool _enablerInverted { false };
103 };
104 
105 class ButtonPreference : public Preference {
106  Q_OBJECT
107 public:
108  using Lambda = std::function<void()>;
109  ButtonPreference(const QString& category, const QString& name, Lambda triggerHandler)
110  : Preference(category, name), _triggerHandler(triggerHandler) { }
111  Type getType() override { return Button; }
112  Q_INVOKABLE void trigger() { _triggerHandler(); }
113 
114 protected:
115  const Lambda _triggerHandler;
116 };
117 
118 class BoolPreference : public Preference {
119  Q_OBJECT
120  Q_PROPERTY(bool value READ getValue WRITE setValue NOTIFY valueChanged)
121 
122 public:
123  using Getter = std::function<bool()>;
124  using Setter = std::function<void(const bool&)>;
125 
126  BoolPreference(const QString& category, const QString& name, Getter getter, Setter setter)
127  : Preference(category, name), _getter(getter), _setter(setter) { }
128 
129  bool getValue() const { return _value; }
130  void setValue(const bool& value) { if (_value != value) { _value = value; emitValueChanged(); } }
131  void load() override { _value = _getter(); }
132  void save() const override {
133  bool oldValue = _getter();
134  if (_value != oldValue) {
135  _setter(_value);
136  }
137  }
138 
139 signals:
140  void valueChanged();
141 
142 protected:
143  bool _value;
144  const Getter _getter;
145  const Setter _setter;
146 
147  void emitValueChanged() override { emit valueChanged(); }
148 };
149 
150 class FloatPreference : public Preference {
151  Q_OBJECT
152  Q_PROPERTY(float value READ getValue WRITE setValue NOTIFY valueChanged)
153  Q_PROPERTY(float min READ getMin CONSTANT)
154  Q_PROPERTY(float max READ getMax CONSTANT)
155  Q_PROPERTY(float step READ getStep CONSTANT)
156  Q_PROPERTY(uint decimals READ getDecimals CONSTANT)
157 
158 public:
159  using Getter = std::function<float()>;
160  using Setter = std::function<void(const float&)>;
161 
162  FloatPreference(const QString& category, const QString& name, Getter getter, Setter setter)
163  : Preference(category, name), _getter(getter), _setter(setter) { }
164 
165  float getValue() const { return _value; }
166  void setValue(const float& value) { if (_value != value) { _value = value; emitValueChanged(); } }
167  void load() override { _value = _getter(); }
168  void save() const override {
169  float oldValue = _getter();
170  if (_value != oldValue) {
171  _setter(_value);
172  }
173  }
174 
175  float getMin() const { return _min; }
176  void setMin(float min) { _min = min; };
177 
178  float getMax() const { return _max; }
179  void setMax(float max) { _max = max; };
180 
181  float getStep() const { return _step; }
182  void setStep(float step) { _step = step; };
183 
184  float getDecimals() const { return _decimals; }
185  void setDecimals(float decimals) { _decimals = decimals; };
186 
187 signals:
188  void valueChanged();
189 
190 protected:
191  void emitValueChanged() override { emit valueChanged(); }
192 
193  float _value;
194  const Getter _getter;
195  const Setter _setter;
196 
197  uint _decimals { 0 };
198  float _min { 0 };
199  float _max { 1 };
200  float _step { 1 };
201 };
202 
203 class IntPreference : public Preference {
204  Q_OBJECT
205  Q_PROPERTY(float value READ getValue WRITE setValue NOTIFY valueChanged)
206  Q_PROPERTY(float min READ getMin CONSTANT)
207  Q_PROPERTY(float max READ getMax CONSTANT)
208  Q_PROPERTY(float step READ getStep CONSTANT)
209  Q_PROPERTY(int decimals READ getDecimals CONSTANT)
210 
211 public:
212  using Getter = std::function<int()>;
213  using Setter = std::function<void(const int&)>;
214 
215  IntPreference(const QString& category, const QString& name, Getter getter, Setter setter)
216  : Preference(category, name), _getter(getter), _setter(setter) { }
217 
218  int getValue() const { return _value; }
219  void setValue(const int& value) { if (_value != value) { _value = value; emitValueChanged(); } }
220  void load() override { _value = _getter(); }
221  void save() const override {
222  int oldValue = _getter();
223  if (_value != oldValue) {
224  _setter(_value);
225  }
226  }
227 
228  float getMin() const { return _min; }
229  void setMin(float min) { _min = min; };
230 
231  float getMax() const { return _max; }
232  void setMax(float max) { _max = max; };
233 
234  float getStep() const { return _step; }
235  void setStep(float step) { _step = step; };
236 
237  int getDecimals() const { return _decimals; }
238  void setDecimals(int decimals) { _decimals = decimals; };
239 
240 signals:
241  void valueChanged();
242 
243 protected:
244  int _value;
245  const Getter _getter;
246  const Setter _setter;
247 
248  void emitValueChanged() override { emit valueChanged(); }
249 
250  int _min { std::numeric_limits<int>::min() };
251  int _max { std::numeric_limits<int>::max() };
252  int _step { 1 };
253  int _decimals { 0 };
254 };
255 
256 class StringPreference : public Preference {
257  Q_OBJECT
258  Q_PROPERTY(QString value READ getValue WRITE setValue NOTIFY valueChanged)
259 
260 public:
261  using Getter = std::function<QString()>;
262  using Setter = std::function<void(const QString&)>;
263 
264  StringPreference(const QString& category, const QString& name, Getter getter, Setter setter)
265  : Preference(category, name), _getter(getter), _setter(setter) { }
266 
267 
268  QString getValue() const { return _value; }
269  void setValue(const QString& value) { if (_value != value) { _value = value; emitValueChanged(); } }
270  void load() override { _value = _getter(); }
271  void save() const override {
272  QString oldValue = _getter();
273  if (_value != oldValue) {
274  _setter(_value);
275  }
276  }
277 
278 signals:
279  void valueChanged();
280 
281 protected:
282  void emitValueChanged() override { emit valueChanged(); }
283 
284  QString _value;
285  const Getter _getter;
286  const Setter _setter;
287 };
288 
289 class SliderPreference : public FloatPreference {
290  Q_OBJECT
291 public:
292  SliderPreference(const QString& category, const QString& name, Getter getter, Setter setter)
293  : FloatPreference(category, name, getter, setter) { }
294 
295  Type getType() override { return Slider; }
296 };
297 
298 class SpinnerPreference : public FloatPreference {
299  Q_OBJECT
300 public:
301  SpinnerPreference(const QString& category, const QString& name, Getter getter, Setter setter)
302  : FloatPreference(category, name, getter, setter) { }
303 
304  Type getType() override { return Spinner; }
305 };
306 
307 class SpinnerSliderPreference : public FloatPreference {
308  Q_OBJECT
309 public:
310  SpinnerSliderPreference(const QString& category, const QString& name, Getter getter, Setter setter)
311  : FloatPreference(category, name, getter, setter) { }
312 
313  Type getType() override { return SpinnerSlider; }
314 };
315 
316 class IntSpinnerPreference : public IntPreference {
317  Q_OBJECT
318 public:
319  IntSpinnerPreference(const QString& category, const QString& name, Getter getter, Setter setter)
320  : IntPreference(category, name, getter, setter) { }
321 
322  Type getType() override { return Spinner; }
323 };
324 
325 class EditPreference : public StringPreference {
326  Q_OBJECT
327  Q_PROPERTY(QString placeholderText READ getPlaceholderText CONSTANT)
328 
329 public:
330  EditPreference(const QString& category, const QString& name, Getter getter, Setter setter)
331  : StringPreference(category, name, getter, setter) { }
332  Type getType() override { return Editable; }
333  const QString& getPlaceholderText() const { return _placeholderText; }
334  void setPlaceholderText(const QString& placeholderText) { _placeholderText = placeholderText; }
335 
336 protected:
337  QString _placeholderText;
338 };
339 
340 class ComboBoxPreference : public EditPreference {
341  Q_OBJECT
342  Q_PROPERTY(QStringList items READ getItems CONSTANT)
343 
344 public:
345  ComboBoxPreference(const QString& category, const QString& name, Getter getter, Setter setter)
346  : EditPreference(category, name, getter, setter) { }
347  Type getType() override { return ComboBox; }
348 
349  const QStringList& getItems() { return _items; }
350  void setItems(const QStringList& items) { _items = items; }
351 
352 protected:
353  QStringList _items;
354 };
355 
356 class BrowsePreference : public EditPreference {
357  Q_OBJECT
358  Q_PROPERTY(QString browseLabel READ getBrowseLabel CONSTANT)
359 
360 public:
361  BrowsePreference(const QString& category, const QString& name, Getter getter, Setter setter)
362  : EditPreference(category, name, getter, setter) { }
363  Type getType() override { return Browsable; }
364 
365  const QString& getBrowseLabel() { return _browseLabel; }
366  void setBrowseLabel(const QString& browseLabel) { _browseLabel = browseLabel; }
367 
368 protected:
369  QString _browseLabel { "Browse" };
370 };
371 
372 class AvatarPreference : public BrowsePreference {
373  Q_OBJECT
374 public:
375  AvatarPreference(const QString& category, const QString& name, Getter getter, Setter setter)
376  : BrowsePreference(category, name, getter, setter) {
377  _browseLabel = "Change";
378  }
379  Type getType() override { return Avatar; }
380 };
381 
382 
383 class CheckPreference : public BoolPreference {
384  Q_OBJECT
385  Q_PROPERTY(bool indented READ getIndented CONSTANT)
386 public:
387  using Getter = std::function<bool()>;
388  using Setter = std::function<void(const bool&)>;
389 
390  CheckPreference(const QString& category, const QString& name, Getter getter, Setter setter)
391  : BoolPreference(category, name, getter, setter) { }
392  Type getType() override { return Checkbox; }
393 
394  bool getIndented() { return _isIndented; }
395  void setIndented(const bool indented) { _isIndented = indented; }
396 protected:
397  bool _isIndented { false };
398 };
399 
400 class PrimaryHandPreference : public StringPreference {
401  Q_OBJECT
402 public:
403  PrimaryHandPreference(const QString& category, const QString& name, Getter getter, Setter setter)
404  : StringPreference(category, name, getter, setter) { }
405  Type getType() override { return PrimaryHand; }
406 };
407 
408 class RadioButtonsPreference : public IntPreference {
409  Q_OBJECT
410  Q_PROPERTY(QString heading READ getHeading CONSTANT)
411  Q_PROPERTY(QStringList items READ getItems CONSTANT)
412  Q_PROPERTY(bool indented READ getIndented CONSTANT)
413 public:
414  RadioButtonsPreference(const QString& category, const QString& name, Getter getter, Setter setter)
415  : IntPreference(category, name, getter, setter) { }
416  Type getType() override { return RadioButtons; }
417 
418  const QString& getHeading() { return _heading; }
419  const QStringList& getItems() { return _items; }
420  void setHeading(const QString& heading) { _heading = heading; }
421  void setItems(const QStringList& items) { _items = items; }
422  bool getIndented() const { return _indented; }
423  void setIndented(const bool indented) { _indented = indented; }
424 
425 protected:
426  QString _heading;
427  QStringList _items;
428  bool _indented { false };
429 };
430 #endif
431 
432