]> cloud.milkyroute.net Git - dolphin.git/blob - src/animatedheightwidget.cpp
viewproperties: Fix leaking file descriptors
[dolphin.git] / src / animatedheightwidget.cpp
1 /*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2024 Felix Ernst <felixernst@kde.org>
4
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 */
7
8 #include "animatedheightwidget.h"
9
10 #include <QGridLayout>
11 #include <QPropertyAnimation>
12 #include <QScrollArea>
13 #include <QStyle>
14
15 AnimatedHeightWidget::AnimatedHeightWidget(QWidget *parent)
16 : QWidget{parent}
17 {
18 // Showing of this widget is normally animated. We hide it for now and make it small.
19 hide();
20 setMaximumHeight(0);
21
22 auto fillParentLayout = new QGridLayout(this);
23 fillParentLayout->setContentsMargins(0, 0, 0, 0);
24
25 // Put the contents into a QScrollArea. This prevents increasing the view width
26 // in case there is not enough available width for the contents.
27 m_contentsContainerParent = new QScrollArea(this);
28 fillParentLayout->addWidget(m_contentsContainerParent);
29 m_contentsContainerParent->setFrameShape(QFrame::NoFrame);
30 m_contentsContainerParent->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
31 m_contentsContainerParent->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
32 m_contentsContainerParent->setWidgetResizable(true);
33
34 setMinimumWidth(0);
35 }
36
37 QSize AnimatedHeightWidget::sizeHint() const
38 {
39 return QSize{1, preferredHeight()};
40 // 1 as width because this widget should never be the reason the DolphinViewContainer is made wider.
41 }
42
43 void AnimatedHeightWidget::setVisible(bool visible, Animated animated)
44 {
45 setEnabled(visible);
46 if (m_heightAnimation) {
47 m_heightAnimation->stop(); // deletes because of QAbstractAnimation::DeleteWhenStopped.
48 }
49
50 if (animated == WithAnimation
51 && (style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, this) < 1 || GlobalConfig::animationDurationFactor() <= 0.0)) {
52 animated = WithoutAnimation;
53 }
54
55 if (animated == WithoutAnimation) {
56 setMaximumHeight(visible ? preferredHeight() : 0);
57 setVisible(visible);
58 return;
59 }
60
61 m_heightAnimation = new QPropertyAnimation(this, "maximumHeight");
62 m_heightAnimation->setDuration(2 * style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, this) * GlobalConfig::animationDurationFactor());
63
64 m_heightAnimation->setStartValue(height());
65 m_heightAnimation->setEasingCurve(QEasingCurve::OutCubic);
66 if (visible) {
67 show();
68 m_heightAnimation->setEndValue(preferredHeight());
69 } else {
70 m_heightAnimation->setEndValue(0);
71 connect(m_heightAnimation, &QAbstractAnimation::finished, this, &QWidget::hide);
72 }
73
74 m_heightAnimation->start(QAbstractAnimation::DeleteWhenStopped);
75 }
76
77 QWidget *AnimatedHeightWidget::prepareContentsContainer(QWidget *contentsContainer)
78 {
79 Q_ASSERT_X(!m_contentsContainerParent->widget(),
80 "AnimatedHeightWidget::prepareContentsContainer",
81 "Another contentsContainer has already been prepared. There can only be one.");
82 contentsContainer->setParent(m_contentsContainerParent);
83 m_contentsContainerParent->setWidget(contentsContainer);
84 m_contentsContainerParent->setFocusProxy(contentsContainer);
85 return contentsContainer;
86 }
87
88 bool AnimatedHeightWidget::isAnimationRunning() const
89 {
90 return m_heightAnimation && m_heightAnimation->state() == QAbstractAnimation::Running;
91 }