Wrong work folder in Raspberry QtCreator - qt

When I try to load a file by the relative path via QFile, gives file not found.
QFile file(fileName);
So I output the current work folder to find the problem like this:
qDebug()<<QDir(".").absolutePath();
Output: /home/username
qDebug()<<qApp->applicationDirPath();
Output: /home/username/program/testApp
The second one is the right path to the work folder. So I think QFile didn't load the file from the work folder but the Linux user folder ~. Why didn't QFile load the file refer to the work folder?
I guess this may be a bug in Raspberry's QtCreator. Because the QFile load file is working well if run in the console.

Use QStandardPaths to store data to your OS paths, in this way you would refer to consistent set of locations when you retrieve the file.
For instance:
auto path = QStandardPaths::writableLocation(QStandardPaths::AppDataLocation);
QFile afile;
QString fileName = "/myfile.txt";
path += fileName;
afile.setFileName(path);

Related

How can I add the qrc import path for qtquick plugin?

I have built a static Qt library and want to use it deploy my app with a standalone exe. After one day effort, I have known that the qtquick plugin can not be static include into exe.
I need copy some folders in qml folder to my exe directory to let the exe can show GUI.
So I want to know which file my exe need, I deleted files in those folders one by one to get it known. The real needed file is just a plugins.QMLTYPES file and a qmldir file.
And then I found the import path of QQmlApplicationEngine can be changed, I output the QQmlApplicationEngine.importPathList() and one of paths is just the qml folder in Qt installed path. So I think this is the place where Qt get the search path of plugins.QMLTYPES file and qmldir file.
If all I think is correct, I can just copy the folders I need into qrc file and use QQmlApplicationEngine.addImportPath("qrc:/foldersIwant") to let exe can import what it need on runtime. And because qrc is compiled into exe, I can get rid of those folders and let my exe standalone.
But after I do this in my code, app still can not find the files it need even the output of QQmlApplicationEngine.importPathList() has the path I put into and I have also checked my path according to Load qmldir from QRC file.
Here is the code:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QQmlApplicationEngine engine;
engine.addImportPath(QStringLiteral("qrc:/import/qtquick/"));
qDebug()<<engine.importPathList();
engine.load(QUrl(QStringLiteral("qrc:/qml/main.qml")));
return app.exec();
}
Here is a part of my qrc file
Is there anything wrong in my deductive?
Further research:
I have add
engine.addImportPath(QDir::currentPath() + QDir::separator() + "custom");
and move all folders into custom folders, it can run successfully. And the exe which doesn't have this line can not run with custom folder. So I'm wondering the "search" behavior can not be applied to qrc file ?
Finally, I get the answer. The result shows all my thoughts are correct!
Below is what I had tried and you can just read the end to get the clear steps.
My aim is to compile a standalone qml2 application exe.
In qml1, I can build static Qt library and compile my app with it.
In qml2, the exe can be compiled in same way. But if I run it without Qt-Runtime. It just do not have any window shown on Windows OS (and also show nothing in other OS). I have googled so many informations and found this problem troubled many people since Qt5.0. Now it is Qt5.5, they still haven't repaired it. So I need copy folders in QT_INSTALLED_PREFIX/qml to the root directory of my app to let my app show GUI.
Althrough the problem will be solved in Qt5.6 (https://codereview.qt-project.org/#/c/114835/), I can't wait for so long (Qt5.6 will be released at the end of this year). So I decide to package the files by myself.
And I see this question by chance :Load qmldir from QRC file. It told me that qmldir file can be include into qrc file and the Qml engine can search into those directory. So I think, the QML files can also be included into qrc file.
But the first thing is to find where the qml2 be imported, when I looking into QQmlApplicationEngine's document, I found addImportPath function and I told myself that it must be the key of finding the import path. The document tells me everything:
QStringList QQmlEngine::importPathList()
const Returns the list of
directories where the engine searches for installed modules in a
URL-based directory structure.
For example, if /opt/MyApp/lib/imports is in the path, then QML that
imports com.mycompany.Feature will cause the QQmlEngine to look in
/opt/MyApp/lib/imports/com/mycompany/Feature/ for the components
provided by that module. A qmldir file is required for defining the
type version mapping and possibly QML extensions plugins.
By default, the list contains the directory of the application
executable, paths specified in the QML2_IMPORT_PATH environment
variable, and the builtin Qml2ImportsPath from QLibraryInfo.
After I delete the Qml2ImportsPath in importPathList at runtime, I made a recurrence of the bugs that app do not show any GUI.
And the document of addImportPath tells my that it can accept qrc url. So I add all the files in qml just like the question described above. But I still cannot see any GUI.
After several days of thinking. I found the pic I posted in question do not have qmldir files! That's a bug of Qt Creator. I add files using Add Existing Directory... and set the filter to *, it still cannot include qmldir file. So I add it into qrc file by xml code.
When I think this time it must work, it just gave me nothing. Just when I was going to give up, a thought occurred : it won't waste me more time to check whether qrc:/import/qtquick/ is valid.
The result is false, there must be a mistake in my qrc usage. I change the prefix and save the qrc with Qt Creator. I found the qrc file cannot use the path like D:/Qt/Qt-5.5-static/qml/Qt/labs/folderlistmodel/plugins.qmltypes, it is changed by Qt Creator to Qt/labs/folderlistmodel/plugins.qmltypes. At this time, everything works perfect!
Thanks for you reading my story. Here is a conclusion of steps for solving this problem:
Copy all folders in QT_INSTALLED_PREFIX/qml to your project folder, it is good to put them under a parent folder not the root folder.
Write some code to get all files' relative path except the .lib files and
.prl files.
Create a new .qrc file and include it in .pro file. Include all files into this .qrc file. I wrote a small program to generate the xml.
Add the import path using addImportPath method of QQmlApplicationEngine.
Build and enjoy.

If directory contains exe or msi file, start it with command line arguments

This app is intended for use on Windows only. It is to be built in QT Creator. I'm using 7zip.exe as an example as it is very quick and easy to test with.
I have a list of directories, each one contains a single *.exe or *.msi file.
On pushbutton_clicked() within Qt I want to go to the single directory that I specify and start whichever executable or *.msi file is in that directory. The *.exe or *.msi filename will change from time to time otherwise I could simple use the system command.
system ("start 7zip\7zip.exe /S");
My trouble has been the fact that I want to run a wildcard e.g. *.exe or *.msi and add a command line switch to it.
I now want to execute the single file in path and add the argument /S
I had this working in a batch file:
for /F %%a in ('dir /b 7zip\*.exe') do SET app1=%%~na
%app1% /S
but am unsure how to implement it in Qt.
Thanks
You want to use 2 things: QDirIterator to iterate directories in the system and QProcess to launch the external process with arguments.
Thanks AlexanderVX
They were just what was needed. I'm sure there are many ways to make this more elegant but it does exactly what i want it to do now.
void MainWindow::on_pushButton_clicked()
{
//set initial directory to search for the exe file
QDirIterator file("7zip", QDirIterator::Subdirectories);
while (file.hasNext())
{
file.next();
QString prog = file.fileName(); //get actual filename
QStringList cswitch;
cswitch << "/S"; //create the command switch to use when running the exe
QProcess *install = new QProcess(this); // create new process called install
QDir::setCurrent("7zip"); //set working directory needed to install the exe
install->start(prog, cswitch); //launch the exe with the desired command switch
}
}

Untar a file in an OS X directory with QProcess

I'm trying to untar a file with QProcess that's in a directory returned by QDir::tempPath(), as follows:
extract.start("tar", QStringList() << "-xvzf" + QDir::tempPath() + "/thefile.tar.gz");
I get the correct output for an extraction by looking at the standardOuput for the QProcess but there's no file extracted at the end. Manually running tar from a shell works fine on the file so I know it's not corrupt, I'd have assumed a permissions issue but I'm actually downloading the file with the application to the temporary directory so the application should have write access.
Edit: I've also now tried it with the file in the home directory, it's definitely there but I get the same results as it being in the temp directory, verbose output indicating success but no resulting file.
You need to set the working directory, which by default, is likely to be the folder of the executable's binary.
You can set the working directory with QProcess::setWorkingDirectory

Qt QPixmap constructing with qstring filename

I need to initialize a qpixmap object with its file directory
It works if I do the following:
image = new QPixmap("C:/Users/Administrator/Desktop/maze/HTetris-build-Desktop_Qt_5_0_1_MinGW_32bit-Debug/untitled/c12.bmp");
and it works with as well:
image = new QPixmap("/Users/Administrator/Desktop/maze/HTetris-build-Desktop_Qt_5_0_1_MinGW_32bit-Debug/untitled/c12.bmp");
But this is just too long and too specific.
I have put c12.bmp in the same file as the project itself. But
image = new QPixmap("c12.bmp");
simply does not work.
Since this project needs to be portal, how can I do!!!!!!!
Thanks guys for help
Consider to put your file into resource file (qrc) or put your file near your executable file, because your "c12.bmp" is searched in runtime and must be in the same with executable directory.
You file must be in the file where your application is executed (runtime directory) that can be different than the directory of the executable.
You can use resource files for the portablity (your pixmap will be "embedded" in your binary).
http://qt-project.org/doc/qt-4.8/resources.html

Play a WAV file on Symbian with Qt (QSound)

I'm trying to play a WAV file in Symbian using Qt Creator.
I got this:
QSound::play("c:/notify.wav");
It works on Windows, but when I try it on Symbian it doesn't make a sound, but no error though.
This is most likely because it doesn't find the file (no notify.wav file under C:)
How can I include a WAV file so it gets installed to the Symbian device and so I can use its path to play it?
Use the DEPLOYMENT qmake instruction in your .pro file
e.g:
symbian{
sounds.sources = path to your wav
sounds.path = ./thewav.wav
DEPLOYMENT += sounds
}
This will deploy the wav in your app's directory. QSound::play("notify.wav") should work then, if not try to get the path to your directory from QApplication.
OK, it worked.
This is what I did:
In the .pro file:
symbian: {
sounds.sources = c:/notify.wav
sounds.path = c:/
DEPLOYMENT += sounds
}
In the program:
QSound::play("c:/notify.wav");
This way it works in Windows and in Symbian.

Resources