┌   ┐
54
└   ┘

summaryrefslogtreecommitdiff
path: root/src/dolphinnavigatorswidgetaction.cpp
diff options
context:
space:
mode:
authorFelix Ernst <[email protected]>2020-09-20 18:53:59 +0200
committerElvis Angelaccio <[email protected]>2020-11-09 23:49:07 +0100
commit37327c9b0aae112c5890703cba1f0157043007e0 (patch)
tree5cda9876f310a258b95226bc0d9681acc665f98e /src/dolphinnavigatorswidgetaction.cpp
parent6151a7aec0516570926cb1d15da48936e38e6765 (diff)
Make UrlNavigators in the toolbar the only option
The UrlNavigators will be automatically added to the toolbar. The Sort By action is removed from the default toolbar to make space. Remove all options to have UrlNavigators outside the toolbar and remove those code paths. Make it so the new NavigatorsWidgetAction contains two UrlNavigators when in split view mode. Spacing was also added to align these UrlNavigators with the ViewContainers when enough space is available. Force the toolbar to be either at the top or bottom of the window. Set a sane sizeHint for DolphinUrlNavigator. It would be better to do this in KUrlNavigator in the future. This commit also contains a changes which should be moved to a separate merge requests before this gets merged: - Add an expansion animation when split view is enabled by the user
Diffstat (limited to 'src/dolphinnavigatorswidgetaction.cpp')
-rw-r--r--src/dolphinnavigatorswidgetaction.cpp243
1 files changed, 243 insertions, 0 deletions
diff --git a/src/dolphinnavigatorswidgetaction.cpp b/src/dolphinnavigatorswidgetaction.cpp
new file mode 100644
index 000000000..bd2985d47
--- /dev/null
+++ b/src/dolphinnavigatorswidgetaction.cpp
@@ -0,0 +1,243 @@
+/*
+ This file is part of the KDE project
+ SPDX-FileCopyrightText: 2020 Felix Ernst <[email protected]>
+
+ SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
+*/
+
+#include "dolphinnavigatorswidgetaction.h"
+
+#include "trash/dolphintrash.h"
+
+#include <KLocalizedString>
+#include <KXMLGUIFactory>
+#include <KXmlGuiWindow>
+
+#include <QDomDocument>
+#include <QHBoxLayout>
+#include <QPushButton>
+#include <QSplitter>
+
+DolphinNavigatorsWidgetAction::DolphinNavigatorsWidgetAction(QWidget *parent) :
+ QWidgetAction{parent},
+ m_splitter{new QSplitter(Qt::Horizontal)},
+ m_adjustSpacingTimer{new QTimer(this)},
+ m_globalXOfPrimary{-1},
+ m_widthOfPrimary{-1},
+ m_globalXOfSecondary{-1},
+ m_widthOfSecondary{-1}
+{
+ setText(i18nc("@action:inmenu", "Url navigator"));
+
+ m_splitter->setChildrenCollapsible(false);
+ setDefaultWidget(m_splitter.get());
+
+ m_splitter->addWidget(createNavigatorWidget(Primary));
+
+ m_adjustSpacingTimer->setInterval(100);
+ m_adjustSpacingTimer->setSingleShot(true);
+ connect(m_adjustSpacingTimer.get(), &QTimer::timeout,
+ this, &DolphinNavigatorsWidgetAction::adjustSpacing);
+}
+
+bool DolphinNavigatorsWidgetAction::addToToolbarAndSave(KXmlGuiWindow *mainWindow)
+{
+ const QString rawXml = KXMLGUIFactory::readConfigFile(mainWindow->xmlFile());
+ QDomDocument domDocument;
+ if (rawXml.isEmpty() || !domDocument.setContent(rawXml) || domDocument.isNull()) {
+ return false;
+ }
+ QDomNode toolbar = domDocument.elementsByTagName(QStringLiteral("ToolBar")).at(0);
+ if (toolbar.isNull()) {
+ return false;
+ }
+
+ QDomElement urlNavigatorElement = domDocument.createElement(QStringLiteral("Action"));
+ urlNavigatorElement.setAttribute(QStringLiteral("name"), QStringLiteral("url_navigators"));
+
+ QDomNode position = toolbar.lastChildElement(QStringLiteral("Spacer"));
+ if (position.isNull()) {
+ toolbar.appendChild(urlNavigatorElement);
+ } else {
+ toolbar.replaceChild(urlNavigatorElement, position);
+ }
+
+ KXMLGUIFactory::saveConfigFile(domDocument, mainWindow->xmlFile());
+ mainWindow->reloadXML();
+ mainWindow->createGUI();
+ return true;
+}
+
+void DolphinNavigatorsWidgetAction::createSecondaryUrlNavigator()
+{
+ Q_ASSERT(m_splitter->count() == 1);
+ m_splitter->addWidget(createNavigatorWidget(Secondary));
+ Q_ASSERT(m_splitter->count() == 2);
+}
+
+void DolphinNavigatorsWidgetAction::followViewContainerGeometry(
+ int globalXOfPrimary, int widthOfPrimary)
+{
+ followViewContainersGeometry(globalXOfPrimary, widthOfPrimary, -1, -1);
+}
+
+void DolphinNavigatorsWidgetAction::followViewContainersGeometry(
+ int globalXOfPrimary, int widthOfPrimary,
+ int globalXOfSecondary, int widthOfSecondary)
+{
+ m_globalXOfSplitter = m_splitter->mapToGlobal(QPoint(0,0)).x();
+ m_globalXOfPrimary = globalXOfPrimary;
+ m_widthOfPrimary = widthOfPrimary;
+ m_globalXOfSecondary = globalXOfSecondary;
+ m_widthOfSecondary = widthOfSecondary;
+ adjustSpacing();
+}
+
+DolphinUrlNavigator* DolphinNavigatorsWidgetAction::primaryUrlNavigator() const
+{
+ Q_ASSERT(m_splitter);
+ return static_cast<DolphinUrlNavigator *>(m_splitter->widget(0)->findChild<KUrlNavigator *>());
+}
+
+DolphinUrlNavigator* DolphinNavigatorsWidgetAction::secondaryUrlNavigator() const
+{
+ Q_ASSERT(m_splitter);
+ if (m_splitter->count() < 2) {
+ return nullptr;
+ }
+ return static_cast<DolphinUrlNavigator *>(m_splitter->widget(1)->findChild<KUrlNavigator *>());
+}
+
+void DolphinNavigatorsWidgetAction::setSecondaryNavigatorVisible(bool visible)
+{
+ if (visible) {
+ Q_ASSERT(m_splitter->count() == 2);
+ m_splitter->widget(1)->setVisible(true);
+ } else if (m_splitter->count() > 1) {
+ m_splitter->widget(1)->setVisible(false);
+ // Fix an unlikely event of wrong trash button visibility.
+ emptyTrashButton(Secondary)->setVisible(false);
+ }
+}
+
+void DolphinNavigatorsWidgetAction::adjustSpacing()
+{
+ const int widthOfSplitterPrimary = m_globalXOfPrimary + m_widthOfPrimary - m_globalXOfSplitter;
+ const QList<int> splitterSizes = {widthOfSplitterPrimary,
+ m_splitter->width() - widthOfSplitterPrimary};
+ m_splitter->setSizes(splitterSizes);
+
+ // primary side of m_splitter
+ int leadingSpacing = m_globalXOfPrimary - m_globalXOfSplitter;
+ if (leadingSpacing < 0) {
+ leadingSpacing = 0;
+ }
+ int trailingSpacing = (m_globalXOfSplitter + m_splitter->width())
+ - (m_globalXOfPrimary + m_widthOfPrimary);
+ if (trailingSpacing < 0 || emptyTrashButton(Primary)->isVisible()) {
+ trailingSpacing = 0;
+ }
+ const int widthLeftForUrlNavigator = m_splitter->widget(0)->width() - leadingSpacing - trailingSpacing;
+ const int widthNeededForUrlNavigator = primaryUrlNavigator()->sizeHint().width() - widthLeftForUrlNavigator;
+ if (widthNeededForUrlNavigator > 0) {
+ trailingSpacing -= widthNeededForUrlNavigator;
+ if (trailingSpacing < 0) {
+ leadingSpacing += trailingSpacing;
+ trailingSpacing = 0;
+ }
+ if (leadingSpacing < 0) {
+ leadingSpacing = 0;
+ }
+ }
+ spacing(Primary, Leading)->setMinimumWidth(leadingSpacing);
+ spacing(Primary, Trailing)->setFixedWidth(trailingSpacing);
+
+ // secondary side of m_splitter
+ if (m_globalXOfSecondary == -1) {
+ Q_ASSERT(m_widthOfSecondary == -1);
+ return;
+ }
+ spacing(Primary, Trailing)->setFixedWidth(0);
+
+ trailingSpacing = (m_globalXOfSplitter + m_splitter->width())
+ - (m_globalXOfSecondary + m_widthOfSecondary);
+ if (trailingSpacing < 0 || emptyTrashButton(Secondary)->isVisible()) {
+ trailingSpacing = 0;
+ } else {
+ const int widthLeftForUrlNavigator2 = m_splitter->widget(1)->width() - trailingSpacing;
+ const int widthNeededForUrlNavigator2 = secondaryUrlNavigator()->sizeHint().width() - widthLeftForUrlNavigator2;
+ if (widthNeededForUrlNavigator2 > 0) {
+ trailingSpacing -= widthNeededForUrlNavigator2;
+ if (trailingSpacing < 0) {
+ trailingSpacing = 0;
+ }
+ }
+ }
+ spacing(Secondary, Trailing)->setMinimumWidth(trailingSpacing);
+}
+
+QWidget *DolphinNavigatorsWidgetAction::createNavigatorWidget(Side side) const
+{
+ auto navigatorWidget = new QWidget(m_splitter.get());
+ auto layout = new QHBoxLayout{navigatorWidget};
+ layout->setSpacing(0);
+ layout->setContentsMargins(0, 0, 0, 0);
+ if (side == Primary) {
+ auto leadingSpacing = new QWidget{navigatorWidget};
+ layout->addWidget(leadingSpacing);
+ }
+ auto urlNavigator = new DolphinUrlNavigator(navigatorWidget);
+ layout->addWidget(urlNavigator);
+
+ auto emptyTrashButton = newEmptyTrashButton(urlNavigator, navigatorWidget);
+ layout->addWidget(emptyTrashButton);
+
+ connect(urlNavigator, &KUrlNavigator::urlChanged, [this]() {
+ // We have to wait for DolphinUrlNavigator::sizeHint() to update which
+ // happens a little bit later than when urlChanged is emitted.
+ this->m_adjustSpacingTimer->start();
+ });
+
+ auto trailingSpacing = new QWidget{navigatorWidget};
+ layout->addWidget(trailingSpacing);
+ return navigatorWidget;
+}
+
+QPushButton * DolphinNavigatorsWidgetAction::emptyTrashButton(DolphinNavigatorsWidgetAction::Side side)
+{
+ int sideIndex = (side == Primary ? 0 : 1);
+ if (side == Primary) {
+ return static_cast<QPushButton *>(m_splitter->widget(sideIndex)->layout()->itemAt(2)->widget());
+ }
+ return static_cast<QPushButton *>(m_splitter->widget(sideIndex)->layout()->itemAt(1)->widget());
+}
+
+QPushButton *DolphinNavigatorsWidgetAction::newEmptyTrashButton(const DolphinUrlNavigator *urlNavigator, QWidget *parent) const
+{
+ auto emptyTrashButton = new QPushButton(QIcon::fromTheme(QStringLiteral("user-trash")),
+ i18nc("@action:button", "Empty Trash"), parent);
+ emptyTrashButton->setFlat(true);
+ connect(emptyTrashButton, &QPushButton::clicked,
+ this, [parent]() { Trash::empty(parent); });
+ connect(&Trash::instance(), &Trash::emptinessChanged,
+ emptyTrashButton, &QPushButton::setDisabled);
+ emptyTrashButton->hide();
+ connect(urlNavigator, &KUrlNavigator::urlChanged, [emptyTrashButton, urlNavigator]() {
+ emptyTrashButton->setVisible(urlNavigator->locationUrl().scheme() == QLatin1String("trash"));
+ });
+ emptyTrashButton->setDisabled(Trash::isEmpty());
+ return emptyTrashButton;
+}
+
+QWidget *DolphinNavigatorsWidgetAction::spacing(Side side, Position position) const
+{
+ int sideIndex = (side == Primary ? 0 : 1);
+ if (position == Leading) {
+ Q_ASSERT(side == Primary); // The secondary side of the splitter has no leading spacing.
+ return m_splitter->widget(sideIndex)->layout()->itemAt(0)->widget();
+ }
+ if (side == Primary) {
+ return m_splitter->widget(sideIndex)->layout()->itemAt(3)->widget();
+ }
+ return m_splitter->widget(sideIndex)->layout()->itemAt(2)->widget();
+}