Портируем код с Qt 1.0 на Qt 5.11

http://blog.qt.io/blog/2018/05/24/porting-from-qt-1-0/
  • Перевод
Недавно вышел Qt 5.11 и мне подумалось, что сейчас самое время обновить до него кое-какие мои проектики на Qt 1.0… Ладно, шучу :) На самом деле мне стало интересно, насколько хорошо за все эти годы развития фреймворка Qt нам удавалось сохранять обратную совместимость кода.

Qt гарантирует совместимость на уровне кода и бинарников при обновлении между минорными версиями фреймворка (и мы серьёзно относимся к этому обещанию). Вы не должны переписывать (или даже перекомпилировать) свой код при переходе на другую минорную версию Qt. Однако переходы между мажорными версиями требовали от нас идти на некоторые жертвы ради прогресса. С релиза Qt 1.0 в 1996 году мы ломали совместимость кода четыре раза: в версиях 2.0, 3.0, 4.0 (ох, это было болезненно!) и 5.0.

Мы старались даже в мажорных версиях сломать как можно меньше всего, но всё же это приходилось делать. Отсюда возникает вопрос: насколько сложно портировать приложение, написанное во времена Qt 1.0 до современного Qt 5.11?

Для ответа на этот вопрос я взял пример кода, который поставлялся с документацией на Qt 1.0 и постарался собрать его с помощью Qt 5. Наши публичные архивы содержат изменения начиная с версии 1.41, так что мне пришлось изрядно покопаться в дрейнейшей истории, пройти через логи четырёх разных систем контроля версий… но это я уже отвлекаюсь. Проект, который я планирую собрать, называется «t14» — поскольку это иллюстрация к 14-ой (и последней) главе оригинального руководства.

И вот, что мне пришлось проделать для его сборки.

Импортируем оригинальный проект: 10 files changed, 798 insertions(+)
Чистое произведение искусства: так в 1996-ом году официально рекомендовалось писать программы на Qt.

Переходим на qmake: 3 files changed, 2 insertions(+), 148 deletions(-)

image

До выхода qmake был tmake. Он был написан на Perl. Базовый синтаксис был похож, только tmake ещё позволял включать прямо в файл проекта код на Perl, чего (к счастью!) уже нельзя сделать в qmake. Кроме того, tmake не был публично описанной частью фреймворка, так что для релизов мы готовили make-файлы. Наличие совершенно разных внутренней и внешней системы сборки кода всегда добавляло в релизы элемент неожиданности.

Исправляем include-файлы: 4 files changed, 8 insertions(+), 8 deletions(-)

image

В те древние времена, когда писался данный пример, операционная система Windows ограничивала длину имени файла до 8 символов. Мы, конечно, могли ориентироваться на Unix и сделать нормальные имена, но, если код должен был быть портируемым — приходилось использовать «восхитительные» названия файлов типа «qscrbar.h» и «qbttngrp.h».

Добавляем отсутствующие include-файлы: 1 file changed, 3 insertions(+)
Зависимости от неявных инклюдов были и остаются проблемой.

Меняем TRUE/FALSE на true/false: 1 file changed, 13 insertions(+), 13 deletions(-)

image

Ох уж эти сегодняшние дети. Счастья своего не осознают! Мы были вынуждены писать свой собственный булевый тип данных, поскольку встроенного в язык у нас не было!

Исправляем ссылки на сущности, которые переехали в пространство имён «Qt»: 3 files changed, 15 insertions(+), 15 deletions(-)

image

«Qt» было добавлено в 1998 году и являлось тогда… классом. Да, классом, поскольку у нас тогда не было пространств имён.

Убираем аргумент «name»: 6 files changed, 26 insertions(+), 26 deletions(-)

image

Все конструкторы подклассов QObject принимали параметром имя объекта.

API класса QScrollBar изменился: 1 file changed, 5 insertions(+), 5 deletions(-)

image

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

Используем QString вместо const char*: 2 files changed, 2 insertions(+), 2 deletions(-)

image

QString существует в Qt с 1994 года. Раньше это была 8-битная строка в кодировке Latin1 с автоматическим преобразованием к const char*, так что кое-где API использовало аргументы типа const char*. Поддержка Unicode появилась в Qt 2.0.

warning() теперь называется qWarning(): 1 file changed, 1 insertion(+), 1 deletion(-)
Мы вообще-то избегаем добавлять сущности в глобальное пространство имён. Ну, разве что, если они начинаются на «Q». Эта буква принадлежит нам.

Убираем ненужные вызовы старых методов QApplication: 1 file changed, 2 deletions(-)

image

Qt сегодня многое делает сам, хорошо и автоматически. А в 1996 году многие дисплеи могли отображать лишь 8 бит на пиксель, так что для показа более 256 цветов нужно было ещё постараться.

Заменяем QAccel на QShortcut: 1 file changed, 4 insertions(+), 3 deletions(-)

image

QShortcut — одновременно мощнее и проще. А ещё его название — не аббревиатура. QShortcut был добавлено в 2004 году.

Исправляем логику перерисовки: 1 file changed, 7 insertions(+), 7 deletions(-)

image

В 90-ые мы могли прямо рисовать на виджетах, когда захотим. Сегодня у нас есть буферизация и композиция, так что всё становится и сложнее, и проще одновременно. Мы отправляем запрос на изменение и позже, когда получим сигнал на перерисовку, рисуем. Чуть больше кода, но намного логичнее.

QObject::killTimers() больше не существует: 2 files changed, 3 insertions(+), 2 deletions(-)

image

Эта функция была слишком опасной. Она убивала все таймеры объекта, включая и использовавшиеся внутри Qt. Сегодня вы должны убивать таймеры осознанно и индивидуально.

QWMatrix теперь называется QMatrix: 1 file changed, 2 insertions(+), 2 deletions(-)
Просто изменение названия класса.

Метод QWidget::setBackgroundColor() был удалён: 1 file changed, 3 insertions(+), 1 deletion(-)

image

Цвет фона виджета — уже не столь простая сущность: он инкапсулирован внутри QPalette вместе с другими свойствами. Кроме того, дочерние виджеты теперь по-умолчанию прозрачны. Мы должны рассказать Qt, как именно хотим рисовать фон.

Не получается заполнить pixmap содержимым виджета: 1 file changed, 1 insertion(+), 1 deletion(-)

image

Я использовал для этого прозрачный pixmap, поскольку теперь Qt их поддерживает.

Рисование прямоугольников изменилось: 1 file changed, 1 insertion(+), 1 deletion(-)

image

Это, наверное, наиболее кардинальное изменение из всех вышеописанных. Начиная с Qt 4.0 метод QPainter::drawRect() был изменён таким образом, чтобы «штриховочный прямоугольник имел размер rectangle.size() + ширина пера». Таким образом, нам необходимо вычесть ширину пера (в нашем случае это 1) перед передачей прямоугольника в QPainter.

Теперь у нас есть полнофункциональный порт примера из оригинального обучающего материала, вот скриншот:

image

Ой… Кое-где текст выглядит обрезанным. Выяснилось, что это произошло из-за жестко прописанных в коде размеров и позиций елементов, а размеры шрифтов, оказывается, поменялись с 1996 года. Решением будет использование QLayout, который не был доступен во времена Qt 1.0 (первая версия появилась в Qt 1.1. и была полностью переписана к выходу Qt 2.0).

Используем QLayout вместо жестко прописанных размеров: 4 files changed, 29 insertions(+), 24 deletions(-)

image

И вот с этим, последним, изменением всё, наконец, выглядит так, как и должно:

image

В чём же мораль этой истории? У нас получилось (и даже не заняло много времени) портировать код 22-летней давности с Qt 1.0 на Qt 5.11. Это возможно. У меня, наверное, больше времени заняло написание данной статьи, чем правки самого кода. Большинство API всё ещё живы в последних версиях Qt даже спустя столько лет и версий. Некоторые из них остались неизменными, другие были расширены и доработаны, но всё же сохранили узнаваемость. Все изменения были направлены на улучшения читабельности, безопасности, поддерживаемости и производительности приложений на Qt.
Инфопульс Украина 178,01
Creating Value, Delivering Excellence
Поделиться публикацией
Похожие публикации
Комментарии 40
  • 0
    Спасибо за статью. У меня валяется дипломный проект на Qt4, вот думаю когда-нибудь его перетащить на Qt5. Мне, наверно, переходить будет проще, не такой большой разрыв
    • +1
      Полгода назад переводил огромный проект с Qt4 на Qt5, поменялись по большому счету только некоторые заголовки, и некоторые минорные вещи в API, в целом за пару дней работа была закончена.
      • 0
        Подтверждаю, тоже портировали с Qt 4.8 на тогда еще Qt 5.3 большой проект (~0.5 млн строк + библиотеки) — заняло пару дней. Исправления были минимальные, ничего не переписывали.
      • 0
        Qt3->Qt4 реально весьма болезненно. Поэтому мы до сих пор на qt3. В качестве подготовки перехода сейчас выкидываю Qt и переписываю всё что можно на std::c++ и boost (кроме графического интерфейса).

        Самая большое преступление разработчиков Qt — игнорирование такой полезной возможности С++, как пространство имён. Если бы они его использовали, то можно было бы, по крайней мере на время переходного периода, линковать обе библиотеки…
        • +3

          Qt можно с пространством имен скомпилировать

          • 0
            Это удивительно, ведь сделали же, но всё равно по умолчанию это отключено и во всех дистрибутивах собрано без пространства имён.
            • +1

              Так это давно уже есть и нужно чтобы подобные ситуации разруливать

              • 0
                Это появилось начиная с Qt 4.4 и для использования требует перекомпиляции. Поэтому при переходе с qt5 на qt6 это можно будет использовать, просто пересобрав qt5 с этой опцией и завернув старый код в пространство имён. Но у qt3 нет такой возможности. Соответственно, для того чтобы это использовать, придётся заворачивать новый код в пространство имён и всегда пересобирать вручную qt5.
          • +3
            Не на всех платформах есть такое счастье, поэтому по умолчанию и отключено.

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

            А вот boost — уже для куда более подготовленных плюсовиков. И, к сожалению, не всегда такие есть под рукой.
            • 0
              В том и дело, что старый код написанный на старом добром C++ собирается без проблем, а код написанный с использованием Qt вызывает много проблем из-за несовместимости Qt с самим собой и просто непродуманности. В итоге «простота» обернулась непредвиденными проблемами.
              Чего стоит только одна небезопасная реализация QString для потоков в qt3! Я просто вынужден выкидывать QString везде, где используются потоки и заменять на std::string.
              Если бы в своё время мы ограничились бы использованием Qt только для графического интерфейса, то переход q3->q5 был бы значительно дешевле.

              При этом, вместо того чтобы просто выкинуть QString в qt5, его продолжают тянуть в новые версии.
              • 0

                Вообще QString лучше с юникодом дружит и в целом удобнее для разработчика

                • 0
                  UTF-16 — худший выбор. Для работы со строками достаточно удобен utf-8, для работы с отдельными символами лучше использовать utf-32. Поэтому не соглашусь.
                • 0
                  Вопрос не только в собирается / не собирается, а в поддержке кода. Старый код на старом добром C++ (а чаще — на C с классами) может и собирается, но разобраться в нем зачастую боль и страдание.

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

                  Что значит эта фраза? QString реализует принцип CoW (Copy-On-Write), что, в общем-то, является одной из киллер-фич фреймворка, и позволяет практически безболезненно быстро гонять данные между потоками.

                  При этом, вместо того чтобы просто выкинуть QString в qt5, его продолжают тянуть в новые версии.

                  Кхм… у меня есть подозрения, что вы все-таки не очень разобрались с фреймворком. QString хранит внутри себя Unicode символы, а std::string — байты. В итоге QString знает, сколько хранит внутри себя символов, умеет гонять данные между разными кодировками, а также имеет удобное API, а std::string — не знает и не умеет. В итоге тот же lenght на UTF-8 данных вернет не количество символов, а размер в байтах.
                  Вообще, std::string корректнее сравнивать с QByteArray.
                  • 0
                    QString::size() возвращает не количество символов, а кол-во QChar в строке. Unicode-символы с кодом больше 65535 кодируются при помощи суррогатных пар с использованием двух QChar.
                    Вообще, UTF-16 это худшая из кодировок, если сравнивать с UTF-8 и UTF-32. Полагаю, что Qt её выбрали с оглядкой на Windows. В юниксах в то время, до всеобщего принятия UTF-8, был полный зоопарк. Теперь приходится тащить на себе бремя обратной совместимости.
                    • 0
                      Верное замечание, спасибо. Тем не менее, такой результат — это более логичное поведение для строки.

                      Насчет UTF-16 — да, думаю, из-за винды. UTF-32 в винде почти нигде не используется, поэтому неудивительно, что выбрали средний вариант.
                      • 0
                        Тем не менее, такой результат — это более логичное поведение для строки.

                        Логичное поведение для строки — возвращать количество символов, а не размер массива. Если же такое поведение устраивает, то с таким же успехом можно использовать std::wstring.
                        • 0
                          Еще раз: возвращается количество объектов QChar. В кодировке UTF-16 при значения больше 65535 используется 2 объекта QChar (ну потому что стандарт так говорит). Вполне логично, что на запрос размера мне возвращается количество QChar.

                          std::wstring

                          Ага, только wchar_t в винде занимает 2 байта, а в никсах — 4 байта. Со всеми вытекающими проблемами отсюда.
                          • 0
                            Ага, только wchar_t в винде занимает 2 байта, а в никсах — 4 байта. Со всеми вытекающими проблемами отсюда.

                            Есть std::u16string. Но главное — есть нормальные полноценные библиотеки типа ICU.
                    • 0
                      только одна небезопасная реализация QString для потоков в qt3


                      Что значит эта фраза? QString реализует принцип CoW (Copy-On-Write), что, в общем-то, является одной из киллер-фич фреймворка, и позволяет практически безболезненно быстро гонять данные между потоками.

                      Вы неправы теоретически и фактически.

                      Теоретически CoW наоборот усложняет и затрудняет обмен данными между потоками, потому что требует использование блокировки в момент изменения объекта. Без использования CoW, мы получаем независимую копию объекта, что делает блокировку излишней, а код реализации объекта — проще. С приходом же C+11 и его концепцией перемещений, CoW становится излишним в большинстве случаев.

                      Практически в qt5 реализация QString вынуждена использовать блокировки, чтобы позволить использовать строки в потоках. Но в qt3, о чём и шла речь, и что Вы аккуратно обрезали при цитировании (случайно, я надеюсь), всё очень и очень плохо — там используется cow и не используются блокировки. В результате, при попытке использование строки в потоке, будут происходить непредсказуемые обрушения программы в произвольном месте.
                      QString хранит внутри себя Unicode символы, а std::string — байты.

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

                      Если же есть необходимость работать с отдельными символами юникода, то для этого существуют полноценные библиотеки и прочие boost::locale. Почему в 2018 это до сих пор это не часть стандарта (или уже?) — вопрос к комитету.

                      Вообще, отступая от темы, Qt исторически был вынужден изобретать велосипеды для каких-то ограниченных платформ и не всегда у него это выходило идеально, хотя для своего времени это было неплохо. На сегодня ситуация сильно изменилась и многие из этих изобретений уже не нужны и надеюсь в следующей версии qt будут существенные изменения в эту сторону.
                      • +1
                        Практически в qt5 реализация QString вынуждена использовать блокировки

                        Все-таки внутри QString (да и вообще всех классов Qt, использующих implicit sharing) используются атомарные счетчики, а не стандартные блокирующие примитивы. Как только мы копируем объект, счетчик ссылок увеличивается на один, и мы получаем легкую копию (shallow copy). Если мы хотим изменить объект, вызывается detach и мы получаем глубокую копию (deep copy).

                        Так вот, если мы делаем копию строку в другом потоке, сначала получаем shallow копию, увеличиваем счетчик и работаем с shared данными. Как только мы начинаем изменять объект, мы получаем отвязанную локальную копию нашей строки, которая уже не ссылается на данные в других потоках. Ее изменение происходит локально, ничего нигде не сломается.

                        Совсем другое дело, если наша строка являются общей для разных поток, и они ее пытаются изменить. Да, тут нужны традиционные блокировки аля mutex, но это ровно также нужно и со всеми другими типами данных (то есть, аналогично нам нужно было бы сделать и с std::string). QString является реентерабельной функцией, не потокобезопасной.

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

                        С чем я соглашусь:
                        1) Действительно, с приходом move-семантики implicit sharing уже не выглядит так вкусно. Единственным аргументом в использовании implicit sharing сейчас является разве что его хорошая производительность из коробки, тогда как про move-семантику нужно всегда помнить и писать код соответствующе (к сожалению, до сих пор многие этим пренебрегают).
                        2) Действительно, я проверил, в qt3 не было атомарных операций при implicit sharing, что ломало счетчик в разных потоках. Только с Qt4 все стало нормально.
                        Но я не очень понял, как так получилось, что раньше так код работал, а потом, когда стало все нормально — перестал.

                        На самом деле обе реализации хранят внутри себя байты

                        Естественно. Только QString имеет представление о том, что она хранит, а std::string — нет.

                        Если же есть необходимость работать с отдельными символами юникода

                        Перегнать что-то из одной кодировки в другую — на самом деле, не такая уж и редкая проблема. Да, в мире, где казалось бы, уже везде используется UTF-8, все равно встречаются системы с какой-нибудь KOI8-R, и никто ничего переделывать не будет. Вот Qt позволяет такие вопросы решать из коробки очевидными способами.
                        А вот почему этого всего нет в стандарте — вопрос действительно хороший.

                        Вообще, отступая от темы, Qt исторически был вынужден изобретать велосипеды для каких-то ограниченных платформ

                        В первую очередь — из-за ограничений языка. Сейчас-то и moc уже не нужен, есть реализация от авторов оригинального moc'a чисто на шаблонной магии и новых стандартах. Я тоже надеюсь, что велосипеды будут потихоньку заменяться на стандарт, а новые фичи будут упрощать код. Но все же даже сегодня писать на Qt очень приятно и производительно.

                        • 0
                          Все-таки внутри QString (да и вообще всех классов Qt, использующих implicit sharing) используются атомарные счетчики, а не стандартные блокирующие примитивы.

                          Атомарные операции не бесплатны, хотя и дешевле мьютексов. Конечно, то что в Qt это сделали — большой плюс qt5 по сравнению с qt3, где использование QString с потоками было связано со всяческими опасностями. Но, как по мне, лучше бы перешли на стандартную строку.

                          Естественно. Только QString имеет представление о том, что она хранит, а std::string — нет.

                          На сколько я знаю, QString не умеет нормально работать с комбинированными символами, состоящими из двух двухбайтовых слов. Точно также, как и std::u16string или std::string с многобайтовыми символами. Для этого нужны специализированные библиотеки. То есть никакого преимущества здесь я не вижу.
                          Сейчас-то и moc уже не нужен, есть реализация от авторов оригинального moc'a чисто на шаблонной магии и новых стандартах.

                          Да. И это и многое многое другое. Регулярки, потоки и т.д.
                          • 0
                            большой плюс qt5 по сравнению с qt3

                            Еще в Qt4 это сделали. И надо сказать, что Qt4 появился аж в 2005 году, 13 лет назад. А это времена, когда никаких умных указателей и потоков в GCC не было, не говоря уж про msvc.
                            Qt3 — это 2001 год. К слову, первый интелловский двухядерный процессор Pentium D и амдешный Opteron появились только в 2005. И я не уверен, что там была отличная аппаратная поддержка атомарных операций (во всяком случае, компиляторы точно не умели правильно генерировать код). В тоже время, Qt3 имеет поддержку потоков (треды, мьютексы, conditional variable и прочее). И мне кажется, вы слишком много просите для того времени.

                            Но, как по мне, лучше бы перешли на стандартную строку.

                            Конечно, нет. Строки в стандарте — это ужас. Вернее, как мы уже обсудили выше, строк как таковых в стандарте нет вообще.

                            На сколько я знаю, QString не умеет нормально работать с комбинированными символами, состоящими из двух двухбайтовых слов

                            QString::fromWCharArray

                            Регулярки, потоки и т.д.

                            Опять же, Qt давно имеет эти классы, на них уже написано много кода, они хорошо, логично и удобно реализованы. Зачем ломать удобные классы, только лишь потому, что в стандарте недавно появилось аналогичное?
                            Я за то, чтобы заменить заведомо костыльные вещи на что-то новое и удобное. moc — замечательный костыль своего времени, но сейчас его можно реализовать элегантнее, не сломав старый код. Слоты в Qt5, благодаря лямбдам, стали намного удобнее и красивее. Вот я за такие изменения.

                            Кстати, на Qt чаще ругаются не когда они вводят что-то новое (за это наоборот все радуются), а когда они что-то удаляют. Как было, например, с перехода QtWebKit на QtWebEngine. Вот тут у людей были болезненные переходы.

                            И еще есть момент. Qt очень часто голым используется в embedded устройствах, прям минуя STL. Если памяти довольно мало, то практически всегда выгоднее тащить с собой QtCore с огромным функционалом из коробки, вместо довольно голого STL.
                            • 0
                              мне кажется, вы слишком много просите для того времени.

                              Простите, где?

                              Конечно, нет. Строки в стандарте — это ужас. Вернее, как мы уже обсудили выше, строк как таковых в стандарте нет вообще.

                              Они не особо хуже QString, как мы уже вроде бы обсудили выше. Точно так же нет поддержки комбинированных символов из коробки.

                              QString::fromWCharArray

                              ?

                              Зачем ломать удобные классы, только лишь потому, что в стандарте недавно появилось аналогичное?

                              Ну почему же сразу ломать? Конечно, какой-то уровень совместимости для работы старого кода следует оставить, но вечно таскать за собой ставшие ненужными костыли неправильно. Qt это хорошая библиотека для создания графических интерфейсов и пусть она останется таковой.
                              • 0
                                Они не особо хуже QString, как мы уже вроде бы обсудили выше. Точно так же нет поддержки комбинированных символов из коробки.


                                Вообще-то умеет

                                Другое дело, что Unicode итераторы нифига не документированы, но вот, скажем, пример
                                • 0
                                  О! Не знал. Интересно сравнение уровня поддержки юникода в Qt и ICU.
                                  • 0
                                    Qt может быть скомпилена с поддержкой ICU (вкл по дефолту), тогда какие-то вещи QString/QLocale и друзья делают через ICU. Какие конкретно — сказать не могу, не копал так глубоко.
                                    В общем случае, Qt не переизобретает велосипед, а умеет только какие-то базовыве вещи, т.е. ICU шире. Ну а фигли, там либа весит больше чем QtCore)
                                    • 0
                                      В контексте нашей беседы c oYASo выше, если бы Qt нужно было заново создавать сегодня, то ICU + std::basic_string из C++11 было бы вполне достаточно и QString был бы не нужен.
                                      Но в реальности разработчикам Qt придётся тащить QString ещё много лет.
                                      • 0
                                        Нет, вы не правы. Во-первых, врядли кто-либо разрешит засунуть ICU в стандартную библиотеку (как зависимость, а-ля pthreads). То есть можно сразу забыть о std::to_lower(«АБВ») и друзьях (привет, QString::number, QString::localeAwareCompare) — скажут дергайте ICU руками. Но это не оч удобно.
                                        Во-вторых, никто не торопится в стандарт добавить функции работы непосредственно со строками — нормальный replace, split/join. Да, возможно, в виде генерик алгоритмов они смотрелись бы лучше, но… Пока никто не написал proposal на это, а значит приходиться кушать что дают. Сюда же попадает localeAwareCompare, он сейчас юзает платформенные функции для (т.е. ICU не особо нужен), но о5 же, нет пропозала в стд для аналога.
                                        В третьих, кодеки для разных кодировок — std::u16string тупо массив short'ов без знания о том, Big-Endian, Little-Endian он или ещё какой.

                                        Вот было огромное обсуждение касательно QString/QStringView (utf16 vs utf8 там тоже затронули).
                                        В общем, сейчас политика партии такова — обоже никогда не юзайте QList, вместо QVector используйте std::vector, вместо QScopedPointer — std::unique_ptr, если это не касается публичного API. До сих пор нет решения касательно холивара «юзать ли std:: в публичном API». Из-за обещаний BC между версиями, нельзя юзать стандартные типы (вдруг stdlib поменяет BC), но слом BC в стандартной библиотеке всё равно ведёт к пересборке всего мира, так что, надеюсь, этот холивар разрешится в пользу std:: к 6й версии). Например, зарезали мою реализацию QOptional (aka std::experimental::optional) — юзай std, говорят. Аналогично не хотят добавлять move-семантику в QScopedPointer (зачем, если есть unique). А вот QString/QStringView/QByteArray — скорее исключения из правила юзать std.
                                        А так, QThread уже давно внутри юзает std::thread (только наворачивает эвентлуп поверх), атомики юзают std:: и только QString живёт и процветает потому что аналога в стандартной библиотеке всё ещё нет.
                                        • 0
                                          > Вот было огромное обсуждение касательно QString/QStringView (utf16 vs utf8 там тоже затронули).

                                          Спасибо, почитаю на досуге.

                                          > и только QString живёт и процветает потому что аналога в стандартной библиотеке всё ещё нет.

                                          Когда же что-то хотя бы уровня ICU появится в стандарте? (хотя ICU тоже заточен под utf-16, как я понял). Ведь уже 2018 год! Доживу ли?
                • +1
                  Года три назад переносил приложение с Qt3 на Qt5. Наибольшую сложность составили .ui файлы — их пришлось просто заново нарисовать в дизайнере, потом вручную код перенести. Благо, на CentOS 5 можно было установить из репозитория сразу Qt3 Designer и новый QtCreator.

                  Ещё немало изменений было в конструкторах, так же, как и у автора.

                  Одно из самых проблемных мест — цветовые схемы, как они применялись в дизайнере, серьёзно изменились.
                • +1
                  Получается, в распоряжении было 7 символов, т.к. первый почему-то обязательно должен быть «q» ))
                  • +1
                    Помню свою боль перехода с qt 4 и webkit на ранний qt 5 и вебенжину… Половины функций, что требовалось от вебкита в вебенжине не было, жуть.
                    • +2
                      Про совместимость бинарников в минорных версиях уже не актуально. Qt 5.4 последняя версия, которую можно собрать под XP, Qt 5.5 — последняя которую можно деплоить под XP. Может некстати подвести — обновился с 5.3 на 5.10, вроде ничего не предвещало несовместимости — получите, распишитесь.
                      • 0
                        Ну, странно было бы ожидать, что Qt будет вечно продолжать поддерживать ОС, которую уже и производитель этой ОС не поддерживает.
                      • 0
                        Qt гарантирует совместимость на уровне кода и бинарников при обновлении между минорными версиями фреймворка

                        Минорные — это 4.Х или, скажем, 4.3.Х
                        Потому как если первый вариант — ой, врут.
                        • 0
                          (пруфы)
                          1. сейчас держим две версии библиотек: 4.5 и 4.7, т.к. новые требует third-party либа, используемая нами, но при попытке стартовать только с 4.7 — софт улетает в неведомые области памяти. Дело тут скорее всего в особенностях компиляции разных версий.
                          2. С каждым изменением graphics pipeline начинается игра «что поменяли в работе с OGL на поверхностях Qt». Артефакты бывают весьма забавными и сложноловимыми.
                          • 0
                            С third-party конечно беда, как правило надо держать зоопарк версий Qt. Однако, справедливости ради, нужно отметить, что во многих случаях это не проблема Qt — многие разработчики в проектах вставляют целые куски кода (может модифицированного под себя) из т.н. «private implementations», благо код Qt открыт и свободен. Естественно там ломается любая совместимость. Но тут как повезет, например достаточно годная библиотека Qxt, канувшая в лету, не соберется уже никогда после Qt 5.3, но бинарники исправно работают на всех минорных версиях 5й ветки.
                        • 0

                          Недавно переносил приложение с qt3 на qt4. На qt5 перейти не получилось, там насколько я понял api изменилось сильно. Так что статья не оторвана от жизни :)

                          • 0
                            «Использование индивидуальных сеттеров — значительно лучшая практика, чем конструктор, принимающий 7 аргументов.» чуть более чем спорно. Про RAII вы скорее всего не слышали.
                            • 0
                              Проблема конструкторов, принимающих по 7 аргументов — в конструкторах вида
                              FooBar(int* a, int b=3, int c=2, int d = 1, int e =0, int f = 1, double g = 1)
                              RAII надо использовать там, где это приносит выгоду — во всех же остальных местах Named Parameter Idiom будет приводить к гораздо меньшему числу багов и более быстрому их поиску.

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

                            Самое читаемое