Logo Search packages:      
Sourcecode: kcontrol-kdmtheme version File versions  Download package

kdmtheme.cpp

/***************************************************************************
 *   Copyright (C) 2005-2006 by Stephen Leaf                               *
 *   smileaf@smileaf.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 <kdeversion.h>
#include <config.h>
#include <unistd.h>

#include <qcheckbox.h>
#include <qstring.h>
#include <qpushbutton.h>
#include <qpixmap.h>
#include <qlabel.h>
#include <qlayout.h>
#include <qfileinfo.h>
#include <qdir.h>

#include <ksimpleconfig.h>
#include <klocale.h>
#include <kglobal.h>
#include <kstandarddirs.h>
#include <kaboutdata.h>
#include <kurlrequesterdlg.h>
#include <kurlrequester.h>
#include <kfiledialog.h>
#include <kio/netaccess.h>
#include <kmessagebox.h>
#include <kprogress.h>
#include <kparts/genericfactory.h>

#include <kio/job.h>
#include <kio/netaccess.h>
#include <ktar.h>

#include "kdmthemeconfig.h"
#include "kdmtheme.h"

typedef KGenericFactory<kdmtheme, QWidget> kdmthemeFactory;
K_EXPORT_COMPONENT_FACTORY( kcm_kdmtheme, kdmthemeFactory("kcmkdmtheme"))

kdmtheme::kdmtheme(QWidget *parent, const char *name, const QStringList&)
    : KCModule(parent, name), p_myAboutData(0), config( 0L )
{
      QVBoxLayout* layout = new QVBoxLayout( this );
      layout->setAutoAdd( true );

      p_configWidget = new KDMThemeConfig( this );

    load();
      toggleUseTheme( p_configWidget->cUseTheme->isChecked() );

      if( getuid() != 0 ) {
            p_configWidget->bInstallTheme->setEnabled(false);
            p_configWidget->bRemoveTheme->setEnabled(false);
            p_configWidget->ThemeList->setEnabled(false);
            p_configWidget->cUseTheme->setEnabled(false);
      } else {
            connect( p_configWidget->bInstallTheme, SIGNAL(clicked()), SLOT(installNewTheme()) );
            connect( p_configWidget->bRemoveTheme, SIGNAL(clicked()), SLOT(removeSelectedTheme()) );

            connect( p_configWidget->ThemeList, SIGNAL(selectionChanged(QListViewItem *)),
                  SLOT(themeSelected(QListViewItem *)) );
            connect( p_configWidget->ThemeList, SIGNAL(selectionChanged()),
                  SLOT(themeSelected()) );

            connect( p_configWidget->cUseTheme, SIGNAL( toggled( bool ) ),
                  SLOT( toggleUseTheme( bool ) ) );
#if KDE_IS_VERSION(3,3,90)
            p_configWidget->ThemeList->setShadeSortColumn( true );
#endif
            p_configWidget->ThemeList->setSorting( 0 );
      }

      KAboutData* about = new KAboutData("kdmtheme", I18N_NOOP("KDM Theme Manager"), "1.1",
            I18N_NOOP("KDM Theme Manager Control Panel Module"),
            KAboutData::License_GPL,
            I18N_NOOP("(c) 2005-2006 Stephen Leaf"), 0, 0);
      about->addAuthor("Stephen Leaf", 0, "smileaf@smileaf.org");

      // Added in the order they contributed.
      about->addCredit("Laurent Montel", 0, "montel@kde.org");
      about->addCredit("Jonathan Patrick Davies", 0, "jpatrick@ubuntu.com");
      setAboutData( about );
};


kdmtheme::~kdmtheme()
{
      delete config;
}

void kdmtheme::toggleUseTheme(bool useTheme) {
      p_configWidget->bInstallTheme->setEnabled(useTheme);
      p_configWidget->bRemoveTheme->setEnabled(useTheme);
      p_configWidget->ThemeList->setEnabled(useTheme);

      if ( config->readBoolEntry( "UseTheme", true ) != useTheme )
            configChanged();
}

void kdmtheme::themeSelected() {
      if (! p_configWidget->ThemeList->selectedItem() ) {
            p_configWidget->bRemoveTheme->setEnabled(false);
      } else {
            p_configWidget->bRemoveTheme->setEnabled(true);
      }
}


void kdmtheme::themeSelected(QListViewItem *theme) {

      updateTheme( m_themeNames[theme->text(0) + "0"] + "/" + m_themeNames[theme->text(0) + "1"],
                         m_themeNames[theme->text(0) + "2"],
                         m_themeNames[theme->text(0) + "3"] );
      m_selectedTheme = theme;

      configChanged();
}

void kdmtheme::insertTheme( QString theme ) {
      insertItem( theme, m_defaultTheme->text(0) );
      themes.append( theme );
}

// Theme installation code borrowed from kcmicon
void kdmtheme::installNewTheme() {
      KURLRequesterDlg * fileRequester = new KURLRequesterDlg( QString::null, this, i18n("Drag or Type Theme URL") );
      KURL themeURL = fileRequester->getURL();
      QString path = themeURL.path();

      kdDebug() << path << endl;

      if ( path.isEmpty() ) return;

      // Make Sure it doesn't end with a /
      // http://doc.trolltech.com/3.3/qfileinfo.html
      if ( path.endsWith("/") ) {
            kdDebug() << "Truncating..." << endl;
            path.truncate( path.length() - 1 );
      }
      QFileInfo * fi = new QFileInfo( path );
      if ( fi->isDir() ) {
            insertTheme( themeURL.path() );
            configChanged();
            return;
      }
      delete fi;

      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 KDM theme archive %1.");
            else
                  sorryText = i18n("Unable to download the KDM 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 KDM theme archive."));
            KMessageBox::error(this, invalidArch);

            KIO::NetAccess::removeTempFile(themeTmpFile);
            return;
      }

      QStringList themeList = installThemes(themesNames, themeTmpFile);
      if (! themeList.isEmpty() ) {
            KMessageBox::informationList( this,
                                                        i18n( "These themes were not installed due to errors" ),
                                                        themeList,
                                                        i18n( "Error" ) );
      }

      KIO::NetAccess::removeTempFile(themeTmpFile);
      configChanged();
}

QStringList kdmtheme::installThemes(QStringList &themesNames, const QString &archiveName)
{
      QStringList themeList;

      if ( ! KGlobal::dirs()->exists( themeDir ) ) {
            KIO::mkdir( KURL( themeDir ), 755 );
      }

      KProgressDialog progressDiag(this, "themeinstallprogress",
                                                i18n("Installing KDM themes"),
                                                QString::null,
                                                true);
      progressDiag.setAutoClose( true );
      progressDiag.progressBar()->setTotalSteps( themes.count() );
      progressDiag.show();

      KTar archive( archiveName );
      archive.open( IO_ReadOnly );

      const KArchiveDirectory* rootDir = archive.directory();

      KArchiveDirectory* currentTheme;
      for ( QStringList::ConstIterator it = themesNames.begin(); it != themesNames.end(); ++it ) {
            progressDiag.setLabel(
                  i18n("<qt>Installing <strong>%1</strong> theme</qt>")
                  .arg( *it ));

            if ( progressDiag.wasCancelled() ) break;

            currentTheme = dynamic_cast<KArchiveDirectory*>(
                                    const_cast<KArchiveEntry*>(
                                    rootDir->entry(*it)));
            if (currentTheme == NULL || m_themeNames[*it + "0"] == themeDir + *it) {
                  // If the theme does not exist add it to our list so we can report it later.
                  themeList.append( *it );
                  continue;
            } else {
                  themes.append( themeDir + *it );
            }

            currentTheme->copyTo(themeDir + *it, true);
            kdDebug() << "Copied Theme to " << themeDir << *it << endl;
            insertItem( themeDir + *it );
            progressDiag.progressBar()->advance( 1 );
      }

      archive.close();
      return themeList;
}

QStringList kdmtheme::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 a GdmGreeterTheme.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("GdmGreeterTheme.desktop") != NULL))
                        foundThemes.append(subDir->name());
            }
      }

      archive.close();
      return foundThemes;
}


void kdmtheme::removeSelectedTheme() {
      QListViewItem *selected = p_configWidget->ThemeList->selectedItem();
      if (! selected )
            return;


      QString question=i18n("<qt>Are you sure you want to remove the "
                  "<strong>%1</strong> KDM theme?</qt>").
            arg(selected->text(0));

      KDialogBase *dialog = new KDialogBase( this,
                                                            "themedeleteconfirm",
                                                            true,
                                                            i18n( "Confimation" ),
                                                            KDialogBase::Ok|KDialogBase::Cancel );
      // TODO: We probably should remove this. Seems kinda silly that you can remove it from your list yet it will
      // Always come back whenever we restart.
      bool deleteFromDisk = false;
      QStringList list;
      int r = KMessageBox::createKMessageBox( dialog,
                                                            QMessageBox::standardIcon( QMessageBox::Warning ),
                                                            question,
                                                            list,
                                                            i18n( "Delete from Hard disk?" ),
                                                            &deleteFromDisk,
                                                            1 );

      if (r != 1) return;

      if (deleteFromDisk) {
            kdDebug() << "Deleting theme at: " << m_themeNames[ selected->text(0) + "0"] << endl;
            KIO::del( m_themeNames[ selected->text(0) + "0"] );
      }

      removeTheme( selected->text(0) );

      int index = p_configWidget->ThemeList->itemIndex( selected );
      QListViewItem *select = m_defaultTheme;
      if ( index > 0 )
            select = p_configWidget->ThemeList->itemAtIndex( index - 1 );
      else if ( index < p_configWidget->ThemeList->childCount() )
            select = p_configWidget->ThemeList->itemAtIndex( index + 1 );

      p_configWidget->ThemeList->setSelected(select , true );

      if ( selected == m_defaultTheme )
            m_defaultTheme = select;

      p_configWidget->ThemeList->takeItem( selected );

      if ( p_configWidget->ThemeList->childCount() == 0 )
            p_configWidget->cUseTheme->setChecked(false);

      configChanged();
}

// TODO this is ugly figure out why themes.remove isn't working.
void kdmtheme::removeTheme( const QString &theme ) {
      QStringList tmpThemes;
      for (QStringList::Iterator it = themes.begin(); it != themes.end(); ++it) {
            kdDebug() << theme << endl;
            if ( *it != m_themeNames[ theme + "0"] ) {
                  tmpThemes.append( *it );
            } else {
                  kdDebug() << "NOT Appending theme: " << *it << endl;
            }
      }
      themes = tmpThemes;
}


void kdmtheme::load() {
      QString kdmrc = KGlobal::dirs()->findResource("config", "kdm/kdmrc");

      if ( kdmrc.isEmpty() ) {
            kdDebug() << "Failed to find kdmrc!" << endl;
            exit(1);
      }

      kdDebug() << "Loading... ( " + kdmrc + " )" << endl;

      delete config;

      config = new KSimpleConfig( kdmrc );

      config->setGroup( "X-*-Greeter" );

      p_configWidget->cUseTheme->setChecked( config->readBoolEntry( "UseTheme", false ) );

      // Import the list instead of using a var inside kdmrc
      themeDir = *(KGlobal::dirs()->findDirs("data","kdm/").begin()) + "themes/";
      kdDebug() << "Using " << themeDir << " for the themes directory." << endl;
      QDir dirThemes( themeDir );
      dirThemes.setFilter( QDir::Dirs );
      dirThemes.setSorting( QDir::Name );
      themes = dirThemes.entryList();

      if ( themes.isEmpty() ) {
            kdDebug() << "Failed to find the kdm data directory! This should never happen!" << endl;
      }

      QString themeActiveName = config->readEntry("Theme");
      if ( themes.isEmpty() ) {
            insertItem( themeActiveName, themeActiveName );
      } else {
            bool setActiveTheme = false;
            QStringList tmpTheme;
            for ( QStringList::Iterator it = themes.begin(); it != themes.end(); ++it ) {
                  if ( *it == "." || *it == "..") continue;

                  *it = themeDir + *it;

                  kdDebug() << "Adding " << *it << " to the list" << endl;

                  insertItem( *it, themeActiveName);
                  tmpTheme.append( *it );
                  if ( *it == themeActiveName )
                        setActiveTheme = true;
            }
            themes = tmpTheme;
            if (! setActiveTheme && p_configWidget->ThemeList->childCount() > 0 ) {
                  p_configWidget->ThemeList->setSelected( p_configWidget->ThemeList->itemAtIndex( 0 ), true );
                  m_defaultTheme = p_configWidget->ThemeList->itemAtIndex( 0 );
            }

            themeSelected( m_defaultTheme );
      }
}

 void kdmtheme::insertItem( const QString &_theme, const QString &_activeName )
 {
      if ( _theme.isEmpty() )
            return;
      KSimpleConfig *themeConfig = new KSimpleConfig (QString::fromLatin1( _theme + "/GdmGreeterTheme.desktop" ));

      themeConfig->setGroup( "GdmGreeterTheme" );
      QString name = themeConfig->readEntry("Name");

      if ( m_themeNames[name + "0"] != _theme ) {
            QListViewItem * item = new QListViewItem( p_configWidget->ThemeList, 0 );
            item->setText( 0, name );
            item->setText( 1, themeConfig->readEntry("Author") );
            m_themeNames.insert( name + "0", _theme );
            m_themeNames.insert( name + "1", themeConfig->readEntry("Screenshot") );
            m_themeNames.insert( name + "2", themeConfig->readEntry("Copyright") );
            m_themeNames.insert( name + "3", themeConfig->readEntry("Description") );
            if ( _theme == _activeName )
            {
                  p_configWidget->ThemeList->setSelected( item, true );
                  m_defaultTheme = item;
            }
      }
      delete themeConfig;
}


void kdmtheme::updateTheme( const QString &screenshot, const QString &copyright, const QString &description ) {
      p_configWidget->Info->setText(
                  ((copyright.length() > 0)?i18n( "<b>Copyright:</b> " ) + copyright + "<br/>":"") +
                  ((description.length() > 0)?i18n( "<b>Description:</b> " ) + description:"") );
      p_configWidget->Preview->setPixmap( screenshot );
}


void kdmtheme::defaults()
{
      p_configWidget->ThemeList->setSelected( m_defaultTheme, true );

      configChanged();
}


void kdmtheme::save()
{
      kdDebug() << "Saving..." << endl;

      config->setGroup( "X-*-Greeter" );

      config->writeEntry( "UseTheme", p_configWidget->cUseTheme->isChecked() );

      if ( m_selectedTheme )
            config->writeEntry( "Theme", m_themeNames[ m_selectedTheme->text(0) + "0"] );

      if ( config->hasKey( "Themes" ) )
            config->deleteEntry( "Themes" );

      config->sync();

      configChanged();
}


int kdmtheme::buttons()
{
    return KCModule::Default|KCModule::Apply|KCModule::Reset;
}


void kdmtheme::configChanged()
{
    emit changed(true);
}


QString kdmtheme::quickHelp() const
{
    return i18n("This module is designed to aid users in configuring which KDM theme is displayed.");
}


#include "kdmtheme.moc"

Generated by  Doxygen 1.6.0   Back to index