Kirigami2

pagerouter.h
1 /*
2  * SPDX-FileCopyrightText: 2020 Carson Black <[email protected]>
3  *
4  * SPDX-License-Identifier: LGPL-2.0-or-later
5  */
6 
7 #pragma once
8 
9 #include <QCache>
10 #include <QQuickItem>
11 #include <QRandomGenerator>
12 #include <QQmlPropertyMap>
13 #include "columnview.h"
14 
15 static std::map<quint32,QVariant> s_knownVariants;
16 class PageRouter;
17 
18 class ParsedRoute : public QObject {
19  Q_OBJECT
20 
21 public:
22  QString name;
23  QVariant data;
24  QVariantMap properties;
25  bool cache;
26  QQuickItem* item = nullptr;
27  void itemDestroyed() {
28  item = nullptr;
29  }
30  QQuickItem* setItem(QQuickItem *newItem) {
31  auto ret = item;
32  if (ret != nullptr) {
33  disconnect(ret, &QObject::destroyed, this, &ParsedRoute::itemDestroyed);
34  }
35  item = newItem;
36  if (newItem != nullptr) {
37  connect(newItem, &QObject::destroyed, this, &ParsedRoute::itemDestroyed);
38  }
39  return ret;
40  }
41  explicit ParsedRoute(const QString& name = QString(), QVariant data = QVariant(), QVariantMap properties = QVariantMap(), bool cache = false, QQuickItem *item = nullptr)
42  : name(name), data(data), properties(properties), cache(cache) {
43  setItem(item);
44  }
45  virtual ~ParsedRoute() {
46  if (item) {
47  item->deleteLater();
48  }
49  }
50  quint32 hash() {
51  for (auto i = s_knownVariants.begin(); i != s_knownVariants.end(); i++) {
52  if (i->second == data) {
53  return i->first;
54  }
55  }
57  while (s_knownVariants.count(number) > 0) {
59  }
60  s_knownVariants[number] = data;
61  return number;
62  }
63  bool equals(const ParsedRoute* rhs, bool countItem = false)
64  {
65  return name == rhs->name &&
66  data == rhs->data &&
67  (!countItem || item == rhs->item) &&
68  cache == rhs->cache;
69  }
70 };
71 
72 struct LRU {
73  int size = 10;
74  QList<QPair<QString,quint32>> evictionList;
75  QMap<QPair<QString,quint32>,int> costs;
76  QMap<QPair<QString,quint32>,ParsedRoute*> items;
77 
78  ParsedRoute* take(QPair<QString,quint32> key) {
79  auto ret = items.take(key);
80  evictionList.removeAll(key);
81  return ret;
82  }
83  int totalCosts() {
84  int ret = 0;
85  for (auto cost : qAsConst(costs)) {
86  ret += cost;
87  }
88  return ret;
89  }
90  void setSize(int size = 10) {
91  this->size = size;
92  prune();
93  }
94  void prune() {
95  while (size < totalCosts()) {
96  auto key = evictionList.last();
97  auto item = items.take(key);
98  delete item;
99  costs.take(key);
100  evictionList.takeLast();
101  }
102  }
103  void insert(QPair<QString,quint32> key, ParsedRoute *newItem, int cost) {
104  if (items.contains(key)) {
105  auto item = items.take(key);
106  evictionList.removeAll(key);
107  if (item != newItem) {
108  delete item;
109  }
110  }
111  costs[key] = cost;
112  items[key] = newItem;
113  evictionList.prepend(key);
114  prune();
115  }
116 };
117 
118 class PageRouterAttached;
119 
131 {
132  Q_OBJECT
133 
139  Q_PROPERTY(QJSValue route MEMBER m_route WRITE setRoute NOTIFY changed)
140  QJSValue m_route;
141 
147  Q_PROPERTY(bool when MEMBER m_when NOTIFY changed)
148  bool m_when;
149 
150  void handleChange();
151  PageRouterAttached* m_parent;
152 
153 public:
155  void setRoute(QJSValue route) {
156  m_route = route;
157  Q_EMIT changed();
158  }
159  PreloadRouteGroup(QObject *parent) : QObject(parent) {
160  m_parent = qobject_cast<PageRouterAttached*>(parent);
161  Q_ASSERT(m_parent);
162  connect(this, &PreloadRouteGroup::changed, this, &PreloadRouteGroup::handleChange);
163  }
164  Q_SIGNAL void changed();
165 };
166 
174 class PageRoute : public QObject
175 {
176  Q_OBJECT
177 
185  Q_PROPERTY(QString name MEMBER m_name READ name)
186 
187 
193  Q_PROPERTY(QQmlComponent* component MEMBER m_component READ component)
194 
210  Q_PROPERTY(bool cache MEMBER m_cache READ cache)
211 
218  Q_PROPERTY(int cost MEMBER m_cost)
219 
220  Q_CLASSINFO("DefaultProperty", "component")
221 
222 Q_SIGNALS:
223  void preloadDataChanged();
224  void preloadChanged();
225 
226 private:
227  QString m_name;
228  QQmlComponent* m_component = nullptr;
229  bool m_cache = false;
230  int m_cost = 1;
231 
232 public:
233  QQmlComponent* component() { return m_component; };
234  QString name() { return m_name; };
235  bool cache() { return m_cache; };
236  int cost() { return m_cost; };
237 };
238 
298 class PageRouter : public QObject, public QQmlParserStatus
299 {
300  Q_OBJECT
301  Q_INTERFACES(QQmlParserStatus)
302 
303 
308  Q_PROPERTY(QQmlListProperty<PageRoute> routes READ routes)
309 
310  Q_CLASSINFO("DefaultProperty", "routes")
311 
322  Q_PROPERTY(QJSValue initialRoute READ initialRoute WRITE setInitialRoute NOTIFY initialRouteChanged)
323 
336  Q_PROPERTY(ColumnView* pageStack MEMBER m_pageStack NOTIFY pageStackChanged)
337 
343  Q_PROPERTY(int cacheCapacity READ cacheCapacity WRITE setCacheCapacity)
344 
350  Q_PROPERTY(int preloadedPoolCapacity READ preloadedPoolCapacity WRITE setPreloadedPoolCapacity)
351 
355  Q_PROPERTY(QQmlPropertyMap* params READ params CONSTANT)
356 
357 private:
364  QSharedPointer<QQmlPropertyMap> m_paramMap;
365 
372  void reevaluateParamMapProperties();
373 
379  QList<PageRoute*> m_routes;
380 
386  ColumnView* m_pageStack = nullptr;
387 
395  QJSValue m_initialRoute;
396 
404  QList<ParsedRoute*> m_currentRoutes;
405 
411  LRU m_cache;
412 
418  LRU m_preload;
419 
426  void push(ParsedRoute* route);
427 
433  bool routesContainsKey(const QString &key) const;
434 
441  QQmlComponent *routesValueForKey(const QString &key) const;
442 
449  bool routesCacheForKey(const QString &key) const;
450 
457  int routesCostForKey(const QString &key) const;
458 
459  void preload(ParsedRoute *route);
460  void unpreload(ParsedRoute *route);
461 
462  void placeInCache(ParsedRoute *route);
463 
464  static void appendRoute(QQmlListProperty<PageRoute>* list, PageRoute*);
465  static int routeCount(QQmlListProperty<PageRoute>* list);
466  static PageRoute* route(QQmlListProperty<PageRoute>* list, int);
467  static void clearRoutes(QQmlListProperty<PageRoute>* list);
468 
469  QVariant dataFor(QObject* object);
470  bool isActive(QObject* object);
471  void pushFromObject(QObject *object, QJSValue route, bool replace = false);
472 
473  friend class PageRouterAttached;
474  friend class PreloadRouteGroup;
475  friend class ParsedRoute;
476 
477 protected:
478  void classBegin() override;
479  void componentComplete() override;
480 
481 public:
482  PageRouter(QQuickItem *parent = nullptr);
483  ~PageRouter();
484 
485  QQmlListProperty<PageRoute> routes();
486 
487  QQmlPropertyMap* params() { return m_paramMap.data(); }
488 
489  QJSValue initialRoute() const;
490  void setInitialRoute(QJSValue initialRoute);
491 
492  int cacheCapacity() const { return m_cache.size; };
493  void setCacheCapacity(int size) { m_cache.setSize(size); };
494 
495  int preloadedPoolCapacity() const { return m_preload.size; };
496  void setPreloadedPoolCapacity(int size) { m_preload.setSize(size); };
497 
526  Q_INVOKABLE void navigateToRoute(QJSValue route);
527 
550  Q_INVOKABLE bool routeActive(QJSValue route);
551 
568  Q_INVOKABLE void pushRoute(QJSValue route);
569 
583  Q_INVOKABLE void popRoute();
584 
613  Q_INVOKABLE void bringToView(QJSValue route);
614 
620  Q_INVOKABLE QJSValue currentRoutes() const;
621 
622  static PageRouterAttached *qmlAttachedProperties(QObject *object);
623 
624 Q_SIGNALS:
625  void routesChanged();
626  void initialRouteChanged();
627  void pageStackChanged();
628  void currentIndexChanged();
629  void navigationChanged();
630 };
631 
639 {
640  Q_OBJECT
641 
642  Q_PROPERTY(PageRouter *router READ router WRITE setRouter NOTIFY routerChanged)
647  Q_PROPERTY(QVariant data READ data MEMBER m_data NOTIFY dataChanged)
648 
653  Q_PROPERTY(bool isCurrent READ isCurrent NOTIFY isCurrentChanged)
654 
660  Q_PROPERTY(QJSValue watchedRoute READ watchedRoute WRITE setWatchedRoute NOTIFY watchedRouteChanged)
661 
665  Q_PROPERTY(PreloadRouteGroup* preload READ preload)
666 
670  Q_PROPERTY(bool watchedRouteActive READ watchedRouteActive NOTIFY navigationChanged)
671 
672 private:
673  explicit PageRouterAttached(QObject *parent = nullptr);
674 
675  QPointer<PageRouter> m_router;
676  PreloadRouteGroup* m_preload;
677  QVariant m_data;
678  QJSValue m_watchedRoute;
679 
680  void findParent();
681 
682  friend class PageRouter;
683  friend class PreloadRouteGroup;
684  friend class ParsedRoute;
685 
686 public:
687  PreloadRouteGroup* preload() const { return m_preload; };
688  PageRouter* router() const { return m_router; };
689  void setRouter(PageRouter* router) {
690  m_router = router;
691  Q_EMIT routerChanged();
692  }
693  QVariant data() const;
694  bool isCurrent() const;
696  Q_INVOKABLE void navigateToRoute(QJSValue route);
698  Q_INVOKABLE bool routeActive(QJSValue route);
700  Q_INVOKABLE void pushRoute(QJSValue route);
702  Q_INVOKABLE void popRoute();
703  // @see PageRouter::bringToView()
704  Q_INVOKABLE void bringToView(QJSValue route);
715  Q_INVOKABLE void pushFromHere(QJSValue route);
726  Q_INVOKABLE void popFromHere();
733  Q_INVOKABLE void replaceFromHere(QJSValue route);
734  bool watchedRouteActive();
735  void setWatchedRoute(QJSValue route);
736  QJSValue watchedRoute();
737 
738 Q_SIGNALS:
739  void routerChanged();
740  void dataChanged();
741  void isCurrentChanged();
742  void navigationChanged();
743  void watchedRouteChanged();
744 };
745 
746 QML_DECLARE_TYPEINFO(PageRouter, QML_HAS_ATTACHED_PROPERTIES)
Attached object allowing children of a PageRouter to access its functions without requiring the child...
Definition: pagerouter.h:638
QString name(const QVariant &location)
bool contains(const Key &key) const const
quint32 generate()
An item managing pages and data of a ColumnView using named routes.
Definition: pagerouter.h:298
ColumnView is a container that lays out items horizontally in a row, when not all items fit in the Co...
Definition: columnview.h:143
bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *method)
bool insert(Part *part, qint64 *insertId=nullptr)
QRandomGenerator * system()
KIOCORE_EXPORT QString number(KIO::filesize_t size)
Q_OBJECTQ_OBJECT
KGuiItem properties()
Item representing a route the PageRouter can navigate to.
Definition: pagerouter.h:174
int removeAll(const T &value)
void deleteLater()
Item holding data about when to preload a route.
Definition: pagerouter.h:130
T takeLast()
T & last()
void prepend(const T &value)
QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *method, Qt::ConnectionType type)
T take(const Key &key)
void destroyed(QObject *obj)
This file is part of the KDE documentation.
Documentation copyright © 1996-2021 The KDE developers.
Generated on Wed Jan 20 2021 22:41:09 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.