Improve code quality

This commit is contained in:
Felix Ernst 2022-04-25 12:52:05 +02:00
parent 8e55f2c240
commit 78cffd2979
15 changed files with 147 additions and 79 deletions

View file

@ -125,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);
@ -1675,8 +1675,7 @@ void DolphinMainWindow::setupActions()
QAction *toggleSelectionModeAction = actionCollection()->addAction(QStringLiteral("toggle_selection_mode"));
// i18n: This action toggles a selection mode.
toggleSelectionModeAction->setText(i18nc("@action:inmenu", "Select Files and Folders"));
// i18n: Opens a selection mode for selecting files/folders and later selecting an action that acts on them.
// So in a way "Select" here is used to mean both "Select files" and also "Select what to do" but mostly the first.
// i18n: Opens a selection mode for selecting files/folders.
// The text is kept so unspecific because it will be shown on the toolbar where space is at a premium.
toggleSelectionModeAction->setIconText(i18nc("@action:intoolbar", "Select"));
toggleSelectionModeAction->setWhatsThis(xi18nc("@info:whatsthis", "<para>This application only knows which files or folders should be acted on if they are"

View file

@ -22,10 +22,13 @@ void ActionTextHelper::registerTextWhenNothingIsSelected(QAction *action, QStrin
void ActionTextHelper::textsWhenNothingIsSelectedEnabled(bool enabled)
{
for (auto i = m_registeredActionTextChanges.begin(); i != m_registeredActionTextChanges.end(); ++i) {
if (!i->action) {
while (!i->action) {
i = m_registeredActionTextChanges.erase(i);
continue;
if (i == m_registeredActionTextChanges.end()) {
break;
}
}
if (enabled && i->textStateOfRegisteredText == TextWhenNothingIsSelected) {
QString textWhenSomethingIsSelected = i->action->text();
i->action->setText(i->registeredText);

View file

@ -17,6 +17,11 @@ namespace SelectionMode
/**
* @brief Helps changing the texts of actions depending on the current selection.
*
* This is useful for actions that directly trigger a change when there is a selection and do something
* different when nothing is selected. For example should the copy action read "Copy" when items are
* selected but when no items are selected it can read "Copy…" since triggering it will enter selection
* mode and ask users to select the files they want to copy first.
*/
class ActionTextHelper : QObject
{
@ -25,7 +30,7 @@ public:
/**
* 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.
* The texts can be changed back by calling textsWhenNothingIsSelectedEnabled(false).
* @see textsWhenNothingIsSelectedEnabled()
*/
void registerTextWhenNothingIsSelected(QAction *action, QString registeredText);

View file

@ -21,6 +21,9 @@ namespace SelectionMode
* @brief Small wrapper/helper class that contains an action and its widget.
*
* This class takes neither the responsibility for deleting its action() nor its widget().
*
* This class is only used from BottomBarContentsContainer currently.
* @see BottomBarContentsContainer
*/
class ActionWithWidget
{
@ -28,9 +31,9 @@ public:
ActionWithWidget(QAction *action);
/**
* Connect @p action and @p button using copyActionDataToButton() and the
* wraps the two together in the ActionWithWidget object.
* ActionWithWidget doesn't take any ownership.
* Connect @p action and @p button using copyActionDataToButton() and
* wraps the two together in a ActionWithWidget object.
* ActionWithWidget doesn't take any ownership over the parameters.
*
* @see copyActionDataToButton()
*
@ -38,7 +41,7 @@ public:
*/
ActionWithWidget(QAction *action, QAbstractButton *button);
/** @returns the action of this object. Crashes if that action has been deleted elsewhere in the meantime. */
/** @returns the action of this object. */
inline QAction *action() {
Q_CHECK_PTR(m_action);
return m_action;
@ -69,7 +72,7 @@ private:
/**
* A small helper method.
* @return a button with the correct styling for the general mode of the SelectionModeBottomBar which can be added to its layout.
* @return a button with the correct styling for the general mode of the BottomBarContentsContainer which can be added to its layout.
*/
QAbstractButton *newButtonForAction(QAction *action, QWidget *parent);

View file

@ -54,9 +54,11 @@ void BackgroundColorHelper::slotPaletteChanged()
{
updateBackgroundColor();
for (auto i = m_colorControlledWidgets.begin(); i != m_colorControlledWidgets.end(); ++i) {
if (!*i) {
while (!*i) {
i = m_colorControlledWidgets.erase(i);
continue;
if (i == m_colorControlledWidgets.end()) {
break;
}
}
setBackgroundColorForWidget(*i, m_backgroundColor);
}
@ -83,7 +85,8 @@ void BackgroundColorHelper::updateBackgroundColor()
}
m_backgroundColor = QColor::fromHsv(newHue,
// Saturation should be closer to the active color because otherwise the selection mode color might overpower it.
// Saturation should be closer to the saturation of the active color
// because otherwise the selection mode color might overpower it.
.7 * activeBackgroundColor.saturation() + .3 * positiveBackgroundColor.saturation(),
(activeBackgroundColor.value() + positiveBackgroundColor.value()) / 2,
(activeBackgroundColor.alpha() + positiveBackgroundColor.alpha()) / 2);

View file

@ -28,20 +28,30 @@ public:
/**
* Changes the background color of @p widget to a distinct color scheme matching color which makes it clear that the widget belongs to the selection mode.
* The background color of @p widget will from now on be updated automatically when the palette of the application changes.
*/
void controlBackgroundColor(QWidget *widget);
private:
BackgroundColorHelper();
/**
* Called when the palette of the application changes.
* Triggers updateBackgroundColor() and the updates the background color of m_colorControlledWidgets.
* @see updateBackgroundColor
*/
void slotPaletteChanged();
/** Calculates a new m_colorControlledWidgets based on the current colour scheme of the application. */
void updateBackgroundColor();
private:
/// The widgets who have given up control over the background color to BackgroundColorHelper.
std::vector<QPointer<QWidget>> m_colorControlledWidgets;
/// The color to be used for the widgets' backgrounds.
QColor m_backgroundColor;
/// Singleton object
static BackgroundColorHelper *s_instance;
};

View file

@ -11,11 +11,6 @@
#include "backgroundcolorhelper.h"
#include "global.h"
#include <KActionCollection>
#include <KFileItem>
#include <KFileItemListProperties>
#include <KStandardAction>
#include <QGridLayout>
#include <QResizeEvent>
#include <QScrollArea>
@ -87,7 +82,6 @@ void BottomBar::setVisibleInternal(bool visible, Animated animated)
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) {
@ -166,7 +160,7 @@ void BottomBar::resizeEvent(QResizeEvent *resizeEvent)
return QWidget::resizeEvent(resizeEvent);
}
m_contentsContainer->updateForNewWidth();
m_contentsContainer->adaptToNewBarWidth(width());
return QWidget::resizeEvent(resizeEvent);
}

View file

@ -15,8 +15,6 @@
#include <QPropertyAnimation>
#include <QWidget>
#include <memory>
class KActionCollection;
class KFileItemList;
class QAction;
@ -30,7 +28,7 @@ namespace SelectionMode
class BottomBarContentsContainer;
/**
* A bar used in selection mode that serves various purposes depending on what the user is currently trying to do.
* @brief A bar used in selection mode that serves various purposes depending on what the user is currently trying to do.
*
* The Contents enum below gives a rough idea about the different states this bar might have.
* The bar is notified of various changes that make changing or updating the content worthwhile.
@ -43,7 +41,7 @@ class BottomBar : public QWidget
public:
/** The different contents this bar can have. */
enum Contents{
enum Contents {
CopyContents,
CopyLocationContents,
CopyToOtherViewContents,
@ -69,11 +67,20 @@ public:
*
* This bar might also not show itself when setVisible(true), when context menu actions are supposed to be shown
* for the selected items but no items have been selected yet. In that case it will only show itself once items were selected.
*
* This bar might also ignore a setVisible(false) call, if it has PasteContents because that bar is supposed to stay visible
* even outside of selection mode.
*
* @param visible Whether this bar is supposed to be visible long term
* @param animated Whether this should be animated. The animation is skipped if the users' settings are configured that way.
*
* @see QWidget::setVisible()
*/
void setVisible(bool visible, Animated animated);
using QWidget::setVisible; // Makes sure that the setVisible() declaration above doesn't hide the one from QWidget.
/**
* Changes the contents of the bar to @p contents.
*/
void resetContents(Contents contents);
Contents contents() const;
@ -81,6 +88,7 @@ public:
QSize sizeHint() const override;
public Q_SLOTS:
/** Adapts the contents based on the selection in the related view. */
void slotSelectionChanged(const KFileItemList &selection, const QUrl &baseUrl);
/** Used to notify the m_selectionModeBottomBar that there is no other ViewContainer in the tab. */
@ -102,6 +110,8 @@ protected:
void resizeEvent(QResizeEvent *resizeEvent) override;
private:
using QWidget::setVisible; // Makes sure that the setVisible() declaration above doesn't hide the one from QWidget so we can still use it privately.
/**
* Identical to SelectionModeBottomBar::setVisible() but doesn't change m_allowedToBeVisible.
* @see SelectionModeBottomBar::setVisible()
@ -119,7 +129,7 @@ private:
* This is necessary because this bar might have been setVisible(true) but there is no reason to show the bar currently so it was kept hidden.
* @see SelectionModeBottomBar::setVisible() */
bool m_allowedToBeVisible = false;
/// @see SelectionModeBottomBar::setVisible()
/** @see SelectionModeBottomBar::setVisible() */
QPointer<QPropertyAnimation> m_heightAnimation;
};

View file

@ -69,8 +69,10 @@ void BottomBarContentsContainer::resetContents(BottomBar::Contents contents)
}
}
void BottomBarContentsContainer::updateForNewWidth()
void BottomBarContentsContainer::adaptToNewBarWidth(int newBarWidth)
{
m_barWidth = newBarWidth;
if (m_contents == BottomBar::GeneralContents) {
Q_ASSERT(m_overflowButton);
if (unusedSpace() < 0) {
@ -94,7 +96,7 @@ void BottomBarContentsContainer::updateForNewWidth()
}
}
} else {
// We have some unusedSpace(). Let's check if we can maybe add more of the contextual action's widgets.
// We have some unusedSpace(). Let's check if we can maybe add more of the contextual actions' widgets.
for (auto i = m_generalBarActions.begin(); i != m_generalBarActions.end(); ++i) {
if (i->isWidgetVisible()) {
continue;
@ -130,6 +132,7 @@ void BottomBarContentsContainer::slotSelectionChanged(const KFileItemList &selec
auto contextActions = contextActionsFor(selection, baseUrl);
m_generalBarActions.clear();
if (contextActions.empty()) {
// We have nothing to show
Q_ASSERT(qobject_cast<BottomBar *>(parentWidget()->parentWidget()->parentWidget()));
if (isVisibleTo(parentWidget()->parentWidget()->parentWidget()->parentWidget())) { // is the bar visible
Q_EMIT barVisibilityChangeRequested(false);
@ -162,7 +165,7 @@ void BottomBarContentsContainer::addCopyContents()
// We claim to have PasteContents already so triggering the copy action next won't instantly hide the bottom bar.
connect(copyButton, &QAbstractButton::clicked, [this]() {
if (GeneralSettings::showPasteBarAfterCopying()) {
m_contents = BottomBar::Contents::PasteContents;
m_contents = BottomBar::Contents::PasteContents; // prevents hiding
}
});
// Connect the copy action as a second step.
@ -232,7 +235,7 @@ void BottomBarContentsContainer::addCutContents()
// We claim to have PasteContents already so triggering the cut action next won't instantly hide the bottom bar.
connect(cutButton, &QAbstractButton::clicked, [this]() {
if (GeneralSettings::showPasteBarAfterCopying()) {
m_contents = BottomBar::Contents::PasteContents;
m_contents = BottomBar::Contents::PasteContents; // prevents hiding
}
});
// Connect the cut action as a second step.
@ -400,9 +403,9 @@ void BottomBarContentsContainer::addPasteContents()
vBoxLayout->addWidget(pasteButton);
auto *dismissButton = new QToolButton(this);
dismissButton->setText(i18nc("@action Dismisses a bar explaining how to use the Paste action", "Dismiss this Reminder"));
dismissButton->setText(i18nc("@action Dismisses a bar explaining how to use the Paste action", "Dismiss This Reminder"));
connect(dismissButton, &QAbstractButton::clicked, this, actuallyLeaveSelectionMode);
auto *dontRemindAgainAction = new QAction(i18nc("@action Dismisses an explanatory area and never shows it again", "Don't remind me again"), this);
auto *dontRemindAgainAction = new QAction(i18nc("@action Dismisses an explanatory area and never shows it again", "Don't Remind Me Again"), this);
connect(dontRemindAgainAction, &QAction::triggered, this, []() {
GeneralSettings::setShowPasteBarAfterCopying(false);
});
@ -516,9 +519,7 @@ int BottomBarContentsContainer::unusedSpace() const
}
sumOfPreferredWidths += m_layout->itemAt(i)->sizeHint().width() + m_layout->spacing();
}
Q_ASSERT(qobject_cast<BottomBar *>(parentWidget()->parentWidget()->parentWidget()));
const int totalBarWidth = parentWidget()->parentWidget()->parentWidget()->width();
return totalBarWidth - sumOfPreferredWidths - 20; // We consider all space used when there are only 20 pixels left
return m_barWidth - sumOfPreferredWidths - 20; // We consider all space used when there are only 20 pixels left
// so there is some room to breath and not too much wonkyness while resizing.
}
@ -535,7 +536,7 @@ void BottomBarContentsContainer::updateExplanatoryLabelVisibility()
}
}
void BottomBarContentsContainer::updateMainActionButton(const KFileItemList& selection)
void BottomBarContentsContainer::updateMainActionButton(const KFileItemList& selectedItems)
{
if (!m_mainAction.widget()) {
return;
@ -543,45 +544,69 @@ void BottomBarContentsContainer::updateMainActionButton(const KFileItemList& sel
Q_ASSERT(qobject_cast<QAbstractButton *>(m_mainAction.widget()));
// Users are nudged towards selecting items by having the button disabled when nothing is selected.
m_mainAction.widget()->setEnabled(selection.count() > 0 && m_mainAction.action()->isEnabled());
m_mainAction.widget()->setEnabled(selectedItems.count() > 0 && m_mainAction.action()->isEnabled());
QFontMetrics fontMetrics = m_mainAction.widget()->fontMetrics();
QString buttonText;
switch (m_contents) {
case BottomBar::CopyContents:
buttonText = i18ncp("@action A more elaborate and clearly worded version of the Copy action",
"Copy %2 to the Clipboard", "Copy %2 to the Clipboard", selection.count(),
fileItemListToString(selection, fontMetrics.averageCharWidth() * 20, fontMetrics));
// i18n: A more elaborate and clearly worded version of the Copy action
// %2 is a textual representation of the currently selected files or folders. This can be the name of
// the file/files like "file1" or "file1, file2 and file3" or an aggregate like "8 Selected Folders".
// If this sort of word puzzle can not be correctly translated in your language, translate it as "NULL" (without the quotes)
// and a fallback will be used.
buttonText = i18ncp("@action", "Copy %2 to the Clipboard", "Copy %2 to the Clipboard", selectedItems.count(), fileItemListToString(selectedItems, fontMetrics.averageCharWidth() * 20, fontMetrics));
// All these long lines can not be broken up with line breaks becaue the i18n call should be completely
// in the line following the "i18n:" comment without any line breaks within the i18n call
// or the comment might not be correctly extracted. See: https://commits.kde.org/kxmlgui/a31135046e1b3335b5d7bbbe6aa9a883ce3284c1
break;
case BottomBar::CopyLocationContents:
buttonText = i18ncp("@action A more elaborate and clearly worded version of the Copy Location action",
"Copy the Location of %2 to the Clipboard", "Copy the Location of %2 to the Clipboard", selection.count(),
fileItemListToString(selection, fontMetrics.averageCharWidth() * 20, fontMetrics));
// i18n: A more elaborate and clearly worded version of the Copy Location action
// %2 is a textual representation of the currently selected files or folders. This can be the name of
// the file/files like "file1" or "file1, file2 and file3" or an aggregate like "8 Selected Folders".
// If this sort of word puzzle can not be correctly translated in your language, translate it as "NULL" (without the quotes)
// and a fallback will be used.
buttonText = i18ncp("@action", "Copy the Location of %2 to the Clipboard", "Copy the Location of %2 to the Clipboard", selectedItems.count(), fileItemListToString(selectedItems, fontMetrics.averageCharWidth() * 20, fontMetrics));
break;
case BottomBar::CutContents:
buttonText = i18ncp("@action A more elaborate and clearly worded version of the Cut action",
"Cut %2 to the Clipboard", "Cut %2 to the Clipboard", selection.count(),
fileItemListToString(selection, fontMetrics.averageCharWidth() * 20, fontMetrics));
// i18n: A more elaborate and clearly worded version of the Cut action
// %2 is a textual representation of the currently selected files or folders. This can be the name of
// the file/files like "file1" or "file1, file2 and file3" or an aggregate like "8 Selected Folders".
// If this sort of word puzzle can not be correctly translated in your language, translate it as "NULL" (without the quotes)
// and a fallback will be used.
buttonText = i18ncp("@action", "Cut %2 to the Clipboard", "Cut %2 to the Clipboard", selectedItems.count(), fileItemListToString(selectedItems, fontMetrics.averageCharWidth() * 20, fontMetrics));
break;
case BottomBar::DeleteContents:
buttonText = i18ncp("@action A more elaborate and clearly worded version of the Delete action",
"Permanently Delete %2", "Permanently Delete %2", selection.count(),
fileItemListToString(selection, fontMetrics.averageCharWidth() * 20, fontMetrics));
// i18n: A more elaborate and clearly worded version of the Delete action
// %2 is a textual representation of the currently selected files or folders. This can be the name of
// the file/files like "file1" or "file1, file2 and file3" or an aggregate like "8 Selected Folders".
// If this sort of word puzzle can not be correctly translated in your language, translate it as "NULL" (without the quotes)
// and a fallback will be used.
buttonText = i18ncp("@action", "Permanently Delete %2", "Permanently Delete %2", selectedItems.count(), fileItemListToString(selectedItems, fontMetrics.averageCharWidth() * 20, fontMetrics));
break;
case BottomBar::DuplicateContents:
buttonText = i18ncp("@action A more elaborate and clearly worded version of the Duplicate action",
"Duplicate %2", "Duplicate %2", selection.count(),
fileItemListToString(selection, fontMetrics.averageCharWidth() * 20, fontMetrics));
// i18n: A more elaborate and clearly worded version of the Duplicate action
// %2 is a textual representation of the currently selected files or folders. This can be the name of
// the file/files like "file1" or "file1, file2 and file3" or an aggregate like "8 Selected Folders".
// If this sort of word puzzle can not be correctly translated in your language, translate it as "NULL" (without the quotes)
// and a fallback will be used.
buttonText = i18ncp("@action", "Duplicate %2", "Duplicate %2", selectedItems.count(), fileItemListToString(selectedItems, fontMetrics.averageCharWidth() * 20, fontMetrics));
break;
case BottomBar::MoveToTrashContents:
buttonText = i18ncp("@action A more elaborate and clearly worded version of the Trash action",
"Move %2 to the Trash", "Move %2 to the Trash", selection.count(),
fileItemListToString(selection, fontMetrics.averageCharWidth() * 20, fontMetrics));
// i18n: A more elaborate and clearly worded version of the Trash action
// %2 is a textual representation of the currently selected files or folders. This can be the name of
// the file/files like "file1" or "file1, file2 and file3" or an aggregate like "8 Selected Folders".
// If this sort of word puzzle can not be correctly translated in your language, translate it as "NULL" (without the quotes)
// and a fallback will be used.
buttonText = i18ncp("@action", "Move %2 to the Trash", "Move %2 to the Trash", selectedItems.count(), fileItemListToString(selectedItems, fontMetrics.averageCharWidth() * 20, fontMetrics));
break;
case BottomBar::RenameContents:
buttonText = i18ncp("@action A more elaborate and clearly worded version of the Rename action",
"Rename %2", "Rename %2", selection.count(),
fileItemListToString(selection, fontMetrics.averageCharWidth() * 20, fontMetrics));
// i18n: A more elaborate and clearly worded version of the Rename action
// %2 is a textual representation of the currently selected files or folders. This can be the name of
// the file/files like "file1" or "file1, file2 and file3" or an aggregate like "8 Selected Folders".
// If this sort of word puzzle can not be correctly translated in your language, translate it as "NULL" (without the quotes)
// and a fallback will be used.
buttonText = i18ncp("@action", "Rename %2", "Rename %2", selectedItems.count(), fileItemListToString(selectedItems, fontMetrics.averageCharWidth() * 20, fontMetrics));
break;
default:
return;

View file

@ -43,6 +43,9 @@ public:
*/
explicit BottomBarContentsContainer(KActionCollection *actionCollection, QWidget *parent);
/**
* @param contents The kind of contents that should be contained instead.
*/
void resetContents(BottomBar::Contents contents);
inline BottomBar::Contents contents() const
{
@ -53,9 +56,14 @@ public:
return contents() != BottomBar::GeneralContents || m_internalContextMenu;
}
void updateForNewWidth();
/**
* Is called when the BottomBar resizes to let this ContentsContainer know that it should adapt its contents to the new width.
* Adapting is done by showing or hiding labels or buttons.
*/
void adaptToNewBarWidth(int newBarWidth);
public Q_SLOTS:
/** Adapts the contents based on the selection in the related view. */
void slotSelectionChanged(const KFileItemList &selection, const QUrl &baseUrl);
Q_SIGNALS:
@ -65,8 +73,8 @@ Q_SIGNALS:
void error(const QString &errorMessage);
/**
* Sometimes the contents see no reason to be visible and request the bar to be hidden instead which emits this signal.
* This can later change e.g. because the user selected items. Then this signal is used to request showing of the bar.
* When it does not make sense to show any specific contents, this signal is emitted and the receiver hides the bar.
* Later it might sense to show it again e.g. because the user selected items. Then this signal is used to request showing of the bar.
*/
void barVisibilityChangeRequested(bool visible);
@ -90,15 +98,15 @@ private:
void addRenameContents();
/**
* Deletes all visible widgets and layouts from the bar.
* Deletes every child layout and child widget of this container.
*/
void emptyBarContents();
/**
* @returns A vector containing contextual actions for the given \a selection in the \a baseUrl.
* @returns A vector containing contextual actions for the given \a selectedItems in the \a baseUrl.
* Cut, Copy, Rename and MoveToTrash are always added. Any further contextual actions depend on
* \a selection and \a baseUrl. \a selection and \a baseUrl can be empty/default constructed if
* no item- or view-specific actions should be added aside from Cut, Copy, Rename, MoveToTrash.
* \a selectedItems and \a baseUrl.
* If there are no \a selectedItems, an empty vector is returned and m_internalContextMenu is deleted.
* @param selectedItems The selected items for which contextual actions should be displayed.
* @param baseUrl Base URL of the viewport the contextual actions apply to.
*/
@ -107,7 +115,7 @@ private:
/**
* @returns the amount of pixels that can be spared to add more widgets. A negative value might
* be returned which signifies that some widgets should be hidden or removed from this bar to
* make sure that this SelectionModeBottomBar won't stretch the width of its parent.
* make sure that this BottomBarContentsContainer can fully fit on the BottomBar.
*/
int unusedSpace() const;
@ -118,12 +126,12 @@ private:
void updateExplanatoryLabelVisibility();
/**
* Changes the text and enabled state of the main action button
* based on the amount of currently selected items and the state of the current m_mainAction.
* Changes the text and enabled state of the main action button based on the amount of currently
* selected items and the state of the current m_mainAction.
* The current main action depends on the current barContents.
* @param selection the currently selected fileItems.
* @param selectedItems the currently selected fileItems.
*/
void updateMainActionButton(const KFileItemList &selection);
void updateMainActionButton(const KFileItemList &selectedItems);
private:
/// All the actions that should be available from this bar when in general mode.
@ -141,11 +149,12 @@ private:
KActionCollection *m_actionCollection;
/// Describes the current contents of the bar.
BottomBar::Contents m_contents;
/** The layout all the buttons and labels are added to.
* Do not confuse this with layout() because we do have a QScrollView in between this widget and m_layout. */
/// The main layout of this ContentsContainer that all the buttons and labels are added to.
QHBoxLayout *m_layout;
/// The info label used for some of the BarContents. Is hidden for narrow widths.
/// Caches the totalBarWidth as set in adaptToNewWidth(newBarWidth). */
int m_barWidth = 0;
/// The info label used for some of the Contents. Is hidden for narrow widths.
QPointer<QLabel> m_explanatoryLabel;
};

View file

@ -42,7 +42,7 @@ TopBar::TopBar(QWidget *parent) :
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 selectionmodebottombar.cpp.)
// in case that not enough width for the contents is available. (this trick is also used in bottombar.cpp.)
auto scrollArea = new QScrollArea(this);
fillParentLayout->addWidget(scrollArea);
scrollArea->setFrameShape(QFrame::NoFrame);
@ -111,9 +111,10 @@ void TopBar::setVisible(bool visible, Animated animated)
m_heightAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}
void TopBar::resizeEvent(QResizeEvent */* resizeEvent */)
void TopBar::resizeEvent(QResizeEvent *resizeEvent)
{
updateLabelString();
return QWidget::resizeEvent(resizeEvent);
}
void TopBar::updateLabelString()

View file

@ -40,15 +40,17 @@ public:
* @see QWidget::setVisible()
*/
void setVisible(bool visible, Animated animated);
using QWidget::setVisible; // Makes sure that the setVisible() declaration above doesn't hide the one from QWidget.
Q_SIGNALS:
void leaveSelectionModeRequested();
protected:
void resizeEvent(QResizeEvent */* resizeEvent */) override;
/** Calls updateLabelString() */
void resizeEvent(QResizeEvent *resizeEvent) override;
private:
using QWidget::setVisible; // Makes sure that the setVisible() declaration above doesn't hide the one from QWidget so we can still use it privately.
/** Decides whether the m_fullLabelString or m_shortLabelString should be used based on available width. */
void updateLabelString();

View file

@ -301,7 +301,6 @@ bool DolphinView::selectionMode() const
return m_container->controller()->selectionMode();
}
void DolphinView::setPreviewsShown(bool show)
{
if (previewsShown() == show) {

View file

@ -112,6 +112,9 @@ public:
void setViewMode(Mode mode);
Mode viewMode() const;
/**
* Enables or disables a mode for quick and easy selection of items.
*/
void setSelectionMode(bool enabled);
bool selectionMode() const;

View file

@ -166,6 +166,7 @@ void DolphinViewActionHandler::createActions(SelectionMode::ActionTextHelper *ac
connect(copyPathAction, &QAction::triggered, this, &DolphinViewActionHandler::slotCopyPath);
if (actionTextHelper) {
// The "…" at the end make clear that they won't trigger their respective actions directly.
actionTextHelper->registerTextWhenNothingIsSelected(trashAction, i18nc("@action:inmenu File", "Move to Trash…"));
actionTextHelper->registerTextWhenNothingIsSelected(deleteAction, i18nc("@action:inmenu File", "Delete…"));
actionTextHelper->registerTextWhenNothingIsSelected(duplicateAction, i18nc("@action:inmenu File", "Duplicate Here…"));
@ -438,6 +439,7 @@ void DolphinViewActionHandler::slotRename()
} else {
Q_EMIT actionBeingHandled();
m_currentView->renameSelectedItems();
// We don't exit selectionMode here because users might want to rename more items.
}
}