Trace: Use scroll bars for popups with too much content
authorSoeren Apel <soeren@apelpie.net>
Tue, 13 Aug 2019 07:18:46 +0000 (09:18 +0200)
committerUwe Hermann <uwe@hermann-uwe.de>
Sat, 7 Sep 2019 15:56:52 +0000 (17:56 +0200)
This fixes bug #183.

pv/views/trace/trace.cpp
pv/widgets/popup.cpp
pv/widgets/popup.hpp

index 76adf1d15e03b6a2f4e69eb1a55f5c020578d8cb..6d44da2c889d8babc73cd6e2054965a1aa980a6c 100644 (file)
@@ -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_);
 }
 
index 13282cda25e458b6b624de563f09e1fc6668a6b5..ec6d29c981c235b86451353ca620d9c5cf147868 100644 (file)
@@ -23,6 +23,8 @@
 #include <QApplication>
 #include <QDesktopWidget>
 #include <QLineEdit>
+#include <QScrollBar>
+#include <QStyle>
 #include <QtGui>
 
 #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_(),
index 66f7f06f5d87192a2ea77cbafee44af21cec294c..736313c79d9615ae890a7c585027483b3761f87d 100644 (file)
 #ifndef PULSEVIEW_PV_WIDGETS_POPUP_HPP
 #define PULSEVIEW_PV_WIDGETS_POPUP_HPP
 
+#include <QScrollArea>
 #include <QWidget>
 
 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