# HG changeset patch
# User Pantxo Diribarne <pantxo.diribarne@gmail.com>
# Date 1489611617 -3600
#      Wed Mar 15 22:00:17 2017 +0100
# Node ID 104517a1ffb94eb220f7c7ef1d4e41fa7f7a9ede
# Parent  eb12cc23b7e8eb71e9b36b727a8e412bbf6a82aa
Fallback to open.m for opening files in the gui file browser (bug #50543)

* files-dock-widget.h/cc (files_dock_widget::files_dock_widget): Update tree 
  view tooltip.
  (files_dock_widget::open_any_signal): New signal.
  (files_dock_widget::display_directory): If the activated file is not a text 
  file with specified extension, emit open_any_signal

* main-window.cc (main_window::handle_open_any_request, 
  main_window::handle_open_any_request): New slot and corresponding interpreter
  thread callback that calls the "open" function.
  (main_window::construct): Connect file browser open_any_signal to 
  handle_open_any_request slot.

* open.m: allow user defined openxxx functions to be called when specific "xxx"
  file extensions are met. Let ".ofig" files be open using hgload and 
  "octave-workspace" files be loaded in the base workspace like ".mat" files

diff -r eb12cc23b7e8 -r 104517a1ffb9 libgui/src/files-dock-widget.cc
--- a/libgui/src/files-dock-widget.cc	Tue May 15 22:06:44 2018 +0200
+++ b/libgui/src/files-dock-widget.cc	Wed Mar 15 22:00:17 2017 +0100
@@ -212,8 +212,7 @@
     m_file_tree_view->setSortingEnabled (true);
     m_file_tree_view->setAlternatingRowColors (true);
     m_file_tree_view->setAnimated (true);
-    m_file_tree_view->setToolTip (
-                                  tr ("Activate to open in editor, right click for alternatives"));
+    m_file_tree_view->setToolTip (tr ("Double click to open file/folder, right click for alternatives"));
 
     // get sort column and order as well as cloumn state (order and width)
 
@@ -388,13 +387,10 @@
 
             if (QFile::exists (abs_fname))
               {
-                if (is_octave_data_file (abs_fname.toStdString ()))
-                  emit load_file_signal (abs_fname);
-                else if (extensions.contains (suffix))
+                if (extensions.contains (suffix))
                   emit open_file (fileInfo.absoluteFilePath ());
                 else
-                  open_item_in_app (m_file_tree_view->selectionModel ()
-                                    ->currentIndex ());
+                  emit open_any_signal (abs_fname);
               }
           }
       }
diff -r eb12cc23b7e8 -r 104517a1ffb9 libgui/src/files-dock-widget.h
--- a/libgui/src/files-dock-widget.h	Tue May 15 22:06:44 2018 +0200
+++ b/libgui/src/files-dock-widget.h	Wed Mar 15 22:00:17 2017 +0100
@@ -141,10 +141,14 @@
 
     void displayed_directory_changed (const QString& dir);
 
-    //! Emitted, whenever the user requested to load a file.
+    //! Emitted, whenever the user requested to load a file in the text editor.
 
     void load_file_signal (const QString& fileName);
 
+    //! Emitted, whenever the user requested to open an unknown type file.
+
+    void open_any_signal (const QString& fileName);
+
     //! Emitted, whenever the user requested to run a file.
 
     void run_file_signal (const QFileInfo& info);
diff -r eb12cc23b7e8 -r 104517a1ffb9 libgui/src/main-window.cc
--- a/libgui/src/main-window.cc	Tue May 15 22:06:44 2018 +0200
+++ b/libgui/src/main-window.cc	Wed Mar 15 22:00:17 2017 +0100
@@ -69,6 +69,7 @@
 #include "interpreter.h"
 #include "oct-map.h"
 #include "octave.h"
+#include "parse.h"
 #include "symscope.h"
 #include "utils.h"
 #include "version.h"
@@ -380,6 +381,13 @@
                                file.toStdString ());
   }
 
+  void main_window::handle_open_any_request (const QString& file_arg)
+  {
+    if (! file_arg.isEmpty ())
+      octave_link::post_event (this, &main_window::open_any_callback,
+                               file_arg.toStdString ());
+  }
+
   void main_window::handle_clear_workspace_request (void)
   {
     octave_link::post_event (this, &main_window::clear_workspace_callback);
@@ -1822,6 +1830,9 @@
         connect (m_file_browser_window, SIGNAL (load_file_signal (const QString&)),
                  this, SLOT (handle_load_workspace_request (const QString&)));
 
+        connect (m_file_browser_window, SIGNAL (open_any_signal (const QString&)),
+                 this, SLOT (handle_open_any_request (const QString&)));
+
         connect (m_file_browser_window, SIGNAL (find_files_signal (const QString&)),
                  this, SLOT (find_files (const QString&)));
 
@@ -2533,6 +2544,20 @@
     command_editor::set_screen_size (sz.first, sz.second);
   }
 
+  void main_window::open_any_callback (const std::string& file)
+  {
+    // INTERPRETER THREAD
+
+    octave::feval ("open", ovl (file));
+
+    // Update the workspace since open.m may have loaded new variables.
+    symbol_scope scope
+      = __get_current_scope__ ("main_window::open_any_callback");
+
+    if (scope)
+          octave_link::set_workspace (true, scope);
+  }
+
   void main_window::clear_workspace_callback (void)
   {
     // INTERPRETER THREAD
diff -r eb12cc23b7e8 -r 104517a1ffb9 libgui/src/main-window.h
--- a/libgui/src/main-window.h	Tue May 15 22:06:44 2018 +0200
+++ b/libgui/src/main-window.h	Wed Mar 15 22:00:17 2017 +0100
@@ -145,6 +145,7 @@
     void report_status_message (const QString& statusMessage);
     void handle_save_workspace_request (void);
     void handle_load_workspace_request (const QString& file = QString ());
+    void handle_open_any_request (const QString& file = QString ());
     void handle_clear_workspace_request (void);
     void handle_clear_command_window_request (void);
     void handle_clear_history_request (void);
@@ -322,6 +323,8 @@
 
     void load_workspace_callback (const std::string& file);
 
+    void open_any_callback (const std::string& file);
+
     void rename_variable_callback (const name_pair& names);
 
     void command_window_undo_callback (void);
diff -r eb12cc23b7e8 -r 104517a1ffb9 scripts/miscellaneous/open.m
--- a/scripts/miscellaneous/open.m	Tue May 15 22:06:44 2018 +0200
+++ b/scripts/miscellaneous/open.m	Wed Mar 15 22:00:17 2017 +0100
@@ -22,19 +22,38 @@
 ## Open the file @var{file} in Octave or in an external application based on
 ## the file type as determined by the filename extension.
 ##
-## Recognized file types are
+## By default, recognized file types are
 ##
 ## @table @code
 ## @item .m
-## Open file in the editor.
+## Open file in the editor. No @var{output} value is returned.
 ##
 ## @item .mat
-## Load the file in the base workspace.
+## @item octave-workspace
+## Open the data file with @code{load}. If no return value @var{output}
+## is requested, variables are loaded in the base workspace. Otherwise
+## @var{output} will be a structure containing loaded data.
+## @xref{XREFload, , load function}.
+##
+## @item .ofig 
+## Open the figure with hgload.  @xref{XREFhgload, , hgload function}.
 ##
 ## @item .exe
-## Execute the program (on Windows systems only).
+## Execute the program (on Windows systems only). No @var{output} value
+## is returned.
 ## @end table
 ##
+## Custom file extensions may also be handled if a function @code{openxxx}, 
+## where @code{xxx} is the extension, is found in the load path.  The function 
+## must accept the file name as input.  For example, in order to load ".dat"
+## data files in the base workspace, as is done by default for ".mat" files, one
+## may define "opendat.m" with the following contents:
+## @example
+## function retval = opendat (fname)
+##   evalin ("base", sprintf ("load ('%s');", fname));
+## endfunction
+## @end example
+##
 ## Other file types are opened in the appropriate external application.
 ## @end deftypefn
 
@@ -48,17 +67,27 @@
     error ("open: FILE must be a string");
   endif
 
-  [~, ~, ext] = fileparts (file);
+  [~, fname, ext] = fileparts (file);
 
-  if (strcmpi (ext, ".m"))
+  if (! isempty (ext)
+      && any (exist (["open" tolower(ext(2:end))]) == [2 3 5 103]))
+    try 
+      feval (["open" tolower(ext(2:end))], file)
+    catch
+      error ("open: %s", lasterr);
+    end_try_catch
+  elseif (strcmpi (ext, ".m"))
     edit (file);
-  elseif (strcmpi (ext, ".mat"))
+  elseif (strcmpi (ext, ".mat") || strcmp (fname, "octave-workspace"))
     if (nargout > 0)
       output = load (file);
     else
       evalin ("base", sprintf ("load ('%s');", file));
     endif
-  elseif (any (strcmpi (ext, {".fig", ".mdl", ".slx", ".prj"})))
+  elseif (strcmpi (ext, ".ofig"))
+    output = hgload (file);
+    drawnow ();
+  elseif (any (strcmpi (ext, {".mdl", ".slx", ".prj"})))
     error ("open: opening file type '%s' is not supported", ext);
   elseif (strcmpi (ext, ".exe"))
     if (ispc ())
