not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / kcontrol / kdm / kdm-theme.cpp
blob3a9a60e8052607c28b550af9e14066c4b65b1722
1 /***************************************************************************
2 * Copyright (C) 2005-2006 by Stephen Leaf <smileaf@smileaf.org> *
3 * Copyright (C) 2006 by Oswald Buddenhagen <ossi@kde.org> *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) any later version. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
21 #include "kdm-theme.h"
23 #include <KDialog>
24 #include <KGlobal>
25 #include <KIO/Job>
26 #include <KIO/DeleteJob>
27 #include <KIO/NetAccess>
28 #include <KLocale>
29 #include <KMessageBox>
30 #include <KProgressDialog>
31 #include <KConfig>
32 #include <KConfigGroup>
33 #include <KStandardDirs>
34 #include <KTar>
35 #include <KUrlRequester>
36 #include <KUrlRequesterDialog>
37 #include <knewstuff2/engine.h>
38 #include <KDebug>
40 #include <QDir>
41 #include <QGridLayout>
42 #include <QLabel>
43 #include <QList>
44 #include <QPixmap>
45 #include <QPushButton>
46 #include <QTreeWidget>
47 #include <QTreeWidgetItem>
48 #include <QWhatsThis>
49 #include <QWidget>
51 #include <unistd.h>
53 extern KConfig *config;
55 class ThemeData : public QTreeWidgetItem {
56 public:
57 ThemeData( QTreeWidget *parent = 0 ) : QTreeWidgetItem( parent ) {}
59 QString path;
60 QString screenShot;
61 QString copyright;
62 QString description;
65 KDMThemeWidget::KDMThemeWidget( QWidget *parent )
66 : QWidget( parent )
68 QGridLayout *ml = new QGridLayout( this );
69 ml->setSizeConstraint( QLayout::SetMinAndMaxSize );
70 ml->setSpacing( KDialog::spacingHint() );
71 ml->setMargin( KDialog::marginHint() );
73 themeWidget = new QTreeWidget( this );
74 themeWidget->setHeaderLabels( QStringList()
75 << i18nc("@title:column", "Theme")
76 << i18nc("@title:column", "Author") );
77 themeWidget->setSortingEnabled( true );
78 themeWidget->sortItems( 0, Qt::AscendingOrder );
79 themeWidget->setRootIsDecorated( false );
80 themeWidget->setWhatsThis( i18n("This is a list of installed themes.\n"
81 "Click the one to be used.") );
83 ml->addWidget( themeWidget, 0, 0, 2, 4 );
85 preview = new QLabel( this );
86 preview->setFixedSize( QSize( 200, 150 ) );
87 preview->setScaledContents( true );
88 preview->setWhatsThis( i18n("This is a screen shot of what KDM will look like.") );
90 ml->addWidget( preview, 0, 4 );
92 info = new QLabel( this );
93 info->setMaximumWidth( 200 );
94 info->setAlignment( Qt::AlignTop );
95 info->setWordWrap( true );
96 info->setWhatsThis( i18n("This contains information about the selected theme.") );
98 ml->addWidget( info, 1, 4 );
100 bInstallTheme = new QPushButton( i18nc("@action:button", "Install &new theme"), this );
101 bInstallTheme->setWhatsThis( i18n("This will install a theme into the theme directory.") );
103 ml->addWidget( bInstallTheme, 2, 0 );
105 bRemoveTheme = new QPushButton( i18nc("@action:button", "&Remove theme"), this );
106 bRemoveTheme->setWhatsThis( i18n("This will remove the selected theme.") );
108 ml->addWidget( bRemoveTheme, 2, 1 );
110 bGetNewThemes = new QPushButton( i18nc("@action:button", "&Get New Themes"), this );
112 ml->addWidget( bGetNewThemes, 2, 2 );
114 connect( themeWidget, SIGNAL(itemSelectionChanged()), SLOT(themeSelected()) );
115 connect( bInstallTheme, SIGNAL(clicked()), SLOT(installNewTheme()) );
116 connect( bRemoveTheme, SIGNAL(clicked()), SLOT(removeSelectedThemes()) );
117 connect( bGetNewThemes, SIGNAL(clicked()), SLOT(getNewStuff()) );
119 themeDir = KStandardDirs::installPath( "data" ) + "kdm/themes/";
120 defaultTheme = 0;
121 QDir testDir( themeDir );
122 if (!testDir.exists() && !testDir.mkdir( testDir.absolutePath() ) && !geteuid())
123 KMessageBox::sorry( this, i18n("Unable to create folder %1", testDir.absolutePath() ) );
125 foreach (const QString& ent,
126 QDir( themeDir ).entryList( QDir::Dirs | QDir::NoDotAndDotDot,
127 QDir::Unsorted ))
128 insertTheme( themeDir + ent );
131 void KDMThemeWidget::selectTheme( const QString &path )
133 for (int i = 0; i < themeWidget->topLevelItemCount(); i++) {
134 ThemeData *td = (ThemeData *)themeWidget->topLevelItem( i );
135 if (td->path == path) {
136 themeWidget->clearSelection();
137 td->setSelected( true );
138 updateInfoView( td );
143 void KDMThemeWidget::load()
145 selectTheme( config->group( "X-*-Greeter" ).readEntry( "Theme", themeDir + "oxygen" ) );
148 void KDMThemeWidget::save()
150 config->group( "X-*-Greeter" ).writeEntry( "Theme", defaultTheme ? defaultTheme->path : "" );
153 void KDMThemeWidget::defaults()
155 selectTheme( themeDir + "oxygen" );
157 emit changed();
160 void KDMThemeWidget::makeReadOnly()
162 themeWidget->setEnabled( false );
163 bInstallTheme->setEnabled( false );
164 bRemoveTheme->setEnabled( false );
165 bGetNewThemes->setEnabled( false );
168 void KDMThemeWidget::insertTheme( const QString &_theme )
170 KConfig themeConfig( _theme + "/KdmGreeterTheme.desktop", KConfig::SimpleConfig );
171 KConfigGroup themeGroup = themeConfig.group( "KdmGreeterTheme" );
173 QString name = themeGroup.readEntry( "Name" );
174 if (name.isEmpty())
175 return;
177 ThemeData *child = new ThemeData( themeWidget );
178 child->setText( 0, name );
179 child->setText( 1, themeGroup.readEntry( "Author" ) );
180 child->path = _theme;
181 child->screenShot = themeGroup.readEntry( "Screenshot" );
182 child->copyright = themeGroup.readEntry( "Copyright" );
183 child->description = themeGroup.readEntry( "Description" );
186 void KDMThemeWidget::removeTheme( const QString &name )
188 if (name.isEmpty())
189 return;
191 QList<QTreeWidgetItem *> ls = themeWidget->findItems( name, Qt::MatchExactly );
192 if (!ls.isEmpty())
193 delete ls.first();
196 void KDMThemeWidget::updateInfoView( ThemeData *theme )
198 if (!(defaultTheme = theme)) {
199 info->setText( QString() );
200 preview->setPixmap( QPixmap() );
201 preview->setText( QString() );
202 } else {
203 info->setText(
204 ((theme->copyright.length() > 0) ?
205 i18n("<qt><strong>Copyright:</strong> %1<br/></qt>",
206 theme->copyright) : "") +
207 ((theme->description.length() > 0) ?
208 i18n("<qt><strong>Description:</strong> %1</qt>",
209 theme->description) : "") );
210 preview->setPixmap( theme->path + '/' + theme->screenShot );
211 preview->setText( theme->screenShot.isEmpty() ?
212 "Screenshot not available" : QString() );
216 // Theme installation code inspired by kcm_icon
217 void KDMThemeWidget::installNewTheme()
219 QString url;
220 KUrlRequesterDialog fileRequester( url, i18n("Drag or Type Theme URL"), this );
221 fileRequester.urlRequester()->setMode( KFile::File | KFile::Directory | KFile::ExistingOnly );
222 KUrl themeURL = fileRequester.getUrl();
223 if (themeURL.isEmpty())
224 return;
226 #if 0
227 if (themeURL.isLocalFile() && QDir( themeURL.path() ).exists()) {
228 insertTheme( themeURL.path() );
229 emit changed();
230 return;
232 #endif
234 QString themeTmpFile;
236 if (!KIO::NetAccess::download( themeURL, themeTmpFile, this )) {
237 QString sorryText;
238 if (themeURL.isLocalFile())
239 sorryText = i18n("Unable to find the KDM theme archive %1.",themeURL.prettyUrl());
240 else
241 sorryText = i18n("Unable to download the KDM theme archive;\n"
242 "please check that address %1 is correct.",themeURL.prettyUrl());
243 KMessageBox::sorry( this, sorryText );
244 return;
247 QList<const KArchiveDirectory *> foundThemes;
249 KTar archive( themeTmpFile );
250 archive.open( QIODevice::ReadOnly );
252 const KArchiveDirectory *archDir = archive.directory();
253 foreach (const QString& ent, archDir->entries()) {
254 const KArchiveEntry *possibleDir = archDir->entry( ent );
255 if (possibleDir->isDirectory()) {
256 const KArchiveDirectory *subDir =
257 static_cast<const KArchiveDirectory *>( possibleDir );
258 if (subDir->entry( "KdmGreeterTheme.desktop" ))
259 foundThemes.append( subDir );
263 if (foundThemes.isEmpty())
264 KMessageBox::error( this, i18n("The file is not a valid KDM theme archive.") );
265 else {
266 KProgressDialog progressDiag( this,
267 i18nc("@title:window", "Installing KDM themes"), QString() );
268 progressDiag.setModal( true );
269 progressDiag.setAutoClose( true );
270 progressDiag.progressBar()->setMaximum( foundThemes.size() );
271 progressDiag.show();
273 foreach (const KArchiveDirectory *ard, foundThemes) {
274 progressDiag.setLabelText(
275 i18nc("@info:progress",
276 "<qt>Installing <strong>%1</strong> theme</qt>", ard->name() ) );
278 QString path = themeDir + ard->name();
279 ard->copyTo( path, true );
280 if (QDir( path ).exists())
281 insertTheme( path );
283 progressDiag.progressBar()->setValue( progressDiag.progressBar()->value() + 1 );
284 if (progressDiag.wasCancelled())
285 break;
289 archive.close();
291 KIO::NetAccess::removeTempFile( themeTmpFile );
292 emit changed();
295 void KDMThemeWidget::themeSelected()
297 if (themeWidget->selectedItems().size() > 0)
298 updateInfoView( (ThemeData *)(themeWidget->selectedItems().first()) );
299 else
300 updateInfoView( 0 );
301 if (bInstallTheme->isEnabled()) // not read-only
302 bRemoveTheme->setEnabled( !themeWidget->selectedItems().isEmpty() );
303 emit changed();
306 void KDMThemeWidget::removeSelectedThemes()
308 QStringList delList, nameList;
309 QList<QTreeWidgetItem *> themes = themeWidget->selectedItems();
310 if (themes.isEmpty())
311 return;
312 foreach (QTreeWidgetItem *itm, themes) {
313 nameList.append( itm->text( 0 ) );
314 delList.append( ((ThemeData *)itm)->path );
316 if (KMessageBox::questionYesNoList( this,
317 i18n("Are you sure you want to remove the following themes?"),
318 nameList, i18nc("@title:window", "Remove themes?") ) != KMessageBox::Yes)
319 return;
320 KIO::del( KUrl::List( delList ) ); // XXX error check
322 foreach (QTreeWidgetItem *itm, themes)
323 themeWidget->takeTopLevelItem( themeWidget->indexOfTopLevelItem( itm ) );
326 void KDMThemeWidget::getNewStuff()
328 KNS::Engine engine( this );
329 if (engine.init( "kdm.knsrc" )) {
330 KNS::Entry::List entries = engine.downloadDialogModal( this );
331 for (int i = 0; i < entries.size(); i ++) {
332 if (entries.at( i )->status() == KNS::Entry::Installed) {
333 QString name = entries.at( i )->installedFiles().at( 0 ).section( '/', -2, -2 );
334 insertTheme( themeDir + name );
335 } else if (entries.at( i )->status() == KNS::Entry::Deleted) {
336 if (!entries.at( i )->uninstalledFiles().isEmpty()) {
337 QString name = entries.at( i )->uninstalledFiles().at( 0 ).section( '/', -2, -2 );
338 removeTheme( themeDir + name );
345 #include "kdm-theme.moc"