1
/***************************************************************************
2
* Copyright Ravikiran Rajagopal 2003 *
3
* ravi@ee.eng.ohio-state.edu *
4
* Copyright (c) 1998 Stefan Taferner <taferner@kde.org> *
6
* This program is free software; you can redistribute it and/or modify *
7
* it under the terms of the GNU General Public License (version 2) as *
8
* published by the Free Software Foundation. *
10
***************************************************************************/
18
#include <qtextedit.h>
20
#include "installer.h"
23
#include <kfiledialog.h>
24
#include <kglobalsettings.h>
26
#include <kmessagebox.h>
28
#include <kpushbutton.h>
29
#include <kstandarddirs.h>
33
#include <kio/netaccess.h>
35
ThemeListBox::ThemeListBox(QWidget *parent)
39
connect(this, SIGNAL(mouseButtonPressed(int, QListBoxItem *, const QPoint &)),
40
this, SLOT(slotMouseButtonPressed(int, QListBoxItem *, const QPoint &)));
43
void ThemeListBox::dragEnterEvent(QDragEnterEvent* event)
45
event->accept((event->source() != this) && KURLDrag::canDecode(event));
48
void ThemeListBox::dropEvent(QDropEvent* event)
51
if (KURLDrag::decode(event, urls))
53
emit filesDropped(urls);
57
void ThemeListBox::slotMouseButtonPressed(int button, QListBoxItem *item, const QPoint &p)
59
if ((button & LeftButton) == 0) return;
61
mDragFile = QString::null;
62
int cur = index(item);
64
mDragFile = text2path[text(cur)];
67
void ThemeListBox::mouseMoveEvent(QMouseEvent *e)
69
if (((e->state() & LeftButton) != 0) && !mDragFile.isEmpty())
71
int delay = KGlobalSettings::dndEventDelay();
72
QPoint newPos = e->globalPos();
73
if(newPos.x() > mOldPos.x()+delay || newPos.x() < mOldPos.x()-delay ||
74
newPos.y() > mOldPos.y()+delay || newPos.y() < mOldPos.y()-delay)
77
url.setPath(mDragFile);
80
KURLDrag *d = new KURLDrag(urls, this);
84
KListBox::mouseMoveEvent(e);
87
//-----------------------------------------------------------------------------
88
SplashInstaller::SplashInstaller (QWidget *aParent, const char *aName, bool aInit)
89
: QWidget(aParent, aName), mGui(!aInit)
91
KGlobal::dirs()->addResourceType("ksplashthemes", KStandardDirs::kde_default("data") + "ksplash/Themes");
96
QHBoxLayout* hbox = new QHBoxLayout( this, 0, KDialog::spacingHint() );
98
QVBoxLayout* leftbox = new QVBoxLayout( hbox, KDialog::spacingHint() );
99
hbox->setStretchFactor( leftbox, 1 );
101
mThemesList = new ThemeListBox(this);
102
mThemesList->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding );
103
connect(mThemesList, SIGNAL(highlighted(int)), SLOT(slotSetTheme(int)));
104
connect(mThemesList, SIGNAL(filesDropped(const KURL::List&)), SLOT(slotFilesDropped(const KURL::List&)));
105
leftbox->addWidget(mThemesList);
107
mBtnAdd = new KPushButton( i18n("Add..."), this );
108
leftbox->addWidget( mBtnAdd );
109
connect(mBtnAdd, SIGNAL(clicked()), SLOT(slotAdd()));
111
mBtnRemove = new KPushButton( i18n("Remove"), this );
112
leftbox->addWidget( mBtnRemove );
113
connect(mBtnRemove, SIGNAL(clicked()), SLOT(slotRemove()));
115
mBtnTest = new KPushButton( i18n("Test"), this );
116
leftbox->addWidget( mBtnTest );
117
connect(mBtnTest, SIGNAL(clicked()), SLOT(slotTest()));
119
QVBoxLayout* rightbox = new QVBoxLayout( hbox, KDialog::spacingHint() );
120
hbox->setStretchFactor( rightbox, 3 );
122
mPreview = new QLabel(this);
123
mPreview->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
124
mPreview->setFrameStyle(QFrame::Panel|QFrame::Sunken);
125
mPreview->setMinimumSize(QSize(320,240));
126
mPreview->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
127
rightbox->addWidget(mPreview);
128
rightbox->setStretchFactor( mPreview, 3 );
130
mText = new QTextEdit(this);
131
mText->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
132
mText->setMinimumSize(mText->sizeHint());
133
mText->setReadOnly(true);
134
rightbox->addWidget(mText);
135
rightbox->setStretchFactor( mText, 1 );
142
//-----------------------------------------------------------------------------
143
SplashInstaller::~SplashInstaller()
147
int SplashInstaller::addTheme(const QString &path, const QString &name)
149
//kdDebug() << "SplashInstaller::addTheme: " << path << " " << name << endl;
150
QString tmp(i18n( name.utf8() ));
151
int i = mThemesList->count();
152
while((i > 0) && (mThemesList->text(i-1) > tmp))
154
if ((i > 0) && (mThemesList->text(i-1) == tmp))
156
mThemesList->insertItem(tmp, i);
157
mThemesList->text2path.insert( tmp, path+"/"+name );
161
// Copy theme package into themes directory
162
void SplashInstaller::addNewTheme(const KURL &srcURL)
164
QString dir = KGlobal::dirs()->saveLocation("ksplashthemes");
166
QString filename = srcURL.fileName();
167
int i = filename.findRev('.');
168
// Convert extension to lower case.
170
filename = filename.left(i)+filename.mid(i).lower();
171
url.setPath(locateLocal("tmp",filename));
173
// Remove file from temporary directory if it aleady exists - usually the result of a failed install.
174
if ( KIO::NetAccess::exists( url, true, 0 ) )
175
KIO::NetAccess::del( url, 0 );
177
bool rc = KIO::NetAccess::copy(srcURL, url, 0);
180
kdWarning() << "Failed to copy theme " << srcURL.fileName()
181
<< " into temporary directory " << url.path() << endl;
185
// Extract into theme directory: we may have multiple themes in one tarball!
186
KTar tarFile(url.path());
187
if (!tarFile.open(IO_ReadOnly))
189
kdDebug() << "Unable to open archive: " << url.path() << endl;
192
KArchiveDirectory const *ad = tarFile.directory();
193
// Find first directory entry.
194
QStringList entries = ad->entries();
195
QString themeName( entries.first() );
197
// The isDirectory() call always returns false; why?
198
for ( QStringList::Iterator it = entries.begin(); it != entries.end(); ++it )
200
if ( ad->entry( *it )->isDirectory() )
207
// TODO: Make sure we put the entries into a subdirectory if the tarball does not.
208
// TODO: Warn the user if we overwrite something.
209
ad->copyTo(locateLocal("ksplashthemes","/"));
211
KIO::NetAccess::del( url, 0 );
213
// TODO: Update only the entries from this installation.
215
mThemesList->setCurrentItem(findTheme(themeName));
216
mThemesList->setSelected(mThemesList->currentItem(), true);
219
//-----------------------------------------------------------------------------
220
void SplashInstaller::readThemesList()
222
mThemesList->clear();
225
QStringList entryList = KGlobal::dirs()->resourceDirs("ksplashthemes");
226
//kdDebug() << "readThemesList: " << entryList << endl;
229
QStringList::ConstIterator name;
230
for(name = entryList.begin(); name != entryList.end(); name++)
235
subdirs = dir.entryList( QDir::Dirs );
236
// kdDebug() << "readThemesList: " << subdirs << endl;
237
// TODO: Make sure it contains a *.rc file.
238
for (QStringList::Iterator l = subdirs.begin(); l != subdirs.end(); l++ )
239
if ( !(*l).startsWith(QString(".")) )
241
mThemesList->blockSignals( true ); // Don't activate any theme until all themes are loaded.
242
addTheme(dir.path(),*l);
243
mThemesList->blockSignals( false );
248
//-----------------------------------------------------------------------------
249
void SplashInstaller::defaults()
254
void SplashInstaller::load()
259
void SplashInstaller::load( bool useDefaults )
261
KConfig cnf("ksplashrc");
262
cnf.setReadDefaults( useDefaults );
263
cnf.setGroup("KSplash");
264
QString curTheme = cnf.readEntry("Theme","Default");
265
mThemesList->setCurrentItem(findTheme(curTheme));
266
emit changed( useDefaults );
269
//-----------------------------------------------------------------------------
270
void SplashInstaller::save()
272
KConfig cnf("ksplashrc");
273
cnf.setGroup("KSplash");
274
int cur = mThemesList->currentItem();
277
QString path = mThemesList->text(cur);
278
if ( mThemesList->text2path.contains( path ) )
279
path = mThemesList->text2path[path];
280
cur = path.findRev('/');
281
cnf.writeEntry("Theme", path.mid(cur+1) );
283
emit changed( false );
286
//-----------------------------------------------------------------------------
287
void SplashInstaller::slotRemove()
289
int cur = mThemesList->currentItem();
294
QString themeName = mThemesList->text(cur);
295
QString themeDir = mThemesList->text2path[themeName];
296
if (!themeDir.isEmpty())
299
url.setPath(themeDir);
300
if (KMessageBox::warningContinueCancel(this,i18n("Delete folder %1 and its contents?").arg(themeDir),"",KGuiItem(i18n("&Delete"),"editdelete"))==KMessageBox::Continue)
301
rc = KIO::NetAccess::del(url,this);
307
KMessageBox::sorry(this, i18n("Failed to remove theme '%1'").arg(themeName));
310
//mThemesList->removeItem(cur);
312
cur = ((unsigned int)cur >= mThemesList->count())?mThemesList->count()-1:cur;
313
mThemesList->setCurrentItem(cur);
317
//-----------------------------------------------------------------------------
318
void SplashInstaller::slotSetTheme(int id)
321
QString path(QString::null);
326
mPreview->setText(QString::null);
327
mText->setText(QString::null);
332
QString error = i18n("(Could not load theme)");
333
path = mThemesList->text(id);
334
if ( mThemesList->text2path.contains( path ) )
335
path = mThemesList->text2path[path];
341
// Make sure the correct plugin is installed.
342
int i = path.findRev('/');
344
themeName = path.mid(i+1);
345
url.setPath( path + "/Theme.rc" );
346
if (!KIO::NetAccess::exists(url, true, 0))
348
url.setPath( path + "/Theme.RC" );
349
if (!KIO::NetAccess::exists(url, true, 0))
351
url.setPath( path + "/theme.rc" );
352
if (!KIO::NetAccess::exists(url, true, 0))
353
url.setPath( path + "/" + themeName + ".rc" );
356
if (KIO::NetAccess::exists(url, true, 0))
358
KConfig cnf(url.path());
359
cnf.setGroup( QString("KSplash Theme: %1").arg(themeName) );
361
// Get theme information.
363
if ( cnf.hasKey( "Name" ) )
364
infoTxt += i18n( "<b>Name:</b> %1<br>" ).arg( cnf.readEntry( "Name", i18n( "Unknown" ) ) );
365
if ( cnf.hasKey( "Description" ) )
366
infoTxt += i18n( "<b>Description:</b> %1<br>" ).arg( cnf.readEntry( "Description", i18n( "Unknown" ) ) );
367
if ( cnf.hasKey( "Version" ) )
368
infoTxt += i18n( "<b>Version:</b> %1<br>" ).arg( cnf.readEntry( "Version", i18n( "Unknown" ) ) );
369
if ( cnf.hasKey( "Author" ) )
370
infoTxt += i18n( "<b>Author:</b> %1<br>" ).arg( cnf.readEntry( "Author", i18n( "Unknown" ) ) );
371
if ( cnf.hasKey( "Homepage" ) )
372
infoTxt += i18n( "<b>Homepage:</b> %1<br>" ).arg( cnf.readEntry( "Homepage", i18n( "Unknown" ) ) );
375
QString pluginName( cnf.readEntry( "Engine", "Default" ) ); // Perhaps no default is better?
376
if ((KTrader::self()->query("KSplash/Plugin", QString("[X-KSplash-PluginName] == '%1'").arg(pluginName))).isEmpty())
379
error = i18n("This theme requires the plugin %1 which is not installed.").arg(pluginName);
382
enabled = true; // Hooray, there is at least one plugin which can handle this theme.
386
error = i18n("Could not load theme configuration file.");
389
mBtnTest->setEnabled(enabled && themeName != "None" );
390
mText->setText(infoTxt);
393
url.setPath( path + "/" + "Preview.png" );
394
if (KIO::NetAccess::exists(url, true, 0))
395
mPreview->setPixmap(QPixmap(url.path()));
397
mPreview->setText(i18n("(Could not load theme)"));
398
KMessageBox::sorry(this, error);
402
url.setPath( path + "/" + "Preview.png" );
403
if (KIO::NetAccess::exists(url, true, 0))
404
mPreview->setPixmap(QPixmap(url.path()));
406
mPreview->setText(i18n("No preview available."));
410
mBtnRemove->setEnabled( !path.isEmpty() && QFileInfo(path).isWritable());
414
//-----------------------------------------------------------------------------
415
void SplashInstaller::slotAdd()
418
if (path.isEmpty()) path = QDir::homeDirPath();
420
KFileDialog dlg(path, "*.tgz *.tar.gz *.tar.bz2|" + i18n( "KSplash Theme Files" ), 0, 0, true);
421
dlg.setCaption(i18n("Add Theme"));
425
path = dlg.baseURL().url();
426
addNewTheme(dlg.selectedURL());
429
//-----------------------------------------------------------------------------
430
void SplashInstaller::slotFilesDropped(const KURL::List &urls)
432
for(KURL::List::ConstIterator it = urls.begin();
438
//-----------------------------------------------------------------------------
439
int SplashInstaller::findTheme( const QString &theme )
441
// theme is untranslated, but the listbox contains translated items
442
QString tmp(i18n( theme.utf8() ));
443
int id = mThemesList->count()-1;
447
if (mThemesList->text(id) == tmp)
455
//-----------------------------------------------------------------------------
456
void SplashInstaller::slotTest()
458
int i = mThemesList->currentItem();
461
QString themeName = mThemesList->text2path[mThemesList->text(i)];
462
int r = themeName.findRev('/');
464
themeName = themeName.mid(r+1);
466
// special handling for none and simple splashscreens
467
if( themeName == "None" )
469
if( themeName == "Simple" )
472
proc << "ksplashsimple" << "--test";
473
if (!proc.start(KProcess::Block))
474
KMessageBox::error(this,i18n("Unable to start ksplashsimple."));
478
proc << "ksplash" << "--test" << "--theme" << themeName;
479
if (!proc.start(KProcess::Block))
480
KMessageBox::error(this,i18n("Unable to start ksplash."));
483
//-----------------------------------------------------------------------------
484
#include "installer.moc"