LINUX.ORG.RU
Форум — Development

Впечатления о QTextDocument и его сохранении в разные форматы

 , ,


0

2

Привет, ЛОР.

В прошлой теме я делился своим огорчением о том, как реализован список форматов в QTextDocumentWriter (напомню, что имена форматов – это такая отдельная сущность, не расширения, и не MIME-типы). В частности, прозвучало предложение @Saakx вынести сопоставление в отдельный конфиг. Сама по себе идея хорошая, но некоторые соображения сводят её полезность к нулю.

Первое. Пользователь всё равно свой формат не сможет добавить, они захардкожены в QTextDocumentWriter, это даже не плагины. Смогут добавить либо разработчики Qt, либо те, кто её патчат. Соответственно, и в мой код тоже можно патчик на одну строку внести, я постарался сделать это место как можно более прозрачным.

Второе. За обозримое время существования QTextDocumentWriter список форматов практически не поменялся. Только markdown добавился.

Третье и самое интересное. С точки зрения содержимого QTextDocument, которое создаётся в программе, нельзя просто так взять и заменить один формат на другой (картинку с Боромиром дорисуйте сами). Особенно в том, что касается таблиц. К примеру, в plaintext таблицы с более чем одним столбцом выдаются просто как мешанина из строк (как я понял, одна ячейка – одна строка, и пофиг, сколько там было столбцов и строк в таблице).

Программисты, заставшие DOS, конечно, умеют и в plaintext таблицы форматировать, но разработчики Qt то ли не овладели древней магией, то ли просто не захотели заморачиваться (такое форматирование и впрямь создаёт разные противные ограничения, самое безобидное из которых – привязка к фиксированной максимальной ширине документа в символах). Поэтому если создаваемый отчёт завязан на таблицы – plaintext надо либо исключать из списка поддерживаемых форматов, либо делать для TXT собственную реализацию, не завязанную на QTextDocumentWriter.

Не столь фатальный, но противный нюанс представляет собой отличие HTML от ODF. Ширину столбцов можно задавать либо в пикселях, либо в процентах от общей ширины таблицы. Так вот, в HTML уродливо выглядит первый вариант, в ODF – второй. Не перепутайте. Для себя я сделал вывод, что при создании документа сначала надо запросить у пользователя выбор формата, а потом уже заполнять QTextDocument, в нужных местах оглядываясь на формат. В исходнике я эту подстройку пока не сделал, но планирую.

★★★★★

Последнее исправление: hobbit (всего исправлений: 4)

Так тебе для отчётов? Не покупай, возьми с улицы пиши, возьми готовый! Например, https://github.com/fralx/limereport

Не помню, правда, какие форматы на выходе.. сами мы в конторе используем более древнюю поделку - cutereport, а это то ли форк, то ли клон, кароч, очень похоже )

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

У меня отчёты довольно специфичные. Ну и в любом случае мне для отчётов, кому-то – для чего-то ещё. Про cutereport знаю.

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

Раскрою мысль немножко подробнее.

У подключения сторонних библиотек всегда есть и плюсы, и минусы. И принимать решения всегда надо по целесообразности, взвесив их.

Самый очевидный плюс – сокращение времени разработки. Ну и избыточность готовых решений увеличивает вероятность того, что потом не придётся допиливать ещё и библиотеки.

Минусы. Та самая избыточность, это ещё и избыточность кода. Далее, стороннюю библиотеку надо либо включать к себе, либо делать ссылку на сторонний репозиторий (submodule или ещё как-то). Разные версии Qt, ещё надо следить, как они сочетаются с разными версиями сторонней библиотеки. Это ещё одна точка отказа даже не столько для меня, сколько для мейнтейнера, который, возможно, будет это собирать под условную федору или альт.

Я представляю, что такое типичный генератор отчётов. Это дополнительная прослойка над БД, иногда ещё с визуальным помощником. Плюс разные форматы представления и разные форматы вывода. Довольно жирная штука.

С другой стороны, кутешные классы QText* – это, по сути и есть низкоуровневая часть библиотеки генерации отчётов (без прослойки), которые всю самую дурную часть работы берут на себя. Некоторые нестыковки, о которых я написал выше, огорчают, но всё это решаемо. Разница в сокращении работы между ними и готовым генератором отчётов для меня, боюсь, ну уж очень незначительна.

И для работы, где эти отчёты придётся клепать под сотню или даже больше, а квалификация у разработчиков разная – я первый посоветую взять тот же cutereport или его форк. Но у меня в текущем проекте отчётов будет не так много, и аккуратное низкоуровневое решение здесь для меня самое то. Напишу несколько функций-хелперов (часть уже написана), делов-то.

P.S. Вот для работы с zip-ами я взял готовую QuaZip. Там это действительно имело смысл.

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

Я представляю, что такое типичный генератор отчётов. Это дополнительная прослойка над БД

Вовсе не обязательно. Это просто еще одна вьюха к модели. Откуда уж эта модель появилась - дело десятое. В том нашем решении с cutereport, о котором я вскользь упомянул выше, вообще субд нет, например.

За свою карьеру я пробовал разное - писать всё самому, чтобы полностью владеть кодовой базой и ни от кого не зависеть; по максимуму «спихивать головняк» на сторону, применяя сторонние решения и составляя продукт как из кубиков с минимальным дописыванием кода…

Скажу прямо: то не удобно и это не удобно, утомительно и т.д… По разным причинам.

Тут только можно выбрать линию и ей следовать.

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

Это просто еще одна вьюха к модели. Откуда уж эта модель появилась - дело десятое. В том нашем решении с cutereport, о котором я вскользь упомянул выше, вообще субд нет, например.

Ну хорошо, раз так. Я не зарекаюсь.

Тут только можно выбрать линию и ей следовать.

Одна линия не всегда оптимальна для всех случаев. Как я уже написал, для работы с архивами я счёл целесообразной отдельную библиотеку (*), а для формирования файловых документов – использование стандартных кутешных классов плюс самый минимум своего кода сверху.


(*) С архивами, точнее, даже гибридное решение получилось. Зипы мне нужны не сами по себе, а для чтения таких файлов как ODS и XLSX. Для них тоже отдельные библиотеки есть, но всё великолепие этих форматов с форматированием и проч. (и соответственно, код парсинга этого самого форматирования и проч.) мне нафиг не упёрлось. Там внутри зипов обычные XMLки, и мне из них нужен только текст нескольких ячеек, которые я добываю обычным QDomDocument (а XMLки перед этим добываю из исходного файла QuaZip-ом).

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

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

Поэтому если создаваемый отчёт завязан на таблицы – plaintext надо либо исключать из списка поддерживаемых форматов, либо делать для TXT собственную реализацию, не завязанную на QTextDocumentWriter.

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

А завязываться только на классы Qt – сужать себе возможность манёвра.

anonymous
()

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

Ещё одна новость – QTextDocumentWriter при записи действительно умеет определять формат по суффиксу (непосредственно внутри write()) и вызывать соответствующий класс. Вот только результат этого определения он нигде не хранит, и вызов QTextDocumentWriter::format() возвращает пустую строку. То есть польза от этого метода вообще сомнительна, он возвращает непустой результат только если до этого формат задавался принудительно через QTextDocumentWriter::setFormat(). Ну и из исходника QTextDocumentWriter, ссылка на который в предыдущей теме выкладывалась, хорошо видно, как это происходит.

Я, мягко говоря, разочарован. Мне мало того, что суффиксы надо хранить в программе, но ещё и по суффиксу определять реальный тип самому при необходимости (см. выше про разницу ODF и HTML).

Жалею, что не начал копать эти классы 10 лет назад. Тогда был бы хороший шанс послать им патч с высоким шансом принятия.

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

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

Вот поддержку разных СУБД действительно стоит делать через плагины. Хотя бы для того, чтобы программа могла работать как в локальном, так и в клиент-серверном исполнение.

hobbit ★★★★★
() автор топика

Ненужная шляпа. Формат делать не так просто, как кажется, если это конечно не сериализация/десериализация в лоб. В хорошем формате надо думать над структурой файла, чтоб читать её эффективно. Да и писать всё под сишные апи тоже плохая идея, у нас есть и джава которая не хочет лишних привязок к сишке и много чего ещё скриптового. Вот было бы что-то по описанию формата, по типу XSD для xml, которое для произвольного формата и по которому биндинги автоматом делались бы под любой ЯП, то было бы кайфово, но без сильного ИИ это невозможно.

ЗЫ

Если кому-то надо делать сложные текстовые форматы для отображения, берите веб морду (можно встроенную, если формат не шибко замороченный, если шибко то лучше чисто веб или электрон) и делайте конвертилку для вашего формата в html.

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

А вот с архивами беда - просто работать только с zip, но на самом деле формат жутко устаревший. По идее надо 7z брать с lzma2 (иногда в non solid виде чтоб произвольный файл быстро подгружать), но там по софту беда, старый дедушка что его поддерживает и разрабатывает в одно рыло явно слишком нагружен, работой в МГУ, хотя sdk сишное есть. А никто из корпорастов не подтянулся (кому российский софт нужен то, кроме авторов). Вот и выходит что тянутся сопли с форматами архивов которым 37 годиков (zip).

peregrine ★★★★★
()

только дополнительно искать cups/pdftk для экспорта в pdf, через dlopen? это что-бы без допов.
Как Сами увидели - это весьма костыльно, без плагинов и dlopen, и понимания метаструктур для них.
fb2 и epub, но это немного не то.

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

Я не вижу в данном случае проблем с zip. Проблемы, возможно, было бы, если бы мне нужно было туда что-то писать, причём с произвольными именами файлов. Но речь про XLSX и ODS, у которых zip стандартизирован, а внутри файлы с фиксированными латинскими именами. То же у меня было в DoubleContact, где среди прочих я читаю файлы NBF (один из старых нокиевских форматов, там vCard и доп.информация инкапсулированы в zip).

hobbit ★★★★★
() автор топика
  • Markdown
Пустая строка (два раза Enter) начинает новый абзац. Знак '>' в начале абзаца выделяет абзац курсивом цитирования.
Внимание: прочитайте описание разметки Markdown.
Используйте Ctrl-Enter для размещения комментария