1 /*
2     This file is part of the KDE project
3     SPDX-FileCopyrightText: 1999 Simon Hausmann <hausmann@kde.org>
4     SPDX-FileCopyrightText: 1999 David Faure <faure@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #ifndef __kpartmanager_h__
10 #define __kpartmanager_h__
11 
12 #include <kparts/kparts_export.h>
13 
14 #include <QWidget>
15 #include <memory>
16 
17 namespace KParts
18 {
19 class Part;
20 
21 class PartManagerPrivate;
22 
23 /**
24  * @class PartManager partmanager.h <KParts/PartManager>
25  *
26  * @short The part manager is an object which knows about a collection of parts
27  * (even nested ones) and handles activation/deactivation.
28  *
29  * Applications that want to embed parts without merging GUIs
30  * only use a KParts::PartManager. Those who want to merge GUIs use a
31  * KParts::MainWindow for example, in addition to a part manager.
32  *
33  * Parts know about the part manager to add nested parts to it.
34  * See also KParts::Part::manager() and KParts::Part::setManager().
35  */
36 class KPARTS_EXPORT PartManager : public QObject
37 {
38     Q_OBJECT
39     Q_PROPERTY(SelectionPolicy selectionPolicy READ selectionPolicy WRITE setSelectionPolicy)
40     Q_PROPERTY(bool allowNestedParts READ allowNestedParts WRITE setAllowNestedParts)
41     Q_PROPERTY(bool ignoreScrollBars READ ignoreScrollBars WRITE setIgnoreScrollBars)
42 public:
43     /// Selection policy. The default policy of a PartManager is Direct.
44     enum SelectionPolicy { Direct, TriState };
45     Q_ENUM(SelectionPolicy)
46 
47     /**
48      * This extends QFocusEvent::Reason with the non-focus-event reasons for partmanager to activate a part.
49      * To test for "any focusin reason", use < ReasonLeftClick
50      * NoReason usually means: explicit activation with @ref setActivePart.
51      */
52     enum Reason { ReasonLeftClick = 100, ReasonMidClick, ReasonRightClick, NoReason };
53 
54     /**
55      * Constructs a part manager.
56      *
57      * @param parent The toplevel widget (window / dialog) the
58      *               partmanager should monitor for activation/selection
59      *               events
60      */
61     PartManager(QWidget *parent);
62     /**
63      * Constructs a part manager.
64      *
65      * @param topLevel The toplevel widget (window / dialog ) the
66      *                 partmanager should monitor for activation/selection
67      *                 events
68      * @param parent   The parent QObject.
69      */
70     PartManager(QWidget *topLevel, QObject *parent);
71     ~PartManager() override;
72 
73     /**
74      * Sets the selection policy of the partmanager.
75      */
76     void setSelectionPolicy(SelectionPolicy policy);
77     /**
78      * Returns the current selection policy.
79      */
80     SelectionPolicy selectionPolicy() const;
81 
82     /**
83      * Specifies whether the partmanager should handle/allow nested parts
84      * or not.
85      *
86      *  This is a property the shell has to set/specify. Per
87      * default we assume that the shell cannot handle nested
88      * parts. However in case of a KOffice shell for example we allow
89      * nested parts.  A Part is nested (a child part) if its parent
90      * object inherits KParts::Part.  If a child part is activated and
91      * nested parts are not allowed/handled, then the top parent part in
92      * the tree is activated.
93      */
94     void setAllowNestedParts(bool allow);
95     /**
96      * @see setAllowNestedParts
97      */
98     bool allowNestedParts() const;
99 
100     /**
101      * Specifies whether the partmanager should ignore mouse click events for
102      * scrollbars or not. If the partmanager ignores them, then clicking on the
103      * scrollbars of a non-active/non-selected part will not change the selection
104      * or activation state.
105      *
106      * The default value is false (read: scrollbars are NOT ignored).
107      */
108     void setIgnoreScrollBars(bool ignore);
109     /**
110      * @see setIgnoreScrollBars
111      */
112     bool ignoreScrollBars() const;
113 
114     /**
115      * Specifies which mouse buttons the partmanager should react upon.
116      * By default it reacts on all mouse buttons (LMB/MMB/RMB).
117      * @param buttonMask a combination of Qt::ButtonState values e.g. Qt::LeftButton | Qt::MiddleButton
118      */
119     void setActivationButtonMask(short int buttonMask);
120     /**
121      * @see setActivationButtonMask
122      */
123     short int activationButtonMask() const;
124 
125     /**
126      * @internal
127      */
128     bool eventFilter(QObject *obj, QEvent *ev) override;
129 
130     /**
131      * Adds a part to the manager.
132      *
133      * Sets it to the active part automatically if @p setActive is true (default).
134      */
135     virtual void addPart(Part *part, bool setActive = true);
136 
137     /**
138      * Removes a part from the manager (this does not delete the object) .
139      *
140      * Sets the active part to 0 if @p part is the activePart() .
141      */
142     virtual void removePart(Part *part);
143 
144     /**
145      * Replaces @p oldPart with @p newPart, and sets @p newPart as active if
146      * @p setActive is true.
147      * This is an optimised version of removePart + addPart
148      */
149     virtual void replacePart(Part *oldPart, Part *newPart, bool setActive = true);
150 
151     /**
152      * Sets the active part.
153      *
154      * The active part receives activation events.
155      *
156      * @p widget can be used to specify which widget was responsible for the activation.
157      * This is important if you have multiple views for a document/part , like in KOffice .
158      */
159     virtual void setActivePart(Part *part, QWidget *widget = nullptr);
160 
161     /**
162      * Returns the active part.
163      **/
164     virtual Part *activePart() const;
165 
166     /**
167      * Returns the active widget of the current active part (see activePart ).
168      */
169     virtual QWidget *activeWidget() const;
170 
171 #if KPARTS_BUILD_DEPRECATED_SINCE(5, 72)
172     /**
173      * Sets the selected part.
174      *
175      * The selected part receives selection events.
176      *
177      * @p widget can be used to specify which widget was responsible for the selection.
178      * This is important if you have multiple views for a document/part , like in KOffice .
179      *
180      * @deprecated Since 5.72, for lack of usage.
181      */
182     KPARTS_DEPRECATED_VERSION(5, 72, "Deprecated for lack of usage")
183     virtual void setSelectedPart(Part *part, QWidget *widget = nullptr);
184 #endif
185 
186 #if KPARTS_BUILD_DEPRECATED_SINCE(5, 72)
187     /**
188      * Returns the current selected part.
189      *
190      * @deprecated Since 5.72, for lack of usage.
191      */
192     KPARTS_DEPRECATED_VERSION(5, 72, "Deprecated for lack of usage")
193     virtual Part *selectedPart() const;
194 #endif
195 
196 #if KPARTS_BUILD_DEPRECATED_SINCE(5, 72)
197     /**
198      * Returns the selected widget of the current selected part (see selectedPart ).
199      *
200      * @deprecated Since 5.72, for lack of usage.
201      */
202     KPARTS_DEPRECATED_VERSION(5, 72, "Deprecated for lack of usage")
203     virtual QWidget *selectedWidget() const;
204 #endif
205 
206     /**
207      * Returns the list of parts being managed by the partmanager.
208      */
209     const QList<Part *> parts() const;
210 
211     /**
212      * Adds the @p topLevel widget to the list of managed toplevel widgets.
213      * Usually a PartManager only listens for events (for activation/selection)
214      * for one toplevel widget (and its children) , the one specified in the
215      * constructor. Sometimes however (like for example when using the KDE dockwidget
216      * library) , it is necessary to extend this.
217      */
218     void addManagedTopLevelWidget(const QWidget *topLevel);
219     /**
220      * Removes the @p topLevel widget from the list of managed toplevel widgets.
221      * @see addManagedTopLevelWidget
222      */
223     void removeManagedTopLevelWidget(const QWidget *topLevel);
224 
225     /**
226      * @return the reason for the last activePartChanged signal emitted.
227      * @see Reason
228      */
229     int reason() const;
230 
231 Q_SIGNALS:
232     /**
233      * Emitted when a new part has been added.
234      * @see addPart()
235      **/
236     void partAdded(KParts::Part *part);
237     /**
238      * Emitted when a part has been removed.
239      * @see removePart()
240      **/
241     void partRemoved(KParts::Part *part);
242     /**
243      * Emitted when the active part has changed.
244      * @see setActivePart()
245      **/
246     void activePartChanged(KParts::Part *newPart);
247 
248 protected:
249     /**
250      * Sets whether the PartManager ignores explicit set focus requests
251      * from the part.
252      *
253      * By default this option is set to false. Set it to true to prevent
254      * the part from sending explicit set focus requests to the client
255      * application.
256      *
257      * @since 4.10
258      */
259     void setIgnoreExplictFocusRequests(bool);
260 
261 protected Q_SLOTS:
262     /**
263      * Removes a part when it is destroyed.
264      **/
265     void slotObjectDestroyed();
266 
267     /**
268      * @internal
269      */
270     void slotWidgetDestroyed();
271 
272     /**
273      * @internal
274      */
275     void slotManagedTopLevelWidgetDestroyed();
276 
277 private:
278     Part *findPartFromWidget(QWidget *widget, const QPoint &pos);
279     Part *findPartFromWidget(QWidget *widget);
280 
281 private:
282     std::unique_ptr<PartManagerPrivate> const d;
283 };
284 
285 }
286 
287 #endif
288