diff options
Diffstat (limited to 'src/tools/list')
-rw-r--r-- | src/tools/list/Makefile.am | 7 | ||||
-rw-r--r-- | src/tools/list/compile_config.cpp | 189 | ||||
-rw-r--r-- | src/tools/list/compile_config.h | 84 | ||||
-rw-r--r-- | src/tools/list/compile_manager.cpp | 292 | ||||
-rw-r--r-- | src/tools/list/compile_manager.h | 74 | ||||
-rw-r--r-- | src/tools/list/compile_process.cpp | 376 | ||||
-rw-r--r-- | src/tools/list/compile_process.h | 179 | ||||
-rw-r--r-- | src/tools/list/device_info.cpp | 63 | ||||
-rw-r--r-- | src/tools/list/device_info.h | 22 | ||||
-rw-r--r-- | src/tools/list/tool_list.cpp | 69 | ||||
-rw-r--r-- | src/tools/list/tool_list.h | 28 | ||||
-rw-r--r-- | src/tools/list/tools_config_widget.cpp | 144 | ||||
-rw-r--r-- | src/tools/list/tools_config_widget.h | 60 |
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&nodeId="; + if ( documents.webpage.isEmpty() ) url += "2044&AllWords=" + data.name(); + else url += "1335&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 |