From 4aed2c8219774f5d797760606b8489a92ddc5163 Mon Sep 17 00:00:00 2001 From: toma Date: Wed, 25 Nov 2009 17:56:58 +0000 Subject: Copy the KDE 3.5 branch to branches/trinity for new KDE 3.5 features. BUG:215923 git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/kdebase@1054174 283d02a7-25f6-0310-bc7c-ecb5cbfe19da --- kcontrol/kthememanager/Makefile.am | 21 + kcontrol/kthememanager/NEWS | 26 + kcontrol/kthememanager/README | 99 +++ kcontrol/kthememanager/TODO | 9 + kcontrol/kthememanager/installktheme.desktop | 78 +++ kcontrol/kthememanager/kdeinstallktheme | 14 + kcontrol/kthememanager/knewthemedlg.cpp | 96 +++ kcontrol/kthememanager/knewthemedlg.h | 58 ++ kcontrol/kthememanager/ktheme.cpp | 897 +++++++++++++++++++++++++++ kcontrol/kthememanager/ktheme.h | 224 +++++++ kcontrol/kthememanager/kthemedlg.ui | 518 ++++++++++++++++ kcontrol/kthememanager/kthemedlg.ui.h | 49 ++ kcontrol/kthememanager/kthememanager.cpp | 425 +++++++++++++ kcontrol/kthememanager/kthememanager.desktop | 220 +++++++ kcontrol/kthememanager/kthememanager.h | 157 +++++ kcontrol/kthememanager/newthemewidget.ui | 130 ++++ kcontrol/kthememanager/x-ktheme.desktop | 84 +++ 17 files changed, 3105 insertions(+) create mode 100644 kcontrol/kthememanager/Makefile.am create mode 100644 kcontrol/kthememanager/NEWS create mode 100644 kcontrol/kthememanager/README create mode 100644 kcontrol/kthememanager/TODO create mode 100644 kcontrol/kthememanager/installktheme.desktop create mode 100755 kcontrol/kthememanager/kdeinstallktheme create mode 100644 kcontrol/kthememanager/knewthemedlg.cpp create mode 100644 kcontrol/kthememanager/knewthemedlg.h create mode 100644 kcontrol/kthememanager/ktheme.cpp create mode 100644 kcontrol/kthememanager/ktheme.h create mode 100644 kcontrol/kthememanager/kthemedlg.ui create mode 100644 kcontrol/kthememanager/kthemedlg.ui.h create mode 100644 kcontrol/kthememanager/kthememanager.cpp create mode 100644 kcontrol/kthememanager/kthememanager.desktop create mode 100644 kcontrol/kthememanager/kthememanager.h create mode 100644 kcontrol/kthememanager/newthemewidget.ui create mode 100644 kcontrol/kthememanager/x-ktheme.desktop (limited to 'kcontrol/kthememanager') diff --git a/kcontrol/kthememanager/Makefile.am b/kcontrol/kthememanager/Makefile.am new file mode 100644 index 000000000..be71094cb --- /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_KIO) +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..0fe235115 --- /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 + + +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: +============================= + + + + + + + + + + + + + + + + + + + + ... + + + + ... + + + + + + + + + + + + + + + + + + + + +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..944f79b78 --- /dev/null +++ b/kcontrol/kthememanager/TODO @@ -0,0 +1,9 @@ +- use KHotNewStuff for directly downloading themes from kde-look.org +- custom pixmap kwin themes (requires kwmtheme to be ported first) +- write user and theme developer documentation + +Handle: +- splash screen (+ copying?) +- K 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..51e5f75a6 --- /dev/null +++ b/kcontrol/kthememanager/installktheme.desktop @@ -0,0 +1,78 @@ +[Desktop Entry] +Name=Install KDE Theme +Name[af]=Installeer KDE temas +Name[ar]=ثبِت سمة KDE +Name[az]=KDE Örtüyünü Qur +Name[be]=Устаноўка тэмы KDE +Name[bg]=Инсталиране на тема +Name[bn]=কে.ডি.ই. থীম ইনস্টল করো +Name[br]=Staliañ ar c'hiz KDE +Name[bs]=Instaliraj KDE temu +Name[ca]=Instal·la tema KDE +Name[cs]=Instalovat KDE motiv +Name[csb]=Instalëjë témã KDE +Name[cy]=Gosod Thema KDE +Name[da]=Installér KDE-tema +Name[de]=KDE-Design installieren +Name[el]=Εγκατάσταση θέματος του KDE +Name[eo]=Instali KDEan etoson +Name[es]=Instalar tema de KDE +Name[et]=KDE teema paigaldamine +Name[eu]=Instalatu KDE gaia +Name[fa]=نصب چهرۀ KDE +Name[fi]=Asenna KDE-teema +Name[fr]=Installer des thèmes KDE +Name[fy]=KDE-tema ynstallearje +Name[ga]=Suiteáil Téama KDE +Name[gl]=Instalar tema de KDE +Name[he]=התקנה של ערכת נושא עבור KDE +Name[hi]=केडीई प्रसंग संस्थापित करें +Name[hr]=Instaliranje KDE teme +Name[hu]=KDE-téma telepítése +Name[is]=Setja inn KDE þemu +Name[it]=Installa tema di KDE +Name[ja]=KDE テーマのインストール +Name[ka]=KDE-ს თემების დაყენება +Name[kk]=KDE нақыштарын орнату +Name[km]=ដំឡើង​ស្បែក KDE +Name[ko]=KDE 테마 설치 +Name[lt]=Įdiegti KDE temą +Name[lv]=Instalēt KDE tēmu +Name[mk]=Инсталирај KDE Тема +Name[ms]=Pasang Tema KDE +Name[mt]=Installa Tema KDE +Name[nb]=Legg inn KDE-tema +Name[nds]=KDE-Muster installeren +Name[ne]=KDE विषयवस्तु स्थापना गर्नुहोस् +Name[nl]=KDE-thema installeren +Name[nn]=Installer KDE-tema +Name[pa]=KDE ਸਰੂਪ ਇੰਸਟਾਲ +Name[pl]=Instaluj motyw KDE +Name[pt]=Instalar um Tema do KDE +Name[pt_BR]=Instalar Tema do KDE +Name[ro]=Instalează tematică KDE +Name[ru]=Установка тем KDE +Name[rw]=Kwinjiza Insanganyamatsiko KDE +Name[se]=Sajáiduhte KDE-fáttá +Name[sk]=Inštalovať tému KDE +Name[sl]=Namesti temo KDE +Name[sr]=Инсталирај KDE тему +Name[sr@Latn]=Instaliraj KDE temu +Name[sv]=Installera KDE-tema +Name[ta]=KDE பொருளை நிறுவு +Name[tg]=Мавзӯъи KDE сабт кунед +Name[th]=ติดตั้งชุดตกแต่ง KDE +Name[tr]=KDE Teması Yükle +Name[tt]=KDE Tışlaw quyu +Name[uk]=Встановлення теми KDE +Name[uz]=KDE mavzusini oʻrnatish +Name[uz@cyrillic]=KDE мавзусини ўрнатиш +Name[vi]=Cài đặt Sắc thái KDE +Name[wa]=Astaler on tinme KDE +Name[zh_CN]=安装 KDE 主题 +Name[zh_TW]=安裝 KDE 佈景 +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..b606fe16b --- /dev/null +++ b/kcontrol/kthememanager/kdeinstallktheme @@ -0,0 +1,14 @@ +#!/bin/sh +# Installs a KDE theme (into the user's theme dir) +appsdir=`kde-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..1514ed453 --- /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 + + 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 +#include + +#include + +KNewThemeDlg::KNewThemeDlg( QWidget * 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, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotThemeNameChanged( const QString & ) ) ); + slotThemeNameChanged( m_base->leName->text() ); +} + +KNewThemeDlg::~KNewThemeDlg() +{ + delete m_base; +} + +void KNewThemeDlg::slotThemeNameChanged( const QString &_text ) +{ + enableButtonOK( !_text.isEmpty() ); +} + +QString KNewThemeDlg::getName() const +{ + return m_base->leName->text(); +} + +QString KNewThemeDlg::getAuthor() const +{ + return m_base->leAuthor->text(); +} + +QString KNewThemeDlg::getEmail() const +{ + return m_base->leEmail->text(); +} + +QString KNewThemeDlg::getHomepage() const +{ + return m_base->leHomepage->text(); +} + +QString KNewThemeDlg::getComment() const +{ + return m_base->teComment->text(); +} + +QString KNewThemeDlg::getVersion() const +{ + return m_base->leVersion->text(); +} + +void KNewThemeDlg::setAuthor( const QString & author ) +{ + m_base->leAuthor->setText( author ); +} + +void KNewThemeDlg::setEmail( const QString & email ) +{ + m_base->leEmail->setText( email ); +} + +void KNewThemeDlg::setVersion( const QString & version ) +{ + m_base->leVersion->setText( version ); +} + +void KNewThemeDlg::setName( const QString & 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..52fd0816f --- /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 + + 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 + +#include + +class NewThemeWidget; + +/** + * Dialog for creating new themes, contains just + * getters and setters used for the theme general properties + * @author Lukas Tinkl + */ +class KNewThemeDlg: public KDialogBase +{ + Q_OBJECT +public: + KNewThemeDlg( QWidget * parent = 0, const char * name = 0); + ~KNewThemeDlg(); + + QString getName() const; + QString getAuthor() const; + QString getEmail() const; + QString getHomepage() const; + QString getComment() const; + QString getVersion() const; + + void setName( const QString & name ); + void setAuthor( const QString & author ); + void setEmail( const QString & email ); + void setVersion( const QString & version ); +private: + NewThemeWidget * m_base; + +private slots: + void slotThemeNameChanged( const QString &_text ); +}; + +#endif diff --git a/kcontrol/kthememanager/ktheme.cpp b/kcontrol/kthememanager/ktheme.cpp new file mode 100644 index 000000000..241aac132 --- /dev/null +++ b/kcontrol/kthememanager/ktheme.cpp @@ -0,0 +1,897 @@ +// -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 4; -*- +/* Copyright (C) 2003 Lukas Tinkl + +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 +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +KTheme::KTheme( QWidget *parent, const QString & xmlFile ) + : m_parent(parent) +{ + QFile file( xmlFile ); + file.open( IO_ReadOnly ); + m_dom.setContent( file.readAll() ); + file.close(); + + //kdDebug() << m_dom.toString( 2 ) << endl; + + setName( QFileInfo( file ).baseName() ); + m_kgd = KGlobal::dirs(); +} + +KTheme::KTheme( QWidget *parent, bool create ) + : m_parent(parent) +{ + if ( create ) + { + m_dom = QDomDocument( "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 = KGlobal::dirs(); +} + +KTheme::~KTheme() +{ +} + +void KTheme::setName( const QString & name ) +{ + m_name = name; +} + +bool KTheme::load( const KURL & url ) +{ + kdDebug() << "Loading theme from URL: " << url << endl; + + QString tmpFile; + if ( !KIO::NetAccess::download( url, tmpFile, 0L ) ) + return false; + + kdDebug() << "Theme is in temp file: " << tmpFile << endl; + + // set theme's name + setName( QFileInfo( url.fileName() ).baseName() ); + + // unpack the tarball + QString location = m_kgd->saveLocation( "themes", m_name + "/" ); + KTar tar( tmpFile ); + tar.open( IO_ReadOnly ); + tar.directory()->copyTo( location ); + tar.close(); + + // create the DOM + QFile file( location + m_name + ".xml" ); + file.open( IO_ReadOnly ); + m_dom.setContent( file.readAll() ); + file.close(); + + // remove the temp file + KIO::NetAccess::removeTempFile( tmpFile ); + + return true; +} + +QString 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 + KConfig * globalConf = KGlobal::config(); + + KConfig kwinConf( "kwinrc", true ); + kwinConf.setGroup( "Desktops" ); + uint numDesktops = kwinConf.readUnsignedNumEntry( "Number", 4 ); + + KConfig desktopConf( "kdesktoprc", true ); + desktopConf.setGroup( "Background Common" ); + bool common = desktopConf.readBoolEntry( "CommonDesktop", true ); + + for ( uint i=0; i < numDesktops-1; i++ ) + { + QDomElement desktopElem = m_dom.createElement( "desktop" ); + desktopElem.setAttribute( "number", i ); + desktopElem.setAttribute( "common", common ); + + desktopConf.setGroup( "Desktop" + QString::number( i ) ); + + QDomElement modeElem = m_dom.createElement( "mode" ); + modeElem.setAttribute( "id", desktopConf.readEntry( "BackgroundMode", "Flat" ) ); + desktopElem.appendChild( modeElem ); + + QDomElement c1Elem = m_dom.createElement( "color1" ); + c1Elem.setAttribute( "rgb", desktopConf.readColorEntry( "Color1" ).name() ); + desktopElem.appendChild( c1Elem ); + + QDomElement c2Elem = m_dom.createElement( "color2" ); + c2Elem.setAttribute( "rgb", desktopConf.readColorEntry( "Color2" ).name() ); + desktopElem.appendChild( c2Elem ); + + QDomElement blendElem = m_dom.createElement( "blending" ); + blendElem.setAttribute( "mode", desktopConf.readEntry( "BlendMode", QString( "NoBlending" ) ) ); + blendElem.setAttribute( "balance", desktopConf.readEntry( "BlendBalance", QString::number( 100 ) ) ); + blendElem.setAttribute( "reverse", desktopConf.readBoolEntry( "ReverseBlending", false ) ); + desktopElem.appendChild( blendElem ); + + QDomElement patElem = m_dom.createElement( "pattern" ); + patElem.setAttribute( "name", desktopConf.readEntry( "Pattern" ) ); + desktopElem.appendChild( patElem ); + + QDomElement 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" ); + QDomElement saverElem = m_dom.createElement( "screensaver" ); + saverElem.setAttribute( "name", desktopConf.readEntry( "Saver" ) ); + m_root.appendChild( saverElem ); + + // 3. Icons + globalConf->setGroup( "Icons" ); + QDomElement iconElem = m_dom.createElement( "icons" ); + iconElem.setAttribute( "name", globalConf->readEntry( "Theme",KIconTheme::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 + KConfig * soundConf = new KConfig( "knotify.eventsrc", true ); + QStringList stdEvents; + stdEvents << "cannotopenfile" << "catastrophe" << "exitkde" << "fatalerror" + << "notification" << "printerror" << "startkde" << "warning" + << "messageCritical" << "messageInformation" << "messageWarning" + << "messageboxQuestion"; + + // 4.2 KWin sounds + KConfig * kwinSoundConf = new KConfig( "kwin.eventsrc", true ); + QStringList kwinEvents; + kwinEvents << "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"; + + QDomElement soundsElem = m_dom.createElement( "sounds" ); + createSoundList( stdEvents, "global", soundsElem, soundConf ); + createSoundList( kwinEvents, "kwin", soundsElem, kwinSoundConf ); + m_root.appendChild( soundsElem ); + delete soundConf; + delete kwinSoundConf; + + + // 5. Colors + QDomElement colorsElem = m_dom.createElement( "colors" ); + globalConf->setGroup( "KDE" ); + colorsElem.setAttribute( "contrast", globalConf->readNumEntry( "contrast", 7 ) ); + QStringList stdColors; + stdColors << "background" << "selectBackground" << "foreground" << "windowForeground" + << "windowBackground" << "selectForeground" << "buttonBackground" + << "buttonForeground" << "linkColor" << "visitedLinkColor" << "alternateBackground"; + + globalConf->setGroup( "General" ); + for ( QStringList::Iterator it = stdColors.begin(); it != stdColors.end(); ++it ) + createColorElem( ( *it ), "global", colorsElem, globalConf ); + + QStringList kwinColors; + kwinColors << "activeForeground" << "inactiveBackground" << "inactiveBlend" << "activeBackground" + << "activeBlend" << "inactiveForeground" << "activeTitleBtnBg" << "inactiveTitleBtnBg" + << "frame" << "inactiveFrame" << "handle" << "inactiveHandle"; + globalConf->setGroup( "WM" ); + for ( QStringList::Iterator it = kwinColors.begin(); it != kwinColors.end(); ++it ) + createColorElem( ( *it ), "kwin", colorsElem, globalConf ); + + m_root.appendChild( colorsElem ); + + // 6. Cursors + KConfig* mouseConf = new KConfig( "kcminputrc", true ); + mouseConf->setGroup( "Mouse" ); + QDomElement cursorsElem = m_dom.createElement( "cursors" ); + cursorsElem.setAttribute( "name", mouseConf->readEntry( "cursorTheme" ) ); + m_root.appendChild( cursorsElem ); + delete mouseConf; + // TODO copy the cursor theme? + + // 7. KWin + kwinConf.setGroup( "Style" ); + QDomElement wmElem = m_dom.createElement( "wm" ); + wmElem.setAttribute( "name", kwinConf.readEntry( "PluginLib" ) ); + wmElem.setAttribute( "type", "builtin" ); // TODO support pixmap themes when the kwin client gets ported + if ( kwinConf.readBoolEntry( "CustomButtonPositions" ) ) + { + QDomElement buttonsElem = m_dom.createElement( "buttons" ); + buttonsElem.setAttribute( "left", kwinConf.readEntry( "ButtonsOnLeft" ) ); + buttonsElem.setAttribute( "right", kwinConf.readEntry( "ButtonsOnRight" ) ); + wmElem.appendChild( buttonsElem ); + } + QDomElement borderElem = m_dom.createElement( "border" ); + borderElem.setAttribute( "size", kwinConf.readNumEntry( "BorderSize", 1 ) ); + wmElem.appendChild( borderElem ); + m_root.appendChild( wmElem ); + + // 8. Konqueror + KConfig konqConf( "konquerorrc", true ); + konqConf.setGroup( "Settings" ); + QDomElement konqElem = m_dom.createElement( "konqueror" ); + QDomElement konqWallElem = m_dom.createElement( "wallpaper" ); + QString bgImagePath = konqConf.readPathEntry( "BgImage" ); + konqWallElem.setAttribute( "url", processFilePath( "konqueror", bgImagePath ) ); + konqElem.appendChild( konqWallElem ); + QDomElement konqBgColorElem = m_dom.createElement( "bgcolor" ); + konqBgColorElem.setAttribute( "rgb", konqConf.readColorEntry( "BgColor" ).name() ); + konqElem.appendChild( konqBgColorElem ); + m_root.appendChild( konqElem ); + + // 9. Kicker (aka KDE Panel) + KConfig kickerConf( "kickerrc", true ); + kickerConf.setGroup( "General" ); + + QDomElement panelElem = m_dom.createElement( "panel" ); + + if ( kickerConf.readBoolEntry( "UseBackgroundTheme" ) ) + { + QDomElement backElem = m_dom.createElement( "background" ); + QString kbgPath = kickerConf.readPathEntry( "BackgroundTheme" ); + backElem.setAttribute( "url", processFilePath( "panel", kbgPath ) ); + backElem.setAttribute( "colorize", kickerConf.readBoolEntry( "ColorizeBackground" ) ); + panelElem.appendChild( backElem ); + } + + QDomElement transElem = m_dom.createElement( "transparent" ); + transElem.setAttribute( "value", kickerConf.readBoolEntry( "Transparent" ) ); + panelElem.appendChild( transElem ); + + QDomElement posElem = m_dom.createElement( "position" ); + posElem.setAttribute( "value", kickerConf.readEntry( "Position" ) ); + panelElem.appendChild( posElem ); + + + QDomElement showLeftHideButtonElem = m_dom.createElement( "showlefthidebutton" ); + showLeftHideButtonElem.setAttribute( "value", kickerConf.readBoolEntry( "ShowLeftHideButton" ) ); + panelElem.appendChild( showLeftHideButtonElem ); + + QDomElement showRightHideButtonElem = m_dom.createElement( "showrighthidebutton" ); + showRightHideButtonElem.setAttribute( "value", kickerConf.readBoolEntry( "ShowRightHideButton" ) ); + panelElem.appendChild( showRightHideButtonElem ); + + + + m_root.appendChild( panelElem ); + + // 10. Widget style + globalConf->setGroup( "General" ); + QDomElement widgetsElem = m_dom.createElement( "widgets" ); + widgetsElem.setAttribute( "name", globalConf->readEntry( "widgetStyle",KStyle::defaultStyle() ) ); + m_root.appendChild( widgetsElem ); + + // 12. + QDomElement fontsElem = m_dom.createElement( "fonts" ); + QStringList fonts; + fonts << "General" << "font" + << "General" << "fixed" + << "General" << "toolBarFont" + << "General" << "menuFont" + << "WM" << "activeFont" + << "General" << "taskbarFont" + << "FMSettings" << "StandardFont"; + + for ( QStringList::Iterator it = fonts.begin(); it != fonts.end(); ++it ) { + QString group = *it; ++it; + QString key = *it; + QString value; + + if ( group == "FMSettings" ) { + desktopConf.setGroup( group ); + value = desktopConf.readEntry( key ); + } + else { + globalConf->setGroup( group ); + value = globalConf->readEntry( key ); + } + QDomElement fontElem = m_dom.createElement( key ); + fontElem.setAttribute( "object", group ); + fontElem.setAttribute( "value", value ); + fontsElem.appendChild( fontElem ); + } + m_root.appendChild( fontsElem ); + + // Save the XML + QFile file( m_kgd->saveLocation( "themes", m_name + "/" ) + m_name + ".xml" ); + if ( file.open( IO_WriteOnly ) ) { + QTextStream stream( &file ); + m_dom.save( stream, 2 ); + file.close(); + } + + QString 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 + "/" ), QString::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; + + QString themeDir = m_kgd->findResourceDir( "themes", m_name + "/" + m_name + ".xml") + m_name + "/"; + kdDebug() << "Theme dir: " << themeDir << endl; + + // 2. Background theme + + QDomNodeList desktopList = m_dom.elementsByTagName( "desktop" ); + KConfig desktopConf( "kdesktoprc" ); + desktopConf.setGroup( "Background Common" ); + + for ( uint i = 0; i <= desktopList.count(); i++ ) + { + QDomElement desktopElem = desktopList.item( i ).toElement(); + if ( !desktopElem.isNull() ) + { + // TODO optimize, don't write several times the common section + bool common = static_cast( desktopElem.attribute( "common", "true" ).toUInt() ); + desktopConf.writeEntry( "CommonDesktop", common ); + desktopConf.writeEntry( "DeskNum", desktopElem.attribute( "number", "0" ).toUInt() ); + + desktopConf.setGroup( QString( "Desktop%1" ).arg( i ) ); + desktopConf.writeEntry( "BackgroundMode", getProperty( desktopElem, "mode", "id" ) ); + desktopConf.writeEntry( "Color1", QColor( getProperty( desktopElem, "color1", "rgb" ) ) ); + desktopConf.writeEntry( "Color2", QColor( getProperty( desktopElem, "color2", "rgb" ) ) ); + desktopConf.writeEntry( "BlendMode", getProperty( desktopElem, "blending", "mode" ) ); + desktopConf.writeEntry( "BlendBalance", getProperty( desktopElem, "blending", "balance" ) ); + desktopConf.writeEntry( "ReverseBlending", + static_cast( getProperty( desktopElem, "blending", "reverse" ).toUInt() ) ); + desktopConf.writeEntry( "Pattern", getProperty( desktopElem, "pattern", "name" ) ); + desktopConf.writeEntry( "Wallpaper", + unprocessFilePath( "desktop", getProperty( desktopElem, "wallpaper", "url" ) ) ); + desktopConf.writeEntry( "WallpaperMode", getProperty( desktopElem, "wallpaper", "mode" ) ); + + if ( common ) + break; // stop here + } + } + + // 11. Screensaver + QDomElement 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 elem present + // reconfigure kdesktop. kdesktop will notify all clients + DCOPClient *client = kapp->dcopClient(); + if ( !client->isAttached() ) + client->attach(); + client->send("kdesktop", "KBackgroundIface", "configure()", ""); + // FIXME Xinerama + + // 3. Icons + QDomElement iconElem = m_dom.elementsByTagName( "icons" ).item( 0 ).toElement(); + if ( !iconElem.isNull() ) + { + KConfig * iconConf = KGlobal::config(); + iconConf->setGroup( "Icons" ); + iconConf->writeEntry( "Theme", iconElem.attribute( "name", "crystalsvg" ), true, true ); + + QDomNodeList iconList = iconElem.childNodes(); + for ( uint i = 0; i < iconList.count(); i++ ) + { + QDomElement iconSubElem = iconList.item( i ).toElement(); + QString 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" ); + + QString iconName = iconSubElem.tagName(); + if ( iconName.contains( "Color" ) ) + { + QColor iconColor = QColor( 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( iconSubElem.attribute( "value" ).toUInt() ), true, true ); + } + iconConf->sync(); + + for ( int i = 0; i < KIcon::LastGroup; i++ ) + KIPC::sendMessageAll( KIPC::IconChanged, i ); + KService::rebuildKSycoca( m_parent ); + } + + // 4. Sounds + QDomElement soundsElem = m_dom.elementsByTagName( "sounds" ).item( 0 ).toElement(); + if ( !soundsElem.isNull() ) + { + KConfig soundConf( "knotify.eventsrc" ); + KConfig kwinSoundConf( "kwin.eventsrc" ); + QDomNodeList eventList = soundsElem.elementsByTagName( "event" ); + for ( uint i = 0; i < eventList.count(); i++ ) + { + QDomElement eventElem = eventList.item( i ).toElement(); + QString 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 == "kwin" ) + { + kwinSoundConf.setGroup( eventElem.attribute( "name" ) ); + kwinSoundConf.writeEntry( "soundfile", unprocessFilePath( "sounds", eventElem.attribute( "url" ) ) ); + kwinSoundConf.writeEntry( "presentation", soundConf.readNumEntry( "presentation" ) | 1 ); + } + } + + soundConf.sync(); + kwinSoundConf.sync(); + client->send("knotify", "", "reconfigure()", ""); + // TODO signal kwin sounds change? + } + + // 5. Colors + QDomElement colorsElem = m_dom.elementsByTagName( "colors" ).item( 0 ).toElement(); + + if ( !colorsElem.isNull() ) + { + QDomNodeList colorList = colorsElem.childNodes(); + KConfig * colorConf = KGlobal::config(); + + QString sCurrentScheme = locateLocal("data", "kdisplay/color-schemes/thememgr.kcsrc"); + KSimpleConfig *colorScheme = new KSimpleConfig( sCurrentScheme ); + colorScheme->setGroup("Color Scheme" ); + + for ( uint i = 0; i < colorList.count(); i++ ) + { + QDomElement colorElem = colorList.item( i ).toElement(); + QString object = colorElem.attribute( "object" ); + if ( object == "global" ) + colorConf->setGroup( "General" ); + else if ( object == "kwin" ) + colorConf->setGroup( "WM" ); + + QString colName = colorElem.tagName(); + QColor curColor = QColor( 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 + QDomElement cursorsElem = m_dom.elementsByTagName( "cursors" ).item( 0 ).toElement(); + + if ( !cursorsElem.isNull() ) + { + KConfig mouseConf( "kcminputrc" ); + mouseConf.setGroup( "Mouse" ); + mouseConf.writeEntry( "cursorTheme", cursorsElem.attribute( "name" )); + // FIXME is there a way to notify KDE of cursor changes? + } + + // 7. KWin + QDomElement wmElem = m_dom.elementsByTagName( "wm" ).item( 0 ).toElement(); + + if ( !wmElem.isNull() ) + { + KConfig kwinConf( "kwinrc" ); + kwinConf.setGroup( "Style" ); + QString type = wmElem.attribute( "type" ); + if ( type == "builtin" ) + kwinConf.writeEntry( "PluginLib", wmElem.attribute( "name" ) ); + //else // TODO support custom themes + QDomNodeList buttons = wmElem.elementsByTagName ("buttons"); + if ( buttons.count() > 0 ) + { + kwinConf.writeEntry( "CustomButtonPositions", true ); + kwinConf.writeEntry( "ButtonsOnLeft", getProperty( wmElem, "buttons", "left" ) ); + kwinConf.writeEntry( "ButtonsOnRight", getProperty( wmElem, "buttons", "right" ) ); + } + else + { + kwinConf.writeEntry( "CustomButtonPositions", false ); + } + kwinConf.writeEntry( "BorderSize", getProperty( wmElem, "border", "size" ) ); + + kwinConf.sync(); + client->send( "kwin", "", "reconfigure()", "" ); + } + + // 8. Konqueror + QDomElement konqElem = m_dom.elementsByTagName( "konqueror" ).item( 0 ).toElement(); + + if ( !konqElem.isNull() ) + { + KConfig konqConf( "konquerorrc" ); + konqConf.setGroup( "Settings" ); + konqConf.writeEntry( "BgImage", unprocessFilePath( "konqueror", getProperty( konqElem, "wallpaper", "url" ) ) ); + konqConf.writeEntry( "BgColor", QColor( getProperty( konqElem, "bgcolor", "rgb" ) ) ); + + konqConf.sync(); + client->send("konqueror*", "KonquerorIface", "reparseConfiguration()", ""); // FIXME seems not to work :( + } + + // 9. Kicker + QDomElement panelElem = m_dom.elementsByTagName( "panel" ).item( 0 ).toElement(); + + if ( !panelElem.isNull() ) + { + KConfig kickerConf( "kickerrc" ); + kickerConf.setGroup( "General" ); + QString kickerBgUrl = getProperty( panelElem, "background", "url" ); + if ( !kickerBgUrl.isEmpty() ) + { + kickerConf.writeEntry( "UseBackgroundTheme", true ); + kickerConf.writeEntry( "BackgroundTheme", unprocessFilePath( "panel", kickerBgUrl ) ); + kickerConf.writeEntry( "ColorizeBackground", + static_cast( getProperty( panelElem, "background", "colorize" ).toUInt() ) ); + } + kickerConf.writeEntry( "Transparent", + static_cast( getProperty( panelElem, "transparent", "value" ).toUInt() ) ); + + kickerConf.writeEntry( "Position", static_cast (getProperty( panelElem, "position", "value" ).toUInt() )); + + kickerConf.writeEntry( "ShowLeftHideButton", static_cast( getProperty( panelElem, "showlefthidebutton", "value").toInt())); + + kickerConf.writeEntry( "ShowRightHideButton", static_cast( getProperty( panelElem, "showrighthidebutton", "value").toInt())); + + kickerConf.sync(); + client->send("kicker", "Panel", "configure()", ""); + } + + // 10. Widget style + QDomElement widgetsElem = m_dom.elementsByTagName( "widgets" ).item( 0 ).toElement(); + + if ( !widgetsElem.isNull() ) + { + KConfig * widgetConf = KGlobal::config(); + widgetConf->setGroup( "General" ); + widgetConf->writeEntry( "widgetStyle", widgetsElem.attribute( "name" ), true, true ); + widgetConf->sync(); + KIPC::sendMessageAll( KIPC::StyleChanged ); + } + + // 12. Fonts + QDomElement fontsElem = m_dom.elementsByTagName( "fonts" ).item( 0 ).toElement(); + if ( !fontsElem.isNull() ) + { + KConfig * fontsConf = KGlobal::config(); + KConfig * kde1xConf = new KSimpleConfig( QDir::homeDirPath() + "/.kderc" ); + kde1xConf->setGroup( "General" ); + + QDomNodeList fontList = fontsElem.childNodes(); + for ( uint i = 0; i < fontList.count(); i++ ) + { + QDomElement fontElem = fontList.item( i ).toElement(); + QString fontName = fontElem.tagName(); + QString fontValue = fontElem.attribute( "value" ); + QString 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 QString & name ) +{ + kdDebug() << "Going to remove theme: " << name << endl; + return KIO::NetAccess::del( KGlobal::dirs()->saveLocation( "themes", name + "/" ), 0L ); +} + +void KTheme::setProperty( const QString & name, const QString & value, QDomElement parent ) +{ + QDomElement tmp = m_dom.createElement( name ); + tmp.setAttribute( "value", value ); + parent.appendChild( tmp ); +} + +QString KTheme::getProperty( const QString & name ) const +{ + QDomNodeList _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 QString::null; + } +} + +QString KTheme::getProperty( QDomElement parent, const QString & tag, + const QString & attr ) const +{ + QDomNodeList _list = parent.elementsByTagName( tag ); + + if ( _list.count() != 0 ) + return _list.item( 0 ).toElement().attribute( attr ); + else + { + kdWarning() << QString( "No such property found: %1->%2->%3" ) + .arg( parent.tagName() ).arg( tag ).arg( attr ) << endl; + return QString::null; + } +} + +void KTheme::createIconElems( const QString & group, const QString & object, + QDomElement parent, KConfig * cfg ) +{ + cfg->setGroup( group ); + QStringList elemNames; + elemNames << "Animated" << "DoublePixels" << "Size" + << "ActiveColor" << "ActiveColor2" << "ActiveEffect" + << "ActiveSemiTransparent" << "ActiveValue" + << "DefaultColor" << "DefaultColor2" << "DefaultEffect" + << "DefaultSemiTransparent" << "DefaultValue" + << "DisabledColor" << "DisabledColor2" << "DisabledEffect" + << "DisabledSemiTransparent" << "DisabledValue"; + for ( QStringList::ConstIterator it = elemNames.begin(); it != elemNames.end(); ++it ) { + if ( (*it).contains( "Color" ) ) + createColorElem( *it, object, parent, cfg ); + else + { + QDomElement 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 QString & name, const QString & object, + QDomElement parent, KConfig * cfg ) +{ + QColor color = cfg->readColorEntry( name ); + if ( color.isValid() ) + { + QDomElement tmpCol = m_dom.createElement( name ); + tmpCol.setAttribute( "rgb", color.name() ); + tmpCol.setAttribute( "object", object ); + parent.appendChild( tmpCol ); + } +} + +void KTheme::createSoundList( const QStringList & events, const QString & object, + QDomElement parent, KConfig * cfg ) +{ + for ( QStringList::ConstIterator it = events.begin(); it != events.end(); ++it ) + { + QString group = ( *it ); + if ( cfg->hasGroup( group ) ) + { + cfg->setGroup( group ); + QString soundURL = cfg->readPathEntry( "soundfile" ); + int pres = cfg->readNumEntry( "presentation", 0 ); + if ( !soundURL.isEmpty() && ( ( pres & 1 ) == 1 ) ) + { + QDomElement eventElem = m_dom.createElement( "event" ); + eventElem.setAttribute( "object", object ); + eventElem.setAttribute( "name", group ); + eventElem.setAttribute( "url", processFilePath( "sounds", soundURL ) ); + parent.appendChild( eventElem ); + } + } + } +} + +QString KTheme::processFilePath( const QString & section, const QString & path ) +{ + QFileInfo 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 QString::null; // an error occured or the resource doesn't exist +} + +QString KTheme::unprocessFilePath( const QString & section, QString path ) +{ + if ( path.startsWith( "theme:/" ) ) + return path.replace( QRegExp( "^theme:/" ), m_kgd->findResourceDir( "themes", m_name + "/" + m_name + ".xml") + m_name + "/" ); + + if ( QFile::exists( path ) ) + return path; + else // try to find it in the system + return findResource( section, path ); +} + +void KTheme::setAuthor( const QString & author ) +{ + setProperty( "author", author, m_general ); +} + +void KTheme::setEmail( const QString & email ) +{ + setProperty( "email", email, m_general ); +} + +void KTheme::setHomepage( const QString & homepage ) +{ + setProperty( "homepage", homepage, m_general ); +} + +void KTheme::setComment( const QString & comment ) +{ + setProperty( "comment", comment, m_general ); +} + +void KTheme::setVersion( const QString & version ) +{ + setProperty( "version", version, m_general ); +} + +void KTheme::addPreview() +{ + QString file = m_kgd->saveLocation( "themes", m_name + "/" ) + m_name + ".preview.png"; + kdDebug() << "Adding preview: " << file << endl; + QPixmap snapshot = QPixmap::grabWindow( qt_xrootwin() ); + snapshot.save( file, "PNG" ); +} + +bool KTheme::copyFile( const QString & from, const QString & to ) +{ + // we overwrite b/c of restoring the "original" theme + return KIO::NetAccess::file_copy( from, to, -1, true /*overwrite*/ ); +} + +QString KTheme::findResource( const QString & section, const QString & 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 QString::null; + } +} diff --git a/kcontrol/kthememanager/ktheme.h b/kcontrol/kthememanager/ktheme.h new file mode 100644 index 000000000..1401b49e7 --- /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 + + 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 +#include +#include +#include +#include + +#include + +class KStandardDirs; +class KConfig; + +/// 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 + */ +class KTheme +{ +public: + /** + * Constructs KTheme using an installed theme + * @param xmlFile The theme's XML file + */ + KTheme( QWidget *parent, const QString & xmlFile ); + + /** + * Constructs an empty theme, to be used with + * #createYourself() + * @param create Whether to start the DOM tree + */ + KTheme( QWidget *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) + */ + QString 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 QString & name ); + + /** + * @return the theme name + */ + QString name() const { return m_name; } + /** + * Set the theme name + */ + void setName( const QString & name ); + + QString author() const { + return getProperty( "author" ); + } + void setAuthor( const QString & author ); + + QString email() const { + return getProperty( "email" ); + } + void setEmail( const QString & email ); + + QString homepage() const { + return getProperty( "homepage" ); + } + void setHomepage( const QString & homepage ); + + QString comment() const { + return getProperty( "comment" ); + } + void setComment ( const QString & comment ); + + QString version() const { + return getProperty( "version" ); + } + void setVersion ( const QString & 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 QString & name, + const QString & value, + QDomElement parent ); + /** + * Get a simple property from the "general" section of the DOM tree + */ + QString getProperty( const QString & 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 + */ + QString getProperty( QDomElement parent, const QString & tag, + const QString & attr ) const; + + /** + * Creates a list of "icon" elements based on: + * @param group The group in the KConfig object @p cfg + * @param object Specifier (similiar, but not identical to @p group) + * @param parent Parent element to append to + * @param cfg The KConfig object to work with + */ + void createIconElems( const QString & group, const QString & object, + QDomElement parent, KConfig * 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 KConfig object to work with + */ + void createColorElem( const QString & name, const QString & object, + QDomElement parent, KConfig * cfg ); + /** + * Creates a list of "event" elements based on: + * @param events The list of events to work on + * @param object Specifier (currently "global" or "kwin") + * @param parent Parent element to append to + * @param cfg The KConfig object to work with + */ + void createSoundList( const QStringList & events, const QString & object, + QDomElement parent, KConfig * 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 QString::null + * in case the resource couldn't be found + */ + QString processFilePath( const QString & section, const QString & path ); + + /** + * Converts an internal theme:/ representation of a resource + * to a real path + */ + QString unprocessFilePath( const QString & section, QString path ); + + /** + * Wrapper around KIO::NetAccess::file_copy + */ + bool copyFile( const QString & from, const QString & to ); + + /** + * Wrapper around KGlobal::dirs()->findResource() + * @param section Section to work on (desktop, sounds, panel etc) + * @param path The file to find + */ + QString findResource( const QString & section, const QString & path ); + + /// name of the theme + QString m_name; + + /// DOM holding the theme + QDomDocument m_dom; + /// the DOM root element + QDomElement m_root; + /// "general" section + QDomElement m_general; + + KStandardDirs * m_kgd; + + QGuardedPtr m_parent; +}; + +#endif diff --git a/kcontrol/kthememanager/kthemedlg.ui b/kcontrol/kthememanager/kthemedlg.ui new file mode 100644 index 000000000..4b46fdc26 --- /dev/null +++ b/kcontrol/kthememanager/kthemedlg.ui @@ -0,0 +1,518 @@ + +KThemeDlg +Lukas Tinkl <lukas@kde.org> + + + KThemeDlg + + + + 0 + 0 + 687 + 382 + + + + + 3 + 3 + 0 + 0 + + + + + unnamed + + + 0 + + + + layout2 + + + + unnamed + + + + textLabel1 + + + NoFrame + + + Plain + + + Choose your visual KDE theme: + + + + + spacer2 + + + Horizontal + + + MinimumExpanding + + + + 170 + 20 + + + + + + lbGet + + + Get new themes... + + + http://themes.kde.org + + + Go to the KDE themes website + + + true + + + + + + + layout1 + + + + unnamed + + + + lbPreview + + + + 5 + 5 + 1 + 0 + + + + Box + + + AlignCenter + + + + + btnRemove + + + &Remove Theme + + + + + btnCreate + + + Create &New Theme... + + + + + btnInstall + + + &Install New Theme... + + + + + + Theme + + + true + + + false + + + + lvThemes + + + + 7 + 7 + 0 + 0 + + + + true + + + AllColumns + + + + + + + line1 + + + HLine + + + Sunken + + + Horizontal + + + + + textLabel1_2 + + + Customize your theme: + + + + + layout4 + + + + unnamed + + + + btnBackground + + + + 5 + 0 + 0 + 0 + + + + + 80 + 60 + + + + + 32767 + 60 + + + + TabFocus + + + + + + true + + + Background + + + Customize the desktop background + + + + + btnColors + + + + 5 + 0 + 0 + 0 + + + + + 80 + 60 + + + + + 32767 + 60 + + + + TabFocus + + + + + + true + + + Colors + + + Customize colors + + + + + btnStyle + + + + 5 + 0 + 0 + 0 + + + + + 80 + 60 + + + + + 32767 + 60 + + + + TabFocus + + + + + + true + + + Style + + + Customize the widget style + + + + + btnIcons + + + + 5 + 0 + 0 + 0 + + + + + 80 + 60 + + + + + 32767 + 60 + + + + TabFocus + + + + + + true + + + Icons + + + Customize the icon theme + + + + + btnFonts + + + + 5 + 0 + 0 + 0 + + + + + 80 + 60 + + + + + 32767 + 60 + + + + TabFocus + + + + + + true + + + Fonts + + + Customize the font theme + + + + + btnSaver + + + + 5 + 0 + 0 + 0 + + + + + 80 + 60 + + + + + 32767 + 60 + + + + TabFocus + + + + + + true + + + Screen Saver + + + Customize the screen saver + + + + + + + + + lbGet + leftClickedURL(const QString&) + KThemeDlg + startKonqui(const QString&) + + + btnBackground + clicked() + KThemeDlg + startBackground() + + + btnColors + clicked() + KThemeDlg + startColors() + + + btnStyle + clicked() + KThemeDlg + startStyle() + + + btnIcons + clicked() + KThemeDlg + startIcons() + + + btnFonts + clicked() + KThemeDlg + startFonts() + + + btnSaver + clicked() + KThemeDlg + startSaver() + + + + lvThemes + btnInstall + btnRemove + btnCreate + btnBackground + btnColors + btnStyle + btnIcons + btnFonts + btnSaver + + + kthemedlg.ui.h + + + startKonqui( const QString & url ) + startBackground() + startColors() + startStyle() + startIcons() + startFonts() + startSaver() + + + + kurllabel.h + + diff --git a/kcontrol/kthememanager/kthemedlg.ui.h b/kcontrol/kthememanager/kthemedlg.ui.h new file mode 100644 index 000000000..53f296a1c --- /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 + +void KThemeDlg::startKonqui( const QString & url ) +{ + (void) new KRun(url); +} + + +void KThemeDlg::startBackground() +{ + KRun::runCommand("kcmshell kde-background"); +} + + +void KThemeDlg::startColors() +{ + KRun::runCommand("kcmshell kde-colors"); +} + + +void KThemeDlg::startStyle() +{ + KRun::runCommand("kcmshell kde-style"); +} + + +void KThemeDlg::startIcons() +{ + KRun::runCommand("kcmshell kde-icons"); +} + +void KThemeDlg::startFonts() +{ + KRun::runCommand("kcmshell kde-fonts"); +} + + +void KThemeDlg::startSaver() +{ + KRun::runCommand("kcmshell kde-screensaver"); +} diff --git a/kcontrol/kthememanager/kthememanager.cpp b/kcontrol/kthememanager/kthememanager.cpp new file mode 100644 index 000000000..d5efc65cd --- /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 + + 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "kthememanager.h" +#include "knewthemedlg.h" +#include "config.h" + +kthememanager::kthememanager( QWidget *parent, const char *name ) + : KCModule( parent, name ), m_theme( 0 ), m_origTheme( 0 ) +{ + + KAboutData *about = new KAboutData("kthememanager", I18N_NOOP("KDE Theme Manager"), + "0.4", I18N_NOOP("This control module handles installing, removing and " + "creating visual KDE themes."), + KAboutData::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 KDE themes.")); + + setButtons( KCModule::Default|KCModule::Apply|KCModule::Help ); + + setAcceptDrops( true ); + init(); + + QBoxLayout *top = new QVBoxLayout(this, 0, KDialog::spacingHint()); + + dlg = new KThemeDlg(this); + top->addWidget( dlg ); + + dlg->lvThemes->setColumnWidthMode( 0, QListView::Maximum ); + + connect( ( QObject * )dlg->btnInstall, SIGNAL( clicked() ), + this, SLOT( slotInstallTheme() ) ); + + connect( ( QObject * )dlg->btnRemove, SIGNAL( clicked() ), + this, SLOT( slotRemoveTheme() ) ); + + connect( ( QObject * )dlg->btnCreate, SIGNAL( clicked() ), + this, SLOT( slotCreateTheme() ) ); + + connect( ( QObject * )dlg->lvThemes, SIGNAL( clicked( QListViewItem * ) ), + this, SLOT( slotThemeChanged( QListViewItem * ) ) ); + + connect( ( QObject * )dlg->lvThemes, SIGNAL( currentChanged( QListViewItem * ) ), + this, SLOT( slotThemeChanged( QListViewItem * ) ) ); + + connect( this, SIGNAL( filesDropped( const KURL::List& ) ), + this, SLOT( updateButton() ) ); + + connect( ( QObject * )dlg->lvThemes, SIGNAL( clicked( QListViewItem * ) ), + this, 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() +{ + KGlobal::dirs()->addResourceType( "themes", KStandardDirs::kde_default("data") + + "kthememanager/themes/" ); +} + +void kthememanager::updateButton() +{ + QListViewItem * cur = dlg->lvThemes->currentItem(); + bool enable = (cur != 0); + if (enable) { + enable = QFile(KGlobal::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 + KConfig conf("kcmthememanagerrc", false, false); + + conf.setReadDefaults( useDefaults ); + + conf.setGroup( "General" ); + QString themeName = conf.readEntry( "CurrentTheme" ); + QListViewItem * 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() +{ + QListViewItem * cur = dlg->lvThemes->currentItem(); + + if ( cur ) + { + QString themeName = cur->text( 0 ); + + m_theme = new KTheme( this, KGlobal::dirs()->findResource( "themes", themeName + "/" + themeName + ".xml") ); + m_theme->apply(); + + // Save the current theme name + KConfig 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( QPixmap() ); + + QStringList themes = KGlobal::dirs()->findAllResources( "themes", "*.xml", true /*recursive*/ ); + + QStringList::const_iterator it; + + for ( it = themes.begin(); it != themes.end(); ++it ) + { + KTheme theme( this, ( *it ) ); + QString name = theme.name(); + if ( name != ORIGINAL_THEME ) // skip the "original" theme + ( void ) new QListViewItem( dlg->lvThemes, name, theme.comment() ); + } + + kdDebug() << "Available themes: " << themes << endl; +} + +float kthememanager::getThemeVersion( const QString & themeName ) +{ + QStringList themes = KGlobal::dirs()->findAllResources( "themes", "*.xml", true /*recursive*/ ); + + QStringList::const_iterator it; + + for ( it = themes.begin(); it != themes.end(); ++it ) + { + KTheme theme( 0L, ( *it ) ); + QString 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() ) + { + QString themeName = QFileInfo( 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 + QListViewItem * cur = dlg->lvThemes->currentItem(); + // ask and remove it + if ( cur ) + { + QString themeName = cur->text( 0 ); + if ( KMessageBox::warningContinueCancel( this, "" + i18n( "Do you really want to remove the theme %1?" ).arg( themeName ), + i18n( "Remove Theme" ), KGuiItem( i18n( "&Remove" ), "editdelete" ) ) + == KMessageBox::Continue ) + { + KTheme::remove( themeName ); + listThemes(); + } + updateButton(); + } +} + +bool kthememanager::themeExist(const QString &_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() == QDialog::Accepted ) + { + + QString 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() ); + + QString 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( QListViewItem * item ) +{ + if ( item ) + { + QString themeName = item->text(0); + kdDebug() << "Activated theme: " << themeName << endl; + + QString themeDir = KGlobal::dirs()->findResourceDir( "themes", themeName + "/" + themeName + ".xml") + themeName + "/"; + + QString pixFile = themeDir + themeName + ".preview.png"; + + if ( QFile::exists( pixFile ) ) + { + updatePreview( pixFile ); + } + else + { + dlg->lbPreview->setPixmap( QPixmap() ); + dlg->lbPreview->setText( i18n( "This theme does not contain a preview." ) ); + } + + KTheme theme( this, themeDir + themeName + ".xml" ); + QToolTip::remove( dlg->lbPreview ); + QToolTip::add( dlg->lbPreview, "" + i18n( "Author: %1
Email: %2
Version: %3
Homepage: %4" ) + .arg( theme.author() ).arg( theme.email() ) + .arg( theme.version() ).arg( theme.homepage() ) + "
"); + + emit changed( true ); + } +} + +void kthememanager::dragEnterEvent( QDragEnterEvent * ev ) +{ + ev->accept( KURLDrag::canDecode( ev ) ); +} + +void kthememanager::dropEvent( QDropEvent * 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( p ); + ( void ) new KThemeDetailsItem( dlg->lvDetails, s->name(), s->pixmap( KIcon::Desktop ), s->exec() ); + } + } + + dlg->lvDetails->sort();*/ + + // For now use a static list + KIconLoader * il = KGlobal::iconLoader(); + dlg->btnBackground->setIconSet( il->loadIconSet( "background", KIcon::Desktop, 32 ) ); + dlg->btnColors->setIconSet( il->loadIconSet( "colorscm", KIcon::Desktop, 32 ) ); + dlg->btnStyle->setIconSet( il->loadIconSet( "style", KIcon::Desktop, 32 ) ); + dlg->btnIcons->setIconSet( il->loadIconSet( "icons", KIcon::Desktop, 32 ) ); + dlg->btnFonts->setIconSet( il->loadIconSet( "fonts", KIcon::Desktop, 32 ) ); + dlg->btnSaver->setIconSet( il->loadIconSet( "kscreensaver", KIcon::Desktop, 32 ) ); +} + +void kthememanager::updatePreview( const QString & pixFile ) +{ + kdDebug() << "Preview is in file: " << pixFile << endl; + QImage preview( pixFile, "PNG" ); + if (preview.width()>dlg->lbPreview->contentsRect().width() || + preview.height()>dlg->lbPreview->contentsRect().height() ) + preview = preview.smoothScale( dlg->lbPreview->contentsRect().size(), QImage::ScaleMin ); + QPixmap pix; + pix.convertFromImage( preview ); + dlg->lbPreview->setPixmap( pix ); +} + +extern "C" +{ + KDE_EXPORT KCModule *create_kthememanager(QWidget *parent, const char *) + { + KGlobal::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..d4c37c965 --- /dev/null +++ b/kcontrol/kthememanager/kthememanager.desktop @@ -0,0 +1,220 @@ +[Desktop Entry] +Comment=Manage global KDE visual themes +Comment[af]=Bestuurder KDE se globale visuele temas +Comment[az]=Qlobal KDE əyani örtüklərini idarə et +Comment[be]=Кіраванне глабальнымі візуальнымі тэмамі KDE +Comment[bg]=Управление на темите +Comment[bn]=গ্লোবাল কে.ডি.ই. ভিসুয়াল থীম ব্যবস্থাপনা +Comment[bs]=Upravljanje globalnim KDE vizuelnim temama +Comment[ca]=Gestiona els temes visuals globals del KDE +Comment[cs]=Správce motivů pracovní plochy +Comment[csb]=Sprôwiôj témą KDE +Comment[cy]=Rheoli themau gweledol KDE eang +Comment[da]=Håndtering af globale visuelle temaer for KDE +Comment[de]=Globale KDE-Designs verwalten +Comment[el]=Διαχειριστής καθολικών οπτικών θεμάτων του KDE +Comment[eo]=Administras mondan KDEan etosoj +Comment[es]=Gestión global de los temas visuales de KDE +Comment[et]=KDE globaalsete teemade haldur +Comment[eu]=Kudeatu KDEren gai bisual orokorrak +Comment[fa]=مدیریت چهره‌های مرئی KDE سراسری +Comment[fi]=Ylläpidä KDE:n teemoja +Comment[fr]=Gestionnaire de thèmes visuels globaux de KDE +Comment[fy]=Algemiene fisuele tema's fan KDE beheare +Comment[gl]=Xestionar temas visuais globais de KDE +Comment[he]=מנהל ערכות נושא גלובליות עבור KDE +Comment[hi]=वैश्विक केडीई दृश्यमय प्रसंग प्रबंधित करें +Comment[hr]=Upravljanje općim KDE vizualnim temama +Comment[hu]=KDE-témák kezelése +Comment[is]=Stjórna víðværum KDE þemum +Comment[it]=Gestore dei temi globali di KDE +Comment[ja]=グローバル KDE 外観テーマの管理 +Comment[ka]=KDE-ს ვიზუალური თემბის გლობალური მენეჯმენტი +Comment[kk]=KDE жалпы көрініс нақыштарын басқару +Comment[km]=គ្រប់គ្រង​ស្បែក​រូបភាព KDE ទាំងអស់ +Comment[ko]=전역 KDE 시각 테마 관리 +Comment[lt]=Globaliai tvarkyti KDE vizualines temas +Comment[lv]=KDE izskata tēmu pārvaldīšana +Comment[mk]=Менаџирајте ги глобалните KDE визуелни теми +Comment[ms]=Urus tema visual KDE global +Comment[mt]=Immaniġġja temi viżwali globali tal-KDE +Comment[nb]=Velg blant KDE-temaer for hele brukerflaten +Comment[nds]=Globale KDE-Muster instellen +Comment[ne]=विश्वव्यापी KDE दृश्य विषयवस्तु व्यवस्थापन गर्नुहोस् +Comment[nl]=Algemene visuele thema's van KDE beheren +Comment[nn]=Vel mellom KDE-tema for heile brukarflata +Comment[pa]=ਮੁੱਢਲੇ KDE ਦਿੱਖ ਸਰੂਪ ਪਰਬੰਧ +Comment[pl]=Zarządzaj motywami KDE +Comment[pt]=Gestão global de temas visuais do KDE +Comment[pt_BR]=Gerencia temas globais do KDE +Comment[ro]=Administrează tematicile vizuale KDE globale +Comment[ru]=Менеджер глобальных визуальных тем KDE +Comment[rw]=Kuyobora insanganyamatsiko igaragara KDE rusange +Comment[se]=Hálddaš oppalaš visuella KDE-fáttáid +Comment[sk]=Globálny správca tém +Comment[sl]=Upravitelj vizualnih tem za KDE +Comment[sr]=Управљање KDE-овим визуелним темама +Comment[sr@Latn]=Upravljanje KDE-ovim vizuelnim temama +Comment[sv]=Hantera KDE:s allmänna visuella teman +Comment[ta]=பொது KDE காட்சி பொருளை மேல்பார்வையிடு +Comment[tg]=Мудири мавзӯъҳои визуалии KDE дар шабака +Comment[th]=จัดการชุดตกแต่งของ KDE +Comment[tr]=Evrensel KDE ekran temalarını yönet +Comment[tt]=KDE'nıñ tışlaw törlären caylaw idäräse +Comment[uk]=Керування глобальними темами KDE +Comment[vi]=Trình quản lý các sắc thái của KDE +Comment[wa]=Manaedjî tinmes pol rivnance globåle di KDE +Comment[zh_CN]=管理全局 KDE 视觉主题 +Comment[zh_TW]=管理全域 KDE 視覺佈景 +Exec=kcmshell 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-KDE-FactoryName=kthememanager +X-KDE-Library=kthememanager +Categories=Qt;KDE;X-KDE-settings-looknfeel; diff --git a/kcontrol/kthememanager/kthememanager.h b/kcontrol/kthememanager/kthememanager.h new file mode 100644 index 000000000..972251f6a --- /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 + + 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 +#include +#include +#include + +#include "kthemedlg.h" +#include "ktheme.h" + +class QString; + +class KAboutData; + +#define ORIGINAL_THEME "original" // no i18n() here!!! + +/* +class KIconViewItem; + +class KThemeDetailsItem: public KIconViewItem +{ +public: + KThemeDetailsItem( KIconView * parent, const QString & text, const QPixmap & icon, const QString & execString ) + : KIconViewItem( parent, text, icon ) { m_exec = execString; } + virtual ~KThemeDetailsItem() { }; + + void exec() { + ( void ) new KRun( m_exec ); + } +private: + QString 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 + */ +class kthememanager: public KCModule +{ + Q_OBJECT +public: + kthememanager( QWidget *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 ( QDragEnterEvent * ev ); + void dropEvent ( QDropEvent * 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( QListViewItem * 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 QString & themeName ); + + void queryLNFModules(); + + /** + * Updates the preview widget + */ + void updatePreview( const QString & pixFile ); + bool themeExist(const QString &_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..905b0749a --- /dev/null +++ b/kcontrol/kthememanager/newthemewidget.ui @@ -0,0 +1,130 @@ + +NewThemeWidget +Lukas Tinkl <lukas@kde.org> + + + NewThemeWidget + + + + 0 + 0 + 537 + 431 + + + + + unnamed + + + + textLabel1 + + + &Theme name: + + + leName + + + + + textLabel2 + + + &Author: + + + leAuthor + + + + + textLabel3 + + + &Email: + + + leEmail + + + + + textLabel4 + + + &Homepage: + + + leHomepage + + + + + leEmail + + + + + leName + + + + + leHomepage + + + + + leAuthor + + + + + textLabel5 + + + Co&mment: + + + AlignTop + + + teComment + + + + + teComment + + + + + leVersion + + + + + textLabel6 + + + &Version: + + + leVersion + + + + + + leName + leAuthor + leEmail + leHomepage + leVersion + teComment + + + diff --git a/kcontrol/kthememanager/x-ktheme.desktop b/kcontrol/kthememanager/x-ktheme.desktop new file mode 100644 index 000000000..6efaa20d6 --- /dev/null +++ b/kcontrol/kthememanager/x-ktheme.desktop @@ -0,0 +1,84 @@ +[Desktop Entry] +MimeType=application/x-ktheme +Comment=KDE Theme +Comment[af]=KDE Tema +Comment[ar]=سمة KDE +Comment[az]=KDE Örtüyü +Comment[be]=Тэма KDE +Comment[bg]=Тема за KDE +Comment[bn]=কে.ডি.ই. থীম +Comment[br]=Giz KDE +Comment[bs]=KDE tema +Comment[ca]=Tema KDE +Comment[cs]=KDE motiv +Comment[csb]=Téma KDE +Comment[cy]=Thema KDE +Comment[da]=KDE-tema +Comment[de]=KDE-Design +Comment[el]=Θέμα του KDE +Comment[eo]=KDEa etoso +Comment[es]=Tema de KDE +Comment[et]=KDE teema +Comment[fa]=چهرۀ KDE +Comment[fi]=KDE-teema +Comment[fr]=Thème KDE +Comment[fy]=KDE-tema +Comment[ga]=Téama KDE +Comment[gl]=Tema de KDE +Comment[he]=ערכת נושא של KDE +Comment[hi]=केडीई प्रसंग +Comment[hr]=KDE tema +Comment[hu]=KDE-téma +Comment[id]=Tema KDE +Comment[is]=KDE þema +Comment[it]=Tema KDE +Comment[ja]=KDE テーマ +Comment[ka]=KDE-ს თემა +Comment[kk]=KDE нақышы +Comment[km]=ស្បែក KDE +Comment[ko]=KDE 테마 설치 +Comment[lo]=ທີມຂອງ KDE +Comment[lt]=KDE Tema +Comment[lv]=KDE Tēma +Comment[mk]=KDE-тема +Comment[mn]=КДЭ-Хэлбэр +Comment[ms]=Tema KDE +Comment[mt]=Tema KDE +Comment[nb]=KDE-tema +Comment[nds]=KDE Muster +Comment[ne]=KDE विषयवस्तु +Comment[nl]=KDE-thema +Comment[nn]=KDE-tema +Comment[nso]=Molaetsa wa KDE +Comment[pa]=KDE ਸਰੂਪ +Comment[pl]=Motywy KDE +Comment[pt]=Tema do KDE +Comment[pt_BR]=Tema do KDE +Comment[ro]=Tematică KDE +Comment[ru]=Тема KDE +Comment[rw]=Insanganyamatsiko za KDE +Comment[se]=KDE-fáddá +Comment[sk]=Téma KDE +Comment[sl]=Tema KDE +Comment[sr]=KDE тема +Comment[sr@Latn]=KDE tema +Comment[sv]=KDE-tema +Comment[ta]=KDE பொருள் +Comment[tg]=Мавзӯъи KDE +Comment[th]=ชุดตกแต่ง KDE +Comment[tr]=KDE Teması +Comment[tt]=KDE Tışlawı +Comment[uk]=Тема KDE +Comment[uz]=KDE mavzusi +Comment[uz@cyrillic]=KDE мавзуси +Comment[ven]=Thero ya KDE +Comment[vi]=Sắc thái KDE +Comment[wa]=Tinme KDE +Comment[xh]=Umxholo we KDE +Comment[zh_CN]=KDE 主题 +Comment[zh_TW]=KDE 主題 +Comment[zu]=Ingqikithi ye-KDE +Icon=kthememgr +Type=MimeType +Patterns=*.kth; +X-KDE-AutoEmbed=false -- cgit v1.2.1