forked from quickshell/quickshell
		
	core/qsmenu!: improve menu layout change UX
Exposes QsMenuOpener.children as an ObjectModel instead of a list to allow smoother layout change handling in custom menu renderers. Fixes QsMenuAnchor/platform menus closing whenever menu content changes.
This commit is contained in:
		
							parent
							
								
									3fc1c914c7
								
							
						
					
					
						commit
						a053373d57
					
				
					 7 changed files with 61 additions and 67 deletions
				
			
		| 
						 | 
					@ -71,6 +71,22 @@ bool UntypedObjectModel::removeObject(const QObject* object) {
 | 
				
			||||||
	return true;
 | 
						return true;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					void UntypedObjectModel::diffUpdate(const QVector<QObject*>& newValues) {
 | 
				
			||||||
 | 
						for (qsizetype i = 0; i < this->valuesList.length();) {
 | 
				
			||||||
 | 
							if (newValues.contains(this->valuesList.at(i))) i++;
 | 
				
			||||||
 | 
							else this->removeAt(i);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						qsizetype oi = 0;
 | 
				
			||||||
 | 
						for (auto* object: newValues) {
 | 
				
			||||||
 | 
							if (this->valuesList.length() == oi || this->valuesList.at(oi) != object) {
 | 
				
			||||||
 | 
								this->insertObject(object, oi);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							oi++;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qsizetype UntypedObjectModel::indexOf(QObject* object) { return this->valuesList.indexOf(object); }
 | 
					qsizetype UntypedObjectModel::indexOf(QObject* object) { return this->valuesList.indexOf(object); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
UntypedObjectModel* UntypedObjectModel::emptyInstance() {
 | 
					UntypedObjectModel* UntypedObjectModel::emptyInstance() {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,6 +73,9 @@ protected:
 | 
				
			||||||
	void insertObject(QObject* object, qsizetype index = -1);
 | 
						void insertObject(QObject* object, qsizetype index = -1);
 | 
				
			||||||
	bool removeObject(const QObject* object);
 | 
						bool removeObject(const QObject* object);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Assumes only one instance of a specific value
 | 
				
			||||||
 | 
						void diffUpdate(const QVector<QObject*>& newValues);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	QVector<QObject*> valuesList;
 | 
						QVector<QObject*> valuesList;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
| 
						 | 
					@ -97,6 +100,11 @@ public:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void removeObject(const T* object) { this->UntypedObjectModel::removeObject(object); }
 | 
						void removeObject(const T* object) { this->UntypedObjectModel::removeObject(object); }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// Assumes only one instance of a specific value
 | 
				
			||||||
 | 
						void diffUpdate(const QVector<T*>& newValues) {
 | 
				
			||||||
 | 
							this->UntypedObjectModel::diffUpdate(*std::bit_cast<const QVector<QObject*>*>(&newValues));
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	static ObjectModel<T>* emptyInstance() {
 | 
						static ObjectModel<T>* emptyInstance() {
 | 
				
			||||||
		return static_cast<ObjectModel<T>*>(UntypedObjectModel::emptyInstance());
 | 
							return static_cast<ObjectModel<T>*>(UntypedObjectModel::emptyInstance());
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,6 +20,7 @@
 | 
				
			||||||
#include "../window/proxywindow.hpp"
 | 
					#include "../window/proxywindow.hpp"
 | 
				
			||||||
#include "../window/windowinterface.hpp"
 | 
					#include "../window/windowinterface.hpp"
 | 
				
			||||||
#include "iconprovider.hpp"
 | 
					#include "iconprovider.hpp"
 | 
				
			||||||
 | 
					#include "model.hpp"
 | 
				
			||||||
#include "platformmenu_p.hpp"
 | 
					#include "platformmenu_p.hpp"
 | 
				
			||||||
#include "popupanchor.hpp"
 | 
					#include "popupanchor.hpp"
 | 
				
			||||||
#include "qsmenu.hpp"
 | 
					#include "qsmenu.hpp"
 | 
				
			||||||
| 
						 | 
					@ -61,6 +62,7 @@ PlatformMenuEntry::PlatformMenuEntry(QsMenuEntry* menu): QObject(menu), menu(men
 | 
				
			||||||
	QObject::connect(menu, &QsMenuEntry::buttonTypeChanged, this, &PlatformMenuEntry::onButtonTypeChanged);
 | 
						QObject::connect(menu, &QsMenuEntry::buttonTypeChanged, this, &PlatformMenuEntry::onButtonTypeChanged);
 | 
				
			||||||
	QObject::connect(menu, &QsMenuEntry::checkStateChanged, this, &PlatformMenuEntry::onCheckStateChanged);
 | 
						QObject::connect(menu, &QsMenuEntry::checkStateChanged, this, &PlatformMenuEntry::onCheckStateChanged);
 | 
				
			||||||
	QObject::connect(menu, &QsMenuEntry::hasChildrenChanged, this, &PlatformMenuEntry::relayoutParent);
 | 
						QObject::connect(menu, &QsMenuEntry::hasChildrenChanged, this, &PlatformMenuEntry::relayoutParent);
 | 
				
			||||||
 | 
						QObject::connect(menu->children(), &UntypedObjectModel::valuesChanged, this, &PlatformMenuEntry::relayout);
 | 
				
			||||||
	// clang-format on
 | 
						// clang-format on
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -178,10 +180,10 @@ void PlatformMenuEntry::relayout() {
 | 
				
			||||||
			this->qmenu->setIcon(getCurrentEngineImageAsIcon(icon));
 | 
								this->qmenu->setIcon(getCurrentEngineImageAsIcon(icon));
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		auto children = this->menu->children();
 | 
							const auto& children = this->menu->children()->valueList();
 | 
				
			||||||
		auto len = children.count(&children);
 | 
							auto len = children.count();
 | 
				
			||||||
		for (auto i = 0; i < len; i++) {
 | 
							for (auto i = 0; i < len; i++) {
 | 
				
			||||||
			auto* child = children.at(&children, i);
 | 
								auto* child = children.at(i);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			auto* instance = new PlatformMenuEntry(child);
 | 
								auto* instance = new PlatformMenuEntry(child);
 | 
				
			||||||
			QObject::connect(instance, &QObject::destroyed, this, &PlatformMenuEntry::onChildDestroyed);
 | 
								QObject::connect(instance, &QObject::destroyed, this, &PlatformMenuEntry::onChildDestroyed);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,8 +4,8 @@
 | 
				
			||||||
#include <qobject.h>
 | 
					#include <qobject.h>
 | 
				
			||||||
#include <qqmllist.h>
 | 
					#include <qqmllist.h>
 | 
				
			||||||
#include <qtmetamacros.h>
 | 
					#include <qtmetamacros.h>
 | 
				
			||||||
#include <qtypes.h>
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#include "model.hpp"
 | 
				
			||||||
#include "platformmenu.hpp"
 | 
					#include "platformmenu.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
using namespace qs::menu::platform;
 | 
					using namespace qs::menu::platform;
 | 
				
			||||||
| 
						 | 
					@ -34,15 +34,6 @@ void QsMenuEntry::display(QObject* parentWindow, int relativeX, int relativeY) {
 | 
				
			||||||
	if (!success) delete platform;
 | 
						if (!success) delete platform;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QQmlListProperty<QsMenuEntry> QsMenuEntry::emptyChildren(QObject* parent) {
 | 
					 | 
				
			||||||
	return QQmlListProperty<QsMenuEntry>(
 | 
					 | 
				
			||||||
	    parent,
 | 
					 | 
				
			||||||
	    nullptr,
 | 
					 | 
				
			||||||
	    &QsMenuEntry::childCount,
 | 
					 | 
				
			||||||
	    &QsMenuEntry::childAt
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
void QsMenuEntry::ref() {
 | 
					void QsMenuEntry::ref() {
 | 
				
			||||||
	this->refcount++;
 | 
						this->refcount++;
 | 
				
			||||||
	if (this->refcount == 1) emit this->opened();
 | 
						if (this->refcount == 1) emit this->opened();
 | 
				
			||||||
| 
						 | 
					@ -53,7 +44,9 @@ void QsMenuEntry::unref() {
 | 
				
			||||||
	if (this->refcount == 0) emit this->closed();
 | 
						if (this->refcount == 0) emit this->closed();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QQmlListProperty<QsMenuEntry> QsMenuEntry::children() { return QsMenuEntry::emptyChildren(this); }
 | 
					ObjectModel<QsMenuEntry>* QsMenuEntry::children() {
 | 
				
			||||||
 | 
						return ObjectModel<QsMenuEntry>::emptyInstance();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QsMenuOpener::~QsMenuOpener() {
 | 
					QsMenuOpener::~QsMenuOpener() {
 | 
				
			||||||
	if (this->mMenu) {
 | 
						if (this->mMenu) {
 | 
				
			||||||
| 
						 | 
					@ -83,13 +76,6 @@ void QsMenuOpener::setMenu(QsMenuHandle* menu) {
 | 
				
			||||||
	if (menu != nullptr) {
 | 
						if (menu != nullptr) {
 | 
				
			||||||
		auto onMenuChanged = [this, menu]() {
 | 
							auto onMenuChanged = [this, menu]() {
 | 
				
			||||||
			if (menu->menu()) {
 | 
								if (menu->menu()) {
 | 
				
			||||||
				QObject::connect(
 | 
					 | 
				
			||||||
				    menu->menu(),
 | 
					 | 
				
			||||||
				    &QsMenuEntry::childrenChanged,
 | 
					 | 
				
			||||||
				    this,
 | 
					 | 
				
			||||||
				    &QsMenuOpener::childrenChanged
 | 
					 | 
				
			||||||
				);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				menu->menu()->ref();
 | 
									menu->menu()->ref();
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -113,19 +99,12 @@ void QsMenuOpener::onMenuDestroyed() {
 | 
				
			||||||
	emit this->childrenChanged();
 | 
						emit this->childrenChanged();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QQmlListProperty<QsMenuEntry> QsMenuOpener::children() {
 | 
					ObjectModel<QsMenuEntry>* QsMenuOpener::children() {
 | 
				
			||||||
	if (this->mMenu && this->mMenu->menu()) {
 | 
						if (this->mMenu && this->mMenu->menu()) {
 | 
				
			||||||
		return this->mMenu->menu()->children();
 | 
							return this->mMenu->menu()->children();
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		return QsMenuEntry::emptyChildren(this);
 | 
							return ObjectModel<QsMenuEntry>::emptyInstance();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
qsizetype QsMenuEntry::childCount(QQmlListProperty<QsMenuEntry>* /*property*/) { return 0; }
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
QsMenuEntry*
 | 
					 | 
				
			||||||
QsMenuEntry::childAt(QQmlListProperty<QsMenuEntry>* /*property*/, qsizetype /*index*/) {
 | 
					 | 
				
			||||||
	return nullptr;
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
} // namespace qs::menu
 | 
					} // namespace qs::menu
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -9,6 +9,7 @@
 | 
				
			||||||
#include <qtypes.h>
 | 
					#include <qtypes.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "doc.hpp"
 | 
					#include "doc.hpp"
 | 
				
			||||||
 | 
					#include "model.hpp"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
namespace qs::menu {
 | 
					namespace qs::menu {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -107,9 +108,7 @@ public:
 | 
				
			||||||
	void ref();
 | 
						void ref();
 | 
				
			||||||
	void unref();
 | 
						void unref();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[[nodiscard]] virtual QQmlListProperty<QsMenuEntry> children();
 | 
						[[nodiscard]] virtual ObjectModel<QsMenuEntry>* children();
 | 
				
			||||||
 | 
					 | 
				
			||||||
	static QQmlListProperty<QsMenuEntry> emptyChildren(QObject* parent);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
signals:
 | 
					signals:
 | 
				
			||||||
	/// Send a trigger/click signal to the menu entry.
 | 
						/// Send a trigger/click signal to the menu entry.
 | 
				
			||||||
| 
						 | 
					@ -125,12 +124,8 @@ signals:
 | 
				
			||||||
	void buttonTypeChanged();
 | 
						void buttonTypeChanged();
 | 
				
			||||||
	void checkStateChanged();
 | 
						void checkStateChanged();
 | 
				
			||||||
	void hasChildrenChanged();
 | 
						void hasChildrenChanged();
 | 
				
			||||||
	QSDOC_HIDE void childrenChanged();
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
private:
 | 
					private:
 | 
				
			||||||
	static qsizetype childCount(QQmlListProperty<QsMenuEntry>* property);
 | 
					 | 
				
			||||||
	static QsMenuEntry* childAt(QQmlListProperty<QsMenuEntry>* property, qsizetype index);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	qsizetype refcount = 0;
 | 
						qsizetype refcount = 0;
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -140,7 +135,8 @@ class QsMenuOpener: public QObject {
 | 
				
			||||||
	/// The menu to retrieve children from.
 | 
						/// The menu to retrieve children from.
 | 
				
			||||||
	Q_PROPERTY(qs::menu::QsMenuHandle* menu READ menu WRITE setMenu NOTIFY menuChanged);
 | 
						Q_PROPERTY(qs::menu::QsMenuHandle* menu READ menu WRITE setMenu NOTIFY menuChanged);
 | 
				
			||||||
	/// The children of the given menu.
 | 
						/// The children of the given menu.
 | 
				
			||||||
	Q_PROPERTY(QQmlListProperty<qs::menu::QsMenuEntry> children READ children NOTIFY childrenChanged);
 | 
						QSDOC_TYPE_OVERRIDE(ObjectModel<qs::menu::QsMenuEntry>*);
 | 
				
			||||||
 | 
						Q_PROPERTY(UntypedObjectModel* children READ children NOTIFY childrenChanged);
 | 
				
			||||||
	QML_ELEMENT;
 | 
						QML_ELEMENT;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
public:
 | 
					public:
 | 
				
			||||||
| 
						 | 
					@ -151,7 +147,7 @@ public:
 | 
				
			||||||
	[[nodiscard]] QsMenuHandle* menu() const;
 | 
						[[nodiscard]] QsMenuHandle* menu() const;
 | 
				
			||||||
	void setMenu(QsMenuHandle* menu);
 | 
						void setMenu(QsMenuHandle* menu);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[[nodiscard]] QQmlListProperty<QsMenuEntry> children();
 | 
						[[nodiscard]] ObjectModel<QsMenuEntry>* children();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
signals:
 | 
					signals:
 | 
				
			||||||
	void menuChanged();
 | 
						void menuChanged();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -21,6 +21,7 @@
 | 
				
			||||||
#include <qvariant.h>
 | 
					#include <qvariant.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../../core/iconimageprovider.hpp"
 | 
					#include "../../core/iconimageprovider.hpp"
 | 
				
			||||||
 | 
					#include "../../core/model.hpp"
 | 
				
			||||||
#include "../../core/qsmenu.hpp"
 | 
					#include "../../core/qsmenu.hpp"
 | 
				
			||||||
#include "../../dbus/properties.hpp"
 | 
					#include "../../dbus/properties.hpp"
 | 
				
			||||||
#include "dbus_menu.h"
 | 
					#include "dbus_menu.h"
 | 
				
			||||||
| 
						 | 
					@ -95,22 +96,8 @@ void DBusMenuItem::updateLayout() const {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
bool DBusMenuItem::hasChildren() const { return this->displayChildren || this->id == 0; }
 | 
					bool DBusMenuItem::hasChildren() const { return this->displayChildren || this->id == 0; }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QQmlListProperty<QsMenuEntry> DBusMenuItem::children() {
 | 
					ObjectModel<QsMenuEntry>* DBusMenuItem::children() {
 | 
				
			||||||
	return QQmlListProperty<QsMenuEntry>(
 | 
						return reinterpret_cast<ObjectModel<QsMenuEntry>*>(&this->enabledChildren);
 | 
				
			||||||
	    this,
 | 
					 | 
				
			||||||
	    nullptr,
 | 
					 | 
				
			||||||
	    &DBusMenuItem::childrenCount,
 | 
					 | 
				
			||||||
	    &DBusMenuItem::childAt
 | 
					 | 
				
			||||||
	);
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
qsizetype DBusMenuItem::childrenCount(QQmlListProperty<QsMenuEntry>* property) {
 | 
					 | 
				
			||||||
	return reinterpret_cast<DBusMenuItem*>(property->object)->enabledChildren.count();
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
QsMenuEntry* DBusMenuItem::childAt(QQmlListProperty<QsMenuEntry>* property, qsizetype index) {
 | 
					 | 
				
			||||||
	auto* item = reinterpret_cast<DBusMenuItem*>(property->object);
 | 
					 | 
				
			||||||
	return item->menu->items.value(item->enabledChildren.at(index));
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DBusMenuItem::updateProperties(const QVariantMap& properties, const QStringList& removed) {
 | 
					void DBusMenuItem::updateProperties(const QVariantMap& properties, const QStringList& removed) {
 | 
				
			||||||
| 
						 | 
					@ -270,14 +257,13 @@ void DBusMenuItem::updateProperties(const QVariantMap& properties, const QString
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void DBusMenuItem::onChildrenUpdated() {
 | 
					void DBusMenuItem::onChildrenUpdated() {
 | 
				
			||||||
	this->enabledChildren.clear();
 | 
						QVector<DBusMenuItem*> children;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	for (auto child: this->mChildren) {
 | 
						for (auto child: this->mChildren) {
 | 
				
			||||||
		auto* item = this->menu->items.value(child);
 | 
							auto* item = this->menu->items.value(child);
 | 
				
			||||||
		if (item->visible) this->enabledChildren.push_back(child);
 | 
							if (item->visible) children.append(item);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	emit this->childrenChanged();
 | 
						this->enabledChildren.diffUpdate(children);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QDebug operator<<(QDebug debug, DBusMenuItem* item) {
 | 
					QDebug operator<<(QDebug debug, DBusMenuItem* item) {
 | 
				
			||||||
| 
						 | 
					@ -388,7 +374,7 @@ void DBusMenu::updateLayoutRecursive(
 | 
				
			||||||
			    [&](const DBusMenuLayout& layout) { return layout.id == *iter; }
 | 
								    [&](const DBusMenuLayout& layout) { return layout.id == *iter; }
 | 
				
			||||||
			);
 | 
								);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (existing == layout.children.end()) {
 | 
								if (!item->mShowChildren || existing == layout.children.end()) {
 | 
				
			||||||
				qCDebug(logDbusMenu) << "Removing missing layout item" << this->items.value(*iter) << "from"
 | 
									qCDebug(logDbusMenu) << "Removing missing layout item" << this->items.value(*iter) << "from"
 | 
				
			||||||
				                     << item;
 | 
									                     << item;
 | 
				
			||||||
				this->removeRecursive(*iter);
 | 
									this->removeRecursive(*iter);
 | 
				
			||||||
| 
						 | 
					@ -402,7 +388,7 @@ void DBusMenu::updateLayoutRecursive(
 | 
				
			||||||
		for (const auto& child: layout.children) {
 | 
							for (const auto& child: layout.children) {
 | 
				
			||||||
			if (item->mShowChildren && !item->mChildren.contains(child.id)) {
 | 
								if (item->mShowChildren && !item->mChildren.contains(child.id)) {
 | 
				
			||||||
				qCDebug(logDbusMenu) << "Creating new layout item" << child.id << "in" << item;
 | 
									qCDebug(logDbusMenu) << "Creating new layout item" << child.id << "in" << item;
 | 
				
			||||||
				item->mChildren.push_back(child.id);
 | 
									// item->mChildren.push_back(child.id);
 | 
				
			||||||
				this->items.insert(child.id, nullptr);
 | 
									this->items.insert(child.id, nullptr);
 | 
				
			||||||
				childrenChanged = true;
 | 
									childrenChanged = true;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
| 
						 | 
					@ -410,7 +396,15 @@ void DBusMenu::updateLayoutRecursive(
 | 
				
			||||||
			this->updateLayoutRecursive(child, item, depth - 1);
 | 
								this->updateLayoutRecursive(child, item, depth - 1);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (childrenChanged) item->onChildrenUpdated();
 | 
							if (childrenChanged) {
 | 
				
			||||||
 | 
								// reset to preserve order
 | 
				
			||||||
 | 
								item->mChildren.clear();
 | 
				
			||||||
 | 
								for (const auto& child: layout.children) {
 | 
				
			||||||
 | 
									item->mChildren.push_back(child.id);
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								item->onChildrenUpdated();
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (item->mShowChildren && !item->childrenLoaded) {
 | 
						if (item->mShowChildren && !item->childrenLoaded) {
 | 
				
			||||||
| 
						 | 
					@ -554,6 +548,7 @@ void DBusMenuHandle::onMenuPathChanged() {
 | 
				
			||||||
		this->mMenu->setParent(this);
 | 
							this->mMenu->setParent(this);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		QObject::connect(&this->mMenu->rootItem, &DBusMenuItem::layoutUpdated, this, [this]() {
 | 
							QObject::connect(&this->mMenu->rootItem, &DBusMenuItem::layoutUpdated, this, [this]() {
 | 
				
			||||||
 | 
								QObject::disconnect(&this->mMenu->rootItem, &DBusMenuItem::layoutUpdated, this, nullptr);
 | 
				
			||||||
			this->loaded = true;
 | 
								this->loaded = true;
 | 
				
			||||||
			emit this->menuChanged();
 | 
								emit this->menuChanged();
 | 
				
			||||||
		});
 | 
							});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -15,6 +15,7 @@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "../../core/doc.hpp"
 | 
					#include "../../core/doc.hpp"
 | 
				
			||||||
#include "../../core/imageprovider.hpp"
 | 
					#include "../../core/imageprovider.hpp"
 | 
				
			||||||
 | 
					#include "../../core/model.hpp"
 | 
				
			||||||
#include "../../core/qsmenu.hpp"
 | 
					#include "../../core/qsmenu.hpp"
 | 
				
			||||||
#include "../properties.hpp"
 | 
					#include "../properties.hpp"
 | 
				
			||||||
#include "dbus_menu_types.hpp"
 | 
					#include "dbus_menu_types.hpp"
 | 
				
			||||||
| 
						 | 
					@ -65,7 +66,7 @@ public:
 | 
				
			||||||
	[[nodiscard]] bool isShowingChildren() const;
 | 
						[[nodiscard]] bool isShowingChildren() const;
 | 
				
			||||||
	void setShowChildrenRecursive(bool showChildren);
 | 
						void setShowChildrenRecursive(bool showChildren);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	[[nodiscard]] QQmlListProperty<menu::QsMenuEntry> children() override;
 | 
						[[nodiscard]] ObjectModel<QsMenuEntry>* children() override;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	void updateProperties(const QVariantMap& properties, const QStringList& removed = {});
 | 
						void updateProperties(const QVariantMap& properties, const QStringList& removed = {});
 | 
				
			||||||
	void onChildrenUpdated();
 | 
						void onChildrenUpdated();
 | 
				
			||||||
| 
						 | 
					@ -96,11 +97,8 @@ private:
 | 
				
			||||||
	menu::QsMenuButtonType::Enum mButtonType = menu::QsMenuButtonType::None;
 | 
						menu::QsMenuButtonType::Enum mButtonType = menu::QsMenuButtonType::None;
 | 
				
			||||||
	Qt::CheckState mCheckState = Qt::Unchecked;
 | 
						Qt::CheckState mCheckState = Qt::Unchecked;
 | 
				
			||||||
	bool displayChildren = false;
 | 
						bool displayChildren = false;
 | 
				
			||||||
	QVector<qint32> enabledChildren;
 | 
						ObjectModel<DBusMenuItem> enabledChildren {this};
 | 
				
			||||||
	DBusMenuItem* parentMenu = nullptr;
 | 
						DBusMenuItem* parentMenu = nullptr;
 | 
				
			||||||
 | 
					 | 
				
			||||||
	static qsizetype childrenCount(QQmlListProperty<menu::QsMenuEntry>* property);
 | 
					 | 
				
			||||||
	static menu::QsMenuEntry* childAt(QQmlListProperty<menu::QsMenuEntry>* property, qsizetype index);
 | 
					 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
QDebug operator<<(QDebug debug, DBusMenuItem* item);
 | 
					QDebug operator<<(QDebug debug, DBusMenuItem* item);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue