mirror of
https://bitbucket.org/smil3y/kde-extraapps.git
synced 2025-02-25 11:22:55 +00:00
324 lines
11 KiB
C++
324 lines
11 KiB
C++
/*
|
|
* This file is part of KDevelop
|
|
*
|
|
* Copyright 2008 David Nolden <david.nolden.kdevelop@art-master.de>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU Library 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 "contextbrowserview.h"
|
|
|
|
///TODO: cleanup includes
|
|
#include <QVBoxLayout>
|
|
#include <QHBoxLayout>
|
|
#include <QLabel>
|
|
#include <QToolButton>
|
|
#include <QShowEvent>
|
|
#include <QAction>
|
|
#include <QMenu>
|
|
#include <KIcon>
|
|
#include <KTextBrowser>
|
|
#include <KLocale>
|
|
#include <KComboBox>
|
|
#include <ktexteditor/document.h>
|
|
#include <ktexteditor/view.h>
|
|
|
|
#include <language/duchain/declaration.h>
|
|
#include <language/duchain/topducontext.h>
|
|
#include <language/duchain/ducontext.h>
|
|
#include <language/duchain/duchain.h>
|
|
#include <language/duchain/duchainlock.h>
|
|
#include <language/duchain/indexedstring.h>
|
|
|
|
#include <interfaces/icore.h>
|
|
#include <interfaces/idocumentcontroller.h>
|
|
|
|
#include "contextbrowser.h"
|
|
#include <language/duchain/duchainutils.h>
|
|
#include <language/duchain/types/functiontype.h>
|
|
#include <language/duchain/specializationstore.h>
|
|
#include "browsemanager.h"
|
|
#include <language/duchain/navigation/abstractnavigationwidget.h>
|
|
#include <kparts/part.h>
|
|
#include <qapplication.h>
|
|
#include <language/interfaces/codecontext.h>
|
|
#include <language/duchain/navigation/abstractdeclarationnavigationcontext.h>
|
|
#include <language/duchain/navigation/useswidget.h>
|
|
#include <interfaces/contextmenuextension.h>
|
|
#include <interfaces/iplugincontroller.h>
|
|
|
|
using namespace KDevelop;
|
|
|
|
QWidget* ContextBrowserView::createWidget(KDevelop::DUContext* context) {
|
|
m_context = IndexedDUContext(context);
|
|
if(m_context.data()) {
|
|
return m_context.data()->createNavigationWidget();
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
KDevelop::IndexedDeclaration ContextBrowserView::declaration() const {
|
|
return m_declaration;
|
|
}
|
|
|
|
QWidget* ContextBrowserView::createWidget(Declaration* decl, TopDUContext* topContext) {
|
|
m_declaration = IndexedDeclaration(decl);
|
|
return decl->context()->createNavigationWidget(decl, topContext);
|
|
}
|
|
|
|
|
|
void ContextBrowserView::resetWidget()
|
|
{
|
|
if (m_navigationWidget) {
|
|
delete m_navigationWidget;
|
|
m_navigationWidget = 0;
|
|
}
|
|
}
|
|
|
|
void ContextBrowserView::declarationMenu() {
|
|
DUChainReadLocker lock(DUChain::lock());
|
|
|
|
AbstractNavigationWidget* navigationWidget = dynamic_cast<AbstractNavigationWidget*>(m_navigationWidget.data());
|
|
if(navigationWidget) {
|
|
AbstractDeclarationNavigationContext* navigationContext = dynamic_cast<AbstractDeclarationNavigationContext*>(navigationWidget->context().data());
|
|
if(navigationContext && navigationContext->declaration().data()) {
|
|
KDevelop::DeclarationContext* c = new KDevelop::DeclarationContext(navigationContext->declaration().data());
|
|
lock.unlock();
|
|
QMenu menu;
|
|
QList<ContextMenuExtension> extensions = ICore::self()->pluginController()->queryPluginsForContextMenuExtensions( c );
|
|
|
|
ContextMenuExtension::populateMenu(&menu, extensions);
|
|
menu.exec(QCursor::pos());
|
|
}
|
|
}
|
|
}
|
|
|
|
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_autoLocked(false) {
|
|
setWindowIcon( KIcon("applications-development-web") );
|
|
|
|
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_buttons->addWidget(m_lockButton);
|
|
|
|
m_layout = new QVBoxLayout;
|
|
m_layout->setSpacing(0);
|
|
m_layout->setMargin(0);
|
|
m_layout->addLayout(m_buttons);
|
|
m_layout->addWidget(m_navigationWidget);
|
|
//m_layout->addStretch();
|
|
setLayout(m_layout);
|
|
|
|
m_plugin->registerToolView(this);
|
|
}
|
|
|
|
ContextBrowserView::~ContextBrowserView() {
|
|
m_plugin->unRegisterToolView(this);
|
|
}
|
|
|
|
void ContextBrowserView::focusInEvent(QFocusEvent* event) {
|
|
//Indicate that we have focus
|
|
kDebug() << "got focus";
|
|
// parentWidget()->setBackgroundRole(QPalette::ToolTipBase);
|
|
/* m_layout->removeItem(m_buttons);*/
|
|
|
|
return QWidget::focusInEvent(event);
|
|
}
|
|
|
|
void ContextBrowserView::focusOutEvent(QFocusEvent* event) {
|
|
kDebug() << "lost focus";
|
|
// parentWidget()->setBackgroundRole(QPalette::Background);
|
|
/* m_layout->insertLayout(0, m_buttons);
|
|
for(int a = 0; a < m_buttons->count(); ++a) {
|
|
QWidgetItem* item = dynamic_cast<QWidgetItem*>(m_buttons->itemAt(a));
|
|
}*/
|
|
QWidget::focusOutEvent(event);
|
|
}
|
|
|
|
bool ContextBrowserView::event(QEvent* event) {
|
|
QKeyEvent* keyEvent = dynamic_cast<QKeyEvent*>(event);
|
|
|
|
if(hasFocus() && keyEvent) {
|
|
AbstractNavigationWidget* navigationWidget = dynamic_cast<AbstractNavigationWidget*>(m_navigationWidget.data());
|
|
if(navigationWidget && event->type() == QEvent::KeyPress) {
|
|
int key = keyEvent->key();
|
|
if(key == Qt::Key_Left)
|
|
navigationWidget->previous();
|
|
if(key == Qt::Key_Right)
|
|
navigationWidget->next();
|
|
if(key == Qt::Key_Up)
|
|
navigationWidget->up();
|
|
if(key == Qt::Key_Down)
|
|
navigationWidget->down();
|
|
if(key == Qt::Key_Return || key == Qt::Key_Enter)
|
|
navigationWidget->accept();
|
|
|
|
|
|
if(key == Qt::Key_L)
|
|
m_lockButton->toggle();
|
|
}
|
|
}
|
|
return QWidget::event(event);
|
|
}
|
|
|
|
void ContextBrowserView::showEvent(QShowEvent* event) {
|
|
DUChainReadLocker lock(DUChain::lock());
|
|
TopDUContext* top = m_lastUsedTopContext.data();
|
|
if(top && m_navigationWidgetDeclaration.isValid() && m_navigationWidgetDeclaration.getDeclaration(top)) {
|
|
if(top) {
|
|
//Update the navigation-widget
|
|
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);
|
|
}
|
|
m_plugin->updateDeclarationListBox(context);
|
|
*/
|
|
}
|
|
}
|
|
QWidget::showEvent(event);
|
|
}
|
|
|
|
bool ContextBrowserView::isLocked() const {
|
|
bool isLocked;
|
|
if (m_allowLockedUpdate) {
|
|
isLocked = false;
|
|
} else {
|
|
isLocked = m_lockButton->isChecked();
|
|
}
|
|
return isLocked;
|
|
}
|
|
|
|
void ContextBrowserView::updateMainWidget(QWidget* widget)
|
|
{
|
|
if (widget) {
|
|
setUpdatesEnabled(false);
|
|
kDebug() << "";
|
|
resetWidget();
|
|
m_navigationWidget = widget;
|
|
m_layout->insertWidget(1, widget, 1);
|
|
m_allowLockedUpdate = false;
|
|
setUpdatesEnabled(true);
|
|
connect(widget, SIGNAL(contextChanged(bool,bool)), this, SLOT(navigationContextChanged(bool,bool)));
|
|
}
|
|
}
|
|
|
|
void ContextBrowserView::navigationContextChanged(bool wasInitial, bool isInitial)
|
|
{
|
|
if(wasInitial && !isInitial && !m_lockButton->isChecked())
|
|
{
|
|
m_autoLocked = true;
|
|
m_lockButton->setChecked(true);
|
|
}else if(!wasInitial && isInitial && m_autoLocked)
|
|
{
|
|
m_autoLocked = false;
|
|
m_lockButton->setChecked(false);
|
|
}else if(isInitial) {
|
|
m_autoLocked = false;
|
|
}
|
|
}
|
|
|
|
void ContextBrowserView::setDeclaration(KDevelop::Declaration* decl, KDevelop::TopDUContext* topContext, bool force) {
|
|
m_lastUsedTopContext = IndexedTopDUContext(topContext);
|
|
|
|
if(isLocked() && (!m_navigationWidget.data() || !isVisible()))
|
|
{
|
|
// Automatically remove the locked state if the view is not visible or the widget was deleted,
|
|
// because the locked state has side-effects on other navigation functionality.
|
|
m_autoLocked = false;
|
|
m_lockButton->setChecked(false);
|
|
}
|
|
|
|
if(m_navigationWidgetDeclaration == decl->id() && !force)
|
|
return;
|
|
|
|
m_navigationWidgetDeclaration = decl->id();
|
|
|
|
if (!isLocked() && (isVisible() || force)) { // NO-OP if toolview is hidden, for performance reasons
|
|
|
|
QWidget* w = createWidget(decl, topContext);
|
|
updateMainWidget(w);
|
|
}
|
|
}
|
|
|
|
KDevelop::IndexedDeclaration ContextBrowserView::lockedDeclaration() const {
|
|
if(m_lockButton->isChecked())
|
|
return declaration();
|
|
else
|
|
return KDevelop::IndexedDeclaration();
|
|
}
|
|
|
|
void ContextBrowserView::allowLockedUpdate() {
|
|
m_allowLockedUpdate = true;
|
|
}
|
|
|
|
void ContextBrowserView::setNavigationWidget(QWidget* widget) {
|
|
updateMainWidget(widget);
|
|
}
|
|
|
|
void ContextBrowserView::setContext(KDevelop::DUContext* context) {
|
|
if(!context)
|
|
return;
|
|
|
|
m_lastUsedTopContext = IndexedTopDUContext(context->topContext());
|
|
|
|
if(context->owner()) {
|
|
if(context->owner()->id() == m_navigationWidgetDeclaration)
|
|
return;
|
|
m_navigationWidgetDeclaration = context->owner()->id();
|
|
}else{
|
|
m_navigationWidgetDeclaration = DeclarationId();
|
|
}
|
|
|
|
if (!isLocked() && isVisible()) { // NO-OP if toolview is hidden, for performance reasons
|
|
|
|
QWidget* w = createWidget(context);
|
|
updateMainWidget(w);
|
|
}
|
|
}
|
|
|
|
void ContextBrowserView::setSpecialNavigationWidget(QWidget* widget) {
|
|
if (!isLocked() && isVisible()) {
|
|
Q_ASSERT(widget);
|
|
updateMainWidget(widget);
|
|
} else if(widget) {
|
|
widget->deleteLater();
|
|
}
|
|
}
|
|
|
|
#include "moc_contextbrowserview.cpp"
|