1 /***************************************************************************
2 * Copyright (C) 2005-2006 by Stephen Leaf <smileaf@smileaf.org> *
3 * Copyright (C) 2006 by Oswald Buddenhagen <ossi@kde.org> *
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. *
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. *
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"
26 #include <KIO/DeleteJob>
27 #include <KIO/NetAccess>
29 #include <KMessageBox>
30 #include <KProgressDialog>
32 #include <KConfigGroup>
33 #include <KStandardDirs>
35 #include <KUrlRequester>
36 #include <KUrlRequesterDialog>
37 #include <knewstuff2/engine.h>
41 #include <QGridLayout>
45 #include <QPushButton>
46 #include <QTreeWidget>
47 #include <QTreeWidgetItem>
53 extern KConfig
*config
;
55 class ThemeData
: public QTreeWidgetItem
{
57 ThemeData( QTreeWidget
*parent
= 0 ) : QTreeWidgetItem( parent
) {}
65 KDMThemeWidget::KDMThemeWidget( 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/";
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
,
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" );
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" );
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
)
191 QList
<QTreeWidgetItem
*> ls
= themeWidget
->findItems( name
, Qt::MatchExactly
);
196 void KDMThemeWidget::updateInfoView( ThemeData
*theme
)
198 if (!(defaultTheme
= theme
)) {
199 info
->setText( QString() );
200 preview
->setPixmap( QPixmap() );
201 preview
->setText( QString() );
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()
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())
227 if (themeURL
.isLocalFile() && QDir( themeURL
.path() ).exists()) {
228 insertTheme( themeURL
.path() );
234 QString themeTmpFile
;
236 if (!KIO::NetAccess::download( themeURL
, themeTmpFile
, this )) {
238 if (themeURL
.isLocalFile())
239 sorryText
= i18n("Unable to find the KDM theme archive %1.",themeURL
.prettyUrl());
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
);
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.") );
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() );
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())
283 progressDiag
.progressBar()->setValue( progressDiag
.progressBar()->value() + 1 );
284 if (progressDiag
.wasCancelled())
291 KIO::NetAccess::removeTempFile( themeTmpFile
);
295 void KDMThemeWidget::themeSelected()
297 if (themeWidget
->selectedItems().size() > 0)
298 updateInfoView( (ThemeData
*)(themeWidget
->selectedItems().first()) );
301 if (bInstallTheme
->isEnabled()) // not read-only
302 bRemoveTheme
->setEnabled( !themeWidget
->selectedItems().isEmpty() );
306 void KDMThemeWidget::removeSelectedThemes()
308 QStringList delList
, nameList
;
309 QList
<QTreeWidgetItem
*> themes
= themeWidget
->selectedItems();
310 if (themes
.isEmpty())
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
)
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"