Как я перестал бояться и переизобрел QML
Привет, хабр, прошло очень много лет, с тех пор как я писал сюда. Надеюсь, время тебя/меня не слишком/слишком потрепало.
Я хотел бы написать о нашем опыте переосмысления идей QML. Qt — прекрасная (по совокупности заслуг) библиотека, и хотя её внутреннее устройство местами вызывает вопросы, но она дала миру не только кросс-платформенный UI тулкит, но и цельный профессиональный набор инструментов: Дизайнер, Креатор, Лингвист, и, конечно же, Qml. Результатом этого переосмысления стал наш скромный проект, который превращает qml в html5/javascript для разных платформ, и даже позволяет собирать простые android приложения используя Cordova.
Qml всегда привлекал нас (небольшую неизвестную группу QML-адвокатов, как мы себя называем, надев монокли и цилиндры) своей абсолютной выразительностью в плане разработки интерфейсов, и поэтому каждый из нас использует их для разработки пользовательских интерфейсов и сайтов.
Мы бы очень хотели, чтобы часть хабр-сообщества, открытая для всего нового, попробовала бы и оценила наши скромные возможности, мы получили фидбек, и смогли бы улучшить наш продукт.
Исходные коды доступны на github, там же лежат исходные коды сайта, примеров и библиотека контролов, которые мы используем для всех своих проектов. Документацию и уроки можно посмотреть на нашем сайте, pureqml.com
Одно из бесплатных приложений, которые мы сделали, был порт игры Fontanero, она должна быть доступна в маркетах LG/Samsung.
Ну, а дальше можно не читать!
Как мы дошли до жизни такой
Всё началось в уже-далеком 2010-ом году, когда мы начали писать встраиваемое ПО (и интерфейс пользователя) в одной крупной корпорации для линейки разношерстных устройств на всевозможных платформах, доступных сейчас: arm, mips, x86, sh4, не хватало только sparc… Основную проблему мы для себя сформулировали так: UI должен быть быстрым, дешевым и хорошим, и, чтобы не надо было выбирать только два пункта из этих трех. Ресурсов было очень мало (полтора программиста), поэтому хотелось, чтобы программирование UI было легким и приятным, а программисты не страдали, не плакали, и не убегали, а фокусировались на решении бизнес-задач, вместо ручного отслеживания координат. HTML отпал сразу же, отчасти потому, что самое первое устройство было на arm926xxx (armv5) и имело на борту 32Мб оперативной памяти, из которых только 23Мб было доступно для user-space приложений (а также armv5 имеет смешное ограничение на 2G виртуальных адресов для всех процессов в сумме, поправьте меня, если я ошибаюсь), что очень сильно сужает область для поисков.
После анализа существующих решений, наш выбор пал на относительно новый (тогда) язык и технологию — QML, что было совсем не удивительно, учитывая предыдущий позитивный опыт разработки с Qt. Исключительно простой и наглядный, мы сразу же решили, что это то, что нам нужно. Появившийся через неделю, искрящийся от модных анимаций, весьма функциональный прототип, еще пуще убедил нас в правильности выбора.
QML — (достаточно) прекрасен
Самое прекрасное в QML то, что он прячет от программиста всё, за исключением, собственно, UI. Надо просто брать замысел в руки, и выплескивать на холст!
Декларативный подход очень нагляден и прост в использовании. Переиспользование компонент интуитивное, и, для простых случаев, — очень лаконичное. Это позволило нам сделать полноценный UI (менюшки, приложения, настроечки, расписания и прочие штуки), буквально за пару месяцев, силами двух программистов.
На утаптывание Qt мы потратили немало времени, но оказалось, что даже кастомные сборки, без капли лишнего, никак не влезают ни в 8, ни в 16 Мб флеш-памяти. Грусти нашей не было предела, ведь мы уже жили в мире, где embedded-интерфейсы перестали быть унылыми и возмущались, вспоминая времена, когда не было Qt QML.
В тот вечер, мы с коллегой коротали вечер за бутылочкой Циндао в одном из отелей Шеньчженя (на 48-ом этаже!), думая о том, можно ли сделать QML, но на C++, и, заодно, проверить на прочность возможности той самой печальной платформы на arm926. Оказалось, что всё не так уж и плохо, и возможностей процессора хватает чтобы рисовать прозрачные красивые окошки даже софтверно, а ведь там был и аппаратный ускоритель 2d графики!
Засучив рукава и отбросив Циндао, мы начали яростно компилировать, и, уже через пару недель мы уже имели свой QML с C++ вместо javascript. Это был наш первый собственный QML, который мы полировали довольно долго, до победного конца.
Но C++ — это достаточно хардкорно, и это накладывает свои ограничения, например, вы не можете распространять приложения для разных платформ, нативный код очень долго компилируется, более требователен к мозгу программиста, и требует бóльших вложений. Поэтому, через пару лет, когда мы с (другим) коллегой коротали вечер за пирожками в одном из кофешопов Амстердама, то придумали, как вернуть javascript (в лице v8) в нативный код.
Эта предыстория может быть не очень интересна, ведь те два QML остались в прошлом, вместе с той самой корпорацией, где они родились. Они так и не предстали перед широкой публикой в качестве средства разработки, но UI, построенный на этой технологии, повседневно использует порядка шести миллионов человек.
Наши дни (полтора года назад)
После ухода из этой большой и страшной корпорации, нам захотелось также быстро и просто разрабатывать интерфейсы, и заодно появилась необходимость написать большое и сложное приложение для SmartTV, сразу на 5 (!) платформ. Android для телевизоров тогда еще не вышел, и все SmartTV тогда (как и большинство сейчас) предлагали SDK на базе HTML, продвигая свои фреймворки и либы для облегчения жизни программистов (например, caph от samsung), но это скорее усложняет процесс, так как реализацию одного UI нужно было переписывать под фреймворк каждого конкретного производителя. Мотивация их (производителей) телевизоров к использованию web-технологий понятна, но реализация становится весьма болезненной по мере увеличения сложности приложения. Имея за плечами пятилетний опыт писания собственных QML движков, мы решили сделать еще один собственный QML (нужно больше велосипедов!), но уже для SmartTV в частности, и для HTML в общем.
Так и зародился наш скромный проект.
Основной инстинкт принцип
Всё устроено почти как в qml, все компоненты описываются в .qml файлах, в .manifest описывается структура приложения. Дальше в дело вступает транслятор/транспайлер (?) QML в html5/javascript: генерируются и подключаются сигналы, обновляторы, прототипы и конструкторы. После трансляции получается компактный и быстрый javascript-файл, вместе с html-запускателем, требующий только Modernizr.
Отличительной особенностью является то, что мы написали QML на QML, все core компоненты написаны на qml и javascript, используя наш тулчейн, сам транспайлер всего лишь раскладывает файлы по пространствам имен и генерирует то, что обычно пишут руками.
Трудности перевода и велосипеды
QML диалект, который мы используем, очень похож на оригинальный QML. Самое главное изменение — мы переделали логику фокуса, сделав его более простым и безопасным.
В целом, мы стараемся сохранять совместимость с Qt QML и иногда устраиваем крестово-совместительные походы по расхождениям.
Так как мы используем HTML5 как основную платформу (наверное, уже не очень модно говорить так, я не знаю точно), то мы используем HTML как простую систему рисования 2d графики, позиционируя элементы (div) абсолютно, относительно родителя. Это позволило нам полноценно реализовать примеси, например, разрешить любому элементу обрабатывать события hover или click, не используя страшный монстр MouseArea. Так же можно добавлять Border, Gradient или Drag-n-Drop в произвольные элементы, не создавая дополнительный элемент, и не создавая связку Item-MouseArea.
Текущее состояние
Очевидно, что небольшой организованной программистской группировкой из трех человек, мы не реализовали все компоненты и функции входящие в Qt QML, но значительную часть, наиболее полезную, по нашему мнению, мы сделали.
Создан генератор документации и навигатор по нему, как и скелет самой документации, при помощи похожих на doxygen аннотаций. Требуется навести порядок в библиотеке компонентов.
Доработать инструкции и инструментарий для Windows и MacOS.
У нас есть масса идей по оптимизации, наращиванию функционала и платформенным доработкам и прочему.
И тем не менее, ядро проекта уже достаточно стабильно, и мы, к сему моменту, успели выпустить несколько коммерческих проектов (и нескольких некоммерческих) на нашем PureQML.
Очень ждем ваших отзывов, а если кто-то захочет сделать что-то реально работающее, это будет просто прекрасно!
Всем кто дочитал эту исповедь до конца, огромное спасибо!
Если эта статья хоть кому-то будет интересна, мы можем продолжить рассматривать наше видение QML, развитие примесей, интеграция с разными платформами на разных уровнях, декларативно и нет, улучшение языка, добавление размерности в декларации (%, em, pt).
Мы пока решили не открывать исходные коды для smartTV платформ, но, вообще, рассматриваем такую возможность. Если вы хотите получить версию для SmartTV, напишите в комментариях, мы подумаем в каком виде это можно сделать.