LINUX.ORG.RU

А расскажите мне про Qt еще! (чтение/сохранение проекта)

 , , ,


1

3

1. В каком формате сохранять? Тут у нас много вариантов. Хотел бы услышать ваши варианты, в каком лучше и чем? Тут я немного потерялся:

1.1. xml? Ну, неплохо, но пилить валидацию на момент загрузки файла.
1.2. json? Тоже хуман реадабле, но опять пилить валидацию на момент загрузки файла.
1.3. QSettings? toByteArray()? Уже глазками не почитать, но зато валидация только один раз (заполнение моделек данными).
1.4. Бинарщина? Мутотня с байтордер, да и может еще чем открыть захочу.
1.5. Я не в курсе и есть другой вариант?

2. Есть связанные и вложенные Model/View и тут бы не создавать лишних прослоек, в частности, используя xml/json получается цепочка: файл-данные-модели, а используя нечитаемые форматы будет цепочка: файл-модели. Понятно, что, модель что-то валидирует при её заполнении данными.

Вобщем вопрос такой комплексный — это вообще нормально валидировать сначала на этапе чтения формата, а затем второй раз при заполнении моделей? Если ответ ДА, то я со спокойной душой запилю на json или xml, но если есть иные менее накладные по кол-ву строк кода варианты — я бы с удовольствием их выслушал. Ну и просто приглашаю подискутировать на этот счет.

Первое:

  1. Валидацию XML пилить не надо, в Qt есть свои классы для работы с XML-документами, которые всё сделают за тебя;
  2. Аналогично;
  3. QSettings — можно, если твой проект можно описать ini-файлом (во что ещё он умеет сохранять, я не помню, использовал только ini), QByteArray же сам по себе никуда не записывает;
  4. Мутотни с ByteOrder нет, если используешь QDataStream (он по умолчанию пишет/читает в сетевом порядке), единственное — стоит сперва записать QDataStream::version() (а потом считать и установить при открытии). Простые типы и классы Qt при записи через QDataStream сериализуются, с этим проблем никаких нет;
  5. Можешь в своём формате сохранить, никто не мешает. Если формат будет текстовый, то берёшь QTextStream и вперёд.

Второе: ты можешь сделать свою модель, которая будет читать напрямую из файла/-ов. И валидирование будет происходить лишь один раз

XMs ★★★★★
()
Ответ на: комментарий от deep-purple

Так настройки или сами данные? Если второе - то зависит от данных. В графическом редакторе сохранение в sql базу ну ни разу не нужно.

RazrFalcon ★★★★★
()
Ответ на: комментарий от XMs

1. Имелась ввиду валидация «а есть ли там такой тег и какой тип данных он содержит». В частности для xml есть xsd schema какраз для этого (вплоть до в каком порядке объявлены теги).

2. А вот для json я что-то не припомню, т.е. придется руками проверять, что такое поле есть и оно содержит именно массив объектов и каждый такой объект в цикле придется провалидировать вглубь.

3. ini сразу отказать — много вложений и много свойств в каждом. Тут я не имел ввиду только QSettins, но еще и toByteArray() как пример того что можно записать данные в сериализованом виде. Насчет простых типов и классов — даже наследуясь от них мне всеравно навешивать свое придется.

Второе:

Мне кажется что давать модели читать файл можно в простых случаях, но точно не в моем. Тут уж пусть каждый своим занимается.

А вот что я имел ввиду под вторичной валидацией: модель, приняв правильные типы данных от загруженного и провалидированного ранее файла, валидирует их значения. Этот же механизм я использую и при взаимодействии с вьюхой — пользак отправил новые данные, но модели они могут не понравится.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от RazrFalcon

Да какие настройки, настройки без вопросов были мной выкурены и реализованы. А тут суть, нужен файл проекта, который пользак может сохранить на флешку, перенести и открыть с другого компа.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

В частности для xml есть xsd schema

QtXmlPatterns — там что-то такое было.


руками проверять, что такое поле есть

Посмотри в https://doc.qt.io/qt-5.6/json.html — я с JSON не работал, поэтому не знаю, на что оно способно, знаю лишь, что оно есть.


toByteArray()
записать данные в сериализованом виде

Не уверен, что понял тебя правильно. Метод toByteArray не даёт сериализации, этим занимаются стримы.


модель, приняв правильные типы данных от загруженного и провалидированного ранее файла, валидирует их значения

То есть, речь идёт о валидации другого рода, например, корректности значений? Тогда валидация XML тут уже ни при чём, это валидация уже извлечённых данных. Хотя и так ты можешь прямо из модели работать с QXmlDocument/QJsonDocument/Whatever. Не понимаю, что тебе не нравится в таком подходе

XMs ★★★★★
()
Ответ на: комментарий от XMs

Насчет xsd валидации в Qt я в курсе, прикрутить можно. Там тупо декларируешь правила (xml формат) для валидатора и он скушав правила, валидирует целевой xml файл.

Для json насколько я знаю такого нет вообще, не только в Qt. В том и проблема. Придется проверять руками.

Возможно я и имел ввиду стримы. Но когда писал пост, вспомнил что находил в сети пример того как можно использовать QSettings в кастомный файл (в моем случае файл проекта) содержимым вида: «fooBar=@ByteArray(\0\0\0\xff\0\0\0\x1\0\0\0\x2\0\0\0\xcd\0\0\x1\xf0\0\0\0\0\x1\x1\0\0\0\x1\0)» так вот toByteArray сам «провалидирует» по идее, далее просто дергаем isValid().

Мне не может нравится или не нравится, я просто не хочу делать лишних движений. На примере xml/json валидация формата потребуется, а на примере «более близких к бинарю» уже вроде как меньше телодвижений.

И еще один немаловажный момент — у меня проект А может быть частью (вложением) проекта Б. Но только при импорте, конечно. А после успешной вставки данных это просто еще более глубокое вложение и сохраняться это будет как проект Б без каких либо отсылок к А и никак уже не действовать на данные в А.

Поэтому я и хочу отделить валидатор формата от валидатора значений. Или максимально избавиться от написания ручками полной валидации формата.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от RazrFalcon

Вот я и хочу выяснить что мне будет удобным.

deep-purple ★★★★★
() автор топика

Я и в прошлый раз похожую тему создавал.

Вот сейчас мне кажется что надо брать xml с валидацией по шеме. И затем уже валидировать значения в моделях теми же валидаторами что проверяют ввод пользака из вьюх.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

QSettings в кастомный файл

Это немного не то. По мне так если уж писать в текстовом формате, то и данные по возможности записывать текстом.


я просто не хочу делать лишних движений

Проверка типов — её тебе в любом случае так или иначе надо делать, пользователь может подсунуть битый или заведомо неправильный файл. В случае бинарных данных типы особо не проверишь, зато надо постоянно проверять, не попал ли на конец файла — по мне так затраты в плане лишних строчек кода сопоставимые.

Я тебе рекомендую написать операторы << и >> для QDataStream/QTextStream для тех классов, которые ты планируешь сохранять. У тебя в итоге сохранение проекта сведётся к stream << project;, и внутри оператора будет то же самое для полей класса. Аналогично с чтением. Даже если в итоге они тебе не понадобятся для основного формата, ты их сможешь использовать потом.


проект А может быть частью (вложением) проекта Б

То есть у тебя в классе проекта есть список, хранящий экземпляры класса проекта? Типа Project содержит QList<Project>? IMHO, свой формат здесь пилить смысла нет, JSON хватит за глаза. XML, может, лучше валидируется, но внешне ужасен, поэтому его не советую

XMs ★★★★★
()
Последнее исправление: XMs (всего исправлений: 1)

QSettings - кал бегемота. Я пользовался, не нравится непредсказуемое время фактической записи настроек. Это бред.

Лучше используй старый добрый INI, но если надо произвольные массивы в настройки сувать, то тогда храни строку в ini-файле, но сделать свой сериализатор-десериазатор, путем разбиения данных при помощи { } : , и прочих спец символов.

I-Love-Microsoft ★★★★★
()

QVariantList можно в строку, а из строки обратно спарсить средствами Qt в идентичный список вариантов.

Вот пример из настроек Qt Creator-а:

[DesignerPropertyEditor]
Colored=true
ExpandedItems="@Variant(\0\0\0\b\0\0\0r\0\0\0\x1e\0S\0p\0\x61\0\x63\0\x65\0r\0|\0s\0i\0z\0\x65\0H\0i\0n\0t\0\0\0\x1\x1\0\0\0\f\0S\0p\0\x61\0\x63\0\x65 ... \0o\0r\0m\0\x41\0l\0i\0g\0n\0m\0\x65\0n\0t\0\0\0\x1\0\0\0\0\f\0L\0\x61\0y\0o\0u\0t\0\0\0\x1\x1\0\0\0\f\0H\0\x65\0\x61\0\x64\0\x65\0r\0\0\0\x1\x1)"
Sorted=false
SplitterPosition=175
View=0
Хотя сам файл тупо INI, но в остальном - в строках можно очень гибкие структуры хранить, которые легко слизать обратно из строки в QVariantList-список в памяти.

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

QSettings - кал бегемота. Я пользовался, не нравится непредсказуемое время фактической записи настроек. Это бред.

Шта?! Какая разница когда оно на диск сбросит?

RazrFalcon ★★★★★
()
Ответ на: комментарий от RazrFalcon

Хорошо, это моя личная боль. Ненавижу недетерминированные хоть как-то процессы. Может это аллергия на всякие KDEшные тормозяки, всякие mlocate apt-индексы и прочие виндовые шуршалки, что некстати выползают и вешают систему.

I-Love-Microsoft ★★★★★
()
Последнее исправление: I-Love-Microsoft (всего исправлений: 1)
Ответ на: комментарий от deep-purple

Вот сейчас мне кажется что надо брать xml с валидацией по шеме. И затем уже валидировать значения в моделях теми же валидаторами что проверяют ввод пользака из вьюх.

Ъ. бинарники не бери, т.к. при разрастании версий модели будет довольно неудобно.

dib2 ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

QSettings - кал бегемота

Лучше используй старый добрый INI

Но ведь QSettings это и есть INI по дефолту в GNU/Linux. В MS Windows это реестр, а в macOS х.з.

EXL ★★★★★
()
Ответ на: комментарий от deep-purple

данные «проекта» над которым работает пользак.

а какие проблемы то... хочешь в бинарный поток заворачивай все классы в Q_DECLARE_METATYPE, хочешь в xml/json я по старой привычке операторами >> << для каждого класса, валидация проста, в начале потока обязательна версионность, которую нужно отслеживать и соблюдать.

anonymous2 ★★★★★
()
Ответ на: комментарий от XMs

QtXmlPatterns — там что-то такое было.

Он недопиленный, заброшенный и валидация схемы там неполная

UVV ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

QSettings - кал бегемота. Я пользовался, не нравится непредсказуемое время фактической записи настроек. Это бред.

Есть мнение, что запишет не позже вызова деструктора. Претензия могла появиться только если ты хранишь экземпляр QSettings долго (не понятно только, зачем)

UVV ★★★★★
()
Ответ на: комментарий от dt1

Ох блин, давно этот метод там? Я искал save/store, а слона не приметил. Что еще я не знаю об этой вселенной?

I-Love-Microsoft ★★★★★
()
Ответ на: комментарий от deep-purple

Имелась ввиду валидация «а есть ли там такой тег и какой тип данных он содержит».

Зачем тебе это? Ты его пишешь, ты его читаешь, предусматривать какие-то неожиданные вещи нет смысла. Делай оптимистичный парсинг и всё, если документ действительно сломан тебе вернутся пустые данные, просто обрабатывай это корректно, а дальше проблемы исключительно того кто руками влез в твой документ и сломал его.

slovazap ★★★★★
()
Ответ на: комментарий от I-Love-Microsoft

непредсказуемое время фактической записи

sync() вроде жи.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от UVV

Он вообще живет статически глобально ака синглтон весь рантайм, дефолтно. Но можно и накрутить иначе.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от slovazap

Если василий пупкин подсунет мне правленный руками и валидный хмл, то... наличие тегов и типы данных в них проверять придется.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от XMs

Хмм, << >> надо подумать за этот вариант, несмотря что он бинарный.

Нет, проект не содержит другие проекты, из А берется все что лежит в его корневом узле данных и вставляется как стандартные потомки в выбранный пользаком узел в проекте Б. Это не подпроект. Все дерево из А становится веткой в Б.

deep-purple ★★★★★
() автор топика
Последнее исправление: deep-purple (всего исправлений: 1)

Можно сохранить в QJson, по умолчанию использовать бинарный формат (его родной, данные в памяти хранятся точно так же как в бинарнике), а при отладке сохранять в текст. Валидации документа нет, только проверка что документ well-formed, но если этот документ генерится твоей же программой, то это вряд ли нужная фича

annulen ★★★★★
()
Ответ на: комментарий от slovazap

Валидный только с точки зрения хмл, но без какого-нибудь тега и данных в нем для модели.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

несмотря что он бинарный

Совершенно необязательно, ты можешь добавить операторы для QTextStream.


дерево из А становится веткой в Б

Значит, пишешь операторы для ноды, и в каждой проходишься по дочерним. Не велика разница

XMs ★★★★★
()
Ответ на: комментарий от XMs

Да. Для начала ковырну всетаки хмл с шемами, может мне тех фич хватит. Все же хотелось бы читаемый формат + его поддержку в Qt. Не прокатит, тогда запилю на стримах.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

Он вообще живет статически глобально ака синглтон весь рантайм, дефолтно.

Кто он? QSettings не синглтон. Если он у тебя в приложении синглтон, то ССЗБ.

UVV ★★★★★
()
Ответ на: комментарий от deep-purple

Только если ты плохо напишешь код. К валидации это ортогонально, прорамма точно так же может падать от документа прошедшего валидацию, так как схемы не всеобъемлющи

annulen ★★★★★
()

Я бы сохранял все в БД (SQLite к примеру) и не парил мозг. См. например сорцы QtC, там есть класс который сохраняет все в базу типа ключь-значение.

Идея такая, что приложение должно иметь виртуальные методы типа fromMap/toMap (точнее, каждый модуль/плагин приложения, который должен чо-то сохранять). И в этом случае каждый модуль переопределяет эти методы и только он и знает как добыть свои значения из мапы, или как сохранить в мапу.. Соответвтвенно, каждый берет то что ему надо. Как то так.

PS: Хотя, можно и сеттинги, но это не годится, к примеру, если приложение работает с некими проектами, которые нужно переносить с компа на комп и открывать в приложении.

PS: А можно и комбинировать settings - только для настроек внешнего вида приложения пользователем (каждый настраивает под себя чо то там), db - для хранения общих вещей, переносимых.

kuzulis ★★
()
Последнее исправление: kuzulis (всего исправлений: 1)
Ответ на: комментарий от kuzulis

ключь-значение

У меня не такие данные чтобы извращаться с плоской БД.

deep-purple ★★★★★
() автор топика
Ответ на: комментарий от deep-purple

Как это утверждение коррелирует с синглтоном? Не хочешь пойти почитать, что такое синглтон?

UVV ★★★★★
()
Ответ на: комментарий от deep-purple

Он вообще живет статически глобально ака синглтон весь рантайм, дефолтно. Но можно и накрутить иначе.

Какой нах кал? Вот твоё высказывание. Ты точно знаешь, что такое синглтон?

Синглтоном он был бы, если бы записывал данные на диск при выходе их программы, ибо синглтон уничтожается именно тогда. Видишь разницу?

UVV ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.