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

superkaramba

  • sources
  • kde-4.12
  • kdeutils
  • superkaramba
  • src
themefile.cpp
Go to the documentation of this file.
1 /****************************************************************************
2 * themefile.cpp - Theme file handling
3 *
4 * Copyright (C) 2003 Hans Karlsson <karlsson.h@home.se>
5 * Copyright (C) 2003-2004 Adam Geitgey <adam@rootnode.org>
6 * Copyright (c) 2004 Petri Damst� <damu@iki.fi>
7 *
8 * This file is part of SuperKaramba.
9 *
10 * SuperKaramba is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * SuperKaramba is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with SuperKaramba; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 ****************************************************************************/
24 #include "themefile.h"
25 #include "lineparser.h"
26 #include "themelocale.h"
27 
28 #include <KZip>
29 #include <KTempDir>
30 #include <KApplication>
31 #include <KMessageBox>
32 #include <KStandardDirs>
33 #include <KLocale>
34 #include <kio/job.h>
35 #include <kio/copyjob.h>
36 #include <KIO/NetAccess>
37 #include <kross/core/manager.h>
38 #include <kross/core/interpreter.h>
39 
40 #include <QDomNode>
41 
42 class ZipFile
43 {
44 public:
45  ZipFile() :
46  m_zip(0), m_file(0), m_tempDir(0)
47  {}
48  void setFile(const QString& filename)
49  {
50  m_filename = filename;
51  if (filename.isEmpty())
52  return;
53 
54  const KArchiveEntry* entry;
55 
56  entry = m_dir->entry(filename);
57  if (entry == 0 || !entry->isFile()) {
58  m_file = 0;
59  return;
60  }
61  m_file = static_cast<const KArchiveFile*>(entry);
62  }
63  void setZip(const QString& zipfile)
64  {
65  closeZip();
66 
67  m_zip = new KZip(zipfile);
68 
69  if (!m_zip->open(QIODevice::ReadOnly)) {
70  qDebug("Unable to open '%s' for reading.", zipfile.toAscii().constData());
71  return;
72  }
73  m_dir = m_zip->directory();
74  if (m_dir == 0) {
75  qDebug("Error reading directory contents of file %s", zipfile.toAscii().constData());
76  return;
77  }
78  }
79 
80  virtual ~ZipFile()
81  {
82  closeZip();
83  }
84 
85  void closeZip()
86  {
87  if (m_zip) {
88  m_zip->close();
89  delete m_zip;
90  delete m_tempDir;
91  }
92  }
93 
94  QByteArray data()
95  {
96  if (m_file)
97  return m_file->data();
98  else {
99  if (!m_filename.isEmpty())
100  qDebug("Error reading file %s from zip", m_filename.toAscii().constData());
101  return QByteArray();
102  }
103  }
104 
105  bool exists()
106  {
107  return (m_file != 0);
108  }
109 
110  QString extractArchive()
111  {
112  QString tmpPath = KStandardDirs::locateLocal("tmp", "runningThemes/");
113 
114  m_tempDir = new KTempDir(tmpPath);
115  m_tempDir->setAutoRemove(true);
116 
117  m_dir->copyTo(m_tempDir->name());
118 
119  return m_tempDir->name();
120  }
121 
122  bool extractArchiveTo(const QString& path)
123  {
124  m_dir->copyTo(path);
125  return true;
126  }
127 
128  bool extractArchiveFileTo(const QString& file, const QString& path)
129  {
130  const KArchiveEntry* entry = m_dir ? m_dir->entry(file) : 0;
131  const KArchiveFile* f = (entry && entry->isFile()) ? static_cast<const KArchiveFile*>(entry) : 0;
132  if (! f)
133  return false;
134  f->copyTo(path);
135  return true;
136  }
137 
138 private:
139  KZip* m_zip;
140  const KArchiveFile* m_file;
141  QString m_filename;
142  const KArchiveDirectory* m_dir;
143  KTempDir* m_tempDir;
144 };
145 
146 class ThemeFile::Private
147 {
148 public:
149  QString path;
150  bool zipTheme;
151  QString file;
152  QString id;
153  QString mo;
154  QString name;
155  QString theme;
156  QString script;
157  QString icon;
158  QString version;
159  QString license;
160  QTextStream* stream;
161  QByteArray ba;
162  QFile fl;
163  QString description;
164  QString author;
165  QString authorEmail;
166  QString homepage;
167  ThemeLocale* locale;
168  ZipFile* zip;
169  KUrl UrlPath;
170 
171  Private()
172  : zipTheme(false), stream(0), locale(0), zip(0)
173  {
174  }
175 
176  ~Private()
177  {
178  delete stream;
179  delete locale;
180  delete zip;
181  }
182 
183 };
184 
185 ThemeFile::ThemeFile(const KUrl& url)
186  : d(new Private)
187 {
188  if (url.isValid())
189  set(url);
190 }
191 
192 ThemeFile::~ThemeFile()
193 {
194  delete d;
195 }
196 
197 bool ThemeFile::open()
198 {
199  bool result = false;
200 
201  close();
202 
203  if (d->zipTheme) {
204  d->zip->setFile(d->theme);
205  d->ba = d->zip->data();
206  if (d->ba.size() > 0) {
207  d->stream = new QTextStream(d->ba, QIODevice::ReadOnly);
208  result = true;
209  }
210  } else {
211  d->fl.setFileName(d->file);
212 
213  if (d->fl.open(QIODevice::ReadOnly | QIODevice::Text)) {
214  d->stream = new QTextStream(&d->fl); // use a text stream
215  result = true;
216  }
217  }
218  return result;
219 }
220 
221 bool ThemeFile::nextLine(LineParser& parser)
222 {
223  parser.set("");
224 
225  if (d->stream) {
226  QString result = d->stream->readLine();
227  while ( result.endsWith("\\") ) {
228  result.chop(1); // remove continuation directive
229  result += d->stream->readLine();
230  }
231 
232  if (result.isNull())
233  return false;
234  parser.set(result);
235  return true;
236  }
237  return false;
238 }
239 
240 bool ThemeFile::close()
241 {
242  if (d->stream) {
243  delete d->stream;
244  d->stream = 0;
245  d->fl.close();
246  d->ba.resize(0);
247  return true;
248  }
249  return false;
250 }
251 
252 bool ThemeFile::isValid() const
253 {
254  return (exists() && !d->name.isEmpty() && !d->theme.isEmpty());
255 }
256 
257 bool ThemeFile::exists() const
258 {
259  QFileInfo file(d->file);
260  return file.exists();
261 }
262 
263 QPixmap ThemeFile::icon() const
264 {
265  QPixmap icon;
266  icon.loadFromData(readThemeFile(d->icon));
267  return icon;
268 }
269 
270 QString ThemeFile::iconName() const
271 {
272  return d->icon;
273 }
274 
275 bool ThemeFile::set(const KUrl &url)
276 {
277  if (!url.isLocalFile() && !url.protocol().isEmpty()) {
278  if (KMessageBox::warningContinueCancel(qApp->activeWindow(),
279  i18n("You are about to install and run %1 SuperKaramba theme. Since "
280  "themes can contain executable code you should only install themes "
281  "from sources that you trust. Continue?",
282  url.prettyUrl()),
283  i18n("Executable Code Warning"),
284  KGuiItem(i18n("Install")))
285  //i18n("Install").arg(url.prettyUrl()))
286  == KMessageBox::Cancel) {
287  return false;
288  }
289 
290  QDir themeDir(KStandardDirs::locateLocal("appdata", "themes/", true));
291  QFileInfo localFile = themeDir.filePath(url.fileName());
292 
293  if (localFile.exists()) {
294  if (KMessageBox::warningContinueCancel(qApp->activeWindow(),
295  i18n("%1 already exists. Do you want to overwrite it?", localFile.filePath()),
296  i18n("File Exists"),
297  KGuiItem(i18n("Overwrite"))
298  )
299  == KMessageBox::Cancel) {
300  return false;
301  }
302  }
303 
304  KIO::Job *job = KIO::file_copy(url, localFile.filePath(), -1, KIO::Overwrite);
305 
306  if (!KIO::NetAccess::synchronousRun(job, qApp->activeWindow())) {
307  return false;
308  }
309 
310  d->file = localFile.filePath();
311  } else {
312  if (url.directory().isEmpty() || url.directory() == "/")
313  d->file = canonicalFile(QDir::current().filePath(url.fileName()));
314  else
315  d->file = canonicalFile(url.path());
316  if (!exists())
317  return false;
318  }
319 
320  d->UrlPath = url;
321 
322  QFileInfo fi(d->file);
323 
324  d->name = fi.completeBaseName();
325  d->theme = d->name + ".theme";
326  d->script = d->name;
327 
328  bool fileExtensionFound = false;
329  const QStringList availInterp = Kross::Manager::self().interpreters();
330  foreach (const QString &interpreter, availInterp) {
331  QString fileExtension = Kross::Manager::self().interpreterInfo(interpreter)->wildcard();
332  fileExtension.remove(0, 1);
333 
334  if (fileExists(fi.path() + '/' + d->script + fileExtension)) {
335  d->script += fileExtension;
336  fileExtensionFound = true;
337  break;
338  }
339  }
340  if (!fileExtensionFound) {
341  d->script += ".py";
342  }
343 
344  d->id = d->name;
345 
346  if (isZipFile(d->file)) {
347  d->path = d->file;
348  d->zipTheme = true;
349  d->zip = new ZipFile();
350  d->zip->setZip(d->file);
351  } else {
352  d->path = fi.absoluteDir().absolutePath() + '/';
353  d->zipTheme = false;
354  }
355  parseXml();
356 
357  QFileInfo fimo(d->script);
358  if (d->script.isEmpty())
359  fimo.setFile(d->theme);
360  else
361  fimo.setFile(d->script);
362  d->mo = fimo.completeBaseName();
363 
364  d->locale = new ThemeLocale(this);
365  return isValid();
366 }
367 
368 KUrl ThemeFile::getUrlPath()
369 {
370  return d->UrlPath;
371 }
372 
373 void ThemeFile::parseXml()
374 {
375  if (!fileExists("maindata.xml"))
376  return;
377  QByteArray ba = readThemeFile("maindata.xml");
378  QDomDocument doc("superkaramba_theme");
379  doc.setContent(ba);
380  QDomElement element = doc.documentElement();
381 
382  QDomNode n = element.firstChild();
383  while (!n.isNull()) {
384  QDomElement e = n.toElement();
385  if (!e.isNull()) {
386  if (e.tagName() == "name") {
387  d->name = e.text();
388  } else if (e.tagName() == "themefile") {
389  d->theme = e.text();
390  } else if (e.tagName() == "python_module") {
391  d->script = e.text();
392  } else if (e.tagName() == "script_module") {
393  d->script = e.text();
394  } else if (e.tagName() == "description") {
395  d->description = e.text();
396  } else if (e.tagName() == "author") {
397  d->author = e.text();
398  } else if (e.tagName() == "author_email") {
399  d->authorEmail = e.text();
400  } else if (e.tagName() == "homepage") {
401  d->homepage = e.text();
402  } else if (e.tagName() == "icon") {
403  d->icon = e.text();
404  } else if (e.tagName() == "version") {
405  d->version = e.text();
406  } else if (e.tagName() == "license") {
407  d->license = e.text();
408  }
409  }
410  n = n.nextSibling();
411  }
412 }
413 
414 bool ThemeFile::canUninstall() const
415 {
416  QFileInfo fi(file());
417  if (fi.permission(QFile::WriteUser) ||
418  fi.permission(QFile::WriteGroup) ||
419  fi.permission(QFile::WriteOther))
420  return true;
421  return false;
422 }
423 
424 bool ThemeFile::isThemeFile(const QString& filename) const
425 {
426  QFileInfo fileInfo(filename);
427 
428  return fileInfo.isRelative();
429 }
430 
431 bool ThemeFile::fileExists(const QString& filename) const
432 {
433  if (isThemeFile(filename)) {
434  if (isZipTheme()) {
435  d->zip->setFile(filename);
436  return d->zip->exists();
437  } else
438  return QFileInfo(path() + '/' + filename).exists();
439  } else
440  return QFileInfo(filename).exists();
441 }
442 
443 QByteArray ThemeFile::readThemeFile(const QString& filename) const
444 {
445  //QTime time;
446  //time.start();
447  QByteArray ba;
448 
449  if (isZipTheme()) {
450  d->zip->setFile(filename);
451  ba = d->zip->data();
452  } else {
453  QFile file(path() + '/' + filename);
454 
455  if (file.open(QIODevice::ReadOnly)) {
456  ba = file.readAll();
457  file.close();
458  }
459  }
460  //kDebug() << "Read theme file: " << filename << ", " << time.elapsed()
461  // << "ms" << endl;
462  return ba;
463 }
464 
465 bool ThemeFile::isZipFile(const QString& filename)
466 {
467  QFile file(filename);
468 
469  if (file.open(QIODevice::ReadOnly)) {
470  unsigned char buf[5];
471 
472  if (file.read((char*)buf, 4) == 4) {
473  if (buf[0] == 'P' && buf[1] == 'K' && buf[2] == 3 && buf[3] == 4)
474  return true;
475  }
476  }
477  return false;
478 }
479 
480 bool ThemeFile::scriptModuleExists() const
481 {
482  if (d->script.isEmpty()) {
483  return false;
484  }
485 
486  if (fileExists(d->script)) {
487  return true;
488  }
489 
490  return false;
491 }
492 
493 QString ThemeFile::canonicalFile(const QString& file)
494 {
495  // Get absolute path with NO symlinks
496  QFileInfo fi(file);
497  return QDir(fi.dir().canonicalPath()).filePath(fi.fileName());
498 }
499 
500 QString ThemeFile::extractArchive() const
501 {
502  if (isZipTheme()) {
503  return d->zip->extractArchive();
504  }
505 
506  return QString();
507 }
508 
509 bool ThemeFile::extractArchiveTo(const QString& path)
510 {
511  return isZipTheme() ? d->zip->extractArchiveTo(path) : false;
512 }
513 
514 bool ThemeFile::extractArchiveFileTo(const QString& file, const QString& path)
515 {
516  return isZipTheme() ? d->zip->extractArchiveFileTo(file, path) : false;
517 }
518 
519 bool ThemeFile::copyArchiveTo(const QString& path)
520 {
521  if (! isZipTheme())
522  return false;
523  KUrl url = getUrlPath();
524  if (! url.isValid())
525  return false;
526  KIO::CopyJob* job = KIO::copy(url, path, KIO::HideProgressInfo | KIO::Overwrite);
527  bool ok = KIO::NetAccess::synchronousRun( job, 0 );
528  return ok;
529 }
530 
531 bool ThemeFile::isZipTheme() const
532 {
533  return d->zipTheme;
534 }
535 
536 const QString& ThemeFile::name() const
537 {
538  return d->name;
539 }
540 
541 const QString& ThemeFile::version() const
542 {
543  return d->version;
544 }
545 
546 const QString& ThemeFile::license() const
547 {
548  return d->license;
549 }
550 
551 const QString& ThemeFile::id() const
552 {
553  return d->id;
554 }
555 
556 const QString& ThemeFile::mo() const
557 {
558  return d->mo;
559 }
560 
561 const QString& ThemeFile::file() const
562 {
563  return d->file;
564 }
565 
566 const QString& ThemeFile::scriptModule() const
567 {
568  return d->script;
569 }
570 
571 const QString& ThemeFile::path() const
572 {
573  return d->path;
574 }
575 
576 const QString& ThemeFile::description() const
577 {
578  return d->description;
579 }
580 
581 const QString& ThemeFile::author() const
582 {
583  return d->author;
584 }
585 
586 const QString& ThemeFile::authorEmail() const
587 {
588  return d->authorEmail;
589 }
590 
591 const QString& ThemeFile::homepage() const
592 {
593  return d->homepage;
594 }
595 
596 const ThemeLocale* ThemeFile::locale() const
597 {
598  return d->locale;
599 }
600 
ThemeFile::~ThemeFile
~ThemeFile()
Definition: themefile.cpp:192
ThemeLocale
Definition: themelocale.h:40
LineParser::set
void set(const QString &line)
Definition: lineparser.cpp:35
ThemeFile::locale
const ThemeLocale * locale() const
Definition: themefile.cpp:596
ThemeFile::file
const QString & file() const
Definition: themefile.cpp:561
ThemeFile::authorEmail
const QString & authorEmail() const
Definition: themefile.cpp:586
ThemeFile::getUrlPath
KUrl getUrlPath()
Definition: themefile.cpp:368
ThemeFile::canonicalFile
static QString canonicalFile(const QString &file)
Definition: themefile.cpp:493
ThemeFile::scriptModule
const QString & scriptModule() const
Definition: themefile.cpp:566
ThemeFile::copyArchiveTo
bool copyArchiveTo(const QString &path)
Definition: themefile.cpp:519
themelocale.h
ThemeFile::isThemeFile
bool isThemeFile(const QString &filename) const
Definition: themefile.cpp:424
ThemeFile::id
const QString & id() const
Definition: themefile.cpp:551
lineparser.h
themefile.h
ThemeFile::name
const QString & name() const
Definition: themefile.cpp:536
LineParser
Definition: lineparser.h:6
ThemeFile::open
bool open()
Definition: themefile.cpp:197
ThemeFile::scriptModuleExists
bool scriptModuleExists() const
Definition: themefile.cpp:480
ThemeFile::exists
bool exists() const
Definition: themefile.cpp:257
ThemeFile::extractArchiveFileTo
bool extractArchiveFileTo(const QString &file, const QString &path)
Definition: themefile.cpp:514
ThemeFile::nextLine
bool nextLine(LineParser &parser)
Definition: themefile.cpp:221
ThemeFile::description
const QString & description() const
Definition: themefile.cpp:576
ThemeFile::homepage
const QString & homepage() const
Definition: themefile.cpp:591
ThemeFile::set
bool set(const KUrl &url)
Definition: themefile.cpp:275
ThemeFile::version
const QString & version() const
Definition: themefile.cpp:541
ThemeFile::extractArchiveTo
bool extractArchiveTo(const QString &path)
Definition: themefile.cpp:509
ThemeFile::ThemeFile
ThemeFile(const KUrl &url=KUrl())
Definition: themefile.cpp:185
ThemeFile::isZipTheme
bool isZipTheme() const
Definition: themefile.cpp:531
ThemeFile::path
const QString & path() const
Definition: themefile.cpp:571
ThemeFile::iconName
QString iconName() const
Definition: themefile.cpp:270
ThemeFile::isValid
bool isValid() const
Definition: themefile.cpp:252
ThemeFile::canUninstall
bool canUninstall() const
Definition: themefile.cpp:414
ThemeFile::mo
const QString & mo() const
Definition: themefile.cpp:556
ThemeFile::author
const QString & author() const
Definition: themefile.cpp:581
ThemeFile::close
bool close()
Definition: themefile.cpp:240
ThemeFile::isZipFile
static bool isZipFile(const QString &filename)
Definition: themefile.cpp:465
ThemeFile::readThemeFile
QByteArray readThemeFile(const QString &filename) const
Definition: themefile.cpp:443
ThemeFile::extractArchive
QString extractArchive() const
Definition: themefile.cpp:500
ThemeFile::license
const QString & license() const
Definition: themefile.cpp:546
ThemeFile::fileExists
bool fileExists(const QString &filename) const
Definition: themefile.cpp:431
ThemeFile::icon
QPixmap icon() const
Definition: themefile.cpp:263
This file is part of the KDE documentation.
Documentation copyright © 1996-2014 The KDE developers.
Generated on Tue Oct 14 2014 23:07:20 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

superkaramba

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

kdeutils API Reference

Skip menu "kdeutils API Reference"
  • ark
  • filelight
  • kcalc
  • kcharselect
  • kdf
  • kfloppy
  • kgpg
  • kremotecontrol
  • ktimer
  • kwallet
  • superkaramba
  • sweeper

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal