# HG changeset patch # User John W. Eaton # Date 1517916008 18000 # Tue Feb 06 06:20:08 2018 -0500 # Node ID 487f404d83dea8d5874658e55df07be0f5936fe2 # Parent 800876b7132c24dd6cd977f022a765f91515aad9 eliminate opaque pointer in variable editor model implementation * variable-editor-model.h, variable-editor-model.cc: Rewrite to use pointer to base class instead of opaque pointer to implementation. This change will allow simpler classes to manage editing of each type of data we can edit (numeric array, string, cell, scalar struct, vector struct, 2-d struct array). diff --git a/libgui/src/variable-editor-model.cc b/libgui/src/variable-editor-model.cc --- a/libgui/src/variable-editor-model.cc +++ b/libgui/src/variable-editor-model.cc @@ -43,8 +43,6 @@ along with Octave; see the file COPYING. #include "utils.h" #include "variables.h" -// Pimpl/Dpointer for variable_editor_model. - static QString make_label (const std::string& name, const octave_value& val) { @@ -69,6 +67,31 @@ make_label (const std::string& name, con return lbl_txt; } +static bool +type_is_editable (const octave_value& val) +{ + if ((val.isnumeric () || val.islogical () || val.iscell () + || val.isstruct ()) && val.ndims () == 2) + return true; + + if (val.is_string () && (val.rows () == 1 || val.is_zero_by_zero ())) + return true; + + return false; +} + +static bool +cell_is_editable (const octave_value& val) +{ + if ((val.isnumeric () || val.islogical ()) && val.numel () == 1) + return true; + + if (val.is_string () && (val.rows () == 1 || val.is_zero_by_zero ())) + return true; + + return false; +} + static char get_quote_char (const octave_value& val) { @@ -81,123 +104,6 @@ get_quote_char (const octave_value& val) return 0; } -static void -get_data_rows_and_columns (const octave_value& val, - octave_idx_type& rows, octave_idx_type& cols) -{ - if (val.is_string ()) - { - // VAL will either be "" or a char array with a single row. - // Either way, edit it as a single string. - - rows = 1; - cols = 1; - } - else if (val.isstruct ()) - { - if (val.numel () == 1) - { - // Scalar struct. Rows are fields, single column for - // values. - - rows = val.nfields (); - cols = 1; - } - else if (val.rows () == 1 || val.columns () == 1) - { - // Vector struct. Columns are fields, rows are values. - - rows = val.numel (); - cols = val.nfields (); - } - else - { - // 2-d struct array. Rows and columns index individual - // scalar structs. - - rows = val.rows (); - cols = val.columns (); - } - } - else - { - rows = val.rows (); - cols = val.columns (); - } -} - -static QVariant -checkelem_edit_display (const float_display_format& fmt, - const octave_value& val, int row, int col) -{ - if (row >= val.rows () || col >= val.columns ()) - return QVariant (); - - return QString::fromStdString (val.edit_display (fmt, row, col)); -} - -static QVariant -do_edit_display_sub (const float_display_format& fmt, const octave_value& val, - const octave_value& elt, int row, int col) -{ - if ((elt.numel () == 1 && (elt.isnumeric () || elt.islogical ())) - || (elt.is_string () && (elt.rows () == 1 || elt.isempty ()))) - return checkelem_edit_display (fmt, elt, 0, 0); - else - return checkelem_edit_display (fmt, val, row, col); -} - -static QVariant -do_edit_display (const float_display_format& fmt, octave_value& val, - int row, int col) -{ - QVariant data; - - if (val.iscell ()) - { - Cell cval = val.cell_value (); - - octave_value ov = cval(row,col); - - data = do_edit_display_sub (fmt, val, cval(row,col), row, col); - } - else if (val.isstruct ()) - { - if (val.numel () == 1) - { - // Scalar struct. Rows are fields, single column for - // values. - - octave_scalar_map m = val.scalar_map_value (); - - data = do_edit_display_sub (fmt, val, m.contents (row), row, col); - } - else if (val.rows () == 1 || val.columns () == 1) - { - // Vector struct. Columns are fields, rows are values. - - octave_map m = val.map_value (); - - Cell cval = m.contents (col); - - data = do_edit_display_sub (fmt, val, cval(row), row, col); - } - else - { - // 2-d struct array. Rows and columns index individual - // scalar structs. - - octave_map m = val.map_value (); - - data = do_edit_display_sub (fmt, val, m(row,col), row, col); - } - } - else - data = checkelem_edit_display (fmt, val, row, col); - - return data; -} - static float_display_format get_edit_display_format (const octave_value& val) { @@ -214,140 +120,434 @@ do_requires_sub_editor_sub (const octave || (elt.is_string () && (elt.rows () == 1 || elt.isempty ())))); } -static bool -do_requires_sub_editor (octave_value& val, int row, int col) +base_ve_model::base_ve_model (const QString& expr, const octave_value& val) + : m_name (expr.toStdString ()), + m_value (val), + m_data_rows (m_value.rows ()), + m_data_cols (m_value.columns ()), + m_display_rows (m_data_rows), + m_display_cols (m_data_cols), + m_update_pending (), + m_valid (m_value.is_defined ()), + m_validtext (make_label (m_name, m_value)), + m_display_fmt (get_edit_display_format (m_value)) +{ } + +std::string +base_ve_model::name (void) const { - if (val.iscell ()) - { - Cell cval = val.cell_value (); + return m_name; +} + +QString +base_ve_model::validtext (void) const +{ + return m_validtext; +} - octave_value ov = cval(row,col); +bool +base_ve_model::index_ok (const QModelIndex& idx, int& row, int& col) const +{ + row = 0; + col = 0; + + if (! idx.isValid ()) + return false; + + row = idx.row (); + col = idx.column (); + + return (row < data_rows () && col < data_columns ()); +} - return do_requires_sub_editor_sub (cval(row,col)); - } - else if (val.isstruct ()) +int +base_ve_model::column_width (void) const +{ + int width = 0; + + float_format r_fmt = m_display_fmt.real_format (); + float_format i_fmt = m_display_fmt.imag_format (); + + int rw = r_fmt.fw; + int iw = i_fmt.fw; + + if (rw > 0) { - if (val.numel () == 1) + if (m_value.iscomplex ()) { - // Scalar struct. Rows are fields, single column for - // values. - - octave_scalar_map m = val.scalar_map_value (); - - return do_requires_sub_editor_sub (m.contents (row)); - } - else if (val.rows () == 1 || val.columns () == 1) - { - // Vector struct. Columns are fields, rows are values. - - octave_map m = val.map_value (); - - Cell cval = m.contents (col); - - return do_requires_sub_editor_sub (cval(row)); + if (iw > 0) + width = rw + iw + 5; } else - { - // 2-d struct array. Rows and columns index individual - // scalar structs. + width = rw + 2; + } + + return width; +} - octave_map m = val.map_value (); +int +base_ve_model::rowCount (const QModelIndex&) const +{ + return m_valid ? m_display_rows : 1; +} + +int +base_ve_model::columnCount (const QModelIndex&) const +{ + return m_valid ? m_display_cols : 1; +} + +QString +base_ve_model::edit_display_sub (const octave_value& elt) const +{ + std::string str; - return do_requires_sub_editor_sub (m(row,col)); - } + if (cell_is_editable (elt)) + str = elt.edit_display (m_display_fmt, 0, 0); + else + { + dim_vector dv = elt.dims (); + str = "[" + dv.str () + " " + elt.class_name () + "]"; } - else - return false; + + return QString::fromStdString (str); +} + +QVariant +base_ve_model::edit_display (const QModelIndex& idx) const +{ + int row; + int col; + + if (! index_ok (idx, row, col)) + return QVariant (); + + std::string str = m_value.edit_display (m_display_fmt, row, col); + return QString::fromStdString (str); } -struct variable_editor_model::impl +QVariant +base_ve_model::data (const QModelIndex& idx, int role) const { - impl (void) = delete; + if (! idx.isValid ()) + return QVariant (); + + if (role == Qt::DisplayRole && update_pending (idx)) + return QVariant (update_pending_data (idx)); + + if (! m_valid) + { + if (role == Qt::DisplayRole) + return QVariant (QString ("Variable %d not found") + .arg (QString::fromStdString (m_name))); + + return QVariant (QString ("x")); + } + + switch (role) + { + case Qt::DisplayRole: + case Qt::EditRole: + return edit_display (idx); + +#if 0 + case Qt::StatusTipRole: + return elem (idx).m_status_tip; + + case Qt::ToolTipRole: + return elem (idx).m_tool_tip; + + case Qt::BackgroundRole: + return elem (idx).m_background; +#endif + } + + // Invalid. + return QVariant (); +} + +bool +base_ve_model::requires_sub_editor (const QModelIndex&) const +{ + return false; +} + +void +base_ve_model::set_update_pending (const QModelIndex& idx, const QString& str) +{ + m_update_pending[idx] = str; +} - impl (const QString& name, const octave_value& val, QLabel *label) - : m_name (name.toStdString ()), m_value (val), - m_data_rows (0), m_data_cols (0), - m_display_rows (32), m_display_cols (16), - m_update_pending (), m_validity (true), - m_validtext (make_label (m_name, m_value)), - m_label (label), - m_display_fmt (get_edit_display_format (m_value)) +bool +base_ve_model::update_pending (const QModelIndex& idx) const +{ + return m_update_pending.contains (idx); +} + +QString +base_ve_model::update_pending_data (const QModelIndex& idx) const +{ + return m_update_pending[idx]; +} + +void +base_ve_model::clear_update_pending (void) +{ + return m_update_pending.clear (); +} + +char +base_ve_model::quote_char (const QModelIndex&) const +{ + return 0; +} + +QVariant +base_ve_model::header_data (int section, Qt::Orientation, int role) const +{ + + if (role != Qt::DisplayRole) + return QVariant (); + + return QString::number (section+1); +} + +QString +base_ve_model::subscript_expression (const QModelIndex&) const +{ + return ""; +} + +// Private slots. + +octave_value +base_ve_model::value_at (const QModelIndex&) const +{ + return octave_value (); +} + +class numeric_model : public base_ve_model +{ +public: + + numeric_model (const QString& expr, const octave_value& val) + : base_ve_model (expr, val) { - m_label->setText (m_validtext); + // FIXME: should fill the window and expand on scrolling or + // resizing. + + m_display_rows = m_data_rows + 16; + m_display_cols = m_data_cols + 16; } - impl (const impl&) = delete; + ~numeric_model (void) = default; + + // No copying! + + numeric_model (const numeric_model&) = delete; + + numeric_model& operator = (const numeric_model&) = delete; - impl& operator = (const impl&) = delete; + QVariant edit_display (const QModelIndex& idx) const + { + int row; + int col; - octave_idx_type data_rows (void) const { return m_data_rows; } - octave_idx_type data_columns (void) const { return m_data_cols; } + if (! index_ok (idx, row, col)) + return QVariant (); + + std::string str = m_value.edit_display (m_display_fmt, row, col); + return QString::fromStdString (str); + } - int display_rows (void) const { return m_display_rows; } - int display_columns (void) const { return m_display_cols; } + QString subscript_expression (const QModelIndex& idx) const + { + if (! idx.isValid ()) + return ""; + + return (QString ("(%1,%2)") + .arg (idx.row () + 1) + .arg (idx.column () + 1)); + } +}; - void set_update_pending (const QModelIndex& idx, const QString& str) +class string_model : public base_ve_model +{ +public: + + string_model (const QString& expr, const octave_value& val) + : base_ve_model (expr, val) { - m_update_pending[idx] = str; + m_data_rows = 1; + m_data_cols = 1; + + m_display_rows = 1; + m_display_cols = 1; } - bool update_pending (const QModelIndex& idx) const + ~string_model (void) = default; + + // No copying! + + string_model (const string_model&) = delete; + + string_model& operator = (const string_model&) = delete; + + QVariant edit_display (const QModelIndex&) const { - return m_update_pending.contains (idx); + std::string str = m_value.edit_display (m_display_fmt, 0, 0); + return QString::fromStdString (str); } - QString update_pending_data (const QModelIndex& idx) const + char quote_char (const QModelIndex&) const { - return m_update_pending[idx]; + return get_quote_char (m_value); + } +}; + +class cell_model : public base_ve_model +{ +public: + + cell_model (const QString& expr, const octave_value& val) + : base_ve_model (expr, val) + { + // FIXME: should fill the window and expand on scrolling or + // resizing. + + m_display_rows = m_data_rows + 16; + m_display_cols = m_data_cols + 16; } - void clear_update_pending (void) + ~cell_model (void) = default; + + // No copying! + + cell_model (const cell_model&) = delete; + + cell_model& operator = (const cell_model&) = delete; + + QVariant edit_display (const QModelIndex& idx) const { - return m_update_pending.clear (); + int row; + int col; + + if (! index_ok (idx, row, col)) + return QVariant (); + + Cell cval = m_value.cell_value (); + + return edit_display_sub (cval(row,col)); } - int column_width (void) const + bool requires_sub_editor (const QModelIndex& idx) const { - int width = 0; + int row; + int col; - float_format r_fmt = m_display_fmt.real_format (); - float_format i_fmt = m_display_fmt.imag_format (); + if (! index_ok (idx, row, col)) + return false; - int rw = r_fmt.fw; - int iw = i_fmt.fw; + Cell cval = m_value.cell_value (); + + return do_requires_sub_editor_sub (cval(row,col)); + } - if (rw > 0) - { - if (m_value.iscomplex ()) - { - if (iw > 0) - width = rw + iw + 5; - } - else - width = rw + 2; - } + char quote_char (const QModelIndex& idx) const + { + octave_value ov = value_at (idx); + + if (ov.is_string ()) + return get_quote_char (ov); - return width; + return 0; + } + + QString subscript_expression (const QModelIndex& idx) const + { + if (! idx.isValid ()) + return ""; + + return (QString ("{%1,%2}") + .arg (idx.row () + 1) + .arg (idx.column () + 1)); } - char quote_char (int row, int col) const + octave_value value_at (const QModelIndex& idx) const { - if (m_value.is_string ()) - return get_quote_char (m_value); - else if (m_value.iscell ()) - { - octave_value ov = value_at (row, col); + int row; + int col; + + if (! index_ok (idx, row, col)) + return octave_value (); + + Cell cval = m_value.cell_value (); + + return cval(row,col); + } +}; + +// Scalar struct. Rows are fields, single column for values. + +class scalar_struct_model : public base_ve_model +{ +public: + + scalar_struct_model (const QString& expr, const octave_value& val) + : base_ve_model (expr, val) + { + // No extra cells. We currently don't allow new fields or + // additional values to be inserted. If we allow additional values, + // then the object becomes a vector structure and the display flips + // (see the vector struct model below). Do we want that? + + m_data_rows = val.nfields (); + m_data_cols = 1; + + m_display_rows = m_data_rows; + m_display_cols = 1; + } + + ~scalar_struct_model (void) = default; - if (ov.is_string ()) - return get_quote_char (ov); - } - else if (m_value.isstruct ()) - { - octave_value ov = value_at (row, col); + // No copying! + + scalar_struct_model (const scalar_struct_model&) = delete; + + scalar_struct_model& operator = (const scalar_struct_model&) = delete; + + QVariant edit_display (const QModelIndex& idx) const + { + int row; + int col; + + if (! index_ok (idx, row, col)) + return QVariant (); + + octave_scalar_map m = m_value.scalar_map_value (); + + return edit_display_sub (m.contents (row)); + } - if (ov.is_string ()) - return get_quote_char (ov); - } + bool requires_sub_editor (const QModelIndex& idx) const + { + int row; + int col; + + if (! index_ok (idx, row, col)) + return false; + + octave_scalar_map m = m_value.scalar_map_value (); + + return do_requires_sub_editor_sub (m.contents (row)); + } + + char quote_char (const QModelIndex& idx) const + { + octave_value ov = value_at (idx); + + if (ov.is_string ()) + return get_quote_char (ov); return 0; } @@ -358,247 +558,303 @@ struct variable_editor_model::impl if (role != Qt::DisplayRole) return QVariant (); - if (m_value.isstruct ()) + switch (orientation) { - if (m_value.numel () == 1) - { - // Scalar struct. Rows are fields, single column for - // values. - - if (orientation == Qt::Horizontal) - return QString ("Values"); - else - { - octave_scalar_map m = m_value.scalar_map_value (); - - string_vector fields = m.fieldnames (); + case Qt::Horizontal: + return QString ("Values"); - return QString::fromStdString (fields(section)); - } - } - else if (m_value.rows () == 1 || m_value.columns () == 1) - { - // Vector struct. Columns are fields, rows are values. + case Qt::Vertical: + { + octave_scalar_map m = m_value.scalar_map_value (); - if (orientation == Qt::Horizontal) - { - octave_map m = m_value.map_value (); - - string_vector fields = m.fieldnames (); + string_vector fields = m.fieldnames (); - return QString::fromStdString (fields(section)); - } - else - return QString::number (section+1); - } - else - { - // 2-d struct array. Rows and columns index individual - // scalar structs. + return QString::fromStdString (fields(section)); + } - return QString::number (section+1); - } + default: + break; } - return QString::number (section+1); + return QVariant (); } - QString subscript_expression (int row, int col) const + QString subscript_expression (const QModelIndex& idx) const { - if (m_value.is_string ()) - return ""; - else if (m_value.iscell ()) - return (QString ("{%1, %2}") - .arg (row + 1) - .arg (col + 1)); - else if (m_value.isstruct ()) - { - if (m_value.numel () == 1) - { - // Scalar struct. Rows are fields, single column for - // values. - - octave_scalar_map m = m_value.scalar_map_value (); - - string_vector fields = m.fieldnames (); + // Display size and data size match, so all valid indices should + // also be valid indices for the existing struct. - return QString (".%1").arg (QString::fromStdString (fields(row))); - } - else if (m_value.rows () == 1 || m_value.columns () == 1) - { - // Vector struct. Columns are fields, rows are values. - - octave_map m = m_value.map_value (); - - string_vector fields = m.fieldnames (); - - return (QString ("(%1).%2") - .arg (row + 1) - .arg (QString::fromStdString (fields(col)))); - } - else - { - // 2-d struct array. Rows and columns index individual - // scalar structs. - - octave_map m = m_value.map_value (); + int row; + int col; - return (QString ("(%1,%2)") - .arg (row + 1) - .arg (col + 1)); - } - } - else - return (QString ("(%1, %2)") - .arg (row + 1) - .arg (col + 1)); - } - - octave_value value_at (int row, int col) const - { - if (m_value.iscell ()) - { - Cell cval = m_value.cell_value (); - - return cval(row,col); - } - else if (m_value.isstruct ()) - { - if (m_value.numel () == 1) - { - // Scalar struct. Rows are fields, single column for - // values. + if (! index_ok (idx, row, col)) + return ""; - octave_scalar_map m = m_value.scalar_map_value (); - - return m.contents (row); - } - else if (m_value.rows () == 1 || m_value.columns () == 1) - { - // Vector struct. Columns are fields, rows are values. - - octave_map m = m_value.map_value (); - - Cell cval = m.contents (col); + octave_scalar_map m = m_value.scalar_map_value (); - return cval(row); - } - else - { - // 2-d struct array. Rows and columns index individual - // scalar structs. + string_vector fields = m.fieldnames (); - octave_map m = m_value.map_value (); - - return m(row,col); - } - } - else - return octave_value (); + return QString (".%1").arg (QString::fromStdString (fields(row))); } octave_value value_at (const QModelIndex& idx) const { - return value_at (idx.row (), idx.column ()); + int row; + int col; + + if (! index_ok (idx, row, col)) + return octave_value (); + + octave_scalar_map m = m_value.scalar_map_value (); + + return m.contents (row); } +}; + +// Vector struct. Columns are fields, rows are values. - bool requires_sub_editor (const QModelIndex& idx) +class vector_struct_model : public base_ve_model +{ +public: + + vector_struct_model (const QString& expr, const octave_value& val) + : base_ve_model (expr, val) { - return (idx.isValid () - && do_requires_sub_editor (m_value, idx.row (), idx.column ())); + // FIXME: should fill the window vertically and expand on scrolling + // or resizing. No extra cells horizontally. New fields must be + // added specially. + + m_data_rows = val.numel (); + m_data_cols = val.nfields (); + + m_display_rows = m_data_rows + 16; + m_display_cols = m_data_cols; } - void reset (const octave_value& val) - { - m_validity = false; + ~vector_struct_model (void) = default; - m_value = val; + // No copying! - m_display_fmt = get_edit_display_format (m_value); + vector_struct_model (const vector_struct_model&) = delete; - if (m_value.is_defined ()) - { - m_validity = true; - - get_data_rows_and_columns (m_value, m_data_rows, m_data_cols); + vector_struct_model& operator = (const vector_struct_model&) = delete; - m_display_rows = (m_data_rows > (m_display_rows - 8) - ? m_data_rows + 16 : m_display_rows); + QVariant edit_display (const QModelIndex& idx) const + { + int row; + int col; - m_display_cols = (m_data_cols > (m_display_cols - 8) - ? m_data_cols + 16 : m_display_cols); - } - else - { - m_data_rows = 0; - m_data_cols = 0; - } + if (! index_ok (idx, row, col)) + return QVariant (); - m_label->setTextFormat (Qt::PlainText); + octave_map m = m_value.map_value (); - m_validtext = make_label (m_name, m_value); + Cell cval = m.contents (col); + + return edit_display_sub (cval(row)); } - void invalidate (void) + bool requires_sub_editor (const QModelIndex& idx) const { - reset (octave_value ()); + int row; + int col; + + if (! index_ok (idx, row, col)) + return false; + + octave_map m = m_value.map_value (); + + Cell cval = m.contents (col); + + return do_requires_sub_editor_sub (cval(row)); } - QVariant data (const QModelIndex& idx, int role) + char quote_char (const QModelIndex& idx) const { - if (idx.isValid ()) - { - switch (role) - { - case Qt::DisplayRole: - case Qt::EditRole: - return do_edit_display (m_display_fmt, m_value, - idx.row (), idx.column ()); + octave_value ov = value_at (idx); + + if (ov.is_string ()) + return get_quote_char (ov); + + return 0; + } + + QVariant header_data (int section, Qt::Orientation orientation, + int role) const + { + if (role != Qt::DisplayRole) + return QVariant (); -#if 0 - case Qt::StatusTipRole: - return elem (idx).m_status_tip; + switch (orientation) + { + case Qt::Horizontal: + { + octave_map m = m_value.map_value (); + + string_vector fields = m.fieldnames (); - case Qt::ToolTipRole: - return elem (idx).m_tool_tip; + return QString::fromStdString (fields(section)); + } - case Qt::BackgroundRole: - return elem (idx).m_background; -#endif - } + case Qt::Vertical: + return QString::number (section+1); + + default: + break; } return QVariant (); } - const std::string m_name; + QString subscript_expression (const QModelIndex& idx) const + { + if (! idx.isValid ()) + return ""; + + octave_map m = m_value.map_value (); + + string_vector fields = m.fieldnames (); + + return (QString ("(%1).%2") + .arg (idx.row () + 1) + .arg (QString::fromStdString (fields(idx.column ())))); + } - octave_value m_value; + octave_value value_at (const QModelIndex& idx) const + { + int row; + int col; + + if (! index_ok (idx, row, col)) + return octave_value (); + + octave_map m = m_value.map_value (); + + Cell cval = m.contents (col); + + return cval(row); + } +}; + +// 2-d struct array. Rows and columns index individual scalar structs. - octave_idx_type m_data_rows; - octave_idx_type m_data_cols; +class struct_model : public base_ve_model +{ +public: + + struct_model (const QString& expr, const octave_value& val) + : base_ve_model (expr, val) + { + // FIXME: should fill the window and expand on scrolling or + // resizing. + + m_display_rows = m_data_rows + 16; + m_display_cols = m_data_cols + 16; + } + + ~struct_model (void) = default; + + // No copying! - // Qt table widget limits the size to int. - int m_display_rows; - int m_display_cols; + struct_model (const struct_model&) = delete; + + struct_model& operator = (const struct_model&) = delete; + + QVariant edit_display (const QModelIndex& idx) const + { + int row; + int col; + + if (! index_ok (idx, row, col)) + return QVariant (); + + std::string str = m_value.edit_display (m_display_fmt, row, col); + return QString::fromStdString (str); + } + + bool requires_sub_editor (const QModelIndex& idx) const + { + int row; + int col; - QMap m_update_pending; + if (! index_ok (idx, row, col)) + return false; + + octave_map m = m_value.map_value (); + + return do_requires_sub_editor_sub (m(row,col)); + } + + char quote_char (const QModelIndex& idx) const + { + octave_value ov = value_at (idx); + + if (ov.is_string ()) + return get_quote_char (ov); + + return 0; + } - bool m_validity; + QString subscript_expression (const QModelIndex& idx) const + { + int row; + int col; + + if (! index_ok (idx, row, col)) + return ""; + + return (QString ("(%1,%2)") + .arg (row + 1) + .arg (col + 1)); + } + + octave_value value_at (const QModelIndex& idx) const + { + int row; + int col; - QString m_validtext; + if (! index_ok (idx, row, col)) + return octave_value (); + + octave_map m = m_value.map_value (); + + return m(row,col); + } +}; + +base_ve_model * +variable_editor_model::create (const QString& expr, const octave_value& val) +{ + // Choose specific model based on type of val. - QLabel *m_label; + if ((val.isnumeric () || val.islogical ()) && val.ndims () == 2) + return new numeric_model (expr, val); + else if (val.is_string () && (val.rows () == 1 || val.is_zero_by_zero ())) + return new string_model (expr, val); + else if (val.iscell ()) + return new cell_model (expr, val); + else if (val.isstruct ()) + { + if (val.numel () == 1) + return new scalar_struct_model (expr, val); + else if (val.ndims () == 2) + { + if (val.rows () == 1 || val.columns () == 1) + return new vector_struct_model (expr, val); + else + return new struct_model (expr, val); + } + } - float_display_format m_display_fmt; -}; + return new base_ve_model (expr, val); +} variable_editor_model::variable_editor_model (const QString& expr, const octave_value& val, QLabel *label, QObject *parent) - : QAbstractTableModel (parent), m_parent (parent), - m_d (new impl (expr, val, label)) + : QAbstractTableModel (parent), m_parent (parent), m_label (label), + rep (create (expr, val)) { connect (this, SIGNAL (user_error_signal (const QString&, const QString&)), this, SLOT (user_error (const QString&, const QString&))); @@ -610,98 +866,58 @@ variable_editor_model::variable_editor_m this, SLOT (data_error (const QString&))); connect (this, SIGNAL (maybe_resize_columns_signal (void)), - parent, SLOT (maybe_resize_columns (void))); + m_parent, SLOT (maybe_resize_columns (void))); + + m_label->setText (validtext ()); if (! type_is_editable (val)) - return; - - // Initializes everything. + { + type_edit_error (val); + return; + } - m_d->reset (val); - - beginInsertRows (QModelIndex (), 0, m_d->display_rows () - 1); + beginInsertRows (QModelIndex (), 0, display_rows () - 1); endInsertRows (); - beginInsertColumns (QModelIndex (), 0, m_d->display_columns () - 1); + beginInsertColumns (QModelIndex (), 0, display_columns () - 1); endInsertColumns (); } -variable_editor_model::~variable_editor_model (void) -{ - delete m_d; -} - -octave_value -variable_editor_model::value_at (const QModelIndex& idx) const -{ - return m_d->value_at (idx); -} - -int -variable_editor_model::column_width (void) const -{ - return m_d->column_width (); -} - -int -variable_editor_model::rowCount (const QModelIndex&) const -{ - return m_d->m_validity ? m_d->display_rows () : 1; -} - -int -variable_editor_model::columnCount (const QModelIndex&) const +bool +variable_editor_model::setData (const QModelIndex& idx, + const QVariant& v_user_input, int role) { - return m_d->m_validity ? m_d->display_columns () : 1; -} - -QVariant -variable_editor_model::data (const QModelIndex& idx, int role) const -{ - if (role == Qt::DisplayRole && update_pending (idx)) - return QVariant (update_pending_data (idx)); - - if (! m_d->m_validity) - { - if (idx.isValid ()) - { - if (role == Qt::DisplayRole) - return QVariant (QString ("Variable %d not found") - .arg (QString::fromStdString (m_d->m_name))); - } - - return QVariant (QString ("x")); - } - - if (idx.isValid ()) - return m_d->data (idx, role); - - // Invalid. - return QVariant (); -} - -bool -variable_editor_model::setData (const QModelIndex& idx, const QVariant& v, - int role) -{ - if (role != Qt::EditRole || v.type () != QVariant::String - || ! idx.isValid () || requires_sub_editor (idx)) + if (role != Qt::EditRole || v_user_input.type () != QVariant::String + || ! idx.isValid ()) return false; // Initially, set value to whatever the user entered. - int row = idx.row (); - int col = idx.column (); + QString user_input = v_user_input.toString (); + + set_update_pending (idx, user_input); + + std::ostringstream os; - QString vstr = v.toString (); + std::string nm = name (); + os << nm; + + QString tmp = subscript_expression (idx); + os << tmp.toStdString () << "="; - set_update_pending (idx, vstr); + char qc = quote_char (idx); + if (qc) + os << qc; + + os << user_input.toStdString (); - // Evaluate the string that the user entered. If that fails, we - // will restore previous value. + if (qc) + os << qc; - octave_link::post_event - (this, &variable_editor_model::set_data_oct, row, col, vstr.toStdString ()); + std::string expr = os.str (); + + octave_link::post_event + (this, &variable_editor_model::set_data_oct, nm, expr, idx); return true; } @@ -709,13 +925,10 @@ variable_editor_model::setData (const QM bool variable_editor_model::clear_content (const QModelIndex& idx) { - octave_idx_type data_rows = m_d->data_rows (); - octave_idx_type data_cols = m_d->data_columns (); - int row = idx.row (); int col = idx.column (); - if (row < data_rows && col < data_cols) + if (row < data_rows () && col < data_columns ()) return setData (idx, QVariant ("0")); return false; @@ -724,7 +937,7 @@ variable_editor_model::clear_content (co Qt::ItemFlags variable_editor_model::flags (const QModelIndex& idx) const { - if (! m_d->m_validity) + if (! is_valid ()) return Qt::NoItemFlags; Qt::ItemFlags retval = QAbstractTableModel::flags (idx); @@ -741,9 +954,9 @@ variable_editor_model::insertRows (int r // FIXME: cells? octave_link::post_event - (this, &variable_editor_model::eval_oct, m_d->m_name, + (this, &variable_editor_model::eval_oct, name (), QString ("%1 = [ %1(1:%2,:) ; zeros(%3, columns(%1)) ; %1(%2+%3:end,:) ]") - .arg (QString::fromStdString (m_d->m_name)) + .arg (QString::fromStdString (name ())) .arg (row) .arg (count) .toStdString ()); @@ -754,18 +967,18 @@ variable_editor_model::insertRows (int r bool variable_editor_model::removeRows (int row, int count, const QModelIndex&) { - if (row + count > m_d->data_rows ()) + if (row + count > data_rows ()) { qDebug () << "Tried to remove too many rows " - << m_d->data_rows () << " " + << data_rows () << " " << count << " (" << row << ")"; return false; } octave_link::post_event - (this, &variable_editor_model::eval_oct, m_d->m_name, + (this, &variable_editor_model::eval_oct, name (), QString ("%1(%2:%3, :) = []") - .arg (QString::fromStdString (m_d->m_name)) + .arg (QString::fromStdString (name ())) .arg (row) .arg (row + count) .toStdString ()); @@ -777,9 +990,9 @@ bool variable_editor_model::insertColumns (int col, int count, const QModelIndex&) { octave_link::post_event - (this, &variable_editor_model::eval_oct, m_d->m_name, + (this, &variable_editor_model::eval_oct, name (), QString ("%1 = [ %1(:,1:%2) ; zeros(rows(%1), %3) %1(:,%2+%3:end) ]") - .arg (QString::fromStdString (m_d->m_name)) + .arg (QString::fromStdString (name ())) .arg (col) .arg (count) .toStdString ()); @@ -790,18 +1003,18 @@ variable_editor_model::insertColumns (in bool variable_editor_model::removeColumns (int col, int count, const QModelIndex&) { - if (col + count > m_d->data_columns ()) + if (col + count > data_columns ()) { qDebug () << "Tried to remove too many cols " - << m_d->data_columns () << " " + << data_columns () << " " << count << " (" << col << ")"; return false; } octave_link::post_event - (this, &variable_editor_model::eval_oct, m_d->m_name, + (this, &variable_editor_model::eval_oct, name (), QString ("%1(:, %2:%3) = []") - .arg (QString::fromStdString (m_d->m_name)) + .arg (QString::fromStdString (name ())) .arg (col) .arg (col + count) .toStdString ()); @@ -810,70 +1023,120 @@ variable_editor_model::removeColumns (in } void -variable_editor_model::update_data_cache (void) +variable_editor_model::set_data_oct (const std::string& name, + const std::string& expr, + const QModelIndex& idx) { - octave_link::post_event - (this, &variable_editor_model::init_from_oct, m_d->m_name); -} + // INTERPRETER THREAD + + try + { + int parse_status = 0; + + octave::eval_string (expr, true, parse_status); + + octave_value val = retrieve_variable (name); -bool -variable_editor_model::requires_sub_editor (const QModelIndex& idx) const -{ - return m_d->requires_sub_editor (idx); + emit update_data_signal (val); + } + catch (octave::execution_exception&) + { + clear_update_pending (); + + evaluation_error (expr); + + // This will cause the data in the cell to be reset + // from the cached octave_value object. + + emit dataChanged (idx, idx); + } } void -variable_editor_model::set_update_pending (const QModelIndex& idx, - const QString& str) +variable_editor_model::init_from_oct (const std::string& name) { - m_d->set_update_pending (idx, str); -} + // INTERPRETER THREAD + + try + { + octave_value val = retrieve_variable (name); -bool -variable_editor_model::update_pending (const QModelIndex& idx) const -{ - return m_d->update_pending (idx); -} + emit update_data_signal (val); + } + catch (octave::execution_exception&) + { + QString msg = (QString ("variable '%1' is invalid or undefined") + .arg (QString::fromStdString (name))); -QString -variable_editor_model::update_pending_data (const QModelIndex& idx) const -{ - return m_d->update_pending_data (idx); + emit data_error_signal (msg); + } } void -variable_editor_model::clear_update_pending (void) +variable_editor_model::eval_oct (const std::string& name, + const std::string& expr) { - m_d->clear_update_pending (); -} + // INTERPRETER THREAD + + try + { + int parse_status = 0; -char -variable_editor_model::quote_char (int row, int col) const -{ - return m_d->quote_char (row, col); + octave::eval_string (expr, true, parse_status); + + init_from_oct (name); + } + catch (octave::execution_exception&) + { + evaluation_error (expr); + } } -QVariant -variable_editor_model::headerData (int section, Qt::Orientation orientation, - int role) const +// If the variable exists, load it into the data model. If it doesn't +// exist, flag the data model as referring to a nonexistent variable. +// This allows the variable to be opened before it is created. + +// This function should only be called within other functions that +// execute in the interpreter thread. It should also be called in a +// try-catch block that catches execution exceptions. + +octave_value +variable_editor_model::retrieve_variable (const std::string& x) { - return m_d->header_data (section, orientation, role); + // INTERPRETER THREAD + + std::string name = x; + + name = name.substr (0, name.find (".")); + + if (name.back () == ')' || name.back () == '}') + name = name.substr (0, name.find (name.back () == ')' ? "(" : "{")); + + if (symbol_exist (name, "var") > 0) + { + int parse_status = 0; + + return octave::eval_string (x, true, parse_status); + } + + return octave_value (); } -QString -variable_editor_model::subscript_expression (int row, int col) const +void +variable_editor_model::update_data_cache (void) { - return m_d->subscript_expression (row, col); + octave_link::post_event + (this, &variable_editor_model::init_from_oct, name ()); } -QString -variable_editor_model::subscript_expression (const QModelIndex& idx) const +void +variable_editor_model::evaluation_error (const std::string& expr) const { - return subscript_expression (idx.row (), idx.column ()); + emit user_error_signal ("Evaluation failed", + QString ("failed to evaluate expression: '%1'") + .arg (QString::fromStdString (expr))); } -// Private slots. - void variable_editor_model::user_error (const QString& title, const QString& msg) { @@ -886,7 +1149,7 @@ variable_editor_model::update_data (cons if (val.is_undefined ()) { QString msg = (QString ("variable '%1' is invalid or undefined") - .arg (QString::fromStdString (m_d->m_name))); + .arg (QString::fromStdString (name ()))); emit data_error_signal (msg); @@ -898,13 +1161,13 @@ variable_editor_model::update_data (cons // Add or remove rows and columns when the size changes. - int old_display_rows = m_d->display_rows (); - int old_display_cols = m_d->display_columns (); + int old_display_rows = display_rows (); + int old_display_cols = display_columns (); - m_d->reset (val); + reset (val); - int new_display_rows = m_d->display_rows (); - int new_display_cols = m_d->display_columns (); + int new_display_rows = display_rows (); + int new_display_cols = display_columns (); if (new_display_rows < old_display_rows) { @@ -938,128 +1201,26 @@ variable_editor_model::update_data (cons emit maybe_resize_columns_signal (); } -// Private. - -// val has to be copied! - void -variable_editor_model::set_data_oct (const int& row, const int& col, - const std::string& rhs) +variable_editor_model::data_error (const QString& msg) { - // INTERPRETER THREAD - - std::string expr; - - try - { - int parse_status = 0; - - std::ostringstream os; - - std::string name = m_d->m_name; - os << name; - - QString tmp = subscript_expression (row, col); - os << tmp.toStdString () << " = "; + invalidate (); - char qc = quote_char (row, col); - if (qc) - os << qc; - - os << rhs; - - if (qc) - os << qc; - - expr = os.str (); - - octave::eval_string (expr, true, parse_status); - - octave_value val = retrieve_variable (name); + m_label->setTextFormat (Qt::PlainText); - emit update_data_signal (val); - } - catch (octave::execution_exception&) - { - clear_update_pending (); + m_label->setText (msg); - evaluation_error (expr); - - // This will cause the data in the cell to be reset - // from the cached octave_value object. - - emit dataChanged (QAbstractTableModel::index (row, col), - QAbstractTableModel::index (row, col)); - } + dynamic_cast (m_parent)->setVisible (false); } void -variable_editor_model::init_from_oct (const std::string& name) +variable_editor_model::reset (const octave_value& val) { - // INTERPRETER THREAD - - try - { - octave_value val = retrieve_variable (name); - - m_d->m_validity = true; - - emit update_data_signal (val); - } - catch (octave::execution_exception&) - { - QString msg = (QString ("variable '%1' is invalid or undefined") - .arg (QString::fromStdString (name))); - - emit data_error_signal (msg); - } -} - -void -variable_editor_model::eval_oct (const std::string& name, const std::string& x) -{ - // INTERPRETER THREAD - - try - { - int parse_status = 0; - - octave::eval_string (x, true, parse_status); + base_ve_model *old_rep = rep; - init_from_oct (name); - } - catch (octave::execution_exception&) - { - evaluation_error (x); - } -} - -// If the variable exists, load it into the data model. If it doesn't -// exist, flag the data model as referring to a nonexistent variable. -// This allows the variable to be opened before it is created. - -// This function should only be called within other functions that -// execute in the interpreter thread. It should also be called in a -// try-catch block that catches execution exceptions. + rep = create (QString::fromStdString (name ()), val); -octave_value -variable_editor_model::retrieve_variable (const std::string& x) -{ - // INTERPRETER THREAD - - std::string name = x; - - if (x.back () == ')' || x.back () == '}') - name = x.substr (0, x.find (x.back () == ')' ? "(" : "{")); - - if (symbol_exist (name, "var") > 0) - { - int parse_status = 0; - - return octave::eval_string (x, true, parse_status); - } - - return octave_value (); + delete old_rep; } void @@ -1067,82 +1228,49 @@ variable_editor_model::invalidate (void) { beginResetModel (); - m_d->invalidate (); + reset (octave_value ()); endResetModel (); } void -variable_editor_model::data_error (const QString& msg) -{ - invalidate (); - - m_d->m_label->setTextFormat (Qt::PlainText); - - m_d->m_label->setText (msg); - - dynamic_cast (m_parent)->setVisible (false); -} - -void variable_editor_model::display_valid (void) { - m_d->m_label->setTextFormat (Qt::PlainText); + m_label->setTextFormat (Qt::PlainText); - m_d->m_label->setText (m_d->m_validtext); + m_label->setText (validtext ()); dynamic_cast (m_parent)->setVisible (true); } -bool -variable_editor_model::type_is_editable (const octave_value& val, - bool display_error) const +void +variable_editor_model::type_edit_error (const octave_value& val) const { - if ((val.isnumeric () || val.islogical () || val.iscell () - || val.isstruct ()) && val.ndims () == 2) - return true; + QString tname = QString::fromStdString (val.type_name ()); - if (val.is_string () && (val.rows () == 1 || val.is_zero_by_zero ())) - return true; + dim_vector dv = val.dims (); + QString dimstr = QString::fromStdString (dv.str ()); - if (display_error) - { - QString tname = QString::fromStdString (val.type_name ()); - - dim_vector dv = val.dims (); - QString dimstr = QString::fromStdString (dv.str ()); + // FIXME: we will probably want to impose a limit on the size of + // the output here... - // FIXME: we will probably want to impose a limit on the size of - // the output here... - - // FIXME: shouldn't octave_value::print be a constant method? - QString sep; - QString output; + // FIXME: shouldn't octave_value::print be a constant method? + QString sep; + QString output; - if (val.is_defined ()) - { - std::ostringstream buf; - octave_value tval = val; - tval.print (buf); - output = QString::fromStdString (buf.str ()); - if (! output.isEmpty ()) - sep = "\n\n"; - } - - emit data_error_signal (QString ("unable to edit [%1] '%2' objects%3%4") - .arg (dimstr) - .arg (tname) - .arg (sep) - .arg (output)); + if (val.is_defined ()) + { + std::ostringstream buf; + octave_value tval = val; + tval.print (buf); + output = QString::fromStdString (buf.str ()); + if (! output.isEmpty ()) + sep = "\n\n"; } - return false; + emit data_error_signal (QString ("unable to edit [%1] '%2' objects%3%4") + .arg (dimstr) + .arg (tname) + .arg (sep) + .arg (output)); } - -void -variable_editor_model::evaluation_error (const std::string& expr) const -{ - emit user_error_signal ("Evaluation failed", - QString ("failed to evaluate expression: '%1'") - .arg (QString::fromStdString (expr))); -} diff --git a/libgui/src/variable-editor-model.h b/libgui/src/variable-editor-model.h --- a/libgui/src/variable-editor-model.h +++ b/libgui/src/variable-editor-model.h @@ -26,22 +26,122 @@ along with Octave; see the file COPYING. #define variable_editor_model_h 1 #include +#include +#include #include "ov.h" +#include "pr-flt-fmt.h" class QLabel; class +base_ve_model +{ +public: + + base_ve_model (const QString &expr, const octave_value& val); + + virtual ~base_ve_model (void) = default; + + // No copying! + + base_ve_model (const base_ve_model&) = delete; + + base_ve_model& operator = (const base_ve_model&) = delete; + + std::string name (void) const; + + QString validtext (void) const; + + bool index_ok (const QModelIndex& idx, int& row, int& col) const; + + virtual octave_value value_at (const QModelIndex& idx) const; + + int column_width (void) const; + + int rowCount (const QModelIndex& = QModelIndex ()) const; + + int columnCount (const QModelIndex& = QModelIndex ()) const; + + QString edit_display_sub (const octave_value& elt) const; + + virtual QVariant edit_display (const QModelIndex& idx) const; + + QVariant data (const QModelIndex& idx, int role = Qt::DisplayRole) const; + + virtual bool requires_sub_editor (const QModelIndex& idx) const; + + void set_update_pending (const QModelIndex& idx, const QString& str); + + bool update_pending (const QModelIndex& idx) const; + + QString update_pending_data (const QModelIndex& idx) const; + + void clear_update_pending (void); + + virtual char quote_char (const QModelIndex& idx) const; + + virtual QVariant + header_data (int section, Qt::Orientation orientation, int role) const; + + // Return a subscript expression as a string that can be used to + // access a sub-element of a data structure. For example "{1,3}" + // for cell array element {1,3} or "(2,4)" for array element (2,4). + + virtual QString subscript_expression (const QModelIndex& idx) const; + + bool is_valid (void) const { return m_valid; } + + octave_idx_type data_rows (void) const { return m_data_rows; } + + octave_idx_type data_columns (void) const { return m_data_cols; } + + int display_rows (void) const { return m_display_rows; } + + int display_columns (void) const { return m_display_cols; } + + void reset (const octave_value& val); + +protected: + + std::string m_name; + + octave_value m_value; + + octave_idx_type m_data_rows; + octave_idx_type m_data_cols; + + // Qt table widget limits the size to int. + int m_display_rows; + int m_display_cols; + + QMap m_update_pending; + + bool m_valid; + + QString m_validtext; + + float_display_format m_display_fmt; +}; + +class variable_editor_model : public QAbstractTableModel { Q_OBJECT +private: + + static base_ve_model * create (const QString &expr, const octave_value& val); + public: variable_editor_model (const QString &expr, const octave_value& val, QLabel *label, QObject *p = nullptr); - ~variable_editor_model (void); + ~variable_editor_model (void) + { + delete rep; + } // No copying! @@ -49,16 +149,40 @@ public: variable_editor_model& operator = (const variable_editor_model&) = delete; - octave_value value_at (const QModelIndex& idx) const; + std::string name (void) const + { + return rep->name (); + } - int column_width (void) const; + QString validtext (void) const + { + return rep->validtext (); + } + + octave_value value_at (const QModelIndex& idx) const + { + return rep->value_at (idx); + } - // Display rows and columns, different from data rows and columns. - int rowCount (const QModelIndex& = QModelIndex ()) const; + int column_width (void) const + { + return rep->column_width (); + } + + int rowCount (const QModelIndex& idx = QModelIndex ()) const + { + return rep->rowCount (idx); + } - int columnCount (const QModelIndex& = QModelIndex ()) const; + int columnCount (const QModelIndex& idx = QModelIndex ()) const + { + return rep->columnCount (idx); + } - QVariant data (const QModelIndex& idx, int role = Qt::DisplayRole) const; + QVariant data (const QModelIndex& idx, int role = Qt::DisplayRole) const + { + return rep->data (idx, role); + } bool setData (const QModelIndex& idx, const QVariant& v, int role = Qt::EditRole); @@ -82,33 +206,55 @@ public: void update_data_cache (void); // Is cell at idx complex enough to require a sub editor? - bool requires_sub_editor (const QModelIndex& idx) const; - // If a sub editor is required, is it a standard type? - bool editor_type_matrix (const QModelIndex& idx) const; + bool requires_sub_editor (const QModelIndex& idx) const + { + return rep->requires_sub_editor (idx); + } - bool editor_type_string (const QModelIndex& idx) const; + void set_update_pending (const QModelIndex& idx, const QString& str) + { + rep->set_update_pending (idx, str); + } - void set_update_pending (const QModelIndex& idx, const QString& str); + bool update_pending (const QModelIndex& idx) const + { + return rep->update_pending (idx); + } - bool update_pending (const QModelIndex& idx) const; + QString update_pending_data (const QModelIndex& idx) const + { + return rep->update_pending_data (idx); + } - QString update_pending_data (const QModelIndex& idx) const; + void clear_update_pending (void) + { + rep->clear_update_pending (); + } - void clear_update_pending (void); - - char quote_char (int r, int c) const; + char quote_char (const QModelIndex& idx) const + { + return rep->quote_char (idx); + } QVariant - headerData (int section, Qt::Orientation orientation, int role) const; + headerData (int section, Qt::Orientation orientation, int role) const + { + if ((orientation == Qt::Vertical && section < data_rows ()) + || (orientation == Qt::Horizontal && section < data_columns ())) + return rep->header_data (section, orientation, role); + + return QVariant (); + } // Return a subscript expression as a string that can be used to // access a sub-element of a data structure. For example "{1,3}" // for cell array element {1,3} or "(2,4)" for array element (2,4). - QString subscript_expression (int r, int c) const; - - QString subscript_expression (const QModelIndex& idx) const; + QString subscript_expression (const QModelIndex& idx) const + { + return rep->subscript_expression (idx); + } signals: // private @@ -124,36 +270,62 @@ private slots: void update_data (const octave_value& val); - // Change the display if the variable does not exist. void data_error (const QString& msg); void user_error (const QString& title, const QString& msg); private: - void set_data_oct (const int& row, const int& col, const std::string& val); + QObject *m_parent; + + // Owned by parent, stored here for convenience. + QLabel *m_label; - void init_from_oct (const std::string& x); + base_ve_model *rep; + + void set_data_oct (const std::string& name, const std::string& expr, + const QModelIndex&); + + void init_from_oct (const std::string& str); void eval_oct (const std::string& name, const std::string& expr); - octave_value retrieve_variable (const std::string& x); + octave_value retrieve_variable (const std::string& name); + + bool is_valid (void) const + { + return rep->is_valid (); + } + + octave_idx_type data_rows (void) const + { + return rep->data_rows (); + } + + octave_idx_type data_columns (void) const + { + return rep->data_columns (); + } + + int display_rows (void) const + { + return rep->display_rows (); + } + + int display_columns (void) const + { + return rep->display_columns (); + } + + void reset (const octave_value& val); void invalidate (void); - // Change the display now that the variable exists void display_valid (void); - bool type_is_editable (const octave_value& val, - bool display_error = true) const; + void type_edit_error (const octave_value& val) const; void evaluation_error (const std::string& expr) const; - - QObject *m_parent; - - struct impl; - - impl *m_d; }; #endif