0

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

MistyD
  • 16,373
  • 40
  • 138
  • 240
  • 2
    If you change a single string you'll only need to rebuild a single `. cpp` and relink the object modules, hardly a full project rebuild. – Matteo Italia Jan 03 '14 at 10:17
  • Even if you change the string and saved file, compiler will look for timestamp for lib and .cpp and cpp is saved later than lib, it will build one .cpp and then link. – Digital_Reality Jan 03 '14 at 10:19
  • I want to stay clear off rebuilding the project. – MistyD Jan 03 '14 at 10:21
  • Use qt linguist and translators (`tr` function and related macros). Then you will have those strings in translation file. – Marek R Jan 03 '14 at 10:32

4 Answers4

3

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.

Devolus
  • 21,661
  • 13
  • 66
  • 113
3

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.

Community
  • 1
  • 1
phyatt
  • 18,472
  • 5
  • 61
  • 80
2

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.

Dmitry Markin
  • 1,145
  • 8
  • 8
1

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.

  • `QSettings` would still require to have the strings in first place to "extract" them. There is no point. Using a XML or JSON file is the way to go indeed. – Guilherme Bernal Jan 03 '14 at 10:24
  • I dont mind extracting strings on application starrtup. @Vladmir could you explain a little how this might work. – MistyD Jan 03 '14 at 10:27
  • I mean for example you want your main window title to be configurable. So you have an entry in your QSettings (ini or registry - it is up to you which you want) called "MainWindow/Title" which contains the title string and which you retrieve at start up. There is a bunch of examples in the link that I posted in my answer. I especially find useful the part "Restoring the State of a GUI Application", though it is not related to strings. XML or JSON is sure an option but it is more work to do in your code. QSettings is extremely straightforward and simple. – HiFile.app - best file manager Jan 03 '14 at 10:35
  • I edited my answer to recommend XML or JSON over QSettings. Thanks Guilherme for your comment. – HiFile.app - best file manager Jan 03 '14 at 10:51