]> cloud.milkyroute.net Git - dolphin.git/blob - src/dolphinnavigatorswidgetaction.h
Fix location bar being wrongly aligned on first startup
[dolphin.git] / src / dolphinnavigatorswidgetaction.h
1 /*
2 This file is part of the KDE project
3 SPDX-FileCopyrightText: 2020 Felix Ernst <fe.a.ernst@gmail.com>
4
5 SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 */
7
8 #ifndef DOLPHINNAVIGATORSWIDGETACTION_H
9 #define DOLPHINNAVIGATORSWIDGETACTION_H
10
11 #include "dolphinurlnavigator.h"
12
13 #include <QPointer>
14 #include <QSplitter>
15 #include <QTimer>
16 #include <QWidgetAction>
17
18 #include <memory>
19
20 class KXmlGuiWindow;
21 class QPushButton;
22
23 /**
24 * @brief QWidgetAction that allows to use DolphinUrlNavigators in a toolbar.
25 *
26 * This class is mainly a container that manages up to two DolphinUrlNavigator objects so they
27 * can be added to a toolbar. It also deals with alignment.
28 *
29 * The structure of the defaultWidget() of this QWidgetAction is as follows:
30 * - A QSplitter manages up to two sides which each correspond to one DolphinViewContainer.
31 * The secondary side only exists for split view and is created by
32 * createSecondaryUrlNavigator() when necessary.
33 * - Each side is a QWidget which I call NavigatorWidget with a QHBoxLayout.
34 * - Each NavigatorWidget consists an UrlNavigator, an emptyTrashButton and spacing.
35 * - Only the primary navigatorWidget has leading spacing. Both have trailing spacing.
36 * The spacing is there to align the UrlNavigator with its DolphinViewContainer.
37 */
38 class DolphinNavigatorsWidgetAction : public QWidgetAction
39 {
40 Q_OBJECT
41
42 public:
43 DolphinNavigatorsWidgetAction(QWidget *parent = nullptr);
44
45 /**
46 * Adjusts the width of the spacings used to align the UrlNavigators with ViewContainers.
47 * This can only work nicely if up-to-date geometry of ViewContainers is cached so
48 * followViewContainersGeometry() has to have been called at least once before.
49 */
50 void adjustSpacing();
51
52 /**
53 * The secondary UrlNavigator is only created on-demand. Such an action is not necessary
54 * for the primary UrlNavigator which is created preemptively.
55 *
56 * This method should preferably only be called when:
57 * - Split view is activated in the active tab
58 * OR
59 * - A switch to a tab that is already in split view mode is occuring
60 */
61 void createSecondaryUrlNavigator();
62
63 /**
64 * Notify this widget of changes in geometry of the ViewContainers it tries to be
65 * aligned with.
66 */
67 void followViewContainersGeometry(QWidget *primaryViewContainer,
68 QWidget *secondaryViewContainer = nullptr);
69
70 bool isInToolbar() const;
71
72 /**
73 * @return the primary UrlNavigator.
74 */
75 DolphinUrlNavigator *primaryUrlNavigator() const;
76 /**
77 * @return the secondary UrlNavigator and nullptr if it doesn't exist.
78 */
79 DolphinUrlNavigator *secondaryUrlNavigator() const;
80
81 /**
82 * Change the visibility of the secondary UrlNavigator including spacing.
83 * @param visible Setting this to false will completely hide the secondary side of this
84 * WidgetAction's QSplitter making the QSplitter effectively disappear.
85 */
86 void setSecondaryNavigatorVisible(bool visible);
87
88 protected:
89 /**
90 * There should always ever be one navigatorsWidget for this action so
91 * this method always returns the same widget and reparents it.
92 * You normally don't have to use this method directly because
93 * QWidgetAction::requestWidget() is used to obtain the navigatorsWidget
94 * and to steal it from whereever it was prior.
95 * @param parent the new parent of the navigatorsWidget.
96 */
97 QWidget *createWidget(QWidget *parent) override;
98
99 /** @see QWidgetAction::deleteWidget() */
100 void deleteWidget(QWidget *widget) override;
101
102 private:
103 /**
104 * In Left-to-right languages the Primary side will be the left one.
105 */
106 enum Side {
107 Primary,
108 Secondary
109 };
110 /**
111 * Used to create the navigatorWidgets for both sides of the QSplitter.
112 */
113 QWidget *createNavigatorWidget(Side side) const;
114
115 /**
116 * Used to retrieve the emptyTrashButtons for the navigatorWidgets on both sides.
117 */
118 QPushButton *emptyTrashButton(Side side);
119
120 /**
121 * Creates a new empty trash button.
122 * @param urlNavigator Only when this UrlNavigator shows the trash directory
123 * will the button be visible.
124 * @param parent Aside from the usual QObject deletion mechanisms,
125 * this parameter influences the positioning of dialog windows
126 * pertaining to this trash button.
127 */
128 QPushButton *newEmptyTrashButton(const DolphinUrlNavigator *urlNavigator, QWidget *parent) const;
129
130 enum Position {
131 Leading,
132 Trailing
133 };
134 /**
135 * Used to retrieve both the leading and trailing spacing for the navigatorWidgets
136 * on both sides. A secondary leading spacing does not exist.
137 */
138 QWidget *spacing(Side side, Position position) const;
139
140 /**
141 * Sets this action's text depending on the amount of visible UrlNavigators.
142 */
143 void updateText();
144
145 /**
146 * The defaultWidget() of this QWidgetAction.
147 */
148 std::unique_ptr<QSplitter> m_splitter;
149
150 /**
151 * adjustSpacing() has to be called slightly later than when urlChanged is emitted.
152 * This timer bridges that time.
153 */
154 std::unique_ptr<QTimer> m_adjustSpacingTimer;
155
156 /**
157 * Extracts the geometry information needed by adjustSpacing() from
158 * ViewContainers. They are also monitored for size changes which
159 * will lead to adjustSpacing() calls.
160 */
161 class ViewGeometriesHelper : public QObject
162 {
163 public:
164 /**
165 * @param navigatorsWidget The QWidget of the navigatorsWidgetAction.
166 * @param navigatorsWidgetAction is only used to call adjustSpacing() whenever that is
167 * deemed necessary.
168 */
169 ViewGeometriesHelper(QWidget *navigatorsWidget, DolphinNavigatorsWidgetAction *navigatorsWidgetAction);
170
171 /**
172 * Calls m_navigatorsWidgetAction::adjustSpacing() when a watched object is resized.
173 */
174 bool eventFilter(QObject *watched, QEvent *event) override;
175
176 /**
177 * Sets the ViewContainers whose geometry is obtained when viewGeometries() is called.
178 */
179 void setViewContainers(QWidget *primaryViewContainer,
180 QWidget *secondaryViewContainer = nullptr);
181
182 struct Geometries {
183 int globalXOfNavigatorsWidget;
184 int globalXOfPrimary;
185 int widthOfPrimary;
186 int globalXOfSecondary;
187 int widthOfSecondary;
188 };
189 /**
190 * @return a Geometries struct that contains values adjustSpacing() requires.
191 */
192 Geometries viewGeometries();
193
194 private:
195 QWidget *m_navigatorsWidget;
196 /** Is only used to call adjustSpacing() whenever that is deemed necessary. */
197 DolphinNavigatorsWidgetAction *m_navigatorsWidgetAction;
198
199 QPointer<QWidget> m_primaryViewContainer;
200 QPointer<QWidget> m_secondaryViewContainer;
201 };
202
203 ViewGeometriesHelper m_viewGeometriesHelper;
204 };
205
206 #endif // DOLPHINNAVIGATORSWIDGETACTION_H