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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: как сохранить QList<MyType> в QSettings  (Прочитано 6126 раз)
Smogg
Гость
« : Июль 22, 2013, 21:39 »

не получается сохранить или прочитать настройки через QVariant.
Отчего?
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #1 : Июль 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;
   ...
}
 
Записан
ритт
Гость
« Ответ #2 : Июль 23, 2013, 10:12 »

не, стримоператоры - это не то. декларации метатипа должно быть достаточно.
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #3 : Июль 23, 2013, 10:38 »

не, стримоператоры - это не то. декларации метатипа должно быть достаточно.

Недостаточно, ведь в QSettings сохраняется QVariant, а откуда QVariant узнает как сериализовать твой собственный тип? И в консоль будет сыпаться "QVariant::save: unable to save type xxx"
Записан
ритт
Гость
« Ответ #4 : Июль 23, 2013, 10:46 »

всё незнакомое QVariant хранит в void*
для конструирования/копирования метатипов в рантайм требуется qRegisterMetaType<>() (который вызывается из qRegisterMetaTypeStreamOperators<>() для удобства), но стримоператоры нужны только для сериализации в датастрим и здесь неуместны.
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #5 : Июль 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.
« Последнее редактирование: Июль 23, 2013, 11:11 от Alex Custov » Записан
Smogg
Гость
« Ответ #6 : Июль 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 в объявлении?
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #7 : Июль 23, 2013, 15:37 »

Как надо реализовывать этот оператор, т.е. лишь бы был доступ из main()?

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

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

если функция используется только в данном TU, то я пишу static чтобы сделать её локальной.
Записан
Smogg
Гость
« Ответ #8 : Июль 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.
Можно как-нибудь запретить завершать нулем каждый байт?
Записан
Alex Custov
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 2063


Просмотр профиля
« Ответ #9 : Июль 23, 2013, 17:02 »

ничего не поделаешь, это сериализация. Рекомендую использовать также IniFormat, он быстрее, чем реестр.
Записан
Smogg
Гость
« Ответ #10 : Июль 23, 2013, 19:54 »

Рекомендую использовать также IniFormat, он быстрее, чем реестр.
OK, thnx!
Записан
ритт
Гость
« Ответ #11 : Июль 23, 2013, 21:08 »

эмм, каюсь, невнимательно прочитал первый пост - речь о сериализации через вариант в QSettings - а про QSettings я как-то и забыл сразу...

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

Как надо реализовывать этот оператор, т.е. лишь бы был доступ из main()?
я предпочитаю инлайнами рядом с декларацией типа (если, конечно, сериализация не требует обращения к приватам и т.п.).
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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