From: Soeren Apel Date: Tue, 13 Aug 2019 07:18:46 +0000 (+0200) Subject: Trace: Use scroll bars for popups with too much content X-Git-Url: https://sigrok.org/gitaction?a=commitdiff_plain;h=f52ffd9d82b45313836c5e612c7cc48982ced529;p=pulseview.git Trace: Use scroll bars for popups with too much content This fixes bug #183. --- diff --git a/pv/views/trace/trace.cpp b/pv/views/trace/trace.cpp index 76adf1d1..6d44da2c 100644 --- a/pv/views/trace/trace.cpp +++ b/pv/views/trace/trace.cpp @@ -346,13 +346,28 @@ void Trace::create_popup_form() // handled, leaving the parent popup_ time to handle the change. if (popup_form_) { QWidget *suicidal = new QWidget(); - suicidal->setLayout(popup_form_); + suicidal->setLayout(popup_->layout()); suicidal->deleteLater(); } // Repopulate the popup - popup_form_ = new QFormLayout(popup_); - popup_->setLayout(popup_form_); + widgets::QWidthAdjustingScrollArea* scrollarea = new widgets::QWidthAdjustingScrollArea(); + QWidget* scrollarea_content = new QWidget(scrollarea); + + scrollarea->setWidget(scrollarea_content); + scrollarea->setWidgetResizable(true); + scrollarea->setContentsMargins(0, 0, 0, 0); + scrollarea->setFrameShape(QFrame::NoFrame); + scrollarea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); + scrollarea_content->setContentsMargins(0, 0, 0, 0); + + popup_->setLayout(new QVBoxLayout()); + popup_->layout()->addWidget(scrollarea); + popup_->layout()->setContentsMargins(0, 0, 0, 0); + + popup_form_ = new QFormLayout(scrollarea_content); + popup_form_->setSizeConstraint(QLayout::SetMinAndMaxSize); + populate_popup_form(popup_, popup_form_); } diff --git a/pv/widgets/popup.cpp b/pv/widgets/popup.cpp index 13282cda..ec6d29c9 100644 --- a/pv/widgets/popup.cpp +++ b/pv/widgets/popup.cpp @@ -23,6 +23,8 @@ #include #include #include +#include +#include #include #include "popup.hpp" @@ -37,6 +39,33 @@ const unsigned int Popup::ArrowLength = 10; const unsigned int Popup::ArrowOverlap = 3; const unsigned int Popup::MarginWidth = 6; + +QWidthAdjustingScrollArea::QWidthAdjustingScrollArea(QWidget* parent) : + QScrollArea(parent) +{ +} + +void QWidthAdjustingScrollArea::setWidget(QWidget* w) +{ + QScrollArea::setWidget(w); + // It happens that QScrollArea already filters widget events, + // but that's an implementation detail that we shouldn't rely on. + w->installEventFilter(this); +} + +bool QWidthAdjustingScrollArea::eventFilter(QObject* obj, QEvent* ev) +{ + if (obj == widget() && ev->type() == QEvent::Resize) { + if (widget()->height() > height()) + setMinimumWidth(widget()->width() + qApp->style()->pixelMetric(QStyle::PM_ScrollBarExtent)); + else + setMinimumWidth(widget()->width()); + } + + return QScrollArea::eventFilter(obj, ev); +} + + Popup::Popup(QWidget *parent) : QWidget(parent, Qt::Popup | Qt::FramelessWindowHint), point_(), diff --git a/pv/widgets/popup.hpp b/pv/widgets/popup.hpp index 66f7f06f..736313c7 100644 --- a/pv/widgets/popup.hpp +++ b/pv/widgets/popup.hpp @@ -20,11 +20,29 @@ #ifndef PULSEVIEW_PV_WIDGETS_POPUP_HPP #define PULSEVIEW_PV_WIDGETS_POPUP_HPP +#include #include namespace pv { namespace widgets { + +// A regular QScrollArea has a fixed size and provides scroll bars when the +// content can't be shown in its entirety. However, we want no horizontal +// scroll bar and want the scroll area to adjust its width to fit the content +// instead. +// Inspired by https://stackoverflow.com/questions/21253755/qscrollarea-with-dynamically-changing-contents?answertab=votes#tab-top +class QWidthAdjustingScrollArea : public QScrollArea +{ + Q_OBJECT + +public: + QWidthAdjustingScrollArea(QWidget* parent = 0); + void setWidget(QWidget* w); + bool eventFilter(QObject* obj, QEvent* ev); +}; + + class Popup : public QWidget { Q_OBJECT