#include "ElaScrollBar.h" #include #include #include #include #include #include #include "ElaMenu.h" #include "ElaScrollBarStyle.h" #include "private/ElaScrollBarPrivate.h" Q_PROPERTY_CREATE_Q_CPP(ElaScrollBar, bool, IsAnimation) Q_PROPERTY_CREATE_Q_CPP(ElaScrollBar, qreal, SpeedLimit) ElaScrollBar::ElaScrollBar(QWidget *parent) : QScrollBar(parent), d_ptr(new ElaScrollBarPrivate()) { Q_D(ElaScrollBar); d->q_ptr = this; setSingleStep(1); setObjectName("ElaScrollBar"); setAttribute(Qt::WA_OpaquePaintEvent, false); d->_pSpeedLimit = 20; d->_pTargetMaximum = 0; d->_pIsAnimation = false; connect(this, &ElaScrollBar::rangeChanged, d, &ElaScrollBarPrivate::onRangeChanged); ElaScrollBarStyle *scrollBarStyle = new ElaScrollBarStyle(style()); scrollBarStyle->setScrollBar(this); setStyle(scrollBarStyle); d->_slideSmoothAnimation = new QPropertyAnimation(this, "value"); d->_slideSmoothAnimation->setEasingCurve(QEasingCurve::OutSine); d->_slideSmoothAnimation->setDuration(300); connect(d->_slideSmoothAnimation, &QPropertyAnimation::finished, this, [=]() { d->_scrollValue = value(); }); d->_expandTimer = new QTimer(this); connect(d->_expandTimer, &QTimer::timeout, this, [=]() { d->_expandTimer->stop(); d->_isExpand = underMouse(); scrollBarStyle->startExpandAnimation(d->_isExpand); }); } ElaScrollBar::ElaScrollBar(Qt::Orientation orientation, QWidget *parent) : ElaScrollBar(parent) { setOrientation(orientation); } ElaScrollBar::ElaScrollBar(QScrollBar *originScrollBar, QAbstractScrollArea *parent) : ElaScrollBar(parent) { Q_D(ElaScrollBar); if (!originScrollBar || !parent) { qCritical() << "Invalid origin or parent!"; return; } d->_originScrollArea = parent; Qt::Orientation orientation = originScrollBar->orientation(); setOrientation(orientation); orientation == Qt::Horizontal ? parent->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff) : parent->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); parent->installEventFilter(this); d->_originScrollBar = originScrollBar; d->_initAllConfig(); connect(d->_originScrollBar, &QScrollBar::valueChanged, this, [=](int value) { d->_handleScrollBarValueChanged(this, value); }); connect(this, &QScrollBar::valueChanged, this, [=](int value) { d->_handleScrollBarValueChanged(d->_originScrollBar, value); }); connect(d->_originScrollBar, &QScrollBar::rangeChanged, this, [=](int min, int max) { d->_handleScrollBarRangeChanged(min, max); }); } ElaScrollBar::~ElaScrollBar() { delete this->style(); } bool ElaScrollBar::event(QEvent *event) { Q_D(ElaScrollBar); switch (event->type()) { case QEvent::Enter: { d->_expandTimer->stop(); if (!d->_isExpand) { d->_expandTimer->start(350); } break; } case QEvent::Leave: { d->_expandTimer->stop(); if (d->_isExpand) { d->_expandTimer->start(350); } break; } default: { break; } } return QScrollBar::event(event); } bool ElaScrollBar::eventFilter(QObject *watched, QEvent *event) { Q_D(ElaScrollBar); switch (event->type()) { case QEvent::Show: case QEvent::Resize: case QEvent::LayoutRequest: { d->_handleScrollBarGeometry(); break; } default: { break; } } return QScrollBar::eventFilter(watched, event); } void ElaScrollBar::mousePressEvent(QMouseEvent *event) { Q_D(ElaScrollBar); d->_slideSmoothAnimation->stop(); QScrollBar::mousePressEvent(event); d->_scrollValue = value(); } void ElaScrollBar::mouseReleaseEvent(QMouseEvent *event) { Q_D(ElaScrollBar); d->_slideSmoothAnimation->stop(); QScrollBar::mouseReleaseEvent(event); d->_scrollValue = value(); } void ElaScrollBar::mouseMoveEvent(QMouseEvent *event) { Q_D(ElaScrollBar); d->_slideSmoothAnimation->stop(); QScrollBar::mouseMoveEvent(event); d->_scrollValue = value(); } void ElaScrollBar::wheelEvent(QWheelEvent *event) { Q_D(ElaScrollBar); int verticalDelta = event->angleDelta().y(); if (d->_slideSmoothAnimation->state() == QAbstractAnimation::Stopped) { d->_scrollValue = value(); } if (verticalDelta != 0) { if ((value() == minimum() && verticalDelta > 0) || (value() == maximum() && verticalDelta < 0)) { QScrollBar::wheelEvent(event); return; } d->_scroll(event->modifiers(), verticalDelta); } else { int horizontalDelta = event->angleDelta().x(); if ((value() == minimum() && horizontalDelta > 0) || (value() == maximum() && horizontalDelta < 0)) { QScrollBar::wheelEvent(event); return; } d->_scroll(event->modifiers(), horizontalDelta); } event->accept(); } void ElaScrollBar::contextMenuEvent(QContextMenuEvent *event) { Q_D(ElaScrollBar); bool horiz = this->orientation() == Qt::Horizontal; QPointer menu = new ElaMenu(this); menu->setMenuItemHeight(27); // Scroll here QAction *actScrollHere = menu->addElaIconAction(ElaIconType::UpDownLeftRight, tr("滚动到此处")); menu->addSeparator(); // Left edge Top QAction *actScrollTop = menu->addElaIconAction(horiz ? ElaIconType::ArrowLeftToLine : ElaIconType::ArrowUpToLine, horiz ? tr("左边缘") : tr("顶端")); // Right edge Bottom QAction *actScrollBottom = menu->addElaIconAction(horiz ? ElaIconType::ArrowRightToLine : ElaIconType::ArrowDownToLine, horiz ? tr("右边缘") : tr("底部")); menu->addSeparator(); // Page left Page up QAction *actPageUp = menu->addElaIconAction(horiz ? ElaIconType::AnglesLeft : ElaIconType::AnglesUp, horiz ? tr("向左翻页") : tr("向上翻页")); // Page right Page down QAction *actPageDn = menu->addElaIconAction(horiz ? ElaIconType::AnglesRight : ElaIconType::AnglesDown, horiz ? tr("向右翻页") : tr("向下翻页")); menu->addSeparator(); // Scroll left Scroll up QAction *actScrollUp = menu->addElaIconAction(horiz ? ElaIconType::AngleLeft : ElaIconType::AngleUp, horiz ? tr("向左滚动") : tr("向上滚动")); // Scroll right Scroll down QAction *actScrollDn = menu->addElaIconAction(horiz ? ElaIconType::AngleRight : ElaIconType::AngleDown, horiz ? tr("向右滚动") : tr("向下滚动")); QAction *actionSelected = menu->exec(event->globalPos()); delete menu; if (!actionSelected) { return; } if (actionSelected == actScrollHere) { setValue(d->_pixelPosToRangeValue(horiz ? event->pos().x() : event->pos().y())); } else if (actionSelected == actScrollTop) { triggerAction(QAbstractSlider::SliderToMinimum); } else if (actionSelected == actScrollBottom) { triggerAction(QAbstractSlider::SliderToMaximum); } else if (actionSelected == actPageUp) { triggerAction(QAbstractSlider::SliderPageStepSub); } else if (actionSelected == actPageDn) { triggerAction(QAbstractSlider::SliderPageStepAdd); } else if (actionSelected == actScrollUp) { triggerAction(QAbstractSlider::SliderSingleStepSub); } else if (actionSelected == actScrollDn) { triggerAction(QAbstractSlider::SliderSingleStepAdd); } }