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