File indexing completed on 2024-04-14 15:49:27
0001 /* 0002 This file is part of the KDE project 0003 SPDX-FileCopyrightText: 2020 Felix Ernst <felixernst@kde.org> 0004 0005 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL 0006 */ 0007 0008 #ifndef DOLPHINNAVIGATORSWIDGETACTION_H 0009 #define DOLPHINNAVIGATORSWIDGETACTION_H 0010 0011 #include "dolphinurlnavigator.h" 0012 0013 #include <QPointer> 0014 #include <QSplitter> 0015 #include <QTimer> 0016 #include <QWidgetAction> 0017 0018 #include <memory> 0019 0020 class KXmlGuiWindow; 0021 class QPushButton; 0022 0023 /** 0024 * @brief QWidgetAction that allows to use DolphinUrlNavigators in a toolbar. 0025 * 0026 * This class is mainly a container that manages up to two DolphinUrlNavigator objects so they 0027 * can be added to a toolbar. It also deals with alignment. 0028 * 0029 * The structure of the defaultWidget() of this QWidgetAction is as follows: 0030 * - A QSplitter manages up to two sides which each correspond to one DolphinViewContainer. 0031 * The secondary side only exists for split view and is created by 0032 * createSecondaryUrlNavigator() when necessary. 0033 * - Each side is a QWidget which I call NavigatorWidget with a QHBoxLayout. 0034 * - Each NavigatorWidget consists an UrlNavigator, an emptyTrashButton, a 0035 * networkFolderButton, and spacing. 0036 * - Only the primary navigatorWidget has leading spacing. Both have trailing spacing. 0037 * The spacing is there to align the UrlNavigator with its DolphinViewContainer. 0038 */ 0039 class DolphinNavigatorsWidgetAction : public QWidgetAction 0040 { 0041 Q_OBJECT 0042 0043 public: 0044 DolphinNavigatorsWidgetAction(QWidget *parent = nullptr); 0045 0046 /** 0047 * Adjusts the width of the spacings used to align the UrlNavigators with ViewContainers. 0048 * This can only work nicely if up-to-date geometry of ViewContainers is cached so 0049 * followViewContainersGeometry() has to have been called at least once before. 0050 */ 0051 void adjustSpacing(); 0052 0053 /** 0054 * The secondary UrlNavigator is only created on-demand. Such an action is not necessary 0055 * for the primary UrlNavigator which is created preemptively. 0056 * 0057 * This method should preferably only be called when: 0058 * - Split view is activated in the active tab 0059 * OR 0060 * - A switch to a tab that is already in split view mode is occurring 0061 */ 0062 void createSecondaryUrlNavigator(); 0063 0064 /** 0065 * Notify this widget of changes in geometry of the ViewContainers it tries to be 0066 * aligned with. 0067 */ 0068 void followViewContainersGeometry(QWidget *primaryViewContainer, QWidget *secondaryViewContainer = nullptr); 0069 0070 bool isInToolbar() const; 0071 0072 /** 0073 * @return the primary UrlNavigator. 0074 */ 0075 DolphinUrlNavigator *primaryUrlNavigator() const; 0076 /** 0077 * @return the secondary UrlNavigator and nullptr if it doesn't exist. 0078 */ 0079 DolphinUrlNavigator *secondaryUrlNavigator() const; 0080 0081 /** 0082 * Change the visibility of the secondary UrlNavigator including spacing. 0083 * @param visible Setting this to false will completely hide the secondary side of this 0084 * WidgetAction's QSplitter making the QSplitter effectively disappear. 0085 */ 0086 void setSecondaryNavigatorVisible(bool visible); 0087 0088 protected: 0089 /** 0090 * There should always ever be one navigatorsWidget for this action so 0091 * this method always returns the same widget and reparents it. 0092 * You normally don't have to use this method directly because 0093 * QWidgetAction::requestWidget() is used to obtain the navigatorsWidget 0094 * and to steal it from wherever it was prior. 0095 * @param parent the new parent of the navigatorsWidget. 0096 */ 0097 QWidget *createWidget(QWidget *parent) override; 0098 0099 /** @see QWidgetAction::deleteWidget() */ 0100 void deleteWidget(QWidget *widget) override; 0101 0102 private: 0103 /** 0104 * In Left-to-right languages the Primary side will be the left one. 0105 */ 0106 enum Side { Primary, Secondary }; 0107 /** 0108 * Used to create the navigatorWidgets for both sides of the QSplitter. 0109 */ 0110 QWidget *createNavigatorWidget(Side side) const; 0111 0112 /** 0113 * Used to retrieve the emptyTrashButtons for the navigatorWidgets on both sides. 0114 */ 0115 QPushButton *emptyTrashButton(Side side); 0116 0117 /** 0118 * Creates a new empty trash button. 0119 * @param urlNavigator Only when this UrlNavigator shows the trash directory 0120 * will the button be visible. 0121 * @param parent Aside from the usual QObject deletion mechanisms, 0122 * this parameter influences the positioning of dialog windows 0123 * pertaining to this trash button. 0124 */ 0125 QPushButton *newEmptyTrashButton(const DolphinUrlNavigator *urlNavigator, QWidget *parent) const; 0126 0127 /** 0128 * Used to retrieve the networkFolderButtons for the navigatorWidgets on 0129 * both sides. 0130 */ 0131 QPushButton *networkFolderButton(Side side); 0132 0133 /** 0134 * Creates a new add "network folder" button. 0135 * @param urlNavigator Only when this UrlNavigator shows the remote directory 0136 * will the button be visible. 0137 * @param parent The object that should be the button's parent. 0138 */ 0139 QPushButton *newNetworkFolderButton(const DolphinUrlNavigator *urlNavigator, QWidget *parent) const; 0140 0141 enum Position { Leading, Trailing }; 0142 /** 0143 * Used to retrieve both the leading and trailing spacing for the navigatorWidgets 0144 * on both sides. A secondary leading spacing does not exist. 0145 */ 0146 QWidget *spacing(Side side, Position position) const; 0147 0148 /** 0149 * Sets this action's text depending on the amount of visible UrlNavigators. 0150 */ 0151 void updateText(); 0152 0153 /** 0154 * The defaultWidget() of this QWidgetAction. 0155 */ 0156 std::unique_ptr<QSplitter> m_splitter; 0157 0158 /** 0159 * adjustSpacing() has to be called slightly later than when urlChanged is emitted. 0160 * This timer bridges that time. 0161 */ 0162 std::unique_ptr<QTimer> m_adjustSpacingTimer; 0163 0164 /** 0165 * Extracts the geometry information needed by adjustSpacing() from 0166 * ViewContainers. They are also monitored for size changes which 0167 * will lead to adjustSpacing() calls. 0168 */ 0169 class ViewGeometriesHelper : public QObject 0170 { 0171 public: 0172 /** 0173 * @param navigatorsWidget The QWidget of the navigatorsWidgetAction. 0174 * @param navigatorsWidgetAction is only used to call adjustSpacing() whenever that is 0175 * deemed necessary. 0176 */ 0177 ViewGeometriesHelper(QWidget *navigatorsWidget, DolphinNavigatorsWidgetAction *navigatorsWidgetAction); 0178 0179 /** 0180 * Calls m_navigatorsWidgetAction::adjustSpacing() when a watched object is resized. 0181 */ 0182 bool eventFilter(QObject *watched, QEvent *event) override; 0183 0184 /** 0185 * Sets the ViewContainers whose geometry is obtained when viewGeometries() is called. 0186 */ 0187 void setViewContainers(QWidget *primaryViewContainer, QWidget *secondaryViewContainer = nullptr); 0188 0189 struct Geometries { 0190 int globalXOfNavigatorsWidget; 0191 int globalXOfPrimary; 0192 int widthOfPrimary; 0193 int globalXOfSecondary; 0194 int widthOfSecondary; 0195 }; 0196 /** 0197 * @return a Geometries struct that contains values adjustSpacing() requires. 0198 */ 0199 Geometries viewGeometries(); 0200 0201 private: 0202 QWidget *m_navigatorsWidget; 0203 /** Is only used to call adjustSpacing() whenever that is deemed necessary. */ 0204 DolphinNavigatorsWidgetAction *m_navigatorsWidgetAction; 0205 0206 QPointer<QWidget> m_primaryViewContainer; 0207 QPointer<QWidget> m_secondaryViewContainer; 0208 }; 0209 0210 ViewGeometriesHelper m_viewGeometriesHelper; 0211 0212 /** 0213 * Used to check if the window has been resized. 0214 * @see ViewGeometriesHelper::eventFilter() for why this is needed. 0215 */ 0216 int m_previousWindowWidth = -1; 0217 }; 0218 0219 #endif // DOLPHINNAVIGATORSWIDGETACTION_H