GNU Octave  6.2.0
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
file-editor.cc
Go to the documentation of this file.
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 (HAVE_CONFIG_H)
27 # include "config.h"
28 #endif
29 
30 #if defined (HAVE_QSCINTILLA)
31 
32 #include <algorithm>
33 
34 #include <QApplication>
35 #include <QFile>
36 #include <QFileDialog>
37 #include <QFont>
38 #include <QMessageBox>
39 #include <QMimeData>
40 #include <QProcess>
41 #include <QPushButton>
42 #include <QStyle>
43 #include <QTabBar>
44 #include <QTextStream>
45 #include <QVBoxLayout>
46 #include <Qsci/qscicommandset.h>
47 
48 #include "file-editor.h"
49 #include "gui-preferences-ed.h"
50 #include "gui-preferences-sc.h"
51 #include "gui-preferences-global.h"
52 #include "main-window.h"
53 #include "octave-qobject.h"
54 #include "shortcut-manager.h"
55 
56 #include "oct-env.h"
57 
58 #include "event-manager.h"
59 #include "interpreter.h"
60 #include "oct-map.h"
61 #include "pt-eval.h"
62 #include "utils.h"
63 
64 namespace octave
65 {
66  // Functions of the the reimplemented tab widget
67 
69  : QTabWidget (p)
70  {
71  tab_bar *bar = new tab_bar (this);
72 
73  connect (bar, SIGNAL (close_current_tab_signal (bool)),
74  p->parent (), SLOT (request_close_file (bool)));
75 
76  this->setTabBar (bar);
77 
78  setTabsClosable (true);
79  setUsesScrollButtons (true);
80 #if defined (HAVE_QTABWIDGET_SETMOVABLE)
81  setMovable (true);
82 #endif
83  }
84 
86  {
87  return qobject_cast<tab_bar *> (tabBar ());
88  }
89 
90  std::list<file_editor_tab *>
92  {
93  std::list<file_editor_tab *> retval;
94  for (int i = 0; i < count (); i++)
95  retval.push_back (static_cast<file_editor_tab *> (widget (i)));
96  return retval;
97  }
98 
99 
100  // File editor
101 
103  : file_editor_interface (p, oct_qobj)
104  {
105  // Set current editing directory before construction because loaded
106  // files will change ced accordingly.
107  m_ced = QDir::currentPath ();
108 
109  // Set actions that are later added by the main window to null,
110  // preventing access to them when they are still undefined.
111  m_undo_action = nullptr;
112  m_copy_action = nullptr;
113  m_paste_action = nullptr;
114  m_selectall_action = nullptr;
115 
116  m_find_dialog = nullptr;
117 
118  m_closed = false;
119  m_no_focus = false;
120 
121  m_copy_action_enabled = false;
122  m_undo_action_enabled = false;
123 
124  construct ();
125 
126  setVisible (false);
127  setAcceptDrops (true);
128  setFocusPolicy (Qt::StrongFocus);
129  }
130 
132  {
133  delete m_mru_file_menu;
134  }
135 
136  void file_editor::focusInEvent (QFocusEvent *e)
137  {
138  // The focus is transferred to the active tab and its edit
139  // area in this focus in event handler. This is to avoid
140  // using focus proxies with conflicts in the proxy change
141  // presumably introduced by bug
142  // https://bugreports.qt.io/browse/QTBUG-61092
143  reset_focus (); // Make sure editor tab with edit area get focus
144 
145  QDockWidget::focusInEvent (e);
146  }
147 
148  // insert global actions, that should also be displayed in the editor window,
149  // into the editor's menu and/or toolbar
151  {
152  // actions/menus that have to be added to the toolbar or the menu
153  QAction *open_action = shared_actions.at (OPEN_ACTION);
154  QAction *new_action = shared_actions.at (NEW_SCRIPT_ACTION);
155  QAction *new_fcn_action = shared_actions.at (NEW_FUNCTION_ACTION);
156  m_fileMenu->insertAction (m_mru_file_menu->menuAction (), open_action);
157  m_fileMenu->insertAction (open_action, new_fcn_action);
158  m_fileMenu->insertAction (new_fcn_action, new_action);
159  m_tool_bar->insertAction (m_popdown_mru_action, open_action);
160  m_tool_bar->insertAction (open_action, new_action);
161 
162  // actions that are additionally enabled/disabled later by the editor
163  // undo
164  m_undo_action = shared_actions.at (UNDO_ACTION);
165  m_tool_bar->insertAction (m_redo_action,m_undo_action);
166  m_edit_menu->insertAction (m_redo_action,m_undo_action);
167  // select all
168  m_selectall_action = shared_actions.at (SELECTALL_ACTION);
170  m_edit_menu->insertSeparator (m_find_action);
171  // paste
172  m_paste_action = shared_actions.at (PASTE_ACTION);
173  m_tool_bar->insertAction (m_find_action,m_paste_action);
175  m_edit_menu->insertSeparator (m_selectall_action);
176  // copy
177  m_copy_action = shared_actions.at (COPY_ACTION);
178  m_tool_bar->insertAction (m_paste_action,m_copy_action);
179  m_edit_menu->insertAction (m_paste_action,m_copy_action);
180  // find files
181  m_find_files_action = shared_actions.at (FIND_FILES_ACTION);
183  }
184 
186  {
189  QString sc_run = settings->sc_value (sc_edit_run_run_file);
190  QString sc_cont = settings->sc_value (sc_main_debug_continue);
191 
192  if (sc_run == sc_cont)
193  m_run_action->setShortcut (QKeySequence ()); // prevent ambiguous shortcuts
194 
195  m_run_action->setToolTip (tr ("Continue")); // update tool tip
196  }
197 
199  {
202  m_run_action->setToolTip (tr ("Save File and Run")); // update tool tip
203  }
204 
206  {
207  bool have_tabs = m_tab_widget->count () > 0;
208 
209  m_edit_cmd_menu->setEnabled (have_tabs);
210  m_edit_fmt_menu->setEnabled (have_tabs);
211  m_edit_nav_menu->setEnabled (have_tabs);
212 
213  m_comment_selection_action->setEnabled (have_tabs);
214  m_uncomment_selection_action->setEnabled (have_tabs);
215  m_comment_var_selection_action->setEnabled (have_tabs);
216  m_indent_selection_action->setEnabled (have_tabs);
217  m_unindent_selection_action->setEnabled (have_tabs);
218  m_smart_indent_line_or_selection_action->setEnabled (have_tabs);
219 
220  m_context_help_action->setEnabled (have_tabs);
221  m_context_doc_action->setEnabled (have_tabs);
222 
223  m_view_editor_menu->setEnabled (have_tabs);
224  m_zoom_in_action->setEnabled (have_tabs);
225  m_zoom_out_action->setEnabled (have_tabs);
226  m_zoom_normal_action->setEnabled (have_tabs);
227 
228  m_find_action->setEnabled (have_tabs);
229  m_find_next_action->setEnabled (have_tabs);
230  m_find_previous_action->setEnabled (have_tabs);
231  m_print_action->setEnabled (have_tabs);
232  m_run_action->setEnabled (have_tabs);
233 
234  m_edit_function_action->setEnabled (have_tabs);
235  m_save_action->setEnabled (have_tabs);
236  m_save_as_action->setEnabled (have_tabs);
237  m_close_action->setEnabled (have_tabs);
238  m_close_all_action->setEnabled (have_tabs);
239  m_close_others_action->setEnabled (have_tabs && m_tab_widget->count () > 1);
240  m_sort_tabs_action->setEnabled (have_tabs && m_tab_widget->count () > 1);
241 
242  emit editor_tabs_changed_signal (have_tabs);
243  }
244 
245  // empty_script determines whether we have to create an empty script
246  // 1. At startup, when the editor has to be (really) visible
247  // (Here we can not use the visibility changed signal)
248  // 2. When the editor becomes visible when octave is running
249  void file_editor::empty_script (bool startup, bool visible)
250  {
254  global_use_custom_editor.def).toBool ())
255  return; // do not open an empty script in the external editor
256 
257  bool real_visible;
258 
259  if (startup)
260  real_visible = isVisible ();
261  else
262  real_visible = visible;
263 
264  if (! real_visible || m_tab_widget->count () > 0)
265  return;
266 
267  if (startup && ! isFloating ())
268  {
269  // check if editor is really visible or hidden between tabbed widgets
270  QList<QTabBar *> tab_list = main_win ()->findChildren<QTabBar *>();
271 
272  bool in_tab = false;
273  int i = 0;
274  while ((i < tab_list.count ()) && (! in_tab))
275  {
276  QTabBar *tab = tab_list.at (i);
277  i++;
278 
279  int j = 0;
280  while ((j < tab->count ()) && (! in_tab))
281  {
282  // check all tabs for the editor
283  if (tab->tabText (j) == windowTitle ())
284  {
285  // editor is in this tab widget
286  in_tab = true;
287  int top = tab->currentIndex ();
288  if (! (top > -1 && tab->tabText (top) == windowTitle ()))
289  return; // not current tab -> not visible
290  }
291  j++;
292  }
293  }
294  }
295 
296  request_new_file ("");
297  }
298 
300  {
301  //restore previous session
302  if (! settings->value (ed_restore_session).toBool ())
303  return;
304 
305  // get the data from the settings file
306  QStringList sessionFileNames
307  = settings->value (ed_session_names).toStringList ();
308 
309  QStringList session_encodings
310  = settings->value (ed_session_enc).toStringList ();
311 
312  QStringList session_index
313  = settings->value (ed_session_ind).toStringList ();
314 
315  QStringList session_lines
316  = settings->value (ed_session_lines).toStringList ();
317 
318  // fill a list of the struct and sort it (depending on index)
319  QList<session_data> s_data;
320 
321  bool do_encoding = (session_encodings.count () == sessionFileNames.count ());
322  bool do_index = (session_index.count () == sessionFileNames.count ());
323  bool do_lines = (session_lines.count () == sessionFileNames.count ());
324 
325  for (int n = 0; n < sessionFileNames.count (); ++n)
326  {
327  QFileInfo file = QFileInfo (sessionFileNames.at (n));
328  if (! file.exists ())
329  continue;
330 
331  session_data item = { 0, -1, sessionFileNames.at (n),
332  QString (), QString ()};
333  if (do_lines)
334  item.line = session_lines.at (n).toInt ();
335  if (do_index)
336  item.index = session_index.at (n).toInt ();
337  if (do_encoding)
338  item.encoding = session_encodings.at (n);
339 
340  s_data << item;
341  }
342 
343  std::sort (s_data.begin (), s_data.end ());
344 
345  // finally open the files with the desired encoding in the desired order
346  for (int n = 0; n < s_data.count (); ++n)
347  request_open_file (s_data.at (n).file_name, s_data.at (n).encoding,
348  s_data.at (n).line);
349  }
350 
352  {
353  if (m_no_focus)
354  return; // No focus for the editor if external open/close request
355 
357 
358  // set focus to current tab
359  reset_focus ();
360  }
361 
363  {
364  setFocus ();
365 
366  // set focus to desired tab
367  if (fet)
368  m_tab_widget->setCurrentWidget (fet);
369  }
370 
371  // function enabling/disabling the menu accelerators depending on the
372  // focus of the editor
374  {
375  // Hide or show the find dialog together with the focus of the
376  // editor widget depending on the overall visibility of the find dialog.
377  // Do not change internal visibility state.
378  if (m_find_dialog)
379  m_find_dialog->set_visible (enable);
380 
381  // Take care of the shortcuts
382  QHash<QMenu*, QStringList>::const_iterator i = m_hash_menu_text.constBegin ();
383 
384  while (i != m_hash_menu_text.constEnd ())
385  {
386  i.key ()->setTitle (i.value ().at (! enable));
387  ++i;
388  }
389 
390  // when editor loses focus, enable the actions, which are always active
391  // in the main window due to missing info on selected text and undo actions
393  {
394  if (enable)
395  {
396  m_copy_action->setEnabled (m_copy_action_enabled);
397  m_undo_action->setEnabled (m_undo_action_enabled);
398  }
399  else
400  {
401  m_copy_action_enabled = m_copy_action->isEnabled ();
402  m_undo_action_enabled = m_undo_action->isEnabled ();
403  m_copy_action->setEnabled (true);
404  m_undo_action->setEnabled (true);
405  }
406  }
407  }
408 
409  // Save open files for restoring in next session
410  // (even if last session will not be restored next time)
411  // together with encoding and the tab index
413  {
416 
417  QStringList fetFileNames;
418  QStringList fet_encodings;
419  QStringList fet_index;
420  QStringList fet_lines;
421 
422  std::list<file_editor_tab *> editor_tab_lst = m_tab_widget->tab_list ();
423 
424  for (auto editor_tab : editor_tab_lst)
425  {
426  QString file_name = editor_tab->file_name ();
427 
428  // Don't append unnamed files.
429 
430  if (! file_name.isEmpty ())
431  {
432  fetFileNames.append (file_name);
433  fet_encodings.append (editor_tab->encoding ());
434 
435  QString index;
436  fet_index.append (index.setNum (m_tab_widget->indexOf (editor_tab)));
437 
438  int l, c;
439  editor_tab->qsci_edit_area ()->getCursorPosition (&l, &c);
440  fet_lines.append (index.setNum (l + 1));
441  }
442  }
443 
444  settings->setValue (ed_session_names.key, fetFileNames);
445  settings->setValue (ed_session_enc.key, fet_encodings);
446  settings->setValue (ed_session_ind.key, fet_index);
447  settings->setValue (ed_session_lines.key, fet_lines);
448  settings->sync ();
449  }
450 
452  {
453  // When the application or the editor is closing and the user wants to
454  // close all files, in the latter case all editor tabs are checked whether
455  // they need to be saved. During these checks tabs are not closed since
456  // the user might cancel closing Octave during one of these saving dialogs.
457  // Therefore, saving the session for restoring at next start is not done
458  // before the application is definitely closing.
459 
460  // Save the session. Even is closing is cancelled, this would be
461  // overwritten by the next attempt to close the editor
462  save_session ();
463 
464  std::list<file_editor_tab *> fe_tab_lst = m_tab_widget->tab_list ();
465  m_number_of_tabs = fe_tab_lst.size ();
466 
467  for (auto fe_tab : fe_tab_lst)
468  {
469  // Wait for all editor tabs to have saved their files if required
470 
471  connect (fe_tab, SIGNAL (tab_ready_to_close (void)),
472  this, SLOT (handle_tab_ready_to_close (void)),
473  Qt::UniqueConnection);
474  }
475 
476  m_closing_canceled = false;
477 
478  for (auto fe_tab : fe_tab_lst)
479  {
480  // If there was a cancellation, make the already saved/discarded tabs
481  // recover from the exit by removing the read-only state and by
482  // recovering the debugger breakpoints. Finally return false in order
483  // to cancel closing the application or the editor.
484 
485  if (fe_tab->check_file_modified (false) == QMessageBox::Cancel)
486  {
487  emit fetab_recover_from_exit ();
488 
489  m_closing_canceled = true;
490 
491  for (auto fet : fe_tab_lst)
492  disconnect (fet, SIGNAL (tab_ready_to_close (void)), 0, 0 );
493 
494  return false;
495  }
496  }
497 
498  return true;
499  }
500 
502  {
503  if (m_closing_canceled)
504  return;
505 
507 
508  if (m_number_of_tabs > 0)
509  return;
510 
511  // Here, the application or the editor will be closed -> store the session
512 
513  // Take care of the find dialog
514  if (m_find_dialog)
515  m_find_dialog->close ();
516 
517  // Finally close all the tabs and return indication that we can exit
518  // the application or close the editor.
519  // Closing and deleting the tabs makes the editor visible. In case it was
520  // hidden before, this state has to be restored afterwards.
521  bool vis = isVisible ();
522 
523  std::list<file_editor_tab *> editor_tab_lst = m_tab_widget->tab_list ();
524  for (auto editor_tab : editor_tab_lst)
525  delete editor_tab;
526 
527  m_tab_widget->clear ();
528 
529  setVisible (vis);
530  }
531 
532  void file_editor::request_new_file (const QString& commands)
533  {
534  // Custom editor? If yes, we can only call the editor without passing
535  // some initial contents and even without being sure a new file is opened
536  if (call_custom_editor ())
537  return;
538 
539  // New file isn't a file_editor_tab function since the file
540  // editor tab has yet to be created and there is no object to
541  // pass a signal to. Hence, functionality is here.
542 
543  file_editor_tab *fileEditorTab = make_file_editor_tab (m_ced);
544  add_file_editor_tab (fileEditorTab, ""); // new tab with empty title
545  fileEditorTab->new_file (commands); // title is updated here
546  activate (); // focus editor and new tab
547  }
548 
550  {
551  file_editor_tab *editor_tab
552  = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());
553  editor_tab->conditional_close ();
554  }
555 
557  {
558  file_editor_tab *editor_tab;
559 
560  // loop over all tabs starting from last one otherwise deletion changes index
561  for (int index = m_tab_widget->count ()-1; index >= 0; index--)
562  {
563  editor_tab = static_cast<file_editor_tab *> (m_tab_widget->widget (index));
564  editor_tab->conditional_close ();
565  }
566  }
567 
569  {
570  file_editor_tab *editor_tab;
571  QWidget *tabID = m_tab_widget->currentWidget ();
572 
573  // loop over all tabs starting from last one otherwise deletion changes index
574  for (int index = m_tab_widget->count ()-1; index >= 0; index--)
575  {
576  if (tabID != m_tab_widget->widget (index))
577  {
578  editor_tab
579  = static_cast<file_editor_tab *> (m_tab_widget->widget (index));
580  editor_tab->conditional_close ();
581  }
582  }
583  }
584 
585  // open a file from the mru list
586  void file_editor::request_mru_open_file (QAction *action)
587  {
588  if (action)
589  {
590  request_open_file (action->data ().toStringList ().at (0),
591  action->data ().toStringList ().at (1));
592  }
593  }
594 
596  {
597  emit fetab_print_file (m_tab_widget->currentWidget ());
598  }
599 
601  {
602  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
603  QsciScintillaBase::SCI_REDO);
604  }
605 
607  {
608  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
609  QsciScintillaBase::SCI_CUT);
610  }
611 
613  {
614  emit fetab_context_help (m_tab_widget->currentWidget (), false);
615  }
616 
618  {
619  emit fetab_context_help (m_tab_widget->currentWidget (), true);
620  }
621 
623  {
624  emit fetab_context_edit (m_tab_widget->currentWidget ());
625  }
626 
628  {
629  emit fetab_save_file (m_tab_widget->currentWidget ());
630  }
631 
633  {
634  emit fetab_save_file_as (m_tab_widget->currentWidget ());
635  }
636 
638  {
639  emit interpreter_event
640  ([this] (interpreter& interp)
641  {
642  // INTERPRETER THREAD
643 
644  tree_evaluator& tw = interp.get_evaluator ();
645 
646  if (tw.in_debug_repl ())
647  emit request_dbcont_signal ();
648  else
649  emit fetab_run_file (m_tab_widget->currentWidget ());
650  });
651  }
652 
654  {
655  emit fetab_run_file (m_tab_widget->currentWidget (), true);
656  }
657 
659  {
660  emit fetab_context_run (m_tab_widget->currentWidget ());
661  }
662 
664  {
665  emit fetab_toggle_bookmark (m_tab_widget->currentWidget ());
666  }
667 
669  {
670  emit fetab_next_bookmark (m_tab_widget->currentWidget ());
671  }
672 
674  {
675  emit fetab_previous_bookmark (m_tab_widget->currentWidget ());
676  }
677 
679  {
680  emit fetab_remove_bookmark (m_tab_widget->currentWidget ());
681  }
682 
684  {
685  emit fetab_move_match_brace (m_tab_widget->currentWidget (), false);
686  }
687 
689  {
690  emit fetab_move_match_brace (m_tab_widget->currentWidget (), true);
691  }
692 
693  // FIXME: What should this do with conditional breakpoints?
695  {
696  emit fetab_toggle_breakpoint (m_tab_widget->currentWidget ());
697  }
698 
700  {
701  emit fetab_next_breakpoint (m_tab_widget->currentWidget ());
702  }
703 
705  {
706  emit fetab_previous_breakpoint (m_tab_widget->currentWidget ());
707  }
708 
710  {
711  emit fetab_remove_all_breakpoints (m_tab_widget->currentWidget ());
712  }
713 
714  // slots for Edit->Commands actions
716  {
717  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
718  QsciScintillaBase::SCI_DELWORDLEFT);
719  }
720 
722  {
723  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
724  QsciScintillaBase::SCI_DELWORDRIGHT);
725  }
726 
728  {
729  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
730  QsciScintillaBase::SCI_DELLINELEFT);
731  }
732 
734  {
735  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
736  QsciScintillaBase::SCI_DELLINERIGHT);
737  }
738 
740  {
741  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
742  QsciScintillaBase::SCI_LINEDELETE);
743  }
744 
746  {
747  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
748  QsciScintillaBase::SCI_LINECOPY);
749  }
750 
752  {
753  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
754  QsciScintillaBase::SCI_LINECUT);
755  }
756 
758  {
759  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
760  QsciScintillaBase::SCI_SELECTIONDUPLICATE);
761  }
762 
764  {
765  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
766  QsciScintillaBase::SCI_LINETRANSPOSE);
767  }
768 
770  {
771  emit fetab_comment_selected_text (m_tab_widget->currentWidget (), false);
772  }
773 
775  {
776  emit fetab_uncomment_selected_text (m_tab_widget->currentWidget ());
777  }
778 
780  {
781  emit fetab_comment_selected_text (m_tab_widget->currentWidget (), true);
782  }
783 
784  // slots for Edit->Format actions
786  {
787  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
788  QsciScintillaBase::SCI_UPPERCASE);
789  }
790 
792  {
793  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
794  QsciScintillaBase::SCI_LOWERCASE);
795  }
796 
798  {
799  emit fetab_indent_selected_text (m_tab_widget->currentWidget ());
800  }
801 
803  {
804  emit fetab_unindent_selected_text (m_tab_widget->currentWidget ());
805  }
806 
808  {
810  }
811 
813  {
814  emit fetab_convert_eol (m_tab_widget->currentWidget (),
815  QsciScintilla::EolWindows);
816  }
817  void
819  {
820  emit fetab_convert_eol (m_tab_widget->currentWidget (),
821  QsciScintilla::EolUnix);
822  }
823 
825  {
826  emit fetab_convert_eol (m_tab_widget->currentWidget (),
827  QsciScintilla::EolMac);
828  }
829 
830  // Slot for initially creating and showing the find dialog
832  {
833  // Create the dialog
834  find_create ();
835 
836  // Since find_create shows the dialog without activating the widget
837  // (which is reuqired in other cases) do this manually here
838  m_find_dialog->activateWindow ();
839 
840  // Initiate search text from possible selection and save the initial
841  // data from the dialog on the defined structure
842  m_find_dialog->init_search_text ();
843  }
844 
845  // This method creates the find dialog.
846 
848  {
849  if (m_find_dialog)
850  m_find_dialog->close ();
851 
852  if (isFloating ())
853  m_find_dialog = new find_dialog (m_octave_qobj, this, this);
854  else
856 
857  // Add required actions
858  m_find_dialog->addAction (m_find_next_action);
860 
861  // Update edit area
862  file_editor_tab* fet
863  = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());
864  m_find_dialog->update_edit_area (fet->qsci_edit_area ());
865 
866  // Icon is the same as the editor
867  m_find_dialog->setWindowIcon (windowIcon ());
868 
869  // Position: lower right of editor's position
870  int xp = x () + frameGeometry ().width ();
871  int yp = y () + frameGeometry ().height ();
872 
873  if (! isFloating ())
874  {
875  // Fix position if editor is docked
876  xp = xp + main_win ()->x();
877  yp = yp + main_win ()->y();
878  }
879 
880  if (yp < 0)
881  yp = 0;
882 
883  // The size of the find dialog is considered in restore_settings
884  // since its size might change depending on the options
885  m_find_dialog->restore_settings (QPoint (xp, yp));
886 
887  // Set visible
888  m_find_dialog->set_visible (true);
889  }
890 
892  {
893  if (m_find_dialog)
894  m_find_dialog->find_next ();
895  }
896 
898  {
899  if (m_find_dialog)
900  m_find_dialog->find_prev ();
901  }
902 
904  {
905  emit fetab_goto_line (m_tab_widget->currentWidget ());
906  }
907 
909  {
910  emit fetab_completion (m_tab_widget->currentWidget ());
911  }
912 
913  void file_editor::handle_file_name_changed (const QString& fname,
914  const QString& tip,
915  bool modified)
916  {
917  QObject *fileEditorTab = sender ();
918  if (fileEditorTab)
919  {
921 
922  for (int i = 0; i < m_tab_widget->count (); i++)
923  {
924  if (m_tab_widget->widget (i) == fileEditorTab)
925  {
926  m_tab_widget->setTabText (i, fname);
927  m_tab_widget->setTabToolTip (i, tip);
928  if (modified)
929  m_tab_widget->setTabIcon (i, rmgr.icon ("document-save"));
930  else
931  m_tab_widget->setTabIcon (i, QIcon ());
932  }
933  }
934  }
935  }
936 
938  {
939  file_editor_tab *editor_tab
940  = static_cast<file_editor_tab *> (m_tab_widget->widget (index));
941  editor_tab->conditional_close ();
942  }
943 
944  void
946  {
947  QObject *fileEditorTab = sender ();
948  if (fileEditorTab)
949  {
950  for (int i = 0; i < m_tab_widget->count (); i++)
951  {
952  if (m_tab_widget->widget (i) == fileEditorTab)
953  {
954  m_tab_widget->removeTab (i);
955  // Deleting sender is dodgy, but works because the signal
956  // is the last item in the sender's routines.
957  // FIXME: can we use deleteLater here?
958  delete fileEditorTab;
959  break;
960  }
961  }
962  }
963  check_actions ();
964 
965  activate (); // focus stays in editor when tab is closed
966 
967  }
968 
969  // context menu of edit area
971  {
972  emit fetab_change_request (m_tab_widget->widget (index));
973  activate ();
974  }
975 
976  void file_editor::handle_editor_state_changed (bool copy_available,
977  bool is_octave_file)
978  {
979  // In case there is some scenario where traffic could be coming from
980  // all the file editor tabs, just process info from the current active tab.
981  if (sender () == m_tab_widget->currentWidget ())
982  {
983  if (m_copy_action)
984  m_copy_action->setEnabled (copy_available);
985  m_cut_action->setEnabled (copy_available);
986  m_run_selection_action->setEnabled (copy_available);
987  m_run_action->setEnabled (is_octave_file);
988  }
989 
990  m_copy_action_enabled = m_copy_action->isEnabled ();
991  m_undo_action_enabled = m_undo_action->isEnabled ();
992  }
993 
994  void file_editor::handle_mru_add_file (const QString& file_name,
995  const QString& encoding)
996  {
997  int index;
998  while ((index = m_mru_files.indexOf (file_name)) >= 0)
999  {
1000  m_mru_files.removeAt (index);
1001  m_mru_files_encodings.removeAt (index);
1002  }
1003 
1004  m_mru_files.prepend (file_name);
1005  m_mru_files_encodings.prepend (encoding);
1006 
1007  mru_menu_update ();
1008  }
1009 
1010  void file_editor::check_conflict_save (const QString& saveFileName,
1011  bool remove_on_success)
1012  {
1013  // Check whether this file is already open in the editor.
1014  file_editor_tab *tab = find_tab_widget (saveFileName);
1015 
1016  if (tab)
1017  {
1018  // Note: to overwrite the contents of some other file editor tab
1019  // with the same name requires identifying which file editor tab
1020  // that is (not too difficult) then closing that tab. Of course,
1021  // that could trigger another dialog box if the file editor tab
1022  // with the same name has modifications in it. This could become
1023  // somewhat confusing to the user. For now, opt to do nothing.
1024 
1025  // Create a NonModal message about error.
1026  QMessageBox *msgBox
1027  = new QMessageBox (QMessageBox::Critical, tr ("Octave Editor"),
1028  tr ("File not saved! A file with the selected name\n%1\n"
1029  "is already open in the editor").
1030  arg (saveFileName),
1031  QMessageBox::Ok, nullptr);
1032 
1033  msgBox->setWindowModality (Qt::NonModal);
1034  msgBox->setAttribute (Qt::WA_DeleteOnClose);
1035  msgBox->show ();
1036 
1037  return;
1038  }
1039 
1040  QObject *saveFileObject = sender ();
1041  QWidget *saveFileWidget = nullptr;
1042 
1043  for (int i = 0; i < m_tab_widget->count (); i++)
1044  {
1045  if (m_tab_widget->widget (i) == saveFileObject)
1046  {
1047  saveFileWidget = m_tab_widget->widget (i);
1048  break;
1049  }
1050  }
1051  if (! saveFileWidget)
1052  {
1053  // Create a NonModal message about error.
1054  QMessageBox *msgBox
1055  = new QMessageBox (QMessageBox::Critical, tr ("Octave Editor"),
1056  tr ("The associated file editor tab has disappeared."),
1057  QMessageBox::Ok, nullptr);
1058 
1059  msgBox->setWindowModality (Qt::NonModal);
1060  msgBox->setAttribute (Qt::WA_DeleteOnClose);
1061  msgBox->show ();
1062 
1063  return;
1064  }
1065 
1066  // Can save without conflict, have the file editor tab do so.
1067  emit fetab_save_file (saveFileWidget, saveFileName, remove_on_success);
1068  }
1069 
1071  int line)
1072  {
1073  request_open_file (file, QString (), line, true); // default encoding
1074  }
1075 
1077  int line)
1078  {
1079  if (! file.isEmpty ())
1080  {
1081  // Check whether this file is already open in the editor.
1082  file_editor_tab *tab = find_tab_widget (file);
1083 
1084  if (tab)
1085  {
1086  m_tab_widget->setCurrentWidget (tab);
1087 
1088  if (line > 0)
1089  emit fetab_delete_debugger_pointer (tab, line);
1090 
1091  emit fetab_set_focus (tab);
1092  }
1093  }
1094  }
1095 
1097  const QString& file,
1098  int line,
1099  const QString& cond)
1100  {
1101  request_open_file (file, QString (), line, false, true, insert, cond);
1102  }
1103 
1104  void file_editor::handle_edit_file_request (const QString& file)
1105  {
1106  request_open_file (file);
1107  }
1108 
1109  // Slot used for signals indicating that a file was changed/renamed or
1110  // is going to be deleted/renamed
1111  void file_editor::handle_file_remove (const QString& old_name,
1112  const QString& new_name)
1113  {
1114  // Clear old list of file data and declare a structure for file data
1115  m_tmp_closed_files.clear ();
1116  session_data f_data;
1117 
1118  // Preprocessing old name(s)
1119  QString old_name_clean = old_name.trimmed ();
1120  int s = old_name_clean.size ();
1121 
1122  if (old_name_clean.at (0) == QChar ('\"')
1123  && old_name_clean.at (s - 1) == QChar ('\"'))
1124  old_name_clean = old_name_clean.mid (1, s - 2);
1125 
1126  QStringList old_names = old_name_clean.split ("\" \"");
1127 
1128  // Check if new name is a file or directory
1129  QFileInfo newf (new_name);
1130  bool new_is_dir = newf.isDir ();
1131 
1132  // Now loop over all old files/dirs (several files by movefile ())
1133  for (int i = 0; i < old_names.count (); i++)
1134  {
1135  // Check if old name is a file or directory
1136  QFileInfo old (old_names.at (i));
1137 
1138  if (old.isDir ())
1139  {
1140  // Call the function which handles directories and return
1141  handle_dir_remove (old_names.at (i), new_name);
1142  }
1143  else
1144  {
1145  // It is a single file. Is it open?
1146  file_editor_tab *editor_tab = find_tab_widget (old_names.at (i));
1147 
1148  if (editor_tab)
1149  {
1150  // Get index and line.
1151 
1152  f_data.encoding = editor_tab->encoding ();
1153  f_data.index = m_tab_widget->indexOf (editor_tab);
1154  int l, c;
1155  editor_tab->qsci_edit_area ()->getCursorPosition (&l, &c);
1156  f_data.line = l + 1;
1157 
1158  // Close it silently
1159  m_no_focus = true; // Remember for not focussing editor
1160  editor_tab->file_has_changed (QString (), true); // Close the tab
1161  m_no_focus = false; // Back to normal
1162 
1163  // For reloading old file if error while removing
1164  f_data.file_name = old_names.at (i);
1165  // For reloading new file (if new_file is not empty)
1166  if (new_is_dir)
1167  {
1168  std::string ndir = new_name.toStdString ();
1169  std::string ofile = old.fileName ().toStdString ();
1170  f_data.new_file_name
1172  }
1173  else
1174  f_data.new_file_name = new_name;
1175 
1176  // Add file data to list
1177  m_tmp_closed_files << f_data;
1178  }
1179  }
1180  }
1181  }
1182 
1183  // Slot for signal indicating that a file was renamed
1185  {
1186  m_no_focus = true; // Remember for not focussing editor
1187 
1188  // Loop over all files that have to be reloaded. Start at the end of the
1189  // list, otherwise the stored indexes are not correct.
1190  for (int i = m_tmp_closed_files.count () - 1; i >= 0; i--)
1191  {
1192  // Load old or new file
1193  if (load_new)
1194  {
1195  if (! m_tmp_closed_files.at (i).new_file_name.isEmpty ())
1196  request_open_file (m_tmp_closed_files.at (i).new_file_name,
1197  m_tmp_closed_files.at (i).encoding,
1198  m_tmp_closed_files.at (i).line,
1199  false, false, true, "",
1200  m_tmp_closed_files.at (i).index);
1201  }
1202  else
1203  {
1204  request_open_file (m_tmp_closed_files.at (i).file_name,
1205  m_tmp_closed_files.at (i).encoding,
1206  m_tmp_closed_files.at (i).line,
1207  false, false, true, "",
1208  m_tmp_closed_files.at (i).index);
1209  }
1210 
1211  }
1212 
1213  m_no_focus = false; // Back to normal focus
1214 
1215  // Clear the list of file data
1216  m_tmp_closed_files.clear ();
1217  }
1218 
1220  {
1221  int size_idx = settings->value (global_icon_size).toInt ();
1222  size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2
1223 
1224  QStyle *st = style ();
1225  int icon_size = st->pixelMetric (global_icon_sizes[size_idx]);
1226  m_tool_bar->setIconSize (QSize (icon_size, icon_size));
1227 
1228  // Tab position
1229  QTabWidget::TabPosition pos
1230  = static_cast<QTabWidget::TabPosition> (settings->value (ed_tab_position).toInt ());
1231 
1232  m_tab_widget->setTabPosition (pos);
1233 
1234  // Update style sheet properties depending on position
1235  QString width_str ("width");
1236  QString height_str ("height");
1237  if (pos == QTabWidget::West || pos == QTabWidget::East)
1238  {
1239  width_str = QString ("height");
1240  height_str = QString ("width");
1241  }
1242 
1243  // Min and max width for full path titles
1244  int tab_width_min = settings->value (ed_notebook_tab_width_min)
1245  .toInt ();
1246  int tab_width_max = settings->value (ed_notebook_tab_width_max)
1247  .toInt ();
1248 
1249  // Get suitable height of a tab related to font and icon size
1250  int height = 1.5*QFontMetrics (m_tab_widget->font ()).height ();
1251  int is = 1.5*m_tab_widget->iconSize ().height ();
1252  if (is > height)
1253  height = is;
1254 
1255  // Style sheet for tab height
1256  QString style_sheet = QString ("QTabBar::tab {max-" + height_str + ": %1px;}")
1257  .arg (height);
1258 
1259  // Style sheet for tab height together with width
1260  if (settings->value (ed_long_window_title).toBool ())
1261  {
1262  style_sheet = QString ("QTabBar::tab "
1263  " {max-" + height_str + ": %1px;"
1264  " min-" + width_str + ": %2px;"
1265  " max-" + width_str + ": %3px;}")
1266  .arg (height).arg (tab_width_min).arg (tab_width_max);
1267  m_tab_widget->setElideMode (Qt::ElideLeft);
1268  }
1269  else
1270  {
1271  m_tab_widget->setElideMode (Qt::ElideNone);
1272  }
1273 
1274 #if defined (Q_OS_MAC)
1275  // FIXME: This is a workaround for missing tab close buttons on MacOS
1276  // in several Qt versions (https://bugreports.qt.io/browse/QTBUG-61092)
1277  QString close_button_css
1278  ("QTabBar::close-button"
1279  " { width: 6px; image: url(:/actions/icons/widget-close.png);}\n"
1280  "QTabBar::close-button:hover"
1281  " { background-color: #cccccc; }");
1282 
1283  style_sheet = style_sheet + close_button_css;
1284 #endif
1285 
1286  m_tab_widget->setStyleSheet (style_sheet);
1287 
1288  bool show_it;
1289  show_it = settings->value (ed_show_line_numbers).toBool ();
1290  m_show_linenum_action->setChecked (show_it);
1291  show_it = settings->value (ed_show_white_space).toBool ();
1292  m_show_whitespace_action->setChecked (show_it);
1293  show_it = settings->value (ed_show_eol_chars).toBool ();
1294  m_show_eol_action->setChecked (show_it);
1295  show_it = settings->value (ed_show_indent_guides).toBool ();
1296  m_show_indguide_action->setChecked (show_it);
1297  show_it = settings->value (ed_long_line_marker).toBool ();
1298  m_show_longline_action->setChecked (show_it);
1299 
1300  show_it = settings->value (ed_show_toolbar).toBool ();
1301  m_show_toolbar_action->setChecked (show_it);
1302  m_tool_bar->setVisible (show_it);
1303  show_it = settings->value (ed_show_edit_status_bar).toBool ();
1304  m_show_statusbar_action->setChecked (show_it);
1305  show_it = settings->value (ed_show_hscroll_bar).toBool ();
1306  m_show_hscrollbar_action->setChecked (show_it);
1307 
1308  set_shortcuts ();
1309 
1310  // Find dialog with the same icon as the editor
1311  if (m_find_dialog)
1312  m_find_dialog->setWindowIcon (windowIcon ());
1313 
1314  // Relay signal to file editor tabs.
1316  }
1317 
1319  {
1320  // Shortcuts also available in the main window, as well as the related
1321  // shortcuts, are defined in main_window and added to the editor
1322 
1324 
1325  // File menu
1333 
1334  // Edit menu
1340 
1353 
1369 
1373 
1374  // View menu
1387 
1388  // Debug menu
1393 
1394  // Run menu
1397 
1398  // Help menu
1401 
1402  // Tab navigation without menu entries
1407 
1408  }
1409 
1410  // This slot is a reimplementation of the virtual slot in octave_dock_widget.
1411  // We need this for creating an empty script when the editor has no open
1412  // files and is made visible.
1414  {
1415  if (m_closed && visible)
1416  {
1417  m_closed = false;
1419  gui_settings *settings = rmgr.get_settings ();
1421  }
1422 
1423  empty_script (false, visible);
1424 
1425  if (visible && ! isFloating ())
1426  setFocus ();
1427  }
1428 
1429  // This slot is a reimplementation of the virtual slot in octave_dock_widget.
1430  // We need this for updating the parent of the find dialog
1432  {
1433  if (m_find_dialog)
1434  {
1435  // close current dialog
1436  m_find_dialog->close ();
1437 
1438  // re-create dialog with the new parent (editor or main-win)
1439  find_create ();
1440  m_find_dialog->activateWindow ();
1441  }
1442  }
1443 
1444  void file_editor::update_octave_directory (const QString& dir)
1445  {
1446  m_ced = dir;
1447  emit fetab_set_directory (m_ced); // for save dialog
1448  }
1449 
1451  {
1452  if (editor_tab_has_focus ())
1453  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
1454  QsciScintillaBase::SCI_COPY);
1455  }
1456 
1458  {
1459  if (editor_tab_has_focus ())
1460  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
1461  QsciScintillaBase::SCI_PASTE);
1462  }
1463 
1465  {
1466  if (editor_tab_has_focus ())
1467  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
1468  QsciScintillaBase::SCI_SELECTALL);
1469  }
1470 
1472  {
1473  if (editor_tab_has_focus ())
1474  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
1475  QsciScintillaBase::SCI_UNDO);
1476  }
1477 
1478  // Open a file, if not already open, and mark the current execution location
1479  // and/or a breakpoint with condition cond.
1480  void file_editor::request_open_file (const QString& openFileName,
1481  const QString& encoding,
1482  int line, bool debug_pointer,
1483  bool breakpoint_marker, bool insert,
1484  const QString& cond, int index)
1485  {
1486  if (call_custom_editor (openFileName, line))
1487  return; // custom editor called
1488 
1490  gui_settings *settings = rmgr.get_settings ();
1491  bool show_dbg_file
1492  = settings->value (ed_show_dbg_file).toBool ();
1493 
1494  if (openFileName.isEmpty ())
1495  {
1496  // This happens if edit is called without an argument
1497  // Open editor with empty edit area instead (as new file would do)
1498  request_new_file ("");
1499  }
1500  else
1501  {
1502  // Check whether this file is already open in the editor.
1503  file_editor_tab *tab = find_tab_widget (openFileName);
1504 
1505  if (tab)
1506  {
1507  m_tab_widget->setCurrentWidget (tab);
1508 
1509  if (line > 0)
1510  {
1511  if (insert)
1512  emit fetab_goto_line (tab, line);
1513 
1514  if (debug_pointer)
1515  emit fetab_insert_debugger_pointer (tab, line);
1516 
1517  if (breakpoint_marker)
1518  emit fetab_do_breakpoint_marker (insert, tab, line, cond);
1519  }
1520 
1521  if (show_dbg_file && ! ((breakpoint_marker || debug_pointer)
1522  && is_editor_console_tabbed ()))
1523  {
1524  emit fetab_set_focus (tab);
1525  activate ();
1526  }
1527  }
1528  else
1529  {
1530  if (! show_dbg_file && (breakpoint_marker || debug_pointer))
1531  return; // Do not open a file for showing dbg markers
1532 
1533  if (breakpoint_marker && ! insert)
1534  return; // Never open a file when removing breakpoints
1535 
1536  file_editor_tab *fileEditorTab = nullptr;
1537  // Reuse <unnamed> tab if it hasn't yet been modified.
1538  bool reusing = false;
1539  tab = find_tab_widget ("");
1540  if (tab)
1541  {
1542  fileEditorTab = tab;
1543  if (fileEditorTab->qsci_edit_area ()->isModified ())
1544  fileEditorTab = nullptr;
1545  else
1546  reusing = true;
1547  }
1548 
1549  // If <unnamed> was absent or modified, create a new tab.
1550  if (! fileEditorTab)
1551  fileEditorTab = make_file_editor_tab ();
1552 
1553  fileEditorTab->set_encoding (encoding);
1554  QString result = fileEditorTab->load_file (openFileName);
1555  if (result == "")
1556  {
1557  // Supply empty title then have the file_editor_tab update
1558  // with full or short name.
1559  if (! reusing)
1560  add_file_editor_tab (fileEditorTab, "", index);
1561  fileEditorTab->update_window_title (false);
1562  // file already loaded, add file to mru list here
1563  QFileInfo file_info = QFileInfo (openFileName);
1564  handle_mru_add_file (file_info.canonicalFilePath (),
1565  encoding);
1566 
1567  if (line > 0)
1568  {
1569  if (insert)
1570  emit fetab_goto_line (fileEditorTab, line);
1571 
1572  if (debug_pointer)
1573  emit fetab_insert_debugger_pointer (fileEditorTab,
1574  line);
1575  if (breakpoint_marker)
1576  emit fetab_do_breakpoint_marker (insert, fileEditorTab,
1577  line, cond);
1578  }
1579  }
1580  else
1581  {
1582  delete fileEditorTab;
1583  fileEditorTab = nullptr;
1584 
1585  if (QFile::exists (openFileName))
1586  {
1587  // File not readable:
1588  // create a NonModal message about error.
1589  QMessageBox *msgBox
1590  = new QMessageBox (QMessageBox::Critical,
1591  tr ("Octave Editor"),
1592  tr ("Could not open file\n%1\nfor read: %2.").
1593  arg (openFileName).arg (result),
1594  QMessageBox::Ok, this);
1595 
1596  msgBox->setWindowModality (Qt::NonModal);
1597  msgBox->setAttribute (Qt::WA_DeleteOnClose);
1598  msgBox->show ();
1599  }
1600  else
1601  {
1602  // File does not exist, should it be created?
1603  bool create_file = true;
1604  QMessageBox *msgBox;
1605 
1606  if (! settings->value (ed_create_new_file).toBool ())
1607  {
1608  msgBox = new QMessageBox (QMessageBox::Question,
1609  tr ("Octave Editor"),
1610  tr ("File\n%1\ndoes not exist. "
1611  "Do you want to create it?").arg (openFileName),
1612  QMessageBox::NoButton,nullptr);
1613  QPushButton *create_button =
1614  msgBox->addButton (tr ("Create"), QMessageBox::YesRole);
1615  msgBox->addButton (tr ("Cancel"), QMessageBox::RejectRole);
1616  msgBox->setDefaultButton (create_button);
1617  msgBox->exec ();
1618 
1619  QAbstractButton *clicked_button = msgBox->clickedButton ();
1620  if (clicked_button != create_button)
1621  create_file = false;
1622 
1623  delete msgBox;
1624  }
1625 
1626  if (create_file)
1627  {
1628  // create the file and call the editor again
1629  QFile file (openFileName);
1630  if (! file.open (QIODevice::WriteOnly))
1631  {
1632  // error opening the file
1633  msgBox = new QMessageBox (QMessageBox::Critical,
1634  tr ("Octave Editor"),
1635  tr ("Could not open file\n%1\nfor write: %2.").
1636  arg (openFileName).arg (file.errorString ()),
1637  QMessageBox::Ok, this);
1638 
1639  msgBox->setWindowModality (Qt::NonModal);
1640  msgBox->setAttribute (Qt::WA_DeleteOnClose);
1641  msgBox->show ();
1642  }
1643  else
1644  {
1645  file.close ();
1646  request_open_file (openFileName);
1647  }
1648  }
1649  }
1650  }
1651 
1652  if (! ((breakpoint_marker || debug_pointer) && is_editor_console_tabbed ()))
1653  {
1654  // update breakpoint pointers, really show editor
1655  // and the current editor tab
1656  if (fileEditorTab)
1657  fileEditorTab->update_breakpoints ();
1658  activate ();
1659  emit file_loaded_signal ();
1660  }
1661  }
1662  }
1663  }
1664 
1666  {
1667  emit request_settings_dialog ("editor");
1668  }
1669 
1671  {
1672  emit request_settings_dialog ("editor_styles");
1673  }
1674 
1676  {
1678  }
1679 
1681  {
1683  }
1684 
1686  {
1688  }
1689 
1691  {
1693  }
1694 
1696  {
1698  }
1699 
1701  {
1703  }
1704 
1706  {
1708  }
1709 
1711  {
1713  }
1714 
1716  {
1717  emit fetab_zoom_in (m_tab_widget->currentWidget ());
1718  }
1719 
1721  {
1722  emit fetab_zoom_out (m_tab_widget->currentWidget ());
1723  }
1724 
1726  {
1727  emit fetab_zoom_normal (m_tab_widget->currentWidget ());
1728  }
1729 
1731  {
1732  // remove all standard actions from scintilla
1733  QList<QAction *> all_actions = menu->actions ();
1734 
1735  for (auto *a : all_actions)
1736  menu->removeAction (a);
1737 
1738  // add editor's actions with icons and customized shortcuts
1739  menu->addAction (m_cut_action);
1740  menu->addAction (m_copy_action);
1741  menu->addAction (m_paste_action);
1742  menu->addSeparator ();
1743  menu->addAction (m_selectall_action);
1744  menu->addSeparator ();
1745  menu->addAction (m_find_files_action);
1746  menu->addAction (m_find_action);
1747  menu->addAction (m_find_next_action);
1748  menu->addAction (m_find_previous_action);
1749  menu->addSeparator ();
1750  menu->addMenu (m_edit_cmd_menu);
1751  menu->addMenu (m_edit_fmt_menu);
1752  menu->addMenu (m_edit_nav_menu);
1753  menu->addSeparator ();
1754  menu->addAction (m_run_selection_action);
1755  }
1756 
1757  void file_editor::edit_status_update (bool undo, bool redo)
1758  {
1759  if (m_undo_action)
1760  m_undo_action->setEnabled (undo);
1761  m_redo_action->setEnabled (redo);
1762  }
1763 
1764  // handler for the close event
1765  void file_editor::closeEvent (QCloseEvent *e)
1766  {
1768  gui_settings *settings = rmgr.get_settings ();
1769  if (settings->value (ed_hiding_closes_files).toBool ())
1770  {
1771  if (check_closing ())
1772  {
1773  // All tabs are closed without cancelling,
1774  // store closing state for restoring session when shown again.
1775  // Editor is closing when session data is stored in preferences
1776  m_closed = true;
1777  e->ignore ();
1778  }
1779  else
1780  {
1781  e->ignore ();
1782  return;
1783  }
1784  }
1785  else
1786  e->accept ();
1787 
1789  }
1790 
1791  void file_editor::dragEnterEvent (QDragEnterEvent *e)
1792  {
1793  if (e->mimeData ()->hasUrls ())
1794  {
1795  e->acceptProposedAction ();
1796  }
1797  }
1798 
1799  void file_editor::dropEvent (QDropEvent *e)
1800  {
1801  if (e->mimeData ()->hasUrls ())
1802  {
1803  for (const auto& url : e->mimeData ()->urls ())
1804  request_open_file (url.toLocalFile ());
1805  }
1806  }
1807 
1809  {
1810  main_window *w = static_cast<main_window *>(main_win ());
1811  QList<QDockWidget *> w_list = w->tabifiedDockWidgets (this);
1812  QDockWidget *console =
1813  static_cast<QDockWidget *> (w->get_dock_widget_list ().at (0));
1814 
1815  for (int i = 0; i < w_list.count (); i++)
1816  {
1817  if (w_list.at (i) == console)
1818  return true;
1819  }
1820 
1821  return false;
1822  }
1823 
1825  {
1826  QWidget *editor_widget = new QWidget (this);
1827 
1828  // FIXME: what was the intended purpose of this unused variable?
1829  // QStyle *editor_style = QApplication::style ();
1830 
1831  // Menu bar: do not set it native, required in macOS and Ubuntu Unity (Qt5)
1832  // for a visible menu bar in the editor widget. This property is ignored
1833  // on other platforms.
1834  m_menu_bar = new QMenuBar (editor_widget);
1835  m_menu_bar->setNativeMenuBar (false);
1836 
1837  m_tool_bar = new QToolBar (editor_widget);
1838  m_tool_bar->setMovable (true);
1839 
1840  m_tab_widget = new file_editor_tab_widget (editor_widget);
1841 
1843 
1844  // the mru-list and an empty array of actions
1845  gui_settings *settings = rmgr.get_settings ();
1846  m_mru_files = settings->value (ed_mru_file_list).toStringList ();
1848  .toStringList ();
1849 
1850  if (m_mru_files_encodings.count () != m_mru_files.count ())
1851  {
1852  // encodings don't have the same count -> do not use them!
1853  m_mru_files_encodings = QStringList ();
1854  for (int i = 0; i < m_mru_files.count (); i++)
1855  m_mru_files_encodings << QString ();
1856  }
1857 
1858  for (int i = 0; i < MaxMRUFiles; ++i)
1859  {
1860  m_mru_file_actions[i] = new QAction (this);
1861  m_mru_file_actions[i]->setVisible (false);
1862  }
1863 
1864  // menu bar
1865 
1866  // file menu
1867 
1868  m_fileMenu = add_menu (m_menu_bar, tr ("&File"));
1869 
1870  // new and open menus are inserted later by the main window
1871  m_mru_file_menu = new QMenu (tr ("&Recent Editor Files"), m_fileMenu);
1872  for (int i = 0; i < MaxMRUFiles; ++i)
1873  m_mru_file_menu->addAction (m_mru_file_actions[i]);
1874  m_fileMenu->addMenu (m_mru_file_menu);
1875 
1876  m_fileMenu->addSeparator ();
1877 
1880  tr ("&Edit Function"),
1881  SLOT (request_context_edit (bool)));
1882 
1883  m_fileMenu->addSeparator ();
1884 
1886  = add_action (m_fileMenu, rmgr.icon ("document-save"),
1887  tr ("&Save File"), SLOT (request_save_file (bool)));
1888 
1890  = add_action (m_fileMenu, rmgr.icon ("document-save-as"),
1891  tr ("Save File &As..."),
1892  SLOT (request_save_file_as (bool)));
1893 
1894  m_fileMenu->addSeparator ();
1895 
1897  = add_action (m_fileMenu, rmgr.icon ("window-close",false),
1898  tr ("&Close"), SLOT (request_close_file (bool)));
1899 
1901  = add_action (m_fileMenu, rmgr.icon ("window-close",false),
1902  tr ("Close All"), SLOT (request_close_all_files (bool)));
1903 
1905  = add_action (m_fileMenu, rmgr.icon ("window-close",false),
1906  tr ("Close Other Files"),
1907  SLOT (request_close_other_files (bool)));
1908 
1909  m_fileMenu->addSeparator ();
1910 
1912  = add_action (m_fileMenu, rmgr.icon ("document-print"),
1913  tr ("Print..."), SLOT (request_print_file (bool)));
1914 
1915  // edit menu (undo, copy, paste and select all later via main window)
1916 
1917  m_edit_menu = add_menu (m_menu_bar, tr ("&Edit"));
1918 
1920  = add_action (m_edit_menu, rmgr.icon ("edit-redo"),
1921  tr ("&Redo"), SLOT (request_redo (bool)));
1922  m_redo_action->setEnabled (false);
1923 
1924  m_edit_menu->addSeparator ();
1925 
1926  m_cut_action
1927  = add_action (m_edit_menu, rmgr.icon ("edit-cut"),
1928  tr ("Cu&t"), SLOT (request_cut (bool)));
1929  m_cut_action->setEnabled (false);
1930 
1932  = add_action (m_edit_menu, rmgr.icon ("edit-find-replace"),
1933  tr ("&Find and Replace..."), SLOT (request_find (bool)));
1934 
1936  = add_action (m_edit_menu, tr ("Find &Next..."),
1937  SLOT (request_find_next (bool)));
1938 
1940  = add_action (m_edit_menu, tr ("Find &Previous..."),
1941  SLOT (request_find_previous (bool)));
1942 
1943  m_edit_menu->addSeparator ();
1944 
1945  m_edit_cmd_menu = m_edit_menu->addMenu (tr ("&Commands"));
1946 
1948  = add_action (m_edit_cmd_menu, tr ("Delete Line"),
1949  SLOT (request_delete_line (bool)));
1950 
1952  = add_action (m_edit_cmd_menu, tr ("Copy Line"),
1953  SLOT (request_copy_line (bool)));
1954 
1956  = add_action (m_edit_cmd_menu, tr ("Cut Line"),
1957  SLOT (request_cut_line (bool)));
1958 
1959  m_edit_cmd_menu->addSeparator ();
1960 
1962  = add_action (m_edit_cmd_menu, tr ("Delete to Start of Word"),
1963  SLOT (request_delete_start_word (bool)));
1964 
1966  = add_action (m_edit_cmd_menu, tr ("Delete to End of Word"),
1967  SLOT (request_delete_end_word (bool)));
1968 
1970  = add_action (m_edit_cmd_menu, tr ("Delete to Start of Line"),
1971  SLOT (request_delete_start_line (bool)));
1972 
1974  = add_action (m_edit_cmd_menu, tr ("Delete to End of Line"),
1975  SLOT (request_delete_end_line (bool)));
1976 
1977  m_edit_cmd_menu->addSeparator ();
1978 
1980  = add_action (m_edit_cmd_menu, tr ("Duplicate Selection/Line"),
1981  SLOT (request_duplicate_selection (bool)));
1982 
1984  = add_action (m_edit_cmd_menu, tr ("Transpose Line"),
1985  SLOT (request_transpose_line (bool)));
1986 
1987  m_edit_cmd_menu->addSeparator ();
1988 
1990  = add_action (m_edit_cmd_menu, tr ("&Show Completion List"),
1991  SLOT (request_completion (bool)));
1992 
1993  m_edit_fmt_menu = m_edit_menu->addMenu (tr ("&Format"));
1994 
1996  = add_action (m_edit_fmt_menu, tr ("&Uppercase Selection"),
1997  SLOT (request_upper_case (bool)));
1998 
2000  = add_action (m_edit_fmt_menu, tr ("&Lowercase Selection"),
2001  SLOT (request_lower_case (bool)));
2002 
2003  m_edit_fmt_menu->addSeparator ();
2004 
2006  = add_action (m_edit_fmt_menu, tr ("&Comment"),
2007  SLOT (request_comment_selected_text (bool)));
2008 
2010  = add_action (m_edit_fmt_menu, tr ("&Uncomment"),
2011  SLOT (request_uncomment_selected_text (bool)));
2012 
2014  = add_action (m_edit_fmt_menu, tr ("Comment (Choosing String)"),
2015  SLOT (request_comment_var_selected_text (bool)));
2016 
2017  m_edit_fmt_menu->addSeparator ();
2018 
2020  = add_action (m_edit_fmt_menu, tr ("&Indent Selection Rigidly"),
2021  SLOT (request_indent_selected_text (bool)));
2022 
2024  = add_action (m_edit_fmt_menu, tr ("&Unindent Selection Rigidly"),
2025  SLOT (request_unindent_selected_text (bool)));
2026 
2028  = add_action (m_edit_fmt_menu, tr ("Indent Code"),
2030 
2031  m_edit_fmt_menu->addSeparator ();
2032 
2035  tr ("Convert Line Endings to &Windows (CRLF)"),
2036  SLOT (request_conv_eol_windows (bool)));
2037 
2039  = add_action (m_edit_fmt_menu, tr ("Convert Line Endings to &Unix (LF)"),
2040  SLOT (request_conv_eol_unix (bool)));
2041 
2044  tr ("Convert Line Endings to Legacy &Mac (CR)"),
2045  SLOT (request_conv_eol_mac (bool)));
2046 
2047  m_edit_nav_menu = m_edit_menu->addMenu (tr ("Navi&gation"));
2048 
2050  = add_action (m_edit_nav_menu, tr ("Go &to Line..."),
2051  SLOT (request_goto_line (bool)));
2052 
2053  m_edit_cmd_menu->addSeparator ();
2054 
2056  = add_action (m_edit_nav_menu, tr ("Move to Matching Brace"),
2057  SLOT (request_move_match_brace (bool)));
2058 
2060  = add_action (m_edit_nav_menu, tr ("Select to Matching Brace"),
2061  SLOT (request_sel_match_brace (bool)));
2062 
2063  m_edit_nav_menu->addSeparator ();
2064 
2066  = add_action (m_edit_nav_menu, tr ("&Next Bookmark"),
2067  SLOT (request_next_bookmark (bool)));
2068 
2070  = add_action (m_edit_nav_menu, tr ("Pre&vious Bookmark"),
2071  SLOT (request_previous_bookmark (bool)));
2072 
2074  = add_action (m_edit_nav_menu, tr ("Toggle &Bookmark"),
2075  SLOT (request_toggle_bookmark (bool)));
2076 
2078  = add_action (m_edit_nav_menu, tr ("&Remove All Bookmarks"),
2079  SLOT (request_remove_bookmark (bool)));
2080 
2081  m_edit_menu->addSeparator ();
2082 
2084  = add_action (m_edit_menu, rmgr.icon ("preferences-system"),
2085  tr ("&Preferences..."),
2086  SLOT (request_preferences (bool)));
2087 
2089  = add_action (m_edit_menu, rmgr.icon ("preferences-system"),
2090  tr ("&Styles Preferences..."),
2091  SLOT (request_styles_preferences (bool)));
2092 
2093  // view menu
2094 
2095  QMenu *view_menu = add_menu (m_menu_bar, tr ("&View"));
2096 
2097  m_view_editor_menu = view_menu->addMenu (tr ("&Editor"));
2098 
2100  = add_action (m_view_editor_menu, tr ("Show &Line Numbers"),
2101  SLOT (show_line_numbers (bool)));
2102  m_show_linenum_action->setCheckable (true);
2103 
2105  = add_action (m_view_editor_menu, tr ("Show &Whitespace Characters"),
2106  SLOT (show_white_space (bool)));
2107  m_show_whitespace_action->setCheckable (true);
2108 
2110  = add_action (m_view_editor_menu, tr ("Show Line &Endings"),
2111  SLOT (show_eol_chars (bool)));
2112  m_show_eol_action->setCheckable (true);
2113 
2115  = add_action (m_view_editor_menu, tr ("Show &Indentation Guides"),
2116  SLOT (show_indent_guides (bool)));
2117  m_show_indguide_action->setCheckable (true);
2118 
2120  = add_action (m_view_editor_menu, tr ("Show Long Line &Marker"),
2121  SLOT (show_long_line (bool)));
2122  m_show_longline_action->setCheckable (true);
2123 
2124  m_view_editor_menu->addSeparator ();
2125 
2127  = add_action (m_view_editor_menu, tr ("Show &Toolbar"),
2128  SLOT (show_toolbar (bool)));
2129  m_show_toolbar_action->setCheckable (true);
2130 
2132  = add_action (m_view_editor_menu, tr ("Show &Statusbar"),
2133  SLOT (show_statusbar (bool)));
2134  m_show_statusbar_action->setCheckable (true);
2135 
2137  = add_action (m_view_editor_menu, tr ("Show &Horizontal Scrollbar"),
2138  SLOT (show_hscrollbar (bool)));
2139  m_show_hscrollbar_action->setCheckable (true);
2140 
2141  view_menu->addSeparator ();
2142 
2144  = add_action (view_menu, rmgr.icon ("zoom-in"), tr ("Zoom &In"),
2145  SLOT (zoom_in (bool)));
2146 
2148  = add_action (view_menu, rmgr.icon ("zoom-out"), tr ("Zoom &Out"),
2149  SLOT (zoom_out (bool)));
2150 
2152  = add_action (view_menu, tr ("&Normal Size"), SLOT (zoom_normal (bool)));
2153 
2154  view_menu->addSeparator ();
2155 
2157  = add_action (view_menu, tr ("&Sort Tabs Alphabetically"),
2158  SLOT (sort_tabs_alph (void)),
2160 
2161  m_menu_bar->addMenu (view_menu);
2162 
2163  // debug menu
2164 
2165  m_debug_menu = add_menu (m_menu_bar, tr ("&Debug"));
2166 
2168  = add_action (m_debug_menu, rmgr.icon ("bp-toggle"),
2169  tr ("Toggle &Breakpoint"),
2170  SLOT (request_toggle_breakpoint (bool)));
2171 
2173  = add_action (m_debug_menu, rmgr.icon ("bp-next"),
2174  tr ("&Next Breakpoint"),
2175  SLOT (request_next_breakpoint (bool)));
2176 
2178  = add_action (m_debug_menu, rmgr.icon ("bp-prev"),
2179  tr ("Pre&vious Breakpoint"),
2180  SLOT (request_previous_breakpoint (bool)));
2181 
2183  = add_action (m_debug_menu, rmgr.icon ("bp-rm-all"),
2184  tr ("&Remove All Breakpoints"),
2185  SLOT (request_remove_breakpoint (bool)));
2186 
2187  m_debug_menu->addSeparator ();
2188 
2189  // The other debug actions will be added by the main window.
2190 
2191  // run menu
2192 
2193  QMenu *_run_menu = add_menu (m_menu_bar, tr ("&Run"));
2194 
2195  m_run_action
2196  = add_action (_run_menu,
2197  rmgr.icon ("system-run"),
2198  tr ("Save File and Run / Continue"),
2199  SLOT (request_run_file (bool)));
2200 
2202  = add_action (_run_menu,
2203  tr ("Run &Selection"),
2204  SLOT (request_context_run (bool)));
2205  m_run_selection_action->setEnabled (false);
2206 
2207  // help menu
2208 
2209  QMenu *_help_menu = add_menu (m_menu_bar, tr ("&Help"));
2210 
2212  = add_action (_help_menu,
2213  tr ("&Help on Keyword"),
2214  SLOT (request_context_help (bool)));
2215 
2217  = add_action (_help_menu,
2218  tr ("&Documentation on Keyword"),
2219  SLOT (request_context_doc (bool)));
2220 
2221  // tab navigation (no menu, only actions; slots in tab_bar)
2222 
2224  = add_action (nullptr, "", SLOT (switch_left_tab (void)),
2226 
2228  = add_action (nullptr, "", SLOT (switch_right_tab (void)),
2230 
2232  = add_action (nullptr, "", SLOT (move_tab_left (void)),
2234 
2236  = add_action (nullptr, "", SLOT (move_tab_right (void)),
2238 
2239  // toolbar
2240 
2241  // popdown menu with mru files
2242  QToolButton *popdown_button = new QToolButton ();
2243  popdown_button->setToolTip (tr ("Recent Files"));
2244  popdown_button->setMenu (m_mru_file_menu);
2245  popdown_button->setPopupMode (QToolButton::InstantPopup);
2246  popdown_button->setArrowType (Qt::DownArrow);
2247  popdown_button->setToolButtonStyle (Qt::ToolButtonTextOnly);
2248 
2249  // new and open actions are inserted later from main window
2250  m_popdown_mru_action = m_tool_bar->addWidget (popdown_button);
2251  m_tool_bar->addAction (m_save_action);
2252  m_tool_bar->addAction (m_save_as_action);
2253  m_tool_bar->addAction (m_print_action);
2254  m_tool_bar->addSeparator ();
2255  // m_undo_action: later via main window
2256  m_tool_bar->addAction (m_redo_action);
2257  m_tool_bar->addSeparator ();
2258  m_tool_bar->addAction (m_cut_action);
2259  // m_copy_action: later via the main window
2260  // m_paste_action: later via the main window
2261  m_tool_bar->addAction (m_find_action);
2262  //m_tool_bar->addAction (m_find_next_action);
2263  //m_tool_bar->addAction (m_find_previous_action);
2264  m_tool_bar->addSeparator ();
2265  m_tool_bar->addAction (m_run_action);
2266  m_tool_bar->addSeparator ();
2269  m_tool_bar->addAction (m_next_breakpoint_action);
2271 
2272  // layout
2273  QVBoxLayout *vbox_layout = new QVBoxLayout ();
2274  vbox_layout->addWidget (m_menu_bar);
2275  vbox_layout->addWidget (m_tool_bar);
2276  vbox_layout->addWidget (m_tab_widget);
2277  vbox_layout->setMargin (0);
2278  vbox_layout->setSpacing (0);
2279  editor_widget->setLayout (vbox_layout);
2280  setWidget (editor_widget);
2281 
2282  // create the context menu of the tab bar
2283  tab_bar *bar = m_tab_widget->get_tab_bar ();
2284  QMenu *ctx_men = bar->get_context_menu ();
2285  ctx_men->addAction (m_close_action);
2286  ctx_men->addAction (m_close_all_action);
2287  ctx_men->addAction (m_close_others_action);
2288  ctx_men->addSeparator ();
2289  ctx_men->addAction (m_sort_tabs_action);
2290 
2291  // signals
2292  connect (this, SIGNAL (request_settings_dialog (const QString&)),
2293  main_win (),
2294  SLOT (process_settings_dialog_request (const QString&)));
2295 
2296  connect (this, SIGNAL (request_dbcont_signal (void)),
2297  main_win (), SLOT (debug_continue (void)));
2298 
2299  connect (m_mru_file_menu, SIGNAL (triggered (QAction *)),
2300  this, SLOT (request_mru_open_file (QAction *)));
2301 
2302  mru_menu_update ();
2303 
2304  connect (m_tab_widget, SIGNAL (tabCloseRequested (int)),
2305  this, SLOT (handle_tab_close_request (int)));
2306 
2307  connect (m_tab_widget, SIGNAL (currentChanged (int)),
2308  this, SLOT (active_tab_changed (int)));
2309 
2310  resize (500, 400);
2311  setWindowIcon (QIcon (":/actions/icons/logo.png"));
2312  set_title (tr ("Editor"));
2313 
2314  check_actions ();
2315  }
2316 
2317  // Slot when autocompletion list was cancelled
2319  {
2320  // List was cancelled but somehow still active and blocking the
2321  // edit area from accepting shortcuts. Only after another keypress
2322  // shortcuts and lists are working againnas expected. This is
2323  // probably caused by qt bug https://bugreports.qt.io/browse/QTBUG-83720
2324  // Hack: Accept the list, which is hidden but still active
2325  // and undo the text insertion, if any
2326 
2328  octave_qscintilla *qsci = f->qsci_edit_area ();
2329 
2330  int line, col;
2331  qsci->getCursorPosition (&line, &col);
2332  int l1 = qsci->lineLength (line); // Current line length
2333 
2334  // Accept autocompletion
2335  qsci->SendScintilla (QsciScintillaBase::SCI_AUTOCCOMPLETE);
2336 
2337  // Was text inserted? If yes, undo
2338  if (qsci->text (line).length () - l1)
2339  qsci->undo ();
2340  }
2341 
2343  {
2344  // Reset the focus of the tab and the related edit area
2346  = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());
2347  emit fetab_set_focus (f);
2348  return f;
2349  }
2350 
2351  file_editor_tab *
2352  file_editor::make_file_editor_tab (const QString& directory)
2353  {
2354  file_editor_tab *f = new file_editor_tab (m_octave_qobj, directory);
2355 
2356  // signals from the qscintilla edit area
2357  connect (f->qsci_edit_area (), SIGNAL (status_update (bool, bool)),
2358  this, SLOT (edit_status_update (bool, bool)));
2359 
2360  connect (f->qsci_edit_area (), SIGNAL (show_doc_signal (const QString&)),
2361  main_win (), SLOT (handle_show_doc (const QString&)));
2362 
2363  connect (f->qsci_edit_area (), SIGNAL (create_context_menu_signal (QMenu *)),
2364  this, SLOT (create_context_menu (QMenu *)));
2365 
2366  connect (f->qsci_edit_area (),
2367  SIGNAL (execute_command_in_terminal_signal (const QString&)),
2368  main_win (), SLOT (execute_command_in_terminal (const QString&)));
2369 
2370  connect (f->qsci_edit_area (),
2371  SIGNAL (focus_console_after_command_signal (void)),
2372  main_win (), SLOT (focus_console_after_command (void)));
2373 
2374  connect (f->qsci_edit_area (),
2375  SIGNAL (SCN_AUTOCCOMPLETED (const char*, int, int, int)),
2376  this, SLOT (reset_focus (void)));
2377 
2378  connect (f->qsci_edit_area (), SIGNAL (SCN_AUTOCCANCELLED (void)),
2379  this, SLOT (handle_autoc_cancelled (void)));
2380 
2381  // Signals from the file editor_tab
2382  connect (f, SIGNAL (autoc_closed (void)),
2383  this, SLOT (reset_focus (void)));
2384 
2385  connect (f, SIGNAL (file_name_changed (const QString&, const QString&, bool)),
2386  this, SLOT (handle_file_name_changed (const QString&,
2387  const QString&, bool)));
2388 
2389  connect (f, SIGNAL (editor_state_changed (bool, bool)),
2390  this, SLOT (handle_editor_state_changed (bool, bool)));
2391 
2392  connect (f, SIGNAL (tab_remove_request ()),
2393  this, SLOT (handle_tab_remove_request ()));
2394 
2395  connect (f, SIGNAL (editor_check_conflict_save (const QString&, bool)),
2396  this, SLOT (check_conflict_save (const QString&, bool)));
2397 
2398  connect (f, SIGNAL (mru_add_file (const QString&, const QString&)),
2399  this, SLOT (handle_mru_add_file (const QString&, const QString&)));
2400 
2401  connect (f, SIGNAL (run_file_signal (const QFileInfo&)),
2402  main_win (), SLOT (run_file_in_terminal (const QFileInfo&)));
2403 
2404  connect (f, SIGNAL (request_open_file (const QString&, const QString&)),
2405  this, SLOT (request_open_file (const QString&, const QString&)));
2406 
2407  connect (f, SIGNAL (edit_mfile_request (const QString&, const QString&,
2408  const QString&, int)),
2409  main_win (), SLOT (handle_edit_mfile_request (const QString&,
2410  const QString&,
2411  const QString&, int)));
2412 
2413  connect (f, SIGNAL (edit_area_changed (octave_qscintilla*)),
2414  this, SIGNAL (edit_area_changed (octave_qscintilla*)));
2415 
2416  connect (f, SIGNAL (set_focus_editor_signal (QWidget*)),
2417  this, SLOT (set_focus (QWidget*)));
2418 
2419  // Signals from the file_editor non-trivial operations
2420  connect (this, SIGNAL (fetab_settings_changed (const gui_settings *)),
2421  f, SLOT (notice_settings (const gui_settings *)));
2422 
2423  connect (this, SIGNAL (fetab_change_request (const QWidget*)),
2424  f, SLOT (change_editor_state (const QWidget*)));
2425 
2426  connect (this, SIGNAL (fetab_save_file (const QWidget*, const QString&,
2427  bool)),
2428  f, SLOT (save_file (const QWidget*, const QString&, bool)));
2429 
2430  // Signals from the file_editor trivial operations
2431  connect (this, SIGNAL (fetab_recover_from_exit (void)),
2432  f, SLOT (recover_from_exit (void)));
2433 
2434  connect (this, SIGNAL (fetab_set_directory (const QString&)),
2435  f, SLOT (set_current_directory (const QString&)));
2436 
2437  connect (this, SIGNAL (fetab_zoom_in (const QWidget*)),
2438  f, SLOT (zoom_in (const QWidget*)));
2439  connect (this, SIGNAL (fetab_zoom_out (const QWidget*)),
2440  f, SLOT (zoom_out (const QWidget*)));
2441  connect (this, SIGNAL (fetab_zoom_normal (const QWidget*)),
2442  f, SLOT (zoom_normal (const QWidget*)));
2443 
2444  connect (this, SIGNAL (fetab_context_help (const QWidget*, bool)),
2445  f, SLOT (context_help (const QWidget*, bool)));
2446 
2447  connect (this, SIGNAL (fetab_context_edit (const QWidget*)),
2448  f, SLOT (context_edit (const QWidget*)));
2449 
2450  connect (this, SIGNAL (fetab_save_file (const QWidget*)),
2451  f, SLOT (save_file (const QWidget*)));
2452 
2453  connect (this, SIGNAL (fetab_save_file_as (const QWidget*)),
2454  f, SLOT (save_file_as (const QWidget*)));
2455 
2456  connect (this, SIGNAL (fetab_print_file (const QWidget*)),
2457  f, SLOT (print_file (const QWidget*)));
2458 
2459  connect (this, SIGNAL (fetab_run_file (const QWidget*, bool)),
2460  f, SLOT (run_file (const QWidget*, bool)));
2461 
2462  connect (this, SIGNAL (fetab_context_run (const QWidget*)),
2463  f, SLOT (context_run (const QWidget*)));
2464 
2465  connect (this, SIGNAL (fetab_toggle_bookmark (const QWidget*)),
2466  f, SLOT (toggle_bookmark (const QWidget*)));
2467 
2468  connect (this, SIGNAL (fetab_next_bookmark (const QWidget*)),
2469  f, SLOT (next_bookmark (const QWidget*)));
2470 
2471  connect (this, SIGNAL (fetab_previous_bookmark (const QWidget*)),
2472  f, SLOT (previous_bookmark (const QWidget*)));
2473 
2474  connect (this, SIGNAL (fetab_remove_bookmark (const QWidget*)),
2475  f, SLOT (remove_bookmark (const QWidget*)));
2476 
2477  connect (this, SIGNAL (fetab_toggle_breakpoint (const QWidget*)),
2478  f, SLOT (toggle_breakpoint (const QWidget*)));
2479 
2480  connect (this, SIGNAL (fetab_next_breakpoint (const QWidget*)),
2481  f, SLOT (next_breakpoint (const QWidget*)));
2482 
2483  connect (this, SIGNAL (fetab_previous_breakpoint (const QWidget*)),
2484  f, SLOT (previous_breakpoint (const QWidget*)));
2485 
2486  connect (this, SIGNAL (fetab_remove_all_breakpoints (const QWidget*)),
2487  f, SLOT (remove_all_breakpoints (const QWidget*)));
2488 
2489  connect (this, SIGNAL (fetab_scintilla_command (const QWidget *,
2490  unsigned int)),
2491  f, SLOT (scintilla_command (const QWidget *, unsigned int)));
2492 
2493  connect (this, SIGNAL (fetab_comment_selected_text (const QWidget*, bool)),
2494  f, SLOT (comment_selected_text (const QWidget*, bool)));
2495 
2496  connect (this, SIGNAL (fetab_uncomment_selected_text (const QWidget*)),
2497  f, SLOT (uncomment_selected_text (const QWidget*)));
2498 
2499  connect (this, SIGNAL (fetab_indent_selected_text (const QWidget*)),
2500  f, SLOT (indent_selected_text (const QWidget*)));
2501 
2502  connect (this, SIGNAL (fetab_unindent_selected_text (const QWidget*)),
2503  f, SLOT (unindent_selected_text (const QWidget*)));
2504 
2505  connect (this, SIGNAL (fetab_smart_indent_line_or_selected_text (const QWidget*)),
2506  f, SLOT (smart_indent_line_or_selected_text (const QWidget*)));
2507 
2508  connect (this,
2509  SIGNAL (fetab_convert_eol (const QWidget*, QsciScintilla::EolMode)),
2510  f, SLOT (convert_eol (const QWidget*, QsciScintilla::EolMode)));
2511 
2512  connect (this, SIGNAL (fetab_goto_line (const QWidget*, int)),
2513  f, SLOT (goto_line (const QWidget*, int)));
2514 
2515  connect (this, SIGNAL (fetab_move_match_brace (const QWidget*, bool)),
2516  f, SLOT (move_match_brace (const QWidget*, bool)));
2517 
2518  connect (this, SIGNAL (fetab_completion (const QWidget*)),
2519  f, SLOT (show_auto_completion (const QWidget*)));
2520 
2521  connect (this, SIGNAL (fetab_set_focus (const QWidget*)),
2522  f, SLOT (set_focus (const QWidget*)));
2523 
2524  connect (this, SIGNAL (fetab_insert_debugger_pointer (const QWidget*, int)),
2525  f, SLOT (insert_debugger_pointer (const QWidget*, int)));
2526 
2527  connect (this, SIGNAL (fetab_delete_debugger_pointer (const QWidget*, int)),
2528  f, SLOT (delete_debugger_pointer (const QWidget*, int)));
2529 
2530  connect (f, SIGNAL (debug_quit_signal (void)),
2531  main_win (), SLOT (debug_quit (void)));
2532 
2533  connect (this, SIGNAL (fetab_do_breakpoint_marker (bool, const QWidget*,
2534  int, const QString&)),
2535  f, SLOT (do_breakpoint_marker (bool, const QWidget*, int,
2536  const QString&)));
2537 
2538  // Any interpreter_event signal from a file_editor_tab_widget is
2539  // handled the same as for the parent main_window object.
2540 
2541  connect (f, SIGNAL (interpreter_event (const fcn_callback&)),
2542  this, SIGNAL (interpreter_event (const fcn_callback&)));
2543 
2544  connect (f, SIGNAL (interpreter_event (const meth_callback&)),
2545  this, SIGNAL (interpreter_event (const meth_callback&)));
2546 
2547  return f;
2548  }
2549 
2551  int index)
2552  {
2553  if (index == -1)
2554  m_tab_widget->addTab (f, fn);
2555  else
2556  m_tab_widget->insertTab (index, f, fn);
2557 
2558  m_tab_widget->setCurrentWidget (f);
2559 
2560  check_actions ();
2561  }
2562 
2564  {
2565  int num_files = qMin (m_mru_files.size (), int (MaxMRUFiles));
2566 
2567  // configure and show active actions of mru-menu
2568  for (int i = 0; i < num_files; ++i)
2569  {
2570  QString text = QString ("&%1 %2").
2571  arg ((i+1) % int (MaxMRUFiles)).arg (m_mru_files.at (i));
2572  m_mru_file_actions[i]->setText (text);
2573 
2574  QStringList action_data;
2575  action_data << m_mru_files.at (i) << m_mru_files_encodings.at (i);
2576  m_mru_file_actions[i]->setData (action_data);
2577 
2578  m_mru_file_actions[i]->setVisible (true);
2579  }
2580 
2581  // hide unused mru-menu entries
2582  for (int j = num_files; j < MaxMRUFiles; ++j)
2583  m_mru_file_actions[j]->setVisible (false);
2584 
2585  // delete entries in string-list beyond MaxMRUFiles
2586  while (m_mru_files.size () > MaxMRUFiles)
2587  {
2588  m_mru_files.removeLast ();
2589  m_mru_files_encodings.removeLast ();
2590  }
2591 
2592  // save actual mru-list in settings
2594  gui_settings *settings = rmgr.get_settings ();
2595 
2598  settings->sync ();
2599  }
2600 
2601  bool file_editor::call_custom_editor (const QString& file_name, int line)
2602  {
2603  // Check if the user wants to use a custom file editor.
2605  gui_settings *settings = rmgr.get_settings ();
2606 
2608  global_use_custom_editor.def).toBool ())
2609  {
2610  // use the external editor interface for handling the call
2611  emit request_open_file_external (file_name, line);
2612 
2613  if (line < 0 && ! file_name.isEmpty ())
2614  handle_mru_add_file (QFileInfo (file_name).canonicalFilePath (),
2615  QString ());
2616 
2617  return true;
2618  }
2619 
2620  return false;
2621  }
2622 
2623  void file_editor::toggle_preference (const gui_pref& preference)
2624  {
2626  gui_settings *settings = rmgr.get_settings ();
2627 
2628  bool old = settings->value (preference).toBool ();
2629  settings->setValue (preference.key, ! old);
2631  }
2632 
2633  // Function for closing the files in a removed directory
2634  void file_editor::handle_dir_remove (const QString& old_name,
2635  const QString& new_name)
2636  {
2637  QDir old_dir (old_name);
2638  session_data f_data;
2639 
2640  std::list<file_editor_tab *> editor_tab_lst = m_tab_widget->tab_list ();
2641 
2642  for (auto editor_tab : editor_tab_lst)
2643  {
2644  QString file_name = editor_tab->file_name ();
2645 
2646  if (file_name.isEmpty ())
2647  continue; // Nothing to do, no valid file name
2648 
2649  // Get abs. file path and its path relative to the removed directory
2650  QString rel_path_to_file = old_dir.relativeFilePath (file_name);
2651  QString abs_path_to_file = old_dir.absoluteFilePath (file_name);
2652 
2653  // Test whether the file is located within the directory that will
2654  // be removed. For this, two conditions must be met:
2655  // 1. The path of the file rel. to the dir is not equal to the
2656  // its absolute one.
2657  // If both are equal, then there is no relative path and removed
2658  // directory and file are on different drives (e.g. on windows)
2659  // 2. The (real) relative path does not start with "../", i.e.,
2660  // the file can be reached from the directory by descending only
2661  if ((rel_path_to_file != abs_path_to_file)
2662  && (rel_path_to_file.left (3) != QString ("../")))
2663  {
2664  // The currently considered file is included in the
2665  // removed/renamed diectory: Delete it.
2666  m_no_focus = true; // Remember for not focussing editor
2667 
2668  if (editor_tab)
2669  {
2670  // Get index and line
2671  int l, c;
2672  editor_tab->qsci_edit_area ()->getCursorPosition (&l, &c);
2673  f_data.line = l + 1;
2674  f_data.index = m_tab_widget->indexOf (editor_tab);
2675  // Close
2676  editor_tab->file_has_changed (QString (), true);
2677  }
2678  m_no_focus = false; // Back to normal
2679 
2680  // Store file for possible later reload
2681  f_data.file_name = file_name;
2682 
2683  // Add the new file path and the encoding for later reloading
2684  // if new_name is given
2685  if (! new_name.isEmpty ())
2686  {
2687  QDir new_dir (new_name);
2688  QString append_to_new_dir;
2689  if (new_dir.exists ())
2690  {
2691  // The new directory already exists (movefile was used).
2692  // This means, we have to add the name (not the path)
2693  // of the old dir and the relative path to the file
2694  // to new dir.
2695  append_to_new_dir
2696  = old_dir.dirName () + "/" + rel_path_to_file;
2697  }
2698  else
2699  append_to_new_dir = rel_path_to_file;
2700 
2701  f_data.new_file_name
2702  = new_dir.absoluteFilePath (append_to_new_dir);
2703  }
2704  else
2705  f_data.new_file_name = ""; // no new name, just removing this file
2706 
2707  f_data.encoding = editor_tab->encoding (); // store the encoding
2708 
2709  // Store data in list for later reloading
2710  m_tmp_closed_files << f_data;
2711  }
2712  }
2713  }
2714 
2716  {
2717  QWidget *foc_w = focusWidget ();
2718  if (foc_w && foc_w->inherits ("octave::octave_qscintilla"))
2719  return true;
2720  return false;
2721  }
2722 
2723  // Check whether this file is already open in the editor.
2725  {
2726  std::string std_file = file.toStdString ();
2727 
2728  std::list<file_editor_tab *> fe_tab_lst = m_tab_widget->tab_list ();
2729 
2730  for (auto fe_tab : fe_tab_lst)
2731  {
2732  QString tab_file = fe_tab->file_name ();
2733 
2734  // We check file == tab_file because
2735  //
2736  // same_file ("", "")
2737  //
2738  // is false
2739 
2740  if (same_file (std_file, tab_file.toStdString ()) || file == tab_file)
2741  return fe_tab;
2742  }
2743 
2744  return nullptr;
2745  }
2746 
2747  QAction * file_editor::add_action (QMenu *menu, const QString& text,
2748  const char *member,
2749  QWidget *receiver)
2750  {
2751  return add_action (menu, QIcon (), text, member, receiver);
2752  }
2753 
2754  QAction * file_editor::add_action (QMenu *menu, const QIcon& icon,
2755  const QString& text, const char *member,
2756  QWidget *receiver)
2757  {
2758  QAction *a;
2759  QWidget *r = this;
2760 
2761  if (receiver != nullptr)
2762  r = receiver;
2763 
2764  if (menu)
2765  a = menu->addAction (icon, text, r, member);
2766  else
2767  {
2768  a = new QAction (this);
2769  connect (a, SIGNAL (triggered ()), r, member);
2770  }
2771 
2772  addAction (a); // important for shortcut context
2773  a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
2774 
2775  return a;
2776  }
2777 
2779  {
2780  QMenu *menu = p->addMenu (name);
2781 
2782  QString base_name = name; // get a copy
2783  // replace intended '&' ("&&") by a temp. string
2784  base_name.replace ("&&", "___octave_amp_replacement___");
2785  // remove single '&' (shortcut)
2786  base_name.remove ("&");
2787  // restore intended '&'
2788  base_name.replace ("___octave_amp_replacement___", "&&");
2789 
2790  // remember names with and without shortcut
2791  m_hash_menu_text[menu] = QStringList () << name << base_name;
2792 
2793  return menu;
2794  }
2795 }
2796 
2797 #endif
Base class for Octave interfaces that use Qt.
resource_manager & get_resource_manager(void)
shortcut_manager & get_shortcut_manager(void)
tab_bar * get_tab_bar(void) const
Definition: file-editor.cc:85
std::list< file_editor_tab * > tab_list(void) const
Definition: file-editor.cc:91
void set_encoding(const QString &new_encoding)
QString load_file(const QString &fileName)
void update_window_title(bool modified)
void file_has_changed(const QString &path, bool do_close=false)
QString encoding(void) const
octave_qscintilla * qsci_edit_area(void)
void new_file(const QString &commands=QString())
QAction * m_delete_start_word_action
Definition: file-editor.h:392
void request_find_previous(bool)
Definition: file-editor.cc:897
void handle_editor_state_changed(bool enableCopy, bool is_octave_file)
Definition: file-editor.cc:976
QAction * m_move_tab_left_action
Definition: file-editor.h:436
void request_close_other_files(bool)
Definition: file-editor.cc:568
void fetab_next_bookmark(const QWidget *ID)
QAction * m_upper_case_action
Definition: file-editor.h:361
QAction * m_previous_breakpoint_action
Definition: file-editor.h:442
void zoom_normal(bool)
void empty_script(bool startup, bool visible)
Definition: file-editor.cc:249
QAction * m_conv_eol_windows_action
Definition: file-editor.h:369
QAction * m_sel_to_matching_brace
Definition: file-editor.h:410
QAction * m_show_indguide_action
Definition: file-editor.h:383
void handle_update_breakpoint_marker_request(bool insert, const QString &file, int line, const QString &cond)
bool check_closing(void)
Definition: file-editor.cc:451
void fetab_zoom_out(const QWidget *ID)
void request_find_next(bool)
Definition: file-editor.cc:891
void handle_tab_close_request(int index)
Definition: file-editor.cc:937
QAction * m_close_action
Definition: file-editor.h:424
QAction * m_switch_right_tab_action
Definition: file-editor.h:435
void fetab_previous_bookmark(const QWidget *ID)
void request_styles_preferences(bool)
QAction * m_transpose_line_action
Definition: file-editor.h:400
void request_step_into_file()
Definition: file-editor.cc:653
QAction * m_indent_selection_action
Definition: file-editor.h:366
QAction * m_completion_action
Definition: file-editor.h:407
void request_mru_open_file(QAction *action)
Definition: file-editor.cc:586
void fetab_zoom_in(const QWidget *ID)
QAction * m_close_others_action
Definition: file-editor.h:426
QAction * m_smart_indent_line_or_selection_action
Definition: file-editor.h:368
QPointer< find_dialog > m_find_dialog
Definition: file-editor.h:469
void request_open_file(const QString &fileName, const QString &encoding=QString(), int line=-1, bool debug_pointer=false, bool breakpoint_marker=false, bool insert=true, const QString &cond="", int index=-1)
QAction * m_save_action
Definition: file-editor.h:422
QAction * m_run_action
Definition: file-editor.h:417
QAction * m_lower_case_action
Definition: file-editor.h:362
QAction * m_paste_action
Definition: file-editor.h:375
QAction * m_print_action
Definition: file-editor.h:416
QAction * m_conv_eol_mac_action
Definition: file-editor.h:371
file_editor(QWidget *p, base_qobject &oct_qobj)
Definition: file-editor.cc:102
void fetab_remove_bookmark(const QWidget *ID)
void request_close_file(bool)
Definition: file-editor.cc:549
void request_delete_end_line(bool)
Definition: file-editor.cc:733
void handle_file_remove(const QString &, const QString &)
void request_move_match_brace(bool)
Definition: file-editor.cc:683
QAction * m_context_doc_action
Definition: file-editor.h:378
QList< session_data > m_tmp_closed_files
Definition: file-editor.h:472
void toggle_preference(const gui_pref &preference)
void fetab_set_directory(const QString &dir)
QAction * m_preferences_action
Definition: file-editor.h:431
file_editor_tab_widget * m_tab_widget
Definition: file-editor.h:455
void request_next_breakpoint(bool)
Definition: file-editor.cc:699
void fetab_context_help(const QWidget *ID, bool)
QAction * m_remove_all_breakpoints_action
Definition: file-editor.h:443
void enable_menu_shortcuts(bool)
Definition: file-editor.cc:373
void find_create(void)
Definition: file-editor.cc:847
void edit_area_changed(octave_qscintilla *edit_area)
void request_conv_eol_unix(bool)
Definition: file-editor.cc:818
QAction * m_move_to_matching_brace
Definition: file-editor.h:409
QAction * m_unindent_selection_action
Definition: file-editor.h:367
void request_open_file_external(const QString &file_name, int line)
QAction * m_selectall_action
Definition: file-editor.h:376
void fetab_context_run(const QWidget *ID)
QAction * m_cut_line_action
Definition: file-editor.h:398
void request_upper_case(bool)
Definition: file-editor.cc:785
bool call_custom_editor(const QString &file_name=QString(), int line=-1)
QAction * m_next_breakpoint_action
Definition: file-editor.h:441
void handle_exit_debug_mode(void)
Definition: file-editor.cc:198
QAction * m_show_statusbar_action
Definition: file-editor.h:386
QAction * m_edit_function_action
Definition: file-editor.h:420
void fetab_delete_debugger_pointer(const QWidget *ID, int line=-1)
void show_hscrollbar(bool)
void request_next_bookmark(bool)
Definition: file-editor.cc:668
void insert_global_actions(QList< QAction * >)
Definition: file-editor.cc:150
void fetab_previous_breakpoint(const QWidget *ID)
void closeEvent(QCloseEvent *event)
void request_delete_start_line(bool)
Definition: file-editor.cc:727
void handle_delete_debugger_pointer_request(const QString &file, int line)
QAction * m_run_selection_action
Definition: file-editor.h:418
QAction * m_undo_action
Definition: file-editor.h:429
void fetab_unindent_selected_text(const QWidget *ID)
bool is_editor_console_tabbed(void)
void request_new_file(const QString &commands)
Definition: file-editor.cc:532
void handle_file_renamed(bool load_new=true)
QMenu * add_menu(QMenuBar *p, QString text)
void request_remove_breakpoint(bool)
Definition: file-editor.cc:709
void set_focus(QWidget *fet)
Definition: file-editor.cc:362
QAction * m_delete_end_line_action
Definition: file-editor.h:395
QAction * m_uncomment_selection_action
Definition: file-editor.h:365
QAction * m_find_files_action
Definition: file-editor.h:405
QAction * m_duplicate_selection_action
Definition: file-editor.h:399
void request_find(bool)
Definition: file-editor.cc:831
void request_unindent_selected_text(bool)
Definition: file-editor.cc:802
QAction * m_delete_end_word_action
Definition: file-editor.h:393
void request_lower_case(bool)
Definition: file-editor.cc:791
void request_context_run(bool)
Definition: file-editor.cc:658
void request_save_file_as(bool)
Definition: file-editor.cc:632
bool editor_tab_has_focus(void)
void fetab_context_edit(const QWidget *ID)
QAction * m_remove_bookmark_action
Definition: file-editor.h:414
QAction * m_copy_line_action
Definition: file-editor.h:397
void show_eol_chars(bool)
void handle_insert_debugger_pointer_request(const QString &file, int line)
void active_tab_changed(int index)
Definition: file-editor.cc:970
void fetab_scintilla_command(const QWidget *ID, unsigned int sci_msg)
QAction * m_find_next_action
Definition: file-editor.h:403
QAction * m_conv_eol_unix_action
Definition: file-editor.h:370
void edit_status_update(bool, bool)
void update_octave_directory(const QString &dir)
void set_shortcuts(void)
void dropEvent(QDropEvent *event)
QAction * m_copy_action
Definition: file-editor.h:373
void fetab_do_breakpoint_marker(bool insert, const QWidget *ID, int line=-1, const QString &="")
QAction * m_show_longline_action
Definition: file-editor.h:384
void show_long_line(bool)
QAction * m_next_bookmark_action
Definition: file-editor.h:411
void request_previous_breakpoint(bool)
Definition: file-editor.cc:704
QAction * add_action(QMenu *menu, const QString &text, const char *member, QWidget *receiver=nullptr)
void request_toggle_breakpoint(bool)
Definition: file-editor.cc:694
QAction * m_comment_selection_action
Definition: file-editor.h:363
void check_actions(void)
Definition: file-editor.cc:205
QAction * m_popdown_mru_action
Definition: file-editor.h:421
void request_delete_end_word(bool)
Definition: file-editor.cc:721
QAction * m_previous_bookmark_action
Definition: file-editor.h:412
void request_conv_eol_windows(bool)
Definition: file-editor.cc:812
QAction * m_move_tab_right_action
Definition: file-editor.h:437
void request_dbcont_signal(void)
void fetab_move_match_brace(const QWidget *ID, bool select)
void show_toolbar(bool)
void request_settings_dialog(const QString &)
void request_conv_eol_mac(bool)
Definition: file-editor.cc:824
void request_cut_line(bool)
Definition: file-editor.cc:751
void fetab_smart_indent_line_or_selected_text(const QWidget *ID)
void handle_tab_ready_to_close(void)
Definition: file-editor.cc:501
void request_save_file(bool)
Definition: file-editor.cc:627
void request_comment_selected_text(bool)
Definition: file-editor.cc:769
void fetab_toggle_bookmark(const QWidget *ID)
QAction * m_mru_file_actions[MaxMRUFiles]
Definition: file-editor.h:465
void fetab_insert_debugger_pointer(const QWidget *ID, int line=-1)
void create_context_menu(QMenu *)
QAction * m_find_action
Definition: file-editor.h:402
void add_file_editor_tab(file_editor_tab *f, const QString &fn, int index=-1)
void dragEnterEvent(QDragEnterEvent *event)
void fetab_save_file(const QWidget *ID, const QString &fileName, bool remove_on_success)
QAction * m_switch_left_tab_action
Definition: file-editor.h:434
void request_delete_start_word(bool)
Definition: file-editor.cc:715
void request_run_file(bool)
Definition: file-editor.cc:637
void request_redo(bool)
Definition: file-editor.cc:600
QStringList m_mru_files_encodings
Definition: file-editor.h:467
void request_close_all_files(bool)
Definition: file-editor.cc:556
void show_indent_guides(bool)
void request_context_doc(bool)
Definition: file-editor.cc:617
QAction * m_redo_action
Definition: file-editor.h:428
QAction * m_delete_start_line_action
Definition: file-editor.h:394
void handle_mru_add_file(const QString &file_name, const QString &encoding)
Definition: file-editor.cc:994
void fetab_uncomment_selected_text(const QWidget *ID)
void request_comment_var_selected_text(bool)
Definition: file-editor.cc:779
void fetab_goto_line(const QWidget *ID, int line=-1)
void request_cut(bool)
Definition: file-editor.cc:606
QAction * m_goto_line_action
Definition: file-editor.h:406
void request_completion(bool)
Definition: file-editor.cc:908
void handle_dir_remove(const QString &old_name, const QString &new_name)
void request_delete_line(bool)
Definition: file-editor.cc:739
void show_statusbar(bool)
void request_toggle_bookmark(bool)
Definition: file-editor.cc:663
QAction * m_save_as_action
Definition: file-editor.h:423
QMenuBar * m_menu_bar
Definition: file-editor.h:353
void file_loaded_signal(void)
void check_conflict_save(const QString &fileName, bool remove_on_success)
void fetab_zoom_normal(const QWidget *ID)
void fetab_settings_changed(const gui_settings *settings)
void mru_menu_update(void)
void restore_session(gui_settings *settings)
Definition: file-editor.cc:299
void handle_autoc_cancelled(void)
QAction * m_cut_action
Definition: file-editor.h:374
QAction * m_show_whitespace_action
Definition: file-editor.h:381
void handle_edit_file_request(const QString &file)
QAction * m_show_hscrollbar_action
Definition: file-editor.h:387
file_editor_tab * make_file_editor_tab(const QString &directory="")
void request_context_edit(bool)
Definition: file-editor.cc:622
QAction * m_show_toolbar_action
Definition: file-editor.h:385
QAction * m_context_help_action
Definition: file-editor.h:377
void fetab_save_file_as(const QWidget *ID)
void focusInEvent(QFocusEvent *e)
Definition: file-editor.cc:136
void notice_settings(const gui_settings *settings)
void fetab_print_file(const QWidget *ID)
QToolBar * m_tool_bar
Definition: file-editor.h:354
void pasteClipboard(void)
void request_duplicate_selection(bool)
Definition: file-editor.cc:757
QAction * m_close_all_action
Definition: file-editor.h:425
void show_white_space(bool)
void fetab_convert_eol(const QWidget *ID, QsciScintilla::EolMode eol_mode)
QAction * m_zoom_in_action
Definition: file-editor.h:388
void copyClipboard(void)
void request_sel_match_brace(bool)
Definition: file-editor.cc:688
QAction * m_zoom_out_action
Definition: file-editor.h:389
void handle_visibility(bool visible)
void request_smart_indent_line_or_selected_text(void)
Definition: file-editor.cc:807
QAction * m_zoom_normal_action
Definition: file-editor.h:390
void fetab_next_breakpoint(const QWidget *ID)
void request_transpose_line(bool)
Definition: file-editor.cc:763
QAction * m_find_previous_action
Definition: file-editor.h:404
void fetab_run_file(const QWidget *ID, bool step_into=false)
QAction * m_toggle_breakpoint_action
Definition: file-editor.h:440
QAction * m_toggle_bookmark_action
Definition: file-editor.h:413
void request_context_help(bool)
Definition: file-editor.cc:612
void request_copy_line(bool)
Definition: file-editor.cc:745
void editor_tabs_changed_signal(bool)
void request_remove_bookmark(bool)
Definition: file-editor.cc:678
file_editor_tab * reset_focus(void)
void show_line_numbers(bool)
QAction * m_delete_line_action
Definition: file-editor.h:396
void request_preferences(bool)
QAction * m_show_eol_action
Definition: file-editor.h:382
QAction * m_show_linenum_action
Definition: file-editor.h:380
void fetab_completion(const QWidget *)
void fetab_change_request(const QWidget *ID)
void fetab_recover_from_exit(void)
QHash< QMenu *, QStringList > m_hash_menu_text
Definition: file-editor.h:349
void fetab_remove_all_breakpoints(const QWidget *ID)
void fetab_comment_selected_text(const QWidget *ID, bool)
QAction * m_sort_tabs_action
Definition: file-editor.h:438
void request_indent_selected_text(bool)
Definition: file-editor.cc:797
void fetab_set_focus(const QWidget *ID)
void handle_file_name_changed(const QString &fileName, const QString &toolTip, bool modified)
Definition: file-editor.cc:913
QAction * m_comment_var_selection_action
Definition: file-editor.h:364
void request_print_file(bool)
Definition: file-editor.cc:595
file_editor_tab * find_tab_widget(const QString &openFileName)
QAction * m_styles_preferences_action
Definition: file-editor.h:432
QStringList m_mru_files
Definition: file-editor.h:466
void request_previous_bookmark(bool)
Definition: file-editor.cc:673
void request_uncomment_selected_text(bool)
Definition: file-editor.cc:774
void handle_tab_remove_request(void)
Definition: file-editor.cc:945
void handle_enter_debug_mode(void)
Definition: file-editor.cc:185
QMenu * m_view_editor_menu
Definition: file-editor.h:453
void fetab_toggle_breakpoint(const QWidget *ID)
void toplevel_change(bool toplevel)
void fetab_indent_selected_text(const QWidget *ID)
void request_goto_line(bool)
Definition: file-editor.cc:903
void save_session(void)
Definition: file-editor.cc:412
tree_evaluator & get_evaluator(void)
void set_title(const QString &)
Represents the main window.
Definition: main-window.h:76
virtual void closeEvent(QCloseEvent *e)
QMainWindow * main_win(void)
void interpreter_event(const fcn_callback &fcn)
gui_settings * get_settings(void) const
QIcon icon(const QString &icon_name, bool fallback=true)
void set_shortcut(QAction *action, const sc_pref &scpref)
static std::string make_absolute(const std::string &s, const std::string &dot_path=get_current_directory())
Definition: oct-env.cc:133
QMenu * get_context_menu(void)
Definition: tab-bar.h:50
bool in_debug_repl(void) const
Definition: pt-eval.cc:4076
QString name
const gui_pref ed_show_hscroll_bar("editor/show_hscroll_bar", QVariant(true))
const gui_pref ed_show_toolbar("editor/show_toolbar", QVariant(true))
const gui_pref ed_long_window_title("editor/longWindowTitle", QVariant(false))
const gui_pref ed_show_white_space("editor/show_white_space", QVariant(false))
const gui_pref ed_create_new_file("editor/create_new_file", QVariant(false))
const gui_pref ed_mru_file_encodings("editor/mru_file_encodings", QVariant())
const gui_pref ed_session_names("editor/savedSessionTabs", QVariant(QStringList()))
const gui_pref ed_notebook_tab_width_min("editor/notebook_tab_width_min", QVariant(160))
const gui_pref ed_long_line_marker("editor/long_line_marker", QVariant(true))
const gui_pref ed_tab_position("editor/tab_position", QVariant(QTabWidget::North))
const gui_pref ed_show_edit_status_bar("editor/show_edit_status_bar", QVariant(true))
const gui_pref ed_restore_session("editor/restoreSession", QVariant(true))
const gui_pref ed_mru_file_list("editor/mru_file_list", QVariant())
const gui_pref ed_show_dbg_file("editor/show_dbg_file", QVariant(true))
const gui_pref ed_session_ind("editor/saved_session_tab_index", QVariant(QStringList()))
const gui_pref ed_show_line_numbers("editor/showLineNumbers", QVariant(true))
const gui_pref ed_notebook_tab_width_max("editor/notebook_tab_width_max", QVariant(300))
const gui_pref ed_show_eol_chars("editor/show_eol_chars", QVariant(false))
const gui_pref ed_session_lines("editor/saved_session_lines", QVariant(QStringList()))
const gui_pref ed_show_indent_guides("editor/show_indent_guides", QVariant(false))
const gui_pref ed_hiding_closes_files("editor/hiding_closes_files", QVariant(false))
const gui_pref ed_session_enc("editor/saved_session_encodings", QVariant(QStringList()))
const QStyle::PixelMetric global_icon_sizes[3]
const gui_pref global_use_custom_editor("useCustomFileEditor", QVariant(false))
const gui_pref global_icon_size("toolbar_icon_size", QVariant(0))
const sc_pref sc_edit_view_show_long_line(sc_edit_view+":show_long_line", QKeySequence::UnknownKey)
const sc_pref sc_edit_file_close(sc_edit_file_cl, QKeySequence::Close)
const sc_pref sc_edit_edit_completion_list(sc_edit_edit+":completion_list", CTRL+Qt::Key_Space)
const sc_pref sc_edit_debug_next_breakpoint(sc_edit_debug+":next_breakpoint", QKeySequence::UnknownKey)
const sc_pref sc_edit_debug_previous_breakpoint(sc_edit_debug+":previous_breakpoint", QKeySequence::UnknownKey)
const sc_pref sc_edit_edit_delete_line(sc_edit_edit+":delete_line", CTRL_SHIFT+Qt::Key_L)
const sc_pref sc_edit_edit_move_to_brace(sc_edit_edit+":move_to_brace", CTRL+Qt::Key_M)
const sc_pref sc_edit_edit_toggle_bookmark(sc_edit_edit+":toggle_bookmark", PRE+Qt::Key_F7)
const sc_pref sc_edit_edit_delete_start_line(sc_edit_edit+":delete_start_line", CTRL_SHIFT+Qt::Key_Backspace)
const sc_pref sc_edit_edit_uncomment_selection(sc_edit_edit+":uncomment_selection", CTRL_SHIFT+Qt::Key_R)
const sc_pref sc_edit_edit_cut_line(sc_edit_edit+":cut_line", CTRL_SHIFT+Qt::Key_X)
const sc_pref sc_edit_view_show_hscrollbar(sc_edit_view+":show_hscrollbar", QKeySequence::UnknownKey)
const sc_pref sc_edit_edit_remove_bookmark(sc_edit_edit+":remove_bookmark", QKeySequence::UnknownKey)
const sc_pref sc_edit_edit_upper_case(sc_edit_edit+":upper_case", CTRL+Qt::Key_U)
const sc_pref sc_edit_file_save(sc_edit_file+":save", QKeySequence::Save)
const sc_pref sc_edit_edit_styles_preferences(sc_edit_edit+":styles_preferences", QKeySequence::UnknownKey)
const sc_pref sc_edit_file_print(sc_edit_file+":print", QKeySequence::Print)
const sc_pref sc_edit_edit_goto_line(sc_edit_edit+":goto_line", CTRL+Qt::Key_L)
const sc_pref sc_edit_edit_smart_indent_line_or_selection(sc_edit_edit+":smart_indent_line_or_selection", QKeySequence::UnknownKey)
const sc_pref sc_main_debug_continue(sc_main_debug+":continue", PRE+Qt::Key_F5)
const sc_pref sc_edit_view_show_statusbar(sc_edit_view+":show_statusbar", QKeySequence::UnknownKey)
const sc_pref sc_edit_view_show_eol_chars(sc_edit_view+":show_eol_chars", QKeySequence::UnknownKey)
const sc_pref sc_edit_file_edit_function(sc_edit_file+":edit_function", CTRL+Qt::Key_E)
const sc_pref sc_edit_edit_comment_selection(sc_edit_edit+":comment_selection", CTRL+Qt::Key_R)
const sc_pref sc_edit_edit_comment_var_selection(sc_edit_edit+":comment_var_selection", CTRL_ALT+Qt::Key_R)
const sc_pref sc_edit_run_run_file(sc_edit_run+":run_file", PRE+Qt::Key_F5)
const sc_pref sc_edit_file_save_as(sc_edit_file+":save_as", QKeySequence::SaveAs)
const sc_pref sc_edit_view_zoom_normal(sc_edit_view_zoom+"_normal", CTRL+Qt::Key_Period)
const sc_pref sc_edit_edit_find_replace(sc_edit_edit_find+"_replace", QKeySequence::Find)
const sc_pref sc_edit_view_show_ind_guides(sc_edit_view+":show_ind_guides", QKeySequence::UnknownKey)
const sc_pref sc_edit_file_close_other(sc_edit_file_cl+"_other", QKeySequence::UnknownKey)
const sc_pref sc_edit_edit_copy_line(sc_edit_edit+":copy_line", CTRL_SHIFT+Qt::Key_C)
const sc_pref sc_edit_edit_transpose_line(sc_edit_edit+":transpose_line", CTRL+Qt::Key_T)
const sc_pref sc_edit_edit_find_next(sc_edit_edit_find+"_next", QKeySequence::FindNext)
const sc_pref sc_edit_help_help_keyword(sc_edit_help+":help_keyword", QKeySequence::HelpContents)
const sc_pref sc_edit_edit_duplicate_selection(sc_edit_edit+":duplicate_selection", CTRL+Qt::Key_D)
const sc_pref sc_edit_view_show_toolbar(sc_edit_view+":show_toolbar", QKeySequence::UnknownKey)
const sc_pref sc_edit_help_doc_keyword(sc_edit_help+":doc_keyword", Qt::SHIFT+Qt::Key_F1)
const sc_pref sc_edit_edit_delete_end_line(sc_edit_edit+":delete_end_line", CTRL_SHIFT+Qt::Key_Delete)
const sc_pref sc_edit_tabs_move_tab_right(sc_edit_tabs+":move_tab_right", Qt::AltModifier+Qt::Key_PageDown)
const sc_pref sc_edit_edit_cut(sc_edit_edit+":cut", QKeySequence::Cut)
const sc_pref sc_edit_debug_remove_breakpoints(sc_edit_debug+":remove_breakpoints", QKeySequence::UnknownKey)
const sc_pref sc_edit_edit_unindent_selection(sc_edit_edit+":unindent_selection", CTRL_SHIFT+Qt::Key_Tab)
const sc_pref sc_edit_edit_next_bookmark(sc_edit_edit+":next_bookmark", PRE+Qt::Key_F2)
const sc_pref sc_edit_run_run_selection(sc_edit_run+":run_selection", PRE+Qt::Key_F9)
const sc_pref sc_edit_edit_find_previous(sc_edit_edit_find+"_previous", QKeySequence::FindPrevious)
const sc_pref sc_edit_view_show_white_spaces(sc_edit_view+":show_white_spaces", QKeySequence::UnknownKey)
const sc_pref sc_edit_file_close_all(sc_edit_file_cl+"_all", QKeySequence::UnknownKey)
const sc_pref sc_edit_edit_select_to_brace(sc_edit_edit+":select_to_brace", CTRL_SHIFT+Qt::Key_M)
const sc_pref sc_edit_debug_toggle_breakpoint(sc_edit_debug+":toggle_breakpoint", QKeySequence::UnknownKey)
const sc_pref sc_edit_edit_lower_case(sc_edit_edit+":lower_case", CTRL_ALT+Qt::Key_U)
const sc_pref sc_edit_edit_indent_selection(sc_edit_edit+":indent_selection", CTRL+Qt::Key_Tab)
const sc_pref sc_edit_view_zoom_in(sc_edit_view_zoom+"_in", QKeySequence::ZoomIn)
const sc_pref sc_edit_tabs_move_tab_left(sc_edit_tabs+":move_tab_left", Qt::AltModifier+Qt::Key_PageUp)
const sc_pref sc_edit_edit_delete_end_word(sc_edit_edit+":delete_end_word", QKeySequence::DeleteEndOfWord)
const sc_pref sc_edit_edit_preferences(sc_edit_edit+":preferences", QKeySequence::UnknownKey)
const sc_pref sc_edit_tabs_switch_right_tab(sc_edit_tabs+":switch_right_tab", CTRL+Qt::Key_PageDown)
const sc_pref sc_edit_edit_redo(sc_edit_edit+":redo", QKeySequence::Redo)
const sc_pref sc_edit_edit_conv_eol_unix(sc_edit_edit+":conv_eol_unix", QKeySequence::UnknownKey)
const sc_pref sc_edit_view_sort_tabs(sc_edit_view+":sort_tabs", QKeySequence::UnknownKey)
const sc_pref sc_edit_tabs_switch_left_tab(sc_edit_tabs+":switch_left_tab", CTRL+Qt::Key_PageUp)
const sc_pref sc_edit_view_show_line_numbers(sc_edit_view+":show_line_numbers", QKeySequence::UnknownKey)
const sc_pref sc_edit_view_zoom_out(sc_edit_view_zoom+"_out", QKeySequence::ZoomOut)
const sc_pref sc_edit_edit_conv_eol_mac(sc_edit_edit+":conv_eol_mac", QKeySequence::UnknownKey)
const sc_pref sc_edit_edit_conv_eol_winows(sc_edit_edit+":conv_eol_winows", QKeySequence::UnknownKey)
const sc_pref sc_edit_edit_previous_bookmark(sc_edit_edit+":previous_bookmark", PRE+Qt::SHIFT+Qt::Key_F2)
const sc_pref sc_edit_edit_delete_start_word(sc_edit_edit+":delete_start_word", QKeySequence::DeleteStartOfWord)
F77_RET_T const F77_DBLE * x
octave_idx_type n
Definition: mx-inlines.cc:753
T * r
Definition: mx-inlines.cc:773
std::complex< double > w(std::complex< double > z, double relerr=0)
QString fromStdString(const std::string &s)
std::function< void(octave::interpreter &)> meth_callback
Definition: event-manager.h:47
static double f(double k, double l_nu, double c_pm)
Definition: randpoisson.cc:118
std::function< void(void)> fcn_callback
Definition: event-manager.h:46
bool same_file(const std::string &f, const std::string &g)
Definition: utils.cc:138
octave_value::octave_value(const Array< char > &chm, char type) return retval
Definition: ov.cc:811
const QString key
const QVariant def