forked from qt-creator/qt-creator
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: Fawzi Mohamed <fawzi.mohamed@digia.com>
This commit is contained in:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user