GNU Octave  4.2.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Pages
workspace-view.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2013-2017 John W. Eaton
4 Copyright (C) 2011-2016 Jacob Dawid
5 
6 This file is part of Octave.
7 
8 Octave is free software; you can redistribute it and/or modify it
9 under the terms of the GNU General Public License as published by the
10 Free Software Foundation; either version 3 of the License, or (at your
11 option) any later version.
12 
13 Octave is distributed in the hope that it will be useful, but WITHOUT
14 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with Octave; see the file COPYING. If not, see
20 <http://www.gnu.org/licenses/>.
21 
22 */
23 
24 #if defined (HAVE_CONFIG_H)
25 # include "config.h"
26 #endif
27 
28 #include <QInputDialog>
29 #include <QApplication>
30 #include <QClipboard>
31 #include <QMessageBox>
32 #include <QLineEdit>
33 #include <QHeaderView>
34 #include <QHBoxLayout>
35 #include <QVBoxLayout>
36 #include <QPushButton>
37 #include <QMenu>
38 #include <QLabel>
39 #include <QCompleter>
40 #include <QSignalMapper>
41 
42 #include "workspace-view.h"
43 #include "resource-manager.h"
44 #include "symtab.h"
45 
47  : octave_dock_widget (p), view (new QTableView (this))
48 {
49  setObjectName ("WorkspaceView");
50  setWindowIcon (QIcon (":/actions/icons/logo.png"));
51  set_title (tr ("Workspace"));
52  setStatusTip (tr ("View the variables in the active workspace."));
53 
54  _filter = new QComboBox (this);
55  _filter->setToolTip (tr ("Enter text to filter the workspace"));
56  _filter->setEditable (true);
57  _filter->setMaxCount (MaxFilterHistory);
58  _filter->setInsertPolicy (QComboBox::NoInsert);
59  _filter->setSizeAdjustPolicy (
60  QComboBox::AdjustToMinimumContentsLengthWithIcon);
61  QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);
62  _filter->setSizePolicy (sizePol);
63  _filter->completer ()->setCaseSensitivity (Qt::CaseSensitive);
64 
65  QLabel *filter_label = new QLabel (tr ("Filter"));
66 
67  _filter_checkbox = new QCheckBox ();
68 
69  view->setWordWrap (false);
70  view->setContextMenuPolicy (Qt::CustomContextMenu);
71  view->setShowGrid (false);
72  (view->verticalHeader) ()->hide ();
73  view->setAlternatingRowColors (true);
75 
76  // Set an empty widget, so we can assign a layout to it.
77  setWidget (new QWidget (this));
78 
79  // Create the layouts
80  _filter_widget = new QWidget (this);
81  QHBoxLayout *filter_layout = new QHBoxLayout ();
82 
83  filter_layout->addWidget (filter_label);
84  filter_layout->addWidget (_filter_checkbox);
85  filter_layout->addWidget (_filter);
86  filter_layout->setMargin(0);
87  _filter_widget->setLayout (filter_layout);
88 
89  QVBoxLayout *ws_layout = new QVBoxLayout ();
90  ws_layout->addWidget (_filter_widget);
91  ws_layout->addWidget (view);
92 
93  QSettings *settings = resource_manager::get_settings ();
94 
95  if (settings)
96  {
97  _filter_shown = settings->value ("workspaceview/filter_shown",true).toBool();
98  _filter_widget->setVisible (_filter_shown);
99 
100  ws_layout->setMargin (2);
101 
102  // Set the empty widget to have our layout.
103  widget ()->setLayout (ws_layout);
104 
105  // Initialize collapse/expand state of the workspace subcategories.
106 
107  //enable sorting (setting column and order after model was set)
108  view->setSortingEnabled (true);
109  // Initialize column order and width of the workspace
110  view->horizontalHeader ()->restoreState (settings->value ("workspaceview/column_state").toByteArray ());
111 
112  // Set header properties for sorting
113 #if defined (HAVE_QT4)
114  view->horizontalHeader ()->setClickable (true);
115  view->horizontalHeader ()->setMovable (true);
116 #else
117  view->horizontalHeader ()->setSectionsClickable (true);
118  view->horizontalHeader ()->setSectionsMovable (true);
119 #endif
120  view->horizontalHeader ()->setSortIndicator (settings->value ("workspaceview/sort_by_column",0).toInt (),
121  static_cast<Qt::SortOrder>
122  (settings->value ("workspaceview/sort_order", Qt::AscendingOrder).toUInt ()));
123  view->horizontalHeader ()->setSortIndicatorShown (true);
124 
125  view->horizontalHeader ()->setContextMenuPolicy (Qt::CustomContextMenu);
126  connect (view->horizontalHeader (),
127  SIGNAL (customContextMenuRequested (const QPoint &)),
128  this, SLOT (header_contextmenu_requested (const QPoint &)));
129 
130  // Init state of the filter
131  _filter->addItems (settings->value ("workspaceview/mru_list").toStringList ());
132 
133  bool filter_state =
134  settings->value ("workspaceview/filter_active", false).toBool ();
135  _filter_checkbox->setChecked (filter_state);
136  filter_activate (filter_state);
137  }
138 
139  // Connect signals and slots.
140 
141  connect (_filter, SIGNAL (editTextChanged (const QString&)),
142  this, SLOT (filter_update (const QString&)));
143  connect (_filter_checkbox, SIGNAL (toggled (bool)),
144  this, SLOT (filter_activate (bool)));
145  connect (_filter->lineEdit (), SIGNAL (editingFinished ()),
146  this, SLOT (update_filter_history ()));
147 
148  connect (view, SIGNAL (customContextMenuRequested (const QPoint&)),
149  this, SLOT (contextmenu_requested (const QPoint&)));
150 
151  connect (this, SIGNAL (command_requested (const QString&)),
152  p, SLOT (execute_command_in_terminal (const QString&)));
153 }
154 
155 void
157 {
158  QSettings *settings = resource_manager::get_settings ();
159 
160  if (! settings)
161  return;
162 
163  settings->setValue ("workspaceview/column_state",
164  view->horizontalHeader ()->saveState ());
165 
166  int sort_column = view->horizontalHeader ()->sortIndicatorSection ();
167  Qt::SortOrder sort_order = view->horizontalHeader ()->sortIndicatorOrder ();
168  settings->setValue ("workspaceview/sort_by_column", sort_column);
169  settings->setValue ("workspaceview/sort_order", sort_order);
170 
171  settings->setValue ("workspaceview/filter_active",
172  _filter_checkbox->isChecked ());
173  settings->setValue ("workspaceview/filter_shown", _filter_shown);
174 
175  QStringList mru;
176  for (int i = 0; i < _filter->count (); i++)
177  mru.append (_filter->itemText (i));
178  settings->setValue ("workspaceview/mru_list", mru);
179 
180  settings->sync ();
181 
182  if (_sig_mapper)
183  delete _sig_mapper;
184 }
185 
187 {
188  _filter_model.setSourceModel (model);
189  _filter_model.setFilterKeyColumn(0);
190 
191  view->setModel (&_filter_model);
192 
193  // set the sorting after a model was set, it would be ignored otherwise
194  QSettings *settings = resource_manager::get_settings ();
195  view->sortByColumn (
196  settings->value ("workspaceview/sort_by_column",0).toInt (),
197  static_cast<Qt::SortOrder>
198  (settings->value ("workspaceview/sort_order", Qt::AscendingOrder).toUInt ())
199  );
200 
201  _model = model;
202 }
203 
204 void
206 {
207  emit active_changed (false);
208  QDockWidget::closeEvent (e);
209 }
210 
211 void
213 {
214  _filter_model.setFilterWildcard (expression);
216 }
217 
218 void
220 {
221  _filter->setEnabled (state);
222  _filter_model.setDynamicSortFilter (state);
223 
224  if (state)
225  filter_update (_filter->currentText ());
226  else
227  filter_update (QString ());
228 }
229 
230 void
232 {
233  QString text = _filter->currentText (); // get current text
234  int index = _filter->findText (text); // and its actual index
235 
236  if (index > -1)
237  _filter->removeItem (index); // remove if already existing
238 
239  _filter->insertItem (0, text); // (re)insert at beginning
240  _filter->setCurrentIndex (0);
241 }
242 
243 QString
244 workspace_view::get_var_name (QModelIndex index)
245 {
246  index = index.sibling (index.row (), 0);
247  QAbstractItemModel *m = view->model ();
248  QMap<int, QVariant> item_data = m->itemData (index);
249 
250  return item_data[0].toString ();
251 }
252 
253 void
255 {
256  QMenu menu (this);
257 
258  if (_sig_mapper)
259  delete _sig_mapper;
260  _sig_mapper = new QSignalMapper (this);
261 
262  QSettings *settings = resource_manager::get_settings ();
263 
264  for (int i = 0; i < _columns_shown.size (); i++)
265  {
266  QAction *action = menu.addAction (_columns_shown.at (i),
267  _sig_mapper, SLOT (map ()));
268  _sig_mapper->setMapping(action, i);
269  action->setCheckable (true);
270  action->setChecked (
271  settings->value (_columns_shown_keys.at (i),true).toBool ());
272  }
273 
274  connect (_sig_mapper, SIGNAL (mapped (int)), this, SLOT (toggle_header (int)));
275 
276  menu.exec (view->mapToGlobal (mpos));
277 }
278 
279 void
281 {
282  QSettings *settings = resource_manager::get_settings ();
283 
284  QString key = _columns_shown_keys.at (col);
285  bool shown = settings->value (key,true).toBool ();
286 
287  view->setColumnHidden (col + 1, shown);
288 
289  settings->setValue (key, ! shown);
290  settings->sync ();
291 
293 }
294 
295 void
297 {
298  QMenu menu (this);
299 
300  QModelIndex index = view->indexAt (qpos);
301 
302  // if it isnt Local, Glocal etc, allow the ctx menu
303  if (index.isValid () && index.column () == 0)
304  {
305  QString var_name = get_var_name (index);
306 
307  menu.addAction (tr ("Copy name"), this,
308  SLOT (handle_contextmenu_copy ()));
309 
310  menu.addAction (tr ("Copy value"), this,
312 
313  QAction *rename = menu.addAction (tr ("Rename"), this,
314  SLOT (handle_contextmenu_rename ()));
315 
316  QAbstractItemModel *m = view->model ();
317  const workspace_model *wm = static_cast<const workspace_model *> (m);
318 
319  if (! wm->is_top_level ())
320  {
321  rename->setDisabled (true);
322  rename->setToolTip (tr ("Only top-level symbols may be renamed"));
323  }
324 
325  menu.addSeparator ();
326 
327  menu.addAction ("disp (" + var_name + ")", this,
328  SLOT (handle_contextmenu_disp ()));
329 
330  menu.addAction ("plot (" + var_name + ")", this,
331  SLOT (handle_contextmenu_plot ()));
332 
333  menu.addAction ("stem (" + var_name + ")", this,
334  SLOT (handle_contextmenu_stem ()));
335 
336  menu.addSeparator ();
337 
338  }
339 
340  if (_filter_shown)
341  menu.addAction (tr ("Hide filter"), this,
342  SLOT (handle_contextmenu_filter ()));
343  else
344  menu.addAction (tr ("Show filter"), this,
345  SLOT (handle_contextmenu_filter ()));
346 
347  menu.exec (view->mapToGlobal (qpos));
348 }
349 
350 void
352 {
353  QModelIndex index = view->currentIndex ();
354 
355  if (index.isValid ())
356  {
357  QString var_name = get_var_name (index);
358 
359  QClipboard *clipboard = QApplication::clipboard ();
360 
361  clipboard->setText (var_name);
362  }
363 }
364 
365 void
367 {
368  QModelIndex index = view->currentIndex ();
369 
370  if (index.isValid ())
371  {
372  QString var_name = get_var_name (index);
373 
374  octave_value val = symbol_table::varval (var_name.toStdString ());
375  std::ostringstream buf;
376  val.print_raw (buf, true);
377 
378  QClipboard *clipboard = QApplication::clipboard ();
379  clipboard->setText (QString::fromStdString (buf.str ()));
380  }
381 }
382 
383 void
385 {
386  QModelIndex index = view->currentIndex ();
387 
388  if (index.isValid ())
389  {
390  QString var_name = get_var_name (index);
391 
392  QInputDialog* inputDialog = new QInputDialog ();
393 
394  inputDialog->setOptions (QInputDialog::NoButtons);
395 
396  bool ok = false;
397 
398  QString new_name
399  = inputDialog->getText (0, "Rename Variable", "New name:",
400  QLineEdit::Normal, var_name, &ok);
401 
402  if (ok && ! new_name.isEmpty ())
403  {
404  QAbstractItemModel *m = view->model ();
405  m->setData (index, new_name, Qt::EditRole);
406  }
407  }
408 }
409 
410 void
412 {
413  relay_contextmenu_command ("disp");
414 }
415 
416 void
418 {
419  relay_contextmenu_command ("figure (); plot");
420 }
421 
422 void
424 {
425  relay_contextmenu_command ("figure (); stem");
426 }
427 
428 void
430 {
431  QModelIndex index = view->currentIndex ();
432 
433  if (index.isValid ())
434  {
435  QString var_name = get_var_name (index);
436 
437  emit command_requested (cmdname + " (" + var_name + ");");
438  }
439 }
440 
441 void
443 {
445  _filter_widget->setVisible (_filter_shown);
446 }
447 
448 void
450 {
451 // view->resizeRowsToContents ();
452  // Just modify those rows that have been added rather than go through
453  // the whole list. For-loop test will handle when number of rows reduced.
454  QFontMetrics fm = view->fontMetrics ();
455  int row_height = fm.height ();
456  int new_row_count = _filter_model.rowCount ();
457  for (int i = view_previous_row_count; i < new_row_count; i++)
458  view->setRowHeight (i, row_height);
459  view_previous_row_count = new_row_count;
460 }
461 
462 void
463 workspace_view::notice_settings (const QSettings *settings)
464 {
465  int i;
466 
467  _model->notice_settings (settings); // update colors of model first
468 
469  for (i = 0; i < _columns_shown_keys.size (); i++)
470  {
471  view->setColumnHidden (i + 1,
472  ! settings->value (_columns_shown_keys.at (i),true).toBool ());
473  }
474 
475  QString tool_tip;
476 
477  if (! settings->value ("workspaceview/hide_tool_tips",false).toBool ())
478  {
479  tool_tip = QString (tr ("View the variables in the active workspace.<br>"));
480  tool_tip += QString (tr ("Colors for variable attributes:"));
481  for (i = 0; i < resource_manager::storage_class_chars ().length (); i++)
482  {
483  tool_tip +=
484  QString ("<div style=\"background-color:%1;color:#000000\">%2</div>")
485  .arg (_model->storage_class_color (i).name ())
487  }
488  }
489 
490  setToolTip (tool_tip);
491 
492  _columns_shown = QStringList ();
493  _columns_shown.append (tr ("Class"));
494  _columns_shown.append (tr ("Dimension"));
495  _columns_shown.append (tr ("Value"));
496  _columns_shown.append (tr ("Attribute"));
497 
498  _columns_shown_keys = QStringList ();
499  _columns_shown_keys.append ("workspaceview/show_class");
500  _columns_shown_keys.append ("workspaceview/show_dimension");
501  _columns_shown_keys.append ("workspaceview/show_value");
502  _columns_shown_keys.append ("workspaceview/show_attribute");
503 
504  _sig_mapper = 0;
505 }
506 
507 void
509 {
510  if (view->hasFocus ())
512 }
513 
514 void
516 {
517  if (view->hasFocus ())
518  view->selectAll ();
519 }
void filter_activate(bool enable)
QCheckBox * _filter_checkbox
void closeEvent(QCloseEvent *event)
QStringList _columns_shown
QColor storage_class_color(int s_class)
QTableView * view
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:5068
QWidget * _filter_widget
void handle_contextmenu_stem(void)
void set_title(const QString &)
void toggle_header(int column)
QString fromStdString(const std::string &s)
void handle_contextmenu_filter(void)
void command_requested(const QString &cmd)
signal that user had requested a command on a variable
void filter_update(const QString &expression)
void header_contextmenu_requested(const QPoint &mpos)
QSortFilterProxyModel _filter_model
i e
Definition: data.cc:2724
static octave_value varval(const std::string &name, scope_id scope=xcurrent_scope, context_id context=xdefault_context)
Definition: symtab.h:1373
void handle_contextmenu_rename(void)
octave_value arg
Definition: pr-output.cc:3440
int rename(const std::string &from, const std::string &to)
Definition: file-ops.cc:521
QStringList _columns_shown_keys
workspace_view(QWidget *parent=0)
OCTAVE_EXPORT octave_value_list any number nd example oindent prints the prompt xample Pick a any number!nd example oindent and waits for the user to enter a value The string entered by the user is evaluated as an expression
Definition: input.cc:871
workspace_model * _model
void setModel(workspace_model *model)
void contextmenu_requested(const QPoint &pos)
nd deftypefn *octave_map m
Definition: ov-struct.cc:2058
void update_filter_history()
void notice_settings(const QSettings *)
void print_raw(std::ostream &os, bool pr_as_read_syntax=false) const
Definition: ov.h:1219
int view_previous_row_count
void handle_model_changed(void)
QComboBox * _filter
returns the type of the matrix and caches it for future use Called with more than one the function will not attempt to guess the type if it is still unknown This is useful for debugging purposes The possible matrix types depend on whether the matrix is full or and can be one of the following able sis tem and mark type as unknown tem as the structure of the matrix explicitly gives this(Sparse matrices only) tem code
Definition: matrix_type.cc:120
void active_changed(bool active)
Custom signal that tells whether a user has clicked away that dock widget, i.e the active dock widget...
void save_settings(void)
static QSettings * get_settings(void)
QString get_var_name(QModelIndex index)
static uint32_t state[624]
Definition: randmtzig.cc:184
QSignalMapper * _sig_mapper
void notice_settings(const QSettings *)
void handle_contextmenu_copy(void)
=val(i)}if ode{val(i)}occurs in table i
Definition: lookup.cc:239
void handle_contextmenu_disp(void)
p
Definition: lu.cc:138
octave_map map(dims)
static QString storage_class_chars(void)
static QStringList storage_class_names(void)
void relay_contextmenu_command(const QString &cmdname)
void handle_contextmenu_copy_value(void)
void handle_contextmenu_plot(void)
bool is_top_level(void) const