summaryrefslogtreecommitdiffstats
path: root/src/libgui/editor_manager.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 18:42:24 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-24 18:42:24 +0000
commitf508189682b6fba62e08feeb1596f682bad5fff9 (patch)
tree28aeb0e6c19386c385c1ce5edf8a92c1bca15281 /src/libgui/editor_manager.cpp
downloadpiklab-f508189682b6fba62e08feeb1596f682bad5fff9.tar.gz
piklab-f508189682b6fba62e08feeb1596f682bad5fff9.zip
Added KDE3 version of PikLab
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/piklab@1095639 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/libgui/editor_manager.cpp')
-rw-r--r--src/libgui/editor_manager.cpp506
1 files changed, 506 insertions, 0 deletions
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;
+}