GNU Octave  4.0.0
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-2015 John W. Eaton
4 Copyright (C) 2011-2015 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 #ifdef 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 
41 #include "workspace-view.h"
42 #include "resource-manager.h"
43 #include "symtab.h"
44 
46  : octave_dock_widget (p), view (new QTableView (this))
47 {
48  setObjectName ("WorkspaceView");
49  setWindowIcon (QIcon (":/actions/icons/logo.png"));
50  set_title (tr ("Workspace"));
51  setStatusTip (tr ("View the variables in the active workspace."));
52 
53  _filter = new QComboBox (this);
54  _filter->setToolTip (tr ("Enter text to filter the workspace"));
55  _filter->setEditable (true);
56  _filter->setMaxCount (MaxFilterHistory);
57  _filter->setInsertPolicy (QComboBox::NoInsert);
58  _filter->setSizeAdjustPolicy (
59  QComboBox::AdjustToMinimumContentsLengthWithIcon);
60  QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);
61  _filter->setSizePolicy (sizePol);
62  _filter->completer ()->setCaseSensitivity (Qt::CaseSensitive);
63 
64  QLabel *filter_label = new QLabel (tr ("Filter"));
65 
66  _filter_checkbox = new QCheckBox ();
67 
68  view->setWordWrap (false);
69  view->setContextMenuPolicy (Qt::CustomContextMenu);
70  view->setShowGrid (false);
71  (view->verticalHeader) ()->hide ();
72  view->setAlternatingRowColors (true);
74 
75  // Set an empty widget, so we can assign a layout to it.
76  setWidget (new QWidget (this));
77 
78  // Create a new layout and add widgets to it.
79  QVBoxLayout *vbox_layout = new QVBoxLayout ();
80  QHBoxLayout *hbox_layout = new QHBoxLayout ();
81  hbox_layout->addWidget (filter_label);
82  hbox_layout->addWidget (_filter_checkbox);
83  hbox_layout->addWidget (_filter);
84  vbox_layout->addLayout (hbox_layout);
85  vbox_layout->addWidget (view);
86  vbox_layout->setMargin (2);
87 
88  // Set the empty widget to have our layout.
89  widget ()->setLayout (vbox_layout);
90 
91  // Initialize collapse/expand state of the workspace subcategories.
92 
93  QSettings *settings = resource_manager::get_settings ();
94 
95  //enable sorting as previously configured
96  view->setSortingEnabled (true);
97  view->sortByColumn (
98  settings->value ("workspaceview/sort_by_column",0).toInt (),
99  static_cast<Qt::SortOrder>
100  (settings->value ("workspaceview/sort_order", Qt::AscendingOrder).toUInt ())
101  );
102  // Initialize column order and width of the workspace
103  view->horizontalHeader ()->restoreState (
104  settings->value ("workspaceview/column_state").toByteArray ());
105 
106  // Init state of the filter
107  _filter->addItems (settings->value ("workspaceview/mru_list").toStringList ());
108 
109  bool filter_state =
110  settings->value ("workspaceview/filter_active", false).toBool ();
111  _filter_checkbox->setChecked (filter_state);
112  filter_activate (filter_state);
113 
114  // Connect signals and slots.
115 
116  connect (_filter, SIGNAL (editTextChanged (const QString&)),
117  this, SLOT (filter_update (const QString&)));
118  connect (_filter_checkbox, SIGNAL (toggled (bool)),
119  this, SLOT (filter_activate (bool)));
120  connect (_filter->lineEdit (), SIGNAL (editingFinished ()),
121  this, SLOT (update_filter_history ()));
122 
123  connect (view, SIGNAL (customContextMenuRequested (const QPoint&)),
124  this, SLOT (contextmenu_requested (const QPoint&)));
125 
126  connect (this, SIGNAL (command_requested (const QString&)),
127  p, SLOT (execute_command_in_terminal (const QString&)));
128 
129 }
130 
132 {
133  QSettings *settings = resource_manager::get_settings ();
134 
135  settings->setValue ("workspaceview/column_state",
136  view->horizontalHeader ()->saveState ());
137 
138  int sort_column = view->horizontalHeader ()->sortIndicatorSection ();
139  Qt::SortOrder sort_order = view->horizontalHeader ()->sortIndicatorOrder ();
140  settings->setValue ("workspaceview/sort_by_column", sort_column);
141  settings->setValue ("workspaceview/sort_order", sort_order);
142 
143  settings->setValue ("workspaceview/filter_active",
144  _filter_checkbox->isChecked ());
145 
146  QStringList mru;
147  for (int i = 0; i < _filter->count (); i++)
148  mru.append (_filter->itemText (i));
149  settings->setValue ("workspaceview/mru_list", mru);
150 
151  settings->sync ();
152 }
153 
155 {
156  _filter_model.setSourceModel (model);
157  _filter_model.setFilterKeyColumn(0);
158 
159  view->setModel (&_filter_model);
160 
161  _model = model;
162 }
163 
164 void
166 {
167  emit active_changed (false);
168  QDockWidget::closeEvent (e);
169 }
170 
171 void
172 workspace_view::filter_update (const QString& expression)
173 {
174  _filter_model.setFilterWildcard (expression);
176 }
177 
178 void
180 {
181  _filter->setEnabled (state);
182  _filter_model.setDynamicSortFilter (state);
183 
184  if (state)
185  filter_update (_filter->currentText ());
186  else
187  filter_update (QString ());
188 }
189 
190 void
192 {
193  QString text = _filter->currentText (); // get current text
194  int index = _filter->findText (text); // and its actual index
195 
196  if (index > -1)
197  _filter->removeItem (index); // remove if already existing
198 
199  _filter->insertItem (0, text); // (re)insert at beginning
200  _filter->setCurrentIndex (0);
201 }
202 
203 QString
204 workspace_view::get_var_name (QModelIndex index)
205 {
206  index = index.sibling (index.row (), 0);
207  QAbstractItemModel *m = view->model ();
208  QMap<int, QVariant> item_data = m->itemData (index);
209 
210  return item_data[0].toString ();
211 }
212 
213 void
215 {
216  QMenu menu (this);
217 
218  QModelIndex index = view->indexAt (qpos);
219 
220  // if it isnt Local, Glocal etc, allow the ctx menu
221  if (index.isValid () && index.column () == 0)
222  {
223  QString var_name = get_var_name (index);
224 
225  menu.addAction (tr ("Copy name"), this,
226  SLOT (handle_contextmenu_copy ()));
227 
228  menu.addAction (tr ("Copy value"), this,
230 
231  QAction *rename = menu.addAction (tr ("Rename"), this,
232  SLOT (handle_contextmenu_rename ()));
233 
234  QAbstractItemModel *m = view->model ();
235  const workspace_model *wm = static_cast<const workspace_model *> (m);
236 
237  if (! wm->is_top_level ())
238  {
239  rename->setDisabled (true);
240  rename->setToolTip (tr ("Only top-level symbols may be renamed."));
241  }
242 
243  menu.addSeparator ();
244 
245  menu.addAction ("disp (" + var_name + ")", this,
246  SLOT (handle_contextmenu_disp ()));
247 
248  menu.addAction ("plot (" + var_name + ")", this,
249  SLOT (handle_contextmenu_plot ()));
250 
251  menu.addAction ("stem (" + var_name + ")", this,
252  SLOT (handle_contextmenu_stem ()));
253 
254  menu.exec (view->mapToGlobal (qpos));
255  }
256 }
257 
258 void
260 {
261  QModelIndex index = view->currentIndex ();
262 
263  if (index.isValid ())
264  {
265  QString var_name = get_var_name (index);
266 
267  QClipboard *clipboard = QApplication::clipboard ();
268 
269  clipboard->setText (var_name);
270  }
271 }
272 
273 void
275 {
276  QModelIndex index = view->currentIndex ();
277 
278  if (index.isValid ())
279  {
280  QString var_name = get_var_name (index);
281 
282  octave_value val = symbol_table::varval (var_name.toStdString ());
283  std::ostringstream buf;
284  val.print_raw (buf, true);
285 
286  QClipboard *clipboard = QApplication::clipboard ();
287  clipboard->setText (QString::fromStdString (buf.str ()));
288  }
289 }
290 
291 void
293 {
294  QModelIndex index = view->currentIndex ();
295 
296  if (index.isValid ())
297  {
298  QString var_name = get_var_name (index);
299 
300  QInputDialog* inputDialog = new QInputDialog ();
301 
302  inputDialog->setOptions (QInputDialog::NoButtons);
303 
304  bool ok = false;
305 
306  QString new_name
307  = inputDialog->getText (0, "Rename Variable", "New name:",
308  QLineEdit::Normal, var_name, &ok);
309 
310  if (ok && ! new_name.isEmpty ())
311  {
312  QAbstractItemModel *m = view->model ();
313  m->setData (index, new_name, Qt::EditRole);
314  }
315  }
316 }
317 
318 void
320 {
321  relay_contextmenu_command ("disp");
322 }
323 
324 void
326 {
327  relay_contextmenu_command ("figure (); plot");
328 }
329 
330 void
332 {
333  relay_contextmenu_command ("figure (); stem");
334 }
335 
336 void
338 {
339  QModelIndex index = view->currentIndex ();
340 
341  if (index.isValid ())
342  {
343  QString var_name = get_var_name (index);
344 
345  emit command_requested (cmdname + " (" + var_name + ");");
346  }
347 }
348 
349 void
351 {
352 // view->resizeRowsToContents ();
353  // Just modify those rows that have been added rather than go through
354  // the whole list. For-loop test will handle when number of rows reduced.
355  QFontMetrics fm = view->fontMetrics ();
356  int row_height = fm.height ();
357  int new_row_count = _filter_model.rowCount ();
358  for (int i = view_previous_row_count; i < new_row_count; i++)
359  view->setRowHeight (i, row_height);
360  view_previous_row_count = new_row_count;
361 }
362 
363 void
364 workspace_view::notice_settings (const QSettings *settings)
365 {
366  _model->notice_settings (settings); // update colors of model first
367 
368  QString tool_tip;
369 
370  if (!settings->value ("workspaceview/hide_tool_tips",false).toBool ())
371  {
372  tool_tip = QString (tr ("View the variables in the active workspace.<br>"));
373  tool_tip += QString (tr ("Colors for variable attributes:"));
374  for (int i = 0; i < resource_manager::storage_class_chars ().length (); i++)
375  {
376  tool_tip +=
377  QString ("<div style=\"background-color:%1;color:#000000\">%2</div>")
378  .arg (_model->storage_class_color (i).name ())
380  }
381  }
382 
383  setToolTip (tool_tip);
384 
385 }
386 
387 void
389 {
390  if (view->hasFocus ())
392 }
393 
394 void
396 {
397  if (view->hasFocus ())
398  view->selectAll ();
399 }
400 
void filter_activate(bool enable)
QCheckBox * _filter_checkbox
void closeEvent(QCloseEvent *event)
QColor storage_class_color(int s_class)
static uint32_t state[624]
Definition: randmtzig.c:188
QTableView * view
void handle_contextmenu_stem(void)
void set_title(const QString &)
QString fromStdString(const std::string &s)
void command_requested(const QString &cmd)
signal that user had requested a command on a variable
void filter_update(const QString &expression)
QSortFilterProxyModel _filter_model
static octave_value varval(const std::string &name, scope_id scope=xcurrent_scope, context_id context=xdefault_context)
Definition: symtab.h:1385
void handle_contextmenu_rename(void)
workspace_view(QWidget *parent=0)
workspace_model * _model
void setModel(workspace_model *model)
void contextmenu_requested(const QPoint &pos)
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:1034
int view_previous_row_count
void handle_model_changed(void)
QComboBox * _filter
void active_changed(bool active)
Custom signal that tells whether a user has clicked away that dock widget, i.e the active dock widget...
static QSettings * get_settings(void)
QString get_var_name(QModelIndex index)
double arg(double x)
Definition: lo-mappers.h:37
void notice_settings(const QSettings *)
void handle_contextmenu_copy(void)
void handle_contextmenu_disp(void)
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