Commit 58b717fb authored by Eike Ziller's avatar Eike Ziller

QmlJSEditor: Move outline model to document

Also the updating of the model is now done only once in the document,
and delayed till an editor is visible if necessary.

Change-Id: I69b1abebc2b691b37a618db7d1f5ebbbc8e75bca
Reviewed-by: default avatarFawzi Mohamed <fawzi.mohamed@digia.com>
parent 1e6bc275
......@@ -114,7 +114,6 @@ void QmlJSTextEditorWidget::ctor()
{
m_qmlJsEditorDocument = static_cast<QmlJSEditorDocument *>(baseTextDocument());
m_outlineCombo = 0;
m_outlineModel = new QmlOutlineModel(m_qmlJsEditorDocument);
m_contextPane = 0;
m_findReferences = new FindReferences(this);
......@@ -130,11 +129,6 @@ void QmlJSTextEditorWidget::ctor()
connect(m_updateUsesTimer, SIGNAL(timeout()), this, SLOT(updateUses()));
connect(this, SIGNAL(cursorPositionChanged()), m_updateUsesTimer, SLOT(start()));
m_updateOutlineTimer = new QTimer(this);
m_updateOutlineTimer->setInterval(UPDATE_OUTLINE_INTERVAL);
m_updateOutlineTimer->setSingleShot(true);
connect(m_updateOutlineTimer, SIGNAL(timeout()), this, SLOT(updateOutlineNow()));
m_updateOutlineIndexTimer = new QTimer(this);
m_updateOutlineIndexTimer->setInterval(UPDATE_OUTLINE_INTERVAL);
m_updateOutlineIndexTimer->setSingleShot(true);
......@@ -157,14 +151,14 @@ void QmlJSTextEditorWidget::ctor()
connect(this->document(), SIGNAL(modificationChanged(bool)), this, SLOT(modificationChanged(bool)));
connect(m_qmlJsEditorDocument, SIGNAL(updateCodeWarnings(QmlJS::Document::Ptr)),
this, SLOT(updateCodeWarnings(QmlJS::Document::Ptr)));
connect(m_qmlJsEditorDocument, SIGNAL(semanticInfoUpdated(QmlJSTools::SemanticInfo)),
this, SLOT(semanticInfoUpdated(QmlJSTools::SemanticInfo)));
connect(this, SIGNAL(refactorMarkerClicked(TextEditor::RefactorMarker)),
SLOT(onRefactorMarkerClicked(TextEditor::RefactorMarker)));
connect(baseTextDocument(), SIGNAL(updateCodeWarnings(QmlJS::Document::Ptr)),
this, SLOT(updateCodeWarnings(QmlJS::Document::Ptr)));
setRequestMarkEnabled(true);
}
......@@ -194,7 +188,7 @@ bool QmlJSTextEditorWidget::isSemanticInfoOutdated() const
QmlOutlineModel *QmlJSTextEditorWidget::outlineModel() const
{
return m_outlineModel;
return m_qmlJsEditorDocument->outlineModel();
}
QModelIndex QmlJSTextEditorWidget::outlineModelIndex()
......@@ -285,7 +279,7 @@ void QmlJSTextEditorWidget::modificationChanged(bool changed)
void QmlJSTextEditorWidget::jumpToOutlineElement(int /*index*/)
{
QModelIndex index = m_outlineCombo->view()->currentIndex();
AST::SourceLocation location = m_outlineModel->sourceLocation(index);
AST::SourceLocation location = m_qmlJsEditorDocument->outlineModel()->sourceLocation(index);
if (!location.isValid())
return;
......@@ -300,33 +294,12 @@ void QmlJSTextEditorWidget::jumpToOutlineElement(int /*index*/)
setFocus();
}
void QmlJSTextEditorWidget::updateOutlineNow()
{
if (!m_qmlJsEditorDocument->semanticInfo().document)
return;
if (m_qmlJsEditorDocument->semanticInfo().document->editorRevision() != editorRevision()) {
m_updateOutlineTimer->start();
return;
}
m_outlineModel->update(m_qmlJsEditorDocument->semanticInfo());
QTreeView *treeView = static_cast<QTreeView*>(m_outlineCombo->view());
treeView->expandAll();
updateOutlineIndexNow();
}
void QmlJSTextEditorWidget::updateOutlineIndexNow()
{
if (m_updateOutlineTimer->isActive())
return; // updateOutlineNow will call this function soon anyway
if (!m_outlineModel->document())
if (!m_qmlJsEditorDocument->outlineModel()->document())
return;
if (m_outlineModel->document()->editorRevision() != editorRevision()) {
if (m_qmlJsEditorDocument->outlineModel()->document()->editorRevision() != editorRevision()) {
m_updateOutlineIndexTimer->start();
return;
}
......@@ -604,7 +577,7 @@ void QmlJSTextEditorWidget::createToolBar(QmlJSEditor *editor)
{
m_outlineCombo = new QComboBox;
m_outlineCombo->setMinimumContentsLength(22);
m_outlineCombo->setModel(m_outlineModel);
m_outlineCombo->setModel(m_qmlJsEditorDocument->outlineModel());
QTreeView *treeView = new QTreeView;
......@@ -627,6 +600,11 @@ void QmlJSTextEditorWidget::createToolBar(QmlJSEditor *editor)
m_outlineCombo->setSizePolicy(policy);
connect(m_outlineCombo, SIGNAL(activated(int)), this, SLOT(jumpToOutlineElement(int)));
connect(m_qmlJsEditorDocument->outlineModel(), SIGNAL(updated()),
m_outlineCombo->view()/*QTreeView*/, SLOT(expandAll()));
connect(m_qmlJsEditorDocument->outlineModel(), SIGNAL(updated()),
this, SLOT(updateOutlineIndexNow()));
connect(this, SIGNAL(cursorPositionChanged()), m_updateOutlineIndexTimer, SLOT(start()));
editor->insertExtraToolBarWidget(TextEditor::BaseTextEditor::Left, m_outlineCombo);
......@@ -856,8 +834,10 @@ void QmlJSTextEditorWidget::unCommentSelection()
void QmlJSTextEditorWidget::semanticInfoUpdated(const SemanticInfo &semanticInfo)
{
if (isVisible())
baseTextDocument()->triggerPendingUpdates(); // trigger semantic highlighting if necessary
if (isVisible()) {
// trigger semantic highlighting and model update if necessary
baseTextDocument()->triggerPendingUpdates();
}
if (m_contextPane) {
Node *newNode = semanticInfo.declaringMemberNoProperties(position());
......@@ -868,9 +848,6 @@ void QmlJSTextEditorWidget::semanticInfoUpdated(const SemanticInfo &semanticInfo
}
updateUses();
// update outline
m_updateOutlineTimer->start();
}
void QmlJSTextEditorWidget::onRefactorMarkerClicked(const TextEditor::RefactorMarker &marker)
......@@ -883,11 +860,11 @@ QModelIndex QmlJSTextEditorWidget::indexForPosition(unsigned cursorPosition, con
{
QModelIndex lastIndex = rootIndex;
const int rowCount = m_outlineModel->rowCount(rootIndex);
QmlOutlineModel *model = m_qmlJsEditorDocument->outlineModel();
const int rowCount = model->rowCount(rootIndex);
for (int i = 0; i < rowCount; ++i) {
QModelIndex childIndex = m_outlineModel->index(i, 0, rootIndex);
AST::SourceLocation location = m_outlineModel->sourceLocation(childIndex);
QModelIndex childIndex = model->index(i, 0, rootIndex);
AST::SourceLocation location = model->sourceLocation(childIndex);
if ((cursorPosition >= location.offset)
&& (cursorPosition <= location.offset + location.length)) {
......
......@@ -105,8 +105,8 @@ public:
bool isSemanticInfoOutdated() const;
int editorRevision() const;
QVector<QTextLayout::FormatRange> diagnosticRanges() const;
Internal::QmlOutlineModel *outlineModel() const;
QModelIndex outlineModelIndex();
static QVector<TextEditor::TextStyle> highlighterFormatCategories();
......@@ -126,7 +126,6 @@ private slots:
void modificationChanged(bool);
void jumpToOutlineElement(int index);
void updateOutlineNow();
void updateOutlineIndexNow();
void updateContextPane();
void showTextMarker();
......@@ -166,11 +165,9 @@ private:
Internal::QmlJSEditorDocument *m_qmlJsEditorDocument;
QTimer *m_updateUsesTimer; // to wait for multiple text cursor position changes
QTimer *m_updateOutlineTimer;
QTimer *m_updateOutlineIndexTimer;
QTimer *m_contextPaneTimer;
QComboBox *m_outlineCombo;
Internal::QmlOutlineModel *m_outlineModel;
QModelIndex m_outlineModelIndex;
QmlJS::ModelManagerInterface *m_modelManager;
......
......@@ -33,6 +33,7 @@
#include "qmljshighlighter.h"
#include "qmljssemantichighlighter.h"
#include "qmljssemanticinfoupdater.h"
#include "qmloutlinemodel.h"
#include <qmljstools/qmljsindenter.h>
#include <qmljstools/qmljsmodelmanager.h>
......@@ -46,7 +47,8 @@ using namespace QmlJSTools;
namespace {
enum {
UPDATE_DOCUMENT_DEFAULT_INTERVAL = 100
UPDATE_DOCUMENT_DEFAULT_INTERVAL = 100,
UPDATE_OUTLINE_INTERVAL = 500
};
class FindIdDeclarations: protected Visitor
......@@ -399,7 +401,9 @@ QmlJSEditorDocumentPrivate::QmlJSEditorDocumentPrivate(QmlJSEditorDocument *pare
: m_q(parent),
m_semanticInfoDocRevision(-1),
m_semanticHighlighter(new SemanticHighlighter(parent)),
m_semanticHighlightingNecessary(false)
m_semanticHighlightingNecessary(false),
m_outlineModelNeedsUpdate(false),
m_outlineModel(new QmlOutlineModel(parent))
{
ModelManagerInterface *modelManager = ModelManagerInterface::instance();
......@@ -425,6 +429,12 @@ QmlJSEditorDocumentPrivate::QmlJSEditorDocumentPrivate(QmlJSEditorDocument *pare
connect(m_reupdateSemanticInfoTimer, SIGNAL(timeout()), this, SLOT(reupdateSemanticInfo()));
connect(modelManager, SIGNAL(libraryInfoUpdated(QString,QmlJS::LibraryInfo)),
m_reupdateSemanticInfoTimer, SLOT(start()));
// outline model
m_updateOutlineModelTimer = new QTimer(this);
m_updateOutlineModelTimer->setInterval(UPDATE_OUTLINE_INTERVAL);
m_updateOutlineModelTimer->setSingleShot(true);
connect(m_updateOutlineModelTimer, SIGNAL(timeout()), this, SLOT(updateOutlineModel()));
}
QmlJSEditorDocumentPrivate::~QmlJSEditorDocumentPrivate()
......@@ -490,8 +500,18 @@ void QmlJSEditorDocumentPrivate::acceptNewSemanticInfo(const SemanticInfo &seman
FindIdDeclarations updateIds;
m_semanticInfo.idLocations = updateIds(doc);
m_outlineModelNeedsUpdate = true;
m_semanticHighlightingNecessary = true;
emit m_q->semanticInfoUpdated(m_semanticInfo);
emit m_q->semanticInfoUpdated(m_semanticInfo); // calls triggerPendingUpdates as necessary
}
void QmlJSEditorDocumentPrivate::updateOutlineModel()
{
if (m_q->isSemanticInfoOutdated())
return; // outline update will be retriggered when semantic info is updated
m_outlineModel->update(m_semanticInfo);
}
QmlJSEditorDocument::QmlJSEditorDocument()
......@@ -523,6 +543,11 @@ QVector<QTextLayout::FormatRange> QmlJSEditorDocument::diagnosticRanges() const
return m_d->m_diagnosticRanges;
}
QmlOutlineModel *QmlJSEditorDocument::outlineModel() const
{
return m_d->m_outlineModel;
}
void QmlJSEditorDocument::setDiagnosticRanges(const QVector<QTextLayout::FormatRange> &ranges)
{
m_d->m_diagnosticRanges = ranges;
......@@ -546,6 +571,10 @@ void QmlJSEditorDocument::triggerPendingUpdates()
m_d->m_semanticHighlightingNecessary = false;
m_d->m_semanticHighlighter->rerun(m_d->m_semanticInfo);
}
if (m_d->m_outlineModelNeedsUpdate && !isSemanticInfoOutdated()) {
m_d->m_outlineModelNeedsUpdate = false;
m_d->m_updateOutlineModelTimer->start();
}
}
} // Internal
......
......@@ -40,6 +40,7 @@ namespace QmlJSEditor {
namespace Internal {
class QmlJSEditorDocumentPrivate;
class QmlOutlineModel;
class QmlJSEditorDocument : public TextEditor::BaseTextDocument
{
......@@ -52,6 +53,7 @@ public:
bool isSemanticInfoOutdated() const;
QVector<QTextLayout::FormatRange> diagnosticRanges() const;
void setDiagnosticRanges(const QVector<QTextLayout::FormatRange> &ranges);
Internal::QmlOutlineModel *outlineModel() const;
signals:
void updateCodeWarnings(QmlJS::Document::Ptr doc);
......
......@@ -41,6 +41,7 @@ namespace QmlJSEditor {
namespace Internal {
class QmlJSEditorDocument;
class QmlOutlineModel;
class SemanticHighlighter;
class SemanticInfoUpdater;
......@@ -58,6 +59,7 @@ public slots:
void onDocumentUpdated(QmlJS::Document::Ptr doc);
void reupdateSemanticInfo();
void acceptNewSemanticInfo(const QmlJSTools::SemanticInfo &semanticInfo);
void updateOutlineModel();
public:
QmlJSEditorDocument *m_q;
......@@ -69,6 +71,9 @@ public:
QVector<QTextLayout::FormatRange> m_diagnosticRanges;
Internal::SemanticHighlighter *m_semanticHighlighter;
bool m_semanticHighlightingNecessary;
bool m_outlineModelNeedsUpdate;
QTimer *m_updateOutlineModelTimer;
Internal::QmlOutlineModel *m_outlineModel;
};
} // Internal
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment