Bug 259066 - "Outline" toolbar item needs "Code Browser" toolview enabled
Summary: "Outline" toolbar item needs "Code Browser" toolview enabled
Status: RESOLVED FIXED
Alias: None
Product: kdevplatform
Classification: Developer tools
Component: contextbrowser (other bugs)
Version First Reported In: 1.1.0
Platform: Unlisted Binaries Linux
: VHI major
Target Milestone: 1.2.0
Assignee: kdevelop-bugs-null
URL:
Keywords:
: 203962 (view as bug list)
Depends on:
Blocks:
 
Reported: 2010-12-07 01:22 UTC by Nicolás Alvarez
Modified: 2010-12-17 17:05 UTC (History)
1 user (show)

See Also:
Latest Commit:
Version Fixed/Implemented In:
Sentry Crash Report:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Nicolás Alvarez 2010-12-07 01:22:39 UTC
If I remove the Code Browser toolview, the Outline pseudo text box in the toolbar disappears immediately. It still appears in the toolbar configuration as if it was there, but it's not visible.

Re-adding the Code Browser toolview makes the toolbar item reappear immediately.
Comment 1 Milian Wolff 2010-12-07 13:08:22 UTC
probably only a wrong parent - the widget should be created in the KAction::createWidget method and not take the toolview as parent.
Comment 2 Milian Wolff 2010-12-16 21:57:04 UTC
it also seems that most other useful features of the context browser plugin (tooltip, actual browsing via ctrl + click, ...) all rely on a view being around.

I'll try to fix that later.
Comment 3 Milian Wolff 2010-12-17 13:04:19 UTC
*** Bug 203962 has been marked as a duplicate of this bug. ***
Comment 4 Milian Wolff 2010-12-17 17:05:10 UTC
commit 3bc2e9b5f2ed606e5d4d85292473f34b9af20f86
branch 1.2
Author: Milian Wolff <mail@milianw.de>
Date:   Fri Dec 17 17:03:21 2010 +0100

    Refactor context browser plugin to make it useable without a toolview.
    
    BUG: 259066
    
    Please, everyone test this as extensively as possible. I didn't spot any issues.
    But I don't want to ship 4.2 with regressions here.

diff --git a/language/util/navigationtooltip.h b/language/util/navigationtooltip.h
index 861fc29..2969c3c 100644
--- a/language/util/navigationtooltip.h
+++ b/language/util/navigationtooltip.h
@@ -27,6 +27,9 @@ namespace KDevelop {
 class AbstractNavigationWidget;
 
 ///A tooltip that just emebed the given widget.
+///
+///TODO: 4.3 - cleanup indentation
+///      introduce getter for widget, use that in context browser
 class KDEVPLATFORMLANGUAGE_EXPORT NavigationToolTip : public ActiveToolTip
 {
     Q_OBJECT
diff --git a/plugins/contextbrowser/browsemanager.cpp b/plugins/contextbrowser/browsemanager.cpp
index 65a673c..77ab0c4 100644
--- a/plugins/contextbrowser/browsemanager.cpp
+++ b/plugins/contextbrowser/browsemanager.cpp
@@ -42,17 +42,14 @@
 #include <qtimer.h>
 #include <qapplication.h>
 
+#include "contextbrowser.h"
+
 using namespace KDevelop;
 using namespace KTextEditor;
 
-static QWidget* masterWidget(QWidget* w) {
-  while(w && w->parentWidget())
-    w = w->parentWidget();
-  return w;
-}
-
-EditorViewWatcher::EditorViewWatcher(QWidget* sameWindow) : m_childrenOf(masterWidget(sameWindow)) {
-    
+EditorViewWatcher::EditorViewWatcher(QObject* parent)
+    : QObject(parent)
+{
     connect(ICore::self()->documentController(), SIGNAL(textDocumentCreated(KDevelop::IDocument*)), this, SLOT(documentCreated(KDevelop::IDocument*)));
     foreach(KDevelop::IDocument* document, ICore::self()->documentController()->openDocuments())
         documentCreated(document);
@@ -64,8 +61,7 @@ void EditorViewWatcher::documentCreated( KDevelop::IDocument* document ) {
         connect(textDocument, SIGNAL(viewCreated(KTextEditor::Document*, KTextEditor::View*)), this, SLOT(viewCreated(KTextEditor::Document*, KTextEditor::View*)));
         foreach(KTextEditor::View* view, textDocument->views()) {
             Q_ASSERT(view->parentWidget());
-//             if(!m_childrenOf || masterWidget(view) == m_childrenOf)
-                addViewInternal(view);
+            addViewInternal(view);
         }
     }
 }
@@ -85,9 +81,7 @@ void EditorViewWatcher::viewDestroyed(QObject* view) {
 
 void EditorViewWatcher::viewCreated(KTextEditor::Document* /*doc*/, KTextEditor::View* view) {
     Q_ASSERT(view->parentWidget());
-    //The test doesn't work porperly at this point
-//     if(!m_childrenOf || masterWidget(view) == m_childrenOf)
-        addViewInternal(view);
+    addViewInternal(view);
 }
 
 QList<KTextEditor::View*> EditorViewWatcher::allViews() {
@@ -99,7 +93,7 @@ void BrowseManager::eventuallyStartDelayedBrowsing() {
         emit startDelayedBrowsing(m_browingStartedInView);
 }
 
-BrowseManager::BrowseManager(ContextBrowserView* controller) : QObject(controller), m_view(controller), m_browsing(false), m_browsingByKey(0), m_watcher(this) {
+BrowseManager::BrowseManager(ContextBrowserPlugin* controller) : QObject(controller), m_plugin(controller), m_browsing(false), m_browsingByKey(0), m_watcher(this) {
     m_delayedBrowsingTimer = new QTimer(this);
     m_delayedBrowsingTimer->setSingleShot(true);
     
@@ -157,7 +151,7 @@ bool BrowseManager::eventFilter(QObject * watched, QEvent * event) {
         }
         
         if(!m_browsing)
-            m_view->setAllowBrowsing(true); 
+            m_plugin->setAllowBrowsing(true); 
         
     }
     
@@ -167,7 +161,7 @@ bool BrowseManager::eventFilter(QObject * watched, QEvent * event) {
     if((keyEvent && m_browsingByKey && keyEvent->key() == m_browsingByKey && keyEvent->type() == QEvent::KeyRelease) || 
        (focusEvent && focusEvent->lostFocus())) {
         if(!m_browsing)
-            m_view->setAllowBrowsing(false);
+            m_plugin->setAllowBrowsing(false);
         m_browsingByKey = 0;
         emit stopDelayedBrowsing();
     }
@@ -302,12 +296,12 @@ void BrowseManager::viewAdded(KTextEditor::View* view) {
     //We need to listen for cursorPositionChanged, to clear the shift-detector. The problem: Kate listens for the arrow-keys using shortcuts,
     //so those keys are not passed to the event-filter
 
-    connect(view, SIGNAL(navigateLeft()), m_view, SLOT(navigateLeft()));
-    connect(view, SIGNAL(navigateRight()), m_view, SLOT(navigateRight()));
-    connect(view, SIGNAL(navigateUp()), m_view, SLOT(navigateUp()));
-    connect(view, SIGNAL(navigateDown()), m_view, SLOT(navigateDown()));
-    connect(view, SIGNAL(navigateAccept()), m_view, SLOT(navigateAccept()));
-    connect(view, SIGNAL(navigateBack()), m_view, SLOT(navigateBack()));
+    connect(view, SIGNAL(navigateLeft()), m_plugin, SLOT(navigateLeft()));
+    connect(view, SIGNAL(navigateRight()), m_plugin, SLOT(navigateRight()));
+    connect(view, SIGNAL(navigateUp()), m_plugin, SLOT(navigateUp()));
+    connect(view, SIGNAL(navigateDown()), m_plugin, SLOT(navigateDown()));
+    connect(view, SIGNAL(navigateAccept()), m_plugin, SLOT(navigateAccept()));
+    connect(view, SIGNAL(navigateBack()), m_plugin, SLOT(navigateBack()));
 }
 
 void BrowseManager::Watcher::viewAdded(KTextEditor::View* view) {
@@ -330,7 +324,8 @@ void BrowseManager::setBrowsing(bool enabled) {
     }
 }
 
-BrowseManager::Watcher::Watcher(BrowseManager* manager) : EditorViewWatcher(masterWidget(manager->m_view)), m_manager(manager) {
+BrowseManager::Watcher::Watcher(BrowseManager* manager)
+    : EditorViewWatcher(manager), m_manager(manager) {
     foreach(KTextEditor::View* view, allViews())
         m_manager->applyEventFilter(view, true);
 }
diff --git a/plugins/contextbrowser/browsemanager.h b/plugins/contextbrowser/browsemanager.h
index 566a9e3..acb896d 100644
--- a/plugins/contextbrowser/browsemanager.h
+++ b/plugins/contextbrowser/browsemanager.h
@@ -43,25 +43,24 @@ namespace KDevelop {
 
 class EditorViewWatcher : QObject {
     Q_OBJECT
-    public:
+public:
     ///@param sameWindow If this is true, only views that are child of the same window as the given widget are registered
-    EditorViewWatcher(QWidget* sameWindow = 0);
+    EditorViewWatcher(QObject* parent = 0);
     QList<KTextEditor::View*> allViews();
-    private:
+private:
     ///Called for every added view. Reimplement this to catch them.
     virtual void viewAdded(KTextEditor::View*);
     
-    private slots:
+private slots:
     void viewDestroyed(QObject* view);
     void viewCreated(KTextEditor::Document*, KTextEditor::View*);
     void documentCreated( KDevelop::IDocument* document );
-    private:
+private:
     void addViewInternal(KTextEditor::View* view);
     QList<KTextEditor::View*> m_views;
-    QWidget* m_childrenOf;
 };
 
-class ContextBrowserView;
+class ContextBrowserPlugin;
 
 /**
  * Integrates the context-browser with the editor views, by listening for navigation events, and implementing html-like source browsing
@@ -70,10 +69,8 @@ class ContextBrowserView;
 class BrowseManager : public QObject {
     Q_OBJECT
     public:
-        BrowseManager(ContextBrowserView* controller);
+        BrowseManager(ContextBrowserPlugin* controller);
     Q_SIGNALS:
-        //Emitted whenever the shift-key has been pressed + released without any other key in between
-        void shiftKeyTriggered();
         //Emitted when browsing was started using the magic-modifier
         void startDelayedBrowsing(KTextEditor::View* view);
         void stopDelayedBrowsing();
@@ -86,10 +83,10 @@ class BrowseManager : public QObject {
         void viewAdded(KTextEditor::View* view);
         class Watcher : public EditorViewWatcher {
             public:
-            Watcher(BrowseManager* manager);
-            virtual void viewAdded(KTextEditor::View*);
+                Watcher(BrowseManager* manager);
+                virtual void viewAdded(KTextEditor::View*);
             private:
-            BrowseManager* m_manager;
+                BrowseManager* m_manager;
         };
         
         void resetChangedCursor();
@@ -98,7 +95,7 @@ class BrowseManager : public QObject {
         //Installs/uninstalls the event-filter
         void applyEventFilter(QWidget* object, bool install);
         virtual bool eventFilter(QObject * watched, QEvent * event) ;
-        ContextBrowserView* m_view;
+        ContextBrowserPlugin* m_plugin;
         bool m_browsing;
         int m_browsingByKey; //Whether the browsing was started because of a key
         Watcher m_watcher;
diff --git a/plugins/contextbrowser/contextbrowser.cpp b/plugins/contextbrowser/contextbrowser.cpp
index f758748..cec1ae1 100644
--- a/plugins/contextbrowser/contextbrowser.cpp
+++ b/plugins/contextbrowser/contextbrowser.cpp
@@ -21,6 +21,9 @@
 
 #include "contextbrowser.h"
 
+#include "browsemanager.h"
+
+///TODO: cleanup includes
 #include <QTimer>
 #include <QApplication>
 #include <qalgorithms.h>
@@ -63,9 +66,14 @@
 #include <interfaces/iplugincontroller.h>
 #include <sublime/mainwindow.h>
 #include <memory>
+#include <QToolButton>
+#include <QLayout>
+#include <language/duchain/types/functiontype.h>
+#include <ktexteditor/codecompletioninterface.h>
 
 static const unsigned int highlightingTimeout = 150;
 static const float highlightingZDepth = -5000;
+static const int maxHistoryLength = 30;
 
 using KDevelop::ILanguage;
 using KTextEditor::Attribute;
@@ -84,11 +92,23 @@ QWidget* masterWidget(QWidget* w) {
 DUContext* contextForHighlightingAt(const SimpleCursor& position, TopDUContext* topContext)
 {
   DUContext* ctx = topContext->findContextAt(topContext->transformToLocalRevision(position));
-  while(ctx && (ctx->type() == DUContext::Template || ctx->type() == DUContext::Helper || ctx->localScopeIdentifier().isEmpty()) && ctx->parentContext())
+  while(ctx && ctx->parentContext()
+        && (ctx->type() == DUContext::Template || ctx->type() == DUContext::Helper
+            || ctx->localScopeIdentifier().isEmpty()))
+  {
     ctx = ctx->parentContext();
+  }
   return ctx;
 }
 
+///Duchain must be locked
+DUContext* getContextAt(KUrl url, KTextEditor::Cursor cursor) {
+  TopDUContext* topContext = DUChainUtils::standardContextForUrl(url);
+  if (!topContext) return 0;
+  return contextForHighlightingAt(SimpleCursor(cursor), topContext);
+}
+
+
 class ContextBrowserViewFactory: public KDevelop::IToolViewFactory
 {
 public:
@@ -97,8 +117,6 @@ public:
     virtual QWidget* create(QWidget *parent = 0)
     {
         ContextBrowserView* ret = new ContextBrowserView(m_plugin, parent);
-        QObject::connect(ret, SIGNAL(startDelayedBrowsing(KTextEditor::View*)), m_plugin, SLOT(startDelayedBrowsing(KTextEditor::View*)));
-        QObject::connect(ret, SIGNAL(stopDelayedBrowsing()), m_plugin, SLOT(stopDelayedBrowsing()));
         return ret;
     }
 
@@ -115,8 +133,84 @@ public:
 private:
     ContextBrowserPlugin *m_plugin;
 };
+KXMLGUIClient* ContextBrowserPlugin::createGUIForMainWindow( Sublime::MainWindow* window )
+{
+    KXMLGUIClient* ret = KDevelop::IPlugin::createGUIForMainWindow( window );
+    
+    m_browseManager = new BrowseManager(this);
+    
+    connect(ICore::self()->documentController(), SIGNAL(documentJumpPerformed(KDevelop::IDocument*, KTextEditor::Cursor, KDevelop::IDocument*, KTextEditor::Cursor)), this, SLOT(documentJumpPerformed(KDevelop::IDocument*, KTextEditor::Cursor, KDevelop::IDocument*, KTextEditor::Cursor)));
+    
+    m_previousButton = new QToolButton();
+    m_previousButton->setToolTip(i18n("Go back in context history"));
+    m_previousButton->setPopupMode(QToolButton::MenuButtonPopup);
+    m_previousButton->setIcon(KIcon("go-previous"));
+    m_previousButton->setEnabled(false);
+    m_previousButton->setFocusPolicy(Qt::NoFocus);
+    m_previousMenu = new QMenu();
+    m_previousButton->setMenu(m_previousMenu);
+    connect(m_previousButton, SIGNAL(clicked(bool)), this, SLOT(historyPrevious()));
+    connect(m_previousMenu, SIGNAL(aboutToShow()), this, SLOT(previousMenuAboutToShow()));
+
+    m_nextButton = new QToolButton();
+    m_nextButton->setToolTip(i18n("Go forward in context history"));
+    m_nextButton->setPopupMode(QToolButton::MenuButtonPopup);
+    m_nextButton->setIcon(KIcon("go-next"));
+    m_nextButton->setEnabled(false);
+    m_nextButton->setFocusPolicy(Qt::NoFocus);
+    m_nextMenu = new QMenu();
+    m_nextButton->setMenu(m_nextMenu);
+    connect(m_nextButton, SIGNAL(clicked(bool)), this, SLOT(historyNext()));
+    connect(m_nextMenu, SIGNAL(aboutToShow()), this, SLOT(nextMenuAboutToShow()));
+
+    m_browseButton = new QToolButton();
+    m_browseButton->setIcon(KIcon("games-hint"));
+    m_browseButton->setToolTip(i18n("Enable/disable source browse mode"));
+    m_browseButton->setWhatsThis(i18n("When this is enabled, you can browse the source-code by clicking in the editor."));
+    m_browseButton->setCheckable(true);
+    m_browseButton->setFocusPolicy(Qt::NoFocus);
+    
+    connect(m_browseButton, SIGNAL(clicked(bool)), m_browseManager, SLOT(setBrowsing(bool)));
+
+    IQuickOpen* quickOpen = KDevelop::ICore::self()->pluginController()->extensionForPlugin<IQuickOpen>("org.kdevelop.IQuickOpen");
+    
+    if(quickOpen) {
+      m_outlineLine = quickOpen->createQuickOpenLine(QStringList(), QStringList() << i18n("Outline"), IQuickOpen::Outline);
+      m_outlineLine->setDefaultText(i18n("Outline..."));
+      m_outlineLine->setToolTip(i18n("Navigate outline of active document, click to browse."));
+    }
+
+    connect(m_browseManager, SIGNAL(startDelayedBrowsing(KTextEditor::View*)),
+            this, SLOT(startDelayedBrowsing(KTextEditor::View*)));
+    connect(m_browseManager, SIGNAL(stopDelayedBrowsing()),
+            this, SLOT(stopDelayedBrowsing()));
+
+    m_toolbarWidget = toolbarWidgetForMainWindow(window);
+    m_toolbarWidgetLayout = new QHBoxLayout;
+    m_toolbarWidgetLayout->setSizeConstraint(QLayout::SetMaximumSize);
+    m_previousButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+    m_nextButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+    m_browseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
+    m_toolbarWidgetLayout->setMargin(0);
+
+    m_toolbarWidgetLayout->addWidget(m_previousButton);
+    m_toolbarWidgetLayout->addWidget(m_outlineLine);
+    m_outlineLine->setMaximumWidth(600);
+    m_toolbarWidgetLayout->addWidget(m_nextButton);
+    m_toolbarWidgetLayout->addWidget(m_browseButton);
+
+    if(m_toolbarWidget->children().isEmpty())
+        m_toolbarWidget->setLayout(m_toolbarWidgetLayout);
+
+    connect(ICore::self()->documentController(), SIGNAL(documentClosed(KDevelop::IDocument*)), m_outlineLine, SLOT(clear()));
+    connect(ICore::self()->documentController(), SIGNAL(documentActivated(KDevelop::IDocument*)), m_outlineLine, SLOT(clear()));
 
-void ContextBrowserPlugin::createActionsForMainWindow(Sublime::MainWindow* window, QString& xmlFile, KActionCollection& actions) {
+    return ret;
+}
+
+void ContextBrowserPlugin::createActionsForMainWindow(Sublime::MainWindow* window, QString& xmlFile,
+                                                      KActionCollection& actions)
+{
     xmlFile = "kdevcontextbrowser.rc" ;
 
     KAction* previousContext = actions.addAction("previous_context");
@@ -150,28 +244,16 @@ void ContextBrowserPlugin::createActionsForMainWindow(Sublime::MainWindow* windo
     outline->setDefaultWidget(w);
 }
 
-
 void ContextBrowserPlugin::nextContextShortcut()
 {
-  foreach(ContextBrowserView* view, m_views)
-  {
-    kDebug() << masterWidget(ICore::self()->uiController()->activeMainWindow()) << masterWidget(view);
-    if(masterWidget(ICore::self()->uiController()->activeMainWindow()) == masterWidget(view)) {
-      view->historyNext();
-      return;
-    }
-  }
+  // TODO: cleanup
+  historyNext();
 }
 
 void ContextBrowserPlugin::previousContextShortcut()
 {
-  foreach(ContextBrowserView* view, m_views)
-  {
-    if(masterWidget(ICore::self()->uiController()->activeMainWindow()) == masterWidget(view)) {
-      view->historyPrevious();
-      return;
-    }
-  }
+  // TODO: cleanup
+  historyPrevious();
 }
 
 K_PLUGIN_FACTORY(ContextBrowserFactory, registerPlugin<ContextBrowserPlugin>(); )
@@ -179,7 +261,8 @@ K_EXPORT_PLUGIN(ContextBrowserFactory(KAboutData("kdevcontextbrowser","kdevconte
 
 ContextBrowserPlugin::ContextBrowserPlugin(QObject *parent, const QVariantList&)
     : KDevelop::IPlugin(ContextBrowserFactory::componentData(), parent)
-    , m_viewFactory(new ContextBrowserViewFactory(this)), m_lastInsertionDocument(0)
+    , m_viewFactory(new ContextBrowserViewFactory(this))
+    , m_nextHistoryIndex(0)
 {
   core()->uiController()->addToolView(i18n("Code Browser"), m_viewFactory);
 
@@ -200,6 +283,15 @@ ContextBrowserPlugin::ContextBrowserPlugin(QObject *parent, const QVariantList&)
 
 ContextBrowserPlugin::~ContextBrowserPlugin()
 {
+  ///TODO: QObject inheritance should suffice?
+  delete m_nextMenu;
+  delete m_previousMenu;
+  delete m_toolbarWidgetLayout;
+
+  delete m_previousButton;
+  delete m_outlineLine;
+  delete m_nextButton;
+  delete m_browseButton;
 }
 
 void ContextBrowserPlugin::unload()
@@ -269,6 +361,7 @@ void ContextBrowserPlugin::stopDelayedBrowsing() {
   if(m_currentToolTip) {
     m_currentToolTip->deleteLater();
     m_currentToolTip = 0;
+    m_currentNavigationWidget = 0;
   }
 }
 
@@ -282,6 +375,7 @@ void ContextBrowserPlugin::hideTooTip() {
   if(m_currentToolTip) {
     m_currentToolTip->deleteLater();
     m_currentToolTip = 0;
+    m_currentNavigationWidget = 0;
   }
 }
 
@@ -330,12 +424,14 @@ void ContextBrowserPlugin::showToolTip(KTextEditor::View* view, KTextEditor::Cur
     if(m_currentToolTip) {
       m_currentToolTip->deleteLater();
       m_currentToolTip = 0;
+      m_currentNavigationWidget = 0;
     }
     
     KDevelop::NavigationToolTip* tooltip = new KDevelop::NavigationToolTip(view, view->mapToGlobal(view->cursorToCoordinate(position)) + QPoint(20, 40), navigationWidget);
     tooltip->resize( navigationWidget->sizeHint() + QSize(10, 10) );
     kDebug() << "tooltip size" << tooltip->size();
     m_currentToolTip = tooltip;
+    m_currentNavigationWidget = navigationWidget;
     ActiveToolTip::showToolTip(tooltip);
 
     //First disconnect to prevent multiple connections
@@ -529,9 +625,7 @@ void ContextBrowserPlugin::updateForView(View* view)
       //Only update the history if this context is around the text cursor
       if(core()->documentController()->activeDocument() && highlightPosition == SimpleCursor(view->cursorPosition()) && view->document() == core()->documentController()->activeDocument()->textDocument())
       {
-        foreach(ContextBrowserView* contextView, m_views)
-          if(masterWidget(contextView) == masterWidget(view))
-            contextView->updateHistory(ctx, highlightPosition);
+        updateHistory(ctx, highlightPosition);
       }
       
       Declaration* foundDeclaration = findDeclaration(view, highlightPosition, mouseHighlight);
@@ -868,18 +962,340 @@ void ContextBrowserPlugin::unRegisterToolView(ContextBrowserView* view)
   m_views.removeAll(view);
 }
 
-QWidget* ContextBrowserPlugin::toolbarWidgetForMainWindow(QWidget* widgetInWindow)
+// history browsing
+
+QWidget* ContextBrowserPlugin::toolbarWidgetForMainWindow( Sublime::MainWindow* window )
 {
-  QWidget* master = masterWidget(widgetInWindow);
-  
-  for(QList< QPointer< QWidget > >::const_iterator it = m_toolbarWidgets.constBegin(); it != m_toolbarWidgets.constEnd(); ++it) {
-    if((*it) && masterWidget(*it) == master) {
-      return *it;
+  //TODO: support multiple windows (if that ever gets revived)
+  if (!m_toolbarWidget) {
+    m_toolbarWidget = new QWidget(window);
+  }
+  return m_toolbarWidget;
+}
+
+void ContextBrowserPlugin::documentJumpPerformed( KDevelop::IDocument* newDocument,
+                                            const KTextEditor::Cursor& newCursor,
+                                            KDevelop::IDocument* previousDocument,
+                                            const KTextEditor::Cursor& previousCursor) {
+        
+    DUChainReadLocker lock(DUChain::lock());
+
+    /*TODO: support multiple windows if that ever gets revived
+    if(newDocument && newDocument->textDocument() && newDocument->textDocument()->activeView() && masterWidget(newDocument->textDocument()->activeView()) != masterWidget(this))
+        return;
+    */
+
+    if(previousDocument && previousCursor.isValid()) {
+        kDebug() << "updating jump source";
+        DUContext* context = getContextAt(previousDocument->url(), previousCursor);
+        if(context) {
+            updateHistory(context, SimpleCursor(previousCursor), true);
+        }else{
+            //We just want this place in the history
+            m_history.resize(m_nextHistoryIndex); // discard forward history
+            m_history.append(HistoryEntry(DocumentCursor(IndexedString(previousDocument->url()), SimpleCursor(previousCursor))));
+            ++m_nextHistoryIndex;
+        }
+    }
+    kDebug() << "new doc: " << newDocument << " new cursor: " << newCursor;
+    if(newDocument && newCursor.isValid()) {
+        kDebug() << "updating jump target";
+        DUContext* context = getContextAt(newDocument->url(), newCursor);
+        if(context) {
+            updateHistory(context, SimpleCursor(newCursor), true);
+        }else{
+            //We just want this place in the history
+            m_history.resize(m_nextHistoryIndex); // discard forward history
+            m_history.append(HistoryEntry(DocumentCursor(IndexedString(newDocument->url()), SimpleCursor(newCursor))));
+            ++m_nextHistoryIndex;
+            m_outlineLine->clear();
+        }
+    }
+}
+
+void ContextBrowserPlugin::updateButtonState()
+{
+    m_nextButton->setEnabled( m_nextHistoryIndex < m_history.size() );
+    m_previousButton->setEnabled( m_nextHistoryIndex >= 2 );
+}
+
+void ContextBrowserPlugin::historyNext() {
+    if(m_nextHistoryIndex >= m_history.size()) {
+        return;
+    }
+    openDocument(m_nextHistoryIndex); // opening the document at given position 
+                                      // will update the widget for us
+    ++m_nextHistoryIndex;
+    updateButtonState();
+}
+
+void ContextBrowserPlugin::openDocument(int historyIndex) {
+    Q_ASSERT_X(historyIndex >= 0, "openDocument", "negative history index");
+    Q_ASSERT_X(historyIndex < m_history.size(), "openDocument", "history index out of range");
+    DocumentCursor c = m_history[historyIndex].computePosition();
+    if (c.isValid() && !c.document.str().isEmpty()) {
+        
+        disconnect(ICore::self()->documentController(), SIGNAL(documentJumpPerformed(KDevelop::IDocument*, KTextEditor::Cursor, KDevelop::IDocument*, KTextEditor::Cursor)), this,      SLOT(documentJumpPerformed(KDevelop::IDocument*, KTextEditor::Cursor, KDevelop::IDocument*, KTextEditor::Cursor)));
+        
+        ICore::self()->documentController()->openDocument(c.document.toUrl(), c.textCursor());
+        
+        connect(ICore::self()->documentController(), SIGNAL(documentJumpPerformed(KDevelop::IDocument*, KTextEditor::Cursor, KDevelop::IDocument*, KTextEditor::Cursor)), this, SLOT(documentJumpPerformed(KDevelop::IDocument*, KTextEditor::Cursor, KDevelop::IDocument*, KTextEditor::Cursor)));
+
+        KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() );
+        updateDeclarationListBox(m_history[historyIndex].context.data());
     }
+}
+
+void ContextBrowserPlugin::historyPrevious() {
+    if(m_nextHistoryIndex < 2) {
+        return;
+    }
+    --m_nextHistoryIndex;
+    openDocument(m_nextHistoryIndex-1); // opening the document at given position 
+                                        // will update the widget for us
+    updateButtonState();
+}
+
+QString ContextBrowserPlugin::actionTextFor(int historyIndex) const
+{
+    const HistoryEntry& entry = m_history.at(historyIndex);
+    QString actionText = entry.context.data() ? entry.context.data()->scopeIdentifier(true).toString() : QString();
+    if(actionText.isEmpty())
+        actionText = entry.alternativeString;
+    if(actionText.isEmpty())
+        actionText = "<unnamed>";
+    actionText += " @ ";
+    QString fileName = entry.absoluteCursorPosition.document.toUrl().fileName();
+    actionText += QString("%1:%2").arg(fileName).arg(entry.absoluteCursorPosition.line+1);
+    return actionText;
+}
+
+/*
+inline QDebug operator<<(QDebug debug, const ContextBrowserPlugin::HistoryEntry &he)
+{
+    DocumentCursor c = he.computePosition();
+    debug << "\n\tHistoryEntry " << c.line << " " << c.document.str();
+    return debug;
+}
+*/
+
+void ContextBrowserPlugin::nextMenuAboutToShow() {
+    QList<int> indices;
+    for(int a = m_nextHistoryIndex; a < m_history.size(); ++a) {
+        indices << a;
+    }
+    fillHistoryPopup(m_nextMenu, indices);
+}
+
+void ContextBrowserPlugin::previousMenuAboutToShow() {
+    QList<int> indices;
+    for(int a = m_nextHistoryIndex-2; a >= 0; --a) {
+        indices << a;
+    }
+    fillHistoryPopup(m_previousMenu, indices);
+}
+
+void ContextBrowserPlugin::fillHistoryPopup(QMenu* menu, const QList<int>& historyIndices) {
+    menu->clear();
+    KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() );
+    foreach(int index, historyIndices) {
+        QAction* action = new QAction(actionTextFor(index), menu);
+        action->setData(index);
+        menu->addAction(action);
+        connect(action, SIGNAL(triggered(bool)), this, SLOT(actionTriggered()));
+    }
+}
+
+bool ContextBrowserPlugin::isPreviousEntry(KDevelop::DUContext* context,
+                                           const KDevelop::SimpleCursor& /*position*/) const
+{
+    if (m_nextHistoryIndex == 0) return false;
+    Q_ASSERT(m_nextHistoryIndex <= m_history.count());
+    const HistoryEntry& he = m_history.at(m_nextHistoryIndex-1);
+    KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() ); // is this necessary??
+    Q_ASSERT(context);
+    return IndexedDUContext(context) == he.context;
+}
+
+void ContextBrowserPlugin::updateHistory(KDevelop::DUContext* context, const KDevelop::SimpleCursor& position, bool force)
+{
+    kDebug() << "updating history";
+    
+    if(m_outlineLine->isVisible())
+        updateDeclarationListBox(context);
+    
+    if(!context && !context->owner() && !force) {
+        return; //Only add history-entries for contexts that have owners, which in practice should be functions and classes
+                //This keeps the history cleaner
+    }
+
+    if (isPreviousEntry(context, position)) {
+        if(m_nextHistoryIndex) {
+            HistoryEntry& he = m_history[m_nextHistoryIndex-1];
+            he.setCursorPosition(position);
+        }
+        return;
+    } else { // Append new history entry
+        m_history.resize(m_nextHistoryIndex); // discard forward history
+        m_history.append(HistoryEntry(IndexedDUContext(context), position));
+        ++m_nextHistoryIndex;
+
+        updateButtonState();
+        if(m_history.size() > (maxHistoryLength + 5)) {
+            m_history = m_history.mid(m_history.size() - maxHistoryLength);
+            m_nextHistoryIndex = m_history.size();
+        }
+    }
+}
+
+void ContextBrowserPlugin::setAllowBrowsing(bool allow) {
+    m_browseButton->setChecked(allow);
+}
+
+void ContextBrowserPlugin::updateDeclarationListBox(DUContext* context) {
+    if(!context || !context->owner()) {
+        kDebug() << "not updating box";
+        m_listUrl = IndexedString(); ///@todo Compute the context in the document here
+        m_outlineLine->clear();
+        return;
+    }
+    
+    Declaration* decl = context->owner();
+    
+    m_listUrl = context->url();
+
+    Declaration* specialDecl = SpecializationStore::self().applySpecialization(decl, decl->topContext());
+
+    FunctionType::Ptr function = specialDecl->type<FunctionType>();
+    QString text = specialDecl->qualifiedIdentifier().toString();
+    if(function)
+        text += function->partToString(KDevelop::FunctionType::SignatureArguments);
+    
+    if(!m_outlineLine->hasFocus())
+    {
+        m_outlineLine->setText(text);
+        m_outlineLine->setCursorPosition(0); 
+    } 
+    
+    kDebug() << "updated" << text;
+}
+
+void ContextBrowserPlugin::actionTriggered() {
+    QAction* action = qobject_cast<QAction*>(sender());
+    Q_ASSERT(action); Q_ASSERT(action->data().type() == QVariant::Int);
+    int historyPosition = action->data().toInt();
+    // kDebug() << "history pos" << historyPosition << m_history.size() << m_history;
+    if(historyPosition >= 0 && historyPosition < m_history.size()) {
+        m_nextHistoryIndex = historyPosition + 1;
+        openDocument(historyPosition);
+        updateButtonState();
+    }
+}
+
+void ContextBrowserPlugin::doNavigate(NavigationActionType action)
+{
+  ///TODO: is this *really* required?
+  KTextEditor::View* view = qobject_cast<KTextEditor::View*>(sender());
+  if(!view) {
+      kWarning() << "sender is not a view";
+      return;
   }
-  m_toolbarWidgets.append(new QWidget(master));
-  m_toolbarWidgets.back()->setHidden(true);
-  return m_toolbarWidgets.back();
+  KTextEditor::CodeCompletionInterface* iface = qobject_cast<KTextEditor::CodeCompletionInterface*>(view);
+  if(!iface || iface->isCompletionActive())
+      return;
+  ///
+
+  QList<QWidget*> widgets;
+  widgets << m_currentNavigationWidget.data();
+  foreach(ContextBrowserView* view, m_views) {
+    widgets << view->navigationWidget();
+  }
+
+  foreach(QWidget* w, widgets) {
+    AbstractNavigationWidget* widget = qobject_cast<AbstractNavigationWidget*>(w);
+    if (!widget)
+      continue;
+
+    switch(action) {
+      case Accept:
+        widget->accept();
+        break;
+      case Back:
+        widget->back();
+        break;
+      case Left:
+        widget->previous();
+        break;
+      case Right:
+        widget->next();
+        break;
+      case Up:
+        widget->up();
+        break;
+      case Down:
+        widget->down();
+        break;
+    }
+  }
+}
+
+void ContextBrowserPlugin::navigateAccept() {
+  doNavigate(Accept);
+}
+
+void ContextBrowserPlugin::navigateBack() {
+  doNavigate(Back);
+}
+
+void ContextBrowserPlugin::navigateDown() {
+  doNavigate(Down);
+}
+
+void ContextBrowserPlugin::navigateLeft() {
+  doNavigate(Left);
+}
+
+void ContextBrowserPlugin::navigateRight() {
+  doNavigate(Right);
+}
+
+void ContextBrowserPlugin::navigateUp() {
+  doNavigate(Up);
+}
+
+
+//BEGIN HistoryEntry
+ContextBrowserPlugin::HistoryEntry::HistoryEntry(KDevelop::DocumentCursor pos) : absoluteCursorPosition(pos) {
+}
+
+ContextBrowserPlugin::HistoryEntry::HistoryEntry(IndexedDUContext ctx, const KDevelop::SimpleCursor& cursorPosition) : context(ctx) {
+        //Use a position relative to the context
+        setCursorPosition(cursorPosition);
+        if(ctx.data())
+            alternativeString = ctx.data()->scopeIdentifier(true).toString();
+        if(!alternativeString.isEmpty())
+            alternativeString += i18n("(changed)"); //This is used when the context was deleted in between
+}
+
+DocumentCursor ContextBrowserPlugin::HistoryEntry::computePosition() const {
+    KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() );
+    DocumentCursor ret;
+    if(context.data()) {
+        ret = DocumentCursor(context.data()->url(), relativeCursorPosition);
+        ret.line += context.data()->range().start.line;
+    }else{
+        ret = absoluteCursorPosition;
+    }
+    return ret;
+}
+
+void ContextBrowserPlugin::HistoryEntry::setCursorPosition(const KDevelop::SimpleCursor& cursorPosition) {
+    KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() );
+    if(context.data()) {
+        absoluteCursorPosition =  DocumentCursor(context.data()->url(), cursorPosition);
+        relativeCursorPosition = cursorPosition;
+        relativeCursorPosition.line -= context.data()->range().start.line;
+    }
 }
 
 #include "contextbrowser.moc"
diff --git a/plugins/contextbrowser/contextbrowser.h b/plugins/contextbrowser/contextbrowser.h
index 7b9262e..22893ce 100644
--- a/plugins/contextbrowser/contextbrowser.h
+++ b/plugins/contextbrowser/contextbrowser.h
@@ -34,6 +34,16 @@
 #include <language/duchain/declaration.h>
 #include <KUrl>
 #include <language/editor/persistentmovingrange.h>
+#include <language/interfaces/iquickopen.h>
+#include <QToolButton>
+#include <QMenu>
+#include <QHBoxLayout>
+#include <language/editor/documentcursor.h>
+#include <KTextEditor/Document>
+
+namespace Sublime {
+  class MainWindow;
+}
 
 namespace KDevelop {
   class IDocument;
@@ -48,10 +58,12 @@ namespace KTextEditor {
   class View;
 }
 
+//TODO: move into kdevelop namespace
 using namespace KDevelop;
 
 class ContextBrowserViewFactory;
 class ContextBrowserView;
+class BrowseManager;
 
 QWidget* masterWidget(QWidget* w);
 
@@ -81,8 +93,16 @@ class ContextBrowserPlugin : public KDevelop::IPlugin
     
     virtual KDevelop::ContextMenuExtension contextMenuExtension(KDevelop::Context*);
 
-    QWidget* toolbarWidgetForMainWindow(QWidget* widgetInWindow);
-    
+    virtual KXMLGUIClient* createGUIForMainWindow( Sublime::MainWindow* window );
+
+    ///duchain must be locked
+    ///@param force When this is true, the history-entry is added, no matter whether the context is "interesting" or not
+    void updateHistory(KDevelop::DUContext* context, const KDevelop::SimpleCursor& cursorPosition,
+                       bool force = false);
+
+    void updateDeclarationListBox(KDevelop::DUContext* context);
+    void setAllowBrowsing(bool allow);
+
   public Q_SLOTS:
     void previousContextShortcut();
     void nextContextShortcut();
@@ -110,10 +130,31 @@ class ContextBrowserPlugin : public KDevelop::IPlugin
     
     void textInserted(KTextEditor::Document*, KTextEditor::Range);
     void selectionChanged(KTextEditor::View*);
-    
+
+  private slots:
+    // history browsing
+    void documentJumpPerformed( KDevelop::IDocument* newDocument,
+                                const KTextEditor::Cursor& newCursor,
+                                KDevelop::IDocument* previousDocument,
+                                const KTextEditor::Cursor& previousCursor);
+
+    void historyNext();
+    void historyPrevious();
+    void nextMenuAboutToShow();
+    void previousMenuAboutToShow();
+    void actionTriggered();
+
+    void navigateLeft();
+    void navigateRight();
+    void navigateUp();
+    void navigateDown();
+    void navigateAccept();
+    void navigateBack();
+
   private:
-    
-    virtual void createActionsForMainWindow(Sublime::MainWindow* /*window*/, QString& xmlFile, KActionCollection& actions);
+    QWidget* toolbarWidgetForMainWindow(Sublime::MainWindow* window);
+    virtual void createActionsForMainWindow(Sublime::MainWindow* window, QString& xmlFile,
+                                            KActionCollection& actions);
     void switchUse(bool forward);
     void clearMouseHover();
 
@@ -125,8 +166,24 @@ class ContextBrowserPlugin : public KDevelop::IPlugin
     KDevelop::Declaration* findDeclaration(KTextEditor::View* view, const KDevelop::SimpleCursor&, bool mouseHighlight);
     void updateForView(KTextEditor::View* view);
 
+    // history browsing
+    bool isPreviousEntry(KDevelop::DUContext*, const KDevelop::SimpleCursor& cursor) const;
+    QString actionTextFor(int historyIndex) const;
+    void updateButtonState();
+    void openDocument(int historyIndex);
+    void fillHistoryPopup(QMenu* menu, const QList<int>& historyIndices);
+
+    enum NavigationActionType {
+      Accept,
+      Back,
+      Down,
+      Up,
+      Left,
+      Right
+    };
+    void doNavigate(NavigationActionType action);
+
   private:
-    
     ContextBrowserView* browserViewForTextView(KTextEditor::View* view);
     
     void showToolTip(KTextEditor::View* view, KTextEditor::Cursor position);
@@ -147,12 +204,46 @@ class ContextBrowserPlugin : public KDevelop::IPlugin
     SimpleCursor m_mouseHoverCursor;
     ContextBrowserViewFactory* m_viewFactory;
     QPointer<QWidget> m_currentToolTip;
+    QPointer<QWidget> m_currentNavigationWidget;
     IndexedDeclaration m_currentToolTipDeclaration;
     QAction* m_findUses;
     
     QPointer<KTextEditor::Document> m_lastInsertionDocument;
     KTextEditor::Cursor m_lastInsertionPos;
-    QList<QPointer<QWidget> > m_toolbarWidgets;
+
+    // outline toolbar
+    QPointer<KDevelop::IQuickOpenLine> m_outlineLine;
+    QPointer<QHBoxLayout> m_toolbarWidgetLayout;
+    QPointer<QWidget> m_toolbarWidget;
+
+    // history browsing
+    struct HistoryEntry {
+        //Duchain must be locked
+        HistoryEntry(KDevelop::IndexedDUContext ctx = KDevelop::IndexedDUContext(), const KDevelop::SimpleCursor& cursorPosition = KDevelop::SimpleCursor());
+        HistoryEntry(KDevelop::DocumentCursor pos);
+        //Duchain must be locked
+        void setCursorPosition(const KDevelop::SimpleCursor& cursorPosition);
+
+        //Duchain does not need to be locked
+        KDevelop::DocumentCursor computePosition() const;
+
+        KDevelop::IndexedDUContext context;
+        KDevelop::DocumentCursor absoluteCursorPosition;
+        KDevelop::SimpleCursor relativeCursorPosition; //Cursor position relative to the start line of the context
+        QString alternativeString;
+    };
+
+    QVector<HistoryEntry> m_history;
+    QPointer<QToolButton> m_previousButton;
+    QPointer<QToolButton> m_nextButton;
+    QPointer<QMenu> m_previousMenu, m_nextMenu;
+    QPointer<QToolButton> m_browseButton;
+    QList<KDevelop::IndexedDeclaration> m_listDeclarations;
+    KDevelop::IndexedString m_listUrl;
+    BrowseManager* m_browseManager;
+    //Used to not record jumps triggered by the context-browser as history entries
+    QPointer<QWidget> m_focusBackWidget;
+    int m_nextHistoryIndex;
 };
 
 #endif // CONTEXTBROWSERPLUGIN_H
diff --git a/plugins/contextbrowser/contextbrowserview.cpp b/plugins/contextbrowser/contextbrowserview.cpp
index 0c04384..2e4f2d8 100644
--- a/plugins/contextbrowser/contextbrowserview.cpp
+++ b/plugins/contextbrowser/contextbrowserview.cpp
@@ -20,6 +20,8 @@
  */
 
 #include "contextbrowserview.h"
+
+///TODO: cleanup includes
 #include <QVBoxLayout>
 #include <QHBoxLayout>
 #include <QLabel>
@@ -56,341 +58,9 @@
 #include <language/duchain/navigation/abstractdeclarationnavigationcontext.h>
 #include <interfaces/contextmenuextension.h>
 #include <interfaces/iplugincontroller.h>
-#include <ktexteditor/codecompletioninterface.h>
-#include <language/interfaces/iquickopen.h>
-
-const int maxHistoryLength = 30;
 
 using namespace KDevelop;
 
-DUContext* contextAt(const CursorInRevision& position, TopDUContext* topContext)
-{
-    DUContext* ctx = topContext->findContextAt(position);
-    while(ctx && (ctx->type() == DUContext::Template || ctx->type() == DUContext::Helper || ctx->localScopeIdentifier().isEmpty()) && ctx->parentContext())
-    ctx = ctx->parentContext();
-    return ctx;
-}
-    
-///Duchain must be locked
-DUContext* getContextAt(KUrl url, KTextEditor::Cursor cursor) {
-    TopDUContext* topContext = DUChainUtils::standardContextForUrl(url);
-    if (!topContext) return 0;
-    return contextAt(topContext->transformToLocalRevision(SimpleCursor(cursor)), topContext);
-}
-
-static bool useNavigationFromView(QObject* viewObject) {
-    KTextEditor::View* view = qobject_cast<KTextEditor::View*>(viewObject);
-    if(!view) {
-        kWarning() << "sender is not a view";
-        return false;
-    }
-    KTextEditor::CodeCompletionInterface* iface = dynamic_cast<KTextEditor::CodeCompletionInterface*>(view);
-    if(!iface || iface->isCompletionActive())
-        return false;
-    
-    return true;
-}
-
-void ContextBrowserView::navigateAccept() {
-    if(!useNavigationFromView(sender()))
-        return;
-    
-    if(AbstractNavigationWidget* widget = dynamic_cast<AbstractNavigationWidget*>(m_navigationWidget.data()))
-        widget->accept();
-}
-
-void ContextBrowserView::navigateBack() {
-    if(!useNavigationFromView(sender()))
-        return;
-    
-    if(AbstractNavigationWidget* widget = dynamic_cast<AbstractNavigationWidget*>(m_navigationWidget.data()))
-        widget->back();
-}
-
-void ContextBrowserView::navigateDown() {
-    if(!useNavigationFromView(sender()))
-        return;
-    
-    if(AbstractNavigationWidget* widget = dynamic_cast<AbstractNavigationWidget*>(m_navigationWidget.data()))
-        widget->down();
-}
-
-void ContextBrowserView::navigateLeft() {
-    if(!useNavigationFromView(sender()))
-        return;
-    
-    if(AbstractNavigationWidget* widget = dynamic_cast<AbstractNavigationWidget*>(m_navigationWidget.data()))
-        widget->previous();
-}
-
-void ContextBrowserView::navigateRight() {
-    if(!useNavigationFromView(sender()))
-        return;
-    
-    if(AbstractNavigationWidget* widget = dynamic_cast<AbstractNavigationWidget*>(m_navigationWidget.data()))
-        widget->next();
-}
-
-void ContextBrowserView::navigateUp() {
-    if(!useNavigationFromView(sender()))
-        return;
-    
-    if(AbstractNavigationWidget* widget = dynamic_cast<AbstractNavigationWidget*>(m_navigationWidget.data()))
-        widget->up();
-}
-
-void ContextBrowserView::documentJumpPerformed( KDevelop::IDocument* newDocument, KTextEditor::Cursor newCursor, KDevelop::IDocument* previousDocument, KTextEditor::Cursor previousCursor) {
-        
-    DUChainReadLocker lock(DUChain::lock());
-    
-    if(newDocument && newDocument->textDocument() && newDocument->textDocument()->activeView() && masterWidget(newDocument->textDocument()->activeView()) != masterWidget(this))
-        return;
-    
-    if(previousDocument && previousCursor.isValid()) {
-        kDebug() << "updating jump source";
-        DUContext* context = getContextAt(previousDocument->url(), previousCursor);
-        if(context) {
-            updateHistory(context, SimpleCursor(previousCursor), true);
-        }else{
-            //We just want this place in the history
-            m_history.resize(m_nextHistoryIndex); // discard forward history
-            m_history.append(HistoryEntry(DocumentCursor(IndexedString(previousDocument->url()), SimpleCursor(previousCursor))));
-            ++m_nextHistoryIndex;
-        }
-    }
-    kDebug() << "new doc: " << newDocument << " new cursor: " << newCursor;
-    if(newDocument && newCursor.isValid()) {
-        kDebug() << "updating jump target";
-        DUContext* context = getContextAt(newDocument->url(), newCursor);
-        if(context) {
-            updateHistory(context, SimpleCursor(newCursor), true);
-        }else{
-            //We just want this place in the history
-            m_history.resize(m_nextHistoryIndex); // discard forward history
-            m_history.append(HistoryEntry(DocumentCursor(IndexedString(newDocument->url()), SimpleCursor(newCursor))));
-            ++m_nextHistoryIndex;
-            m_outlineLine->clear();
-        }
-    }
-}
-
-void ContextBrowserView::updateButtonState()
-{
-    m_nextButton->setEnabled( m_nextHistoryIndex < m_history.size() );
-    m_previousButton->setEnabled( m_nextHistoryIndex >= 2 );
-}
-
-void ContextBrowserView::historyNext() {
-    if(m_nextHistoryIndex >= m_history.size()) {
-        return;
-    }
-    allowLockedUpdate();
-    openDocument(m_nextHistoryIndex); // opening the document at given position 
-                                      // will update the widget for us
-    ++m_nextHistoryIndex;
-    updateButtonState();
-}
-
-void ContextBrowserView::openDocument(int historyIndex) {
-    Q_ASSERT_X(historyIndex >= 0, "openDocument", "negative history index");
-    Q_ASSERT_X(historyIndex < m_history.size(), "openDocument", "history index out of range");
-    DocumentCursor c = m_history[historyIndex].computePosition();
-    if (c.isValid() && !c.document.str().isEmpty()) {
-        
-        disconnect(ICore::self()->documentController(), SIGNAL(documentJumpPerformed(KDevelop::IDocument*, KTextEditor::Cursor, KDevelop::IDocument*, KTextEditor::Cursor)), this,      SLOT(documentJumpPerformed(KDevelop::IDocument*, KTextEditor::Cursor, KDevelop::IDocument*, KTextEditor::Cursor)));
-        
-        ICore::self()->documentController()->openDocument(c.document.toUrl(), c.textCursor());
-        
-        connect(ICore::self()->documentController(), SIGNAL(documentJumpPerformed(KDevelop::IDocument*, KTextEditor::Cursor, KDevelop::IDocument*, KTextEditor::Cursor)), this, SLOT(documentJumpPerformed(KDevelop::IDocument*, KTextEditor::Cursor, KDevelop::IDocument*, KTextEditor::Cursor)));
-
-        KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() );
-        updateDeclarationListBox(m_history[historyIndex].context.data());
-    }
-}
-
-void ContextBrowserView::historyPrevious() {
-    if(m_nextHistoryIndex < 2) {
-        return;
-    }
-    --m_nextHistoryIndex;
-    allowLockedUpdate();
-    openDocument(m_nextHistoryIndex-1); // opening the document at given position 
-                                        // will update the widget for us
-    updateButtonState();
-}
-
-QString ContextBrowserView::actionTextFor(int historyIndex)
-{
-    HistoryEntry& entry = m_history[historyIndex];
-    QString actionText = entry.context.data() ? entry.context.data()->scopeIdentifier(true).toString() : QString();
-    if(actionText.isEmpty())
-        actionText = entry.alternativeString;
-    if(actionText.isEmpty())
-        actionText = "<unnamed>";
-    actionText += " @ ";
-    QString fileName = entry.absoluteCursorPosition.document.toUrl().fileName();
-    actionText += QString("%1:%2").arg(fileName).arg(entry.absoluteCursorPosition.line+1);
-    return actionText;
-}
-
-inline QDebug operator<<(QDebug debug, const ContextBrowserView::HistoryEntry &he)
-{
-    DocumentCursor c = he.computePosition();
-    debug << "\n\tHistoryEntry " << c.line << " " << c.document.str();
-    return debug;
-}
-
-void ContextBrowserView::nextMenuAboutToShow() {
-    QList<int> indices;
-    for(int a = m_nextHistoryIndex; a < m_history.size(); ++a) {
-        indices << a;
-    }
-    fillHistoryPopup(m_nextMenu, indices);
-}
-
-void ContextBrowserView::previousMenuAboutToShow() {
-    QList<int> indices;
-    for(int a = m_nextHistoryIndex-2; a >= 0; --a) {
-        indices << a;
-    }
-    fillHistoryPopup(m_previousMenu, indices);
-}
-
-void ContextBrowserView::fillHistoryPopup(QMenu* menu, const QList<int>& historyIndices) {
-    menu->clear();
-    KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() );
-    foreach(int index, historyIndices) {
-        QAction* action = new QAction(actionTextFor(index), menu);
-        action->setData(index);
-        menu->addAction(action);
-        connect(action, SIGNAL(triggered(bool)), this, SLOT(actionTriggered()));
-    }
-}
-
-void ContextBrowserView::switchFocusToContextBrowser() {
-    if(isVisible()) {
-        kDebug() << "switching focus to context-browser";
-        if(QApplication::focusWidget() != this)
-            m_focusBackWidget = QApplication::focusWidget();
-        setFocus();
-    }
-}
-
-void ContextBrowserView::actionTriggered() {
-    QAction* action = qobject_cast<QAction*>(sender());
-    Q_ASSERT(action); Q_ASSERT(action->data().type() == QVariant::Int);
-    int historyPosition = action->data().toInt();
-    // kDebug() << "history pos" << historyPosition << m_history.size() << m_history;
-    if(historyPosition >= 0 && historyPosition < m_history.size()) {
-        m_nextHistoryIndex = historyPosition + 1;
-        allowLockedUpdate(); // opening the document at given position 
-                                     // will update the widget for us
-        openDocument(historyPosition);
-        updateButtonState();
-    }
-}
-
-ContextBrowserView::HistoryEntry::HistoryEntry(KDevelop::DocumentCursor pos) : absoluteCursorPosition(pos) {
-}
-
-ContextBrowserView::HistoryEntry::HistoryEntry(IndexedDUContext ctx, const KDevelop::SimpleCursor& cursorPosition) : context(ctx) {
-        //Use a position relative to the context
-        setCursorPosition(cursorPosition);
-        if(ctx.data())
-            alternativeString = ctx.data()->scopeIdentifier(true).toString();
-        if(!alternativeString.isEmpty())
-            alternativeString += i18n("(changed)"); //This is used when the context was deleted in between
-}
-
-DocumentCursor ContextBrowserView::HistoryEntry::computePosition() const {
-    KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() );
-    DocumentCursor ret;
-    if(context.data()) {
-        ret = DocumentCursor(context.data()->url(), relativeCursorPosition);
-        ret.line += context.data()->range().start.line;
-    }else{
-        ret = absoluteCursorPosition;
-    }
-    return ret;
-}
-
-void ContextBrowserView::HistoryEntry::setCursorPosition(const KDevelop::SimpleCursor& cursorPosition) {
-    KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() );
-    if(context.data()) {
-        absoluteCursorPosition =  DocumentCursor(context.data()->url(), cursorPosition);
-        relativeCursorPosition = cursorPosition;
-        relativeCursorPosition.line -= context.data()->range().start.line;
-    }
-}
-
-bool ContextBrowserView::isPreviousEntry(KDevelop::DUContext* context, const KDevelop::SimpleCursor& /*position*/) {
-    if (m_nextHistoryIndex == 0) return false;
-    Q_ASSERT(m_nextHistoryIndex <= m_history.count());
-    HistoryEntry& he = m_history[m_nextHistoryIndex-1];
-    KDevelop::DUChainReadLocker lock( KDevelop::DUChain::lock() ); // is this necessary??
-    Q_ASSERT(context);
-    return IndexedDUContext(context) == he.context;
-}
-
-void ContextBrowserView::updateDeclarationListBox(DUContext* context) {
-    if(!context || !context->owner()) {
-        kDebug() << "not updating box";
-        m_listUrl = IndexedString(); ///@todo Compute the context in the document here
-        m_outlineLine->clear();
-        return;
-    }
-    
-    Declaration* decl = context->owner();
-    
-    m_listUrl = context->url();
-
-    Declaration* specialDecl = SpecializationStore::self().applySpecialization(decl, decl->topContext());
-
-    FunctionType::Ptr function = specialDecl->type<FunctionType>();
-    QString text = specialDecl->qualifiedIdentifier().toString();
-    if(function)
-        text += function->partToString(KDevelop::FunctionType::SignatureArguments);
-    
-    if(!m_outlineLine->hasFocus())
-    {
-        m_outlineLine->setText(text);
-        m_outlineLine->setCursorPosition(0); 
-    } 
-    
-    kDebug() << "updated" << text;
-}
-
-void ContextBrowserView::updateHistory(KDevelop::DUContext* context, const KDevelop::SimpleCursor& position, bool force)
-{
-    kDebug() << "updating history";
-    
-    if(m_outlineLine->isVisible())
-        updateDeclarationListBox(context);
-    
-    if(!context && !context->owner() && !force) {
-        return; //Only add history-entries for contexts that have owners, which in practice should be functions and classes
-                //This keeps the history cleaner
-    }
-
-    if (isPreviousEntry(context, position)) {
-        if(m_nextHistoryIndex) {
-            HistoryEntry& he = m_history[m_nextHistoryIndex-1];
-            he.setCursorPosition(position);
-        }
-        return;
-    } else { // Append new history entry
-        m_history.resize(m_nextHistoryIndex); // discard forward history
-        m_history.append(HistoryEntry(IndexedDUContext(context), position));
-        ++m_nextHistoryIndex;
-
-        updateButtonState();
-        if(m_history.size() > (maxHistoryLength + 5)) {
-            m_history = m_history.mid(m_history.size() - maxHistoryLength);
-            m_nextHistoryIndex = m_history.size();
-        }
-    }
-}
-
 QWidget* ContextBrowserView::createWidget(KDevelop::DUContext* context) {
         m_context = IndexedDUContext(context);
         if(m_context.data()) {
@@ -439,91 +109,24 @@ void ContextBrowserView::updateLockIcon(bool checked) {
     m_lockButton->setIcon(KIcon(checked ? "document-encrypt" : "document-decrypt"));
 }
 
-ContextBrowserView::ContextBrowserView( ContextBrowserPlugin* plugin, QWidget* parent ) : QWidget(parent), m_plugin(plugin), m_navigationWidget(new KTextBrowser()), m_nextHistoryIndex(0), m_outlineLine(0) {
+ContextBrowserView::ContextBrowserView( ContextBrowserPlugin* plugin, QWidget* parent ) : QWidget(parent), m_plugin(plugin), m_navigationWidget(new KTextBrowser()) {
     setWindowIcon( KIcon("applications-development-web") );
 
-    m_browseManager = new BrowseManager(this);
-    
-    connect(ICore::self()->documentController(), SIGNAL(documentJumpPerformed(KDevelop::IDocument*, KTextEditor::Cursor, KDevelop::IDocument*, KTextEditor::Cursor)), this, SLOT(documentJumpPerformed(KDevelop::IDocument*, KTextEditor::Cursor, KDevelop::IDocument*, KTextEditor::Cursor)));
-    
-    connect(m_browseManager, SIGNAL(shiftKeyTriggered()), this, SLOT(switchFocusToContextBrowser()));
-    
-    m_previousButton = new QToolButton();
-    m_previousButton->setToolTip(i18n("Go back in context history"));
-    m_previousButton->setPopupMode(QToolButton::MenuButtonPopup);
-    m_previousButton->setIcon(KIcon("go-previous"));
-    m_previousButton->setEnabled(false);
-    m_previousButton->setFocusPolicy(Qt::NoFocus);
-    m_previousMenu = new QMenu();
-    m_previousButton->setMenu(m_previousMenu);
-    connect(m_previousButton, SIGNAL(clicked(bool)), this, SLOT(historyPrevious()));
-    connect(m_previousMenu, SIGNAL(aboutToShow()), this, SLOT(previousMenuAboutToShow()));
-
-    m_nextButton = new QToolButton();
-    m_nextButton->setToolTip(i18n("Go forward in context history"));
-    m_nextButton->setPopupMode(QToolButton::MenuButtonPopup);
-    m_nextButton->setIcon(KIcon("go-next"));
-    m_nextButton->setEnabled(false);
-    m_nextButton->setFocusPolicy(Qt::NoFocus);
-    m_nextMenu = new QMenu();
-    m_nextButton->setMenu(m_nextMenu);
-    connect(m_nextButton, SIGNAL(clicked(bool)), this, SLOT(historyNext()));
-    connect(m_nextMenu, SIGNAL(aboutToShow()), this, SLOT(nextMenuAboutToShow()));
-
-    m_browseButton = new QToolButton();
-    m_browseButton->setIcon(KIcon("games-hint"));
-    m_browseButton->setToolTip(i18n("Enable/disable source browse mode"));
-    m_browseButton->setWhatsThis(i18n("When this is enabled, you can browse the source-code by clicking in the editor."));
-    m_browseButton->setCheckable(true);
-    m_browseButton->setFocusPolicy(Qt::NoFocus);
-    
-    connect(m_browseButton, SIGNAL(clicked(bool)), m_browseManager, SLOT(setBrowsing(bool)));
-
-    IQuickOpen* quickOpen = KDevelop::ICore::self()->pluginController()->extensionForPlugin<IQuickOpen>("org.kdevelop.IQuickOpen");
-    
-    if(quickOpen) {
-      m_outlineLine = quickOpen->createQuickOpenLine(QStringList(), QStringList() << i18n("Outline"), IQuickOpen::Outline);
-      m_outlineLine->setDefaultText(i18n("Outline..."));
-      m_outlineLine->setToolTip(i18n("Navigate outline of active document, click to browse."));
-    }
-    
-    connect(m_browseManager, SIGNAL(startDelayedBrowsing(KTextEditor::View*)), this, SIGNAL(startDelayedBrowsing(KTextEditor::View*)));
-    connect(m_browseManager, SIGNAL(stopDelayedBrowsing()), this, SIGNAL(stopDelayedBrowsing()));
-    
     m_allowLockedUpdate = false;
-    
+
     m_buttons = new QHBoxLayout;
+    m_buttons->addStretch();
+    m_declarationMenuButton = new QToolButton();
+    m_declarationMenuButton->setIcon(KIcon("code-class"));
+    m_declarationMenuButton->setToolTip(i18n("Declaration menu"));
+    connect(m_declarationMenuButton, SIGNAL(clicked(bool)), SLOT(declarationMenu()));
+    m_buttons->addWidget(m_declarationMenuButton);
     m_lockButton = new QToolButton();
     m_lockButton->setCheckable(true);
     m_lockButton->setChecked(false);
     m_lockButton->setToolTip(i18n("Lock current view"));
     updateLockIcon(m_lockButton->isChecked());
     connect(m_lockButton, SIGNAL(toggled(bool)), SLOT(updateLockIcon(bool)));
-
-    m_declarationMenuButton = new QToolButton();
-    m_declarationMenuButton->setIcon(KIcon("code-class"));
-    m_declarationMenuButton->setToolTip(i18n("Declaration menu"));
-    connect(m_declarationMenuButton, SIGNAL(clicked(bool)), SLOT(declarationMenu()));
-    
-    m_toolbarWidget = plugin->toolbarWidgetForMainWindow(this);
-    m_toolbarWidgetLayout = new QHBoxLayout;
-    m_toolbarWidgetLayout->setSizeConstraint(QLayout::SetMaximumSize);
-    m_previousButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
-    m_nextButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
-    m_browseButton->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
-    m_toolbarWidgetLayout->setMargin(0);
-    
-    m_toolbarWidgetLayout->addWidget(m_previousButton);
-    m_toolbarWidgetLayout->addWidget(m_outlineLine);
-    m_outlineLine->setMaximumWidth(600);
-    m_toolbarWidgetLayout->addWidget(m_nextButton);
-    m_toolbarWidgetLayout->addWidget(m_browseButton);
-    
-    if(m_toolbarWidget->children().isEmpty())
-        m_toolbarWidget->setLayout(m_toolbarWidgetLayout);
-    
-    m_buttons->addStretch();
-    m_buttons->addWidget(m_declarationMenuButton);
     m_buttons->addWidget(m_lockButton);
 
     m_layout = new QVBoxLayout;
@@ -535,22 +138,10 @@ ContextBrowserView::ContextBrowserView( ContextBrowserPlugin* plugin, QWidget* p
     setLayout(m_layout);
 
     m_plugin->registerToolView(this);
-    
-    connect(ICore::self()->documentController(), SIGNAL(documentClosed(KDevelop::IDocument*)), m_outlineLine, SLOT(clear()));
-    connect(ICore::self()->documentController(), SIGNAL(documentActivated(KDevelop::IDocument*)), m_outlineLine, SLOT(clear()));
 }
 
 ContextBrowserView::~ContextBrowserView() {
     m_plugin->unRegisterToolView(this);
-    delete m_nextMenu;
-    delete m_previousMenu;
-    delete m_toolbarWidgetLayout;
-    
-    delete m_previousButton;
-    delete m_outlineLine;
-    delete m_nextButton;
-    delete m_browseButton;
-    
 }
 
 void ContextBrowserView::focusInEvent(QFocusEvent* event) {
@@ -607,13 +198,16 @@ void ContextBrowserView::showEvent(QShowEvent* event) {
             Declaration* decl = m_navigationWidgetDeclaration.getDeclaration(top);
             setDeclaration(decl, top, true);
             //Update the declaration combo-box
+            /*
+            TODO: bring this back if required
             DUContext* context = 0;
             KDevelop::IDocument* doc = ICore::self()->documentController()->activeDocument();
             if(doc && doc->textDocument() && doc->textDocument()->activeView()) {
                 KTextEditor::Cursor c = doc->textDocument()->activeView()->cursorPosition();
                 context = getContextAt(top->url().toUrl(), c);
             }
-            updateDeclarationListBox(context);
+            m_plugin->updateDeclarationListBox(context);
+            */
         }
     }
     QWidget::showEvent(event);
@@ -699,9 +293,4 @@ void ContextBrowserView::setSpecialNavigationWidget(QWidget* widget) {
     }
 }
 
-void ContextBrowserView::setAllowBrowsing(bool allow) {
-    m_browseButton->setChecked(allow);
-}
-
-
 #include "contextbrowserview.moc"
diff --git a/plugins/contextbrowser/contextbrowserview.h b/plugins/contextbrowser/contextbrowserview.h
index bf9a6d9..8f00e61 100644
--- a/plugins/contextbrowser/contextbrowserview.h
+++ b/plugins/contextbrowser/contextbrowserview.h
@@ -24,12 +24,12 @@
 
 #include <QWidget>
 #include <QVector>
+#include <QPointer>
+
 #include <language/duchain/topducontext.h>
 #include <language/editor/simplecursor.h>
 #include <language/editor/documentcursor.h>
-#include "browsemanager.h"
 #include <language/duchain/indexedstring.h>
-#include <language/interfaces/iquickopen.h>
 
 class ContextBrowserPlugin;
 class QVBoxLayout;
@@ -38,7 +38,6 @@ class QToolButton;
 class QCheckBox;
 class QMenu;
 class KComboBox;
-class BrowseManager;
 
 namespace KDevelop {
 class IDocument;
@@ -69,65 +68,17 @@ class ContextBrowserView : public QWidget {
             return m_navigationWidget;
         }
         
-        QWidget* toolbarWidget() {
-            return m_toolbarWidget;
-        }
-        
-        ///duchain must be locked
-        ///@param force When this is true, the history-entry is added, no matter whether the context is "interesting" or not
-        void updateHistory(KDevelop::DUContext* context, const
-        KDevelop::SimpleCursor& cursorPosition, bool force = false);
+        //duchain must be locked
         QWidget* createWidget(KDevelop::DUContext* context);
         
         //duchain must be locked
         QWidget* createWidget(KDevelop::Declaration* decl, KDevelop::TopDUContext* topContext);
 
         KDevelop::IndexedDeclaration declaration() const;
-        
-        struct HistoryEntry {
-            //Duchain must be locked
-            HistoryEntry(KDevelop::IndexedDUContext ctx = KDevelop::IndexedDUContext(), const KDevelop::SimpleCursor& cursorPosition = KDevelop::SimpleCursor());
-            HistoryEntry(KDevelop::DocumentCursor pos);
-            //Duchain must be locked
-            void setCursorPosition(const KDevelop::SimpleCursor& cursorPosition);
-
-            //Duchain does not need to be locked
-            KDevelop::DocumentCursor computePosition() const;
-
-            KDevelop::IndexedDUContext context;
-            KDevelop::DocumentCursor absoluteCursorPosition;
-            KDevelop::SimpleCursor relativeCursorPosition; //Cursor position relative to the start line of the context
-            QString alternativeString;
-        };
-
-        void updateDeclarationListBox(KDevelop::DUContext* context);
-        
-        void setAllowBrowsing(bool allow) ;
-        
-    Q_SIGNALS:
-        void startDelayedBrowsing(KTextEditor::View*);
-        void stopDelayedBrowsing();
-        
-    public Q_SLOTS:
-        void navigateLeft();
-        void navigateRight();
-        void navigateUp();
-        void navigateDown();
-        void navigateAccept();
-        void navigateBack();
-
-        void historyNext();
-        void historyPrevious();
-        void nextMenuAboutToShow();
-        void previousMenuAboutToShow();
-        void actionTriggered();
-        void switchFocusToContextBrowser();
-        
+
     private Q_SLOTS:
         void updateLockIcon(bool); 
         void declarationMenu();
-        void documentJumpPerformed( KDevelop::IDocument* newDocument, KTextEditor::Cursor newCursor, KDevelop::IDocument* previousDocument, KTextEditor::Cursor previousCursor);
-        
 
     private:
         virtual void showEvent(QShowEvent* event);
@@ -137,12 +88,6 @@ class ContextBrowserView : public QWidget {
         virtual void focusOutEvent(QFocusEvent* event);
         bool isLocked() const;
         void resetWidget();
-        
-        bool isPreviousEntry(KDevelop::DUContext*, const KDevelop::SimpleCursor& cursor);
-        QString actionTextFor(int historyIndex);
-        void updateButtonState();
-        void openDocument(int historyIndex);
-        void fillHistoryPopup(QMenu* menu, const QList<int>& historyIndices);
 
     private:
         
@@ -152,30 +97,14 @@ class ContextBrowserView : public QWidget {
         QVBoxLayout* m_layout;
         QToolButton* m_lockButton;
         QToolButton* m_declarationMenuButton;
-        
         QHBoxLayout* m_buttons;
+
         QPointer<QWidget> m_navigationWidget;
         KDevelop::DeclarationId m_navigationWidgetDeclaration;
         bool m_allowLockedUpdate;
         KDevelop::IndexedTopDUContext m_lastUsedTopContext;
 
         KDevelop::IndexedDUContext m_context;
-        int m_nextHistoryIndex;
-        
-        QVector<HistoryEntry> m_history;
-        QPointer<QToolButton> m_previousButton;
-        QPointer<QToolButton> m_nextButton;
-        QPointer<QMenu> m_previousMenu, m_nextMenu;
-        QPointer<QToolButton> m_browseButton;
-        QList<KDevelop::IndexedDeclaration> m_listDeclarations;
-        KDevelop::IndexedString m_listUrl;
-        BrowseManager* m_browseManager;
-        //Used to not record jumps triggered by the context-browser as history entries
-        QPointer<QWidget> m_focusBackWidget;
-        QPointer<KDevelop::IQuickOpenLine> m_outlineLine;
-        
-        QPointer<QHBoxLayout> m_toolbarWidgetLayout;
-        QPointer<QWidget> m_toolbarWidget;
 };
 
 #endif