GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
variable-editor-model.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2013-2018 John W. Eaton
4 Copyright (C) 2015 Michael Barnes
5 Copyright (C) 2013 RĂ¼diger Sonderfeld
6 
7 This file is part of Octave.
8 
9 Octave is free software: you can redistribute it and/or modify it
10 under the terms of the GNU General Public License as published by the
11 Free Software Foundation, either version 3 of the License, or (at your
12 option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 for more details.
18 
19 You should have received a copy of the GNU General Public License
20 along with Octave; see the file COPYING. If not, see
21 <https://www.gnu.org/licenses/>.
22 
23 */
24 
25 #ifdef HAVE_CONFIG_H
26 # include <config.h>
27 #endif
28 
29 #include <sstream>
30 
31 #include <QDebug>
32 #include <QLabel>
33 #include <QMap>
34 #include <QMessageBox>
35 #include <QString>
36 #include <QTableView>
37 
38 #include "octave-qt-link.h"
39 #include "variable-editor-model.h"
40 
41 #include "ov.h"
42 #include "parse.h"
43 #include "pr-flt-fmt.h"
44 #include "utils.h"
45 #include "variables.h"
46 
47 static bool
49 {
50  if ((val.isnumeric () || val.islogical ()) && val.numel () == 1)
51  return true;
52 
53  if (val.is_string () && (val.rows () == 1 || val.is_zero_by_zero ()))
54  return true;
55 
56  return false;
57 }
58 
59 static char
61 {
62  if (val.is_sq_string ())
63  return '\'';
64 
65  if (val.is_dq_string ())
66  return '"';
67 
68  return 0;
69 }
70 
73 {
74  // FIXME: make this limit configurable.
75 
76  return (val.numel () > 250000
77  ? float_display_format () : val.get_edit_display_format ());
78 }
79 
80 static bool
82 {
83  return (! ((elt.numel () == 1 && (elt.isnumeric () || elt.islogical ()))
84  || (elt.is_string () && (elt.rows () == 1 || elt.isempty ()))));
85 }
86 
87 namespace octave
88 {
89  base_ve_model::base_ve_model (const QString& expr, const octave_value& val)
90  : m_name (expr.toStdString ()),
91  m_value (val),
92  m_data_rows (m_value.rows ()),
93  m_data_cols (m_value.columns ()),
94  m_display_rows (m_data_rows),
95  m_display_cols (m_data_cols),
96  m_update_pending (),
97  m_valid (m_value.is_defined ()),
98  m_display_fmt (get_edit_display_format (m_value))
99  { }
100 
102  base_ve_model::name (void) const
103  {
104  return m_name;
105  }
106 
107  bool
108  base_ve_model::index_ok (const QModelIndex& idx, int& row, int& col) const
109  {
110  row = 0;
111  col = 0;
112 
113  if (! idx.isValid ())
114  return false;
115 
116  row = idx.row ();
117  col = idx.column ();
118 
119  return (row < data_rows () && col < data_columns ());
120  }
121 
122  int
124  {
125  int width = 0;
126 
129 
130  int rw = r_fmt.fw;
131  int iw = i_fmt.fw;
132 
133  if (rw > 0)
134  {
135  if (m_value.iscomplex ())
136  {
137  if (iw > 0)
138  width = rw + iw + 5;
139  }
140  else
141  width = rw + 2;
142  }
143 
144  return width;
145  }
146 
147  int
148  base_ve_model::rowCount (const QModelIndex&) const
149  {
150  return m_valid ? m_display_rows : 1;
151  }
152 
153  int
154  base_ve_model::columnCount (const QModelIndex&) const
155  {
156  return m_valid ? m_display_cols : 1;
157  }
158 
159  QString
160  base_ve_model::edit_display_sub (const octave_value& elt, int role) const
161  {
163 
164  if (cell_is_editable (elt))
165  {
167 
168  if (role == Qt::DisplayRole)
169  fmt = get_edit_display_format (elt);
170  else
171  fmt.set_precision (elt.is_single_type () ? 8 : 16);
172 
173  str = elt.edit_display (fmt, 0, 0);
174  }
175  else
176  {
177  dim_vector dv = elt.dims ();
178  str = "[" + dv.str () + " " + elt.class_name () + "]";
179  }
180 
181  return QString::fromStdString (str);
182  }
183 
184  QVariant
185  base_ve_model::edit_display (const QModelIndex& idx, int role) const
186  {
187  int row;
188  int col;
189 
190  if (! index_ok (idx, row, col))
191  return QVariant ();
192 
194  if (role == Qt::DisplayRole)
195  fmt = m_display_fmt;
196  else
197  fmt.set_precision (m_value.is_single_type () ? 8 : 16);
198 
199  std::string str = m_value.edit_display (fmt, row, col);
200 
201  return QString::fromStdString (str);
202  }
203 
204  QVariant
205  base_ve_model::data (const QModelIndex& idx, int role) const
206  {
207  if (idx.isValid () && role == Qt::DisplayRole && update_pending (idx))
208  return QVariant (update_pending_data (idx));
209 
210  if (! m_valid)
211  {
212  if (role == Qt::DisplayRole)
213  return QVariant (QString ("Variable %1 not found")
215 
216  return QVariant (QString ("x"));
217  }
218 
219  switch (role)
220  {
221  case Qt::DisplayRole:
222  case Qt::EditRole:
223  return edit_display (idx, role);
224  return edit_display (idx, role);
225 
226 #if 0
227  case Qt::StatusTipRole:
228  return elem (idx).m_status_tip;
229 
230  case Qt::ToolTipRole:
231  return elem (idx).m_tool_tip;
232 
233  case Qt::BackgroundRole:
234  return elem (idx).m_background;
235 #endif
236  }
237 
238  // Invalid.
239  return QVariant ();
240  }
241 
242  bool
243  base_ve_model::requires_sub_editor (const QModelIndex&) const
244  {
245  return false;
246  }
247 
248  void
249  base_ve_model::set_update_pending (const QModelIndex& idx, const QString& str)
250  {
251  m_update_pending[idx] = str;
252  }
253 
254  bool
255  base_ve_model::update_pending (const QModelIndex& idx) const
256  {
257  return m_update_pending.contains (idx);
258  }
259 
260  QString
261  base_ve_model::update_pending_data (const QModelIndex& idx) const
262  {
263  return m_update_pending[idx];
264  }
265 
266  void
268  {
269  return m_update_pending.clear ();
270  }
271 
272  char
273  base_ve_model::quote_char (const QModelIndex&) const
274  {
275  return 0;
276  }
277 
278  QVariant
279  base_ve_model::header_data (int section, Qt::Orientation, int role) const
280  {
281 
282  if (role != Qt::DisplayRole)
283  return QVariant ();
284 
285  return QString::number (section+1);
286  }
287 
288  QString
289  base_ve_model::subscript_expression (const QModelIndex&) const
290  {
291  return "";
292  }
293 
294  QString
296  {
297  QString lbl_txt = QString::fromStdString (m_name);
298 
299  if (m_value.is_defined ())
300  {
301  if (! lbl_txt.isEmpty ())
302  lbl_txt += " ";
303 
304  dim_vector dv = m_value.dims ();
305 
306  lbl_txt += ("["
308  + " "
310  + "]");
311  }
312  else
313  lbl_txt += " [undefined]";
314 
315  return lbl_txt;
316  }
317 
318  // Private slots.
319 
321  base_ve_model::value_at (const QModelIndex&) const
322  {
323  return octave_value ();
324  }
325 
327  {
328  public:
329 
330  numeric_model (const QString& expr, const octave_value& val)
331  : base_ve_model (expr, val)
332  {
333  // FIXME: should fill the window and expand on scrolling or
334  // resizing.
335 
338  }
339 
340  ~numeric_model (void) = default;
341 
342  // No copying!
343 
344  numeric_model (const numeric_model&) = delete;
345 
346  numeric_model& operator = (const numeric_model&) = delete;
347 
348  void maybe_resize_rows (int rows)
349  {
350  if (rows > m_display_rows)
351  m_display_rows = rows;
352  }
353 
354  void maybe_resize_columns (int cols)
355  {
356  if (cols > m_display_cols)
357  m_display_cols = cols;
358  }
359 
360  QVariant edit_display (const QModelIndex& idx, int role) const
361  {
362  int row;
363  int col;
364 
365  if (! index_ok (idx, row, col))
366  return QVariant ();
367 
369  if (role == Qt::DisplayRole)
370  fmt = m_display_fmt;
371  else
372  fmt.set_precision (m_value.is_single_type () ? 8 : 16);
373 
374  std::string str = m_value.edit_display (fmt, row, col);
375 
376  return QString::fromStdString (str);
377  }
378 
379  QString subscript_expression (const QModelIndex& idx) const
380  {
381  if (! idx.isValid ())
382  return "";
383 
384  return (QString ("(%1,%2)")
385  .arg (idx.row () + 1)
386  .arg (idx.column () + 1));
387  }
388  };
389 
391  {
392  public:
393 
394  string_model (const QString& expr, const octave_value& val)
395  : base_ve_model (expr, val)
396  {
397  m_data_rows = 1;
398  m_data_cols = 1;
399 
400  m_display_rows = 1;
401  m_display_cols = 1;
402  }
403 
404  ~string_model (void) = default;
405 
406  // No copying!
407 
408  string_model (const string_model&) = delete;
409 
410  string_model& operator = (const string_model&) = delete;
411 
412  QVariant edit_display (const QModelIndex&, int) const
413  {
414  // There isn't really a format for strings...
415 
417 
418  return QString::fromStdString (str);
419  }
420 
421  char quote_char (const QModelIndex&) const
422  {
423  return get_quote_char (m_value);
424  }
425  };
426 
427  class cell_model : public base_ve_model
428  {
429  public:
430 
431  cell_model (const QString& expr, const octave_value& val)
432  : base_ve_model (expr, val)
433  {
434  // FIXME: should fill the window and expand on scrolling or
435  // resizing.
436 
439  }
440 
441  ~cell_model (void) = default;
442 
443  // No copying!
444 
445  cell_model (const cell_model&) = delete;
446 
447  cell_model& operator = (const cell_model&) = delete;
448 
449  void maybe_resize_rows (int rows)
450  {
451  if (rows > m_display_rows)
452  m_display_rows = rows;
453  }
454 
455  void maybe_resize_columns (int cols)
456  {
457  if (cols > m_display_cols)
458  m_display_cols = cols;
459  }
460 
461  QVariant edit_display (const QModelIndex& idx, int role) const
462  {
463  int row;
464  int col;
465 
466  if (! index_ok (idx, row, col))
467  return QVariant ();
468 
469  Cell cval = m_value.cell_value ();
470 
471  return edit_display_sub (cval(row,col), role);
472  }
473 
474  bool requires_sub_editor (const QModelIndex& idx) const
475  {
476  int row;
477  int col;
478 
479  if (! index_ok (idx, row, col))
480  return false;
481 
482  Cell cval = m_value.cell_value ();
483 
484  return do_requires_sub_editor_sub (cval(row,col));
485  }
486 
487  char quote_char (const QModelIndex& idx) const
488  {
489  octave_value ov = value_at (idx);
490 
491  if (ov.is_string ())
492  return get_quote_char (ov);
493 
494  return 0;
495  }
496 
497  QString subscript_expression (const QModelIndex& idx) const
498  {
499  if (! idx.isValid ())
500  return "";
501 
502  return (QString ("{%1,%2}")
503  .arg (idx.row () + 1)
504  .arg (idx.column () + 1));
505  }
506 
507  octave_value value_at (const QModelIndex& idx) const
508  {
509  int row;
510  int col;
511 
512  if (! index_ok (idx, row, col))
513  return octave_value ();
514 
515  Cell cval = m_value.cell_value ();
516 
517  return cval(row,col);
518  }
519  };
520 
521  // Scalar struct. Rows are fields, single column for values.
522 
524  {
525  public:
526 
527  scalar_struct_model (const QString& expr, const octave_value& val)
528  : base_ve_model (expr, val)
529  {
530  // No extra cells. We currently don't allow new fields or
531  // additional values to be inserted. If we allow additional values,
532  // then the object becomes a vector structure and the display flips
533  // (see the vector struct model below). Do we want that?
534 
535  m_data_rows = val.nfields ();
536  m_data_cols = 1;
537 
539  m_display_cols = 1;
540  }
541 
542  ~scalar_struct_model (void) = default;
543 
544  // No copying!
545 
546  scalar_struct_model (const scalar_struct_model&) = delete;
547 
549 
550  QVariant edit_display (const QModelIndex& idx, int role) const
551  {
552  int row;
553  int col;
554 
555  if (! index_ok (idx, row, col))
556  return QVariant ();
557 
559 
560  return edit_display_sub (m.contents (row), role);
561  }
562 
563  bool requires_sub_editor (const QModelIndex& idx) const
564  {
565  int row;
566  int col;
567 
568  if (! index_ok (idx, row, col))
569  return false;
570 
572 
574  }
575 
576  char quote_char (const QModelIndex& idx) const
577  {
578  octave_value ov = value_at (idx);
579 
580  if (ov.is_string ())
581  return get_quote_char (ov);
582 
583  return 0;
584  }
585 
586  QVariant header_data (int section, Qt::Orientation orientation,
587  int role) const
588  {
589  if (role != Qt::DisplayRole)
590  return QVariant ();
591 
592  switch (orientation)
593  {
594  case Qt::Horizontal:
595  if (section < data_columns ())
596  return QString ("Values");
597  else
598  break;
599 
600  case Qt::Vertical:
601  if (section < data_rows ())
602  {
604 
606 
607  return QString::fromStdString (fields(section));
608  }
609  else
610  break;
611 
612  default:
613  break;
614  }
615 
616  return QVariant ();
617  }
618 
619  QString subscript_expression (const QModelIndex& idx) const
620  {
621  // Display size and data size match, so all valid indices should
622  // also be valid indices for the existing struct.
623 
624  int row;
625  int col;
626 
627  if (! index_ok (idx, row, col))
628  return "";
629 
631 
633 
634  return QString (".%1").arg (QString::fromStdString (fields(row)));
635  }
636 
637  octave_value value_at (const QModelIndex& idx) const
638  {
639  int row;
640  int col;
641 
642  if (! index_ok (idx, row, col))
643  return octave_value ();
644 
646 
647  return m.contents (row);
648  }
649  };
650 
652  {
653  public:
654 
655  display_only_model (const QString& expr, const octave_value& val)
656  : base_ve_model (expr, val)
657  {
658  m_data_rows = 1;
659  m_data_cols = 1;
660 
663  }
664 
665  ~display_only_model (void) = default;
666 
667  // No copying!
668 
669  display_only_model (const display_only_model&) = delete;
670 
672 
673  bool is_editable (void) const { return false; }
674 
675  QVariant edit_display (const QModelIndex&, int) const
676  {
677  if (m_value.is_undefined ())
678  return QVariant ();
679 
680  std::ostringstream buf;
681 
682  octave_value tval = m_value;
683 
684  tval.print_with_name (buf, m_name);
685 
686  return QString::fromStdString (buf.str ());
687  }
688 
689  QString make_description_text (void) const
690  {
691  return (QString ("unable to edit %1")
693  }
694  };
695 
696  // Vector struct. Columns are fields, rows are values.
697 
699  {
700  public:
701 
702  vector_struct_model (const QString& expr, const octave_value& val)
703  : base_ve_model (expr, val)
704  {
705  // FIXME: should fill the window vertically and expand on scrolling
706  // or resizing. No extra cells horizontally. New fields must be
707  // added specially.
708 
709  m_data_rows = val.numel ();
710  m_data_cols = val.nfields ();
711 
713  }
714 
715  ~vector_struct_model (void) = default;
716 
717  // No copying!
718 
719  vector_struct_model (const vector_struct_model&) = delete;
720 
722 
723  void maybe_resize_rows (int rows)
724  {
725  if (rows > m_display_rows)
726  m_display_rows = rows;
727  }
728 
729  QVariant edit_display (const QModelIndex& idx, int role) const
730  {
731  int row;
732  int col;
733 
734  if (! index_ok (idx, row, col))
735  return QVariant ();
736 
738 
739  Cell cval = m.contents (col);
740 
741  return edit_display_sub (cval(row), role);
742  }
743 
744  bool requires_sub_editor (const QModelIndex& idx) const
745  {
746  int row;
747  int col;
748 
749  if (! index_ok (idx, row, col))
750  return false;
751 
753 
754  Cell cval = m.contents (col);
755 
756  return do_requires_sub_editor_sub (cval(row));
757  }
758 
759  char quote_char (const QModelIndex& idx) const
760  {
761  octave_value ov = value_at (idx);
762 
763  if (ov.is_string ())
764  return get_quote_char (ov);
765 
766  return 0;
767  }
768 
769  QVariant header_data (int section, Qt::Orientation orientation,
770  int role) const
771  {
772  if (role != Qt::DisplayRole)
773  return QVariant ();
774 
775  switch (orientation)
776  {
777  case Qt::Horizontal:
778  if (section < data_columns ())
779  {
781 
783 
784  return QString::fromStdString (fields(section));
785  }
786  else
787  break;
788 
789  case Qt::Vertical:
790  if (section < data_rows ())
791  return QString::number (section+1);
792  else
793  break;
794 
795  default:
796  break;
797  }
798 
799  return QVariant ();
800  }
801 
802  QString subscript_expression (const QModelIndex& idx) const
803  {
804  if (! idx.isValid ())
805  return "";
806 
808 
810 
811  return (QString ("(%1).%2")
812  .arg (idx.row () + 1)
813  .arg (QString::fromStdString (fields(idx.column ()))));
814  }
815 
816  octave_value value_at (const QModelIndex& idx) const
817  {
818  int row;
819  int col;
820 
821  if (! index_ok (idx, row, col))
822  return octave_value ();
823 
825 
826  Cell cval = m.contents (col);
827 
828  return cval(row);
829  }
830  };
831 
832  // 2-d struct array. Rows and columns index individual scalar structs.
833 
835  {
836  public:
837 
838  struct_model (const QString& expr, const octave_value& val)
839  : base_ve_model (expr, val)
840  {
841  // FIXME: should fill the window and expand on scrolling or
842  // resizing.
843 
846  }
847 
848  ~struct_model (void) = default;
849 
850  // No copying!
851 
852  struct_model (const struct_model&) = delete;
853 
854  struct_model& operator = (const struct_model&) = delete;
855 
856  void maybe_resize_rows (int rows)
857  {
858  if (rows > m_display_rows)
859  m_display_rows = rows;
860  }
861 
862  void maybe_resize_columns (int cols)
863  {
864  if (cols > m_display_cols)
865  m_display_cols = cols;
866  }
867 
868  QVariant edit_display (const QModelIndex& idx, int) const
869  {
870  int row;
871  int col;
872 
873  if (! index_ok (idx, row, col))
874  return QVariant ();
875 
877  return QString::fromStdString (str);
878  }
879 
880  bool requires_sub_editor (const QModelIndex& idx) const
881  {
882  int row;
883  int col;
884 
885  if (! index_ok (idx, row, col))
886  return false;
887 
889 
890  return do_requires_sub_editor_sub (m(row,col));
891  }
892 
893  char quote_char (const QModelIndex& idx) const
894  {
895  octave_value ov = value_at (idx);
896 
897  if (ov.is_string ())
898  return get_quote_char (ov);
899 
900  return 0;
901  }
902 
903  QString subscript_expression (const QModelIndex& idx) const
904  {
905  int row;
906  int col;
907 
908  if (! index_ok (idx, row, col))
909  return "";
910 
911  return (QString ("(%1,%2)")
912  .arg (row + 1)
913  .arg (col + 1));
914  }
915 
916  octave_value value_at (const QModelIndex& idx) const
917  {
918  int row;
919  int col;
920 
921  if (! index_ok (idx, row, col))
922  return octave_value ();
923 
925 
926  return m(row,col);
927  }
928  };
929 
930  base_ve_model *
931  variable_editor_model::create (const QString& expr, const octave_value& val)
932  {
933  // Choose specific model based on type of val.
934 
935  if ((val.isnumeric () || val.islogical ()) && val.ndims () == 2)
936  return new numeric_model (expr, val);
937  else if (val.is_string () && (val.rows () == 1 || val.is_zero_by_zero ()))
938  return new string_model (expr, val);
939  else if (val.iscell ())
940  return new cell_model (expr, val);
941  else if (val.isstruct ())
942  {
943  if (val.numel () == 1)
944  return new scalar_struct_model (expr, val);
945  else if (val.ndims () == 2)
946  {
947  if (val.rows () == 1 || val.columns () == 1)
948  return new vector_struct_model (expr, val);
949  else
950  return new struct_model (expr, val);
951  }
952  }
953 
954  return new display_only_model (expr, val);
955  }
956 
958  const octave_value& val,
959  QObject *parent)
960  : QAbstractTableModel (parent), rep (create (expr, val))
961  {
963 
964  connect (this, SIGNAL (user_error_signal (const QString&, const QString&)),
965  this, SLOT (user_error (const QString&, const QString&)));
966 
967  connect (this, SIGNAL (update_data_signal (const octave_value&)),
968  this, SLOT (update_data (const octave_value&)));
969 
970  connect (this, SIGNAL (data_error_signal (const QString&)),
971  this, SLOT (data_error (const QString&)));
972 
973  if (is_editable ())
974  {
975  beginInsertRows (QModelIndex (), 0, display_rows () - 1);
976  endInsertRows ();
977 
978  beginInsertColumns (QModelIndex (), 0, display_columns () - 1);
979  endInsertColumns ();
980  }
981  }
982 
983  bool
984  variable_editor_model::setData (const QModelIndex& idx,
985  const QVariant& v_user_input, int role)
986  {
987  if (role != Qt::EditRole || ! v_user_input.canConvert (QVariant::String)
988  || ! idx.isValid ())
989  return false;
990 
991  // Initially, set value to whatever the user entered.
992 
993  QString user_input = v_user_input.toString ();
994 
995  char qc = quote_char (idx);
996 
997  // FIXME: maybe we need a better way to ask whether empty input is
998  // valid than to rely on whether there is a quote character (meaning
999  // we are editing a character string)?
1000  if (user_input.isEmpty () && ! qc)
1001  return false;
1002 
1003  set_update_pending (idx, user_input);
1004 
1005  std::ostringstream os;
1006 
1007  std::string nm = name ();
1008  os << nm;
1009 
1010  QString tmp = subscript_expression (idx);
1011  os << tmp.toStdString () << "=";
1012 
1013  if (qc)
1014  os << qc;
1015 
1016  os << user_input.toStdString ();
1017 
1018  if (qc)
1019  os << qc;
1020 
1021  std::string expr = os.str ();
1022 
1023  octave_link::post_event<variable_editor_model, std::string, std::string, QModelIndex>
1024  (this, &variable_editor_model::set_data_oct, nm, expr, idx);
1025 
1026  return true;
1027  }
1028 
1029  bool
1030  variable_editor_model::clear_content (const QModelIndex& idx)
1031  {
1032  int row = idx.row ();
1033  int col = idx.column ();
1034 
1035  if (row < data_rows () && col < data_columns ())
1036  return setData (idx, QVariant ("0"));
1037 
1038  return false;
1039  }
1040 
1041  Qt::ItemFlags
1042  variable_editor_model::flags (const QModelIndex& idx) const
1043  {
1044  if (! is_valid ())
1045  return Qt::NoItemFlags;
1046 
1047  Qt::ItemFlags retval = QAbstractTableModel::flags (idx);
1048 
1049  if (! requires_sub_editor (idx))
1050  retval |= Qt::ItemIsEditable;
1051 
1052  return retval;
1053  }
1054 
1055  bool
1056  variable_editor_model::insertRows (int row, int count, const QModelIndex&)
1057  {
1058  // FIXME: cells?
1059 
1060  octave_link::post_event <variable_editor_model, std::string, std::string>
1062  QString ("%1 = [ %1(1:%2,:) ; zeros(%3, columns(%1)) ; %1(%2+%3:end,:) ]")
1063  .arg (QString::fromStdString (name ()))
1064  .arg (row)
1065  .arg (count)
1066  .toStdString ());
1067 
1068  return true;
1069  }
1070 
1071  bool
1072  variable_editor_model::removeRows (int row, int count, const QModelIndex&)
1073  {
1074  if (row + count > data_rows ())
1075  {
1076  qDebug () << "Tried to remove too many rows "
1077  << data_rows () << " "
1078  << count << " (" << row << ")";
1079  return false;
1080  }
1081 
1082  octave_link::post_event <variable_editor_model, std::string, std::string>
1084  QString ("%1(%2:%3, :) = []")
1085  .arg (QString::fromStdString (name ()))
1086  .arg (row)
1087  .arg (row + count)
1088  .toStdString ());
1089 
1090  return true;
1091  }
1092 
1093  bool
1094  variable_editor_model::insertColumns (int col, int count, const QModelIndex&)
1095  {
1096  octave_link::post_event <variable_editor_model, std::string, std::string>
1098  QString ("%1 = [ %1(:,1:%2) ; zeros(rows(%1), %3) %1(:,%2+%3:end) ]")
1099  .arg (QString::fromStdString (name ()))
1100  .arg (col)
1101  .arg (count)
1102  .toStdString ());
1103 
1104  return true;
1105  }
1106 
1107  bool
1108  variable_editor_model::removeColumns (int col, int count, const QModelIndex&)
1109  {
1110  if (col + count > data_columns ())
1111  {
1112  qDebug () << "Tried to remove too many cols "
1113  << data_columns () << " "
1114  << count << " (" << col << ")";
1115  return false;
1116  }
1117 
1118  octave_link::post_event <variable_editor_model, std::string, std::string>
1120  QString ("%1(:, %2:%3) = []")
1121  .arg (QString::fromStdString (name ()))
1122  .arg (col)
1123  .arg (col + count)
1124  .toStdString ());
1125 
1126  return true;
1127  }
1128 
1129  void
1131  const std::string& expr,
1132  const QModelIndex& idx)
1133  {
1134  // INTERPRETER THREAD
1135 
1136  try
1137  {
1138  int parse_status = 0;
1139 
1140  eval_string (expr, true, parse_status);
1141 
1143 
1144  emit update_data_signal (val);
1145  }
1146  catch (execution_exception&)
1147  {
1149 
1150  evaluation_error (expr);
1151 
1152  // This will cause the data in the cell to be reset
1153  // from the cached octave_value object.
1154 
1155  emit dataChanged (idx, idx);
1156  }
1157  }
1158 
1159  void
1161  {
1162  // INTERPRETER THREAD
1163 
1164  try
1165  {
1167 
1168  emit update_data_signal (val);
1169  }
1170  catch (execution_exception&)
1171  {
1172  QString msg = (QString ("variable '%1' is invalid or undefined")
1173  .arg (QString::fromStdString (name)));
1174 
1175  emit data_error_signal (msg);
1176  }
1177  }
1178 
1179  void
1181  const std::string& expr)
1182  {
1183  // INTERPRETER THREAD
1184 
1185  try
1186  {
1187  int parse_status = 0;
1188 
1189  eval_string (expr, true, parse_status);
1190 
1191  init_from_oct (name);
1192  }
1193  catch (execution_exception&)
1194  {
1195  evaluation_error (expr);
1196  }
1197  }
1198 
1199  // If the variable exists, load it into the data model. If it doesn't
1200  // exist, flag the data model as referring to a nonexistent variable.
1201  // This allows the variable to be opened before it is created.
1202 
1203  // This function should only be called within other functions that
1204  // execute in the interpreter thread. It should also be called in a
1205  // try-catch block that catches execution exceptions.
1206 
1207  octave_value
1209  {
1210  // INTERPRETER THREAD
1211 
1212  std::string name = x;
1213 
1214  name = name.substr (0, name.find ("."));
1215 
1216  if (name.back () == ')' || name.back () == '}')
1217  name = name.substr (0, name.find (name.back () == ')' ? "(" : "{"));
1218 
1219  if (symbol_exist (name, "var") > 0)
1220  {
1221  int parse_status = 0;
1222 
1223  return eval_string (x, true, parse_status);
1224  }
1225 
1226  return octave_value ();
1227  }
1228 
1229  void
1231  {
1232  emit user_error_signal ("Evaluation failed",
1233  QString ("failed to evaluate expression: '%1'")
1234  .arg (QString::fromStdString (expr)));
1235  }
1236 
1237  void
1238  variable_editor_model::user_error (const QString& title, const QString& msg)
1239  {
1240  QMessageBox::critical (nullptr, title, msg);
1241  }
1242 
1243  void
1245  {
1248  }
1249 
1250  void
1252  {
1253  if (val.is_undefined ())
1254  {
1255  QString msg = (QString ("variable '%1' is invalid or undefined")
1256  .arg (QString::fromStdString (name ())));
1257 
1258  emit data_error_signal (msg);
1259 
1260  return;
1261  }
1262 
1263  // Add or remove rows and columns when the size changes.
1264 
1265  int old_rows = display_rows ();
1266  int old_cols = display_columns ();
1267 
1268  reset (val);
1269 
1270  int new_rows = display_rows ();
1271  int new_cols = display_columns ();
1272 
1273  if (new_rows != old_rows || new_cols != old_cols)
1274  change_display_size (old_rows, old_cols, new_rows, new_cols);
1275 
1276  // Even if the size doesn't change, we still need to update here
1277  // because the data may have changed.
1278 
1279  emit dataChanged (QAbstractTableModel::index (0, 0),
1280  QAbstractTableModel::index (new_rows-1, new_cols-1));
1281 
1283  }
1284 
1285  void
1286  variable_editor_model::change_display_size (int old_rows, int old_cols,
1287  int new_rows, int new_cols)
1288  {
1289  if (new_rows < old_rows)
1290  {
1291  beginRemoveRows (QModelIndex (), new_rows, old_rows-1);
1292  endRemoveRows ();
1293  }
1294  else if (new_rows > old_rows)
1295  {
1296  beginInsertRows (QModelIndex (), old_rows, new_rows-1);
1297  endInsertRows ();
1298  }
1299 
1300  if (new_cols < old_cols)
1301  {
1302  beginRemoveColumns (QModelIndex (), new_cols, old_cols-1);
1303  endRemoveColumns ();
1304  }
1305  else if (new_cols > old_cols)
1306  {
1307  beginInsertColumns (QModelIndex (), old_cols, new_cols-1);
1308  endInsertColumns ();
1309  }
1310  }
1311 
1312  void
1314  {
1315  int old_rows = display_rows ();
1316  int old_cols = display_columns ();
1317 
1318  rep->maybe_resize_rows (rows);
1319 
1320  int new_rows = display_rows ();
1321  int new_cols = display_columns ();
1322 
1323  if (new_rows != old_rows)
1324  change_display_size (old_rows, old_cols, new_rows, new_cols);
1325  }
1326 
1327  void
1329  {
1330  int old_rows = display_rows ();
1331  int old_cols = display_columns ();
1332 
1333  rep->maybe_resize_columns (cols);
1334 
1335  int new_rows = display_rows ();
1336  int new_cols = display_columns ();
1337 
1338  if (new_cols != old_cols)
1339  change_display_size (old_rows, old_cols, new_rows, new_cols);
1340  }
1341 
1342  void
1344  {
1345  invalidate ();
1346 
1347  update_description (msg);
1348  }
1349 
1350  void
1352  {
1353  base_ve_model *old_rep = rep;
1354 
1356 
1357  delete old_rep;
1358 
1359  update_description ();
1360 
1361  emit set_editable_signal (is_editable ());
1362  }
1363 
1364  void
1366  {
1367  beginResetModel ();
1368 
1369  reset (octave_value ());
1370 
1371  endResetModel ();
1372  }
1373 
1374  void
1375  variable_editor_model::update_description (const QString& description)
1376  {
1377  emit description_changed (description.isEmpty ()
1378  ? make_description_text () : description);
1379  }
1380 
1381  void
1382  variable_editor_model::double_click (const QModelIndex& idx)
1383  {
1384  if (requires_sub_editor (idx))
1385  {
1386  QString name = QString::fromStdString(rep->name ());
1388  value_at (idx));
1389  }
1390  }
1391 }
bool requires_sub_editor(const QModelIndex &idx) const
~vector_struct_model(void)=default
string_vector fieldnames(void) const
Definition: oct-map.h:216
string_model(const QString &expr, const octave_value &val)
void update_data_signal(const octave_value &val)
void eval_oct(const std::string &name, const std::string &expr)
std::string str(char sep='x') const
Definition: dim-vector.cc:73
cell_model(const QString &expr, const octave_value &val)
scalar structure containing the fields
Definition: ov-struct.cc:1736
scalar_struct_model(const QString &expr, const octave_value &val)
Definition: Cell.h:37
void description_changed(const QString &description)
octave_value value_at(const QModelIndex &idx) const
bool removeRows(int row, int count, const QModelIndex &parent=QModelIndex())
QVariant edit_display(const QModelIndex &idx, int) const
void double_click(const QModelIndex &idx)
QString subscript_expression(const QModelIndex &idx) const
char quote_char(const QModelIndex &idx) const
bool isempty(void) const
Definition: ov.h:529
void data_error_signal(const QString &name) const
octave_idx_type data_columns(void) const
virtual QString make_description_text(void) const
bool islogical(void) const
Definition: ov.h:696
octave_map map_value(void) const
string_vector fieldnames(void) const
Definition: oct-map.h:339
void print_with_name(std::ostream &os, const std::string &name) const
Definition: ov.h:1274
variable_editor_model(const QString &expr, const octave_value &val, QObject *parent=nullptr)
int columnCount(const QModelIndex &=QModelIndex()) const
QString subscript_expression(const QModelIndex &idx) const
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
~cell_model(void)=default
char quote_char(const QModelIndex &idx) const
bool clear_content(const QModelIndex &idx)
for fields that display a single number
Definition: time.cc:441
bool index_ok(const QModelIndex &idx, int &row, int &col) const
QVariant edit_display(const QModelIndex &, int) const
static bool cell_is_editable(const octave_value &val)
virtual QVariant header_data(int section, Qt::Orientation orientation, int role) const
bool setData(const QModelIndex &idx, const QVariant &v, int role=Qt::EditRole)
bool requires_sub_editor(const QModelIndex &idx) const
base_ve_model(const QString &expr, const octave_value &val)
float_format imag_format(void) const
Definition: pr-flt-fmt.h:168
QString edit_display_sub(const octave_value &elt, int role) const
QString fromStdString(const std::string &s)
bool requires_sub_editor(const QModelIndex &idx) const
char quote_char(const QModelIndex &idx) const
~numeric_model(void)=default
display_only_model & operator=(const display_only_model &)=delete
~display_only_model(void)=default
bool insertRows(int row, int count, const QModelIndex &parent=QModelIndex())
bool is_defined(void) const
Definition: ov.h:523
QMap< QModelIndex, QString > m_update_pending
bool requires_sub_editor(const QModelIndex &idx) const
QString make_description_text(void) const
virtual void maybe_resize_columns(int)
void edit_variable_signal(const QString &name, const octave_value &val)
QString subscript_expression(const QModelIndex &idx) const
float_format real_format(void) const
Definition: pr-flt-fmt.h:166
QString subscript_expression(const QModelIndex &idx) const
char quote_char(const QModelIndex &) const
octave_value arg
Definition: pr-output.cc:3244
numeric_model & operator=(const numeric_model &)=delete
static char get_quote_char(const octave_value &val)
numeric_model(const QString &expr, const octave_value &val)
string_model & operator=(const string_model &)=delete
display_only_model(const QString &expr, const octave_value &val)
void set_update_pending(const QModelIndex &idx, const QString &str)
void init_from_oct(const std::string &str)
bool update_pending(const QModelIndex &idx) const
void set_data_oct(const std::string &name, const std::string &expr, const QModelIndex &)
virtual char quote_char(const QModelIndex &idx) const
nd deftypefn *std::string name
Definition: sysdep.cc:647
OCTAVE_EXPORT octave_value_list isdir nd deftypefn *std::string nm
Definition: utils.cc:975
void user_error(const QString &title, const QString &msg)
virtual octave_value value_at(const QModelIndex &idx) const
void change_display_size(int old_rows, int old_cols, int new_rows, int new_cols)
scalar_struct_model & operator=(const scalar_struct_model &)=delete
OCTINTERP_API octave_value_list eval_string(const std::string &, bool silent, int &parse_status, int nargout)
octave_idx_type numel(const octave_value_list &idx)
Definition: ov.h:412
static base_ve_model * create(const QString &expr, const octave_value &val)
float_display_format m_display_fmt
octave_value value_at(const QModelIndex &idx) const
void maybe_resize_columns(int cols)
octave_idx_type data_rows(void) const
octave_value value_at(const QModelIndex &idx) const
QString update_pending_data(const QModelIndex &idx) const
bool is_single_type(void) const
Definition: ov.h:651
QVariant data(const QModelIndex &idx, int role=Qt::DisplayRole) const
std::string str
Definition: hash.cc:118
char quote_char(const QModelIndex &idx) const
dim_vector dims(void) const
Definition: ov.h:469
static int elem
Definition: __contourc__.cc:47
QVariant header_data(int section, Qt::Orientation orientation, int role) const
octave_idx_type rows(void) const
Definition: ov.h:472
double tmp
Definition: data.cc:6252
octave_value retval
Definition: data.cc:6246
QVariant edit_display(const QModelIndex &idx, int role) const
vector_struct_model(const QString &expr, const octave_value &val)
const Cell & contents(const_iterator p) const
Definition: oct-map.h:317
virtual void maybe_resize_rows(int)
QVariant header_data(int section, Qt::Orientation orientation, int role) const
QVariant edit_display(const QModelIndex &, int) const
std::string class_name(void) const
Definition: ov.h:1291
Qt::ItemFlags flags(const QModelIndex &idx) const
static bool do_requires_sub_editor_sub(const octave_value &elt)
octave_value value_at(const QModelIndex &idx) const
octave_idx_type data_rows(void) const
void set_update_pending(const QModelIndex &idx, const QString &str)
~scalar_struct_model(void)=default
cell_model & operator=(const cell_model &)=delete
struct_model(const QString &expr, const octave_value &val)
QString subscript_expression(const QModelIndex &idx) const
return octave_value(v1.char_array_value() . concat(v2.char_array_value(), ra_idx),((a1.is_sq_string()||a2.is_sq_string()) ? '\'' :'"'))
octave_scalar_map scalar_map_value(void) const
octave_value value_at(const QModelIndex &idx) const
void evaluation_error(const std::string &expr) const
const octave_value & contents(const_iterator p) const
Definition: oct-map.h:194
QVariant edit_display(const QModelIndex &idx, int role) const
bool is_undefined(void) const
Definition: ov.h:526
static int symbol_exist(octave::interpreter &interp, const std::string &name, const std::string &type="any")
Definition: variables.cc:371
std::string edit_display(const float_display_format &fmt, octave_idx_type i, octave_idx_type j) const
Definition: ov.h:1281
int rowCount(const QModelIndex &=QModelIndex()) const
bool requires_sub_editor(const QModelIndex &idx) const
octave_idx_type data_columns(void) const
QString make_description_text(void) const
virtual bool requires_sub_editor(const QModelIndex &idx) const
QString subscript_expression(const QModelIndex &idx) const
void maybe_resize_columns(int cols)
void update_data(const octave_value &val)
bool iscomplex(void) const
Definition: ov.h:710
QVariant edit_display(const QModelIndex &idx, int role) const
std::string name(void) const
octave_value retrieve_variable(const std::string &name)
bool is_string(void) const
Definition: ov.h:577
void maybe_resize_rows(int rows)
bool removeColumns(int column, int count, const QModelIndex &parent=QModelIndex())
QVariant edit_display(const QModelIndex &idx, int role) const
~struct_model(void)=default
void user_error_signal(const QString &title, const QString &msg) const
virtual QString subscript_expression(const QModelIndex &idx) const
char quote_char(const QModelIndex &idx) const
struct_model & operator=(const struct_model &)=delete
Vector representing the dimensions (size) of an Array.
Definition: dim-vector.h:87
std::string toStdString(const QString &s)
void set_precision(int prec)
Definition: pr-flt-fmt.h:170
If this string is the system will ring the terminal sometimes it is useful to be able to print the original representation of the string
Definition: utils.cc:888
dim_vector dv
Definition: sub2ind.cc:263
~string_model(void)=default
void update_description(const QString &description=QString())
octave::stream os
Definition: file-io.cc:627
Cell cell_value(void) const
bool isnumeric(void) const
Definition: ov.h:723
bool insertColumns(int column, int count, const QModelIndex &parent=QModelIndex())
void data_error(const QString &msg)
void reset(const octave_value &val)
where the brackets indicate optional arguments and and character or cell array For character arrays the conversion is repeated for every row
Definition: str2double.cc:342
F77_RET_T const F77_REAL const F77_REAL F77_REAL &F77_RET_T const F77_DBLE const F77_DBLE F77_DBLE &F77_RET_T const F77_DBLE F77_DBLE &F77_RET_T const F77_REAL F77_REAL &F77_RET_T const F77_DBLE * x
vector_struct_model & operator=(const vector_struct_model &)=delete
virtual QVariant edit_display(const QModelIndex &idx, int role) const
static float_display_format get_edit_display_format(const octave_value &val)