Commit 8e55f2c2 authored by Felix Ernst's avatar Felix Ernst 🇺🇦
Browse files

Better separation of classes

Make obvious when actions trigger selection mode.
parent 402b4a56
......@@ -87,6 +87,7 @@ target_sources(dolphinprivate PRIVATE
settings/viewmodes/viewmodesettings.cpp
settings/viewpropertiesdialog.cpp
settings/viewpropsprogressinfo.cpp
selectionmode/actiontexthelper.cpp
views/dolphinfileitemlistwidget.cpp
views/dolphinitemlistview.cpp
views/dolphinnewfilemenuobserver.cpp
......@@ -219,10 +220,12 @@ target_sources(dolphinstatic PRIVATE
search/dolphinfacetswidget.cpp
search/dolphinquery.cpp
search/dolphinsearchbox.cpp
selectionmode/actiontexthelper.cpp
selectionmode/actionwithwidget.cpp
selectionmode/backgroundcolorhelper.cpp
selectionmode/selectionmodebottombar.cpp
selectionmode/selectionmodetopbar.cpp
selectionmode/bottombar.cpp
selectionmode/bottombarcontentscontainer.cpp
selectionmode/topbar.cpp
settings/general/behaviorsettingspage.cpp
settings/general/configurepreviewplugindialog.cpp
settings/general/confirmationssettingspage.cpp
......
......@@ -24,6 +24,7 @@
#include "panels/folders/folderspanel.h"
#include "panels/places/placespanel.h"
#include "panels/terminal/terminalpanel.h"
#include "selectionmode/actiontexthelper.h"
#include "settings/dolphinsettingsdialog.h"
#include "statusbar/dolphinstatusbar.h"
#include "views/dolphinviewactionhandler.h"
......@@ -124,7 +125,7 @@ DolphinMainWindow::DolphinMainWindow() :
setComponentName(QStringLiteral("dolphin"), QGuiApplication::applicationDisplayName());
setObjectName(QStringLiteral("Dolphin#"));
setStateConfigGroup("State");
// setStateConfigGroup("State");
connect(&DolphinNewFileMenuObserver::instance(), &DolphinNewFileMenuObserver::errorMessage,
this, &DolphinMainWindow::showErrorMessage);
......@@ -160,9 +161,10 @@ DolphinMainWindow::DolphinMainWindow() :
this, &DolphinMainWindow::updateWindowTitle);
setCentralWidget(m_tabWidget);
m_actionTextHelper = new SelectionMode::ActionTextHelper(this);
setupActions();
m_actionHandler = new DolphinViewActionHandler(actionCollection(), this);
m_actionHandler = new DolphinViewActionHandler(actionCollection(), m_actionTextHelper, this);
connect(m_actionHandler, &DolphinViewActionHandler::actionBeingHandled, this, &DolphinMainWindow::clearStatusBar);
connect(m_actionHandler, &DolphinViewActionHandler::createDirectoryTriggered, this, &DolphinMainWindow::createDirectory);
connect(m_actionHandler, &DolphinViewActionHandler::setSelectionMode, this, &DolphinMainWindow::slotSetSelectionMode);
......@@ -715,7 +717,7 @@ void DolphinMainWindow::undo()
void DolphinMainWindow::cut()
{
if (m_activeViewContainer->view()->selectedItems().isEmpty()) {
m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionModeBottomBar::Contents::CutContents);
m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionMode::BottomBar::Contents::CutContents);
} else {
m_activeViewContainer->view()->cutSelectedItemsToClipboard();
m_activeViewContainer->setSelectionModeEnabled(false);
......@@ -725,7 +727,7 @@ void DolphinMainWindow::cut()
void DolphinMainWindow::copy()
{
if (m_activeViewContainer->view()->selectedItems().isEmpty()) {
m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionModeBottomBar::Contents::CopyContents);
m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionMode::BottomBar::Contents::CopyContents);
} else {
m_activeViewContainer->view()->copySelectedItemsToClipboard();
m_activeViewContainer->setSelectionModeEnabled(false);
......@@ -856,7 +858,7 @@ void DolphinMainWindow::slotGoForward(QAction* action)
}
}
void DolphinMainWindow::slotSetSelectionMode(bool enabled, SelectionModeBottomBar::Contents bottomBarContents)
void DolphinMainWindow::slotSetSelectionMode(bool enabled, SelectionMode::BottomBar::Contents bottomBarContents)
{
m_activeViewContainer->setSelectionModeEnabled(enabled, actionCollection(), bottomBarContents);
}
......@@ -903,7 +905,7 @@ void DolphinMainWindow::toggleSplitStash()
void DolphinMainWindow::copyToInactiveSplitView()
{
if (m_activeViewContainer->view()->selectedItems().isEmpty()) {
m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionModeBottomBar::Contents::CopyToOtherViewContents);
m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionMode::BottomBar::Contents::CopyToOtherViewContents);
} else {
m_tabWidget->copyToInactiveSplitView();
m_activeViewContainer->setSelectionModeEnabled(false);
......@@ -913,7 +915,7 @@ void DolphinMainWindow::copyToInactiveSplitView()
void DolphinMainWindow::moveToInactiveSplitView()
{
if (m_activeViewContainer->view()->selectedItems().isEmpty()) {
m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionModeBottomBar::Contents::MoveToOtherViewContents);
m_activeViewContainer->setSelectionModeEnabled(true, actionCollection(), SelectionMode::BottomBar::Contents::MoveToOtherViewContents);
} else {
m_tabWidget->moveToInactiveSplitView();
m_activeViewContainer->setSelectionModeEnabled(false);
......@@ -946,7 +948,7 @@ void DolphinMainWindow::toggleSelectionMode()
{
const bool checked = !m_activeViewContainer->isSelectionModeEnabled();
m_activeViewContainer->setSelectionModeEnabled(checked, actionCollection(), SelectionModeBottomBar::Contents::GeneralContents);
m_activeViewContainer->setSelectionModeEnabled(checked, actionCollection(), SelectionMode::BottomBar::Contents::GeneralContents);
actionCollection()->action(QStringLiteral("toggle_selection_mode"))->setChecked(checked);
}
......@@ -1584,12 +1586,14 @@ void DolphinMainWindow::setupActions()
"next to each other on the keyboard: <shortcut>Ctrl+X</shortcut>, "
"<shortcut>Ctrl+C</shortcut> and <shortcut>Ctrl+V</shortcut>.</para>");
QAction* cutAction = KStandardAction::cut(this, &DolphinMainWindow::cut, actionCollection());
m_actionTextHelper->registerTextWhenNothingIsSelected(cutAction, i18nc("@action", "Cut…"));
cutAction->setWhatsThis(xi18nc("@info:whatsthis cut", "This copies the items "
"in your current selection to the <emphasis>clipboard</emphasis>.<nl/>"
"Use the <emphasis>Paste</emphasis> action afterwards to copy them from "
"the clipboard to a new location. The items will be removed from their "
"initial location.") + cutCopyPastePara);
QAction* copyAction = KStandardAction::copy(this, &DolphinMainWindow::copy, actionCollection());
m_actionTextHelper->registerTextWhenNothingIsSelected(copyAction, i18nc("@action", "Copy…"));
copyAction->setWhatsThis(xi18nc("@info:whatsthis copy", "This copies the "
"items in your current selection to the <emphasis>clipboard</emphasis>."
"<nl/>Use the <emphasis>Paste</emphasis> action afterwards to copy them "
......@@ -1606,6 +1610,7 @@ void DolphinMainWindow::setupActions()
QAction* copyToOtherViewAction = actionCollection()->addAction(QStringLiteral("copy_to_inactive_split_view"));
copyToOtherViewAction->setText(i18nc("@action:inmenu", "Copy to Inactive Split View"));
m_actionTextHelper->registerTextWhenNothingIsSelected(copyToOtherViewAction, i18nc("@action:inmenu", "Copy to Inactive Split View…"));
copyToOtherViewAction->setWhatsThis(xi18nc("@info:whatsthis Copy", "This copies the selected items from "
"the <emphasis>active</emphasis> view to the inactive split view."));
copyToOtherViewAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-copy")));
......@@ -1615,6 +1620,7 @@ void DolphinMainWindow::setupActions()
QAction* moveToOtherViewAction = actionCollection()->addAction(QStringLiteral("move_to_inactive_split_view"));
moveToOtherViewAction->setText(i18nc("@action:inmenu", "Move to Inactive Split View"));
m_actionTextHelper->registerTextWhenNothingIsSelected(moveToOtherViewAction, i18nc("@action:inmenu", "Move to Inactive Split View…"));
moveToOtherViewAction->setWhatsThis(xi18nc("@info:whatsthis Move", "This moves the selected items from "
"the <emphasis>active</emphasis> view to the inactive split view."));
moveToOtherViewAction->setIcon(QIcon::fromTheme(QStringLiteral("edit-cut")));
......@@ -2229,7 +2235,7 @@ void DolphinMainWindow::updateFileAndEditActions()
QAction* deleteAction = col->action(KStandardAction::name(KStandardAction::DeleteFile));
QAction* cutAction = col->action(KStandardAction::name(KStandardAction::Cut));
QAction* duplicateAction = col->action(QStringLiteral("duplicate")); // see DolphinViewActionHandler
QAction* addToPlacesAction = col->action(QStringLiteral("add_to_places"));
QAction* addToPlacesAction = col->action(QStringLiteral("add_to_places"));
QAction* copyToOtherViewAction = col->action(QStringLiteral("copy_to_inactive_split_view"));
QAction* moveToOtherViewAction = col->action(QStringLiteral("move_to_inactive_split_view"));
QAction* copyLocation = col->action(QString("copy_location"));
......@@ -2245,7 +2251,11 @@ void DolphinMainWindow::updateFileAndEditActions()
duplicateAction->setEnabled(true);
addToPlacesAction->setEnabled(true);
copyLocation->setEnabled(true);
// Them triggering selection mode and not directly acting on selected items is signified by adding "…" to their text.
m_actionTextHelper->textsWhenNothingIsSelectedEnabled(true);
} else {
m_actionTextHelper->textsWhenNothingIsSelectedEnabled(false);
stateChanged(QStringLiteral("has_selection"));
QAction* deleteWithTrashShortcut = col->action(QStringLiteral("delete_shortcut")); // see DolphinViewActionHandler
......
......@@ -10,7 +10,7 @@
#define DOLPHIN_MAINWINDOW_H
#include "dolphintabwidget.h"
#include "selectionmode/selectionmodebottombar.h"
#include "selectionmode/bottombar.h"
#include "config-dolphin.h"
#include <KFileItemActions>
#include <kio/fileundomanager.h>
......@@ -48,6 +48,9 @@ class TerminalPanel;
namespace KIO {
class OpenUrlJob;
}
namespace SelectionMode {
class ActionTextHelper;
}
/**
* @short Main window for Dolphin.
......@@ -315,7 +318,7 @@ private Q_SLOTS:
void updatePasteAction();
/** Calls DolphinViewContainer::setSelectionMode() for m_activeViewContainer. */
void slotSetSelectionMode(bool enabled, SelectionModeBottomBar::Contents bottomBarContents);
void slotSetSelectionMode(bool enabled, SelectionMode::BottomBar::Contents bottomBarContents);
/** Selects all items from the active view. */
void selectAll();
......@@ -705,6 +708,7 @@ private:
DolphinRemoteEncoding* m_remoteEncoding;
QPointer<DolphinSettingsDialog> m_settingsDialog;
DolphinBookmarkHandler* m_bookmarkHandler;
SelectionMode::ActionTextHelper* m_actionTextHelper;
// Members for the toolbar menu that is shown when the menubar is hidden:
QToolButton* m_controlButton;
......
......@@ -110,7 +110,7 @@ DolphinPart::DolphinPart(QWidget* parentWidget, QObject* parent,
connect(m_view, &DolphinView::itemCountChanged, this, &DolphinPart::updateStatusBar);
connect(m_view, &DolphinView::selectionChanged, this, &DolphinPart::updateStatusBar);
m_actionHandler = new DolphinViewActionHandler(actionCollection(), this);
m_actionHandler = new DolphinViewActionHandler(actionCollection(), nullptr, this);
m_actionHandler->setCurrentView(m_view);
connect(m_actionHandler, &DolphinViewActionHandler::createDirectoryTriggered, this, &DolphinPart::createDirectory);
......
......@@ -12,7 +12,7 @@
#include "filterbar/filterbar.h"
#include "global.h"
#include "search/dolphinsearchbox.h"
#include "selectionmode/selectionmodetopbar.h"
#include "selectionmode/topbar.h"
#include "statusbar/dolphinstatusbar.h"
#include "views/viewmodecontroller.h"
#include "views/viewproperties.h"
......@@ -373,7 +373,7 @@ void DolphinViewContainer::disconnectUrlNavigator()
m_urlNavigatorConnected = nullptr;
}
void DolphinViewContainer::setSelectionModeEnabled(bool enabled, KActionCollection *actionCollection, SelectionModeBottomBar::Contents bottomBarContents)
void DolphinViewContainer::setSelectionModeEnabled(bool enabled, KActionCollection *actionCollection, SelectionMode::BottomBar::Contents bottomBarContents)
{
const bool wasEnabled = m_view->selectionMode();
m_view->setSelectionMode(enabled);
......@@ -395,28 +395,28 @@ void DolphinViewContainer::setSelectionModeEnabled(bool enabled, KActionCollecti
setSelectionModeEnabled(false);
});
m_selectionModeTopBar = new SelectionModeTopBar(this); // will be created hidden
connect(m_selectionModeTopBar, &SelectionModeTopBar::leaveSelectionModeRequested, this, [this]() {
m_selectionModeTopBar = new SelectionMode::TopBar(this); // will be created hidden
connect(m_selectionModeTopBar, &SelectionMode::TopBar::leaveSelectionModeRequested, this, [this]() {
setSelectionModeEnabled(false);
});
m_topLayout->addWidget(m_selectionModeTopBar, positionFor.selectionModeTopBar, 0);
}
if (!m_selectionModeBottomBar) {
m_selectionModeBottomBar = new SelectionModeBottomBar(actionCollection, this);
m_selectionModeBottomBar = new SelectionMode::BottomBar(actionCollection, this);
connect(m_view, &DolphinView::selectionChanged, this, [this](const KFileItemList &selection) {
m_selectionModeBottomBar->slotSelectionChanged(selection, m_view->url());
});
connect(m_selectionModeBottomBar, &SelectionModeBottomBar::error, this, [this](const QString &errorMessage) {
connect(m_selectionModeBottomBar, &SelectionMode::BottomBar::error, this, [this](const QString &errorMessage) {
showErrorMessage(errorMessage);
});
connect(m_selectionModeBottomBar, &SelectionModeBottomBar::leaveSelectionModeRequested, this, [this]() {
connect(m_selectionModeBottomBar, &SelectionMode::BottomBar::leaveSelectionModeRequested, this, [this]() {
setSelectionModeEnabled(false);
});
m_topLayout->addWidget(m_selectionModeBottomBar, positionFor.selectionModeBottomBar, 0);
}
m_selectionModeBottomBar->resetContents(bottomBarContents);
if (bottomBarContents == SelectionModeBottomBar::GeneralContents) {
if (bottomBarContents == SelectionMode::BottomBar::GeneralContents) {
m_selectionModeBottomBar->slotSelectionChanged(m_view->selectedItems(), m_view->url());
}
......@@ -433,12 +433,12 @@ bool DolphinViewContainer::isSelectionModeEnabled() const
Q_ASSERT((!isEnabled
// We can't assert that the bars are invisible only because the selection mode is disabled because the hide animation might still be playing.
&& (!m_selectionModeBottomBar || !m_selectionModeBottomBar->isEnabled() ||
!m_selectionModeBottomBar->isVisible() || m_selectionModeBottomBar->contents() == SelectionModeBottomBar::PasteContents))
!m_selectionModeBottomBar->isVisible() || m_selectionModeBottomBar->contents() == SelectionMode::BottomBar::PasteContents))
|| ( isEnabled
&& m_selectionModeTopBar && m_selectionModeTopBar->isVisible()
// The bottom bar is either visible or was hidden because it has nothing to show in GeneralContents mode e.g. because no items are selected.
&& m_selectionModeBottomBar
&& (m_selectionModeBottomBar->isVisible() || m_selectionModeBottomBar->contents() == SelectionModeBottomBar::GeneralContents)));
&& (m_selectionModeBottomBar->isVisible() || m_selectionModeBottomBar->contents() == SelectionMode::BottomBar::GeneralContents)));
return isEnabled;
}
......
......@@ -9,7 +9,7 @@
#include "config-dolphin.h"
#include "dolphinurlnavigator.h"
#include "selectionmode/selectionmodebottombar.h"
#include "selectionmode/bottombar.h"
#include "views/dolphinview.h"
#include <KFileItem>
......@@ -33,7 +33,9 @@ class QGridLayout;
class QUrl;
class DolphinSearchBox;
class DolphinStatusBar;
class SelectionModeTopBar;
namespace SelectionMode {
class TopBar;
}
/**
* @short Represents a view for the directory content
......@@ -135,7 +137,7 @@ public:
*/
void disconnectUrlNavigator();
void setSelectionModeEnabled(bool enabled, KActionCollection *actionCollection = nullptr, SelectionModeBottomBar::Contents bottomBarContents = SelectionModeBottomBar::Contents::GeneralContents);
void setSelectionModeEnabled(bool enabled, KActionCollection *actionCollection = nullptr, SelectionMode::BottomBar::Contents bottomBarContents = SelectionMode::BottomBar::Contents::GeneralContents);
bool isSelectionModeEnabled() const;
/**
......@@ -429,14 +431,14 @@ private:
KMessageWidget* m_messageWidget;
/// A bar shown at the top of the view to signify that selection mode is currently active.
SelectionModeTopBar *m_selectionModeTopBar;
SelectionMode::TopBar *m_selectionModeTopBar;
DolphinView* m_view;
FilterBar* m_filterBar;
/// A bar shown at the bottom of the view whose contents depend on what the user is currently doing.
SelectionModeBottomBar *m_selectionModeBottomBar;
SelectionMode::BottomBar *m_selectionModeBottomBar;
DolphinStatusBar* m_statusBar;
QTimer* m_statusBarTimer; // Triggers a delayed update
......
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 2022 Felix Ernst <felixernst@zohomail.eu>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "actiontexthelper.h"
using namespace SelectionMode;
ActionTextHelper::ActionTextHelper(QObject *parent) :
QObject(parent)
{ }
void ActionTextHelper::registerTextWhenNothingIsSelected(QAction *action, QString registeredText)
{
Q_CHECK_PTR(action);
m_registeredActionTextChanges.emplace_back(action, registeredText, TextWhenNothingIsSelected);
}
void ActionTextHelper::textsWhenNothingIsSelectedEnabled(bool enabled)
{
for (auto i = m_registeredActionTextChanges.begin(); i != m_registeredActionTextChanges.end(); ++i) {
if (!i->action) {
i = m_registeredActionTextChanges.erase(i);
continue;
}
if (enabled && i->textStateOfRegisteredText == TextWhenNothingIsSelected) {
QString textWhenSomethingIsSelected = i->action->text();
i->action->setText(i->registeredText);
i->registeredText = textWhenSomethingIsSelected;
i->textStateOfRegisteredText = TextWhenSomethingIsSelected;
} else if (!enabled && i->textStateOfRegisteredText == TextWhenSomethingIsSelected) {
QString textWhenNothingIsSelected = i->action->text();
i->action->setText(i->registeredText);
i->registeredText = textWhenNothingIsSelected;
i->textStateOfRegisteredText = TextWhenNothingIsSelected;
}
}
}
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 2022 Felix Ernst <felixernst@zohomail.eu>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#ifndef ACTIONTEXTHELPER_H
#define ACTIONTEXTHELPER_H
#include <QAction>
#include <QPointer>
#include <QString>
namespace SelectionMode
{
/**
* @brief Helps changing the texts of actions depending on the current selection.
*/
class ActionTextHelper : QObject
{
public:
explicit ActionTextHelper(QObject *parent);
/**
* Changes the text of \a action to \a text whenever textsWhenNothingIsSelectedEnabled(true) is called.
* The texts can be changed back by calling textsWhenNothingIsSelectedEnabled(false) is called.
* @see textsWhenNothingIsSelectedEnabled()
*/
void registerTextWhenNothingIsSelected(QAction *action, QString registeredText);
/**
* Changes all texts that were registered previously using registerTextWhenNothingIsSelected() to those
* registered texts if called with \a enabled == true. Otherwise resets the texts to the original one.
*/
void textsWhenNothingIsSelectedEnabled(bool enabled);
private:
enum TextState {
TextWhenNothingIsSelected,
TextWhenSomethingIsSelected
};
/**
* Utility struct to allow switching back and forth between registered actions showing their
* distinct texts for when no items are selected or when items are selected.
* An example is "Copy" or "Copy…". The latter one is used when nothing is selected and signifies
* that it will trigger SelectionMode so items can be selected and then copied.
*/
struct RegisteredActionTextChange {
QPointer<QAction> action;
QString registeredText;
TextState textStateOfRegisteredText;
RegisteredActionTextChange(QAction *action, QString registeredText, TextState state) :
action{action},
registeredText{registeredText},
textStateOfRegisteredText{state}
{ };
};
/**
* @see RegisteredActionTextChange
*/
std::vector<RegisteredActionTextChange> m_registeredActionTextChanges;
};
}
#endif // ACTIONTEXTHELPER_H
......@@ -12,6 +12,8 @@
#include <QPushButton>
#include <QToolButton>
using namespace SelectionMode;
ActionWithWidget::ActionWithWidget(QAction *action) :
m_action{action}
{ }
......@@ -40,7 +42,7 @@ QWidget *ActionWithWidget::newWidget(QWidget *parent)
return m_widget;
}
QAbstractButton *newButtonForAction(QAction *action, QWidget *parent)
QAbstractButton *SelectionMode::newButtonForAction(QAction *action, QWidget *parent)
{
Q_CHECK_PTR(action);
Q_ASSERT(!action->isSeparator());
......@@ -62,7 +64,7 @@ QAbstractButton *newButtonForAction(QAction *action, QWidget *parent)
return toolButton;
}
void copyActionDataToButton(QAbstractButton *button, QAction *action)
void SelectionMode::copyActionDataToButton(QAbstractButton *button, QAction *action)
{
button->setText(action->text());
button->setIcon(action->icon());
......
......@@ -14,6 +14,9 @@
class QAbstractButton;
namespace SelectionMode
{
/**
* @brief Small wrapper/helper class that contains an action and its widget.
*
......@@ -83,4 +86,6 @@ QAbstractButton *newButtonForAction(QAction *action, QWidget *parent);
*/
void copyActionDataToButton(QAbstractButton *button, QAction *action);
}
#endif // ACTIONWITHWIDGET_H
......@@ -14,6 +14,8 @@
#include <QtGlobal>
#include <QWidget>
using namespace SelectionMode;
BackgroundColorHelper *BackgroundColorHelper::instance()
{
if (!s_instance) {
......
......@@ -15,6 +15,9 @@
class QWidget;
namespace SelectionMode
{
/**
* @brief A Singleton class for managing the colors of selection mode widgets.
*/
......@@ -42,4 +45,6 @@ private:
static BackgroundColorHelper *s_instance;
};
}
#endif // BACKGROUNDCOLORHELPER_H
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 2022 Felix Ernst <felixernst@zohomail.eu>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "bottombar.h"
#include "bottombarcontentscontainer.h"
#include "backgroundcolorhelper.h"
#include "global.h"
#include <KActionCollection>
#include <KFileItem>
#include <KFileItemListProperties>
#include <KStandardAction>
#include <QGridLayout>
#include <QResizeEvent>
#include <QScrollArea>
#include <QStyle>
#include <QtGlobal>
#include <QTimer>
using namespace SelectionMode;
BottomBar::BottomBar(KActionCollection *actionCollection, QWidget *parent) :
QWidget{parent}
{
// Showing of this widget is normally animated. We hide it for now and make it small.
hide();
setMaximumHeight(0);
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
setMinimumWidth(0);
auto fillParentLayout = new QGridLayout(this);
fillParentLayout->setContentsMargins(0, 0, 0, 0);
// Put the contents into a QScrollArea. This prevents increasing the view width
// in case that not enough width for the contents is available. (this trick is also used in dolphinsearchbox.cpp.)
m_scrollArea = new QScrollArea(this);
fillParentLayout->addWidget(m_scrollArea);
m_scrollArea->setFrameShape(QFrame::NoFrame);
m_scrollArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_scrollArea->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
m_scrollArea->setWidgetResizable(true);
m_contentsContainer = new BottomBarContentsContainer(actionCollection, m_scrollArea);
m_scrollArea->setWidget(m_contentsContainer);
m_contentsContainer->installEventFilter(this); // Adjusts the height of this bar to the height of the contentsContainer
connect(m_contentsContainer, &BottomBarContentsContainer::error, this, &BottomBar::error);
connect(m_contentsContainer, &BottomBarContentsContainer::barVisibilityChangeRequested, this, [this](bool visible){
if (!m_allowedToBeVisible && visible) {
return;
}
setVisibleInternal(visible, WithAnimation);
});
connect(m_contentsContainer, &BottomBarContentsContainer::leaveSelectionModeRequested, this, &BottomBar::leaveSelectionModeRequested);
BackgroundColorHelper::instance()->controlBackgroundColor(this);
}
void BottomBar::setVisible(bool visible, Animated animated)
{
m_allowedToBeVisible = visible;
setVisibleInternal(visible, animated);
}
void BottomBar::setVisibleInternal(bool visible, Animated animated)
{
Q_ASSERT_X(animated == WithAnimation, "SelectionModeBottomBar::setVisible", "This wasn't implemented.");
if (!visible && contents() == PasteContents) {
return; // The bar with PasteContents should not be hidden or users might not know how to paste what they just copied.
// Set contents to anything else to circumvent this prevention mechanism.
}
if (visible && !m_contentsContainer->hasSomethingToShow()) {
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.
}
setEnabled(visible);
if (m_heightAnimation) {
m_heightAnimation->stop(); // deletes because of QAbstractAnimation::DeleteWhenStopped.
}
m_heightAnimation = new QPropertyAnimation(this, "maximumHeight");
m_heightAnimation->setDuration(2 *
style()->styleHint(QStyle::SH_Widget_Animation_Duration, nullptr, this) *
GlobalConfig::animationDurationFactor());
m_heightAnimation->setStartValue(height());
m_heightAnimation->setEasingCurve(QEasingCurve::OutCubic);
if (visible) {
show();
m_heightAnimation->setEndValue(sizeHint().height());
connect(m_heightAnimation, &QAbstractAnimation::finished,
this, [this](){ setMaximumHeight(sizeHint().height()); });
} else {
m_heightAnimation->setEndValue(0);
connect(m_heightAnimation, &QAbstractAnimation::finished,
this, &QWidget::hide);
}
m_heightAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}
QSize BottomBar::sizeHint() const
{
return QSize{1, m_contentsContainer->sizeHint().height()};
// 1 as width because this widget should never be the reason the DolphinViewContainer is made wider.
}
void BottomBar::slotSelectionChanged(const KFileItemList &selection, const QUrl &baseUrl)
{