diff --git a/src/dolphinnavigatorswidgetaction.cpp b/src/dolphinnavigatorswidgetaction.cpp index 6b76aad084..ace004f0fc 100644 --- a/src/dolphinnavigatorswidgetaction.cpp +++ b/src/dolphinnavigatorswidgetaction.cpp @@ -26,11 +26,7 @@ DolphinNavigatorsWidgetAction::DolphinNavigatorsWidgetAction(QWidget *parent) : QWidgetAction{parent}, m_splitter{new QSplitter(Qt::Horizontal)}, m_adjustSpacingTimer{new QTimer(this)}, - m_globalXOfSplitter{INT_MIN}, - m_globalXOfPrimary{INT_MIN}, - m_widthOfPrimary{INT_MIN}, - m_globalXOfSecondary{INT_MIN}, - m_widthOfSecondary{INT_MIN} + m_viewGeometriesHelper{m_splitter.get(), this} { updateText(); setIcon(QIcon::fromTheme(QStringLiteral("dialog-scripts"))); @@ -45,6 +41,63 @@ DolphinNavigatorsWidgetAction::DolphinNavigatorsWidgetAction(QWidget *parent) : this, &DolphinNavigatorsWidgetAction::adjustSpacing); } +void DolphinNavigatorsWidgetAction::adjustSpacing() +{ + auto viewGeometries = m_viewGeometriesHelper.viewGeometries(); + const int widthOfSplitterPrimary = viewGeometries.globalXOfPrimary + viewGeometries.widthOfPrimary - viewGeometries.globalXOfNavigatorsWidget; + const QList splitterSizes = {widthOfSplitterPrimary, + m_splitter->width() - widthOfSplitterPrimary}; + m_splitter->setSizes(splitterSizes); + + // primary side of m_splitter + int leadingSpacing = viewGeometries.globalXOfPrimary - viewGeometries.globalXOfNavigatorsWidget; + if (leadingSpacing < 0) { + leadingSpacing = 0; + } + int trailingSpacing = (viewGeometries.globalXOfNavigatorsWidget + m_splitter->width()) + - (viewGeometries.globalXOfPrimary + viewGeometries.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 (viewGeometries.globalXOfSecondary == INT_MIN) { + Q_ASSERT(viewGeometries.widthOfSecondary == INT_MIN); + return; + } + spacing(Primary, Trailing)->setFixedWidth(0); + + trailingSpacing = (viewGeometries.globalXOfNavigatorsWidget + m_splitter->width()) + - (viewGeometries.globalXOfSecondary + viewGeometries.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); +} + void DolphinNavigatorsWidgetAction::createSecondaryUrlNavigator() { Q_ASSERT(m_splitter->count() == 1); @@ -53,31 +106,10 @@ void DolphinNavigatorsWidgetAction::createSecondaryUrlNavigator() updateText(); } -void DolphinNavigatorsWidgetAction::followViewContainerGeometry( - int globalXOfPrimary, int widthOfPrimary) +void DolphinNavigatorsWidgetAction::followViewContainersGeometry(QWidget *primaryViewContainer, + QWidget *secondaryViewContainer) { - followViewContainersGeometry(globalXOfPrimary, widthOfPrimary, INT_MIN, INT_MIN); -} - -void DolphinNavigatorsWidgetAction::followViewContainersGeometry( - int globalXOfPrimary, int widthOfPrimary, - int globalXOfSecondary, int widthOfSecondary) -{ - if (QApplication::layoutDirection() == Qt::LeftToRight) { - m_globalXOfSplitter = m_splitter->mapToGlobal(QPoint(0,0)).x(); - m_globalXOfPrimary = globalXOfPrimary; - m_globalXOfSecondary = globalXOfSecondary; - } else { - // When the direction is reversed, globalX does not change. - // For the adjustSpacing() code to work we need globalX to measure from right to left - // and to measure up to the rightmost point of a widget instead of the leftmost. - m_globalXOfSplitter = (-1) * (m_splitter->mapToGlobal(QPoint(0,0)).x() + m_splitter->width()); - m_globalXOfPrimary = (-1) * (globalXOfPrimary + widthOfPrimary); - m_globalXOfSecondary = (globalXOfSecondary == INT_MIN) ? INT_MIN : - (-1) * (globalXOfSecondary + widthOfSecondary); - } - m_widthOfPrimary = widthOfPrimary; - m_widthOfSecondary = widthOfSecondary; + m_viewGeometriesHelper.setViewContainers(primaryViewContainer, secondaryViewContainer); adjustSpacing(); } @@ -137,65 +169,6 @@ void DolphinNavigatorsWidgetAction::deleteWidget(QWidget *widget) m_splitter->setParent(nullptr); } -void DolphinNavigatorsWidgetAction::adjustSpacing() -{ - Q_ASSERT(m_globalXOfSplitter != INT_MIN); - Q_ASSERT(m_globalXOfPrimary != INT_MIN); - Q_ASSERT(m_widthOfPrimary != INT_MIN); - const int widthOfSplitterPrimary = m_globalXOfPrimary + m_widthOfPrimary - m_globalXOfSplitter; - const QList 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 == INT_MIN) { - Q_ASSERT(m_widthOfSecondary == INT_MIN); - 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()); @@ -281,3 +254,70 @@ void DolphinNavigatorsWidgetAction::updateText() 2 : 1; setText(i18ncp("@action:inmenu", "Location Bar", "Location Bars", urlNavigatorsAmount)); } + +DolphinNavigatorsWidgetAction::ViewGeometriesHelper::ViewGeometriesHelper + (QWidget *navigatorsWidget, DolphinNavigatorsWidgetAction *navigatorsWidgetAction) : + m_navigatorsWidget{navigatorsWidget}, + m_navigatorsWidgetAction{navigatorsWidgetAction} +{ + Q_CHECK_PTR(navigatorsWidget); + Q_CHECK_PTR(navigatorsWidgetAction); +} + +bool DolphinNavigatorsWidgetAction::ViewGeometriesHelper::eventFilter(QObject *watched, QEvent *event) +{ + if (event->type() == QEvent::Resize) { + m_navigatorsWidgetAction->adjustSpacing(); + return false; + } + return QObject::eventFilter(watched, event); +} + +void DolphinNavigatorsWidgetAction::ViewGeometriesHelper::setViewContainers(QWidget *primaryViewContainer, + QWidget *secondaryViewContainer) +{ + Q_CHECK_PTR(primaryViewContainer); + if (m_primaryViewContainer) { + m_primaryViewContainer->removeEventFilter(this); + } + primaryViewContainer->installEventFilter(this); + m_primaryViewContainer = primaryViewContainer; + + // It is not possible to resize the secondaryViewContainer without simultaneously + // resizing the primaryViewContainer so we don't have to installEventFilter() here. + m_secondaryViewContainer = secondaryViewContainer; +} + +DolphinNavigatorsWidgetAction::ViewGeometriesHelper::Geometries + DolphinNavigatorsWidgetAction::ViewGeometriesHelper::viewGeometries() +{ + Q_ASSERT(m_primaryViewContainer); + Geometries geometries; + + // width + geometries.widthOfPrimary = m_primaryViewContainer->width(); + if (m_secondaryViewContainer) { + geometries.widthOfSecondary = m_secondaryViewContainer->width(); + } else { + geometries.widthOfSecondary = INT_MIN; + } + + // globalX + if (QApplication::layoutDirection() == Qt::LeftToRight) { + geometries.globalXOfNavigatorsWidget = m_navigatorsWidget->mapToGlobal(QPoint(0,0)).x(); + geometries.globalXOfPrimary = m_primaryViewContainer->mapToGlobal(QPoint(0,0)).x(); + geometries.globalXOfSecondary = !m_secondaryViewContainer ? INT_MIN : + m_secondaryViewContainer->mapToGlobal(QPoint(0,0)).x(); + } else { + // When the direction is reversed, globalX does not change. + // For the adjustSpacing() code to work we need globalX to measure from right to left + // and to measure up to the rightmost point of a widget instead of the leftmost. + geometries.globalXOfNavigatorsWidget = + (-1) * (m_navigatorsWidget->mapToGlobal(QPoint(0,0)).x() + m_navigatorsWidget->width()); + geometries.globalXOfPrimary = + (-1) * (m_primaryViewContainer->mapToGlobal(QPoint(0,0)).x() + geometries.widthOfPrimary); + geometries.globalXOfSecondary = !m_secondaryViewContainer ? INT_MIN : + (-1) * (m_secondaryViewContainer->mapToGlobal(QPoint(0,0)).x() + geometries.widthOfSecondary); + } + return geometries; +} diff --git a/src/dolphinnavigatorswidgetaction.h b/src/dolphinnavigatorswidgetaction.h index f15ea144d6..8049965321 100644 --- a/src/dolphinnavigatorswidgetaction.h +++ b/src/dolphinnavigatorswidgetaction.h @@ -10,6 +10,7 @@ #include "dolphinurlnavigator.h" +#include #include #include #include @@ -41,6 +42,13 @@ class DolphinNavigatorsWidgetAction : public QWidgetAction public: DolphinNavigatorsWidgetAction(QWidget *parent = nullptr); + /** + * 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(); + /** * The secondary UrlNavigator is only created on-demand. Such an action is not necessary * for the primary UrlNavigator which is created preemptively. @@ -52,17 +60,12 @@ public: */ 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); + void followViewContainersGeometry(QWidget *primaryViewContainer, + QWidget *secondaryViewContainer = nullptr); bool isInToolbar() const; @@ -97,13 +100,6 @@ protected: void deleteWidget(QWidget *widget) override; private: - /** - * 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(); - /** * In Left-to-right languages the Primary side will be the left one. */ @@ -157,12 +153,54 @@ private: */ std::unique_ptr m_adjustSpacingTimer; - // cached values - int m_globalXOfSplitter; - int m_globalXOfPrimary; - int m_widthOfPrimary; - int m_globalXOfSecondary; - int m_widthOfSecondary; + /** + * Extracts the geometry information needed by adjustSpacing() from + * ViewContainers. They are also monitored for size changes which + * will lead to adjustSpacing() calls. + */ + class ViewGeometriesHelper : public QObject + { + public: + /** + * @param navigatorsWidget The QWidget of the navigatorsWidgetAction. + * @param navigatorsWidgetAction is only used to call adjustSpacing() whenever that is + * deemed necessary. + */ + ViewGeometriesHelper(QWidget *navigatorsWidget, DolphinNavigatorsWidgetAction *navigatorsWidgetAction); + + /** + * Calls m_navigatorsWidgetAction::adjustSpacing() when a watched object is resized. + */ + bool eventFilter(QObject *watched, QEvent *event) override; + + /** + * Sets the ViewContainers whose geometry is obtained when viewGeometries() is called. + */ + void setViewContainers(QWidget *primaryViewContainer, + QWidget *secondaryViewContainer = nullptr); + + struct Geometries { + int globalXOfNavigatorsWidget; + int globalXOfPrimary; + int widthOfPrimary; + int globalXOfSecondary; + int widthOfSecondary; + }; + /** + * @return a Geometries struct that contains values adjustSpacing() requires. + */ + Geometries viewGeometries(); + + private: + QWidget *m_navigatorsWidget; + /** Is only used to call adjustSpacing() whenever that is deemed necessary. */ + DolphinNavigatorsWidgetAction *m_navigatorsWidgetAction; + + QPointer m_primaryViewContainer; + QPointer m_secondaryViewContainer; + }; + + ViewGeometriesHelper m_viewGeometriesHelper; }; #endif // DOLPHINNAVIGATORSWIDGETACTION_H diff --git a/src/dolphintabpage.cpp b/src/dolphintabpage.cpp index a90e8e7f0c..36049fa974 100644 --- a/src/dolphintabpage.cpp +++ b/src/dolphintabpage.cpp @@ -43,7 +43,6 @@ 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()) { @@ -53,7 +52,6 @@ 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(); } @@ -98,9 +96,10 @@ void DolphinTabPage::setSplitViewEnabled(bool enabled, Animated animated, const } m_secondaryViewContainer->connectUrlNavigator(secondaryNavigator); m_navigatorsWidget->setSecondaryNavigatorVisible(true); + m_navigatorsWidget->followViewContainersGeometry(m_primaryViewContainer, + m_secondaryViewContainer); m_splitter->addWidget(m_secondaryViewContainer); - m_secondaryViewContainer->installEventFilter(this); m_secondaryViewContainer->setActive(true); if (animated == WithAnimation) { @@ -141,6 +140,7 @@ void DolphinTabPage::setSplitViewEnabled(bool enabled, Animated animated, const } } m_primaryViewContainer->setActive(true); + m_navigatorsWidget->followViewContainersGeometry(m_primaryViewContainer, nullptr); if (animated == WithoutAnimation) { view->close(); @@ -201,7 +201,8 @@ void DolphinTabPage::connectNavigators(DolphinNavigatorsWidgetAction *navigators auto secondaryNavigator = navigatorsWidget->secondaryUrlNavigator(); m_secondaryViewContainer->connectUrlNavigator(secondaryNavigator); } - resizeNavigators(); + m_navigatorsWidget->followViewContainersGeometry(m_primaryViewContainer, + m_secondaryViewContainer); } void DolphinTabPage::disconnectNavigators() @@ -213,15 +214,6 @@ void DolphinTabPage::disconnectNavigators() } } -bool DolphinTabPage::eventFilter(QObject *watched, QEvent *event) -{ - if (event->type() == QEvent::Resize && m_navigatorsWidget) { - resizeNavigators(); - return false; - } - return QWidget::eventFilter(watched, event); -} - void DolphinTabPage::insertNavigatorsWidget(DolphinNavigatorsWidgetAction* navigatorsWidget) { QGridLayout *gridLayout = static_cast(layout()); @@ -235,22 +227,6 @@ void DolphinTabPage::insertNavigatorsWidget(DolphinNavigatorsWidgetAction* navig } } - -void DolphinTabPage::resizeNavigators() const -{ - if (!m_secondaryViewContainer) { - 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& urls) { m_primaryViewContainer->view()->markUrlsAsSelected(urls); diff --git a/src/dolphintabpage.h b/src/dolphintabpage.h index e90bf99bf5..a3659aa184 100644 --- a/src/dolphintabpage.h +++ b/src/dolphintabpage.h @@ -93,11 +93,6 @@ public: */ void disconnectNavigators(); - /** - * Calls resizeNavigators() when a watched object is resized. - */ - bool eventFilter(QObject *watched, QEvent *event) override; - void insertNavigatorsWidget(DolphinNavigatorsWidgetAction *navigatorsWidget); /**