File indexing completed on 2024-04-28 15:27:44
0001 /* 0002 * SPDX-FileCopyrightText: 2020 Carson Black <uhhadd@gmail.com> 0003 * 0004 * SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #pragma once 0008 0009 #include "columnview.h" 0010 #include <QCache> 0011 #include <QQmlPropertyMap> 0012 #include <QQuickItem> 0013 #include <QRandomGenerator> 0014 0015 static std::map<quint32, QVariant> s_knownVariants; 0016 class PageRouter; 0017 0018 class ParsedRoute : public QObject 0019 { 0020 Q_OBJECT 0021 0022 public: 0023 QString name; 0024 QVariant data; 0025 QVariantMap properties; 0026 bool cache; 0027 QQuickItem *item = nullptr; 0028 void itemDestroyed() 0029 { 0030 item = nullptr; 0031 } 0032 QQuickItem *setItem(QQuickItem *newItem) 0033 { 0034 auto ret = item; 0035 if (ret != nullptr) { 0036 disconnect(ret, &QObject::destroyed, this, &ParsedRoute::itemDestroyed); 0037 } 0038 item = newItem; 0039 if (newItem != nullptr) { 0040 connect(newItem, &QObject::destroyed, this, &ParsedRoute::itemDestroyed); 0041 } 0042 return ret; 0043 } 0044 explicit ParsedRoute(const QString &name = QString(), 0045 QVariant data = QVariant(), 0046 QVariantMap properties = QVariantMap(), 0047 bool cache = false, 0048 QQuickItem *item = nullptr) 0049 : name(name) 0050 , data(data) 0051 , properties(properties) 0052 , cache(cache) 0053 { 0054 setItem(item); 0055 } 0056 ~ParsedRoute() override 0057 { 0058 if (item) { 0059 item->deleteLater(); 0060 } 0061 } 0062 quint32 hash() 0063 { 0064 for (auto i = s_knownVariants.begin(); i != s_knownVariants.end(); i++) { 0065 if (i->second == data) { 0066 return i->first; 0067 } 0068 } 0069 auto number = QRandomGenerator::system()->generate(); 0070 while (s_knownVariants.count(number) > 0) { 0071 number = QRandomGenerator::system()->generate(); 0072 } 0073 s_knownVariants[number] = data; 0074 return number; 0075 } 0076 bool equals(const ParsedRoute *rhs, bool countItem = false) 0077 { 0078 /* clang-format off */ 0079 return name == rhs->name 0080 && data == rhs->data 0081 && (!countItem || item == rhs->item) 0082 && cache == rhs->cache; 0083 /* clang-format on */ 0084 } 0085 }; 0086 0087 struct LRU { 0088 int size = 10; 0089 QList<QPair<QString, quint32>> evictionList; 0090 QMap<QPair<QString, quint32>, int> costs; 0091 QMap<QPair<QString, quint32>, ParsedRoute *> items; 0092 0093 ParsedRoute *take(QPair<QString, quint32> key) 0094 { 0095 auto ret = items.take(key); 0096 evictionList.removeAll(key); 0097 return ret; 0098 } 0099 int totalCosts() 0100 { 0101 int ret = 0; 0102 for (auto cost : std::as_const(costs)) { 0103 ret += cost; 0104 } 0105 return ret; 0106 } 0107 void setSize(int size = 10) 0108 { 0109 this->size = size; 0110 prune(); 0111 } 0112 void prune() 0113 { 0114 while (size < totalCosts()) { 0115 auto key = evictionList.last(); 0116 auto item = items.take(key); 0117 delete item; 0118 costs.take(key); 0119 evictionList.takeLast(); 0120 } 0121 } 0122 void insert(QPair<QString, quint32> key, ParsedRoute *newItem, int cost) 0123 { 0124 if (items.contains(key)) { 0125 auto item = items.take(key); 0126 evictionList.removeAll(key); 0127 if (item != newItem) { 0128 delete item; 0129 } 0130 } 0131 costs[key] = cost; 0132 items[key] = newItem; 0133 evictionList.prepend(key); 0134 prune(); 0135 } 0136 }; 0137 0138 class PageRouterAttached; 0139 0140 /** 0141 * Item holding data about when to preload a route. 0142 * 0143 * @code{.qml} 0144 * [...] 0145 * preload { 0146 * route: "updates-page" 0147 * when: updatesCount > 0 0148 * } 0149 * @endcode 0150 */ 0151 class PreloadRouteGroup : public QObject 0152 { 0153 Q_OBJECT 0154 0155 /** 0156 * @brief This property holds the route to preload. 0157 */ 0158 Q_PROPERTY(QJSValue route MEMBER m_route WRITE setRoute NOTIFY changed) 0159 QJSValue m_route; 0160 0161 /** 0162 * @brief This property sets whether the route should be preloaded. 0163 */ 0164 Q_PROPERTY(bool when MEMBER m_when NOTIFY changed) 0165 bool m_when; 0166 0167 void handleChange(); 0168 PageRouterAttached *m_parent; 0169 0170 public: 0171 ~PreloadRouteGroup() override; 0172 void setRoute(QJSValue route) 0173 { 0174 m_route = route; 0175 Q_EMIT changed(); 0176 } 0177 PreloadRouteGroup(QObject *parent) 0178 : QObject(parent) 0179 { 0180 m_parent = qobject_cast<PageRouterAttached *>(parent); 0181 Q_ASSERT(m_parent); 0182 connect(this, &PreloadRouteGroup::changed, this, &PreloadRouteGroup::handleChange); 0183 } 0184 Q_SIGNAL void changed(); 0185 }; 0186 0187 /** 0188 * Item representing a route the PageRouter can navigate to. 0189 * 0190 * @include pagerouter/PageRoute.qml 0191 * 0192 * @see kirigami::PageRouter 0193 */ 0194 class PageRoute : public QObject 0195 { 0196 Q_OBJECT 0197 0198 /** 0199 * @brief This property holds the name of this route. 0200 * 0201 * This name should be unique per PageRoute in a PageRouter. 0202 * When two PageRoutes have the same name, the one listed first 0203 * in the PageRouter will be used. 0204 */ 0205 Q_PROPERTY(QString name MEMBER m_name READ name) 0206 0207 /** 0208 * @brief This property holds the page component of this route. 0209 * 0210 * This should be an instance of Component with a Kirigami::Page inside 0211 * of it. 0212 */ 0213 Q_PROPERTY(QQmlComponent *component MEMBER m_component READ component) 0214 0215 /** 0216 * @brief This property sets whether pages generated by this route should be cached. 0217 * 0218 * This should be an instance of Component with a Kirigami::Page inside 0219 * of it. 0220 * 0221 * This will not work: 0222 * 0223 * @include pagerouter/PageRouterCachePagesDont.qml 0224 * 0225 * This will work: 0226 * 0227 * @include pagerouter/PageRouterCachePagesDo.qml 0228 * 0229 */ 0230 Q_PROPERTY(bool cache MEMBER m_cache READ cache) 0231 0232 /** 0233 * @brief This property specifies how expensive this route is on memory. 0234 * 0235 * This affects caching, as the sum of costs of routes in the cache 0236 * can never exceed the cache's cap. 0237 */ 0238 Q_PROPERTY(int cost MEMBER m_cost) 0239 0240 Q_CLASSINFO("DefaultProperty", "component") 0241 0242 Q_SIGNALS: 0243 void preloadDataChanged(); 0244 void preloadChanged(); 0245 0246 private: 0247 QString m_name; 0248 QQmlComponent *m_component = nullptr; 0249 bool m_cache = false; 0250 int m_cost = 1; 0251 0252 public: 0253 QQmlComponent *component() 0254 { 0255 return m_component; 0256 }; 0257 QString name() 0258 { 0259 return m_name; 0260 }; 0261 bool cache() 0262 { 0263 return m_cache; 0264 }; 0265 int cost() 0266 { 0267 return m_cost; 0268 }; 0269 }; 0270 0271 /** 0272 * An item managing pages and data of a ColumnView using named routes. 0273 * 0274 * <br> <br> 0275 * 0276 * ## Using a PageRouter 0277 * 0278 * Applications typically manage their contents via elements called "pages" or "screens." 0279 * In Kirigami, these are called @link kirigami::Page Pages @endlink and are 0280 * arranged in @link PageRoute routes @endlink using a PageRouter to manage them. The PageRouter 0281 * manages a stack of @link kirigami::Page Pages @endlink created from a pool of potential 0282 * @link PageRoute PageRoutes @endlink. 0283 * 0284 * Unlike most traditional stacks, a PageRouter provides functions for random access to its pages 0285 * with navigateToRoute and routeActive. 0286 * 0287 * When your user interface fits the stack paradigm and is likely to use random access navigation, 0288 * using the PageRouter is appropriate. For simpler navigation, it is more appropriate to avoid 0289 * the overhead of a PageRouter by using a @link kirigami::PageRow PageRow @endlink 0290 * instead. 0291 * 0292 * <br> <br> 0293 * 0294 * ## Navigation Model 0295 * 0296 * A PageRouter draws from a pool of @link PageRoute PageRoutes @endlink in order to construct 0297 * its stack. 0298 * 0299 * @image html PageRouterModel.svg width=50% 0300 * 0301 * <br> <br> 0302 * 0303 * You can push pages onto this stack... 0304 * 0305 * @image html PageRouterPush.svg width=50% 0306 * 0307 * ...or pop them off... 0308 * 0309 * @image html PageRouterPop.svg width=50% 0310 * 0311 * ...or navigate to an arbitrary collection of pages. 0312 * 0313 * @image html PageRouterNavigate.svg width=50% 0314 * 0315 * <br> <br> 0316 * 0317 * Components are able to query the PageRouter about the currently active routes 0318 * on the stack. This is useful for e.g. a card indicating that the page it takes 0319 * the user to is currently active. 0320 * 0321 * <br> <br> 0322 * 0323 * ## Example 0324 * 0325 * @include pagerouter/PageRouter.qml 0326 * 0327 * @see kirigami::PageRouterAttached 0328 * @see kirigami::PageRoute 0329 */ 0330 class PageRouter : public QObject, public QQmlParserStatus 0331 { 0332 Q_OBJECT 0333 Q_INTERFACES(QQmlParserStatus) 0334 0335 /** 0336 * @brief This property holds a list of named routes a PageRouter can navigate to. 0337 * 0338 * @include pagerouter/PageRouterRoutes.qml 0339 */ 0340 Q_PROPERTY(QQmlListProperty<PageRoute> routes READ routes) 0341 0342 Q_CLASSINFO("DefaultProperty", "routes") 0343 0344 /** 0345 * @brief This property sets the initial route. 0346 * 0347 * `initialRoute` is the page that the PageRouter will push upon 0348 * creation. Changing it after creation will cause the PageRouter to reset 0349 * its state. Not providing an `initialRoute` will result in undefined 0350 * behavior. 0351 * 0352 * @see kirigami::PageRoute::name 0353 * @include pagerouter/PageRouterInitialRoute.qml 0354 */ 0355 Q_PROPERTY(QJSValue initialRoute READ initialRoute WRITE setInitialRoute NOTIFY initialRouteChanged) 0356 0357 /** 0358 * @brief This property holds the ColumnView being puppeted by the PageRouter. 0359 * 0360 * All PageRouters should be created with a ColumnView, and creating one without 0361 * a ColumnView is undefined behaviour. 0362 * 0363 * @warning You should **not** directly interact with a ColumnView being puppeted 0364 * by a PageRouter. Instead, use a PageRouter's functions to manipulate the 0365 * ColumnView. 0366 * 0367 * @include pagerouter/PageRouterColumnView.qml 0368 */ 0369 Q_PROPERTY(ColumnView *pageStack MEMBER m_pageStack NOTIFY pageStackChanged) 0370 0371 /** 0372 * @brief This property holds how large the cache can be. 0373 * 0374 * The combined costs of cached routes will never exceed the cache capacity. 0375 */ 0376 Q_PROPERTY(int cacheCapacity READ cacheCapacity WRITE setCacheCapacity) 0377 0378 /** 0379 * @brief This property holds how large the preloaded pool can be. 0380 * 0381 * The combined costs of preloaded routes will never exceed the pool capacity. 0382 */ 0383 Q_PROPERTY(int preloadedPoolCapacity READ preloadedPoolCapacity WRITE setPreloadedPoolCapacity) 0384 0385 /** 0386 * Exposes the data of all pages on the stack, preferring pages on the top 0387 * (e.g. most recently pushed) to pages pushed on the bottom (least recently 0388 * pushed). 0389 */ 0390 Q_PROPERTY(QQmlPropertyMap *params READ params CONSTANT) 0391 0392 private: 0393 /** 0394 * The map exposing to QML all the params of the stack. This is a 0395 * QQmlPropertyMap to allow binding to param values. This *does* lack 0396 * the ability to drop items, but the amount of all params in an app 0397 * is overwhelmingly likely to be fixed, not dynamic. 0398 */ 0399 QSharedPointer<QQmlPropertyMap> m_paramMap; 0400 0401 /** 0402 * @brief This method reevaluates the properties of the param map by going through all of the 0403 * routes on the stack to determine the topmost value for every parameter. 0404 * 0405 * Should be called for every time a route is pushed, popped, or modified. 0406 */ 0407 void reevaluateParamMapProperties(); 0408 0409 /** 0410 * @brief This property holds a list of routes the PageRouter is aware of. 0411 * 0412 * Generally, this should not be mutated from C++, only read. 0413 */ 0414 QList<PageRoute *> m_routes; 0415 0416 /** 0417 * @brief The PageRouter being puppeted. 0418 * 0419 * m_pageRow is the ColumnView this PageRouter puppets. 0420 */ 0421 ColumnView *m_pageStack = nullptr; 0422 0423 /** 0424 * @brief The route that the PageRouter will load on completion. 0425 * 0426 * m_initialRoute is the raw QJSValue from QML that will be 0427 * parsed into a ParsedRoute struct on construction. 0428 * Generally, this should not be mutated from C++, only read. 0429 */ 0430 QJSValue m_initialRoute; 0431 0432 /** 0433 * @brief The current routes pushed on the PageRow. 0434 * 0435 * Generally, the state of m_pageRow and m_currentRoutes 0436 * should be kept in sync. Undesirable behaviour will result 0437 * from desynchronisation of the two. 0438 */ 0439 QList<ParsedRoute *> m_currentRoutes; 0440 0441 /** 0442 * @brief Cached routes. 0443 * 0444 * An LRU cache of ParsedRoutes with items that were previously on the stack. 0445 */ 0446 LRU m_cache; 0447 0448 /** @brief Preloaded routes. 0449 * 0450 * A LRU cache of ParsedRoutes with items that may be on the stack in the future, 0451 * but were not on the stack before. 0452 */ 0453 LRU m_preload; 0454 0455 /** 0456 * @brief Helper function to push a route. 0457 * 0458 * This function has the shared logic between 0459 * navigateToRoute and pushRoute. 0460 */ 0461 void push(ParsedRoute *route); 0462 0463 /** 0464 * @brief This method returns whether m_routes has a key. 0465 * 0466 * This function abstracts the QJSValue. 0467 */ 0468 bool routesContainsKey(const QString &key) const; 0469 0470 /** 0471 * @brief This method returns the component of the specified key for m_routes. 0472 * 0473 * The return value will be a @c nullptr if @p key does not exist in 0474 * m_routes. 0475 */ 0476 QQmlComponent *routesValueForKey(const QString &key) const; 0477 0478 /** 0479 * @brief This method returns the cache status of a key for m_routes. 0480 * 0481 * The return value will be @c false if @p key does not exist in 0482 * m_routes. 0483 */ 0484 bool routesCacheForKey(const QString &key) const; 0485 0486 /** 0487 * @brief This method return the cost of a key for m_routes. 0488 * 0489 * The return value will be -1 if @p key does not exist in 0490 * m_routes. 0491 */ 0492 int routesCostForKey(const QString &key) const; 0493 0494 void preload(ParsedRoute *route); 0495 void unpreload(ParsedRoute *route); 0496 0497 void placeInCache(ParsedRoute *route); 0498 0499 static void appendRoute(QQmlListProperty<PageRoute> *list, PageRoute *); 0500 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0501 static int routeCount(QQmlListProperty<PageRoute> *list); 0502 static PageRoute *route(QQmlListProperty<PageRoute> *list, int); 0503 #else 0504 static qsizetype routeCount(QQmlListProperty<PageRoute> *list); 0505 static PageRoute *route(QQmlListProperty<PageRoute> *list, qsizetype); 0506 #endif 0507 static void clearRoutes(QQmlListProperty<PageRoute> *list); 0508 0509 QVariant dataFor(QObject *object); 0510 bool isActive(QObject *object); 0511 void pushFromObject(QObject *object, QJSValue route, bool replace = false); 0512 0513 friend class PageRouterAttached; 0514 friend class PreloadRouteGroup; 0515 friend class ParsedRoute; 0516 0517 protected: 0518 void classBegin() override; 0519 void componentComplete() override; 0520 0521 public: 0522 PageRouter(QQuickItem *parent = nullptr); 0523 ~PageRouter() override; 0524 0525 QQmlListProperty<PageRoute> routes(); 0526 0527 QQmlPropertyMap *params() 0528 { 0529 return m_paramMap.data(); 0530 } 0531 0532 QJSValue initialRoute() const; 0533 void setInitialRoute(QJSValue initialRoute); 0534 0535 int cacheCapacity() const 0536 { 0537 return m_cache.size; 0538 }; 0539 void setCacheCapacity(int size) 0540 { 0541 m_cache.setSize(size); 0542 }; 0543 0544 int preloadedPoolCapacity() const 0545 { 0546 return m_preload.size; 0547 }; 0548 void setPreloadedPoolCapacity(int size) 0549 { 0550 m_preload.setSize(size); 0551 }; 0552 0553 /** 0554 * @brief This method makes the PageRouter navigate to the specified route. 0555 * 0556 * Calling `navigateToRoute` causes the PageRouter to replace currently 0557 * active pages with the new route. 0558 * 0559 * @param route The given route for the PageRouter to navigate to. 0560 * A route is an array of variants or a single item. A string item will be interpreted 0561 * as a page without associated data. An object item will be interpreted 0562 * as follows: 0563 * @code{.js} 0564 * { 0565 * "route": "/home" // The named page of the route. 0566 * "data": QtObject {} // The data to pass to the page. 0567 * } 0568 * @endcode 0569 * Navigating to a route not defined in a PageRouter's routes is undefined 0570 * behavior. 0571 * 0572 * @code{.qml} 0573 * Button { 0574 * text: "Login" 0575 * onClicked: { 0576 * Kirigami.PageRouter.navigateToRoute(["/home", "/login"]) 0577 * } 0578 * } 0579 * @endcode 0580 */ 0581 Q_INVOKABLE void navigateToRoute(QJSValue route); 0582 0583 /** 0584 * @brief This method Checs whether the current route is on the stack. 0585 * 0586 * `routeActive` will return @c true if the given route 0587 * is on the stack. 0588 * 0589 * @param route The given route to check for. 0590 * 0591 * `routeActive` returns @c true for partial routes like 0592 * the following: 0593 * 0594 * @code{.js} 0595 * Kirigami.PageRouter.navigateToRoute(["/home", "/login", "/google"]) 0596 * Kirigami.PageRouter.routeActive(["/home", "/login"]) // returns true 0597 * @endcode 0598 * 0599 * This only works from the root page, e.g. the following will return false: 0600 * @code{.js} 0601 * Kirigami.PageRouter.navigateToRoute(["/home", "/login", "/google"]) 0602 * Kirigami.PageRouter.routeActive(["/login", "/google"]) // returns false 0603 * @endcode 0604 */ 0605 Q_INVOKABLE bool routeActive(QJSValue route); 0606 0607 /** 0608 * @brief This method appends a route to the currently navigated route. 0609 * 0610 * Calling `pushRoute` will append the given @p route to the currently navigated 0611 * routes. See navigateToRoute() if you want to replace the items currently on 0612 * the PageRouter. 0613 * 0614 * @param route The given route to push. 0615 * 0616 * @code{.js} 0617 * Kirigami.PageRouter.navigateToRoute(["/home", "/login"]) 0618 * // The PageRouter is navigated to /home/login 0619 * Kirigami.PageRouter.pushRoute("/google") 0620 * // The PageRouter is navigated to /home/login/google 0621 * @endcode 0622 */ 0623 Q_INVOKABLE void pushRoute(QJSValue route); 0624 0625 /** 0626 * @brief This method pops the last page on the router. 0627 * 0628 * Calling `popRoute` will result in the last page on the router getting popped. 0629 * You should not call this function when there is only one page on the router. 0630 * 0631 * @code{.js} 0632 * Kirigami.PageRouter.navigateToRoute(["/home", "/login"]) 0633 * // The PageRouter is navigated to /home/login 0634 * Kirigami.PageRouter.popRoute() 0635 * // The PageRouter is navigated to /home 0636 * @endcode 0637 */ 0638 Q_INVOKABLE void popRoute(); 0639 0640 /** 0641 * @brief This method shifts keyboard focus and view to a given index on the PageRouter's stack. 0642 * 0643 * @param view The view to bring to focus. If this is an integer index, the PageRouter will 0644 * navigate to the given index. If it's a route specifier, the PageRouter will navigate 0645 * to the first route matching it. 0646 * 0647 * Navigating to route by index: 0648 * @code{.js} 0649 * Kirigami.PageRouter.navigateToRoute(["/home", "/browse", "/apps", "/login"]) 0650 * Kirigami.PageRouter.bringToView(1) 0651 * @endcode 0652 * 0653 * Navigating to route by name: 0654 * @code{.js} 0655 * Kirigami.PageRouter.navigateToRoute(["/home", "/browse", "/apps", "/login"]) 0656 * Kirigami.PageRouter.bringToView("/browse") 0657 * @endcode 0658 * 0659 * Navigating to route by data: 0660 * @code{.js} 0661 * Kirigami.PageRouter.navigateToRoute([{"route": "/page", "data": "red"}, 0662 * {"route": "/page", "data": "blue"}, 0663 * {"route": "/page", "data": "green"}, 0664 * {"route": "/page", "data": "yellow"}]) 0665 * Kirigami.PageRouter.bringToView({"route": "/page", "data": "blue"}) 0666 * @endcode 0667 */ 0668 Q_INVOKABLE void bringToView(QJSValue route); 0669 0670 /** 0671 * @brief This method returns a QJSValue corresponding to the current pages on the stack. 0672 * 0673 * The returned value is in the same form as the input to navigateToRoute. 0674 */ 0675 Q_INVOKABLE QJSValue currentRoutes() const; 0676 0677 static PageRouterAttached *qmlAttachedProperties(QObject *object); 0678 0679 Q_SIGNALS: 0680 void routesChanged(); 0681 void initialRouteChanged(); 0682 void pageStackChanged(); 0683 void currentIndexChanged(); 0684 void navigationChanged(); 0685 }; 0686 0687 /** 0688 * Attached object allowing children of a PageRouter to access its functions 0689 * without requiring the children to have the parent PageRouter's id. 0690 * 0691 * @see kirigami::PageRouter 0692 */ 0693 class PageRouterAttached : public QObject 0694 { 0695 Q_OBJECT 0696 0697 Q_PROPERTY(PageRouter *router READ router WRITE setRouter NOTIFY routerChanged) 0698 /** 0699 * @brief This property holds data for the page this item belongs to. 0700 * @note Accessing this property outside of a PageRouter will result in undefined behaviour. 0701 */ 0702 Q_PROPERTY(QVariant data READ data MEMBER m_data NOTIFY dataChanged) 0703 0704 /** 0705 * @brief This property sets whether the page this item belongs to is the current index of the ColumnView. 0706 * @note Accessing this property outside of a PageRouter will result in undefined behaviour. 0707 */ 0708 Q_PROPERTY(bool isCurrent READ isCurrent NOTIFY isCurrentChanged) 0709 0710 /** 0711 * @brief This property holds which route this PageRouterAttached should watch for. 0712 * @include pagerouter/PageRouterWatchedRoute.qml 0713 */ 0714 Q_PROPERTY(QJSValue watchedRoute READ watchedRoute WRITE setWatchedRoute NOTIFY watchedRouteChanged) 0715 0716 /** 0717 * @brief This property holds route preloading settings. 0718 */ 0719 Q_PROPERTY(PreloadRouteGroup *preload READ preload) 0720 0721 /** 0722 * Ths property sets whether the watchedRoute is currently active. 0723 */ 0724 Q_PROPERTY(bool watchedRouteActive READ watchedRouteActive NOTIFY navigationChanged) 0725 0726 private: 0727 explicit PageRouterAttached(QObject *parent = nullptr); 0728 0729 QPointer<PageRouter> m_router; 0730 PreloadRouteGroup *m_preload; 0731 QVariant m_data; 0732 QJSValue m_watchedRoute; 0733 0734 void findParent(); 0735 0736 friend class PageRouter; 0737 friend class PreloadRouteGroup; 0738 friend class ParsedRoute; 0739 0740 public: 0741 PreloadRouteGroup *preload() const 0742 { 0743 return m_preload; 0744 }; 0745 PageRouter *router() const 0746 { 0747 return m_router; 0748 }; 0749 void setRouter(PageRouter *router) 0750 { 0751 m_router = router; 0752 Q_EMIT routerChanged(); 0753 } 0754 QVariant data() const; 0755 bool isCurrent() const; 0756 /// @see PageRouter::navigateToRoute() 0757 Q_INVOKABLE void navigateToRoute(QJSValue route); 0758 /// @see PageRouter::routeActive() 0759 Q_INVOKABLE bool routeActive(QJSValue route); 0760 /// @see PageRouter::pushRoute() 0761 Q_INVOKABLE void pushRoute(QJSValue route); 0762 /// @see PageRouter::popRoute() 0763 Q_INVOKABLE void popRoute(); 0764 // @see PageRouter::bringToView() 0765 Q_INVOKABLE void bringToView(QJSValue route); 0766 /** 0767 * @brief Push a route from this route on the stack. 0768 * 0769 * Replace the routes after the route this is invoked on 0770 * with the provided @p route. 0771 * 0772 * For example, if you invoke this method on the second route 0773 * in the PageRouter's stack, routes after the second 0774 * route will be replaced with the provided routes. 0775 */ 0776 Q_INVOKABLE void pushFromHere(QJSValue route); 0777 /** 0778 * @brief Pop routes after this route on the stack. 0779 * 0780 * Pop the routes after the route this is invoked on with 0781 * the provided @p route. 0782 * 0783 * For example, if you invoke this method on the second route 0784 * in the PageRouter's stack, routes after the second route 0785 * will be removed from the stack. 0786 */ 0787 Q_INVOKABLE void popFromHere(); 0788 /** 0789 * @brief Replaces this route with the given routes on the stack. 0790 * 0791 * Behaves like pushFromHere, except the current route is also 0792 * popped. 0793 */ 0794 Q_INVOKABLE void replaceFromHere(QJSValue route); 0795 bool watchedRouteActive(); 0796 void setWatchedRoute(QJSValue route); 0797 QJSValue watchedRoute(); 0798 0799 Q_SIGNALS: 0800 void routerChanged(); 0801 void dataChanged(); 0802 void isCurrentChanged(); 0803 void navigationChanged(); 0804 void watchedRouteChanged(); 0805 }; 0806 0807 QML_DECLARE_TYPEINFO(PageRouter, QML_HAS_ATTACHED_PROPERTIES)