dolphinnavigatorswidgetaction.h 7.8 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
/*
    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"

13
#include <QPointer>
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
#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.
34
35
 * - Each NavigatorWidget consists an UrlNavigator, an emptyTrashButton, a
 *   networkFolderButton, and spacing.
36
37
38
39
40
41
42
43
44
45
 * - 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

public:
    DolphinNavigatorsWidgetAction(QWidget *parent = nullptr);

46
47
48
49
50
51
52
    /**
     * 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();

53
    /**
54
55
56
57
58
59
60
     * The secondary UrlNavigator is only created on-demand. Such an action is not necessary
     * for the primary UrlNavigator which is created preemptively.
     *
     * This method should preferably only be called when:
     * - Split view is activated in the active tab
     * OR
     * - A switch to a tab that is already in split view mode is occuring
61
62
63
64
65
66
67
     */
    void createSecondaryUrlNavigator();

    /**
     * Notify this widget of changes in geometry of the ViewContainers it tries to be
     * aligned with.
     */
68
69
    void followViewContainersGeometry(QWidget *primaryViewContainer,
                                      QWidget *secondaryViewContainer = nullptr);
70

71
72
    bool isInToolbar() const;

73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
    /**
     * @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);

89
90
91
92
93
94
95
96
97
98
99
100
101
102
protected:
    /**
     * There should always ever be one navigatorsWidget for this action so
     * this method always returns the same widget and reparents it.
     * You normally don't have to use this method directly because
     * QWidgetAction::requestWidget() is used to obtain the navigatorsWidget
     * and to steal it from whereever it was prior.
     * @param parent the new parent of the navigatorsWidget.
     */
    QWidget *createWidget(QWidget *parent) override;

    /** @see QWidgetAction::deleteWidget() */
    void deleteWidget(QWidget *widget) override;

103
104
105
106
107
108
109
110
private:
    /**
     * In Left-to-right languages the Primary side will be the left one.
     */
    enum Side {
        Primary,
        Secondary
    };
111
112
113
114
115
116
117
118
119
120
121
122
123
    /**
     * 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
Nate Graham's avatar
Nate Graham committed
124
     *                     will the button be visible.
125
126
127
128
129
130
     * @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;

131
132
133
134
135
136
137
138
139
140
141
142
143
144
    /**
     * Used to retrieve the networkFolderButtons for the navigatorWidgets on
     * both sides.
     */
    QPushButton *networkFolderButton(Side side);

    /**
     * Creates a new add "network folder" button.
     * @param urlNavigator Only when this UrlNavigator shows the remote directory
     *                     will the button be visible.
     * @param parent       The object that should be the button's parent.
     */
    QPushButton *newNetworkFolderButton(const DolphinUrlNavigator *urlNavigator, QWidget *parent) const;

145
146
147
148
149
150
151
152
153
154
    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;

155
156
157
158
159
    /**
     * Sets this action's text depending on the amount of visible UrlNavigators.
     */
    void updateText();

160
161
162
163
164
165
166
167
168
169
170
    /**
     * 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;

171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
    /**
     * 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<QWidget> m_primaryViewContainer;
        QPointer<QWidget> m_secondaryViewContainer;
    };

    ViewGeometriesHelper m_viewGeometriesHelper;
219
220
221
222
223
224

    /**
     * Used to check if the window has been resized.
     * @see ViewGeometriesHelper::eventFilter() for why this is needed.
     */
    int m_previousWindowWidth = -1;
225
226
227
};

#endif // DOLPHINNAVIGATORSWIDGETACTION_H