Russian Qt Forum

Qt => Вопросы новичков => Тема начата: Smogg от Июль 22, 2013, 21:39



Название: как сохранить QList<MyType> в QSettings
Отправлено: Smogg от Июль 22, 2013, 21:39
не получается сохранить или прочитать настройки через QVariant.
Отчего?


Название: Re: как сохранить QList<MyType> в QSettings
Отправлено: Alex Custov от Июль 22, 2013, 21:59
Код не смотрел. Во-первых, о своих типах нужно сообщить куда надо в moc:

Код
C++ (Qt)
struct MyType
{
  QString data;
};
 
Q_DECLARE_METATYPE(MyType)
Q_DECLARE_METATYPE(QList<MyType>)
 

Во-вторых, нужно написать [де]сериализатор и зарегистрировать его:

Код
C++ (Qt)
static QDataStream &operator<<(QDataStream &out, const MyType &t)
{
   out << t.data;
   return out;
}
 
static QDataStream &operator>>(QDataStream &in, MyType &t)
{
   in >> t.data;
   return in;
}
 
...
 
main()
{
   ...
   qRegisterMetaTypeStreamOperators<MyType>("MyType");
   qRegisterMetaTypeStreamOperators<QList<MyType> >("QList<MyType>");
 
   QSettings sett;
   ...
}
 


Название: Re: как сохранить QList<MyType> в QSettings
Отправлено: ритт от Июль 23, 2013, 10:12
не, стримоператоры - это не то. декларации метатипа должно быть достаточно.


Название: Re: как сохранить QList<MyType> в QSettings
Отправлено: Alex Custov от Июль 23, 2013, 10:38
не, стримоператоры - это не то. декларации метатипа должно быть достаточно.

Недостаточно, ведь в QSettings сохраняется QVariant, а откуда QVariant узнает как сериализовать твой собственный тип? И в консоль будет сыпаться "QVariant::save: unable to save type xxx"


Название: Re: как сохранить QList<MyType> в QSettings
Отправлено: ритт от Июль 23, 2013, 10:46
всё незнакомое QVariant хранит в void*
для конструирования/копирования метатипов в рантайм требуется qRegisterMetaType<>() (который вызывается из qRegisterMetaTypeStreamOperators<>() для удобства), но стримоператоры нужны только для сериализации в датастрим и здесь неуместны.


Название: Re: как сохранить QList<MyType> в QSettings
Отправлено: Alex Custov от Июль 23, 2013, 10:48
проверил - ты прав.

Up. Поспешил, что-то не сходится

Код
C++ (Qt)
struct MyType
{
   MyType(const QString &d = QString(), int t = 0)
       : data(d), type(t)
   {}
 
   QString data;
   int type;
};
 
Q_DECLARE_METATYPE(MyType)
Q_DECLARE_METATYPE(QList<MyType>)
 
int main(int argc, char *argv[])
{
   QCoreApplication::setApplicationName("T2");
   QCoreApplication::setOrganizationName("T2");
 
   QCoreApplication ap(argc, argv);
 
   qRegisterMetaType<MyType>("MyType");
   qRegisterMetaType<QList<MyType> >("QList<MyType>");
 
   MyType t("xxx", 8);
   QSettings ss;
   ss.setValue("key", QVariant::fromValue<MyType>(t));
   return 0;
}
 

Цитировать
QVariant::save: unable to save type 258.


Название: Re: как сохранить QList<MyType> в QSettings
Отправлено: Smogg от Июль 23, 2013, 15:30
Alex Custov, спасибо! работает)

Но есть вопрос на понимание:
Код
C++ (Qt)
static QDataStream &operator<<(QDataStream &out, const MyType &t)
{
   out << t.data;
   return out;
}
Как надо реализовывать этот оператор, т.е. лишь бы был доступ из main()?
 A если его не получается засунуть в class , то зачем нужно static в объявлении?


Название: Re: как сохранить QList<MyType> в QSettings
Отправлено: Alex Custov от Июль 23, 2013, 15:37
Как надо реализовывать этот оператор, т.е. лишь бы был доступ из main()?

доступ должен быть там, где используется QSettings::value() и QSettings::setValue(). В данном случае - в main.

A если его не получается засунуть в class , то зачем нужно static в объявлении?

если функция используется только в данном TU, то я пишу static чтобы сделать её локальной.


Название: Re: как сохранить QList<MyType> в QSettings
Отправлено: Smogg от Июль 23, 2013, 17:00
TU - как расшифровывается? Темплейт юнит?

Нулей-то, нулей-то пихается в ключ реестра...

Такой вариант ситуацию чуть улучшил:
Код:
static QDataStream &operator<<(QDataStream &out, const _ITEM_s &t)
{
QByteArray utf;
out << t.val1.toUtf8();
out << t.val2.toUtf8();
out << t.val3.toUtf8();
return out;
}

static QDataStream &operator>>(QDataStream &in, _ITEM_s &t)
{
QByteArray utf;
in >> utf;
t.val1 = QString::fromUtf8(utf, -1);
in >> utf;
t.val2 = QString::fromUtf8(utf, -1);
in >> utf;
t.val3 = QString::fromUtf8(utf, -1);

return in;
}
Но все равно на русскую 'ы' тратится 4 байта. Хотя QString, как и положено, пишет в Unicode-16.
Можно как-нибудь запретить завершать нулем каждый байт?


Название: Re: как сохранить QList<MyType> в QSettings
Отправлено: Alex Custov от Июль 23, 2013, 17:02
ничего не поделаешь, это сериализация. Рекомендую использовать также IniFormat, он быстрее, чем реестр.


Название: Re: как сохранить QList<MyType> в QSettings
Отправлено: Smogg от Июль 23, 2013, 19:54
Рекомендую использовать также IniFormat, он быстрее, чем реестр.
OK, thnx!


Название: Re: как сохранить QList<MyType> в QSettings
Отправлено: ритт от Июль 23, 2013, 21:08
эмм, каюсь, невнимательно прочитал первый пост - речь о сериализации через вариант в QSettings - а про QSettings я как-то и забыл сразу...

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

Как надо реализовывать этот оператор, т.е. лишь бы был доступ из main()?
я предпочитаю инлайнами рядом с декларацией типа (если, конечно, сериализация не требует обращения к приватам и т.п.).