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"
13 #include <QGridLayout>
14 #include <QResizeEvent>
15 #include <QScrollArea>
19 using namespace SelectionMode
;
21 BottomBar::BottomBar(KActionCollection
*actionCollection
, QWidget
*parent
) :
24 // Showing of this widget is normally animated. We hide it for now and make it small.
28 setSizePolicy(QSizePolicy::Minimum
, QSizePolicy::Fixed
);
31 auto fillParentLayout
= new QGridLayout(this);
32 fillParentLayout
->setContentsMargins(0, 0, 0, 0);
34 // Put the contents into a QScrollArea. This prevents increasing the view width
35 // in case that not enough width for the contents is available. (this trick is also used in dolphinsearchbox.cpp.)
36 m_scrollArea
= new QScrollArea(this);
37 fillParentLayout
->addWidget(m_scrollArea
);
38 m_scrollArea
->setFrameShape(QFrame::NoFrame
);
39 m_scrollArea
->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
40 m_scrollArea
->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
41 m_scrollArea
->setWidgetResizable(true);
43 m_contentsContainer
= new BottomBarContentsContainer(actionCollection
, m_scrollArea
);
44 m_scrollArea
->setWidget(m_contentsContainer
);
45 m_contentsContainer
->installEventFilter(this); // Adjusts the height of this bar to the height of the contentsContainer
46 connect(m_contentsContainer
, &BottomBarContentsContainer::error
, this, &BottomBar::error
);
47 connect(m_contentsContainer
, &BottomBarContentsContainer::barVisibilityChangeRequested
, this, [this](bool visible
){
48 if (!m_allowedToBeVisible
&& visible
) {
51 setVisibleInternal(visible
, WithAnimation
);
53 connect(m_contentsContainer
, &BottomBarContentsContainer::selectionModeLeavingRequested
, this, &BottomBar::selectionModeLeavingRequested
);
55 BackgroundColorHelper::instance()->controlBackgroundColor(this);
58 void BottomBar::setVisible(bool visible
, Animated animated
)
60 m_allowedToBeVisible
= visible
;
61 setVisibleInternal(visible
, animated
);
64 void BottomBar::setVisibleInternal(bool visible
, Animated animated
)
66 Q_ASSERT_X(animated
== WithAnimation
, "SelectionModeBottomBar::setVisible", "This wasn't implemented.");
67 if (!visible
&& contents() == PasteContents
) {
68 return; // The bar with PasteContents should not be hidden or users might not know how to paste what they just copied.
69 // Set contents to anything else to circumvent this prevention mechanism.
71 if (visible
&& !m_contentsContainer
->hasSomethingToShow()) {
72 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.
76 if (m_heightAnimation
) {
77 m_heightAnimation
->stop(); // deletes because of QAbstractAnimation::DeleteWhenStopped.
79 m_heightAnimation
= new QPropertyAnimation(this, "maximumHeight");
80 m_heightAnimation
->setDuration(2 *
81 style()->styleHint(QStyle::SH_Widget_Animation_Duration
, nullptr, this) *
82 GlobalConfig::animationDurationFactor());
83 m_heightAnimation
->setStartValue(height());
84 m_heightAnimation
->setEasingCurve(QEasingCurve::OutCubic
);
87 m_heightAnimation
->setEndValue(sizeHint().height());
88 connect(m_heightAnimation
, &QAbstractAnimation::finished
,
89 this, [this](){ setMaximumHeight(sizeHint().height()); });
91 m_heightAnimation
->setEndValue(0);
92 connect(m_heightAnimation
, &QAbstractAnimation::finished
,
93 this, &QWidget::hide
);
96 m_heightAnimation
->start(QAbstractAnimation::DeleteWhenStopped
);
99 QSize
BottomBar::sizeHint() const
101 return QSize
{1, m_contentsContainer
->sizeHint().height()};
102 // 1 as width because this widget should never be the reason the DolphinViewContainer is made wider.
105 void BottomBar::slotSelectionChanged(const KFileItemList
&selection
, const QUrl
&baseUrl
)
107 m_contentsContainer
->slotSelectionChanged(selection
, baseUrl
);
110 void BottomBar::slotSplitTabDisabled()
112 switch (contents()) {
113 case CopyToOtherViewContents
:
114 case MoveToOtherViewContents
:
115 Q_EMIT
selectionModeLeavingRequested();
121 void BottomBar::resetContents(BottomBar::Contents contents
)
123 m_contentsContainer
->resetContents(contents
);
125 if (m_allowedToBeVisible
) {
126 setVisibleInternal(true, WithAnimation
);
130 BottomBar::Contents
BottomBar::contents() const
132 return m_contentsContainer
->contents();
135 bool BottomBar::eventFilter(QObject
*watched
, QEvent
*event
)
137 Q_ASSERT(qobject_cast
<QWidget
*>(watched
)); // This evenfFilter is only implemented for QWidgets.
139 switch (event
->type()) {
140 case QEvent::ChildAdded
:
141 case QEvent::ChildRemoved
:
142 QTimer::singleShot(0, this, [this]() {
143 // The necessary height might have changed because of the added/removed child so we change the height manually.
144 if (isVisibleTo(parentWidget()) && isEnabled() && (!m_heightAnimation
|| m_heightAnimation
->state() != QAbstractAnimation::Running
)) {
145 setMaximumHeight(sizeHint().height());
154 void BottomBar::resizeEvent(QResizeEvent
*resizeEvent
)
156 if (resizeEvent
->oldSize().width() == resizeEvent
->size().width()) {
157 // The width() didn't change so our custom override isn't needed.
158 return QWidget::resizeEvent(resizeEvent
);
161 m_contentsContainer
->adaptToNewBarWidth(width());
163 return QWidget::resizeEvent(resizeEvent
);