3

I am totally new to Qt and CMake. I have been doing a google test on my project (cmake and qt) for which I need to test the match of two images. I have a folder (outside the project directory) that contains these images. I want to access these images but not using the absolute path.

Something like this:

imread("home/../../test_images/img1.jpg")

But I want to set a common path for the images folder, so that anybody using my project later on will just have to set their test_image folder path with respect to their machine, and need not make changes in the code.

I have tried the following so far.

1 . Tried adding a .qrc resource file and tried to access the images. (This did not work since the images folder was outside the project directory.)

  1. Tried to set a Path variable in QT build environment settings.

None of the two methods worked.

What I am trying to accomplish: "To be able to avoid using an absolute path for the images I use and allow people trying to implement my code to only change the path at one place with their own test image locations."

Edit: Looking for a way for setting a variable eg.IMG_PATH = "/path/to/image/files" which can be set once and only the variable is used all over the executable files. So when someone clones my project they will just have to update the IMG_PATH variable with the path to where their image files are located. So that now the IMG_PATH variable gets updated everywhere in the remaining parts of the project.

UPDATE after answer given by @squareskittles :

My project Structure :

Project_Tester

|--CMakeList.txt

|--ExecutableScript.sh.in   

|--test

       |---CMakeList.txt

       |---sample1.cpp

       |---sample2.cpp

       |---main.cpp

Sample 1,2 are c++ files with different testcases. The main.cpp runs all tests in the sample.cpp files, as below :

#include "gtest/gtest.h" 

int main(int argc, char** argv)
 { 
       ::testing::InitGoogleTest(&argc, argv);

       return RUN_ALL_TESTS(); 
}

According to answer given by @squareskittles , How should i structure my main.cpp ,to be able to use/access the variable "IMAGES_PATH" in the files sample1.cpp and sample2.cpp ?

  1. Is there a way to do it from QT Creator alone than running it from the terminal ?(by modifying .sh file contents)?

  2. Or can the Path be set manually in the ExecutableScript.sh.in file ?

  3. How can I access this variable that is set, from the other cpp files of the project ?

Debby
  • 33
  • 1
  • 5
  • 2
    You are wrong trying to solve your issue with the build system, CMake or whatever. The build systems are for building the executables. The data path of a program should be allowed to change without needing to rebuild the program each time the user decides to process files in a different directory. – Former contributor Sep 26 '19 at 11:26
  • @Pedro So how should I proceed from here ? Is there any other approach you'd like to suggest that is close to this or similar ? In a way in which my project could know where to find the image files . – Debby Sep 26 '19 at 11:34
  • I agree with @Pedro. You should look into using a command line argument to import the path to the local image files into your executable. You can use something like CMake to configure the default path in, say, an executable start script with default command line arguments for the executable. Yet, it should still be command line configurable after-the-fact. – Kevin Sep 26 '19 at 11:41
  • @squareskittles This sounds exactly like what I am trying to accomplish . Following up with your suggestion I looked up for "How to pass a command line argument for an executable ?" . So by the above were u suggesting me to use the argc and argv methods to pass the "path" ? Since I could'nt find any more information can you please advice me on how to proceed or how to pass the "path" using argc and argv? – Debby Sep 27 '19 at 03:35

2 Answers2

0

Define your pictures path in your program settings. Use the QSettings class to store (persist) and retrieve your program settings when needed. You may want to provide your uses with a QDialog to edit your program settings. Here is an example of a portable app doing that.

Former contributor
  • 2,466
  • 2
  • 10
  • 15
  • Thank you for your response . I checked your example . But I am not looking forward to provide any form of UI . I am looking for a way to do something simple like , setting a variable eg.IMG_PATH = "/path/to/image/files" which can be set once and only the variable is used all over the executable files . So when someone clones my project they will just have to update the IMG_PATH variable with the path where their image files are located . So that now the IMG_PATH variable gets updated eveyrwhere in the remaining parts of the project . – Debby Sep 26 '19 at 10:44
  • 1
    Then, if your program is a command line program, the IMG_PATH could be a command line argument. See [QCommandLineParser](https://doc.qt.io/qt-5/qcommandlineparser.html) class. If you prefer, it may also be an environment variable. Then look to [QProcess::systemEnvironment()](https://doc.qt.io/qt-5/qprocess.html#systemEnvironment) – Former contributor Sep 26 '19 at 11:33
  • @Debby May I ask, what you are using Qt for, if not for UI? – nada Sep 26 '19 at 11:38
  • @Pedro I will surely try the mentioned approaches and give Updates .Thanks a lot . – Debby Sep 26 '19 at 11:50
  • @nada It is a small test I am trying to write for an application that might add some UI features later on . So I need my implementations to be as simple as possible . – Debby Sep 26 '19 at 11:52
  • @Debby Interesting. Just keep in mind Qt is not a lightweight framework. – nada Sep 26 '19 at 12:00
0

To expand my suggestion, you can use CMake to grab an initial default path from the user configuring and building the project. CMake can grab the path from the command line like this, then use configure_file() to populate an executable start script with the provided path.

Run cmake with the -D option like this to populate a CMake variable called IMAGES_PATH:

cmake -DIMAGES_PATH=/my/path/to/imagefiles ..

Add a configure_file() call to your CMakeLists.txt to generate an executable start script:

...
configure_file(
    ${CMAKE_SOURCE_DIR}/MyExecutableStartScript.sh.in 
    ${CMAKE_BINARY_DIR}/MyExecutableStartScript.sh @ONLY
)

This call reads in the template file (MyExecutableStartScript.sh.in) and will generate a new MyExecutableStartScript.sh file, replacing the @IMAGES_PATH@ variable in your template start script with the actual path to the images. The template file would look something like this:

#!/bin/sh

./MyExecutable "@IMAGES_PATH@"

The populated start script (after running CMake) would be renamed MyExecutableStartScript.sh and contain this:

#!/bin/sh

./MyExecutable "/my/path/to/imagefiles"

A simple C++ executable to read this command line path argument could look something like this:

#include <string>
#include <iostream>

int main(int argc, char ** argv) {
    string imagesPath = "";
    if( argc == 2 ) {
      imagesPath = argv[1];
    } else {
      std::cout << "Usage: ./MyExecutable /path/to/images" << std::endl;
      return 1;
    }
    ...
}

Once the executable is built, the path to your images can easily be changed by modifying the generated start script manually. Most importantly, this example allows you to set a default location once at the beginning, but you also wouldn't require a code re-build to change the image file path.

Kevin
  • 16,549
  • 8
  • 60
  • 74
  • Thank you so much for the detailed answer . I tried it and had a few questions . I have updated my answer for you to explain the scenario . Could You please tell me how to handle it ? – Debby Sep 30 '19 at 07:34
  • **"Once the executable is built, the path to your images can easily be changed by modifying the generated start script manually "** - does this mean I can directly edit the **script.sh.in** file generated with my image path ? If yes , should I replace the **@IMAGES_PATH@** with my path ? Also how to access this variable from the other c++ files of the project ? Kindly have a look at my project structure and please let me know. Thanks again. – Debby Sep 30 '19 at 11:00
  • @Debby You don't want to manually modify the `script.sh.in` file, this is a template file and CMake will do the `@IMAGES_PATH@` variable replacement here. However, if you want to change the path again, *after you run CMake*, you can manually modify the generated `script.sh` file if necessary... – Kevin Sep 30 '19 at 11:48
  • @Debby With regard to accessing this command line parameter from your test files, see [this answer](https://stackoverflow.com/a/5262122/3987854) for a solution. – Kevin Sep 30 '19 at 11:49