<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook V3.1-Based Variant V1.0//EN" [
 <!ENTITY kdevelop "<application>kdevelop</application>">
 <!ENTITY tex "<application>TeX</application>">
 <!ENTITY latex "<application>LaTeX</application>">
 <!ENTITY etago "&lt;/">
 <!ENTITY % addindex "IGNORE">
 <![ %addindex; [ <!ENTITY docindex SYSTEM "docindex.docbook"> ]]>
]>
<book lang="ru">
<bookinfo>
<title>KDevelop. Руководство программиста
</title>
<subtitle>Руководство по разработке приложений на C++ для K Desktop Environment (KDE) с использованием KDevelop IDE, Version
1.0</subtitle>
<authorgroup>
<author>
<surname>Ralf Nolden </surname>
<affiliation>
	  <orgname>Команда разработчиков KDevelop</orgname>
<address><email><ulink url="mailto:Ralf.Nolden@post.rwth-aachen.de">&lt;Ralf.Nolden@post.rwth-aachen.de&gt;</ulink></email></address>
</affiliation>
</author>
</authorgroup>
<date>Version 2.1 , July 7, 1999</date>
<releaseinfo><!-- information about this particular version --></releaseinfo>
<abstract>
<para>Это руководство - часть интегрированной среды разработки KDevelop, и, следовательно, на него распространяется GNU General
Public License; см. <link linkend="Copyright">Copyright</link> для получения более детальной информации.</para>
<para>KDE</para><!-- Merge this with the previous paragraph; it comes from <META NAME="description" CONTENT="..."> --></abstract>

</bookinfo>

<chapter id="vvedenie">
<title>Введение</title>

<para>По мере того, как Unix системы становятся все более и более популярными даже для начинающих пользователей благодаря своим преимуществам с точки зрения
стабильности и функциональности, многих как-то разочаровывает то, что Unix приложения не имеют надлежащего оформления и каждое
ведет себя по-своему. KDE дает разработчикам почти совершенный путь для создания первоклассных приложений для Unix систем, которые
они смогут предложить широким пользовательским массам. Таким образом, KDE становится все более и более популярной как основа для разработки программ,
и разработчики стремятся извлечь все преимущества из возможностей, предлагаемых этой системой.</para>

<sect1 id="chto-vy-dolzhny-znat">
<title>Что вы должны знать</title>

<para>При написании этой книги мы предполагали, что вы уже владеете языком программирования C++; если это не так, вы
должны его освоить в первую очередь. Информация о C++ доступна из многих источников как в печатной форме в ваших книжных магазинах,
так и в электронном виде через Internet. Знания о разработке графического пользовательского интерфейса не являются необходимыми, так как
это руководство пытается охватить процесс разработки программ для KDE, что включает в себя введение в инструментарий Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>, библиотеки KDE <indexterm remap="idx"><primary>библиотеки KDE</primary></indexterm> и
разработку пользовательского интерфейса. Будет хорошо, если вы чувствуете себя комфортно с KDevelop. Для этого можно прочитать 
"Руководство пользователя KDevelop" ("The User Manual to KDevelop"), 
которое содержит описание функций, предоставляемых IDE.</para>
</sect1>

<sect1 id="ob-etoi-knige">
<title>Об этой книге</title>

<para>Эта книга написана для разработчиков как введение в процесс создания приложений для KDE с использованием интегрированной среды разработки KDevelop.</para>

<para>Следующие главы дают представление о том, как создавать проекты, объясняют автоматически сгенерированный исходник и показывают, как
расширить данный код в различных направлениях - панель инструментов <indexterm remap="idx"><primary>панель инструментов</primary></indexterm>, панель меню и рабочая область приложения. </para>

<para>Затем в деталях рассматривается редактор диалоговых окон. Объясняется, как создаются элементы (widget), и подробно рассматриваются
установки свойств для всех предоставляемых элементов.</para>

<para>Наконец, вы узнаете еще о некоторых полезных вещах, что завершит ваше обучение в области разработки проекта и поможет вам освоить
выполнение таких проектных работ, как создание API <indexterm remap="idx"><primary>API</primary></indexterm> документации и online-документации.</para>

<para><emphasis remap="bf">В следующей главе</emphasis></para>

<para>мы рассмотрим Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> и библиотеки KDE <indexterm remap="idx"><primary>библиотеки KDE</primary></indexterm>, рассмотрим базовые концепции и поймем, почему все так, а не иначе.
Также мы обсудим, как создать учебные приложения, поставляемые с Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> инструментарием, используя KDevelop, после чего начинающие 
смогут увидеть первые результаты после первых шагов, и почувствовать преимущества использования KDevelop.</para>

<para><emphasis remap="bf">В дальнейших главах</emphasis> вы разберетесь:
<itemizedlist>
<listitem>
<para>как создавать приложения с помощью KAppWizard,</para>
</listitem>
<listitem>
<para>что предоставляет вам скелет проекта,</para>
</listitem>
<listitem>
<para>что делает автоматически созданный код,</para>
</listitem>
<listitem>
<para>как создавать свои собственные формы (views),</para>
</listitem>
<listitem>
<para>как расширить функциональность ваших приложений с помощью диалоговых окон, панелей меню и панелей инструментов <indexterm remap="idx"><primary>панелей инструментов</primary></indexterm>,</para>
</listitem>
<listitem>
<para>как сделать ваши приложения более дружественными, реализовав систему помощи,</para>
</listitem>
<listitem>
<para>как писать SGML <indexterm remap="idx"><primary>SGML</primary></indexterm> online документацию.</para>
</listitem>
</itemizedlist>
</para>
</sect1>

<sect1 id="dopolnitelnaia-informatsiia">
<title>Дополнительная информация</title>

<para>Дополнительная информация о Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>/KDE программировании доступна из многих источников:</para>

<para><itemizedlist>
<listitem>
<para><emphasis>Programming with Qt <indexterm remap="idx"><primary>Qt</primary></indexterm></emphasis> by Matthias Kalle Dalheimer, опубликована изд. O'Reilly (см. <ulink url="http://www.oreilly.com">\|\|</ulink>), рассматривает
почти все аспекты Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> GUI инструментария и содержит множество примеров.</para>
</listitem>
<listitem>
<para>"Руководство пользователя KDevelop" ("The User Manual to KDevelop"), поставляется вместе с KDevelop IDE,</para>
</listitem>
<listitem>
<para><emphasis>Online-Reference</emphasis> по Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>-библиотеке, предоставляемая вместе с копией вашего Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> инструментария 
в HTML и доступная в формате PostScript на <ulink url="http://www.troll.no">\|\|</ulink></para>
</listitem>
<listitem>
<para>В Internet смотрите
<itemizedlist>
<listitem>
<para>Troll Tech web site - <ulink url="http://www.troll.no">\|\|</ulink>,</para>
</listitem>
<listitem>
<para>KDE web site - <ulink url="http://www.kde.org">\|\|</ulink>,</para>
</listitem>
<listitem>
<para>KDE developer web site - <ulink url="http://developer.kde.org">\|\|</ulink></para>
</listitem>
<listitem>
<para>Домашняя страница KDevelop - <ulink url="http://www.kdevelop.org">\|\|</ulink></para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>

<para>Кроме того, вы можете получить помощь, подписавшись на различные mail-листы, адреса которых имеются на упомянутых
сайтах, и в Usenet группах новостей, посвященных KDE, Unix, программированию на C и C++.</para>

<para>Для получения помощи о KDevelop IDE вы можете послать запрос в наш mail-лист
<ulink url="mailto:kdevelop@fara3.cs.uni-potsdam.de">kdevelop@fara3.cs.uni-potsdam.de</ulink>. 
Имейте в виду, что команда разработчиков KDevelop предоставляет возможность
вам заниматься разработкой приложений и, следовательно, не является командой технической поддержки в случае,
если разработанное вами приложение не работает в связи с ошибками реализации или неверной конфигурацией операционной системы. Учитывая это, мы просим
всех пользователей обращаться к услугам mail-листа в случаях, когда вы сталкиваетесь с проблемами использования собственно IDE, а также
для сообщения нам об ошибках и предложениях по повышению функциональности среды разработки.</para>
</sect1>
</chapter>

<chapter id="kde-i-qt-qt-biblioteki">
<title>KDE и Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> Библиотеки</title>

<para>Норвежская компания Troll Tech (<ulink url="http://www.troll.no">\|\|</ulink>) предоставляет так называемый 
GUI инструментарий (toolkit), именуемый Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>. GUI означает "<emphasis remap="bf">Г</emphasis>рафический <emphasis remap="bf">П</emphasis>ользовательский <emphasis remap="bf">И</emphasis>нтерфейс"
("<emphasis remap="bf">G</emphasis>raphical <emphasis remap="bf">U</emphasis>ser <emphasis remap="bf">I</emphasis>nterface"), поэтому базирующиеся на Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> приложения представляются кнопками, окнами и т.п.
Такие приложения осуществляют взаимодействие с пользователем, представляя в визуальной форме выполняемые функции.
Этот инструментарий необходим для разработки графических приложений, которые используют
X-Window интерфейс в Unix системах, потому что X не содержит предопределенного пользовательского интерфейса.
И хотя другие наборы инструментов также позволяют создавать пользовательский интерфейс, Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> предоставляет некоторые технические возможности, которые делают разработку приложений
очень простой. Кроме того, 
Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> инструментарий также доступен для Microsoft Windows систем, что позволяет разработчикам
выпускать приложения для обеих платформ.</para>

<para>Команда KDE (<ulink url="http://www.kde.org">\|\|</ulink>) объединилась вместе с целью сделать Unix
системы более дружественными для пользователя, и решила использовать набор инструментов
Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> для разработки оконного менеджера для X-Window, плюс различных приложений,
включенных в дистрибутив KDE.
K Desktop Environment, таким образом, включает оконный менеджер <emphasis>kwm</emphasis>, 
менеджер файлов <emphasis>kfm</emphasis> и панель задач <emphasis>kpanel</emphasis> как главные компоненты, а также
массу первоклассных утилит и приложений. После выхода KDE множество
разработчиков обратили свои взоры к новой графической среде и к тому, что она предлагала.
Библиотеки KDE <indexterm remap="idx"><primary>Библиотеки KDE</primary></indexterm> предоставляют все необходимые
методы и классы, которые делают процесс разработки приложений с их помощью однотипным и согласованным, и положение пользователя резко улучшается, так
как он теперь должен разбираться только в специфике использования данного приложения, а не обучаться общим использования очередного варианта пользовательского интерфейса.
Кроме того, KDE программы интегрируются в рабочую среду и предоставляют возможность взаимодействовать
с менеджером файлов, используя drag'n drop <indexterm remap="idx"><primary>drag'n drop</primary></indexterm>, предоставляют возможность управления сеансами (session management) и многое другое, 
если разработчик реализовал все возможности, предоставляемые библиотеками KDE <indexterm remap="idx"><primary>библиотеками KDE</primary></indexterm>.</para>

<para>И Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> инструментарий, и библиотеки KDE <indexterm remap="idx"><primary>библиотеки KDE</primary></indexterm> реализованы с использованием языка программирования C++; 
поэтому большинство приложений, которые используют эти библиотеки, также написаны на C++.
В последующих главах мы бегло ознакомимся с библиотеками, чтобы увидеть, что
за инструмент нам предлагается и как вообще создаются Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> и KDE  <indexterm remap="idx"><primary>KDE </primary></indexterm> приложения.</para>

<sect1 id="qt-qt-gui-instrumentarii">
<title>Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> GUI инструментарий</title>

<para>Как уже говорилось, Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> библиотека - это инструментарий, который предоставляет 
графические элементы, используемые для создания GUI приложений, и который необходим 
при разработке программ для X-Window. Кроме того, Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> предоставляет:</para>

<para><itemizedlist>
<listitem>
<para> Широкий набор классов и методов, пригодных для использования даже для программ без графического интерфейса,</para>
</listitem>
<listitem>
<para> Хорошее решение для реализации взаимодействия с пользователем посредством виртуальных методов и механизма сигнал/слот,</para>
</listitem>
<listitem>
<para> Набором предопределенных GUI-элементов, называемых "widgets", которые могут быть легко использованы для создания видимых элементов,</para>
</listitem>
<listitem>
<para> Дополнительные полностью предопределенные диалоговые окна, которые часто используются в приложениях, такие как окно прогресса и окно выбора файлов.</para>
</listitem>
</itemizedlist>
</para>

<para>Знание Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> классов очень необходимо, даже если вы хотите разрабатывать только KDE-приложения. Чтобы получить первое представление
о том, как GUI-приложения конструируются и компилируются, мы рассмотрим простую, основанную исключительно на использовании Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> программу; 
затем мы расширим ее до KDE-приложения.</para>

<sect2 id="pervoe-qt-qt-prilozhenie">
<title>Первое Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> приложение</title>

<para>Как правило, программа на C++ должна содержать функцию <literal remap="tt">main()</literal>, которая является стартовой точкой для выполнения приложения. 
Так как мы хотим, чтобы наше приложение отображалось в графическом окне и предоставляло возможность взаимодействия с пользователем, первое, что мы должны знать, - как оно может показать себя
пользователю. Посмотрим, например, на первую программу, включенную в учебник, поставляемый как часть Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> Online Reference Documentation,
и объясним основные шаги выполнения. 
Итак, почему и как появляется окно приложения:</para>

<para><screen>#include &lt;qapplication.h&gt;
#include &lt;qpushbutton.h&gt;

int main( int argc, char **argv )
{
QApplication a( argc, argv );

QPushButton hello( "Hello world!" );
hello.resize( 100, 30 );

a.setMainWidget( &&amp;;hello );
hello.show();
return a.exec();
}
</screen>
</para>

<para>Это приложение просто рисует окно, содержащее кнопку с надписью "Hello world".  Как и для всех основанных на Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> приложений, вы первым делом
создаете экземпляр (instance) класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication</literal>, представленный переменной <literal remap="tt">a</literal>.</para>

<para>Затем программа создает экземпляр класса <literal remap="tt">QPushButton</literal>, называемый <literal remap="tt">hello</literal>, это будет кнопка. 
Конструктор <literal remap="tt">hello</literal> получает строку в качестве параметра, которая представляет собой содержимое элемента, отображаемое как текст на кнопке.</para>

<para>Потом вызывается метод <literal remap="tt">resize()</literal> кнопки <literal remap="tt">hello</literal>. Это изменяет размер элемента по умолчанию (в данном случае
QPushButton), который при создании имел длину 100 пикселей и высоту 30 пикселей. Наконец, метод <literal remap="tt">setMainWidget()</literal>
вызывается для объекта <literal remap="tt">a</literal> и метод <literal remap="tt">show()</literal> -  для объекта <literal remap="tt">hello</literal>. <literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication</literal> выполняет вызов <literal remap="tt">a.exec()</literal>,
входя в главный цикл событий (main event loop) и ожидая, когда он должен будет вернуть значение integer операционной системе, сигнализируя,
что приложение завершилось.</para>
</sect2>

<sect2 id="spravochnaia-dokumentatsiia-dlia-qt-qt">
<title>Справочная документация для Qt <indexterm remap="idx"><primary>Qt</primary></indexterm></title>

<para>А сейчас мы кратко рассмотрим справочную документацию по Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> библиотеке. 
Для того, чтобы сделать это, запустите KDevelop и выберите "Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>-library" из
"Help"-меню на панели меню. Средство просмотра документации откроет и покажет вам стартовую страницу справочного руководства Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>. 
Это первое место, где необходимо искать информацию о Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>, его классах и доступных функциях. Кроме того, приведенная выше программа входит первой
в секцию "tutorials". Чтобы добраться к тем классам, которые мы хотим посмотреть,
<literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication</literal> и <literal remap="tt">QPushButton</literal>, выберите 
"Alphabetical Class List" и найдите соответствующие имена. Следуйте по любому из линков, чтобы посмотреть документацию
по соответствующему классу.</para>

<para>Для <literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication</literal> вы увидите конструктор и все другие методы, которые есть в данном классе.
Если вы нажмете на линк какого-либо метода, вы получите более детальную информацию об использовании этого метода,
которая бывает очень полезна, если вы не можете определить, как правильно использовать метод, или хотите увидеть пример.
Это также относится к документации по библиотекам KDE, которые используют похожую структуру; вот и почти все,
что вы должны знать о просмотре документации по классам с помощью браузера.</para>
</sect2>

<sect2 id="interpretatsiia-primera">
<title>Интерпретация примера</title>

<para>Просматривая <literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication</literal>, вы найдете все его методы, используемые в нашем примере:</para>

<para><itemizedlist>
<listitem>
<para>constructor <literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication()</literal>,</para>
</listitem>
<listitem>
<para><literal remap="tt">setMainWidget()</literal> метод и</para>
</listitem>
<listitem>
<para><literal remap="tt">exec()</literal> метод.</para>
</listitem>
</itemizedlist>
</para>

<para>Пояснения, почему мы используем эти методы, очень простые:</para>

<para><orderedlist><listitem>
<para>вначале создаем экземпляр класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication</literal> с помощью вызова конструктора, после этого мы можем использовать GUI элементы, предоставляемые Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>,</para>
</listitem>
<listitem>
<para>создаем элемент, который будет наполнением окна нашей программы,</para>
</listitem>
<listitem>
<para>устанавливаем этот элемент как главный элемент для <literal remap="tt">a</literal>,</para>
</listitem>
<listitem>
<para>выполняем экземпляр <literal remap="tt">a</literal> класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication</literal>.</para>
</listitem>
</orderedlist>
</para>

<para>Второй объект нашей программы - кнопка (pushbutton), экземпляр класса <literal remap="tt">QPushButton</literal>. Из двух конструкторов, предоставляемых
для создания объекта, мы выбрали второй: он принимает в качестве аргумента текст, который будет отображаться как метка на кнопке; в данном случае это строка
"Hello world!". Затем мы вызвали метод <literal remap="tt">resize()</literal> для изменения размеров кнопки в соответствии с размерами ее содержимого - кнопка должна быть больше, чтобы весь текст был видимым.</para>

<para>А как насчет метода <literal remap="tt">show()</literal>? Сейчас вы видите, что, как и большинство других элементов, <literal remap="tt">QPushButton</literal> основывается на одиночном наследовании (single-inheritance).
Документация говорит, что <literal remap="tt">QPushButton</literal> <emphasis>унаследована</emphasis> от <literal remap="tt"><indexterm remap="cdx"><primary><literal>QButton</literal></primary></indexterm>QButton</literal>.
Перейдем по линку на описание класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>QButton</literal></primary></indexterm>QButton</literal>. Это откроет множество других методов,
которые унаследованы QPushButton, мы воспользуемся ими позже для объяснения механизма сигнал/слот. В любом случае, метод <literal remap="tt">show()</literal>
не присутствует в списке, следовательно, это должен быть метод, передаваемый по наследству. Класс, от которого унаследован <literal remap="tt"><indexterm remap="cdx"><primary><literal>QButton</literal></primary></indexterm>QButton</literal>,
<literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>. Перейдя опять по ссылке, вы увидите целую связку методов, которые реализованы в классе <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>, включая
метод <literal remap="tt">show()</literal>. Теперь мы можем понять, что было сделано в примере с кнопкой:</para>

<para><orderedlist><listitem>
<para>создаем экземпляр <literal remap="tt">QPushButton</literal>, используя второй конструктор для установки текста на кнопке,</para>
</listitem>
<listitem>
<para>изменяем размер элемента в соответствии с размером его содержимого (текста),</para>
</listitem>
<listitem>
<para>делаем элемент главным элементом экземпляра <literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication</literal> <literal remap="tt">a</literal>,</para>
</listitem>
<listitem>
<para>говорим элементу показать себя на экране, вызывая его метод <literal remap="tt">show()</literal>, унаследованный от <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>.</para>
</listitem>
</orderedlist>
</para>

<para>После вызова метода <literal remap="tt">exec()</literal> приложение становится видимым для пользователя, отображая окно с кнопкой "Hello world!".
Таким образом, GUI программа кое в чем отличается от процедурного приложения. Основное здесь в том, что приложение входит
в так называемый "главный цикл событий" ("main event loop"). Это означает, что Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> приложение должно войти в главный цикл событий, чтобы начать обработку событий, потом программа ждет от пользователя действия и затем реагирует на него. 
Следующий раздел коротко описывает,
что это значит для программиста и какие средства представляет Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> для обработки пользовательских событий.</para>

<para>(Для уже опытных пользователей: Кнопка не имеет родителя, он не указан в конструкторе, поэтому она - единственный элемент верхнего уровня и 
работает в локальном цикле событий, и не нуждается во входе в глобальный цикл событий, см. документацию по классу <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>  и 
"The KDE Library Reference Guide")</para>

<para><emphasis remap="bf">Подведение итогов:</emphasis></para>

<para>Приложения Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> всегда создают экземпляр класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication</literal>. Это обеспечивает нам возможность создавать окна, которые
графически представляют программу пользователю и обеспечивают взаимодействие с ним. Содержимое окна называется Главный элемент ("Main Widget"). Это означает
что все графические элементы базируются на классе <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>, и могут быть любыми элементами, удовлетворяющими нужды приложения
в части связи с пользователем. Поэтому все пользовательские элементы, которые необходимо сделать видимыми, должны быть унаследованы от <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>.</para>
</sect2>

<sect2 id="user-interaction">
<title>Взаимодействие с пользователем</title>

<para>После прочтения последнего раздела вы должны уже знать:
<itemizedlist>
<listitem>
<para>что предоставляет библиотека Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> в терминах GUI приложения,</para>
</listitem>
<listitem>
<para>как создаются программы, использующие Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> и</para>
</listitem>
<listitem>
<para>где и как найти информацию о классах, которые вас интересуют, используя средство просмотра документации.</para>
</listitem>
</itemizedlist>
</para>

<para>А сейчас мы вдохнем в приложение "жизнь", научив его обрабатывать пользовательские события. Обычно пользователь имеет два средства для взаимодействия с программой:
мышь и клавиатуру. В обеих случаях, графический пользовательский интерфейс должен иметь методы для регистрации действия и методы,
которые делают что-то, реагируя на это действие.</para>

<para>Оконная система, таким образом, передает все сгенерированные пользователем события соответствующему приложению. <indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication затем передает их активному окну
как <literal remap="tt"><indexterm remap="cdx"><primary><literal>QEvent</literal></primary></indexterm>QEvent</literal> и элементы сами решают, что с ними делать. Элемент получает событие и выполняет
<literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget::event(<indexterm remap="cdx"><primary><literal>QEvent</literal></primary></indexterm>QEvent*)</literal>, который решает, какое событие произошло и как реагировать; <literal remap="tt">event()</literal>, следовательно,
является главным обработчиком событий. Затем функция <literal remap="tt">event()</literal> проводит событие через так называемый фильтр событий, который определяет, что случилось и что делать
с событием. Если ни один фильтр не распознал событие, вызывается специальный обработчик событий.
Таким образом, мы должны различать:</para>

<para><emphasis remap="bf">a) События клавиатуры -- клавиши TAB и  Shift-TAB :</emphasis></para>

<para>изменяет фокус ввода с клавиатуры с текущего элемента на следующий элемент в порядке изменения фокусов. Фокус может быть установлен для элемента
вызовом <literal remap="tt">setFocusPolicy<indexterm remap="ncdx"><primary><literal>setFocusPolicy()</literal></primary></indexterm>()</literal>. Изменение фокуса обрабатывается следующими обработчиками событий: :</para>

<para><itemizedlist>
<listitem>
<para><literal remap="tt">virtual void focusInEvent<indexterm remap="ncdx"><primary><literal>focusInEvent()</literal></primary></indexterm> ( <indexterm remap="cdx"><primary><literal>QFocusEvent</literal></primary></indexterm>QFocusEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void focusOutEvent<indexterm remap="ncdx"><primary><literal>focusOutEvent()</literal></primary></indexterm> ( <indexterm remap="cdx"><primary><literal>QFocusEvent</literal></primary></indexterm>QFocusEvent * )</literal></para>
</listitem>
</itemizedlist>
</para>

<para><emphasis remap="bf">b) другой ввод с клавиатуры:</emphasis>
<itemizedlist>
<listitem>
<para><literal remap="tt">virtual void keyPressEvent<indexterm remap="ncdx"><primary><literal>keyPressEvent()</literal></primary></indexterm> ( <indexterm remap="cdx"><primary><literal>QKeyEvent</literal></primary></indexterm>QKeyEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void keyReleaseEvent<indexterm remap="ncdx"><primary><literal>keyReleaseEvent()</literal></primary></indexterm> ( <indexterm remap="cdx"><primary><literal>QKeyEvent</literal></primary></indexterm>QKeyEvent * )</literal></para>
</listitem>
</itemizedlist>
</para>

<para><emphasis remap="bf">c) перемещение мыши:</emphasis>
<itemizedlist>
<listitem>
<para><literal remap="tt">virtual void mouseMoveEvent ( <indexterm remap="cdx"><primary><literal>QMouseEvent</literal></primary></indexterm>QMouseEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void enterEvent ( <indexterm remap="cdx"><primary><literal>QEvent</literal></primary></indexterm>QEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void leaveEvent ( <indexterm remap="cdx"><primary><literal>QEvent</literal></primary></indexterm>QEvent * )</literal></para>
</listitem>
</itemizedlist>
</para>

<para><emphasis remap="bf">d) нажатие кнопок мыши:</emphasis>
<itemizedlist>
<listitem>
<para><literal remap="tt">virtual void mousePressEvent ( <indexterm remap="cdx"><primary><literal>QMouseEvent</literal></primary></indexterm>QMouseEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void mouseReleaseEvent ( <indexterm remap="cdx"><primary><literal>QMouseEvent</literal></primary></indexterm>QMouseEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void mouseDoubleClickEvent ( <indexterm remap="cdx"><primary><literal>QMouseEvent</literal></primary></indexterm>QMouseEvent * )</literal></para>
</listitem>
</itemizedlist>
</para>

<para><emphasis remap="bf">e) события окна, содержащего элемент:</emphasis>
<itemizedlist>
<listitem>
<para><literal remap="tt">virtual void moveEvent ( <indexterm remap="cdx"><primary><literal>QMoveEvent</literal></primary></indexterm>QMoveEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void resizeEvent ( <indexterm remap="cdx"><primary><literal>QResizeEvent</literal></primary></indexterm>QResizeEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void closeEvent ( <indexterm remap="cdx"><primary><literal>QCloseEvent</literal></primary></indexterm>QCloseEvent * )</literal></para>
</listitem>
</itemizedlist>
</para>

<para>Заметьте, что все функции событий virtual и protected; таким образом, вы можете переопределить события, которые вам нужны в ваших элементах,
и указать, как ваш элемент должен на них реагировать. <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal> также содержит несколько других виртуальных методов, которые могут быть полезны в ваших программах; 
это, в общем-то, все, что вам сейчас необходимо знать о <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>.</para>
</sect2>

<sect2 id="vzaimodeistvie-obektov-s-pomoshchiu-signalov">
<title>Взаимодействие объектов с помощью сигналов и слотов</title>

<para>Сейчас мы подошли к наиболее яркому преимуществу Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> инструментария: механизм сигнал/слот. Этот механизм предлагает очень удобное и полезное 
решение для реализации взаимодействия объектов, которое обычно выполняется с помощью <literal remap="tt">callback</literal> функций для различных X-Window наборов элементов.
Реализация с помощью <literal remap="tt">callback</literal> функций требует очень строгого программирования и иногда превращает задачу построения пользовательского интерфейса в очень сложную
(как об этом говорится в документации Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> и как это объяснено в книге K.Dalheimer <emphasis>Programming with Qt <indexterm remap="idx"><primary>Qt</primary></indexterm></emphasis>).
Troll Tech изобрела новую систему, в которой объекты могут испускать (emit) сигналы,
которые могут быть соединены (connected) с методами, объявленными как слоты (slot).
Для программиста на C++ необходимо знать несколько простых вещей об этом механизме:</para>

<para><orderedlist><listitem>
<para>объявление класса, который использует сигналы/слоты, должно содержать макрос <literal remap="tt">Q&&lowbar;;OBJECT</literal> в начале (без ";");
и этот класс должен быть унаследован от <literal remap="tt">QObject</literal>.</para>
</listitem>
<listitem>
<para>сигнал может испускаться по ключевому слову <literal remap="tt">emit</literal>, например, <literal remap="tt">emit signal(parameters);</literal> из любой функции-члена класса, который поддерживает механизм сигнал/слот,</para>
</listitem>
<listitem>
<para>все сигналы, используемые классом и не унаследованные от предков, должны быть добавлены в объявление класса в секцию <literal remap="tt">signals:</literal>,</para>
</listitem>
<listitem>
<para>все методы, которые могут быть соединены с сигналами, должны быть объявлены в секциях с дополнительным ключевым словом <literal remap="tt">slot</literal>, например,
<literal remap="tt-bf">public slots:</literal> внутри объявления класса,</para>
</listitem>
<listitem>
<para>meta-object компилятор <literal remap="tt">moc</literal> должен быть запущен для обработки файла заголовка для подстановки макросов и выдачи файла с реализацией
(в которой не требуется разбираться). Выходной файл <literal remap="tt">moc</literal> компилируется обычным компилятором C++.</para>
</listitem>
</orderedlist>

Другой способ использовать сигналы без наследования от <literal remap="tt">QObject</literal> - использовать класс <literal remap="tt">QSignal</literal> - см. справочное руководство
для получения дополнительной информации и примеров использования. В дальнейшем материале мы предполагаем, что используется наследование от <literal remap="tt">QObject</literal>.</para>

<para>Используя этот механизм, ваш класс может посылать сигналы и предоставлять слоты для присоединения к ним сигналов. Используя сигналы, вы не должны
заботиться о том, кто их получает - вы должны испустить сигнал и любой слот, который вы соединили с этим сигналом, сможет прореагировать
на появление сигнала. Кроме того, слоты могут использоваться как обычные методы при реализации программы.</para>

<para>Теперь, для того, чтобы соединить сигнал и слот, вы должны использовать метод <literal remap="tt">connect()</literal>, который предоставляет <literal remap="tt">QObject</literal>, или, где это возможно, 
специальные методы, которые предоставляют объекты для установки соединения с определенными сигналами.</para>

<sect3 id="primer-ispolzovaniia">
<title>Пример использования</title>

<para>Чтобы объяснить, как организовать межобъектное взаимодействие, вернемся к нашему первому примеру и добавим в него простое соединение:</para>

<para><screen>#include &lt;qapplication.h&gt;
#include &lt;qpushbutton.h&gt;

int main( int argc, char **argv )
{
QApplication a( argc, argv );

QPushButton hello( "Hello world!" );
hello.resize( 100, 30 );

a.setMainWidget( &&amp;;hello );

connect(&&amp;;hello, SIGNAL( clicked() ), &&amp;;a, SLOT( quit() ));

hello.show();
return a.exec();
}
</screen>
</para>

<para>Как видно, единственное изменение, оживляющее кнопку, - использование метода <literal remap="tt">connect()</literal>:
<literal remap="tt">connect(&&amp;;hello, SIGNAL( clicked() ), &&amp;;a, SLOT( quit() ));</literal>. Вот и все, что мы добавили. 
Что это значит? В классе <literal remap="tt">QObject</literal> метод <literal remap="tt">connect()</literal> объявляется так:</para>

<para><literal remap="tt">bool connect ( const QObject * sender, const char * signal, const QObject * receiver, const char * member )</literal></para>

<para>Это значит, что вы должны предоставить экземпляру QObject указатель на источник сигнала, имея в виду, что он должен уметь испускать этот сигнал, 
первым параметром; затем вы должны указать сигнал, для которого устанавливается соединение. Следующие два параметра - объект-получатель, 
который предоставляет слот, и фукнкция-член, которая <emphasis>и есть</emphasis> слот, выполняемый при получении сигнала. </para>

<para>Используя сигналы и слоты, объекты вашей программы могут взаимодействовать между собой проще, без точного определения типа объекта-получателя сигнала. 
Вы изучите подробнее использование этого механизма позднее в этой книге. Более подробная информация о
механизме Сигнал/Слот также может быть найдена в "The KDE Library Reference Guide" 
и в Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> online-документации.</para>
</sect3>
</sect2>
</sect1>

<sect1 id="chto-predlagaet-kde">
<title>Что предлагает KDE</title>

<sect2 id="biblioteki-kde-1.1.x">
<title>Библиотеки KDE 1.1.x </title>

<para>На момент написания книги KDevelop использует KDE 1.1, поэтому мы здесь рассмотрим 
библиотеки KDE  <indexterm remap="idx"><primary>библиотеки KDE </primary></indexterm> этого релиза. Основные библиотеки KDE <indexterm remap="idx"><primary>библиотеки KDE</primary></indexterm>, которые вы будете использовать при разработке приложений KDE <indexterm remap="idx"><primary>приложений KDE</primary></indexterm>, следующие: </para>

<para><itemizedlist>
<listitem>
<para>библиотека KDE-Core содержит все классы, не являющиеся видимыми элементами, и обеспечивает реализацию тех возможностей, которые ваше приложение может использовать;</para>
</listitem>
<listitem>
<para>библиотека KDE-UI содержит элементы пользовательского интерфейса, такие как панель меню, панели инструментов <indexterm remap="idx"><primary>панели инструментов</primary></indexterm> и т.п.;</para>
</listitem>
<listitem>
<para>библиотека KFile содержит диалоговое окно выбора файлов.</para>
</listitem>
</itemizedlist>
</para>

<para>Кроме того, для специальных целей KDE предоставляет следующие библиотеки:</para>

<para><itemizedlist>
<listitem>
<para>библиотека KHTMLW содержит элемент, который полностью интерпретирует HTML-файлы и используется в таких программах, как KDEHelp <indexterm remap="idx"><primary>KDEHelp</primary></indexterm>, KFM, KDevelop;</para>
</listitem>
<listitem>
<para>библиотека KFM позволяет использовать KDE менеджер файлов из вашего приложения;</para>
</listitem>
<listitem>
<para>библиотека KAb, KAddressBook. Реализует доступ к адресной книге, например, для приложений, работающих с email;</para>
</listitem>
<listitem>
<para>библиотека KSpell предоставляет элементы для интеграции Ispell, программы проверки правописания, в приложения типа
редакторов; используется в KEdit.</para>
</listitem>
</itemizedlist>
</para>

<para>Теперь давайте посмотрим, что необходимо сделать, чтобы превратить наше Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> приложение в KDE приложение.</para>
</sect2>

<sect2 id="primer-prilozheniia-kde">
<title>Пример приложения KDE </title>

<para>Сейчас вы увидите, что создание KDE приложения не на много сложнее, чем приложения для Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>. Для использования возможностей KDE
вы просто должны включить в программу другие классы, и все будет сделано. Например, рассмотрим измененную версию примера программы Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>,
приведенного выше:</para>

<para><screen>#include &lt;kapp.h&gt;
#include &lt;qpushbutton.h&gt;

int main( int argc, char **argv )
{
KApplication a( argc, argv );

QPushButton hello( "Hello world!" );
hello.resize( 100, 30 );

a.setTopWidget( &&amp;;hello );

connect(&&amp;;hello, SIGNAL( clicked() ), &&amp;;a, SLOT( quit() ));

hello.show();
return a.exec();
}
</screen>
</para>

<para>Как видно, в первую очередь мы изменили <literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication</literal> на <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal>. Далее, мы использовали вместо метода
<literal remap="tt">setMainWidget()</literal> метод <literal remap="tt">setTopWidget</literal>, который вызывает <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal> для установки главного элемента (main widget). Вот и все! Ваше первое KDE
приложение готово - вы только должны сообщить компилятору путь к файлам KDE, упомянутым в командах "&&num;;include", и линкеру - линковать с ключом -lkdecore.</para>

<para>Теперь, когда вы знаете, что в общем делает функция main(), как приложения становятся видимыми и как организовать взаимодействие пользователя и объектов программы,
мы переходим к следующей главе, где мы сделаем наше первое приложение с помощью KDevelop - там вы сможете также протестировать все вышеупомянутое и посмотреть результат.</para>

<para>Сейчас вам будет полезно посмотреть дополнительно справочное руководство по Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>, особенно в части <literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication</literal>,
<literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal> и <literal remap="tt">QObject</literal>, документацию по библиотеке KDE-Core для класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal>.
Справочник "KDE Library Reference" содержит полное описание вызова
конструкторов <literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication</literal> и <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal>, включая обработку аргументов командной строки.</para>
</sect2>
</sect1>
</chapter>

<chapter id="creating-new-applications">
<title>Создание новых приложений </title>

<para>KAppWizard, также называемый KDE Application Wizard, предназначен для того, чтобы помочь вам начать работу над новым проектом в KDevelop.
Таким образом, для начала любого вашего проекта вы должны использовать KAppWizard. Потом вы сможете модифицировать и дополнять автоматически сгенерированный скелет кода.
KAppWizard позволяет выбрать один из нескольких типовых проектов, в зависимости от предназначения вашего приложения:</para>

<para><itemizedlist>
<listitem>
<para>Обычное приложение KDE: включает исходный код, реализующий стандартную структуру фреймов приложения KDE с поддержкой
модели Докумет-Просмотр (Document-View-Controller), панели меню, панели инструментов <indexterm remap="idx"><primary>панели инструментов</primary></indexterm> и строки статуса, а также набор базовых шаблонов документации в SGML <indexterm remap="idx"><primary>SGML</primary></indexterm>-формате, 
ссылки на KDE-ресурсы и иконки приложения. Этот тип приложений обычно используется для создания новых KDE-проектов.</para>
</listitem>
<listitem>
<para>Простое KDE приложение (Mini KDE Application): имеет ту же структуру, что и обычное KDE приложение, но с тем отличием, что
есть только один видимый элемент - окно.</para>
</listitem>
<listitem>
<para>Обычное Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> приложение: содержит то же, что и KDE приложение, но код использует только Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>
библиотеки и не содержит поддержки KDE. Это может быть полезно для приложений, которые планируется переносить на WINDOWS платформу, или для тех,
которые не планируют использование конечным пользователем KDE библиотек.</para>
</listitem>
<listitem>
<para>C приложение: консольное приложение для C компилятора.</para>
</listitem>
<listitem>
<para>C++ приложение: использует C++ компилятор и запускается в консоли, следовательно, не требует  X-Window.</para>
</listitem>
<listitem>
<para>Пользовательский проект: создает пустой проект без какого-либо кода. Это может быть полезно для перевода уже существующих программ
под KDevelop или для старта "с самого начала". Имейте в виду, что вы должны уделить внимание созданию makefile'ов и конфигурационных скриптов.</para>
</listitem>
</itemizedlist>
</para>

<para>В этой главе мы увидим, как можно использовать KAppWizard и что должно быть сделано для создания проекта KDE приложения.
Это будет первый шаг нашего пути, где мы создадим исходную версию примера проекта. Для всех остальных типов проектов
шаги почти такие же, только вам предоставляется меньше опций для выбора.</para>

<sect1 id="ispolzovanie-kappwizard-i-generatsiia-proekt">
<title>Использование KAppWizard и генерация проекта</title>

<sect2 id="zapusk-kappwizard-i-pervaia-stranitsa">
<title>Запуск KAppWizard и первая страница</title>

<para>Чтобы начать создание вашего первого KDE приложения, откройте KDevelop. Затем выберите пункт "New..." из меню "Project". Запустится KAppWizard, и вы
увидите дерево на первой странице, содержащее типы проектов. При выборе типа в правой части окна можно увидеть, как будет выглядеть приложение после
работы KAppWizard. Выберите ветвь KDE, тип Normal (Обычное приложение KDE). После этого нажмите кнопку "Next" внизу первой страницы KAppWizard.
Это приведет к переходу на следующую страницу, где вы сможете установить основные опции проекта.</para>
</sect2>

<sect2 id="ustanovki-stranitsy-generate">
<title>Установки страницы Generate</title>

<para>Для нашего примера мы выберем имя проекта <literal remap="tt">KScribble</literal>; введите это в поле "Projectname". Затем выберите
каталог, в котором вы хотите разместить свой проект; по умолчанию это ваш домашний каталог. Вы можете ввести путь вручную или 
нажать кнопку справа от поля для выбора каталога через диалоговое окно.</para>

<para>Теперь вы должны ввести номер версии. Для первой версии установите номер <literal remap="tt">0.1</literal>. Это обычный номер для нового приложения, которое находится в стадии разработки.
Для таких приложений присваиваются номера, меньшие 1, а стартовая версия вашего приложения будет иметь только исходный набор фреймов, поэтому назовите ее 
0.1.</para>

<para>Наконец, введите свое имя в поле "Author" и ваш email адрес. Остальные опции можете оставить с их значениями по умолчанию.</para>

<para>Для получения дополнительной информации обо всех других опциях, вы можете нажать правую кнопку мыши над соответствующим полем и выбрать пункт меню quick-help.
Откроется окно помощи с кратким описанием назначения опции. Это:</para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">generate sources and headers:</emphasis>  генерировать исходный код и файлы заголовков.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">GNU-Standard-Files:</emphasis>  добавить копию GNU - General Public License в проект и некоторые стандартные файлы с информацией для пользователя
при распространении пакета.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">User-Documentation:</emphasis> руководство пользователя в SGML <indexterm remap="idx"><primary>SGML</primary></indexterm>, шаблон которого уже подготовлен для вашего проекта.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">API <indexterm remap="idx"><primary>API</primary></indexterm>-Documentation:</emphasis> создает стартовый набор HTML документации для <emphasis remap="bf">A</emphasis>pplication <emphasis remap="bf">P</emphasis>rogramming <emphasis remap="bf">I</emphasis>nterface.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">lsm-File:</emphasis> Linux Software Map, используется при распространении программы на предлагающих ее сайтах и представляет собой файл с кратким описанием назначения
проекта и его требований.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">.kdelnk <indexterm remap="idx"><primary>.kdelnk</primary></indexterm>-File: </emphasis> файл ссылки, который будет записан в ветку "Applications" дерева меню панели KDE-Panel при инсталляции приложения.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Program-Icon: </emphasis> иконка, которая представляет проект и может быть использована для создания ссылки на рабочем столе.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Mini-Icon: </emphasis> мини-иконка, которая отображается возле названия приложения в KDE-Panel,
в верхнем левом углу диалоговых окон приложения и его главного окна.</para>
</listitem>
</itemizedlist>
</para>

<para>Теперь переключаемся на следующую страницу нажатием кнопки "Next" для создания шаблона файла заголовка вашего проекта.</para>
</sect2>

<sect2 id="shablony-zagolovkov-i-iskhodnikov">
<title>Шаблоны заголовков и исходников</title>

<para>Страница шаблонов заголовков позволяет вам автоматически включать предисловие в ваш файл шаблона, содержащее имя файла, дату, год,
copyright, ваше имя и email адрес. Вы не должны изменять текст, набранный заглавными буквами, самостоятельно,
KAppWizard сделает это автоматически и добавит шаблон в ваш проект, вы сможете его использовать в дальнейшем для создания новых файлов.</para>

<para>Вторая часть шаблона файла заголовка, предоставляемого по умолчанию, содержит информацию о лицензировании. Предполагается, что ваш проект попадает под действие 
GNU General Public License, которая также включается в дистрибутив. Эта лицензия используется, чтобы защитить ваш исходный код от любого, кто
захочет его скопировать для своих собственных целей. General Public License предлагает вам эту лицензию и таким образом защищает ваши авторские права,
это общепринято при распространении свободного программного обеспечения. Для получения дополнительной информации о лицензии вы можете прочитать COPYING
файл в корневом каталоге вашего проекта (он будет туда занесен после завершения работы KAppWizard), который является копией GPL и уже входит в состав вашего приложения.</para>

<para>Вы можете выбрать другую лицензию или другой шаблон для использования с проектом. 
Также вы можете отредактировать предоставляемый по умолчанию шаблон. Для того, чтобы сделать это, вы должны вызвать шаблон в окно редактирования. Для очистки страницы по умолчанию
выберите "New", для использования другого шаблона выберите "Load...", что откроет диалоговое окно выбора файла.</para>

<para>Когда вы закончите с этим, переходите к следующей странице, нажав "Next". Эта страница для создания шаблона вашего исходника. В общем она
такая же, как и страница создания шаблона файла заголовка. Единственное отличие в том, что шаблоны используются 
для создания файлов реализации объявленных в заголовках функций.</para>
</sect2>

<sect2 id="sozdanie-proekta">
<title>Создание проекта</title>

<para>Теперь, когда вы заполнили все опции для <emphasis>KScribble</emphasis>, выберите "Next" и нажмите кнопку "Generate" внизу окна KAppWizard.
Если кнопка недоступна, значит, вы установили неправильное значение какой-либо опции. Для исправления ошибки вернитесь назад с помощью кнопки "Back".</para>

<para>После нажатия кнопки "Generate" вы должны увидеть, что KAppWizard начал работу - он копирует все шаблоны в каталог вашего проекта. Потом, когда KAppWizard
завершит работу, кнопка "Cancel" заменится на "Exit". Ее нажатие приведет к выходу из генератора.</para>

<para>После этого шага вы завершаете процесс создания нового проекта. KDevelop загрузит его и предоставит возможность исследовать структуру,
представив проект в виде дерева файлов или классов.</para>

<para>В следующем разделе мы опишем, как откомпилировать и запустить вашу первую версию <emphasis>KScribble</emphasis>, и обсудим, как организован исходный код.</para>
</sect2>
</sect1>

<sect1 id="pervyi-zapusk">
<title>Первый запуск</title>

<para>После того, как наш проект сгенерирован, первое, что необходимо сделать, - просмотреть структуру кода, чтобы получить общее понимание того, как работает приложение.
Это не только поможет нам начать разработку, а и в дальнейшем мы будем ориентироваться, где необходимо вносить изменения.</para>

<para>Когда мы откроем страничку LFV (Logical File Viewer) в левой части окна KDevelop, мы увидим несколько папок, в которых уже размещены файлы проекта в соответствии с их назначением.  
Первые две папки - "Headers" и "Sources". Папка заголовков логически содержит все файлы заголовков проекта,
папка "Sources" - все исходники. Остальные папки сейчас для нас не интересны, их назначение мы рассмотрим позднее.</para>

<para>Две папки содержат следующие файлы:</para>

<para><emphasis remap="bf">Headers:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">kscribble.h :</emphasis> содержит объявление класса <emphasis remap="bf">KScribbleApp</emphasis>.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">kscribbledoc.h :</emphasis> содержит объявление класса <emphasis remap="bf">KScribbleDoc</emphasis>.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">kscribbleview.h :</emphasis> содержит объявление класса <emphasis remap="bf">KScribbleView</emphasis>.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">resource.h :</emphasis> содержит коллекцию макросов идентификаторов пунктов меню.</para>
</listitem>
</itemizedlist>
</para>

<para><emphasis remap="bf">Sources:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">kscribble.cpp :</emphasis> содержит реализацию класса <emphasis remap="bf">KScribbleApp</emphasis>.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">kscribbledoc.cpp :</emphasis> содержит реализацию класса <emphasis remap="bf">KScribbleDoc</emphasis>.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">kscribbleview.cpp :</emphasis> содержит реализацию класса <emphasis remap="bf">KScribbleView</emphasis>.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">main.cpp :</emphasis> содержит реализацию функции <emphasis remap="bf">main()</emphasis>.</para>
</listitem>
</itemizedlist>
</para>

<para>Перед тем, как углубиться в исходный код, позволим KDevelop откомпилировать и запустить наше новое приложение. Чтобы сделать это, выберем "Make" из меню "Build".
или нажмем соответствующую кнопку на панели инструментов. В нижней части KDevelop откроется окно вывода,
и мы увидим сообщения, выдаваемые <literal remap="tt">make</literal> при работе. Они могут несколько отличаться от приводимых ниже,
в зависимости от используемых настроек.</para>

<para><screen>1   Making all in docs
2   make[1]: Entering directory `/home/rnolden/Tutorial/kscribble1/kscribble/docs'
3   Making all in en
4   make[2]: Entering directory `/home/rnolden/Tutorial/kscribble1/kscribble/docs/en'
5   make[2]: Nothing to be done for `all'.
6   make[2]: Leaving directory `/home/rnolden/Tutorial/kscribble1/kscribble/docs/en'
7   make[2]: Entering directory `/home/rnolden/Tutorial/kscribble1/kscribble/docs'
8   make[2]: Nothing to be done for `all-am'.
9   make[2]: Leaving directory `/home/rnolden/Tutorial/kscribble1/kscribble/docs'
10  make[1]: Leaving directory `/home/rnolden/Tutorial/kscribble1/kscribble/docs'
11  make[1]: Entering directory `/home/rnolden/Tutorial/kscribble1/kscribble'
12  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c
    kscribbleview.cpp
13  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c
    kscribbledoc.cpp
14  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c 		
    kscribble.cpp
15  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c
    main.cpp
16  /usr/bin/moc ./kscribble.h -o kscribble.moc.cpp
17  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c
    kscribble.moc.cpp 		
18  /usr/bin/moc ./kscribbledoc.h -o kscribbledoc.moc.cpp
19  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c
    kscribbledoc.moc.cpp
20  /usr/bin/moc ./kscribbleview.h -o kscribbleview.moc.cpp
21  g++ -DHAVE_CONFIG_H -I. -I. -I.. -I/opt/kde/include -I/usr/lib/qt/include  -I/usr/X11R6/include    -O0 -g -Wall  -c
    kscribbleview.moc.cpp

22  /bin/sh ../libtool --silent --mode=link g++  -O0 -g -Wall   -o kscribble -L/opt/kde/lib  -L/usr/X11R6/lib -rpath /opt/kde/lib
    -rpath /usr/X11R6/lib kscribbleview.o kscribbledoc.o kscribble.o main.o kscribble.moc.o kscribbledoc.moc.o kscribbleview.moc.o
    -lkfile -lkfm -lkdeui -lkdecore -lqt -lXext -lX11

23  make[1]: Leaving directory `/home/rnolden/Tutorial/kscribble1/kscribble'
</screen>
</para>

<para>Мы проставили номера строк напротив каждой строки, которых нет в выводе KDevelop. Это сделано для облегчения дальнейшего обсуждения того,
что происходит при компиляции. Во-первых, <literal remap="tt">make</literal> работает рекурсивно. Это значит, что она начинает с каталога, откуда была вызвана, и
затем в первую очередь заходит в подкаталог, возвращается и заходит в следующий подкаталог. Наконец, обрабатывается стартовый каталог
и <literal remap="tt">make</literal> завершается. <literal remap="tt">make</literal> вызывается из главного каталога проекта, содержащего исходники. В строках 1 и 2 
мы видим, как <literal remap="tt">make</literal> входит в каталог <literal remap="tt">docs</literal>, затем в подкаталог <literal remap="tt">en</literal>. Так как там нечего делать, она
выходит из этих каталогов, пока не вернется в каталог исходников <literal remap="tt">kscribble</literal> в строке 11. Теперь начинается настоящая работа: <literal remap="tt">make</literal>
вызывает компилятор, <literal remap="tt">g++</literal>, для компиляции файла-исходника <literal remap="tt">kscribbleview.cpp</literal>. Макрос <literal remap="tt">-DHAVE&&lowbar;;CONFIG&&lowbar;;H</literal> говорит о том, что должен быть использован файл
<literal remap="tt">config.h</literal>. Этот файл содержит макросы для определения платформы и приложения, и расположен в корневом каталоге проекта.
Следующие <literal remap="tt">-I</literal> команды добавляют пути для поиска файлов, указанных в команде <literal remap="tt">"&&num;;include"</literal>. Это
текущий каталог, корневой каталог проекта (<literal remap="tt">-I..</literal>), и пути к файлам KDE, Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> и заголовкам библиотек X11.
Эти пути определяются при выполнении скрипта <literal remap="tt">configure</literal> и устанавливаются в файлах Makefile; таким образом, компилятор
знает, где файлы расположены. Наконец, <literal remap="tt">-O0</literal> устанавливает оптимизацию в ноль (без оптимизации), <literal remap="tt">-g</literal> разрешает отладку, <literal remap="tt">-Wall</literal>
устанавливает предупреждения компилятора в значение <literal remap="tt">all</literal>, и <literal remap="tt">-c</literal> говорит компилятору, что необходимо генерировать только файлы obj, то есть надо только откомпилировать файлы.</para>

<para>Это делается и для других файлов-исходников нашего проекта в строках 13-15. Очевидно, наш исходный код откомпилирован, но вместо того,
чтобы линковать объектные файлы исходников в конечный бинарный файл, мы видим несколько иные команды. В строке 16 программа "moc"
вызывается для обработки файла-заголовка <literal remap="tt">kscribble.h</literal>, выводя результат в <literal remap="tt">kscribble.moc.cpp</literal>. Затем, в строке 17, этот исходный файл
компилируется. Аналогичные операции проделываются с другими файлами заголовков проекта до строки 21. Это необходимо, поскольку Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> поддерживает механизм сигнал/слот,
но базируется на C++ реализации, и мы используем определенные ключевые слова, не поддерживаемые языком C++, такие как  
<literal remap="tt">signals:</literal> и <literal remap="tt">slots:</literal>, в наших классах. Это дает нам возможность легко организовать межобъектное взаимодействие для всех 
экземпляров классов, порожденных от <literal remap="tt">QObject</literal>, и избежать использования традиционного механизма callback указателей на функции. 
Таким образом, приложению необходим исходный код, который обеспечивает данную функциональность, и вот для чего вызывается
<literal remap="tt">moc</literal>. <literal remap="tt">Moc</literal> - Meta Object Compiler набора инструментов Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>. Он реализует механизм сигнал/слот, обрабатывая файл заголовка и генерируя код, который
должен быть откомпилирован для получения бинарного файла. Поскольку проекты KDevelop используют <literal remap="tt">automoc</literal> для определения того, какие файлы заголовков должны быть обработаны, мы
не должны следить за вызовами <literal remap="tt">moc</literal> и C++ компилятора для обработки сгенерированных <literal remap="tt">moc</literal> файлов. Только запомните правило, что для использования
механизма сигнал/слот класс должен быть порожден от <literal remap="tt">QObject</literal>, или от любого другого класса, порожденного от <literal remap="tt">QObject</literal>; кроме того,
этот класс должен содержать макрос <literal remap="tt">Q&&lowbar;;OBJECT</literal> (без ";"!) в начале своего объявления, и объявления сигналов и слотов.</para>

<para>Наконец, генерируется бинарный файл. Выходной бинарный файл называется <literal remap="tt">kscribble</literal>, линкер использует пути к библиотекам KDE и 
X11, и линкует исходники с библиотеками <literal remap="tt">kfile, kfm, kdeui, kdecore, qt, Xext</literal> и <literal remap="tt">X11</literal>. На этом 
make завершает свою работу.</para>
</sect1>

<sect1 id="struktura-skeleta-iskhodnogo-koda">
<title>Структура скелета исходного кода</title>

<para>Чтобы понять и использовать концепцию того, как работает приложение KDE, в первую очередь мы должны очень внимательно изучить структуру скелета исходного кода, сгенерированную KAppWizarg.
Как мы уже видели, у нас есть набор файлов заголовков и кода, которые реализуют исходный код приложения,
и делают его готовым к выполнению. Таким образом, простейший путь объяснить код - пройти строка за строкой код так,
как он обрабатывается в процессе выполнения программы до входа в главный цикл событий и перехода в режим ожидания ввода пользователя. Затем мы рассмотрим, как реализуются функции взаимодействия с пользователем
и как некоторые вещи работают. Это, наверное, лучший путь объяснить, как работают элементы окна (framework),
и, поскольку это стандартно для большинства приложений KDE, такое объяснение позволит нам читать исходный код других проектов; кроме того,
мы узнаем, где что необходимо изменить, чтобы заставить свое приложение работать так, как от него требуется.</para>

<sect2 id="the-main-function">
<title>Функция <literal remap="tt">main()</literal></title>

<para>Поскольку приложение начинает свое выполнение входом в функцию <literal remap="tt">main()</literal>, она и будет стартовой точкой нашего исследования.
Функция <literal remap="tt">main()</literal> <emphasis>KScribble</emphasis> реализована в файле <literal remap="tt">main.cpp</literal>, а также может быть найдена с помощью
просмотрщика классов (Class Browser) в папке "Globals", подпапке "Functions":</para>

<para><screen>1  #include "kscribble.h"
2
3  int main(int argc, char* argv[]) {
4    KApplication app(argc,argv,"KScribble");
5
6    if (app.isRestored())
7    {
8       RESTORE(KScribbleApp);
9    }
10   else
11   {
12      KScribbleApp* kscribble = new KScribbleApp;
13      kscribble-&gt;show();
14      if(argc &gt; 1){
15        kscribble-&gt;openFile(argv[1]);
16      }
17    }
18    return app.exec();
19  }
</screen>
</para>

<para>Итак, что же происходит в первую очередь при создании объекта <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal>, который получает третьим аргументом имя приложения <emphasis>KScribble</emphasis>?
Когда создается новый <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal>, порождается новый экземпляр объекта <literal remap="tt"><indexterm remap="cdx"><primary><literal>KConfig</literal></primary></indexterm>KConfig</literal>, который устанавливает связь с конфигурационным файлом,
$HOME/.kde/share/config/appname+rc, содержащим информацию, которую мы хотим использовать при открытии окна приложения. Имя,
которое мы передали конструктору <literal remap="tt">app</literal>, будет использовано позднее в заголовке окна.</para>

<para>По сравнению с примером кода, приведенным при преобразовании первого приложения Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> в приложение KDE, нынешний код имеет отличия. 
После создания экземпляра <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal> мы проверяем, как приложение вызвано: <literal remap="tt">kwm</literal> менеджером сессий или пользователем.
Это можно узнать, вызывая метод <literal remap="tt">isRestored()</literal> объекта <literal remap="tt">app</literal>, который возвращает <literal remap="tt">true</literal> для случая менеджера сессий
и <literal remap="tt">false</literal> при нормальном запуске.</para>

<para>Менеджмент сессий (session management) - одна из основных возможность приложений KDE, и она широко используется приложениями, но ее несколько долго объяснять.
Поэтому мы вначале последуем по ветке <literal remap="tt">else&&lcub;;&&rcub;;</literal>; затем мы вернемся и поясним функционирование менеджмента сессий.</para>
</sect2>

<sect2 id="zapusk-prilozheniia-polzovatelem">
<title>Запуск приложения пользователем</title>

<para>В ветке <literal remap="tt">else&&lcub;;&&rcub;;</literal> создается экземпляр класса <literal remap="tt">KScribbleApp</literal> (строка 12). Этот объект вызывается, чтобы прорисовать себя, в строке
13, как обычно; строка 14 определяет, есть ли аргументы в командной строке. Если есть, то обычно это имя файла, поэтому
объект <literal remap="tt">kscribble</literal> открывает этот файл с помощью метода <literal remap="tt">openFile()</literal>.</para>

<para>Обратите внимание, что мы не вызывали метод <literal remap="tt">setTopWidget(kscribble)</literal> для нашего приложения - это уже сделано предками класса <literal remap="tt">KScribbleApp</literal>.
Теперь посмотрим на наш объект <literal remap="tt">KScribbleApp</literal> - что это такое и что он предлагает? Единственная вещь, которую мы знаем
на текущий момент, это то, что он должен быть видимым элементом (Widget) для представления пользовательского интерфейса в окне приложения. Обратимся к реализации класса
<literal remap="tt">KScribbleApp</literal>, которая находится в файле <literal remap="tt">kscribble.cpp</literal>, или нажмем мышкой на иконке класса в просмотрщике классов.
Экземпляр класса был создан с помощью конструктора. Во-первых, мы видим, что он порожден от класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal>, который является частью <literal remap="tt">kdeui</literal>. Этот класс, в свою очередь,
унаследован от <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>, таким образом, мы имеем нормальный видимый элемент в качестве верхнего окна (top-level window).
<literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal> содержит массу функций, которые использует класс <literal remap="tt">KScribbleApp</literal>. Он предоставляет панель меню, панели инструментов <indexterm remap="idx"><primary>панели инструментов</primary></indexterm>, строку статуса и поддержку менеджмента сессий. Единственная вещь,
которую мы должны сделать, когда наследуем новый класс от <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal>, - создать все объекты, которые нам нужны, и создать другой элемент, который управляется нашим 
экземпляром <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal> и заполняет рабочую область окна; обычно этот объект выглядит как область редактирования текста. </para>

<sect3 id="konstruktor">
<title>Конструктор</title>

<para>Давайте взглянем на код конструктора и рассмотрим, как создается экземпляр объекта:</para>

<para><screen>1   KScribbleApp::KScribbleApp()
2   {
3     config=kapp-&gt;getConfig();
4	
5
6     ///////////////////////////////////////////////////////////////////
7     // вызываем методы init для активации всех остальных частей конструктора
8     initMenuBar();
9     initToolBar();
10    initStatusBar();
11    initKeyAccel();
12    initDocument();
13    initView();
14
15    readOptions();
16
17    ///////////////////////////////////////////////////////////////////
18    // запрещаем меню и панели инструментов при старте
19    disableCommand(ID_FILE_SAVE);
20    disableCommand(ID_FILE_SAVE_AS);
21    disableCommand(ID_FILE_PRINT);
22
23    disableCommand(ID_EDIT_CUT);
24    disableCommand(ID_EDIT_COPY);
25    disableCommand(ID_EDIT_PASTE);
26  }
</screen>
</para>

<para>Мы видим, что наш экземпляр <literal remap="tt"><indexterm remap="cdx"><primary><literal>KConfig</literal></primary></indexterm>KConfig</literal>, отвечающий за конфигурацию, сейчас указывает на конфигурацию приложения, поэтому мы сможем работать
с установками конфигурационного файла в дальнейшем.</para>

<para>Затем, все части приложения, которые необходимы, созданы вызовом соответствующих функций-членов, которые специфичны для нашего приложения.</para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">initMenuBar():</emphasis>  создает панель меню,</para>
</listitem>
<listitem>
<para><emphasis remap="bf">initToolBar():</emphasis>  создает  панель инструментов <indexterm remap="idx"><primary>панель инструментов</primary></indexterm>,</para>
</listitem>
<listitem>
<para><emphasis remap="bf">initStatusBar():</emphasis> создает строку статуса,</para>
</listitem>
<listitem>
<para><emphasis remap="bf">initKeyAccel():</emphasis>  устанавливает все клавиши быстрого доступа(accelerators)<indexterm><primary>accelerator</primary></indexterm> для нашего приложения согласно глобальной конфигурации, определенной приложением,</para>
</listitem>
<listitem>
<para><emphasis remap="bf">initDocument():</emphasis> создает объект документа для окна приложения,</para>
</listitem>
<listitem>
<para><emphasis remap="bf">initView():</emphasis> создает главный элемент, заполняющий наше окно,</para>
</listitem>
<listitem>
<para><emphasis remap="bf">readOptions():</emphasis>  считывает все специфичные для приложения установки из конфигурационного файла и инициализирует 
оставшиеся части приложения, такие как список последних файлов, положение панелей и размеры окна.</para>
</listitem>
</itemizedlist>
</para>

<para>Наконец, мы запрещаем несколько команд, которые пользователь может выдать, поскольку они не должны быть доступны в нынешнем состоянии приложения.
Сейчас мы рассмотрели в общем как создается окно приложения, теперь мы углубимся в детали того, как создаются пользовательские элементы
в упомянутых выше методах.</para>
</sect3>

<sect3 id="panel-meniu">
<title>Панель меню</title>

<para>Как показано выше, панель меню <emphasis>KScribble</emphasis> создается методом <literal remap="tt">initMenuBar()</literal>. В нем мы создаем набор
<literal remap="tt"><indexterm remap="cdx"><primary><literal>QPopupMenu</literal></primary></indexterm>QPopupMenu</literal>, которые выпадают, когда пользователь выбирает пункт меню. Затем мы вставляем их в панель меню и подсоединяем к их входам функции, выполняемые при выборе.</para>

<para>В первую очередь, мы создаем наше <literal remap="tt">recent&&lowbar;;file&&lowbar;;menu</literal>, которое содержит названия последних 5 открытых файлов. Мы делаем это первым делом, потому что
это меню вставляется в <literal remap="tt">file&&lowbar;;menu</literal>. Затем мы добавляем непосредственно связь  - мы только что получили сигнал, который испущен
входом меню с определенным номером входа и вызываем <literal remap="tt">slotFileOpenRecent( int )</literal>, который затем вызывает нужный файл из списка последних открытых файлов.</para>

<para>Теперь мы создаем наше "File"-меню. Это будет меню, выпадающее из панели меню. Стандартные действия вставляются одно за другим в
выпадающее меню - вначале команда создания нового файла, открытия файла, закрытия файла и т.д., наконец "E&&amp;;xit" для закрытия
приложения. Все входы меню должны быть созданы в том порядке, в каком они будут появляться в дальнейшем, поэтому мы должны следить за тем, 
что в каком месте необходимо расположить. Рассмотрим, например, следующие входы:</para>

<para><screen>file_menu-&gt;insertItem(Icon("fileopen.xpm"), i18n("&&amp;;Open..."), ID_FILE_OPEN );
file_menu-&gt;insertItem(i18n("Open &&amp;;recent"), recent_files_menu, ID_FILE_OPEN_RECENT );
</screen>
</para>

<para>Первая команда вставляет вход "Open...". Поскольку мы хотим иметь его с иконкой, мы используем <literal remap="tt">insertItem()</literal> с именем иконки.
Чтобы понять процесс загрузки иконок, мы должны знать, где определен <literal remap="tt">Icon()</literal>. На самом деле это не метод, это макрос, предоставляемый
классом <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal>:</para>

<para><screen>#define Icon(x) kapp-&gt;getIconLoader()-&gt;loadIcon(x)
</screen>
</para>

<para>Кроме того, он использует внутри следующий макрос для получения доступа к объекту приложения:</para>

<para><screen>#define kapp KApplication::getKApplication()
</screen>
</para>

<para>Это означает, что объект <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal> уже содержит экземпляр загрузчика иконок - мы должны только получить к нему доступ; после этого он
загрузит соответствующую иконку. Поскольку все наши иконки входят в состав библиотек KDE <indexterm remap="idx"><primary>библиотек KDE</primary></indexterm>, мы не должны заботиться ни о чем больше - они устанавливаются 
в системе автоматически, следовательно, мы также не должны включать их в состав дистрибутива нашего приложения.</para>

<para>После параметра иконки (который не обязателен), мы вставляем вход меню с именем <literal remap="tt">i18n("&&amp;;Open...")</literal>. Таким образом, мы должны разобраться с двумя вещами.
Во-первых, вход вставлен с использованием метода <literal remap="tt">i18n()</literal>. Как и <literal remap="tt">Icon()</literal>, это макрос, определенный в <literal remap="tt"><indexterm remap="cdx"><primary><literal>kapp.h</literal></primary></indexterm>kapp.h</literal>,
который вызывает <literal remap="tt">KLocale</literal> объект класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal> для перевода входа на используемый язык:</para>

<para><screen>#define i18n(X) KApplication::getKApplication()-&gt;getLocale()-&gt;translate(X)
</screen>
</para>

<para>Однако, кто-то может сказать "Я не хочу использовать макросы!" - вы можете делать это в большинстве случаев. Но в данной ситуации
вы должны использовать <literal remap="tt">i18n()</literal>, потому что процедура интернационализации приложения предполагает генерацию файлов,
содержащих то, что надо интернационализировать. А ход этого процесса зависит от строки <literal remap="tt">i18n()</literal>. Поэтому вы должны использовать макрос.</para>

<para>Как вы уже, наверное, догадались, амперсант внутри входа меню интерпретируется как подчеркивание следующей буквы в
тексте входа меню. Это позволяет осуществлять быстрый доступ к командам меню с клавиатуры, когда пользователь нажимает клавишу <literal remap="tt">Alt</literal> и одновременно 
подчеркнутую букву.</para>

<para>Наконец, мы назначаем входу меню идентификатор, который является числом типа integer, по которому мы сможем найти вход меню в дальнейшем.
Чтобы иметь контроль над значениями используемых идентификаторов, они определяются как макросы. Все они собраны в файле <literal remap="tt">resource.h</literal> нашего проекта.
Для обеспечения однообразия, эти макросы все набраны заглавными буквами и начинаются с ID&&lowbar;;, затем следует имя меню, а за ним имя входа. Это делает очень простым
определение смысла каждого входа, где бы он ни встретился в коде, и вы не должны возвращаться к коду панели меню для поиска входов.</para>

<para>Следующий пример входа показывает другой вариант метода <literal remap="tt">insertItem()</literal>. Здесь мы добавляем выпадающее меню recent&&lowbar;;files&&lowbar;;menu как
элемент меню. Это значит, что вход отобразится в виде переданной ему надписи "Open recent", а затем будет стоять стрелка вправо. При выборе входа
появится выпадающее меню со списком последних открытых файлов, и пользователь сможет из него выбрать необходимый файл.</para>

<para>Наконец, существует еще множество способов добавления нового входа меню - в данном случае все реализовано максимально просто. Более подробную
информацию можно найти в документации Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>, в описании класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>QMenuData</literal></primary></indexterm>QMenuData</literal>.</para>

<para>Теперь, после создания выпадающих меню <literal remap="tt">file&&lowbar;;menu, edit&&lowbar;;menu</literal> и <literal remap="tt">view&&lowbar;;menu</literal>, мы должны включить "Help"-меню. Мы можем
сделать это аналогично, но класс <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal> предоставляет красивый и быстрый метод для этого:</para>

<para><screen>help_menu = kapp-&gt;getHelpMenu(true, i18n("KScribble\n" VERSION ));
</screen>
</para>

<para>Это все, что мы должны сделать, чтобы получить меню помощи, которое содержит вход для вызова системы помощи с горячей клавишей<indexterm><primary>shortcuts</primary></indexterm>, окно "about" ("о программе...")
для приложения и аналогичное окно для KDE (которое может быть запрещено вызовом <literal remap="tt">getHelpMenu(false,...);</literal>). Содержимое наших окон
"about" определяется с использованием макроса <literal remap="tt">i18n()</literal>. VERSION использует макрос, определенный для номера версии проекта
в файле <literal remap="tt">config.h</literal>, поэтому мы не должны изменять это каждый раз вручную при выпуске нового релиза. Вы можете спокойно добавить в окне "about" любую
информацию о себе - ваше имя, email-адрес, copyright и др.</para>

<para>Теперь мы должны только вставить выпадающие меню в панель меню. Поскольку <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal> уже создал панель меню для нас, мы только
вставляем их, вызывая <literal remap="tt">menuBar()-&gt;insertItem();</literal>.</para>

<para>Все, что осталось сделать - соединить входы меню с методами, которые должны выполняться по их выбору. Следовательно, мы соединяем каждое выпадающее меню по
сигналу <literal remap="tt">activated( int )</literal> с методом <literal remap="tt">commandCallback( int )</literal>, который содержит конструкцию <literal remap="tt">switch</literal>, вызывающую соответствующие
методы для входов меню. Дополнительно, мы соединяем выпадающие меню по их сигналу <literal remap="tt">highlighted( int )</literal> для вывода помощи в строке статуса
по каждому входу. Когда бы пользователь ни перевел указатель мыши или фокус ввода клавиатуры на вход меню, строка статуса выведет соответствующую подсказку.</para>

<para>После того, как мы завершили с панелью меню, мы начнем разбираться с панелью инструментов. Это мы сделаем в следующей секции. Заметьте, что экземпляр
<literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal> может иметь только одну видимую панель меню; таким образом, если вы хотите создать несколько панелей меню, 
вы должны это делать раздельно с использованием экземпляров <literal remap="tt"><indexterm remap="cdx"><primary><literal>KMenuBar</literal></primary></indexterm>KMenuBar</literal>, и установить одну из них в соответствующем методе <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal> как текущую
панель меню. См. документацию по классу <literal remap="tt"><indexterm remap="cdx"><primary><literal>KMenuBar</literal></primary></indexterm>KMenuBar</literal> для получения более детальной информации; о том, как расширить возможности, также см.
<link linkend="Configuring-Menubars-and-Toolbars">Конфигурирование панелей меню и панелей инструментов</link>.</para>
</sect3>

<sect3 id="panel-instrumentov">
<title>Панель инструментов</title>

<para>Создание панелей инструментов <indexterm remap="idx"><primary>панелей инструментов</primary></indexterm> даже проще, чем панелей меню. <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal> предоставляет готовую панель инструментов, которая создается автоматически при вызове конструктора,
а вы можете легко создать еще несколько. На панель инструментов нужно только добавить кнопки для выполнения тех функций, которые вы желаете реализовать:</para>

<para><screen>toolBar()-&gt;insertButton(Icon("filenew.xpm"), ID_FILE_NEW, true, i18n("New File") );
</screen>
</para>

<para>Это добавляет прижатую к левому краю кнопку с иконкой "filenew.xpm" и соответствующим идентификатором на панель инструментов. Третий параметр определяет,
разрешена или запрещена кнопка; по умолчанию мы устанавливаем его равным <literal remap="tt">true</literal>, потому что наш метод <literal remap="tt">disableCommand()</literal> в конце
конструктора сделает необходимые нам установки автоматически для входов меню и панелей инструментов. Наконец, последний параметр используется для
так называемых "всплывающих подсказок" ("Quick-Tip") - когда пользователь располагает указатель мыши над кнопкой так, что она подсвечивается,
появляется окошко с сообщением, содержание которого можно определить этим параметром.</para>

<para>Наконец, все кнопки панели инструментов соединяются с нашим методом <literal remap="tt">commandCallback()</literal> по сигналу <literal remap="tt">clicked()</literal>. По сигналу
<literal remap="tt">pressed()</literal>, мы предоставляем пользователю возможность получить соответствующую подсказку в строке статуса.</para>

<para><emphasis remap="bf">Дополнительная информация:</emphasis></para>

<para>Поскольку панели инструментов <indexterm remap="idx"><primary>панели инструментов</primary></indexterm> создаются на основе класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>KToolBar</literal></primary></indexterm>KToolBar</literal>, вы можете посмотреть соответствующую документацию.
С помощью <literal remap="tt"><indexterm remap="cdx"><primary><literal>KToolBar</literal></primary></indexterm>KToolBar</literal> можно реализовать множество вещей, необходимых для панели инструментов, например задержка перед выпадением меню, если по вашей кнопке вызывается выпадающее меню;
кнопки типа "выпадающий список". По умолчанию панель инструментов заполняет всю ширину
окна, что весьма удобно и красиво, если используется только одна панель. Когда их больше, вы должны продумать
их размеры, так как другие панели могут быть показаны в той же строке, что и первая, под панелью меню. Мы обсудим некоторые
вопросы разработки и расширения возможностей панелей инструментов в разделе <link linkend="Configuring-Menubars-and-Toolbars">Конфигурирование панелей меню и панелей инструментов</link>.</para>
</sect3>

<sect3 id="stroka-statusa">
<title>Строка статуса</title>

<para>Строка статуса, как и панели, предоставляется экземпляром <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal>, поэтому мы должны только вставить в нее свои составляющие.
По умолчанию, сгенерированное приложение содержит только один элемент для отображения подсказки в строке статуса. Для многих приложений
этого может быть не достаточно. Поэтому вы должны добавить необходимые элементы, например, координаты и т.п.</para>

<para>Кроме того, приложение может иметь только одну активную строку статуса, как и панель меню. Если вы хотите создать их несколько, вы должны
создать их по отдельности и установить текущую строку вызовом соответствующего метода <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal>. В строку статуса также можно
вставлять видимые элементы, которые могут быть использованы для красивого отображения индикаторов прогресса, как это делает KDevelop. За дальнейшей информацией обращайтесь к описанию класса
<literal remap="tt">KStatusBar</literal> в документации по классам.</para>
</sect3>

<sect3 id="goriachie-klavishi-keyboard-accelerator">
<title>Горячие клавиши (keyboard accelerator)</title>

<para>Добравшись до метода <literal remap="tt">initKeyAccel()</literal>, мы уже создали стандартные объекты главного окна приложения - панель меню, 
панели инструментов <indexterm remap="idx"><primary>панели инструментов</primary></indexterm> и строку статуса. Неужели мы не создали ни одной горячей клавиши, с помощью которых опытный пользователь, который желает
работать с клавиатурой, будет иметь быстрый доступ к определенным командам, использующимся наиболее часто в процессе работы с нашей программой. Чтобы сделать это, мы
можем использовать встроенные горячие клавиши, созданные при разработке, например, меню, но KDE предоставляет хорошее 
решение для создания и поддержания пользовательских горячих клавиш. Множество пользователей хотят, чтобы они были конфигурируемыми, с одной стороны,
а с другой стороны, стандартные горячие клавиши должны быть одинаковыми для различных приложений. Центр управления KDE
предоставляет конфигурирование стандартных горячих клавиш<indexterm><primary>accelerator</primary></indexterm> глобально, используя класс <literal remap="tt"><indexterm remap="cdx"><primary><literal>KAccel</literal></primary></indexterm>KAccel</literal>. Кроме того,
библиотеки KDE <indexterm remap="idx"><primary>библиотеки KDE</primary></indexterm> содержат элемент, который позволяет пользователю легко конфигурировать специфические для приложения горячие клавиши<indexterm><primary>shortcuts</primary></indexterm> локально.
Поскольку наше приложение использует только меню, выполняющие стандартные действия, такие как "New" или "Exit", они устанавливаются с помощью метода
<literal remap="tt">initKeyAccel()</literal>. Стандартные действия должны быть только связаны с соответствующей комбинацией клавиш. Мы должны добавить их, 
вначале указав наименование стандартного действия, а затем выполняемой функции. Поскольку все наши горячие клавиши
определены в меню, мы должны изменить их для входов выпадающих меню. Затем мы вызываем
<literal remap="tt">readSettings()</literal>, который считывает текущие установки корневого окна KDE, содержащего конфигурацию стандартных
горячих клавиш, потом установки для них, определенные в конфигурационном файле приложения.
Когда мы продвинемся дальше в разработке нашего примера, мы поговорим также о том, как конфигурировать специфические
для приложения горячие клавиши через диалоговое окно, 
см. <link linkend="Configuring-Menubars-and-Toolbars">Конфигурирование панелей меню и панелей инструментов</link> об этой части процесса разработки.</para>
</sect3>

<sect3 id="model-dokument-prosmotr-document-view-model">
<title>Модель Документ-Просмотр (Document-View Model)</title>

<para>Следующие два вызова функций-членов, <literal remap="tt">initDocument()</literal> и <literal remap="tt">initView()</literal>, завершают построение той части окна приложения, которую
предполагается представить пользователю: интерфейс для работы с данными, которые должно обрабатывать приложение; это еще одна причина,
по которой наше приложение состоит из трех классов, <literal remap="tt">*App</literal>, <literal remap="tt">*View</literal> и <literal remap="tt">*Doc</literal>. 
Чтобы понять пользу такой структуры, немного отвлечемся от кода и ознакомимся с теорией, а затем снова
вернемся к программе, чтобы увидеть, как KDevelop поддерживает теоретическую модель.</para>

<para>Вообще говоря, все, что было сказано о нашем приложении, это что нам необходим экземпляр приложения, содержащий главное окно. Это окно имеет возможность предоставить 
пользователю базисный интерфейс - оно содержит меню, панель инструментов и строку статуса, а также механизм обработки ввода пользователя. 
Кроме того, оно содержит область, описанную как "просмотр" ("view"). В общем, назначение этой области - показывать данные, которыми сможет манипулировать пользователь,
например, часть большого текстового файла. Хотя текстовый файл, вероятно, больше, чем наша область может показать на экране, она 
предоставляет возможность пользователю перейти к той части документа, которую он хочет видеть (это и есть "просмотр"). Здесь же пользователь может редактировать файл.
Чтобы дать программисту возможность наилучшим образом разделить части приложения при реализации кода, была разработана модель Документ-Просмотр. Хотя она и не является стандартом, она 
предлагает способ, как приложение должно работать:</para>

<para><itemizedlist>
<listitem>
<para> Приложение содержит управляющий объект (controller object),</para>
</listitem>
<listitem>
<para> объект Просмотр, отображающий данные, с которыми работает пользователь,</para>
</listitem>
<listitem>
<para> и объект Документ, который в действительности содержит обрабатываемые данные.</para>
</listitem>
</itemizedlist>
</para>

<para>Возвращаясь к нашему примеру обработки текстового файла - наша модель должна работать так: Документ считывает содержимое файла и
предоставляет методы для изменения данных и для сохранения файла. Объект Просмотр обрабатывает события, которые генерирует пользователь
с помощью клавиатуры и мыши, и использует методы объекта Документ для обработки данных.</para>

<para>Наконец, управляющий объект отвечает за взаимодействие с пользователем, предоставляя ему доступ к объектам Документ и Просмотр,
а также интерфейс для выдачи команд на открытие и закрытие документа. Кроме того, некоторые методы объекта Просмотр могут активироваться
командами, поступающими от горячих клавиш, меню и панелей инструментов.</para>

<para>Эта модель Документ-Просмотр имеет некоторые преимущества - она разделяет программный код более объектно-ориентированно, и, таким образом, предоставляет большую гибкость,
например, один и тот же объект Документ может отображаться в нескольких объектах Просмотр одновременно; это может происходить как в различных окнах,
так и в рамках одного окна, разделяя его рабочую область на несколько элементов Просмотр.</para>

<para>Если вы работали в MS-Windows, у вас может быть некоторый опыт такой работы - MFC предоставляет модель документа,
готовую к использованию. Для KDE и Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> приложений дело обстоит несколько по иному. Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> - мощный инструмент, который предоставляет
наиболее необходимые классы и видимые элементы. Но он не заботится о реализации модели Документ-Просмотр, и поскольку KDE унаследована от Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>,
нет никаких оснований вводить в ней такую модель. Есть какой-то смысл в том, что традиционное X-приложение не работает 
с многодокументным интерфейсом (MDI, Multiple Document Interface). Каждое главное окно отвечает за содержащиеся в нем данные и, таким образом,
уменьшает потребность в модели Документ-Просмотр, поскольку все методы работы с документом реализованы в видимом элементе. Единственное исключение на текущий момент -
проект <emphasis>KOffice</emphasis>, который предоставляет полный набор офисных приложений, таких как текстовый процессор, электронные таблицы и т.д.
Технически это реализовано внесением двух изменений в традиционный способ использования Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> и KDE:</para>

<para><itemizedlist>
<listitem>
<para>KOffice использует KOM и бесплатную (free) реализацию MICO из CORBA для межобъектного взаимодействия,</para>
</listitem>
<listitem>
<para>приложения KOffice используют модель Документ-Просмотр, чтобы позволить всем приложениям работать с объектами данных KOffice.</para>
</listitem>
</itemizedlist>
</para>

<para>Но, поскольку сейчас KDevelop ориентирован на использование текущих библиотек KDE 1.1.x и Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> 1.4x, мы не можем использовать данную модель по определению - 
она появится в более поздних версиях KDE 2, которая, как предполагается, будет содержать два основных изменения по отношению к текущей - </para>

<para><orderedlist><listitem>
<para>MDI-интерфейс для <indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</para>
</listitem>
<listitem>
<para>KOM библиотеки, которые реализуют модель Документ-Просмотр.</para>
</listitem>
</orderedlist>
</para>

<para>Таким образом, в настоящее время разработчик приложений может либо реализовать все необходимые методы объекта Документ в объекте Просмотр,
или попытаться воспроизвести модель Документ-Просмотр самостоятельно. KDevelop поддерживает такую реализацию, предоставляя все необходимые классы и
основные методы, которые обычно используются в модели Документ-Просмотр в шаблонах приложений для Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> и KDE.</para>

<para>Возвращаясь к коду, сейчас вы понимаете цели использования двух методов, которые мы упоминали в начале данного раздела:
функции <literal remap="tt">initDocument()</literal> и <literal remap="tt">initView()</literal>. <literal remap="tt">initDocument()</literal> создает объект документа, который представляет
данные окна приложения и инициализирует базисные атрибуты, такие как бит модификации, отображающий наличие изменений в текущих данных.
Затем метод <literal remap="tt">initView()</literal> создает видимый элемент <literal remap="tt">*View</literal>, связанный с документом, и
вызывает метод <literal remap="tt">setView()</literal> <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal>, чтобы сообщить окну <literal remap="tt">*App</literal>, что необходимо использовать элемент <literal remap="tt">*View</literal> как Просмотр.</para>

<para>Для разработчика необходимо знать, что в процессе разработки он должен:</para>

<para><itemizedlist>
<listitem>
<para>переопределить виртуальные методы для обработки событий мыши и клавиатуры, предоставляемые <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>, в объекте <literal remap="tt">*View</literal>, чтобы реализовать 
способы управления данными.</para>
</listitem>
<listitem>
<para>переопределить <literal remap="tt">paintEvent()</literal> класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal> в объекте <literal remap="tt">*View</literal> для перерисовки (repaint()) области просмотра после изменения,</para>
</listitem>
<listitem>
<para>доработать реализацию печати документа в методе печати объекта <literal remap="tt">*View</literal>,</para>
</listitem>
<listitem>
<para>научить объект <literal remap="tt">*Doc</literal> считыванию и записи файлов,</para>
</listitem>
<listitem>
<para>добавить реализацию структуры данных документа к объекту <literal remap="tt">*Doc</literal>, который логически представляет данные документа
в памяти.</para>
</listitem>
<listitem>
<para>добавить все методы, которые должны быть доступны пользователю через горячие клавиши, меню и панели инструментов.</para>
</listitem>
</itemizedlist>
</para>
</sect3>

<sect3 id="konfigurirovanie-prilozheniia">
<title>Конфигурирование приложения</title>

<para>Теперь, после того, как мы создали все элементы, инициируемые экземпляром <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal> нашего приложения, мы должны
установить определенные атрибуты, значения которых влияют на внешний вид нашего приложения. Для этого мы вызываем <literal remap="tt">readOptions()</literal>, которые
считывает все значения и вызывает методы, устанавливающие соответствующие атрибуты. Библиотека KDE-Core содержит класс <literal remap="tt"><indexterm remap="cdx"><primary><literal>KConfig</literal></primary></indexterm>KConfig</literal>, который предоставляет удобный
способ записи значений в конфигурационный файл, а также считывания их из файла снова. Поскольку каждый экземпляр <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal> 
создает по умолчанию свой ресурсный файл, мы должны только получить доступ к этому файлу и создать наши значения.  
<literal remap="tt"><indexterm remap="cdx"><primary><literal>KConfig</literal></primary></indexterm>KConfig</literal> предоставляет нам объект файла.
А мы используем класс <literal remap="tt"><indexterm remap="cdx"><primary><literal>KConfigBase</literal></primary></indexterm>KConfigBase</literal> для чтения и записи всех входов. Тогда как запись выполнить очень просто с помощью
метода <literal remap="tt">writeEntry()</literal>, чтение зависит от типа атрибута, который мы хотим инициализировать. Вообще говоря, все входы в конфигурационном файле
состоят из имени значения и значения. Значения, взаимосвязанные по смыслу, могут быть объединены в группы. 
Поэтому мы должны задать имя группы до того, как обратимся к значению. Группа должна быть определена только однажды для чтения набора атрибутов,
входящих в нее. Давайте посмотрим, что мы хотим читать:</para>

<para><screen>1   void KScribbleApp::readOptions()
2   {
3
4      config-&gt;setGroup("General Options");
5
6      // bar status settings
7      bool bViewToolbar = config-&gt;readBoolEntry("Show Toolbar", true);
8      view_menu-&gt;setItemChecked(ID_VIEW_TOOLBAR, bViewToolbar);
9      if(!bViewToolbar)
10       enableToolBar(KToolBar::Hide);
11
12     bool bViewStatusbar = config-&gt;readBoolEntry("Show Statusbar", true);
13     view_menu-&gt;setItemChecked(ID_VIEW_STATUSBAR, bViewStatusbar);
14     if(!bViewStatusbar)
15       enableStatusBar(KStatusBar::Hide);
16
17     // bar position settings
18     KMenuBar::menuPosition menu_bar_pos;
19     menu_bar_pos=(KMenuBar::menuPosition)config-&gt;readNumEntry("MenuBar Position", KMenuBar::Top);
20
21     KToolBar::BarPosition tool_bar_pos;
22     tool_bar_pos=(KToolBar::BarPosition)config-&gt;readNumEntry("ToolBar Position", KToolBar::Top);
23
24     menuBar()-&gt;setMenuBarPos(menu_bar_pos);
25     toolBar()-&gt;setBarPos(tool_bar_pos);
26
27     // initialize the recent file list
28     recent_files.setAutoDelete(TRUE);
29     config-&gt;readListEntry("Recent Files",recent_files);
30
31     uint i;
32     for ( i =0 ; i &lt; recent_files.count(); i++){
33       recent_files_menu-&gt;insertItem(recent_files.at(i));
34     }
35
36     QSize size=config-&gt;readSizeEntry("Geometry");
37     if(!size.isEmpty())
38       resize(size);
39   }
</screen>
</para>

<para>Как мы уже видели в одном из предыдущих примеров первое действие, которое делает наш конструктор:</para>

<para><screen>config=kapp-&gt;getConfig();
</screen>
</para>

<para>что устанавливает указатель <literal remap="tt">config</literal> типа <literal remap="tt"><indexterm remap="cdx"><primary><literal>KConfig</literal></primary></indexterm>KConfig</literal> на конфигурацию приложения. Поэтому мы не должны заботиться о расположении
конфигурационного файла. Этот файл, согласно стандарту файловой системы KDE (KDE File System Standard, KDE FSS), располагается в
<literal remap="tt">&&dollar;;HOME/.kde/share/config/</literal>; подробнее файловую систему KDE мы рассмотрим позднее, когда будем обсуждать расположение файлов в дистрибутиве приложения.
Поскольку конфигурационный файл располагается в домашнем каталоге пользователя, каждый пользователь имеет свои настройки внешнего вида приложения. 
Это не касается значений, определенных в общесистемном конфигурационном файле, который при необходимости может быть создан и инсталлирован
программистом в каталоге KDE. </para>

<para>Хотя это бывает полезно в некоторых случаях, мы должны избегать зависимости нашего приложения от существования
значения параметра в конфигурационном файле. Поэтому все методы чтения значений параметров, предоставляемые <literal remap="tt"><indexterm remap="cdx"><primary><literal>KConfigBase</literal></primary></indexterm>KConfigBase</literal>, позволяют добавить значение по умолчанию, которое будет использовано,
если не будет найдено в файле. Другой момент, важный для программиста, это то, что конфигурационный файл представляет собой обычный текстовый файл,
поэтому необходимо обратить внимание:</para>

<para><itemizedlist>
<listitem>
<para>пользователь может редактировать конфигурационный файл в текстовом редакторе,</para>
</listitem>
<listitem>
<para>если пользователь хочет изменить значения вручную, названия должны быть понятными,</para>
</listitem>
<listitem>
<para>для значений, которые необходимо сохранить, но которые критичны с точки зрения безопасности (пароли), необходимо предусмотреть соответствующее решение, обеспечивающее безопасность.</para>
</listitem>
</itemizedlist>
</para>

<para>Теперь, когда мы знаем теорию, начнем анализировать код. Как уже говорилось, мы должны использовать только наш указатель на конфигурацию для доступа к значениям.
В строке 4 мы делаем текущей группу "General Options".  Это означает, что входящие в нее значения устанавливают какие-то общие атрибуты
приложения. Затем мы считываем значения для панели инструментов и строки статуса - они должны быть сохранены приложением при закрытии,
чтобы восстановить их при перезапуске программы. Поскольку панели могут быть либо включены, либо выключены, мы используем значения типа boolean и
вызываем метод <literal remap="tt">readBoolEntry()</literal>. Процесс идентичен для обеих панелей, поэтому мы рассмотрим только строки 7-10, чтобы понять,
что происходит с панелью инструментов. Во-первых, мы читаем значение во временную переменную <literal remap="tt">bViewToolbar</literal> в строке 7. Имя атрибута
в конфигурационном файле "Show Toolbar", и, если такое значение отсутствует (например, при первом запуске приложения),
задаем значение по умолчанию <literal remap="tt">true</literal>. Потом мы устанавливаем пометку для пункта меню, отвечающего за разрешение/запрещение показа панели инструментов:
мы вызываем <literal remap="tt">setItemChecked()</literal> для входа меню <literal remap="tt">ID&&lowbar;;VIEW&&lowbar;;TOOLBAR</literal> с нашим атрибутом. Наконец, мы говорим панели инструментов
установить требуемое значение. По умолчанию панель видима, поэтому мы должны что-то делать только в том случае, если <literal remap="tt">bViewToolbar</literal> равно <literal remap="tt">false</literal>.
Вызывая <literal remap="tt">enableToolBar()</literal> (строка 10), мы скрываем панель, если она запрещена.</para>

<para>Теперь мы должны прочитать положение панели. Поскольку пользователь может изменить положение панели, переместив ее с помощью мыши
в другое место, это должно быть, как и отображение панели, также сохранено. Посмотрев на классы <literal remap="tt"><indexterm remap="cdx"><primary><literal>KToolBar</literal></primary></indexterm>KToolBar</literal> и
<literal remap="tt"><indexterm remap="cdx"><primary><literal>KMenuBar</literal></primary></indexterm>KMenuBar</literal>, мы видим, что положение панели может быть:</para>

<para><screen>enum BarPosition {Top, Left, Bottom, Right, Floating, Flat}
</screen>
</para>

<para>Поскольку это значение записывается в числовом виде, мы должны считывать его с помощью метода <literal remap="tt">readNumEntry()</literal> и преобразовывать в значение положения.
С помощью <literal remap="tt">setMenuBarPos()</literal> и <literal remap="tt">setBarPos()</literal> говорим панелям, где отображаться.</para>

<para>Сейчас вы, возможно, вспомните, что наше меню "File" содержит подменю со списком последних открытых файлов. Имена файлов занесены в список
строк, который сохраняется при закрытии приложения и сейчас должен быть считан для восстановления меню. Во-первых, мы инициализируем список
с занесенными в него значениями строк, используя <literal remap="tt">readListEntry()</literal>. Затем в цикле <literal remap="tt">for-</literal> мы создаем входы меню для каждого элемента списка.</para>

<para>Наконец, мы должны позаботиться о размерах окна нашего приложения. Мы считываем его расположение в переменную <literal remap="tt">QSize</literal>, содержащую x
и y значения для ширины и высоты окна. Поскольку окно инициализируется <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal>, мы не должны заботиться
о значениях по умолчанию, и только используем метод <literal remap="tt">resize()</literal>, если значение не пусто.</para>

<para>Нам еще осталось объяснить в создании приложения запрет команд, которые
не должны быть доступны, если не удовлетворяются определенные условия. Это сохранение файла и операции, которые используют буфер обмена. В течение
жизни приложения мы должны об этом позаботиться несколько раз, но это достаточно просто, так как шаблон дает нам только 
два метода для разрешения/запрещения команд меню и кнопок панели инструментов.</para>
</sect3>

<sect3 id="vypolnenie">
<title>Выполнение</title>

<para>В предыдущем разделе мы рассматривали только то, что происходит при вызове конструктора экземпляра нашего <literal remap="tt">KScribbleApp</literal>, готовящего для нас главное окно. 
После возвращения в функцию <literal remap="tt">main()</literal> мы должны вызвать метод <literal remap="tt">show()</literal> для того, чтобы отобразить окно. Чем отличаются
<literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal> и <literal remap="tt"><indexterm remap="cdx"><primary><literal>QApplication</literal></primary></indexterm>QApplication</literal> здесь, так это тем, что мы используем <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal> как экземпляр нашего
главного элемента (main widget), но мы не устанавливали его с помощью <literal remap="tt">setMainWidget()</literal>. Это делает <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal> самостоятельно, 
и мы не должны заботиться об этом.</para>

<para>Единственное, что осталось - это обработать аргументы командной строки. Если <literal remap="tt">int argc</literal> &gt; 1,
то пользователь вызвал приложение в виде <literal remap="tt">kscribble имя&&lowbar;;файла&&lowbar;;для&&lowbar;;открытия</literal>. Поэтому мы просим наше приложение
открыть файл <literal remap="tt">имя&&lowbar;;файла&&lowbar;;для&&lowbar;;открытия</literal>, вызывая метод <literal remap="tt">openDocumentFile()</literal> с аргументом, содержащим имя файла.</para>

<para>Последняя строка в <literal remap="tt">main()</literal> выполняет уже известную нам работу: она запускает на выполнение экземпляр приложения, и программа входит в
главный цикл событий.</para>

<para>Ранее, в разделе <link linkend="The-main-Function">Функция main()</link>, мы решили рассмотреть только обычный запуск приложения,
и не анализировали ветку <literal remap="tt">if( app.isRestored() )</literal>. Следующий материал является введением в менеджмент сессий, и объясняет,
как приложения используют этот механизм.</para>
</sect3>
</sect2>

<sect2 id="vvedenie-v-menedzhment-sessii-session-manage">
<title>Введение в Менеджмент сессий (Session Management)</title>

<para>Как мы уже говорили, функция <literal remap="tt">main()</literal> проверяет, запущено ли приложение пользователем или менеджером сессий. Менеджер сессий отвечает за
сохранение текущего состояния всех открытых окон приложения на рабочем столе и должен восстановить их, когда пользователь войдет в систему в следующий раз,
что значит, что приложение запускается не пользователем, а автоматически. Часть кода, которая выполняется:</para>

<para><screen>6    if (app.isRestored())
7    {
8       RESTORE(KScribbleApp);
9    }
</screen>
</para>

<para>В разделе <link linkend="The-main-Function">Функция main()</link> мы начинали с того, что проверяли метод вызова,
запрашивая <literal remap="tt">app.isRestored()</literal>. Затем выполняется строка 8. Она выглядит как простой оператор, но на самом деле это результат выполнения сложного
процесса, за которым мы проследим в этом разделе.</para>

<para>RESTORE() сам по себе - макрос, предоставляемый <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal>. Он содержит следующий код:</para>

<para><screen>if (app.isRestored()){
  int n = 1;
  while (KTMainWindow::canBeRestored(n)){
    (new KScribbleApp)-&gt;restore(n);
    n++;
  }
}
</screen>
</para>

<para>Это должно восстанавливать все окна приложения класса <literal remap="tt">KScribbleApp</literal>, создавая экземпляры и вызывая <literal remap="tt">restore()</literal> для
новых окон. Необходимо учесть, что, если ваше приложение использует несколько различных элементов, унаследованных от <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal>,
вы должны расширить макрос и определять тип верхнего элемента, используя <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow::classNameOfToplevel(n)</literal> вместо класса
<literal remap="tt">KScribbleApp</literal>.</para>

<para>Метод <literal remap="tt">restore()</literal> затем считывает часть файла сессии, которая содержит информацию об окне. Так как <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal>
запоминает все это для нас, мы не должны заботиться ни о чем больше. Только необходимо сделать так, чтобы специфичная для нашего экземпляра приложения информация 
была доступна <literal remap="tt">KScribbleApp</literal>. Обычно это будет временный файл, созданный для занесения в него документа,
или другая инициализация, которая нам необходима. Для предоставления этой информации по восстановлению мы должны только переопределить два виртуальных метода
<literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal>, <literal remap="tt">saveProperties()</literal> и <literal remap="tt">readProperties()</literal>. 
Информация, которую мы хотим сохранить в конце сессии, - был ли модифицирован текущий файл и имя файла.
Если файл был модифицирован, мы должны создать временный файл и сохранить модифицированный документ в него.
В начале следующей сессии эта информация используется для восстановления содержимого документа:</para>

<para><screen>void KScribbleApp::readProperties(KConfig*)
{
  QString filename = config-&gt;readEntry("filename","");
  bool modified = config-&gt;readBoolEntry("modified",false);
  if( modified ){
    bool b_canRecover;
    QString tempname = kapp-&gt;checkRecoverFile(filename,b_canRecover);

    if(b_canRecover){
      doc-&gt;openDocument(tempname);
      doc-&gt;setModified();
      QFileInfo info(filename);
      doc-&gt;pathName(info.absFilePath());
      doc-&gt;title(info.fileName());
      QFile::remove(tempname);
    }
  }
  else if(!filename.isEmpty()){
  doc-&gt;openDocument(filename);
  }
  setCaption(kapp-&gt;appName()+": "+doc-&gt;getTitle());
}		
</screen>
</para>

<para>Здесь строка <literal remap="tt">kapp-&gt;checkRecoverFile()</literal> выглядит несколько странно, так как <literal remap="tt">b&&lowbar;;canRecover</literal> не инициализирован. Это делается методом <literal remap="tt">checkRecoverFile()</literal>,
который устанавливает <literal remap="tt">true</literal>, если есть файл для восстановления. Поскольку мы сохраняем документ в файл для восстановления только в том случае, если он был изменен,
мы устанавливаем бит "модифицирован" непосредственно, чтобы показать, что информация не была сохранена в надлежащий файл. Также мы должны позаботиться,
чтобы файл для восстановления имел имя, отличное от имени открытого оригинала. Таким образом, мы должны переустановить имя и путь
для старого файла. Наконец, мы извлекли всю информацию для восстановления, какую хотели, и можем удалить временный файл.</para>

<para><emphasis remap="bf">Подведение итогов:</emphasis></para>

<para>В этой главе вы узнали, как запускается приложение при нормальном старте и при восстановлении менеджером сессий. Мы прошли
через весь код, разобравшись, как создаются части видимого интерфейса приложения, как инициализируются
атрибуты по значениям, сохраненным в конфигурационном файле. Сейчас вы можете запустить приложение, чтобы проверить его функции и посмотреть,
как реагирует окно программы на события.</para>
</sect2>
</sect1>

<sect1 id="dopolnitelnye-sostavliaiushchie-proekta-kdev">
<title>Дополнительные составляющие проекта KDevelop</title>

<para>Кроме исходного кода, проект KDevelop содержит множество других частей, интересных для разработчика. Это:
<itemizedlist>
<listitem>
<para>иконка программы,</para>
</listitem>
<listitem>
<para>мини-иконка программы,</para>
</listitem>
<listitem>
<para>файл .kdelnk <indexterm remap="idx"><primary>.kdelnk</primary></indexterm>, </para>
</listitem>
<listitem>
<para>пример SGML <indexterm remap="idx"><primary>SGML</primary></indexterm>-файла документации,</para>
</listitem>
<listitem>
<para>набор документации по API <indexterm remap="idx"><primary>API</primary></indexterm>, сгенерированный из исходного кода.</para>
</listitem>
</itemizedlist>
</para>

<para>Кроме API <indexterm remap="idx"><primary>API</primary></indexterm>-документации, эти элементы проекта будут инсталлированы вместе с бинарными файлами приложения. 
Чтобы проект был как можно более открытым, вы должны согласовать эти его части с функциями приложения. Во-первых, вы должны отредактировать иконки.
Это даст вашему приложению уникальный идентификатор, с помощью которого пользователь сможет узнать ваше приложение в окне
менеджера меню. Файл .kdelnk <indexterm remap="idx"><primary>.kdelnk</primary></indexterm> - это файл, который добавляет ваше приложение в <literal remap="tt">kpanel</literal> в меню <literal remap="tt">Applications</literal>.
Он должен быть отредактирован - необходимо установить путь для инсталляции, что будет обсуждаться далее в этой книге. Наконец, документация, которую вы
предоставите пользователю, пишется в SGML <indexterm remap="idx"><primary>SGML</primary></indexterm>. Это делает очень простым создание нескольких конечных файлов различных форматов из одного исходника. По умолчанию,
KDevelop предлагает создать HTML файлы из этого исходника, для KDE-проектов это делается автоматически с использованием <literal remap="tt">ksgml2html <indexterm remap="idx"><primary>ksgml2html</primary></indexterm></literal>,
что добавляет классический KDE-вид документации. В последующих главах мы увидим, как редактировать файл SGML <indexterm remap="idx"><primary>SGML</primary></indexterm>, 
и что мы предоставим конечному пользователю для инсталляции.</para>

<para>Наконец, API <indexterm remap="idx"><primary>API</primary></indexterm>-документация (Application Programming Interface) позволит вам и другим разработчикам быстро понять код
и использовать классы, не угадывая, для чего они предназначены. Мы научимся создавать API <indexterm remap="idx"><primary>API</primary></indexterm>-документацию позднее.
На текущий момент достаточно знать, что документация генерируется программой <literal remap="tt">KDoc <indexterm remap="idx"><primary>KDoc</primary></indexterm></literal>, которая обрабатывает файлы заголовков и создает
HTML документ, поэтому все подлежащие включению в документацию комментарии должны располагаться в заголовках.</para>
</sect1>
</chapter>

<chapter id="glavnoe-okno-prilozheniia">
<title>Главное окно приложения</title>

<para>При разработке приложения с графическим пользовательским интерфейсом наиболее трудоемкой является реализация так называемого элемента Просмотр ("view") приложения.
Просмотр - это видимый элемент, который отображает данные, содержащиеся в обрабатываемом приложением документе, и предоставляет методы для изменения
этих данных. Пользователь заставляет эти методы работать, порождая события клавиатуры и мыши; сложные операции часто
выполняются с помощью команд, генерируемых при выборе пунктов меню или кнопок панели управления, которые взаимодействуют с Просмотром. Строка статуса предоставляет информацию о
документе, о режиме работы объекта Просмотр и о состоянии приложения. Рассмотрим, например, как устроен текстовый редактор, и где реализованы его части.</para>

<para>Редактор обычно предназначен для просмотра и изменения текстового файла пользователем. Если вы
откроете <emphasis>KEdit</emphasis>, вы увидите следующие элементы пользовательского интерфейса:</para>

<para><itemizedlist>
<listitem>
<para>Панель меню: предоставляет возможность выполнять сложные операции, такие как открытие и закрытие файлов, выход из приложения и т.п.,</para>
</listitem>
<listitem>
<para>Панель инструментов: содержит иконки для быстрого доступа к наиболее часто используемым функциям,</para>
</listitem>
<listitem>
<para>Строка статуса: отображает координаты текущего положения курсора,</para>
</listitem>
<listitem>
<para>Объект Просмотр в центре окна: отображает документ и предоставляет связь курсора с клавиатурой и мышью для обработки данных.</para>
</listitem>
</itemizedlist>
</para>

<para>Теперь легко понять, что Просмотр - наиболее специализированная часть приложения, и от того, как он разработан, зависит полезность
приложения и удобство работы с ним. Это значит, что один из первых шагов при разработке приложения - это определение назначения
приложения и того, какой тип объекта Просмотра наилучшим образом позволит пользователю работать с приложением, с минимумом затрат на освоение пользовательского интерфейса.</para>

<para>Для некоторых стандартных задач, например, текстовой обработки или отображения HTML файлов, Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> и библиотеки KDE <indexterm remap="idx"><primary>библиотеки KDE</primary></indexterm> предоставляют специальные объекты просмотра; мы обсудим 
некоторые аспекты использования таких объектов высокого уровня в следующем разделе. Но для большинства приложений должны быть разработаны новые элементы.
Это момент, где программист становится также дизайнером, и где требуются его творческие способности. Однако не забывайте, что основное в пользовательском интерфейсе - это его интуитивность.
Помните, что многие пользователи не воспримут приложение, которое:</para>

<para><itemizedlist>
<listitem>
<para>некрасиво выглядит,</para>
</listitem>
<listitem>
<para>не предлагает широкого набора возможностей,</para>
</listitem>
<listitem>
<para>трудно в использовании,</para>
</listitem>
<listitem>
<para>тяжело для изучения.</para>
</listitem>
</itemizedlist>
</para>

<para>Однако не стоит даже говорить, что основной критерий качества разработки - стабильность. Никто не сможет предотвратить все ошибки,
но с помощью хорошо продуманного процесса разработки можно свести их число к минимуму. 
Четко определите цель и широко используйте методы объектно-ориентированного программирования. C++ сделает программирование удовольствием,
если вы будете знать, как использовать его возможности - наследование, ограничения доступа и повторное использование кода.</para>

<para>При создании KDE или Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> проекта вы всегда наследуете объект Просмотра от <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal> непосредственно или через использование библиотечного элемента,
унаследованного от <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>. KAppWizard уже создал объект Просмотра, который является экземпляром класса &lt;ваше&&lowbar;;приложение&gt;View, унаследованного от
<literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>. Приложение создает его в методе
<literal remap="tt">initView()</literal>, где создается экземпляр объекта, который затем устанавливается как главный с помощью <literal remap="tt">KTMainWidget::setView()</literal>.</para>

<para>Эта глава описывает, как использовать библиотеку элементов для создания главного объекта (объекта Просмотр) для KDE или Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> приложений,
которые разрабатываются с помощью KDevelop. Мы просмотрим библиотеки и узнаем, какие типы элементов они предлагают.</para>

<sect1 id="ispolzovanie-bibliotechnykh-elementov">
<title>Использование библиотечных элементов</title>

<para>Когда начинается разработка приложения, вы в первую очередь должны просмотреть уже существующий код, что сделает вашу жизнь гораздо легче.
Например, необходимо изучить уже существующие элементы, которые могут быть использованы в качестве объектов Просмотра или как их часть, как непосредственно, так и путем наследования.
Библиотеки KDE и Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> уже содержат набор элементов, которые могут быть использованы для этих целей. Вы имеете две возможности для их использования:</para>

<para><orderedlist><listitem>
<para> удалить объект Просмотра, включенный в шаблон, создать экземпляр библиотечного элемента и установить его как главный элемент;</para>
</listitem>
<listitem>
<para> изменить предка предложенного в шаблоне элемента на класс библиотечного элемента.</para>
</listitem>
</orderedlist>
</para>

<para>В любом случае, важно понимать, что если приложение на данный момент не линкуется с библиотекой, которая содержит новый элемент,
линкование завершится с ошибкой. После того, как вы решили использовать определенный элемент, посмотрите, с какой библиотекой необходимо связаться. Потом откройте
"Project"-&gt;"Options" из меню KDevelop, переключитесь на страницу "Linker Options" и посмотрите на то,
какие библиотеки используются на текущий момент. Если среди них есть библиотека, в которой содержится ваш элемент, вы можете закрыть окно опций проекта без изменений
и начать вносить необходимые изменения в ваш код. Если нет, и в опциях линкера есть возможность добавить необходимую библиотеку выбором соответствующего пункта,
выберите его и нажмите "OK", чтобы закрыть окно опций проекта. В любом другом случае добавьте библиотеку в строку ввода внизу окна с
опцией <literal remap="tt">-l</literal>. Для библиотек, которые ваше приложение должно искать перед генерацией файлов Makefiles в скрипте <literal remap="tt">configure</literal>
на машине пользователя, добавьте соответствующий макрос для поиска в файл <literal remap="tt">configure.in</literal>, расположенный в корневом каталоге проекта, и
добавьте макрос для изменения строки. Имейте в виду, что вы должны запустить "Build"-&gt;"Autoconf" и "Build"-&gt;"Configure" для того, чтобы
в файлы Makefile была записана правильная информация о макросе для вашей библиотеки.</para>

<para>Кроме того, если include-файлы добавленной библиотеки не попадают в текущий путь для поиска include-файлов (каталоги, заданные с помощью ключа <literal remap="tt">-I</literal> 
в окне вывода информации о работе "Make"), вы должны добавить путь в диалоговом окне Project Options - страница "Compiler Options", с ключом <literal remap="tt">-I</literal>, 
или соответствующий макрос automake в строке ввода "Additional Options".</para>

<sect2 id="elementy-qt-qt">
<title>Элементы Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> </title>

<para>На первой странице Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> online-документации вы найдете ссылку на картинки элементов "Widget Screenshots", где сможете посмотреть,
как выглядят различные элементы Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>. Все они готовы к использованию и могут быть объединены вместе для создания 
сложных главных окон приложений или диалогов. Далее мы описываем некоторые из этих элементов, которые очень полезны при разработке приложений и элементов Просмотр,
но имейте в виду, что библиотеки KDE <indexterm remap="idx"><primary>библиотеки KDE</primary></indexterm> иногда содержат другие элементы, выполняющие те же задачи; их мы обсудим в следующем разделе.</para>

<para>Перед вами несколько подсказок, для каких целей какие элементы Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> использовать:</para>

<para><orderedlist><listitem>
<para>если ваша область просмотра недостаточно велика, чтобы вместить все данные, необходимо обеспечить пользователю возможность прокрутки (скроллинга)
с помощью полос прокрутки справа и внизу. Для этого Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> предоставляет класс <literal remap="tt">QScrollView</literal>, у которого имеется пользовательская область с обеспечением прокрутки.
Вы можете наследовать свой собственный элемент от <literal remap="tt">QScrollView</literal> или использовать его экземпляр для организации просмотра в вашем приложении.</para>
</listitem>
<listitem>
<para>для создания прокручиваемой области самостоятельно наследуйте объект Просмотра от класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal> и добавьте к нему вертикальную и горизонтальную прокрутку <literal remap="tt">QScrollBar</literal>
(это сделано в KDE для элемента KHTMLView);</para>
</listitem>
<listitem>
<para>для текстовой обработки используйте <literal remap="tt">QMultiLineEdit</literal>. Этот класс предоставляет полнофункциональный текстовый редактор, умеющий
работать с буфером обмена и полосами прокрутки;</para>
</listitem>
<listitem>
<para>используйте <literal remap="tt">QTableView</literal>, чтобы отобразить данные в табличной форме. <literal remap="tt">QTableView</literal> управляется полосами прокрутки,
поэтому он - хорошее решение для приложения типа электронных таблиц.</para>
</listitem>
<listitem>
<para>для одновременного отображения двух различных элементов или двух экземпляров элемента используйте <literal remap="tt">QSplitter</literal>. Это позволит разделить
область просмотра горизонтально или вертикально. Окно Netscape's Mail - хороший пример того, как это выглядит. Главное окно разделено
по вертикали, а правая часть снова разделена по горизонтали.</para>
</listitem>
<listitem>
<para><literal remap="tt">QListView</literal> отображает информацию в виде дерева. Это полезно для представления дерева каталогов или другой иерархической информации, которую необходимо обрабатывать.</para>
</listitem>
</orderedlist>
</para>

<para>Как видно, Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> предоставляет полный набор элементов, уже готовых к использованию, поэтому вы не должны изобретать новых решений,
если они удовлетворяют вашим требованиям. Еще одно преимущество использования стандартных элементов - пользователь уже знает, как с ними работать, и сможет 
сконцентрироваться не на интерфейсе, а на обрабатываемых данных.</para>
</sect2>

<sect2 id="elementy-kde">
<title>Элементы KDE</title>

<para>Библиотеки KDE созданы для облегчения разработки приложений K Desktop Environment, и поддерживают всю функциональность,
реализованную в Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>. Чтобы определить, что нам доступно, посмотрим на дерево документации в KDevelop. Мы видим, что библиотеки KDE
начинаются с <literal remap="tt">kdecore</literal>, которая является основой для всех приложений KDE. Идущая следом <literal remap="tt">kdeui</literal> предоставляет элементы пользовательского интерфейса.
Здесь мы найдем несколько полезных вещей. Для создания приложений <literal remap="tt">kdeui</literal> предлагает:</para>

<para><orderedlist><listitem>
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>KTabListBox</literal></primary></indexterm>KTabListBox</literal>: список с несколькими столбцами, строки которого можно изменять с помощью drag'n drop <indexterm remap="idx"><primary>drag'n drop</primary></indexterm>.</para>
</listitem>
<listitem>
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>KTreeList</literal></primary></indexterm>KTreeList</literal>: унаследованный от <literal remap="tt"><indexterm remap="cdx"><primary><literal>QTableView</literal></primary></indexterm>QTableView</literal>, реализует дерево с возможностью показа/скрытия веток. Может быть использован вместо
<literal remap="tt">QListView</literal>. В KDE 2.0 этот класс реализован не будет.</para>
</listitem>
<listitem>
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>KEdit</literal></primary></indexterm>KEdit</literal>: базовый класс для приложения <emphasis>KEdit</emphasis>, поставляемого вместе с KDE;
может использоваться вместо <literal remap="tt"><indexterm remap="cdx"><primary><literal>QMultiLineEdit</literal></primary></indexterm>QMultiLineEdit</literal>.</para>
</listitem>
<listitem>
<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>KNewPanner</literal></primary></indexterm>KNewPanner</literal>: Управляет двумя дочерними элементами как <literal remap="tt"><indexterm remap="cdx"><primary><literal>QSplitter</literal></primary></indexterm>QSplitter</literal>. В KDE 2.0 этот класс реализован не будет.</para>
</listitem>
</orderedlist>
</para>

<para>Библиотека <literal remap="tt">khtmlw</literal> предоставляет полнофункциональный интерпретатор HTML документов, готовый к использованию. Он поддерживает прокрутку,
поэтому вы не должны о ней заботиться.  Может быть полезен как интегрированное средство просмотра в HTML-редакторе; используется такими приложениями,
как KFM, KDEHelp <indexterm remap="idx"><primary>KDEHelp</primary></indexterm> и KDevelop для показа HTML файлов.</para>
</sect2>
</sect1>

<sect1 id="creating-your-own-views">
<title>Создание собственного элемента просмотра</title>

<para>Теперь, когда вы получили общее представление о предоставляемых возможностях, можно заметить, что для большинства задач уже существуют элементы,
которые могут быть использованы самостоятельно или объединены с другими. KMail и сам KDevelop - хорошие примеры использования библиотечных элементов для отображения данных.</para>

<para>Для приложений, которые используют специфические форматы файлов или имеют дело с графикой, вы, вероятно, будете вынуждены создать свой собственный элемент просмотра
для организации обработки данных. Это реализуется в нашем примере с помощью класса <literal remap="tt">KScribbleView</literal>, уже имеющего все необходимое для области просмотра.</para>

<para>При наследовании от <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal> необходимо переопределить виртуальные методы для обработки пользовательских событий, что, вероятно, будет основной работой;
кроме того, необходимо реализовать всплывающие меню для быстрого доступа к функциям. Вероятно, вам также придется реализовать несколько слотов,
которые будут доступны через кнопки панели инструментов или пункты меню, а также методы управления различными переменными, например, 
цветом кисточки в графическом редакторе.</para>

<para>Повторим для полноты подлежащие переопределению методы:</para>

<para><emphasis remap="bf">a) События клавиатуры -- клавиши TAB и  Shift-TAB :</emphasis></para>

<para>изменяет фокус ввода с клавиатуры с текущего элемента на следующий элемент в порядке изменения фокусов. Фокус может быть установлен для элемента
вызовом <literal remap="tt">setFocusPolicy<indexterm remap="ncdx"><primary><literal>setFocusPolicy()</literal></primary></indexterm>()</literal>. Изменение фокуса обрабатывается следующими обработчиками событий: :</para>

<para><itemizedlist>
<listitem>
<para><literal remap="tt">virtual void focusInEvent<indexterm remap="ncdx"><primary><literal>focusInEvent()</literal></primary></indexterm> ( <indexterm remap="cdx"><primary><literal>QFocusEvent</literal></primary></indexterm>QFocusEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void focusOutEvent<indexterm remap="ncdx"><primary><literal>focusOutEvent()</literal></primary></indexterm> ( <indexterm remap="cdx"><primary><literal>QFocusEvent</literal></primary></indexterm>QFocusEvent * )</literal></para>
</listitem>
</itemizedlist>
</para>

<para><emphasis remap="bf">b) другой ввод с клавиатуры:</emphasis>
<itemizedlist>
<listitem>
<para><literal remap="tt">virtual void keyPressEvent<indexterm remap="ncdx"><primary><literal>keyPressEvent()</literal></primary></indexterm> ( <indexterm remap="cdx"><primary><literal>QKeyEvent</literal></primary></indexterm>QKeyEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void keyReleaseEvent<indexterm remap="ncdx"><primary><literal>keyReleaseEvent()</literal></primary></indexterm> ( <indexterm remap="cdx"><primary><literal>QKeyEvent</literal></primary></indexterm>QKeyEvent * )</literal></para>
</listitem>
</itemizedlist>
</para>

<para><emphasis remap="bf">c) перемещение мыши:</emphasis>
<itemizedlist>
<listitem>
<para><literal remap="tt">virtual void mouseMoveEvent ( <indexterm remap="cdx"><primary><literal>QMouseEvent</literal></primary></indexterm>QMouseEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void enterEvent ( <indexterm remap="cdx"><primary><literal>QEvent</literal></primary></indexterm>QEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void leaveEvent ( <indexterm remap="cdx"><primary><literal>QEvent</literal></primary></indexterm>QEvent * )</literal></para>
</listitem>
</itemizedlist>
</para>

<para><emphasis remap="bf">d) нажатие кнопок мыши:</emphasis>
<itemizedlist>
<listitem>
<para><literal remap="tt">virtual void mousePressEvent ( <indexterm remap="cdx"><primary><literal>QMouseEvent</literal></primary></indexterm>QMouseEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void mouseReleaseEvent ( <indexterm remap="cdx"><primary><literal>QMouseEvent</literal></primary></indexterm>QMouseEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void mouseDoubleClickEvent ( <indexterm remap="cdx"><primary><literal>QMouseEvent</literal></primary></indexterm>QMouseEvent * )</literal></para>
</listitem>
</itemizedlist>
</para>

<para><emphasis remap="bf">e) события окна, содержащего элемент:</emphasis>
<itemizedlist>
<listitem>
<para><literal remap="tt">virtual void moveEvent ( <indexterm remap="cdx"><primary><literal>QMoveEvent</literal></primary></indexterm>QMoveEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void resizeEvent ( <indexterm remap="cdx"><primary><literal>QResizeEvent</literal></primary></indexterm>QResizeEvent * )</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">virtual void closeEvent ( <indexterm remap="cdx"><primary><literal>QCloseEvent</literal></primary></indexterm>QCloseEvent * )</literal></para>
</listitem>
</itemizedlist>
</para>

<para>Когда вы переопределяете эти функции, вы должны учесть некоторые моменты, чтобы избежать ошибок, которые 
сделают невозможным изменение поведения элементов в дальнейшем:</para>

<para><orderedlist><listitem>
<para>объявляйте ваши виртуальные методы как <emphasis remap="bf">virtual</emphasis> в секции <emphasis remap="bf">protected</emphasis>. Это позволит переиспользовать код при наследовании
и обеспечит логическую целостность;</para>
</listitem>
<listitem>
<para>не включайте в текст программы, реализующей обработку событий, непосредственно (hard-code) ничего такого, что может конфигурироваться. Это в основном относится к событиям клавиатуры,
которые реализуются через горячие клавиши и состоят в вызове функций. Данное замечание касается даже текстовой обработки! (Вообразите себе, что множество пользователей
привыкли к своему любимому текстовому редактору. Если горячие клавиши конфигурируются, то они смогут использовать привычные для себя настройки);</para>
</listitem>
<listitem>
<para>передавайте сигналы, генерируемые при подсветке пунктов меню, главному элементу, чтобы обеспечить подсказки в строке статуса.</para>
</listitem>
</orderedlist>
</para>
</sect1>
</chapter>

<chapter id="configuring-menubars-and-toolbars">
<title>Конфигурирование меню и панелей инструментов</title>

<para>Меню и панели инструментов - одна из наиболее важных частей приложения для обеспечения работы с документом.
Как правило, вы должны сделать доступными все функции через меню. Те пункты меню, которые вызывают функции, недоступные в текущем состоянии приложения,
должны быть запрещены.</para>

<para>Далее, приложение может содержать только одну панель меню, но несколько панелей инструментов. </para>

<para>Панель инструментов должна содержать только наиболее часто используемые функции,
которые должны вызываться нажатием кнопок с иконками; также в состав панелей инструментов могут входить выпадающие списки для выбора значений.</para>

<sect1 id="kak-oni-rabotaiut">
<title>Как они работают ?</title>

<para>Каждый вход меню или кнопка панели инструментов имеет ресурсный идентификатор (ID), представляющий собой число типа integer. Поскольку данные значения не могут использоваться дважды,
они представляются макросами. В макросах числовое значение заменяется осмысленным названием, используемым в коде программы.</para>

<para>Все ресурсные ID собраны в файле <literal remap="tt">resource.h</literal>, где можно посмотреть, какие числа уже задействованы. В любом случае, компилятор
проинформирует вас, если вы дважды используете одно и то же число для различных входов. Кроме того, ресурсный файл должен содержать все клавиши быстрого доступа к меню,
заменяемые в IDK-макросе(?). Например:</para>

<para><programlisting>(resource.h)

#define ID_VIEW_TOOLBAR             12010


(kscribble.cpp)

// menu entry Toolbar in the "view" menubar menu
view_menu-&gt;insertItem(i18n("&&amp;;Toolbar"), ID_VIEW_TOOLBAR);
</programlisting>
</para>

<para>Этот код добавляет вход Toolbar в меню View панели меню приложения kscribble. Имя ресурсного ID
состоит из имени меню и имени входа, как видно. Амперсант, стоящий перед буквой, заставляет ее работать как горячую клавишу,
а само имя входа передается с использованием макроса интернационализации i18n().</para>

<para>При активации входа меню вызывается конструкция switch функции commandCallback() с ID меню. Поэтому вы должны добавить соответствующее сравнение
в конструкцию switch и функцию, которую необходимо выполнить при выборе данного входа меню:</para>

<para><programlisting>    case ID_VIEW_TOOLBAR:
    	slotViewToolBar();
    	break;</programlisting>
</para>

<para>Заметьте, что вы не обязаны использовать систему ID. Если не задан никакой ID, меню нумеруется автоматически. 
KDevelop использует систему ID для того, чтобы иметь возможность создать конструкции switch для выбора выполняемого слота при
поступлении сигнала <literal remap="tt">activated()</literal> для меню и <literal remap="tt">clicked()</literal> для кнопок панели инструментов. 
Однако эта связь может быть реализована непосредственно, используя соответствующие методы классов меню и панели инструментов.</para>
</sect1>

<sect1 id="dobavlenie-novogo-meniu">
<title>Добавление нового меню</title>

<para>Новое меню добавляется в приложение так:</para>

<para><orderedlist><listitem>
<para>добавьте указатель на новое меню в заголовке класса приложения (App-class);</para>
</listitem>
<listitem>
<para>вызовите конструктор <literal remap="tt"><indexterm remap="cdx"><primary><literal>QPopupMenu</literal></primary></indexterm>QPopupMenu</literal> для указателя в <literal remap="tt">initMenuBar()</literal> там, где должна появиться ваша панель меню в дальнейшем;</para>
</listitem>
<listitem>
<para>добавьте соответствующие пункты меню в выпадающие меню и установите их ресурсные ID в файле ресурсов;</para>
</listitem>
<listitem>
<para>добавьте связи меню с <literal remap="tt">commandCallback()</literal> и <literal remap="tt">statusCallback()</literal> в конце <literal remap="tt">initMenuBar()</literal>;</para>
</listitem>
<listitem>
<para>добавьте методы, которые будут вызываться при выборе входов меню, в заголовки и файлы реализации;</para>
</listitem>
<listitem>
<para>добавьте конструкции switch для входов в <literal remap="tt">commandCallback()</literal> и <literal remap="tt">statusCallback()</literal>;</para>
</listitem>
</orderedlist>
</para>
</sect1>

<sect1 id="ispolzovanie-knopok-panelei-instrumentov">
<title>Использование кнопок панелей инструментов</title>

<para>Кнопки панелей инструментов могут быть добавлены аналогично входам меню, но с тем отличием, что используемый метод - <literal remap="tt">insertButton()</literal>. 
Этот метод принимает в качестве аргументов иконку и всплывающую подсказку вместо текста меню.</para>

<para>Иконки, которые вы хотите использовать, загружаются с помощью <literal remap="tt">KIconLoader</literal>. <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal> предоставляет макросы <literal remap="tt">ICON()</literal> и <literal remap="tt">Icon()</literal> 
для доступа к <literal remap="tt">KIconLoader</literal> и загрузки иконок. Эти макросы получают в качестве параметра имя файла иконки для ее загрузки из
файловой системы KDE, производя в ней поиск в определенном порядке (см. <literal remap="tt">KIconLoader</literal> для уточнения этого порядка).</para>

<para>Библиотеки KDE <indexterm remap="idx"><primary>Библиотеки KDE</primary></indexterm> также предоставляют набор кнопок для панелей инструментов, которые используются для выполнения стандартных действий. В случае, когда они не удовлетворяют ваших потребностей,
вы должны самостоятельно нарисовать иконки. KDevelop поможет вам это сделать - выберите "New" из меню "File", затем выберите тип файла Pixmap.
Обычно иконки для панели инструментов располагаются в поддиректории проекта "toolbar <indexterm remap="idx"><primary>toolbar</primary></indexterm>" и инсталлируются оттуда в специфичный для вашего приложения
KDE каталог "toolbar <indexterm remap="idx"><primary>toolbar</primary></indexterm>".</para>
</sect1>

<sect1 id="konfiguratsiia-stroki-statusa">
<title>Конфигурация строки статуса</title>

<para>Шаблон проекта KDevelop уже использует строку статуса, отображая в ней справку о назначении входов меню и кнопок панели инструментов.
При добавлении входа меню также добавляйте справочное сообщение в метод <literal remap="tt">statusCallback()</literal>.</para>

<para><literal remap="tt">statusCallback()</literal> использует метод <literal remap="tt">slotStatusHelpMsg()</literal> для показа сообщения в строке статуса в течение 2 секунд.
Когда выполняется команда, вы должны использовать метод <literal remap="tt">slotStatusMsg()</literal> в начале выполнения со строкой, поясняющей, что приложение делает;
перед окончанием операции вы должны установить сообщение в строке статуса "Ready.", вызывая тот же метод.</para>
</sect1>

<sect1 id="konfiguratsiia-goriachikh-klavish">
<title>Конфигурация горячих клавиш</title>

<para>Очень профессиональная вещь, которую вы всегда должны добавлять в ваше приложение, - это горячие клавиши. Они обычно используются опытными пользователями,
которые хотят работать с приложением быстро и готовы изучить горячие клавиши. Для них библиотека KDE предоставляет класс
<literal remap="tt"><indexterm remap="cdx"><primary><literal>KAccel</literal></primary></indexterm>KAccel</literal>, который реализует горячие клавиши и обеспечивает доступ к стандартной глобальной конфигурации горячих клавиш.</para>

<para>По умолчанию, приложение, сгенерированное KDevelop, использует только стандартные горячие клавиши, такие как F1 для получения помощи,
Ctrl+N для создания нового файла. Перед добавлением новой комбинации клавиш вы должны посмотреть, а не определена ли она уже.</para>

<para>Если ваше приложение содержит множество горячих клавиш, вы должны сделать их конфигурируемыми через меню Options; они могут совпадать с конфигурацией других приложений
или использоваться только в вашем. Библиотека KDE предоставляет класс <literal remap="tt">KKeyChooser</literal> для использования в многостраничном диалоге,
тогда как <literal remap="tt">KKeyDialog</literal> дает готовое диалоговое окно для конфигурации горячих клавиш.</para>

<para>Для более детальной информации см. следующие классы:
<literal remap="tt"><indexterm remap="cdx"><primary><literal>KAccel</literal></primary></indexterm>KAccel</literal>(<indexterm remap="cdx"><primary><literal>kdecore</literal></primary></indexterm>kdecore), <literal remap="tt"><indexterm remap="cdx"><primary><literal>KKeyChooser</literal></primary></indexterm>KKeyChooser</literal>, <literal remap="tt"><indexterm remap="cdx"><primary><literal>KKeyDialog</literal></primary></indexterm>KKeyDialog</literal> (<indexterm remap="cdx"><primary><literal>kdeui</literal></primary></indexterm>kdeui).</para>
</sect1>
</chapter>

<chapter id="redaktor-dialogovykh-okon-dialogeditor-gde-s">
<title>Редактор диалоговых окон  Dialogeditor: Где строятся диалоги</title>

<sect1 id="chto-predlagaet-dialogeditor">
<title>Что предлагает Dialogeditor</title>

<para>Встроенный в KDevelop редактор диалогов разработан для того, чтобы помочь создавать диалоги, которые требуются для вашего приложения,
и тем самым резко уменьшить время, расходуемое на построение графического пользовательского интерфейса. Единственное ограничение на сегодняшний день состоит в том, что Dialogeditor не поддерживает
управление геометрическими размерами элементов, которое предоставляется Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>; поэтому диалоговые окна получаются статическими в своих размерах, что при определенных условиях может привести
к нарушениям во внешнем виде приложения, например, текст метки после перевода приложения на другой язык окажется слишком длинным и не поместится в отведенном для него пространстве.</para>

<para>Но текущее состояние редактора в сочетании с возможностями по управлению проектом KDevelop обеспечивает скорейший путь для создания
полнофункциональных приложений для K Desktop Environment.</para>
</sect1>

<sect1 id="elementy-qt-qt-i-kde">
<title>Элементы Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> и KDE</title>

<para>На текущий момент доступны следующие элементы:</para>

<para><emphasis remap="bf">QT-элементы:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</emphasis> - элемент, который может использоваться сам по себе, и может содержать другие элементы. Это позволяет создать иерархию элементов внутри вашего диалога.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">QLabel <indexterm remap="idx"><primary>QLabel</primary></indexterm></emphasis> - метка, представляющая текстовую информацию на элементе. Используется QLabel <indexterm remap="idx"><primary>QLabel</primary></indexterm>, например, напротив строк ввода
для пояснения их предназначения или возле выпадающего списка для указания названия устанавливаемого параметра.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">QPushButton</emphasis> - кнопка, позволяющая, например, вызвать другое диалоговое окно типа QFileDialog для выбора имени файла.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">QCheckBox</emphasis> - элемент, показывающий, разрешена или запрещена опция. QCheckBox широко используется в диалоговых окнах конфигурации.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">QLCDNumber</emphasis> - отображает номер как на жидкокристаллическом (LCD) экране. Часто используется как часы.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">QRadioButton</emphasis> - как и QCheckBox, позволяет пользователю выбрать опцию. QRadioButton используется для установки опций, когда
они являются взаимозависимыми, например, вы имеете 3 кнопки, но выбрана может быть только одна из них. См.
<literal remap="tt"><indexterm remap="cdx"><primary><literal>QButtonGroup</literal></primary></indexterm>QButtonGroup</literal> для более детальной информации.</para>
</listitem>
<listitem>
<para><emphasis remap="bf"><indexterm remap="cdx"><primary><literal>QComboBox</literal></primary></indexterm>QComboBox</emphasis> - позволяет пользователю установить значение, выбирая его из
выпадающего меню, или ввести значение, если элемент сконфигурирован доступным для этого.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">QListBox</emphasis> - предоставляет список элементов, состоящий из одной колонки, с возможностью прокрутки.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">QListView</emphasis> - создает многоколонный список, который может быть использован для отображения, например, иерархии каталогов в виде таблицы или дерева.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">QMultiLineEdit</emphasis> - предоставляет многострочный текстовый редактор.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">QProgressBar</emphasis> - показывает степень выполнения действия, если оно занимает много времени.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">QSpinBox</emphasis> - позволяет выбрать числовое значение с помощью стрелок вверх/вниз, или ввести его непосредственно в поле ввода, если позволяет конфигурация.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">QSlider</emphasis> - устанавливает значение в заданном программой диапазоне.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">QScrollBar</emphasis> - показывает диапазон изменения значения и устанавливает текущее значение с помощью ползунка и кнопок вверх/вниз; часто
используется для элементов, чье содержимое больше видимой области. С его использованием организуется прокрутка и видимая область элемента может меняться.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">QGroupBox</emphasis> - предоставляет фрейм с заголовком, чтобы показать, что элементы внутри сгруппированы.</para>
</listitem>
</itemizedlist>
</para>

<para><emphasis remap="bf">KDE-элементы:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">KColorButton</emphasis> - кнопка, отображающая выбранный цвет. При нажатии вызывается KDE-окно выбора цвета, в котором пользователь
может выбрать другой цвет. Часто используется для приложений типа графического редактора и в других случаях, когда может быть выбран цвет.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">KCombo</emphasis> - аналогичен <literal remap="tt"><indexterm remap="cdx"><primary><literal>QComboBox</literal></primary></indexterm>QComboBox</literal>. Позволяет пользователю выбирать значение из выпадающего списка.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">KDatePicker</emphasis> - мощный элемент для ввода даты пользователем.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">KDateTable</emphasis> - табличка календаря для выбора дня месяца. Используется <literal remap="tt">KDatePicker</literal> для построения диалога ввода даты.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">KKeyButton</emphasis> - кнопка для выбора значения клавиши. Если кнопка выбрана, то она активируется, и нажатие клавиши на клавиатуре
изменяет установленный для кнопки код. Может быть использована для конфигурирования обработки клавиатурных команд.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">KLed</emphasis> - LED (Light Emitting Diode), светящийся диод. Предназначен для отображения текущего состояния.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">KLedLamp</emphasis> - аналогичен <emphasis remap="bf">KLed</emphasis>, но поддерживает нажатие мышью.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">KProgress</emphasis> - аналогичен <literal remap="tt">QProgressBar</literal>, но поддерживает другие диапазоны значений.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">KRestrictedLine</emphasis> - <literal remap="tt">QLineEdit</literal> с возможностями фильтрации ввода. Может быть использован для создания окна ввода пароля.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">KSeparator</emphasis> - разделитель, который используется во всех случаях, где необходимо что-то отделить от чего-то.
Часто используется в диалогах для выделения логических частей там, где не может быть использован <literal remap="tt">QGroupBox</literal>.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">KTreeList</emphasis> - сворачивающийся список для отображения деревьев, похожий на <literal remap="tt">QListView</literal>.</para>
</listitem>
</itemizedlist>
</para>
</sect1>

<sect1 id="svoistva-elementov-qt-qt">
<title>Свойства элементов Qt <indexterm remap="idx"><primary>Qt</primary></indexterm></title>

<para>Эта глава дает полный обзор поддерживаемых в настоящее время элементов Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>. Чтобы достичь лучшего понимания
назначения свойств, они разделены в соответствии с иерархией наследования. Так как все элементы имеют предком <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>, этот класс описан
первым. Все свойства <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal> доступны для всех остальных элементов, поэтому повторно не приводятся. Для групп элементов,
которые унаследованы от абстрактных подклассов (<literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal> - базовый класс), свойства базового класса приведены вначале 
(хотя этот класс и не предоставляет видимых элементов в редакторе диалогов).
Затем приводятся свойства для доступных элементов группы, содержащих специфичные опции.
Для лучшего понимания иерархии наследования дерево, представляющее ее, приводится ниже:</para>

<para><itemizedlist>
<listitem>
<para><link linkend="QWidget">QWidget</link>
<itemizedlist>
<listitem>
<para><link linkend="QButton">QButton</link> (abstract)
<itemizedlist>
<listitem>
<para><link linkend="QCheckBox">QCheckBox</link></para>
</listitem>
<listitem>
<para><link linkend="QPushButton">QPushButton</link></para>
</listitem>
<listitem>
<para><link linkend="QRadioButton">QRadioButton</link></para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><link linkend="QComboBox">QComboBox</link></para>
</listitem>
<listitem>
<para><link linkend="QFrame">QFrame</link> (abstract for now)
<itemizedlist>
<listitem>
<para><link linkend="QGroupBox">QGroupBox</link></para>
</listitem>
<listitem>
<para><link linkend="QLCDNumber">QLCDNumber</link></para>
</listitem>
<listitem>
<para><link linkend="QLabel">QLabel</link></para>
</listitem>
<listitem>
<para><link linkend="QProgressBar">QProgressBar</link></para>
</listitem>
<listitem>
<para><link linkend="QScrollView">QScrollView</link> (abstract for now)
<itemizedlist>
<listitem>
<para><link linkend="QListView">QListView</link></para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><link linkend="QSpinBox">QSpinBox</link></para>
</listitem>
<listitem>
<para><link linkend="QTableView">QTableView</link> (abstract)
<itemizedlist>
<listitem>
<para><link linkend="QListBox">QListBox</link></para>
</listitem>
<listitem>
<para><link linkend="QMultiLineEdit">QMultiLineEdit</link></para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><link linkend="QLineEdit">QLineEdit</link></para>
</listitem>
<listitem>
<para><link linkend="QScrollBar">QScrollBar</link></para>
</listitem>
<listitem>
<para><link linkend="QSlider">QSlider</link></para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>

<sect2 id="qwidget">
<title>Свойства <indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget </title>

<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal> - базовый класс почти для всех элементов Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> и KDE. Поэтому элементы, унаследованные от <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>, позволяют использовать те же
установки в большинстве случаев.</para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">Appearance:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">BgColor:</emphasis> Цвет заднего плана (background) элемента</para>
</listitem>
<listitem>
<para><emphasis remap="bf">BgMode:</emphasis> Режим заднего плана элемента</para>
</listitem>
<listitem>
<para><emphasis remap="bf">BgPalColor:</emphasis> Цветовая палитра заднего плана элемента</para>
</listitem>
<listitem>
<para><emphasis remap="bf">BgPixmap:</emphasis> Имя файла картинки заднего плана элемента</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Cursor:</emphasis> Курсор над элементом</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Font:</emphasis> Шрифт элемента</para>
</listitem>
<listitem>
<para><emphasis remap="bf">MaskBitmap:</emphasis> Имя файла для накладываемого точечного рисунка (masking bitmap)</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><emphasis remap="bf">C++ Code:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">AcceptsDrops:</emphasis> если установлено в true, экземпляр элемента воспринимает механизм drag'n drop <indexterm remap="idx"><primary>drag'n drop</primary></indexterm> Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>-протокола, не KDE 1.x !</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Connections:</emphasis> соединение сигналов и слотов элемента</para>
</listitem>
<listitem>
<para><emphasis remap="bf">FocusProxy:</emphasis> элемент, предоставляющий фокус данному элементу</para>
</listitem>
<listitem>
<para><emphasis remap="bf">HasFocus:</emphasis> устанавливается, если элемент имеет фокус по умолчанию. Помните, что только один объект в диалоге может иметь данное свойство равным true</para>
</listitem>
<listitem>
<para><emphasis remap="bf">ResizeToParent:</emphasis> изменяет размер элемента до размера родителя (не виден в режиме редактирования)</para>
</listitem>
<listitem>
<para><emphasis remap="bf">VarName:</emphasis> имя переменной объекта. Измените это на имя, описывающее предназначение элемента.</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">IsEnabled:</emphasis> устанавливается, если элемент должен принимать пользовательские события</para>
</listitem>
<listitem>
<para><emphasis remap="bf">IsHidden:</emphasis> делает элемент невидимым (true) или видимым (false)</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Name:</emphasis> устанавливает имя элемента. Помните, что имя отличается от VarName в коде C++.</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Geometry:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">Height:</emphasis> высота элемента</para>
</listitem>
<listitem>
<para><emphasis remap="bf">IsFixedSize:</emphasis> true - имеет фиксированный размер</para>
</listitem>
<listitem>
<para><emphasis remap="bf">MaxHeight:</emphasis> максимальное значение для высоты  Height</para>
</listitem>
<listitem>
<para><emphasis remap="bf">MaxWidth:</emphasis>  максимальное значение для ширины Width</para>
</listitem>
<listitem>
<para><emphasis remap="bf">MinHeight:</emphasis> минимальное значение для высоты Height</para>
</listitem>
<listitem>
<para><emphasis remap="bf">MinWidth:</emphasis> минимальное значение для ширины Width</para>
</listitem>
<listitem>
<para><emphasis remap="bf">SizeIncX:</emphasis> количество пикселей в одном шаге при изменении размеров по X</para>
</listitem>
<listitem>
<para><emphasis remap="bf">SizeIncY:</emphasis> количество пикселей в одном шаге при изменении размеров по Y</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Width:</emphasis> ширина элемента</para>
</listitem>
<listitem>
<para><emphasis remap="bf">X:</emphasis> положение по горизонтали, считаемое от левого угла</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Y:</emphasis> положение по вертикали, считаемое сверху вниз</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect2>

<sect2 id="qbutton">
<title>Наследуемые элементы <indexterm remap="cdx"><primary><literal>QButton</literal></primary></indexterm>QButton</title>

<para><literal remap="tt"><indexterm remap="cdx"><primary><literal>QButton</literal></primary></indexterm>QButton</literal> - абстрактный класс, предоставляющий свойства для всех кнопок.</para>

<para>Порожден от <link linkend="QWidget">QWidget</link></para>

<para>Наследуется <link linkend="QCheckBox">QCheckBox</link>, <link linkend="QPushButton">QPushButton</link> и <link linkend="QRadioButton">QRadioButton</link>.</para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">Appearance:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">setPixmap:</emphasis> имя файла используемой картинки</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">setText:</emphasis> текст на метках, кнопках и ящиках (boxes), также предустановленный текст для строк ввода</para>
</listitem>
<listitem>
<para><emphasis remap="bf">setAutoRepeat:</emphasis> если разрешено, сигнал clicked() испускается через равные интервалы времени, пока кнопка находится в нажатом состоянии. Не действует на переключаемые (toggle) кнопки.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">setAutoResize:</emphasis> Если true, то разрешается автоматическое изменение размера. Если оно разрешено, то кнопка изменяет свой размер
при изменении содержимого.</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>

<sect3 id="qcheckbox">
<title>Свойства QCheckBox </title>

<para>Порожден от <link linkend="QWidget">QWidget</link> и <link linkend="QButton">QButton</link></para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">isChecked: (setChecked)</emphasis> определяет, выбрана ли кнопка при создании</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect3>

<sect3 id="qpushbutton">
<title>Свойства QPushButton </title>

<para>Порожден от <link linkend="QWidget">QWidget</link> и <link linkend="QButton">QButton</link></para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">isAutoDefault: (setAutoDefault)</emphasis> если установлено авто-умолчание, то кнопка становится кнопкой по умолчанию, когда она получает фокус ввода с клавиатуры</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isDefault: (setDefault)</emphasis> может быть только одна кнопка по умолчанию и это может быть использовано только в диалоге. 
Кнопка по умолчанию испускает сигнал <literal remap="tt">clicked()</literal> при нажатии пользователем клавиши Enter.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isMenuButton: (setIsMenuButton)</emphasis> сообщает кнопке о необходимости нарисовать стрелку меню. Меню должно быть вставлено отдельно.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isToggleButton::(setToggleButton)</emphasis> делает кнопку переключаемой, то есть заставляет ее вести себя аналогично QCheckBox.</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isToggledOn: (setOn)</emphasis> (public slot) включает переключаемую кнопку.</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect3>

<sect3 id="qradiobutton">
<title>Свойства QRadioButton </title>

<para>Порожден от <link linkend="QWidget">QWidget</link> и <link linkend="QButton">QButton</link></para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">isChecked: (setChecked)</emphasis> определяет, выбрана ли кнопка при создании</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect3>
</sect2>

<sect2 id="qcombobox">
<title>Свойства <indexterm remap="cdx"><primary><literal>QComboBox</literal></primary></indexterm>QComboBox </title>

<para>Порожден от <link linkend="QWidget">QWidget</link></para>

<para>(нет дополнительных свойств)</para>
</sect2>

<sect2 id="qframe">
<title>Элементы, унаследованные от QFrame </title>

<para>Порожден от <link linkend="QWidget">QWidget</link></para>

<para>Сейчас используется только как абстрактный класс.</para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">Appearance:</emphasis>
<itemizedlist>
<listitem>
<para>Margin (setMargin): устанавливает отступ, равный расстоянию от самого внутреннего пикселя рамки и до 
самого внешнего пикселя содержимого</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>

<sect3 id="qgroupbox">
<title>Свойства QGroupBox </title>

<para>Порожден от <link linkend="QWidget">QWidget</link> и <link linkend="QFrame">QFrame</link></para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">Title: (setTitle)</emphasis> устанавливает заголовок группы, который отображается на групповой рамке</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect3>

<sect3 id="qlcdnumber">
<title>Свойства QLCDNumber </title>

<para>Порожден от <link linkend="QWidget">QWidget</link> и <link linkend="QFrame">QFrame</link></para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">NumDigits:(setNumDigits)</emphasis> устанавливает количество цифр, отображаемых в QLCDNumber</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Value: (display)</emphasis> (public slot) отображает исходное значение QLCDNumber</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect3>

<sect3 id="qlabel">
<title>Свойства QLabel <indexterm remap="idx"><primary>QLabel</primary></indexterm> </title>

<para>Порожден от <link linkend="QWidget">QWidget</link> и <link linkend="QFrame">QFrame</link></para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">Appearance:</emphasis>
<itemizedlist>
<listitem>
<para>Margin (setMargin): устанавливает отступ, который для QLabel <indexterm remap="idx"><primary>QLabel</primary></indexterm> равен расстоянию от рамки до первого символа текста метки,
в зависимости от выравнивания метки</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><emphasis remap="bf">C++ Code: </emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">Buddy: (setBuddy)</emphasis> определяет объект, которому передается фокус при выборе метки</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">Text: (setText)</emphasis> устанавливает текст метки</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isAutoResize: (setAutoResize)</emphasis> если true, то метка изменяет свой размер при изменении содержимого. Левый верхний угол
не передвигается</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect3>

<sect3 id="qprogressbar">
<title>Свойства QProgressBar</title>

<para>Порожден от <link linkend="QWidget">QWidget</link> и <link linkend="QFrame">QFrame</link></para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">TotalSteps: (setTotalSteps)</emphasis> (public slot) устанавливает общее количество шагов для индикатора прогресса. В процессе выполнения вашего задания
для отображения прогресса вы должны вызывать метод setProgress(int) для отображения количества пройденных шагов (int).</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect3>

<sect3 id="qscrollview">
<title>QScrollView </title>

<para>Порожден от <link linkend="QWidget">QWidget</link> and <link linkend="QFrame">QFrame</link></para>

<para>Наследуется <link linkend="QListBox">QListBox</link>
(сейчас абстрактный)</para>

<para>Предоставляет элемент с возможностью прокрутки, который управляет отображением дочерних элементов с помощью вертикальной и горизонтальной прокрутки</para>

<sect4 id="qlistview">
<title>QListView</title>

<para>Порожден от <link linkend="QWidget">QWidget</link>, <link linkend="QFrame">QFrame</link> и <link linkend="QListView">QListView</link></para>

<para>Предоставляет список для отображения иерархических данных как в виде таблицы, так и в виде дерева. Имеет прокрутку, организованную с помощью
<link linkend="QScrollView">QScrollView</link>.</para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">Appearance:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">ListViewFont:</emphasis> (setFont()) устанавливает шрифт для строк списка</para>
</listitem>
<listitem>
<para><emphasis remap="bf">ListViewPalette:</emphasis> (setPalette()) устанавливает палитру для строк списка</para>
</listitem>
<listitem>
<para><emphasis remap="bf">TreeStepSize:</emphasis> (setTreeStepSize(int)) смещение в пикселях дочернего элемента от родительского</para>
</listitem>
<listitem>
<para><emphasis remap="bf">hScrollBarMode:</emphasis> Режим прокрутки предоставляется <link linkend="QScrollView">QScrollView</link> для горизонтальной прокрутки</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isAllColumnsShowFocus:</emphasis> (setAllColumnsShowFocus(bool)) показывает фокус для всех колонок списка</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isMultiSelection:</emphasis> разрешает множественный выбор строк списка</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isRootDecorated:</emphasis> разрешает показ "+" и "-" для развернутых и свернутых веток</para>
</listitem>
<listitem>
<para><emphasis remap="bf">vScrollBarMode:</emphasis> Режим прокрутки предоставляется <link linkend="QScrollView">QScrollView</link> для вертикальной прокрутки</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">Entries:</emphasis> позволяет вам вставить список строк, который устанавливается как QListViewItems</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isAutoUpdate:</emphasis></para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect4>
</sect3>

<sect3 id="qspinbox">
<title>Свойства QSpinBox </title>

<para>Порожден от <link linkend="QWidget">QWidget</link> и <link linkend="QFrame">QFrame</link></para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">MaxValue:</emphasis>  максимальное значение, которое пользователь может выбрать</para>
</listitem>
<listitem>
<para><emphasis remap="bf">MinValue:</emphasis>  минимальное значение, которое пользователь может выбрать</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Prefix:</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">Suffix:</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">Value:</emphasis>     предустановленное значение при отображении элемента</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isWrapping:</emphasis></para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect3>

<sect3 id="qtableview">
<title>Элементы, унаследованные от QTableView </title>

<para>Порожден от <link linkend="QWidget">&lt;QWidget</link>, <link linkend="QFrame">QFrame</link> и <link linkend="QTableView">QTableView</link></para>

<para>Наследуется <link linkend="QListBox">QListBox</link> and <link linkend="QMultiLineEdit">QMultiLineEdit</link></para>

<sect4 id="qlistbox">
<title>Свойства QListBox </title>

<para>Порожден от <link linkend="QWidget">QWidget</link>, <link linkend="QFrame">QFrame</link> и <link linkend="QTableView">QTableView</link></para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">isAutoBottomScrollBar: (setAutoBottomScrollBar)</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">isAutoScroll: (setAutoScroll)</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">isAutoScrollBar: (setAutoScrollBar)</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">isAutoUpdate: (setAutoUpdate)</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">isBottomScrollBar: (setBottomScrollBar)</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">isDragSelect: (setDragSelect)</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">isSmoothScrolling: (setSmoothScrolling)</emphasis></para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Geometry:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">setFixedVisibleLines:</emphasis> устанавливает фиксированную высоту элемента, указывая количество текстовых строк, которые отображаются с использованием текущего шрифта</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect4>

<sect4 id="qmultilineedit">
<title>Свойства QMultiLineEdit</title>

<para>Порожден от <link linkend="QWidget">QWidget</link>, <link linkend="QFrame">QFrame</link> и <link linkend="QTableView">QTableView</link></para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">Text: (setText) </emphasis> (public slot) устанавливает текст элемента</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isAutoUpdate: (setAutoUpdate)</emphasis> используется для того, чтобы избежать мигания при больших изменениях; элемент не обновляется, если запрещено</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isOverWriteMode: (setOverwriteMode) </emphasis>(public slot) включает режим замены при вводе</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isReadOnly: (setReadOnly)</emphasis> (public slot) если установлен в true, то текст не может редактироваться</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isTextSelected: (selectAll)</emphasis>(public slot) делает выбранным весь текст</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Geometry:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">setFixedVisibleLines:</emphasis> устанавливает фиксированную высоту для элементов, при этом отображается заданное количество текстовых строк текущим шрифтом</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect4>
</sect3>
</sect2>

<sect2 id="qlineedit">
<title>Свойства QLineEdit </title>

<para>Порожден от <link linkend="QWidget">QWidget</link></para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">CursorPosition: (setCursorPosition)</emphasis> устанавливает позицию курсора по умолчанию</para>
</listitem>
<listitem>
<para><emphasis remap="bf">MaxLength: (setMaxLength) </emphasis> устанавливает максимальную длину строки</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Text: (setText) </emphasis> (public slot) устанавливает текст, отображаемый при создании</para>
</listitem>
<listitem>
<para><emphasis remap="bf">hasFrame: (setFrame) </emphasis> если разрешено, то рисует элемент внутри рамки шириной 2 пикселя</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isTextSelected: (selectAll) </emphasis> (public slot) делает текст выбранным</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect2>

<sect2 id="qscrollbar">
<title>Свойства QScrollBar</title>

<para>Порожден от <link linkend="QWidget">QWidget</link> и <literal remap="tt">QRangeControl</literal>.</para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">MaxValue:</emphasis> устанавливает максимальное значение ползунка; используется в конструкторе (не обязательно)</para>
</listitem>
<listitem>
<para><emphasis remap="bf">MinValue:</emphasis> устанавливает минимальное значение ползунка; используется в конструкторе (не обязательно)</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Orientation: (setOrientation)</emphasis> устанавливает горизонтальное или вертикальное положение</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Value: </emphasis> устанавливает начальное положение (не обязательно)</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isTracking: (setTracking)</emphasis> если разрешено, то элемент испускает сигнал <literal remap="tt">valueChanged()</literal>, пока он перемещает ползунок при нажатой кнопке мыши; иначе 
сигнал испускается после того, как кнопка мыши будет отпущена</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect2>

<sect2 id="qslider">
<title>Свойства QSlider </title>

<para>Порожден от <link linkend="QWidget">&lt;QWidget</link> и <literal remap="tt">QRangeControl</literal>.</para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">General:</emphasis>
<itemizedlist>
<listitem>
<para><emphasis remap="bf">MaxValue:</emphasis> устанавливает максимальное значение ползунка; используется в конструкторе (не обязательно)</para>
</listitem>
<listitem>
<para><emphasis remap="bf">MinValue:</emphasis> устанавливает минимальное значение ползунка; используется в конструкторе (не обязательно)</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Orientation: (setOrientation)</emphasis> устанавливает горизонтальное или вертикальное положение</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Value: (setValue)</emphasis> (public slot) использует <literal remap="tt">QRangeControl::setValue()</literal> для присвоения значения</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isTracking:(setTracking)</emphasis> если разрешено, то элемент испускает сигнал <literal remap="tt">valueChanged()</literal>, пока он перемещает ползунок при нажатой кнопке мыши; иначе 
сигнал испускается после того, как кнопка мыши будет отпущена</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect2>
</sect1>

<sect1 id="svoistva-elementov-kde">
<title>Свойства элементов KDE </title>

<para><itemizedlist>
<listitem>
<para><link linkend="QWidget">QWidget</link>
<itemizedlist>
<listitem>
<para><link linkend="QButton">QButton</link> (abstract)
<itemizedlist>
<listitem>
<para><link linkend="QPushButton">QPushButton</link>
<itemizedlist>
<listitem>
<para><link linkend="KColorButton">KColorButton</link></para>
</listitem>
<listitem>
<para><link linkend="KKeyButton">KKeyButton</link></para>
</listitem>
</itemizedlist>
		</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><link linkend="QComboBox">QComboBox</link>
<itemizedlist>
<listitem>
<para><link linkend="KCombo">KCombo</link></para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><link linkend="QFrame">QFrame</link> (abstract for now)
<itemizedlist>
<listitem>
<para><link linkend="KDatePicker">KDatePicker</link></para>
</listitem>
<listitem>
<para><link linkend="KLedLamp">KLedLamp</link></para>
</listitem>
<listitem>
<para><link linkend="KProgress">KProgress</link></para>
</listitem>
<listitem>
<para><link linkend="KSeparator">KSeparator</link></para>
</listitem>
<listitem>
<para><link linkend="QTableView">QTableView</link> (abstract)
<itemizedlist>
<listitem>
<para><link linkend="KDateTable">KDateTable</link></para>
</listitem>
<listitem>
<para><link linkend="KTreeList">KTreeList</link></para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><link linkend="QLineEdit">QLineEdit</link>
<itemizedlist>
<listitem>
<para><link linkend="KRestrictedLine">KRestrictedLine</link></para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para><link linkend="KLed">KLed</link></para>
</listitem>
</itemizedlist>
</para>

<sect2 id="kcolorbutton">
<title>KColorButton</title>

<para>Порожден от <link linkend="QPushButton">QPushButton</link></para>

<para><itemizedlist>
<listitem>
<para>General
<itemizedlist>
<listitem>
<para><emphasis remap="bf">DisplayedColor (setColor())</emphasis> отображаемый цвет кнопки</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect2>

<sect2 id="kkeybutton">
<title>KKeyButton</title>
	<para></para>
</sect2>

<sect2 id="kcombo">
<title>KCombo</title>

<para>Порожден от <link linkend="QComboBox">QComboBox</link></para>

<para><itemizedlist>
<listitem>
<para>General
<itemizedlist>
<listitem>
<para><emphasis remap="bf">Entries</emphasis> список входов, отображаемых в элементе</para>
</listitem>
<listitem>
<para><emphasis remap="bf">Text</emphasis> текущий отображаемый текст</para>
</listitem>
<listitem>
<para><emphasis remap="bf">isAutoResize</emphasis> изменить размер в соответствии с размером текущего элемента</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect2>

<sect2 id="kdatepicker">
<title>KDatePicker</title>

<para><itemizedlist>
<listitem>
<para>Appearance
<itemizedlist>
<listitem>
<para><emphasis remap="bf">FontSize</emphasis> размер шрифта элемента</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect2>

<sect2 id="kledlamp">
<title>KLedLamp</title>
	<para></para>
</sect2>

<sect2 id="kprogress">
<title>KProgress</title>
	<para></para>
</sect2>

<sect2 id="kseparator">
<title>KSeparator</title>

<para><itemizedlist>
<listitem>
<para>General
<itemizedlist>
<listitem>
<para><emphasis remap="bf">Orientation</emphasis> устанавливает ориентацию разделителя - горизонтальная или вертикальная; по умолчанию горизонтальная</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect2>

<sect2 id="kdatetable">
<title>KDateTable</title>
	<para></para>
</sect2>

<sect2 id="ktreelist">
<title>KTreeList</title>

<para><itemizedlist>
<listitem>
<para>Appearance
<itemizedlist>
<listitem>
<para><emphasis remap="bf">TreeListBgColor</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">TreeListPalette</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">isBottomScrollbar</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">isScrollBar</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">isShowItemText</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">isSmoothScrolling</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">isTreeDrawing</emphasis></para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>General
<itemizedlist>
<listitem>
<para><emphasis remap="bf">Entries</emphasis></para>
</listitem>
<listitem>
<para><emphasis remap="bf">isAutoUpdate</emphasis></para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect2>

<sect2 id="krestrictedline">
<title>KRestrictedLine</title>
	<para></para>
</sect2>

<sect2 id="kled">
<title>KLed</title>

<para>Порожден от <link linkend="QWidget">QWidget</link></para>

<para><itemizedlist>
<listitem>
<para>Appearance
<itemizedlist>
<listitem>
<para><emphasis remap="bf">LedColor: (setColor())</emphasis> устанавливает отображаемый цвет индикатора</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect2>
</sect1>

<sect1 id="sozdanie-novogo-dialoga">
<title>Создание нового диалога</title>

<para>Создание нового диалога очень простой процесс, если у вас уже есть опыт графической разработки приложений. KDevelop предоставляет
возможность создавать элементы визуально и показывает, как они будут выглядеть в приложении. Кроме того, вы можете выбрать команду предварительного просмотра 
"Preview" из меню "View".</para>

<para>Для создания диалога или любого другого элемента переключитесь в режим Dialogeditor'а и выберите "New" из меню "File". Затем введите
всю необходимую информацию в диалог "New Dialog". Это:</para>

<para><orderedlist><listitem>
<para>От какого класса наследуется диалог (The Dialog inheritance). Это необходимо, потому что любой элемент в конце концов порожден от <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>. Кроме типов элементов,
предоставляемых Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>, вы можете наследовать элемент, например, от абстрактного базового класса, который вы создали сами в проекте. В этом случае
выберите "custom" и введите путь файла заголовка в строку ввода ниже.</para>
</listitem>
<listitem>
<para>Имя диалога (The Dialog name). Это устанавливает имя класса для генерируемого диалога. Выберите осмысленное имя, отражающее назначение диалога; 
в случае наследования от <literal remap="tt">QDialog</literal>, вы можете ввести имя, заканчивающееся буквами <literal remap="tt">Dlg</literal>, чтобы помнить, что это диалог.
При присвоении имени следует использовать принятые в KDE и Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> соглашения: используйте заглавные буквы в имени класса. Например, диалог выбора размеров таблицы
вы можете назвать <literal remap="tt">GridSizeDlg</literal>.</para>
</listitem>
<listitem>
<para>Имена генерируемых файлов (The generated filenames). Они заполняются при вводе имени диалога, но могут быть изменены. Если вы хотите использовать другие
имена файлов, также необходимо придерживаться соглашений KDE и Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>: все имена файлов набираются строчными буквами и содержат имя класса
для напоминания, что он содержится в этом файле. Файл данных, который будет задан позднее, содержит сгенерированный код, получаемый при создании диалога. 
Вы не должны редактировать этот файл непосредственно; используйте файл реализации для любых добавлений в диалог и реализации его методов.</para>
</listitem>
</orderedlist>
</para>

<para>После этого диалог отобразится как элемент с сеткой. Поскольку сетка используется редактором диалогов для привязки элементов к ее узлам, вы можете
изменять шаг сетки с помощью пункта "Grid Size" в меню "View", если вас не удовлетворяет значение по умолчанию</para>

<para>Выберите переключатель "Widgets" на левой панели и нажмите тот элемент, который вы хотите добавить в главное окно. Он
появится в главном окне в левом верхнем углу и будет выбран рамкой, позволяющей производить изменение размеров. Передвиньте или измените размер элемента
с помощью мыши. Курсор будет при этом изменяться, чтобы показать, какое действие может быть выполнено в данной позиции.</para>

<para>После завершения создания диалога выберите "Generate Files" из меню "Build" или нажмите соответствующую кнопку панели инструментов.
Файлы будут сгенерированы в предопределенном месте и включены в исходники вашего проекта. Команда "Build" или "Make" перекомпилирует все сгенерированные
файлы вашего проекта и вы сможете добавить соответствующий вызов конструктора в ваше приложение для отображения диалога или элемента.
Для проектов KDE все свойства элементов могут быть просмотрены позже, например текст метки, установленный с помощью макроса <literal remap="tt">i18n()</literal> из <literal remap="tt"><indexterm remap="cdx"><primary><literal>kapp.h</literal></primary></indexterm>kapp.h</literal>
для поддержки интернационализации. Таким образом, вы должны выполнить "Make Messages and merge" после завершения создания и реализации.</para>

<para>При создании диалога или элемента вы должны следовать следующим советам:
<itemizedlist>
<listitem>
<para>Всегда стремитесь к стандарту! Это, наверное, наиболее важное правило при разработке элементов графического пользовательского интерфейса. Помните, что пользователь
воспримет только те приложения, которые легко понять, независимо от того, насколько сложны решаемые ими задачи.</para>
</listitem>
<listitem>
<para>Добавляйте везде, где это возможно, всплывающие подсказки. Что это..? Помощь, или Быстрая помощь. Это позволяет получить информацию
о целях конкретного объекта пользовательского интерфейса.</para>
</listitem>
<listitem>
<para>Следите за <emphasis remap="bf">фокусом ввода клавиатуры</emphasis>! Генератор не заботится об этом - об этом надо помнить при создании любого элемента;
иначе вы будете вынуждены переупорядочивать ваш инициализационный код вручную, что является очень неблагодарным занятием. Порядок изменения фокуса ввода клавиатуры значит
порядок, в котором составляющие диалог элементы получают фокус, когда пользователь нажимает клавиши Tab и Shift+Tab. Очень надоедливо,
когда фокус изменяется как угодно, но только не на следующий элемент, расположенный ниже или справа от текущего. Поэтому начинайте
создание ваших элементов сверху вниз слева направо для уверенности в правильности перемещения фокуса.</para>
</listitem>
</itemizedlist>
</para>
</sect1>

<sect1 id="ustanovka-svoistv-elementa">
<title>Установка свойств элемента</title>

<para><indexterm><primary>widget properties</primary></indexterm><indexterm><primary>dialogeditor</primary></indexterm><indexterm><primary>properties window</primary></indexterm>
Свойства элемента могут быть легко установлены через окно свойств элемента. Когда выбирается элемент, окно свойств
автоматически обновляется и отображает свойства текущего элемента. Поскольку все элементы произошли от <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>, вы можете установить 
свойства <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal> и свойства, специфичные для выбранного элемента. Свойства могут быть:</para>

<para><itemizedlist>
<listitem>
<para>Значениями типа integer, такие как положение элемента или размер шрифта</para>
</listitem>
<listitem>
<para>Значениями типа boolean для разрешения/запрещения определенных параметров элемента. Установленные выбором из списка содержат true и false</para>
</listitem>
<listitem>
<para>Значения перечислимых типов, например, палитра. При установке выбором из списка содержат все доступные значения</para>
</listitem>
<listitem>
<para>Значение цвета, например, для цвета элемента. Устанавливается с помощью диалога выбора цветов KDE</para>
</listitem>
<listitem>
<para>Шрифт, например, текста метки. Будьте осторожны, задавая значение шрифта, отличное от шрифта по умолчанию, поскольку может случиться, что KDE не обновит шрифт.</para>
</listitem>
<listitem>
<para>Имена файлов для картинок заднего плана. Не используйте файлы формата gif,
поскольку они могут не поддерживаться последующими версиями Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>.</para>
</listitem>
</itemizedlist>
</para>
</sect1>

<sect1 id="podkliuchenie-dialoga-k-proektu">
<title>Подключение диалога к проекту</title>

<para>Когда вы создаете элемент, вы, вероятно, хотите добавить его в проект для выполнения функций, для которых он был разработан. Поскольку элемент
может быть создан для выполнения нескольких функций, мы рассмотрим 2 случая - элемент унаследован от <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal>, и элемент унаследован от <literal remap="tt">QDialog</literal>.</para>

<sect2 id="nasledovanie-ot-qwidgetqwidget">
<title>Наследование от <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWidget</literal></primary></indexterm>QWidget</literal> </title>

<para>Предположим, вы создали элемент, который будет входить в состав главного окна. Если вы заполняете всю видимую область, вы должны добавить 
указатель на экземпляр объекта в файл заголовка с определением вашего экземпляра <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal>, заменив текущий объект Просмотр. Затем измените код в
методе <literal remap="tt">initView</literal> для установки вашего элемента главным. Кроме того, вы можете удалить класс View из сгенерированного проекта, но помните,
что экземпляр документа и экземпляр приложения (App) зависят от класса View. В этой ситуации технически гораздо более удобно создать
мини-KDE приложение и создать свой экземпляр <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal>.</para>

<para>Гораздо чаще элемент будет частью видимой области, что предполагает его объединение с другими элементами. Это может быть сделано
с использованием одного из следующих классов, которые предлагают разделители для отделения двух элементов:</para>

<para><orderedlist><listitem>
<para><literal remap="tt">QSplitter</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">KPanner</literal></para>
</listitem>
<listitem>
<para><literal remap="tt">KNewPanner</literal></para>
</listitem>
</orderedlist>
</para>

<para>Если видимая область будет содержать более двух элементов, вы сможете использовать второй экземпляр разделителя в качестве объекта управления
в одной из первоначальных областей. Добавьте соответствующие элементы на каждую из частей видимой области и установите первый разделитель как видимую область.
(см. Netscape Mail - прим. переводч.)</para>
</sect2>

<sect2 id="nasledovanie-ot-qdialog">
<title>Наследование от <literal remap="tt">QDialog</literal> </title>

<para>Если ваш элемент унаследован от <literal remap="tt">QDialog</literal>, то, вероятно, он используется для изменения одного или нескольких значений; часто это необходимо для установки
настроек приложения. Для вызова диалога вы должны добавить слот в класс <literal remap="tt">App</literal>, вставляя объявление метода и его реализацию.
Затем добавьте вызов конструктора для метода, а также вызов <literal remap="tt">show()</literal> или <literal remap="tt">exec()</literal> диалога. Наконец, вы должны позаботиться
об обработке результатов работы диалога; это может быть сделано в диалоге изменением значений родителя, или
получением значений из диалога (что сделает ваш диалог гораздо более легко переносимым в другие проекты). Имейте в виду, что вы должны вызвать
<literal remap="tt">delete</literal>, если вы создаете экземпляр диалога с помощью <literal remap="tt">new</literal>, чтобы избежать потери памяти.</para>

<para>Наконец, вы должны связать вход меню (обеспечив соответствующее сообщение в строке статуса) с новым методом, вызывающим диалог; можно 
создать горячую клавишу и кнопку на панели инструментов. Для этого добавьте ресурсный ID в файл <literal remap="tt">resource.h</literal>. Затем
добавьте соответствующий вход меню в одно из выпадающих меню, уже имеющихся в панели меню, или создайте новое.
Вход меню состоит из:</para>

<para><itemizedlist>
<listitem>
<para>необязательной иконки. Установите ее вызовом макроса <literal remap="tt">Icon("iconname.xpm")</literal> из <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal>, чтобы использовать
уже существующий экземпляр <literal remap="tt">KIconLoader</literal>.</para>
</listitem>
<listitem>
<para>имени входа меню. Добавьте его с использованием макроса <literal remap="tt">i18n("&&amp;;имя&&lowbar;;входа")</literal> из <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal>, чтобы обеспечить
интернационализацию. Амперсант должен быть перед буквой, которая обеспечивает доступ по горячей клавише.</para>
</listitem>
<listitem>
<para>экземпляр, содержащий вызываемый метод. Обычно это указатель <literal remap="tt">this</literal>.</para>
</listitem>
<listitem>
<para>вызываемый слот. Используйте <literal remap="tt">SLOT(ваш&&lowbar;;метод())</literal> для вызова слота по сигналу <literal remap="tt">activated()</literal>.</para>
</listitem>
<listitem>
<para>горячая клавиша. Должна быть установлена в 0, поскольку это назначение делается в <literal remap="tt">initKeyAccel()</literal>, где вы
вводите горячие клавиши вместе с слотами для вызова. Затем вызовите <literal remap="tt">changeMenuAccel()</literal> для изменения
горячей клавиши. Это позволит сделать ее конфигурируемой через стандартный диалог в дальнейшем. Для стандартных действий используйте 
значения, определенные <literal remap="tt"><indexterm remap="cdx"><primary><literal>KAccel</literal></primary></indexterm>KAccel</literal>.</para>
</listitem>
<listitem>
<para>меню ID, установленный в <literal remap="tt">resource.h</literal></para>
</listitem>
</itemizedlist>
</para>
</sect2>
</sect1>
</chapter>

<chapter id="podderzhka-pechati">
<title>Поддержка печати</title>

<para><indexterm remap="ncdx"><primary><literal>QPrinter</literal></primary></indexterm><indexterm remap="ncdx"><primary><literal>QPainter</literal></primary></indexterm><indexterm remap="ncdx"><primary><literal>QPrintdialog</literal></primary></indexterm><indexterm><primary>printing</primary></indexterm>
Печать обычно используется, чтобы пользователь мог получить твердую копию созданного им электронного документа.
Поэтому функция необходима только для тех программ, которые делают что-то, что можно напечатать, например, текст
или картинку. В любом случае, это требует интерфейсного решения, предоставляемого библиотекой Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> в двух классах: <literal remap="tt">QPrintDialog</literal>,
предоставляющий диалог печати, и <literal remap="tt">QPainter</literal>, который обычно используется для прорисовки содержимого элемента. Поскольку объект Просмотр
приложения способен отобразить документ, он также способен его и напечатать.</para>

<sect1 id="qt-qt-dialog-pechati">
<title>Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> диалог печати</title>

<para>Для использования Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> диалога печати необходимо добавить в секцию "&&num;;include" <literal remap="tt">qprintdialog.h</literal>. При использовании шаблона KDE приложения это 
делается автоматически объектом Просмотра, поэтому вы должны только завершить реализацию метода <literal remap="tt">print()</literal>, используя <literal remap="tt">QPainter</literal>.</para>
</sect1>

<sect1 id="klass-qpainter">
<title>Класс QPainter </title>

<para>Независимо от возможностей принтера, вы можете использовать <literal remap="tt">QPainter</literal> для вывода вашего документа на принтер, предоставляемый <literal remap="tt">QPrinter</literal>,
как будто вы прорисовываете элемент на экране. Сложности возникнут только с тем, как создать то, что необходимо напечатать.</para>
</sect1>
</chapter>

<chapter id="sistema-pomoshchi">
<title>Система помощи</title>

<para>Очень важная часть процесса разработки - реализация системы помощи там, где это возможно. Многие разработчики
стараются сделать это в последнюю очередь, но вы должны помнить, что обычный пользователь не обязательно эксперт Unix'а. Он может прийти с темной стороны
компьютерных программ, где даются все возможные конфетки и пользоваться приложением можно, даже не заглядывая в руководство.
Библиотеки KDE и Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> предоставляют все, что может потребоваться, чтобы сделать приложение профессионально выглядящим в глазах
обычного пользователя, и все функции помощи могут быть использованы. В приложении это:</para>

<para><itemizedlist>
<listitem>
<para>Всплывающие подсказки (Tool-Tips)</para>
</listitem>
<listitem>
<para>Быстрая помощь (Quick-Help)</para>
</listitem>
<listitem>
<para>Помощь в строке статуса (Statusbar help)</para>
</listitem>
<listitem>
<para>Кнопка What's this...? </para>
</listitem>
</itemizedlist>
</para>

<para>Кроме того, приложение должно обеспечивать доступ к документации в HTML-формате, используя стандартную кнопку F1.</para>

<para>KDevelop предоставляет возможность реализации всех функций помощи, и стандартный шаблон приложения уже содержит их базовую реализацию.
Поэтому в данной главе мы рассмотрим, что, где и как надо добавлять в вашу систему помощи для ее расширения.</para>

<para>В процессе разработки вашего приложения вы должны следить за согласованностью элементов того, что вы разрабатываете; вы должны добавлять
функции помощи непосредственно при разработке кода. Это позволит вам избежать его последующего анализа и выяснения, за что же отвечает
данная часть приложения.</para>

<sect1 id="vsplyvaiushchie-podskazki">
<title>Всплывающие подсказки</title>

<para>Очень простой способ обеспечения помощи - это всплывающие подсказки. Это маленькие сообщения, которые появляются, когда пользователь подводит указатель мыши к элементу.
Сообщение исчезает, когда указатель мыши убирается с элемента. Наиболее популярно использование всплывающих подсказок в панелях инструментов.
Здесь всплывающие подсказки должны быть как можно короче, потому что панель инструментов может конфигурироваться для отображения только кнопок, кнопок и текста справа, кнопок и текста под ними или только текста.
Это может быть реализовано в приложении, а может и не быть реализовано.
Текст всегда отображается как всплывающая подсказка, и панель инструментов обычно состоит из кнопок и других элементов,
например, строк ввода и выпадающих списков. Для получения полной информации см. описание класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>KToolBar</literal></primary></indexterm>KToolBar</literal> в библиотеке KDE-UI.</para>

<para>Например, рассмотрим кнопку "New File" в сгенерированном шаблоне:</para>

<para><screen>toolBar()-&gt;insertButton(Icon("filenew.xpm"), ID_FILE_NEW, true, i18n("New File") );
</screen>
</para>

<para><indexterm remap="ncdx"><primary><literal>toolBar()</literal></primary></indexterm><indexterm><primary>KToolBar</primary></indexterm>
Здесь часть <literal remap="tt">i18n("New File")</literal> реализует всплывающую подсказку. Она заключена в макрос i18n(), предоставляемый <literal remap="tt"><indexterm remap="cdx"><primary><literal>kapp.h</literal></primary></indexterm>kapp.h</literal>
для перевода подсказки на используемый язык.</para>

<para>Всплывающая подсказка может быть добавлена к любому пользовательскому элементу с помощью Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>-классов <literal remap="tt">QToolTip</literal> и <literal remap="tt"><indexterm remap="cdx"><primary><literal>QToolTipGroup</literal></primary></indexterm>QToolTipGroup</literal>.
Например,</para>

<para><screen>QToolTip::add( yourwidget, i18n("Ваша_подсказка") );
</screen>
</para>

<para>Для получения более подробной информации, см. описание класса <literal remap="tt"><indexterm remap="cdx"><primary><literal>QToolTip</literal></primary></indexterm>QToolTip</literal> в документации Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>.</para>
</sect1>

<sect1 id="dobavlenie-bystroi-pomoshchi">
<title>Добавление быстрой помощи</title>

<para>Окно быстрой помощи - это другой хороший пример предоставления помощи. Пользователь может получить быструю помощь о назначении элемента, нажав правую кнопку мыши
над ним и выбрав из контекстного меню пункт "Quick-Help". Функция Быстрой помощи располагается где-то посередине между всплывающими подсказками и полным руководством пользователя.
Полное руководство содержит слишком много связанной с другими частями приложения информации, а всплывающие подсказки не дают достаточно информации.
Чтобы увидеть, как работает быстрая помощь, откройте любой диалог в KDevelop и нажмите правую кнопку мыши над его элементом.
Затем выберите пункт меню Quick-Help, и появится окно с сообщением. Эти сообщения могут быть отформатированы с использованием цвета, различных шрифтов,
и даже содержать гиперссылки (что может быть использовано для обращения к страницам документации).</para>

<para>Для реализации быстрой помощи добавьте в секцию "include" файл <literal remap="tt"><indexterm remap="cdx"><primary><literal>kquickhelp.h</literal></primary></indexterm>kquickhelp.h</literal>.
Поскольку класс <literal remap="tt"><indexterm remap="cdx"><primary><literal>KQuickHelp</literal></primary></indexterm>KQuickHelp</literal> - часть библиотеки KDE-UI, она уже должна использоваться вашим приложением. Если это не так, установите соответствующий флаг линкера
для использования kdeui.</para>

<para>Например,</para>

<para><screen>KQuickHelp::add( yourwidget, i18n("Ваше_сообщение") );
</screen>
</para>

<para>что почти аналогично QToolTip. При создании диалогового окна с помощью редактора диалогов KDevelop'а, добавьте ваши всплывающие подсказки и быструю помощь
в файл реализации - НЕ в исходный файл редактора диалогов, поскольку этот файл переписывается при каждом редактировании элемента.</para>

<para>Класс <literal remap="tt"><indexterm remap="cdx"><primary><literal>KQuickHelp</literal></primary></indexterm>KQuickHelp</literal> предоставляет возможность форматирования текста с использованием тагов. Он позволяет включение цветового выделения, гиперссылок,
типов шрифтов и размеров шрифтов. См. "KDE Library Reference Guide" и 
документацию по классу <literal remap="tt"><indexterm remap="cdx"><primary><literal>KQuickTip</literal></primary></indexterm>KQuickTip</literal> для дополнительной информации.</para>
</sect1>

<sect1 id="realizatsiia-pomoshchi-v-stroke-statusa">
<title>Реализация помощи в строке статуса</title>

<para>Шаблон приложения, генерируемый KDevelop, содержит, кроме всего прочего, строку статуса. Кроме того, он содержит сообщения для каждого из
пунктов меню и элементов панели инструментов. Помощь строки статуса - короткое сообщение, которое подробнее объясняет смысл всплывающей подсказки, или
может рассматриваться как замена всплывающих подсказок для пунктов меню, и, как следует из названия, отображается в строке статуса, когда вход меню
подсвечивается; поэтому все входы меню связывают сигнал <literal remap="tt">highlighted(int)</literal> с методом <literal remap="tt">statusCallback(int)</literal>,
который выбирает соответствующее сообщение в конструкции switch. Если вы добавляете новый пункт меню или новую кнопку панели инструментов, 
добавьте соответствующий вход в этот метод с кратким описанием действия, выполняемого при активации кнопки или пункта меню.</para>

<para>Пример:</para>

<para><screen>    case ID_FILE_NEW:
 	  	slotStatusHelpMsg(i18n("Creates a new document"));
 	  	break;
</screen>
</para>

<para>Это будет отображать сообщение в строке статуса, вызывая метод <literal remap="tt">slotStatusHelpMsg()</literal> с соответствующей переведенной строкой помощи, 
когда пользователь подсвечивает вход меню или кнопку панели инструментов с ID ID&&lowbar;;FILE&&lowbar;;NEW, который привязан к методу <literal remap="tt">statusCallback()</literal>.
Панели инструментов связаны с этим методом сигналом <literal remap="tt">pressed(int)</literal>, что позволяет пользователю нажать кнопку панели и убрать с нее
указатель мыши, не выполняя команды. <literal remap="tt"><indexterm remap="cdx"><primary><literal>KToolBar</literal></primary></indexterm>KToolBar</literal> также предоставляет сигнал <literal remap="tt">highlighted(int, bool)</literal>, который может быть использован
для отображения сообщения при подсветке кнопки вместо ее нажатия.</para>
</sect1>

<sect1 id="knopka-whats-this...">
<title>Кнопка "What's This...?"</title>

<para>Кнопка "What's This...?" <indexterm remap="idx"><primary>"What's This...?"</primary></indexterm> предоставляет окно помощи, аналогичное Quickhelp, когда пользователь хочет получить
конкретную помощь по определенному элементу рабочей области или элементу панели инструментов. Она располагается на панели инструментов и активируется
после нажатия пользователем на нее. Курсор изменяется на стрелку с вопросительным знаком, как это изображено на кнопке.
Пользователь может нажать на видимый элемент и получить окно помощи. В качестве упражнения вы можете посмотреть на поведение What's this...?
в KDevelop.
Для добавления кнопки What's This...? проделайте следующее:</para>

<para><orderedlist><listitem>
<para>включите <literal remap="tt">qwhatsthis.h</literal> в исходный код</para>
</listitem>
<listitem>
<para>добавьте функцию-член <literal remap="tt"><indexterm remap="cdx"><primary><literal>QWhatsThis</literal></primary></indexterm>QWhatsThis</literal> whats&&lowbar;;this (или с другим именем) в область private вашего класса, унаследованного от <literal remap="tt"><indexterm remap="cdx"><primary><literal>KTMainWindow</literal></primary></indexterm>KTMainWindow</literal></para>
</listitem>
<listitem>
<para>определите идентификатор ресурса для этой кнопки в <literal remap="tt">resource.h</literal>, например, <literal remap="tt">&&num;;define ID&&lowbar;;HELP&&lowbar;;WHATS&&lowbar;;THIS 10100</literal></para>
</listitem>
<listitem>
<para>в методе, создающем панель инструментов (обычно <literal remap="tt">initToolBar()</literal>), добавьте, где должна располагаться ваша кнопка:
<screen>  whats_this = new QWhatsThis;
  QToolButton *btnwhat = whats_this-&gt;whatsThisButton(toolBar());
  QToolTip::add(btnwhat, i18n("What's this...?"));
  toolBar()-&gt;insertWidget(ID_HELP_WHATS_THIS, btnwhat-&gt;sizeHint().width(), btnwhat);
  btnwhat-&gt;setFocusPolicy(QWidget::NoFocus);
</screen>

<indexterm remap="ncdx"><primary><literal>setFocusPolicy()</literal></primary></indexterm></para>
</listitem>
<listitem>
<para>добавьте сообщение, которое будет отображаться для определенного элемента:
<screen>whats_this-&gt;add(class_tree, i18n("Class Viewer\n\n"
                                  "The class viewer shows all classes, methods and variables "
                                  "of the current project files and allows switching to declarations "
                                  "and implementations. The right button popup-menu allows more specialized "
                                  "functionality."));
</screen>
</para>
</listitem>
</orderedlist>
</para>
</sect1>
</chapter>

<chapter id="sozdanie-dokumentatsii-s-ispolzovaniem-sgml-">
<title>Создание документации с использованием SGML <indexterm remap="idx"><primary>SGML</primary></indexterm></title>

<para>Учитывая тот факт, что зачастую проекты не содержат полного набора пользовательской документации, все проекты KDevelop 
включают в себя шаблон документации, который может быть легко приспособлен к проекту; этим достигается одна из целей KDE: предоставить достаточное количество online-помощи для поддержки пользователей, еще не овладевших приложением.
Эта глава посвящена тому, как расширить предлагаемый шаблон документации и что необходимо сделать, чтобы он стал доступен пользователю.</para>

<sect1 id="pochemu-sgml">
<title>Почему SGML ?</title>

<para>SGML <indexterm remap="idx"><primary>SGML</primary></indexterm> (Standard Generalized Markup Language) 
- язык, с помощью которого можно написать спецификацию другого языка разметки (markup language),
но он не является языком разметки сам по себе. Спецификация для языка разметки называется DTD (Document Type Definition, Определение типа документа), и содержит
структуры документа и доступные таги. Кроме того, SGML-система предоставляет набор файлов замены, которые переводят таги DTD
в требуемый формат - вот так это работает. Наиболее часто используемый формат вывода - HTML для создания online-помощи,
просматриваемой через браузер, учитывая, что стандарты Internet доступны даже на отдельно стоящих компьютерах. KDE широко использует HTML
документацию в KDEHelp <indexterm remap="idx"><primary>KDEHelp</primary></indexterm>, в котором приведены все приложения KDE <indexterm remap="idx"><primary>приложения KDE</primary></indexterm>, и предоставляет доступ к их руководствам пользователя.
Эти руководства доступны также через меню Help непосредственно из приложения.</para>

<para>Сейчас KDE и, следовательно, KDevelop, используют пакет SGML-Tools 1.x (см. <ulink url="http://www.sgmltools.org">\|\|</ulink>), ранее известный как
пакет LinuxDoc. Он содержит DTD, называемый <literal remap="tt">LinuxDoc</literal>, набор map-файлов для генерации выходных файлов в различных форматах
и необходимые инструменты, которые в действительности производят замену тагов <literal remap="tt">LinuxDoc</literal>. LinuxDoc DTD базируется на Qwertz DTD, который, в свою очередь,
был написан для обеспечения хорошего картирования (mapping, то есть замена тагов) в основном для текстовой системы &latex;, поэтому с ним очень легко генерировать
готовые к печати документы. Пакет получил свое название в связи с его использованием для написания документации LDP (Linux Documentation Project, Проект документирования Linux),
и его имя было изменено только из-за того, что это была sgml-система, которая вовсе не должна быть связана с Linux-проектом, а может использоваться
на любой из Unix-систем; вы можете даже написать свой собственный DTD и map-файлы для него.</para>

<para>Тем временем был разработан для определенных целей другой DTD - "DocBook DTD". DocBook имеет почти те же возможности, что и 
LinuxDoc DTD, но предоставляет лучшие таги и map-файлы для таблиц и включаемой графики, но все это возможно и в LinuxDoc.
SGML-инструмент, таким образом, получил необходимость поддержки DocBook DTD в серии версий 2.x, которые также предоставляли конвертер для получения
DocBook sgml из исходников LinuxDoc.</para>

<para>В своем текущем состоянии KDE все еще использует LinuxDoc DTD по нескольким причинам:
<itemizedlist><listitem>
<para>написание LinuxDoc документации проще,</para>
</listitem>
<listitem>
<para>инсталляция SGML-Tools 1.x для использования LinuxDoc еще проще,</para>
</listitem>
<listitem>
<para>KDE предоставляет дополнительный инструмент, называемый <literal remap="tt">ksgml2html</literal>, который придает стиль KDE выходным файлам HTML, генерируемым
конвертером SGML-Tools 1.x <literal remap="tt">sgml2html</literal>.</para>
</listitem>
</itemizedlist></para>

<para>Я сам обнаружил, пока писал книги о KDevelop, что использовать LinuxDoc DTD очень просто, и он предоставляет все необходимое
для написания документации. Скорость изучения очень высокая, поэтому вы сможете стать гуру в области sgml-tools/LinuxDoc DTD
за несколько дней, и это сохранит вам очень много времени при работе с такими системами форматирования, как &tex; для распечатки
документации или языком разметки для создания HTML.</para>

<para>Основная причина продолжать использовать sgml-tools 1.x - большинство дистрибутивов содержат пакет и дополнительные средства, необходимые вам
для производства других выходных форматов. Это делает инсталляцию максимально простой, да и написание sgml-документа само по себе не сложное, как вы увидите. 
Вы можете получить документы в следующих форматах, генерируя их из sgml: </para>

<para><itemizedlist>
<listitem>
<para>HTML, который приобретает вид KDE документа, если дополнительно используется <literal remap="tt">ksgml2html</literal>,</para>
</listitem>
<listitem>
<para>текст,</para>
</listitem>
<listitem>
<para>GNU info,</para>
</listitem>
<listitem>
<para>Lyx формат,</para>
</listitem>
<listitem>
<para>&tex;, DVI, PostScript и PDF формат,</para>
</listitem>
<listitem>
<para>Rich Text Format (RTF).</para>
</listitem>
</itemizedlist>
</para>
</sect1>

<sect1 id="chto-uzhe-soderzhit-shablon-dokumentatsii">
<title>Что уже содержит шаблон документации</title>

<para>При создании проекта KDevelop подкаталог <literal remap="tt">docs/en</literal> уже содержит файл <literal remap="tt">index.sgml</literal> с документацией на английском языке и
уже сгенерированные файлы HTML формата. Они уже включены в проект, и путь для их инсталляции указывает
на KDE HTML каталог. Документация уже адаптирована к вашему наименованию проекта, номеру версии и содержит информацию о программисте.
Далее, файл index.html включает содержание руководства по использованию программы. Этот файл открывается системой помощи KDE, когда пользователь
запрашивает помощь по работе с вашим приложением; в файл включены инструкция по установке, лицензия GPL и информация о copyright.</para>

<para>При разработке документации вы должны только добавить информацию, специфичную для вашего приложения. Помните, что
проект KDE требует запуска "Make Doc-Handbook" из меню "Project" после окончания разработки проекта. Файл index.sgml
при этом вновь обрабатывается <literal remap="tt">ksgml2html <indexterm remap="idx"><primary>ksgml2html</primary></indexterm></literal> и генерируется выполненная в KDE-стиле HTML документация. Откройте каталог <literal remap="tt">docs/en</literal> в RFV
и добавьте <literal remap="tt">logotp3.gif</literal> в проект через контекстное меню; затем правильно задайте его свойства для инсталляции логотипа
в тот же каталог, где будут расположены HTML файлы - <literal remap="tt">$(kde&&lowbar;;htmldir)/en/&&lt;;ваш&&lowbar;;проект&&gt;;/logotp3.gif</literal>.</para>
</sect1>

<sect1 id="napisanie-sgml-dokumentatsii">
<title>Написание SGML документации</title>

<para>Этот раздел добавлен, потому что SGML (или, более точно, LinuxDoc DTD), все еще кажется сложным для начинающих
писать документацию. Когда я посмотрел на некоторые приложения KDE, то увидел, что некоторые из них содержат файл sgml в виде исходного шаблона -
а автор редактировал HTML файлы вместо sgml. Это приводит к проблемам при переводе - если необходимо
перевести документацию на родной язык, приходится редактировать каждый файл в HTML формате, и это делает
невозможным повторное использование документов в других форматах, причем не только в английской версии, а и во всех локализованных версиях проекта.
Как видно, это не продуманное решение, приводящее к весьма тяжким последствиям; я считаю, что это происходит, поскольку автор знает HTML,
но не знает SGML. Поскольку большинство старается избежать изучения нового языка форматирования, они используют HTML файлы как шаблон для редактирования.
Если вы однажды посмотрите на то, как легко и просто использовать SGML с LinuxDoc, вы решите, что лучше выучить несколько лишних тагов
и создавать SGML формат.</para>

<para>Следующие разделы дают начальную информацию о наиболее важных частях файла sgml в LinuxDoc, и объясняют, как расширить
вашу документацию.</para>

<sect2 id="obiavleniia-dtd">
<title>Объявления DTD</title>

<para>Для того, чтобы показать, какой вариант DTD используется, каждый sgml файл начинается с объявления DTD.
Первый таг (взятое в скобки выражение, например &&lt;;ваш&&lowbar;;таг&&gt;; содержимое &&lt;;/ваш&&lowbar;;таг&&gt;;) всегда DOCTYPE:</para>

<para><literal remap="verb">&&lt;;!doctype linuxdoc system&&gt;;</literal></para>

<para>Это сообщает вашему форматировщику sgml, что он должен использовать LinuxDoc DTD.</para>

<sect3 id="struktura-dokumenta">
<title>Структура документа</title>

<para>При использовании LinuxDoc следующий таг - стартовый таг документа, определяющий его стиль. LinuxDoc DTD предлагает целый набор типов документов,
из который вы можете выбрать нужный в зависимости от назначения документа и его длины. Доступны следующие типы:</para>

<para><itemizedlist>
<listitem>
<para><literal remap="tt">&&lt;;notes&&gt;;</literal> для короткого пояснения,</para>
</listitem>
<listitem>
<para><literal remap="tt">&&lt;;article&&gt;;</literal> для написания статьи длиной 10-20 страниц (примерно). Этот тип используется в качестве шаблона в KDevelop и большинстве KDE
приложений,</para>
</listitem>
<listitem>
<para><literal remap="tt">&&lt;;report&&gt;;</literal> для статей длиннее &&lt;;article&&gt;;,</para>
</listitem>
<listitem>
<para><literal remap="tt">&&lt;;book&&gt;;</literal> для написания большой книги - руководство по KDevelop использует этот тип,</para>
</listitem>
<listitem>
<para><literal remap="tt">&&lt;;slides&&gt;;</literal> для слайд-шоу. Это полезно для презентаций. Предполагается использование &latex; в качестве конечного формата в большинстве случаев,</para>
</listitem>
<listitem>
<para><literal remap="tt">&&lt;;letter&&gt;;</literal> для обычных писем,</para>
</listitem>
<listitem>
<para><literal remap="tt">&&lt;;telefax&&gt;;</literal> для факсов,</para>
</listitem>
<listitem>
<para><literal remap="tt">&&lt;;manpage&&gt;;</literal> для статьи man.</para>
</listitem>
</itemizedlist>
</para>

<para>Имейте в виду, что эти типы описывают только общую организацию структуры документа, а не конкретный вид выходных документов. Как упоминалось,
KDevelop по умолчанию генерирует шаблон, используя структуру &&lt;;article&&gt;;. Это используется большинством приложений, исключая сам KDevelop, который использует тип
&&lt;;book&&gt;;. В HTML формате это не имеет серьезного значения - но для &latex;, например, это важно.
Руководство - это настоящая "книга" с отдельными страницами для каждой главы (главное отличие).</para>

<para>Конец sgml файла должен содержать завершающий таг для структуры документа - для &&lt;;article&&gt;; это будет 
&&etago;;article&&gt;;.</para>
</sect3>
</sect2>

<sect2 id="titulnaia-stranitsa">
<title>Титульная страница</title>

<para>После тага структуры документа идет секция, описывающая основные пункты, располагаемые на титульной странице. Шаблон
не использует их все, но заполняет информацию для тагов <literal remap="tt">&&lt;;title&&gt;;</literal>, <literal remap="tt">&&lt;;author&&gt;;</literal> и <literal remap="tt">&&lt;;date&&gt;;</literal>, чего обычно достаточно.
При использовании структуры <literal remap="tt">&&lt;;book&&gt;;</literal> вы, вероятно, захотите определить все таги титульной страницы.
Следующий пример показывает использование этих тагов, он взят из sgml исходника этой книги:</para>

<para><programlisting>&&lt;;!doctype linuxdoc system&&gt;;
&&lt;;book&&gt;;
&&lt;;titlepag&&gt;;
&&lt;;title&&gt;;The KDevelop Programming Handbook
&&lt;;subtitle&&gt;;The User Guide to C++ Application Design for the K Desktop Environment (KDE) with the KDevelop IDE, Version 1.0
&&lt;;author&&gt;;
&&lt;;name&&gt;;Ralf Nolden &&lt;;htmlurl url="mailto:Ralf.Nolden@post.rwth-aachen.de"
                                   name = "&&lt;;Ralf.Nolden@post.rwth-aachen.de&&gt;;"&&gt;;
&&lt;;inst&&gt;;The KDevelop Team
&&lt;;date&&gt;;Version 2.1 , July 7, 1999
&&lt;;abstract&&gt;;
This handbook itself is part of the KDevelop Integrated Development Environment
and is therefore also licensed under the GNU General Public License;
see &&lt;;ref id="Copyright" name="Copyright"&&gt;; for more information.
&&etago;;abstract&&gt;;</programlisting>
</para>

<para>Это включает в себя все, что обычно содержит титульная страница. Таг <literal remap="tt">&&lt;;author&&gt;;</literal> включает таг <literal remap="tt">&&lt;;thanks&&gt;;</literal>, вставляющий
некоторые благодарности соавторам и т.п. <literal remap="tt">&&lt;;inst&&gt;;</literal> представляет институт или компанию, для которой автор писал
документацию; вы также можете использовать имя вашей команды, как сделал я. <literal remap="tt">&&lt;;abstract&&gt;;</literal> содержит краткое описание, расположенное
на титульной странице. Это несколько неприятно в печатной версии, поэтому там данная секция будет напечатана на обратной стороне титульной страницы
вместе с copyright; это может быть изменено в &latex; редактированием файла &tex;.</para>
</sect2>

<sect2 id="indeksy">
<title>Индексы</title>

<para>LinuxDoc DTD определяет набор тагов для построения различных индексов, как это обычно делается в документах. Это:</para>

<para><itemizedlist>
<listitem>
<para>&&lt;;toc&&gt;; для содержания</para>
</listitem>
<listitem>
<para>&&lt;;lof&&gt;; для списка рисунков</para>
</listitem>
<listitem>
<para>&&lt;;lot&&gt;; для списка таблиц</para>
</listitem>
</itemizedlist>
</para>

<para>Завершающий таг не требуется в конце; индексы вставляются непосредственно после титульной страницы перед началом
документа с соответствующими разделами или главами.</para>

<para>Для индексации ключевых слов, список которых располагается в конце документа, вам предоставляются 4 различных тага;
два из них оставляют индексированную фразу видимой на странице, а два других не отображают индексные входы:</para>

<para><itemizedlist><listitem>
<para>&&lt;;idx&&gt;; для элемента обычного индекса,</para>
</listitem>
<listitem>
<para>&&lt;;cdx&&gt;; для true-type элемента индекса,</para>
</listitem>
<listitem>
<para>&&lt;;nidx&&gt;; для индексного входа, не отображаемого на странице,</para>
</listitem>
<listitem>
<para>&&lt;;ncdx&&gt;; аналогично для tt-индекса</para>
</listitem>
</itemizedlist></para>

<para>Эти таги игнорируются всеми конечными форматами, кроме
<literal remap="tt">sgml2latex</literal>, который генерирует индексный файл <literal remap="tt">index.idx</literal>, который преобразуется в &tex;-индекс командой <literal remap="tt">makeindex index.idx</literal>.
Сам индекс может быть вставлен в &tex; файл с помощью <literal remap="tt">\printindex</literal>.
Я написал скрипт, автоматизирующий вставку
индекса в &latex; (но до сих пор не знаю, как включить индекс в содержание...).</para>
</sect2>

<sect2 id="soderzhanie-dokumenta">
<title>Содержание документа</title>

<para>Сейчас, после объяснения большинства деталей основной структуры, мы переходим к рассмотрению текста документа. В зависимости от 
типа структуры документа, он начинается либо с тага <literal remap="tt">&&lt;;sect&&gt;;</literal>, либо, при использовании <literal remap="tt">&&lt;;book&&gt;;</literal>, с тага <literal remap="tt">&&lt;;chapt&&gt;;</literal>
для глав.</para>

<para>После стартового тага, вы можете структурировать каждую главу с помощью <literal remap="tt">&&lt;;sect1&&gt;;</literal>, <literal remap="tt">&&lt;;sect2&&gt;;</literal> и т.п. до максимального
уровня вложенности (4).</para>

<para>После стартового тага главы следует ее заголовок. Здесь вы можете использовать <literal remap="tt">&&lt;;title&&gt;;</literal> 
и <literal remap="tt">&&etago;;title&&gt;;</literal> для заголовков глав (при необходимости). После заголовка главы вы должны добавить таг &&lt;;p&&gt;;,
чтобы обозначить начало текста главы. В тексте вы имеете возможность использовать списки, перечисления,
списки определений (description lists) и т.п. Далее, цитаты и фрагменты кода также могут быть вставлены с помощью тагов, см. 
документацию по <literal remap="tt">sgmltools</literal> для получения полного перечня тагов. Также в ней посмотрите раздел о добавлении специальных символов.
В нем перечислены все доступные неалфавитные символ, например, знак торговой марки.
С помощью этих тагов вы сможете структурировать документацию так, как это требуется для вашего приложения.</para>
</sect2>
</sect1>

<sect1 id="kak-vyzyvat-pomoshch-v-dialogovykh-oknakh">
<title>Как вызывать помощь в диалоговых окнах</title>

<para><indexterm><primary>help functions</primary></indexterm>
Вызов помощи в диалогах часто реализуется с помощью кнопки Помощь (Help); после этого вы добавляете слот, выполняемый по нажатию этой кнопки.
В коде этого слота вы должны вызвать:</para>

<para><screen>kapp-&gt;invokeHTMLHelp( QString aFilename, QString aTopic );
</screen>
</para>

<para>где <literal remap="tt">aFilename</literal> - имя файла в каталоге с HTML-документацией вашего приложения; например, index-3.html.
<literal remap="tt">aTopic</literal> - заголовок, который должен быть вызван. Хеш-префикс "&&num;;" добавляется автоматически; введите главу,
к которой вы хотите обратиться, хотя это может быть и заголовок более низкого уровня.</para>
</sect1>
</chapter>

<chapter id="dokumentirovanie-klassov-s-pomoshchiu-kdoc-k">
<title>Документирование классов с помощью KDoc <indexterm remap="idx"><primary>KDoc</primary></indexterm></title>

<para>Другая важная часть документации - краткое описание интерфейса классов. Это позволит вам и другим
программистам использовать ваши классы, читая HTML файлы документации классов, которая создается с помощью <literal remap="tt">KDoc <indexterm remap="idx"><primary>KDoc</primary></indexterm></literal>. KDevelop поддерживает использование
<literal remap="tt">KDoc <indexterm remap="idx"><primary>KDoc</primary></indexterm></literal> для создания документации к KDE-библиотекам, и ваш шаблон уже документирован. Для работы
с предлагаемым в нем кодом полезно прочитать online-документацию. Данная глава описывает, что необходимо сделать
для документирования API <indexterm remap="idx"><primary>API</primary></indexterm>, и как KDevelop поможет вам в этом, также рассматриваются дополнительные таги, поддерживаемые <literal remap="tt">KDoc <indexterm remap="idx"><primary>KDoc</primary></indexterm></literal>.</para>

<sect1 id="kak-ispolzovat-vozmozhnosti-kdevelop-po-doku">
<title>Как использовать возможности KDevelop по документированию</title>

<para>Для создания документации API <indexterm remap="idx"><primary>API</primary></indexterm> после разработки проекта выберите "Make API <indexterm remap="idx"><primary>API</primary></indexterm>-Doc" из меню "Project". 
Это приведет к просмотру всех файлов заголовков и созданию на их основе HTML файлов документации. После этого
вы сможете получить доступ к документации, выбирая "API <indexterm remap="idx"><primary>API</primary></indexterm>-Documentation" из меню помощи
или соответствующую книгу в дереве документации, папка "Current Project".</para>

<para>Документация уже содержит ссылки на KDE и Qt <indexterm remap="idx"><primary>Qt</primary></indexterm> online-документацию классов, поэтому вы сможете проследить наследование
и легко обозреть иерархию. Это может вам также помочь в начале работы с документацией KDE и Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>.</para>
</sect1>

<sect1 id="dobavlenie-dokumentatsii-klassov-i-ikh-chlen">
<title>Добавление документации классов и их членов</title>

<para>KDevelop предоставляет как способы автоматического добавления кода, так и способы автоматического документирования. 
Когда вы используете генератор классов, выбирая "Project"-&gt;"New Class", добавьте краткое описание класса в поле документирования. Это вставит
его в заголовок класса.</para>

<para>При добавлении в класс функции-члена и атрибутов с помощью classtools <indexterm remap="idx"><primary>classtools</primary></indexterm>, добавьте краткое описание члена в поле документирования.</para>

<para>Вы можете подумать, что документация - это часть процесса разработки, которая не очень важна. Но помните, что большинство
проектов растут, и все больше и больше людей начинают принимать участие в их разработке. Поэтому документирование классов - хороший путь сэкономить время.
Даже если вы присвоили методам имена, точно описывающие их назначение, очень вероятно, что их не поймут или со временем изменятся функции метода.
Поэтому поддерживайте в порядке вашу документацию и обновляйте ее как можно чаще.</para>

<para>Несмотря на вышесказанное, файлы документации НЕ включаются в проект, и не интернационализируются. Поэтому
вся документация API <indexterm remap="idx"><primary>API</primary></indexterm> должна быть написана на английском, чтобы позволить работать с ней международной команде.</para>

<para>Если вы хотите добавить документирование вручную в файл заголовка, добавьте его <emphasis remap="bf">над</emphasis>  методом или классом
в виде C-комментария с одним отличием - первая строка должна начинаться со слеша и двух звездочек.</para>

<para>Например:</para>

<para><screen>  /** enables menuentries/toolbar items
  	*/
  void enableCommand(int id_);
</screen>
</para>
</sect1>

<sect1 id="spetsialnye-tagi">
<title>Специальные таги</title>

<para><emphasis remap="bf">Внимание:</emphasis> последующий текст этой главы взят из документации KDoc <indexterm remap="idx"><primary>KDoc</primary></indexterm>, поставляемой вместе с KDoc <indexterm remap="idx"><primary>KDoc</primary></indexterm> и написанной
Sirtaj S. Kang <ulink url="mailto:taj@.kde.org">taj@.kde.org</ulink>), автором KDoc <indexterm remap="idx"><primary>KDoc</primary></indexterm>; Copyright (c) 1997</para>

<para>Документация состоит из:</para>

<para><itemizedlist>
<listitem>
<para>Обычного текста. Параграфы должны быть разделены минимум одной пустой строкой.
</para>
</listitem>
<listitem>
<para>Текста в форме
<programlisting>&&lt;;pre&&gt;;
.....фрагмент кода....
&&lt;;/pre&&gt;;</programlisting>
</para>
</listitem>
<listitem>
<para>Различных тагов в форме:
<screen>@имя_тага [параметры тага]
</screen>
</para>
</listitem>
</itemizedlist>
</para>

<para>Доступные таги для каждого объекта кода следующие:</para>

<para><itemizedlist>
<listitem>
<para>Классы
<screen>  @short [одна фраза текста]
    Краткое описание класса
  @author [одна фраза текста]
    Автор класса
  @version [одна фраза текста]
    Версия класса (Я обычно устанавливаю это равным RCS/CVS "Id" тага)
  @see [одна или несколько ссылок на классы и методы] 	
    Ссылки на связанную документацию.
</screen>

</para>
</listitem>
<listitem>
<para>Методы

<screen>  @see
    см. выше
  @return [одна фраза текста]
    Фраза, описывающая возвращаемое значение
  @param [идентификатор имени параметра] [описание параметра]
    Описывает параметр. Может содержать несколько строк и прерывается
    пустой строкой, окончанием комментария или другим тагом параметра.
    Поэтому обычно располагается в конце комментариев.
</screen>

</para>
</listitem>
<listitem>
<para>Константы, множества, свойства
<screen>  @see
    см. выше
</screen>
</para>
</listitem>
<listitem>
<para>ALSO <literal remap="tt">@ref</literal>
Взято из формата документирования java. Метасимвол @ref имеет тот же формат, что и @see, но может встречаться в любом месте документации
(остальные описания должны располагаться на той же строке, что и таг).</para>
</listitem>
</itemizedlist>
</para>
</sect1>
</chapter>

<chapter id="internatsionalizatsiia">
<title>Интернационализация</title>

<sect1 id="chto-takoe-i18n">
<title>Что такое i18n ?</title>

<para>i18n - это система интернационализации, которая используется для разработки интернациональных версий программы или проекта. Сложность
написания приложений состоит в том, что они поддерживают только один язык, заложенный в них при разработке; это проявляется в
надписях меток, входов меню и т.п. Цель интернационализации - предоставить приложения и библиотечные функции на языке
пользователя; это сделает их доступными пользователям, не владеющим языком оригинала, сделает их работу более комфортной.</para>
</sect1>

<sect1 id="kak-kde-podderzhivaet-internatsionalizatsiiu">
<title>Как KDE поддерживает интернационализацию</title>

<para>KDE, как современная рабочая среда, среди множества других целей ставит перед собой цель обеспечения пользователей приложениями
на их родном языке, и облегчения работы программистов в части реализации поддержки множества языков.</para>

<para>Технически это реализуется с помощью стандарта файловой системы KDE, который поддерживает локализацию документации
и предоставляет возможность интернационализации приложений, используя класс  <literal remap="tt">KLocale</literal> библиотеки KDE-core.
Он реализует перевод в зависимости от того, какой язык установлен по умолчанию в Центре управления KDE (KDE Control Center).</para>

<para>Разработчик, с другой стороны, должен соблюдать только три правила, чтобы сделать свое приложение обладающим возможностью интернационализации:</para>

<para><orderedlist><listitem>
<para>включить <literal remap="tt"><indexterm remap="cdx"><primary><literal>kapp.h</literal></primary></indexterm>kapp.h</literal> в исходный код везде, где есть видимый текст, т.е. в исходники, содержащие
объекты QLabel <indexterm remap="idx"><primary>QLabel</primary></indexterm>,</para>
</listitem>
<listitem>
<para>везде, где встречаются видимые строки, вставить их в макрос <literal remap="tt">i18n()</literal>, предоставляемый <literal remap="tt"><indexterm remap="cdx"><primary><literal>kapp.h</literal></primary></indexterm>kapp.h</literal> для интернационализации,</para>
</listitem>
<listitem>
<para>везде, где вы используете локализованный объект, использовать макрос <literal remap="tt">klocale</literal>, предоставляемый <literal remap="tt"><indexterm remap="cdx"><primary><literal>kapp.h</literal></primary></indexterm>kapp.h</literal>.</para>
</listitem>
</orderedlist>
</para>

<para>Это почти все, за чем вы должны следить при разработке кода. Имейте в виду, что вы не должны интернационализировать конфигурационные строки,
используемые <literal remap="tt"><indexterm remap="cdx"><primary><literal>KConfig</literal></primary></indexterm>KConfig</literal>, потому что это, с одной стороны, ненужно, а с другой стороны, не будет работать.</para>
</sect1>

<sect1 id="dobavlenie-iazyka-v-proekt">
<title>Добавление языка в проект</title>

<para>KDevelop также принимает участие в облегчении вашей жизни при добавлении поддержки нового языка в ваше приложение. 
Всегда при создании нового проекта KDE каталог <literal remap="tt">po</literal> добавляется в корневой каталог проекта. В него будет помещен ваш файл <emphasis>&&lt;;приложение&&gt;;</emphasis>.pot 
после окончания генерации. pot файл содержит все строки, заключенные в макрос i18n().
Вы должны только написать свой код, используя этот макрос. Время от времени вы должны запускать "Project"-"Make messages and
merge", что автоматически извлечет все макросы из кода и сгенерирует pot файл.
<indexterm><primary>"Project"-menu</primary></indexterm><indexterm><primary>PO-files</primary></indexterm><indexterm><primary>translations</primary></indexterm><indexterm remap="ncdx"><primary><literal>KLocale</literal></primary></indexterm></para>

<para>Для добавления языка в ваше приложение, выберите "Project"-"Add translation file", после чего откроется каталог выбора языка. Выберите
требуемый язык и нажмите OK. После этого соответствующий <emphasis>&&lt;;lang&&gt;;</emphasis>.po файл появится в каталоге <literal remap="tt">po</literal>. Запустите
перевод po файла, выбрав его в каталоге po, в Real File Viewer или из LFV, папка "Translations". Если вы
установили KTranslator <indexterm remap="idx"><primary>KTranslator</primary></indexterm>, он откроется в окне "Tools" с KTranslator <indexterm remap="idx"><primary>KTranslator</primary></indexterm>, иначе как текстовый файл в панели header/resource.
KTranslator <indexterm remap="idx"><primary>KTranslator</primary></indexterm> облегчает перевод строк, сканируя уже существующие переводы вашей локальной инсталляции KDE, поэтому
уже существующий перевод может использоваться повторно.</para>

<para>Рассмотрим пример ручного редактирования:
<screen>#: kscribble.cpp:619
msgid "Opens an existing document"
msgstr ""
</screen>
</para>

<para>Это строка, взятая из файла <literal remap="tt">kscribble.cpp</literal>, строка кода номер 619. <literal remap="tt"><indexterm remap="cdx"><primary><literal>msgid</literal></primary></indexterm>msgid</literal> и <literal remap="tt"><indexterm remap="cdx"><primary><literal>msgstr</literal></primary></indexterm>msgstr</literal> - это таги, которые
дают информацию для перевода; <literal remap="tt"><indexterm remap="cdx"><primary><literal>msgstr</literal></primary></indexterm>msgstr</literal> должен содержать переведенный текст. Вы можете увидеть эскейп-последовательности
типа \n или \t, которые должны быть включены в переведенную строку. Русский перевод будет выглядеть так:</para>

<para><screen>#: kscribble.cpp:619
msgid "Opens an existing document"
msgstr "Открыть существующий документ"
</screen>
</para>

<para>Это все, что необходимо для перевода; когда это сделано, сохраните файл. Когда make будет просматривать каталог po, будет обработан файл сообщений
и могут возникнуть ошибки, если строки переведены неправильно, например, без учета эскейп-последовательностей. 
Если это произошло, отредактируйте строку сообщения снова и убедитесь, что make выполняется без ошибок.</para>

<para>Кроме того, вы должны быть очень аккуратны при переводе амперсантов в текстовых строках. Буква после амперсанта используется как
горячая клавиша в сочетании с клавишей ALT для переключения фокуса ввода клавиатуры на требуемый элемент. 
Если одинаковые буквы используются в одной области фокуса клавиатуры (например, главное окно или диалоговое окно),
все элементы, кроме первого, не будут доступны по горячей клавише. Поэтому переводчик также отвечает за возможность использования приложения.
Кроме того, нет никаких гарантий, что исходная буква встретится в переводе, поэтому переводчик должен быть очень осторожен и должен протестировать приложение на своем языке
после установки перевода, чтобы убедиться в отсутствии подобных неприятностей.</para>
</sect1>

<sect1 id="sviaz-s-komandoi-perevoda">
<title>Связь с командой перевода</title>

<para>Команда KDE предоставляет многочисленные возможности контакта для разработчиков, выполняющих функции переводчиков.
Они организованы в группы по языку перевода, на уровне которых и координируется работа. Для получения списка групп и адресов, где можно узнать 
о переводе ваших приложений, см. <ulink url="http://www.kde.org">\|\|</ulink>.</para>

<para>Информация, приводимая ниже, взята с web-сайта KDE и отражает состояние на 6 марта 1999 года. Если вы хотите присоединиться к команде перевода,
пишите непосредственно своему координатору.</para>

<para>Перевод KDE организован Juraj Bednar <ulink url="mailto:bednar@rak.isternet.sk">mailto:bednar@rak.isternet.sk</ulink> и Matthias Elter <ulink url="mailto:me@kde.org">me@kde.org</ulink>.</para>

<para>Вы можете подписаться на лист рассылки kde-i18n-doc@kde.org, послав письмо на <ulink url="mailto:kde-i18n-doc-request@kde.org?subject=subscribe">kde-i18n-doc-request@kde.org</ulink> 
со словом "subscribe" в теме письма.</para>

<para>Перед началом любой работы по переводу, пожалуйста, свяжитесь с координатором вашей группы, чтобы избежать двойной работы.</para>

<variablelist>
<varlistentry>
<term>br Breton translation team:</term>
<listitem>
<para>team coordinators: JaЯ-Mai DRAPIER <ulink url="mailto:jdrapier@club-internet.fr">jdrapier@club-internet.fr</ulink>
website: <ulink url="http://perso.club-internet.fr/jdrapier">http://perso.club-internet.fr/jdrapier</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>ca Catalan translation team:</term>
<listitem>
<para>team coordinators: SebastiЮ Pla <ulink url="mailto:sastia@redestb.es">sastia@redestb.es</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>cs Czech translation team:</term>
<listitem>
<para>team coordinators:  Miroslav FlМdr <ulink url="mailto:flidr@kky.zcu.cz">flidr@kky.zcu.cz</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>da Danish translation team:</term>
<listitem>
<para>team coordinators:  Erik KjФr Pedersen <ulink url="mailto:erik@binghamton.edu">erik@binghamton.edu</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>de German translation team:</term>
<listitem>
<para>team coordinators: Thomas Diehl <ulink url="mailto:th.diehl@gmx.net">th.diehl@gmx.net</ulink>
website: <ulink url="http://www.dtp-service.com/kde/de/">\|\|</ulink>
mailing list:  send a mail with 'subscribe' in the subject line to: <ulink url="mailto:kde-i18n-de-request@kde.org?subject=subscribe">kde-i18n-de-request@kde.org</ulink> Webforum for discussions and user feedback: <ulink url="http://www.dtp-service.com/discus_d">\|\|</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>el Greek translation team:</term>
<listitem>
<para>team coordinators:  Theodore J. Soldatos <ulink url="mailto:theodore@eexi.gr">theodore@eexi.gr</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>eo Esperanto translation team:</term>
<listitem>
<para>team coordinators:  Wolfram Diestel <ulink url="mailto:diestel@rzaix340.rz-uni-leipzig.de">diestel@rzaix340.rz-uni-leipzig.de</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>es Spanish translation team:</term>
<listitem>
<para>team coordinators:  Boris Wesslowski, Alonso Lara <ulink url="mailto:Boris@Wesslowski.com">Boris@Wesslowski.com</ulink>
website: <ulink url="http://members.xoom.com/keko5/">\|\|</ulink>
mailing list: send a mail with 'subscribe' in the subject line to <ulink url="mailto:kde-es@kde.org?subject=subscribe">kde-es@kde.org</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>et Estonian translation team:</term>
<listitem>
<para>team coordinators:  Hasso C. Tepper <ulink url="mailto:hasso@ewsound.estnet.ee">hasso@ewsound.estnet.ee</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>fi Finnish translation team:</term>
<listitem>
<para>team coordinators: Kim Enkovaara <ulink url="mailto:kim.enkovaara@iki.fi">kim.enkovaara@iki.fi</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>fr French translation team:</term>
<listitem>
<para>team coordinators:  Francois-Xavier Duranceau <ulink url="mailto:Francois-Xavier.Duranceau@loria.fr">Francois-Xavier.Duranceau@loria.fr</ulink>
website: <ulink url="http://www.loria.fr/~durancea/kde/wip-apps.html">\|\|</ulink>
mailing list: send an empty mail to:  <ulink url="mailto:kde-traduc-fr-subscribe@egroups.com">kde-traduc-fr-subscribe@egroups.com</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>he Hebrew translation team:</term>
<listitem>
<para>team coordinators:  Erez Nir <ulink url="mailto:erez-n@actcom.co.il">erez-n@actcom.co.il</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>hr Croatian translation team:</term>
<listitem>
<para>team coordinators:  Vladimir Vuksan <ulink url="mailto:vuksan@veus.hr">vuksan@veus.hr</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>hu Hungarian translation team:</term>
<listitem>
<para>team coordinators:  Marcell Lengyel <ulink url="mailto:miketkf@yahoo.com">miketkf@yahoo.com</ulink>
website:<ulink url="http://sophia.jpte.hu/~kde">\|\|</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>is Icelandic translation team:</term>
<listitem>
<para>team coordinators:
Logi Ragnarsson, <ulink url="mailto:logir@imf.au.dk">logir@imf.au.dk</ulink>
Thorarinn R. Einarsson, <ulink url="mailto:thori@mindspring.com">thori@mindspring.com</ulink>
Bjarni R. Einarsson, <ulink url="mailto:bre@netverjar.is">bre@netverjar.is</ulink>
Hrafnkell Eiriksson, <ulink url="mailto:hkelle@rhi.hi.is">hkelle@rhi.hi.is</ulink>
Gudmundur Erlingsson, <ulink url="mailto:gudmuner@lexis.hi.is">gudmuner@lexis.hi.is</ulink>
Richard Allen <ulink url="mailto:ra@hp.is">ra@hp.is</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>it Italian translation team:</term>
<listitem>
<para>team coordinators:  Andrea Rizzi <ulink url="mailto:rizzi@kde.org">rizzi@kde.org</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>ko Korean translation team:</term>
<listitem>
<para>team coordinators:  LinuxKorea Co. <ulink url="mailto:kde@linuxkorea.co.kr">kde@linuxkorea.co.kr</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>mk Macedonian translation team:</term>
<listitem>
<para>team coordinators:  Sasha Konecni <ulink url="mailto:sasha@msi-uk.com">sasha@msi-uk.com</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>nl Dutch translation team:</term>
<listitem>
<para>team coordinators:  flidr@CyberGate.zcu.cz <ulink url="mailto:flidr@CyberGate.zcu.cz">flidr@CyberGate.zcu.cz</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>no Norwegian translation team:</term>
<listitem>
<para>team coordinators:  Hans Petter Bieker <ulink url="mailto:zerium@webindex.no">zerium@webindex.no</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>pl Polish translation team:</term>
<listitem>
<para>team coordinators:  Piotr Roszatycki <ulink url="mailto:dexter@fnet.pl">dexter@fnet.pl</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>pt Portuguese translation team:</term>
<listitem>
<para>team coordinators:  Pedro Morais <ulink url="mailto:pmmm@camoes.rnl.ist.utl.pt">pmmm@camoes.rnl.ist.utl.pt</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>pt&&lowbar;;BR Brazil Portuguese translation team:</term>
<listitem>
<para>team coordinators:  Elvis PfЭtzenreuter <ulink url="mailto:epx@netville.com.br">epx@netville.com.br</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>ro Romanian translation team:</term>
<listitem>
<para>team coordinators:  Paul Ionescu <ulink url="mailto:ipaul@romsys.ro">ipaul@romsys.ro</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>ru Russian translation team:</term>
<listitem>
<para>team coordinators:  Denis Y. Pershin <ulink url="mailto:dyp@inetlab.com">dyp@inetlab.com</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>sk Slovak translation team:</term>
<listitem>
<para>team coordinators:  Juraj Bednar <ulink url="mailto:bednar@isternet.sk">bednar@isternet.sk</ulink>
mailling list:  send a mail with 'subscribe' in the subject line to: <ulink url="mailto:sk-i18n@rak.isternet.sk?subject=subscribe">sk-i18n@rak.isternet.sk</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>sl Slovenian translation team:</term>
<listitem>
<para>team coordinators:  blazzupancic@hotmail.com <ulink url="mailto:blazzupancic@hotmail.com">blazzupancic@hotmail.com</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>sv Swedish translation team:</term>
<listitem>
<para>team coordinators:  Anders Widell <ulink url="mailto:d95-awi@nada.kth.se">d95-awi@nada.kth.se</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>tr Turkish translation team:</term>
<listitem>
<para>team coordinators:  Gorkem Cetin <ulink url="mailto:gorkem@linux.org.tr">gorkem@linux.org.tr</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>zh&&lowbar;;GB2312 Simplified Chinese translation team:</term>
<listitem>
<para>team coordinators:  Wang Jian <ulink url="mailto:larkw@263.net">larkw@263.net</ulink></para>
</listitem>
</varlistentry>
<varlistentry>
<term>zh&&lowbar;;TW&&lowbar;;Big5 Chinese BIG5 translation team:</term>
<listitem>
<para>team coordinators:  Chou Yeh-Jyi <ulink url="mailto:ycchou@ccca.nctu.edu.tw">ycchou@ccca.nctu.edu.tw</ulink></para>
</listitem>
</varlistentry>
</variablelist>

</sect1>
</chapter>

<chapter id="poisk-oshibok">
<title>Поиск ошибок</title>

<para><indexterm><primary>debugging macros</primary></indexterm></para>

<sect1 id="otladochnye-makrosy-predostavliaemye-qt-qt">
<title>Отладочные макросы, предоставляемые Qt <indexterm remap="idx"><primary>Qt</primary></indexterm></title>

<para>Отладочные макросы, предоставляемые  библиотекой Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>, описаны на странице debug.html online-документации Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>, 
доступной по линку "Debugging Techniques" на странице с индексом Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>-документации.</para>

<para>Наиболее часто используемые макросы:</para>

<para><itemizedlist>
<listitem>
<para>ASSERT(b)</para>
</listitem>
<listitem>
<para>CHECK&&lowbar;;PTR(p)</para>
</listitem>
</itemizedlist>
</para>

<para>b - выражение типа boolean. Генерирует предупреждающее сообщение дебаггера, если равно false; p - указатель, который проверяется, если
он равен нулю, то генерируется предупреждающее сообщение.</para>

<para>Подробности см. в online-документации Qt <indexterm remap="idx"><primary>Qt</primary></indexterm>.</para>
</sect1>

<sect1 id="makrosy-kde">
<title>Макросы KDE</title>

<para><emphasis remap="bf">Внимание:</emphasis> Эта глава - копия документа о макросе KDEBUG <indexterm remap="idx"><primary>KDEBUG</primary></indexterm>, включенного в набор библиотек KDE и
написанного Kalle Dalheimer's <ulink url="mailto:kalle@kde.org">kalle@kde.org</ulink>. Документ
находится в файле kdebug.html.</para>

<para>Последнее изменение: Sat Sep 13 11:56:01 CEST 1997</para>

<para><emphasis remap="bf">Что такое KDebug</emphasis></para>

<para>KDebug - набор макросов и функций, делающий более эффективным использование диагностических сообщений. Вы можете получать сообщения
одного из четырех уровней строгости. Вы можете выбрать в процессе выполнения, куда должны выводиться диагностические сообщения, и какие из них
вообще должны выводиться.</para>

<para><emphasis remap="bf">Макрос KDEBUG <indexterm remap="idx"><primary>KDEBUG</primary></indexterm></emphasis></para>

<para>Использование KDebug очень простое. Все, что вы должны сделать, это включить &&num;;include &&lt;;kdebug.h&&gt;; 
в начало каждого исходного файла, в котором вы хотите использовать диагностические сообщения, и выводить эти сообщения, 
вызывая макрос KDEBUG <indexterm remap="idx"><primary>KDEBUG</primary></indexterm>. Он ожидает 3 параметра. Первый - уровень безопасности; используйте следующие константы:</para>

<para><itemizedlist>
<listitem>
<para>KDEBUG&&lowbar;;INFO <indexterm remap="idx"><primary>KDEBUG&&lowbar;;INFO</primary></indexterm></para>
</listitem>
<listitem>
<para>KDEBUG&&lowbar;;WARN <indexterm remap="idx"><primary>KDEBUG&&lowbar;;WARN</primary></indexterm></para>
</listitem>
<listitem>
<para>KDEBUG&&lowbar;;ERROR <indexterm remap="idx"><primary>KDEBUG&&lowbar;;ERROR</primary></indexterm></para>
</listitem>
<listitem>
<para>KDEBUG&&lowbar;;FATAL <indexterm remap="idx"><primary>KDEBUG&&lowbar;;FATAL</primary></indexterm></para>
</listitem>
</itemizedlist>
</para>

<para>Второй параметр - это область. Область - часть KDE, которую вы определяете сами. Потом, в процессе выполнения, вы сможете выбрать, от какой
области необходимо печатать диагностические сообщения. См. файл kdelibs/kdecore/kdebugareas.txt для получения списка уже назначенных диапазонов областей.
Выберите область в диапазоне вашего приложения. Если ваше приложение еще не включено в этот список, и вы имеете доступ к CVS, вы можете
назначить там область для своего приложения, иначе напишите мне. Вероятно, будет хорошей идеей определить символическую константу для
области, которую вы хотите использовать, но это решаете вы. </para>

<para>Третий параметр, наконец, это текст, который вы хотите вывести. KDebug
автоматически добавит логическое имя приложения, если вы производите вывод в файл, в stderr или в syslog. Всегда добавляется символ новой строки, 
вы не должны его использовать сами. Если вам нужны параметры, вы можете использовать один из макросов KDEBUG1, ..., KDEBUG9. Это позволит
иметь от 1 до 9 дополнительных параметров. Синтаксис вывода абсолютно аналогичен printf, например, вы можете включать спецификации формата в ваше
сообщение, которые заменяются дополнительными параметрами. Например:</para>

<para><screen>KDEBUG3( &lt;idx/KDEBUG_INFO/, kmail_composer, "Message no. %d to %s has %d bytes",
          message_no, aMessage.to(), aMessage.length() );
</screen>
</para>

<para><emphasis remap="bf">KASSERT <indexterm remap="idx"><primary>KASSERT</primary></indexterm></emphasis></para>

<para>Есть также макросы KASSERT, KASSERT1, ..., KASSERT9, которые работают так же, как их KDEBUG <indexterm remap="idx"><primary>KDEBUG</primary></indexterm>-аналоги, однако они имеют
дополнительный первый параметр булевского типа. Только если он обращается в ложь, сообщение будет распечатано. </para>

<para>Примечание 1: вы не должны использовать ни KDEBUG <indexterm remap="idx"><primary>KDEBUG</primary></indexterm>, ни KASSERT <indexterm remap="idx"><primary>KASSERT</primary></indexterm> до создания объекта <indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication.</para>

<para>Примечание 2: KDebug не предоставляет никаких возможностей интернационализации, поскольку он предназначен только для разработчиков.
Если вы хотите информировать пользователя о нештатной ситуации (например, "этот файл защищен от записи"), используйте 
KMsgBox.</para>

<para><emphasis remap="bf">Опции компилятора</emphasis></para>

<para>Вы не должны задавать никаких специальных ключей для компилятора при использовании KDebug. 
Но когда вы распространяете свое приложение (в основном это касается людей, которые создают .rpm или .deb пакеты), вы должны компилировать с ключом
-DNDEBUG. Это просто удалит код дебаггера из вашего приложения и сделает его меньше и быстрее (например, оно будет использовать на 256K меньше
памяти).</para>

<para><emphasis remap="bf">Как анализировать диагностические сообщения в процессе выполнения</emphasis></para>

<para>Вы можете нажать Ctrl-Shift-F12 в любом приложении KDE в любое время, и появится диалог "Debug Settings". В нем вы сможете определить
раздельно для каждого уровня строгости, что должно быть сделано с диагностическими сообщениями этого уровня. Возможны следующие настройки:</para>

<para><itemizedlist>
<listitem>
<para>Output: в этом списке вы можете выбрать, куда будут выводиться диагностические сообщения; доступен выбор "File", "Message Box", "Shell" (имеется в виду stderr)
и "syslog". Не направляйте фатальные сообщения в syslog, если вы не системный администратор.
По умолчанию используется "Message Box".</para>
</listitem>
<listitem>
<para>File: это поле используется, если вы решили выводить сообщения в файл; здесь указывается имя файла (интерпретируется относительно текущего каталога).
По умолчанию kdebug.dbg.
</para>
</listitem>
<listitem>
<para>Area: определяет области, для которых осуществляется вывод. Все сообщения, не упомянутые в них, не будут выведены
(если только это поле не оставлено пустым, что используется по умолчанию и значит вывод всех сообщений). Вы можете ввести несколько областей,
разделенных ",", и вы можете назначить диапазоны областей с синтаксисом "начало-конец". Например, 117,214-289,356-359,221. Не используйте пробелы.</para>
</listitem>
</itemizedlist>
</para>

<para>Кроме того, вы можете выбрать опцию "Прерывать на фатальных ошибках" ("Abort on fatal errors"). В этом случае при возникновении диагностического сообщения с уровнем
"KDEBUG&&lowbar;;FATAL <indexterm remap="idx"><primary>KDEBUG&&lowbar;;FATAL</primary></indexterm>" приложение завершит работу с кодом SIGABRT после вывода этого сообщения. Когда вы закроете диалог кнопкой OK, ваши
настройки вступят в силу немедленно и сохранятся в конфигурационном файле вашего приложения. Имейте в виду, что эти установки специфичны
для каждого приложения! При нажатии cancel все изменения будут утеряны, и будут возвращены предыдущие установки.</para>
</sect1>
</chapter>

<chapter id="standart-failovoi-sistemy-kde">
<title>Стандарт файловой системы KDE</title>

<para>Эта глава - копия стандарта файловой системы KDE, опубликованного на web-сайте KDE <ulink url="http://www.kde.org">\|\|</ulink>. Стандарт написан
Richard Moore <ulink url="rich@kde.org">rich@kde.org</ulink></para>

<para><emphasis remap="bf">Стандарт файловой системы KDE</emphasis></para>

<para>Этот документ определяет структуру каталогов, которую должны использовать все программы KDE. Это версия 0.0.4 стандарта.</para>

<sect1 id="vvedenie-0">
<title>Введение</title>

<para>Цель KDE FSSTD <indexterm remap="idx"><primary>KDE FSSTD</primary></indexterm> - создать уверенность, что все ресурсы (иконки, mime-типы и т.п.), необходимые приложению KDE, расположены
в соответствующих директориях. Следование этой структуре позволит приложениям использовать такие инструменты, как класс KIconLoader, и
реализует отделение платформеннозависимых данных, необходимых KDE, от платформеннонезависимых данных (сделав возможной инсталляцию для различных
архитектур). В этом документе имена каталогов оканчиваются '/'. Когда употребляется слово 'appname', взятое в угловые скобки
&&lt;;вот так&&gt;;, то это значит, что на его месте могут быть входы, соответствующие любому установленному приложению KDE.
Слово 'lang' используется аналогично, чтобы показать, что здесь должны быть входы для всех поддерживаемых языков, состоящие из двух букв,
например, 'fr' для французского, 'ru' для русского.</para>
</sect1>

<sect1 id="struktura-katalogov">
<title>Структура каталогов</title>

<para>Структура каталогов KDE показана ниже, корневой каталог инсталляции KDE обычно '/opt/kde', и может быть получен в процессе выполнения
вызовом метода kdedir() класса <indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication (это заменяет переменную окружения KDEDIR, которую постепенно перестают использовать).
В данном документе этот каталог обозначается kdedir().
<indexterm><primary>KDE File System</primary></indexterm><indexterm><primary>.kdelnk files</primary></indexterm></para>

<para><itemizedlist>
<listitem>
<para>kdedir()/
<itemizedlist>
<listitem>
<para>bin/
<itemizedlist>
<listitem>
<para>Бинарные файлы приложений</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>lib/
<itemizedlist>
<listitem>
<para>стандартные библиотеки KDE (libkdecore, например)</para>
</listitem>
<listitem>
<para><emphasis>&&lt;;appname&&gt;;</emphasis>/
<itemizedlist>
<listitem>
<para>Платформеннозависимые данные приложения</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>include/
<itemizedlist>
<listitem>
<para>Стандартные файлы заголовков KDE</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>parts/</para>
</listitem>
<listitem>
<para>cgi-bin/
<itemizedlist>
<listitem>
<para>CGI программы для kdehelp</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>share/
<itemizedlist>
<listitem>
<para>doc/
<itemizedlist>
<listitem>
<para>HTML/
<itemizedlist>
<listitem>
<para>default --&gt; ссылка на kdedir()/share/doc/HTML/en</para>
</listitem>
<listitem>
<para><emphasis>&&lt;;lang&&gt;;</emphasis>/
<itemizedlist>
<listitem>
<para><emphasis>&&lt;;appname&&gt;;</emphasis>/
<itemizedlist>
<listitem>
<para>index.html</para>
</listitem>
<listitem>
<para>Другие файлы помощи</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>config/</para>
</listitem>
<listitem>
<para>applnk/
<itemizedlist>
<listitem>
<para>System/</para>
</listitem>
<listitem>
<para>Utilities/</para>
</listitem>
<listitem>
<para>Applications/</para>
</listitem>
<listitem>
<para>Games/</para>
</listitem>
<listitem>
<para>kfind.kdelnk <indexterm remap="idx"><primary>.kdelnk</primary></indexterm></para>
</listitem>
<listitem>
<para>khelp.kdelnk <indexterm remap="idx"><primary>.kdelnk</primary></indexterm></para>
</listitem>
<listitem>
<para>khome.kdelnk <indexterm remap="idx"><primary>.kdelnk</primary></indexterm></para>
</listitem>
<listitem>
<para>krefresh.kdelnk <indexterm remap="idx"><primary>.kdelnk</primary></indexterm></para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>mimelnk/
<itemizedlist>
<listitem>
<para>magic</para>
</listitem>
<listitem>
<para>text/</para>
</listitem>
<listitem>
<para>audio/</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>partlnk/
<itemizedlist>
<listitem>
<para><emphasis>&&lt;;partname&&gt;;</emphasis>.kdelnk <indexterm remap="idx"><primary>.kdelnk</primary></indexterm></para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>icons/
<itemizedlist>
<listitem>
<para>Иконки, используемые в kdelnk файлах</para>
</listitem>
<listitem>
<para><emphasis>&&lt;;appname&&gt;;</emphasis>.xpm</para>
</listitem>
<listitem>
<para>mini/
<itemizedlist>
<listitem>
<para>Мини-иконки для kpanel</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>toolbar <indexterm remap="idx"><primary>toolbar</primary></indexterm>/
<itemizedlist>
<listitem>
<para>Стандартные иконки панели инструментов (например, fileopen.xpm)</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>wallpapers/
<itemizedlist>
<listitem>
<para>Обои, используемые kdisplay</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>apps/
<itemizedlist>
<listitem>
<para><emphasis>&&lt;;appname&&gt;;</emphasis>/
<itemizedlist>
<listitem>
<para>toolbar <indexterm remap="idx"><primary>toolbar</primary></indexterm>/
<itemizedlist>
<listitem>
<para>Иконки панели инструментов</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>pics/
<itemizedlist>
<listitem>
<para>Другие рисунки приложения</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>Платформеннонезависимые данные приложения</para>
</listitem>
</itemizedlist>
				</para>
</listitem>
<listitem>
<para><emphasis>&&lt;;libname&&gt;;</emphasis>/
<itemizedlist>
<listitem>
<para>pics/</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
<listitem>
<para>locale/
<itemizedlist>
<listitem>
<para><emphasis>&&lt;;lang&&gt;;</emphasis>/
<itemizedlist>
<listitem>
<para>LC&&lowbar;;MESSAGES/
<itemizedlist>
<listitem>
<para><emphasis>&&lt;;appname&&gt;;</emphasis>.mo</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</itemizedlist>
</para>
</sect1>

<sect1 id="chto-eto-znachit-dlia-razrabotchika">
<title>Что это значит для разработчика?</title>

<para>Стандартное приложение KDE инсталлирует файлы в различные места вышеприведенной структуры. Безусловно необходимые файлы - исполнимые файлы приложения,
файл kdelnk, иконка приложения и файлы помощи - все остальные не обязательны. Файлы инсталлируются в следующие каталоги:</para>

<para><screen>Тип файла	                                  Расположение

Бинарные файлы приложения (необходимо             kdedir()/bin/
Файл kdelnk приложения (необходимо)               kdedir()/share/applnk/
Иконка приложения (необходимо)                    kdedir()/share/icons/&&lt;;appname&&gt;;.xpm
Файлы помощи приложения (необходимо)              kdedir()/share/doc/default/HTML/&&lt;;appname&&gt;;/&&lt;;index&&gt;;.html
Иконки панели инструментов приложения             kdedir()/share/apps/&&lt;;appname&&gt;;/toolbar/
Платформеннонезависимые данные приложения         kdedir()/share/apps/&&lt;;appname&&gt;;/
Платформеннозависимые данные приложения           kdedir()/lib/&&lt;;appname&&gt;;/
</screen>

<indexterm><primary>KDE File System</primary></indexterm></para>
</sect1>

<sect1 id="dokumentatsiia-prilozheniia">
<title>Документация приложения</title>

<para>Я советую поместить хотя бы одну страницу в</para>

<para>kdedir()/doc/default/HTML/&&lt;;appname&&gt;;/&&lt;;appname&&gt;;.html</para>

<para>для соответствия стандартам KDE. Приложение может использовать каталог для хранения в нем любых необходимых файлов помощи. </para>

<para>Приложения, поддерживающие несколько языков, должны поместить файлы на этих языках в 
kdedir()/doc/&&lt;;lang&&gt;;/HTML/&&lt;;appname&&gt;;/&&lt;;appname&&gt;;.html,
создавая один 'lang' каталог для каждого языка, используя его двухбуквенный код, как обычно. Такое расположение файлов позволит создать ссылки
между файлами помощи двух различных приложений, поддерживающих данный язык. </para>

<para>Я не совсем удовлетворен предлагаемым решением, поскольку оно не позволяет вернуться к языку по умолчанию, если требуемый перевод отсутствует.</para>
</sect1>

<sect1 id="chto-eto-znachit-dlia-razrabotchikov-bibliot">
<title>Что это значит для разработчиков библиотек?</title>

<para><itemizedlist>
<listitem>
<para>kdedir()/share/apps/&&lt;;libname&&gt;;/toolbar <indexterm remap="idx"><primary>toolbar</primary></indexterm></para>
</listitem>
</itemizedlist>

Иконки панели инструментов для элементов библиотеки.</para>

<para><itemizedlist>
<listitem>
<para>kdedir()/share/apps/&&lt;;libname&&gt;;/pics</para>
</listitem>
</itemizedlist>

Другие картинки (bitmaps) для элементов библиотеки.</para>
</sect1>
</chapter>

<chapter id="ispolzovanie-failovoi-sistemy-v-proektakh-kd">
<title>Использование файловой системы в проектах KDevelop</title>

<para>Предыдущая глава описывала стандарт файловой системы KDE, эта глава описывает, как использовать файловую систему. Проект KDE
использует файловую систему по крайней мере при инсталляции; поэтому мы обсудим правила установки инсталляционных свойств 
файлов вашего проекта. Поскольку ваше приложение будет использовать все установленные файлы, ему важно знать, как получить к ним
стандартные относительные пути. Это позволит вашему приложению работать независимо от того, где располагается корневой каталог файловой системы KDE, и, таким образом,
избежать жесткого задания путей файлов.</para>

<sect1 id="dostup-k-failam-v-protsesse-vypolneniia">
<title>Доступ к файлам в процессе выполнения</title>

<para>После инсталляции вашего проекта конечным пользователем, вашему приложению может потребоваться файл в процессе выполнения. В ходе
разработки вы наверняка натыкались на одну ошибку при запуске приложения из IDE KDevelop - при вызове
помощи через "Help"-"Contents" или нажатием F1. В результате вам выдавалось сообщение, что
файл index.html не найден - если вы не установили перед этим приложение в локальной файловой системе KDE. Ваше приложение запрашивает
KDEHelp <indexterm remap="idx"><primary>KDEHelp</primary></indexterm>, чтобы он открыл индексную страницу, предварительно определяя каталог инсталляции методами <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal>, осуществляющими доступ
к файловой системе; поэтому рассмотрим, что предлагает <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal>, и приведем несколько примеров использования. Другие классы
<literal remap="tt">KDE-Core</literal> также используют файловую систему KDE, например, <literal remap="tt">KIconLoader</literal> и <literal remap="tt">KLocale</literal>, которые будут рассмотрены позже.</para>
</sect1>

<sect1 id="metody-kapplicationkapplication">
<title>Методы <indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication </title>

<para>Класс <indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication предоставляет следующие методы доступа к файловой системе KDE:
<screen>void invokeHTMLHelp ( QString aFilename, QString aTopic ) const
static const QString& kde_htmldir ()
static const QString& kde_appsdir ()
static const QString& kde_icondir ()
static const QString& kde_datadir ()
static const QString& kde_localedir ()
static const QString& kde_cgidir ()
static const QString& kde_sounddir ()
static const QString& kde_toolbardir ()
static const QString& kde_wallpaperdir ()
static const QString& kde_bindir ()
static const QString& kde_configdir ()
static const QString& kde_mimedir ()
static QString localkdedir ()
static QString localconfigdir ()
static QString findFile ( const char *file )
</screen>

<indexterm><primary>KDE File System</primary></indexterm></para>

<para>Методы обычно используются с объектом <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal> вашего приложения, где <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal> предоставляет макрос 
<literal remap="tt">kapp</literal>, возвращающий указатель на него:</para>

<para>&&num;;define kapp <indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication::getKApplication()</para>

<para>Поэтому обычно методы используются так:
<screen>QString sounddir=kapp-&gt;kde_sounddir();
</screen>

В этом примере путь к каталогу KDE с звуковыми файлами заносится в <literal remap="tt">QString</literal>, к которому вы должны добавить, например, имя файла.
Затем вы можете обработать эту информацию и проиграть файл. Всегда проверяйте существование файла, используя
метод <literal remap="tt">exists()</literal> объекта <literal remap="tt">QFileInfo</literal>.</para>

<para>Среди этих методов,
<screen>void invokeHTMLHelp( QString aFilename, QString aTopic ) const [public]
</screen>

занимает специальное положение; он запускает помощь KDE. Вы должны использовать его везде, где пользователю требуется доступ к информации, например, когда
открыт модальный диалог. Клавиша F1 не будет работать для вызова помощи в этой ситуации, хотя пользователь должен быть обеспечен соответствующей
страницей помощи. Чтобы обеспечить ее использование, добавьте кнопку "Help" в ваш диалог и создайте слот, к которому подсоедините кнопку по сигналу 
<literal remap="tt">pressed()</literal>. В этом слоте используйте <literal remap="tt"><indexterm remap="cdx"><primary><literal>invokeHTMLHelp()</literal></primary></indexterm>invokeHTMLHelp()</literal> со ссылкой на соответствующую страницу и раздел; в случае, если
документация еще не написана, оставьте вопрос открытым, чтобы решить его при синхронизации документации с приложением.</para>

<para>В документации по <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal> говорится:</para>

<para>Вызов просмотрщика HTML файлов помощи KDE.</para>

<para>Параметры: aTopic - 
Это позволяет реализовать контекстно-зависимую помощь. Его значение добавляется к имени файла после хеш-символа "&&num;;".</para>

<para>aFilename - Имя файла, который будет загружен. Его расположение определяется автоматически в соответствии с KFSSTND. Если aFilename пусто,
используется логическое имя приложения с добавленным к нему расширением .html.</para>

<para>Методы  <literal remap="tt"><indexterm remap="cdx"><primary><literal>KApplication</literal></primary></indexterm>KApplication</literal> возвращают следующие пути:</para>

<para><screen>kde_htmldir()         kdedir()/share/doc/HTML         Возвращает каталог, в котором KDE хранит
                                                      свои файлы HTML документации

kde_appsdir()         kdedir()/share/applnk           Возвращает каталог, в котором приложения 
						      KDE хранят файл .kdelnk

kde_icondir()         kdedir()/share/icons            Возвращает каталог иконок KDE

kde_datadir()         kdedir()/share/apps             Возвращает каталог, в котором приложения
                                                      KDE хранят свои специальные данные

kde_localedir()       kdedir()/share/locale           Возвращает каталог, в котором хранятся файлы с информацией
                                                      о локализации (например, перевод экранных сообщений) 

kde_cgidir()          kdedir()/cgi-bin                Возвращает каталог с cgi-скриптами

kde_sounddir()        kdedir()/share/sounds           Возвращает каталог со звуковыми файлами.
                                                      Это каталог специальных звуков KDE.
                                                      Звуки приложения хранятся в
                                                      kde_datadir()

kde_toolbardir()      kdedir()/share/toolbar          Возвращает каталог с иконками кнопок панели инструментов

kde_wallpaperdir()    kdedir()/share/wallpapers       Возвращает каталог с обоями

kde_bindir()          kdedir()/bin                    Возвращает каталог с бинарными файлами приложений KDE

kde_configdir()       kdedir()/share/config           Возвращает каталог с конфигурационными файлами

kde_mimedir()         kdedir()/share/mimelnk          Возвращает каталог с информацией о mime-типах

localkdedir()         $HOME/.kde                      Возвращает локальный корневой каталог KDE (KDE base dir)

localconfigdir()      $HOME/.kde/share/config         Возвращает локальный каталог KDE с конфигурационными файлами
</screen>
</para>

<para>Для поиска определенного файла, используйте <literal remap="tt">findFile(const char *file)</literal>, который просматривает следующие пути файловой системы KDE:</para>

<para><orderedlist><listitem>
<para>$KDEDIR,</para>
</listitem>
<listitem>
<para>$KDEPATH,</para>
</listitem>
<listitem>
<para>"&&lsqb;;KDE Setup&&rsqb;;:Path=" вход в конфигурационном файле.</para>
</listitem>
</orderedlist>
</para>

<para>Если файл не найден, метод QString isEmpty() возвращает True</para>
</sect1>

<sect1 id="metody-kiconloader">
<title>Методы KIconLoader </title>

<para>QPixmap loadIcon ( const QString &&amp;;name, int w = 0, int h = 0 )</para>

<para>QPixmap reloadIcon ( const QString &&amp;;name, int w = 0, int h = 0)</para>

<para>QPixmap loadMiniIcon ( const QString &&amp;;name , int w = 0, int h = 0 )</para>

<para>QPixmap loadApplicationIcon ( const QString &&amp;;name, int w = 0, int h = 0 )</para>

<para>QPixmap loadApplicationMiniIcon ( const QString &&amp;;name, int w = 0, int h = 0 )</para>

<para>bool insertDirectory ( int index, const QString &&amp;;dir&&lowbar;;name )</para>
</sect1>

<sect1 id="ustanovka-installiatsionnykh-svoistv-failov">
<title>Установка инсталляционных свойств файлов</title>

<para>Выше было объяснено, где приложение KDE должно располагать свои файлы и как получить к ним доступ при выполнении. Теперь объясним,
как правильно установить свойства файлов, чтобы они записались в нужные места при инсталляции. Файлы Makefiles поддерживают набор макросов
для инсталляции ваших файлов в файловую систему KDE, которые должны быть использованы при установке значений инсталляционных свойств файлов.</para>

<para>Для установки свойств откройте проект и выберите "Project"-"File Properties", что откроет диалог свойств файла.
Свойства файла отображаются, если вы выберите файл, включенный в проект. Во-первых, файл имеет свойство "тип" ("type"),
которое может принимать такие значения:</para>

<para><itemizedlist>
<listitem>
<para><emphasis remap="bf">HEADER:</emphasis> файл заголовка</para>
</listitem>
<listitem>
<para><emphasis remap="bf">SOURCE:</emphasis> файл исходника</para>
</listitem>
<listitem>
<para><emphasis remap="bf">SCRIPT:</emphasis> файл сценария (script-файл)</para>
</listitem>
<listitem>
<para><emphasis remap="bf">DATA:</emphasis> файл данных, обычно картинка или файл документации HTML</para>
</listitem>
<listitem>
<para><emphasis remap="bf">PO:</emphasis> файл перевода</para>
</listitem>
<listitem>
<para><emphasis remap="bf">KDEV&&lowbar;;DIALOG:</emphasis> файл диалога, обрабатываемый библиотекой диалогов</para>
</listitem>
</itemizedlist>
</para>

<para>Далее, файл включен в проект, если выбрана опция "Include in Distribution". Ее установка приведет к включению файла в дистрибутив приложения.</para>

<para>Если файл должен быть инсталлирован, вы должны разрешить опцию "Install". Это сделает доступным свойство Installation path (путь инсталляции) для выбранного файла,
куда уже вставлено имя файла.</para>

<para>Как уже говорилось, Makefile содержит набор макросов для путей файловой системы KDE. Они используются для установки
путей инсталляции, и дают гарантию, что файл будет действительно записан в соответствующее место файловой системы, а не куда-нибудь еще. Используемые макросы
должны быть взяты в круглые скобки и отмечены символом доллара перед макросом. Когда configure создает файлы Makefile
на машине конечного пользователя, то определяются значения этих макросов, соответствующие реальному каталогу, и в файлы Makefile.am 
заносится действительная информация о путях.</para>

<para>Если посмотреть на стандартный проект KDE, то можно увидеть, что свойство файла <literal remap="tt">index.html</literal> уже использует макрос
для определения пути:</para>

<para>$(kde&&lowbar;;htmldir)/en/kscribble/index.html</para>

<para>Это значит, что make запишет файл index.html в kde-html каталог, подкаталог en для английского языка, подкаталог приложения в файл с именем index.html.
Вы можете использовать другое имя файла, если вы хотите переименовать файл при инсталляции.</para>

<para>Для определения положения файлов приложения в структуре kpanel вы должны отредактировать файл проекта Makefile.am, если место назначения отличается от
секции "Приложения" ("Applications") kpanel:</para>

<para>APPSDIR = $(kde&&lowbar;;appsdir)/Applications</para>

<para>Возможные значения (как говорит стандарт файловой системы KDE):</para>

<para><itemizedlist>
<listitem>
<para>Applications</para>
</listitem>
<listitem>
<para>Games</para>
</listitem>
<listitem>
<para>Graphics</para>
</listitem>
<listitem>
<para>Internet</para>
</listitem>
<listitem>
<para>Multimedia</para>
</listitem>
<listitem>
<para>Settings</para>
</listitem>
<listitem>
<para>System</para>
</listitem>
<listitem>
<para>Utilities</para>
</listitem>
</itemizedlist>
</para>

<para>Установка пустого пути добавит линк вашего приложения непосредственно в корень kpanel.</para>

<para>Следующий список содержит макросы, которые могут использоваться для указания путей файлов:</para>

<para><screen>kde_htmldir       - для документации (содержит подкаталоги для языков),
kde_appsdir       - для файла (.kdelnk), 
kde_icondir       - для иконок,
kde_minidir       - для мини-иконок,
kde_datadir       - для данных приложения (используйте подкаталог),
kde_locale        - для файлов перевода (содержит подкаталоги для языков),
kde_cgidir        - для cgi-bin исполнимых файлов,
kde_confdir       - для конфигурационных файлов,
kde_mimedir       - для mime-типов,
kde_toolbardir    - для общих иконок панелей инструментов,
kde_wallpaperdir  - для общих обоев.
</screen>
</para>

<para>Используйте эти макросы с необходимыми подкаталогами и именами файлов для установки инсталляционных свойств.
По умолчанию, текущая версия HTML документации, файл kdelnk, иконка и мини-иконка, файлы перевода (даже новые)
уже имеют установленными пути инсталляции; поэтому вы не должны вносить никаких изменений в конфигурацию по умолчанию
шаблона, сгенерированного KDevelop.</para>
</sect1>

<sect1 id="organizatsiia-dannykh-proekta">
<title>Организация данных проекта</title>

<para>Другая проблема, с которой часто сталкиваются разработчики, это когда они включают в свой проект дополнительные файлы с данными,
которые необходимо инсталлировать вместе с проектом. Вы уже знаете, куда их инсталлировать, но как организовать их в исходном дереве?</para>

<para>Хорошим советом будет собрать данные в каталоги, которые более-менее соответствуют стандарту файловой системы KDE, например,
ваше приложение требует дополнительных иконок панели инструментов. Создание этих иконок в главном каталоге проекта - не очень хорошая идея,
поскольку их будет тяжело найти в просмотрщике файлов, и их удаление превращается в долгую работу с каждой иконкой. Создайте свой каталог для иконок
с помощью "File"- "New" и выберите подкаталог <literal remap="tt">toolbar <indexterm remap="idx"><primary>toolbar</primary></indexterm></literal>; если он не существует, то его можно легко создать через диалог "выбор каталога" ("select directory").
Существующие иконки можно скопировать и добавить в проект командой "добавить существующие файлы" ("Project"-"Add existing file(s)"), в которой необходимо выбрать
файлы и каталог назначения. При выборе каталога назначения, вы можете вначале создать каталог <literal remap="tt">toolbar <indexterm remap="idx"><primary>toolbar</primary></indexterm></literal> в диалоге.
По окончании нажмите OK, и файлы будут скопированы и включены в проект.</para>

<para>Как пример, иконки панели инструментов должны инсталлироваться в:</para>

<para>$(kde&&lowbar;;datadir)/<emphasis>&&lt;;appname&&gt;;</emphasis>/toolbar <indexterm remap="idx"><primary>toolbar</primary></indexterm>/<emphasis>&&lt;;ваша&&lowbar;;иконка&&gt;;</emphasis>.xpm</para>

<para>Картинки и другие иконки, которые не используются на панелях инструментов, лучше положить в подкаталог <emphasis>pics</emphasis> вместо <emphasis>toolbar <indexterm remap="idx"><primary>toolbar</primary></indexterm></emphasis>.</para>
</sect1>

<sect1 id="fail-kdelnk">
<title>Файл <literal remap="tt">kdelnk</literal></title>

<para>Файл <emphasis>&&lt;;appname&&gt;;</emphasis>.kdelnk <indexterm remap="idx"><primary>.kdelnk</primary></indexterm>, включенный в ваш проект, будет проинсталлирован в структуру меню kpanel.
Он полностью заполнен, и в общем случае не требует доработки. Но, несмотря на способности KDevelop помогать вам в разработке проекта,
он не может определить конечных целей вашего приложения, а эту информацию можно включить в 
файл kdelnk. Поскольку это текстовый файл, выберите его из RFV или LFV; он откроется в
окне Header/Resource.</para>

<para>Перед вами пример файла kdelnk:
<screen># KDE Config File
&&lsqb;;KDE Desktop Entry&&rsqb;;
Type=Application
Exec=kscribble
Icon=kscribble.xpm
DocPath=kscribble/index.html
Comment=
Comment&&lsqb;;de&&rsqb;;=
Terminal=0
Name=kscribble
Name&&lsqb;;de&&rsqb;;=kscribble
</screen>
</para>

<para>Это уже содержит базовую конфигурацию нашего приложения (иконки, имя исполнимого файла, название приложения и т.п.).
Но секция комментариев Comment остается пустой. Сюда вы можете вставить всплывающую подсказку, которая будет отображаться, когда курсор
мыши будет находиться над иконкой файла на рабочем столе или в меню kpanel. Если scribble будет небольшой графической программой, то введите, например,</para>

<para><screen>Comment=A simple drawing program
</screen>
</para>

<para>Каждая последующая строка комментариев содержит перевод этого описания на указанный в квадратных скобках язык. Попросите переводчиков
вставить правильный перевод на их родной язык или включите файл kdelnk, когда будете просить о переводе файла po приложения;
то же самое касается и названия приложения в строке Name файла. 
<footnote>
<para>Более подробную информацию о файле .kdelnk <indexterm remap="idx"><primary>.kdelnk</primary></indexterm>, особенно о его использовании
при обработке командной строки, см.
<ulink url="kde_libref.html">The KDE Library Reference Guide</ulink></para>
</footnote>
</para>
</sect1>
</chapter>

<chapter id="sovety-po-programmirovaniiu">
<title>Советы по программированию</title>

<para>В конце этой книги я хочу обратить внимание на некоторые моменты, о которых надо помнить при разработке. Это в основном
советы по программированию на C++, которые относятся к KDE и особенно Qt, и взяты в центре разработчиков KDE, который можно найти
в Internet по адресу <ulink url="http://www.kde.org">\|\|</ulink>.</para>

<para><variablelist>
<varlistentry>
<term>Имена файлов</term>
<listitem>
<para>Во-первых, при создании исходников вы должны использовать только строчные буквы в именах файлов. KDevelop обеспечивает
это, если вы используете автоприсвоение имен. Это упрощает для других разработчиков запоминание того,
что в каком файле искать при отладке.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Имена классов</term>
<listitem>
<para>Имена классов в приложении KDE должны:
<itemizedlist>
<listitem>
<para>начинаться с префикса <emphasis remap="bf">K</emphasis>, затем следует имя, описывающее назначение класса (по вашему выбору). Например,
<literal remap="tt">KMyWidget</literal> для специального элемента приложения,</para>
</listitem>
<listitem>
<para>иметь членов, имена которых начинаются только со строчной буквы, а следующие слова в них начинаются с заглавной, например,
<literal remap="tt">myWidgetPointer()</literal>,</para>
</listitem>
<listitem>
<para>называть методы, которые возвращают значения private-атрибутов, без использования префикса <literal remap="tt">get</literal>. Используйте содержательное имя
члена класса. Например, <literal remap="tt">b&&lowbar;;myboolean</literal> - private член. Метод, возвращающий текущее значение, может называться
<literal remap="tt">myBoolean()</literal>.</para>
</listitem>
</itemizedlist>
</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Обращение к файлам в коде</term>
<listitem>
<para>Следует избегать жесткого задания путей, используя стандарт файловой системы KDE. Вы должны только определить путь к вашему приложению,
это можно сделать с помощью соответствующего макроса в файле <literal remap="tt">Makefile.am</literal>, как это было описано выше. В коде используйте методы
<literal remap="tt">KApplication</literal> для получения действительных путей.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Документация классов</term>
<listitem>
<para>Еще один пункт, который уже упоминался, - документация классов. Вы должны придерживаться правил форматирования <literal remap="tt">KDoc</literal>, поскольку их используют все разработчики KDE
для документирования классов. Добавьте хотя бы одну строку комментариев к каждому члену класса себе для напоминания
его предназначения и другим для повторного использования кода. Повторное использование кода с GPL имеет больше смысла, когда вы знаете, где найти
уже существующее решение по документированному классу. Qt-библиотека - хороший пример хорошо документированного интерфейса, хотя он не использует 
<literal remap="tt">KDoc</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Используйте <literal remap="tt">new</literal> для создания элементов</term>
<listitem>
<para>В реализации приложения предпочитайте создавать элементы в куче вызовом <literal remap="tt">new</literal>. Библиотеки Qt имеют хорошее свойство
автоматически удалять все дочерние элементы, созданные с помощью <literal remap="tt">new</literal>, поэтому вы не должны даже использовать <literal remap="tt">delete</literal>.
Это одно из важнейших технических преимуществ библиотеки Qt, и вы должны его широко использовать.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Отладка</term>
<listitem>
<para>Когда дело доходит до отладки, используйте макрос <literal remap="tt">KDebug</literal>. Есть похожие макросы Qt, но он обеспечивает доступ с свойствам через клавиши
STRG+ALT+F12. См. <ulink url="../kde_libref/index-4.html#ss4.4">KDE Library Reference Guide</ulink> 
для более подробной информации о фильтрации событий этим макросом. Вы также можете использовать <literal remap="tt">assert()</literal>, но поддерживайте соответствие
с кодом для отладки.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Объявления <literal remap="tt">const</literal></term>
<listitem>
<para>Используйте объявление <literal remap="tt">const</literal> для функций-членов, которые не меняют значений private-членов. Это можно использовать
для всех методов, возвращающих значения этих членов. Это позволяет избежать случайного изменения значения и отловить
логические ошибки на этапе компиляции. Что касается инициализации членов с декларацией const, вы должны это делать одновременно с использованием 
<literal remap="tt">static</literal> в определении, и инициализировать значение вне конструктора:
<screen>class foo {
	static const int value;
};

const foo::value = 10;
</screen>
</para>
<para>ANSI C++ позволяет инициализировать член в конструкторе, но избегайте подобной техники, так как некоторые компиляторы не поддерживают данную возможность.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Виртуальные методы</term>
<listitem>
<para>Как объяснялось в разделе <link linkend="User-Interaction">Взаимодействие с пользователем</link>, 
вы должны учитывать права доступа и декларацию <literal remap="tt">virtual</literal> при перекрывании виртуальных методов. По крайней мере, вы не должны уменьшать доступ к виртуальному методу от protected
до private.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Предварительные объявления</term>
<listitem>
<para>Заголовки классов должны быть включены там, где вы обращаетесь к объекту или экземпляру класса в вашем коде. Это значит, что если ваш класс
использует член другого класса, замените директиву &&num;;include предварительным описанием класса, например, вместо:</para>
<para><screen>#include &lt;qpushbutton.h&gt;

class KMyWidget:public QWidget
{

private:
  QPushButton* ok_button;
};
</screen>
</para>
<para>предпочтительнее только объявить класс <literal remap="tt">QPushButton</literal> в файле заголовка:</para>
<para><screen>class QPushButton;

class KMyWidget:public QWidget
{

private:
  QPushButton* ok_button;
};
</screen>
</para>
<para>и поместить директиву include в соответствующий файл-исходник, где, например, экземпляр <literal remap="tt">ok&&lowbar;;button</literal> используется любым методом
класса <literal remap="tt">QPushButton</literal>. Это сохранит время компилятора, особенно если вы используете экземпляры классов, которые вы разрабатываете. 
Компилятор должен перекомпилировать все исходники, включающие заголовок, если вы делаете любое изменение в интерфейсе класса,
поэтому простое добавление метода, возвращающего целое значение внутреннего объекта, может привести к перекомпиляции всех исходников,
включающих файл заголовка данного класса.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Сообщения о неиспользуемых параметрах и значения по умолчанию</term>
<listitem>
<para>Также вы должны удалить формальные параметры методов, которые не являются необходимыми. Это позволит избежать
предупреждения <literal remap="tt">unused parameter</literal> от вашего компилятора, когда он увидит формальный параметр, который не используется
в реализации. Обычно вы посылаете несколько аргументов по умолчанию в некоторые методы. Их значения необходимо устанавливать в объявлении
члена класса, а не в его реализации.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Использование <literal remap="tt">config.h</literal></term>
<listitem>
<para>Проекты KDevelop, как и любые другие проекты, использующие <literal remap="tt">autoconf</literal> для создания скриптов <literal remap="tt">configure</literal>, создают файл
<literal remap="tt">config.h</literal> после выполнения скрипта <literal remap="tt">configure</literal> на пользовательской машине. В нем приводятся значения, найденные <literal remap="tt">configure</literal>,
которые могут быть использованы в исходниках. Директива для включения файла <literal remap="tt">config.h</literal> следующая:</para>
<para><screen>#ifdef HAVE_CONFIG_H
#include &lt;config.h&gt;
#endif
</screen>
</para>
<para>Один из наиболее часто используемых входов <literal remap="tt">config.h</literal>, вероятно, определение типа <literal remap="tt">bool</literal> для компиляторов,
которые не совместимы с проектами последних версий ANSI C++.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Используйте <literal remap="tt">0</literal> вместо <literal remap="tt">NULL</literal></term>
<listitem>
<para>Предпочитайте использовать <literal remap="tt">0</literal> непосредственно вместо <literal remap="tt">NULL</literal> для установки значений, как это делают библиотеки KDE и Qt. 
Это повышает переносимость ваших приложений для компиляторов, которые имеют проблемы с использованием <literal remap="tt">NULL</literal>.</para>
</listitem>
</varlistentry>
<varlistentry>
<term>Временные данные</term>
<listitem>
<para>Вы должны определять временные экземпляры всегда перед их использованием. Это лучший путь, чем прямое использование. Пример:
<screen>// Не следует
for( int i=0; i&lt;n; i++){
  //что-то делаем
  };

// Следует
int i;

for(i=0; i&lt;n; i++){
  //что-то делаем
  };
</screen>
</para>
<para>Это также касается вызовов функций:
<screen>// Не следует
setColor( &&amp;;(QColor(black)) );

// Следует
QColor color(black);
setColor( &&amp;;color );
</screen>
</para>
<para></para>
</listitem>
</varlistentry>
</variablelist>
</para>
</chapter>

<chapter id="litsenzirovanie">
<title>Лицензирование</title>

<para>В этой секции обсуждаются вопросы, связанные с лицензированием приложений, разработанных с использованием KDevelop IDE. Во-первых, мы
рассмотрим стандартное поведение, рассмотрим преимущества лицензирования вашего приложения в соответствии с GPL и, наконец, 
обсудим вопросы разработки коммерческих приложений.</para>

<sect1 id="litsenziia-gpl">
<title>Лицензия GPL</title>

<para>KDevelop IDE лицензирован в соответствии с GNU General Public License. Это значит, что любой пользователь может копировать, изменять и
распространять исходный код пакета KDevelop в соответствии с условиями данной лицензии. Эта лицензия защищает права команды разработчиков 
KDevelop как авторов данного продукта.</para>

<para>Исходя из этого, с целью помочь авторам при разработке свободно распространяемых программ, все сгенерированные KDevelop шаблоны
содержат ссылку на GPL, а также копию самой лицензии. Разработчики, с другой стороны, <emphasis>могут</emphasis> использовать данную лицензию
как основу для распространения своей продукции, но ни в коем случае не принуждаются к этому.</para>

<para>Автор, лицензируя свой продукт на основе GPL, получает следующие возможности:</para>

<para><itemizedlist>
<listitem>
<para>вы можете использовать любой уже существующий код, лицензированный в соответствии с GPL, и включить его в ваш пакет (также не существует ограничений
на повторное использование кода, не входящего в противоречие с его лицензией),</para>
</listitem>
<listitem>
<para>ваш код имеет copyright, что защищает ваши права как автора,</para>
</listitem>
<listitem>
<para>повторное использование кода другими авторами улучшает общий процесс разработки свободных программ.</para>
</listitem>
</itemizedlist>
</para>
</sect1>

<sect1 id="litsenzii-kde-i-qt">
<title>Лицензии KDE и Qt</title>

<para>Лицензирование Qt создавало много проблем разработчикам KDE, пока не вышла версия Qt 2.0, которая распространяется с новой QPL
лицензией. Компания Troll Tech, собственник и создатель Qt, поставляет Unix-версию библиотеки бесплатно, но с
ограничением, что вы не можете изменять поставляемый код и распространять его без их согласия.
По этой причине многие разработчики свободного программного обеспечения осуждают эту лицензию, поскольку она не абсолютно свободна, особенно для внесения изменений.
С другой стороны, библиотеки Qt предоставляют много возможностей, которые делают их очень привлекательными для коммерческих приложений:</para>

<para><itemizedlist>
<listitem>
<para>Покупая коммерческую лицензию, вы можете писать переносимые приложения для Unix и Windows платформ,</para>
</listitem>
<listitem>
<para>Предлагаемые классы и шаблоны - хорошее решение для быстрой и простой разработки приложений,</para>
</listitem>
<listitem>
<para>Вы можете вести разработку для Unix, не завися от лицензии GPL, если приобретаете коммерческую лицензию.</para>
</listitem>
</itemizedlist>
</para>

<para>Проект KDE, в свою очередь, использует библиотеку Qt как базу для разработки оболочки для Unix систем, а также
предоставляет дополнительные возможности к предлагаемым Qt. Разработчики могут реализовать их, используя библиотеки, распространяемые как библиотеки KDE.</para>

<para>Библиотеки KDE распространяются в соответствии с LGPL, GNU Library General Public License. </para>

<para>Что это значит для разработчиков приложений?</para>

<sect2 id="ne-kommercheskaia-razrabotka">
<title>Не коммерческая разработка</title>

<para>Для не коммерческой разработки, библиотеки Qt предоставляются бесплатно. Приложение может их использовать, не изменяя сами библиотеки;
разработчик должен также бесплатно предоставить исходный код приложения.</para>

<para>LGPL библиотек KDE позволяет использовать библиотеки KDE для не коммерческой разработки. Вы можете использовать библиотеки KDE
как вы того хотите, или как это необходимо вашему приложению.</para>
</sect2>

<sect2 id="kommercheskaia-razrabotka">
<title>Коммерческая разработка</title>

<para>Для коммерческой разработки, компания Troll Tech предлагает купить коммерческую лицензию. Это позволит использовать библиотеки Qt
для разработки так, как это требуется вашему приложению. Вы можете распространять ваше приложение в любой форме, как в бинарной, 
так и с исходным кодом, независимо от лицензии GPL.</para>

<para>При использовании библиотек KDE, вы должны посмотреть лицензию LGPL, которая ясно разрешает коммерческую разработку с использованием библиотек,
распространяемых в соответствии с LGPL. Вы должны только изучить условия лицензии, чтобы знать ограничения, могущие возникнуть при использовании библиотек KDE
как базы для коммерческой разработки приложений, основанных на KDE.</para>
</sect2>
</sect1>

<sect1 id="litsenziia-vashego-produkta">
<title>Лицензия вашего продукта</title>

<para>Таким образом, команда KDevelop, как авторы интегрированной среды разработки KDevelop, позволяют вам распространять любое приложение,
созданное с использованием KDevelop IDE, в соответствии с выбранной вами лицензией; только с учетом ограничений лицензий, которые возникают 
при использовании кода библиотек. Это:</para>

<para><itemizedlist>
<listitem>
<para>Для приложений Qt: Ограничения лицензии Qt, которые влияют на статус вашего дистрибутива, который может быть
не коммерческим (free) продуктом, или коммерческим.</para>
</listitem>
<listitem>
<para>Для приложений KDE: Ограничения лицензии Qt, определяющие статус вашего продукта, <emphasis>плюс</emphasis> ограничения
LGPL (GNU Library General Public License), поставляемой с копиями используемых библиотек.</para>
</listitem>
<listitem>
<para>для всех остальных исходных кодов вы можете выбирать лицензию.</para>
</listitem>
</itemizedlist>
</para>

<para>Таким образом, вы можете изменить лицензию по умолчанию, включаемую в любое сгенерированное KDevelop приложение, или базовое приложение,
по вашему выбору, только выполняя ограничения лицензий связанных библиотек.</para>

<para>Если у вас есть другие вопросы, связанные с лицензированием, обращайтесь к команде разработчиков KDevelop.</para>
</sect1>
</chapter>

<chapter id="ssylki">
<title>Ссылки</title>

<para>Руководство программиста KDevelop содержит информацию, полученную из различных источников в Internet и mail-листов,
таких как:</para>

<para><emphasis remap="bf">KDoc <indexterm remap="idx"><primary>KDoc</primary></indexterm> documentation:</emphasis> Sirtaj S. Kang <ulink url="mailto:taj@.kde.org">taj@.kde.org</ulink></para>

<para><emphasis remap="bf">KDE Developer's Center</emphasis> maintained by Sirtaj S. Kang <ulink url="mailto:taj@.kde.org">taj@.kde.org</ulink></para>

<para><emphasis remap="bf">KDE Internationalization:</emphasis> Matthias Elter <ulink url="mailto:me@kde.org">me@kde.org</ulink></para>

<para><emphasis remap="bf">KDebug documentation:</emphasis> Kalle Dalheimer <ulink url="mailto:kalle@kde.org">kalle@kde.org</ulink></para>

<para><emphasis remap="bf">The KDE File System Standard:</emphasis> Richard Moore <ulink url="mailto:rich@kde.org">rich@kde.org</ulink></para>

<para><emphasis remap="bf">KDE-Developer's mini-HOWTO:</emphasis> David Sweet <ulink url="mailto:dsweet@chaos.umd.edu">&lt;dsweet@chaos.umd.edu&gt;</ulink></para>

<para>Содержимое соответствующих глав сохраняет copyright его авторов.</para>
</chapter>

<chapter id="copyright">
<title>Copyright</title>

<para><screen>
KDevelop Copyright 1998,1999 The KDevelop Team.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
</screen>
</para>
</chapter>
<appendix id="dopolnitelnaia-informatsiia-0">
<title>Дополнительная информация</title>

<sect1 id="primer-makefile.am-dlia-dinamicheskoi-biblio">
<title>Пример Makefile.am для динамической библиотеки</title>

<para><screen># Example Makefile.am for a shared library.  It makes a library
#  called "example" as libexample.so.2.1.2
# This Makefile.am was taken from the kdelibs distribution and modified
#  to serve as an example.
#
# David Sweet
#
INCLUDES=  $(all_includes)

lib_LTLIBRARIES  = libexample.la

# Note:  If you specify a:b:c as the version in the next line,
#  the library that is made has version (a-c).c.b.  In this
#  example, the version is 2.1.2.
libexample_la_LDFLAGS = -version-info 3:2:1 $(all_libraries)

include_HEADERS = header1.h header2.h\
                  header3.h

# Which headers shouldn't be installed when a   make install  is done?
noinst_HEADERS = version.h

libexample_la_SOURCES = code1.cpp code2.cpp
                        code3.cpp

#  USE_AUTOMOC is great.  This takes care of all of your  moc'ing
#   dependencies.
#  (You still need to include, for example, header1.moc in code1.cpp.)
libexample_la_METASOURCES = USE_AUTOMOC
</screen>
</para>
</sect1>
  </appendix>
<![ %addindex; [ &docindex; ]]>
</book>
<!--
Local Variables:
mode: sgml
sgml-omittag: nil
sgml-shorttag: t
sgml-general-insert-case: lower
End:
-->
