Qt Configuration Storage with XML
Qt provides comprehensive libraries for application development, including configuration menagement capabilities. While QSettings handles INI file operations effectively, certain limitations may necessitate alternative approaches. This implemantation demonstrates using XML files as configuration storage through Qt's QDomDocument class.
QSettings Limitations
QSettings offers straightforward INI file operations but has several constraints:
- Encoding issues with specific character sets
- Inability to use Chinese characters as keys
- Encoding conflicts when multiple QSettings instances are created in nested scopes
XML Document Structure
The XML structure mimics INI file organization with groups and items:
<groups>
<group name="General">
<item name="username">admin</item>
<item name="language">English</item>
</group>
</groups>
XML Configuration Handler Implementation
Reading XML Configuration
void XmlConfigHandler::loadConfiguration(const QString &configPath)
{
if(configPath.isEmpty()) return;
QFile configFile(configPath);
if(!configFile.open(QFile::ReadOnly | QFile::Text)) return;
QDomDocument xmlDoc;
QString parseError;
int errorLine, errorColumn;
if(!xmlDoc.setContent(&configFile, false, &parseError, &errorLine, &errorColumn)) {
configFile.close();
return;
}
if(xmlDoc.isNull()) {
configFile.close();
return;
}
m_configData.clear();
QDomElement root = xmlDoc.documentElement();
QDomNodeList sections = root.childNodes();
for(int i = 0; i < sections.count(); ++i) {
QDomNode sectionNode = sections.item(i);
QDomElement sectionElement = sectionNode.toElement();
QString sectionName = sectionElement.attribute("name");
QMap<QString, QString> parameters;
QDomNodeList paramList = sectionElement.childNodes();
for(int j = 0; j < paramList.count(); ++j) {
QDomNode paramNode = paramList.item(j);
QDomElement paramElement = paramNode.toElement();
QString paramName = paramElement.attribute("name");
QString paramValue = paramElement.text();
if(paramName.isEmpty()) {
parameters[QString::number(j)] = paramValue;
} else {
parameters[paramName] = paramValue;
}
}
m_configData[sectionName] = parameters;
}
configFile.close();
}
Saving XML Configuration
void XmlConfigHandler::saveConfiguration(const QString &configPath)
{
QDomDocument xmlDoc;
QString xmlHeader("version=\"1.0\" encoding=\"UTF-8\"");
xmlDoc.appendChild(xmlDoc.createProcessingInstruction("xml", xmlHeader));
QDomElement rootElement = xmlDoc.createElement("groups");
xmlDoc.appendChild(rootElement);
for(auto sectionIter = m_configData.begin(); sectionIter != m_configData.end(); ++sectionIter) {
QDomElement sectionNode = xmlDoc.createElement("group");
sectionNode.setAttribute("name", sectionIter.key());
QMap<QString, QString> sectionParams = sectionIter.value();
for(auto paramIter = sectionParams.begin(); paramIter != sectionParams.end(); ++paramIter) {
QString paramKey = paramIter.key();
QString paramValue = paramIter.value();
QDomElement paramNode = xmlDoc.createElement("item");
paramNode.setAttribute("name", paramKey);
QDomText valueNode = xmlDoc.createTextNode(paramValue);
paramNode.appendChild(valueNode);
sectionNode.appendChild(paramNode);
}
rootElement.appendChild(sectionNode);
}
QFile outputFile(configPath);
if(outputFile.open(QFile::WriteOnly | QFile::Text)) {
QTextStream fileStream(&outputFile);
xmlDoc.save(fileStream, 4);
outputFile.close();
}
}
Addding Configuration Items
bool XmlConfigHandler::insertParameter(const QString &value, const QString §ion, const QString &key)
{
if(value.isEmpty() || section.isEmpty()) return false;
if(key.isEmpty()) {
int paramCount = m_configData[section].size();
m_configData[section][QString::number(paramCount)] = value;
} else {
m_configData[section][key] = value;
}
saveConfiguration(m_configFilePath);
return true;
}
Removing Configuration Items
bool XmlConfigHandler::deleteParameter(const QString &value, const QString §ion, const QString &key)
{
if(value.isEmpty() || section.isEmpty()) return false;
if(key.isEmpty()) {
int paramCount = m_configData[section].size();
if(paramCount == 0) return false;
auto paramIter = m_configData[section].begin();
while(paramIter != m_configData[section].end()) {
if(paramIter.value() == value) {
paramIter = m_configData[section].erase(paramIter);
} else {
++paramIter;
}
}
} else {
m_configData[section].remove(key);
}
saveConfiguration(m_configFilePath);
return true;
}
This XML-based configuration system provides a flexible alternative to QSettings while maintaining similar functionality for application configuration management.