summaryrefslogtreecommitdiffstats
path: root/kcontrol/icons/iconthemes.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'kcontrol/icons/iconthemes.cpp')
-rw-r--r--kcontrol/icons/iconthemes.cpp452
1 files changed, 452 insertions, 0 deletions
diff --git a/kcontrol/icons/iconthemes.cpp b/kcontrol/icons/iconthemes.cpp
new file mode 100644
index 000000000..a79ad6ddf
--- /dev/null
+++ b/kcontrol/icons/iconthemes.cpp
@@ -0,0 +1,452 @@
+/**
+ * Copyright (c) 2000 Antonio Larrosa <larrosa@kde.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <qfileinfo.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+
+#include <kdebug.h>
+#include <kapplication.h>
+#include <kstandarddirs.h>
+#include <kservice.h>
+#include <klocale.h>
+#include <ksimpleconfig.h>
+#undef Unsorted
+#include <kipc.h>
+
+#include <klistview.h>
+#include <kurlrequesterdlg.h>
+#include <kmessagebox.h>
+#include <kprogress.h>
+#include <kiconloader.h>
+
+#include <kio/job.h>
+#include <kio/netaccess.h>
+#include <ktar.h>
+
+#ifdef HAVE_LIBART
+#include <ksvgiconengine.h>
+#endif
+
+#include "iconthemes.h"
+
+IconThemesConfig::IconThemesConfig(QWidget *parent, const char *name)
+ : KCModule(parent, name)
+{
+ QVBoxLayout *topLayout = new QVBoxLayout(this, KDialog::marginHint(),
+ KDialog::spacingHint());
+
+ QFrame *m_preview=new QFrame(this);
+ m_preview->setMinimumHeight(50);
+
+ QHBoxLayout *lh2=new QHBoxLayout( m_preview );
+ m_previewExec=new QLabel(m_preview);
+ m_previewExec->setPixmap(DesktopIcon("exec"));
+ m_previewFolder=new QLabel(m_preview);
+ m_previewFolder->setPixmap(DesktopIcon("folder"));
+ m_previewDocument=new QLabel(m_preview);
+ m_previewDocument->setPixmap(DesktopIcon("document"));
+
+ lh2->addStretch(10);
+ lh2->addWidget(m_previewExec);
+ lh2->addStretch(1);
+ lh2->addWidget(m_previewFolder);
+ lh2->addStretch(1);
+ lh2->addWidget(m_previewDocument);
+ lh2->addStretch(10);
+
+
+ m_iconThemes=new KListView(this,"IconThemeList");
+ m_iconThemes->addColumn(i18n("Name"));
+ m_iconThemes->addColumn(i18n("Description"));
+ m_iconThemes->setAllColumnsShowFocus( true );
+ m_iconThemes->setFullWidth(true);
+ connect(m_iconThemes,SIGNAL(selectionChanged(QListViewItem *)),
+ SLOT(themeSelected(QListViewItem *)));
+
+ QPushButton *installButton=new QPushButton( i18n("Install New Theme..."),
+ this, "InstallNewTheme");
+ connect(installButton,SIGNAL(clicked()),SLOT(installNewTheme()));
+ m_removeButton=new QPushButton( i18n("Remove Theme"),
+ this, "RemoveTheme");
+ connect(m_removeButton,SIGNAL(clicked()),SLOT(removeSelectedTheme()));
+
+ topLayout->addWidget(
+ new QLabel(i18n("Select the icon theme you want to use:"), this));
+ topLayout->addWidget(m_preview);
+ topLayout->addWidget(m_iconThemes);
+ QHBoxLayout *lg = new QHBoxLayout(topLayout, KDialog::spacingHint());
+ lg->addWidget(installButton);
+ lg->addWidget(m_removeButton);
+
+ loadThemes();
+
+ load();
+
+ m_iconThemes->setFocus();
+}
+
+IconThemesConfig::~IconThemesConfig()
+{
+}
+
+QListViewItem *IconThemesConfig::iconThemeItem(const QString &name)
+{
+ QListViewItem *item;
+ for ( item=m_iconThemes->firstChild(); item ; item=item->nextSibling() )
+ if (m_themeNames[item->text(0)]==name) return item;
+
+ return 0L;
+}
+
+void IconThemesConfig::loadThemes()
+{
+ m_iconThemes->clear();
+ m_themeNames.clear();
+ QStringList themelist(KIconTheme::list());
+ QString name;
+ QString tname;
+ QStringList::Iterator it;
+ for (it=themelist.begin(); it != themelist.end(); ++it)
+ {
+ KIconTheme icontheme(*it);
+ if (!icontheme.isValid()) kdDebug() << "notvalid\n";
+ if (icontheme.isHidden()) continue;
+
+ name=icontheme.name();
+ tname=name;
+
+ // Just in case we have duplicated icon theme names on separate directories
+ for (int i=2; m_themeNames.find(tname)!=m_themeNames.end() ; i++)
+ tname=QString("%1-%2").arg(name).arg(i);
+
+ m_iconThemes->insertItem(new QListViewItem(m_iconThemes,name,
+ icontheme.description()));
+
+ m_themeNames.insert(name,*it);
+
+ }
+}
+
+void IconThemesConfig::installNewTheme()
+{
+ KURL themeURL = KURLRequesterDlg::getURL(QString::null, this,
+ i18n("Drag or Type Theme URL"));
+ kdDebug() << themeURL.prettyURL() << endl;
+
+ if (themeURL.url().isEmpty()) return;
+
+ QString themeTmpFile;
+ // themeTmpFile contains the name of the downloaded file
+
+ if (!KIO::NetAccess::download(themeURL, themeTmpFile, this)) {
+ QString sorryText;
+ if (themeURL.isLocalFile())
+ sorryText = i18n("Unable to find the icon theme archive %1.");
+ else
+ sorryText = i18n("Unable to download the icon theme archive;\n"
+ "please check that address %1 is correct.");
+ KMessageBox::sorry(this, sorryText.arg(themeURL.prettyURL()));
+ return;
+ }
+
+ QStringList themesNames = findThemeDirs(themeTmpFile);
+ if (themesNames.isEmpty()) {
+ QString invalidArch(i18n("The file is not a valid icon theme archive."));
+ KMessageBox::error(this, invalidArch);
+
+ KIO::NetAccess::removeTempFile(themeTmpFile);
+ return;
+ }
+
+ if (!installThemes(themesNames, themeTmpFile)) {
+ //FIXME: make me able to know what is wrong....
+ // QStringList instead of bool?
+ QString somethingWrong =
+ i18n("A problem occurred during the installation process; "
+ "however, most of the themes in the archive have been installed");
+ KMessageBox::error(this, somethingWrong);
+ }
+
+ KIO::NetAccess::removeTempFile(themeTmpFile);
+
+ KGlobal::instance()->newIconLoader();
+ loadThemes();
+
+ QListViewItem *item=iconThemeItem(KIconTheme::current());
+ m_iconThemes->setSelected(item, true);
+ updateRemoveButton();
+}
+
+bool IconThemesConfig::installThemes(const QStringList &themes, const QString &archiveName)
+{
+ bool everythingOk = true;
+ QString localThemesDir(locateLocal("icon", "./"));
+
+ KProgressDialog progressDiag(this, "themeinstallprogress",
+ i18n("Installing icon themes"),
+ QString::null,
+ true);
+ progressDiag.setAutoClose(true);
+ progressDiag.progressBar()->setTotalSteps(themes.count());
+ progressDiag.show();
+
+ KTar archive(archiveName);
+ archive.open(IO_ReadOnly);
+ kapp->processEvents();
+
+ const KArchiveDirectory* rootDir = archive.directory();
+
+ KArchiveDirectory* currentTheme;
+ for (QStringList::ConstIterator it = themes.begin();
+ it != themes.end();
+ ++it) {
+ progressDiag.setLabel(
+ i18n("<qt>Installing <strong>%1</strong> theme</qt>")
+ .arg(*it));
+ kapp->processEvents();
+
+ if (progressDiag.wasCancelled())
+ break;
+
+ currentTheme = dynamic_cast<KArchiveDirectory*>(
+ const_cast<KArchiveEntry*>(
+ rootDir->entry(*it)));
+ if (currentTheme == NULL) {
+ // we tell back that something went wrong, but try to install as much
+ // as possible
+ everythingOk = false;
+ continue;
+ }
+
+ currentTheme->copyTo(localThemesDir + *it);
+ progressDiag.progressBar()->advance(1);
+ }
+
+ archive.close();
+ return everythingOk;
+}
+
+QStringList IconThemesConfig::findThemeDirs(const QString &archiveName)
+{
+ QStringList foundThemes;
+
+ KTar archive(archiveName);
+ archive.open(IO_ReadOnly);
+ const KArchiveDirectory* themeDir = archive.directory();
+
+ KArchiveEntry* possibleDir = 0L;
+ KArchiveDirectory* subDir = 0L;
+
+ // iterate all the dirs looking for an index.theme or index.desktop file
+ QStringList entries = themeDir->entries();
+ for (QStringList::Iterator it = entries.begin();
+ it != entries.end();
+ ++it) {
+ possibleDir = const_cast<KArchiveEntry*>(themeDir->entry(*it));
+ if (possibleDir->isDirectory()) {
+ subDir = dynamic_cast<KArchiveDirectory*>( possibleDir );
+ if (subDir && (subDir->entry("index.theme") != NULL ||
+ subDir->entry("index.desktop") != NULL))
+ foundThemes.append(subDir->name());
+ }
+ }
+
+ archive.close();
+ return foundThemes;
+}
+
+void IconThemesConfig::removeSelectedTheme()
+{
+ QListViewItem *selected = m_iconThemes->selectedItem();
+ if (!selected)
+ return;
+
+ QString question=i18n("<qt>Are you sure you want to remove the "
+ "<strong>%1</strong> icon theme?<br>"
+ "<br>"
+ "This will delete the files installed by this theme.</qt>").
+ arg(selected->text(0));
+
+ bool deletingCurrentTheme=(selected==iconThemeItem(KIconTheme::current()));
+
+ int r=KMessageBox::warningContinueCancel(this,question,i18n("Confirmation"),KStdGuiItem::del());
+ if (r!=KMessageBox::Continue) return;
+
+ KIconTheme icontheme(m_themeNames[selected->text(0)]);
+
+ // delete the index file before the async KIO::del so loadThemes() will
+ // ignore that dir.
+ unlink(QFile::encodeName(icontheme.dir()+"/index.theme").data());
+ unlink(QFile::encodeName(icontheme.dir()+"/index.desktop").data());
+ KIO::del(KURL( icontheme.dir() ));
+
+ KGlobal::instance()->newIconLoader();
+
+ loadThemes();
+
+ QListViewItem *item=0L;
+ //Fallback to the default if we've deleted the current theme
+ if (!deletingCurrentTheme)
+ item=iconThemeItem(KIconTheme::current());
+ if (!item)
+ item=iconThemeItem(KIconTheme::defaultThemeName());
+
+ m_iconThemes->setSelected(item, true);
+ updateRemoveButton();
+
+ if (deletingCurrentTheme) // Change the configuration
+ save();
+}
+
+void IconThemesConfig::updateRemoveButton()
+{
+ QListViewItem *selected = m_iconThemes->selectedItem();
+ bool enabled = false;
+ if (selected)
+ {
+ KIconTheme icontheme(m_themeNames[selected->text(0)]);
+ QFileInfo fi(icontheme.dir());
+ enabled = fi.isWritable();
+ // Don't let users remove the current theme.
+ if(m_themeNames[selected->text(0)] == KIconTheme::current() ||
+ m_themeNames[selected->text(0)] == KIconTheme::defaultThemeName())
+ enabled = false;
+ }
+ m_removeButton->setEnabled(enabled);
+}
+
+void IconThemesConfig::themeSelected(QListViewItem *item)
+{
+#ifdef HAVE_LIBART
+ KSVGIconEngine engine;
+#endif
+ QString dirName(m_themeNames[item->text(0)]);
+ KIconTheme icontheme(dirName);
+ if (!icontheme.isValid()) kdDebug() << "notvalid\n";
+
+ updateRemoveButton();
+ const int size = icontheme.defaultSize(KIcon::Desktop);
+
+ KIcon icon=icontheme.iconPath("exec.png", size, KIcon::MatchBest);
+ if (!icon.isValid()) {
+#ifdef HAVE_LIBART
+ icon=icontheme.iconPath("exec.svg", size, KIcon::MatchBest);
+ if(engine.load(size, size, icon.path))
+ m_previewExec->setPixmap(*engine.image());
+ else {
+ icon=icontheme.iconPath("exec.svgz", size, KIcon::MatchBest);
+ if(engine.load(size, size, icon.path))
+ m_previewExec->setPixmap(*engine.image());
+ }
+#endif
+ }
+ else
+ m_previewExec->setPixmap(QPixmap(icon.path));
+
+ icon=icontheme.iconPath("folder.png",size,KIcon::MatchBest);
+ if (!icon.isValid()) {
+#ifdef HAVE_LIBART
+ icon=icontheme.iconPath("folder.svg", size, KIcon::MatchBest);
+ if(engine.load(size, size, icon.path))
+ m_previewFolder->setPixmap(*engine.image());
+ else {
+ icon=icontheme.iconPath("folder.svgz", size, KIcon::MatchBest);
+ if(engine.load(size, size, icon.path))
+ m_previewFolder->setPixmap(*engine.image());
+ }
+#endif
+ }
+ else
+ m_previewFolder->setPixmap(QPixmap(icon.path));
+
+ icon=icontheme.iconPath("txt.png",size,KIcon::MatchBest);
+ if (!icon.isValid()) {
+#ifdef HAVE_LIBART
+ icon=icontheme.iconPath("txt.svg", size, KIcon::MatchBest);
+ if(engine.load(size, size, icon.path))
+ m_previewDocument->setPixmap(*engine.image());
+ else {
+ icon=icontheme.iconPath("txt.svgz", size, KIcon::MatchBest);
+ if(engine.load(size, size, icon.path))
+ m_previewDocument->setPixmap(*engine.image());
+ }
+#endif
+ }
+ else
+ m_previewDocument->setPixmap(QPixmap(icon.path));
+
+ emit changed(true);
+ m_bChanged = true;
+}
+
+void IconThemesConfig::load()
+{
+ m_defaultTheme=iconThemeItem(KIconTheme::current());
+ m_iconThemes->setSelected(m_defaultTheme, true);
+ updateRemoveButton();
+
+ emit changed(false);
+ m_bChanged = false;
+}
+
+void IconThemesConfig::save()
+{
+ if (!m_bChanged)
+ return;
+ QListViewItem *selected = m_iconThemes->selectedItem();
+ if (!selected)
+ return;
+
+ KSimpleConfig *config = new KSimpleConfig("kdeglobals", false);
+ config->setGroup("Icons");
+ config->writeEntry("Theme", m_themeNames[selected->text(0)]);
+ delete config;
+
+ KIconTheme::reconfigure();
+ emit changed(false);
+
+ for (int i=0; i<KIcon::LastGroup; i++)
+ {
+ KIPC::sendMessageAll(KIPC::IconChanged, i);
+ }
+
+ KService::rebuildKSycoca(this);
+
+ m_bChanged = false;
+ m_removeButton->setEnabled(false);
+}
+
+void IconThemesConfig::defaults()
+{
+ if (m_iconThemes->currentItem()==m_defaultTheme) return;
+
+ m_iconThemes->setSelected(m_defaultTheme, true);
+ updateRemoveButton();
+
+ emit changed(true);
+ m_bChanged = true;
+}
+
+#include "iconthemes.moc"