QIODevice::write : device not open - c++

I've been trying to build a card game using Qt recently, but I come across a bug which is very weird.
QFile file(":/file/02");
file.open(QIODevice::ReadWrite|QIODevice::Truncate);
The return value of the second line is false. So when I try to read or write the file, this exception is thrown.
However,the file actually exists and a qrc file in the project writes like this:
<qresource prefix="/file">
<file alias="01">data.json</file>
<file alias="02">deck.json</file>
I've also run qmake after adding this qrc file, but everything remains the same. How can I fix it? Thanks a lot.

According to the docs:
The Qt resource system is a platform-independent mechanism for storing
binary files in the application's executable. This is useful if your
application always needs a certain set of files (icons, translation
files, etc.) and you don't want to run the risk of losing the files.
As it is part of the resource, the files are read only, so if you open it with write permission it will always return false.
In short the files stored in .qrc are static.

Related

Why does giving ":/Icons/controller.png" to a constructor work (is that valid relative filepath syntax)?

The details of the situation don't matter, but in particular I'm making a QIcon object (part of the Qt library) out of a .png file. The constructor for this takes a string that should be a filepath
I find that, instead of using an absolute path, I can simply give something like ":/Icons/controller.png" to the constructor and the icon is still correctly retrieved and displayed.
My project is huge so I won't write out the hierarchy and where the file is relative to everything else, but they're at 3 degrees of separation at least. Because of this I think there's some sort of file searching mechanic that I don't know of. Can anyone guess what's going on here?
:/ paths are paths in the Qt Resource System.
You have a QRC file that is compiled and bundled with your executable. It references the images.
E.g. your qrc file contains this:
<RCC version="1.0">
<qresource>
<file>Icons/controller.png</file>
</qresource>
</RCC>
This is then compiled in your build process with the RCC compiler. This file is then linked with your exe.
The default resources are automatically registered, but you can also compile resources into external RCC bundles, and load them at runtime using QResource::registerResource("/path/to/myresource.rcc");

C/C++ project under Visual Studio : Not found resources

When I run the Debug in Visual Studio for a project, fopen function works fine. It tries to open a file contained in the project and that I added in the filter "Resources".
But when I run .EXE file of my project, I get the null pointer exception: 0x000005c.
When I added the file to be in the same directory as my .EXE file, the exception disappeared.
This is the instruction I use :
fopen(&filename, "rb");
I know it is adviced to use fopen_s instead, but the file is not found anyway...
Apparently, the file is searched always in the current directory...
So, how to include the file in .EXE and make the path of the file relative to the .EXE, at a way it will be contained in the .EXE and not added to the directory where there is .EXE?
You can't include the file in the .exe. You just need to make sure that the file is in the same directory as the .exe.
If you really, really want to only use one file, you could either:
Zip the .exe and the text file together and make sure you include in a readme that the text file needs to be in the same location as the .exe
Use an array/struct/some other way of storing the contents of the file in the program itself, and reference that instead of using a file (I assume you don't care about users being able to edit this data outside of an instance of the program since you wanted it bundled with an executable, so the file is unnecessary in that case)
The reason the program only works when you put the file in the directory of the .exe is because the path to the file is defined in the program as something like .\file.txt or file.txt. When the file isn't in the same directory as the .exe, the program will try to find it, and will be unable to, which is why you get the error. It works when you debug because you have a copy of the text file in the same location as the debug .exe.
EDIT: I would also ignore the warnings about fopen_s and other variant's that append a _s to the end of a command - these are windows specific, non-standard, and in most cases, pointless. If you know this program will only be used in windows environments and you're not doing something for school where you are required to write standard code, I suggest you use the _s variants for the sake of security, but it will reduce portability of your code.

Extract absolute file path from a QRessource loaded file

I have a file in /home/me/xmls/foo/bar.xml
and a correct qrc file containing this path
The folowing code :
QFileInfo f (":/foo/bar.xml");
cout<<f.absoluteFilePath().toAscii().data()<<endl;
outputs:
:/foo/bar.xml
when i was expecting:
/home/me/xmls/foo/bar.xml
Is there any way to recover the absolute path in the system of a QRessource loaded file ?
QResource encodes its contents into a file that gets compiled into the final binary. So, no I would expect it is not possible to get the original path at run time. As the Qt docs state: -
The Qt resource system is a platform-independent mechanism for storing binary files in the application's executable
Also, it doesn't make sense to want the original path, as other users are unlikely to have the file at that location.
This :
QFileInfo f (":/foo/bar.xml");
means that you are going to load a file from the resource file. Basically, this is a library (static or shared), which contains resources (images, translations, etc).
That is a standard syntax to access a file in the resources, as explained in their documentation for the resources.

Open a file in current directory

I'm trying to open a file where my program runs, I could open a file in directories like this:
myfile.open("D:\\users.txt");
But I want to open this file:
myfile.open("users.txt");
users.txt is placed where my program is.
users.txt is placed where my program is.
The current working directory of your process may not be where your program executable is. The two are not bound together.
This:
myfile.open("users.txt");
should work just fine. However, I have encountered situations where the program could not read the file. That was due to the white spaces being included within the full path:
eg: "C:\Folder1\Folder 2\file.txt"
Make sure you don't have any white spaces there...
I recommend reading up on Naming Files, Paths, and Namespaces to give you a better understanding how Win32 API handles File paths, and also Namespaces. It will help you in the long run when you need to open USB and Serial connections to external devices.

Qt Resource Files don't update without compiling

I am making a C++ application, and I created a function that will apply a stylesheet from a css file. This is the method:
void MainWindow::load_css_file() {
QFile styleFile(":/light_style_css");
styleFile.open(QFile::ReadOnly);
QString styleSheet = styleFile.readAll();
setStyleSheet(styleSheet);
};
This works fine, except for the fact that I need to run "make" every time I make a change to "light_style_css" (which is an alias for a css file in my project resource file).
But, when I change the method to something like this:
void MainWindow::load_css_file() {
QFile styleFile("../stylesheets/light_style.css");
styleFile.open(QFile::ReadOnly);
QString styleSheet = styleFile.readAll();
setStyleSheet(styleSheet);
};
I can make changes to the file, and the program updates without having to run "make" for the changes to take place.
Is there a way, that I can use the resource system, without having to run "make" for the changes to take place?
This is my resource file:
<!DOCTYPE RCC><RCC version="1.0">
<qresource>
<file alias="light_style_css">stylesheets/light_style.css</file>
</qresource>
</RCC>
Simply said: no, you can't.
Resources are built into your executable. If you want to change them, you need to rebuild the executable.
Your second method reads the file from disk, so it doesn't have that behavior.
If this is a real problem for you, give the possibility to pass in the stylesheet as an argument on the command line, and default to the resource. That way you can debug the stylesheet as much as you want without recompiling every time. Rebuild once it's satisfactory (and before you ship!).
We do the following solution in our project (I can't provide code because of company policies):
First, we build all resources to separate binary .rcc file. It is not necessary, but helpful.
Second, In release builds we always load resources from the Qt resource system.
Third, only in debug builds:
We check the resource folder for a main.qss file.
If it exists: we open it and replace all :/ with ./resource/ string, then apply it
If it doesn't exist: we load resources as in the release version.