forked from quickshell/quickshell
core/menu: add QsMenuAnchor for more control of platform menus
This commit is contained in:
parent
54350277be
commit
6b9b1fcb53
10 changed files with 245 additions and 21 deletions
105
src/core/qsmenuanchor.cpp
Normal file
105
src/core/qsmenuanchor.cpp
Normal file
|
@ -0,0 +1,105 @@
|
|||
#include "qsmenuanchor.hpp"
|
||||
|
||||
#include <qlogging.h>
|
||||
#include <qobject.h>
|
||||
#include <qtmetamacros.h>
|
||||
|
||||
#include "platformmenu.hpp"
|
||||
#include "popupanchor.hpp"
|
||||
#include "qsmenu.hpp"
|
||||
|
||||
using qs::menu::platform::PlatformMenuEntry;
|
||||
|
||||
namespace qs::menu {
|
||||
|
||||
QsMenuAnchor::~QsMenuAnchor() { this->onClosed(); }
|
||||
|
||||
void QsMenuAnchor::open() {
|
||||
if (this->mOpen) {
|
||||
qCritical() << "Cannot call QsMenuAnchor.open() as it is already open.";
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this->mMenu) {
|
||||
qCritical() << "Cannot open QsMenuAnchor with no menu attached.";
|
||||
return;
|
||||
}
|
||||
|
||||
this->mOpen = true;
|
||||
|
||||
if (this->mMenu->menu()) this->onMenuChanged();
|
||||
QObject::connect(this->mMenu, &QsMenuHandle::menuChanged, this, &QsMenuAnchor::onMenuChanged);
|
||||
this->mMenu->refHandle();
|
||||
|
||||
emit this->visibleChanged();
|
||||
}
|
||||
|
||||
void QsMenuAnchor::onMenuChanged() {
|
||||
// close menu if the path changes
|
||||
if (this->platformMenu || !this->mMenu->menu()) {
|
||||
this->onClosed();
|
||||
return;
|
||||
}
|
||||
|
||||
this->platformMenu = new PlatformMenuEntry(this->mMenu->menu());
|
||||
QObject::connect(this->platformMenu, &PlatformMenuEntry::closed, this, &QsMenuAnchor::onClosed);
|
||||
|
||||
auto success = this->platformMenu->display(&this->mAnchor);
|
||||
if (!success) this->onClosed();
|
||||
else emit this->opened();
|
||||
}
|
||||
|
||||
void QsMenuAnchor::close() {
|
||||
if (!this->mOpen) {
|
||||
qCritical() << "Cannot close QsMenuAnchor as it isn't open.";
|
||||
return;
|
||||
}
|
||||
|
||||
this->onClosed();
|
||||
}
|
||||
|
||||
void QsMenuAnchor::onClosed() {
|
||||
if (!this->mOpen) return;
|
||||
|
||||
this->mOpen = false;
|
||||
|
||||
if (this->platformMenu) {
|
||||
this->platformMenu->deleteLater();
|
||||
this->platformMenu = nullptr;
|
||||
}
|
||||
|
||||
QObject::disconnect(this->mMenu, &QsMenuHandle::menuChanged, this, &QsMenuAnchor::onMenuChanged);
|
||||
this->mMenu->unrefHandle();
|
||||
emit this->closed();
|
||||
emit this->visibleChanged();
|
||||
}
|
||||
|
||||
PopupAnchor* QsMenuAnchor::anchor() { return &this->mAnchor; }
|
||||
|
||||
QsMenuHandle* QsMenuAnchor::menu() const { return this->mMenu; }
|
||||
|
||||
void QsMenuAnchor::setMenu(QsMenuHandle* menu) {
|
||||
if (menu == this->mMenu) return;
|
||||
|
||||
if (this->mMenu != nullptr) {
|
||||
if (this->platformMenu != nullptr) this->platformMenu->deleteLater();
|
||||
QObject::disconnect(this->mMenu, nullptr, this, nullptr);
|
||||
}
|
||||
|
||||
this->mMenu = menu;
|
||||
|
||||
if (menu != nullptr) {
|
||||
QObject::connect(menu, &QObject::destroyed, this, &QsMenuAnchor::onMenuDestroyed);
|
||||
}
|
||||
|
||||
emit this->menuChanged();
|
||||
}
|
||||
|
||||
bool QsMenuAnchor::isVisible() const { return this->mOpen; }
|
||||
|
||||
void QsMenuAnchor::onMenuDestroyed() {
|
||||
this->mMenu = nullptr;
|
||||
emit this->menuChanged();
|
||||
}
|
||||
|
||||
} // namespace qs::menu
|
Loading…
Add table
Add a link
Reference in a new issue