summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/controls/Menu.qml28
-rw-r--r--src/controls/plugin.cpp2
-rw-r--r--src/controls/qtmenu.cpp39
-rw-r--r--src/controls/qtmenu_p.h2
-rw-r--r--src/controls/qtmenuitem_p.h17
-rw-r--r--src/controls/qtmenuitemcontainer_p.h10
-rw-r--r--src/private/qstyleitem.cpp2
-rw-r--r--src/styles/Desktop/MenuStyle.qml2
-rw-r--r--src/styles/MenuStyle.qml2
-rw-r--r--tests/auto/controls/data/tst_menu.qml43
10 files changed, 129 insertions, 18 deletions
diff --git a/src/controls/Menu.qml b/src/controls/Menu.qml
index 9ee03e46f..6ac930ef2 100644
--- a/src/controls/Menu.qml
+++ b/src/controls/Menu.qml
@@ -103,6 +103,20 @@ import "Styles/Settings.js" as Settings
MenuPrivate {
id: root
+ /*!
+ Adds a submenu to the menu. Returns the newly created \l Menu.
+ */
+ function addMenu(title) {
+ if (!__selfComponent)
+ __selfComponent = Qt.createComponent("Menu.qml", root)
+ var submenu = __selfComponent.createObject(__selfComponent, { "title": title })
+ root.insertItem(items.length, submenu)
+ return submenu
+ }
+
+ /*! internal */
+ property Component __selfComponent: null
+
/*! \internal */
property Component style: Qt.createComponent(Settings.THEME_PATH + "/MenuStyle.qml", root)
@@ -183,7 +197,7 @@ MenuPrivate {
Keys.onRightPressed: {
var item = itemsRepeater.itemAt(root.__currentIndex)
- if (item && item.hasSubmenu) {
+ if (item && item.isSubmenu) {
item.showSubMenu(true)
item.menuItem.__currentIndex = 0
}
@@ -197,7 +211,7 @@ MenuPrivate {
var item = itemsRepeater.itemAt(root.__currentIndex)
if (item && !item.isSeparator) {
root.__dismissMenu()
- if (!item.hasSubmenu)
+ if (!item.isSubmenu)
item.menuItem.trigger()
}
}
@@ -229,12 +243,12 @@ MenuPrivate {
function updateCurrentItem(mouse) {
var pos = mapToItem(column, mouse.x, mouse.y)
if (!currentItem || !currentItem.contains(Qt.point(pos.x - currentItem.x, pos.y - currentItem.y))) {
- if (currentItem && !pressed && currentItem.hasSubmenu)
+ if (currentItem && !pressed && currentItem.isSubmenu)
currentItem.closeSubMenu()
currentItem = column.childAt(pos.x, pos.y)
if (currentItem) {
root.__currentIndex = currentItem.menuItemIndex
- if (currentItem.hasSubmenu && !currentItem.menuItem.__popupVisible)
+ if (currentItem.isSubmenu && !currentItem.menuItem.__popupVisible)
currentItem.showSubMenu(false)
} else {
root.__currentIndex = -1
@@ -255,10 +269,10 @@ MenuPrivate {
id: menuItemLoader
property var menuItem: modelData
- property bool isSeparator: menuItem ? !menuItem.hasOwnProperty("enabled") : true
- property bool hasSubmenu: menuItem ? !!menuItem["items"] : false
+ readonly property bool isSeparator: !!menuItem && menuItem.type === MenuItemType.Separator
+ readonly property bool isSubmenu: !!menuItem && menuItem.type === MenuItemType.Menu
property bool selected: !isSeparator && root.__currentIndex === index
- property string text: hasSubmenu ? menuItem.title : !isSeparator ? menuItem.text : ""
+ property string text: isSubmenu ? menuItem.title : !isSeparator ? menuItem.text : ""
property int menuItemIndex: index
diff --git a/src/controls/plugin.cpp b/src/controls/plugin.cpp
index b7dd36cd3..50c8fe69c 100644
--- a/src/controls/plugin.cpp
+++ b/src/controls/plugin.cpp
@@ -82,6 +82,8 @@ void StylePlugin::registerTypes(const char *uri)
qmlRegisterType<QtMenu>(uri, 1, 0, "MenuPrivate");
qmlRegisterType<QtMenuBar>(uri, 1, 0, "MenuBarPrivate");
qmlRegisterType<QtMenuItem>(uri, 1, 0, "MenuItem");
+ qmlRegisterUncreatableType<QtMenuItemType>(uri, 1, 0, "MenuItemType",
+ QLatin1String("Do not create objects of type MenuItemType"));
qmlRegisterType<QtMenuSeparator>(uri, 1, 0, "MenuSeparator");
qmlRegisterUncreatableType<QtMenuBase>(uri, 1, 0, "MenuBase",
QLatin1String("Do not create objects of type MenuBase"));
diff --git a/src/controls/qtmenu.cpp b/src/controls/qtmenu.cpp
index 150efcee1..dbcbe1137 100644
--- a/src/controls/qtmenu.cpp
+++ b/src/controls/qtmenu.cpp
@@ -123,6 +123,38 @@ QT_BEGIN_NAMESPACE
*/
/*!
+ \qmlmethod MenuItem Menu::addItem(text)
+
+ Adds an item to the menu. Returns the newly created \l MenuItem.
+*/
+
+/*!
+ \qmlmethod MenuSeparator Menu::addSeparator()
+
+ Adds a separator to the menu. Returns the newly created \l MenuSeparator.
+*/
+
+/*!
+ \qmlmethod void Menu::insertItem(before, item)
+
+ Inserts the \c item at the index \c before in the current menu.
+ In this case, \c item can be either a \l MenuItem, a \l MenuSeparator,
+ or a \l Menu.
+
+ \sa removeItem()
+*/
+
+/*!
+ \qmlmethod void Menu::removeItem(item)
+
+ Removes the \c item from the menu.
+ In this case, \c item can be either a \l MenuItem, a \l MenuSeparator,
+ or a \l Menu.
+
+ \sa insertItem()
+*/
+
+/*!
\qmlproperty var Menu::model
*/
@@ -402,6 +434,13 @@ QtMenuItem *QtMenu::addItem(QString title)
return item;
}
+QtMenuSeparator *QtMenu::addSeparator()
+{
+ QtMenuSeparator *item = new QtMenuSeparator(this);
+ insertItem(m_itemsCount, item);
+ return item;
+}
+
void QtMenu::insertItem(int index, QtMenuBase *menuItem)
{
if (!menuItem)
diff --git a/src/controls/qtmenu_p.h b/src/controls/qtmenu_p.h
index 650d8e80f..9d0418734 100644
--- a/src/controls/qtmenu_p.h
+++ b/src/controls/qtmenu_p.h
@@ -74,6 +74,7 @@ class QtMenu : public QtMenuText
public:
Q_INVOKABLE void popup();
Q_INVOKABLE QtMenuItem *addItem(QString);
+ Q_INVOKABLE QtMenuSeparator *addSeparator();
Q_INVOKABLE void __popup(qreal x, qreal y, int atActionIndex = -1);
@@ -115,6 +116,7 @@ public:
QQuickItem *menuContentItem() const { return m_menuContentItem; }
bool popupVisible() const { return m_popupVisible; }
+ QtMenuItemType::MenuItemType type() { return QtMenuItemType::Menu; }
bool isNative() { return m_platformMenu != 0; }
protected Q_SLOTS:
diff --git a/src/controls/qtmenuitem_p.h b/src/controls/qtmenuitem_p.h
index d00f821ed..4762d6e2f 100644
--- a/src/controls/qtmenuitem_p.h
+++ b/src/controls/qtmenuitem_p.h
@@ -59,10 +59,24 @@ class QtExclusiveGroup;
class QtMenu;
class QtMenuItemContainer;
+class QtMenuItemType
+{
+ Q_GADGET
+ Q_ENUMS(MenuItemType)
+
+public:
+ enum MenuItemType {
+ Separator,
+ Item,
+ Menu
+ };
+};
+
class QtMenuBase: public QObject
{
Q_OBJECT
Q_PROPERTY(bool visible READ visible WRITE setVisible NOTIFY visibleChanged)
+ Q_PROPERTY(QtMenuItemType::MenuItemType type READ type CONSTANT)
Q_PROPERTY(QtMenu *__parentMenu READ parentMenu CONSTANT)
Q_PROPERTY(bool __isNative READ isNative CONSTANT)
@@ -90,6 +104,7 @@ public:
QQuickItem *visualItem() const;
void setVisualItem(QQuickItem *item);
+ virtual QtMenuItemType::MenuItemType type() { return QtMenuItemType::Item; }
virtual bool isNative() { return m_platformItem != 0; }
private:
@@ -105,6 +120,8 @@ class QtMenuSeparator : public QtMenuBase
Q_OBJECT
public:
QtMenuSeparator(QObject *parent = 0);
+
+ QtMenuItemType::MenuItemType type() { return QtMenuItemType::Separator; }
};
class QtMenuText: public QtMenuBase
diff --git a/src/controls/qtmenuitemcontainer_p.h b/src/controls/qtmenuitemcontainer_p.h
index b4168b74d..2dbad6c62 100644
--- a/src/controls/qtmenuitemcontainer_p.h
+++ b/src/controls/qtmenuitemcontainer_p.h
@@ -75,7 +75,7 @@ public:
m_menuItems.removeOne(item);
}
- const QList<QtMenuBase *> &items()
+ const QList<QPointer<QtMenuBase> > &items()
{
return m_menuItems;
}
@@ -84,13 +84,15 @@ public:
{
while (!m_menuItems.empty()) {
QtMenuBase *item = m_menuItems.takeFirst();
- item->setParentMenu(0);
- item->setContainer(0);
+ if (item) {
+ item->setParentMenu(0);
+ item->setContainer(0);
+ }
}
}
private:
- QList<QtMenuBase *> m_menuItems;
+ QList<QPointer<QtMenuBase> > m_menuItems;
};
QT_END_NAMESPACE
diff --git a/src/private/qstyleitem.cpp b/src/private/qstyleitem.cpp
index 3d2710924..1e50d3726 100644
--- a/src/private/qstyleitem.cpp
+++ b/src/private/qstyleitem.cpp
@@ -368,7 +368,7 @@ void QStyleItem::initStyleOption()
} else {
opt->text = text();
- if (m_properties["hasSubmenu"].toBool()) {
+ if (m_properties["isSubmenu"].toBool()) {
opt->menuItemType = QStyleOptionMenuItem::SubMenu;
} else {
QString shortcut = m_properties["shortcut"].toString();
diff --git a/src/styles/Desktop/MenuStyle.qml b/src/styles/Desktop/MenuStyle.qml
index 6de5c95a5..7bfee4e0b 100644
--- a/src/styles/Desktop/MenuStyle.qml
+++ b/src/styles/Desktop/MenuStyle.qml
@@ -88,7 +88,7 @@ Style {
"checkable": !!menuItem && !!menuItem["checkable"],
"exclusive": !!menuItem && !!menuItem["exclusiveGroup"],
"shortcut": !!menuItem && menuItem["shortcut"] || "",
- "hasSubmenu": hasSubmenu,
+ "isSubmenu": isSubmenu,
"icon": !!menuItem && menuItem.__icon
}
}
diff --git a/src/styles/MenuStyle.qml b/src/styles/MenuStyle.qml
index d80ba9e6e..dfc25ac50 100644
--- a/src/styles/MenuStyle.qml
+++ b/src/styles/MenuStyle.qml
@@ -72,7 +72,7 @@ Style {
Text {
id: text
visible: !isSeparator
- text: menuItem.text + (hasSubmenu ? " \u25b6" : "")
+ text: menuItem.text + (isSubmenu ? " \u25b6" : "")
x: 6
anchors.verticalCenter: parent.verticalCenter
renderType: Text.NativeRendering
diff --git a/tests/auto/controls/data/tst_menu.qml b/tests/auto/controls/data/tst_menu.qml
index 7d6219123..3c109347f 100644
--- a/tests/auto/controls/data/tst_menu.qml
+++ b/tests/auto/controls/data/tst_menu.qml
@@ -93,13 +93,20 @@ TestCase {
Component {
id: modelCreationComponent
- // TODO Update when model patch is in
- // Menu { MenuItemRepeater { model: testcase.itemsText MenuItem { text: modelData } }
- Menu {}
+ Menu {
+ id: modelMenu
+ Instantiator {
+ model: itemsText
+ MenuItem {
+ text: modelData
+ }
+ onObjectAdded: modelMenu.insertItem(index, object)
+ }
+
+ }
}
function test_modelCreation() {
- testcase.skip("No support for model in Menu. It'll come back")
var menu = modelCreationComponent.createObject(testcase)
compare(menu.items.length, testcase.itemsText.length)
for (var i = 0; i < menu.items.length; i++)
@@ -182,4 +189,32 @@ TestCase {
compare(menu.__selectedIndex, 2)
verify(menu.items[menu.__selectedIndex].checked)
}
+
+ function test_dynamicItems() {
+ menu.clear()
+ compare(menu.items.length, 0)
+ var n = 6
+ var separatorIdx = 4
+ var submenuIdx = 5
+ for (var i = 0; i < n; ++i) {
+ if (i === separatorIdx)
+ var item = menu.addSeparator()
+ else if (i === submenuIdx)
+ item = menu.addMenu("Submenu")
+ else
+ item = menu.addItem("Item " + i)
+ }
+ compare(menu.items.length, n)
+
+ for (i = 0; i < n; ++i) {
+ item = menu.items[i]
+ compare(item.type, i === submenuIdx ? MenuItemType.Menu :
+ i === separatorIdx ? MenuItemType.Separator :
+ MenuItemType.Item)
+ if (i === submenuIdx)
+ compare(item.title, "Submenu")
+ else if (i !== separatorIdx)
+ compare(item.text, "Item " + i)
+ }
+ }
}