diff options
author | Eike Ziller <eike.ziller@qt.io> | 2022-10-20 12:18:42 +0200 |
---|---|---|
committer | Eike Ziller <eike.ziller@qt.io> | 2022-11-09 11:11:26 +0000 |
commit | 1beaa0771cf45abd04d62e5aa833d289fcf1019e (patch) | |
tree | 212427cdda39b9da3c8688f0b3e4d0b64727ef86 | |
parent | a8801eff5faa99104cc9016fe5d10f77ba2bc3c9 (diff) |
Support temporarily dragging progress details out of the way
The progress details can cover UI that the user is interested in, and
with e.g. the Clangd indexing, building and update check we have some
long term progress details visible.
It is already possible to hide the details by pressing the tool button,
but another natural reaction is to just drag the UI out of the way.
Add support to drag the progress details to a different position
temporarily. The original "preferred" location is reset either when we
show a new progress detail and we didn't show anything before, or when
the user hides and shows the progress details via the button.
Fixes: QTCREATORBUG-28078
Change-Id: Ie9cecf8b4a34385426a4de3baaf4da92e6387254
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
6 files changed, 88 insertions, 14 deletions
diff --git a/src/plugins/coreplugin/progressmanager/futureprogress.cpp b/src/plugins/coreplugin/progressmanager/futureprogress.cpp index b2ea4fdd96..1590931839 100644 --- a/src/plugins/coreplugin/progressmanager/futureprogress.cpp +++ b/src/plugins/coreplugin/progressmanager/futureprogress.cpp @@ -296,11 +296,11 @@ QFuture<void> FutureProgress::future() const /*! \internal */ -void FutureProgress::mousePressEvent(QMouseEvent *event) +void FutureProgress::mouseReleaseEvent(QMouseEvent *event) { if (event->button() == Qt::LeftButton) emit clicked(); - QWidget::mousePressEvent(event); + QWidget::mouseReleaseEvent(event); } void FutureProgress::paintEvent(QPaintEvent *) diff --git a/src/plugins/coreplugin/progressmanager/futureprogress.h b/src/plugins/coreplugin/progressmanager/futureprogress.h index 0f6630cd8c..20bdf1784d 100644 --- a/src/plugins/coreplugin/progressmanager/futureprogress.h +++ b/src/plugins/coreplugin/progressmanager/futureprogress.h @@ -74,7 +74,7 @@ signals: void subtitleInStatusBarChanged(); protected: - void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; void paintEvent(QPaintEvent *) override; private: diff --git a/src/plugins/coreplugin/progressmanager/progressbar.cpp b/src/plugins/coreplugin/progressmanager/progressbar.cpp index e143b26251..c1ced8961f 100644 --- a/src/plugins/coreplugin/progressmanager/progressbar.cpp +++ b/src/plugins/coreplugin/progressmanager/progressbar.cpp @@ -181,17 +181,15 @@ QSize ProgressBar::sizeHint() const namespace { const int INDENT = 6; } -void ProgressBar::mousePressEvent(QMouseEvent *event) +void ProgressBar::mouseReleaseEvent(QMouseEvent *event) { if (m_cancelEnabled) { if (event->modifiers() == Qt::NoModifier && m_cancelRect.contains(event->pos())) { - event->accept(); emit clicked(); - return; } } - QWidget::mousePressEvent(event); + QWidget::mouseReleaseEvent(event); } QFont ProgressBar::titleFont() const @@ -202,9 +200,10 @@ QFont ProgressBar::titleFont() const return boldFont; } -void ProgressBar::mouseMoveEvent(QMouseEvent *) +void ProgressBar::mouseMoveEvent(QMouseEvent *ev) { update(); + QWidget::mouseMoveEvent(ev); } void ProgressBar::paintEvent(QPaintEvent *) diff --git a/src/plugins/coreplugin/progressmanager/progressbar.h b/src/plugins/coreplugin/progressmanager/progressbar.h index 060f0e947b..5c33273e8c 100644 --- a/src/plugins/coreplugin/progressmanager/progressbar.h +++ b/src/plugins/coreplugin/progressmanager/progressbar.h @@ -49,7 +49,7 @@ signals: void clicked(); protected: - void mousePressEvent(QMouseEvent *event) override; + void mouseReleaseEvent(QMouseEvent *event) override; private: QFont titleFont() const; diff --git a/src/plugins/coreplugin/progressmanager/progressview.cpp b/src/plugins/coreplugin/progressmanager/progressview.cpp index f145d34428..be2c113e8d 100644 --- a/src/plugins/coreplugin/progressmanager/progressview.cpp +++ b/src/plugins/coreplugin/progressmanager/progressview.cpp @@ -3,7 +3,9 @@ #include "progressview.h" +#include <QApplication> #include <QEvent> +#include <QMouseEvent> #include <QVBoxLayout> using namespace Core; @@ -24,6 +26,8 @@ ProgressView::~ProgressView() = default; void ProgressView::addProgressWidget(QWidget *widget) { + if (m_layout->count() == 0) + m_anchorBottomRight = {}; // reset temporarily user-moved progress details m_layout->insertWidget(0, widget); } @@ -44,6 +48,7 @@ void ProgressView::setReferenceWidget(QWidget *widget) m_referenceWidget = widget; if (m_referenceWidget) installEventFilter(this); + m_anchorBottomRight = {}; reposition(); } @@ -61,6 +66,9 @@ bool ProgressView::event(QEvent *event) } else if (event->type() == QEvent::Leave) { m_hovered = false; emit hoveredChanged(m_hovered); + } else if (event->type() == QEvent::Show) { + m_anchorBottomRight = {}; // reset temporarily user-moved progress details + reposition(); } return QWidget::event(event); } @@ -72,11 +80,65 @@ bool ProgressView::eventFilter(QObject *obj, QEvent *event) return false; } +void ProgressView::mousePressEvent(QMouseEvent *ev) +{ + if ((ev->buttons() & Qt::LeftButton) && parentWidget() && m_referenceWidget) { + m_clickPosition = ev->globalPosition(); + m_clickPositionInWidget = ev->position(); + } else { + m_clickPosition.reset(); + } + QWidget::mousePressEvent(ev); +} + +static QPoint boundedInParent(QWidget *widget, const QPoint &pos, QWidget *parent) +{ + QPoint bounded = pos; + bounded.setX(qBound(widget->rect().width(), bounded.x(), parent->width())); + bounded.setY(qBound(widget->rect().height(), bounded.y(), parent->height())); + return bounded; +} + +void ProgressView::mouseMoveEvent(QMouseEvent *ev) +{ + if (m_clickPosition) { + const QPointF current = ev->globalPosition(); + if (m_isDragging + || (current - *m_clickPosition).manhattanLength() > QApplication::startDragDistance()) { + m_isDragging = true; + const QPointF newGlobal = current - m_clickPositionInWidget; + const QPoint bottomRightInParent = parentWidget()->mapFromGlobal(newGlobal).toPoint() + + rect().bottomRight(); + m_anchorBottomRight = boundedInParent(this, bottomRightInParent, parentWidget()) + - topRightReferenceInParent(); + if (m_anchorBottomRight.manhattanLength() <= QApplication::startDragDistance()) + m_anchorBottomRight = {}; + QMetaObject::invokeMethod(this, [this] { reposition(); }); + } + } + QWidget::mouseMoveEvent(ev); +} + +void ProgressView::mouseReleaseEvent(QMouseEvent *ev) +{ + if ((ev->buttons() & Qt::LeftButton)) { + m_clickPosition.reset(); + m_isDragging = false; + } + QWidget::mouseReleaseEvent(ev); +} + void ProgressView::reposition() { if (!parentWidget() || !m_referenceWidget) return; - QPoint topRightReferenceInParent = - m_referenceWidget->mapTo(parentWidget(), m_referenceWidget->rect().topRight()); - move(topRightReferenceInParent - rect().bottomRight()); + move(boundedInParent(this, topRightReferenceInParent() + m_anchorBottomRight, parentWidget()) + - rect().bottomRight()); +} + +QPoint ProgressView::topRightReferenceInParent() const +{ + if (!parentWidget() || !m_referenceWidget) + return {}; + return m_referenceWidget->mapTo(parentWidget(), m_referenceWidget->rect().topRight()); } diff --git a/src/plugins/coreplugin/progressmanager/progressview.h b/src/plugins/coreplugin/progressmanager/progressview.h index f9bdf5043b..60176d374a 100644 --- a/src/plugins/coreplugin/progressmanager/progressview.h +++ b/src/plugins/coreplugin/progressmanager/progressview.h @@ -3,10 +3,9 @@ #pragma once -#include "progressmanager.h" - #include <QWidget> +#include <optional> QT_BEGIN_NAMESPACE class QVBoxLayout; @@ -34,15 +33,29 @@ public: protected: bool event(QEvent *event) override; bool eventFilter(QObject *obj, QEvent *event) override; + void mousePressEvent(QMouseEvent *ev) override; + void mouseMoveEvent(QMouseEvent *ev) override; + void mouseReleaseEvent(QMouseEvent *ev) override; signals: void hoveredChanged(bool hovered); private: void reposition(); + QPoint topRightReferenceInParent() const; QVBoxLayout *m_layout; QWidget *m_referenceWidget = nullptr; + + // dragging + std::optional<QPointF> m_clickPosition; + QPointF m_clickPositionInWidget; + bool m_isDragging = false; + + // relative to referenceWidget's topRight in parentWidget() + // can be changed by the user by dragging + QPoint m_anchorBottomRight; + bool m_hovered = false; }; |