What i'm trying to do is to check if a registry key (NOT VALUE, KEY) exists in the registry. I can't find any way to check that.
Idea?
Using QSettings you can open the key's parent and retrieve the list of its keys. Use the function childGroups() to get the list of keys. It seems that "groups" in qt are keys in Windows registry.
This is the only way I found to check whether a key exists. In this code I look for the key "SearchedKey".
QSettings settings(
"HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Windows\\CurrentVersion\\App Paths",
QSettings::NativeFormat
);
if (settings.childGroups().contains("SearchedKey", Qt::CaseInsensitive))
std::cout << "Key exists" << std::endl;
else
std::cout << "Key doesn't exist" << std::endl;
EDIT:
In 2011 I wrote:
The registry is a Windows concept and doesn't fit Qt's cross-platform notions. You will have to use the Windows API or a C++ wrapper for it.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms724875(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/xka57xy4(v=vs.80).aspx
If your needs are more abstract for your application to save and restore its own settings, Qt has a cross-platform design of something called QSettings.
Depending on the nature of the setting and the platform, will store these in the registry or in a file/etc.
But it appears in the answer by #mateuszb that QSettings can open Windows keys if you use QSettings::NativeFormat:
http://doc.qt.io/qt-5/qsettings.html#Format-enum
I'd still suggest that if you are hardcoding something like "HKEY_LOCAL_MACHINE" into your source, that you are not really in the spirit of abstracting your code across platforms in the way that Qt intends. But you apparently can (at least in recent Qt versions) do this without digging beneath Qt and calling the Windows registry APIs.
There is still not a way that I can find for checking for groups. However you can set a key inside a group and check for the existence of that key:
QString groupname = "group";
QString keyname = "/name";
QString name_read = settings.value(groupname + keyname, QString()).toString();
if(name_read == groupname){
...
}else {
// default action
}
This requires an additional key inside of the group called "name" that is set to the name of your group.
Related
Why it was possible in Qt 5.2 and previously and stored data in following format:
key=#Variant(\0\0\0\b\0\0\0)
but have problem now in Qt 5.11?! Following code
QVariantMap projectsMap;
for (auto project : projects)
projectsMap.insert(key, value);
settings->setValue("Group/projects", projectsMap);
executes correctly however stores nothing to ini file.
qRegisterMetaTypeStreamOperators<QVariantMap>("QVariantMap");
does not help as well. How to store this, what is the problem here?
Don’t store QSettings: it’s not meant to be used that way. You should use a fresh instance of QSettings every time you change the settings. Your destructor should look as follows:
MyClass::~MyClass() {
QSettings s;
s.setValue(kFoo, this->m_bar);
…
}
QSettings is an ephemeral handle to the settings system, its instantiation is cheap. You leak it because QPointer does not destroy anything: it’s not an owning pointer.
I am using the GoogleTest (GTest) framework in conjunction with a Qt5 application.
Whenever a test fails using a QString argument, the framework tries to print all the involved values. However, it cannot automatically handle foreign types (Qt5's QString in this case).
QString test = "Test";
ASSERT_EQ(test, "Value");
How can I get GoogleTest to pretty print QStrings automatically (= without having to manually convert them each time)?
The GoogleTest Guide explains how you can in general teach the framework to handle custom types.
In the end, the following code snippet is all that needs to be added for GoogleTest being able to work with QStrings:
QT_BEGIN_NAMESPACE
inline void PrintTo(const QString &qString, ::std::ostream *os)
{
*os << qUtf8Printable(qString);
}
QT_END_NAMESPACE
This code MUST NOT be in the namespace of your test fixtures, but must be in the Qt namespace (or in general in the namespace where the type that should be pretty-printed is defined in).
This code MUST also be viewable from all translation units where you call a GoogleTest assertion on that particular type, otherwise it will not get used (see comments).
As a result GoogleTest now pretty prints QStrings:
You can of course also add some quotation marks to make it clearer that it comes from a QString:
*os << "\"" << qUtf8Printable(qString) << "\"";
Source: Webinar ICS Qt Test-Driven Development Using Google Test and Google Mock by Justin Noel, Senior Consulting Engineer
Saving UI settings with QSettings is cumbersome and buggy, because each time you must use setValue() and value() functions and also define groups, application name and organization which can be buggy in large applications:
QSettings settings(qApp->applicationDirPath() + "/" + qApp->applicationName() + ".ini" , QSettings::IniFormat) ...
settings.beginGroup("someGroup");
settings.setValue("someKey", "blah blah");
QString str = settings.value("someKey");
settings.endGroup();
However with JSON it can be simpler:
QJsonObject obj;
obj["someKey"] = "blah blah"
...
What is the best practice for saving and restoring ui settings?
Save each key/value in QSettings?
Save in QJson and then save with QSettings?
Save in QJson only (with another mechanism for defining groups and application)?
Any other idea?
The QSettings code won't be more cumbersome than your QJsonObject example if you use all benefits of the first one.
Default QSettings constructor:
You can set the application and organization names just once:
QApplication::setApplicationName("My Application");
QApplication::setOrganizationName("My Organization");
QSettings::setDefaultFormat(QSettings::IniFormat);
Then simply use the default QSettings constructor anywhere in your code:
QSettings settings;
settings.setValue("Key", "Value");
Group as an argument:
The settings group for your keys can be set without using the beginGroup() / endGroup() methods. Simply pass the slash-delimited argument to thevalue() / setValue() methods:
settings.setValue("Group/Key", "Value");
Storing the UI settings:
It's not clear from your question what exact UI settings you want to save, however there are two handy methods – QWidget::saveGeometry() and QMainWindow::saveState(). You can use it to store your windows geometry and state respectively:
QSettings settings;
settings.setValue("ui/geometry", saveGeometry());
settings.setValue("ui/state", saveState());
JSON:
In case if you still want some deep nesting and hierarchy for your settings file, you're right, you will have to use JSON. The most convenient way is to register the custom read/write functions using the QSettings::registerFormat. Why still QSettings? This class is designed considering the cross-platform code, no need to reinvent the wheel.
Of course, you can also write your own JSON settings class from scratch. But if there is no need in multilevel settings hierarchy – is it worth it?
In terms of application design you can wrap QSettings in an additional class. In this case you can easily experiment and switch to your own JSON read/write implementations without touching the main code.
Standard system paths:
In your example you are using the applicationDirPath() to store the settings data. That's an improper place to keep your settings for the most applications (e.g. you will likely face the Windows UAC issues in this case; Unix systems also have the separate directory for such files). Use the paths intended by the operating system for storing application data.
For example, on Windows QSettings::setDefaultFormat(QSettings::IniFormat) coupled with the default scope (UserScope) will store the settings in the %APPDATA% path. This also improves the cross-platform portability of your code.
My QT application uses WinApi library.
Now I have the following code:
//main.cpp
qDebug() << "main::instance = " << qApp; //0x29fe18
//lib.cpp
qDebug() << "library::instance = " << GetModuleHandle(NULL); // 0x400000
As you see, I'm getting different handles while my app has only one thread flow.
What's wrong?
Edit:
Yes, I guessed that those are kind of different things.
Question is: how do I get thread handle from both places (if code running from the same thread - I should get the same handle value, if there's 2 threads - I should get 2 different thread handles)?
We don't know what qApp is. Presumably it's a pointer to the global instance of QApplication. That's a C++ object instance in your process.
On the other hand GetModuleHandle(NULL) is the base address of your executable module.
These two things are completely different. You should not expect them to be the same.
According to your edit you aren't interested in either of these things and actually want to identify threads. For Win32 code you use GetCurrentThreadId. For Qt use QThread::currentThreadId().
I need to create my own codec, i.e. subclass of QTextCodec. And I'd like to use it via QTextCodec::codecForName("myname");
However, just subclass is not enough. QTextCodec::availableCodecs() does not contain my codec name.
QTextCodec documentation does not cover the area of proper registration of a custom codec:
Creating Your Own Codec Class
Support for new text encodings can be
added to Qt by creating QTextCodec
subclasses.
The pure virtual functions describe
the encoder to the system and the
coder is used as required in the
different text file formats supported
by QTextStream, and under X11, for the
locale-specific character input and
output.
To add support for another encoding to
Qt, make a subclass of QTextCodec and
implement the functions listed in the
table below.
name()
aliases()
mibEnum()
convertToUnicode()
convertFromUnicode()
You may find it more convenient to
make your codec class available as a
plugin; see How to Create Qt Plugins
for details.
So, I've tried to dig a little into plugins' direction. But I don't want to have a separate project with plugin. Is it possible to declare plugin within the same project?
Or is there a direct way to register my codec into QTextCodec? This is preferable.
according to qtextcodex.cpp any new codec is added to the collection of registered codecs (*static QList all) by its own constructor. So creating an instance of your codec class should do the trick; code below worked fine for me:
QMyCodec myCodec;
foreach (QByteArray codecName, QTextCodec::availableCodecs())
{
QString codecNameStr(codecName);
qDebug() << codecNameStr;
}
QTextCodec* codec = QTextCodec::codecForName("MyNewCodec");
if (codec)
{
qDebug() << "found ";
qDebug() << codec->name() << '\n';
}
QTextCodec::availableCodecs returned:
"MyNewCodec"
"System"
"roman8"
"hp-roman8"
"csHPRoman8" ...
QTextCodec::codecForName returned a pointer to my codec class
hope this helps, regards