diff --git a/chatterino.pro b/chatterino.pro index 88907f6c..1c2145ea 100644 --- a/chatterino.pro +++ b/chatterino.pro @@ -249,7 +249,8 @@ SOURCES += \ src/util/JsonQuery.cpp \ src/RunGui.cpp \ src/BrowserExtension.cpp \ - src/util/FormatTime.cpp + src/util/FormatTime.cpp \ + src/util/FunctionEventFilter.cpp HEADERS += \ src/Application.hpp \ @@ -446,7 +447,8 @@ HEADERS += \ src/util/JsonQuery.hpp \ src/RunGui.hpp \ src/BrowserExtension.hpp \ - src/util/FormatTime.hpp + src/util/FormatTime.hpp \ + src/util/FunctionEventFilter.hpp RESOURCES += \ resources/resources.qrc \ diff --git a/src/util/FunctionEventFilter.cpp b/src/util/FunctionEventFilter.cpp new file mode 100644 index 00000000..3006597b --- /dev/null +++ b/src/util/FunctionEventFilter.cpp @@ -0,0 +1,17 @@ +#include "FunctionEventFilter.hpp" + +namespace chatterino { + +FunctionEventFilter::FunctionEventFilter( + QObject *parent, std::function function) + : QObject(parent) + , function_(std::move(function)) +{ +} + +bool FunctionEventFilter::eventFilter(QObject *watched, QEvent *event) +{ + return this->function_(watched, event); +} + +} // namespace chatterino diff --git a/src/util/FunctionEventFilter.hpp b/src/util/FunctionEventFilter.hpp new file mode 100644 index 00000000..a849af6f --- /dev/null +++ b/src/util/FunctionEventFilter.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include +#include +#include + +namespace chatterino { + +class FunctionEventFilter : public QObject +{ + Q_OBJECT + +public: + FunctionEventFilter(QObject *parent, + std::function function); + +protected: + bool eventFilter(QObject *watched, QEvent *event) override; + +private: + std::function function_; +}; + +} // namespace chatterino diff --git a/src/widgets/splits/SplitHeader.cpp b/src/widgets/splits/SplitHeader.cpp index b90f7c9e..211d0b48 100644 --- a/src/widgets/splits/SplitHeader.cpp +++ b/src/widgets/splits/SplitHeader.cpp @@ -6,6 +6,7 @@ #include "providers/twitch/TwitchServer.hpp" #include "singletons/Resources.hpp" #include "singletons/Theme.hpp" +#include "util/FunctionEventFilter.hpp" #include "util/LayoutCreator.hpp" #include "widgets/Label.hpp" #include "widgets/TooltipWidget.hpp" @@ -86,33 +87,13 @@ SplitHeader::SplitHeader(Split *_split) // dropdown->setPixmap(*app->resources->splitHeaderContext->getPixmap()); // dropdown->setScaleIndependantSize(23, 23); this->addDropdownItems(dropdown.getElement()); - QObject::connect( - dropdown.getElement(), &RippleEffectButton::leftMousePress, this, - [this] { - QTimer::singleShot(80, this, [this] { - auto point = [this] { - auto bounds = - QApplication::desktop()->availableGeometry(this); - - auto point = this->dropdownButton_->mapToGlobal( - QPoint(this->dropdownButton_->width() - - this->dropdownMenu_.width(), - this->dropdownButton_->height())); - - if (point.y() + this->dropdownMenu_.height() > - bounds.bottom()) { - point.setY(point.y() - - this->dropdownMenu_.height() - - this->dropdownButton_->height()); - } - - return point; - }; - - this->dropdownMenu_.popup(point()); - this->dropdownMenu_.move(point()); - }); - }); + QObject::connect(dropdown.getElement(), + &RippleEffectButton::leftMousePress, this, [this] { + if (!this->menuVisible_) { + QTimer::singleShot( + 80, this, [this] { this->showMenu(); }); + } + }); } // ---- misc @@ -147,6 +128,15 @@ SplitHeader::SplitHeader(Split *_split) getSettings()->showUptime.connect( [this](const auto &, const auto &) { this->updateChannelText(); }, this->managedConnections_); + + this->dropdownMenu_.installEventFilter( + new FunctionEventFilter(this, [this](QObject *, QEvent *event) { + if (event->type() == QEvent::Hide) { + QTimer::singleShot(20, this, + [this] { this->menuVisible_ = false; }); + } + return false; + })); } SplitHeader::~SplitHeader() @@ -191,6 +181,28 @@ void SplitHeader::addDropdownItems(RippleEffectButton *) // clang-format on } +void SplitHeader::showMenu() +{ + auto point = [this] { + auto bounds = QApplication::desktop()->availableGeometry(this); + + auto point = this->dropdownButton_->mapToGlobal( + QPoint(this->dropdownButton_->width() - this->dropdownMenu_.width(), + this->dropdownButton_->height())); + + if (point.y() + this->dropdownMenu_.height() > bounds.bottom()) { + point.setY(point.y() - this->dropdownMenu_.height() - + this->dropdownButton_->height()); + } + + return point; + }; + + this->dropdownMenu_.popup(point()); + this->dropdownMenu_.move(point()); + this->menuVisible_ = true; +} + void SplitHeader::updateRoomModes() { this->modeUpdateRequested_.invoke(); diff --git a/src/widgets/splits/SplitHeader.hpp b/src/widgets/splits/SplitHeader.hpp index 9b3d7528..9250eda3 100644 --- a/src/widgets/splits/SplitHeader.hpp +++ b/src/widgets/splits/SplitHeader.hpp @@ -54,6 +54,7 @@ private: void addModeActions(QMenu &menu); void setupModeLabel(RippleEffectLabel &label); void addDropdownItems(RippleEffectButton *label); + void showMenu(); Split *const split_; @@ -64,15 +65,17 @@ private: pajlada::Signals::Connection onlineStatusChangedConnection_; - RippleEffectButton *dropdownButton_ = nullptr; - // Label *titleLabel; - Label *titleLabel = nullptr; - RippleEffectLabel *modeButton_ = nullptr; - RippleEffectButton *moderationButton_ = nullptr; + RippleEffectButton *dropdownButton_{}; + // Label *titleLabel{}; + Label *titleLabel{}; + RippleEffectLabel *modeButton_{}; + RippleEffectButton *moderationButton_{}; QMenu dropdownMenu_; QMenu modeMenu_; + bool menuVisible_{}; + pajlada::Signals::NoArgSignal modeUpdateRequested_; QString tooltip_;