From 93cf07deac366888fa7e8a06fe7593c1d5a92505 Mon Sep 17 00:00:00 2001 From: Kai Uwe Broulik Date: Mon, 27 Apr 2015 22:19:41 +0200 Subject: [PATCH] Add support for menu sections Also adds a manual unit test CHANGELOG: PlasmaComponents.Menu now supports sections REVIEW: 123537 --- .../plasmacomponents/qmenu.cpp | 34 +++++++-- .../plasmacomponents/qmenu.h | 1 + .../plasmacomponents/qmenuitem.cpp | 14 +++- .../plasmacomponents/qmenuitem.h | 8 +++ tests/components/menu.qml | 72 +++++++++++++++++++ 5 files changed, 123 insertions(+), 6 deletions(-) create mode 100644 tests/components/menu.qml diff --git a/src/declarativeimports/plasmacomponents/qmenu.cpp b/src/declarativeimports/plasmacomponents/qmenu.cpp index 0b82a99f3..d84f4815c 100644 --- a/src/declarativeimports/plasmacomponents/qmenu.cpp +++ b/src/declarativeimports/plasmacomponents/qmenu.cpp @@ -84,7 +84,15 @@ void QMenuProxy::setVisualParent(QObject *parent) action->setMenu(m_menu); m_menu->clear(); foreach (QMenuItem *item, m_items) { - m_menu->addAction(item->action()); + if (item->section()) { + if (!item->isVisible()) { + continue; + } + + m_menu->addSection(item->text()); + } else { + m_menu->addAction(item->action()); + } } m_menu->updateGeometry(); } @@ -116,7 +124,11 @@ bool QMenuProxy::event(QEvent *event) QMenuItem *mi = qobject_cast(ce->child()); //FIXME: linear complexity here if (mi && !m_items.contains(mi)) { - m_menu->addAction(mi->action()); + if (mi->separator()) { + m_menu->addSection(mi->text()); + } else { + m_menu->addAction(mi->action()); + } m_items << mi; } break; @@ -161,6 +173,11 @@ void QMenuProxy::addMenuItem(QMenuItem *item) m_items << item; } +void QMenuProxy::addSection(const QString &text) +{ + m_menu->addSection(text); +} + void QMenuProxy::itemTriggered(QAction *action) { QMenuItem *item = qobject_cast(action); @@ -178,8 +195,17 @@ void QMenuProxy::open(int x, int y) qDebug() << "opening menu at " << x << y; m_menu->clear(); foreach (QMenuItem *item, m_items) { - qDebug() << "Adding action: " << item->text(); - m_menu->addAction(item->action()); + if (item->section()) { + if (!item->isVisible()) { + continue; + } + + qDebug() << "Adding section: " << item->text(); + m_menu->addSection(item->text()); + } else { + qDebug() << "Adding action: " << item->text(); + m_menu->addAction(item->action()); + } } QQuickItem *parentItem; diff --git a/src/declarativeimports/plasmacomponents/qmenu.h b/src/declarativeimports/plasmacomponents/qmenu.h index a927d1267..6cf009642 100644 --- a/src/declarativeimports/plasmacomponents/qmenu.h +++ b/src/declarativeimports/plasmacomponents/qmenu.h @@ -67,6 +67,7 @@ public: Q_INVOKABLE void clearMenuItems(); Q_INVOKABLE void addMenuItem(const QString &text); Q_INVOKABLE void addMenuItem(QMenuItem *item); + Q_INVOKABLE void addSection(const QString &text); protected: bool event(QEvent *event) Q_DECL_OVERRIDE; diff --git a/src/declarativeimports/plasmacomponents/qmenuitem.cpp b/src/declarativeimports/plasmacomponents/qmenuitem.cpp index aa61288f5..287e9b33e 100644 --- a/src/declarativeimports/plasmacomponents/qmenuitem.cpp +++ b/src/declarativeimports/plasmacomponents/qmenuitem.cpp @@ -22,8 +22,8 @@ QMenuItem::QMenuItem(QQuickItem *parent) : QQuickItem(parent), - m_action(0) - + m_action(0), + m_section(false) { setAction(new QAction(this)); connect(m_action, &QAction::triggered, this, &QMenuItem::clicked); @@ -78,6 +78,16 @@ void QMenuItem::setSeparator(bool s) m_action->setSeparator(s); } +bool QMenuItem::section() const +{ + return m_section; +} + +void QMenuItem::setSection(bool s) +{ + m_section = s; +} + QString QMenuItem::text() const { return m_action->text(); diff --git a/src/declarativeimports/plasmacomponents/qmenuitem.h b/src/declarativeimports/plasmacomponents/qmenuitem.h index f8629f00c..03a5629e6 100644 --- a/src/declarativeimports/plasmacomponents/qmenuitem.h +++ b/src/declarativeimports/plasmacomponents/qmenuitem.h @@ -37,6 +37,10 @@ class QMenuItem : public QQuickItem * If true, the menu item will behave like a separator */ Q_PROPERTY(bool separator READ separator WRITE setSeparator NOTIFY separatorChanged) + /** + * If true, the menu item will behave like a section + */ + Q_PROPERTY(bool section READ section WRITE setSection NOTIFY sectionChanged) Q_PROPERTY(QString text READ text WRITE setText NOTIFY textChanged) Q_PROPERTY(QVariant icon READ icon WRITE setIcon NOTIFY iconChanged) Q_PROPERTY(QAction *action READ action WRITE setAction NOTIFY actionChanged) @@ -52,6 +56,8 @@ public: void setIcon(const QVariant &i); bool separator() const; void setSeparator(bool s); + bool section() const; + void setSection(bool s); QString text() const; void setText(const QString &t); @@ -67,6 +73,7 @@ Q_SIGNALS: void actionChanged(); void iconChanged(); void separatorChanged(); + void sectionChanged(); void textChanged(); void toggled(bool checked); void checkableChanged(); @@ -75,6 +82,7 @@ private: void updateAction(); QAction *m_action; QVariant m_icon; + bool m_section; }; #endif // QMENUITEM_H diff --git a/tests/components/menu.qml b/tests/components/menu.qml new file mode 100644 index 000000000..429cdb0cb --- /dev/null +++ b/tests/components/menu.qml @@ -0,0 +1,72 @@ +import QtQuick 2.0 +import org.kde.plasma.components 2.0 as PlasmaComponents + +Rectangle { + width: 600 + height: 200 + color: "white" + + Flow { + anchors.fill: parent + anchors.margins: 20 + spacing: 20 + + PlasmaComponents.Button { + text: "Simple menu" + onClicked: simpleMenu.open(0, height) + + PlasmaComponents.Menu { + id: simpleMenu + + PlasmaComponents.MenuItem { text: "Hello" } + PlasmaComponents.MenuItem { text: "This is just a simple" } + PlasmaComponents.MenuItem { text: "Menu" } + PlasmaComponents.MenuItem { text: "without separators" } + PlasmaComponents.MenuItem { text: "and other stuff" } + } + } + + PlasmaComponents.Button { + text: "Checkable menu items" + onClicked: checkableMenu.open(0, height) + + PlasmaComponents.Menu { + id: checkableMenu + + PlasmaComponents.MenuItem { text: "Apple"; checkable: true } + PlasmaComponents.MenuItem { text: "Banana"; checkable: true } + PlasmaComponents.MenuItem { text: "Orange"; checkable: true } + } + } + + + PlasmaComponents.Button { + text: "Icons" + onClicked: iconsMenu.open(0, height) + + PlasmaComponents.Menu { + id: iconsMenu + + PlasmaComponents.MenuItem { text: "Error"; icon: "dialog-error" } + PlasmaComponents.MenuItem { text: "Warning"; icon: "dialog-warning" } + PlasmaComponents.MenuItem { text: "Information"; icon: "dialog-information" } + } + } + + PlasmaComponents.Button { + text: "Separators and sections" + onClicked: sectionsMenu.open(0, height) + + PlasmaComponents.Menu { + id: sectionsMenu + + PlasmaComponents.MenuItem { text: "A menu"; section: true } + PlasmaComponents.MenuItem { text: "One entry" } + PlasmaComponents.MenuItem { text: "Another entry" } + PlasmaComponents.MenuItem { separator: true } + PlasmaComponents.MenuItem { text: "One item" } + PlasmaComponents.MenuItem { text: "Another item" } + } + } + } +}