# HG changeset patch # User John W. Eaton # Date 1367433100 14400 # Node ID f8e8c21cd89569b1f5c55a41e26ba4c0671abbc0 # Parent e84b77df8940ddba4fa699ed0bb0385b31823c5c matrix editor * matrix-view.h, matrix-view.cc: New files. * main-window.h, main-window.cc (main_window::matrix_editor): New member varaible. (main_window::handle_edit_matrix, main_window::close_matrix_editor, main_window::edit_variable, main_window::edit_variable_callback): New functions. (main_window::construct_octave_qt_link): Connect _octave_qt_link::edit_matrix_signal to main_window::handle_edit_matrix. * libgui/src/module.mk: Update file lists. * octave-qt-link.h, octave-qt-link.cc (octave_qt_link::do_edit_matrix): New function. (octave_qt_link::edit_matrix_signal): New signal. 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 @@ -74,6 +74,7 @@ doc_browser_window (new documentation_dock_widget (this)), editor_window (create_default_editor (this)), workspace_window (new workspace_view (this)), + matrix_editor (0), find_files_dlg (0), _octave_main_thread (0), _octave_qt_link (0) @@ -194,6 +195,39 @@ } void +main_window::handle_edit_matrix (const QString& name, + const QDoubleList& xdata, + octave_idx_type nr, octave_idx_type nc) +{ + if (! matrix_editor) + { + matrix_editor = new matrix_view (this, name, xdata, nr, nc); + + connect (matrix_editor, SIGNAL (finished ()), + this, SLOT (close_matrix_editor ())); + + addDockWidget (Qt::RightDockWidgetArea, matrix_editor); + + tabifyDockWidget (command_window, matrix_editor); + + matrix_editor->show (); + matrix_editor->raise (); + } + else + QMessageBox::about (this, tr ("Matrix Editor Error"), + tr ("One at a time for now, eh?")); +} + +void +main_window::close_matrix_editor (void) +{ + delete matrix_editor; + matrix_editor = 0; + + focus_command_window (); +} + +void main_window::execute_command_in_terminal (const QString& command) { octave_link::post_event (this, &main_window::execute_command_callback, @@ -216,6 +250,13 @@ } void +main_window::edit_variable (const QString& var_name) +{ + octave_link::post_event (this, &main_window::edit_variable_callback, + var_name.toStdString ()); +} + +void main_window::open_online_documentation_page (void) { QDesktopServices::openUrl (QUrl ("http://gnu.org/software/octave/doc/interpreter")); @@ -851,6 +892,15 @@ connect (_octave_qt_link, SIGNAL (exit_signal (int)), this, SLOT (exit (int))); + qRegisterMetaType("QDoubleList"); + qRegisterMetaType("octave_idx_type"); + connect (_octave_qt_link, + SIGNAL (edit_matrix_signal (const QString&, const QDoubleList&, + octave_idx_type, octave_idx_type)), + this, + SLOT (handle_edit_matrix (const QString&, const QDoubleList&, + octave_idx_type, octave_idx_type))); + connect (_octave_qt_link, SIGNAL (set_workspace_signal (bool, const QString&, const QStringList&, @@ -1519,6 +1569,36 @@ } void +main_window::edit_variable_callback (const std::string& var_name) +{ + if (var_name == "foobar") + octave_link::message_dialog + ("warn", + "Variable too large to edit in spreadsheet.", + "Variable Editor"); + else + { + octave_value val = symbol_table::varval (var_name); + + if (val.is_real_matrix ()) + { + const Matrix mx = val.matrix_value (); + + int i = 0; + std::vector vec (mx.numel ()); + for (std::vector::iterator p = vec.begin (); + p != vec.end (); p++) + *p = mx(i++); + + octave_idx_type nr = mx.rows (); + octave_idx_type nc = mx.columns (); + + octave_link::edit_matrix (var_name, vec, nr, nc); + } + } +} + +void main_window::exit_callback (void) { Fquit (); diff --git a/libgui/src/main-window.h b/libgui/src/main-window.h --- a/libgui/src/main-window.h +++ b/libgui/src/main-window.h @@ -54,6 +54,7 @@ #include "documentation-dock-widget.h" #include "octave-qt-link.h" #include "find-files-dialog.h" +#include "matrix-view.h" /** * \class MainWindow @@ -115,12 +116,19 @@ void change_directory_up (void); void accept_directory_line_edit (void); + void handle_edit_matrix (const QString& name, const QDoubleList& data, + octave_idx_type nr, octave_idx_type nc); + + void close_matrix_editor (void); + void execute_command_in_terminal(const QString& dir); void handle_new_figure_request (void); void handle_new_variable_request (void); + void edit_variable (const QString& var_name); + void handle_enter_debugger (void); void handle_exit_debugger (void); void debug_continue (void); @@ -228,6 +236,8 @@ void debug_quit_callback (void); + void edit_variable_callback (const std::string& var_name); + void exit_callback (void); // Data models. @@ -243,6 +253,7 @@ documentation_dock_widget *doc_browser_window; file_editor_interface *editor_window; workspace_view *workspace_window; + matrix_view *matrix_editor; QToolBar *_main_tool_bar; QMenu *_debug_menu; diff --git a/libgui/src/matrix-view.cc b/libgui/src/matrix-view.cc new file mode 100644 --- /dev/null +++ b/libgui/src/matrix-view.cc @@ -0,0 +1,213 @@ +/* + +Copyright (C) 2013 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "matrix-view.h" +#include "resource-manager.h" +#include "octave-qt-link.h" + +#include "symtab.h" + +class +matrix_data +{ +public: + + matrix_data (const QString& n, const QDoubleList& d, int r, int c) + : name (n), data (d), nr (r), nc (c) + { } + + matrix_data (const matrix_data& md) + : name (md.name), data (md.data), nr (md.nr), nc (md.nc) { } + + matrix_data& operator = (const matrix_data& md) + { + if (this != &md) + { + name = md.name; + data = md.data; + nr = md.nr; + nc = md.nc; + } + + return *this; + } + + ~matrix_data (void) { } + + QString name; + QDoubleList data; + int nr; + int nc; +}; + +matrix_view::matrix_view (QWidget *p, const QString& n, const QDoubleList& d, + octave_idx_type r, octave_idx_type c) + : octave_dock_widget (p), view (new QTableWidget (r, c, this)), + var_edit (new QLineEdit (n, this)), + xname (n), xdata (d), xnr (r), xnc (c) +{ + setObjectName ("matrix_view"); + setWindowIcon (QIcon (":/actions/icons/logo.png")); + setWindowTitle (tr ("Matrix Editor")); + setStatusTip (tr ("Edit a matrix from the workspace.")); + + view->setWordWrap (false); + view->setContextMenuPolicy (Qt::CustomContextMenu); + + QStringList hlabels; + for (octave_idx_type i = 1; i <= xnc; i++) + hlabels << QString::number (i); + view->setHorizontalHeaderLabels (hlabels); + + QStringList vlabels; + for (octave_idx_type i = 1; i <= xnr; i++) + vlabels << QString::number (i); + view->setVerticalHeaderLabels (vlabels); + + QDoubleList::const_iterator it = d.begin (); + for (octave_idx_type j = 0; j < xnc; j++) + for (octave_idx_type i = 0; i < xnr; i++) + { + QTableWidgetItem *item = new QTableWidgetItem (QString::number (*it++)); + + item->setTextAlignment (Qt::AlignRight); + + view->setItem (i, j, item); + } + + connect (view, SIGNAL (cellChanged (int, int)), + this, SLOT (cell_changed (int, int))); + + // Set an empty widget, so we can assign a layout to it. + setWidget (new QWidget (this)); + + QLabel *var_label = new QLabel (tr ("Name:"), this); + + connect (var_edit, SIGNAL (editingFinished ()), this, SLOT (rename())); + + QPushButton *edit_finished_button = new QPushButton (tr ("Done")); + connect (edit_finished_button, SIGNAL (clicked ()), + this, SLOT (finish_editing ())); + + QHBoxLayout *hbox_layout = new QHBoxLayout (); + hbox_layout->addWidget (var_label); + hbox_layout->addWidget (var_edit); + hbox_layout->addWidget (edit_finished_button); + hbox_layout->setMargin (2); + + // Create a new layout and add widgets to it. + QVBoxLayout *vbox_layout = new QVBoxLayout (); + vbox_layout->addLayout (hbox_layout); + vbox_layout->addWidget (view); + vbox_layout->setMargin (2); + + // Set the empty widget to have our layout. + widget ()->setLayout (vbox_layout); + + QSettings *settings = resource_manager::get_settings (); + + // Initialize column order and width + + view->horizontalHeader ()->restoreState (settings->value ("matrixview/column_state").toByteArray ()); +} + +matrix_view::~matrix_view (void) +{ + QSettings *settings = resource_manager::get_settings (); + + settings->setValue ("matrixview/column_state", + view->horizontalHeader ()->saveState ()); + + settings->sync (); +} + +void +matrix_view::cell_changed (int i, int j) +{ + QTableWidgetItem *item = view->item (i, j); + + if (item) + { + QString qstr = item->text (); + xdata[j*xnr+i] = qstr.toDouble (); + } +} + +void +matrix_view::rename (void) +{ + xname = var_edit->text (); +} + +void +matrix_view::finish_editing (void) +{ + octave_link::post_event (this, &matrix_view::define_matrix_callback, + matrix_data (xname, xdata, xnr, xnc)); + + emit finished (); +} + +void +matrix_view::closeEvent (QCloseEvent *) +{ + emit finished (); +} + +void +matrix_view::define_matrix_callback (const matrix_data& md) +{ + Matrix mx (md.nr, md.nc); + + double *pmx = mx.fortran_vec (); + + octave_idx_type i = 0; + QDoubleList lst_data = md.data; + for (QDoubleList::const_iterator p = lst_data.begin (); + p != lst_data.end (); p++) + pmx[i++] = *p; + + QString name = md.name; + + symbol_table::assign (name.toStdString (), mx); + + octave_link::set_workspace (); +} diff --git a/libgui/src/matrix-view.h b/libgui/src/matrix-view.h new file mode 100644 --- /dev/null +++ b/libgui/src/matrix-view.h @@ -0,0 +1,80 @@ +/* + +Copyright (C) 2013 John W. Eaton + +This file is part of Octave. + +Octave is free software; you can redistribute it and/or modify it +under the terms of the GNU General Public License as published by the +Free Software Foundation; either version 3 of the License, or (at your +option) any later version. + +Octave is distributed in the hope that it will be useful, but WITHOUT +ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +for more details. + +You should have received a copy of the GNU General Public License +along with Octave; see the file COPYING. If not, see +. + +*/ + +#if !defined (matrix_view_h) +#define matrix_view_h 1 + +#include +#include + +#include "octave-dock-widget.h" +#include "workspace-model.h" + +class matrix_data; + +typedef QList QDoubleList; + +class matrix_view : public octave_dock_widget +{ + Q_OBJECT + +public: + + matrix_view (QWidget *p = 0) + : octave_dock_widget (p), view (0), xname (), xdata (), xnr (0), xnc (0) + { } + + matrix_view (QWidget *p, const QString& n, const QDoubleList& d, + octave_idx_type r, octave_idx_type c); + + ~matrix_view (void); + +protected: + + void closeEvent (QCloseEvent *); + +signals: + + void finished (void); + +protected slots: + + void cell_changed (int r, int c); + + void rename (void); + + void finish_editing (void); + +private: + + QTableWidget *view; + QLineEdit *var_edit; + + QString xname; + QDoubleList xdata; + octave_idx_type xnr; + octave_idx_type xnc; + + void define_matrix_callback (const matrix_data& md); +}; + +#endif diff --git a/libgui/src/module.mk b/libgui/src/module.mk --- a/libgui/src/module.mk +++ b/libgui/src/module.mk @@ -78,6 +78,7 @@ src/moc-files-dock-widget.cc \ src/moc-history-dock-widget.cc \ src/moc-main-window.cc \ + src/moc-matrix-view.cc \ src/moc-octave-qt-link.cc \ src/moc-settings-dialog.cc \ src/moc-terminal-dock-widget.cc \ @@ -112,6 +113,7 @@ src/m-editor/find-dialog.h \ src/m-editor/lexer-octave-gui.h \ src/main-window.h \ + src/matrix-view.h \ src/octave-gui.h \ src/octave-main-thread.h \ src/octave-qt-link.h \ @@ -137,6 +139,7 @@ src/m-editor/find-dialog.cc \ src/m-editor/lexer-octave-gui.cc \ src/main-window.cc \ + src/matrix-view.cc \ src/octave-gui.cc \ src/octave-main-thread.cc \ src/octave-qt-link.cc \ 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 @@ -337,6 +337,18 @@ } void +octave_qt_link::do_edit_matrix (const std::string& name, + const std::vector& data, + octave_idx_type nr, octave_idx_type nc) +{ + QDoubleList qdata; + for (int i = 0; i < nr * nc; i++) + qdata.append (data[i]); + + emit edit_matrix_signal (QString::fromStdString (name), qdata, nr, nc); +} + +void octave_qt_link::do_clear_workspace (void) { emit clear_workspace_signal (); 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 @@ -35,6 +35,8 @@ #include "octave-link.h" #include "octave-main-thread.h" +typedef QList QDoubleList; + // \class OctaveLink // \brief Provides threadsafe access to octave. // \author Jacob Dawid @@ -98,6 +100,10 @@ void do_execute_command_in_terminal (const std::string& command); + void do_edit_matrix (const std::string& name, + const std::vector& data, + octave_idx_type nr, octave_idx_type nc); + void do_set_workspace (bool top_level, const std::list& ws); @@ -144,6 +150,9 @@ void execute_command_in_terminal_signal (const QString& command); + void edit_matrix_signal (const QString& name, const QDoubleList& data, + octave_idx_type nr, octave_idx_type nc); + void set_workspace_signal (bool top_level, const QString& scopes, const QStringList& symbols, diff --git a/libgui/src/workspace-view.cc b/libgui/src/workspace-view.cc --- a/libgui/src/workspace-view.cc +++ b/libgui/src/workspace-view.cc @@ -35,10 +35,13 @@ #include #include #include +#include #include "workspace-view.h" #include "resource-manager.h" +#include "octave-link.h" + workspace_view::workspace_view (QWidget *p) : octave_dock_widget (p), view (new QTableView (this)) { @@ -77,6 +80,9 @@ connect (this, SIGNAL (command_requested (const QString&)), p, SLOT (execute_command_in_terminal (const QString&))); + + connect (this, SIGNAL (edit_variable_signal (const QString&)), + p, SLOT (edit_variable (const QString&))); } workspace_view::~workspace_view (void) @@ -129,6 +135,9 @@ menu.addSeparator (); + menu.addAction ("Open in Variable Editor", this, + SLOT (handle_contextmenu_edit ())); + menu.addAction ("disp(" + var_name + ")", this, SLOT (handle_contextmenu_disp ())); @@ -194,6 +203,25 @@ } void +workspace_view::handle_contextmenu_edit (void) +{ + QModelIndex index = view->currentIndex (); + + if (index.isValid ()) + { + index = index.sibling (index.row (), 0); + + QAbstractItemModel *m = view->model (); + + QMap item_data = m->itemData (index); + + QString var_name = item_data[0].toString (); + + emit edit_variable_signal (var_name); + } +} + +void workspace_view::handle_contextmenu_disp (void) { relay_contextmenu_command ("disp"); diff --git a/libgui/src/workspace-view.h b/libgui/src/workspace-view.h --- a/libgui/src/workspace-view.h +++ b/libgui/src/workspace-view.h @@ -50,6 +50,8 @@ /** signal that user had requested a command on a variable */ void command_requested (const QString& cmd); + void edit_variable_signal (const QString&); + protected: void closeEvent (QCloseEvent *event); @@ -61,6 +63,7 @@ // context menu slots void handle_contextmenu_copy (void); void handle_contextmenu_rename (void); + void handle_contextmenu_edit (void); void handle_contextmenu_disp (void); void handle_contextmenu_plot (void); void handle_contextmenu_stem (void); diff --git a/libinterp/interpfcn/octave-link.h b/libinterp/interpfcn/octave-link.h --- a/libinterp/interpfcn/octave-link.h +++ b/libinterp/interpfcn/octave-link.h @@ -213,6 +213,14 @@ instance->do_execute_command_in_terminal (command); } + static void edit_matrix (const std::string& name, + const std::vector& data, + octave_idx_type nr, octave_idx_type nc) + { + if (instance_ok ()) + instance->do_edit_matrix (name, data, nr, nc); + } + static void set_workspace (void); static void set_workspace (bool top_level, @@ -397,6 +405,10 @@ virtual void do_execute_command_in_terminal (const std::string& command) = 0; + virtual void do_edit_matrix (const std::string& name, + const std::vector& data, + octave_idx_type nr, octave_idx_type nc) = 0; + virtual void do_set_workspace (bool top_level, const std::list& ws) = 0;