1 /*  SPDX-License-Identifier: LGPL-2.0-or-later
2 
3     SPDX-FileCopyrightText: 2005 Christoph Cullmann <cullmann@kde.org>
4     SPDX-FileCopyrightText: 2002, 2003 Joseph Wenninger <jowenn@kde.org>
5 
6     SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #ifndef __KATE_MDI_H__
10 #define __KATE_MDI_H__
11 
12 #include <KTextEditor/Plugin>
13 
14 #include <KParts/MainWindow>
15 
16 #include <KMultiTabBar>
17 #include <KToggleAction>
18 #include <KXMLGUIClient>
19 
20 #include <QChildEvent>
21 #include <QEvent>
22 #include <QFrame>
23 #include <QPointer>
24 #include <QSplitter>
25 
26 #include <map>
27 #include <unordered_map>
28 #include <vector>
29 
30 class KActionMenu;
31 class QAction;
32 class QLabel;
33 class QPixmap;
34 class KConfigBase;
35 
36 namespace KTextEditor
37 {
38 class ConfigPageInterface;
39 }
40 
41 namespace KateMDI
42 {
43 class ToolView;
44 
45 class ToggleToolViewAction : public KToggleAction
46 {
47     Q_OBJECT
48 
49 public:
50     ToggleToolViewAction(const QString &text, ToolView *tv, QObject *parent);
51 
52 protected Q_SLOTS:
53     void slotToggled(bool) override;
54     void toolVisibleChanged(bool);
55 
56 private:
57     ToolView *m_tv;
58 };
59 
60 class GUIClient : public QObject, public KXMLGUIClient
61 {
62     Q_OBJECT
63 
64 public:
65     GUIClient(class MainWindow *mw);
66 
67     void registerToolView(ToolView *tv);
68     void unregisterToolView(ToolView *tv);
69     void updateSidebarsVisibleAction();
70 
71 private Q_SLOTS:
72     void clientAdded(KXMLGUIClient *client);
73     void updateActions();
74 
75 private:
76     MainWindow *m_mw;
77     KToggleAction *m_showSidebarsAction;
78     std::vector<QAction *> m_toolViewActions;
79     std::unordered_map<ToolView *, QAction *> m_toolToAction;
80     KActionMenu *m_toolMenu;
81 };
82 
83 class ToolView : public QFrame
84 {
85     Q_OBJECT
86 
87     friend class Sidebar;
88     friend class MainWindow;
89     friend class GUIClient;
90     friend class ToggleToolViewAction;
91 
92 protected:
93     /**
94      * ToolView
95      * Objects of this clas represent a toolview in the mainwindow
96      * you should only add one widget as child to this toolview, it will
97      * be automatically set to be the focus proxy of the toolview
98      * @param mainwin main window for this toolview
99      * @param sidebar sidebar of this toolview
100      * @param parent parent widget, e.g. the splitter of one of the sidebars
101      */
102     ToolView(class MainWindow *mainwin, class Sidebar *sidebar, QWidget *parent);
103 
104 public:
105     /**
106      * destruct me, this is allowed for all, will care itself that the toolview is removed
107      * from the mainwindow and sidebar
108      */
109     ~ToolView() override;
110 
111 Q_SIGNALS:
112     /**
113      * toolview hidden or shown
114      * @param visible is this toolview made visible?
115      */
116     void toolVisibleChanged(bool visible);
117 
118     /**
119      * some internal methodes needed by the main window and the sidebars
120      */
121 protected:
mainWindow()122     MainWindow *mainWindow()
123     {
124         return m_mainWin;
125     }
126 
sidebar()127     Sidebar *sidebar()
128     {
129         return m_sidebar;
130     }
131 
132     void setToolVisible(bool vis);
133 
134 public:
135     bool toolVisible() const;
136     QSize sizeHint() const override;
137     QSize minimumSizeHint() const override;
138 
139 protected:
140     void childEvent(QChildEvent *ev) override;
141     void actionEvent(QActionEvent *event) override;
142 
143 private:
144     MainWindow *m_mainWin;
145     Sidebar *m_sidebar;
146     KToolBar *m_toolbar;
147 
148     /// plugin this view belongs to, may be 0
149     QPointer<KTextEditor::Plugin> plugin;
150 
151     /**
152      * unique id
153      */
154     QString id;
155 
156     /**
157      * is visible in sidebar
158      */
159     bool m_toolVisible;
160 
161     /**
162      * is this view persistent?
163      */
164     bool persistent;
165 
166     QIcon icon;
167     QString text;
168 };
169 
170 class Sidebar : public KMultiTabBar
171 {
172     Q_OBJECT
173 
174 public:
175     Sidebar(KMultiTabBar::KMultiTabBarPosition pos, class MainWindow *mainwin, QWidget *parent);
176 
177     void setSplitter(QSplitter *sp);
178 
179     /**
180      * Monitor resizes using the mouse and update the last size accordingly.
181      * Only call this when the sidebar has siblings in the splitter (i.e. m_splitter->count() >= 2) to guarantee that resize handles exist
182      */
183     void updateLastSizeOnResize();
184 
185 public:
186     ToolView *addWidget(const QIcon &icon, const QString &text, ToolView *widget);
187     bool removeWidget(ToolView *widget);
188 
189     bool showWidget(ToolView *widget);
190     bool hideWidget(ToolView *widget);
191 
192     bool isCollapsed();
193     void handleCollapse(int pos, int index);
194     void expandSidebar(ToolView *widget);
195 
setLastSize(int s)196     void setLastSize(int s)
197     {
198         m_lastSize = s;
199     }
lastSize()200     int lastSize() const
201     {
202         return m_lastSize;
203     }
204     void updateLastSize();
205 
splitterVisible()206     bool splitterVisible() const
207     {
208         return m_ownSplit->isVisible();
209     }
210 
211     void restoreSession();
212 
213     /**
214      * restore the current session config from given object, use current group
215      * @param config config object to use
216      */
217     void restoreSession(KConfigGroup &config);
218 
219     /**
220      * save the current session config to given object, use current group
221      * @param config config object to use
222      */
223     void saveSession(KConfigGroup &config);
224 
225 public Q_SLOTS:
226     // reimplemented, to block a show() call if all sidebars are forced hidden
227     void setVisible(bool visible) override;
228 private Q_SLOTS:
229     void tabClicked(int);
230 
231 protected:
232     bool eventFilter(QObject *obj, QEvent *ev) override;
233 
234 private Q_SLOTS:
235     void buttonPopupActivate(QAction *);
236 
237 private:
238     MainWindow *m_mainWin;
239 
240     KMultiTabBar::KMultiTabBarPosition m_pos{};
241     QSplitter *m_splitter;
242     KMultiTabBar *m_tabBar = nullptr;
243     QSplitter *m_ownSplit;
244 
245     std::map<int, ToolView *> m_idToWidget;
246     std::map<ToolView *, int> m_widgetToId;
247     std::map<ToolView *, QSize> m_widgetToSize;
248 
249     /**
250      * list of all toolviews around in this sidebar
251      */
252     std::vector<ToolView *> m_toolviews;
253 
254     int m_lastSize;
255 
256     QSize m_preHideSize;
257 
258     int m_popupButton = 0;
259 
260     QLabel *m_resizePlaceholder;
261     bool m_isPreviouslyCollapsed = false;
262 
263 Q_SIGNALS:
264     void sigShowPluginConfigPage(KTextEditor::Plugin *configpageinterface, int id);
265 };
266 
267 class MainWindow : public KParts::MainWindow
268 {
269     Q_OBJECT
270 
271     friend class ToolView;
272 
273     //
274     // Constructor area
275     //
276 public:
277     /**
278      * Constructor
279      */
280     MainWindow(QWidget *parentWidget = nullptr);
281 
282     /**
283      * Destructor
284      */
285     ~MainWindow() override;
286 
287     //
288     // public interfaces
289     //
290 
291     /**
292      * add a given widget to the given sidebar if possible, name is very important
293      * @param plugin pointer to the plugin
294      * @param identifier unique identifier for this toolview
295      * @param pos position for the toolview, if we are in session restore, this is only a preference
296      * @param icon icon to use for the toolview
297      * @param text text to use in addition to icon
298      * @return created toolview on success or 0
299      */
300     ToolView *
301     createToolView(KTextEditor::Plugin *plugin, const QString &identifier, KMultiTabBar::KMultiTabBarPosition pos, const QIcon &icon, const QString &text);
302 
303     /**
304      * give you handle to toolview for the given name, 0 if no toolview around
305      * @param identifier toolview name
306      * @return toolview if existing, else 0
307      */
308     ToolView *toolView(const QString &identifier) const;
309 
310     /**
311      * set the toolview's tabbar style.
312      * @param style the tabbar style.
313      */
314     void setToolViewStyle(KMultiTabBar::KMultiTabBarStyle style);
315 
316     /**
317      * get the toolview's tabbar style. Call this before @p startRestore(),
318      * otherwise you overwrite the usersettings.
319      * @return toolview's tabbar style
320      */
321     KMultiTabBar::KMultiTabBarStyle toolViewStyle() const;
322 
323     /**
324      * get the sidebars' visibility.
325      * @return false, if the sidebars' visibility is forced hidden, otherwise true
326      */
327     bool sidebarsVisible() const;
328 
329 public Q_SLOTS:
330     /**
331      * set the sidebars' visibility to @p visible. If false, the sidebars
332      * are @e always hidden. Usually you do not have to call this because
333      * the user can set this in the menu.
334      * @param visible sidebars visibility
335      */
336     void setSidebarsVisible(bool visible);
337 
338 protected:
339     /**
340      * called by toolview destructor
341      * @param widget toolview which is destroyed
342      */
343     void toolViewDeleted(ToolView *widget);
344 
345     /**
346      * central widget ;)
347      * use this as parent for your content
348      * this widget will get focus if a toolview is hidden
349      * @return central widget
350      */
351     QWidget *centralWidget() const;
352 
353     /**
354      * modifiers for existing toolviews
355      */
356 public:
357     /**
358      * move a toolview around
359      * @param widget toolview to move
360      * @param pos position to move too, during session restore, only preference
361      * @return success
362      */
363     bool moveToolView(ToolView *widget, KMultiTabBar::KMultiTabBarPosition pos);
364 
365     /**
366      * show given toolview, discarded while session restore
367      * @param widget toolview to show
368      * @return success
369      */
370     bool showToolView(ToolView *widget);
371 
372     /**
373      * hide given toolview, discarded while session restore
374      * @param widget toolview to hide
375      * @return success
376      */
377     bool hideToolView(ToolView *widget);
378 
379     /**
380      * session saving and restore stuff
381      */
382 public:
383     /**
384      * start the restore
385      * @param config config object to use
386      * @param group config group to use
387      */
388     void startRestore(KConfigBase *config, const QString &group);
389 
390     /**
391      * finish the restore
392      */
393     void finishRestore();
394 
395     /**
396      * save the current session config to given object and group
397      * @param group config group to use
398      */
399     void saveSession(KConfigGroup &group);
400 
401     /**
402      * internal data ;)
403      */
404 private:
405     /**
406      * map identifiers to widgets
407      */
408     std::map<QString, ToolView *> m_idToWidget;
409 
410     /**
411      * list of all toolviews around
412      */
413     std::vector<ToolView *> m_toolviews;
414 
415     /**
416      * widget, which is the central part of the
417      * main window ;)
418      */
419     QWidget *m_centralWidget;
420 
421     /**
422      * horizontal splitter
423      */
424     QSplitter *m_hSplitter;
425 
426     /**
427      * vertical splitter
428      */
429     QSplitter *m_vSplitter;
430 
431     /**
432      * sidebars for the four sides
433      */
434     std::unique_ptr<Sidebar> m_sidebars[4];
435 
436     /**
437      * sidebars state.
438      */
439     bool m_sidebarsVisible = true;
440 
441     /**
442      * config object for session restore, only valid between
443      * start and finish restore calls
444      */
445     KConfigBase *m_restoreConfig = nullptr;
446 
447     /**
448      * restore group
449      */
450     QString m_restoreGroup;
451 
452     /**
453      * out guiclient
454      */
455     GUIClient *m_guiClient;
456 
457 Q_SIGNALS:
458     void sigShowPluginConfigPage(KTextEditor::Plugin *configpageinterface, int id);
459 };
460 
461 }
462 
463 #endif
464