<?xml version="1.0" ?> <!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [ <!ENTITY kappname "&ksplash;"> <!ENTITY package "kdebase"> <!ENTITY % addindex "IGNORE"> <!ENTITY % Russian "INCLUDE"> ]> <book lang="&language;"> <bookinfo> <title >Руководство &ksplash;</title> <authorgroup> <author >&Teemu.Rytilahti; &Teemu.Rytilahti.mail; </author> <othercredit role="developer" >&Brian.C.Ledbetter; &Brian.C.Ledbetter.mail; </othercredit> <othercredit role="developer" >&Ravikiran.Rajagopal; &Ravikiran.Rajagopal.mail; </othercredit> <othercredit role="translator" ><firstname >Иван</firstname ><surname >Кашуков</surname ><affiliation ><address ><email >dolphin210@yandex.ru</email ></address ></affiliation ><contrib >Перевод на русский</contrib ></othercredit ><othercredit role="translator" ><firstname >Николай</firstname ><surname >Шафоростов</surname ><affiliation ><address ><email >shafff@ukr.net</email ></address ></affiliation ><contrib >Обновление русского перевода</contrib ></othercredit > </authorgroup> <copyright> <year >2003</year> <holder >Teemu Rytilahti</holder> </copyright> <copyright> <year >2003-04</year> <holder >Ravikiran Rajagopal</holder> </copyright> <legalnotice >&FDLNotice;</legalnotice> <date >2003-01-10</date> <releaseinfo >1.01.00</releaseinfo> <abstract> <para >&ksplash; — симпатичный экран, показывающий процесс загрузки приложения</para> </abstract> <keywordset> <keyword >KDE</keyword> <keyword >kdebase</keyword> <keyword >ksplash</keyword> <keyword >ksplashml</keyword> <keyword >splashscreen</keyword> <keyword >eye candy</keyword> </keywordset> </bookinfo> <chapter id="introduction"> <title >Введение</title> <para >&ksplash; — симпатичный экран, показывающий процесс загрузки приложения. Вопросы и пожелания отправляйте в списки рассылки &kde;. Отличительные особенности &ksplash;: </para> <simplelist> <member >Возможность применения тем</member> <member >Высокая гибкость в настройке обеспечивается использованием подключаемых модулей</member> <member >Программа может быть использована любым приложением, которое работает с DCOP</member> </simplelist> <para >Это руководство объясняет, как создавать темы для использования с уже доступными подключаемыми модулями. Если ни один из доступных модулей не удовлетворяет вашему вкусу, вы можете научиться полностью настраивать внешний вид &ksplash;, создавая подключаемые модули на C++. </para> </chapter> <chapter id="using-themes"> <title >Использование тем</title> <para >Чтобы использовать темы с <ulink url="http://www.kde-look.org" >KDE-Look</ulink >, скопируйте их в <filename >~/.kde/apps/ksplash/Themes/</filename > (для одного пользователя) или в <filename >$<envar >KDEDIR</envar >/share/apps/ksplash/Themes/</filename > (чтобы сделать их доступными для всех пользователей вашей системы).</para> <para >Чтобы сделать это автоматически, используйте модуль <guilabel >Экран загрузки</guilabel > раздела <guilabel >Внешний вид</guilabel > Центра управления &kde;.</para> <sect1 id="using-kcontrol-module"> <title >Модуль Центра управления</title> <para >Этот модуль позволяет устанавливать, тестировать и удалять темы &ksplash;.</para> <para >Внизу расположен список доступных тем &ksplash;. При выборе одной из последних, её предварительный просмотр появится в соответствующей части окна. Чтобы активировать тему, нажмите <guibutton >OK</guibutton > или <guibutton >Применить</guibutton >.</para> <para >Чтобы установить новые модули, нажмите <guibutton >Добавить...</guibutton >. Не нужно распаковывать файлы тем, они могут обрабатываться и в сжатом виде.</para> <para >Для просмотра анимации темы, нажмите кнопку<guibutton >Тест</guibutton >.</para> <para >Чтобы удалить тему, воспользуйтесь кнопкой <guibutton >Удалить</guibutton >. Если тема установлена для всех пользователей, то удалять её нужно с правами администратора. Также, мы не рекомендуем удалять тему <guilabel >по умолчанию</guilabel >.</para> </sect1> </chapter> <chapter id="themes"> <title >Как создавать темы для &ksplash;</title> <sect1 id="themes-general"> <title >Основные положения</title> <para >Создавать свои собственные темы для &ksplash; достаточно легко. Когда вы закончили свою тему, вы можете отослать её в <ulink url="http://www.kde-look.org" >KDE-Look</ulink >, чтобы её могли использовать другие.</para> <sect2 id="theme-syntax"> <title >Определение своей темы</title> <para >Давайте создадим тему под названием <literal >MyCoolTheme</literal >. Чтобы тема была распознана &ksplash;, следует поместить её в папку <filename class="directory" >MyCoolTheme</filename > в каталоге <filename class="directory" >~/.kde/apps/ksplash/Themes/</filename >. В ней должен содержаться файл <filename >Theme.rc</filename >, содержащий настройки темы. Вы можете установить множество особенностей для темы, изменить движок подключаемых модулей и т. д. Не обязательно использовать все доступные настройки, обычно используются только некоторые. Синтаксис записей файла <filename >Theme.rc</filename >: <literal >[опция] = [значение]</literal >. В последующих секциях определяется множество опций.</para> <example> <title >Простой файл <filename >Theme.rc</filename ></title> <programlisting >[KSplash Theme: MyCoolTheme] Name = MyCoolTheme Description = Симпатичная тема, использующая движок XpLike Version = 1.0 Author = Настоящее имя <имя_пользователя@имя_сервера.домен> ## Use the XpLike engine for this theme. Engine = XpLike Show Icon = false Welcome Text = Загрузка KDE </programlisting> </example> <para >После того как вы задали имя, описание и автора темы, вам следует выбрать движок темы (подключаемый модуль). Затем вы сможете настроить разнообразные характеристики движка темы, устанавливая пары опция=значение, как в вышеприведённом файле.</para> <para >Важно чтобы имя папки, в которой хранятся файлы темы (<filename class="directory" >~/.kde/apps/ksplash/Themes/MyCoolTheme</filename >) и идентификатор (<literal >[KSplash Theme: MyCoolTheme] </literal >) в <filename >Theme.rc</filename > совпадали. </para> </sect2> <sect2 id="theme-files"> <title >Файлы фона</title> <para >При запуске &ksplash; пытается найти файл фона, соответствующий текущему разрешению экрана (если файл используется движком темы). Формат названия файла фона: <filename >Background-<replaceable >WWWxHHH</replaceable >.png</filename >.</para> <para >Например, вам надо использовать файл <filename >Background-1024x768</filename >. Если файл, соответствующий текущему разрешению экрана, не найден, программа пытается изменить размер файла <filename >Background.png</filename > (или другого, заданного в <filename >Theme.rc</filename >) так, чтобы он соответствовал разрешению. Изменение размера <quote >на лету</quote > занимает некоторое время, так что вам следует создать файлы как минимум для следующих разрешений экрана: 1280x1024, 1024x768 и 800x600.</para> </sect2> </sect1> <sect1 id="theme-engines"> <title >Опции движков тем</title> <sect2 id="standard-themes"> <title >Стандартная тема</title> <table> <title >Опции стандартной темы</title> <tgroup cols="3"> <tbody> <row> <entry >Название</entry> <entry >Аргумент</entry> <entry >Значение</entry> </row> <!-- Statusbar --> <row> <entry >Statusbar Position</entry> <entry >[top/bottom]</entry> <entry >Определяет расположение индикатора состояния на экране. Значение по умолчанию — bottom (внизу).</entry> </row> <row> <entry >Statusbar Visible</entry> <entry >[true/false]</entry> <entry >Определяет, будет ли индикатор состояния видимым. Значение по умолчанию — true (истина).</entry> </row> <row> <entry >Progress Visible</entry> <entry >[true/false]</entry> <entry >Определяет, будет ли показан прогресс загрузки. Значение по умолчанию — true.</entry> </row> <!-- Fonts --> <row> <entry >Statusbar Font</entry> <entry >[название_шрифта]</entry> <entry >Шрифт, используемый в индикаторе состояния (по умолчанию — Helvetica).</entry> </row> <row> <entry >Statusbar Font Size</entry> <entry >[размер]</entry> <entry >Размер шрифта индикатора состояния (по умолчанию — 16).</entry> </row> <row> <entry >Statusbar Font Bold</entry> <entry >[true/false]</entry> <entry >Определяет, будет ли шрифт индикатора состояния полужирным (по умолчанию — true).</entry> </row> <row> <entry >Statusbar Font Italic</entry> <entry >[true/false]</entry> <entry >Определяет, будет ли шрифт индикатора состояния наклонным (по умолчанию -true).</entry> </row> <!-- Misc. things --> <row> <entry >Statusbar Foreground</entry> <entry >[цвет]</entry> <entry >Цвет переднего плана индикатора состояния. Значение по умолчанию — white (белый).</entry> </row> <row> <entry >Statusbar Background</entry> <entry >[цвет]</entry> <entry >Цвет фона индикатора состояния. Значение по умолчанию — black (чёрный).</entry> </row> <row> <entry >Statusbar Icon</entry> <entry >[true/false]</entry> <entry >Определяет, будет ли пиктограмма у индикатора состояния.</entry> </row> <row> <entry >Icons Visible</entry> <entry >[true/false]</entry> <entry >Определяет, будут ли пиктограммы видимыми. Значение по умолчанию — true.</entry> </row> <row> <entry >Icons Jumping</entry> <entry >[true/false]</entry> <entry >Определяет, будут ли пиктограммы прыгающими. Значение по умолчанию — true.</entry> </row> <row> <entry >Icon Position</entry> <entry >[0-3, 10-13]</entry> <entry >Расположение пиктограмм (по умолчанию — вверху слева).</entry> </row> <row> <entry >Splash Screen</entry> <entry >[название]</entry> <entry >Изменяет образ отображаемого экрана.</entry> </row> </tbody> </tgroup> </table> </sect2> <sect2 id="redmond-themes"> <title >Тема Redmond</title> <table> <title >Опции темы Redmond</title> <tgroup cols="3"> <tbody> <row> <entry >Название</entry> <entry >Аргумент</entry> <entry >Значение</entry> </row> <!-- Main elements --> <row> <entry >Background Image</entry> <entry >[имя_файла]</entry> <entry >Определяемый пользователем фоновый рисунок.</entry> </row> <row> <entry >User Icon</entry> <entry >[название]</entry> <entry >Название пиктограммы, отображаемой для пользователя. По умолчанию — <constant >go</constant >.</entry> </row> <row> <entry >Welcome Text</entry> <entry >[текст]</entry> <entry >Текст, отображающийся на экране. По умолчанию — "Добро пожаловать".</entry> </row> <row> <entry >Username Text</entry> <entry >[текст]</entry> <entry >Текст, замещающий имя пользователя.</entry> </row> <!-- Positioning elements --> <row> <entry >Welcome Text Position</entry> <entry >[x,y]</entry> <entry >Область экрана, в которой отображается текст приглашения (определяемый опцией Welcome Text).</entry> </row> <row> <entry >Username Text Position</entry> <entry >[x,y]</entry> <entry >Область экрана, в которой отображается имя пользователя.</entry> </row> <row> <entry >Action Text Position</entry> <entry >[x,y]</entry> <entry >Область экрана, в которой отображается текущее действие.</entry> </row> <row> <entry >Icon Position</entry> <entry >[x,y]</entry> <entry >Область экрана, в которой отображается пиктограмма пользователя.</entry> </row> <!-- Show to show.. --> <row> <entry >Show Welcome Text</entry> <entry >[true/false]</entry> <entry >Определяет, будет ли отображаться текст приглашения (значение по умолчанию — true).</entry> </row> <row> <entry >Show Welcome Shadow</entry> <entry >[true/false]</entry> <entry >Определяет, будет ли отображаться тень текста приглашения (значение по умолчанию — true).</entry> </row> <row> <entry >Show Username</entry> <entry >[true/false]</entry> <entry >Определяет, будет ли отображаться имя пользователя (значение по умолчанию — true).</entry> </row> <row> <entry >Show Action</entry> <entry >[true/false]</entry> <entry >Определяет, будет ли отображаться действие, выполняемое в данный момент. Значение по умолчанию — true.</entry> </row> <row> <entry >Show Icon</entry> <entry >[true/false]</entry> <entry >Определяет, будет ли отображаться пиктограмма. Значение по умолчанию — true.</entry> </row> <row> <entry >Use KDM User Icon</entry> <entry >[true/false]</entry> <entry >Определяет, будет ли использоваться пиктограмма, соответствующая пользователю при входе в систему. Значение по умолчанию — true.</entry> </row> </tbody> </tgroup> </table> </sect2> <sect2 id="macx-themes"> <title >Тема MacX</title> <table> <title >Опции темы MacX</title> <tgroup cols="3"> <tbody> <row> <entry >Название</entry> <entry >Аргумент</entry> <entry >Значение</entry> </row> <row> <entry >Icon Size Minimum</entry> <entry >[размер]</entry> <entry >Минимальный размер пиктограммы (по умолчанию — 16).</entry> </row> <row> <entry >Icon Size Maximum</entry> <entry >[размер]</entry> <entry >Максимальный размер пиктограммы (по умолчанию — 64).</entry> </row> <row> <entry >Optimized Icon Rendering</entry> <entry >[true/false]</entry> <entry >Будет ли оптимизироваться отрисовка пиктограмм (значение по умолчанию — true).</entry> </row> <row> <entry >Progress Bar Visible</entry> <entry >[true/false]</entry> <entry >По умолчанию — true.</entry> </row> <row> <entry >Progress Bar Position</entry> <entry >[top/bottom]</entry> <entry >Определяет расположение индикатора состояния (внизу или вверху). По умолчанию - bottom (внизу).</entry> </row> <row> <entry >Icons Jumping</entry> <entry >[true/false]</entry> <entry >Определяет, будут ли пиктограммы прыгающими (по умолчанию — false).</entry> </row> </tbody> </tgroup> </table> </sect2> <sect2 id="mac-classic-themes"> <title >Тема MacClassic</title> <table> <title >Опции темы MacClassic</title> <tgroup cols="3"> <tbody> <row> <entry >Название</entry> <entry >Аргумент</entry> <entry >Значение</entry> </row> <row> <entry >Icon Position</entry> <entry >[0-3, 10-13]</entry> <entry >Расположение пиктограмм на экране, по умолчанию — внизу слева.</entry> </row> <row> <entry >Icons Jumping</entry> <entry >[true/false]</entry> <entry >Определяет, будут ли пиктограммы прыгающими (по умолчанию — false).</entry> </row> <row> <entry >Icons Visible</entry> <entry >[true/false]</entry> <entry >Определяет, будут ли пиктограммы видимыми. Значение по умолчанию — true.</entry> </row> <row> <entry >Splash Screen</entry> <entry >[название]</entry> <entry >Изменяет образ отображаемого экрана.</entry> </row> </tbody> </tgroup> </table> </sect2> <sect2 id="themes-2k"> <title >Тема 2k</title> <table> <title >Опции темы 2k</title> <tgroup cols="3"> <tbody> <row> <entry >Название</entry> <entry >Аргумент</entry> <entry >Значение</entry> </row> <row> <entry >Title Background Color</entry> <entry >[цвет]</entry> <entry >Фоновый цвет заголовка, по умолчанию — dark blue (тёмно-синий).</entry> </row> <row> <entry >Title Foreground Color</entry> <entry >[цвет]</entry> <entry >Цвет переднего плана заголовка. По умолчанию — white (белый).</entry> </row> <row> <entry >Status Text Color</entry> <entry >[цвет]</entry> <entry >Цвет текста состояния. По умолчанию соответствует фоновому тексту заголовка (определяемому опцией Title Background Color).</entry> </row> <row> <entry >Rotator Color 1</entry> <entry >[цвет]</entry> <entry >Определяет цвет индикатора 1. По умолчанию — dark blue, тёмно-синий.</entry> </row> <row> <entry >Rotator Color 2</entry> <entry >[цвет]</entry> <entry >Определяет цвет индикатора 2, по умолчанию — светло-серый (cyan).</entry> </row> <row> <entry >Rotator Speed</entry> <entry >[значение]</entry> <entry >Определяет скорость индикатора, по умолчанию — 30.</entry> </row> <row> <entry >Window Title</entry> <entry >[текст]</entry> <entry >Определяет текст заголовка окна.</entry> </row> <row> <entry >Logo File</entry> <entry >[имя_файла]</entry> <entry >Определяет используемый логотип.</entry> </row> </tbody> </tgroup> </table> </sect2> </sect1> </chapter> <chapter id="from-other-applications"> <title >Использование &ksplash; в вашем собственном приложении</title> <para >В этой главе описывается простой метод использования &ksplash; в качестве окна-показателя загрузки в вашем приложении для &kde;. Если вы не разрабатываете приложения для &kde;, вы можете опустить эту главу.</para> <sect1 id="basic-other-reqs"> <title >Основные требования</title> <para >Ваше приложение &kde; должно работать с &DCOP;. &DCOP; — это технология &kde;, использующаяся для коммуникации между приложениями. Если вы используете <ulink url="http://developer.kde.org" >стандартную структуру приложения &kde;</ulink >, это обеспечивается автоматически. Чтобы получить информацию о &DCOP; и связанных технологиях &kde;, посетите <ulink url="http://developer.kde.org" >сайт разработчиков &kde;</ulink >.</para> </sect1> <sect1 id="other-using"> <title >Запуск &ksplash;</title> <para >До того, как ваше приложение начнёт вычисления, загрузку подключаемых модулей и т. д., запустите &ksplash;. Образец:</para> <programlisting >DCOPClient *c = kapp->dcopClient(); QString error; QCString KSplashName; int pid = 0; QStringList args; args << "--theme=MyCoolTheme" << "--managed"; if (kapp->startServiceByDesktopName("ksplash", args, &error, &KSplashName, &pid)) { KMessageBox::sorry(0, error, "Unable to invoke KSplash"); // Some error processing here. } </programlisting> <para >Мы предполагаем, что запущено только одно окно &ksplash;. Другие случаи немного более сложны. Разъяснения см. в документации &DCOP;.</para> </sect1> <sect1 id="show-messages"> <title >Отображение сообщений</title> <para >Перед отображением сообщений вам необходимо установить число шагов. Например, процедура запуска &kde; включает 7 этапов.</para> <programlisting >QByteArray data; QDataStream arg(data,IO_WriteOnly); arg << someNumber; if (!(c->send(KSplashName, "KSplashIface", "setStartupItemCount(int)", data)) // Здесь проявляется некоторая ошибка. </programlisting> <para >Если вы хотите, чтобы сообщение отображалось с пиктограммой или без неё, используйте</para> <programlisting >arg << QString("название_пиктограммы") << QString("название_программы") << QString("некоторое описание"); if (!(c->send(KSplashName, "KSplashIface", "programStarted(QString,QString,QString)", data)) { // Здесь проявляется некоторая ошибка. } </programlisting> <para >Каждый раз, когда вы вызываете <constant >programStarted</constant >, шаги заканчиваются. Когда ваша программа закончила запуск, выполните следующие команды, чтобы убрать экран загрузки:</para> <programlisting >if (!(c->send(KSplashName, "KSplashIface", "startupComplete()", data)) { // Здесь проявляется некоторая ошибка. } </programlisting> <para >Это всё, что вам необходимо, чтобы использовать все преимущества &ksplash;.</para> </sect1> </chapter> <!-- FIXME: Better to leave this out until it's written, or the translators --> <!-- will have to still translate it ... --> <chapter id="wrplugins"> <title >Создание новых подключаемых модулей &ksplash;</title> <para >Создавать подключаемые модули &ksplash; нетрудно. В этой главе мы напишем простой модуль, который эмулирует экран загрузки одной очень известной операционной системы. Предполагается, что вы знакомы с основами языка C++, и хотя бы немного — с программированием для KDE/Qt.</para> <sect1 id="basic-requirements"> <title >Основные требования</title> <para >Мы создадим модуль с названием <literal >2k</literal >. Название используется во многих местах. Важно не исказить его, чтобы модуль был распознан &ksplash;. Модули &ksplash; являются динамически загружаемыми библиотеками со следующими объявлениями: </para> <simplelist> <member >Библиотеку следует называть по образцу: <filename >ksplash+название_темы_в_нижнем_регистре</filename >. В нашем случае название будет <filename >ksplash2k</filename >.</member> <member >Тема должна иметь свой desktop-файл, который следует назвать <filename >ksplash+название_темы_в_нижнем_регистре.desktop</filename >. В нашем случае — <filename >ksplash2k.desktop</filename >. </member> <member >Наконец, библиотека должна возвращать класс с названием <literal >Theme+название_темы</literal >, в нашем случае — <literal >Theme2k</literal >.</member> </simplelist> <para >Не беспокойтесь, если вы не поняли всё вышесказанное. Далее мы рассмотрим каждый шаг в деталях. Важной деталью является то, что класс модуля вы должны взять из <literal >ThemeEngine</literal >. </para> </sect1> <sect1 id="skeleton"> <title >Создание основы</title> <para >При создании модуля мы будем использовать основу для приложения &kde;, которая обеспечит независимость от платформы во всех частях нашей работы. Убедитесь, что в вашей системе установлен пакет <filename >kdesdk</filename >. Выполните команду <literal >kapptemplate</literal >, чтобы создать приложение с названием "2k". Будет создана папка, содержащая основные файлы (такие как AUTHORS и т. п.). Нам нужен подкаталог <filename class="directory" >2k</filename >. Удалите все файлы в нём, и основа готова. </para> <para >На следующем этапе вы должны создать файл <filename >.desktop</filename >, который, после установки, сообщит &ksplash;, что подключаемый модуль доступен. В соответствии с правилами наименования файлов, которые даны <link linkend="basic-requirements" >в предыдущей секции</link >, создайте файл <filename >ksplash2k.desktop</filename > (в каталоге /2k). Он должен содержать следующие строки: </para> <programlisting ><literal> [Desktop Entry] Encoding=UTF-8 Type=Service Comment=KSplash Plugin Name=KSplash2k ServiceTypes=KSplash/Plugin X-KDE-Library=ksplash2k X-KSplash-Default=true X-KSplash-PluginName=2k X-KSplash-ObjectName=Theme2k </literal > </programlisting> <para >Опции <literal >Encoding</literal >, <literal >Type</literal >, <literal >Comment</literal > и <literal >ServiceTypes</literal > одинаковы для всех подключаемых модулей. Название модуля и библиотеки следуют вышеописанным правилам. Опция <literal >X-KSplash-Default</literal > может принимать одно из двух значений (true или false). Она определяет, будет ли этот модуль показан в Центре управления как модуль по умолчанию. За исключением некоторых очень редких случаев, его значение должно быть <constant >true</constant >. </para> </sect1> <sect1 id="headerfile"> <title >Объявление класса подключаемого модуля</title> <para >Теперь, когда мы закончили подготовительную работу, начинается действительно интересная часть — создание класса, который обеспечивает нужное поведение модуля. Хотя мы вольны делать с этим классом всё, что хотим, существует несколько ограничений.</para> <orderedlist> <listitem ><para >Классы модуля должны соответствовать классу <constant >ThemeEngine</constant >.</para ></listitem> <listitem ><para >Классы модуля следует называть в соответствии с правилом: <classname >Тема+название_модуля</classname >.</para ></listitem> <listitem ><para >Классы модуля должны обеспечивать <literal >статическую</literal > функцию с названием <function >names</function >, которая возвращает список названий, под которыми она может быть задействована.</para ></listitem> <listitem ><para >Чтобы модуль можно было настраивать из Центра управления, он должен включать класс, основанный на классе <literal >ThemeEngineConfig</literal >.</para ></listitem> <listitem ><para >Классы модуля должны перекрывать хотя бы одну из следующих виртуальных функций: <function >slotSetText</function >, <function >slotSetPixmap</function >, <function >slotUpdateProgress</function > и <function >slotUpdateSteps</function >, чтобы обеспечить возможность использования.</para ></listitem> <listitem ><para >Разработчик должен использовать форму <literal >ThemeEngine( QWidget *parent, символьную постоянную *name, постоянную QStringList &args )</literal >, чтобы модуль можно было использовать с <classname >KGenericFactory</classname >.</para ></listitem> </orderedlist> <para >Последнее требование может показаться сложным, но, как мы увидим позже, вы можете обычно игнорировать его, добавив одну строку к исходным кодам.</para> </sect1> <sect1 id="headercode"> <title >Код файла заголовка</title> <para >Присвоив значения константам, мы увидим, что файл заголовков <filename >theme2k.h</filename > приобретёт вид вроде этого:</para> <example> <title >Файл <filename >theme2k.h</filename ></title> <programlisting >#ifndef __THEME2K_H__ #define __THEME2K_H__ #include <qlabel.h> #include <qwidget.h> #include <kdialogbase.h> #include <kpixmap.h> #include <ksplash/themeengine.h> class RotWidget; class Cfg2k: public ThemeEngineConfig { Q_OBJECT public: Cfg2k( KConfig * ); }; class ObjKsTheme; class Theme2k: public ThemeEngine { Q_OBJECT public: Theme2k( QWidget *, const char *, const QStringList& ); inline const QString name() { return( QString("KSplash2k") ); } inline const KDialogBase *config( KConfig *kc ) { return new Cfg2k( kc ); } static QStringList names() { QStringList Names; Names << "KSplash2k"; Names << "ks2k"; Names << "2k"; Names << "2000"; return( Names ); }; public slots: inline void slotSetText( const QString& s ) { if( mText && mText->text() != s ) mText->setText( s ); }; private: void initUi(); void readSettings(); QLabel *mText; RotWidget *mRotator; QColor mTBgColor, mTFgColor, mRotColor1, mRotColor2, mStatusColor; int mRotSpeed; QString mWndTitle, mLogoFile; }; #endif </programlisting> </example> <para >Давайте проанализируем вышеприведённое. Класс <classname >Theme2k</classname >, произведённый от <classname >ThemeEngine</classname > удовлетворяет объявлениям. Он обеспечивает метод <methodname >Theme2k::names()</methodname >, и имеет конструктор, который принимает необходимые параметры: <function >Theme2k( QWidget *, const char *, const QStringList& );</function >, и к тому же обеспечивает простой метод <methodname >Theme2k::slotSetText()</methodname >. На данном этапе вам не следует беспокоиться насчёт класса <classname >RotWidget</classname >. Это небольшой элемент графического интерфейса, который делает программу более наглядной для пользователя. Наш подключаемый модуль очень прост: он не отображает ни пиктограмм, ни шкалы загрузки. Если вы хотите использовать пиктограммы, перекройте функцию <function >slotSetPixmap</function >. Подобные функции есть для установки шкалы загрузки (<function >slotUpdateSteps</function >) и увеличения счётчика (<function >slotUpdateProgress</function >) текущего шага. </para> </sect1> <sect1 id="Implementation"> <title >Реализация подключаемого модуля</title> <para >Мы проверим только связанные части реализации. В приложении находится описание всей реализации. В первую очередь нам необходимо удовлетворить требованиям библиотеки:</para> <example> <title >Требования библиотеки</title> <programlisting >K_EXPORT_COMPONENT_FACTORY( ksplash2k, KGenericFactory<Theme2k> ); </programlisting> </example> <para >Объявление макроса <constant >K_EXPORT_COMPONENT_FACTORY</constant > содержится в файле <filename >kgenericfactory.h</filename >. Теперь перейдём к конструктору. Так как подключаемый модуль совсем прост, конструктор тоже несложен.</para> <example> <title >Конструктор подключаемого модуля</title> <programlisting >Theme2k::Theme2k( QWidget *parent, const char *name, const QStringList &args ) :ThemeEngine( parent, name, args ) { readSettings(); initUi(); } </programlisting> </example> <para >Метод <function >readSettings()</function > является иллюстрацией подходящего способа получить настройки темы (вы ведь хотите, чтобы люди могли использовать ваш модуль для своих тем?)</para> <example> <title >Получение настроек темы</title> <programlisting >void Theme2k::readSettings() { if( !mTheme ) return; KConfig *cfg = mTheme->themeConfig(); if( !cfg ) return; cfg->setGroup( QString("KSplash Theme: %1").arg(mTheme->theme()) ); QColor DefaultTBgColor( Qt::darkBlue ); QColor DefaultTFgColor( Qt::white ); mTBgColor = cfg->readColorEntry( "Title Background Color", &DefaultTBgColor ); mTFgColor = cfg->readColorEntry( "Title Foreground Color", &DefaultTFgColor ); mStatusColor = cfg->readColorEntry("Status Text Color", &mTBgColor ); QColor DefaultRot1( Qt::darkBlue ); QColor DefaultRot2( Qt::cyan ); mRotColor1 = cfg->readColorEntry( "Rotator Color 1", &DefaultRot1 ); mRotColor2 = cfg->readColorEntry( "Rotator Color 2", &DefaultRot2 ); mRotSpeed = cfg->readNumEntry( "Rotator Speed", 30 ); mWndTitle = cfg->readEntry( "Window Title", i18n("Please wait...") ); mLogoFile = cfg->readEntry( "Logo File", QString::null ); } </programlisting> </example> <para >Так как мы работаем для пользователей, следует обеспечить подходящие настройки по умолчанию для параметров, которые не представлены в файле темы. Обратите внимание, что группу следует устанавливать следующим образом: "KSplash Theme: название_темы", чтобы обеспечить совместимость с будущими спецификациями темы. Метод <function >initUI()</function > не представляет большого интереса, он просто организует элементы графического интерфейса. Детали см. в приложении. </para> </sect1> <sect1 id="compilingfile"> <title >Компиляция подключаемого модуля</title> <para >Для компиляции модуля мы решили использовать основу &kde;, поэтому необходимо создать файл <filename >Makefile.am</filename >. Он должен выглядеть следующим образом:</para> <example> <title >Файл <filename >Makefile.am</filename ></title> <programlisting >INCLUDES = $(all_includes) kde_module_LTLIBRARIES = ksplash2k.la ksplash2k_la_SOURCES = theme2k.cpp rotwidget.cpp ksplash2k_la_LDFLAGS = $(all_libraries) $(KDE_RPATH) ksplash2k_la_LIBADD = $(LIB_KDEUI) -lksplashthemes METASOURCES = AUTO noinst_HEADERS = theme2k.h rotwidget.h servicesdir = $(kde_servicesdir) services_DATA = ksplash2k.desktop themedir = $(kde_datadir)/ksplash/Themes/2k theme_DATA = Theme.rc Preview.png </programlisting> </example> <para >Чтобы получить дальнейшую информацию по созданию <filename >Makefile.am</filename >, загляните на <ulink url="http://developer.kde.org/documentation/other/makefile_am_howto.html" >веб-сайт</ulink > разработчиков &kde;. Заметим, что мы создаём тему по умолчанию, основанную на этом модуле, и прилагаем к нему графический файл фона. В качестве жеста вежливости по отношению к пользователям создайте файл <filename >Theme.rc</filename >, являющийся примером использования опций.</para> </sect1> </chapter> <chapter id="faq"> <title >Вопросы и ответы</title> &reporting.bugs; &updating.documentation; <qandaset id="faqlist"> <qandaentry> <question> <para >Я не могу найти ни одной темы, которая работала бы с &ksplash;. Почему?</para> </question> <answer> <para >Возможно, у вас нет соответствующих подключаемых модулей для тем. Модули содержатся в пакете <literal >kde-artwork</literal >. Скачайте, установите его и попытайтесь запустить темы снова.</para> </answer> </qandaentry> <qandaentry> <question> <para >Что такое файл <filename >Theme.rc</filename > и как его создать?</para> </question> <answer> <para ><filename >Theme.rc</filename > — это файл, где вы можете задать настройки темы. Информация по нему находится в разделе <link linkend="themes" >Как создавать темы для &ksplash;</link >. </para> </answer> </qandaentry> </qandaset> </chapter> <chapter id="credits"> <title >Благодарности и лицензирование</title> <para >&ksplash;</para> <para >Авторские права на программу принадлежат © 2003 &Ravikiran.Rajagopal; &Ravikiran.Rajagopal.mail;</para> <itemizedlist> <title >Помощь в разработке</title> <listitem ><para >&Brian.C.Ledbetter; &Brian.C.Ledbetter.mail;</para> </listitem> </itemizedlist> <para >Документация © 2003 &Teemu.Rytilahti; &Teemu.Rytilahti.mail;</para> &underFDL; &underGPL; </chapter> <appendix id="installation"> <title >Установка</title> <sect1 id="requirements"> <title >Системные требования</title> <para >Чтобы иметь возможность использовать возможности &ksplash; вам необходим оконный менеджер &kde; версии 3.2 или выше. Если тема не работает, свяжитесь с её автором, чтобы выяснить, где можно взять подходящий подключаемый модуль.</para> </sect1> <sect1 id="compilation"> <title >Сборка и установка</title> &install.compile.documentation; </sect1> </appendix> <appendix id="srccode"> <title >Исходные коды</title> <sect1 id="theme2kcpp"> <title >Файл <filename >theme2k.cpp</filename ></title> <programlisting >#include <qlabel.h> #include <qwidget.h> #include <kapplication.h> #include <kconfig.h> #include <kdebug.h> #include <kdialogbase.h> #include <kgenericfactory.h> #include <kglobalsettings.h> #include <klocale.h> #include <ksplash/objkstheme.h> #include <kstandarddirs.h> #include "rotwidget.h" #include "theme2k.h" #include "theme2k.moc" K_EXPORT_COMPONENT_FACTORY( ksplash2k, KGenericFactory<Theme2k> ); Cfg2k::Cfg2k( KConfig * ) {} Theme2k::Theme2k( QWidget *parent, const char *name, const QStringList &args ) :ThemeEngine( parent, name, args ) { readSettings(); initUi(); } void Theme2k::initUi() { QVBox *vbox = new QVBox( this ); vbox->setFrameShape( QFrame::WinPanel ); vbox->setFrameShadow( QFrame::Raised ); QHBox *labelBox = new QHBox( vbox ); labelBox->setPalette( mTBgColor ); labelBox->setMargin( 1 ); QLabel *lbl = new QLabel( mWndTitle, labelBox ); lbl->setFont( QFont( "Arial", 12, QFont::Bold ) ); lbl->setPaletteForegroundColor( mTFgColor ); QLabel *logo = new QLabel( vbox ); logo->setPalette( Qt::white ); QString px( locate( "appdata", mTheme->themeDir() + (mLogoFile.isNull()?QString("/Logo.png"):mLogoFile) ) ); if (px.isNull()) px = locate("appdata","Themes/Default/splash_top.png"); if( !px.isNull() ) { QPixmap pix( px ); logo->setPixmap( pix ); } else { logo->setText( "<B>KDE</B>2000" ); logo->setAlignment( AlignCenter|AlignVCenter ); } mRotator = new RotWidget( vbox, mRotColor1, mRotColor2, mRotSpeed ); QHBox *hbox = new QHBox( vbox ); labelBox->setSpacing( 4 ); labelBox->setMargin( 4 ); mText = new QLabel( hbox ); mText->setPaletteForegroundColor( mStatusColor ); mText->setPaletteBackgroundColor( mTFgColor ); mText->setText( mWndTitle ); mText->setFixedHeight( 48 ); setFixedSize( vbox->sizeHint() ); QRect rect(KGlobalSettings::splashScreenDesktopGeometry()); move( rect.x() + (rect.width() - size().width())/2, rect.y() + (rect.height() - size().height())/2 ); } void Theme2k::readSettings() { if( !mTheme ) return; KConfig *cfg = mTheme->themeConfig(); if( !cfg ) return; cfg->setGroup( QString("KSplash Theme: %1").arg(mTheme->theme()) ); QColor DefaultTBgColor( Qt::darkBlue ); QColor DefaultTFgColor( Qt::white ); mTBgColor = cfg->readColorEntry( "Title Background Color", &DefaultTBgColor ); mTFgColor = cfg->readColorEntry( "Title Foreground Color", &DefaultTFgColor ); mStatusColor = cfg->readColorEntry("Status Text Color", &mTBgColor ); QColor DefaultRot1( Qt::darkBlue ); QColor DefaultRot2( Qt::cyan ); mRotColor1 = cfg->readColorEntry( "Rotator Color 1", &DefaultRot1 ); mRotColor2 = cfg->readColorEntry( "Rotator Color 2", &DefaultRot2 ); mRotSpeed = cfg->readNumEntry( "Rotator Speed", 30 ); mWndTitle = cfg->readEntry( "Window Title", i18n("Please wait...") ); mLogoFile = cfg->readEntry( "Logo File", QString::null ); } </programlisting> </sect1> <sect1 id="rotwidgeth"> <title >Файл <filename >rotwidget.h</filename ></title> <programlisting >#ifndef __ROTWIDGET_H__ #define __ROTWIDGET_H__ #include <qlabel.h> #include <qtimer.h> #include <qwidget.h> #include <kdialogbase.h> #include <kpixmap.h> /** * @short Display a rotating-gradient widget. */ class RotWidget: public QWidget { Q_OBJECT public: RotWidget( QWidget *, const QColor&, const QColor&, int ); ~RotWidget(); private slots: void stepEvent(); protected: void preparePixmap( int ); void paintEvent( QPaintEvent * ); void resizeEvent( QResizeEvent * ); QColor m_color1, m_color2; int m_step, m_speed; QTimer *m_stepTimer; QList<KPixmap> m_stepPixmap; }; #endif </programlisting> </sect1> <sect1 id="rotwidgetcpp"> <title >Файл <filename >rotwidget.cpp</filename ></title> <programlisting >#include <kdebug.h> #include <kdialogbase.h> #include <kpixmapeffect.h> #include <qlabel.h> #include <qpainter.h> #include <qwidget.h> #include "rotwidget.h" #include "rotwidget.moc" RotWidget::RotWidget( QWidget *parent, const QColor& c1, const QColor& c2, int sp ) :QWidget(parent), m_color1(c1), m_color2(c2), m_step(0), m_speed(sp) { if( (m_speed <= 0) || (m_speed > 20) ) m_speed = 1; setFixedHeight( 6 ); for( int i = 0; i <= width(); i++ ) preparePixmap( i ); m_stepTimer = new QTimer( this ); connect(m_stepTimer, SIGNAL(timeout()), this, SLOT(stepEvent())); m_stepTimer->start( 50 ); } RotWidget::~RotWidget() { } void RotWidget::stepEvent() { // This is inefficient as we create too many pixmaps, optimize later. m_step += m_speed; if( m_step > width() ) m_step = 0; repaint( true ); } // Todo: Optimize drawing. void RotWidget::paintEvent( QPaintEvent *pe ) { QPainter p; p.begin( this ); QRect r = pe->rect(); if( m_stepPixmap.at( m_step ) ) bitBlt( this, r.x(), r.y(), m_stepPixmap.at( m_step ), r.x(), r.y(), r.width(), r.height() ); else p.fillRect( rect(), Qt::black ); p.end(); } void RotWidget::resizeEvent( QResizeEvent *re ) { m_stepPixmap.clear(); for( int i = 0; i <= re->size().width(); i++ ) preparePixmap( i ); } void RotWidget::preparePixmap( int step ) { if( step < 0 ) return; // Explicitly draw our first pixmap. The rest we will bitBlt() from here. if( step == 0 ) { KPixmap tmp; tmp.resize( size().width() / 2, size().height() ); KPixmap tmp2(tmp); KPixmapEffect::gradient( tmp, m_color1, m_color2, KPixmapEffect::HorizontalGradient ); KPixmapEffect::gradient( tmp2, m_color2, m_color1, KPixmapEffect::HorizontalGradient ); KPixmap *px = new KPixmap( size() ); QPainter p; p.begin( px ); p.drawPixmap( 0, 0, tmp ); p.drawPixmap( size().width()/2, 0, tmp2 ); p.end(); m_stepPixmap.append( px ); } else if( m_stepPixmap.at( step-1 ) ) { QPixmap *prev = m_stepPixmap.at( step-1 ); QPixmap next; next.resize( size() ); // convert // prev = "[------------]" // to // next = "------------][" bitBlt( &next, 0, 0, prev, 1, 0, prev->width()-1, prev->height() ); bitBlt( &next, width()-1, 0, prev, 0, 0, 1, prev->height() ); KPixmap *n = new KPixmap( next ); m_stepPixmap.append( n ); } } </programlisting> </sect1> </appendix> &documentation.index; </book> <!-- Local Variables: mode: xml sgml-minimize-attributes:nil sgml-general-insert-case:lower sgml-indent-step:0 sgml-indent-data:nil End: vim:tabstop=2:shiftwidth=2:expandtab -->