1 ////////////////////////////////////////////////////////////////////////
2 //
3 // Copyright (C) 2011-2021 The Octave Project Developers
4 //
5 // See the file COPYRIGHT.md in the top-level directory of this
6 // distribution or <https://octave.org/copyright/>.
7 //
8 // This file is part of Octave.
9 //
10 // Octave is free software: you can redistribute it and/or modify it
11 // under the terms of the GNU General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // Octave is distributed in the hope that it will be useful, but
16 // WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 // GNU General Public License for more details.
19 //
20 // You should have received a copy of the GNU General Public License
21 // along with Octave; see the file COPYING.  If not, see
22 // <https://www.gnu.org/licenses/>.
23 //
24 ////////////////////////////////////////////////////////////////////////
25 
26 #if ! defined (octave_file_editor_tab_h)
27 #define octave_file_editor_tab_h 1
28 
29 #include <QAbstractButton>
30 #include <QCloseEvent>
31 #include <QDateTime>
32 #include <QFileInfo>
33 #include <QFileSystemWatcher>
34 #include <QLabel>
35 #include <QStatusBar>
36 #include <QWidget>
37 #include <Qsci/qsciapis.h>
38 
39 #include "gui-settings.h"
40 #include "marker.h"
41 #include "octave-qscintilla.h"
42 #include "qt-interpreter-events.h"
43 
44 class octave_value_list;
45 
46 namespace octave
47 {
48   class base_qobject;
49   class file_editor;
50 
51   class file_editor_tab : public QWidget
52   {
53     Q_OBJECT
54 
55   public:
56 
57     file_editor_tab (base_qobject& oct_qobj, const QString& directory = "");
58 
59     ~file_editor_tab (void);
60 
qsci_edit_area(void)61     octave_qscintilla * qsci_edit_area (void) { return m_edit_area; }
62 
63     // Will initiate close if associated with the identifier tag.
64     bool conditional_close (void);
65 
66     void update_breakpoints ();
67 
file_name(void)68     QString file_name (void) const { return m_file_name; }
encoding(void)69     QString encoding (void) const { return m_encoding; }
70 
71   signals:
72 
73     void tab_ready_to_close (void);
74     void file_name_changed (const QString& fileName,
75                             const QString& toolTip,
76                             bool modified);
77     void editor_state_changed (bool copy_available, bool is_octave_file);
78     void set_focus_editor_signal (QWidget *);
79     void edit_area_changed (octave_qscintilla *edit_area);
80     void tab_remove_request (void);
81     void mru_add_file (const QString& file_name, const QString& encoding);
82     void editor_check_conflict_save (const QString& saveFileName,
83                                      bool remove_on_success);
84     void run_file_signal (const QFileInfo& info);
85     void request_open_file (const QString&, const QString& = QString ());
86     void edit_mfile_request (const QString&, const QString&,
87                              const QString&, int);
88 
89     void autoc_closed (void);
90 
91     void update_breakpoints_signal (const octave_value_list& args);
92 
93     void remove_breakpoint_via_debugger_linenr (int debugger_linenr);
94     void request_remove_breakpoint_via_editor_linenr (int editor_linenr);
95     void remove_all_breakpoints (void);
96     void find_translated_line_number (int original_linenr,
97                                       int& translated_linenr, marker*&);
98     void find_linenr_just_before (int linenr, int& original_linenr,
99                                   int& editor_linenr);
100     void report_marker_linenr (QIntList& lines, QStringList& conditions);
101     void remove_position_via_debugger_linenr (int debugger_linenr);
102     void remove_all_positions (void);
103 
104     void debug_quit_signal (void);
105 
106     void interpreter_event (const fcn_callback& fcn);
107     void interpreter_event (const meth_callback& meth);
108 
109     void maybe_remove_next (int remove_line);
110 
111     void dbstop_if (const QString& prompt, int line, const QString& cond);
112     void request_add_breakpoint (int line, const QString& cond);
113     void request_add_octave_apis (const QStringList&);
114     void api_entries_added (void);
115 
116     void do_save_file_signal (const QString& file_to_save,
117                               bool remove_on_success, bool restore_breakpoints);
118 
119     void confirm_dbquit_and_save_signal (const QString& file_to_save,
120                                          const QString& base_name,
121                                          bool remove_on_success,
122                                          bool restore_breakpoints);
123 
124     // FIXME: The following is similar to "process_octave_code" signal.
125     // However, currently that signal is connected to something that simply
126     // focuses a window and does not actually communicate with Octave.
127     //
128     // void evaluate_octave_command (const QString& command);
129 
130   public slots:
131 
132     void update_window_title (bool modified);
133     void handle_copy_available (bool enableCopy);
134     void handle_margin_clicked (int line, int margin,
135                                 Qt::KeyboardModifiers state);
136 
137     // Tells the editor tab to react on changed settings.
138     void notice_settings (const gui_settings *settings, bool init = false);
139 
140     // Change to a different editor tab by identifier tag.
141     void change_editor_state (const QWidget *ID);
142 
143     void set_focus (const QWidget *ID);
144     void set_current_directory (const QString& dir);
145     void context_help (const QWidget *ID, bool);
146     void context_edit (const QWidget *ID);
147     void save_file (const QWidget *ID);
148     void save_file (const QWidget *ID, const QString& fileName,
149                     bool remove_on_success);
150     void save_file_as (const QWidget *ID);
151     void print_file (const QWidget *ID);
152     void run_file (const QWidget *ID, bool step_into = false);
153     void context_run (const QWidget *ID);
154     void toggle_bookmark (const QWidget *ID);
155     void next_bookmark (const QWidget *ID);
156     void previous_bookmark (const QWidget *ID);
157     void remove_bookmark (const QWidget *ID);
158 
159     void toggle_breakpoint (const QWidget *ID);
160     void next_breakpoint (const QWidget *ID);
161     void previous_breakpoint (const QWidget *ID);
162     void remove_all_breakpoints (const QWidget *ID);
163 
164     void scintilla_command (const QWidget *, unsigned int);
165 
166     void comment_selected_text (const QWidget *ID, bool input_str);
167     void uncomment_selected_text (const QWidget *ID);
168 
169     void indent_selected_text (const QWidget *ID);
170     void unindent_selected_text (const QWidget *ID);
171     void smart_indent_line_or_selected_text (const QWidget *ID);
172     void convert_eol (const QWidget *ID, QsciScintilla::EolMode);
173 
174     void zoom_in (const QWidget *ID);
175     void zoom_out (const QWidget *ID);
176     void zoom_normal (const QWidget *ID);
177 
178     void goto_line (const QWidget *ID, int line = -1);
179     void move_match_brace (const QWidget *ID, bool select);
180     void show_auto_completion (const QWidget *ID);
181 
182     void insert_debugger_pointer (const QWidget *ID, int line = -1);
183     void delete_debugger_pointer (const QWidget *ID, int line = -1);
184 
185     void do_breakpoint_marker (bool insert, const QWidget *ID, int line = -1,
186                                const QString& cond = "");
187 
188     void recover_from_exit (void);
189     void set_modified (bool modified = true);
190 
191     void set_encoding (const QString& new_encoding);
192 
193     QString load_file (const QString& fileName);
194 
195     void new_file (const QString& commands = QString ());
196 
197     void file_has_changed (const QString& path, bool do_close = false);
198 
199     void handle_context_menu_edit (const QString&);
200     void handle_context_menu_break_condition (int linenr);
201 
202     void handle_request_add_breakpoint (int line, const QString& cond);
203     void handle_request_remove_breakpoint (int line);
204 
205     void update_breakpoints_handler (const octave_value_list& argout);
206 
207   private slots:
208 
209     // When user closes message box for decoding problems
210     void handle_decode_warning_answer (QAbstractButton *btn);
211 
212     // When user closes message box for reload question.
213     void handle_file_reload_answer (int decision);
214 
215     // When user closes message box for resave question.
216     void handle_file_resave_answer (int decision);
217 
218     // When user closes QFileDialog box.
219     void handle_save_file_as_answer (const QString& fileName);
220     void handle_save_file_as_answer_close (const QString& fileName);
221     void handle_save_file_as_answer_cancel (void);
222     void handle_save_as_filter_selected (const QString& filter);
223 
224     // When user changes encoding after decoding errors were found
225     void handle_current_enc_changed (const QString& enc);
226 
227     // When apis preparation has finished and is ready to save
228     void save_apis_info (void);
229 
230     // When the numer of lines changes -> adapt width of margin
231     void auto_margin_width (void);
232 
233     void handle_cursor_moved (int line, int col);
234     void handle_char_added (int character);
235     void handle_double_click (int p, int l, int modifier);
236     void handle_lines_changed (void);
237 
238     void handle_remove_next (int remove_line);
239     void handle_dbstop_if (const QString& prompt, int line,
240                            const QString& cond);
241     void handle_add_octave_apis (const QStringList& api_entries);
242     void handle_api_entries_added (void);
243 
244     void do_save_file (const QString& file_to_save, bool remove_on_success,
245                        bool restore_breakpoints);
246 
247     void confirm_dbquit_and_save (const QString& file_to_save,
248                                   const QString& base_name,
249                                   bool remove_on_success,
250                                   bool restore_breakpoints);
251 
252   protected:
253 
254     void closeEvent (QCloseEvent *event);
255     void set_file_name (const QString& fileName);
256 
257   private:
258 
259     base_qobject& m_octave_qobj;
260 
261     struct bp_info
262     {
263       bp_info (const QString& fname, int l = 0, const QString& cond = "");
264 
265       int line;
266       std::string file;
267       std::string dir;
268       std::string function_name;
269       std::string condition;
270     };
271 
272     void add_breakpoint_event (const bp_info& info);
273 
274     bool valid_file_name (const QString& file = QString ());
275     void save_file (const QString& saveFileName, bool remove_on_success = false,
276                     bool restore_breakpoints = true);
277     void save_file_as (bool remove_on_success = false);
278     bool check_valid_identifier (QString file_name);
279     QTextCodec* check_valid_codec (void);
280 
281     bool unchanged_or_saved (void);
282 
283     void update_lexer (void);
284     void update_lexer_settings (void);
285 
286     void show_dialog (QDialog *dlg, bool modal);
287   public:
288     int check_file_modified (bool remove = false);
289   private:
290     void do_comment_selected_text (bool comment, bool input_str = false);
291     void do_indent_selected_text (bool indent);
292     void do_smart_indent_line_or_selected_text (void);
293 
294     void check_restore_breakpoints (void);
295     void center_current_line (bool always=true);
296 
297     QString get_function_name (void);
298 
299     QsciScintilla::EolMode detect_eol_mode (void);
300     void update_eol_indicator (void);
301 
302     octave_qscintilla *m_edit_area;
303 
304     QStatusBar *m_status_bar;
305     QLabel *m_row_indicator;
306     QLabel *m_col_indicator;
307     QLabel *m_eol_indicator;
308     QLabel *m_enc_indicator;
309 
310     QsciScintilla::EolMode m_save_as_desired_eol;
311 
312     QString m_file_name;
313     QString m_file_name_short;
314     QString m_ced;
315     QString m_encoding;
316     QString m_new_encoding;
317     QDateTime m_last_modified;
318 
319     bool m_autoc_active;
320     bool m_long_title;
321     bool m_copy_available;
322     bool m_is_octave_file;
323     bool m_always_reload_changed_files;
324     bool m_smart_indent;
325     int m_auto_endif;
326     int m_ind_char_width;
327 
328     QFileSystemWatcher m_file_system_watcher;
329 
330     QIntList m_bp_lines;
331     QStringList m_bp_conditions;
332 
333     QsciAPIs *m_lexer_apis;
334     QString m_prep_apis_path;
335     QString m_prep_apis_file;
336 
337     int m_line_break;
338     bool m_line_break_comments;
339     int m_line;
340     int m_col;
341     bool m_lines_changed;
342     bool m_highlight_all_occurrences;
343     int m_bp_restore_count;
344 
345     struct breakpoint_info
346     {
347       bool remove_next;
348       int remove_line;
349       int do_not_remove_line;
350     };
351 
352     breakpoint_info m_breakpoint_info;
353   };
354 }
355 
356 #endif
357