]> git.lyx.org Git - features.git/blob - src/frontends/qt/GuiView.h
Fix broken Apple speller interface
[features.git] / src / frontends / qt / GuiView.h
1 // -*- C++ -*-
2 /**
3  * \file GuiView.h
4  * This file is part of LyX, the document processor.
5  * Licence details can be found in the file COPYING.
6  *
7  * \author Lars Gullik Bjornes
8  * \author John Levon
9  * \author Abdelrazak Younes
10  * \author Peter Kümmel
11  *
12  * Full author contact details are available in file CREDITS.
13  */
14
15 #ifndef GUI_VIEW_H
16 #define GUI_VIEW_H
17
18 #include "frontends/Delegates.h"
19
20 #include "support/strfwd.h"
21
22 #include <QMainWindow>
23 #include <QLabel>
24 #include <QMenu>
25 #include <QSvgWidget>
26
27 class QCloseEvent;
28 class QDragEnterEvent;
29 class QDropEvent;
30 class QPushButton;
31 class QShowEvent;
32 class QSlider;
33
34
35 namespace lyx {
36
37 namespace support { class FileName; }
38
39 class Buffer;
40 class BufferView;
41 class Cursor;
42 class DispatchResult;
43 class FuncStatus;
44 class FuncRequest;
45 class Inset;
46
47 namespace frontend {
48
49 class Dialog;
50 class LayoutBox;
51 class GuiClickableLabel;
52 class GuiToolbar;
53 class GuiWorkArea;
54 class TabWorkArea;
55 class TocModels;
56 class ToolbarInfo;
57
58 /**
59  * GuiView - Qt main LyX window
60  *
61  * This class represents the main LyX window and provides
62  * accessor functions to its content.
63  *
64  * Note: a QObject emits a destroyed(QObject *) Qt signal when it
65  * is deleted. This might be useful for closing other dialogs
66  * depending on a given GuiView.
67  */
68 class GuiView : public QMainWindow, public GuiBufferViewDelegate,
69         public GuiBufferDelegate
70 {
71         Q_OBJECT
72
73 public:
74         /// create a main window of the given dimensions
75         GuiView(int id);
76
77         ~GuiView();
78
79         /// closes the view such that the view knows that is closed
80         /// programmatically and not by the user clicking the x.
81         bool closeScheduled();
82
83         /// Things that need to be done when the OSes session manager
84         /// requests a log out.
85         bool prepareAllBuffersForLogout();
86
87         int id() const { return id_; }
88
89         /// are we busy ?
90         bool busy() const;
91
92         /// Signal that the any "auto" minibuffer can be closed now.
93         void resetCommandExecute();
94
95         /// \name Generic accessor functions
96         //@{
97         /// The current BufferView refers to the BufferView that has the focus,
98         /// including for example the one that is created when you use the
99         /// advanced search and replace pane.
100         /// \return the currently selected buffer view.
101         BufferView * currentBufferView();
102         BufferView const * currentBufferView() const;
103
104         /// The document BufferView always refers to the view's main document
105         /// BufferView. So, even if the BufferView in e.g., the advanced
106         /// search and replace pane has the focus.
107         /// \return the current document buffer view.
108         BufferView * documentBufferView();
109         BufferView const * documentBufferView() const;
110
111         void newDocument(std::string const & filename,
112                          std::string templatefile = std::string(),
113                          bool fromTemplate = false);
114
115         /// display a message in the view
116         /// could be called from any thread
117         void message(docstring const &) override;
118
119         bool getStatus(FuncRequest const & cmd, FuncStatus & flag);
120         /// dispatch command.
121         /// \return true if the \c FuncRequest has been dispatched.
122         void dispatch(FuncRequest const & cmd, DispatchResult & dr);
123
124         void restartCaret();
125         /// Update the completion popup and the inline completion state.
126         /// If \c start is true, then a new completion might be started.
127         /// If \c keep is true, an active completion will be kept active
128         /// even though the cursor moved. The update flags of \c cur might
129         /// be changed.
130         void updateCompletion(Cursor & cur, bool start, bool keep);
131
132         ///
133         void setFocus();
134         bool hasFocus() const;
135
136         ///
137         void focusInEvent(QFocusEvent * e) override;
138         /// Add a Buffer to the View
139         /// \param b Buffer to set.
140         /// \param switch_to Whether to set it to the current workarea.
141         void setBuffer(Buffer * b, bool switch_to = true);
142
143         /// load a document into the current workarea.
144         Buffer * loadDocument(
145                 support::FileName const &  name, ///< File to load.
146                 bool tolastfiles = true  ///< append to the "Open recent" menu?
147                 );
148
149         /// add toolbar, if newline==true, add a toolbar break before the toolbar
150         GuiToolbar * makeToolbar(ToolbarInfo const & tbinfo, bool newline);
151         void updateStatusBar();
152
153         /// updates the possible layouts selectable
154         void updateLayoutList();
155         void updateToolbars();
156
157         ///
158         LayoutBox * getLayoutDialog() const;
159
160         /// hides the workarea and makes sure it is clean
161         bool hideWorkArea(GuiWorkArea * wa);
162         /// closes workarea; close buffer only if no other workareas point to it
163         bool closeWorkArea(GuiWorkArea * wa);
164         /// closes the buffer
165         bool closeBuffer(Buffer & buf);
166         ///
167         void openDocument(std::string const & filename);
168         ///
169         void importDocument(std::string const &);
170
171         /// \name GuiBufferDelegate.
172         //@{
173         void resetAutosaveTimers() override;
174         // shows an error list
175         // if from_master is true, show master's error list
176         void errors(std::string const &, bool from_master = false) override;
177         void structureChanged() override;
178         void updateTocItem(std::string const &, DocIterator const &) override;
179         //@}
180
181         ///
182         TocModels & tocModels();
183
184         /// called on timeout
185         void autoSave();
186
187         /// check for external change of any opened buffer, mainly for svn usage
188         void checkExternallyModifiedBuffers();
189
190         /** redraw \c inset in all the BufferViews in which it is currently
191          *  visible. If successful return a pointer to the owning Buffer.
192          */
193         Buffer const * updateInset(Inset const *);
194
195         /// \return the \c Workarea associated to \p  Buffer
196         /// \retval 0 if no \c WorkArea is found.
197         GuiWorkArea * workArea(Buffer & buffer);
198         /// \return the \c Workarea at index \c index
199         GuiWorkArea * workArea(int index);
200
201         /// Add a \c WorkArea
202         /// \return the \c Workarea associated to \p  Buffer
203         /// \retval 0 if no \c WorkArea is found.
204         GuiWorkArea * addWorkArea(Buffer & buffer);
205         /// \param work_area The current \c WorkArea, or \c NULL
206         void setCurrentWorkArea(GuiWorkArea * work_area);
207         ///
208         void removeWorkArea(GuiWorkArea * work_area);
209         /// return true if \c wa is one of the visibles workareas of this view
210         bool hasVisibleWorkArea(GuiWorkArea * wa) const;
211         /// return the current WorkArea (the one that has the focus).
212         GuiWorkArea const * currentWorkArea() const;
213         /// return the current WorkArea (the one that has the focus).
214         GuiWorkArea * currentWorkArea();
215
216         /// return the current document WorkArea (it may not have the focus).
217         GuiWorkArea const * currentMainWorkArea() const;
218         /// return the current document WorkArea (it may not have the focus).
219         GuiWorkArea * currentMainWorkArea();
220
221         /// Current ratio between physical pixels and device-independent pixels
222         double pixelRatio() const;
223
224 Q_SIGNALS:
225         void closing(int);
226         void triggerShowDialog(QString const & qname, QString const & qdata, Inset * inset);
227         // emitted when the work area or its buffer view changed
228         void bufferViewChanged();
229         /// emitted when zoom is modified
230         void currentZoomChanged(int);
231         /// emitted when script is killed (e.g., user cancels export)
232         void scriptKilled();
233
234 public Q_SLOTS:
235         ///
236         void setBusy(bool) override;
237         /// idle timeout.
238         /// clear any temporary message and replace with current status.
239         void clearMessage();
240         /// show documents stats in toolbar and trigger new iteration
241         void showStats();
242         ///
243         void updateWindowTitle(GuiWorkArea * wa);
244         ///
245         void disableShellEscape();
246
247 private Q_SLOTS:
248         ///
249         void resetWindowTitle();
250
251         void flatGroupBoxes(const QObject * object, bool flag);
252
253         ///
254         void checkCancelBackground();
255         ///
256         void statsPressed();
257         ///
258         void zoomSliderMoved(int);
259         ///
260         void zoomValueChanged(int);
261         ///
262         void zoomInPressed();
263         ///
264         void zoomOutPressed();
265         ///
266         void showZoomContextMenu();
267         ///
268         void showStatusBarContextMenu();
269         ///
270         void on_currentWorkAreaChanged(GuiWorkArea *);
271         ///
272         void onBufferViewChanged();
273         ///
274         void on_lastWorkAreaRemoved();
275
276         /// For completion of autosave or export threads.
277         void processingThreadStarted();
278         void processingThreadFinished();
279         void autoSaveThreadFinished();
280
281         /// must be called in GUI thread
282         void doShowDialog(QString const & qname, QString const & qdata,
283         Inset * inset);
284
285         /// must be called from GUI thread
286         void updateStatusBarMessage(QString const & str);
287         void clearMessageText();
288
289         ///
290         void toolBarPopup(const QPoint &pos);
291
292 private:
293         /// Open given child document in current buffer directory.
294         void openChildDocument(std::string const & filename);
295         /// Close current document buffer.
296         bool closeBuffer();
297         /// Close all document buffers.
298         bool closeBufferAll();
299         ///
300         TabWorkArea * addTabWorkArea();
301
302         ///
303         void scheduleRedrawWorkAreas();
304
305         /// connect to signals in the given BufferView
306         void connectBufferView(BufferView & bv);
307         /// disconnect from signals in the given BufferView
308         void disconnectBufferView();
309         /// connect to signals in the given buffer
310         void connectBuffer(Buffer & buf);
311         /// disconnect from signals in the given buffer
312         void disconnectBuffer();
313         ///
314         void dragEnterEvent(QDragEnterEvent * ev) override;
315         ///
316         void dropEvent(QDropEvent * ev) override;
317         /// make sure we quit cleanly
318         void closeEvent(QCloseEvent * e) override;
319         ///
320         void showEvent(QShowEvent *) override;
321
322         /// in order to catch Tab key press.
323         bool event(QEvent * e) override;
324         bool focusNextPrevChild(bool) override;
325
326         ///
327         bool goToFileRow(std::string const & argument);
328
329         ///
330         class GuiViewPrivate;
331         GuiViewPrivate & d;
332
333 public:
334         ///
335         /// dialogs for this view
336         ///
337
338         ///
339         void resetDialogs();
340
341         /// Hide all visible dialogs
342         void hideAll() const;
343
344         /// Update all visible dialogs.
345         /**
346          *  Check the status of all visible dialogs and disable or re-enable
347          *  them as appropriate.
348          *
349          *  Disabling is needed for example when a dialog is open and the
350          *  cursor moves to a position where the corresponding inset is not
351          *  allowed.
352          */
353         void updateDialogs();
354
355         /** Show dialog could be called from arbitrary threads.
356             \param name == "bibtex", "citation" etc; an identifier used to
357             launch a particular dialog.
358             \param data is a string representation of the Inset contents.
359             It is often little more than the output from Inset::write.
360             It is passed to, and parsed by, the frontend dialog.
361             Several of these dialogs do not need any data,
362             so it defaults to string().
363             \param inset ownership is _not_ passed to the frontend dialog.
364             It is stored internally and used by the kernel to ascertain
365             what to do with the FuncRequest dispatched from the frontend
366             dialog on 'Apply'; should it be used to create a new inset at
367             the current cursor position or modify an existing, 'open' inset?
368         */
369         void showDialog(std::string const & name,
370                 std::string const & data, Inset * inset = 0) override;
371
372         /** \param name == "citation", "bibtex" etc; an identifier used
373             to reset the contents of a particular dialog with \param data.
374             See the comments to 'show', above.
375         */
376         void updateDialog(std::string const & name, std::string const & data) override;
377
378         /** All Dialogs of the given \param name will be closed if they are
379             connected to the given \param inset.
380         */
381         void hideDialog(std::string const & name, Inset * inset);
382         ///
383         void disconnectDialog(std::string const & name);
384         ///
385         bool develMode() const { return devel_mode_; }
386         ///
387         void setCurrentZoom(int const v);
388
389 private:
390         /// Saves the layout and geometry of the window
391         void saveLayout() const;
392         /// Saves the settings of toolbars and all dialogs
393         void saveUISettings() const;
394         ///
395         bool restoreLayout();
396         ///
397         GuiToolbar * toolbar(std::string const & name);
398         ///
399         void constructToolbars();
400         ///
401         void initToolbars();
402         ///
403         void initToolbar(std::string const & name);
404         /// Update lock (all) toolbars position
405         void updateLockToolbars();
406         /// refill the toolbars (dark/light mode switch)
407         void refillToolbars();
408         ///
409         bool lfunUiToggle(std::string const & ui_component);
410         ///
411         /// kill the script and hide export-in-progress status bar icons
412         void cancelExport();
413         ///
414         void toggleFullScreen();
415         /// \return whether we did anything
416         bool insertLyXFile(docstring const & fname, bool ignorelang = false);
417         ///
418         /// Open Export As ... dialog. \p iformat is the format the
419         /// filter is initially set to.
420         bool exportBufferAs(Buffer & b, docstring const & iformat);
421
422         ///
423         enum RenameKind {
424                 LV_WRITE_AS,
425                 LV_WRITE_AS_TEMPLATE,
426                 LV_VC_RENAME,
427                 LV_VC_COPY,
428         };
429         /// Get a path for LFUN_BUFFER_WRITE_AS_TEMPLATE
430         std::string const getTemplatesPath(Buffer & buf);
431         /// Save a buffer as a new file.
432         /**
433          * Write a buffer to a new file name and rename the buffer
434          * according to the new file name.
435          *
436          * This function is e.g. used by menu callbacks and
437          * LFUN_BUFFER_WRITE_AS.
438          *
439          * If 'newname' is empty, the user is asked via a
440          * dialog for the buffer's new name and location.
441          *
442          * If 'newname' is non-empty and has an absolute path, that is used.
443          * Otherwise the base directory of the buffer is used as the base
444          * for any relative path in 'newname'.
445          *
446          * \p kind controls what is done besides the pure renaming:
447          * LV_WRITE_AS  => The buffer is written without version control actions.
448          * LV_VC_RENAME => The file is renamed in version control.
449          * LV_VC_COPY   => The file is copied in version control.
450          */
451         bool renameBuffer(Buffer & b, docstring const & newname,
452                           RenameKind kind = LV_WRITE_AS);
453         ///
454         bool saveBuffer(Buffer & b);
455         /// save and rename buffer to fn. If fn is empty, the buffer
456         /// is just saved as the filename it already has.
457         bool saveBuffer(Buffer & b, support::FileName const & fn);
458         /// closes a workarea, if close_buffer is true the buffer will
459         /// also be released, otherwise the buffer will be hidden.
460         bool closeWorkArea(GuiWorkArea * wa, bool close_buffer);
461         /// closes the tabworkarea and all tabs. If we are in a close event,
462         /// all buffers will be closed, otherwise they will be hidden.
463         bool closeTabWorkArea(TabWorkArea * twa);
464         /// gives the user the possibility to save their work
465         /// or to discard the changes. If hiding is true, the
466         /// document will be reloaded.
467         bool saveBufferIfNeeded(Buffer & buf, bool hiding);
468         /// closes all workareas
469         bool closeWorkAreaAll();
470         /// write all open workareas into the session file
471         void writeSession() const;
472         /// is the buffer in this workarea also shown in another tab ?
473         /// This tab can either be in the same view or in another one.
474         bool inMultiTabs(GuiWorkArea * wa);
475         /// is the buffer shown in some other view ?
476         bool inOtherView(Buffer & buf);
477         ///
478         enum NextOrPrevious {
479                 NEXTBUFFER,
480                 PREVBUFFER
481         };
482         ///
483         void gotoNextOrPreviousBuffer(NextOrPrevious np, bool const move);
484
485         /// Is the dialog currently visible?
486         bool isDialogVisible(std::string const & name) const;
487         ///
488         Dialog * find(std::string const & name, bool hide_it) const;
489         ///
490         Dialog * findOrBuild(std::string const & name, bool hide_it);
491         ///
492         Dialog * build(std::string const & name);
493         ///
494         bool reloadBuffer(Buffer & buffer);
495         ///
496         void dispatchVC(FuncRequest const & cmd, DispatchResult & dr);
497         ///
498         void dispatchToBufferView(FuncRequest const & cmd, DispatchResult & dr);
499         ///
500         void showMessage();
501         /// Check whether any of the stats is enabled in status bar
502         bool statsEnabled() const;
503
504         /// This view ID.
505         int id_;
506
507         /// flag to avoid two concurrent close events.
508         bool closing_;
509         /// if the view is busy the cursor shouldn't blink for instance.
510         /// This counts the number of times more often we called
511         /// setBusy(true) compared to setBusy(false), so we can nest
512         /// functions that call setBusy;
513         int busy_;
514
515         /// Request to open the command toolbar if it is "auto"
516         bool command_execute_;
517         /// Request to give focus to minibuffer
518         bool minibuffer_focus_;
519
520         /// Statusbar widget that shows shell-escape status
521         QLabel * shell_escape_;
522         /// Statusbar widget that shows read-only status
523         QLabel * read_only_;
524         /// Statusbar widget that shows version control status
525         QLabel * version_control_;
526         /// Statusbar widget that document count statistics
527         QLabel * stat_counts_;
528         /// Word count info feature can be disabled by context menu
529         bool word_count_enabled_;
530         /// Char count info feature can be disabled by context menu
531         bool char_count_enabled_;
532         /// Char count info feature can be disabled by context menu
533         /// This excludes blanks
534         bool char_nb_count_enabled_;
535         /// Statusbar widget that shows zoom value
536         GuiClickableLabel * zoom_value_;
537         /// The zoom slider widget
538         QSlider * zoom_slider_;
539         /// Zoom in ("+") Button
540         GuiClickableLabel * zoom_in_;
541         /// Zoom out ("-") Button
542         GuiClickableLabel * zoom_out_;
543
544         /// The rate from which the actual zoom value is calculated
545         /// from the default zoom pref
546         double zoom_ratio_ = 1.0;
547         /// Minimum zoom percentage
548         int const zoom_min_ = 10;
549         /// Maximum zoom percentage
550         int const zoom_max_ = 1000;
551
552         // movability flag of all toolbars
553         bool toolbarsMovable_;
554
555         // developer mode
556         bool devel_mode_;
557
558         // initial zoom for pinch gesture
559         int initialZoom_;
560 };
561
562
563 class SEMenu : public QMenu
564 {
565         Q_OBJECT
566 public:
567         explicit SEMenu(QWidget * parent);
568
569 public Q_SLOTS:
570         void showMenu(QPoint const &) { exec(QCursor::pos()); }
571 };
572
573
574 class PressableSvgWidget : public QSvgWidget
575 {
576         Q_OBJECT
577 public:
578     explicit PressableSvgWidget(const QString &file, QWidget * parent = nullptr)
579         : QSvgWidget(file, parent) {};
580 protected:
581     void mousePressEvent(QMouseEvent *event) override;
582 Q_SIGNALS:
583     void pressed();
584 };
585
586 } // namespace frontend
587 } // namespace lyx
588
589 #endif // GUIVIEW_H