summaryrefslogtreecommitdiffstats
path: root/src/controls/qtmenu.cpp
diff options
context:
space:
mode:
authorGabriel de Dietrich <gabriel.dedietrich@digia.com>2013-03-12 17:15:02 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-03-13 15:33:53 +0100
commit8cc52b9d1e2638f0636f2817dffeccd623063718 (patch)
tree0498fe65c48bbd4383b68315cecc4ec4efe6cb47 /src/controls/qtmenu.cpp
parent15c57038d9ac4720f4bc4b476d978a3824ed71ab (diff)
Menu: Remove 'model' property, ContextMenu
In the near future, we hope that QML types like Creator/Instantiator (currently under review) will help simplify model binding, and object creation and deletion. Also, given the differences between QML models and QAbstractItemModel APIs, it's hard to provide a unified and elegant solution for this right now. ComboBox gets the part of the logic that ContextMenu was responsible for, extended to support string list and number models. Auto-tests updated and XFAIL removed where applicable. Change-Id: I9f5d4059644c495bffff76fb7c353e6fe7fde62e Reviewed-by: Frederik Gladhorn <frederik.gladhorn@digia.com>
Diffstat (limited to 'src/controls/qtmenu.cpp')
-rw-r--r--src/controls/qtmenu.cpp249
1 files changed, 183 insertions, 66 deletions
diff --git a/src/controls/qtmenu.cpp b/src/controls/qtmenu.cpp
index 1dbc64e44..bed3d6ab7 100644
--- a/src/controls/qtmenu.cpp
+++ b/src/controls/qtmenu.cpp
@@ -40,6 +40,7 @@
****************************************************************************/
#include "qtmenu_p.h"
+#include "qtmenuitemcontainer_p.h"
#include "qtaction_p.h"
#include "qtmenupopupwindow_p.h"
@@ -133,14 +134,14 @@ QT_BEGIN_NAMESPACE
QtMenu::QtMenu(QObject *parent)
: QtMenuText(parent),
+ m_itemsCount(0),
m_selectedIndex(-1),
- m_highlightedIndex(0),
m_parentWindow(0),
- m_hasNativeModel(false),
m_minimumWidth(0),
m_popupWindow(0),
m_menuContentItem(0),
- m_popupVisible(false)
+ m_popupVisible(false),
+ m_containersCount(0)
{
connect(this, SIGNAL(__textChanged()), this, SIGNAL(titleChanged()));
@@ -155,6 +156,7 @@ QtMenu::QtMenu(QObject *parent)
QtMenu::~QtMenu()
{
delete m_platformMenu;
+ m_platformMenu = 0;
}
void QtMenu::updateText()
@@ -191,15 +193,15 @@ void QtMenu::setSelectedIndex(int index)
void QtMenu::updateSelectedIndex()
{
- if (QtMenuBase *menuItem = qobject_cast<QtMenuItem*>(sender())) {
- int index = m_menuItems.indexOf(menuItem);
+ if (QtMenuItem *menuItem = qobject_cast<QtMenuItem*>(sender())) {
+ int index = indexOfMenuItem(menuItem);
setSelectedIndex(index);
}
}
-QQmlListProperty<QtMenuBase> QtMenu::menuItems()
+QtMenuItems QtMenu::menuItems()
{
- return QQmlListProperty<QtMenuBase>(this, 0, &QtMenu::append_menuItems, &QtMenu::count_menuItems, &QtMenu::at_menuItems, 0);
+ return QtMenuItems(this, 0, &QtMenu::append_menuItems, &QtMenu::count_menuItems, &QtMenu::at_menuItems, 0);
}
QQuickWindow *QtMenu::findParentWindow()
@@ -228,12 +230,7 @@ void QtMenu::__popup(qreal x, qreal y, int atItemIndex)
setPopupVisible(true);
- // If atItemIndex is valid, x and y is specified from the
- // the position of the corresponding QtMenuItem:
- QtMenuItem *atItem = 0;
- if (atItemIndex >= 0)
- while (!atItem && atItemIndex < m_menuItems.size())
- atItem = qobject_cast<QtMenuItem *>(m_menuItems[atItemIndex++]);
+ QtMenuBase *atItem = menuItemAtIndex(atItemIndex);
QQuickWindow *parentWindow = findParentWindow();
@@ -324,91 +321,211 @@ void QtMenu::windowVisibleChanged(bool v)
}
}
-void QtMenu::clear()
+void QtMenu::itemIndexToListIndex(int itemIndex, int *listIndex, int *containerIndex) const
+{
+ *listIndex = -1;
+ QtMenuItemContainer *container = 0;
+ while (itemIndex >= 0 && ++*listIndex < m_menuItems.count())
+ if ((container = qobject_cast<QtMenuItemContainer *>(m_menuItems[*listIndex])))
+ itemIndex -= container->items().count();
+ else
+ --itemIndex;
+
+ if (container)
+ *containerIndex = container->items().count() + itemIndex;
+ else
+ *containerIndex = -1;
+}
+
+int QtMenu::itemIndexForListIndex(int listIndex) const
+{
+ int index = 0;
+ int i = 0;
+ while (i < listIndex && i < m_menuItems.count())
+ if (QtMenuItemContainer *container = qobject_cast<QtMenuItemContainer *>(m_menuItems[i++]))
+ index += container->items().count();
+ else
+ ++index;
+
+ return index;
+}
+
+QtMenuBase *QtMenu::nextMenuItem(QtMenu::MenuItemIterator *it) const
{
- foreach (QtMenuBase *item, m_menuItems) {
- if (m_platformMenu)
- m_platformMenu->removeMenuItem(item->platformItem());
- delete item;
+ if (it->containerIndex != -1) {
+ QtMenuItemContainer *container = qobject_cast<QtMenuItemContainer *>(m_menuItems[it->index]);
+ if (++it->containerIndex < container->items().count())
+ return container->items()[it->containerIndex];
}
- m_menuItems.clear();
+
+ if (++it->index < m_menuItems.count()) {
+ if (QtMenuItemContainer *container = qobject_cast<QtMenuItemContainer *>(m_menuItems[it->index])) {
+ it->containerIndex = 0;
+ return container->items()[0];
+ } else {
+ it->containerIndex = -1;
+ return m_menuItems[it->index];
+ }
+ }
+
+ return 0;
}
-void QtMenu::addMenuItem(QtMenuBase *menuItem)
+QtMenuBase *QtMenu::menuItemAtIndex(int index) const
{
- menuItem->setParentMenu(this);
- m_menuItems.append(menuItem);
- if (QPlatformMenuItem *platformItem = menuItem->platformItem()) {
- if (m_platformMenu)
- m_platformMenu->insertMenuItem(platformItem, 0 /* append */);
+ if (0 <= index && index < m_itemsCount) {
+ if (!m_containersCount) {
+ return m_menuItems[index];
+ } else if (m_containersCount == 1 && m_menuItems.count() == 1) {
+ QtMenuItemContainer *container = qobject_cast<QtMenuItemContainer *>(m_menuItems[0]);
+ return container->items()[index];
+ } else {
+ int containerIndex;
+ int i;
+ itemIndexToListIndex(index, &i, &containerIndex);
+ if (containerIndex != -1) {
+ QtMenuItemContainer *container = qobject_cast<QtMenuItemContainer *>(m_menuItems[i]);
+ return container->items()[containerIndex];
+ } else {
+ return m_menuItems[i];
+ }
+ }
}
+
+ return 0;
}
-QtMenuItem *QtMenu::addItem(const QString &text)
+bool QtMenu::contains(QtMenuBase *item)
{
- QtMenuItem *menuItem = new QtMenuItem(this);
- menuItem->setText(text);
- addMenuItem(menuItem);
+ if (item->container())
+ return item->container()->items().contains(item);
- emit itemsChanged();
- return menuItem;
+ return m_menuItems.contains(item);
}
-QString QtMenu::__modelTextAt(int index) const
+int QtMenu::indexOfMenuItem(QtMenuBase *item) const
{
- if (QAbstractItemModel *model = qobject_cast<QAbstractItemModel*>(m_model.value<QObject*>())) {
- return model->data(model->index(index, 0)).toString();
- } else if (m_model.canConvert(QVariant::StringList)) {
- return m_model.toStringList().at(index);
+ if (!item)
+ return -1;
+ if (item->container()) {
+ int containerIndex = m_menuItems.indexOf(item->container());
+ if (containerIndex == -1)
+ return -1;
+ int index = item->container()->items().indexOf(item);
+ return index == -1 ? -1 : itemIndexForListIndex(containerIndex) + index;
+ } else {
+ int index = m_menuItems.indexOf(item);
+ return index == -1 ? -1 : itemIndexForListIndex(index);
}
- return "";
}
-int QtMenu::__modelCount() const
+QtMenuItem *QtMenu::addItem(QString title)
{
- if (QAbstractItemModel *model = qobject_cast<QAbstractItemModel*>(m_model.value<QObject*>())) {
- return model->rowCount();
- } else if (m_model.canConvert(QVariant::StringList)) {
- return m_model.toStringList().count();
+ QtMenuItem *item = new QtMenuItem(this);
+ item->setText(title);
+ insertItem(m_itemsCount, item);
+ return item;
+}
+
+void QtMenu::insertItem(int index, QtMenuBase *menuItem)
+{
+ if (!menuItem)
+ return;
+ int itemIndex;
+ if (m_containersCount) {
+ QtMenuItemContainer *container = menuItem->parent() != this ? m_containers[menuItem->parent()] : 0;
+ if (container) {
+ container->insertItem(index, menuItem);
+ itemIndex = itemIndexForListIndex(m_menuItems.indexOf(container)) + index;
+ } else {
+ itemIndex = itemIndexForListIndex(index);
+ m_menuItems.insert(itemIndex, menuItem);
+ }
+ } else {
+ itemIndex = index;
+ m_menuItems.insert(index, menuItem);
}
- return -1;
+
+ setupMenuItem(menuItem, itemIndex);
+ emit itemsChanged();
}
-void QtMenu::append_menuItems(QQmlListProperty<QtMenuBase> *list, QtMenuBase *menuItem)
+void QtMenu::removeItem(QtMenuBase *menuItem)
{
- if (QtMenu *menu = qobject_cast<QtMenu *>(list->object))
- menu->addMenuItem(menuItem);
+ if (!menuItem)
+ return;
+ menuItem->setParentMenu(0);
+
+ QtMenuItemContainer *container = menuItem->parent() != this ? m_containers[menuItem->parent()] : 0;
+ if (container)
+ container->removeItem(menuItem);
+ else
+ m_menuItems.removeOne(menuItem);
+
+ --m_itemsCount;
+ emit itemsChanged();
}
-int QtMenu::count_menuItems(QQmlListProperty<QtMenuBase> *list)
+void QtMenu::clear()
{
- QtMenu *menu = qobject_cast<QtMenu *>(list->object);
- if (menu)
- return menu->m_menuItems.size();
- return 0;
+ m_containers.clear();
+ m_containersCount = 0;
+
+ while (!m_menuItems.empty())
+ delete m_menuItems.takeFirst();
+ m_itemsCount = 0;
}
-QtMenuBase *QtMenu::at_menuItems(QQmlListProperty<QtMenuBase> *list, int index)
+void QtMenu::setupMenuItem(QtMenuBase *item, int platformIndex)
{
- QtMenu *menu = qobject_cast<QtMenu *>(list->object);
- if (menu && 0 <= index && index < menu->m_menuItems.size())
- return menu->m_menuItems[index];
- return 0;
+ item->setParentMenu(this);
+ if (m_platformMenu) {
+ QPlatformMenuItem *before = 0;
+ if (platformIndex != -1)
+ before = m_platformMenu->menuItemAt(platformIndex);
+ m_platformMenu->insertMenuItem(item->platformItem(), before);
+ }
+ ++m_itemsCount;
}
+void QtMenu::append_menuItems(QtMenuItems *list, QObject *o)
+{
+ if (QtMenu *menu = qobject_cast<QtMenu *>(list->object)) {
+ Q_ASSERT(o->parent() == menu);
+
+ if (QtMenuBase *menuItem = qobject_cast<QtMenuBase *>(o)) {
+ menu->m_menuItems.append(menuItem);
+ menu->setupMenuItem(menuItem);
+ } else {
+ QtMenuItemContainer *menuItemContainer = new QtMenuItemContainer(menu);
+ menu->m_menuItems.append(menuItemContainer);
+ menu->m_containers.insert(o, menuItemContainer);
+ menuItemContainer->setParentMenu(menu);
+ ++menu->m_containersCount;
+ foreach (QObject *child, o->children()) {
+ if (QtMenuBase *item = qobject_cast<QtMenuBase *>(child)) {
+ menuItemContainer->insertItem(-1, item);
+ menu->setupMenuItem(item);
+ }
+ }
+ }
+ }
+}
+
+int QtMenu::count_menuItems(QtMenuItems *list)
+{
+ if (QtMenu *menu = qobject_cast<QtMenu *>(list->object))
+ return menu->m_itemsCount;
-void QtMenu::setModel(const QVariant &newModel) {
- if (m_model != newModel) {
- m_hasNativeModel = false;
- m_model = newModel;
+ return 0;
+}
- if (qobject_cast<QAbstractItemModel*>(newModel.value<QObject*>()))
- m_hasNativeModel = true;
- else if (newModel.canConvert(QVariant::StringList))
- m_hasNativeModel = true;
+QObject *QtMenu::at_menuItems(QtMenuItems *list, int index)
+{
+ if (QtMenu *menu = qobject_cast<QtMenu *>(list->object))
+ return menu->menuItemAtIndex(index);
- emit modelChanged(m_model);
- }
+ return 0;
}
QT_END_NAMESPACE