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. Loading UI Form from disk, logic deployed as resource

Loading UI Form from disk, logic deployed as resource

Scheduled Pinned Locked Moved Solved QML and Qt Quick
11 Posts 3 Posters 1.7k 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.
  • T Offline
    T Offline
    ThoPa
    wrote on last edited by
    #1

    I'm currently working on an application in which I want to give the opportunity to customize the look and feel of the application.

    Is there some way to load the UI part from disk (eg. a subdirectory of the applicationDirPath), while the logic to this form is contained as qrc?

    Adding the disk path as importPath to the qml engine does not work.

    In depth:
    I add the path to Page3Form.ui.qml to the engine's importPath.
    If I push Page3.qml (contained in the qrc) to a stackView, Page3Form can't be found (Page3Form is not a type).

    Page3.qml:

    import QtQuick 2.7
    
    Page3Form {
    
    }
    

    Page3Form.ui.qml:

    import QtQuick 2.7
    import QtQuick.Controls 2.0
    
    Page {
        width: 600
        height: 400
    
        title: qsTr("Page 3")
    
        Label {
            text: qsTr("You are on Page 3.")
            anchors.centerIn: parent
        }
    }
    

    If I add Page3Form.ui.qml to the resource file, the test app is working as expected.

    1 Reply Last reply
    0
    • T Offline
      T Offline
      ThoPa
      wrote on last edited by
      #2

      Or does anyone know a way to make the UI customizable without exposing my program logic?

      1 Reply Last reply
      0
      • fcarneyF Offline
        fcarneyF Offline
        fcarney
        wrote on last edited by
        #3

        Is Page3Form.ui.qml in the same directory? I guess it cant be if one is in a qrc.

        Also for importing:
        https://stackoverflow.com/questions/22168457/include-another-qml-file-from-a-qml-file

        Maybe try putting your user customizable qml in a directory that is imported?

        C++ is a perfectly valid school of magic.

        1 Reply Last reply
        0
        • fcarneyF Offline
          fcarneyF Offline
          fcarney
          wrote on last edited by
          #4

          I have tried to load qml files from the local directory and while it acts like it will work in the editor it will not see those files when running. I don't see a way to make qml files that are qrc resources to "see" files that are local on the disk. There has to be a way though. It seems silly that you could not mix them.

          C++ is a perfectly valid school of magic.

          1 Reply Last reply
          0
          • fcarneyF Offline
            fcarneyF Offline
            fcarney
            wrote on last edited by
            #5

            I checked the qml import path:

            qInfo() << engine.importPathList();
            

            It returns the local directory of the application. I have qml files and directories placed there and it will not import the files or directories from there.

            C++ is a perfectly valid school of magic.

            1 Reply Last reply
            0
            • fcarneyF Offline
              fcarneyF Offline
              fcarney
              wrote on last edited by
              #6

              I can import relative path qml files this way:

              import 'file:qml' as QML
              ...
              QML.TestComponent02 {
              
                  }
              

              Where qml is a directory in the current directory of where the executable runs and TestComponent02 is TestComponent02.qml in that qml directory. I cannot find a way to import the current directory path.

              I found this where some of this is discussed:

              https://stackoverflow.com/questions/45484222/qml-import-external-javascript-file
              

              C++ is a perfectly valid school of magic.

              1 Reply Last reply
              0
              • T Offline
                T Offline
                ThoPa
                wrote on last edited by
                #7

                @fcarney said in Loading UI Form from disk, logic deployed as resource:

                I can import relative path qml files this way:

                import 'file:qml' as QML
                ...
                QML.TestComponent02 {
                
                    }
                

                I could live with a fixed subdirectory of the applicationDirPath, but this only works for me with an absolute path, like

                import "file:D:/Projects/qmltest/qml" as QML
                

                I added both the applicationDirPath and the qml-subdir to the importPathList, with no luck. Did you add anything else to get this to work? Is the file containing this import loaded from qrc?

                @fcarney said in Loading UI Form from disk, logic deployed as resource:

                I found this where some of this is discussed:

                https://stackoverflow.com/questions/45484222/qml-import-external-javascript-file
                

                Unfortunately this seems to work only for javascript files (and not qml).

                J.HilkJ 1 Reply Last reply
                0
                • T ThoPa

                  @fcarney said in Loading UI Form from disk, logic deployed as resource:

                  I can import relative path qml files this way:

                  import 'file:qml' as QML
                  ...
                  QML.TestComponent02 {
                  
                      }
                  

                  I could live with a fixed subdirectory of the applicationDirPath, but this only works for me with an absolute path, like

                  import "file:D:/Projects/qmltest/qml" as QML
                  

                  I added both the applicationDirPath and the qml-subdir to the importPathList, with no luck. Did you add anything else to get this to work? Is the file containing this import loaded from qrc?

                  @fcarney said in Loading UI Form from disk, logic deployed as resource:

                  I found this where some of this is discussed:

                  https://stackoverflow.com/questions/45484222/qml-import-external-javascript-file
                  

                  Unfortunately this seems to work only for javascript files (and not qml).

                  J.HilkJ Offline
                  J.HilkJ Offline
                  J.Hilk
                  Moderators
                  wrote on last edited by
                  #8

                  @ThoPa
                  I haven't tried this, but you could give your qml engine the applicationDir path as contextproperty

                  setContextProperty("applicationDirPath", QApplication::applicationDirPath());

                  Maybe the import accepts that as valid path ?


                  Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                  Q: What's that?
                  A: It's blue light.
                  Q: What does it do?
                  A: It turns blue.

                  T 1 Reply Last reply
                  0
                  • J.HilkJ J.Hilk

                    @ThoPa
                    I haven't tried this, but you could give your qml engine the applicationDir path as contextproperty

                    setContextProperty("applicationDirPath", QApplication::applicationDirPath());

                    Maybe the import accepts that as valid path ?

                    T Offline
                    T Offline
                    ThoPa
                    wrote on last edited by ThoPa
                    #9

                    @J.Hilk said in Loading UI Form from disk, logic deployed as resource:

                    @ThoPa
                    I haven't tried this, but you could give your qml engine the applicationDir path as contextproperty

                    setContextProperty("applicationDirPath", QApplication::applicationDirPath());

                    Maybe the import accepts that as valid path ?

                    Yeah, I tried that, but you can't use variables in import statements.

                    But I guess I found another workaround.
                    If I create my own NetworkAccessManagerFactory and pass it to the qmlengine, use my own scheme in the import statement and redirect this to the local dir, it seems to work:

                    QNetworkReply* createRequest(QNetworkAccessManager::Operation op, const QNetworkRequest& originalRequest, QIODevice* outgoingData = nullptr) {
                          if (op == QNetworkAccessManager::GetOperation) {
                            QUrl url = originalRequest.url();
                    
                            if (originalRequest.url().scheme() == "test") {
                              QUrl nurl = QUrl::fromLocalFile(QString("%1/qml%2").arg(qApp->applicationDirPath()).arg(url.path()));
                              
                              QNetworkRequest req(originalRequest);
                              req.setUrl(nurl);
                              
                              return QNetworkAccessManager::createRequest(op, req, outgoingData);
                            }
                          }
                    
                          return QNetworkAccessManager::createRequest(op, originalRequest, outgoingData);
                        }
                    

                    And in my Page3.qml from qrc:

                    import "test://qml" as Test
                    
                    Test.Page3Form {
                    
                    }
                    

                    Thanks for the help!

                    1 Reply Last reply
                    0
                    • fcarneyF Offline
                      fcarneyF Offline
                      fcarney
                      wrote on last edited by
                      #10

                      You have to copy the qml files to the actual run/build directory for it to see the files. The path of that directory is added to the qml import paths. So wherever the exe is actually running from is the path that shows up as "local" to the program. I had to explicitly copy those files. So if you want to have your source qml be seen after changes you may want to add the copying of those files to the build process script (pro file).

                      C++ is a perfectly valid school of magic.

                      1 Reply Last reply
                      0
                      • fcarneyF Offline
                        fcarneyF Offline
                        fcarney
                        wrote on last edited by
                        #11

                        Another option that you could use for development is to add an additional import path:

                        engine.addImportPath("D:/Projects/qmltest/qml");
                        qInfo() << engine.importPathList();
                        

                        Then during development you don't have to copy files.

                        C++ is a perfectly valid school of magic.

                        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