summaryrefslogtreecommitdiffstats
path: root/ksplashml/kcmksplash/installer.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'ksplashml/kcmksplash/installer.cpp')
-rw-r--r--ksplashml/kcmksplash/installer.cpp484
1 files changed, 484 insertions, 0 deletions
diff --git a/ksplashml/kcmksplash/installer.cpp b/ksplashml/kcmksplash/installer.cpp
new file mode 100644
index 000000000..a2850ecfa
--- /dev/null
+++ b/ksplashml/kcmksplash/installer.cpp
@@ -0,0 +1,484 @@
+/***************************************************************************
+ * Copyright Ravikiran Rajagopal 2003 *
+ * Copyright (c) 1998 Stefan Taferner <[email protected]> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License (version 2) as *
+ * published by the Free Software Foundation. *
+ * *
+ ***************************************************************************/
+
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <qdir.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtextedit.h>
+
+#include "installer.h"
+
+#include <kdebug.h>
+#include <kfiledialog.h>
+#include <kglobalsettings.h>
+#include <klocale.h>
+#include <kmessagebox.h>
+#include <kprocess.h>
+#include <kpushbutton.h>
+#include <kstandarddirs.h>
+#include <ktar.h>
+#include <ktrader.h>
+#include <kurldrag.h>
+#include <kio/netaccess.h>
+
+ThemeListBox::ThemeListBox(QWidget *parent)
+ : KListBox(parent)
+{
+ setAcceptDrops(true);
+ connect(this, SIGNAL(mouseButtonPressed(int, QListBoxItem *, const QPoint &)),
+ this, SLOT(slotMouseButtonPressed(int, QListBoxItem *, const QPoint &)));
+}
+
+void ThemeListBox::dragEnterEvent(QDragEnterEvent* event)
+{
+ event->accept((event->source() != this) && KURLDrag::canDecode(event));
+}
+
+void ThemeListBox::dropEvent(QDropEvent* event)
+{
+ KURL::List urls;
+ if (KURLDrag::decode(event, urls))
+ {
+ emit filesDropped(urls);
+ }
+}
+
+void ThemeListBox::slotMouseButtonPressed(int button, QListBoxItem *item, const QPoint &p)
+{
+ if ((button & LeftButton) == 0) return;
+ mOldPos = p;
+ mDragFile = QString::null;
+ int cur = index(item);
+ if (cur >= 0)
+ mDragFile = text2path[text(cur)];
+}
+
+void ThemeListBox::mouseMoveEvent(QMouseEvent *e)
+{
+ if (((e->state() & LeftButton) != 0) && !mDragFile.isEmpty())
+ {
+ int delay = KGlobalSettings::dndEventDelay();
+ QPoint newPos = e->globalPos();
+ if(newPos.x() > mOldPos.x()+delay || newPos.x() < mOldPos.x()-delay ||
+ newPos.y() > mOldPos.y()+delay || newPos.y() < mOldPos.y()-delay)
+ {
+ KURL url;
+ url.setPath(mDragFile);
+ KURL::List urls;
+ urls.append(url);
+ KURLDrag *d = new KURLDrag(urls, this);
+ d->dragCopy();
+ }
+ }
+ KListBox::mouseMoveEvent(e);
+}
+
+//-----------------------------------------------------------------------------
+SplashInstaller::SplashInstaller (QWidget *aParent, const char *aName, bool aInit)
+ : QWidget(aParent, aName), mGui(!aInit)
+{
+ KGlobal::dirs()->addResourceType("ksplashthemes", KStandardDirs::kde_default("data") + "ksplash/Themes");
+
+ if (!mGui)
+ return;
+
+ QHBoxLayout* hbox = new QHBoxLayout( this, 0, KDialog::spacingHint() );
+
+ QVBoxLayout* leftbox = new QVBoxLayout( hbox, KDialog::spacingHint() );
+ hbox->setStretchFactor( leftbox, 1 );
+
+ mThemesList = new ThemeListBox(this);
+ mThemesList->setSizePolicy( QSizePolicy::Preferred, QSizePolicy::Expanding );
+ connect(mThemesList, SIGNAL(highlighted(int)), SLOT(slotSetTheme(int)));
+ connect(mThemesList, SIGNAL(filesDropped(const KURL::List&)), SLOT(slotFilesDropped(const KURL::List&)));
+ leftbox->addWidget(mThemesList);
+
+ mBtnAdd = new KPushButton( i18n("Add..."), this );
+ leftbox->addWidget( mBtnAdd );
+ connect(mBtnAdd, SIGNAL(clicked()), SLOT(slotAdd()));
+
+ mBtnRemove = new KPushButton( i18n("Remove"), this );
+ leftbox->addWidget( mBtnRemove );
+ connect(mBtnRemove, SIGNAL(clicked()), SLOT(slotRemove()));
+
+ mBtnTest = new KPushButton( i18n("Test"), this );
+ leftbox->addWidget( mBtnTest );
+ connect(mBtnTest, SIGNAL(clicked()), SLOT(slotTest()));
+
+ QVBoxLayout* rightbox = new QVBoxLayout( hbox, KDialog::spacingHint() );
+ hbox->setStretchFactor( rightbox, 3 );
+
+ mPreview = new QLabel(this);
+ mPreview->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Expanding );
+ mPreview->setFrameStyle(QFrame::Panel|QFrame::Sunken);
+ mPreview->setMinimumSize(QSize(320,240));
+ mPreview->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
+ rightbox->addWidget(mPreview);
+ rightbox->setStretchFactor( mPreview, 3 );
+
+ mText = new QTextEdit(this);
+ mText->setSizePolicy( QSizePolicy::Expanding, QSizePolicy::Preferred );
+ mText->setMinimumSize(mText->sizeHint());
+ mText->setReadOnly(true);
+ rightbox->addWidget(mText);
+ rightbox->setStretchFactor( mText, 1 );
+
+ readThemesList();
+ load();
+}
+
+
+//-----------------------------------------------------------------------------
+SplashInstaller::~SplashInstaller()
+{
+}
+
+int SplashInstaller::addTheme(const QString &path, const QString &name)
+{
+ //kdDebug() << "SplashInstaller::addTheme: " << path << " " << name << endl;
+ QString tmp(i18n( name.utf8() ));
+ int i = mThemesList->count();
+ while((i > 0) && (mThemesList->text(i-1) > tmp))
+ i--;
+ if ((i > 0) && (mThemesList->text(i-1) == tmp))
+ return i-1;
+ mThemesList->insertItem(tmp, i);
+ mThemesList->text2path.insert( tmp, path+"/"+name );
+ return i;
+}
+
+// Copy theme package into themes directory
+void SplashInstaller::addNewTheme(const KURL &srcURL)
+{
+ QString dir = KGlobal::dirs()->saveLocation("ksplashthemes");
+ KURL url;
+ QString filename = srcURL.fileName();
+ int i = filename.findRev('.');
+ // Convert extension to lower case.
+ if (i >= 0)
+ filename = filename.left(i)+filename.mid(i).lower();
+ url.setPath(locateLocal("tmp",filename));
+
+ // Remove file from temporary directory if it aleady exists - usually the result of a failed install.
+ if ( KIO::NetAccess::exists( url, true, 0 ) )
+ KIO::NetAccess::del( url, 0 );
+
+ bool rc = KIO::NetAccess::copy(srcURL, url, 0);
+ if (!rc)
+ {
+ kdWarning() << "Failed to copy theme " << srcURL.fileName()
+ << " into temporary directory " << url.path() << endl;
+ return;
+ }
+
+ // Extract into theme directory: we may have multiple themes in one tarball!
+ KTar tarFile(url.path());
+ if (!tarFile.open(IO_ReadOnly))
+ {
+ kdDebug() << "Unable to open archive: " << url.path() << endl;
+ return;
+ }
+ KArchiveDirectory const *ad = tarFile.directory();
+ // Find first directory entry.
+ QStringList entries = ad->entries();
+ QString themeName( entries.first() );
+#if 0
+ // The isDirectory() call always returns false; why?
+ for ( QStringList::Iterator it = entries.begin(); it != entries.end(); ++it )
+ {
+ if ( ad->entry( *it )->isDirectory() )
+ {
+ themeName = *it;
+ break;
+ }
+ }
+#endif
+ // TODO: Make sure we put the entries into a subdirectory if the tarball does not.
+ // TODO: Warn the user if we overwrite something.
+ ad->copyTo(locateLocal("ksplashthemes","/"));
+ tarFile.close();
+ KIO::NetAccess::del( url, 0 );
+
+ // TODO: Update only the entries from this installation.
+ readThemesList();
+ mThemesList->setCurrentItem(findTheme(themeName));
+ mThemesList->setSelected(mThemesList->currentItem(), true);
+}
+
+//-----------------------------------------------------------------------------
+void SplashInstaller::readThemesList()
+{
+ mThemesList->clear();
+
+ // Read local themes
+ QStringList entryList = KGlobal::dirs()->resourceDirs("ksplashthemes");
+ //kdDebug() << "readThemesList: " << entryList << endl;
+ QDir dir;
+ QStringList subdirs;
+ QStringList::ConstIterator name;
+ for(name = entryList.begin(); name != entryList.end(); name++)
+ {
+ dir = *name;
+ if (!dir.exists())
+ continue;
+ subdirs = dir.entryList( QDir::Dirs );
+ // kdDebug() << "readThemesList: " << subdirs << endl;
+ // TODO: Make sure it contains a *.rc file.
+ for (QStringList::Iterator l = subdirs.begin(); l != subdirs.end(); l++ )
+ if ( !(*l).startsWith(QString(".")) )
+ {
+ mThemesList->blockSignals( true ); // Don't activate any theme until all themes are loaded.
+ addTheme(dir.path(),*l);
+ mThemesList->blockSignals( false );
+ }
+ }
+}
+
+//-----------------------------------------------------------------------------
+void SplashInstaller::defaults()
+{
+ load( true );
+}
+
+void SplashInstaller::load()
+{
+ load( false );
+}
+
+void SplashInstaller::load( bool useDefaults )
+{
+ KConfig cnf("ksplashrc");
+ cnf.setReadDefaults( useDefaults );
+ cnf.setGroup("KSplash");
+ QString curTheme = cnf.readEntry("Theme","Default");
+ mThemesList->setCurrentItem(findTheme(curTheme));
+ emit changed( useDefaults );
+}
+
+//-----------------------------------------------------------------------------
+void SplashInstaller::save()
+{
+ KConfig cnf("ksplashrc");
+ cnf.setGroup("KSplash");
+ int cur = mThemesList->currentItem();
+ if (cur < 0)
+ return;
+ QString path = mThemesList->text(cur);
+ if ( mThemesList->text2path.contains( path ) )
+ path = mThemesList->text2path[path];
+ cur = path.findRev('/');
+ cnf.writeEntry("Theme", path.mid(cur+1) );
+ cnf.sync();
+ emit changed( false );
+}
+
+//-----------------------------------------------------------------------------
+void SplashInstaller::slotRemove()
+{
+ int cur = mThemesList->currentItem();
+ if (cur < 0)
+ return;
+
+ bool rc = false;
+ QString themeName = mThemesList->text(cur);
+ QString themeDir = mThemesList->text2path[themeName];
+ if (!themeDir.isEmpty())
+ {
+ KURL url;
+ url.setPath(themeDir);
+ if (KMessageBox::warningContinueCancel(this,i18n("Delete folder %1 and its contents?").arg(themeDir),"",KGuiItem(i18n("&Delete"),"editdelete"))==KMessageBox::Continue)
+ rc = KIO::NetAccess::del(url,this);
+ else
+ return;
+ }
+ if (!rc)
+ {
+ KMessageBox::sorry(this, i18n("Failed to remove theme '%1'").arg(themeName));
+ return;
+ }
+ //mThemesList->removeItem(cur);
+ readThemesList();
+ cur = ((unsigned int)cur >= mThemesList->count())?mThemesList->count()-1:cur;
+ mThemesList->setCurrentItem(cur);
+}
+
+
+//-----------------------------------------------------------------------------
+void SplashInstaller::slotSetTheme(int id)
+{
+ bool enabled;
+ QString path(QString::null);
+ QString infoTxt;
+
+ if (id < 0)
+ {
+ mPreview->setText(QString::null);
+ mText->setText(QString::null);
+ enabled = false;
+ }
+ else
+ {
+ QString error = i18n("(Could not load theme)");
+ path = mThemesList->text(id);
+ if ( mThemesList->text2path.contains( path ) )
+ path = mThemesList->text2path[path];
+ enabled = false;
+ KURL url;
+ QString themeName;
+ if (!path.isEmpty())
+ {
+ // Make sure the correct plugin is installed.
+ int i = path.findRev('/');
+ if (i >= 0)
+ themeName = path.mid(i+1);
+ url.setPath( path + "/Theme.rc" );
+ if (!KIO::NetAccess::exists(url, true, 0))
+ {
+ url.setPath( path + "/Theme.RC" );
+ if (!KIO::NetAccess::exists(url, true, 0))
+ {
+ url.setPath( path + "/theme.rc" );
+ if (!KIO::NetAccess::exists(url, true, 0))
+ url.setPath( path + "/" + themeName + ".rc" );
+ }
+ }
+ if (KIO::NetAccess::exists(url, true, 0))
+ {
+ KConfig cnf(url.path());
+ cnf.setGroup( QString("KSplash Theme: %1").arg(themeName) );
+
+ // Get theme information.
+ infoTxt = "<qt>";
+ if ( cnf.hasKey( "Name" ) )
+ infoTxt += i18n( "<b>Name:</b> %1<br>" ).arg( cnf.readEntry( "Name", i18n( "Unknown" ) ) );
+ if ( cnf.hasKey( "Description" ) )
+ infoTxt += i18n( "<b>Description:</b> %1<br>" ).arg( cnf.readEntry( "Description", i18n( "Unknown" ) ) );
+ if ( cnf.hasKey( "Version" ) )
+ infoTxt += i18n( "<b>Version:</b> %1<br>" ).arg( cnf.readEntry( "Version", i18n( "Unknown" ) ) );
+ if ( cnf.hasKey( "Author" ) )
+ infoTxt += i18n( "<b>Author:</b> %1<br>" ).arg( cnf.readEntry( "Author", i18n( "Unknown" ) ) );
+ if ( cnf.hasKey( "Homepage" ) )
+ infoTxt += i18n( "<b>Homepage:</b> %1<br>" ).arg( cnf.readEntry( "Homepage", i18n( "Unknown" ) ) );
+ infoTxt += "</qt>";
+
+ QString pluginName( cnf.readEntry( "Engine", "Default" ) ); // Perhaps no default is better?
+ if ((KTrader::self()->query("KSplash/Plugin", QString("[X-KSplash-PluginName] == '%1'").arg(pluginName))).isEmpty())
+ {
+ enabled = false;
+ error = i18n("This theme requires the plugin %1 which is not installed.").arg(pluginName);
+ }
+ else
+ enabled = true; // Hooray, there is at least one plugin which can handle this theme.
+ }
+ else
+ {
+ error = i18n("Could not load theme configuration file.");
+ }
+ }
+ mBtnTest->setEnabled(enabled && themeName != "None" );
+ mText->setText(infoTxt);
+ if (!enabled)
+ {
+ url.setPath( path + "/" + "Preview.png" );
+ if (KIO::NetAccess::exists(url, true, 0))
+ mPreview->setPixmap(QPixmap(url.path()));
+ else
+ mPreview->setText(i18n("(Could not load theme)"));
+ KMessageBox::sorry(this, error);
+ }
+ else
+ {
+ url.setPath( path + "/" + "Preview.png" );
+ if (KIO::NetAccess::exists(url, true, 0))
+ mPreview->setPixmap(QPixmap(url.path()));
+ else
+ mPreview->setText(i18n("No preview available."));
+ emit changed(true);
+ }
+ }
+ mBtnRemove->setEnabled( !path.isEmpty() && QFileInfo(path).isWritable());
+}
+
+
+//-----------------------------------------------------------------------------
+void SplashInstaller::slotAdd()
+{
+ static QString path;
+ if (path.isEmpty()) path = QDir::homeDirPath();
+
+ KFileDialog dlg(path, "*.tgz *.tar.gz *.tar.bz2|" + i18n( "KSplash Theme Files" ), 0, 0, true);
+ dlg.setCaption(i18n("Add Theme"));
+ if (!dlg.exec())
+ return;
+
+ path = dlg.baseURL().url();
+ addNewTheme(dlg.selectedURL());
+}
+
+//-----------------------------------------------------------------------------
+void SplashInstaller::slotFilesDropped(const KURL::List &urls)
+{
+ for(KURL::List::ConstIterator it = urls.begin();
+ it != urls.end();
+ ++it)
+ addNewTheme(*it);
+}
+
+//-----------------------------------------------------------------------------
+int SplashInstaller::findTheme( const QString &theme )
+{
+ // theme is untranslated, but the listbox contains translated items
+ QString tmp(i18n( theme.utf8() ));
+ int id = mThemesList->count()-1;
+
+ while (id >= 0)
+ {
+ if (mThemesList->text(id) == tmp)
+ return id;
+ id--;
+ }
+
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+void SplashInstaller::slotTest()
+{
+ int i = mThemesList->currentItem();
+ if (i < 0)
+ return;
+ QString themeName = mThemesList->text2path[mThemesList->text(i)];
+ int r = themeName.findRev('/');
+ if (r >= 0)
+ themeName = themeName.mid(r+1);
+
+ // special handling for none and simple splashscreens
+ if( themeName == "None" )
+ return;
+ if( themeName == "Simple" )
+ {
+ KProcess proc;
+ proc << "ksplashsimple" << "--test";
+ if (!proc.start(KProcess::Block))
+ KMessageBox::error(this,i18n("Unable to start ksplashsimple."));
+ return;
+ }
+ KProcess proc;
+ proc << "ksplash" << "--test" << "--theme" << themeName;
+ if (!proc.start(KProcess::Block))
+ KMessageBox::error(this,i18n("Unable to start ksplash."));
+}
+
+//-----------------------------------------------------------------------------
+#include "installer.moc"