LeechCraft  0.6.70-18450-gabe19ee3b0
Modular cross-platform feature rich live environment.
itemsmodel.h
Go to the documentation of this file.
1 /**********************************************************************
2  * LeechCraft - modular cross-platform feature rich internet client.
3  * Copyright (C) 2006-2014 Georg Rudoy
4  *
5  * Distributed under the Boost Software License, Version 1.0.
6  * (See accompanying file LICENSE or copy at https://www.boost.org/LICENSE_1_0.txt)
7  **********************************************************************/
8 
9 #pragma once
10 
11 #include <util/sll/ctstring.h>
12 #include <util/sll/typegetter.h>
14 
15 namespace LC::Util
16 {
17  template<typename T, int RoleV>
18  struct RoleOf
19  {
20  constexpr static auto Role = RoleV;
21 
22  using Type = T;
23 
24  T Value_ {};
25 
26  RoleOf () = default;
27 
28  RoleOf (const RoleOf& other) = default;
29  RoleOf (RoleOf&& other) = default;
30 
31  RoleOf& operator= (const RoleOf& other) = default;
32  RoleOf& operator= (RoleOf&& other) = default;
33 
34  template<typename U = T>
35  RoleOf (U&& value)
36  : Value_ (std::forward<U> (value))
37  {
38  }
39 
40  template<typename U = T>
41  RoleOf& operator= (U&& value)
42  {
43  Value_ = std::forward<U> (value);
44  return *this;
45  }
46 
47  template<typename U = T>
48  requires requires (T t, U u) { t == u; }
49  bool operator== (const U& value) const
50  {
51  return Value_ == value;
52  }
53 
55  {
56  return Value_;
57  }
58 
59  const T& operator* () const
60  {
61  return Value_;
62  }
63 
65  {
66  return &Value_;
67  }
68 
69  const T* operator-> () const
70  {
71  return &Value_;
72  }
73 
74  operator T () const
75  requires (!std::is_same_v<T, QVariant>)
76  {
77  return Value_;
78  }
79 
80  operator QVariant () const
81  {
82  return Value_;
83  }
84  };
85 
86  namespace detail
87  {
88  constexpr auto GetFieldsCount (auto&& val)
89  {
90  auto&& [...elems] = val;
91  return std::integral_constant<size_t, sizeof... (elems)> {};
92  }
93 
94  template<size_t I>
95  constexpr auto GetFieldAt (auto&& val)
96  {
97  auto&& [...elems] = val;
98  return elems... [I];
99  }
100 
101  template<typename T, size_t I>
102  using FieldType_t = decltype (GetFieldAt<I> (std::declval<T> ()));
103 
104  template<typename T>
105  constexpr size_t FieldsCount_v = decltype (GetFieldsCount (std::declval<T> ()))::value;
106 
107  template<typename T>
108  using FieldGetter_t = QVariant (*) (const T&);
109 
110  template<typename T, size_t Ix>
111  std::pair<int, FieldGetter_t<T>> Role2GetterPair ()
112  {
113  if constexpr (requires { FieldType_t<T, Ix>::Role; })
114  return
115  {
117  +[] (const T& t) { return QVariant::fromValue (*GetFieldAt<Ix> (t)); }
118  };
119  else
120  return { -1, nullptr };
121  }
122 
123  template<typename T>
124  QHash<int, FieldGetter_t<T>> MkGetters ()
125  {
126  return []<size_t... Ixs> (std::index_sequence<Ixs...>)
127  {
128  return QHash<int, FieldGetter_t<T>> { Role2GetterPair<T, Ixs> ()... };
129  } (std::make_index_sequence<FieldsCount_v<T>> {});
130  }
131  }
132 
133  template<auto F>
134  constexpr auto FromField = +[] (const ArgType_t<decltype (F), 0>& t) { return QVariant::fromValue (t.*F); };
135 
136  template<typename T>
138  {
139  public:
141  private:
142  const QHash<int, FieldGetter_t> Role2Getter_;
143  public:
144  explicit RoledItemsModel (QObject *parent = nullptr)
145  : FlatItemsModelTypedBase<T> { QStringList { {} }, parent }
146  , Role2Getter_ { detail::MkGetters<T> () }
147  {
148  }
149 
150  explicit RoledItemsModel (const QHash<int, FieldGetter_t>& getters, QObject *parent = nullptr)
151  : FlatItemsModelTypedBase<T> { QStringList { {} }, parent }
152  , Role2Getter_ { getters }
153  {
154  }
155 
156  template<auto F, typename V>
157  void SetField (int idx, V&& value)
158  {
159  if (this->Items_ [idx].*F == value)
160  return;
161 
162  this->Items_ [idx].*F = std::forward<V> (value);
163  emit this->dataChanged (this->index (idx, 0), this->index (idx, 0),
164  { std::decay_t<decltype (T {}.*F)>::Role });
165  }
166 
167  template<auto... Fs, typename... Vs>
168  void SetFields (int idx, Vs&&... values)
169  {
170  QList<int> changedRoles;
171  changedRoles.reserve (sizeof... (values));
172  (([&, this]
173  {
174  if (this->Items_ [idx].*Fs != std::forward<Vs> (values))
175  {
176  this->Items_ [idx].*Fs = std::forward<Vs> (values);
177  changedRoles << std::decay_t<decltype (T {}.*Fs)>::Role;
178  }
179  } ()), ...);
180 
181  if (!changedRoles.isEmpty ())
182  emit this->dataChanged (this->index (idx, 0), this->index (idx, 0), changedRoles);
183  }
184  protected:
185  QVariant GetData (int row, int, int role) const override
186  {
187  if (const auto getter = Role2Getter_.value (role))
188  return getter (this->Items_.at (row));
189  return {};
190  }
191  };
192 
193 
194  template<CtString RoleArg, auto GetterArg>
196  {
197  static constexpr auto Getter = GetterArg;
198  static constexpr auto Role = RoleArg;
199  };
200 
201  template<CtString RoleArg, auto GetterArg>
203 
204  template<typename T>
206  {
207  public:
209  using FieldsList_t = QVector<QPair<QByteArray, FieldGetter_t>>;
210  private:
211  const QVector<FieldGetter_t> Fields_;
212  const QHash<int, QByteArray> Roles_;
213  public:
214  template<typename... Fields>
215  explicit NamedItemsModel (QObject *parent, Fields...) noexcept
216  : FlatItemsModelTypedBase<T> { QStringList { {} }, parent }
217  , Fields_ { +[] (const T& t) -> QVariant { return t.*Fields::Getter; }... }
218  , Roles_ { MakeRoles ({ ToByteArray<Fields::Role> ()... }) }
219  {
220  }
221 
222  QHash<int, QByteArray> roleNames () const override
223  {
224  return Roles_;
225  }
226  protected:
227  QVariant GetData (int row, int, int role) const override
228  {
229  if (const auto getter = Fields_.value (role - this->DataRole - 1))
230  return getter (this->Items_.at (row));
231  return {};
232  }
233  private:
234  QHash<int, QByteArray> MakeRoles (QVector<QByteArray> fields) const
235  {
236  auto result = FlatItemsModelTypedBase<T>::roleNames ();
237  result.reserve (result.size () + fields.size ());
238  for (int i = 0; i < fields.size (); ++i)
239  result [this->DataRole + i + 1] = std::move (fields [i]);
240  return result;
241  }
242  };
243 
244  template<auto Getter>
245  struct Field
246  {
247  QString Name_;
248  };
249 
250  namespace detail
251  {
252  template<Qt::ItemDataRole Role>
253  using RoleTag = std::integral_constant<Qt::ItemDataRole, Role>;
254 
255  struct Extension
256  {
257  explicit Extension (auto&&...) {}
258 
259  static Qt::ItemFlags GetFlags (auto&&...) { return {}; }
260  static bool SetData (auto&&...) { return false; }
261  static void GetDataForRole () {}
262  };
263 
264  template<typename P>
266  {
267  struct Param
268  {
270  };
271 
273 
274  template<typename... Params>
275  requires (std::is_same_v<Param, Params> || ...)
276  explicit ParameterizedExtension (const std::tuple<Params...>& args)
277  : Param_ { std::get<Param> (args).Param_ }
278  {
279  }
280  };
281  }
282 
283  template<auto IconField>
285  {
286  using Extension::Extension;
287 
288  static QVariant GetDataForRole (detail::RoleTag<Qt::DecorationRole>, const auto& item, int column)
289  {
290  if (column)
291  return {};
292  return item.*IconField;
293  }
294  };
295 
297  {
298  using ParameterizedExtension::ParameterizedExtension;
299 
300  Qt::ItemFlags GetFlags (int column) const
301  {
302  return Param_.contains (column) ? Qt::ItemIsEditable : Qt::ItemFlags {};
303  }
304  };
305 
306  template<auto CheckField>
308  {
309  using Extension::Extension;
310 
311  static Qt::ItemFlags GetFlags (int column)
312  {
313  return column ? Qt::ItemFlags {} : Qt::ItemIsUserCheckable;
314  }
315 
316  static QVariant GetDataForRole (detail::RoleTag<Qt::CheckStateRole>, const auto& item, int, int column)
317  {
318  if (column)
319  return QVariant {};
320 
321  if constexpr (std::is_same_v<std::decay_t<decltype (item.*CheckField)>, Qt::CheckState>)
322  return item.*CheckField;
323  else if constexpr (std::is_same_v<std::decay_t<decltype (item.*CheckField)>, bool>)
324  return item.*CheckField ? Qt::Checked : Qt::Unchecked;
325  else
326  static_assert (false, "expected Qt::CheckState or bool field");
327  }
328 
329  template<typename Item>
330  static bool SetData (Item& item, int, int column, const QVariant& value, int role)
331  {
332  if (role != Qt::CheckStateRole || column)
333  return false;
334 
335  const auto state = value.value<Qt::CheckState> ();
336  if constexpr (std::is_same_v<std::decay_t<decltype (item.*CheckField)>, Qt::CheckState>)
337  item.*CheckField = state;
338  else if constexpr (std::is_same_v<std::decay_t<decltype (item.*CheckField)>, bool>)
339  item.*CheckField = state == Qt::Checked;
340  else
341  static_assert (false, "expected Qt::CheckState or bool field");
342  return true;
343  }
344  };
345 
346  struct NoField {};
347  inline constexpr auto NoField_v = NoField {};
348 
349  template<>
351  {
352  QHash<int, Qt::CheckState> RowsStates_;
353 
354  using ParameterizedExtension::ParameterizedExtension;
355 
356  static Qt::ItemFlags GetFlags (int column)
357  {
358  return column ? Qt::ItemFlags {} : Qt::ItemIsUserCheckable;
359  }
360 
361  bool IsChecked (int row) const
362  {
363  return RowsStates_.value (row, Param_) == Qt::Checked;
364  }
365 
366  QVariant GetDataForRole (detail::RoleTag<Qt::CheckStateRole>, const auto&, int row, int column)
367  {
368  return column ? QVariant {} : RowsStates_.value (row, Param_);
369  }
370 
371  template<typename Item>
372  bool SetData (Item&, int row, int column, const QVariant& value, int role)
373  {
374  if (role != Qt::CheckStateRole || column)
375  return false;
376 
377  RowsStates_ [row] = value.value<Qt::CheckState> ();
378  return true;
379  }
380  };
381 
382  template<typename T, typename... Extensions>
384  , public Extensions...
385  {
386  using FieldGetter_t = QVariant (*) (const T&);
387  const QVector<FieldGetter_t> Fields_;
388 
389  using FieldSetter_t = void (*) (T&, const QVariant&);
390  const QVector<FieldSetter_t> Setters_;
391  public:
392  template<auto... Getter>
393  explicit ItemsModel (const Field<Getter>&... fields)
394  : ItemsModel { std::tuple {}, fields... }
395  {
396  }
397 
398  template<auto... Member, typename... ExtParams>
399  explicit ItemsModel (const std::tuple<ExtParams...>& extParams, const Field<Member>&... fields)
400  : FlatItemsModelTypedBase<T> { { fields.Name_... } }
401  , Extensions { extParams }...
402  , Fields_ { +[] (const T& t) -> QVariant { return t.*Member; }... }
403  , Setters_ { +[] (T& t, const QVariant& v) { t.*Member = v.value<std::decay_t<decltype (t.*Member)>> (); }... }
404  {
405  }
406 
407  Qt::ItemFlags flags (const QModelIndex& index) const override
408  {
410  flags |= (Extensions::GetFlags (index.column ()) | ...);
411  return flags;
412  }
413 
414  bool setData (const QModelIndex& index, const QVariant& value, int role) override
415  {
416  auto& item = this->Items_ [index.row ()];
417  if ((Extensions::SetData (item, index.row (), index.column (), value, role) ||...))
418  {
419  emit this->dataChanged (index, index);
420  return true;
421  }
422 
423  if (role != Qt::EditRole)
424  return false;
425 
426  Setters_ [index.column ()] (item, value);
427  emit this->dataChanged (index, index);
428  return true;
429  }
430  protected:
431  QVariant GetData (int row, int column, int role) const override
432  {
433  const auto& item = this->Items_ [row];
434 
435  switch (role)
436  {
437  case Qt::DisplayRole:
438  case Qt::EditRole:
439  if (const auto getter = Fields_.value (column))
440  return getter (item);
441  return {};
442  case Qt::CheckStateRole:
443  return this->GetDataForRole (detail::RoleTag<Qt::CheckStateRole> {}, item, row, column);
444  case Qt::DecorationRole:
445  return this->GetDataForRole (detail::RoleTag<Qt::DecorationRole> {}, item, row, column);
446  default:
447  return {};
448  }
449  }
450 
451  using Extensions::GetDataForRole...;
452 
453  static QVariant GetDataForRole (auto&&...)
454  {
455  return {};
456  }
457  };
458 }
static QVariant GetDataForRole(detail::RoleTag< Qt::CheckStateRole >, const auto &item, int, int column)
Definition: itemsmodel.h:316
constexpr auto NoField_v
Definition: itemsmodel.h:347
NamedItemsModel(QObject *parent, Fields...) noexcept
Definition: itemsmodel.h:215
ItemsModel(const Field< Getter > &... fields)
Definition: itemsmodel.h:393
QModelIndex index(int row, int col, const QModelIndex &parent={}) const override
RoleOf & operator=(const RoleOf &other)=default
RoledItemsModel(QObject *parent=nullptr)
Definition: itemsmodel.h:144
bool setData(const QModelIndex &index, const QVariant &value, int role) override
Definition: itemsmodel.h:414
RoleOf(U &&value)
Definition: itemsmodel.h:35
std::integral_constant< Qt::ItemDataRole, Role > RoleTag
Definition: itemsmodel.h:253
QVariant GetData(int row, int, int role) const override
Definition: itemsmodel.h:227
static Qt::ItemFlags GetFlags(int column)
Definition: itemsmodel.h:311
static QVariant GetDataForRole(detail::RoleTag< Qt::DecorationRole >, const auto &item, int column)
Definition: itemsmodel.h:288
class UTIL_XDG_API Item
Definition: itemsfinder.h:19
QHash< int, FieldGetter_t< T > > MkGetters()
Definition: itemsmodel.h:124
static Qt::ItemFlags GetFlags(int column)
Definition: itemsmodel.h:356
QVariant GetData(int row, int, int role) const override
Definition: itemsmodel.h:185
STL namespace.
QVariant GetData(int row, int column, int role) const override
Definition: itemsmodel.h:431
QVariant(*)(const T &) FieldGetter_t
Definition: itemsmodel.h:108
QHash< int, Qt::CheckState > RowsStates_
Definition: itemsmodel.h:352
requires(std::is_same_v< Param, Params >||...) explicit ParameterizedExtension(const std
Definition: itemsmodel.h:275
constexpr detail::ExprTree< detail::ExprType::LeafStaticPlaceholder, detail::MemberPtrs< Ptrs... > > tuple
Definition: oral.h:1086
static constexpr auto Role
Definition: itemsmodel.h:198
void SetFields(int idx, Vs &&... values)
Definition: itemsmodel.h:168
requires requires(T t, U u)
Definition: itemsmodel.h:48
QVariant GetDataForRole(detail::RoleTag< Qt::CheckStateRole >, const auto &, int row, int column)
Definition: itemsmodel.h:366
NamedMemberField< RoleArg, GetterArg > NamedMemberField_v
Definition: itemsmodel.h:202
Qt::ItemFlags flags(const QModelIndex &index) const override
Definition: itemsmodel.h:407
decltype(GetFieldAt< I >(std::declval< T >())) FieldType_t
Definition: itemsmodel.h:102
RoledItemsModel(const QHash< int, FieldGetter_t > &getters, QObject *parent=nullptr)
Definition: itemsmodel.h:150
static QVariant GetDataForRole(auto &&...)
Definition: itemsmodel.h:453
static void GetDataForRole()
Definition: itemsmodel.h:261
detail::FieldGetter_t< T > FieldGetter_t
Definition: itemsmodel.h:208
static bool SetData(auto &&...)
Definition: itemsmodel.h:260
constexpr size_t FieldsCount_v
Definition: itemsmodel.h:105
QVector< QPair< QByteArray, FieldGetter_t > > FieldsList_t
Definition: itemsmodel.h:209
QModelIndex parent(const QModelIndex &) const override
detail::FieldGetter_t< Item > FieldGetter_t
Definition: itemsmodel.h:140
static bool SetData(Item &item, int, int column, const QVariant &value, int role)
Definition: itemsmodel.h:330
requires(Tup1Size==Tup2Size) const expr auto ZipWith(Tup1 &&tup1
Fields_t Fields_
void SetField(int idx, V &&value)
Definition: itemsmodel.h:157
Tag P(Nodes &&children)
Definition: xmlnode.cpp:165
constexpr auto FromField
Definition: itemsmodel.h:134
std::tuple_element_t< Idx+1, detail::CallTypeGetter_t< F > > ArgType_t
Definition: typegetter.h:49
std::pair< int, FieldGetter_t< T > > Role2GetterPair()
Definition: itemsmodel.h:111
bool operator==(const U &value) const
Definition: itemsmodel.h:49
bool SetData(Item &, int row, int column, const QVariant &value, int role)
Definition: itemsmodel.h:372
auto Tup2 &&tup2 noexcept
Definition: ctstringutils.h:68
constexpr detail::MemberPtrs< Ptrs... > fields
Definition: oral.h:1089
Qt::ItemFlags GetFlags(int column) const
Definition: itemsmodel.h:300
constexpr auto GetFieldsCount(auto &&val)
Definition: itemsmodel.h:88
static Qt::ItemFlags GetFlags(auto &&...)
Definition: itemsmodel.h:259
RoleOf()=default
ItemsModel(const std::tuple< ExtParams... > &extParams, const Field< Member > &... fields)
Definition: itemsmodel.h:399
constexpr auto GetFieldAt(auto &&val)
Definition: itemsmodel.h:95
QHash< int, QByteArray > roleNames() const override
Definition: itemsmodel.h:222
static constexpr auto Role
Definition: itemsmodel.h:20
static constexpr auto DataRole
static constexpr auto Getter
Definition: itemsmodel.h:197