language/duchain
abstractnavigationwidget.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "abstractnavigationwidget.h"
00021
00022 #include <QtCore/QMap>
00023 #include <QtCore/QStringList>
00024 #include <QtCore/QMetaObject>
00025 #include <QtGui/QScrollBar>
00026 #include <QtGui/QBoxLayout>
00027
00028 #include <klocale.h>
00029
00030 #include "../declaration.h"
00031 #include "../ducontext.h"
00032 #include "../duchainlock.h"
00033 #include "../functiondeclaration.h"
00034 #include "../functiondefinition.h"
00035 #include "../forwarddeclaration.h"
00036 #include "../namespacealiasdeclaration.h"
00037 #include "../classfunctiondeclaration.h"
00038 #include "../classmemberdeclaration.h"
00039 #include "../topducontext.h"
00040 #include "abstractnavigationcontext.h"
00041 #include "abstractdeclarationnavigationcontext.h"
00042 #include "navigationaction.h"
00043 #include "useswidget.h"
00044 #include "../../../interfaces/icore.h"
00045 #include "../../../interfaces/idocumentcontroller.h"
00046 #include <qapplication.h>
00047 #include <qevent.h>
00048
00049 namespace KDevelop {
00050
00051 AbstractNavigationWidget::AbstractNavigationWidget()
00052 : m_browser(0), m_currentWidget(0)
00053 {
00054 setPalette( QApplication::palette() );
00055 setFocusPolicy(Qt::NoFocus);
00056 resize(100, 100);
00057 }
00058
00059 const int maxNavigationWidgetWidth = 580;
00060
00061 QSize AbstractNavigationWidget::sizeHint() const
00062 {
00063 if(m_browser) {
00064 updateIdealSize();
00065 QSize ret = QSize(qMin(m_idealTextSize.width(), maxNavigationWidgetWidth), qMin(m_idealTextSize.height(), 300));
00066
00067 if(m_currentWidget) {
00068 ret.setHeight( ret.height() + m_currentWidget->sizeHint().height() );
00069 if(m_currentWidget->sizeHint().width() > ret.width())
00070 ret.setWidth(m_currentWidget->sizeHint().width());
00071 if(ret.width() < 500)
00072 ret.setWidth(500);
00073
00074 }
00075 return ret;
00076 } else
00077 return QWidget::sizeHint();
00078 }
00079
00080 void AbstractNavigationWidget::initBrowser(int height) {
00081 Q_UNUSED(height);
00082 m_browser = new KTextBrowser;
00083
00084
00085 m_browser->setPalette( QPalette( Qt::black, Qt::white ) );
00086
00087 m_browser->setOpenLinks(false);
00088 m_browser->setOpenExternalLinks(false);
00089
00090 QVBoxLayout* layout = new QVBoxLayout;
00091 layout->addWidget(m_browser);
00092 layout->setMargin(0);
00093 setLayout(layout);
00094
00095 connect( m_browser, SIGNAL(anchorClicked(const QUrl&)), this, SLOT(anchorClicked(const QUrl&)) );
00096 }
00097
00098 AbstractNavigationWidget::~AbstractNavigationWidget() {
00099 if(m_currentWidget)
00100 layout()->removeWidget(m_currentWidget);
00101
00102 }
00103
00104 void AbstractNavigationWidget::setContext(NavigationContextPointer context, int initBrows)
00105 {
00106 if(m_browser == 0)
00107 initBrowser(initBrows);
00108
00109 if(!context) {
00110 kDebug() << "no new context created";
00111 return;
00112 }
00113 if(context == m_context && (!context || context->alreadyComputed()))
00114 return;
00115 m_context = context;
00116 update();
00117
00118 emit sizeHintChanged();
00119 }
00120
00121 void AbstractNavigationWidget::updateIdealSize() const {
00122 if(m_context && !m_idealTextSize.isValid()) {
00123 QTextDocument doc;
00124 doc.setHtml(m_currentText);
00125 if(doc.idealWidth() > maxNavigationWidgetWidth) {
00126 doc.setPageSize( QSize(maxNavigationWidgetWidth, 30) );
00127 m_idealTextSize.setWidth(maxNavigationWidgetWidth);
00128 }else{
00129 m_idealTextSize.setWidth(doc.idealWidth());
00130 }
00131 m_idealTextSize.setHeight(doc.size().height());
00132 }
00133 }
00134
00135 void AbstractNavigationWidget::update() {
00136 setUpdatesEnabled(false);
00137 Q_ASSERT( m_context );
00138
00139 QString html = m_context->html();
00140 if(!html.isEmpty()) {
00141 int scrollPos = m_browser->verticalScrollBar()->value();
00142
00143 m_browser->setHtml( html );
00144
00145 m_currentText = html;
00146 m_idealTextSize = QSize();
00147
00148 QSize hint = sizeHint();
00149 if(hint.height() >= m_idealTextSize.height()) {
00150 m_browser->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
00151 }else{
00152 m_browser->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded);
00153 }
00154
00155 m_browser->verticalScrollBar()->setValue(scrollPos);
00156 m_browser->scrollToAnchor("currentPosition");
00157 m_browser->show();
00158 }else{
00159 m_browser->hide();
00160 }
00161
00162 if(m_currentWidget) {
00163 layout()->removeWidget(m_currentWidget);
00164 m_currentWidget->setParent(0);
00165 }
00166
00167 m_currentWidget = m_context->widget();
00168
00169 m_browser->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
00170 m_browser->setMaximumHeight(10000);
00171
00172 if(m_currentWidget) {
00173
00174 connect(m_currentWidget, SIGNAL(navigateDeclaration(KDevelop::IndexedDeclaration)), this, SLOT(navigateDeclaration(KDevelop::IndexedDeclaration)));
00175 layout()->addWidget(m_currentWidget);
00176 if(m_context->isWidgetMaximized()) {
00177
00178 m_browser->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Minimum);
00179 m_browser->setMaximumHeight(25);
00180 }
00181 }
00182
00183 setUpdatesEnabled(true);
00184 }
00185
00186 NavigationContextPointer AbstractNavigationWidget::context() {
00187 return m_context;
00188 }
00189
00190 void AbstractNavigationWidget::navigateDeclaration(KDevelop::IndexedDeclaration decl) {
00191 DUChainReadLocker lock( DUChain::lock() );
00192 setContext(m_context->accept(decl));
00193 }
00194
00195 void AbstractNavigationWidget::anchorClicked(const QUrl& url) {
00196 DUChainReadLocker lock( DUChain::lock() );
00197
00198
00199 QPointer<AbstractNavigationWidget> thisPtr(this);
00200 NavigationContextPointer oldContext = m_context;
00201 NavigationContextPointer nextContext = m_context->acceptLink(url.toString());
00202
00203 if(thisPtr)
00204 setContext( nextContext );
00205 }
00206
00207 void AbstractNavigationWidget::keyPressEvent(QKeyEvent* event) {
00208 QWidget::keyPressEvent(event);
00209 }
00210
00211 void AbstractNavigationWidget::executeContextAction(QString action) {
00212 DUChainReadLocker lock( DUChain::lock() );
00213
00214 QPointer<AbstractNavigationWidget> thisPtr(this);
00215 NavigationContextPointer oldContext = m_context;
00216 NavigationContextPointer nextContext = m_context->executeLink(action);
00217
00218 if(thisPtr)
00219 setContext( nextContext );
00220 }
00221
00222 void AbstractNavigationWidget::next() {
00223 DUChainReadLocker lock( DUChain::lock() );
00224 Q_ASSERT( m_context );
00225 m_context->nextLink();
00226 update();
00227 }
00228
00229 void AbstractNavigationWidget::previous() {
00230 DUChainReadLocker lock( DUChain::lock() );
00231 Q_ASSERT( m_context );
00232 m_context->previousLink();
00233 update();
00234 }
00235
00236 void AbstractNavigationWidget::accept() {
00237 DUChainReadLocker lock( DUChain::lock() );
00238 Q_ASSERT( m_context );
00239
00240 QPointer<AbstractNavigationWidget> thisPtr(this);
00241 NavigationContextPointer oldContext = m_context;
00242 NavigationContextPointer nextContext = m_context->accept();
00243
00244 if(thisPtr)
00245 setContext( nextContext );
00246 }
00247
00248 void AbstractNavigationWidget::back() {
00249 DUChainReadLocker lock( DUChain::lock() );
00250
00251 QPointer<AbstractNavigationWidget> thisPtr(this);
00252 NavigationContextPointer oldContext = m_context;
00253 NavigationContextPointer nextContext = m_context->back();
00254
00255 if(thisPtr)
00256 setContext( nextContext );
00257 }
00258
00259 void AbstractNavigationWidget::up() {
00260 DUChainReadLocker lock( DUChain::lock() );
00261 m_context->up();
00262 update();
00263 }
00264
00265 void AbstractNavigationWidget::down() {
00266 DUChainReadLocker lock( DUChain::lock() );
00267 m_context->down();
00268 update();
00269 }
00270
00271 void AbstractNavigationWidget::embeddedWidgetAccept() {
00272 accept();
00273 }
00274 void AbstractNavigationWidget::embeddedWidgetDown() {
00275 down();
00276 }
00277
00278 void AbstractNavigationWidget::embeddedWidgetRight() {
00279 next();
00280 }
00281
00282 void AbstractNavigationWidget::embeddedWidgetLeft() {
00283 previous();
00284 }
00285
00286 void AbstractNavigationWidget::embeddedWidgetUp() {
00287 up();
00288 }
00289
00290
00291 void AbstractNavigationWidget::wheelEvent(QWheelEvent* event )
00292 {
00293 QWidget::wheelEvent(event);
00294 event->accept();
00295 return;
00296 }
00297
00298
00299
00300 }
00301
00302 #include "abstractnavigationwidget.moc"