Skip to content

Commit

Permalink
Support temporarily dragging progress details out of the way
Browse files Browse the repository at this point in the history
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 <[email protected]>
Reviewed-by: <[email protected]>
Reviewed-by: Qt CI Bot <[email protected]>
  • Loading branch information
e4z9 committed Nov 9, 2022
1 parent a8801ef commit 1beaa07
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/plugins/coreplugin/progressmanager/futureprogress.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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 *)
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/coreplugin/progressmanager/futureprogress.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class CORE_EXPORT FutureProgress : public QWidget
void subtitleInStatusBarChanged();

protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
void paintEvent(QPaintEvent *) override;

private:
Expand Down
9 changes: 4 additions & 5 deletions src/plugins/coreplugin/progressmanager/progressbar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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 *)
Expand Down
2 changes: 1 addition & 1 deletion src/plugins/coreplugin/progressmanager/progressbar.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class ProgressBar : public QWidget
void clicked();

protected:
void mousePressEvent(QMouseEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;

private:
QFont titleFont() const;
Expand Down
68 changes: 65 additions & 3 deletions src/plugins/coreplugin/progressmanager/progressview.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@

#include "progressview.h"

#include <QApplication>
#include <QEvent>
#include <QMouseEvent>
#include <QVBoxLayout>

using namespace Core;
Expand All @@ -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);
}

Expand All @@ -44,6 +48,7 @@ void ProgressView::setReferenceWidget(QWidget *widget)
m_referenceWidget = widget;
if (m_referenceWidget)
installEventFilter(this);
m_anchorBottomRight = {};
reposition();
}

Expand All @@ -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);
}
Expand All @@ -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());
}
17 changes: 15 additions & 2 deletions src/plugins/coreplugin/progressmanager/progressview.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@

#pragma once

#include "progressmanager.h"

#include <QWidget>

#include <optional>

QT_BEGIN_NAMESPACE
class QVBoxLayout;
Expand Down Expand Up @@ -34,15 +33,29 @@ class ProgressView : public QWidget
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;
};

Expand Down

0 comments on commit 1beaa07

Please sign in to comment.