You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
485 lines
15 KiB
485 lines
15 KiB
/***************************************************************************
|
|
* Copyright Ravikiran Rajagopal 2003 *
|
|
* ravi@ee.eng.ohio-state.edu *
|
|
* Copyright (c) 1998 Stefan Taferner <taferner@kde.org> *
|
|
* *
|
|
* 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 <tqdir.h>
|
|
#include <tqlabel.h>
|
|
#include <tqlayout.h>
|
|
#include <tqtextedit.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(TQWidget *parent)
|
|
: KListBox(parent)
|
|
{
|
|
setAcceptDrops(true);
|
|
connect(this, TQT_SIGNAL(mouseButtonPressed(int, TQListBoxItem *, const TQPoint &)),
|
|
this, TQT_SLOT(slotMouseButtonPressed(int, TQListBoxItem *, const TQPoint &)));
|
|
}
|
|
|
|
void ThemeListBox::dragEnterEvent(TQDragEnterEvent* event)
|
|
{
|
|
event->accept((event->source() != this) && KURLDrag::canDecode(event));
|
|
}
|
|
|
|
void ThemeListBox::dropEvent(TQDropEvent* event)
|
|
{
|
|
KURL::List urls;
|
|
if (KURLDrag::decode(event, urls))
|
|
{
|
|
emit filesDropped(urls);
|
|
}
|
|
}
|
|
|
|
void ThemeListBox::slotMouseButtonPressed(int button, TQListBoxItem *item, const TQPoint &p)
|
|
{
|
|
if ((button & LeftButton) == 0) return;
|
|
mOldPos = p;
|
|
mDragFile = TQString::null;
|
|
int cur = index(item);
|
|
if (cur >= 0)
|
|
mDragFile = text2path[text(cur)];
|
|
}
|
|
|
|
void ThemeListBox::mouseMoveEvent(TQMouseEvent *e)
|
|
{
|
|
if (((e->state() & LeftButton) != 0) && !mDragFile.isEmpty())
|
|
{
|
|
int delay = KGlobalSettings::dndEventDelay();
|
|
TQPoint 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 (TQWidget *aParent, const char *aName, bool aInit)
|
|
: TQWidget(aParent, aName), mGui(!aInit)
|
|
{
|
|
KGlobal::dirs()->addResourceType("ksplashthemes", KStandardDirs::kde_default("data") + "ksplash/Themes");
|
|
|
|
if (!mGui)
|
|
return;
|
|
|
|
TQHBoxLayout* hbox = new TQHBoxLayout( this, 0, KDialog::spacingHint() );
|
|
|
|
TQVBoxLayout* leftbox = new TQVBoxLayout( hbox, KDialog::spacingHint() );
|
|
hbox->setStretchFactor( leftbox, 1 );
|
|
|
|
mThemesList = new ThemeListBox(this);
|
|
mThemesList->setSizePolicy( TQSizePolicy::Preferred, TQSizePolicy::Expanding );
|
|
connect(mThemesList, TQT_SIGNAL(highlighted(int)), TQT_SLOT(slotSetTheme(int)));
|
|
connect(mThemesList, TQT_SIGNAL(filesDropped(const KURL::List&)), TQT_SLOT(slotFilesDropped(const KURL::List&)));
|
|
leftbox->addWidget(mThemesList);
|
|
|
|
mBtnAdd = new KPushButton( i18n("Add..."), this );
|
|
leftbox->addWidget( mBtnAdd );
|
|
connect(mBtnAdd, TQT_SIGNAL(clicked()), TQT_SLOT(slotAdd()));
|
|
|
|
mBtnRemove = new KPushButton( i18n("Remove"), this );
|
|
leftbox->addWidget( mBtnRemove );
|
|
connect(mBtnRemove, TQT_SIGNAL(clicked()), TQT_SLOT(slotRemove()));
|
|
|
|
mBtnTest = new KPushButton( i18n("Test"), this );
|
|
leftbox->addWidget( mBtnTest );
|
|
connect(mBtnTest, TQT_SIGNAL(clicked()), TQT_SLOT(slotTest()));
|
|
|
|
TQVBoxLayout* rightbox = new TQVBoxLayout( hbox, KDialog::spacingHint() );
|
|
hbox->setStretchFactor( rightbox, 3 );
|
|
|
|
mPreview = new TQLabel(this);
|
|
mPreview->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Expanding );
|
|
mPreview->setFrameStyle(TQFrame::Panel|TQFrame::Sunken);
|
|
mPreview->setMinimumSize(TQSize(320,240));
|
|
mPreview->setAlignment(Qt::AlignHCenter|Qt::AlignVCenter);
|
|
rightbox->addWidget(mPreview);
|
|
rightbox->setStretchFactor( mPreview, 3 );
|
|
|
|
mText = new TQTextEdit(this);
|
|
mText->setSizePolicy( TQSizePolicy::Expanding, TQSizePolicy::Preferred );
|
|
mText->setMinimumSize(mText->sizeHint());
|
|
mText->setReadOnly(true);
|
|
rightbox->addWidget(mText);
|
|
rightbox->setStretchFactor( mText, 1 );
|
|
|
|
readThemesList();
|
|
load();
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
SplashInstaller::~SplashInstaller()
|
|
{
|
|
}
|
|
|
|
int SplashInstaller::addTheme(const TQString &path, const TQString &name)
|
|
{
|
|
//kdDebug() << "SplashInstaller::addTheme: " << path << " " << name << endl;
|
|
TQString 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)
|
|
{
|
|
TQString dir = KGlobal::dirs()->saveLocation("ksplashthemes");
|
|
KURL url;
|
|
TQString 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.
|
|
TQStringList entries = ad->entries();
|
|
TQString themeName( entries.first() );
|
|
#if 0
|
|
// The isDirectory() call always returns false; why?
|
|
for ( TQStringList::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
|
|
TQStringList entryList = KGlobal::dirs()->resourceDirs("ksplashthemes");
|
|
//kdDebug() << "readThemesList: " << entryList << endl;
|
|
TQDir dir;
|
|
TQStringList subdirs;
|
|
TQStringList::ConstIterator name;
|
|
for(name = entryList.begin(); name != entryList.end(); name++)
|
|
{
|
|
dir = *name;
|
|
if (!dir.exists())
|
|
continue;
|
|
subdirs = dir.entryList( TQDir::Dirs );
|
|
// kdDebug() << "readThemesList: " << subdirs << endl;
|
|
// TODO: Make sure it contains a *.rc file.
|
|
for (TQStringList::Iterator l = subdirs.begin(); l != subdirs.end(); l++ )
|
|
if ( !(*l).startsWith(TQString(".")) )
|
|
{
|
|
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");
|
|
TQString 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;
|
|
TQString 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;
|
|
TQString themeName = mThemesList->text(cur);
|
|
TQString 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;
|
|
TQString path(TQString::null);
|
|
TQString infoTxt;
|
|
|
|
if (id < 0)
|
|
{
|
|
mPreview->setText(TQString::null);
|
|
mText->setText(TQString::null);
|
|
enabled = false;
|
|
}
|
|
else
|
|
{
|
|
TQString error = i18n("(Could not load theme)");
|
|
path = mThemesList->text(id);
|
|
if ( mThemesList->text2path.contains( path ) )
|
|
path = mThemesList->text2path[path];
|
|
enabled = false;
|
|
KURL url;
|
|
TQString 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( TQString("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>";
|
|
|
|
TQString pluginName( cnf.readEntry( "Engine", "Default" ) ); // Perhaps no default is better?
|
|
if ((KTrader::self()->query("KSplash/Plugin", TQString("[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(TQPixmap(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(TQPixmap(url.path()));
|
|
else
|
|
mPreview->setText(i18n("No preview available."));
|
|
emit changed(true);
|
|
}
|
|
}
|
|
mBtnRemove->setEnabled( !path.isEmpty() && TQFileInfo(path).isWritable());
|
|
}
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
void SplashInstaller::slotAdd()
|
|
{
|
|
static TQString path;
|
|
if (path.isEmpty()) path = TQDir::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 TQString &theme )
|
|
{
|
|
// theme is untranslated, but the listbox contains translated items
|
|
TQString 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;
|
|
TQString 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"
|