From 3a7d7a19fdf4dae5ca528f8f3eca173df07e2909 Mon Sep 17 00:00:00 2001 From: johanneshilden Date: Sat, 7 Oct 2017 15:54:56 +0300 Subject: [PATCH] Add overlayMode property to QtMaterialDrawer --- components/qtmaterialdrawer.cpp | 82 ++++++++----- components/qtmaterialdrawer.h | 5 +- components/qtmaterialdrawer_internal.cpp | 148 ++++++++++++++++++++--- components/qtmaterialdrawer_internal.h | 66 ++++++++-- components/qtmaterialdrawer_p.h | 5 + examples/drawersettingseditor.cpp | 1 + 6 files changed, 239 insertions(+), 68 deletions(-) diff --git a/components/qtmaterialdrawer.cpp b/components/qtmaterialdrawer.cpp index 973ce9b..ed4db12 100644 --- a/components/qtmaterialdrawer.cpp +++ b/components/qtmaterialdrawer.cpp @@ -2,6 +2,7 @@ #include "qtmaterialdrawer_p.h" #include #include +#include #include #include #include @@ -36,17 +37,25 @@ void QtMaterialDrawerPrivate::init() { Q_Q(QtMaterialDrawer); - stateMachine = new QtMaterialDrawerStateMachine(q); + widget = new QtMaterialDrawerWidget; + stateMachine = new QtMaterialDrawerStateMachine(widget, q); window = new QWidget; width = 250; clickToClose = false; autoRaise = true; + closed = true; + overlay = false; QVBoxLayout *layout = new QVBoxLayout; layout->addWidget(window); - q->setLayout(layout); - q->setFixedWidth(width+16); + widget->setLayout(layout); + widget->setFixedWidth(width+16); + + widget->setParent(q); + + q->setAttribute(Qt::WA_TransparentForMouseEvents); + q->setAttribute(Qt::WA_NoSystemBackground); stateMachine->start(); QCoreApplication::processEvents(); @@ -73,7 +82,7 @@ void QtMaterialDrawer::setDrawerWidth(int width) d->width = width; d->stateMachine->updatePropertyAssignments(); - setFixedWidth(width+16); + d->widget->setFixedWidth(width+16); } int QtMaterialDrawer::drawerWidth() const @@ -125,22 +134,43 @@ bool QtMaterialDrawer::autoRaise() const return d->autoRaise; } +void QtMaterialDrawer::setOverlayMode(bool value) +{ + Q_D(QtMaterialDrawer); + + d->overlay = value; +} + +bool QtMaterialDrawer::overlayMode() const +{ + Q_D(const QtMaterialDrawer); + + return d->overlay; +} + void QtMaterialDrawer::openDrawer() { Q_D(QtMaterialDrawer); - emit d->stateMachine->enterOpenedState(); + emit d->stateMachine->signalOpen(); if (d->autoRaise) { raise(); } + if (d->overlay) { + setAttribute(Qt::WA_TransparentForMouseEvents, false); + setAttribute(Qt::WA_NoSystemBackground, false); + } } void QtMaterialDrawer::closeDrawer() { Q_D(QtMaterialDrawer); - emit d->stateMachine->enterClosedState(); + emit d->stateMachine->signalClose(); + + setAttribute(Qt::WA_TransparentForMouseEvents); + setAttribute(Qt::WA_NoSystemBackground); } bool QtMaterialDrawer::eventFilter(QObject *obj, QEvent *event) @@ -152,7 +182,8 @@ bool QtMaterialDrawer::eventFilter(QObject *obj, QEvent *event) case QEvent::MouseButtonPress: { QMouseEvent *mouseEvent; if ((mouseEvent = static_cast(event))) { - if (!geometry().contains(mouseEvent->pos()) && d->clickToClose) { + const bool canClose = d->clickToClose || d->overlay; + if (!d->widget->geometry().contains(mouseEvent->pos()) && canClose) { closeDrawer(); } } @@ -160,9 +191,9 @@ bool QtMaterialDrawer::eventFilter(QObject *obj, QEvent *event) } case QEvent::Move: case QEvent::Resize: { - QLayout *lyut = layout(); - if (lyut && 16 != lyut->contentsMargins().right()) { - lyut->setContentsMargins(0, 0, 16, 0); + QLayout *lout = d->widget->layout(); + if (lout && 16 != lout->contentsMargins().right()) { + lout->setContentsMargins(0, 0, 16, 0); } } default: @@ -175,28 +206,13 @@ void QtMaterialDrawer::paintEvent(QPaintEvent *event) { Q_UNUSED(event) + Q_D(QtMaterialDrawer); + + if (!d->overlay || d->stateMachine->isInClosedState()) { + return; + } + QPainter painter(this); - - QBrush brush; - brush.setStyle(Qt::SolidPattern); - brush.setColor(Qt::white); - painter.setBrush(brush); - painter.setPen(Qt::NoPen); - - painter.drawRect(rect().adjusted(0, 0, -16, 0)); - - QLinearGradient gradient(QPointF(width()-16, 0), QPointF(width(), 0)); - gradient.setColorAt(0, QColor(0, 0, 0, 80)); - gradient.setColorAt(0.5, QColor(0, 0, 0, 20)); - gradient.setColorAt(1, QColor(0, 0, 0, 0)); - painter.setBrush(QBrush(gradient)); - - painter.drawRect(width()-16, 0, 16, height()); -} - -QRect QtMaterialDrawer::overlayGeometry() const -{ - Q_D(const QtMaterialDrawer); - - return QtMaterialOverlayWidget::overlayGeometry().translated(d->stateMachine->offset(), 0); + painter.setOpacity(d->stateMachine->opacity()); + painter.fillRect(rect(), Qt::SolidPattern); } diff --git a/components/qtmaterialdrawer.h b/components/qtmaterialdrawer.h index 6dd69e8..2ba313c 100644 --- a/components/qtmaterialdrawer.h +++ b/components/qtmaterialdrawer.h @@ -26,6 +26,9 @@ public: void setAutoRaise(bool state); bool autoRaise() const; + void setOverlayMode(bool value); + bool overlayMode() const; + public slots: void openDrawer(); void closeDrawer(); @@ -34,8 +37,6 @@ protected: bool eventFilter(QObject *obj, QEvent *event) Q_DECL_OVERRIDE; void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; - QRect overlayGeometry() const Q_DECL_OVERRIDE; - const QScopedPointer d_ptr; private: diff --git a/components/qtmaterialdrawer_internal.cpp b/components/qtmaterialdrawer_internal.cpp index 6751def..7f32700 100644 --- a/components/qtmaterialdrawer_internal.cpp +++ b/components/qtmaterialdrawer_internal.cpp @@ -1,17 +1,29 @@ #include "qtmaterialdrawer_internal.h" #include +#include +#include #include #include #include "qtmaterialdrawer.h" -QtMaterialDrawerStateMachine::QtMaterialDrawerStateMachine(QtMaterialDrawer *drawer) - : QStateMachine(drawer), +/*! + * \class QtMaterialDrawerStateMachine + * \internal + */ + +QtMaterialDrawerStateMachine::QtMaterialDrawerStateMachine(QtMaterialDrawerWidget *drawer, QtMaterialDrawer *parent) + : QStateMachine(parent), m_drawer(drawer), - m_openState(new QState), + m_main(parent), + m_openingState(new QState), + m_openedState(new QState), + m_closingState(new QState), m_closedState(new QState), - m_offset(0) + m_opacity(0) { - addState(m_openState); + addState(m_openingState); + addState(m_openedState); + addState(m_closingState); addState(m_closedState); setInitialState(m_closedState); @@ -19,24 +31,57 @@ QtMaterialDrawerStateMachine::QtMaterialDrawerStateMachine(QtMaterialDrawer *dra QSignalTransition *transition; QPropertyAnimation *animation; - transition = new QSignalTransition(this, SIGNAL(enterOpenedState())); - transition->setTargetState(m_openState); + transition = new QSignalTransition(this, SIGNAL(signalOpen())); + transition->setTargetState(m_openingState); m_closedState->addTransition(transition); - animation = new QPropertyAnimation(this, "offset", this); + animation = new QPropertyAnimation(drawer, "offset", this); animation->setDuration(220); animation->setEasingCurve(QEasingCurve::OutCirc); transition->addAnimation(animation); - transition = new QSignalTransition(this, SIGNAL(enterClosedState())); - transition->setTargetState(m_closedState); - m_openState->addTransition(transition); + animation = new QPropertyAnimation(this, "opacity", this); + animation->setDuration(220); + transition->addAnimation(animation); - animation = new QPropertyAnimation(this, "offset", this); + transition = new QSignalTransition(animation, SIGNAL(finished())); + transition->setTargetState(m_openedState); + m_openingState->addTransition(transition); + + transition = new QSignalTransition(this, SIGNAL(signalClose())); + transition->setTargetState(m_closingState); + m_openingState->addTransition(transition); + + animation = new QPropertyAnimation(this, "opacity", this); + animation->setDuration(220); + transition->addAnimation(animation); + + animation = new QPropertyAnimation(drawer, "offset", this); animation->setDuration(220); animation->setEasingCurve(QEasingCurve::InCirc); transition->addAnimation(animation); + transition = new QSignalTransition(animation, SIGNAL(finished())); + transition->setTargetState(m_closedState); + m_closingState->addTransition(transition); + + transition = new QSignalTransition(this, SIGNAL(signalClose())); + transition->setTargetState(m_closingState); + m_openedState->addTransition(transition); + + animation = new QPropertyAnimation(drawer, "offset", this); + animation->setDuration(220); + animation->setEasingCurve(QEasingCurve::InCirc); + transition->addAnimation(animation); + + animation = new QPropertyAnimation(this, "opacity", this); + animation->setDuration(220); + transition->addAnimation(animation); + + transition = new QSignalTransition(animation, SIGNAL(finished())); + transition->setTargetState(m_closedState); + m_closingState->addTransition(transition); + updatePropertyAssignments(); } @@ -44,18 +89,81 @@ QtMaterialDrawerStateMachine::~QtMaterialDrawerStateMachine() { } -void QtMaterialDrawerStateMachine::setOffset(int offset) +void QtMaterialDrawerStateMachine::setOpacity(qreal opacity) { - m_offset = offset; + m_opacity = opacity; + m_main->update(); +} - QWidget *widget = m_drawer->parentWidget(); - if (widget) { - m_drawer->setGeometry(widget->rect().translated(offset, 0)); - } +bool QtMaterialDrawerStateMachine::isInClosedState() const +{ + return m_closedState->active(); } void QtMaterialDrawerStateMachine::updatePropertyAssignments() { - m_closedState->assignProperty(this, "offset", -(m_drawer->width()+32)); - m_openState->assignProperty(this, "offset", 0); + const qreal closedOffset = -(m_drawer->width()+32); + + m_closingState->assignProperty(m_drawer, "offset", closedOffset); + m_closedState->assignProperty(m_drawer, "offset", closedOffset); + + m_closingState->assignProperty(this, "opacity", 0); + m_closedState->assignProperty(this, "opacity", 0); + + m_openingState->assignProperty(m_drawer, "offset", 0); + m_openingState->assignProperty(this, "opacity", 0.4); +} + +/*! + * \class QtMaterialDrawerWidget + * \internal + */ + +QtMaterialDrawerWidget::QtMaterialDrawerWidget(QWidget *parent) + : QtMaterialOverlayWidget(parent), + m_offset(0) +{ +} + +QtMaterialDrawerWidget::~QtMaterialDrawerWidget() +{ +} + +void QtMaterialDrawerWidget::setOffset(int offset) +{ + m_offset = offset; + + QWidget *widget = parentWidget(); + if (widget) { + setGeometry(widget->rect().translated(offset, 0)); + } + update(); +} + +void QtMaterialDrawerWidget::paintEvent(QPaintEvent *event) +{ + Q_UNUSED(event) + + QPainter painter(this); + + QBrush brush; + brush.setStyle(Qt::SolidPattern); + brush.setColor(Qt::white); + painter.setBrush(brush); + painter.setPen(Qt::NoPen); + + painter.drawRect(rect().adjusted(0, 0, -16, 0)); + + QLinearGradient gradient(QPointF(width()-16, 0), QPointF(width(), 0)); + gradient.setColorAt(0, QColor(0, 0, 0, 80)); + gradient.setColorAt(0.5, QColor(0, 0, 0, 20)); + gradient.setColorAt(1, QColor(0, 0, 0, 0)); + painter.setBrush(QBrush(gradient)); + + painter.drawRect(width()-16, 0, 16, height()); +} + +QRect QtMaterialDrawerWidget::overlayGeometry() const +{ + return QtMaterialOverlayWidget::overlayGeometry().translated(m_offset, 0); } diff --git a/components/qtmaterialdrawer_internal.h b/components/qtmaterialdrawer_internal.h index 746620d..76d219d 100644 --- a/components/qtmaterialdrawer_internal.h +++ b/components/qtmaterialdrawer_internal.h @@ -2,35 +2,75 @@ #define DRAWER_INTERNAL_H #include +#include "lib/qtmaterialoverlaywidget.h" class QtMaterialDrawer; +class QtMaterialDrawerWidget; class QtMaterialDrawerStateMachine : public QStateMachine { Q_OBJECT + Q_PROPERTY(qreal opacity WRITE setOpacity READ opacity) + +public: + explicit QtMaterialDrawerStateMachine(QtMaterialDrawerWidget *drawer, + QtMaterialDrawer *parent); + ~QtMaterialDrawerStateMachine(); + + void setOpacity(qreal opacity); + inline qreal opacity() const; + + bool isInClosedState() const; + + void updatePropertyAssignments(); + +signals: + void signalOpen(); + void signalClose(); + +private: + Q_DISABLE_COPY(QtMaterialDrawerStateMachine) + + QtMaterialDrawerWidget *const m_drawer; + QtMaterialDrawer *const m_main; + QState *const m_openingState; + QState *const m_openedState; + QState *const m_closingState; + QState *const m_closedState; + qreal m_opacity; +}; + +inline qreal QtMaterialDrawerStateMachine::opacity() const +{ + return m_opacity; +} + +class QtMaterialDrawerWidget : public QtMaterialOverlayWidget +{ + Q_OBJECT + Q_PROPERTY(int offset WRITE setOffset READ offset) public: - explicit QtMaterialDrawerStateMachine(QtMaterialDrawer *drawer); - ~QtMaterialDrawerStateMachine(); + explicit QtMaterialDrawerWidget(QWidget *parent = 0); + ~QtMaterialDrawerWidget(); void setOffset(int offset); - inline int offset() const { return m_offset; } + inline int offset() const; - void updatePropertyAssignments(); +protected: + void paintEvent(QPaintEvent *event) Q_DECL_OVERRIDE; -signals: - void enterOpenedState(); - void enterClosedState(); + QRect overlayGeometry() const Q_DECL_OVERRIDE; private: - Q_DISABLE_COPY(QtMaterialDrawerStateMachine) - - QtMaterialDrawer *const m_drawer; - QState *const m_openState; - QState *const m_closedState; - int m_offset; + int m_offset; }; +inline int QtMaterialDrawerWidget::offset() const +{ + return m_offset; +} + #endif // DRAWER_INTERNAL_H diff --git a/components/qtmaterialdrawer_p.h b/components/qtmaterialdrawer_p.h index 1a1247f..cdd064d 100644 --- a/components/qtmaterialdrawer_p.h +++ b/components/qtmaterialdrawer_p.h @@ -4,6 +4,7 @@ #include class QtMaterialDrawer; +class QtMaterialDrawerWidget; class QtMaterialDrawerStateMachine; class QtMaterialDrawerPrivate @@ -16,13 +17,17 @@ public: ~QtMaterialDrawerPrivate(); void init(); + void setClosed(bool value = true); QtMaterialDrawer *const q_ptr; + QtMaterialDrawerWidget *widget; QtMaterialDrawerStateMachine *stateMachine; QWidget *window; int width; bool clickToClose; bool autoRaise; + bool closed; + bool overlay; }; #endif // DRAWER_P_H diff --git a/examples/drawersettingseditor.cpp b/examples/drawersettingseditor.cpp index e90773e..9444d52 100644 --- a/examples/drawersettingseditor.cpp +++ b/examples/drawersettingseditor.cpp @@ -27,6 +27,7 @@ DrawerSettingsEditor::DrawerSettingsEditor(QWidget *parent) m_drawer->setParent(this); m_drawer->setClickOutsideToClose(true); + m_drawer->setOverlayMode(true); setupForm();