katemainwindow.h 16.4 KB
Newer Older
1
/* This file is part of the KDE project
2
3
4
   SPDX-FileCopyrightText: 2001 Christoph Cullmann <cullmann@kde.org>
   SPDX-FileCopyrightText: 2001 Joseph Wenninger <jowenn@kde.org>
   SPDX-FileCopyrightText: 2001 Anders Lund <anders.lund@lund.tdcadsl.dk>
5

6
   SPDX-License-Identifier: LGPL-2.0-only
7
8
9
10
11
12
*/

#ifndef __KATE_MAINWINDOW_H__
#define __KATE_MAINWINDOW_H__

#include "katemdi.h"
13
#include "kateviewmanager.h"
14

15
#include <ktexteditor/document.h>
16
#include <ktexteditor/mainwindow.h>
17
#include <ktexteditor/view.h>
18

Michal Humpula's avatar
Michal Humpula committed
19
#include <KParts/Part>
20
21
22

#include <QDragEnterEvent>
#include <QDropEvent>
23
#include <QEvent>
24
#include <QHash>
25
#include <QModelIndex>
26
#include <QStackedLayout>
27
#include <QStackedWidget>
Michal Humpula's avatar
Michal Humpula committed
28
#include <QUrl>
29
#include <QVBoxLayout>
30
31
32

class QMenu;

33
34
namespace KIO
{
35
36
class UDSEntry;
typedef class QList<UDSEntry> UDSEntryList;
37
}
38
39
40
41

class KFileItem;
class KRecentFilesAction;

42
class KateViewManager;
43
class KateMwModOnHdDialog;
44

45
46
47
// Helper layout class to always provide minimum size
class KateContainerStackedLayout : public QStackedLayout
{
48
    Q_OBJECT
49
public:
50
    KateContainerStackedLayout(QWidget *parent);
Kevin Funk's avatar
Kevin Funk committed
51
52
    QSize sizeHint() const override;
    QSize minimumSize() const override;
53
54
};

55
56
57
58
class KateMainWindow : public KateMDI::MainWindow, virtual public KParts::PartBase
{
    Q_OBJECT

59
public:
60
    /**
Vegard Øye's avatar
Vegard Øye committed
61
     * Construct the window and restore its state from given config if any
62
63
64
     * @param sconfig session config for this window, 0 if none
     * @param sgroup session config group to use
     */
65
    KateMainWindow(KConfig *sconfig, const QString &sgroup);
66
67
68
69

    /**
     * Destruct the nice window
     */
Kevin Funk's avatar
Kevin Funk committed
70
    ~KateMainWindow() override;
71
72
73
74

    /**
     * Accessor methodes for interface and child objects
     */
75
public:
76
77
    KateViewManager *viewManager()
    {
78
        return m_viewManager;
79
    }
80

81
82
83
84
    /**
     * KTextEditor::MainWindow wrapper
     * @return KTextEditor::MainWindow wrapper.
     */
85
86
    KTextEditor::MainWindow *wrapper()
    {
87
        return m_wrapper;
88
    }
89

90
public:
91
92
    /** Returns the URL of the current document.
     * anders: I add this for use from the file selector. */
Michal Humpula's avatar
Michal Humpula committed
93
    QUrl activeDocumentUrl();
94

95
96
97
    /** Enumeration to specify if files modified on disk should show up
     * in the reload dialog even if not edited in this instance. */
    enum ModOnDiskMode {
Christoph Cullmann's avatar
Christoph Cullmann committed
98
        PromptEdited, ///< Do not list files that have not been edited
Alexander Lohnau's avatar
Alexander Lohnau committed
99
        PromptAll, ///< Include all files modified on disk
100
101
    };

102
103
104
105
106
107
108
    /**
     * Prompts the user for what to do with files that are modified on disk if any.
     * This is optionally run when the window receives focus, and when the last
     * window is closed.
     * @return true if no documents are modified on disk, or all documents were
     * handled by the dialog; otherwise (the dialog was canceled) false.
     */
109
    bool showModOnDiskPrompt(ModOnDiskMode mode);
110

111
public:
Kevin Funk's avatar
Kevin Funk committed
112
113
114
    /*reimp*/ void readProperties(const KConfigGroup &config) override;
    /*reimp*/ void saveProperties(KConfigGroup &config) override;
    /*reimp*/ void saveGlobalProperties(KConfig *sessionConfig) override;
115

116
117
118
    void saveOpenRecent(KConfig *config);
    void loadOpenRecent(const KConfig *config);

119
public:
120
    bool queryClose_internal(KTextEditor::Document *doc = nullptr);
121

122
123
124
125
126
127
128
129
130
131
132
    /**
     * save the settings, size and state of this window in
     * the provided config group
     */
    void saveWindowConfig(const KConfigGroup &);
    /**
     * restore the settings, size and state of this window from
     * the provided config group.
     */
    void restoreWindowConfig(const KConfigGroup &);

Christoph Cullmann's avatar
Christoph Cullmann committed
133
134
135
136
137
    /**
     * save some global options to katerc
     */
    void saveOptions();

138
private:
139
140
141
    /**
     * Setup actions which pointers are needed already in setupMainWindow
     */
142
    void setupImportantActions();
143
144
145

    void setupMainWindow();
    void setupActions();
Kevin Funk's avatar
Kevin Funk committed
146
    bool queryClose() override;
147

148
149
150
    void addMenuBarActionToContextMenu();
    void removeMenuBarActionFromContextMenu();

151
152
153
154
155
    /**
     * read some global options from katerc
     */
    void readOptions();

Kevin Funk's avatar
Kevin Funk committed
156
157
    void dragEnterEvent(QDragEnterEvent *) override;
    void dropEvent(QDropEvent *) override;
158

159
public Q_SLOTS:
Christoph Cullmann's avatar
erlend:    
Christoph Cullmann committed
160
    void slotFileClose();
161
    void slotFileQuit();
162
    void queueModifiedOnDisc(KTextEditor::Document *doc);
163

164
165
166
    void slotFocusPrevTab();
    void slotFocusNextTab();

167
    /**
168
     * Show quick open
169
     */
170
    void slotQuickOpen();
Christoph Cullmann's avatar
Christoph Cullmann committed
171

Waqar Ahmed's avatar
Waqar Ahmed committed
172
173
    void slotCommandBarOpen();

174
175
176
177
    /**
     * Overwrite size hint for better default window sizes
     * @return size hint
     */
Kevin Funk's avatar
Kevin Funk committed
178
    QSize sizeHint() const override;
179

180
181
182
183
184
185
    /**
     * slots used for actions in the menus/toolbars
     * or internal signal connections
     */
private Q_SLOTS:
    void newWindow();
186
187
188

    void slotConfigure();

189
    void slotOpenWithMenuAction(QAction *a);
190
191
192
193

    void slotEditToolbars();
    void slotNewToolbarConfig();
    void slotUpdateOpenWith();
194
    void slotUpdateActionsNeedingUrl();
Laurent Montel's avatar
Laurent Montel committed
195
    void slotOpenDocument(const QUrl &);
196
197
198
199

    void slotDropEvent(QDropEvent *);
    void editKeys();
    void mSlotFixOpenWithMenu();
200
    void reloadXmlGui();
201
202

    /* to update the caption */
203
204
    void slotDocumentCreated(KTextEditor::Document *doc);
    void updateCaption(KTextEditor::Document *doc);
205
    // calls updateCaption(doc) with the current document
206
    void updateCaption();
207

208
    void pluginHelp();
209
210
    void slotFullScreen(bool);

211
212
    void slotListRecursiveEntries(KIO::Job *job, const KIO::UDSEntryList &list);

213
private Q_SLOTS:
214
    void toggleShowMenuBar(bool showMessage = true);
215
    void toggleShowStatusBar();
Christoph Cullmann's avatar
Christoph Cullmann committed
216
    void toggleShowTabBar();
217

218
219
public:
    bool showStatusBar();
Christoph Cullmann's avatar
Christoph Cullmann committed
220
    bool showTabBar();
221

222
223
Q_SIGNALS:
    void statusBarToggled();
Christoph Cullmann's avatar
Christoph Cullmann committed
224
    void tabBarToggled();
225
    void unhandledShortcutOverride(QEvent *e);
226

227
228
public:
    void openUrl(const QString &name = QString());
229

Christoph Cullmann's avatar
Christoph Cullmann committed
230
231
    QHash<KTextEditor::Plugin *, QObject *> &pluginViews()
    {
232
        return m_pluginViews;
233
234
    }

Christoph Cullmann's avatar
Christoph Cullmann committed
235
236
    QWidget *bottomViewBarContainer()
    {
237
238
        return m_bottomViewBarContainer;
    }
Christoph Cullmann's avatar
Christoph Cullmann committed
239
240
241

    void addToBottomViewBarContainer(KTextEditor::View *view, QWidget *bar)
    {
242
243
244
        m_bottomContainerStack->addWidget(bar);
        m_bottomViewBarMapping[view] = BarState(bar);
    }
Christoph Cullmann's avatar
Christoph Cullmann committed
245
246
247
248
249
250
251

    void hideBottomViewBarForView(KTextEditor::View *view)
    {
        BarState &state = m_bottomViewBarMapping[view];
        if (state.bar()) {
            m_bottomContainerStack->setCurrentWidget(state.bar());
            state.bar()->hide();
252
            state.setState(false);
Christoph Cullmann's avatar
Christoph Cullmann committed
253
254
        }
        m_bottomViewBarContainer->hide();
255
    }
Christoph Cullmann's avatar
Christoph Cullmann committed
256
257
258
259
260
261
262

    void showBottomViewBarForView(KTextEditor::View *view)
    {
        BarState &state = m_bottomViewBarMapping[view];
        if (state.bar()) {
            m_bottomContainerStack->setCurrentWidget(state.bar());
            state.bar()->show();
263
264
265
266
            state.setState(true);
            m_bottomViewBarContainer->show();
        }
    }
Christoph Cullmann's avatar
Christoph Cullmann committed
267
268
269

    void deleteBottomViewBarForView(KTextEditor::View *view)
    {
270
        BarState state = m_bottomViewBarMapping.take(view);
Christoph Cullmann's avatar
Christoph Cullmann committed
271
272
        if (state.bar()) {
            if (m_bottomContainerStack->currentWidget() == state.bar()) {
273
                m_bottomViewBarContainer->hide();
Christoph Cullmann's avatar
Christoph Cullmann committed
274
275
            }
            delete state.bar();
276
277
        }
    }
Christoph Cullmann's avatar
jowenn:    
Christoph Cullmann committed
278

279
280
    bool modNotificationEnabled() const
    {
281
        return m_modNotification;
Christoph Cullmann's avatar
Christoph Cullmann committed
282
283
    }

284
285
    void setModNotificationEnabled(bool e)
    {
286
        m_modNotification = e;
Christoph Cullmann's avatar
Christoph Cullmann committed
287
288
    }

289
290
    bool modCloseAfterLast() const
    {
291
292
293
        return m_modCloseAfterLast;
    }

294
295
    void setModCloseAfterLast(bool e)
    {
296
297
298
        m_modCloseAfterLast = e;
    }

299
300
301
302
303
    /**
     * add given url to list of recently opened files
     * @param url url that got opened
     */
    void addRecentOpenedFile(const QUrl &url);
Christoph Cullmann's avatar
Christoph Cullmann committed
304

305
306
307
308
    //
    // KTextEditor::MainWindow interface, get called by invokeMethod from our wrapper object!
    //
public Q_SLOTS:
309
310
311
312
    /**
     * get the toplevel widget.
     * \return the real main window widget.
     */
313
314
    QWidget *window()
    {
315
316
317
        return this;
    }

Christoph Cullmann's avatar
Christoph Cullmann committed
318
319
320
321
    /**
     * Accessor to the XMLGUIFactory.
     * \return the mainwindow's KXMLGUIFactory.
     */
322
323
    KXMLGUIFactory *guiFactory() override
    {
324
        return KateMDI::MainWindow::guiFactory();
Christoph Cullmann's avatar
Christoph Cullmann committed
325
    }
326

327
328
329
330
    /**
     * Get a list of all views for this main window.
     * @return all views
     */
331
332
    QList<KTextEditor::View *> views()
    {
333
        return viewManager()->views();
334
    }
335

336
337
338
339
    /**
     * Access the active view.
     * \return active view
     */
340
341
    KTextEditor::View *activeView()
    {
342
        return viewManager()->activeView();
343
344
345
346
347
348
349
350
    }

    /**
     * Activate the view with the corresponding \p document.
     * If none exist for this document, create one
     * \param document the document
     * \return activated view of this document
     */
351
352
    KTextEditor::View *activateView(KTextEditor::Document *document)
    {
353
        return viewManager()->activateView(document);
354
355
356
357
358
359
360
361
362
363
    }

    /**
     * Open the document \p url with the given \p encoding.
     * \param url the document's url
     * \param encoding the preferred encoding. If encoding is QString() the
     *        encoding will be guessed or the default encoding will be used.
     * \return a pointer to the created view for the new document, if a document
     *         with this url is already existing, its view will be activated
     */
364
365
    KTextEditor::View *openUrl(const QUrl &url, const QString &encoding = QString())
    {
366
        return viewManager()->openUrlWithView(url, encoding);
367
    }
368

369
370
371
372
373
374
375
376
377
378
379
    /**
     * Close selected view
     * \param view the view
     * \return true if view was closed
     */
    bool closeView(KTextEditor::View *view)
    {
        m_viewManager->closeView(view);
        return true;
    }

380
381
382
383
384
385
386
387
388
389
390
    /**
     * Close the split view where the given view is contained.
     * \param view the view.
     * \return true if the split view was closed.
     */
    bool closeSplitView(KTextEditor::View *view)
    {
        m_viewManager->closeViewSpace(view);
        return true;
    }

391
392
393
394
    /**
     * @returns true if the two given views share the same split view,
     * false otherwise.
     */
395
    bool viewsInSameSplitView(KTextEditor::View *view1, KTextEditor::View *view2)
396
397
398
399
    {
        return m_viewManager->viewsInSameViewSpace(view1, view2);
    }

400
    /**
Yuri Chornoivan's avatar
Yuri Chornoivan committed
401
     * Split current view space according to \p orientation
402
403
404
405
     * \param orientation in which line split the view
     */
    void splitView(Qt::Orientation orientation)
    {
406
        m_viewManager->splitViewSpace(nullptr, orientation);
407
408
    }

409
410
    /**
     * Try to create a view bar for the given view.
Yuri Chornoivan's avatar
Yuri Chornoivan committed
411
     * Its parameter is the view for which we want a view bar
412
     * @return suitable widget that can host view bars widgets or nullptr
413
414
415
     */
    QWidget *createViewBar(KTextEditor::View *)
    {
416
        return bottomViewBarContainer();
417
418
419
420
421
422
    }

    /**
     * Delete the view bar for the given view.
     * @param view view for which we want an view bar
     */
423
424
    void deleteViewBar(KTextEditor::View *view)
    {
425
        deleteBottomViewBarForView(view);
426
427
428
429
430
431
432
    }

    /**
     * Add a widget to the view bar.
     * @param view view for which the view bar is used
     * @param bar bar widget, shall have the viewBarParent() as parent widget
     */
433
434
    void addWidgetToViewBar(KTextEditor::View *view, QWidget *bar)
    {
435
        addToBottomViewBarContainer(view, bar);
436
    }
437

438
439
440
441
    /**
     * Show the view bar for the given view
     * @param view view for which the view bar is used
     */
442
443
    void showViewBar(KTextEditor::View *view)
    {
444
        showBottomViewBarForView(view);
445
    }
446

447
448
449
450
    /**
     * Hide the view bar for the given view
     * @param view view for which the view bar is used
     */
451
452
    void hideViewBar(KTextEditor::View *view)
    {
453
        hideBottomViewBarForView(view);
454
    }
455

456
457
    /**
     * Create a new toolview with unique \p identifier at side \p pos
Yuri Chornoivan's avatar
Yuri Chornoivan committed
458
     * with \p icon and caption \p text. Use the returned widget to embed
459
460
461
462
463
464
465
466
467
     * your widgets.
     * \param plugin which owns this tool view
     * \param identifier unique identifier for this toolview
     * \param pos position for the toolview, if we are in session restore,
     *        this is only a preference
     * \param icon icon to use in the sidebar for the toolview
     * \param text translated text (i18n()) to use in addition to icon
     * \return created toolview on success, otherwise NULL
     */
Alexander Lohnau's avatar
Alexander Lohnau committed
468
469
470
471
472
    QWidget *createToolView(KTextEditor::Plugin *plugin,
                            const QString &identifier,
                            KTextEditor::MainWindow::ToolViewPosition pos,
                            const QIcon &icon,
                            const QString &text);
473
474
475
476
477
478
479
480

    /**
     * Move the toolview \p widget to position \p pos.
     * \param widget the toolview to move, where the widget was constructed
     *        by createToolView().
     * \param pos new position to move widget to
     * \return \e true on success, otherwise \e false
     */
481
    bool moveToolView(QWidget *widget, KTextEditor::MainWindow::ToolViewPosition pos);
482
483
484
485
486
487
488
489

    /**
     * Show the toolview \p widget.
     * \param widget the toolview to show, where the widget was constructed
     *        by createToolView().
     * \return \e true on success, otherwise \e false
     * \todo add focus parameter: bool showToolView (QWidget *widget, bool giveFocus );
     */
490
    bool showToolView(QWidget *widget);
491
492
493
494
495
496
497

    /**
     * Hide the toolview \p widget.
     * \param widget the toolview to hide, where the widget was constructed
     *        by createToolView().
     * \return \e true on success, otherwise \e false
     */
498
499
    bool hideToolView(QWidget *widget);

500
501
502
503
504
505
506
507
508
    /**
     * Shows the @p plugin's config page. The @p page specifies which
     * config page will be shown, see KTextEditor::Plugin::configPages().
     *
     * \return \e true on success, otherwise \e false
     * \since 5.63
     */
    bool showPluginConfigPage(KTextEditor::Plugin *configpageinterface, int id);

509
510
511
512
513
514
    /**
     * Get a plugin view for the plugin with with identifier \p name.
     * \param name the plugin's name
     * \return pointer to the plugin view if a plugin with \p name is loaded and has a view for this mainwindow,
     *         otherwise NULL
     */
515
516
517
    QObject *pluginView(const QString &name);

private Q_SLOTS:
Christoph Cullmann's avatar
jowenn:    
Christoph Cullmann committed
518
    void slotUpdateBottomViewBar();
519

520
private Q_SLOTS:
521
    void slotDocumentCloseAll();
522
    void slotDocumentCloseOther();
523
    void slotDocumentCloseOther(KTextEditor::Document *document);
524
    void slotDocumentCloseSelected(const QList<KTextEditor::Document *> &);
525

526
private:
Christoph Cullmann's avatar
Christoph Cullmann committed
527
528
529
    /**
     * Notify about file modifications from other processes?
     */
530
    bool m_modNotification = false;
531

532
533
534
    /**
     * Shutdown Kate after last file is closed
     */
535
    bool m_modCloseAfterLast = false;
536

Christoph Cullmann's avatar
Christoph Cullmann committed
537
538
539
    /**
     * stacked widget containing the central area, aka view manager, quickopen, ...
     */
540
    QStackedWidget *m_mainStackedWidget = nullptr;
541

Christoph Cullmann's avatar
Christoph Cullmann committed
542
543
544
    /**
     * keeps track of views
     */
545
    KateViewManager *m_viewManager = nullptr;
546

547
    KRecentFilesAction *m_fileOpenRecent = nullptr;
548

549
    KActionMenu *documentOpenWith = nullptr;
550

551
    KToggleAction *settingsShowFileselector = nullptr;
552

553
    KToggleAction *m_showFullScreenAction = nullptr;
Christoph Cullmann's avatar
Christoph Cullmann committed
554

555
    bool m_modignore;
556
557

    // all plugin views for this mainwindow, used by the pluginmanager
558
    QHash<KTextEditor::Plugin *, QObject *> m_pluginViews;
559
560

    // options: show statusbar + show path
561
562
563
564
    KToggleAction *m_paShowPath = nullptr;
    KToggleAction *m_paShowMenuBar = nullptr;
    KToggleAction *m_paShowStatusBar = nullptr;
    KToggleAction *m_paShowTabBar = nullptr;
565

566
567
    QWidget *m_bottomViewBarContainer = nullptr;
    KateContainerStackedLayout *m_bottomContainerStack = nullptr;
Christoph Cullmann's avatar
jowenn:    
Christoph Cullmann committed
568

569
570
571
    class BarState
    {
    public:
572
        BarState() = default;
573
574
575
576
577
578
579
580
581
582
        BarState(QWidget *bar)
            : m_bar(bar)
            , m_state(false)
        {
        }
        ~BarState()
        {
        }
        QWidget *bar()
        {
583
584
            return m_bar;
        }
585
586
        bool state()
        {
587
588
            return m_state;
        }
589
590
        void setState(bool state)
        {
591
592
            m_state = state;
        }
593

594
    private:
595
596
        QWidget *m_bar = nullptr;
        bool m_state = false;
597
    };
598
    QHash<KTextEditor::View *, BarState> m_bottomViewBarMapping;
599

600
public:
601
602
    static void unsetModifiedOnDiscDialogIfIf(KateMwModOnHdDialog *diag)
    {
603
        if (s_modOnHdDialog == diag) {
604
            s_modOnHdDialog = nullptr;
605
        }
606
    }
607

608
private:
609
    static KateMwModOnHdDialog *s_modOnHdDialog;
610

611
612
613
614
    /**
     * Wrapper of main window for KTextEditor
     */
    KTextEditor::MainWindow *m_wrapper;
615

616
617
public Q_SLOTS:
    void slotWindowActivated();
618

619
protected:
Kevin Funk's avatar
Kevin Funk committed
620
621
    bool event(QEvent *e) override;
    void mousePressEvent(QMouseEvent *e) override;
622
623
624
};

#endif