Начинаем писать на Qt под Maemo
Я давно обещал написать вводную статью по написанию приложений под Maemo (и не только) на Qt 4.6. Обещания нужно выполнять, так что начнем. Сразу хочу оговориться, я не профессиональный дядя-разработчик, я лишь тупой и зеленый студент IT-специальности, занимающийся этим в свободное время. Так что все, сказанное мной, не особо претендует на библиографическую грамотность и энциклопедическую ценность. Долго определялся какого уровня писать статью: написать обзор maemo-специфичного API для тех, кто знает Qt, C++ и Linux и хочет просто узнать как пользоваться десятком дополнительных возможностей, или же начать с нуля и написать полный обзор. Как всегда, победила золотая середина, а именно: я не буду полностью рассказывать про все библиотеки Qt, потому что это займет слишком много времени, да и не очень нужно нам на этом этапе. На этот счет написаны целые книги, и тем, кто точно заинтересован в изучении Qt я бы посоветовал начать с книжки «Qt 4: Программирование GUI на C++» за авторством Жасмин Бланшет и Марка Саммерфилда. Книга переведена на русский, описывает Qt 4 с самого начала (с первого Hello, world) в объеме, достаточном для большинства приложений. Прочитав хотя бы 200 страниц уже можно спокойно пользоваться официальной документацией и написать всё что угодно. Qt — один из тех фреймворков, поняв и подружившись с которым, можно не использовать ничего, кроме документации по классам. Но вот сразу же понять его получается не у всех. Усугубляет дело еще то, что вам потребуется достаточные знания языка С++. Хотя бы умение писать свои классы, использовать наследование и других основополагающих понятий объектно-ориентированного программирования. Если вы вообще не знакомы с С++, то я бы порекомендовал перед началом разработки на Qt хоть немного узнать этот язык, написать десяток консольных приложений. Можете не углубляться в API взаимодействия с ОС, с сетью и другими сторонними библиотеками, так как всё это есть в Qt. Но знать хотя бы отличие агрегирования от наследования, по моему мнению, все-таки надо. Я буду стараться держаться именно того, что вы знакомы с С++, но первый раз видите Qt. Если вы не знакомы с программированием вообще, то я думаю вам не стоит бросаться писать под Maemo. Походите на школьные уроки информатики, прочитайте десяток книжек (для начала). Программирование — очень сложный процесс, он только кажется таким простым. Люди учатся этому годами, для этого нужен специальный склад ума, нельзя просто «сесть и написать программу». Заранее прошу прощения у тех, кто знаком с Linux, C++ или Qt, большинство моментов пришлось описывать очень подробно, можете их пропускать.
Что нам понадобится
Для начала определимся с инструментарием. Конечно же, нам понадобится Maemo SDK, в простонародье scratchbox. Установка и настройка на половину правильно описана на форуме maemos.ru. Почему на половину? Во-первых, scratchbox с тех пор сильно изменился, стал более дружелюбным. Теперь не надо самому создавать группу sbox, запускать вручную xephyr (это делается ярлыком на вашем десктопе). Во-вторых, автор ошибся с репозиториями и добавил репы diablo вместо fremantle. В-третьих — НЕ ставьте пакеты libqt4-***. Почему, объясню позже. Так что качаем GUI Installer и ставим его на ваш Linux.
Ах да, Linux — это второе обязательное условие (уже вижу как пол зала встало и вышло). Если вы уже наслаждаетесь миром Linux — вы знаете как вам повезло. Если этот Linux еще и deb-based, вам повезло еще больше. А вот если вы до сих пор пользуетесь windows, то я вам сочувствую. Дело в том, что Maemo SDK запускается через xephyr, а это вложенный Х-сервер. Под виндой нету Х-сервера вообще, у нее графическая оболочка неотделима от ядра, поэтому запуск SDK на ней невозможен. Придется качать VirtualBox, ставить туда любой Linux, ставить на него SDK и как-то с этим жить. Честно говоря, не представляю себе как это может нравиться, но, говорят, пользователи windows привыкли к такому.
Третье, что нам понадобится — QtCreator. Для тех, кто никогда полноценно не работал с большими IDE это просто находка, но Настоящие Мужики очень любят троллить этот продукт. Не без причин. Qt Creator правда очень малофункциональная IDE. О поддержке рефакторинга можно забыть, встроенного профайлинга приложений тоже нет, слава богу в последних версиях появилась поддержка систем контроля ревизий. Из плюсов: заточенность именно под разработку на C++ и Qt, а именно очень удобная система управления сборками и выбора компилятора и библиотек (например, если у вас в системе стоит несколько версий Qt, как у меня), некоторая автогенерация кода (на начальном этапе), встроенная документация (полная), дебаггер и нормальный текстовый редактор со всеми модными возможностями. Если вы ни разу не работали ни с чем сложнее блокнота, то вам покажется довольно наворочено, если же вы привыкли к своей IDE и не хотите переходить на что-то другое, можете поискать как настроить ее. Это должно быть просто: поставить на выполнение qmake && make clean && make и потом на запуск готового файла. В тех IDE, которыми пользовался я, сделать это было вполне возможно в настройках сборки проекта.
Философия Maemo
Что мы имеем внутри нашего девайса. Довольно полный обзор я писал как-то в начале одной своей статьи, повторюсь тут в более понятном виде. В общем, аппаратно это 32-битная архитектура ARM, которая уже успешно показала себя в миллионах девайсов, в основном мобильных и встраиваемых. Отличается очень низким энергопотреблением и невозможностью поставить на нее некошерную винду. Больше нам о ней ничего знать и не надо. Из программной части у нас настоящее ядро Linux 2.6.28 (на момент написания статьи), узнать его можно набрав в терминале uname -a. Полноценные HAL (for noobs: такая штука, чтобы переферию в линуксах автоматически включать-отключать, например флешки), D-Bus (шина, по которой одна программа может послать нахуй другую, а та понять и отреагировать), X-сервер (тот самый для графического интерфейса). Сам GUI, как вам известно, написан на GTK+ (на нем же написана среда GNOME), но 6 маемо уже на Qt. Короче, если не обращать внимание на размер, несовместимости пакетов и специально урезанные на благо хомячков функции, то у нас в руках компьютер, но не такой, как стоят у вас на столе, а на ARM.
Определимся с структурой директорий:
/bin — здесь лежат системные исполняемые файлы. Тот же терминал (он же BusyBox), и все консольные утилиты: ls, cp, grep, etc…
/boot — папка с загрузчиком. Во время работы девайса пуста, видимо для того, чтобы вы не сломали его своими ручками.
/cdrom — нухуясебе, да?
/dev — полностью под властью HAL и udev, о которых я уже упоминал. В мире Linux всё — файлы. Соответственно, здесь появляются все подключаемые устройства: флешки, память, жесткие диски, мышки, клавиатуры, даже терминалы, мониторы и звуковые карты.
/etc — глобальная свалка на всех линуксах. Сюда кладут всё, что не попадя, однако, обычно тут лежат конфиги программ и нужные модули для них. Реже — сами программы.
/floppy — второе нихуясебе
/home — ваша кладезь. Тут две нужные папки: в /home/opt ставятся все приложения (это тот самый 2-гигабайтный раздел) отформатирован он в ext2 и позволяет запуск приложений, а в /home/user/MyDocs уже ваш домашний каталог. Он нарочно отформатирован в fat 32, чтобы открываться на всех ОС. Честно говоря, мера вынужденная из-за windows, потому что он остался единственным, у кого проблемы с чтением ext-разделов. А еще он примонтирован с опцией noexec, поэтому с него запрещено запускать любые программы (вы получите Permission denied даже от рута). Вот это первый камень на нашем пути, если мы будем заливать программы на устройство через USB, нам придется дополнительно копировать их, например в специально созданную ручками /home/dev
/initrd — временная ФС для загрузки. Заинтересованным сюда.
/lib — здесь хранятся библиотеки, нужные системе. К счастью, Qt хранится не здесь
/media — сюда в подпапки монтируются SD-карты и другие флешки.
/mnt — сюда можете монтировать вы что угодно
/opt — является ссылкой на /home/opt
/proc — виртуальная ФС, позволяющая посмотреть любую информацию об оборудовании, если знать как. Архиполезная вещь, но на первом этапе забудьте.
/root — домашняя папка для пользователя root
/sbin — папка /bin для пользователя root
/tmp — временная папка. Лучше не класть сюда ничего надолго, системе бывает приспичивает его внезапно очищать. Да и тут особо не разгуляешься, ибо на rootfs всего 250 мегабайт места. Поэтому у нас есть /home/user/MyDocs/tmp. И ее уже никто кроме вас не тронет.
/usr — тут хранится весь софт, устанавливаемый юзером, который почему-то не попал в /opt как полагается. Обычно именно он виноват во всех проблемах с «недостаточно памяти в выбранном расположении».
/var — тут логи, PID’ы, локи и другая информация, которую обычно можно трогать, если вы знаете, что делаете
Остальные каталоги нас мало интересуют.
Философия Qt
С Linux разобрались, теперь ближе к делу. А именно как организована внутри себя Qt. Кьют — очень большая библиотека, поэтому внутри себя она поделена на модули (описания взяты с википедии):
QtCore — классы ядра библиотеки, используемые другими модулями;
QtGui — компоненты графического интерфейса;
QtNetwork — набор классов для сетевого программирования. Поддержка различных высокоуровневых протоколов может меняться от версии к версии. В версии 4.2.x присутствуют классы для работы с протоколами FTP и HTTP. Для работы с протоколами TCP/IP предназначены такие классы, как QTcpServer, QTcpSocket для TCP и QUdpSocket для UDP;
QtOpenGL — набор классов для работы с OpenGL;
QtSql — набор классов для работы с базами данных используя язык структурированных запросов SQL. Основные классы данного модуля в версии 4.2.х: QSqlDatabase — класс для предоставления соединения с базой, для работы с какой-нибудь конкретной базой данных требует объект, унаследованный от класса QSqlDriver — абстрактного класса, который реализуется для конкретной базы данных и может требовать для компиляции SDK базы данных. Например, для сборки драйвера под базу данных FireBird/InterBase требует .h файлы и библиотеки статической линковки, входящие в комплект поставки данной БД;
QtScript — классы для работы с Qt Scripts;
QtSvg — классы для отображения и работы с данными Scalable Vector Graphics(SVG);
QtXml — модуль для работы с XML, поддерживается SAX и DOM модели работы;
QtDesigner — классы создания расширений QtDesigner’а для своих собственных виджетов;
QtUiTools — классы для обработки в приложении форм Qt Designer;
QtAssistant — справочная система;
Qt3Support — модуль с классами, необходимыми для совместимости с библиотекой Qt версии 3.х.х;
QtTest — модуль для работы с UNIT тестами;
QtWebKit — модуль WebKit, интегрированный в Qt и доступный через её классы;
QtXmlPatterns — модуль для поддержки XQuery 1.0 и XPath 2.0;
Phonon — модуль для поддержки воспроизведения и записи видео и аудио, как локально, так и с устройств и по сети;
QtCLucene — модуль для поддержки полнотекстового поиска, применяется в новой версии Assistant в Qt 4.4;
ActiveQt — модуль для работы с ActiveX и COM технологиями для Qt-разработчиков под Windows.
Сразу же испытывать баттхерт не надо, ибо знать это все не обязательно (даже я знаю от силы половину). QtCore нам нужен всегда первом этапе нам бы освоить QtGui, ведь именно он у нас самый большой и самый интересный. Qt написан на С++ довольно высокого уровня. Все остальные модификации Qt под другие языки (PyQt, PySide, PHP-Qt) — это просто биндинги. Архитектурно программа на Qt выглядит так:
Объект QApplication, отвечающий практически за все основные функции, не относящиеся к GUI. Например, обработка событий. Чтобы пользователь хоть что-то увидел, нам нужны объекты окон. Обычно это QMainWindow, QWidget или QDialog. На эти окна можно набросать других виджетов: кнопки, чекбоксы и все остальные привычные контроллеры. Но как теперь все это связать воедино? Если вы писали на Delphi вы привыкли ко всяким Object::onMouseMove(), короче к обычной событийной реализации. В Qt, кстати, она тоже есть, только используется именно там, где надо, а не везде. Для связывания виджетов с действиями существует система сигналов и слотов. Обычно это то самое, что вызывает больше всего затруднений у новичков. Для полного понимания нужно открыть книжку, а я попробую объяснить на пальцах. Объект1 может послать сигнал, на который реагирует объект2. При этом объекту1 насрать кто на него отреагирует, да хоть никто. А объекту2 уже надо решить обрабатывать ли или забить. Метод, принимающий этот сигнал называется слотом. Сигналы могут быть любыми, от стандартных clicked() или itemChnged() до определенных пользователем. Вторые используются редко, зато пользовательские слоты встречаются постоянно. Теперь на примере: вы нажали на кнопку, которая шлет сигнал clicked() (и еще несколько, но не важно), и соединили ее со слотом, который открывает новое окно. Если вы все сделали правильно, то все заработает. На первый взгляд просто, но одновременно таит в себе много вкусного: один сигнал может обрабатываться сразу несколькими слотами (что проблематично при обычном «событие-обработчик» соединении), и наоборот: один слот может ловить несколько сигналов. Сигнал может быть соединен не только со слотом, но и сигналом, тогда он просто будет вызывать его. А так как сигналы и слоты — это обычные методы С++, то их даже можно вызывать руками, что иногда помогает избегать дублирования кода.
В этой же главе я хочу объяснить такой момент: почему С++? Я по своей натуре пишу на многих языках (более десятка), поэтому имею неплохое поле для выбора. Язык — это инструмент, программировать надо не «на языке», а «с использованием его» и всегда выбирать верный инструмент. Отверткой тоже можно забивать гвозди, а экскаватором мыть посуду, но тут явно что-то не так. Недавний мой PyCallBlocker был написан на прекрасном языке Python. Сам Qt есть еще для нескольких языков, даже для Java. Я мог бы выбрать Python и статья бы была в 2 раза меньше. Я мог бы выбрать Java и статья бы была в 2 раза больше. Я мог бы выбрать РНР и… проблюваться. Я выбрал С++. Во-первых, потому что для его запуска нам понадобится минимальный набор библиотек. Никаких PyQt, PySide, все уже идет с последней прошивкой. Во-вторых, я предпочитаю не учить новичков Python’у, чтобы жизнь малиной не казалась. Очень гибкий и простой язык, но только когда разбираешься в программировании. Мне хватило тучи хомячков, скандирующих «Питон — ахуенен» после прочтения пары моих статей. Поэтому учиться будем сразу правильно.
Начинаем писать
Я думаю вы уже поставили пакеты libqt4-memo5-core и libqt4-maemo5-gui по этому мануалу. Я обещал рассказать, почему не надо ставить libqt4-**, а надо ставить только то, что с суффиксом -maemo5-. Дело в том, что пакеты без него — это сборка коммьюнити. Там Qt 4.5.3 (вроде бы) и нет никаких специфичных функций для maemo. Только перерисован стиль и оптимизированы виджеты. А пакеты libqt4-maemo5-*** – это официальная сборка нокии, там последний Qt 4.6 с полной поддержкой виджетов и других полезных фич типа портретной ориентации.
Запустим свой установленный QtCreator и создадим новое «GUI-приложения на Qt4». После создания у нас должно появиться четыре файла: *.cpp — исходник, *.h — хедер, *.ui — интерфейс, *.pro — файл проекта (используется для сборки на настройки). Запустить все это можно уже сейчас (зеленой кнопкой run) и полюбоваться на пустую форму. За одно убедиться, что Qt установился. Напишем хелловорлд. В любой книжке, которую вы откроете вас будут учить это делать по-хорошему, не открывая QtCreator или QtDeigner и создавая классы с нуля. Это очень правильный подход, не пропускайте его, когда будете читать, потому что именно так формируется понимание языка и фреймворка, но я не собираюсь учить с нуля, поэтому воспользуемся готовыми средствами дизайна GUI.
Откройте .ui файл и бросьте на форму кнопочку (QPushButton) и метку (QLabel). Выделите оба виджета и сгруппируйте их в размещения (Layout) с помощью кнопочек сверху. Они нужны, чтобы растягивать виджеты вместе с растяжкой окна, а на maemo без них просто никуда, потому что мы не знаем точные размеры и положения кнопок. А еще одни сыграют нам первостепенную роль, когда будем прикручивать к приложению портретный режим. Один хинт: чтобы окончательно привязать размещение к окну — кликните по окну, а затем по любой кнопке размещения сверху.
Сделаем так, чтобы при клике на кнопку на метке появлялась надпись «Hello, Qt». Для этого снова снова воспользуемся встроенными средствами QtCreator’а. Перейдем в режим редактирования сигналов и протянем красную стрелочку от кнопки до формы (не до метки). Нажмем там на плюсик и добавим новый слот. Назовем его «testslot()». Затем выберем сигнал «clicked()» и слот «testslot()». Сохраняем и закрываем .ui-файл, он нам больше не нужен.
Открываем *.h. В нем нужно добавить новый прототип слота. Для этого добавим секцию public slots: и пропишем в нем прототипа слота: void testslot(); Закрываем. Открываем *.cpp и пишем реализацию. Примерно вот что:
void HelloWorld::testslot() {
this->ui->myLabel->setText('Hello, Qt');
}
Три строчки, а столько всего. HelloWorld:: – имя класса (оно же имя проекта). this->ui — здесь хранится весь ваш UI, созданный в файле .ui. Например myLabel — так я назвал метку в дизайнере, setText() – метод, вызываемый у объекта QLabel. Вот тут официальная документация, в которой всегда можно посмотреть все методы любого встроенного класса.
Кросскомпиляция и запуск на Maemo
Попробуем запустить это все кнопочкой Run. Все должно пройти успешно, можете пожать свою кнопочку, но нам же нужно это все запустить на Maemo. Простым переносом запустить получится только на x86 (если у вас 32-битная ОС), но в самом начале статьи я уже говорил, что это не x86, а ARMEL. Тупой перенос и запуск исполняемого файла на телефоне завершился бы неудачей (можете проверить). Поэтому запускаем наш scratchbox и xephyr (один запускается просто командой scratchbox в консоли, второй — ярлыком на десктопе). Обычно он запускается в режиме платформы X86, для чего выполняем команду: «sb-conf se FREMANTLE_ARMEL» (чтобы обратно, замените ARMEL на X86). Копируем всё дерево исходников куда-нибудь в домашний каталог scratchbox’а. И делаем cd в него. Чтобы откомпилировать нужно выполнить три команды:
/opt/qt4-maemo5/bin/qmake — утилита, генерирующая makefile на основе нашего *.pro-файла.
make clean — очищает все файлы с предыдущей сборки
make — собственно, выполняет сборку.
Можно объединить в одну строку: /opt/qt4-maemo5/bin/qmake && make clean && make
Затем запускаем созданный файл как «run-standalone.sh ./Имя_проекта». Скрипт run-standalone.sh запускает приложение с нативным итерфейсом. Попробуйте без него и ощутите разницу.
А вот теперь уже можно подключать телефон по USB, либо заливать по SSH, кому как больше нравится. В нашем случае заливать нужно лишь один исполняемый файл, но если вы подключаете ресурсы извне (например, используете иконки и конфигурационные файлы), то позаботьтесь о том, чтобы их тоже было видно и права доступа к ним были правильные. И не забываем о том, что из папки /home/user/MyDocs запуск приложений невозможен.
Любите свой maemo. В следующей статье попробуем углубиться в специфический API, например работу с акселерометром, датчиком уха (proximity sensor который), stackable windows (окошки с клавишей назад вместо закрыть, как в медиаплеере), показом желтых баннеров и всплывающих окон. А пока можете начинать осваивать официальную доку, она очень помогает: http://qt.nokia.com/doc/qt-maemo-4.6/
А особое внимание на раздел специфичных методов: http://qt.nokia.com/doc/qt-maemo-4.6/platform-notes-maemo5.html
И еще можете посмотреть примеры. Там со скриншотами и кодом: http://qt.nokia.com/doc/qt-maemo-4.6/examples-maemo5.html
Посмотри статью http://habrahabr.ru/blogs/qt_software/86689/ . Я там описал как запускать сразу из креатора на эмуляторе. Кстати советую пользоваться снепшотами креатора, там много всего нового появилось
Да, я вчера читал ее, принял к сведению. Просто эту статью писал еще на прошлой неделе и не знал про сей замечательный способ.
Кстати. на счет хабра. Я вас там вчера немного потроллил со второго аккаунта (табуредко который), сорри :D
Но предложение все еще в силе: нет ли линков на статьи как работать с сенсорами по D-Bus?
ну есть клеви X2, где есть пример работы с акселеромометром. Если вдруг не знаете что это то вот http://gitorious.org/ofi-labs/X2 . Если в кратце то это новый проект Арайи Хирадата.