GNU Octave  8.1.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-2023 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 <QClipboard>
36 #include <QFile>
37 #include <QFileDialog>
38 #include <QFont>
39 #include <QMessageBox>
40 #include <QMimeData>
41 #include <QProcess>
42 #include <QPushButton>
43 #include <QStyle>
44 #include <QTabBar>
45 #include <QTextStream>
46 #include <QVBoxLayout>
47 #include <Qsci/qscicommandset.h>
48 
49 #include "file-editor.h"
50 #include "gui-preferences-ed.h"
51 #include "gui-preferences-sc.h"
52 #include "gui-preferences-global.h"
53 #include "main-window.h"
54 #include "octave-qobject.h"
55 #include "octave-qtutils.h"
56 #include "shortcut-manager.h"
57 
58 #include "oct-env.h"
59 
60 #include "event-manager.h"
61 #include "interpreter.h"
62 #include "oct-map.h"
63 #include "pt-eval.h"
64 #include "utils.h"
65 
67 
68 // Functions of the the reimplemented tab widget
69 
71 : QTabWidget (p)
72 {
73  tab_bar *bar = new tab_bar (this);
74 
75  connect (bar, &tab_bar::close_current_tab_signal,
77 
78  this->setTabBar (bar);
79 
80  setTabsClosable (true);
81  setUsesScrollButtons (true);
82  setMovable (true);
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 // File editor
100 
102  : file_editor_interface (p, oct_qobj)
103 {
104  // Set current editing directory before construction because loaded
105  // files will change ced accordingly.
106  m_ced = QDir::currentPath ();
107 
108  // Set actions that are later added by the main window to null,
109  // preventing access to them when they are still undefined.
110  m_undo_action = nullptr;
111  m_copy_action = nullptr;
112  m_paste_action = nullptr;
113  m_selectall_action = nullptr;
114 
115  m_find_dialog = nullptr;
116 
117  m_closed = false;
118  m_no_focus = false;
119  m_editor_ready = false;
120 
121  m_copy_action_enabled = false;
122  m_undo_action_enabled = false;
123  m_current_tab_modified = false;
124 
125  construct ();
126 
127  setVisible (false);
128  setAcceptDrops (true);
129  setFocusPolicy (Qt::StrongFocus);
130 }
131 
132 void file_editor::focusInEvent (QFocusEvent *e)
133 {
134  // The focus is transferred to the active tab and its edit
135  // area in this focus in event handler. This is to avoid
136  // using focus proxies with conflicts in the proxy change
137  // presumably introduced by bug
138  // https://bugreports.qt.io/browse/QTBUG-61092
139  reset_focus (); // Make sure editor tab with edit area get focus
140 
141  QDockWidget::focusInEvent (e);
142 }
143 
144 // insert global actions, that should also be displayed in the editor window,
145 // into the editor's menu and/or toolbar
147 {
148  // actions/menus that have to be added to the toolbar or the menu
149  QAction *open_action = shared_actions.at (OPEN_ACTION);
150  QAction *new_action = shared_actions.at (NEW_SCRIPT_ACTION);
151  QAction *new_fcn_action = shared_actions.at (NEW_FUNCTION_ACTION);
152  m_fileMenu->insertAction (m_mru_file_menu->menuAction (), open_action);
153  m_fileMenu->insertAction (open_action, new_fcn_action);
154  m_fileMenu->insertAction (new_fcn_action, new_action);
155  m_tool_bar->insertAction (m_popdown_mru_action, open_action);
156  m_tool_bar->insertAction (open_action, new_action);
157 
158  // actions that are additionally enabled/disabled later by the editor
159  // undo
160  m_undo_action = shared_actions.at (UNDO_ACTION);
161  m_tool_bar->insertAction (m_redo_action, m_undo_action);
162  m_edit_menu->insertAction (m_redo_action, m_undo_action);
163  // select all
164  m_selectall_action = shared_actions.at (SELECTALL_ACTION);
166  m_edit_menu->insertSeparator (m_find_action);
167  // paste
168  m_paste_action = shared_actions.at (PASTE_ACTION);
169  m_tool_bar->insertAction (m_find_action, m_paste_action);
171  m_edit_menu->insertSeparator (m_selectall_action);
172  // copy
173  m_copy_action = shared_actions.at (COPY_ACTION);
174  m_tool_bar->insertAction (m_paste_action, m_copy_action);
175  m_edit_menu->insertAction (m_paste_action, m_copy_action);
176  // find files
177  m_find_files_action = shared_actions.at (FIND_FILES_ACTION);
179 }
180 
182 {
185  QString sc_run = settings->sc_value (sc_edit_run_run_file);
186  QString sc_cont = settings->sc_value (sc_main_debug_continue);
187 
188  if (sc_run == sc_cont)
189  m_run_action->setShortcut (QKeySequence ()); // prevent ambiguous shortcuts
190 
191  m_run_action->setToolTip (tr ("Continue")); // update tool tip
192 
193  emit enter_debug_mode_signal ();
194 }
195 
197 {
200  m_run_action->setToolTip (tr ("Save File and Run")); // update tool tip
201 
202  emit exit_debug_mode_signal ();
203 }
204 
206 {
207  // Do not include shared actions not only related to the editor
208  bool have_tabs = m_tab_widget->count () > 0;
209 
210  m_edit_cmd_menu->setEnabled (have_tabs);
211  m_edit_fmt_menu->setEnabled (have_tabs);
212  m_edit_nav_menu->setEnabled (have_tabs);
213 
214  m_comment_selection_action->setEnabled (have_tabs);
215  m_uncomment_selection_action->setEnabled (have_tabs);
216  m_comment_var_selection_action->setEnabled (have_tabs);
217  m_indent_selection_action->setEnabled (have_tabs);
218  m_unindent_selection_action->setEnabled (have_tabs);
219  m_smart_indent_line_or_selection_action->setEnabled (have_tabs);
220 
221  m_context_help_action->setEnabled (have_tabs);
222  m_context_doc_action->setEnabled (have_tabs);
223 
224  m_view_editor_menu->setEnabled (have_tabs);
225  m_zoom_in_action->setEnabled (have_tabs);
226  m_zoom_out_action->setEnabled (have_tabs);
227  m_zoom_normal_action->setEnabled (have_tabs);
228 
229  m_find_action->setEnabled (have_tabs);
230  m_find_next_action->setEnabled (have_tabs);
231  m_find_previous_action->setEnabled (have_tabs);
232  m_print_action->setEnabled (have_tabs);
233 
234  m_run_action->setEnabled (have_tabs && m_is_octave_file);
235 
236  m_toggle_breakpoint_action->setEnabled (have_tabs && m_is_octave_file);
237  m_next_breakpoint_action->setEnabled (have_tabs && m_is_octave_file);
238  m_previous_breakpoint_action->setEnabled (have_tabs && m_is_octave_file);
239  m_remove_all_breakpoints_action->setEnabled (have_tabs && m_is_octave_file);
240 
241  m_edit_function_action->setEnabled (have_tabs);
242  m_save_action->setEnabled (have_tabs && m_current_tab_modified);
243  m_save_as_action->setEnabled (have_tabs);
244  m_close_action->setEnabled (have_tabs);
245  m_close_all_action->setEnabled (have_tabs);
246  m_close_others_action->setEnabled (have_tabs && m_tab_widget->count () > 1);
247  m_sort_tabs_action->setEnabled (have_tabs && m_tab_widget->count () > 1);
248 
250 }
251 
252 // empty_script determines whether we have to create an empty script
253 // 1. At startup, when the editor has to be (really) visible
254 // (Here we can not use the visibility changed signal)
255 // 2. When the editor becomes visible when octave is running
256 void file_editor::empty_script (bool startup, bool visible)
257 {
258 
259  if (startup)
260  m_editor_ready = true;
261  else
262  {
263  if (! m_editor_ready)
264  return; // not yet ready but got visibility changed signals
265  }
266 
270  global_use_custom_editor.def).toBool ())
271  return; // do not open an empty script in the external editor
272 
273  bool real_visible;
274 
275  if (startup)
276  real_visible = isVisible ();
277  else
278  real_visible = visible;
279 
280  if (! real_visible || m_tab_widget->count () > 0)
281  return;
282 
283  if (startup && ! isFloating ())
284  {
285  // check if editor is really visible or hidden between tabbed widgets
286  QWidget *parent = parentWidget ();
287 
288  if (parent)
289  {
290  QList<QTabBar *> tab_list = parent->findChildren<QTabBar *>();
291 
292  bool in_tab = false;
293  int i = 0;
294  while ((i < tab_list.count ()) && (! in_tab))
295  {
296  QTabBar *tab = tab_list.at (i);
297  i++;
298 
299  int j = 0;
300  while ((j < tab->count ()) && (! in_tab))
301  {
302  // check all tabs for the editor
303  if (tab->tabText (j) == windowTitle ())
304  {
305  // editor is in this tab widget
306  in_tab = true;
307  int top = tab->currentIndex ();
308  if (! (top > -1 && tab->tabText (top) == windowTitle ()))
309  return; // not current tab -> not visible
310  }
311  j++;
312  }
313  }
314  }
315  }
316 
317  request_new_file ("");
318 }
319 
321 {
322  //restore previous session
323  if (! settings->value (ed_restore_session).toBool ())
324  return;
325 
326  // get the data from the settings file
327  QStringList sessionFileNames
328  = settings->value (ed_session_names).toStringList ();
329 
330  QStringList session_encodings
331  = settings->value (ed_session_enc).toStringList ();
332 
333  QStringList session_index
334  = settings->value (ed_session_ind).toStringList ();
335 
336  QStringList session_lines
337  = settings->value (ed_session_lines).toStringList ();
338 
339  QStringList session_bookmarks
340  = settings->value (ed_session_bookmarks).toStringList ();
341 
342  // fill a list of the struct and sort it (depending on index)
343  QList<session_data> s_data;
344 
345  bool do_encoding = (session_encodings.count () == sessionFileNames.count ());
346  bool do_index = (session_index.count () == sessionFileNames.count ());
347  bool do_lines = (session_lines.count () == sessionFileNames.count ());
348  bool do_bookmarks = (session_bookmarks.count () == sessionFileNames.count ());
349 
350  for (int n = 0; n < sessionFileNames.count (); ++n)
351  {
352  QFileInfo file = QFileInfo (sessionFileNames.at (n));
353  if (! file.exists ())
354  continue;
355 
356  session_data item = { 0, -1, sessionFileNames.at (n),
357  QString (), QString (), QString ()};
358  if (do_lines)
359  item.line = session_lines.at (n).toInt ();
360  if (do_index)
361  item.index = session_index.at (n).toInt ();
362  if (do_encoding)
363  item.encoding = session_encodings.at (n);
364  if (do_bookmarks)
365  item.bookmarks = session_bookmarks.at (n);
366 
367  s_data << item;
368  }
369 
370  std::sort (s_data.begin (), s_data.end ());
371 
372  // finally open the files with the desired encoding in the desired order
373  for (int n = 0; n < s_data.count (); ++n)
374  request_open_file (s_data.at (n).file_name, s_data.at (n).encoding,
375  s_data.at (n).line, false, false, true, "", -1,
376  s_data.at (n).bookmarks);
377 }
378 
380 {
381  if (m_no_focus)
382  return; // No focus for the editor if external open/close request
383 
385 
386  // set focus to current tab
387  reset_focus ();
388 }
389 
391 {
392  setFocus ();
393 
394  // set focus to desired tab
395  if (fet)
396  m_tab_widget->setCurrentWidget (fet);
397 }
398 
399 // function enabling/disabling the menu accelerators depending on the
400 // focus of the editor
402 {
403  // Hide or show the find dialog together with the focus of the
404  // editor widget depending on the overall visibility of the find dialog.
405  // Do not change internal visibility state.
406  if (m_find_dialog)
407  m_find_dialog->set_visible (enable);
408 
409  // Take care of the shortcuts
410  QHash<QMenu *, QStringList>::const_iterator i = m_hash_menu_text.constBegin ();
411 
412  while (i != m_hash_menu_text.constEnd ())
413  {
414  i.key ()->setTitle (i.value ().at (! enable));
415  ++i;
416  }
417 
418  // when editor loses focus, enable the actions, which are always active
419  // in the main window due to missing info on selected text and undo actions
421  {
422  if (enable)
423  {
424  m_copy_action->setEnabled (m_copy_action_enabled);
425  m_undo_action->setEnabled (m_undo_action_enabled);
426  }
427  else
428  {
429  m_copy_action_enabled = m_copy_action->isEnabled ();
430  m_undo_action_enabled = m_undo_action->isEnabled ();
431  m_copy_action->setEnabled (true);
432  m_undo_action->setEnabled (true);
433  }
434  }
435 }
436 
437 // Save open files for restoring in next session
438 // (even if last session will not be restored next time)
439 // together with encoding and the tab index
441 {
444 
445  QStringList fetFileNames;
446  QStringList fet_encodings;
447  QStringList fet_index;
448  QStringList fet_lines;
449  QStringList fet_bookmarks;
450 
451  std::list<file_editor_tab *> editor_tab_lst = m_tab_widget->tab_list ();
452 
453  for (auto editor_tab : editor_tab_lst)
454  {
455  QString file_name = editor_tab->file_name ();
456 
457  // Don't append unnamed files.
458 
459  if (! file_name.isEmpty ())
460  {
461  fetFileNames.append (file_name);
462  fet_encodings.append (editor_tab->encoding ());
463 
464  QString index;
465  fet_index.append (index.setNum (m_tab_widget->indexOf (editor_tab)));
466 
467  int l, c;
468  editor_tab->qsci_edit_area ()->getCursorPosition (&l, &c);
469  fet_lines.append (index.setNum (l + 1));
470 
471  fet_bookmarks.append (editor_tab->get_all_bookmarks ());
472  }
473  }
474 
475  settings->setValue (ed_session_names.key, fetFileNames);
476  settings->setValue (ed_session_enc.key, fet_encodings);
477  settings->setValue (ed_session_ind.key, fet_index);
478  settings->setValue (ed_session_lines.key, fet_lines);
479  settings->setValue (ed_session_bookmarks.key, fet_bookmarks);
480  settings->sync ();
481 }
482 
484 {
485  // When the application or the editor is closing and the user wants to
486  // close all files, in the latter case all editor tabs are checked whether
487  // they need to be saved. During these checks tabs are not closed since
488  // the user might cancel closing Octave during one of these saving dialogs.
489  // Therefore, saving the session for restoring at next start is not done
490  // before the application is definitely closing.
491 
492  // Save the session. Even is closing is cancelled, this would be
493  // overwritten by the next attempt to close the editor
494  save_session ();
495 
496  std::list<file_editor_tab *> fe_tab_lst = m_tab_widget->tab_list ();
497  m_number_of_tabs = fe_tab_lst.size ();
498 
499  for (auto fe_tab : fe_tab_lst)
500  {
501  // Wait for all editor tabs to have saved their files if required
502 
503  connect (fe_tab, &file_editor_tab::tab_ready_to_close,
505  Qt::UniqueConnection);
506  }
507 
508  m_closing_canceled = false;
509 
510  for (auto fe_tab : fe_tab_lst)
511  {
512  // If there was a cancellation, make the already saved/discarded tabs
513  // recover from the exit by removing the read-only state and by
514  // recovering the debugger breakpoints. Finally return false in order
515  // to cancel closing the application or the editor.
516 
517  if (fe_tab->check_file_modified (false) == QMessageBox::Cancel)
518  {
519  emit fetab_recover_from_exit ();
520 
521  m_closing_canceled = true;
522 
523  for (auto fet : fe_tab_lst)
524  disconnect (fet, &file_editor_tab::tab_ready_to_close, 0, 0);
525 
526  return false;
527  }
528  }
529 
530  return true;
531 }
532 
534 {
535  if (m_closing_canceled)
536  return;
537 
538  // FIXME: Why count down to zero here before doing anything? Why
539  // not remove and delete each tab that is ready to be closed, one
540  // per invocation?
541 
543 
544  if (m_number_of_tabs > 0)
545  return;
546 
547  // Here, the application or the editor will be closed -> store the session
548 
549  // Take care of the find dialog
550  if (m_find_dialog)
551  m_find_dialog->close ();
552 
553  // Finally close all the tabs and return indication that we can exit
554  // the application or close the editor.
555  // Closing and deleting the tabs makes the editor visible. In case it was
556  // hidden before, this state has to be restored afterwards.
557  bool vis = isVisible ();
558 
559  std::list<file_editor_tab *> editor_tab_lst = m_tab_widget->tab_list ();
560  for (auto editor_tab : editor_tab_lst)
561  editor_tab->deleteLater ();
562 
563  m_tab_widget->clear ();
564 
565  setVisible (vis);
566 }
567 
568 void file_editor::request_new_file (const QString& commands)
569 {
570  // Custom editor? If yes, we can only call the editor without passing
571  // some initial contents and even without being sure a new file is opened
572  if (call_custom_editor ())
573  return;
574 
575  // New file isn't a file_editor_tab function since the file
576  // editor tab has yet to be created and there is no object to
577  // pass a signal to. Hence, functionality is here.
578 
579  file_editor_tab *fileEditorTab = make_file_editor_tab (m_ced);
580  add_file_editor_tab (fileEditorTab, ""); // new tab with empty title
581  fileEditorTab->new_file (commands); // title is updated here
582  activate (); // focus editor and new tab
583 }
584 
586 {
587  file_editor_tab *editor_tab
588  = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());
589  editor_tab->conditional_close ();
590 }
591 
593 {
594  file_editor_tab *editor_tab;
595 
596  // loop over all tabs starting from last one otherwise deletion changes index
597  for (int index = m_tab_widget->count ()-1; index >= 0; index--)
598  {
599  editor_tab = static_cast<file_editor_tab *> (m_tab_widget->widget (index));
600  editor_tab->conditional_close ();
601  }
602 }
603 
605 {
606  file_editor_tab *editor_tab;
607  QWidget *tabID = m_tab_widget->currentWidget ();
608 
609  // loop over all tabs starting from last one otherwise deletion changes index
610  for (int index = m_tab_widget->count ()-1; index >= 0; index--)
611  {
612  if (tabID != m_tab_widget->widget (index))
613  {
614  editor_tab
615  = static_cast<file_editor_tab *> (m_tab_widget->widget (index));
616  editor_tab->conditional_close ();
617  }
618  }
619 }
620 
622 {
623  file_editor_tab *editor_tab
624  = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());
625 
626  if (editor_tab)
627  QGuiApplication::clipboard ()->setText (editor_tab->file_name ());
628 }
629 
630 // open a file from the mru list
632 {
633  if (action)
634  {
635  request_open_file (action->data ().toStringList ().at (0),
636  action->data ().toStringList ().at (1));
637  }
638 }
639 
641 {
642  emit fetab_print_file (m_tab_widget->currentWidget ());
643 }
644 
646 {
647  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
648  QsciScintillaBase::SCI_REDO);
649 }
650 
652 {
653  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
654  QsciScintillaBase::SCI_CUT);
655 }
656 
658 {
659  emit fetab_context_help (m_tab_widget->currentWidget (), false);
660 }
661 
663 {
664  emit fetab_context_help (m_tab_widget->currentWidget (), true);
665 }
666 
668 {
669  emit fetab_context_edit (m_tab_widget->currentWidget ());
670 }
671 
673 {
674  emit fetab_save_file (m_tab_widget->currentWidget ());
675 }
676 
678 {
679  emit fetab_save_file_as (m_tab_widget->currentWidget ());
680 }
681 
683 {
684  // The interpreter_event callback function below emits a signal.
685  // Because we don't control when that happens, use a guarded pointer
686  // so that the callback can abort if this object is no longer valid.
687 
688  QPointer<file_editor> this_fe (this);
689 
690  emit interpreter_event
691  ([=] (interpreter& interp)
692  {
693  // INTERPRETER THREAD
694 
695  // If THIS_FE is no longer valid, skip the entire callback
696  // function. With the way things are implemented now, we can't
697  // run the contents of a file unless the file editor and the
698  // corresponding file editor tab are still valid.
699 
700  if (this_fe.isNull ())
701  return;
702 
703  // Act as though this action was entered at the command propmt
704  // so that the interpreter will check for updated file time
705  // stamps.
706  Vlast_prompt_time.stamp ();
707 
708  tree_evaluator& tw = interp.get_evaluator ();
709 
710  if (tw.in_debug_repl ())
711  emit request_dbcont_signal ();
712  else
713  emit fetab_run_file (m_tab_widget->currentWidget ());
714  });
715 }
716 
718 {
719  emit fetab_run_file (m_tab_widget->currentWidget (), true);
720 }
721 
723 {
724  emit fetab_context_run (m_tab_widget->currentWidget ());
725 }
726 
728 {
729  emit fetab_toggle_bookmark (m_tab_widget->currentWidget ());
730 }
731 
733 {
734  emit fetab_next_bookmark (m_tab_widget->currentWidget ());
735 }
736 
738 {
739  emit fetab_previous_bookmark (m_tab_widget->currentWidget ());
740 }
741 
743 {
744  emit fetab_remove_bookmark (m_tab_widget->currentWidget ());
745 }
746 
748 {
749  emit fetab_move_match_brace (m_tab_widget->currentWidget (), false);
750 }
751 
753 {
754  emit fetab_move_match_brace (m_tab_widget->currentWidget (), true);
755 }
756 
757 // FIXME: What should this do with conditional breakpoints?
759 {
760  emit fetab_toggle_breakpoint (m_tab_widget->currentWidget ());
761 }
762 
764 {
765  emit fetab_next_breakpoint (m_tab_widget->currentWidget ());
766 }
767 
769 {
770  emit fetab_previous_breakpoint (m_tab_widget->currentWidget ());
771 }
772 
774 {
775  emit fetab_remove_all_breakpoints (m_tab_widget->currentWidget ());
776 }
777 
778 // slots for Edit->Commands actions
780 {
781  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
782  QsciScintillaBase::SCI_DELWORDLEFT);
783 }
784 
786 {
787  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
788  QsciScintillaBase::SCI_DELWORDRIGHT);
789 }
790 
792 {
793  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
794  QsciScintillaBase::SCI_DELLINELEFT);
795 }
796 
798 {
799  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
800  QsciScintillaBase::SCI_DELLINERIGHT);
801 }
802 
804 {
805  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
806  QsciScintillaBase::SCI_LINEDELETE);
807 }
808 
810 {
811  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
812  QsciScintillaBase::SCI_LINECOPY);
813 }
814 
816 {
817  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
818  QsciScintillaBase::SCI_LINECUT);
819 }
820 
822 {
823  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
824  QsciScintillaBase::SCI_SELECTIONDUPLICATE);
825 }
826 
828 {
829  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
830  QsciScintillaBase::SCI_LINETRANSPOSE);
831 }
832 
834 {
835  emit fetab_comment_selected_text (m_tab_widget->currentWidget (), false);
836 }
837 
839 {
840  emit fetab_uncomment_selected_text (m_tab_widget->currentWidget ());
841 }
842 
844 {
845  emit fetab_comment_selected_text (m_tab_widget->currentWidget (), true);
846 }
847 
848 // slots for Edit->Format actions
850 {
851  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
852  QsciScintillaBase::SCI_UPPERCASE);
853 }
854 
856 {
857  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
858  QsciScintillaBase::SCI_LOWERCASE);
859 }
860 
862 {
863  emit fetab_indent_selected_text (m_tab_widget->currentWidget ());
864 }
865 
867 {
868  emit fetab_unindent_selected_text (m_tab_widget->currentWidget ());
869 }
870 
872 {
874 }
875 
877 {
878  emit fetab_convert_eol (m_tab_widget->currentWidget (),
879  QsciScintilla::EolWindows);
880 }
881 void
883 {
884  emit fetab_convert_eol (m_tab_widget->currentWidget (),
885  QsciScintilla::EolUnix);
886 }
887 
889 {
890  emit fetab_convert_eol (m_tab_widget->currentWidget (),
891  QsciScintilla::EolMac);
892 }
893 
894 // Slot for initially creating and showing the find dialog
896 {
897  // Create the dialog
898  find_create ();
899 
900  // Since find_create shows the dialog without activating the widget
901  // (which is reuqired in other cases) do this manually here
902  m_find_dialog->activateWindow ();
903 
904  // Initiate search text from possible selection and save the initial
905  // data from the dialog on the defined structure
906  m_find_dialog->init_search_text ();
907 }
908 
909 // This method creates the find dialog.
910 
912 {
913  if (m_find_dialog)
914  m_find_dialog->close ();
915 
916  if (isFloating ())
917  m_find_dialog = new find_dialog (m_octave_qobj, this, this);
918  else
919  m_find_dialog = new find_dialog (m_octave_qobj, this, parentWidget ());
920 
921  // Add required actions
922  m_find_dialog->addAction (m_find_next_action);
924 
925  // Update edit area
926  file_editor_tab *fet
927  = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());
928  m_find_dialog->update_edit_area (fet->qsci_edit_area ());
929 
930  // Icon is the same as the editor
931  m_find_dialog->setWindowIcon (windowIcon ());
932 
933  // Position: lower right of editor's position
934  int xp = x () + frameGeometry ().width ();
935  int yp = y () + frameGeometry ().height ();
936 
937  if (! isFloating ())
938  {
939  // Fix position if editor is docked
940 
941  QWidget *parent = parentWidget ();
942 
943  if (parent)
944  {
945  xp = xp + parent->x ();
946  yp = yp + parent->y ();
947  }
948  }
949 
950  if (yp < 0)
951  yp = 0;
952 
953  // The size of the find dialog is considered in restore_settings
954  // since its size might change depending on the options
955  m_find_dialog->restore_settings (QPoint (xp, yp));
956 
957  // Set visible
958  m_find_dialog->set_visible (true);
959 }
960 
962 {
963  if (m_find_dialog)
964  m_find_dialog->find_next ();
965 }
966 
968 {
969  if (m_find_dialog)
970  m_find_dialog->find_prev ();
971 }
972 
974 {
975  emit fetab_goto_line (m_tab_widget->currentWidget ());
976 }
977 
979 {
980  emit fetab_completion (m_tab_widget->currentWidget ());
981 }
982 
983 void file_editor::handle_file_name_changed (const QString& fname,
984  const QString& tip,
985  bool modified)
986 {
987  QObject *fileEditorTab = sender ();
988  if (fileEditorTab)
989  {
991 
992  for (int i = 0; i < m_tab_widget->count (); i++)
993  {
994  if (m_tab_widget->widget (i) == fileEditorTab)
995  {
996  m_tab_widget->setTabText (i, fname);
997  m_tab_widget->setTabToolTip (i, tip);
998 
999  m_save_action->setEnabled (modified);
1000  m_current_tab_modified = modified;
1001 
1002  if (modified)
1003  m_tab_widget->setTabIcon (i, rmgr.icon ("document-save"));
1004  else
1005  m_tab_widget->setTabIcon (i, QIcon ());
1006  }
1007  }
1008  }
1009 }
1010 
1012 {
1013  file_editor_tab *editor_tab
1014  = static_cast<file_editor_tab *> (m_tab_widget->widget (index));
1015  editor_tab->conditional_close ();
1016 }
1017 
1018 void
1020 {
1021  QObject *fileEditorTab = sender ();
1022  if (fileEditorTab)
1023  {
1024  for (int i = 0; i < m_tab_widget->count (); i++)
1025  {
1026  if (m_tab_widget->widget (i) == fileEditorTab)
1027  {
1028  m_tab_widget->removeTab (i);
1029 
1030  // Deleting the sender (even with deleteLater) seems a
1031  // bit strange. Is there a better way?
1032  fileEditorTab->deleteLater ();
1033  break;
1034  }
1035  }
1036  }
1037  check_actions ();
1038 
1039  activate (); // focus stays in editor when tab is closed
1040 
1041 }
1042 
1043 // context menu of edit area
1045 {
1046  emit fetab_change_request (m_tab_widget->widget (index));
1047  activate ();
1048 }
1049 
1051  bool is_octave_file,
1052  bool is_modified)
1053 {
1054  // In case there is some scenario where traffic could be coming from
1055  // all the file editor tabs, just process info from the current active tab.
1056  if (sender () == m_tab_widget->currentWidget ())
1057  {
1058  m_save_action->setEnabled (is_modified);
1059  m_current_tab_modified = is_modified;
1060 
1061  if (m_copy_action)
1062  m_copy_action->setEnabled (copy_available);
1063 
1064  m_cut_action->setEnabled (copy_available);
1065 
1066  m_run_selection_action->setEnabled (copy_available);
1067  m_run_action->setEnabled (is_octave_file);
1068  m_is_octave_file = is_octave_file;
1069 
1071  }
1072 
1073  m_copy_action_enabled = m_copy_action->isEnabled ();
1074  m_undo_action_enabled = m_undo_action->isEnabled ();
1075 }
1076 
1077 void file_editor::handle_mru_add_file (const QString& file_name,
1078  const QString& encoding)
1079 {
1080  int index;
1081  while ((index = m_mru_files.indexOf (file_name)) >= 0)
1082  {
1083  m_mru_files.removeAt (index);
1084  m_mru_files_encodings.removeAt (index);
1085  }
1086 
1087  m_mru_files.prepend (file_name);
1088  m_mru_files_encodings.prepend (encoding);
1089 
1090  mru_menu_update ();
1091 }
1092 
1093 void file_editor::check_conflict_save (const QString& saveFileName,
1094  bool remove_on_success)
1095 {
1096  // Check whether this file is already open in the editor.
1097  file_editor_tab *tab = find_tab_widget (saveFileName);
1098 
1099  if (tab)
1100  {
1101  // Note: to overwrite the contents of some other file editor tab
1102  // with the same name requires identifying which file editor tab
1103  // that is (not too difficult) then closing that tab. Of course,
1104  // that could trigger another dialog box if the file editor tab
1105  // with the same name has modifications in it. This could become
1106  // somewhat confusing to the user. For now, opt to do nothing.
1107 
1108  // Create a NonModal message about error.
1109  QMessageBox *msgBox
1110  = new QMessageBox (QMessageBox::Critical, tr ("Octave Editor"),
1111  tr ("File not saved! A file with the selected name\n%1\n"
1112  "is already open in the editor").
1113  arg (saveFileName),
1114  QMessageBox::Ok, nullptr);
1115 
1116  msgBox->setWindowModality (Qt::NonModal);
1117  msgBox->setAttribute (Qt::WA_DeleteOnClose);
1118  msgBox->show ();
1119 
1120  return;
1121  }
1122 
1123  QObject *saveFileObject = sender ();
1124  QWidget *saveFileWidget = nullptr;
1125 
1126  for (int i = 0; i < m_tab_widget->count (); i++)
1127  {
1128  if (m_tab_widget->widget (i) == saveFileObject)
1129  {
1130  saveFileWidget = m_tab_widget->widget (i);
1131  break;
1132  }
1133  }
1134  if (! saveFileWidget)
1135  {
1136  // Create a NonModal message about error.
1137  QMessageBox *msgBox
1138  = new QMessageBox (QMessageBox::Critical, tr ("Octave Editor"),
1139  tr ("The associated file editor tab has disappeared."),
1140  QMessageBox::Ok, nullptr);
1141 
1142  msgBox->setWindowModality (Qt::NonModal);
1143  msgBox->setAttribute (Qt::WA_DeleteOnClose);
1144  msgBox->show ();
1145 
1146  return;
1147  }
1148 
1149  // Can save without conflict, have the file editor tab do so.
1150  emit fetab_save_file (saveFileWidget, saveFileName, remove_on_success);
1151 }
1152 
1154  int line)
1155 {
1156  request_open_file (file, QString (), line, true); // default encoding
1157 }
1158 
1160  int line)
1161 {
1162  if (! file.isEmpty ())
1163  {
1164  // Check whether this file is already open in the editor.
1165  file_editor_tab *tab = find_tab_widget (file);
1166 
1167  if (tab)
1168  {
1169  m_tab_widget->setCurrentWidget (tab);
1170 
1171  if (line > 0)
1172  emit fetab_delete_debugger_pointer (tab, line);
1173 
1174  emit fetab_set_focus (tab);
1175  }
1176  }
1177 }
1178 
1180  const QString& file,
1181  int line,
1182  const QString& cond)
1183 {
1184  request_open_file (file, QString (), line, false, true, insert, cond);
1185 }
1186 
1187 void file_editor::handle_edit_file_request (const QString& file)
1188 {
1189  request_open_file (file);
1190 }
1191 
1192 // Slot used for signals indicating that a file was changed/renamed or
1193 // is going to be deleted/renamed
1194 void file_editor::handle_file_remove (const QString& old_name,
1195  const QString& new_name)
1196 {
1197  // Clear old list of file data and declare a structure for file data
1198  m_tmp_closed_files.clear ();
1199  removed_file_data f_data;
1200 
1201  // Preprocessing old name(s)
1202  QString old_name_clean = old_name.trimmed ();
1203  int s = old_name_clean.size ();
1204 
1205  if (s > 1 && old_name_clean.at (0) == QChar ('\"')
1206  && old_name_clean.at (s - 1) == QChar ('\"'))
1207  old_name_clean = old_name_clean.mid (1, s - 2);
1208 
1209  QStringList old_names = old_name_clean.split ("\" \"");
1210 
1211  // Check if new name is a file or directory
1212  QFileInfo newf (new_name);
1213  bool new_is_dir = newf.isDir ();
1214 
1215  // Now loop over all old files/dirs (several files by movefile ())
1216  for (int i = 0; i < old_names.count (); i++)
1217  {
1218  // Check if old name is a file or directory
1219  QFileInfo old (old_names.at (i));
1220 
1221  if (old.isDir ())
1222  {
1223  // Call the function which handles directories and return
1224  handle_dir_remove (old_names.at (i), new_name);
1225  }
1226  else
1227  {
1228  // It is a single file. Is it open?
1229  file_editor_tab *editor_tab = find_tab_widget (old_names.at (i));
1230 
1231  if (editor_tab)
1232  {
1233 
1234  editor_tab->enable_file_watcher (false);
1235 
1236  // For re-enabling tracking if error while removing/renaming
1237  f_data.editor_tab = editor_tab;
1238  // For renaming into new file (if new_file is not empty)
1239  if (new_is_dir)
1240  {
1241  std::string ndir = new_name.toStdString ();
1242  std::string ofile = old.fileName ().toStdString ();
1243  f_data.new_file_name
1245  }
1246  else
1247  f_data.new_file_name = new_name;
1248 
1249  // Add file data to list
1250  m_tmp_closed_files << f_data;
1251  }
1252  }
1253  }
1254 }
1255 
1256 // Slot for signal indicating that a file was renamed
1258 {
1259  m_no_focus = true; // Remember for not focussing editor
1260 
1261  // Loop over all files that have to be handled. Start at the end of the
1262  // list, otherwise the stored indexes are not correct.
1263  for (int i = m_tmp_closed_files.count () - 1; i >= 0; i--)
1264  {
1265  if (load_new)
1266  {
1267  // Close file (remove) or rename into new file (rename)
1268  if (m_tmp_closed_files.at (i).new_file_name.isEmpty ())
1269  m_tmp_closed_files.at (i).editor_tab->file_has_changed (QString (), true);
1270  else
1271  m_tmp_closed_files.at (i).editor_tab->set_file_name (
1272  m_tmp_closed_files.at (i).new_file_name);
1273  }
1274  else
1275  {
1276  // Something went wrong while renaming or removing:
1277  // Leave everything as it is but reactivate tracking
1278  m_tmp_closed_files.at (i).editor_tab->enable_file_watcher (true);
1279  }
1280 
1281  }
1282 
1283  m_no_focus = false; // Back to normal focus
1284 
1285  // Clear the list of file data
1286  m_tmp_closed_files.clear ();
1287 }
1288 
1290 {
1291  int size_idx = settings->value (global_icon_size).toInt ();
1292  size_idx = (size_idx > 0) - (size_idx < 0) + 1; // Make valid index from 0 to 2
1293 
1294  QStyle *st = style ();
1295  int icon_size = st->pixelMetric (global_icon_sizes[size_idx]);
1296  m_tool_bar->setIconSize (QSize (icon_size, icon_size));
1297 
1298  // Tab position and rotation
1299  QTabWidget::TabPosition pos
1300  = static_cast<QTabWidget::TabPosition> (settings->value (ed_tab_position).toInt ());
1301  bool rotated = settings->value (ed_tabs_rotated).toBool ();
1302 
1303  m_tab_widget->setTabPosition (pos);
1304 
1305  if (rotated)
1306  m_tab_widget->setTabsClosable (false); // No close buttons
1307  // FIXME: close buttons can not be correctly placed in rotated tabs
1308 
1309  // Get the tab bar and set the rotation
1310  int rotation = rotated;
1311  if (pos == QTabWidget::West)
1312  rotation = -rotation;
1313 
1314  tab_bar *bar = m_tab_widget->get_tab_bar ();
1315  bar->set_rotated (rotation);
1316 
1317  // Get suitable height of a tab related to font and icon size
1318  int height = 1.5*QFontMetrics (m_tab_widget->font ()).height ();
1319  int is = 1.5*m_tab_widget->iconSize ().height ();
1320  if (is > height)
1321  height = is;
1322 
1323  // Calculate possibly limited width and set the elide mode
1324  int chars = settings->value (ed_tabs_max_width).toInt ();
1325  int width = 9999;
1326  if (chars > 0)
1327  width = chars * QFontMetrics (m_tab_widget->font ()).averageCharWidth ();
1328 
1329  // Get tab bar size properties for style sheet depending on rotation
1330  QString width_str ("width");
1331  QString height_str ("height");
1332  if ((pos == QTabWidget::West) || (pos == QTabWidget::East))
1333  {
1334  width_str = QString ("height");
1335  height_str = QString ("width");
1336  }
1337 
1338  QString style_sheet
1339  = QString ("QTabBar::tab {max-" + height_str + ": %1px;\n"
1340  "max-" + width_str + ": %2px; }")
1341  .arg (height).arg (width);
1342 
1343 #if defined (Q_OS_MAC)
1344  // FIXME: This is a workaround for missing tab close buttons on MacOS
1345  // in several Qt versions (https://bugreports.qt.io/browse/QTBUG-61092)
1346  if (! rotated)
1347  {
1348  QString icon = global_icon_paths.at (ICON_THEME_OCTAVE) + "widget-close.png";
1349 
1350  QString close_button_css_mac (
1351  "QTabBar::close-button"
1352  " { image: url(" + icon + ");"
1353  " padding: 4px;"
1354  " subcontrol-position: bottom; }\n"
1355  "QTabBar::close-button:hover"
1356  " { background-color: #cccccc; }");
1357 
1358  style_sheet = style_sheet + close_button_css_mac;
1359  }
1360 #endif
1361 
1362  m_tab_widget->setStyleSheet (style_sheet);
1363 
1364  bool show_it;
1365  show_it = settings->value (ed_show_line_numbers).toBool ();
1366  m_show_linenum_action->setChecked (show_it);
1367  show_it = settings->value (ed_show_white_space).toBool ();
1368  m_show_whitespace_action->setChecked (show_it);
1369  show_it = settings->value (ed_show_eol_chars).toBool ();
1370  m_show_eol_action->setChecked (show_it);
1371  show_it = settings->value (ed_show_indent_guides).toBool ();
1372  m_show_indguide_action->setChecked (show_it);
1373  show_it = settings->value (ed_long_line_marker).toBool ();
1374  m_show_longline_action->setChecked (show_it);
1375 
1376  show_it = settings->value (ed_show_toolbar).toBool ();
1377  m_show_toolbar_action->setChecked (show_it);
1378  m_tool_bar->setVisible (show_it);
1379  show_it = settings->value (ed_show_edit_status_bar).toBool ();
1380  m_show_statusbar_action->setChecked (show_it);
1381  show_it = settings->value (ed_show_hscroll_bar).toBool ();
1382  m_show_hscrollbar_action->setChecked (show_it);
1383 
1384  set_shortcuts ();
1385 
1386  // Find dialog with the same icon as the editor
1387  if (m_find_dialog)
1388  m_find_dialog->setWindowIcon (windowIcon ());
1389 
1390  // Relay signal to file editor tabs.
1392 }
1393 
1395 {
1396  // Shortcuts also available in the main window, as well as the related
1397  // shortcuts, are defined in main_window and added to the editor
1398 
1400 
1401  // File menu
1409 
1410  // Edit menu
1416 
1429 
1445 
1449 
1450  // View menu
1463 
1464  // Debug menu
1469 
1470  // Run menu
1473 
1474  // Help menu
1477 
1478  // Tab navigation without menu entries
1483 
1484 }
1485 
1486 // This slot is a reimplementation of the virtual slot in octave_dock_widget.
1487 // We need this for creating an empty script when the editor has no open
1488 // files and is made visible.
1490 {
1492 
1493  if (! m_editor_ready)
1494  return;
1495 
1496  if (m_closed && visible)
1497  {
1498  m_closed = false;
1500  gui_settings *settings = rmgr.get_settings ();
1502  }
1503 
1504  empty_script (false, visible);
1505 }
1506 
1507 // This slot is a reimplementation of the virtual slot in octave_dock_widget.
1508 // We need this for updating the parent of the find dialog
1510 {
1511  if (m_find_dialog)
1512  {
1513  // close current dialog
1514  m_find_dialog->close ();
1515 
1516  // re-create dialog with the new parent (editor or main-win)
1517  find_create ();
1518  m_find_dialog->activateWindow ();
1519  }
1520 }
1521 
1522 void file_editor::update_octave_directory (const QString& dir)
1523 {
1524  m_ced = dir;
1525  emit fetab_set_directory (m_ced); // for save dialog
1526 }
1527 
1529 {
1530  if (editor_tab_has_focus ())
1531  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
1532  QsciScintillaBase::SCI_COPY);
1533 }
1534 
1536 {
1537  if (editor_tab_has_focus ())
1538  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
1539  QsciScintillaBase::SCI_PASTE);
1540 }
1541 
1543 {
1544  if (editor_tab_has_focus ())
1545  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
1546  QsciScintillaBase::SCI_SELECTALL);
1547 }
1548 
1550 {
1551  if (editor_tab_has_focus ())
1552  emit fetab_scintilla_command (m_tab_widget->currentWidget (),
1553  QsciScintillaBase::SCI_UNDO);
1554 }
1555 
1556 // Open a file, if not already open, and mark the current execution location
1557 // and/or a breakpoint with condition cond.
1558 void file_editor::request_open_file (const QString& openFileName,
1559  const QString& encoding,
1560  int line, bool debug_pointer,
1561  bool breakpoint_marker, bool insert,
1562  const QString& cond, int index,
1563  const QString& bookmarks)
1564 {
1566  gui_settings *settings = rmgr.get_settings ();
1567 
1568  if (settings->value (global_use_custom_editor).toBool ())
1569  {
1570  // Custom editor
1571  if (debug_pointer || breakpoint_marker)
1572  return; // Do not call custom editor during debugging
1573 
1574  if (call_custom_editor (openFileName, line))
1575  return; // Custom editor called
1576  }
1577 
1578  bool show_dbg_file
1579  = settings->value (ed_show_dbg_file).toBool ();
1580 
1581  if (openFileName.isEmpty ())
1582  {
1583  // This happens if edit is called without an argument
1584  // Open editor with empty edit area instead (as new file would do)
1585  request_new_file ("");
1586  }
1587  else
1588  {
1589  // Check whether this file is already open in the editor.
1590  file_editor_tab *tab = find_tab_widget (openFileName);
1591 
1592  if (tab)
1593  {
1594  m_tab_widget->setCurrentWidget (tab);
1595 
1596  if (line > 0)
1597  {
1598  if (insert)
1599  emit fetab_goto_line (tab, line);
1600 
1601  if (debug_pointer)
1602  emit fetab_insert_debugger_pointer (tab, line);
1603 
1604  if (breakpoint_marker)
1605  emit fetab_do_breakpoint_marker (insert, tab, line, cond);
1606  }
1607 
1608  if (show_dbg_file && ! ((breakpoint_marker || debug_pointer)
1609  && is_editor_console_tabbed ()))
1610  {
1611  emit fetab_set_focus (tab);
1612  activate ();
1613  }
1614  }
1615  else
1616  {
1617  if (! show_dbg_file && (breakpoint_marker || debug_pointer))
1618  return; // Do not open a file for showing dbg markers
1619 
1620  if (breakpoint_marker && ! insert)
1621  return; // Never open a file when removing breakpoints
1622 
1623  file_editor_tab *fileEditorTab = nullptr;
1624  // Reuse <unnamed> tab if it hasn't yet been modified.
1625  bool reusing = false;
1626  tab = find_tab_widget ("");
1627  if (tab)
1628  {
1629  fileEditorTab = tab;
1630  if (fileEditorTab->qsci_edit_area ()->isModified ())
1631  fileEditorTab = nullptr;
1632  else
1633  reusing = true;
1634  }
1635 
1636  // If <unnamed> was absent or modified, create a new tab.
1637  if (! fileEditorTab)
1638  fileEditorTab = make_file_editor_tab ();
1639 
1640  fileEditorTab->set_encoding (encoding);
1641  QString result = fileEditorTab->load_file (openFileName);
1642  if (result == "")
1643  {
1644  // Supply empty title then have the file_editor_tab update
1645  // with full or short name.
1646  if (! reusing)
1647  add_file_editor_tab (fileEditorTab, "", index);
1648  fileEditorTab->update_window_title (false);
1649  // file already loaded, add file to mru list here
1650  QFileInfo file_info = QFileInfo (openFileName);
1651  handle_mru_add_file (file_info.canonicalFilePath (),
1652  encoding);
1653 
1654  if (line > 0)
1655  {
1656  if (insert)
1657  emit fetab_goto_line (fileEditorTab, line);
1658 
1659  if (debug_pointer)
1660  emit fetab_insert_debugger_pointer (fileEditorTab,
1661  line);
1662  if (breakpoint_marker)
1663  emit fetab_do_breakpoint_marker (insert, fileEditorTab,
1664  line, cond);
1665  }
1666  }
1667  else
1668  {
1669  if (! reusing)
1670  {
1671  delete fileEditorTab;
1672  fileEditorTab = nullptr;
1673  }
1674 
1675  if (QFile::exists (openFileName))
1676  {
1677  // File not readable:
1678  // create a NonModal message about error.
1679  QMessageBox *msgBox
1680  = new QMessageBox (QMessageBox::Critical,
1681  tr ("Octave Editor"),
1682  tr ("Could not open file\n%1\nfor read: %2.").
1683  arg (openFileName).arg (result),
1684  QMessageBox::Ok, this);
1685 
1686  msgBox->setWindowModality (Qt::NonModal);
1687  msgBox->setAttribute (Qt::WA_DeleteOnClose);
1688  msgBox->show ();
1689  }
1690  else
1691  {
1692  // File does not exist, should it be created?
1693  bool create_file = true;
1694  QMessageBox *msgBox;
1695 
1696  if (! settings->value (ed_create_new_file).toBool ())
1697  {
1698  msgBox = new QMessageBox (QMessageBox::Question,
1699  tr ("Octave Editor"),
1700  tr ("File\n%1\ndoes not exist. "
1701  "Do you want to create it?").arg (openFileName),
1702  QMessageBox::NoButton, nullptr);
1703  QPushButton *create_button =
1704  msgBox->addButton (tr ("Create"), QMessageBox::YesRole);
1705  msgBox->addButton (tr ("Cancel"), QMessageBox::RejectRole);
1706  msgBox->setDefaultButton (create_button);
1707  msgBox->exec ();
1708 
1709  QAbstractButton *clicked_button = msgBox->clickedButton ();
1710  if (clicked_button != create_button)
1711  create_file = false;
1712 
1713  delete msgBox;
1714  }
1715 
1716  if (create_file)
1717  {
1718  // create the file and call the editor again
1719  QFile file (openFileName);
1720  if (! file.open (QIODevice::WriteOnly))
1721  {
1722  // error opening the file
1723  msgBox = new QMessageBox (QMessageBox::Critical,
1724  tr ("Octave Editor"),
1725  tr ("Could not open file\n%1\nfor write: %2.").
1726  arg (openFileName).arg (file.errorString ()),
1727  QMessageBox::Ok, this);
1728 
1729  msgBox->setWindowModality (Qt::NonModal);
1730  msgBox->setAttribute (Qt::WA_DeleteOnClose);
1731  msgBox->show ();
1732  }
1733  else
1734  {
1735  file.close ();
1736  request_open_file (openFileName);
1737  }
1738  }
1739  }
1740  }
1741 
1742  if (! bookmarks.isEmpty ())
1743  {
1744  // Restore bookmarks
1745  for (const auto& bms : bookmarks.split (','))
1746  {
1747  int bm = bms.toInt ();
1748  if (fileEditorTab)
1749  fileEditorTab->qsci_edit_area ()->markerAdd (bm, marker::bookmark);
1750  }
1751  }
1752 
1753  if (! ((breakpoint_marker || debug_pointer) && is_editor_console_tabbed ()))
1754  {
1755  // update breakpoint pointers, really show editor
1756  // and the current editor tab
1757  if (fileEditorTab)
1758  fileEditorTab->update_breakpoints ();
1759  activate ();
1760  emit file_loaded_signal ();
1761  }
1762  }
1763  }
1764 }
1765 
1767 {
1768  emit request_settings_dialog ("editor");
1769 }
1770 
1772 {
1773  emit request_settings_dialog ("editor_styles");
1774 }
1775 
1777 {
1779 }
1780 
1782 {
1784 }
1785 
1787 {
1789 }
1790 
1792 {
1794 }
1795 
1797 {
1799 }
1800 
1802 {
1804 }
1805 
1807 {
1809 }
1810 
1812 {
1814 }
1815 
1817 {
1818  emit fetab_zoom_in (m_tab_widget->currentWidget ());
1819 }
1820 
1822 {
1823  emit fetab_zoom_out (m_tab_widget->currentWidget ());
1824 }
1825 
1827 {
1828  emit fetab_zoom_normal (m_tab_widget->currentWidget ());
1829 }
1830 
1832 {
1833  // remove all standard actions from scintilla
1834  QList<QAction *> all_actions = menu->actions ();
1835 
1836  for (auto *a : all_actions)
1837  menu->removeAction (a);
1838 
1839  // add editor's actions with icons and customized shortcuts
1840  menu->addAction (m_cut_action);
1841  menu->addAction (m_copy_action);
1842  menu->addAction (m_paste_action);
1843  menu->addSeparator ();
1844  menu->addAction (m_selectall_action);
1845  menu->addSeparator ();
1846  menu->addAction (m_find_files_action);
1847  menu->addAction (m_find_action);
1848  menu->addAction (m_find_next_action);
1849  menu->addAction (m_find_previous_action);
1850  menu->addSeparator ();
1851  menu->addMenu (m_edit_cmd_menu);
1852  menu->addMenu (m_edit_fmt_menu);
1853  menu->addMenu (m_edit_nav_menu);
1854  menu->addSeparator ();
1855  menu->addAction (m_run_selection_action);
1856 }
1857 
1858 void file_editor::edit_status_update (bool undo, bool redo)
1859 {
1860  if (m_undo_action)
1861  m_undo_action->setEnabled (undo);
1862  m_redo_action->setEnabled (redo);
1863 }
1864 
1865 // handler for the close event
1866 void file_editor::closeEvent (QCloseEvent *e)
1867 {
1869  gui_settings *settings = rmgr.get_settings ();
1870  if (settings->value (ed_hiding_closes_files).toBool ())
1871  {
1872  if (check_closing ())
1873  {
1874  // All tabs are closed without cancelling,
1875  // store closing state for restoring session when shown again.
1876  // Editor is closing when session data is stored in preferences
1877  m_closed = true;
1878  e->ignore ();
1879  }
1880  else
1881  {
1882  e->ignore ();
1883  return;
1884  }
1885  }
1886  else
1887  e->accept ();
1888 
1890 }
1891 
1892 void file_editor::dragEnterEvent (QDragEnterEvent *e)
1893 {
1894  if (e->mimeData ()->hasUrls ())
1895  {
1896  e->acceptProposedAction ();
1897  }
1898 }
1899 
1900 void file_editor::dropEvent (QDropEvent *e)
1901 {
1902  if (e->mimeData ()->hasUrls ())
1903  {
1904  for (const auto& url : e->mimeData ()->urls ())
1905  request_open_file (url.toLocalFile ());
1906  }
1907 }
1908 
1910 {
1911  // FIXME: is there a way to do this job that doesn't require casting
1912  // the parent to a main_window object?
1913 
1914  main_window *w = dynamic_cast<main_window *> (parentWidget ());
1915 
1916  if (w)
1917  {
1918  QList<QDockWidget *> w_list = w->tabifiedDockWidgets (this);
1919  QDockWidget *console =
1920  static_cast<QDockWidget *> (w->get_dock_widget_list ().at (0));
1921 
1922  for (int i = 0; i < w_list.count (); i++)
1923  {
1924  if (w_list.at (i) == console)
1925  return true;
1926  }
1927  }
1928 
1929  return false;
1930 }
1931 
1933 {
1934  QWidget *editor_widget = new QWidget (this);
1935 
1936  // FIXME: what was the intended purpose of this unused variable?
1937  // QStyle *editor_style = QApplication::style ();
1938 
1939  // Menu bar: do not set it native, required in macOS and Ubuntu Unity (Qt5)
1940  // for a visible menu bar in the editor widget. This property is ignored
1941  // on other platforms.
1942  m_menu_bar = new QMenuBar (editor_widget);
1943  m_menu_bar->setNativeMenuBar (false);
1944 
1945  m_tool_bar = new QToolBar (editor_widget);
1946  m_tool_bar->setMovable (true);
1947 
1948  m_tab_widget = new file_editor_tab_widget (editor_widget, this);
1949 
1951 
1952  // the mru-list and an empty array of actions
1953  gui_settings *settings = rmgr.get_settings ();
1954  m_mru_files = settings->value (ed_mru_file_list).toStringList ();
1956  .toStringList ();
1957 
1958  if (m_mru_files_encodings.count () != m_mru_files.count ())
1959  {
1960  // encodings don't have the same count -> do not use them!
1961  m_mru_files_encodings = QStringList ();
1962  for (int i = 0; i < m_mru_files.count (); i++)
1963  m_mru_files_encodings << QString ();
1964  }
1965 
1966  for (int i = 0; i < MaxMRUFiles; ++i)
1967  {
1968  m_mru_file_actions[i] = new QAction (this);
1969  m_mru_file_actions[i]->setVisible (false);
1970  }
1971 
1972  // menu bar
1973 
1974  // file menu
1975 
1976  m_fileMenu = add_menu (m_menu_bar, tr ("&File"));
1977 
1978  // new and open menus are inserted later by the main window
1979  m_mru_file_menu = new QMenu (tr ("&Recent Editor Files"), m_fileMenu);
1980  for (int i = 0; i < MaxMRUFiles; ++i)
1981  m_mru_file_menu->addAction (m_mru_file_actions[i]);
1982  m_fileMenu->addMenu (m_mru_file_menu);
1983 
1984  m_fileMenu->addSeparator ();
1985 
1988  tr ("&Edit Function"),
1989  SLOT (request_context_edit (bool)));
1990 
1991  m_fileMenu->addSeparator ();
1992 
1994  = add_action (m_fileMenu, rmgr.icon ("document-save"),
1995  tr ("&Save File"), SLOT (request_save_file (bool)));
1996 
1998  = add_action (m_fileMenu, rmgr.icon ("document-save-as"),
1999  tr ("Save File &As..."),
2000  SLOT (request_save_file_as (bool)));
2001 
2002  m_fileMenu->addSeparator ();
2003 
2005  = add_action (m_fileMenu, rmgr.icon ("window-close", false),
2006  tr ("&Close"), SLOT (request_close_file (bool)));
2007 
2009  = add_action (m_fileMenu, rmgr.icon ("window-close", false),
2010  tr ("Close All"), SLOT (request_close_all_files (bool)));
2011 
2013  = add_action (m_fileMenu, rmgr.icon ("window-close", false),
2014  tr ("Close Other Files"),
2015  SLOT (request_close_other_files (bool)));
2016 
2017  m_fileMenu->addSeparator ();
2018 
2020  = add_action (m_fileMenu, rmgr.icon ("document-print"),
2021  tr ("Print..."), SLOT (request_print_file (bool)));
2022 
2023  // edit menu (undo, copy, paste and select all later via main window)
2024 
2025  m_edit_menu = add_menu (m_menu_bar, tr ("&Edit"));
2026 
2028  = add_action (m_edit_menu, rmgr.icon ("edit-redo"),
2029  tr ("&Redo"), SLOT (request_redo (bool)));
2030  m_redo_action->setEnabled (false);
2031 
2032  m_edit_menu->addSeparator ();
2033 
2034  m_cut_action
2035  = add_action (m_edit_menu, rmgr.icon ("edit-cut"),
2036  tr ("Cu&t"), SLOT (request_cut (bool)));
2037  m_cut_action->setEnabled (false);
2038 
2040  = add_action (m_edit_menu, rmgr.icon ("edit-find-replace"),
2041  tr ("&Find and Replace..."), SLOT (request_find (bool)));
2042 
2044  = add_action (m_edit_menu, tr ("Find &Next..."),
2045  SLOT (request_find_next (bool)));
2046 
2048  = add_action (m_edit_menu, tr ("Find &Previous..."),
2049  SLOT (request_find_previous (bool)));
2050 
2051  m_edit_menu->addSeparator ();
2052 
2053  m_edit_cmd_menu = m_edit_menu->addMenu (tr ("&Commands"));
2054 
2056  = add_action (m_edit_cmd_menu, tr ("Delete Line"),
2057  SLOT (request_delete_line (bool)));
2058 
2060  = add_action (m_edit_cmd_menu, tr ("Copy Line"),
2061  SLOT (request_copy_line (bool)));
2062 
2064  = add_action (m_edit_cmd_menu, tr ("Cut Line"),
2065  SLOT (request_cut_line (bool)));
2066 
2067  m_edit_cmd_menu->addSeparator ();
2068 
2070  = add_action (m_edit_cmd_menu, tr ("Delete to Start of Word"),
2071  SLOT (request_delete_start_word (bool)));
2072 
2074  = add_action (m_edit_cmd_menu, tr ("Delete to End of Word"),
2075  SLOT (request_delete_end_word (bool)));
2076 
2078  = add_action (m_edit_cmd_menu, tr ("Delete to Start of Line"),
2079  SLOT (request_delete_start_line (bool)));
2080 
2082  = add_action (m_edit_cmd_menu, tr ("Delete to End of Line"),
2083  SLOT (request_delete_end_line (bool)));
2084 
2085  m_edit_cmd_menu->addSeparator ();
2086 
2088  = add_action (m_edit_cmd_menu, tr ("Duplicate Selection/Line"),
2089  SLOT (request_duplicate_selection (bool)));
2090 
2092  = add_action (m_edit_cmd_menu, tr ("Transpose Line"),
2093  SLOT (request_transpose_line (bool)));
2094 
2095  m_edit_cmd_menu->addSeparator ();
2096 
2098  = add_action (m_edit_cmd_menu, tr ("&Show Completion List"),
2099  SLOT (request_completion (bool)));
2100 
2101  m_edit_fmt_menu = m_edit_menu->addMenu (tr ("&Format"));
2102 
2104  = add_action (m_edit_fmt_menu, tr ("&Uppercase Selection"),
2105  SLOT (request_upper_case (bool)));
2106 
2108  = add_action (m_edit_fmt_menu, tr ("&Lowercase Selection"),
2109  SLOT (request_lower_case (bool)));
2110 
2111  m_edit_fmt_menu->addSeparator ();
2112 
2114  = add_action (m_edit_fmt_menu, tr ("&Comment"),
2115  SLOT (request_comment_selected_text (bool)));
2116 
2118  = add_action (m_edit_fmt_menu, tr ("&Uncomment"),
2119  SLOT (request_uncomment_selected_text (bool)));
2120 
2122  = add_action (m_edit_fmt_menu, tr ("Comment (Choosing String)"),
2123  SLOT (request_comment_var_selected_text (bool)));
2124 
2125  m_edit_fmt_menu->addSeparator ();
2126 
2128  = add_action (m_edit_fmt_menu, tr ("&Indent Selection Rigidly"),
2129  SLOT (request_indent_selected_text (bool)));
2130 
2132  = add_action (m_edit_fmt_menu, tr ("&Unindent Selection Rigidly"),
2133  SLOT (request_unindent_selected_text (bool)));
2134 
2136  = add_action (m_edit_fmt_menu, tr ("Indent Code"),
2138 
2139  m_edit_fmt_menu->addSeparator ();
2140 
2143  tr ("Convert Line Endings to &Windows (CRLF)"),
2144  SLOT (request_conv_eol_windows (bool)));
2145 
2147  = add_action (m_edit_fmt_menu, tr ("Convert Line Endings to &Unix (LF)"),
2148  SLOT (request_conv_eol_unix (bool)));
2149 
2152  tr ("Convert Line Endings to Legacy &Mac (CR)"),
2153  SLOT (request_conv_eol_mac (bool)));
2154 
2155  m_edit_nav_menu = m_edit_menu->addMenu (tr ("Navi&gation"));
2156 
2158  = add_action (m_edit_nav_menu, tr ("Go &to Line..."),
2159  SLOT (request_goto_line (bool)));
2160 
2161  m_edit_cmd_menu->addSeparator ();
2162 
2164  = add_action (m_edit_nav_menu, tr ("Move to Matching Brace"),
2165  SLOT (request_move_match_brace (bool)));
2166 
2168  = add_action (m_edit_nav_menu, tr ("Select to Matching Brace"),
2169  SLOT (request_sel_match_brace (bool)));
2170 
2171  m_edit_nav_menu->addSeparator ();
2172 
2174  = add_action (m_edit_nav_menu, tr ("&Next Bookmark"),
2175  SLOT (request_next_bookmark (bool)));
2176 
2178  = add_action (m_edit_nav_menu, tr ("Pre&vious Bookmark"),
2179  SLOT (request_previous_bookmark (bool)));
2180 
2182  = add_action (m_edit_nav_menu, tr ("Toggle &Bookmark"),
2183  SLOT (request_toggle_bookmark (bool)));
2184 
2186  = add_action (m_edit_nav_menu, tr ("&Remove All Bookmarks"),
2187  SLOT (request_remove_bookmark (bool)));
2188 
2189  m_edit_menu->addSeparator ();
2190 
2192  = add_action (m_edit_menu, rmgr.icon ("preferences-system"),
2193  tr ("&Preferences..."),
2194  SLOT (request_preferences (bool)));
2195 
2197  = add_action (m_edit_menu, rmgr.icon ("preferences-system"),
2198  tr ("&Styles Preferences..."),
2199  SLOT (request_styles_preferences (bool)));
2200 
2201  // view menu
2202 
2203  QMenu *view_menu = add_menu (m_menu_bar, tr ("&View"));
2204 
2205  m_view_editor_menu = view_menu->addMenu (tr ("&Editor"));
2206 
2208  = add_action (m_view_editor_menu, tr ("Show &Line Numbers"),
2209  SLOT (show_line_numbers (bool)));
2210  m_show_linenum_action->setCheckable (true);
2211 
2213  = add_action (m_view_editor_menu, tr ("Show &Whitespace Characters"),
2214  SLOT (show_white_space (bool)));
2215  m_show_whitespace_action->setCheckable (true);
2216 
2218  = add_action (m_view_editor_menu, tr ("Show Line &Endings"),
2219  SLOT (show_eol_chars (bool)));
2220  m_show_eol_action->setCheckable (true);
2221 
2223  = add_action (m_view_editor_menu, tr ("Show &Indentation Guides"),
2224  SLOT (show_indent_guides (bool)));
2225  m_show_indguide_action->setCheckable (true);
2226 
2228  = add_action (m_view_editor_menu, tr ("Show Long Line &Marker"),
2229  SLOT (show_long_line (bool)));
2230  m_show_longline_action->setCheckable (true);
2231 
2232  m_view_editor_menu->addSeparator ();
2233 
2235  = add_action (m_view_editor_menu, tr ("Show &Toolbar"),
2236  SLOT (show_toolbar (bool)));
2237  m_show_toolbar_action->setCheckable (true);
2238 
2240  = add_action (m_view_editor_menu, tr ("Show &Statusbar"),
2241  SLOT (show_statusbar (bool)));
2242  m_show_statusbar_action->setCheckable (true);
2243 
2245  = add_action (m_view_editor_menu, tr ("Show &Horizontal Scrollbar"),
2246  SLOT (show_hscrollbar (bool)));
2247  m_show_hscrollbar_action->setCheckable (true);
2248 
2249  view_menu->addSeparator ();
2250 
2252  = add_action (view_menu, rmgr.icon ("view-zoom-in"), tr ("Zoom &In"),
2253  SLOT (zoom_in (bool)));
2254 
2256  = add_action (view_menu, rmgr.icon ("view-zoom-out"), tr ("Zoom &Out"),
2257  SLOT (zoom_out (bool)));
2258 
2260  = add_action (view_menu, rmgr.icon ("view-zoom-original"), tr ("&Normal Size"),
2261  SLOT (zoom_normal (bool)));
2262 
2263  view_menu->addSeparator ();
2264 
2266  = add_action (view_menu, tr ("&Sort Tabs Alphabetically"),
2267  SLOT (sort_tabs_alph (void)),
2269 
2270  m_menu_bar->addMenu (view_menu);
2271 
2272  // debug menu
2273 
2274  m_debug_menu = add_menu (m_menu_bar, tr ("&Debug"));
2275 
2277  = add_action (m_debug_menu, rmgr.icon ("bp-toggle"),
2278  tr ("Toggle &Breakpoint"),
2279  SLOT (request_toggle_breakpoint (bool)));
2280 
2282  = add_action (m_debug_menu, rmgr.icon ("bp-next"),
2283  tr ("&Next Breakpoint"),
2284  SLOT (request_next_breakpoint (bool)));
2285 
2287  = add_action (m_debug_menu, rmgr.icon ("bp-prev"),
2288  tr ("Pre&vious Breakpoint"),
2289  SLOT (request_previous_breakpoint (bool)));
2290 
2292  = add_action (m_debug_menu, rmgr.icon ("bp-rm-all"),
2293  tr ("&Remove All Breakpoints"),
2294  SLOT (request_remove_breakpoint (bool)));
2295 
2296  m_debug_menu->addSeparator ();
2297 
2298  // The other debug actions will be added by the main window.
2299 
2300  // run menu
2301 
2302  QMenu *_run_menu = add_menu (m_menu_bar, tr ("&Run"));
2303 
2304  m_run_action
2305  = add_action (_run_menu,
2306  rmgr.icon ("system-run"),
2307  tr ("Save File and Run / Continue"),
2308  SLOT (request_run_file (bool)));
2309 
2311  = add_action (_run_menu,
2312  tr ("Run &Selection"),
2313  SLOT (request_context_run (bool)));
2314  m_run_selection_action->setEnabled (false);
2315 
2316  // help menu
2317 
2318  QMenu *_help_menu = add_menu (m_menu_bar, tr ("&Help"));
2319 
2321  = add_action (_help_menu,
2322  tr ("&Help on Keyword"),
2323  SLOT (request_context_help (bool)));
2324 
2326  = add_action (_help_menu,
2327  tr ("&Documentation on Keyword"),
2328  SLOT (request_context_doc (bool)));
2329 
2330  // tab navigation (no menu, only actions; slots in tab_bar)
2331 
2333  = add_action (nullptr, "", SLOT (switch_left_tab (void)),
2335 
2337  = add_action (nullptr, "", SLOT (switch_right_tab (void)),
2339 
2341  = add_action (nullptr, "", SLOT (move_tab_left (void)),
2343 
2345  = add_action (nullptr, "", SLOT (move_tab_right (void)),
2347 
2348  // toolbar
2349 
2350  // popdown menu with mru files
2351  QToolButton *popdown_button = new QToolButton ();
2352  popdown_button->setToolTip (tr ("Recent Files"));
2353  popdown_button->setMenu (m_mru_file_menu);
2354  popdown_button->setPopupMode (QToolButton::InstantPopup);
2355  popdown_button->setArrowType (Qt::DownArrow);
2356  popdown_button->setToolButtonStyle (Qt::ToolButtonTextOnly);
2357 
2358  // new and open actions are inserted later from main window
2359  m_popdown_mru_action = m_tool_bar->addWidget (popdown_button);
2360  m_tool_bar->addAction (m_save_action);
2361  m_tool_bar->addAction (m_save_as_action);
2362  m_tool_bar->addAction (m_print_action);
2363  m_tool_bar->addSeparator ();
2364  // m_undo_action: later via main window
2365  m_tool_bar->addAction (m_redo_action);
2366  m_tool_bar->addSeparator ();
2367  m_tool_bar->addAction (m_cut_action);
2368  // m_copy_action: later via the main window
2369  // m_paste_action: later via the main window
2370  m_tool_bar->addAction (m_find_action);
2371  //m_tool_bar->addAction (m_find_next_action);
2372  //m_tool_bar->addAction (m_find_previous_action);
2373  m_tool_bar->addSeparator ();
2374  m_tool_bar->addAction (m_run_action);
2375  m_tool_bar->addSeparator ();
2378  m_tool_bar->addAction (m_next_breakpoint_action);
2380 
2381  // layout
2382  QVBoxLayout *vbox_layout = new QVBoxLayout ();
2383  vbox_layout->addWidget (m_menu_bar);
2384  vbox_layout->addWidget (m_tool_bar);
2385  vbox_layout->addWidget (m_tab_widget);
2386  vbox_layout->setMargin (0);
2387  vbox_layout->setSpacing (0);
2388  editor_widget->setLayout (vbox_layout);
2389  setWidget (editor_widget);
2390 
2391  // Create the basic context menu of the tab bar with editor actions.
2392  // Actions for selecting an tab are added when the menu is activated.
2393  tab_bar *bar = m_tab_widget->get_tab_bar ();
2394  QMenu *ctx_men = bar->get_context_menu ();
2395  ctx_men->addSeparator ();
2396  ctx_men->addAction (m_close_action);
2397  ctx_men->addAction (m_close_all_action);
2398  ctx_men->addAction (m_close_others_action);
2399  ctx_men->addSeparator ();
2400  ctx_men->addAction (m_sort_tabs_action);
2401  add_action (ctx_men, tr ("Copy Full File &Path"),
2402  SLOT (copy_full_file_path (bool)), this);
2403 
2404  // signals
2405  connect (m_mru_file_menu, &QMenu::triggered,
2407 
2408  mru_menu_update ();
2409 
2410  connect (m_tab_widget, &file_editor_tab_widget::tabCloseRequested,
2412 
2413  connect (m_tab_widget, &file_editor_tab_widget::currentChanged,
2415 
2416  resize (500, 400);
2417  set_title (tr ("Editor"));
2418 
2419  check_actions ();
2420 }
2421 
2422 // Slot when autocompletion list was cancelled
2424 {
2425  // List was cancelled but somehow still active and blocking the
2426  // edit area from accepting shortcuts. Only after another keypress
2427  // shortcuts and lists are working againnas expected. This is
2428  // probably caused by qt bug https://bugreports.qt.io/browse/QTBUG-83720
2429  // Hack: Accept the list, which is hidden but still active
2430  // and undo the text insertion, if any
2431 
2433  octave_qscintilla *qsci = f->qsci_edit_area ();
2434 
2435  int line, col;
2436  qsci->getCursorPosition (&line, &col);
2437  int l1 = qsci->lineLength (line); // Current line length
2438 
2439  // Accept autocompletion
2440  qsci->SendScintilla (QsciScintillaBase::SCI_AUTOCCOMPLETE);
2441 
2442  // Was text inserted? If yes, undo
2443  if (qsci->text (line).length () - l1)
2444  qsci->undo ();
2445 }
2446 
2448 {
2449  // Reset the focus of the tab and the related edit area
2451  = static_cast<file_editor_tab *> (m_tab_widget->currentWidget ());
2452  emit fetab_set_focus (f);
2453  return f;
2454 }
2455 
2457 file_editor::make_file_editor_tab (const QString& directory)
2458 {
2459  file_editor_tab *f = new file_editor_tab (m_octave_qobj, directory);
2460 
2461  // signals from the qscintilla edit area
2462  connect (f->qsci_edit_area (), &octave_qscintilla::status_update,
2464 
2465  connect (f->qsci_edit_area (), &octave_qscintilla::create_context_menu_signal,
2467 
2468  connect (f->qsci_edit_area (),
2469  SIGNAL (SCN_AUTOCCOMPLETED (const char *, int, int, int)),
2470  this, SLOT (reset_focus (void)));
2471 
2472  connect (f->qsci_edit_area (), SIGNAL (SCN_AUTOCCANCELLED (void)),
2473  this, SLOT (handle_autoc_cancelled (void)));
2474 
2475  // signals from the qscintilla edit area
2476  connect (this, &file_editor::enter_debug_mode_signal,
2477  f->qsci_edit_area (), &octave_qscintilla::handle_enter_debug_mode);
2478 
2479  connect (this, &file_editor::exit_debug_mode_signal,
2480  f->qsci_edit_area (), &octave_qscintilla::handle_exit_debug_mode);
2481 
2482  // Signals from the file editor_tab
2483  connect (f, &file_editor_tab::autoc_closed,
2484  this, &file_editor::reset_focus);
2485 
2488 
2491 
2494 
2497 
2498  connect (f, &file_editor_tab::mru_add_file,
2500 
2502  this, [=] (const QString& fname, const QString& encoding) { request_open_file (fname, encoding); });
2503 
2506 
2508  this, &file_editor::set_focus);
2509 
2510  // Signals from the file_editor or main-win non-trivial operations
2511  connect (this, &file_editor::fetab_settings_changed,
2512  f, [=] (const gui_settings *settings) { f->notice_settings (settings); });
2513 
2514  connect (this, &file_editor::fetab_change_request,
2516 
2519 
2520  // Signals from the file_editor trivial operations
2521  connect (this, &file_editor::fetab_recover_from_exit,
2523 
2524  connect (this, &file_editor::fetab_set_directory,
2526 
2527  connect (this, &file_editor::fetab_zoom_in,
2529  connect (this, &file_editor::fetab_zoom_out,
2531  connect (this, &file_editor::fetab_zoom_normal,
2533 
2534  connect (this, &file_editor::fetab_context_help,
2536 
2537  connect (this, &file_editor::fetab_context_edit,
2539 
2542 
2543  connect (this, &file_editor::fetab_save_file_as,
2545 
2546  connect (this, &file_editor::fetab_print_file,
2548 
2549  connect (this, &file_editor::fetab_run_file,
2551 
2552  connect (this, &file_editor::fetab_context_run,
2554 
2555  connect (this, &file_editor::fetab_toggle_bookmark,
2557 
2558  connect (this, &file_editor::fetab_next_bookmark,
2560 
2561  connect (this, &file_editor::fetab_previous_bookmark,
2563 
2564  connect (this, &file_editor::fetab_remove_bookmark,
2566 
2567  connect (this, &file_editor::fetab_toggle_breakpoint,
2569 
2570  connect (this, &file_editor::fetab_next_breakpoint,
2572 
2575 
2578 
2579  connect (this, &file_editor::fetab_scintilla_command,
2581 
2584 
2587 
2590 
2593 
2596 
2597  connect (this, &file_editor::fetab_convert_eol,
2599 
2600  connect (this, &file_editor::fetab_goto_line,
2602 
2603  connect (this, &file_editor::fetab_move_match_brace,
2605 
2606  connect (this, &file_editor::fetab_completion,
2608 
2609  connect (this, &file_editor::fetab_set_focus,
2611 
2614 
2617 
2620 
2621  connect (this, &file_editor::update_gui_lexer_signal,
2623 
2624  // Convert other signals from the edit area and tab to editor signals.
2625 
2626  connect (f->qsci_edit_area (), &octave_qscintilla::execute_command_in_terminal_signal,
2628 
2629  connect (f->qsci_edit_area (), &octave_qscintilla::focus_console_after_command_signal,
2631 
2634 
2637 
2640 
2641  // Any interpreter_event signal from a file_editor_tab_widget is
2642  // handled the same as for the parent main_window object.
2643 
2646 
2649 
2650  return f;
2651 }
2652 
2654  int index)
2655 {
2656  if (index == -1)
2657  m_tab_widget->addTab (f, fn);
2658  else
2659  m_tab_widget->insertTab (index, f, fn);
2660 
2661  m_tab_widget->setCurrentWidget (f);
2662 
2663  check_actions ();
2664 }
2665 
2667 {
2668  int num_files = qMin (m_mru_files.size (), int (MaxMRUFiles));
2669 
2670  // configure and show active actions of mru-menu
2671  for (int i = 0; i < num_files; ++i)
2672  {
2673  QString text = QString ("&%1 %2").
2674  arg ((i+1) % int (MaxMRUFiles)).arg (m_mru_files.at (i));
2675  m_mru_file_actions[i]->setText (text);
2676 
2677  QStringList action_data;
2678  action_data << m_mru_files.at (i) << m_mru_files_encodings.at (i);
2679  m_mru_file_actions[i]->setData (action_data);
2680 
2681  m_mru_file_actions[i]->setVisible (true);
2682  }
2683 
2684  // hide unused mru-menu entries
2685  for (int j = num_files; j < MaxMRUFiles; ++j)
2686  m_mru_file_actions[j]->setVisible (false);
2687 
2688  // delete entries in string-list beyond MaxMRUFiles
2689  while (m_mru_files.size () > MaxMRUFiles)
2690  {
2691  m_mru_files.removeLast ();
2692  m_mru_files_encodings.removeLast ();
2693  }
2694 
2695  // save actual mru-list in settings
2697  gui_settings *settings = rmgr.get_settings ();
2698 
2701  settings->sync ();
2702 }
2703 
2704 bool file_editor::call_custom_editor (const QString& file_name, int line)
2705 {
2706  // Check if the user wants to use a custom file editor.
2708  gui_settings *settings = rmgr.get_settings ();
2709 
2711  global_use_custom_editor.def).toBool ())
2712  {
2713  // use the external editor interface for handling the call
2714  emit request_open_file_external (file_name, line);
2715 
2716  if (line < 0 && ! file_name.isEmpty ())
2717  handle_mru_add_file (QFileInfo (file_name).canonicalFilePath (),
2718  QString ());
2719 
2720  return true;
2721  }
2722 
2723  return false;
2724 }
2725 
2727 {
2729  gui_settings *settings = rmgr.get_settings ();
2730 
2731  bool old = settings->value (preference).toBool ();
2732  settings->setValue (preference.key, ! old);
2734 }
2735 
2736 // Function for closing the files in a removed directory
2737 void file_editor::handle_dir_remove (const QString& old_name,
2738  const QString& new_name)
2739 {
2740  QDir old_dir (old_name);
2741  removed_file_data f_data;
2742 
2743  std::list<file_editor_tab *> editor_tab_lst = m_tab_widget->tab_list ();
2744 
2745  for (auto editor_tab : editor_tab_lst)
2746  {
2747  QString file_name = editor_tab->file_name ();
2748 
2749  if (file_name.isEmpty ())
2750  continue; // Nothing to do, no valid file name
2751 
2752  // Get abs. file path and its path relative to the removed directory
2753  QString rel_path_to_file = old_dir.relativeFilePath (file_name);
2754  QString abs_path_to_file = old_dir.absoluteFilePath (file_name);
2755 
2756  // Test whether the file is located within the directory that will
2757  // be removed. For this, two conditions must be met:
2758  // 1. The path of the file rel. to the dir is not equal to the
2759  // its absolute one.
2760  // If both are equal, then there is no relative path and removed
2761  // directory and file are on different drives (e.g. on windows)
2762  // 2. The (real) relative path does not start with "../", i.e.,
2763  // the file can be reached from the directory by descending only
2764  if ((rel_path_to_file != abs_path_to_file)
2765  && (rel_path_to_file.left (3) != QString ("../")))
2766  {
2767  // The currently considered file is included in the
2768  // removed/renamed diectory: remeber it
2769  if (editor_tab)
2770  {
2771  editor_tab->enable_file_watcher (false);
2772  f_data.editor_tab = editor_tab;
2773 
2774  // Add the new file path and the encoding for later reloading
2775  // if new_name is given
2776  if (! new_name.isEmpty ())
2777  {
2778  QDir new_dir (new_name);
2779  QString append_to_new_dir;
2780  if (new_dir.exists ())
2781  {
2782  // The new directory already exists (movefile was used).
2783  // This means, we have to add the name (not the path)
2784  // of the old dir and the relative path to the file
2785  // to new dir.
2786  append_to_new_dir
2787  = old_dir.dirName () + "/" + rel_path_to_file;
2788  }
2789  else
2790  append_to_new_dir = rel_path_to_file;
2791 
2792  f_data.new_file_name
2793  = new_dir.absoluteFilePath (append_to_new_dir);
2794  }
2795  else
2796  f_data.new_file_name = ""; // no new name, just removing this file
2797 
2798  // Store data in list for later reloading
2799  m_tmp_closed_files << f_data;
2800  }
2801  }
2802  }
2803 }
2804 
2806 {
2807  QWidget *foc_w = focusWidget ();
2808  if (foc_w && foc_w->inherits ("octave::octave_qscintilla"))
2809  return true;
2810  return false;
2811 }
2812 
2813 // Check whether this file is already open in the editor.
2815 {
2816  std::string std_file = file.toStdString ();
2817 
2818  std::list<file_editor_tab *> fe_tab_lst = m_tab_widget->tab_list ();
2819 
2820  for (auto fe_tab : fe_tab_lst)
2821  {
2822  QString tab_file = fe_tab->file_name ();
2823 
2824  // We check file == tab_file because
2825  //
2826  // same_file ("", "")
2827  //
2828  // is false
2829 
2830  if (same_file (std_file, tab_file.toStdString ()) || file == tab_file)
2831  return fe_tab;
2832  }
2833 
2834  return nullptr;
2835 }
2836 
2837 QAction * file_editor::add_action (QMenu *menu, const QString& text,
2838  const char *member,
2839  QWidget *receiver)
2840 {
2841  return add_action (menu, QIcon (), text, member, receiver);
2842 }
2843 
2844 QAction * file_editor::add_action (QMenu *menu, const QIcon& icon,
2845  const QString& text, const char *member,
2846  QWidget *receiver)
2847 {
2848  QAction *a;
2849  QWidget *r = this;
2850 
2851  if (receiver != nullptr)
2852  r = receiver;
2853 
2854  if (menu)
2855  a = menu->addAction (icon, text, r, member);
2856  else
2857  {
2858  a = new QAction (this);
2859  connect (a, SIGNAL (triggered ()), r, member);
2860  }
2861 
2862  addAction (a); // important for shortcut context
2863  a->setShortcutContext (Qt::WidgetWithChildrenShortcut);
2864 
2865  return a;
2866 }
2867 
2869 {
2870  QMenu *menu = p->addMenu (name);
2871 
2872  QString base_name = name; // get a copy
2873  // replace intended '&' ("&&") by a temp. string
2874  base_name.replace ("&&", "___octave_amp_replacement___");
2875  // remove single '&' (shortcut)
2876  base_name.remove ("&");
2877  // restore intended '&'
2878  base_name.replace ("___octave_amp_replacement___", "&&");
2879 
2880  // remember names with and without shortcut
2881  m_hash_menu_text[menu] = QStringList () << name << base_name;
2882 
2883  return menu;
2884 }
2885 
2887 
2888 #endif
OCTAVE_END_NAMESPACE(octave)
Base class for Octave interfaces that use Qt.
resource_manager & get_resource_manager(void)
shortcut_manager & get_shortcut_manager(void)
void interpreter_event(const fcn_callback &fcn)
std::list< file_editor_tab * > tab_list(void) const
Definition: file-editor.cc:91
tab_bar * get_tab_bar(void) const
Definition: file-editor.cc:85
void next_breakpoint(const QWidget *ID)
void smart_indent_line_or_selected_text(const QWidget *ID)
void run_file_signal(const QFileInfo &info)
void move_match_brace(const QWidget *ID, bool select)
void previous_breakpoint(const QWidget *ID)
void save_file_as(const QWidget *ID)
void set_focus(const QWidget *ID)
void set_focus_editor_signal(QWidget *)
void run_file(const QWidget *ID, bool step_into=false)
void unindent_selected_text(const QWidget *ID)
void comment_selected_text(const QWidget *ID, bool input_str)
void do_breakpoint_marker(bool insert, const QWidget *ID, int line=-1, const QString &cond="")
QString load_file(const QString &fileName)
void indent_selected_text(const QWidget *ID)
void context_run(const QWidget *ID)
void next_bookmark(const QWidget *ID)
void debug_quit_signal(void)
void convert_eol(const QWidget *ID, QsciScintilla::EolMode)
void interpreter_event(const fcn_callback &fcn)
void recover_from_exit(void)
void new_file(const QString &commands=QString())
void tab_remove_request(void)
void previous_bookmark(const QWidget *ID)
void remove_bookmark(const QWidget *ID)
void enable_file_watcher(bool do_enable)
void editor_check_conflict_save(const QString &saveFileName, bool remove_on_success)
bool conditional_close(void)
void mru_add_file(const QString &file_name, const QString &encoding)
void remove_all_breakpoints(const QWidget *ID)
void save_file(const QWidget *ID)
void context_help(const QWidget *ID, bool)
void delete_debugger_pointer(const QWidget *ID, int line=-1)
void update_lexer_settings(bool update_apis_only=false)
void editor_state_changed(bool copy_available, bool is_octave_file, bool is_modified)
void set_current_directory(const QString &dir)
void set_encoding(const QString &new_encoding)
void zoom_in(const QWidget *ID)
void scintilla_command(const QWidget *, unsigned int)
void toggle_bookmark(const QWidget *ID)
void change_editor_state(const QWidget *ID)
void edit_mfile_request(const QString &, const QString &, const QString &, int)
QString file_name(void) const
void show_auto_completion(const QWidget *ID)
octave_qscintilla * qsci_edit_area(void)
void insert_debugger_pointer(const QWidget *ID, int line=-1)
void autoc_closed(void)
void request_open_file(const QString &, const QString &=QString())
void zoom_normal(const QWidget *ID)
void tab_ready_to_close(void)
void uncomment_selected_text(const QWidget *ID)
void print_file(const QWidget *ID)
void file_name_changed(const QString &fileName, const QString &toolTip, bool modified)
void context_edit(const QWidget *ID)
void goto_line(const QWidget *ID, int line=-1)
void toggle_breakpoint(const QWidget *ID)
void update_window_title(bool modified)
void edit_area_changed(octave_qscintilla *edit_area)
void zoom_out(const QWidget *ID)
QAction * m_find_next_action
Definition: file-editor.h:426
void request_new_file(const QString &commands)
Definition: file-editor.cc:568
void toplevel_change(bool toplevel)
void handle_insert_debugger_pointer_request(const QString &file, int line)
QMenu * m_edit_fmt_menu
Definition: file-editor.h:475
void handle_exit_debug_mode(void)
Definition: file-editor.cc:196
void request_remove_breakpoint(bool)
Definition: file-editor.cc:773
void fetab_smart_indent_line_or_selected_text(const QWidget *ID)
void request_preferences(bool)
QAction * m_cut_action
Definition: file-editor.h:397
void fetab_zoom_out(const QWidget *ID)
QAction * m_zoom_out_action
Definition: file-editor.h:412
void request_copy_line(bool)
Definition: file-editor.cc:809
QToolBar * m_tool_bar
Definition: file-editor.h:377
void fetab_toggle_breakpoint(const QWidget *ID)
void zoom_out(bool)
QAction * m_close_others_action
Definition: file-editor.h:449
QAction * m_zoom_normal_action
Definition: file-editor.h:413
bool m_copy_action_enabled
Definition: file-editor.h:468
void request_open_file_external(const QString &file_name, int line)
QAction * m_conv_eol_mac_action
Definition: file-editor.h:394
void do_undo(void)
QString m_ced
Definition: file-editor.h:374
QAction * m_context_help_action
Definition: file-editor.h:400
void fetab_remove_bookmark(const QWidget *ID)
void request_conv_eol_windows(bool)
Definition: file-editor.cc:876
QAction * m_show_statusbar_action
Definition: file-editor.h:409
QAction * m_redo_action
Definition: file-editor.h:451
void fetab_recover_from_exit(void)
QAction * m_unindent_selection_action
Definition: file-editor.h:390
void request_comment_selected_text(bool)
Definition: file-editor.cc:833
bool m_closing_canceled
Definition: file-editor.h:484
QAction * m_conv_eol_unix_action
Definition: file-editor.h:393
QAction * m_transpose_line_action
Definition: file-editor.h:423
void handle_tab_close_request(int index)
void fetab_context_edit(const QWidget *ID)
void request_smart_indent_line_or_selected_text(void)
Definition: file-editor.cc:871
QAction * m_comment_selection_action
Definition: file-editor.h:386
void request_close_other_files(bool)
Definition: file-editor.cc:604
void request_delete_end_word(bool)
Definition: file-editor.cc:785
QMenu * m_edit_cmd_menu
Definition: file-editor.h:474
void enable_menu_shortcuts(bool)
Definition: file-editor.cc:401
QAction * m_previous_breakpoint_action
Definition: file-editor.h:465
void request_find_next(bool)
Definition: file-editor.cc:961
bool call_custom_editor(const QString &file_name=QString(), int line=-1)
void request_delete_line(bool)
Definition: file-editor.cc:803
void handle_tab_remove_request(void)
QAction * m_popdown_mru_action
Definition: file-editor.h:444
void empty_script(bool startup, bool visible)
Definition: file-editor.cc:256
QAction * m_find_previous_action
Definition: file-editor.h:427
void request_close_file(bool)
Definition: file-editor.cc:585
QAction * m_close_all_action
Definition: file-editor.h:448
QAction * m_preferences_action
Definition: file-editor.h:454
void show_line_numbers(bool)
bool check_closing(void)
Definition: file-editor.cc:483
void fetab_next_bookmark(const QWidget *ID)
void construct(void)
QAction * m_close_action
Definition: file-editor.h:447
QMenu * m_view_editor_menu
Definition: file-editor.h:478
void fetab_comment_selected_text(const QWidget *ID, bool)
void request_context_help(bool)
Definition: file-editor.cc:657
void zoom_in(bool)
void request_toggle_breakpoint(bool)
Definition: file-editor.cc:758
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, const QString &bookmarks=QString())
void show_toolbar(bool)
void save_session(void)
Definition: file-editor.cc:440
QAction * m_move_tab_right_action
Definition: file-editor.h:460
void request_move_match_brace(bool)
Definition: file-editor.cc:747
file_editor(QWidget *p, base_qobject &oct_qobj)
Definition: file-editor.cc:101
QMenu * add_menu(QMenuBar *p, QString text)
void fetab_zoom_normal(const QWidget *ID)
void fetab_context_help(const QWidget *ID, bool)
void check_conflict_save(const QString &fileName, bool remove_on_success)
bool editor_tab_has_focus(void)
QAction * m_find_files_action
Definition: file-editor.h:428
void show_long_line(bool)
void selectAll(void)
QAction * m_show_whitespace_action
Definition: file-editor.h:404
QMenu * m_mru_file_menu
Definition: file-editor.h:490
void handle_file_name_changed(const QString &fileName, const QString &toolTip, bool modified)
Definition: file-editor.cc:983
void request_delete_start_line(bool)
Definition: file-editor.cc:791
void request_upper_case(bool)
Definition: file-editor.cc:849
void handle_mru_add_file(const QString &file_name, const QString &encoding)
QMenu * m_fileMenu
Definition: file-editor.h:477
QAction * m_completion_action
Definition: file-editor.h:430
QAction * add_action(QMenu *menu, const QString &text, const char *member, QWidget *receiver=nullptr)
void request_context_run(bool)
Definition: file-editor.cc:722
void fetab_zoom_in(const QWidget *ID)
QAction * m_conv_eol_windows_action
Definition: file-editor.h:392
bool m_is_octave_file
Definition: file-editor.h:470
void request_conv_eol_mac(bool)
Definition: file-editor.cc:888
void insert_global_actions(QList< QAction * >)
Definition: file-editor.cc:146
void show_white_space(bool)
QAction * m_goto_line_action
Definition: file-editor.h:429
QAction * m_toggle_bookmark_action
Definition: file-editor.h:436
QAction * m_show_eol_action
Definition: file-editor.h:405
void request_close_all_files(bool)
Definition: file-editor.cc:592
void add_file_editor_tab(file_editor_tab *f, const QString &fn, int index=-1)
void edit_status_update(bool, bool)
void closeEvent(QCloseEvent *event)
QHash< QMenu *, QStringList > m_hash_menu_text
Definition: file-editor.h:372
void fetab_previous_breakpoint(const QWidget *ID)
QAction * m_styles_preferences_action
Definition: file-editor.h:455
void handle_edit_file_request(const QString &file)
void request_redo(bool)
Definition: file-editor.cc:645
void fetab_goto_line(const QWidget *ID, int line=-1)
QMenu * m_debug_menu
Definition: file-editor.h:378
QAction * m_show_hscrollbar_action
Definition: file-editor.h:410
void handle_autoc_cancelled(void)
void copyClipboard(void)
void handle_editor_state_changed(bool enableCopy, bool is_octave_file, bool is_modified)
QAction * m_delete_line_action
Definition: file-editor.h:419
void handle_file_remove(const QString &, const QString &)
bool is_editor_console_tabbed(void)
void check_actions(void)
Definition: file-editor.cc:205
void pasteClipboard(void)
void request_save_file(bool)
Definition: file-editor.cc:672
QAction * m_delete_start_line_action
Definition: file-editor.h:417
QAction * m_find_action
Definition: file-editor.h:425
QAction * m_delete_end_word_action
Definition: file-editor.h:416
void request_next_breakpoint(bool)
Definition: file-editor.cc:763
void request_find_previous(bool)
Definition: file-editor.cc:967
void show_eol_chars(bool)
int m_number_of_tabs
Definition: file-editor.h:371
void focus_console_after_command_signal(void)
void find_create(void)
Definition: file-editor.cc:911
void request_next_bookmark(bool)
Definition: file-editor.cc:732
QAction * m_print_action
Definition: file-editor.h:439
void handle_tab_ready_to_close(void)
Definition: file-editor.cc:533
void handle_visibility(bool visible)
void request_context_edit(bool)
Definition: file-editor.cc:667
void fetab_set_directory(const QString &dir)
QAction * m_zoom_in_action
Definition: file-editor.h:411
void update_octave_directory(const QString &dir)
QAction * m_save_as_action
Definition: file-editor.h:446
void handle_delete_debugger_pointer_request(const QString &file, int line)
QAction * m_edit_function_action
Definition: file-editor.h:443
void dragEnterEvent(QDragEnterEvent *event)
QAction * m_toggle_breakpoint_action
Definition: file-editor.h:463
void fetab_save_file(const QWidget *ID, const QString &fileName, bool remove_on_success)
void edit_area_changed(octave_qscintilla *edit_area)
void request_conv_eol_unix(bool)
Definition: file-editor.cc:882
void zoom_normal(bool)
void activate(void)
Definition: file-editor.cc:379
void fetab_previous_bookmark(const QWidget *ID)
void fetab_next_breakpoint(const QWidget *ID)
QAction * m_run_action
Definition: file-editor.h:440
void fetab_run_file(const QWidget *ID, bool step_into=false)
QStringList m_mru_files_encodings
Definition: file-editor.h:493
void request_step_into_file()
Definition: file-editor.cc:717
void request_dbcont_signal(void)
QAction * m_remove_bookmark_action
Definition: file-editor.h:437
file_editor_tab * make_file_editor_tab(const QString &directory="")
QAction * m_context_doc_action
Definition: file-editor.h:401
void fetab_do_breakpoint_marker(bool insert, const QWidget *ID, int line=-1, const QString &="")
QAction * m_show_toolbar_action
Definition: file-editor.h:408
void toggle_preference(const gui_pref &preference)
QAction * m_next_breakpoint_action
Definition: file-editor.h:464
void request_run_file(bool)
Definition: file-editor.cc:682
void fetab_convert_eol(const QWidget *ID, QsciScintilla::EolMode eol_mode)
file_editor_tab_widget * m_tab_widget
Definition: file-editor.h:480
QAction * m_undo_action
Definition: file-editor.h:452
QAction * m_copy_action
Definition: file-editor.h:396
void notice_settings(const gui_settings *settings)
QMenu * m_edit_nav_menu
Definition: file-editor.h:476
void request_toggle_bookmark(bool)
Definition: file-editor.cc:727
QStringList m_mru_files
Definition: file-editor.h:492
void mru_menu_update(void)
QAction * m_cut_line_action
Definition: file-editor.h:421
void request_previous_bookmark(bool)
Definition: file-editor.cc:737
void update_gui_lexer_signal(bool)
void run_file_signal(const QFileInfo &)
void request_cut(bool)
Definition: file-editor.cc:651
void fetab_save_file_as(const QWidget *ID)
QAction * m_save_action
Definition: file-editor.h:445
void request_save_file_as(bool)
Definition: file-editor.cc:677
void show_hscrollbar(bool)
QAction * m_run_selection_action
Definition: file-editor.h:441
QAction * m_switch_left_tab_action
Definition: file-editor.h:457
void request_print_file(bool)
Definition: file-editor.cc:640
void request_indent_selected_text(bool)
Definition: file-editor.cc:861
QAction * m_move_tab_left_action
Definition: file-editor.h:459
void request_completion(bool)
Definition: file-editor.cc:978
void request_goto_line(bool)
Definition: file-editor.cc:973
void request_duplicate_selection(bool)
Definition: file-editor.cc:821
bool m_editor_ready
Definition: file-editor.h:487
bool m_current_tab_modified
Definition: file-editor.h:471
void fetab_uncomment_selected_text(const QWidget *ID)
QAction * m_switch_right_tab_action
Definition: file-editor.h:458
void fetab_change_request(const QWidget *ID)
void request_unindent_selected_text(bool)
Definition: file-editor.cc:866
void handle_file_renamed(bool load_new=true)
QAction * m_next_bookmark_action
Definition: file-editor.h:434
void request_delete_start_word(bool)
Definition: file-editor.cc:779
void exit_debug_mode_signal(void)
void request_uncomment_selected_text(bool)
Definition: file-editor.cc:838
QAction * m_comment_var_selection_action
Definition: file-editor.h:387
QAction * m_duplicate_selection_action
Definition: file-editor.h:422
void execute_command_in_terminal_signal(const QString &)
void request_transpose_line(bool)
Definition: file-editor.cc:827
QAction * m_sel_to_matching_brace
Definition: file-editor.h:433
QAction * m_indent_selection_action
Definition: file-editor.h:389
QAction * m_smart_indent_line_or_selection_action
Definition: file-editor.h:391
void fetab_print_file(const QWidget *ID)
void request_delete_end_line(bool)
Definition: file-editor.cc:797
QAction * m_show_indguide_action
Definition: file-editor.h:406
void request_context_doc(bool)
Definition: file-editor.cc:662
QList< removed_file_data > m_tmp_closed_files
Definition: file-editor.h:498
file_editor_tab * reset_focus(void)
QAction * m_show_longline_action
Definition: file-editor.h:407
void show_indent_guides(bool)
void fetab_settings_changed(const gui_settings *settings)
file_editor_tab * find_tab_widget(const QString &openFileName)
void fetab_scintilla_command(const QWidget *ID, unsigned int sci_msg)
QAction * m_sort_tabs_action
Definition: file-editor.h:461
@ NEW_FUNCTION_ACTION
Definition: file-editor.h:116
void request_lower_case(bool)
Definition: file-editor.cc:855
void request_find(bool)
Definition: file-editor.cc:895
void edit_mfile_request(const QString &, const QString &, const QString &, int)
QAction * m_upper_case_action
Definition: file-editor.h:384
QAction * m_move_to_matching_brace
Definition: file-editor.h:432
void fetab_remove_all_breakpoints(const QWidget *ID)
QAction * m_remove_all_breakpoints_action
Definition: file-editor.h:466
void set_focus(QWidget *fet)
Definition: file-editor.cc:390
void handle_update_breakpoint_marker_request(bool insert, const QString &file, int line, const QString &cond)
void request_cut_line(bool)
Definition: file-editor.cc:815
QAction * m_previous_bookmark_action
Definition: file-editor.h:435
void request_comment_var_selected_text(bool)
Definition: file-editor.cc:843
void fetab_toggle_bookmark(const QWidget *ID)
void request_settings_dialog(const QString &)
QPointer< find_dialog > m_find_dialog
Definition: file-editor.h:495
QAction * m_show_linenum_action
Definition: file-editor.h:403
void fetab_unindent_selected_text(const QWidget *ID)
void copy_full_file_path(bool)
Definition: file-editor.cc:621
QAction * m_selectall_action
Definition: file-editor.h:399
void request_previous_breakpoint(bool)
Definition: file-editor.cc:768
void debug_quit_signal(void)
bool m_undo_action_enabled
Definition: file-editor.h:469
QAction * m_uncomment_selection_action
Definition: file-editor.h:388
void fetab_indent_selected_text(const QWidget *ID)
QAction * m_paste_action
Definition: file-editor.h:398
QAction * m_lower_case_action
Definition: file-editor.h:385
void handle_enter_debug_mode(void)
Definition: file-editor.cc:181
void fetab_context_run(const QWidget *ID)
void focusInEvent(QFocusEvent *e)
Definition: file-editor.cc:132
void request_styles_preferences(bool)
void fetab_set_focus(const QWidget *ID)
void set_shortcuts(void)
void request_remove_bookmark(bool)
Definition: file-editor.cc:742
void create_context_menu(QMenu *)
void dropEvent(QDropEvent *event)
QMenu * m_edit_menu
Definition: file-editor.h:473
void fetab_completion(const QWidget *)
void file_loaded_signal(void)
void editor_tabs_changed_signal(bool, bool)
QAction * m_delete_end_line_action
Definition: file-editor.h:418
void fetab_move_match_brace(const QWidget *ID, bool select)
QMenuBar * m_menu_bar
Definition: file-editor.h:376
void request_mru_open_file(QAction *action)
Definition: file-editor.cc:631
QAction * m_copy_line_action
Definition: file-editor.h:420
void enter_debug_mode_signal(void)
QAction * m_mru_file_actions[MaxMRUFiles]
Definition: file-editor.h:491
void active_tab_changed(int index)
void handle_dir_remove(const QString &old_name, const QString &new_name)
QAction * m_delete_start_word_action
Definition: file-editor.h:415
void fetab_insert_debugger_pointer(const QWidget *ID, int line=-1)
void show_statusbar(bool)
void restore_session(gui_settings *settings)
Definition: file-editor.cc:320
void request_sel_match_brace(bool)
Definition: file-editor.cc:752
void fetab_delete_debugger_pointer(const QWidget *ID, int line=-1)
bool m_no_focus
Definition: file-editor.h:486
tree_evaluator & get_evaluator(void)
base_qobject & m_octave_qobj
void set_title(const QString &)
Represents the main window.
Definition: main-window.h:73
@ bookmark
Definition: marker.h:58
virtual void handle_visibility(bool visible)
QWidget * focusWidget(void)
virtual void closeEvent(QCloseEvent *e)
virtual void activate(void)
void focus_console_after_command_signal(void)
void status_update(bool, bool)
void execute_command_in_terminal_signal(const QString &)
void handle_exit_debug_mode(void)
void handle_enter_debug_mode(void)
void create_context_menu_signal(QMenu *)
gui_settings * get_settings(void) const
QIcon icon(const QString &icon_name, bool octave_only=false, const QString &icon_alt_name=QString())
void set_shortcut(QAction *action, const sc_pref &scpref, bool enable=true)
void close_current_tab_signal(bool)
void set_rotated(int rotated)
Definition: tab-bar.cc:45
QMenu * get_context_menu(void)
Definition: tab-bar.h:55
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
const gui_pref ed_tabs_rotated("editor/tabs_rotated", QVariant(false))
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_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_tabs_max_width("editor/tabs_max_width", QVariant(0))
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_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_bookmarks("editor/saved_session_bookmarks", QVariant(QStringList()))
const gui_pref ed_session_enc("editor/saved_session_encodings", QVariant(QStringList()))
const QStyle::PixelMetric global_icon_sizes[3]
const QStringList global_icon_paths
const gui_pref global_use_custom_editor("useCustomFileEditor", QVariant(false))
@ ICON_THEME_OCTAVE
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)
octave::sys::time Vlast_prompt_time
Definition: input.cc:84
F77_RET_T const F77_DBLE * x
F77_RET_T const F77_DBLE const F77_DBLE * f
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)
static double fe[256]
Definition: randmtzig.cc:466
file_editor_tab * editor_tab
Definition: file-editor.h:95
const QString key
const QVariant def
static string_vector make_absolute(const string_vector &sv)
Definition: utils.cc:536
bool same_file(const std::string &f, const std::string &g)
Definition: utils.cc:294