Портирование приложений с qt2.3 на qt4.6
Я недавно столкнулся с задачей портирования gui-приложений с qt2.3.10 на qt4.6.
qt2.3.10 у нас использовался в b4. а qt4.6 используется в b5. Ну… если быть совсем честным,
то в b5 используется qt4.5, но при отладке на десктопе мы используем qt4.6.
поэтому портировал я именно на qt4.6.
При портировании я опирался на родной гайд qt4.6
Ну… если быть совсем честным, то к этой документации я «пришёл» после двух вручную спортированных приложений ;) Когда упёрся в приложение с ui-файлом старой версии.
Исходные приложения используют только «стандартные» элементы управления (кнопки, поля ввода, выпадающие списки), Layout’ы и .ui — формы. Никакой экзотики, вроде custom drawn виджетов и т.п.
Тролли описывают переход от qt3 к qt4 в своей доке, но мне удалось переехать и от qt2.3 к qt4 без проблем.
Вот как выглядит процедура. Сначала натравливаем утилиту qt3to4 на файл проекта (.pro-шник, то есть). Всё работает чётко и быстро: все старые qt-шные классы переименовываются в соответствующие с приставкой Q3 и правятся имена подключаемых хедеров. Но на этом не всё: программа ещё лезет в .pro-файл и устанавливает там QMAKE_UIC=uic3. Эта строка лишняя, если
портировать и ui-файл тоже, потому что в этом случае утилита uic3 предназначена для работы со старыми ui-файлами.
Да. Программа создаёт log-файл, в котором протоколирует все изменения, сделанные в исходниках проекта. И программе можно подсунуть конфигурационный файл, который будет выполнять те замены, которые будут указаны. То есть замену QMAKE_UIC можно отключить.
Дальше конвертируем старые ui-файлы в новые командой uic3 -convert. Все работает быстро и чётко. Но на этом автоматика заканчивается ;) Дальше — ручками и/или regexp’ами.
Из старых ui-ков генерировался хедер, в котором объявлялось готовое окно. Нужно было только от
него унаследоваться. В qt4 из новых ui-ков генерируется класс-контейнер и он не является окном.
Соответственно, в коде нужно это учесть: унаследоваться от окна и автогенерированного хедера (причём в строго такой последовательности, так требует moc). Другой вариант — сделать переменную
в окне типа автогенерированного класса. И вызвать в конструкторе setupUi( this ).
Я выбрал второй вариант. А если быть честным, то пока писал статью, нашёл информацию о том, что порядок наследования строго определён. А когда я экспериментировал, сделал включение в другом порядке, и пришлось отказаться от этого метода. Поторопился я… :(
Ещё я заметил, что конвертор uic3 в редких случаях меняет разметку. И некоторые элементы
управления, к которым производилось обращение из кода, перестают существовать.
В моём случае конвертор из набора BoxLayout’ов сгенерил QGridLayout.
Также из автоматизма выбился такой момент: раньше существовал конструктор с указанием
имени окошка: QWidget( parent, title, flags ). Теперь этот конструктор принимает только parent & flags.
Для установки title требуется вызов setWIndowTitle. Но это, конечно, мелочи.
В итоге: имеется два спортированных приложения с десятью GUI-шными плагинами.
На первый взгляд — работают. Детальное тестирование будет на следующей неделе. Заняло это примерно 3 дня плотной работы.
Таким образом, команде Trolltech — зачёт. За то, что не пришлось переписывать код,
а воспользоваться старыми объектами, оставленными для совместимости. За то, что удалось сэкономить кучу труда на составление списка замен и на переделывание старых форм в новые.
PS: пока писал заметку, я «нашёл» и porting guide from qt2 to qt3. Но какой в нём теперь смысл… ;)