File indexing completed on 2024-05-12 09:51:04
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2022 Felix Ernst <felixernst@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 #include "bottombar.h" 0009 0010 #include "backgroundcolorhelper.h" 0011 #include "bottombarcontentscontainer.h" 0012 0013 #include <QGridLayout> 0014 #include <QResizeEvent> 0015 #include <QScrollArea> 0016 #include <QStyle> 0017 #include <QTimer> 0018 0019 using namespace SelectionMode; 0020 0021 BottomBar::BottomBar(KActionCollection *actionCollection, QWidget *parent) 0022 : QWidget{parent} 0023 { 0024 // Showing of this widget is normally animated. We hide it for now and make it small. 0025 hide(); 0026 setMaximumHeight(0); 0027 0028 setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed); 0029 setMinimumWidth(0); 0030 0031 auto fillParentLayout = new QGridLayout(this); 0032 fillParentLayout->setContentsMargins(0, 0, 0, 0); 0033 0034 // Put the contents into a QScrollArea. This prevents increasing the view width 0035 // in case that not enough width for the contents is available. (this trick is also used in dolphinsearchbox.cpp.) 0036 m_scrollArea = new QScrollArea(this); 0037 fillParentLayout->addWidget(m_scrollArea); 0038 m_scrollArea->setFrameShape(QFrame::NoFrame); 0039 m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 0040 m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); 0041 m_scrollArea->setWidgetResizable(true); 0042 0043 m_contentsContainer = new BottomBarContentsContainer(actionCollection, m_scrollArea); 0044 m_scrollArea->setWidget(m_contentsContainer); 0045 m_contentsContainer->installEventFilter(this); // Adjusts the height of this bar to the height of the contentsContainer 0046 connect(m_contentsContainer, &BottomBarContentsContainer::error, this, &BottomBar::error); 0047 connect(m_contentsContainer, &BottomBarContentsContainer::barVisibilityChangeRequested, this, [this](bool visible) { 0048 if (!m_allowedToBeVisible && visible) { 0049 return; 0050 } 0051 setVisibleInternal(visible, WithAnimation); 0052 }); 0053 connect(m_contentsContainer, &BottomBarContentsContainer::selectionModeLeavingRequested, this, &BottomBar::selectionModeLeavingRequested); 0054 0055 BackgroundColorHelper::instance()->controlBackgroundColor(this); 0056 } 0057 0058 void BottomBar::setVisible(bool visible, Animated animated) 0059 { 0060 m_allowedToBeVisible = visible; 0061 setVisibleInternal(visible, animated); 0062 } 0063 0064 void BottomBar::setVisibleInternal(bool visible, Animated animated) 0065 { 0066 Q_ASSERT_X(animated == WithAnimation, "SelectionModeBottomBar::setVisible", "This wasn't implemented."); 0067 if (!visible && contents() == PasteContents) { 0068 return; // The bar with PasteContents should not be hidden or users might not know how to paste what they just copied. 0069 // Set contents to anything else to circumvent this prevention mechanism. 0070 } 0071 if (visible && !m_contentsContainer->hasSomethingToShow()) { 0072 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. 0073 } 0074 0075 setEnabled(visible); 0076 if (m_heightAnimation) { 0077 m_heightAnimation->stop(); // deletes because of QAbstractAnimation::DeleteWhenStopped. 0078 } 0079 m_heightAnimation = new QPropertyAnimation(this, "maximumHeight"); 0080 m_heightAnimation->setDuration(2 * style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, this) * GlobalConfig::animationDurationFactor()); 0081 m_heightAnimation->setStartValue(height()); 0082 m_heightAnimation->setEasingCurve(QEasingCurve::OutCubic); 0083 if (visible) { 0084 show(); 0085 m_heightAnimation->setEndValue(sizeHint().height()); 0086 connect(m_heightAnimation, &QAbstractAnimation::finished, this, [this]() { 0087 setMaximumHeight(sizeHint().height()); 0088 }); 0089 } else { 0090 m_heightAnimation->setEndValue(0); 0091 connect(m_heightAnimation, &QAbstractAnimation::finished, this, &QWidget::hide); 0092 } 0093 0094 m_heightAnimation->start(QAbstractAnimation::DeleteWhenStopped); 0095 } 0096 0097 QSize BottomBar::sizeHint() const 0098 { 0099 return QSize{1, m_contentsContainer->sizeHint().height()}; 0100 // 1 as width because this widget should never be the reason the DolphinViewContainer is made wider. 0101 } 0102 0103 void BottomBar::slotSelectionChanged(const KFileItemList &selection, const QUrl &baseUrl) 0104 { 0105 m_contentsContainer->slotSelectionChanged(selection, baseUrl); 0106 } 0107 0108 void BottomBar::slotSplitTabDisabled() 0109 { 0110 switch (contents()) { 0111 case CopyToOtherViewContents: 0112 case MoveToOtherViewContents: 0113 Q_EMIT selectionModeLeavingRequested(); 0114 default: 0115 return; 0116 } 0117 } 0118 0119 void BottomBar::resetContents(BottomBar::Contents contents) 0120 { 0121 m_contentsContainer->resetContents(contents); 0122 0123 if (m_allowedToBeVisible) { 0124 setVisibleInternal(true, WithAnimation); 0125 } 0126 } 0127 0128 BottomBar::Contents BottomBar::contents() const 0129 { 0130 return m_contentsContainer->contents(); 0131 } 0132 0133 bool BottomBar::eventFilter(QObject *watched, QEvent *event) 0134 { 0135 Q_ASSERT(qobject_cast<QWidget *>(watched)); // This evenfFilter is only implemented for QWidgets. 0136 0137 switch (event->type()) { 0138 case QEvent::ChildAdded: 0139 case QEvent::ChildRemoved: 0140 QTimer::singleShot(0, this, [this]() { 0141 // The necessary height might have changed because of the added/removed child so we change the height manually. 0142 if (isVisibleTo(parentWidget()) && isEnabled() && (!m_heightAnimation || m_heightAnimation->state() != QAbstractAnimation::Running)) { 0143 setMaximumHeight(sizeHint().height()); 0144 } 0145 }); 0146 // Fall through. 0147 default: 0148 return false; 0149 } 0150 } 0151 0152 void BottomBar::resizeEvent(QResizeEvent *resizeEvent) 0153 { 0154 if (resizeEvent->oldSize().width() == resizeEvent->size().width()) { 0155 // The width() didn't change so our custom override isn't needed. 0156 return QWidget::resizeEvent(resizeEvent); 0157 } 0158 0159 m_contentsContainer->adaptToNewBarWidth(width()); 0160 0161 return QWidget::resizeEvent(resizeEvent); 0162 } 0163 0164 #include "moc_bottombar.cpp"