QtMvvm  1.1.0
A mvvm oriented library for Qt, to create Projects for Widgets and Quick in parallel
settingsentry.h
1 #ifndef QTMVVM_SETTINGSENTRY_H
2 #define QTMVVM_SETTINGSENTRY_H
3 
4 #include <functional>
5 
6 #include <QtCore/qlist.h>
7 #include <QtCore/qregularexpression.h>
8 #include <QtCore/qhash.h>
9 #include <QtCore/qsharedpointer.h>
10 
11 #include "QtMvvmCore/qtmvvmcore_global.h"
12 #include "QtMvvmCore/isettingsaccessor.h"
13 
14 namespace QtMvvm {
15 
17 template <typename T>
19 {
20  Q_DISABLE_COPY(SettingsEntry)
21 
22 public:
23  SettingsEntry() = default;
24 
26  bool isSet() const;
28  QString key() const;
29 
31  T get() const;
33  void set(const T &value);
35  void reset();
36 
38  SettingsEntry<T> &operator=(const T &value);
40  operator T() const;
41 
43  void addChangeCallback(const std::function<void(T)> &callback);
45  void addChangeCallback(QObject *scope, const std::function<void(T)> &callback);
46 
48  void setup(QString key, ISettingsAccessor *accessor, QVariant defaultValue = {});
49 
50 private:
51  QString _key;
52  ISettingsAccessor *_accessor = nullptr;
53  QVariant _default;
54 };
55 
57 template <>
58 class SettingsEntry<void>
59 {
60  Q_DISABLE_COPY(SettingsEntry)
61 
62 public:
63  inline SettingsEntry() = default;
64 
66  inline void setup(const QString &, ISettingsAccessor *, const QVariant & = {}) {}
67 };
68 
70 template <typename TType>
72 {
73  Q_DISABLE_COPY(SettingsListNode)
74 
75 public:
77  class Deferred
78  {
79  Q_DISABLE_COPY(Deferred)
80 
81  public:
83  inline Deferred(Deferred &&other) noexcept = default;
85  inline Deferred &operator=(Deferred &&other) noexcept = default;
86  inline ~Deferred() { commit(); }
87 
89  inline TType &element() { return _element; }
90 
92  inline TType &operator*() { return _element; }
94  inline TType *operator->() { return &_element; }
95 
97  inline void commit() { if(!_commited) { _commited = true; _node->commit(_index);} }
98 
99  private:
100  friend class SettingsListNode<TType>;
101 
103  TType &_element;
104  bool _commited = false;
105  int _index;
106 
107  inline Deferred(SettingsListNode<TType> *node, TType &element, int index) :
108  _node{node},
109  _element{element},
110  _index{index}
111  {}
112  };
113 
115  template <typename T>
117  {
118  public:
120  using iterator_category = std::random_access_iterator_tag;
122  using difference_type = int;
124  using value_type = T;
126  using pointer = value_type*;
128  using reference = value_type&;
129 
131  inline iterator_base() = default;
133  inline iterator_base(const iterator_base<T> &other) = default;
135  inline iterator_base &operator=(const iterator_base<T> &other) = default;
137  inline iterator_base(iterator_base<T> &&other) noexcept = default;
139  inline iterator_base &operator=(iterator_base<T> &&other) noexcept = default;
140 
142  inline iterator_base<T> &operator++() { ++_index; return *this; }
144  inline iterator_base<T> operator++(int) { return iterator_base<T>{_node, _index++}; }
146  inline iterator_base<T> &operator--() { --_index; return *this; }
148  inline iterator_base<T> operator--(int) { return iterator_base<T>{_node, _index--}; }
149 
151  inline reference operator*() const { return _node->at(_index); }
153  inline pointer operator->() const { return &_node->at(_index); }
155  inline friend void swap(iterator_base<T> &lhs, iterator_base<T> &rhs) noexcept { std::swap(lhs._node, rhs._node); std::swap(lhs._index, rhs._index); }
156 
158  inline friend bool operator==(const iterator_base<T> &lhs, const iterator_base<T> &rhs) { assert(lhs._node == rhs._node); return lhs._index == rhs._index; }
160  inline friend bool operator!=(const iterator_base<T> &lhs, const iterator_base<T> &rhs) { assert(lhs._node == rhs._node); return lhs._index != rhs._index; }
162  inline friend bool operator<(const iterator_base<T> &lhs, const iterator_base<T> &rhs) { assert(lhs._node == rhs._node); return lhs._index < rhs._index; }
164  inline friend bool operator>(const iterator_base<T> &lhs, const iterator_base<T> &rhs) { assert(lhs._node == rhs._node); return lhs._index > rhs._index; }
166  inline friend bool operator<=(const iterator_base<T> &lhs, const iterator_base<T> &rhs) { assert(lhs._node == rhs._node); return lhs._index <= rhs._index; }
168  inline friend bool operator>=(const iterator_base<T> &lhs, const iterator_base<T> &rhs) { assert(lhs._node == rhs._node); return lhs._index >= rhs._index; }
169 
171  inline iterator_base<T> &operator+=(difference_type delta) { _index += delta; return *this; }
173  inline friend iterator_base<T> operator+(const iterator_base<T> &iter, difference_type delta) { return iterator_base<T>{iter._node, iter._index + delta}; }
175  inline friend iterator_base<T> operator+(difference_type delta, const iterator_base<T> &iter) { return iterator_base<T>{iter._node, iter._index + delta}; }
177  inline iterator_base<T> &operator-=(difference_type delta) { _index -= delta; return *this; }
179  inline friend iterator_base<T> operator-(const iterator_base<T> &iter, difference_type delta) { return iterator_base<T>{iter._node, iter._index - delta}; }
181  inline friend difference_type operator-(const iterator_base<T> &lhs, const iterator_base<T> &rhs) { assert(lhs._node == rhs._node); return lhs._index - rhs._index; }
182 
184  inline reference operator[](difference_type delta) const { return _node->at(_index + delta); }
185 
186  private:
187  friend class SettingsListNode<TType>;
188 
190  int _index;
191 
192  inline iterator_base(SettingsListNode<TType> *node, int index) :
193  _node{node},
194  _index{index}
195  {}
196  };
197 
202 
203  SettingsListNode() = default;
204 
206  bool isSet() const;
208  QString key() const;
210  int size() const;
212  const TType &at(int index) const;
214  TType &at(int index);
215 
217  TType &push();
221  void pop(int count = 1);
223  void reset();
224 
226  TType &operator[](int index);
228  const TType &operator[](int index) const;
229 
231  iterator begin();
233  iterator end();
235  const_iterator begin() const;
237  const_iterator end() const;
239  const_iterator constBegin() const;
241  const_iterator constEnd() const;
242 
244  void addChangeCallback(const std::function<void(int)> &callback); // size
246  void addChangeCallback(QObject *scope, const std::function<void(int)> &callback);
247 
249  void setup(QString key, ISettingsAccessor *accessor, std::function<void(int, TType&)> setupFn);
251  void commit(int index);
252 
253 private:
254  struct ElementHolder {
255  bool __initialized = false;
256  QSharedPointer<TType> _element;
257  inline ElementHolder() : _element{new TType{}} {}
258  };
259 
260  QString _key;
261  QString _sizeKey;
262  ISettingsAccessor *_accessor = nullptr;
263  std::function<void(int, TType&)> _setupFn;
264  mutable QHash<int, ElementHolder> _cache;
265 };
266 
267 // ------------- Generic Implementation -------------
268 
269 template<typename T>
271 {
272  return _accessor->contains(_key);
273 }
274 
275 template<typename T>
277 {
278  return _key;
279 }
280 
281 template<typename T>
283 {
284  return _accessor->load(_key, _default).template value<T>();
285 }
286 
287 template<>
288 Q_MVVMCORE_EXPORT QVariant SettingsEntry<QVariant>::get() const;
289 
290 template<typename T>
291 void SettingsEntry<T>::set(const T &value)
292 {
293  _accessor->save(_key, QVariant::fromValue(value));
294 }
295 
296 template<>
297 Q_MVVMCORE_EXPORT void SettingsEntry<QVariant>::set(const QVariant &value);
298 
299 template<typename T>
301 {
302  _accessor->remove(_key);
303 }
304 
305 template<typename T>
307 {
308  set(value);
309  return (*this);
310 }
311 
312 template<typename T>
314 {
315  return get();
316 }
317 
318 template<typename T>
319 void SettingsEntry<T>::addChangeCallback(const std::function<void (T)> &callback)
320 {
321  addChangeCallback(_accessor, callback);
322 }
323 
324 template<typename T>
325 void SettingsEntry<T>::addChangeCallback(QObject *scope, const std::function<void (T)> &callback)
326 {
327  auto mKey = _key;
328  auto mDefault = _default;
330  scope, [mKey, callback](const QString &key, const QVariant &value) {
331  if(key == mKey)
332  callback(value.template value<T>());
333  });
335  scope, [mKey, mDefault, callback](const QString &key) {
336  if(key == mKey)
337  callback(mDefault.template value<T>());
338  });
339 }
340 
341 template<>
342 Q_MVVMCORE_EXPORT void SettingsEntry<QVariant>::addChangeCallback(QObject *scope, const std::function<void (QVariant)> &callback);
343 
344 template<typename T>
345 void SettingsEntry<T>::setup(QString key, ISettingsAccessor *accessor, QVariant defaultValue)
346 {
347  Q_ASSERT_X(accessor, Q_FUNC_INFO, "You must set a valid accessor before initializing the settings!");
348  _key = std::move(key);
349  _accessor = accessor;
350  _default = std::move(defaultValue);
351 }
352 
353 // ------------- Generic Implementation ListNode -------------
354 
355 template<typename TType>
357 {
358  return _accessor->contains(_sizeKey);
359 }
360 
361 template<typename TType>
363 {
364  return _key;
365 }
366 
367 template<typename TType>
369 {
370  return _accessor->load(_sizeKey, 0).toInt();
371 }
372 
373 template<typename TType>
374 const TType &SettingsListNode<TType>::at(int index) const
375 {
376  auto &value = _cache[index];
377  if(!value.__initialized) {
378  _setupFn(index, *(value._element));
379  value.__initialized = true;
380  }
381  return *(value._element);
382 }
383 
384 template<typename TType>
386 {
387  auto &value = _cache[index];
388  if(!value.__initialized) {
389  _setupFn(index, *(value._element));
390  value.__initialized = true;
391  }
392  return *(value._element);
393 }
394 
395 template<typename TType>
397 {
398  auto cIndex = size();
399  _accessor->save(_sizeKey, cIndex + 1);
400  return at(cIndex);
401 }
402 
403 template<typename TType>
405 {
406  auto cIndex = size();
407  return {this, at(cIndex), cIndex};
408 }
409 
410 template<typename TType>
412 {
413  auto cSize = size();
414  auto nSize = qMax(size() - count, 0);
415  for(auto i = cSize - 1; i >= nSize; --i)
416  _accessor->remove(_key + QStringLiteral("/%1").arg(i));
417  _accessor->save(_sizeKey, nSize);
418 }
419 
420 template<typename TType>
422 {
423  _accessor->remove(_key);
424 }
425 
426 template<typename TType>
427 const TType &SettingsListNode<TType>::operator[](int index) const
428 {
429  return at(index);
430 }
431 
432 
433 template<typename TType>
435 {
436  return at(index);
437 }
438 
439 template<typename TType>
441 {
442  return iterator{this, 0};
443 }
444 
445 template<typename TType>
447 {
448  return iterator{this, size()};
449 }
450 
451 template<typename TType>
453 {
454  return constBegin();
455 }
456 
457 template<typename TType>
459 {
460  return constEnd();
461 }
462 
463 template<typename TType>
465 {
466  return const_iterator{const_cast<SettingsListNode<TType>*>(this), 0};
467 }
468 
469 template<typename TType>
471 {
472  return const_iterator{const_cast<SettingsListNode<TType>*>(this), size()};
473 }
474 
475 template<typename TType>
476 void SettingsListNode<TType>::addChangeCallback(const std::function<void (int)> &callback)
477 {
478  addChangeCallback(_accessor, callback);
479 }
480 
481 template<typename TType>
482 void SettingsListNode<TType>::addChangeCallback(QObject *scope, const std::function<void (int)> &callback)
483 {
484  QString mKey = _sizeKey;
486  scope, [mKey, callback](const QString &key, const QVariant &value) {
487  if(key == mKey)
488  callback(value.toInt());
489  });
491  scope, [mKey, callback](const QString &key) {
492  if(key == mKey)
493  callback(0);
494  });
495 }
496 
497 template<typename TType>
498 void SettingsListNode<TType>::setup(QString key, ISettingsAccessor *accessor, std::function<void(int, TType&)> setupFn)
499 {
500  Q_ASSERT_X(accessor, Q_FUNC_INFO, "You must set a valid accessor before initializing the settings!");
501  _key = std::move(key);
502  _sizeKey = _key + QStringLiteral("/size");
503  _accessor = accessor;
504  _setupFn = std::move(setupFn);
505 }
506 
507 template<typename TType>
508 void SettingsListNode<TType>::commit(int index)
509 {
510  _accessor->save(_sizeKey, qMax(size(), index + 1));
511 }
512 
513 }
514 
515 
516 #endif // QTMVVM_SETTINGSENTRY_H
pointer operator->() const
Member access operator.
void reset()
Removes the list and all of its elements from the settings.
T get() const
Loads the value from the settings.
Entry container to make deferred creation of a new list element possible.
Definition: settingsentry.h:77
const_iterator constEnd() const
returns an iterator pointing after the end of the list
void addChangeCallback(const std::function< void(T)> &callback)
Adds a method to be called if the entries value changes.
An interface to provide a generic way to access settings of any origin.
iterator_base< T > & operator--()
Posfix decrement operator.
iterator_base & operator=(const iterator_base< T > &other)=default
Copy assignment operator.
Deferred(Deferred &&other) noexcept=default
Move constructor.
friend bool operator!=(const iterator_base< T > &lhs, const iterator_base< T > &rhs)
Inequality operator.
bool isSet() const
Checks if the entry is stored in the settings.
TType & operator[](int index)
Returns a reference to the element at the given position in the list.
TType & push()
Appends a new element to the list and returns a reference to that entry.
friend difference_type operator-(const iterator_base< T > &lhs, const iterator_base< T > &rhs)
Substraction operator.
QString key() const
Returns the key this entry uses to access the settings.
const_iterator constBegin() const
returns an iterator pointing to the beginning of the list
void commit()
Appends the created element to the list.
Definition: settingsentry.h:97
TType * operator->()
Member access operator.
Definition: settingsentry.h:94
friend bool operator>(const iterator_base< T > &lhs, const iterator_base< T > &rhs)
Geater than operator.
void addChangeCallback(const std::function< void(int)> &callback)
Adds a method to be called if the number of elements stored for the list change.
friend iterator_base< T > operator+(difference_type delta, const iterator_base< T > &iter)
Addition operator.
Deferred & operator=(Deferred &&other) noexcept=default
Move assignment operator.
friend bool operator==(const iterator_base< T > &lhs, const iterator_base< T > &rhs)
Equality operator.
bool isSet() const
Checks if the entry that represents the list node is stored in the settings.
int toInt(bool *ok) const const
friend void swap(iterator_base< T > &lhs, iterator_base< T > &rhs) noexcept
Swap operator.
friend bool operator>=(const iterator_base< T > &lhs, const iterator_base< T > &rhs)
Geater equal than operator.
const TType & at(int index) const
Returns a reference to the element at the given position in the list.
A generic wrapper around ISettingsAccessor used by the qsettingsgenerator.
Definition: settingsentry.h:18
iterator end()
returns an iterator pointing after the end of the list
iterator_base< T > & operator++()
Posfix increment operator.
QString key() const
Returns the key this list node uses to access the settings.
iterator begin()
returns an iterator pointing to the beginning of the list
iterator_base< T > & operator+=(difference_type delta)
Compound assignment operator.
friend iterator_base< T > operator-(const iterator_base< T > &iter, difference_type delta)
Substraction operator.
QVariant fromValue(const T &value)
iterator_base< T > operator--(int)
Suffix decrement operator.
void reset()
Removes the entry and all child entries from the settings.
void set(const T &value)
Stores the passed value in the settings.
Deferred push_deferred()
Creates a new element and returns it, but does not push it yet.
iterator_base()=default
Default constructor.
void pop(int count=1)
Removes count elements from the back of the list from the settings.
TType & element()
Returns a reference to the element beeing edited.
Definition: settingsentry.h:89
iterator_base< T > & operator-=(difference_type delta)
Compound assignment operator.
void entryRemoved(const QString &key)
Is emitted whenever a settings value was removed, at least via this instance.
int size() const
Returns the current size of the list, as stored in the settings.
iterator_base< T > operator++(int)
Suffix increment operator.
friend iterator_base< T > operator+(const iterator_base< T > &iter, difference_type delta)
Addition operator.
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
The primary namespace of the QtMvvm library.
TType & operator*()
Indirection operator.
Definition: settingsentry.h:92
The iterator class to iterate through the list nodes entries.
reference operator*() const
Indirection operator.
SettingsEntry< T > & operator=(const T &value)
Stores the passed value in the settings.
void entryChanged(const QString &key, const QVariant &value)
Is emitted whenever a settings value was changed, at least via this instance.
reference operator[](difference_type delta) const
Subscript operator.
A helper class used by the qsettingsgenerator to represent list nodes.
Definition: settingsentry.h:71