From 15ac92ca2c3a0bfb66288fd270b61891569a9016 Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Sat, 1 Dec 2012 17:37:46 -0300 Subject: QMenuModel now keeps cache of any link element. --- libqmenumodel/src/qmenumodel.cpp | 69 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 63 insertions(+), 6 deletions(-) (limited to 'libqmenumodel/src/qmenumodel.cpp') diff --git a/libqmenumodel/src/qmenumodel.cpp b/libqmenumodel/src/qmenumodel.cpp index 53dc966..b18cc45 100644 --- a/libqmenumodel/src/qmenumodel.cpp +++ b/libqmenumodel/src/qmenumodel.cpp @@ -26,6 +26,24 @@ extern "C" { #include +class CacheData +{ +public: + CacheData(QMenuModel *link, int pos) + : link(link), + pos(pos) + { + } + + ~CacheData() + { + delete link; + } + + QMenuModel *link; + int pos; +}; + /*! \qmltype QMenuModel \brief The QMenuModel class implements the base list model for menus @@ -131,10 +149,10 @@ void QMenuModel::clearModel() m_menuModel = NULL; } - QList list = findChildren(QString(), Qt::FindDirectChildrenOnly); - Q_FOREACH(QMenuModel *model, list) { - delete model; + Q_FOREACH(CacheData *data, m_cache) { + delete data; } + m_cache.clear(); } /*! \internal */ @@ -226,8 +244,23 @@ QVariant QMenuModel::getLink(const QModelIndex &index, linkName.toUtf8().data()); if (link) { - QMenuModel *other = new QMenuModel(link, const_cast(this)); - return QVariant::fromValue(other); + QMenuModel *result = 0; + Q_FOREACH(CacheData *cache, m_cache) { + if ((cache->link->menuModel() == link) && + (cache->pos == index.row())) { + result = cache->link; + break; + } + } + + if (result == 0) { + QMenuModel *self = const_cast(this); + result = new QMenuModel(link, self); + self->m_cache << new CacheData(result, index.row()); + } + + g_object_unref(link); + return QVariant::fromValue(result); } return QVariant(); @@ -265,7 +298,13 @@ QVariant QMenuModel::getExtraProperties(const QModelIndex &index) const } /*! \internal */ -void QMenuModel::onItemsChanged(GMenuModel *, +QList QMenuModel::cache() const +{ + return m_cache; +} + +/*! \internal */ +void QMenuModel::onItemsChanged(GMenuModel *model, gint position, gint removed, gint added, @@ -275,11 +314,29 @@ void QMenuModel::onItemsChanged(GMenuModel *, if (removed > 0) { self->beginRemoveRows(QModelIndex(), position, position + removed - 1); + for(int i=position, iMax=position+removed; i < iMax; i++) { + QList lst = self->m_cache; + Q_FOREACH(CacheData* data, lst) { + if (data->pos == position) { + self->m_cache.removeOne(data); + delete data; + } else if (data->pos >= position) { + data->pos -= removed; + } + } + } self->endRemoveRows(); } if (added > 0) { self->beginInsertRows(QModelIndex(), position, position + added - 1); + for(int i=position, iMax=position+added; i < iMax; i++) { + Q_FOREACH(CacheData* data, self->m_cache) { + if (data->pos >= position) { + data->pos += added; + } + } + } self->endInsertRows(); } } -- cgit v1.2.3 From 5c529632253bb8e864b3cc81eaabbd0a423112aa Mon Sep 17 00:00:00 2001 From: Renato Araujo Oliveira Filho Date: Mon, 3 Dec 2012 09:36:59 -0300 Subject: Changed getLink function to not be const. --- libqmenumodel/src/qmenumodel.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'libqmenumodel/src/qmenumodel.cpp') diff --git a/libqmenumodel/src/qmenumodel.cpp b/libqmenumodel/src/qmenumodel.cpp index b18cc45..51b6863 100644 --- a/libqmenumodel/src/qmenumodel.cpp +++ b/libqmenumodel/src/qmenumodel.cpp @@ -185,11 +185,17 @@ QVariant QMenuModel::data(const QModelIndex &index, int role) const attribute = getStringAttribute(index, G_MENU_ATTRIBUTE_LABEL); break; case LinkSection: - attribute = getLink(index, G_MENU_LINK_SECTION); + { + QMenuModel *self = const_cast(this); + attribute = self->getLink(index, G_MENU_LINK_SECTION); break; + } case LinkSubMenu: - attribute = getLink(index, G_MENU_LINK_SUBMENU); + { + QMenuModel *self = const_cast(this); + attribute = self->getLink(index, G_MENU_LINK_SUBMENU); break; + } case Extra: attribute = getExtraProperties(index); break; @@ -235,7 +241,7 @@ QVariant QMenuModel::getStringAttribute(const QModelIndex &index, /*! \internal */ QVariant QMenuModel::getLink(const QModelIndex &index, - const QString &linkName) const + const QString &linkName) { GMenuModel *link; @@ -254,9 +260,8 @@ QVariant QMenuModel::getLink(const QModelIndex &index, } if (result == 0) { - QMenuModel *self = const_cast(this); - result = new QMenuModel(link, self); - self->m_cache << new CacheData(result, index.row()); + result = new QMenuModel(link, this); + m_cache << new CacheData(result, index.row()); } g_object_unref(link); -- cgit v1.2.3 From 2f3299465de87c5801a5016c39b0fdb129347895 Mon Sep 17 00:00:00 2001 From: Olivier Tilloy Date: Mon, 3 Dec 2012 18:52:59 +0100 Subject: Simplify the caching mechanism using a a QHash that associates indexes (int) to QMenuModel*. --- libqmenumodel/src/qmenumodel.cpp | 84 ++++++++++++++-------------------------- 1 file changed, 28 insertions(+), 56 deletions(-) (limited to 'libqmenumodel/src/qmenumodel.cpp') diff --git a/libqmenumodel/src/qmenumodel.cpp b/libqmenumodel/src/qmenumodel.cpp index 51b6863..e9ce5fc 100644 --- a/libqmenumodel/src/qmenumodel.cpp +++ b/libqmenumodel/src/qmenumodel.cpp @@ -24,26 +24,6 @@ extern "C" { #include "qmenumodel.h" #include "converter.h" -#include - -class CacheData -{ -public: - CacheData(QMenuModel *link, int pos) - : link(link), - pos(pos) - { - } - - ~CacheData() - { - delete link; - } - - QMenuModel *link; - int pos; -}; - /*! \qmltype QMenuModel \brief The QMenuModel class implements the base list model for menus @@ -149,8 +129,8 @@ void QMenuModel::clearModel() m_menuModel = NULL; } - Q_FOREACH(CacheData *data, m_cache) { - delete data; + Q_FOREACH(QMenuModel* child, m_cache) { + delete child; } m_cache.clear(); } @@ -243,31 +223,25 @@ QVariant QMenuModel::getStringAttribute(const QModelIndex &index, QVariant QMenuModel::getLink(const QModelIndex &index, const QString &linkName) { - GMenuModel *link; - - link = g_menu_model_get_item_link(m_menuModel, - index.row(), - linkName.toUtf8().data()); - + GMenuModel *link = g_menu_model_get_item_link(m_menuModel, + index.row(), + linkName.toUtf8().data()); if (link) { - QMenuModel *result = 0; - Q_FOREACH(CacheData *cache, m_cache) { - if ((cache->link->menuModel() == link) && - (cache->pos == index.row())) { - result = cache->link; - break; + QMenuModel* child = 0; + int key = index.row(); + if (m_cache.contains(key)) { + QMenuModel* cached = m_cache.value(key); + if (cached->menuModel() == link) { + child = cached; } } - - if (result == 0) { - result = new QMenuModel(link, this); - m_cache << new CacheData(result, index.row()); + if (child == 0) { + child = new QMenuModel(link, this); + m_cache.insert(key, child); } - g_object_unref(link); - return QVariant::fromValue(result); + return QVariant::fromValue(child); } - return QVariant(); } @@ -303,7 +277,7 @@ QVariant QMenuModel::getExtraProperties(const QModelIndex &index) const } /*! \internal */ -QList QMenuModel::cache() const +QHash QMenuModel::cache() const { return m_cache; } @@ -317,17 +291,17 @@ void QMenuModel::onItemsChanged(GMenuModel *model, { QMenuModel *self = reinterpret_cast(data); + int prevcount = g_menu_model_get_n_items(model) + removed - added; if (removed > 0) { self->beginRemoveRows(QModelIndex(), position, position + removed - 1); - for(int i=position, iMax=position+removed; i < iMax; i++) { - QList lst = self->m_cache; - Q_FOREACH(CacheData* data, lst) { - if (data->pos == position) { - self->m_cache.removeOne(data); - delete data; - } else if (data->pos >= position) { - data->pos -= removed; - } + for (int i = position, iMax = position + removed; i < iMax; ++i) { + if (self->m_cache.contains(i)) { + delete self->m_cache.take(i); + } + } + for (int i = position + removed; i < prevcount; ++i) { + if (self->m_cache.contains(i)) { + self->m_cache.insert(i - removed, self->m_cache.take(i)); } } self->endRemoveRows(); @@ -335,11 +309,9 @@ void QMenuModel::onItemsChanged(GMenuModel *model, if (added > 0) { self->beginInsertRows(QModelIndex(), position, position + added - 1); - for(int i=position, iMax=position+added; i < iMax; i++) { - Q_FOREACH(CacheData* data, self->m_cache) { - if (data->pos >= position) { - data->pos += added; - } + for (int i = prevcount - removed - 1; i >= position; --i) { + if (self->m_cache.contains(i)) { + self->m_cache.insert(i + added, self->m_cache.take(i)); } } self->endInsertRows(); -- cgit v1.2.3 From 7b2badf6f2c2d5d4596ca3778b4cf924d498e2d7 Mon Sep 17 00:00:00 2001 From: Olivier Tilloy Date: Tue, 4 Dec 2012 08:30:24 +0100 Subject: Make the cache a pointer, to enforce const correctness. --- libqmenumodel/src/qmenumodel.cpp | 41 +++++++++++++++++++--------------------- 1 file changed, 19 insertions(+), 22 deletions(-) (limited to 'libqmenumodel/src/qmenumodel.cpp') diff --git a/libqmenumodel/src/qmenumodel.cpp b/libqmenumodel/src/qmenumodel.cpp index e9ce5fc..524953f 100644 --- a/libqmenumodel/src/qmenumodel.cpp +++ b/libqmenumodel/src/qmenumodel.cpp @@ -39,6 +39,7 @@ QMenuModel::QMenuModel(GMenuModel *other, QObject *parent) m_menuModel(0), m_signalChangedId(0) { + m_cache = new QHash; setMenuModel(other); connect(this, SIGNAL(rowsInserted(const QModelIndex &, int, int)), SIGNAL(countChanged())); @@ -50,6 +51,7 @@ QMenuModel::QMenuModel(GMenuModel *other, QObject *parent) QMenuModel::~QMenuModel() { clearModel(); + delete m_cache; } /*! @@ -129,10 +131,10 @@ void QMenuModel::clearModel() m_menuModel = NULL; } - Q_FOREACH(QMenuModel* child, m_cache) { + Q_FOREACH(QMenuModel* child, *m_cache) { delete child; } - m_cache.clear(); + m_cache->clear(); } /*! \internal */ @@ -165,17 +167,11 @@ QVariant QMenuModel::data(const QModelIndex &index, int role) const attribute = getStringAttribute(index, G_MENU_ATTRIBUTE_LABEL); break; case LinkSection: - { - QMenuModel *self = const_cast(this); - attribute = self->getLink(index, G_MENU_LINK_SECTION); + attribute = getLink(index, G_MENU_LINK_SECTION); break; - } case LinkSubMenu: - { - QMenuModel *self = const_cast(this); - attribute = self->getLink(index, G_MENU_LINK_SUBMENU); + attribute = getLink(index, G_MENU_LINK_SUBMENU); break; - } case Extra: attribute = getExtraProperties(index); break; @@ -221,7 +217,7 @@ QVariant QMenuModel::getStringAttribute(const QModelIndex &index, /*! \internal */ QVariant QMenuModel::getLink(const QModelIndex &index, - const QString &linkName) + const QString &linkName) const { GMenuModel *link = g_menu_model_get_item_link(m_menuModel, index.row(), @@ -229,15 +225,15 @@ QVariant QMenuModel::getLink(const QModelIndex &index, if (link) { QMenuModel* child = 0; int key = index.row(); - if (m_cache.contains(key)) { - QMenuModel* cached = m_cache.value(key); + if (m_cache->contains(key)) { + QMenuModel* cached = m_cache->value(key); if (cached->menuModel() == link) { child = cached; } } if (child == 0) { - child = new QMenuModel(link, this); - m_cache.insert(key, child); + child = new QMenuModel(link); + m_cache->insert(key, child); } g_object_unref(link); return QVariant::fromValue(child); @@ -279,7 +275,7 @@ QVariant QMenuModel::getExtraProperties(const QModelIndex &index) const /*! \internal */ QHash QMenuModel::cache() const { - return m_cache; + return *m_cache; } /*! \internal */ @@ -290,18 +286,19 @@ void QMenuModel::onItemsChanged(GMenuModel *model, gpointer data) { QMenuModel *self = reinterpret_cast(data); + QHash* cache = self->m_cache; int prevcount = g_menu_model_get_n_items(model) + removed - added; if (removed > 0) { self->beginRemoveRows(QModelIndex(), position, position + removed - 1); for (int i = position, iMax = position + removed; i < iMax; ++i) { - if (self->m_cache.contains(i)) { - delete self->m_cache.take(i); + if (cache->contains(i)) { + delete cache->take(i); } } for (int i = position + removed; i < prevcount; ++i) { - if (self->m_cache.contains(i)) { - self->m_cache.insert(i - removed, self->m_cache.take(i)); + if (cache->contains(i)) { + cache->insert(i - removed, cache->take(i)); } } self->endRemoveRows(); @@ -310,8 +307,8 @@ void QMenuModel::onItemsChanged(GMenuModel *model, if (added > 0) { self->beginInsertRows(QModelIndex(), position, position + added - 1); for (int i = prevcount - removed - 1; i >= position; --i) { - if (self->m_cache.contains(i)) { - self->m_cache.insert(i + added, self->m_cache.take(i)); + if (cache->contains(i)) { + cache->insert(i + added, cache->take(i)); } } self->endInsertRows(); -- cgit v1.2.3 From 517c21c4f3b4ff3e4e07b0e0f9cc41c3cefccba7 Mon Sep 17 00:00:00 2001 From: Olivier Tilloy Date: Tue, 4 Dec 2012 08:32:13 +0100 Subject: Add myself to the list of authors. --- libqmenumodel/src/qmenumodel.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'libqmenumodel/src/qmenumodel.cpp') diff --git a/libqmenumodel/src/qmenumodel.cpp b/libqmenumodel/src/qmenumodel.cpp index 524953f..e9f6acc 100644 --- a/libqmenumodel/src/qmenumodel.cpp +++ b/libqmenumodel/src/qmenumodel.cpp @@ -15,6 +15,7 @@ * * Authors: * Renato Araujo Oliveira Filho + * Olivier Tilloy */ extern "C" { -- cgit v1.2.3 From 395a8c64acee78f206b021b3218de4641c4d95d6 Mon Sep 17 00:00:00 2001 From: Olivier Tilloy Date: Tue, 4 Dec 2012 09:21:06 +0100 Subject: Add comments to explain non-trivial cache updates. --- libqmenumodel/src/qmenumodel.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'libqmenumodel/src/qmenumodel.cpp') diff --git a/libqmenumodel/src/qmenumodel.cpp b/libqmenumodel/src/qmenumodel.cpp index e9f6acc..1326d77 100644 --- a/libqmenumodel/src/qmenumodel.cpp +++ b/libqmenumodel/src/qmenumodel.cpp @@ -292,11 +292,13 @@ void QMenuModel::onItemsChanged(GMenuModel *model, int prevcount = g_menu_model_get_n_items(model) + removed - added; if (removed > 0) { self->beginRemoveRows(QModelIndex(), position, position + removed - 1); + // Remove invalidated menus from the cache for (int i = position, iMax = position + removed; i < iMax; ++i) { if (cache->contains(i)) { delete cache->take(i); } } + // Update the indexes of other cached menus to account for the removals for (int i = position + removed; i < prevcount; ++i) { if (cache->contains(i)) { cache->insert(i - removed, cache->take(i)); @@ -307,6 +309,7 @@ void QMenuModel::onItemsChanged(GMenuModel *model, if (added > 0) { self->beginInsertRows(QModelIndex(), position, position + added - 1); + // Update the indexes of cached menus to account for the insertions for (int i = prevcount - removed - 1; i >= position; --i) { if (cache->contains(i)) { cache->insert(i + added, cache->take(i)); -- cgit v1.2.3