summaryrefslogtreecommitdiffstats
path: root/src/libgui
diff options
context:
space:
mode:
Diffstat (limited to 'src/libgui')
-rw-r--r--src/libgui/Makefile.am12
-rw-r--r--src/libgui/breakpoint_view.cpp94
-rw-r--r--src/libgui/breakpoint_view.h48
-rw-r--r--src/libgui/config_center.cpp132
-rw-r--r--src/libgui/config_center.h85
-rw-r--r--src/libgui/config_gen.cpp189
-rw-r--r--src/libgui/config_gen.h82
-rw-r--r--src/libgui/console.cpp42
-rw-r--r--src/libgui/console.h27
-rw-r--r--src/libgui/device_editor.cpp141
-rw-r--r--src/libgui/device_editor.h47
-rw-r--r--src/libgui/device_gui.cpp463
-rw-r--r--src/libgui/device_gui.h205
-rw-r--r--src/libgui/editor.cpp91
-rw-r--r--src/libgui/editor.h68
-rw-r--r--src/libgui/editor_manager.cpp506
-rw-r--r--src/libgui/editor_manager.h128
-rw-r--r--src/libgui/global_config.cpp106
-rw-r--r--src/libgui/global_config.h39
-rw-r--r--src/libgui/gui_debug_manager.cpp249
-rw-r--r--src/libgui/gui_debug_manager.h61
-rw-r--r--src/libgui/gui_prog_manager.cpp72
-rw-r--r--src/libgui/gui_prog_manager.h37
-rw-r--r--src/libgui/hex_editor.cpp192
-rw-r--r--src/libgui/hex_editor.h83
-rw-r--r--src/libgui/likeback.cpp668
-rw-r--r--src/libgui/likeback.h120
-rw-r--r--src/libgui/log_view.cpp135
-rw-r--r--src/libgui/log_view.h51
-rw-r--r--src/libgui/main_global.cpp81
-rw-r--r--src/libgui/main_global.h70
-rw-r--r--src/libgui/new_dialogs.cpp83
-rw-r--r--src/libgui/new_dialogs.h59
-rw-r--r--src/libgui/object_view.cpp145
-rw-r--r--src/libgui/object_view.h99
-rw-r--r--src/libgui/project.cpp226
-rw-r--r--src/libgui/project.h49
-rw-r--r--src/libgui/project_editor.cpp72
-rw-r--r--src/libgui/project_editor.h47
-rw-r--r--src/libgui/project_manager.cpp651
-rw-r--r--src/libgui/project_manager.h106
-rw-r--r--src/libgui/project_manager_ui.cpp185
-rw-r--r--src/libgui/project_manager_ui.h121
-rw-r--r--src/libgui/project_wizard.cpp283
-rw-r--r--src/libgui/project_wizard.h91
-rw-r--r--src/libgui/register_view.cpp51
-rw-r--r--src/libgui/register_view.h42
-rw-r--r--src/libgui/text_editor.cpp346
-rw-r--r--src/libgui/text_editor.h103
-rw-r--r--src/libgui/toplevel.cpp993
-rw-r--r--src/libgui/toplevel.h132
-rw-r--r--src/libgui/toplevel_ui.cpp79
-rw-r--r--src/libgui/toplevel_ui.h77
-rw-r--r--src/libgui/watch_view.cpp225
-rw-r--r--src/libgui/watch_view.h94
55 files changed, 8683 insertions, 0 deletions
diff --git a/src/libgui/Makefile.am b/src/libgui/Makefile.am
new file mode 100644
index 0000000..b12fc23
--- /dev/null
+++ b/src/libgui/Makefile.am
@@ -0,0 +1,12 @@
+INCLUDES = -I$(top_srcdir)/src $(all_includes)
+METASOURCES = AUTO
+
+noinst_LTLIBRARIES = libgui.la
+libgui_la_LDFLAGS = $(all_libraries)
+libgui_la_SOURCES = editor.cpp device_gui.cpp toplevel.cpp object_view.cpp \
+ config_gen.cpp register_view.cpp device_editor.cpp watch_view.cpp project.cpp \
+ project_editor.cpp project_manager.cpp hex_editor.cpp global_config.cpp config_center.cpp \
+ editor_manager.cpp new_dialogs.cpp text_editor.cpp log_view.cpp gui_prog_manager.cpp \
+ gui_debug_manager.cpp breakpoint_view.cpp likeback.cpp main_global.cpp console.cpp \
+ project_wizard.cpp toplevel_ui.cpp project_manager_ui.cpp
+
diff --git a/src/libgui/breakpoint_view.cpp b/src/libgui/breakpoint_view.cpp
new file mode 100644
index 0000000..6f49aac
--- /dev/null
+++ b/src/libgui/breakpoint_view.cpp
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * 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 "breakpoint_view.h"
+
+#include <qlayout.h>
+#include <klocale.h>
+#include <qpopupmenu.h>
+
+#include "main_global.h"
+#include "editor_manager.h"
+#include "coff/base/text_coff.h"
+#include "gui_debug_manager.h"
+
+//----------------------------------------------------------------------------
+void Breakpoint::updateActions(const Data *data)
+{
+ bool hasBreakpoint = (data ? Breakpoint::list().contains(*data) : false);
+ Main::action("toggle_breakpoint")->setText(hasBreakpoint ? i18n("Remove breakpoint") : i18n("Set breakpoint"));
+ Main::action("toggle_breakpoint")->setEnabled(data);
+ bool isActive = (hasBreakpoint ? Breakpoint::list().state(*data)==Breakpoint::Active : false);
+ Main::action("enable_breakpoint")->setText(!isActive ? i18n("Enable breakpoint") : i18n("Disable breakpoint"));
+ Main::action("enable_breakpoint")->setEnabled(Debugger::manager->coff() && hasBreakpoint);
+}
+
+//----------------------------------------------------------------------------
+Breakpoint::ListViewItem::ListViewItem(ListView *parent, const Data &data)
+ : KListViewItem(parent), _data(data)
+{}
+
+//----------------------------------------------------------------------------
+Breakpoint::View::View(QWidget *parent)
+ : QWidget(parent, "breakpoints_view"), GenericView(Breakpoint::list()),
+ _currentData(0)
+{
+ QVBoxLayout *top = new QVBoxLayout(this);
+ _listview = new ListView(this);
+ connect(_listview, SIGNAL(clicked(QListViewItem *)), SLOT(itemClicked(QListViewItem *)));
+ connect(_listview, SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)),
+ SLOT(contextMenu(QListViewItem *, const QPoint &, int)));
+ _listview->setAllColumnsShowFocus(true);
+ _listview->addColumn(i18n("Status"));
+ _listview->addColumn(i18n("Location"));
+ _listview->addColumn(i18n("Address"));
+ top->addWidget(_listview);
+}
+
+void Breakpoint::View::updateView()
+{
+ // #### flickering...
+ _listview->clear();
+ for (uint i=0; i<Breakpoint::list().count(); i++) {
+ const Data &data = Breakpoint::list().data(i);
+ KListViewItem *item = new ListViewItem(_listview, data);
+ item->setPixmap(0, TextEditor::pixmap(Debugger::manager->breakpointType(data)));
+ item->setText(1, data.url.filename() + ":" + QString::number(data.line));
+ Address address = Breakpoint::list().address(data);
+ if ( address.isValid() ) item->setText(2, toHexLabelAbs(address));
+ else if ( Debugger::manager->coff() ) item->setText(2, i18n("Non-code breakpoint"));
+ else item->setText(2, "---");
+ }
+}
+
+void Breakpoint::View::itemClicked(QListViewItem *item)
+{
+ if ( item==0 ) return;
+ const Data &data = static_cast<ListViewItem *>(item)->data();
+ Address address = Breakpoint::list().address(data);
+ TextEditor *editor = ::qt_cast<TextEditor *>(Main::currentEditor());
+ const Coff::TextObject *coff = Debugger::manager->coff();
+ int line = -1;
+ if ( coff && editor && editor->fileType()==PURL::Coff && address.isValid() )
+ line = coff->lineForAddress(editor->url(), address);
+ if ( line==-1 ) {
+ editor = ::qt_cast<TextEditor *>(Main::editorManager().openEditor(data.url));
+ line = data.line;
+ }
+ if ( editor==0 ) return;
+ editor->show();
+ editor->setCursor(line, 0);
+}
+
+void Breakpoint::View::contextMenu(QListViewItem *item, const QPoint &pos, int)
+{
+ _currentData = (item ? &static_cast<ListViewItem *>(item)->data() : 0);
+ updateActions(_currentData);
+ Main::popup("breakpoint_context_menu").exec(pos);
+ _currentData = 0;
+}
diff --git a/src/libgui/breakpoint_view.h b/src/libgui/breakpoint_view.h
new file mode 100644
index 0000000..984a7ed
--- /dev/null
+++ b/src/libgui/breakpoint_view.h
@@ -0,0 +1,48 @@
+/***************************************************************************
+ * 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 BREAKPOINT_VIEW_H
+#define BREAKPOINT_VIEW_H
+
+#include "progs/manager/breakpoint.h"
+#include "common/gui/list_view.h"
+
+namespace Breakpoint
+{
+//----------------------------------------------------------------------------
+class ListViewItem : public KListViewItem
+{
+public:
+ ListViewItem(ListView *parent, const Data &data);
+ const Data &data() const { return _data; }
+
+private:
+ Data _data;
+};
+
+//----------------------------------------------------------------------------
+class View : public QWidget, public GenericView
+{
+Q_OBJECT
+public:
+ View(QWidget *parent);
+ virtual void updateView();
+ const Data *currentData() const { return _currentData; }
+
+private slots:
+ void itemClicked(QListViewItem *item);
+ void contextMenu(QListViewItem *item, const QPoint &pos, int col);
+
+private:
+ ListView *_listview;
+ const Data *_currentData;
+};
+
+} // namespace
+
+#endif
diff --git a/src/libgui/config_center.cpp b/src/libgui/config_center.cpp
new file mode 100644
index 0000000..530cbbf
--- /dev/null
+++ b/src/libgui/config_center.cpp
@@ -0,0 +1,132 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "config_center.h"
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qtooltip.h>
+#include <qgroupbox.h>
+#include <qtabwidget.h>
+#include <qtimer.h>
+#include <kiconloader.h>
+#include <klocale.h>
+#include <klistview.h>
+
+#include "global_config.h"
+#include "device_gui.h"
+#include "tools/list/tools_config_widget.h"
+#include "progs/gui/prog_config_center.h"
+#include "progs/gui/debug_config_center.h"
+#include "tools/list/compile_config.h"
+
+//----------------------------------------------------------------------------
+GlobalConfigWidget::GlobalConfigWidget()
+{
+ uint row = numRows();
+ _showDebug = new KeyComboBox<Log::DebugLevel>(this);
+ FOR_EACH(Log::DebugLevel, level) _showDebug->appendItem(level, level.label());
+ addWidget(_showDebug->widget(), row,row, 0,0);
+ row++;
+}
+
+void GlobalConfigWidget::loadConfig()
+{
+ BaseGlobalConfigWidget::loadConfig();
+ _showDebug->setCurrentItem(GlobalConfig::debugLevel());
+}
+
+void GlobalConfigWidget::saveConfig()
+{
+ BaseGlobalConfigWidget::saveConfig();
+ GlobalConfig::writeDebugLevel(_showDebug->currentItem());
+}
+
+QPixmap GlobalConfigWidget::pixmap() const
+{
+ KIconLoader loader;
+ return loader.loadIcon("configure", KIcon::Toolbar, KIcon::SizeMedium);
+}
+
+//----------------------------------------------------------------------------
+StandaloneConfigWidget::StandaloneConfigWidget()
+ : ConfigWidget(0)
+{
+ uint row = 0;
+
+ QLabel *label = new QLabel(i18n("Device:"), this);
+ addWidget(label, row,row, 0,0);
+ _device = new DeviceChooser::Button(true, this);
+ addWidget(_device, row,row, 1,1);
+ row++;
+
+ _tools = new ToolsConfigWidget(0, this);
+ addWidget(_tools, row,row, 0,2);
+ row++;
+
+ setColStretch(2, 1);
+}
+
+void StandaloneConfigWidget::loadConfig()
+{
+ _device->setDevice(Compile::Config::device(0));
+ _tools->loadConfig();
+}
+
+void StandaloneConfigWidget::saveConfig()
+{
+ Compile::Config::setDevice(0, _device->device());
+ _tools->saveConfig();
+}
+
+QPixmap StandaloneConfigWidget::pixmap() const
+{
+ KIconLoader loader;
+ return loader.loadIcon("configure", KIcon::Toolbar, KIcon::SizeMedium);
+}
+
+//----------------------------------------------------------------------------
+ConfigWidget *ConfigCenter::factory(Type type)
+{
+ switch (type) {
+ case General: return new GlobalConfigWidget;
+ case ProgSelect: return new Programmer::SelectConfigWidget;
+ case ProgOptions: return new Programmer::OptionsConfigWidget;
+ case DebugOptions: return new Debugger::OptionsConfigWidget;
+ case Standalone: return new StandaloneConfigWidget;
+ case Nb_Types: break;
+ }
+ Q_ASSERT(false);
+ return 0;
+}
+
+ConfigCenter::ConfigCenter(Type showType, QWidget *parent)
+ : Dialog(IconList, i18n("Configure Piklab"), Ok|Cancel, Cancel, parent, "configure_piklab_dialog", true, false)
+{
+ for (uint i=0; i<Nb_Types; i++) {
+ _configWidgets[i] = factory(Type(i));
+ _configWidgets[i]->loadConfig();
+ _pages[i] = addPage(_configWidgets[i]->title(), _configWidgets[i]->header(), _configWidgets[i]->pixmap());
+ QVBoxLayout *vbox = new QVBoxLayout(_pages[i]);
+ _configWidgets[i]->reparent(_pages[i], QPoint(0,0));
+ vbox->addWidget(_configWidgets[i]);
+ }
+ showPage(showType);
+}
+
+void ConfigCenter::slotApply()
+{
+ for (uint i=0; i<Nb_Types; i++) _configWidgets[i]->saveConfig();
+}
+
+void ConfigCenter::slotOk()
+{
+ slotApply();
+ accept();
+}
diff --git a/src/libgui/config_center.h b/src/libgui/config_center.h
new file mode 100644
index 0000000..1e543b7
--- /dev/null
+++ b/src/libgui/config_center.h
@@ -0,0 +1,85 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef CONFIG_CENTER_H
+#define CONFIG_CENTER_H
+
+#include <qcheckbox.h>
+#include <qlineedit.h>
+#include <qwidgetstack.h>
+
+#include "common/gui/key_gui.h"
+#include "common/gui/dialog.h"
+#include "progs/gui/prog_config_widget.h"
+#include "global_config.h"
+namespace DeviceChooser { class Button; }
+class SelectDirectoryWidget;
+class ToolsConfigWidget;
+
+//----------------------------------------------------------------------------
+BEGIN_DECLARE_CONFIG_WIDGET(BaseGlobalConfig, BaseGlobalConfigWidget)
+END_DECLARE_CONFIG_WIDGET
+
+class GlobalConfigWidget : public BaseGlobalConfigWidget
+{
+Q_OBJECT
+public:
+ GlobalConfigWidget();
+ virtual QString title() const { return i18n("General"); }
+ virtual QString header() const { return i18n("General Configuration"); }
+ virtual QPixmap pixmap() const;
+ virtual void loadConfig();
+
+public slots:
+ virtual void saveConfig();
+
+private:
+ KeyComboBox<Log::DebugLevel> *_showDebug;
+};
+
+//----------------------------------------------------------------------------
+class StandaloneConfigWidget : public ConfigWidget
+{
+ Q_OBJECT
+public:
+ StandaloneConfigWidget();
+ virtual void loadConfig();
+ virtual QString title() const { return i18n("Standalone File"); }
+ virtual QString header() const { return i18n("Standalone File Compilation"); }
+ virtual QPixmap pixmap() const;
+
+public slots:
+ virtual void saveConfig();
+
+private:
+ DeviceChooser::Button *_device;
+ ToolsConfigWidget *_tools;
+};
+
+//----------------------------------------------------------------------------
+class ConfigCenter : public Dialog
+{
+Q_OBJECT
+public:
+ enum Type { General = 0, ProgSelect, ProgOptions, DebugOptions,
+ Standalone, Nb_Types };
+ ConfigCenter(Type showType, QWidget *parent);
+
+public slots:
+ virtual void slotOk();
+ virtual void slotApply();
+
+private:
+ QWidget *_pages[Nb_Types];
+ ConfigWidget *_configWidgets[Nb_Types];
+
+ static ConfigWidget *factory(Type type);
+};
+
+#endif
diff --git a/src/libgui/config_gen.cpp b/src/libgui/config_gen.cpp
new file mode 100644
index 0000000..036e62e
--- /dev/null
+++ b/src/libgui/config_gen.cpp
@@ -0,0 +1,189 @@
+/***************************************************************************
+ * Copyright (C) 2006-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "config_gen.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <klocale.h>
+
+#include "device_gui.h"
+#include "devices/base/generic_memory.h"
+#include "devices/gui/hex_view.h"
+#include "devices/gui/memory_editor.h"
+#include "devices/base/device_group.h"
+#include "devices/gui/device_group_ui.h"
+#include "devices/list/device_list.h"
+#include "text_editor.h"
+#include "tools/list/tool_list.h"
+
+//-----------------------------------------------------------------------------
+GeneratorDialog::GeneratorDialog(const QString &title, QWidget *parent, const char *name)
+ : Dialog(parent, name, true, title, Close|User1, Close, false, QSize(400, 300))
+{
+ QVBoxLayout *top = new QVBoxLayout(mainWidget(), 10, 10);
+
+ QHBoxLayout *hbox = new QHBoxLayout(top);
+ QLabel *label = new QLabel(i18n("Device:"), mainWidget());
+ hbox->addWidget(label);
+ _deviceChooser = new DeviceChooser::Button(false, mainWidget());
+ connect(_deviceChooser, SIGNAL(changed()), SLOT(reset()));
+ hbox->addWidget(_deviceChooser);
+ hbox->addSpacing(20);
+
+ label = new QLabel(i18n("Toolchain:"), mainWidget());
+ hbox->addWidget(label);
+ _configType = new KeyComboBox<QString>(mainWidget());
+ Tool::Lister::ConstIterator it;
+ for (it=Tool::lister().begin(); it!=Tool::lister().end(); ++it)
+ _configType->appendItem(it.key(), it.data()->label());
+ connect(_configType->widget(), SIGNAL(activated(int)), SLOT(typeChanged()));
+ hbox->addWidget(_configType->widget());
+
+ label = new QLabel(i18n("Tool Type:"), mainWidget());
+ hbox->addWidget(label);
+ _toolType = new KeyComboBox<PURL::ToolType>(mainWidget());
+ FOR_EACH(PURL::ToolType, type) _toolType->appendItem(type, type.label());
+ _toolType->fixMinimumWidth();
+ connect(_toolType->widget(), SIGNAL(activated(int)), SLOT(compute()));
+ hbox->addWidget(_toolType->widget());
+ hbox->addStretch(1);
+
+ _hbox = new QHBoxLayout(top);
+
+ _text = new SimpleTextEditor(false, PURL::Nb_FileTypes, mainWidget());
+ _text->setReadOnly(true);
+ top->addWidget(_text);
+
+ _warning = new QLabel(mainWidget());
+ top->addWidget(_warning);
+
+ setButtonText(User1, i18n("Copy to clipboard"));
+}
+
+void GeneratorDialog::set(const Device::Data *data, const Tool::Group &group, PURL::ToolType stype)
+{
+ QString device;
+ if ( data==0 ) {
+ QValueVector<QString> devices = group.supportedDevices();
+ if ( devices.isEmpty() ) return;
+ device = devices[0];
+ } else device = data->name();
+ _deviceChooser->setDevice(device);
+ _configType->setCurrentItem(group.name());
+ setToolType(stype);
+ reset();
+}
+
+void GeneratorDialog::typeChanged()
+{
+ setToolType(PURL::ToolType::Nb_Types);
+ compute();
+}
+
+void GeneratorDialog::setToolType(PURL::ToolType stype)
+{
+ const Tool::Group *group = Tool::lister().group(_configType->currentItem());
+ _toolType->clear();
+ FOR_EACH(PURL::ToolType, type)
+ if ( group->implementationType(type)!=PURL::Nb_FileTypes ) _toolType->appendItem(type, type.label());
+ _toolType->setCurrentItem(stype);
+ _toolType->widget()->setEnabled( _toolType->count()>=2 );
+}
+
+PURL::ToolType GeneratorDialog::toolType() const
+{
+ return _toolType->currentItem();
+}
+
+void GeneratorDialog::compute()
+{
+ const Tool::Group *group = Tool::lister().group(_configType->currentItem());
+ _warning->hide();
+ if ( group->isSupported(_deviceChooser->device()) ) {
+ const Tool::SourceGenerator *generator = group->sourceGenerator();
+ if ( generator==0 ) {
+ _text->setFileType(PURL::Nb_FileTypes);
+ _text->setText(i18n("Generation is not supported yet for the selected toolchain or device."));
+ } else {
+ bool ok = true;
+ PURL::FileType type = group->implementationType(toolType());
+ SourceLine::List lines = generateLines(ok);
+ if ( ok && lines.isEmpty() ) {
+ _text->setFileType(PURL::Nb_FileTypes);
+ _text->setText(i18n("This toolchain does not need explicit config bits."));
+ } else {
+ _text->setFileType(type);
+ _text->setText(SourceLine::text(type.data().sourceFamily, lines, 4));
+ }
+ if ( !ok ) {
+ _warning->show();
+ _warning->setText(i18n("Generation is only partially supported for this device."));
+ }
+ }
+ } else {
+ _text->setFileType(PURL::Nb_FileTypes);
+ if ( group->supportedDevices().isEmpty() ) _text->setText(i18n("Could not detect supported devices for selected toolchain. Please check installation."));
+ else _text->setText(i18n("Device not supported by the selected toolchain."));
+ }
+}
+
+void GeneratorDialog::slotUser1()
+{
+ _text->selectAll();
+ _text->copy();
+ _text->deselect();
+}
+
+//-----------------------------------------------------------------------------
+ConfigGenerator::ConfigGenerator(QWidget *parent)
+ : GeneratorDialog(i18n("Config Generator"), parent, "config_generator"), _memory(0), _configEditor(0)
+{}
+
+ConfigGenerator::~ConfigGenerator()
+{
+ delete _memory;
+}
+
+void ConfigGenerator::reset()
+{
+ delete _memory;
+ const Device::Data *data = Device::lister().data(_deviceChooser->device());
+ _memory = data->group().createMemory(*data);
+ delete _configEditor;
+ _configEditor = Device::groupui(*data).createConfigEditor(*_memory, mainWidget());
+ if (_configEditor) {
+ _configEditor->show();
+ connect(_configEditor, SIGNAL(modified()), SLOT(compute()));
+ _configEditor->updateDisplay();
+ _hbox->addWidget(_configEditor);
+ }
+ compute();
+}
+
+SourceLine::List ConfigGenerator::generateLines(bool &ok) const
+{
+ const Tool::Group *group = Tool::lister().group(_configType->currentItem());
+ const Tool::SourceGenerator *generator = group->sourceGenerator();
+ Q_ASSERT(generator);
+ return generator->configLines(toolType(), *_memory, ok);
+}
+
+//-----------------------------------------------------------------------------
+TemplateGenerator::TemplateGenerator(QWidget *parent)
+ : GeneratorDialog(i18n("Template Generator"), parent, "template_generator")
+{}
+
+SourceLine::List TemplateGenerator::generateLines(bool &ok) const
+{
+ const Tool::Group *group = Tool::lister().group(_configType->currentItem());
+ const Tool::SourceGenerator *generator = group->sourceGenerator();
+ Q_ASSERT(generator);
+ const Device::Data *data = Device::lister().data(_deviceChooser->device());
+ return generator->templateSourceFile(toolType(), *data, ok);
+}
diff --git a/src/libgui/config_gen.h b/src/libgui/config_gen.h
new file mode 100644
index 0000000..fa9fd56
--- /dev/null
+++ b/src/libgui/config_gen.h
@@ -0,0 +1,82 @@
+/***************************************************************************
+ * Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef CONFIG_GEN_H
+#define CONFIG_GEN_H
+
+class QHBoxLayout;
+class QLabel;
+
+#include "common/gui/dialog.h"
+#include "tools/base/tool_group.h"
+#include "common/gui/key_gui.h"
+namespace DeviceChooser { class Button; }
+namespace Device {
+ class Memory;
+ class MemoryEditor;
+}
+class SimpleTextEditor;
+
+//-----------------------------------------------------------------------------
+class GeneratorDialog : public Dialog
+{
+Q_OBJECT
+public:
+ GeneratorDialog(const QString &title, QWidget *parent, const char *name);
+ void set(const Device::Data *data, const Tool::Group &group, PURL::ToolType stype);
+
+protected slots:
+ void typeChanged();
+ virtual void reset() { compute(); }
+ virtual void compute();
+ virtual void slotUser1();
+
+protected:
+ QHBoxLayout *_hbox;
+ DeviceChooser::Button *_deviceChooser;
+ KeyComboBox<QString> *_configType;
+ KeyComboBox<PURL::ToolType> *_toolType;
+ SimpleTextEditor *_text;
+ QLabel *_warning;
+
+ PURL::ToolType toolType() const;
+ void setToolType(PURL::ToolType stype);
+ virtual SourceLine::List generateLines(bool &ok) const = 0;
+};
+
+//-----------------------------------------------------------------------------
+class ConfigGenerator : public GeneratorDialog
+{
+Q_OBJECT
+public:
+ ConfigGenerator(QWidget *parent);
+ virtual ~ConfigGenerator();
+
+private slots:
+ virtual void reset();
+
+private:
+ Device::Memory *_memory;
+ Device::MemoryEditor *_configEditor;
+
+ void setToolType(PURL::ToolType stype);
+ virtual SourceLine::List generateLines(bool &ok) const;
+};
+
+//-----------------------------------------------------------------------------
+class TemplateGenerator : public GeneratorDialog
+{
+Q_OBJECT
+public:
+ TemplateGenerator(QWidget *parent);
+
+private:
+ virtual SourceLine::List generateLines(bool &ok) const;
+};
+
+#endif
diff --git a/src/libgui/console.cpp b/src/libgui/console.cpp
new file mode 100644
index 0000000..99c996c
--- /dev/null
+++ b/src/libgui/console.cpp
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "console.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qdir.h>
+#include <klibloader.h>
+#include <klocale.h>
+#include <kparts/part.h>
+#include <kde_terminal_interface.h>
+
+ConsoleView::ConsoleView(QWidget *parent)
+ : QWidget(parent, "console_view"), _initialized(false)
+{}
+
+void ConsoleView::showEvent(QShowEvent *e)
+{
+ if ( !_initialized ) {
+ _initialized = true;
+ KLibFactory *factory = KLibLoader::self()->factory("libkonsolepart");
+ QVBoxLayout *top = new QVBoxLayout(this, 0, 10);
+ if ( factory==0 ) {
+ QLabel *label = new QLabel(i18n("Could not find \"konsolepart\"; please install kdebase."), this);
+ label->show();
+ top->addWidget(label);
+ return;
+ } else {
+ QWidget *pwidget = static_cast<KParts::Part *>(factory->create(this, "konsole"))->widget();
+ pwidget->show();
+ top->addWidget(pwidget);
+ setFocusProxy(pwidget);
+ }
+ }
+ QWidget::showEvent(e);
+}
diff --git a/src/libgui/console.h b/src/libgui/console.h
new file mode 100644
index 0000000..e073754
--- /dev/null
+++ b/src/libgui/console.h
@@ -0,0 +1,27 @@
+/***************************************************************************
+ * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef CONSOLE_H
+#define CONSOLE_H
+
+#include <qwidget.h>
+
+class ConsoleView : public QWidget
+{
+Q_OBJECT
+public:
+ ConsoleView(QWidget *parent);
+
+protected:
+ virtual void showEvent(QShowEvent *e);
+
+private:
+ bool _initialized;
+};
+
+#endif
diff --git a/src/libgui/device_editor.cpp b/src/libgui/device_editor.cpp
new file mode 100644
index 0000000..7a2a3c6
--- /dev/null
+++ b/src/libgui/device_editor.cpp
@@ -0,0 +1,141 @@
+/***************************************************************************
+ * 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 "device_editor.h"
+
+#include <qscrollview.h>
+#include <qregexp.h>
+
+#include "devices/list/device_list.h"
+#include "toplevel.h"
+#include "gui_debug_manager.h"
+#include "project_manager.h"
+#include "common/global/pfile.h"
+#include "main_global.h"
+
+DeviceEditor::DeviceEditor(const QString &title, const QString &tag, QWidget *parent, const char *name)
+ : Editor(title, tag, parent, name), _view(0)
+{
+ init();
+}
+
+DeviceEditor::DeviceEditor(QWidget *parent, const char *name)
+ : Editor(parent, name), _view(0)
+{
+ init();
+}
+
+void DeviceEditor::init()
+{
+ QHBoxLayout *hbox = new QHBoxLayout(this, 0);
+ QScrollView *sview = new QScrollView(this, "scroll_view");
+ sview->setResizePolicy(QScrollView::AutoOneFit);
+ hbox->addWidget(sview);
+ _widget = new QWidget(sview->viewport(), "main_scroll_widget");
+ sview->addChild(_widget);
+ _top = new QVBoxLayout(_widget, 0, 0);
+ _labelDevice = new QLabel(_widget);
+ _labelDevice->setMargin(10);
+ _labelDevice->setTextFormat(RichText);
+ _top->addWidget(_labelDevice);
+ _labelWarning = new QLabel(_widget);
+ _labelWarning->setMargin(10);
+ _labelWarning->setTextFormat(RichText);
+ _top->addWidget(_labelWarning);
+ _vbox = new QVBoxLayout(_top);
+
+ connect(&Main::toplevel(), SIGNAL(stateChanged()), SLOT(updateDevice()));
+}
+
+void DeviceEditor::setDevice(bool force)
+{
+ if ( Main::device()==Device::AUTO_DATA.name ) {
+ PURL::Url url = Main::projectManager().projectUrl();
+ QString name = guessDeviceFromFile(url);
+ if ( !force && name==_device ) return;
+ _device = name;
+ if ( name==Device::AUTO_DATA.name )
+ _labelDevice->setText(i18n("The target device is not configured and cannot be guessed from source file. "
+ "The source file either cannot be found or does not contain any processor directive."));
+ else _labelDevice->setText(i18n("Device guessed from file: %1").arg(name));
+ _labelDevice->show();
+ } else {
+ if ( !force && Main::device()==_device ) return;
+ _device = Main::device();
+ _labelDevice->hide();
+ }
+ if ( _view && isModified() ) {
+ if ( MessageBox::questionYesNo(i18n("File %1 not saved.").arg(filename()), KStdGuiItem::save(), KStdGuiItem::discard()) )
+ Editor::save();
+ }
+ _labelWarning->hide();
+ const Device::Data *data = Device::lister().data(_device);
+ delete _view;
+ _view = createView(data, _widget);
+ if (_view) {
+ _view->show();
+ _vbox->addWidget(_view);
+ updateGeometry();
+ }
+ setModified(false);
+ emit guiChanged();
+}
+
+PURL::Url DeviceEditor::findAsmFile(const PURL::Url &url)
+{
+ if ( url.isEmpty() ) return PURL::Url();
+ PURL::SourceFamily family = url.fileType().data().sourceFamily;
+ if ( family.data().toolType==PURL::ToolType::Assembler ) return url;
+ FOR_EACH(PURL::FileType, i) {
+ PURL::SourceFamily source = i.data().sourceFamily;
+ if ( source.data().toolType!=PURL::ToolType::Assembler ) continue;
+ for (uint k=0; i.data().extensions[k]; k++) {
+ PURL::Url src = url.toExtension(i.data().extensions[k]);
+ if ( PURL::findExistingUrl(src) ) return src;
+ }
+ }
+ return PURL::Url();
+}
+
+QString DeviceEditor::guessDeviceFromFile(const PURL::Url &url)
+{
+ PURL::Url src = findAsmFile(url);
+ if ( src.isEmpty() ) return Device::AUTO_DATA.name;
+ Log::StringView sview;
+ PURL::File file(src, sview);
+ if ( !file.openForRead() ) return Device::AUTO_DATA.name;
+
+ QString device;
+ // QRegExp re1("^[ \\t]+(?:PROCESSOR|processor)[ \\t]+((?:p|sx|P|SX)[a-z0-9A-Z]+)" ) ;
+ QRegExp re1("^[ \\t]+(?:PROCESSOR|processor)[ \\t]+([a-z0-9A-Z]+)" ) ;
+ QRegExp re2("^[ \\t]+(?:LIST|list)[ \\t]+" ) ;
+ for (;;) {
+ QString line = file.readLine();
+ if ( line.isNull() ) break;
+ // search PROCESSOR directive
+ if ( re1.search(line, 0)!=-1 ) {
+ device = re1.cap(1);
+ break;
+ }
+ // search LIST p=... directive
+ int k = re2.search(line,0);
+ if ( k!=-1 ) {
+ //QRegExp re3("(?:p|P)[ \\t]*=[ \\t]*((?:p|sx|P|SX)[a-z0-9A-Z]+)") ;
+ QRegExp re3("(?:p|P)[ \\t]*=[ \\t]*([a-z0-9A-Z]+)") ;
+ if ( re3.search(line, k+5)!=-1 ) {
+ device = re3.cap(1);
+ break;
+ }
+ }
+ }
+ device = device.upper();
+ if( device[0]=='P') return device.mid(1);
+ if ( Device::lister().data(device)==0 ) return Device::AUTO_DATA.name;
+ return device;
+}
diff --git a/src/libgui/device_editor.h b/src/libgui/device_editor.h
new file mode 100644
index 0000000..8b7cab7
--- /dev/null
+++ b/src/libgui/device_editor.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef DEVICE_EDITOR_H
+#define DEVICE_EDITOR_H
+
+#include "editor.h"
+namespace Device { class Data; }
+
+class DeviceEditor : public Editor
+{
+Q_OBJECT
+public:
+ DeviceEditor(const QString &title, const QString &tag, QWidget *parent, const char *name);
+ DeviceEditor(QWidget *parent, const char *name);
+ virtual PURL::FileType fileType() const { return PURL::Nb_FileTypes; }
+ virtual PURL::Url url() const { return PURL::Url(); }
+ virtual void setDevice(bool force = false);
+ static QString guessDeviceFromFile(const PURL::Url &url);
+ virtual bool save(const PURL::Url &) { return false; }
+ virtual bool open(const PURL::Url &) { return true; }
+ virtual QValueList<uint> bookmarkLines() const { return QValueList<uint>(); }
+ virtual void setBookmarkLines(const QValueList<uint> &) {}
+
+public slots:
+ virtual void statusChanged() { emit statusTextChanged(" "); }
+
+protected:
+ QString _device;
+ QWidget *_widget, *_view;
+ QVBoxLayout *_top, *_vbox;
+ QLabel *_labelDevice, *_labelWarning;
+
+ void init();
+ virtual QWidget *createView(const Device::Data *data, QWidget *parent) = 0;
+ static PURL::Url findAsmFile(const PURL::Url &url);
+
+private slots:
+ void updateDevice() { setDevice(); }
+};
+
+#endif
diff --git a/src/libgui/device_gui.cpp b/src/libgui/device_gui.cpp
new file mode 100644
index 0000000..8183725
--- /dev/null
+++ b/src/libgui/device_gui.cpp
@@ -0,0 +1,463 @@
+/***************************************************************************
+ * 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_gui.h"
+
+#include <qlayout.h>
+#include <qpainter.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qcheckbox.h>
+#include <qsplitter.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+#include <klistview.h>
+#include <klocale.h>
+
+#include "devices/list/device_list.h"
+#include "devices/base/device_group.h"
+#include "devices/gui/device_group_ui.h"
+#include "progs/list/prog_list.h"
+#include "tools/list/device_info.h"
+#include "tools/list/tool_list.h"
+
+namespace DeviceChooser
+{
+//-----------------------------------------------------------------------------
+void DeviceChooser::Config::writeProgrammerGroup(const Programmer::Group *group)
+{
+ writeEntry("programmer", group ? group->name() : QString::null);
+}
+const Programmer::Group *DeviceChooser::Config::programmerGroup()
+{
+ QString name = readEntry("programmer", QString::null);
+ return Programmer::lister().group(name);
+}
+
+void DeviceChooser::Config::writeToolGroup(const Tool::Group *group)
+{
+ writeEntry("tool", group ? group->name() : QString::null);
+}
+const Tool::Group *DeviceChooser::Config::toolGroup()
+{
+ QString name = readEntry("tool", QString::null);
+ return Tool::lister().group(name);
+}
+
+//-----------------------------------------------------------------------------
+class ListItem : public KListViewItem
+{
+public:
+ ListItem(KListView *list, const QString &name, bool selectable, bool isDevice)
+ : KListViewItem(list, name), _device(isDevice) {
+ setSelectable(selectable);
+ }
+ ListItem(KListViewItem *item, const QString &name)
+ : KListViewItem(item, name), _device(true) {}
+
+ bool isDevice() const { return _device; }
+ virtual void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align) {
+ QColorGroup ncg = cg;
+ if (_device) {
+ const Device::Data *device = Device::lister().data(text(0));
+ Q_ASSERT(device);
+ ncg.setColor(QColorGroup::Text, Device::statusColor(device->status()));
+ }
+ KListViewItem::paintCell(p, ncg, column, width, align);
+ }
+
+private:
+ bool _device;
+};
+
+} // namespace
+
+//-----------------------------------------------------------------------------
+const DeviceChooser::ListType::Data DeviceChooser::ListType::DATA[Nb_Types] = {
+ { "family_tree", I18N_NOOP("Family Tree") },
+ { "flat", I18N_NOOP("Flat List") }
+};
+
+DeviceChooser::Dialog::Dialog(const QString &device, Type type, QWidget *parent)
+ : ::Dialog(parent, "device_chooser_dialog", true, i18n("Select a device"),
+ Ok|Close, Close, false, QSize(400, 300)), _withAuto(type==ChooseWithAuto)
+{
+ setButtonOK(KGuiItem(i18n( "&Select"), "button_ok"));
+ QVBoxLayout *top = new QVBoxLayout(mainWidget(), 0, 10);
+
+ // view
+ QHBoxLayout *hbox = new QHBoxLayout(top, 10);
+ QVBoxLayout *vbox = new QVBoxLayout(hbox);
+ _listTypeCombo = new EnumComboBox<ListType>("list_type", mainWidget());
+ connect(_listTypeCombo->combo(), SIGNAL(activated(int)), SLOT(updateList()));
+ vbox->addWidget(_listTypeCombo->combo());
+ QPushButton *button = new KPushButton(KGuiItem(i18n("Reset Filters"), "reload"), mainWidget());
+ connect(button, SIGNAL(clicked()), SLOT(resetFilters()));
+ vbox->addWidget(button);
+ vbox->addStretch(1);
+
+ // filters
+ QFrame *frame = new QFrame(mainWidget());
+ frame->setFrameStyle(QFrame::Panel | QFrame::Raised);
+ frame->setMargin(5);
+ hbox->addWidget(frame);
+ hbox = new QHBoxLayout(frame, 10, 10);
+ QLabel *label = new QLabel(i18n("Filters:"), frame);
+ hbox->addWidget(label);
+ vbox = new QVBoxLayout(hbox);
+
+ QHBoxLayout *shbox = new QHBoxLayout(vbox);
+
+ // programmer filter
+ _programmerCombo = new KeyComboBox<QString>(frame);
+ _programmerCombo->appendItem("<all>", i18n("<Programmer>"));
+ Programmer::Lister::ConstIterator pit;
+ for (pit=Programmer::lister().begin(); pit!=Programmer::lister().end(); ++pit)
+ _programmerCombo->appendItem(pit.key(), pit.data()->label());
+ Config config;
+ const Programmer::Group *pgroup = config.programmerGroup();
+ if (pgroup) _programmerCombo->setCurrentItem(pgroup->name());
+ connect(_programmerCombo->widget(), SIGNAL(activated(int)), SLOT(updateList()));
+ shbox->addWidget(_programmerCombo->widget());
+
+ // tool filter
+ _toolCombo = new KeyComboBox<QString>(frame);
+ _toolCombo->appendItem("<all>", i18n("<Toolchain>"));
+ Tool::Lister::ConstIterator tit;
+ for (tit=Tool::lister().begin(); tit!=Tool::lister().end(); ++tit) {
+ if ( tit.data()->isCustom() ) continue;
+ _toolCombo->appendItem(tit.key(), tit.data()->label());
+ }
+ const Tool::Group *tgroup = config.toolGroup();
+ if (tgroup) _toolCombo->setCurrentItem(tgroup->name());
+ connect(_toolCombo->widget(), SIGNAL(activated(int)), SLOT(updateList()));
+ shbox->addWidget(_toolCombo->widget());
+
+ // memory filter
+ _memoryCombo = new EnumComboBox<Device::MemoryTechnology>(i18n("<Memory Type>"), "memory_technology", frame);
+ connect(_memoryCombo->combo(), SIGNAL(activated(int)), SLOT(updateList()));
+ shbox->addWidget(_memoryCombo->combo());
+
+ shbox->addStretch(1);
+ shbox = new QHBoxLayout(vbox);
+
+ // status filter
+ _statusCombo = new EnumComboBox<Device::Status>(i18n("<Status>"), "status", frame);
+ connect(_statusCombo->combo(), SIGNAL(activated(int)), SLOT(updateList()));
+ shbox->addWidget(_statusCombo->combo());
+
+ // features filter
+ _featureCombo = new EnumComboBox<Pic::Feature>(i18n("<Feature>"), "feature", frame);
+ connect(_featureCombo->combo(), SIGNAL(activated(int)), SLOT(updateList()));
+ shbox->addWidget(_featureCombo->combo());
+
+ shbox->addStretch(1);
+
+ // list view
+ QValueList<int> widths;
+ widths += 80;
+ widths += 500;
+ Splitter *splitter = new Splitter(widths, Horizontal, mainWidget(), "device_shooser_splitter");
+ top->addWidget(splitter, 1);
+ _listView = new KListView(splitter);
+ connect(_listView, SIGNAL(currentChanged(QListViewItem *)),
+ SLOT(currentChanged(QListViewItem *)));
+ connect(_listView, SIGNAL(doubleClicked(QListViewItem *, const QPoint &, int)),
+ SLOT(listDoubleClicked(QListViewItem *)));
+ _listView->setAllColumnsShowFocus(true);
+ _listView->setRootIsDecorated(true);
+ _listView->setSorting(-1);
+ _listView->addColumn(i18n("Device"));
+ _listView->setResizeMode(QListView::LastColumn);
+
+ // device view
+ _deviceView = new View(splitter);
+ connect(_deviceView, SIGNAL(deviceChanged(const QString &)),
+ SLOT(deviceChange(const QString &)));
+
+ updateList(device);
+}
+
+DeviceChooser::Dialog::~Dialog()
+{
+ Config config;
+ config.writeProgrammerGroup(programmerGroup());
+ config.writeToolGroup(toolGroup());
+ _listTypeCombo->writeConfig();
+ _memoryCombo->writeConfig();
+ _statusCombo->writeConfig();
+ _featureCombo->writeConfig();
+}
+
+QString DeviceChooser::Dialog::device() const
+{
+ QListViewItem *item = _listView->selectedItem();
+ if ( item==0 || !static_cast<ListItem *>(item)->isDevice() ) return Device::AUTO_DATA.name;
+ return item->text(0);
+}
+
+void DeviceChooser::Dialog::listDoubleClicked(QListViewItem *item)
+{
+ if ( item==0 ) return;
+ if ( !static_cast<ListItem *>(item)->isDevice() ) item->setOpen(!item->isOpen());
+ else accept();
+}
+
+void DeviceChooser::Dialog::currentChanged(QListViewItem *item)
+{
+ if ( item==0 || !static_cast<ListItem *>(item)->isDevice() ) _deviceView->clear();
+ else _deviceView->setDevice(item->text(0), false);
+}
+
+void DeviceChooser::Dialog::deviceChange(const QString &name)
+{
+ QListViewItemIterator it(_listView);
+ for (; it.current(); ++it)
+ if ( it.current()->text(0)==name ) {
+ _listView->setSelected(it.current(), true);
+ _listView->ensureItemVisible(it.current());
+ break;
+ }
+}
+
+void DeviceChooser::Dialog::resetFilters()
+{
+ _programmerCombo->setCurrentItem("<all>");
+ _toolCombo->setCurrentItem("<all>");
+ _memoryCombo->reset();
+ _statusCombo->reset();
+ _featureCombo->reset();
+ updateList();
+}
+
+void DeviceChooser::Dialog::updateList()
+{
+ QListViewItem *item = _listView->selectedItem();
+ QString device = (item ? item->text(0) : QString::null);
+ _listView->clear();
+ updateList(device);
+}
+
+const Programmer::Group *DeviceChooser::Dialog::programmerGroup() const
+{
+ return Programmer::lister().group(_programmerCombo->currentItem());
+}
+
+const Tool::Group *DeviceChooser::Dialog::toolGroup() const
+{
+ return Tool::lister().group(_toolCombo->currentItem());
+}
+
+void DeviceChooser::Dialog::updateList(const QString &device)
+{
+ QValueVector<QString> list = Device::lister().supportedDevices();
+ QMap<QString, KListViewItem *> groups;
+ QListViewItem *selected = 0;
+ const Programmer::Group *pgroup = programmerGroup();
+ if ( pgroup && pgroup->supportedDevices().isEmpty() && pgroup->isSoftware() ) {
+ _deviceView->setText(i18n("Could not detect supported devices for \"%1\". Please check installation.").arg(pgroup->label()));
+ return;
+ }
+ const Tool::Group *tgroup = toolGroup();
+ if ( tgroup && tgroup->supportedDevices().isEmpty() ) {
+ _deviceView->setText(i18n("Could not detect supported devices for toolchain \"%1\". Please check installation.").arg(tgroup->label()));
+ return;
+ }
+ for (int i=list.count()-1; i>=0; i--) {
+ if ( pgroup && !pgroup->isSupported(list[i]) ) continue;
+ if ( tgroup && !tgroup->isSupported(list[i]) ) continue;
+ const Device::Data *data = Device::lister().data(list[i]);
+ Q_ASSERT(data);
+ if ( _memoryCombo->value()!=Device::MemoryTechnology::Nb_Types && data->memoryTechnology()!=_memoryCombo->value() ) continue;
+ if ( _statusCombo->value()!=Device::Status::Nb_Types && data->status()!=_statusCombo->value() ) continue;
+ if ( _featureCombo->value()!=Pic::Feature::Nb_Types ) {
+ if ( data->group().name()!="pic" ) continue;
+ if ( !static_cast<const Pic::Data *>(data)->hasFeature(_featureCombo->value()) ) continue;
+ }
+ KListViewItem *item = 0;
+ switch (_listTypeCombo->value().type()) {
+ case ListType::FamilyTree: {
+ QString gname = data->listViewGroup();
+ if ( !groups.contains(gname) )
+ groups[gname] = new ListItem(_listView, gname, false, false);
+ item = new ListItem(groups[gname], list[i]);
+ break;
+ }
+ case ListType::Flat:
+ item = new ListItem(_listView, list[i], true, true);
+ break;
+ case ListType::Nb_Types: Q_ASSERT(false); break;
+ }
+ if ( device==list[i] ) selected = item;
+ }
+ if (_withAuto) (void)new ListItem(_listView, i18n(Device::AUTO_DATA.label), true, false);
+ if ( selected==0 ) selected = _listView->firstChild();
+ if (selected) {
+ _listView->setSelected(selected, true);
+ _listView->ensureItemVisible(selected);
+ currentChanged(selected);
+ }
+}
+
+//-----------------------------------------------------------------------------
+DeviceChooser::ComboBox::ComboBox(bool withAuto, QWidget *parent)
+ : QComboBox(parent, "device_chooser_combo"), _withAuto(withAuto)
+{
+ if (withAuto) insertItem(i18n(Device::AUTO_DATA.label));
+ Device::Lister::ConstIterator it;
+ for (it=Device::lister().begin(); it!=Device::lister().end(); ++it) {
+ QValueVector<QString> devices = it.data()->supportedDevices();
+ qHeapSort(devices);
+ for (uint k=0; k<devices.count(); k++) insertItem(devices[k]);
+ }
+}
+
+void DeviceChooser::ComboBox::setDevice(const QString &device, const Device::Data *data)
+{
+ QString text = device;
+ if ( device.isEmpty() || device==Device::AUTO_DATA.name ) {
+ if (_withAuto) text = QString::null;
+ else text = Device::lister().supportedDevices()[0];
+ }
+ if ( text.isEmpty() ) {
+ if (data) changeItem(data->name() + " " + i18n(Device::AUTO_DATA.label), 0);
+ else changeItem(i18n(Device::AUTO_DATA.label), 0);
+ setCurrentItem(0);
+ } else setCurrentText(text);
+}
+
+QString DeviceChooser::ComboBox::device() const
+{
+ if ( _withAuto && currentItem()==0 ) return Device::AUTO_DATA.name;
+ return currentText();
+}
+
+//-----------------------------------------------------------------------------
+DeviceChooser::Button::Button(bool withAuto, QWidget *parent)
+ : QWidget(parent, "device_chooser_button")
+{
+ QHBoxLayout *hbox = new QHBoxLayout(this, 0, 10);
+ _combo = new ComboBox(withAuto, this);
+ connect(_combo, SIGNAL(activated(int)), SIGNAL(changed()));
+ hbox->addWidget(_combo);
+ KIconLoader loader;
+ QIconSet iconset = loader.loadIcon("fileopen", KIcon::Toolbar);
+ KPushButton *button = new KPushButton(iconset, QString::null, this);
+ connect(button, SIGNAL(clicked()), SLOT(chooseDevice()));
+ hbox->addWidget(button);
+}
+
+void DeviceChooser::Button::chooseDevice()
+{
+ Dialog dialog(_combo->device(), (_combo->withAuto() ? ChooseWithAuto : Choose), this);
+ if ( !dialog.exec() || dialog.device().isEmpty() ) return;
+ _combo->setDevice(dialog.device());
+ emit changed();
+}
+
+//-----------------------------------------------------------------------------
+DeviceChooser::Browser::Browser(QWidget *parent)
+ : KTextBrowser(parent, "device_browser")
+{}
+
+PURL::Url findDocumentUrl(const QString &prefix, const QString &baseName)
+{
+ PURL::Url previous = KURL::fromPathOrURL(prefix + baseName + ".pdf");
+ bool previousExists = previous.exists();
+ for (uint i=0; i<26; i++) {
+ PURL::Url url = KURL::fromPathOrURL(prefix + baseName + QChar('a' + i) + ".pdf");
+ bool exists = url.exists();
+ if ( !exists && previousExists ) return previous;
+ previous = url;
+ previousExists = exists;
+ }
+ return previous;
+}
+
+void DeviceChooser::Browser::setSource(const QString &name)
+{
+ ::BusyCursor bc;
+ if ( name.startsWith("device://") ) emit deviceChanged(name.mid(9));
+ else if ( name.startsWith("document://") ) {
+ QString prefix = "http://ww1.microchip.com/downloads/en/DeviceDoc/";
+ PURL::Url url = findDocumentUrl(prefix, name.mid(11, name.length()-11-1));
+ KTextBrowser::setSource(url.kurl().htmlURL());
+ }
+ else KTextBrowser::setSource(name);
+}
+
+//-----------------------------------------------------------------------------
+DeviceChooser::View::View(QWidget *parent)
+ : TabWidget(parent, "device_view")
+{
+ // Information
+ _info = new Browser(this);
+ _info->setMimeSourceFactory(&_msf);
+ insertTab(_info, i18n("Information"));
+ connect(_info, SIGNAL(deviceChanged(const QString &)),
+ SIGNAL(deviceChanged(const QString &)));
+
+ // Memory Map
+ _memory = new Browser(this);
+ _memory->setMimeSourceFactory(&_msf);
+ insertTab(_memory, i18n("Memory Map"));
+
+ // Voltage-Frequency Graphs
+ _vfg = new Browser(this);
+ _vfg->setMimeSourceFactory(&_msf);
+ insertTab(_vfg, i18n("Voltage-Frequency Graphs"));
+
+ // Pin Diagrams
+ _pins = new Browser(this);
+ _pins->setMimeSourceFactory(&_msf);
+ insertTab(_pins, i18n("Pin Diagrams"));
+}
+
+void DeviceChooser::View::setDevice(const QString &name, bool cannotChangeDevice)
+{
+ const Device::Data *data = Device::lister().data(name);
+ if ( data==0 ) return;
+ QString doc = htmlInfo(*data, (cannotChangeDevice ? QString::null : "device:%1"), Device::documentHtml(*data));
+ doc += Device::supportedHtmlInfo(*data);
+ _info->setText("<html><body>" + doc + "</body></html>");
+ doc = htmlVoltageFrequencyGraphs(*data, QString::null, &_msf);
+ QPixmap pix = data->group().memoryGraph(*data);
+ QString label = data->name() + "_memory_map.png";
+ _msf.setPixmap(label, pix);
+ _memory->setText("<html><body><img src=\"" + label + "\" /></body></html>");
+ _vfg->setText("<html><body>" + doc + "</body></html>");
+ doc = htmlPinDiagrams(*data, QString::null, &_msf);
+ _pins->setText("<html><body>" + doc + "</body></html>");
+}
+
+void DeviceChooser::View::setText(const QString &text)
+{
+ _info->setText(text);
+ _vfg->setText(text);
+ _pins->setText(text);
+}
+
+void DeviceChooser::View::clear()
+{
+ _info->clear();
+ _vfg->clear();
+ _pins->clear();
+}
+
+//-----------------------------------------------------------------------------
+DeviceChooser::Editor::Editor(const QString &title, const QString &tag, QWidget *widget)
+ : DeviceEditor(title, tag, widget, "device_view_editor")
+{}
+
+QWidget *DeviceChooser::Editor::createView(const Device::Data *, QWidget *parent)
+{
+ DeviceChooser::View *view = new DeviceChooser::View(parent);
+ connect(view, SIGNAL(deviceChanged(const QString &)), SIGNAL(deviceChanged(const QString &)));
+ view->setDevice(_device, true);
+ return view;
+}
diff --git a/src/libgui/device_gui.h b/src/libgui/device_gui.h
new file mode 100644
index 0000000..a10c58a
--- /dev/null
+++ b/src/libgui/device_gui.h
@@ -0,0 +1,205 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef DEVICE_GUI_H
+#define DEVICE_GUI_H
+
+#include <qpushbutton.h>
+#include <qlayout.h>
+#include <qcombobox.h>
+class QListViewItem;
+class QCheckBox;
+#include <ktextbrowser.h>
+class KListView;
+
+#include "common/gui/key_gui.h"
+#include "common/gui/dialog.h"
+#include "device_editor.h"
+#include "devices/pic/base/pic.h"
+namespace Programmer { class Group; }
+namespace Tool { class Group; }
+
+namespace DeviceChooser
+{
+
+enum Type { Choose, ChooseWithAuto };
+class View;
+
+BEGIN_DECLARE_ENUM(ListType)
+ FamilyTree = 0, Flat
+END_DECLARE_ENUM_STD(ListType)
+
+//-----------------------------------------------------------------------------
+class Config : public GenericConfig
+{
+public:
+ Config() : GenericConfig("device_chooser") {}
+ const Programmer::Group *programmerGroup();
+ void writeProgrammerGroup(const Programmer::Group *group);
+ const Tool::Group *toolGroup();
+ void writeToolGroup(const Tool::Group *group);
+};
+
+//-----------------------------------------------------------------------------
+template <typename Enum>
+class EnumComboBox
+{
+public:
+ EnumComboBox(const QString &key, QWidget *parent) : _key(key) {
+ _combo = new QComboBox(parent);
+ for (Enum type; type<Enum::Nb_Types; ++type) _combo->insertItem(type.label());
+ Config config;
+ Enum type = config.readEnumEntry(key, Enum(Enum::Nb_Types));
+ if ( type!=Enum::Nb_Types ) _combo->setCurrentItem(type.type());
+ }
+ EnumComboBox(const QString &emptyLabel, const QString &key, QWidget *parent) : _key(key) {
+ _combo = new QComboBox(parent);
+ _combo->insertItem(emptyLabel);
+ for (Enum type; type<Enum::Nb_Types; ++type) _combo->insertItem(type.label());
+ Config config;
+ Enum type = config.readEnumEntry(key, Enum(Enum::Nb_Types));
+ if ( type!=Enum::Nb_Types ) _combo->setCurrentItem(type.type()+1);
+ }
+ QComboBox *combo() { return _combo; }
+ Enum value() const {
+ if ( _combo->count()==Enum::Nb_Types ) return typename Enum::Type(_combo->currentItem());
+ if ( _combo->currentItem()==0 ) return Enum::Nb_Types;
+ return typename Enum::Type(_combo->currentItem()-1);
+ }
+ void reset() { _combo->setCurrentItem(0); }
+ void writeConfig() {
+ Config config;
+ config.writeEnumEntry(_key, value());
+ }
+
+private:
+ QString _key;
+ QComboBox *_combo;
+};
+
+//-----------------------------------------------------------------------------
+class Dialog : public ::Dialog
+{
+Q_OBJECT
+public:
+ Dialog(const QString &device, Type type, QWidget *parent);
+ virtual ~Dialog();
+
+ QString device() const;
+
+private slots:
+ void listDoubleClicked(QListViewItem *item);
+ void currentChanged(QListViewItem *item);
+ void deviceChange(const QString &device);
+ void updateList();
+ void resetFilters();
+
+private:
+ bool _withAuto;
+ KeyComboBox<QString> *_programmerCombo, *_toolCombo;
+ EnumComboBox<ListType> *_listTypeCombo;
+ EnumComboBox<Device::MemoryTechnology> *_memoryCombo;
+ EnumComboBox<Device::Status> *_statusCombo;
+ EnumComboBox<Pic::Feature> *_featureCombo;
+ KListView *_listView;
+ View *_deviceView;
+
+ void updateList(const QString &device);
+ const Programmer::Group *programmerGroup() const;
+ const Tool::Group *toolGroup() const;
+};
+
+//-----------------------------------------------------------------------------
+class ComboBox : public QComboBox
+{
+Q_OBJECT
+public:
+ ComboBox(bool withAuto, QWidget *parent);
+ void setDevice(const QString &device, const Device::Data *data = 0);
+ QString device() const;
+ bool withAuto() const { return _withAuto; }
+
+private:
+ bool _withAuto;
+};
+
+//-----------------------------------------------------------------------------
+class Button : public QWidget
+{
+Q_OBJECT
+public:
+ Button(bool withAuto, QWidget *parent);
+ void setDevice(const QString &device) { _combo->setDevice(device); }
+ QString device() const { return _combo->device(); }
+
+signals:
+ void changed();
+
+private slots:
+ void chooseDevice();
+
+private:
+ ComboBox *_combo;
+};
+
+//-----------------------------------------------------------------------------
+class Browser : public KTextBrowser
+{
+Q_OBJECT
+public:
+ Browser(QWidget *parent);
+
+signals:
+ void deviceChanged(const QString &device);
+
+public slots:
+ virtual void setSource(const QString &name);
+};
+
+//-----------------------------------------------------------------------------
+class View : public TabWidget
+{
+Q_OBJECT
+public:
+ View(QWidget *parent);
+ void clear();
+ void setText(const QString &text);
+ void setDevice(const QString &name, bool cannotChangeDevice);
+
+signals:
+ void deviceChanged(const QString &device);
+
+private:
+ QMimeSourceFactory _msf;
+ Browser *_info, *_memory, *_vfg, *_pins;
+};
+
+//-----------------------------------------------------------------------------
+class Editor : public DeviceEditor
+{
+Q_OBJECT
+public:
+ Editor(const QString &title, const QString &tag, QWidget *parent);
+ virtual bool isModified() const { return false; }
+ virtual bool isReadOnly() const { return true; }
+ virtual void addGui() {}
+ virtual void removeGui() {}
+ virtual void setFocus() {}
+
+signals:
+ void deviceChanged(const QString &device);
+
+private:
+ virtual QWidget *createView(const Device::Data *data, QWidget *parent);
+ virtual void setModifiedInternal(bool) {}
+ virtual void setReadOnlyInternal(bool) {}
+};
+
+} // namespace
+
+#endif
diff --git a/src/libgui/editor.cpp b/src/libgui/editor.cpp
new file mode 100644
index 0000000..c64d98f
--- /dev/null
+++ b/src/libgui/editor.cpp
@@ -0,0 +1,91 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "editor.h"
+
+#include <klocale.h>
+
+#include "common/gui/purl_gui.h"
+#include "common/gui/misc_gui.h"
+
+Editor::Editor(const QString &title, const QString &tag, QWidget *parent, const char *name)
+ : QWidget(parent, name), _title(title), _tag(tag)
+{}
+
+Editor::Editor(QWidget *parent, const char *name)
+ : QWidget(parent, name)
+{}
+
+QSizePolicy Editor::sizePolicy() const
+{
+ return QSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
+}
+
+void Editor::setModified(bool m)
+{
+ setModifiedInternal(m);
+ if (m) emit modified();
+}
+
+void Editor::setReadOnly(bool ro)
+{
+ setReadOnlyInternal(ro);
+ emit guiChanged();
+}
+
+bool Editor::save()
+{
+ if ( url().isEmpty() ) return saveAs();
+ if ( !save(url()) ) return false;
+ setModified(false);
+ emit guiChanged();
+ return true;
+}
+
+bool Editor::saveAs()
+{
+ QString filter = PURL::filter(fileType());
+ PURL::Url purl = PURL::getSaveUrl(":save_file_as", filter, this, i18n("Save File"), PURL::AskOverwrite);
+ if ( purl.isEmpty() ) return false;
+ if ( !save(purl) ) return false;
+ setModified(false);
+ emit guiChanged();
+ return true;
+}
+
+bool Editor::slotLoad()
+{
+ bool readOnly = isReadOnly();
+ if ( !open(url()) ) return false;
+ setModified(false);
+ setReadOnly(readOnly);
+ statusChanged();
+ emit guiChanged();
+ return true;
+}
+
+QString Editor::filename() const
+{
+ return (url().isEmpty() ? "<" + _title + ">" : "\"" + url().filepath() + "\"");
+}
+
+bool Editor::checkSaved()
+{
+ if ( !isModified() ) return true;
+ MessageBox::Result res = MessageBox::questionYesNoCancel(i18n("File %1 not saved.").arg(filename()),
+ KStdGuiItem::save(), KStdGuiItem::discard());
+ if ( res==MessageBox::Cancel ) return false;
+ if ( res==MessageBox::Yes ) save();
+ return true;
+}
+
+bool Editor::reload()
+{
+ if ( !checkSaved() ) return false;
+ return slotLoad();
+}
diff --git a/src/libgui/editor.h b/src/libgui/editor.h
new file mode 100644
index 0000000..9247c80
--- /dev/null
+++ b/src/libgui/editor.h
@@ -0,0 +1,68 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef EDITOR_H
+#define EDITOR_H
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <qvaluevector.h>
+#include "common/common/qflags.h"
+#include <kstdaction.h>
+class KPopupMenu;
+
+#include "common/global/purl.h"
+
+class Editor : public QWidget
+{
+Q_OBJECT
+public:
+ Editor(const QString &title, const QString &tag, QWidget *parent, const char *name);
+ Editor(QWidget *parent, const char *name);
+ virtual QSizePolicy sizePolicy() const;
+ virtual PURL::FileType fileType() const = 0;
+ virtual bool isModified() const = 0;
+ void setModified(bool modified);
+ virtual PURL::Url url() const = 0;
+ QString name() const { return _title; }
+ QString tag() const { return _tag; }
+ void setReadOnly(bool readOnly);
+ virtual bool isReadOnly() const = 0;
+ bool checkSaved();
+ bool reload();
+ virtual void setFocus() = 0;
+ virtual bool open(const PURL::Url &url) = 0;
+ virtual bool save(const PURL::Url &url) = 0;
+ virtual void addGui() = 0;
+ virtual void removeGui() = 0;
+ virtual QValueList<uint> bookmarkLines() const = 0;
+ virtual void setBookmarkLines(const QValueList<uint> &lines) = 0;
+
+public slots:
+ bool slotLoad();
+ bool save();
+ bool saveAs();
+ void toggleReadOnly() { setReadOnly(!isReadOnly()); }
+ virtual void statusChanged() = 0;
+
+signals:
+ void modified();
+ void guiChanged();
+ void statusTextChanged(const QString &text);
+ void dropEventPass(QDropEvent *e);
+
+protected:
+ QString filename() const;
+ virtual void setModifiedInternal(bool modified) = 0;
+ virtual void setReadOnlyInternal(bool readOnly) = 0;
+
+private:
+ QString _title, _tag;
+};
+
+#endif
diff --git a/src/libgui/editor_manager.cpp b/src/libgui/editor_manager.cpp
new file mode 100644
index 0000000..2a42554
--- /dev/null
+++ b/src/libgui/editor_manager.cpp
@@ -0,0 +1,506 @@
+/***************************************************************************
+ * 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 "editor_manager.h"
+
+#include <qiconset.h>
+#include <qdragobject.h>
+#include <qpainter.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <kaction.h>
+
+#include "text_editor.h"
+#include "hex_editor.h"
+#include "object_view.h"
+#include "new_dialogs.h"
+#include "main_global.h"
+#include "gui_debug_manager.h"
+#include "common/gui/purl_gui.h"
+#include "device_gui.h"
+#include "register_view.h"
+#include "device_editor.h"
+#include "project_manager.h"
+#include "global_config.h"
+#include "project.h"
+
+//-----------------------------------------------------------------------------
+SwitchToDialog::SwitchToDialog(const QStringList &names, QWidget *parent)
+ : Dialog(parent, "switch_to_dialog", true, i18n("Switch to editor"), Ok | Cancel, Ok, false)
+{
+ QVBoxLayout *top = new QVBoxLayout(mainWidget(), 10, 10);
+ _edit = new KLineEdit(mainWidget());
+ _edit->setCompletedItems(names);
+ top->addWidget(_edit);
+}
+
+//-----------------------------------------------------------------------------
+void EditorTabBar::paintLabel(QPainter *p, const QRect &br, QTab *t, bool has_focus) const
+{
+ QFont f = p->font();
+ f.setItalic(_readOnly[t]);
+ p->setFont(f);
+ QTabBar::paintLabel(p, br, t, has_focus);
+}
+
+//-----------------------------------------------------------------------------
+QString EditorHistory::goBack()
+{
+ if ( !hasBack() ) return QString::null;
+ _current--;
+ return _names[_current];
+}
+
+QString EditorHistory::goForward()
+{
+ if ( !hasForward() ) return QString::null;
+ _current++;
+ return _names[_current];
+}
+
+void EditorHistory::add(const QString &name)
+{
+ if ( _names.count()!=0 ) {
+ _current = QMIN(_current, _names.count()-1);
+ if ( _names[_current]==name ) return;
+ if ( _current!=0 && _names[_current-1]==name ) {
+ _current--;
+ return;
+ }
+ _current++;
+ if ( _current<_names.count() && _names[_current]==name ) return;
+ }
+ _names.resize(_current+1);
+ _names[_current] = name;
+}
+
+void EditorHistory::closedLast()
+{
+ if ( _names.count()==0 ) return;
+ _names.resize(_current);
+ if ( _current!=0 ) _current--;
+}
+
+//-----------------------------------------------------------------------------
+const char * const EditorManager::EDITOR_TAGS[Nb_EditorTypes] = { "device", "registers" };
+
+EditorManager::EditorManager(QWidget *parent)
+ : TabWidget(parent, "editor_manager"), _current(0)
+{
+ setTabBar(new EditorTabBar(this));
+ connect(this, SIGNAL(currentChanged(QWidget *)), SLOT(showEditor(QWidget *)));
+ setHoverCloseButton(readConfigEntry(BaseGlobalConfig::ShowTabCloseButton).toBool());
+ setHoverCloseButtonDelayed(false);
+}
+
+bool EditorManager::openFile(const PURL::Url &url)
+{
+ if ( url.isEmpty() ) return false;
+ Editor *e = findEditor(url);
+ if (e) { // document already loaded
+ if ( !MessageBox::askContinue(i18n("File \"%1\" already loaded. Reload?").arg(url.kurl().prettyURL()),
+ i18n("Warning"), i18n("Reload")) ) return true;
+ if ( !e->slotLoad() ) {
+ closeEditor(e, false);
+ return false;
+ }
+ return true;
+ }
+ if ( !openEditor(url) ) {
+ static_cast< KRecentFilesAction *>(Main::action("file_open_recent"))->removeURL(url.kurl());
+ return false;
+ }
+ static_cast<KRecentFilesAction *>(Main::action("file_open_recent"))->addURL(url.kurl());
+ return true;
+}
+
+void EditorManager::connectEditor(Editor *editor)
+{
+ disconnectEditor(currentEditor());
+ if ( editor==0 ) return;
+ editor->addGui();
+ connect(editor, SIGNAL(modified()), SLOT(modifiedSlot()));
+ connect(editor, SIGNAL(guiChanged()), SIGNAL(guiChanged()));
+ connect(editor, SIGNAL(dropEventPass(QDropEvent *)), SLOT(slotDropEvent(QDropEvent *)));
+ connect(editor, SIGNAL(statusTextChanged(const QString &)), SIGNAL(statusChanged(const QString &)));
+}
+
+void EditorManager::modifiedSlot()
+{
+ emit modified(currentEditor()->url());
+}
+
+void EditorManager::disconnectEditor(Editor *editor)
+{
+ if ( editor==0 ) return;
+ editor->disconnect(this);
+ editor->removeGui();
+}
+
+QString EditorManager::title(const Editor &e) const
+{
+ return (e.url().isEmpty() ? "<" + e.name() + ">" : e.url().filename());
+}
+
+void EditorManager::updateTitles()
+{
+ KIconLoader loader;
+ QPixmap def = loader.loadIcon("piklab", KIcon::Small);
+ QPixmap modified = loader.loadIcon("filesave", KIcon::Small);
+ QPixmap chip = loader.loadIcon("piklab_chip", KIcon::Small);
+ QValueList<Editor *>::iterator it = _editors.begin();
+ for (; it!=_editors.end(); ++it) {
+ static_cast<EditorTabBar *>(tabBar())->setReadOnly(indexOf(*it), (*it)->isReadOnly());
+ QPixmap pixmap;
+ if ( (*it)->isModified() ) pixmap = modified;
+ else if ( ::qt_cast< ::DeviceEditor *>(*it)==0 ) pixmap = PURL::icon((*it)->fileType());
+ else pixmap = chip;
+ changeTab(*it, pixmap.isNull() ? def : pixmap, title(**it));
+ }
+}
+
+bool EditorManager::closeCurrentEditor()
+{
+ if ( !closeEditor(_current, true) ) return false;
+ emit guiChanged();
+ return true;
+}
+
+bool EditorManager::closeAllEditors()
+{
+ if ( currentEditor()==0 ) return true;
+ while ( currentEditor() )
+ if ( !closeEditor(currentEditor(), true) ) break;
+ emit guiChanged();
+ return ( currentEditor()==0 );
+}
+
+bool EditorManager::closeAllOtherEditors()
+{
+ if ( nbEditors()==1 ) return true;
+ QValueList<Editor *> list = _editors;
+ list.remove(currentEditor());
+ QValueList<Editor *>::iterator it = list.begin();
+ bool ok = true;
+ for (; it!=list.end(); ++it) {
+ if ( !closeEditor(*it, true) ) {
+ ok = false;
+ break;
+ }
+ }
+ emit guiChanged();
+ return ok;
+}
+
+bool EditorManager::closeEditor(const PURL::Url &url)
+{
+ Editor *e = findEditor(url);
+ if ( e==0 ) return true;
+ if ( !closeEditor(e, true) ) return false;
+ emit guiChanged();
+ return true;
+}
+
+void EditorManager::closeRequest(int i)
+{
+ closeEditor(static_cast<Editor *>(page(i)), true);
+ emit guiChanged();
+}
+
+bool EditorManager::closeEditor(Editor *e, bool ask)
+{
+ if ( e==0 ) return true;
+ if ( ask && !e->checkSaved() ) return false;
+ removePage(e);
+ _editors.remove(e);
+ Editor *g = static_cast<Editor *>(currentPage());
+ changeToEditor(g);
+ saveBookmarks(*e);
+ delete e;
+ return true;
+}
+
+void EditorManager::saveBookmarks(const Editor &e)
+{
+ if ( Main::project()==0 ) return;
+ QValueList<uint> lines = e.bookmarkLines();
+ Main::project()->setBookmarkLines(e.url(), lines);
+}
+
+void EditorManager::restoreBookmarks(Editor &e)
+{
+ if ( Main::project()==0 ) return;
+ QValueList<uint> lines = Main::project()->bookmarkLines(e.url());
+ e.setBookmarkLines(lines);
+}
+
+void EditorManager::showEditor(Editor *e)
+{
+ changeToEditor(e);
+ emit guiChanged();
+}
+
+void EditorManager::changeToEditor(Editor *e)
+{
+ if ( e==_current ) return;
+ connectEditor(e);
+ _current = e;
+ if (e) {
+ showPage(e);
+ e->clearFocus(); // force a got focus signal
+ e->setFocus();
+ e->statusChanged();
+ _history.add(name(*e));
+ } else {
+ emit statusChanged(QString::null);
+ _history.closedLast();
+ }
+}
+
+Editor *EditorManager::findEditor(const QString &tag)
+{
+ QValueList<Editor *>::iterator it = _editors.begin();
+ for (; it!=_editors.end(); ++it) if ( (*it)->tag()==tag ) return *it;
+ return 0;
+}
+
+Editor *EditorManager::findEditor(const PURL::Url &url)
+{
+ QValueList<Editor *>::iterator it = _editors.begin();
+ for (; it!=_editors.end(); ++it) if ( (*it)->url()==url ) return *it;
+ return 0;
+}
+
+Editor *EditorManager::createEditor(PURL::FileType type, const PURL::Url &url)
+{
+ Editor *e = findEditor(url);
+ if (e) closeEditor(e, false);
+ switch (type.type()) {
+ case PURL::Hex:
+ e = new HexEditor(this);
+ break;
+ case PURL::CSource:
+ case PURL::CppSource:
+ case PURL::CHeader:
+ case PURL::AsmGPAsm:
+ case PURL::AsmPIC30:
+ case PURL::AsmPICC:
+ case PURL::Inc:
+ case PURL::JalSource:
+ case PURL::BasicSource:
+ e = new TextEditor(true, this);
+ break;
+ case PURL::Lkr:
+ case PURL::Gld:
+ case PURL::Map:
+ case PURL::Lst:
+ case PURL::Cod:
+ case PURL::Unknown:
+ e = new TextEditor(false, this);
+ break;
+ case PURL::Coff:
+ if ( Main::project()==0 ) {
+ if ( Main::deviceData()==0 ) return 0;
+ e = new Coff::CoffEditor(url, *Main::deviceData(), this);
+ } else {
+ if ( Debugger::manager->coff()==0 ) return 0;
+ e = new Coff::CoffEditor(*Debugger::manager->coff(), this);
+ }
+ static_cast<Coff::CoffEditor *>(e)->setView(&Main::compileLog());
+ break;
+ case PURL::Object:
+ e = new Coff::ObjectEditor(url, this);
+ static_cast<Coff::ObjectEditor *>(e)->setView(&Main::compileLog());
+ break;
+ case PURL::Library:
+ e = new Coff::LibraryEditor(url, this);
+ static_cast<Coff::LibraryEditor *>(e)->setView(&Main::compileLog());
+ break;
+ case PURL::Elf:
+ case PURL::Project:
+ case PURL::PikdevProject:
+ case PURL::Nb_FileTypes: break;
+ }
+ return e;
+}
+
+void EditorManager::addEditor(Editor *e)
+{
+ QValueList<Editor *>::iterator it = _editors.begin();
+ for (; it!=_editors.end(); ++it) if ( *it==e ) return;
+ _editors.append(e);
+ addTab(e, QString::null);
+ setTabEnabled(e, true);
+ restoreBookmarks(*e);
+ showEditor(e);
+}
+
+void EditorManager::slotDropEvent(QDropEvent *event)
+{
+ QStringList urls;
+ if ( !QUriDrag::decodeLocalFiles(event, urls)) return;
+ QStringList::const_iterator it = urls.begin();
+ for(; it!=urls.end(); ++it) openEditor(PURL::Url::fromPathOrUrl(*it));
+}
+
+Editor *EditorManager::openEditor(const PURL::Url &url)
+{
+ Editor *e = findEditor(url);
+ if ( e==0 ) {
+ e = createEditor(url.fileType(), url);
+ if ( e==0 ) return 0;
+ if ( !e->open(url) ) {
+ closeEditor(e, false);
+ return 0;
+ }
+ addEditor(e);
+ } else showEditor(e);
+ return e;
+}
+
+void EditorManager::saveAllFiles()
+{
+ QValueList<Editor *>::iterator it = _editors.begin();
+ for (; it!=_editors.end(); ++it) {
+ if ( !(*it)->isModified() ) continue;
+ (*it)->save();
+ }
+ emit guiChanged();
+}
+
+PURL::UrlList EditorManager::files() const
+{
+ PURL::UrlList names;
+ QValueList<Editor *>::const_iterator it = _editors.begin();
+ for(; it!=_editors.end(); ++it) {
+ if ( (*it)->url().isEmpty() ) continue;
+ names.push_back((*it)->url());
+ }
+ return names;
+}
+
+void EditorManager::contextMenu(int i, const QPoint &p)
+{
+ Editor *editor = static_cast<Editor *>(page(i));
+ if ( editor==0 ) return;
+
+ KIconLoader loader;
+ QPixmap closeIcon = loader.loadIcon("fileclose", KIcon::Small);
+ QPixmap saveIcon = loader.loadIcon("filesave", KIcon::Small);
+ QPixmap saveAsIcon = loader.loadIcon("filesaveas", KIcon::Small);
+ QPixmap reloadIcon = loader.loadIcon("reload", KIcon::Small);
+ KPopupMenu *popup = new KPopupMenu;
+ popup->insertTitle(title(*editor));
+ popup->insertItem(closeIcon, i18n("Close"), 1);
+ if ( nbEditors()>1 ) popup->insertItem(i18n("Close All Others"), 2);
+ if ( editor->isModified() ) popup->insertItem(saveIcon, i18n("Save"), 3);
+ popup->insertItem(saveAsIcon, i18n("Save As..."), 4);
+ if ( !editor->url().isEmpty() ) popup->insertItem(reloadIcon, i18n("Reload"), 5);
+ switch (popup->exec(p)) {
+ case 1: closeEditor(editor, true); break;
+ case 2: closeAllOtherEditors(); break;
+ case 3: editor->save(); break;
+ case 4: editor->saveAs(); break;
+ case 5: editor->reload(); break;
+ }
+ emit guiChanged();
+ delete popup;
+}
+
+void EditorManager::switchHeaderImplementation()
+{
+ if ( currentEditor()==0 ) return;
+ PURL::Url url = currentEditor()->url();
+ PURL::FileType type = url.fileType();
+ PURL::SourceFamily source = type.data().sourceFamily;
+ if ( type.data().group==PURL::Source ) type = source.data().headerType;
+ else {
+ Q_ASSERT( type.data().group==PURL::Source );
+ type = Main::toolGroup().implementationType(source.data().toolType);
+ }
+ if ( type==PURL::Nb_FileTypes ) return;
+ url = url.toFileType(type);
+ if ( !url.exists() ) return;
+ openEditor(url);
+}
+
+void EditorManager::switchToEditor()
+{
+ QStringList names;
+ for (uint i=0; i<_editors.count(); i++) names.append(title(*_editors[i]));
+ SwitchToDialog dialog(names, this);
+ if ( dialog.exec()!=QDialog::Accepted ) return;
+ for (uint i=0; i<names.count(); i++) {
+ if ( dialog.name()!=names[i] && dialog.name()!=QString("%1").arg(i+1) ) continue;
+ showEditor(_editors[i]);
+ return;
+ }
+}
+
+QString EditorManager::name(const Editor &e) const
+{
+ return (!e.name().isEmpty() ? e.name() : e.url().filepath());
+}
+
+void EditorManager::goBack()
+{
+ Q_ASSERT( _history.hasBack() );
+ QString s = _history.goBack();
+ for (uint i=0; i<_editors.count(); i++)
+ if ( s==name(*_editors[i]) ) showEditor(_editors[i]);
+}
+
+void EditorManager::goForward()
+{
+ Q_ASSERT( _history.hasForward() );
+ QString s = _history.goForward();
+ for (uint i=0; i<_editors.count(); i++)
+ if ( s==name(*_editors[i]) ) showEditor(_editors[i]);
+}
+
+Editor *EditorManager::openEditor(EditorType type)
+{
+ bool created = false;
+ Editor *e = 0;
+ QString tag = EDITOR_TAGS[type];
+ switch (type) {
+ case DeviceEditor: {
+ e = findEditor(tag);
+ if ( e==0 ) {
+ e = new DeviceChooser::Editor(i18n("Device"), tag, this);
+ static_cast<DeviceChooser::Editor *>(e)->setDevice(false);
+ static_cast<DeviceChooser::Editor *>(e)->setDevice(true); // #### needed to fix GUI glitch ???
+ created = true;
+ }
+ break;
+ }
+ case RegisterEditor: {
+ e = findEditor(tag);
+ if ( e==0 ) {
+ ::BusyCursor bc;
+ e = new Register::MainView(i18n("Registers"), tag);
+ static_cast<Debugger::GuiManager *>(Debugger::manager)->addRegisterView(*static_cast<Register::MainView *>(e));
+ created = true;
+ }
+ break;
+ }
+ case Nb_EditorTypes: Q_ASSERT(false); break;
+ }
+ if ( e==0 ) return 0;
+ if (created) {
+ if ( !e->slotLoad() ) {
+ delete e;
+ return 0;
+ }
+ addEditor(e);
+ } else showEditor(e);
+ return e;
+}
diff --git a/src/libgui/editor_manager.h b/src/libgui/editor_manager.h
new file mode 100644
index 0000000..0d180b9
--- /dev/null
+++ b/src/libgui/editor_manager.h
@@ -0,0 +1,128 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef EDITOR_MANAGER_H
+#define EDITOR_MANAGER_H
+
+class QEvent;
+#include <ktabbar.h>
+#include <ktabwidget.h>
+#include <klineedit.h>
+
+#include "text_editor.h"
+#include "common/gui/misc_gui.h"
+#include "common/gui/dialog.h"
+
+//-----------------------------------------------------------------------------
+class SwitchToDialog : public Dialog
+{
+Q_OBJECT
+public:
+ SwitchToDialog(const QStringList &names, QWidget *parent);
+ QString name() const { return _edit->text(); }
+
+private:
+ KLineEdit *_edit;
+};
+
+//-----------------------------------------------------------------------------
+class EditorTabBar : public TabBar
+{
+Q_OBJECT
+public:
+ EditorTabBar(QWidget *parent) : TabBar(parent, "editor_tab_bar") {}
+ void setReadOnly(uint index, bool readOnly) { _readOnly[tabAt(index)] = readOnly; }
+
+private:
+ QMap<QTab *, bool> _readOnly;
+ virtual void paintLabel(QPainter *p, const QRect &br, QTab *t, bool has_focus) const;
+};
+
+//-----------------------------------------------------------------------------
+class EditorHistory
+{
+public:
+ EditorHistory() : _current(0) {}
+ bool hasBack() const { return _current!=0; }
+ bool hasForward() const { return (_current+1)<_names.count(); }
+ void add(const QString &name);
+ void closedLast();
+ QString goBack();
+ QString goForward();
+
+private:
+ uint _current;
+ QValueVector<QString> _names;
+};
+
+//-----------------------------------------------------------------------------
+class EditorManager : public TabWidget
+{
+Q_OBJECT
+public:
+ EditorManager(QWidget *parent);
+
+ PURL::UrlList files() const;
+ QValueList<Editor *> &editors() { return _editors; }
+ uint nbEditors() const { return _editors.count(); }
+ Editor *createEditor(PURL::FileType type, const PURL::Url &url);
+ void addEditor(Editor *e);
+ Editor *currentEditor() const { return _current; }
+ Editor *findEditor(const PURL::Url &file);
+ Editor *findEditor(const QString &tag);
+ void showEditor(Editor *e);
+ bool closeEditor(const PURL::Url &url);
+ bool closeEditor(Editor *e, bool ask);
+ bool openFile(const PURL::Url &url);
+ Editor *openEditor(const PURL::Url &url);
+ void connectEditor(Editor *editor);
+ void disconnectEditor(Editor *editor);
+ const EditorHistory &history() const { return _history; }
+ enum EditorType { DeviceEditor = 0, RegisterEditor, Nb_EditorTypes };
+ Editor *openEditor(EditorType type);
+
+public slots:
+ void updateTitles();
+ void slotDropEvent(QDropEvent *e);
+ void saveAllFiles();
+ bool closeCurrentEditor();
+ bool closeAllEditors();
+ bool closeAllOtherEditors();
+ void switchHeaderImplementation();
+ void switchToEditor();
+ void goBack();
+ void goForward();
+
+signals:
+ void modified(const PURL::Url &url);
+ void guiChanged();
+ void statusChanged(const QString &);
+
+private:
+ void changeToEditor(Editor *e);
+ void enableActions(bool enable);
+ QString title(const Editor &e) const;
+ QString name(const Editor &e) const;
+ virtual void contextMenu(int i, const QPoint &p);
+ void saveBookmarks(const Editor &e);
+ void restoreBookmarks(Editor &e);
+
+private slots:
+ void showEditor(QWidget *w) { showEditor(static_cast<Editor *>(w)); }
+ void closeRequest(int i);
+ void modifiedSlot();
+
+private:
+ Editor *_current;
+ QValueList<Editor *> _editors;
+ EditorHistory _history;
+ static const char * const EDITOR_TAGS[Nb_EditorTypes];
+};
+
+#endif
diff --git a/src/libgui/global_config.cpp b/src/libgui/global_config.cpp
new file mode 100644
index 0000000..8424450
--- /dev/null
+++ b/src/libgui/global_config.cpp
@@ -0,0 +1,106 @@
+/***************************************************************************
+ * Copyright (C) 2005 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 "global_config.h"
+
+#include <kapplication.h>
+#include <kconfig.h>
+#include <klocale.h>
+
+#include "progs/list/prog_list.h"
+#include "tools/list/tool_list.h"
+
+const BaseGlobalConfig::Data BaseGlobalConfig::DATA[Nb_Types] = {
+ { "auto_rebuild_modified", I18N_NOOP("Automatically rebuild project before programming if it is modified."), QVariant(true, 0) },
+ { "program_after_build", I18N_NOOP("Program device after successful build."), QVariant(false, 0) },
+ { "user_id_set_to_checksum", I18N_NOOP("Set User Ids to unprotected checksum (if User Ids are empty)."), QVariant(false, 0) },
+ { "show_tab_close_buttons", I18N_NOOP("Show close buttons on tabs (need restart to take effect)."), QVariant(true, 0) }
+};
+
+PURL::Url GlobalConfig::openedProject()
+{
+ GenericConfig config(QString::null);
+ return PURL::Url::fromPathOrUrl(config.readEntry("project", QString::null));
+}
+void GlobalConfig::writeOpenedProject(const PURL::Url &p)
+{
+ GenericConfig config(QString::null);
+ config.writeEntry("project", p.filepath());
+}
+
+PURL::UrlList GlobalConfig::openedFiles()
+{
+ GenericConfig config(QString::null);
+ PURL::UrlList files;
+ uint i = 0;
+ for (;;) {
+ QString file = config.readEntry(QString("file%1").arg(i), QString::null);
+ if ( file.isEmpty() ) break;
+ files += PURL::Url::fromPathOrUrl(file);
+ i++;
+ }
+ return files;
+}
+void GlobalConfig::writeOpenedFiles(const PURL::UrlList &files)
+{
+ GenericConfig config(QString::null);
+ for (uint i=0; i<=files.count(); i++) {
+ QString s = (i==files.count() ? QString::null : files[i].filepath());
+ config.writeEntry(QString("file%1").arg(i), s);
+ }
+}
+
+void GlobalConfig::writeProgrammerGroup(const Programmer::Group &group)
+{
+ GenericConfig config(QString::null);
+ config.writeEntry("programmer", group.name());
+}
+const Programmer::Group &GlobalConfig::programmerGroup()
+{
+ GenericConfig config(QString::null);
+ QString s = config.readEntry("programmer");
+ const Programmer::Group *group = Programmer::lister().group(s);
+ if ( group==0 ) return *Programmer::lister().begin().data();
+ return *group;
+}
+
+void GlobalConfig::writeDebugLevel(Log::DebugLevel level)
+{
+ GenericConfig config(QString::null);
+ config.writeEnumEntry<Log::DebugLevel>("log_debug_level", level);
+}
+Log::DebugLevel GlobalConfig::debugLevel()
+{
+ GenericConfig config(QString::null);
+ return config.readEnumEntry<Log::DebugLevel>("log_debug_level", Log::DebugLevel::Normal);
+}
+
+void GlobalConfig::writeLogOutputType(Log::OutputType type)
+{
+ GenericConfig config(QString::null);
+ config.writeEntry("log_output_type", type);
+}
+Log::OutputType GlobalConfig::logOutputType()
+{
+ GenericConfig config(QString::null);
+ uint output = config.readUIntEntry("log_output_type", Log::GuiOnly);
+ if ( output>=Log::Nb_OutputTypes ) return Log::GuiOnly;
+ return Log::OutputType(output);
+}
+
+void GlobalConfig::writeShowLineNumbers(bool show)
+{
+ GenericConfig config(QString::null);
+ config.writeEntry("show_line_numbers", show);
+}
+bool GlobalConfig::showLineNumbers()
+{
+ GenericConfig config(QString::null);
+ return config.readBoolEntry("show_line_numbers", false);
+}
diff --git a/src/libgui/global_config.h b/src/libgui/global_config.h
new file mode 100644
index 0000000..8e5cfaa
--- /dev/null
+++ b/src/libgui/global_config.h
@@ -0,0 +1,39 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef GLOBAL_CONFIG_H
+#define GLOBAL_CONFIG_H
+
+#include "progs/base/generic_prog.h"
+#include "common/global/purl.h"
+#include "tools/base/tool_group.h"
+#include "log_view.h"
+
+BEGIN_DECLARE_CONFIG(BaseGlobalConfig)
+ AutoRebuildModified, ProgramAfterBuild, UserIdSetToChecksum,
+ ShowTabCloseButton
+END_DECLARE_CONFIG(BaseGlobalConfig, "")
+
+namespace GlobalConfig
+{
+extern PURL::Url openedProject();
+extern void writeOpenedProject(const PURL::Url &p);
+extern PURL::UrlList openedFiles();
+extern void writeOpenedFiles(const PURL::UrlList &files);
+extern void writeProgrammerGroup(const Programmer::Group &group);
+extern const Programmer::Group &programmerGroup();
+extern void writeDebugLevel(Log::DebugLevel level);
+extern Log::DebugLevel debugLevel();
+extern void writeLogOutputType(Log::OutputType type);
+extern Log::OutputType logOutputType();
+extern void writeShowLineNumbers(bool show);
+extern bool showLineNumbers();
+} // namespace
+
+#endif
diff --git a/src/libgui/gui_debug_manager.cpp b/src/libgui/gui_debug_manager.cpp
new file mode 100644
index 0000000..adda68a
--- /dev/null
+++ b/src/libgui/gui_debug_manager.cpp
@@ -0,0 +1,249 @@
+/***************************************************************************
+ * 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 "gui_debug_manager.h"
+
+#include "toplevel.h"
+#include "text_editor.h"
+#include "project.h"
+#include "tools/list/compile_config.h"
+#include "register_view.h"
+#include "watch_view.h"
+#include "project_manager.h"
+#include "editor_manager.h"
+#include "main_global.h"
+#include "coff/base/text_coff.h"
+#include "progs/base/generic_prog.h"
+#include "gui_prog_manager.h"
+#include "breakpoint_view.h"
+#include "progs/base/prog_group.h"
+
+bool Debugger::GuiManager::addEditor(Editor &editor)
+{
+ if ( _editors.find(&editor)!=_editors.end() ) return false;
+ connect(&editor, SIGNAL(destroyed()), SLOT(editorDestroyed()));
+ _editors.append(&editor);
+ return true;
+}
+
+void Debugger::GuiManager::addRegisterView(Register::MainView &view)
+{
+ if ( !addEditor(view) ) return;
+ updateRegisters();
+}
+
+void Debugger::GuiManager::addTextEditor(TextEditor &editor)
+{
+ if ( !addEditor(editor) ) return;
+ updateView(false);
+}
+
+void Debugger::GuiManager::clearEditors()
+{
+ QValueList<Editor *>::iterator it = _editors.begin();
+ for (; it!=_editors.end(); ++it) (*it)->disconnect(this);
+ _editors.clear();
+}
+
+void Debugger::GuiManager::editorDestroyed()
+{
+ QValueList<Editor *>::iterator it = _editors.begin();
+ for (; it!=_editors.end(); ++it) {
+ if ( (*it)!=sender() ) continue;
+ _editors.remove(it);
+ break;
+ }
+}
+
+void Debugger::GuiManager::updateDevice()
+{
+ Manager::updateDevice();
+ Main::watchView().init(false);
+}
+
+PURL::Url Debugger::GuiManager::coffUrl() const
+{
+ return Main::projectManager().projectUrl().toFileType(PURL::Coff);
+}
+
+bool Debugger::GuiManager::internalInit()
+{
+ if ( !Manager::internalInit() ) return false;
+ if ( !Main::projectManager().contains(coffUrl()) )
+ Main::projectManager().addExternalFile(coffUrl(), ProjectManager::Generated);
+ Main::watchView().init(true);
+ if ( registerView() ) registerView()->view()->updateView();
+ return true;
+}
+
+bool Debugger::GuiManager::checkState(bool &first)
+{
+ if ( !Debugger::Manager::checkState(first) ) return false;
+ if ( first && !Main::toolGroup().generateDebugInformation(Main::device()) )
+ MessageBox::information(i18n("The toolchain in use does not generate all necessary debugging information with the selected device. This may reduce debugging capabilities."), Log::Show, "doesnt_generate_debug_information");
+ return true;
+}
+
+Breakpoint::Data Debugger::GuiManager::currentBreakpointData()
+{
+ const Breakpoint::Data *data = Main::breakpointsView().currentData();
+ if (data) return *data;
+ TextEditor *editor = ::qt_cast<TextEditor *>(Main::currentEditor());
+ Q_ASSERT(editor);
+ return Breakpoint::Data(editor->url(), editor->cursorLine());
+}
+
+void Debugger::GuiManager::toggleBreakpoint()
+{
+ if ( !Main::programmerGroup().isDebugger() ) {
+ MessageBox::sorry(i18n("You cannot set breakpoints when a debugger is not selected."), Log::Show);
+ return;
+ }
+ Breakpoint::Data data = currentBreakpointData();
+ if ( Breakpoint::list().contains(data) ) {
+ Breakpoint::list().remove(data);
+ return;
+ }
+ Address address;
+ if ( !checkBreakpoint(data, false, address) ) return;
+ Breakpoint::list().append(data);
+ Breakpoint::list().setAddress(data, address);
+ if (_coff) toggleEnableBreakpoint();
+}
+
+void Debugger::GuiManager::toggleEnableBreakpoint()
+{
+ Q_ASSERT(_coff);
+ Breakpoint::Data data = currentBreakpointData();
+ bool isActive = ( Breakpoint::list().state(data)==Breakpoint::Active );
+ if ( !Breakpoint::list().address(data).isValid() ) {
+ if ( !isActive ) MessageBox::sorry(i18n("Breakpoint at non-code line cannot be activated."), Log::Show);
+ } else {
+ if ( !isActive ) {
+ freeActiveBreakpoint();
+ Breakpoint::list().setState(data, Breakpoint::Active);
+ } else Breakpoint::list().setState(data, Breakpoint::Disabled);
+ }
+}
+
+void Debugger::GuiManager::updateEditorMarks(TextEditor &editor) const
+{
+ editor.clearBreakpointMarks();
+ // update breakpoints
+ bool reached = false;
+ for (uint i=0; i<Breakpoint::list().count(); i++) {
+ const Breakpoint::Data &data = Breakpoint::list().data(i);
+ int line = -1;
+ Address address = Breakpoint::list().address(data);
+ if ( _coff && address.isValid() ) line = _coff->lineForAddress(editor.url(), address);
+ else if ( data.url==editor.url() ) line = data.line;
+ Breakpoint::MarkType type = breakpointType(data);
+ if ( line!=-1 ) editor.setMark(line, type);
+ if ( type==Breakpoint::BreakpointReached ) reached = true;
+ }
+ // update pc
+ if ( _coff && programmer() && programmer()->isActive() && pc().isInitialized() && !reached
+ && _currentSourceLines.contains(editor.url()) ) {
+ int pcline = _currentSourceLines[editor.url()];
+ if ( programmer()->state()==Programmer::Halted ) editor.setMark(pcline, Breakpoint::ProgramCounterActive);
+ else editor.setMark(pcline, Breakpoint::ProgramCounterDisabled);
+ }
+}
+
+void Debugger::GuiManager::clear()
+{
+ Manager::clear();
+ Main::watchView().init(true);
+}
+
+bool Debugger::GuiManager::update(bool gotoPC)
+{
+ bool on = (programmer() ? programmer()->isTargetPowerOn() : false);
+ static_cast<KToggleAction *>(Main::action("prog_power"))->setChecked(on);
+ return Manager::update(gotoPC);
+}
+
+bool Debugger::GuiManager::checkIfContinueStepping(bool &continueStepping)
+{
+ if ( Main::toolGroup().generateDebugInformation(Main::device()) )
+ return Debugger::Manager::checkIfContinueStepping(continueStepping);
+ if ( !update(false) ) return false;
+ continueStepping = false;
+ return true;
+}
+
+void Debugger::GuiManager::updateView(bool gotoPC)
+{
+ Main::breakpointsView().updateView();
+ bool currentHasPC = false;
+ QValueList<Editor *>::iterator ite;
+ for (ite=_editors.begin(); ite!=_editors.end(); ++ite) {
+ TextEditor *e = ::qt_cast<TextEditor *>(*ite);
+ if ( e==0 ) continue;
+ updateEditorMarks(*e);
+ if ( !_currentSourceLines.contains(e->url()) ) continue;
+ if (gotoPC) e->setCursor(_currentSourceLines[e->url()], 0);
+ if ( e==Main::currentEditor() ) currentHasPC = true;
+ }
+ if ( programmer()==0 || programmer()->state()!=Programmer::Halted || !pc().isInitialized() || currentHasPC ) return;
+ // 1: look at files inside project and not generated
+ // 2: look at files inside project
+ // 3: look at existing files
+ for (uint i=0; i<3; i++) {
+ QMap<PURL::Url, uint>::const_iterator it;
+ for (it=_currentSourceLines.begin(); it!=_currentSourceLines.end(); ++it) {
+ switch (i) {
+ case 0: if ( !Main::projectManager().contains(it.key()) || Main::projectManager().isExternalFile(it.key()) ) continue; break;
+ case 1: if ( !Main::projectManager().contains(it.key()) ) continue; break;
+ case 2: if ( !it.key().exists() ) continue; break;
+ }
+ TextEditor *e = ::qt_cast<TextEditor *>(Main::editorManager().findEditor(it.key()));
+ if ( e==0 ) {
+ if (gotoPC) e = ::qt_cast<TextEditor *>(Main::editorManager().openEditor(it.key()));
+ if ( e==0 ) continue;
+ }
+ updateEditorMarks(*e);
+ if (gotoPC) {
+ e->setCursor(_currentSourceLines[e->url()], 0);
+ Main::editorManager().showEditor(e);
+ }
+ return;
+ }
+ }
+}
+
+Register::MainView *Debugger::GuiManager::registerView() const
+{
+ QValueList<Editor *>::const_iterator it = _editors.begin();
+ for (; it!=_editors.end(); ++it) {
+ Register::MainView *rv = ::qt_cast<Register::MainView *>(*it);
+ if (rv) return rv;
+ }
+ return 0;
+}
+
+bool Debugger::GuiManager::isProjectSource(const PURL::Url &url) const
+{
+ return ( Main::projectManager().contains(url) && !Main::projectManager().isExternalFile(url) );
+}
+
+void Debugger::GuiManager::showDisassemblyLocation()
+{
+ TextEditor *editor = ::qt_cast<TextEditor *>(Main::currentEditor());
+ Q_ASSERT(editor);
+ Q_ASSERT(_coff);
+ QValueVector<Address> addresses = _coff->addresses(editor->url(), editor->cursorLine());
+ if ( addresses.isEmpty() ) {
+ MessageBox::sorry(i18n("Cannot show disassembly location for non-code line."), Log::Show);
+ return;
+ }
+ int line = _coff->lineForAddress(_coff->url(), addresses[0]);
+ if ( line==-1 ) return; // possible ?
+ TextEditor *e = ::qt_cast<TextEditor *>(Main::editorManager().openEditor(_coff->url()));
+ if (e) e->setCursor(line, 0);
+}
diff --git a/src/libgui/gui_debug_manager.h b/src/libgui/gui_debug_manager.h
new file mode 100644
index 0000000..661f86a
--- /dev/null
+++ b/src/libgui/gui_debug_manager.h
@@ -0,0 +1,61 @@
+/***************************************************************************
+ * Copyright (C) 2006 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef GUI_DEBUG_MANAGER_H
+#define GUI_DEBUG_MANAGER_H
+
+#include "progs/manager/debug_manager.h"
+#include "text_editor.h"
+#include "main_global.h"
+#include "tools/list/compile_process.h"
+namespace Register { class MainView; }
+
+namespace Debugger
+{
+class GuiManager : public Manager
+{
+Q_OBJECT
+public:
+ GuiManager() {}
+ virtual void updateDevice();
+ void addTextEditor(TextEditor &editor);
+ void addRegisterView(Register::MainView &view);
+ void clearEditors();
+ virtual void clear();
+
+public slots:
+ virtual bool update(bool gotoPC);
+ void toggleBreakpoint();
+ void toggleEnableBreakpoint();
+ void showPC() { updateView(true); }
+ void showDisassemblyLocation();
+
+private slots:
+ void editorDestroyed();
+
+private:
+ QValueList<Editor *> _editors;
+
+ static Breakpoint::Data currentBreakpointData();
+ void updateEditorMarks(TextEditor &editor) const; // return PC line
+ Register::MainView *registerView() const;
+ bool addEditor(Editor &editor);
+ virtual bool internalInit();
+ virtual bool checkState(bool &first);
+ virtual const Programmer::Group *programmerGroup() const { return &Main::programmerGroup(); }
+ virtual const Device::Data *deviceData() const { return Main::deviceData(); }
+ virtual PURL::Url coffUrl() const;
+ virtual Log::View *compileView() { return &Main::compileLog(); }
+ virtual void updateView(bool gotoPC);
+ virtual bool isProjectSource(const PURL::Url &url) const;
+ virtual bool checkIfContinueStepping(bool &continueStepping);
+};
+
+} // namespace
+
+#endif
diff --git a/src/libgui/gui_prog_manager.cpp b/src/libgui/gui_prog_manager.cpp
new file mode 100644
index 0000000..ea22d7e
--- /dev/null
+++ b/src/libgui/gui_prog_manager.cpp
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "gui_prog_manager.h"
+
+#include <kaction.h>
+
+#include "progs/base/generic_prog.h"
+#include "progs/base/prog_group.h"
+#include "progs/base/prog_config.h"
+#include "progs/base/hardware_config.h"
+#include "progs/base/generic_debug.h"
+#include "progs/gui/prog_group_ui.h"
+#include "toplevel.h"
+#include "project.h"
+#include "project_manager.h"
+#include "progs/manager/debug_manager.h"
+
+//----------------------------------------------------------------------------
+bool Programmer::GuiManager::internalInitProgramming(bool debugging)
+{
+ if ( !Manager::internalInitProgramming(debugging) ) return false;
+ if ( !debugging && _programmer->isActive() ) {
+ if ( group().isDebugger() && !askContinue(i18n("The selected operation will stop the debugging session. Continue anyway?")) ) return false;
+ if ( !halt() ) return false;
+ }
+ if ( debugging && !_programmer->isActive() ) {
+ if ( ::Debugger::manager->coff()==0 && !::Debugger::manager->init() ) {
+ sorry(i18n("Cannot start debugging without a COFF file. Please compile the project."));
+ return false;
+ }
+ if ( !group().isSoftware() ) {
+ if ( !askContinue(i18n("The device memory is in an unknown state. You may want to reprogram the device. Continue anyway?")) )
+ return false;
+ }
+ }
+ return true;
+}
+
+void Programmer::GuiManager::toggleDevicePower()
+{
+ bool on = static_cast<KToggleAction *>(Main::action("prog_power"))->isChecked();
+ setDevicePower(on);
+}
+
+void Programmer::GuiManager::showAdvancedDialog()
+{
+ const ::Programmer::GroupUI *groupui = static_cast<const ::Programmer::GroupUI *>(group().gui());
+ const Device::Data *data = Main::deviceData();
+ if ( data && !group().isSupported(data->name()) ) data = 0;
+ createProgrammer(data);
+ ::Programmer::AdvancedDialog *dialog = groupui->createAdvancedDialog(*_programmer, &Main::toplevel());
+ Q_ASSERT(dialog);
+ dialog->updateDisplay();
+ dialog->exec();
+ delete dialog;
+}
+
+void Programmer::GuiManager::createProgrammer(const Device::Data *data)
+{
+ HardwareDescription hd;
+ hd.port = GroupConfig::portDescription(group());
+ ::Hardware::Config *hconfig = group().hardwareConfig();
+ if (hconfig) hd.name = hconfig->currentHardware(hd.port.type);
+ delete hconfig;
+ Manager::createProgrammer(data, hd);
+}
diff --git a/src/libgui/gui_prog_manager.h b/src/libgui/gui_prog_manager.h
new file mode 100644
index 0000000..b19186e
--- /dev/null
+++ b/src/libgui/gui_prog_manager.h
@@ -0,0 +1,37 @@
+/***************************************************************************
+ * 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 GUI_PROG_MANAGER_H
+#define GUI_PROG_MANAGER_H
+
+#include "progs/manager/prog_manager.h"
+#include "libgui/main_global.h"
+
+namespace Programmer
+{
+class GuiManager : public Manager
+{
+Q_OBJECT
+public:
+ GuiManager(QObject *parent) : Manager(parent) {}
+ virtual void createProgrammer(const Device::Data *data);
+ virtual void setState(State state) { Main::setState(state==Idle ? Main::Idle : Main::Programming); }
+
+public slots:
+ void toggleDevicePower();
+ void showAdvancedDialog();
+
+private:
+ virtual const Group &group() const { return Main::programmerGroup(); }
+ virtual bool internalInitProgramming(bool debugging);
+ virtual const Device::Data *device() const { return Main::deviceData(); }
+};
+
+} // namespace
+
+#endif
diff --git a/src/libgui/hex_editor.cpp b/src/libgui/hex_editor.cpp
new file mode 100644
index 0000000..48ad7e8
--- /dev/null
+++ b/src/libgui/hex_editor.cpp
@@ -0,0 +1,192 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003 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 "hex_editor.h"
+
+#include <qgroupbox.h>
+#include <qhgroupbox.h>
+#include <qregexp.h>
+#include <qlayout.h>
+#include <qscrollview.h>
+#include <qstringlist.h>
+#include <qlabel.h>
+#include <qtimer.h>
+
+#include <klocale.h>
+#include <ktempfile.h>
+
+#include "devices/base/device_group.h"
+#include "devices/gui/device_group_ui.h"
+#include "devices/gui/hex_view.h"
+#include "toplevel.h"
+#include "common/global/pfile.h"
+#include "main_global.h"
+
+//-----------------------------------------------------------------------------
+HexEditorPart::HexEditorPart(HexEditor *editor)
+ : KParts::ReadWritePart(editor, "hex_editor_part")
+{
+ setXMLFile("hexeditorpartui.rc");
+
+ (void)KStdAction::save(editor, SLOT(save()), actionCollection());
+ (void)KStdAction::saveAs(editor, SLOT(saveAs()), actionCollection());
+ (void)new KToggleAction(i18n("Read Only Mode"), 0, 0, editor, SLOT(toggleReadOnly()), actionCollection(), "tools_toggle_write_lock");
+}
+
+void HexEditorPart::setReadWrite(bool rw)
+{
+ KParts::ReadWritePart::setReadWrite(rw);
+ static_cast<KToggleAction *>(action("tools_toggle_write_lock"))->setChecked(!rw);
+}
+
+//-----------------------------------------------------------------------------
+HexEditor::HexEditor(const QString &name, QWidget *parent)
+ : DeviceEditor(name, QString::null, parent, "hex_editor")
+{
+ init();
+}
+
+HexEditor::HexEditor(QWidget *parent)
+ : DeviceEditor(parent, "hex_editor")
+{
+ init();
+}
+
+void HexEditor::init()
+{
+ _modified = false;
+ _memory = 0;
+ _originalMemory = 0;
+ _top->addStretch(1);
+ _part = new HexEditorPart(this);
+ setReadOnly(false);
+}
+
+void HexEditor::clear()
+{
+ delete _memory;
+ _memory = 0;
+ delete _originalMemory;
+ _originalMemory = 0;
+}
+
+QWidget *HexEditor::createView(const Device::Data *data, QWidget *parent)
+{
+ clear();
+ if (data) {
+ _originalMemory = data->group().createMemory(*data);
+ _memory = data->group().createMemory(*data);
+ }
+ if ( data==0 ) return new QWidget(parent);
+ Device::HexView *hv = Device::groupui(*data).createHexView(*this, parent);
+ connect(hv, SIGNAL(modified()), SLOT(slotModified()));
+ _dirty = true;
+ QTimer::singleShot(0, this, SLOT(simpleLoad()));
+ return hv;
+}
+
+bool HexEditor::simpleLoad()
+{
+ if ( !_dirty ) return true;
+ _dirty = false;
+ if (_memory) {
+ QStringList warnings;
+ if ( _memory->fromHexBuffer(_hexBuffer, warnings)!=Device::Memory::NoWarning ) {
+ _labelWarning->setText(i18n("<b>Warning:</b> hex file seems to be incompatible with the selected device %1:<br>%2")
+ .arg(_memory->device().name()).arg(warnings.join("<br>")));
+ _labelWarning->show();
+ } else _labelWarning->hide();
+ display();
+ }
+ return true;
+}
+
+void HexEditor::setReadOnlyInternal(bool readOnly)
+{
+ _part->setReadWrite(!readOnly);
+ if (_memory) static_cast<Device::HexView *>(_view)->setReadOnly(readOnly);
+}
+
+void HexEditor::addGui()
+{
+ Main::toplevel().guiFactory()->addClient(_part);
+}
+
+void HexEditor::removeGui()
+{
+ Main::toplevel().guiFactory()->removeClient(_part);
+}
+
+bool HexEditor::open(const PURL::Url &url)
+{
+ _url = url;
+ PURL::File file(url, Main::compileLog());
+ if ( !file.openForRead() ) return false;
+ QStringList errors;
+ if ( !_hexBuffer.load(file.stream(), errors) ) {
+ MessageBox::detailedSorry(i18n("Error(s) reading hex file."), errors.join("\n"), Log::Show);
+ return false;
+ }
+ _dirty = true;
+ return simpleLoad();
+}
+
+bool HexEditor::save(const PURL::Url &url)
+{
+ return save(url, i18n("File URL: \"%1\".").arg(url.pretty()));
+}
+
+bool HexEditor::save(const PURL::Url &url, const QString &fileErrorString)
+{
+ PURL::File file(url, Main::compileLog());
+ if ( !file.openForWrite() ) return false;
+ if ( !_memory->save(file.stream(), HexBuffer::IHX32) ) {
+ MessageBox::detailedSorry(i18n("Error while writing file \"%1\".").arg(url.pretty()), fileErrorString, Log::Show);
+ return false;
+ }
+ _originalMemory->copyFrom(*_memory);
+ _url = url;
+ return file.close();
+}
+
+void HexEditor::display()
+{
+ _modified = false;
+ if (_memory) {
+ _originalMemory->copyFrom(*_memory);
+ static_cast<Device::HexView *>(_view)->display(_memory);
+ static_cast<Device::HexView *>(_view)->setReadOnly(isReadOnly());
+ static_cast<Device::HexView *>(_view)->updateDisplay();
+ }
+ statusChanged();
+}
+
+void HexEditor::memoryRead()
+{
+ display();
+ emit guiChanged();
+}
+
+void HexEditor::slotModified()
+{
+ static_cast<Device::HexView *>(_view)->updateDisplay();
+ _modified = true;
+ statusChanged();
+ emit guiChanged();
+}
+
+void HexEditor::statusChanged()
+{
+ QString s;
+ if (_memory) {
+ BitValue cs = static_cast<Device::HexView *>(_view)->checksum();
+ s = i18n("Checksum: %1").arg(toHexLabel(cs, 4));
+ }
+ emit statusTextChanged(s);
+}
diff --git a/src/libgui/hex_editor.h b/src/libgui/hex_editor.h
new file mode 100644
index 0000000..86b7f2c
--- /dev/null
+++ b/src/libgui/hex_editor.h
@@ -0,0 +1,83 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003 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 HEX_EDITOR_H
+#define HEX_EDITOR_H
+
+#include <kparts/part.h>
+
+#include "device_editor.h"
+#include "devices/base/hex_buffer.h"
+#include "devices/base/generic_memory.h"
+
+//-----------------------------------------------------------------------------
+class HexEditor;
+
+class HexEditorPart : public KParts::ReadWritePart
+{
+Q_OBJECT
+public:
+ HexEditorPart(HexEditor *editor);
+ virtual void setReadWrite(bool readWrite);
+
+private:
+ virtual bool openFile() { return true; }
+ virtual bool saveFile() { return true; }
+};
+
+//-----------------------------------------------------------------------------
+class HexEditor : public DeviceEditor
+{
+Q_OBJECT
+public:
+ HexEditor(const QString &name, QWidget *parent);
+ HexEditor(QWidget *parent);
+ virtual bool isModified() const { return _modified; }
+ virtual bool isReadOnly() const { return !_part->isReadWrite(); }
+ virtual ~HexEditor() { clear(); }
+ virtual PURL::FileType fileType() const { return PURL::Hex; }
+ virtual PURL::Url url() const { return _url; }
+ virtual bool save(const PURL::Url &url);
+ virtual bool open(const PURL::Url &url);
+ Device::Memory *memory() { return _memory; }
+ const Device::Memory *memory() const { return _memory; }
+ const Device::Memory *originalMemory() const { return _originalMemory; }
+ void memoryRead();
+ virtual void addGui();
+ virtual void removeGui();
+ virtual void setFocus() {}
+ virtual QValueList<uint> bookmarkLines() const { return QValueList<uint>(); }
+ virtual void setBookmarkLines(const QValueList<uint> &) {}
+
+public slots:
+ virtual void statusChanged();
+
+private slots:
+ void slotModified();
+ bool simpleLoad();
+
+private:
+ Device::Memory *_originalMemory, *_memory;
+ HexBuffer _hexBuffer;
+ bool _modified, _dirty;
+ HexEditorPart *_part;
+ PURL::Url _url;
+
+ virtual void dropEvent(QDropEvent *e) { emit dropEventPass(e); }
+ bool save(const PURL::Url &url, const QString &fileErrorString);
+ bool verifyDeviceType();
+ virtual QWidget *createView(const Device::Data *data, QWidget *parent);
+ virtual void setModifiedInternal(bool modified) { _modified = modified; }
+ virtual void setReadOnlyInternal(bool readOnly);
+ void display();
+ void init();
+ void clear();
+};
+
+#endif
diff --git a/src/libgui/likeback.cpp b/src/libgui/likeback.cpp
new file mode 100644
index 0000000..eac86ff
--- /dev/null
+++ b/src/libgui/likeback.cpp
@@ -0,0 +1,668 @@
+/***************************************************************************
+ * Copyright (C) 2006 by S�bastien Laot *
+ * slaout@linux62.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. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include <kapplication.h>
+#include <kaboutdata.h>
+#include <kconfig.h>
+#include <kiconloader.h>
+#include <kaboutdata.h>
+#include <klocale.h>
+#include <kdebug.h>
+#include <kmessagebox.h>
+#include <qlayout.h>
+#include <qtoolbutton.h>
+#include <qpushbutton.h>
+#include <qpopupmenu.h>
+#include <qtextedit.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <kdialogbase.h>
+#include <qhttp.h>
+#include <kurl.h>
+#include <kinputdialog.h>
+#include <qvalidator.h>
+#include <kdebug.h>
+#include <kprocess.h>
+#include "netwm.h"
+
+#include <pwd.h>
+
+#include <iostream>
+
+#include "likeback.h"
+
+#include <krun.h>
+#include "common/global/about.h"
+
+LikeBack::LikeBack(Button buttons)
+ : QWidget( 0, "LikeBack", Qt::WX11BypassWM | Qt::WStyle_NoBorder | Qt::WNoAutoErase | Qt::WStyle_StaysOnTop | Qt::WStyle_NoBorder | Qt::Qt::WGroupLeader)
+ , m_buttons(buttons)
+{
+ QHBoxLayout *layout = new QHBoxLayout(this);
+
+ QIconSet likeIconSet = kapp->iconLoader()->loadIconSet("likeback_like", KIcon::Small);
+ QIconSet dislikeIconSet = kapp->iconLoader()->loadIconSet("likeback_dislike", KIcon::Small);
+ QIconSet bugIconSet = kapp->iconLoader()->loadIconSet("likeback_bug", KIcon::Small);
+// QIconSet configureIconSet = kapp->iconLoader()->loadIconSet("configure", KIcon::Small);
+
+ QToolButton *m_likeButton = new QToolButton(this, "ilike");
+ m_likeButton->setIconSet(likeIconSet);
+ m_likeButton->setTextLabel(i18n("I Like..."));
+ m_likeButton->setAutoRaise(true);
+ connect( m_likeButton, SIGNAL(clicked()), this, SLOT(iLike()) );
+ layout->add(m_likeButton);
+
+ QToolButton *m_dislikeButton = new QToolButton(this, "idonotlike");
+ m_dislikeButton->setIconSet(dislikeIconSet);
+ m_dislikeButton->setTextLabel(i18n("I Do not Like..."));
+ m_dislikeButton->setAutoRaise(true);
+ connect( m_dislikeButton, SIGNAL(clicked()), this, SLOT(iDoNotLike()) );
+ layout->add(m_dislikeButton);
+
+ QToolButton *m_bugButton = new QToolButton(this, "ifoundabug");
+ m_bugButton->setIconSet(bugIconSet);
+ m_bugButton->setTextLabel(i18n("I Found a Bug..."));
+ m_bugButton->setAutoRaise(true);
+ connect( m_bugButton, SIGNAL(clicked()), this, SLOT(iFoundABug()) );
+ layout->add(m_bugButton);
+
+ m_configureButton = new QToolButton(this, "configure");
+ QIconSet helpIconSet = kapp->iconLoader()->loadIconSet("help", KIcon::Small);
+ m_configureButton->setIconSet(helpIconSet);
+ m_configureButton->setTextLabel(i18n("Configure..."));
+ m_configureButton->setAutoRaise(true);
+ connect( m_likeButton, SIGNAL(clicked()), this, SLOT(configure()) );
+ layout->add(m_configureButton);
+
+ QPopupMenu *configureMenu = new QPopupMenu(this);
+ configureMenu->insertItem(helpIconSet, i18n("What's &This?"), this , SLOT(showWhatsThisMessage()) );
+ QIconSet changeEmailIconSet = kapp->iconLoader()->loadIconSet("mail_generic", KIcon::Small);
+ configureMenu->insertItem(changeEmailIconSet, i18n("&Configure Email Address..."), this , SLOT(askEMail()) );
+// QIconSet dontHelpIconSet = kapp->iconLoader()->loadIconSet("stop", KIcon::Small);
+// configureMenu->insertItem( dontHelpIconSet, i18n("&Do not Help Anymore"), this , SLOT(doNotHelpAnymore()) );
+ m_configureButton->setPopup(configureMenu);
+ connect( m_configureButton, SIGNAL(pressed()), this, SLOT(openConfigurePopup()) );
+
+ if (!emailAddressAlreadyProvided())
+ //beginFetchingEmail(); // Begin before showing the message, so we have time!
+ endFetchingEmailFrom();
+
+// static const char *messageShown = "LikeBack_starting_information";
+// if (KMessageBox::shouldBeShownContinue(messageShown)) {
+// showInformationMessage();
+// KMessageBox::saveDontShowAgainContinue(messageShown);
+// }
+
+ resize(sizeHint());
+
+ connect( &m_timer, SIGNAL(timeout()), this, SLOT(autoMove()) );
+ m_timer.start(10);
+
+ s_instance = this;
+}
+
+LikeBack::~LikeBack()
+{
+}
+
+void LikeBack::openConfigurePopup()
+{
+ m_configureButton->openPopup();
+}
+
+void LikeBack::doNotHelpAnymore()
+{
+ disable();
+ int result = KMessageBox::questionYesNo(
+ kapp->activeWindow(),
+ i18n("Are you sure you do not want to participate anymore in the application enhancing program?"),
+ i18n("Do not Help Anymore"));
+ if (result == KMessageBox::No) {
+ enable();
+ return;
+ }
+
+ s_config->setGroup("LikeBack");
+ s_config->writeEntry("userWantToParticipateForVersion_" + s_about->version(), false);
+ deleteLater();
+}
+
+void LikeBack::showWhatsThisMessage()
+{
+ disable();
+ showInformationMessage();
+ enable();
+}
+
+bool LikeBack::userWantToParticipate()
+{
+ if (!kapp)
+ return true;
+
+ s_config->setGroup("LikeBack");
+ return s_config->readBoolEntry("userWantToParticipateForVersion_" + s_about->version(), true);
+}
+
+// TODO: Only show relevant buttons!
+
+void LikeBack::showInformationMessage()
+{
+ QPixmap likeIcon = kapp->iconLoader()->loadIcon("likeback_like", KIcon::Small);
+ QPixmap dislikeIcon = kapp->iconLoader()->loadIcon("likeback_dislike", KIcon::Small);
+ QPixmap bugIcon = kapp->iconLoader()->loadIcon("likeback_bug", KIcon::Small);
+ QMimeSourceFactory::defaultFactory()->setPixmap("likeback_icon_like", likeIcon);
+ QMimeSourceFactory::defaultFactory()->setPixmap("likeback_icon_dislike", dislikeIcon);
+ QMimeSourceFactory::defaultFactory()->setPixmap("likeback_icon_bug", bugIcon);
+ KMessageBox::information(0,
+ "<p><b>" + i18n("This is a quick feedback system for %1.").arg(s_about->programName()) + "</b></p>"
+ "<p>" + i18n("To help us improve it, your comments are important.") + "</p>"
+ "<p>" + i18n("Each time you have a great or frustrating experience, "
+ "please click the appropriate hand below the window title-bar, "
+ "briefly describe what you like or dislike and click Send.") + "</p>"
+ "<p><b>" + i18n("Icons description:") + "</b><table>"
+ "<tr><td><nobr><img source=\"likeback_icon_like\">: " + i18n("Send a comment about what you like.") + "</nobr></td></tr>"
+ "<tr><td><nobr><img source=\"likeback_icon_dislike\">: " + i18n("Send a comment about what you don't like.") + "</nobr></td></tr>"
+ "<tr><td><nobr><img source=\"likeback_icon_bug\">: " + i18n("Report a bug.") + "</nobr></td></tr>"
+ "</table></p>",
+ i18n("Help Improve the Application"));
+ QMimeSourceFactory::defaultFactory()->setData("likeback_icon_like", 0L);
+ QMimeSourceFactory::defaultFactory()->setData("likeback_icon_dislike", 0L);
+ QMimeSourceFactory::defaultFactory()->setData("likeback_icon_bug", 0L);
+}
+
+QString LikeBack::s_customLanguageMessage = QString();
+bool LikeBack::s_allowFeatureWishes = false;
+LikeBack::WindowListing LikeBack::s_windowListing = LikeBack::NoListing;
+QString LikeBack::s_hostName = QString();
+QString LikeBack::s_remotePath = QString();
+Q_UINT16 LikeBack::s_hostPort = 16;
+int LikeBack::s_disabledCount = 0;
+LikeBack* LikeBack::s_instance = 0;
+KConfig* LikeBack::s_config = 0;
+KAboutData* LikeBack::s_about = 0;
+
+LikeBack* LikeBack::instance()
+{
+ return s_instance;
+}
+
+QString LikeBack::customLanguageMessage()
+{
+ return s_customLanguageMessage;
+}
+
+QString LikeBack::hostName()
+{
+ return s_hostName;
+}
+
+QString LikeBack::remotePath()
+{
+ return s_remotePath;
+}
+
+Q_UINT16 LikeBack::hostPort()
+{
+ return s_hostPort;
+}
+
+KAboutData* LikeBack::about()
+{
+ return s_about;
+}
+
+void LikeBack::disable()
+{
+ s_disabledCount++;
+}
+
+void LikeBack::enable()
+{
+ s_disabledCount--;
+ if (s_disabledCount < 0)
+ std::cerr << "===== LikeBack ===== Enabled too many times (less than how many times it was disabled)" << std::endl;
+}
+
+bool LikeBack::enabled()
+{
+ return s_disabledCount == 0;
+}
+
+void LikeBack::setServer(QString hostName, QString remotePath, Q_UINT16 hostPort)
+{
+ s_hostName = hostName;
+ s_remotePath = remotePath;
+ s_hostPort = hostPort;
+}
+
+void LikeBack::setWindowNamesListing(WindowListing windowListing)
+{
+ s_windowListing = windowListing;
+}
+
+void LikeBack::setCustomLanguageMessage(const QString &message)
+{
+ s_customLanguageMessage = message;
+}
+
+void LikeBack::setAllowFeatureWishes(bool allow)
+{
+ s_allowFeatureWishes = allow;
+}
+
+bool LikeBack::allowFeatureWishes()
+{
+ return s_allowFeatureWishes;
+}
+
+void LikeBack::autoMove()
+{
+ static QWidget *lastWindow = 0;
+
+ QWidget *window = kapp->activeWindow();
+ // When a Kicker applet has the focus, like the Commandline QLineEdit,
+ // the systemtray icon indicates to be the current window and the LikeBack is shown next to the system tray icon.
+ // It's obviously bad ;-) :
+ bool shouldShow = false;//(enabled() && window && window->inherits("KMainWindow") );
+ if (shouldShow) {
+ //move(window->x() + window->width() - 100 - width(), window->y());
+ //move(window->x() + window->width() - 100 - width(), window->mapToGlobal(QPoint(0, 0)).y() - height());
+ move(window->mapToGlobal(QPoint(0, 0)).x() + window->width() - width(), window->mapToGlobal(QPoint(0, 0)).y() + 1);
+
+ if (window != lastWindow && s_windowListing != NoListing)
+// if (qstricmp(window->name(), "") == 0 || qstricmp(window->name(), "unnamed") == 0) ;
+// std::cout << "===== LikeBack ===== UNNAMED ACTIVE WINDOW OF TYPE " << window->className() << " ======" << activeWindowPath() << std::endl;
+// else if (s_windowListing == AllWindows) ;
+// std::cout << "LikeBack: Active Window: " << activeWindowPath() << std::endl;
+ lastWindow = window;
+ }
+ if (shouldShow && !isShown()) {
+ show();
+ } else if (!shouldShow && isShown())
+ hide();
+}
+
+void LikeBack::iLike()
+{
+ showDialog(ILike);
+}
+
+void LikeBack::iDoNotLike()
+{
+ showDialog(IDoNotLike);
+}
+
+void LikeBack::iFoundABug()
+{
+ (void)new KRun(Piklab::URLS[Piklab::BugReport], kapp->mainWidget());
+ // showDialog(IFoundABug);
+}
+
+void LikeBack::configure()
+{
+}
+
+QString LikeBack::activeWindowPath()
+{
+ QStringList windowNames;
+ QWidget *window = kapp->activeWindow();
+ while (window) {
+ QString name = window->name();
+ if (name == "unnamed")
+ name += QString(":") + window->className();
+ windowNames.append(name);
+ window = dynamic_cast<QWidget*>(window->parent());
+ }
+
+ QString windowName;
+ for (int i = ((int)windowNames.count()) - 1; i >= 0; i--) {
+ if (windowName.isEmpty())
+ windowName = windowNames[i];
+ else
+ windowName += QString("~~") + windowNames[i];
+ }
+
+ return windowName;
+}
+
+void LikeBack::showDialog(Button button)
+{
+ LikeBackDialog dialog(button, activeWindowPath(), "");
+ disable();
+ hide();
+ kapp->processEvents();
+ dialog.exec();
+ enable();
+}
+
+bool LikeBack::emailAddressAlreadyProvided()
+{
+ return s_config->readBoolEntry("emailAlreadyAsked", false);
+}
+
+QString LikeBack::emailAddress()
+{
+ if (!emailAddressAlreadyProvided())
+ instance()->askEMail();
+
+ return s_config->readEntry("emailAddress", "");
+}
+
+void LikeBack::setEmailAddress(const QString &address)
+{
+ s_config->setGroup("LikeBack");
+ s_config->writeEntry("emailAddress", address);
+ s_config->writeEntry("emailAlreadyAsked", true);
+}
+
+void LikeBack::askEMail()
+{
+ s_config->setGroup("LikeBack");
+
+ QString currentEMailAddress = s_config->readEntry("emailAddress", "");
+ if (!emailAddressAlreadyProvided() && !instance()->m_fetchedEmail.isEmpty())
+ currentEMailAddress = instance()->m_fetchedEmail;
+
+ bool ok;
+
+ QString mailExpString = "[\\w-\\.]+@[\\w-\\.]+\\.[\\w]+";
+ //QString namedMailExpString = "[.]*[ \\t]+<" + mailExpString + ">";
+ //QRegExp mailExp("^(|" + mailExpString + "|" + namedMailExpString + ")$");
+ QRegExp mailExp("^(|" + mailExpString + ")$");
+ QRegExpValidator emailValidator(mailExp, this);
+
+ disable();
+ QString email = KInputDialog::getText(
+ i18n("Set Email Address"),
+ "<p><b>" + i18n("Please provide your email address.") + "</b></p>" +
+ "<p>" + i18n("It will only be used to contact you back if more information is needed about your comments, how to reproduce the bugs you report, send bug corrections for you to test...") + "</p>" +
+ "<p>" + i18n("The email address is optional. If you do not provide any, your comments will be sent anonymously. Just click OK in that case.") + "</p>" +
+ "<p>" + i18n("You can change or remove your email address whenever you want. For that, use the little arrow icon at the top-right corner of a window.") + "</p>" +
+ "<p>" + i18n("Your email address (keep empty to post comments anonymously):"),
+ currentEMailAddress, &ok, kapp->activeWindow(), /*name=*/(const char*)0, &emailValidator);
+ enable();
+
+ if (ok)
+ setEmailAddress(email);
+}
+
+// FIXME: Should be moved to KAboutData? Cigogne will also need it.
+bool LikeBack::isDevelopmentVersion(const QString &version)
+{
+ QString theVersion = (version.isEmpty() ? s_about->version() : version);
+
+ return theVersion.find("alpha", /*index=*/0, /*caseSensitive=*/false) != -1 ||
+ theVersion.find("beta", /*index=*/0, /*caseSensitive=*/false) != -1 ||
+ theVersion.find("rc", /*index=*/0, /*caseSensitive=*/false) != -1 ||
+ theVersion.find("svn", /*index=*/0, /*caseSensitive=*/false) != -1 ||
+ theVersion.find("cvs", /*index=*/0, /*caseSensitive=*/false) != -1;
+}
+
+void LikeBack::init(KConfig* config, KAboutData* about, Button buttons)
+{
+ s_config = config;
+ s_about = about;
+ init(isDevelopmentVersion(), buttons);
+}
+
+void LikeBack::init(Button buttons)
+{
+ init(isDevelopmentVersion(), buttons);
+}
+
+void LikeBack::init(bool isDevelopmentVersion, Button buttons)
+{
+ if (s_config == 0)
+ s_config = kapp->config();
+ if (s_about == 0)
+ s_about = (KAboutData*) kapp->aboutData();
+
+ if (LikeBack::userWantToParticipate() && isDevelopmentVersion)
+ new LikeBack(buttons);
+}
+
+
+
+
+
+
+
+/**
+ * Code from KBugReport::slotConfigureEmail() in kdeui/kbugreport.cpp:
+ */
+/*void LikeBack::beginFetchingEmail()
+{
+ if (m_process)
+ return;
+ m_process = new KProcess();
+ *m_process << QString::fromLatin1("kcmshell") << QString::fromLatin1("kcm_useraccount");
+ connect( m_process, SIGNAL(processExited(KProcess*)), SLOT(endFetchingEmailFrom()) );
+ if (!m_process->start()) {
+ kdDebug() << "Couldn't start kcmshell.." << endl;
+ delete m_process;
+ m_process = 0;
+ return;
+ }
+// m_configureEmail->setEnabled(false);
+}*/
+
+/**
+ * Code from KBugReport::slotSetFrom() in kdeui/kbugreport.cpp:
+ */
+void LikeBack::endFetchingEmailFrom()
+{
+// delete m_process;
+// m_process = 0;
+// m_configureEmail->setEnabled(true);
+
+ // ### KDE4: why oh why is KEmailSettings in kio?
+ KConfig emailConf( QString::fromLatin1("emaildefaults") );
+
+ // find out the default profile
+ emailConf.setGroup(QString::fromLatin1("Defaults"));
+ QString profile = QString::fromLatin1("PROFILE_");
+ profile += emailConf.readEntry(QString::fromLatin1("Profile"), QString::fromLatin1("Default"));
+
+ emailConf.setGroup(profile);
+ QString fromaddr = emailConf.readEntry(QString::fromLatin1("EmailAddress"));
+ if (fromaddr.isEmpty()) {
+ struct passwd *p;
+ p = getpwuid(getuid());
+ m_fetchedEmail = QString::fromLatin1(p->pw_name);
+ } else {
+ QString name = emailConf.readEntry(QString::fromLatin1("FullName"));
+ if (!name.isEmpty())
+ m_fetchedEmail = /*name + QString::fromLatin1(" <") +*/ fromaddr /*+ QString::fromLatin1(">")*/;
+ }
+// m_from->setText( fromaddr );
+}
+
+
+
+
+
+
+
+/** class LikeBackDialog: */
+
+LikeBackDialog::LikeBackDialog(LikeBack::Button reason, QString windowName, QString context)
+ : KDialog(kapp->activeWindow(), "_likeback_feedback_window_")
+ , m_reason(reason)
+ , m_windowName(windowName)
+ , m_context(context)
+{
+ setModal(true);
+ QVBoxLayout *mainLayout = new QVBoxLayout(this);
+
+ QWidget *coloredWidget = new QWidget(this);
+ QLabel *explainings = new QLabel(this);
+ QHBoxLayout *explainingLayout = new QHBoxLayout((QWidget*)0, KDialogBase::marginHint());
+ explainingLayout->addWidget(explainings);
+ mainLayout->addWidget(coloredWidget);
+
+ QColor color;
+ QColor lineColor;
+ QPixmap icon;
+ QString title;
+ QString please;
+ switch (reason) {
+ case LikeBack::ILike:
+ color = QColor("#DFFFDF");
+ lineColor = Qt::green;
+ icon = kapp->iconLoader()->loadIcon("likeback_like", KIcon::Small);
+ title = i18n("I like...");
+ please = i18n("Please briefly describe what you like.");
+ break;
+ case LikeBack::IDoNotLike:
+ color = QColor("#FFDFDF");
+ lineColor = Qt::red;
+ icon = kapp->iconLoader()->loadIcon("likeback_dislike", KIcon::Small);
+ title = i18n("I do not like...");
+ please = i18n("Please briefly describe what you do not like.");
+ break;
+ case LikeBack::IFoundABug:
+ color = QColor("#C0C0C0");
+ lineColor = Qt::black;
+ icon = kapp->iconLoader()->loadIcon("bug", KIcon::Small);
+ title = i18n("I found a bug...");
+ please = i18n("Please briefly describe the bug you encountered.");
+ break;
+ case LikeBack::Configure:
+ case LikeBack::AllButtons:
+ return;
+ }
+
+ QWidget *line = new QWidget(this);
+ line->setPaletteBackgroundColor(lineColor);
+ line->setFixedHeight(1);
+ mainLayout->addWidget(line);
+ mainLayout->addLayout(explainingLayout);
+
+ QHBoxLayout *titleLayout = new QHBoxLayout(0);
+ coloredWidget->setPaletteBackgroundColor(color);
+ QLabel *iconLabel = new QLabel(coloredWidget);
+ iconLabel->setPixmap(icon);
+ QLabel *titleLabel = new QLabel(title, coloredWidget);
+ QFont font = titleLabel->font();
+ font.setBold(true);
+ titleLabel->setFont(font);
+ titleLabel->setPaletteForegroundColor(Qt::black);
+ titleLayout->addWidget(iconLabel);
+ titleLayout->addSpacing(4);
+ titleLayout->addWidget(titleLabel);
+ titleLayout->addStretch();
+
+ QVBoxLayout *coloredWidgetLayout = new QVBoxLayout(coloredWidget);
+ coloredWidgetLayout->setMargin(KDialogBase::marginHint());
+ coloredWidgetLayout->setSpacing(KDialogBase::spacingHint());
+ coloredWidgetLayout->addLayout(titleLayout);
+
+ QHBoxLayout *commentLayout = new QHBoxLayout((QWidget*)0);
+ commentLayout->setMargin(0);
+ commentLayout->setSpacing(KDialogBase::spacingHint());
+ m_comment = new QTextEdit(coloredWidget);
+ QIconSet sendIconSet = kapp->iconLoader()->loadIconSet("mail_send", KIcon::Toolbar);
+ m_sendButton = new QPushButton(sendIconSet, i18n("Send"), coloredWidget);
+ m_sendButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding);
+ m_sendButton->setEnabled(false);
+ connect( m_sendButton, SIGNAL(clicked()), this, SLOT(send()) );
+ connect( m_comment, SIGNAL(textChanged()), this, SLOT(commentChanged()) );
+ commentLayout->addWidget(m_comment);
+ commentLayout->addWidget(m_sendButton);
+ coloredWidgetLayout->addLayout(commentLayout);
+
+ explainings->setText(
+ "<p>" + please + " " +
+ (LikeBack::customLanguageMessage().isEmpty() ?
+ i18n("Only english language is accepted.") :
+ LikeBack::customLanguageMessage()
+ ) + " " +
+ (reason == LikeBack::ILike || reason == LikeBack::IDoNotLike ?
+ i18n("Note that to improve this application, it's important to tell us the things you like as much as the things you dislike.") + " " :
+ ""
+ ) +
+ (LikeBack::allowFeatureWishes() ?
+ "" :
+ i18n("Do not ask for features: your wishes will be ignored.")
+ ) + "</p>"
+ );
+
+ resize(kapp->desktop()->width() / 2, kapp->desktop()->height() / 3);
+
+ setCaption(kapp->makeStdCaption(i18n("Send a Comment")));
+ // setMinimumSize(mainLayout->sizeHint()); // FIXME: Doesn't work!
+}
+
+LikeBackDialog::~LikeBackDialog()
+{
+}
+
+QHttp *http ;
+
+void LikeBackDialog::send()
+{
+ QString emailAddress = LikeBack::instance()->emailAddress();
+
+ QString type = (m_reason == LikeBack::ILike ? "Like" : (m_reason == LikeBack::IDoNotLike ? "Dislike" : "Bug"));
+ QString data =
+ "protocol=" + KURL::encode_string("1.0") + "&" +
+ "type=" + KURL::encode_string(type) + "&" +
+ "version=" + KURL::encode_string(LikeBack::about()->version()) + "&" +
+ "locale=" + KURL::encode_string(KGlobal::locale()->language()) + "&" +
+ "window=" + KURL::encode_string(m_windowName) + "&" +
+ "context=" + KURL::encode_string(m_context) + "&" +
+ "comment=" + KURL::encode_string(m_comment->text()) + "&" +
+ "email=" + KURL::encode_string(emailAddress);
+ //QByteArray *data = new QByteArray();
+ /*QHttp **/http = new QHttp(LikeBack::hostName(), LikeBack::hostPort());
+
+// std::cout << "http://" << LikeBack::hostName() << ":" << LikeBack::hostPort() << LikeBack::remotePath() << std::endl;
+// std::cout << data << std::endl;
+ connect( http, SIGNAL(requestFinished(int, bool)), this, SLOT(requestFinished(int, bool)) );
+// http->post(LikeBack::remotePath(), data.utf8());
+
+ QHttpRequestHeader header("POST", LikeBack::remotePath());
+ header.setValue("Host", LikeBack::hostName());
+ header.setValue("Content-Type", "application/x-www-form-urlencoded");
+ http->setHost(LikeBack::hostName());
+ http->request(header, data.utf8());
+
+
+ m_comment->setEnabled(false);
+}
+
+void LikeBackDialog::requestFinished(int /*id*/, bool error)
+{
+ // TODO: Save to file if error (connection not present at the moment)
+ m_comment->setEnabled(true);
+ LikeBack::disable();
+ if (error) {
+ KMessageBox::error(this, i18n("<p>Error while trying to send the report.</p><p>Please retry later.</p>"), i18n("Transfer Error"));
+ } else {
+ KMessageBox::information(this, i18n("<p>Your comment has been sent successfully. It will help improve the application.</p><p>Thanks for your time.</p>") /*+ QString(http->readAll())*/, i18n("Comment Sent"));
+ close();
+ }
+ LikeBack::enable();
+}
+
+void LikeBackDialog::commentChanged()
+{
+ m_sendButton->setEnabled(!m_comment->text().isEmpty());
+}
diff --git a/src/libgui/likeback.h b/src/libgui/likeback.h
new file mode 100644
index 0000000..70a68dd
--- /dev/null
+++ b/src/libgui/likeback.h
@@ -0,0 +1,120 @@
+/***************************************************************************
+ * Copyright (C) 2006 by Sébastien Laot *
+ * slaout@linux62.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. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+#ifndef LIKEBACK_H
+#define LIKEBACK_H
+
+#include <kdialog.h>
+#include <qtimer.h>
+
+class QTextEdit;
+class QToolButton;
+class QPushButton;
+class KProcess;
+class KConfig;
+class KAboutData;
+
+/**
+ * @author S�astien Laot <slaout@linux62.org>
+ */
+class LikeBack : public QWidget
+{
+ Q_OBJECT
+ public:
+ enum Button { ILike = 0x01, IDoNotLike = 0x02, IFoundABug = 0x04, Configure = 0x10,
+ AllButtons = ILike | IDoNotLike | IFoundABug | Configure };
+ enum WindowListing { NoListing, WarnUnnamedWindows, AllWindows };
+ LikeBack(Button buttons = AllButtons);
+ ~LikeBack();
+ static void showInformationMessage();
+ static LikeBack* instance();
+ static QString customLanguageMessage();
+ static bool allowFeatureWishes();
+ static QString hostName();
+ static QString remotePath();
+ static Q_UINT16 hostPort();
+ static void setServer(QString hostName, QString remotePath, Q_UINT16 hostPort = 80);
+ static void setWindowNamesListing(WindowListing windowListing);
+ static void setCustomLanguageMessage(const QString &message);
+ static void setAllowFeatureWishes(bool allow);
+ static bool enabled();
+ static void disable();
+ static void enable();
+ static bool userWantToParticipate(); /// << @Returns true if the user have not disabled LikeBack for this version
+ static bool emailAddressAlreadyProvided();
+ static QString emailAddress(); /// << @Returns the email user address, or ask it to the user if he haven't provided or ignored it
+ static void setEmailAddress(const QString &address); /// << Calling emailAddress() will ask it to the user the first time
+ static bool isDevelopmentVersion(const QString &version = QString::null); /// << @Returns true if version is an alpha/beta/rc/svn/cvs version. Use kapp->aboutData()->version is @p version is empty
+ static void init(Button buttons = AllButtons); /// << Initialize the LikeBack system: enable it if the application version is a development one.
+ static void init(bool isDevelopmentVersion, Button buttons = AllButtons); /// << Initialize the LikeBack system: enable it if @p isDevelopmentVersion is true.
+ static void init(KConfig* config, KAboutData* about, Button buttons = AllButtons);
+ static QString activeWindowPath();
+ static KAboutData* about();
+ public slots:
+ void iLike();
+ void iDoNotLike();
+ void iFoundABug();
+ void configure();
+
+ private slots:
+ void autoMove();
+ void showDialog(Button button);
+ void openConfigurePopup();
+ void doNotHelpAnymore();
+ void showWhatsThisMessage();
+ void askEMail();
+// void beginFetchingEmail();
+ void endFetchingEmailFrom(); // static QString fetchingEmail();
+ private:
+ QTimer m_timer;
+ Button m_buttons;
+ QToolButton *m_configureButton;
+ QString m_fetchedEmail;
+ KProcess *m_process;
+ static QString s_hostName;
+ static QString s_remotePath;
+ static Q_UINT16 s_hostPort;
+ static QString s_customLanguageMessage;
+ static bool s_allowFeatureWishes;
+ static WindowListing s_windowListing;
+ static LikeBack *s_instance;
+ static int s_disabledCount;
+ static KConfig *s_config;
+ static KAboutData *s_about;
+};
+
+class LikeBackDialog : public KDialog
+{
+ Q_OBJECT
+ public:
+ LikeBackDialog(LikeBack::Button reason, QString windowName, QString context);
+ ~LikeBackDialog();
+ private:
+ LikeBack::Button m_reason;
+ QTextEdit *m_comment;
+ QPushButton *m_sendButton;
+ QString m_windowName;
+ QString m_context;
+ private slots:
+ void send();
+ void requestFinished(int id, bool error);
+ void commentChanged();
+};
+
+#endif // LIKEBACK_H
diff --git a/src/libgui/log_view.cpp b/src/libgui/log_view.cpp
new file mode 100644
index 0000000..158c281
--- /dev/null
+++ b/src/libgui/log_view.cpp
@@ -0,0 +1,135 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "log_view.h"
+
+#include <qpopupmenu.h>
+#include <qeventloop.h>
+#include <qapplication.h>
+#include <kiconloader.h>
+
+#include "global_config.h"
+#include "common/gui/purl_gui.h"
+#include "common/gui/misc_gui.h"
+
+Log::Widget::Widget(QWidget *parent, const char *name)
+ : QTextEdit(parent, name)
+{
+ setTextFormat(LogText);
+ setMinimumWidth(300);
+}
+
+void Log::Widget::updateDebugLevel()
+{
+ setDebugLevel(GlobalConfig::debugLevel());
+}
+
+void Log::Widget::logExtra(const QString &text)
+{
+ _text += text;
+ if ( GlobalConfig::logOutputType()==GuiConsole ) fprintf(stdout, "%s", text.latin1());
+}
+
+void Log::Widget::doLog(LineType type, const QString &text, Action action)
+{
+ doLog(text, type.data().color, type.data().bold, action);
+}
+
+void Log::Widget::doLog(DebugLevel level, const QString &text, Action action)
+{
+ doLog(text, level.data().color, false, action);
+}
+
+void Log::Widget::doLog(const QString &text, const QString &color, bool bold, Action action)
+{
+ logExtra(text + "\n");
+ QString s = QString("<font color=%1>").arg(color);
+ if (bold) s += "<b>";
+ s += escapeXml(text);
+ if (bold) s += "</b>";
+ s += "</font>";
+ QTextEdit::append(s);
+ updateContents(); // #### fix bug in Qt (display is messed up)
+ ensureVisible(0, contentsHeight());
+ if ( action==Immediate)
+ QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
+}
+
+void Log::Widget::appendToLastLine(const QString &text)
+{
+ logExtra(text);
+ uint p = paragraphs() - 1;
+ insertAt(escapeXml(text), p, paragraphLength(p));
+ updateContents(); // #### fix bug in Qt (display is messed up)
+ ensureVisible(0, contentsHeight());
+ // immediately visible...
+ QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput);
+}
+
+QPopupMenu *Log::Widget::createPopupMenu(const QPoint &pos)
+{
+ updateDebugLevel();
+ _popup = QTextEdit::createPopupMenu(pos);
+ KIconLoader loader;
+ QIconSet iset = loader.loadIconSet("filesave", KIcon::Small, 0);
+ _popup->insertItem(iset, "Save As...", this, SLOT(saveAs()));
+ iset = loader.loadIconSet("fileclose", KIcon::Small, 0);
+ _popup->insertItem(iset, "Clear", this, SLOT(clear()));
+ _popup->insertSeparator();
+ FOR_EACH(DebugLevel, level) {
+ _id[level.type()] = _popup->insertItem(level.label());
+ _popup->setItemChecked(_id[level.type()], _debugLevel==level);
+ }
+ _popup->insertSeparator();
+ int id = _popup->insertItem(i18n("Output in console"), this, SLOT(toggleConsoleOutput()));
+ _popup->setItemChecked(id, GlobalConfig::logOutputType()==GuiConsole);
+ connect(_popup, SIGNAL(activated(int)), SLOT(toggleVisible(int)));
+ return _popup;
+}
+
+void Log::Widget::toggleVisible(int id)
+{
+ FOR_EACH(DebugLevel, level) {
+ if ( _id[level.type()]==id ) {
+ _debugLevel = level;
+ GlobalConfig::writeDebugLevel(level);
+ break;
+ }
+ }
+}
+
+void Log::Widget::toggleConsoleOutput()
+{
+ GlobalConfig::writeLogOutputType(GlobalConfig::logOutputType()==GuiOnly ? GuiConsole : GuiOnly);
+}
+
+void Log::Widget::sorry(const QString &message, const QString &details)
+{
+ logExtra(message + " [" + details + "]\n");
+ MessageBox::detailedSorry(message, details, Log::Show);
+}
+
+bool Log::Widget::askContinue(const QString &message)
+{
+ bool ok = MessageBox::askContinue(message);
+ logExtra(message + " [" + (ok ? "continue" : "cancel") + "]\n");
+ return ok;
+}
+
+void Log::Widget::clear()
+{
+ QTextEdit::clear();
+ _text = QString::null;
+}
+
+void Log::Widget::saveAs()
+{
+ PURL::Url url = PURL::getSaveUrl(":save_log", "text/x-log", this, i18n("Save log to file"), PURL::AskOverwrite);
+ if ( url.isEmpty() ) return;
+ url.write(_text, *this);
+}
diff --git a/src/libgui/log_view.h b/src/libgui/log_view.h
new file mode 100644
index 0000000..c84849e
--- /dev/null
+++ b/src/libgui/log_view.h
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef LOG_VIEW_H
+#define LOG_VIEW_H
+
+#include <qtextedit.h>
+#include "common/global/log.h"
+
+namespace Log
+{
+enum OutputType { GuiOnly = 0, GuiConsole, Nb_OutputTypes };
+
+class Widget : public QTextEdit, public View
+{
+ Q_OBJECT
+public:
+ Widget(QWidget *parent = 0, const char *name = 0);
+ virtual void appendToLastLine(const QString &text);
+ virtual void clear();
+ virtual void sorry(const QString &message, const QString &details);
+ virtual bool askContinue(const QString &message);
+
+protected:
+ QPopupMenu *createPopupMenu(const QPoint &pos);
+
+private slots:
+ void toggleVisible(int i);
+ void toggleConsoleOutput();
+ void saveAs();
+
+private:
+ int _id[DebugLevel::Nb_Types];
+ QPopupMenu *_popup;
+ QString _text;
+
+ virtual void updateDebugLevel();
+ virtual void doLog(LineType type, const QString &text, Action action = Immediate);
+ virtual void doLog(DebugLevel level, const QString &text, Action action = Immediate);
+ void doLog(const QString &text, const QString &color, bool bold, Action action = Immediate);
+ void logExtra(const QString &text);
+};
+
+} // namespace
+
+#endif
diff --git a/src/libgui/main_global.cpp b/src/libgui/main_global.cpp
new file mode 100644
index 0000000..8741a44
--- /dev/null
+++ b/src/libgui/main_global.cpp
@@ -0,0 +1,81 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "main_global.h"
+
+#include <qpopupmenu.h>
+
+#include "toplevel.h"
+#include "common/global/about.h"
+#include "global_config.h"
+#include "devices/list/device_list.h"
+#include "project_manager.h"
+#include "editor_manager.h"
+#include "tools/list/compile_config.h"
+#include "gui_prog_manager.h"
+#include "device_editor.h"
+
+Main::State Main::_state = Main::Idle;
+MainWindow *Main::_toplevel = 0;
+EditorManager *Main::_editorManager = 0;
+ProjectManager::View *Main::_projectManager = 0;
+Breakpoint::View *Main::_breakpointsView = 0;
+Register::WatchView *Main::_watchView = 0;
+Compile::LogWidget *Main::_compileLog = 0;
+Compile::Manager *Main::_compileManager = 0;
+ConsoleView *Main::_consoleView = 0;
+
+void Main::setState(State state)
+{
+ _state = state;
+ _toplevel->updateGUI();
+}
+
+Programmer::Base *Main::programmer()
+{
+ return Programmer::manager->programmer();
+}
+
+const Programmer::Group &Main::programmerGroup()
+{
+ return GlobalConfig::programmerGroup();
+}
+
+Programmer::State Main::programmerState()
+{
+ return (programmer() ? programmer()->state() : Programmer::NotConnected);
+}
+
+KAction *Main::action(const char* name)
+{
+ return _toplevel->KMainWindow::action(name);
+}
+KAction *Main::action(KStdAction::StdAction action)
+{
+ return _toplevel->KMainWindow::action(KStdAction::name(action));
+}
+
+QPopupMenu &Main::popup(const char *name)
+{
+ QPopupMenu *popup = static_cast<QPopupMenu *>(_toplevel->factory()->container(name, _toplevel));
+ Q_ASSERT(popup);
+ return *popup;
+}
+
+const Device::Data *Main::deviceData()
+{
+ QString name = device();
+ if ( name==Device::AUTO_DATA.name )
+ name = DeviceEditor::guessDeviceFromFile(_projectManager->projectUrl());
+ return Device::lister().data(name);
+}
+
+Editor *Main::currentEditor() { return _editorManager->currentEditor(); }
+Project *Main::project() { return _projectManager->project(); }
+QString Main::device() { return Compile::Config::device(project()); }
+const Tool::Group &Main::toolGroup() { return Compile::Config::toolGroup(project()); }
diff --git a/src/libgui/main_global.h b/src/libgui/main_global.h
new file mode 100644
index 0000000..020253e
--- /dev/null
+++ b/src/libgui/main_global.h
@@ -0,0 +1,70 @@
+/***************************************************************************
+ * 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 MAIN_GLOBAL_H
+#define MAIN_GLOBAL_H
+
+#include <qstring.h>
+#include <qpopupmenu.h>
+#include <kstdaction.h>
+
+#include "progs/base/generic_prog.h"
+
+class EditorManager;
+namespace ProjectManager { class View; }
+class Editor;
+class Project;
+namespace Compile { class LogWidget; class Manager; }
+namespace Register { class List; class WatchView; }
+namespace Breakpoint { class View; }
+class MainWindow;
+namespace Programmer { class Group; class Base; }
+namespace Device { class Data; }
+namespace Tool { class Group; }
+class ConsoleView;
+
+class Main
+{
+public:
+ enum State { Idle, Compiling, Programming, Closing };
+ static void setState(State state);
+ static State state() { return _state; }
+
+ static MainWindow &toplevel() { return *_toplevel; }
+ static const Programmer::Group &programmerGroup();
+ static Programmer::Base *programmer();
+ static Programmer::State programmerState();
+ static KAction *action(const char *name);
+ static KAction *action(KStdAction::StdAction action);
+ static QPopupMenu &popup(const char *name);
+ static EditorManager &editorManager() { return *_editorManager; }
+ static Editor *currentEditor();
+ static QString device();
+ static const Device::Data *deviceData();
+ static Breakpoint::View &breakpointsView() { return *_breakpointsView; }
+ static ProjectManager::View &projectManager() { return *_projectManager; }
+ static Project *project();
+ static Register::WatchView &watchView() { return *_watchView; }
+ static Compile::LogWidget &compileLog() { return *_compileLog; }
+ static const Tool::Group &toolGroup();
+
+private:
+ static State _state;
+ static MainWindow *_toplevel;
+ static EditorManager *_editorManager;
+ static ProjectManager::View *_projectManager;
+ static Breakpoint::View *_breakpointsView;
+ static Register::WatchView *_watchView;
+ static Compile::LogWidget *_compileLog;
+ static Compile::Manager *_compileManager;
+ static ConsoleView *_consoleView;
+
+ friend class MainWindow;
+};
+
+#endif
diff --git a/src/libgui/new_dialogs.cpp b/src/libgui/new_dialogs.cpp
new file mode 100644
index 0000000..d26c15c
--- /dev/null
+++ b/src/libgui/new_dialogs.cpp
@@ -0,0 +1,83 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "new_dialogs.h"
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kpushbutton.h>
+
+#include "common/gui/purl_gui.h"
+#include "project.h"
+
+//----------------------------------------------------------------------------
+NewDialog::NewDialog(const QString &caption, QWidget *parent)
+ : Dialog(parent, "new_dialog", true, caption, Ok|Cancel, Ok, false)
+{
+ _top = new QGridLayout(mainWidget(), 0, 0, 10, 10);
+ _top->setColStretch(2, 1);
+
+ _fLabel = new QLabel(mainWidget());
+ _top->addWidget(_fLabel, 0, 0);
+ _filename = new QLineEdit(mainWidget());
+ connect(_filename, SIGNAL(textChanged(const QString &)), SLOT(changed()));
+ _top->addMultiCellWidget(_filename, 0,0, 1,3);
+
+ QLabel *label= new QLabel(i18n("Location:"), mainWidget());
+ _top->addWidget(label, 1, 0);
+ _dir = new QLineEdit(mainWidget());
+ connect(_dir, SIGNAL(textChanged(const QString &)), SLOT(changed()));
+ _top->addMultiCellWidget(_dir, 1,1, 1,2);
+ KIconLoader loader;
+ QIconSet iconset = loader.loadIcon("fileopen", KIcon::Toolbar);
+ KPushButton *button = new KPushButton(iconset, QString::null, mainWidget());
+ connect(button, SIGNAL(clicked()), SLOT(browse()));
+ _top->addWidget(button, 1, 3);
+
+ _filename->setFocus();
+ enableButtonOK(false);
+}
+
+void NewDialog::changed()
+{
+ enableButtonOK(!_filename->text().isEmpty() && !_dir->text().isEmpty());
+}
+
+void NewDialog::browse()
+{
+ PURL::Directory dir = PURL::getExistingDirectory(startDir(), this, QString::null);
+ if ( dir.isEmpty() ) return;
+ _dir->setText(dir.path());
+}
+
+//----------------------------------------------------------------------------
+NewFileDialog::NewFileDialog(Project *project, QWidget *parent)
+ : NewDialog(i18n("Create New File"), parent), _project(project)
+{
+ _fLabel->setText(i18n("File Name:"));
+
+ if (project) {
+ _add = new QCheckBox(i18n("Add to project"), mainWidget());
+ _add->setChecked(project);
+ _top->addMultiCellWidget(_add, 2,2, 1,2);
+ _top->setRowStretch(3, 1);
+ _dir->setText(project->directory().path());
+ }
+}
+
+QString NewFileDialog::startDir() const
+{
+ if (_project) return _project->directory().path();
+ return ":new_file";
+}
+
+PURL::Url NewFileDialog::url() const
+{
+ return PURL::Url(PURL::Directory(_dir->text()), _filename->text());
+}
diff --git a/src/libgui/new_dialogs.h b/src/libgui/new_dialogs.h
new file mode 100644
index 0000000..26e3cf7
--- /dev/null
+++ b/src/libgui/new_dialogs.h
@@ -0,0 +1,59 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef NEW_DIALOGS_H
+#define NEW_DIALOGS_H
+
+#include <qlineedit.h>
+#include <qcheckbox.h>
+#include <qcombobox.h>
+#include <qlabel.h>
+#include <qlayout.h>
+#include <kcombobox.h>
+
+#include "common/global/purl.h"
+#include "common/gui/dialog.h"
+class Project;
+
+//----------------------------------------------------------------------------
+class NewDialog : public Dialog
+{
+Q_OBJECT
+public:
+ NewDialog(const QString &caption, QWidget *parent);
+
+protected:
+ QGridLayout *_top;
+ QLabel *_fLabel;
+ QLineEdit *_filename, *_dir;
+
+ virtual QString startDir() const = 0;
+
+private slots:
+ void changed();
+ void browse();
+};
+
+//----------------------------------------------------------------------------
+class NewFileDialog : public NewDialog
+{
+Q_OBJECT
+public:
+ NewFileDialog(Project *project, QWidget *parent);
+ PURL::Url url() const;
+ bool addToProject() const { return (_project ? _add->isChecked() : false); }
+
+private:
+ Project *_project;
+ QCheckBox *_add;
+
+ virtual QString startDir() const;
+};
+
+#endif
diff --git a/src/libgui/object_view.cpp b/src/libgui/object_view.cpp
new file mode 100644
index 0000000..91625fb
--- /dev/null
+++ b/src/libgui/object_view.cpp
@@ -0,0 +1,145 @@
+/***************************************************************************
+ * 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 "object_view.h"
+
+#include <klocale.h>
+
+#include "devices/base/device_group.h"
+#include "devices/pic/pic/pic_memory.h"
+#include "tools/gputils/gputils.h"
+#include "hex_editor.h"
+#include "coff/base/text_coff.h"
+#include "coff/base/coff_archive.h"
+#include "main_global.h"
+#include "tools/list/compile_process.h"
+#include "coff/base/disassembler.h"
+#include "common/gui/misc_gui.h"
+
+//-----------------------------------------------------------------------------
+Coff::BaseEditor::BaseEditor(const PURL::Url &source, const Device::Data *data, QWidget *parent)
+ : SimpleTextEditor(true, parent), _source(source), _ok(false), _created(0), _device(data)
+{
+ setReadOnly(true);
+ _view->setDynWordWrap(false);
+ setView(&Main::compileLog());
+}
+
+Coff::BaseEditor::~BaseEditor()
+{
+ delete _created;
+}
+
+//-----------------------------------------------------------------------------
+Coff::CoffEditor::CoffEditor(const PURL::Url &source, const Device::Data &data, QWidget *parent)
+ : BaseEditor(source, &data, parent), _provided(0)
+{}
+
+Coff::CoffEditor::CoffEditor(const TextObject &object, QWidget *parent)
+ : BaseEditor(PURL::Url(), object.device(), parent), _provided(&object)
+{}
+
+bool Coff::CoffEditor::open(const PURL::Url &url)
+{
+ _url = url;
+ if (_provided) return setText(_provided->disassembly());
+ if ( _created==0 ) {
+ _created = new TextObject(_device, _source);
+ _ok = _created->parse(*this);
+ }
+ return setText(static_cast<Coff::TextObject *>(_created)->disassembly());
+}
+
+//-----------------------------------------------------------------------------
+Coff::ObjectEditor::ObjectEditor(const PURL::Url &source, QWidget *parent)
+ : BaseEditor(source, 0, parent)
+{}
+
+bool Coff::ObjectEditor::open(const PURL::Url &url)
+{
+ _url = url;
+ if ( _created==0 ) {
+ _created = new TextObject(0, _source);
+ _ok = _created->parse(*this);
+ }
+ if ( !_ok ) return setText(i18n("Error parsing object:\n") + error());
+ QString s = coff()->information().text() + "\n";
+ return setText(s);
+}
+
+//-----------------------------------------------------------------------------
+Coff::LibraryEditor::LibraryEditor(const PURL::Url &source, QWidget *parent)
+ : BaseEditor(source, 0, parent)
+{}
+
+bool Coff::LibraryEditor::open(const PURL::Url &url)
+{
+ _url = url;
+ if ( _created==0 ) {
+ _created = new Archive(_source);
+ _ok = _created->parse(*this);
+ }
+ if ( !_ok ) return setText(i18n("Error parsing library:\n") + error());
+ QString s = coff()->information().text() + "\n";
+ if ( coff()->members().count()!=0 ) s += coff()->membersInformation().text() + "\n";
+ if ( coff()->symbols().count()!=0 ) s += coff()->symbolsInformation().text() + "\n";
+ return setText(s);
+}
+
+//-----------------------------------------------------------------------------
+DisassemblyEditor::DisassemblyEditor(const PURL::Url &source, const Device::Data &data, QWidget *parent)
+ : SimpleTextEditor(true, parent), _source(source), _device(data), _editor(0)
+{
+ setReadOnly(true);
+ _view->setDynWordWrap(false);
+ setView(&Main::compileLog());
+}
+
+DisassemblyEditor::DisassemblyEditor(const HexEditor &e, const Device::Data &data, QWidget *parent)
+ : SimpleTextEditor(true, parent), _device(data), _editor(&e)
+{
+ setReadOnly(true);
+ _view->setDynWordWrap(false);
+ setView(&Main::compileLog());
+}
+
+bool DisassemblyEditor::open(const PURL::Url &url)
+{
+ _url = url;
+ if ( Main::toolGroup().name()!="sdcc" && Main::toolGroup().name()!="gputils" ) {
+ MessageBox::sorry(i18n("Disassembly not supported for the selected toolchain."), Log::Show);
+ return false;
+ }
+ Pic::Architecture arch = (_device.group().name()=="pic" ? static_cast<const Pic::Data &>(_device).architecture() : Pic::Architecture(Pic::Architecture::Nb_Types));
+ if ( arch==Pic::Architecture::Nb_Types ) {
+ MessageBox::sorry(i18n("Disassembly not supported for the selected device."), Log::Show);
+ return false;
+ }
+
+ Device::Memory *memory = 0;
+ if ( _editor==0 ) {
+ log(Log::LineType::Information, i18n("Disassembling hex file: %1").arg(_source.pretty()));
+ PURL::File file(_source, Main::compileLog());
+ if ( !file.openForRead() ) return false;
+ memory = _device.group().createMemory(_device);
+ QStringList errors, warnings;
+ Device::Memory::WarningTypes warningTypes;
+ if ( !memory->load(file.stream(), errors, warningTypes, warnings) ) {
+ delete memory;
+ log(Log::LineType::Error, errors[0]);
+ return false;
+ }
+ for (uint i=0; i<warnings.count(); i++) log(Log::LineType::Warning, warnings[i]);
+ } else {
+ log(Log::LineType::Information, i18n("Disassembling content of hex file editor."));
+ memory = const_cast<Device::Memory *>(_editor->memory());
+ }
+ SourceLine::List list = GPUtils::disassemble(static_cast<const Pic::Memory &>(*memory));
+ if ( _editor==0 ) delete memory;
+ return setText(SourceLine::text(PURL::SourceFamily::Asm, list, 4));
+}
diff --git a/src/libgui/object_view.h b/src/libgui/object_view.h
new file mode 100644
index 0000000..358101b
--- /dev/null
+++ b/src/libgui/object_view.h
@@ -0,0 +1,99 @@
+/***************************************************************************
+ * 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 OBJECT_VIEW_H
+#define OBJECT_VIEW_H
+
+#include "text_editor.h"
+#include "coff/base/coff_archive.h"
+#include "coff/base/coff_object.h"
+namespace Device { class Data; }
+class HexEditor;
+
+namespace Coff
+{
+class Base;
+class TextObject;
+
+//-----------------------------------------------------------------------------
+class BaseEditor : public SimpleTextEditor, public Log::Base
+{
+Q_OBJECT
+public:
+ BaseEditor(const PURL::Url &source, const Device::Data *data, QWidget *parent);
+ virtual ~BaseEditor();
+ virtual PURL::Url url() const { return _url; }
+
+protected:
+ PURL::Url _source, _url;
+ bool _ok;
+ Coff::Base *_created;
+ const Device::Data *_device;
+};
+
+//-----------------------------------------------------------------------------
+class CoffEditor : public BaseEditor
+{
+Q_OBJECT
+public:
+ CoffEditor(const PURL::Url &source, const Device::Data &data, QWidget *parent);
+ CoffEditor(const TextObject &object, QWidget *parent);
+ virtual PURL::FileType fileType() const { return PURL::Coff; }
+ virtual bool open(const PURL::Url &url);
+
+private:
+ const TextObject *_provided;
+};
+
+//-----------------------------------------------------------------------------
+class ObjectEditor : public BaseEditor
+{
+Q_OBJECT
+public:
+ ObjectEditor(const PURL::Url &source, QWidget *parent);
+ virtual PURL::FileType fileType() const { return PURL::Unknown; }
+ virtual bool open(const PURL::Url &url);
+
+private:
+ const Coff::Object *coff() const { return static_cast<const Coff::Object *>(_created); }
+};
+
+//-----------------------------------------------------------------------------
+class LibraryEditor : public BaseEditor
+{
+Q_OBJECT
+public:
+ LibraryEditor(const PURL::Url &source, QWidget *parent);
+ virtual PURL::FileType fileType() const { return PURL::Unknown; }
+ virtual bool open(const PURL::Url &url);
+
+private:
+ const Coff::Archive *coff() const { return static_cast<const Coff::Archive *>(_created); }
+};
+
+} // namespace
+
+//-----------------------------------------------------------------------------
+class DisassemblyEditor : public SimpleTextEditor, public Log::Base
+{
+Q_OBJECT
+public:
+ DisassemblyEditor(const PURL::Url &hexUrl, const Device::Data &data, QWidget *parent);
+ DisassemblyEditor(const HexEditor &e, const Device::Data &data, QWidget *parent);
+ virtual PURL::FileType fileType() const { return PURL::AsmGPAsm; }
+ virtual bool open(const PURL::Url &url);
+ virtual PURL::Url url() const { return _url; }
+
+private:
+ PURL::Url _source, _url;
+ const Device::Data &_device;
+ const HexEditor *_editor;
+};
+
+
+#endif
diff --git a/src/libgui/project.cpp b/src/libgui/project.cpp
new file mode 100644
index 0000000..dcf34c3
--- /dev/null
+++ b/src/libgui/project.cpp
@@ -0,0 +1,226 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003 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 "project.h"
+
+#include <ksimpleconfig.h>
+
+#include "devices/list/device_list.h"
+#include "progs/base/prog_group.h"
+#include "global_config.h"
+#include "tools/gputils/gputils_config.h"
+
+bool Project::load(QString &error)
+{
+ if ( _url.fileType()==PURL::Project ) return XmlDataFile::load(error);
+
+ if ( !_url.exists() ) {
+ error = i18n("Project file %1 does not exist.").arg(_url.pretty());
+ return false;
+ }
+ PURL::Url tmp = _url;
+ _url = _url.toFileType(PURL::Project);
+ if ( _url.exists() && XmlDataFile::load(error) ) return true;
+ KConfig *config = new KSimpleConfig(tmp.filepath(), false);
+
+ config->setGroup("Files");
+ QStringList list = config->readListEntry("inputFiles");
+ QStringList::const_iterator it = list.begin();
+ for (; it!=list.end(); ++it) addFile(PURL::Url(directory(), *it));
+
+ config->setGroup("General");
+ setVersion(config->readEntry("version", "0.1"));
+ setDescription(config->readEntry("description", QString::null));
+
+ config->setGroup("Assembler");
+ QString device = config->readEntry("target-device");
+ if ( device=="*" ) device = GlobalConfig::programmerGroup().supportedDevices()[0]; // compatibility
+ Compile::Config::setDevice(this, Device::lister().checkName(device));
+ GPUtils::Config *gconfig = new GPUtils::Config(this);
+ gconfig->setGPAsmWarningLevel(QMIN(config->readUnsignedNumEntry("warn-level", 0), uint(GPUtils::Config::Nb_WarningLevels)));
+ gconfig->setRawIncludeDirs(Tool::Category::Assembler, config->readEntry("include-dir", QString::null));
+ gconfig->setRawCustomOptions(Tool::Category::Assembler, config->readEntry("other-options", QString::null));
+
+ config->setGroup("Linker") ;
+ QString hexFormatString = config->readEntry("hex-format", HexBuffer::FORMATS[HexBuffer::IHX32]);
+ for (uint i=0; i<HexBuffer::Nb_Formats; i++)
+ if ( hexFormatString==HexBuffer::FORMATS[i] ) gconfig->setHexFormat(HexBuffer::Format(i));
+ gconfig->setRawIncludeDirs(Tool::Category::Linker, config->readEntry("objs-libs-dir", QString::null));
+ gconfig->setRawCustomOptions(Tool::Category::Linker, config->readEntry("other-options", QString::null));
+
+ delete gconfig;
+ delete config;
+ return true;
+}
+
+PURL::UrlList Project::openedFiles() const
+{
+ PURL::UrlList files;
+ QStringList list = listValues("general", "opened_files", QStringList());
+ QStringList::const_iterator it = list.begin();
+ for (; it!=list.end(); ++it) {
+ if ( PURL::Url::fromPathOrUrl(*it).isRelative() ) files += PURL::Url(directory(), *it);
+ else files += PURL::Url::fromPathOrUrl(*it);
+ }
+ return files;
+}
+void Project::setOpenedFiles(const PURL::UrlList &list)
+{
+ clearList("general", "opened_files");
+ PURL::UrlList::const_iterator it = list.begin();
+ for (; it!=list.end(); ++it)
+ appendListValue("general", "opened_files", (*it).relativeTo(directory()));
+}
+
+PURL::UrlList Project::absoluteFiles() const
+{
+ PURL::UrlList abs;
+ QStringList files = listValues("general", "files", QStringList());
+ QStringList::const_iterator it = files.begin();
+ for (; it!=files.end(); ++it) abs += PURL::Url::fromPathOrUrl(*it).toAbsolute(directory());
+ return abs;
+}
+void Project::addFile(const PURL::Url &url)
+{
+ appendListValue("general", "files", url.relativeTo(directory()));
+}
+void Project::removeFile(const PURL::Url &url)
+{
+ removeListValue("general", "files", url.relativeTo(directory()));
+}
+void Project::clearFiles()
+{
+ clearList("general", "files");
+}
+
+QString Project::toSourceObject(const PURL::Url &url, const QString &extension, bool forWindows) const
+{
+ PURL::Url tmp;
+ if ( extension.isEmpty() ) tmp = url.toFileType(PURL::Object);
+ else tmp = url.toExtension(extension);
+ return tmp.relativeTo(directory(), forWindows ? PURL::WindowsSeparator : PURL::UnixSeparator);
+}
+
+QStringList Project::objectsForLinker(const QString &extension, bool forWindows) const
+{
+ QStringList objs;
+ // objects files corresponding to src files
+ PURL::UrlList files = absoluteFiles();
+ PURL::UrlList::const_iterator it;
+ for (it=files.begin(); it!=files.end(); ++it)
+ if ( (*it).data().group==PURL::Source ) objs += toSourceObject(*it, extension, forWindows);
+ // objects
+ for (it=files.begin(); it!=files.end(); ++it)
+ if ( (*it).fileType()==PURL::Object ) objs += (*it).relativeTo(directory(), forWindows ? PURL::WindowsSeparator : PURL::UnixSeparator);
+ return objs;
+}
+
+QStringList Project::librariesForLinker(const QString &prefix, bool forWindows) const
+{
+ QStringList libs;
+ PURL::UrlList files = absoluteFiles();
+ PURL::UrlList::const_iterator it;
+ for (it=files.begin(); it!=files.end(); ++it)
+ if ( (*it).fileType()==PURL::Library ) libs += prefix + (*it).relativeTo(directory(), forWindows ? PURL::WindowsSeparator : PURL::UnixSeparator);
+ return libs;
+}
+
+QString Project::version() const
+{
+ return Compile::Config::globalValue(this, "version", "0.1");
+}
+void Project::setVersion(const QString &version)
+{
+ Compile::Config::setGlobalValue(this, "version", version);
+}
+
+Tool::OutputType Project::outputType() const
+{
+ return Tool::OutputType::fromKey(Compile::Config::globalValue(this, "output_type", Tool::OutputType(Tool::OutputType::Executable).key()));
+}
+void Project::setOutputType(Tool::OutputType type)
+{
+ Compile::Config::setGlobalValue(this, "output_type", type.key());
+}
+
+QString Project::description() const
+{
+ return Compile::Config::globalValue(this, "description", QString::null);
+}
+void Project::setDescription(const QString &description)
+{
+ Compile::Config::setGlobalValue(this, "description", description);
+}
+
+PURL::Url Project::customLinkerScript() const
+{
+ QString s = Compile::Config::globalValue(this, "custom_linker_script", QString::null);
+ return PURL::Url::fromPathOrUrl(s);
+}
+void Project::setCustomLinkerScript(const PURL::Url &url)
+{
+ Compile::Config::setGlobalValue(this, "custom_linker_script", url.filepath());
+}
+
+QValueList<Register::TypeData> Project::watchedRegisters() const
+{
+ QValueList<Register::TypeData> watched;
+ QStringList list = listValues("general", "watched_registers", QStringList());
+ QStringList::const_iterator it;
+ for (it=list.begin(); it!=list.end(); ++it) {
+ Register::TypeData rtd = Register::TypeData::fromString(*it);
+ if ( rtd.type()!=Register::Invalid ) watched.append(rtd);
+ }
+ return watched;
+}
+void Project::setWatchedRegisters(const QValueList<Register::TypeData> &watched)
+{
+ clearList("general", "watched_registers");
+ QValueList<Register::TypeData>::const_iterator it;
+ for (it=watched.begin(); it!=watched.end(); ++it)
+ appendListValue("general", "watched_registers", (*it).toString());
+}
+
+QValueList<uint> Project::bookmarkLines(const PURL::Url &url) const
+{
+ QValueList<uint> lines;
+ QStringList list = listValues("editors", "bookmarks", QStringList());
+ QStringList::const_iterator it;
+ for (it=list.begin(); it!=list.end(); ++it) {
+ QStringList slist = QStringList::split(",", *it);
+ QStringList::const_iterator sit = slist.begin();
+ if ( sit==slist.end() || (*sit)!=url.kurl().url() ) continue;
+ for (; sit!=slist.end(); ++sit) {
+ bool ok;
+ uint line = (*sit).toUInt(&ok);
+ if (!ok) continue;
+ lines.append(line);
+ }
+ break;
+ }
+ return lines;
+}
+void Project::setBookmarkLines(const PURL::Url &url, const QValueList<uint> &lines)
+{
+ QStringList list = listValues("editors", "bookmarks", QStringList());
+ QStringList nlist;
+ QStringList::const_iterator it;
+ for (it=list.begin(); it!=list.end(); ++it) {
+ QStringList slist = QStringList::split(",", *it);
+ QStringList::const_iterator sit = slist.begin();
+ if ( sit!=slist.end() && slist.count()>1 && (*sit)!=url.kurl().url() ) nlist += *it;
+ }
+ if ( lines.count()!=0 ) {
+ QStringList slist = url.kurl().url();
+ QValueList<uint>::const_iterator lit;
+ for (lit=lines.begin(); lit!=lines.end(); ++lit) slist += QString::number(*lit);
+ nlist += slist.join(",");
+ }
+ setListValues("editors", "bookmarks", nlist);
+}
diff --git a/src/libgui/project.h b/src/libgui/project.h
new file mode 100644
index 0000000..0dfdeab
--- /dev/null
+++ b/src/libgui/project.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003 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 PROJECT_H
+#define PROJECT_H
+
+#include "devices/base/register.h"
+#include "common/global/xml_data_file.h"
+#include "tools/base/generic_tool.h"
+
+class Project : public XmlDataFile
+{
+public:
+ Project(const PURL::Url &url) : XmlDataFile(url, "piklab") {}
+ virtual bool load(QString &error);
+
+ PURL::Directory directory() const { return url().directory(); }
+ QString name() const { return url().basename(); }
+ PURL::UrlList absoluteFiles() const;
+ QString version() const;
+ QString description() const;
+ Tool::OutputType outputType() const;
+ PURL::UrlList openedFiles() const;
+ PURL::Url customLinkerScript() const;
+ QValueList<Register::TypeData> watchedRegisters() const;
+ QString toSourceObject(const PURL::Url &url, const QString &extension, bool forWindows) const;
+ QStringList objectsForLinker(const QString &extension, bool forWindows) const;
+ QStringList librariesForLinker(const QString &prefix, bool forWindows) const;
+ QValueList<uint> bookmarkLines(const PURL::Url &url) const; // absolute filepath
+
+ void removeFile(const PURL::Url &url); // take absolute filepath (but inside project dir)
+ void addFile(const PURL::Url &url); // take absolute filePath (but inside project dir)
+ void clearFiles();
+ void setVersion(const QString &version);
+ void setDescription(const QString &description);
+ void setOutputType(Tool::OutputType type);
+ void setOpenedFiles(const PURL::UrlList &list);
+ void setCustomLinkerScript(const PURL::Url &url);
+ void setWatchedRegisters(const QValueList<Register::TypeData> &watched);
+ void setBookmarkLines(const PURL::Url &url, const QValueList<uint> &lines); // absolute filepath
+};
+
+#endif
diff --git a/src/libgui/project_editor.cpp b/src/libgui/project_editor.cpp
new file mode 100644
index 0000000..4b86429
--- /dev/null
+++ b/src/libgui/project_editor.cpp
@@ -0,0 +1,72 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003 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 "project_editor.h"
+
+#include <qlabel.h>
+#include <qlayout.h>
+#include <klocale.h>
+
+#include "project.h"
+#include "tools/list/compile_config.h"
+#include "device_gui.h"
+
+ProjectEditor::ProjectEditor(Project &project, QWidget *parent)
+ : Dialog(parent, "project_options", true, i18n("Project Options"), Ok|Cancel, Ok, false),
+ _project(project)
+{
+ QVBoxLayout *top = new QVBoxLayout(mainWidget(), 0, 10);
+ TabWidget *tabWidget = new TabWidget(mainWidget());
+ top->addWidget(tabWidget);
+
+// global
+ QWidget *tab = new QWidget(tabWidget);
+ tabWidget->addTab(tab, i18n("General"));
+ QGridLayout *grid = new QGridLayout(tab, 0, 0, 10, 10);
+ QLabel *label = new QLabel(i18n("Name:"), tab);
+ grid->addWidget(label, 0, 0);
+ label = new QLabel(project.name(), tab);
+ grid->addWidget(label, 0, 1);
+ label = new QLabel(i18n("Description:"), tab);
+ grid->addWidget(label, 1, 0);
+ _description = new QTextEdit(tab);
+ _description->setText(_project.description());
+ grid->addMultiCellWidget(_description, 1,1, 1,2);
+ label = new QLabel(i18n("Version:"), tab);
+ grid->addWidget(label, 2, 0);
+ _version = new QLineEdit(tab);
+ _version->setText(_project.version());
+ grid->addWidget(_version, 2, 1);
+ label = new QLabel(i18n("Device:"), tab);
+ grid->addWidget(label, 3, 0);
+ _device = new DeviceChooser::Button(false, tab);
+ _device->setDevice(Compile::Config::device(&_project));
+ grid->addWidget(_device, 3, 1);
+ grid->setRowStretch(4, 1);
+ grid->setColStretch(2, 1);
+
+// toochain
+ tab = new QWidget(tabWidget);
+ tabWidget->addTab(tab, i18n("Toochain"));
+ grid = new QGridLayout(tab, 0, 0, 10, 10);
+ _tools = new ToolsConfigWidget(&project, tab);
+ _tools->loadConfig();
+ grid->addMultiCellWidget(_tools, 0,0, 0,2);
+ grid->setRowStretch(1, 1);
+ grid->setColStretch(2, 1);
+}
+
+void ProjectEditor::slotOk()
+{
+ _project.setDescription(_description->text());
+ _project.setVersion(_version->text());
+ Compile::Config::setDevice(&_project, _device->device());
+ _tools->saveConfig();
+ accept();
+}
diff --git a/src/libgui/project_editor.h b/src/libgui/project_editor.h
new file mode 100644
index 0000000..5e83fe2
--- /dev/null
+++ b/src/libgui/project_editor.h
@@ -0,0 +1,47 @@
+/***************************************************************************
+ ProjectEditorWid.cpp - description
+ -------------------
+ begin : lun déc 8 2003
+ copyright : (C) 2003 by Alain Gibaud
+ email : alain.gibaud@univ-valenciennes.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 PROJECT_EDITOR_H
+#define PROJECT_EDITOR_H
+
+#include <qtextedit.h>
+#include <qlineedit.h>
+#include <qcombobox.h>
+#include <qwidgetstack.h>
+
+#include "tools/list/tools_config_widget.h"
+#include "common/gui/misc_gui.h"
+class Project;
+namespace DeviceChooser { class Button; }
+
+class ProjectEditor : public Dialog
+{
+Q_OBJECT
+public:
+ ProjectEditor(Project &project, QWidget *parent);
+
+private slots:
+ virtual void slotOk();
+
+private:
+ Project &_project;
+ QTextEdit *_description;
+ QLineEdit *_version;
+ DeviceChooser::Button *_device;
+ ToolsConfigWidget *_tools;
+};
+
+#endif
diff --git a/src/libgui/project_manager.cpp b/src/libgui/project_manager.cpp
new file mode 100644
index 0000000..dcc4941
--- /dev/null
+++ b/src/libgui/project_manager.cpp
@@ -0,0 +1,651 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003 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 "project_manager.h"
+
+#include <qdragobject.h>
+#include <qpainter.h>
+#include <qstyle.h>
+#include <qtimer.h>
+#include <qheader.h>
+
+#include <klocale.h>
+#include <kiconloader.h>
+#include <kaction.h>
+#include <kapplication.h>
+
+#include "project.h"
+#include "project_wizard.h"
+#include "project_editor.h"
+#include "toplevel.h"
+#include "editor_manager.h"
+#include "object_view.h"
+#include "devices/list/device_list.h"
+#include "tools/list/compile_config.h"
+#include "register_view.h"
+#include "hex_editor.h"
+#include "main_global.h"
+#include "common/gui/purl_gui.h"
+#include "device_gui.h"
+
+//----------------------------------------------------------------------------
+ProjectManager::View::View(QWidget *parent)
+ : ListView(parent, "project_manager"), _project(0), _modified(false)
+{
+ connect(this, SIGNAL(mouseButtonClicked(int, QListViewItem *, const QPoint &, int)),
+ SLOT(clicked(int, QListViewItem *, const QPoint &, int)));
+ connect(this, SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)),
+ SLOT(contextMenu(QListViewItem *, const QPoint &, int)));
+ connect(this, SIGNAL(itemRenamed(QListViewItem *, int, const QString &)),
+ SLOT(renamed(QListViewItem *, int, const QString &)));
+ connect(this, SIGNAL(moved()), SLOT(filesReordered()));
+
+ header()->hide();
+ setSorting(-1);
+ addColumn(QString::null, 170);
+ setFullWidth(true);
+ setRootIsDecorated(false);
+ setAcceptDrops(true);
+ setDragEnabled(true);
+ setDropVisualizer(true);
+ QTimer::singleShot(0, this, SLOT(init()));;
+}
+
+ProjectManager::View::~View()
+{
+ delete _project;
+}
+
+void ProjectManager::View::init()
+{
+ clear();
+ _rootItem = new RootItem(this);
+ setCurrentItem(_rootItem);
+ KListViewItem *item = new RegisterItem(headerItem(DeviceGroup));
+ ensureItemVisible(item);
+ _deviceItem = new DeviceItem(headerItem(DeviceGroup));
+ ensureItemVisible(_deviceItem);
+ _linkerScriptItem = 0;
+ (void)headerItem(SourceGroup);
+}
+
+ProjectManager::HeaderItem *ProjectManager::View::findHeaderItem(Group group) const
+{
+ QListViewItemIterator it(const_cast<View *>(this));
+ for(; it.current(); ++it) {
+ if ( it.current()->rtti()!=HeaderRtti ) continue;
+ HeaderItem *hi = static_cast<HeaderItem *>(it.current());
+ if ( hi->group()==group ) return hi;
+ }
+ return 0;
+}
+
+ProjectManager::HeaderItem *ProjectManager::View::headerItem(Group group)
+{
+ HeaderItem *item = findHeaderItem(group);
+ if (item) return item;
+ item = new HeaderItem(_rootItem, group);
+ // reorder groups...
+ HeaderItem *items[Nb_Groups];
+ for (uint i=0; i<Nb_Groups; i++) {
+ items[i] = findHeaderItem(Group(i));
+ if (items[i]) _rootItem->takeItem(items[i]);
+ }
+ for (int i=Nb_Groups-1; i>=0; i--) {
+ if ( items[i]==0 ) continue;
+ _rootItem->insertItem(items[i]);
+ }
+ return item;
+}
+
+ProjectManager::FileItem *ProjectManager::View::findFileItem(const PURL::Url &url) const
+{
+ QListViewItemIterator it(const_cast<View *>(this));
+ for(; it.current(); ++it) {
+ if ( it.current()->rtti()!=FileRtti ) continue;
+ FileItem *fi = static_cast<FileItem *>(it.current());
+ if ( fi->url()==url ) return fi;
+ }
+ return 0;
+}
+
+ProjectManager::FileItem *ProjectManager::View::findFileItem(PURL::FileType type) const
+{
+ QListViewItemIterator it(const_cast<View *>(this));
+ for(; it.current(); ++it) {
+ if ( it.current()->rtti()!=FileRtti ) continue;
+ FileItem *fi = static_cast<FileItem *>(it.current());
+ if ( fi->ftype()==type ) return fi;
+ }
+ return 0;
+}
+
+QListViewItem *ProjectManager::View::findItem(const QString &tag) const
+{
+ QListViewItemIterator it(const_cast<View *>(this));
+ for(; it.current(); ++it) {
+ switch (Rtti(it.current()->rtti())) {
+ case RootRtti:
+ case FileRtti:
+ case LinkerScriptRtti:
+ case DeviceRtti: continue;
+ case HeaderRtti:
+ case RegisterRtti: break;
+ }
+ if ( it.current()->text(0)==tag ) return it.current();
+ }
+ return 0;
+}
+
+void ProjectManager::View::select(const Editor *e)
+{
+ QListViewItem *item = 0;
+ if ( e->url().isEmpty() ) item = findItem(e->tag());
+ else item = findFileItem(e->url());
+ if (item) setSelected(item, true);
+ else clearSelection();
+}
+
+void ProjectManager::View::contextMenu(QListViewItem *item, const QPoint &p, int)
+{
+ if ( item==0 ) return;
+
+ PopupMenu pop;
+ Group group = Nb_Groups;
+ if ( item->rtti()==HeaderRtti) group = static_cast<const HeaderItem *>(item)->group();
+
+ if ( item->rtti()==LinkerScriptRtti || group==LinkerScriptGroup ) {
+ if ( _project==0 || Main::toolGroup().linkerScriptType()==PURL::Nb_FileTypes ) return;
+ pop.insertTitle(i18n("Linker Script"));
+ pop.insertItem("piklab_addfile", i18n("Set Custom..."));
+ if ( !_project->customLinkerScript().isEmpty() ) pop.insertItem("editdelete", i18n("Set Default"));
+ switch( pop.exec(p) ) {
+ case 1: {
+ PURL::Url url = PURL::getOpenUrl(":custom_linker_script", PURL::filter(Main::toolGroup().linkerScriptType()), this, i18n("Select Linker Script"));
+ if ( !url.isEmpty() ) _project->setCustomLinkerScript(url);
+ break;
+ }
+ case 2: _project->setCustomLinkerScript(PURL::Url()); break;
+ }
+ _linkerScriptItem->init();
+ } else if ( item->rtti()==RootRtti ) {
+ RootItem *ri = static_cast<RootItem *>(item);
+ if ( _project==0 ) {
+ if ( ri->url().isEmpty() ) {
+ pop.insertItem("piklab_createproject", i18n("New Project..."), &Main::toplevel(), SLOT(newProject()));
+ pop.insertItem("piklab_openproject", i18n("Open Project..."), &Main::toplevel(), SLOT(openProject()));
+ pop.exec(p);
+ } else {
+ pop.insertTitle(i18n("Standalone File"));
+ pop.insertItem("configure", i18n("Configure..."));
+ if ( pop.exec(p)==1 ) Main::toplevel().configure(ConfigCenter::Standalone);
+ }
+ } else {
+ pop.insertTitle(i18n("Project"));
+ pop.insertItem("configure", i18n("Options..."), &Main::toplevel(), SLOT(configureProject()));
+ pop.insertItem("find", i18n("Find Files..."), &Main::toplevel(), SLOT(runKfind()));
+ pop.insertSeparator();
+ pop.insertItem("piklab_compile", i18n("Build Project"), &Main::toplevel(), SLOT(buildProject()));
+ pop.insertItem("trashcan_empty", i18n("Clean Project"), &Main::toplevel(), SLOT(cleanBuild()));
+ pop.insertSeparator();
+ pop.insertItem("filenew", i18n("New Source File..."), &Main::toplevel(), SLOT(newSourceFile()));
+ pop.insertItem("piklab_addfile", i18n("Add Source Files..."), this, SLOT(insertSourceFiles()));
+ pop.insertItem("piklab_addfile", i18n("Add Object Files..."), this, SLOT(insertObjectFiles()));
+ if ( Main::currentEditor() ) pop.insertItem("piklab_addcurrentfile", i18n("Add Current File"), this, SLOT(insertCurrentFile()));
+ pop.exec(p);
+ }
+ } else if ( item->rtti()==FileRtti ) {
+ if ( _project==0 ) return;
+ FileItem *fi = static_cast<FileItem *>(item);
+ if ( isExternalFile(fi->url()) ) return;
+ pop.insertTitle(item->text(0));
+ pop.insertItem("editdelete", i18n("Remove From Project"));
+ if ( pop.exec(p)==1 ) removeFile(fi->url());
+ } else if ( item->rtti()==HeaderRtti ) {
+ if ( _project==0 ) return;
+ if ( group==LinkerObjectGroup ) {
+ pop.insertTitle(i18n("Objects"));
+ pop.insertItem("piklab_addfile", i18n("Add Object Files..."), this, SLOT(insertObjectFiles()));
+ pop.exec(p);
+ } else if ( group==SourceGroup || group==HeaderGroup ) {
+ pop.insertTitle(i18n("Sources"));
+ pop.insertItem("filenew", i18n("New File..."), &Main::toplevel(), SLOT(newSourceFile()));
+ pop.insertItem("piklab_addfile", i18n("Add Source Files..."), this, SLOT(insertSourceFiles()));
+ pop.exec(p);
+ } else if ( group==DeviceGroup ) {
+ pop.insertItem("filenew", i18n("Select Device..."), &Main::toplevel(), SLOT(showDeviceInfo()));
+ pop.exec(p);
+ }
+ }
+}
+
+void ProjectManager::View::closeProject()
+{
+ if ( _project==0 && projectUrl().isEmpty() ) return;
+ if (_project) {
+ // save opened files
+ PURL::UrlList files = Main::editorManager().files();
+ PURL::UrlList::const_iterator it = files.begin();
+ PURL::UrlList opened;
+ for (; it!=files.end(); ++it) {
+ if ( !isExternalFile(*it) ) opened += *it;
+ Main::editorManager().closeEditor(*it);
+ }
+ _project->setOpenedFiles(opened);
+ // save watched registers
+ _project->setWatchedRegisters(Register::list().watched());
+ QString error;
+ if ( !_project->save(error) )
+ MessageBox::detailedSorry(i18n("Could not save project file \"%1\".").arg(_project->url().pretty()), error, Log::Show);
+ delete _project;
+ _project = 0;
+ }
+ _modified = false;
+ init();
+}
+
+void ProjectManager::View::addExternalFiles()
+{
+ const QMap<PURL::Url, FileOrigin> &ext = projectData().externals;
+ QMap<PURL::Url, FileOrigin>::const_iterator it;
+ for (it=ext.begin(); it!=ext.end(); ++it) {
+ if ( !it.key().exists() ) continue;
+ addFile(it.key(), it.key().fileType(), it.data());
+ }
+}
+
+void ProjectManager::View::setStandalone(const PURL::Url &url, PURL::FileType type)
+{
+ if ( projectUrl()==url ) return;
+ closeProject();
+ _rootItem->set(url, true);
+ addFile(url, type, Intrinsic);
+ _standaloneData[url].type = type;
+ addExternalFiles();
+}
+
+PURL::Url ProjectManager::View::standaloneGenerator(const PURL::Url &url, PURL::FileType &type) const
+{
+ QMap<PURL::Url, ProjectData>::const_iterator it;
+ for (it=_standaloneData.begin(); it!=_standaloneData.end(); ++it) {
+ if ( !it.data().externals.contains(url) ) continue;
+ if ( !it.key().exists() ) continue;
+ type = it.data().type;
+ return it.key();
+ }
+ type = PURL::Nb_FileTypes;
+ return url;
+}
+
+void ProjectManager::View::insertSourceFiles()
+{
+ Q_ASSERT(_project);
+ PURL::UrlList list = PURL::getOpenUrls(":<sources>", PURL::sourceFilter(PURL::CompleteFilter), this, i18n("Select Source File"));
+ if ( list.isEmpty() ) return;
+ PURL::UrlList::const_iterator it;
+ for (it=list.begin(); it!=list.end(); ++it) insertFile(*it);
+}
+
+void ProjectManager::View::insertObjectFiles()
+{
+ Q_ASSERT(_project);
+ PURL::UrlList list = PURL::getOpenUrls(":<objects>", PURL::objectFilter(PURL::CompleteFilter), this, i18n("Select Object File"));
+ if ( list.isEmpty() ) return;
+ PURL::UrlList::const_iterator it;
+ for (it=list.begin(); it!=list.end(); ++it) insertFile(*it);
+}
+
+void ProjectManager::View::insertFile(const PURL::Url &url)
+{
+ if ( !url.exists() ) {
+ MessageBox::detailedSorry(i18n("Could not find file."), i18n("File: %1").arg(url.pretty()), Log::Show);
+ return;
+ }
+ PURL::Url purl = url;
+ MessageBox::Result copy = MessageBox::No;
+ if ( !url.isInto(_project->directory()) ) {
+ copy = MessageBox::questionYesNoCancel(i18n("File \"%1\" is not inside the project directory. Do you want to copy the file to your project directory?").arg(url.pretty()),
+ i18n("Copy and Add"), i18n("Add only"));
+ if ( copy==MessageBox::Cancel ) return;
+ if ( copy==MessageBox::Yes ) purl = PURL::Url(_project->directory(), url.filename());
+ }
+ if ( _project->absoluteFiles().contains(purl) ) {
+ MessageBox::detailedSorry(i18n("File is already in the project."), i18n("File: %1").arg(purl.pretty()), Log::Show);
+ return;
+ }
+ if ( copy==MessageBox::Yes ) {
+ Log::StringView sview;
+ if ( !url.copyTo(purl, sview) ) {
+ MessageBox::detailedSorry(i18n("Copying file to project directory failed."), i18n("File: %1\n").arg(url.pretty()) + sview.string(), Log::Show);
+ return;
+ }
+ }
+ _project->addFile(purl);
+ addFile(purl, purl.fileType(), Intrinsic);
+}
+
+bool ProjectManager::View::openProject()
+{
+ PURL::Url url = PURL::getOpenUrl(":open_project", PURL::projectFilter(PURL::CompleteFilter), this, i18n("Select Project file"));
+ return openProject(url);
+}
+
+void ProjectManager::View::addExternalFile(const PURL::Url &url, FileOrigin origin)
+{
+ Q_ASSERT( origin!=Intrinsic );
+ addFile(url, url.fileType(), origin);
+}
+
+const ProjectManager::View::ProjectData &ProjectManager::View::projectData() const
+{
+ if ( _project==0 ) return _standaloneData[projectUrl()];
+ return _projectData;
+}
+
+ProjectManager::View::ProjectData &ProjectManager::View::projectData()
+{
+ if ( _project==0 ) return _standaloneData[projectUrl()];
+ return _projectData;
+}
+
+void ProjectManager::View::addFile(const PURL::Url &url, PURL::FileType type, FileOrigin origin)
+{
+ if ( contains(url) ) return;
+ QMap<PURL::Url, FileOrigin> &ext = projectData().externals;
+ if ( type.data().group==PURL::LinkerScript && _linkerScriptItem ) {
+ _linkerScriptItem->set(url);
+ ext[url] = Included;
+ return;
+ }
+ PURL::FileProperties properties = type.data().properties;
+ Group grp = Nb_Groups;
+ switch (origin) {
+ case Intrinsic: grp = group(type); break;
+ case Generated: grp = GeneratedGroup; break;
+ case Included: grp = IncludedGroup; break;
+ }
+ HeaderItem *hitem = headerItem(grp);
+ QListViewItem *item = new FileItem(hitem, type, url, origin!=Intrinsic);
+ item->moveItem(hitem->lastChild());
+ ensureItemVisible(item);
+ if ( origin!=Intrinsic ) ext[url] = origin;
+ if ( type==PURL::Hex && _project==0 ) {
+ QString extension = PURL::extension(PURL::AsmGPAsm);
+ PURL::Url durl = PURL::Url::fromPathOrUrl("<" + (url.isEmpty() ? i18n("Disassembly") : url.appendExtension(extension).filename()) + ">");
+ if ( findFileItem(durl)==0 ) {
+ (void)new FileItem(headerItem(ViewGroup), PURL::Coff, durl, true);
+ ext[durl] = Generated;
+ }
+ }
+ if ( _project && origin==Intrinsic ) _modified = true;
+}
+
+void ProjectManager::View::removeExternalFiles()
+{
+ QMap<PURL::Url, FileOrigin> &ext = projectData().externals;
+ QMap<PURL::Url, FileOrigin>::const_iterator it;
+ for (it=ext.begin(); it!=ext.end(); ++it) {
+ Main::editorManager().closeEditor(it.key());
+ removeFile(it.key());
+ }
+ ext.clear();
+ if (_linkerScriptItem) _linkerScriptItem->init();
+}
+
+void ProjectManager::View::removeFile(const PURL::Url &url)
+{
+ if ( _project && !isExternalFile(url) ) _project->removeFile(url);
+ FileItem *item = findFileItem(url);
+ if ( item==0 ) return;
+ HeaderItem *group = static_cast<HeaderItem *>(item->parent());
+ delete item;
+ if ( group->childCount()==0 ) delete group;
+ _modified = true;
+ emit guiChanged();
+}
+
+void ProjectManager::View::clicked(int button, QListViewItem *item, const QPoint &, int)
+{
+ if ( item==0 ) return;
+ if ( button!=LeftButton ) return;
+ const Device::Data *data = Main::deviceData();
+ Rtti rtti = Rtti(item->rtti());
+ if ( data==0 && rtti!=DeviceRtti && rtti!=RootRtti ) {
+ MessageBox::sorry(i18n("Cannot open without device specified."), Log::Show);
+ return;
+ }
+ Editor *e = 0;
+ ::BusyCursor bc;
+ switch (rtti) {
+ case RootRtti:
+ Main::toplevel().configureProject();
+ break;
+ case HeaderRtti: {
+ if ( static_cast<HeaderItem *>(item)->group()!=DeviceGroup ) break;
+ e = Main::editorManager().openEditor(EditorManager::DeviceEditor);
+ break;
+ }
+ case RegisterRtti:
+ e = Main::editorManager().openEditor(EditorManager::RegisterEditor);
+ break;
+ case DeviceRtti: return;
+ case LinkerScriptRtti: {
+ PURL::Url url = Main::projectManager().linkerScriptUrl();
+ if ( url.isEmpty() ) break;
+ e = Main::editorManager().findEditor(url);
+ if ( e==0 ) {
+ e = Main::editorManager().createEditor(url.fileType(), url);
+ if ( !e->open(url) ) {
+ delete e;
+ break;
+ }
+ if ( e && isExternalFile(url) ) e->setReadOnly(true);
+ Main::editorManager().addEditor(e);
+ } else Main::editorManager().showEditor(e);
+ break;
+ }
+ case FileRtti: {
+ FileItem *fi = static_cast<FileItem *>(item);
+ if ( !(fi->ftype().data().properties & PURL::Editable) ) break;
+ e = Main::editorManager().findEditor(fi->url());
+ if ( e==0 ) {
+ if ( fi->ftype()==PURL::Coff && _project==0 && !fi->url().exists() ) {
+ PURL::Url url = findFileItem(PURL::Hex)->url();
+ if ( url.isEmpty() ) {
+ HexEditor *he = ::qt_cast<HexEditor *>(Main::currentEditor());
+ if ( he==0 ) break;
+ e = new DisassemblyEditor(*he, *data, this);
+ } else e = new DisassemblyEditor(url, *data, this);
+ addExternalFile(fi->url(), Generated);
+ } else e = Main::editorManager().createEditor(fi->url().fileType(), fi->url());
+ if ( e==0 ) break;
+ if ( !e->open(fi->url()) ) {
+ delete e;
+ break;
+ }
+ if ( isExternalFile(fi->url()) ) e->setReadOnly(true);
+ Main::editorManager().addEditor(e);
+ } else Main::editorManager().showEditor(e);
+ break;
+ }
+ }
+ cancelRenaming();
+ emit guiChanged();
+}
+
+void ProjectManager::View::insertCurrentFile()
+{
+ insertFile(Main::editorManager().currentEditor()->url());
+}
+
+bool ProjectManager::View::editProject()
+{
+ ProjectEditor dialog(*_project, this);
+ if ( dialog.exec()!=QDialog::Accepted ) return false;
+ _modified = true;
+ if (_linkerScriptItem) _linkerScriptItem->init();
+ return true;
+}
+
+bool ProjectManager::View::newProject()
+{
+ ProjectWizard wizard(this);
+ if ( wizard.exec()==QDialog::Rejected ) return false;
+ closeProject();
+ QString error;
+ if ( !wizard.project()->save(error) ) {
+ MessageBox::detailedSorry(i18n("Failed to create new project file"), error, Log::Show);
+ return false;
+ }
+ openProject(wizard.url());
+ return true;
+}
+
+void ProjectManager::View::setProject(Project *project)
+{
+ closeProject();
+ Main::editorManager().closeAllEditors();
+ _project = project;
+ _rootItem->set(project->url(), false);
+ if ( project && Main::toolGroup().linkerScriptType()!=PURL::Nb_FileTypes ) {
+ _linkerScriptItem = new LinkerScriptItem(headerItem(LinkerScriptGroup));
+ ensureItemVisible(_linkerScriptItem);
+ }
+}
+
+bool ProjectManager::View::openProject(const PURL::Url &url)
+{
+ if ( url.isEmpty() ) return false;
+ bool reload = ( _project && _project->url()==url );
+ if ( reload && !MessageBox::askContinue(i18n("Project already loaded. Reload?"), i18n("Reload")) ) return false;
+ static_cast< KRecentFilesAction *>(Main::action("project_open_recent"))->removeURL(url.kurl());
+ Project *p = new Project(url);
+ QString error;
+ if ( !p->load(error) ) {
+ MessageBox::detailedSorry(i18n("Could not open project file."), error, Log::Show);
+ delete p;
+ return false;
+ }
+ setProject(p);
+ PURL::UrlList files = _project->absoluteFiles();
+ PURL::UrlList::const_iterator it;
+ for(it=files.begin(); it!=files.end(); ++it) addFile(*it, (*it).fileType(), Intrinsic);
+ _projectData.type = PURL::Project;
+ _projectData.externals.clear();
+ static_cast<KRecentFilesAction *>(Main::action("project_open_recent"))->addURL(url.kurl());
+ files = _project->openedFiles();
+ for(it = files.begin(); it!=files.end(); ++it) Main::editorManager().openFile(*it);
+ Register::list().init();
+ QValueList<Register::TypeData> watched = _project->watchedRegisters();
+ QValueList<Register::TypeData>::const_iterator wit;
+ for (wit=watched.begin(); wit!=watched.end(); ++wit) Register::list().setWatched(*wit, true);
+ return true;
+}
+
+bool ProjectManager::View::isExternalFile(const PURL::Url &url) const
+{
+ if ( projectUrl().isEmpty() ) return false;
+ return projectData().externals.contains(url);
+}
+
+void ProjectManager::View::modified(const PURL::Url &url)
+{
+ FileItem *item = findFileItem(url);
+ if ( item && !isExternalFile(url) ) _modified = true;
+}
+
+void ProjectManager::View::renamed(QListViewItem *item, int, const QString &text)
+{
+ Q_ASSERT ( item->rtti()==DeviceRtti );
+ Main::toplevel().setDevice(text);
+}
+
+void ProjectManager::View::updateGUI()
+{
+ _deviceItem->updateText();
+}
+
+QDragObject *ProjectManager::View::dragObject()
+{
+ if ( currentItem()==0 || currentItem()->rtti()!=FileRtti ) return 0;
+ const FileItem *item = static_cast<const FileItem *>(currentItem());
+ const HeaderItem *hitem = static_cast<const HeaderItem *>(item->parent());
+ if ( hitem->group()!=SourceGroup ) return 0;
+ QStrList uris;
+ uris.append(QUriDrag::localFileToUri(item->url().filepath()));
+ return new QUriDrag(uris, viewport());
+}
+
+bool ProjectManager::View::acceptDrag(QDropEvent* e) const
+{
+ if ( e->source()!=viewport() ) return false;
+ const QListViewItem *item = itemAt(e->pos());
+ if ( item==0 || item->rtti()!=FileRtti ) return false;
+ const HeaderItem *hitem = static_cast<const HeaderItem *>(item->parent());
+ return ( hitem->group()==SourceGroup );
+}
+
+void ProjectManager::View::filesReordered()
+{
+ if ( _project==0 ) return;
+ _project->clearFiles();
+ QListViewItem *item = headerItem(SourceGroup)->firstChild();
+ for (;item; item=item->nextSibling())
+ _project->addFile(static_cast<FileItem *>(item)->url());
+}
+
+QString ProjectManager::View::tooltip(QListViewItem *item, int) const
+{
+ switch (Rtti(item->rtti())) {
+ case RootRtti:
+ case FileRtti:
+ case LinkerScriptRtti: return static_cast<const UrlItem *>(item)->url().filepath();
+ case DeviceRtti:
+ case RegisterRtti:
+ case HeaderRtti: break;
+ }
+ return QString::null;
+}
+
+PURL::Url ProjectManager::View::linkerScriptUrl() const
+{
+ QListViewItemIterator it(const_cast<View *>(this));
+ for(; it.current(); ++it) {
+ if ( it.current()->rtti()!=LinkerScriptRtti ) continue;
+ return static_cast<LinkerScriptItem *>(it.current())->url();
+ }
+ return PURL::Url();
+}
+
+bool ProjectManager::View::needsRecompile() const
+{
+ // ### this could be perfected...
+ PURL::Url output = projectUrl().toFileType(PURL::Hex);
+ QDateTime outputLastModified;
+ if ( !output.exists(&outputLastModified) ) return true;
+ PURL::UrlList files;
+ if ( Main::project() ) files = Main::project()->absoluteFiles();
+ else files.append(projectUrl());
+ PURL::UrlList::const_iterator it;
+ for (it=files.begin(); it!=files.end(); ++it) {
+ QDateTime lastModified;
+ if ( !(*it).exists(&lastModified) ) continue;
+ if ( lastModified>outputLastModified ) return true;
+ }
+ return false;
+}
+
+PURL::Url ProjectManager::View::selectedUrl() const
+{
+ QListViewItem *item = currentItem();
+ if ( item==0 ) return PURL::Url();
+ Rtti rtti = Rtti(item->rtti());
+ if ( rtti!=FileRtti ) return PURL::Url();
+ return static_cast<FileItem *>(item)->url();
+}
diff --git a/src/libgui/project_manager.h b/src/libgui/project_manager.h
new file mode 100644
index 0000000..2939f33
--- /dev/null
+++ b/src/libgui/project_manager.h
@@ -0,0 +1,106 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003 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 PROJECT_MANAGER_H
+#define PROJECT_MANAGER_H
+
+#include "common/global/purl.h"
+#include "common/gui/misc_gui.h"
+#include "common/gui/list_view.h"
+#include "project_manager_ui.h"
+class Project;
+class Editor;
+namespace Coff { class SectionParser; }
+
+namespace ProjectManager
+{
+
+class View : public ListView
+{
+Q_OBJECT
+public:
+ View(QWidget *parent);
+ virtual ~View();
+
+ bool editProject();
+ bool newProject();
+ bool openProject();
+ bool openProject(const PURL::Url &url);
+ void closeProject();
+ Project *project() const { return _project; }
+
+ void setStandalone(const PURL::Url &url, PURL::FileType type);
+ PURL::Url projectUrl() const { return _rootItem->url(); }
+ PURL::Url standaloneGenerator(const PURL::Url &url, PURL::FileType &type) const;
+ PURL::Url linkerScriptUrl() const;
+ PURL::Url selectedUrl() const;
+ void removeFile(const PURL::Url &url);
+ void select(const Editor *e);
+ void insertFile(const PURL::Url &url);
+ bool contains(const PURL::Url &url) const { return findFileItem(url); }
+ void addExternalFile(const PURL::Url &url, FileOrigin fileOrigin);
+ bool isExternalFile(const PURL::Url &url) const;
+ void removeExternalFiles();
+
+ bool isModified() const { return _modified; }
+ void setModified(bool modified) { _modified = modified; }
+ bool needsRecompile() const;
+
+public slots:
+ void insertSourceFiles();
+ void insertObjectFiles();
+ void insertCurrentFile();
+ void updateGUI();
+
+private slots:
+ void init();
+ void contextMenu(QListViewItem *item, const QPoint &pos, int column);
+ void clicked(int button, QListViewItem *item, const QPoint &pos, int column);
+ void renamed(QListViewItem *item, int column, const QString &text);
+ void modified(const PURL::Url &url);
+ void filesReordered();
+
+signals:
+ void guiChanged();
+
+private:
+ Project *_project;
+ RootItem *_rootItem;
+ DeviceItem *_deviceItem;
+ LinkerScriptItem *_linkerScriptItem;
+ class ProjectData {
+ public:
+ PURL::FileType type;
+ QMap<PURL::Url, FileOrigin> externals;
+ };
+ QMap<PURL::Url, ProjectData> _standaloneData;
+ ProjectData _projectData;
+ bool _modified;
+
+ HeaderItem *findHeaderItem(Group group) const;
+ HeaderItem *headerItem(Group group);
+ FileItem *findFileItem(const PURL::Url &url) const;
+ FileItem *findFileItem(PURL::FileType type) const;
+ QListViewItem *findItem(const QString &name) const;
+ virtual QDragObject *dragObject();
+ virtual bool acceptDrag(QDropEvent* e) const;
+ virtual QString tooltip(QListViewItem *item, int col) const;
+ void addExternalFiles();
+ void rightClicked(QListViewItem *item, const QPoint &pos);
+ void leftClicked(QListViewItem *item);
+ void addFile(const PURL::Url &url, PURL::FileType type, FileOrigin origin);
+ void setProject(Project *project);
+ void initListView();
+ ProjectData &projectData();
+ const ProjectData &projectData() const;
+};
+
+} // namespace
+
+#endif
diff --git a/src/libgui/project_manager_ui.cpp b/src/libgui/project_manager_ui.cpp
new file mode 100644
index 0000000..235d360
--- /dev/null
+++ b/src/libgui/project_manager_ui.cpp
@@ -0,0 +1,185 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003 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 "project_manager_ui.h"
+
+#include <qpainter.h>
+#include <kiconloader.h>
+
+#include "project.h"
+#include "devices/list/device_list.h"
+#include "main_global.h"
+#include "common/gui/purl_gui.h"
+#include "device_gui.h"
+
+//----------------------------------------------------------------------------
+void PopupMenu::insertItem(const QString &icon, const QString &label, QObject *receiver, const char *slot)
+{
+ KIconLoader loader;
+ QPixmap pixmap = loader.loadIcon(icon, KIcon::Small);
+ if (receiver) KPopupMenu::insertItem(pixmap, label, receiver, slot, 0, _index);
+ else KPopupMenu::insertItem(pixmap, label, _index);
+ _index++;
+}
+
+//----------------------------------------------------------------------------
+const char *ProjectManager::HeaderItem::GROUP_LABELS[Nb_Groups] = {
+ I18N_NOOP("Device"), I18N_NOOP("Headers"), I18N_NOOP("Linker Script"),
+ I18N_NOOP("Sources"), I18N_NOOP("Objects"), I18N_NOOP("Views"),
+ I18N_NOOP("Generated"), I18N_NOOP("Included")
+};
+
+ProjectManager::Group ProjectManager::group(PURL::FileType type)
+{
+ switch (type.data().group) {
+ case PURL::Source: return SourceGroup;
+ case PURL::Header: return HeaderGroup;
+ case PURL::LinkerScript: return LinkerScriptGroup;
+ case PURL::LinkerObject: return LinkerObjectGroup;
+ case PURL::Nb_FileGroups: break;
+ }
+ return ViewGroup;
+}
+
+ProjectManager::RootItem::RootItem(KListView *listview)
+ : UrlItem(listview)
+{
+ setSelectable(false);
+ setPixmap(0, PURL::icon(PURL::Project));
+ set(PURL::Url(), true);
+}
+
+void ProjectManager::RootItem::set(const PURL::Url &url, bool standalone)
+{
+ _url = url;
+ _standalone = standalone;
+ if ( _url.isEmpty() ) setText(0, i18n("<no project>"));
+ else if (_standalone) setText(0, i18n("Standalone File"));
+ else setText(0, _url.basename());
+}
+
+ProjectManager::HeaderItem::HeaderItem(RootItem *item, Group group)
+ : KListViewItem(item), _group(group)
+{
+ if ( group!=DeviceGroup) setSelectable(false);
+ setText(0, i18n(GROUP_LABELS[group]));
+}
+
+QListViewItem *ProjectManager::HeaderItem::lastChild() const
+{
+ QListViewItem *item = firstChild();
+ if ( item==0 ) return 0;
+ for (;;) {
+ if ( item->nextSibling()==0 ) break;
+ item = item->nextSibling();
+ }
+ return item;
+}
+
+ProjectManager::FileItem::FileItem(HeaderItem *item, PURL::FileType ftype,
+ const PURL::Url &url, bool external)
+ : UrlItem(item), _ftype(ftype), _external(external)
+{
+ setPixmap(0, PURL::icon(ftype));
+ set(url);
+}
+
+void ProjectManager::FileItem::set(const PURL::Url &url)
+{
+ _url = url;
+ switch (_ftype.type()) {
+ case PURL::Hex: setText(0, i18n("Hex File")); break;
+ case PURL::Coff: setText(0, i18n("Disassembly Listing")); break;
+ case PURL::Lst: setText(0, i18n("List")); break;
+ case PURL::Map: setText(0, i18n("Memory Map")); break;
+ case PURL::Project:
+ case PURL::Nb_FileTypes: Q_ASSERT(false); break;
+ default: {
+ QString s = url.filename();
+ if ( _external && group(_ftype)==LinkerScriptGroup )
+ s += i18n(" (default)");
+ setText(0, s); break;
+ }
+ }
+}
+
+void ProjectManager::FileItem::paintCell(QPainter *p, const QColorGroup &cg,
+ int column, int width, int align)
+{
+ QFont f = p->font();
+ f.setItalic(group(_ftype)!=ViewGroup && _external);
+ p->setFont(f);
+ KListViewItem::paintCell(p, cg, column, width, align);
+}
+
+ProjectManager::RegisterItem::RegisterItem(HeaderItem *item)
+ : KListViewItem(item)
+{
+ KIconLoader loader;
+ QPixmap chip = loader.loadIcon("piklab_chip", KIcon::Small);
+ setPixmap(0, chip);
+ setText(0, i18n("Registers"));
+}
+
+ProjectManager::DeviceItem::DeviceItem(HeaderItem *item)
+ : EditListViewItem(item)
+{}
+
+QWidget *ProjectManager::DeviceItem::editWidgetFactory(int) const
+{
+ QComboBox *combo = new DeviceChooser::ComboBox(Main::project()==0, 0);
+ QString device = Main::device();
+ if ( device!=Device::AUTO_DATA.name ) combo->setCurrentText(device);
+ QObject::connect(combo, SIGNAL(activated(int)), listView(), SLOT(finishRenaming()));
+ return combo;
+}
+
+void ProjectManager::DeviceItem::updateText()
+{
+ QString device = Main::device();
+ if ( device==Device::AUTO_DATA.name ) {
+ const Device::Data *data = Main::deviceData();
+ if (data) device = data->name() + " " + i18n(Device::AUTO_DATA.label);
+ else device = i18n(Device::AUTO_DATA.label);
+ }
+ setText(0, device);
+}
+
+ProjectManager::LinkerScriptItem::LinkerScriptItem(HeaderItem *item)
+ : UrlItem(item)
+{
+ init();
+}
+
+void ProjectManager::LinkerScriptItem::init()
+{
+ _url = PURL::Url();
+ PURL::Url lkr;
+ if ( Main::project() ) lkr = Main::project()->customLinkerScript();
+ setText(0, lkr.isEmpty() ? i18n("<default>") : lkr.filename());
+ setPixmap(0, lkr.isEmpty() ? QPixmap() : PURL::icon(PURL::Lkr));
+}
+
+void ProjectManager::LinkerScriptItem::set(const PURL::Url &url)
+{
+ _url = url;
+ QString s = url.filename();
+ PURL::Url lkr;
+ if ( Main::project() ) lkr = Main::project()->customLinkerScript();
+ if ( lkr.isEmpty() ) s += i18n(" (default)");
+ setText(0, s);
+ setPixmap(0, PURL::icon(PURL::Lkr));
+}
+
+PURL::Url ProjectManager::LinkerScriptItem::url() const
+{
+ if ( !_url.isEmpty() ) return _url;
+ if ( Main::project() ) return Main::project()->customLinkerScript();
+ return PURL::Url();
+}
diff --git a/src/libgui/project_manager_ui.h b/src/libgui/project_manager_ui.h
new file mode 100644
index 0000000..012eb64
--- /dev/null
+++ b/src/libgui/project_manager_ui.h
@@ -0,0 +1,121 @@
+/***************************************************************************
+ * Copyright (C) 2005-2006 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003 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 PROJECT_MANAGER_UI_H
+#define PROJECT_MANAGER_UI_H
+
+#include <kpopupmenu.h>
+
+#include "common/global/purl.h"
+#include "common/gui/misc_gui.h"
+#include "common/gui/list_view.h"
+
+//-----------------------------------------------------------------------------
+class PopupMenu : public KPopupMenu
+{
+Q_OBJECT
+public:
+ PopupMenu() : _index(1) {}
+ void insertItem(const QString &icon, const QString &label, QObject *receiver = 0, const char *slot = 0);
+
+private:
+ uint _index;
+};
+
+//-----------------------------------------------------------------------------
+namespace ProjectManager
+{
+ enum Rtti { RootRtti = 1000, HeaderRtti, FileRtti, DeviceRtti, RegisterRtti, LinkerScriptRtti };
+ enum Group { DeviceGroup = 0, HeaderGroup, LinkerScriptGroup, SourceGroup,
+ LinkerObjectGroup, ViewGroup, GeneratedGroup, IncludedGroup, Nb_Groups };
+ extern Group group(PURL::FileType type);
+ enum FileOrigin { Intrinsic, Generated, Included };
+
+class UrlItem : public KListViewItem
+{
+public:
+ UrlItem(KListView *listview) : KListViewItem(listview) {}
+ UrlItem(KListViewItem *item) : KListViewItem(item) {}
+ virtual PURL::Url url() const { return _url; }
+
+protected:
+ PURL::Url _url;
+};
+
+class RootItem : public UrlItem
+{
+public:
+ RootItem(KListView *listview);
+ void set(const PURL::Url &url, bool standAlone);
+ virtual int rtti() const { return RootRtti; }
+
+private:
+ bool _standalone;
+};
+
+class HeaderItem : public KListViewItem
+{
+public:
+ HeaderItem(RootItem *item, Group group);
+ virtual int rtti() const { return HeaderRtti; }
+ Group group() const { return _group; }
+ QListViewItem *lastChild() const;
+
+private:
+ static const char *GROUP_LABELS[Nb_Groups];
+ Group _group;
+};
+
+class FileItem : public UrlItem
+{
+public:
+ FileItem(HeaderItem *item, PURL::FileType type, const PURL::Url &url, bool external);
+ virtual int rtti() const { return FileRtti; }
+ PURL::FileType ftype() const { return _ftype; }
+
+private:
+ PURL::FileType _ftype;
+ bool _external;
+
+ void set(const PURL::Url &url);
+ virtual void paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align);
+};
+
+class RegisterItem : public KListViewItem
+{
+public:
+ RegisterItem(HeaderItem *item);
+ virtual int rtti() const { return RegisterRtti; }
+};
+
+class DeviceItem : public EditListViewItem
+{
+public:
+ DeviceItem(HeaderItem *item);
+ void updateText();
+ virtual int rtti() const { return DeviceRtti; }
+
+private:
+ virtual QWidget *editWidgetFactory(int) const;
+ virtual bool alwaysAcceptEdit(int) const { return true; }
+};
+
+class LinkerScriptItem : public UrlItem
+{
+public:
+ LinkerScriptItem(HeaderItem *item);
+ void set(const PURL::Url &url);
+ virtual PURL::Url url() const;
+ void init();
+ virtual int rtti() const { return LinkerScriptRtti; }
+};
+
+} // namespace
+
+#endif
diff --git a/src/libgui/project_wizard.cpp b/src/libgui/project_wizard.cpp
new file mode 100644
index 0000000..b4d26df
--- /dev/null
+++ b/src/libgui/project_wizard.cpp
@@ -0,0 +1,283 @@
+/***************************************************************************
+ * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "project_wizard.h"
+
+#include <qheader.h>
+#include <qvbuttongroup.h>
+#include <qradiobutton.h>
+#include <qstyle.h>
+#include <kfiledialog.h>
+#include <kiconloader.h>
+
+#include "common/gui/purl_gui.h"
+#include "device_gui.h"
+#include "tools/list/tool_list.h"
+#include "tools/list/compile_config.h"
+#include "main_global.h"
+#include "project.h"
+#include "tools/list/compile_process.h"
+#include "common/gui/editlistbox.h"
+#include "devices/list/device_list.h"
+
+//-----------------------------------------------------------------------------
+FileListItem::FileListItem(KListView *view)
+ : KListViewItem(view), _group(0), _copy(true)
+{
+ KIconLoader loader;
+ _pixmap = loader.loadIcon("button_ok", KIcon::Small);
+}
+
+void FileListItem::toggle()
+{
+ _copy = !_copy;
+ repaint();
+}
+
+PURL::FileGroup FileListItem::fileGroup() const
+{
+ if ( _group==0 ) return PURL::Nb_FileGroups;
+ PURL::Url url = PURL::Url::fromPathOrUrl(text(1));
+ switch (url.data().group) {
+ case PURL::Source: {
+ FOR_EACH(PURL::ToolType, type)
+ if ( _group->implementationType(type)==url.fileType() ) return PURL::Source;
+ break;
+ }
+ case PURL::Header: return PURL::Header;
+ case PURL::LinkerScript: {
+ if ( _group->linkerScriptType()==url.fileType() ) return PURL::LinkerScript;
+ break;
+ }
+ case PURL::LinkerObject: return PURL::LinkerObject;
+ case PURL::Nb_FileGroups: break;
+ }
+ return PURL::Nb_FileGroups;
+}
+
+const QPixmap *FileListItem::pixmap(int column) const
+{
+
+ if ( column==0 && _copy ) return &_pixmap;
+ return KListViewItem::pixmap(column);
+}
+
+//-----------------------------------------------------------------------------
+FileListBox::FileListBox(QWidget *parent)
+ : EditListBox(2, 0, 0, parent, "file_list_box")
+{
+ _listView->header()->show();
+ _listView->header()->setClickEnabled(false);
+ _listView->header()->setResizeEnabled(false);
+ _listView->header()->setMovingEnabled(false);
+ _listView->setColumnText(0, i18n("Copy"));
+ int spacing = style().pixelMetric(QStyle::PM_HeaderMargin);
+ QFontMetrics fm(font());
+ _listView->header()->resizeSection(0, fm.width(i18n("Copy")) + 2*spacing); // hack
+ _listView->setColumnText(1, i18n("Filename"));
+ _listView->setAllColumnsShowFocus(true);
+ connect(_listView, SIGNAL(clicked(QListViewItem *, const QPoint &, int)), SLOT(clicked(QListViewItem *, const QPoint &, int)));
+}
+
+void FileListBox::addItem()
+{
+ PURL::UrlList urls = PURL::getOpenUrls(_directory.path(), QString::null, this, i18n("Select Files"));
+ PURL::UrlList::const_iterator it;
+ for (it=urls.begin(); it!=urls.end(); ++it) EditListBox::addItem((*it).pretty());
+}
+
+QListViewItem *FileListBox::createItem()
+{
+ return new FileListItem(_listView);
+}
+
+void FileListBox::clicked(QListViewItem *item, const QPoint &, int column)
+{
+ if ( item==0 || column!=0 ) return;
+ static_cast<FileListItem *>(item)->toggle();
+}
+
+void FileListBox::setToolGroup(const Tool::Group &group)
+{
+ QListViewItem *item = _listView->firstChild();
+ for (; item; item = item->nextSibling()) static_cast<FileListItem *>(item)->setToolGroup(group);
+}
+
+//-----------------------------------------------------------------------------
+ProjectWizard::ProjectWizard(QWidget *parent)
+ : KWizard(parent, "project_wizard"), _project(0)
+{
+ // first page
+ _first = new QWidget(this);
+ addPage(_first, i18n("New Project: Basic Settings"));
+ setHelpEnabled(_first, false);
+ QGridLayout *grid = new QGridLayout(_first, 1, 1, 10, 10);
+ QLabel *label = new QLabel(i18n("Name:"), _first);
+ grid->addWidget(label, 0, 0);
+ _name = new KLineEdit(_first);
+ _name->setFocus();
+ grid->addMultiCellWidget(_name, 0,0, 1,2);
+ label = new QLabel(i18n("Directory:"), _first);
+ grid->addWidget(label, 1, 0);
+ _directory = new PURL::DirectoryWidget(":new_project", _first);
+ grid->addMultiCellWidget(_directory, 1,1, 1,2);
+ label = new QLabel(i18n("Device:"), _first);
+ grid->addWidget(label, 2, 0);
+ _device = new DeviceChooser::Button(false, _first);
+ _device->setDevice(Main::device());
+ grid->addWidget(_device, 2, 1);
+ label = new QLabel(i18n("Toolchain:"), _first);
+ grid->addWidget(label, 3, 0);
+ _toolchain = new KeyComboBox<QString>(_first);
+ Tool::Lister::ConstIterator it;
+ for (it=Tool::lister().begin(); it!=Tool::lister().end(); ++it)
+ _toolchain->appendItem(it.key(), it.data()->label());
+ _toolchain->setCurrentItem(Main::toolGroup().name());
+ grid->addWidget(_toolchain->widget(), 3, 1);
+ grid->setColStretch(2, 1);
+ grid->setRowStretch(4, 1);
+
+ // second page
+ _second = new QWidget(this);
+ addPage(_second, i18n("New Project: Source Files"));
+ grid = new QGridLayout(_second, 1, 1, 10, 10);
+ _bgroup = new QVButtonGroup(i18n("Add Source Files"), _second);
+ _templateButton = new QRadioButton(i18n("Create template source file."), _bgroup);
+ _addButton = new QRadioButton(i18n("Add existing files."), _bgroup);
+ (void)new QRadioButton(i18n("Do not add files now."), _bgroup);
+ connect(_bgroup, SIGNAL(clicked(int)), SLOT(buttonClicked(int)));
+ grid->addWidget(_bgroup, 0, 0);
+
+ // third page
+ _third = new QWidget(this);
+ addPage(_third, i18n("New Project: Add Files"));
+ setHelpEnabled(_third, false);
+ setFinishEnabled(_third, true);
+ grid = new QGridLayout(_third, 1, 1, 10, 10);
+ _files = new FileListBox(_third);
+ grid->addWidget(_files, 0, 0);
+}
+
+void ProjectWizard::next()
+{
+ if ( currentPage()==_first ) {
+ QString name = _name->text().stripWhiteSpace();
+ if ( name.isEmpty() ) {
+ MessageBox::sorry(i18n("Project name is empty."), Log::Show);
+ return;
+ }
+ PURL::Directory directory = _directory->directory();
+ if ( directory.isEmpty() ) {
+ MessageBox::sorry(i18n("Directory is empty."), Log::Show);
+ return;
+ }
+ Log::StringView sview;
+ if ( !directory.exists() ) {
+ if ( !MessageBox::askContinue(i18n("Directory does not exists. Create it?")) ) return;
+ if ( !_directory->directory().create(sview) ) {
+ MessageBox::detailedSorry(i18n("Error creating directory."), sview.string(), Log::Show);
+ return;
+ }
+ } else if ( url().exists() ) {
+ if ( !MessageBox::askContinue(i18n("Project \"%1\"already exists. Overwrite it?").arg(url().filename())) ) return;
+ }
+ if ( !toolchain().check(device(), &Main::compileLog()) ) return;
+ _files->setDirectory(_directory->directory());
+ _files->setToolGroup(toolchain());
+ if ( toolchain().name()=="custom" ) {
+ _templateButton->hide();
+ _addButton->setChecked(true);
+ } else {
+ _templateButton->show();
+ _templateButton->setChecked(true);
+ }
+ buttonClicked(0);
+ }
+ if ( currentPage()==_third ) {
+ uint nb = 0;
+ for (uint i=0; i<_files->count(); i++)
+ if ( static_cast<const FileListItem *>(_files->item(i))->fileGroup()==PURL::Source ) nb++;
+ if ( toolchain().compileType()==Tool::SingleFile && nb>1 ) {
+ if ( !MessageBox::askContinue(i18n("The selected toolchain can only compile a single source file and you have selected %1 source files. Continue anyway? ").arg(nb)) ) return;
+ }
+ }
+ KWizard::next();
+}
+
+void ProjectWizard::done(int r)
+{
+ if ( r==Accepted ) {
+ PURL::UrlList files;
+ _project = new Project(url());
+ Compile::Config::setDevice(_project, device());
+ Compile::Config::setToolGroup(_project, toolchain());
+ Compile::Config::setCustomCommands(_project, Compile::Config::customCommands(0));
+
+ if ( _bgroup->selectedId()==0 ) {
+ PURL::ToolType ttype = PURL::ToolType::Compiler;
+ PURL::FileType ftype = PURL::Nb_FileTypes;
+ FOR_EACH(PURL::ToolType, i) {
+ PURL::FileType type = toolchain().implementationType(i);
+ if ( type==PURL::Nb_FileTypes ) continue;
+ ftype = type;
+ ttype = i;
+ }
+ Q_ASSERT( ftype!=PURL::Nb_FileTypes );
+ PURL::Url turl = url().toFileType(ftype);
+ QString text;
+ const Tool::SourceGenerator *generator = toolchain().sourceGenerator();
+ if ( generator==0 ) text = i18n("Template source file generation not implemented yet for this toolchain...");
+ else {
+ bool ok = true;
+ const Device::Data *data = Device::lister().data(device());
+ SourceLine::List lines;
+ SourceLine::List list = generator->templateSourceFile(ttype, *data, ok);
+ if ( !ok ) lines.appendTitle(i18n("Template source file generation only partially implemented."));
+ lines += list;
+ text = SourceLine::text(ftype.data().sourceFamily, lines, 4);
+ }
+ Log::StringView sview;
+ if ( turl.write(text, sview) ) files += turl;
+ else MessageBox::detailedSorry(i18n("Error creating template file."), i18n("File: %1\n").arg(turl.pretty()) + sview.string(), Log::Show);
+ _project->setOpenedFiles(files);
+ } else {
+ Log::StringView sview;
+ for (uint i=0; i<_files->count(); i++) {
+ PURL::Url furl = PURL::Url::fromPathOrUrl(_files->text(i));
+ if ( static_cast<const FileListItem *>(_files->item(i))->copy() ) {
+ PURL::Url to(url().directory(), furl.filename());
+ if ( furl==to || furl.copyTo(to, sview) ) files += to;
+ } else files += furl;
+ }
+ }
+ PURL::UrlList::const_iterator it;
+ for (it=files.begin(); it!=files.end(); ++it) _project->addFile(*it);
+ }
+ KWizard::done(r);
+}
+
+PURL::Url ProjectWizard::url() const
+{
+ return PURL::Url(PURL::Directory(_directory->directory()), _name->text(), PURL::Project);
+}
+
+const Tool::Group &ProjectWizard::toolchain() const
+{
+ return *Tool::lister().group(_toolchain->currentItem());
+}
+
+QString ProjectWizard::device() const
+{
+ return _device->device();
+}
+
+void ProjectWizard::buttonClicked(int id)
+{
+ setNextEnabled(_second, id==1);
+ setFinishEnabled(_second, id!=1);
+}
diff --git a/src/libgui/project_wizard.h b/src/libgui/project_wizard.h
new file mode 100644
index 0000000..312ef01
--- /dev/null
+++ b/src/libgui/project_wizard.h
@@ -0,0 +1,91 @@
+/***************************************************************************
+ * Copyright (C) 2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef PROJECT_WIZARD_H
+#define PROJECT_WIZARD_H
+
+#include <qbuttongroup.h>
+#include <qradiobutton.h>
+#include <kwizard.h>
+#include <klineedit.h>
+#include <kcombobox.h>
+
+#include "common/global/purl.h"
+#include "common/gui/editlistbox.h"
+#include "common/gui/key_gui.h"
+namespace PURL { class DirectoryWidget; }
+namespace DeviceChooser { class Button; }
+namespace Tool { class Group; }
+class Project;
+
+//-----------------------------------------------------------------------------
+class FileListItem : public KListViewItem
+{
+public:
+ FileListItem(KListView *view);
+ void setToolGroup(const Tool::Group &group) { _group = &group; }
+ bool copy() const { return _copy; }
+ void toggle();
+ PURL::FileGroup fileGroup() const;
+ virtual const QPixmap *pixmap(int column) const;
+
+private:
+ const Tool::Group *_group;
+ QPixmap _pixmap;
+ bool _copy;
+};
+
+class FileListBox : public EditListBox
+{
+Q_OBJECT
+public:
+ FileListBox(QWidget *parent);
+ void setDirectory(const PURL::Directory &directory) { _directory = directory; }
+ void setToolGroup(const Tool::Group &group);
+
+protected slots:
+ virtual void addItem();
+ virtual void clicked(QListViewItem *item, const QPoint &point, int column);
+
+private:
+ PURL::Directory _directory;
+
+ virtual uint textColumn() const { return 1; }
+ virtual QListViewItem *createItem();
+};
+
+//-----------------------------------------------------------------------------
+class ProjectWizard : public KWizard
+{
+Q_OBJECT
+public:
+ ProjectWizard(QWidget *parent);
+ PURL::Url url() const;
+ Project *project() const { return _project; }
+
+protected slots:
+ void buttonClicked(int id);
+ virtual void next();
+ virtual void done(int r);
+
+private:
+ QWidget *_first, *_second, *_third;
+ KLineEdit *_name;
+ PURL::DirectoryWidget *_directory;
+ DeviceChooser::Button *_device;
+ KeyComboBox<QString> *_toolchain;
+ QButtonGroup *_bgroup;
+ QRadioButton *_templateButton, *_addButton;
+ FileListBox *_files;
+ Project *_project;
+
+ QString device() const;
+ const Tool::Group &toolchain() const;
+};
+
+#endif
diff --git a/src/libgui/register_view.cpp b/src/libgui/register_view.cpp
new file mode 100644
index 0000000..3c244e8
--- /dev/null
+++ b/src/libgui/register_view.cpp
@@ -0,0 +1,51 @@
+/***************************************************************************
+ * 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 "register_view.h"
+
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qpushbutton.h>
+#include <qcheckbox.h>
+#include <klocale.h>
+
+#include "devices/base/device_group.h"
+#include "devices/gui/device_group_ui.h"
+#include "progs/base/prog_group.h"
+#include "common/gui/misc_gui.h"
+#include "main_global.h"
+#include "editor_manager.h"
+#include "gui_debug_manager.h"
+
+//-----------------------------------------------------------------------------
+Register::MainView::MainView(const QString &title, const QString &tag, QWidget *parent)
+ : DeviceEditor(title, tag, parent, "register_view"), _debugging(false)
+{}
+
+void Register::MainView::setDevice(bool force)
+{
+ bool oldDebugging = _debugging;
+ _debugging = Main::programmerGroup().isDebugger();
+ DeviceEditor::setDevice(force || oldDebugging!=_debugging);
+}
+
+QWidget *Register::MainView::createView(const Device::Data *data, QWidget *parent)
+{
+ if ( data==0 ) return new QWidget(parent);
+ Register::View *view = Device::groupui(*data).createRegisterView(parent);
+ if (view) view->updateView();
+ else {
+ QWidget *w = new QWidget(parent);
+ QVBoxLayout *vbox = new QVBoxLayout(w, 10, 10);
+ QLabel *label = new QLabel(i18n("The selected device has no register."), w);
+ vbox->addWidget(label);
+ vbox->addStretch(1);
+ return w;
+ }
+ return view;
+}
diff --git a/src/libgui/register_view.h b/src/libgui/register_view.h
new file mode 100644
index 0000000..7d12f0d
--- /dev/null
+++ b/src/libgui/register_view.h
@@ -0,0 +1,42 @@
+/***************************************************************************
+ * 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 REGISTER_EDITOR_H
+#define REGISTER_EDITOR_H
+
+#include "device_editor.h"
+#include "devices/gui/register_view.h"
+
+namespace Register
+{
+class View;
+
+//-----------------------------------------------------------------------------
+class MainView : public DeviceEditor
+{
+Q_OBJECT
+public:
+ MainView(const QString &title, const QString &tag, QWidget *parent = 0);
+ virtual bool isModified() const { return false; }
+ virtual bool isReadOnly() const { return true; }
+ virtual void addGui() {}
+ virtual void removeGui() {}
+ virtual void setFocus() {}
+ virtual void setDevice(bool force = false);
+ Register::View *view() { return static_cast<Register::View *>(_view); }
+
+private:
+ bool _debugging;
+ virtual QWidget *createView(const Device::Data *, QWidget *parent);
+ virtual void setModifiedInternal(bool) {}
+ virtual void setReadOnlyInternal(bool) {}
+};
+
+} // namespace
+
+#endif
diff --git a/src/libgui/text_editor.cpp b/src/libgui/text_editor.cpp
new file mode 100644
index 0000000..aecbc99
--- /dev/null
+++ b/src/libgui/text_editor.cpp
@@ -0,0 +1,346 @@
+/***************************************************************************
+ * 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 "text_editor.h"
+
+#include <qfile.h>
+#include <qtextedit.h>
+#include <qlayout.h>
+
+#include <klibloader.h>
+#include <kpopupmenu.h>
+#include <kiconloader.h>
+#include <kfiledialog.h>
+#include <klocale.h>
+#include <kapplication.h>
+#include <ktexteditor/markinterface.h>
+
+#include "main_global.h"
+#include "gui_debug_manager.h"
+#include "editor_manager.h"
+#include "global_config.h"
+#include "toplevel.h"
+
+//-----------------------------------------------------------------------------
+const TextEditor::MarkTypeData TextEditor::MARK_TYPE_DATA[Breakpoint::Nb_MarkTypes] = {
+ { KTextEditor::MarkInterface::Execution, "piklab_program_counter" },
+ { KTextEditor::MarkInterface::markType08, "piklab_program_counter_disabled" },
+ { KTextEditor::MarkInterface::BreakpointActive, "piklab_breakpoint_active" },
+ { KTextEditor::MarkInterface::BreakpointDisabled, "piklab_breakpoint_disabled" },
+ { KTextEditor::MarkInterface::BreakpointReached, "piklab_breakpoint_reached" },
+ { KTextEditor::MarkInterface::Error, "piklab_breakpoint_invalid" }
+};
+
+QPixmap TextEditor::pixmap(Breakpoint::MarkType type)
+{
+ return SmallIcon(MARK_TYPE_DATA[type].pixmap);
+}
+
+TextEditor::TextEditor(bool withDebugger, QWidget *parent, const char *name)
+ : Editor(parent, name), _view(0)
+{
+ KLibFactory *factory = KLibLoader::self()->factory("libkatepart");
+ if ( factory==0 ) qFatal("Could not find katepart");
+ _document = static_cast<Kate::Document *>(factory->create(this, "kate", "KTextEditor::Document"));
+ _oldModified = _document->isModified();
+ _oldReadOnly = !_document->isReadWrite();
+
+ QVBoxLayout *top = new QVBoxLayout(this, 0, 10);
+ _split = new QSplitter(this);
+ _split->setFrameStyle(QFrame::TabWidgetPanel | QFrame::Sunken);
+ top->addWidget(_split);
+
+ connect(_document, SIGNAL(hlChanged()), SLOT(highlightChanged()));
+ setAcceptDrops(true);
+ addView();
+
+ for (uint i=0; i<Breakpoint::Nb_MarkTypes; i++)
+ _document->setPixmap(KTextEditor::MarkInterface::MarkTypes(MARK_TYPE_DATA[i].type), pixmap(Breakpoint::MarkType(i)));
+
+ if (withDebugger) QTimer::singleShot(0, this, SLOT(addToDebugManager()));
+}
+
+bool TextEditor::open(const PURL::Url &url)
+{
+ setReadOnly(url.fileType().data().properties & PURL::ReadOnly);
+ if ( !_document->openURL(url.kurl()) ) return false;
+ _view->setEol(url.isDosFile() ? Dos : Unix);
+ highlightChanged();
+ return true;
+}
+
+void TextEditor::addToDebugManager()
+{
+ static_cast<Debugger::GuiManager *>(Debugger::manager)->addTextEditor(*this);
+}
+
+bool TextEditor::eventFilter(QObject *, QEvent *e)
+{
+ if ( e->type()==QEvent::KeyPress ) {
+ if ( static_cast<QKeyEvent *>(e)->key()==Key_Escape ) return true;
+ }
+ return false;
+}
+
+void TextEditor::addView()
+{
+ KTextEditor::View *v = _document->createView(_split);
+ if ( _view==0 ) _view = static_cast<Kate::View *>(v);
+ Q_ASSERT(v);
+ connect(v, SIGNAL(gotFocus(Kate::View *)), SLOT(gotFocus(Kate::View *)));
+ connect(v, SIGNAL(cursorPositionChanged()), SLOT(statusChanged()));
+ connect(v, SIGNAL(dropEventPass(QDropEvent *)), SIGNAL(dropEventPass(QDropEvent *)));
+ connect(v, SIGNAL(newStatus()), SLOT(statusChanged()));
+ v->show();
+ v->setFocus();
+ v->child(0, "KateViewInternal")->installEventFilter(this);
+ KTextEditor::PopupMenuInterface *pmi = KTextEditor::popupMenuInterface(v);
+ pmi->installPopup(&Main::popup("ktexteditor_popup"));
+
+ // dispatch available space between views
+ QValueList<int> list = _split->sizes();
+ QValueList<int>::Iterator it;
+ int sum = 0;
+ for (it = list.begin(); it!= list.end(); ++it) sum += *it;
+ sum /= list.size();
+ for (it = list.begin(); it!=list.end(); ++it) *it = sum;
+ _split->setSizes(list);
+
+ emit guiChanged();
+}
+
+void TextEditor::gotFocus(Kate::View *v)
+{
+ _view = v;
+ setFocusProxy(v);
+ statusChanged();
+ emit guiChanged();
+}
+
+void TextEditor::addGui()
+{
+ Main::toplevel().guiFactory()->addClient(_view);
+}
+
+void TextEditor::removeGui()
+{
+ Main::toplevel().guiFactory()->removeClient(_view);
+}
+
+void TextEditor::removeCurrentView()
+{
+ delete _view;
+ _view = static_cast<Kate::View *>(_document->views().last());
+ _document->views().last()->setFocus();
+ emit guiChanged();
+}
+
+bool TextEditor::isReadOnly() const
+{
+ return !_document->isReadWrite();
+}
+
+void TextEditor::setReadOnlyInternal(bool ro)
+{
+ _oldReadOnly = ro;
+ _document->setReadWrite(!ro);
+}
+
+bool TextEditor::isModified() const
+{
+ return _document->isModified();
+}
+
+void TextEditor::setModifiedInternal(bool m)
+{
+ _oldModified = m;
+ _document->setModified(m);
+}
+
+void TextEditor::statusChanged()
+{
+ uint line, col;
+ _view->cursorPosition(&line, &col) ;
+ QString text = i18n("Line: %1 Col: %2").arg(line+1).arg(col+1);
+ if( isReadOnly() ) text += " " + i18n("R/O");
+ emit statusTextChanged(" " + text + " ");
+ if ( isReadOnly()!=_oldReadOnly || isModified()!=_oldModified ) emit guiChanged();
+ if ( isModified()!=_oldModified ) emit modified();
+ _oldModified = isModified();
+ _oldReadOnly = isReadOnly();
+ Breakpoint::Data data(url(), line);
+ Breakpoint::updateActions(&data);
+}
+
+uint TextEditor::highlightMode(const QString &name) const
+{
+ uint mode = 0;
+ for (; mode<_document->hlModeCount(); mode++)
+ if ( _document->hlModeName(mode)==name ) break;
+ return mode;
+}
+
+void TextEditor::highlightChanged()
+{
+ if ( fileType()==PURL::Nb_FileTypes ) return;
+ // managed by hand because of collisions with file extensions
+ // used by other languages/softwares like other ASM and also PHP...
+ const char *name = fileType().data().highlightModeName;
+ if ( name==0 ) return;
+ uint mode = highlightMode(name);
+ if ( mode>=_document->hlModeCount() || _document->hlMode()==mode ) return;
+ _document->setHlMode(mode);
+}
+
+uint TextEditor::cursorLine() const
+{
+ uint line;
+ _view->cursorPosition(&line, 0);
+ return line;
+}
+
+void TextEditor::setMark(uint line, Breakpoint::MarkType type)
+{
+ _view->setIconBorder(true);
+ _document->setMark(line, MARK_TYPE_DATA[type].type);
+}
+
+void TextEditor::clearMarks(uint type)
+{
+ QPtrList<KTextEditor::Mark> marks = _document->marks();
+ QPtrListIterator<KTextEditor::Mark> it(marks);
+ for (; it.current(); ++it)
+ if ( it.current()->type==type ) _document->removeMark(it.current()->line, it.current()->type);
+}
+
+void TextEditor::clearBreakpointMarks()
+{
+ for (uint i=0; i<Breakpoint::Nb_MarkTypes; i++) clearMarks(MARK_TYPE_DATA[i].type);
+}
+
+QValueList<uint> TextEditor::bookmarkLines() const
+{
+ QValueList<uint> lines;
+ QPtrList<KTextEditor::Mark> marks = _document->marks();
+ QPtrListIterator<KTextEditor::Mark> it(marks);
+ for (; it.current(); ++it)
+ if ( it.current()->type==KTextEditor::MarkInterface::Bookmark ) lines.append(it.current()->line);
+ return lines;
+}
+
+void TextEditor::setBookmarkLines(const QValueList<uint> &lines)
+{
+ clearMarks(KTextEditor::MarkInterface::Bookmark);
+ QValueList<uint>::const_iterator it;
+ for (it=lines.begin(); it!=lines.end(); ++it)
+ _document->setMark(*it, KTextEditor::MarkInterface::Bookmark);
+}
+
+
+#if 0
+void TextEditor::slotChangedText()
+{
+ //This slot runs the instrucion set help bar,
+ // finds the current command word and compares it to the set of instrucions
+ //Found in the descript Qstringlist.
+
+
+ QString currentword;
+ QString testval;
+
+ Kate::View *v = currentView();
+ currentword = v->currentTextLine();
+ //prepare the string for compareing
+ currentword = currentword.simplifyWhiteSpace();
+ currentword = currentword.upper();
+
+ for ( QStringList::Iterator it = descript.begin(); it != descript.end(); ++it )
+ {
+ testval = *it;
+ if(testval.startsWith(currentword.left(5)))
+ {
+ //if (testval.left(5) == currentword.left(5) ) {
+ lab_curword->setText(*it);
+ }
+ // else {
+ // lab_curword->setText("Pic Instruction Help");
+ // }
+ }
+
+
+}
+#endif
+#if 0
+void TextEditor::populateList()
+{
+ //Populate the qstringlist with the pic instruction set, and the text to go along with them
+
+ descript += "CLRF : Clear F OPERANDS: f";
+ descript += "ADDWF : Add W to F OPERANDS: f,d";
+ descript += "ANDWF : AND W with F OPERANDS: f,d";
+ descript += "CLRW : Clear W OPERANDS: NONE";
+ descript += "COMF : Complement F OPERANDS: f,d";
+ descript += "DECF : Decrement F OPERANDS: f,d";
+ descript += "DECSSZ: Decrement F, Skip 0 OPERANDS: f,d";
+ descript += "INCF : Increment F OPERANDS: f,d";
+ descript += "INCFSZ: Increment F, Skip 0 OPERANDS: f,d";
+ descript += "IORWF : Inclusive OR W with F OPERANDS: f,d";
+ descript += "MOVF : Move F, OPERANDS: f,d";
+ descript += "MOVWF : Move W to F OPERANDS: f,d";
+ descript += "NOP : No Operation OPERANDS: NONE";
+ descript += "RLF : Rotate Left F through Carry OPERANDS: f,d";
+ descript += "RRF : Rotate Right F through Carry OPERANDS: f,d";
+ descript += "SUBWF : Subtract W from F OPERANDS: f,d";
+ descript += "SWAPF : Swap Nibbles in F OPERANDS: f,d";
+ descript += "XORWF : Exclusive OR W with F OPERANDS: f,s";
+ descript += "BCF : Bit Clear F OPERANDS: f,b";
+ descript += "BSF : Bit Set F OPERANDS: f,b";
+ descript += "BTFSC : Bit Test F, Skip if Clear OPERANDS: f,b";
+ descript += "BTFSS : Bit Test F, Skip if Set OPERANDS: f,b";
+ descript += "ADDLW : Add Literal and W OPERANDS: k";
+ descript += "ANDLW : And Literal and W OPERANDS: k";
+ descript += "CLRWDT: Clear Watchdog Timer OPERANDS: NONE";
+ descript += "CALL : Call Subroutine OPERANDS: k";
+ descript += "GOTO : Goto address OPERANDS: k";
+ descript += "IORLW : Inclusive OR literal with W OPERANDS: k";
+ descript += "MOVLW : Move Literal with W OPERANDS: k";
+ descript += "RETFIE: Return From Interrupt OPERANDS: NONE";
+ descript += "RETLW : Return with Literal in W OPERANDS: k";
+ descript += "RETURN: Return from subroutine OPERANDS: NONE";
+ descript += "SLEEP : Go into Standby Mode OPERANDS: NONE";
+ descript += "SUBLW : Subtract W from Literal OPERANDS: k";
+ descript += "XORLW : Exclusive OR Literal with W OPERANDS: k";
+
+}
+#endif
+
+//-----------------------------------------------------------------------------
+SimpleTextEditor::SimpleTextEditor(bool withDebugger, PURL::FileType type, QWidget *parent, const char *name)
+ : TextEditor(withDebugger, parent, name), _type(type), _file(_sview)
+{}
+
+SimpleTextEditor::SimpleTextEditor(bool withDebugger, QWidget *parent, const char *name)
+ : TextEditor(withDebugger, parent, name), _type(PURL::Nb_FileTypes), _file(_sview)
+{}
+
+bool SimpleTextEditor::open(const PURL::Url &url)
+{
+ _type = url.fileType();
+ return TextEditor::open(url);
+}
+
+bool SimpleTextEditor::setText(const QString &text)
+{
+ _file.openForWrite();
+ _file.appendText(text);
+ _file.close();
+ if ( !_document->openURL(_file.url().kurl()) ) return false;
+ highlightChanged();
+ return true;
+}
diff --git a/src/libgui/text_editor.h b/src/libgui/text_editor.h
new file mode 100644
index 0000000..9c5a994
--- /dev/null
+++ b/src/libgui/text_editor.h
@@ -0,0 +1,103 @@
+/***************************************************************************
+ * Copyright (C) 2005 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef TEXT_EDITOR_H
+#define TEXT_EDITOR_H
+
+#include <qsplitter.h>
+#include <qstringlist.h>
+class QSplitter;
+
+#include <kate/view.h>
+#include <kate/document.h>
+
+#include "common/gui/pfile_ext.h"
+#include "editor.h"
+#include "progs/manager/breakpoint.h"
+
+//-----------------------------------------------------------------------------
+class TextEditor : public Editor
+{
+Q_OBJECT
+public:
+ TextEditor(bool withDebugger, QWidget *parent, const char *name = 0);
+ virtual PURL::FileType fileType() const { return url().fileType(); }
+ virtual PURL::Url url() const { return _document->url(); }
+ virtual bool isModified() const;
+ virtual bool isReadOnly() const;
+ virtual void addGui();
+ virtual void removeGui();
+ virtual void setFocus() { _view->setFocus(); }
+ static QPixmap pixmap(Breakpoint::MarkType type);
+ void setMark(uint line, Breakpoint::MarkType type);
+ void clearBreakpointMarks();
+ void setCursor(uint line, uint column) { _view->setCursorPosition(line, column); }
+ uint cursorLine() const;
+ virtual bool open(const PURL::Url &url);
+ virtual bool save(const PURL::Url &url) { return _document->saveAs(url.kurl()); }
+ virtual bool eventFilter(QObject *o, QEvent *e);
+ virtual QValueList<uint> bookmarkLines() const;
+ virtual void setBookmarkLines(const QValueList<uint> &lines);
+
+public slots:
+ void addView();
+ void removeCurrentView();
+ void gotFocus(Kate::View *);
+ void highlightChanged();
+ virtual void statusChanged();
+ void selectAll() { _document->selectAll(); }
+ void deselect() { _document->clearSelection(); }
+ void copy() { _view->copy(); }
+
+protected:
+ enum EolType { Dos = 1, Unix = 0, Mac = 2 };
+ Kate::Document *_document;
+ Kate::View *_view;
+
+private slots:
+ void addToDebugManager();
+
+private:
+ QSplitter *_split;
+ bool _oldModified, _oldReadOnly;
+ struct MarkTypeData {
+ uint type;
+ const char *pixmap;
+ };
+ static const MarkTypeData MARK_TYPE_DATA[Breakpoint::Nb_MarkTypes];
+
+private:
+ virtual void setModifiedInternal(bool modified);
+ virtual void setReadOnlyInternal(bool readOnly);
+ uint highlightMode(const QString &name) const;
+ void clearMarks(uint type);
+};
+
+//-----------------------------------------------------------------------------
+class SimpleTextEditor : public TextEditor
+{
+Q_OBJECT
+public:
+ SimpleTextEditor(bool withDebugger, PURL::FileType type, QWidget *parent, const char *name = 0);
+ SimpleTextEditor(bool withDebugger, QWidget *parent, const char *name = 0);
+ void setFileType(PURL::FileType type) { _type = type; }
+ virtual PURL::FileType fileType() const { return _type; }
+ bool setText(const QString &text);
+ virtual bool open(const PURL::Url &url);
+
+protected:
+ virtual bool load() { return false; }
+
+private:
+ Log::StringView _sview;
+ PURL::FileType _type;
+ PURL::TempFile _file;
+};
+
+#endif
diff --git a/src/libgui/toplevel.cpp b/src/libgui/toplevel.cpp
new file mode 100644
index 0000000..c757ace
--- /dev/null
+++ b/src/libgui/toplevel.cpp
@@ -0,0 +1,993 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "toplevel.h"
+
+#include <qpixmap.h>
+#include <qiconset.h>
+#include <qlayout.h>
+#include <qsplitter.h>
+#include <qstringlist.h>
+#include <qtimer.h>
+#include <qprogressbar.h>
+#include <qeventloop.h>
+#include <qapplication.h>
+#include <qtooltip.h>
+
+#include <kstatusbar.h>
+#include <klocale.h>
+#include <kedittoolbar.h>
+#include <kapplication.h>
+#include <kconfig.h>
+#include <kaction.h>
+#include <kcmdlineargs.h>
+#include <kio/observer.h>
+#include <kiconloader.h>
+#include <kpopupmenu.h>
+#include <khelpmenu.h>
+#include <kmenubar.h>
+
+#include "gui_debug_manager.h"
+#include "hex_editor.h"
+#include "project_manager.h"
+#include "project.h"
+#include "global_config.h"
+#include "editor.h"
+#include "device_gui.h"
+#include "text_editor.h"
+#include "new_dialogs.h"
+#include "common/global/process.h"
+#include "common/gui/misc_gui.h"
+#include "common/gui/purl_gui.h"
+#include "devices/list/device_list.h"
+#include "progs/base/prog_config.h"
+#include "progs/list/prog_list.h"
+#include "progs/gui/prog_group_ui.h"
+#include "editor_manager.h"
+#include "tools/list/compile_manager.h"
+#include "object_view.h"
+#include "config_gen.h"
+#include "tools/list/compile_config.h"
+#include "watch_view.h"
+#include "coff/base/text_coff.h"
+#include "tools/list/tool_list.h"
+#include "breakpoint_view.h"
+#include "main_global.h"
+#include "gui_prog_manager.h"
+#include "devices/gui/register_view.h"
+#include "likeback.h"
+#include "console.h"
+#include "devices/base/device_group.h"
+#include "tools/gui/toolchain_config_center.h"
+#include "global_config.h"
+
+//----------------------------------------------------------------------------
+KDockWidget *MainWindow::createDock(const QString &name, const QPixmap &icon,
+ const QString &title, const DockPosition &position)
+{
+ KDockWidget *dock = createDockWidget(name, icon, 0, title);
+ dock->setDockSite(KDockWidget::DockCenter);
+ DockData ddata;
+ ddata.title = title;
+ ddata.position = position;
+ ddata.dock = dock;
+ ddata.action = new ViewMenuAction(dock);
+ connect(ddata.action, SIGNAL(activated(QWidget *)), SLOT(toggleToolView(QWidget *)));
+ _docks += ddata;
+ initDockPosition(ddata);
+ return dock;
+}
+
+MainWindow::MainWindow()
+ : _configGenerator(0), _pikloopsProcess(0), _kfindProcess(0), _forceProgramAfterBuild(false)
+{
+ Q_ASSERT( Main::_toplevel==0 );
+ Main::_toplevel = this;
+
+// status bar
+ _actionStatus = new QLabel(statusBar());
+ statusBar()->addWidget(_actionStatus);
+ _actionProgress = new QProgressBar(statusBar());
+ statusBar()->addWidget(_actionProgress);
+ _debugStatus = new QLabel(statusBar());
+ statusBar()->addWidget(_debugStatus, 0, true);
+ _editorStatus = new QLabel(statusBar());
+ statusBar()->addWidget(_editorStatus, 0, true);
+ _programmerStatus = new ProgrammerStatusWidget(statusBar());
+ connect(_programmerStatus, SIGNAL(configure()), SLOT(configureProgrammer()));
+ connect(_programmerStatus, SIGNAL(selected(const Programmer::Group &)), SLOT(selectProgrammer(const Programmer::Group &)));
+ statusBar()->addWidget(_programmerStatus->widget(), 0, true);
+ _toolStatus = new ToolStatusWidget(statusBar());
+ connect(_toolStatus, SIGNAL(configureToolchain()), SLOT(configureToolchains()));
+ connect(_toolStatus, SIGNAL(configure()), SLOT(configureProject()));
+ connect(_toolStatus, SIGNAL(selected(const Tool::Group &)), SLOT(selectTool(const Tool::Group &)));
+ statusBar()->addWidget(_toolStatus->widget(), 0, true);
+
+// interface
+ _mainDock = createDockWidget("main_dock_widget", QPixmap());
+ _mainDock->setDockSite(KDockWidget::DockCorner);
+ _mainDock->setEnableDocking(KDockWidget::DockNone);
+ setView(_mainDock);
+ setMainDockWidget(_mainDock);
+
+ KIconLoader loader;
+ KDockWidget *dock = createDock("project_manager_dock_widget", PURL::icon(PURL::Project),
+ i18n("Project Manager"), DockPosition(KDockWidget::DockLeft, 20));
+ Main::_projectManager = new ProjectManager::View(dock);
+ connect(Main::_projectManager, SIGNAL(guiChanged()), SLOT(updateGUI()));
+ dock->setWidget(Main::_projectManager);
+
+ dock = createDock("watch_view_dock_widget", loader.loadIcon("viewmag", KIcon::Small),
+ i18n("Watch View"), DockPosition("project_manager_dock_widget"));
+ Main::_watchView = new Register::WatchView(dock);
+ dock->setWidget(Main::_watchView);
+
+ Main::_editorManager = new EditorManager(_mainDock);
+ _mainDock->setWidget(Main::_editorManager);
+ connect(Main::_editorManager, SIGNAL(guiChanged()), SLOT(updateGUI()));
+ connect(Main::_editorManager, SIGNAL(modified(const PURL::Url &)), Main::_projectManager, SLOT(modified(const PURL::Url &)));
+ connect(Main::_editorManager, SIGNAL(statusChanged(const QString &)), _editorStatus, SLOT(setText(const QString &)));
+
+ dock = createDock("compile_log_dock_widget", loader.loadIcon("piklab_compile", KIcon::Small),
+ i18n("Compile Log"), DockPosition(KDockWidget::DockBottom, 80));
+ Main::_compileLog = new Compile::LogWidget(dock);
+ Main::_compileLog->setFocusPolicy(NoFocus);
+ dock->setWidget(Main::_compileLog);
+
+ dock = createDock("program_log_dock_widget", loader.loadIcon("piklab_burnchip", KIcon::Small),
+ i18n("Program Log"), DockPosition("compile_log_dock_widget"));
+ _programLog = new Log::Widget(dock, "program_log");
+ _programLog->setFocusPolicy(NoFocus);
+ dock->setWidget(_programLog);
+
+ dock = createDock("breakpoints_dock_widget", loader.loadIcon("piklab_breakpoint_active", KIcon::Small),
+ i18n("Breakpoints"), DockPosition("compile_log_dock_widget"));
+ Main::_breakpointsView = new Breakpoint::View(dock);
+ Main::_breakpointsView->setFocusPolicy(NoFocus);
+ dock->setWidget(Main::_breakpointsView);
+
+ dock = createDock("console_dock_widget", loader.loadIcon("konsole", KIcon::Small),
+ i18n("Konsole"), DockPosition("compile_log_dock_widget"));
+ Main::_consoleView = new ConsoleView(dock);
+ dock->setWidget(Main::_consoleView);
+
+// managers
+ Programmer::manager = new Programmer::GuiManager(this);
+ Programmer::manager->setView(_programLog);
+ connect(Programmer::manager, SIGNAL(actionMessage(const QString &)), _actionStatus, SLOT(setText(const QString &)));
+ connect(Programmer::manager, SIGNAL(showProgress(bool)), SLOT(showProgress(bool)));
+ connect(Programmer::manager, SIGNAL(setTotalProgress(uint)), SLOT(setTotalProgress(uint)));
+ connect(Programmer::manager, SIGNAL(setProgress(uint)), SLOT(setProgress(uint)));
+
+ Debugger::manager = new Debugger::GuiManager;
+ connect(Debugger::manager, SIGNAL(targetStateChanged()), SLOT(updateGUI()));
+ connect(Debugger::manager, SIGNAL(statusChanged(const QString &)), _debugStatus, SLOT(setText(const QString &)));
+ connect(Debugger::manager, SIGNAL(actionMessage(const QString &)), _actionStatus, SLOT(setText(const QString &)));
+
+ Main::_compileManager = new Compile::Manager(this);
+ Main::_compileManager->setView(Main::_compileLog);
+ connect(Main::_compileManager, SIGNAL(success()), SLOT(compileSuccess()));
+ connect(Main::_compileManager, SIGNAL(failure()), SLOT(compileFailure()));
+ connect(Main::_compileManager, SIGNAL(updateFile(const Compile::FileData &)),
+ SLOT(updateFile(const Compile::FileData &)));
+
+// actions
+ // file actions
+ KAction *a = KStdAction::openNew(this, SLOT(newSourceFile()), actionCollection());
+ a->setText(i18n("&New Source File..."));
+ (void)new KAction(i18n("New hex File..."), "filenew", 0, this, SLOT(newHexFile()),
+ actionCollection(), "file_new_hex");
+ KStdAction::open(this, SLOT(openFile()), actionCollection());
+ KRecentFilesAction *recent = KStdAction::openRecent(this, SLOT(openRecentFile(const KURL &)), actionCollection());
+ recent->setMaxItems(20);
+ recent->loadEntries(kapp->config(), "recent-files");
+ (void)new KAction(i18n("Save All"), 0, 0, Main::_editorManager, SLOT(saveAllFiles()),
+ actionCollection(), "file_save_all");
+ KStdAction::close(Main::_editorManager, SLOT(closeCurrentEditor()), actionCollection());
+ (void)new KAction(i18n("C&lose All"), 0, 0, Main::_editorManager, SLOT(closeAllEditors()),
+ actionCollection(), "file_close_all");
+ (void)new KAction(i18n("Close All Others"), 0, 0, Main::_editorManager, SLOT(closeAllOtherEditors()),
+ actionCollection(), "file_closeother");
+ KStdAction::quit(this, SLOT(close()), actionCollection());
+
+ // edit actions
+
+ // view actions
+ (void)new KAction(i18n("Back"), "back", Qt::ALT + Qt::Key_Left,
+ Main::_editorManager, SLOT(goBack()), actionCollection(), "history_back");
+ (void)new KAction(i18n("Forward"), "forward", Qt::ALT + Qt::Key_Right,
+ Main::_editorManager, SLOT(goForward()), actionCollection(), "history_forward");
+ (void)new KAction(i18n("Switch to..."), 0, Qt::CTRL + Qt::Key_Slash,
+ Main::_editorManager, SLOT(switchToEditor()), actionCollection(), "file_switchto");
+ (void)new KAction(i18n("Switch Header/Implementation"), 0, Qt::SHIFT + Qt::Key_F12,
+ Main::_editorManager, SLOT(switchHeaderImplementation()), actionCollection(), "view_switch_source");
+ (void)new KAction(QString::null, 0, 0,
+ Debugger::manager, SLOT(toggleBreakpoint()), actionCollection(), "toggle_breakpoint");
+ (void)new KAction(QString::null, 0, 0,
+ Debugger::manager, SLOT(toggleEnableBreakpoint()), actionCollection(), "enable_breakpoint");
+ (void)new KAction(i18n("Show disassembly location"), 0, 0,
+ Debugger::manager, SLOT(showDisassemblyLocation()), actionCollection(), "show_disassembly_location");
+ KActionMenu *toolViewsMenu = new KActionMenu( i18n("Tool Views"), 0, "view_tool_views");
+ connect(toolViewsMenu->popupMenu(), SIGNAL(aboutToShow()), SLOT(updateToolViewsActions()));
+ actionCollection()->insert(toolViewsMenu);
+ a = new KAction(i18n("&Reset Layout"), 0, 0, this, SLOT(resetDockLayout()), actionCollection(), "view_reset_layout");
+ toolViewsMenu->insert(a);
+ toolViewsMenu->popupMenu()->insertSeparator();
+ QValueList<DockData>::iterator it;
+ for(it=_docks.begin(); it!=_docks.end(); ++it) toolViewsMenu->insert((*it).action);
+
+ // project actions
+ (void)new KAction(i18n("New Project..."), "piklab_createproject", 0,
+ this, SLOT(newProject()), actionCollection(), "project_new");
+ (void)new KAction(i18n("Open Project..."), "piklab_openproject", 0,
+ this , SLOT(openProject()), actionCollection(), "project_open");
+ recent = new KRecentFilesAction(i18n("Open Recent Project"), 0,
+ this, SLOT(openRecentProject(const KURL &)), actionCollection(), "project_open_recent");
+ recent->setMaxItems(20);
+ recent->loadEntries(kapp->config(), "recent-projects");
+ (void)new KAction(i18n("Project Options..."), "configure", 0,
+ this, SLOT(configureProject()), actionCollection(), "project_options");
+ (void)new KAction(i18n("Close Project"), "fileclose", 0,
+ this, SLOT(closeProject()), actionCollection(), "project_close");
+ (void)new KAction(i18n("Add Source File..."), "piklab_addfile", 0,
+ Main::_projectManager, SLOT(insertSourceFiles()), actionCollection(), "project_add_source_file");
+ (void)new KAction(i18n("Add Object File..."), "piklab_addfile", 0,
+ Main::_projectManager, SLOT(insertObjectFiles()), actionCollection(), "project_add_object_file");
+ (void)new KAction(i18n("Add Current File"), "piklab_addcurrentfile", 0,
+ Main::_projectManager, SLOT(insertCurrentFile()), actionCollection(), "project_add_current_file");
+
+ // build actions
+ (void)new KAction(i18n("&Build Project"), "piklab_compile", Qt::Key_F8,
+ this, SLOT(buildProject()), actionCollection(), "build_build_project");
+ (void)new KAction(i18n("&Compile File"), 0, Qt::SHIFT + Qt::Key_F8,
+ this, SLOT(compileFile()), actionCollection(), "build_compile_file");
+ (void)new KAction(i18n("Clean"), "trashcan_empty", 0,
+ this, SLOT(cleanBuild()), actionCollection(), "build_clean");
+ (void)new KAction(i18n("Stop"), "stop", 0,
+ this, SLOT(stopBuild()), actionCollection(), "build_stop");
+
+ // programmer actions
+ (void)new KAction(i18n("&Connect"), "connect_creating", 0,
+ Programmer::manager, SLOT(connectDevice()), actionCollection(), "prog_connect");
+ (void)new KToggleAction(i18n("Device Power"), "piklab_power", 0,
+ Programmer::manager, SLOT(toggleDevicePower()), actionCollection(), "prog_power");
+ (void)new KAction(i18n("&Disconnect"), "connect_no", 0,
+ Programmer::manager, SLOT(disconnectDevice()), actionCollection(), "prog_disconnect");
+ (void)new KAction(i18n("&Program"), "piklab_burnchip", Qt::SHIFT + Qt::Key_F5,
+ this , SLOT(program()), actionCollection(), "prog_program");
+ (void)new KAction(i18n("&Verify"), "piklab_verifychip", Qt::SHIFT + Qt::Key_F6,
+ this , SLOT(verify()), actionCollection(), "prog_verify");
+ (void)new KAction(i18n("&Read"), "piklab_readchip", Qt::SHIFT + Qt::Key_F7,
+ this , SLOT(read()), actionCollection(), "prog_read");
+ (void)new KAction(i18n("&Erase"), "piklab_erasechip", 0,
+ this, SLOT(erase()), actionCollection(), "prog_erase");
+ (void)new KAction(i18n("&Blank Check"), "piklab_blankcheck", 0,
+ this, SLOT(blankCheck()), actionCollection(), "prog_blank_check");
+ (void)new KAction(i18n("&Run"), "launch", Qt::SHIFT + Qt::Key_F9,
+ Programmer::manager, SLOT(run()), actionCollection(), "prog_run");
+ (void)new KAction(i18n("&Stop"), "piklab_stop", 0,
+ Programmer::manager, SLOT(halt()), actionCollection(), "prog_stop");
+ (void)new KAction(i18n("R&estart"), "piklab_restart", 0,
+ Programmer::manager, SLOT(restart()), actionCollection(), "prog_restart");
+ (void)new KAction(i18n("&Advanced..."), 0, 0,
+ Programmer::manager , SLOT(showAdvancedDialog()), actionCollection(), "prog_advanced");
+ (void)new KAction(i18n("Settings..."), "configure", 0,
+ this , SLOT(showProgrammerSettings()), actionCollection(), "prog_settings");
+
+ // debugger actions
+ (void)new KAction(i18n("&Start"), "launch", Qt::SHIFT + Qt::Key_F9,
+ Programmer::manager, SLOT(restart()), actionCollection(), "debug_start");
+ (void)new KAction(i18n("&Run"), "piklab_run", Qt::SHIFT + Qt::Key_F9,
+ Programmer::manager, SLOT(run()), actionCollection(), "debug_run");
+ (void)new KAction(i18n("&Step"), "piklab_debug_step", 0,
+ Programmer::manager, SLOT(step()), actionCollection(), "debug_next");
+ //(void)new KAction(i18n("Step &In"), "piklab_debug_stepin",
+ // 0, this, SLOT(debugStepIn()), actionCollection(), "debug_step_in");
+ //(void)new KAction(i18n("Step &Out"), "piklab_debug_stepout",
+ // 0, this, SLOT(debugStepOut()), actionCollection(), "debug_step_out");
+ (void)new KAction(i18n("&Break<Translators: it is the verb>", "&Halt"), "piklab_debughalt", 0,
+ Programmer::manager, SLOT(halt()), actionCollection(), "debug_halt");
+ (void)new KAction(i18n("&Disconnect/Stop"), "piklab_stop", 0,
+ Programmer::manager, SLOT(disconnectDevice()), actionCollection(), "debug_stop");
+ (void)new KAction(i18n("R&eset"), "piklab_restart", 0,
+ Programmer::manager, SLOT(restart()), actionCollection(), "debug_reset");
+ (void)new KAction(i18n("Show Program Counter"), "piklab_program_counter", 0,
+ Debugger::manager, SLOT(showPC()), actionCollection(), "debug_show_pc");
+ (void)new KAction(i18n("Clear All Breakpoints"), "remove", 0,
+ Debugger::manager, SLOT(clearBreakpoints()), actionCollection(), "debug_clear_breakpoints");
+ (void)new KAction(i18n("Settings..."), "configure", 0,
+ this , SLOT(showDebuggerSettings()), actionCollection(), "debug_settings");
+
+ // tools
+ (void)new KAction(i18n("&Pikloops..."), 0, 0,
+ this , SLOT(runPikloops()), actionCollection(), "tools_pikloops");
+ (void)new KAction(i18n("&Find Files..."), "find", 0,
+ this , SLOT(runKfind()), actionCollection(), "tools_kfind");
+ (void)new KAction(i18n("&Device Information..."), "info", 0,
+ this , SLOT(showDeviceInfo()), actionCollection(), "tools_device_information");
+ (void)new KAction(i18n("&Config Generator..."), 0, 0,
+ this , SLOT(configGenerator()), actionCollection(), "tools_config_generator");
+ (void)new KAction(i18n("&Template Generator..."), 0, 0,
+ this , SLOT(templateGenerator()), actionCollection(), "tools_template_generator");
+
+ // settings actions
+ (void)new KAction(i18n("Configure Toolchains..."), 0, 0,
+ this, SLOT(configureToolchains()), actionCollection(), "options_configure_toolchains");
+ (void)KStdAction::preferences(this, SLOT(configure()), actionCollection());
+
+ // help
+ (void)new KAction(i18n("Report Bug..."), "likeback_bug", 0,
+ LikeBack::instance(), SLOT(iFoundABug()), actionCollection(), "help_report_bug_piklab");
+
+ setupGUI();
+ readDockConfig();
+
+ // LikeBack buttons
+ menuBar()->insertItem(new QLabel(menuBar())); // #### first widget is put left-most...
+ MenuBarButton *button = new MenuBarButton("likeback_like", menuBar());
+ QToolTip::add(button, i18n("I like..."));
+ connect(button, SIGNAL(clicked()), LikeBack::instance(), SLOT(iLike()));
+ menuBar()->insertItem(button);
+ button = new MenuBarButton("likeback_dislike", menuBar());
+ QToolTip::add(button, i18n("I do not like..."));
+ connect(button, SIGNAL(clicked()), LikeBack::instance(), SLOT(iDoNotLike()));
+ menuBar()->insertItem(button);
+ button = new MenuBarButton("likeback_bug", menuBar());
+ QToolTip::add(button, i18n("I found a bug..."));
+ connect(button, SIGNAL(clicked()), LikeBack::instance(), SLOT(iFoundABug()));
+ menuBar()->insertItem(button);
+ button = new MenuBarButton("configure", menuBar());
+ QToolTip::add(button, i18n("Configure email..."));
+ connect(button, SIGNAL(clicked()), LikeBack::instance(), SLOT(askEMail()));
+ menuBar()->insertItem(button);
+ button = new MenuBarButton("help", menuBar());
+ connect(button, SIGNAL(clicked()), LikeBack::instance(), SLOT(showWhatsThisMessage()));
+ menuBar()->insertItem(button);
+
+ QTimer::singleShot(0, this, SLOT(initialLoading()));
+}
+
+MainWindow::~MainWindow()
+{}
+
+void MainWindow::readDockConfig()
+{
+ KDockMainWindow::readDockConfig(kapp->config(), "dock_config");
+
+ // if there is a new dock: it is not displayed by default...
+ QMap<QString, QString> entries = kapp->config()->entryMap("dock_config");
+ QValueList<DockData>::iterator it;
+ for(it=_docks.begin(); it!=_docks.end(); ++it) {
+ QMap<QString, QString>::const_iterator eit;
+ for(eit=entries.begin(); eit!=entries.end(); ++eit)
+ if ( eit.key().startsWith((*it).dock->name()) ) break;
+ if ( eit==entries.end() ) initDockPosition(*it);
+ }
+
+ // readDockConfig also restore the names/tooltips: what if a new version of the application changes these names...
+ for(it=_docks.begin(); it!=_docks.end(); ++it) (*it).dock->setTabPageLabel((*it).title);
+ QApplication::postEvent(this, new QEvent(QEvent::CaptionChange));
+}
+
+void MainWindow::initialLoading()
+{
+ ::BusyCursor bc;
+ KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
+ if ( args->count()!=0 ) { // opened urls provided on the command line
+ for (int i = 0; i<args->count(); i++) {
+ PURL::Url url(args->url(i));
+ if ( url.fileType()==PURL::Project ) {
+ if ( Main::_projectManager->project()==0 ) Main::_projectManager->openProject(url);
+ } else Main::_editorManager->openEditor(url);
+ }
+ } else { // otherwise reopen last project/files
+ Main::_projectManager->openProject(GlobalConfig::openedProject());
+ PURL::UrlList files = GlobalConfig::openedFiles();
+ PURL::UrlList::const_iterator it = files.begin();
+ for (; it!=files.end(); ++it) Main::_editorManager->openEditor(*it);
+ }
+ updateGUI();
+}
+
+void MainWindow::openRecentFile(const KURL &kurl)
+{
+ Main::_editorManager->openFile(PURL::Url(kurl));
+}
+
+void MainWindow::configureToolbar()
+{
+ saveMainWindowSettings(KGlobal::config(), "MainWindow");
+ KEditToolbar dlg(actionCollection());
+ connect(&dlg, SIGNAL(newToolbarConfig()), SLOT(applyToolbarSettings()));
+ dlg.exec();
+}
+
+void MainWindow::applyToolbarSettings()
+{
+ createGUI();
+ applyMainWindowSettings(KGlobal::config(), "MainWindow");
+}
+
+void MainWindow::configure(ConfigCenter::Type showType)
+{
+ stopOperations();
+ ConfigCenter dialog(showType, this);
+ dialog.exec();
+ Programmer::manager->clear();
+ updateGUI();
+ Debugger::manager->update(true);
+}
+
+void MainWindow::configureToolchains()
+{
+ stopOperations();
+ ToolchainsConfigCenter dialog(Main::toolGroup(), this);
+ dialog.exec();
+ Programmer::manager->clear();
+ updateGUI();
+ Debugger::manager->update(true);
+}
+
+void MainWindow::selectProgrammer(const Programmer::Group &group)
+{
+ if ( group.name()==Main::programmerGroup().name() ) return;
+ bool debugInitialized = Debugger::manager->coff();
+ stopOperations();
+ GlobalConfig::writeProgrammerGroup(group);
+ Programmer::manager->clear();
+ updateGUI();
+ if (debugInitialized) Debugger::manager->init();
+ else Debugger::manager->update(true);
+}
+
+void MainWindow::selectTool(const Tool::Group &group)
+{
+ if ( group.name()==Compile::Config::toolGroup(Main::project()).name() ) return;
+ bool debugInitialized = Debugger::manager->coff();
+ stopOperations();
+ Compile::Config::setToolGroup(Main::project(), group);
+ updateGUI();
+ if (debugInitialized) Debugger::manager->init();
+ else Debugger::manager->update(true);
+}
+
+void MainWindow::setDevice(const QString &device)
+{
+ if ( device==i18n(Device::AUTO_DATA.label) ) Compile::Config::setDevice(Main::project(), Device::AUTO_DATA.name);
+ else Compile::Config::setDevice(Main::project(), device);
+ updateGUI();
+}
+
+void MainWindow::showDeviceInfo()
+{
+ DeviceChooser::Dialog d(Main::device(), (Main::project() ? DeviceChooser::Choose : DeviceChooser::ChooseWithAuto), this);
+ if ( d.exec() ) {
+ setDevice(d.device());
+ updateGUI();
+ }
+}
+
+void MainWindow::configGenerator()
+{
+ PURL::FileType ftype = (Main::currentEditor() ? Main::currentEditor()->fileType() : PURL::Nb_FileTypes);
+ PURL::SourceFamily family = (ftype!=PURL::Nb_FileTypes ? ftype.data().sourceFamily : PURL::SourceFamily(PURL::SourceFamily::Nb_Types));
+ PURL::ToolType type = (family!=PURL::SourceFamily::Nb_Types ? family.data().toolType : PURL::ToolType(PURL::ToolType::Assembler));
+ ConfigGenerator dialog(this);
+ dialog.set(Main::deviceData(), Main::toolGroup(), type);
+ dialog.exec();
+}
+
+void MainWindow::templateGenerator()
+{
+ PURL::FileType ftype = (Main::currentEditor() ? Main::currentEditor()->fileType() : PURL::Nb_FileTypes);
+ PURL::SourceFamily family = (ftype!=PURL::Nb_FileTypes ? ftype.data().sourceFamily : PURL::SourceFamily(PURL::SourceFamily::Nb_Types));
+ PURL::ToolType type = (family!=PURL::SourceFamily::Nb_Types ? family.data().toolType : PURL::ToolType(PURL::ToolType::Assembler));
+ TemplateGenerator dialog(this);
+ dialog.set(Main::deviceData(), Main::toolGroup(), type);
+ dialog.exec();
+}
+
+bool MainWindow::queryClose()
+{
+ if ( !stopOperations() ) return false;
+ Main::setState(Main::Closing);
+ // save list of opened editors
+ PURL::UrlList toSave;
+ const PURL::UrlList files = Main::_editorManager->files();
+ PURL::UrlList::const_iterator it;
+ for (it=files.begin(); it!=files.end(); ++it)
+ if ( !Main::_projectManager->isExternalFile(*it) ) toSave.append(*it);
+ GlobalConfig::writeOpenedFiles(toSave);
+ // close editors
+ if ( !Main::_editorManager->closeAllEditors() ) {
+ Main::setState(Main::Idle);
+ return false;
+ }
+ // save other settings
+ ::BusyCursor bc;
+ writeDockConfig(kapp->config(), "dock_config");
+ static_cast<KRecentFilesAction *>(Main::action("project_open_recent"))->saveEntries(kapp->config(), "recent-projects");
+ static_cast<KRecentFilesAction *>(Main::action("file_open_recent"))->saveEntries(kapp->config(), "recent-files");
+ GlobalConfig::writeOpenedProject(Main::project() ? Main::project()->url() : PURL::Url());
+ if ( Main::project() ) Main::_projectManager->closeProject();
+ return true;
+}
+
+void MainWindow::newSourceFile()
+{
+ NewFileDialog dialog(Main::project(), this);
+ if ( dialog.exec()!=QDialog::Accepted ) return;
+ if ( !dialog.url().exists() && !dialog.url().create(*Main::_compileLog) ) return;
+ Main::_editorManager->openEditor(dialog.url());
+ if ( dialog.addToProject() ) Main::_projectManager->insertFile(dialog.url());
+}
+
+void MainWindow::newHexFile()
+{
+ if ( Main::device()==Device::AUTO_DATA.name ) {
+ MessageBox::sorry(i18n("You need to specify a device to create a new hex file."), Log::Show);
+ return;
+ }
+ QString s;
+ for (uint i=0; true; i++) {
+ s = i18n("Hex") + (i==0 ? QString::null : QString::number(i));
+ if ( Main::_editorManager->findEditor(s)==0 ) break;
+ }
+ HexEditor *editor = new HexEditor(s, Main::_editorManager);
+ editor->memoryRead();
+ Main::_editorManager->addEditor(editor);
+}
+
+bool MainWindow::openFile()
+{
+ QString filter;
+ filter += PURL::sourceFilter(PURL::SimpleFilter);
+ filter += "\n" + PURL::filter(PURL::Hex);
+ filter += "\n" + PURL::projectFilter(PURL::SimpleFilter);
+ filter += "\n*|" + i18n("All Files");
+ PURL::Url url = PURL::getOpenUrl(":open_file", filter, this ,i18n("Open File"));
+ if ( url.fileType()==PURL::Project || url.fileType()==PURL::PikdevProject ) {
+ stopOperations();
+ if ( !Main::_projectManager->openProject(url) ) return false;
+ updateGUI();
+ return true;
+ }
+ return Main::_editorManager->openFile(url);
+}
+
+void MainWindow::updateGUI()
+{
+ bool idle = ( Main::_state==Main::Idle );
+ switch (Main::_state) {
+ case Main::Closing: return;
+ case Main::Idle:
+ showProgress(false);
+ break;
+ case Main::Compiling:
+ _actionStatus->setText(Main::_compileManager->label());
+ showProgress(true);
+ makeWidgetDockVisible(Main::_compileLog);
+ break;
+ case Main::Programming:
+ makeWidgetDockVisible(_programLog);
+ break;
+ }
+
+ // update editor actions
+ Main::_editorManager->updateTitles();
+ Main::action("file_save_all")->setEnabled(Main::currentEditor());
+ Main::action("file_close")->setEnabled(Main::currentEditor());
+ Main::action("file_close_all")->setEnabled(Main::currentEditor());
+ Main::action("file_closeother")->setEnabled(Main::_editorManager->nbEditors()>1);
+ Main::action("options_configure")->setEnabled(idle);
+ PURL::FileType currentType = (Main::currentEditor() ? Main::currentEditor()->fileType() : PURL::Nb_FileTypes);
+ bool isSource = (currentType==PURL::Nb_FileTypes ? false : currentType.data().group==PURL::Source);
+ bool isHeader = (currentType==PURL::Nb_FileTypes ? false : currentType.data().group==PURL::Header);
+ Main::action("view_switch_source")->setEnabled(isSource || isHeader);
+ Main::action("history_back")->setEnabled(Main::editorManager().history().hasBack());
+ Main::action("history_forward")->setEnabled(Main::editorManager().history().hasForward());
+ Main::action("show_disassembly_location")->setEnabled(Debugger::manager->coff()!=0 && (isSource || isHeader));
+
+ // update project
+ bool inProject = ( Main::currentEditor() && (currentType==PURL::Nb_FileTypes || Main::currentEditor()->url().isEmpty() || Main::_projectManager->contains(Main::currentEditor()->url())) );
+ if ( Main::project()==0 && !inProject ) {
+ if ( Main::currentEditor()==0 ) Main::_projectManager->closeProject();
+ else if ( isSource ) Main::_projectManager->setStandalone(Main::currentEditor()->url(), currentType);
+ else {
+ PURL::FileType type;
+ PURL::Url purl = Main::_projectManager->standaloneGenerator(Main::currentEditor()->url(), type);
+ if ( type!=PURL::Nb_FileTypes ) Main::_projectManager->setStandalone(purl, type);
+ else if ( currentType==PURL::Hex ) Main::_projectManager->setStandalone(purl, PURL::Hex);
+ }
+ }
+ if ( Main::currentEditor() ) Main::_projectManager->select(Main::currentEditor());
+
+ // update project actions
+ Main::action("project_new")->setEnabled(idle);
+ Main::action("project_open")->setEnabled(idle);
+ Main::action("project_close")->setEnabled(Main::project() && idle);
+ Main::action("project_options")->setEnabled(Main::project() && idle);
+ Main::action("project_add_source_file")->setEnabled(Main::project() && idle);
+ Main::action("project_add_object_file")->setEnabled(Main::project() && idle);
+ Main::action("project_add_current_file")->setEnabled(Main::project() && !inProject && idle && isSource);
+
+ // update build actions
+ static_cast<PopupButton *>(_toolStatus->widget())->setText(" " + Main::toolGroup().label() + " ");
+ bool hexProject = ( Main::_projectManager->projectUrl().fileType()==PURL::Hex );
+ bool customTool = Main::toolGroup().isCustom();
+ Main::action("build_build_project")->setEnabled((Main::project() || (inProject && !hexProject) ) && idle);
+ PURL::Url selected = Main::_projectManager->selectedUrl();
+ bool isSelectedSource = ( !selected.isEmpty() && selected.data().group==PURL::Source );
+ Main::action("build_compile_file")->setEnabled(!hexProject && (isSource || isSelectedSource) && idle && !customTool);
+ Main::action("build_clean")->setEnabled((Main::project() || inProject) && idle && !customTool);
+ Main::action("build_stop")->setEnabled(Main::_state==Main::Compiling);
+
+ // update programmer status
+ PortType ptype = Programmer::GroupConfig::portType(Main::programmerGroup());
+ static_cast<PopupButton *>(_programmerStatus->widget())->setText(" " + Main::programmerGroup().statusLabel(ptype) + " ");
+ QFont f = font();
+ bool supported = (Main::deviceData() ? Main::programmerGroup().isSupported(Main::deviceData()->name()) : false);
+ f.setItalic(!supported);
+ _programmerStatus->widget()->setFont(f);
+ bool isProgrammer = ( Main::programmerGroup().properties() & ::Programmer::Programmer );
+ PURL::Url purl = Main::_projectManager->projectUrl();
+ bool hasHex = ( currentType==PURL::Hex || Main::_projectManager->contains(purl.toFileType(PURL::Hex)) );
+ Main::action("prog_connect")->setEnabled(isProgrammer && idle);
+ Main::action("prog_read")->setEnabled(isProgrammer && idle);
+ Main::action("prog_program")->setEnabled(isProgrammer && hasHex && idle);
+ Main::action("prog_verify")->setEnabled(isProgrammer && hasHex && idle);
+ Main::action("prog_erase")->setEnabled(isProgrammer && idle);
+ Main::action("prog_blank_check")->setEnabled(isProgrammer && idle);
+ Programmer::State pstate = (Main::programmer() ? Main::programmer()->state() : Programmer::NotConnected);
+ static_cast<KToggleAction *>(Main::action("prog_power"))->setEnabled(isProgrammer && idle && pstate!=Programmer::NotConnected);
+ Main::action("prog_disconnect")->setEnabled(isProgrammer && idle && pstate!=Programmer::NotConnected);
+ bool isDebugger = ( Main::programmerGroup().properties() & ::Programmer::Debugger );
+ bool resetAvailable = ( Main::programmerGroup().properties() & Programmer::CanReleaseReset );
+ Main::action("prog_run")->setEnabled(idle && resetAvailable && !isDebugger && pstate!=Programmer::Running);
+ Main::action("prog_stop")->setEnabled(idle && !isDebugger && pstate==Programmer::Running);
+ Main::action("prog_restart")->setEnabled(idle && !isDebugger && pstate==Programmer::Running);
+ const Programmer::GroupUI *pgui = static_cast<const Programmer::GroupUI *>(Main::programmerGroup().gui());
+ Main::action("prog_advanced")->setEnabled(idle && pgui->hasAdvancedDialog());
+
+ // update debugger status
+ Debugger::manager->updateDevice();
+ Main::action("debug_start")->setEnabled(idle && isDebugger && pstate!=Programmer::Running && pstate!=Programmer::Halted);
+ Main::action("debug_run")->setEnabled(idle && isDebugger && pstate!=Programmer::Running && !Debugger::manager->isStepping() );
+ Main::action("debug_halt")->setEnabled(idle && isDebugger && (pstate==Programmer::Running || Debugger::manager->isStepping()) );
+ Main::action("debug_stop")->setEnabled(idle && isDebugger && (pstate==Programmer::Running || pstate==Programmer::Halted));
+ Main::action("debug_next")->setEnabled(idle && isDebugger && pstate!=Programmer::Running);
+ Main::action("debug_reset")->setEnabled(idle && isDebugger && (pstate==Programmer::Running || pstate==Programmer::Halted));
+ Main::action("debug_show_pc")->setEnabled(idle && isDebugger && Debugger::manager->coff()!=0 && Debugger::manager->pc().isInitialized() );
+
+ Main::_projectManager->updateGUI();
+
+ // caption
+ QString caption;
+ if ( Main::project() ) caption += Main::project()->name();
+ if ( Main::currentEditor() ) {
+ if ( Main::project() ) caption += " - ";
+ caption += Main::currentEditor()->url().filepath();
+ }
+ setCaption(KApplication::kApplication()->makeStdCaption(caption));
+
+ emit stateChanged();
+}
+
+void MainWindow::updateToolViewsActions()
+{
+ QValueList<DockData>::iterator it;
+ for(it=_docks.begin(); it!=_docks.end(); ++it) (*it).action->setChecked((*it).dock->mayBeHide());
+}
+
+void MainWindow::initDockPosition(const DockData &ddata)
+{
+ const DockPosition &pos = ddata.position;
+ ddata.dock->manualDock(manager()->getDockWidgetFromName(pos.parent), pos.pos, pos.space);
+}
+
+void MainWindow::resetDockLayout()
+{
+ QValueList<DockData>::iterator it;
+ for (it=_docks.begin(); it!=_docks.end(); ++it) initDockPosition(*it);
+}
+
+void MainWindow::toggleToolView(QWidget *widget)
+{
+ static_cast<KDockWidget *>(widget)->changeHideShowState();
+}
+
+void MainWindow::runKfind()
+{
+ if (_kfindProcess) return;
+ _kfindProcess = new ::Process::StringOutput;
+ QString path;
+ PURL::Url url = Main::projectManager().projectUrl();
+ if ( !url.isEmpty() ) path = url.path();
+ _kfindProcess->setup("kfind", path, false);
+ connect(_kfindProcess, SIGNAL(done(int)), SLOT(kfindDone()));
+ if ( !_kfindProcess->start(0) )
+ MessageBox::sorry(i18n("Could not run \"kfind\""), Log::Show);
+}
+
+void MainWindow::kfindDone()
+{
+ delete _kfindProcess;
+ _kfindProcess = 0;
+}
+
+void MainWindow::runPikloops()
+{
+ if (_pikloopsProcess) return;
+ _pikloopsProcess = new ::Process::StringOutput;
+ _pikloopsProcess->setup("pikloops", QStringList(), false);
+ connect(_pikloopsProcess, SIGNAL(done(int)), SLOT(pikloopsDone()));
+ if ( !_pikloopsProcess->start(0) )
+ MessageBox::detailedSorry(i18n("Could not run \"pikloops\""), i18n("The Pikloops utility (%1) is not installed in your system.").arg("http://pikloops.sourceforge.net"), Log::Show);
+}
+
+void MainWindow::pikloopsDone()
+{
+ delete _pikloopsProcess;
+ _pikloopsProcess = 0;
+}
+
+//-----------------------------------------------------------------------------
+void MainWindow::compileFile()
+{
+ Editor *e = Main::currentEditor();
+ if ( e && e->isModified() ) e->save(); // buffer is systematically saved
+ stopOperations();
+ Main::_compileLog->clear();
+ PURL::Url url = (e ? e->url() : Main::_projectManager->selectedUrl());
+ bool generated = (e ? Main::_projectManager->isExternalFile(url) : false);
+ if ( Main::project()==0 || !generated ) Main::_projectManager->removeExternalFiles();
+ url = (!generated ? url : Main::_projectManager->projectUrl());
+ if ( Main::_compileManager->compileFile(Compile::TodoItem(url, generated)) ) Main::setState(Main::Compiling);
+ else compileFailure();
+}
+
+void MainWindow::buildProject()
+{
+ if ( Main::project()==0 ) {
+ compileFile();
+ return;
+ }
+ // save modified buffers
+ PURL::UrlList files = Main::project()->absoluteFiles();
+ PURL::UrlList::const_iterator it;
+ for (it=files.begin(); it!=files.end(); ++it) {
+ // save modified editors
+ Editor *e = Main::_editorManager->findEditor(*it);
+ if ( e && e->isModified() ) e->save();
+ }
+ bool tmp = _forceProgramAfterBuild;
+ stopOperations();
+ _forceProgramAfterBuild = tmp;
+ Main::_compileLog->clear();
+ Main::_projectManager->removeExternalFiles();
+ Compile::LinkType ltype = (Main::programmerGroup().name()=="icd2_debugger" ? Compile::Icd2Linking : Compile::NormalLinking);
+ if ( Main::_compileManager->buildProject(ltype) ) Main::setState(Main::Compiling);
+ else compileFailure();
+}
+
+void MainWindow::compileFailure()
+{
+ _forceProgramAfterBuild = false;
+ Main::setState(Main::Idle);
+}
+
+void MainWindow::compileSuccess()
+{
+ if ( !Main::_compileManager->compileOnly() ) {
+ Main::_projectManager->setModified(false);
+ if ( Main::project()->outputType()==Tool::OutputType::Executable ) {
+ if ( Debugger::manager->init() ) {
+ const QStringList &included = Debugger::manager->coff()->filenames();
+ QStringList::const_iterator it;
+ for (it=included.begin(); it!=included.end(); ++it) {
+ PURL::Directory dir = (Main::project() ? Main::project()->directory() : Main::projectManager().projectUrl().directory());
+ PURL::Url url = PURL::Url::fromPathOrUrl(*it).toAbsolute(dir);
+ if ( !url.exists() ) continue;
+ Main::_projectManager->addExternalFile(url, ProjectManager::Included);
+ }
+ }
+ if ( _forceProgramAfterBuild || readConfigEntry(BaseGlobalConfig::ProgramAfterBuild).toBool() ) program();
+ }
+ }
+ _forceProgramAfterBuild = false;
+ Main::setState(Main::Idle);
+}
+
+void MainWindow::updateFile(const Compile::FileData &fdata)
+{
+ if ( fdata.actions & Compile::InProject ) {
+ if ( fdata.actions & Compile::Generated ) Main::_projectManager->addExternalFile(fdata.url, ProjectManager::Generated);
+ else if ( fdata.actions & Compile::Included ) Main::_projectManager->addExternalFile(fdata.url, ProjectManager::Included);
+ else Q_ASSERT(false);
+ }
+ if ( fdata.actions & Compile::Show ) {
+ Editor *e = Main::_editorManager->openEditor(fdata.url);
+ if (e) e->setReadOnly(true);
+ }
+}
+
+void MainWindow::cleanBuild()
+{
+ stopOperations();
+ Main::_compileLog->clear();
+ if ( Main::project() ) {
+ Compile::LinkType ltype = (Main::programmerGroup().name()=="icd2_debugger" ? Compile::Icd2Linking : Compile::NormalLinking);
+ Main::_compileManager->cleanProject(ltype);
+ } else {
+ PURL::FileType type;
+ PURL::Url url = Main::_projectManager->standaloneGenerator(Main::currentEditor()->url(), type);
+ Main::_compileManager->cleanFile(url);
+ }
+ Main::_projectManager->removeExternalFiles();
+}
+
+void MainWindow::stopBuild()
+{
+ Main::_compileManager->kill();
+}
+
+//-----------------------------------------------------------------------------
+void MainWindow::keyPressEvent(QKeyEvent *e)
+{
+ if ( e->key()==Key_Escape ) stopOperations();
+}
+
+bool MainWindow::stopOperations()
+{
+ if ( Main::_state==Main::Programming ) {
+ _programLog->log(Log::LineType::Warning, i18n("Programming in progress. Cannot be aborted."));
+ return false;
+ }
+ stopBuild();
+ Programmer::manager->stop();
+ Debugger::manager->clear();
+ return true;
+}
+
+void MainWindow::newProject()
+{
+ stopOperations();
+ Main::_projectManager->newProject();
+ updateGUI();
+ Main::_compileLog->clear();
+}
+
+void MainWindow::openProject()
+{
+ stopOperations();
+ Main::_projectManager->openProject();
+ updateGUI();
+ Main::_compileLog->clear();
+}
+
+void MainWindow::openRecentProject(const KURL &url)
+{
+ stopOperations();
+ Main::_projectManager->openProject(PURL::Url(url));
+ updateGUI();
+ Main::_compileLog->clear();
+}
+
+void MainWindow::configureProject()
+{
+ stopOperations();
+ if ( Main::project()==0 ) configure(ConfigCenter::Standalone);
+ else Main::_projectManager->editProject();
+ updateGUI();
+}
+
+void MainWindow::closeProject()
+{
+ stopOperations();
+ Main::_projectManager->closeProject();
+ updateGUI();
+ Main::_compileLog->clear();
+}
+
+//----------------------------------------------------------------------------
+HexEditor *MainWindow::getHexEditor()
+{
+ if ( Main::_projectManager->isModified() || Main::_projectManager->needsRecompile() ) {
+ MessageBox::Result res = MessageBox::Yes;
+ if ( !readConfigEntry(BaseGlobalConfig::AutoRebuildModified).toBool() ) {
+ res = MessageBox::questionYesNoCancel(i18n("The project hex file may not be up-to-date since some project files have been modified."),
+ i18n("Recompile First"), i18n("Continue Anyway"));
+ if ( res==MessageBox::Cancel ) return 0;
+ }
+ if ( res==MessageBox::Yes ) {
+ _forceProgramAfterBuild = true;
+ buildProject();
+ return 0;
+ }
+ }
+ if ( Main::currentEditor() && Main::currentEditor()->fileType()==PURL::Hex )
+ return static_cast<HexEditor *>(Main::currentEditor());
+ PURL::Url purl = Main::_projectManager->projectUrl();
+ HexEditor *editor = static_cast<HexEditor *>(Main::_editorManager->openEditor(purl.toFileType(PURL::Hex)));
+ if ( editor==0 ) return 0;
+ editor->setReadOnly(true);
+ return editor;
+}
+
+void MainWindow::erase()
+{
+ Programmer::manager->erase(Device::MemoryRange());
+}
+
+void MainWindow::blankCheck()
+{
+ Programmer::manager->blankCheck(Device::MemoryRange());
+}
+
+void MainWindow::program()
+{
+ HexEditor *editor = getHexEditor();
+ if ( editor==0 ) return;
+ if ( Main::programmerGroup().isDebugger() && !Main::_projectManager->contains(editor->url()) ) {
+ MessageBox::sorry(i18n("It is not possible to start a debugging session with an hex file not generated with the current project."), Log::Show);
+ return;
+ }
+ Programmer::manager->program(*editor->memory(), Device::MemoryRange());
+}
+
+void MainWindow::verify()
+{
+ HexEditor *editor = getHexEditor();
+ if ( editor==0 ) return;
+ Programmer::manager->verify(*editor->memory(), Device::MemoryRange());
+}
+
+void MainWindow::read()
+{
+ QString s = i18n("Read");
+ Editor *e = Main::_editorManager->findEditor(s);
+ if (e) Main::_editorManager->closeEditor(e, true);
+ HexEditor *editor = new HexEditor(s, Main::_editorManager);
+ editor->setDevice();
+ if ( Programmer::manager->read(*editor->memory(), Device::MemoryRange()) ) {
+ editor->memoryRead();
+ Main::_editorManager->addEditor(editor);
+ } else delete editor;
+}
+
+void MainWindow::showProgress(bool show)
+{
+ if (show) {
+ BusyCursor::start();
+ _actionStatus->show();
+ _actionProgress->show();
+ } else {
+ BusyCursor::stop();
+ _actionStatus->hide();
+ _actionProgress->hide();
+ }
+}
+
+void MainWindow::setTotalProgress(uint nb)
+{
+ //KIO::Job *job = new KIO::SimpleJob(KURL(), 0, 0, false);
+ //int id = Observer::self()->newJob(job, true);
+ //Observer::self()->slotTotalSize(job, total);
+ //Observer::self()->slotInfoMessage(job, "test");
+ //qDebug("set total steps: %i", total);
+ _actionProgress->setTotalSteps(nb);
+ _actionProgress->setProgress(0);
+ QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput); // #### DANGER !!!!
+}
+
+void MainWindow::setProgress(uint nb)
+{
+ _actionProgress->setProgress(nb);
+ QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput); // #### DANGER !!!!
+}
diff --git a/src/libgui/toplevel.h b/src/libgui/toplevel.h
new file mode 100644
index 0000000..11a4316
--- /dev/null
+++ b/src/libgui/toplevel.h
@@ -0,0 +1,132 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * Copyright (C) 2003-2004 Alain Gibaud <alain.gibaud@free.fr> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef TOPLEVEL_H
+#define TOPLEVEL_H
+
+#include <qlabel.h>
+#include <qprogressbar.h>
+#include <kdockwidget.h>
+
+#include "config_center.h"
+#include "tools/list/compile_process.h"
+#include "toplevel_ui.h"
+namespace Programmer { class Group; }
+namespace Tool { class Group; }
+class ConfigGenerator;
+class HexEditor;
+namespace Process { class Base; }
+
+class MainWindow : public KDockMainWindow
+{
+Q_OBJECT
+public:
+ MainWindow();
+ virtual ~MainWindow();
+ void setDevice(const QString &device);
+
+public slots:
+ void newSourceFile();
+ void newProject();
+ void openProject();
+ void buildProject();
+ void cleanBuild();
+ void configure(ConfigCenter::Type showType = ConfigCenter::General);
+ void configureProject();
+ void showDeviceInfo();
+ void runPikloops();
+ void runKfind();
+ void configGenerator();
+ void templateGenerator();
+ void updateGUI();
+
+private slots:
+ void newHexFile();
+ bool openFile();
+ void openRecentFile(const KURL &url);
+
+ void compileFile();
+ void compileSuccess();
+ void compileFailure();
+ void updateFile(const Compile::FileData &data);
+ void stopBuild();
+
+ void erase();
+ void blankCheck();
+ void program();
+ void verify();
+ void read();
+ void showProgress(bool show);
+ void setTotalProgress(uint nbSteps);
+ void setProgress(uint nbSteps);
+
+ void applyToolbarSettings();
+ void configureToolbar();
+ void configureToolchains();
+ void configureProgrammer() { configure(ConfigCenter::ProgSelect); }
+ void showProgrammerSettings() { configure(ConfigCenter::ProgOptions); }
+ void showDebuggerSettings() { configure(ConfigCenter::DebugOptions); }
+ void selectProgrammer(const Programmer::Group &group);
+ void selectTool(const Tool::Group &group);
+
+ void updateToolViewsActions();
+ void resetDockLayout();
+ void toggleToolView(QWidget *widget);
+
+ void pikloopsDone();
+ void kfindDone();
+
+ void openRecentProject(const KURL &url);
+ void closeProject();
+
+ void initialLoading();
+
+signals:
+ void stateChanged();
+
+private:
+ Log::Widget *_programLog;
+ QLabel *_actionStatus, *_debugStatus, *_editorStatus;
+ ProgrammerStatusWidget *_programmerStatus;
+ ToolStatusWidget *_toolStatus;
+ QProgressBar *_actionProgress;
+ ConfigGenerator *_configGenerator;
+ ::Process::Base *_pikloopsProcess, *_kfindProcess;
+ bool _forceProgramAfterBuild;
+
+ class DockPosition {
+ public:
+ DockPosition() {}
+ DockPosition(const QString &pparent) : parent(pparent), pos(KDockWidget::DockCenter), space(0) {}
+ DockPosition(KDockWidget::DockPosition ppos, uint pspace) : parent("main_dock_widget"), pos(ppos), space(pspace) {}
+ QString parent;
+ KDockWidget::DockPosition pos;
+ uint space;
+ };
+ class DockData {
+ public:
+ ViewMenuAction *action;
+ KDockWidget *dock;
+ QString title;
+ DockPosition position;
+ };
+ QValueList<DockData> _docks;
+ KDockWidget *_mainDock;
+
+ HexEditor *getHexEditor();
+ virtual bool queryClose();
+ bool stopOperations();
+ void cleanBuild(bool singleFile);
+ virtual void keyPressEvent(QKeyEvent *e);
+ void readDockConfig();
+ KDockWidget *createDock(const QString &name, const QPixmap &icon, const QString &title, const DockPosition &position);
+ void initDockPosition(const DockData &ddata);
+};
+
+#endif
diff --git a/src/libgui/toplevel_ui.cpp b/src/libgui/toplevel_ui.cpp
new file mode 100644
index 0000000..5e8db32
--- /dev/null
+++ b/src/libgui/toplevel_ui.cpp
@@ -0,0 +1,79 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "toplevel_ui.h"
+
+#include <qstyle.h>
+#include <kiconloader.h>
+
+#include "progs/list/prog_list.h"
+#include "tools/list/tool_list.h"
+
+//----------------------------------------------------------------------------
+ProgrammerStatusWidget::ProgrammerStatusWidget(QWidget *parent)
+ : QObject(parent), KeyPopupButton<QString>(parent)
+{
+ connect(widget(), SIGNAL(activated(int)), SLOT(activatedSlot(int)));
+ widget()->appendAction(i18n("Configure..."), "configure", this, SIGNAL(configure()));
+ widget()->appendSeparator();
+ Programmer::Lister::ConstIterator it;
+ for (it=Programmer::lister().begin(); it!=Programmer::lister().end(); ++it)
+ appendItem(it.key(), it.data()->label());
+}
+
+void ProgrammerStatusWidget::activatedSlot(int id)
+{
+ emit selected(*Programmer::lister().group(key(id)));
+}
+
+//----------------------------------------------------------------------------
+ToolStatusWidget::ToolStatusWidget(QWidget *parent)
+ : QObject(parent), KeyPopupButton<QString>(parent)
+{
+ connect(widget(), SIGNAL(activated(int)), SLOT(activatedSlot(int)));
+ widget()->appendAction(i18n("Configure Toolchain..."), "configure", this, SIGNAL(configureToolchain()));
+ widget()->appendAction(i18n("Configure Compilation..."), "configure", this, SIGNAL(configure()));
+ widget()->appendSeparator();
+ Tool::Lister::ConstIterator it;
+ for (it=Tool::lister().begin(); it!=Tool::lister().end(); ++it)
+ appendItem(it.key(), it.data()->label());
+}
+
+void ToolStatusWidget::activatedSlot(int id)
+{
+ emit selected(*Tool::lister().group(key(id)));
+}
+
+//----------------------------------------------------------------------------
+ViewMenuAction::ViewMenuAction(KDockWidget *widget)
+ : KToggleAction(widget->tabPageLabel()), _widget(widget)
+{}
+
+void ViewMenuAction::slotActivated()
+{
+ KAction::slotActivated();
+ emit activated(_widget);
+}
+
+//----------------------------------------------------------------------------
+MenuBarButton::MenuBarButton(const QString &icon, QWidget *parent)
+ : QToolButton(parent, "menu_bar_button")
+{
+ QFontMetrics fm(font());
+ int h = fm.height() + 2*style().pixelMetric(QStyle::PM_DefaultFrameWidth, this);
+ setFixedHeight(h);
+ KIconLoader loader;
+ setIconSet(loader.loadIconSet(icon, KIcon::Small, fm.height()-2));
+ setUsesTextLabel(false);
+ setAutoRaise(true);
+}
+
+QSize MenuBarButton::sizeHint() const
+{
+ return QSize(QToolButton::sizeHint().width(), height());
+}
diff --git a/src/libgui/toplevel_ui.h b/src/libgui/toplevel_ui.h
new file mode 100644
index 0000000..8a5f631
--- /dev/null
+++ b/src/libgui/toplevel_ui.h
@@ -0,0 +1,77 @@
+/***************************************************************************
+ * Copyright (C) 2005-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef TOPLEVEL_UI_H
+#define TOPLEVEL_UI_H
+
+#include <qtoolbutton.h>
+#include <kdockwidget.h>
+#include <kaction.h>
+
+#include "common/gui/key_gui.h"
+namespace Programmer { class Group; }
+namespace Tool { class Group; }
+
+//----------------------------------------------------------------------------
+class ProgrammerStatusWidget : public QObject, public KeyPopupButton<QString>
+{
+Q_OBJECT
+public:
+ ProgrammerStatusWidget(QWidget *parent);
+
+signals:
+ void configure();
+ void selected(const Programmer::Group &group);
+
+private slots:
+ void activatedSlot(int id);
+};
+
+//----------------------------------------------------------------------------
+class ToolStatusWidget : public QObject, public KeyPopupButton<QString>
+{
+Q_OBJECT
+public:
+ ToolStatusWidget(QWidget *parent);
+
+signals:
+ void configureToolchain();
+ void configure();
+ void selected(const Tool::Group &group);
+
+private slots:
+ void activatedSlot(int id);
+};
+
+//----------------------------------------------------------------------------
+class ViewMenuAction : public KToggleAction
+{
+Q_OBJECT
+public:
+ ViewMenuAction(KDockWidget *widget);
+
+signals:
+ void activated(QWidget *);
+
+private slots:
+ virtual void slotActivated();
+
+private:
+ KDockWidget *_widget;
+};
+
+//----------------------------------------------------------------------------
+class MenuBarButton : public QToolButton
+{
+Q_OBJECT
+public:
+ MenuBarButton(const QString &icon, QWidget *parent);
+ virtual QSize sizeHint() const;
+};
+
+#endif
diff --git a/src/libgui/watch_view.cpp b/src/libgui/watch_view.cpp
new file mode 100644
index 0000000..984dc7c
--- /dev/null
+++ b/src/libgui/watch_view.cpp
@@ -0,0 +1,225 @@
+/***************************************************************************
+ * Copyright (C) 2006-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#include "watch_view.h"
+
+#include <qheader.h>
+#include <qcombobox.h>
+#include <kiconloader.h>
+
+#include "main_global.h"
+#include "register_view.h"
+#include "devices/base/device_group.h"
+#include "devices/gui/device_group_ui.h"
+#include "gui_debug_manager.h"
+#include "editor_manager.h"
+#include "common/gui/list_container.h"
+
+//-----------------------------------------------------------------------------
+Register::BaseListView::BaseListView(QWidget *parent)
+ : ListView(parent), _root(0)
+{
+ header()->hide();
+ setSorting(-1);
+ setFullWidth(true);
+ setRootIsDecorated(false);
+ setAllColumnsShowFocus(true);
+ connect(this, SIGNAL(mouseButtonClicked(int, QListViewItem *, const QPoint &, int)),
+ SLOT(itemClicked(int, QListViewItem *, const QPoint &, int)));
+ connect(this, SIGNAL(contextMenuRequested(QListViewItem *, const QPoint &, int)),
+ SLOT(contextMenu(QListViewItem *, const QPoint &, int)));
+}
+
+//-----------------------------------------------------------------------------
+Register::RegisterListView::RegisterListView(QWidget *parent)
+ : BaseListView(parent)
+{
+ addColumn(QString::null);
+}
+
+void Register::RegisterListView::init(const Device::Data *data)
+{
+ delete _root;
+ _root = new ListViewItemContainer(i18n("Registers"), this);
+ KIconLoader loader;
+ _root->setPixmap(0, loader.loadIcon("piklab_chip", KIcon::Small));
+ _root->setSelectable(false);
+ _root->setOpen(true);
+ if (data) Device::groupui(*data).fillWatchListContainer(_root, _ids);
+}
+
+void Register::RegisterListView::updateView()
+{
+ QListViewItemIterator it(_root);
+ for (; it.current(); ++it) {
+ int id = _root->id(it.current());
+ if ( id==-1 || _ids[id].type()==Invalid ) continue;
+ bool watched = Register::list().isWatched(_ids[id]);
+ static_cast<QCheckListItem *>(it.current())->setOn(watched);
+ }
+}
+
+void Register::RegisterListView::itemClicked(int button, QListViewItem *item, const QPoint &, int)
+{
+ if ( item==0 || button!=LeftButton ) return;
+ if ( item==firstChild() ) Main::editorManager().openEditor(EditorManager::RegisterEditor);
+ int id = _root->id(item);
+ if ( id==-1 || _ids[id].type()==Invalid ) return;
+ bool watched = Register::list().isWatched(_ids[id]);
+ static_cast<QCheckListItem *>(item)->setOn(!watched);
+ Debugger::manager->setRegisterWatched(_ids[id], !watched);
+}
+
+//-----------------------------------------------------------------------------
+Register::WatchedListView::WatchedListView(QWidget *parent)
+ : BaseListView(parent), _popup(0), _base(NumberBase::Hex)
+{
+ setSorting(0);
+ addColumn(QString::null);
+ addColumn(QString::null);
+ addColumn(QString::null);
+
+ _root = new ListViewItemContainer(i18n("Watched"), this);
+ KIconLoader loader;
+ _root->setPixmap(0, loader.loadIcon("viewmag", KIcon::Small));
+ _root->setSelectable(false);
+ _root->setOpen(true);
+}
+
+KPopupMenu *Register::WatchedListView::appendFormatMenu(KPopupMenu *parent, uint offset)
+{
+ KIconLoader loader;
+ QPixmap icon = loader.loadIcon("fonts", KIcon::Small);
+ KPopupMenu *popup = new KPopupMenu;
+ popup->insertTitle(i18n("Format"));
+ FOR_EACH(NumberBase, base) popup->insertItem(base.label(), offset + base.type());
+ parent->insertItem(icon, i18n("Format"), popup);
+ return popup;
+}
+
+void Register::WatchedListView::init(const Device::Data *data)
+{
+ delete _popup;
+ _popup = 0;
+ if ( data==0 ) return;
+ _popup = new PopupContainer(i18n("Watch Register"), this);
+ Device::groupui(*data).fillWatchListContainer(_popup, _ids);
+ _popup->insertSeparator();
+ _formatPopup = appendFormatMenu(_popup, _ids.count());
+ KIconLoader loader;
+ QPixmap icon = loader.loadIcon("cancel", KIcon::Small);
+ _popup->insertItem(icon, i18n("Clear"), Debugger::manager, SLOT(stopWatchAll()));
+}
+
+void Register::WatchedListView::updateView()
+{
+ // delete items not watched anymore
+ for (QListViewItem *item=_root->firstChild(); item;) {
+ ListViewItem *ritem = static_cast<ListViewItem *>(item);
+ item = item->nextSibling();
+ if ( !Register::list().isWatched(ritem->data()) ) delete ritem;
+ }
+ // add new items
+ bool added = false;
+ QValueList<Register::TypeData> watched = Register::list().watched();
+ QValueVector<ListViewItem *> items(watched.count());
+ for (uint k=0; k<watched.count(); k++) {
+ QListViewItem *item = _root->firstChild();
+ for (; item; item=item->nextSibling())
+ if ( static_cast<ListViewItem *>(item)->data()==watched[k] ) break;
+ if (item) {
+ items[k] = static_cast<ListViewItem *>(item);
+ items[k]->updateView();
+ } else {
+ items[k] = Device::groupui(*Main::deviceData()).createWatchItem(watched[k], _root);
+ items[k]->setBase(_base);
+ added = true;
+ }
+ }
+}
+
+QString Register::WatchedListView::tooltip(const QListViewItem &item, int col) const
+{
+ if ( item.rtti()==Register::PortBitRtti ) return static_cast<const PortBitListViewItem &>(item).tooltip(col);
+ if ( item.rtti()==Register::RegisterRtti ) return static_cast<const ListViewItem &>(item).tooltip(col);
+ return QString::null;
+}
+
+void Register::WatchedListView::itemClicked(int button, QListViewItem *item, const QPoint &, int col)
+{
+ if ( item==0 || button!=LeftButton ) return;
+ else if ( item->rtti()==RegisterRtti ) {
+ if ( col==2 && Main::programmerState()==Programmer::Halted ) static_cast<ListViewItem *>(item)->startRename();
+ else item->setOpen(!item->isOpen());
+ }
+}
+
+void Register::WatchedListView::contextMenu(QListViewItem *item, const QPoint &p, int)
+{
+ if ( item==0 ) return;
+ if ( item==firstChild() ) {
+ if ( _popup==0 ) return;
+ FOR_EACH(NumberBase, base) _formatPopup->setItemChecked(_ids.count()+base.type(), _base==base);
+ int res = _popup->exec(p);
+ if ( res<0 ) return;
+ if ( res<int(_ids.count()) ) Debugger::manager->setRegisterWatched(_ids[res], true);
+ else {
+ _base = NumberBase::Type(res-_ids.count());
+ for (QListViewItem *item=_root->firstChild(); item; item=item->nextSibling())
+ static_cast<ListViewItem *>(item)->setBase(_base);
+ }
+ } else {
+ if ( item->rtti()==Register::PortBitRtti ) return;
+ Register::ListViewItem *ritem = static_cast<ListViewItem *>(item);
+ KPopupMenu *pop = new KPopupMenu;
+ pop->insertTitle(ritem->label());
+ QPopupMenu *fpop = appendFormatMenu(pop, 0);
+ FOR_EACH(NumberBase, base) fpop->setItemChecked(base.type(), ritem->base()==base);
+ pop->insertSeparator();
+ KIconLoader loader;
+ QPixmap icon = loader.loadIcon("edit", KIcon::Small);
+ int editId = pop->insertItem(icon, i18n("Edit"));
+ pop->setItemEnabled(editId, Main::programmerState()==Programmer::Halted);
+ icon = loader.loadIcon("cancel", KIcon::Small);
+ int removeId = pop->insertItem(icon, i18n("Remove"));
+ int res = pop->exec(p);
+ if ( res==editId ) ritem->startRename();
+ else if ( res==removeId ) Debugger::manager->setRegisterWatched(ritem->data(), false);
+ else if ( res>=0 ) ritem->setBase(NumberBase::Type(res));
+ delete pop;
+ }
+}
+
+//-----------------------------------------------------------------------------
+Register::WatchView::WatchView(QWidget *parent)
+ : QWidget(parent, "watch_view"), GenericView(Register::list()), _data(0)
+{
+ QVBoxLayout *top = new QVBoxLayout(this);
+ QValueList<int> sizes;
+ sizes.append(50);
+ Splitter *splitter = new Splitter(sizes, Qt::Vertical, this, "watch_window_splitter");
+ top->addWidget(splitter);
+
+ _registerListView = new RegisterListView(splitter);
+ _watchedListView = new WatchedListView(splitter);
+}
+
+void Register::WatchView::init(bool force)
+{
+ if ( !force && _data==Main::deviceData() ) return;
+ _data = Main::deviceData();
+ _registerListView->init(_data);
+ _watchedListView->init(_data);
+ updateView();
+}
+
+void Register::WatchView::updateView()
+{
+ _registerListView->updateView();
+ _watchedListView->updateView();
+}
diff --git a/src/libgui/watch_view.h b/src/libgui/watch_view.h
new file mode 100644
index 0000000..a7ac24c
--- /dev/null
+++ b/src/libgui/watch_view.h
@@ -0,0 +1,94 @@
+/***************************************************************************
+ * Copyright (C) 2006-2007 Nicolas Hadacek <hadacek@kde.org> *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) any later version. *
+ ***************************************************************************/
+#ifndef WATCH_VIEW_H
+#define WATCH_VIEW_H
+
+#include "common/gui/list_container.h"
+#include "common/common/storage.h"
+#include "common/gui/list_view.h"
+#include "devices/base/register.h"
+namespace Device { class Data; }
+
+namespace Register
+{
+
+//-----------------------------------------------------------------------------
+class BaseListView : public ListView
+{
+Q_OBJECT
+public:
+ BaseListView(QWidget *parent);
+ virtual void init(const Device::Data *data) = 0;
+ virtual void updateView() = 0;
+
+private slots:
+ virtual void itemClicked(int button, QListViewItem *item, const QPoint &p, int col) = 0;
+ virtual void contextMenu(QListViewItem *item, const QPoint &p, int col) = 0;
+
+protected:
+ ListViewItemContainer *_root;
+ QValueVector<Register::TypeData> _ids;
+};
+
+//-----------------------------------------------------------------------------
+class RegisterListView : public BaseListView
+{
+Q_OBJECT
+public:
+ RegisterListView(QWidget *parent);
+ virtual void init(const Device::Data *data);
+ virtual void updateView();
+
+private slots:
+ virtual void itemClicked(int button, QListViewItem *item, const QPoint &p, int col);
+ virtual void contextMenu(QListViewItem *, const QPoint &, int) {}
+};
+
+//-----------------------------------------------------------------------------
+class WatchedListView : public BaseListView
+{
+Q_OBJECT
+public:
+ WatchedListView(QWidget *parent);
+ virtual QString tooltip(const QListViewItem &item, int col) const;
+ virtual void init(const Device::Data *data);
+ virtual void updateView();
+
+private slots:
+ virtual void itemClicked(int button, QListViewItem *item, const QPoint &p, int col);
+ virtual void contextMenu(QListViewItem *item, const QPoint &p, int col);
+
+private:
+ PopupContainer *_popup;
+ KPopupMenu *_formatPopup;
+ NumberBase _base;
+
+ static KPopupMenu *appendFormatMenu(KPopupMenu *parent, uint offset);
+};
+
+//-----------------------------------------------------------------------------
+class WatchView : public QWidget, public GenericView
+{
+Q_OBJECT
+public:
+ WatchView(QWidget *parent);
+ void init(bool force);
+
+public slots:
+ virtual void updateView();
+
+private:
+ WatchedListView *_watchedListView;
+ RegisterListView *_registerListView;
+ const Device::Data *_data;
+};
+
+} // namespace
+
+#endif