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>
40 #include <QGridLayout>
44 #include <QPushButton>
45 #include <QTreeWidget>
46 #include <QTreeWidgetItem>
52 extern KConfig
*config
;
54 class ThemeData
: public QTreeWidgetItem
{
56 ThemeData( QTreeWidget
*parent
= 0 ) : QTreeWidgetItem( parent
) {}
64 KDMThemeWidget::KDMThemeWidget( 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/";
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
,
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" );
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" );
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() );
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()
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())
214 if (themeURL
.isLocalFile() && QDir( themeURL
.path() ).exists()) {
215 insertTheme( themeURL
.path() );
221 QString themeTmpFile
;
223 if (!KIO::NetAccess::download( themeURL
, themeTmpFile
, this )) {
225 if (themeURL
.isLocalFile())
226 sorryText
= i18n("Unable to find the KDM theme archive %1.",themeURL
.prettyUrl());
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
);
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.") );
253 KProgressDialog
progressDiag( this,
254 i18n("Installing KDM themes"), QString() );
255 progressDiag
.setModal( true );
256 progressDiag
.setAutoClose( true );
257 progressDiag
.progressBar()->setMaximum( foundThemes
.size() );
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())
269 progressDiag
.progressBar()->setValue( progressDiag
.progressBar()->value() + 1 );
270 if (progressDiag
.wasCancelled())
277 KIO::NetAccess::removeTempFile( themeTmpFile
);
281 void KDMThemeWidget::themeSelected()
283 if (themeWidget
->selectedItems().size() > 0)
284 updateInfoView( (ThemeData
*)(themeWidget
->selectedItems().first()) );
290 void KDMThemeWidget::removeSelectedThemes()
292 QStringList delList
, nameList
;
293 QList
<QTreeWidgetItem
*> themes
= themeWidget
->selectedItems();
294 if (themes
.isEmpty())
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
)
304 KIO::del( KUrl::List( delList
) ); // XXX error check
306 foreach (QTreeWidgetItem
*itm
, themes
)
307 themeWidget
->takeTopLevelItem( themeWidget
->indexOfTopLevelItem( itm
) );
310 void KDMThemeWidget::getNewStuff()
313 engine
.init("kdm.knsrc");
314 KNS::Entry::List entries
= engine
.downloadDialogModal(this);
317 #include "kdm-theme.moc"