Is there a way to have multiple values for each key, stored in a human-readable (no binaries) .ini file, using QSettings?
Something that could look like:
key_1=value_1,value2
key_2=value_1
...
Yes, you should use QStringList type:
QStringList list;
list << "value_1" << "value2";
settings.setValue("key_1", list);
Output:
key_1=value_1, value2
Items that contains , will be quoted using "...".
Well from depends how you want to access it, you could use
QVariant value ( const QString & key, const QVariant & defaultValue = QVariant() ) const
in which you would be able to insert a QVariantList.
But i see there is a group format.
http://doc.qt.digia.com/4.6/qsettings.html#childGroups
Related
As part of parsing a JSON response, we are traversing a tree of QVariantMaps. To my understanding, we are creating a copy at each level by calling QVariant::toMap() or qvariant_cast<QVariantMap>(). I would like to optimize this process however I can.
QString parse (QVariant input) {
QVariantMap map = input.toMap();
QVariant innerValue = map.value("key");
QVariantMap subMap = innerValue.toMap();
QVariant desiredValue = subMap.value("key2");
return desiredValue.toString();
}
Can we avoid copying each map by directly referencing the underlying value inside the QVariant? I assume that we would need a pointer, something like the following:
QString parse (QVariant input) {
// Assuming we know that input is a map
QVariantMap* map = getVariantPointer<QVariantMap*>(input);
QVariantMap* subMap = getVariantPointer<QVariantMap*>(map->value("key"));
return getVariantPointer<QString*>(subMap->value("key2"));
I'm a complete beginner to QT5, I searched YouTube for any QSettings tutorials and only found 2 of them, both in Spanish.
I'm trying to store simple text from a textEdit and then load it on save/load button click. So far I have not been able to accomplish this. Here's my code so far, no errors, it just doesn't work.
Widget.cpp
void Widget::saveText(QString key, QString text)
{
QSettings settings("App", "BillReminder");
settings.beginGroup("Text");
settings.setValue(key + "t", text);
settings.endGroup();
}
QString Widget::loadText(QString key)
{
QSettings settings("App", "BillReminder");
settings.beginGroup("Text");
settings.value(key + "t", text).toString();
settings.endGroup();
return QString(text);
}
void Widget::on_saveButton_clicked()
{
saveText("textEdit", text);
}
void Widget::on_loadButton_clicked()
{
QString text1 = loadText(text);
ui->textEdit->setText(text1);
}
widget.h - class Widget : public QWidget
private:
Ui::Widget *ui;
QString text;
void saveText(QString key, QString text);
QString loadText(QString key);
void SetText(QString key);
The problem is in your loadText() method. QSettings::value() is a function that returns a value retrieved from the QSettings storage. The second parameter is only a default value, that would be returned in case your settings storage doesn't contain the requested key.
QString Widget::loadText(QString key)
{
QSettings settings("App", "BillReminder");
settings.beginGroup("Text");
QString theValue = settings.value(key + "t", text).toString();
settings.endGroup();
return theValue;
}
This code example contains many issues.
don't shadow variable names (e.g. "text" is method argument and member variable); use e.g. underscore to indicate member variables
above answer about reading values as return value solve one issue as well
on_saveButton is using as a settings key a "textEdit" string but on_loadButton is used wrong "text" member variable string as key -> you want use the same string to load stored variable i.e. you are reading something else just now.
you are saving member variable "text" that is not initialised in your example i.e. it may be empty; and later you are setting UI text edit with stored settings (empty string in your example?)
Please go through QSettings Qt documentation for working example.
I have a QVariant with userType QVariantList and the exact format looks like this when i qDebug the qvariant
QVariant(QVariantList, (QVariant(QVariantMap, QMap(("name", QVariant(QString, "UK English Female"))))
I want QString, "UK English Female" from the variant how can i get that i have already tried QVariant.toStringList() but the stringlist is empty.
Thanks.
From what is shown as a debug output, I presume it was produced in a similar manner:
QVariantMap map;
map.insert("name", QVariant("UK English Female"));
qDebug() << QVariant(QVariantList{QVariant(map)});
and as a result you have a string data, which is burried relatively deep in a sequence of containers.
So, how to get there?
As a whole you have a QVariant holding a QVariantList with a single QVariant value, which in turn is a QMap. The map has a key name of type QVariant holding a QString. Chaining the necessary conversions, we end up with:
qDebug() << myVar.value<QVariantList>().first().toMap().value("name").toString();
assuming the whole thing is held in QVariant myVar;.
there is a QJsonObject
{
"a":"...",
"b":"...",
"c":"..."
}
is there a method to check if this object contains "a"?
You have a few options, according to the documentation:
The most obvious is QJsonObject::contains which returns a bool
You can call QJsonObject::find which will return an iterator. If the item isn't found, the return value will be equal to QJsonObject::end Use this if you need an iterator anyways.
You can call QJsonObject::value, which will return the value for the key if present, and QJsonValue::Undefined otherwise. You're probably using the value method anyways to get the value for a key, so this will allow you to do one lookup instead of two. It may be tempting to use this for a performance boost, but remember that it will be harder to read and in most cases the performance gain is small enough that it's probably not worth it
All of this came directly from the Qt documentation - my favorite thing about Qt is their fantastic documentation, so I encourage you to make that your first stop when you have questions like these.
Right, so in general, Qt uses the API "contains" for such things. If you take a look at the following places, you will see it yourself:
QHash: bool QHash::contains(const Key & key) const
QMap: bool QMap::contains(const Key & key) const
QStringList: bool QStringList::contains(const QString & str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
QString: bool QString::contains(const QString & str, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
QList: bool QList::contains(const T & value) const
QVector: bool QVector::contains(const T & value) const
QByteArray: bool QByteArray::contains(const QByteArray & ba) const
Having mentioned all this, you may not be entirely surprised that the requested class have a method called contains as follows:
QJsonObject: bool QJsonObject::contains(const QString & key) const
After reading Save QList<int> to QSettings, I'm tring to do the same with QMap<QString,int>. I would like the configuration file to look like this:
1111=1
2222=3
4444=0
But I'm getting a compilation error:
Q_DECLARE_METATYPE(QMap<QString,int>)
Warning C4002: too many actual parameters for macro 'Q_DECLARE_METATYPE'
ConfigSettings.h(5) : error C2976: 'QMap' : too few template arguments
The error message you're getting is caused by the fact that the preprocessor doesn't know about templates. So it's parsing that macro call is if it had two arguments - QMap<QString and int>, which makes no sense.
To save the data as you want it, you're better of serializing it yourself to your QSettings. Something like this for writing:
settings.beginGroup("Whatever");
QMap<QString, int>::const_iterator i = map.constBegin();
while (i != map.constEnd()) {
settings.setValue(i.key(), i.value());
++i;
}
settings.endGroup();
To read the settings, use the same approach with the help of the childKeys() function.
settings.beginGroup("Whatever");
QStringList keys = settings.childKeys();
foreach (QString key, keys) {
map[key] = settings.value(key).toInt();
}
settings.endGroup();
Like Mat said, the error is caused by the preprocessor not understanding templates. However, you can easily fix this via a simple typedef.
typedef QMap<QString,int> QIntMap
Q_DECLARE_METATYPE(QIntMap)
QSetting accept QVariant type to pass into setValue method, so it means that you can store QMap<QString, QVarint> map directly to settings
// Store
QMap<QString, QVariant> storeMap;
QMapIterator it(myMap);
// iterate through the map to save the values in your chosen format
while(it.hasNext())
{
storeMap[it.key()] = QVariant(it.value());
it.next();
}
settings.setValue("myKey", storeMap);
..
// Read
QMap<QString, QVariant> readMap = settings.value("myKey").toMap();
QMapIterator it(readMap);
while(it.hasNext())
{
myMap[it.key()] = it.value().toInt();
it.next();
}
I understand the accepted answer, but I think the original question was how to store the QMap. It devolved into how to make the compiler behave.
QSettings mySettings...
QMapIterator it(myMap);
// iterate through the map to save the values in your chosen format
while(it.hasNext())
{
it.next();
mySettings.setValue(it.key(), it.value());
}
If however you wish to store this along with a bunch of other settings or data structures, you might consider using "beginGroup()" and "endGroup()" to group a bunch of different data structures into one file. Very tidy and readable.