Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Qt Creator and other tools
  4. How to dynamically generate files in the build directory?
Forum Updated to NodeBB v4.3 + New Features

How to dynamically generate files in the build directory?

Scheduled Pinned Locked Moved Solved Qt Creator and other tools
10 Posts 4 Posters 177 Views 2 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.
  • J Offline
    J Offline
    Jay_emissary
    wrote last edited by Jay_emissary
    #1

    Good morning everyone!
    I have a folder of images, and I'm looking to load one in QML based on the corresponding file name in a JSON file.

    Let's say I would like to load a file named 1.png. In the JSON file, I would need to add the file name

    {"imageFile": "1.png"}
    

    and from my handler.cpp I would need to parse the file:

     QJsonDocument Document = QJsonDocument::fromJson(Bytes, &SyntaxError);
            if (SyntaxError.error != QJsonParseError::NoError){
                qDebug() << SyntaxError.errorString() << "JSON PARSE ERROR";
            }
    
     
            if (Document.isObject()){
              m_imageFilePath = QUrl::fromLocalFile(imFolderDir.path()).toString()+ "/" + Document.object().value("imageFile").toString();
    

    This returns the full file path:

    "file:///C:/Users/xxx/Documents/xxx/build/Desktop_Qt_6_8_3_llvm_mingw_64_bit-Debug/xxx/images/1.png"
    

    m_imageFilePath is a variable exposed to QML, so I should be able to load it

    Image {
        source: handler.imageFilePath
        anchors.centerIn: parent.Center
        width: parent.width
        height: parent.height
    }
    

    But I receive a "Cannot open" error. I believe this is because the image file doesn't get generated in the build location of the project (when I check
    /build/Desktop_Qt_6_8_3_llvm_mingw_64_bit-Debug/xxxx/Images/1.png in file explorer, the file doesn't exist.) To have Qt generate the file, I can specify the location of the file in CMake

    RESOURCES Images/1.png
    

    Here's the problem:
    I would need to manually do this for every file in the folder, and if I expand the folder with more images, I would need a more-dynamic way of generating loading them. Is there a way to get the images in my debug directory to be generated in the build directory, without manually inputting the file paths in CMake?

    Thanks!

    1 Reply Last reply
    0
    • A Offline
      A Offline
      ankou29666
      wrote last edited by ankou29666
      #9

      hmmm you're doing it the wrong way.

      If you need the user to be able to add files into a specific path, then the source and build folders are not the place to put those images in the first place.

      what you should do is allow the user to specify a directory to put those files into and you save / restore that path with QML Settings or QSettings. You still can do it with a JSON file if you really want to, but QSettings is far more appropriate for that purpose, at least in my opinion.
      If you need to monitor the content of the folder and emit a signal when a change has occured in the folder, then you need QFileSystemWatcher.

      1 Reply Last reply
      4
      • Christian EhrlicherC Offline
        Christian EhrlicherC Offline
        Christian Ehrlicher
        Lifetime Qt Champion
        wrote last edited by
        #2

        Put your images in a resource file so you don't have problems with relative paths anymore: https://doc.qt.io/qt-6/resources.html

        Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
        Visit the Qt Academy at https://academy.qt.io/catalog

        J 1 Reply Last reply
        2
        • Christian EhrlicherC Christian Ehrlicher

          Put your images in a resource file so you don't have problems with relative paths anymore: https://doc.qt.io/qt-6/resources.html

          J Offline
          J Offline
          Jay_emissary
          wrote last edited by Jay_emissary
          #3

          @Christian-Ehrlicher Hello,
          My issue is less so the fact that I have to deal with relative paths. It's the fact that I have to explicitly add paths in the first place. Suppose a user adds multiple images to the empty images folder while the app is running. Because we don't know how many images exist in the folder at runtime, if we were to obtain a path to one of those images, we would need to dynamically assemble a path. This is where the JSON file comes in; it has access to the file name and the extension. But to keep things simple:

          Essentially, I would like to set a path to the folder, and the app picks up on all the images in the folder. For some reason, Qt doesn't add the contents of the folder to the build folder, so when I run the project, the files don't exist. I need to, at all costs, avoid manually setting image paths, as the number of images in the folder isn't static; it's user-defined.

          1 Reply Last reply
          0
          • J Offline
            J Offline
            Jay_emissary
            wrote last edited by
            #4

            So far:
            I understand how to locate folders, including the images folder, but I don't know how to get the images folder with the unknown number of images inside the build folder without specifying them either in CMake or qrc.

            To my knowledge, this should be possible. I've seen functions like this in major applications, such as Adobe Photoshop, where you can add a folder full of brush files or fonts, and the app will read and add each one to your toolkit

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote last edited by
              #5

              Hi,

              Usually you have this information in the application settings or in a known hard coded path.
              So in the case of your application, you should add that option in a similar fashion.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              J 1 Reply Last reply
              1
              • A Offline
                A Offline
                ankou29666
                wrote last edited by
                #6

                if you need it at build time, then the best solution is Qt Resource as @Christian-Ehrlicher already stated, thus you solve the problem of relative path. If the sole reason of that JSON file is about path in source/build directory, that file is not needed. If you didn't state those files to be part of the project, then it's normal they are not copied into the build directory.
                Otherwise you can make a python or js script to build that file and call it whenever you need (use a cmake statement to call that script if really needed)

                if you really needed it for whatever other reason, what I would do is instead of a JSON file is use a JS file instead in which you assign the object to a variable and import that JS file into QML, which spares you from JSON parsing in C++.
                In your project you treat that JS file as a QML file.

                /// myfile.js
                var object = { ... }
                
                /// MyComponent.qml
                import myfile.js as myfile
                
                // and use the object as myfile.object
                
                J 1 Reply Last reply
                1
                • A ankou29666

                  if you need it at build time, then the best solution is Qt Resource as @Christian-Ehrlicher already stated, thus you solve the problem of relative path. If the sole reason of that JSON file is about path in source/build directory, that file is not needed. If you didn't state those files to be part of the project, then it's normal they are not copied into the build directory.
                  Otherwise you can make a python or js script to build that file and call it whenever you need (use a cmake statement to call that script if really needed)

                  if you really needed it for whatever other reason, what I would do is instead of a JSON file is use a JS file instead in which you assign the object to a variable and import that JS file into QML, which spares you from JSON parsing in C++.
                  In your project you treat that JS file as a QML file.

                  /// myfile.js
                  var object = { ... }
                  
                  /// MyComponent.qml
                  import myfile.js as myfile
                  
                  // and use the object as myfile.object
                  
                  J Offline
                  J Offline
                  Jay_emissary
                  wrote last edited by
                  #7

                  @ankou29666

                  @ankou29666 said in How to dynamically generate files in the build directory?:

                  If you didn't state those files to be part of the project, then it's normal they are not copied into the build directory.

                  Yes, this is the case with my situation. I have an image folder that the user can add images to while the app is running, so the files won't necessarily exist at compile time.

                  @ankou29666 said in How to dynamically generate files in the build directory?:

                  if you really needed it for whatever other reason, what I would do is instead of a JSON file is use a JS file instead in which you assign the object to a variable and import that JS file into QML, which spares you from JSON parsing in C++.
                  In your project you treat that JS file as a QML file.

                  I think I may have confused you with the whole point of the JSON file. I tried to avoid going in depth for simplicity's sake, but essentially, the JSON file holds dynamic configuration data for the app, including the image it's associated with and the relative path to said image. I'd say it's required for that reason alone. It needs to be parsed by a C++ class specifically, so the class can signal other classes, as well as get referenced later. Otherwise, I totally agree with your workflow!

                  1 Reply Last reply
                  0
                  • SGaistS SGaist

                    Hi,

                    Usually you have this information in the application settings or in a known hard coded path.
                    So in the case of your application, you should add that option in a similar fashion.

                    J Offline
                    J Offline
                    Jay_emissary
                    wrote last edited by Jay_emissary
                    #8

                    @SGaist I'm not sure that I understand. In a practical sense, among many other possibilities, a user could add a file named image1.png or image2.png to the images folder at runtime. How would my app know the full path of the file if there are over 1000 possible image choices? I'd have to hard-code each to get generated at compile time. Because there are many possibilities, I took a more dynamic approach and instead coded the app to read what's in the folder and create paths based on each file. That way, I can select and load a specific file.

                    The only issue I have is that the files I want to read in the images folder aren't copied over in the "build" version of the project due to the paths not being hard-coded in CMake, That said, the image files don't exist on the working build, and I can't load them. I was hoping that there would be a way to have them generated in the build directory, just like the hard-coded cpp, .h, and QML files...

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      ankou29666
                      wrote last edited by ankou29666
                      #9

                      hmmm you're doing it the wrong way.

                      If you need the user to be able to add files into a specific path, then the source and build folders are not the place to put those images in the first place.

                      what you should do is allow the user to specify a directory to put those files into and you save / restore that path with QML Settings or QSettings. You still can do it with a JSON file if you really want to, but QSettings is far more appropriate for that purpose, at least in my opinion.
                      If you need to monitor the content of the folder and emit a signal when a change has occured in the folder, then you need QFileSystemWatcher.

                      1 Reply Last reply
                      4
                      • J Jay_emissary has marked this topic as solved
                      • J Offline
                        J Offline
                        Jay_emissary
                        wrote last edited by
                        #10

                        Ahhh, I see... now that I've taken a break, I didn't realize that my entire process was flawed. The user is going to be adding files to the folder at any point in time, so of course it wouldn't be best to generate those files at compile time, lol. Like you've mentioned, I'll just monitor the folder within C++ and have QML react to the changes. Thank you for the help!

                        1 Reply Last reply
                        1

                        • Login

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