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.
Related
What is the best way/common practice for maintaining all string resources found on a UI in Qt, especially the textual input/text in combo boxes etc. (since these are the once that are frequently used in the code itself)?
I know that Android has this string resources thing such that resources only have to be modified at one position.
Does Qt have something like that too or do I have to initialize string resources in code instead of in the UI's XML itself...
AFAIK, there is no built-in mechanism for string resources in Qt. If you want to maintain strings at build time you can define them in one .h/.cpp file as global variables and reuse them in your code.
Otherwise you can use Qt's translator files (binary) and load them along with your application. If you need to change a string, you simply will need to edit the translation file (xml) and "recompile" it with lrelease utility without building the application again.
There is a mechanism to dynamically translate texts in application, but it works a bit different than Android string resources, but achieves the same goals.
Qt uses i18n system modelled after standard, well known unix gettext. It works in a very similar way to iOS NSLocalizedString, if that rings a bell.
http://doc.qt.io/qt-5/qobject.html#tr
This is worth reading too:
http://en.wikipedia.org/wiki/Gettext
http://doc.qt.io/qt-5/internationalization.html
Android approach is a bit unique and you should not expect it to be a "standard everywhere". It works, it's ok, but it's not a standard way of doing things on desktop.
I am writing a program that produces a formatted file for the user, but it's not only producing the formatted file, it does more.
I want to distribute a single binary to the end user and when the user runs the program, it will generate the xml file for the user with appropriate data.
In order to achieve this, I want to give the file contents to a char array variable that is compiled in code. When the user runs the program, I will write out the char file to generate an xml file for the user.
char* buffers = "a xml format file contents, \
this represent many block text \
from a file,...";
I have two questions.
Q1. Do you have any other ideas for how to compile my file contents into binary, i.e, distribute as one binary file.
Q2. Is this even a good idea as I described above?
What you describe is by far the norm for C/C++. For large amounts of text data, or for arbitrary binary data (or indeed any data you can store in a file - e.g. zip file) you can write the data to a file, link it into your program directly.
An example may be found on sites like this one
I'll recommend using another file to contain data other than putting data into the binary, unless you have your own reasons. I don't know other portable ways to put strings into binary file, but your solution seems OK.
However, note that using \ at the end of line to form strings of multiple lines, the indentation should be taken care of, because they are concatenated from the begging of the next lineļ¼
char* buffers = "a xml format file contents, \
this represent many block text \
from a file,...";
Or you can use another form:
char *buffers =
"a xml format file contents,"
"this represent many block text"
"from a file,...";
Probably, my answer provides much redundant information for topic-starter, but here are what I'm aware of:
Embedding in source code: plain C/C++ solution it is a bad idea because each time you will want to change your content, you will need:
recompile
relink
It can be acceptable only your content changes very rarely or never of if build time is not an issue (if you app is small).
Embedding in binary: Few little more flexible solutions of embedding content in executables exists, but none of them cross-platform (you've not stated your target platform):
Windows: resource files. With most IDEs it is very simple
Linux: objcopy.
MacOS: Application Bundles. Even more simple than on Windows.
You will not need recompile C++ file(s), only re-link.
Application virtualization: there are special utilities that wraps all your application resources into single executable, that runs it similar to as on virtual machine.
I'm only aware of such utilities for Windows (ThinApp, BoxedApp), but there are probably such things for other OSes too, or even cross-platform ones.
Consider distributing your application in some form of installer: when starting installer it creates all resources and unpack executable. It is similar to generating whole stuff by main executable. This can be large and complex package or even simple self-extracting archive.
Of course choice, depends on what kind of application you are creating, who are your target auditory, how you will ship package to end-users etc. If it is a game and you targeting children its not the same as Unix console utility for C++ coders =)
It depends. If you are doing some small unix style utility with no perspective on internatialization, then it's probably fine. You don't want to bloat a distributive with a file no one would ever touch anyways.
But in general it is a bad practice, because eventually someone might want to modify this data and he or she would have to rebuild the whole thing just to fix a typo or anything.
The decision is really up to you.
If you just want to keep your distributive in one piece, you might also find this thread interesting: Store data in executable
Why don't you distribute your application with an additional configuration file? e.g. package your application executable and config file together.
If you do want to make it into a single file, try embed your config file into the executable one as resources.
I see it more of an OS than C/C++ issue. You can add the text to the resource part of your binary/program. In Windows programs HTML, graphics and even movie files are often compiled into resources that make part of the final binary.
That is handy for possible future translation into another language, plus you can modify resource part of the binary without recompiling the code.
For educational purposes, I would like to build an IDE for PHP coding.
I made a form app and added OpenFileDialog ..(my c# knowledge was useful, because it was easy ... even though without intelisense!)
Loading a file and reading lines from it is basically the same in every language (even PERL).
But my goal is to write homemade intelisense. I don't need info on the richtextBox and the events it generates, endline, EOF, etc, etc.
The problem I have is, how do I handle the data? line for line?
a struct for each line of text file?
looping all the structs in a linked list? ...
while updating the richtextBox?
searching for opening and closing brackets, variables, etc, etc
I think Microsoft stores a SQL type of database in the app project folders.
But how would you keep track of the variables and simulate them in some sort of form?
I would like to know how to handle this efficiently on dynamic text.
Having never thought this through before, it sounds like an interesting challenge.
Personally, I think you'll have to implement a lexical scanner, tokenizing the entire source file into a source tree, with each token also having information about it mapping the token to a line/character inside of the source file.
From there you can see how far you want to go with it - when someone hovers over a token, it can use the context of the code around it to be more intelligent about the "intellisense" you are providing.
Hovering over something would map back to your source tree, which (as you are building it) you would load up with any information that you want to display.
Maybe it's overkill, but it sounds like a fun project.
This sounds to be related to this question:
https://softwareengineering.stackexchange.com/questions/189471/how-do-ide-s-provide-auto-completion-instant-error-checking-and-debugging
The accepted answer of that question recommends this link which I found very interesting:
http://msdn.microsoft.com/en-us/magazine/cc163781.aspx
In a nutshell, most IDEs generate the parse tree from the code and that is what they stores and manage.
I need some methods of storing and getting data from a file (in WIN32 api c++ application, not MFC or .NET)
e.g. saving the x, y, width and height of the window when you close it, and loading the data when you open the window.
I have tried .ini files, with the functions -- WritePrivateProfileString and ReadPrivateProfileString/Int, but on MSDN it says
"This function is provided only for compatibility with 16-bit Windows-based applications. Applications should store initialization information in the registry."
and when i tried on my Windows7 64bit machine to read a ini file, i got blue screen! (in debug mode with visual studio) O.O
I notice that most other application use XML to store data, but I don't have a clue how to read/write xml data in c++, are there any libraries or windows functions which will allow me to use xml data?
Any other suggestions would be good too, thanks.
There is nothing wrong with .ini files, the only problem with them is where to write them. CIniFile from CodeProject is good enough class. Ini file should be placed in %APPDATA%/<Name Of Your Application> (or %LOCALAPPDATA%\<Same Name Here>, as described below).
EDIT: If we are talking about Windows family of operating systems from Windows 2000 onward then function SHGetFolderPath is portable way to retrieve user specific folder where application configuration files should be stored. To store data in romaing folder use CSIDL_APPDATA with SHGetFolderPath. To store data to local folder use CSIDL_LOCAL_APPDATA.
The difference between local and roaming folder is in the nature of the data to be stored. If data is too large or machine specific then store it in local folder. Your data (coordinates and size of the window) are local in nature (on other machine you may have different resolution), so you should actually use CSIDL_LOCAL_APPDATA.
Windows Vista and later have extended function SHGetKnownFolderPath with its own set of constants, but if you seek compatibility stick to the former SHGetFolderPath.
TinyXML is a popular and simple XML parser for C++.
Apart from that, you can really use any format you want to store your settings, though it's considered good practice to keep settings in text format so that they can be hand-edited if necessary.
It's fairly simple to write your own functions for reading/writing a file in INI or similar format. The format is entirely up to you, as long as it's easily comprehensible to humans. Some possibilities are:
; Comment
# Comment
Key = Value (standard INI format)
Key Value
Key: Value
You could use Boost.PropertyTree for this.
Property trees are versatile data
structures, but are particularly
suited for holding configuration data.
The tree provides its own,
tree-specific interface, and each node
is also an STL-compatible Sequence for
its child nodes.
It supports serialization, and so is well-suited to managing and persisting changeable configuration data. There is an example here on how to load and save using the XML data format that this library supports.
The library uses RapidXML internally but hides the parsing and encoding details, which would save you some implementation time (XML libraries all have their idiosyncracies), while still allowing you to use XML as the data representation on disk.
libxml2. I have seen quite a lot places where it is used. Easy to use and loads of examples to get you started and not a vast library as such. And in C, take it wherever you want.
pugixml is another good (and well documented) XML parser library. And If you like portability XML is a better option.
While INI files may not be the best format, I think you can safely ignore the warning MSDN puts on WritePrivateProfileString and ReadPrivateProfileString.
Those two functions are NEVER going away. It would break THOUSANDS of applications.
That warning has been there for years and I suspect was added when the registry was all the rage and someone naively thought it would one day completely replace INI files.
I might be wrong but it would be very unlike Microsoft to break so many existing apps like this for no good reasons. (Not that they do not occasionally break backwards compatibility, but this would cause huge problems for zero benefit.)
Ohhh My GOD? Have you ever thought of stright-forward solution rather then thinking of Super-Duper-all-can-do framework way?
Sorry...
You want to store two numbers between restarts???
Save: Open a file, write these two numbers, close the file:
std::ifstream out(file_name);
out << x << ' ' << y;
out.close();
Load: Open a file, read these two numbers, close the file:
std::ifstream in(file_name);
if(!in) return error...
in >> x >> y;
if(!in) return error...
in.close();
Libconfig is the best solution in C++ as far as I have tried.
Works multi platform with minimum coding.
You must try that!
I like the TinyXML solution suggested.
But for Windows, I like .ini even more.
So I'll suggest the inih library, free and open source on GitHub here. Very simple and easy to use - 1 header file library iirc.
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.