summaryrefslogtreecommitdiffstats
path: root/kcontrol/kthememanager
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/kthememanager')
-rw-r--r--kcontrol/kthememanager/CMakeLists.txt38
-rw-r--r--kcontrol/kthememanager/Makefile.am21
-rw-r--r--kcontrol/kthememanager/NEWS26
-rw-r--r--kcontrol/kthememanager/README99
-rw-r--r--kcontrol/kthememanager/TODO9
-rw-r--r--kcontrol/kthememanager/installktheme.desktop78
-rwxr-xr-xkcontrol/kthememanager/kdeinstallktheme14
-rw-r--r--kcontrol/kthememanager/knewthemedlg.cpp96
-rw-r--r--kcontrol/kthememanager/knewthemedlg.h58
-rw-r--r--kcontrol/kthememanager/ktheme.cpp900
-rw-r--r--kcontrol/kthememanager/ktheme.h224
-rw-r--r--kcontrol/kthememanager/kthemedlg.ui518
-rw-r--r--kcontrol/kthememanager/kthemedlg.ui.h49
-rw-r--r--kcontrol/kthememanager/kthememanager.cpp425
-rw-r--r--kcontrol/kthememanager/kthememanager.desktop221
-rw-r--r--kcontrol/kthememanager/kthememanager.h157
-rw-r--r--kcontrol/kthememanager/newthemewidget.ui130
-rw-r--r--kcontrol/kthememanager/x-ktheme.desktop84
18 files changed, 3147 insertions, 0 deletions
diff --git a/kcontrol/kthememanager/CMakeLists.txt b/kcontrol/kthememanager/CMakeLists.txt
new file mode 100644
index 000000000..b3d000aa5
--- /dev/null
+++ b/kcontrol/kthememanager/CMakeLists.txt
@@ -0,0 +1,38 @@
+#################################################
+#
+# (C) 2010-2011 Serghei Amelian
+# serghei (DOT) amelian (AT) gmail.com
+#
+# Improvements and feedback are welcome
+#
+# This file is released under GPL >= 2
+#
+#################################################
+
+include_directories(
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_BINARY_DIR}
+ ${TDE_INCLUDE_DIR}
+ ${TQT_INCLUDE_DIRS}
+)
+
+link_directories(
+ ${TQT_LIBRARY_DIRS}
+)
+
+##### other data ################################
+
+install( FILES kthememanager.desktop installktheme.desktop DESTINATION ${XDG_APPS_INSTALL_DIR} )
+install( FILES x-ktheme.desktop DESTINATION ${MIME_INSTALL_DIR}/application )
+install( PROGRAMS kdeinstallktheme DESTINATION ${BIN_INSTALL_DIR} )
+
+
+##### kcm_kthememanager (module) ################
+
+tde_add_kpart( kcm_kthememanager AUTOMOC
+ SOURCES
+ kthemedlg.ui newthemewidget.ui knewthemedlg.cpp
+ ktheme.cpp kthememanager.cpp
+ LINK tdeio-shared
+ DESTINATION ${PLUGIN_INSTALL_DIR}
+)
diff --git a/kcontrol/kthememanager/Makefile.am b/kcontrol/kthememanager/Makefile.am
new file mode 100644
index 000000000..cbc241dd9
--- /dev/null
+++ b/kcontrol/kthememanager/Makefile.am
@@ -0,0 +1,21 @@
+AM_CPPFLAGS = $(all_includes)
+METASOURCES = AUTO
+
+kde_module_LTLIBRARIES = kcm_kthememanager.la
+
+kcm_kthememanager_la_SOURCES = kthemedlg.ui newthemewidget.ui knewthemedlg.cpp ktheme.cpp kthememanager.cpp
+kcm_kthememanager_la_LIBADD = $(LIB_TDEIO)
+kcm_kthememanager_la_LDFLAGS = $(all_libraries) $(KDE_PLUGIN) -module
+
+noinst_HEADERS = kthememanager.h ktheme.h knewthemedlg.h kthemedlg.ui.h
+
+xdg_apps_DATA = kthememanager.desktop installktheme.desktop
+
+# MIME type
+kthememime_DATA = x-ktheme.desktop
+kthememimedir = $(kde_mimedir)/application
+
+bin_SCRIPTS = kdeinstallktheme
+
+messages: rc.cpp
+ $(XGETTEXT) *.cpp -o $(podir)/kthememanager.pot
diff --git a/kcontrol/kthememanager/NEWS b/kcontrol/kthememanager/NEWS
new file mode 100644
index 000000000..23cd860ee
--- /dev/null
+++ b/kcontrol/kthememanager/NEWS
@@ -0,0 +1,26 @@
+Version 0.4
+===========
+- added support for screensaver
+- fixed Kicker transparency not being saved correctly
+
+Version 0.3
+===========
+- the theme manager now correctly handles installing and creating
+ new themes over existing ones
+- support for widget styles (or the name thereof)
+- added new details buttons to launch idividual kcm style-related
+ modules
+- write/read the current theme and preselect it at startup
+- the preview pixmap is now generated dynamically
+ and taken at full size
+
+Version 0.2
+===========
+- support for colorizing the Kicker background
+- support for relative URLs, as the README states
+- installing themes via DnD, even remote ones
+- installing themes via context (service) menu from Konqueror
+
+Version 0.1
+===========
+- first release
diff --git a/kcontrol/kthememanager/README b/kcontrol/kthememanager/README
new file mode 100644
index 000000000..cd32a528a
--- /dev/null
+++ b/kcontrol/kthememanager/README
@@ -0,0 +1,99 @@
+This theme manager should handle installing, removing
+and creating global visual KDE themes. It's written
+from scratch, totally unrelated to the old kthememgr
+which was not maintained and obsolete.
+
+*** WARNING ***
+The XML file format is still subject to change!
+*** WARNING ***
+
+(c) 2003, 2004 Lukas Tinkl <[email protected]>
+
+
+A KDE theme consists of:
+========================
+- wallpapers or bg colors
+- icons
+- sounds
+- color scheme
+- cursor theme
+- window decorations
+- screensaver
+- name of the widget theme
+- themed apps (mainly Konqueror and Kicker)
+
+
+Sample XML theme config file:
+=============================
+<ktheme version="1">
+<general>
+ <author value="Me" />
+ <email value="[email protected]" />
+ <homepage value="http://me.home.com" />
+ <version value="0.1" />
+ <comment value="this is a nice theme, bla bla" />
+</general>
+<desktop number="0" common="true|false">
+ <mode id="Flat|Pattern|*Gradient" />
+ <color1 rgb="#123456" />
+ <color2 rgb="#123456" />
+ <blending mode="" balance="" reverse="true|false" />
+ <pattern name="fish" />
+ <wallpaper url="theme:/wallpapers/desktop/image.jpg"
+ mode="Centred|Tiled|CenterTiled|CentredMaxpect|TiledMaxpect|Scaled|CentredAutoFit" />
+</desktop>
+<icons name="crystalsvg" />
+<sounds>
+ <event object="global|twin" name="eventname" url="theme:/sounds/file.wav" />
+ ...
+</sounds>
+<colors contrast="7">
+ <alternateBackground rgb="#123456" object="global|twin"/>
+ ...
+</colors>
+<cursors name="theme_name" />
+<wm type="builtin|custom" name="twin_lib_name">
+ <buttons left="M" right="HIAX" />
+ <border size="number" />
+</wm>
+<konqueror>
+ <wallpaper url="" />
+ <bgcolor rgb="#123456" />
+</konqueror>
+<panel>
+ <background url="theme:/wallpapers/panel.png" colorize="true|false" />
+ <!-- or -->
+ <transparent value="true|false" />
+</panel>
+<widgets name="Style Name" />
+<screensaver name="saver.desktop" />
+</kdetheme>
+
+
+Theme storage:
+==============
+- a gzipped tarball, directory tree based (e.g. theme.kth)
+
+
+Sample dir tree:
+================
+-- mytheme.kth
+ - mytheme.xml
+ - mytheme.preview.png
+ - sounds/
+ - wallpapers/
+ - konqueror/
+ - desktop/
+ - panel/
+
+
+The notion of "url" here:
+=========================
+- local: points to an already installed file in the system
+ (must be a sole filename, e.g. "background.png"); this differs
+ according to the theme part (ie. can be different for sounds
+ and/or wallpapers)
+- theme: relative to the root of the theme tarball or directory
+ (e.g. theme:/wallpapers/desktop/image.png)
+- other URLs are not allowed, the file must be contained
+ either in the theme or in the target system
diff --git a/kcontrol/kthememanager/TODO b/kcontrol/kthememanager/TODO
new file mode 100644
index 000000000..59bea20c7
--- /dev/null
+++ b/kcontrol/kthememanager/TODO
@@ -0,0 +1,9 @@
+- use KHotNewStuff for directly downloading themes from kde-look.org
+- custom pixmap twin themes (requires kwmtheme to be ported first)
+- write user and theme developer documentation
+
+Handle:
+- splash screen (+ copying?)
+- TDE Menu sidebar pixmap
+- bundling the cursor theme
+- slideshow and "active" background program
diff --git a/kcontrol/kthememanager/installktheme.desktop b/kcontrol/kthememanager/installktheme.desktop
new file mode 100644
index 000000000..52674fa80
--- /dev/null
+++ b/kcontrol/kthememanager/installktheme.desktop
@@ -0,0 +1,78 @@
+[Desktop Entry]
+Name=Install TDE Theme
+Name[af]=Installeer TDE temas
+Name[ar]=ثبِت سمة TDE
+Name[az]=TDE Örtüyünü Qur
+Name[be]=Устаноўка тэмы TDE
+Name[bg]=Инсталиране на тема
+Name[bn]=কে.ডি.ই. থীম ইনস্টল করো
+Name[br]=Staliañ ar c'hiz TDE
+Name[bs]=Instaliraj TDE temu
+Name[ca]=Instal·la tema TDE
+Name[cs]=Instalovat TDE motiv
+Name[csb]=Instalëjë témã TDE
+Name[cy]=Gosod Thema TDE
+Name[da]=Installér TDE-tema
+Name[de]=TDE-Design installieren
+Name[el]=Εγκατάσταση θέματος του TDE
+Name[eo]=Instali TDEan etoson
+Name[es]=Instalar tema de TDE
+Name[et]=TDE teema paigaldamine
+Name[eu]=Instalatu TDE gaia
+Name[fa]=نصب چهرۀ TDE
+Name[fi]=Asenna TDE-teema
+Name[fr]=Installer des thèmes TDE
+Name[fy]=TDE-tema ynstallearje
+Name[ga]=Suiteáil Téama TDE
+Name[gl]=Instalar tema de TDE
+Name[he]=התקנה של ערכת נושא עבור TDE
+Name[hi]=केडीई प्रसंग संस्थापित करें
+Name[hr]=Instaliranje TDE teme
+Name[hu]=TDE-téma telepítése
+Name[is]=Setja inn TDE þemu
+Name[it]=Installa tema di TDE
+Name[ja]=TDE テーマのインストール
+Name[ka]=TDE-ს თემების დაყენება
+Name[kk]=TDE нақыштарын орнату
+Name[km]=ដំឡើង​ស្បែក TDE
+Name[ko]=TDE 테마 설치
+Name[lt]=Įdiegti TDE temą
+Name[lv]=Instalēt TDE tēmu
+Name[mk]=Инсталирај TDE Тема
+Name[ms]=Pasang Tema TDE
+Name[mt]=Installa Tema TDE
+Name[nb]=Legg inn TDE-tema
+Name[nds]=TDE-Muster installeren
+Name[ne]=TDE विषयवस्तु स्थापना गर्नुहोस्
+Name[nl]=TDE-thema installeren
+Name[nn]=Installer TDE-tema
+Name[pa]=TDE ਸਰੂਪ ਇੰਸਟਾਲ
+Name[pl]=Instaluj motyw TDE
+Name[pt]=Instalar um Tema do TDE
+Name[pt_BR]=Instalar Tema do TDE
+Name[ro]=Instalează tematică TDE
+Name[ru]=Установка тем TDE
+Name[rw]=Kwinjiza Insanganyamatsiko TDE
+Name[se]=Sajáiduhte TDE-fáttá
+Name[sk]=Inštalovať tému TDE
+Name[sl]=Namesti temo TDE
+Name[sr]=Инсталирај TDE тему
+Name[sr@Latn]=Instaliraj TDE temu
+Name[sv]=Installera TDE-tema
+Name[ta]=TDE பொருளை நிறுவு
+Name[tg]=Мавзӯъи TDE сабт кунед
+Name[th]=ติดตั้งชุดตกแต่ง TDE
+Name[tr]=TDE Teması Yükle
+Name[tt]=TDE Tışlaw quyu
+Name[uk]=Встановлення теми TDE
+Name[uz]=TDE mavzusini oʻrnatish
+Name[uz@cyrillic]=TDE мавзусини ўрнатиш
+Name[vi]=Cài đặt Sắc thái TDE
+Name[wa]=Astaler on tinme TDE
+Name[zh_CN]=安装 TDE 主题
+Name[zh_TW]=安裝 TDE 佈景
+MimeType=application/x-ktheme;
+Icon=kthememgr
+Type=Application
+NoDisplay=true
+Exec=kdeinstallktheme %f
diff --git a/kcontrol/kthememanager/kdeinstallktheme b/kcontrol/kthememanager/kdeinstallktheme
new file mode 100755
index 000000000..95b40eec6
--- /dev/null
+++ b/kcontrol/kthememanager/kdeinstallktheme
@@ -0,0 +1,14 @@
+#!/bin/sh
+# Installs a KDE theme (into the user's theme dir)
+appsdir=`tde-config --path data | sed -e 's/:.*//'`
+themedir=$appsdir"/kthememanager/themes/"`basename "$1" ".kth"`
+if test -n "$appsdir"; then
+ test -d "$themedir" || mkdir -p "$themedir"
+ #echo "$themedir"
+ cp -f "$1" "$themedir"
+ cd "$themedir"
+ tarball=`basename "$1"`
+ #echo $tarball
+ tar xzf "$tarball"
+ rm -f "$tarball"
+fi
diff --git a/kcontrol/kthememanager/knewthemedlg.cpp b/kcontrol/kthememanager/knewthemedlg.cpp
new file mode 100644
index 000000000..ee18c31c7
--- /dev/null
+++ b/kcontrol/kthememanager/knewthemedlg.cpp
@@ -0,0 +1,96 @@
+// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*-
+/* Copyright (C) 2003 Lukas Tinkl <[email protected]>
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "knewthemedlg.h"
+#include "newthemewidget.h"
+
+#include <tqlineedit.h>
+#include <tqtextedit.h>
+
+#include <tdelocale.h>
+
+KNewThemeDlg::KNewThemeDlg( TQWidget * parent, const char * name )
+ : KDialogBase(parent, name, true, i18n("New Theme"), Ok|Cancel, Ok)
+{
+ m_base = new NewThemeWidget( this, "new_theme_base" );
+ setMainWidget( m_base );
+ connect( m_base->leName, TQT_SIGNAL( textChanged ( const TQString & ) ), this, TQT_SLOT( slotThemeNameChanged( const TQString & ) ) );
+ slotThemeNameChanged( m_base->leName->text() );
+}
+
+KNewThemeDlg::~KNewThemeDlg()
+{
+ delete m_base;
+}
+
+void KNewThemeDlg::slotThemeNameChanged( const TQString &_text )
+{
+ enableButtonOK( !_text.isEmpty() );
+}
+
+TQString KNewThemeDlg::getName() const
+{
+ return m_base->leName->text();
+}
+
+TQString KNewThemeDlg::getAuthor() const
+{
+ return m_base->leAuthor->text();
+}
+
+TQString KNewThemeDlg::getEmail() const
+{
+ return m_base->leEmail->text();
+}
+
+TQString KNewThemeDlg::getHomepage() const
+{
+ return m_base->leHomepage->text();
+}
+
+TQString KNewThemeDlg::getComment() const
+{
+ return m_base->teComment->text();
+}
+
+TQString KNewThemeDlg::getVersion() const
+{
+ return m_base->leVersion->text();
+}
+
+void KNewThemeDlg::setAuthor( const TQString & author )
+{
+ m_base->leAuthor->setText( author );
+}
+
+void KNewThemeDlg::setEmail( const TQString & email )
+{
+ m_base->leEmail->setText( email );
+}
+
+void KNewThemeDlg::setVersion( const TQString & version )
+{
+ m_base->leVersion->setText( version );
+}
+
+void KNewThemeDlg::setName( const TQString & name )
+{
+ m_base->leName->setText( name );
+}
+
+#include "knewthemedlg.moc"
diff --git a/kcontrol/kthememanager/knewthemedlg.h b/kcontrol/kthememanager/knewthemedlg.h
new file mode 100644
index 000000000..5a0df045a
--- /dev/null
+++ b/kcontrol/kthememanager/knewthemedlg.h
@@ -0,0 +1,58 @@
+// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*-
+/* Copyright (C) 2003 Lukas Tinkl <[email protected]>
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef KNEWTHEMEDLG_H
+#define KNEWTHEMEDLG_H
+
+#include <tqstring.h>
+
+#include <kdialogbase.h>
+
+class NewThemeWidget;
+
+/**
+ * Dialog for creating new themes, contains just
+ * getters and setters used for the theme general properties
+ * @author Lukas Tinkl <[email protected]>
+ */
+class KNewThemeDlg: public KDialogBase
+{
+ Q_OBJECT
+public:
+ KNewThemeDlg( TQWidget * parent = 0, const char * name = 0);
+ ~KNewThemeDlg();
+
+ TQString getName() const;
+ TQString getAuthor() const;
+ TQString getEmail() const;
+ TQString getHomepage() const;
+ TQString getComment() const;
+ TQString getVersion() const;
+
+ void setName( const TQString & name );
+ void setAuthor( const TQString & author );
+ void setEmail( const TQString & email );
+ void setVersion( const TQString & version );
+private:
+ NewThemeWidget * m_base;
+
+private slots:
+ void slotThemeNameChanged( const TQString &_text );
+};
+
+#endif
diff --git a/kcontrol/kthememanager/ktheme.cpp b/kcontrol/kthememanager/ktheme.cpp
new file mode 100644
index 000000000..0dcee8105
--- /dev/null
+++ b/kcontrol/kthememanager/ktheme.cpp
@@ -0,0 +1,900 @@
+// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*-
+/* Copyright (C) 2003 Lukas Tinkl <[email protected]>
+
+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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include "ktheme.h"
+
+#include <tqfile.h>
+#include <tqfileinfo.h>
+#include <tqimage.h>
+#include <tqpixmap.h>
+#include <tqregexp.h>
+#include <tqtextstream.h>
+#include <tqdir.h>
+
+#include <dcopclient.h>
+#include <tdeapplication.h>
+#include <tdeconfig.h>
+#include <kdatastream.h>
+#include <kdebug.h>
+#include <tdeglobal.h>
+#include <kiconloader.h>
+#include <tdeio/job.h>
+#include <tdeio/netaccess.h>
+#include <kipc.h>
+#include <tdelocale.h>
+#include <kservice.h>
+#include <ksimpleconfig.h>
+#include <kstandarddirs.h>
+#include <ktar.h>
+#include <tdestyle.h>
+
+KTheme::KTheme( TQWidget *parent, const TQString & xmlFile )
+ : m_parent(parent)
+{
+ TQFile file( xmlFile );
+ file.open( IO_ReadOnly );
+ m_dom.setContent( TQByteArray(file.readAll()) );
+ file.close();
+
+ //kdDebug() << m_dom.toString( 2 ) << endl;
+
+ setName( TQFileInfo( file ).baseName() );
+ m_kgd = TDEGlobal::dirs();
+}
+
+KTheme::KTheme( TQWidget *parent, bool create )
+ : m_parent(parent)
+{
+ if ( create )
+ {
+ m_dom = TQDomDocument( "ktheme" );
+
+ m_root = m_dom.createElement( "ktheme" );
+ m_root.setAttribute( "version", SYNTAX_VERSION );
+ m_dom.appendChild( m_root );
+
+ m_general = m_dom.createElement( "general" );
+ m_root.appendChild( m_general );
+ }
+
+ m_kgd = TDEGlobal::dirs();
+}
+
+KTheme::~KTheme()
+{
+}
+
+void KTheme::setName( const TQString & name )
+{
+ m_name = name;
+}
+
+bool KTheme::load( const KURL & url )
+{
+ kdDebug() << "Loading theme from URL: " << url << endl;
+
+ TQString tmpFile;
+ if ( !TDEIO::NetAccess::download( url, tmpFile, 0L ) )
+ return false;
+
+ kdDebug() << "Theme is in temp file: " << tmpFile << endl;
+
+ // set theme's name
+ setName( TQFileInfo( url.fileName() ).baseName() );
+
+ // unpack the tarball
+ TQString location = m_kgd->saveLocation( "themes", m_name + "/" );
+ KTar tar( tmpFile );
+ tar.open( IO_ReadOnly );
+ tar.directory()->copyTo( location );
+ tar.close();
+
+ // create the DOM
+ TQFile file( location + m_name + ".xml" );
+ file.open( IO_ReadOnly );
+ m_dom.setContent( TQByteArray(file.readAll()) );
+ file.close();
+
+ // remove the temp file
+ TDEIO::NetAccess::removeTempFile( tmpFile );
+
+ return true;
+}
+
+TQString KTheme::createYourself( bool pack )
+{
+ // start with empty dir for orig theme
+ if ( !pack )
+ KTheme::remove( name() );
+
+ // 1. General stuff set by methods setBlah()
+
+ // 2. Background theme
+ TDEConfig * globalConf = TDEGlobal::config();
+
+ TDEConfig twinConf( "twinrc", true );
+ twinConf.setGroup( "Desktops" );
+ uint numDesktops = twinConf.readUnsignedNumEntry( "Number", 4 );
+
+ TDEConfig desktopConf( "kdesktoprc", true );
+ desktopConf.setGroup( "Background Common" );
+ bool common = desktopConf.readBoolEntry( "CommonDesktop", true );
+
+ for ( uint i=0; i < numDesktops-1; i++ )
+ {
+ TQDomElement desktopElem = m_dom.createElement( "desktop" );
+ desktopElem.setAttribute( "number", i );
+ desktopElem.setAttribute( "common", common );
+
+ desktopConf.setGroup( "Desktop" + TQString::number( i ) );
+
+ TQDomElement modeElem = m_dom.createElement( "mode" );
+ modeElem.setAttribute( "id", desktopConf.readEntry( "BackgroundMode", "Flat" ) );
+ desktopElem.appendChild( modeElem );
+
+ TQDomElement c1Elem = m_dom.createElement( "color1" );
+ c1Elem.setAttribute( "rgb", desktopConf.readColorEntry( "Color1" ).name() );
+ desktopElem.appendChild( c1Elem );
+
+ TQDomElement c2Elem = m_dom.createElement( "color2" );
+ c2Elem.setAttribute( "rgb", desktopConf.readColorEntry( "Color2" ).name() );
+ desktopElem.appendChild( c2Elem );
+
+ TQDomElement blendElem = m_dom.createElement( "blending" );
+ blendElem.setAttribute( "mode", desktopConf.readEntry( "BlendMode", TQString( "NoBlending" ) ) );
+ blendElem.setAttribute( "balance", desktopConf.readEntry( "BlendBalance", TQString::number( 100 ) ) );
+ blendElem.setAttribute( "reverse", desktopConf.readBoolEntry( "ReverseBlending", false ) );
+ desktopElem.appendChild( blendElem );
+
+ TQDomElement patElem = m_dom.createElement( "pattern" );
+ patElem.setAttribute( "name", desktopConf.readEntry( "Pattern" ) );
+ desktopElem.appendChild( patElem );
+
+ TQDomElement wallElem = m_dom.createElement( "wallpaper" );
+ wallElem.setAttribute( "url", processFilePath( "desktop", desktopConf.readPathEntry( "Wallpaper" ) ) );
+ wallElem.setAttribute( "mode", desktopConf.readEntry( "WallpaperMode" ) );
+ desktopElem.appendChild( wallElem );
+
+ // TODO handle multi wallpapers (aka slideshow)
+
+ m_root.appendChild( desktopElem );
+
+ if ( common ) // generate only one node
+ break;
+ }
+
+ // 11. Screensaver
+ desktopConf.setGroup( "ScreenSaver" );
+ TQDomElement saverElem = m_dom.createElement( "screensaver" );
+ saverElem.setAttribute( "name", desktopConf.readEntry( "Saver" ) );
+ m_root.appendChild( saverElem );
+
+ // 3. Icons
+ globalConf->setGroup( "Icons" );
+ TQDomElement iconElem = m_dom.createElement( "icons" );
+ iconElem.setAttribute( "name", globalConf->readEntry( "Theme",TDEIconTheme::current() ) );
+ createIconElems( "DesktopIcons", "desktop", iconElem, globalConf );
+ createIconElems( "MainToolbarIcons", "mainToolbar", iconElem, globalConf );
+ createIconElems( "PanelIcons", "panel", iconElem, globalConf );
+ createIconElems( "SmallIcons", "small", iconElem, globalConf );
+ createIconElems( "ToolbarIcons", "toolbar", iconElem, globalConf );
+ m_root.appendChild( iconElem );
+
+ // 4. Sounds
+ // 4.1 Global sounds
+ TDEConfig * soundConf = new TDEConfig( "knotify.eventsrc", true );
+ TQStringList stdEvents;
+ stdEvents << "cannotopenfile" << "catastrophe" << "exitkde" << "fatalerror"
+ << "notification" << "printerror" << "starttde" << "warning"
+ << "messageCritical" << "messageInformation" << "messageWarning"
+ << "messageboxQuestion";
+
+ // 4.2 KWin sounds
+ TDEConfig * twinSoundConf = new TDEConfig( "twin.eventsrc", true );
+ TQStringList twinEvents;
+ twinEvents << "activate" << "close" << "delete" <<
+ "desktop1" << "desktop2" << "desktop3" << "desktop4" <<
+ "desktop5" << "desktop6" << "desktop7" << "desktop8" <<
+ "maximize" << "minimize" << "moveend" << "movestart" <<
+ "new" << "not_on_all_desktops" << "on_all_desktops" <<
+ "resizeend" << "resizestart" << "shadedown" << "shadeup" <<
+ "transdelete" << "transnew" << "unmaximize" << "unminimize";
+
+ TQDomElement soundsElem = m_dom.createElement( "sounds" );
+ createSoundList( stdEvents, "global", soundsElem, soundConf );
+ createSoundList( twinEvents, "twin", soundsElem, twinSoundConf );
+ m_root.appendChild( soundsElem );
+ delete soundConf;
+ delete twinSoundConf;
+
+
+ // 5. Colors
+ TQDomElement colorsElem = m_dom.createElement( "colors" );
+ globalConf->setGroup( "KDE" );
+ colorsElem.setAttribute( "contrast", globalConf->readNumEntry( "contrast", 7 ) );
+ TQStringList stdColors;
+ stdColors << "background" << "selectBackground" << "foreground" << "windowForeground"
+ << "windowBackground" << "selectForeground" << "buttonBackground"
+ << "buttonForeground" << "linkColor" << "visitedLinkColor" << "alternateBackground";
+
+ globalConf->setGroup( "General" );
+ for ( TQStringList::Iterator it = stdColors.begin(); it != stdColors.end(); ++it )
+ createColorElem( ( *it ), "global", colorsElem, globalConf );
+
+ TQStringList twinColors;
+ twinColors << "activeForeground" << "inactiveBackground" << "inactiveBlend" << "activeBackground"
+ << "activeBlend" << "inactiveForeground" << "activeTitleBtnBg" << "inactiveTitleBtnBg"
+ << "frame" << "inactiveFrame" << "handle" << "inactiveHandle";
+ globalConf->setGroup( "WM" );
+ for ( TQStringList::Iterator it = twinColors.begin(); it != twinColors.end(); ++it )
+ createColorElem( ( *it ), "twin", colorsElem, globalConf );
+
+ m_root.appendChild( colorsElem );
+
+ // 6. Cursors
+ TDEConfig* mouseConf = new TDEConfig( "kcminputrc", true );
+ mouseConf->setGroup( "Mouse" );
+ TQDomElement cursorsElem = m_dom.createElement( "cursors" );
+ cursorsElem.setAttribute( "name", mouseConf->readEntry( "cursorTheme" ) );
+ m_root.appendChild( cursorsElem );
+ delete mouseConf;
+ // TODO copy the cursor theme?
+
+ // 7. KWin
+ twinConf.setGroup( "Style" );
+ TQDomElement wmElem = m_dom.createElement( "wm" );
+ wmElem.setAttribute( "name", twinConf.readEntry( "PluginLib" ) );
+ wmElem.setAttribute( "type", "builtin" ); // TODO support pixmap themes when the twin client gets ported
+ if ( twinConf.readBoolEntry( "CustomButtonPositions" ) )
+ {
+ TQDomElement buttonsElem = m_dom.createElement( "buttons" );
+ buttonsElem.setAttribute( "left", twinConf.readEntry( "ButtonsOnLeft" ) );
+ buttonsElem.setAttribute( "right", twinConf.readEntry( "ButtonsOnRight" ) );
+ wmElem.appendChild( buttonsElem );
+ }
+ TQDomElement borderElem = m_dom.createElement( "border" );
+ borderElem.setAttribute( "size", twinConf.readNumEntry( "BorderSize", 1 ) );
+ wmElem.appendChild( borderElem );
+ m_root.appendChild( wmElem );
+
+ // 8. Konqueror
+ TDEConfig konqConf( "konquerorrc", true );
+ konqConf.setGroup( "Settings" );
+ TQDomElement konqElem = m_dom.createElement( "konqueror" );
+ TQDomElement konqWallElem = m_dom.createElement( "wallpaper" );
+ TQString bgImagePath = konqConf.readPathEntry( "BgImage" );
+ konqWallElem.setAttribute( "url", processFilePath( "konqueror", bgImagePath ) );
+ konqElem.appendChild( konqWallElem );
+ TQDomElement konqBgColorElem = m_dom.createElement( "bgcolor" );
+ konqBgColorElem.setAttribute( "rgb", konqConf.readColorEntry( "BgColor" ).name() );
+ konqElem.appendChild( konqBgColorElem );
+ m_root.appendChild( konqElem );
+
+ // 9. Kicker (aka TDE Panel)
+ TDEConfig kickerConf( "kickerrc", true );
+ kickerConf.setGroup( "General" );
+
+ TQDomElement panelElem = m_dom.createElement( "panel" );
+
+ if ( kickerConf.readBoolEntry( "UseBackgroundTheme" ) )
+ {
+ TQDomElement backElem = m_dom.createElement( "background" );
+ TQString kbgPath = kickerConf.readPathEntry( "BackgroundTheme" );
+ backElem.setAttribute( "url", processFilePath( "panel", kbgPath ) );
+ backElem.setAttribute( "colorize", kickerConf.readBoolEntry( "ColorizeBackground" ) );
+ panelElem.appendChild( backElem );
+ }
+
+ TQDomElement transElem = m_dom.createElement( "transparent" );
+ transElem.setAttribute( "value", kickerConf.readBoolEntry( "Transparent" ) );
+ panelElem.appendChild( transElem );
+
+ TQDomElement posElem = m_dom.createElement( "position" );
+ posElem.setAttribute( "value", kickerConf.readEntry( "Position" ) );
+ panelElem.appendChild( posElem );
+
+
+ TQDomElement showLeftHideButtonElem = m_dom.createElement( "showlefthidebutton" );
+ showLeftHideButtonElem.setAttribute( "value", kickerConf.readBoolEntry( "ShowLeftHideButton" ) );
+ panelElem.appendChild( showLeftHideButtonElem );
+
+ TQDomElement showRightHideButtonElem = m_dom.createElement( "showrighthidebutton" );
+ showRightHideButtonElem.setAttribute( "value", kickerConf.readBoolEntry( "ShowRightHideButton" ) );
+ panelElem.appendChild( showRightHideButtonElem );
+
+
+
+ m_root.appendChild( panelElem );
+
+ // 10. Widget style
+ globalConf->setGroup( "General" );
+ TQDomElement widgetsElem = m_dom.createElement( "widgets" );
+ widgetsElem.setAttribute( "name", globalConf->readEntry( "widgetStyle",TDEStyle::defaultStyle() ) );
+ m_root.appendChild( widgetsElem );
+
+ // 12.
+ TQDomElement fontsElem = m_dom.createElement( "fonts" );
+ TQStringList fonts;
+ fonts << "General" << "font"
+ << "General" << "fixed"
+ << "General" << "toolBarFont"
+ << "General" << "menuFont"
+ << "WM" << "activeFont"
+ << "General" << "taskbarFont"
+ << "FMSettings" << "StandardFont";
+
+ for ( TQStringList::Iterator it = fonts.begin(); it != fonts.end(); ++it ) {
+ TQString group = *it; ++it;
+ TQString key = *it;
+ TQString value;
+
+ if ( group == "FMSettings" ) {
+ desktopConf.setGroup( group );
+ value = desktopConf.readEntry( key );
+ }
+ else {
+ globalConf->setGroup( group );
+ value = globalConf->readEntry( key );
+ }
+ TQDomElement fontElem = m_dom.createElement( key );
+ fontElem.setAttribute( "object", group );
+ fontElem.setAttribute( "value", value );
+ fontsElem.appendChild( fontElem );
+ }
+ m_root.appendChild( fontsElem );
+
+ // Save the XML
+ TQFile file( m_kgd->saveLocation( "themes", m_name + "/" ) + m_name + ".xml" );
+ if ( file.open( IO_WriteOnly ) ) {
+ TQTextStream stream( &file );
+ m_dom.save( stream, 2 );
+ file.close();
+ }
+
+ TQString result;
+ if ( pack )
+ {
+ // Pack the whole theme
+ KTar tar( m_kgd->saveLocation( "themes" ) + m_name + ".kth", "application/x-gzip" );
+ tar.open( IO_WriteOnly );
+
+ kdDebug() << "Packing everything under: " << m_kgd->saveLocation( "themes", m_name + "/" ) << endl;
+
+ if ( tar.addLocalDirectory( m_kgd->saveLocation( "themes", m_name + "/" ), TQString::null ) )
+ result = tar.fileName();
+
+ tar.close();
+ }
+
+ //kdDebug() << m_dom.toString( 2 ) << endl;
+
+ return result;
+}
+
+void KTheme::apply()
+{
+ kdDebug() << "Going to apply theme: " << m_name << endl;
+
+ TQString themeDir = m_kgd->findResourceDir( "themes", m_name + "/" + m_name + ".xml") + m_name + "/";
+ kdDebug() << "Theme dir: " << themeDir << endl;
+
+ // 2. Background theme
+
+ TQDomNodeList desktopList = m_dom.elementsByTagName( "desktop" );
+ TDEConfig desktopConf( "kdesktoprc" );
+ desktopConf.setGroup( "Background Common" );
+
+ for ( uint i = 0; i <= desktopList.count(); i++ )
+ {
+ TQDomElement desktopElem = desktopList.item( i ).toElement();
+ if ( !desktopElem.isNull() )
+ {
+ // TODO optimize, don't write several times the common section
+ bool common = static_cast<bool>( desktopElem.attribute( "common", "true" ).toUInt() );
+ desktopConf.writeEntry( "CommonDesktop", common );
+ desktopConf.writeEntry( "DeskNum", desktopElem.attribute( "number", "0" ).toUInt() );
+
+ desktopConf.setGroup( TQString( "Desktop%1" ).arg( i ) );
+ if (getProperty( desktopElem, "mode", "id" ) != TQString::null) desktopConf.writeEntry( "BackgroundMode", getProperty( desktopElem, "mode", "id" ) );
+ if (getProperty( desktopElem, "color1", "rgb" ) != TQString::null) desktopConf.writeEntry( "Color1", TQColor( getProperty( desktopElem, "color1", "rgb" ) ) );
+ if (getProperty( desktopElem, "color2", "rgb" ) != TQString::null) desktopConf.writeEntry( "Color2", TQColor( getProperty( desktopElem, "color2", "rgb" ) ) );
+ if (getProperty( desktopElem, "blending", "mode" ) != TQString::null) desktopConf.writeEntry( "BlendMode", getProperty( desktopElem, "blending", "mode" ) );
+ if (getProperty( desktopElem, "blending", "balance" ) != TQString::null) desktopConf.writeEntry( "BlendBalance", getProperty( desktopElem, "blending", "balance" ) );
+ if (getProperty( desktopElem, "blending", "reverse" ) != TQString::null) desktopConf.writeEntry( "ReverseBlending", static_cast<bool>( getProperty( desktopElem, "blending", "reverse" ).toUInt() ) );
+ if (getProperty( desktopElem, "pattern", "name" ) != TQString::null) desktopConf.writeEntry( "Pattern", getProperty( desktopElem, "pattern", "name" ) );
+ if (getProperty( desktopElem, "wallpaper", "url" ) != TQString::null) desktopConf.writeEntry( "Wallpaper", unprocessFilePath( "desktop", getProperty( desktopElem, "wallpaper", "url" ) ) );
+ if (getProperty( desktopElem, "wallpaper", "mode" ) != TQString::null) desktopConf.writeEntry( "WallpaperMode", getProperty( desktopElem, "wallpaper", "mode" ) );
+
+ if ( common ) {
+ break; // stop here
+ }
+ }
+ }
+
+ // 11. Screensaver
+ TQDomElement saverElem = m_dom.elementsByTagName( "screensaver" ).item( 0 ).toElement();
+
+ if ( !saverElem.isNull() )
+ {
+ desktopConf.setGroup( "ScreenSaver" );
+ desktopConf.writeEntry( "Saver", saverElem.attribute( "name" ) );
+ }
+
+ desktopConf.sync(); // TODO sync and signal only if <desktop> elem present
+ // reconfigure kdesktop. kdesktop will notify all clients
+ DCOPClient *client = kapp->dcopClient();
+ if ( !client->isAttached() ) {
+ client->attach();
+ }
+ client->send("kdesktop", "KBackgroundIface", "configure()", TQString(""));
+ // FIXME Xinerama
+
+ // 3. Icons
+ TQDomElement iconElem = m_dom.elementsByTagName( "icons" ).item( 0 ).toElement();
+ if ( !iconElem.isNull() )
+ {
+ TDEConfig * iconConf = TDEGlobal::config();
+ iconConf->setGroup( "Icons" );
+ iconConf->writeEntry( "Theme", iconElem.attribute( "name", "crystalsvg" ), true, true );
+
+ TQDomNodeList iconList = iconElem.childNodes();
+ for ( uint i = 0; i < iconList.count(); i++ )
+ {
+ TQDomElement iconSubElem = iconList.item( i ).toElement();
+ TQString object = iconSubElem.attribute( "object" );
+ if ( object == "desktop" ) {
+ iconConf->setGroup( "DesktopIcons" );
+ }
+ else if ( object == "mainToolbar" ) {
+ iconConf->setGroup( "MainToolbarIcons" );
+ }
+ else if ( object == "panel" ) {
+ iconConf->setGroup( "PanelIcons" );
+ }
+ else if ( object == "small" ) {
+ iconConf->setGroup( "SmallIcons" );
+ }
+ else if ( object == "toolbar" ) {
+ iconConf->setGroup( "ToolbarIcons" );
+ }
+
+ TQString iconName = iconSubElem.tagName();
+ if ( iconName.contains( "Color" ) ) {
+ TQColor iconColor = TQColor( iconSubElem.attribute( "rgb" ) );
+ iconConf->writeEntry( iconName, iconColor, true, true );
+ }
+ else if ( iconName.contains( "Value" ) || iconName == "Size" ) {
+ iconConf->writeEntry( iconName, iconSubElem.attribute( "value" ).toUInt(), true, true );
+ }
+ else if ( iconName.contains( "Effect" ) ) {
+ iconConf->writeEntry( iconName, iconSubElem.attribute( "name" ), true, true );
+ }
+ else {
+ iconConf->writeEntry( iconName, static_cast<bool>( iconSubElem.attribute( "value" ).toUInt() ), true, true );
+ }
+ }
+ iconConf->sync();
+
+ for ( int i = 0; i < TDEIcon::LastGroup; i++ )
+ KIPC::sendMessageAll( KIPC::IconChanged, i );
+ KService::rebuildKSycoca( m_parent );
+ }
+
+ // 4. Sounds
+ TQDomElement soundsElem = m_dom.elementsByTagName( "sounds" ).item( 0 ).toElement();
+ if ( !soundsElem.isNull() )
+ {
+ TDEConfig soundConf( "knotify.eventsrc" );
+ TDEConfig twinSoundConf( "twin.eventsrc" );
+ TQDomNodeList eventList = soundsElem.elementsByTagName( "event" );
+ for ( uint i = 0; i < eventList.count(); i++ )
+ {
+ TQDomElement eventElem = eventList.item( i ).toElement();
+ TQString object = eventElem.attribute( "object" );
+
+ if ( object == "global" )
+ {
+ soundConf.setGroup( eventElem.attribute( "name" ) );
+ soundConf.writeEntry( "soundfile", unprocessFilePath( "sounds", eventElem.attribute( "url" ) ) );
+ soundConf.writeEntry( "presentation", soundConf.readNumEntry( "presentation" ) | 1 );
+ }
+ else if ( object == "twin" )
+ {
+ twinSoundConf.setGroup( eventElem.attribute( "name" ) );
+ twinSoundConf.writeEntry( "soundfile", unprocessFilePath( "sounds", eventElem.attribute( "url" ) ) );
+ twinSoundConf.writeEntry( "presentation", soundConf.readNumEntry( "presentation" ) | 1 );
+ }
+ }
+
+ soundConf.sync();
+ twinSoundConf.sync();
+ client->send("knotify", "", "reconfigure()", TQString(""));
+ // TODO signal twin sounds change?
+ }
+
+ // 5. Colors
+ TQDomElement colorsElem = m_dom.elementsByTagName( "colors" ).item( 0 ).toElement();
+
+ if ( !colorsElem.isNull() )
+ {
+ TQDomNodeList colorList = colorsElem.childNodes();
+ TDEConfig * colorConf = TDEGlobal::config();
+
+ TQString sCurrentScheme = locateLocal("data", "tdedisplay/color-schemes/thememgr.kcsrc");
+ KSimpleConfig *colorScheme = new KSimpleConfig( sCurrentScheme );
+ colorScheme->setGroup("Color Scheme" );
+
+ for ( uint i = 0; i < colorList.count(); i++ )
+ {
+ TQDomElement colorElem = colorList.item( i ).toElement();
+ TQString object = colorElem.attribute( "object" );
+ if ( object == "global" )
+ colorConf->setGroup( "General" );
+ else if ( object == "twin" )
+ colorConf->setGroup( "WM" );
+
+ TQString colName = colorElem.tagName();
+ TQColor curColor = TQColor( colorElem.attribute( "rgb" ) );
+ colorConf->writeEntry( colName, curColor, true, true ); // kdeglobals
+ colorScheme->writeEntry( colName, curColor ); // thememgr.kcsrc
+ }
+
+ colorConf->setGroup( "KDE" );
+ colorConf->writeEntry( "colorScheme", "thememgr.kcsrc", true, true );
+ colorConf->writeEntry( "contrast", colorsElem.attribute( "contrast", "7" ), true, true );
+ colorScheme->writeEntry( "contrast", colorsElem.attribute( "contrast", "7" ) );
+ colorConf->sync();
+ delete colorScheme;
+
+ KIPC::sendMessageAll( KIPC::PaletteChanged );
+ }
+
+ // 6.Cursors
+ TQDomElement cursorsElem = m_dom.elementsByTagName( "cursors" ).item( 0 ).toElement();
+
+ if ( !cursorsElem.isNull() )
+ {
+ TDEConfig mouseConf( "kcminputrc" );
+ mouseConf.setGroup( "Mouse" );
+ mouseConf.writeEntry( "cursorTheme", cursorsElem.attribute( "name" ));
+ // FIXME is there a way to notify KDE of cursor changes?
+ }
+
+ // 7. KWin
+ TQDomElement wmElem = m_dom.elementsByTagName( "wm" ).item( 0 ).toElement();
+
+ if ( !wmElem.isNull() )
+ {
+ TDEConfig twinConf( "twinrc" );
+ twinConf.setGroup( "Style" );
+ TQString type = wmElem.attribute( "type" );
+ if ( type == "builtin" ) {
+ twinConf.writeEntry( "PluginLib", wmElem.attribute( "name" ) );
+ }
+ //else // TODO support custom themes
+ TQDomNodeList buttons = wmElem.elementsByTagName ("buttons");
+ if ( buttons.count() > 0 )
+ {
+ twinConf.writeEntry( "CustomButtonPositions", true );
+ if (getProperty( wmElem, "buttons", "left" ) != TQString::null) twinConf.writeEntry( "ButtonsOnLeft", getProperty( wmElem, "buttons", "left" ) );
+ if (getProperty( wmElem, "buttons", "right" ) != TQString::null) twinConf.writeEntry( "ButtonsOnRight", getProperty( wmElem, "buttons", "right" ) );
+ }
+ else
+ {
+ twinConf.writeEntry( "CustomButtonPositions", false );
+ }
+ if (getProperty( wmElem, "border", "size" ) != TQString::null) twinConf.writeEntry( "BorderSize", getProperty( wmElem, "border", "size" ) );
+
+ twinConf.sync();
+ client->send( "twin", "", "reconfigure()", TQString("") );
+ }
+
+ // 8. Konqueror
+ TQDomElement konqElem = m_dom.elementsByTagName( "konqueror" ).item( 0 ).toElement();
+
+ if ( !konqElem.isNull() )
+ {
+ TDEConfig konqConf( "konquerorrc" );
+ konqConf.setGroup( "Settings" );
+ if (getProperty( konqElem, "wallpaper", "url" ) != TQString::null) konqConf.writeEntry( "BgImage", unprocessFilePath( "konqueror", getProperty( konqElem, "wallpaper", "url" ) ) );
+ if (getProperty( konqElem, "bgcolor", "rgb" ) != TQString::null) konqConf.writeEntry( "BgColor", TQColor( getProperty( konqElem, "bgcolor", "rgb" ) ) );
+
+ konqConf.sync();
+ client->send("konqueror*", "KonquerorIface", "reparseConfiguration()", TQString("")); // FIXME seems not to work :(
+ }
+
+ // 9. Kicker
+ TQDomElement panelElem = m_dom.elementsByTagName( "panel" ).item( 0 ).toElement();
+
+ if ( !panelElem.isNull() )
+ {
+ TDEConfig kickerConf( "kickerrc" );
+ kickerConf.setGroup( "General" );
+ TQString kickerBgUrl = getProperty( panelElem, "background", "url" );
+ if ( !kickerBgUrl.isEmpty() )
+ {
+ kickerConf.writeEntry( "UseBackgroundTheme", true );
+ if (getProperty( panelElem, "panel", kickerBgUrl ) != TQString::null) kickerConf.writeEntry( "BackgroundTheme", unprocessFilePath( "panel", kickerBgUrl ) );
+ if (getProperty( panelElem, "background", "colorize" ) != TQString::null) kickerConf.writeEntry( "ColorizeBackground", static_cast<bool>( getProperty( panelElem, "background", "colorize" ).toUInt() ) );
+ }
+ if (getProperty( panelElem, "transparent", "value" ) != TQString::null) kickerConf.writeEntry( "Transparent", static_cast<bool>( getProperty( panelElem, "transparent", "value" ).toUInt() ) );
+ if (getProperty( panelElem, "position", "value" ) != TQString::null) kickerConf.writeEntry( "Position", static_cast<int> (getProperty( panelElem, "position", "value" ).toUInt() ));
+ if (getProperty( panelElem, "showlefthidebutton", "value" ) != TQString::null) kickerConf.writeEntry( "ShowLeftHideButton", static_cast<bool>( getProperty( panelElem, "showlefthidebutton", "value").toInt()));
+ if (getProperty( panelElem, "showrighthidebutton", "value" ) != TQString::null) kickerConf.writeEntry( "ShowRightHideButton", static_cast<bool>( getProperty( panelElem, "showrighthidebutton", "value").toInt()));
+
+ kickerConf.sync();
+ client->send("kicker", "Panel", "configure()", TQString(""));
+ }
+
+ // 10. Widget style
+ TQDomElement widgetsElem = m_dom.elementsByTagName( "widgets" ).item( 0 ).toElement();
+
+ if ( !widgetsElem.isNull() )
+ {
+ TDEConfig * widgetConf = TDEGlobal::config();
+ widgetConf->setGroup( "General" );
+ widgetConf->writeEntry( "widgetStyle", widgetsElem.attribute( "name" ), true, true );
+ widgetConf->sync();
+ KIPC::sendMessageAll( KIPC::StyleChanged );
+ }
+
+ // 12. Fonts
+ TQDomElement fontsElem = m_dom.elementsByTagName( "fonts" ).item( 0 ).toElement();
+ if ( !fontsElem.isNull() )
+ {
+ TDEConfig * fontsConf = TDEGlobal::config();
+ TDEConfig * kde1xConf = new KSimpleConfig( TQDir::homeDirPath() + "/.tderc" );
+ kde1xConf->setGroup( "General" );
+
+ TQDomNodeList fontList = fontsElem.childNodes();
+ for ( uint i = 0; i < fontList.count(); i++ )
+ {
+ TQDomElement fontElem = fontList.item( i ).toElement();
+ TQString fontName = fontElem.tagName();
+ TQString fontValue = fontElem.attribute( "value" );
+ TQString fontObject = fontElem.attribute( "object" );
+
+ if ( fontObject == "FMSettings" ) {
+ desktopConf.setGroup( fontObject );
+ desktopConf.writeEntry( fontName, fontValue, true, true );
+ desktopConf.sync();
+ }
+ else {
+ fontsConf->setGroup( fontObject );
+ fontsConf->writeEntry( fontName, fontValue, true, true );
+ }
+ kde1xConf->writeEntry( fontName, fontValue, true, true );
+ }
+
+ fontsConf->sync();
+ kde1xConf->sync();
+ KIPC::sendMessageAll( KIPC::FontChanged );
+ }
+
+}
+
+bool KTheme::remove( const TQString & name )
+{
+ kdDebug() << "Going to remove theme: " << name << endl;
+ return TDEIO::NetAccess::del( TDEGlobal::dirs()->saveLocation( "themes", name + "/" ), 0L );
+}
+
+void KTheme::setProperty( const TQString & name, const TQString & value, TQDomElement parent )
+{
+ TQDomElement tmp = m_dom.createElement( name );
+ tmp.setAttribute( "value", value );
+ parent.appendChild( tmp );
+}
+
+TQString KTheme::getProperty( const TQString & name ) const
+{
+ TQDomNodeList _list = m_dom.elementsByTagName( name );
+ if ( _list.count() != 0 )
+ return _list.item( 0 ).toElement().attribute( "value" );
+ else
+ {
+ kdWarning() << "Found no such property: " << name << endl;
+ return TQString::null;
+ }
+}
+
+TQString KTheme::getProperty( TQDomElement parent, const TQString & tag,
+ const TQString & attr ) const
+{
+ TQDomNodeList _list = parent.elementsByTagName( tag );
+
+ if ( _list.count() != 0 )
+ return _list.item( 0 ).toElement().attribute( attr );
+ else
+ {
+ kdWarning() << TQString( "No such property found: %1->%2->%3" )
+ .arg( parent.tagName() ).arg( tag ).arg( attr ) << endl;
+ return TQString::null;
+ }
+}
+
+void KTheme::createIconElems( const TQString & group, const TQString & object,
+ TQDomElement parent, TDEConfig * cfg )
+{
+ cfg->setGroup( group );
+ TQStringList elemNames;
+ elemNames << "Animated" << "DoublePixels" << "Size"
+ << "ActiveColor" << "ActiveColor2" << "ActiveEffect"
+ << "ActiveSemiTransparent" << "ActiveValue"
+ << "DefaultColor" << "DefaultColor2" << "DefaultEffect"
+ << "DefaultSemiTransparent" << "DefaultValue"
+ << "DisabledColor" << "DisabledColor2" << "DisabledEffect"
+ << "DisabledSemiTransparent" << "DisabledValue";
+ for ( TQStringList::ConstIterator it = elemNames.begin(); it != elemNames.end(); ++it ) {
+ if ( (*it).contains( "Color" ) )
+ createColorElem( *it, object, parent, cfg );
+ else
+ {
+ TQDomElement tmpCol = m_dom.createElement( *it );
+ tmpCol.setAttribute( "object", object );
+
+ if ( (*it).contains( "Value" ) || *it == "Size" )
+ tmpCol.setAttribute( "value", cfg->readNumEntry( *it, 1 ) );
+ else if ( (*it).contains( "DisabledEffect" ) )
+ tmpCol.setAttribute( "name", cfg->readEntry( *it, "togray" ) );
+ else if ( (*it).contains( "Effect" ) )
+ tmpCol.setAttribute( "name", cfg->readEntry( *it, "none" ) );
+ else
+ tmpCol.setAttribute( "value", cfg->readBoolEntry( *it, false ) );
+ parent.appendChild( tmpCol );
+ }
+ }
+}
+
+void KTheme::createColorElem( const TQString & name, const TQString & object,
+ TQDomElement parent, TDEConfig * cfg )
+{
+ TQColor color = cfg->readColorEntry( name );
+ if ( color.isValid() )
+ {
+ TQDomElement tmpCol = m_dom.createElement( name );
+ tmpCol.setAttribute( "rgb", color.name() );
+ tmpCol.setAttribute( "object", object );
+ parent.appendChild( tmpCol );
+ }
+}
+
+void KTheme::createSoundList( const TQStringList & events, const TQString & object,
+ TQDomElement parent, TDEConfig * cfg )
+{
+ for ( TQStringList::ConstIterator it = events.begin(); it != events.end(); ++it )
+ {
+ TQString group = ( *it );
+ if ( cfg->hasGroup( group ) )
+ {
+ cfg->setGroup( group );
+ TQString soundURL = cfg->readPathEntry( "soundfile" );
+ int pres = cfg->readNumEntry( "presentation", 0 );
+ if ( !soundURL.isEmpty() && ( ( pres & 1 ) == 1 ) )
+ {
+ TQDomElement eventElem = m_dom.createElement( "event" );
+ eventElem.setAttribute( "object", object );
+ eventElem.setAttribute( "name", group );
+ eventElem.setAttribute( "url", processFilePath( "sounds", soundURL ) );
+ parent.appendChild( eventElem );
+ }
+ }
+ }
+}
+
+TQString KTheme::processFilePath( const TQString & section, const TQString & path )
+{
+ TQFileInfo fi( path );
+
+ if ( fi.isRelative() )
+ fi.setFile( findResource( section, path ) );
+
+ kdDebug() << "Processing file: " << fi.absFilePath() << ", " << fi.fileName() << endl;
+
+ if ( section == "desktop" )
+ {
+ if ( copyFile( fi.absFilePath(), m_kgd->saveLocation( "themes", m_name + "/wallpapers/desktop/" ) + "/" + fi.fileName() ) )
+ return "theme:/wallpapers/desktop/" + fi.fileName();
+ }
+ else if ( section == "sounds" )
+ {
+ if ( copyFile( fi.absFilePath(), m_kgd->saveLocation( "themes", m_name + "/sounds/" ) + "/" + fi.fileName() ) )
+ return "theme:/sounds/" + fi.fileName();
+ }
+ else if ( section == "konqueror" )
+ {
+ if ( copyFile( fi.absFilePath(), m_kgd->saveLocation( "themes", m_name + "/wallpapers/konqueror/" ) + "/" + fi.fileName() ) )
+ return "theme:/wallpapers/konqueror/" + fi.fileName();
+ }
+ else if ( section == "panel" )
+ {
+ if ( copyFile( fi.absFilePath(), m_kgd->saveLocation( "themes", m_name + "/wallpapers/panel/" ) + "/" + fi.fileName() ) )
+ return "theme:/wallpapers/panel/" + fi.fileName();
+ }
+ else
+ kdWarning() << "Unsupported theme resource type" << endl;
+
+ return TQString::null; // an error occured or the resource doesn't exist
+}
+
+TQString KTheme::unprocessFilePath( const TQString & section, TQString path )
+{
+ if ( path.startsWith( "theme:/" ) )
+ return path.replace( TQRegExp( "^theme:/" ), m_kgd->findResourceDir( "themes", m_name + "/" + m_name + ".xml") + m_name + "/" );
+
+ if ( TQFile::exists( path ) )
+ return path;
+ else // try to find it in the system
+ return findResource( section, path );
+}
+
+void KTheme::setAuthor( const TQString & author )
+{
+ setProperty( "author", author, m_general );
+}
+
+void KTheme::setEmail( const TQString & email )
+{
+ setProperty( "email", email, m_general );
+}
+
+void KTheme::setHomepage( const TQString & homepage )
+{
+ setProperty( "homepage", homepage, m_general );
+}
+
+void KTheme::setComment( const TQString & comment )
+{
+ setProperty( "comment", comment, m_general );
+}
+
+void KTheme::setVersion( const TQString & version )
+{
+ setProperty( "version", version, m_general );
+}
+
+void KTheme::addPreview()
+{
+ TQString file = m_kgd->saveLocation( "themes", m_name + "/" ) + m_name + ".preview.png";
+ kdDebug() << "Adding preview: " << file << endl;
+ TQPixmap snapshot = TQPixmap::grabWindow( tqt_xrootwin() );
+ snapshot.save( file, "PNG" );
+}
+
+bool KTheme::copyFile( const TQString & from, const TQString & to )
+{
+ // we overwrite b/c of restoring the "original" theme
+ return TDEIO::NetAccess::file_copy( from, to, -1, true /*overwrite*/ );
+}
+
+TQString KTheme::findResource( const TQString & section, const TQString & path )
+{
+ if ( section == "desktop" )
+ return m_kgd->findResource( "wallpaper", path );
+ else if ( section == "sounds" )
+ return m_kgd->findResource( "sound", path );
+ else if ( section == "konqueror" )
+ return m_kgd->findResource( "data", "konqueror/tiles/" + path );
+ else if ( section == "panel" )
+ return m_kgd->findResource( "data", "kicker/wallpapers/" + path );
+ else
+ {
+ kdWarning() << "Requested unknown resource: " << section << endl;
+ return TQString::null;
+ }
+}
diff --git a/kcontrol/kthememanager/ktheme.h b/kcontrol/kthememanager/ktheme.h
new file mode 100644
index 000000000..11fa6b056
--- /dev/null
+++ b/kcontrol/kthememanager/ktheme.h
@@ -0,0 +1,224 @@
+// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*-
+/* Copyright (C) 2003 Lukas Tinkl <[email protected]>
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef KTHEME_H
+#define KTHEME_H
+
+#include <tqdom.h>
+#include <tqguardedptr.h>
+#include <tqstring.h>
+#include <tqstringlist.h>
+#include <tqwidget.h>
+
+#include <kurl.h>
+
+class TDEStandardDirs;
+class TDEConfig;
+
+/// defines the syntax version used by the XML
+#define SYNTAX_VERSION 1
+
+/**
+ * The base class representing a KDE theme. The data are stored internally
+ * in a DOM tree and accessed using the member methods.
+ *
+ * @brief Class representing a theme
+ * @author Lukas Tinkl <[email protected]>
+ */
+class KTheme
+{
+public:
+ /**
+ * Constructs KTheme using an installed theme
+ * @param xmlFile The theme's XML file
+ */
+ KTheme( TQWidget *parent, const TQString & xmlFile );
+
+ /**
+ * Constructs an empty theme, to be used with
+ * #createYourself()
+ * @param create Whether to start the DOM tree
+ */
+ KTheme( TQWidget *parent, bool create = false );
+
+ /**
+ * Destructor
+ */
+ ~KTheme();
+
+ /**
+ * Download from @p url, unpack the tarball and load the theme definition
+ *
+ * @return true on success
+ */
+ bool load( const KURL & url );
+
+ /**
+ * Creates a snapshot of the current configuration in the work directory
+ * (used for getting the defaults or to create a new user theme).
+ * @param pack Whether to also pack the theme in tar.gz format
+ * @return The path to the newly created tarball with theme (if @p pack == true)
+ */
+ TQString createYourself( bool pack = false );
+
+ /**
+ * Apply the theme to the system, ie. set the config variables and
+ * adjust file paths
+ */
+ void apply();
+
+ /**
+ * Uninstall the theme from the system
+ * @param name The name of the theme
+ * @return true on success
+ */
+ static bool remove( const TQString & name );
+
+ /**
+ * @return the theme name
+ */
+ TQString name() const { return m_name; }
+ /**
+ * Set the theme name
+ */
+ void setName( const TQString & name );
+
+ TQString author() const {
+ return getProperty( "author" );
+ }
+ void setAuthor( const TQString & author );
+
+ TQString email() const {
+ return getProperty( "email" );
+ }
+ void setEmail( const TQString & email );
+
+ TQString homepage() const {
+ return getProperty( "homepage" );
+ }
+ void setHomepage( const TQString & homepage );
+
+ TQString comment() const {
+ return getProperty( "comment" );
+ }
+ void setComment ( const TQString & comment );
+
+ TQString version() const {
+ return getProperty( "version" );
+ }
+ void setVersion ( const TQString & version );
+
+ /**
+ * Creates a preview file called theme_name.preview.png
+ * (i.e. takes a snapshot of the current desktop)
+ */
+ void addPreview();
+
+private:
+ /**
+ * Create a property with @p name, value @p value
+ * and append it to @p parent element
+ */
+ void setProperty( const TQString & name,
+ const TQString & value,
+ TQDomElement parent );
+ /**
+ * Get a simple property from the "general" section of the DOM tree
+ */
+ TQString getProperty( const TQString & name ) const;
+
+ /**
+ * Get a property from the DOM tree, based on:
+ * @param parent Parent tag
+ * @param tag From the this tag
+ * @param attr From this attribute
+ */
+ TQString getProperty( TQDomElement parent, const TQString & tag,
+ const TQString & attr ) const;
+
+ /**
+ * Creates a list of "icon" elements based on:
+ * @param group The group in the TDEConfig object @p cfg
+ * @param object Specifier (similiar, but not identical to @p group)
+ * @param parent Parent element to append to
+ * @param cfg The TDEConfig object to work with
+ */
+ void createIconElems( const TQString & group, const TQString & object,
+ TQDomElement parent, TDEConfig * cfg );
+
+ /**
+ * Creates a color DOM element @p name, with a specifier @p object,
+ * appends it to @p parent; used when creating themes
+ * @param cfg The TDEConfig object to work with
+ */
+ void createColorElem( const TQString & name, const TQString & object,
+ TQDomElement parent, TDEConfig * cfg );
+ /**
+ * Creates a list of "event" elements based on:
+ * @param events The list of events to work on
+ * @param object Specifier (currently "global" or "twin")
+ * @param parent Parent element to append to
+ * @param cfg The TDEConfig object to work with
+ */
+ void createSoundList( const TQStringList & events, const TQString & object,
+ TQDomElement parent, TDEConfig * cfg );
+
+ /**
+ * Tries to find out absolute path to a resource and copy it to the theme's temp dir;
+ * used when creating themes
+ * @param section The theme section to work on, corresponds to toplevel XML tags
+ * @param path The original path, relative or absolute
+ * @return an internal path suitable for writing into the XML file or TQString::null
+ * in case the resource couldn't be found
+ */
+ TQString processFilePath( const TQString & section, const TQString & path );
+
+ /**
+ * Converts an internal theme:/ representation of a resource
+ * to a real path
+ */
+ TQString unprocessFilePath( const TQString & section, TQString path );
+
+ /**
+ * Wrapper around TDEIO::NetAccess::file_copy
+ */
+ bool copyFile( const TQString & from, const TQString & to );
+
+ /**
+ * Wrapper around TDEGlobal::dirs()->findResource()
+ * @param section Section to work on (desktop, sounds, panel etc)
+ * @param path The file to find
+ */
+ TQString findResource( const TQString & section, const TQString & path );
+
+ /// name of the theme
+ TQString m_name;
+
+ /// DOM holding the theme
+ TQDomDocument m_dom;
+ /// the DOM root element
+ TQDomElement m_root;
+ /// "general" section
+ TQDomElement m_general;
+
+ TDEStandardDirs * m_kgd;
+
+ TQGuardedPtr<TQWidget> m_parent;
+};
+
+#endif
diff --git a/kcontrol/kthememanager/kthemedlg.ui b/kcontrol/kthememanager/kthemedlg.ui
new file mode 100644
index 000000000..68e176eef
--- /dev/null
+++ b/kcontrol/kthememanager/kthemedlg.ui
@@ -0,0 +1,518 @@
+<!DOCTYPE UI><UI version="3.3" stdsetdef="1">
+<class>KThemeDlg</class>
+<author>Lukas Tinkl &lt;[email protected]&gt;</author>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>KThemeDlg</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>687</width>
+ <height>382</height>
+ </rect>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>3</hsizetype>
+ <vsizetype>3</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <property name="margin">
+ <number>0</number>
+ </property>
+ <widget class="TQLayoutWidget" row="0" column="0">
+ <property name="name">
+ <cstring>layout2</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>NoFrame</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Plain</enum>
+ </property>
+ <property name="text">
+ <string>Choose your visual TDE theme:</string>
+ </property>
+ </widget>
+ <spacer>
+ <property name="name">
+ <cstring>spacer2</cstring>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ <property name="sizeType">
+ <enum>MinimumExpanding</enum>
+ </property>
+ <property name="sizeHint">
+ <size>
+ <width>170</width>
+ <height>20</height>
+ </size>
+ </property>
+ </spacer>
+ <widget class="KURLLabel">
+ <property name="name">
+ <cstring>lbGet</cstring>
+ </property>
+ <property name="text">
+ <string>Get new themes...</string>
+ </property>
+ <property name="url" stdset="0">
+ <string>http://themes.kde.org</string>
+ </property>
+ <property name="tipText">
+ <string>Go to the TDE themes website</string>
+ </property>
+ <property name="useTips">
+ <bool>true</bool>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ <widget class="TQLayoutWidget" row="1" column="0">
+ <property name="name">
+ <cstring>layout1</cstring>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="1" rowspan="4" colspan="1">
+ <property name="name">
+ <cstring>lbPreview</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>5</vsizetype>
+ <horstretch>1</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="frameShape">
+ <enum>Box</enum>
+ </property>
+ <property name="alignment">
+ <set>AlignCenter</set>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="2" column="0">
+ <property name="name">
+ <cstring>btnRemove</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Remove Theme</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="3" column="0">
+ <property name="name">
+ <cstring>btnCreate</cstring>
+ </property>
+ <property name="text">
+ <string>Create &amp;New Theme...</string>
+ </property>
+ </widget>
+ <widget class="TQPushButton" row="1" column="0">
+ <property name="name">
+ <cstring>btnInstall</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Install New Theme...</string>
+ </property>
+ </widget>
+ <widget class="TQListView" row="0" column="0">
+ <column>
+ <property name="text">
+ <string>Theme</string>
+ </property>
+ <property name="clickable">
+ <bool>true</bool>
+ </property>
+ <property name="resizable">
+ <bool>false</bool>
+ </property>
+ </column>
+ <property name="name">
+ <cstring>lvThemes</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>7</hsizetype>
+ <vsizetype>7</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="showSortIndicator">
+ <bool>true</bool>
+ </property>
+ <property name="resizeMode">
+ <enum>AllColumns</enum>
+ </property>
+ </widget>
+ </grid>
+ </widget>
+ <widget class="Line" row="2" column="0">
+ <property name="name">
+ <cstring>line1</cstring>
+ </property>
+ <property name="frameShape">
+ <enum>HLine</enum>
+ </property>
+ <property name="frameShadow">
+ <enum>Sunken</enum>
+ </property>
+ <property name="orientation">
+ <enum>Horizontal</enum>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel1_2</cstring>
+ </property>
+ <property name="text">
+ <string>Customize your theme:</string>
+ </property>
+ </widget>
+ <widget class="TQLayoutWidget" row="4" column="0">
+ <property name="name">
+ <cstring>layout4</cstring>
+ </property>
+ <hbox>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQToolButton">
+ <property name="name">
+ <cstring>btnBackground</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="focusPolicy">
+ <enum>TabFocus</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="usesTextLabel">
+ <bool>true</bool>
+ </property>
+ <property name="textLabel">
+ <string>Background</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Customize the desktop background</string>
+ </property>
+ </widget>
+ <widget class="TQToolButton">
+ <property name="name">
+ <cstring>btnColors</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="focusPolicy">
+ <enum>TabFocus</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="usesTextLabel">
+ <bool>true</bool>
+ </property>
+ <property name="textLabel">
+ <string>Colors</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Customize colors</string>
+ </property>
+ </widget>
+ <widget class="TQToolButton">
+ <property name="name">
+ <cstring>btnStyle</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="focusPolicy">
+ <enum>TabFocus</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="usesTextLabel">
+ <bool>true</bool>
+ </property>
+ <property name="textLabel">
+ <string>Style</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Customize the widget style</string>
+ </property>
+ </widget>
+ <widget class="TQToolButton">
+ <property name="name">
+ <cstring>btnIcons</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="focusPolicy">
+ <enum>TabFocus</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="usesTextLabel">
+ <bool>true</bool>
+ </property>
+ <property name="textLabel">
+ <string>Icons</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Customize the icon theme</string>
+ </property>
+ </widget>
+ <widget class="TQToolButton">
+ <property name="name">
+ <cstring>btnFonts</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="focusPolicy">
+ <enum>TabFocus</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="usesTextLabel">
+ <bool>true</bool>
+ </property>
+ <property name="textLabel">
+ <string>Fonts</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Customize the font theme</string>
+ </property>
+ </widget>
+ <widget class="TQToolButton">
+ <property name="name">
+ <cstring>btnSaver</cstring>
+ </property>
+ <property name="sizePolicy">
+ <sizepolicy>
+ <hsizetype>5</hsizetype>
+ <vsizetype>0</vsizetype>
+ <horstretch>0</horstretch>
+ <verstretch>0</verstretch>
+ </sizepolicy>
+ </property>
+ <property name="minimumSize">
+ <size>
+ <width>80</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="maximumSize">
+ <size>
+ <width>32767</width>
+ <height>60</height>
+ </size>
+ </property>
+ <property name="focusPolicy">
+ <enum>TabFocus</enum>
+ </property>
+ <property name="text">
+ <string></string>
+ </property>
+ <property name="usesTextLabel">
+ <bool>true</bool>
+ </property>
+ <property name="textLabel">
+ <string>Screen Saver</string>
+ </property>
+ <property name="toolTip" stdset="0">
+ <string>Customize the screen saver</string>
+ </property>
+ </widget>
+ </hbox>
+ </widget>
+ </grid>
+</widget>
+<connections>
+ <connection>
+ <sender>lbGet</sender>
+ <signal>leftClickedURL(const TQString&amp;)</signal>
+ <receiver>KThemeDlg</receiver>
+ <slot>startKonqui(const TQString&amp;)</slot>
+ </connection>
+ <connection>
+ <sender>btnBackground</sender>
+ <signal>clicked()</signal>
+ <receiver>KThemeDlg</receiver>
+ <slot>startBackground()</slot>
+ </connection>
+ <connection>
+ <sender>btnColors</sender>
+ <signal>clicked()</signal>
+ <receiver>KThemeDlg</receiver>
+ <slot>startColors()</slot>
+ </connection>
+ <connection>
+ <sender>btnStyle</sender>
+ <signal>clicked()</signal>
+ <receiver>KThemeDlg</receiver>
+ <slot>startStyle()</slot>
+ </connection>
+ <connection>
+ <sender>btnIcons</sender>
+ <signal>clicked()</signal>
+ <receiver>KThemeDlg</receiver>
+ <slot>startIcons()</slot>
+ </connection>
+ <connection>
+ <sender>btnFonts</sender>
+ <signal>clicked()</signal>
+ <receiver>KThemeDlg</receiver>
+ <slot>startFonts()</slot>
+ </connection>
+ <connection>
+ <sender>btnSaver</sender>
+ <signal>clicked()</signal>
+ <receiver>KThemeDlg</receiver>
+ <slot>startSaver()</slot>
+ </connection>
+</connections>
+<tabstops>
+ <tabstop>lvThemes</tabstop>
+ <tabstop>btnInstall</tabstop>
+ <tabstop>btnRemove</tabstop>
+ <tabstop>btnCreate</tabstop>
+ <tabstop>btnBackground</tabstop>
+ <tabstop>btnColors</tabstop>
+ <tabstop>btnStyle</tabstop>
+ <tabstop>btnIcons</tabstop>
+ <tabstop>btnFonts</tabstop>
+ <tabstop>btnSaver</tabstop>
+</tabstops>
+<includes>
+ <include location="local" impldecl="in implementation">kthemedlg.ui.h</include>
+</includes>
+<Q_SLOTS>
+ <slot specifier="non virtual">startKonqui( const TQString &amp; url )</slot>
+ <slot specifier="non virtual">startBackground()</slot>
+ <slot specifier="non virtual">startColors()</slot>
+ <slot specifier="non virtual">startStyle()</slot>
+ <slot specifier="non virtual">startIcons()</slot>
+ <slot specifier="non virtual">startFonts()</slot>
+ <slot specifier="non virtual">startSaver()</slot>
+</Q_SLOTS>
+<layoutdefaults spacing="6" margin="11"/>
+<includehints>
+ <includehint>kurllabel.h</includehint>
+</includehints>
+</UI>
diff --git a/kcontrol/kthememanager/kthemedlg.ui.h b/kcontrol/kthememanager/kthemedlg.ui.h
new file mode 100644
index 000000000..78e0e48e1
--- /dev/null
+++ b/kcontrol/kthememanager/kthemedlg.ui.h
@@ -0,0 +1,49 @@
+/****************************************************************************
+** ui.h extension file, included from the uic-generated form implementation.
+**
+** If you wish to add, delete or rename functions or slots use
+** Qt Designer which will update this file, preserving your code. Create an
+** init() function in place of a constructor, and a destroy() function in
+** place of a destructor.
+*****************************************************************************/
+#include <krun.h>
+
+void KThemeDlg::startKonqui( const TQString & url )
+{
+ (void) new KRun(url);
+}
+
+
+void KThemeDlg::startBackground()
+{
+ KRun::runCommand("tdecmshell tde-background");
+}
+
+
+void KThemeDlg::startColors()
+{
+ KRun::runCommand("tdecmshell tde-colors");
+}
+
+
+void KThemeDlg::startStyle()
+{
+ KRun::runCommand("tdecmshell tde-style");
+}
+
+
+void KThemeDlg::startIcons()
+{
+ KRun::runCommand("tdecmshell tde-icons");
+}
+
+void KThemeDlg::startFonts()
+{
+ KRun::runCommand("tdecmshell tde-fonts");
+}
+
+
+void KThemeDlg::startSaver()
+{
+ KRun::runCommand("tdecmshell tde-screensaver");
+}
diff --git a/kcontrol/kthememanager/kthememanager.cpp b/kcontrol/kthememanager/kthememanager.cpp
new file mode 100644
index 000000000..969e377ce
--- /dev/null
+++ b/kcontrol/kthememanager/kthememanager.cpp
@@ -0,0 +1,425 @@
+// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*-
+/* Copyright (C) 2003 Lukas Tinkl <[email protected]>
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <tqlabel.h>
+#include <tqlayout.h>
+#include <tqpixmap.h>
+#include <tqpushbutton.h>
+#include <tqtoolbutton.h>
+#include <tqtooltip.h>
+
+#include <tdeaboutdata.h>
+#include <tdeapplication.h>
+#include <kdebug.h>
+#include <kdialog.h>
+#include <tdeemailsettings.h>
+#include <tdefiledialog.h>
+#include <tdeglobal.h>
+#include <kiconloader.h>
+#include <tdelistview.h>
+#include <tdelocale.h>
+#include <tdemessagebox.h>
+#include <kservicegroup.h>
+#include <kstandarddirs.h>
+#include <kurldrag.h>
+
+#include "kthememanager.h"
+#include "knewthemedlg.h"
+#include "config.h"
+
+kthememanager::kthememanager( TQWidget *parent, const char *name )
+ : TDECModule( parent, name ), m_theme( 0 ), m_origTheme( 0 )
+{
+
+ TDEAboutData *about = new TDEAboutData("kthememanager", I18N_NOOP("TDE Theme Manager"),
+ "0.4", I18N_NOOP("This control module handles installing, removing and "
+ "creating visual TDE themes."),
+ TDEAboutData::License_GPL, "(c) 2003, 2004, 2006 Lukáš Tinkl", 0,
+ "http://developer.kde.org/~lukas/kthememanager");
+ setAboutData( about );
+
+ setQuickHelp( i18n("This control module handles installing, removing and "
+ "creating visual TDE themes."));
+
+ setButtons( TDECModule::Default|TDECModule::Apply|TDECModule::Help );
+
+ setAcceptDrops( true );
+ init();
+
+ TQBoxLayout *top = new TQVBoxLayout(this, 0, KDialog::spacingHint());
+
+ dlg = new KThemeDlg(this);
+ top->addWidget( dlg );
+
+ dlg->lvThemes->setColumnWidthMode( 0, TQListView::Maximum );
+
+ connect( ( TQObject * )dlg->btnInstall, TQT_SIGNAL( clicked() ),
+ this, TQT_SLOT( slotInstallTheme() ) );
+
+ connect( ( TQObject * )dlg->btnRemove, TQT_SIGNAL( clicked() ),
+ this, TQT_SLOT( slotRemoveTheme() ) );
+
+ connect( ( TQObject * )dlg->btnCreate, TQT_SIGNAL( clicked() ),
+ this, TQT_SLOT( slotCreateTheme() ) );
+
+ connect( ( TQObject * )dlg->lvThemes, TQT_SIGNAL( clicked( TQListViewItem * ) ),
+ this, TQT_SLOT( slotThemeChanged( TQListViewItem * ) ) );
+
+ connect( ( TQObject * )dlg->lvThemes, TQT_SIGNAL( currentChanged( TQListViewItem * ) ),
+ this, TQT_SLOT( slotThemeChanged( TQListViewItem * ) ) );
+
+ connect( this, TQT_SIGNAL( filesDropped( const KURL::List& ) ),
+ this, TQT_SLOT( updateButton() ) );
+
+ connect( ( TQObject * )dlg->lvThemes, TQT_SIGNAL( clicked( TQListViewItem * ) ),
+ this, TQT_SLOT( updateButton() ) );
+
+ m_origTheme = new KTheme( this, true ); // stores the defaults to get back to
+ m_origTheme->setName( ORIGINAL_THEME );
+ m_origTheme->createYourself();
+
+ load();
+ queryLNFModules();
+ updateButton();
+}
+
+kthememanager::~kthememanager()
+{
+ delete m_theme;
+ delete m_origTheme;
+}
+
+void kthememanager::init()
+{
+ TDEGlobal::dirs()->addResourceType( "themes", TDEStandardDirs::kde_default("data") +
+ "kthememanager/themes/" );
+}
+
+void kthememanager::updateButton()
+{
+ TQListViewItem * cur = dlg->lvThemes->currentItem();
+ bool enable = (cur != 0);
+ if (enable) {
+ enable = TQFile(TDEGlobal::dirs()->saveLocation( "themes", cur->text( 0 ) + "/"+ cur->text( 0 )+ ".xml" ,false)).exists() ;
+ }
+ dlg->btnRemove->setEnabled(enable);
+}
+
+void kthememanager::load()
+{
+ load( false );
+}
+
+void kthememanager::load(bool useDefaults)
+{
+ listThemes();
+
+ // Load the current theme name
+ TDEConfig conf("kcmthememanagerrc", false, false);
+
+ conf.setReadDefaults( useDefaults );
+
+ conf.setGroup( "General" );
+ TQString themeName = conf.readEntry( "CurrentTheme" );
+ TQListViewItem * cur = dlg->lvThemes->findItem( themeName, 0 );
+ if ( cur )
+ {
+ dlg->lvThemes->setSelected( cur, true );
+ dlg->lvThemes->ensureItemVisible( cur );
+ slotThemeChanged( cur );
+ }
+
+ emit changed( true );
+}
+
+void kthememanager::defaults()
+{
+ load( true );
+}
+
+void kthememanager::save()
+{
+ TQListViewItem * cur = dlg->lvThemes->currentItem();
+
+ if ( cur )
+ {
+ TQString themeName = cur->text( 0 );
+
+ m_theme = new KTheme( this, TDEGlobal::dirs()->findResource( "themes", themeName + "/" + themeName + ".xml") );
+ m_theme->apply();
+
+ // Save the current theme name
+ TDEConfig conf("kcmthememanagerrc", false, false);
+ conf.setGroup( "General" );
+ conf.writeEntry( "CurrentTheme", themeName );
+ conf.sync();
+
+ delete m_theme;
+ m_theme = 0;
+
+ }
+}
+
+void kthememanager::listThemes()
+{
+ dlg->lvThemes->clear();
+ dlg->lbPreview->setPixmap( TQPixmap() );
+
+ TQStringList themes = TDEGlobal::dirs()->findAllResources( "themes", "*.xml", true /*recursive*/ );
+
+ TQStringList::const_iterator it;
+
+ for ( it = themes.begin(); it != themes.end(); ++it )
+ {
+ KTheme theme( this, ( *it ) );
+ TQString name = theme.name();
+ if ( name != ORIGINAL_THEME ) // skip the "original" theme
+ ( void ) new TQListViewItem( dlg->lvThemes, name, theme.comment() );
+ }
+
+ kdDebug() << "Available themes: " << themes << endl;
+}
+
+float kthememanager::getThemeVersion( const TQString & themeName )
+{
+ TQStringList themes = TDEGlobal::dirs()->findAllResources( "themes", "*.xml", true /*recursive*/ );
+
+ TQStringList::const_iterator it;
+
+ for ( it = themes.begin(); it != themes.end(); ++it )
+ {
+ KTheme theme( 0L, ( *it ) );
+ TQString name = theme.name();
+ bool ok = false;
+ float version = theme.version().toFloat( &ok );
+ if ( name == themeName && ok )
+ return version;
+ }
+
+ return -1;
+}
+
+void kthememanager::slotInstallTheme()
+{
+ addNewTheme( KFileDialog::getOpenURL( ":themes", "*.kth|" + i18n("Theme Files"), this,
+ i18n( "Select Theme File" ) ) );
+}
+
+void kthememanager::addNewTheme( const KURL & url )
+{
+ if ( url.isValid() )
+ {
+ TQString themeName = TQFileInfo( url.fileName() ).baseName();
+ if ( getThemeVersion( themeName ) != -1 ) // theme exists already
+ {
+ KTheme::remove( themeName ); // remove first
+ }
+
+ m_theme = new KTheme(this);
+ if ( m_theme->load( url ) )
+ {
+ listThemes();
+ emit changed( true );
+ }
+
+ delete m_theme;
+ m_theme = 0;
+ updateButton();
+ }
+}
+
+void kthememanager::slotRemoveTheme()
+{
+ // get the selected item from the listview
+ TQListViewItem * cur = dlg->lvThemes->currentItem();
+ // ask and remove it
+ if ( cur )
+ {
+ TQString themeName = cur->text( 0 );
+ if ( KMessageBox::warningContinueCancel( this, "<qt>" + i18n( "Do you really want to remove the theme <b>%1</b>?" ).arg( themeName ),
+ i18n( "Remove Theme" ), KGuiItem( i18n( "&Remove" ), "edit-delete" ) )
+ == KMessageBox::Continue )
+ {
+ KTheme::remove( themeName );
+ listThemes();
+ }
+ updateButton();
+ }
+}
+
+bool kthememanager::themeExist(const TQString &_themeName)
+{
+ return ( dlg->lvThemes->findItem( _themeName, 0 )!=0 );
+}
+
+void kthememanager::slotCreateTheme()
+{
+ KNewThemeDlg dlg( this );
+
+ KEMailSettings es;
+ es.setProfile( es.defaultProfileName() );
+
+ dlg.setName( i18n( "My Theme" ) );
+ dlg.setAuthor( es.getSetting( KEMailSettings::RealName ) ) ;
+ dlg.setEmail( es.getSetting( KEMailSettings::EmailAddress ) );
+ dlg.setVersion( "0.1" );
+
+ if ( dlg.exec() == TQDialog::Accepted )
+ {
+
+ TQString themeName = dlg.getName();
+ if ( themeExist(themeName) )
+ {
+ KMessageBox::information( this, i18n( "Theme %1 already exists." ).arg( themeName ) );
+ }
+ else
+ {
+ if ( getThemeVersion( themeName ) != -1 ) // remove the installed theme first
+ {
+ KTheme::remove( themeName );
+ }
+ m_theme = new KTheme( this, true );
+ m_theme->setName( dlg.getName() );
+ m_theme->setAuthor( dlg.getAuthor() );
+ m_theme->setEmail( dlg.getEmail() );
+ m_theme->setHomepage( dlg.getHomepage() );
+ m_theme->setComment( dlg.getComment().replace( "\n", "" ) );
+ m_theme->setVersion( dlg.getVersion() );
+
+ TQString result = m_theme->createYourself( true );
+ m_theme->addPreview();
+
+ if ( !result.isEmpty() )
+ KMessageBox::information( this, i18n( "Your theme has been successfully created in %1." ).arg( result ),
+ i18n( "Theme Created" ), "theme_created_ok" );
+ else
+ KMessageBox::error( this, i18n( "An error occurred while creating your theme." ),
+ i18n( "Theme Not Created" ) );
+ delete m_theme;
+ m_theme = 0;
+
+ listThemes();
+ }
+ }
+}
+
+void kthememanager::slotThemeChanged( TQListViewItem * item )
+{
+ if ( item )
+ {
+ TQString themeName = item->text(0);
+ kdDebug() << "Activated theme: " << themeName << endl;
+
+ TQString themeDir = TDEGlobal::dirs()->findResourceDir( "themes", themeName + "/" + themeName + ".xml") + themeName + "/";
+
+ TQString pixFile = themeDir + themeName + ".preview.png";
+
+ if ( TQFile::exists( pixFile ) )
+ {
+ updatePreview( pixFile );
+ }
+ else
+ {
+ dlg->lbPreview->setPixmap( TQPixmap() );
+ dlg->lbPreview->setText( i18n( "This theme does not contain a preview." ) );
+ }
+
+ KTheme theme( this, themeDir + themeName + ".xml" );
+ TQToolTip::remove( dlg->lbPreview );
+ TQToolTip::add( dlg->lbPreview, "<qt>" + i18n( "Author: %1<br>Email: %2<br>Version: %3<br>Homepage: %4" )
+ .arg( theme.author() ).arg( theme.email() )
+ .arg( theme.version() ).arg( theme.homepage() ) + "</qt>");
+
+ emit changed( true );
+ }
+}
+
+void kthememanager::dragEnterEvent( TQDragEnterEvent * ev )
+{
+ ev->accept( KURLDrag::canDecode( ev ) );
+}
+
+void kthememanager::dropEvent( TQDropEvent * ev )
+{
+ KURL::List urls;
+ if ( KURLDrag::decode( ev, urls ) )
+ {
+ emit filesDropped( urls );
+ }
+}
+
+void kthememanager::slotFilesDropped( const KURL::List & urls )
+{
+ for ( KURL::List::ConstIterator it = urls.begin(); it != urls.end(); ++it )
+ addNewTheme( *it );
+}
+
+void kthememanager::queryLNFModules()
+{
+ /*KServiceGroup::Ptr settings = KServiceGroup::group( "Settings/LookNFeel/" );
+ if ( !settings || !settings->isValid() )
+ return;
+
+ KServiceGroup::List list = settings->entries();
+
+ // Iterate over all entries in the group
+ for( KServiceGroup::List::ConstIterator it = list.begin();
+ it != list.end(); it++ )
+ {
+ KSycocaEntry *p = ( *it );
+ if ( p->isType( KST_KService ) )
+ {
+ KService *s = static_cast<KService *>( p );
+ ( void ) new KThemeDetailsItem( dlg->lvDetails, s->name(), s->pixmap( TDEIcon::Desktop ), s->exec() );
+ }
+ }
+
+ dlg->lvDetails->sort();*/
+
+ // For now use a static list
+ TDEIconLoader * il = TDEGlobal::iconLoader();
+ dlg->btnBackground->setIconSet( il->loadIconSet( "background", TDEIcon::Desktop, 32 ) );
+ dlg->btnColors->setIconSet( il->loadIconSet( "application-x-kcsrc", TDEIcon::Desktop, 32 ) );
+ dlg->btnStyle->setIconSet( il->loadIconSet( "style", TDEIcon::Desktop, 32 ) );
+ dlg->btnIcons->setIconSet( il->loadIconSet( "icons", TDEIcon::Desktop, 32 ) );
+ dlg->btnFonts->setIconSet( il->loadIconSet( "fonts", TDEIcon::Desktop, 32 ) );
+ dlg->btnSaver->setIconSet( il->loadIconSet( "tdescreensaver", TDEIcon::Desktop, 32 ) );
+}
+
+void kthememanager::updatePreview( const TQString & pixFile )
+{
+ kdDebug() << "Preview is in file: " << pixFile << endl;
+ TQImage preview( pixFile, "PNG" );
+ if (preview.width()>dlg->lbPreview->contentsRect().width() ||
+ preview.height()>dlg->lbPreview->contentsRect().height() )
+ preview = preview.smoothScale( dlg->lbPreview->contentsRect().size(), TQ_ScaleMin );
+ TQPixmap pix;
+ pix.convertFromImage( preview );
+ dlg->lbPreview->setPixmap( pix );
+}
+
+extern "C"
+{
+ KDE_EXPORT TDECModule *create_kthememanager(TQWidget *parent, const char *)
+ {
+ TDEGlobal::locale()->insertCatalogue( "kthememanager" );
+ return new kthememanager( parent, "kthememanager" );
+ }
+}
+
+#include "kthememanager.moc"
diff --git a/kcontrol/kthememanager/kthememanager.desktop b/kcontrol/kthememanager/kthememanager.desktop
new file mode 100644
index 000000000..b44e215d4
--- /dev/null
+++ b/kcontrol/kthememanager/kthememanager.desktop
@@ -0,0 +1,221 @@
+[Desktop Entry]
+Comment=Manage global TDE visual themes
+Comment[af]=Bestuurder TDE se globale visuele temas
+Comment[az]=Qlobal TDE əyani örtüklərini idarə et
+Comment[be]=Кіраванне глабальнымі візуальнымі тэмамі TDE
+Comment[bg]=Управление на темите
+Comment[bn]=গ্লোবাল কে.ডি.ই. ভিসুয়াল থীম ব্যবস্থাপনা
+Comment[bs]=Upravljanje globalnim TDE vizuelnim temama
+Comment[ca]=Gestiona els temes visuals globals del TDE
+Comment[cs]=Správce motivů pracovní plochy
+Comment[csb]=Sprôwiôj témą TDE
+Comment[cy]=Rheoli themau gweledol TDE eang
+Comment[da]=Håndtering af globale visuelle temaer for TDE
+Comment[de]=Globale TDE-Designs verwalten
+Comment[el]=Διαχειριστής καθολικών οπτικών θεμάτων του TDE
+Comment[eo]=Administras mondan TDEan etosoj
+Comment[es]=Gestión global de los temas visuales de TDE
+Comment[et]=TDE globaalsete teemade haldur
+Comment[eu]=Kudeatu TDEren gai bisual orokorrak
+Comment[fa]=مدیریت چهره‌های مرئی TDE سراسری
+Comment[fi]=Ylläpidä TDE:n teemoja
+Comment[fr]=Gestionnaire de thèmes visuels globaux de TDE
+Comment[fy]=Algemiene fisuele tema's fan TDE beheare
+Comment[gl]=Xestionar temas visuais globais de TDE
+Comment[he]=מנהל ערכות נושא גלובליות עבור TDE
+Comment[hi]=वैश्विक केडीई दृश्यमय प्रसंग प्रबंधित करें
+Comment[hr]=Upravljanje općim TDE vizualnim temama
+Comment[hu]=TDE-témák kezelése
+Comment[is]=Stjórna víðværum TDE þemum
+Comment[it]=Gestore dei temi globali di TDE
+Comment[ja]=グローバル TDE 外観テーマの管理
+Comment[ka]=TDE-ს ვიზუალური თემბის გლობალური მენეჯმენტი
+Comment[kk]=TDE жалпы көрініс нақыштарын басқару
+Comment[km]=គ្រប់គ្រង​ស្បែក​រូបភាព TDE ទាំងអស់
+Comment[ko]=전역 TDE 시각 테마 관리
+Comment[lt]=Globaliai tvarkyti TDE vizualines temas
+Comment[lv]=TDE izskata tēmu pārvaldīšana
+Comment[mk]=Менаџирајте ги глобалните TDE визуелни теми
+Comment[ms]=Urus tema visual TDE global
+Comment[mt]=Immaniġġja temi viżwali globali tal-TDE
+Comment[nb]=Velg blant TDE-temaer for hele brukerflaten
+Comment[nds]=Globale TDE-Muster instellen
+Comment[ne]=विश्वव्यापी TDE दृश्य विषयवस्तु व्यवस्थापन गर्नुहोस्
+Comment[nl]=Algemene visuele thema's van TDE beheren
+Comment[nn]=Vel mellom TDE-tema for heile brukarflata
+Comment[pa]=ਮੁੱਢਲੇ TDE ਦਿੱਖ ਸਰੂਪ ਪਰਬੰਧ
+Comment[pl]=Zarządzaj motywami TDE
+Comment[pt]=Gestão global de temas visuais do TDE
+Comment[pt_BR]=Gerencia temas globais do TDE
+Comment[ro]=Administrează tematicile vizuale TDE globale
+Comment[ru]=Менеджер глобальных визуальных тем TDE
+Comment[rw]=Kuyobora insanganyamatsiko igaragara TDE rusange
+Comment[se]=Hálddaš oppalaš visuella TDE-fáttáid
+Comment[sk]=Globálny správca tém
+Comment[sl]=Upravitelj vizualnih tem za TDE
+Comment[sr]=Управљање TDE-овим визуелним темама
+Comment[sr@Latn]=Upravljanje TDE-ovim vizuelnim temama
+Comment[sv]=Hantera TDE:s allmänna visuella teman
+Comment[ta]=பொது TDE காட்சி பொருளை மேல்பார்வையிடு
+Comment[tg]=Мудири мавзӯъҳои визуалии TDE дар шабака
+Comment[th]=จัดการชุดตกแต่งของ TDE
+Comment[tr]=Evrensel TDE ekran temalarını yönet
+Comment[tt]=TDE'nıñ tışlaw törlären caylaw idäräse
+Comment[uk]=Керування глобальними темами TDE
+Comment[vi]=Trình quản lý các sắc thái của TDE
+Comment[wa]=Manaedjî tinmes pol rivnance globåle di TDE
+Comment[zh_CN]=管理全局 TDE 视觉主题
+Comment[zh_TW]=管理全域 TDE 視覺佈景
+Exec=tdecmshell kthememanager
+Icon=kthememgr
+Keywords=themes;look and feel;
+Keywords[af]=themes;look and feel;temas;
+Keywords[ar]=سمات;المظهر و الإحساس;
+Keywords[az]=örtüklər;görünüş;örtük;theme;look;
+Keywords[be]=Тэмы;Вонкавы выгляд;themes;look and feel;
+Keywords[bg]=теми; вид; themes; look and feel;
+Keywords[br]=gizioù;Neuz ha feson;
+Keywords[bs]=themes;look and feel;teme;izgled;osjećaj;
+Keywords[ca]=temes;aspecte i efecte;
+Keywords[cs]=motivy;vzhled a chování;
+Keywords[csb]=téma;wëzdrzatk;
+Keywords[cy]=themau;golwg a theimlad;
+Keywords[da]=temaer;udseende;
+Keywords[de]=Designs;Themes;Erscheinungsbild;
+Keywords[el]=θέματα;εμφάνιση και αίσθηση;
+Keywords[eo]=etoso;etosoj;videbleco;uzebleco;
+Keywords[es]=temas;aspecto y comportamiento;
+Keywords[et]=teemad;välimus;
+Keywords[eu]=gaiak;itxura eta portaera;
+Keywords[fa]=چهره‌ها، ظاهر و احساس;
+Keywords[fi]=teemat;ulkonäkö ja tuntuma;
+Keywords[fr]=thèmes;apparence et ergonomie;
+Keywords[fy]=tema's;úterlik en gedrach;
+Keywords[ga]=téamaí;cuma;
+Keywords[gl]=temas;apariencia;
+Keywords[he]=ערכות; מראה ותחושה; themes;look and feel;
+Keywords[hi]=प्रसंग; रूप तथा आकार;
+Keywords[hr]=themes;look and feel;izgled i osjećaj;teme;
+Keywords[hu]=témák;megjelenés;
+Keywords[it]=temi;aspetto;
+Keywords[ja]=テーマ;look and feel;外観;ルックアンドフィール;
+Keywords[km]=ស្បែក;រូបរាង និង​មុខងារ;
+Keywords[lt]=themes;look and feel;temos;išvaizda ir jausena;
+Keywords[lv]=tēmas;izskats un sajūtas;
+Keywords[mk]=themes;look and feel;теми;изглед и чувство;
+Keywords[ms]=tema; rupa dan rasa;
+Keywords[mt]=themes;look and feel;temi;dehra;
+Keywords[nb]=temaer;utseende og oppførsel;
+Keywords[nds]=Muster;themes;Themas;look and feel;Achtergrund;Klören;Klöörschemas;Schemas;Klöörschema;
+Keywords[ne]=विषयवस्तु; हेराइ र बुझाइ;
+Keywords[nl]=thema's;uiterlijk en gedrag;
+Keywords[nn]=tema;utsjånad og åtferd;
+Keywords[pa]=ਸਰੂਪ;ਦਿੱਖ ਅਤੇ ਛੋਹ;
+Keywords[pl]=motywy;wygląd;
+Keywords[pt]=temas;aparência e comportamento;
+Keywords[pt_BR]=temas;aparência;
+Keywords[ro]=tematici;apect;grafică;
+Keywords[rw]=Insanganyamatsiko;imboneko n'ukumva;
+Keywords[se]=fáttát;fárda ja láhtten;
+Keywords[sk]=témy;vzhľad;
+Keywords[sl]=teme;videz in občutek;
+Keywords[sr]=themes;look and feel;теме;изглед и осећај;изглед;
+Keywords[sr@Latn]=themes;look and feel;teme;izgled i osećaj;izgled;
+Keywords[sv]=teman;utseende och känsla;
+Keywords[ta]=உரைபொருள்;பார் மற்றும் உணர்ணர்;
+Keywords[th]=ชุดตกแต่ง;รูปแบบและสัมผัส;
+Keywords[tr]=temalar;görünüm ve hisset;
+Keywords[uk]=теми;вигляд та поведінка;
+Keywords[uz]=mavzular;tashqi koʻrinishi;
+Keywords[uz@cyrillic]=мавзулар;ташқи кўриниши;
+Keywords[vi]=sắc thái;cảm nhận;
+Keywords[wa]=tinmes;rivnance;
+Keywords[zh_CN]=themes;look and feel;主题;观感;
+Keywords[zh_TW]=themes;look and feel;主題;外觀與感覺;
+Name=Theme Manager
+Name[af]=Tema Bestuurder
+Name[ar]=مسيير السمات
+Name[az]=Örtük İdarəcisi
+Name[be]=Кіраванне тэмамі
+Name[bg]=Мениджър на теми
+Name[bn]=থীম ম্যানেজার
+Name[br]=Merour gwiskadoù
+Name[bs]=Upravitelj temama
+Name[ca]=Gestor de temes
+Name[cs]=Správce motivů
+Name[csb]=Menedżer témów
+Name[cy]=Rheolwr Thema
+Name[da]=Temahåndtering
+Name[de]=Designverwaltung
+Name[el]=Διαχειριστής θεμάτων
+Name[eo]=Etosadministrilo
+Name[es]=Gestor de temas
+Name[et]=Teemahaldur
+Name[eu]=Gai kudeatzailea
+Name[fa]=مدیر چهره
+Name[fi]=Teemanhallinta
+Name[fr]=Gestionnaire de thèmes
+Name[fy]=Temabehearder
+Name[ga]=Bainisteoir na dTéamaí
+Name[gl]=Xestor de Temas
+Name[he]=מנהל ערכות נושא
+Name[hi]=प्रसंग प्रबंधक
+Name[hr]=Upravljanje temama
+Name[hu]=Témák
+Name[id]=Manajer Theme
+Name[is]=Þemustjóri
+Name[it]=Gestore dei temi
+Name[ja]=テーママネージャ
+Name[ka]=თემების მენეჯერი
+Name[kk]=Нақыштар менеджері
+Name[km]=កម្មវិធី​គ្រប់គ្រង​ស្បែក
+Name[ko]=테마 관리자
+Name[lo]=ເຄື່ອງມືຈັດການ ທີມ
+Name[lt]=Temų tvarkyklė
+Name[lv]=Tēmu Menedžeris
+Name[mk]=Менаџер на теми
+Name[mn]=Загвар-Удирлагч
+Name[ms]=Pengurus Tema
+Name[mt]=Manager tat-Temi
+Name[nb]=Temabehandler
+Name[nds]=Musterpleger
+Name[ne]=विषयवस्तु प्रबन्धक
+Name[nl]=Themabeheerder
+Name[nn]=Temahandsamar
+Name[nso]=Molaodi wa Molaetsa
+Name[oc]=Gestionari de temes
+Name[pa]=ਸਰੂਪ ਮੈਨੇਜਰ
+Name[pl]=Menedżer motywów
+Name[pt]=Gestor de Temas
+Name[pt_BR]=Gerenciador de Temas
+Name[ro]=Managerul de tematică
+Name[ru]=Менеджер тем
+Name[rw]=Mugenga Insanganyamatsiko
+Name[se]=Fáddagieđahalli
+Name[sk]=Správca tém
+Name[sl]=Upravitelj tem
+Name[sr]=Менаџер тема
+Name[sr@Latn]=Menadžer tema
+Name[ss]=Siphatsi sendzikimba
+Name[sv]=Temahanterare
+Name[ta]=பொருள் மேலாளர்
+Name[tg]=Мудири мавзӯъ
+Name[th]=เครื่องมือจัดการชุดตกแต่ง
+Name[tr]=Tema Yöneticisi
+Name[tt]=Tışlaw İdäräçe
+Name[uk]=Менеджер тем
+Name[uz]=Mavzu boshqaruvchisi
+Name[uz@cyrillic]=Мавзу бошқарувчиси
+Name[ven]=Mulanguli wa thero
+Name[vi]=Trình quản lí sắc thái
+Name[wa]=Manaedjeu di tinmes
+Name[xh]=Umphathi Womxholo
+Name[zh_CN]=主题管理器
+Name[zh_TW]=佈景管理程式
+Name[zu]=Imenenja Yengqikithi
+Terminal=false
+Type=Application
+X-TDE-FactoryName=kthememanager
+X-TDE-Library=kthememanager
+Categories=Qt;TDE;X-TDE-settings-looknfeel;
+X-DocPath=kcontrol/kthememanager/index.html
diff --git a/kcontrol/kthememanager/kthememanager.h b/kcontrol/kthememanager/kthememanager.h
new file mode 100644
index 000000000..2c5e494f4
--- /dev/null
+++ b/kcontrol/kthememanager/kthememanager.h
@@ -0,0 +1,157 @@
+// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*-
+/* Copyright (C) 2003 Lukas Tinkl <[email protected]>
+
+ 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef KTHEMEMANAGER_H
+#define KTHEMEMANAGER_H
+
+#include <tdecmodule.h>
+#include <krun.h>
+#include <kservice.h>
+#include <kurl.h>
+
+#include "kthemedlg.h"
+#include "ktheme.h"
+
+class TQString;
+
+class TDEAboutData;
+
+#define ORIGINAL_THEME "original" // no i18n() here!!!
+
+/*
+class TDEIconViewItem;
+
+class KThemeDetailsItem: public TDEIconViewItem
+{
+public:
+ KThemeDetailsItem( TDEIconView * parent, const TQString & text, const TQPixmap & icon, const TQString & execString )
+ : TDEIconViewItem( parent, text, icon ) { m_exec = execString; }
+ virtual ~KThemeDetailsItem() { };
+
+ void exec() {
+ ( void ) new KRun( m_exec );
+ }
+private:
+ TQString m_exec;
+};
+*/
+
+/**
+ *
+ * This is the for KControl config module for installing,
+ * creating and removing visual themes.
+ *
+ * @brief The Theme Manager config module.
+ * @author Lukas Tinkl <[email protected]>
+ */
+class kthememanager: public TDECModule
+{
+ Q_OBJECT
+public:
+ kthememanager( TQWidget *parent=0, const char *name=0 );
+ virtual ~kthememanager();
+
+ /**
+ * Called on module startup
+ */
+ virtual void load();
+ virtual void load(bool useDefaults);
+ /**
+ * Called when applying the changes
+ */
+ virtual void save();
+ /**
+ * Called when the user requests the default values
+ */
+ virtual void defaults();
+
+protected:
+ void dragEnterEvent ( TQDragEnterEvent * ev );
+ void dropEvent ( TQDropEvent * ev );
+
+signals:
+ /**
+ * Emitted when some @p urls are dropped onto the kcm
+ */
+ void filesDropped(const KURL::List &urls);
+
+private slots:
+ /**
+ * Install a theme from a tarball (*.kth)
+ */
+ void slotInstallTheme();
+
+ /**
+ * Remove an installed theme
+ */
+ void slotRemoveTheme();
+
+ /**
+ * Create a new theme
+ */
+ void slotCreateTheme();
+
+ /**
+ * Update the theme's info and preview
+ */
+ void slotThemeChanged( TQListViewItem * item );
+
+ /**
+ * Invoked when one drag and drops @p urls onto the kcm
+ * @see signal filesDropped
+ */
+ void slotFilesDropped( const KURL::List & urls );
+ void updateButton();
+
+private:
+ /**
+ * List themes available in the system and insert them into the listview.
+ */
+ void listThemes();
+
+ /**
+ * Performs the actual theme installation.
+ */
+ void addNewTheme( const KURL & url );
+
+ /**
+ * Perform internal initialization of paths.
+ */
+ void init();
+
+ /**
+ * Try to find out whether a theme is installed and get its version number
+ * @param themeName The theme name
+ * @return The theme's version number or -1 if not installed
+ */
+ static float getThemeVersion( const TQString & themeName );
+
+ void queryLNFModules();
+
+ /**
+ * Updates the preview widget
+ */
+ void updatePreview( const TQString & pixFile );
+ bool themeExist(const TQString &_themeName);
+ KThemeDlg * dlg;
+
+ KTheme * m_theme;
+ KTheme * m_origTheme;
+};
+
+#endif
diff --git a/kcontrol/kthememanager/newthemewidget.ui b/kcontrol/kthememanager/newthemewidget.ui
new file mode 100644
index 000000000..e84f1efa8
--- /dev/null
+++ b/kcontrol/kthememanager/newthemewidget.ui
@@ -0,0 +1,130 @@
+<!DOCTYPE UI><UI version="3.2" stdsetdef="1">
+<class>NewThemeWidget</class>
+<author>Lukas Tinkl &lt;[email protected]&gt;</author>
+<widget class="TQWidget">
+ <property name="name">
+ <cstring>NewThemeWidget</cstring>
+ </property>
+ <property name="geometry">
+ <rect>
+ <x>0</x>
+ <y>0</y>
+ <width>537</width>
+ <height>431</height>
+ </rect>
+ </property>
+ <grid>
+ <property name="name">
+ <cstring>unnamed</cstring>
+ </property>
+ <widget class="TQLabel" row="0" column="0">
+ <property name="name">
+ <cstring>textLabel1</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Theme name:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>leName</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="1" column="0">
+ <property name="name">
+ <cstring>textLabel2</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Author:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>leAuthor</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="2" column="0">
+ <property name="name">
+ <cstring>textLabel3</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Email:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>leEmail</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="3" column="0">
+ <property name="name">
+ <cstring>textLabel4</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Homepage:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>leHomepage</cstring>
+ </property>
+ </widget>
+ <widget class="TQLineEdit" row="2" column="1">
+ <property name="name">
+ <cstring>leEmail</cstring>
+ </property>
+ </widget>
+ <widget class="TQLineEdit" row="0" column="1">
+ <property name="name">
+ <cstring>leName</cstring>
+ </property>
+ </widget>
+ <widget class="TQLineEdit" row="3" column="1">
+ <property name="name">
+ <cstring>leHomepage</cstring>
+ </property>
+ </widget>
+ <widget class="TQLineEdit" row="1" column="1">
+ <property name="name">
+ <cstring>leAuthor</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="5" column="0">
+ <property name="name">
+ <cstring>textLabel5</cstring>
+ </property>
+ <property name="text">
+ <string>Co&amp;mment:</string>
+ </property>
+ <property name="alignment">
+ <set>AlignTop</set>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>teComment</cstring>
+ </property>
+ </widget>
+ <widget class="TQTextEdit" row="5" column="1">
+ <property name="name">
+ <cstring>teComment</cstring>
+ </property>
+ </widget>
+ <widget class="TQLineEdit" row="4" column="1">
+ <property name="name">
+ <cstring>leVersion</cstring>
+ </property>
+ </widget>
+ <widget class="TQLabel" row="4" column="0">
+ <property name="name">
+ <cstring>textLabel6</cstring>
+ </property>
+ <property name="text">
+ <string>&amp;Version:</string>
+ </property>
+ <property name="buddy" stdset="0">
+ <cstring>leVersion</cstring>
+ </property>
+ </widget>
+ </grid>
+</widget>
+<tabstops>
+ <tabstop>leName</tabstop>
+ <tabstop>leAuthor</tabstop>
+ <tabstop>leEmail</tabstop>
+ <tabstop>leHomepage</tabstop>
+ <tabstop>leVersion</tabstop>
+ <tabstop>teComment</tabstop>
+</tabstops>
+<layoutdefaults spacing="6" margin="11"/>
+</UI>
diff --git a/kcontrol/kthememanager/x-ktheme.desktop b/kcontrol/kthememanager/x-ktheme.desktop
new file mode 100644
index 000000000..8db7d86b5
--- /dev/null
+++ b/kcontrol/kthememanager/x-ktheme.desktop
@@ -0,0 +1,84 @@
+[Desktop Entry]
+MimeType=application/x-ktheme
+Comment=TDE Theme
+Comment[af]=TDE Tema
+Comment[ar]=سمة TDE
+Comment[az]=TDE Örtüyü
+Comment[be]=Тэма TDE
+Comment[bg]=Тема за TDE
+Comment[bn]=কে.ডি.ই. থীম
+Comment[br]=Giz TDE
+Comment[bs]=TDE tema
+Comment[ca]=Tema TDE
+Comment[cs]=TDE motiv
+Comment[csb]=Téma TDE
+Comment[cy]=Thema TDE
+Comment[da]=TDE-tema
+Comment[de]=TDE-Design
+Comment[el]=Θέμα του TDE
+Comment[eo]=TDEa etoso
+Comment[es]=Tema de TDE
+Comment[et]=TDE teema
+Comment[fa]=چهرۀ TDE
+Comment[fi]=TDE-teema
+Comment[fr]=Thème TDE
+Comment[fy]=TDE-tema
+Comment[ga]=Téama TDE
+Comment[gl]=Tema de TDE
+Comment[he]=ערכת נושא של TDE
+Comment[hi]=केडीई प्रसंग
+Comment[hr]=TDE tema
+Comment[hu]=TDE-téma
+Comment[id]=Tema TDE
+Comment[is]=TDE þema
+Comment[it]=Tema TDE
+Comment[ja]=TDE テーマ
+Comment[ka]=TDE-ს თემა
+Comment[kk]=TDE нақышы
+Comment[km]=ស្បែក TDE
+Comment[ko]=TDE 테마 설치
+Comment[lo]=ທີມຂອງ TDE
+Comment[lt]=TDE Tema
+Comment[lv]=TDE Tēma
+Comment[mk]=TDE-тема
+Comment[mn]=КДЭ-Хэлбэр
+Comment[ms]=Tema TDE
+Comment[mt]=Tema TDE
+Comment[nb]=TDE-tema
+Comment[nds]=TDE Muster
+Comment[ne]=TDE विषयवस्तु
+Comment[nl]=TDE-thema
+Comment[nn]=TDE-tema
+Comment[nso]=Molaetsa wa TDE
+Comment[pa]=TDE ਸਰੂਪ
+Comment[pl]=Motywy TDE
+Comment[pt]=Tema do TDE
+Comment[pt_BR]=Tema do TDE
+Comment[ro]=Tematică TDE
+Comment[ru]=Тема TDE
+Comment[rw]=Insanganyamatsiko za TDE
+Comment[se]=TDE-fáddá
+Comment[sk]=Téma TDE
+Comment[sl]=Tema TDE
+Comment[sr]=TDE тема
+Comment[sr@Latn]=TDE tema
+Comment[sv]=TDE-tema
+Comment[ta]=TDE பொருள்
+Comment[tg]=Мавзӯъи TDE
+Comment[th]=ชุดตกแต่ง TDE
+Comment[tr]=TDE Teması
+Comment[tt]=TDE Tışlawı
+Comment[uk]=Тема TDE
+Comment[uz]=TDE mavzusi
+Comment[uz@cyrillic]=TDE мавзуси
+Comment[ven]=Thero ya TDE
+Comment[vi]=Sắc thái TDE
+Comment[wa]=Tinme TDE
+Comment[xh]=Umxholo we TDE
+Comment[zh_CN]=TDE 主题
+Comment[zh_TW]=TDE 主題
+Comment[zu]=Ingqikithi ye-TDE
+Icon=kthememgr
+Type=MimeType
+Patterns=*.kth;
+X-TDE-AutoEmbed=false