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
This commit is contained in:
Felix Ernst 2020-09-20 18:53:59 +02:00 committed by Elvis Angelaccio
parent 6151a7aec0
commit 37327c9b0a
18 changed files with 747 additions and 485 deletions

View file

@ -203,6 +203,7 @@ set(dolphinstatic_SRCS
dolphinmainwindow.cpp
dolphinviewcontainer.cpp
dolphincontextmenu.cpp
dolphinnavigatorswidgetaction.cpp
dolphintabbar.cpp
dolphinplacesmodelsingleton.cpp
dolphinrecenttabsmenu.cpp
@ -249,7 +250,6 @@ set(dolphinstatic_SRCS
statusbar/mountpointobservercache.cpp
statusbar/spaceinfoobserver.cpp
statusbar/statusbarspaceinfo.cpp
views/dolphinurlnavigatorwidgetaction.cpp
views/zoomlevelinfo.cpp
dolphindebug.cpp
global.cpp

View file

@ -31,7 +31,7 @@
#include "views/draganddrophelper.h"
#include "views/viewproperties.h"
#include "views/dolphinnewfilemenuobserver.h"
#include "views/dolphinurlnavigatorwidgetaction.h"
#include "dolphinnavigatorswidgetaction.h"
#include "dolphin_generalsettings.h"
#include <KActionCollection>
@ -49,7 +49,6 @@
#include <KJobWidgets>
#include <KLocalizedString>
#include <KMessageBox>
#include <KMessageWidget>
#include <KNS3/KMoreToolsMenuFactory>
#include <KProtocolInfo>
#include <KProtocolManager>
@ -107,7 +106,8 @@ DolphinMainWindow::DolphinMainWindow() :
m_placesPanel(nullptr),
m_tearDownFromPlacesRequested(false),
m_backAction(nullptr),
m_forwardAction(nullptr)
m_forwardAction(nullptr),
m_updateHistoryConnection{}
{
Q_INIT_RESOURCE(dolphin);
@ -142,7 +142,12 @@ DolphinMainWindow::DolphinMainWindow() :
setAcceptDrops(true);
m_tabWidget = new DolphinTabWidget(this);
auto *navigatorsWidgetAction = new DolphinNavigatorsWidgetAction(this);
navigatorsWidgetAction->setText(i18nc(
"@action:inmenu When split view is enabled there are two otherwise one.",
"Url Navigator(s)"));
actionCollection()->addAction(QStringLiteral("url_navigators"), navigatorsWidgetAction);
m_tabWidget = new DolphinTabWidget(navigatorsWidgetAction, this);
m_tabWidget->setObjectName("tabWidget");
connect(m_tabWidget, &DolphinTabWidget::activeViewChanged,
this, &DolphinMainWindow::activeViewChanged);
@ -167,6 +172,11 @@ DolphinMainWindow::DolphinMainWindow() :
setupGUI(Keys | Save | Create | ToolBar);
stateChanged(QStringLiteral("new_file"));
toolBar()->setAllowedAreas(Qt::TopToolBarArea | Qt::BottomToolBarArea);
toolBar()->setFloatable(false);
if (!toolBar()->actions().contains(navigatorsWidgetAction)) {
navigatorsWidgetAction->addToToolbarAndSave(this);
}
QClipboard* clipboard = QApplication::clipboard();
connect(clipboard, &QClipboard::dataChanged,
this, &DolphinMainWindow::updatePasteAction);
@ -843,64 +853,6 @@ void DolphinMainWindow::showFilterBar()
m_activeViewContainer->setFilterBarVisible(true);
}
void DolphinMainWindow::toggleLocationInToolbar()
{
// collect needed variables
QAction *locationInToolbarAction = actionCollection()->action(QStringLiteral("location_in_toolbar"));
const bool locationInToolbar = locationInToolbarAction->isChecked();
auto viewContainers = this->viewContainers();
auto urlNavigatorWidgetAction = static_cast<DolphinUrlNavigatorWidgetAction *>
(actionCollection()->action(QStringLiteral("url_navigator")));
const bool isEditable = m_activeViewContainer->urlNavigator()->isUrlEditable();
const QLineEdit *lineEdit = m_activeViewContainer->urlNavigator()->editor()->lineEdit();
const bool hasFocus = lineEdit->hasFocus();
const int cursorPosition = lineEdit->cursorPosition();
const int selectionStart = lineEdit->selectionStart();
const int selectionLength = lineEdit->selectionLength();
if (locationInToolbar && !toolBar()->actions().contains(urlNavigatorWidgetAction)) {
// There is no UrlNavigator on the toolbar. Try to fix it. Otherwise show an error.
if (!urlNavigatorWidgetAction->addToToolbarAndSave(this)) {
QAction *configureToolbars = actionCollection()->action(KStandardAction::name(KStandardAction::ConfigureToolbars));
KMessageWidget *messageWidget = m_activeViewContainer->showMessage(
xi18nc("@info 2 is the visible text on a button just below the message",
"The location could not be moved onto the toolbar because there is currently "
"no \"%1\" item on the toolbar. Select <interface>%2</interface> and add the "
"\"%1\" item. Then this will work.", urlNavigatorWidgetAction->iconText(),
configureToolbars->iconText()), DolphinViewContainer::Information);
messageWidget->addAction(configureToolbars);
messageWidget->addAction(locationInToolbarAction);
locationInToolbarAction->setChecked(false);
return;
}
}
// do the switching
GeneralSettings::setLocationInToolbar(locationInToolbar);
if (locationInToolbar) {
for (const auto viewContainer : viewContainers) {
viewContainer->disconnectUrlNavigator();
}
m_activeViewContainer->connectUrlNavigator(urlNavigatorWidgetAction->urlNavigator());
} else {
m_activeViewContainer->disconnectUrlNavigator();
for (const auto viewContainer : viewContainers) {
viewContainer->connectToInternalUrlNavigator();
}
}
urlNavigatorWidgetAction->setUrlNavigatorVisible(locationInToolbar);
m_activeViewContainer->urlNavigator()->setUrlEditable(isEditable);
if (hasFocus) { // the rest of this method is unneeded perfectionism
m_activeViewContainer->urlNavigator()->editor()->lineEdit()->setText(lineEdit->text());
m_activeViewContainer->urlNavigator()->editor()->lineEdit()->setFocus();
m_activeViewContainer->urlNavigator()->editor()->lineEdit()->setCursorPosition(cursorPosition);
if (selectionStart != -1) {
m_activeViewContainer->urlNavigator()->editor()->lineEdit()->setSelection(selectionStart, selectionLength);
}
}
}
void DolphinMainWindow::toggleEditLocation()
{
clearStatusBar();
@ -1314,9 +1266,11 @@ void DolphinMainWindow::activeViewChanged(DolphinViewContainer* viewContainer)
// view and url navigator) and main window.
oldViewContainer->disconnect(this);
oldViewContainer->view()->disconnect(this);
oldViewContainer->urlNavigator()->disconnect(this);
if (GeneralSettings::locationInToolbar()) {
oldViewContainer->disconnectUrlNavigator();
auto navigators = static_cast<DolphinNavigatorsWidgetAction *>
(actionCollection()->action(QStringLiteral("url_navigators")));
navigators->primaryUrlNavigator()->disconnect(this);
if (auto secondaryUrlNavigator = navigators->secondaryUrlNavigator()) {
secondaryUrlNavigator->disconnect(this);
}
// except the requestItemInfo so that on hover the information panel can still be updated
@ -1324,10 +1278,6 @@ void DolphinMainWindow::activeViewChanged(DolphinViewContainer* viewContainer)
this, &DolphinMainWindow::requestItemInfo);
}
if (GeneralSettings::locationInToolbar()) {
viewContainer->connectUrlNavigator(static_cast<DolphinUrlNavigatorWidgetAction *>
(actionCollection()->action(QStringLiteral("url_navigator")))->urlNavigator());
}
connectViewSignals(viewContainer);
m_actionHandler->setCurrentView(viewContainer->view());
@ -1559,16 +1509,6 @@ void DolphinMainWindow::setupActions()
stop->setIcon(QIcon::fromTheme(QStringLiteral("process-stop")));
connect(stop, &QAction::triggered, this, &DolphinMainWindow::stopLoading);
KToggleAction* locationInToolbar = actionCollection()->add<KToggleAction>(QStringLiteral("location_in_toolbar"));
locationInToolbar->setText(i18nc("@action:inmenu Navigation Bar", "Location in Toolbar"));
locationInToolbar->setWhatsThis(xi18nc("@info:whatsthis",
"This toggles between showing the <emphasis>path</emphasis> in the "
"<emphasis>Location Bar</emphasis> and in the <emphasis>Toolbar</emphasis>."));
actionCollection()->setDefaultShortcut(locationInToolbar, Qt::Key_F12);
locationInToolbar->setChecked(GeneralSettings::locationInToolbar());
connect(locationInToolbar, &KToggleAction::triggered, this, &DolphinMainWindow::toggleLocationInToolbar);
DolphinUrlNavigator::addToContextMenu(locationInToolbar);
KToggleAction* editableLocation = actionCollection()->add<KToggleAction>(QStringLiteral("editable_location"));
editableLocation->setText(i18nc("@action:inmenu Navigation Bar", "Editable Location"));
editableLocation->setWhatsThis(xi18nc("@info:whatsthis",
@ -1770,12 +1710,6 @@ void DolphinMainWindow::setupActions()
connect(activatePrevTab, &QAction::triggered, m_tabWidget, &DolphinTabWidget::activatePrevTab);
actionCollection()->setDefaultShortcuts(activatePrevTab, prevTabKeys);
auto *urlNavigatorWidgetAction = new DolphinUrlNavigatorWidgetAction(this);
urlNavigatorWidgetAction->setText(i18nc("@action:inmenu auto-hide: "
"Depending on the settings this Widget is blank/invisible.",
"Url Navigator (auto-hide)"));
actionCollection()->addAction(QStringLiteral("url_navigator"), urlNavigatorWidgetAction);
// for context menu
QAction* showTarget = actionCollection()->addAction(QStringLiteral("show_target"));
showTarget->setText(i18nc("@action:inmenu", "Show Target"));
@ -2107,10 +2041,6 @@ void DolphinMainWindow::updateViewActions()
showFilterBarAction->setChecked(m_activeViewContainer->isFilterBarVisible());
updateSplitAction();
QAction* editableLocactionAction = actionCollection()->action(QStringLiteral("editable_location"));
const KUrlNavigator* urlNavigator = m_activeViewContainer->urlNavigator();
editableLocactionAction->setChecked(urlNavigator->isUrlEditable());
}
void DolphinMainWindow::updateGoActions()
@ -2246,15 +2176,24 @@ void DolphinMainWindow::connectViewSignals(DolphinViewContainer* container)
connect(view, &DolphinView::goUpRequested,
this, &DolphinMainWindow::goUp);
const KUrlNavigator* navigator = container->urlNavigator();
auto navigators = static_cast<DolphinNavigatorsWidgetAction *>
(actionCollection()->action(QStringLiteral("url_navigators")));
KUrlNavigator *navigator = m_tabWidget->currentTabPage()->primaryViewActive() ?
navigators->primaryUrlNavigator() :
navigators->secondaryUrlNavigator();
connect(navigator, &KUrlNavigator::urlChanged,
this, &DolphinMainWindow::changeUrl);
QAction* editableLocactionAction = actionCollection()->action(QStringLiteral("editable_location"));
editableLocactionAction->setChecked(navigator->isUrlEditable());
connect(navigator, &KUrlNavigator::editableStateChanged,
this, &DolphinMainWindow::slotEditableStateChanged);
connect(navigator, &KUrlNavigator::tabRequested,
this, &DolphinMainWindow::openNewTabAfterLastTab);
connect(container->urlNavigatorInternalWithHistory(), &KUrlNavigator::historyChanged,
disconnect(m_updateHistoryConnection);
m_updateHistoryConnection = connect(
container->urlNavigatorInternalWithHistory(), &KUrlNavigator::historyChanged,
this, &DolphinMainWindow::updateHistory);
}

View file

@ -69,16 +69,9 @@ public:
/**
* Returns the active view containers of all tabs.
* @see activeViewContainer()
* Use viewContainers() to also include the inactive ones.
*/
QVector<DolphinViewContainer *> activeViewContainers() const;
/**
* Returns all view containers.
*/
QVector<DolphinViewContainer *> viewContainers() const;
/**
* Opens each directory in \p dirs in a separate tab. If \a splitView is set,
* 2 directories are collected within one tab.
@ -312,12 +305,6 @@ private slots:
void showFilterBar();
/**
* Toggle between either using an UrlNavigator in the toolbar or the
* ones in the location bar for navigating.
*/
void toggleLocationInToolbar();
/**
* Toggles between edit and browse mode of the navigation bar.
*/
@ -662,6 +649,9 @@ private:
KToolBarPopupAction* m_backAction;
KToolBarPopupAction* m_forwardAction;
/** Makes sure that only one object is ever connected to the history. */
QMetaObject::Connection m_updateHistoryConnection;
QMenu m_searchTools;
};

View file

@ -0,0 +1,243 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 2020 Felix Ernst <fe.a.ernst@gmail.com>
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();
}

View file

@ -0,0 +1,149 @@
/*
This file is part of the KDE project
SPDX-FileCopyrightText: 2020 Felix Ernst <fe.a.ernst@gmail.com>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#ifndef DOLPHINNAVIGATORSWIDGETACTION_H
#define DOLPHINNAVIGATORSWIDGETACTION_H
#include "dolphinurlnavigator.h"
#include <QSplitter>
#include <QTimer>
#include <QWidgetAction>
#include <memory>
class KXmlGuiWindow;
class QPushButton;
/**
* @brief QWidgetAction that allows to use DolphinUrlNavigators in a toolbar.
*
* This class is mainly a container that manages up to two DolphinUrlNavigator objects so they
* can be added to a toolbar. It also deals with alignment.
*
* The structure of the defaultWidget() of this QWidgetAction is as follows:
* - A QSplitter manages up to two sides which each correspond to one DolphinViewContainer.
* The secondary side only exists for split view and is created by
* createSecondaryUrlNavigator() when necessary.
* - Each side is a QWidget which I call NavigatorWidget with a QHBoxLayout.
* - Each NavigatorWidget consists an UrlNavigator, an emptyTrashButton and spacing.
* - Only the primary navigatorWidget has leading spacing. Both have trailing spacing.
* The spacing is there to align the UrlNavigator with its DolphinViewContainer.
*/
class DolphinNavigatorsWidgetAction : public QWidgetAction
{
Q_OBJECT
/**
* In Left-to-right languages the Primary side will be the left one.
*/
enum Side {
Primary,
Secondary
};
public:
DolphinNavigatorsWidgetAction(QWidget *parent = nullptr);
/**
* Adds this action to the mainWindow's toolbar and saves the change
* in the users ui configuration file.
* @return true if successful. Otherwise false.
*/
bool addToToolbarAndSave(KXmlGuiWindow *mainWindow);
/**
* Different to the primary UrlNavigator, the secondary UrlNavigator is only created on-demand.
*/
void createSecondaryUrlNavigator();
/**
* Notify the primary UrlNavigator of changes in geometry of the ViewContainer it tries to be
* aligned with. Only call this method if there is no secondary UrlNavigator.
*/
void followViewContainerGeometry(int globalXOfPrimary, int widthOfPrimary);
/**
* Notify this widget of changes in geometry of the ViewContainers it tries to be
* aligned with.
*/
void followViewContainersGeometry(int globalXOfPrimary, int widthOfPrimary,
int globalXOfSecondary, int widthOfSecondary);
/**
* @return the primary UrlNavigator.
*/
DolphinUrlNavigator *primaryUrlNavigator() const;
/**
* @return the secondary UrlNavigator and nullptr if it doesn't exist.
*/
DolphinUrlNavigator *secondaryUrlNavigator() const;
/**
* Change the visibility of the secondary UrlNavigator including spacing.
* @param visible Setting this to false will completely hide the secondary side of this
* WidgetAction's QSplitter making the QSplitter effectively disappear.
*/
void setSecondaryNavigatorVisible(bool visible);
protected:
/**
* Adjusts the width of the spacings used to align the UrlNavigators with ViewContainers.
* This can only work nicely if up-to-date geometry of ViewContainers is cached so
* followViewContainersGeometry() has to have been called at least once before.
*/
void adjustSpacing();
/**
* Used to create the navigatorWidgets for both sides of the QSplitter.
*/
QWidget *createNavigatorWidget(Side side) const;
/**
* Used to retrieve the emptyTrashButtons for the navigatorWidgets on both sides.
*/
QPushButton *emptyTrashButton(Side side);
/**
* Creates a new empty trash button.
* @param urlNavigator Only when this UrlNavigator shows the trash directory
* will the the button be visible.
* @param parent Aside from the usual QObject deletion mechanisms,
* this parameter influences the positioning of dialog windows
* pertaining to this trash button.
*/
QPushButton *newEmptyTrashButton(const DolphinUrlNavigator *urlNavigator, QWidget *parent) const;
enum Position {
Leading,
Trailing
};
/**
* Used to retrieve both the leading and trailing spacing for the navigatorWidgets
* on both sides. A secondary leading spacing does not exist.
*/
QWidget *spacing(Side side, Position position) const;
/**
* The defaultWidget() of this QWidgetAction.
*/
std::unique_ptr<QSplitter> m_splitter;
/**
* adjustSpacing() has to be called slightly later than when urlChanged is emitted.
* This timer bridges that time.
*/
std::unique_ptr<QTimer> m_adjustSpacingTimer;
// cached values
int m_globalXOfSplitter;
int m_globalXOfPrimary;
int m_widthOfPrimary;
int m_globalXOfSecondary;
int m_widthOfSecondary;
};
#endif // DOLPHINNAVIGATORSWIDGETACTION_H

View file

@ -9,6 +9,7 @@
#include "dolphin_generalsettings.h"
#include "dolphinviewcontainer.h"
#include <QPropertyAnimation>
#include <QSplitter>
#include <QVBoxLayout>
@ -24,6 +25,8 @@ DolphinTabPage::DolphinTabPage(const QUrl &primaryUrl, const QUrl &secondaryUrl,
m_splitter = new QSplitter(Qt::Horizontal, this);
m_splitter->setChildrenCollapsible(false);
connect(m_splitter, &QSplitter::splitterMoved,
this, &DolphinTabPage::splitterMoved);
layout->addWidget(m_splitter);
// Create a new primary view
@ -34,6 +37,7 @@ DolphinTabPage::DolphinTabPage(const QUrl &primaryUrl, const QUrl &secondaryUrl,
this, &DolphinTabPage::slotViewUrlRedirection);
m_splitter->addWidget(m_primaryViewContainer);
m_primaryViewContainer->installEventFilter(this);
m_primaryViewContainer->show();
if (secondaryUrl.isValid() || GeneralSettings::splitView()) {
@ -43,6 +47,7 @@ DolphinTabPage::DolphinTabPage(const QUrl &primaryUrl, const QUrl &secondaryUrl,
const QUrl& url = secondaryUrl.isValid() ? secondaryUrl : primaryUrl;
m_secondaryViewContainer = createViewContainer(url);
m_splitter->addWidget(m_secondaryViewContainer);
m_secondaryViewContainer->installEventFilter(this);
m_secondaryViewContainer->show();
}
@ -65,17 +70,59 @@ void DolphinTabPage::setSplitViewEnabled(bool enabled, const QUrl &secondaryUrl)
m_splitViewEnabled = enabled;
if (enabled) {
int splitterTotalWidth = m_splitter->width();
const QUrl& url = (secondaryUrl.isEmpty()) ? m_primaryViewContainer->url() : secondaryUrl;
m_secondaryViewContainer = createViewContainer(url);
auto secondaryNavigator = m_navigatorsWidget->secondaryUrlNavigator();
if (!secondaryNavigator) {
m_navigatorsWidget->createSecondaryUrlNavigator();
secondaryNavigator = m_navigatorsWidget->secondaryUrlNavigator();
}
m_secondaryViewContainer->connectUrlNavigator(secondaryNavigator);
m_navigatorsWidget->setSecondaryNavigatorVisible(true);
m_splitter->addWidget(m_secondaryViewContainer);
m_secondaryViewContainer->show();
m_secondaryViewContainer->installEventFilter(this);
m_secondaryViewContainer->setActive(true);
// opening animation
m_splitter->widget(1)->setMinimumWidth(1);
const QList<int> splitterSizes = {m_splitter->width(), 0};
m_splitter->setSizes(splitterSizes);
// TODO: This is only here to test the robustness of DolphinNavigatorsWidgetAction! I still have to move it to another merge request!
m_splitViewAnimation = new QVariantAnimation(m_splitter);
m_splitViewAnimation->setDuration(200); // TODO: where do I get the animation times from again?
m_splitViewAnimation->setStartValue(splitterTotalWidth);
m_splitViewAnimation->setEndValue(splitterTotalWidth / 2);
m_splitViewAnimation->setEasingCurve(QEasingCurve::OutCubic);
connect(m_splitViewAnimation, &QVariantAnimation::valueChanged, [=]() {
if (m_splitter->count() != 2) {
return;
}
int value = m_splitViewAnimation->currentValue().toInt();
const QList<int> splitterSizes = {value, m_splitter->width() - value};
m_splitter->setSizes(splitterSizes);
if (value == m_splitViewAnimation->endValue().toInt()) {
m_splitter->widget(1)->setMinimumWidth(m_splitter->widget(1)->minimumSizeHint().width());
}
});
m_splitViewAnimation->start(QAbstractAnimation::DeleteWhenStopped);
m_secondaryViewContainer->show();
} else {
m_navigatorsWidget->setSecondaryNavigatorVisible(false);
m_secondaryViewContainer->disconnectUrlNavigator();
DolphinViewContainer* view;
if (GeneralSettings::closeActiveSplitView()) {
view = activeViewContainer();
if (m_primaryViewActive) {
m_primaryViewContainer->disconnectUrlNavigator();
m_secondaryViewContainer->connectUrlNavigator(
m_navigatorsWidget->primaryUrlNavigator());
// If the primary view is active, we have to swap the pointers
// because the secondary view will be the new primary view.
qSwap(m_primaryViewContainer, m_secondaryViewContainer);
@ -84,6 +131,10 @@ void DolphinTabPage::setSplitViewEnabled(bool enabled, const QUrl &secondaryUrl)
} else {
view = m_primaryViewActive ? m_secondaryViewContainer : m_primaryViewContainer;
if (!m_primaryViewActive) {
m_primaryViewContainer->disconnectUrlNavigator();
m_secondaryViewContainer->connectUrlNavigator(
m_navigatorsWidget->primaryUrlNavigator());
// If the secondary view is active, we have to swap the pointers
// because the secondary view will be the new primary view.
qSwap(m_primaryViewContainer, m_secondaryViewContainer);
@ -93,6 +144,10 @@ void DolphinTabPage::setSplitViewEnabled(bool enabled, const QUrl &secondaryUrl)
m_primaryViewContainer->setActive(true);
view->close();
view->deleteLater();
if (m_splitViewAnimation) {
delete m_splitViewAnimation;
m_splitter->widget(0)->setMinimumWidth(m_splitter->widget(0)->minimumSizeHint().width());
}
}
}
}
@ -131,6 +186,56 @@ int DolphinTabPage::selectedItemsCount() const
return selectedItemsCount;
}
void DolphinTabPage::connectNavigators(DolphinNavigatorsWidgetAction *navigatorsWidget)
{
m_navigatorsWidget = navigatorsWidget;
auto primaryNavigator = navigatorsWidget->primaryUrlNavigator();
primaryNavigator->setActive(m_primaryViewActive);
m_primaryViewContainer->connectUrlNavigator(primaryNavigator);
if (m_splitViewEnabled) {
auto secondaryNavigator = navigatorsWidget->secondaryUrlNavigator();
if (!secondaryNavigator) {
navigatorsWidget->createSecondaryUrlNavigator();
secondaryNavigator = navigatorsWidget->secondaryUrlNavigator();
}
secondaryNavigator->setActive(!m_primaryViewActive);
m_secondaryViewContainer->connectUrlNavigator(secondaryNavigator);
}
resizeNavigators();
}
void DolphinTabPage::disconnectNavigators()
{
m_navigatorsWidget = nullptr;
m_primaryViewContainer->disconnectUrlNavigator();
if (m_splitViewEnabled) {
m_secondaryViewContainer->disconnectUrlNavigator();
}
}
bool DolphinTabPage::eventFilter(QObject */* watched */, QEvent *event)
{
if (event->type() == QEvent::Resize && m_navigatorsWidget) {
resizeNavigators();
}
return false;
}
void DolphinTabPage::resizeNavigators() const
{
if (!m_splitViewEnabled) {
m_navigatorsWidget->followViewContainerGeometry(
m_primaryViewContainer->mapToGlobal(QPoint(0,0)).x(),
m_primaryViewContainer->width());
} else {
m_navigatorsWidget->followViewContainersGeometry(
m_primaryViewContainer->mapToGlobal(QPoint(0,0)).x(),
m_primaryViewContainer->width(),
m_secondaryViewContainer->mapToGlobal(QPoint(0,0)).x(),
m_secondaryViewContainer->width());
}
}
void DolphinTabPage::markUrlsAsSelected(const QList<QUrl>& urls)
{
m_primaryViewContainer->view()->markUrlsAsSelected(urls);
@ -222,11 +327,17 @@ void DolphinTabPage::restoreState(const QByteArray& state)
stream >> m_primaryViewActive;
if (m_primaryViewActive) {
m_primaryViewContainer->setActive(true);
m_navigatorsWidget->primaryUrlNavigator()->setActive(true);
} else {
Q_ASSERT(m_splitViewEnabled);
m_secondaryViewContainer->setActive(true);
m_navigatorsWidget->primaryUrlNavigator()->setActive(false);
}
if (m_splitViewAnimation) {
delete m_splitViewAnimation;
m_splitter->widget(0)->setMinimumWidth(m_splitter->widget(0)->minimumSizeHint().width());
}
QByteArray splitterState;
stream >> splitterState;
m_splitter->restoreState(splitterState);

View file

@ -11,8 +11,10 @@
#include <QUrl>
#include <QWidget>
class QSplitter;
class DolphinNavigatorsWidgetAction;
class DolphinViewContainer;
class QSplitter;
class QVariantAnimation;
class KFileItemList;
class DolphinTabPage : public QWidget
@ -66,6 +68,30 @@ public:
*/
int selectedItemsCount() const;
/**
* Connects a navigatorsWidget to this. It will be connected to the DolphinViewContainers
* managed by this tab. For alignment purposes this will from now on notify the
* navigatorsWidget when this tab or its viewContainers are resized.
*/
void connectNavigators(DolphinNavigatorsWidgetAction *navigatorsWidget);
/**
* Makes it so this tab and its DolphinViewContainers aren't controlled by any
* UrlNavigators anymore.
*/
void disconnectNavigators();
/**
* Calls resizeNavigators() when a watched object is resized.
*/
bool eventFilter(QObject */* watched */, QEvent *event) override;
/**
* Notify the connected DolphinNavigatorsWidgetAction of geometry changes which it
* needs for visual alignment.
*/
void resizeNavigators() const;
/**
* Marks the items indicated by \p urls to get selected after the
* directory DolphinView::url() has been loaded. Note that nothing
@ -80,14 +106,6 @@ public:
*/
void markUrlAsCurrent(const QUrl& url);
/**
* Sets the places selector visible, if \a visible is true.
* The places selector allows to select the places provided
* by the places model passed in the constructor. Per default
* the places selector is visible.
*/
void setPlacesSelectorVisible(bool visible);
/**
* Refreshes the views of the main window by recreating them according to
* the given Dolphin settings.
@ -125,6 +143,7 @@ public:
signals:
void activeViewChanged(DolphinViewContainer* viewContainer);
void activeViewUrlChanged(const QUrl& url);
void splitterMoved(int pos, int index);
private slots:
/**
@ -153,8 +172,10 @@ private:
private:
QSplitter* m_splitter;
QPointer<DolphinNavigatorsWidgetAction> m_navigatorsWidget;
QPointer<DolphinViewContainer> m_primaryViewContainer;
QPointer<DolphinViewContainer> m_secondaryViewContainer;
QPointer<QVariantAnimation> m_splitViewAnimation;
bool m_primaryViewActive;
bool m_splitViewEnabled;

View file

@ -20,9 +20,10 @@
#include <QApplication>
#include <QDropEvent>
DolphinTabWidget::DolphinTabWidget(QWidget* parent) :
DolphinTabWidget::DolphinTabWidget(DolphinNavigatorsWidgetAction *navigatorsWidget, QWidget* parent) :
QTabWidget(parent),
m_lastViewedTab(0)
m_lastViewedTab(nullptr),
m_navigatorsWidget{navigatorsWidget}
{
KAcceleratorManager::setNoAccel(this);
@ -126,11 +127,19 @@ bool DolphinTabWidget::isUrlOpen(const QUrl &url) const
void DolphinTabWidget::openNewActivatedTab()
{
std::unique_ptr<DolphinUrlNavigator::VisualState> oldNavigatorState;
if (currentTabPage()->primaryViewActive()) {
oldNavigatorState = m_navigatorsWidget->primaryUrlNavigator()->visualState();
} else {
if (!m_navigatorsWidget->secondaryUrlNavigator()) {
m_navigatorsWidget->createSecondaryUrlNavigator();
}
oldNavigatorState = m_navigatorsWidget->secondaryUrlNavigator()->visualState();
}
const DolphinViewContainer* oldActiveViewContainer = currentTabPage()->activeViewContainer();
Q_ASSERT(oldActiveViewContainer);
const bool isUrlEditable = oldActiveViewContainer->urlNavigator()->isUrlEditable();
openNewActivatedTab(oldActiveViewContainer->url());
DolphinViewContainer* newActiveViewContainer = currentTabPage()->activeViewContainer();
@ -138,7 +147,7 @@ void DolphinTabWidget::openNewActivatedTab()
// The URL navigator of the new tab should have the same editable state
// as the current tab
newActiveViewContainer->urlNavigator()->setUrlEditable(isUrlEditable);
newActiveViewContainer->urlNavigator()->setVisualState(*oldNavigatorState.get());
// Always focus the new tab's view
newActiveViewContainer->view()->setFocus();
@ -384,16 +393,21 @@ void DolphinTabWidget::tabUrlChanged(const QUrl& url)
void DolphinTabWidget::currentTabChanged(int index)
{
// last-viewed tab deactivation
if (DolphinTabPage* tabPage = tabPageAt(m_lastViewedTab)) {
tabPage->setActive(false);
DolphinTabPage *tabPage = tabPageAt(index);
if (tabPage == m_lastViewedTab) {
return;
}
if (m_lastViewedTab) {
m_lastViewedTab->disconnectNavigators();
m_lastViewedTab->setActive(false);
}
DolphinTabPage* tabPage = tabPageAt(index);
DolphinViewContainer* viewContainer = tabPage->activeViewContainer();
Q_EMIT activeViewChanged(viewContainer);
Q_EMIT currentUrlChanged(viewContainer->url());
tabPage->setActive(true);
m_lastViewedTab = index;
tabPage->connectNavigators(m_navigatorsWidget);
m_navigatorsWidget->setSecondaryNavigatorVisible(tabPage->splitViewEnabled());
m_lastViewedTab = tabPageAt(index);
}
void DolphinTabWidget::tabInserted(int index)

View file

@ -7,11 +7,13 @@
#ifndef DOLPHIN_TAB_WIDGET_H
#define DOLPHIN_TAB_WIDGET_H
#include "dolphinnavigatorswidgetaction.h"
#include <QTabWidget>
#include <QUrl>
class DolphinViewContainer;
class DolphinTabPage;
class DolphinViewContainer;
class KConfigGroup;
class DolphinTabWidget : public QTabWidget
@ -32,7 +34,12 @@ public:
*/
AfterLastTab
};
explicit DolphinTabWidget(QWidget* parent);
/**
* @param navigatorsWidget The navigatorsWidget which is always going to be connected
* to the active tabPage.
*/
explicit DolphinTabWidget(DolphinNavigatorsWidgetAction *navigatorsWidget, QWidget *parent);
/**
* @return Tab page at the current index (can be 0 if tabs count is smaller than 1)
@ -224,7 +231,8 @@ private:
QPair<int, bool> indexByUrl(const QUrl& url) const;
private:
int m_lastViewedTab;
QPointer<DolphinTabPage> m_lastViewedTab;
QPointer<DolphinNavigatorsWidgetAction> m_navigatorsWidget;
};
#endif

View file

@ -56,7 +56,6 @@
<text context="@title:menu">Location Bar</text>
<Action name="editable_location" />
<Action name="replace_location" />
<Action name="location_in_toolbar" />
</Menu>
<Separator/>
<Action name="view_properties" />
@ -120,9 +119,7 @@
<Action name="icons" />
<Action name="compact" />
<Action name="details" />
<Separator name="separator_0" />
<Action name="sort" />
<Action name="url_navigator" />
<Action name="url_navigators" />
<Action name="split_view" />
<Action name="split_stash" />
<Action name="toggle_search" />

View file

@ -1,22 +1,9 @@
/*
* Copyright 2020 Felix Ernst <fe.a.ernst@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <https://www.gnu.org/licenses/>.
*/
This file is part of the KDE project
SPDX-FileCopyrightText: 2020 Felix Ernst <fe.a.ernst@gmail.com>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#include "dolphinurlnavigator.h"
@ -24,12 +11,12 @@
#include "dolphinplacesmodelsingleton.h"
#include "global.h"
#include <KToggleAction>
#include <KUrlComboBox>
#include <KLocalizedString>
#include <QAbstractButton>
#include <QLayout>
#include <QLineEdit>
#include <QMenu>
DolphinUrlNavigator::DolphinUrlNavigator(QWidget *parent) :
KUrlNavigator(DolphinPlacesModelSingleton::instance().placesModel(), QUrl(), parent)
@ -51,10 +38,8 @@ void DolphinUrlNavigator::init()
setHomeUrl(Dolphin::homeUrl());
setPlacesSelectorVisible(s_placesSelectorVisible);
editor()->setCompletionMode(KCompletion::CompletionMode(settings->urlCompletionMode()));
editor()->lineEdit()->installEventFilter(this);
installEventFilter(this);
setWhatsThis(xi18nc("@info:whatsthis location bar",
"<para>This line describes the location of the files and folders "
"<para>This describes the location of the files and folders "
"displayed below.</para><para>The name of the currently viewed "
"folder can be read at the very right. To the left of it is the "
"name of the folder that contains it. The whole line is called "
@ -79,30 +64,50 @@ DolphinUrlNavigator::~DolphinUrlNavigator()
s_instances.remove(this);
}
bool DolphinUrlNavigator::eventFilter(QObject* watched, QEvent* event)
QSize DolphinUrlNavigator::sizeHint() const
{
Q_UNUSED(watched)
if (event->type() == QEvent::ChildPolished) {
QChildEvent *childEvent = static_cast<QChildEvent *>(event);
QMenu *popup = qobject_cast<QMenu *>(childEvent->child());
if (popup) {
// The popups of the "breadcrumb mode" navigation buttons
// should not get the action added. They can currently be
// identified by their number of separators: 0 or 1
// The popups we are interested in have 2 or more separators.
int separatorCount = 0;
for (QAction *action : popup->actions()) {
if (action->isSeparator()) {
separatorCount++;
}
}
if (separatorCount > 1) {
q_check_ptr(s_ActionForContextMenu);
popup->addAction(s_ActionForContextMenu);
}
// Change sizeHint() in KUrlNavigator instead.
if (isUrlEditable()) {
return editor()->lineEdit()->sizeHint();
}
int widthHint = 0;
for (int i = 0; i < layout()->count(); ++i) {
QWidget *widget = layout()->itemAt(i)->widget();
const QAbstractButton *button = qobject_cast<QAbstractButton *>(widget);
if (button && button->icon().isNull()) {
widthHint += widget->minimumSizeHint().width();
}
}
return QSize(widthHint, KUrlNavigator::sizeHint().height());
}
std::unique_ptr<DolphinUrlNavigator::VisualState> DolphinUrlNavigator::visualState() const
{
std::unique_ptr<VisualState> visualState{new VisualState};
visualState->isUrlEditable = (isUrlEditable());
const QLineEdit *lineEdit = editor()->lineEdit();
visualState->hasFocus = lineEdit->hasFocus();
visualState->text = lineEdit->text();
visualState->cursorPosition = lineEdit->cursorPosition();
visualState->selectionStart = lineEdit->selectionStart();
visualState->selectionLength = lineEdit->selectionLength();
return visualState;
}
void DolphinUrlNavigator::setVisualState(const VisualState& visualState)
{
setUrlEditable(visualState.isUrlEditable);
if (!visualState.isUrlEditable) {
return;
}
editor()->lineEdit()->setText(visualState.text);
if (visualState.hasFocus) {
editor()->lineEdit()->setFocus();
editor()->lineEdit()->setCursorPosition(visualState.cursorPosition);
if (visualState.selectionStart != -1) {
editor()->lineEdit()->setSelection(visualState.selectionStart, visualState.selectionLength);
}
}
return false;
}
void DolphinUrlNavigator::slotReadSettings()
@ -126,12 +131,6 @@ void DolphinUrlNavigator::slotReturnPressed()
}
}
void DolphinUrlNavigator::addToContextMenu(QAction* action)
{
s_ActionForContextMenu = action;
}
void DolphinUrlNavigator::slotPlacesPanelVisibilityChanged(bool visible)
{
// The places-selector from the URL navigator should only be shown
@ -157,4 +156,3 @@ void DolphinUrlNavigator::setCompletionMode(const KCompletion::CompletionMode co
std::forward_list<DolphinUrlNavigator *> DolphinUrlNavigator::s_instances;
bool DolphinUrlNavigator::s_placesSelectorVisible = true;
QAction *DolphinUrlNavigator::s_ActionForContextMenu = nullptr;

View file

@ -1,22 +1,9 @@
/*
* Copyright 2020 Felix Ernst <fe.a.ernst@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <https://www.gnu.org/licenses/>.
*/
This file is part of the KDE project
SPDX-FileCopyrightText: 2020 Felix Ernst <fe.a.ernst@gmail.com>
SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
*/
#ifndef DOLPHINURLNAVIGATOR_H
#define DOLPHINURLNAVIGATOR_H
@ -30,10 +17,10 @@ class KToggleAction;
/**
* @brief Extends KUrlNavigator in a Dolphin-specific way
*
*
* Makes sure that Dolphin preferences, settings and settings changes are
* applied to all constructed DolphinUrlNavigators.
*
*
* @see KUrlNavigator
*/
class DolphinUrlNavigator : public KUrlNavigator
@ -55,6 +42,36 @@ public:
virtual ~DolphinUrlNavigator();
/**
* This method is needed so the DolphinNavigatorWidgetAction knows when there is not enough
* space to neatly align the UrlNavigator with the ViewContainers. Unfortunately KUrlNavigator
* does not have a useful sizeHint() currently. It would make more sense to change
* KUrlNavigator instead.
*/
QSize sizeHint() const override;
/**
* Wraps the visual state of a DolphinUrlNavigator so it can be passed around.
* This notably doesn't involve the locationUrl or history.
*/
struct VisualState {
bool isUrlEditable;
bool hasFocus;
QString text;
int cursorPosition;
int selectionStart;
int selectionLength;
};
/**
* Retrieve the visual state of this DolphinUrlNavigator.
* If two DolphinUrlNavigators have the same visual state they should look identical.
*/
std::unique_ptr<VisualState> visualState() const;
/**
* @param visualState A struct describing the new visual state of this object.
*/
void setVisualState(const VisualState &visualState);
public slots:
/**
* Refreshes all DolphinUrlNavigators to get synchronized with the
@ -68,16 +85,6 @@ public slots:
*/
void slotReturnPressed();
/**
* This method is specifically here so the locationInToolbar
* KToggleAction that is created in DolphinMainWindow can be passed to
* this class and then appear in all context menus. This last part is
* done by eventFilter().
* For any other use parts of this class need to be rewritten.
* @param action The locationInToolbar-action from DolphinMainWindow
*/
static void addToContextMenu(QAction *action);
static void slotPlacesPanelVisibilityChanged(bool visible);
protected:
@ -86,14 +93,6 @@ protected:
*/
void init();
/**
* This filter adds the s_ActionForContextMenu action to QMenus which
* are spawned by the watched QObject if that QMenu contains at least
* two separators.
* @see addToContextMenu()
*/
bool eventFilter(QObject * watched, QEvent * event) override;
protected slots:
/**
* Sets the completion mode for all DolphinUrlNavigators
@ -107,9 +106,6 @@ protected:
/** Caches the (negated) places panel visibility */
static bool s_placesSelectorVisible;
/** An action that is added to the context menu */
static QAction *s_ActionForContextMenu;
};
#endif // DOLPHINURLNAVIGATOR_H

View file

@ -13,7 +13,6 @@
#include "global.h"
#include "search/dolphinsearchbox.h"
#include "statusbar/dolphinstatusbar.h"
#include "trash/dolphintrash.h"
#include "views/viewmodecontroller.h"
#include "views/viewproperties.h"
#include "dolphin_detailsmodesettings.h"
@ -44,10 +43,8 @@
DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) :
QWidget(parent),
m_topLayout(nullptr),
m_navigatorWidget(nullptr),
m_urlNavigator(nullptr),
m_urlNavigatorConnected(nullptr),
m_emptyTrashButton(nullptr),
m_urlNavigator{new DolphinUrlNavigator(url)},
m_urlNavigatorConnected{nullptr},
m_searchBox(nullptr),
m_searchModeEnabled(false),
m_messageWidget(nullptr),
@ -56,7 +53,8 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) :
m_statusBar(nullptr),
m_statusBarTimer(nullptr),
m_statusBarTimestamp(),
m_autoGrabFocus(true)
m_autoGrabFocus(true),
m_urlNavigatorVisualState{}
#ifdef HAVE_KACTIVITIES
, m_activityResourceInstance(nullptr)
#endif
@ -67,20 +65,6 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) :
m_topLayout->setSpacing(0);
m_topLayout->setContentsMargins(0, 0, 0, 0);
m_navigatorWidget = new QWidget(this);
m_navigatorWidget->setVisible(false);
QHBoxLayout* navigatorLayout = new QHBoxLayout(m_navigatorWidget);
navigatorLayout->setSpacing(0);
navigatorLayout->setContentsMargins(0, 0, 0, 0);
m_urlNavigator = new DolphinUrlNavigator(url, m_navigatorWidget);
m_emptyTrashButton = new QPushButton(QIcon::fromTheme(QStringLiteral("user-trash")), i18nc("@action:button", "Empty Trash"), this);
m_emptyTrashButton->setFlat(true);
connect(m_emptyTrashButton, &QPushButton::clicked, this, [this]() { Trash::empty(this); });
connect(&Trash::instance(), &Trash::emptinessChanged, m_emptyTrashButton, &QPushButton::setDisabled);
m_emptyTrashButton->setDisabled(Trash::isEmpty());
m_emptyTrashButton->hide();
m_searchBox = new DolphinSearchBox(this);
m_searchBox->hide();
connect(m_searchBox, &DolphinSearchBox::activated, this, &DolphinViewContainer::activate);
@ -132,8 +116,8 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) :
// m_urlNavigator stays in sync with m_view's location changes and
// keeps track of them so going back and forth in the history works.
connect(m_view, &DolphinView::urlChanged,
m_urlNavigator, &DolphinUrlNavigator::setLocationUrl);
connect(m_urlNavigator, &DolphinUrlNavigator::urlChanged,
m_urlNavigator.get(), &DolphinUrlNavigator::setLocationUrl);
connect(m_urlNavigator.get(), &DolphinUrlNavigator::urlChanged,
this, &DolphinViewContainer::slotUrlNavigatorLocationChanged);
connect(m_view, &DolphinView::writeStateChanged,
this, &DolphinViewContainer::writeStateChanged);
@ -166,10 +150,6 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) :
connect(m_view, &DolphinView::activated,
this, &DolphinViewContainer::activate);
connect(m_view, &DolphinView::directoryLoadingCompleted, this, [this]() {
m_emptyTrashButton->setVisible(m_view->url().scheme() == QLatin1String("trash"));
});
// Initialize status bar
m_statusBar = new DolphinStatusBar(this);
m_statusBar->setUrl(m_view->url());
@ -196,19 +176,12 @@ DolphinViewContainer::DolphinViewContainer(const QUrl& url, QWidget* parent) :
connect(undoManager, &KIO::FileUndoManager::jobRecordingFinished,
this, &DolphinViewContainer::delayedStatusBarUpdate);
navigatorLayout->addWidget(m_urlNavigator);
navigatorLayout->addWidget(m_emptyTrashButton);
m_topLayout->addWidget(m_navigatorWidget);
m_topLayout->addWidget(m_searchBox);
m_topLayout->addWidget(m_messageWidget);
m_topLayout->addWidget(m_view);
m_topLayout->addWidget(m_filterBar);
m_topLayout->addWidget(m_statusBar);
if (!GeneralSettings::locationInToolbar()) {
connectToInternalUrlNavigator();
}
setSearchModeEnabled(isSearchUrl(url));
connect(DetailsModeSettings::self(), &KCoreConfigSkeleton::configChanged, this, [=]() {
@ -237,7 +210,9 @@ QUrl DolphinViewContainer::url() const
void DolphinViewContainer::setActive(bool active)
{
m_searchBox->setActive(active);
m_urlNavigator->setActive(active);
if (m_urlNavigatorConnected) {
m_urlNavigatorConnected->setActive(active);
}
m_view->setActive(active);
#ifdef HAVE_KACTIVITIES
@ -251,7 +226,6 @@ void DolphinViewContainer::setActive(bool active)
bool DolphinViewContainer::isActive() const
{
Q_ASSERT(!m_urlNavigatorConnected || m_urlNavigatorConnected->isActive() == m_view->isActive());
return m_view->isActive();
}
@ -292,12 +266,12 @@ DolphinUrlNavigator* DolphinViewContainer::urlNavigator()
const DolphinUrlNavigator *DolphinViewContainer::urlNavigatorInternalWithHistory() const
{
return m_urlNavigator;
return m_urlNavigator.get();
}
DolphinUrlNavigator *DolphinViewContainer::urlNavigatorInternalWithHistory()
{
return m_urlNavigator;
return m_urlNavigator.get();
}
const DolphinView* DolphinViewContainer::view() const
@ -314,19 +288,20 @@ void DolphinViewContainer::connectUrlNavigator(DolphinUrlNavigator *urlNavigator
{
Q_CHECK_PTR(urlNavigator);
Q_ASSERT(!m_urlNavigatorConnected);
Q_ASSERT(m_urlNavigator.get() != urlNavigator);
Q_CHECK_PTR(m_view);
m_urlNavigatorConnected = urlNavigator;
// m_urlNavigator is already connected through urlChanged signals.
if (urlNavigator != m_urlNavigator) {
urlNavigator->setLocationUrl(m_view->url());
connect(m_view, &DolphinView::urlChanged,
urlNavigator, &DolphinUrlNavigator::setLocationUrl);
connect(urlNavigator, &DolphinUrlNavigator::urlChanged,
this, &DolphinViewContainer::slotUrlNavigatorLocationChanged);
urlNavigator->setLocationUrl(m_view->url());
urlNavigator->setActive(isActive());
if (m_urlNavigatorVisualState) {
urlNavigator->setVisualState(*m_urlNavigatorVisualState.get());
m_urlNavigatorVisualState.reset();
}
connect(m_view, &DolphinView::urlChanged,
urlNavigator, &DolphinUrlNavigator::setLocationUrl);
connect(urlNavigator, &DolphinUrlNavigator::urlChanged,
this, &DolphinViewContainer::slotUrlNavigatorLocationChanged);
connect(urlNavigator, &DolphinUrlNavigator::activated,
this, &DolphinViewContainer::activate);
connect(urlNavigator, &DolphinUrlNavigator::urlAboutToBeChanged,
@ -337,7 +312,7 @@ void DolphinViewContainer::connectUrlNavigator(DolphinUrlNavigator *urlNavigator
m_view->dropUrls(destination, event, urlNavigator->dropWidget());
});
updateNavigatorWidgetVisibility();
m_urlNavigatorConnected = urlNavigator;
}
void DolphinViewContainer::disconnectUrlNavigator()
@ -346,34 +321,27 @@ void DolphinViewContainer::disconnectUrlNavigator()
return;
}
// m_urlNavigator stays connected through the urlChanged signals.
if (m_urlNavigatorConnected != m_urlNavigator) {
disconnect(m_view, &DolphinView::urlChanged,
m_urlNavigatorConnected, &DolphinUrlNavigator::setLocationUrl);
disconnect(m_urlNavigatorConnected, &DolphinUrlNavigator::urlChanged,
this, &DolphinViewContainer::slotUrlNavigatorLocationChanged);
}
disconnect(m_view, &DolphinView::urlChanged,
m_urlNavigatorConnected, &DolphinUrlNavigator::setLocationUrl);
disconnect(m_urlNavigatorConnected, &DolphinUrlNavigator::urlChanged,
this, &DolphinViewContainer::slotUrlNavigatorLocationChanged);
disconnect(m_urlNavigatorConnected, &DolphinUrlNavigator::activated,
this, &DolphinViewContainer::activate);
this, &DolphinViewContainer::activate);
disconnect(m_urlNavigatorConnected, &DolphinUrlNavigator::urlAboutToBeChanged,
this, &DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged);
this, &DolphinViewContainer::slotUrlNavigatorLocationAboutToBeChanged);
disconnect(m_urlNavigatorConnected, &DolphinUrlNavigator::urlSelectionRequested,
this, &DolphinViewContainer::slotUrlSelectionRequested);
this, &DolphinViewContainer::slotUrlSelectionRequested);
disconnect(m_urlNavigatorConnected, &DolphinUrlNavigator::urlsDropped,
this, nullptr);
this, nullptr);
m_urlNavigatorVisualState = m_urlNavigatorConnected->visualState();
m_urlNavigatorConnected = nullptr;
updateNavigatorWidgetVisibility();
}
KMessageWidget *DolphinViewContainer::showMessage(const QString& msg, MessageType type)
void DolphinViewContainer::showMessage(const QString& msg, MessageType type)
{
if (msg.isEmpty()) {
return m_messageWidget;
}
for (auto action : m_messageWidget->actions()) {
m_messageWidget->removeAction(action);
return;
}
m_messageWidget->setText(msg);
@ -399,7 +367,6 @@ KMessageWidget *DolphinViewContainer::showMessage(const QString& msg, MessageTyp
m_messageWidget->hide();
}
m_messageWidget->animatedShow();
return m_messageWidget;
}
void DolphinViewContainer::readSettings()
@ -423,7 +390,6 @@ bool DolphinViewContainer::isFilterBarVisible() const
void DolphinViewContainer::setSearchModeEnabled(bool enabled)
{
m_searchBox->setVisible(enabled);
updateNavigatorWidgetVisibility();
if (enabled) {
const QUrl& locationUrl = m_urlNavigatorConnected->locationUrl();
@ -540,9 +506,8 @@ QString DolphinViewContainer::caption() const
void DolphinViewContainer::setUrl(const QUrl& newUrl)
{
Q_CHECK_PTR(m_urlNavigatorConnected);
if (newUrl != m_urlNavigatorConnected->locationUrl()) {
m_urlNavigatorConnected->setLocationUrl(newUrl);
if (newUrl != m_urlNavigator->locationUrl()) {
m_urlNavigator->setLocationUrl(newUrl);
}
#ifdef HAVE_KACTIVITIES
@ -603,15 +568,6 @@ void DolphinViewContainer::updateDirectorySortingProgress(int percent)
m_statusBar->setProgress(percent);
}
void DolphinViewContainer::updateNavigatorWidgetVisibility()
{
if (m_urlNavigatorConnected == m_urlNavigator && !m_searchBox->isVisible()) {
m_navigatorWidget->setVisible(true);
} else {
m_navigatorWidget->setVisible(false);
}
}
void DolphinViewContainer::slotDirectoryLoadingStarted()
{
if (isSearchUrl(url())) {

View file

@ -90,7 +90,7 @@ public:
* or nullptr if there is none.
* @see connectUrlNavigator()
* @see disconnectUrlNavigator()
*
*
* Use urlNavigatorInternalWithHistory() if you want to access the history.
* @see urlNavigatorInternalWithHistory()
*/
@ -100,7 +100,7 @@ public:
* or nullptr if there is none.
* @see connectUrlNavigator()
* @see disconnectUrlNavigator()
*
*
* Use urlNavigatorInternalWithHistory() if you want to access the history.
* @see urlNavigatorInternalWithHistory()
*/
@ -126,11 +126,6 @@ public:
*/
void connectUrlNavigator(DolphinUrlNavigator *urlNavigator);
inline void connectToInternalUrlNavigator()
{
connectUrlNavigator(m_urlNavigator);
}
/**
* Disconnects the navigator that is currently controling the view.
* This method completely reverses connectUrlNavigator().
@ -140,9 +135,8 @@ public:
/**
* Shows the message \msg with the given type non-modal above
* the view-content.
* @return the KMessageWidget used to show the message
*/
KMessageWidget *showMessage(const QString& msg, MessageType type);
void showMessage(const QString& msg, MessageType type);
/**
* Refreshes the view container to get synchronized with the (updated) Dolphin settings.
@ -244,8 +238,6 @@ private slots:
void updateDirectorySortingProgress(int percent);
void updateNavigatorWidgetVisibility();
/**
* Updates the statusbar to show an undetermined progress with the correct
* context information whether a searching or a directory loading is done.
@ -369,21 +361,20 @@ private:
private:
QVBoxLayout* m_topLayout;
QWidget* m_navigatorWidget;
/**
* The UrlNavigator within the m_navigatorWidget. m_urlNavigator is
* used even when another UrlNavigator is controlling the view to keep
* track of this view containers history.
* The internal UrlNavigator which is never visible to the user.
* m_urlNavigator is used even when another UrlNavigator is controlling
* the view to keep track of this object's history.
*/
DolphinUrlNavigator *m_urlNavigator;
std::unique_ptr<DolphinUrlNavigator> m_urlNavigator;
/**
* The UrlNavigator that is currently connected to the view. This could
* either be m_urlNavigator, the urlNavigator in the toolbar or nullptr.
* The UrlNavigator that is currently connected to the view.
* This is a nullptr if no UrlNavigator is connected.
* Otherwise it's one of the UrlNavigators visible in the toolbar.
*/
QPointer<DolphinUrlNavigator> m_urlNavigatorConnected;
QPushButton* m_emptyTrashButton;
DolphinSearchBox* m_searchBox;
bool m_searchModeEnabled;
KMessageWidget* m_messageWidget;
@ -396,6 +387,11 @@ private:
QTimer* m_statusBarTimer; // Triggers a delayed update
QElapsedTimer m_statusBarTimestamp; // Time in ms since last update
bool m_autoGrabFocus;
/**
* The visual state to be applied to the next UrlNavigator that gets
* connected to this ViewContainer.
*/
std::unique_ptr<DolphinUrlNavigator::VisualState> m_urlNavigatorVisualState;
#ifdef HAVE_KACTIVITIES
private:

View file

@ -21,6 +21,7 @@
#include <KCrash>
#include <KDBusService>
#include <KLocalizedString>
#include <KToolBar>
#include <Kdelibs4ConfigMigrator>
#include <KConfigGui>
@ -213,6 +214,12 @@ extern "C" Q_DECL_EXPORT int kdemain(int argc, char **argv)
}
}
}
Qt::ToolBarArea area = mainWindow->toolBarArea(mainWindow->toolBar());
if (area != Qt::TopToolBarArea && area != Qt::BottomToolBarArea) {
// Migrate users with disabled tool bar positions.
// Remove this a few years from now (2020).
mainWindow->addToolBar(Qt::TopToolBarArea, mainWindow->toolBar());
}
#ifdef HAVE_KUSERFEEDBACK
auto feedbackProvider = DolphinFeedbackProvider::instance();

View file

@ -50,10 +50,6 @@
<label>Split the view into two panes</label>
<default>false</default>
</entry>
<entry name="LocationInToolbar" type="Bool">
<label>Should the location be shown in the toolbar instead</label>
<default>false</default>
</entry>
<entry name="FilterBar" type="Bool">
<label>Should the filter bar be shown</label>
<default>false</default>

View file

@ -1,91 +0,0 @@
/*
* Copyright 2020 Felix Ernst <fe.a.ernst@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <https://www.gnu.org/licenses/>.
*/
#include "dolphinurlnavigatorwidgetaction.h"
#include "dolphin_generalsettings.h"
#include "dolphinviewcontainer.h"
#include <KLocalizedString>
#include <KXMLGUIFactory>
#include <KXmlGuiWindow>
#include <QDomDocument>
#include <QStackedWidget>
DolphinUrlNavigatorWidgetAction::DolphinUrlNavigatorWidgetAction(QWidget *parent) :
QWidgetAction(parent)
{
setText(i18nc("@action:inmenu", "Url navigator"));
m_stackedWidget = new QStackedWidget(parent);
auto expandingSpacer = new QWidget(m_stackedWidget);
expandingSpacer->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
m_stackedWidget->addWidget(expandingSpacer); // index 0 of QStackedWidget
auto urlNavigator = new DolphinUrlNavigator(m_stackedWidget);
m_stackedWidget->addWidget(urlNavigator); // index 1 of QStackedWidget
setDefaultWidget(m_stackedWidget);
setUrlNavigatorVisible(GeneralSettings::locationInToolbar());
}
DolphinUrlNavigator* DolphinUrlNavigatorWidgetAction::urlNavigator() const
{
return static_cast<DolphinUrlNavigator *>(m_stackedWidget->widget(1));
}
void DolphinUrlNavigatorWidgetAction::setUrlNavigatorVisible(bool visible)
{
if (!visible) {
m_stackedWidget->setCurrentIndex(0); // expandingSpacer
} else {
m_stackedWidget->setCurrentIndex(1); // urlNavigator
}
}
bool DolphinUrlNavigatorWidgetAction::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_navigator"));
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;
}

View file

@ -1,68 +0,0 @@
/*
* Copyright 2020 Felix Ernst <fe.a.ernst@gmail.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) version 3, or any
* later version accepted by the membership of KDE e.V. (or its
* successor approved by the membership of KDE e.V.), which shall
* act as a proxy defined in Section 6 of version 3 of the license.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <https://www.gnu.org/licenses/>.
*/
#ifndef DOLPHINURLNAVIGATORWIDGETACTION_H
#define DOLPHINURLNAVIGATORWIDGETACTION_H
#include "dolphinurlnavigator.h"
#include <QWidgetAction>
class KXmlGuiWindow;
class QStackedWidget;
/**
* @brief QWidgetAction that allows to use a KUrlNavigator in a toolbar.
*
* When the UrlNavigator of this object is not in use,
* setUrlNavigatorVisible(false) is used to hide it. It will then be
* replaced in the toolbar by an empty expanding spacer. This makes sure
* that the other widgets in the toolbar will not change location when
* switching the UrlNavigators visibility.
*/
class DolphinUrlNavigatorWidgetAction : public QWidgetAction
{
Q_OBJECT
public:
DolphinUrlNavigatorWidgetAction(QWidget *parent = nullptr);
DolphinUrlNavigator *urlNavigator() const;
/**
* Sets the QStackedWidget which is the defaultWidget() to either
* show a KUrlNavigator or an expanding spacer.
*/
void setUrlNavigatorVisible(bool visible);
/**
* Adds this action to the mainWindow's toolbar and saves the change
* in the users ui configuration file.
* @return true if successful. Otherwise false.
* @note This method does multiple things which are discouraged in
* the API documentation.
*/
bool addToToolbarAndSave(KXmlGuiWindow *mainWindow);
private:
QStackedWidget *m_stackedWidget;
};
#endif // DOLPHINURLNAVIGATORWIDGETACTION_H