<?xml version="1.0" ?>
<!DOCTYPE book PUBLIC "-//KDE//DTD DocBook XML V4.2-Based Variant V1.1//EN" "dtd/kdex.dtd" [
  <!ENTITY ksplash "KSplash">
  <!ENTITY package "kdebase">
  <!ENTITY % addindex "IGNORE">
  <!ENTITY % Danish "INCLUDE">
]>

<book lang="&language;">

<bookinfo>
<title
>&ksplash;-håndbogen</title>

<authorgroup>
<author
>&Teemu.Rytilahti; &Teemu.Rytilahti.mail; </author>

<othercredit role="developer"
>&Brian.C.Ledbetter; &Brian.C.Ledbetter.mail; </othercredit>

<othercredit role="developer"
>&Ravikiran.Rajagopal; &Ravikiran.Rajagopal.mail; </othercredit>

&erik.kjaer.pedersen.role; 

</authorgroup>

<copyright>
<year
>2003</year>
<holder
>Teemu Rytilahti</holder>
</copyright>
<copyright>
<year
>2003-04</year>
<holder
>Ravikiran Rajagopal</holder>
</copyright>
<legalnotice
>&FDLNotice;</legalnotice>

<date
>2003-01-10</date>
<releaseinfo
>1.01.00</releaseinfo>

<abstract>
<para
>&ksplash; er en opstartsskærm der viser fremskridt for et program der er ved at blive indlæst.</para>
</abstract>

<keywordset>
<keyword
>KDE</keyword>
<keyword
>kdebase</keyword>
<keyword
>ksplash</keyword>
<keyword
>ksplashml</keyword>
<keyword
>opstartsskærm</keyword>
<keyword
>øjenlækkerier</keyword>
</keywordset>

</bookinfo>

<chapter id="introduction">
<title
>Indledning</title>

<para
>&ksplash; er en opstartsskærm der viser fremskridt for et program der er ved at blive indlæst. Rapportér venligst om problemer eller ønsker om nye egenskaber til &kde;'s e-mail-lister. &ksplash;'s hovedegenskaber er: </para>
<simplelist>
<member
>Kan påvirkes af temaer</member>
<member
>Bruger plugin til fuldstændig brugerinderetning</member>
<member
>Kan bruges af et vilkårligt program der bruger DCOP</member>
</simplelist>

<para
>Denne håndbog vil vise dig hvordan man laver temaer til brug med plugin der allerede findes. Hvis ingen af de tilgængelige plugin tilfredsstiller din smag, kan du lære hvordan du brugerindstiller &ksplash;'s udseende fuldstændigt ved at  skrive et plugin i C++. </para>
</chapter>

<chapter id="using-themes">
<title
>brug af temaer</title>

<para
>For at bruge temaer fra <ulink url="http://www.kde-look.org"
>KDE-Look</ulink
>, pakkes de ud til <filename
>~/.kde/share/apps/ksplash/Themes/</filename
> for en enkelt bruger, eller til <filename
>$<envar
>KDEDIR</envar
>/share/apps/ksplash/Themes/</filename
> for at gøre dem tilgængelige for alle brugerne på dit system.</para>

<para
> Du kan også bruge <guilabel
>Opstartsskærm</guilabel
>-modulet under <guilabel
>Udseende</guilabel
> i &kde;'s kontrolcenter til at gøre dette automatisk.</para>

<sect1 id="using-kcontrol-module">
<title
>Ved brug af &kcontrol;-modulet</title>

<para
>Dette module tillader dig at installere, teste og fjerne &ksplash;-temaer.</para>

<para
>Nede langs siden af modulet er en liste af de for øjeblikket tilgængelige &ksplash;-temaer. Når du vælger en, vil en forhåndsvisning blive vist i hoveddelen af vinduet. Når du har valgt den du ønsker at bruge, tryk så på <guibutton
>O.k.</guibutton
> eller <guibutton
>Anvend</guibutton
>. Tryk på <guibutton
>Annullér</guibutton
> for at afslutte modulet uden at lave ændringer, og <guibutton
>Standard</guibutton
> for at genoprette systemets standard-opstartsskærm.</para>

<para
>Fro at installere nye moduler, trykkes på <guibutton
>Tilføj...</guibutton
>, og find temaet på din computer. Du behøver ikke at pakke temafiler ud, du kan blot vælge den komprimerede temafil. Installering af et tema gør det ikke til det tema der bruges før du vælger det på listen og trykker enten på <guibutton
>O.k.</guibutton
> eller <guibutton
>Anvend</guibutton
>.</para>

<para
>Selvom du kan se en forhåndsvisning af opstartsskærmen, vil du måske gerne se hvordan det ser ud i rigtigt brug, for eksempel for at se hvordan animeringen ser ud. Du kan teste temaer ved at vælge dem på listen og klikke på <guibutton
>Test</guibutton
>-knappen.</para>

<para
>Du kan også fjerne de temaer du ikke længere ønsker at bruge, ved at vælge dem og trykke på <guibutton
>Fjern</guibutton
>-knappen. bemærk at din brugerkonto måske ikke har lov til at fjerne temaer der er installeret systemomfattende. Det  anbefales også at du ikke afinstallerer <guilabel
>Standard</guilabel
>-opstartskærmen.</para>

</sect1>

</chapter>

<chapter id="themes">
<title
>Hvordan man laver temaer for &ksplash;</title>
<sect1 id="themes-general">
<title
>Generelt</title>
<para
>Det er nemt at lave dine egne temaer for &ksplash;. Efter du er færdig med dine temaer kan du sende dem til <ulink url="http://www.kde-look.org"
>KDE-Look</ulink
> så andre kan bruge dem.</para>

<sect2 id="theme-syntax">
<title
>Identificering af dit tema</title>

<para
>Lad os lave et tema der hedder <literal
>MitHeltEget</literal
>. For at temaet skal blive genkendt af &ksplash;, skal det gemmes i en mappe der hedder <filename class="directory"
>MitHelEget</filename
> under <filename class="directory"
>~/.kde/apps/ksplash/Themes/</filename
>. Det skal have en fil der hedder <filename
>Theme.rc</filename
>, der indeholder opsætningen af temaet. Du kan angive mange specielle ting i temaet, ændre den plugin-maskine der bruges, og så videre. Du behøver ikke at bruge alle de mulige indstillinger; sædvanligvis har indstillingerne en acceptabel standardværdi. Den basale syntaks for indgange i <filename
>Theme.rc</filename
>-filen er <literal
>[option] = [value]</literal
> Du kan finde definitionerne på de forskellige muligheder i de følgende afsnit.</para>

<example>
<title
>Simpel <filename
>Theme.rc</filename
> fil</title>
<programlisting
>[KSplash Theme: MitHeltEget]
Name = MitHeltEget
Description = Et lækkert tema der bruger XpLike-maskinen
Version = 1.0
Author = Rigtigt navn &lt;rigtigpost@post.dk&gt;
## Brug XpLike-maskinen til dette tema.
Engine = XpLike
Show Icon = false
Welcome Text = Indlæser KDE
</programlisting>
</example>

<para
>Efter at have angivet navnet, beskrivelsen og forfatteren for temaet, skal du først vælge en tema-maskine (også kendt som et plugin). Så kan du brugerindstille forskellige egenskaber af tema-maskinen ved at tilknytte nøgle-værdi par som i eksempel-filen ovenfor.</para>

<para
>Det er vigtigt at navnet på mappen hvori temafilerne opbevares (<filename class="directory"
>~/.kde/apps/ksplash/Themes/MitHeltEget</filename
> i vores tilfælde) og identifikatoren (<literal
>[KSplash Tema: MitHeltEget] </literal
> i vores tilfælde) for temaet i <filename
>Theme.rc</filename
>-filen er identiske.Ellers vil &ksplash; ikke genkende temaet. </para>

</sect2>

<sect2 id="theme-files">
<title
>Baggrundsfiler</title>

<para
>Når &ksplash; starter, prøver den at finde et baggrundsbillede der passer til skærmens opløsning hvis tema-maskinen bruger et. Baggrundsbilledfilen skan navngives i følgende: <filename
>Background-<replaceable
>WWWxHHH</replaceable
>.png</filename
>.</para>

<para
>For eksempel vil du måske bruge en fil der hedder <filename
>Background-1024x768</filename
>. Hvis baggrundsbilledet for din skærms opløsning ikke kan findes, prøver den at ændre størrelse på den originale <filename
>Background.png</filename
> eller filen angivet i <filename
>Theme.rc</filename
> til at passe med den nuværende opløsning. Ændring af størrelse uden-videre vil selvfølgelig tage et stykke tid, så du bør sørge for baggrundsbilleder i det mindste i følgende størrelser: 1280x1024, 1024x768 og 800x600.</para>
</sect2>
</sect1>

<sect1 id="theme-engines">
<title
>Valgmuligheder for tema-maskiner</title>

<sect2 id="standard-themes">
<title
>Standard-tema</title>
<table>
<title
>Valgmuligheder for standard-tema</title>
<tgroup cols="3">
<tbody>
<row>
<entry
>Navn</entry>
<entry
>Argument</entry>
<entry
>Forklaring</entry>
</row>
<!-- Statusbar -->
<row>
<entry
>Placering af statuslinje</entry>
<entry
>[top/bund]</entry>
<entry
>Skifter positionen af statuslinjen på skærmen. Standard er for neden.</entry>
</row>
<row>
<entry
>Synlig statuslinje</entry>
<entry
>[sand/falsk]</entry>
<entry
>Indikerer om statuslinjen skal vises. Standard er sand.</entry>
</row>
<row>
<entry
>Fremgang synlig</entry>
<entry
>[sand/falsk]</entry>
<entry
>Indikerer om indlæsningsfremgang skal vises. Standard er sand.</entry>
</row>
<!-- Fonts -->
<row>
<entry
>Skrifttype for statuslinje</entry>
<entry
>[skrifttypenavn]</entry>
<entry
>Den skrifttype der bruges i statuslinjen. Standard er Helvetica.</entry>
</row>
<row>
<entry
>Skrifttypestørrelse for statuslinje</entry>
<entry
>[størrelse]</entry>
<entry
>Skrifttypens størrelse på statuslinjen. Standard er 16.</entry>
</row>
<row>
<entry
>Fed skrifttype på statuslinje</entry>
<entry
>[sand/falsk]</entry>
<entry
>Indikerer om skrifttypen på statuslinjen skal være fed. Standard er sand.</entry>
</row>
<row>
<entry
>Kursiv skrifttype for statuslinje</entry>
<entry
>[sand/falsk]</entry>
<entry
>Indikere om statuslinjen skrifttype skal være kursiv. Standard er falsk.</entry>
</row>
<!-- Misc. things -->
<row>
<entry
>Forgrund for statuslinje</entry>
<entry
>[farve]</entry>
<entry
>Forgrundsfarven på statuslinjen. Standard er hvid.</entry>
</row>
<row>
<entry
>Baggrund for statuslinje</entry>
<entry
>[farve]</entry>
<entry
>Baggrundsfarve for statuslinjen. Standard er sort.</entry>
</row>
<row>
<entry
>Ikon for statuslinje</entry>
<entry
>[sand/falsk]</entry>
<entry
>Indikerer om statuslinjen skal have en ikon.</entry>
</row>
<row>
<entry
>Ikoner synlige</entry>
<entry
>[sand/falsk]</entry>
<entry
>Indikerer om ikoner skal være synlige. Standard er sand.</entry>
</row>
<row>
<entry
>Ikoner hopper</entry>
<entry
>[sand/falsk]</entry>
<entry
>Indikerer om ikoner skal hoppe. Standard er sand.</entry>
</row>
<row>
<entry
>Ikonplacering</entry>
<entry
>[0-3,10-13]</entry>
<entry
>Position hvor ikonerne vises. Standard er for neden til venstre.</entry>
</row>
<row>
<entry
>Opstartskærm</entry>
<entry
>[navn]</entry>
<entry
>Ændrer det billede der vises i opstartsskærmen.</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>

<sect2 id="redmond-themes">
<title
>Redmond tema</title>
<table>
<title
>Indstillinger for Redmond tema</title>
<tgroup cols="3">
<tbody>
<row>
<entry
>Navn</entry>
<entry
>Argument</entry>
<entry
>Forklaring</entry>
</row>
<!-- Main elements -->
<row>
<entry
>Baggrundsbillede</entry>
<entry
>[filnavn]</entry>
<entry
>Brugerdefineret baggrundsbillede der skal bruges.</entry>
</row>
<row>
<entry
>Bruger-ikon</entry>
<entry
>[Ikonnavn]</entry>
<entry
>Navn på standard-ikon at vise til brugeren. Standard er <constant
>kør</constant
>.</entry>
</row>
<row>
<entry
>Velkomsttekst</entry>
<entry
>[tekst]</entry>
<entry
>Tekst der vises i opstartsskærmen. Standard er "Velkommen".</entry>
</row>
<row>
<entry
>Tekst for brugernavn</entry>
<entry
>[tekst]</entry>
<entry
>Tekst der vises i stedet for brugerens rigtige navn.</entry>
</row>
<!-- Positioning elements -->
<row>
<entry
>Placering af velkomsttekst</entry>
<entry
>[x,y]</entry>
<entry
>Position på skærmen hvor velkomstteksten vises.</entry>
</row>
<row>
<entry
>Tekst-position for brugernavn</entry>
<entry
>[x,y]</entry>
<entry
>Position på skærmen hvor brugernavnet vises.</entry>
</row>
<row>
<entry
>Placering af handlingstekst</entry>
<entry
>[x,y]</entry>
<entry
>Position på skærmen hvor den nuværende handling vises.</entry>
</row>
<row>
<entry
>Ikonplacering</entry>
<entry
>[x,y]</entry>
<entry
>Position på skærmen hvor brugerikonen vises.</entry>
</row>
<!-- Show to show.. -->
<row>
<entry
>Vis velkomsttekst</entry>
<entry
>[sand/falsk]</entry>
<entry
>Slår visning af velkomsttekst til og fra. Standard er sand.</entry>
</row>
<row>
<entry
>Vis velkomstskygge</entry>
<entry
>[sand/falsk]</entry>
<entry
>Slår visning af velkomsttekstens skygge til og fra. Standard er sand.</entry>
</row>
<row>
<entry
>Vis brugernavn</entry>
<entry
>[sand/falsk]</entry>
<entry
>Slår visning af brugernavn til og fra. Standard er sand.</entry>
</row>
<row>
<entry
>Vis handling</entry>
<entry
>[sand/falsk]</entry>
<entry
>Slår visning af den handling der udføres lige nu til og fra. Standard er sand.</entry>
</row>
<row>
<entry
>Vis ikon</entry>
<entry
>[sand/falsk]</entry>
<entry
>Indikerer om ikon skal vises. Standard er sand</entry>
</row>
<row>
<entry
>Brug KDM's bruger-ikon</entry>
<entry
>[sand/falsk]</entry>
<entry
>Vis brugerens login-ikon. Standard er sand.</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>

<sect2 id="macx-themes">
<title
>MacX tema</title>
<table>
<title
>Indstillinger for MacX tema</title>
<tgroup cols="3">
<tbody>
<row>
<entry
>Navn</entry>
<entry
>Argument</entry>
<entry
>Forklaring</entry>
</row>
<row>
<entry
>Minimum ikonstørrelse</entry>
<entry
>[størrelse]</entry>
<entry
>Tilknyt en minimumstørrelse for ikoner. Standard er 16.</entry>
</row>
<row>
<entry
>Maksimal ikonstørrelse</entry>
<entry
>[størrelse]</entry>
<entry
>Tilknyt maksimum størrelse for ikoner. Standard er 64.</entry>
</row>
<row>
<entry
>Optimeret ikonvisning</entry>
<entry
>[sand/falsk]</entry>
<entry
>Optimér ikonvisning. Standard er sand.</entry>
</row>
<row>
<entry
>Synlig fremgangslinje</entry>
<entry
>[sand/falsk]</entry>
<entry
>Standard er sand.</entry>
</row>
<row>
<entry
>Placering af fremgangslinje</entry>
<entry
>[top/bund]</entry>
<entry
>Skifter mellem om statuslinjen skal være foroven eller forneden. Standard er forneden.</entry>
</row>
<row>
<entry
>Ikoner hopper</entry>
<entry
>[sand/falsk]</entry>
<entry
>Indikerer om ikoner skal hoppe. Standard er falsk.</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>

<sect2 id="mac-classic-themes">
<title
>MacClassic tema</title>
<table>
<title
>Indstillinger af MacClassic tema</title>
<tgroup cols="3">
<tbody>
<row>
<entry
>Navn</entry>
<entry
>Argument</entry>
<entry
>Forklaring</entry>
</row>
<row>
<entry
>Ikonplacering</entry>
<entry
>[0-3,10-13]</entry>
<entry
>Placering af ikonerne på skærmen. Standard er forneden til venstre.</entry>
</row>
<row>
<entry
>Ikoner hopper</entry>
<entry
>[sand/falsk]</entry>
<entry
>Indikerer om ikoner skal hoppe. Standard er falsk.</entry>
</row>
<row>
<entry
>Ikoner synlige</entry>
<entry
>[sand/falsk]</entry>
<entry
>Indikerer om ikoner skal være synlige. Standard er sand.</entry>
</row>
<row>
<entry
>Opstartskærm</entry>
<entry
>[navn]</entry>
<entry
>Ændrer det billede der vises i opstartsskærmen.</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>

<sect2 id="themes-2k">
<title
>2k tema</title>
<table>
<title
>Indstillinger af 2k tema</title>
<tgroup cols="3">
<tbody>
<row>
<entry
>Navn</entry>
<entry
>Argument</entry>
<entry
>Forklaring</entry>
</row>
<row>
<entry
>Baggrundsfarve for titel</entry>
<entry
>[farve]</entry>
<entry
>Baggrundsfarven for titlen. Standard er mørkeblå.</entry>
</row>
<row>
<entry
>Forgrundsfarve for titel</entry>
<entry
>[farve]</entry>
<entry
>Forgrundsfarve for titlen. Standard er hvid.</entry>
</row>
<row>
<entry
>Tekstfarve for status</entry>
<entry
>[farve]</entry>
<entry
>Farven på statustekster. Standard er den samme som titelens baggrundsfarve.</entry>
</row>
<row>
<entry
>Rotator-farve 1</entry>
<entry
>[farve]</entry>
<entry
>Definerer farven på rotator 1. Standard er mørkeblå.</entry>
</row>
<row>
<entry
>Rotator-farve 1</entry>
<entry
>[farve]</entry>
<entry
>Definerer farven på rotator 1. Standard er cyan.</entry>
</row>
<row>
<entry
>Rotatorhastighed</entry>
<entry
>[værdi]</entry>
<entry
>Definerer rotatorens hastighed. Standard er 30.</entry>
</row>
<row>
<entry
>Vinduestitel</entry>
<entry
>[tekst]</entry>
<entry
>Angiver titelens tekst i vinduet.</entry>
</row>
<row>
<entry
>Logo-fil</entry>
<entry
>[filnavn]</entry>
<entry
>Definerer det logo der bruges.</entry>
</row>
</tbody>
</tgroup>
</table>
</sect2>
</sect1>
</chapter>

<chapter id="from-other-applications">
<title
>Brug af &ksplash; indefra dit eget program</title>

<para
>I dette kapitel beskriver en simpel metode at bruge &ksplash; som opstartskærm for dit &kde;-program. Hvis du ikke udvikler programmer for &kde;, kan du springe over dette kapitel.</para>

<sect1 id="basic-other-reqs">
<title
>Basale krav</title>

<para
>Dit &kde;-program skal være klar over &DCOP;. &DCOP; er den teknik &kde; bruger til at kommunikere mellem programmer. Hvis du bruger <ulink url="http://developer.kde.org"
>&kde; application framework</ulink
>, sker dette automatisk. For information om &DCOP; og relaterede &kde; teknologier, besøg venligst <ulink url="http://developer.kde.org"
>&kde; developers' corner</ulink
>.</para>
</sect1>

<sect1 id="other-using">
<title
>Start af &ksplash;</title>

<para
>Før dit program starter sit beregningsintensive arbejde, eller før det begynder med at indlæse plugin, &etc;, startes &ksplash; som følger:</para>

<programlisting
>DCOPClient *c = kapp-&gt;dcopClient();
QString error;
QCString KSplashName;
int pid = 0;
QStringList args;
args &lt;&lt; "--theme=MitEgetTema" &lt;&lt; "--managed";
if (kapp-&gt;startServiceByDesktopName("ksplash", args, &amp;error, &amp;KSplashName, &amp;pid))
{
  KMessageBox::sorry(0, error, "Kan ikke starte KSplash");
  // Noget fejlbehandling her.
}
</programlisting>

<para
>Vi vil antage at der kun er én udgave af &ksplash; der kører. Andre tilfælde er en smule mere komplicerede. Se venligst &DCOP;-dokumentationen for yderligere detaljer.</para>
</sect1>

<sect1 id="show-messages">
<title
>Viser beskeder</title>

<para
>Før du viser nogen beskeder, skal du indstille det antal skridt du vil vise. For eksempel bruger &kde;'s opstartsprocedure 7 skridt.</para>

<programlisting
>QByteArray data;
    QDataStream arg(data,IO_WriteOnly);
    arg &lt;&lt; someNumber;
    if (!(c-&gt;send(KSplashName, "KSplashIface", "setStartupItemCount(int)", data))
      // Noget fejlbehandling her.
</programlisting>

<para
>Når du ønsker at vise en besked med eller uden ikon bruges</para>

<programlisting
>arg &lt;&lt; QString("iconName") &lt;&lt; QString("programName") &lt;&lt; QString("Some description");
    if (!(c-&gt;send(KSplashName, "KSplashIface", "programStarted(QString,QString,QString)", data))
    {
      // Noget fejlbehandling her.
    }
</programlisting>

<para
>Hver gang du kalder <constant
>programStarted</constant
>, forøges antallet af færdige skridt. Når dit program er færdig med sin opstart, så gør følgende for at få opstartskærmen til at gå væk:</para>

<programlisting
>if (!(c-&gt;send(KSplashName, "KSplashIface", "startupComplete()", data))
    {
      // Noget fejlbehandling her.
    }
</programlisting>

<para
>Det er det hele! Du behøver ikke andet for kunne udnytte alt hvad &ksplash; har at tilbyde.</para>

</sect1>
</chapter>

<!-- FIXME: Better to leave this out until it's written, or the translators -->
<!-- will have to still translate it ... -->

<chapter id="wrplugins">
<title
>Skriv nye &ksplash;-plugin</title>

<para
>Det er ikke svært at skrive et nyt plugin for &ksplash;. I dette kapitel vil vi skrive et simpelt plugin der vil emulere opstartsskærmen for et velkendt operativsystem. Denne øvelse antager at du kender til basal C++, og en smule om KDE/Qt programmering.</para>

<sect1 id="basic-requirements">
<title
>Basale krav</title>
<para
>Vi vil lave et plugin der hedder <literal
>2k</literal
>. Navnet på et plugin bruges forskellige steder, og det er vigtigt at du er konsistent i dets brug så dit plugin bliver genkendt af &ksplash;. &ksplash; plugin er rent faktisk dynamisk indlæsbare biblioteker med følgende navnekonvention: </para>
<simplelist>
<member
>Biblioteket skal hedde <filename
>ksplash+temanavnmedsmaabogstaver</filename
>. For vore tema, vil et være <filename
>ksplash2k</filename
>.</member>
<member
>Det skal have en tilsvarende desktop-fil som hedder  <filename
>ksplash+temanavnmedsmaabogstaver.desktop</filename
>. For vores tema vil det være <filename
>ksplash2k.desktop</filename
>. </member>
<member
>Endelig skal objektet der returneres af biblioteket være en klasse som hedder <literal
>Theme+temanavnet</literal
>. For vores eksempel vil det være <literal
>Theme2k</literal
>.</member>
</simplelist>
<para
>Du skal ikke bekymre dig om du forstår alt dette. Vi vil  betragte hvert af punkterne i detalje senere. Den anden meget vigtige detalje er at plugin-klassen skal være afledt fra <literal
>ThemeEngine</literal
>. </para>
</sect1>
<sect1 id="skeleton">
<title
>Bygning af skelet-ramme</title>
<para
>Vi vil bruge &kde;'s program-ramme som vil tage sig af at bygge dit plugin og vil sørge for uafhængighed af platform uden at vi skal gøre noget. For at gøre dette sørg for at du har <filename
>kdesdk</filename
>-pakken installeret. Kør kommandoen <literal
>kapptemplate</literal
> for at producere et program der hedder "2k". Det vil lave en mappe på topniveau som indeholder generiske filer såsom AUTHORS, &etc;. Vi er mest interesseret i undermappen der hedder <filename class="directory"
>2k</filename
>. Gå ind i den undermappe og slet alle filerne der. Nu har vi det krævede skelet. </para>
<para
>Næste skridt er at lave en <filename
>.desktop</filename
>-fil som, når den er installeret, vil fortælle &ksplash; at vores plugin er tilstede. Konsistent med navngivningkonventionerne lagt ud i <link linkend="basic-requirements"
>det foregående afsnit</link
>, laves en fil der hedder <filename
>ksplash2k.desktop</filename
> i den mappe. Den skal indeholde følgende linjer: </para>
<programlisting
><literal>
[Desktop Entry]
Encoding=UTF-8
Type=Service
Comment=KSplash Plugin
Name=KSplash2k
ServiceTypes=KSplash/Plugin
X-KDE-Library=ksplash2k
X-KSplash-Default=true
X-KSplash-PluginName=2k
X-KSplash-ObjectName=Theme2k
</literal
>
</programlisting>
<para
><literal
>Encoding</literal
>, <literal
>Type</literal
>, <literal
>Comment</literal
> og <literal
>ServiceTypes</literal
> er det samme for alle plugin. Navnet på dit plugin og biblioteksnavnet følger de konventioner ve bemærkede tidligere. Indgangen <literal
>X-KSplash-Default</literal
> tager en boolesk værdi som afgør om det vises som standard i kontrolpanelets indstillingsmodul. Undtagen i meget sjældne tilfælde skal det være <constant
>true</constant
>. </para>
</sect1>
<sect1 id="headerfile">
<title
>Deklaration af plugin-klasse</title>
<para
>Nu da vi er færdige med det indledende arbejde, lad os begynde med den morsomme del - at lave en klasse der vil sørge for den opførsel vi ønsker. Mens vi er fire til at få denne klasse til at gøre næsten hvadsomhelst vi ønsker den skal gøre, er der nogle få begrænsninger.</para>
<orderedlist>
<listitem
><para
>Plugin-klasser skal arve <constant
>ThemeEngine</constant
>-klassen.</para
></listitem>
<listitem
><para
>Plugin-klasser skal navngives efter reglen: <classname
>Tema+PluginNavn</classname
>.</para
></listitem>
<listitem
><para
>Plugin-klasser skal sørge for en <literal
>statisk</literal
> funktion der hedder <function
>names</function
> der returnerer en liste af navne ved hvilke de kan startes.</para
></listitem>
<listitem
><para
>Hvis dit plugin kan indstilles i kontrolcenter-modulet, skal det sørge for en <literal
>ThemeEngineConfig</literal
>-baseret klasse for indstillingen.</para
></listitem>
<listitem
><para
>Plugin-klasser skal gå forud for mindst en af de virtuelle funktioner <function
>slotSetText</function
>, <function
>slotSetPixmap</function
>, <function
>slotUpdateProgress</function
> og <function
>slotUpdateSteps</function
> for at være brugbare.</para
></listitem>
<listitem
><para
>Konstruktøren skal være på formen <literal
>ThemeEngine( QWidget *parent, const char *name, const QStringList &amp;args )</literal
> så den kan bruges med <classname
>KGenericFactory</classname
>.</para
></listitem>
</orderedlist>
<para
>Det sidste krav synes måske kompliceret, men, som vi skal se senere, du kan sædvanligvis ignorere det ved at tilføje en enkelt linje til din kildefil.</para>
</sect1>
<sect1 id="headercode">
<title
>Kode for header-filen</title>
<para
>Givet disse begrænsninger vil vi nu se at header-filen <filename
>theme2k.h</filename
> ser sådan her ud:</para>
<example>
<title
>Visning af <filename
>theme2k.h</filename
></title>
<programlisting
>#ifndef __THEME2K_H__
#define __THEME2K_H__

#include &lt;qlabel.h&gt;
#include &lt;qwidget.h&gt;

#include &lt;kdialogbase.h&gt;
#include &lt;kpixmap.h&gt;
#include &lt;ksplash/themeengine.h&gt;

class RotWidget;

class Cfg2k: public ThemeEngineConfig
{
  Q_OBJECT
public:
  Cfg2k( KConfig * );
};

class ObjKsTheme;
class Theme2k: public ThemeEngine
{
  Q_OBJECT
public:
  Theme2k( QWidget *, const char *, const QStringList&amp; );

  inline const QString name()
  {
    return( QString("KSplash2k") );
  }
  inline const KDialogBase *config( KConfig *kc )
  {
    return new Cfg2k( kc );
  }
  static QStringList names()
  {
    QStringList Names;
    Names &lt;&lt; "KSplash2k";
    Names &lt;&lt; "ks2k";
    Names &lt;&lt; "2k";
    Names &lt;&lt; "2000";
    return( Names );
  };

public slots:
  inline void slotSetText( const QString&amp; s )
  {
    if( mText &amp;&amp; mText-&gt;text() != s ) mText-&gt;setText( s );
  };

private:
  void initUi();
  void readSettings();

  QLabel *mText;
  RotWidget *mRotator;
  QColor mTBgColor, mTFgColor, mRotColor1, mRotColor2, mStatusColor;
  int mRotSpeed;
  QString mWndTitle, mLogoFile;
};

#endif
</programlisting>
</example>
<para
>Lad os analysere ovenstående. <classname
>Theme2k</classname
>-klassen tilfredsstiller navnekonventionerne, og er arvet fra <classname
>ThemeEngine</classname
>. Den sørger for en  <methodname
>Theme2k::names()</methodname
>, og har en konstruktør der tager de krævede parametre: <function
>Theme2k( QWidget *, const char *, const QStringList&amp; );</function
> og sørger også for en simpel <methodname
>Theme2k::slotSetText()</methodname
> metode. Indtil videre bekymrer vi os ikke om <classname
>RotWidget</classname
>-klassen. Det er en lille kontrol der sørger for nogle øjenlækkerier for brugeren. Vores plugin er meget simpelt og viser ikke nogen ikoner og har ingen fremgangslinje. Hvis du gerne vil vise ikoner, så sæt <function
>slotSetPixmap</function
>-funktionen ud af kraft. Lignende funktioner eksisterer til at sætte fremgangslinjens område (<function
>slotUpdateSteps</function
>) og til at forøge (<function
>slotUpdateProgress</function
>) det nuværende skridt. </para>
</sect1>
<sect1 id="Implementation">
<title
>Implementation af plugin</title>
<para
>Vi vil kun undersøge de relevante dele af implementationen. For en liste af hele implementationen, kig venligst i appendiks. Det første vi vil gøre er at bibliotekskravene til en side:</para>
<example>
<title
>Bibliotekskrav</title>
<programlisting
>K_EXPORT_COMPONENT_FACTORY( ksplash2k, KGenericFactory&lt;Theme2k&gt; );
</programlisting>
</example>
<para
>Makroen <constant
>K_EXPORT_COMPONENT_FACTORY</constant
> erklæres i <filename
>kgenericfactory.h</filename
>. Videre til konstruktøren! Da dette er et meget simpelt plugin, er konstruktøren temmelig ligetil.</para>
<example>
<title
>Plugin-konstruktør</title>
<programlisting
>Theme2k::Theme2k( QWidget *parent, const char *name, const QStringList &amp;args  )
    :ThemeEngine( parent, name, args )
{
  readSettings();
  initUi();
}
</programlisting>
</example>
<para
>Metoden <function
>readSettings()</function
> illustrerer den rigtige måde at opnå din temaopsætning. (Du ønsker at folk skal bruge dit plugin i deres temaer, ikke sandt?)</para>
<example>
<title
>Opnået temaopsætning</title>
<programlisting
>void Theme2k::readSettings()
{
  if( !mTheme )
    return;

  KConfig *cfg = mTheme-&gt;themeConfig();
  if( !cfg )
    return;

  cfg-&gt;setGroup( QString("KSplash Theme: %1").arg(mTheme-&gt;theme()) );

  QColor DefaultTBgColor( Qt::darkBlue );
  QColor DefaultTFgColor( Qt::white );

  mTBgColor = cfg-&gt;readColorEntry( "Title Background Color", &amp;DefaultTBgColor );
  mTFgColor = cfg-&gt;readColorEntry( "Title Foreground Color", &amp;DefaultTFgColor );
  mStatusColor = cfg-&gt;readColorEntry("Status Text Color", &amp;mTBgColor );

  QColor DefaultRot1( Qt::darkBlue );
  QColor DefaultRot2( Qt::cyan );
  mRotColor1 = cfg-&gt;readColorEntry( "Rotator Color 1", &amp;DefaultRot1 );
  mRotColor2 = cfg-&gt;readColorEntry( "Rotator Color 2", &amp;DefaultRot2 );

  mRotSpeed = cfg-&gt;readNumEntry( "Rotator Speed", 30 );
  mWndTitle = cfg-&gt;readEntry( "Window Title", i18n("Please wait...") );
  mLogoFile = cfg-&gt;readEntry( "Logo File", QString::null );
}
</programlisting>
</example>
<para
>Da vi kan lide vore brugere, sørger vi for rimelige standardværdier for parametre der ikke er tilstede i temafilen. Bemærk at vi altid skal sætte vores gruppe til "KSplash Theme: themename" for at forblive kompatible med fremtidige tema-specifikationer. <function
>initUI()</function
>-metoden er ikke særlig interessant, da den blot opbygger kontrollerne. Se venligst appendiks for detaljer. </para>
</sect1>
<sect1 id="compilingfile">
<title
>Kompilering af plugin</title>
<para
>Da vi besluttede os for at bruge &kde;'s rammer til at kompilere vores plugin, må vi lave en <filename
>Makefile.am</filename
>. Den skal se sådan her ud:</para>
<example>
<title
>Visning af <filename
>Makefile.am</filename
></title>
<programlisting
>INCLUDES = $(all_includes)

kde_module_LTLIBRARIES = ksplash2k.la

ksplash2k_la_SOURCES = theme2k.cpp rotwidget.cpp
ksplash2k_la_LDFLAGS = $(all_libraries) $(KDE_RPATH)
ksplash2k_la_LIBADD = $(LIB_KDEUI) -lksplashthemes

METASOURCES = AUTO

noinst_HEADERS        = theme2k.h rotwidget.h

servicesdir = $(kde_servicesdir)
services_DATA = ksplash2k.desktop

themedir = $(kde_datadir)/ksplash/Themes/2k
theme_DATA = Theme.rc Preview.png
</programlisting>
</example>
<para
>For yderligere oplysninger om at skrive <filename
>Makefile.am</filename
>-filer for &kde;, se venligst &kde;-udviklernes' <ulink url="http://developer.kde.org/documentation/other/makefile_am_howto.html"
>netside</ulink
>. Det eneste der skal bemærkes er at vi sørger for et standardtema baseret på dette plugin, og vi sørger for et forhåndsbillede for det. Som en venlighed  overfor dine brugere, bør du sørge for et eksempel på en <filename
>Theme.rc</filename
>-fil der illustrerer brugen af de forskellige tilvalg.</para>
</sect1>
</chapter>

<chapter id="faq">
<title
>Spørgsmål og svar</title>
&reporting.bugs; &updating.documentation; <qandaset id="faqlist">
<qandaentry>
<question>
<para
>Jeg kan ikke finde nogen temaer der virker i &ksplash;. Hvorfor er det?</para>
</question>
<answer>
<para
>Du har formodentlig ikke de rigtige plugin for temaet. Plugin er i <literal
>kde-artwork</literal
> pakken. Hent den og installér den, og prøv så igen.</para>
</answer>
</qandaentry>
<qandaentry>
<question>
<para
>Hvad er filen <filename
>Theme.rc</filename
> og hvordan laver jeg én?</para>
</question>
<answer>
<para
><filename
>Theme.rc</filename
> er filen hvor du kan specificere temaets opsætning. For yderligere oplysninger kig i <link linkend="themes"
>Hvordan laver jeg temaer for &ksplash;</link
>. </para>
</answer>
</qandaentry>
</qandaset>
</chapter>

<chapter id="credits">
<title
>Medvirkende og licens</title>

<para
>&ksplash;</para>

<para
>Program ophavsret &copy; 2003 &Ravikiran.Rajagopal; &Ravikiran.Rajagopal.mail;</para>

<itemizedlist>
<title
>Bidragydere</title>
<listitem
><para
>&Brian.C.Ledbetter; &Brian.C.Ledbetter.mail;</para>
</listitem>
</itemizedlist>

<para
>Dokumentation ophavsret &copy; 2003 &Teemu.Rytilahti; &Teemu.Rytilahti.mail;</para>
&underFDL; &underGPL; </chapter>

<appendix id="installation">
<title
>Installation</title>

<sect1 id="requirements">
<title
>Krav</title>

<para
>For at det skal lykkes at bruge &ksplash;, har du brug for &kde; version 3.2 eller højere. Nogle temaer vil måske kræve bestemte plugin. Hvis et tema ikke virker, så kontakt venligst temaets forfatter for at finde ud af hvor man får fat i et passende plugin.</para>

</sect1>

<sect1 id="compilation">
<title
>Kompilering og installation</title>
&install.compile.documentation; </sect1>
</appendix>
<appendix id="srccode">
<title
>Kildekode</title>
<sect1 id="theme2kcpp">
<title
>Visning af <filename
>theme2k.cpp</filename
></title>
<programlisting
>#include &lt;qlabel.h&gt;
#include &lt;qwidget.h&gt;

#include &lt;kapplication.h&gt;
#include &lt;kconfig.h&gt;
#include &lt;kdebug.h&gt;
#include &lt;kdialogbase.h&gt;
#include &lt;kgenericfactory.h&gt;
#include &lt;kglobalsettings.h&gt;
#include &lt;klocale.h&gt;
#include &lt;ksplash/objkstheme.h&gt;
#include &lt;kstandarddirs.h&gt;

#include "rotwidget.h"
#include "theme2k.h"
#include "theme2k.moc"

K_EXPORT_COMPONENT_FACTORY( ksplash2k, KGenericFactory&lt;Theme2k&gt; );

Cfg2k::Cfg2k( KConfig * )
{}

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

void Theme2k::initUi()
{
  QVBox *vbox = new QVBox( this );
  vbox-&gt;setFrameShape( QFrame::WinPanel );
  vbox-&gt;setFrameShadow( QFrame::Raised );

  QHBox *labelBox = new QHBox( vbox );
  labelBox-&gt;setPalette( mTBgColor );
  labelBox-&gt;setMargin( 1 );
  QLabel *lbl = new QLabel( mWndTitle, labelBox );
  lbl-&gt;setFont( QFont( "Arial", 12, QFont::Bold ) );
  lbl-&gt;setPaletteForegroundColor( mTFgColor );

  QLabel *logo = new QLabel( vbox );
  logo-&gt;setPalette( Qt::white );

  QString px( locate( "appdata", mTheme-&gt;themeDir() + (mLogoFile.isNull()?QString("/Logo.png"):mLogoFile) ) );
  if (px.isNull())
    px = locate("appdata","Themes/Default/splash_top.png");
  if( !px.isNull() )
  {
    QPixmap pix( px );
    logo-&gt;setPixmap( pix );
  }
  else
  {
    logo-&gt;setText( "&lt;B&gt;KDE&lt;/B&gt;2000" );
    logo-&gt;setAlignment( AlignCenter|AlignVCenter );
  }

  mRotator = new RotWidget( vbox, mRotColor1, mRotColor2, mRotSpeed );

  QHBox *hbox = new QHBox( vbox );
  labelBox-&gt;setSpacing( 4 );
  labelBox-&gt;setMargin( 4 );

  mText = new QLabel( hbox );
  mText-&gt;setPaletteForegroundColor( mStatusColor );
  mText-&gt;setPaletteBackgroundColor( mTFgColor );
  mText-&gt;setText( mWndTitle );
  mText-&gt;setFixedHeight( 48 );

  setFixedSize( vbox-&gt;sizeHint() );
  QRect rect(KGlobalSettings::splashScreenDesktopGeometry());
  move( rect.x() + (rect.width() - size().width())/2,
        rect.y() + (rect.height() - size().height())/2 );
}

void Theme2k::readSettings()
{
  if( !mTheme )
    return;

  KConfig *cfg = mTheme-&gt;themeConfig();
  if( !cfg )
    return;

  cfg-&gt;setGroup( QString("KSplash Theme: %1").arg(mTheme-&gt;theme()) );

  QColor DefaultTBgColor( Qt::darkBlue );
  QColor DefaultTFgColor( Qt::white );

  mTBgColor = cfg-&gt;readColorEntry( "Title Background Color", &amp;DefaultTBgColor );
  mTFgColor = cfg-&gt;readColorEntry( "Title Foreground Color", &amp;DefaultTFgColor );
  mStatusColor = cfg-&gt;readColorEntry("Status Text Color", &amp;mTBgColor );

  QColor DefaultRot1( Qt::darkBlue );
  QColor DefaultRot2( Qt::cyan );
  mRotColor1 = cfg-&gt;readColorEntry( "Rotator Color 1", &amp;DefaultRot1 );
  mRotColor2 = cfg-&gt;readColorEntry( "Rotator Color 2", &amp;DefaultRot2 );

  mRotSpeed = cfg-&gt;readNumEntry( "Rotator Speed", 30 );
  mWndTitle = cfg-&gt;readEntry( "Window Title", i18n("Please wait...") );
  mLogoFile = cfg-&gt;readEntry( "Logo File", QString::null );
}
</programlisting>
</sect1>
<sect1 id="rotwidgeth">
<title
>Visning af <filename
>rotwidget.h</filename
></title>
<programlisting
>#ifndef         __ROTWIDGET_H__
#define         __ROTWIDGET_H__

#include &lt;qlabel.h&gt;
#include &lt;qtimer.h&gt;
#include &lt;qwidget.h&gt;

#include &lt;kdialogbase.h&gt;
#include &lt;kpixmap.h&gt;

/**
 * @short Display a rotating-gradient widget.
 */
class         RotWidget: public QWidget
{
  Q_OBJECT
public:
  RotWidget( QWidget *, const QColor&amp;, const QColor&amp;, int );
  ~RotWidget();

private slots:
  void stepEvent();

protected:
  void        preparePixmap( int );
  void        paintEvent( QPaintEvent * );
  void        resizeEvent( QResizeEvent * );

  QColor m_color1, m_color2;
  int m_step, m_speed;
  QTimer *m_stepTimer;

  QList&lt;KPixmap&gt; m_stepPixmap;
};

#endif
</programlisting>
</sect1>
<sect1 id="rotwidgetcpp">
<title
>Visning af <filename
>rotwidget.cpp</filename
></title>
<programlisting
>#include &lt;kdebug.h&gt;
#include &lt;kdialogbase.h&gt;
#include &lt;kpixmapeffect.h&gt;

#include &lt;qlabel.h&gt;
#include &lt;qpainter.h&gt;
#include &lt;qwidget.h&gt;

#include "rotwidget.h"
#include "rotwidget.moc"

RotWidget::RotWidget( QWidget *parent, const QColor&amp; c1, const QColor&amp; c2, int sp )
    :QWidget(parent), m_color1(c1), m_color2(c2), m_step(0), m_speed(sp)
{
  if( (m_speed &lt;= 0) || (m_speed &gt; 20) )
    m_speed = 1;
  setFixedHeight( 6 );

  for( int i = 0; i &lt;= width(); i++ )
    preparePixmap( i );

  m_stepTimer = new QTimer( this );
  connect(m_stepTimer, SIGNAL(timeout()), this, SLOT(stepEvent()));
  m_stepTimer-&gt;start( 50 );
}

RotWidget::~RotWidget()
{
}

void RotWidget::stepEvent()
{
  // This is inefficient as we create too many pixmaps, optimize later.
  m_step += m_speed;
  if( m_step &gt; width() )
    m_step = 0;
  repaint( true );
}

// Todo: Optimize drawing.
void RotWidget::paintEvent( QPaintEvent *pe )
{
  QPainter p;
  p.begin( this );

  QRect r = pe-&gt;rect();

  if( m_stepPixmap.at( m_step ) )
    bitBlt( this, r.x(), r.y(), m_stepPixmap.at( m_step ), r.x(), r.y(), r.width(), r.height() );
  else
    p.fillRect( rect(), Qt::black );
  p.end();
}

void RotWidget::resizeEvent( QResizeEvent *re )
{
  m_stepPixmap.clear();
  for( int i = 0; i &lt;= re-&gt;size().width(); i++ )
    preparePixmap( i );
}

void RotWidget::preparePixmap( int step )
{
  if( step &lt; 0 )
    return;

  // Explicitly draw our first pixmap. The rest we will bitBlt() from here.
  if( step == 0 )
  {
    KPixmap tmp; tmp.resize( size().width() / 2, size().height() );
    KPixmap tmp2(tmp);
    KPixmapEffect::gradient( tmp, m_color1, m_color2, KPixmapEffect::HorizontalGradient );
    KPixmapEffect::gradient( tmp2, m_color2, m_color1, KPixmapEffect::HorizontalGradient );
    KPixmap *px = new KPixmap( size() );
    QPainter p;
    p.begin( px );
    p.drawPixmap( 0, 0, tmp );
    p.drawPixmap( size().width()/2, 0, tmp2 );
    p.end();
    m_stepPixmap.append( px );
  }
  else if( m_stepPixmap.at( step-1 ) )
  {
    QPixmap *prev = m_stepPixmap.at( step-1 );
    QPixmap next; next.resize( size() );
    // convert
    // prev = "[------------]"
    // to
    // next = "------------]["
    bitBlt( &amp;next, 0, 0, prev, 1, 0, prev-&gt;width()-1, prev-&gt;height() );
    bitBlt( &amp;next, width()-1, 0, prev, 0, 0, 1, prev-&gt;height() );
    KPixmap *n = new KPixmap( next );
    m_stepPixmap.append( n );
  }
}
</programlisting>
</sect1>
</appendix>

&documentation.index;
</book>

<!--
Local Variables:
mode: xml
sgml-minimize-attributes:nil
sgml-general-insert-case:lower
sgml-indent-step:0
sgml-indent-data:nil
End:

vim:tabstop=2:shiftwidth=2:expandtab
-->
