Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / kcontrol / kdm / kdm-theme.cpp
blob271edae0185ea542b1a14d388ee8ea5a4affd2a6
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>
39 #include <QDir>
40 #include <QGridLayout>
41 #include <QLabel>
42 #include <QList>
43 #include <QPixmap>
44 #include <QPushButton>
45 #include <QTreeWidget>
46 #include <QTreeWidgetItem>
47 #include <QWhatsThis>
48 #include <QWidget>
50 #include <unistd.h>
52 extern KConfig *config;
54 class ThemeData : public QTreeWidgetItem {
55 public:
56 ThemeData( QTreeWidget *parent = 0 ) : QTreeWidgetItem( parent ) {}
58 QString path;
59 QString screenShot;
60 QString copyright;
61 QString description;
64 KDMThemeWidget::KDMThemeWidget( QWidget *parent )
65 : QWidget( parent )
67 QGridLayout *ml = new QGridLayout( this );
68 ml->setSpacing( KDialog::spacingHint() );
69 ml->setMargin( KDialog::marginHint() );
71 themeWidget = new QTreeWidget( this );
72 themeWidget->setHeaderLabels( QStringList() << i18n("Theme") << i18n("Author") );
73 themeWidget->setSortingEnabled( true );
74 themeWidget->sortItems( 0, Qt::AscendingOrder );
75 themeWidget->setRootIsDecorated( false );
76 themeWidget->setWhatsThis( i18n("This is a list of installed themes.\n"
77 "Click the one to be used.") );
79 ml->addWidget( themeWidget, 0, 0, 2, 4 );
81 preview = new QLabel( this );
82 preview->setFixedSize( QSize( 200, 150 ) );
83 preview->setScaledContents( true );
84 preview->setWhatsThis( i18n("This is a screen shot of what KDM will look like.") );
86 ml->addWidget( preview, 0, 4 );
88 info = new QLabel( this );
89 info->setMaximumWidth( 200 );
90 info->setAlignment( Qt::AlignTop );
91 info->setWordWrap( true );
92 info->setWhatsThis( i18n("This contains information about the selected theme.") );
94 ml->addWidget( info, 1, 4 );
96 bInstallTheme = new QPushButton( i18n("Install &new theme"), this );
97 bInstallTheme->setWhatsThis( i18n("This will install a theme into the theme directory.") );
99 ml->addWidget( bInstallTheme, 2, 0 );
101 bRemoveTheme = new QPushButton( i18n("&Remove theme"), this );
102 bRemoveTheme->setWhatsThis( i18n("This will remove the selected theme.") );
104 ml->addWidget( bRemoveTheme, 2, 1 );
106 bGetNewThemes = new QPushButton( i18n("&Get New Themes"), this );
107 bGetNewThemes->setWhatsThis( i18n("Get New Themes") );
109 ml->addWidget( bGetNewThemes, 2, 2 );
111 connect( themeWidget, SIGNAL(itemSelectionChanged()), SLOT(themeSelected()) );
112 connect( bInstallTheme, SIGNAL(clicked()), SLOT(installNewTheme()) );
113 connect( bRemoveTheme, SIGNAL(clicked()), SLOT(removeSelectedThemes()) );
114 connect( bGetNewThemes, SIGNAL(clicked()), SLOT(getNewStuff()) );
116 themeDir = KGlobal::dirs()->resourceDirs( "data" ).last() + "kdm/themes/";
117 defaultTheme = 0;
118 QDir testDir( themeDir );
119 if (!testDir.exists() && !testDir.mkdir( testDir.absolutePath() ) && !geteuid())
120 KMessageBox::sorry( this, i18n("Unable to create folder %1", testDir.absolutePath() ) );
122 foreach (QString ent,
123 QDir( themeDir ).entryList( QDir::Dirs | QDir::NoDotAndDotDot,
124 QDir::Unsorted ))
125 insertTheme( themeDir + ent );
128 void KDMThemeWidget::selectTheme( const QString &path )
130 for (int i = 0; i < themeWidget->topLevelItemCount(); i++) {
131 ThemeData *td = (ThemeData *)themeWidget->topLevelItem( i );
132 if (td->path == path) {
133 themeWidget->clearSelection();
134 td->setSelected( true );
135 updateInfoView( td );
140 void KDMThemeWidget::load()
142 selectTheme( config->group("X-*-Greeter").readEntry( "Theme", themeDir + "circles" ) );
145 void KDMThemeWidget::save()
147 config->group("X-*-Greeter").writeEntry( "Theme", defaultTheme ? defaultTheme->path : "" );
150 void KDMThemeWidget::defaults()
152 selectTheme( themeDir + "circles" );
154 emit changed();
157 void KDMThemeWidget::makeReadOnly()
159 themeWidget->setEnabled( false );
160 bInstallTheme->setEnabled( false );
161 bRemoveTheme->setEnabled( false );
162 bGetNewThemes->setEnabled( false );
165 void KDMThemeWidget::insertTheme( const QString &_theme )
167 KConfig themeConfig( _theme + "/KdmGreeterTheme.desktop", KConfig::SimpleConfig);
168 KConfigGroup themeGroup = themeConfig.group("KdmGreeterTheme");
170 QString name = themeGroup.readEntry( "Name" );
171 if (name.isEmpty())
172 return;
174 ThemeData *child = new ThemeData( themeWidget );
175 child->setText( 0, name );
176 child->setText( 1, themeGroup.readEntry( "Author" ) );
177 child->path = _theme;
178 child->screenShot = themeGroup.readEntry( "Screenshot" );
179 child->copyright = themeGroup.readEntry( "Copyright" );
180 child->description = themeGroup.readEntry( "Description" );
183 void KDMThemeWidget::updateInfoView( ThemeData *theme )
185 if (!(defaultTheme = theme)) {
186 info->setText( QString() );
187 preview->setPixmap( QPixmap() );
188 preview->setText( QString() );
189 } else {
190 info->setText(
191 ((theme->copyright.length() > 0) ?
192 i18n("<qt><strong>Copyright:</strong> %1<br/></qt>",
193 theme->copyright) : "") +
194 ((theme->description.length() > 0) ?
195 i18n("<qt><strong>Description:</strong> %1</qt>",
196 theme->description) : "") );
197 preview->setPixmap( theme->path + '/' + theme->screenShot );
198 preview->setText( theme->screenShot.isEmpty() ?
199 "Screenshot not available" : QString() );
203 // Theme installation code inspired by kcm_icon
204 void KDMThemeWidget::installNewTheme()
206 QString url;
207 KUrlRequesterDialog fileRequester( url, i18n("Drag or Type Theme URL"), this );
208 fileRequester.urlRequester()->setMode( KFile::File | KFile::Directory | KFile::ExistingOnly );
209 KUrl themeURL = fileRequester.getUrl();
210 if (themeURL.isEmpty())
211 return;
213 #if 0
214 if (themeURL.isLocalFile() && QDir( themeURL.path() ).exists()) {
215 insertTheme( themeURL.path() );
216 emit changed();
217 return;
219 #endif
221 QString themeTmpFile;
223 if (!KIO::NetAccess::download( themeURL, themeTmpFile, this )) {
224 QString sorryText;
225 if (themeURL.isLocalFile())
226 sorryText = i18n("Unable to find the KDM theme archive %1.",themeURL.prettyUrl());
227 else
228 sorryText = i18n("Unable to download the KDM theme archive;\n"
229 "please check that address %1 is correct.",themeURL.prettyUrl());
230 KMessageBox::sorry( this, sorryText );
231 return;
234 QList<const KArchiveDirectory *> foundThemes;
236 KTar archive( themeTmpFile );
237 archive.open( IO_ReadOnly );
239 const KArchiveDirectory *archDir = archive.directory();
240 foreach (QString ent, archDir->entries()) {
241 const KArchiveEntry *possibleDir = archDir->entry( ent );
242 if (possibleDir->isDirectory()) {
243 const KArchiveDirectory *subDir =
244 static_cast<const KArchiveDirectory *>( possibleDir );
245 if (subDir->entry( "KdmGreeterTheme.desktop" ))
246 foundThemes.append( subDir );
250 if (foundThemes.isEmpty())
251 KMessageBox::error( this, i18n("The file is not a valid KDM theme archive.") );
252 else {
253 KProgressDialog progressDiag( this,
254 i18n("Installing KDM themes"), QString() );
255 progressDiag.setModal( true );
256 progressDiag.setAutoClose( true );
257 progressDiag.progressBar()->setMaximum( foundThemes.size() );
258 progressDiag.show();
260 foreach (const KArchiveDirectory *ard, foundThemes) {
261 progressDiag.setLabelText(
262 i18n("<qt>Installing <strong>%1</strong> theme</qt>", ard->name() ) );
264 QString path = themeDir + ard->name();
265 ard->copyTo( path, true );
266 if (QDir( path ).exists())
267 insertTheme( path );
269 progressDiag.progressBar()->setValue( progressDiag.progressBar()->value() + 1 );
270 if (progressDiag.wasCancelled())
271 break;
275 archive.close();
277 KIO::NetAccess::removeTempFile( themeTmpFile );
278 emit changed();
281 void KDMThemeWidget::themeSelected()
283 if (themeWidget->selectedItems().size() > 0)
284 updateInfoView( (ThemeData *)(themeWidget->selectedItems().first()) );
285 else
286 updateInfoView( 0 );
287 emit changed();
290 void KDMThemeWidget::removeSelectedThemes()
292 QStringList delList, nameList;
293 QList<QTreeWidgetItem *> themes = themeWidget->selectedItems();
294 if (themes.isEmpty())
295 return;
296 foreach (QTreeWidgetItem *itm, themes) {
297 nameList.append( itm->text( 0 ) );
298 delList.append( ((ThemeData *)itm)->path );
300 if (KMessageBox::questionYesNoList( this,
301 i18n("Are you sure you want to remove the following themes?"),
302 nameList, i18n("Remove themes?") ) != KMessageBox::Yes)
303 return;
304 KIO::del( KUrl::List( delList ) ); // XXX error check
306 foreach (QTreeWidgetItem *itm, themes)
307 themeWidget->takeTopLevelItem( themeWidget->indexOfTopLevelItem( itm ) );
310 void KDMThemeWidget::getNewStuff()
312 KNS::Engine engine;
313 engine.init("kdm.knsrc");
314 KNS::Entry::List entries = engine.downloadDialogModal(this);
317 #include "kdm-theme.moc"