Logging rules in .ini file with QSetting and asterisk
-
Hi,
I want to use the logging rules in my configuration file (config.ini).I write the logging rules with:
void setLoggingRules(const QString& category, const bool &value) { QSettings settings("config.ini", QSettings::IniFormat); settings.beginGroup("Rules"); settings.setValue(category, value); settings.endGroup(); }
If the category contains an asterisk, eg.
module.general.*
the asterisk will be encoded to%2A
in my ini file. So the rule won't be applied.I tried to set the ini codec to UTF-8, but the asterisk is still saved as
%2A
void setLoggingRules(const QString& category, const bool &value) { QSettings settings("config.ini", QSettings::IniFormat); settings.setIniCodec("UTF-8"); settings.beginGroup("Rules"); settings.setValue(category, value); settings.endGroup(); }
Is there a way to store the asterisk in the file?
-
@beecksche
Basically, no. People keep asking about why Qt.ini
file is not identical to Windows. It isn't, it's only "approximate". Qt.ini
files work consistently if you only write/read them from Qt, but there are incompatibilities if you mix Qt read/write with non-Qt-app write/read. -
@JonB , he writes a file though that is most likely to be consumed by the Qt Logging Framework (https://doc.qt.io/qt-5/qloggingcategory.html#configuring-categories). So it is consumed by Qt, after all.
For internal reasons, the logging file is not parsed by QSettings, which is probably why it doesn't handle this. But Qt could arguably work around this by normalizing %2A when parsing; feel free to create a suggestion about this on bugreports.qt.io .
-
@kkoehne
Then he's going to have a problem between Categories allowing*
character whileQSettings
does not!Sorry, I phrased that badly. Does the Qt logging actually read categories from that file itself, or will he be doing that via his own
QSettings
reading and passing on the results to logging categories function calls? If it's the latter, then it's all done byQSettings
and will be decoded properly. It just won't "look" right if he inspects the file. -
@JonB said in Logging rules in .ini file with QSetting and asterisk:
Does the Qt logging actually read categories from that file itself, or will he be doing that via his own QSettings reading and passing on the results to logging categories function calls?
Qt Core does parse the file manually, not using QSettings. This is mainly to avoid deadlocks when QSettings does start to use logging ... But as I said, we can look into making the parsing compatible with whatever QSettings writes.
-
The configuration file for the logging is set with the neviroment vairable QT_LOGGING_CONF.
qputenv("QT_LOGGING_CONF", "config.ini");
In this file Qt"searches" for a "Rules" group and read the keys and values, example from https://doc.qt.io/qt-5/qloggingcategory.html#configuring-categories:
The asterisk is a wildcard for the rules.
[Rules] *.debug=false driver.usb.debug=true
In my applikation i already use a configuration file. So my idea was to implement the logging rules in this configuration file. To read/write this file i use
QSettings
, so for me it would be nice, to write the logging rules also withQSettings
. -
@beecksche said in Logging rules in .ini file with QSetting and asterisk:
so for me it would be nice, to write the logging rules also with QSettings
And as I understand @kkoehne to be saying, this cannot be done till something is changed in Qt library code?
-
Well, you can hack around it and write the file in QSettings, but then 'un-mask' the character manually using QFile :)
Not that this is particularly elegant ...
-
Now I save all rules with one key, the value sperated with semicolons. I don't use the
QT_LOGGING_CONF
enviroment variable.[Rules] LoggingRules="module.io.low=true;module.db.low=true;"
Read/Write the keys and values from
LoggingRules
withQSettings
and set theQLoggingCategory::setFilterRules()
.void setLoggingRules(const QString& category, const bool &value) { QMap<QString, bool> rules = loggingRules(); if (rules.contains(category)) rules[category] = value; else rules.insert(category, value); setLoggingRules(rules, true); } void setLoggingRules(const QMap<QString, bool> &loggingRules, bool save) { QString qt_logging_rules; QMapIterator<QString, bool> i(loggingRules); while (i.hasNext()) { i.next(); qt_logging_rules.append(QString("%1=%2").arg(i.key()).arg(i.value() ? "true" : "false")); if (i.hasNext()) qt_logging_rules.append(";"); } if (save) { QSettings settings("config.ini", QSettings::IniFormat; settings.beginGroup("Rules"); settings.setValue("LoggingRules", qt_logging_rules); settings.endGroup(); } qt_logging_rules.replace(";", "\n"); QLoggingCategory::setFilterRules(qt_logging_rules); } QMap<QString, bool> loggingRules() { QSettings settings("config.ini", QSettings::IniFormat); settings.beginGroup("Rules"); QString rulesString = settings.value("LoggingRules").toString(); QStringList rules = rulesString.split(";"); QMap<QString, bool> loggingRules; for (auto rule : rules) { QStringList ruleAndValue = rule.split("="); if (ruleAndValue.size() != 2) continue; QString category = ruleAndValue.at(0); bool value = ruleAndValue.at(1) == "true"; loggingRules.insert(category, value); } return loggingRules; }
Ugly but it works ;)
-
Corresponding bugreport: https://bugreports.qt.io/browse/QTBUG-69548