summaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 18:42:24 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 18:42:24 +0000
commitf508189682b6fba62e08feeb1596f682bad5fff9 (patch)
tree28aeb0e6c19386c385c1ce5edf8a92c1bca15281 /src/common
downloadpiklab-f508189682b6fba62e08feeb1596f682bad5fff9.tar.gz
piklab-f508189682b6fba62e08feeb1596f682bad5fff9.zip
Added KDE3 version of PikLab
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/piklab@1095639 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/common')
-rw-r--r--src/common/Makefile.am4
-rw-r--r--src/common/cli/Makefile.am7
-rw-r--r--src/common/cli/cli.pro6
-rw-r--r--src/common/cli/cli_global.cpp37
-rw-r--r--src/common/cli/cli_global.h33
-rw-r--r--src/common/cli/cli_log.cpp74
-rw-r--r--src/common/cli/cli_log.h33
-rw-r--r--src/common/cli/cli_main.cpp208
-rw-r--r--src/common/cli/cli_main.h82
-rw-r--r--src/common/cli/cli_pfile.cpp47
-rw-r--r--src/common/cli/cli_purl.cpp9
-rw-r--r--src/common/common.pro2
-rw-r--r--src/common/common/Makefile.am9
-rw-r--r--src/common/common/bitvalue.cpp30
-rw-r--r--src/common/common/bitvalue.h129
-rw-r--r--src/common/common/common.pro6
-rw-r--r--src/common/common/group.cpp71
-rw-r--r--src/common/common/group.h82
-rw-r--r--src/common/common/key_enum.h107
-rw-r--r--src/common/common/lister.h71
-rw-r--r--src/common/common/misc.cpp72
-rw-r--r--src/common/common/misc.h39
-rw-r--r--src/common/common/number.cpp201
-rw-r--r--src/common/common/number.h92
-rw-r--r--src/common/common/purl_base.cpp133
-rw-r--r--src/common/common/purl_base.h79
-rw-r--r--src/common/common/qflags.h81
-rw-r--r--src/common/common/range.h61
-rw-r--r--src/common/common/storage.cpp42
-rw-r--r--src/common/common/storage.h85
-rw-r--r--src/common/common/streamer.h59
-rw-r--r--src/common/common/synchronous.cpp58
-rw-r--r--src/common/common/synchronous.h32
-rw-r--r--src/common/common/version_data.cpp55
-rw-r--r--src/common/common/version_data.h47
-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
-rw-r--r--src/common/gui/Makefile.am7
-rw-r--r--src/common/gui/config_widget.h107
-rw-r--r--src/common/gui/container.cpp80
-rw-r--r--src/common/gui/container.h58
-rw-r--r--src/common/gui/dialog.cpp199
-rw-r--r--src/common/gui/dialog.h77
-rw-r--r--src/common/gui/editlistbox.cpp340
-rw-r--r--src/common/gui/editlistbox.h95
-rw-r--r--src/common/gui/hexword_gui.cpp136
-rw-r--r--src/common/gui/hexword_gui.h88
-rw-r--r--src/common/gui/key_gui.h125
-rw-r--r--src/common/gui/list_container.cpp95
-rw-r--r--src/common/gui/list_container.h55
-rw-r--r--src/common/gui/list_view.cpp221
-rw-r--r--src/common/gui/list_view.h93
-rw-r--r--src/common/gui/misc_gui.cpp234
-rw-r--r--src/common/gui/misc_gui.h164
-rw-r--r--src/common/gui/number_gui.cpp72
-rw-r--r--src/common/gui/number_gui.h40
-rw-r--r--src/common/gui/pfile_ext.cpp114
-rw-r--r--src/common/gui/pfile_ext.h29
-rw-r--r--src/common/gui/purl_ext.cpp111
-rw-r--r--src/common/gui/purl_gui.cpp151
-rw-r--r--src/common/gui/purl_gui.h120
-rw-r--r--src/common/nokde/nokde.pro8
-rw-r--r--src/common/nokde/nokde_kaboutdata.cpp469
-rw-r--r--src/common/nokde/nokde_kaboutdata.h571
-rw-r--r--src/common/nokde/nokde_kcmdlineargs.cpp1329
-rw-r--r--src/common/nokde/nokde_kcmdlineargs.h701
-rw-r--r--src/common/nokde/nokde_klocale.cpp4
-rw-r--r--src/common/nokde/nokde_klocale.h17
-rw-r--r--src/common/nokde/nokde_kprocess.cpp100
-rw-r--r--src/common/nokde/nokde_kprocess.h51
-rw-r--r--src/common/nokde/nokde_kurl.h32
-rw-r--r--src/common/nokde/win32_utils.c81
-rw-r--r--src/common/nokde/win32_utils.h97
-rw-r--r--src/common/port/Makefile.am7
-rw-r--r--src/common/port/parallel.cpp247
-rw-r--r--src/common/port/parallel.h70
-rw-r--r--src/common/port/port.cpp98
-rw-r--r--src/common/port/port.h56
-rw-r--r--src/common/port/port.pro10
-rw-r--r--src/common/port/port_base.cpp127
-rw-r--r--src/common/port/port_base.h59
-rw-r--r--src/common/port/serial.cpp523
-rw-r--r--src/common/port/serial.h113
-rw-r--r--src/common/port/usb_port.cpp411
-rw-r--r--src/common/port/usb_port.h70
104 files changed, 12482 insertions, 0 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am
new file mode 100644
index 0000000..da1638b
--- /dev/null
+++ b/src/common/Makefile.am
@@ -0,0 +1,4 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+
+SUBDIRS = common global port cli gui
diff --git a/src/common/cli/Makefile.am b/src/common/cli/Makefile.am
new file mode 100644
index 0000000..2225bc0
--- /dev/null
+++ b/src/common/cli/Makefile.am
@@ -0,0 +1,7 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libcli.la
+libcli_la_LDFLAGS = $(all_libraries)
+libcli_la_SOURCES = cli_purl.cpp cli_pfile.cpp cli_global.cpp cli_log.cpp \
+ cli_main.cpp
diff --git a/src/common/cli/cli.pro b/src/common/cli/cli.pro
new file mode 100644
index 0000000..20bb3b7
--- /dev/null
+++ b/src/common/cli/cli.pro
@@ -0,0 +1,6 @@
+STOPDIR = ../../..
+include($${STOPDIR}/lib.pro)
+
+TARGET = cli
+HEADERS += cli_global.h cli_log.h cli_main.h
+SOURCES += cli_global.cpp cli_log.cpp cli_purl.cpp cli_pfile.cpp cli_main.cpp
diff --git a/src/common/cli/cli_global.cpp b/src/common/cli/cli_global.cpp
new file mode 100644
index 0000000..4d58bdd
--- /dev/null
+++ b/src/common/cli/cli_global.cpp
@@ -0,0 +1,37 @@
+/***************************************************************************
+ * 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 "cli_global.h"
+
+#include <qdir.h>
+
+#include "common/global/purl.h"
+#include "cli_log.h"
+
+bool CLI::_force = false;
+bool CLI::_isInteractive = false;
+CLI::View *CLI::_view = 0;
+CLI::MainBase *CLI::_main = 0;
+
+CLI::ExitCode CLI::errorExit(const QString &message, ExitCode code)
+{
+ Q_ASSERT( code!=OK );
+ _view->log(Log::LineType::SoftError, message);
+ return code;
+}
+
+CLI::ExitCode CLI::okExit(const QString &message)
+{
+ _view->log(Log::LineType::Information, message);
+ return OK;
+}
+
+PURL::Directory CLI::runDirectory()
+{
+ return PURL::Directory(QDir::currentDirPath());
+}
diff --git a/src/common/cli/cli_global.h b/src/common/cli/cli_global.h
new file mode 100644
index 0000000..b90f36e
--- /dev/null
+++ b/src/common/cli/cli_global.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+ * 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 CLI_GLOBAL_H
+#define CLI_GLOBAL_H
+
+#include <qstring.h>
+namespace PURL { class Directory; }
+
+namespace CLI
+{
+
+class View;
+class MainBase;
+enum ExitCode { EXITING = 1, OK = 0, ARG_ERROR = -1, NOT_SUPPORTED_ERROR = -2,
+ FILE_ERROR = -3, EXEC_ERROR = -4 };
+extern ExitCode errorExit(const QString &message, ExitCode code);
+extern ExitCode okExit(const QString &message);
+extern PURL::Directory runDirectory();
+
+extern bool _force;
+extern bool _isInteractive;
+extern View *_view;
+extern MainBase *_main;
+
+} // namespace
+
+#endif
diff --git a/src/common/cli/cli_log.cpp b/src/common/cli/cli_log.cpp
new file mode 100644
index 0000000..603d5f8
--- /dev/null
+++ b/src/common/cli/cli_log.cpp
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * Copyright (C) 2005-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 "cli_log.h"
+
+#include "common/global/global.h"
+#include "cli_global.h"
+
+void CLI::View::doLog(Log::LineType type, const QString &text, Log::Action)
+{
+ QString s = text + "\n";
+ switch (type.type()) {
+ case Log::LineType::Error:
+ case Log::LineType::SoftError: s = "Error: " + s; break;
+ case Log::LineType::Warning: s = "Warning: " + s; break;
+ default: break;
+ }
+#if QT_VERSION<0x040000
+ if ( type==Log::LineType::Error || type==Log::LineType::SoftError ) fprintf(stderr, "%s", s.latin1());
+ else fprintf(stdout, "%s", s.latin1());
+#else
+ QByteArray ba = s.toLatin1();
+ if ( type==Log::LineType::Error || type==Log::LineType::SoftError ) fprintf(stderr, "%s", ba.constData());
+ else fprintf(stdout, "%s", ba.constData());
+#endif
+}
+
+void CLI::View::doLog(Log::DebugLevel, const QString &text, Log::Action)
+{
+ QString s = text + "\n";
+#if QT_VERSION<0x040000
+ fprintf(stdout, "%s", s.latin1());
+#else
+ QByteArray ba = s.toLatin1();
+ fprintf(stdout, "%s", ba.constData());
+#endif
+}
+
+void CLI::View::appendToLastLine(const QString &text)
+{
+#if QT_VERSION<0x040000
+ fprintf(stdout, "%s", text.latin1());
+#else
+ QByteArray ba = text.toLatin1();
+ fprintf(stdout, "%s", ba.constData());
+#endif
+}
+
+void CLI::View::sorry(const QString &message, const QString &details)
+{
+ if ( details.isEmpty() ) log(Log::LineType::Error, message, Log::Immediate);
+ else log(Log::LineType::Error, message + " (" + details + ")", Log::Immediate);
+}
+
+bool CLI::View::askContinue(const QString &message)
+{
+ log(Log::LineType::Warning, message + " " + (_force ? i18n("*yes*") : i18n("*no*")), Log::Immediate);
+ if (_force) return true;
+ if ( !_isInteractive ) return false; // always fail
+ // #### TODO
+ return false;
+}
+
+void CLI::View::logUserAbort()
+{
+ if ( !_isInteractive ) return;
+ return;
+ //Log::View::logUserAbort();
+}
diff --git a/src/common/cli/cli_log.h b/src/common/cli/cli_log.h
new file mode 100644
index 0000000..2fa83dc
--- /dev/null
+++ b/src/common/cli/cli_log.h
@@ -0,0 +1,33 @@
+/***************************************************************************
+ * 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 CLI_LOG_H
+#define CLI_LOG_H
+
+#include "common/global/log.h"
+
+namespace CLI
+{
+
+class View : public Log::View
+{
+public:
+ virtual void appendToLastLine(const QString &text);
+ virtual void clear() {}
+ virtual void sorry(const QString &message, const QString &details);
+ virtual bool askContinue(const QString &message);
+ virtual void logUserAbort();
+
+private:
+ virtual void doLog(Log::LineType type, const QString &text, Log::Action action);
+ virtual void doLog(Log::DebugLevel level, const QString &text, Log::Action action);
+};
+
+} // namespace
+
+#endif
diff --git a/src/common/cli/cli_main.cpp b/src/common/cli/cli_main.cpp
new file mode 100644
index 0000000..7d75dbb
--- /dev/null
+++ b/src/common/cli/cli_main.cpp
@@ -0,0 +1,208 @@
+/***************************************************************************
+ * 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 "cli_main.h"
+
+#include "cli_log.h"
+#include "common/global/about.h"
+
+//-----------------------------------------------------------------------------
+const CLI::CommandData *CLI::findCommandData(const QString &command)
+{
+ for (uint i=0; NORMAL_COMMAND_DATA[i].name; i++)
+ if ( NORMAL_COMMAND_DATA[i].name==command ) return &NORMAL_COMMAND_DATA[i];
+ if ( !_isInteractive) return 0;
+ for (uint i=0; INTERACTIVE_COMMAND_DATA[i].name; i++)
+ if ( INTERACTIVE_COMMAND_DATA[i].name==command ) return &INTERACTIVE_COMMAND_DATA[i];
+ return 0;
+}
+
+CLI::ExitCode CLI::findCommand(const QString &s)
+{
+ if ( s.isEmpty() ) return errorExit(i18n("No command specified"), ARG_ERROR);
+ const CommandData *data = findCommandData(s);
+ if ( data==0 ) return errorExit(i18n("Unknown command: %1").arg(s), ARG_ERROR);
+ return OK;
+}
+
+//-----------------------------------------------------------------------------
+bool CLI::isPropertyList(const QString &s)
+{
+ for (uint i=0; PROPERTY_DATA[i].name; i++)
+ if ( s==PROPERTY_DATA[i].list ) return true;
+ return false;
+}
+
+bool CLI::isProperty(const QString &s)
+{
+ for (uint i=0; PROPERTY_DATA[i].name; i++)
+ if ( s==PROPERTY_DATA[i].name ) return true;
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+const KCmdLineOptions STANDARD_OPTIONS[] = {
+ { "c", 0, 0 },
+ { "command <name>", I18N_NOOP("Perform the requested command."), 0 },
+ { "command-list", I18N_NOOP("Return the list of recognized commands."), 0 },
+ { "debug", I18N_NOOP("Display debug messages."), 0 },
+ { "extra-debug", I18N_NOOP("Display extra debug messages."), 0 },
+ { "max-debug", I18N_NOOP("Display all debug messages."), 0 },
+ { "lowlevel-debug", I18N_NOOP("Display low level debug messages."), 0 },
+ { "quiet", I18N_NOOP("Do not display messages."), 0 },
+ KCmdLineLastOption
+};
+
+const KCmdLineOptions FORCE_OPTIONS[] = {
+ { "f", 0, 0 },
+ { "force", I18N_NOOP("Overwrite files and answer \"yes\" to questions."), 0 },
+ KCmdLineLastOption
+};
+
+const KCmdLineOptions INTERACTIVE_OPTIONS[] = {
+ { "i", 0, 0 },
+ { "cli", I18N_NOOP("Interactive mode"), 0 },
+ KCmdLineLastOption
+};
+
+CLI::OptionList::OptionList(Properties properties)
+{
+ init(properties);
+}
+
+CLI::OptionList::OptionList(Properties properties, const KCmdLineOptions *options)
+{
+ init(properties);
+ for (uint i=0; options[i].name; i++) append(options[i]);
+}
+
+void CLI::OptionList::init(Properties properties)
+{
+ for (uint i=0; STANDARD_OPTIONS[i].name; i++) append(STANDARD_OPTIONS[i]);
+ if ( properties & HasForce ) for (uint i=0; FORCE_OPTIONS[i].name; i++) append(FORCE_OPTIONS[i]);
+ if ( properties & HasInteractiveMode ) for (uint i=0; INTERACTIVE_OPTIONS[i].name; i++) append(INTERACTIVE_OPTIONS[i]);
+}
+
+CLI::ExitCode CLI::commandList()
+{
+ Log::KeyList keys(i18n("Supported commands:"));
+ for (uint i=0; NORMAL_COMMAND_DATA[i].name; i++)
+ keys.append(NORMAL_COMMAND_DATA[i].name, i18n(NORMAL_COMMAND_DATA[i].help));
+ if (_isInteractive) {
+ for (uint i=0; INTERACTIVE_COMMAND_DATA[i].name; i++)
+ keys.append(INTERACTIVE_COMMAND_DATA[i].name, i18n(INTERACTIVE_COMMAND_DATA[i].help));
+ }
+ keys.display(*_view);
+ return OK;
+}
+
+CLI::ExitCode CLI::propertyList()
+{
+ Log::KeyList keys;
+ for (uint i=0; PROPERTY_DATA[i].name; i++)
+ keys.append(PROPERTY_DATA[i].name, i18n(PROPERTY_DATA[i].help));
+ keys.display(*_view);
+ return OK;
+}
+
+//-----------------------------------------------------------------------------
+CLI::MainBase::MainBase(Properties properties)
+ : QObject(0, "main"), _properties(properties)
+{
+ Q_ASSERT( _main==0 );
+ _main = this;
+ _view = new View;
+ setView(_view);
+}
+
+void CLI::MainBase::init()
+{
+ _args = KCmdLineArgs::parsedArgs();
+ if ( _properties & HasInteractiveMode ) _isInteractive = _args->isSet("cli");
+ if ( _properties & HasForce ) _force = _args->isSet("force");
+ FOR_EACH(Log::DebugLevel, level) if ( _args->isSet(level.key()) ) _view->setDebugLevel(level);
+}
+
+CLI::OptionList CLI::MainBase::optionList(const char *fileDescription) const
+{
+ OptionList list(_properties, OPTIONS);
+ KCmdLineOptions opt;
+ for (uint i=0; PROPERTY_DATA[i].name; i++) {
+ opt.description = 0;
+ opt.def = 0;
+ if ( PROPERTY_DATA[i].help==0 ) {
+ Q_ASSERT( QString(PROPERTY_DATA[i].name)!=PROPERTY_DATA[i].optName );
+ opt.name = PROPERTY_DATA[i].name; // alias
+ list.append(opt);
+ } else {
+ if ( PROPERTY_DATA[i].optName==0 ) continue; // interactive only
+ if ( PROPERTY_DATA[i].alias ) {
+ opt.name = PROPERTY_DATA[i].alias;
+ list.append(opt);
+ }
+ opt.name = PROPERTY_DATA[i].optName;
+ opt.description = PROPERTY_DATA[i].help;
+ list.append(opt);
+ if ( PROPERTY_DATA[i].list ) {
+ opt.name = PROPERTY_DATA[i].list;
+ opt.description = PROPERTY_DATA[i].listHelp;
+ list.append(opt);
+ }
+ }
+ }
+ if (fileDescription) {
+ opt.name = "+[file]";
+ opt.description = fileDescription;
+ opt.def = 0;
+ }
+ list.append(opt);
+ return list;
+}
+
+CLI::ExitCode CLI::MainBase::list(const QString &command)
+{
+ if ( command=="command-list" ) return commandList();
+ if ( command=="property-list" ) return propertyList();
+ return ARG_ERROR;
+}
+
+CLI::ExitCode CLI::MainBase::doRun()
+{
+ init();
+
+ // process set options
+ for (uint i=0; PROPERTY_DATA[i].name; i++) {
+ if ( PROPERTY_DATA[i].optName==0 ) continue; // alias or interactive only
+ if ( !_args->isSet(PROPERTY_DATA[i].name) ) continue;
+ QString option = _args->getOption(PROPERTY_DATA[i].name);
+ ExitCode code = executeSetCommand(PROPERTY_DATA[i].name, option);
+ if ( code!=OK ) return code;
+ log(Log::LineType::Information, QString("%1: %2").arg(PROPERTY_DATA[i].name).arg(executeGetCommand(PROPERTY_DATA[i].name)));
+ }
+
+ // process default lists
+ if ( _args->isSet("command-list") ) return list("command-list");
+ for (uint i=0; PROPERTY_DATA[i].name; i++) {
+ if ( PROPERTY_DATA[i].list==0 ) continue;
+ if ( _args->isSet(PROPERTY_DATA[i].list) ) return list(PROPERTY_DATA[i].list);
+ }
+
+ bool interactive;
+ ExitCode code = prepareRun(interactive);
+ if ( code!=OK || interactive ) return code;
+
+ // find command
+ QString command = _args->getOption("command");
+ code = findCommand(command);
+ if ( code!=OK ) return code;
+
+ // execute command
+ code = prepareCommand(command);
+ if ( code!=OK ) return code;
+ return executeCommand(command);
+}
diff --git a/src/common/cli/cli_main.h b/src/common/cli/cli_main.h
new file mode 100644
index 0000000..9b54c70
--- /dev/null
+++ b/src/common/cli/cli_main.h
@@ -0,0 +1,82 @@
+/***************************************************************************
+ * 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 CLI_MAIN_H
+#define CLI_MAIN_H
+
+#include "common/global/about.h"
+#include "common/global/log.h"
+#include "cli_global.h"
+
+namespace CLI
+{
+//-----------------------------------------------------------------------------
+enum Property { NoProperty = 0, HasForce = 1, HasInteractiveMode = 2 };
+Q_DECLARE_FLAGS(Properties, Property)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Properties)
+
+extern const KCmdLineOptions OPTIONS[];
+//-----------------------------------------------------------------------------
+struct CommandData {
+ const char *name;
+ int properties;
+ const char *help;
+};
+extern const CommandData NORMAL_COMMAND_DATA[];
+extern const CommandData INTERACTIVE_COMMAND_DATA[];
+extern const CommandData *findCommandData(const QString &command);
+extern ExitCode findCommand(const QString &s);
+extern ExitCode commandList();
+
+//-----------------------------------------------------------------------------
+struct PropertyData
+{
+ const char *name, *optName, *alias, *help, *list, *listHelp;
+};
+extern const PropertyData PROPERTY_DATA[];
+extern bool isPropertyList(const QString &s);
+extern bool isProperty(const QString &s);
+extern ExitCode propertyList();
+
+//-----------------------------------------------------------------------------
+class OptionList : public Piklab::OptionList
+{
+public:
+ OptionList(Properties properties);
+ OptionList(Properties properties, const KCmdLineOptions *options);
+
+private:
+ void init(Properties properties);
+};
+
+//-----------------------------------------------------------------------------
+class MainBase : public QObject, public Log::Base
+{
+Q_OBJECT
+public:
+ MainBase(Properties properties);
+ virtual OptionList optionList(const char *fileDescription) const;
+ virtual ExitCode doRun();
+ virtual ExitCode list(const QString &listName);
+ virtual ExitCode prepareCommand(const QString &command) = 0;
+ virtual ExitCode executeCommand(const QString &command) = 0;
+ virtual ExitCode executeSetCommand(const QString &property, const QString &value) = 0;
+ virtual QString executeGetCommand(const QString &property) = 0;
+
+protected:
+ Properties _properties;
+ KCmdLineArgs *_args;
+
+private:
+ virtual ExitCode prepareRun(bool &interactive) = 0;
+ virtual void init();
+};
+
+} // namespace
+
+#endif
diff --git a/src/common/cli/cli_pfile.cpp b/src/common/cli/cli_pfile.cpp
new file mode 100644
index 0000000..96add3a
--- /dev/null
+++ b/src/common/cli/cli_pfile.cpp
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * 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 "common/global/pfile.h"
+
+#include <qfile.h>
+
+//-----------------------------------------------------------------------------
+bool PURL::File::openForWrite()
+{
+ close();
+ _file->setName(url().filepath());
+ if ( !_file->open(IO_WriteOnly) ) {
+ _error = i18n("Could not open file for writing.");
+ _log.sorry(_error, i18n("File: %1").arg(_file->name()));
+ return false;
+ }
+ return true;
+}
+
+bool PURL::File::close()
+{
+ _file->close();
+ return ( uint(_file->status())==IO_Ok );
+}
+
+bool PURL::File::openForRead()
+{
+ close();
+ _file->setName(_url.filepath());
+ if ( !_file->open(IO_ReadOnly) ) {
+ _error = i18n("Could not open file for reading.");
+ _log.sorry(_error, i18n("File: %1").arg(_file->name()));
+ return false;
+ }
+ return true;
+}
+
+bool PURL::File::remove()
+{
+ return _file->remove();
+}
diff --git a/src/common/cli/cli_purl.cpp b/src/common/cli/cli_purl.cpp
new file mode 100644
index 0000000..e52c977
--- /dev/null
+++ b/src/common/cli/cli_purl.cpp
@@ -0,0 +1,9 @@
+/***************************************************************************
+ * 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 "common/global/purl.h"
diff --git a/src/common/common.pro b/src/common/common.pro
new file mode 100644
index 0000000..aa219c1
--- /dev/null
+++ b/src/common/common.pro
@@ -0,0 +1,2 @@
+TEMPLATE = subdirs
+SUBDIRS = common nokde global port cli
diff --git a/src/common/common/Makefile.am b/src/common/common/Makefile.am
new file mode 100644
index 0000000..0f68067
--- /dev/null
+++ b/src/common/common/Makefile.am
@@ -0,0 +1,9 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libcommon.la
+libcommon_la_SOURCES = bitvalue.cpp group.cpp misc.cpp number.cpp purl_base.cpp \
+ storage.cpp synchronous.cpp version_data.cpp
+libcommon_la_LDFLAGS = $(all_libraries)
+
+
diff --git a/src/common/common/bitvalue.cpp b/src/common/common/bitvalue.cpp
new file mode 100644
index 0000000..16d5ef0
--- /dev/null
+++ b/src/common/common/bitvalue.cpp
@@ -0,0 +1,30 @@
+/***************************************************************************
+ * 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 "bitvalue.h"
+
+const uint GenericValue::INVALID = 0xFFFFFFFFU;
+
+BitValue BitValue::XORn(uint n) const
+{
+ uint nb = nbBits(_value);
+ uint mask = maxValue(NumberBase::Bin, n);
+ uint res = 0x0;
+ for (uint i=0; i<nb; i +=n) {
+ res ^= (_value >> i) & mask;
+ //qDebug("%i %s %s", i, toHexLabel((value>>i) & mask, 4).latin1(), toHexLabel(res, 4).latin1());
+ }
+ return res;
+}
+
+BitValue BitValue::XNORn(uint n) const
+{
+ BitValue res = XORn(n);
+ BitValue mask = maxValue(NumberBase::Bin, n);
+ return res.complementInMask(mask);
+}
diff --git a/src/common/common/bitvalue.h b/src/common/common/bitvalue.h
new file mode 100644
index 0000000..d3ef9fe
--- /dev/null
+++ b/src/common/common/bitvalue.h
@@ -0,0 +1,129 @@
+/***************************************************************************
+ * 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 BITVALUE_H
+#define BITVALUE_H
+
+#include "number.h"
+#include "range.h"
+
+//----------------------------------------------------------------------------
+class GenericValue
+{
+public:
+ GenericValue(uint value) : _value(value) {}
+
+ bool operator <(GenericValue v) const { CRASH_ASSERT(_value!=INVALID); return _value<v._value; }
+ bool operator >(GenericValue v) const { CRASH_ASSERT(_value!=INVALID); return _value>v._value; }
+ bool operator <=(GenericValue v) const { CRASH_ASSERT(_value!=INVALID); return _value<=v._value; }
+ bool operator >=(GenericValue v) const { CRASH_ASSERT(_value!=INVALID); return _value>=v._value; }
+ bool operator ==(GenericValue v) const { return _value==v._value; }
+ bool operator !=(GenericValue v) const { return _value!=v._value; }
+
+ bool bit(uint index) const { return (_value >> index) & 0x1; }
+ uchar nybble(uint index) const { return (_value >> (4*index)) & 0xF; }
+ uchar byte(uint index) const { return (_value >> (8*index)) & 0xFF; }
+ uint toUInt() const { return _value; }
+
+protected:
+ static const uint INVALID;
+ uint _value;
+
+private:
+ friend QDataStream &operator <<(QDataStream &s, GenericValue v);
+ friend QDataStream &operator >>(QDataStream &s, GenericValue &v);
+};
+
+inline QDataStream &operator <<(QDataStream &s, GenericValue v) { s << v._value; return s; }
+inline QDataStream &operator >>(QDataStream &s, GenericValue &v) { s >> v._value; return s; }
+
+inline QString toLabel(GenericValue v) { return QString::number(v.toUInt()); }
+inline QString toLabel(NumberBase base, GenericValue v, uint nbChars) { return toLabel(base, v.toUInt(), nbChars); }
+inline QString toHexLabel(GenericValue v, uint nbChars) { return toHexLabel(v.toUInt(), nbChars); }
+inline QString toHex(GenericValue v, uint nbChars) { return toHex(v.toUInt(), nbChars); }
+inline QString toHexLabelAbs(GenericValue v) { return ::toHexLabelAbs(v.toUInt()); }
+
+//----------------------------------------------------------------------------
+class Address : public GenericValue
+{
+public:
+ Address(uint value = INVALID) : GenericValue(value) {}
+ bool isValid() const { return ( _value!=INVALID ); }
+
+ Address &operator ++() { CRASH_ASSERT(_value!=INVALID); _value++; return *this; }
+ Address &operator ++(int) { CRASH_ASSERT(_value!=INVALID); _value++; return *this; }
+ Address operator +(int dec) const { CRASH_ASSERT(_value!=INVALID); return _value + dec; }
+ Address &operator +=(int dec) { CRASH_ASSERT(_value!=INVALID);_value += dec; return *this; }
+ Address &operator --() { CRASH_ASSERT(_value!=INVALID); _value--; return *this; }
+ Address &operator --(int) { CRASH_ASSERT(_value!=INVALID); _value--; return *this; }
+ Address operator -(int dec) const { CRASH_ASSERT(_value!=INVALID);return _value - dec; }
+ Address &operator -=(int dec) { CRASH_ASSERT(_value!=INVALID);_value -= dec; return *this; }
+ int operator -(Address a) const { CRASH_ASSERT(_value!=INVALID && a._value!=INVALID); return _value - a._value; }
+};
+
+class AddressRange : public GenericRange<Address>
+{
+public:
+ AddressRange() {}
+ AddressRange(Address s, Address e) { start = s; end = e; }
+ virtual bool isEmpty() const { return !start.isValid() || !end.isValid() || end<=start; }
+};
+
+typedef GenericRangeVector<Address, AddressRange> AddressRangeVector;
+
+//----------------------------------------------------------------------------
+class BitValue : public GenericValue
+{
+public:
+ BitValue(uint value = INVALID) : GenericValue(value) {}
+ bool isInitialized() const { return ( _value!=INVALID ); }
+
+ BitValue operator |(BitValue v) const { return _value | v._value; }
+ BitValue operator <<(uint shift) const { return _value << shift; }
+ BitValue operator >>(uint shift) const { return _value >> shift; }
+ BitValue operator +(BitValue v) const { return _value + v._value; }
+
+ BitValue &operator |=(BitValue v) { _value |= v._value; return *this; }
+ BitValue &operator <<=(uint shift) { _value <<= shift; return *this; }
+ BitValue &operator >>=(uint shift) { _value >>= shift; return *this; }
+ BitValue &operator +=(BitValue v) { _value += v._value; return *this; }
+
+ BitValue XORn(uint n) const; // XOR between groups of n bits inside value
+ BitValue XNORn(uint n) const; // XORn then NOT on n bits
+
+ BitValue maskWith(BitValue mask) const { return _value & mask._value; }
+ bool isInside(BitValue v) const { return ( (_value & v._value)==_value ); }
+ BitValue complementInMask(BitValue mask) const { return mask._value & ~_value; }
+ BitValue twoComplement() const { return -_value; }
+ BitValue clearMaskBits(BitValue mask) const { return _value & ~mask._value; }
+ bool isOverlapping(BitValue v) const { return ( _value & v._value ); }
+
+ class const_iterator {
+ public:
+ const_iterator() {}
+ bool operator !=(const_iterator it) const { return ( _current!=it._current ); }
+ BitValue operator *() const { return BitValue(_current); }
+ const_iterator &operator ++() {
+ do {
+ if ( _current==_value+1 ) _current = INVALID;
+ if ( _current==INVALID ) break;
+ _current++;
+ } while ( (_current & _value)!=_current );
+ return *this;
+ }
+ private:
+ const_iterator(uint value, uint current) : _value(value), _current(current) {}
+ uint _value, _current;
+ friend class BitValue;
+ };
+ const_iterator begin() const { return const_iterator(_value, 0); }
+ const_iterator end() const { return const_iterator(_value, INVALID); }
+
+};
+
+#endif
diff --git a/src/common/common/common.pro b/src/common/common/common.pro
new file mode 100644
index 0000000..3451c92
--- /dev/null
+++ b/src/common/common/common.pro
@@ -0,0 +1,6 @@
+STOPDIR = ../../..
+include($${STOPDIR}/lib.pro)
+
+TARGET = common
+HEADERS += qflags.h misc.h group.h storage.h synchronous.h purl_base.h number.h bitvalue.h key_enum.h version_data.h
+SOURCES += misc.cpp group.cpp storage.cpp synchronous.cpp purl_base.cpp number.cpp bitvalue.cpp version_data.cpp
diff --git a/src/common/common/group.cpp b/src/common/common/group.cpp
new file mode 100644
index 0000000..2a0610f
--- /dev/null
+++ b/src/common/common/group.cpp
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * 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 "group.h"
+
+//-----------------------------------------------------------------------------
+const Group::Support::Data Group::Support::DATA[Nb_Types] = {
+ { "not_supported", I18N_NOOP("Not Supported") },
+ { "untested", I18N_NOOP("Untested") },
+ { "tested", I18N_NOOP("Tested") }
+};
+
+Group::Base::Base()
+ : _gui(0), _initialized(false)
+{}
+
+Group::Base::ConstIterator Group::Base::begin() const
+{
+ const_cast<Base &>(*this).checkInitSupported();
+ return _devices.begin();
+}
+
+Group::Base::ConstIterator Group::Base::end() const
+{
+ const_cast<Base &>(*this).checkInitSupported();
+ return _devices.end();
+}
+
+void Group::Base::addDevice(const QString &name, const Device::Data *data, Support support)
+{
+ _devices[name].data = data;
+ _devices[name].support = support;
+}
+
+Group::Base::Data Group::Base::deviceData(const QString &device) const
+{
+ const_cast<Base &>(*this).checkInitSupported();
+ return _devices[device];
+}
+
+QValueVector<QString> Group::Base::supportedDevices() const
+{
+ const_cast<Base &>(*this).checkInitSupported();
+ QValueVector<QString> names;
+ for (ConstIterator it=begin(); it!=end(); ++it) names.append(it.key());
+ return names;
+}
+
+uint Group::Base::count() const
+{
+ const_cast<Base &>(*this).checkInitSupported();
+ return _devices.count();
+}
+
+void Group::Base::init()
+{
+ _initialized = false;
+}
+
+void Group::Base::checkInitSupported()
+{
+ if (_initialized) return;
+ _initialized = true;
+ _devices.clear();
+ initSupported();
+}
diff --git a/src/common/common/group.h b/src/common/common/group.h
new file mode 100644
index 0000000..2a87674
--- /dev/null
+++ b/src/common/common/group.h
@@ -0,0 +1,82 @@
+/***************************************************************************
+ * 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 GROUP_H
+#define GROUP_H
+
+#include <qstringlist.h>
+#include <qmap.h>
+
+#include "common/global/global.h"
+#include "key_enum.h"
+namespace Device { class Data; }
+
+namespace Group
+{
+//-----------------------------------------------------------------------------
+class BaseGui;
+BEGIN_DECLARE_ENUM(Support)
+ None = 0, Untested, Tested
+END_DECLARE_ENUM_STD(Support)
+
+//-----------------------------------------------------------------------------
+class Base
+{
+public:
+ class Data {
+ public:
+ Data() : data(0), support(Support::None) {}
+ const Device::Data *data;
+ Support support;
+ };
+ typedef QMap<QString, Data>::ConstIterator ConstIterator;
+
+ Base();
+ virtual ~Base() {}
+ virtual QString name() const = 0;
+ virtual QString label() const = 0;
+ ConstIterator begin() const;
+ ConstIterator end() const;
+ Data deviceData(const QString &device) const;
+ bool isSupported(const QString &device) const { return deviceData(device).support!=Support::None; }
+ QValueVector<QString> supportedDevices() const;
+ uint count() const;
+ const BaseGui *gui() const { return _gui; }
+ void checkInitSupported();
+
+protected:
+ virtual void init();
+ virtual void addDevice(const QString &name, const Device::Data *data, Support support);
+ virtual void initSupported() = 0;
+
+ QMap<QString, Data> _devices;
+
+private:
+ const BaseGui *_gui;
+ bool _initialized;
+
+ template <class GroupType> friend class Lister;
+};
+
+//-----------------------------------------------------------------------------
+class BaseGui
+{
+public:
+ BaseGui() : _group(0) {}
+ virtual ~BaseGui() {}
+ const Base &group() const { return *_group; }
+
+private:
+ const Base *_group;
+
+ template <class GroupType> friend class Lister;
+};
+
+} // namespace
+
+#endif
diff --git a/src/common/common/key_enum.h b/src/common/common/key_enum.h
new file mode 100644
index 0000000..504ca56
--- /dev/null
+++ b/src/common/common/key_enum.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * 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 KEY_ENUM_H
+#define KEY_ENUM_H
+
+#include <qdatastream.h>
+
+#include "misc.h"
+#include "common/global/global.h"
+
+class GenericEnum
+{
+public:
+ GenericEnum(uint value) : _value(value) {}
+ bool operator ==(GenericEnum e) const { return _value==e._value; }
+ bool operator !=(GenericEnum e) const { return _value!=e._value; }
+ bool operator <(GenericEnum e) const { return _value<e._value; }
+ bool operator <=(GenericEnum e) const { return _value<=e._value; }
+ bool operator >(GenericEnum e) const { return _value>e._value; }
+ bool operator >=(GenericEnum e) const { return _value>=e._value; }
+ GenericEnum &operator ++() { _value++; return *this; }
+
+protected:
+ uint _value;
+
+private:
+ friend QDataStream &operator >>(QDataStream &s, GenericEnum &e);
+ friend QDataStream &operator <<(QDataStream &s, const GenericEnum &e);
+};
+
+inline QDataStream &operator <<(QDataStream &s, const GenericEnum &e)
+{
+ s << e._value;
+ return s;
+}
+inline QDataStream &operator >>(QDataStream &s, GenericEnum &e)
+{
+ s >> e._value;
+ return s;
+}
+
+#define BEGIN_DECLARE_ENUM(Enum) \
+class Enum : public GenericEnum \
+{ \
+public: \
+ enum Type {
+
+#define DECLARE_DATA \
+public: \
+ static Type fromKey(const QString &key) { \
+ for (uint i=0; i<Nb_Types; i++) \
+ if ( key==DATA[i].key ) return Type(i); \
+ return Type(Nb_Types); \
+ } \
+ const Data &data() const { \
+ CRASH_ASSERT( _value!=Nb_Types ); \
+ return DATA[_value]; \
+ } \
+ const char *key() const { \
+ if ( _value==Nb_Types ) return 0; \
+ Q_ASSERT(DATA[_value].key); \
+ return DATA[_value].key; \
+ } \
+ QString label() const { \
+ CRASH_ASSERT( _value!=Nb_Types ); \
+ Q_ASSERT(DATA[_value].label); \
+ return i18n(DATA[_value].label); \
+ } \
+ private: \
+ static const Data DATA[Nb_Types]; \
+
+#define DECLARE_ENUM_CLASS(Enum) \
+public: \
+ Enum(Type value = Type(0)) : GenericEnum(value) { Q_ASSERT( value>=0 && value<=Type(Nb_Types)); } \
+ Type type() const { return Type(_value); } \
+};
+
+#define END_DECLARE_ENUM(Enum, EnumData) \
+ , Nb_Types \
+ }; \
+ typedef EnumData Data; \
+ DECLARE_DATA \
+ DECLARE_ENUM_CLASS(Enum) \
+
+#define END_DECLARE_ENUM_STD(Enum) \
+ , Nb_Types \
+ }; \
+ struct Data { \
+ const char *key, *label; \
+ }; \
+ DECLARE_DATA \
+ DECLARE_ENUM_CLASS(Enum)
+
+#define END_DECLARE_ENUM_NO_DATA(Enum) \
+ , Nb_Types \
+ }; \
+ DECLARE_ENUM_CLASS(Enum)
+
+#define FOR_EACH(Enum, e) for(Enum e; e<Enum::Type(Enum::Nb_Types); ++e)
+
+#endif
diff --git a/src/common/common/lister.h b/src/common/common/lister.h
new file mode 100644
index 0000000..35413e8
--- /dev/null
+++ b/src/common/common/lister.h
@@ -0,0 +1,71 @@
+/***************************************************************************
+ * 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 LISTER_H
+#define LISTER_H
+
+#include "group.h"
+
+namespace Group
+{
+//-----------------------------------------------------------------------------
+template <class GroupType>
+class Lister
+{
+public:
+ typedef typename QMap<QString, const GroupType *>::ConstIterator ConstIterator;
+ ConstIterator begin() const { return ConstIterator(_groups.begin()); }
+ ConstIterator end() const { return ConstIterator(_groups.end()); }
+
+ virtual ~Lister() {
+ for (ConstIterator it=begin(); it!=end(); ++it) delete it.data();
+ }
+
+ QValueVector<QString> supportedDevices() const {
+ QValueVector<QString> names;
+ for (ConstIterator it=begin(); it!=end(); ++it) {
+ QValueVector<QString> gnames = it.data()->supportedDevices();
+ for (uint k=0; k<uint(gnames.count()); k++) names.append(gnames[k]);
+ }
+ return names;
+ }
+
+ uint count() const {
+ uint nb = 0;
+ for (ConstIterator it=begin(); it!=end(); ++it) nb += it.data()->count();
+ return nb;
+ }
+
+ bool isSupported(const QString &device) const {
+ for (ConstIterator it=begin(); it!=end(); ++it)
+ if ( it.data()->isSupported(device) ) return true;
+ return false;
+ }
+
+ const GroupType *group(const QString &name) const {
+ if ( _groups.contains(name) ) return _groups[name];
+ return 0;
+ }
+
+protected:
+ void addGroup(GroupType *group, BaseGui *gui) {
+ Q_ASSERT(group);
+ group->_gui = gui;
+ if (gui) gui->_group = group;
+ group->init();
+ Q_ASSERT( !_groups.contains(group->name()) );
+ _groups.insert(group->name(), group);
+ }
+
+private:
+ QMap<QString, const GroupType *> _groups;
+};
+
+} // namespace
+
+#endif
diff --git a/src/common/common/misc.cpp b/src/common/common/misc.cpp
new file mode 100644
index 0000000..1974024
--- /dev/null
+++ b/src/common/common/misc.cpp
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * 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 "misc.h"
+
+#include <unistd.h>
+
+#include <qregexp.h>
+#include <qtimer.h>
+
+#include "number.h"
+
+//-----------------------------------------------------------------------------
+uchar bin2bcd(uchar bin)
+{
+ char h = bin / 10;
+ char l = bin % 10;
+ return (h*16) + l;
+}
+
+uchar bcd2bin(uchar bcd)
+{
+ char h = bcd / 16;
+ char l = bcd % 16;
+ return (h*10) + l;
+}
+
+QString escapeXml(const QString &cs)
+{
+ QString s;
+ for (uint i=0; i<uint(cs.length()); i++) {
+ if ( cs[i]=='<' ) s += "&lt;";
+ else if ( cs[i]=='>' ) s += "&gt;";
+ else s += cs[i];
+ }
+ return s;
+}
+
+QString htmlTableRow(const QString &title, const QString &value)
+{
+ return "<tr><td>" + title + ":</td><td>" + value + "</td></tr>";
+}
+
+void crash(const char *assert, const char *file, int line)
+{
+ qDebug("CRASH_ASSERT: \"%s\" in %s (%d)", assert, file, line);
+ int * ptr = 0;
+ (*ptr)++;
+}
+
+bool checkAvailable(const QByteArray &data, uint offset, uint nbBytes)
+{
+ return ( offset+nbBytes<=uint(data.size()) );
+}
+
+Q_UINT32 getULong(const QByteArray &data, uint offset, uint nbBytes, bool *ok)
+{
+ Q_ASSERT( nbBytes<=8 );
+ if ( !checkAvailable(data, offset, nbBytes) ) {
+ if (ok) *ok = false;
+ return 0;
+ }
+ if (ok) *ok = true;
+ Q_UINT32 r = 0;
+ for (uint i=0; i<nbBytes; i++) r += Q_UINT8(data[offset+i]) << (8*i);
+ return r;
+}
diff --git a/src/common/common/misc.h b/src/common/common/misc.h
new file mode 100644
index 0000000..f8f92f6
--- /dev/null
+++ b/src/common/common/misc.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * 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 MISC_H
+#define MISC_H
+
+#include <qstring.h>
+
+inline QString repeat(const char *r, uint nb)
+{
+ QString s;
+ for (uint i=0; i<nb; i++) s += r;
+ return s;
+}
+
+inline QString stripEndingWhiteSpaces(const QString &s) {
+ int k = s.length()-1;
+ for (; k>=0; k--) if ( s[k]!=' ' ) break;
+ return s.mid(0, k+1);
+}
+
+extern uchar bin2bcd(uchar bin);
+extern uchar bcd2bin(uchar bcd);
+inline bool XOR(bool b1, bool b2) { return ( (!b1 && b2) || (b1 && !b2) ); }
+
+extern bool checkAvailable(const QByteArray &data, uint offset, uint nbBytes);
+extern Q_UINT32 getULong(const QByteArray &data, uint offset, uint nbBytes, bool *ok);
+
+extern QString escapeXml(const QString &s);
+extern QString htmlTableRow(const QString &title, const QString &value);
+extern void crash(const char *assert, const char *file, int line);
+#define CRASH_ASSERT(x) ((x) ? void(0) : crash(#x, __FILE__, __LINE__))
+
+#endif
diff --git a/src/common/common/number.cpp b/src/common/common/number.cpp
new file mode 100644
index 0000000..12fcac0
--- /dev/null
+++ b/src/common/common/number.cpp
@@ -0,0 +1,201 @@
+/***************************************************************************
+ * 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 "number.h"
+
+#include "common/global/global.h"
+#include "misc.h"
+#if !defined(NO_KDE)
+# include <kglobal.h>
+#endif
+
+//-----------------------------------------------------------------------------
+const NumberBase::Data NumberBase::DATA[Nb_Types] = {
+ { 10, "", I18N_NOOP("Decimal"), "dec" },
+ { 16, "0x", I18N_NOOP("Hexadecimal"), "hex" },
+ { 2, "0b", I18N_NOOP("Binary"), "bin" },
+ { 8, "o", I18N_NOOP("Octal"), "oct" },
+ { 256, "", I18N_NOOP("String"), "str" }
+};
+
+char toChar(NumberBase base, uint value)
+{
+ Q_ASSERT( value<base.data().base );
+ if ( value>=base.data().base ) qDebug("toChar %u (%u)", value, base.data().base);
+ if ( base==NumberBase::String ) {
+ if ( !isprint(value) ) return '.';
+ return value;
+ }
+ if ( value<=9 ) return '0' + value;
+ return 'A' + value - 10;
+}
+
+QString toString(NumberBase base, ulong value, uint nbChars)
+{
+ ulong tmp = value;
+ QString s;
+ s.fill(0, nbChars);
+ for (uint i=0; i<nbChars; i++) {
+ s[nbChars-i-1] = toChar(base, uint(value % base.data().base));
+ value /= base.data().base;
+ }
+ Q_ASSERT( value==0 );
+ if ( value!=0 ) qDebug("toString %s nbChars=%u", toLabel(base, tmp, ::nbChars(base, tmp)).latin1(), nbChars);
+ return s;
+}
+
+QString toLabel(NumberBase base, ulong value, uint nbChars)
+{
+ if ( base==NumberBase::String ) return "\'" + toString(base, value, nbChars) + "\'";
+ return base.data().prefix + toString(base, value, nbChars);
+}
+
+uint nbChars(NumberBase base, ulong value)
+{
+ uint nb = 1;
+ for (;;) {
+ value /= base.data().base;
+ if ( value==0 ) break;
+ nb++;
+ }
+ return nb;
+}
+
+ulong maxValue(NumberBase base, uint nbChars)
+{
+ uint v = 1;
+ for (uint i=0; i<nbChars; i++) v *= base.data().base;
+ return v - 1;
+}
+
+ulong fromString(NumberBase base, const QCString &s, bool *ok)
+{
+ return fromString(base, s.data(), s.length(), ok);
+}
+ulong fromString(NumberBase base, const QString &s, bool *ok)
+{
+#if QT_VERSION<0x040000
+ return fromString(base, s.latin1(), s.length(), ok);
+#else
+ QByteArray a = s.toLatin1();
+ return fromString(base, a.data(), a.count(), ok);
+#endif
+}
+
+ulong fromLabel(NumberBase base, const QString &s, bool *ok)
+{
+#if QT_VERSION<0x040000
+ return fromLabel(base, s.latin1(), s.length(), ok);
+#else
+ QByteArray a = s.toLatin1();
+ return fromLabel(base, a.data(), a.count(), ok);
+#endif
+}
+
+ulong fromLabel(NumberBase base, const QString &s, uint nbChars, bool *ok)
+{
+ if ( uint(s.length())!=nbChars+strlen(base.data().prefix) ) {
+ if (ok) *ok = false;
+ return 0;
+ }
+ return fromLabel(base, s, ok);
+}
+
+ulong fromLabel(NumberBase base, const char *s, uint size, bool *ok)
+{
+ if (ok) *ok = false;
+ if ( s==0 ) return 0;
+ uint psize = (base==NumberBase::String ? 1 : strlen(base.data().prefix));
+ uint ssize = (base==NumberBase::String ? 1 : 0);
+ if ( size<=(psize+ssize) ) return 0;
+ if ( base==NumberBase::String ) {
+ if ( s[0]=='"' ) {
+ if ( s[size-1]!='"' ) return 0;
+ } else if ( s[0]=='\'' ) {
+ if ( s[size-1]!='\'' ) return 0;
+ } else return 0;
+ } else for (uint i=0; i<psize; i++) if ( s[i]!=base.data().prefix[i] ) return 0;
+ return fromString(base, s+psize, size-psize-ssize, ok);
+}
+
+ulong fromAnyLabel(const QString &s, bool *ok)
+{
+ uint v = 0;
+ bool bok = false;
+ FOR_EACH(NumberBase, base) {
+ v = fromLabel(base, s.lower(), &bok);
+ if (bok) break;
+ }
+ if ( !bok ) v = fromString(NumberBase::Dec, s, &bok);
+ if ( !bok ) {
+ if (ok) *ok = false;
+ return 0;
+ }
+ if (ok) *ok = true;
+ return v;
+}
+
+uint fromChar(NumberBase base, char c, bool *ok)
+{
+ uint v = 0;
+ if ( base==NumberBase::String ) {
+ if (ok) *ok = true;
+ return c;
+ }
+ if ( c>='0' && c<='9' ) v = c - '0';
+ else if ( c>='A' && c<'Z' ) v = 10 + c - 'A';
+ else if ( c>='a' && c<'z' ) v = 10 + c - 'a';
+ else {
+ if (ok) *ok = false;
+ return 0;
+ }
+ if (ok) *ok = ( v<base.data().base );
+ return v;
+}
+
+ulong fromString(NumberBase base, const char *s, uint size, bool *ok)
+{
+ if (ok) *ok = false;
+ if ( s==0 || size==0 ) return 0;
+ ulong v = 0;
+ for (uint i=0; i<size; i++) {
+ v *= base.data().base;
+ bool bok;
+ v += fromChar(base, s[i], &bok);
+ if ( !bok ) return 0;
+ }
+ if (ok) *ok = true;
+ return v;
+}
+
+QString toLabels(NumberBase base, const QMemArray<uint> &values, uint nbChars)
+{
+ QString s = "[";
+ for (uint i=0; i<values.count(); i++) {
+ if ( i!=0 ) s += ' ';
+ s += toLabel(base, values[i], nbChars);
+ }
+ s += "]";
+ return s;
+}
+
+QString formatNumber(ulong v)
+{
+#if defined(NO_KDE)
+ return QString::number(v);
+#else
+ return KGlobal::locale()->formatNumber(v, 0);
+#endif
+}
+
+QByteArray toAscii(const QString &s)
+{
+ QByteArray a(s.length());
+ for (uint i=0; i<uint(s.length()); i++) a[i] = s[i].latin1();
+ return a;
+}
diff --git a/src/common/common/number.h b/src/common/common/number.h
new file mode 100644
index 0000000..f4dae79
--- /dev/null
+++ b/src/common/common/number.h
@@ -0,0 +1,92 @@
+/***************************************************************************
+ * 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 NUMBER_H
+#define NUMBER_H
+
+#include <ctype.h>
+
+#include "common/global/global.h"
+#include "key_enum.h"
+
+//----------------------------------------------------------------------------
+struct NumberBaseData {
+ uint base;
+ const char *prefix, *label,* key;
+};
+
+BEGIN_DECLARE_ENUM(NumberBase)
+ Dec = 0, Hex, Bin, Oct, String
+END_DECLARE_ENUM(NumberBase, NumberBaseData)
+
+extern uint nbChars(NumberBase base, ulong value);
+extern ulong maxValue(NumberBase base, uint nbChars);
+inline uint convertNbChars(uint nb, NumberBase from, NumberBase to) { return nbChars(to, maxValue(from, nb)); }
+
+extern char toChar(NumberBase base, uint value);
+extern QString toString(NumberBase base, ulong value, uint nbChars);
+extern QString toLabel(NumberBase base, ulong value, uint nbChars);
+extern QString toLabels(NumberBase base, const QMemArray<ulong> &values, uint nbChars);
+
+extern uint fromChar(NumberBase base, char c, bool *ok);
+extern ulong fromString(NumberBase base, const char *s, uint size, bool *ok);
+extern ulong fromString(NumberBase base, const QString &s, bool *ok);
+extern ulong fromLabel(NumberBase base, const QString &s, bool *ok);
+extern ulong fromLabel(NumberBase base, const QString &s, uint nbChars, bool *ok);
+extern ulong fromLabel(NumberBase base, const char *s, uint size, bool *ok);
+
+extern ulong fromAnyLabel(const QString &s, bool *ok);
+
+//----------------------------------------------------------------------------
+inline QString toHex(ulong value, uint nbChars) { return toString(NumberBase::Hex, value, nbChars); }
+inline QString toHexLabel(ulong value, uint nbChars) { return toLabel(NumberBase::Hex, value, nbChars); }
+inline QString toHexLabelAbs(ulong value) { return toLabel(NumberBase::Hex, value, nbChars(NumberBase::Hex, value)); }
+
+inline uint fromHex(char c, bool *ok) { return fromChar(NumberBase::Hex, c, ok); }
+inline uint fromHex(QChar c, bool *ok) { return fromChar(NumberBase::Hex, c.latin1(), ok); }
+inline ulong fromHex(const char *s, uint size, bool *ok) { return fromString(NumberBase::Hex, s, size, ok); }
+inline ulong fromHex(const QString &s, bool *ok) { return fromString(NumberBase::Hex, s, ok); }
+inline ulong fromHexLabel(const QString &s, bool *ok) { return fromLabel(NumberBase::Hex, s, ok); }
+inline ulong fromHexLabel(const QString &s, uint nbChars, bool *ok) { return fromLabel(NumberBase::Hex, s, nbChars, ok); }
+inline ulong fromHexLabel(const char *s, uint size, bool *ok) { return fromLabel(NumberBase::Hex, s, size, ok); }
+
+//----------------------------------------------------------------------------
+inline uint nbBits(ulong value) { return nbChars(NumberBase::Bin, value); }
+inline uint nbBitsToNbChars(uint nbBits) { return nbBits/4 + (nbBits%4 ? 1 : 0); }
+inline uint nbBitsToNbBytes(uint nbBits) { return nbBits/8 + (nbBits%8 ? 1 : 0); }
+inline uint nbChars(ulong value) { return nbBitsToNbChars(nbBits(value)); }
+inline uint nbBytes(ulong value) { return nbBitsToNbBytes(nbBits(value)); }
+
+//----------------------------------------------------------------------------
+extern QString formatNumber(ulong v);
+extern QByteArray toAscii(const QString &s);
+
+//----------------------------------------------------------------------------
+enum PrintMode { PrintAlphaNum, PrintEscapeAll };
+inline QString toPrintable(char c, PrintMode mode)
+{
+ if ( mode==PrintAlphaNum && isalnum(c) ) return QChar(c);
+ return "\\" + toHex(uchar(c), 2);
+}
+inline QString toPrintable(const char *data, uint size, PrintMode mode)
+{
+ QString s;
+ for (uint i=0; i<size; i++) s += toPrintable(data[i], mode);
+ return s;
+}
+inline QString toPrintable(const QString &s, PrintMode mode)
+{
+ QByteArray a = toAscii(s);
+ return toPrintable(a.data(), a.count(), mode);
+}
+inline QString toPrintable(const QMemArray<uchar> &data, PrintMode mode)
+{
+ return toPrintable((const char *)data.data(), data.size(), mode);
+}
+
+#endif
diff --git a/src/common/common/purl_base.cpp b/src/common/common/purl_base.cpp
new file mode 100644
index 0000000..2493322
--- /dev/null
+++ b/src/common/common/purl_base.cpp
@@ -0,0 +1,133 @@
+/***************************************************************************
+ * 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_base.h"
+
+#include "common/global/global.h"
+#include <qfileinfo.h>
+
+#include "data/xpms/project.xpm"
+#include "data/xpms/sourcefile.xpm"
+#include "data/xpms/includefile.xpm"
+#include "data/xpms/objectfile.xpm"
+
+const PURL::ToolType::Data PURL::ToolType::DATA[Nb_Types] = {
+ { "assembler", I18N_NOOP("Assembler") },
+ { "compiler", I18N_NOOP("Compiler") }
+};
+
+const PURL::SourceFamily::Data PURL::SourceFamily::DATA[Nb_Types] = {
+ { ToolType::Assembler, "asm", I18N_NOOP("Assembler"), Inc },
+ { ToolType::Compiler, "c", I18N_NOOP("C Compiler"), CHeader },
+ { ToolType::Compiler, "jal", I18N_NOOP("JAL Compiler"), Nb_FileTypes },
+ { ToolType::Compiler, "cpp", I18N_NOOP("C++ Compiler"), CHeader },
+ { ToolType::Compiler, "basic", I18N_NOOP("Basic Compiler"), Nb_FileTypes }
+};
+
+const PURL::FileType::Data PURL::FileType::DATA[Nb_Types] = {
+ { "AsmGPAsm", Source, Editable, SourceFamily::Asm, I18N_NOOP("Assembler File"), { "asm", "src", "pic", 0 }, sourcefile_xpm, 0, "XPicAsm" },
+ { "AsmPIC30", Source, Editable, SourceFamily::Asm, I18N_NOOP("Assembler File for PIC30"), { "s", 0 }, sourcefile_xpm, 0, "XPicAsm" },
+ { "AsmPICC", Source, Editable, SourceFamily::Asm, I18N_NOOP("Assembler File for PICC"), { "as", 0 }, sourcefile_xpm, 0, "XPicAsm" },
+ { "Inc", Header, Editable, SourceFamily::Asm, I18N_NOOP("Include File"), { "inc", 0 }, includefile_xpm, 0, "XPicAsm" },
+ { "CSource", Source, Editable, SourceFamily::C, I18N_NOOP("C Source File"), { "c", 0 }, 0, "text/x-csrc", "C" },
+ { "CppSource", Source, Editable, SourceFamily::C, I18N_NOOP("C++ Source File"), { "cpp", "cxx", 0 }, 0, "text/x-c++src", "C++" },
+ { "CHeader", Header, Editable, SourceFamily::C, I18N_NOOP("C Header File"), { "h", 0 }, 0, "text/x-chdr", "C" },
+ { "JalSource", Source, Editable, SourceFamily::JAL, I18N_NOOP("JAL File"), { "jal", 0}, sourcefile_xpm, 0, "XPicJal" },
+ { "BasicSource", Source, Editable, SourceFamily::Basic, I18N_NOOP("Basic Source File"), { "bas", 0 }, sourcefile_xpm, 0, "FreeBASIC" },
+
+ { "Object", LinkerObject, Editable | ReadOnly, SourceFamily::Nb_Types, I18N_NOOP("Object File"), { "o", "obj", 0 }, objectfile_xpm, 0, 0 },
+ { "Library", LinkerObject, Editable | ReadOnly, SourceFamily::Nb_Types, I18N_NOOP("Library File"), { "a", "lib", 0 }, objectfile_xpm, 0, 0 },
+
+ { "Lkr", LinkerScript, Editable, SourceFamily::Nb_Types, I18N_NOOP("Linker Script"), { "lkr", 0 }, includefile_xpm, 0, 0 },
+ { "Gld", LinkerScript, Editable, SourceFamily::Nb_Types, I18N_NOOP("Linker Script for PIC30"), { "gld", 0 }, includefile_xpm, 0, 0 },
+
+ { "Hex", Nb_FileGroups, Editable, SourceFamily::Nb_Types, I18N_NOOP("Hex File"), { "hex", 0 }, 0, "text/x-hex", 0 },
+ { "Elf", Nb_FileGroups, ReadOnly, SourceFamily::Nb_Types, I18N_NOOP("Elf File"), { "elf", 0 }, 0, 0, 0 },
+ { "Project", Nb_FileGroups, NoProperty, SourceFamily::Nb_Types, I18N_NOOP("Project File"), { "piklab", 0 }, project_xpm, 0, 0 },
+ { "Lst", Nb_FileGroups, Editable | ReadOnly, SourceFamily::Nb_Types, I18N_NOOP("List File"), { "lst", 0 }, 0, "text/plain", 0 },
+ { "Map", Nb_FileGroups, Editable | ReadOnly, SourceFamily::Nb_Types, I18N_NOOP("Map File"), { "map", 0 }, 0, "text/plain", 0 },
+ { "Cod", Nb_FileGroups, ReadOnly, SourceFamily::Nb_Types, I18N_NOOP("COD File"), { "cod", 0 }, 0, 0, 0 },
+ { "Coff", Nb_FileGroups, Editable | ReadOnly, SourceFamily::Nb_Types, I18N_NOOP("COFF File"), { "cof", 0 }, 0, "application/x-object", "XCoffDisasm" },
+
+ { "", Nb_FileGroups, NoProperty, SourceFamily::Nb_Types, I18N_NOOP("Unknown File"), { 0 }, 0, 0, 0 },
+ { "", Nb_FileGroups, NoProperty, SourceFamily::Nb_Types, I18N_NOOP("Pikdev Project File"), { "pikprj", 0 }, 0, 0, 0 }
+};
+
+QString PURL::addExtension(const QString &filename, FileType type)
+{
+ QFileInfo info(filename);
+ if ( !info.extension().isEmpty() ) return filename;
+ return filename + '.' + extension(type);
+}
+
+QString PURL::extension(FileType type)
+{
+ return type.data().extensions[0];
+}
+
+QString PURL::extensions(FileType type)
+{
+ Q_ASSERT( type!=PURL::Nb_FileTypes );
+ QString s;
+ for (uint i=0; type.data().extensions[i]; i++) {
+ if ( i!=0 ) s += ' ';
+ s += QString("*.") + type.data().extensions[i];
+ }
+ return s;
+}
+
+QString PURL::filter(FileType type)
+{
+ //if ( hasMimetype(type) ) return DATA[type].mimetype; // #### we cannot mix mimetype and regular filters in KFileDialog...
+ QString s = extensions(type);
+ return s + ' ' + s.upper() + '|' + type.label() + " (" + s + ")";
+}
+
+QString PURL::extensions(FileGroup group)
+{
+ QString e;
+ FOR_EACH(FileType, type) {
+ if ( type.data().group!=group ) continue;
+ if ( type!=FileType::Type(0) ) e += ' ';
+ QString s = extensions(type);
+ e += s + ' ' + s.upper();
+ }
+ return e;
+}
+
+QString PURL::sourceFilter(FilterType type)
+{
+ QString f = extensions(Source) + ' ' + extensions(Header) + '|' + i18n("All Source Files");
+ if ( type==CompleteFilter) {
+ FOR_EACH(FileType, type) {
+ if ( !(type.data().properties & (Source | Header)) ) continue;
+ f += '\n' + filter(type);
+ }
+ }
+ return f;
+}
+
+QString PURL::objectFilter(FilterType type)
+{
+ QString f = extensions(Object) + ' ' + extensions(Library) + '|' + i18n("All Object Files");
+ if ( type==CompleteFilter ) {
+ f += '\n' + filter(Object);
+ f += '\n' + filter(Library);
+ }
+ return f;
+}
+
+QString PURL::projectFilter(FilterType type)
+{
+ QString f = extensions(Project) + ' ' + extensions(PikdevProject) + '|' + i18n("Project Files");
+ if ( type==CompleteFilter ) {
+ f += '\n' + filter(Project);
+ f += '\n' + filter(PikdevProject);
+ }
+ return f;
+}
diff --git a/src/common/common/purl_base.h b/src/common/common/purl_base.h
new file mode 100644
index 0000000..7a7e4ea
--- /dev/null
+++ b/src/common/common/purl_base.h
@@ -0,0 +1,79 @@
+/***************************************************************************
+ * 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_BASE_H
+#define PURL_BASE_H
+
+#include "common/global/global.h"
+#include "common/common/key_enum.h"
+
+//----------------------------------------------------------------------------
+namespace PURL
+{
+BEGIN_DECLARE_ENUM(ToolType)
+ Assembler = 0, Compiler
+END_DECLARE_ENUM_STD(ToolType)
+
+enum FileTypeEnum {
+ AsmGPAsm = 0, AsmPIC30, AsmPICC, Inc, CSource, CppSource, CHeader, JalSource, BasicSource,
+ Object, Library, Lkr, Gld, Hex, Elf, Project, Lst, Map, Cod, Coff,
+ Unknown, PikdevProject,
+ Nb_FileTypes
+};
+
+struct SourceFamilyData {
+ ToolType toolType;
+ const char *key, *label;
+ FileTypeEnum headerType;
+};
+BEGIN_DECLARE_ENUM(SourceFamily)
+ Asm = 0, C, JAL, Cpp, Basic
+END_DECLARE_ENUM(SourceFamily, SourceFamilyData)
+
+enum FileGroup { Source = 0, Header, LinkerScript, LinkerObject, Nb_FileGroups };
+
+enum FileProperty { NoProperty = 0, Editable = 1, ReadOnly = 2 };
+Q_DECLARE_FLAGS(FileProperties, FileProperty)
+Q_DECLARE_OPERATORS_FOR_FLAGS(FileProperties)
+
+struct FileTypeData {
+ const char *key;
+ FileGroup group;
+ FileProperties properties;
+ SourceFamily sourceFamily;
+ const char *label;
+ const char *extensions[10];
+ const char **xpm_icon;
+ const char *mimetype;
+ const char *highlightModeName;
+};
+#ifndef Q_MOC_RUN // needed because MOC does not expand defines...
+class FileType : public GenericEnum
+{
+public:
+ typedef FileTypeEnum Type;
+ enum { Nb_Types = Nb_FileTypes };
+ typedef FileTypeData Data;
+DECLARE_DATA
+DECLARE_ENUM_CLASS(FileType)
+#endif
+
+// add correct extension if filename has no extension
+extern QString addExtension(const QString &filename, FileType type);
+extern QString extension(FileType type);
+extern QString extensions(FileType type);
+extern QString filter(FileType type);
+enum FilterType { SimpleFilter, CompleteFilter };
+extern QString sourceFilter(FilterType type);
+extern QString objectFilter(FilterType type);
+extern QString projectFilter(FilterType type);
+extern QString extensions(FileGroup group);
+
+} // namespace
+
+#endif
diff --git a/src/common/common/qflags.h b/src/common/common/qflags.h
new file mode 100644
index 0000000..4858ce4
--- /dev/null
+++ b/src/common/common/qflags.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+**
+** Copyright (C) 1992-2005 Trolltech AS. All rights reserved.
+**
+** This file is part of the QtCore module of the Qt Toolkit.
+**
+** This file may be used under the terms of the GNU General Public
+** License version 2.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of
+** this file. Please review the following information to ensure GNU
+** General Public Licensing requirements will be met:
+** http://www.trolltech.com/products/qt/opensource.html
+**
+** If you are unsure which license is appropriate for your use, please
+** review the following information:
+** http://www.trolltech.com/products/qt/licensing.html or contact the
+** sales department at sales@trolltech.com.
+**
+** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
+** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+**
+****************************************************************************/
+#ifndef QFLAGS_H
+#define QFLAGS_H
+
+#include <qglobal.h>
+
+class QFlag
+{
+ int i;
+public:
+ inline QFlag(int i);
+ inline operator int() const { return i; }
+};
+
+inline QFlag::QFlag(int ai) : i(ai) {}
+
+template<typename Enum>
+class QFlags
+{
+ typedef void **Zero;
+ int i;
+public:
+ typedef Enum enum_type;
+ inline QFlags(const QFlags &f) : i(f.i) {}
+ inline QFlags(Enum f) : i(f) {}
+ inline QFlags(Zero = 0) : i(0) {}
+ inline QFlags(QFlag f) : i(f) {}
+
+ inline QFlags &operator=(const QFlags &f) { i = f.i; return *this; }
+ inline QFlags &operator&=(int mask) { i &= mask; return *this; }
+ inline QFlags &operator&=(uint mask) { i &= mask; return *this; }
+ inline QFlags &operator|=(QFlags f) { i |= f.i; return *this; }
+ inline QFlags &operator|=(Enum f) { i |= f; return *this; }
+ inline QFlags &operator^=(QFlags f) { i ^= f.i; return *this; }
+ inline QFlags &operator^=(Enum f) { i ^= f; return *this; }
+
+
+ inline operator int() const { return i;}
+
+ inline QFlags operator|(QFlags f) const { QFlags g; g.i = i | f.i; return g; }
+ inline QFlags operator|(Enum f) const { QFlags g; g.i = i | f; return g; }
+ inline QFlags operator^(QFlags f) const { QFlags g; g.i = i ^ f.i; return g; }
+ inline QFlags operator^(Enum f) const { QFlags g; g.i = i ^ f; return g; }
+ inline QFlags operator&(int mask) const { QFlags g; g.i = i & mask; return g; }
+ inline QFlags operator&(uint mask) const { QFlags g; g.i = i & mask; return g; }
+ inline QFlags operator&(Enum f) const { QFlags g; g.i = i & f; return g; }
+ inline QFlags operator~() const { QFlags g; g.i = ~i; return g; }
+
+ inline bool operator!() const { return !i; }
+};
+
+#define Q_DECLARE_FLAGS(Flags, Enum)\
+typedef QFlags<Enum> Flags;
+#define Q_DECLARE_OPERATORS_FOR_FLAGS(Flags) \
+inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, Flags::enum_type f2) \
+{ return QFlags<Flags::enum_type>(f1) | f2; } \
+inline QFlags<Flags::enum_type> operator|(Flags::enum_type f1, QFlags<Flags::enum_type> f2) \
+{ return f2 | f1; }
+
+#endif
diff --git a/src/common/common/range.h b/src/common/common/range.h
new file mode 100644
index 0000000..e07cb68
--- /dev/null
+++ b/src/common/common/range.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * 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 RANGE_H
+#define RANGE_H
+
+#include "common/global/global.h"
+
+//-----------------------------------------------------------------------------
+template <typename Type>
+class GenericRange
+{
+public:
+ virtual ~GenericRange() {}
+ virtual bool isEmpty() const = 0;
+ bool contains(Type v) const { return !isEmpty() && v>=start && v<=end; }
+
+ Type start, end;
+};
+
+class Range : public GenericRange<uint>
+{
+public:
+ Range() { start = 0; end = 0; }
+ Range(uint s, uint e) { start = s; end = e; }
+ virtual bool isEmpty() const { return end<=start; }
+};
+
+template <typename Type>
+inline QDataStream &operator >>(QDataStream &s, GenericRange<Type> &r) { s >> r.start >> r.end; return s; }
+template <typename Type>
+inline QDataStream &operator <<(QDataStream &s, const GenericRange<Type> &r) { s << r.start << r.end; return s; }
+template <typename Type>
+inline bool operator ==(const GenericRange<Type> &r1, const GenericRange<Type> &r2) { return ( r1.start==r2.start && r1.end==r2.end ); }
+
+template <typename Type, typename RangeType>
+class GenericRangeVector : public QValueVector<RangeType>
+{
+public:
+ GenericRangeVector() {}
+ GenericRangeVector(const RangeType &range) { append(range); }
+ bool isEmpty() const {
+ uint nb = this->count();
+ for (uint i=0; i<nb; i++) if ( !this->at(i).isEmpty() ) return false;
+ return true;
+ }
+ bool contains(Type v) const {
+ uint nb = this->count();
+ for (uint i=0; i<nb; i++) if ( this->at(i).contains(v) ) return true;
+ return false;
+ }
+};
+
+typedef GenericRangeVector<uint, Range> RangeVector;
+
+#endif
diff --git a/src/common/common/storage.cpp b/src/common/common/storage.cpp
new file mode 100644
index 0000000..00137b8
--- /dev/null
+++ b/src/common/common/storage.cpp
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * 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 "storage.h"
+
+#include <qtimer.h>
+
+//----------------------------------------------------------------------------
+void GenericStorage::delayedChanged()
+{
+ if (_dirty) return;
+ _dirty = true;
+ QTimer::singleShot(0, this, SLOT(changedSlot()));
+}
+
+void GenericStorage::changedSlot()
+{
+ _dirty = false;
+ emit changed();
+}
+
+//----------------------------------------------------------------------------
+void GenericViewProxy::addStorage(GenericStorage &storage)
+{
+ connect(&storage, SIGNAL(changed()), SLOT(changed()));
+}
+
+void GenericViewProxy::changed()
+{
+ _view.updateView();
+}
+
+GenericView::GenericView(GenericStorage &storage)
+{
+ _proxy = new GenericViewProxy(*this);
+ _proxy->addStorage(storage);
+}
diff --git a/src/common/common/storage.h b/src/common/common/storage.h
new file mode 100644
index 0000000..b61123a
--- /dev/null
+++ b/src/common/common/storage.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * 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 STORAGE_H
+#define STORAGE_H
+
+#include "common/global/global.h"
+#include <qobject.h>
+
+//-----------------------------------------------------------------------------
+template <class Type>
+class Fifo
+{
+public:
+ Fifo() {}
+ void clear() { _list.clear(); }
+ uint count() const { return _list.count(); }
+ void put(Type type) { _list.append(type); }
+ Type get() {
+ Type t = _list.first();
+ _list.pop_front();
+ return t;
+ }
+
+private:
+ QValueList<Type> _list;
+};
+
+//----------------------------------------------------------------------------
+class GenericStorage : public QObject
+{
+Q_OBJECT
+public:
+ GenericStorage(QObject *parent = 0, const char *name = 0) : QObject(parent, name), _dirty(false) {}
+
+signals:
+ void changed();
+
+protected:
+ // emit changed() only after a return to the GUI loop and only one time
+ void delayedChanged();
+
+private slots:
+ void changedSlot();
+
+private:
+ bool _dirty;
+};
+
+//----------------------------------------------------------------------------
+class GenericView;
+
+class GenericViewProxy : public QObject
+{
+Q_OBJECT
+public:
+ GenericViewProxy(GenericView &view) : _view(view) {}
+ void addStorage(GenericStorage &storage);
+
+private slots:
+ void changed();
+
+private:
+ GenericView &_view;
+};
+
+class GenericView
+{
+public:
+ GenericView(GenericStorage &storage);
+ virtual ~GenericView() { delete _proxy; }
+ virtual void updateView() = 0;
+
+private:
+ GenericViewProxy *_proxy;
+
+ friend class GenericViewProxy;
+};
+
+#endif
diff --git a/src/common/common/streamer.h b/src/common/common/streamer.h
new file mode 100644
index 0000000..93d1421
--- /dev/null
+++ b/src/common/common/streamer.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * 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 STREAMER_H
+#define STREAMER_H
+
+#include <qdatastream.h>
+#include <qtextstream.h>
+
+#include "common/global/global.h"
+#include "common/common/number.h"
+
+template <class DataType>
+class DataStreamer
+{
+public:
+ uint toCppString(const QValueList<DataType *> &list, QTextStream &s) {
+ QByteArray a;
+#if QT_VERSION<0x040000
+ QDataStream ds(a, IO_WriteOnly);
+#else
+ QDataStream ds(&a, QIODevice::WriteOnly);
+#endif
+ for (uint i=0; i<uint(list.count()); i++) ds << *list[i];
+ s << "\"";
+ for (uint i=0; i<uint(a.count()); i++) {
+ if ( i!=0 && (i%40)==0 ) s << "\"" << endl << "\"";
+ s << "\\x" << toChar(NumberBase::Hex, uchar(a[i])/16) << toChar(NumberBase::Hex, uchar(a[i])%16);
+ }
+ s << "\"";
+ return a.count();
+ }
+
+ QValueList<DataType *> fromCppString(const char *data, uint size) {
+ QByteArray a;
+ a.setRawData(data, size);
+#if QT_VERSION<0x040000
+ QDataStream ds(a, IO_ReadOnly);
+#else
+ QDataStream ds(&a, QIODevice::ReadOnly);
+#endif
+ QValueList<DataType *> list;
+ for (;;) {
+ if ( ds.atEnd() ) break;
+ DataType *data = new DataType;
+ ds >> *data;
+ list.append(data);
+ }
+ a.resetRawData(data, size);
+ return list;
+ }
+};
+
+#endif
diff --git a/src/common/common/synchronous.cpp b/src/common/common/synchronous.cpp
new file mode 100644
index 0000000..f392103
--- /dev/null
+++ b/src/common/common/synchronous.cpp
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * 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 "synchronous.h"
+
+#include "common/global/global.h"
+#if QT_VERSION<0x040000
+# include <qwidget.h>
+#endif
+
+Synchronous::Synchronous(uint timeout)
+{
+ connect(&_timer, SIGNAL(timeout()), SLOT(done()));
+ if (timeout) _timer.start(timeout, true);
+#if QT_VERSION>=0x040000
+ _loop = new QEventLoop(this);
+#endif
+}
+
+#if QT_VERSION<0x040000
+// uplifted from kdelibs...
+void qt_enter_modal(QWidget *widget);
+void qt_leave_modal(QWidget *widget);
+#endif
+
+bool Synchronous::enterLoop()
+{
+#if QT_VERSION<0x040000
+ QWidget *dummy = 0;
+ if ( qApp->type()!=QApplication::Tty ) {
+ dummy = new QWidget(0, 0, WType_Dialog | WShowModal);
+ dummy->setFocusPolicy(QWidget::NoFocus);
+ qt_enter_modal(dummy);
+ }
+ QApplication::eventLoop()->enterLoop();
+ if ( qApp->type()!=QApplication::Tty ) {
+ qt_leave_modal(dummy);
+ delete dummy;
+ }
+#else
+ _loop->exec();
+#endif
+ return _timer.isActive();
+}
+
+void Synchronous::done()
+{
+#if QT_VERSION<0x040000
+ QApplication::eventLoop()->exitLoop();
+#else
+ _loop->exit();
+#endif
+}
diff --git a/src/common/common/synchronous.h b/src/common/common/synchronous.h
new file mode 100644
index 0000000..e855e38
--- /dev/null
+++ b/src/common/common/synchronous.h
@@ -0,0 +1,32 @@
+/***************************************************************************
+ * 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 SYNCHRONOUS_H
+#define SYNCHRONOUS_H
+
+#include <qtimer.h>
+#include <qeventloop.h>
+
+class Synchronous : public QObject
+{
+Q_OBJECT
+public:
+ Synchronous(uint timeout = 0); // timeout is ms (0 == no timeout)
+ bool enterLoop(); // return false on timeout
+
+public slots:
+ void done();
+
+private:
+ QTimer _timer;
+#if QT_VERSION>=0x040000
+ QEventLoop *_loop;
+#endif
+};
+
+#endif
diff --git a/src/common/common/version_data.cpp b/src/common/common/version_data.cpp
new file mode 100644
index 0000000..481ba1a
--- /dev/null
+++ b/src/common/common/version_data.cpp
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * 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 "version_data.h"
+
+#include <qregexp.h>
+
+#include "number.h"
+
+VersionData VersionData::fromString(const QString &s)
+{
+ VersionData vd;
+ QRegExp re("([0-9]+)\\.([0-9]+)\\.([0-9]+)(.*)");
+ if ( !re.exactMatch(s) ) return vd;
+ vd._valid = true;
+ vd._majorNum = re.cap(1).toUInt();
+ vd._minorNum = re.cap(2).toUInt();
+ vd._dotNum = re.cap(3).toUInt();
+ vd._sub = re.cap(4);
+ return vd;
+}
+
+VersionData VersionData::fromHexString(const QString &s)
+{
+ VersionData vd;
+ if ( s.length()!=6 ) return vd;
+ vd._valid = true;
+ vd._majorNum = ::fromString(NumberBase::Hex, s.mid(0, 2), 0);
+ vd._minorNum = ::fromString(NumberBase::Hex, s.mid(2, 2), 0);
+ vd._dotNum = ::fromString(NumberBase::Hex, s.mid(4, 2), 0);
+ return vd;
+}
+
+QString VersionData::pretty() const
+{
+ if ( !isValid() ) return "---";
+ return QString::number(_majorNum) + '.' + QString::number(_minorNum) + '.' + QString::number(_dotNum) + _sub;
+}
+
+QString VersionData::prettyWithoutDot() const
+{
+ if ( !isValid() ) return "---";
+ return QString::number(_majorNum) + '.' + QString::number(_minorNum);
+}
+
+uint VersionData::toUInt() const
+{
+ Q_ASSERT(_valid);
+ return (_majorNum << 16) | (_minorNum << 8) | _dotNum;
+}
diff --git a/src/common/common/version_data.h b/src/common/common/version_data.h
new file mode 100644
index 0000000..2571631
--- /dev/null
+++ b/src/common/common/version_data.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * 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 VERSION_DATA_H
+#define VERSION_DATA_H
+
+#include "common/global/global.h"
+
+class VersionData
+{
+public:
+ static VersionData fromString(const QString &s);
+ static VersionData fromHexString(const QString &s);
+
+public:
+ VersionData() : _valid(false) {}
+ VersionData(uchar majorNum, uchar minorNum, uchar dotNum)
+ : _valid(true), _majorNum(majorNum), _minorNum(minorNum), _dotNum(dotNum) {}
+ bool isValid() const { return _valid; }
+ void clear() { _valid = false; }
+ uchar majorNum() const { return _majorNum; }
+ uchar minorNum() const { return _minorNum; }
+ uchar dotNum() const { return _dotNum; }
+ QString sub() const { return _sub; }
+ VersionData toWithoutDot() const { return VersionData(_majorNum, _minorNum, 0); }
+ QString pretty() const;
+ QString prettyWithoutDot() const;
+ uint toUInt() const;
+ bool operator <(const VersionData &vd) const { return toUInt()<vd.toUInt(); }
+ bool operator <=(const VersionData &vd) const { return toUInt()<=vd.toUInt(); }
+ bool operator >(const VersionData &vd) const { return toUInt()>vd.toUInt(); }
+ bool operator >=(const VersionData &vd) const { return toUInt()>=vd.toUInt(); }
+ bool operator ==(const VersionData &vd) const { return toUInt()==vd.toUInt(); }
+ bool operator !=(const VersionData &vd) const { return toUInt()!=vd.toUInt(); }
+
+private:
+ bool _valid;
+ uchar _majorNum, _minorNum, _dotNum;
+ QString _sub;
+};
+
+#endif
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
diff --git a/src/common/gui/Makefile.am b/src/common/gui/Makefile.am
new file mode 100644
index 0000000..c4bb948
--- /dev/null
+++ b/src/common/gui/Makefile.am
@@ -0,0 +1,7 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+libcommonui_la_LDFLAGS = $(all_libraries)
+noinst_LTLIBRARIES = libcommonui.la
+libcommonui_la_SOURCES = container.cpp dialog.cpp editlistbox.cpp \
+ hexword_gui.cpp list_view.cpp misc_gui.cpp number_gui.cpp pfile_ext.cpp purl_ext.cpp \
+ purl_gui.cpp list_container.cpp
diff --git a/src/common/gui/config_widget.h b/src/common/gui/config_widget.h
new file mode 100644
index 0000000..abfafab
--- /dev/null
+++ b/src/common/gui/config_widget.h
@@ -0,0 +1,107 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * *
+ * 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 CONFIG_WIDGET_H
+#define CONFIG_WIDGET_H
+
+#include <qpixmap.h>
+#include <qcheckbox.h>
+#include <qvaluevector.h>
+#include <qvariant.h>
+
+#include "container.h"
+
+//-----------------------------------------------------------------------------
+class ConfigWidget : public Container
+{
+Q_OBJECT
+public:
+ ConfigWidget(QWidget *parent = 0) : Container(parent) {}
+ virtual QString title() const { return QString::null; }
+ virtual QString header() const { return QString::null; }
+ virtual QPixmap pixmap() const { return QPixmap(); }
+
+public slots:
+ virtual void loadConfig() = 0;
+ virtual void saveConfig() = 0;
+};
+
+//-----------------------------------------------------------------------------
+template <typename Type>
+class BaseConfigWidget
+{
+public:
+ BaseConfigWidget(ConfigWidget *widget) {
+ _widgets.resize(Type::Nb_Types);
+ for(Type type; type<Type::Nb_Types; ++type) _widgets[type.type()] = createWidget(type, widget);
+ }
+ void loadConfig() {
+ for(Type type; type<Type::Nb_Types; ++type) load(type, _widgets[type.type()]);
+ }
+ void saveConfig() {
+ for(Type type; type<Type::Nb_Types; ++type) save(type, _widgets[type.type()]);
+ }
+ void setDefault() {
+ for(Type type; type<Type::Nb_Types; ++type) setDefault(type, _widgets[type.type()]);
+ }
+
+private:
+ QValueVector<QWidget *> _widgets;
+
+ static QWidget *createWidget(Type type, ConfigWidget *widget) {
+ QWidget *w = 0;
+ uint row = widget->numRows();
+ switch (type.data().defValue.type()) {
+ case QVariant::Bool:
+ w = new QCheckBox(type.label(), widget);
+ widget->addWidget(w, row,row, 0,1);
+ break;
+ default: Q_ASSERT(false); break;
+ }
+ return w;
+ }
+ void load(Type type, QWidget *widget) const {
+ switch (type.data().defValue.type()) {
+ case QVariant::Bool:
+ static_cast<QCheckBox *>(widget)->setChecked(readConfigEntry(type).toBool());
+ break;
+ default: Q_ASSERT(false); break;
+ }
+ }
+ void save(Type type, QWidget *widget) {
+ switch (type.data().defValue.type()) {
+ case QVariant::Bool:
+ writeConfigEntry(type, QVariant(static_cast<QCheckBox *>(widget)->isChecked(), 0));
+ break;
+ default: Q_ASSERT(false); break;
+ }
+ }
+ void setDefault(Type type, QWidget *widget) const {
+ switch (type.data().defValue.type()) {
+ case QVariant::Bool:
+ static_cast<QCheckBox *>(widget)->setChecked(type.data().defValue.toBool());
+ break;
+ default: Q_ASSERT(false); break;
+ }
+ }
+};
+
+//-----------------------------------------------------------------------------
+#define BEGIN_DECLARE_CONFIG_WIDGET(ConfigType, ConfigWidgetType) \
+class ConfigWidgetType : public ::ConfigWidget, public BaseConfigWidget<ConfigType> \
+{ \
+public: \
+ ConfigWidgetType() : BaseConfigWidget<ConfigType>(this) {} \
+ virtual void loadConfig() { BaseConfigWidget<ConfigType>::loadConfig(); } \
+ virtual void saveConfig() { BaseConfigWidget<ConfigType>::saveConfig(); } \
+
+#define END_DECLARE_CONFIG_WIDGET \
+};
+
+#endif
diff --git a/src/common/gui/container.cpp b/src/common/gui/container.cpp
new file mode 100644
index 0000000..881e265
--- /dev/null
+++ b/src/common/gui/container.cpp
@@ -0,0 +1,80 @@
+/***************************************************************************
+ * 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 "container.h"
+
+#include "misc_gui.h"
+
+//----------------------------------------------------------------------------
+Container::Container(QWidget *parent, Type type)
+ : QFrame(parent), _type(type)
+{
+ initLayout();
+}
+
+Container::Container(QWidgetStack *stack, uint index, Type type)
+ : QFrame(stack), _type(type)
+{
+ initLayout();
+ stack->addWidget(this, index);
+}
+
+Container::Container(QTabWidget *tabw, const QString &title, Type type)
+ : QFrame(tabw), _type(type)
+{
+ initLayout();
+ tabw->addTab(this, title);
+}
+
+void Container::setFrame(Type type)
+{
+ _type = type;
+ switch (type) {
+ case Flat:
+ setMargin(parent() && parent()->inherits("QTabWidget") ? 10 : 0);
+ setFrameStyle(QFrame::NoFrame);
+ break;
+ case Sunken:
+ setMargin(10);
+ setFrameStyle(QFrame::StyledPanel | QFrame::Sunken);
+ break;
+ }
+}
+
+void Container::initLayout()
+{
+ _topLayout = new QGridLayout(this, 1, 1, 0, 10);
+ _gridLayout = new QGridLayout(1, 1, 10);
+ _topLayout->addLayout(_gridLayout, 0, 0);
+ _topLayout->setRowStretch(1, 1);
+ setFrame(_type);
+}
+
+void Container::addWidget(QWidget *w, uint startRow, uint endRow, uint startCol, uint endCol, int alignment)
+{
+ Q_ASSERT( startRow<=endRow );
+ Q_ASSERT( startCol<=endCol );
+ w->show();
+ _gridLayout->addMultiCellWidget(w, startRow, endRow, startCol, endCol, alignment);
+}
+
+void Container::addLayout(QLayout *l, uint startRow, uint endRow, uint startCol, uint endCol, int alignment)
+{
+ Q_ASSERT( startRow<=endRow );
+ Q_ASSERT( startCol<=endCol );
+ _gridLayout->addMultiCellLayout(l, startRow, endRow, startCol, endCol, alignment);
+}
+
+//----------------------------------------------------------------------------
+ButtonContainer::ButtonContainer(const QString &title, QWidget *parent)
+ : Container(parent, Sunken)
+{
+ _button = new PopupButton(title, this);
+ addWidget(_button, 0,0, 0,1);
+ setColStretch(2, 1);
+}
diff --git a/src/common/gui/container.h b/src/common/gui/container.h
new file mode 100644
index 0000000..d718c6f
--- /dev/null
+++ b/src/common/gui/container.h
@@ -0,0 +1,58 @@
+/***************************************************************************
+ * 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 CONTAINER_H
+#define CONTAINER_H
+
+#include <qframe.h>
+#include <qwidgetstack.h>
+#include <qtabwidget.h>
+#include <qlayout.h>
+
+class PopupButton;
+
+//----------------------------------------------------------------------------
+class Container : public QFrame
+{
+Q_OBJECT
+public:
+ enum Type { Flat, Sunken };
+ Container(QWidget *parent = 0, Type type = Flat);
+ Container(QWidgetStack *stack, uint index, Type type = Flat);
+ Container(QTabWidget *tabw, const QString &title, Type type = Flat);
+ void addWidget(QWidget *widget, uint startRow, uint endRow, uint startCol, uint endCol, int alignment = 0);
+ void addLayout(QLayout *layout, uint startRow, uint endRow, uint startCol, uint endCol, int alignment = 0);
+ uint numRows() const { return _gridLayout->numRows(); }
+ uint numCols() const { return _gridLayout->numCols(); }
+ void setFrame(Type type);
+ void setMargin(uint margin) { _topLayout->setMargin(margin); }
+ void setRowSpacing(uint row, uint spacing) { _gridLayout->setRowSpacing(row, spacing); }
+ void setColSpacing(uint col, uint spacing) { _gridLayout->setColSpacing(col, spacing); }
+ void setRowStretch(uint row, uint stretch) { _gridLayout->setRowStretch(row, stretch); }
+ void setColStretch(uint col, uint stretch) { _gridLayout->setColStretch(col, stretch); }
+
+private:
+ Type _type;
+ QGridLayout *_topLayout, *_gridLayout;
+
+ void initLayout();
+};
+
+//----------------------------------------------------------------------------
+class ButtonContainer : public Container
+{
+Q_OBJECT
+public:
+ ButtonContainer(const QString &title, QWidget *parent);
+ PopupButton &button() { return *_button; }
+
+private:
+ PopupButton *_button;
+};
+
+#endif
diff --git a/src/common/gui/dialog.cpp b/src/common/gui/dialog.cpp
new file mode 100644
index 0000000..650b086
--- /dev/null
+++ b/src/common/gui/dialog.cpp
@@ -0,0 +1,199 @@
+/***************************************************************************
+ * 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 "dialog.h"
+
+#include <qheader.h>
+#include <qtimer.h>
+#include <qlabel.h>
+#include <qwidgetstack.h>
+#include <ktextedit.h>
+
+#include "misc_gui.h"
+
+//-----------------------------------------------------------------------------
+Dialog::Dialog(QWidget *parent, const char *name, bool modal,
+ const QString &caption, int buttonMask, ButtonCode defaultButton,
+ bool separator, const QSize &defaultSize)
+ : KDialogBase(parent, name, modal, caption, buttonMask, defaultButton, separator),
+ _defaultSize(defaultSize)
+{
+ BusyCursor::start();
+ Q_ASSERT(name);
+ QWidget *main = new QWidget(this);
+ setMainWidget(main);
+
+ QTimer::singleShot(0, this, SLOT(updateSize()));
+}
+
+Dialog::Dialog(DialogType type, const QString &caption, int buttonMask, ButtonCode defaultButton,
+ QWidget *parent, const char *name, bool modal, bool separator, const QSize &defaultSize)
+ : KDialogBase(type, caption, buttonMask, defaultButton, parent, name, modal, separator),
+ _defaultSize(defaultSize)
+{
+ BusyCursor::start();
+ Q_ASSERT(name);
+ QTimer::singleShot(0, this, SLOT(updateSize()));
+}
+
+Dialog::~Dialog()
+{
+ GuiConfig gc;
+ gc.writeEntry(QString(name()) + "_size", size());
+}
+
+void Dialog::updateSize()
+{
+ GuiConfig gc;
+ resize(gc.readSizeEntry(QString(name()) + "_size", &_defaultSize));
+ BusyCursor::stop();
+}
+
+//-----------------------------------------------------------------------------
+TreeListDialog::Item::Item(const QString &label, QWidget *page, const QString &title, QListView *listview)
+ : KListViewItem(listview, label), _page(page), _title(title)
+{}
+TreeListDialog::Item::Item(const QString &label, QWidget *page, const QString &title, QListViewItem *item)
+ : KListViewItem(item, label), _page(page), _title(title)
+{}
+
+TreeListDialog::TreeListDialog(QWidget *parent, const char *name, bool modal,
+ const QString &caption, int buttonMask, ButtonCode defaultButton,
+ bool separator)
+ : Dialog(parent, name, modal, caption, buttonMask, defaultButton, separator)
+{
+ QVBoxLayout *top = new QVBoxLayout(mainWidget(), 0, 10);
+
+ // list view
+ QValueList<int> widths;
+ widths += 80;
+ widths += 500;
+ Splitter *splitter = new Splitter(widths, Horizontal, mainWidget(), name);
+ top->addWidget(splitter);
+ _listView = new KListView(splitter);
+ connect(_listView, SIGNAL(currentChanged(QListViewItem *)), SLOT(currentChanged(QListViewItem *)));
+ _listView->setAllColumnsShowFocus(true);
+ _listView->setRootIsDecorated(true);
+ _listView->setSorting(0);
+ _listView->addColumn(QString::null);
+ _listView->header()->hide();
+ _listView->setResizeMode(QListView::LastColumn);
+
+ // pages
+ _frame = new QFrame(splitter);
+ QVBoxLayout *vbox = new QVBoxLayout(_frame, 10, 10);
+ _titleBox = new QHBoxLayout(vbox);
+ _label = new QLabel(_frame);
+ _titleBox->addWidget(_label);
+ _stack = new QWidgetStack(_frame);
+ connect(_stack, SIGNAL(aboutToShow(QWidget *)), SIGNAL(aboutToShowPage(QWidget *)));
+ vbox->addWidget(_stack);
+ vbox->addStretch(1);
+}
+
+QWidget *TreeListDialog::addPage(const QStringList &labels)
+{
+ Q_ASSERT( !labels.isEmpty() );
+
+ QWidget *page = 0;
+ QListViewItem *item = 0;
+ QListViewItemIterator it(_listView);
+ for (; it.current(); ++it) {
+ if ( it.current()->text(0)==labels[0] ) {
+ item = it.current();
+ break;
+ }
+ }
+ if ( item==0 ) {
+ page = new QWidget(_stack);
+ connect(page, SIGNAL(destroyed(QObject *)), SLOT(pageDestroyed(QObject *)));
+ _stack->addWidget(page);
+ item = new Item(labels[0], page, labels[0], _listView);
+ item->setOpen(true);
+ bool last = ( labels.count()==1 );
+ item->setSelectable(last);
+ }
+ for (uint i=1; i<labels.count(); i++) {
+ QListViewItem *parent = item;
+ item = 0;
+ QListViewItemIterator iti(parent);
+ for (; it.current(); ++it) {
+ if ( it.current()->text(0)==labels[i] ) {
+ item = it.current();
+ break;
+ }
+ }
+ if ( item==0 ) {
+ page = new QWidget(_stack);
+ connect(page, SIGNAL(destroyed(QObject *)), SLOT(pageDestroyed(QObject *)));
+ _stack->addWidget(page);
+ item = new Item(labels[i], page, labels[i], parent);
+ item->setOpen(true);
+ bool last = ( labels.count()==i+1 );
+ item->setSelectable(last);
+ }
+ }
+
+ return page;
+}
+
+void TreeListDialog::currentChanged(QListViewItem *lvitem)
+{
+ if ( lvitem==0 ) return;
+ Item *item = static_cast<Item *>(lvitem);
+ _listView->ensureItemVisible(item);
+ _label->setText(item->_title);
+ _stack->raiseWidget(item->_page);
+}
+
+void TreeListDialog::showPage(QWidget *page)
+{
+ QListViewItemIterator it(_listView);
+ for (; it.current(); ++it) {
+ Item *item = static_cast<Item *>(it.current());
+ if ( item->_page==page ) {
+ _listView->setCurrentItem(item);
+ currentChanged(item);
+ break;
+ }
+ }
+}
+
+int TreeListDialog::pageIndex(QWidget *page) const
+{
+ return _stack->id(page);
+}
+
+int TreeListDialog::activePageIndex() const
+{
+ const Item *item = static_cast<const Item *>(_listView->currentItem());
+ if ( item==0 ) return -1;
+ return pageIndex(item->_page);
+}
+
+void TreeListDialog::pageDestroyed(QObject *object)
+{
+ QListViewItemIterator it(_listView);
+ for (; it.current(); ++it) {
+ Item *item = static_cast<Item *>(it.current());
+ if ( item->_page!=object ) continue;
+ delete item;
+ break;
+ }
+}
+
+//-----------------------------------------------------------------------------
+TextEditorDialog::TextEditorDialog(const QString &text, const QString &caption,
+ bool wrapAtWidgetWidth, QWidget *parent)
+ : Dialog(parent, "text_editor_dialog", true, caption, Close, Close, false, QSize(200, 100))
+{
+ KTextEdit *w = new KTextEdit(text, QString::null, this);
+ w->setReadOnly(true);
+ w->setWordWrap(wrapAtWidgetWidth ? QTextEdit::WidgetWidth : QTextEdit::NoWrap);
+ setMainWidget(w);
+}
diff --git a/src/common/gui/dialog.h b/src/common/gui/dialog.h
new file mode 100644
index 0000000..1227a7d
--- /dev/null
+++ b/src/common/gui/dialog.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+ * 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 DIALOG_H
+#define DIALOG_H
+
+#include <qlayout.h>
+#include <kdialogbase.h>
+#include <klistview.h>
+
+//-----------------------------------------------------------------------------
+class Dialog : public KDialogBase
+{
+Q_OBJECT
+public:
+ Dialog(QWidget *parent, const char *name, bool modal,
+ const QString &caption, int buttonMask, ButtonCode defaultButton, bool separator,
+ const QSize &defaultSize = QSize());
+ Dialog(DialogType type, const QString &caption,
+ int buttonMask, ButtonCode defaultButton, QWidget *parent, const char *name,
+ bool modal, bool separator, const QSize &defaultSize = QSize());
+ virtual ~Dialog();
+
+private slots:
+ void updateSize();
+
+private:
+ QSize _defaultSize;
+};
+
+//-----------------------------------------------------------------------------
+class TreeListDialog : public Dialog
+{
+Q_OBJECT
+public:
+ TreeListDialog(QWidget *parent, const char *name, bool modal,
+ const QString &caption, int buttonMask, ButtonCode defaultButton, bool separator);
+ QWidget *addPage(const QStringList &labels);
+ void showPage(QWidget *page);
+ int activePageIndex() const;
+ int pageIndex(QWidget *page) const;
+
+protected slots:
+ virtual void currentChanged(QListViewItem *item);
+ void pageDestroyed(QObject *page);
+
+protected:
+ QFrame *_frame;
+ KListView *_listView;
+ QHBoxLayout *_titleBox;
+ QLabel *_label;
+ QWidgetStack *_stack;
+
+ class Item : public KListViewItem {
+ public:
+ Item(const QString &label, QWidget *page, const QString &title, QListView *listview);
+ Item(const QString &label, QWidget *page, const QString &title, QListViewItem *item);
+ QWidget *_page;
+ QString _title;
+ };
+};
+
+//-----------------------------------------------------------------------------
+class TextEditorDialog : public Dialog
+{
+Q_OBJECT
+public:
+ TextEditorDialog(const QString &text, const QString &caption,
+ bool wrapAtWidgetWidth, QWidget *parent);
+};
+
+#endif
diff --git a/src/common/gui/editlistbox.cpp b/src/common/gui/editlistbox.cpp
new file mode 100644
index 0000000..1d2916d
--- /dev/null
+++ b/src/common/gui/editlistbox.cpp
@@ -0,0 +1,340 @@
+/* Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org>
+ 2000, 2002 Carsten Pfeiffer <pfeiffer@kde.org>
+ Copyright (C) 2006-2007 Nicolas Hadacek <hadacek@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#include "editlistbox.h"
+
+#include <qstringlist.h>
+#include <qlabel.h>
+#include <qheader.h>
+
+#include <kdialog.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <knotifyclient.h>
+#include <kiconloader.h>
+#include <kstdguiitem.h>
+
+EditListBox::EditListBox(uint nbColumns, QWidget *parent, const char *name, Mode mode, Buttons buttons)
+ : QFrame(parent, name), _mode(mode), _buttons(buttons)
+{
+ m_lineEdit = new KLineEdit;
+ init(nbColumns, m_lineEdit);
+}
+
+EditListBox::EditListBox(uint nbColumns, QWidget *view, KLineEdit *lineEdit, QWidget *parent, const char *name,
+ Mode mode, Buttons buttons)
+ : QFrame(parent, name), _mode(mode), _buttons(buttons)
+{
+ m_lineEdit = lineEdit;
+ init(nbColumns, view);
+}
+
+void EditListBox::init(uint nbColumns, QWidget *view)
+{
+ _addButton = 0;
+ _removeButton = 0;
+ _moveUpButton = 0;
+ _moveDownButton = 0;
+ _removeAllButton = 0;
+ _resetButton = 0;
+ setSizePolicy(QSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding));
+
+ QGridLayout *grid = new QGridLayout(this, 1, 1, 0, KDialog::spacingHint());
+ uint row = 0;
+ if (view) {
+ QHBoxLayout *hbox = new QHBoxLayout(KDialog::spacingHint());
+ grid->addMultiCellLayout(hbox, row,row, 0,1);
+ if (m_lineEdit) {
+ KIconLoader loader;
+ QIconSet iconset = loader.loadIcon("locationbar_erase", KIcon::Toolbar);
+ KPushButton *button = new KPushButton(iconset, QString::null, this);
+ connect(button, SIGNAL(clicked()), SLOT(clearEdit()));
+ hbox->addWidget(button);
+ }
+ view->reparent( this, QPoint(0,0) );
+ hbox->addWidget(view);
+ row++;
+ }
+ _listView= new KListView(this);
+ for (uint i=0; i<nbColumns; i++) _listView->addColumn(QString::null);
+ _listView->header()->hide();
+ _listView->setSorting(-1);
+ _listView->setResizeMode(KListView::LastColumn);
+ _listView->setColumnWidthMode(nbColumns-1, KListView::Maximum);
+ grid->addWidget(_listView, row, 0);
+ QVBoxLayout *vbox = new QVBoxLayout(10);
+ grid->addLayout(vbox, row, 1);
+ _buttonsLayout = new QVBoxLayout(10);
+ vbox->addLayout(_buttonsLayout);
+ vbox->addStretch(1);
+
+ setButtons(_buttons);
+
+ if (m_lineEdit) {
+ connect(m_lineEdit,SIGNAL(textChanged(const QString&)),this,SLOT(typedSomething(const QString&)));
+ m_lineEdit->setTrapReturnKey(true);
+ connect(m_lineEdit,SIGNAL(returnPressed()),this,SLOT(addItem()));
+ }
+ connect(_listView, SIGNAL(selectionChanged()), SLOT(selectionChanged()));
+
+ // maybe supplied lineedit has some text already
+ typedSomething(m_lineEdit ? m_lineEdit->text() : QString::null);
+}
+
+void EditListBox::setButtons(Buttons buttons)
+{
+ _buttons = buttons;
+
+ delete _addButton;
+ _addButton = 0;
+ if ( buttons & Add ) {
+#if KDE_VERSION < KDE_MAKE_VERSION(3,4,0)
+ _addButton = new KPushButton(KGuiItem(i18n("Add"), "edit_add"), this);
+#else
+ _addButton = new KPushButton(KStdGuiItem::add(), this);
+#endif
+ _addButton->setEnabled(false);
+ _addButton->show();
+ connect(_addButton, SIGNAL(clicked()), SLOT(addItem()));
+ _buttonsLayout->addWidget(_addButton);
+ }
+
+ delete _removeButton;
+ _removeButton = 0;
+ if ( buttons & Remove ) {
+ _removeButton = new KPushButton(KGuiItem(i18n("Remove"), "clear"), this);
+ _removeButton->setEnabled(false);
+ _removeButton->show();
+ connect(_removeButton, SIGNAL(clicked()), SLOT(removeItem()));
+ _buttonsLayout->addWidget(_removeButton);
+ }
+
+ delete _removeAllButton;
+ _removeAllButton = 0;
+ if ( buttons & RemoveAll ) {
+ _removeAllButton = new KPushButton(KGuiItem(i18n("Remove All"), "delete"), this);
+ _removeAllButton->show();
+ connect(_removeAllButton, SIGNAL(clicked()), SLOT(clear()));
+ _buttonsLayout->addWidget(_removeAllButton);
+ }
+
+ delete _moveUpButton;
+ _moveUpButton = 0;
+ delete _moveDownButton;
+ _moveDownButton = 0;
+ if ( buttons & UpDown ) {
+ _moveUpButton = new KPushButton(KGuiItem(i18n("Move &Up"), "up"), this);
+ _moveUpButton->setEnabled(false);
+ _moveUpButton->show();
+ connect(_moveUpButton, SIGNAL(clicked()), SLOT(moveItemUp()));
+ _buttonsLayout->addWidget(_moveUpButton);
+ _moveDownButton = new KPushButton(KGuiItem(i18n("Move &Down"), "down"), this);
+ _moveDownButton->setEnabled(false);
+ _moveDownButton->show();
+ connect(_moveDownButton, SIGNAL(clicked()), SLOT(moveItemDown()));
+ _buttonsLayout->addWidget(_moveDownButton);
+ }
+
+ delete _resetButton;
+ _resetButton = 0;
+ if ( buttons & Reset ) {
+ _resetButton = new KPushButton(KStdGuiItem::reset(), this);
+ _resetButton->show();
+ connect(_resetButton, SIGNAL(clicked()), SIGNAL(reset()));
+ _buttonsLayout->addWidget(_resetButton);
+ }
+}
+
+void EditListBox::typedSomething(const QString& text)
+{
+ QListViewItem *item = _listView->selectedItem();
+ if (item) {
+ if( selectedText()!=text ) {
+ item->setText(textColumn(), text);
+ emit changed();
+ }
+ }
+ updateButtons();
+}
+
+void EditListBox::moveItemUp()
+{
+ QListViewItem *item = _listView->selectedItem();
+ if ( item==0 || item->itemAbove()==0 ) return;
+ item->itemAbove()->moveItem(item);
+ updateButtons();
+ emit changed();
+}
+
+void EditListBox::moveItemDown()
+{
+ QListViewItem *item = _listView->selectedItem();
+ if ( item==0 || item->itemBelow()==0 ) return;
+ item->moveItem(item->itemBelow());
+ updateButtons();
+ emit changed();
+}
+
+void EditListBox::addItem()
+{
+ // when m_checkAtEntering is true, the add-button is disabled, but this
+ // slot can still be called through Key_Return/Key_Enter. So we guard
+ // against this.
+ if ( !_addButton || !_addButton->isEnabled() || m_lineEdit==0 ) return;
+
+ addItem(m_lineEdit->text());
+}
+
+void EditListBox::addItem(const QString &text)
+{
+ bool alreadyInList(false);
+ //if we didn't check for dupes at the inserting we have to do it now
+ if ( _mode==DuplicatesDisallowed ) alreadyInList = _listView->findItem(text, textColumn());
+
+ if (m_lineEdit) {
+ bool block = m_lineEdit->signalsBlocked();
+ m_lineEdit->blockSignals(true);
+ m_lineEdit->clear();
+ m_lineEdit->blockSignals(block);
+ }
+ _listView->clearSelection();
+
+ if (!alreadyInList) {
+ QListViewItem *item = createItem();
+ item->setText(textColumn(), text);
+ if ( _listView->lastItem() ) item->moveItem(_listView->lastItem());
+ emit changed();
+ emit added(text);
+ }
+ updateButtons();
+}
+
+void EditListBox::clearEdit()
+{
+ _listView->clearSelection();
+ if (m_lineEdit) {
+ m_lineEdit->clear();
+ m_lineEdit->setFocus();
+ }
+ updateButtons();
+}
+
+void EditListBox::removeItem()
+{
+ QListViewItem *item = _listView->selectedItem();
+ if (item) {
+ QString text = item->text(textColumn());
+ delete item;
+ emit changed();
+ emit removed(text);
+ updateButtons();
+ }
+}
+
+void EditListBox::selectionChanged()
+{
+ if (m_lineEdit) m_lineEdit->setText(selectedText());
+ updateButtons();
+}
+
+void EditListBox::clear()
+{
+ _listView->clear();
+ if (m_lineEdit) {
+ m_lineEdit->clear();
+ m_lineEdit->setFocus();
+ }
+ updateButtons();
+ emit changed();
+}
+
+uint EditListBox::count() const
+{
+ uint nb = 0;
+ QListViewItemIterator it(_listView);
+ for (; it.current(); ++it) nb++;
+ return nb;
+}
+
+const QListViewItem *EditListBox::item(uint i) const
+{
+ uint k = 0;
+ QListViewItemIterator it(_listView);
+ for (; it.current(); ++it) {
+ if ( k==i ) return it.current();
+ k++;
+ }
+ return 0;
+}
+
+QStringList EditListBox::texts() const
+{
+ QStringList list;
+ QListViewItemIterator it(_listView);
+ for (; it.current(); ++it) list.append(it.current()->text(textColumn()));
+ return list;
+}
+
+void EditListBox::setTexts(const QStringList& items)
+{
+ _listView->clear();
+ for (int i=items.count()-1; i>=0; i--) {
+ QListViewItem *item = createItem();
+ item->setText(textColumn(), items[i]);
+ }
+ if (m_lineEdit) m_lineEdit->clear();
+ updateButtons();
+}
+
+void EditListBox::updateButtons()
+{
+ QListViewItem *item = _listView->selectedItem();
+ if (_addButton) {
+ if ( m_lineEdit==0 ) _addButton->setEnabled(true);
+ else {
+ QString text = m_lineEdit->text();
+ if ( _mode!=DuplicatesCheckedAtEntering ) _addButton->setEnabled(!text.isEmpty());
+ else if ( text.isEmpty() ) _addButton->setEnabled(false);
+ else _addButton->setEnabled(!_listView->findItem(text, textColumn()));
+ }
+ }
+ if (_removeButton) _removeButton->setEnabled(item);
+ if (_moveUpButton) _moveUpButton->setEnabled(item && item->itemAbove());
+ if (_moveDownButton) _moveDownButton->setEnabled(item && item->itemBelow());
+ if (_removeAllButton) _removeAllButton->setEnabled(_listView->firstChild());
+}
+
+void EditListBox::setEditText(const QString &text)
+{
+ _listView->clearSelection();
+ if (m_lineEdit) m_lineEdit->setText(text);
+ updateButtons();
+}
+
+QListViewItem *EditListBox::createItem()
+{
+ return new KListViewItem(_listView);
+}
+
+QString EditListBox::selectedText() const
+{
+ QListViewItem *item = _listView->selectedItem();
+ if ( item==0 ) return QString::null;
+ return item->text(textColumn());
+}
diff --git a/src/common/gui/editlistbox.h b/src/common/gui/editlistbox.h
new file mode 100644
index 0000000..c259278
--- /dev/null
+++ b/src/common/gui/editlistbox.h
@@ -0,0 +1,95 @@
+/* Copyright (C) 2000 David Faure <faure@kde.org>, Alexander Neundorf <neundorf@kde.org>
+ Copyright (C) 2006-2007 Nicolas Hadacek <hadacek@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License as published by the Free Software Foundation; either
+ version 2 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+#ifndef EDITLISTBOX_H
+#define EDITLISTBOX_H
+
+#include <qlayout.h>
+#include <klineedit.h>
+#include <kpushbutton.h>
+#include <klistview.h>
+
+#include "common/common/qflags.h"
+
+//----------------------------------------------------------------------------
+// modified KEditListBox (beyond recognition)
+// * support for duplicated items
+// * use KStdGuiItem for buttons
+// * support for New, Clear, Reset buttons
+// * use KListView
+class EditListBox : public QFrame
+{
+Q_OBJECT
+ public:
+ enum Mode { DuplicatesDisallowed, DuplicatesAllowed, DuplicatesCheckedAtEntering };
+ enum Button { Add = 1, Remove = 2, UpDown = 4, RemoveAll = 8, Reset = 16 };
+ Q_DECLARE_FLAGS(Buttons, Button)
+
+ EditListBox(uint nbColumns, QWidget *parent = 0, const char *name = 0, Mode mode = DuplicatesDisallowed,
+ Buttons buttons = Buttons(Add|Remove|RemoveAll|UpDown) );
+ EditListBox(uint nbColumns, QWidget *view, KLineEdit *lineEdit, QWidget *parent = 0, const char *name = 0,
+ Mode mode = DuplicatesDisallowed, Buttons buttons = Buttons(Add|Remove|RemoveAll|UpDown) );
+ void setTexts(const QStringList& items);
+ QStringList texts() const;
+ uint count() const;
+ QString text(uint i) const { return item(i)->text(textColumn()); }
+ const QListViewItem *item(uint i) const;
+ Buttons buttons() const { return _buttons; }
+ void setButtons(Buttons buttons);
+ void setEditText(const QString &text);
+ void addItem(const QString &text);
+
+ signals:
+ void reset();
+ void changed();
+ void added( const QString & text );
+ void removed( const QString & text );
+
+ public slots:
+ void clear();
+
+ protected slots:
+ virtual void moveItemUp();
+ virtual void moveItemDown();
+ virtual void clearEdit();
+ virtual void addItem();
+ virtual void removeItem();
+ void selectionChanged();
+ void typedSomething(const QString& text);
+
+ protected:
+ KListView *_listView;
+
+ virtual QListViewItem *createItem();
+ virtual uint textColumn() const { return 0; }
+ QString selectedText() const;
+
+ private:
+ Mode _mode;
+ Buttons _buttons;
+ QVBoxLayout *_buttonsLayout;
+ KLineEdit *m_lineEdit;
+ KPushButton *_addButton, *_removeButton, *_moveUpButton, *_moveDownButton,
+ *_removeAllButton, *_resetButton;
+
+ void init(uint nbColumns, QWidget *view);
+ void updateButtons();
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(EditListBox::Buttons)
+
+#endif
diff --git a/src/common/gui/hexword_gui.cpp b/src/common/gui/hexword_gui.cpp
new file mode 100644
index 0000000..d794a11
--- /dev/null
+++ b/src/common/gui/hexword_gui.cpp
@@ -0,0 +1,136 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * *
+ * 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 "hexword_gui.h"
+
+#include <qtimer.h>
+
+#include "common/gui/number_gui.h"
+#include "common/common/misc.h"
+
+//-----------------------------------------------------------------------------
+HexValueValidator::HexValueValidator(uint nbChars, QObject *parent)
+ : QValidator(parent, "hex_value_validator"), _nbChars(nbChars) {}
+
+QValidator::State HexValueValidator::validate(QString &input, int &) const
+{
+ if ( input.length()==0 ) return Acceptable;
+ if ( input.length()>_nbChars ) return Invalid;
+ for (uint i=0; i<input.length(); i++)
+ if ( !isxdigit(input[i].latin1()) && input[i]!='-' ) return Invalid;
+ return Acceptable;
+}
+
+//-----------------------------------------------------------------------------
+GenericHexWordEditor::GenericHexWordEditor(uint nbChars, bool hasBlankValue, QWidget *parent)
+ : KLineEdit(parent, "hex_word_editor"), _nbChars(nbChars), _hasBlankValue(hasBlankValue)
+{
+ setFocusPolicy(ClickFocus);
+ setValidator(new HexValueValidator(nbChars, this));
+ connect(this, SIGNAL(textChanged(const QString &)), SLOT(slotTextChanged()));
+ setFrame(false);
+}
+
+void GenericHexWordEditor::slotTextChanged()
+{
+ if ( text().length()!=_nbChars ) return;
+ if ( changeValue() ) emit moveNext();
+}
+
+bool GenericHexWordEditor::changeValue()
+{
+ if ( !isValid() ) return false;
+ QString s = text();
+ BitValue v = blankValue();
+ if ( s!=QString(repeat("-", _nbChars)) ) {
+ s = s.leftJustify(_nbChars, '0', true);
+ for (uint i=0; i<_nbChars; i++)
+ if ( !isxdigit(s[i].latin1()) ) s[i] = '0';
+ v = normalizeWord(fromHex(s, 0));
+ setText(toHex(v, _nbChars));
+ }
+ if ( v==word() ) return false;
+ setWord(v);
+ emit modified();
+ return true;
+}
+
+void GenericHexWordEditor::set()
+{
+ blockSignals(true);
+ setEnabled(isValid());
+ if ( !isValid() ) clear();
+ else {
+ BitValue value = word();
+ if ( _hasBlankValue && value==blankValue() ) setText(repeat("-", _nbChars));
+ else setText(toHex(normalizeWord(value), _nbChars));
+ }
+ blockSignals(false);
+}
+
+bool GenericHexWordEditor::event(QEvent *e)
+{
+ switch (e->type()) {
+ case QEvent::FocusOut:
+ changeValue();
+ break;
+ case QEvent::FocusIn:
+ QTimer::singleShot(0, this, SLOT(selectAll())); // ugly but it works
+ break;
+ case QEvent::KeyPress:
+ switch ( static_cast<QKeyEvent *>(e)->key() ) {
+ case Key_Next:
+ emit moveNextPage();
+ return true;
+ case Key_Tab:
+ case Key_Enter:
+ case Key_Return:
+ emit moveNext();
+ return true;
+ case Key_Prior:
+ emit movePrevPage();
+ return true;
+ case Key_BackTab:
+ emit movePrev();
+ return true;
+ case Key_Down:
+ emit moveDown();
+ return true;
+ case Key_Up:
+ emit moveUp();
+ return true;
+ case Key_Home:
+ emit moveFirst();
+ return true;
+ case Key_End:
+ emit moveLast();
+ return true;
+ case Key_Right:
+ if ( cursorPosition()!=int(text().length()) ) break;
+ emit moveNext();
+ return true;
+ case Key_Left:
+ if ( cursorPosition()!=0 ) break;
+ emit movePrev();
+ return true;
+ }
+ default: break;
+ }
+ return QLineEdit::event(e);
+}
+
+QSize GenericHexWordEditor::sizeHint() const
+{
+ return QSize(maxCharWidth(NumberBase::Hex, font()) * (_nbChars+1), fontMetrics().height());
+}
+
+QSize GenericHexWordEditor::minimumSizeHint() const
+{
+ return QSize(maxCharWidth(NumberBase::Hex, font()) * (_nbChars+1), fontMetrics().height());
+}
diff --git a/src/common/gui/hexword_gui.h b/src/common/gui/hexword_gui.h
new file mode 100644
index 0000000..5da6840
--- /dev/null
+++ b/src/common/gui/hexword_gui.h
@@ -0,0 +1,88 @@
+/***************************************************************************
+ * Copyright (C) 2006-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * *
+ * 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 HEXWORD_GUI_H
+#define HEXWORD_GUI_H
+
+#include <qvalidator.h>
+#include <klineedit.h>
+
+#include "common/common/bitvalue.h"
+
+//-----------------------------------------------------------------------------
+class HexValueValidator : public QValidator
+{
+Q_OBJECT
+public:
+ HexValueValidator(uint nbChars, QObject *parent);
+ virtual State validate(QString &input, int &pos) const;
+
+private:
+ uint _nbChars;
+};
+
+//-----------------------------------------------------------------------------
+class GenericHexWordEditor : public KLineEdit
+{
+Q_OBJECT
+public:
+ GenericHexWordEditor(uint nbChars, bool hasBlankValue, QWidget *parent);
+ virtual QSize sizeHint() const;
+ virtual QSize minimumSizeHint() const;
+
+signals:
+ void modified();
+ void moveNext();
+ void movePrev();
+ void moveUp();
+ void moveDown();
+ void moveFirst();
+ void moveLast();
+ void moveNextPage();
+ void movePrevPage();
+
+private slots:
+ bool changeValue();
+ void slotTextChanged();
+
+protected:
+ uint _nbChars;
+ bool _hasBlankValue;
+
+ virtual bool isValid() const = 0;
+ virtual BitValue mask() const = 0;
+ virtual BitValue normalizeWord(BitValue value) const = 0;
+ virtual bool event(QEvent *e);
+ virtual void set();
+ virtual BitValue word() const = 0;
+ virtual void setWord(BitValue value) = 0;
+ virtual BitValue blankValue() const = 0;
+};
+
+//-----------------------------------------------------------------------------
+class HexWordEditor : public GenericHexWordEditor
+{
+Q_OBJECT
+public:
+ HexWordEditor(uint nbChars, QWidget *parent) : GenericHexWordEditor(nbChars, false, parent) {}
+ void setValue(BitValue word) { _word = word; set(); }
+ BitValue value() const { return _word; }
+
+protected:
+ BitValue _word;
+
+ virtual bool isValid() const { return true; }
+ virtual BitValue mask() const { return maxValue(NumberBase::Hex, _nbChars); }
+ virtual BitValue normalizeWord(BitValue value) const { return value.maskWith(mask()); }
+ virtual BitValue word() const { return _word; }
+ virtual void setWord(BitValue value) { _word = value; }
+ virtual BitValue blankValue() const { return 0; }
+};
+
+#endif
diff --git a/src/common/gui/key_gui.h b/src/common/gui/key_gui.h
new file mode 100644
index 0000000..fb8a9f5
--- /dev/null
+++ b/src/common/gui/key_gui.h
@@ -0,0 +1,125 @@
+/***************************************************************************
+ * Copyright (C) 2006-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 KEY_GUI_H
+#define KEY_GUI_H
+
+#include <qcombobox.h>
+#include <qwidgetstack.h>
+#include <qpopupmenu.h>
+
+#include "common/gui/misc_gui.h"
+#include "common/common/misc.h"
+
+//-----------------------------------------------------------------------------
+template <typename KeyType, typename Type, typename WidgetType>
+class KeyWidget
+{
+public:
+ typedef QMapConstIterator<KeyType, int> ConstIterator;
+
+public:
+ KeyWidget(QWidget *parent) { _widget = new WidgetType(parent); }
+ virtual ~KeyWidget() { delete _widget; }
+ virtual WidgetType *widget() { return _widget; }
+ virtual void clear() { _ids.clear(); }
+ ConstIterator begin() const { return _ids.begin(); }
+ ConstIterator end() const { return _ids.end(); }
+ uint count() const { return _ids.count(); }
+ void appendItem(const KeyType &key, Type type) {
+ CRASH_ASSERT( !_ids.contains(key) );
+ _ids[key] = append(type);
+ }
+ KeyType currentItem() const { return key(currentId()); }
+ void setCurrentItem(const KeyType &key) {
+ if ( _ids.contains(key) ) setCurrentId(_ids[key]);
+ }
+ bool contains(const KeyType &key) const { return _ids.contains(key); }
+ Type item(const KeyType &key) const {
+ CRASH_ASSERT( _ids.contains(key) );
+ return get(_ids[key]);
+ }
+ Type item(ConstIterator it) const {
+ CRASH_ASSERT( it!=end() );
+ return get(it.data());
+ }
+ KeyType key(int id) const {
+ for (ConstIterator it=begin(); it!=end(); it++)
+ if ( it.data()==id ) return it.key();
+ return KeyType();
+ }
+
+protected:
+ virtual int append(Type type) = 0;
+ virtual int currentId() const = 0;
+ virtual void setCurrentId(int id) = 0;
+ virtual Type get(int id) const = 0;
+
+ QWidget *_parent;
+ QMap<KeyType, int> _ids;
+ WidgetType *_widget;
+};
+
+//-----------------------------------------------------------------------------
+template <typename KeyType>
+class KeyComboBox : public KeyWidget<KeyType, QString, QComboBox>
+{
+public:
+ typedef KeyWidget<KeyType, QString, QComboBox> ParentType;
+ KeyComboBox(QWidget *parent = 0) : ParentType(parent) {}
+ virtual void clear() {
+ ParentType::clear();
+ ParentType::_widget->clear();
+ }
+ void fixMinimumWidth() {
+ ParentType::_widget->setMinimumWidth(ParentType::_widget->sizeHint().width());
+ }
+
+protected:
+ virtual int append(QString label) { ParentType::_widget->insertItem(label); return ParentType::_widget->count()-1; }
+ virtual int currentId() const { return ParentType::_widget->currentItem(); }
+ virtual void setCurrentId(int id) { ParentType::_widget->setCurrentItem(id); }
+ virtual QString get(int id) const { return ParentType::_widget->text(id); }
+};
+
+//-----------------------------------------------------------------------------
+template <typename KeyType>
+class KeyWidgetStack : public KeyWidget<KeyType, QWidget *, QWidgetStack>
+{
+public:
+ typedef KeyWidget<KeyType, QWidget *, QWidgetStack> ParentType;
+ KeyWidgetStack(QWidget *parent = 0) : ParentType(parent) {}
+
+protected:
+ virtual int append(QWidget *widget) { return ParentType::_widget->addWidget(widget); }
+ virtual int currentId() const { return ParentType::_widget->id(ParentType::_widget->visibleWidget()); }
+ virtual void setCurrentId(int id) { ParentType::_widget->raiseWidget(id); }
+ virtual QWidget *get(int id) const { return ParentType::_widget->widget(id); }
+};
+
+//-----------------------------------------------------------------------------
+template <typename KeyType>
+class KeyPopupButton : public KeyWidget<KeyType, QString, PopupButton>
+{
+public:
+ typedef KeyWidget<KeyType, QString, PopupButton> ParentType;
+ KeyPopupButton(QWidget *parent = 0) : ParentType(parent) {}
+
+protected:
+ virtual int append(QString label) { return ParentType::_widget->appendItem(label, QPixmap()); }
+ virtual QString get(int id) const { return ParentType::_widget->popup()->text(id); }
+
+private:
+ // disabled
+ QString currentItem() const;
+ void setCurrentItem(const QString &key);
+ virtual int currentId() const { return 0; }
+ virtual void setCurrentId(int) {}
+};
+
+#endif
diff --git a/src/common/gui/list_container.cpp b/src/common/gui/list_container.cpp
new file mode 100644
index 0000000..0103175
--- /dev/null
+++ b/src/common/gui/list_container.cpp
@@ -0,0 +1,95 @@
+/***************************************************************************
+ * 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 "list_container.h"
+
+//----------------------------------------------------------------------------
+PopupContainer::PopupContainer(const QString &title, QWidget *parent, const char *name)
+ : KPopupMenu(parent, name)
+{
+ if ( !title.isEmpty() ) insertTitle(title);
+}
+
+ListContainer *PopupContainer::appendBranch(const QString &title)
+{
+ PopupContainer *branch = new PopupContainer(title, this);
+ insertItem(title, branch);
+ return branch;
+}
+
+ListContainer *PopupContainer::appendBranch(const QPixmap &pixmap, const QString &title)
+{
+ PopupContainer *branch = new PopupContainer(title, this);
+ insertItem(pixmap, title, branch);
+ return branch;
+}
+
+void PopupContainer::appendItem(const QPixmap &icon, const QString &label, uint id, ItemState state)
+{
+ insertItem(icon, label, id);
+ switch (state) {
+ case Normal: break;
+ case Checked: setItemChecked(id, true); break;
+ case UnChecked: setItemChecked(id, false); break;
+ case Disabled: setItemEnabled(id, false); break;
+ }
+}
+
+//----------------------------------------------------------------------------
+ListViewItemContainer::ListViewItemContainer(const QString &title, KListView *parent)
+ : KListViewItem(parent, title), _parent(0), _column(0)
+{
+ _ids = new QMap<const QListViewItem *, uint>;
+}
+
+ListViewItemContainer::ListViewItemContainer(const QString &title, ListViewItemContainer *parent)
+ : KListViewItem(parent, title), _parent(parent), _column(0)
+{
+ _ids = parent->_ids;
+}
+
+ListViewItemContainer::~ListViewItemContainer()
+{
+ if ( _parent==0 ) delete _ids;
+}
+
+ListContainer *ListViewItemContainer::appendBranch(const QString &title)
+{
+ ListViewItemContainer *branch = new ListViewItemContainer(title, this);
+ branch->setColumn(_column);
+ branch->setSelectable(false);
+ // append instead of prepend
+ QListViewItem *litem=firstChild();
+ while ( litem && litem->nextSibling() ) litem = litem->nextSibling();
+ if (litem) branch->moveItem(litem);
+ return branch;
+}
+
+void ListViewItemContainer::appendItem(const QPixmap &icon, const QString &title, uint id, ItemState state)
+{
+ QListViewItem *item = 0;
+ if ( state==Normal || state==Disabled ) {
+ item = new KListViewItem(this);
+ item->setText(_column, title);
+ } else {
+ item = new QCheckListItem(this, title, QCheckListItem::CheckBox);
+ static_cast<QCheckListItem *>(item)->setState(state==Checked ? QCheckListItem::On : QCheckListItem::Off);
+ }
+ item->setPixmap(_column, icon);
+ item->setSelectable(state==Normal);
+ // append instead of prepend
+ QListViewItem *litem=firstChild();
+ while ( litem && litem->nextSibling() ) litem = litem->nextSibling();
+ if (litem) item->moveItem(litem);
+ (*_ids)[item] = id;
+}
+
+int ListViewItemContainer::id(const QListViewItem *item) const
+{
+ return (_ids->contains(item) ? int((*_ids)[item]) : -1);
+}
diff --git a/src/common/gui/list_container.h b/src/common/gui/list_container.h
new file mode 100644
index 0000000..b70db57
--- /dev/null
+++ b/src/common/gui/list_container.h
@@ -0,0 +1,55 @@
+/***************************************************************************
+ * 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 LIST_CONTAINER_H
+#define LIST_CONTAINER_H
+
+#include <kpopupmenu.h>
+#include <klistview.h>
+
+//----------------------------------------------------------------------------
+class ListContainer
+{
+public:
+ virtual ~ListContainer() {}
+ virtual ListContainer *appendBranch(const QString &title) = 0;
+ enum ItemState { Normal, Checked, UnChecked, Disabled };
+ void appendItem(const QString &label, uint id, ItemState state) { appendItem(QPixmap(), label, id, state); }
+ virtual void appendItem(const QPixmap &icon, const QString &label, uint id, ItemState state) = 0;
+};
+
+//----------------------------------------------------------------------------
+class PopupContainer : public KPopupMenu, public ListContainer
+{
+Q_OBJECT
+public:
+ PopupContainer(const QString &title, QWidget *parent = 0, const char *name = 0);
+ virtual ListContainer *appendBranch(const QString &title);
+ virtual ListContainer *appendBranch(const QPixmap &icon, const QString &title);
+ virtual void appendItem(const QPixmap &icon, const QString &label, uint id, ItemState state);
+};
+
+//----------------------------------------------------------------------------
+class ListViewItemContainer : public KListViewItem, public ListContainer
+{
+public:
+ ListViewItemContainer(const QString &title, KListView *parent);
+ ListViewItemContainer(const QString &title, ListViewItemContainer *parent);
+ virtual ~ListViewItemContainer();
+ void setColumn(uint column) { _column = column; }
+ virtual ListContainer *appendBranch(const QString &title);
+ virtual void appendItem(const QPixmap &icon, const QString &label, uint id, ItemState state);
+ int id(const QListViewItem* item) const; // -1 if not known
+
+private:
+ ListViewItemContainer *_parent;
+ uint _column;
+ QMap<const QListViewItem *, uint> *_ids;
+};
+
+#endif
diff --git a/src/common/gui/list_view.cpp b/src/common/gui/list_view.cpp
new file mode 100644
index 0000000..c9434f3
--- /dev/null
+++ b/src/common/gui/list_view.cpp
@@ -0,0 +1,221 @@
+/***************************************************************************
+ * Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 1992-2003 Trolltech AS. *
+ * *
+ * 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 "list_view.h"
+
+#include <qapplication.h>
+#include <qpainter.h>
+#include <qlineedit.h>
+#include <qheader.h>
+#include <qmetaobject.h>
+#include <qvariant.h>
+
+//----------------------------------------------------------------------------
+ListView::ListView(QWidget *parent, const char *name)
+ : KListView(parent, name)
+{
+ QToolTip::remove(this);
+ _tooltip = new ListViewToolTip(this);
+}
+
+ListView::~ListView()
+{
+ delete _tooltip;
+}
+
+QString ListView::tooltip(const QListViewItem &, int) const
+{
+ return QString::null;
+}
+
+void ListView::clear()
+{
+ _editItems.clear();
+ KListView::clear();
+}
+
+bool ListView::eventFilter(QObject *o, QEvent *e)
+{
+ QValueList<EditListViewItem *>::const_iterator it;
+ for (it=_editItems.begin(); it!=_editItems.end(); ++it) {
+ for (uint i=0; i<(*it)->_editWidgets.count(); i++) {
+ if ( (*it)->_editWidgets[i]==o ) {
+ //qDebug("event %i", e->type());
+ switch (e->type()) {
+ case QEvent::KeyPress: {
+ QKeyEvent *ke = static_cast<QKeyEvent *>(e);
+ switch (ke->key()) {
+ case Key_Enter:
+ case Key_Return:
+ (*it)->renameDone(true);
+ return true;
+ case Key_Escape:
+ (*it)->removeEditBox();
+ return true;
+ }
+ break;
+ }
+ case QEvent::FocusOut: {
+ //qDebug("focus out %i %i=%i", qApp->focusWidget(), focusWidget(), (*it)->_editWidgets[i]);
+ if ( qApp->focusWidget() && focusWidget()==(*it)->_editWidgets[i] ) break;
+ //qDebug("ext");
+ QCustomEvent *e = new QCustomEvent(9999);
+ QApplication::postEvent(o, e);
+ return true;
+ }
+ case 9999:
+ (*it)->renameDone(false);
+ return true;
+ default:
+ //qDebug(" ignored");
+ break;
+ }
+ }
+ }
+ }
+ return KListView::eventFilter(o, e);
+}
+
+void ListView::stopRenaming(bool force)
+{
+ QValueList<EditListViewItem *>::const_iterator it;
+ for (it=_editItems.begin(); it!=_editItems.end(); ++it)
+ if ( (*it)->isRenaming() ) (*it)->renameDone(force);
+}
+
+//----------------------------------------------------------------------------
+void ListViewToolTip::maybeTip(const QPoint &p)
+{
+ if ( _listView==0 ) return;
+ const QListViewItem* item = _listView->itemAt(p);
+ if ( item==0 ) return;
+ QRect rect = _listView->itemRect(item);
+ if ( !rect.isValid() ) return;
+ int col = _listView->header()->sectionAt(p.x());
+ QString text = _listView->tooltip(*item, col);
+ if ( !text.isEmpty() ) {
+ int hpos = _listView->header()->sectionPos(col);
+ rect.setLeft(hpos);
+ rect.setRight(hpos + _listView->header()->sectionSize(col));
+ tip(rect, text);
+ }
+}
+
+//----------------------------------------------------------------------------
+EditListViewItem::EditListViewItem(ListView *list)
+ : KListViewItem(list), _renaming(false)
+{
+ setRenameEnabled(0, true);
+ list->_editItems.append(this);
+}
+
+EditListViewItem::EditListViewItem(KListViewItem *item)
+ : KListViewItem(item), _renaming(false)
+{
+ setRenameEnabled(0, true);
+ static_cast<ListView *>(listView())->_editItems.append(this);
+}
+
+EditListViewItem::~EditListViewItem()
+{
+ if ( listView() ) static_cast<ListView *>(listView())->_editItems.remove(this);
+ for (uint i=0; i<_editWidgets.count(); i++) delete _editWidgets[i];
+}
+
+void EditListViewItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align)
+{
+ if ( column<int(_editWidgets.count()) && _editWidgets[column] )
+ p->fillRect(0, 0, width, height(), cg.color(QColorGroup::Background));
+ else KListViewItem::paintCell(p, cg, column, width, align);
+}
+
+void EditListViewItem::startRename()
+{
+ if ( !renameEnabled(0) ) return;
+ QListView *lv = listView();
+ if ( !lv ) return;
+ KListViewItem::startRename(0);
+ if (renameBox) {
+ renameBox->removeEventFilter(lv);
+ renameBox->hide();
+ lv->removeChild(renameBox);
+ }
+ _renaming = true;
+ _editWidgets.resize(lv->columns());
+ for (uint i=0; i<_editWidgets.count(); i++) {
+ QRect r = lv->itemRect(this);
+ r = QRect(lv->viewportToContents(r.topLeft()), r.size());
+ r.setLeft(lv->header()->sectionPos(i));
+ r.setWidth(lv->header()->sectionSize(i) - 1);
+ if ( i==0 ) r.setLeft(r.left() + lv->itemMargin() + (depth() + (lv->rootIsDecorated() ? 1 : 0)) * lv->treeStepSize() - 1);
+ if ( (lv->contentsX() + lv->visibleWidth())<(r.x() + r.width()) )
+ lv->scrollBy((r.x() + r.width() ) - ( lv->contentsX() + lv->visibleWidth() ), 0);
+ if ( r.width()>lv->visibleWidth() ) r.setWidth(lv->visibleWidth());
+
+ _editWidgets[i] = editWidgetFactory(i);
+ if ( _editWidgets[i]==0 ) continue;
+ _editWidgets[i]->installEventFilter(lv);
+ lv->addChild(_editWidgets[i], r.x(), r.y());
+ uint w = QMIN(r.width(), _editWidgets[i]->sizeHint().width());
+ _editWidgets[i]->resize(w, r.height());
+ lv->viewport()->setFocusProxy(_editWidgets[i]);
+ _editWidgets[i]->setFocus();
+ _editWidgets[i]->show();
+ }
+}
+
+void EditListViewItem::removeEditBox()
+{
+ QListView *lv = listView();
+ if ( !lv ) return;
+ _renaming = false;
+ bool resetFocus = false;
+ for (uint i=0; i<_editWidgets.count(); i++) {
+ if ( lv->viewport()->focusProxy()==_editWidgets[i] ) resetFocus = true;
+ delete _editWidgets[i];
+ }
+ _editWidgets.clear();
+ delete renameBox;
+ renameBox = 0;
+ if (resetFocus) {
+ lv->viewport()->setFocusProxy(lv);
+ lv->setFocus();
+ }
+}
+
+void EditListViewItem::editDone(int col, const QWidget *edit)
+{
+ if ( edit->metaObject()->findProperty("text", true)!=-1 )
+ emit listView()->itemRenamed(this, col, edit->property("text").toString());
+ else if ( edit->metaObject()->findProperty("currentText", true)!=-1 )
+ emit listView()->itemRenamed(this, col, edit->property("currentText").toString());
+}
+
+void EditListViewItem::renameDone(bool force)
+{
+ QListView *lv = listView();
+ if ( !lv || !_renaming ) return;
+ _renaming = false;
+ for (uint i=0; i<_editWidgets.count(); i++) {
+ if ( !force && !alwaysAcceptEdit(i) ) continue;
+ emit lv->itemRenamed(this, i);
+ if ( _editWidgets[i] ) editDone(i, _editWidgets[i]);
+ }
+ removeEditBox();
+}
+
+int EditListViewItem::width(const QFontMetrics &fm, const QListView *lv, int col) const
+{
+ int w = KListViewItem::width(fm, lv, col);
+ QWidget *edit = editWidgetFactory(col);
+ if ( edit==0 ) return w;
+ w = QMAX(w, edit->sizeHint().width());
+ delete edit;
+ return w;
+}
diff --git a/src/common/gui/list_view.h b/src/common/gui/list_view.h
new file mode 100644
index 0000000..09ca984
--- /dev/null
+++ b/src/common/gui/list_view.h
@@ -0,0 +1,93 @@
+/***************************************************************************
+ * 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 LIST_VIEW_H
+#define LIST_VIEW_H
+
+#include <qtooltip.h>
+#include <qvaluevector.h>
+#define private public
+#define protected public
+#include <klistview.h>
+#undef private
+#undef protected
+
+//-----------------------------------------------------------------------------
+class EditListViewItem;
+class ListViewToolTip;
+
+class ListView : public KListView
+{
+Q_OBJECT
+public:
+ ListView(QWidget *parent = 0, const char *name = 0);
+ virtual ~ListView();
+ virtual void clear();
+ void stopRenaming(bool force);
+ virtual QString tooltip(const QListViewItem &item, int column) const;
+
+public slots:
+ void cancelRenaming() { stopRenaming(false); }
+ void finishRenaming() { stopRenaming(true); }
+
+protected:
+ virtual bool eventFilter(QObject *o, QEvent *e);
+
+private:
+ ListViewToolTip *_tooltip;
+ QValueList<EditListViewItem *> _editItems;
+
+ friend class EditListViewItem;
+};
+
+//-----------------------------------------------------------------------------
+class ListViewToolTip : public QToolTip
+{
+public:
+ ListViewToolTip(ListView *parent)
+ : QToolTip(parent->viewport()), _listView(parent) {}
+
+protected:
+ virtual void maybeTip(const QPoint &p);
+
+private:
+ ListView *_listView;
+};
+
+//-----------------------------------------------------------------------------
+class EditListViewItem : public KListViewItem
+{
+public:
+ EditListViewItem(ListView *list);
+ EditListViewItem(KListViewItem *item);
+ virtual ~EditListViewItem();
+ void startRename();
+ bool isRenaming() const { return _renaming; }
+
+protected:
+ virtual QWidget *editWidgetFactory(int col) const = 0;
+ virtual bool alwaysAcceptEdit(int col) const = 0;
+ virtual int width(const QFontMetrics &fm, const QListView *lv, int c) const;
+ virtual void editDone(int col, const QWidget *editWidget);
+ virtual void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align);
+
+private:
+ bool _renaming;
+ QValueVector<QWidget *> _editWidgets;
+
+ virtual void activate() { startRename(); }
+ virtual void startRename(int) { startRename(); }
+ virtual void okRename(int) { renameDone(true); }
+ virtual void cancelRename(int) { renameDone(false); }
+ void renameDone(bool force);
+ void removeEditBox();
+
+ friend class ListView;
+};
+
+#endif
diff --git a/src/common/gui/misc_gui.cpp b/src/common/gui/misc_gui.cpp
new file mode 100644
index 0000000..00f4997
--- /dev/null
+++ b/src/common/gui/misc_gui.cpp
@@ -0,0 +1,234 @@
+/***************************************************************************
+ * Copyright (C) 2005-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 "misc_gui.h"
+
+#include <qapplication.h>
+#include <qpushbutton.h>
+#include <qtimer.h>
+#include <qwidgetstack.h>
+#include <qobjectlist.h>
+#include <qpainter.h>
+#include <qheader.h>
+#include <qmetaobject.h>
+#include <qvariant.h>
+#include <qpopupmenu.h>
+
+#include <kcursor.h>
+#include <kiconloader.h>
+#include <kmessagebox.h>
+#include <kaction.h>
+#include <ktabbar.h>
+
+#include "dialog.h"
+#include "common/common/number.h"
+#include "common/common/misc.h"
+#include "common/gui/number_gui.h"
+
+//-----------------------------------------------------------------------------
+bool BusyCursor::_overridePaused = false;
+
+void BusyCursor::start()
+{
+ QApplication::setOverrideCursor(KCursor::waitCursor(), true);
+}
+
+void BusyCursor::stop()
+{
+ QApplication::restoreOverrideCursor();
+}
+
+void BusyCursor::pause()
+{
+ _overridePaused = QApplication::overrideCursor();
+ stop();
+}
+
+void BusyCursor::restore()
+{
+ if (_overridePaused) start();
+}
+
+//-----------------------------------------------------------------------------
+void MessageBox::information(const QString &text, Log::ShowMode show, const QString &dontShowAgainName)
+{
+ if ( show==Log::DontShow ) return;
+ BusyCursor::pause();
+ KMessageBox::information(qApp->mainWidget(), text, QString::null, dontShowAgainName, KMessageBox::Notify | KMessageBox::AllowLink);
+ BusyCursor::restore();
+}
+
+void MessageBox::detailedSorry(const QString &text, const QString &details, Log::ShowMode show)
+{
+ if ( show==Log::DontShow ) return;
+ BusyCursor::pause();
+ if ( details.isEmpty() ) KMessageBox::sorry(qApp->mainWidget(), text, QString::null, KMessageBox::Notify | KMessageBox::AllowLink);
+ else KMessageBox::detailedSorry(qApp->mainWidget(), text, details, QString::null, KMessageBox::Notify | KMessageBox::AllowLink);
+ BusyCursor::restore();
+}
+
+bool MessageBox::askContinue(const QString &text, const KGuiItem &buttonContinue, const QString &caption)
+{
+ ::BusyCursor::pause();
+ int res = KMessageBox::warningContinueCancel(qApp->mainWidget(), text, caption, buttonContinue);
+ ::BusyCursor::restore();
+ return ( res==KMessageBox::Continue );
+}
+
+bool MessageBox::questionYesNo(const QString &text, const KGuiItem &yesButton,const KGuiItem &noButton, const QString &caption)
+{
+ ::BusyCursor::pause();
+ int res = KMessageBox::questionYesNo(qApp->mainWidget(), text, caption, yesButton, noButton);
+ ::BusyCursor::restore();
+ return ( res==KMessageBox::Yes );
+}
+
+MessageBox::Result MessageBox::questionYesNoCancel(const QString &text, const KGuiItem &yesButton, const KGuiItem &noButton,
+ const QString &caption)
+{
+ ::BusyCursor::pause();
+ int res = KMessageBox::questionYesNoCancel(qApp->mainWidget(), text, caption, yesButton, noButton);
+ ::BusyCursor::restore();
+ if ( res==KMessageBox::Yes ) return Yes;
+ if ( res==KMessageBox::No ) return No;
+ return Cancel;
+}
+
+void MessageBox::text(const QString &text, Log::ShowMode show)
+{
+ if ( show==Log::DontShow ) return;
+ BusyCursor::pause();
+ TextEditorDialog dialog(text, QString::null, false, qApp->mainWidget());
+ dialog.exec();
+ BusyCursor::restore();
+}
+
+//----------------------------------------------------------------------------
+PopupButton::PopupButton(QWidget *parent, const char *name)
+ : KPushButton(parent, name)
+{
+ init();
+}
+
+PopupButton::PopupButton(const QString &text, QWidget *parent, const char *name)
+ : KPushButton(text, parent, name)
+{
+ init();
+}
+
+void PopupButton::init()
+{
+ _separator = false;
+ setFlat(true);
+ QPopupMenu *popup = new QPopupMenu(this);
+ connect(popup, SIGNAL(activated(int)), SIGNAL(activated(int)));
+ setPopup(popup);
+}
+
+void PopupButton::appendAction(KAction *action)
+{
+ if ( _separator && popup()->count()!=0 ) popup()->insertSeparator();
+ _separator = false;
+ action->plug(popup());
+}
+
+void PopupButton::appendAction(const QString &label, const QString &icon,
+ QObject *receiver, const char *slot)
+{
+ appendAction(new KAction(label, icon, 0, receiver, slot, (KActionCollection *)0));
+}
+
+int PopupButton::appendItem(const QString &label, const QString &icon, int id)
+{
+ KIconLoader loader;
+ QPixmap pixmap = loader.loadIcon(icon, KIcon::Small);
+ return appendItem(label, pixmap, id);
+}
+
+int PopupButton::appendItem(const QString &label, const QPixmap &icon, int id)
+{
+ if ( _separator && popup()->count()!=0 ) popup()->insertSeparator();
+ _separator = false;
+ return popup()->insertItem(icon, label, id);
+}
+
+//-----------------------------------------------------------------------------
+Splitter::Splitter(const QValueList<int> &defaultSizes, Orientation o, QWidget *parent, const char *name)
+ : QSplitter(o, parent, name), _defaultSizes(defaultSizes)
+{
+ Q_ASSERT(name);
+ setOpaqueResize(true);
+ QTimer::singleShot(0, this, SLOT(updateSizes()));
+}
+
+Splitter::~Splitter()
+{
+ GuiConfig gc;
+ gc.writeEntry(QString(name()) + "_sizes", sizes());
+}
+
+void Splitter::updateSizes()
+{
+ GuiConfig gc;
+ QValueList<int> sizes = gc.readIntListEntry(QString(name()) + "_sizes");
+ for (uint i=sizes.count(); i<_defaultSizes.count(); i++) sizes.append(_defaultSizes[i]);
+ setSizes(sizes);
+}
+
+//-----------------------------------------------------------------------------
+TabBar::TabBar(QWidget *parent, const char *name)
+ : KTabBar(parent, name), _ignoreWheelEvent(false)
+{}
+
+void TabBar::wheelEvent(QWheelEvent *e)
+{
+ if (_ignoreWheelEvent) QApplication::sendEvent(parent(), e); // #### not sure why ignoring is not enough...
+ else KTabBar::wheelEvent(e);
+}
+
+TabWidget::TabWidget(QWidget *parent, const char *name)
+ : KTabWidget(parent, name)
+{
+ setTabBar(new TabBar(this));
+}
+
+void TabWidget::setIgnoreWheelEvent(bool ignore)
+{
+ static_cast<TabBar *>(tabBar())->_ignoreWheelEvent = ignore;
+}
+
+void TabWidget::wheelEvent(QWheelEvent *e)
+{
+ if (static_cast<TabBar *>(tabBar())->_ignoreWheelEvent) e->ignore();
+ else KTabWidget::wheelEvent(e);
+}
+
+void TabWidget::setTabBar(TabBar *tabbar)
+{
+ KTabWidget::setTabBar(tabbar);
+ connect(tabBar(), SIGNAL(contextMenu( int, const QPoint & )), SLOT(contextMenu( int, const QPoint & )));
+ connect(tabBar(), SIGNAL(mouseDoubleClick( int )), SLOT(mouseDoubleClick( int )));
+ connect(tabBar(), SIGNAL(mouseMiddleClick( int )), SLOT(mouseMiddleClick( int )));
+ connect(tabBar(), SIGNAL(initiateDrag( int )), SLOT(initiateDrag( int )));
+ connect(tabBar(), SIGNAL(testCanDecode(const QDragMoveEvent *, bool & )), SIGNAL(testCanDecode(const QDragMoveEvent *, bool & )));
+ connect(tabBar(), SIGNAL(receivedDropEvent( int, QDropEvent * )), SLOT(receivedDropEvent( int, QDropEvent * )));
+ connect(tabBar(), SIGNAL(moveTab( int, int )), SLOT(moveTab( int, int )));
+ connect(tabBar(), SIGNAL(closeRequest( int )), SLOT(closeRequest( int )));
+ connect(tabBar(), SIGNAL(wheelDelta( int )), SLOT(wheelDelta( int )));
+}
+
+//-----------------------------------------------------------------------------
+ComboBox::ComboBox(QWidget *parent, const char *name)
+ : QComboBox(parent, name), _ignoreWheelEvent(false)
+{}
+
+void ComboBox::wheelEvent(QWheelEvent *e)
+{
+ if (_ignoreWheelEvent) QApplication::sendEvent(parent(), e); // #### not sure why ignoring is not enough...
+ else QComboBox::wheelEvent(e);
+}
diff --git a/src/common/gui/misc_gui.h b/src/common/gui/misc_gui.h
new file mode 100644
index 0000000..2d58569
--- /dev/null
+++ b/src/common/gui/misc_gui.h
@@ -0,0 +1,164 @@
+/***************************************************************************
+ * Copyright (C) 2006-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 MISC_GUI_H
+#define MISC_GUI_H
+
+#include <qlayout.h>
+#include <qsplitter.h>
+#include <qvaluevector.h>
+#include <qvalidator.h>
+#include <qcombobox.h>
+#include <qwidgetstack.h>
+
+#include <klocale.h>
+#include <kpushbutton.h>
+#include <ktabwidget.h>
+#include <ktabbar.h>
+#include <kstdguiitem.h>
+#include <klineedit.h>
+class KAction;
+
+#include "common/global/generic_config.h"
+#include "common/global/log.h"
+#include "common/common/number.h"
+
+//-----------------------------------------------------------------------------
+class BusyCursor
+{
+public:
+ BusyCursor() { start(); }
+ ~BusyCursor() { stop(); }
+ static void start();
+ static void stop();
+ static void pause();
+ static void restore();
+
+private:
+ static bool _overridePaused;
+};
+
+//-----------------------------------------------------------------------------
+namespace MessageBox
+{
+extern void information(const QString &text, Log::ShowMode show, const QString &dontShowAgainName = QString::null);
+extern void detailedSorry(const QString &text, const QString &details, Log::ShowMode show);
+inline void sorry(const QString &text, Log::ShowMode show) { detailedSorry(text, QString::null, show); }
+extern bool askContinue(const QString &text, const KGuiItem &continueButton = KStdGuiItem::cont(),
+ const QString &caption = i18n("Warning"));
+extern bool questionYesNo(const QString &text, const KGuiItem &yesButton, const KGuiItem &noButton,
+ const QString &caption = i18n("Warning"));
+enum Result { Yes, No, Cancel };
+extern Result questionYesNoCancel(const QString &text, const KGuiItem &yesButton, const KGuiItem &noButton,
+ const QString &caption = i18n("Warning"));
+extern void text(const QString &text, Log::ShowMode show);
+}
+
+//----------------------------------------------------------------------------
+class PopupButton : public KPushButton
+{
+Q_OBJECT
+public:
+ PopupButton(QWidget *parent = 0, const char *name = 0);
+ PopupButton(const QString &text, QWidget *parent = 0, const char *name = 0);
+ void appendAction(KAction *action);
+ void appendAction(const QString &label, const QString &icon = QString::null,
+ QObject *receiver = 0, const char *slot = 0);
+ int appendItem(const QString &label, uint id) { return appendItem(label, QPixmap(), id); }
+ int appendItem(const QString &label, const QString &icon, int id = -1);
+ int appendItem(const QString &label, const QPixmap &icon, int id = -1);
+ void appendSeparator() { _separator = true; }
+
+signals:
+ void activated(int id);
+
+private:
+ bool _separator;
+
+ void init();
+};
+
+//-----------------------------------------------------------------------------
+class Splitter : public QSplitter
+{
+Q_OBJECT
+public:
+ Splitter(const QValueList<int> &defaultSizes, Orientation orientation,
+ QWidget *parent, const char *name);
+ virtual ~Splitter();
+
+private slots:
+ void updateSizes();
+
+private:
+ QValueList<int> _defaultSizes;
+};
+
+//-----------------------------------------------------------------------------
+class GuiConfig : public GenericConfig
+{
+public:
+ GuiConfig() : GenericConfig("gui") {}
+};
+
+//-----------------------------------------------------------------------------
+class SeparatorWidget : public QFrame
+{
+Q_OBJECT
+public:
+ SeparatorWidget(QWidget *parent) : QFrame(parent, "separator") {
+ setFrameStyle(QFrame::Panel | QFrame::Sunken);
+ setMargin(2);
+ setFixedHeight(2*2);
+ }
+};
+
+//-----------------------------------------------------------------------------
+class TabBar : public KTabBar
+{
+Q_OBJECT
+public:
+ TabBar(QWidget *parent = 0, const char *name = 0);
+
+protected:
+ virtual void wheelEvent(QWheelEvent *e);
+
+private:
+ bool _ignoreWheelEvent;
+
+ friend class TabWidget;
+};
+
+class TabWidget : public KTabWidget
+{
+Q_OBJECT
+public:
+ TabWidget(QWidget *parent = 0, const char *name = 0);
+ void setIgnoreWheelEvent(bool ignore);
+
+protected:
+ virtual void wheelEvent(QWheelEvent *e);
+ void setTabBar(TabBar *tabbar);
+};
+
+//-----------------------------------------------------------------------------
+class ComboBox : public QComboBox
+{
+Q_OBJECT
+public:
+ ComboBox(QWidget *parent = 0, const char *name = 0);
+ void setIgnoreWheelEvent(bool ignore) { _ignoreWheelEvent = ignore; }
+
+protected:
+ virtual void wheelEvent(QWheelEvent *e);
+
+private:
+ bool _ignoreWheelEvent;
+};
+
+#endif
diff --git a/src/common/gui/number_gui.cpp b/src/common/gui/number_gui.cpp
new file mode 100644
index 0000000..d855407
--- /dev/null
+++ b/src/common/gui/number_gui.cpp
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * 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 "number_gui.h"
+
+#include <qfontmetrics.h>
+
+//-----------------------------------------------------------------------------
+uint maxCharWidth(const QString &s, const QFont &font)
+{
+ QFontMetrics fm(font);
+ uint w = 0;
+ for (uint i=0; i<uint(s.length()); i++)
+ w = QMAX(w, uint(fm.width(s[i])));
+ return w;
+}
+
+uint maxCharWidth(NumberBase base, const QFont &font)
+{
+ QString s;
+ for (uint i=0; i<base.data().base; i++) s += toChar(base, i);
+ return maxCharWidth(s, font);
+}
+
+uint maxLabelWidth(NumberBase base, uint nbChars, const QFont &font)
+{
+ uint w = maxStringWidth(base, nbChars, font);
+ QFontMetrics fm(font);
+ if ( base==NumberBase::String ) return w + 2 * fm.width("\"");
+ return w + fm.width(base.data().prefix);
+}
+
+//-----------------------------------------------------------------------------
+NumberLineEdit::NumberLineEdit(QWidget *parent, const char *name)
+ : KLineEdit(parent, name)
+{
+ connect(this, SIGNAL(textChanged(const QString &)), SLOT(textChangedSlot()));
+}
+
+NumberLineEdit::NumberLineEdit(const QString &text, QWidget *parent, const char *name)
+ : KLineEdit(text, parent, name)
+{
+ connect(this, SIGNAL(textChanged(const QString &)), SLOT(textChangedSlot()));
+}
+
+QValidator::State validateNumber(const QString &input)
+{
+ if ( input.isEmpty() ) return QValidator::Intermediate;
+ bool ok;
+ (void)fromAnyLabel(input, &ok);
+ if (ok) return QValidator::Acceptable;
+ FOR_EACH(NumberBase, base)
+ if ( input==base.data().prefix ) return QValidator::Intermediate;
+ if ( input[0]=='\"' ) return QValidator::Intermediate;
+ if ( input[0]=='\'' ) return QValidator::Intermediate;
+ return QValidator::Invalid;
+}
+
+void NumberLineEdit::textChangedSlot()
+{
+ QValidator::State state = validateNumber(text());
+ switch (state) {
+ case QValidator::Acceptable: unsetColor(); break;
+ case QValidator::Intermediate: setColor(QColor("#FF9900")); break;
+ case QValidator::Invalid: setColor(red); break;
+ }
+}
diff --git a/src/common/gui/number_gui.h b/src/common/gui/number_gui.h
new file mode 100644
index 0000000..f910820
--- /dev/null
+++ b/src/common/gui/number_gui.h
@@ -0,0 +1,40 @@
+/***************************************************************************
+ * 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 NUMBER_GUI_H
+#define NUMBER_GUI_H
+
+#include <qvalidator.h>
+#include <klineedit.h>
+
+#include "common/common/number.h"
+
+//-----------------------------------------------------------------------------
+extern uint maxCharWidth(const QString &s, const QFont &font);
+extern uint maxCharWidth(NumberBase base, const QFont &font);
+inline uint maxStringWidth(NumberBase base, uint nbChars, const QFont &font) { return nbChars * maxCharWidth(base, font); }
+extern uint maxLabelWidth(NumberBase base, uint nbChars, const QFont &font);
+
+extern QValidator::State validateNumber(const QString &s);
+
+//-----------------------------------------------------------------------------
+class NumberLineEdit : public KLineEdit
+{
+Q_OBJECT
+public:
+ NumberLineEdit(QWidget *parent = 0, const char *name = 0);
+ NumberLineEdit(const QString &text, QWidget *parent = 0, const char *name = 0);
+ uint value(bool *ok = 0) const { return fromAnyLabel(text(), ok); }
+ void setColor(const QColor &color) { setPaletteForegroundColor(color); }
+ void unsetColor() { unsetPalette(); }
+
+private slots:
+ void textChangedSlot();
+};
+
+#endif
diff --git a/src/common/gui/pfile_ext.cpp b/src/common/gui/pfile_ext.cpp
new file mode 100644
index 0000000..d42de16
--- /dev/null
+++ b/src/common/gui/pfile_ext.cpp
@@ -0,0 +1,114 @@
+/***************************************************************************
+ * 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_ext.h"
+
+#include <qfile.h>
+#include <kio/netaccess.h>
+#include <ktempfile.h>
+#include "common/gui/misc_gui.h"
+
+//-----------------------------------------------------------------------------
+bool PURL::File::openForWrite()
+{
+ close();
+ if (_tmp) delete _tmp;
+ _tmp = new KTempFile(QString::null, _extension);
+ _tmp->setAutoDelete(true);
+ if ( _tmp->status()!=0 ) {
+ _error = i18n("Could not create temporary file.");
+ _log.sorry(_error, i18n("File: %1").arg(_tmp->name()));
+ return false;
+ }
+ return true;
+}
+
+bool PURL::File::close()
+{
+ if (_tmp) _tmp->close();
+ else _file->close();
+ bool ok = (_tmp ? _tmp->status() : _file->status())==IO_Ok;
+ if ( !_file->name().isEmpty() ) {
+ KIO::NetAccess::removeTempFile(_file->name());
+ _file->setName(QString::null);
+ }
+ delete _stream;
+ _stream = 0;
+ if ( ok && _tmp && !_url.isEmpty() && !KIO::NetAccess::upload(_tmp->name(), _url.kurl(), qApp->mainWidget()) ) {
+ _error = KIO::NetAccess::lastErrorString();
+ ok = false;
+ _log.sorry(i18n("Could not save file."), errorString());
+ }
+ delete _tmp;
+ _tmp = 0;
+ return ok;
+}
+
+bool PURL::File::openForRead()
+{
+ close();
+ QString tmp;
+ if ( !KIO::NetAccess::download(_url.kurl(), tmp, qApp->mainWidget()) ) {
+ _error = KIO::NetAccess::lastErrorString();
+ _log.sorry(i18n("Could not open file for reading."), errorString());
+ return false;
+ }
+ _file->setName(tmp);
+ if ( !_file->open(IO_ReadOnly) ) {
+ _error = i18n("Could not open temporary file.");
+ _log.sorry(_error, i18n("File: %1").arg(_file->name()));
+ return false;
+ }
+ return true;
+}
+
+bool PURL::File::remove()
+{
+ close();
+ if ( !_url.isEmpty() ) return _url.del(_log);
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+PURL::TempFile::TempFile(Log::Generic &log, const QString &extension)
+ : FileBase(log, extension)
+{}
+
+PURL::Url PURL::TempFile::url() const
+{
+ return (_tmp ? Url::fromPathOrUrl(_tmp->name()) : Url());
+}
+
+bool PURL::TempFile::close()
+{
+ delete _stream;
+ _stream = 0;
+ if (_tmp) {
+ _tmp->close();
+ if ( _tmp->status()!=IO_Ok ) {
+ _error = i18n("Could not write to temporary file.");
+ _log.sorry(_error, i18n("File: %1").arg(_tmp->name()));
+ return false;
+ }
+ }
+ return true;
+}
+
+bool PURL::TempFile::openForWrite()
+{
+ close();
+ if (_tmp) delete _tmp;
+ _tmp = new KTempFile(QString::null, _extension);
+ _tmp->setAutoDelete(true);
+ if ( _tmp->status()!=0 ) {
+ _error = i18n("Could not create temporary file.");
+ _log.sorry(_error, i18n("File: %1").arg(_tmp->name()));
+ return false;
+ }
+ return true;
+}
diff --git a/src/common/gui/pfile_ext.h b/src/common/gui/pfile_ext.h
new file mode 100644
index 0000000..14c007a
--- /dev/null
+++ b/src/common/gui/pfile_ext.h
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * 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_EXT_H
+#define PFILE_EXT_H
+
+#include "common/global/pfile.h"
+
+namespace PURL
+{
+
+class TempFile : public FileBase
+{
+public:
+ TempFile(Log::Generic &log, const QString &extension = QString::null);
+ ~TempFile() { close(); }
+ Url url() const;
+ bool close();
+ bool openForWrite();
+};
+
+} // namespace
+
+#endif
diff --git a/src/common/gui/purl_ext.cpp b/src/common/gui/purl_ext.cpp
new file mode 100644
index 0000000..5d69d05
--- /dev/null
+++ b/src/common/gui/purl_ext.cpp
@@ -0,0 +1,111 @@
+/***************************************************************************
+ * 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 "common/global/purl.h"
+
+#include <qfile.h>
+#include <qapplication.h>
+#include <kio/netaccess.h>
+#include <kfileitem.h>
+#include <ktempfile.h>
+#include <kconfigbackend.h>
+
+#include "common/global/pfile.h"
+
+bool PURL::Url::copyTo(const Url &destination, Log::Generic &log) const
+{
+//#if defined(NO_KDE)
+// Synchronous sync;
+// if ( sync.op().copy(_url.filepath(), destination.filepath()) && sync.execute() ) {
+// if ( show==Log::Show ) ConsoleView::sorry(i18n("Could not copy file"), sync.error());
+// return false;
+// }
+//#else
+ // do not overwrite
+ bool ok = KIO::NetAccess::file_copy(_url, destination._url, -1, false, false, qApp->mainWidget());
+ if ( !ok ) log.sorry(i18n("Could not copy file"), KIO::NetAccess::lastErrorString());
+ return ok;
+//#endif
+}
+
+bool PURL::Url::create(Log::Generic &log) const
+{
+//#if defined(NO_KDE)
+// QByteArray a;
+// Synchronous sync;
+// if ( sync.op().put(a, _url.filepath()) && sync.execute() ) {
+// if ( show==Log::Show ) ConsoleView::sorry(i18n("Could not create file"), sync.error());
+// return false;
+// }
+//#else
+ // assume file do no exist if ioslave cannot tell...
+ if ( KIO::NetAccess::exists(_url, false, qApp->mainWidget()) ) return true;
+ KTempFile tmp;
+ tmp.setAutoDelete(true);
+ // do not overwrite
+ bool ok = KIO::NetAccess::file_copy(tmp.name(), _url, -1, false, false, qApp->mainWidget());
+ if ( !ok ) log.sorry(i18n("Could not create file"), KIO::NetAccess::lastErrorString());
+//#endif
+ return ok;
+}
+
+bool PURL::Url::write(const QString &text, Log::Generic &log) const
+{
+ File file(*this, log);
+ if ( !file.openForWrite() ) return false;
+ file.stream() << text;
+ return file.close();
+}
+
+bool PURL::Url::del(Log::Generic &log) const
+{
+//#if defined(NO_KDE)
+// Synchronous sync;
+// if ( sync.op().remove(_url.filepath()) && sync.execute() ) {
+// if ( show==Log::Show ) ConsoleView::sorry(i18n("Could not delete file"), sync.error());
+// return false;
+// }
+//#else
+ bool ok = KIO::NetAccess::del(_url, qApp->mainWidget());
+ if ( !ok ) log.sorry(i18n("Could not delete file."), KIO::NetAccess::lastErrorString());
+ return ok;
+//#endif
+}
+
+bool PURL::Url::isDosFile() const
+{
+ Log::Base log;
+ File file(*this, log);
+ if( !file.openForRead() ) return false;
+ int oldc = 0;
+ for (;;) {
+ int c = file.qfile()->getch();
+ if ( c==-1 ) break;
+ if( c=='\n' && oldc=='\r' ) return true;
+ oldc = c;
+ }
+ return false;
+}
+
+//-----------------------------------------------------------------------------
+bool PURL::Directory::create(Log::Generic &log) const
+{
+//#if defined(NO_KDE)
+// Synchronous sync;
+// if ( sync.op().mkdir(_url.filepath()) && sync.execute() ) {
+// if ( show==Log::Show ) ConsoleView::sorry(i18n("Could not create directory"), sync.error());
+// return false;
+// }
+//#else
+ // assume dir do no exist if ioslave cannot tell...
+ if ( KIO::NetAccess::exists(_url, false, qApp->mainWidget()) ) return true;
+ bool ok = KIO::NetAccess::mkdir(_url, qApp->mainWidget());
+ if ( !ok ) log.sorry(i18n("Could not create directory"), KIO::NetAccess::lastErrorString());
+//#endif
+ return ok;
+}
diff --git a/src/common/gui/purl_gui.cpp b/src/common/gui/purl_gui.cpp
new file mode 100644
index 0000000..d81fdb6
--- /dev/null
+++ b/src/common/gui/purl_gui.cpp
@@ -0,0 +1,151 @@
+/***************************************************************************
+ * 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 "purl_gui.h"
+
+#include <qlayout.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+#include <krun.h>
+#include <kfiledialog.h>
+#include <kdirselectdialog.h>
+
+#include "misc_gui.h"
+
+//-----------------------------------------------------------------------------
+PURL::Url PURL::getOpenUrl(const QString &startDir, const QString &filter,
+ QWidget *widget, const QString &caption)
+{
+ return KFileDialog::getOpenURL(startDir, filter, widget, caption);
+}
+
+PURL::UrlList PURL::getOpenUrls(const QString &startDir, const QString &filter,
+ QWidget *widget, const QString &caption)
+{
+ return KFileDialog::getOpenURLs(startDir, filter, widget, caption);
+}
+
+PURL::Url PURL::getSaveUrl(const QString &startDir, const QString &filter,
+ QWidget *widget, const QString &caption,
+ SaveAction action)
+{
+ Url url = KFileDialog::getSaveURL(startDir, filter, widget, caption);
+ if ( url.isEmpty() ) return Url();
+ switch (action) {
+ case NoSaveAction: break;
+ case AskOverwrite:
+ if ( url.exists() ) {
+ if ( !MessageBox::askContinue(i18n("File \"%1\" already exists. Overwrite ?").arg(url.pretty())) ) return Url();
+ }
+ break;
+ case CancelIfExists:
+ if ( url.exists() ) return Url();
+ break;
+ }
+ return url;
+}
+
+PURL::Directory PURL::getExistingDirectory(const QString &startDir, QWidget *widget,
+ const QString &caption)
+{
+ KURL kurl = KDirSelectDialog::selectDirectory(startDir, false, widget, caption);
+ if ( kurl.isEmpty() ) return Directory();
+ return Directory(kurl.path(1));
+}
+
+QPixmap PURL::icon(FileType type)
+{
+ if (type.data().xpm_icon) return QPixmap(type.data().xpm_icon);
+ if ( hasMimetype(type) ) return KMimeType::mimeType(type.data().mimetype)->pixmap(KIcon::Small);
+ return QPixmap();
+}
+
+bool PURL::hasMimetype(FileType type)
+{
+ if ( type.data().mimetype==0 ) return false;
+ KMimeType::Ptr ptr = KMimeType::mimeType(type.data().mimetype);
+ return ( ptr!=KMimeType::defaultMimeTypePtr() );
+}
+
+//-----------------------------------------------------------------------------
+PURL::Label::Label(const QString &url, const QString &text,
+ QWidget *parent, const char *name)
+ : KURLLabel(url, text, parent, name)
+{
+ connect(this, SIGNAL(leftClickedURL()), SLOT(urlClickedSlot()));
+}
+
+void PURL::Label::urlClickedSlot()
+{
+ (void)new KRun(url());
+}
+
+//-----------------------------------------------------------------------------
+PURL::BaseWidget::BaseWidget(QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{
+ init();
+}
+
+PURL::BaseWidget::BaseWidget(const QString &defaultDir, QWidget *parent, const char *name)
+ : QWidget(parent, name), _defaultDir(defaultDir)
+{
+ init();
+}
+
+void PURL::BaseWidget::init()
+{
+ QHBoxLayout *top = new QHBoxLayout(this, 0, 10);
+
+ _edit = new KLineEdit(this);
+ connect(_edit, SIGNAL(textChanged(const QString &)), SIGNAL(changed()));
+ top->addWidget(_edit);
+ KIconLoader loader;
+ QIconSet iconset = loader.loadIcon("fileopen", KIcon::Toolbar);
+ QPushButton *button = new KPushButton(iconset, QString::null, this);
+ connect(button, SIGNAL(clicked()), SLOT(buttonClicked()));
+ top->addWidget(button);
+}
+
+//----------------------------------------------------------------------------
+void PURL::DirectoryWidget::buttonClicked()
+{
+ Directory dir = getExistingDirectory(_defaultDir, this, i18n("Select Directory"));
+ if ( dir.isEmpty() ) return;
+ _edit->setText(dir.path());
+ emit changed();
+}
+
+//----------------------------------------------------------------------------
+PURL::DirectoriesWidget::DirectoriesWidget(const QString &title, QWidget *parent, const char *name)
+ : QVGroupBox(title, parent, name)
+{
+ init(QString::null);
+}
+
+PURL::DirectoriesWidget::DirectoriesWidget(const QString &title, const QString &defaultDir, QWidget *parent, const char *name)
+ : QVGroupBox(title, parent, name)
+{
+ init(defaultDir);
+}
+
+void PURL::DirectoriesWidget::init(const QString &defaultDir)
+{
+ DirectoryWidget *edit = new DirectoryWidget(defaultDir);
+ _editListBox = new EditListBox(1, edit, edit->lineEdit(), this, "directories_editlistbox");
+ connect(_editListBox, SIGNAL(changed()), SIGNAL(changed()));
+}
+
+//----------------------------------------------------------------------------
+void PURL::UrlWidget::buttonClicked()
+{
+ Url url = getOpenUrl(_defaultDir, _filter, this, i18n("Select File"));
+ if ( url.isEmpty() ) return;
+ _edit->setText(url.filepath());
+ emit changed();
+}
diff --git a/src/common/gui/purl_gui.h b/src/common/gui/purl_gui.h
new file mode 100644
index 0000000..a11bedf
--- /dev/null
+++ b/src/common/gui/purl_gui.h
@@ -0,0 +1,120 @@
+/***************************************************************************
+ * Copyright (C) 2006-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 PURL_GUI_H
+#define PURL_GUI_H
+
+#include <qvgroupbox.h>
+#include <klineedit.h>
+#include <klocale.h>
+#include <kurllabel.h>
+
+#include "common/global/purl.h"
+#include "editlistbox.h"
+
+namespace PURL
+{
+//-----------------------------------------------------------------------------
+extern bool hasMimetype(FileType type);
+extern QPixmap icon(FileType type);
+extern Directory getExistingDirectory(const QString &startDir, QWidget *widget, const QString &caption);
+extern Url getOpenUrl(const QString &startDir, const QString &filter, QWidget *widget,
+ const QString &caption);
+extern UrlList getOpenUrls(const QString &startDir, const QString &filter, QWidget *widget,
+ const QString &caption);
+enum SaveAction { NoSaveAction, AskOverwrite, CancelIfExists };
+extern Url getSaveUrl(const QString &startDir, const QString &filter, QWidget *widget,
+ const QString &caption, SaveAction action);
+
+//-----------------------------------------------------------------------------
+class Label : public KURLLabel
+{
+Q_OBJECT
+public:
+ Label(const QString &url, const QString &text, QWidget *parent = 0, const char *name = 0);
+
+private slots:
+ void urlClickedSlot();
+};
+
+//-----------------------------------------------------------------------------
+class BaseWidget : public QWidget
+{
+Q_OBJECT
+public:
+ BaseWidget(QWidget *parent = 0, const char *name = 0);
+ BaseWidget(const QString &defaultDir, QWidget *parent = 0, const char *name = 0);
+ KLineEdit *lineEdit() { return _edit; }
+
+signals:
+ void changed();
+
+protected slots:
+ virtual void buttonClicked() = 0;
+
+protected:
+ QString _defaultDir;
+ KLineEdit *_edit;
+
+ void init();
+};
+
+//-----------------------------------------------------------------------------
+class DirectoryWidget : public BaseWidget
+{
+Q_OBJECT
+public:
+ DirectoryWidget(QWidget *parent = 0, const char *name = 0) : BaseWidget(parent, name) {}
+ DirectoryWidget(const QString &defaultDir, QWidget *parent = 0, const char *name = 0) : BaseWidget(defaultDir, parent, name) {}
+ void setDirectory(const Directory &dir) { _edit->setText(dir.path()); }
+ Directory directory() const { return _edit->text(); }
+
+protected slots:
+ virtual void buttonClicked();
+};
+
+//-----------------------------------------------------------------------------
+class DirectoriesWidget : public QVGroupBox
+{
+Q_OBJECT
+public:
+ DirectoriesWidget(const QString &title, QWidget *parent = 0, const char *name = 0);
+ DirectoriesWidget(const QString &title, const QString &defaultDir, QWidget *parent = 0, const char *name = 0);
+ void setDirectories(const QStringList &dirs) { _editListBox->setTexts(dirs); }
+ QStringList directories() const { return _editListBox->texts(); }
+
+signals:
+ void changed();
+
+private:
+ EditListBox *_editListBox;
+ void init(const QString &defaultDir);
+};
+
+//-----------------------------------------------------------------------------
+class UrlWidget : public BaseWidget
+{
+Q_OBJECT
+public:
+ UrlWidget(const QString &filter, QWidget *parent = 0, const char *name = 0)
+ : BaseWidget(parent, name), _filter(filter) {}
+ UrlWidget(const QString &defaultDir, const QString &filter, QWidget *parent = 0, const char *name = 0)
+ : BaseWidget(defaultDir, parent, name), _filter(filter) {}
+ Url url() const { return PURL::Url::fromPathOrUrl(_edit->text()); }
+ void setUrl(const Url &url) { _edit->setText(url.filepath()); }
+
+protected slots:
+ virtual void buttonClicked();
+
+private:
+ QString _filter;
+};
+
+} // namespace
+
+#endif
diff --git a/src/common/nokde/nokde.pro b/src/common/nokde/nokde.pro
new file mode 100644
index 0000000..aa92599
--- /dev/null
+++ b/src/common/nokde/nokde.pro
@@ -0,0 +1,8 @@
+STOPDIR = ../../..
+include($${STOPDIR}/lib.pro)
+
+TARGET = nokde
+HEADERS += nokde_klocale.h nokde_kaboutdata.h nokde_kcmdlineargs.h nokde_kprocess.h
+SOURCES += nokde_klocale.cpp nokde_kaboutdata.cpp nokde_kcmdlineargs.cpp nokde_kprocess.cpp
+win32:HEADERS += win32_utils.h
+win32:SOURCES += win32_utils.c \ No newline at end of file
diff --git a/src/common/nokde/nokde_kaboutdata.cpp b/src/common/nokde/nokde_kaboutdata.cpp
new file mode 100644
index 0000000..21b6917
--- /dev/null
+++ b/src/common/nokde/nokde_kaboutdata.cpp
@@ -0,0 +1,469 @@
+// modified from KDE 3.4 for Windows port (Nicolas Hadacek)
+
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 2000 Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+
+#include "nokde_kaboutdata.h"
+//#include <kstandarddirs.h>
+#include <qfile.h>
+#include <qtextstream.h>
+#include <qstringlist.h>
+
+QString
+KAboutPerson::name() const
+{
+ return QString::fromUtf8(mName);
+}
+
+QString
+KAboutPerson::task() const
+{
+ if (mTask && *mTask)
+ return i18n(mTask);
+ else
+ return QString::null;
+}
+
+QString
+KAboutPerson::emailAddress() const
+{
+ return QString::fromUtf8(mEmailAddress);
+}
+
+
+QString
+KAboutPerson::webAddress() const
+{
+ return QString::fromUtf8(mWebAddress);
+}
+
+
+KAboutTranslator::KAboutTranslator(const QString & name,
+ const QString & emailAddress)
+{
+ mName=name;
+ mEmail=emailAddress;
+}
+
+QString KAboutTranslator::name() const
+{
+ return mName;
+}
+
+QString KAboutTranslator::emailAddress() const
+{
+ return mEmail;
+}
+
+class KAboutDataPrivate
+{
+public:
+ KAboutDataPrivate()
+ : translatorName("_: NAME OF TRANSLATORS\nYour names")
+ , translatorEmail("_: EMAIL OF TRANSLATORS\nYour emails")
+ , productName(0)
+// , programLogo(0)
+ {}
+ ~KAboutDataPrivate()
+ {
+// delete programLogo;
+ }
+ const char *translatorName;
+ const char *translatorEmail;
+ const char *productName;
+// QImage* programLogo;
+};
+
+
+
+KAboutData::KAboutData( const char *appName,
+ const char *programName,
+ const char *version,
+ const char *shortDescription,
+ int licenseType,
+ const char *copyrightStatement,
+ const char *text,
+ const char *homePageAddress,
+ const char *bugsEmailAddress
+ ) :
+ mProgramName( programName ),
+ mVersion( version ),
+ mShortDescription( shortDescription ),
+ mLicenseKey( licenseType ),
+ mCopyrightStatement( copyrightStatement ),
+ mOtherText( text ),
+ mHomepageAddress( homePageAddress ),
+ mBugEmailAddress( bugsEmailAddress ),
+ mLicenseText (0)
+{
+ d = new KAboutDataPrivate;
+
+ if( appName ) {
+ const char *p = strrchr(appName, '/');
+ if( p )
+ mAppName = p+1;
+ else
+ mAppName = appName;
+ } else
+ mAppName = 0;
+}
+
+KAboutData::~KAboutData()
+{
+ if (mLicenseKey == License_File)
+ delete [] mLicenseText;
+ delete d;
+}
+
+void
+KAboutData::addAuthor( const char *name, const char *task,
+ const char *emailAddress, const char *webAddress )
+{
+ mAuthorList.append(KAboutPerson(name,task,emailAddress,webAddress));
+}
+
+void
+KAboutData::addCredit( const char *name, const char *task,
+ const char *emailAddress, const char *webAddress )
+{
+ mCreditList.append(KAboutPerson(name,task,emailAddress,webAddress));
+}
+
+void
+KAboutData::setTranslator( const char *name, const char *emailAddress)
+{
+ d->translatorName=name;
+ d->translatorEmail=emailAddress;
+}
+
+void
+KAboutData::setLicenseText( const char *licenseText )
+{
+ mLicenseText = licenseText;
+ mLicenseKey = License_Custom;
+}
+
+void
+KAboutData::setLicenseTextFile( const QString &file )
+{
+ mLicenseText = qstrdup(QFile::encodeName(file));
+ mLicenseKey = License_File;
+}
+
+void
+KAboutData::setAppName( const char *appName )
+{
+ mAppName = appName;
+}
+
+void
+KAboutData::setProgramName( const char* programName )
+{
+ mProgramName = programName;
+}
+
+void
+KAboutData::setVersion( const char* version )
+{
+ mVersion = version;
+}
+
+void
+KAboutData::setShortDescription( const char *shortDescription )
+{
+ mShortDescription = shortDescription;
+}
+
+void
+KAboutData::setLicense( LicenseKey licenseKey)
+{
+ mLicenseKey = licenseKey;
+}
+
+void
+KAboutData::setCopyrightStatement( const char *copyrightStatement )
+{
+ mCopyrightStatement = copyrightStatement;
+}
+
+void
+KAboutData::setOtherText( const char *otherText )
+{
+ mOtherText = otherText;
+}
+
+void
+KAboutData::setHomepage( const char *homepage )
+{
+ mHomepageAddress = homepage;
+}
+
+void
+KAboutData::setBugAddress( const char *bugAddress )
+{
+ mBugEmailAddress = bugAddress;
+}
+
+void
+KAboutData::setProductName( const char *productName )
+{
+ d->productName = productName;
+}
+
+const char *
+KAboutData::appName() const
+{
+ return mAppName;
+}
+
+const char *
+KAboutData::productName() const
+{
+ if (d->productName)
+ return d->productName;
+ else
+ return appName();
+}
+
+QString
+KAboutData::programName() const
+{
+ if (mProgramName && *mProgramName)
+ return i18n(mProgramName);
+ else
+ return QString::null;
+}
+/*
+QImage
+KAboutData::programLogo() const
+{
+ return d->programLogo ? (*d->programLogo) : QImage();
+}
+
+void
+KAboutData::setProgramLogo(const QImage& image)
+{
+ if (!d->programLogo)
+ d->programLogo = new QImage( image );
+ else
+ *d->programLogo = image;
+}
+*/
+QString
+KAboutData::version() const
+{
+ return QString::fromLatin1(mVersion);
+}
+
+QString
+KAboutData::shortDescription() const
+{
+ if (mShortDescription && *mShortDescription)
+ return i18n(mShortDescription);
+ else
+ return QString::null;
+}
+
+QString
+KAboutData::homepage() const
+{
+ return QString::fromLatin1(mHomepageAddress);
+}
+
+QString
+KAboutData::bugAddress() const
+{
+ return QString::fromLatin1(mBugEmailAddress);
+}
+
+const QValueList<KAboutPerson>
+KAboutData::authors() const
+{
+ return mAuthorList;
+}
+
+const QValueList<KAboutPerson>
+KAboutData::credits() const
+{
+ return mCreditList;
+}
+
+const QValueList<KAboutTranslator>
+KAboutData::translators() const
+{
+ QValueList<KAboutTranslator> personList;
+
+ if(d->translatorName == 0)
+ return personList;
+
+ QStringList nameList;
+ QStringList emailList;
+
+ QString names = i18n(d->translatorName);
+ if(names != QString::fromUtf8(d->translatorName))
+ {
+#if QT_VERSION < 0x040000
+ nameList = QStringList::split(',',names);
+#else
+ nameList = names.split(',', QString::SkipEmptyParts);
+#endif
+ }
+
+
+ if(d->translatorEmail)
+ {
+ QString emails = i18n(d->translatorEmail);
+
+ if(emails != QString::fromUtf8(d->translatorEmail))
+ {
+#if QT_VERSION < 0x040000
+ emailList = QStringList::split(',',emails,true);
+#else
+ emailList = emails.split(',');
+#endif
+ }
+ }
+
+
+ QStringList::Iterator nit;
+ QStringList::Iterator eit=emailList.begin();
+
+ for(nit = nameList.begin(); nit != nameList.end(); ++nit)
+ {
+ QString email;
+ if(eit != emailList.end())
+ {
+ email=*eit;
+ ++eit;
+ }
+
+ QString name=*nit;
+
+#if QT_VERSION < 0x040000
+ personList.append(KAboutTranslator(name.stripWhiteSpace(), email.stripWhiteSpace()));
+#else
+ personList.append(KAboutTranslator(name.trimmed(), email.trimmed()));
+#endif
+ }
+
+ return personList;
+}
+
+QString
+KAboutData::aboutTranslationTeam()
+{
+ return i18n("replace this with information about your translation team",
+ "<p>KDE is translated into many languages thanks to the work "
+ "of the translation teams all over the world.</p>"
+ "<p>For more information on KDE internationalization "
+ "visit http://i18n.kde.org</p>");
+}
+
+QString
+KAboutData::otherText() const
+{
+ if (mOtherText && *mOtherText)
+ return i18n(mOtherText);
+ else
+ return QString::null;
+}
+
+
+QString
+KAboutData::license() const
+{
+ QString result;
+ if (!copyrightStatement().isEmpty())
+ result = copyrightStatement() + "\n\n";
+
+ QString l;
+ QString f;
+ switch ( mLicenseKey )
+ {
+ case License_File:
+ f = QFile::decodeName(mLicenseText);
+ break;
+ case License_GPL_V2:
+ l = "GPL v2";
+ f = locate("data", "LICENSES/GPL_V2");
+ break;
+ case License_LGPL_V2:
+ l = "LGPL v2";
+ f = locate("data", "LICENSES/LGPL_V2");
+ break;
+ case License_BSD:
+ l = "BSD License";
+ f = locate("data", "LICENSES/BSD");
+ break;
+ case License_Artistic:
+ l = "Artistic License";
+ f = locate("data", "LICENSES/ARTISTIC");
+ break;
+ case License_QPL_V1_0:
+ l = "QPL v1.0";
+ f = locate("data", "LICENSES/QPL_V1.0");
+ break;
+ case License_Custom:
+ if (mLicenseText && *mLicenseText)
+ return( i18n(mLicenseText) );
+ // fall through
+ default:
+ result += i18n("No licensing terms for this program have been specified.\n"
+ "Please check the documentation or the source for any\n"
+ "licensing terms.\n");
+ return result;
+ }
+
+ if (!l.isEmpty())
+ result += i18n("This program is distributed under the terms of the %1.").arg( l );
+
+ if (!f.isEmpty())
+ {
+ QFile file(f);
+#if QT_VERSION < 0x040000
+ if (file.open(IO_ReadOnly))
+#else
+ if (file.open(QIODevice::ReadOnly))
+#endif
+ {
+ result += '\n';
+ result += '\n';
+ QTextStream str(&file);
+#if QT_VERSION < 0x040000
+ result += str.read();
+#else
+ result += str.readAll();
+#endif
+ }
+ }
+
+ return result;
+}
+
+QString
+KAboutData::copyrightStatement() const
+{
+ if (mCopyrightStatement && *mCopyrightStatement)
+ return i18n(mCopyrightStatement);
+ else
+ return QString::null;
+}
diff --git a/src/common/nokde/nokde_kaboutdata.h b/src/common/nokde/nokde_kaboutdata.h
new file mode 100644
index 0000000..13076d4
--- /dev/null
+++ b/src/common/nokde/nokde_kaboutdata.h
@@ -0,0 +1,571 @@
+// modified from KDE 3.4 for Windows port (Nicolas Hadacek)
+
+/*
+ * This file is part of the KDE Libraries
+ * Copyright (C) 2000 Espen Sand (espen@kde.org)
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include <qglobal.h>
+#if QT_VERSION < 0x040000
+# include <qvaluelist.h>
+#else
+# include <Qt3Support/Q3ValueList>
+# define QValueList Q3ValueList
+# include <QStringList>
+#endif
+#include <qstring.h>
+//#include <qimage.h>
+
+#include "nokde_klocale.h"
+
+#ifndef _KABOUTDATA_H_
+#define _KABOUTDATA_H_
+
+class KAboutPersonPrivate;
+class KAboutDataPrivate;
+
+/**
+ * This structure is used to store information about a person or developer.
+ * It can store the person's name, a task, an email address and a
+ * link to a home page. This class is intended for use in the
+ * KAboutData class, but it can be used elsewhere as well.
+ * Normally you should at least define the person's name.
+ *
+ * Example Usage within a main():
+ *
+ * KAboutData about("khello", I18N_NOOP("KHello"), "0.1",
+ * I18N_NOOP("A KDE version of Hello, world!"),
+ * KAboutData::License_LGPL,
+ * I18N_NOOP("Copyright (c) 2003 Developer"));
+ *
+ * about.addAuthor("Joe Developer", I18N_NOOP("developer"), "joe@host.com", 0);
+ * about.addCredit("Joe User", I18N_NOOP("A lot of bug reports"),
+ * "joe.user@host.org", 0);
+ * KCmdLineArgs::init(argc, argv, &about);
+ */
+class KDECORE_EXPORT KAboutPerson
+{
+public:
+ /**
+ * Convenience constructor
+ *
+ * @param name The name of the person.
+ *
+ * @param task The task of this person. This string should be
+ * marked for translation, e.g.
+ * I18N_NOOP("Task description....")
+ *
+ * @param emailAddress The email address of the person.
+ *
+ * @param webAddress Home page of the person.
+ */
+ KAboutPerson( const char *name, const char *task,
+ const char *emailAddress, const char *webAddress )
+ {
+ mName = name;
+ mTask = task;
+ mEmailAddress = emailAddress;
+ mWebAddress = webAddress;
+ }
+ /**
+ * @internal
+ * Don't use. Required by QValueList
+ */
+ KAboutPerson() {}
+
+ /**
+ * The person's name
+ * @return the person's name (can be QString::null, if it has been
+ * constructed with a null name)
+ */
+ QString name() const;
+
+ /**
+ * The person's task
+ * @return the person's task (can be QString::null, if it has been
+ * constructed with a null task)
+ */
+ QString task() const;
+
+ /**
+ * The person's email address
+ * @return the person's email address (can be QString::null, if it has been
+ * constructed with a null email)
+ */
+ QString emailAddress() const;
+
+ /**
+ * The home page or a relevant link
+ * @return the persons home page (can be QString::null, if it has been
+ * constructed with a null home page)
+ */
+ QString webAddress() const;
+
+private:
+ const char *mName;
+ const char *mTask;
+ const char *mEmailAddress;
+ const char *mWebAddress;
+
+ KAboutPersonPrivate *d;
+};
+
+class KAboutTranslatorPrivate;
+/**
+ * This structure is used to store information about a translator.
+ * It can store the translator's name and an email address.
+ * This class is intended for use in the KAboutData class,
+ * but it can be used elsewhere as well.
+ * Normally you should at least define the translator's name.
+ *
+ * It's not possible to use KAboutPerson for this, because
+ * KAboutPerson stores internally only const char* pointers, but the
+ * translator information is generated dynamically from the translation
+ * of a dummy string.
+*/
+class KDECORE_EXPORT KAboutTranslator
+{
+public:
+ /**
+ * Convenience constructor
+ *
+ * @param name The name of the person.
+ *
+ * @param emailAddress The email address of the person.
+ */
+ KAboutTranslator(const QString & name=QString::null,
+ const QString & emailAddress=QString::null);
+
+ /**
+ * The translator's name
+ * @return the translators's name (can be QString::null, if it has been
+ * constructed with a null name)
+ */
+ QString name() const;
+
+ /**
+ * The translator's email
+ * @return the translator's email address (can be QString::null, if it has been
+ * constructed with a null email)
+ */
+ QString emailAddress() const;
+
+private:
+ QString mName;
+ QString mEmail;
+ KAboutTranslatorPrivate* d;
+};
+
+
+/**
+ * This class is used to store information about a program. It can store
+ * such values as version number, program name, home page, email address
+ * for bug reporting, multiple authors and contributors
+ * (using KAboutPerson), license and copyright information.
+ *
+ * Currently, the values set here are shown by the "About" box
+ * (see KAboutDialog), used by the bug report dialog (see KBugReport),
+ * and by the help shown on command line (see KCmdLineArgs).
+ *
+ * @short Holds information needed by the "About" box and other
+ * classes.
+ * @author Espen Sand (espen@kde.org), David Faure (faure@kde.org)
+ */
+class KDECORE_EXPORT KAboutData
+{
+ public:
+ /**
+ * Descibes the license of the software.
+ */
+ enum LicenseKey
+ {
+ License_Custom = -2,
+ License_File = -1,
+ License_Unknown = 0,
+ License_GPL = 1,
+ License_GPL_V2 = 1,
+ License_LGPL = 2,
+ License_LGPL_V2 = 2,
+ License_BSD = 3,
+ License_Artistic = 4,
+ License_QPL = 5,
+ License_QPL_V1_0 = 5
+ };
+
+ public:
+ /**
+ * Constructor.
+ *
+ * @param appName The program name used internally. Example: "kedit"
+ *
+ * @param programName A displayable program name string. This string
+ * should be marked for translation. Example: I18N_NOOP("KEdit")
+ *
+ * @param version The program version string.
+ *
+ * @param shortDescription A short description of what the program does.
+ * This string should be marked for translation.
+ * Example: I18N_NOOP("A simple text editor.")
+ *
+ * @param licenseType The license identifier. Use setLicenseText if
+ * you use a license not predefined here.
+ *
+ * @param copyrightStatement A copyright statement, that can look like this:
+ * "(c) 1999-2000, Name". The string specified here is not modified
+ * in any manner. The author information from addAuthor is not
+ * used.
+ *
+ * @param text Some free form text, that can contain any kind of
+ * information. The text can contain newlines. This string
+ * should be marked for translation.
+ *
+ * @param homePageAddress The program homepage string.
+ * Start the address with "http://". "http://some.domain" is
+ * is correct, "some.domain" is not.
+ *
+ * @param bugsEmailAddress The bug report email address string.
+ * This defaults to the kde.org bug system.
+ *
+ */
+ KAboutData( const char *appName,
+ const char *programName,
+ const char *version,
+ const char *shortDescription = 0,
+ int licenseType = License_Unknown,
+ const char *copyrightStatement = 0,
+ const char *text = 0,
+ const char *homePageAddress = 0,
+ const char *bugsEmailAddress = "submit@bugs.kde.org"
+ );
+
+ ~KAboutData();
+
+ /**
+ * Defines an author. You can call this function as many times you
+ * need. Each entry is appended to a list. The person in the first entry
+ * is assumed to be the leader of the project.
+ *
+ * @param name The developer's name in UTF-8 encoding.
+ *
+ * @param task What the person is responsible for. This text can contain
+ * newlines. It should be marked for translation like this:
+ * I18N_NOOP("Task description..."). Can be 0.
+ *
+ * @param emailAddress An Email address where the person can be reached.
+ * Can be 0.
+ *
+ * @param webAddress The person's homepage or a relevant link.
+ * Start the address with "http://". "http://some.domain" is
+ * correct, "some.domain" is not. Can be 0.
+ *
+ */
+ void addAuthor( const char *name,
+ const char *task=0,
+ const char *emailAddress=0,
+ const char *webAddress=0 );
+
+ /**
+ * Defines a person that deserves credit. You can call this function
+ * as many times you need. Each entry is appended to a list.
+ *
+ * @param name The person's name in UTF-8 encoding.
+ *
+ * @param task What the person has done to deserve the honor. The
+ * text can contain newlines. It should be marked for
+ * translation like this: I18N_NOOP("Task description...")
+ * Can be 0.
+ *
+ * @param emailAddress An Email address when the person can be reached.
+ * Can be 0.
+ *
+ * @param webAddress The person's homepage or a relevant link.
+ * Start the address with "http://". "http://some.domain" is
+ * is correct, "some.domain" is not. Can be 0.
+ *
+ */
+ void addCredit( const char *name,
+ const char *task=0,
+ const char *emailAddress=0,
+ const char *webAddress=0 );
+
+ /**
+ * Sets the name of the translator of the gui. Since this depends
+ * on the language, just use a dummy text marked for translation.
+ *
+ * For example:
+ * \code
+ * setTranslator(I18N_NOOP("_: NAME OF TRANSLATORS\\nYour names")
+ * ,I18N_NOOP("_: EMAIL OF TRANSLATORS\\nYour emails"));
+ * \endcode
+ *
+ * The translator can then translate this dummy text with his name
+ * or with a list of names separated with ",".
+ * If there is no translation or the application is used with the
+ * default language, this function call is ignored.
+ *
+ * Note: If you are using the default KDE automake environment,
+ * there is no need to use this function, because the two
+ * default strings above are added to the applications po file
+ * automatically.
+ *
+ * @param name the name of the translator
+ * @param emailAddress the email address of the translator
+ * @see KAboutTranslator
+ */
+ void setTranslator(const char* name, const char* emailAddress);
+
+ /**
+ * Defines a license text.
+ *
+ * The text will be translated if it got marked for
+ * translations with the I18N_NOOP() macro.
+ *
+ * Example:
+ * \code
+ * setLicenseText( I18N_NOOP("This is my license"));
+ * \endcode
+ *
+ * NOTE: No copy of the text is made.
+ *
+ * @param license The license text in utf8 encoding.
+ */
+ void setLicenseText( const char *license );
+
+ /**
+ * Defines a license text.
+ *
+ * @param file File containing the license text.
+ */
+ void setLicenseTextFile( const QString &file );
+
+ /**
+ * Defines the program name used internally.
+ *
+ * @param appName The application name. Example: "kate".
+ */
+ void setAppName( const char *appName );
+
+ /**
+ * Defines the displayable program name string.
+ *
+ * @param programName The program name. This string should be
+ * marked for translation.
+ * Example: I18N_NOOP("Advanced Text Editor").
+ */
+ void setProgramName( const char* programName );
+
+ /**
+ * Defines the program logo.
+ * Use this if you need to have application logo
+ * in AboutData other than application icon.
+ *
+ * @param image logo image.
+ * @see programLogo()
+ * @since 3.4
+ */
+// void setProgramLogo(const QImage& image);
+
+ /**
+ * Defines the program version string.
+ *
+ * @param version The program version.
+ */
+ void setVersion( const char* version );
+
+ /**
+ * Defines a short description of what the program does.
+ *
+ * @param shortDescription The program description This string should be marked
+ * for translation. Example: I18N_NOOP("An advanced text editor
+ * with syntax highlithing support.").
+ */
+ void setShortDescription( const char *shortDescription );
+
+ /**
+ * Defines the license identifier.
+ *
+ * @param licenseKey The license identifier.
+ */
+ void setLicense( LicenseKey licenseKey);
+
+ /**
+ * Defines the copyright statement to show when displaying the license.
+ *
+ * @param copyrightStatement A copyright statement, that can look like
+ * this: "(c) 1999-2000, Name". The string specified here is not
+ * modified in any manner. The author information from addAuthor
+ * is not used.
+ */
+ void setCopyrightStatement( const char *copyrightStatement );
+
+ /**
+ * Defines the additional text to show in the about dialog.
+ *
+ * @param otherText Some free form text, that can contain any kind of
+ * information. The text can contain newlines. This string
+ * should be marked for translation.
+ */
+ void setOtherText( const char *otherText );
+
+ /**
+ * Defines the program homepage.
+ *
+ * @param homepage The program homepage string.
+ * Start the address with "http://". "http://kate.kde.org" is
+ * is correct, "kde.kde.org" is not.
+ */
+ void setHomepage( const char *homepage );
+
+ /**
+ * Defines the address where bug reports should be sent.
+ *
+ * @param bugAddress The bug report email address string.
+ * This defaults to the kde.org bug system.
+ */
+ void setBugAddress( const char *bugAddress );
+
+ /**
+ * Defines the product name wich will be used in the KBugReport dialog.
+ * By default it's the appName, but you can overwrite it here to provide
+ * support for special components e.g. 'product/component' like
+ * 'kontact/summary'.
+ *
+ * @param name The name of product
+ */
+ void setProductName( const char *name );
+
+ /**
+ * Returns the application's internal name.
+ * @return the internal program name.
+ */
+ const char *appName() const;
+
+ /**
+ * Returns the application's product name, which will be used in KBugReport
+ * dialog. By default it returns appName(), otherwise the one which is set
+ * with setProductName()
+ *
+ * @return the product name.
+ */
+ const char *productName() const;
+
+ /**
+ * Returns the translated program name.
+ * @return the program name (translated).
+ */
+ QString programName() const;
+
+ /**
+ * Returns the program logo image.
+ * @return the program logo data or null image if there is
+ * no custom application logo defined.
+ * @since 3.4
+ */
+// QImage programLogo() const;
+
+ /**
+ * Returns the program's version.
+ * @return the version string.
+ */
+ QString version() const;
+
+ /**
+ * Returns a short, translated description.
+ * @return the short description (translated). Can be
+ * QString::null if not set.
+ */
+ QString shortDescription() const;
+
+ /**
+ * Returns the application homepage.
+ * @return the application homepage URL. Can be QString::null if
+ * not set.
+ */
+ QString homepage() const;
+
+ /**
+ * Returns the email address for bugs.
+ * @return the email address where to report bugs.
+ */
+ QString bugAddress() const;
+
+ /**
+ * Returns a list of authors.
+ * @return author information (list of persons).
+ */
+ const QValueList<KAboutPerson> authors() const;
+
+ /**
+ * Returns a list of persons who contributed.
+ * @return credit information (list of persons).
+ */
+ const QValueList<KAboutPerson> credits() const;
+
+ /**
+ * Returns a list of translators.
+ * @return translators information (list of persons)
+ */
+ const QValueList<KAboutTranslator> translators() const;
+
+ /**
+ * Returns a message about the translation team.
+ * @return a message about the translation team
+ */
+ static QString aboutTranslationTeam();
+
+ /**
+ * Returns a translated, free form text.
+ * @return the free form text (translated). Can be QString::null if not set.
+ */
+ QString otherText() const;
+
+ /**
+ * Returns the license. If the licenseType argument of the constructor has been
+ * used, any text defined by setLicenseText is ignored,
+ * and the standard text for the chosen license will be returned.
+ *
+ * @return The license text.
+ */
+ QString license() const;
+
+ /**
+ * Returns the copyright statement.
+ * @return the copyright statement. Can be QString::null if not set.
+ */
+ QString copyrightStatement() const;
+
+ private:
+ const char *mAppName;
+ const char *mProgramName;
+ const char *mVersion;
+ const char *mShortDescription;
+ int mLicenseKey;
+ const char *mCopyrightStatement;
+ const char *mOtherText;
+ const char *mHomepageAddress;
+ const char *mBugEmailAddress;
+ QValueList<KAboutPerson> mAuthorList;
+ QValueList<KAboutPerson> mCreditList;
+ const char *mLicenseText;
+
+ KAboutDataPrivate *d;
+};
+
+#endif
+
diff --git a/src/common/nokde/nokde_kcmdlineargs.cpp b/src/common/nokde/nokde_kcmdlineargs.cpp
new file mode 100644
index 0000000..7f026fe
--- /dev/null
+++ b/src/common/nokde/nokde_kcmdlineargs.cpp
@@ -0,0 +1,1329 @@
+// modified from KDE 3.4 for Windows port (Nicolas Hadacek)
+
+/*
+ Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+//#include <config.h>
+
+#include <sys/param.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+
+#include <qdir.h>
+#include <qfile.h>
+#include <qurl.h>
+
+#include <qstringlist.h>
+#if QT_VERSION<0x040000
+# include <qasciidict.h>
+# include <qstrlist.h>
+#else
+# include <Qt3Support/Q3StrList>
+# define QGList Q3GList
+# define QStrList Q3StrList
+# include <Qt3Support/Q3AsciiDict>
+# define QGDict Q3GDict
+# define QAsciiDict Q3AsciiDict
+# include <Qt3Support/Q3PtrCollection>
+# define QPtrCollection Q3PtrCollection
+#endif
+
+
+#include "nokde_kcmdlineargs.h"
+#include "nokde_kaboutdata.h"
+#include "nokde_klocale.h"
+//#include <kapplication.h>
+//#include <kglobal.h>
+//#include <kstringhandler.h>
+//#include <kstaticdeleter.h>
+
+#ifdef Q_WS_X11
+#define DISPLAY "DISPLAY"
+#elif defined(Q_WS_QWS)
+#define DISPLAY "QWS_DISPLAY"
+#endif
+
+#ifdef Q_WS_WIN
+#include <win32_utils.h>
+#endif
+
+template class QAsciiDict<QCString>;
+template class QPtrList<KCmdLineArgs>;
+
+class KCmdLineParsedOptions : public QAsciiDict<QCString>
+{
+public:
+ KCmdLineParsedOptions()
+ : QAsciiDict<QCString>( 7 ) { }
+
+ // WABA: Huh?
+ // The compiler doesn't find KCmdLineParsedOptions::write(s) by itself ???
+ // WABA: No, because there is another write function that hides the
+ // write function in the base class even though this function has a
+ // different signature. (obscure C++ feature)
+ QDataStream& save( QDataStream &s) const
+ { return QGDict::write(s); }
+
+ QDataStream& load( QDataStream &s)
+ { return QGDict::read(s); }
+
+protected:
+ virtual QDataStream& write( QDataStream &s, QPtrCollection::Item data) const
+ {
+ QCString *str = (QCString *) data;
+ s << (*str);
+ return s;
+ }
+
+ virtual QDataStream& read( QDataStream &s, QPtrCollection::Item &item)
+ {
+ QCString *str = new QCString;
+ s >> (*str);
+ item = (void *)str;
+ return s;
+ }
+
+};
+
+class KCmdLineParsedArgs : public QStrList
+{
+public:
+ KCmdLineParsedArgs()
+ : QStrList( true ) { }
+ QDataStream& save( QDataStream &s) const
+ { return QGList::write(s); }
+
+ QDataStream& load( QDataStream &s)
+ { return QGList::read(s); }
+};
+
+
+class KCmdLineArgsList: public QPtrList<KCmdLineArgs>
+{
+public:
+ KCmdLineArgsList() { }
+};
+
+KCmdLineArgsList *KCmdLineArgs::argsList = 0;
+int KCmdLineArgs::argc = 0;
+char **KCmdLineArgs::argv = 0;
+char *KCmdLineArgs::mCwd = 0;
+//static KStaticDeleter <char> mCwdd;
+const KAboutData *KCmdLineArgs::about = 0;
+bool KCmdLineArgs::parsed = false;
+bool KCmdLineArgs::ignoreUnknown = false;
+
+//
+// Static functions
+//
+
+void
+KCmdLineArgs::init(int _argc, char **_argv, const char *_appname, const char* programName,
+ const char *_description, const char *_version, bool noKApp)
+{
+ init(_argc, _argv,
+ new KAboutData(_appname, programName, _version, _description),
+ noKApp);
+}
+
+void
+KCmdLineArgs::init(int _argc, char **_argv, const char *_appname,
+ const char *_description, const char *_version, bool noKApp)
+{
+ init(_argc, _argv,
+ new KAboutData(_appname, _appname, _version, _description),
+ noKApp);
+}
+
+void
+KCmdLineArgs::initIgnore(int _argc, char **_argv, const char *_appname )
+{
+ init(_argc, _argv,
+ new KAboutData(_appname, _appname, "unknown", "KDE Application", false));
+ ignoreUnknown = true;
+}
+
+void
+KCmdLineArgs::init(const KAboutData* ab)
+{
+ char **_argv = (char **) malloc(sizeof(char *));
+ _argv[0] = (char *) ab->appName();
+ init(1,_argv,ab, true);
+}
+
+
+void
+KCmdLineArgs::init(int _argc, char **_argv, const KAboutData *_about, bool /*noKApp*/)
+{
+ argc = _argc;
+ argv = _argv;
+
+ if (!argv)
+ {
+ fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
+ fprintf(stderr, "Passing null-pointer to 'argv' is not allowed.\n\n");
+
+ assert( 0 );
+ exit(255);
+ }
+
+ // Strip path from argv[0]
+ if (argc) {
+ char *p = strrchr( argv[0], '/');
+ if (p)
+ argv[0] = p+1;
+ }
+
+ about = _about;
+ parsed = false;
+ mCwd = /*mCwdd.setObject(mCwd, */new char [PATH_MAX+1];//, true);
+ getcwd(mCwd, PATH_MAX);
+#ifdef Q_WS_WIN
+ win32_slashify(mCwd, PATH_MAX);
+#endif
+// if (!noKApp)
+// KApplication::addCmdLineOptions();
+}
+
+QString KCmdLineArgs::cwd()
+{
+ return QFile::decodeName(QCString(mCwd));
+}
+
+const char * KCmdLineArgs::appName()
+{
+ if (!argc) return 0;
+ return argv[0];
+}
+
+void
+KCmdLineArgs::addCmdLineOptions( const KCmdLineOptions *options, const char *name,
+ const char *id, const char *afterId)
+{
+ if (!argsList)
+ argsList = new KCmdLineArgsList();
+
+ int pos = argsList->count();
+
+ if (pos && id && argsList->last() && !argsList->last()->name)
+ pos--;
+
+ KCmdLineArgs *args;
+ int i = 0;
+ for(args = argsList->first(); args; args = argsList->next(), i++)
+ {
+ if (!id && !args->id)
+ return; // Options already present.
+
+ if (id && args->id && (::qstrcmp(id, args->id) == 0))
+ return; // Options already present.
+
+ if (afterId && args->id && (::qstrcmp(afterId, args->id) == 0))
+ pos = i+1;
+ }
+
+ assert( parsed == false ); // You must add _ALL_ cmd line options
+ // before accessing the arguments!
+ args = new KCmdLineArgs(options, name, id);
+ argsList->insert(pos, args);
+}
+
+void
+KCmdLineArgs::saveAppArgs( QDataStream &ds)
+{
+ if (!parsed)
+ parseAllArgs();
+
+ // Remove Qt and KDE options.
+ removeArgs("qt");
+ removeArgs("kde");
+
+ QCString qCwd = mCwd;
+ ds << qCwd;
+
+ uint count = argsList ? argsList->count() : 0;
+ ds << count;
+
+ if (!count) return;
+
+ KCmdLineArgs *args;
+ for(args = argsList->first(); args; args = argsList->next())
+ {
+ ds << QCString(args->id);
+ args->save(ds);
+ }
+}
+
+void
+KCmdLineArgs::loadAppArgs( QDataStream &ds)
+{
+ // Remove Qt and KDE options.
+ removeArgs("qt");
+ removeArgs("kde");
+
+ KCmdLineArgs *args;
+ if ( argsList ) {
+ for(args = argsList->first(); args; args = argsList->next())
+ {
+ args->clear();
+ }
+ }
+
+ if (ds.atEnd())
+ return;
+
+ QCString qCwd;
+ ds >> qCwd;
+ delete [] mCwd;
+
+ mCwd = /*mCwdd.setObject(mCwd, */new char[qCwd.length()+1];//, true);
+ strncpy(mCwd, qCwd.data(), qCwd.length()+1);
+
+ uint count;
+ ds >> count;
+
+ while(count--)
+ {
+ QCString id;
+ ds >> id;
+ assert( argsList );
+ for(args = argsList->first(); args; args = argsList->next())
+ {
+ if (args->id == id)
+ {
+ args->load(ds);
+ break;
+ }
+ }
+ }
+ parsed = true;
+}
+
+KCmdLineArgs *KCmdLineArgs::parsedArgs(const char *id)
+{
+ KCmdLineArgs *args = argsList ? argsList->first() : 0;
+ while(args)
+ {
+ if ((id && ::qstrcmp(args->id, id) == 0) || (!id && !args->id))
+ {
+ if (!parsed)
+ parseAllArgs();
+ return args;
+ }
+ args = argsList->next();
+ }
+
+ return args;
+}
+
+void KCmdLineArgs::removeArgs(const char *id)
+{
+ KCmdLineArgs *args = argsList ? argsList->first() : 0;
+ while(args)
+ {
+ if (args->id && id && ::qstrcmp(args->id, id) == 0)
+ {
+ if (!parsed)
+ parseAllArgs();
+ break;
+ }
+ args = argsList->next();
+ }
+
+ if (args)
+ delete args;
+}
+
+/*
+ * @return:
+ * 0 - option not found.
+ * 1 - option found // -fork
+ * 2 - inverse option found ('no') // -nofork
+ * 3 - option + arg found // -fork now
+ *
+ * +4 - no more options follow // !fork
+ */
+static int
+findOption(const KCmdLineOptions *options, QCString &opt,
+ const char *&opt_name, const char *&def, bool &enabled)
+{
+ int result;
+ bool inverse;
+ int len = opt.length();
+ while(options && options->name)
+ {
+ result = 0;
+ inverse = false;
+ opt_name = options->name;
+ if ((opt_name[0] == ':') || (opt_name[0] == 0))
+ {
+ options++;
+ continue;
+ }
+
+ if (opt_name[0] == '!')
+ {
+ opt_name++;
+ result = 4;
+ }
+ if ((opt_name[0] == 'n') && (opt_name[1] == 'o'))
+ {
+ opt_name += 2;
+ inverse = true;
+ }
+ if (strncmp(opt.data(), opt_name, len) == 0)
+ {
+ opt_name += len;
+ if (!opt_name[0])
+ {
+ if (inverse)
+ return result+2;
+
+ if (!options->description)
+ {
+ options++;
+ if (!options->name)
+ return result+0;
+ QCString nextOption = options->name;
+# if QT_VERSION<0x040000
+ int p = nextOption.find(' ');
+#else
+ int p = QString(nextOption).indexOf(' ');
+#endif
+ if (p > 0)
+ nextOption = nextOption.left(p);
+ if (strncmp(nextOption.data(), "no", 2) == 0)
+ {
+ nextOption = nextOption.mid(2);
+ enabled = !enabled;
+ }
+ result = findOption(options, nextOption, opt_name, def, enabled);
+ assert(result);
+ opt = nextOption;
+ return result;
+ }
+
+ return 1;
+ }
+ if (opt_name[0] == ' ')
+ {
+ opt_name++;
+ def = options->def;
+ return result+3;
+ }
+ }
+
+ options++;
+ }
+ return 0;
+}
+
+
+void
+KCmdLineArgs::findOption(const char *_opt, QCString opt, int &i, bool _enabled, bool &moreOptions)
+{
+ KCmdLineArgs *args = argsList->first();
+ const char *opt_name;
+ const char *def;
+ QCString argument;
+# if QT_VERSION<0x040000
+ int j = opt.find('=');
+#else
+ int j = QString(opt).indexOf('=');
+#endif
+ if (j != -1)
+ {
+ argument = opt.mid(j+1);
+ opt = opt.left(j);
+ }
+
+ bool enabled = true;
+ int result = 0;
+ while (args)
+ {
+ enabled = _enabled;
+ result = ::findOption(args->options, opt, opt_name, def, enabled);
+ if (result) break;
+ args = argsList->next();
+ }
+ if (!args && (_opt[0] == '-') && _opt[1] && (_opt[1] != '-'))
+ {
+ // Option not found check if it is a valid option
+ // in the style of -Pprinter1 or ps -aux
+ int p = 1;
+ while (true)
+ {
+ QCString singleCharOption = " ";
+ singleCharOption[0] = _opt[p];
+ args = argsList->first();
+ while (args)
+ {
+ enabled = _enabled;
+ result = ::findOption(args->options, singleCharOption, opt_name, def, enabled);
+ if (result) break;
+ args = argsList->next();
+ }
+ if (!args)
+ break; // Unknown argument
+
+ p++;
+ if (result == 1) // Single option
+ {
+ args->setOption(singleCharOption, enabled);
+ if (_opt[p])
+ continue; // Next option
+ else
+ return; // Finished
+ }
+ else if (result == 3) // This option takes an argument
+ {
+ if (argument.isEmpty())
+ {
+ argument = _opt+p;
+ }
+ args->setOption(singleCharOption, argument.data());
+ return;
+ }
+ break; // Unknown argument
+ }
+ args = 0;
+ result = 0;
+ }
+
+ if (!args || !result)
+ {
+ if (ignoreUnknown)
+ return;
+ enable_i18n();
+ usage( i18n("Unknown option '%1'.").arg(QString::fromLocal8Bit(_opt)));
+ }
+
+ if ((result & 4) != 0)
+ {
+ result &= ~4;
+ moreOptions = false;
+ }
+
+ if (result == 3) // This option takes an argument
+ {
+ if (!enabled)
+ {
+ if (ignoreUnknown)
+ return;
+ enable_i18n();
+ usage( i18n("Unknown option '%1'.").arg(QString::fromLocal8Bit(_opt)));
+ }
+ if (argument.isEmpty())
+ {
+ i++;
+ if (i >= argc)
+ {
+ enable_i18n();
+ usage( i18n("'%1' missing.").arg( opt_name));
+ }
+ argument = argv[i];
+ }
+ args->setOption(opt, argument.data());
+ }
+ else
+ {
+ args->setOption(opt, enabled);
+ }
+}
+
+void
+KCmdLineArgs::printQ(const QString &msg)
+{
+# if QT_VERSION<0x040000
+ QCString localMsg = msg.local8Bit();
+#else
+ QCString localMsg = msg.toLocal8Bit();
+#endif
+ fprintf(stdout, "%s", localMsg.data());
+}
+
+void
+KCmdLineArgs::parseAllArgs()
+{
+ bool allowArgs = false;
+ bool inOptions = true;
+ bool everythingAfterArgIsArgs = false;
+ KCmdLineArgs *appOptions = argsList->last();
+ if (!appOptions->id)
+ {
+ const KCmdLineOptions *option = appOptions->options;
+ while(option && option->name)
+ {
+ if (option->name[0] == '+')
+ allowArgs = true;
+ if ( option->name[0] == '!' && option->name[1] == '+' )
+ {
+ allowArgs = true;
+ everythingAfterArgIsArgs = true;
+ }
+ option++;
+ }
+ }
+ for(int i = 1; i < argc; i++)
+ {
+ if (!argv[i])
+ continue;
+
+ if ((argv[i][0] == '-') && argv[i][1] && inOptions)
+ {
+ bool enabled = true;
+ const char *option = &argv[i][1];
+ const char *orig = argv[i];
+ if (option[0] == '-')
+ {
+ option++;
+ argv[i]++;
+ if (!option[0])
+ {
+ inOptions = false;
+ continue;
+ }
+ }
+ if (::qstrcmp(option, "help") == 0)
+ {
+ usage(0);
+ }
+ else if (strncmp(option, "help-",5) == 0)
+ {
+ usage(option+5);
+ }
+ else if ( (::qstrcmp(option, "version") == 0) ||
+ (::qstrcmp(option, "v") == 0))
+ {
+ printQ( QString("Qt: %1\n").arg(qVersion()));
+// printQ( QString("KDE: %1\n").arg(KDE_VERSION_STRING));
+ printQ( QString("%1: %2\n").
+ arg(about->programName()).arg(about->version()));
+ exit(0);
+ } else if ( (::qstrcmp(option, "license") == 0) )
+ {
+ enable_i18n();
+ printQ( about->license() );
+ printQ( "\n" );
+ exit(0);
+ } else if ( ::qstrcmp( option, "author") == 0 ) {
+ enable_i18n();
+ if ( about ) {
+ const QValueList<KAboutPerson> authors = about->authors();
+ if ( !authors.isEmpty() ) {
+ QString authorlist;
+ for (QValueList<KAboutPerson>::ConstIterator it = authors.begin(); it != authors.end(); ++it ) {
+ QString email;
+ if ( !(*it).emailAddress().isEmpty() )
+ email = " <" + (*it).emailAddress() + ">";
+ authorlist += QString(" ") + (*it).name() + email + "\n";
+ }
+ printQ( i18n("the 2nd argument is a list of name+address, one on each line","%1 was written by\n%2").arg ( QString(about->programName()) ).arg( authorlist ) );
+ }
+ } else {
+ printQ( i18n("%1 was written by somebody who wants to remain anonymous.").arg(about->programName()) );
+ }
+ if (!about->bugAddress().isEmpty())
+ {
+ if (about->bugAddress() == "submit@bugs.kde.org")
+ printQ( i18n( "Please use http://bugs.kde.org to report bugs, do not mail the authors directly.\n" ) );
+ else
+ printQ( i18n( "Please use %1 to report bugs, do not mail the authors directly.\n" ).arg(about->bugAddress()) );
+ }
+ exit(0);
+ } else {
+ if ((option[0] == 'n') && (option[1] == 'o'))
+ {
+ option += 2;
+ enabled = false;
+ }
+ findOption(orig, option, i, enabled, inOptions);
+ }
+ }
+ else
+ {
+ // Check whether appOptions allows these arguments
+ if (!allowArgs)
+ {
+ if (ignoreUnknown)
+ continue;
+ enable_i18n();
+ usage( i18n("Unexpected argument '%1'.").arg(QString::fromLocal8Bit(argv[i])));
+ }
+ else
+ {
+ appOptions->addArgument(argv[i]);
+ if (everythingAfterArgIsArgs)
+ inOptions = false;
+ }
+ }
+ }
+ parsed = true;
+}
+
+/**
+ * For KApplication only:
+ *
+ * Return argc
+ */
+int *
+KCmdLineArgs::qt_argc()
+{
+// if (!argsList)
+// KApplication::addCmdLineOptions(); // Lazy bastards!
+
+ static int qt_argc = -1;
+ if( qt_argc != -1 )
+ return &qt_argc;
+
+ KCmdLineArgs *args = parsedArgs("qt");
+ assert(args); // No qt options have been added!
+ if (!argv)
+ {
+ fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
+ fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
+
+ assert( 0 );
+ exit(255);
+ }
+
+ assert(argc >= (args->count()+1));
+ qt_argc = args->count() +1;
+ return &qt_argc;
+}
+
+/**
+ * For KApplication only:
+ *
+ * Return argv
+ */
+char ***
+KCmdLineArgs::qt_argv()
+{
+// if (!argsList)
+// KApplication::addCmdLineOptions(); // Lazy bastards!
+
+ static char** qt_argv;
+ if( qt_argv != NULL )
+ return &qt_argv;
+
+ KCmdLineArgs *args = parsedArgs("qt");
+ assert(args); // No qt options have been added!
+ if (!argv)
+ {
+ fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
+ fprintf(stderr, "Application has not called KCmdLineArgs::init(...).\n\n");
+
+ assert( 0 );
+ exit(255);
+ }
+
+ qt_argv = new char*[ args->count() + 2 ];
+ qt_argv[ 0 ] = qstrdup( appName());
+ int i = 0;
+ for(; i < args->count(); i++)
+ {
+ qt_argv[i+1] = qstrdup((char *) args->arg(i));
+ }
+ qt_argv[i+1] = 0;
+
+ return &qt_argv;
+}
+
+void
+KCmdLineArgs::enable_i18n()
+{
+ // called twice or too late
+/* if (KGlobal::_locale)
+ return;
+
+ if (!KGlobal::_instance) {
+ KInstance *instance = new KInstance(about);
+ (void) instance->config();
+ // Don't delete instance!
+ }*/
+}
+
+void
+KCmdLineArgs::usage(const QString &error)
+{
+// assert(KGlobal::_locale);
+# if QT_VERSION<0x040000
+ QCString localError = error.local8Bit();
+#else
+ QCString localError = error.toLocal8Bit();
+#endif
+ if (localError[error.length()-1] == '\n')
+ localError = localError.left(error.length()-1);
+ fprintf(stderr, "%s: %s\n", argv[0], localError.data());
+
+ QString tmp = i18n("Use --help to get a list of available command line options.");
+# if QT_VERSION<0x040000
+ localError = tmp.local8Bit();
+#else
+ localError = tmp.toLocal8Bit();
+#endif
+ fprintf(stderr, "%s: %s\n", argv[0], localError.data());
+ exit(254);
+}
+
+void
+KCmdLineArgs::usage(const char *id)
+{
+ enable_i18n();
+ assert(argsList != 0); // It's an error to call usage(...) without
+ // having done addCmdLineOptions first!
+
+ QString optionFormatString = " %1 %2\n";
+ QString optionFormatStringDef = " %1 %2 [%3]\n";
+ QString optionHeaderString = i18n("\n%1:\n");
+ QString tmp;
+ QString usage;
+
+ KCmdLineArgs *args = argsList->last();
+
+ if (!(args->id) && (args->options) &&
+ (args->options->name) && (args->options->name[0] != '+'))
+ {
+ usage = i18n("[options] ")+usage;
+ }
+
+ while(args)
+ {
+ if (args->name)
+ {
+ usage = i18n("[%1-options]").arg(args->name)+" "+usage;
+ }
+ args = argsList->prev();
+ }
+
+ KCmdLineArgs *appOptions = argsList->last();
+ if (!appOptions->id)
+ {
+ const KCmdLineOptions *option = appOptions->options;
+ while(option && option->name)
+ {
+ if (option->name[0] == '+')
+ usage = usage + (option->name+1) + " ";
+ else if ( option->name[0] == '!' && option->name[1] == '+' )
+ usage = usage + (option->name+2) + " ";
+
+ option++;
+ }
+ }
+
+ printQ(i18n("Usage: %1 %2\n").arg(argv[0]).arg(usage));
+ printQ("\n"+about->shortDescription()+"\n");
+
+ printQ(optionHeaderString.arg(i18n("Generic options")));
+ printQ(optionFormatString.arg("--help", -25).arg(i18n("Show help about options")));
+
+ args = argsList->first();
+ while(args)
+ {
+ if (args->name && args->id)
+ {
+ QString option = QString("--help-%1").arg(args->id);
+ QString desc = i18n("Show %1 specific options").arg(args->name);
+
+ printQ(optionFormatString.arg(option, -25).arg(desc));
+ }
+ args = argsList->next();
+ }
+
+ printQ(optionFormatString.arg("--help-all",-25).arg(i18n("Show all options")));
+ printQ(optionFormatString.arg("--author",-25).arg(i18n("Show author information")));
+ printQ(optionFormatString.arg("-v, --version",-25).arg(i18n("Show version information")));
+ printQ(optionFormatString.arg("--license",-25).arg(i18n("Show license information")));
+ printQ(optionFormatString.arg("--", -25).arg(i18n("End of options")));
+
+ args = argsList->first(); // Sets current to 1st.
+
+ bool showAll = id && (::qstrcmp(id, "all") == 0);
+
+ if (!showAll)
+ {
+ while(args)
+ {
+ if (!id && !args->id) break;
+ if (id && (::qstrcmp(args->id, id) == 0)) break;
+ args = argsList->next();
+ }
+ }
+
+ while(args)
+ {
+ bool hasArgs = false;
+ bool hasOptions = false;
+ QString optionsHeader;
+ if (args->name)
+ optionsHeader = optionHeaderString.arg(i18n("%1 options").arg(QString::fromLatin1(args->name)));
+ else
+ optionsHeader = i18n("\nOptions:\n");
+
+ while (args)
+ {
+ const KCmdLineOptions *option = args->options;
+ QCString opt = "";
+//
+ while(option && option->name)
+ {
+ QString description;
+ QString descriptionRest;
+ QStringList dl;
+
+ // Option header
+ if (option->name[0] == ':')
+ {
+ if (option->description)
+ {
+ optionsHeader = "\n"+i18n(option->description);
+ if (!optionsHeader.endsWith("\n"))
+ optionsHeader.append("\n");
+ hasOptions = false;
+ }
+ option++;
+ continue;
+ }
+
+ // Free-form comment
+ if (option->name[0] == 0)
+ {
+ if (option->description)
+ {
+ QString tmp = "\n"+i18n(option->description);
+ if (!tmp.endsWith("\n"))
+ tmp.append("\n");
+ printQ(tmp);
+ }
+ option++;
+ continue;
+ }
+
+ // Options
+ if (option->description)
+ {
+ description = i18n(option->description);
+# if QT_VERSION<0x040000
+ dl = QStringList::split("\n", description, true);
+#else
+ dl = description.split("\n");
+#endif
+ description = dl.first();
+ dl.erase( dl.begin() );
+ }
+ QCString name = option->name;
+ if (name[0] == '!')
+ name = name.mid(1);
+
+ if (name[0] == '+')
+ {
+ if (!hasArgs)
+ {
+ printQ(i18n("\nArguments:\n"));
+ hasArgs = true;
+ }
+
+ name = name.mid(1);
+ if ((name[0] == '[') && (name[name.length()-1] == ']'))
+ name = name.mid(1, name.length()-2);
+ printQ(optionFormatString.arg(QString(name), -25)
+ .arg(description));
+ }
+ else
+ {
+ if (!hasOptions)
+ {
+ printQ(optionsHeader);
+ hasOptions = true;
+ }
+
+ if ((name.length() == 1) || (name[1] == ' '))
+ name = "-"+name;
+ else
+ name = "--"+name;
+ if (!option->description)
+ {
+ opt = name + ", ";
+ }
+ else
+ {
+ opt = opt + name;
+ if (!option->def)
+ {
+ printQ(optionFormatString.arg(QString(opt), -25)
+ .arg(description));
+ }
+ else
+ {
+ printQ(optionFormatStringDef.arg(QString(opt), -25)
+ .arg(description).arg(option->def));
+ }
+ opt = "";
+ }
+ }
+ for(QStringList::Iterator it = dl.begin();
+ it != dl.end();
+ ++it)
+ {
+ printQ(optionFormatString.arg("", -25).arg(*it));
+ }
+
+ option++;
+ }
+ args = argsList->next();
+ if (!args || args->name || !args->id) break;
+ }
+ if (!showAll) break;
+ }
+
+ exit(254);
+}
+
+//
+// Member functions
+//
+
+/**
+ * Constructor.
+ *
+ * The given arguments are assumed to be constants.
+ */
+KCmdLineArgs::KCmdLineArgs( const KCmdLineOptions *_options,
+ const char *_name, const char *_id)
+ : options(_options), name(_name), id(_id)
+{
+ parsedOptionList = 0;
+ parsedArgList = 0;
+ isQt = (::qstrcmp(id, "qt") == 0);
+}
+
+/**
+ * Destructor.
+ */
+KCmdLineArgs::~KCmdLineArgs()
+{
+ delete parsedOptionList;
+ delete parsedArgList;
+ if (argsList)
+ argsList->removeRef(this);
+}
+
+void
+KCmdLineArgs::clear()
+{
+ delete parsedArgList;
+ parsedArgList = 0;
+ delete parsedOptionList;
+ parsedOptionList = 0;
+}
+
+void
+KCmdLineArgs::reset()
+{
+ if ( argsList ) {
+ argsList->setAutoDelete( true );
+ argsList->clear();
+ delete argsList;
+ argsList = 0;
+ }
+ parsed = false;
+}
+
+void
+KCmdLineArgs::save( QDataStream &ds) const
+{
+ uint count = 0;
+ if (parsedOptionList)
+ parsedOptionList->save( ds );
+ else
+ ds << count;
+
+ if (parsedArgList)
+ parsedArgList->save( ds );
+ else
+ ds << count;
+}
+
+void
+KCmdLineArgs::load( QDataStream &ds)
+{
+ if (!parsedOptionList) parsedOptionList = new KCmdLineParsedOptions;
+ if (!parsedArgList) parsedArgList = new KCmdLineParsedArgs;
+
+ parsedOptionList->load( ds );
+ parsedArgList->load( ds );
+
+ if (parsedOptionList->count() == 0)
+ {
+ delete parsedOptionList;
+ parsedOptionList = 0;
+ }
+ if (parsedArgList->count() == 0)
+ {
+ delete parsedArgList;
+ parsedArgList = 0;
+ }
+}
+
+void
+KCmdLineArgs::setOption(const QCString &opt, bool enabled)
+{
+ if (isQt)
+ {
+ // Qt does it own parsing.
+ QCString arg = "-";
+ if( !enabled )
+ arg += "no";
+ arg += opt;
+ addArgument(arg);
+ }
+ if (!parsedOptionList) {
+ parsedOptionList = new KCmdLineParsedOptions;
+ parsedOptionList->setAutoDelete(true);
+ }
+
+ if (enabled)
+ parsedOptionList->replace( opt, new QCString("t") );
+ else
+ parsedOptionList->replace( opt, new QCString("f") );
+}
+
+void
+KCmdLineArgs::setOption(const QCString &opt, const char *value)
+{
+ if (isQt)
+ {
+ // Qt does it's own parsing.
+ QCString arg = "-";
+ arg += opt;
+ addArgument(arg);
+ addArgument(value);
+
+#ifdef Q_WS_X11
+ // Hack coming up!
+ if (arg == "-display")
+ {
+ setenv(DISPLAY, value, true);
+ }
+#endif
+ }
+ if (!parsedOptionList) {
+ parsedOptionList = new KCmdLineParsedOptions;
+ parsedOptionList->setAutoDelete(true);
+ }
+
+ parsedOptionList->insert( opt, new QCString(value) );
+}
+
+QCString
+KCmdLineArgs::getOption(const char *_opt) const
+{
+ QCString *value = 0;
+ if (parsedOptionList)
+ {
+ value = parsedOptionList->find(_opt);
+ }
+
+ if (value)
+ return (*value);
+
+ // Look up the default.
+ const char *opt_name;
+ const char *def;
+ bool dummy = true;
+ QCString opt = _opt;
+ int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
+
+ if (result != 3)
+ {
+ fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
+ fprintf(stderr, "Application requests for getOption(\"%s\") but the \"%s\" option\n",
+ _opt, _opt);
+ fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
+
+ assert( 0 );
+ exit(255);
+ }
+ return QCString(def);
+}
+
+QCStringList
+KCmdLineArgs::getOptionList(const char *_opt) const
+{
+ QCStringList result;
+ if (!parsedOptionList)
+ return result;
+
+ while(true)
+ {
+ QCString *value = parsedOptionList->take(_opt);
+ if (!value)
+ break;
+ result.prepend(*value);
+ delete value;
+ }
+
+ // Reinsert items in dictionary
+ // WABA: This is rather silly, but I don't want to add restrictions
+ // to the API like "you can only call this function once".
+ // I can't access all items without taking them out of the list.
+ // So taking them out and then putting them back is the only way.
+ for(QCStringList::ConstIterator it=result.begin();
+ it != result.end();
+ ++it)
+ {
+ parsedOptionList->insert(_opt, new QCString(*it));
+ }
+ return result;
+}
+
+bool
+KCmdLineArgs::isSet(const char *_opt) const
+{
+ // Look up the default.
+ const char *opt_name;
+ const char *def;
+ bool dummy = true;
+ QCString opt = _opt;
+ int result = ::findOption( options, opt, opt_name, def, dummy) & ~4;
+
+ if (result == 0)
+ {
+ fprintf(stderr, "\n\nFAILURE (KCmdLineArgs):\n");
+ fprintf(stderr, "Application requests for isSet(\"%s\") but the \"%s\" option\n",
+ _opt, _opt);
+ fprintf(stderr, "has never been specified via addCmdLineOptions( ... )\n\n");
+
+ assert( 0 );
+ exit(255);
+ }
+
+ QCString *value = 0;
+ if (parsedOptionList)
+ {
+ value = parsedOptionList->find(opt);
+ }
+
+ if (value)
+ {
+ if (result == 3)
+ return true;
+ else
+ return ((*value)[0] == 't');
+ }
+
+ if (result == 3)
+ return false; // String option has 'false' as default.
+
+ // We return 'true' as default if the option was listed as '-nofork'
+ // We return 'false' as default if the option was listed as '-fork'
+ return (result == 2);
+}
+
+int
+KCmdLineArgs::count() const
+{
+ if (!parsedArgList)
+ return 0;
+ return parsedArgList->count();
+}
+
+const char *
+KCmdLineArgs::arg(int n) const
+{
+ if (!parsedArgList || (n >= (int) parsedArgList->count()))
+ {
+ fprintf(stderr, "\n\nFAILURE (KCmdLineArgs): Argument out of bounds\n");
+ fprintf(stderr, "Application requests for arg(%d) without checking count() first.\n",
+ n);
+
+ assert( 0 );
+ exit(255);
+ }
+
+ return parsedArgList->at(n);
+}
+
+KURL
+KCmdLineArgs::url(int n) const
+{
+ return makeURL( arg(n) );
+}
+
+KURL KCmdLineArgs::makeURL(const char *_urlArg)
+{
+ QString urlArg = QFile::decodeName(_urlArg);
+ if (!QDir::isRelativePath(urlArg))
+ {
+ //KURL result;
+ //result.setPath(urlArg);
+ //return result; // Absolute path.
+ return urlArg;
+ }
+# if QT_VERSION<0x040000
+ if ( !QUrl::isRelativeUrl(urlArg) )
+#else
+ if ( !QUrl(urlArg).isRelative() )
+#endif
+ //return KURL(urlArg); // Argument is a URL
+ return urlArg;
+
+// KURL result;
+// result.setPath( cwd()+"/"+urlArg );
+// result.cleanPath();
+// return result; // Relative path
+ return cwd() + "/" + urlArg;
+}
+
+void
+KCmdLineArgs::addArgument(const char *argument)
+{
+ if (!parsedArgList)
+ parsedArgList = new KCmdLineParsedArgs;
+
+ parsedArgList->append(argument);
+}
+
+static const KCmdLineOptions kde_tempfile_option[] =
+{
+ { "tempfile", I18N_NOOP("The files/URLs opened by the application will be deleted after use"), 0},
+ KCmdLineLastOption
+};
+
+void
+KCmdLineArgs::addTempFileOption()
+{
+ KCmdLineArgs::addCmdLineOptions( kde_tempfile_option, "KDE-tempfile", "kde-tempfile" );
+}
+
+bool KCmdLineArgs::isTempFileSet()
+{
+ KCmdLineArgs* args = KCmdLineArgs::parsedArgs( "kde-tempfile" );
+ if ( args )
+ return args->isSet( "tempfile" );
+ return false;
+}
diff --git a/src/common/nokde/nokde_kcmdlineargs.h b/src/common/nokde/nokde_kcmdlineargs.h
new file mode 100644
index 0000000..8b79b62
--- /dev/null
+++ b/src/common/nokde/nokde_kcmdlineargs.h
@@ -0,0 +1,701 @@
+// modified from KDE 3.4 for Windows port (Nicolas Hadacek)
+
+/* This file is part of the KDE project
+ Copyright (C) 1999 Waldo Bastian <bastian@kde.org>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef _KCMDLINEARGS_H_
+#define _KCMDLINEARGS_H_
+
+#include "nokde_klocale.h"
+#include "nokde_kurl.h"
+
+# if QT_VERSION<0x040000
+# include <qptrlist.h>
+# include <qvaluelist.h>
+#else
+# include <Qt3Support/Q3CString>
+# define QCString Q3CString
+# include <Qt3Support/Q3PtrList>
+# define QPtrList Q3PtrList
+# include <Qt3Support/Q3ValueList>
+# define QValueList Q3ValueList
+#endif
+# include <qstring.h>
+
+typedef QValueList<QCString> QCStringList;
+
+/**
+ * @short Structure that holds command line options.
+ *
+ * This class is intended to be used with the KCmdLineArgs class, which
+ * provides convenient and powerful command line argument parsing and
+ * handling functionality.
+ *
+ * @see KCmdLineArgs for additional usage information
+ */
+struct KDECORE_EXPORT KCmdLineOptions
+{
+ /**
+ * The name of the argument as it should be called on the command line and
+ * appear in <i>myapp --help</i>.
+ *
+ * Note that if this option starts with "no" that you will need to test for
+ * the name without the "no" and the result will be the inverse of what is
+ * specified. i.e. if "nofoo" is the name of the option and
+ * <i>myapp --nofoo</i> is called:
+ *
+ * \code
+ * KCmdLineArgs::parsedArgs()->isSet("foo"); // false
+ * \endcode
+ */
+ const char *name;
+ /**
+ * The text description of the option as should appear in
+ * <i>myapp --help</i>. This value should be wrapped with I18N_NOOP().
+ */
+ const char *description;
+ /**
+ * The default value for the option, if it is not specified on the
+ * command line.
+ */
+ const char *def; // Default
+};
+
+#define KCmdLineLastOption { 0, 0, 0 }
+
+class KCmdLineArgsList;
+class KApplication;
+class KUniqueApplication;
+class KCmdLineParsedOptions;
+class KCmdLineParsedArgs;
+class KAboutData;
+class KCmdLineArgsPrivate;
+
+/**
+ * @short A class for command-line argument handling.
+ *
+ * KCmdLineArgs provides simple access to the command-line arguments
+ * for an application. It takes into account Qt-specific options,
+ * KDE-specific options and application specific options.
+ *
+ * This class is used in %main() via the static method
+ * init().
+ *
+ * A typical %KDE application using %KCmdLineArgs should look like this:
+ *
+ * \code
+ * int main(int argc, char *argv[])
+ * {
+ * // Initialize command line args
+ * KCmdLineArgs::init(argc, argv, appName, programName, description, version);
+ *
+ * // Tell which options are supported
+ * KCmdLineArgs::addCmdLineOptions( options );
+ *
+ * // Add options from other components
+ * KUniqueApplication::addCmdLineOptions();
+ *
+ * ....
+ *
+ * // Create application object without passing 'argc' and 'argv' again.
+ * KUniqueApplication app;
+ *
+ * ....
+ *
+ * // Handle our own options/arguments
+ * // A KApplication will usually do this in main but this is not
+ * // necessary.
+ * // A KUniqueApplication might want to handle it in newInstance().
+ *
+ * KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ *
+ * // A binary option (on / off)
+ * if (args->isSet("some-option"))
+ * ....
+ *
+ * // An option which takes an additional argument
+ * QCString anotherOptionArg = args->getOption("another-option");
+ *
+ * // Arguments (e.g. files to open)
+ * for(int i = 0; i < args->count(); i++) // Counting start at 0!
+ * {
+ * // don't forget to convert to Unicode!
+ * openFile( QFile::decodeName( args->arg(i)));
+ * // Or more convenient:
+ * // openURL( args->url(i));
+ *
+ * }
+ *
+ * args->clear(); // Free up some memory.
+ * ....
+ * }
+ * \endcode
+ *
+ * The options that an application supports are configured using the
+ * KCmdLineOptions class. An example is shown below:
+ *
+ * \code
+ * static const KCmdLineOptions options[] =
+ * {
+ * { "a", I18N_NOOP("A short binary option"), 0 },
+ * { "b \<file>", I18N_NOOP("A short option which takes an argument"), 0 },
+ * { "c \<speed>", I18N_NOOP("As above but with a default value"), "9600" },
+ * { "option1", I18N_NOOP("A long binary option, off by default"), 0 },
+ * { "nooption2", I18N_NOOP("A long binary option, on by default"), 0 },
+ * { ":", I18N_NOOP("Extra options:"), 0 },
+ * { "option3 \<file>", I18N_NOOP("A long option which takes an argument"), 0 },
+ * { "option4 \<speed>", I18N_NOOP("A long option which takes an argument, defaulting to 9600"), "9600" },
+ * { "d", 0, 0 },
+ * { "option5", I18N_NOOP("A long option which has a short option as alias"), 0 },
+ * { "e", 0, 0 },
+ * { "nooption6", I18N_NOOP("Another long option with an alias"), 0 },
+ * { "f", 0, 0 },
+ * { "option7 \<speed>", I18N_NOOP("'--option7 speed' is the same as '-f speed'"), 0 },
+ * { "!option8 \<cmd>", I18N_NOOP("All options following this one will be treated as arguments"), 0 },
+ * { "+file", I18N_NOOP("A required argument 'file'"), 0 },
+ * { "+[arg1]", I18N_NOOP("An optional argument 'arg1'"), 0 },
+ * { "!+command", I18N_NOOP("A required argument 'command', that can contain multiple words, even starting with '-'"), 0 },
+ * { "", I18N_NOOP("Additional help text not associated with any particular option") 0 },
+ * KCmdLineLastOption // End of options.
+ * };
+ * \endcode
+ *
+ * The I18N_NOOP macro is used to indicate that these strings should be
+ * marked for translation. The actual translation is done by KCmdLineArgs.
+ * You can't use i18n() here because we are setting up a static data
+ * structure and can't do translations at compile time.
+ *
+ * Note that a program should define the options before any arguments.
+ *
+ * When a long option has a short option as an alias, a program should
+ * only test for the long option.
+ *
+ * With the above options a command line could look like:
+ * \code
+ * myapp -a -c 4800 --display localhost:0.0 --nooption5 -d /tmp/file
+ * \endcode
+ *
+ * Long binary options can be in the form 'option' and 'nooption'.
+ * A command line may contain the same binary option multiple times,
+ * the last option determines the outcome:
+ * \code
+ * myapp --nooption4 --option4 --nooption4
+ * \endcode
+ * is the same as:
+ * \code
+ * myapp --nooption4
+ * \endcode
+ *
+ * If an option value is provided multiple times, normally only the last
+ * value is used:
+ * \code
+ * myapp -c 1200 -c 2400 -c 4800
+ * \endcode
+ * is usually the same as:
+ * \code
+ * myapp -c 4800
+ * \endcode
+ *
+ * However, an application can choose to use all values specified as well.
+ * As an example of this, consider that you may wish to specify a
+ * number of directories to use:
+ * \code
+ * myapp -I /usr/include -I /opt/kde/include -I /usr/X11/include
+ * \endcode
+ * When an application does this it should mention this in the description
+ * of the option. To access these options, use getOptionList()
+ *
+ * Tips for end-users:
+ *
+ * @li Single char options like "-a -b -c" may be combined into "-abc"
+ * @li The option "--foo bar" may also be written "--foo=bar"
+ * @li The option "-P lp1" may also be written "-P=lp1" or "-Plp1"
+ * @li The option "--foo bar" may also be written "-foo bar"
+ *
+ * @author Waldo Bastian
+ * @version 0.0.4
+ */
+class KDECORE_EXPORT KCmdLineArgs
+{
+ friend class KApplication;
+ friend class KUniqueApplication;
+ friend class QPtrList<KCmdLineArgs>;
+public:
+ // Static functions:
+
+ /**
+ * Initialize class.
+ *
+ * This function should be called as the very first thing in
+ * your application.
+ * @param _argc As passed to @p main(...).
+ * @param _argv As passed to @p main(...).
+ * @param _appname The untranslated name of your application. This should
+ * match with @p argv[0].
+ * @param programName A program name string to be used for display
+ * purposes. This string should be marked for
+ * translation. Example: I18N_NOOP("KEdit")
+ * @param _description A short description of what your application is about.
+ * @param _version A version.
+ * @param noKApp Set this true to not add commandline options for
+ * QApplication / KApplication
+ *
+ * @since 3.2
+ */
+ static void init(int _argc, char **_argv, const char *_appname,
+ const char* programName, const char *_description,
+ const char *_version, bool noKApp = false);
+ /**
+ * @deprecated
+ * You should convert any calls to this method to use the one
+ * above, by adding in the program name to be used for display
+ * purposes. Do not forget to mark it for translation using I18N_NOOP.
+ */
+ static void init(int _argc, char **_argv,
+ const char *_appname, const char *_description,
+ const char *_version, bool noKApp = false) KDE_DEPRECATED;
+
+ /**
+ * Initialize class.
+ *
+ * This function should be called as the very first thing in
+ * your application. It uses KAboutData to replace some of the
+ * arguments that would otherwise be required.
+ *
+ * @param _argc As passed to @p main(...).
+ * @param _argv As passed to @p main(...).
+ * @param about A KAboutData object describing your program.
+ * @param noKApp Set this true to not add commandline options for
+ * QApplication / KApplication
+ */
+ static void init(int _argc, char **_argv,
+ const KAboutData *about, bool noKApp = false);
+
+ /**
+ * Initialize Class
+ *
+ * This function should be called as the very first thing in your
+ * application. This method will rarely be used, since it doesn't
+ * provide any argument parsing. It does provide access to the
+ * KAboutData information.
+ * This method is exactly the same as calling
+ * init(0,0, const KAboutData *about, true).
+ *
+ * @param about the about data.
+ * \see KAboutData
+ */
+ static void init(const KAboutData *about);
+
+ /**
+ * Add options to your application.
+ *
+ * You must make sure that all possible options have been added before
+ * any class uses the command line arguments.
+ *
+ * The list of options should look like this:
+ *
+ * \code
+ * static KCmdLineOptions options[] =
+ * {
+ * { "option1 \<argument>", I18N_NOOP("Description 1"), "my_extra_arg" },
+ * { "o", 0, 0 },
+ * { "option2", I18N_NOOP("Description 2"), 0 },
+ * { "nooption3", I18N_NOOP("Description 3"), 0 },
+ * KCmdLineLastOption
+ * }
+ * \endcode
+ *
+ * @li "option1" is an option that requires an additional argument,
+ * but if one is not provided, it uses "my_extra_arg".
+ * @li "option2" is an option that can be turned on. The default is off.
+ * @li "option3" is an option that can be turned off. The default is on.
+ * @li "o" does not have a description. It is an alias for the option
+ * that follows. In this case "option2".
+ * @li "+file" specifies an argument. The '+' is removed. If your program
+ * doesn't specify that it can use arguments your program will abort
+ * when an argument is passed to it. Note that the reverse is not
+ * true. If required, you must check yourself the number of arguments
+ * specified by the user:
+ * \code
+ * KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ * if (args->count() == 0) KCmdLineArgs::usage(i18n("No file specified!"));
+ * \endcode
+ *
+ * In BNF:
+ * \code
+ * cmd = myapp [options] file
+ * options = (option)*
+ * option = --option1 \<argument> |
+ * (-o | --option2 | --nooption2) |
+ * ( --option3 | --nooption3 )
+ * \endcode
+ *
+ * Instead of "--option3" one may also use "-option3"
+ *
+ * Usage examples:
+ *
+ * @li "myapp --option1 test"
+ * @li "myapp" (same as "myapp --option1 my_extra_arg")
+ * @li "myapp --option2"
+ * @li "myapp --nooption2" (same as "myapp", since it is off by default)
+ * @li "myapp -o" (same as "myapp --option2")
+ * @li "myapp --nooption3"
+ * @li "myapp --option3 (same as "myapp", since it is on by default)
+ * @li "myapp --option2 --nooption2" (same as "myapp", because it
+ * option2 is off by default, and the last usage applies)
+ * @li "myapp /tmp/file"
+ *
+ * @param options A list of options that your code supplies.
+ * @param name the name of the option, can be 0.
+ * @param id A name with which these options can be identified, can be 0.
+ * @param afterId The options are inserted after this set of options, can be 0.
+ */
+ static void addCmdLineOptions( const KCmdLineOptions *options,
+ const char *name=0, const char *id = 0,
+ const char *afterId=0);
+
+ /**
+ * Access parsed arguments.
+ *
+ * This function returns all command line arguments that your code
+ * handles. If unknown command-line arguments are encountered the program
+ * is aborted and usage information is shown.
+ *
+ * @param id The name of the options you are interested in, can be 0.
+ */
+ static KCmdLineArgs *parsedArgs(const char *id=0);
+
+ /**
+ * Get the CWD (Current Working Directory) associated with the
+ * current command line arguments.
+ *
+ * Typically this is needed in KUniqueApplication::newInstance()
+ * since the CWD of the process may be different from the CWD
+ * where the user started a second instance.
+ * @return the current working directory
+ **/
+ static QString cwd();
+
+ /**
+ * Get the appname according to argv[0].
+ * @return the name of the application
+ **/
+ static const char *appName();
+
+ /**
+ * Print the usage help to stdout and exit.
+ *
+ * @param id if 0, print all options. If id is set, only print the
+ * option specified by id. The id is the value set by
+ * #ref addCmdLineOptions().
+ **/
+ static void usage(const char *id = 0);
+
+ /**
+ * Print an error to stderr and the usage help to stdout and exit.
+ * @param error the error to print
+ **/
+ static void usage(const QString &error);
+
+ /**
+ * Enable i18n to be able to print a translated error message.
+ *
+ * N.B.: This function leaks memory, therefore you are expected to exit
+ * afterwards (e.g., by calling usage()).
+ **/
+ static void enable_i18n();
+
+ // Member functions:
+
+
+ /**
+ * Read out a string option.
+ *
+ * The option must have a corresponding KCmdLineOptions entry
+ * of the form:
+ * \code
+ * { "option \<argument>", I18N_NOOP("Description"), "default" }
+ * \endcode
+ * You cannot test for the presence of an alias - you must always
+ * test for the full option.
+ *
+ * @param option The name of the option without '-'.
+ *
+ * @return The value of the option. If the option was not
+ * present on the command line the default is returned.
+ * If the option was present more than the value of the
+ * last occurrence is used.
+ */
+ QCString getOption(const char *option) const;
+
+ /**
+ * Read out all occurrences of a string option.
+ *
+ * The option must have a corresponding KCmdLineOptions entry
+ * of the form:
+ * \code
+ * { "option \<argument>", I18N_NOOP("Description"), "default" }
+ * \endcode
+ * You cannot test for the presence of an alias - you must always
+ * test for the full option.
+ *
+ * @param option The name of the option, without '-' or '-no'.
+ *
+ * @return A list of all option values. If no option was present
+ * on the command line, an empty list is returned.
+ */
+ QCStringList getOptionList(const char *option) const;
+
+ /**
+ * Read out a boolean option or check for the presence of string option.
+ *
+ * @param option The name of the option without '-' or '-no'.
+ *
+ * @return The value of the option. It will be true if the option
+ * was specifically turned on in the command line, or if the option
+ * is turned on by default (in the KCmdLineOptions list) and was
+ * not specifically turned off in the command line. Equivalently,
+ * it will be false if the option was specifically turned off in
+ * the command line, or if the option is turned off by default (in
+ * the KCmdLineOptions list) and was not specifically turned on in
+ * the command line.
+ */
+ bool isSet(const char *option) const;
+
+ /**
+ * Read the number of arguments that aren't options (but,
+ * for example, filenames).
+ *
+ * @return The number of arguments that aren't options
+ */
+ int count() const;
+
+ /**
+ * Read out an argument.
+ *
+ * @param n The argument to read. 0 is the first argument.
+ * count()-1 is the last argument.
+ *
+ * @return A @p const @p char @p * pointer to the n'th argument.
+ */
+ const char *arg(int n) const;
+
+ /**
+ * Read out an argument representing a URL.
+ *
+ * The argument can be
+ * @li an absolute filename
+ * @li a relative filename
+ * @li a URL
+ *
+ * @param n The argument to read. 0 is the first argument.
+ * count()-1 is the last argument.
+ *
+ * @return a URL representing the n'th argument.
+ */
+ KURL url(int n) const;
+
+ /**
+ * Used by url().
+ * Made public for apps that don't use KCmdLineArgs
+ * @param urlArg the argument
+ * @return the url.
+ */
+ static KURL makeURL( const char * urlArg );
+
+ /**
+ * Made public for apps that don't use KCmdLineArgs
+ * To be done before makeURL, to set the current working
+ * directory in case makeURL needs it.
+ * @param cwd the new working directory
+ */
+ static void setCwd( char * cwd ) { mCwd = cwd; }
+
+ /**
+ * Clear all options and arguments.
+ */
+ void clear();
+
+ /**
+ * Reset all option definitions, i.e. cancel all addCmdLineOptions calls.
+ * Note that KApplication's options are removed too, you might want to
+ * call KApplication::addCmdLineOptions if you want them back.
+ *
+ * You usually don't want to call this method.
+ */
+ static void reset();
+
+ /**
+ * Load arguments from a stream.
+ */
+ static void loadAppArgs( QDataStream &);
+
+ /**
+ * Add standard option --tempfile
+ * @since 3.4
+ */
+ static void addTempFileOption();
+
+ // this avoids having to know the "id" used by addTempFileOption
+ // but this approach doesn't scale well, we can't have 50 standard options here...
+ /**
+ * @return true if --tempfile was set
+ * @since 3.4
+ */
+ static bool isTempFileSet();
+
+protected:
+ /**
+ * @internal
+ * Constructor.
+ */
+ KCmdLineArgs( const KCmdLineOptions *_options, const char *_name,
+ const char *_id);
+
+ /**
+ * @internal use only.
+ *
+ * Use clear() if you want to free up some memory.
+ *
+ * Destructor.
+ */
+ ~KCmdLineArgs();
+
+private:
+ /**
+ * @internal
+ *
+ * Checks what to do with a single option
+ */
+ static void findOption(const char *_opt, QCString opt, int &i, bool enabled, bool &moreOptions);
+
+ /**
+ * @internal
+ *
+ * Parse all arguments, verify correct syntax and put all arguments
+ * where they belong.
+ */
+ static void parseAllArgs();
+
+ /**
+ * @internal for KApplication only:
+ *
+ * Return argc
+ */
+ static int *qt_argc();
+
+ /**
+ * @internal for KApplication only:
+ *
+ * Return argv
+ */
+
+ static char ***qt_argv();
+
+ /**
+ * @internal
+ *
+ * Remove named options.
+ *
+ * @param id The name of the options to be removed.
+ */
+ static void removeArgs(const char *id);
+
+ /**
+ * @internal for KUniqueApplication only:
+ *
+ * Save all but the Qt and KDE arguments to a stream.
+ */
+ static void saveAppArgs( QDataStream &);
+
+ /**
+ * @internal
+ *
+ * Set a boolean option
+ */
+ void setOption(const QCString &option, bool enabled);
+
+ /**
+ * @internal
+ *
+ * Set a string option
+ */
+ void setOption(const QCString &option, const char *value);
+
+ /**
+ * @internal
+ *
+ * Add an argument
+ */
+ void addArgument(const char *argument);
+
+ /**
+ * @internal
+ *
+ * Save to a stream.
+ */
+ void save( QDataStream &) const;
+
+ /**
+ * @internal
+ *
+ * Restore from a stream.
+ */
+ void load( QDataStream &);
+
+ /**
+ * @internal for KApplication only
+ *
+ * Initialize class.
+ *
+ * This function should be called as the very first thing in
+ * your application.
+ * @param argc As passed to @p main(...).
+ * @param argv As passed to @p main(...).
+ * @param appname The untranslated name of your application. This should
+ * match with @p argv[0].
+ *
+ * This function makes KCmdLineArgs ignore all unknown options as well as
+ * all arguments.
+ */
+ static void initIgnore(int _argc, char **_argv, const char *_appname);
+
+ static void printQ(const QString &msg);
+
+ const KCmdLineOptions *options;
+ const char *name;
+ const char *id;
+ KCmdLineParsedOptions *parsedOptionList;
+ KCmdLineParsedArgs *parsedArgList;
+ bool isQt;
+
+ static KCmdLineArgsList *argsList; // All options.
+ static const KAboutData *about;
+
+ static int argc; // The original argc
+ static char **argv; // The original argv
+ static bool parsed; // Whether we have parsed the arguments since calling init
+ static bool ignoreUnknown; // Ignore unknown options and arguments
+ static char *mCwd; // Current working directory. Important for KUnqiueApp!
+ static bool parseArgs;
+
+ KCmdLineArgsPrivate *d;
+};
+
+#endif
+
diff --git a/src/common/nokde/nokde_klocale.cpp b/src/common/nokde/nokde_klocale.cpp
new file mode 100644
index 0000000..e30ba2f
--- /dev/null
+++ b/src/common/nokde/nokde_klocale.cpp
@@ -0,0 +1,4 @@
+#include "nokde_klocale.h"
+
+QString i18n(const QString &, const QString &text) { return text; }
+QString locate(const QString &, const QString &) { return QString::null; }
diff --git a/src/common/nokde/nokde_klocale.h b/src/common/nokde/nokde_klocale.h
new file mode 100644
index 0000000..a1cf720
--- /dev/null
+++ b/src/common/nokde/nokde_klocale.h
@@ -0,0 +1,17 @@
+#ifndef NOKDE_KLOCALE_H
+#define NOKDE_KLOCALE_H
+
+#undef KDECORE_EXPORT
+#define KDECORE_EXPORT
+
+#undef KDE_DEPRECATED
+#define KDE_DEPRECATED
+
+#undef I18N_NOOP
+#define I18N_NOOP(x) (x)
+#include <qstring.h>
+inline QString i18n(const QString &text) { return text; }
+extern QString i18n(const QString &index, const QString &text);
+extern QString locate(const QString &, const QString &);
+
+#endif
diff --git a/src/common/nokde/nokde_kprocess.cpp b/src/common/nokde/nokde_kprocess.cpp
new file mode 100644
index 0000000..92c8968
--- /dev/null
+++ b/src/common/nokde/nokde_kprocess.cpp
@@ -0,0 +1,100 @@
+#include "nokde_kprocess.h"
+
+#if QT_VERSION<0x040000
+# include <qprocess.h>
+# define Q3Process QProcess
+#else
+# include <Qt3Support/Q3Process>
+#endif
+
+#if defined(Q_OS_UNIX)
+# include <signal.h>
+#endif
+
+KProcess::KProcess(QObject *parent, const char *name)
+ : QObject(parent, name)
+{
+ _process = new Q3Process(this);
+ connect(_process, SIGNAL(processExited()), SLOT(processExitedSlot()));
+ connect(_process, SIGNAL(readyReadStdout()), SLOT(readyReadStdoutSlot()));
+ connect(_process, SIGNAL(readyReadStderr()), SLOT(readyReadStderrSlot()));
+}
+
+bool KProcess::start()
+{
+ _process->setArguments(_arguments);
+ QStringList env;
+ if ( !_environment.isEmpty() ) {
+ for (uint i=0; environ[i]; i++) env += environ[i];
+ env += _environment;
+ }
+ return _process->start(env.isEmpty() ? 0 : &env);
+}
+
+void KProcess::processExitedSlot()
+{
+ readyReadStdoutSlot();
+ readyReadStderrSlot();
+ emit processExited(this);
+}
+
+void KProcess::readyReadStdoutSlot()
+{
+ QByteArray a = _process->readStdout();
+ emit receivedStdout(this, a.data(), a.count());
+}
+
+void KProcess::readyReadStderrSlot()
+{
+ QByteArray a = _process->readStderr();
+ emit receivedStderr(this, a.data(), a.count());
+}
+
+bool KProcess::writeStdin(const char *buffer, int len)
+{
+#if QT_VERSION<0x040000
+ QByteArray a;
+ a.assign(buffer, len);
+#else
+ QByteArray a(buffer, len);
+#endif
+ _process->writeToStdin(a);
+ return true;
+}
+
+bool KProcess::kill()
+{
+ _process->kill();
+ return true;
+}
+
+bool KProcess::kill(int n)
+{
+#if defined(Q_OS_UNIX)
+ return ( ::kill(_process->processIdentifier(), n)!=-1 );
+#elif defined(Q_OS_WIN)
+ // #### impossible to do ??
+ return false;
+#endif
+}
+
+int KProcess::exitStatus() const
+{
+ return _process->exitStatus();
+}
+
+bool KProcess::isRunning() const
+{
+ return _process->isRunning();
+}
+
+void KProcess::setWorkingDirectory(const QDir &dir)
+{
+ return _process->setWorkingDirectory(dir);
+}
+
+void KProcess::setUseShell(bool useShell)
+{
+ // ### TODO: just issue "/bin/sh" "-c" "command"
+ Q_ASSERT(false);
+}
diff --git a/src/common/nokde/nokde_kprocess.h b/src/common/nokde/nokde_kprocess.h
new file mode 100644
index 0000000..59ff73c
--- /dev/null
+++ b/src/common/nokde/nokde_kprocess.h
@@ -0,0 +1,51 @@
+#ifndef _KPROCESS_H_
+#define _KPROCESS_H_
+
+#include <qdir.h>
+#include "common/global/global.h"
+#include "common/common/synchronous.h"
+#if QT_VERSION<0x040000
+class QProcess;
+#else
+class Q3Process;
+#endif
+
+class KProcess : public QObject
+{
+Q_OBJECT
+public:
+ KProcess(QObject *parent = 0, const char *name = 0);
+ void clearArguments() { _arguments.clear(); }
+ KProcess &operator<< (const QString &arg) { _arguments += arg; return *this; }
+ KProcess &operator<< (const QStringList &args) { _arguments += args; return *this; }
+ QStringList args() const { return _arguments; }
+ void setEnvironment(const QString &name, const QString &value) { _environment += name + "=" + value; }
+ bool start();
+ bool writeStdin(const char *buffer, int len);
+ bool kill();
+ bool kill(int n);
+ int exitStatus() const;
+ bool isRunning() const;
+ void setWorkingDirectory(const QDir &dir);
+ void setUseShell(bool useShell);
+
+signals:
+ void processExited(KProcess *process);
+ void receivedStdout(KProcess *process, char *buffer, int len);
+ void receivedStderr(KProcess *process, char *buffer, int len);
+
+private slots:
+ void processExitedSlot();
+ void readyReadStdoutSlot();
+ void readyReadStderrSlot();
+
+private:
+#if QT_VERSION<0x040000
+ QProcess *_process;
+#else
+ Q3Process *_process;
+#endif
+ QStringList _arguments,_environment;
+};
+
+#endif
diff --git a/src/common/nokde/nokde_kurl.h b/src/common/nokde/nokde_kurl.h
new file mode 100644
index 0000000..202c46d
--- /dev/null
+++ b/src/common/nokde/nokde_kurl.h
@@ -0,0 +1,32 @@
+#ifndef _KURL_H_
+#define _KURL_H_
+
+#include <qfile.h>
+
+#include "common/global/global.h"
+
+class KURL : public Q3Url
+{
+public:
+ KURL() {}
+ KURL(const QString &s) : Q3Url(s) {}
+ void cleanPath() {}
+ bool isEmpty() const { return toString(false, false).isEmpty(); }
+ QString fileName(bool b) const { Q_UNUSED(b); Q_ASSERT(!b); return Q3Url::fileName(); }
+ static KURL fromPathOrURL(const QString &s) { return KURL(s); }
+#if QT_VERSION>=0x040000
+ bool operator <(const KURL &url) const { return path()<url.path(); }
+ bool operator ==(const KURL &url) const { return path()==url.path(); }
+ bool operator !=(const KURL &url) const { return path()!=url.path(); }
+#endif
+};
+
+// ### DUMMY
+class KTempFile
+{
+public:
+ const QFile *file() const { return 0; }
+ QFile *file() { return 0; }
+};
+
+#endif
diff --git a/src/common/nokde/win32_utils.c b/src/common/nokde/win32_utils.c
new file mode 100644
index 0000000..975261e
--- /dev/null
+++ b/src/common/nokde/win32_utils.c
@@ -0,0 +1,81 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (C) 2004 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+// helper functions
+
+#include "win32_utils.h"
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <signal.h>
+
+//---------------------------------------------
+#define _fcopy_BUFLEN 1024*32
+int fcopy(const char *src, const char *dest)
+{
+ static char _fcopy_buf[_fcopy_BUFLEN]; //not reentrant!
+ FILE *in, *out;
+ int c_in=0, c_out=0;
+ int res=0;
+
+ in=fopen(src, "rb");
+ if (!in)
+ return fcopy_src_err;
+ out=fopen(dest, "wb");
+ if (!out)
+ return fcopy_dest_err;
+ while (!feof(in) && !ferror(in) && !ferror(out)) {
+ c_in=fread(_fcopy_buf, 1, _fcopy_BUFLEN, in);
+ if (ferror(in) || c_in==0) {
+ break;
+ }
+ c_out=fwrite(_fcopy_buf, 1, c_in, out);
+ if (ferror(out) || c_in!=c_out) {
+ break;
+ }
+ }
+
+ if (ferror(in)) {
+ res=fcopy_src_err;
+ }
+ else if (ferror(out)) {
+ res=fcopy_dest_err;
+ }
+ else if (c_in!=c_out) {
+ res=fcopy_dest_err;
+ }
+ fclose(in);
+ fclose(out);
+ return res;
+}
+
+KDEWIN32_EXPORT
+void win32_slashify(char *path, int maxlen)
+{
+ int len = 0;
+ if (!path)
+ return;
+ for (; *path && len < maxlen ; path++)
+ if ( *path == '\\' )
+ *path = '/';
+}
+
diff --git a/src/common/nokde/win32_utils.h b/src/common/nokde/win32_utils.h
new file mode 100644
index 0000000..cc5e110
--- /dev/null
+++ b/src/common/nokde/win32_utils.h
@@ -0,0 +1,97 @@
+/*
+ This file is part of the KDE libraries
+ Copyright (C) 2004-2005 Jaroslaw Staniek <js@iidea.pl>
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public
+ License version 2 as published by the Free Software Foundation.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public License
+ along with this library; see the file COPYING.LIB. If not, write to
+ the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA.
+*/
+
+#ifndef KDE_WIN32_UTILS_H
+#define KDE_WIN32_UTILS_H
+
+#include <windows.h>
+
+//#include <kdecore/kdelibs_export.h>
+#define KDEWIN32_EXPORT
+
+#ifdef __cplusplus
+#include <qstring.h>
+
+extern "C" {
+#endif
+
+#define fcopy_src_err -1
+#define fcopy_dest_err -2
+
+/**
+ Copies @p src file to @p dest file.
+ @return 0 on success, fcopy_src_err on source file error,
+ fcopy_dest_err on destination file error.
+*/
+KDEWIN32_EXPORT int fcopy(const char *src, const char *dest);
+
+/**
+ Converts all backslashes to slashes in @p path.
+ Converting is stopped on a null character or at @p maxlen character.
+*/
+KDEWIN32_EXPORT void win32_slashify(char *path, int maxlen);
+
+#ifdef __cplusplus
+}
+
+/**
+ \return a value from MS Windows native registry.
+ @param key is usually one of HKEY_CLASSES_ROOT, HKEY_CURRENT_USER, HKEY_LOCAL_MACHINE
+ constants defined in WinReg.h.
+ @param subKey is a registry subkey defined as a path to a registry folder, eg.
+ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders"
+ ('\' delimiter must be used)
+ @param item is an item inside subKey or "" if default folder's value should be returned
+ @param ok if not null, will be set to true on success and false on failure
+*/
+KDEWIN32_EXPORT QString getWin32RegistryValue(HKEY key, const QString& subKey,
+ const QString& item, bool *ok = 0);
+
+/**
+ \return a value from MS Windows native registry for shell folder \a folder.
+*/
+inline QString getWin32ShellFoldersPath(const QString& folder) {
+ return getWin32RegistryValue(HKEY_CURRENT_USER,
+ "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", folder);
+}
+
+/**
+ Shows native MS Windows file property dialog for a file \a fileName.
+ Return true on success. Only works for local absolute paths.
+ Used by KPropertiesDialog, if possible.
+*/
+KDEWIN32_EXPORT
+bool showWin32FilePropertyDialog(const QString& fileName);
+
+/**
+ \return two-letter locale name (like "en" or "pl") taken from MS Windows native registry.
+ Useful when we don't want to rely on KSyCoCa.
+ Used e.g. by kbuildsycoca application.
+*/
+KDEWIN32_EXPORT
+QCString getWin32LocaleName();
+
+/*! Temporary solutiuon
+ \return a KFileDialog-compatible filter string converted to QFileDialog compatible one.
+ This is temporary solution for kdelibs/win32... */
+KDEWIN32_EXPORT QString convertKFileDialogFilterToQFileDialogFilter(const QString& filter);
+
+#endif //__cplusplus
+
+#endif
diff --git a/src/common/port/Makefile.am b/src/common/port/Makefile.am
new file mode 100644
index 0000000..d1d2ce8
--- /dev/null
+++ b/src/common/port/Makefile.am
@@ -0,0 +1,7 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libport.la
+libport_la_SOURCES = parallel.cpp port.cpp serial.cpp usb_port.cpp \
+ port_base.cpp
+libport_la_LDFLAGS = $(all_libraries)
diff --git a/src/common/port/parallel.cpp b/src/common/port/parallel.cpp
new file mode 100644
index 0000000..22b6a4c
--- /dev/null
+++ b/src/common/port/parallel.cpp
@@ -0,0 +1,247 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * Copyright (C) 2002-2003 Stephen Landamore <stephen@landamore.com> *
+ * *
+ * 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 "parallel.h"
+
+#include "common/global/global.h"
+#if defined(HAVE_PPDEV)
+# include <linux/ppdev.h>
+# include <linux/parport.h>
+# include <fcntl.h>
+# include <sys/ioctl.h>
+# include <unistd.h> // needed on some system
+# include <errno.h>
+#elif defined(HAVE_PPBUS)
+# include <sys/param.h>
+# include <machine/cpufunc.h>
+# include <dev/ppbus/ppi.h>
+# include <dev/ppbus/ppbconf.h>
+# include <fcntl.h>
+# include <unistd.h>
+# include <errno.h>
+#endif
+#include "common/common/misc.h"
+
+//-----------------------------------------------------------------------------
+QStringList *Port::Parallel::_list = 0;
+
+Port::IODirs Port::Parallel::probe(const QString &device)
+{
+#if defined(HAVE_PPDEV)
+ int fd = ::open(device.latin1(), O_RDWR);
+ if ( fd<0) return NoIO;
+ if ( ioctl(fd, PPCLAIM)<0 ) {
+ ::close(fd) ;
+ return In;
+ }
+ ioctl(fd, PPRELEASE);
+ ::close(fd);
+ return (In | Out);
+#elif defined(HAVE_PPBUS)
+ int fd = ::open(device.latin1(), O_RDWR);
+ if ( fd<0 ) return NoIO;
+ ::close(fd);
+ return In | Out; // #### can we detect read-only ?
+#else
+ return NoIO;
+#endif
+}
+
+QStringList Port::Parallel::deviceList()
+{
+ QStringList list;
+#if defined(HAVE_PPDEV)
+ // standard parport in user space
+ for(int i = 0; i<8; ++i) list.append(QString("/dev/parport%1").arg(i));
+ // new devfs parport flavour
+ for(int i = 0; i<8; ++i) list.append(QString("/dev/parports/%1").arg(i));
+#elif defined(HAVE_PPBUS)
+ // FreeBSD
+ for(int i = 0; i<8; ++i) list.append(QString("/dev/ppi%1").arg(i));
+#endif
+ return list;
+}
+
+const QStringList &Port::Parallel::probedDeviceList()
+{
+ if ( _list==0 ) {
+ QStringList all = deviceList();
+ _list = new QStringList;
+ for (uint i=0; i<uint(all.count()); i++)
+ if( probe(all[i]) & (In | Out) ) _list->append(all[i]);
+ }
+ return *_list;
+}
+
+bool Port::Parallel::isAvailable()
+{
+#if defined(HAVE_PPDEV) || defined(HAVE_PPBUS)
+ return true;
+#else
+ return false;
+#endif
+}
+
+//-----------------------------------------------------------------------------
+const Port::Parallel::PPinData Port::Parallel::PIN_DATA[Nb_Pins] = {
+ { Control, 0x01, Out, "/DS" }, // !strobe
+ { Data, 0x01, Out, "D0" }, // data 0
+ { Data, 0x02, Out, "D1" }, // data 1
+ { Data, 0x04, Out, "D2" }, // data 2
+ { Data, 0x08, Out, "D3" }, // data 3
+ { Data, 0x10, Out, "D4" }, // data 4
+ { Data, 0x20, Out, "D5" }, // data 5
+ { Data, 0x40, Out, "D6" }, // data 6
+ { Data, 0x80, Out, "D7" }, // data 7
+ { Status, 0x40, In, "/ACK" }, // !ack
+ { Status, 0x80, In, "BUSY" }, // busy
+ { Status, 0x20, In, "PAPER" }, // pout
+ { Status, 0x10, In, "SELin" }, // select
+ { Control, 0x02, Out, "LF" }, // !feed
+ { Status, 0x08, In, "/ERROR" }, // !error
+ { Control, 0x04, Out, "PRIME" }, // !init
+ { Control, 0x08, Out, "SELout" }, // !si
+ { Nb_RequestTypes, 0x00, NoIO, "GND" }, // GND
+ { Nb_RequestTypes, 0x00, NoIO, "GND" }, // GND
+ { Nb_RequestTypes, 0x00, NoIO, "GND" }, // GND
+ { Nb_RequestTypes, 0x00, NoIO, "GND" }, // GND
+ { Nb_RequestTypes, 0x00, NoIO, "GND" }, // GND
+ { Nb_RequestTypes, 0x00, NoIO, "GND" }, // GND
+ { Nb_RequestTypes, 0x00, NoIO, "GND" }, // GND
+ { Nb_RequestTypes, 0x00, NoIO, "GND" } // GND
+};
+
+QValueVector<Port::PinData> Port::Parallel::pinData(IODir dir) const
+{
+ QValueVector<PinData> v;
+ for (uint i=0; i<Nb_Pins; i++) {
+ if ( PIN_DATA[i].dir!=dir ) continue;
+ PinData pd = { i, PIN_DATA[i].label };
+ v.append(pd);
+ }
+ return v;
+}
+
+bool Port::Parallel::isGroundPin(uint pin) const
+{
+ return ( PIN_DATA[pin].label==QString("GND") );
+}
+
+Port::IODir Port::Parallel::ioDir(uint pin) const
+{
+ return PIN_DATA[pin].dir;
+}
+
+const Port::Parallel::RequestData Port::Parallel::REQUEST_DATA[Nb_RequestTypes] = {
+#if defined(HAVE_PPDEV)
+ { PPRCONTROL, PPWCONTROL },
+ { PPRSTATUS, 0 },
+ { PPRDATA, PPWDATA }
+#elif defined(HAVE_PPBUS)
+ { PPIGCTRL, PPISCTRL },
+ { PPIGSTATUS, 0 },
+ { PPIGDATA, PPISDATA }
+#else
+ { 0, 0 },
+ { 0, 0 },
+ { 0, 0 }
+#endif
+};
+
+Port::Parallel::Parallel(const QString &device, Log::Base &base)
+ : Base(base), _fd(-1), _device(device)
+{
+ for (uint i=0; i<Nb_RequestTypes; i++) _images[i] = 0;
+}
+
+bool Port::Parallel::internalOpen()
+{
+#if defined(HAVE_PPDEV)
+ _fd = ::open(_device.latin1(), O_RDWR);
+ if ( _fd<0 ) {
+ setSystemError(i18n("Could not open device \"%1\"").arg(_device));
+ return false;
+ }
+ if ( ioctl(_fd, PPCLAIM)<0 ) {
+ setSystemError(i18n("Could not claim device \"%1\": check it is read/write enabled").arg(_device));
+ return false;
+ }
+#elif defined(HAVE_PPBUS)
+ _fd = ::open(_device.latin1(), O_RDWR);
+ if ( _fd<0 ) {
+ setSystemError(i18n("Could not open device \"%1\"").arg(_device));
+ return false;
+ }
+#endif
+ return true;
+}
+
+void Port::Parallel::internalClose()
+{
+ if ( _fd<0 ) return;
+#if defined(HAVE_PPDEV)
+ ioctl(_fd, PPRELEASE);
+ ::close(_fd);
+#elif defined(HAVE_PPBUS)
+ ::close(_fd);
+#endif
+ _fd = -1;
+}
+
+bool Port::Parallel::setPinOn(uint pin, bool on, LogicType type)
+{
+ if ( _fd<0 ) return false;
+#if defined(HAVE_PPDEV) || defined(HAVE_PPBUS)
+ Q_ASSERT( pin<Nb_Pins );
+ Q_ASSERT( PIN_DATA[pin].dir==Out );
+ RequestType rtype = PIN_DATA[pin].rType;
+ Q_ASSERT( rtype!=Nb_RequestTypes );
+ uchar mask = PIN_DATA[pin].mask;
+ uchar c = (XOR(type==NegativeLogic, on) ? _images[rtype] | mask : _images[rtype] & ~mask);
+ int request = REQUEST_DATA[rtype].write;
+ Q_ASSERT( request!=0 );
+ if ( ioctl(_fd, request, &c)<0 ) {
+ setSystemError(i18n("Error setting pin %1 to %2").arg(PIN_DATA[pin].label).arg(on));
+ return false;
+ }
+ _images[rtype] = c;
+#endif
+ return true;
+}
+
+bool Port::Parallel::readPin(uint pin, LogicType type, bool &value)
+{
+ if ( _fd<0 ) return false;
+#if defined(HAVE_PPDEV) || defined(HAVE_PPBUS)
+ Q_ASSERT( pin<Nb_Pins );
+ Q_ASSERT( PIN_DATA[pin].dir==In );
+ RequestType rtype = PIN_DATA[pin].rType;
+ Q_ASSERT( rtype!=Nb_RequestTypes );
+ int request = REQUEST_DATA[rtype].read;
+ Q_ASSERT( request!=0 );
+ uchar c = 0;
+ if ( ioctl(_fd, request, &c)<0 ) {
+ setSystemError(i18n("Error reading bit on pin %1").arg(PIN_DATA[pin].label));
+ return false;
+ }
+ _images[rtype] = c;
+ value = (type==NegativeLogic ? ~c : c ) & PIN_DATA[pin].mask;
+#endif
+ return true;
+}
+
+void Port::Parallel::setSystemError(const QString &message)
+{
+#if defined(HAVE_PPDEV) || defined(HAVE_PPBUS)
+ log(Log::LineType::Error, message + QString(" (errno=%1).").arg(strerror(errno)));
+#else
+ Q_UNUSED(message);
+#endif
+}
diff --git a/src/common/port/parallel.h b/src/common/port/parallel.h
new file mode 100644
index 0000000..1473db0
--- /dev/null
+++ b/src/common/port/parallel.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * Copyright (C) 2002-2003 Stephen Landamore <stephen@landamore.com> *
+ * *
+ * 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 PARALLEL_H
+#define PARALLEL_H
+
+#include "port_base.h"
+#if defined(Q_OS_WIN)
+# undef ERROR
+#endif
+
+namespace Port
+{
+
+class Parallel : public Base
+{
+public:
+ Parallel(const QString &device, Log::Base &base);
+ virtual ~Parallel() { close(); }
+ virtual Description description() const { return Description(PortType::Parallel, _device); }
+
+ static IODirs probe(const QString &device);
+ static const QStringList &probedDeviceList();
+ static bool isAvailable();
+
+ enum Pin { DS = 0, D0, D1, D2, D3, D4, D5, D6, D7, ACK, BUSY, PAPER, SELin,
+ LF, ERROR, PRIME, SELout, P18, P19, P20, P21, P22, P23, P24, P25,
+ Nb_Pins };
+ enum RequestType { Control = 0, Status, Data, Nb_RequestTypes };
+ struct PPinData {
+ RequestType rType;
+ uchar mask;
+ IODir dir;
+ const char *label;
+ };
+ static const PPinData PIN_DATA[Nb_Pins];
+ virtual bool setPinOn(uint pin, bool on, LogicType type);
+ virtual bool readPin(uint pin, LogicType type, bool &value);
+ virtual QValueVector<PinData> pinData(IODir dir) const;
+ virtual bool isGroundPin(uint pin) const;
+ virtual uint groundPin() const { return P25; }
+ virtual IODir ioDir(uint pin) const;
+
+private:
+ int _fd;
+ QString _device;
+ struct RequestData {
+ int read, write;
+ };
+ static const RequestData REQUEST_DATA[Nb_RequestTypes];
+ uchar _images[Nb_RequestTypes];
+
+ static QStringList *_list;
+ static QStringList deviceList();
+
+ virtual bool internalOpen();
+ virtual void internalClose();
+ virtual void setSystemError(const QString &message);
+};
+
+} // namespace
+
+#endif
diff --git a/src/common/port/port.cpp b/src/common/port/port.cpp
new file mode 100644
index 0000000..c56c120
--- /dev/null
+++ b/src/common/port/port.cpp
@@ -0,0 +1,98 @@
+/***************************************************************************
+ * 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 "port.h"
+
+#if defined(Q_WS_WIN)
+# include <sys/timeb.h>
+#else
+# include <sys/time.h>
+#endif
+
+#include "common/global/global.h"
+#include "serial.h"
+#include "parallel.h"
+#include "usb_port.h"
+
+//-----------------------------------------------------------------------------
+void getTime(int &sec, int &usec)
+{
+#if defined (Q_OS_WIN)
+ struct _timeb tb;
+ _ftime (&tb);
+ sec = tb.time;
+ usec = tb.millitm * 1000 + 500;
+#else
+ struct timeval tv;
+ gettimeofday(&tv, 0);
+ usec = tv.tv_usec;
+ sec = tv.tv_sec;
+#endif
+}
+
+void Port::msleep(uint ms)
+{
+ usleep(ms*1000);
+}
+
+// from Brian C Lane's code
+// works better than usleep
+void Port::usleep(uint us)
+{
+ if ( us==0 ) return;
+ int tsec, tusec;
+ getTime(tsec, tusec);
+ int usec = (tusec + us) % 1000000;
+ int sec = tsec + (tusec + us) / 1000000;
+ for (;;) {
+ getTime(tsec, tusec);
+ if ( tsec>sec ) return;
+ if ( tsec==sec && tusec>usec ) return;
+ }
+}
+
+//-----------------------------------------------------------------------------
+const PortType::Data PortType::DATA[Nb_Types] = {
+ { I18N_NOOP("Serial Port"), "serial", true },
+ { I18N_NOOP("Parallel Port"), "parallel", true },
+ { I18N_NOOP("USB Port"), "usb", false }
+};
+
+const char * const Port::IO_DIR_NAMES[3] = { "no_io", "in", "out" };
+
+QStringList Port::probedDeviceList(PortType type)
+{
+ if ( !isAvailable(type) ) return QStringList();
+ switch (type.type()) {
+ case PortType::Serial: return Serial::probedDeviceList();
+ case PortType::Parallel: return Parallel::probedDeviceList();
+ case PortType::USB: return USB::probedDeviceList();
+ case PortType::Nb_Types: break;
+ }
+ return QStringList();
+}
+
+bool Port::isAvailable(PortType type)
+{
+ switch (type.type()) {
+ case PortType::Serial: return Serial::isAvailable();
+ case PortType::Parallel: return Parallel::isAvailable();
+ case PortType::USB: return USB::isAvailable();
+ case PortType::Nb_Types: break;
+ }
+ return false;
+}
+
+PortType Port::findType(const QString &portDevice)
+{
+ FOR_EACH(PortType, type) {
+ if ( !type.data().withDevice ) continue;
+ if ( probedDeviceList(type).contains(portDevice) ) return type;
+ }
+ return PortType::Nb_Types;
+}
diff --git a/src/common/port/port.h b/src/common/port/port.h
new file mode 100644
index 0000000..f385deb
--- /dev/null
+++ b/src/common/port/port.h
@@ -0,0 +1,56 @@
+/***************************************************************************
+ * 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 PORT_H
+#define PORT_H
+
+#include <qstringlist.h>
+
+#include "common/global/global.h"
+#include "common/common/key_enum.h"
+
+//-----------------------------------------------------------------------------
+struct PortTypeData {
+ const char *label, *key;
+ bool withDevice;
+};
+
+BEGIN_DECLARE_ENUM(PortType)
+ Serial = 0, Parallel, USB
+END_DECLARE_ENUM(PortType, PortTypeData)
+
+namespace Port
+{
+//-----------------------------------------------------------------------------
+extern void msleep(uint ms); // in milliseconds
+extern void usleep(uint us); // in microseconds
+
+//-----------------------------------------------------------------------------
+ class Description {
+ public:
+ Description() : type(PortType::Nb_Types) {}
+ Description(PortType ptype, const QString &pdevice) : type(ptype), device(pdevice) {}
+ PortType type;
+ QString device;
+ };
+
+ enum IODir { NoIO = 0, In = 1, Out = 2 };
+ extern const char * const IO_DIR_NAMES[3];
+ Q_DECLARE_FLAGS(IODirs, IODir)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(IODirs)
+ extern QStringList probedDeviceList(PortType type);
+ extern PortType findType(const QString &device);
+ extern bool isAvailable(PortType type);
+ struct PinData {
+ uint pin;
+ const char *label;
+ };
+ enum LogicType { PositiveLogic, NegativeLogic };
+} // namespace
+
+#endif
diff --git a/src/common/port/port.pro b/src/common/port/port.pro
new file mode 100644
index 0000000..f09414b
--- /dev/null
+++ b/src/common/port/port.pro
@@ -0,0 +1,10 @@
+STOPDIR = ../../..
+include($${STOPDIR}/lib.pro)
+
+TARGET = port
+HEADERS += port.h port_base.h parallel.h serial.h usb_port.h
+SOURCES += port.cpp port_base.cpp parallel.cpp serial.cpp usb_port.cpp
+contains(DEFINES, HAVE_USB) {
+ win32:INCLUDEPATH += $${LIBUSB_PATH}\include
+}
+
diff --git a/src/common/port/port_base.cpp b/src/common/port/port_base.cpp
new file mode 100644
index 0000000..7528eeb
--- /dev/null
+++ b/src/common/port/port_base.cpp
@@ -0,0 +1,127 @@
+/***************************************************************************
+ * 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 "port_base.h"
+
+#include "common/global/global.h"
+#include "common/common/misc.h"
+#include "common/common/number.h"
+
+bool Port::Base::open()
+{
+ close();
+ resetError();
+ _closing = false;
+ return internalOpen();
+}
+
+void Port::Base::close()
+{
+ _closing = true;
+ internalClose();
+}
+
+bool Port::Base::send(const char *data, uint size, uint timeout)
+{
+ log(Log::DebugLevel::LowLevel, QString("Sending: \"%1\"").arg(toPrintable(data, size, PrintAlphaNum)));
+ return internalSend(data, size, timeout);
+}
+
+bool Port::Base::receive(uint size, QString &s, uint timeout)
+{
+ QMemArray<uchar> a;
+ if ( !receive(size, a, timeout) ) return false;
+ s.fill(0, size);
+ for (uint i=0; i<size; i++) s[i] = a[i];
+ return true;
+}
+
+bool Port::Base::receive(uint size, QMemArray<uchar> &a, uint timeout)
+{
+ a.resize(size);
+ bool ok = internalReceive(size, (char *)a.data(), timeout);
+ if (ok) log(Log::DebugLevel::LowLevel, QString("Received: \"%1\"").arg(toPrintable(a, PrintAlphaNum)));
+ return ok;
+}
+
+bool Port::Base::receiveChar(char &c, uint timeout)
+{
+ if ( !internalReceive(1, &c, timeout) ) return false;
+ log(Log::DebugLevel::LowLevel, QString("Received: \"%1\"").arg(toPrintable(c, PrintAlphaNum)));
+ return true;
+}
+
+bool Port::Base::setPinOn(uint, bool, LogicType)
+{
+ qFatal("setPinOn not implemented");
+ return false;
+}
+bool Port::Base::readPin(uint, LogicType, bool &)
+{
+ qFatal("readPin not implemented");
+ return 0;
+}
+QValueVector<Port::PinData> Port::Base::pinData(IODir) const
+{
+ qFatal("pinData not implemented");
+ return QValueVector<PinData>();
+}
+bool Port::Base::isGroundPin(uint) const
+{
+ qFatal("isGroundPin not implemented");
+ return false;
+}
+uint Port::Base::groundPin() const
+{
+ qFatal("groundPin not implemented");
+ return 0;
+}
+Port::IODir Port::Base::ioDir(uint) const
+{
+ qFatal("ioType not implemented");
+ return NoIO;
+}
+
+void Port::Base::log(Log::LineType lineType, const QString &message)
+{
+ if ( lineType==Log::LineType::Error && _closing ) return;
+ Log::Base::log(lineType, description().type.label() + ": " + message);
+ if ( lineType==Log::LineType::Error ) close();
+}
+
+void Port::Base::log(Log::DebugLevel level, const QString &message)
+{
+ Log::Base::log(level, description().type.label() + ": " + message);
+}
+
+void Port::Base::logData(const QString &)
+{
+/*
+ QString vs;
+ for (uint i=0; i<s.length(); i++) {
+ char c = s[i];
+ switch (c) {
+ case '\r': vs += "\\r"; break;
+ case '\n': vs += "\\n"; break;
+ case '<': vs += "&lt;"; break;
+ case '>': vs += "&gt;"; break;
+ default: {
+ if ( c>=32 && c<=126 ) vs += c;
+ else {
+ QString tmp;
+ tmp.sprintf("\\x%02x", c);
+ vs += tmp;
+ }
+ break;
+ }
+ }
+ }
+ qDebug("%s", vs.latin1());
+*/
+ //log(Log::Debug, vs);
+}
diff --git a/src/common/port/port_base.h b/src/common/port/port_base.h
new file mode 100644
index 0000000..3ae4787
--- /dev/null
+++ b/src/common/port/port_base.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * 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 PORT_BASE_H
+#define PORT_BASE_H
+
+#include "port.h"
+#include "common/global/log.h"
+
+namespace Port
+{
+
+class Base : public Log::Base
+{
+public:
+ Base(Log::Base &base) : Log::Base(&base) {}
+ virtual PortType type() const { return description().type; }
+ virtual Description description() const = 0;
+ bool open();
+ void close();
+
+ virtual void log(Log::LineType kind, const QString &message);
+ virtual void log(Log::DebugLevel level, const QString &message);
+ void logData(const QString &s);
+
+ enum { DEFAULT_TIMEOUT = 3000 }; // 3s
+ bool sendChar(char c, uint timeout = DEFAULT_TIMEOUT) { return send(&c, 1, timeout); }
+ bool send(const char *data, uint size, uint timeout = DEFAULT_TIMEOUT);
+ bool send(const QMemArray<uchar> &a, uint timeout = DEFAULT_TIMEOUT) { return send((const char *)a.data(), a.count(), timeout); }
+ bool receiveChar(char &c, uint timeout = DEFAULT_TIMEOUT);
+ bool receive(uint size, QString &s, uint timeout = DEFAULT_TIMEOUT);
+ bool receive(uint size, QMemArray<uchar> &a, uint timeout = DEFAULT_TIMEOUT);
+
+ virtual bool setPinOn(uint pin, bool on, LogicType type);
+ virtual bool readPin(uint pin, LogicType type, bool &value);
+ virtual QValueVector<PinData> pinData(IODir dir) const;
+ virtual bool isGroundPin(uint pin) const;
+ virtual uint groundPin() const;
+ virtual IODir ioDir(uint pin) const;
+
+protected:
+ virtual bool internalOpen() = 0;
+ virtual void internalClose() = 0;
+ virtual bool internalSend(const char *, uint, uint) { qFatal("Not implemented"); return false; }
+ virtual bool internalReceive(uint, char *, uint) { qFatal("Not implemented"); return false; }
+ virtual void setSystemError(const QString &message) = 0;
+
+private:
+ bool _closing;
+};
+
+} // namespace
+
+#endif
diff --git a/src/common/port/serial.cpp b/src/common/port/serial.cpp
new file mode 100644
index 0000000..b370d22
--- /dev/null
+++ b/src/common/port/serial.cpp
@@ -0,0 +1,523 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * Copyright (C) 2002-2003 Stephen Landamore <stephen@landamore.com> *
+ * *
+ * 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 "serial.h"
+
+#ifdef Q_OS_UNIX
+# include <stdio.h>
+# include <fcntl.h>
+# include <sys/time.h>
+# include <sys/types.h>
+# include <sys/stat.h>
+# include <sys/ioctl.h>
+# include <errno.h>
+# include <unistd.h> // needed on some system
+#endif
+#include <qdatetime.h>
+
+//-----------------------------------------------------------------------------
+QStringList *Port::Serial::_list = 0;
+#if defined(Q_OS_UNIX)
+const Port::Serial::Handle Port::Serial::INVALID_HANDLE = -1;
+#elif defined(Q_OS_WIN)
+const Port::Serial::Handle Port::Serial::INVALID_HANDLE = INVALID_HANDLE_VALUE;
+#endif
+
+Port::Serial::Handle Port::Serial::openHandle(const QString &device, IODirs dirs)
+{
+#if defined(Q_OS_UNIX)
+ // open non blocking: avoid missing DCD (comment from xwisp2)
+ int mode = O_NOCTTY | O_NONBLOCK;
+ if ( dirs & In ) {
+ if ( dirs & Out ) mode |= O_RDWR;
+ else mode |= O_RDONLY;
+ } else mode |= O_WRONLY;
+ return ::open(device.latin1(), mode);
+#elif defined(Q_OS_WIN)
+ int mode = 0;
+ if ( dirs & In ) mode |= GENERIC_READ;
+ if ( dirs & Out ) mode |= GENERIC_WRITE;
+ return CreateFileA(device.latin1(), mode, 0, NULL, OPEN_EXISTING, FILE_FLAG_NO_BUFFERING, NULL);
+#endif
+}
+
+void Port::Serial::closeHandle(Handle handle)
+{
+#if defined(Q_OS_UNIX)
+ ::close(handle);
+#elif defined(Q_OS_WIN)
+ CloseHandle(handle);
+#endif
+}
+
+Port::IODirs Port::Serial::probe(const QString &device)
+{
+ Handle handle = openHandle(device, In);
+ if ( handle==INVALID_HANDLE ) return NoIO;
+ closeHandle(handle);
+ handle = openHandle(device, In | Out);
+ if ( handle==INVALID_HANDLE ) return In;
+ closeHandle(handle);
+ return (In | Out);
+}
+
+QStringList Port::Serial::deviceList()
+{
+ QStringList list;
+#if defined(Q_OS_UNIX)
+ // standard serport in user space
+ for (uint i=0; i<8; i++) list.append(QString("/dev/ttyS%1").arg(i));
+ // new devfs serport flavour
+ for (uint i=0; i<8; i++) list.append(QString("/dev/tts/%1").arg(i));
+ // standard USB serport in user space
+ for (uint i=0; i<8; i++) list.append(QString("/dev/ttyUSB%1").arg(i));
+ // new devfs USB serport flavour
+ for (uint i=0; i<8; i++) list.append(QString("/dev/usb/tts/%1").arg(i));
+ // FreeBSD
+ for (uint i=0; i<8; i++) list.append(QString("/dev/ttyd%1").arg(i));
+ // Slackware 11 devfs USB Serial port support.
+ for (uint i=0; i<8; i++) list.append(QString("/dev/tts/USB%1").arg(i));
+ // MacOSX devfs USB Serial port support.
+ list.append("/dev/tty.usbserial");
+#elif defined(Q_OS_WIN)
+ for (uint i=1; i<10; i++) list.append(QString("COM%1").arg(i));
+#endif
+ return list;
+}
+
+const QStringList &Port::Serial::probedDeviceList()
+{
+ if ( _list==0 ) {
+ QStringList all = deviceList();
+ _list = new QStringList;
+ for (uint i=0; i<uint(all.count()); i++)
+ if( probe(all[i]) & (In | Out) ) _list->append(all[i]);
+ }
+ return *_list;
+}
+
+//-----------------------------------------------------------------------------
+const uint Port::Serial::SPEED_VALUES[Nb_Speeds] = {
+ 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 1800, 2400, 4800, 9600, 19200, 38400,
+ 57600, 115200
+};
+const Port::Serial::SpeedData Port::Serial::SPEED_DATA[Nb_Speeds] = {
+#if defined(Q_OS_UNIX)
+ { true, B0 }, { true, B50 }, { true, B75 }, { true, B110 },
+ { true, B134 }, { true, B150 }, { true, B200 }, { true, B300 },
+ { true, B600 }, { true, B1200 }, { true, B1800 }, { true, B2400 },
+ { true, B4800 }, { true, B9600 }, { true, B19200 }, { true, B38400 },
+ { true, B57600 }, { true, B115200 }
+#elif defined(Q_OS_WIN)
+ { false, 0 }, { false, 0 }, { false, 0 }, { true, CBR_110 },
+ { false, 0 }, { false, 0 }, { false, 0 }, { true, CBR_300 },
+ { true, CBR_600 }, { true, CBR_1200 }, { false, 0 }, { true, CBR_2400 },
+ { true, CBR_4800 }, { true, CBR_9600 }, { true, CBR_19200 }, { true, CBR_38400 },
+ { true, CBR_57600 }, { true, CBR_115200 }
+#endif
+};
+
+const Port::Serial::SPinData Port::Serial::PIN_DATA[Nb_Pins] = {
+ { In, "DCD" }, { In, "RX" }, { Out, "TX" }, { Out, "DTR" },
+ { NoIO, "GND" }, { In, "DSR" }, { Out, "RTS" }, { In, "CTS" },
+ { Out, "RI" }
+};
+
+QValueVector<Port::PinData> Port::Serial::pinData(IODir dir) const
+{
+ QValueVector<PinData> v;
+ for (uint i=0; i<Nb_Pins; i++) {
+ if ( PIN_DATA[i].dir!=dir ) continue;
+ PinData pd = { i, PIN_DATA[i].label };
+ v.append(pd);
+ }
+ return v;
+}
+bool Port::Serial::isGroundPin(uint pin) const
+{
+ return ( PIN_DATA[pin].label==QString("GND") );
+}
+
+Port::IODir Port::Serial::ioDir(uint pin) const
+{
+ return PIN_DATA[pin].dir;
+}
+
+Port::Serial::Serial(const QString &device, Properties properties, Log::Base &base)
+ : Base(base), _device(device), _properties(properties), _fd(INVALID_HANDLE)
+{}
+
+bool Port::Serial::getParameters(Parameters &parameters)
+{
+ if ( _fd==INVALID_HANDLE ) return false;
+#if defined(Q_OS_UNIX)
+ if ( tcgetattr(_fd, &parameters)<0 ) {
+#elif defined(Q_OS_WIN)
+ if ( !GetCommState(_fd, &parameters.dcb) || !GetCommTimeouts(_fd, &parameters.comtmo) ) {
+#endif
+ setSystemError(i18n("Could not get file descriptor parameters"));
+ return false;
+ }
+ return true;
+}
+
+bool Port::Serial::setParameters(const Parameters &parameters)
+{
+ if ( _fd==INVALID_HANDLE ) return false;
+#if defined(Q_OS_UNIX)
+ if ( tcsetattr(_fd, TCSANOW, &parameters)<0 ) {
+#elif defined(Q_OS_WIN)
+ Parameters tmp = parameters;
+ if ( !SetCommState(_fd, &tmp.dcb) || !SetCommTimeouts(_fd, &tmp.comtmo) ) {
+#endif
+ setSystemError(i18n("Could not set file descriptor parameters"));
+ return false;
+ }
+ return true;
+}
+
+bool Port::Serial::internalOpen()
+{
+ _fd = openHandle(_device, In | Out);
+ if ( _fd==INVALID_HANDLE ) {
+ setSystemError(i18n("Could not open device \"%1\" read-write").arg(_device));
+ return false;
+ }
+ if ( !getParameters(_oldParameters) ) return false; // save configuration
+#if defined(Q_OS_UNIX)
+ if ( _properties & Blocking ) {
+ int flags = fcntl(_fd, F_GETFL, 0);
+ if ( fcntl(_fd, F_SETFL, flags & ~O_NONBLOCK)<0 ) {
+ setSystemError(i18n("Could not modify file descriptor flags"));
+ return false;
+ }
+ }
+#endif
+ return flush(DEFAULT_TIMEOUT);
+}
+
+void Port::Serial::internalClose()
+{
+ if ( _fd==INVALID_HANDLE ) return;
+ if ( _properties & NeedFlush ) flush(0);
+ if ( _properties & NeedBreak ) doBreak(1);
+ setParameters(_oldParameters);
+ closeHandle(_fd);
+ _fd = INVALID_HANDLE;
+}
+
+bool Port::Serial::internalSend(const char *data, uint size, uint timeout)
+{
+ if ( _fd==INVALID_HANDLE ) return false;
+ QTime time;
+ time.start();
+ for (uint todo=size; todo!=0; ) {
+#if defined(Q_OS_UNIX)
+ int res = write(_fd, data+size-todo, todo);
+ if ( res<0 && errno!=EAGAIN ) {
+#elif defined(Q_OS_WIN)
+ DWORD res = 0;
+ if ( WriteFile(_fd, data+size-todo, todo, &res, NULL)==0 ) {
+#endif
+ setSystemError(i18n("Error sending data"));
+ return false;
+ }
+ if ( res>0 ) todo -= res;
+ else {
+ if ( uint(time.elapsed())>timeout ) {
+ log(Log::LineType::Error, i18n("Timeout sending data (%1/%2 bytes sent).").arg(size-todo).arg(size));
+ return false;
+ }
+ msleep(1);
+ }
+ }
+ if ( (_properties & NeedDrain) && !drain(timeout) ) return false;
+ return true;
+}
+
+bool Port::Serial::internalReceive(uint size, char *data, uint timeout)
+{
+ if ( _fd==INVALID_HANDLE ) return false;
+ QTime time;
+ time.start();
+ for(uint todo=size; todo!=0; ) {
+#if defined(Q_OS_UNIX)
+ // this help reduce CPU usage. It also prevents blocking if the serial cable is disconnected
+ fd_set rfd;
+ FD_ZERO(&rfd);
+ FD_SET(_fd, &rfd);
+ struct timeval tv;
+ tv.tv_sec = timeout / 1000;
+ tv.tv_usec = (timeout%1000)*1000;
+ int res = select(_fd+1, &rfd, 0, 0, &tv);
+ if ( res<0 ) {
+ setSystemError(i18n("Error receiving data"));
+ return false;
+ }
+ if ( res==0 ) {
+ log(Log::LineType::Error, i18n("Timeout waiting for data."));
+ return false;
+ }
+ res = read(_fd, data+size-todo, todo);
+ if ( res<0 && errno!=EAGAIN ) {
+#elif defined(Q_OS_WIN)
+ DWORD res = 0;
+ if ( ReadFile(_fd, data+size-todo, todo, &res, NULL)==0 ) {
+#endif
+ setSystemError(i18n("Error receiving data"));
+ return false;
+ }
+ if ( res>0 ) todo -= res;
+ else {
+ if ( uint(time.elapsed())>timeout ) {
+ log(Log::LineType::Error, i18n("Timeout receiving data (%1/%2 bytes received).").arg(size-todo).arg(size));
+ return false;
+ }
+ msleep(1);
+ }
+ }
+ return true;
+}
+
+bool Port::Serial::drain(uint timeout)
+{
+ if ( _fd==INVALID_HANDLE ) return false;
+#if defined(Q_OS_UNIX)
+ // tcdrain will block if the serial cable is disconnected
+ // so we first check for data in output buffer...
+ QTime time;
+ time.start();
+ for (;;) {
+ int nb;
+ if ( ioctl(_fd, TIOCOUTQ, &nb)==-1 ) {
+ setSystemError(i18n("Error checking for data in output buffer"));
+ return false;
+ }
+ if ( nb==0 ) break;
+ if ( uint(time.elapsed())>timeout ) {
+ _fd = INVALID_HANDLE; // otherwise close blocks...
+ log(Log::LineType::Error, i18n("Timeout sending data (%1 bytes left).").arg(nb));
+ return false;
+ }
+ }
+ if ( tcdrain(_fd)<0 ) {
+ setSystemError(i18n("Error while draining"));
+ return false;
+ }
+#endif
+ return true;
+}
+
+bool Port::Serial::flush(uint timeout)
+{
+ if ( _fd==INVALID_HANDLE ) return false;
+ if ( (_properties & NeedDrain) && !drain(timeout) ) return false;
+#if defined(Q_OS_UNIX)
+ if ( tcflush(_fd, TCIFLUSH)<0 ) {
+#elif defined(Q_OS_WIN)
+ if ( FlushFileBuffers(_fd)==0 || PurgeComm(_fd, PURGE_TXABORT)==0
+ || PurgeComm(_fd, PURGE_RXABORT)==0 || PurgeComm(_fd, PURGE_TXCLEAR)==0
+ || PurgeComm(_fd, PURGE_RXCLEAR)==0 ) {
+#endif
+ setSystemError(i18n("Could not flush device"));
+ return false;
+ }
+ return true;
+}
+
+bool Port::Serial::internalSetPinOn(Pin pin, bool on)
+{
+#if defined(Q_OS_UNIX)
+ int bit = 0;
+ switch (pin) {
+ case TX: return ( ioctl(_fd, on ? TIOCSBRK : TIOCCBRK, 0)>=0 );
+ case DTR: bit = TIOCM_DTR; break;
+ case RTS: bit = TIOCM_RTS; break;
+ case RI: bit = TIOCM_RI; break;
+ default: Q_ASSERT(false); return false;
+ }
+ return ( ioctl(_fd, on ? TIOCMBIS : TIOCMBIC, &bit)>=0 );
+#elif defined(Q_OS_WIN)
+ DWORD func = 0;
+ switch (pin) {
+ case TX: func = (on ? SETBREAK : CLRBREAK); break;
+ case DTR: func = (on ? SETDTR : CLRDTR); break;
+ case RTS: func = (on ? SETRTS : CLRRTS); break;
+ case RI: // #### not possible with Win32 API ??
+ default: Q_ASSERT(false); return false;
+ }
+ return ( EscapeCommFunction(_fd, func)!=0 );
+#endif
+}
+
+bool Port::Serial::setPinOn(uint pin, bool on, LogicType type)
+{
+ if ( _fd==INVALID_HANDLE ) return false;
+ if ( type==NegativeLogic ) on = !on;
+ Q_ASSERT( pin<Nb_Pins );
+ Q_ASSERT( PIN_DATA[pin].dir==Out );
+ if ( !internalSetPinOn(Pin(pin), on) ) {
+ setSystemError(i18n("Error setting bit %1 of serial port to %2").arg(PIN_DATA[pin].label).arg(on));
+ return false;
+ }
+ return true;
+}
+
+bool Port::Serial::internalReadPin(Pin pin, LogicType type, bool &value)
+{
+#if defined(Q_OS_UNIX)
+ int bits;
+ if ( ioctl(_fd, TIOCMGET, &bits)<0 ) return false;
+ int mask = 0;
+ switch (pin) {
+ case DCD: mask = TIOCM_CD; break;
+ case RX : mask = TIOCM_SR; break;
+ case DSR: mask = TIOCM_DSR; break;
+ case CTS: mask = TIOCM_CTS; break;
+ default: Q_ASSERT(false); return false;
+ }
+ value = ((type==NegativeLogic ? ~bits : bits) & mask);
+ return true;
+#elif defined(Q_OS_WIN)
+ DWORD status;
+ if ( GetCommModemStatus(_fd, &status)==0 ) return false;
+ switch (pin) {
+ case DCD: value = (status & MS_RLSD_ON); break;
+ case DSR: value = (status & MS_DSR_ON); break;
+ case CTS: value = (status & MS_CTS_ON); break;
+ case RX: // not possible with Win32 API ??
+ default: Q_ASSERT(false); return false;
+ }
+ if ( type==NegativeLogic) value = !value;
+ return true;
+#endif
+}
+
+ bool Port::Serial::readPin(uint pin, LogicType type, bool &value)
+{
+ if ( _fd==INVALID_HANDLE ) return false;
+ Q_ASSERT( pin<Nb_Pins );
+ Q_ASSERT( PIN_DATA[pin].dir==In );
+ if ( !internalReadPin(Pin(pin), type, value) ) {
+ setSystemError(i18n("Error reading serial pin %1").arg(PIN_DATA[pin].label));
+ return false;
+ }
+ return true;
+}
+
+bool Port::Serial::setMode(InputFlags inputFlags, ControlFlags controlFlags, Speed speed, uint readTimeout)
+{
+ Q_ASSERT (SPEED_DATA[speed].supported );
+ if ( !flush(0) ) return false;
+ Parameters parameters;
+ if ( !getParameters(parameters) ) return false;
+#if defined(Q_OS_UNIX)
+ cfsetispeed(&parameters, SPEED_DATA[speed].flag);
+ cfsetospeed(&parameters, SPEED_DATA[speed].flag);
+ parameters.c_cflag &= ~(CSIZE|PARENB|PARODD|HUPCL|CSTOPB);
+ int cflags = 0;
+ if ( controlFlags & ByteSize8 ) cflags |= CS8;
+ if ( controlFlags & HardwareFlowControl ) cflags |= CRTSCTS;
+ if ( controlFlags & EnableReceiver ) cflags |= CREAD;
+ if ( controlFlags & IgnoreControlLines ) cflags |= CLOCAL;
+ parameters.c_cflag |= cflags;
+ parameters.c_iflag &= ~(ISTRIP|INPCK|IGNCR|INLCR|ICRNL|IXOFF|IXON);
+ int iflags = 0;
+ if ( inputFlags & IgnoreBreak ) iflags |= IGNBRK;
+ if ( inputFlags & IgnoreParity ) iflags |= IGNPAR;
+ parameters.c_iflag |= iflags;
+ parameters.c_oflag &= ~OPOST;
+ parameters.c_lflag &= ~(ICANON|ECHO|ECHONL|ISIG|IEXTEN|TOSTOP);
+ parameters.c_cc[VMIN] = 0; // wait for 1 char or timeout
+ parameters.c_cc[VTIME] = readTimeout/100; // wait in deciseconds
+#elif defined(Q_OS_WIN)
+ if ( controlFlags & EnableReceiver ) ; // #### not sure what to do
+ if ( controlFlags & IgnoreControlLines ) ; // #### not sure what to do
+ setHardwareFlowControl(parameters, (controlFlags & HardwareFlowControl));
+ if ( inputFlags & IgnoreParity ) parameters.dcb.Parity = NOPARITY;
+ parameters.dcb.StopBits = ONESTOPBIT;
+ if ( controlFlags & ByteSize8 ) parameters.dcb.ByteSize = 8;
+ parameters.dcb.BaudRate = SPEED_DATA[speed].flag;
+ parameters.comtmo.ReadIntervalTimeout = MAXDWORD;
+ parameters.comtmo.ReadTotalTimeoutMultiplier = MAXDWORD;
+ parameters.comtmo.ReadTotalTimeoutConstant = readTimeout;
+ parameters.comtmo.WriteTotalTimeoutMultiplier = 1;
+ parameters.comtmo.WriteTotalTimeoutConstant = readTimeout;
+#endif
+ return setParameters(parameters);
+ // need flush ??
+}
+
+bool Port::Serial::doBreak(uint duration)
+{
+ if ( !flush(0) ) return false;
+#if defined(Q_OS_UNIX)
+ if ( ioctl(_fd, TIOCSBRK)<0 ) {
+#elif defined(Q_OS_WIN)
+ if ( SetCommBreak(_fd)==0 ) {
+#endif
+ setSystemError(i18n("Error setting up break"));
+ return false;
+ }
+ msleep(duration);
+#if defined(Q_OS_UNIX)
+ if ( ioctl(_fd, TIOCCBRK) ) {
+#elif defined(Q_OS_WIN)
+ if ( ClearCommBreak(_fd)==0 ) {
+#endif
+ setSystemError(i18n("Error clearing up break"));
+ return false;
+ }
+ msleep(1);
+ return flush(0);
+}
+
+void Port::Serial::setHardwareFlowControl(Parameters &parameters, bool on)
+{
+#if defined(Q_OS_UNIX)
+ if (on) parameters.c_cflag |= CRTSCTS;
+ else parameters.c_cflag &= ~CRTSCTS;
+ parameters.c_cc[VMIN] = 0; // #### needed ?
+ parameters.c_cc[VTIME] = 0; // #### needed ?
+#elif defined(Q_OS_WIN)
+ // #### not sure about that
+ parameters.dcb.fParity = on;
+ parameters.dcb.fOutxCtsFlow = on;
+ parameters.dcb.fOutxDsrFlow = on;
+ parameters.dcb.fDtrControl = (on ? DTR_CONTROL_ENABLE : DTR_CONTROL_DISABLE);
+ parameters.dcb.fDsrSensitivity = on;
+ parameters.dcb.fTXContinueOnXoff = on;
+ parameters.dcb.fOutX = on;
+ parameters.dcb.fInX = on;
+ parameters.dcb.fNull = on;
+ parameters.dcb.fRtsControl = (on ? RTS_CONTROL_ENABLE : RTS_CONTROL_DISABLE);
+ parameters.dcb.fAbortOnError = on;
+#endif
+}
+
+bool Port::Serial::setHardwareFlowControl(bool on)
+{
+ Parameters parameters;
+ if ( !getParameters(parameters) ) return false;
+ setHardwareFlowControl(parameters, on);
+ return setParameters(parameters);
+}
+
+void Port::Serial::setSystemError(const QString &message)
+{
+#if defined(Q_OS_UNIX)
+ log(Log::LineType::Error, message + QString(" (errno=%1)").arg(strerror(errno)));
+#elif defined(Q_OS_WIN)
+ LPVOID lpMsgBuf;
+ FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
+ log(Log::LineType::Error, message + QString(" (last error=%1 %2)").arg(GetLastError()).arg((const char *)(LPCTSTR)lpMsgBuf));
+ LocalFree(lpMsgBuf);
+#endif
+}
diff --git a/src/common/port/serial.h b/src/common/port/serial.h
new file mode 100644
index 0000000..b2911e6
--- /dev/null
+++ b/src/common/port/serial.h
@@ -0,0 +1,113 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * Copyright (C) 2002-2003 Stephen Landamore <stephen@landamore.com> *
+ * *
+ * 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 SERIAL_H
+#define SERIAL_H
+
+#include "common/global/global.h"
+#ifdef Q_OS_UNIX
+# include <termios.h>
+#elif defined(Q_OS_WIN)
+# include <io.h>
+#endif
+#include "port_base.h"
+
+namespace Port
+{
+
+class Serial : public Base
+{
+public:
+ enum Speed { S0 = 0, S50, S75, S110, S134, S150, S200, S300, S600, S1200,
+ S1800, S2400, S4800, S9600, S19200, S38400, S57600, S115200,
+ Nb_Speeds };
+ static const uint SPEED_VALUES[Nb_Speeds];
+ struct SpeedData {
+ bool supported;
+ uint flag;
+ };
+ static const SpeedData SPEED_DATA[Nb_Speeds];
+
+ enum Property { NoProperty = 0, NeedDrain = 1, NeedFlush = 2, NeedBreak = 4,
+ Blocking = 8 };
+ Q_DECLARE_FLAGS(Properties, Property)
+
+ Serial(const QString &device, Properties properties, Log::Base &base);
+ virtual ~Serial() { close(); }
+ virtual Description description() const { return Description(PortType::Serial, _device); }
+
+ static const QStringList &probedDeviceList();
+ static IODirs probe(const QString &device);
+ static bool isAvailable() { return true; }
+
+ enum InputFlag { NoInputFlag = 0, IgnoreBreak = 1, IgnoreParity = 2 };
+ Q_DECLARE_FLAGS(InputFlags, InputFlag)
+ enum ControlFlag { NoControlFlag = 0, ByteSize8 = 1, HardwareFlowControl = 2,
+ EnableReceiver = 4, IgnoreControlLines = 8 };
+ Q_DECLARE_FLAGS(ControlFlags, ControlFlag)
+ bool setMode(InputFlags inputFlags, ControlFlags controlFlags, Speed speed, uint readTimeout); // in ms
+ bool drain(uint timeout);
+ bool flush(uint timeout);
+ bool doBreak(uint duration); // in ms
+ bool setHardwareFlowControl(bool on);
+
+ enum Pin { DCD = 0, RX, TX, DTR, SG, DSR, RTS, CTS, RI, Nb_Pins };
+ struct SPinData {
+ IODir dir;
+ const char *label;
+ };
+ static const SPinData PIN_DATA[Nb_Pins];
+ virtual bool setPinOn(uint pin, bool on, LogicType type);
+ virtual bool readPin(uint pin, LogicType type, bool &value);
+ virtual QValueVector<PinData> pinData(IODir dir) const;
+ virtual bool isGroundPin(uint pin) const;
+ virtual uint groundPin() const { return SG; }
+ virtual IODir ioDir(uint pin) const;
+
+private:
+ QString _device;
+ Properties _properties;
+#if defined(Q_OS_UNIX)
+ typedef int Handle;
+ typedef termios Parameters;
+#elif defined(Q_OS_WIN)
+ typedef HANDLE Handle;
+ struct Parameters {
+ DCB dcb;
+ COMMTIMEOUTS comtmo;
+ };
+#endif
+ Handle _fd;
+ Parameters _oldParameters;
+
+ bool setParameters(const Parameters &parameters);
+ bool getParameters(Parameters &parameters);
+ virtual bool internalOpen();
+ virtual void internalClose();
+ virtual bool internalSend(const char *data, uint size, uint timeout);
+ virtual bool internalReceive(uint size, char *data, uint timeout);
+ virtual void setSystemError(const QString &message);
+ bool internalSetPinOn(Pin pin, bool on);
+ bool internalReadPin(Pin pin, LogicType type, bool &value);
+
+ static const Handle INVALID_HANDLE;
+ static Handle openHandle(const QString &device, IODirs dirs);
+ static void closeHandle(Handle handle);
+ static QStringList *_list;
+ static QStringList deviceList();
+ static void setHardwareFlowControl(Parameters &parameters, bool on);
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(Serial::Properties)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Serial::InputFlags)
+Q_DECLARE_OPERATORS_FOR_FLAGS(Serial::ControlFlags)
+
+} // namespace
+
+#endif
diff --git a/src/common/port/usb_port.cpp b/src/common/port/usb_port.cpp
new file mode 100644
index 0000000..392b483
--- /dev/null
+++ b/src/common/port/usb_port.cpp
@@ -0,0 +1,411 @@
+/***************************************************************************
+ * Copyright (C) 2005 Lorenz Mösenlechner & Matthias Kranz *
+ * <icd2linux@hcilab.org> *
+ * Copyright (C) 2003-2005 Orion Sky Lawlor <olawlor@acm.org> *
+ * Copyright (C) 2005-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 "usb_port.h"
+
+#ifdef HAVE_USB
+# include <usb.h>
+#endif
+#include <qdatetime.h>
+
+#include "common/common/version_data.h"
+#include "common/common/number.h"
+
+//-----------------------------------------------------------------------------
+class Port::USB::Private
+{
+public:
+#ifdef HAVE_USB
+ Private() : _interface(0) {}
+ const usb_interface_descriptor *_interface;
+#endif
+};
+
+bool Port::USB::_initialized = false;
+
+void Port::USB::initialize()
+{
+ if (_initialized) return;
+ _initialized = true;
+#ifdef HAVE_USB
+ usb_init();
+ VersionData vd = VersionData::fromString(LIBUSB_VERSION);
+ QString s = QString("libusb %1").arg(vd.pretty());
+ if ( vd<VersionData(0, 1, 8) ) qWarning("%s: may be too old (you need at least version 0.1.8)", s.latin1());
+#endif
+}
+
+bool Port::USB::isAvailable()
+{
+#ifdef HAVE_USB
+ return true;
+#else
+ return false;
+#endif
+}
+
+usb_bus *Port::USB::getBusses()
+{
+ initialize();
+#ifdef HAVE_USB
+ // refresh libusb structures
+ usb_find_busses();
+ usb_find_devices();
+ return usb_get_busses();
+#else
+ return 0;
+#endif
+}
+
+bool Port::USB::findBulk(const struct usb_device *dev)
+{
+ initialize();
+#ifdef HAVE_USB
+ int configuration = -1, interface = -1, altsetting = -1, bulk_endpoint = -1;
+ // walk through the possible configs, etc.
+ qDebug("This device has %d possible configuration(s).", dev->descriptor.bNumConfigurations);
+ for (int c=0; c<dev->descriptor.bNumConfigurations; c++) {
+ qDebug("Looking at configuration %d...This configuration has %d interfaces.", c, dev->config[c].bNumInterfaces);
+ for(int i=0; i<dev->config[c].bNumInterfaces; i++) {
+ qDebug(" Looking at interface %d...This interface has %d altsettings.", i, dev->config[c].interface[i].num_altsetting);
+ for (int a=0; a < dev->config[c].interface[i].num_altsetting; a++) {
+ qDebug(" Looking at altsetting %d...This altsetting has %d endpoints.", a, dev->config[c].interface[i].altsetting[a].bNumEndpoints);
+ for (int e=0; e < dev->config[c].interface[i].altsetting[a].bNumEndpoints; e++) {
+ QString s;
+ s.sprintf(" Endpoint %d: Address %02xh, attributes %02xh ", e, dev->config[c].interface[i].altsetting[a].endpoint[e].bEndpointAddress, dev->config[c].interface[i].altsetting[a].endpoint[e].bmAttributes);
+ uchar attribs = (dev->config[c].interface[i].altsetting[a].endpoint[e].bmAttributes & 3);
+ switch (attribs) {
+ case 0: s += "(Control) "; break;
+ case 1: s += "(Isochronous) "; break;
+ case 2: s += "(Bulk) ";
+ /* Found the correct configuration, interface etc... it has bulk endpoints! */
+ configuration=c;
+ interface=i;
+ altsetting=a;
+ break;
+ case 3: s += "(Interrupt) "; break;
+ default: s += "ERROR! Got an illegal value in endpoint bmAttributes";
+ }
+ if ( attribs!=0 ) {
+ uchar dir = (dev->config[c].interface[i].altsetting[a].endpoint[e].bEndpointAddress & 0x80);
+ switch (dir) {
+ case 0x00: s += "(Out)";
+ // Do nothing in this case
+ break;
+ case 0x80: s += "(In)";
+ if ((dev->config[c].interface[i].altsetting[a].endpoint[e].bmAttributes & 0x03) == 2) /* Make sure it's a *bulk* endpoint */ {
+ // Found the correct endpoint to use for bulk transfer; use its ADDRESS
+ bulk_endpoint=dev->config[c].interface[i].altsetting[a].endpoint[e].bEndpointAddress;
+ }
+ break;
+ default: s += "ERROR! Got an illegal value in endpoint bEndpointAddress";
+ }
+ }
+ qDebug("%s", s.latin1());
+ }
+ }
+ }
+ }
+ if (bulk_endpoint<0) {
+ qDebug("No valid interface found!");
+ return false;
+ }
+#endif
+ return true;
+}
+
+QStringList Port::USB::probedDeviceList()
+{
+ initialize();
+ QStringList list;
+#ifdef HAVE_USB
+ usb_init(); // needed ?
+ for (usb_bus *bus=getBusses(); bus; bus=bus->next) {
+ for (struct usb_device *dev=bus->devices; dev; dev=dev->next) {
+ if ( dev->descriptor.idVendor==0 ) continue; // controller
+ list.append(QString("Vendor Id: %1 - Product Id: %2")
+ .arg(toLabel(NumberBase::Hex, dev->descriptor.idVendor, 4)).arg(toLabel(NumberBase::Hex, dev->descriptor.idProduct, 4)));
+ }
+ }
+#endif
+ return list;
+}
+
+struct usb_device *Port::USB::findDevice(uint vendorId, uint productId)
+{
+ initialize();
+#ifdef HAVE_USB
+ for (usb_bus *bus=getBusses(); bus; bus=bus->next) {
+ for (struct usb_device *dev=bus->devices; dev; dev=dev->next) {
+ if ( dev->descriptor.idVendor==vendorId && dev->descriptor.idProduct==productId )
+ return dev;
+ }
+ }
+#else
+ Q_UNUSED(vendorId); Q_UNUSED(productId);
+ qDebug("USB support disabled");
+#endif
+ return 0;
+}
+
+//-----------------------------------------------------------------------------
+const char * const Port::USB::ENDPOINT_MODE_NAMES[Nb_EndpointModes] = {
+ "bulk", "interrupt", "control", "isochronous"
+};
+
+Port::USB::USB(Log::Base &base, uint vendorId, uint productId, uint config, uint interface)
+ : Base(base), _vendorId(vendorId), _productId(productId),
+ _config(config), _interface(interface), _handle(0), _device(0)
+{
+ Q_ASSERT( config>=1 );
+ _private = new Private;
+ initialize();
+}
+
+Port::USB::~USB()
+{
+ close();
+ delete _private;
+}
+
+void Port::USB::setSystemError(const QString &message)
+{
+#ifdef HAVE_USB
+ log(Log::LineType::Error, message + QString(" (err=%1).").arg(usb_strerror()));
+#else
+ log(Log::LineType::Error, message);
+#endif
+}
+
+void Port::USB::tryToDetachDriver()
+{
+ // try to detach an already existing driver... (linux only)
+#if defined(LIBUSB_HAS_GET_DRIVER_NP) && LIBUSB_HAS_GET_DRIVER_NP
+ log(Log::DebugLevel::Extra, "find if there is already an installed driver");
+ char dname[256] = "";
+ if ( usb_get_driver_np(_handle, _interface, dname, 255)<0 ) return;
+ log(Log::DebugLevel::Normal, QString(" a driver \"%1\" is already installed...").arg(dname));
+# if defined(LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP) && LIBUSB_HAS_DETACH_KERNEL_DRIVER_NP
+ usb_detach_kernel_driver_np(_handle, _interface);
+ log(Log::DebugLevel::Normal, " try to detach it...");
+ if ( usb_get_driver_np(_handle, _interface, dname, 255)<0 ) return;
+ log(Log::DebugLevel::Normal, " failed to detach it");
+# endif
+#endif
+}
+
+bool Port::USB::internalOpen()
+{
+#ifdef HAVE_USB
+ _device = findDevice(_vendorId, _productId);
+ if ( _device==0 ) {
+ log(Log::LineType::Error, i18n("Could not find USB device (vendor=%1 product=%2).")
+ .arg(toLabel(NumberBase::Hex, _vendorId, 4)).arg(toLabel(NumberBase::Hex, _productId, 4)));
+ return false;
+ }
+ log(Log::DebugLevel::Extra, QString("found USB device as \"%1\" on bus \"%2\"").arg(_device->filename).arg(_device->bus->dirname));
+ _handle = usb_open(_device);
+ if ( _handle==0 ) {
+ setSystemError(i18n("Error opening USB device."));
+ return false;
+ }
+// windows: usb_reset takes about 7-10 seconds to re-enumerate the device...
+// BSD : not implemented in libusb...
+# if !defined(Q_OS_BSD4) && !defined(Q_OS_WIN)
+ if ( usb_reset(_handle)<0 ) {
+ setSystemError(i18n("Error resetting USB device."));
+ return false;
+ }
+# endif
+ usb_close(_handle);
+ _handle = usb_open(_device);
+ if ( _handle==0 ) {
+ setSystemError(i18n("Error opening USB device."));
+ return false;
+ }
+ tryToDetachDriver();
+ uint i = 0;
+ for (; i<_device->descriptor.bNumConfigurations; i++)
+ if ( _config==_device->config[i].bConfigurationValue ) break;
+ if ( i==_device->descriptor.bNumConfigurations ) {
+ uint old = _config;
+ i = 0;
+ _config = _device->config[i].bConfigurationValue;
+ log(Log::LineType::Warning, i18n("Configuration %1 not present: using %2").arg(old).arg(_config));
+ }
+ const usb_config_descriptor &configd = _device->config[i];
+ if ( usb_set_configuration(_handle, _config)<0 ) {
+ setSystemError(i18n("Error setting USB configuration %1.").arg(_config));
+ return false;
+ }
+ for (i=0; i<configd.bNumInterfaces; i++)
+ if ( _interface==configd.interface[i].altsetting[0].bInterfaceNumber ) break;
+ if ( i==configd.bNumInterfaces ) {
+ uint old = _interface;
+ i = 0;
+ _interface = configd.interface[i].altsetting[0].bInterfaceNumber;
+ log(Log::LineType::Warning, i18n("Interface %1 not present: using %2").arg(old).arg(_interface));
+ }
+ _private->_interface = &(configd.interface[i].altsetting[0]);
+ if ( usb_claim_interface(_handle, _interface)<0 ) {
+ setSystemError(i18n("Could not claim USB interface %1").arg(_interface));
+ return false;
+ }
+ log(Log::DebugLevel::Max, QString("alternate setting is %1").arg(_private->_interface->bAlternateSetting));
+ log(Log::DebugLevel::Max, QString("USB bcdDevice: %1").arg(toHexLabel(_device->descriptor.bcdDevice, 4)));
+ return true;
+#else
+ log(Log::LineType::Error, i18n("USB support disabled"));
+ return false;
+#endif
+}
+
+void Port::USB::internalClose()
+{
+ if ( _handle==0 ) return;
+#ifdef HAVE_USB
+ usb_release_interface(_handle, _interface);
+ usb_close(_handle);
+ _private->_interface = 0;
+#endif
+ _device = 0;
+ _handle = 0;
+}
+
+bool Port::USB::sendControlMessage(const ControlMessageData &data)
+{
+ if ( hasError() ) return false;
+#ifdef HAVE_USB
+ QString s = data.bytes;
+ uint length = strlen(data.bytes) / 2;
+ QByteArray ba(length);
+ for (uint i=0; i<length; i++)
+ ba[i] = fromString(NumberBase::Hex, s.mid(2*i, 2), 0);
+ int res = usb_control_msg(_handle, data.type, data.request, data.value, 0, ba.data(), length, 1000); // 1s
+ if ( res<0 ) {
+ setSystemError(i18n("Error sending control message to USB port."));
+ return false;
+ }
+#endif
+ return true;
+}
+
+uint timeout(uint size)
+{
+ return qMax(size*5, uint(1000)); // 5ms per byte or 1s
+}
+
+
+Port::USB::EndpointMode Port::USB::endpointMode(uint ep) const
+{
+#ifdef HAVE_USB
+ uint index = ep & USB_ENDPOINT_ADDRESS_MASK;
+ Q_ASSERT(_private->_interface);
+ const usb_endpoint_descriptor *ued = _private->_interface->endpoint + index;
+ Q_ASSERT(ued);
+ switch (ued->bmAttributes & USB_ENDPOINT_TYPE_MASK) {
+ case USB_ENDPOINT_TYPE_BULK: return Bulk;
+ case USB_ENDPOINT_TYPE_INTERRUPT: return Interrupt;
+ case USB_ENDPOINT_TYPE_ISOCHRONOUS: return Isochronous;
+ case USB_ENDPOINT_TYPE_CONTROL: return Control;
+ default: break;
+ }
+#endif
+ Q_ASSERT(false);
+ return Nb_EndpointModes;
+}
+
+Port::IODir Port::USB::endpointDir(uint ep) const
+{
+#ifdef HAVE_USB
+ switch (ep & USB_ENDPOINT_DIR_MASK) {
+ case USB_ENDPOINT_IN: return In;
+ case USB_ENDPOINT_OUT: return Out;
+ default: break;
+ }
+#endif
+ Q_ASSERT(false);
+ return NoIO;
+}
+
+bool Port::USB::write(uint ep, const char *data, uint size)
+{
+ if ( hasError() ) return false;
+#ifdef HAVE_USB
+ IODir dir = endpointDir(ep);
+ EndpointMode mode = endpointMode(ep);
+ log(Log::DebugLevel::LowLevel, QString("write to endpoint %1 (%2 - %3) %4 chars: \"%5\"")
+ .arg(toHexLabel(ep, 2)).arg(ENDPOINT_MODE_NAMES[mode]).arg(IO_DIR_NAMES[dir]).arg(size).arg(toPrintable(data, size, PrintEscapeAll)));
+ Q_ASSERT( dir==Out );
+ QTime time;
+ time.start();
+ int todo = size;
+ for (;;) {
+ int res = 0;
+ //qDebug("write ep=%i todo=%i/%i", ep, todo, size);
+ if ( mode==Interrupt ) res = usb_interrupt_write(_handle, ep, (char *)data + size - todo, todo, timeout(todo));
+ else res = usb_bulk_write(_handle, ep, (char *)data + size - todo, todo, timeout(todo));
+ //qDebug("res: %i", res);
+ if ( res==todo ) break;
+ if ( uint(time.elapsed())>3000 ) { // 3 s
+ if ( res<0 ) setSystemError(i18n("Error sending data (ep=%1 res=%2)").arg(toHexLabel(ep, 2)).arg(res));
+ else log(Log::LineType::Error, i18n("Timeout: only some data sent (%1/%2 bytes).").arg(size-todo).arg(size));
+ return false;
+ }
+ if ( res==0 ) log(Log::DebugLevel::Normal, i18n("Nothing sent: retrying..."));
+ if ( res>0 ) todo -= res;
+ msleep(100);
+ }
+#else
+ Q_UNUSED(ep); Q_UNUSED(data); Q_UNUSED(size);
+#endif
+ return true;
+}
+
+bool Port::USB::read(uint ep, char *data, uint size, bool *poll)
+{
+ if ( hasError() ) return false;
+#ifdef HAVE_USB
+ IODir dir = endpointDir(ep);
+ EndpointMode mode = endpointMode(ep);
+ log(Log::DebugLevel::LowLevel, QString("read from endpoint %1 (%2 - %3) %4 chars")
+ .arg(toHexLabel(ep, 2)).arg(ENDPOINT_MODE_NAMES[mode]).arg(IO_DIR_NAMES[dir]).arg(size));
+ Q_ASSERT( dir==In );
+ QTime time;
+ time.start();
+ int todo = size;
+ for (;;) {
+ int res = 0;
+ //qDebug("read ep=%i size=%i", ep, todo);
+ if ( mode==Interrupt ) res = usb_interrupt_read(_handle, ep, data + size - todo, todo, timeout(todo));
+ else res = usb_bulk_read(_handle, ep, data + size - todo, todo, timeout(todo));
+ //qDebug("res: %i", res);
+ if ( res==todo ) break;
+ if ( uint(time.elapsed())>3000 ) { // 3 s: seems to help icd2 in some case (?)
+ if ( res<0 ) setSystemError(i18n("Error receiving data (ep=%1 res=%2)").arg(toHexLabel(ep, 2)).arg(res));
+ else log(Log::LineType::Error, i18n("Timeout: only some data received (%1/%2 bytes).").arg(size-todo).arg(size));
+ return false;
+ }
+ if ( res==0 ) {
+ if (poll) {
+ *poll = false;
+ return true;
+ } else log(Log::DebugLevel::Normal, i18n("Nothing received: retrying..."));
+ }
+ if ( res>0 ) todo -= res;
+ msleep(100);
+ }
+ if (poll) *poll = true;
+#else
+ Q_UNUSED(ep); Q_UNUSED(data); Q_UNUSED(size);
+#endif
+ return true;
+}
diff --git a/src/common/port/usb_port.h b/src/common/port/usb_port.h
new file mode 100644
index 0000000..73961cc
--- /dev/null
+++ b/src/common/port/usb_port.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+ * Copyright (C) 2005 Lorenz Mösenlechner & Matthias Kranz *
+ * <icd2linux@hcilab.org> *
+ * 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 USB_PORT_H
+#define USB_PORT_H
+
+#include "port_base.h"
+#if defined(Q_OS_WIN)
+#undef interface
+#endif
+struct usb_dev_handle;
+struct usb_device;
+struct usb_bus;
+
+namespace Port
+{
+
+class USB : public Base
+{
+public:
+ USB(Log::Base &base, uint vendorId, uint productId, uint config, uint interface);
+ virtual ~USB();
+ virtual Description description() const { return Description(PortType::USB, QString::null); }
+
+ static struct usb_device *findDevice(uint vendorId, uint productId);
+ static bool isAvailable();
+ static QStringList probedDeviceList();
+
+ struct ControlMessageData {
+ int type, request, value;
+ const char *bytes;
+ };
+ bool sendControlMessage(const ControlMessageData &data);
+ enum EndpointMode { Bulk = 0, Interrupt, Control, Isochronous, Nb_EndpointModes };
+ static const char * const ENDPOINT_MODE_NAMES[Nb_EndpointModes];
+ EndpointMode endpointMode(uint ep) const;
+ IODir endpointDir(uint ep) const;
+
+protected:
+ bool write(uint endPoint, const char *data, uint size);
+ bool read(uint endPoint, char *data, uint size, bool *poll = 0);
+
+private:
+ class Private;
+ Private *_private;
+ uint _vendorId, _productId, _config, _interface;
+ usb_dev_handle *_handle;
+ usb_device *_device;
+
+ virtual bool internalOpen();
+ virtual void internalClose();
+ virtual void setSystemError(const QString &message);
+ void tryToDetachDriver();
+
+ static bool _initialized;
+ static void initialize();
+ static usb_bus *getBusses();
+ static bool findBulk(const struct usb_device *device);
+};
+
+} // namespace
+
+#endif