summaryrefslogtreecommitdiffstats
path: root/src/common/global
diff options
context:
space:
mode:
Diffstat (limited to 'src/common/global')
-rw-r--r--src/common/global/Makefile.am8
-rw-r--r--src/common/global/about.cpp94
-rw-r--r--src/common/global/about.h43
-rw-r--r--src/common/global/generic_config.cpp241
-rw-r--r--src/common/global/generic_config.h84
-rw-r--r--src/common/global/global.h61
-rw-r--r--src/common/global/global.pro8
-rw-r--r--src/common/global/log.cpp154
-rw-r--r--src/common/global/log.h134
-rw-r--r--src/common/global/pfile.cpp89
-rw-r--r--src/common/global/pfile.h66
-rw-r--r--src/common/global/process.cpp193
-rw-r--r--src/common/global/process.h138
-rw-r--r--src/common/global/progress_monitor.cpp84
-rw-r--r--src/common/global/progress_monitor.h46
-rw-r--r--src/common/global/purl.cpp428
-rw-r--r--src/common/global/purl.h136
-rw-r--r--src/common/global/svn_revision/Makefile.am5
-rwxr-xr-xsrc/common/global/svn_revision/svn_revision.sh20
-rw-r--r--src/common/global/xml_data_file.cpp160
-rw-r--r--src/common/global/xml_data_file.h45
21 files changed, 2237 insertions, 0 deletions
diff --git a/src/common/global/Makefile.am b/src/common/global/Makefile.am
new file mode 100644
index 0000000..a94b45c
--- /dev/null
+++ b/src/common/global/Makefile.am
@@ -0,0 +1,8 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+SUBDIRS = svn_revision
+
+noinst_LTLIBRARIES = libglobal.la
+libglobal_la_SOURCES = about.cpp generic_config.cpp log.cpp pfile.cpp \
+ process.cpp progress_monitor.cpp purl.cpp xml_data_file.cpp
+libglobal_la_LDFLAGS = $(all_libraries)
diff --git a/src/common/global/about.cpp b/src/common/global/about.cpp
new file mode 100644
index 0000000..33bfae9
--- /dev/null
+++ b/src/common/global/about.cpp
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#include "about.h"
+
+#if defined(Q_WS_WIN)
+# define SVN_REVISION "windows"
+#else
+# include "svn_revision/svn_revision.h"
+#endif
+
+//---------------------------------------------------------------------------
+const char * const Piklab::URLS[Nb_UrlTypes] = {
+ "http://piklab.sourceforge.net",
+ "http://piklab.sourceforge.net/wiki/index.php/FAQ",
+ "http://sourceforge.net/tracker/?func=add&group_id=138852&atid=743140"
+};
+
+//-----------------------------------------------------------------------------
+Piklab::OptionList::OptionList(const KCmdLineOptions *options)
+ : _options(0)
+{
+ for (uint i=0; options[i].name; i++) append(options[i]);
+}
+
+const KCmdLineOptions *Piklab::OptionList::ptr() const
+{
+ delete[] _options;
+ _options = new KCmdLineOptions[count()+1];
+ for (uint i=0; i<uint(count()); i++) {
+ _options[i] = *at(i);
+ Q_ASSERT( _options[i].name );
+ }
+ _options[count()].name = 0;
+ return _options;
+}
+
+//-----------------------------------------------------------------------------
+void Piklab::init(KAboutData *about, int argc, char **argv, bool gui, const KCmdLineOptions *options)
+{
+ Q_ASSERT(about);
+#if defined(NO_KDE)
+# if defined(Q_OS_WIN)
+ printf("%s \"win32\": version %s\n", about->appName(), VERSION);
+# else
+ printf("%s \"qt-only\": version %s (rev. %s)\n", about->appName(), VERSION, SVN_REVISION);
+# endif
+ Q_UNUSED(gui);
+ Q_ASSERT( !gui );
+#else
+ printf("%s: version %s (rev. %s)\n", about->appName(), VERSION, SVN_REVISION);
+ if ( !gui ) KApplication::disableAutoDcopRegistration();
+#endif
+ KCmdLineArgs::init(argc, argv, about);
+ KCmdLineArgs::addCmdLineOptions(options);
+#if defined(NO_KDE)
+# if QT_VERSION<0x040000
+ (void)new QApplication(argc, argv, QApplication::Tty);
+# else
+ (void)new QCoreApplication(argc, argv);
+# endif
+#else
+ (void)new KApplication(gui, gui);
+#endif
+}
+
+//---------------------------------------------------------------------------
+Piklab::AboutData::AboutData(const char *executable, const char *name,
+ const char *description)
+ : KAboutData(executable, name, VERSION, description, KAboutData::License_GPL,
+ "(c) 2005-2007 Nicolas Hadacek\n(c) 2002-2005 Alain Gibaud\n(c) 2003-2004 Stephen Landamore\n(c) 2005 Lorenz Möenlechner and Matthias Kranz\n(c) 2001-2005 Craig Franklin",
+ 0, URLS[Homepage], URLS[BugReport])
+{
+ addAuthor("Nicolas Hadacek", I18N_NOOP("Author and maintainer."), "hadacek@kde.org");
+ addAuthor("Alain Gibaud", I18N_NOOP("Original author of PiKdev."), "alain.gibaud@free.fr");
+ addAuthor("Stephen Landamore", I18N_NOOP("LPLAB author (original microchip programmer support)."), "webmaster@landamore.com");
+ addAuthor("Craig Franklin", I18N_NOOP("Author of gputils"), "craigfranklin@users.sourceforge.net");
+ addAuthor("Sébastien Laoût", I18N_NOOP("Author of likeback"), "slaout@linux62.org");
+
+ addCredit("Brian C. Lane", I18N_NOOP("Original code for direct programming."), 0);
+ addCredit("Manwlis \"Manos\" Giannos", I18N_NOOP("Direct programming for PIC18F devices."), "mgiannos2000@yahoo.gr");
+ addCredit("Sean A. Walberg", I18N_NOOP("Direct programming for 16F676/630."), "sean@ertw.com");
+ addCredit("Mirko Panciri", I18N_NOOP("Support for direct programmers with bidirectionnal buffers."), "mirko.panciri@adept.it");
+ addCredit("Keith Baker", I18N_NOOP("Direct programming for 16F73/74/76/77."), "susyzygy@pubnix.org" );
+ addCredit("Lorenz Möenlechner and Matthias Kranz", I18N_NOOP("USB support for ICD2 programmer."), "icd2linux@hcilab.org");
+ addCredit("Xiaofan Chen", I18N_NOOP("Test of PICkit2 and ICD2 programmer."), "xiaofanc@gmail.com");
+ addCredit("Homer Reid", I18N_NOOP("Direct programming for dsPICs is inspired from his program \"dspicprg\"."), "homer@homerreid.com");
+ addCredit("Frank Damgaard", I18N_NOOP("Direct programming for 24C EEPROM is inspired from his program \"prog84\"."), "frda@post3.tele.dk");
+}
diff --git a/src/common/global/about.h b/src/common/global/about.h
new file mode 100644
index 0000000..e20ee46
--- /dev/null
+++ b/src/common/global/about.h
@@ -0,0 +1,43 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#ifndef ABOUT_H
+#define ABOUT_H
+
+#include "global.h"
+
+namespace Piklab
+{
+//-----------------------------------------------------------------------------
+class OptionList : public QValueList<KCmdLineOptions>
+{
+public:
+ OptionList() : _options(0) {}
+ OptionList(const KCmdLineOptions *options);
+ virtual ~OptionList() { delete[] _options; }
+ const KCmdLineOptions *ptr() const;
+
+private:
+ mutable KCmdLineOptions *_options;
+};
+
+//---------------------------------------------------------------------------
+enum UrlType { Homepage = 0, Support, BugReport, Nb_UrlTypes };
+extern const char * const URLS[Nb_UrlTypes];
+extern void init(KAboutData *about, int argc, char **argv, bool gui, const KCmdLineOptions *options);
+
+//---------------------------------------------------------------------------
+class AboutData : public KAboutData
+{
+public:
+ AboutData(const char *executable, const char *name, const char *description);
+};
+
+} // namespace
+
+#endif
diff --git a/src/common/global/generic_config.cpp b/src/common/global/generic_config.cpp
new file mode 100644
index 0000000..841233b
--- /dev/null
+++ b/src/common/global/generic_config.cpp
@@ -0,0 +1,241 @@
+/***************************************************************************
+ * Copyright (C) 2006 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#include "generic_config.h"
+
+#include "global.h"
+
+#if defined(NO_KDE)
+# include <qsettings.h>
+class GenericConfigPrivate
+{
+public:
+ GenericConfigPrivate(const QString &group) { _settings.beginGroup("/piklab/" + group); }
+ QSettings _settings;
+};
+#else
+# include <kapplication.h>
+# include <kconfig.h>
+class GenericConfigPrivate
+{
+public:
+ GenericConfigPrivate(const QString &group) : _group(group) {}
+ ~GenericConfigPrivate() { kapp->config()->sync(); }
+ KConfig &config() {
+ KConfig *conf = kapp->config();
+ conf->setGroup(_group);
+ return *conf;
+ }
+
+private:
+ QString _group;
+};
+#endif
+
+GenericConfig::GenericConfig(const QString &group)
+ : _group(group)
+{
+ _d = new GenericConfigPrivate(group);
+}
+
+GenericConfig::~GenericConfig()
+{
+ delete _d;
+}
+
+void GenericConfig::rollback()
+{
+#if defined(NO_KDE)
+ qWarning("Config rollback not supported");
+#else
+ _d->config().rollback();
+#endif
+}
+
+QString GenericConfig::readEntry(const QString &key, const QString &def) const
+{
+#if defined(NO_KDE)
+# if QT_VERSION<0x040000
+ return _d->_settings.readEntry(key, def);
+# else
+ return _d->_settings.value(key, def).toString();
+# endif
+#else
+ return _d->config().readEntry(key, def);
+#endif
+}
+void GenericConfig::writeEntry(const QString &key, const QString &value)
+{
+#if defined(NO_KDE)
+# if QT_VERSION<0x040000
+ _d->_settings.writeEntry(key, value);
+# else
+ _d->_settings.setValue(key, value);
+# endif
+#else
+ _d->config().writeEntry(key, value);
+#endif
+}
+
+QStringList GenericConfig::readListEntry(const QString &key, const QStringList &defaultValues) const
+{
+#if defined(NO_KDE)
+# if QT_VERSION<0x040000
+ if ( _d->_settings.readEntry(key).isNull() ) return defaultValues;
+ return _d->_settings.readListEntry(key);
+# else
+ return _d->_settings.value(key, defaultValues).toStringList();
+# endif
+#else
+ if ( !_d->config().hasKey(key) ) return defaultValues;
+ return _d->config().readListEntry(key);
+#endif
+}
+void GenericConfig::writeEntry(const QString &key, const QStringList &value)
+{
+#if defined(NO_KDE)
+# if QT_VERSION<0x040000
+ _d->_settings.writeEntry(key, value);
+# else
+ _d->_settings.setValue(key, value);
+# endif
+#else
+ _d->config().writeEntry(key, value);
+#endif
+}
+
+QValueList<int> GenericConfig::readIntListEntry(const QString &key) const
+{
+#if defined(NO_KDE)
+ QValueList<int> ilist;
+ QStringList list = readListEntry(key, QStringList());
+ QStringList::const_iterator it;
+ for (it=list.begin(); it!=list.end(); ++it) {
+ bool ok;
+ int v = (*it).toInt(&ok);
+ if ( !ok ) return ilist;
+ ilist.append(v);
+ }
+ return ilist;
+#else
+ return _d->config().readIntListEntry(key);
+#endif
+}
+void GenericConfig::writeEntry(const QString &key, const QValueList<int> &value)
+{
+#if defined(NO_KDE)
+ QStringList list;
+ QValueList<int>::const_iterator it;
+ for (it=value.begin(); it!=value.end(); ++it) list.append(QString::number(*it));
+ writeEntry(key, list);
+#else
+ _d->config().writeEntry(key, value);
+#endif
+}
+
+QSize GenericConfig::readSizeEntry(const QString &key, const QSize *def) const
+{
+#if defined(NO_KDE)
+ QValueList<int> list = readIntListEntry(key);
+ if ( list.count()!=2 ) return *def;
+ return QSize(list[0], list[1]);
+#else
+ return _d->config().readSizeEntry(key, def);
+#endif
+}
+void GenericConfig::writeEntry(const QString &key, const QSize &value)
+{
+#if defined(NO_KDE)
+ QValueList<int> ilist;
+ ilist.append(value.width());
+ ilist.append(value.height());
+ writeEntry(key, ilist);
+#else
+ _d->config().writeEntry(key, value);
+#endif
+}
+
+bool GenericConfig::readBoolEntry(const QString &key, bool def) const
+{
+#if defined(NO_KDE)
+# if QT_VERSION<0x040000
+ return _d->_settings.readBoolEntry(key, def);
+# else
+ return _d->_settings.value(key, def).toBool();
+# endif
+#else
+ return _d->config().readBoolEntry(key, def);
+#endif
+}
+void GenericConfig::writeEntry(const QString &key, bool value)
+{
+#if defined(NO_KDE)
+# if QT_VERSION<0x040000
+ _d->_settings.writeEntry(key, value);
+# else
+ _d->_settings.setValue(key, value);
+# endif
+#else
+ _d->config().writeEntry(key, value);
+#endif
+}
+
+int GenericConfig::readIntEntry(const QString &key, int def) const
+{
+#if defined(NO_KDE)
+# if QT_VERSION<0x040000
+ return _d->_settings.readNumEntry(key, def);
+# else
+ return _d->_settings.value(key, def).toInt();
+# endif
+#else
+ return _d->config().readNumEntry(key, def);
+#endif
+}
+void GenericConfig::writeEntry(const QString &key, int value)
+{
+#if defined(NO_KDE)
+# if QT_VERSION<0x040000
+ _d->_settings.writeEntry(key, value);
+# else
+ _d->_settings.setValue(key, value);
+# endif
+#else
+ _d->config().writeEntry(key, value);
+#endif
+}
+
+void GenericConfig::deleteGroup(const QString &group)
+{
+#if defined(NO_KDE)
+ Q_UNUSED(group);
+ // #### cannot do that...
+#else
+ kapp->config()->deleteGroup(group);
+#endif
+}
+
+QVariant GenericConfig::readVariantEntry(const QString &key, const QVariant &defValue) const
+{
+ switch (defValue.type()) {
+ case QVariant::Bool: return QVariant(readBoolEntry(key, defValue.toBool()), 0);
+ case QVariant::UInt: return readUIntEntry(key, defValue.toUInt());
+ default: break;
+ }
+ Q_ASSERT(false);
+ return QVariant();
+}
+
+void GenericConfig::writeEntry(const QString &key, const QVariant &v)
+{
+ switch (v.type()) {
+ case QVariant::Bool: writeEntry(key, v.toBool()); break;
+ case QVariant::UInt: writeEntry(key, v.toUInt()); break;
+ default: Q_ASSERT(false); break;
+ }
+}
diff --git a/src/common/global/generic_config.h b/src/common/global/generic_config.h
new file mode 100644
index 0000000..70dfeaa
--- /dev/null
+++ b/src/common/global/generic_config.h
@@ -0,0 +1,84 @@
+/***************************************************************************
+ * Copyright (C) 2006 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#ifndef GENERIC_CONFIG_H
+#define GENERIC_CONFIG_H
+
+#include <qvariant.h>
+#include <qsize.h>
+
+#include "global.h"
+#include "common/common/misc.h"
+
+class GenericConfigPrivate;
+
+class GenericConfig
+{
+public:
+ GenericConfig(const QString &group);
+ ~GenericConfig();
+ QString group() const { return _group; }
+ void rollback();
+
+ QString readEntry(const QString &key, const QString &def = QString::null) const;
+ void writeEntry(const QString &key, const QString &value);
+ void writeEntry(const QString &key, const QCString &value) { writeEntry(key, QString(value)); }
+ void writeEntry(const QString &key, const char *value) { writeEntry(key, QString(value)); }
+ QStringList readListEntry(const QString &key, const QStringList &defaultValues) const;
+ void writeEntry(const QString &key, const QStringList &value);
+ QValueList<int> readIntListEntry(const QString &key) const;
+ void writeEntry(const QString &key, const QValueList<int> &value);
+ QSize readSizeEntry(const QString &key, const QSize *def = 0) const;
+ void writeEntry(const QString &key, const QSize &value);
+ bool readBoolEntry(const QString &key, bool def) const;
+ void writeEntry(const QString &key, bool value);
+ int readIntEntry(const QString &key, int def = 0) const;
+ void writeEntry(const QString &key, int value);
+ uint readUIntEntry(const QString &key, uint def = 0) const { return qMax(0, readIntEntry(key, def)); }
+ void writeEntry(const QString &key, uint value) { writeEntry(key, int(value)); }
+ template <typename Enum>
+ Enum readEnumEntry(const QString &key, Enum def = Enum::Nb_Types) const { return Enum::fromKey(readEntry(key, def.key())); }
+ template <typename Enum>
+ void writeEnumEntry(const QString &key, Enum v) { writeEntry(key, v.key()); }
+ QVariant readVariantEntry(const QString &key, const QVariant &defValue) const;
+ void writeEntry(const QString &key, const QVariant &value);
+
+ static void deleteGroup(const QString &group);
+
+ struct ItemData {
+ const char *key, *label;
+ QVariant defValue;
+ };
+ template <typename Type>
+ QVariant readVariantEntry(Type type) const { return readVariantEntry(type.data().key, type.data().defValue); }
+ template <typename Type>
+ void writeVariantEntry(Type type, const QVariant &value) {
+ Q_ASSERT( value.type()==type.data().defValue.type() );
+ writeEntry(type.data().key, value);
+ }
+
+private:
+ QString _group;
+ GenericConfigPrivate *_d;
+};
+
+#define BEGIN_DECLARE_CONFIG(Type) \
+ BEGIN_DECLARE_ENUM(Type)
+
+#define END_DECLARE_CONFIG(Type, group) \
+ END_DECLARE_ENUM(Type, GenericConfig::ItemData) \
+ inline QVariant readConfigEntry(Type type) { \
+ GenericConfig config(group); \
+ return config.readVariantEntry<Type>(type); \
+ } \
+ inline void writeConfigEntry(Type type, const QVariant &v) { \
+ GenericConfig config(group); \
+ config.writeVariantEntry<Type>(type, v); \
+ }
+
+#endif
diff --git a/src/common/global/global.h b/src/common/global/global.h
new file mode 100644
index 0000000..72dab0e
--- /dev/null
+++ b/src/common/global/global.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * Copyright (C) 2006 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#ifndef GLOBAL_H
+#define GLOBAL_H
+
+#include <qglobal.h>
+
+#if QT_VERSION<0x040000
+# include <qapplication.h>
+# include <qvaluelist.h>
+# include <qvaluevector.h>
+# include <qmemarray.h>
+# include "common/common/qflags.h"
+# define qMax QMAX
+# define qMin QMIN
+# include <qurl.h>
+# define Q3Url QUrl
+# include <qguardedptr.h>
+#else
+# include <qcoreapplication.h>
+# include <Qt3Support/Q3ValueList>
+# define QValueList Q3ValueList
+# include <Qt3Support/Q3ValueVector>
+# define QValueVector Q3ValueVector
+# include <Qt3Support/Q3MemArray>
+# define QMemArray Q3MemArray
+# define qHeapSort qSort
+# include <Qt3Support/Q3Url>
+# include <Qt3Support/Q3MimeSourceFactory>
+# define QMimeSourceFactory Q3MimeSourceFactory
+# include <qpointer.h>
+# define QGuardedPtr QPointer
+#endif
+
+#if defined(NO_KDE)
+# include "qt_config.h"
+# include "common/nokde/nokde_kurl.h"
+# include "common/nokde/nokde_klocale.h"
+# include "common/nokde/nokde_kaboutdata.h"
+# include "common/nokde/nokde_kcmdlineargs.h"
+#else
+# include "config.h"
+# include <kapplication.h>
+# include <klocale.h>
+# include <kaboutdata.h>
+# include <kcmdlineargs.h>
+# include <ktempfile.h>
+# include <kconfigbackend.h>
+#endif
+
+#if defined(Q_OS_WIN)
+# include <windows.h>
+#endif
+
+#endif
diff --git a/src/common/global/global.pro b/src/common/global/global.pro
new file mode 100644
index 0000000..3756177
--- /dev/null
+++ b/src/common/global/global.pro
@@ -0,0 +1,8 @@
+STOPDIR = ../../..
+include($${STOPDIR}/lib.pro)
+
+TARGET = global
+HEADERS += about.h generic_config.h log.h process.h purl.h pfile.h progress_monitor.h
+SOURCES += about.cpp generic_config.cpp log.cpp process.cpp purl.cpp pfile.cpp progress_monitor.cpp
+
+unix:system(cd svn_revision && sh svn_revision.sh)
diff --git a/src/common/global/log.cpp b/src/common/global/log.cpp
new file mode 100644
index 0000000..cf85303
--- /dev/null
+++ b/src/common/global/log.cpp
@@ -0,0 +1,154 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#include "log.h"
+
+#include <qeventloop.h>
+#include "global.h"
+
+//-----------------------------------------------------------------------------
+const Log::LineType::Data Log::LineType::DATA[Nb_Types] = {
+ { 0, 0, "red", false }, // error
+ { 0, 0, "red", false }, // soft error
+ { 0, 0, "orange", false }, // warning
+ { 0, 0, "black", false }, // normal
+ { 0, 0, "blue", false }, // info
+ { 0, 0, "black", true }, // command
+};
+
+const Log::DebugLevel::Data Log::DebugLevel::DATA[Nb_Types] = {
+ { "quiet", I18N_NOOP("No debug message"), 0, false },
+ { "debug", I18N_NOOP("Normal debug messages"), "darkGreen", false },
+ { "extra-debug", I18N_NOOP("Extra debug messages"), "darkGreen", false },
+ { "max-debug", I18N_NOOP("Max debug messages"), "darkGreen", false },
+ { "lowlevel-debug", I18N_NOOP("All debug messages"), "darkGreen", false }
+};
+
+//-----------------------------------------------------------------------------
+Log::View::View()
+{
+ setDebugLevel(DebugLevel::Normal);
+ FOR_EACH(LineType, type) _modes[type.type()] = Show;
+}
+
+void Log::View::setDebugLevel(DebugLevel level)
+{
+ _debugLevel = level;
+}
+
+void Log::View::log(LineType type, const QString &text, Action action)
+{
+ if ( _modes[type.type()]==Show ) doLog(type, text, action);
+}
+
+void Log::View::log(DebugLevel level, const QString &text, Action action)
+{
+ Q_ASSERT( level!=DebugLevel::Quiet );
+ updateDebugLevel();
+ if ( level<=_debugLevel ) doLog(level, text, action);
+}
+
+void Log::View::logUserAbort()
+{
+ doLog(LineType::SoftError, i18n("Operation aborted by user."), Immediate);
+}
+
+//-----------------------------------------------------------------------------
+void Log::StringView::sorry(const QString &message, const QString &details)
+{
+ if ( details.isEmpty() ) _s += message;
+ else _s += message + ": " + details;
+}
+
+bool Log::StringView::askContinue(const QString &message)
+{
+ log(LineType::Warning, message, Immediate);
+ return false; // always fail
+}
+
+//-----------------------------------------------------------------------------
+Log::Base::Base(Base *parent)
+ : _parent(0), _data(0)
+{
+ setParent(parent);
+}
+
+void Log::Base::setParent(Base *parent)
+{
+ delete _data;
+ _parent = parent;
+ _data = (parent ? 0 : new LogData);
+}
+
+Log::Base::~Base()
+{
+ delete _data;
+}
+
+void Log::Base::setView(View *view)
+{
+ Q_ASSERT(_data);
+ _data->view = view;
+}
+
+void Log::Base::logUserAbort()
+{
+ if ( view() ) view()->logUserAbort();
+}
+
+void Log::Base::log(LineType type, const QString &message, Action action)
+{
+ if ( type==LineType::Error ) setError(message);
+ if ( view() ) view()->log(type, message, action);
+}
+
+void Log::Base::log(DebugLevel level, const QString &message, Action action)
+{
+ if ( view() ) view()->log(level, message, action);
+}
+
+void Log::Base::appendToLastLine(const QString &text)
+{
+ if ( view() ) view()->appendToLastLine(text);
+}
+
+void Log::Base::sorry(const QString &message, const QString &details)
+{
+ if ( view() ) view()->sorry(message, details);
+}
+
+bool Log::Base::askContinue(const QString &message)
+{
+ if ( view()==0 ) return false;
+ return view()->askContinue(message);
+}
+
+void Log::Base::clear()
+{
+ resetError();
+ if ( view() ) view()->clear();
+}
+
+//-----------------------------------------------------------------------------
+QString Log::KeyList::text() const
+{
+ QString text;
+ if ( !_title.isEmpty() ) text += _title + "\n";
+ uint nb = 0;
+ for (uint i=0; i<uint(_keys.count()); i++) nb = qMax(nb, uint(_keys[i].length()));
+ for (uint i=0; i<uint(_keys.count()); i++) text += " " + _keys[i].leftJustify(nb+2) + _labels[i] + "\n";
+ return text;
+}
+
+void Log::KeyList::display(Generic &log) const
+{
+ if ( !_title.isEmpty() ) log.log(Log::LineType::Normal, _title);
+ uint nb = 0;
+ for (uint i=0; i<uint(_keys.count()); i++) nb = qMax(nb, uint(_keys[i].length()));
+ for (uint i=0; i<uint(_keys.count()); i++) log.log(Log::LineType::Normal, " " + _keys[i].leftJustify(nb+2) + _labels[i]);
+}
diff --git a/src/common/global/log.h b/src/common/global/log.h
new file mode 100644
index 0000000..7383d57
--- /dev/null
+++ b/src/common/global/log.h
@@ -0,0 +1,134 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#ifndef LOG_H
+#define LOG_H
+
+#include <qstringlist.h>
+
+#include "common/common/key_enum.h"
+
+namespace Log
+{
+ // immediat visibily by calling processEvent... BEWARE of side effects
+ enum Action { Immediate, Delayed };
+ enum ShowMode { DontShow, Show };
+ struct LogData {
+ const char *key, *label, *color;
+ bool bold;
+ };
+ BEGIN_DECLARE_ENUM(DebugLevel)
+ Quiet = 0, Normal, Extra, Max, LowLevel
+ END_DECLARE_ENUM(DebugLevel, LogData)
+ BEGIN_DECLARE_ENUM(LineType)
+ Error = 0, SoftError, Warning, Normal, Information, Command
+ END_DECLARE_ENUM(LineType, LogData)
+
+//-----------------------------------------------------------------------------
+class Generic
+{
+public:
+ virtual ~Generic() {}
+ virtual void log(LineType type, const QString &text, Action action = Immediate) = 0;
+ virtual void log(DebugLevel level, const QString &text, Action action = Immediate) = 0;
+ virtual void appendToLastLine(const QString &text) = 0;
+ virtual void sorry(const QString &message, const QString &details) = 0;
+ virtual bool askContinue(const QString &message) = 0;
+ virtual void clear() = 0;
+ virtual void logUserAbort() = 0;
+};
+
+class View : public Generic
+{
+public:
+ View();
+ ShowMode showMode(LineType type) const { return _modes[type.type()]; }
+ void setShowMode(LineType type, ShowMode mode) { _modes[type.type()] = mode; }
+ void setDebugLevel(DebugLevel level);
+ virtual void log(LineType type, const QString &text, Action action = Immediate);
+ virtual void log(DebugLevel level, const QString &text, Action action = Immediate);
+ virtual void logUserAbort();
+
+protected:
+ ShowMode _modes[LineType::Nb_Types];
+ DebugLevel _debugLevel;
+
+ virtual void updateDebugLevel() {}
+ virtual void doLog(LineType type, const QString &text, Action action) = 0;
+ virtual void doLog(DebugLevel level, const QString &text, Action action) = 0;
+};
+
+//-----------------------------------------------------------------------------
+class StringView : public View
+{
+public:
+ StringView() {}
+ QString string() const { return _s; }
+ virtual void appendToLastLine(const QString &text) { _s += text; }
+ virtual void clear() { _s = QString::null; }
+ virtual void sorry(const QString &message, const QString &details);
+ virtual bool askContinue(const QString &message);
+
+private:
+ QString _s;
+
+ virtual void doLog(LineType, const QString &text, Action) { _s += text + "\n"; }
+ virtual void doLog(DebugLevel, const QString &text, Action) { _s += text + "\n"; }
+};
+
+//-----------------------------------------------------------------------------
+class Base : public Generic
+{
+public:
+ Base(Base *parent = 0);
+ virtual ~Base();
+ void setParent(Base *parent);
+ void setView(View *view);
+ View *view() { return logData()->view; }
+
+ virtual void log(LineType type, const QString &message, Action action = Immediate);
+ virtual void log(DebugLevel level, const QString &message, Action action = Immediate);
+ virtual void appendToLastLine(const QString &text);
+ void setError(const QString &error) { logData()->error = error; }
+ virtual bool hasError() const { return !logData()->error.isNull(); }
+ virtual QString error() const { return logData()->error; }
+ virtual void resetError() { logData()->error = QString::null; }
+ virtual void sorry(const QString &message, const QString &details = QString::null);
+ virtual bool askContinue(const QString &message);
+ virtual void clear();
+ void logUserAbort();
+
+protected:
+ Base *_parent;
+ class LogData {
+ public:
+ LogData() : view(0) {}
+ QString error;
+ View *view;
+ };
+ LogData *_data;
+ LogData *logData() { return _parent ? _parent->logData() : _data; }
+ const LogData *logData() const { return _parent ? _parent->logData() : _data; }
+};
+
+class KeyList {
+public:
+ KeyList(const QString &title = QString::null) : _title(title) {}
+ void setTitle(const QString &title) { _title = title; }
+ void append(const QString &key, const QString &label) { _keys += key; _labels += label; }
+ QString text() const;
+ void display(Generic &log) const;
+
+private:
+ QString _title;
+ QStringList _keys, _labels;
+};
+
+} // namespace
+
+#endif
diff --git a/src/common/global/pfile.cpp b/src/common/global/pfile.cpp
new file mode 100644
index 0000000..71cee16
--- /dev/null
+++ b/src/common/global/pfile.cpp
@@ -0,0 +1,89 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#include "pfile.h"
+
+#include <qfile.h>
+
+//-----------------------------------------------------------------------------
+PURL::FileBase::FileBase(Log::Generic &log, const QString &extension)
+ : _tmp(0), _file(0), _stream(0), _extension(extension), _log(log)
+{}
+
+PURL::FileBase::~FileBase()
+{
+ delete _stream;
+ delete _file;
+ delete _tmp;
+}
+
+const QFile *PURL::FileBase::qfile() const
+{
+ return (_tmp ? _tmp->file() : _file);
+}
+
+QFile *PURL::FileBase::qfile()
+{
+ return (_tmp ? _tmp->file() : _file);
+}
+
+void PURL::FileBase::flush()
+{
+ if ( qfile() ) qfile()->flush();
+}
+
+QTextStream &PURL::FileBase::stream()
+{
+ if ( _stream==0 ) _stream = new QTextStream(qfile());
+ return *_stream;
+}
+
+bool PURL::FileBase::hasError() const
+{
+ if ( qfile()==0 || !_error.isEmpty() ) return true;
+ return ( uint(qfile()->status())!=IO_Ok );
+}
+
+QString PURL::FileBase::errorString() const
+{
+ if ( _error.isEmpty() ) {
+ if ( qfile()==0 ) return i18n("File not open.");
+ else return qfile()->errorString();
+ }
+ return _error;
+}
+
+QStringList PURL::FileBase::readLines()
+{
+ QStringList lines;
+ for (;;) {
+ QString s = stream().readLine();
+ if ( s.isNull() ) break;
+ lines.append(s);
+ }
+ return lines;
+}
+
+QByteArray PURL::FileBase::readAll()
+{
+ if ( qfile() ) return qfile()->readAll();
+ return QByteArray();
+}
+
+//-----------------------------------------------------------------------------
+PURL::File::File(const Url &url, Log::Generic &log)
+ : FileBase(log, QString::null), _url(url)
+{
+ _file = new QFile;
+}
+
+void PURL::File::setUrl(const Url &url)
+{
+ close();
+ _url = url;
+}
diff --git a/src/common/global/pfile.h b/src/common/global/pfile.h
new file mode 100644
index 0000000..d0955e7
--- /dev/null
+++ b/src/common/global/pfile.h
@@ -0,0 +1,66 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#ifndef PFILE_H
+#define PFILE_H
+
+#include <qtextstream.h>
+#include "purl.h"
+
+namespace PURL
+{
+//-----------------------------------------------------------------------------
+class FileBase
+{
+public:
+ FileBase(Log::Generic &log, const QString &extension);
+ ~FileBase();
+ QFile *qfile();
+ const QFile *qfile() const;
+ QTextStream &stream();
+ QString readText() { return stream().read(); }
+ QString readLine() { return stream().readLine(); }
+ QStringList readLines();
+ QByteArray readAll();
+ void appendText(const QString &text) { stream() << text; }
+ void flush();
+ bool hasError() const;
+ QString errorString() const;
+
+protected:
+ KTempFile *_tmp;
+ QFile *_file;
+ QTextStream *_stream;
+ QString _error, _extension;
+ Log::Generic &_log;
+
+private: // disable copy constructor and operator =
+ FileBase(const FileBase &base);
+ FileBase &operator =(const FileBase &base);
+};
+
+//-----------------------------------------------------------------------------
+class File : public FileBase
+{
+public:
+ File(const Url &url, Log::Generic &log);
+ ~File() { close(); }
+ void setUrl(const Url &url); // close file too
+ Url url() const { return _url; }
+ bool openForWrite();
+ bool openForRead();
+ bool close();
+ bool remove();
+
+private:
+ Url _url;
+};
+
+} // namespace
+
+#endif
diff --git a/src/common/global/process.cpp b/src/common/global/process.cpp
new file mode 100644
index 0000000..7659eea
--- /dev/null
+++ b/src/common/global/process.cpp
@@ -0,0 +1,193 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#include "process.h"
+
+#include <qdatetime.h>
+
+#if defined(NO_KDE)
+# include "common/nokde/nokde_kprocess.h"
+#else
+# include <kprocess.h>
+#endif
+#include "purl.h"
+#include "common/common/synchronous.h"
+
+//----------------------------------------------------------------------------
+Process::State Process::runSynchronously(Base &process, RunActions actions, uint timeout)
+{
+ Synchronous sync(timeout);
+ QObject::connect(&process, SIGNAL(done(int)), &sync, SLOT(done()));
+ QObject::connect(&process, SIGNAL(requestSynchronousStop()), &sync, SLOT(done()));
+ if ( (actions & Start) && !process.start(0) ) return process.state();
+ Q_ASSERT( process.isRunning() );
+ if ( !sync.enterLoop() ) process.timeoutSlot();
+ return process.state();
+}
+
+//----------------------------------------------------------------------------
+Process::Base::Base(QObject *parent, const char *name)
+ : QObject(parent, name), _state(Stopped)
+{
+ _process = new KProcess(this);
+ connect(_process, SIGNAL(processExited(KProcess *)), SLOT(exited()));
+ connect(_process, SIGNAL(receivedStdout(KProcess *, char *, int)), SLOT(receivedStdout(KProcess*, char *, int)));
+ connect(_process, SIGNAL(receivedStderr(KProcess *, char *, int)), SLOT(receivedStderr(KProcess*, char *, int)));
+ _timer = new QTimer(this);
+ connect(_timer, SIGNAL(timeout()), SLOT(timeoutSlot()));
+}
+
+Process::Base::~Base()
+{
+ _process->kill();
+}
+
+QStringList Process::Base::arguments() const
+{
+ if ( _process==0 ) return QStringList();
+#if defined(NO_KDE)
+ return _process->args();
+#else
+ QStringList list;
+ const QValueList<QCString> &args = _process->args();
+ for (uint i=0; i<args.count(); i++) list.append(args[i]);
+ return list;
+#endif
+}
+
+void Process::Base::setup(const QString &executable, const QStringList &options, bool withWine)
+{
+ _state = Stopped;
+ _timer->stop();
+ _process->clearArguments();
+ if (withWine) {
+ _process->setEnvironment("WINEDEBUG", "-all");
+ *_process << QString("wine");
+ }
+ *_process << executable;
+ *_process << options;
+}
+
+bool Process::Base::start(uint timeout)
+{
+ _state = Stopped;
+ _timer->stop();
+ _stdout = QString::null;
+ _stderr = QString::null;
+#if defined(NO_KDE)
+ if ( !_process->start() ) {
+#else
+ if ( !_process->start(KProcess::NotifyOnExit, KProcess::All) ) {
+#endif
+ _state = StartFailed;
+ return false;
+ }
+ _state = Running;
+ if (timeout) _timer->start(timeout);
+ return true;
+}
+
+void Process::Base::timeoutSlot()
+{
+ _state = Timedout;
+ _process->kill();
+ emit timeout();
+}
+
+int Process::Base::exitCode() const
+{
+ return _process->exitStatus();
+}
+
+void Process::Base::exited()
+{
+ _state = Exited;
+ _timer->stop();
+ emit done(exitCode());
+}
+
+bool Process::Base::isRunning() const
+{
+ return _process->isRunning();
+}
+
+void Process::Base::writeToStdin(const QString &s)
+{
+ QCString cs = s.latin1();
+ _process->writeStdin(cs.data(), cs.length());
+}
+
+bool Process::Base::signal(int n)
+{
+ return _process->kill(n);
+}
+
+void Process::Base::setWorkingDirectory(const PURL::Directory &dir)
+{
+ _process->setWorkingDirectory(dir.path());
+}
+
+void Process::Base::setUseShell(bool useShell)
+{
+ _process->setUseShell(useShell);
+}
+
+bool Process::Base::isFilteredLine(const QString &line)
+{
+ // "wine" returns all those "libGL warning" that mess up the output...
+ return line.startsWith("libGL warning");
+}
+
+//----------------------------------------------------------------------------
+void Process::StringOutput::receivedStdout(KProcess*, char *data, int len)
+{
+ _stdout += QString::fromLatin1(data, len);
+ emit stdoutDataReceived();
+}
+
+void Process::StringOutput::receivedStderr(KProcess*, char *data, int len)
+{
+ _stderr += QString::fromLatin1(data, len);
+ emit stderrDataReceived();
+}
+
+//----------------------------------------------------------------------------
+void Process::LineBase::receivedStdout(KProcess*, char *data, int len)
+{
+ for (uint i=0; i<uint(len); i++) {
+ if ( data[i]=='\r' ) continue;
+ if ( data[i]=='\n' ) {
+ if ( !isFilteredLine(_stdout) ) addStdoutLine(_stdout);
+ _stdout = QString::null;
+ } else _stdout += QString::fromLatin1(data + i, 1);
+ }
+ if ( !_process->isRunning() && !isFilteredLine(_stdout) ) addStdoutLine(_stdout);
+ emit stdoutDataReceived();
+}
+
+void Process::LineBase::receivedStderr(KProcess*, char *data, int len)
+{
+ for (uint i=0; i<uint(len); i++) {
+ if ( data[i]=='\r' ) continue;
+ if ( data[i]=='\n' ) {
+ if ( !isFilteredLine(_stderr) ) addStderrLine(_stderr);
+ _stderr = QString::null;
+ } else _stderr += QString::fromLatin1(data + i, 1);
+ }
+ if ( !_process->isRunning() && !isFilteredLine(_stderr) ) addStderrLine(_stderr);
+ emit stderrDataReceived();
+}
+
+//----------------------------------------------------------------------------
+bool Process::LineOutput::start(uint timeout)
+{
+ _stdoutLines.clear();
+ _stderrLines.clear();
+ return Process::LineBase::start(timeout);
+}
+
diff --git a/src/common/global/process.h b/src/common/global/process.h
new file mode 100644
index 0000000..9c67149
--- /dev/null
+++ b/src/common/global/process.h
@@ -0,0 +1,138 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#ifndef PROCESS_H
+#define PROCESS_H
+
+#include <signal.h>
+#include <qstringlist.h>
+#include <qobject.h>
+#include <qtimer.h>
+class KProcess;
+
+#include "global.h"
+namespace PURL { class Directory; }
+
+namespace Process
+{
+enum State { Stopped, StartFailed, Running, Exited, Timedout };
+class Base;
+enum RunAction { NoRunAction = 0, Start = 1 };
+Q_DECLARE_FLAGS(RunActions, RunAction)
+Q_DECLARE_OPERATORS_FOR_FLAGS(RunActions)
+extern State runSynchronously(Base &process, RunActions actions, uint timeout); // in ms (0 == no timeout)
+
+//----------------------------------------------------------------------------
+class Base : public QObject
+{
+Q_OBJECT
+public:
+ Base(QObject *parent, const char *name);
+ virtual ~Base();
+ void setup(const QString &executable, const QStringList &options, bool withWine);
+ QStringList arguments() const;
+ void setWorkingDirectory(const PURL::Directory &dir);
+ void setUseShell(bool useShell);
+ virtual bool start(uint timeout); // in ms (0 == no timeout)
+ QString prettyCommand() const { return arguments().join(" "); }
+ void writeToStdin(const QString &s);
+ bool signal(int n);
+ bool isRunning() const;
+ State state() const { return _state; }
+ int exitCode() const;
+
+signals:
+ void requestSynchronousStop();
+ void done(int code);
+ void timeout();
+ void stdoutDataReceived();
+ void stderrDataReceived();
+
+protected slots:
+ void exited();
+ void timeoutSlot();
+ virtual void receivedStdout(KProcess*, char *buffer, int len) = 0;
+ virtual void receivedStderr(KProcess*, char *buffer, int len) = 0;
+
+ friend State runSynchronously(Base &, RunActions, uint);
+
+protected:
+ State _state;
+ KProcess *_process;
+ QTimer *_timer;
+ QString _stdout, _stderr;
+
+ static bool isFilteredLine(const QString &line);
+};
+
+//----------------------------------------------------------------------------
+class StringOutput : public Base
+{
+Q_OBJECT
+public:
+ StringOutput(QObject *parent = 0, const char *name = 0) : Base(parent, name) {}
+ QString sout() const { return _stdout; }
+ QString serr() const { return _stderr; }
+
+private slots:
+ virtual void receivedStdout(KProcess *, char *buffer, int len);
+ virtual void receivedStderr(KProcess *, char *buffer, int len);
+};
+
+//----------------------------------------------------------------------------
+class LineBase : public Base
+{
+Q_OBJECT
+public:
+ LineBase(QObject *parent = 0, const char *name = 0) : Base(parent, name) {}
+
+private slots:
+ virtual void receivedStdout(KProcess *, char *buffer, int len);
+ virtual void receivedStderr(KProcess *, char *buffer, int len);
+
+private:
+ virtual void addStdoutLine(const QString &line) = 0;
+ virtual void addStderrLine(const QString &line) = 0;
+};
+
+//----------------------------------------------------------------------------
+class LineOutput : public LineBase
+{
+Q_OBJECT
+public:
+ LineOutput(QObject *parent = 0, const char *name = 0) : LineBase(parent, name) {}
+ virtual bool start(uint timeout);
+ QStringList sout() const { return _stdoutLines; }
+ QStringList serr() const { return _stderrLines; }
+
+protected:
+ QStringList _stdoutLines, _stderrLines;
+
+ virtual void addStdoutLine(const QString &line) { _stdoutLines += line; }
+ virtual void addStderrLine(const QString &line) { _stderrLines += line; }
+};
+
+//----------------------------------------------------------------------------
+class LineSignal : public LineBase
+{
+Q_OBJECT
+public:
+ LineSignal(QObject *parent = 0, const char *name = 0) : LineBase(parent, name) {}
+
+signals:
+ void logStdoutLine(const QString &line);
+ void logStderrLine(const QString &line);
+
+private:
+ virtual void addStdoutLine(const QString &line) { emit logStdoutLine(line); }
+ virtual void addStderrLine(const QString &line) { emit logStderrLine(line); }
+};
+
+} // namespace
+
+#endif
diff --git a/src/common/global/progress_monitor.cpp b/src/common/global/progress_monitor.cpp
new file mode 100644
index 0000000..fcd0cec
--- /dev/null
+++ b/src/common/global/progress_monitor.cpp
@@ -0,0 +1,84 @@
+/***************************************************************************
+ * Copyright (C) 2007 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#include "progress_monitor.h"
+
+ProgressMonitor::ProgressMonitor(QObject* parent)
+ : QObject(parent, "progress_monitor")
+{
+ _current = _tasks.end();
+}
+
+void ProgressMonitor::clear()
+{
+ _tasks.clear();
+ _current = _tasks.end();
+ emit showProgress(false);
+}
+
+void ProgressMonitor::appendTask(const QString &label, uint nbSteps)
+{
+ Task task;
+ task.label = label;
+ task.nbSteps = nbSteps;
+ task.nbDoneSteps = 0;
+ _tasks.append(task);
+}
+
+void ProgressMonitor::insertTask(const QString &label, uint nbSteps)
+{
+ Task task;
+ task.label = label;
+ task.nbSteps = nbSteps;
+ task.nbDoneSteps = 0;
+ if ( _current==_tasks.end() ) _current = _tasks.prepend(task);
+ else _current = _tasks.insert(_current, task);
+ update();
+}
+
+uint ProgressMonitor::nbSteps() const
+{
+ uint nb = 0;
+ for (uint i=0; i<uint(_tasks.count()); i++) nb += _tasks[i].nbSteps;
+ return nb;
+}
+
+uint ProgressMonitor::nbDoneSteps() const
+{
+ uint nb = 0;
+ for (uint i=0; i<uint(_tasks.count()); i++) nb += _tasks[i].nbDoneSteps;
+ return nb;
+}
+
+void ProgressMonitor::update()
+{
+ QString label = (_current==_tasks.end() ? QString::null : (*_current).label);
+ emit setLabel(label);
+ emit setTotalProgress(nbSteps());
+ emit setProgress(nbDoneSteps());
+ emit showProgress(true);
+}
+
+void ProgressMonitor::startNextTask()
+{
+ if ( _current==_tasks.end() ) _current = _tasks.begin();
+ else ++_current;
+ Q_ASSERT( _current!=_tasks.end() ) ;
+ update();
+}
+
+void ProgressMonitor::addTaskProgress(uint nbSteps)
+{
+ Q_ASSERT( _current!=_tasks.end() ) ;
+ if ( _current==_tasks.end() ) return;
+ uint nb = (*_current).nbDoneSteps + nbSteps;
+ Q_ASSERT( nb<=(*_current).nbSteps );
+ if ( nb>(*_current).nbSteps ) qDebug("%s %i+%i > %i", (*_current).label.latin1(), (*_current).nbDoneSteps, nbSteps, (*_current).nbSteps);
+ (*_current).nbDoneSteps = QMIN(nb, (*_current).nbSteps);
+ update();
+}
diff --git a/src/common/global/progress_monitor.h b/src/common/global/progress_monitor.h
new file mode 100644
index 0000000..bb905f7
--- /dev/null
+++ b/src/common/global/progress_monitor.h
@@ -0,0 +1,46 @@
+/***************************************************************************
+ * Copyright (C) 2007 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#ifndef PROGRESS_MONITOR_H
+#define PROGRESS_MONITOR_H
+
+#include "global.h"
+
+class ProgressMonitor : public QObject
+{
+Q_OBJECT
+public:
+ ProgressMonitor(QObject *parent = 0);
+ void clear();
+ void appendTask(const QString &label, uint nbSteps);
+ void insertTask(const QString &label, uint nbSteps);
+ void startNextTask();
+ void addTaskProgress(uint nbSteps);
+ uint nbSteps() const;
+ uint nbDoneSteps() const;
+
+public slots:
+ void update();
+
+signals:
+ void showProgress(bool show);
+ void setLabel(const QString &label);
+ void setTotalProgress(uint nbSteps);
+ void setProgress(uint nbSteps);
+
+private:
+ class Task {
+ public:
+ QString label;
+ uint nbSteps, nbDoneSteps;
+ };
+ QValueList<Task> _tasks;
+ QValueList<Task>::iterator _current;
+};
+
+#endif
diff --git a/src/common/global/purl.cpp b/src/common/global/purl.cpp
new file mode 100644
index 0000000..6db2914
--- /dev/null
+++ b/src/common/global/purl.cpp
@@ -0,0 +1,428 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#include "purl.h"
+
+#include <qfileinfo.h>
+#include <qdatetime.h>
+#include <qdir.h>
+#include <qregexp.h>
+#include <qmap.h>
+#if QT_VERSION<0x040000
+# include <qnetwork.h>
+#endif
+
+#include "common/common/synchronous.h"
+#include "process.h"
+
+#if !defined(NO_KDE)
+# include <kio/netaccess.h>
+# include <kfileitem.h>
+# include <kconfigbackend.h>
+#endif
+
+//-----------------------------------------------------------------------------
+PURL::Http::Http(const QString &hostname)
+ : QHttp(hostname)
+{
+ connect(this, SIGNAL(responseHeaderReceived(const QHttpResponseHeader &)),
+ SLOT(responseHeaderReceivedSlot(const QHttpResponseHeader &)));
+}
+
+//-----------------------------------------------------------------------------
+class PURL::Private
+{
+public:
+ QString convertWindowsFilepath(const QString &filepath);
+
+private:
+ QMap<char, QString> _winDrives; // drive -> unix path
+ QMap<QString, QString> _winPaths; // windows path -> unix path
+
+ QString getWindowsDrivePath(char drive);
+ bool checkCachedPath(QString &filepath) const;
+ QString cachePath(const QString &origin, const QString &filepath);
+ QString convertWindowsShortFilepath(const QString &filepath);
+ QString findName(const QString &path, const QString &name);
+ static QString findName(const QString &filepath);
+};
+
+QString PURL::Private::getWindowsDrivePath(char drive)
+{
+#if defined(Q_OS_UNIX)
+ if ( !_winDrives.contains(drive) ) {
+ QStringList args;
+ args += "-u";
+ QString s;
+ s += drive;
+ args += s + ":\\";
+ ::Process::StringOutput process;
+ process.setup("winepath", args, false);
+ ::Process::State state = ::Process::runSynchronously(process, ::Process::Start, 3000);
+ if ( state!=::Process::Exited ) qWarning("Error running \"winepath\" with \"%s\" (%i)", args.join(" ").latin1(), state);
+ s = process.sout() + process.serr();
+ QDir dir(s.stripWhiteSpace());
+ _winDrives[drive] = dir.canonicalPath();
+ }
+ return _winDrives[drive];
+#else
+ return QString("%1:\\").arg(drive);
+#endif
+}
+
+bool PURL::Private::checkCachedPath(QString &filepath) const
+{
+ if ( !_winPaths.contains(filepath) ) return false;
+ filepath = _winPaths[filepath];
+ return true;
+}
+
+QString PURL::Private::cachePath(const QString &origin, const QString &filepath)
+{
+ _winPaths[origin] = filepath;
+ return filepath;
+}
+
+QString PURL::Private::convertWindowsFilepath(const QString &filepath)
+{
+ // appears to be an absolute windows path
+ if ( filepath[0]=='\\' ) {
+ QString tmp = filepath;
+ if ( checkCachedPath(tmp) ) return tmp;
+ return cachePath(filepath, convertWindowsShortFilepath(tmp.replace('\\', "/")));
+ }
+ // appears to be a windows path with a drive
+ if ( (filepath.length()>=2 && filepath[0].isLetter() && filepath[1]==':') ) {
+ QString tmp = filepath;
+ if ( checkCachedPath(tmp) ) return tmp;
+#if QT_VERSION<0x040000
+ tmp = getWindowsDrivePath(filepath[0]) + tmp.mid(2).replace('\\', "/");
+#else
+ tmp = getWindowsDrivePath(filepath[0].toLatin1()) + tmp.mid(2).replace('\\', "/");
+#endif
+ return cachePath(filepath, convertWindowsShortFilepath(tmp));
+ }
+ return filepath;
+}
+
+QString PURL::Private::findName(const QString &path, const QString &name)
+{
+ QString filepath = path + '/' + name;
+ if ( checkCachedPath(filepath) ) return filepath;
+ return cachePath(filepath, findName(filepath));
+}
+
+QString PURL::Private::findName(const QString &filepath)
+{
+ QFileInfo finfo(filepath);
+ if ( finfo.exists() || !finfo.dir().exists() ) return finfo.filePath();
+ QStringList list = finfo.dir().entryList(QDir::All, QDir::Name);
+ // find if name is just in a different case
+ for (uint j=0; j<uint(list.count()); j++) {
+ if ( list[j].lower()!=finfo.fileName().lower() ) continue;
+ return finfo.dirPath() + '/' + list[j];
+ }
+ // find if name is a shorted filename
+ QRegExp rexp("([^~]+)~(\\d+).*");
+ if ( !rexp.exactMatch(finfo.fileName()) ) return finfo.filePath();
+ QString start = rexp.cap(1).lower();
+ uint index = rexp.cap(2).toUInt();
+ uint k = 0;
+ for (uint j = 0; j<uint(list.count()); j++) {
+ if ( !list[j].lower().startsWith(start) ) continue;
+ k++;
+ if ( k==index ) return finfo.dirPath() + '/' + list[j];
+ }
+ return finfo.filePath();
+}
+
+QString PURL::Private::convertWindowsShortFilepath(const QString &filepath)
+{
+ // apparently "winepath" cannot do that for us and it is a real pain too...
+ // we assume filepath is an absolute unix path
+ // first see if we know the dirpath
+ QFileInfo finfo(filepath);
+ QString path = finfo.dirPath();
+ if ( checkCachedPath(path) ) return findName(path, finfo.fileName());
+
+ // otherwise go down the path
+ QStringList names = QStringList::split('/', filepath);
+ QString tmp;
+ for (uint i=0; i<uint(names.count()); i++)
+ tmp = findName(tmp, names[i]);
+ if ( filepath.endsWith("/") ) tmp += "/";
+ return tmp;
+}
+
+//-----------------------------------------------------------------------------
+PURL::Private *PURL::Base::_private = 0;
+
+PURL::Base::Base(const QString &filepath)
+ : _relative(true)
+{
+ if ( !filepath.isEmpty() ) {
+ if ( _private==0 ) _private = new Private;
+#if defined(Q_OS_UNIX)
+ QString tmp = _private->convertWindowsFilepath(filepath);
+#else
+ QString tmp = filepath;
+#endif
+ if ( tmp.startsWith("~") ) tmp = QDir::homeDirPath() + tmp.mid(1);
+ _relative = Q3Url::isRelativeUrl(tmp);
+#if defined(Q_OS_UNIX)
+ if ( !tmp.startsWith("/") ) tmp = '/' + tmp;
+#endif
+#if defined(NO_KDE)
+ _url.setPath(tmp);
+#else
+ _url = KURL::fromPathOrURL(tmp);
+#endif
+ _url.cleanPath();
+ }
+}
+
+PURL::Base::Base(const KURL &url)
+ : _relative(false), _url(url)
+{
+ _url.cleanPath();
+}
+
+bool PURL::Base::isLocal() const
+{
+ return ( _url.protocol().isEmpty() || _url.protocol()=="file" );
+}
+
+bool PURL::Base::operator ==(const Base &url) const
+{
+ if ( _url.isEmpty() ) return url._url.isEmpty();
+ return _url==url._url;
+}
+
+QString PURL::Base::path(SeparatorType type) const
+{
+#if defined(NO_KDE)
+ QString s = _url.dirPath();
+ if ( !s.isEmpty() && !s.endsWith("/") ) s += '/';
+#else
+ QString s = _url.directory(false, false);
+#endif
+ if ( type==WindowsSeparator ) {
+ for (uint i=0; i<uint(s.length()); i++)
+ if ( s[i]=='/' ) s[i] = '\\';
+ }
+ return s;
+}
+
+QString PURL::Base::unterminatedPath(SeparatorType type) const
+{
+#if defined(NO_KDE)
+ QString s = _url.dirPath();
+ if ( s.endsWith("/") ) s = s.mid(0, s.length()-1);
+#else
+ QString s = _url.directory(true, false);
+#endif
+ if ( type==WindowsSeparator ) {
+ for (uint i=0; i<uint(s.length()); i++)
+ if ( s[i]=='/' ) s[i] = '\\';
+ }
+ return s;
+}
+
+QString PURL::Base::pretty() const
+{
+#if defined(NO_KDE)
+ QString s = _url.toString();
+ if ( s.startsWith("://") ) return s.mid(3);
+ return s;
+#else
+ return _url.prettyURL(0, KURL::StripFileProtocol);
+#endif
+}
+
+PURL::Directory PURL::Base::directory() const
+{
+ return Directory(path());
+}
+
+bool PURL::Base::isInto(const Directory &dir) const
+{
+ return path().startsWith(dir.path());
+}
+
+bool PURL::Base::httpUrlExists(bool *ok) const
+{
+#if QT_VERSION<0x040000
+ qInitNetworkProtocols();
+#endif
+ if (ok) *ok = false;
+ Http http(_url.host());
+ Synchronous sync(500);
+ QObject::connect(&http, SIGNAL(done(bool)), &sync, SLOT(done()));
+ QFileInfo info(_url.fileName(false));
+ http.head(_url.path());
+ if ( !sync.enterLoop() ) return false; // timeout
+ if ( http.error()!=QHttp::NoError ) return false;
+ if (ok ) *ok = true;
+ return ( http._header.statusCode()==200 );
+}
+
+bool PURL::Base::exists(QDateTime *lastModified) const
+{
+ if ( isEmpty() ) return false;
+ if ( isLocal() ) {
+ QFileInfo fi(_url.path());
+ if (lastModified) *lastModified = fi.lastModified();
+ return fi.exists();
+ }
+ if ( _url.protocol()=="http" ) return httpUrlExists();
+#if !defined(NO_KDE)
+ if (lastModified) {
+ KIO::UDSEntry uds;
+ if ( !KIO::NetAccess::stat(_url, uds, qApp->mainWidget()) ) return false;
+ KFileItem item(uds, _url);
+ lastModified->setTime_t(item.time(KIO::UDS_MODIFICATION_TIME));
+ return true;
+ } else {
+ // assume file exists if ioslave cannot tell...
+ return KIO::NetAccess::exists(_url, true, qApp->mainWidget());
+ }
+#else
+ if (lastModified) lastModified->setTime_t(0);
+ // assume file exists
+ return true;
+#endif
+}
+
+//----------------------------------------------------------------------------
+PURL::Url PURL::Url::fromPathOrUrl(const QString &s)
+{
+ KURL kurl = KURL::fromPathOrURL(s);
+ if ( !kurl.protocol().isEmpty() && kurl.protocol()!="file" && kurl.protocol().length()!=1 ) return kurl;
+ return Url(s.startsWith("file://") ? s.mid(7) : s);
+}
+
+PURL::Url::Url(const Directory &dir, const QString &filename, FileType type)
+ : Base(dir.path() + '/' + addExtension(filename, type))
+{}
+
+PURL::Url::Url(const Directory &dir, const QString &filepath)
+ : Base(dir.path() + '/' + filepath)
+{}
+
+PURL::FileType PURL::Url::fileType() const
+{
+ QFileInfo info(filename());
+ FOR_EACH(FileType, type)
+ for (uint i=0; type.data().extensions[i]; i++)
+ if ( info.extension(false).lower()==type.data().extensions[i] ) return type;
+ return Unknown;
+}
+
+QString PURL::Url::basename() const
+{
+ QFileInfo info(_url.fileName(false));
+ return info.baseName(true);
+}
+
+QString PURL::Url::filename() const
+{
+ QFileInfo info(_url.fileName(false));
+ return info.fileName();
+}
+
+QString PURL::Url::filepath(SeparatorType type) const
+{
+ return path(type) + filename();
+}
+
+PURL::Url PURL::Url::toExtension(const QString &extension) const
+{
+ QFileInfo info(filename());
+ return Url(directory().path() + info.baseName(true) + '.' + extension);
+}
+
+PURL::Url PURL::Url::appendExtension(const QString &extension) const
+{
+ QFileInfo info(filename());
+ return Url(directory().path() + info.fileName() + '.' + extension);
+}
+
+QString PURL::Url::relativeTo(const Directory &dir, SeparatorType type) const
+{
+ QString s = filepath(type);
+ if ( !isInto(dir) ) return s;
+ return s.right(s.length() - dir.path(type).length());
+}
+
+PURL::Url PURL::Url::toAbsolute(const Directory &dir) const
+{
+ if ( isRelative() ) return Url(dir, filepath());
+ return *this;
+}
+
+bool PURL::findExistingUrl(Url &url)
+{
+ if ( url.exists() ) return true;
+ QFileInfo info(url.filename());
+ Url tmp = url.toExtension(info.extension(false).upper());
+ if ( !tmp.exists() ) {
+ tmp = url.toExtension(info.extension(false).lower());
+ if ( !tmp.exists() ) return false;
+ }
+ url = tmp;
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+#if !defined(NO_KDE)
+PURL::UrlList::UrlList(const KURL::List &list)
+{
+ KURL::List::const_iterator it;
+ for (it=list.begin(); it!=list.end(); ++it) append(*it);
+}
+#endif
+
+//-----------------------------------------------------------------------------
+PURL::Directory::Directory(const QString &path)
+ : Base(path.isEmpty() ? QString::null : path + '/')
+{}
+
+PURL::Directory PURL::Directory::up() const
+{
+ QDir dir(path());
+ dir.cdUp();
+ return PURL::Directory(dir.path());
+}
+
+PURL::Directory PURL::Directory::down(const QString &subPath) const
+{
+ Q_ASSERT( QDir::isRelativePath(subPath) );
+ QDir dir(path());
+ dir.cd(subPath);
+ return PURL::Directory(dir.path());
+}
+
+QStringList PURL::Directory::files(const QString &filter) const
+{
+ QDir dir(path());
+ return dir.entryList(filter, QDir::Files);
+}
+
+PURL::Url PURL::Directory::findMatchingFilename(const QString &filename) const
+{
+ QDir dir(path());
+ QStringList files = dir.entryList(QDir::Files);
+ for (uint i=0; i<uint(files.count()); i++)
+ if ( files[i].lower()==filename.lower() ) return Url(*this, files[i]);
+ return Url(*this, filename);
+}
+
+PURL::Directory PURL::Directory::current()
+{
+ return QDir::currentDirPath();
+}
diff --git a/src/common/global/purl.h b/src/common/global/purl.h
new file mode 100644
index 0000000..6cbf38b
--- /dev/null
+++ b/src/common/global/purl.h
@@ -0,0 +1,136 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#ifndef PURL_H
+#define PURL_H
+
+#include "common/global/global.h"
+#if QT_VERSION<0x040000
+# include <qhttp.h>
+#else
+# include <QtNetwork/QHttp>
+# include <QDateTime>
+#endif
+#include "common/global/log.h"
+#include "common/common/purl_base.h"
+
+namespace PURL
+{
+//----------------------------------------------------------------------------
+class Http : public QHttp
+{
+Q_OBJECT
+public:
+ Http(const QString &hostname);
+ QHttpResponseHeader _header;
+
+private slots:
+ void responseHeaderReceivedSlot(const QHttpResponseHeader &rh) { _header = rh; }
+};
+
+class Url;
+class Directory;
+class Private;
+
+enum SeparatorType { UnixSeparator, WindowsSeparator };
+
+//----------------------------------------------------------------------------
+class Base
+{
+public:
+ Base(const QString &filepath = QString::null);
+ Base(const KURL &url);
+ bool operator <(const Base &url) const { return _url<url._url; }
+ bool operator ==(const Base &url) const;
+ bool operator !=(const Base &url) const { return !(_url==url._url); }
+ const KURL &kurl() const { return _url; }
+ QString pretty() const;
+ bool isEmpty() const { return _url.isEmpty(); }
+ bool isLocal() const;
+ QString path(SeparatorType type = UnixSeparator) const; // with ending '/' unless empty path
+ QString unterminatedPath(SeparatorType type = UnixSeparator) const; // no ending '/'
+ Directory directory() const;
+ bool isInto(const Directory &dir) const;
+ bool isRelative() const { return _relative; }
+ bool exists(QDateTime *lastModified = 0) const;
+
+protected:
+ bool _relative;
+ KURL _url;
+ static Private *_private;
+
+private:
+ bool httpUrlExists(bool *ok = 0) const;
+};
+
+//----------------------------------------------------------------------------
+class Url : public Base
+{
+public:
+ Url() {}
+ Url(const KURL &url) : Base(url) {}
+ // add correct extension if filename has no extension
+ Url(const Directory &path, const QString &filename, FileType type);
+ Url(const Directory &path, const QString &filepath);
+ static Url fromPathOrUrl(const QString &s);
+
+ Url toFileType(FileType type) const { return toExtension(type.data().extensions[0]); }
+ Url toExtension(const QString &extension) const;
+ Url appendExtension(const QString &extension) const;
+
+ const FileType::Data &data() const { return fileType().data(); }
+ FileType fileType() const;
+ QString basename() const; // filename without extension
+ QString filename() const; // filename without path
+ QString filepath(SeparatorType type = UnixSeparator) const; // filename with path
+ QString relativeTo(const Directory &dir, SeparatorType type = UnixSeparator) const;
+ Url toAbsolute(const Directory &dir) const;
+#if !defined(NO_KDE)
+ bool isDosFile() const;
+ bool create(Log::Generic &log) const; // do not overwrite
+ bool write(const QString &text, Log::Generic &log) const;
+ bool copyTo(const Url &destination, Log::Generic &log) const; // do not overwrite
+ bool del(Log::Generic &log) const;
+#endif
+
+private:
+ Url(const QString &filepath) : Base(filepath) {}
+};
+
+extern bool findExistingUrl(Url &url); // may transform extension's case if needed
+
+//----------------------------------------------------------------------------
+class UrlList : public QValueList<Url>
+{
+public:
+ UrlList() {}
+ UrlList(const Url &url) { append(url); }
+ UrlList(const QValueList<Url> &list) : QValueList<Url>(list) {}
+#if !defined(NO_KDE)
+ UrlList(const KURL::List &list);
+#endif
+};
+
+//----------------------------------------------------------------------------
+class Directory : public Base
+{
+public:
+ Directory(const QString &path = QString::null);
+ QStringList files(const QString &filter) const;
+ Url findMatchingFilename(const QString &filename) const;
+ Directory up() const;
+ Directory down(const QString &path) const;
+ static Directory current();
+#if !defined(NO_KDE)
+ bool create(Log::Generic &log) const;
+#endif
+};
+
+} // namespace
+
+#endif
diff --git a/src/common/global/svn_revision/Makefile.am b/src/common/global/svn_revision/Makefile.am
new file mode 100644
index 0000000..f3d4ee4
--- /dev/null
+++ b/src/common/global/svn_revision/Makefile.am
@@ -0,0 +1,5 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+
+all-local:
+ sh svn_revision.sh
diff --git a/src/common/global/svn_revision/svn_revision.sh b/src/common/global/svn_revision/svn_revision.sh
new file mode 100755
index 0000000..3590568
--- /dev/null
+++ b/src/common/global/svn_revision/svn_revision.sh
@@ -0,0 +1,20 @@
+if [ -d .svn ]; then
+ ( echo '// generated file';
+ printf '#define SVN_REVISION "';
+ (svnversion -n .);
+ echo '"' ) > svn_revision.h.new;
+ if [ ! -f svn_revision.h ]; then
+ mv -f svn_revision.h.new svn_revision.h;
+ else
+ if cmp svn_revision.h svn_revision.h.new; then
+ rm -f svn_revision.h.new;
+ else
+ mv -f svn_revision.h.new svn_revision.h;
+ fi
+ fi
+fi
+if [ ! -f svn_revision.h ]; then
+ ( echo '// generated file';
+ echo '#define SVN_REVISION "distribution"'; ) > svn_revision.h;
+fi
+
diff --git a/src/common/global/xml_data_file.cpp b/src/common/global/xml_data_file.cpp
new file mode 100644
index 0000000..2464b34
--- /dev/null
+++ b/src/common/global/xml_data_file.cpp
@@ -0,0 +1,160 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#include "xml_data_file.h"
+
+#include <qfile.h>
+#include <qstringlist.h>
+#include <ksimpleconfig.h>
+#include <klocale.h>
+#include "common/global/pfile.h"
+
+XmlDataFile::XmlDataFile(const PURL::Url &url, const QString &name)
+ : _url(url), _name(name), _document(name)
+{
+ QDomElement root = _document.createElement(name);
+ _document.appendChild(root);
+}
+
+bool XmlDataFile::load(QString &error)
+{
+ Log::StringView sview;
+ PURL::File file(_url, sview);
+ if ( !file.openForRead() ) {
+ error = i18n("Error opening file: %1").arg(sview.string());
+ return false;
+ }
+ if ( !_document.setContent(file.qfile(), false, &error) ) return false;
+ if ( _document.doctype().name()!=_name
+ || _document.documentElement().nodeName()!=_name ) {
+ error = i18n("File is not of correct type.");
+ return false;
+ }
+ return true;
+}
+
+bool XmlDataFile::save(QString &error) const
+{
+ Log::StringView sview;
+ PURL::File file(_url, sview);
+ bool ok = file.openForWrite();
+ if (ok) {
+ QString s = _document.toString(2);
+ file.appendText(s);
+ ok = file.close();
+ }
+ if ( !ok ) error = i18n("Error saving file: %1").arg(sview.string());
+ return ok;
+}
+
+QDomElement XmlDataFile::findChildElement(QDomElement parent, const QString &name) const
+{
+ QDomNodeList list = parent.elementsByTagName(name);
+ return list.item(0).toElement();
+}
+
+QDomElement XmlDataFile::createChildElement(QDomElement parent, const QString &name)
+{
+ QDomNodeList list = parent.elementsByTagName(name);
+ if ( list.count()==0 ) {
+ QDomElement element = _document.createElement(name);
+ parent.appendChild(element);
+ return element;
+ }
+ return list.item(0).toElement();
+}
+
+void XmlDataFile::removeChilds(QDomNode parent) const
+{
+ QDomNodeList list = parent.childNodes();
+ for (uint i=0; i<list.count(); i++)
+ parent.removeChild(list.item(i));
+}
+
+QString XmlDataFile::value(const QString &group, const QString &key, const QString &defValue) const
+{
+ QDomElement root = _document.documentElement();
+ QDomElement groupElement = findChildElement(root, group);
+ if ( groupElement.isNull() ) return defValue;
+ QDomElement element = findChildElement(groupElement, key);
+ if ( element.isNull() ) return defValue;
+ QDomText text = element.firstChild().toText();
+ if ( text.isNull() ) return defValue;
+ return text.data();
+}
+
+void XmlDataFile::setValue(const QString &group, const QString &key, const QString &value)
+{
+ QDomElement root = _document.documentElement();
+ QDomElement groupElement = createChildElement(root, group);
+ QDomElement element = createChildElement(groupElement, key);
+ removeChilds(element);
+ QDomText text = _document.createTextNode(value);
+ element.appendChild(text);
+}
+
+QStringList XmlDataFile::listValues(const QString &group, const QString &key, const QStringList &defaultValues) const
+{
+ QStringList list;
+ QDomElement root = _document.documentElement();
+ QDomElement groupElement = findChildElement(root, group);
+ if ( groupElement.isNull() ) return defaultValues;
+ QDomElement element = findChildElement(groupElement, key);
+ if ( element.isNull() ) return defaultValues;
+ QDomNodeList childs = element.childNodes();
+ if ( childs.count()==1 ) { // legacy compatibility
+ QDomText text = element.firstChild().toText();
+ if ( !text.isNull() ) return text.data();
+ }
+ for (uint i=0; i<childs.count(); i++) {
+ QDomText text = childs.item(i).toElement().firstChild().toText();
+ if ( text.isNull() ) continue;
+ list.append(text.data());
+ }
+ return list;
+}
+
+void XmlDataFile::appendListValue(const QString &group, const QString &key, const QString &value)
+{
+ QDomElement root = _document.documentElement();
+ QDomElement groupElement = createChildElement(root, group);
+ QDomElement element = createChildElement(groupElement, key);
+ QDomElement item = _document.createElement("item");
+ element.appendChild(item);
+ QDomText text = _document.createTextNode(value);
+ item.appendChild(text);
+}
+
+void XmlDataFile::removeListValue(const QString &group, const QString &key, const QString &value)
+{
+ QDomElement root = _document.documentElement();
+ QDomElement groupElement = createChildElement(root, group);
+ QDomElement element = createChildElement(groupElement, key);
+ QDomNodeList list = element.childNodes();
+ for (uint i=0; i<list.count(); i++) {
+ QDomElement item = list.item(i).toElement();
+ QDomText text = item.firstChild().toText();
+ if ( text.isNull() || text.data()!=value ) continue;
+ element.removeChild(item);
+ break;
+ }
+}
+
+void XmlDataFile::clearList(const QString &group, const QString &key)
+{
+ QDomElement root = _document.documentElement();
+ QDomElement groupElement = createChildElement(root, group);
+ QDomElement element = createChildElement(groupElement, key);
+ groupElement.removeChild(element);
+}
+
+void XmlDataFile::setListValues(const QString &group, const QString &key, const QStringList &values)
+{
+ clearList(group, key);
+ for (uint i=0; i<values.count(); i++) appendListValue(group, key, values[i]);
+}
diff --git a/src/common/global/xml_data_file.h b/src/common/global/xml_data_file.h
new file mode 100644
index 0000000..dfcbc73
--- /dev/null
+++ b/src/common/global/xml_data_file.h
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@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. *
+ ***************************************************************************/
+#ifndef XML_DATA_FILE_H
+#define XML_DATA_FILE_H
+
+#include <qdom.h>
+
+#include "common/global/purl.h"
+
+class XmlDataFile
+{
+public:
+ XmlDataFile(const PURL::Url &url, const QString &name);
+ virtual ~XmlDataFile() {}
+ PURL::Url url() const { return _url; }
+ virtual bool load(QString &error);
+ bool save(QString &error) const;
+
+ QString value(const QString &group, const QString &key, const QString &defaultValue) const;
+ void setValue(const QString &group, const QString &key, const QString &value);
+ QStringList listValues(const QString &group, const QString &key, const QStringList &defaultValues) const;
+ void setListValues(const QString &group, const QString &key, const QStringList &values);
+ void appendListValue(const QString &group, const QString &key, const QString &value);
+ void removeListValue(const QString &group, const QString &key, const QString &value);
+ void clearList(const QString &group, const QString &key);
+
+protected:
+ PURL::Url _url;
+
+private:
+ QString _name;
+ QDomDocument _document;
+
+ QDomElement findChildElement(QDomElement element, const QString &tag) const;
+ QDomElement createChildElement(QDomElement element, const QString &tag);
+ void removeChilds(QDomNode node) const;
+};
+
+#endif