aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libqmenumodel/src/qmenumodel.cpp69
-rw-r--r--libqmenumodel/src/qmenumodel.h6
-rw-r--r--tests/client/CMakeLists.txt1
-rw-r--r--tests/client/cachetest.cpp175
4 files changed, 245 insertions, 6 deletions
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 <QDebug>
+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<QMenuModel*> list = findChildren<QMenuModel*>(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<QMenuModel*>(this));
- return QVariant::fromValue<QObject*>(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<QMenuModel*>(this);
+ result = new QMenuModel(link, self);
+ self->m_cache << new CacheData(result, index.row());
+ }
+
+ g_object_unref(link);
+ return QVariant::fromValue<QObject*>(result);
}
return QVariant();
@@ -265,7 +298,13 @@ QVariant QMenuModel::getExtraProperties(const QModelIndex &index) const
}
/*! \internal */
-void QMenuModel::onItemsChanged(GMenuModel *,
+QList<CacheData*> 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<CacheData*> 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();
}
}
diff --git a/libqmenumodel/src/qmenumodel.h b/libqmenumodel/src/qmenumodel.h
index 9371bd8..de49368 100644
--- a/libqmenumodel/src/qmenumodel.h
+++ b/libqmenumodel/src/qmenumodel.h
@@ -28,6 +28,8 @@ typedef void* gpointer;
typedef struct _GMenuModel GMenuModel;
typedef struct _GObject GObject;
+class CacheData;
+
class QMenuModel : public QAbstractListModel
{
Q_OBJECT
@@ -60,7 +62,11 @@ protected:
void setMenuModel(GMenuModel *model);
GMenuModel *menuModel() const;
+ // help function for test
+ QList<CacheData*> cache() const;
+
private:
+ QList<CacheData*> m_cache;
GMenuModel *m_menuModel;
guint m_signalChangedId;
diff --git a/tests/client/CMakeLists.txt b/tests/client/CMakeLists.txt
index 392437c..0fcac9e 100644
--- a/tests/client/CMakeLists.txt
+++ b/tests/client/CMakeLists.txt
@@ -58,6 +58,7 @@ declare_test(modeltest)
declare_test(actiongrouptest)
declare_test(qmltest)
declare_simple_test(convertertest)
+declare_simple_test(cachetest)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/qmlfiles.h.in
${CMAKE_CURRENT_BINARY_DIR}/qmlfiles.h)
diff --git a/tests/client/cachetest.cpp b/tests/client/cachetest.cpp
new file mode 100644
index 0000000..16b3a6a
--- /dev/null
+++ b/tests/client/cachetest.cpp
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2012 Canonical Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation; version 3.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors:
+ * Renato Araujo Oliveira Filho <renato@canonical.com>
+ */
+
+#include "qmenumodel.h"
+
+extern "C" {
+#include <gio/gio.h>
+}
+
+#include <QtTest>
+#include <QDebug>
+
+
+class MenuModelTestClass : public QMenuModel
+{
+ Q_OBJECT
+public:
+ MenuModelTestClass()
+ : QMenuModel(0)
+ {
+ }
+
+ void loadMenu()
+ {
+ GMenu *menu3 = g_menu_new();
+ g_menu_append(menu3, "menu4", NULL);
+ g_menu_append(menu3, "menu5", NULL);
+ g_menu_append(menu3, "menu6", NULL);
+
+ GMenu *menu = g_menu_new();
+ g_menu_append(menu, "menu0", NULL);
+ g_menu_append(menu, "menu1", NULL);
+ g_menu_append(menu, "menu2", NULL);
+ g_menu_append_section(menu, "menu3", G_MENU_MODEL(menu3));
+
+ setMenuModel(G_MENU_MODEL(menu));
+
+ m_menus << menu << menu3;
+ }
+
+ void removeItem(int section, int index)
+ {
+ GMenu *menu = m_menus[section];
+ g_menu_remove(menu, index);
+ }
+
+ void insertItem(int section, int index, const QString &label)
+ {
+ GMenu *menu = m_menus[section];
+ g_menu_insert(menu, index, label.toUtf8().data(), NULL);
+ }
+
+ int cacheSize() const
+ {
+ return cache().size();
+ }
+
+private:
+ QList<GMenu*> m_menus;
+};
+
+class CacheTest : public QObject
+{
+ Q_OBJECT
+private Q_SLOTS:
+ void initTestCase()
+ {
+ g_type_init();
+ }
+
+ //
+ // Test if the link property always returns the same element
+ //
+ void testStaticMenuCache()
+ {
+ MenuModelTestClass menu;
+ menu.loadMenu();
+
+ QModelIndex index = menu.index(3);
+
+ QVariant data = menu.data(index, QMenuModel::LinkSection);
+ QCOMPARE(menu.cacheSize(), 1);
+
+ QVariant data2 = menu.data(index, QMenuModel::LinkSection);
+ QCOMPARE(menu.cacheSize(), 1);
+
+ QVERIFY(data.value<QObject*>() == data2.value<QObject*>());
+
+ QMenuModel *section = qvariant_cast<QMenuModel*>(data);
+
+ index = section->index(1);
+ data = menu.data(index, QMenuModel::LinkSection);
+ data2 = menu.data(index, QMenuModel::LinkSection);
+ QVERIFY(data.value<QObject*>() == data2.value<QObject*>());
+ }
+
+
+ //
+ // Test if cache works after add a new item
+ //
+ void testAddItem()
+ {
+ MenuModelTestClass menu;
+ menu.loadMenu();
+
+ QModelIndex index = menu.index(3);
+ QVariant data = menu.data(index, QMenuModel::LinkSection);
+
+ menu.insertItem(0, 1, "newMenu");
+
+ index = menu.index(4);
+ QVariant data2 = menu.data(index, QMenuModel::LinkSection);
+
+ QCOMPARE(menu.cacheSize(), 1);
+ QVERIFY(data.value<QObject*>() == data2.value<QObject*>());
+ }
+
+
+ //
+ // Test if cache works after remove a item
+ //
+ void testRemoveItem()
+ {
+ MenuModelTestClass menu;
+ menu.loadMenu();
+
+ QModelIndex index = menu.index(3);
+ QVariant data = menu.data(index, QMenuModel::LinkSection);
+
+ menu.removeItem(0, 1);
+
+ index = menu.index(2);
+ QVariant data2 = menu.data(index, QMenuModel::LinkSection);
+
+ QCOMPARE(menu.cacheSize(), 1);
+ QVERIFY(data.value<QObject*>() == data2.value<QObject*>());
+ }
+
+ //
+ // Test if cached item is removed after removed from the menu
+ //
+ void testRemoveCachedItem()
+ {
+ MenuModelTestClass menu;
+ menu.loadMenu();
+
+ QModelIndex index = menu.index(3);
+ QVariant data = menu.data(index, QMenuModel::LinkSection);
+
+ QCOMPARE(menu.cacheSize(), 1);
+ menu.removeItem(0, 3);
+ QCOMPARE(menu.cacheSize(), 0);
+ }
+};
+
+QTEST_MAIN(CacheTest)
+
+#include "cachetest.moc"
+