changeset 16377:8430ea8c1594

open editor tab and insert marker for debugging with gui * file-editor-interface.h (file_editor_interface::request_open_file): New public slot. (file_editor_interface::handle_dbstop_request): New virtual function. * file-editor-tab.h, file-editor-tab.cc (file_editor_tab::goto_line): New arg, line, with default value. Don't prompt if line is greater than zero. (file_editor_tab::set_debugger_position): New arg, widget id. (file_editor_tab::add_filename_to_list): New arg, widget id. * file-editor.h, file-editor.cc (file_eidtor::editor_tab_map): New data member. (file_editor::fetFileNames) Delete. (file_editor::~file_editor, file_editor::check_conflict_save, file_editor::handle_add_filename_to_list): Use editor_tab_map instead of fetFileNames. (file_editor::request_open_file): New args, line and set_marker. Optionally position cursor at line and with debug marker. If file is already open in tab, switch to it instead of giving error. (file_editor::construct): Connect fetab_set_debugger_position signal to set_debugger_position slot. * main-window.h, main-window.cc (main_window::dbstop_signal): New signal. (main_window::handle_dbstop_request): New function. * octave-event-listener.h (octave_event_listener::dbstop): New virtual function. * octave-qt-event-listener.h, octave-qt-event-listener.cc (octave_qt_event_listener::dbstop): New function. (octave_qt_event_listener::dbstop_signal): New signal. * octave-link.h, octave-link.cc (octave_link::dbstop, octave_link::do_dbstop, octave_link::dbstop_event_hook_fcn, octave_link::do_dbstop_event_hook_fcn): New functions * octave-main-thread.h, octave-main-thread.cc (dbstop_event_hook_fcn): New function. (octave_main_thread::run): Add it to the list of dbstop event hook functions.
author John W. Eaton <jwe@octave.org>
date Wed, 27 Mar 2013 12:59:12 -0400
parents a2f65b8f1955
children b28ae106e316
files libgui/src/m-editor/file-editor-interface.h libgui/src/m-editor/file-editor-tab.cc libgui/src/m-editor/file-editor-tab.h libgui/src/m-editor/file-editor.cc libgui/src/m-editor/file-editor.h libgui/src/main-window.cc libgui/src/main-window.h libgui/src/octave-adapter/octave-event-listener.h libgui/src/octave-adapter/octave-link.cc libgui/src/octave-adapter/octave-link.h libgui/src/octave-adapter/octave-main-thread.cc libgui/src/octave-qt-event-listener.cc libgui/src/octave-qt-event-listener.h
diffstat 13 files changed, 208 insertions(+), 76 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/m-editor/file-editor-interface.h	Wed Mar 27 00:45:49 2013 -0400
+++ b/libgui/src/m-editor/file-editor-interface.h	Wed Mar 27 12:59:12 2013 -0400
@@ -46,12 +46,14 @@
 
   virtual void handle_entered_debug_mode () = 0;
   virtual void handle_quit_debug_mode () = 0;
+  virtual void handle_dbstop_request (const QString& file, int line) = 0;
   virtual void set_focus () = 0;
 
 public slots:
   virtual void request_new_file () = 0;
   virtual void request_open_file () = 0;
-  virtual void request_open_file (const QString& fileName) = 0;
+  virtual void request_open_file (const QString& fileName, int line = -1,
+                                  bool set_marker = false) = 0;
 
 //signals:
 
--- a/libgui/src/m-editor/file-editor-tab.cc	Wed Mar 27 00:45:49 2013 -0400
+++ b/libgui/src/m-editor/file-editor-tab.cc	Wed Mar 27 12:59:12 2013 -0400
@@ -629,19 +629,26 @@
 }
 
 void
-file_editor_tab::goto_line (const QWidget* ID)
+file_editor_tab::goto_line (const QWidget* ID, int line)
 {
   if (ID != this)
     return;
 
-  int line, index;
+  bool ok = true;
 
-  _edit_area->getCursorPosition(&line, &index);
+  if (line <= 0)
+    {
+      bool ok = false;
+
+      int index;
 
-  bool ok = false;
+      _edit_area->getCursorPosition(&line, &index);
+
 
-  line = QInputDialog::getInt (_edit_area, "Goto line", "Line number", 
-                               line+1, 1, _edit_area->lines(), 1, &ok);
+      line = QInputDialog::getInt (_edit_area, "Goto line", "Line number", 
+                                   line+1, 1, _edit_area->lines(), 1, &ok);
+    }
+
   if (ok)
     _edit_area->setCursorPosition (line-1, 0);
 }
@@ -1103,7 +1110,7 @@
 
   // Unnamed files shouldn't be transmitted.
   if (!_file_name.isEmpty ())
-    emit add_filename_to_list (_file_name);
+    emit add_filename_to_list (_file_name, this);
 }
 
 void
@@ -1140,8 +1147,11 @@
 }
 
 void
-file_editor_tab::set_debugger_position (int line)
+file_editor_tab::set_debugger_position (const QWidget *ID, int line)
 {
+  if (ID != this || ID == 0)
+    return;
+
   _edit_area->markerDeleteAll (debugger_position);
   if (line > 0)
     {
--- a/libgui/src/m-editor/file-editor-tab.h	Wed Mar 27 00:45:49 2013 -0400
+++ b/libgui/src/m-editor/file-editor-tab.h	Wed Mar 27 12:59:12 2013 -0400
@@ -75,9 +75,9 @@
   void comment_selected_text (const QWidget* ID);
   void uncomment_selected_text (const QWidget* ID);
   void find (const QWidget* ID);
-  void goto_line (const QWidget* ID);
+  void goto_line (const QWidget* ID, int line = -1);
 
-  void set_debugger_position (int line);
+  void set_debugger_position (const QWidget *ID, int line = -1);
 
   void set_modified (bool modified = true);
 
@@ -90,7 +90,7 @@
   void file_name_changed (const QString& fileName, const QString& toolTip);
   void editor_state_changed (bool copy_available, const QString& fileName);
   void tab_remove_request ();
-  void add_filename_to_list (const QString& fileName);
+  void add_filename_to_list (const QString&, QWidget *);
   void mru_add_file (const QString& file_name);
   void editor_check_conflict_save (const QString& saveFileName, bool remove_on_success);
   void process_octave_code (const QString& command);
--- a/libgui/src/m-editor/file-editor.cc	Wed Mar 27 00:45:49 2013 -0400
+++ b/libgui/src/m-editor/file-editor.cc	Wed Mar 27 12:59:12 2013 -0400
@@ -54,12 +54,17 @@
 file_editor::~file_editor ()
 {
   QSettings *settings = resource_manager::get_settings ();
-  fetFileNames.clear ();
+  editor_tab_map.clear ();
   if (settings->value ("editor/restoreSession",true).toBool ())
     {
       // Have all file editor tabs signal what their file names are.
       emit fetab_file_name_query (0);
     }
+  QStringList fetFileNames;
+  for (std::map<QString, QWidget *>::const_iterator p = editor_tab_map.begin ();
+       p != editor_tab_map.end (); p++)
+    fetFileNames.append (p->first);
+
   settings->setValue ("editor/savedSessionTabs", fetFileNames);
   settings->sync ();
 
@@ -142,7 +147,8 @@
 }
 
 void
-file_editor::request_open_file (const QString& openFileName)
+file_editor::request_open_file (const QString& openFileName, int line,
+                                bool set_marker)
 {
   if (openFileName.isEmpty ())
     {
@@ -152,63 +158,66 @@
   else
     {
       // Have all file editor tabs signal what their file names are.
-      fetFileNames.clear ();
+      editor_tab_map.clear ();
       emit fetab_file_name_query (0);
 
       // Check whether this file is already open in the editor.
-      if (fetFileNames.contains (openFileName, Qt::CaseSensitive))
+      std::map<QString, QWidget *>::const_iterator p = editor_tab_map.find (openFileName);
+      if (p != editor_tab_map.end ())
+        {
+          _tab_widget->setCurrentWidget (p->second);
+
+          if (line > 0)
+            {
+              emit fetab_goto_line (p->second, line);
+
+              if (set_marker)
+                emit fetab_set_debugger_position (p->second, line-1);
+            }
+
+          emit fetab_set_focus (p->second);
+        }
+      else
         {
-          // Create a NonModal message so nothing is blocked and
-          // bring the existing file forward.
-          QMessageBox* msgBox = new QMessageBox (
-                  QMessageBox::Critical, tr ("Octave Editor"),
-                  tr ("File %1 is already open in the editor.").
-                  arg (openFileName), QMessageBox::Ok, 0);
-          msgBox->setWindowModality (Qt::NonModal);
-          msgBox->setAttribute (Qt::WA_DeleteOnClose);
-          msgBox->show ();
-          QFileInfo file(openFileName);
-          QString short_openFileName = file.fileName();  // get file name only
-          for(int i = 0; i < _tab_widget->count (); i++)
-            { // check whether tab title is file name (long or short)
-              if (_tab_widget->tabText (i) == openFileName ||
-                  _tab_widget->tabText (i) == short_openFileName)
+          file_editor_tab *fileEditorTab = new file_editor_tab ();
+          if (fileEditorTab)
+            {
+              QString result = fileEditorTab->load_file(openFileName);
+              if (result == "")
                 {
-                  _tab_widget->setCurrentIndex (i);
-                  break;
+                  // Supply empty title then have the file_editor_tab update
+                  // with full or short name.
+                  add_file_editor_tab (fileEditorTab, "");
+                  fileEditorTab->update_window_title (false);
+                  // file already loaded, add file to mru list here
+                  handle_mru_add_file(QDir::cleanPath (openFileName));
+
+                  if (line > 0)
+                    {
+                      emit fetab_goto_line (fileEditorTab, line);
+
+                      if (set_marker)
+                        emit fetab_set_debugger_position (fileEditorTab, line-1);
+                    }
+                }
+              else
+                {
+                  delete fileEditorTab;
+                  // Create a NonModal message about error.
+                  QMessageBox* msgBox = new QMessageBox (
+                                                         QMessageBox::Critical, tr ("Octave Editor"),
+                                                         tr ("Could not open file %1 for read:\n%2.").
+                                                         arg (openFileName).arg (result),
+                                                         QMessageBox::Ok, 0);
+                  msgBox->setWindowModality (Qt::NonModal);
+                  msgBox->setAttribute (Qt::WA_DeleteOnClose);
+                  msgBox->show ();
                 }
             }
-          return;
+
+          // really show editor and the current editor tab
+          set_focus ();
         }
-
-      file_editor_tab *fileEditorTab = new file_editor_tab ();
-      if (fileEditorTab)
-        {
-          QString result = fileEditorTab->load_file(openFileName);
-          if (result == "")
-            {
-              // Supply empty title then have the file_editor_tab update
-              // with full or short name.
-              add_file_editor_tab (fileEditorTab, "");
-              fileEditorTab->update_window_title (false);
-              // file already loaded, add file to mru list here
-              handle_mru_add_file(QDir::cleanPath (openFileName));
-            }
-          else
-            {
-              delete fileEditorTab;
-              // Create a NonModal message about error.
-              QMessageBox* msgBox = new QMessageBox (
-                      QMessageBox::Critical, tr ("Octave Editor"),
-                      tr ("Could not open file %1 for read:\n%2.").
-                      arg (openFileName).arg (result),
-                      QMessageBox::Ok, 0);
-              msgBox->setWindowModality (Qt::NonModal);
-              msgBox->setAttribute (Qt::WA_DeleteOnClose);
-              msgBox->show ();
-            }
-        }
-      set_focus ();  // really show editor and the current editor tab
     }
 }
 
@@ -228,11 +237,11 @@
 file_editor::check_conflict_save (const QString& saveFileName, bool remove_on_success)
 {
   // Have all file editor tabs signal what their file names are.
-  fetFileNames.clear ();
+  editor_tab_map.clear ();
   emit fetab_file_name_query (0);
 
-  // If one of those names matches the desired name, that's a conflict.
-  if (fetFileNames.contains (saveFileName, Qt::CaseSensitive))
+  std::map<QString, QWidget *>::const_iterator p = editor_tab_map.find (saveFileName);
+  if (p != editor_tab_map.end ())
     {
       // Note: to overwrite the contents of some other file editor tab
       // with the same name requires identifying which file editor tab
@@ -283,6 +292,12 @@
 }
 
 void
+file_editor::handle_dbstop_request (const QString& file, int line)
+{
+  request_open_file (file, line, true);
+}
+
+void
 file_editor::request_undo ()
 {
   emit fetab_undo (_tab_widget->currentWidget ());
@@ -484,9 +499,11 @@
 }
 
 void
-file_editor::handle_add_filename_to_list (const QString& fileName)
+file_editor::handle_add_filename_to_list (const QString& fileName, QWidget *ID)
 {
-  fetFileNames.append (fileName);
+  // Should we allow multiple tabs for a single file?
+
+  editor_tab_map[fileName] = ID;
 }
 
 void
@@ -788,8 +805,8 @@
            this, SLOT (handle_editor_state_changed (bool, const QString&)));
   connect (f, SIGNAL (tab_remove_request ()),
            this, SLOT (handle_tab_remove_request ()));
-  connect (f, SIGNAL (add_filename_to_list (const QString&)),
-           this, SLOT (handle_add_filename_to_list (const QString&)));
+  connect (f, SIGNAL (add_filename_to_list (const QString&, QWidget *)),
+           this, SLOT (handle_add_filename_to_list (const QString&, QWidget *)));
   connect (f, SIGNAL (editor_check_conflict_save (const QString&, bool)),
            this, SLOT (check_conflict_save (const QString&, bool)));
   connect (f, SIGNAL (mru_add_file (const QString&)),
@@ -847,10 +864,12 @@
            f, SLOT (uncomment_selected_text (const QWidget*)));
   connect (this, SIGNAL (fetab_find (const QWidget*)),
            f, SLOT (find (const QWidget*)));
-  connect (this, SIGNAL (fetab_goto_line (const QWidget*)),
-           f, SLOT (goto_line (const QWidget*)));
+  connect (this, SIGNAL (fetab_goto_line (const QWidget *, int)),
+           f, SLOT (goto_line (const QWidget *, int)));
   connect (this, SIGNAL (fetab_set_focus (const QWidget*)),
            f, SLOT (set_focus (const QWidget*)));
+  connect (this, SIGNAL (fetab_set_debugger_position (const QWidget *, int)),
+           f, SLOT (set_debugger_position (const QWidget *, int)));
 
   _tab_widget->setCurrentWidget (f);
 }
--- a/libgui/src/m-editor/file-editor.h	Wed Mar 27 00:45:49 2013 -0400
+++ b/libgui/src/m-editor/file-editor.h	Wed Mar 27 12:59:12 2013 -0400
@@ -30,6 +30,8 @@
 #include <QCloseEvent>
 #include <QTabWidget>
 
+#include <map>
+
 #include "file-editor-interface.h"
 #include "file-editor-tab.h"
 
@@ -85,7 +87,8 @@
   void fetab_comment_selected_text (const QWidget* ID);
   void fetab_uncomment_selected_text (const QWidget* ID);
   void fetab_find (const QWidget* ID);
-  void fetab_goto_line (const QWidget* ID);
+  void fetab_goto_line (const QWidget* ID, int line = -1);
+  void fetab_set_debugger_position (const QWidget* ID, int line = -1);
   void fetab_set_focus (const QWidget* ID);
 
 public slots:
@@ -120,17 +123,19 @@
   void handle_file_name_changed (const QString& fileName, const QString& toolTip);
   void handle_tab_close_request (int index);
   void handle_tab_remove_request ();
-  void handle_add_filename_to_list (const QString& fileName);
+  void handle_add_filename_to_list (const QString& fileName, QWidget *ID);
   void active_tab_changed (int index);
   void handle_editor_state_changed (bool enableCopy, const QString& fileName);
   void handle_mru_add_file (const QString& file_name);
   void check_conflict_save (const QString& fileName, bool remove_on_success);
 
+  void handle_dbstop_request (const QString& file, int line);
+
   /** Tells the editor to react on changed settings. */
   void notice_settings ();
 
 private slots:
-  void request_open_file (const QString& fileName);
+  void request_open_file (const QString& fileName, int line = -1, bool = false);
 
 private:
   void construct ();
@@ -138,7 +143,8 @@
   void save_file_as (QWidget *fetabID = 0);
   void mru_menu_update ();
 
-  QStringList fetFileNames;
+  std::map<QString, QWidget *> editor_tab_map;
+
   QString ced;
 
   QMenuBar *        _menu_bar;
--- a/libgui/src/main-window.cc	Wed Mar 27 00:45:49 2013 -0400
+++ b/libgui/src/main-window.cc	Wed Mar 27 12:59:12 2013 -0400
@@ -512,6 +512,14 @@
 }
 
 void
+main_window::handle_dbstop_request (const QString& file, int line)
+{
+#ifdef HAVE_QSCINTILLA
+  _file_editor->handle_dbstop_request (file, line);
+#endif
+}
+
+void
 main_window::debug_continue ()
 {
   octave_link::post_event (this, &main_window::debug_continue_callback);
@@ -1155,6 +1163,10 @@
            SIGNAL (quit_debug_mode_signal ()),
            this,
            SLOT (handle_quit_debug_mode ()));
+
+  connect (_octave_qt_event_listener,
+           SIGNAL (dbstop_signal (const QString&, int)), this,
+           SLOT (handle_dbstop_request (const QString&, int)));
 }
 
 void
--- a/libgui/src/main-window.h	Wed Mar 27 00:45:49 2013 -0400
+++ b/libgui/src/main-window.h	Wed Mar 27 12:59:12 2013 -0400
@@ -118,6 +118,7 @@
 
   void handle_entered_debug_mode ();
   void handle_quit_debug_mode ();
+  void handle_dbstop_request (const QString& file, int line);
   void debug_continue ();
   void debug_step_into ();
   void debug_step_over ();
--- a/libgui/src/octave-adapter/octave-event-listener.h	Wed Mar 27 00:45:49 2013 -0400
+++ b/libgui/src/octave-adapter/octave-event-listener.h	Wed Mar 27 12:59:12 2013 -0400
@@ -40,6 +40,8 @@
     virtual void
     update_history (void) = 0;
 
+    virtual void dbstop (const std::string& file, int line) = 0;
+
     virtual void about_to_exit () = 0;
 
     virtual void entered_debug_mode () = 0;
--- a/libgui/src/octave-adapter/octave-link.cc	Wed Mar 27 00:45:49 2013 -0400
+++ b/libgui/src/octave-adapter/octave-link.cc	Wed Mar 27 12:59:12 2013 -0400
@@ -157,6 +157,40 @@
 }
 
 void
+octave_link::do_dbstop (const octave_value_list& args)
+{
+  if (event_listener)
+    {
+      if (args.length () == 1)
+        {
+          octave_scalar_map m = args(0).scalar_map_value ();
+
+          if (! error_state)
+            {
+              octave_value ov_file = m.getfield ("file");
+              octave_value ov_line = m.getfield ("line");
+
+              std::string file = ov_file.string_value ();
+              int line = ov_line.int_value ();
+
+              if (! error_state)
+                {
+                  event_listener->dbstop (file, line);
+
+                  do_process_events ();
+                }
+              else
+                ::error ("invalid struct in dbstop callback");
+            }
+          else
+            ::error ("expecting struct in dbstop callback");
+        }
+      else
+        ::error ("invalid call to dbstop callback");
+    }
+}
+
+void
 octave_link::do_pre_input_event_hook_fcn (void)
 {
   do_update_workspace ();
@@ -168,6 +202,12 @@
   do_update_history ();
 }
 
+void
+octave_link::do_dbstop_event_hook_fcn (const octave_value_list& args)
+{
+  do_dbstop (args);
+}
+
 bool
 octave_link::instance_ok (void)
 {
--- a/libgui/src/octave-adapter/octave-link.h	Wed Mar 27 00:45:49 2013 -0400
+++ b/libgui/src/octave-adapter/octave-link.h	Wed Mar 27 12:59:12 2013 -0400
@@ -28,6 +28,8 @@
 
 class octave_mutex;
 
+#include "oct-obj.h"
+
 #include "event-queue.h"
 
 #include "octave-main-thread.h"
@@ -132,6 +134,12 @@
       instance->do_update_history ();
   }
 
+  static void dbstop (const octave_value_list& args)
+  {
+    if (instance_ok ())
+      instance->do_dbstop (args);
+  }
+
   static void pre_input_event_hook_fcn (void)
   {
     if (instance_ok ())
@@ -144,6 +152,12 @@
       instance->do_post_input_event_hook_fcn ();
   }
 
+  static void dbstop_event_hook_fcn (const octave_value_list& args)
+  {
+    if (instance_ok ())
+      instance->do_dbstop_event_hook_fcn (args);
+  }
+
 private:
 
   static octave_link *instance;
@@ -206,9 +220,11 @@
   std::string do_last_working_directory (void);
   void do_update_workspace (void);
   void do_update_history (void);
+  void do_dbstop (const octave_value_list& args);
 
   void do_pre_input_event_hook_fcn (void);
   void do_post_input_event_hook_fcn (void);
+  void do_dbstop_event_hook_fcn (const octave_value_list& args);
 };
 
 #endif // OCTAVELINK_H
--- a/libgui/src/octave-adapter/octave-main-thread.cc	Wed Mar 27 00:45:49 2013 -0400
+++ b/libgui/src/octave-adapter/octave-main-thread.cc	Wed Mar 27 12:59:12 2013 -0400
@@ -55,6 +55,16 @@
   return retval;
 }
 
+static octave_value_list
+dbstop_event_hook_fcn (const octave_value_list& args, int)
+{
+  octave_value_list retval;
+
+  octave_link::dbstop_event_hook_fcn (args);
+
+  return retval;
+}
+
 octave_main_thread::octave_main_thread () : QThread ()
 {
 }
@@ -78,6 +88,10 @@
   octave_value post_fcn_handle (new octave_fcn_handle (post_fcn));
   Fadd_post_input_event_hook (post_fcn_handle);
 
+  octave_value dbstop_fcn (new octave_builtin (dbstop_event_hook_fcn));
+  octave_value dbstop_fcn_handle (new octave_fcn_handle (dbstop_fcn));
+  Fadd_dbstop_event_hook (dbstop_fcn_handle);
+
   // Prime the history list.
   octave_link::update_history ();
 
--- a/libgui/src/octave-qt-event-listener.cc	Wed Mar 27 00:45:49 2013 -0400
+++ b/libgui/src/octave-qt-event-listener.cc	Wed Mar 27 12:59:12 2013 -0400
@@ -24,6 +24,8 @@
 #include <config.h>
 #endif
 
+#include <iostream>
+
 #include "octave-qt-event-listener.h"
 #include <QApplication>
 
@@ -52,6 +54,12 @@
 }
 
 void
+octave_qt_event_listener::dbstop (const std::string& file, int line)
+{
+  emit dbstop_signal (QString::fromStdString (file), line);
+}
+
+void
 octave_qt_event_listener::about_to_exit ()
 {
   qApp->quit ();
--- a/libgui/src/octave-qt-event-listener.h	Wed Mar 27 00:45:49 2013 -0400
+++ b/libgui/src/octave-qt-event-listener.h	Wed Mar 27 12:59:12 2013 -0400
@@ -37,6 +37,7 @@
   void current_directory_has_changed (const std::string& directory);
   void update_workspace (void);
   void update_history (void);
+  void dbstop (const std::string& file, int line);
   void about_to_exit ();
 
   void entered_debug_mode ();
@@ -46,6 +47,7 @@
   void current_directory_has_changed_signal (const QString& directory);
   void update_workspace_signal (void);
   void update_history_signal (void);
+  void dbstop_signal (const QString& file, int line);
   void entered_debug_mode_signal ();
   void quit_debug_mode_signal ();
 };