# Руководство пользователя &ksplash;

&Teemu.Rytilahti; &Teemu.Rytilahti.mail;
&Brian.C.Ledbetter; &Brian.C.Ledbetter.mail;
&Ravikiran.Rajagopal; &Ravikiran.Rajagopal.mail;
Иван Кашуков

    dolphin210@yandex.ru

Перевод на русский язык
Николай Шафоростов

    shafff@ukr.net

Обновление перевода
Виктор Ерёмин

    ErV2005@rambler.ru

Перевод на русский язык
2003 Teemu Rytilahti
2003-04 Ravikiran Rajagopal
&FDLNotice;
2003-01-10
1.01.00

&ksplash; — симпатичный экран, показывающий процесс загрузки среды KDE.

KDE kdebase ksplash ksplashml заставка украшение

## Введение

&ksplash; — симпатичный экран, показывающий процесс загрузки KDE. Вопросы и пожелания отправляйте в списки рассылки &kde;. Отличительные особенности &ksplash;:

- Возможность применения тем
- Высокая гибкость в настройке обеспечивается использованием подключаемых модулей
- Программа может быть использована любым приложением, которое работает с DCOP

Это руководство объясняет, как создавать темы для использования с уже доступными подключаемыми модулями. Если ни один из доступных модулей не удовлетворяет вашему вкусу, вы можете научиться полностью настраивать внешний вид &ksplash;, создавая подключаемые модули на C++.

## Использование тем

Чтобы использовать темы с KDE-Look, скопируйте их в `~/.kde/apps/ksplash/Themes/` (для одного пользователя) или в `$`KDEDIR`/share/apps/ksplash/Themes/` (чтобы сделать их доступными для всех пользователей вашей системы).

Чтобы сделать это автоматически, используйте модуль Заставка раздела Внешний вид и темы Центра управления &kde;.

### Модуль Центра управления

Этот модуль позволяет устанавливать, проверять и удалять темы &ksplash;.

Внизу расположен список доступных тем &ksplash;. При выборе одной из последних, её предварительный просмотр появится в соответствующей части окна. Чтобы активировать тему, нажмите OK или Применить.

Чтобы установить новые модули, нажмите Добавить.... Не нужно распаковывать файлы тем, они могут обрабатываться и в сжатом виде.

Для просмотра анимации темы, нажмите кнопкуТест.

Чтобы удалить тему, воспользуйтесь кнопкой Удалить. Если тема установлена для всех пользователей, то удалять её нужно с правами администратора. Также, мы не рекомендуем удалять тему «По умолчанию».

## Как создавать темы для &ksplash;

### Основные положения

Создавать свои собственные темы для &ksplash; достаточно легко. Когда вы закончили свою тему, вы можете отправить её на KDE-Look, чтобы её могли использовать другие.

#### Определение своей темы

Давайте создадим тему под названием `MyCoolTheme`. Чтобы тема была найдена &ksplash;, следует поместить её в папку `MyCoolTheme` в папке `~/.kde/apps/ksplash/Themes/`. В ней должен содержаться файл `Theme.rc`, содержащий настройки темы. Вы можете установить множество особенностей для темы, изменить движок подключаемых модулей и т. д. Не обязательно использовать все доступные параметры, обычно используются только некоторые. Синтаксис записей файла `Theme.rc`: `[параметр] = [значение]`. Параметры описаны в следующих разделах.

Простой файл `Theme.rc`

    [KSplash Theme: MyCoolTheme]
    Name = MyCoolTheme
    Description = Симпатичная тема, использующая движок XpLike
    Version = 1.0
    Author = Имя автора <realmail@mail.com>
    ## Используйте движок XpLike для этой темы.
    Engine = XpLike
    Show Icon = false
    Welcome Text = Загрузка KDE

После того как вы задали имя, описание и автора темы, вам следует выбрать движок темы (подключаемый модуль). Затем вы сможете настроить разнообразные характеристики движка темы, устанавливая пары параметр=значение, как в вышеприведённом файле.

Важно, чтобы имя папки, в которой хранятся файлы темы (`~/.kde/apps/ksplash/Themes/MyCoolTheme` в данном примере) и идентификатор (`[KSplash Theme: MyCoolTheme]` в данном примере) в `Theme.rc` совпадали. В противном случае, &ksplash; не распознает тему.

#### Файлы фона

При запуске &ksplash; пытается найти файл фона, соответствующий текущему разрешению экрана (если файл используется движком темы). Формат названия файла фона: `Background-WWWxHHH.png`, где WWW-ширина, а HHH-высота изображения.

Например, вам надо использовать файл `Background-1024x768`. Если файл, соответствующий текущему разрешению экрана, не найден, программа пытается изменить размер файла `Background.png` (или другого, заданного в `Theme.rc`) так, чтобы он соответствовал разрешению. Изменение размера на лету занимает некоторое время, так что вам следует создать файлы как минимум для следующих разрешений экрана: 1280x1024, 1024x768 и 800x600.

### Параметры движков тем

#### Тема, используемая по умолчанию

Настройка темы по умолчанию

Параметр | Значение | Описание
Always Show Progress | [true/false] | Определяет, будет ли показан прогресс загрузки. Значение по умолчанию — true.
Label Foreground | [цвет] | Цвет текста индикатора состояния. Значение по умолчанию — white (белый, #FFFFFF).
Icons Flashing | [true/false] | Определяет, будут ли мерцать значки. По умолчанию — true (да).

#### Стандартная тема

Параметры стандартной темы

Параметр | Значение | Описание
Statusbar Position | [top/bottom] | Определяет расположение индикатора состояния на экране. Значение по умолчанию — bottom (внизу).
Statusbar Visible | [true/false] | Определяет, будет ли индикатор состояния видимым. Значение по умолчанию — true (да).
Progress Visible | [true/false] | Определяет, будет ли показан прогресс загрузки. Значение по умолчанию — true.
Statusbar Font | [шрифт] | Шрифт, используемый в индикаторе состояния. Значение по умолчанию — Helvetica.
Statusbar Font Size | [размер] | Размер шрифта индикатора состояния. Значение по умолчанию — 16 пт.
Statusbar Font Bold | [true/false] | Определяет, будет ли шрифт индикатора состояния полужирным. Значение по умолчанию — true (да).
Statusbar Font Italic | [true/false] | Определяет, будет ли шрифт индикатора состояния курсивным. Значение по умолчанию — false (нет).
Statusbar Foreground | [цвет] | Цвет переднего плана индикатора состояния. Значение по умолчанию — white (белый).
Statusbar Background | [цвет] | Цвет фона индикатора состояния. Значение по умолчанию — black (чёрный).
Statusbar Icon | [true/false] | Определяет, будет ли значок у индикатора состояния.
Icons Visible | [true/false] | Определяет, будут ли значки видимыми. Значение по умолчанию — true (да).
Icons Jumping | [true/false] | Определяет, будут ли прыгать значки. Значение по умолчанию — true (да).
Icon Position | [0-3, 10-13] | Расположение значков. Значение по умолчанию — вверху слева.
Splash Screen | [название] | Название заставки.

#### Тема Redmond

Параметры темы Redmond

Параметр | Значение | Описание
Background Image | [имя_файла] | Определяемое пользователем фоновое изображение.
User Icon | [имя_значка] | Имя значка пользователя. Значение по умолчанию — `go`.
Welcome Text | [текст] | Текст, показываемый на экране. Значение по умолчанию — «Добро пожаловать».
Username Text | [текст] | Текст, замещающий имя пользователя.
Welcome Text Position | [x,y] | Область экрана, в которой показывается текст приглашения (определяемый параметром «Welcome Text»).
Username Text Position | [x,y] | Область экрана, в которой показывается имя пользователя.
Action Text Position | [x,y] | Область экрана, в которой показывается текущее действие.
Icon Position | [x,y] | Область экрана, в которой показывается значок пользователя.
Show Welcome Text | [true/false] | Определяет, будет ли показываться текст приглашения. Значение по умолчанию — true (да).
Show Welcome Shadow | [true/false] | Определяет, будет ли показываться тень под текстом приглашения. Значение по умолчанию — true (да).
Show Username | [true/false] | Определяет, будет ли показываться имя пользователя. Значение по умолчанию — true (да).
Show Action | [true/false] | Определяет, будет ли показываться действие, выполняемое в данный момент. Значение по умолчанию — true (да).
Show Icon | [true/false] | Определяет, будет ли показываться значок пользователя. Значение по умолчанию — true (да).
Use KDM User Icon | [true/false] | Определяет, будет ли использоваться значок, соответствующий пользователю при входе в систему. Значение по умолчанию — true (да).

#### Тема MacX

Параметры темы MacX

Параметр | Значение | Описание
Icon Size Minimum | [размер] | Минимальный размер значков. Значение по умолчанию — 16 пикселей.
Icon Size Maximum | [размер] | Максимальный размер значков. Значение по умолчанию — 64 пикселя.
Optimized Icon Rendering | [true/false] | Будет ли оптимизироваться отрисовка значков. Значение по умолчанию — true (да).
Progress Bar Visible | [true/false] | По умолчанию — true (да).
Progress Bar Position | [top/bottom] | Определяет расположение индикатора состояния (внизу или вверху). По умолчанию - bottom (внизу).
Icons Jumping | [true/false] | Определяет, будут ли прыгать значки. Значение по умолчанию — false (нет).

#### Тема MacClassic

Параметры темы MacClassic

Параметр | Значение | Описание
Icon Position | [0-3, 10-13] | Расположение значков на экране. Значение по умолчанию — внизу слева.
Icons Jumping | [true/false] | Определяет, будут ли прыгать значки. Значение по умолчанию — false (нет).
Icons Visible | [true/false] | Определяет, будут ли значки видимыми. Значение по умолчанию — true (да).
Splash Screen | [название] | Название заставки.

#### Тема 2k

Параметры темы 2k

Параметр | Значение | Описание
Title Background Color | [цвет] | Фоновый цвет заголовка. Значение по умолчанию — dark blue (тёмно-синий).
Title Foreground Color | [цвет] | Цвет переднего плана заголовка. Значение по умолчанию — white (белый).
Status Text Color | [цвет] | Цвет текста состояния. По умолчанию соответствует фоновому тексту заголовка (определяемому параметром «Title Background Color»).
Rotator Color 1 | [цвет] | Определяет цвет индикатора 1. Значение по умолчанию — dark blue (тёмно-синий).
Rotator Color 2 | [цвет] | Определяет цвет индикатора 2. Значение по умолчанию — cyan (циан).
Rotator Speed | [значение] | Определяет скорость индикатора. Значение по умолчанию — 30.
Window Title | [текст] | Определяет текст заголовка окна.
Logo File | [имя_файла] | Определяет используемый логотип.

## Использование &ksplash; в вашем собственном приложении

В этой главе описывается простой метод использования &ksplash; в качестве заставки для вашего приложения &kde;. Если вы не разрабатываете приложения для &kde;, вы можете опустить эту главу.

### Основные требования

Ваше приложение &kde; должно работать с &DCOP;. &DCOP; — это технология &kde;, использующаяся для коммуникации между приложениями. Если вы используете стандартную структуру приложения &kde;, это обеспечивается автоматически. Чтобы получить информацию о &DCOP; и связанных технологиях &kde;, посетите сайт разработчиков &kde;.

### Запуск &ksplash;

До того, как ваше приложение начнёт вычисления, загрузку подключаемых модулей и т.д., запустите &ksplash;. Образец:

    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, "Невозможно запустить KSplash");
      //обработка ошибок.
    }

Мы предполагаем, что запущено только одно окно &ksplash;. Другие случаи немного более сложны. Разъяснения смотрите в документации &DCOP;.

### Показ сообщений

Перед показом сообщений вам необходимо установить число шагов. Например, процедура запуска &kde; включает 7 этапов.

    QByteArray data;
        QDataStream arg(data,IO_WriteOnly);
        arg << someNumber;
        if (!(c->send(KSplashName, "KSplashIface", "setStartupItemCount(int)",
    data))
          // Обработка ошибок.

Если вы хотите, чтобы сообщение связывалось с соответствующим значком или без него, используйте

    arg << QString("имя_значка") << QString("название_программы") <<
    QString("какое-то описание");
        if (!(c->send(KSplashName, "KSplashIface",
    "programStarted(QString,QString,QString)", data))
        {
          // Обработка ошибок.
        }

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

    if (!(c->send(KSplashName, "KSplashIface", "startupComplete()", data))
        {
          // Обработка ошибок.
        }

Это всё, что вам необходимо, чтобы использовать все преимущества &ksplash;.

## Создание новых подключаемых модулей &ksplash;

Создавать подключаемые модули &ksplash; нетрудно. В этой главе мы напишем простой модуль, который эмулирует экран загрузки одной очень известной операционной системы. Предполагается, что вы знакомы с основами языка C++ и хотя бы немного — с программированием для KDE/Qt.

### Основные требования

Мы создадим модуль с названием `2k`. Название используется во многих местах. Важно не исказить его, чтобы модуль был распознан &ksplash;. Модули &ksplash; являются динамически загружаемыми библиотеками со следующими объявлениями:

- Библиотеку следует называть по образцу: `ksplash+название_темы_в_нижнем_регистре`. В нашем случае название будет `ksplash2k`.
- Тема должна иметь свой файл desktop, который следует назвать `ksplash+название_темы_в_нижнем_регистре.desktop`. В нашем случае — `ksplash2k.desktop`.
- Наконец, библиотека должна возвращать класс с названием `Theme+название_темы`, в нашем случае — `Theme2k`.

Не беспокойтесь, если вы не поняли всё вышесказанное. Далее мы рассмотрим каждый шаг в деталях. Важной деталью является то, что класс модуля вы должны взять из `ThemeEngine`.

### Создание основы

При создании модуля мы будем использовать основу для приложения &kde;, которая обеспечит независимость от платформы во всех частях нашей работы. Убедитесь, что в вашей системе установлен пакет `kdesdk`. Выполните команду `kapptemplate`, чтобы создать приложение с названием "2k". Будет создана папка, содержащая основные файлы (такие как AUTHORS и т.п.). Нам нужна подпапка `2k`. Удалите все файлы в ней, и основа готова.

На следующем этапе вы должны создать файл `.desktop`, который, после установки, сообщит &ksplash;, что подключаемый модуль доступен. В соответствии с правилами наименования файлов, которые даны в предыдущей секции, создайте файл `ksplash2k.desktop`. Он должен содержать следующие строки:

    [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

Параметры `Encoding`, `Type`, `Comment` и `ServiceTypes` одинаковы для всех подключаемых модулей. Название модуля и библиотеки следуют вышеописанным правилам. Параметр `X-KSplash-Default` может принимать одно из двух значений (true или false). Он определяет, будет ли этот модуль показан в Центре управления KDE. За исключением некоторых очень редких случаев, его значение должно быть `true`.

### Объявление класса подключаемого модуля

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

1. Классы модуля должны наследоваться от класса `ThemeEngine`.

2. Классы модуля следует называть в соответствии с правилом: Theme+название_модуля.

3. Классы модуля должны обеспечивать `статическую` функцию с названием `names`, которая возвращает список названий, под которыми она может быть задействована.

4. Чтобы модуль можно было настраивать из Центра управления KDE, он должен включать класс, основанный на классе `ThemeEngineConfig`.

5. Классы модуля должны перекрывать хотя бы одну из следующих виртуальных функций: `slotSetText`, `slotSetPixmap`, `slotUpdateProgress` и `slotUpdateSteps`, чтобы обеспечить возможность использования.

6. Разработчик должен создать конструктор `ThemeEngine( QWidget *parent, const char *name, const QStringList &args )`, чтобы модуль можно было использовать из KGenericFactory.

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

### Код файла заголовка

Присвоив значения константам, мы увидим, что файл заголовков `theme2k.h` приобретёт вид вроде этого:

Файл `theme2k.h`

    #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

Давайте проанализируем вышеприведённое. Класс Theme2k, унаследованный от ThemeEngine удовлетворяет объявлениям. Он обеспечивает метод Theme2k::names(), и имеет конструктор, который принимает необходимые параметры: `Theme2k( QWidget *, const char *, const QStringList& );`, и к тому же обеспечивает простой метод Theme2k::slotSetText(). На данном этапе вам не следует беспокоиться насчёт класса RotWidget. Это небольшой элемент графического интерфейса, который делает программу более наглядной для пользователя. Наш подключаемый модуль очень прост: он не показывает ни значков, ни индикатора загрузки. Если вы хотите использовать значки, перекройте функцию `slotSetPixmap`. Подобные функции есть для установки индикатора загрузки (`slotUpdateSteps`) и увеличения счётчика (`slotUpdateProgress`) текущего шага.

### Реализация подключаемого модуля

Мы проверим только связанные части реализации. В приложении находится описание всей реализации. В первую очередь нам необходимо удовлетворить требованиям библиотеки:

Требования библиотеки

    K_EXPORT_COMPONENT_FACTORY( ksplash2k, KGenericFactory<Theme2k> );

Объявление макроса `K_EXPORT_COMPONENT_FACTORY` содержится в файле `kgenericfactory.h`. Теперь перейдём к конструктору. Так как подключаемый модуль совсем прост, конструктор тоже несложен.

Конструктор подключаемого модуля

    Theme2k::Theme2k( QWidget *parent, const char *name, const QStringList &args
     )
        :ThemeEngine( parent, name, args )
    {
      readSettings();
      initUi();
    }

Метод `readSettings()` является иллюстрацией подходящего способа получить параметры темы (вы ведь хотите, чтобы люди могли использовать ваш модуль для своих тем?)

Получение параметров темы

    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 );
    }

Так как мы работаем для пользователей, следует обеспечить подходящие параметры по умолчанию для параметров, которые не представлены в файле темы. Обратите внимание, что группу следует устанавливать следующим образом: "KSplash Theme: название_темы", чтобы обеспечить совместимость с будущими спецификациями темы. Метод `initUI()` не представляет большого интереса, он просто организует элементы графического интерфейса. Детали указаны в приложении.

### Компиляция подключаемого модуля

Для компиляции модуля мы решили использовать основу &kde;, поэтому необходимо создать файл `Makefile.am`. Он должен выглядеть следующим образом:

Файл `Makefile.am`

    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

Чтобы получить дальнейшую информацию по созданию `Makefile.am`, загляните на веб-сайт разработчиков &kde;. Заметим, что мы создаём тему по умолчанию, основанную на этом модуле, и прилагаем к нему графический файл фона. В качестве жеста доброй воли по отношению к пользователям создайте файл `Theme.rc`, иллюстрирующий примеры использования различных параметров.

## Вопросы и ответы

&reporting.bugs; &updating.documentation;

Я не могу найти ни одной темы, которая работала бы с &ksplash;. Почему?

Возможно, у вас нет соответствующих подключаемых модулей для тем. Модули содержатся в пакете `kdeartwork`. Скачайте, установите его и попытайтесь запустить темы снова.

Что такое файл `Theme.rc` и как его создать?

`Theme.rc` — это файл, где вы можете задать параметры темы. Информация по нему находится в разделе Как создавать темы для &ksplash;.

## Благодарности и лицензирование

&ksplash;

Программа: © &Ravikiran.Rajagopal; &Ravikiran.Rajagopal.mail;, 2003.

Помощь в разработке

- &Brian.C.Ledbetter; &Brian.C.Ledbetter.mail;

Документация: © &Teemu.Rytilahti; &Teemu.Rytilahti.mail;, 2003.

&underFDL; &underGPL;

## Установка

### Системные требования

Чтобы иметь возможность использовать возможности &ksplash; вам необходим &kde; версии 3.2 или выше. Если тема не работает, свяжитесь с её автором, чтобы выяснить, где можно взять подходящий подключаемый модуль.

### Сборка и установка

&install.compile.documentation;

## Исходные коды

### Файл `theme2k.cpp`

    #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 );
    }

### Файл `rotwidget.h`

    #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

### Файл `rotwidget.cpp`

    #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 );
      }
    }

&documentation.index;