• Skip to content
  • Skip to link menu
KDE 4.0 API Reference
  • KDE API Reference
  • kdeutils
  • Sitemap
  • Contact Us
 

superkaramba

themefile.cpp

Go to the documentation of this file.
00001 /****************************************************************************
00002 *  themefile.cpp - Theme file handling
00003 *
00004 *  Copyright (C) 2003 Hans Karlsson <karlsson.h@home.se>
00005 *  Copyright (C) 2003-2004 Adam Geitgey <adam@rootnode.org>
00006 *  Copyright (c) 2004 Petri Damst� <damu@iki.fi>
00007 *
00008 *  This file is part of SuperKaramba.
00009 *
00010 *  SuperKaramba is free software; you can redistribute it and/or modify
00011 *  it under the terms of the GNU General Public License as published by
00012 *  the Free Software Foundation; either version 2 of the License, or
00013 *  (at your option) any later version.
00014 *
00015 *  SuperKaramba is distributed in the hope that it will be useful,
00016 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 *  GNU General Public License for more details.
00019 *
00020 *  You should have received a copy of the GNU General Public License
00021 *  along with SuperKaramba; if not, write to the Free Software
00022 *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
00023 ****************************************************************************/
00024 #include "themefile.h"
00025 #include "lineparser.h"
00026 #include "themelocale.h"
00027 
00028 #include <KZip>
00029 #include <KTempDir>
00030 #include <KApplication>
00031 #include <KMessageBox>
00032 #include <KStandardDirs>
00033 #include <KLocale>
00034 #include <kio/job.h>
00035 #include <KIO/NetAccess>
00036 #include <kross/core/manager.h>
00037 #include <kross/core/interpreter.h>
00038 
00039 #include <QDomNode>
00040 
00041 class ZipFile
00042 {
00043 public:
00044     ZipFile() :
00045             m_zip(0), m_file(0), m_tempDir(0)
00046     {}
00047     void setFile(const QString& filename)
00048     {
00049         m_filename = filename;
00050         if (filename.isEmpty())
00051             return;
00052 
00053         const KArchiveEntry* entry;
00054 
00055         entry = m_dir->entry(filename);
00056         if (entry == 0 || !entry->isFile()) {
00057             m_file = 0;
00058             return;
00059         }
00060         m_file = static_cast<const KArchiveFile*>(entry);
00061     }
00062     void setZip(const QString& zipfile)
00063     {
00064         closeZip();
00065 
00066         m_zip = new KZip(zipfile);
00067 
00068         if (!m_zip->open(QIODevice::ReadOnly)) {
00069             qDebug("Unable to open '%s' for reading.", zipfile.toAscii().constData());
00070             return;
00071         }
00072         m_dir = m_zip->directory();
00073         if (m_dir == 0) {
00074             qDebug("Error reading directory contents of file %s", zipfile.toAscii().constData());
00075             return;
00076         }
00077     }
00078 
00079     virtual ~ZipFile()
00080     {
00081         closeZip();
00082     }
00083 
00084     void closeZip()
00085     {
00086         if (m_zip) {
00087             m_zip->close();
00088             delete m_zip;
00089             delete m_tempDir;
00090         }
00091     }
00092 
00093     QByteArray data()
00094     {
00095         if (m_file)
00096             return m_file->data();
00097         else {
00098             if (!m_filename.isEmpty())
00099                 qDebug("Error reading file %s from zip", m_filename.toAscii().constData());
00100             return QByteArray();
00101         }
00102     }
00103 
00104     bool exists()
00105     {
00106         return (m_file != 0);
00107     }
00108 
00109     QString extractArchive()
00110     {
00111         QString tmpPath = KStandardDirs::locateLocal("tmp", "runningThemes/");
00112 
00113         m_tempDir = new KTempDir(tmpPath);
00114         m_tempDir->setAutoRemove(true);
00115 
00116         m_dir->copyTo(m_tempDir->name());
00117 
00118         return m_tempDir->name();
00119     }
00120 
00121 private:
00122     KZip* m_zip;
00123     const KArchiveFile* m_file;
00124     QString m_filename;
00125     const KArchiveDirectory* m_dir;
00126     KTempDir* m_tempDir;
00127 };
00128 
00129 class ThemeFile::Private
00130 {
00131 public:
00132     QString path;
00133     bool zipTheme;
00134     QString file;
00135     QString id;
00136     QString mo;
00137     QString name;
00138     QString theme;
00139     QString script;
00140     QString icon;
00141     QString version;
00142     QString license;
00143     QTextStream* stream;
00144     QByteArray ba;
00145     QFile fl;
00146     QString description;
00147     QString author;
00148     QString authorEmail;
00149     QString homepage;
00150     ThemeLocale* locale;
00151     ZipFile* zip;
00152     KUrl UrlPath;
00153 
00154     Private()
00155         : zipTheme(false), stream(0), locale(0), zip(0)
00156     {
00157     }
00158 
00159     ~Private()
00160     {
00161         delete stream;
00162         delete locale;
00163         delete zip;
00164     }
00165 
00166 };
00167 
00168 ThemeFile::ThemeFile(const KUrl& url)
00169     : d(new Private)
00170 {
00171     if (url.isValid())
00172         set(url);
00173 }
00174 
00175 ThemeFile::~ThemeFile()
00176 {
00177     delete d;
00178 }
00179 
00180 bool ThemeFile::open()
00181 {
00182     bool result = false;
00183 
00184     close();
00185 
00186     if (d->zipTheme) {
00187         d->zip->setFile(d->theme);
00188         d->ba = d->zip->data();
00189         if (d->ba.size() > 0) {
00190             d->stream = new QTextStream(d->ba, QIODevice::ReadOnly);
00191             result = true;
00192         }
00193     } else {
00194         d->fl.setFileName(d->file);
00195 
00196         if (d->fl.open(QIODevice::ReadOnly | QIODevice::Text)) {
00197             d->stream = new QTextStream(&d->fl);        // use a text stream
00198             result = true;
00199         }
00200     }
00201     return result;
00202 }
00203 
00204 bool ThemeFile::nextLine(LineParser& parser)
00205 {
00206     parser.set("");
00207 
00208     if (d->stream) {
00209         QString result = d->stream->readLine();
00210 
00211         if (result.isNull())
00212             return false;
00213         parser.set(result);
00214         return true;
00215     }
00216     return false;
00217 }
00218 
00219 bool ThemeFile::close()
00220 {
00221     if (d->stream) {
00222         delete d->stream;
00223         d->stream = 0;
00224         d->fl.close();
00225         d->ba.resize(0);
00226         return true;
00227     }
00228     return false;
00229 }
00230 
00231 bool ThemeFile::isValid() const
00232 {
00233     return (exists() && !d->name.isEmpty() && !d->theme.isEmpty());
00234 }
00235 
00236 bool ThemeFile::exists() const
00237 {
00238     QFileInfo file(d->file);
00239     return file.exists();
00240 }
00241 
00242 QPixmap ThemeFile::icon() const
00243 {
00244     QPixmap icon;
00245     icon.loadFromData(readThemeFile(d->icon));
00246     return icon;
00247 }
00248 
00249 bool ThemeFile::set(const KUrl &url)
00250 {
00251     if (!url.isLocalFile() && !url.protocol().isEmpty()) {
00252         if (KMessageBox::warningContinueCancel(qApp->activeWindow(),
00253                                                i18n("You are about to install and run %1 SuperKaramba theme. Since "
00254                                                     "themes can contain executable code you should only install themes "
00255                                                     "from sources that you trust. Continue?",
00256                                                     url.prettyUrl()),
00257                                                i18n("Executable Code Warning"),
00258                                                KGuiItem(i18n("Install")))
00259                 //i18n("Install").arg(url.prettyUrl()))
00260                 == KMessageBox::Cancel) {
00261             return false;
00262         }
00263 
00264         QDir themeDir(KStandardDirs::locateLocal("appdata", "themes/", true));
00265         QFileInfo localFile = themeDir.filePath(url.fileName());
00266 
00267         if (localFile.exists()) {
00268             if (KMessageBox::warningContinueCancel(qApp->activeWindow(),
00269                                                    i18n("%1 already exists. Do you want to overwrite it?", localFile.filePath()),
00270                                                    i18n("File Exists"),
00271                                                    KGuiItem(i18n("Overwrite"))
00272                                                   )
00273                     == KMessageBox::Cancel) {
00274                 return false;
00275             }
00276         }
00277 
00278         KIO::Job *job = KIO::file_copy(url, localFile.filePath(), -1, KIO::Overwrite);
00279 
00280         if (!KIO::NetAccess::synchronousRun(job, qApp->activeWindow())) {
00281             return false;
00282         }
00283 
00284         d->file = localFile.filePath();
00285     } else {
00286         if (url.directory().isEmpty() || url.directory() == "/")
00287             d->file = canonicalFile(QDir::current().filePath(url.fileName()));
00288         else
00289             d->file = canonicalFile(url.path());
00290         if (!exists())
00291             return false;
00292     }
00293 
00294     d->UrlPath = url;
00295 
00296     QFileInfo fi(d->file);
00297 
00298     d->name = fi.completeBaseName();
00299     d->theme = d->name + ".theme";
00300     d->script = d->name;
00301 
00302     bool fileExtensionFound = false;
00303     QStringList availInterp = Kross::Manager::self().interpreters();
00304     foreach (QString interpreter, availInterp) {
00305         QString fileExtension = Kross::Manager::self().interpreterInfo(interpreter)->wildcard();
00306         fileExtension.remove(0, 1);
00307 
00308         if (fileExists(fi.path() + '/' + d->script + fileExtension)) {
00309             d->script += fileExtension;
00310             fileExtensionFound = true;
00311             break;
00312         }
00313     }
00314     if (!fileExtensionFound) {
00315         d->script += ".py";
00316     }
00317 
00318     d->id = d->name;
00319 
00320     if (isZipFile(d->file)) {
00321         d->path = d->file;
00322         d->zipTheme = true;
00323         d->zip = new ZipFile();
00324         d->zip->setZip(d->file);
00325     } else {
00326         d->path = fi.absoluteDir().absolutePath() + '/';
00327         d->zipTheme = false;
00328     }
00329     parseXml();
00330 
00331     QFileInfo fimo(d->script);
00332     if (d->script.isEmpty())
00333         fimo.setFile(d->theme);
00334     else
00335         fimo.setFile(d->script);
00336     d->mo = fimo.completeBaseName();
00337 
00338     d->locale = new ThemeLocale(this);
00339     return isValid();
00340 }
00341 
00342 KUrl ThemeFile::getUrlPath()
00343 {
00344     return d->UrlPath;
00345 }
00346 
00347 void ThemeFile::parseXml()
00348 {
00349     if (!fileExists("maindata.xml"))
00350         return;
00351     QByteArray ba = readThemeFile("maindata.xml");
00352     QDomDocument doc("superkaramba_theme");
00353     doc.setContent(ba);
00354     QDomElement element = doc.documentElement();
00355 
00356     QDomNode n = element.firstChild();
00357     while (!n.isNull()) {
00358         QDomElement e = n.toElement();
00359         if (!e.isNull()) {
00360             if (e.tagName() == "name") {
00361                 d->name = e.text();
00362             } else if (e.tagName() == "themefile") {
00363                 d->theme = e.text();
00364             } else if (e.tagName() == "python_module") {
00365                 d->script = e.text();
00366             } else if (e.tagName() == "script_module") {
00367                 d->script = e.text();
00368             } else if (e.tagName() == "description") {
00369                 d->description = e.text();
00370             } else if (e.tagName() == "author") {
00371                 d->author = e.text();
00372             } else if (e.tagName() == "author_email") {
00373                 d->authorEmail = e.text();
00374             } else if (e.tagName() == "homepage") {
00375                  d->homepage = e.text();
00376             } else if (e.tagName() == "icon") {
00377                 d->icon = e.text();
00378             } else if (e.tagName() == "version") {
00379                 d->version = e.text();
00380             } else if (e.tagName() == "license") {
00381                 d->license = e.text();
00382             }
00383         }
00384         n = n.nextSibling();
00385     }
00386 }
00387 
00388 bool ThemeFile::canUninstall() const
00389 {
00390     QFileInfo fi(file());
00391     if (fi.permission(QFile::WriteUser) ||
00392             fi.permission(QFile::WriteGroup) ||
00393             fi.permission(QFile::WriteOther))
00394         return true;
00395     return false;
00396 }
00397 
00398 bool ThemeFile::isThemeFile(const QString& filename) const
00399 {
00400     QFileInfo fileInfo(filename);
00401 
00402     return fileInfo.isRelative();
00403 }
00404 
00405 bool ThemeFile::fileExists(const QString& filename) const
00406 {
00407     if (isThemeFile(filename)) {
00408         if (isZipTheme()) {
00409             d->zip->setFile(filename);
00410             return d->zip->exists();
00411         } else
00412             return QFileInfo(path() + '/' + filename).exists();
00413     } else
00414         return QFileInfo(filename).exists();
00415 }
00416 
00417 QByteArray ThemeFile::readThemeFile(const QString& filename) const
00418 {
00419     //QTime time;
00420     //time.start();
00421     QByteArray ba;
00422 
00423     if (isZipTheme()) {
00424         d->zip->setFile(filename);
00425         ba = d->zip->data();
00426     } else {
00427         QFile file(path() + '/' + filename);
00428 
00429         if (file.open(QIODevice::ReadOnly)) {
00430             ba = file.readAll();
00431             file.close();
00432         }
00433     }
00434     //kDebug() << "Read theme file: " << filename << ", " << time.elapsed()
00435     //    << "ms" << endl;
00436     return ba;
00437 }
00438 
00439 bool ThemeFile::isZipFile(const QString& filename)
00440 {
00441     QFile file(filename);
00442 
00443     if (file.open(QIODevice::ReadOnly)) {
00444         unsigned char buf[5];
00445 
00446         if (file.read((char*)buf, 4) == 4) {
00447             if (buf[0] == 'P' && buf[1] == 'K' && buf[2] == 3 && buf[3] == 4)
00448                 return true;
00449         }
00450     }
00451     return false;
00452 }
00453 
00454 bool ThemeFile::scriptModuleExists() const
00455 {
00456     if (d->script.isEmpty()) {
00457         return false;
00458     }
00459 
00460     if (fileExists(d->script)) {
00461         return true;
00462     }
00463 
00464     return false;
00465 }
00466 
00467 QString ThemeFile::canonicalFile(const QString& file)
00468 {
00469     // Get absolute path with NO symlinks
00470     QFileInfo fi(file);
00471     return QDir(fi.dir().canonicalPath()).filePath(fi.fileName());
00472 }
00473 
00474 QString ThemeFile::extractArchive() const
00475 {
00476     if (isZipTheme()) {
00477         return d->zip->extractArchive();
00478     }
00479 
00480     return QString();
00481 }
00482 
00483 bool ThemeFile::isZipTheme() const
00484 {
00485     return d->zipTheme;
00486 }
00487 
00488 const QString& ThemeFile::name() const
00489 {
00490     return d->name;
00491 }
00492 
00493 const QString& ThemeFile::version() const
00494 {
00495     return d->version;
00496 }
00497 
00498 const QString& ThemeFile::license() const
00499 {
00500     return d->license;
00501 }
00502 
00503 const QString& ThemeFile::id() const
00504 {
00505     return d->id;
00506 }
00507 
00508 const QString& ThemeFile::mo() const
00509 {
00510     return d->mo;
00511 }
00512 
00513 const QString& ThemeFile::file() const
00514 {
00515     return d->file;
00516 }
00517 
00518 const QString& ThemeFile::scriptModule() const
00519 {
00520     return d->script;
00521 }
00522 
00523 const QString& ThemeFile::path() const
00524 {
00525     return d->path;
00526 }
00527 
00528 const QString& ThemeFile::description() const
00529 {
00530     return d->description;
00531 }
00532 
00533 const QString& ThemeFile::author() const
00534 {
00535     return d->author;
00536 }
00537 
00538 const QString& ThemeFile::authorEmail() const
00539 {
00540     return d->authorEmail;
00541 }
00542 
00543 const QString& ThemeFile::homepage() const
00544 {
00545     return d->homepage;
00546 }
00547 
00548 const ThemeLocale* ThemeFile::locale() const
00549 {
00550     return d->locale;
00551 }
00552 

superkaramba

Skip menu "superkaramba"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Class Members
  • Related Pages

kdeutils

Skip menu "kdeutils"
  • ark
  • kcalc
  • kcharselect
  • kdelirc
  • kdessh
  • kdf
  • kfloppy
  • kgpg
  • kjots
  • klaptopdaemon
  • kmilo
  • ksim
  • ktimer
  • kwallet
  • superkaramba
Generated for kdeutils by doxygen 1.5.4
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal