2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2022 Felix Ernst <felixernst@zohomail.eu>
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
10 #include "bottombarcontentscontainer.h"
11 #include "backgroundcolorhelper.h"
14 #include <QGridLayout>
15 #include <QResizeEvent>
16 #include <QScrollArea>
21 using namespace SelectionMode
;
23 BottomBar::BottomBar(KActionCollection
*actionCollection
, QWidget
*parent
) :
26 // Showing of this widget is normally animated. We hide it for now and make it small.
30 setSizePolicy(QSizePolicy::Minimum
, QSizePolicy::Fixed
);
33 auto fillParentLayout
= new QGridLayout(this);
34 fillParentLayout
->setContentsMargins(0, 0, 0, 0);
36 // Put the contents into a QScrollArea. This prevents increasing the view width
37 // in case that not enough width for the contents is available. (this trick is also used in dolphinsearchbox.cpp.)
38 m_scrollArea
= new QScrollArea(this);
39 fillParentLayout
->addWidget(m_scrollArea
);
40 m_scrollArea
->setFrameShape(QFrame::NoFrame
);
41 m_scrollArea
->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
42 m_scrollArea
->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
43 m_scrollArea
->setWidgetResizable(true);
45 m_contentsContainer
= new BottomBarContentsContainer(actionCollection
, m_scrollArea
);
46 m_scrollArea
->setWidget(m_contentsContainer
);
47 m_contentsContainer
->installEventFilter(this); // Adjusts the height of this bar to the height of the contentsContainer
48 connect(m_contentsContainer
, &BottomBarContentsContainer::error
, this, &BottomBar::error
);
49 connect(m_contentsContainer
, &BottomBarContentsContainer::barVisibilityChangeRequested
, this, [this](bool visible
){
50 if (!m_allowedToBeVisible
&& visible
) {
53 setVisibleInternal(visible
, WithAnimation
);
55 connect(m_contentsContainer
, &BottomBarContentsContainer::leaveSelectionModeRequested
, this, &BottomBar::leaveSelectionModeRequested
);
57 BackgroundColorHelper::instance()->controlBackgroundColor(this);
60 void BottomBar::setVisible(bool visible
, Animated animated
)
62 m_allowedToBeVisible
= visible
;
63 setVisibleInternal(visible
, animated
);
66 void BottomBar::setVisibleInternal(bool visible
, Animated animated
)
68 Q_ASSERT_X(animated
== WithAnimation
, "SelectionModeBottomBar::setVisible", "This wasn't implemented.");
69 if (!visible
&& contents() == PasteContents
) {
70 return; // The bar with PasteContents should not be hidden or users might not know how to paste what they just copied.
71 // Set contents to anything else to circumvent this prevention mechanism.
73 if (visible
&& !m_contentsContainer
->hasSomethingToShow()) {
74 return; // There is nothing on the bar that we want to show. We keep it invisible and only show it when the selection or the contents change.
78 if (m_heightAnimation
) {
79 m_heightAnimation
->stop(); // deletes because of QAbstractAnimation::DeleteWhenStopped.
81 m_heightAnimation
= new QPropertyAnimation(this, "maximumHeight");
82 m_heightAnimation
->setDuration(2 *
83 style()->styleHint(QStyle::SH_Widget_Animation_Duration
, nullptr, this) *
84 GlobalConfig::animationDurationFactor());
85 m_heightAnimation
->setStartValue(height());
86 m_heightAnimation
->setEasingCurve(QEasingCurve::OutCubic
);
89 m_heightAnimation
->setEndValue(sizeHint().height());
90 connect(m_heightAnimation
, &QAbstractAnimation::finished
,
91 this, [this](){ setMaximumHeight(sizeHint().height()); });
93 m_heightAnimation
->setEndValue(0);
94 connect(m_heightAnimation
, &QAbstractAnimation::finished
,
95 this, &QWidget::hide
);
98 m_heightAnimation
->start(QAbstractAnimation::DeleteWhenStopped
);
101 QSize
BottomBar::sizeHint() const
103 return QSize
{1, m_contentsContainer
->sizeHint().height()};
104 // 1 as width because this widget should never be the reason the DolphinViewContainer is made wider.
107 void BottomBar::slotSelectionChanged(const KFileItemList
&selection
, const QUrl
&baseUrl
)
109 m_contentsContainer
->slotSelectionChanged(selection
, baseUrl
);
112 void BottomBar::slotSplitTabDisabled()
114 switch (contents()) {
115 case CopyToOtherViewContents
:
116 case MoveToOtherViewContents
:
117 Q_EMIT
leaveSelectionModeRequested();
123 void BottomBar::resetContents(BottomBar::Contents contents
)
125 m_contentsContainer
->resetContents(contents
);
127 if (m_allowedToBeVisible
) {
128 setVisibleInternal(true, WithAnimation
);
132 BottomBar::Contents
BottomBar::contents() const
134 return m_contentsContainer
->contents();
137 bool BottomBar::eventFilter(QObject
*watched
, QEvent
*event
)
139 Q_ASSERT(qobject_cast
<QWidget
*>(watched
)); // This evenfFilter is only implemented for QWidgets.
141 switch (event
->type()) {
142 case QEvent::ChildAdded
:
143 case QEvent::ChildRemoved
:
144 QTimer::singleShot(0, this, [this]() {
145 // The necessary height might have changed because of the added/removed child so we change the height manually.
146 if (isVisibleTo(parentWidget()) && isEnabled() && (!m_heightAnimation
|| m_heightAnimation
->state() != QAbstractAnimation::Running
)) {
147 setMaximumHeight(sizeHint().height());
156 void BottomBar::resizeEvent(QResizeEvent
*resizeEvent
)
158 if (resizeEvent
->oldSize().width() == resizeEvent
->size().width()) {
159 // The width() didn't change so our custom override isn't needed.
160 return QWidget::resizeEvent(resizeEvent
);
163 m_contentsContainer
->adaptToNewBarWidth(width());
165 return QWidget::resizeEvent(resizeEvent
);