GNU Octave  4.4.1
A high-level interpreted language, primarily intended for numerical computations, mostly compatible with Matlab
octave-qt-link.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2013-2018 John W. Eaton
4 Copyright (C) 2011-2018 Jacob Dawid
5 Copyright (C) 2011-2018 John P. Swensen
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
11 the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License 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 #if defined (HAVE_CONFIG_H)
26 # include "config.h"
27 #endif
28 
29 #include <QDialog>
30 #include <QDir>
31 #include <QMetaType>
32 #include <QPushButton>
33 #include <QStringList>
34 
35 #include "oct-env.h"
36 #include "str-vec.h"
37 
38 #include "builtin-defun-decls.h"
39 #include "dialog.h"
40 #include "error.h"
41 #include "interpreter-private.h"
42 #include "load-path.h"
43 #include "ov.h"
44 #include "symscope.h"
45 #include "utils.h"
46 
47 #include "octave-gui.h"
48 #include "octave-qt-link.h"
49 #include "resource-manager.h"
50 
51 Q_DECLARE_METATYPE (octave_value)
52 Q_DECLARE_METATYPE (octave::symbol_scope)
53 
54 namespace octave
55 {
56  octave_qt_link::octave_qt_link (QWidget *, gui_application *app_context)
57  : octave_link (), m_app_context (app_context)
58  {
59  qRegisterMetaType<octave_value> ("octave_value");
60  qRegisterMetaType<symbol_scope> ("symbol_scope");
61  }
62 
64  {
65  // Lock the mutex before emitting signal.
66  lock ();
67 
69 
70  // Wait while the GUI shuts down.
71  wait ();
72 
73  // The GUI has sent a signal and the thread has been awakened.
74 
75  unlock ();
76 
78  }
79 
81  {
83 
84  return true;
85  }
86 
88  {
90 
91  return true;
92  }
93 
95  {
96  QSettings *settings = resource_manager::get_settings ();
97 
98  if (! settings || settings->value ("editor/create_new_file",false).toBool ())
99  return true;
100 
101  QFileInfo file_info (QString::fromStdString (file));
102  QStringList btn;
103  QStringList role;
104  role << "YesRole" << "RejectRole";
105  btn << tr ("Create") << tr ("Cancel");
106 
107  // Lock mutex before signaling.
109 
111  tr ("File\n%1\ndoes not exist. Do you want to create it?").
112  arg (QDir::currentPath () + QDir::separator ()
114  tr ("Octave Editor"), "quest", btn, tr ("Create"), role);
115 
116  // Wait while the user is responding to message box.
118 
119  // The GUI has sent a signal and the thread has been awakened.
120 
121  QString answer = uiwidget_creator.get_dialog_button ();
122 
124 
125  return (answer == tr ("Create"));
126  }
127 
129  const std::string& msg,
130  const std::string& title)
131  {
132  // Lock mutex before signaling.
134 
136  QString::fromStdString (title),
138  QStringList (), QString (),
139  QStringList ());
140 
141  // Wait while the user is responding to message box.
143 
144  // The GUI has sent a signal and the thread has been awakened.
145 
146  int answer = uiwidget_creator.get_dialog_result ();
147 
149 
150  return answer;
151  }
152 
154  const std::string& title,
155  const std::string& btn1,
156  const std::string& btn2,
157  const std::string& btn3,
158  const std::string& btndef)
159  {
160  QStringList btn;
161  QStringList role;
162  // Must use ResetRole which is left-aligned for all OS and WM.
163  role << "ResetRole" << "ResetRole" << "ResetRole";
164  btn << QString::fromStdString (btn1);
165  if (btn2 == "")
166  role.removeAt (0);
167  else
168  btn << QString::fromStdString (btn2);
169  btn << QString::fromStdString (btn3);
170 
171  // Lock mutex before signaling.
173 
175  QString::fromStdString (title),
176  "quest",
177  btn,
178  QString::fromStdString (btndef),
179  role);
180 
181  // Wait while the user is responding to message box.
183 
184  // The GUI has sent a signal and the thread has been awakened.
185 
186  std::string answer = uiwidget_creator.get_dialog_button ().toStdString ();
187 
189 
190  return answer;
191  }
192 
193  static QStringList
194  make_qstring_list (const std::list<std::string>& lst)
195  {
196  QStringList retval;
197 
198  for (std::list<std::string>::const_iterator it = lst.begin ();
199  it != lst.end (); it++)
200  {
201  retval.append (QString::fromStdString (*it));
202  }
203 
204  return retval;
205  }
206 
207  static QStringList
208  make_filter_list (const octave_link::filter_list& lst)
209  {
210  QStringList retval;
211 
212  // We have pairs of data, first being the list of extensions
213  // exta;exb;extc etc second the name to use as filter name
214  // (optional). Qt wants a list of filters in the format of
215  // 'FilterName (space separated exts)'.
216 
217  for (octave_link::filter_list::const_iterator it = lst.begin ();
218  it != lst.end (); it++)
219  {
220  QString ext = QString::fromStdString (it->first);
221  QString name = QString::fromStdString (it->second);
222 
223  // Strip out extensions from name and replace ';' with spaces in
224  // list.
225 
226  name.replace (QRegExp ("\\(.*\\)"), "");
227  ext.replace (";", " ");
228 
229  if (name.isEmpty ())
230  {
231  // No name field. Build one from the extensions.
232  name = ext.toUpper () + " Files";
233  }
234 
235  retval.append (name + " (" + ext + ')');
236  }
237 
238  return retval;
239  }
240 
241  std::pair<std::list<int>, int>
242  octave_qt_link::do_list_dialog (const std::list<std::string>& list,
243  const std::string& mode,
244  int width, int height,
245  const std::list<int>& initial,
246  const std::string& name,
247  const std::list<std::string>& prompt,
248  const std::string& ok_string,
249  const std::string& cancel_string)
250  {
251  // Lock mutex before signaling.
253 
254  uiwidget_creator.signal_listview (make_qstring_list (list),
256  width, height,
257  QList<int>::fromStdList (initial),
259  make_qstring_list (prompt),
260  QString::fromStdString (ok_string),
261  QString::fromStdString (cancel_string));
262 
263  // Wait while the user is responding to message box.
265 
266  // The GUI has sent a signal and the thread has been awakened.
267 
268  const QIntList *selected = uiwidget_creator.get_list_index ();
270 
272 
273  return std::pair<std::list<int>, int> (selected->toStdList (), ok);
274  }
275 
276  std::list<std::string>
277  octave_qt_link::do_input_dialog (const std::list<std::string>& prompt,
278  const std::string& title,
279  const std::list<float>& nr,
280  const std::list<float>& nc,
281  const std::list<std::string>& defaults)
282  {
283  std::list<std::string> retval;
284 
285  // Lock mutex before signaling.
287 
288  uiwidget_creator.signal_inputlayout (make_qstring_list (prompt),
289  QString::fromStdString (title),
290  QFloatList::fromStdList (nr),
291  QFloatList::fromStdList (nc),
292  make_qstring_list (defaults));
293 
294  // Wait while the user is responding to message box.
296 
297  // The GUI has sent a signal and the thread has been awakened.
298 
299  const QStringList *inputLine = uiwidget_creator.get_string_list ();
300 
302 
303  for (QStringList::const_iterator it = inputLine->begin ();
304  it != inputLine->end (); it++)
305  {
306  retval.push_back (it->toStdString ());
307  }
308 
309  return retval;
310  }
311 
312  std::list<std::string>
313  octave_qt_link::do_file_dialog (const filter_list& filter,
314  const std::string& title,
315  const std::string& filename,
316  const std::string& dirname,
317  const std::string& multimode)
318  {
319  std::list<std::string> retval;
320 
321  // Lock mutex before signaling.
323 
324  uiwidget_creator.signal_filedialog (make_filter_list (filter),
325  QString::fromStdString (title),
328  QString::fromStdString (multimode));
329 
330  // Wait while the user is responding to dialog.
332 
333  // The GUI has sent a signal and the thread has been awakened.
334 
335  // Add all the file dialog results to a string list.
336  const QStringList *inputLine = uiwidget_creator.get_string_list ();
337 
338  for (QStringList::const_iterator it = inputLine->begin ();
339  it != inputLine->end (); it++)
340  retval.push_back (it->toStdString ());
341 
342  retval.push_back (uiwidget_creator.get_dialog_path ()->toStdString ());
343  retval.push_back ((QString ("%1").arg (
344  uiwidget_creator.get_dialog_result ())).toStdString ());
345 
347 
348  return retval;
349  }
350 
351  // Prompt to allow file to be run by setting cwd (or if addpath_option==true,
352  // alternatively setting the path).
353  // This uses a QMessageBox unlike other functions in this file,
354  // because uiwidget_creator.waitcondition.wait hangs when called from
355  // file_editor_tab::handle_context_menu_break_condition(). (FIXME: why hang?)
357  const std::string& dir,
358  bool addpath_option)
359  {
360  int retval = -1;
361 
362  QString qdir = QString::fromStdString (dir);
363  QString qfile = QString::fromStdString (file);
364  QString msg
365  = (addpath_option
366  ? tr ("The file %1 does not exist in the load path. To run or debug the function you are editing, you must either change to the directory %2 or add that directory to the load path.").arg (qfile).arg (qdir)
367  : tr ("The file %1 is shadowed by a file with the same name in the load path. To run or debug the function you are editing, change to the directory %2.").arg (qfile).arg (qdir));
368 
369  QString title = tr ("Change Directory or Add Directory to Load Path");
370 
371  QString cd_txt = tr ("&Change Directory");
372  QString addpath_txt = tr ("&Add Directory to Load Path");
373  QString cancel_txt = tr ("Cancel");
374 
375  QStringList btn;
376  QStringList role;
377  btn << cd_txt;
378  role << "YesRole";
379  if (addpath_option)
380  {
381  btn << addpath_txt;
382  role << "AcceptRole";
383  }
384  btn << cancel_txt;
385  role << "RejectRole";
386 
387  // Lock mutex before signaling.
389 
390  uiwidget_creator.signal_dialog (msg, title, "quest", btn, cancel_txt, role);
391 
392  // Wait while the user is responding to message box.
394 
395  // The GUI has sent a signal and the thread has been awakened.
396 
398 
400 
401  if (result == cd_txt)
402  retval = 1;
403  else if (result == addpath_txt)
404  retval = 2;
405 
406  return retval;
407  }
408 
410  {
412  }
413 
415  (const std::string& command)
416  {
418  }
419 
420  void octave_qt_link::do_set_workspace (bool top_level, bool debug,
421  const symbol_scope& scope,
422  bool update_variable_editor)
423  {
424  if (! top_level && ! debug)
425  return;
426 
427  emit set_workspace_signal (top_level, debug, scope);
428 
429  if (update_variable_editor)
431  }
432 
434  {
435  emit clear_workspace_signal ();
436  }
437 
439  {
440  QStringList qt_hist;
441 
442  for (octave_idx_type i = 0; i < hist.numel (); i++)
443  qt_hist.append (QString::fromStdString (hist[i]));
444 
445  emit set_history_signal (qt_hist);
446  }
447 
448  void octave_qt_link::do_append_history (const std::string& hist_entry)
449  {
450  emit append_history_signal (QString::fromStdString (hist_entry));
451  }
452 
454  {
455  emit clear_history_signal ();
456  }
457 
459  { }
460 
462  { }
463 
465  int line)
466  {
468 
469  emit enter_debugger_signal ();
470  }
471 
473  int line)
474  {
476  }
477 
479  {
480  emit exit_debugger_signal ();
481  }
482 
483  // Display (if @insert true) or remove the appropriate symbol for a breakpoint
484  // in @file at @line with condition @cond.
485  void octave_qt_link::do_update_breakpoint (bool insert,
486  const std::string& file,
487  int line,
488  const std::string& cond)
489  {
491  line, QString::fromStdString (cond));
492  }
493 
495  std::string& ps2,
496  std::string& ps4)
497  {
498  if (m_app_context->start_gui_p ())
499  {
500  ps1 = ">> ";
501  ps2 = "";
502  ps4 = "";
503  }
504  }
505 
507  const std::string& dir)
508  {
509 
510  bool ok = false;
511  bool addpath_option = true;
512 
514 
515  if (same_file (curr_dir, dir))
516  ok = true;
517  else
518  {
519  load_path& lp = __get_load_path__ ("octave_qt_link::file_in_path");
520 
521  bool dir_in_load_path = lp.contains_canonical (dir);
522 
523  // get base name, allowing "@class/method.m" (bug #41514)
524  std::string base_file = (file.length () > dir.length ())
525  ? file.substr (dir.length () + 1)
527 
528  std::string lp_file = lp.find_file (base_file);
529 
530  if (dir_in_load_path)
531  {
532  if (same_file (lp_file, file))
533  ok = true;
534  }
535  else
536  {
537  // File directory is not in path. Is the file in the path in
538  // the current directory? If so, then changing the current
539  // directory will be needed. Adding directory to path is
540  // not enough because the file in the current directory would
541  // still be found.
542 
543  if (same_file (lp_file, base_file))
544  {
545  if (same_file (curr_dir, dir))
546  ok = true;
547  else
548  addpath_option = false;
549  }
550  }
551  }
552 
553  if (! ok)
554  {
555  int action = debug_cd_or_addpath_error (file, dir, addpath_option);
556  switch (action)
557  {
558  case 1:
559  Fcd (ovl (dir));
560  ok = true;
561  break;
562 
563  case 2:
564  {
565  load_path& lp = __get_load_path__ ("octave_qt_link::file_in_path");
566 
567  lp.prepend (dir);
568  ok = true;
569  }
570  break;
571 
572  default:
573  break;
574  }
575  }
576 
577  return ok;
578  }
579 
581  {
582  emit show_preferences_signal ();
583  }
584 
586  {
588  }
589 
591  {
593  }
594 
596  {
598  }
599 
601  const octave_value& val)
602  {
604  }
605 
607  int line)
608  {
610  }
611 
613  int line)
614  {
616  }
617 }
bool signal_filedialog(const QStringList &filters, const QString &title, const QString &filename, const QString &dirname, const QString &multimode)
Definition: dialog.h:113
static std::string get_current_directory(void)
Definition: oct-env.cc:136
For example cd octave end example noindent changes the current working directory to file
Definition: dirfns.cc:124
bool same_file(const std::string &f, const std::string &g)
Definition: utils.cc:130
The value of lines which begin with a space character are not saved in the history list A value of all commands are saved on the history list
Definition: oct-hist.cc:734
void signal_dialog(const QString &message, const QString &title, const QString &icon, const QStringList &button, const QString &defbutton, const QStringList &role)
Definition: dialog.h:59
identity matrix If supplied two scalar respectively For allows like xample val
Definition: data.cc:4986
Return the CPU time used by your Octave session The first output is the total time spent executing your process and is equal to the sum of second and third which are the number of CPU seconds spent executing in user mode and the number of CPU seconds spent executing in system mode
Definition: data.cc:6348
bool signal_inputlayout(const QStringList &prompt, const QString &title, const QFloatList &nr, const QFloatList &nc, const QStringList &defaults)
Definition: dialog.h:99
QString fromStdString(const std::string &s)
std::string filename
Definition: urlwrite.cc:121
std::string dirname(const std::string &path)
Definition: file-ops.cc:353
to define functions rather than attempting to enter them directly on the command line The block of commands is executed as soon as you exit the editor To avoid executing any simply delete all the lines from the buffer before leaving the editor When invoked with no edit the previously executed command
Definition: oct-hist.cc:587
octave_value arg
Definition: pr-output.cc:3244
static bool debug
nd deftypefn *std::string name
Definition: sysdep.cc:647
bool signal_listview(const QStringList &list, const QString &mode, int wd, int ht, const QList< int > &initial, const QString &name, const QStringList &prompt, const QString &ok_string, const QString &cancel_string)
Definition: dialog.h:82
octave_value retval
Definition: data.cc:6246
int get_dialog_result(void)
Definition: dialog.h:78
MArray< T > filter(MArray< T > &b, MArray< T > &a, MArray< T > &x, MArray< T > &si, int dim=0)
Definition: filter.cc:43
static std::string base_pathname(const std::string &s)
Definition: oct-env.cc:122
const QStringList * get_string_list(void)
Definition: dialog.h:111
QString get_dialog_button(void)
Definition: dialog.h:80
load_path & __get_load_path__(const std::string &who)
With real return the complex result
Definition: data.cc:3260
bool start_gui_p(void) const
Definition: octave-gui.cc:80
OCTAVE_EXPORT octave_value_list isa nd deftypefn *return ovl(args(0).isinteger())
const QIntList * get_list_index(void)
Definition: dialog.h:97
OCTAVE_EXPORT octave_value_list Fcd(const octave_value_list &args, int nargout) the current directory is changed to the user 's home directory(@qcode
Definition: dirfns.cc:124
static QSettings * get_settings(void)
for i
Definition: data.cc:5264
QList< int > QIntList
Definition: dialog.h:38
octave_idx_type numel(void) const
Number of elements in the array.
Definition: Array.h:366
const QString * get_dialog_path(void)
Definition: dialog.h:121
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
QUIWidgetCreator uiwidget_creator
Definition: dialog.cc:46