Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. QQuickView.rootObject() issues, dynamic signal/slot management design
Qt 6.11 is out! See what's new in the release blog

QQuickView.rootObject() issues, dynamic signal/slot management design

Scheduled Pinned Locked Moved QML and Qt Quick
8 Posts 2 Posters 5.6k Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • ? Offline
    ? Offline
    A Former User
    wrote on last edited by
    #1

    Hi all,

    first what i'm trying to do: [maybe there is another (easier) 'design pattern' to this, since i can't imagine this problem didn't arise to anyone before]

    i have one single QQuickView Window which should support switching between different "root" QML Files, e.g. you got "ProjectManagement" and "Wizard", both are loaded via setSource() und both define signals unique to them (which are emitted somewhere inside their respective qml tree)

    The MainWindow (class inheriting QQuickView) has a pointer to a QObject, which offers the slots for the currently displayed qml. After loading a new root qml, the qml itself calls a slot in the mainWindow (exported via a property in the rootContext) and requests a certain slotProvider. The mainWindow itself is 'agnostic' regarding to the qml it is displaying, it just knows about all possible slotProviders which are stored in a map with string keys. The mainWindow (or SlotManager as i called it in the code) disconnects the previous slotProvider and asks the new one to connect his stuff to the signals. So the sequence in short:

    0 - SlotManager creates N QObjects offering slots (SlotProvider), stored in QMap<QString, QObject*>
    1 - qml is loaded and does e.g. Component.onCompleted: { SlotManager.setSlotProvider('mainMenu') }
    2 - SlotManager sets currentSlotProvider to the correct pointer from his map and calls a method inside
    the provider which connects his slots to the signals, the latter are defined in the root element of the qml
    (3 - qml could request a new root element, which in turn request a new slotProvider and disonnects the old one)

    So far the design part, maybe this could be done even better/nicer, basically i just need dynamic slots which are requested from the qml side. And thoses slots need to be C++ (at least partial) to offer some low-level stuff qml can't provide.

    Now the problem: in order to connect the slots i need a valid QQuickView.rootObject(), because thats the Object which emits the signals, but it seems i can't track the moment this gets non-null from qml. This is what i've tried so far:

    1- using Component.onCompleted (inside qml), calls a slot in the exported C++ Object which just prints the pointer, which is null at this moment (as far as i have googled on this, onCompleted gets called after parsing is done, so this won't guarantee a valid pointer?)
    2 - using onStatusChanged() (in qml), still null
    3 - using onStatusChanged in cpp, (with Status = Ready) not null
    4 - checking the pointer just after the setSource call in cpp, not null

    Now i could of course do it from cpp side by enforcing a common interface function in qml, so the cpp side actively requests the required slot provider, as in:
    setSource("SomeThing.qml");
    invokeMethod( rootObject(), "getProvider" );
    but i'd like to avoid having such an interface, because the qml side should be the one which starts the whole process.
    Or maybe Qt already offers something for this, i just haven't found it yet?

    Any hints are appreciated! :)

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      If you are ready for another level of indirection, I guess you could make a single, global QML file containing a simple Loader element that would load your current qml code on demand. This way your rootObject would be valid at any time. However, with the engine caching it's items you could run into high RAM usage.

      (Z(:^

      1 Reply Last reply
      0
      • ? Offline
        ? Offline
        A Former User
        wrote on last edited by
        #3

        bq. If you are ready for another level of indirection, I guess you could make a single, global QML file containing a simple Loader element that would load your current qml code on demand. This way your rootObject would be valid at any time. However, with the engine caching it’s items you could run into high RAM usage.

        Well this should work obviously, but then the comfort of having the signal declarations at root level would be lost right? That is, i would have to do a findChild(dren) on the rootObject (which is the Loader, not the actual loaded component) or use the item property of the Loader. But i guess this (using Loader.item) would show the same "null/non-null" behaviour as if i would have loaded it as the root element in the first place? Will check that out...

        1 Reply Last reply
        0
        • sierdzioS Offline
          sierdzioS Offline
          sierdzio
          Moderators
          wrote on last edited by
          #4

          Yeah, I realise that even if it would work it's not a very good solution.

          (Z(:^

          1 Reply Last reply
          0
          • ? Offline
            ? Offline
            A Former User
            wrote on last edited by
            #5

            As far as i could test this, it somewhat does what it should:
            onLoaded slot in a Loader seems to guarantee a non-null Loader.item property (else onLoaded shouldn't be signaled in the first place, right?)
            The item can be passed to the SlotManager which does the connect/disconnect magic.
            And for the caching stuff, even if everything would be active at the same time, we would be far from lets say 1 GB RAM. Its just approx 8 "screens" with some controls and logic in the cpp background, its not Doom 5 :)

            1 Reply Last reply
            0
            • sierdzioS Offline
              sierdzioS Offline
              sierdzio
              Moderators
              wrote on last edited by
              #6

              Hehehe ok, I'm happy it works for you, even if only "somewhat".

              (Z(:^

              1 Reply Last reply
              0
              • ? Offline
                ? Offline
                A Former User
                wrote on last edited by
                #7

                After sleeping a night over it, it think it's even easier and safer to just export all classes which provide slots to the rootContext and allow to call them directly. You would circumvent the whole signal/slot mechanism (which is of course a not very qt'ish design approach), but i'm safe that the pointers will be around. Is there some documentation about the lifespan of the rootContext? Does it stay the same for the whole lifespan of a QQuickView and its engine?

                1 Reply Last reply
                0
                • sierdzioS Offline
                  sierdzioS Offline
                  sierdzio
                  Moderators
                  wrote on last edited by
                  #8

                  No idea. You can safely ping QtQuick developers on IRC or interest mailing list, though, they should know. You can aim at Alan Alpert, Jerome Pasion or Topi Reinio.

                  (Z(:^

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved