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>
20 using namespace SelectionMode
;
22 BottomBar::BottomBar(KActionCollection
*actionCollection
, QWidget
*parent
) :
25 // Showing of this widget is normally animated. We hide it for now and make it small.
29 setSizePolicy(QSizePolicy::Minimum
, QSizePolicy::Fixed
);
32 auto fillParentLayout
= new QGridLayout(this);
33 fillParentLayout
->setContentsMargins(0, 0, 0, 0);
35 // Put the contents into a QScrollArea. This prevents increasing the view width
36 // in case that not enough width for the contents is available. (this trick is also used in dolphinsearchbox.cpp.)
37 m_scrollArea
= new QScrollArea(this);
38 fillParentLayout
->addWidget(m_scrollArea
);
39 m_scrollArea
->setFrameShape(QFrame::NoFrame
);
40 m_scrollArea
->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
41 m_scrollArea
->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff
);
42 m_scrollArea
->setWidgetResizable(true);
44 m_contentsContainer
= new BottomBarContentsContainer(actionCollection
, m_scrollArea
);
45 m_scrollArea
->setWidget(m_contentsContainer
);
46 m_contentsContainer
->installEventFilter(this); // Adjusts the height of this bar to the height of the contentsContainer
47 connect(m_contentsContainer
, &BottomBarContentsContainer::error
, this, &BottomBar::error
);
48 connect(m_contentsContainer
, &BottomBarContentsContainer::barVisibilityChangeRequested
, this, [this](bool visible
){
49 if (!m_allowedToBeVisible
&& visible
) {
52 setVisibleInternal(visible
, WithAnimation
);
54 connect(m_contentsContainer
, &BottomBarContentsContainer::selectionModeLeavingRequested
, this, &BottomBar::selectionModeLeavingRequested
);
56 BackgroundColorHelper::instance()->controlBackgroundColor(this);
59 void BottomBar::setVisible(bool visible
, Animated animated
)
61 m_allowedToBeVisible
= visible
;
62 setVisibleInternal(visible
, animated
);
65 void BottomBar::setVisibleInternal(bool visible
, Animated animated
)
67 Q_ASSERT_X(animated
== WithAnimation
, "SelectionModeBottomBar::setVisible", "This wasn't implemented.");
68 if (!visible
&& contents() == PasteContents
) {
69 return; // The bar with PasteContents should not be hidden or users might not know how to paste what they just copied.
70 // Set contents to anything else to circumvent this prevention mechanism.
72 if (visible
&& !m_contentsContainer
->hasSomethingToShow()) {
73 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.
77 if (m_heightAnimation
) {
78 m_heightAnimation
->stop(); // deletes because of QAbstractAnimation::DeleteWhenStopped.
80 m_heightAnimation
= new QPropertyAnimation(this, "maximumHeight");
81 m_heightAnimation
->setDuration(2 *
82 style()->styleHint(QStyle::SH_Widget_Animation_Duration
, nullptr, this) *
83 GlobalConfig::animationDurationFactor());
84 m_heightAnimation
->setStartValue(height());
85 m_heightAnimation
->setEasingCurve(QEasingCurve::OutCubic
);
88 m_heightAnimation
->setEndValue(sizeHint().height());
89 connect(m_heightAnimation
, &QAbstractAnimation::finished
,
90 this, [this](){ setMaximumHeight(sizeHint().height()); });
92 m_heightAnimation
->setEndValue(0);
93 connect(m_heightAnimation
, &QAbstractAnimation::finished
,
94 this, &QWidget::hide
);
97 m_heightAnimation
->start(QAbstractAnimation::DeleteWhenStopped
);
100 QSize
BottomBar::sizeHint() const
102 return QSize
{1, m_contentsContainer
->sizeHint().height()};
103 // 1 as width because this widget should never be the reason the DolphinViewContainer is made wider.
106 void BottomBar::slotSelectionChanged(const KFileItemList
&selection
, const QUrl
&baseUrl
)
108 m_contentsContainer
->slotSelectionChanged(selection
, baseUrl
);
111 void BottomBar::slotSplitTabDisabled()
113 switch (contents()) {
114 case CopyToOtherViewContents
:
115 case MoveToOtherViewContents
:
116 Q_EMIT
selectionModeLeavingRequested();
122 void BottomBar::resetContents(BottomBar::Contents contents
)
124 m_contentsContainer
->resetContents(contents
);
126 if (m_allowedToBeVisible
) {
127 setVisibleInternal(true, WithAnimation
);
131 BottomBar::Contents
BottomBar::contents() const
133 return m_contentsContainer
->contents();
136 bool BottomBar::eventFilter(QObject
*watched
, QEvent
*event
)
138 Q_ASSERT(qobject_cast
<QWidget
*>(watched
)); // This evenfFilter is only implemented for QWidgets.
140 switch (event
->type()) {
141 case QEvent::ChildAdded
:
142 case QEvent::ChildRemoved
:
143 QTimer::singleShot(0, this, [this]() {
144 // The necessary height might have changed because of the added/removed child so we change the height manually.
145 if (isVisibleTo(parentWidget()) && isEnabled() && (!m_heightAnimation
|| m_heightAnimation
->state() != QAbstractAnimation::Running
)) {
146 setMaximumHeight(sizeHint().height());
155 void BottomBar::resizeEvent(QResizeEvent
*resizeEvent
)
157 if (resizeEvent
->oldSize().width() == resizeEvent
->size().width()) {
158 // The width() didn't change so our custom override isn't needed.
159 return QWidget::resizeEvent(resizeEvent
);
162 m_contentsContainer
->adaptToNewBarWidth(width());
164 return QWidget::resizeEvent(resizeEvent
);