┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAkseli Lahtinen <[email protected]>2025-02-24 18:39:22 +0000
committerAkseli Lahtinen <[email protected]>2025-02-24 18:39:22 +0000
commita27443d904bc220615f2c4e8df74187b0c806d8a (patch)
tree420ff120b30bb2492a363abf9ddf80a8697d3ad9
parent69c4792928edef91b5aea06772d02eb0f7c873b4 (diff)
Add smaller statusbar and set it as default
- Statusbar has three modes: Small, FullWidth and Disabled - FullWidth is the original statusbar - Small is the new default statusbar - This statusbar overlays on top of the items instead of taking space - It changes size according to content - Disabled turns statusbar completely off - Zoom slider and space information is only shown in full-width statusbar - Space information is now always on - If user navigates with keyboard, or scrolls to selection, the scrolling will take the statusbar into account - This makes sure the statusbar does not cover any items Related discussion: https://invent.kde.org/system/dolphin/-/issues/50
-rw-r--r--src/CMakeLists.txt14
-rw-r--r--src/dolphinmainwindow.cpp8
-rw-r--r--src/dolphinviewcontainer.cpp85
-rw-r--r--src/dolphinviewcontainer.h14
-rw-r--r--src/kitemviews/kitemlistview.cpp16
-rw-r--r--src/kitemviews/kitemlistview.h8
-rw-r--r--src/kitemviews/private/kitemlistviewlayouter.cpp9
-rw-r--r--src/kitemviews/private/kitemlistviewlayouter.h8
-rw-r--r--src/settings/dolphin_25.04_update_statusandlocationbarssettings.cpp28
-rw-r--r--src/settings/dolphin_generalsettings.kcfg17
-rw-r--r--src/settings/dolphin_statusandlocationbarssettings.upd9
-rw-r--r--src/settings/interface/statusandlocationbarssettingspage.cpp49
-rw-r--r--src/settings/interface/statusandlocationbarssettingspage.h7
-rw-r--r--src/statusbar/dolphinstatusbar.cpp114
-rw-r--r--src/statusbar/dolphinstatusbar.h36
-rw-r--r--src/tests/dolphinmainwindowtest.cpp6
-rw-r--r--src/views/dolphinview.cpp16
-rw-r--r--src/views/dolphinview.h12
18 files changed, 400 insertions, 56 deletions
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index ef50cf77d..6e52772e0 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -634,8 +634,22 @@ install( FILES settings/dolphin_directoryviewpropertysettings.kcfg
install( FILES settings/dolphin_detailsmodesettings.upd
settings/dolphin_directorysizemode.upd
settings/dolphin_directorysizemode.py
+ settings/dolphin_statusandlocationbarssettings.upd
DESTINATION ${KDE_INSTALL_KCONFUPDATEDIR} )
+# install KF6 kconfig updater C++ scripts to kconf_update_bin
+add_executable(dolphin_25.04_update_statusandlocationbarssettings "settings/dolphin_25.04_update_statusandlocationbarssettings.cpp")
+target_link_libraries(dolphin_25.04_update_statusandlocationbarssettings
+ KF6::ConfigCore
+ KF6::XmlGui
+)
+
+install(
+ TARGETS
+ dolphin_25.04_update_statusandlocationbarssettings
+ DESTINATION ${KDE_INSTALL_LIBDIR}/kconf_update_bin
+)
+
if(BUILD_TESTING)
add_subdirectory(tests)
endif()
diff --git a/src/dolphinmainwindow.cpp b/src/dolphinmainwindow.cpp
index c8538bce4..a2d6e0b9c 100644
--- a/src/dolphinmainwindow.cpp
+++ b/src/dolphinmainwindow.cpp
@@ -2129,14 +2129,6 @@ void DolphinMainWindow::setupActions()
&DolphinMainWindow::toggleShowMenuBar,
Qt::QueuedConnection);
- KToggleAction *showStatusBar = KStandardAction::showStatusbar(nullptr, nullptr, actionCollection());
- showStatusBar->setChecked(GeneralSettings::showStatusBar());
- connect(GeneralSettings::self(), &GeneralSettings::showStatusBarChanged, showStatusBar, &KToggleAction::setChecked);
- connect(showStatusBar, &KToggleAction::triggered, this, [this](bool checked) {
- GeneralSettings::setShowStatusBar(checked);
- refreshViews();
- });
-
KStandardAction::keyBindings(this, &DolphinMainWindow::slotKeyBindings, actionCollection());
KStandardAction::preferences(this, &DolphinMainWindow::editSettings, actionCollection());
diff --git a/src/dolphinviewcontainer.cpp b/src/dolphinviewcontainer.cpp
index f2df638f6..99b7a4042 100644
--- a/src/dolphinviewcontainer.cpp
+++ b/src/dolphinviewcontainer.cpp
@@ -17,6 +17,7 @@
#include "dolphinplacesmodelsingleton.h"
#include "filterbar/filterbar.h"
#include "global.h"
+#include "kitemviews/kitemlistcontainer.h"
#include "search/dolphinsearchbox.h"
#include "selectionmode/topbar.h"
#include "statusbar/dolphinstatusbar.h"
@@ -42,6 +43,8 @@
#include <QGridLayout>
#include <QGuiApplication>
#include <QRegularExpression>
+#include <QScrollBar>
+#include <QStyle>
#include <QTimer>
#include <QUrl>
#include <QUrlQuery>
@@ -173,6 +176,9 @@ DolphinViewContainer::DolphinViewContainer(const QUrl &url, QWidget *parent)
connect(m_statusBar, &DolphinStatusBar::showMessage, this, [this](const QString &message, KMessageWidget::MessageType messageType) {
showMessage(message, messageType);
});
+ connect(m_statusBar, &DolphinStatusBar::widthUpdated, this, &DolphinViewContainer::updateStatusBarGeometry);
+ connect(m_statusBar, &DolphinStatusBar::urlChanged, this, &DolphinViewContainer::updateStatusBar);
+ connect(this, &DolphinViewContainer::showFilterBarChanged, this, &DolphinViewContainer::updateStatusBar);
m_statusBarTimer = new QTimer(this);
m_statusBarTimer->setSingleShot(true);
@@ -186,7 +192,24 @@ DolphinViewContainer::DolphinViewContainer(const QUrl &url, QWidget *parent)
m_topLayout->addWidget(m_messageWidget, positionFor.messageWidget, 0);
m_topLayout->addWidget(m_view, positionFor.view, 0);
m_topLayout->addWidget(m_filterBar, positionFor.filterBar, 0);
- m_topLayout->addWidget(m_statusBar, positionFor.statusBar, 0);
+ if (GeneralSettings::showStatusBar() == GeneralSettings::EnumShowStatusBar::FullWidth) {
+ m_topLayout->addWidget(m_statusBar, positionFor.statusBar, 0);
+ }
+ connect(m_statusBar, &DolphinStatusBar::modeUpdated, this, [this]() {
+ const bool statusBarInLayout = m_topLayout->itemAtPosition(positionFor.statusBar, 0);
+ if (GeneralSettings::showStatusBar() == GeneralSettings::EnumShowStatusBar::FullWidth) {
+ if (!statusBarInLayout) {
+ m_topLayout->addWidget(m_statusBar, positionFor.statusBar, 0);
+ m_statusBar->setUrl(m_view->url());
+ }
+ } else {
+ if (statusBarInLayout) {
+ m_topLayout->removeWidget(m_statusBar);
+ }
+ }
+ updateStatusBarGeometry();
+ });
+ m_statusBar->setHidden(false);
setSearchModeEnabled(isSearchUrl(url));
@@ -200,6 +223,8 @@ DolphinViewContainer::DolphinViewContainer(const QUrl &url, QWidget *parent)
connect(placesModel, &KFilePlacesModel::rowsRemoved, this, &DolphinViewContainer::slotPlacesModelChanged);
connect(this, &DolphinViewContainer::searchModeEnabledChanged, this, &DolphinViewContainer::captionChanged);
+
+ QApplication::instance()->installEventFilter(this);
}
DolphinViewContainer::~DolphinViewContainer()
@@ -614,6 +639,7 @@ void DolphinViewContainer::setFilterBarVisible(bool visible)
m_filterBar->setVisible(true, WithAnimation);
m_filterBar->setFocus();
m_filterBar->selectAll();
+ Q_EMIT showFilterBarChanged(true);
} else {
closeFilterBar();
}
@@ -638,6 +664,7 @@ void DolphinViewContainer::updateStatusBar()
{
m_statusBarTimestamp.start();
m_view->requestStatusBarText();
+ updateStatusBarGeometry();
}
void DolphinViewContainer::slotDirectoryLoadingStarted()
@@ -1043,4 +1070,60 @@ QString DolphinViewContainer::getNearestExistingAncestorOfPath(const QString &pa
return dir.exists() ? dir.path() : QString{};
}
+void DolphinViewContainer::updateStatusBarGeometry()
+{
+ if (!m_statusBar) {
+ return;
+ }
+ if (GeneralSettings::showStatusBar() == GeneralSettings::EnumShowStatusBar::Small) {
+ QRect statusBarRect(preferredSmallStatusBarGeometry());
+ if (view()->layoutDirection() == Qt::RightToLeft) {
+ const int splitterWidth = m_statusBar->clippingAmount();
+ statusBarRect.setLeft(rect().width() - m_statusBar->width() + splitterWidth); // Add clipping amount.
+ }
+ // Move statusbar to bottomLeft, or bottomRight with right-to-left-layout.
+ m_statusBar->setGeometry(statusBarRect);
+ // Add 1 due to how qrect coordinates work.
+ m_view->setStatusBarOffset(m_statusBar->geometry().height() - m_statusBar->clippingAmount() + 1);
+ } else {
+ m_view->setStatusBarOffset(0);
+ }
+}
+
+bool DolphinViewContainer::eventFilter(QObject *object, QEvent *event)
+{
+ if (GeneralSettings::showStatusBar() == GeneralSettings::EnumShowStatusBar::Small && object == m_view) {
+ switch (event->type()) {
+ case QEvent::Resize: {
+ m_statusBar->updateWidthToContent();
+ break;
+ }
+ case QEvent::LayoutRequest: {
+ m_statusBar->updateWidthToContent();
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return false;
+}
+
+QRect DolphinViewContainer::preferredSmallStatusBarGeometry()
+{
+ // Add offset depending if horizontal scrollbar or filterbar is visible.
+ int filterBarHeightOffset = 0;
+ int scrollbarHeightOffset = m_view->horizontalScrollBarHeight();
+
+ if (m_filterBar->isVisible()) {
+ filterBarHeightOffset = m_filterBar->height();
+ }
+
+ // Adjust to clipping, we need to add 1 due to how QRects coordinates work.
+ int clipAdjustment = m_statusBar->clippingAmount() + 1;
+ const int yPos = rect().bottom() - m_statusBar->minimumHeight() - scrollbarHeightOffset - filterBarHeightOffset + clipAdjustment;
+ QRect statusBarRect = rect().adjusted(-clipAdjustment, yPos, 0, 0);
+ return statusBarRect;
+}
+
#include "moc_dolphinviewcontainer.cpp"
diff --git a/src/dolphinviewcontainer.h b/src/dolphinviewcontainer.h
index be28ecdeb..a509bab3d 100644
--- a/src/dolphinviewcontainer.h
+++ b/src/dolphinviewcontainer.h
@@ -33,6 +33,7 @@ class QGridLayout;
class QUrl;
class DolphinSearchBox;
class DolphinStatusBar;
+class KFileItemList;
namespace SelectionMode
{
class TopBar;
@@ -432,6 +433,19 @@ private:
*/
QString getNearestExistingAncestorOfPath(const QString &path) const;
+ /**
+ * Update the geometry of statusbar depending on what mode it is using.
+ */
+ void updateStatusBarGeometry();
+
+ /**
+ * @return Preferred geometry of the small statusbar.
+ */
+ QRect preferredSmallStatusBarGeometry();
+
+protected:
+ bool eventFilter(QObject *object, QEvent *event) override;
+
private:
QGridLayout *m_topLayout;
diff --git a/src/kitemviews/kitemlistview.cpp b/src/kitemviews/kitemlistview.cpp
index 369415f1b..c56785c36 100644
--- a/src/kitemviews/kitemlistview.cpp
+++ b/src/kitemviews/kitemlistview.cpp
@@ -106,6 +106,7 @@ KItemListView::KItemListView(QGraphicsWidget *parent)
, m_header(nullptr)
, m_headerWidget(nullptr)
, m_indicatorAnimation(nullptr)
+ , m_statusBarOffset(0)
, m_dropIndicator()
, m_sizeHintResolver(nullptr)
{
@@ -192,7 +193,7 @@ qreal KItemListView::scrollOffset() const
qreal KItemListView::maximumScrollOffset() const
{
- return m_layouter->maximumScrollOffset();
+ return m_layouter->maximumScrollOffset() + m_statusBarOffset;
}
void KItemListView::setItemOffset(qreal offset)
@@ -554,6 +555,9 @@ void KItemListView::scrollToItem(int index, ViewItemPosition viewItemPosition)
const qreal headerHeight = m_headerWidget->size().height();
viewGeometry.adjust(0, headerHeight, 0, 0);
}
+ if (m_statusBarOffset != 0) {
+ viewGeometry.adjust(0, 0, 0, -m_statusBarOffset);
+ }
QRectF currentRect = itemRect(index);
if (layoutDirection() == Qt::RightToLeft && scrollOrientation() == Qt::Horizontal) {
@@ -829,6 +833,16 @@ void KItemListView::paint(QPainter *painter, const QStyleOptionGraphicsItem *opt
}
}
+void KItemListView::setStatusBarOffset(int offset)
+{
+ if (m_statusBarOffset != offset) {
+ m_statusBarOffset = offset;
+ if (m_layouter) {
+ m_layouter->setStatusBarOffset(offset);
+ }
+ }
+}
+
QVariant KItemListView::itemChange(GraphicsItemChange change, const QVariant &value)
{
if (change == QGraphicsItem::ItemSceneHasChanged && scene()) {
diff --git a/src/kitemviews/kitemlistview.h b/src/kitemviews/kitemlistview.h
index 30ce4d871..7fb3344b4 100644
--- a/src/kitemviews/kitemlistview.h
+++ b/src/kitemviews/kitemlistview.h
@@ -302,6 +302,12 @@ public:
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = nullptr) override;
+ /**
+ * Set the bottom offset for moving the view so that the small overlayed statusbar
+ * won't cover any items by accident.
+ */
+ void setStatusBarOffset(int offset);
+
Q_SIGNALS:
void scrollOrientationChanged(Qt::Orientation current, Qt::Orientation previous);
void scrollOffsetChanged(qreal current, qreal previous);
@@ -776,6 +782,8 @@ private:
QPropertyAnimation *m_indicatorAnimation;
+ int m_statusBarOffset;
+
// When dragging items into the view where the sort-role of the model
// is empty, a visual indicator should be shown during dragging where
// the dropping will happen. This indicator is specified by an index
diff --git a/src/kitemviews/private/kitemlistviewlayouter.cpp b/src/kitemviews/private/kitemlistviewlayouter.cpp
index 99a95d98c..3ed2343a8 100644
--- a/src/kitemviews/private/kitemlistviewlayouter.cpp
+++ b/src/kitemviews/private/kitemlistviewlayouter.cpp
@@ -40,6 +40,7 @@ KItemListViewLayouter::KItemListViewLayouter(KItemListSizeHintResolver *sizeHint
, m_groupHeaderHeight(0)
, m_groupHeaderMargin(0)
, m_itemInfos()
+ , m_statusBarOffset(0)
{
Q_ASSERT(m_sizeHintResolver);
}
@@ -341,6 +342,13 @@ void KItemListViewLayouter::markAsDirty()
m_dirty = true;
}
+void KItemListViewLayouter::setStatusBarOffset(int offset)
+{
+ if (m_statusBarOffset != offset) {
+ m_statusBarOffset = offset;
+ }
+}
+
#ifndef QT_NO_DEBUG
bool KItemListViewLayouter::isDirty()
{
@@ -378,6 +386,7 @@ void KItemListViewLayouter::doLayout()
itemSize.transpose();
itemMargin.transpose();
size.transpose();
+ size.rwidth() -= m_statusBarOffset;
if (grouped) {
// In the horizontal scrolling case all groups are aligned
diff --git a/src/kitemviews/private/kitemlistviewlayouter.h b/src/kitemviews/private/kitemlistviewlayouter.h
index 77d59c947..fed541a4c 100644
--- a/src/kitemviews/private/kitemlistviewlayouter.h
+++ b/src/kitemviews/private/kitemlistviewlayouter.h
@@ -154,6 +154,12 @@ public:
return m_columnCount;
}
+ /**
+ * Set the bottom offset for moving the view so that the small overlayed statusbar
+ * won't cover any items by accident.
+ */
+ void setStatusBarOffset(int offset);
+
#ifndef QT_NO_DEBUG
/**
* @return True if the layouter has been marked as dirty and hence has
@@ -219,6 +225,8 @@ private:
};
QVector<ItemInfo> m_itemInfos;
+ int m_statusBarOffset;
+
friend class KItemListControllerTest;
};
diff --git a/src/settings/dolphin_25.04_update_statusandlocationbarssettings.cpp b/src/settings/dolphin_25.04_update_statusandlocationbarssettings.cpp
new file mode 100644
index 000000000..2188fcb82
--- /dev/null
+++ b/src/settings/dolphin_25.04_update_statusandlocationbarssettings.cpp
@@ -0,0 +1,28 @@
+/*
+ SPDX-FileCopyrightText: 2025 Akseli Lahtinen <[email protected]>
+
+ SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include <KConfigGroup>
+#include <KSharedConfig>
+
+int main()
+{
+ const auto showStatusBar = QStringLiteral("ShowStatusBar");
+ auto config = KSharedConfig::openConfig(QStringLiteral("dolphinrc"));
+
+ KConfigGroup general = config->group(QStringLiteral("General"));
+ if (!general.hasKey(showStatusBar)) {
+ return EXIT_SUCCESS;
+ }
+
+ const auto value = general.readEntry(showStatusBar);
+ if (value == QStringLiteral("true")) {
+ general.writeEntry(showStatusBar, QStringLiteral("Small"));
+ } else if (value == QStringLiteral("false")) {
+ general.writeEntry(showStatusBar, QStringLiteral("Disabled"));
+ }
+
+ return general.sync() ? EXIT_SUCCESS : EXIT_FAILURE;
+}
diff --git a/src/settings/dolphin_generalsettings.kcfg b/src/settings/dolphin_generalsettings.kcfg
index c800eadb8..e950099ec 100644
--- a/src/settings/dolphin_generalsettings.kcfg
+++ b/src/settings/dolphin_generalsettings.kcfg
@@ -117,18 +117,19 @@
<label>Use auto-expanding folders for all view types</label>
<default>false</default>
</entry>
- <entry name="ShowStatusBar" type="Bool">
- <label>Show the statusbar</label>
- <default>true</default>
+ <entry name="ShowStatusBar" type="Enum">
+ <choices>
+ <choice name="Small" />
+ <choice name="FullWidth" />
+ <choice name="Disabled" />
+ </choices>
+ <label>Statusbar</label>
+ <default>0</default>
<emit signal="showStatusBarChanged" />
</entry>
<entry name="ShowZoomSlider" type="Bool">
<label>Show zoom slider in the statusbar</label>
- <default>true</default>
- </entry>
- <entry name="ShowSpaceInfo" type="Bool">
- <label>Show the space information in the statusbar</label>
- <default>true</default>
+ <default>false</default>
</entry>
<entry name="LockPanels" type="Bool">
<label>Lock the layout of the panels</label>
diff --git a/src/settings/dolphin_statusandlocationbarssettings.upd b/src/settings/dolphin_statusandlocationbarssettings.upd
new file mode 100644
index 000000000..d7dd095f2
--- /dev/null
+++ b/src/settings/dolphin_statusandlocationbarssettings.upd
@@ -0,0 +1,9 @@
+#SPDX-FileCopyrightText: 2025 Akseli Lahtinen <[email protected]>
+#SPDX-License-Identifier: GPL-2.0-or-later
+
+#Configuration update for Dolphin
+Version=6
+
+#Convert bool ShowStatusBar to enum ShowStatusBar
+Id=25.04-convert-bool-showstatusbar-to-enum-showstatusbar
+Script=dolphin_25.04_update_statusandlocationbarssettings
diff --git a/src/settings/interface/statusandlocationbarssettingspage.cpp b/src/settings/interface/statusandlocationbarssettingspage.cpp
index 5e0536a6e..14b5c8188 100644
--- a/src/settings/interface/statusandlocationbarssettingspage.cpp
+++ b/src/settings/interface/statusandlocationbarssettingspage.cpp
@@ -14,16 +14,21 @@
#include <QCheckBox>
#include <QFormLayout>
+#include <QButtonGroup>
#include <QRadioButton>
#include <QSpacerItem>
+#include <QStyle>
+#include <QStyleOption>
StatusAndLocationBarsSettingsPage::StatusAndLocationBarsSettingsPage(QWidget *parent, FoldersTabsSettingsPage *foldersPage)
: SettingsPageBase(parent)
, m_editableUrl(nullptr)
, m_showFullPath(nullptr)
- , m_showStatusBar(nullptr)
+ , m_statusBarButtonGroup(nullptr)
+ , m_showStatusBarSmall(nullptr)
+ , m_showStatusBarFullWidth(nullptr)
, m_showZoomSlider(nullptr)
- , m_showSpaceInfo(nullptr)
+ , m_disableStatusBar(nullptr)
{
// We need to update some urls at the Folders & Tabs tab. We get that from foldersPage and set it on a private attribute
// foldersTabsPage. That way, we can modify the necessary stuff from here. Specifically, any changes on locationUpdateInitialViewOptions()
@@ -33,14 +38,30 @@ StatusAndLocationBarsSettingsPage::StatusAndLocationBarsSettingsPage(QWidget *pa
QFormLayout *topLayout = new QFormLayout(this);
// Status bar
- m_showStatusBar = new QCheckBox(i18nc("@option:check", "Show status bar"), this);
+ m_statusBarButtonGroup = new QButtonGroup(this);
+ m_showStatusBarSmall = new QRadioButton(i18nc("@option:radio", "Small"), this);
+ m_showStatusBarFullWidth = new QRadioButton(i18nc("@option:radio", "Full width"), this);
m_showZoomSlider = new QCheckBox(i18nc("@option:check", "Show zoom slider"), this);
- m_showSpaceInfo = new QCheckBox(i18nc("@option:check", "Show space information"), this);
+ m_disableStatusBar = new QRadioButton(i18nc("@option:check", "Disabled"), this);
- topLayout->addRow(i18nc("@title:group", "Status Bar: "), m_showStatusBar);
- topLayout->addRow(QString(), m_showZoomSlider);
- topLayout->addRow(QString(), m_showSpaceInfo);
+ m_statusBarButtonGroup->addButton(m_showStatusBarSmall, GeneralSettings::EnumShowStatusBar::Small);
+ m_statusBarButtonGroup->addButton(m_showStatusBarFullWidth, GeneralSettings::EnumShowStatusBar::FullWidth);
+ m_statusBarButtonGroup->addButton(m_disableStatusBar, GeneralSettings::EnumShowStatusBar::Disabled);
+ topLayout->addRow(i18nc("@title:group", "Status Bar:"), m_showStatusBarSmall);
+ topLayout->addRow(QString(), m_showStatusBarFullWidth);
+
+ // Indent the m_showZoomSlider checkbox under m_showStatusBarFullWidth.
+ QHBoxLayout *zoomSliderLayout = new QHBoxLayout;
+ QStyleOption opt;
+ opt.initFrom(this);
+ zoomSliderLayout->addItem(
+ new QSpacerItem(style()->pixelMetric(QStyle::PM_IndicatorWidth, &opt, this), Dolphin::VERTICAL_SPACER_HEIGHT, QSizePolicy::Fixed, QSizePolicy::Fixed));
+ zoomSliderLayout->addWidget(m_showZoomSlider);
+
+ topLayout->addRow(QString(), zoomSliderLayout);
+
+ topLayout->addRow(QString(), m_disableStatusBar);
topLayout->addItem(new QSpacerItem(0, Dolphin::VERTICAL_SPACER_HEIGHT, QSizePolicy::Fixed, QSizePolicy::Fixed));
// Location bar
@@ -57,10 +78,9 @@ StatusAndLocationBarsSettingsPage::StatusAndLocationBarsSettingsPage(QWidget *pa
connect(m_editableUrl, &QCheckBox::toggled, this, &StatusAndLocationBarsSettingsPage::locationSlotSettingsChanged);
connect(m_showFullPath, &QCheckBox::toggled, this, &StatusAndLocationBarsSettingsPage::locationSlotSettingsChanged);
- connect(m_showStatusBar, &QCheckBox::toggled, this, &StatusAndLocationBarsSettingsPage::changed);
- connect(m_showStatusBar, &QCheckBox::toggled, this, &StatusAndLocationBarsSettingsPage::onShowStatusBarToggled);
+ connect(m_statusBarButtonGroup, &QButtonGroup::idClicked, this, &StatusAndLocationBarsSettingsPage::changed);
+ connect(m_statusBarButtonGroup, &QButtonGroup::idClicked, this, &StatusAndLocationBarsSettingsPage::onShowStatusBarToggled);
connect(m_showZoomSlider, &QCheckBox::toggled, this, &StatusAndLocationBarsSettingsPage::changed);
- connect(m_showSpaceInfo, &QCheckBox::toggled, this, &StatusAndLocationBarsSettingsPage::changed);
}
StatusAndLocationBarsSettingsPage::~StatusAndLocationBarsSettingsPage()
@@ -74,18 +94,16 @@ void StatusAndLocationBarsSettingsPage::applySettings()
settings->setEditableUrl(m_editableUrl->isChecked());
settings->setShowFullPath(m_showFullPath->isChecked());
- settings->setShowStatusBar(m_showStatusBar->isChecked());
+ settings->setShowStatusBar(m_statusBarButtonGroup->checkedId());
settings->setShowZoomSlider(m_showZoomSlider->isChecked());
- settings->setShowSpaceInfo(m_showSpaceInfo->isChecked());
settings->save();
}
void StatusAndLocationBarsSettingsPage::onShowStatusBarToggled()
{
- const bool checked = m_showStatusBar->isChecked();
+ const bool checked = (m_statusBarButtonGroup->checkedId() == GeneralSettings::EnumShowStatusBar::FullWidth);
m_showZoomSlider->setEnabled(checked);
- m_showSpaceInfo->setEnabled(checked);
}
void StatusAndLocationBarsSettingsPage::restoreDefaults()
@@ -118,9 +136,8 @@ void StatusAndLocationBarsSettingsPage::loadSettings()
{
m_editableUrl->setChecked(GeneralSettings::editableUrl());
m_showFullPath->setChecked(GeneralSettings::showFullPath());
- m_showStatusBar->setChecked(GeneralSettings::showStatusBar());
+ m_statusBarButtonGroup->button(GeneralSettings::showStatusBar())->setChecked(true);
m_showZoomSlider->setChecked(GeneralSettings::showZoomSlider());
- m_showSpaceInfo->setChecked(GeneralSettings::showSpaceInfo());
onShowStatusBarToggled();
}
diff --git a/src/settings/interface/statusandlocationbarssettingspage.h b/src/settings/interface/statusandlocationbarssettingspage.h
index c22ff2041..3b8049782 100644
--- a/src/settings/interface/statusandlocationbarssettingspage.h
+++ b/src/settings/interface/statusandlocationbarssettingspage.h
@@ -16,6 +16,7 @@ class QCheckBox;
class QLineEdit;
class QLabel;
class QRadioButton;
+class QButtonGroup;
/**
* @brief Tab page for the 'Behavior' settings of the Dolphin settings dialog.
@@ -47,9 +48,11 @@ private:
QCheckBox *m_editableUrl;
QCheckBox *m_showFullPath;
- QCheckBox *m_showStatusBar;
+ QButtonGroup *m_statusBarButtonGroup;
+ QRadioButton *m_showStatusBarSmall;
+ QRadioButton *m_showStatusBarFullWidth;
QCheckBox *m_showZoomSlider;
- QCheckBox *m_showSpaceInfo;
+ QRadioButton *m_disableStatusBar;
};
#endif
diff --git a/src/statusbar/dolphinstatusbar.cpp b/src/statusbar/dolphinstatusbar.cpp
index 6da4b4ddf..d9ed1076e 100644
--- a/src/statusbar/dolphinstatusbar.cpp
+++ b/src/statusbar/dolphinstatusbar.cpp
@@ -20,6 +20,7 @@
#include <QIcon>
#include <QMenu>
#include <QPainter>
+#include <QPainterPath>
#include <QProgressBar>
#include <QSlider>
#include <QStyleOption>
@@ -136,8 +137,7 @@ DolphinStatusBar::DolphinStatusBar(QWidget *parent)
m_topLayout->addWidget(m_progressTextLabel);
m_topLayout->addWidget(m_progressBar);
- setVisible(GeneralSettings::showStatusBar(), WithoutAnimation);
- setExtensionsVisible(true);
+ readSettings();
setWhatsThis(xi18nc("@info:whatsthis Statusbar",
"<para>This is "
"the <emphasis>Statusbar</emphasis>. It contains three elements "
@@ -203,6 +203,7 @@ void DolphinStatusBar::showProgress(const QString &currentlyRunningTaskTitle, in
}
m_progressTextLabel->setText(currentlyRunningTaskTitle);
+ updateWidthToContent();
}
QString DolphinStatusBar::progressText() const
@@ -240,8 +241,9 @@ QString DolphinStatusBar::defaultText() const
void DolphinStatusBar::setUrl(const QUrl &url)
{
- if (GeneralSettings::showSpaceInfo()) {
+ if (GeneralSettings::showStatusBar() == GeneralSettings::EnumShowStatusBar::FullWidth && m_spaceInfo && m_spaceInfo->url() != url) {
m_spaceInfo->setUrl(url);
+ Q_EMIT urlChanged();
}
}
@@ -264,7 +266,7 @@ int DolphinStatusBar::zoomLevel() const
void DolphinStatusBar::readSettings()
{
- setVisible(GeneralSettings::showStatusBar(), WithAnimation);
+ updateMode();
setExtensionsVisible(true);
}
@@ -273,6 +275,66 @@ void DolphinStatusBar::updateSpaceInfo()
m_spaceInfo->update();
}
+void DolphinStatusBar::updateWidthToContent()
+{
+ if (GeneralSettings::showStatusBar() == GeneralSettings::EnumShowStatusBar::Small) {
+ QStyleOptionSlider opt;
+ opt.initFrom(this);
+ opt.orientation = Qt::Vertical;
+ const QSize labelSize = QFontMetrics(font()).size(Qt::TextSingleLine, m_label->fullText());
+ // Make sure minimum height takes clipping into account.
+ setMinimumHeight(m_label->height() + clippingAmount());
+ const int scrollbarWidth = style()->pixelMetric(QStyle::PM_ScrollBarExtent, &opt, this);
+ const int maximumViewWidth = parentWidget()->width() - scrollbarWidth;
+ if (m_stopButton->isVisible() || m_progressTextLabel->isVisible() || m_progressBar->isVisible()) {
+ // Use maximum width when interactable elements are shown, to keep them
+ // from "jumping around" when user tries to interact with them.
+ setFixedWidth(maximumViewWidth);
+ } else {
+ const int contentWidth = labelSize.width() + 15;
+ setFixedWidth(qMin(contentWidth, maximumViewWidth));
+ }
+ Q_EMIT widthUpdated();
+ } else {
+ setMinimumHeight(0);
+ setFixedWidth(QWIDGETSIZE_MAX);
+ Q_EMIT widthUpdated();
+ }
+}
+
+int DolphinStatusBar::clippingAmount() const
+{
+ QStyleOption opt;
+ opt.initFrom(this);
+ // Add 2 for extra padding due to how QRect coordinates work.
+ const int val = 2 + style()->pixelMetric(QStyle::PM_SplitterWidth, &opt, this) * 2;
+ return val;
+}
+
+void DolphinStatusBar::updateMode()
+{
+ switch (GeneralSettings::showStatusBar()) {
+ case GeneralSettings::EnumShowStatusBar::Small:
+ setEnabled(true);
+ m_spaceInfo->setShown(false);
+ m_zoomSlider->setVisible(false);
+ m_zoomLabel->setVisible(false);
+ setVisible(true, WithAnimation);
+ break;
+ case GeneralSettings::EnumShowStatusBar::FullWidth:
+ setEnabled(true);
+ m_spaceInfo->setShown(true);
+ setVisible(true, WithAnimation);
+ break;
+ case GeneralSettings::EnumShowStatusBar::Disabled:
+ setEnabled(false);
+ setVisible(false, WithoutAnimation);
+ break;
+ }
+ Q_EMIT modeUpdated();
+ updateWidthToContent();
+}
+
void DolphinStatusBar::contextMenuEvent(QContextMenuEvent *event)
{
Q_UNUSED(event)
@@ -283,20 +345,12 @@ void DolphinStatusBar::contextMenuEvent(QContextMenuEvent *event)
showZoomSliderAction->setCheckable(true);
showZoomSliderAction->setChecked(GeneralSettings::showZoomSlider());
- QAction *showSpaceInfoAction = menu.addAction(i18nc("@action:inmenu", "Show Space Information"));
- showSpaceInfoAction->setCheckable(true);
- showSpaceInfoAction->setChecked(GeneralSettings::showSpaceInfo());
-
const QAction *action = menu.exec(event->reason() == QContextMenuEvent::Reason::Mouse ? QCursor::pos() : mapToGlobal(QPoint(width() / 2, height() / 2)));
if (action == showZoomSliderAction) {
const bool visible = showZoomSliderAction->isChecked();
GeneralSettings::setShowZoomSlider(visible);
m_zoomSlider->setVisible(visible);
m_zoomLabel->setVisible(visible);
- } else if (action == showSpaceInfoAction) {
- const bool visible = showSpaceInfoAction->isChecked();
- GeneralSettings::setShowSpaceInfo(visible);
- m_spaceInfo->setShown(visible);
}
updateContentsMargins();
}
@@ -326,12 +380,14 @@ void DolphinStatusBar::updateProgressInfo()
m_progressBar->hide();
setExtensionsVisible(true);
}
+ updateWidthToContent();
}
void DolphinStatusBar::updateLabelText()
{
const QString text = m_text.isEmpty() ? m_defaultText : m_text;
m_label->setText(text);
+ updateWidthToContent();
}
void DolphinStatusBar::updateZoomSliderToolTip(int zoomLevel)
@@ -342,14 +398,11 @@ void DolphinStatusBar::updateZoomSliderToolTip(int zoomLevel)
void DolphinStatusBar::setExtensionsVisible(bool visible)
{
- bool showSpaceInfo = visible;
bool showZoomSlider = visible;
if (visible) {
- showSpaceInfo = GeneralSettings::showSpaceInfo();
- showZoomSlider = GeneralSettings::showZoomSlider();
+ showZoomSlider = GeneralSettings::showZoomSlider() && GeneralSettings::showStatusBar() == GeneralSettings::EnumShowStatusBar::FullWidth;
}
- m_spaceInfo->setShown(showSpaceInfo);
m_zoomSlider->setVisible(showZoomSlider);
m_zoomLabel->setVisible(showZoomSlider);
updateContentsMargins();
@@ -357,12 +410,14 @@ void DolphinStatusBar::setExtensionsVisible(bool visible)
void DolphinStatusBar::updateContentsMargins()
{
- if (GeneralSettings::showSpaceInfo()) {
+ if (GeneralSettings::showStatusBar() == GeneralSettings::EnumShowStatusBar::FullWidth) {
// We reduce the outside margin for the flat button so it visually has the same margin as the status bar text label on the other end of the bar.
m_topLayout->setContentsMargins(6, 0, 2, 0);
} else {
- m_topLayout->setContentsMargins(6, 0, 6, 0);
+ // Add extra margins to toplayout to avoid clipping too early.
+ m_topLayout->setContentsMargins(clippingAmount() * 2, 0, clippingAmount(), clippingAmount());
}
+ setContentsMargins(0, 0, 0, 0);
}
void DolphinStatusBar::paintEvent(QPaintEvent *paintEvent)
@@ -371,7 +426,28 @@ void DolphinStatusBar::paintEvent(QPaintEvent *paintEvent)
QPainter p(this);
QStyleOption opt;
opt.initFrom(this);
- style()->drawPrimitive(QStyle::PE_PanelStatusBar, &opt, &p, this);
+ // Draw statusbar only if there is text.
+ if (GeneralSettings::showStatusBar() == GeneralSettings::EnumShowStatusBar::Small) {
+ if (m_label && !m_label->fullText().isEmpty()) {
+ opt.state = QStyle::State_Sunken;
+ QPainterPath path;
+ // Clip the left and bottom border off.
+ QRect clipRect;
+ if (layoutDirection() == Qt::RightToLeft) {
+ clipRect = QRect(opt.rect.topLeft(), opt.rect.bottomRight()).adjusted(0, 0, -clippingAmount(), -clippingAmount());
+ } else {
+ clipRect = QRect(opt.rect.topLeft(), opt.rect.bottomRight()).adjusted(clippingAmount(), 0, 0, -clippingAmount());
+ }
+ path.addRect(clipRect);
+ p.setClipPath(path);
+ opt.palette.setColor(QPalette::Base, palette().window().color());
+ style()->drawPrimitive(QStyle::PE_Frame, &opt, &p, this);
+ }
+ }
+ // Draw regular statusbar.
+ else {
+ style()->drawPrimitive(QStyle::PE_PanelStatusBar, &opt, &p, this);
+ }
}
int DolphinStatusBar::preferredHeight() const
diff --git a/src/statusbar/dolphinstatusbar.h b/src/statusbar/dolphinstatusbar.h
index a620a0117..b4ddcd95e 100644
--- a/src/statusbar/dolphinstatusbar.h
+++ b/src/statusbar/dolphinstatusbar.h
@@ -39,7 +39,10 @@ public:
QString text() const;
- enum class CancelLoading { Allowed, Disallowed };
+ enum class CancelLoading {
+ Allowed,
+ Disallowed
+ };
/**
* Shows progress for a task on the status bar.
*
@@ -85,6 +88,22 @@ public:
*/
void updateSpaceInfo();
+ /**
+ * Changes the statusbar between disabled, small, and full width
+ * depending on settings enabled.
+ */
+ void updateMode();
+
+ /**
+ * Updates the statusbar width to fit all content.
+ */
+ void updateWidthToContent();
+
+ /**
+ * @return The amount of clipping done to the small statusbar side and bottom.
+ */
+ int clippingAmount() const;
+
public Q_SLOTS:
void setText(const QString &text);
void setUrl(const QUrl &url);
@@ -103,6 +122,21 @@ Q_SIGNALS:
*/
void showMessage(const QString &message, KMessageWidget::MessageType messageType);
+ /**
+ * Emitted when statusbar mode is changed.
+ */
+ void modeUpdated();
+
+ /**
+ * Emitted when statusbar width is updated to fit content.
+ */
+ void widthUpdated();
+
+ /**
+ * Emitted when statusbar url has changed.
+ */
+ void urlChanged();
+
protected:
void contextMenuEvent(QContextMenuEvent *event) override;
void paintEvent(QPaintEvent *paintEvent) override;
diff --git a/src/tests/dolphinmainwindowtest.cpp b/src/tests/dolphinmainwindowtest.cpp
index d7cb763fd..c7d2f4b6d 100644
--- a/src/tests/dolphinmainwindowtest.cpp
+++ b/src/tests/dolphinmainwindowtest.cpp
@@ -9,6 +9,7 @@
#include "dolphintabpage.h"
#include "dolphintabwidget.h"
#include "dolphinviewcontainer.h"
+#include "dolphin_generalsettings.h"
#include "kitemviews/kfileitemmodel.h"
#include "kitemviews/kfileitemmodelrolesupdater.h"
#include "kitemviews/kitemlistcontainer.h"
@@ -75,6 +76,11 @@ private:
void DolphinMainWindowTest::initTestCase()
{
QStandardPaths::setTestModeEnabled(true);
+ // Use fullWidth statusbar during testing, to test out most of the features.
+ GeneralSettings *settings = GeneralSettings::self();
+ settings->setShowStatusBar(GeneralSettings::EnumShowStatusBar::FullWidth);
+ settings->setShowZoomSlider(true);
+ settings->save();
}
void DolphinMainWindowTest::init()
diff --git a/src/views/dolphinview.cpp b/src/views/dolphinview.cpp
index a18f53769..fc4f5e2df 100644
--- a/src/views/dolphinview.cpp
+++ b/src/views/dolphinview.cpp
@@ -2285,6 +2285,22 @@ bool DolphinView::isFolderWritable() const
return m_isFolderWritable;
}
+int DolphinView::horizontalScrollBarHeight() const
+{
+ if (m_container && m_container->horizontalScrollBar() && m_container->horizontalScrollBar()->isVisible()) {
+ return m_container->horizontalScrollBar()->height();
+ }
+ return 0;
+}
+
+void DolphinView::setStatusBarOffset(int offset)
+{
+ KItemListView *view = m_container->controller()->view();
+ if (view) {
+ view->setStatusBarOffset(offset);
+ }
+}
+
QUrl DolphinView::viewPropertiesUrl() const
{
if (m_viewPropertiesContext.isEmpty()) {
diff --git a/src/views/dolphinview.h b/src/views/dolphinview.h
index d1667334e..de4bc1af2 100644
--- a/src/views/dolphinview.h
+++ b/src/views/dolphinview.h
@@ -357,6 +357,18 @@ public:
*/
bool isFolderWritable() const;
+ /**
+ * @returns the height of the scrollbar at the bottom of the view or zero if no such scroll bar is visible.
+ */
+ int horizontalScrollBarHeight() const;
+
+ /**
+ * Set the offset for any view items that small statusbar would otherwise
+ * cover. For example, in compact view this is used to make sure no
+ * item is covered by statusbar.
+ */
+ void setStatusBarOffset(int offset);
+
public Q_SLOTS:
void reload();