summaryrefslogtreecommitdiffstats
path: root/src/tools/list
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/list')
-rw-r--r--src/tools/list/Makefile.am7
-rw-r--r--src/tools/list/compile_config.cpp189
-rw-r--r--src/tools/list/compile_config.h84
-rw-r--r--src/tools/list/compile_manager.cpp292
-rw-r--r--src/tools/list/compile_manager.h74
-rw-r--r--src/tools/list/compile_process.cpp376
-rw-r--r--src/tools/list/compile_process.h179
-rw-r--r--src/tools/list/device_info.cpp63
-rw-r--r--src/tools/list/device_info.h22
-rw-r--r--src/tools/list/tool_list.cpp69
-rw-r--r--src/tools/list/tool_list.h28
-rw-r--r--src/tools/list/tools_config_widget.cpp144
-rw-r--r--src/tools/list/tools_config_widget.h60
13 files changed, 1587 insertions, 0 deletions
diff --git a/src/tools/list/Makefile.am b/src/tools/list/Makefile.am
new file mode 100644
index 0000000..9d62533
--- /dev/null
+++ b/src/tools/list/Makefile.am
@@ -0,0 +1,7 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libtoollist.la
+libtoollist_la_LDFLAGS = $(all_libraries)
+libtoollist_la_SOURCES = tool_list.cpp tools_config_widget.cpp \
+ compile_config.cpp device_info.cpp compile_manager.cpp compile_process.cpp
diff --git a/src/tools/list/compile_config.cpp b/src/tools/list/compile_config.cpp
new file mode 100644
index 0000000..5ec8dfc
--- /dev/null
+++ b/src/tools/list/compile_config.cpp
@@ -0,0 +1,189 @@
+/***************************************************************************
+ * 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 "compile_config.h"
+
+#include "common/global/generic_config.h"
+#include "devices/list/device_list.h"
+#include "libgui/project.h"
+#include "tool_list.h"
+
+//----------------------------------------------------------------------------
+PURL::Directory Compile::Config::directory(const Tool::Group &group, DirectoryType type)
+{
+ QString def;
+ if ( type!=DirectoryType::Executable )
+ def = group.autodetectDirectory(type, directory(group, DirectoryType::Executable), withWine(group)).path();
+ return PURL::Directory(value(group.name(), QString::null, type.key() + QString("_path"), def));
+}
+void Compile::Config::setDirectory(const Tool::Group &group, DirectoryType type, const PURL::Directory &dir)
+{
+ setValue(group.name(), QString::null, type.key() + QString("_path"), dir.path());
+ if ( type==DirectoryType::Executable ) const_cast<Tool::Group &>(group).init();
+}
+
+bool Compile::Config::withWine(const Tool::Group &group)
+{
+ QString def = (group.preferedExecutableType()==Tool::ExecutableType::Unix ? "false" : "true");
+ return ( value(group.name(), QString::null, "with_wine", def)=="true" );
+}
+void Compile::Config::setWithWine(const Tool::Group &group, bool withWine)
+{
+ setValue(group.name(), QString::null, "with_wine", withWine ? "true" : "false");
+ const_cast<Tool::Group &>(group).init();
+}
+
+Tool::OutputExecutableType Compile::Config::outputExecutableType(const Tool::Group &group)
+{
+ QString s = value(group.name(), QString::null, "output_type", Tool::OutputExecutableType(Tool::OutputExecutableType::Coff).key());
+ return Tool::OutputExecutableType::fromKey(s);
+}
+void Compile::Config::setOutputExecutableType(const Tool::Group &group, Tool::OutputExecutableType type)
+{
+ setValue(group.name(), QString::null, "output_type", type.key());
+ const_cast<Tool::Group &>(group).init();
+}
+
+QString Compile::Config::value(const QString &group, const QString &subGroup, const QString &key, const QString &defaultValue)
+{
+ QString grp = (subGroup.isEmpty() ? group : group + '-' + subGroup);
+ GenericConfig gc(grp);
+ return gc.readEntry(key, defaultValue);
+}
+void Compile::Config::setValue(const QString &group, const QString &subGroup, const QString &key, const QString &value)
+{
+ QString grp = (subGroup.isEmpty() ? group : group + '-' + subGroup);
+ GenericConfig gc(grp);
+ gc.writeEntry(key, value);
+}
+QStringList Compile::Config::listValues(const QString &group, const QString &subGroup, const QString &key, const QStringList &defaultValues)
+{
+ QString grp = (subGroup.isEmpty() ? group : group + '-' + subGroup);
+ GenericConfig gc(grp);
+ return gc.readListEntry(key, defaultValues);
+}
+void Compile::Config::setListValues(const QString &group, const QString &subGroup, const QString &key, const QStringList &values)
+{
+ QString grp = (subGroup.isEmpty() ? group : group + '-' + subGroup);
+ GenericConfig gc(grp);
+ gc.writeEntry(key, values);
+}
+
+QStringList Compile::Config::includeDirs(Tool::Category category, const QString &prefix, const QString &suffix, const QString &separator) const
+{
+ QStringList list;
+ QStringList raw = rawIncludeDirs(category);
+ for (uint i=0; i<raw.size(); i++) {
+ if ( separator.isEmpty() ) list.append(prefix + raw[i] + suffix);
+ else if ( i==0 ) list.append(prefix + raw[i]);
+ else list[0] += separator + raw[i];
+ }
+ if ( !separator.isEmpty() && list.count()!=0 ) list[0] += suffix;
+ return list;
+}
+
+HexBuffer::Format Compile::Config::hexFormat() const
+{
+ QString s = value(Tool::Category::Linker, "format", HexBuffer::FORMATS[HexBuffer::IHX32]);
+ for (uint i=0; i<HexBuffer::Nb_Formats; i++)
+ if ( s==HexBuffer::FORMATS[i] ) return HexBuffer::Format(i);
+ return HexBuffer::Nb_Formats;
+}
+void Compile::Config::setHexFormat(HexBuffer::Format f)
+{
+ QString s = (f==HexBuffer::Nb_Formats ? 0 : HexBuffer::FORMATS[f]);
+ setValue(Tool::Category::Linker, "format", s);
+}
+
+QString Compile::Config::device(const Project *project)
+{
+ QString device = globalValue(project, "device", QString::null);
+ return Device::lister().checkName(device);
+}
+
+const Tool::Group &Compile::Config::toolGroup(const Project *project)
+{
+ QString s = globalValue(project, "tool", QString::null);
+ const Tool::Group *group = Tool::lister().group(s);
+ if ( group==0 ) return *Tool::lister().begin().data();
+ return *group;
+}
+
+QStringList Compile::Config::customOptions(Tool::Category category) const
+{
+ return QStringList::split(' ', rawCustomOptions(category));
+}
+
+QStringList Compile::Config::customLibraries(Tool::Category category) const
+{
+ return QStringList::split(' ', rawCustomLibraries(category));
+}
+
+void Compile::Config::setValue(Tool::Category category, const QString &key, const QString &value)
+{
+ Q_ASSERT( category!=Tool::Category::Nb_Types );
+ Q_ASSERT( _project || _group );
+ if (_project) _project->setValue(category.key(), key, value);
+ else Config::setValue(_group->name(), category.key(), key, value);
+}
+QString Compile::Config::value(Tool::Category category, const QString &key, const QString &defaultValue) const
+{
+ Q_ASSERT( category!=Tool::Category::Nb_Types );
+ Q_ASSERT( _project || _group );
+ if (_project) return _project->value(category.key(), key, defaultValue);
+ return Config::value(_group->name(), category.key(), key, defaultValue);
+}
+void Compile::Config::setListValues(Tool::Category category, const QString &key, const QStringList &values)
+{
+ Q_ASSERT( category!=Tool::Category::Nb_Types );
+ Q_ASSERT( _project || _group );
+ if (_project) _project->setListValues(category.key(), key, values);
+ else Config::setListValues(_group->name(), category.key(), key, values);
+}
+QStringList Compile::Config::listValues(Tool::Category category, const QString &key, const QStringList &defaultValues) const
+{
+ Q_ASSERT( category!=Tool::Category::Nb_Types );
+ Q_ASSERT( _project || _group );
+ if (_project) return _project->listValues(category.key(), key, defaultValues);
+ return Config::listValues(_group->name(), category.key(), key, defaultValues);
+}
+bool Compile::Config::boolValue(Tool::Category category, const QString &key, bool defaultValue) const
+{
+ QString s = value(category, key, QString::null);
+ if ( s.isNull() ) return defaultValue;
+ return !( s=="false" || s=="0" );
+}
+uint Compile::Config::uintValue(Tool::Category category, const QString &key, uint defaultValue) const
+{
+ bool ok;
+ uint i = value(category, key, QString::null).toUInt(&ok);
+ if ( !ok ) return defaultValue;
+ return i;
+}
+
+QString Compile::Config::globalValue(const Project *project, const QString &key, const QString &defaultValue)
+{
+ if (project) return project->value("general", key, defaultValue);
+ return Config::value("general", QString::null, key, defaultValue);
+}
+void Compile::Config::setGlobalValue(Project *project, const QString &key, const QString &value)
+{
+ if (project) project->setValue("general", key, value);
+ else Config::setValue("general", QString::null, key, value);
+}
+
+QStringList Compile::Config::globalListValues(const Project *project, const QString &key, const QStringList &defaultValues)
+{
+ if (project) return project->listValues("general", key, defaultValues);
+ return Config::listValues("general", QString::null, key, defaultValues);
+}
+void Compile::Config::setGlobalListValues(Project *project, const QString &key, const QStringList &values)
+{
+ if (project) project->setListValues("general", key, values);
+ else Config::setListValues("general", QString::null, key, values);
+}
diff --git a/src/tools/list/compile_config.h b/src/tools/list/compile_config.h
new file mode 100644
index 0000000..13beff4
--- /dev/null
+++ b/src/tools/list/compile_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 COMPILE_CONFIG_H
+#define COMPILE_CONFIG_H
+
+#include "common/global/purl.h"
+#include "devices/base/hex_buffer.h"
+#include "tools/base/tool_group.h"
+class Project;
+
+//----------------------------------------------------------------------------
+namespace Compile
+{
+class Config
+{
+public:
+ Config(Project *project) : _group(0), _project(project) {}
+
+ bool hasCustomArguments(Tool::Category category) const { return boolValue(category, "has_custom_arguments", false); }
+ void setHasCustomArguments(Tool::Category category, bool custom) { setValue(category, "has_custom_arguments", custom); }
+ QStringList customArguments(Tool::Category category) const { return listValues(category, "custom_arguments", QStringList()); }
+ void setCustomArguments(Tool::Category category, const QStringList &args) { return setListValues(category, "custom_arguments", args); }
+ QStringList rawIncludeDirs(Tool::Category category) const { return listValues(category, "includes", "$(SRCPATH)"); }
+ QStringList includeDirs(Tool::Category category, const QString &prefix, const QString &suffix = QString::null, const QString &separator = QString::null) const;
+ void setRawIncludeDirs(Tool::Category category, const QStringList &dirs) { setListValues(category, "includes", dirs); }
+ QString rawCustomOptions(Tool::Category category) const { return value(category, "custom_options", QString::null); }
+ QStringList customOptions(Tool::Category category) const;
+ void setRawCustomOptions(Tool::Category category, const QString &value) { setValue(category, "custom_options", value); }
+ QString rawCustomLibraries(Tool::Category category) const { return value(category, "custom_libraries", QString::null); }
+ QStringList customLibraries(Tool::Category category) const;
+ void setRawCustomLibraries(Tool::Category category, const QString &value) { setValue(category, "custom_libraries", value); }
+ uint warningLevel(Tool::Category category) const { return uintValue(category, "warning_level", 0); }
+ void setWarningLevel(Tool::Category category, uint level) { setValue(category, "warning_level", QString::number(level)); }
+ HexBuffer::Format hexFormat() const;
+ void setHexFormat(HexBuffer::Format format);
+
+ static const Tool::Group &toolGroup(const Project *project);
+ static void setToolGroup(Project *project, const Tool::Group &group) { setGlobalValue(project, "tool", group.name()); }
+ static QString device(const Project *project);
+ static void setDevice(Project *project, const QString &device) { setGlobalValue(project, "device", device); }
+ static QStringList customCommands(Project *project) { return globalListValues(project, "custom_shell_commands", QStringList()); }
+ static void setCustomCommands(Project *project, const QStringList &commands) { setGlobalListValues(project, "custom_shell_commands", commands); }
+ static QString globalValue(const Project *project, const QString &key, const QString &defaultValue);
+ static void setGlobalValue(Project *project, const QString &key, const QString &value);
+ static QStringList globalListValues(const Project *project, const QString &key, const QStringList &defaultValues);
+ static void setGlobalListValues(Project *project, const QString &key, const QStringList &value);
+
+ static PURL::Directory directory(const Tool::Group &group, DirectoryType type);
+ static void setDirectory(const Tool::Group &group, DirectoryType type, const PURL::Directory &dir);
+ static bool withWine(const Tool::Group &group);
+ static void setWithWine(const Tool::Group &group, bool withWine);
+ static Tool::OutputExecutableType outputExecutableType(const Tool::Group &group);
+ static void setOutputExecutableType(const Tool::Group &group, Tool::OutputExecutableType type);
+
+protected:
+ const Tool::Group *_group;
+ Project *_project;
+
+ void setValue(Tool::Category category, const QString &key, const QString &value);
+ QString value(Tool::Category category, const QString &key, const QString &defaultValue) const;
+ void setListValues(Tool::Category category, const QString &key, const QStringList &values);
+ QStringList listValues(Tool::Category category, const QString &key, const QStringList &defaultValues) const;
+ void setValue(Tool::Category category, const QString &key, bool value) { setValue(category, key, QString(value ? "true" : "false")); }
+ bool boolValue(Tool::Category category, const QString &key, bool defaultValue) const;
+ void setValue(Tool::Category category, const QString &key, uint value) { setValue(category, key, QString::number(value)); }
+ uint uintValue(Tool::Category category, const QString &key, uint defaultValue) const;
+
+ static QString value(const QString &group, const QString &subGroup, const QString &key, const QString &defaultValue);
+ static void setValue(const QString &group, const QString &subGroup, const QString &key, const QString &value);
+ static QStringList listValues(const QString &group, const QString &subGroup, const QString &key, const QStringList &defaultValues);
+ static void setListValues(const QString &group, const QString &subGroup, const QString &key, const QStringList &values);
+
+ friend class Tool::Group;
+};
+
+} // namespace
+
+#endif
diff --git a/src/tools/list/compile_manager.cpp b/src/tools/list/compile_manager.cpp
new file mode 100644
index 0000000..00a4182
--- /dev/null
+++ b/src/tools/list/compile_manager.cpp
@@ -0,0 +1,292 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 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 "compile_manager.h"
+
+#include <qtimer.h>
+
+#include "libgui/project.h"
+#include "common/gui/misc_gui.h"
+#include "compile_config.h"
+
+Compile::Manager::Manager(QObject *parent)
+ : QObject(parent, "compile_manager"), _base(0)
+{}
+
+void Compile::Manager::cleanFile(const PURL::Url &url)
+{
+ setupFile(Clean, TodoItem(url, false));
+}
+
+bool Compile::Manager::compileFile(const TodoItem &item)
+{
+ _label = i18n("Compiling file...");
+ return setupFile(Clean | (Main::project() ? CompileOnly : Build), item);
+}
+
+bool Compile::Manager::setupFile(Operations op, const TodoItem &item)
+{
+ Log::Base::clear();
+ clearAll();
+ _operations = op;
+ _type = NormalLinking;
+ _todo.append(item);
+ _action = Compiling;
+ _wholeProject = false;
+ QTimer::singleShot(0, this, SLOT(start()));
+ return true;
+}
+
+void Compile::Manager::cleanProject(LinkType type)
+{
+ setupProject(Clean, type);
+}
+
+bool Compile::Manager::buildProject(LinkType type)
+{
+ _label = i18n("Building project...");
+ return setupProject(Clean | Build, type);
+}
+
+bool Compile::Manager::setupProject(Operations op, LinkType type)
+{
+ Log::Base::clear();
+ clearAll();
+ _operations = op;
+ _type = type;
+ PURL::UrlList files = Main::project()->absoluteFiles();
+ if ( files.count()==0 ) {
+ MessageBox::sorry(i18n("Cannot build empty project."), Log::Show);
+ return false;
+ }
+ PURL::UrlList::const_iterator it;
+ for (it=files.begin(); it!=files.end(); ++it)
+ if ( (*it).data().group==PURL::Source ) _todo.append(TodoItem(*it, false));
+ if ( _todo.count()>1 && Main::toolGroup().compileType()==Tool::SingleFile ) {
+ MessageBox::sorry(i18n("The selected toolchain only supports single-file project."), Log::Show);
+ return false;
+ }
+ _action = Compiling;
+ _wholeProject = true;
+ QTimer::singleShot(0, this, SLOT(start()));
+ return true;
+}
+
+void Compile::Manager::kill()
+{
+ if ( clearAll() ) Log::Base::log(Log::LineType::Error, i18n("*** Aborted ***"), Log::Delayed);
+ emit failure();
+}
+
+bool Compile::Manager::clearAll()
+{
+ bool running = ( _base!=0 );
+ delete _base;
+ _base = 0;
+ _todo.clear();
+ return running;
+}
+
+void Compile::Manager::setup(Tool::Category category)
+{
+ delete _base;
+ Compile::Data data(category, _items, Main::device(), Main::project(), _type);
+ _base = Main::toolGroup().createCompileProcess(data, this);
+}
+
+bool Compile::Manager::setupCompile()
+{
+ PURL::FileType type = Main::toolGroup().implementationType(PURL::ToolType::Compiler);
+ for (uint i=0; i<_items.count(); i++) {
+ if ( _items[i].url.fileType()!=type ) {
+ if ( _operations!=Clean ) {
+ QString e = PURL::extensions(type);
+ MessageBox::detailedSorry(i18n("The selected toolchain (%1) cannot compile file. It only supports files with extensions: %2")
+ .arg(Main::toolGroup().label()).arg(e), i18n("File: %1").arg(_items[i].url.pretty()), Log::Show);
+ Log::Base::log(Log::LineType::Error, i18n("*** Aborted ***"), Log::Delayed);
+ processFailed();
+ }
+ return false;
+ }
+ }
+ if ( !compileOnly() && Main::toolGroup().needs(Main::project(), Tool::Category::Assembler) ) {
+ PURL::FileType type = Main::toolGroup().implementationType(PURL::ToolType::Assembler);
+ for (uint i=0; i<_items.count(); i++)
+ _todo.append(TodoItem(_items[i].url.toFileType(type), true));
+ }
+ setup(Tool::Category::Compiler);
+ return true;
+}
+
+bool Compile::Manager::setupAssemble()
+{
+ PURL::FileType type = Main::toolGroup().implementationType(PURL::ToolType::Assembler);
+ for (uint i=0; i<_items.count(); i++) {
+ if ( _items[i].url.fileType()!=type ) {
+ if ( _operations!=Clean ) {
+ if ( type==PURL::Nb_FileTypes ) type = Main::toolGroup().implementationType(PURL::ToolType::Compiler);
+ QString e = PURL::extensions(type);
+ MessageBox::detailedSorry(i18n("The selected toolchain (%1) cannot assemble file. It only supports files with extensions: %2")
+ .arg(Main::toolGroup().label()).arg(e), i18n("File: %1").arg(_items[i].url.pretty()), Log::Show);
+ Log::Base::log(Log::LineType::Error, i18n("*** Aborted ***"), Log::Delayed);
+ processFailed();
+ }
+ return false;
+ }
+ }
+ setup(Tool::Category::Assembler);
+ return true;
+}
+
+bool Compile::Manager::setupLink()
+{
+ _action = Linking;
+ Tool::Category category = (Main::project() && Main::project()->outputType()==Tool::OutputType::Library ? Tool::Category::Librarian : Tool::Category::Linker);
+ if ( !Main::toolGroup().needs(Main::project(), category) ) {
+ start();
+ return false;
+ }
+ setup(category);
+ return true;
+}
+
+bool Compile::Manager::setupBinToHex()
+{
+ _action = BinToHex;
+ if ( !Main::toolGroup().needs(Main::project(), Tool::Category::BinToHex) ) {
+ start();
+ return false;
+ }
+ setup(Tool::Category::BinToHex);
+ return true;
+}
+
+bool Compile::Manager::prepareAction()
+{
+ switch (_action) {
+ case Compiling:
+ if ( _todo.count()!=0 ) {
+ _items.clear();
+ if ( Main::toolGroup().compileType()==Tool::AllFiles ) {
+ _items = _todo;
+ _todo.clear();
+ } else {
+ _items.append(_todo[0]);
+ _todo.remove(_todo.begin());
+ }
+ PURL::SourceFamily family = _items[0].url.data().sourceFamily;
+ if ( family.data().toolType==PURL::ToolType::Compiler && Main::toolGroup().base(Tool::Category::Compiler) )
+ return setupCompile();
+ return setupAssemble();
+ }
+ if ( !compileOnly() ) return setupLink();
+ break;
+ case Linking: return setupBinToHex();
+ case BinToHex: break;
+ }
+ if ( !(_operations & Clean) ) {
+ Log::Base::log(Log::LineType::Information, i18n("*** Success ***"), Log::Delayed);
+ emit success();
+ } else if ( _operations!=Clean ) {
+ _operations &= ~Clean;
+ if (_wholeProject) setupProject(_operations, _type);
+ else setupFile(_operations, _items[0]);
+ }
+ return false;
+}
+
+void Compile::Manager::start()
+{
+ if ( Main::toolGroup().isCustom() ) {
+ executeCustomCommands();
+ return;
+ }
+ delete _base;
+ _base = 0;
+ if ( !prepareAction() ) return;
+ if ( !_base->check() ) {
+ processFailed();
+ return;
+ }
+ if ( _operations & Clean ) {
+ _base->files(0).onlyExistingFiles().cleanGenerated();
+ QTimer::singleShot(0, this, SLOT(start()));
+ return;
+ }
+ if ( !_base->start() ) {
+ Log::Base::log(Log::LineType::Error, i18n("Failed to execute command: check toolchain configuration."), Log::Delayed);
+ processFailed();
+ }
+}
+
+void Compile::Manager::log(Log::LineType type, const QString &message, const QString &filepath, uint line)
+{
+ if ( type==Log::LineType::Error ) setError(message);
+ static_cast<LogWidget *>(view())->appendLine(type, message, filepath, line);
+}
+
+void Compile::Manager::log(Log::DebugLevel level, const QString &message, const QString &filepath, uint line)
+{
+ static_cast<LogWidget *>(view())->appendLine(level, message, filepath, line);
+}
+
+void Compile::Manager::processDone()
+{
+ if ( hasError() ) {
+ processFailed();
+ return;
+ }
+ if ( Main::toolGroup().isCustom() ) {
+ _customCommandIndex++;
+ startCustomCommand();
+ } else {
+ FileData::List list = _base->files(0).onlyExistingFiles();
+ FileData::List::iterator it;
+ for (it=list.begin(); it!=list.end(); ++it) emit updateFile(*it);
+ QTimer::singleShot(0, this, SLOT(start()));
+ }
+}
+
+void Compile::Manager::processFailed()
+{
+ clearAll();
+ emit failure();
+}
+
+void Compile::Manager::startCustomCommand()
+{
+ delete _base;
+ _base = 0;
+ QStringList commands = Compile::Config::customCommands(Main::project());
+ if ( _customCommandIndex==commands.count() ) {
+ Log::Base::log(Log::LineType::Information, i18n("*** Success ***"), Log::Delayed);
+ emit success();
+ return;
+ }
+ QString command = commands[_customCommandIndex];
+ _base = new CustomProcess(command);
+ Compile::Data data(Tool::Category::Nb_Types, _todo, Main::device(), Main::project(), _type);
+ _base->init(data, this);
+ if ( !_base->start() ) {
+ Log::Base::log(Log::LineType::Error, i18n("Failed to execute custom command #%1.").arg(_customCommandIndex+1), Log::Delayed);
+ processFailed();
+ }
+}
+
+void Compile::Manager::executeCustomCommands()
+{
+ _customCommandIndex = 0;
+ if ( Compile::Config::customCommands(Main::project()).isEmpty() ) {
+ MessageBox::sorry(i18n("No custom commands specified."), Log::Show);
+ emit failure();
+ return;
+ }
+ log(Log::LineType::Information, i18n("Executing custom commands..."));
+ startCustomCommand();
+}
diff --git a/src/tools/list/compile_manager.h b/src/tools/list/compile_manager.h
new file mode 100644
index 0000000..6f617b4
--- /dev/null
+++ b/src/tools/list/compile_manager.h
@@ -0,0 +1,74 @@
+/***************************************************************************
+ * 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 COMPILE_MANAGER_H
+#define COMPILE_MANAGER_H
+
+#include "compile_process.h"
+
+namespace Compile
+{
+
+class Manager : public QObject, public Log::Base
+{
+Q_OBJECT
+public:
+ enum Operation { NoOperation = 0, Clean = 1, CompileOnly = 2, Build = 4 };
+ Q_DECLARE_FLAGS(Operations, Operation)
+
+public:
+ Manager(QObject *parent);
+ QString label() const { return _label; }
+ bool compileFile(const TodoItem &item);
+ void cleanFile(const PURL::Url &url);
+ bool buildProject(LinkType type);
+ void cleanProject(LinkType type);
+ void kill();
+ bool compileOnly() const { return (_operations & CompileOnly); }
+ void processDone();
+ void processFailed();
+ void log(Log::LineType type, const QString &message, const QString &filepath = QString::null, uint line = 0);
+ void log(Log::DebugLevel debug, const QString &message, const QString &filepath = QString::null, uint line = 0);
+
+signals:
+ void success();
+ void failure();
+ void updateFile(const Compile::FileData &fdata);
+
+private slots:
+ void start();
+
+private:
+ Operations _operations;
+ enum Action { Compiling, Linking, BinToHex };
+ Action _action;
+ QValueList<TodoItem> _todo, _items;
+ BaseProcess *_base;
+ QString _label;
+ LinkType _type;
+ bool _wholeProject;
+ uint _customCommandIndex;
+
+ bool startProject();
+ bool clearAll();
+ bool setupFile(Operations operations, const TodoItem &item);
+ bool setupProject(Operations operations, LinkType type);
+ void setup(Tool::Category category);
+ bool setupCompile();
+ bool setupAssemble();
+ bool setupLink();
+ bool setupBinToHex();
+ bool prepareAction();
+ void startCustomCommand();
+ void executeCustomCommands();
+};
+Q_DECLARE_OPERATORS_FOR_FLAGS(Manager::Operations)
+
+} // namespace
+
+#endif
diff --git a/src/tools/list/compile_process.cpp b/src/tools/list/compile_process.cpp
new file mode 100644
index 0000000..4f251bc
--- /dev/null
+++ b/src/tools/list/compile_process.cpp
@@ -0,0 +1,376 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 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 "compile_process.h"
+
+#include <qtimer.h>
+#include <qregexp.h>
+
+#include "devices/list/device_list.h"
+#include "common/global/process.h"
+#include "common/gui/misc_gui.h"
+#include "libgui/text_editor.h"
+#include "libgui/editor_manager.h"
+#include "libgui/project.h"
+#include "compile_config.h"
+#include "compile_manager.h"
+
+//-----------------------------------------------------------------------------
+const Compile::ArgumentData Compile::ARGUMENT_DATA[] = {
+ { "$(SRCPATH)", I18N_NOOP("Replaced by the source directory.") },
+ { "$LKR(xxx)", I18N_NOOP("Replaced by \"xxx\" when there is a custom linker script.") },
+ { "$WINE(xxx)", I18N_NOOP("Replaced by \"xxx\" when \"wine\" is used.") },
+ { "$NO_AUTO_DEVICE(xxx)", I18N_NOOP("Replaced by \"xxx\" when the device name is specified.") },
+ { "%OBJS", I18N_NOOP("Replaced by the list of additionnal objects.") },
+ { "%LIBS", I18N_NOOP("Replaced by the list of additionnal libraries.") },
+ { "%O", I18N_NOOP("Replaced by the output filename.") },
+ { "%PROJECT", I18N_NOOP("Replaced by the project name.") },
+ { "%COFF", I18N_NOOP("Replaced by the COFF filename.") },
+ { "%MAP", I18N_NOOP("Replaced by the map filename.") },
+ { "%SYM", I18N_NOOP("Replaced by the symbol filename.") },
+ { "%LIST", I18N_NOOP("Replaced by the list filename.") },
+ { "%DEVICE", I18N_NOOP("Replaced by the device name.") },
+ { "%FAMILY", I18N_NOOP("Replaced by the device family name (when needed).") },
+ { "%I", I18N_NOOP("Replaced by the relative input filepath(s).") },
+ { "%OBJECT", I18N_NOOP("Replaced by the object file name.") },
+ { "%LKR_PATH", I18N_NOOP("Replaced by the linker script path.") },
+ { "%LKR_NAME", I18N_NOOP("Replaced by the linker script basename.") },
+ { "%LKR", I18N_NOOP("Replaced by the linker script filename.") },
+ { "%SEP", I18N_NOOP("Replaced by a separation into two arguments.") },
+ { 0, 0 }
+};
+
+//-----------------------------------------------------------------------------
+Compile::FileData::List Compile::FileData::List::onlyExistingFiles() const
+{
+ List list;
+ List::const_iterator it;
+ for (it=begin(); it!=end(); ++it) {
+ FileData data = *it;
+ if ( PURL::findExistingUrl(data.url) ) list.append(data);
+ }
+ return list;
+}
+
+void Compile::FileData::List::cleanGenerated() const
+{
+ Log::StringView sview;
+ List::const_iterator it;
+ for (it=begin(); it!=end(); ++it)
+ if ( (*it).actions & Generated ) (*it).url.del(sview);
+}
+
+//-----------------------------------------------------------------------------
+Compile::LogWidget::LogWidget(QWidget *parent)
+ : Log::Widget(parent, "compile_log")
+{
+ connect(this, SIGNAL(clicked(int, int)), SLOT(lineClicked(int)));
+}
+
+void Compile::LogWidget::clear()
+{
+ Log::Widget::clear();
+ _map.clear();
+}
+
+void Compile::LogWidget::appendLine(Log::LineType type, const QString &message, const QString &filepath, uint line)
+{
+ log(type, message, Log::Delayed);
+ if ( !filepath.isEmpty() ) _map[paragraphs()-1] = Data(filepath, line);
+}
+
+void Compile::LogWidget::appendLine(Log::DebugLevel level, const QString &message, const QString &filepath, uint line)
+{
+ log(level, message, Log::Delayed);
+ if ( !filepath.isEmpty() ) _map[paragraphs()-1] = Data(filepath, line);
+}
+
+void Compile::LogWidget::lineClicked(int line)
+{
+ if ( !_map.contains(line) ) return;
+ PURL::Url url = PURL::Url::fromPathOrUrl(_map[line].filepath);
+ TextEditor *e = ::qt_cast<TextEditor *>(Main::editorManager().openEditor(url));
+ if ( e==0 ) return;
+ e->setCursor(_map[line].line, 0);
+}
+
+//-----------------------------------------------------------------------------
+Compile::BaseProcess::BaseProcess()
+ : QObject(0, "compile_process"), _manager(0), _process(0)
+{}
+
+void Compile::BaseProcess::init(const Data &data, Manager *manager)
+{
+ _data = data;
+ _manager = manager;
+}
+
+PURL::Directory Compile::BaseProcess::directory(uint i) const
+{
+ if (_data.project) return _data.project->directory();
+ Q_ASSERT( i<_data.items.count() );
+ return _data.items[i].url.directory();
+}
+
+bool Compile::BaseProcess::start()
+{
+ _stdout = QString::null;
+ _stderr = QString::null;
+ delete _process;
+ _process = new ::Process::LineSignal;
+ connect(_process, SIGNAL(done(int)), SLOT(done(int)));
+ connect(_process, SIGNAL(timeout()), SLOT(timeout()));
+ connect(_process, SIGNAL(logStdoutLine(const QString &)), SLOT(logStdoutLine(const QString &)));
+ connect(_process, SIGNAL(logStderrLine(const QString &)), SLOT(logStderrLine(const QString &)));
+ _process->setWorkingDirectory(directory().path());
+ setupProcess();
+ _manager->log(Log::LineType::Command, _process->arguments().join(" "));
+ return _process->start(0); // no timeout
+}
+
+void Compile::BaseProcess::done(int code)
+{
+ if ( code!=0 ) {
+ _manager->log(Log::LineType::Error, i18n("*** Exited with status: %1 ***").arg(code));
+ _manager->processFailed();
+ } else if ( _manager->hasError() ) {
+ _manager->log(Log::LineType::Error, i18n("*** Error ***"));
+ _manager->processFailed();
+ } else _manager->processDone();
+}
+
+void Compile::BaseProcess::timeout()
+{
+ _manager->log(Log::LineType::Error, i18n("*** Timeout ***"));
+ _manager->processFailed();
+}
+
+//-----------------------------------------------------------------------------
+void Compile::Process::init(const Data &data, Manager *manager)
+{
+ BaseProcess::init(data, manager);
+ _config = group().createConfig(const_cast<Project *>(data.project));
+}
+
+Compile::Process::~Process()
+{
+ delete _config;
+}
+
+bool Compile::Process::check() const
+{
+ return group().check(_data.device, _manager);
+}
+
+PURL::Url Compile::Process::url(PURL::FileType type, uint i) const
+{
+ PURL::Url url;
+ if ( _data.project && (type==PURL::Hex || _data.category==Tool::Category::Linker || _data.category==Tool::Category::BinToHex) )
+ url = _data.project->url();
+ else if ( _data.project && (type==PURL::Library || _data.category==Tool::Category::Librarian) )
+ return _data.project->url().toExtension(libraryExtension());
+ else {
+ Q_ASSERT( i<_data.items.count() );
+ url = _data.items[i].url;
+ }
+ if ( type==PURL::Nb_FileTypes ) return url;
+ return url.toFileType(type);
+}
+
+QString Compile::Process::filepath(PURL::FileType type, uint i) const
+{
+ return url(type, i).relativeTo(directory(), Compile::Config::withWine(group()) ? PURL::WindowsSeparator : PURL::UnixSeparator);
+}
+
+QString Compile::Process::outputFilepath() const
+{
+ if ( _data.category==Tool::Category::Librarian ) return filepath(PURL::Library);
+ return filepath(PURL::Hex);
+}
+
+Compile::FileData Compile::Process::fileData(PURL::FileType type, FileActions actions) const
+{
+ return FileData(url(type, nbFiles()-1), actions);
+}
+
+Compile::FileData::List Compile::Process::files(bool *ok) const
+{
+ if (ok) *ok = true;
+ FileData::List list;
+ QRegExp rexp("PURL::(.*)");
+ QStringList files = QStringList::split(" ", outputFiles());
+ for (uint i=0; i<files.count(); i++) {
+ if ( rexp.exactMatch(files[i]) ) {
+ PURL::FileType type = PURL::FileType::fromKey(rexp.cap(1));
+ if ( type==PURL::Nb_FileTypes ) {
+ if (ok) *ok = false;
+ qWarning("Unknown PURL::FileType in file list for %s", _manager->label().latin1());
+ continue;
+ }
+ if ( type.data().group==PURL::LinkerScript ) {
+ PURL::Url lkr = Main::toolGroup().linkerScript(_data.project, _data.linkType);
+ list += FileData(lkr, Included | InProject);
+ } else {
+ FileActions actions = Generated;
+ if ( type.data().group==PURL::Source || type==PURL::Hex
+ || type==PURL::Map || type==PURL::Coff || type==PURL::Library ) actions |= InProject;
+ if ( type==PURL::Hex && _data.project==0 ) actions |= Show;
+ list += fileData(type, actions);
+ }
+ } else list += FileData(url().toExtension(files[i]), Compile::Generated);
+ }
+ return list;
+}
+
+bool Compile::Process::checkIs(const QString &s, const QString &key)
+{
+ if ( !s.contains(key) ) return false;
+ if ( s!=key ) qWarning("Argument should be only %s, the rest will be ignored...", key.latin1());
+ return true;
+}
+
+QString Compile::Process::replaceIf(const QString &s, const QString &key, bool condition)
+{
+ QRegExp rexp("(.*)\\$" + key + "\\(([^)]*)\\)(.*)");
+ if ( !rexp.exactMatch(s) ) return s;
+ return rexp.cap(1) + (condition ? rexp.cap(2) : QString::null) + rexp.cap(3);
+}
+
+QStringList Compile::Process::arguments() const
+{
+ bool custom = _config->hasCustomArguments(_data.category);
+ bool withWine = Compile::Config::withWine(group());
+ QStringList args = (custom ? _config->customArguments(_data.category) : genericArguments(*_config));
+ PURL::Url lkr = Main::toolGroup().linkerScript(_data.project, _data.linkType);
+ QStringList nargs;
+ for (uint i=0; i<args.count(); i++) {
+ if ( args[i].contains("$(SRCPATH)") ) {
+ args[i].replace("$(SRCPATH)", directory().path());
+ args[i].replace("//", "/");
+ }
+ args[i] = replaceIf(args[i], "WINE", withWine);
+ args[i] = replaceIf(args[i], "LKR", hasLinkerScript());
+ args[i] = replaceIf(args[i], "NO_AUTO_DEVICE", _data.device!=Device::AUTO_DATA.name);
+ if ( checkIs(args[i], "%OBJS") ) { // before %O
+ if (_data.project) nargs += _data.project->objectsForLinker(objectExtension(), withWine);
+ else {
+ PURL::Url tmp = url(PURL::Object);
+ if ( !objectExtension().isEmpty() ) tmp = tmp.toExtension(objectExtension());
+ nargs += tmp.relativeTo(directory(), withWine ? PURL::WindowsSeparator : PURL::UnixSeparator);
+ }
+ continue;
+ }
+ if ( checkIs(args[i], "%LIBS") ) {
+ if (_data.project) nargs += _data.project->librariesForLinker(QString::null, withWine);
+ continue;
+ }
+ args[i].replace("%OBJECT", filepath(PURL::Object)); // before %O
+ args[i].replace("%O", outputFilepath());
+ args[i].replace("%COFF", filepath(PURL::Coff));
+ if (_data.project) args[i].replace("%PROJECT", _data.project->name());
+ else args[i].replace("%PROJECT", url().basename());
+ args[i].replace("%MAP", filepath(PURL::Map));
+ args[i].replace("%SYM", url().toExtension("sym").relativeTo(directory(), withWine ? PURL::WindowsSeparator : PURL::UnixSeparator));
+ args[i].replace("%LIST", filepath(PURL::Lst));
+ args[i].replace("%DEVICE", deviceName());
+ args[i].replace("%FAMILY", familyName());
+ args[i].replace("%LKR_PATH", lkr.path()); // before %LKR
+ args[i].replace("%LKR_NAME", lkr.filename()); // before LKR
+ args[i].replace("%LKR", lkr.filepath());
+ if ( checkIs(args[i], "%I") ) {
+ for (uint k=0; k<nbFiles(); k++) nargs += inputFilepath(k);
+ continue;
+ }
+ if ( !args[i].isEmpty() ) nargs += args[i];
+ }
+ args.clear();
+ for (uint i=0; i<nargs.count(); i++) args += QStringList::split("%SEP", nargs[i]);
+ return args;
+}
+
+void Compile::Process::setupProcess()
+{
+ bool withWine = Compile::Config::withWine(group());
+ QString exec = tool()->baseExecutable(withWine, Compile::Config::outputExecutableType(group()));
+ QString path = tool()->executableDirectory().path();
+ _process->setup(path + exec, arguments(), withWine);
+}
+
+Log::LineType Compile::Process::filterType(const QString &type) const
+{
+ QString s = type.lower();
+ if ( s.startsWith("warning") ) return Log::LineType::Warning;
+ if ( s.startsWith("error") ) return Log::LineType::Error;
+ if ( s.startsWith("message") ) return Log::LineType::Information;
+ return Log::LineType::Normal;
+}
+
+bool Compile::Process::parseErrorLine(const QString &s, const ParseErrorData &data)
+{
+ QRegExp re(data.pattern);
+ if ( !re.exactMatch(s) ) return false;
+ QString file;
+ if ( data.indexFile>=0 ) {
+ file = re.cap(data.indexFile).stripWhiteSpace();
+ if ( file.endsWith(".") ) file = file.mid(0, file.length()-1);
+ if ( file=="-" ) file = QString::null;
+ }
+ bool ok;
+ int line = -1;
+ if ( data.indexLine>=0 ) line = re.cap(data.indexLine).stripWhiteSpace().toUInt(&ok) - 1;
+ if ( !ok ) line = -1;
+ QString message;
+ if ( data.indexMessage>=0 ) message= re.cap(data.indexMessage).stripWhiteSpace();
+ Log::LineType type = data.defaultLineType;
+ if ( data.indexLogType>=0 ) {
+ QString s = re.cap(data.indexLogType).stripWhiteSpace();
+ if ( s.isEmpty() ) type = data.defaultLineType;
+ else type = filterType(s);
+ }
+ doLog(type, message, file, line);
+ return true;
+}
+
+void Compile::Process::doLog(const QString &type, const QString &message, const QString &surl, uint line)
+{
+ doLog(filterType(type), message, surl, line);
+}
+
+void Compile::Process::doLog(Log::LineType type, const QString &message, const QString &surl, uint line)
+{
+ if ( surl.isEmpty() ) {
+ _manager->log(type, message);
+ return;
+ }
+ PURL::Url url = PURL::Url::fromPathOrUrl(surl);
+ QString s;
+ if ( !url.isEmpty() ) {
+ if ( !url.exists() && !url.isInto(directory()) ) url = PURL::Url(directory(), surl);
+ s += url.filename() + ":" + QString::number(line+1) + ": ";
+ }
+ switch (type.type()) {
+ case Log::LineType::Warning: s += i18n("warning: "); break;
+ case Log::LineType::Error: s += i18n("error: "); break;
+ case Log::LineType::Information: s += i18n("message: "); break;
+ default: break;
+ }
+ _manager->log(type, s + message.stripWhiteSpace(), url.filepath(), line);
+}
+
+//-----------------------------------------------------------------------------
+void Compile::CustomProcess::setupProcess()
+{
+ _process->setUseShell(true);
+ _process->setup(_command, QStringList(), false);
+}
+
+void Compile::CustomProcess::logStderrLine(const QString &line)
+{
+ _manager->log(Log::LineType::Normal, line);
+}
diff --git a/src/tools/list/compile_process.h b/src/tools/list/compile_process.h
new file mode 100644
index 0000000..4fe396e
--- /dev/null
+++ b/src/tools/list/compile_process.h
@@ -0,0 +1,179 @@
+/***************************************************************************
+ * 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 COMPILE_PROCESS_H
+#define COMPILE_PROCESS_H
+
+#include "common/common/qflags.h"
+#include "common/global/purl.h"
+#include "libgui/log_view.h"
+#include "devices/base/hex_buffer.h"
+#include "tools/base/tool_group.h"
+#include "tools/base/generic_tool.h"
+#include "libgui/main_global.h"
+namespace Process { class LineSignal; }
+
+namespace Compile
+{
+ class Manager;
+ enum FileAction { NoAction = 0, Show = 1, InProject = 2, Generated = 8, Included = 16 };
+ Q_DECLARE_FLAGS(FileActions, FileAction)
+ Q_DECLARE_OPERATORS_FOR_FLAGS(FileActions)
+
+ class FileData {
+ public:
+ FileData() {}
+ FileData(const PURL::Url &u, FileActions a) : url(u), actions(a) {}
+ PURL::Url url;
+ FileActions actions;
+ class List : public QValueList<FileData> {
+ public:
+ List() {}
+ List(const FileData &data) { append(data); }
+ List onlyExistingFiles() const;
+ void cleanGenerated() const;
+ };
+ };
+
+ struct ArgumentData {
+ const char *key, *description;
+ };
+ extern const ArgumentData ARGUMENT_DATA[];
+
+ class ParseErrorData {
+ public:
+ ParseErrorData(const QString &p, int iFile, int iLine, int iMessage, Log::LineType dLineType)
+ : pattern(p), indexFile(iFile), indexLine(iLine), indexMessage(iMessage), indexLogType(-1),
+ defaultLineType(dLineType) {}
+ ParseErrorData(const QString &p, int iFile, int iLine, int iMessage, uint iLogType,
+ Log::LineType dLineType = Log::LineType::Error)
+ : pattern(p), indexFile(iFile), indexLine(iLine), indexMessage(iMessage), indexLogType(iLogType),
+ defaultLineType(dLineType) {}
+ QString pattern;
+ int indexFile, indexLine, indexMessage, indexLogType;
+ Log::LineType defaultLineType;
+ };
+
+//-----------------------------------------------------------------------------
+class LogWidget : public Log::Widget
+{
+ Q_OBJECT
+public:
+ LogWidget(QWidget *parent);
+ void appendLine(Log::LineType type, const QString &message, const QString &filepath, uint line);
+ void appendLine(Log::DebugLevel debug, const QString &message, const QString &filepath, uint line);
+ virtual void clear();
+
+private slots:
+ void lineClicked(int line);
+
+private:
+ class Data {
+ public:
+ Data() {}
+ Data(const QString &fp, uint l) : filepath(fp), line(l) {}
+ QString filepath;
+ uint line;
+ };
+ QMap<uint, Data> _map;
+};
+
+//-----------------------------------------------------------------------------
+class BaseProcess : public QObject
+{
+Q_OBJECT
+public:
+ BaseProcess();
+ virtual void init(const Data &data, Manager *manager);
+ virtual bool check() const = 0;
+ virtual FileData::List files(bool *ok) const = 0;
+ bool start();
+
+signals:
+ void success();
+ void failure();
+
+protected:
+ Manager *_manager;
+ Data _data;
+ ::Process::LineSignal *_process;
+ QString _stdout, _stderr;
+
+ const Tool::Group &group() const { return Main::toolGroup(); }
+ PURL::Directory directory(uint i = 0) const;
+ virtual void setupProcess() = 0;
+
+protected slots:
+ virtual void logStdoutLine(const QString &line) { logStderrLine(line); }
+ virtual void logStderrLine(const QString &line) = 0;
+ virtual void done(int code);
+ void timeout();
+};
+
+//-----------------------------------------------------------------------------
+class Process : public BaseProcess
+{
+Q_OBJECT
+public:
+ virtual ~Process();
+ virtual void init(const Data &data, Manager *manager);
+ virtual bool check() const;
+ virtual FileData::List files(bool *ok) const;
+ virtual QStringList genericArguments(const Compile::Config &config) const = 0;
+ void checkArguments() const;
+
+protected:
+ Config *_config;
+
+ virtual PURL::Url url(PURL::FileType type = PURL::Nb_FileTypes, uint i = 0) const;
+ QString filepath(PURL::FileType type, uint i=0) const;
+ virtual QString outputFilepath() const;
+ virtual QString outputFiles() const = 0;
+ uint nbFiles() const { return _data.items.count(); }
+ virtual QString inputFilepath(uint i) const { return filepath(PURL::Nb_FileTypes, i); }
+ virtual QString deviceName() const = 0;
+ virtual QString familyName() const { return QString::null; }
+ virtual QString objectExtension() const { return QString::null; }
+ virtual QString libraryExtension() const { return "lib"; }
+ virtual bool hasLinkerScript() const { return group().hasCustomLinkerScript(_data.project); }
+ FileData fileData(PURL::FileType type, FileActions actions) const;
+ bool parseErrorLine(const QString &s, const ParseErrorData &data);
+ virtual Log::LineType filterType(const QString &type) const;
+ void doLog(const QString &type, const QString &message, const QString &surl, uint line);
+ void doLog(Log::LineType type, const QString &message, const QString &surl, uint line);
+ virtual void setupProcess();
+ QStringList arguments() const;
+ const Tool::Base *tool() const { return group().base(_data.category); }
+
+private:
+ static bool checkIs(const QString &s, const QString &key);
+ static QString replaceIf(const QString &s, const QString &key, bool condition);
+};
+
+//-----------------------------------------------------------------------------
+class CustomProcess : public BaseProcess
+{
+Q_OBJECT
+public:
+ CustomProcess(const QString &command) : _command(command) {}
+ virtual bool check() const { return true; }
+ virtual FileData::List files(bool *ok) const { if (ok) *ok = true; return FileData::List(); }
+
+protected:
+ virtual void setupProcess();
+
+protected slots:
+ virtual void logStderrLine(const QString &line);
+
+private:
+ QString _command;
+};
+
+} // namespace
+
+#endif
diff --git a/src/tools/list/device_info.cpp b/src/tools/list/device_info.cpp
new file mode 100644
index 0000000..78ca7a7
--- /dev/null
+++ b/src/tools/list/device_info.cpp
@@ -0,0 +1,63 @@
+/***************************************************************************
+ * 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 "device_info.h"
+
+#include "devices/base/generic_device.h"
+#include "progs/list/prog_list.h"
+#include "tool_list.h"
+
+QString Device::webpageHtml(const Device::Data &data)
+{
+ const Device::Documents &documents = data.documents();
+ QString url = "http://www.microchip.com/stellent/idcplg?IdcService=SS_GET_PAGE&amp;nodeId=";
+ if ( documents.webpage.isEmpty() ) url += "2044&amp;AllWords=" + data.name();
+ else url += "1335&amp;dDocName=en" + documents.webpage;
+ return "<a href=\"" + url + "\">" + i18n("Device Page") + "</a> ";
+}
+
+QString documentHtml(const QString &document, const QString &label)
+{
+ if ( document.isEmpty() ) return QString::null;
+ return ", <a href=\"document://" + document + "\">" + label + "</a>";
+}
+
+QString Device::documentHtml(const Device::Data &data)
+{
+ QString s = webpageHtml(data);
+ s += documentHtml(data.documents().datasheet, i18n("Datasheet"));
+ s += documentHtml(data.documents().progsheet, i18n("Programming Specifications"));
+ return htmlTableRow(i18n("Documents"), s);
+}
+
+QString Device::supportedHtmlInfo(const Device::Data &data)
+{
+ QString doc;
+ doc += "<hr />\n";
+ doc += "<table>\n";
+ QString tools;
+ Tool::Lister::ConstIterator tit;
+ for (tit=Tool::lister().begin(); tit!=Tool::lister().end(); ++tit) {
+ if ( !tit.data()->isSupported(data.name()) ) continue;
+ if ( tit.data()->isCustom() ) continue;
+ if ( !tools.isEmpty() ) tools += ", ";
+ tools += tit.data()->label();
+ }
+ doc += htmlTableRow(i18n("Tools"), tools) + "\n";
+ QString progs;
+ Programmer::Lister::ConstIterator pit;
+ for (pit=Programmer::lister().begin(); pit!=Programmer::lister().end(); ++pit) {
+ if ( !pit.data()->isSupported(data.name()) ) continue;
+ if ( !progs.isEmpty() ) progs += ", ";
+ progs += pit.data()->label();
+ }
+ doc += htmlTableRow(i18n("Programmers"), progs) + "\n";
+ doc += "</table>\n";
+
+ return doc;
+}
diff --git a/src/tools/list/device_info.h b/src/tools/list/device_info.h
new file mode 100644
index 0000000..ad69c59
--- /dev/null
+++ b/src/tools/list/device_info.h
@@ -0,0 +1,22 @@
+/***************************************************************************
+ * 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 DEVICE_INFO_H
+#define DEVICE_INFO_H
+
+#include <qstring.h>
+namespace Device { class Data; }
+
+namespace Device
+{
+ extern QString webpageHtml(const Device::Data &data);
+ extern QString documentHtml(const Device::Data &data);
+ extern QString supportedHtmlInfo(const Device::Data &data);
+} // namespace
+
+#endif
diff --git a/src/tools/list/tool_list.cpp b/src/tools/list/tool_list.cpp
new file mode 100644
index 0000000..da21cd7
--- /dev/null
+++ b/src/tools/list/tool_list.cpp
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * 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 "tool_list.h"
+
+#include "tools/gputils/gputils.h"
+#include "tools/gputils/gui/gputils_ui.h"
+#include "tools/sdcc/sdcc.h"
+#include "tools/sdcc/gui/sdcc_ui.h"
+#include "tools/pic30/pic30.h"
+#include "tools/pic30/gui/pic30_ui.h"
+#include "tools/picc/picc.h"
+#include "tools/picc/gui/picc_ui.h"
+#include "tools/jal/jal.h"
+#include "tools/jal/gui/jal_ui.h"
+#include "tools/c18/c18.h"
+#include "tools/c18/gui/c18_ui.h"
+#include "tools/ccsc/ccsc.h"
+#include "tools/ccsc/gui/ccsc_ui.h"
+#include "tools/jalv2/jalv2.h"
+#include "tools/jalv2/gui/jalv2_ui.h"
+#include "tools/boost/boostc.h"
+#include "tools/boost/boostcpp.h"
+#include "tools/boost/boostbasic.h"
+#include "tools/boost/gui/boost_ui.h"
+#include "tools/mpc/mpc.h"
+#include "tools/mpc/gui/mpc_ui.h"
+#include "tools/cc5x/cc5x.h"
+#include "tools/cc5x/gui/cc5x_ui.h"
+#include "tools/custom/custom.h"
+
+Tool::Lister::Lister()
+{
+ addGroup(new GPUtils::Group, new GPUtils::GroupUI);
+ addGroup(new SDCC::Group, new SDCC::GroupUI);
+ addGroup(new PIC30::Group, new PIC30::GroupUI);
+ addGroup(new PICC::PICCLiteGroup, new PICC::GroupUI);
+ addGroup(new PICC::PICCGroup, new PICC::GroupUI);
+ addGroup(new PICC::PICC18Group, new PICC::GroupUI);
+ addGroup(new JAL::Group, new JAL::GroupUI);
+ addGroup(new C18::Group, new C18::GroupUI);
+ addGroup(new CCSC::Group, new CCSC::GroupUI);
+ addGroup(new JALV2::Group, new JALV2::GroupUI);
+ addGroup(new Boost::GroupC16, new Boost::GroupUI);
+ addGroup(new Boost::GroupC18, new Boost::GroupUI);
+ addGroup(new Boost::GroupCpp16, new Boost::GroupUI);
+ addGroup(new Boost::GroupCpp18, new Boost::GroupUI);
+ addGroup(new Boost::GroupBasic16, new Boost::GroupUI);
+ addGroup(new Boost::GroupBasic18, new Boost::GroupUI);
+ addGroup(new MPC::Group, new MPC::GroupUI);
+ addGroup(new CC5X::Group, new CC5X::GroupUI);
+ addGroup(new CustomTool::Group, 0);
+}
+
+namespace Tool
+{
+ Lister *_lister = 0;
+}
+
+const Tool::Lister &Tool::lister()
+{
+ if ( _lister==0 ) _lister = new Lister;
+ return *_lister;
+}
diff --git a/src/tools/list/tool_list.h b/src/tools/list/tool_list.h
new file mode 100644
index 0000000..b63aee0
--- /dev/null
+++ b/src/tools/list/tool_list.h
@@ -0,0 +1,28 @@
+/***************************************************************************
+ * 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 TOOL_LIST_H
+#define TOOL_LIST_H
+
+#include "common/common/lister.h"
+#include "tools/base/tool_group.h"
+
+namespace Tool
+{
+
+class Lister : public ::Group::Lister<Group>
+{
+public:
+ Lister();
+};
+
+extern const Lister &lister();
+
+} // namespace
+
+#endif
diff --git a/src/tools/list/tools_config_widget.cpp b/src/tools/list/tools_config_widget.cpp
new file mode 100644
index 0000000..449183d
--- /dev/null
+++ b/src/tools/list/tools_config_widget.cpp
@@ -0,0 +1,144 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 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. *
+ ***************************************************************************/
+#include "tools_config_widget.h"
+
+#include <qwidgetstack.h>
+#include <qlabel.h>
+
+#include "tool_list.h"
+#include "tools/gui/tool_config_widget.h"
+#include "tools/gui/tool_group_ui.h"
+#include "compile_config.h"
+#include "compile_process.h"
+#include "libgui/project.h"
+
+//----------------------------------------------------------------------------
+HelpDialog::HelpDialog(QWidget *parent)
+ : Dialog(parent, "help_dialog", false, i18n("Help Dialog"), Close, Close, false)
+{
+ QGridLayout *top = new QGridLayout(mainWidget(), 1, 1, 10, 10);
+ uint k = 0;
+ for (; Compile::ARGUMENT_DATA[k].key; k++) {
+ QLabel *label = new QLabel(Compile::ARGUMENT_DATA[k].key, mainWidget());
+ top->addWidget(label, k, 0);
+ label = new QLabel(i18n(Compile::ARGUMENT_DATA[k].description), mainWidget());
+ top->addWidget(label, k, 1);
+ }
+ top->setColStretch(2, 1);
+ top->setRowStretch(k, 1);
+}
+
+//----------------------------------------------------------------------------
+ToolsConfigWidget::ToolsConfigWidget(Project *project, QWidget *parent)
+ : ::ConfigWidget(parent), _project(project), _helpDialog(0)
+{
+ uint row = 0;
+
+ QLabel *label = new QLabel(i18n("Toolchain:"), this);
+ addWidget(label, row,row, 0,0);
+ _tool = new KeyComboBox<QString>(this);
+ Tool::Lister::ConstIterator it;
+ for (it=Tool::lister().begin(); it!=Tool::lister().end(); ++it)
+ _tool->appendItem(it.key(), it.data()->label());
+ connect(_tool->widget(), SIGNAL(activated(int)), SLOT(toolChanged()));
+ addWidget(_tool->widget(), row,row, 1,1);
+ label = new QLabel(i18n("Output type:"), this);
+ addWidget(label, row,row, 2,2);
+ _output = new KeyComboBox<Tool::OutputType>(this);
+ FOR_EACH(Tool::OutputType, type) _output->appendItem(type, type.label());
+ addWidget(_output->widget(), row,row, 3,3);
+ row++;
+
+ _mainStack = new QWidgetStack(this);
+ addWidget(_mainStack, row,row, 0,4);
+ row++;
+ _tabWidget = new QTabWidget(_mainStack);
+ _mainStack->addWidget(_tabWidget);
+ FOR_EACH(Tool::Category, category) {
+ _stacks[category] = new KeyWidgetStack<QString>(_tabWidget);
+ _stacks[category]->widget()->setMargin(10);
+ Tool::Lister::ConstIterator it;
+ for (it=Tool::lister().begin(); it!=Tool::lister().end(); ++it) {
+ if ( it.data()->isCustom() ) continue;
+ if ( !it.data()->needs(_project, category) ) continue;
+ ToolConfigWidget *cw = static_cast<const Tool::GroupUI *>(it.data()->gui())->createConfigWidget(category, project);
+ Q_ASSERT(cw);
+ _stacks[category]->appendItem(it.key(), cw);
+ connect(cw, SIGNAL(displayHelp()), SLOT(displayHelp()));
+ }
+ }
+ _customWidget = new QWidget(_mainStack);
+ _mainStack->addWidget(_customWidget);
+ QVBoxLayout *vbox = new QVBoxLayout(_customWidget);
+ label = new QLabel(i18n("Custom shell commands:"), _customWidget);
+ vbox->addWidget(label);
+ _commandsEditor = new EditListBox(1, _customWidget, "command_editor", EditListBox::DuplicatesAllowed);
+ vbox->addWidget(_commandsEditor);
+
+ setColStretch(4, 1);
+}
+
+void ToolsConfigWidget::toolChanged()
+{
+ QString name = _tool->currentItem();
+ bool canMakeLibrary = Tool::lister().group(name)->needs(_project, Tool::Category::Librarian);
+ _output->widget()->setEnabled(canMakeLibrary);
+ if ( !canMakeLibrary ) _output->setCurrentItem(Tool::OutputType::Executable);
+ if ( name==Tool::Group::CUSTOM_NAME ) _mainStack->raiseWidget(_customWidget);
+ else {
+ _mainStack->raiseWidget(_tabWidget);
+ FOR_EACH(Tool::Category, k) {
+ _tabWidget->removePage(_stacks[k]->widget());
+ _stacks[k]->widget()->hide();
+ if ( _stacks[k]->contains(name) ) {
+ _stacks[k]->setCurrentItem(name);
+ _stacks[k]->widget()->show();
+ _tabWidget->addTab(_stacks[k]->widget(), i18n(k.data().title));
+ }
+ }
+ _tabWidget->setCurrentPage(0);
+ }
+}
+
+void ToolsConfigWidget::loadConfig()
+{
+ const Tool::Group &group = Compile::Config::toolGroup(_project);
+ _tool->setCurrentItem(group.name());
+ _output->setCurrentItem(_project->outputType());
+ QStringList commands = Compile::Config::customCommands(_project);
+ _commandsEditor->setTexts(commands);
+ toolChanged();
+ FOR_EACH(Tool::Category, k) {
+ KeyWidgetStack<QString>::ConstIterator it;
+ for (it=_stacks[k]->begin(); it!=_stacks[k]->end(); ++it) {
+ if ( it.key()==Tool::Group::CUSTOM_NAME ) continue;
+ static_cast<ToolConfigWidget *>(_stacks[k]->item(it.key()))->loadConfig();
+ }
+ }
+}
+
+void ToolsConfigWidget::saveConfig()
+{
+ QString name = _tool->currentItem();
+ Compile::Config::setToolGroup(_project, *Tool::lister().group(name));
+ _project->setOutputType(_output->currentItem());
+ Compile::Config::setCustomCommands(_project, _commandsEditor->texts());
+ FOR_EACH(Tool::Category, k) {
+ if ( !_stacks[k]->contains(name) ) continue;
+ QWidget *w = _stacks[k]->item(name);
+ static_cast<ToolConfigWidget *>(w)->saveConfig();
+ }
+}
+
+void ToolsConfigWidget::displayHelp()
+{
+ if ( _helpDialog.isNull() ) _helpDialog = new HelpDialog(this);
+ _helpDialog->show();
+}
diff --git a/src/tools/list/tools_config_widget.h b/src/tools/list/tools_config_widget.h
new file mode 100644
index 0000000..0f41b6a
--- /dev/null
+++ b/src/tools/list/tools_config_widget.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 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 TOOLS_CONFIG_WIDGET_H
+#define TOOLS_CONFIG_WIDGET_H
+
+#include <qcombobox.h>
+#include <qtabwidget.h>
+#include <qvaluevector.h>
+
+#include "common/gui/config_widget.h"
+#include "common/gui/dialog.h"
+#include "common/gui/key_gui.h"
+#include "common/gui/editlistbox.h"
+#include "tools/base/generic_tool.h"
+class Project;
+class ToolConfigWidget;
+
+//----------------------------------------------------------------------------
+class HelpDialog : public Dialog
+{
+Q_OBJECT
+public:
+ HelpDialog(QWidget *parent);
+};
+
+//----------------------------------------------------------------------------
+class ToolsConfigWidget : public ConfigWidget
+{
+Q_OBJECT
+public:
+ ToolsConfigWidget(Project *project, QWidget *parent);
+ virtual void loadConfig();
+
+public slots:
+ virtual void saveConfig();
+ virtual void displayHelp();
+
+private slots:
+ void toolChanged();
+
+private:
+ Project *_project;
+ KeyComboBox<QString> *_tool;
+ KeyComboBox<Tool::OutputType> *_output;
+ QWidgetStack *_mainStack;
+ QWidget *_customWidget;
+ EditListBox *_commandsEditor;
+ QTabWidget *_tabWidget;
+ QMap<Tool::Category, KeyWidgetStack<QString> *> _stacks;
+ QGuardedPtr<Dialog> _helpDialog;
+};
+
+#endif