QmlDesigner: Introduce SkipIterator

Instead of having a cache using an iterator skipping entries is much
easier because the cache has not to be anymore updated. When we get
C++ 20 ranges use them instead.

Change-Id: If5b45c53bbd0b12138328862ac152788ffd911b2
Reviewed-by: Thomas Hartmann <thomas.hartmann@qt.io>
Reviewed-by: Mahmoud Badri <mahmoud.badri@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
This commit is contained in:
Marco Bubke
2023-04-22 01:44:27 +02:00
parent dd5730d2a3
commit 3ff90526f5
5 changed files with 111 additions and 27 deletions

View File

@@ -371,6 +371,7 @@ extend_qtc_library(QmlDesignerCore
rewriteactioncompressor.h rewriteactioncompressor.h
rewriterview.cpp rewriterview.cpp
signalhandlerproperty.cpp signalhandlerproperty.cpp
skipiterator.h
stylesheetmerger.cpp stylesheetmerger.cpp
textmodifier.cpp textmodifier.cpp
texttomodelmerger.cpp texttomodelmerger.cpp

View File

@@ -143,9 +143,6 @@ The default implementation is setting the reference of the model to the view.
void AbstractView::modelAttached(Model *model) void AbstractView::modelAttached(Model *model)
{ {
setModel(model); setModel(model);
if (model)
model->d->updateEnabledViews();
} }
/*! /*!
@@ -617,9 +614,6 @@ bool AbstractView::isEnabled() const
void AbstractView::setEnabled(bool b) void AbstractView::setEnabled(bool b)
{ {
m_enabled = b; m_enabled = b;
if (model())
model()->d->updateEnabledViews();
} }
QList<ModelNode> AbstractView::allModelNodes() const QList<ModelNode> AbstractView::allModelNodes() const

View File

@@ -96,7 +96,6 @@ void ModelPrivate::detachAllViews()
detachView(view.data(), true); detachView(view.data(), true);
m_viewList.clear(); m_viewList.clear();
updateEnabledViews();
if (m_nodeInstanceView) { if (m_nodeInstanceView) {
m_nodeInstanceView->modelAboutToBeDetached(m_model); m_nodeInstanceView->modelAboutToBeDetached(m_model);
@@ -299,9 +298,9 @@ void ModelPrivate::removeNodeFromModel(const InternalNodePointer &node)
m_internalIdNodeHash.remove(node->internalId); m_internalIdNodeHash.remove(node->internalId);
} }
const QList<QPointer<AbstractView>> ModelPrivate::enabledViews() const EnabledViewRange ModelPrivate::enabledViews() const
{ {
return m_enabledViewList; return EnabledViewRange{m_viewList};
} }
void ModelPrivate::removeAllSubNodes(const InternalNodePointer &node) void ModelPrivate::removeAllSubNodes(const InternalNodePointer &node)
@@ -754,7 +753,6 @@ void ModelPrivate::detachView(AbstractView *view, bool notifyView)
if (notifyView) if (notifyView)
view->modelAboutToBeDetached(m_model); view->modelAboutToBeDetached(m_model);
m_viewList.removeOne(view); m_viewList.removeOne(view);
updateEnabledViews();
} }
void ModelPrivate::notifyNodeCreated(const InternalNodePointer &newInternalNodePointer) void ModelPrivate::notifyNodeCreated(const InternalNodePointer &newInternalNodePointer)
@@ -1317,13 +1315,6 @@ InternalNodePointer ModelPrivate::currentTimelineNode() const
return m_currentTimelineNode; return m_currentTimelineNode;
} }
void ModelPrivate::updateEnabledViews()
{
m_enabledViewList = Utils::filtered(m_viewList, [](QPointer<AbstractView> view) {
return view->isEnabled();
});
}
InternalNodePointer ModelPrivate::nodeForId(const QString &id) const InternalNodePointer ModelPrivate::nodeForId(const QString &id) const
{ {
return m_idNodeHash.value(id); return m_idNodeHash.value(id);

View File

@@ -3,17 +3,20 @@
#pragma once #pragma once
#include "qmldesignercorelib_global.h"
#include "abstractview.h"
#include "metainfo.h"
#include "modelnode.h"
#include "skipiterator.h"
#include <QList> #include <QList>
#include <QPointer> #include <QPointer>
#include <QSet> #include <QSet>
#include <QUrl> #include <QUrl>
#include <QVector3D> #include <QVector3D>
#include "modelnode.h" #include <algorithm>
#include "abstractview.h"
#include "metainfo.h"
#include "qmldesignercorelib_global.h"
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QPlainTextEdit; class QPlainTextEdit;
@@ -64,7 +67,28 @@ private:
QPointer<ModelPrivate> m_model; QPointer<ModelPrivate> m_model;
}; };
class ModelPrivate : public QObject { struct Increment
{
using iterator = QList<QPointer<AbstractView>>::const_iterator;
auto operator()(iterator current) {
return std::find_if(std::next(current),
end,
[] (iterator::reference &view) { return view && view->isEnabled(); });
}
iterator end;
};
class EnabledViewRange : public SkipRange<QList<QPointer<AbstractView>>, Increment>
{
public:
EnabledViewRange(const container &views)
: base{views, Increment{views.end()}}
{}
};
class ModelPrivate : public QObject
{
Q_OBJECT Q_OBJECT
friend Model; friend Model;
@@ -249,8 +273,6 @@ public:
InternalNodePointer currentStateNode() const; InternalNodePointer currentStateNode() const;
InternalNodePointer currentTimelineNode() const; InternalNodePointer currentTimelineNode() const;
void updateEnabledViews();
private: private:
void removePropertyWithoutNotification(const InternalPropertyPointer &property); void removePropertyWithoutNotification(const InternalPropertyPointer &property);
void removeAllSubNodes(const InternalNodePointer &node); void removeAllSubNodes(const InternalNodePointer &node);
@@ -259,7 +281,7 @@ private:
QList<ModelNode> toModelNodeList(const QList<InternalNodePointer> &nodeList, AbstractView *view) const; QList<ModelNode> toModelNodeList(const QList<InternalNodePointer> &nodeList, AbstractView *view) const;
QVector<ModelNode> toModelNodeVector(const QVector<InternalNodePointer> &nodeVector, AbstractView *view) const; QVector<ModelNode> toModelNodeVector(const QVector<InternalNodePointer> &nodeVector, AbstractView *view) const;
QVector<InternalNodePointer> toInternalNodeVector(const QVector<ModelNode> &modelNodeVector) const; QVector<InternalNodePointer> toInternalNodeVector(const QVector<ModelNode> &modelNodeVector) const;
const QList<QPointer<AbstractView>> enabledViews() const; EnabledViewRange enabledViews() const;
public: public:
NotNullPointer<ProjectStorageType> projectStorage = nullptr; NotNullPointer<ProjectStorageType> projectStorage = nullptr;
@@ -271,7 +293,6 @@ private:
Imports m_possibleImportList; Imports m_possibleImportList;
Imports m_usedImportList; Imports m_usedImportList;
QList<QPointer<AbstractView>> m_viewList; QList<QPointer<AbstractView>> m_viewList;
QList<QPointer<AbstractView>> m_enabledViewList;
QList<InternalNodePointer> m_selectedInternalNodeList; QList<InternalNodePointer> m_selectedInternalNodeList;
QHash<QString,InternalNodePointer> m_idNodeHash; QHash<QString,InternalNodePointer> m_idNodeHash;
QHash<qint32, InternalNodePointer> m_internalIdNodeHash; QHash<qint32, InternalNodePointer> m_internalIdNodeHash;

View File

@@ -0,0 +1,77 @@
// Copyright (C) 2023 The Qt Company Ltd.
// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0
#pragma once
#include <iterator>
namespace QmlDesigner {
template<typename BaseIterator, typename Increment>
class SkipIterator
{
public:
using iterator_category = std::forward_iterator_tag;
using difference_type = qsizetype;
using value_type = typename BaseIterator::value_type;
using pointer = typename BaseIterator::pointer;
using reference = typename BaseIterator::reference;
SkipIterator() = default;
SkipIterator(BaseIterator current, Increment increment)
: m_current{current}
, m_increment{std::move(increment)}
{}
SkipIterator operator++()
{
m_current = m_increment(m_current);
return *this;
}
SkipIterator operator++(int)
{
auto tmp = *this;
m_current = m_increment(m_current);
return tmp;
}
reference operator*() const { return *m_current; }
pointer operator->() const { return m_current.operator->(); }
friend bool operator==(const SkipIterator &first, const SkipIterator &second)
{
return first.m_current == second.m_current;
}
friend bool operator!=(const SkipIterator &first, const SkipIterator &second)
{
return first.m_current != second.m_current;
}
private:
BaseIterator m_current = {};
Increment m_increment;
};
template<typename Container, typename Increment>
class SkipRange
{
public:
using container = Container;
using base = SkipRange<Container, Increment>;
using iterator = SkipIterator<typename Container::const_iterator, Increment>;
SkipRange(const Container &container, Increment increment)
: m_begin{container.begin(), increment}
, m_end{container.end(), increment}
{}
iterator begin() const { return m_begin; }
iterator end() const { return m_end; }
private:
iterator m_begin;
iterator m_end;
};
} // namespace QmlDesigner