Russian Qt Forum

Qt => Общие вопросы => Тема начата: Гурман от Июнь 29, 2010, 14:44



Название: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: Гурман от Июнь 29, 2010, 14:44
первый раз пишется объект, наследующий QSettings, записывается пустой QStringList, причем его по идее нельзя ничем заполнять, запись выполняется таким образом:

Код:
	beginGroup( "ShellSettings" );
setValue("MRUlist", MRUlist );
endGroup();

в файле появляется запись

Код:
[ShellSettings]
MRUlist=@Invalid()

после добавления хотя бы одного имени в MRU list, он снова сохраняется точно тем же кодом, но в файле остается предыдущая запись и появляется совершенно отдельный ключ, не входящий в сегмент [ShellSettings], но входящий в предыдущий сегмент (в моем случае это [ViewSettings], ключ выглядит таким образом:

Код:
ShellSettings\MRUlist=<полное имя файла>

далее при добавлении файлов в список, они добавляются в этот ключ, а предыдущий созданный инвалид остается на месте

что не есть правильно, хотя ключ восстанавливается вроде бы верно, и при старте приложение получает список предыдущих открытых файлов

баг??


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: crossly от Июнь 29, 2010, 14:54
я так полагаю не закрыта группа [ViewSettings].... вот в нее и пишется....

ПЫСЫ можно было и в предыдущем топике закончить разговор...


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: Гурман от Июнь 29, 2010, 15:02
группа точно закрыта, и пишет в обоих случаях один и тот же метод recordSettings() но в первом случае пишет одно, во втором другое




Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: crossly от Июнь 29, 2010, 15:17
давай чуть модифицируем мой пример
Код:
QSettings s("test.ini",QSettings::IniFormat);
    QStringList list;
    s.beginGroup("test");
    list<<"test"<<"sss"<<"1";
    s.setValue("list",list);
    s.beginGroup("test");
    s.setValue("list",list);
результат
Код:
[test]
list=test, sss, 1
test\list=test, sss, 1

ежели сделаем так
Код:
QSettings s("test.ini",QSettings::IniFormat);
    QStringList list;
    s.beginGroup("test");
    list<<"test"<<"sss"<<"1";
    s.setValue("list",list);
    s.endGroup();
    s.beginGroup("test");
    s.setValue("list",list);
    s.endGroup();
получим
Код:
[test]
list=test, sss, 1

ничего не напоминает??


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: Гурман от Июнь 29, 2010, 15:34
нет, не напоминает

я же ясно написал - первый раз ключ создается с пустым списком QStringList, в результате появляется запись с Invalid внутри группы

второй раз тот же самый код создает запись с непустым списком, который записывается, как длинный ключ, а в группу ничего не добавляется

если есть сомнения в моей внимательности или желание поупражняться в проверке баланса begin/end, то вот пожалуйста код функции, пишущей группы, убраны только коды записи отдельных ключей

Код:
void Settings::recordSettings()
{
setValue("SettingsDefined", true );
beginGroup( "ViewSettings" );

beginGroup( "MainText" );

beginGroup( "FontsAndColors" );
endGroup(); // FontsAndColors

beginGroup( "DistanciesAndSizes" );
endGroup(); // DistanciesAndSizes

beginGroup( "OtherSettings" );
endGroup(); // OtherSettings

endGroup(); // MainText

beginGroup( "ConsoleText" );

beginGroup( "FontsAndColors" );
endGroup(); // FontsAndColors

beginGroup( "OtherSettings" );
endGroup(); //OtherSettings

endGroup(); // ConsoleText

beginGroup( "SelectAndView" );
endGroup(); // SelectAndView

endGroup(); // ViewSettings

beginGroup( "ShellSettings" );
setValue("MRUlist", MRUlist );
endGroup(); //ShellSettings

sync();
}


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: crossly от Июнь 29, 2010, 15:39
покажите полностью получившуюся инишку...


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: Гурман от Июнь 29, 2010, 15:43
Код:
[General]
SettingsDefined=true

[ViewSettings]
ProgramText\FontsAndColors\<несколько записей>
ProgramText\OtherSettings\<несколько записей>
SettingsDefined=true
ViewSettings\ProgramText\FontsAndColors\<несколько записей, столько же и такие же, как в предыдущем ключе>
ShellSettings\MRUlist=<список через запятые>

[ShellSettings]
MRUlist=@Invalid()

может собака порылась в том, что у меня есть пустые группы только из begin/end?


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: crossly от Июнь 29, 2010, 15:46
на лицо  косяк с закрытием группы [ViewSettings].... попробуй закоментировать пустую...


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: Гурман от Июнь 29, 2010, 15:48
точно! закомментировал все пустые пары begin/end - все стало нормально

не помню, чтобы в документации было где-либо сказано, что пустых групп не должно быть... если пропустил, мой промах, если нет - надо писать report о неполной документации


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: Гурман от Июнь 29, 2010, 15:52
ХОТЯ НЕТ! ВРУ!!!

Первый раз создается правильный файл установок.

Но при перезаписи получается опять двоение...  ???

Причем при загрузке настроек, они читаются ТОЛЬКО из длинных ключей, то есть, при загрузке правильного созданного в первый раз файла настроек, содержимое MRUlist не восстанавливается


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: crossly от Июнь 29, 2010, 16:08
тады весь код показывай....


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: break от Июнь 29, 2010, 19:32
сори оффтоп:
Вроде INI шники нужны чтобы человек мог их поправить вручную - но с QSettings и его способом представления в INI пар ключей/значений это не очень хорошо получается. Особенно если несколько вложенных массивов сохранить друг в друга. В вашей задаче смысл с ним мучаться есть?

Даже если то с чем вы столкнулись не косяк - то там косяки точно есть например:
1) бесконечное переупорядочевание пар ключ/значение в конечном файле - результат файл нечитаем для пользователя - пока найдешь то что было в определенной строке - глаза сломаешь
2) неправильная работа если передать пустое имя файла (необнуление пар ключ/значение, даже после удаления конкретного экземпляра QSettings - они кешируются в приватной части которая видимо для всех экземпляров общая - что вызовет ошибку если разные части программы будут независимо читать свои настройки где ключи одинаково называются - например каждый загружаемый плагин)


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: Гурман от Июнь 29, 2010, 20:01
Цитировать
В вашей задаче смысл с ним мучаться есть?

да, есть, требование портабельности + работа без инсталляции

Цитировать
весь код показывай

какой именно? который убран из кода выше? там только строки setValue(), больше ничего

есть еще код загрузки из настроечного файла, там могли оказаться непарные begin-end, хотя маловероятно, и если они в самом деле есть, то точно есть косяк в QSettings, из-за которого загрузка из файла ломает его последующую запись

имхо, эта модель с begin-end - ущербная, и плохо продуманная

я сначала подумал, что можно унаследовать QSetiings, и в классе-наследнике "сообщить" классу-родителю, какие данные надо сохранять и загружать при выполнении sync(), имхо это было бы правильно, но оказалось не так, а гораздо примитивнее


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: break от Июнь 29, 2010, 20:18
Цитировать
да, есть, требование портабельности + работа без инсталляции

Для этого подойдет и XML


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: Гурман от Июнь 29, 2010, 20:35
угу, и как его включить, если enum QSettings::Format имеет 2 варианта: QSettings::NativeFormat и QSettings::IniFormat ? я все время удивляюсь, что нет вариант QSettings::XmlFormat, который был бы наиболее логичен


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: SimpleSunny от Июнь 29, 2010, 20:46
Можно глянуть тут.
http://www.prog.org.ru/topic_12074_0.html


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: Гурман от Июнь 29, 2010, 21:21
не нравится... это должно было быть нативно


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: break от Июнь 29, 2010, 21:34
куитивно


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: Гурман от Июнь 30, 2010, 08:23
Все, исправил... в коде загрузки настроек были пустые пары begin-end и это влияло на запись, поэтому первоначально создавался правильный файл, а если он уже был, то после загрузки настроек все ломалось

ИМХО еще раз - механизм QSettings реализован угребищный, можно было бы сделать гораздо удобнее и надежнее в использовании.

а чтобы не было больше такой ситуации, переделал класс Settings "не по Шлее", сделал 1 метод записи-чтения настроек, чтобы структура задавалась 1 раз

Код:
void Settings::settingsSaveRestore( bool save )
{
if( save )
setValue("SettingsDefined", true );
beginGroup( "ViewSettings" );
{
beginGroup( "MainText" );
{
beginGroup( "FontsAndColors" );
{
if( save )
{
setValue(....);
......
}
else
{
var = value(....).value<QColor>();
....
}
}
endGroup(); // FontsAndColors

//beginGroup( "DistanciesAndSizes" );
//endGroup(); // DistanciesAndSizes

beginGroup( "OtherSettings" );
{
if( save )
{
setValue(....);
....
}
else
{
value = value(....).toInt();
....
}
}
endGroup(); // OtherSettings
}
endGroup(); // MainText

//beginGroup( "ConsoleText" );
{
//beginGroup( "FontsAndColors" );
//endGroup(); // FontsAndColors

//beginGroup( "OtherSettings" );
//endGroup(); //OtherSettings
}
//endGroup(); // ConsoleText

//beginGroup( "SelectAndViewWins" );
//endGroup(); // SelectAndViewWins
}
endGroup(); // ViewSettings

beginGroup( "ShellSettings" );
{
if( save )
{
setValue("MRUlist", MRUlist );
}
else
{
MRUlist = value("MRUlist").toStringList();
}
}
endGroup(); //ShellSettings
if( save )
sync();
}

соответственно, конструктор этого класса

Код:
Settings::Settings()
: QSettings( "settings.ini", QSettings::IniFormat )
{
if( !value( "SettingsDefined" ).toBool() )
{ // файл только что создан, установки не определены, заполняются умолчательными значениями
resetDefaultSettings();
settingsSaveRestore( true );
}
else // установки загружены из файла
settingsSaveRestore( false );
}


рекомендация в Шлее наихудшая


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: navrocky от Июнь 30, 2010, 09:28
rtfm QSettings::registerFormat, можешь сделать себе в формате XML


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: Гурман от Июнь 30, 2010, 10:08
некогда мне еще потрохами XML заниматься... тем более, что в INI пока все работает, что нужно

где-нибудь можно написать или подписать имеющийся feature request чтобы QSettings::XmlFormat и соответствующая поддержка появились?


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: break от Июнь 30, 2010, 13:27
Цитировать
где-нибудь можно написать или подписать имеющийся feature request чтобы QSettings::XmlFormat и соответствующая поддержка появились?

конечно можно - в баг репорте троллей, а на следующий день когда закроют - к себе в список дел, сделаешь все то же что уже делал я и поймешь что это не удобно - проще простенькую обвязку вокруг QDOMElement использовать. Да можно и просто QDOMElement - никаких глубоких проблем нет - переносимость, возможность правки пользователем, удобство при написании загрузки / сохранения, XML одинаковый на всех системах а не этот неичтаемый INI.


Название: Re: запись QSettings в INI создает 2 ключа, так и должно быть?
Отправлено: Гурман от Июнь 30, 2010, 13:48
Цитировать
сделаешь все то же что уже делал я и поймешь что это не удобно

почему это? я в таком случае просто заменю Settings::Settings() : QSettings( "settings.ini", QSettings::IniFormat ) на Settings::Settings() : QSettings( "settings.xml", QSettings::XmlFormat ) и меня это устроит