From 148a706771f872a7afae0942039d3a36c1793ec6 Mon Sep 17 00:00:00 2001 From: Connor McLaughlin Date: Sun, 16 May 2021 03:23:26 +1000 Subject: [PATCH] Qt: Add CollapsibleWidget --- src/duckstation-qt/CMakeLists.txt | 2 + src/duckstation-qt/collapsiblewidget.cpp | 56 +++++++++++++++++++ src/duckstation-qt/collapsiblewidget.h | 27 +++++++++ src/duckstation-qt/duckstation-qt.vcxproj | 5 +- .../duckstation-qt.vcxproj.filters | 6 +- 5 files changed, 93 insertions(+), 3 deletions(-) create mode 100644 src/duckstation-qt/collapsiblewidget.cpp create mode 100644 src/duckstation-qt/collapsiblewidget.h diff --git a/src/duckstation-qt/CMakeLists.txt b/src/duckstation-qt/CMakeLists.txt index 33434ae31..88dbc99f1 100644 --- a/src/duckstation-qt/CMakeLists.txt +++ b/src/duckstation-qt/CMakeLists.txt @@ -24,6 +24,8 @@ set(SRCS cheatcodeeditordialog.cpp cheatcodeeditordialog.h cheatcodeeditordialog.ui + collapsiblewidget.cpp + collapsiblewidget.h consolesettingswidget.cpp consolesettingswidget.h consolesettingswidget.ui diff --git a/src/duckstation-qt/collapsiblewidget.cpp b/src/duckstation-qt/collapsiblewidget.cpp new file mode 100644 index 000000000..c0b680841 --- /dev/null +++ b/src/duckstation-qt/collapsiblewidget.cpp @@ -0,0 +1,56 @@ +#include + +#include "collapsiblewidget.h" + +CollapsibleWidget::CollapsibleWidget(const QString& title, const int animationDuration, QWidget* parent) + : QWidget(parent), animationDuration(animationDuration) +{ + toggleButton.setStyleSheet("QToolButton { border: none; }"); + toggleButton.setToolButtonStyle(Qt::ToolButtonTextBesideIcon); + toggleButton.setArrowType(Qt::ArrowType::RightArrow); + toggleButton.setText(title); + toggleButton.setCheckable(true); + toggleButton.setChecked(false); + + contentArea.setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + + // start out collapsed + contentArea.setMaximumHeight(0); + contentArea.setMinimumHeight(0); + + // let the entire widget grow and shrink with its content + toggleAnimation.addAnimation(new QPropertyAnimation(this, "minimumHeight")); + toggleAnimation.addAnimation(new QPropertyAnimation(this, "maximumHeight")); + toggleAnimation.addAnimation(new QPropertyAnimation(&contentArea, "maximumHeight")); + + // don't waste space + mainLayout.setContentsMargins(0, 0, 0, 0); + mainLayout.addWidget(&toggleButton); + mainLayout.addWidget(&contentArea); + setLayout(&mainLayout); + QObject::connect(&toggleButton, &QToolButton::clicked, [this](const bool checked) { + toggleButton.setArrowType(checked ? Qt::ArrowType::DownArrow : Qt::ArrowType::RightArrow); + toggleAnimation.setDirection(checked ? QAbstractAnimation::Forward : QAbstractAnimation::Backward); + toggleAnimation.start(); + }); +} + +void CollapsibleWidget::setContentLayout(QLayout* contentLayout) +{ + delete contentArea.layout(); + contentArea.setLayout(contentLayout); + const auto collapsedHeight = sizeHint().height() - contentArea.maximumHeight(); + auto contentHeight = contentLayout->sizeHint().height(); + for (int i = 0; i < toggleAnimation.animationCount() - 1; ++i) + { + QPropertyAnimation* spoilerAnimation = static_cast(toggleAnimation.animationAt(i)); + spoilerAnimation->setDuration(animationDuration); + spoilerAnimation->setStartValue(collapsedHeight); + spoilerAnimation->setEndValue(collapsedHeight + contentHeight); + } + QPropertyAnimation* contentAnimation = + static_cast(toggleAnimation.animationAt(toggleAnimation.animationCount() - 1)); + contentAnimation->setDuration(animationDuration); + contentAnimation->setStartValue(0); + contentAnimation->setEndValue(contentHeight); +} \ No newline at end of file diff --git a/src/duckstation-qt/collapsiblewidget.h b/src/duckstation-qt/collapsiblewidget.h new file mode 100644 index 000000000..4af041efc --- /dev/null +++ b/src/duckstation-qt/collapsiblewidget.h @@ -0,0 +1,27 @@ +// https://stackoverflow.com/questions/32476006/how-to-make-an-expandable-collapsable-section-widget-in-qt + +#pragma once + +#include +#include +#include +#include +#include + +class CollapsibleWidget : public QWidget +{ + Q_OBJECT +private: + QVBoxLayout mainLayout; + QToolButton toggleButton; + QParallelAnimationGroup toggleAnimation; + QScrollArea contentArea; + int animationDuration{300}; + +public: + explicit CollapsibleWidget(const QString& title = "", const int animationDuration = 300, QWidget* parent = 0); + + QScrollArea* getScrollArea() { return &contentArea; } + + void setContentLayout(QLayout* contentLayout); +}; diff --git a/src/duckstation-qt/duckstation-qt.vcxproj b/src/duckstation-qt/duckstation-qt.vcxproj index 789e008d1..81763020d 100644 --- a/src/duckstation-qt/duckstation-qt.vcxproj +++ b/src/duckstation-qt/duckstation-qt.vcxproj @@ -60,6 +60,7 @@ + @@ -118,6 +119,7 @@ + @@ -228,6 +230,7 @@ + @@ -287,7 +290,7 @@ Document - + Document diff --git a/src/duckstation-qt/duckstation-qt.vcxproj.filters b/src/duckstation-qt/duckstation-qt.vcxproj.filters index b374176ce..44508bf61 100644 --- a/src/duckstation-qt/duckstation-qt.vcxproj.filters +++ b/src/duckstation-qt/duckstation-qt.vcxproj.filters @@ -79,14 +79,16 @@ - + + + @@ -181,7 +183,7 @@ translations - + translations