Warning, file /frameworks/kconfigwidgets/src/khamburgermenuhelpers.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2021 Felix Ernst <fe.a.ernst@gmail.com> 0004 0005 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 #include "khamburgermenuhelpers_p.h" 0009 0010 #include "khamburgermenu.h" 0011 0012 #include <QEvent> 0013 #include <QMenu> 0014 #include <QToolButton> 0015 #include <QWidget> 0016 #include <QWindow> 0017 0018 ListenerContainer::ListenerContainer(KHamburgerMenuPrivate *hamburgerMenuPrivate) 0019 : QObject{hamburgerMenuPrivate} 0020 , m_listeners{std::vector<std::unique_ptr<QObject>>(4)} 0021 { 0022 } 0023 0024 ListenerContainer::~ListenerContainer() 0025 { 0026 } 0027 0028 bool AddOrRemoveActionListener::eventFilter(QObject * /*watched*/, QEvent *event) 0029 { 0030 if (event->type() == QEvent::ActionAdded || event->type() == QEvent::ActionRemoved) { 0031 static_cast<KHamburgerMenuPrivate *>(parent())->notifyMenuResetNeeded(); 0032 } 0033 return false; 0034 } 0035 0036 bool ButtonPressListener::eventFilter(QObject *watched, QEvent *event) 0037 { 0038 if (event->type() == QEvent::KeyPress || event->type() == QEvent::MouseButtonPress) { 0039 auto hamburgerMenuPrivate = static_cast<KHamburgerMenuPrivate *>(parent()); 0040 auto q = static_cast<KHamburgerMenu *>(hamburgerMenuPrivate->q_ptr); 0041 Q_EMIT q->aboutToShowMenu(); 0042 hamburgerMenuPrivate->resetMenu(); // This menu never has a parent which can be 0043 // problematic because it can lead to situations in which the QMenu itself is 0044 // treated like its own window. 0045 // To avoid this we set a sane transientParent() now even if it already has one 0046 // because the menu might be opened from another window this time. 0047 const auto watchedButton = qobject_cast<QToolButton *>(watched); 0048 if (!watchedButton) { 0049 return false; 0050 } 0051 auto menu = watchedButton->menu(); 0052 if (!menu) { 0053 return false; 0054 } 0055 // ensure polished so the style can change the surfaceformat of the window which is 0056 // not possible once the window has been created 0057 menu->ensurePolished(); 0058 menu->winId(); // trigger being a native widget already, to ensure windowHandle created 0059 // generic code if not known if the available parent widget is a native widget or not 0060 auto parentWindowHandle = watchedButton->windowHandle(); 0061 if (!parentWindowHandle) { 0062 parentWindowHandle = watchedButton->nativeParentWidget()->windowHandle(); 0063 } 0064 menu->windowHandle()->setTransientParent(parentWindowHandle); 0065 } 0066 return false; 0067 } 0068 0069 bool VisibleActionsChangeListener::eventFilter(QObject *watched, QEvent *event) 0070 { 0071 if (event->type() == QEvent::Show || event->type() == QEvent::Hide) { 0072 if (!event->spontaneous()) { 0073 static_cast<KHamburgerMenuPrivate *>(parent())->notifyMenuResetNeeded(); 0074 } 0075 } else if (event->type() == QEvent::ActionAdded || event->type() == QEvent::ActionRemoved) { 0076 Q_ASSERT_X(qobject_cast<QWidget *>(watched), "VisibileActionsChangeListener", "The watched QObject is expected to be a QWidget."); 0077 if (static_cast<QWidget *>(watched)->isVisible()) { 0078 static_cast<KHamburgerMenuPrivate *>(parent())->notifyMenuResetNeeded(); 0079 } 0080 } 0081 return false; 0082 } 0083 0084 bool VisibilityChangesListener::eventFilter(QObject * /*watched*/, QEvent *event) 0085 { 0086 if (event->type() == QEvent::Show || event->type() == QEvent::Hide) { 0087 if (!event->spontaneous()) { 0088 static_cast<KHamburgerMenuPrivate *>(parent())->updateVisibility(); 0089 } 0090 } 0091 return false; 0092 } 0093 0094 bool isWidgetActuallyVisible(const QWidget *widget) 0095 { 0096 Q_CHECK_PTR(widget); 0097 bool actuallyVisible = widget->isVisible(); 0098 const QWidget *ancestorWidget = widget->parentWidget(); 0099 while (actuallyVisible && ancestorWidget) { 0100 actuallyVisible = ancestorWidget->isVisible(); 0101 ancestorWidget = ancestorWidget->parentWidget(); 0102 } 0103 return actuallyVisible; 0104 } 0105 0106 bool listContainsWidget(const std::forward_list<QPointer<const QWidget>> &list, const QWidget *widget) 0107 { 0108 for (const auto &item : list) { 0109 if (widget == item) { 0110 return true; 0111 } 0112 } 0113 return false; 0114 }