# HG changeset patch
# User Daniel J Sebald <daniel.sebald@ieee.org>
# Date 1370810296 18000
# Node ID b498aeb01cf4a0ba712817f55b529cb77cc28de1
# Parent  cfefcc2a4dae1434a107e611d4c82a920cc668c2
Pass result of request_open_file back to edit.m script (bug #39179)

* file-editor-interface.h (file_editor::request_open_file): Return an int.
(file_editor::edit_file_finished): New signal returning file open result.

* file-editor.h (file_editor::request_open_file): Return an int.

* file-editor.cc (file_editor::request_open_file): Return appropriate result
for the various outcomes.
(file_editor::handle_edit_file_request): Retain result of open file, set focus
if successful, emit edit_file_finished with result.

* main-window.cc (main_window::construct_octave_qt_link): Connect signal
edit_file_finished() to slot handle_edit_file_finished().

* octave-qt-link.h (octave_qt_link : public QObject, public octave_link): New
QMutex, QWaitcondition and result variable for edit_file.
(octave_qt_link::handle_edit_file_finished) New slot.

* octave-qt-link.cc (octave_qt_link::do_edit_file): Init edit_file_result,
lock mutex, emit edit file signal, wait for ten seconds, unlock mutex, error
if edit_file_result bad, return true if result good, false if bad.
(octave_qt_link::handle_edit_file_finished): Save result in edit_file_result,
create error dialog if can't lock mutex, wake all threads if can lock mutex.

diff --git a/libgui/src/m-editor/file-editor-interface.h b/libgui/src/m-editor/file-editor-interface.h
--- a/libgui/src/m-editor/file-editor-interface.h
+++ b/libgui/src/m-editor/file-editor-interface.h
@@ -31,7 +31,7 @@
 {
   Q_OBJECT
 
-  public:
+public:
   file_editor_interface (QWidget *p)
     : octave_dock_widget (p)
   {
@@ -68,11 +68,12 @@
   virtual void request_new_script (const QString& command = QString ()) = 0;
   virtual void request_new_function (const QString& command = QString ()) = 0;
   virtual void request_open_file () = 0;
-  virtual void request_open_file (const QString& openFileName, int line = -1,
-                                  bool debug_pointer = false,
-                                  bool breakpoint_marker = false,
-                                  bool insert = true) = 0;
-//signals:
+  virtual int request_open_file (const QString& openFileName, int line = -1,
+                                 bool debug_pointer = false,
+                                 bool breakpoint_marker = false,
+                                 bool insert = true) = 0;
+signals:
+  void edit_file_finished (const int result);
 
 //protected:
 
diff --git a/libgui/src/m-editor/file-editor.cc b/libgui/src/m-editor/file-editor.cc
--- a/libgui/src/m-editor/file-editor.cc
+++ b/libgui/src/m-editor/file-editor.cc
@@ -223,7 +223,7 @@
   return retval;
 }    
 
-void
+int
 file_editor::request_open_file (const QString& openFileName, int line,
                                 bool debug_pointer,
                                 bool breakpoint_marker, bool insert)
@@ -238,13 +238,14 @@
       QProcess::startDetached (editor);
       if (line < 0)
         handle_mru_add_file (QDir::cleanPath (openFileName));
-      return;
+      return 0;
     }
 
   if (openFileName.isEmpty ())
     {
       // ??  Not sure this will happen.  This routine isn't even called
       // if the user hasn't selected a file.
+      return 2;
     }
   else
     {
@@ -302,6 +303,7 @@
               else
                 {
                   delete fileEditorTab;
+
                   // Create a NonModal message about error.
                   QMessageBox *msgBox
                     = new QMessageBox (QMessageBox::Critical,
@@ -313,6 +315,8 @@
                   msgBox->setWindowModality (Qt::NonModal);
                   msgBox->setAttribute (Qt::WA_DeleteOnClose);
                   msgBox->show ();
+
+                  return 3;
                 }
             }
 
@@ -320,6 +324,8 @@
           set_focus ();
         }
     }
+
+  return 0;
 }
 
 // open a file from the mru list
@@ -440,8 +446,12 @@
 void
 file_editor::handle_edit_file_request (const QString& file)
 {
-  request_open_file (file);
-  set_focus ();
+  int result = request_open_file (file);
+
+  if (! result)
+    set_focus ();
+
+  emit edit_file_finished (result);
 }
 
 void
diff --git a/libgui/src/m-editor/file-editor.h b/libgui/src/m-editor/file-editor.h
--- a/libgui/src/m-editor/file-editor.h
+++ b/libgui/src/m-editor/file-editor.h
@@ -156,10 +156,13 @@
   void notice_settings (const QSettings *settings);
 
 private slots:
-
-  void request_open_file (const QString& fileName, int line = -1,
-                          bool debug_pointer = false,
-                          bool breakpoint_marker = false, bool insert = true);
+  // 0 - no error
+  // 1 - no editor support
+  // 2 - empty file name
+  // 3 - file not found
+  int request_open_file (const QString& fileName, int line = -1,
+                         bool debug_pointer = false,
+                         bool breakpoint_marker = false, bool insert = true);
 
 private:
 
diff --git a/libgui/src/main-window.cc b/libgui/src/main-window.cc
--- a/libgui/src/main-window.cc
+++ b/libgui/src/main-window.cc
@@ -912,6 +912,10 @@
            SIGNAL (edit_file_signal (const QString&)),
            editor_window,
            SLOT (handle_edit_file_request (const QString&)));
+  connect (editor_window,
+           SIGNAL (edit_file_finished (const int)),
+           _octave_qt_link,
+           SLOT (handle_edit_file_finished (const int)));
 #endif
 
   connect (_octave_qt_link,
diff --git a/libgui/src/octave-qt-link.cc b/libgui/src/octave-qt-link.cc
--- a/libgui/src/octave-qt-link.cc
+++ b/libgui/src/octave-qt-link.cc
@@ -62,9 +62,58 @@
 bool
 octave_qt_link::do_edit_file (const std::string& file)
 {
+  edit_file_result = -1;
+
+#ifdef HAVE_QSCINTILLA
+  // This lock is to ensure that this Octave worker thread becomes
+  // unlocked by the QWaitCondition a few lines further down before
+  // the GUI thread attempts to wake the process.  Otherwise, there
+  // is the risk of this thread being awaken before going to sleep.
+  edit_file_mutex.lock ();
+
   emit edit_file_signal (QString::fromStdString (file));
 
-  return true;
+  // Wait for GUI to respond and awake, at most 10 seconds.
+  edit_file_waitcondition.wait (&edit_file_mutex, 10000);
+  edit_file_mutex.unlock ();
+  if (edit_file_result == -1)
+    error ("GUI not responding");
+#endif
+
+  // -1 means GUI not responding, 0 means success, 1 2 etc. mean other errors.
+  if (! edit_file_result)
+    return true;
+  else
+    return false;
+}
+
+void
+octave_qt_link::handle_edit_file_finished (const int result)
+{
+  // Save result so that when worker process is awakened, it might
+  // react accordingly.
+  edit_file_result = result;
+
+  // Wake up Octave worker process so that it continues but make sure the
+  // process is asleep first just in case there is some rare condition in
+  // which the GUI thread reaches this point before the Octave worker thread
+  // goes into a sleep state.  (This test may be overdoing things.)
+  if (! edit_file_mutex.tryLock (5000))
+    {
+      // Create a NonModal message about error.
+      QMessageBox* msgBox = new QMessageBox (
+              QMessageBox::Critical, tr ("Octave Qt Link"),
+              "Connection Timeout: Lost link to worker process.",
+              QMessageBox::Ok, 0);
+      msgBox->setWindowModality (Qt::NonModal);
+      msgBox->setAttribute (Qt::WA_DeleteOnClose);
+      msgBox->show ();
+    }
+  else
+    {
+      edit_file_mutex.unlock ();
+      edit_file_waitcondition.wakeAll ();
+    }
 }
 
 int
diff --git a/libgui/src/octave-qt-link.h b/libgui/src/octave-qt-link.h
--- a/libgui/src/octave-qt-link.h
+++ b/libgui/src/octave-qt-link.h
@@ -31,6 +31,8 @@
 #include <QList>
 #include <QObject>
 #include <QString>
+#include <QMutex>
+#include <QWaitCondition>
 
 #include "octave-link.h"
 #include "octave-main-thread.h"
@@ -135,6 +137,11 @@
   // Thread running octave_main.
   octave_main_thread *main_thread;
 
+  // Mutex for waiting on response to opening a file in the GUI editor.
+  QMutex edit_file_mutex;
+  QWaitCondition edit_file_waitcondition;
+  int edit_file_result;
+
 signals:
 
   void exit_signal (int status);
@@ -166,6 +173,9 @@
 
   void insert_debugger_pointer_signal (const QString&, int);
   void delete_debugger_pointer_signal (const QString&, int);
+
+public slots:
+  void handle_edit_file_finished (const int result);
 };
 
 #endif
