forked from quickshell/quickshell
core/menu: add handle support to QsMenuOpener + add handle to tray
This commit is contained in:
parent
acdbe73c10
commit
54350277be
6 changed files with 101 additions and 51 deletions
|
@ -21,6 +21,8 @@ QString QsMenuButtonType::toString(QsMenuButtonType::Enum value) {
|
|||
}
|
||||
}
|
||||
|
||||
QsMenuEntry* QsMenuEntry::menu() { return this; }
|
||||
|
||||
void QsMenuEntry::display(QObject* parentWindow, int relativeX, int relativeY) {
|
||||
auto* platform = new PlatformMenuEntry(this);
|
||||
|
||||
|
@ -53,22 +55,52 @@ void QsMenuEntry::unref() {
|
|||
|
||||
QQmlListProperty<QsMenuEntry> QsMenuEntry::children() { return QsMenuEntry::emptyChildren(this); }
|
||||
|
||||
QsMenuEntry* QsMenuOpener::menu() const { return this->mMenu; }
|
||||
QsMenuOpener::~QsMenuOpener() {
|
||||
if (this->mMenu) {
|
||||
if (this->mMenu->menu()) this->mMenu->menu()->unref();
|
||||
this->mMenu->unrefHandle();
|
||||
}
|
||||
}
|
||||
|
||||
void QsMenuOpener::setMenu(QsMenuEntry* menu) {
|
||||
QsMenuHandle* QsMenuOpener::menu() const { return this->mMenu; }
|
||||
|
||||
void QsMenuOpener::setMenu(QsMenuHandle* menu) {
|
||||
if (menu == this->mMenu) return;
|
||||
|
||||
if (this->mMenu != nullptr) {
|
||||
this->mMenu->unref();
|
||||
QObject::disconnect(this->mMenu, nullptr, this, nullptr);
|
||||
|
||||
if (this->mMenu->menu()) {
|
||||
this->mMenu->menu()->unref();
|
||||
QObject::disconnect(this->mMenu->menu(), nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
this->mMenu->unrefHandle();
|
||||
}
|
||||
|
||||
this->mMenu = menu;
|
||||
|
||||
if (menu != nullptr) {
|
||||
auto onMenuChanged = [this, menu]() {
|
||||
if (menu->menu()) {
|
||||
QObject::connect(
|
||||
menu->menu(),
|
||||
&QsMenuEntry::childrenChanged,
|
||||
this,
|
||||
&QsMenuOpener::childrenChanged
|
||||
);
|
||||
|
||||
menu->menu()->ref();
|
||||
}
|
||||
|
||||
emit this->childrenChanged();
|
||||
};
|
||||
|
||||
QObject::connect(menu, &QObject::destroyed, this, &QsMenuOpener::onMenuDestroyed);
|
||||
QObject::connect(menu, &QsMenuEntry::childrenChanged, this, &QsMenuOpener::childrenChanged);
|
||||
menu->ref();
|
||||
QObject::connect(menu, &QsMenuHandle::menuChanged, this, onMenuChanged);
|
||||
|
||||
if (menu->menu()) onMenuChanged();
|
||||
menu->refHandle();
|
||||
}
|
||||
|
||||
emit this->menuChanged();
|
||||
|
@ -82,7 +114,11 @@ void QsMenuOpener::onMenuDestroyed() {
|
|||
}
|
||||
|
||||
QQmlListProperty<QsMenuEntry> QsMenuOpener::children() {
|
||||
return this->mMenu ? this->mMenu->children() : QsMenuEntry::emptyChildren(this);
|
||||
if (this->mMenu && this->mMenu->menu()) {
|
||||
return this->mMenu->menu()->children();
|
||||
} else {
|
||||
return QsMenuEntry::emptyChildren(this);
|
||||
}
|
||||
}
|
||||
|
||||
qsizetype QsMenuEntry::childCount(QQmlListProperty<QsMenuEntry>* /*property*/) { return 0; }
|
||||
|
|
|
@ -33,7 +33,28 @@ public:
|
|||
Q_INVOKABLE static QString toString(QsMenuButtonType::Enum value);
|
||||
};
|
||||
|
||||
class QsMenuEntry: public QObject {
|
||||
class QsMenuEntry;
|
||||
|
||||
///! Menu handle for QsMenuOpener
|
||||
/// See @@QsMenuOpener.
|
||||
class QsMenuHandle: public QObject {
|
||||
Q_OBJECT;
|
||||
QML_ELEMENT;
|
||||
QML_UNCREATABLE("");
|
||||
|
||||
public:
|
||||
explicit QsMenuHandle(QObject* parent): QObject(parent) {}
|
||||
|
||||
virtual void refHandle() {};
|
||||
virtual void unrefHandle() {};
|
||||
|
||||
[[nodiscard]] virtual QsMenuEntry* menu() = 0;
|
||||
|
||||
signals:
|
||||
void menuChanged();
|
||||
};
|
||||
|
||||
class QsMenuEntry: public QsMenuHandle {
|
||||
Q_OBJECT;
|
||||
/// If this menu item should be rendered as a separator between other items.
|
||||
///
|
||||
|
@ -68,7 +89,9 @@ class QsMenuEntry: public QObject {
|
|||
QML_UNCREATABLE("QsMenuEntry cannot be directly created");
|
||||
|
||||
public:
|
||||
explicit QsMenuEntry(QObject* parent = nullptr): QObject(parent) {}
|
||||
explicit QsMenuEntry(QObject* parent): QsMenuHandle(parent) {}
|
||||
|
||||
[[nodiscard]] QsMenuEntry* menu() override;
|
||||
|
||||
/// Display a platform menu at the given location relative to the parent window.
|
||||
Q_INVOKABLE void display(QObject* parentWindow, qint32 relativeX, qint32 relativeY);
|
||||
|
@ -111,37 +134,22 @@ private:
|
|||
qsizetype refcount = 0;
|
||||
};
|
||||
|
||||
class QsMenuHandle: public QObject {
|
||||
Q_OBJECT;
|
||||
QML_ELEMENT;
|
||||
QML_UNCREATABLE("");
|
||||
|
||||
public:
|
||||
explicit QsMenuHandle(QObject* parent): QObject(parent) {}
|
||||
|
||||
virtual void ref() {};
|
||||
virtual void unref() {};
|
||||
|
||||
[[nodiscard]] virtual QsMenuEntry* menu() const = 0;
|
||||
|
||||
signals:
|
||||
void menuChanged();
|
||||
};
|
||||
|
||||
///! Provides access to children of a QsMenuEntry
|
||||
class QsMenuOpener: public QObject {
|
||||
Q_OBJECT;
|
||||
/// The menu to retrieve children from.
|
||||
Q_PROPERTY(QsMenuEntry* menu READ menu WRITE setMenu NOTIFY menuChanged);
|
||||
Q_PROPERTY(QsMenuHandle* menu READ menu WRITE setMenu NOTIFY menuChanged);
|
||||
/// The children of the given menu.
|
||||
Q_PROPERTY(QQmlListProperty<QsMenuEntry> children READ children NOTIFY childrenChanged);
|
||||
QML_ELEMENT;
|
||||
|
||||
public:
|
||||
explicit QsMenuOpener(QObject* parent = nullptr): QObject(parent) {}
|
||||
~QsMenuOpener() override;
|
||||
Q_DISABLE_COPY_MOVE(QsMenuOpener);
|
||||
|
||||
[[nodiscard]] QsMenuEntry* menu() const;
|
||||
void setMenu(QsMenuEntry* menu);
|
||||
[[nodiscard]] QsMenuHandle* menu() const;
|
||||
void setMenu(QsMenuHandle* menu);
|
||||
|
||||
[[nodiscard]] QQmlListProperty<QsMenuEntry> children();
|
||||
|
||||
|
@ -153,7 +161,7 @@ private slots:
|
|||
void onMenuDestroyed();
|
||||
|
||||
private:
|
||||
QsMenuEntry* mMenu = nullptr;
|
||||
QsMenuHandle* mMenu = nullptr;
|
||||
};
|
||||
|
||||
} // namespace qs::menu
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue