C++ (Qt) #ifndef __XML_SETTINGS_H__#define __XML_SETTINGS_H__ #include <QString>#include <QSettings> class QDomDocument;class QDomElement;class QIODevice; class CXmlSettings{ QSettings * m_pSettings;public: CXmlSettings( QString fname = "" ); ~CXmlSettings(); inline QSettings& settings() const { return * m_pSettings; } // при использование CXmlSettings::value конфиг создастся автоматически, если его не было QVariant value( const QString & key, const QVariant & defaultValue = QVariant() ); void setValue ( const QString & key, const QVariant & value ); private: static bool readXmlFile(QIODevice &device, QSettings::SettingsMap &map); static bool writeXmlFile(QIODevice &device, const QSettings::SettingsMap &map); static void processWriteKey( QDomDocument& doc, QDomElement& domElement, QString key, const QVariant& value ); static void processReadKey( QString key, QSettings::SettingsMap &map, QDomElement& domElement );}; #endif // __XML_SETTINGS_H__
C++ (Qt) #include "XmlSettings.h"#include "FileUtils.h"#include <QDomDocument>#include <QDebug> CXmlSettings::CXmlSettings( QString fname ){ if ( fname.isEmpty() ) fname = settingsPath() + appBaseName() + ".xml"; static const QSettings::Format XmlFormat = QSettings::registerFormat("xml", readXmlFile, writeXmlFile); m_pSettings = new QSettings( fname, XmlFormat );} CXmlSettings::~CXmlSettings(){ delete m_pSettings;} QVariant CXmlSettings::value( const QString & key, const QVariant & defaultValue ){ if ( !settings().contains( key ) ) settings().setValue( key, defaultValue ); return settings().value( key );}void CXmlSettings::setValue ( const QString & key, const QVariant & value ){ settings().setValue( key, value );} bool CXmlSettings::readXmlFile(QIODevice &device, QSettings::SettingsMap &map){ qDebug() << "-----readXmlSettings------"; QDomDocument doc(""); if ( !doc.setContent( &device ) ) return false; QDomElement root = doc.documentElement(); processReadKey( "", map, root ); /* // Для теста использовалось при отладке QMap<QString, QVariant>::const_iterator i = map.constBegin(); while (i != map.constEnd()) { qDebug() << i.key() << ": " << i.value() << endl; ++i; }*/ return true;} bool CXmlSettings::writeXmlFile(QIODevice &device, const QSettings::SettingsMap &map){ qDebug() << "-----writeXmlSettings-----"; /* // Для теста использовалось при отладке QMap<QString, QVariant>::const_iterator i = map.constBegin(); while (i != map.constEnd()) { qDebug() << i.key() << ": " << i.value() << endl; ++i; }*/ QDomDocument doc(""); QDomElement root = doc.createElement("Main"); doc.appendChild(root); QMapIterator<QString, QVariant> i(map); while ( i.hasNext() ) { i.next(); QString sKey = i.key(); QVariant value = i.value(); processWriteKey( doc, root, sKey, i.value() ); }; QDomNode xmlNode = doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\""); doc.insertBefore(xmlNode, doc.firstChild()); QTextStream out( &device ); doc.save(out, 4); return true;} void CXmlSettings::processWriteKey( QDomDocument& doc, QDomElement& domElement, QString key, const QVariant& value ){ int slashPos = key.indexOf( '/' ); // переданный ключ является параметром if ( slashPos < 0 ) { // не пишем в конфиг параметр size (является ограничением - нельзя исп. пар-тр с таким именем) if ( key == "size" ) return; domElement.setAttribute( key, value.toString() ); return; }; // получение имени группы соответствующей xml ноде QString groupName = key.left( slashPos ); // если в качестве имени использован числовой параметр - это табличная строка, преобразуем ее в row_? if ( groupName.toInt() ) { groupName = "row_" + groupName; domElement.toElement().setAttribute("table", "1"); }; // поиск/создание ноды соответствующей ключу QDomElement groupElement; QDomNode findedGroupNode = domElement.namedItem( groupName ); if ( findedGroupNode.isNull() ) { groupElement = doc.createElement( groupName ); domElement.appendChild( groupElement ); } else groupElement = findedGroupNode.toElement(); // готовим обрезанную часть ключа key = key.right( key.size() - slashPos - 1 ); // продолжение обработки (создание/поиск групп) - пока не найдется параметр processWriteKey( doc, groupElement, key, value );} void CXmlSettings::processReadKey( QString key, QSettings::SettingsMap &map, QDomElement& domElement ){ QDomNamedNodeMap namedNodeMap = domElement.attributes(); // Добавление всех атрибутов элемента в качестве значений for (int i = 0; i < namedNodeMap.count(); ++i) { QString name = namedNodeMap.item( i ).toAttr().name(); QString value = namedNodeMap.item( i ).toAttr().value(); map.insert( key + name, value ); }; QDomNodeList nlChild = domElement.childNodes(); // если узел является таблицей - то все дети строки bool isTable = domElement.attribute("table", "0").toInt(); // создаем доп. элемент size равный числу детей (необходим для QSettings - beginArray) if ( isTable ) map.insert( key + "size", nlChild.count() ); // проход по всем детям for (int i = 0; i < nlChild.count(); ++i) { QString childName = nlChild.item(i).toElement().tagName(); if ( childName.contains("row_") ) childName = childName.right( childName.size() - 4 ); QString subKey = key + childName + "/"; QDomElement subElement = nlChild.item(i).toElement(); processReadKey( subKey, map, subElement ); };}
C++ (Qt)QString settingsPath(){ QDir dir( QCoreApplication::applicationDirPath() + "/../Settings" ); return dir.absolutePath() + "/";} QString appBaseName(){ QString appBaseName = QCoreApplication::applicationFilePath(); QStringList sl = appBaseName.split("/"); appBaseName = sl[ sl.count()-1 ]; // убираем ".EXE" для виндовых файлов appBaseName.replace( ".exe", "", Qt::CaseInsensitive ); return appBaseName;}
C++ (Qt)static bool readXmlFile(QIODevice &device, QSettings::SettingsMap &map);static bool writeXmlFile(QIODevice &device, const QSettings::SettingsMap &map);
C++ (Qt)CXmlSettings xml;obj->( xml.settings() );
C++ (Qt) m_xml.beginGroup( "ThresholdRU_Values" ); int nGearPos = 0; float fValueI = 0; QDomElement deItem = m_xml.currentElement().firstChildElement( "item" ); while( !deItem.isNull() ) { nGearPos = deItem.attribute( "gear_pos" ).toInt(); fValueI = deItem.attribute( "value_i" ).toDouble(); m_threshold_RU_Gear_Assign.insert( nGearPos, fValueI ); deItem = deItem.nextSiblingElement( "item" ); }; m_xml.endGroup();
C++ (Qt)#ifndef __XML_SETTINGS_H__#define __XML_SETTINGS_H__ #include <QDomDocument>#include <QVariant> class CXml_Settings{ QDomDocument m_doc; QDomElement m_rootElement; QDomElement m_currentElement; QString m_sFileName; bool m_bAutoSave; public: CXml_Settings(); CXml_Settings( QString sFName ); ~CXml_Settings(); bool loadFromFile( const QString sFName ); void saveToFile( const QString sFName ); void beginGroup( const QString sName ); void endGroup(); QVariant value( const QString & sName, const QVariant & defaultValue = QVariant() ); void setValue ( const QString & key, const QVariant & value ); inline QDomElement& currentElement() { return m_currentElement; }; inline QDomElement& rootElement() { return m_rootElement; }; inline void setAutoSave( bool bVal ) { m_bAutoSave = bVal; } private: void createRootElement();}; #endif // __XML_SETTINGS_H__
C++ (Qt) #include "Xml_Settings.h" #include "FileUtils.h"#include "DebugLog.h" #define ROOT_NODE_NAME "Main" CXml_Settings::CXml_Settings() : m_doc(""){ m_sFileName.clear(); createRootElement(); m_bAutoSave = true;} CXml_Settings::CXml_Settings( QString sFName ) : m_doc(""){ m_sFileName.clear(); createRootElement(); loadFromFile( sFName );} CXml_Settings::~CXml_Settings(){ if ( ( m_bAutoSave ) && ( !m_sFileName.isEmpty() ) ) saveToFile( m_sFileName );} bool CXml_Settings::loadFromFile( const QString sFName ){ m_doc.clear(); m_sFileName = sFName; if ( !openXMLfile( m_sFileName, QFile::ReadOnly, m_doc ) ) { createRootElement(); return false; } else { m_rootElement = m_doc.namedItem( ROOT_NODE_NAME ).toElement(); bool bNormalLoad = !m_rootElement.isNull(); if ( !bNormalLoad ) ERROR_OUT << "Can't find root XML node with name =" << ROOT_NODE_NAME; m_currentElement = m_rootElement; return bNormalLoad; };} void CXml_Settings::saveToFile( const QString sFName ){ saveXMLfile( sFName, m_doc );} void CXml_Settings::beginGroup( const QString sName ){ QDomNode node = m_currentElement.namedItem( sName ); if ( !node.isNull() ) m_currentElement = node.toElement(); else { QDomElement deNewElement = m_doc.createElement( sName ); m_currentElement.appendChild( deNewElement ); m_currentElement = deNewElement; };} void CXml_Settings::endGroup(){ if ( m_currentElement.nodeName() == ROOT_NODE_NAME ) return; m_currentElement = m_currentElement.parentNode().toElement();} QVariant CXml_Settings::value( const QString & key, const QVariant & defaultValue ){ if ( m_currentElement.hasAttribute( key ) ) return QVariant( m_currentElement.attribute( key ) ); else { m_currentElement.setAttribute( key, defaultValue.toString() ); return defaultValue; }} void CXml_Settings::setValue ( const QString & key, const QVariant & value ){ m_currentElement.setAttribute( key, value.toString() );} void CXml_Settings::createRootElement(){// QDomNode xmlNode = m_doc.createProcessingInstruction("xml","version=\"1.0\" encoding=\"UTF-8\"");// m_doc.insertBefore(xmlNode, m_doc.firstChild()); m_rootElement = m_doc.createElement( ROOT_NODE_NAME ); m_doc.appendChild( m_rootElement ); m_currentElement = m_rootElement;}
C++ (Qt)bool openXMLfile( QString fname, QFile::OpenMode mode, QDomDocument& doc ){ QFile file( fname ); if ( !file.open(mode) ) { ERROR_OUT << "Error open file: " << fname << "!!!"; return false; }; if ( !doc.setContent(&file) ) { ERROR_OUT << "Error read XML file: " << fname << "!!!"; file.close(); return false; } file.close(); return true;} bool saveXMLfile(QString fname, QDomDocument& doc){ QFile ofile( fname ); if (!ofile.open(QIODevice::WriteOnly)) { ERROR_OUT << "Can't open file to write: " << fname; return false; }; QTextStream out(&ofile); //doc.save(out, 4); out.setCodec( QTextCodec::codecForName("UTF-8") ); doc.save(out, 4, QDomNode::EncodingFromTextStream ); ofile.close(); return true;}