Russian Qt Forum
Сентябрь 21, 2024, 20:19 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 2 [3]   Вниз
  Печать  
Автор Тема: Проблема с записью в ini файл  (Прочитано 26043 раз)
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #30 : Июль 05, 2009, 20:45 »

Цитировать
Жаль, если это так, не хотелось бы заморачиваться с написанием своих ReadFunc и WriteFunc.

Сталкивался с описанной здесь проблемой и с некоторыми другими при работе с INI - например абсолючно не читаемое для человека представление таблицы или вложенной таблицы. Написал свои ReadFunc и WriteFunc для XML файлов. Теперь все настройки храню в XML. Интерфейс использования естественно не изменился, уже в какой-то теме выкладывал если нужно выложу здесь еще раз.
Записан
Alexkvs
Гость
« Ответ #31 : Июль 06, 2009, 19:23 »

Цитировать
Жаль, если это так, не хотелось бы заморачиваться с написанием своих ReadFunc и WriteFunc.
... если нужно выложу здесь еще раз.
Выложите если можно, многим думаю пригодится.
Записан
break
Гипер активный житель
*****
Offline Offline

Сообщений: 846


Просмотр профиля
« Ответ #32 : Июль 06, 2009, 19:51 »

выкладываю:
H файл: XmlSettings.h
Код
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__
 
 

CPP файл: XmlSettings.cpp
Код
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 );
};
}
 
 

Функции settingsPath()  и  appBaseName() - у меня реализованы в моем FileUtils - возвращают дефолтный путь к папке с настройками и базовое имя программы (без расширения)

Также продублировал во вложении.

Пользоваться можно через обращение к settings() - всеми возможностями самого QSettings - группы, массивы и т.д. Ограничение - нельзя использовать атрибут с именем "table" - он используется для определения таблицы (массива) при чтение настроек. Если пользоваться через прямые методы value, CXmlSettings - то в случае если значения в конфиге не было - оно создасться и заполниться значением по умолчанию (сделал чтобы программа сама создавала свой конфиг если был утерян...).
« Последнее редактирование: Июль 06, 2009, 19:55 от break » Записан
ритт
Гость
« Ответ #33 : Август 11, 2009, 19:01 »

break, продублируй, пожалуйста, последний пост в "доп.компонентах". и хотелось бы файлик лицензии в папке с исходниками...
Записан
Страниц: 1 2 [3]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.127 секунд. Запросов: 22.