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
dialog.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2013-2015 John W. Eaton
4 Copyright (C) 2013-2015 Daniel J. Sebald
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 "dialog.h"
29 
30 #include <QString>
31 #include <QStringList>
32 #include <QStringListModel>
33 #include <QListView>
34 #include <QFileInfo>
35 // Could replace most of these with #include <QtGui>
36 #include <QMessageBox>
37 #include <QHBoxLayout>
38 #include <QVBoxLayout>
39 #include <QPushButton>
40 #include <QGroupBox>
41 #include <QGridLayout>
42 #include <QLabel>
43 
45 
46 
48  : QObject (), dialog_result (-1), dialog_button (),
49  string_list (new QStringList ()), list_index (new QIntList ()),
50  path_name (new QString ())
51 { }
52 
53 
55 {
56  delete string_list;
57  delete list_index;
58  delete path_name;
59 }
60 
61 
62 void
63 QUIWidgetCreator::dialog_button_clicked (QAbstractButton *button)
64 {
65  // Wait for link thread to go to sleep state.
66  mutex.lock ();
67 
68  // Store the value so that builtin functions can retrieve.
69  if (button)
70  dialog_button = button->text ();
71 
72  // The value should always be 1 for the Octave functions.
73  dialog_result = 1;
74 
75  mutex.unlock ();
76 
77  // Wake up Octave process so that it continues.
78  waitcondition.wakeAll ();
79 }
80 
81 
82 void
84  int button_pressed)
85 {
86  // Wait for link thread to go to sleep state.
87  mutex.lock ();
88 
89  // Store the value so that builtin functions can retrieve.
90  *list_index = selected;
91  dialog_result = button_pressed;
92 
93  mutex.unlock ();
94 
95  // Wake up Octave process so that it continues.
96  waitcondition.wakeAll ();
97 }
98 
99 
100 void
101 QUIWidgetCreator::input_finished (const QStringList& input, int button_pressed)
102 {
103  // Wait for link thread to go to sleep state.
104  mutex.lock ();
105 
106  // Store the value so that builtin functions can retrieve.
107  *string_list = input;
108  dialog_result = button_pressed;
109 
110  mutex.unlock ();
111 
112  // Wake up Octave process so that it continues.
113  waitcondition.wakeAll ();
114 }
115 
116 void
117 QUIWidgetCreator::filedialog_finished (const QStringList& files,
118  const QString& path, int filterindex)
119 {
120  // Wait for link thread to go to sleep state.
121  mutex.lock ();
122 
123  // Store the value so that builtin functions can retrieve.
124  *string_list = files;
125  dialog_result = filterindex;
126  *path_name = path;
127 
128  mutex.unlock ();
129 
130  // Wake up Octave process so that it continues.
131  waitcondition.wakeAll ();
132 }
133 
134 
135 
137  const QString& title,
138  const QString& qsicon,
139  const QStringList& qsbutton,
140  const QString& defbutton,
141  const QStringList& role)
142  : QMessageBox (QMessageBox::NoIcon, title.isEmpty () ? " " : title,
143  message, 0, 0)
144 {
145  // Create a NonModal message.
146  setWindowModality (Qt::NonModal);
147 
148  // Interpret the icon string, because enumeration QMessageBox::Icon can't
149  // easily be made to pass through a signal.
150  QMessageBox::Icon eicon = QMessageBox::NoIcon;
151  if (qsicon == "error")
152  eicon = QMessageBox::Critical;
153  else if (qsicon == "warn")
154  eicon = QMessageBox::Warning;
155  else if (qsicon == "help")
156  eicon = QMessageBox::Information;
157  else if (qsicon == "quest")
158  eicon = QMessageBox::Question;
159  setIcon (eicon);
160 
161  int N = qsbutton.size () < role.size () ? qsbutton.size () : role.size ();
162  if (N == 0)
163  addButton (QMessageBox::Ok);
164  else
165  {
166  for (int i = N-1; i >= 0; i--)
167  {
168  // Interpret the button role string, because enumeration
169  // QMessageBox::ButtonRole can't be made to pass through a signal.
170  QString srole = role.at (i);
171  QMessageBox::ButtonRole erole = QMessageBox::InvalidRole;
172  if (srole == "YesRole")
173  erole = QMessageBox::YesRole;
174  else if (srole == "NoRole")
175  erole = QMessageBox::NoRole;
176  else if (srole == "RejectRole")
177  erole = QMessageBox::RejectRole;
178  else if (srole == "AcceptRole")
179  erole = QMessageBox::AcceptRole;
180 
181  QPushButton *pbutton = addButton (qsbutton.at (i), erole);
182  if (qsbutton.at (i) == defbutton)
183  setDefaultButton (pbutton);
184  // Make the last button the button pressed when <esc> key activated.
185  if (i == N-1)
186  {
187 #define ACTIVE_ESCAPE 1
188 #if ACTIVE_ESCAPE
189  setEscapeButton (pbutton);
190 #else
191  setEscapeButton (0);
192 #endif
193 #undef ACTIVE_ESCAPE
194  }
195  }
196  }
197 
198  connect (this, SIGNAL (buttonClicked (QAbstractButton *)),
199  &uiwidget_creator, SLOT (dialog_button_clicked (QAbstractButton *)));
200 }
201 
202 
203 ListDialog::ListDialog (const QStringList& list, const QString& mode,
204  int wd, int ht, const QList<int>& initial,
205  const QString& title, const QStringList& prompt,
206  const QString& ok_string, const QString& cancel_string)
207  : QDialog ()
208 {
209  // Put the list of items into a model. Keep this off of the stack
210  // because this conceivably could be a very large list.
211  QAbstractItemModel *model = new QStringListModel (list);
212 
213  QListView *view = new QListView;
214  view->setModel (model);
215 
216  if (mode == "single")
217  view->setSelectionMode (QAbstractItemView::SingleSelection);
218  else if (mode == "multiple")
219  view->setSelectionMode (QAbstractItemView::ExtendedSelection);
220  else
221  view->setSelectionMode (QAbstractItemView::NoSelection);
222 
223  selector = view->selectionModel ();
224  int i = 0;
225  for (QList<int>::const_iterator it = initial.begin ();
226  it != initial.end (); it++)
227  {
228  QModelIndex idx = model->index (initial.value (i++) - 1, 0,
229  QModelIndex ());
230  selector->select (idx, QItemSelectionModel::Select);
231  }
232 
233  bool fixed_layout = false;
234  if (wd > 0 && ht > 0)
235  {
236  view->setFixedSize (wd, ht);
237  fixed_layout = true;
238  }
239 
240  view->setEditTriggers (QAbstractItemView::NoEditTriggers);
241 
242  QVBoxLayout *listLayout = new QVBoxLayout;
243  if (! prompt.isEmpty ())
244  {
245  // For now, assume html-like Rich Text. May be incompatible
246  // with something down the road, but just testing capability.
247  QString prompt_string;
248  for (int j = 0; j < prompt.length (); j++)
249  {
250  if (j > 0)
251 #define RICH_TEXT 1
252 #if RICH_TEXT
253  prompt_string.append ("<br>");
254 #else
255  prompt_string.append ("\n");
256 #endif
257  prompt_string.append (prompt.at (j));
258  }
259  QLabel *plabel = new QLabel (prompt_string);
260 #if RICH_TEXT
261  plabel->setTextFormat (Qt::RichText);
262 #endif
263 #undef RICH_TEXT
264  listLayout->addWidget (plabel);
265  }
266  listLayout->addWidget (view);
267  QPushButton *select_all = new QPushButton (tr ("Select All"));
268  select_all->setEnabled (mode == "multiple");
269  listLayout->addWidget (select_all);
270 
271  QPushButton *buttonOk = new QPushButton (ok_string);
272  QPushButton *buttonCancel = new QPushButton (cancel_string);
273  QHBoxLayout *buttonsLayout = new QHBoxLayout;
274  buttonsLayout->addStretch (1);
275  buttonsLayout->addWidget (buttonOk);
276  buttonsLayout->addWidget (buttonCancel);
277 
278  QVBoxLayout *mainLayout = new QVBoxLayout;
279  mainLayout->addLayout (listLayout);
280  mainLayout->addSpacing (12);
281  mainLayout->addLayout (buttonsLayout);
282  setLayout (mainLayout);
283  if (fixed_layout)
284  layout ()->setSizeConstraint (QLayout::SetFixedSize);
285 
286  // If empty, make blank rather than use default OS behavior.
287  setWindowTitle (title.isEmpty () ? " " : title);
288 
289  connect (select_all, SIGNAL (clicked ()),
290  view, SLOT (selectAll ()));
291 
292  connect (buttonOk, SIGNAL (clicked ()),
293  this, SLOT (buttonOk_clicked ()));
294 
295  connect (buttonCancel, SIGNAL (clicked ()),
296  this, SLOT (buttonCancel_clicked ()));
297 
298  connect (this, SIGNAL (finish_selection (const QIntList&, int)),
299  &uiwidget_creator,
300  SLOT (list_select_finished (const QIntList&, int)));
301 }
302 
303 
304 void
306 {
307  // Store information about what button was pressed so that builtin
308  // functions can retrieve.
309  QModelIndexList selected_index = selector->selectedIndexes ();
310  QIntList selected_int;
311 
312  for (int i = 0; i < selected_index.size (); i++)
313  selected_int << selected_index.at (i).row () + 1;
314 
315  emit finish_selection (selected_int, 1);
316 
317  done (QDialog::Accepted);
318 }
319 
320 
321 void
323 {
324  // Store information about what button was pressed so that builtin
325  // functions can retrieve.
326  QIntList empty;
327 
328  emit finish_selection (empty, 0);
329 
330  done (QDialog::Rejected);
331 }
332 
333 
334 void
336 {
338 }
339 
340 
341 InputDialog::InputDialog (const QStringList& prompt, const QString& title,
342  const QFloatList& nr, const QFloatList& nc,
343  const QStringList& defaults)
344  : QDialog ()
345 {
346 
347 #define LINE_EDIT_FOLLOWS_PROMPT 0
348 
349 #if LINE_EDIT_FOLLOWS_PROMPT
350  // Prompt on left followed by input on right.
351  QGridLayout *promptInputLayout = new QGridLayout;
352 #else
353  // Prompt aligned above input.
354  QVBoxLayout *promptInputLayout = new QVBoxLayout;
355 #endif
356  int N_gridrows = prompt.size ();
357  for (int i = 0; i < N_gridrows; i++)
358  {
359  QLabel *label = new QLabel (prompt.at (i));
360  QLineEdit *line_edit = new QLineEdit (defaults.at (i));
361  if (nr.at (i) > 0)
362  {
363  QSize qsize = line_edit->sizeHint ();
364  int intval = qsize.height () * nr.at (i);
365  line_edit->setFixedHeight (intval);
366  if (nc.at (i) > 0)
367  {
368  intval = qsize.height () * nc.at (i) / 2;
369  line_edit->setFixedWidth (intval);
370  }
371  }
372  input_line << line_edit;
373 #if LINE_EDIT_FOLLOWS_PROMPT
374  promptInputLayout->addWidget (label, i + 1, 0);
375  promptInputLayout->addWidget (line_edit, i + 1, 1);
376 #else
377  promptInputLayout->addWidget (label);
378  promptInputLayout->addWidget (line_edit);
379 #endif
380  }
381 #undef LINE_EDIT_FOLLOWS_PROMPT
382 
383  QPushButton *buttonOk = new QPushButton ("OK");
384  QPushButton *buttonCancel = new QPushButton ("Cancel");
385  QHBoxLayout *buttonsLayout = new QHBoxLayout;
386  buttonsLayout->addStretch (1);
387  buttonsLayout->addWidget (buttonOk);
388  buttonsLayout->addWidget (buttonCancel);
389 
390  QVBoxLayout *mainLayout = new QVBoxLayout;
391  mainLayout->addLayout (promptInputLayout);
392  mainLayout->addSpacing (12);
393  mainLayout->addLayout (buttonsLayout);
394  setLayout (mainLayout);
395 
396  // If empty, make blank rather than use default OS behavior.
397  setWindowTitle (title.isEmpty () ? " " : title);
398 
399  connect (buttonOk, SIGNAL (clicked ()),
400  this, SLOT (buttonOk_clicked ()));
401 
402  connect (buttonCancel, SIGNAL (clicked ()),
403  this, SLOT (buttonCancel_clicked ()));
404 
405  connect (this, SIGNAL (finish_input (const QStringList&, int)),
406  &uiwidget_creator,
407  SLOT (input_finished (const QStringList&, int)));
408 }
409 
410 
411 void
413 {
414  // Store information about what button was pressed so that builtin
415  // functions can retrieve.
416  QStringList string_result;
417  for (int i = 0; i < input_line.size (); i++)
418  string_result << input_line.at (i)->text ();
419  emit finish_input (string_result, 1);
420  done (QDialog::Accepted);
421 }
422 
423 void
425 {
426  // Store information about what button was pressed so that builtin
427  // functions can retrieve.
428  QStringList empty;
429  emit finish_input (empty, 0);
430  done (QDialog::Rejected);
431 }
432 
433 
434 void
436 {
438 }
439 
440 FileDialog::FileDialog (const QStringList& name_filters, const QString& title,
441  const QString& filename, const QString& dirname,
442  const QString& multimode)
443  : QFileDialog ()
444 {
445  // Create a NonModal message.
446  setWindowModality (Qt::NonModal);
447 
448  setWindowTitle (title.isEmpty () ? " " : title);
449  setDirectory (dirname);
450 
451  if (multimode == "on") // uigetfile multiselect=on
452  {
453  setFileMode (QFileDialog::ExistingFiles);
454  setAcceptMode (QFileDialog::AcceptOpen);
455  }
456  else if (multimode == "create") // uiputfile
457  {
458  setFileMode (QFileDialog::AnyFile);
459  setAcceptMode (QFileDialog::AcceptSave);
460  setOption (QFileDialog::DontConfirmOverwrite, false);
461  setConfirmOverwrite (true);
462  }
463  else if (multimode == "dir") // uigetdir
464  {
465  setFileMode (QFileDialog::Directory);
466  setOption (QFileDialog::ShowDirsOnly, true);
467  setOption (QFileDialog::HideNameFilterDetails, true);
468  setAcceptMode (QFileDialog::AcceptOpen);
469  }
470  else // uigetfile multiselect=off
471  {
472  setFileMode (QFileDialog::ExistingFile);
473  setAcceptMode (QFileDialog::AcceptOpen);
474  }
475 
476  setNameFilters (name_filters);
477 
478  selectFile (filename);
479 
480  connect (this,
481  SIGNAL (finish_input (const QStringList&, const QString&, int)),
482  &uiwidget_creator,
483  SLOT (filedialog_finished (const QStringList&, const QString&,
484  int)));
485  connect (this, SIGNAL (accepted ()), this, SLOT (acceptSelection ()));
486  connect (this, SIGNAL (rejected ()), this, SLOT (rejectSelection ()));
487 }
488 
489 void
491 {
492  QStringList empty;
493  emit finish_input (empty, "", 0);
494 }
495 
497 {
498  QStringList string_result;
499  QString path;
500  int idx = 1;
501 
502  string_result = selectedFiles ();
503 
504  if (testOption (QFileDialog::ShowDirsOnly) == true &&
505  string_result.size () > 0)
506  {
507  path = string_result[0];
508  }
509  else
510  {
511  path = directory ().absolutePath ();
512  }
513 
514  // Matlab expects just the file name, whereas the file dialog gave us
515  // full path names, so fix it.
516 
517  for (int i = 0; i < string_result.size (); i++)
518  string_result[i] = QFileInfo (string_result[i]).fileName ();
519 
520  // if not showing only dirs, add end slash for the path component
521  if (testOption (QFileDialog::ShowDirsOnly) == false)
522  path = path + "/";
523 
524  // convert to native slashes
525  path = QDir::toNativeSeparators (path);
526 
527  QStringList name_filters = nameFilters ();
528  idx = name_filters.indexOf (selectedNameFilter ()) + 1;
529 
530  // send the selected info
531  emit finish_input (string_result, path, idx);
532 }
533 
~QUIWidgetCreator(void)
Definition: dialog.cc:54
void list_select_finished(const QIntList &selected, int button_pressed)
Definition: dialog.cc:83
void buttonOk_clicked(void)
Definition: dialog.cc:305
void finish_selection(const QIntList &, int)
Definition: moc-dialog.cc:301
QItemSelectionModel * selector
Definition: dialog.h:193
FileDialog(const QStringList &filters, const QString &title, const QString &filename, const QString &dirname, const QString &multimode)
Definition: dialog.cc:440
QMutex mutex
Definition: dialog.h:120
ListDialog(const QStringList &list, const QString &mode, int width, int height, const QList< int > &initial, const QString &name, const QStringList &prompt, const QString &ok_string, const QString &cancel_string)
Definition: dialog.cc:203
void rejectSelection(void)
Definition: dialog.cc:490
void filedialog_finished(const QStringList &files, const QString &path, int filterindex)
Definition: dialog.cc:117
void reject(void)
Definition: dialog.cc:435
QUIWidgetCreator uiwidget_creator
Definition: dialog.cc:44
void message(const char *name, const char *fmt,...)
Definition: error.cc:380
void reject(void)
Definition: dialog.cc:335
QString dialog_button
Definition: dialog.h:153
QString * path_name
Definition: dialog.h:160
void dialog_button_clicked(QAbstractButton *button)
Definition: dialog.cc:63
QIntList * list_index
Definition: dialog.h:158
void buttonCancel_clicked(void)
Definition: dialog.cc:424
void input_finished(const QStringList &input, int button_pressed)
Definition: dialog.cc:101
QWaitCondition waitcondition
Definition: dialog.h:121
QStringList * string_list
Definition: dialog.h:157
void buttonOk_clicked(void)
Definition: dialog.cc:412
int dialog_result
Definition: dialog.h:152
F77_RET_T const octave_idx_type & N
Definition: CmplxGEPBAL.cc:39
MessageDialog(const QString &message, const QString &title, const QString &icon, const QStringList &button, const QString &defbutton, const QStringList &role)
Definition: dialog.cc:136
InputDialog(const QStringList &prompt, const QString &title, const QFloatList &nr, const QFloatList &nc, const QStringList &defaults)
Definition: dialog.cc:341
void finish_input(const QStringList &, const QString &, int)
Definition: moc-dialog.cc:478
static int input(yyscan_t yyscanner)
QList< int > QIntList
Definition: dialog.h:38
void acceptSelection(void)
Definition: dialog.cc:496
QList< QLineEdit * > input_line
Definition: dialog.h:220
QUIWidgetCreator(void)
Definition: dialog.cc:47
void buttonCancel_clicked(void)
Definition: dialog.cc:322
void finish_input(const QStringList &, int)
Definition: moc-dialog.cc:391