Qt C++: Save project in file [duplicate] - c++

This question already has answers here:
Qt - How to save a configuration file on multiple platforms
(4 answers)
Closed 9 years ago.
I would like to save data from memory to some file. This includes QFileSystemModel and others which are important for program to create some progress. How to create some export file from where those settings would be read and how to read it?

Create some schema for storing all the important persistent variables for your class/file.
Make a save function that pushes all these variables out to a file.
Make a load function that retrieves all these variables from a file.
If your file has a lot of binary data or a large structure you probably should make your own.
Qt has XML and JSON available if one of those make sense to use. (Tree's or node based information).
http://qt-project.org/doc/qt-4.8/examples-xml.html
http://qt-project.org/doc/qt-4.8/xmlpatterns-filetree.html
http://qt-project.org/doc/qt-5.0/qtcore/json.html
If they are a few settings variables, that are short, such as a string or two, or native Qt objects, like a QRect, a QPoint, a QStringList, etc, you can do it with QSettings.
Also QSettings has a really nifty way of handling defaults, and fall-backs, and using the application name and the organization name. I like the INI-format.
http://qt-project.org/doc/qt-5.0/qtcore/qsettings.html
Hope that helps.

Related

Qt : Avoid Rebuilding Applications incase strings change

I wanted to know what my options are for storing strings in a QT application.
One of my major requirements in not re-building the entire project or any file in-case one string changes and also have all the strings in one place.In short I would like to have the strings in one place and extract them during Application startup
I've used all of the elements talked about in above answers.
XML, JSON, QSettings w/ Ini files, tr()
All of them can do it just fine. I've put together some notes on the different options:
QTranslator
Qt Linguist and the tr() tags are designed to take your stock language and translate it into another language. Keeping track of multiple versions of the english translation and modifying/releasing without Qt Linguist is almost impossible. Qt Linguist is required to "release" your translations and convert them from a TS file (translation source) to an optimized QM file.
The QM file format is a compact binary format that is used by the localized application. It provides extremely fast lookups for translations.
Here is what using a translation file looks like:
QTranslator translator;
translator.load("hellotr_la");
app.installTranslator(&translator);
http://qt-project.org/doc/qt-4.8/qtranslator.html#details
I think using QTranslator for a few string changes may be a weird use case, unless you are using for localizing your program. But like the docs say, it is optimized for very fast look ups of string replacements.
QXMLStreamReader
The stream reader is "recommended" way to access XML files, or at least with better support. You write your own files for organizing it, or you write code to generate the XML.
<STRING_1>Some string</STRING_1>
Here is what it looks like to navigate into xml.
QXmlStreamReader xml;
...
while (!xml.atEnd()) {
xml.readNext();
... // do processing
}
if (xml.hasError()) {
... // do error handling
}
XML is very similar to Json, but with larger files and the start and end tags are longer. There are a lot more stock readers out there for XML. It is also a lot more human readable in many cases because so many people know html and they are very similar.
QJsonDocument
The JSON suppport in Qt 5 looks really good. I haven't built a project with it quite yet It is as easy as it looks, and as far as accessing and setting, it looks just like using a dictionary or a map or a vector.
UPDATE: You just pass around a pointer into your QJsonDocument or your QJsonObject or your QJsonArray as you are navigating deeper or appending more onto your Json file. And when you are done you can save it as a binary file, or as a clear text, human readable file, with proper indentation and everything!
How to create/read/write JSon files in Qt5
Json seems to be turning into the replacement for XML for many people. I like the example of using Json to save and load the state of a role playing game.
http://qt-project.org/doc/qt-5/qtcore-savegame-example.html
QSettings
QSettings is one of my favorites, just because it has been supported for so long, and it is how most persistent settings should be saved and accessed.
When I use it, to take advantage of the defaults and fall back mechanisms, I put this in my main.cpp:
QCoreApplication::setOrganizationName("MySoft");
QCoreApplication::setOrganizationDomain("mysoft.com");
QCoreApplication::setApplicationName("Star Runner");
And because I sometimes find a need to edit these setting by hand in windows, I use the Ini format.
QSettings::setDefaultFormat(QSettings::IniFormat); // also in main.cpp
Then when I deploy my exe, and I want to have particular value loaded instead of the hardcoded defaults, the installer drops the main fallback into
C:/ProgramData/MySoft/Star Runner.ini
And when the program saves a change at runtime, it gets saved to:
C:/Users/<username>/AppData/Roaming/MySoft/Star Runner.ini
And then throughout my program if I need to get a setting or set a setting, it takes 3 lines of code or less.
// setting the value
QSettings s;
s.setValue("Strings/string_1", "new string");
// getting the value
QString str;
QSettings s;
str = s.value("Strings/string_1", "default string").toString();
And here is what your ini file would look like:
[Strings]
string_1=default string
QSettings is the way to go if you are storing a few strings you want to change on deployment or at runtime. (or if a checkbox is now checked, or your window size and position, or the recent files list or whatever).
QSettings has been optimized quite a bit and is well thought out. The ini support is awesome, with the exception that it sometimes reorders groups and keys (usually alphabetically), and it may drop any comments you put in it. I think ini comments are either started with a ; or a #.
Hope that helps.
One way to do this would be to put it in a shared library. This way you can only recompile the shared library, but not the whole project. Another approach would be to put it in a file or a database and load it at runtime.
And of course you have to check your include dependencies. If you are including the headers everywhere, the compiler will rebuild everything that depends on it, even if the header is not really needed.
Another possible solution is to replace all strings with default ones inside tr() calls and use Qt Linguist to manage all the strings.
You'll also be able to load all the "translations" from external .qm file on startup.
It is simple: Store your volatile strings in QSettings http://qt-project.org/doc/qt-4.8/qsettings.html (you can use ini files or registry) or an XML file which will make you application configurable.
Edit: Well, after thinking about it a few more minutes, Guilherme's comment is right. QSettings will need to be initialized somehow (either manually or from some default values in your code)... and to be honest manual editing registry to change a few strings is not the brightest idea. So I conclude that XML or JSON is definitely better. It has advantages, for example you can keep several config files which allow you for switching languages at runtime etc.

Edit an existing file in C++

I have preferences file for my application in Qt.
Whenever I launch the application it loads the file & depending the contents creates the widgets accordingly. I have given some customisation option for the user. Now when my application is closed I am checking whether the preferences are changed. If yes then I am opening the preferences file again & then just adding everything again in it. I am not creating a temporary file, I am directly editing the file. Is this method an efficient one? or am I doing it wrong? because I found these threads:
1. What is the best way to edit the middle of an existing flat file?
http://qt-project.org/forums/viewthread/25924/
Should use I binary file? Currently I am using ASCII file.
Thanks.
UPDATE: In the stackoverflow link above the correct answer has
If you're stuck using flat, then you're stuck using the old fashioned
way of updating them
I meant to ask whether the method I am using is old fashioned & is there a better method used nowadays? & what does flat file mean?
Don't try to edit the file. Rewrite the whole thing
Rewrite by using a temporary file. i.e. write the current state of preferences into temp file. And then move/rename the file to your actual preference file after making sure the temp file has been written successfully. This helps in case there is a crash when you rewriting the file. If you rewrite it directly, you will be left with neither the old one nor a good new one. In case you do it through a temp file, then do it this way ensures that in case of a crash, you atleast have a good preferences file(though it contains the old preferences).
Text/Binary doesn't make much difference unless it's a really huge file. Text will help to hand edit it if required.
That's a perfectly fine way of doing it. Since you already seem to have all of the preferences loaded into memory and you have edited them there, you don't need to bother with a temporary file (unless you want to ensure safety if your program fails during writing). Just write all of the preferences back into the original file.
Whether you choose a binary file or text file is up to you. Preferences tend to be text files because they have the added benefit of being human readable with just a text editor, rather than some specialised software for viewing them. A binary file may, however, have slightly better performance due to simpler decoding.

is there any reference/resource about how to design the structure of a data file? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
What are important points when designing a (binary) file format?
I am going to develop a program which will store data in file.
The file can be big. The data in the file is basically made up with variable length records. And I need random access to the records.
I just want to read some resouces/books about how to design the structure of a data file. But I can't find any yet.
Any suggestion is much appreciated.
You might find http://decoy.iki.fi/texts/filefd/filefd useful. It's a general starting point to the techniques to consider.
Also look at this question here on SO: What are important points when designing a (binary) file format?
The problem you describe is a central theme of Database Theory.
Any decent text on the subject should give you some good ideas. The standard text from uni was:
Fundamentals of Database Systems- Elmasari & Nava (PDF) (Amazon)
Another approach is to use a memory mapped array of structs, take a look at my bountied answer to a similar question
Yet another approach is to use a binary protocol like Google protobuf and "send" your data to the file when writing and "receive" it when writing.
If the answer you're looking for is "what book to read" I can't help.
If "how do to that" may be good for you as well I've some suggestions.
One good solution is the one suggested by Srykar; I would just add that I'd use SQLite instead of MySQL. It's an open source C library that you can embed in your program. It lets you store data in a DB just the way you'd do with SQL statement, but calling the library C functions instead. In your case you may keep everything in memory and then save the data to disk at proper time.
Reference:
http://www.sqlite.org
Another option is the old "do it yourself way". I mean: there's nothing very complicated about storing your data to a file (unless your data is very very structured, but I'd go with option nr. 1 in this case).
You write down a plan of how you want the structure of your file to be. And you follow that plan both when writing the file to disk and when reading it re-storing the data into memory.
If you have n records. Write n to disk, then write each record.
If each record has variable lenght, then write the length of each record before writing the record.
You talk about "random access" in your question. Probably you mean that the file is very big and at access time you want to read from disk only the portion you're interested in.
If so plan to build an index; that index will tell the offset of each element in bytes from the beginning of the file. Store the index at the beginning of the file and then store the data.
When you read the file you start reading the index, get the offset to the data you need, and read that portion of file.
These are very basic examples, just to get the idea...
Hope they helps!
Is there any reason you are not considering putting this data in a persistent DB store like mysql? these system are built to deal with random data access with proper indexes to speeden you data retrieval. Plus while reading from a file, you would have to read the entire file to get what you want as there are no indexes and no query language.
Added to this they have systems in place to make sure multiple running processes can access the same data without data getting corrupted. It provided data recovery incase of inconsistencies.
So just storing is the simple part, it does not end there. You would have to provide all the other solutions eventually. Better use whats available.

C++/MFC - How to export window contents to Excel? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Excel files and C++
I am using an API called UltimateGrid which allows me to easily create Excel-like grids using C++/MFC. I need a way to export all of the contents of these grids to an actual Excel document. I could not find anything about this in the documentation for this API. Then I got to thinking ... exporting contents to an Excel document is a common requirement in applications. I was thinking about creating a right-click menu option for exporting a grid to Excel. I feel like I am reinventing the wheel as I start to code this. I googled around and saw a lot of common ways of dealing with this when database tables are involved. But that is not the case here. My underlying "datasource" is not a database table, but rather just some business objects internal to the application. Am I going to have to just write my own custom handler that iterates through the business objects corresponding to the rows and output them to a CSV file to be used by Excel?
I'm not sure how automated you want this to be. I did this a while back (as in years ago), so forgive me if this info is out of date. Here's what I remember:
CSV is fine, as long as you don't want to export formats, graphs, etc...
You should be able to access the Excel object from your C++ code, and Microsoft should have documentation on how to do this.
It may be easier to have your C++ generate a VBScript to access the component, since last I checked, there was much less red tape to doing it that way, but you could run into permissions/security issues with this method.
Also, have you checked to see if UltimateGrid supports other export formats that are compatible with Excel?
If there are no other options, I think you might want to look into DDE (Dynamic Data Exchange).
There could be a limitation on that OS should be Microsoft Windows, however you might be able to find some open source/runtime that supports other OSs as well.
One that I used long ago was NDde.

How do I deal with "Project Files" in my Qt application?

My Qt application should be able to create/open/save a single "Project" at once. What is the painless way to store project's settings in a file? Should it be XML or something less horrible?
Of course data to be stored in a file is a subject to change over time.
What I need is something like QSettings but bounded to a project in my application rather than to the whole application.
You can use QSettings to store data in a specific .ini file.
From the docs:
Sometimes you do want to access settings stored in a specific file or registry path. On all platforms, if you want to read an INI file directly, you can use the QSettings constructor that takes a file name as first argument and pass QSettings::IniFormat as second argument. For example:
QSettings settings("/home/petra/misc/myapp.ini",
QSettings::IniFormat);
I order to make it user editable, I would stick to plain text with one key = values by line, like in most of the Linux apps.
However this is only for the settings, not for the complete project's data which I suppose requires more complex structures.
So maybe JSON ?
Pro XML:
You can have a look at it in an editor
You can store any kind of string in any language in it (unicode support)
It's simple to learn
More than one program can read the same XML
It's easy to structure your data with XML. When you use key/value lists, for example, you'll run into problems when you need to save tree-like structures.
Contra XML
The result is somewhat bloated
Most programming languages (especially old ones like C++) have no good support for XML. The old XML APIs were designed in such a way that they could be implemented in any language (smallest common denominator). 'nuff said.
You need to understand the concept of "encoding" (or "charset"). While this may look trivial at first glance, there are some hidden issues which can bite you. So always test your code with some umlauts and even kanji (Japanese characters) to make sure you got it right.