Введение в разработку приложений для Qtopia

В статье приводится пошаговое руководство по написанию, отладке и созданию дистрибутива (очень) простого приложения под Qtopia на КПК Sharp Zaurus.

Предполагается, что читатель знаком с языком C++ и умеет работать в командном интерпретаторе Линукс.

Все примеры проверены на Sharp Zaurus SL-C860 с прошивкой Cacko 1.22a и Developer Image 1.6 на борту.

Матчасть

Qtopia — графический интерфейс и менеджер программ для небольших устройств, работающих на Линуксе. Пользовательский интерфейс Qtopia основан на библиотеке Qt-embedded, являющейся уменьшенной версией библиотеки Qt. Qtopia, Qt-embedded и Qt производятся небольшой софтверной компанией Trolltech из Норвегии.

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

Qtopia написана на языке C++, “родные” (native) Qtopia-приложения также должны писаться на этом языке. Приложение должно быть реализовано как класс C++. Так полагается реализовывать любой элемент пользовательского интерфейса.

Вы не обязаны создавать дистрибутивный пакет, чтобы установить и запустить приложение на Заурусе. Возможно просто перенести исполняемый файл на машинку и запустить из командной строки. Однако, этот способ подходит для отладки программ и некоторых компьютерных маньяков, но не для обычного пользователя. Если вы заинтересованы в распространении своего приложения, вы должны упаковать его в ipk-файл, являющийся упакованным архивом. Пакеты ipk являются стандартным форматом дистрибутива для Зауруса, при установке они просто распаковываются в файловую систему на устройстве. Чтобы создавать ipk-файлы, вы должны знать в общих чертах устройство файловой системы на Qtopia-устройствах.

Сама Qtopia устанавливается в каталог /opt/Qtopia на устройстве. По историческим причинам также имеется каталог /opt/QtPalmtop. Реально это символические ссылки, указывающие на /home/QtPalmtop. На каждом сменном носителе (карте памяти) также создается каталог /opt/QtPalmtop. Приложение может быть установлено в любой из них, поэтому разработчик не должен “привязываться”, например, к /opt/Qtopia. На практике это означает, что при пакет должен создаваться так, чтобы при установке он распаковывался в ./opt/QtPalmtop. Точка в начале пути при установке будет заменена инсталлятором на имя соответствующего корневого каталога. Поступая таким образом, разработчик предоставляет пользователю возможность установки пакета в несколько разных мест (как правило установка в основную память или на одну из карт памяти или жесткий диск).

Внутри /opt/QtPalmtop (и ее аналогов на сменных носителях) может находиться несколько подкаталогов, которые должен знать и использовать разработчик.

  • ./opt/QtPalmtop/bin предназначен для исполняемых файлов (программ). Это единственное место где гарантированно происходит поиск исполняемых файлов системой запуска Qtopia.
  • ./opt/QtPalmtop/lib предназначен для динамических библиотек. И снова, это единственное место, где система будет искать библиотеки. На практике поиск также производится в стандартных юниксовых каталогах /lib и /usr/lib, но устанавливать туда ничего не рекомендуется (например, /lib является частью ROM-памяти, соответственно, вы ничего не можете туда поместить).
  • ./opt/QtPalmtop/apps содержит конфигурационные файлы для системы запуска. В файле с расширением .desktop, вы говорите системе запуска как нужно вызывать ваше приложение, какую пиктограмму использовать для него, какие особые у него есть особые требования (например, разрешение экрана).
  • ./opt/QtPalmtop/etc — здесь находятся различные файлы данных и конфигурационные файлы.

Инструменты

Разработку можно вести как на самом Заурусе, так и на десктрпе под Линуксом. В первом случае вам понадобится Developer Image, во втором — кросс-компилятор. Здесь описывается только первого варианта.

Developer Image содержит все необходимые инструменты, заголовочные файлы и документацию, необходимую для разработки программ на C++ прямо на Заурусе.

Кроме Developer Image вам, конечно же, понадобится текстовый редактор. Вы можете пользоваться vim, который находится в Developer Image, либо вы можете использовать vi (elvis), имеющийся в Cacko ROM. Также вы можете поставить Emacs или Jed, использовать встроенный редактор Midnight Commander’а. Существует еще несколько редакторов с графическим интерфейсом (VisiScript, ZEditor). Используйте тот, что вам удобнее.

Установка

Скачать dev-image можно, например, с Zaurus User Group (прямая ссылка: http://www.zaurususergroup.org/UpDownload+index-req-getit-lid-207.phtml)

Далее распакуйте архив и скопируйте файлы dev_img-1.6 и image_setup.sh на карточку. Например, в /mnt/card/devel.

Станьте суперпользователем (su), перейдите в каталог /mnt/card/devel и выполните следующую команду:
# image_setup.sh ./dev_img-1.6 /mnt/dev

Образ файловой системы смонтирован теперь в /mnt/dev, также настроены все нужные переменные окружения. Выйдите из команды su и перезапустите Qkonsole (в дальнейшем этого делать не надо будет).

Совет Скрипт image_setup.sh добавляет строки в файлы /etc/fstab и ~/.profile при каждом запуске. Поэтому после первого удачного запуска я открыл его в редакторе и закоментировал все команды, которые что-либо пишут в эти файлы.

Структура /mnt/dev

Что мы теперь имеем? Заглянем в /mnt/dev.

В каталоге bin мы обнаруживаем gcc, make, as и прочие нужные вещи. В usr/bin находим perl и vim.

В каталоге include лежат все нужные заголовочные файлы, а в lib — динамические библиотеки.

Наконец, в каталоге docs располагается вся нужная нам документация:

  • docs/qt/html/ — полная документация по Qt от Trolltech
  • docs/qtopia/ — документация по Qtopia
  • docs/sharp/dtm — SL Data Manager Class References
  • docs/BusyBox.html — справка по командам BusyBox

Hello, world!

Давайте начнем с чего-нибудь самого простого, например, с Hello, world!. Почему? Чтобы, во-первых, проверить работоспособность Developer Image, а во-вторых, показать как писать и отлаживать программы на Заурусе.

Запустите Qkonsole, откройте редактор (я обычно сразу открываю две сессии — в одной запускаю Emacs, в другой запускаю компилятор и саму отлаживаемую программу).

Создайте новый файл с таким содержимым:

Filename: hello1.cpp

#include
int main(int argc, char **argv)
{
printf("Hello, world!\n");
return 0;
}

Откомпилируйте его:

$ gcc -o hello1.o -c hello1.cpp

После компиляции у вас должен появиться файл hello1.o. Затем запустите сборку этого объектного файла со стандартными библиотеками:
$ gcc -o hello1 hello1.o

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

Линкер создал исполняемый файл hello1. Если вы проверите его утилитой file, вы увидите следующее:
$ file hello1
hello1: ELF 32-bit LSB executable, ARM, version 1 (ARM),
for GNU/Linux 2.0.0, dynamically linked (uses shared libs), not stripped

“Not stripped” означает, что файл содержит отладочную информацию. Команда

$ ls -l hello1

покажет, что файл занимает 11K — многовато для программы из нескольких строк. Можно его сжать, выбросив ненужную информацию:
$ strip hello1

Теперь файл занимает чуть больше двух килобайт.

Запустите его:

$ ./hello1
Hello, world!
$

Отлично! Все работает.

В реальной работе вы, конечно же, не станете каждый раз вводить все эти команды в терминале. Вы напишите небольшой скрипт, или, более вероятно, Makefile. Мы не будем рассказывать здесь как использовать программу make, так как это часть стандартного процесса разработки на любом Юниксе и в ее использовании на Заурусе нет ничего особенного.

Простейшая программа с GUI

Теперь самое время написать “Hello, world!” с использованием графического интерфейса. Ниже приведен исходный текст файла hello2.cpp.

Filename: hello2.cpp

#include
#include

int main(int argc, char** argv)
{
QPEApplication app(argc, argv);
QMainWindow* mainWindow = new QMainWindow();
mainWindow->setCaption("Hello, World!");
app.showMainWidget(mainWindow);
return app.exec();
}

В первой строке функции main создается объект класса QPEApplication. Этот класс описывает модель всего приложения и содержит, среди прочего, код для обработки событий, запуска и остановки. Затем мы создаем главное окно приложения. Класс QMainWindow описывает главное окно, то есть то, которое может иметь меню, панель инструментов и рамку с заголовком. Метод setCaption() вызываемый для главного окна задает текст заголовка. Затем мы говорим, что только что созданное окно будет главным виджетом приложения (виджетом называется любой элемент GUI). Наконец, мы вызываем метод exec() чтобы запустить приложение. Этот метод является главной точкой входа в приложение и не завершается, пока работает приложение.
Давайте теперь откомпилируем его:

$ g++ -I/home/QtPalmtop/include -DQT_QWS_EBX -DQT_QWS_CUSTOM \
-DQWS -fno-exceptions -fno-rtti -march=armv4 -mtune=strongarm -o \
hello2.o -c hello2.cpp

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

  • Ключ -I сообщает компилятору, что искать заголовочные файлы нужно в /opt/QtPalmtop/include. Этот ключ нужен, чтобы компилятор смог найти qpeapplication.h и qmainwindow.h.
  • -DQT_QWS_EBX -DQT_QWS_CUSTOM -DQWS определяют необходимые макросы для правильной компиляции заголовочных файлов Qt (и указывают, что мы компилируем для Qtopia).
  • -march=armv4 -mtune=strongarm — означают, что мы собираем приложение для архитектуры ARM, точнее для процессоров Strong Arm.
  • -fno-rtti приказывает компилятору не включать информацию о типах времени исполнения (run-time type information) в откомпилированные классы. Так как классы самой Qtopia откомпилированы без RTTI, включение этой информации в наш код приведет к ошибкам сборки.

Теперь соберем приложение:

$ g++ -L /opt/QtPalmtop/lib/ -o hello2 hello2.o -lqte -lqpe -ljpeg

Ключ -L сообщает линковщику где нужно искать библиотеки, указанные дальше в командной строке:

- -lqte: содержит классы Qt-embedded, такие как QMainWindow;
- -lqpe: содержит классы приложений Qtopia, такие как QPEApplication;
- -ljpeg: содержит код для работы с изображениями в формате JPEG.

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

Если сборка прошла успешно, вы получите исполняемый файл hello2, который при необходимости может быть сжат утилитой strip и запущен из командной строки. При запуске вы увидите новое чистое окно на весь экран с заголовком и кнопкой закрытия. Вы можете закрыть его нажав на кнопку.

Примечание Qtopia имеет один неприятный баг. При запуске из командной строки никогда не переключайтесь на Qkonsole или какое-либо другое приложение, пока работает ваша программа. Если вы сделаете это, то при переключении обратно на ваше приложение система перейдет в режим Magnified Screen, но как-то криво: вы увидите только белый экран и как правило ничего более. Если с вами произошла такая неприятность, нажмите несколько раз Cancel и немного подождите — приложение закроется и экран вернется на место.

Если вы переключились на консоль, лучше и быстрее будет открыть новую сессию и убить ваше приложение командой kill -9.

Более сложная графическая программа

Теперь пример посложнее. На нем мы покажем основы концепцию слотов и сигналов (одну из самых важных в Qt), а также расскажем как пользоваться компилятором метаобъектов (Meta-Object Compiler, MOC).

В предыдущем примере главное окно приложения было просто экземпляром классы QMainWindow. Оно мало что умело делать, так как мы не добавили никакой новой функциональности в предопределенный объект. В реальном приложении мы должны как минимум создать новый класс окна. Во многих простых приложениях это может быть единственный класс, который нужно определить — приложение может состоять целиком из одного окна, содержащего все необходимые графические элементы (кнопки, списки и т.п.).

В этом примере мы определим новый класс FrmMain, который будет наследовать QMainWindow. По соглашению, окна Qtopia, которые содержат поля для ввода данных, называются формами (forms). Это слово, обычно в виде Frm, входит в названия классов. У этого окна будет строка меню, содержащая пункт “File”, в котором будет находится команда “Quit”. Выбор этой команды будет закрывать приложение.

Интерфейс класса главного окна

Следуя принятым в C++ соглашениям, мы определяем новый класс главного окна в отдельном .cpp файле. Также мы должны определить интерфейс этого класса в отдельном заголовочном классе, чтобы тот код, что будет его использовать, “знал” как к нему обращаться. На самом деле мы должны вынести интерфейс в отдельный файл для правильной работы MOC. Но об этом потом. Заголовочный файл будет называться FrmMain.h, а реализация класса будет находиться в файле FrmMain.cpp.

Filename: FrmMain.h

#include

class FrmMain : public QMainWindow
{
Q_OBJECT
public:
FrmMain(QWidget* parent=0, const char* name=0, WFlags fl=0);

public slots:

void    cmdFileQuit();
};

Обратите внимание: мы определили FrmMain как подкласс QMainWindow. Если вы не знакомы с разработкой под Qt, то для вам покажется странной эта стока:
public slots:

Терм ’slot’ определен в макросе Q_OBJECT, включенном в описание класса выше. Слотом называется функция, ответственная за обработку события, генерируемого где-то в другом месте приложения. Ниже мы покажем как выбор команды в меню генерирует событие, и как это событие соединяется со слотом. Пока же запомните, что cmdFileQuit() есть функция, которая будет определена в FrmMain.cpp, и которая будет вызываться в ответ на определенное действие пользователя.

Реализация класса главного окна

Как вы могли понять из определения интерфейса, нам нужно написать реализацию конструктора класса и метода cmdFileQuit(). Вот этот код, в файле FrmMain.cpp:

Filename: FrmMain.cpp

#include
#include
#include "FrmMain.h"

FrmMain::FrmMain(QWidget* parent, const char* name, WFlags fl)
: QMainWindow(parent, name, fl)
{
setCaption("Hello, World!");

QMenuBar *menubar = this->menuBar();
QPopupMenu *mnuFile = new QPopupMenu(this, "MenuFile");
menubar->insertItem("&File", mnuFile);
mnuFile->insertItem("&Quit", this,
SLOT(cmdFileQuit()), 0, 1);
}

void FrmMain::cmdFileQuit()
{
this->close();
}

В конструкторе создается главное меню приложения. Пункты меню вставляются при помощи строк вида:
mnuFile->insertItem("&Quit", this,
SLOT(cmdFileQuit()), 0, 1);

Эта строка создает пункт меню “Quit” и связывает событие, генерируемое при выборе этого пункта, с функцией-слотом cmdFileQuit(). Впоследствии эта функция будет вызвана, когда пользователь выберет пункт “Quit” в меню “File”. События пользовательского интерфейса являются частным случаем того, что в Qt называется “сигналом”. Классы могут определять собственные сигналы, которые могут быть связаны со слотами в других классах, которые будут получать эти сигналы. Это очень мощный механизм управления поведением программы, но его полное описание выходит за рамки этой статьи.

Компиляция класса главного окна

Мы уже знаем, как компилировать файлы:

$ g++ -I/home/QtPalmtop/include -DQT_QWS_EBX -DQT_QWS_CUSTOM \
-DQWS -fno-exceptions -fno-rtti -march=armv4 -mtune=strongarm -o \
FrmMain.o FrmMain.cpp

Результатом выполнения (если все пройдет без ошибок) будет файл FrmMain.o.

Главная программа

Главная программа по сути такая же, как и в предыдущей главе. Но вместо экземпляра QMainWindow мы должны создать экземпляр класса FrmMain. Таким образом, код будет выглядеть следующим образом:

Filename: hello3.cpp

#include
#include
#include "FrmMain.h"

int main(int argc, char** argv)
{
QPEApplication app(argc, argv);
QMainWindow* mainWindow = new FrmMain();
app.showMainWidget(mainWindow);
return app.exec();
}

Чтобы откомпилировать его выполните следующую команду:

$ g++ -I/home/QtPalmtop/include -DQT_QWS_EBX -DQT_QWS_CUSTOM \
-DQWS -fno-exceptions -fno-rtti -march=armv4 -mtune=strongarm -o \
hello3.o -c hello3.cpp

Компилятор мета-объектов

Теперь у нас есть два объектных файла, hello3.o и FrmMain.o, которые по идее должны быть слинкованы вместе чтобы получилось готовое приложение. Но если вы попробуете сделать это, выполнив такую команду:
$ g++ -L /opt/QtPalmtop/lib/ -o hello3 hello3.o FrmMain.o \
-lqte -lqpe -ljpeg

то получите кучу ошибок такого вида:

 FrmMain.o(.text+0x450): undefined reference to
 `FrmMain::QPaintDevice virtual table'

Да… Такое ощущение, что чего-то не хватает или что-то лишнее. Проблема в том, что механизм слотов и сигналов в Qt нуждается в некоторой дополнительной инфраструктуре. Эта инфраструктура не может быть статически включена в какой-либо из базовых классов (например, QMainWindow), потому что зависит от того, как определяются слоты и сигналы. Таким образом, и в этом важное отличие Qt, она должна создаваться динамически. Для этого Trolltech предоставляет соответствующий инструмент — Meta-Object Compiler (MOC). MOC читает заголовочные файлы с описаниями объектов пользовательского интерфейса и генерирует файлы с кодом на C++, реализующий необходимую логику для поддержки механизма сигналов и слотов.

Таким образом, нам нужно “натравить” MOC на FrmMain.h, чтобы получить такой файл (он будет называться FrmMain_moc.cpp), который затем нужно откомпилировать. Наконец, нужно собрать приложение с использованием полученного файла.
$ moc -o FrmMain_moc.cpp FrmMain.h
$ g++ -I/home/QtPalmtop/include -DQT_QWS_EBX -DQT_QWS_CUSTOM -DQWS \
-fno-exceptions -fno-rtti -march=armv4 -mtune=strongarm -o \
FrmMain_moc.o -c FrmMain_moc.cpp

Первая строка генерирует код на C++, а вторая — компилирует его. Теперь мы можем собрать приложение из FrmMain.o, hello3.o, и FrmMain_moc.o:
$ g++ -o hello3 FrmMain.o hello3.o FrmMain_moc.o \
-L/home/QtPalmtop/lib -lqte -lqpe

В результате работы последней команды вы должны получить исполняемый файл hello3. Когда вы его запустите, то увидите окно приложения с заголовком “Hello, World!” и главным меню, состоящим из одного пункта “File”, в котором расположен пункт “Quit”. При выборе этого пункта приложение закроется.

Использование tmake и make для сборки приложения

Как мы уже говорили выше, описание использования программы make не входит в задачи данного руководства, однако эта утилита значительно облегчает жизнь при разработке. А другая утилита, tmake, еще более помогает при разработке программ под Qt и Qtopia. Эта утилита, как и moc, поставляется вместе с Qt и, конечно же, имеется в Developer Image.

Программа tmake генерирует Makefile на основе небольшого файла описания проекта. Все, что вам нужно сделать, это создать такое описание.

Для нашего последнего примера файл проекта будет выглядеть следующим образом:

Filename: hello3.pro

 TEMPLATE = app
 CONFIG  = qt warn_on release
 HEADERS = FrmMain.h
 SOURCES = FrmMain.cpp hello3.cpp
 TARGET  = hello3

Первая строка сообщает, что мы делаем приложение (app от application), далее мы сообщаем, что это приложение использует Qt, что мы хотим видеть предупреждения компилятора и что мы собираемся выпускать релизы (в Makrfile будет добавлена цель dist для получения тарболла). В следующих строках последовательно перечисляются заголовочные файлы, файлы с исходным текстом и задается название результирующего исполняемого файла. Получаем Makefile и собираем наше приложение:
$ tmake -o Makefile hello3.pro
$ make

Теперь после любых изменений исходного текста, а также после добавления или удаления файлов (не забудьте в этом случае обновить hello2.pro) используем команду make для сборки.

Ну, наше приложение не слишком-то сложное. Но оно демонстрирует все, что вы должны знать о том, как откомпилировать, собрать и запустить программу на Заурусе. Конечно, эта статья не охватывает и маленькой части программирования под Qtopia, но сама Qtopia хорошо документирована и можно найти множество примеров в Интернете.

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

Создание дистрибутива

Создание ipk-пакетов для Зауруса подробно описано в статье Создание дистрибутивов для Зауруса. Здесь же мы вкратце расскажем об основных этапах создания простого дистрибутива. Рекомендуется прочесть вышеприведенную статью перед тем, как вы займетесь созданием дистрибутивов.
Сначала создадим файл control с описанием нашего приложения:

Filename: ./control

 Package: hello_test
 Installed-Size: 32000
 Filename: ./hello_0.1_arm.ipk
 Version: 0.1
 Depends:
 Priority: optional
 Section: qpe/utilities
 Maintainer: your name here
 Architecture: arm
 Description: Test application

Имя файла предопределено — файл должен называться control, и никак иначе. Значения большинства строк очевидно из названий.

Filename содержит имя пакета. По соглашению оно должно иметь следующий формат: название_версия_платформа.ipk, т.е. для Зауруса имя файла пакета должно оканчиваться на “_arm.ipk”.

Installed-Size приводится только для информации — оно не обязано быть точным до байта. Depends содержит список пакетов, которые должны быть установлены, чтобы приложение заработало. В нашем случае таких пакетов нет.

Сжимаем файл в control.tar.gz:

$ tar cf control.tar ./control
$ gzip control.tar

Символы “./” перед именем файла “./control” тут обязательны! Без них инсталлятор не будет правильно работать. Встроенная версия tar не понимает команду “z” и не умеет упаровывать полученный tar при помощи gzip, поэтому мы должны выполнить две команды.

Теперь упаковываем приложение. Нужно создать архив таким образом, чтобы при распаковке его содержимое попало в нужные подкаталоги /opt/QtPalmtop (или его аналогов на карточках). Необходимо поместить в архив три вещи:

  • Исполняемый файл приложения;
  • .desktop-файл (который сообщает системе ззапуска что делать с приложением);
  • Иконку для приложения, которая будет отображаться на рабочем столе.

Давайте создадим вначале нужную файловую структуру для архива. В рабочем каталоге (где уже лежат hello3 и control.tar.gz) выполните следующие команды:
$ mkdir -p opt/QtPalmtop/bin
$ mkdir -p opt/QtPalmtop/apps/Applications
$ mkdir -p opt/QtPalmtop/pics

Эти три каталога будут содержать, сообветственно, исполняемый файл, .desktop-файл и иконку. Опять-таки, вы не можете назвать каталоги по-другому — каталоги с такими именами уже существуют в системе, и вы должны поместить нужные файлы в нужные места, чтобы приложение было установлено правильно.
Теперь скопируйте исполняемый файл hello3 в ./opt/QtPalmtop/bin.

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

Filename: **./opt/QtPalmtop/apps/Applications/hello3.desktop**

 [Desktop Entry]
 Comment=Qtopia test app
 Exec=hello3
 Icon=hello3
 Type=Application
 Name=Test app
 Display=640x480/144dpi,480x640/144dpi

Строка Exec=hello3 указывает, что для того, чтобы запустить приложение, нужно выполнить команду hello3.

Последняя строка, “Display”, указывает, что приложение работает в режиме 640×480. Если у вас Заурус другой серии, имеющий экран 320×200, уберите эту строку.

Icon=hello3 сообщает, что в качестве иконки для приложения нужно использовать файл hello3.png, который должен находиться в каталоге pics. Иконка должна быть в формате PNG и иметь размер 32×32 пиксела. Чтобы не возиться сейчас с иконкой для нашего приложения, возьмем файл datebook_icon.png и скопируем его в ./opt/QtPalmtop/pics:
$ cp /usr/QtPalmtop.rom/pics144/datebook_icon.png \
./opt/QtPalmtop/pics/hello3.png

(Многие файлы /opt/QtPalmtop на самом деле являются символическими ссылками на файлы, расположенные в ROM-памяти.)
Наконец, скопируем исполняемый файл:

$ cp hello3 ./opt/QtPalmtop/bin/

В результате у нас получилась следующая структура:

 opt
   QtPalmtop
     pics
       hello3.png
     apps
       Applications
         hello3.desktop
     bin
       hello3

Теперь нужно сжать эту структуру каталогов в data.tar.gz. И в этом случае название файла предопределено — инсталлятор ожидает именно этот файл.
$ tar cf data.tar ./opt
$ gzip data.tar

Создадим debian-binary — он должен содержать одну строку со значением “2.0″:
$ echo "2.0" > debian-binary

Наконец, мы можем создать пакет для установки из файлов, созданных на предыдущих стадиях. Сначала упаковываем все добро в hello_0.1_arm.tar.gz, который затем переименовываем в hello_0.1_arm.ipk:

$ tar cf hello_0.1_arm.tar ./data.tar.gz \
./control.tar.gz ./debian-binary
$ gzip hello_0.1_arm.tar
$ mv hello_0.1_arm.tar.gz hello_0.1_arm.ipk

Не забудьте, что символы “./” в начале файлов очень важны. Если вы опустите их, установка не пройдет.

Теперь у вас есть дистрибутивный ipk-файл, который вы можете попробовать поставить обычным способом: выполнив команду
$ sudo ipkg install hello_0.1_arm.ipk

или через Settings->Add/Remove Software. В первом случае вам, скорее всего, потребуется запустить Settings->Tab Settings и нажать там “OK”, чтобы иконка появилась на закладке Applications рабочего стола.

Готово. Кликнув на иконке, вы должны увидеть окно нашего приложения.

Полезные советы

Напоследок несколько полезных советов.

Не забывайте, что вся необходимая документация по классам Qt и Qtopia имеется у вас под рукой. Изучите содержимое /mnt/dev/docs/.

При разработке может оказаться удобным вручную сделать ярлык для разрабатываемого приложения. Я поступил следующим образом: создал новую закладку Utils, в которую перенес ярлыки для запуска консоли и текстовых редакторов. На этой же закладке у меня находятся и ярлыки для отлаживаемых приложений. Все это можно сделать как вручную (загляните в /opt/QtPalmtop/apps), так и при помощи графической утилиты Settings->Tab Settings. Перед тем, как создавать ярлык для приложения, сделайте символическую ссылку в /opt/QtPalmtop/bin. Для нашего приложения это может выглядеть так:

$ su
# cd /opt/QtPalmtop/bin
# ln -s /home/zaurus/MyFirstQtopiaApp/hello3 ./hello3_dev

Я добавляю “суффикс” _dev чтобы не путались файлы уже готовой и установленной версии и той, что еще в разработке.

Кроме Developer Image существуют также другие инструменты, например, zgcc. Если вы по каким-то причинам не удовлетворены dev-image, попробуйте поискать более подходящий инструментарий.


В данном руководстве были использованы материале Кевина Буна: Kevin Boone “My first Qtopia application — how to get started with Qtopia development” с The K-Zone.