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 "columnview.h"
10 #include <QCache>
11 #include <QQmlPropertyMap>
12 #include <QQuickItem>
13 #include <QRandomGenerator>
14 
15 static std::map<quint32, QVariant> s_knownVariants;
16 class PageRouter;
17 
18 class ParsedRoute : public QObject
19 {
20  Q_OBJECT
21 
22 public:
23  QString name;
24  QVariant data;
25  QVariantMap properties;
26  bool cache;
27  QQuickItem *item = nullptr;
28  void itemDestroyed()
29  {
30  item = nullptr;
31  }
32  QQuickItem *setItem(QQuickItem *newItem)
33  {
34  auto ret = item;
35  if (ret != nullptr) {
36  disconnect(ret, &QObject::destroyed, this, &ParsedRoute::itemDestroyed);
37  }
38  item = newItem;
39  if (newItem != nullptr) {
40  connect(newItem, &QObject::destroyed, this, &ParsedRoute::itemDestroyed);
41  }
42  return ret;
43  }
44  explicit ParsedRoute(const QString &name = QString(),
45  QVariant data = QVariant(),
46  QVariantMap properties = QVariantMap(),
47  bool cache = false,
48  QQuickItem *item = nullptr)
49  : name(name)
50  , data(data)
51  , properties(properties)
52  , cache(cache)
53  {
54  setItem(item);
55  }
56  virtual ~ParsedRoute()
57  {
58  if (item) {
59  item->deleteLater();
60  }
61  }
62  quint32 hash()
63  {
64  for (auto i = s_knownVariants.begin(); i != s_knownVariants.end(); i++) {
65  if (i->second == data) {
66  return i->first;
67  }
68  }
70  while (s_knownVariants.count(number) > 0) {
72  }
73  s_knownVariants[number] = data;
74  return number;
75  }
76  bool equals(const ParsedRoute *rhs, bool countItem = false)
77  {
78  /* clang-format off */
79  return name == rhs->name
80  && data == rhs->data
81  && (!countItem || item == rhs->item)
82  && cache == rhs->cache;
83  /* clang-format on */
84  }
85 };
86 
87 struct LRU {
88  int size = 10;
89  QList<QPair<QString, quint32>> evictionList;
90  QMap<QPair<QString, quint32>, int> costs;
91  QMap<QPair<QString, quint32>, ParsedRoute *> items;
92 
93  ParsedRoute *take(QPair<QString, quint32> key)
94  {
95  auto ret = items.take(key);
96  evictionList.removeAll(key);
97  return ret;
98  }
99  int totalCosts()
100  {
101  int ret = 0;
102  for (auto cost : std::as_const(costs)) {
103  ret += cost;
104  }
105  return ret;
106  }
107  void setSize(int size = 10)
108  {
109  this->size = size;
110  prune();
111  }
112  void prune()
113  {
114  while (size < totalCosts()) {
115  auto key = evictionList.last();
116  auto item = items.take(key);
117  delete item;
118  costs.take(key);
119  evictionList.takeLast();
120  }
121  }
122  void insert(QPair<QString, quint32> key, ParsedRoute *newItem, int cost)
123  {
124  if (items.contains(key)) {
125  auto item = items.take(key);
126  evictionList.removeAll(key);
127  if (item != newItem) {
128  delete item;
129  }
130  }
131  costs[key] = cost;
132  items[key] = newItem;
133  evictionList.prepend(key);
134  prune();
135  }
136 };
137 
138 class PageRouterAttached;
139 
140 /**
141  * Item holding data about when to preload a route.
142  *
143  * @code{.qml}
144  * preload {
145  * route: "updates-page"
146  * when: updatesCount > 0
147  * }
148  * @endcode
149  */
151 {
152  Q_OBJECT
153 
154  /**
155  * @brief The route to preload.
156  *
157  * When the condition is false, the route will not be preloaded.
158  */
159  Q_PROPERTY(QJSValue route MEMBER m_route WRITE setRoute NOTIFY changed)
160  QJSValue m_route;
161 
162  /**
163  * @brief When the route should be preloaded.
164  *
165  * When the condition is false, the route will not be preloaded.
166  */
167  Q_PROPERTY(bool when MEMBER m_when NOTIFY changed)
168  bool m_when;
169 
170  void handleChange();
171  PageRouterAttached *m_parent;
172 
173 public:
175  void setRoute(QJSValue route)
176  {
177  m_route = route;
178  Q_EMIT changed();
179  }
180  PreloadRouteGroup(QObject *parent)
181  : QObject(parent)
182  {
183  m_parent = qobject_cast<PageRouterAttached *>(parent);
184  Q_ASSERT(m_parent);
185  connect(this, &PreloadRouteGroup::changed, this, &PreloadRouteGroup::handleChange);
186  }
187  Q_SIGNAL void changed();
188 };
189 
190 /**
191  * Item representing a route the PageRouter can navigate to.
192  *
193  * @include PageRoute.qml
194  *
195  * @see PageRouter
196  */
197 class PageRoute : public QObject
198 {
199  Q_OBJECT
200 
201  /**
202  * @brief The name of this route.
203  *
204  * This name should be unique per PageRoute in a PageRouter.
205  * When two PageRoutes have the same name, the one listed first
206  * in the PageRouter will be used.
207  */
208  Q_PROPERTY(QString name MEMBER m_name READ name)
209 
210  /**
211  * @brief The page component of this route.
212  *
213  * This should be an instance of Component with a Kirigami::Page inside
214  * of it.
215  */
216  Q_PROPERTY(QQmlComponent *component MEMBER m_component READ component)
217 
218  /**
219  * @brief Whether pages generated by this route should be cached or not.
220  *
221  * This should be an instance of Component with a Kirigami::Page inside
222  * of it.
223  *
224  * This will not work:
225  *
226  * @include PageRouterCachePagesDont.qml
227  *
228  * This will work:
229  *
230  * @include PageRouterCachePagesDo.qml
231  *
232  */
233  Q_PROPERTY(bool cache MEMBER m_cache READ cache)
234 
235  /**
236  * @brief How expensive this route is on memory.
237  *
238  * This affects caching, as the sum of costs of routes in the cache
239  * can never exceed the cache's cap.
240  */
241  Q_PROPERTY(int cost MEMBER m_cost)
242 
243  Q_CLASSINFO("DefaultProperty", "component")
244 
245 Q_SIGNALS:
246  void preloadDataChanged();
247  void preloadChanged();
248 
249 private:
250  QString m_name;
251  QQmlComponent *m_component = nullptr;
252  bool m_cache = false;
253  int m_cost = 1;
254 
255 public:
256  QQmlComponent *component()
257  {
258  return m_component;
259  };
260  QString name()
261  {
262  return m_name;
263  };
264  bool cache()
265  {
266  return m_cache;
267  };
268  int cost()
269  {
270  return m_cost;
271  };
272 };
273 
274 /**
275  * An item managing pages and data of a ColumnView using named routes.
276  *
277  * <br> <br>
278  *
279  * ## Using a PageRouter
280  *
281  * Applications typically manage their contents via elements called "pages" or "screens."
282  * In Kirigami, these are called @link org::kde::kirigami::Page Pages @endlink and are
283  * arranged in @link PageRoute routes @endlink using a PageRouter to manage them. The PageRouter
284  * manages a stack of @link org::kde::kirigami::Page Pages @endlink created from a pool of potential
285  * @link PageRoute PageRoutes @endlink.
286  *
287  * Unlike most traditional stacks, a PageRouter provides functions for random access to its pages
288  * with navigateToRoute and routeActive.
289  *
290  * When your user interface fits the stack paradigm and is likely to use random access navigation,
291  * using the PageRouter is appropriate. For simpler navigation, it is more appropriate to avoid
292  * the overhead of a PageRouter by using a @link org::kde::kirigami::PageRow PageRow @endlink
293  * instead.
294  *
295  * <br> <br>
296  *
297  * ## Navigation Model
298  *
299  * A PageRouter draws from a pool of @link PageRoute PageRoutes @endlink in order to construct
300  * its stack.
301  *
302  * @image html PageRouterModel.svg width=50%
303  *
304  * <br> <br>
305  *
306  * You can push pages onto this stack...
307  *
308  * @image html PageRouterPush.svg width=50%
309  *
310  * ...or pop them off...
311  *
312  * @image html PageRouterPop.svg width=50%
313  *
314  * ...or navigate to an arbitrary collection of pages.
315  *
316  * @image html PageRouterNavigate.svg width=50%
317  *
318  * <br> <br>
319  *
320  * Components are able to query the PageRouter about the currently active routes
321  * on the stack. This is useful for e.g. a card indicating that the page it takes
322  * the user to is currently active.
323  *
324  * <br> <br>
325  *
326  * ## Example
327  *
328  * @include PageRouter.qml
329  *
330  * @see PageRouterAttached
331  * @see PageRoute
332  */
333 class PageRouter : public QObject, public QQmlParserStatus
334 {
335  Q_OBJECT
336  Q_INTERFACES(QQmlParserStatus)
337 
338  /**
339  * @brief The named routes a PageRouter can navigate to.
340  *
341  * @include PageRouterRoutes.qml
342  */
343  Q_PROPERTY(QQmlListProperty<PageRoute> routes READ routes)
344 
345  Q_CLASSINFO("DefaultProperty", "routes")
346 
347  /**
348  * @brief The initial route.
349  *
350  * `initialRoute` is the page that the PageRouter will push upon
351  * creation. Changing it after creation will cause the PageRouter to reset
352  * its state. Not providing an `initialRoute` will result in undefined
353  * behavior.
354  *
355  * @include PageRouterInitialRoute.qml
356  */
357  Q_PROPERTY(QJSValue initialRoute READ initialRoute WRITE setInitialRoute NOTIFY initialRouteChanged)
358 
359  /**
360  * @brief The ColumnView being puppeted by the PageRouter.
361  *
362  * All PageRouters should be created with a ColumnView, and creating one without
363  * a ColumnView is undefined behaviour.
364  *
365  * @warning You should **not** directly interact with a ColumnView being puppeted
366  * by a PageRouter. Instead, use a PageRouter's functions to manipulate the
367  * ColumnView.
368  *
369  * @include PageRouterColumnView.qml
370  */
371  Q_PROPERTY(ColumnView *pageStack MEMBER m_pageStack NOTIFY pageStackChanged)
372 
373  /**
374  * @brief How large the cache can be.
375  *
376  * The combined costs of cached routes will never exceed the cache capacity.
377  */
378  Q_PROPERTY(int cacheCapacity READ cacheCapacity WRITE setCacheCapacity)
379 
380  /**
381  * @brief How large the preloaded pool can be.
382  *
383  * The combined costs of preloaded routes will never exceed the pool capacity.
384  */
385  Q_PROPERTY(int preloadedPoolCapacity READ preloadedPoolCapacity WRITE setPreloadedPoolCapacity)
386 
387  /**
388  * Exposes the data of all pages on the stack, preferring pages on the top
389  * (e.g. most recently pushed) to pages pushed on the bottom (least recently
390  * pushed).
391  */
392  Q_PROPERTY(QQmlPropertyMap *params READ params CONSTANT)
393 
394 private:
395  /**
396  * The map exposing to QML all the params of the stack. This is a
397  * QQmlPropertyMap to allow binding to param values. This *does* lack
398  * the ability to drop items, but the amount of all params in an app
399  * is overwhelmingly likely to be fixed, not dynamic.
400  */
401  QSharedPointer<QQmlPropertyMap> m_paramMap;
402 
403  /**
404  * Reevaluate the properties of the param map by going through all of the
405  * routes on the stack to determine the topmost value for every parametre.
406  *
407  * Should be called for every time a route is pushed, popped, or modified.
408  */
409  void reevaluateParamMapProperties();
410 
411  /**
412  * @brief The routes the PageRouter is aware of.
413  *
414  * Generally, this should not be mutated from C++, only read.
415  */
416  QList<PageRoute *> m_routes;
417 
418  /**
419  * @brief The PageRouter being puppeted.
420  *
421  * m_pageRow is the ColumnView this PageRouter puppets.
422  */
423  ColumnView *m_pageStack = nullptr;
424 
425  /**
426  * @brief The route that the PageRouter will load on completion.
427  *
428  * m_initialRoute is the raw QJSValue from QML that will be
429  * parsed into a ParsedRoute struct on construction.
430  * Generally, this should not be mutated from C++, only read.
431  */
432  QJSValue m_initialRoute;
433 
434  /**
435  * @brief The current routes pushed on the PageRow.
436  *
437  * Generally, the state of m_pageRow and m_currentRoutes
438  * should be kept in sync. Undesirable behaviour will result
439  * from desynchronisation of the two.
440  */
441  QList<ParsedRoute *> m_currentRoutes;
442 
443  /**
444  * @brief Cached routes.
445  *
446  * An LRU cache of ParsedRoutes with items that were previously on the stack.
447  */
448  LRU m_cache;
449 
450  /** @brief Preloaded routes.
451  *
452  * A LRU cache of ParsedRoutes with items that may be on the stack in the future,
453  * but were not on the stack before.
454  */
455  LRU m_preload;
456 
457  /**
458  * @brief Helper function to push a route.
459  *
460  * This function has the shared logic between
461  * navigateToRoute and pushRoute.
462  */
463  void push(ParsedRoute *route);
464 
465  /**
466  * @brief Helper function to access whether m_routes has a key.
467  *
468  * This function abstracts the QJSValue.
469  */
470  bool routesContainsKey(const QString &key) const;
471 
472  /**
473  * @brief Helper function to access the component of a key for m_routes.
474  *
475  * The return value will be a nullptr if @p key does not exist in
476  * m_routes.
477  */
478  QQmlComponent *routesValueForKey(const QString &key) const;
479 
480  /**
481  * @brief Helper function to access the cache status of a key for m_routes.
482  *
483  * The return value will be false if @p key does not exist in
484  * m_routes.
485  */
486  bool routesCacheForKey(const QString &key) const;
487 
488  /**
489  * @brief Helper function to access the cost of a key for m_routes.
490  *
491  * The return value will be -1 if @p key does not exist in
492  * m_routes.
493  */
494  int routesCostForKey(const QString &key) const;
495 
496  void preload(ParsedRoute *route);
497  void unpreload(ParsedRoute *route);
498 
499  void placeInCache(ParsedRoute *route);
500 
501  static void appendRoute(QQmlListProperty<PageRoute> *list, PageRoute *);
502  static int routeCount(QQmlListProperty<PageRoute> *list);
503  static PageRoute *route(QQmlListProperty<PageRoute> *list, int);
504  static void clearRoutes(QQmlListProperty<PageRoute> *list);
505 
506  QVariant dataFor(QObject *object);
507  bool isActive(QObject *object);
508  void pushFromObject(QObject *object, QJSValue route, bool replace = false);
509 
510  friend class PageRouterAttached;
511  friend class PreloadRouteGroup;
512  friend class ParsedRoute;
513 
514 protected:
515  void classBegin() override;
516  void componentComplete() override;
517 
518 public:
519  PageRouter(QQuickItem *parent = nullptr);
520  ~PageRouter();
521 
522  QQmlListProperty<PageRoute> routes();
523 
524  QQmlPropertyMap *params()
525  {
526  return m_paramMap.data();
527  }
528 
529  QJSValue initialRoute() const;
530  void setInitialRoute(QJSValue initialRoute);
531 
532  int cacheCapacity() const
533  {
534  return m_cache.size;
535  };
536  void setCacheCapacity(int size)
537  {
538  m_cache.setSize(size);
539  };
540 
541  int preloadedPoolCapacity() const
542  {
543  return m_preload.size;
544  };
545  void setPreloadedPoolCapacity(int size)
546  {
547  m_preload.setSize(size);
548  };
549 
550  /**
551  * @brief Navigate to the given route.
552  *
553  * Calling `navigateToRoute` causes the PageRouter to replace currently
554  * active pages with the new route.
555  *
556  * @param route The given route for the PageRouter to navigate to.
557  * A route is an array of variants or a single item. A string item will be interpreted
558  * as a page without associated data. An object item will be interpreted
559  * as follows:
560  * @code{.js}
561  * {
562  * "route": "/home" // The named page of the route.
563  * "data": QtObject {} // The data to pass to the page.
564  * }
565  * @endcode
566  * Navigating to a route not defined in a PageRouter's routes is undefined
567  * behavior.
568  *
569  * @code{.qml}
570  * Button {
571  * text: "Login"
572  * onClicked: {
573  * Kirigami.PageRouter.navigateToRoute(["/home", "/login"])
574  * }
575  * }
576  * @endcode
577  */
578  Q_INVOKABLE void navigateToRoute(QJSValue route);
579 
580  /**
581  * @brief Check whether the current route is on the stack.
582  *
583  * `routeActive` will return true if the given route
584  * is on the stack.
585  *
586  * @param route The given route to check for.
587  *
588  * `routeActive` returns true for partial routes like
589  * the following:
590  *
591  * @code{.js}
592  * Kirigami.PageRouter.navigateToRoute(["/home", "/login", "/google"])
593  * Kirigami.PageRouter.routeActive(["/home", "/login"]) // returns true
594  * @endcode
595  *
596  * This only works from the root page, e.g. the following will return false:
597  * @code{.js}
598  * Kirigami.PageRouter.navigateToRoute(["/home", "/login", "/google"])
599  * Kirigami.PageRouter.routeActive(["/login", "/google"]) // returns false
600  * @endcode
601  */
602  Q_INVOKABLE bool routeActive(QJSValue route);
603 
604  /**
605  * @brief Appends a route to the currently navigated route.
606  *
607  * Calling `pushRoute` will append the given @p route to the currently navigated
608  * routes. See navigateToRoute() if you want to replace the items currently on
609  * the PageRouter.
610  *
611  * @param route The given route to push.
612  *
613  * @code{.js}
614  * Kirigami.PageRouter.navigateToRoute(["/home", "/login"])
615  * // The PageRouter is navigated to /home/login
616  * Kirigami.PageRouter.pushRoute("/google")
617  * // The PageRouter is navigated to /home/login/google
618  * @endcode
619  */
620  Q_INVOKABLE void pushRoute(QJSValue route);
621 
622  /**
623  * @brief Pops the last page on the router.
624  *
625  * Calling `popRoute` will result in the last page on the router getting popped.
626  * You should not call this function when there is only one page on the router.
627  *
628  * @code{.js}
629  * Kirigami.PageRouter.navigateToRoute(["/home", "/login"])
630  * // The PageRouter is navigated to /home/login
631  * Kirigami.PageRouter.popRoute()
632  * // The PageRouter is navigated to /home
633  * @endcode
634  */
635  Q_INVOKABLE void popRoute();
636 
637  /**
638  * @brief Shifts keyboard focus and view to a given index on the PageRouter's stack.
639  *
640  * @param view The view to bring to focus. If this is an integer index, the PageRouter will
641  * navigate to the given index. If it's a route specifier, the PageRouter will navigate
642  * to the first route matching it.
643  *
644  * Navigating to route by index:
645  * @code{.js}
646  * Kirigami.PageRouter.navigateToRoute(["/home", "/browse", "/apps", "/login"])
647  * Kirigami.PageRouter.bringToView(1)
648  * @endcode
649  *
650  * Navigating to route by name:
651  * @code{.js}
652  * Kirigami.PageRouter.navigateToRoute(["/home", "/browse", "/apps", "/login"])
653  * Kirigami.PageRouter.bringToView("/browse")
654  * @endcode
655  *
656  * Navigating to route by data:
657  * @code{.js}
658  * Kirigami.PageRouter.navigateToRoute([{"route": "/page", "data": "red"},
659  * {"route": "/page", "data": "blue"},
660  * {"route": "/page", "data": "green"},
661  * {"route": "/page", "data": "yellow"}])
662  * Kirigami.PageRouter.bringToView({"route": "/page", "data": "blue"})
663  * @endcode
664  */
665  Q_INVOKABLE void bringToView(QJSValue route);
666 
667  /**
668  * @brief Returns a QJSValue corresponding to the current pages on the stack.
669  *
670  * The returned value is in the same form as the input to navigateToRoute.
671  */
672  Q_INVOKABLE QJSValue currentRoutes() const;
673 
674  static PageRouterAttached *qmlAttachedProperties(QObject *object);
675 
676 Q_SIGNALS:
677  void routesChanged();
678  void initialRouteChanged();
679  void pageStackChanged();
680  void currentIndexChanged();
681  void navigationChanged();
682 };
683 
684 /**
685  * Attached object allowing children of a PageRouter to access its functions
686  * without requiring the children to have the parent PageRouter's id.
687  *
688  * @see PageRouter
689  */
691 {
692  Q_OBJECT
693 
694  Q_PROPERTY(PageRouter *router READ router WRITE setRouter NOTIFY routerChanged)
695  /**
696  * The data for the page this item belongs to. Accessing this property
697  * outside of a PageRouter will result in undefined behavior.
698  */
699  Q_PROPERTY(QVariant data READ data MEMBER m_data NOTIFY dataChanged)
700 
701  /**
702  * Whether the page this item belongs to is the current index of the ColumnView.
703  * Accessing this property outside of a PageRouter will result in undefined behaviour.
704  */
705  Q_PROPERTY(bool isCurrent READ isCurrent NOTIFY isCurrentChanged)
706 
707  /**
708  * Which route this PageRouterAttached should watch for.
709  *
710  * @include PageRouterWatchedRoute.qml
711  */
712  Q_PROPERTY(QJSValue watchedRoute READ watchedRoute WRITE setWatchedRoute NOTIFY watchedRouteChanged)
713 
714  /**
715  * Route preloading settings.
716  */
717  Q_PROPERTY(PreloadRouteGroup *preload READ preload)
718 
719  /**
720  * Whether the watchedRoute is currently active.
721  */
722  Q_PROPERTY(bool watchedRouteActive READ watchedRouteActive NOTIFY navigationChanged)
723 
724 private:
725  explicit PageRouterAttached(QObject *parent = nullptr);
726 
727  QPointer<PageRouter> m_router;
728  PreloadRouteGroup *m_preload;
729  QVariant m_data;
730  QJSValue m_watchedRoute;
731 
732  void findParent();
733 
734  friend class PageRouter;
735  friend class PreloadRouteGroup;
736  friend class ParsedRoute;
737 
738 public:
739  PreloadRouteGroup *preload() const
740  {
741  return m_preload;
742  };
743  PageRouter *router() const
744  {
745  return m_router;
746  };
747  void setRouter(PageRouter *router)
748  {
749  m_router = router;
750  Q_EMIT routerChanged();
751  }
752  QVariant data() const;
753  bool isCurrent() const;
754  /// @see PageRouter::navigateToRoute()
755  Q_INVOKABLE void navigateToRoute(QJSValue route);
756  /// @see PageRouter::routeActive()
757  Q_INVOKABLE bool routeActive(QJSValue route);
758  /// @see PageRouter::pushRoute()
759  Q_INVOKABLE void pushRoute(QJSValue route);
760  /// @see PageRouter::popRoute()
761  Q_INVOKABLE void popRoute();
762  // @see PageRouter::bringToView()
763  Q_INVOKABLE void bringToView(QJSValue route);
764  /**
765  * @brief Push a route from this route on the stack.
766  *
767  * Replace the routes after the route this is invoked on
768  * with the provided @p route.
769  *
770  * For example, if you invoke this method on the second route
771  * in the PageRouter's stack, routes after the second
772  * route will be replaced with the provided routes.
773  */
774  Q_INVOKABLE void pushFromHere(QJSValue route);
775  /**
776  * @brief Pop routes after this route on the stack.
777  *
778  * Pop the routes after the route this is invoked on with
779  * the provided @p route.
780  *
781  * For example, if you invoke this method on the second route
782  * in the PageRouter's stack, routes after the second route
783  * will be removed from the stack.
784  */
785  Q_INVOKABLE void popFromHere();
786  /**
787  * @brief Replaces this route with the given routes on the stack.
788  *
789  * Behaves like pushFromHere, except the current route is also
790  * popped.
791  */
792  Q_INVOKABLE void replaceFromHere(QJSValue route);
793  bool watchedRouteActive();
794  void setWatchedRoute(QJSValue route);
795  QJSValue watchedRoute();
796 
797 Q_SIGNALS:
798  void routerChanged();
799  void dataChanged();
800  void isCurrentChanged();
801  void navigationChanged();
802  void watchedRouteChanged();
803 };
804 
805 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:690
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:333
ColumnView is a container that lays out items horizontally in a row, when not all items fit in the Co...
Definition: columnview.h:147
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:197
int removeAll(const T &value)
void deleteLater()
Item holding data about when to preload a route.
Definition: pagerouter.h:150
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 Fri Oct 22 2021 22:39:17 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.