# HG changeset patch # User John W. Eaton # Date 1366736236 14400 # Node ID 04fb96f4bea1900a9388e585b69a36afc920ce29 # Parent 03a28487fa9d9cbcab5926b9a380f3fdaf9c3ad0 allow double-click in file browser to load data files * files-dock-widget.cc (files_dock_widget::display_directory): If file looks like Octave data file, load it instead of opening with editor. * ls-mat-ascii.h, ls-mat-ascii.cc (get_lines_and_columns): New option to supress error messages. New option to check for numeric values. (looks_like_mat_ascii_file): New function. * load-save.h load-save.cc (is_octave_data_file): New function. (get_file_format): Don't return LS_MAT_ASCII unless the file really looks like it is a numeric data file. diff -r 03a28487fa9d -r 04fb96f4bea1 libgui/src/files-dock-widget.cc --- a/libgui/src/files-dock-widget.cc Tue Apr 23 08:14:54 2013 -0400 +++ b/libgui/src/files-dock-widget.cc Tue Apr 23 12:57:16 2013 -0400 @@ -41,6 +41,8 @@ #include #include +#include "load-save.h" + files_dock_widget::files_dock_widget (QWidget *p) : octave_dock_widget (p) { @@ -280,8 +282,15 @@ } else { - if (QFile::exists (fileInfo.absoluteFilePath ())) - emit open_file (fileInfo.absoluteFilePath ()); + QString abs_fname = fileInfo.absoluteFilePath (); + + if (QFile::exists (abs_fname)) + { + if (is_octave_data_file (abs_fname.toStdString ())) + emit load_file_signal (abs_fname); + else + emit open_file (fileInfo.absoluteFilePath ()); + } } } } diff -r 03a28487fa9d -r 04fb96f4bea1 libinterp/interp-core/ls-mat-ascii.cc --- a/libinterp/interp-core/ls-mat-ascii.cc Tue Apr 23 08:14:54 2013 -0400 +++ b/libinterp/interp-core/ls-mat-ascii.cc Tue Apr 23 12:57:16 2013 -0400 @@ -107,7 +107,10 @@ } static void -get_lines_and_columns (std::istream& is, const std::string& filename, octave_idx_type& nr, octave_idx_type& nc) +get_lines_and_columns (std::istream& is, + octave_idx_type& nr, octave_idx_type& nc, + const std::string& filename = std::string (), + bool quiet = false, bool check_numeric = false) { std::streampos pos = is.tellg (); @@ -147,6 +150,25 @@ if (end != std::string::npos) { + if (check_numeric) + { + std::istringstream tmp_stream (buf.substr (beg, end-beg)); + + octave_read_double (tmp_stream); + + if (tmp_stream.fail ()) + { + if (! quiet) + error ("load: %s: non-numeric data found near line %d", + filename.c_str (), file_line_number); + + nr = 0; + nc = 0; + + goto done; + } + } + beg = buf.find_first_not_of (", \t", end); if (beg == std::string::npos || (buf[beg] == '\r' && @@ -172,14 +194,24 @@ else if (nc == tmp_nc) nr++; else - error ("load: %s: inconsistent number of columns near line %d", - filename.c_str (), file_line_number); + { + if (! quiet) + error ("load: %s: inconsistent number of columns near line %d", + filename.c_str (), file_line_number); + + nr = 0; + nc = 0; + + goto done; + } } } - if (nr == 0 || nc == 0) + if (! quiet && (nr == 0 || nc == 0)) error ("load: file '%s' seems to be empty!", filename.c_str ()); + done: + is.clear (); is.seekg (pos); } @@ -233,7 +265,7 @@ int total_count = 0; - get_lines_and_columns (is, filename, nr, nc); + get_lines_and_columns (is, nr, nc, filename); octave_quit (); @@ -376,3 +408,23 @@ return (os && success); } + +bool +looks_like_mat_ascii_file (const std::string& filename) +{ + bool retval = false; + + std::ifstream is (filename.c_str ()); + + if (is) + { + int nr = 0; + int nc = 0; + + get_lines_and_columns (is, nr, nc, filename, true, true); + + retval = (nr != 0 && nc != 0); + } + + return retval; +} diff -r 03a28487fa9d -r 04fb96f4bea1 libinterp/interp-core/ls-mat-ascii.h --- a/libinterp/interp-core/ls-mat-ascii.h Tue Apr 23 08:14:54 2013 -0400 +++ b/libinterp/interp-core/ls-mat-ascii.h Tue Apr 23 12:57:16 2013 -0400 @@ -31,4 +31,6 @@ save_mat_ascii_data (std::ostream& os, const octave_value& val_arg, int precision, bool tabs = false); +extern bool looks_like_mat_ascii_file (const std::string& filename); + #endif diff -r 03a28487fa9d -r 04fb96f4bea1 libinterp/interpfcn/load-save.cc --- a/libinterp/interpfcn/load-save.cc Tue Apr 23 08:14:54 2013 -0400 +++ b/libinterp/interpfcn/load-save.cc Tue Apr 23 12:57:16 2013 -0400 @@ -242,7 +242,8 @@ int32_t mopt, nr, nc, imag, len; - int err = read_mat_file_header (file, swap, mopt, nr, nc, imag, len, 1); + int err = read_mat_file_header (file, swap, mopt, nr, nc, imag, len, + true); if (! err) retval = LS_MAT_BINARY; @@ -277,7 +278,7 @@ static load_save_format get_file_format (const std::string& fname, const std::string& orig_fname, - bool &use_zlib) + bool &use_zlib, bool quiet = false) { load_save_format retval = LS_UNKNOWN; @@ -309,19 +310,16 @@ } #endif - if (retval == LS_UNKNOWN) - { - // Try reading the file as numbers only, determining the - // number of rows and columns from the data. We don't - // even bother to check to see if the first item in the - // file is a number, so that get_complete_line() can - // skip any comments that might appear at the top of the - // file. + // FIXME -- looks_like_mat_ascii_file does not check to see + // whether the file contains numbers. It just skips comments and + // checks for the same number of words on each line. We may need + // a better check here. The best way to do that might be just + // to try to read the file and see if it works. - retval = LS_MAT_ASCII; - } + if (retval == LS_UNKNOWN && looks_like_mat_ascii_file (fname)) + retval = LS_MAT_ASCII; } - else + else if (! quiet) gripe_file_open ("load", orig_fname); return retval; @@ -537,6 +535,12 @@ return fname; } +bool +is_octave_data_file (const std::string& fname) +{ + bool use_zlib = false; + return get_file_format (fname, fname, use_zlib, true) != LS_UNKNOWN; +} DEFUN (load, args, nargout, "-*- texinfo -*-\n\ diff -r 03a28487fa9d -r 04fb96f4bea1 libinterp/interpfcn/load-save.h --- a/libinterp/interpfcn/load-save.h Tue Apr 23 08:14:54 2013 -0400 +++ b/libinterp/interpfcn/load-save.h Tue Apr 23 12:57:16 2013 -0400 @@ -26,6 +26,9 @@ #include #include +#include "mach-info.h" +#include "symtab.h" + class octave_value; // FIXME: maybe MAT5 and MAT7 should be options to MAT_BINARY. @@ -80,6 +83,8 @@ bool list_only, bool swap, bool verbose, const string_vector& argv, int argv_idx, int argc, int nargout); +extern bool is_octave_data_file (const std::string& file); + extern void do_save (std::ostream& os, const symbol_table::symbol_record& sr, load_save_format fmt, bool save_as_floats);