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
rewriterview.cpp
signalhandlerproperty.cpp
skipiterator.h
stylesheetmerger.cpp
textmodifier.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)
{
setModel(model);
if (model)
model->d->updateEnabledViews();
}
/*!
@@ -617,9 +614,6 @@ bool AbstractView::isEnabled() const
void AbstractView::setEnabled(bool b)
{
m_enabled = b;
if (model())
model()->d->updateEnabledViews();
}
QList<ModelNode> AbstractView::allModelNodes() const

View File

@@ -96,7 +96,6 @@ void ModelPrivate::detachAllViews()
detachView(view.data(), true);
m_viewList.clear();
updateEnabledViews();
if (m_nodeInstanceView) {
m_nodeInstanceView->modelAboutToBeDetached(m_model);
@@ -299,9 +298,9 @@ void ModelPrivate::removeNodeFromModel(const InternalNodePointer &node)
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)
@@ -754,7 +753,6 @@ void ModelPrivate::detachView(AbstractView *view, bool notifyView)
if (notifyView)
view->modelAboutToBeDetached(m_model);
m_viewList.removeOne(view);
updateEnabledViews();
}
void ModelPrivate::notifyNodeCreated(const InternalNodePointer &newInternalNodePointer)
@@ -1317,13 +1315,6 @@ InternalNodePointer ModelPrivate::currentTimelineNode() const
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
{
return m_idNodeHash.value(id);

View File

@@ -3,17 +3,20 @@
#pragma once
#include "qmldesignercorelib_global.h"
#include "abstractview.h"
#include "metainfo.h"
#include "modelnode.h"
#include "skipiterator.h"
#include <QList>
#include <QPointer>
#include <QSet>
#include <QUrl>
#include <QVector3D>
#include "modelnode.h"
#include "abstractview.h"
#include "metainfo.h"
#include "qmldesignercorelib_global.h"
#include <algorithm>
QT_BEGIN_NAMESPACE
class QPlainTextEdit;
@@ -64,7 +67,28 @@ private:
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
friend Model;
@@ -249,8 +273,6 @@ public:
InternalNodePointer currentStateNode() const;
InternalNodePointer currentTimelineNode() const;
void updateEnabledViews();
private:
void removePropertyWithoutNotification(const InternalPropertyPointer &property);
void removeAllSubNodes(const InternalNodePointer &node);
@@ -259,7 +281,7 @@ private:
QList<ModelNode> toModelNodeList(const QList<InternalNodePointer> &nodeList, AbstractView *view) const;
QVector<ModelNode> toModelNodeVector(const QVector<InternalNodePointer> &nodeVector, AbstractView *view) const;
QVector<InternalNodePointer> toInternalNodeVector(const QVector<ModelNode> &modelNodeVector) const;
const QList<QPointer<AbstractView>> enabledViews() const;
EnabledViewRange enabledViews() const;
public:
NotNullPointer<ProjectStorageType> projectStorage = nullptr;
@@ -271,7 +293,6 @@ private:
Imports m_possibleImportList;
Imports m_usedImportList;
QList<QPointer<AbstractView>> m_viewList;
QList<QPointer<AbstractView>> m_enabledViewList;
QList<InternalNodePointer> m_selectedInternalNodeList;
QHash<QString,InternalNodePointer> m_idNodeHash;
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