Mercurial > hg > octave-shane
changeset 16579:7f8db1942dc0
Add Qt link uigetfile dialog implementation.
* libgui/src/octave-qt-link.cc, libgui/src/octave-qt-link.h,
(octave_qt_link::do_file_dialog): New function.
(make_filter_list): New function.
* libinterp/interpfcn/octave-link.cc
(__octave_link_file_dialog__): New function.
* libinterp/interpfcn/octave-link.h:
(octave_link::file_dialog): New function.
(octave_link::do_file_dialog): New virtual function.
* scripts/plot/uigetfile.m: update to call octave_link file dialog if octave link is present.
* libgui/src/dialog.cc, libgui/src/dialog.h
(class FileDialog): New class.
(QUIWidgetCreator::QUIWidgetCreator): added initialization of new var path_name.
(QUIWidgetCreator::signal_filedialog): New function.
(QUIWidgetCreator::create_filedialog): New function.
(QUIWidgetCreator::filedialog_finished): New function.
(QUIWidgetCreator::get_dialog_path): New function.
* libgui/src/main-window.cc, libgui/src/main-window.h
(main_window::connect_uiwidget_links): Added connect for handle_file_dialog.
(main_window::handle_create_filedialog): New function.
author | John Donoghue <john.donoghue@ieee.org> |
---|---|
date | Sun, 28 Apr 2013 09:45:19 -0400 |
parents | 0eca6c5657c9 |
children | adc150db1809 |
files | libgui/src/dialog.cc libgui/src/dialog.h libgui/src/main-window.cc libgui/src/main-window.h libgui/src/octave-qt-link.cc libgui/src/octave-qt-link.h libinterp/interpfcn/octave-link.cc libinterp/interpfcn/octave-link.h scripts/plot/uigetfile.m |
diffstat | 9 files changed, 327 insertions(+), 13 deletions(-) [+] |
line wrap: on
line diff
--- a/libgui/src/dialog.cc +++ b/libgui/src/dialog.cc @@ -31,6 +31,7 @@ #include <QStringList> #include <QStringListModel> #include <QListView> +#include <QFileInfo> // Could replace most of these with #include <QtGui> #include <QMessageBox> #include <QHBoxLayout> @@ -45,7 +46,7 @@ QUIWidgetCreator::QUIWidgetCreator (void) : QObject (), dialog_result (-1), dialog_button (), - string_list (new QStringList ()), list_index (new QIntList ()) + string_list (new QStringList ()), list_index (new QIntList ()), path_name (new QString ()) { } @@ -53,6 +54,7 @@ { delete string_list; delete list_index; + delete path_name; } @@ -94,6 +96,19 @@ waitcondition.wakeAll (); } +void +QUIWidgetCreator::filedialog_finished (const QStringList& files, const QString & path, const int filterindex) +{ + // Store the value so that builtin functions can retrieve. + *string_list = files; + dialog_result = filterindex; + *path_name = path; + + // Wake up Octave process so that it continues. + waitcondition.wakeAll (); +} + + MessageDialog::MessageDialog (const QString& message, const QString& title, @@ -386,7 +401,6 @@ done (QDialog::Accepted); } - void InputDialog::buttonCancel_clicked (void) { @@ -403,3 +417,66 @@ { buttonCancel_clicked (); } + +FileDialog::FileDialog (const QStringList &filters, + const QString& title, + const QString& filename, + const QString &dirname, + bool multiselect) + : QFileDialog() +{ + // Create a NonModal message. + setWindowModality (Qt::NonModal); + + setWindowTitle (title.isEmpty () ? " " : title); + setDirectory (dirname); + + if (multiselect) + setFileMode (QFileDialog::ExistingFiles); + else + setFileMode (QFileDialog::ExistingFile); + + setNameFilters (filters); + setAcceptMode (QFileDialog::AcceptOpen); + selectFile (filename); + + connect (this, SIGNAL (finish_input (const QStringList&, const QString &, const int)), + &uiwidget_creator, + SLOT (filedialog_finished (const QStringList&, const QString &, const int))); +} + +void +FileDialog::reject (void) +{ + QStringList empty; + emit finish_input (empty, "", 0); + done (QDialog::Rejected); + +} + +void FileDialog::accept(void) +{ + QStringList string_result; + QString path; + int idx = 1; + + string_result = selectedFiles(); + + // matlab expects just the file name, whereas the file dialog gave us + // pull path names, so fix it + for(int i=0;i<string_result.size ();i++) + { + string_result[i] = QFileInfo (string_result[i]).fileName (); + } + + + path = directory ().absolutePath (); + + QStringList filters = nameFilters (); + idx = filters.indexOf( selectedNameFilter ()) + 1; + + // send the selected info + emit finish_input (string_result, path, idx); + done (QDialog::Accepted); +} +
--- a/libgui/src/dialog.h +++ b/libgui/src/dialog.h @@ -32,6 +32,7 @@ #include <QDialog> #include <QMessageBox> #include <QLineEdit> +#include <QFileDialog> // Defined for purposes of sending QList<int> as part of signal. typedef QList<int> QIntList; @@ -102,7 +103,17 @@ }; const QStringList *get_string_list (void) { return string_list; } - + + bool signal_filedialog (const QStringList &filters, const QString &title, + const QString &filename, const QString &dirname, + bool multiselect) + { + emit create_filedialog (filters, title, filename, dirname, multiselect); + return true; + } + + const QString * get_dialog_path(void) { return path_name; } + void wait (void) { // Wait while the user is responding to message box. @@ -122,6 +133,11 @@ const QFloatList&, const QFloatList&, const QStringList&); + void create_filedialog (const QStringList &filters, + const QString &title, + const QString &filename, + const QString &dirname, + bool multiselect); public slots: void dialog_button_clicked (QAbstractButton *button); @@ -131,6 +147,8 @@ void input_finished (const QStringList& input, const int button_pressed); + void filedialog_finished (const QStringList& files, const QString &path, const int filterindex); + private: int dialog_result; @@ -141,6 +159,8 @@ QStringList *string_list; QIntList *list_index; + QString * path_name; + // GUI objects cannot be accessed in the non-GUI thread. However, // signals can be sent to slots across threads with proper // synchronization. Hence, the use of QWaitCondition. @@ -227,4 +247,24 @@ void reject (void); }; +class FileDialog : public QFileDialog +{ + Q_OBJECT + +public: + + explicit FileDialog (const QStringList &filters, + const QString& title, const QString& filename, + const QString& dirname, bool multiselect); + +signals: + + void finish_input (const QStringList&, const QString &, const int); + +private slots: + void reject(); + void accept(); + +}; + #endif
--- a/libgui/src/main-window.cc +++ b/libgui/src/main-window.cc @@ -651,6 +651,11 @@ SLOT (handle_create_inputlayout (const QStringList&, const QString&, const QFloatList&, const QFloatList&, const QStringList&))); + + connect (&uiwidget_creator, + SIGNAL (create_filedialog (const QStringList &,const QString&, const QString&, const QString&, bool)), + this, + SLOT (handle_create_filedialog (const QStringList &,const QString&, const QString&,const QString&, bool))); } // Create a message dialog with specified string, buttons and decorative @@ -707,6 +712,19 @@ input_dialog->show (); } +void +main_window::handle_create_filedialog (const QStringList &filters, + const QString& title, + const QString& filename, + const QString &dirname, + bool multiselect) +{ + FileDialog * file_dialog = new FileDialog(filters, title, + filename, dirname, multiselect); + file_dialog->setAttribute (Qt::WA_DeleteOnClose); + file_dialog->show (); +} + // Main subroutine of the constructor void main_window::construct (void)
--- a/libgui/src/main-window.h +++ b/libgui/src/main-window.h @@ -157,6 +157,11 @@ const QFloatList&, const QFloatList&, const QStringList&); + void handle_create_filedialog (const QStringList &filters, + const QString& title, const QString& filename, + const QString &dirname, + bool multiselect); + // find files dialog void find_files(const QString &startdir=QDir::currentPath()); void find_files_finished(int);
--- a/libgui/src/octave-qt-link.cc +++ b/libgui/src/octave-qt-link.cc @@ -128,6 +128,37 @@ return retval; } +static QStringList +make_filter_list (const std::list< std::pair<std::string, std::string> >& lst) +{ + QStringList retval; + + // we have pairs of data, first being the list of extensions exta;exb;extc etc + // second the name to use as filter name (optional). + // Qt wants a a list of filters in the format of 'FilterName (spacfe separated exts)' + + for (std::list< std::pair<std::string,std::string> >::const_iterator it = lst.begin (); + it != lst.end (); it++) + { + QString ext = QString::fromStdString ((*it).first); + QString name = QString::fromStdString ((*it).second); + + // strip out (exts) from name (if any) + name.replace(QRegExp("\\(.*\\)"), ""); + // replace ';' with spaces in ext list + ext.replace(";"," "); + + if (name.length() == 0) + { + // no name field - so need build one from teh extendiions + name = ext.toUpper() + " Files"; + } + + retval.append (name + " (" + ext + ")"); + } + + return retval; +} std::pair<std::list<int>, int> octave_qt_link::do_list_dialog (const std::list<std::string>& list, @@ -188,6 +219,39 @@ return retval; } +std::list<std::string> +octave_qt_link::do_file_dialog (const std::list< std::pair< std::string, std::string > > filter, + const std::string& title, + const std::string& filename, + const std::string& dirname, + bool multiselect) +{ + std::list<std::string> retval; + + uiwidget_creator.signal_filedialog ( make_filter_list (filter), + QString::fromStdString (title), + QString::fromStdString (filename), + QString::fromStdString (dirname), + multiselect); + + // Wait while the user is responding to dialog. + uiwidget_creator.wait (); + + // add all the file dialog result to a string list + const QStringList *inputLine = uiwidget_creator.get_string_list (); + + for (QStringList::const_iterator it = inputLine->begin (); + it != inputLine->end (); it++) + { + retval.push_back (it->toStdString ()); + } + + retval.push_back (uiwidget_creator.get_dialog_path ()->toStdString ()); + retval.push_back ((QString ("%1").arg (uiwidget_creator.get_dialog_result ())).toStdString ()); + + return retval; +} + int octave_qt_link::do_debug_cd_or_addpath_error (const std::string& file, const std::string& dir,
--- a/libgui/src/octave-qt-link.h +++ b/libgui/src/octave-qt-link.h @@ -84,6 +84,13 @@ const std::list<float>& nc, const std::list<std::string>& defaults); + std::list<std::string> + do_file_dialog (const std::list< std::pair< std::string, std::string > > filter, + const std::string& title, + const std::string &filename, + const std::string &pathname, + bool multiselect); + int do_debug_cd_or_addpath_error (const std::string& file, const std::string& dir, @@ -114,6 +121,7 @@ void do_set_default_prompts (std::string& ps1, std::string& ps2, std::string& ps4); + private: // No copying!
--- a/libinterp/interpfcn/octave-link.cc +++ b/libinterp/interpfcn/octave-link.cc @@ -193,6 +193,82 @@ return retval; } +DEFUN (__octave_link_file_dialog__, args, , + "-*- texinfo -*-\n\ +@deftypefn {Built-in Function} {} __octave_link_file_dialog__ (@var{filterlist}, @var{title}, @var{filename}, @var{size} @var{multiselect}, @var{pathname})\n\ +Undocumented internal function.\n\ +@end deftypefn") +{ + octave_value_list retval(3, octave_value (0)); + + if (args.length () == 6) + { + + const Array<std::string> flist = args (0).cellstr_value (); + std::string title = args (1).string_value (); + std::string filename = args (2).string_value (); + Matrix pos = args (3).matrix_value (); + std::string multi_on = args (4).string_value (); // on, off + std::string pathname = args (5).string_value (); + + octave_idx_type nel = flist.numel (); + std::list< std::pair<std::string, std::string> > filter_lst; + + for(octave_idx_type i = 0; i < flist.rows (); i++) + { + filter_lst.push_back ( std::make_pair (flist.elem (i,0), flist.columns ()>1 ? flist.elem (i, 1) : "" ) ); + } + + if (! error_state) + { + + flush_octave_stdout (); + + std::list<std::string> items_lst + = octave_link::file_dialog (filter_lst, title, filename, pathname, multi_on == "on" ? true : false); + + nel = items_lst.size (); + + // if 3, then is filename, dolder and selected index, + if (items_lst.size () <= 3) + { + int idx = 0; + for (std::list<std::string>::iterator it = items_lst.begin (); + it != items_lst.end (); it++) + { + retval (idx++) = *(it); + + if (idx == 1 && retval (0).string_value ().length () == 0) + retval (0) = 0; + if(idx == 3) retval (2) = atoi (retval (2).string_value ().c_str ()); + } + } + else + { + // multiple files + nel = items_lst.size (); + Cell items (dim_vector (1, nel)); + + std::list<std::string>::iterator it = items_lst.begin (); + for (int idx=0;idx<items_lst.size ()-2;idx++) + { + items.xelem (idx) = *it; + it++; + } + retval (0) = items; + retval (1) = *it; + it++; + retval (2) = atoi ((*it).c_str ()); + } + + } + else + error ("invalid arguments"); + + } + return retval; +} + DEFUN (__octave_link_list_dialog__, args, , "-*- texinfo -*-\n\ @deftypefn {Built-in Function} {} __octave_link_list_dialog__ (@var{list}, @var{mode}, @var{size}, @var{intial}, @var{name}, @var{prompt}, @var{ok_string}, @var{cancel_string})\n\
--- a/libinterp/interpfcn/octave-link.h +++ b/libinterp/interpfcn/octave-link.h @@ -179,6 +179,19 @@ : std::list<std::string> (); } + static std::list<std::string> + file_dialog ( const std::list< std::pair< std::string, std::string > > filter, + const std::string& title, + const std::string& filename, + const std::string& dirname, + bool multiselect) + { + return enabled () + ? instance->do_file_dialog (filter, title, filename, dirname, multiselect) + : std::list<std::string> (); + } + + static int debug_cd_or_addpath_error (const std::string& file, const std::string& dir, bool addpath_option) @@ -370,6 +383,13 @@ const std::list<float>& nc, const std::list<std::string>& defaults) = 0; + virtual std::list<std::string> + do_file_dialog (const std::list< std::pair< std::string, std::string > > filter, + const std::string& title, + const std::string& filename, + const std::string& dirname, + bool multiselect) = 0; + virtual int do_debug_cd_or_addpath_error (const std::string& file, const std::string& dir,
--- a/scripts/plot/uigetfile.m +++ b/scripts/plot/uigetfile.m @@ -65,19 +65,21 @@ function [retfile, retpath, retindex] = uigetfile (varargin) - defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__"); - funcname = ["__uigetfile_", defaulttoolkit, "__"]; - functype = exist (funcname); - if (! __is_function__ (funcname)) - funcname = "__uigetfile_fltk__"; + if (! __octave_link_enabled__ ()) + defaulttoolkit = get (0, "defaultfigure__graphics_toolkit__"); + funcname = ["__uigetfile_", defaulttoolkit, "__"]; + functype = exist (funcname); if (! __is_function__ (funcname)) - error ("uigetfile: fltk graphics toolkit required"); - elseif (! strcmp (defaulttoolkit, "gnuplot")) - warning ("uigetfile: no implementation for toolkit '%s', using 'fltk' instead", + funcname = "__uigetfile_fltk__"; + if (! __is_function__ (funcname)) + error ("uigetfile: fltk graphics toolkit required"); + elseif (! strcmp (defaulttoolkit, "gnuplot")) + warning ("uigetfile: no implementation for toolkit '%s', using 'fltk' instead", defaulttoolkit); + endif endif endif - + if (nargin > 7) error ("uigetfile: number of input arguments must be less than eight"); endif @@ -183,7 +185,11 @@ endfor endif - [retfile, retpath, retindex] = feval (funcname, outargs{:}); + if (__octave_link_enabled__ ()) + [retfile, retpath, retindex] = __octave_link_file_dialog__ (outargs{:}); + else + [retfile, retpath, retindex] = feval (funcname, outargs{:}); + endif endfunction