From 8a0daa0c8fd2180f9ad8d1fc0786a1287b345bc4 Mon Sep 17 00:00:00 2001 From: laserpants Date: Wed, 27 Apr 2016 02:14:39 +0300 Subject: [PATCH] implement toggle action for icon menu --- components/iconmenu.cpp | 78 ++++++++++++++++++++++++++++++++++++++--- components/iconmenu.h | 30 +++++++++++++--- 2 files changed, 98 insertions(+), 10 deletions(-) diff --git a/components/iconmenu.cpp b/components/iconmenu.cpp index 42f49e2..18ccb4f 100644 --- a/components/iconmenu.cpp +++ b/components/iconmenu.cpp @@ -1,5 +1,8 @@ #include #include +#include +#include +#include #include "iconmenu.h" #include "menu.h" @@ -7,6 +10,7 @@ MenuOverlay::MenuOverlay(QWidget *parent) : QWidget(parent) { setAttribute(Qt::WA_NoSystemBackground); + setAttribute(Qt::WA_TransparentForMouseEvents); } MenuOverlay::~MenuOverlay() @@ -15,11 +19,27 @@ MenuOverlay::~MenuOverlay() IconMenu::IconMenu(const QIcon &icon, QWidget *parent) : IconButton(icon, parent), - _menuOverlay(new MenuOverlay(parent)), + _menuOverlay(new MenuOverlay), _menu(new Menu(_menuOverlay)), - _menuGeometryWidget(0) + _animation(new QPropertyAnimation(this)), + _menuVisible(false), + _progress(0) { setCheckable(true); + setOverlayParent(parent); + + _animation->setPropertyName("progress"); + _animation->setTargetObject(this); + _animation->setDuration(350); + _animation->setStartValue(1); + _animation->setEndValue(0); + + _menu->hide(); + + _menuOverlay->installEventFilter(this); + + connect(this, SIGNAL(clicked(bool)), this, SLOT(toggleMenu())); + connect(_animation, SIGNAL(finished()), this, SLOT(animationFinished())); _menu->addMenuItem("Maps"); _menu->addMenuItem("Books"); @@ -31,17 +51,65 @@ IconMenu::~IconMenu() { } +void IconMenu::setProgress(qreal progress) +{ + if (_progress == progress) + return; + _progress = progress; + + emit progressChanged(progress); + update(); +} + void IconMenu::setOverlayParent(QWidget *parent) { _menuOverlay->setParent(parent); } +void IconMenu::toggleMenu() +{ + _animation->setDirection(_menuVisible + ? QAbstractAnimation::Forward + : QAbstractAnimation::Backward); + _animation->start(); + + _menuVisible = !_menuVisible; + + if (_menuVisible) { + _menu->show(); + _menuOverlay->setAttribute(Qt::WA_TransparentForMouseEvents, false); + } +} + +void IconMenu::animationFinished() +{ + if (!_menuVisible) { + _menu->hide(); + _menuOverlay->setAttribute(Qt::WA_TransparentForMouseEvents, true); + } +} + +bool IconMenu::eventFilter(QObject *obj, QEvent *event) +{ + if (QEvent::MouseButtonRelease == event->type() && _menuOverlay == obj) + toggleMenu(); + return IconButton::eventFilter(obj, event); +} + bool IconMenu::event(QEvent *event) { - if (QEvent::ParentChange == event->type()) { + const QEvent::Type &type = event->type(); + if (QEvent::ParentChange == type) { setOverlayParent(parentWidget()); - QSize hint = _menu->layout()->sizeHint(); - _menuOverlay->setGeometry(0, 0, hint.width(), hint.height()); + updateOverlayGeometry(); + } else if (QEvent::Move == type || QEvent::Resize == type) { + _menuPos = parentWidget()->mapToParent(pos()); + updateOverlayGeometry(); } return IconButton::event(event); } + +void IconMenu::updateOverlayGeometry() +{ + _menu->setGeometry(QRect(_menuPos, _menu->layout()->sizeHint())); +} diff --git a/components/iconmenu.h b/components/iconmenu.h index fd73629..7aef37c 100644 --- a/components/iconmenu.h +++ b/components/iconmenu.h @@ -2,10 +2,9 @@ #define ICONMENU_H #include +#include #include "iconbutton.h" -class Menu; - class MenuOverlay : public QWidget { Q_OBJECT @@ -15,23 +14,44 @@ public: ~MenuOverlay(); }; +class QPropertyAnimation; +class Menu; + class IconMenu : public IconButton { Q_OBJECT + Q_PROPERTY(qreal progress WRITE setProgress READ progress NOTIFY progressChanged) + public: explicit IconMenu(const QIcon &icon, QWidget *parent = 0); ~IconMenu(); + void setProgress(qreal progress); + inline qreal progress() const { return _progress; } + void setOverlayParent(QWidget *parent); +protected slots: + void toggleMenu(); + void animationFinished(); + +signals: + void progressChanged(qreal); + protected: + bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; bool event(QEvent *event) Q_DECL_OVERRIDE; + void updateOverlayGeometry(); + private: - MenuOverlay *const _menuOverlay; - Menu *const _menu; - QWidget *_menuGeometryWidget; + MenuOverlay *const _menuOverlay; + Menu *const _menu; + QPropertyAnimation *const _animation; + QPoint _menuPos; + bool _menuVisible; + qreal _progress; }; #endif // ICONMENU_H