changeset 24660:a4ea36915e38

handle structure arrays in the variable editor * ov-struct.h, ov-struct.cc (octave_struct::edit_display, octave_scalar_struct::edit_display): New functions. * variable-editor-model.h, variable-editor-model.cc (variable_editor_model::impl::cell::init_data_and_sub_editor): New function. (get_rows_and_columns, variable_editor_model::impl, variable_editor_model::impl::quote_char, variable_editor_model::value_at, variable_editor_model::type_is_editable, variable_editor_model::subscript_expression): Handle structs. (variable_editor_model::impl::header_data, variable_editor_model::headerData): New functions.
author John W. Eaton <jwe@octave.org>
date Wed, 31 Jan 2018 16:18:24 -0500
parents 13d7fdaad391
children 02989d7d68dc
files libgui/src/variable-editor-model.cc libgui/src/variable-editor-model.h libinterp/octave-value/ov-struct.cc libinterp/octave-value/ov-struct.h
diffstat 4 files changed, 265 insertions(+), 17 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/src/variable-editor-model.cc	Wed Jan 31 12:41:36 2018 -0800
+++ b/libgui/src/variable-editor-model.cc	Wed Jan 31 16:18:24 2018 -0500
@@ -91,6 +91,32 @@
       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 ();
@@ -115,18 +141,41 @@
 
           octave_value ov = cval(r,c);
 
-          if ((ov.numel () == 1 && (ov.isnumeric () || ov.islogical ()))
-              || (ov.is_string () && (ov.rows () == 1 || ov.isempty ())))
+          init_data_and_sub_editor (val, cval(r,c), r, c);
+        }
+      else if (val.isstruct ())
+        {
+          if (val.numel () == 1)
             {
-              m_data = QString::fromStdString (ov.edit_display (r, c));
+              // Scalar struct.  Rows are fields, single column for
+              // values.
+
+              octave_scalar_map m = val.scalar_map_value ();
 
-              return;
+              init_data_and_sub_editor (val, m.contents (r), r, c);
+            }
+          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 (c);
+
+              init_data_and_sub_editor (val, cval(r), r, c);
             }
           else
-            m_requires_sub_editor = true;
+            {
+              // 2-d struct array.  Rows and columns index individual
+              // scalar structs.
+
+              octave_map m = val.map_value ();
+
+              init_data_and_sub_editor (val, m(r,c), r, c);
+            }
         }
-
-      m_data = QString::fromStdString (val.edit_display (r, c));
+      else
+        m_data = QString::fromStdString (val.edit_display (r, c));
     }
 
     cell (const QString& d, const QString& s, const QString& t,
@@ -135,6 +184,23 @@
         m_requires_sub_editor (rse), m_editor_type (edtype)
     { }
 
+    void init_data_and_sub_editor (const octave_value& val,
+                                   const octave_value& elt,
+                                   int r, int c)
+    {
+      if ((elt.numel () == 1 && (elt.isnumeric () || elt.islogical ()))
+          || (elt.is_string () && (elt.rows () == 1 || elt.isempty ())))
+        {
+          m_requires_sub_editor = false;
+          m_data = QString::fromStdString (elt.edit_display (0, 0));
+        }
+      else
+        {
+          m_requires_sub_editor = true;
+          m_data = QString::fromStdString (val.edit_display (r, c));
+        }
+    }
+
     bool m_defined;
 
     QVariant m_data;
@@ -190,17 +256,73 @@
       return get_quote_char (m_value);
     else if (m_value.iscell ())
       {
-        Cell cval = m_value.cell_value ();
+        octave_value ov = value_at (r, c);
 
-        octave_value ov = cval(r,c);
+        if (ov.is_string ())
+          return get_quote_char (ov);
+      }
+    else if (m_value.isstruct ())
+      {
+        octave_value ov = value_at (r, c);
 
-        if (ov.rows () == 1 || ov.is_zero_by_zero ())
+        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 (m_value.isstruct ())
+      {
+        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 ();
+
+                return QString::fromStdString (fields(section));
+              }
+          }
+        else if (m_value.rows () == 1 || m_value.columns () == 1)
+          {
+            // Vector struct.  Columns are fields, rows are values.
+
+            if (orientation == Qt::Horizontal)
+              {
+                octave_map m = m_value.map_value ();
+
+                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::number (section+1);
+          }
+      }
+
+    return QString::number (section+1);
+  }
+
   QString subscript_expression (int r, int c) const
   {
     if (m_value.is_string ())
@@ -209,6 +331,43 @@
       return (QString ("{%1, %2}")
               .arg (r + 1)
               .arg (c + 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 ();
+
+            return QString (".%1").arg (QString::fromStdString (fields(r)));
+          }
+        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 (r + 1)
+                    .arg (QString::fromStdString (fields(c))));
+          }
+        else
+          {
+            // 2-d struct array.  Rows and columns index individual
+            // scalar structs.
+
+            octave_map m = m_value.map_value ();
+
+            return (QString ("(%1,%2)")
+                    .arg (r + 1)
+                    .arg (c + 1));
+          }
+      }
     else
       return (QString ("(%1, %2)")
               .arg (r + 1)
@@ -233,12 +392,45 @@
 
   octave_value value_at (int r, int c) const
   {
-    if (! m_value.iscell ())
-      return octave_value ();
+    if (m_value.iscell ())
+      {
+        Cell cval = m_value.cell_value ();
+
+        return cval(r,c);
+      }
+    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 ();
 
-    Cell cval = m_value.cell_value ();
+            return m.contents (r);
+          }
+        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 (c);
 
-    return cval.elem (r, c);
+            return cval(r);
+          }
+        else
+          {
+            // 2-d struct array.  Rows and columns index individual
+            // scalar structs.
+
+            octave_map m = m_value.map_value ();
+
+            return m(r,c);
+          }
+      }
+    else
+      return octave_value ();
   }
 
   octave_value value_at (const QModelIndex& idx) const
@@ -593,6 +785,13 @@
   return m_d->quote_char (r, c);
 }
 
+QVariant
+variable_editor_model::headerData (int section, Qt::Orientation orientation,
+                                   int role) const
+{
+  return m_d->header_data (section, orientation, role);
+}
+
 QString
 variable_editor_model::subscript_expression (int r, int c) const
 {
@@ -841,9 +1040,11 @@
 variable_editor_model::type_is_editable (const octave_value& val,
                                          bool display_error) const
 {
-  if (((val.isnumeric () || val.islogical () || val.iscell ())
-       && val.ndims () == 2)
-      || (val.is_string () && (val.rows () == 1 || val.is_zero_by_zero ())))
+  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;
 
   if (display_error)
--- a/libgui/src/variable-editor-model.h	Wed Jan 31 12:41:36 2018 -0800
+++ b/libgui/src/variable-editor-model.h	Wed Jan 31 16:18:24 2018 -0500
@@ -94,6 +94,9 @@
 
   char quote_char (int r, int c) const;
 
+  QVariant
+  headerData (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).
--- a/libinterp/octave-value/ov-struct.cc	Wed Jan 31 12:41:36 2018 -0800
+++ b/libinterp/octave-value/ov-struct.cc	Wed Jan 31 16:18:24 2018 -0500
@@ -656,6 +656,33 @@
   return dims.ndims () == 2 && dims(0) == 1 && dims(1) == 1;
 }
 
+std::string
+octave_struct::edit_display (octave_idx_type r, octave_idx_type c) const
+{
+  octave_value val;
+  if (map.rows () == 1 || map.columns () == 1)
+    {
+      // Vector struct.  Columns are fields, rows are values.
+
+      Cell cval = map.contents (c);
+
+      val = cval(r);
+    }
+  else
+    {
+      // 2-d struct array.  Rows and columns index individual
+      // scalar structs.
+
+      val = map(r,c);
+    }
+
+  std::string tname = val.type_name ();
+  dim_vector dv = val.dims ();
+  std::string dimstr = dv.str ();
+  return "[" + dimstr + " " + tname + "]";
+}
+
+
 bool
 octave_struct::save_ascii (std::ostream& os)
 {
@@ -1331,6 +1358,19 @@
   return retval;
 }
 
+std::string
+octave_scalar_struct::edit_display (octave_idx_type r, octave_idx_type) const
+{
+  // Scalar struct.  Rows are fields, single column for values.
+
+  octave_value val = map.contents (r);
+
+  std::string tname = val.type_name ();
+  dim_vector dv = val.dims ();
+  std::string dimstr = dv.str ();
+  return "[" + dimstr + " " + tname + "]";
+}
+
 bool
 octave_scalar_struct::save_ascii (std::ostream& os)
 {
--- a/libinterp/octave-value/ov-struct.h	Wed Jan 31 12:41:36 2018 -0800
+++ b/libinterp/octave-value/ov-struct.h	Wed Jan 31 16:18:24 2018 -0500
@@ -131,6 +131,8 @@
 
   bool print_name_tag (std::ostream& os, const std::string& name) const;
 
+  std::string edit_display (octave_idx_type i, octave_idx_type j) const;
+
   bool save_ascii (std::ostream& os);
 
   bool load_ascii (std::istream& is);
@@ -252,6 +254,8 @@
 
   bool print_name_tag (std::ostream& os, const std::string& name) const;
 
+  std::string edit_display (octave_idx_type i, octave_idx_type j) const;
+
   bool save_ascii (std::ostream& os);
 
   bool load_ascii (std::istream& is);