From a41c0e65ac5f6e18e7350f64a2820faadf87be8a Mon Sep 17 00:00:00 2001 From: itsmattkc Date: Thu, 5 Mar 2020 00:34:39 +1100 Subject: [PATCH] re-implemented resizable scrollbar (still somewhat crude) --- app/widget/CMakeLists.txt | 1 + app/widget/resizablescrollbar/CMakeLists.txt | 22 +++ .../resizablescrollbar/resizablescrollbar.cpp | 133 ++++++++++++++++++ .../resizablescrollbar/resizablescrollbar.h | 44 ++++++ app/widget/timebased/timebased.cpp | 10 +- app/widget/timebased/timebased.h | 8 +- 6 files changed, 213 insertions(+), 5 deletions(-) create mode 100644 app/widget/resizablescrollbar/CMakeLists.txt create mode 100644 app/widget/resizablescrollbar/resizablescrollbar.cpp create mode 100644 app/widget/resizablescrollbar/resizablescrollbar.h diff --git a/app/widget/CMakeLists.txt b/app/widget/CMakeLists.txt index dc16dd0ec..842d835a5 100644 --- a/app/widget/CMakeLists.txt +++ b/app/widget/CMakeLists.txt @@ -29,6 +29,7 @@ add_subdirectory(panel) add_subdirectory(playbackcontrols) add_subdirectory(projectexplorer) add_subdirectory(projecttoolbar) +add_subdirectory(resizablescrollbar) add_subdirectory(slider) add_subdirectory(taskview) add_subdirectory(timebased) diff --git a/app/widget/resizablescrollbar/CMakeLists.txt b/app/widget/resizablescrollbar/CMakeLists.txt new file mode 100644 index 000000000..a31827510 --- /dev/null +++ b/app/widget/resizablescrollbar/CMakeLists.txt @@ -0,0 +1,22 @@ +# Olive - Non-Linear Video Editor +# Copyright (C) 2019 Olive Team +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +set(OLIVE_SOURCES + ${OLIVE_SOURCES} + widget/resizablescrollbar/resizablescrollbar.h + widget/resizablescrollbar/resizablescrollbar.cpp + PARENT_SCOPE +) diff --git a/app/widget/resizablescrollbar/resizablescrollbar.cpp b/app/widget/resizablescrollbar/resizablescrollbar.cpp new file mode 100644 index 000000000..fc6a79d44 --- /dev/null +++ b/app/widget/resizablescrollbar/resizablescrollbar.cpp @@ -0,0 +1,133 @@ +#include "resizablescrollbar.h" + +#include +#include +#include +#include + +#include "common/range.h" + +const int ResizableScrollBar::kHandleWidth = 10; + +ResizableScrollBar::ResizableScrollBar(QWidget *parent) : + QScrollBar(parent) +{ + Init(); +} + +ResizableScrollBar::ResizableScrollBar(Qt::Orientation orientation, QWidget *parent): + QScrollBar(orientation, parent) +{ + Init(); +} + +void ResizableScrollBar::mousePressEvent(QMouseEvent *event) +{ + if (mouse_handle_state_ == kNotInHandle) { + QScrollBar::mousePressEvent(event); + } else { + mouse_dragging_ = true; + + mouse_drag_start_ = GetActiveMousePos(event); + } +} + +void ResizableScrollBar::mouseMoveEvent(QMouseEvent *event) +{ + QStyleOptionSlider opt; + initStyleOption(&opt); + + QRect sr = style()->subControlRect(QStyle::CC_ScrollBar, &opt, + QStyle::SC_ScrollBarSlider, this); + QRect gr = style()->subControlRect(QStyle::CC_ScrollBar, &opt, + QStyle::SC_ScrollBarGroove, this); + + if (mouse_dragging_) { + + int new_drag_pos = GetActiveMousePos(event); + int mouse_movement = new_drag_pos - mouse_drag_start_; + mouse_drag_start_ = new_drag_pos; + + if (mouse_handle_state_ == kInTopHandle) { + mouse_movement = -mouse_movement; + } + + double scale_multiplier = static_cast(sr.width()) / static_cast(sr.width() + mouse_movement); + emit RequestScale(scale_multiplier); + + if (mouse_handle_state_ == kInTopHandle) { + int slider_min = gr.x(); + int slider_max = gr.right() - (sr.width() + mouse_movement); + int val = QStyle::sliderValueFromPosition(minimum(), + maximum(), + event->pos().x() - slider_min, + slider_max - slider_min, + opt.upsideDown); + + setValue(val); + } else { + setValue(qRound(static_cast(value()) * scale_multiplier)); + } + + } else { + + int mouse_pos, top, bottom; + Qt::CursorShape target_cursor; + mouse_pos = GetActiveMousePos(event); + + if (orientation() == Qt::Horizontal) { + top = sr.left(); + bottom = sr.right(); + target_cursor = Qt::SizeHorCursor; + } else { + top = sr.top(); + bottom = sr.bottom(); + target_cursor = Qt::SizeVerCursor; + } + + if (InRange(mouse_pos, top, kHandleWidth)) { + mouse_handle_state_ = kInTopHandle; + } else if (InRange(mouse_pos, bottom, kHandleWidth)) { + mouse_handle_state_ = kInBottomHandle; + } else { + mouse_handle_state_ = kNotInHandle; + } + + if (mouse_handle_state_ == kNotInHandle) { + unsetCursor(); + } else { + setCursor(target_cursor); + } + + QScrollBar::mouseMoveEvent(event); + + } +} + +void ResizableScrollBar::mouseReleaseEvent(QMouseEvent *event) +{ + if (mouse_dragging_) { + mouse_dragging_ = false; + } else { + QScrollBar::mouseReleaseEvent(event); + } +} + +void ResizableScrollBar::Init() +{ + setSingleStep(20); + setMaximum(0); + setMouseTracking(true); + + mouse_handle_state_= kNotInHandle; + mouse_dragging_ = false; +} + +int ResizableScrollBar::GetActiveMousePos(QMouseEvent *event) +{ + if (orientation() == Qt::Horizontal) { + return event->pos().x(); + } else { + return event->pos().y(); + } +} diff --git a/app/widget/resizablescrollbar/resizablescrollbar.h b/app/widget/resizablescrollbar/resizablescrollbar.h new file mode 100644 index 000000000..ac5f80a66 --- /dev/null +++ b/app/widget/resizablescrollbar/resizablescrollbar.h @@ -0,0 +1,44 @@ +#ifndef RESIZABLESCROLLBAR_H +#define RESIZABLESCROLLBAR_H + +#include + +class ResizableScrollBar : public QScrollBar +{ + Q_OBJECT +public: + ResizableScrollBar(QWidget* parent = nullptr); + ResizableScrollBar(Qt::Orientation orientation, QWidget* parent = nullptr); + +signals: + void RequestScale(const double& multiplier); + +protected: + virtual void mousePressEvent(QMouseEvent* event) override; + + virtual void mouseMoveEvent(QMouseEvent* event) override; + + virtual void mouseReleaseEvent(QMouseEvent* event) override; + +private: + static const int kHandleWidth; + + enum MouseHandleState { + kNotInHandle, + kInTopHandle, + kInBottomHandle + }; + + void Init(); + + int GetActiveMousePos(QMouseEvent* event); + + MouseHandleState mouse_handle_state_; + + bool mouse_dragging_; + + int mouse_drag_start_; + +}; + +#endif // RESIZABLESCROLLBAR_H diff --git a/app/widget/timebased/timebased.cpp b/app/widget/timebased/timebased.cpp index 428697347..b7feb9bb6 100644 --- a/app/widget/timebased/timebased.cpp +++ b/app/widget/timebased/timebased.cpp @@ -10,7 +10,8 @@ TimeBasedWidget::TimeBasedWidget(bool ruler_text_visible, bool ruler_cache_statu ruler_ = new TimeRuler(ruler_text_visible, ruler_cache_status_visible, this); connect(ruler_, &TimeRuler::TimeChanged, this, &TimeBasedWidget::SetTimeAndSignal); - scrollbar_ = new QScrollBar(Qt::Horizontal, this); + scrollbar_ = new ResizableScrollBar(Qt::Horizontal, this); + connect(scrollbar_, &ResizableScrollBar::RequestScale, this, &TimeBasedWidget::ScrollBarResized); } void TimeBasedWidget::SetScaleAndCenterOnPlayhead(const double &scale) @@ -65,12 +66,17 @@ void TimeBasedWidget::UpdateMaximumScroll() scrollbar_->setMaximum(qMax(0, qCeil(TimeToScene(viewer_node_->Length())) - width())); } +void TimeBasedWidget::ScrollBarResized(const double &multiplier) +{ + SetScale(GetScale() * multiplier); +} + TimeRuler *TimeBasedWidget::ruler() const { return ruler_; } -QScrollBar *TimeBasedWidget::scrollbar() const +ResizableScrollBar *TimeBasedWidget::scrollbar() const { return scrollbar_; } diff --git a/app/widget/timebased/timebased.h b/app/widget/timebased/timebased.h index b68180c91..50b0f4882 100644 --- a/app/widget/timebased/timebased.h +++ b/app/widget/timebased/timebased.h @@ -1,10 +1,10 @@ #ifndef TIMEBASEDWIDGET_H #define TIMEBASEDWIDGET_H -#include #include #include "node/output/viewer/viewer.h" +#include "widget/resizablescrollbar/resizablescrollbar.h" #include "widget/timelinewidget/timelinescaledobject.h" #include "widget/timeruler/timeruler.h" @@ -54,7 +54,7 @@ protected slots: void SetTimeAndSignal(const int64_t& t); protected: - QScrollBar* scrollbar() const; + ResizableScrollBar* scrollbar() const; virtual void TimebaseChangedEvent(const rational&) override; @@ -88,13 +88,15 @@ private: TimeRuler* ruler_; - QScrollBar* scrollbar_; + ResizableScrollBar* scrollbar_; bool auto_max_scrollbar_; private slots: void UpdateMaximumScroll(); + void ScrollBarResized(const double& multiplier); + }; #endif // TIMEBASEDWIDGET_H