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
octave-qt-link.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 Copyright (C) 2011-2015 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 the
11 Free Software Foundation; either version 3 of the License, or (at your
12 option) any later version.
13 
14 Octave is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
17 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 <http://www.gnu.org/licenses/>.
22 
23 */
24 
25 #ifdef HAVE_CONFIG_H
26 #include <config.h>
27 #endif
28 
29 #include <QStringList>
30 #include <QDialog>
31 #include <QDir>
32 
33 #include "str-vec.h"
34 #include "dialog.h"
35 #include "error.h"
36 #include "workspace-element.h"
37 #include "builtin-defun-decls.h"
38 #include "load-path.h"
39 #include "oct-env.h"
40 #include "utils.h"
41 
42 #include "octave-qt-link.h"
43 
44 #include "resource-manager.h"
45 
47  : octave_link (), main_thread (new QThread ()),
48  command_interpreter (new octave_interpreter ())
49 {
50  _current_directory = "";
51  _new_dir = true;
52 
53  connect (this, SIGNAL (execute_interpreter_signal (void)),
54  command_interpreter, SLOT (execute (void)));
55 
56  connect (command_interpreter, SIGNAL (octave_ready_signal ()),
57  p, SLOT (handle_octave_ready ()));
58 
59  command_interpreter->moveToThread (main_thread);
60 
61  main_thread->start ();
62 }
63 
65 
66 void
68 {
70 }
71 
72 bool
74 {
75  // Lock the mutex before emitting signal.
76  mutex.lock ();
77 
79 
80  // Wait while the GUI shuts down.
81  waitcondition.wait (&mutex);
82 
83  // The GUI has sent a signal and the thread has been awakened.
84 
85  mutex.unlock ();
86 
88 }
89 
90 bool
92 {
93  emit exit_app_signal (status);
94 
95  // Could wait for a while and then timeout, but for now just
96  // assume the GUI application exit will be without problems.
97  return true;
98 }
99 
100 bool
102 {
104 
105  return true;
106 }
107 
108 bool
109 octave_qt_link::do_edit_file (const std::string& file)
110 {
112 
113  return true;
114 }
115 
116 bool
118 {
119  QSettings *settings = resource_manager::get_settings ();
120 
121  if (settings->value ("editor/create_new_file",false).toBool ())
122  return true;
123 
124  QFileInfo file_info (QString::fromStdString (file));
125  QStringList btn;
126  QStringList role;
127  role << "YesRole" << "RejectRole";
128  btn << tr ("Create") << tr ("Cancel");
129 
130  // Lock mutex before signaling.
131  uiwidget_creator.mutex.lock ();
132 
134  tr ("File\n%1\ndoes not exist. Do you want to create it?").
135  arg (QDir::currentPath () + QDir::separator ()
136  + QString::fromStdString (file)),
137  tr ("Octave Editor"), "quest", btn, tr ("Create"), role );
138 
139  // Wait while the user is responding to message box.
141 
142  // The GUI has sent a signal and the thread has been awakened.
143 
144  QString answer = uiwidget_creator.get_dialog_button ();
145 
146  uiwidget_creator.mutex.unlock ();
147 
148  return (answer == tr ("Create"));
149 }
150 
151 int
152 octave_qt_link::do_message_dialog (const std::string& dlg,
153  const std::string& msg,
154  const std::string& title)
155 {
156  // Lock mutex before signaling.
157  uiwidget_creator.mutex.lock ();
158 
160  QString::fromStdString (title),
162  QStringList (), QString (),
163  QStringList ());
164 
165  // Wait while the user is responding to message box.
167 
168  // The GUI has sent a signal and the thread has been awakened.
169 
170  int answer = uiwidget_creator.get_dialog_result ();
171 
172  uiwidget_creator.mutex.unlock ();
173 
174  return answer;
175 }
176 
177 std::string
178 octave_qt_link::do_question_dialog (const std::string& msg,
179  const std::string& title,
180  const std::string& btn1,
181  const std::string& btn2,
182  const std::string& btn3,
183  const std::string& btndef)
184 {
185  QStringList btn;
186  QStringList role;
187  role << "AcceptRole" << "AcceptRole" << "AcceptRole";
188  btn << QString::fromStdString (btn1);
189  if (btn2 == "")
190  role.removeAt (0);
191  else
192  btn << QString::fromStdString (btn2);
193  btn << QString::fromStdString (btn3);
194 
195  // Lock mutex before signaling.
196  uiwidget_creator.mutex.lock ();
197 
198  uiwidget_creator.signal_dialog (QString::fromStdString (msg),
199  QString::fromStdString (title),
200  "quest",
201  btn,
202  QString::fromStdString (btndef),
203  role);
204 
205  // Wait while the user is responding to message box.
207 
208  // The GUI has sent a signal and the thread has been awakened.
209 
210  std::string answer = uiwidget_creator.get_dialog_button ().toStdString ();
211 
212  uiwidget_creator.mutex.unlock ();
213 
214  return answer;
215 }
216 
217 static QStringList
218 make_qstring_list (const std::list<std::string>& lst)
219 {
220  QStringList retval;
221 
222  for (std::list<std::string>::const_iterator it = lst.begin ();
223  it != lst.end (); it++)
224  {
225  retval.append (QString::fromStdString (*it));
226  }
227 
228  return retval;
229 }
230 
231 static QStringList
233 {
234  QStringList retval;
235 
236  // We have pairs of data, first being the list of extensions
237  // exta;exb;extc etc second the name to use as filter name
238  // (optional). Qt wants a a list of filters in the format of
239  // 'FilterName (space separated exts)'.
240 
241  for (octave_link::filter_list::const_iterator it = lst.begin ();
242  it != lst.end (); it++)
243  {
244  QString ext = QString::fromStdString (it->first);
245  QString name = QString::fromStdString (it->second);
246 
247  // Strip out extensions from name and replace ';' with spaces in
248  // list.
249 
250  name.replace (QRegExp ("\\(.*\\)"), "");
251  ext.replace (";", " ");
252 
253  if (name.length () == 0)
254  {
255  // No name field. Build one from the extensions.
256  name = ext.toUpper () + " Files";
257  }
258 
259  retval.append (name + " (" + ext + ")");
260  }
261 
262  return retval;
263 }
264 
265 std::pair<std::list<int>, int>
266 octave_qt_link::do_list_dialog (const std::list<std::string>& list,
267  const std::string& mode,
268  int width, int height,
269  const std::list<int>& initial,
270  const std::string& name,
271  const std::list<std::string>& prompt,
272  const std::string& ok_string,
273  const std::string& cancel_string)
274 {
275  // Lock mutex before signaling.
276  uiwidget_creator.mutex.lock ();
277 
279  QString::fromStdString (mode),
280  width, height,
281  QList<int>::fromStdList (initial),
282  QString::fromStdString (name),
283  make_qstring_list (prompt),
284  QString::fromStdString (ok_string),
285  QString::fromStdString (cancel_string));
286 
287  // Wait while the user is responding to message box.
289 
290  // The GUI has sent a signal and the thread has been awakened.
291 
292  const QIntList *selected = uiwidget_creator.get_list_index ();
294 
295  uiwidget_creator.mutex.unlock ();
296 
297  return std::pair<std::list<int>, int> (selected->toStdList (), ok);
298 }
299 
300 std::list<std::string>
301 octave_qt_link::do_input_dialog (const std::list<std::string>& prompt,
302  const std::string& title,
303  const std::list<float>& nr,
304  const std::list<float>& nc,
305  const std::list<std::string>& defaults)
306 {
307  std::list<std::string> retval;
308 
309  // Lock mutex before signaling.
310  uiwidget_creator.mutex.lock ();
311 
313  QString::fromStdString (title),
314  QFloatList::fromStdList (nr),
315  QFloatList::fromStdList (nc),
316  make_qstring_list (defaults));
317 
318  // Wait while the user is responding to message box.
320 
321  // The GUI has sent a signal and the thread has been awakened.
322 
323  const QStringList *inputLine = uiwidget_creator.get_string_list ();
324 
325  uiwidget_creator.mutex.unlock ();
326 
327  for (QStringList::const_iterator it = inputLine->begin ();
328  it != inputLine->end (); it++)
329  {
330  retval.push_back (it->toStdString ());
331  }
332 
333  return retval;
334 }
335 
336 std::list<std::string>
338  const std::string& title,
339  const std::string& filename,
340  const std::string& dirname,
341  const std::string& multimode)
342 {
343  std::list<std::string> retval;
344 
345  // Lock mutex before signaling.
346  uiwidget_creator.mutex.lock ();
347 
349  QString::fromStdString (title),
350  QString::fromStdString (filename),
351  QString::fromStdString (dirname),
352  QString::fromStdString (multimode));
353 
354  // Wait while the user is responding to dialog.
356 
357  // The GUI has sent a signal and the thread has been awakened.
358 
359  // Add all the file dialog results to a string list.
360  const QStringList *inputLine = uiwidget_creator.get_string_list ();
361 
362  for (QStringList::const_iterator it = inputLine->begin ();
363  it != inputLine->end (); it++)
364  retval.push_back (it->toStdString ());
365 
366  retval.push_back (uiwidget_creator.get_dialog_path ()->toStdString ());
367  retval.push_back ((QString ("%1").arg (
368  uiwidget_creator.get_dialog_result ())).toStdString ());
369 
370  uiwidget_creator.mutex.unlock ();
371 
372  return retval;
373 }
374 
375 int
377  const std::string& dir,
378  bool addpath_option)
379 {
380  int retval = -1;
381 
382  QString qdir = QString::fromStdString (dir);
383  QString qfile = QString::fromStdString (file);
384 
385  QString msg
386  = (addpath_option
387  ? 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)
388  : 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));
389 
390  QString title = tr ("Change Directory or Add Directory to Load Path");
391 
392  QString cd_txt = tr ("Change Directory");
393  QString addpath_txt = tr ("Add Directory to Load Path");
394  QString cancel_txt = tr ("Cancel");
395 
396  QStringList btn;
397  QStringList role;
398  btn << cd_txt;
399  role << "AcceptRole";
400  if (addpath_option)
401  {
402  btn << addpath_txt;
403  role << "AcceptRole";
404  }
405  btn << cancel_txt;
406  role << "AcceptRole";
407 
408  // Lock mutex before signaling.
409  uiwidget_creator.mutex.lock ();
410 
411  uiwidget_creator.signal_dialog (msg, title, "quest", btn, cancel_txt, role);
412 
413  // Wait while the user is responding to message box.
415 
416  // The GUI has sent a signal and the thread has been awakened.
417 
418  QString result = uiwidget_creator.get_dialog_button ();
419 
420  uiwidget_creator.mutex.unlock ();
421 
422  if (result == cd_txt)
423  retval = 1;
424  else if (result == addpath_txt)
425  retval = 2;
426 
427  return retval;
428 }
429 
430 void
431 octave_qt_link::do_change_directory (const std::string& dir)
432 {
434  _new_dir = true;
435 }
436 
437 void
439 {
441  _new_dir = false;
442 }
443 
444 void
446 {
448 }
449 
450 void
452  const std::list<workspace_element>& ws)
453 {
454  if (! top_level && ! debug)
455  return;
456 
457  if (_new_dir)
458  update_directory ();
459 
460  QString scopes;
461  QStringList symbols;
462  QStringList class_names;
463  QStringList dimensions;
464  QStringList values;
465  QIntList complex_flags;
466 
467  for (std::list<workspace_element>::const_iterator it = ws.begin ();
468  it != ws.end (); it++)
469  {
470  scopes.append (it->scope ());
471  symbols.append (QString::fromStdString (it->symbol ()));
472  class_names.append (QString::fromStdString (it->class_name ()));
473  dimensions.append (QString::fromStdString (it->dimension ()));
474  values.append (QString::fromStdString (it->value ()));
475  complex_flags.append (it->complex_flag ());
476  }
477 
478  emit set_workspace_signal (top_level, debug, scopes, symbols, class_names,
479  dimensions, values, complex_flags);
480 }
481 
482 void
484 {
485  emit clear_workspace_signal ();
486 }
487 
488 void
490 {
491  QStringList qt_hist;
492 
493  for (octave_idx_type i = 0; i < hist.length (); i++)
494  qt_hist.append (QString::fromStdString (hist[i]));
495 
496  emit set_history_signal (qt_hist);
497 }
498 
499 void
500 octave_qt_link::do_append_history (const std::string& hist_entry)
501 {
502  emit append_history_signal (QString::fromStdString (hist_entry));
503 }
504 
505 void
507 {
508  emit clear_history_signal ();
509 }
510 
511 void
513 {
514 }
515 
516 void
518 {
519 }
520 
521 void
522 octave_qt_link::do_enter_debugger_event (const std::string& file, int line)
523 {
524  do_insert_debugger_pointer (file, line);
525 
526  emit enter_debugger_signal ();
527 }
528 
529 void
531 {
532  do_delete_debugger_pointer (file, line);
533 }
534 
535 void
537 {
538  emit exit_debugger_signal ();
539 }
540 
541 void
543  const std::string& file, int line)
544 {
546  line);
547 }
548 
549 void
550 octave_qt_link::do_set_default_prompts (std::string& ps1, std::string& ps2,
551  std::string& ps4)
552 {
553  ps1 = ">> ";
554  ps2 = "";
555  ps4 = "";
556 }
557 
558 
559 void
560 octave_qt_link::do_insert_debugger_pointer (const std::string& file, int line)
561 {
563 }
564 
565 void
566 octave_qt_link::do_delete_debugger_pointer (const std::string& file, int line)
567 {
569 }
570 
571 
572 bool
573 octave_qt_link::file_in_path (const std::string& file, const std::string& dir)
574 {
575 
576  bool ok = false;
577  bool addpath_option = true;
578 
579  std::string curr_dir = octave_env::get_current_directory ();
580 
581  if (same_file (curr_dir, dir))
582  ok = true;
583  else
584  {
585  bool dir_in_load_path = load_path::contains_canonical (dir);
586 
587  std::string base_file = octave_env::base_pathname (file);
588  std::string lp_file = load_path::find_file (base_file);
589 
590  if (dir_in_load_path)
591  {
592  if (same_file (lp_file, file))
593  ok = true;
594  }
595  else
596  {
597  // File directory is not in path. Is the file in the path in
598  // the current directory? If so, then changing the current
599  // directory will be needed. Adding directory to path is
600  // not enough because the file in the current directory would
601  // still be found.
602 
603  if (same_file (lp_file, base_file))
604  {
605  if (same_file (curr_dir, dir))
606  ok = true;
607  else
608  addpath_option = false;
609  }
610  }
611  }
612 
613  if (! ok)
614  {
615  int action = debug_cd_or_addpath_error (file, dir, addpath_option);
616  switch (action)
617  {
618  case 1:
619  Fcd (ovl (dir));
620  ok = true;
621  break;
622 
623  case 2:
624  load_path::prepend (dir);
625  ok = true;
626  break;
627 
628  default:
629  break;
630  }
631  }
632 
633  return ok;
634 }
635 
636 void
638 {
639  emit show_preferences_signal ();
640 }
641 
642 void
643 octave_qt_link::do_show_doc (const std::string& file)
644 {
646 }
647 
648 void
650 {
652 }
void signal_dialog(const QString &message, const QString &title, const QString &icon, const QStringList &button, const QString &defbutton, const QStringList &role)
Definition: dialog.h:56
bool same_file(const std::string &f, const std::string &g)
Definition: utils.cc:133
bool signal_filedialog(const QStringList &filters, const QString &title, const QString &filename, const QString &dirname, const QString &multimode)
Definition: dialog.h:107
int get_dialog_result(void)
Definition: dialog.h:73
static void prepend(const std::string &dir, bool warn=false)
Definition: load-path.h:74
static std::string find_file(const std::string &file)
Definition: load-path.h:197
QString fromStdString(const std::string &s)
const QIntList * get_list_index(void)
Definition: dialog.h:91
QMutex mutex
Definition: dialog.h:120
QUIWidgetCreator uiwidget_creator
Definition: dialog.cc:44
const QStringList * get_string_list(void)
Definition: dialog.h:105
static std::string get_current_directory(void)
Definition: oct-env.cc:139
MArray< double > filter(MArray< double > &, MArray< double > &, MArray< double > &, int dim)
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:77
static bool contains_canonical(const std::string &dir_name)
Definition: load-path.h:91
static QSettings * get_settings(void)
QWaitCondition waitcondition
Definition: dialog.h:121
double arg(double x)
Definition: lo-mappers.h:37
static std::string base_pathname(const std::string &s)
Definition: oct-env.cc:125
octave_idx_type length(void) const
Number of elements in the array.
Definition: Array.h:267
static bool debug
Definition: mkoctfile.cc:227
octave_value_list ovl(const octave_value &a0)
Definition: oct-obj.h:178
bool signal_inputlayout(const QStringList &prompt, const QString &title, const QFloatList &nr, const QFloatList &nc, const QStringList &defaults)
Definition: dialog.h:93
const QString * get_dialog_path(void)
Definition: dialog.h:115
QList< int > QIntList
Definition: dialog.h:38
QString get_dialog_button(void)
Definition: dialog.h:75
OCTINTERP_API octave_value_list Fcd(const octave_value_list &=octave_value_list(), int=0)
Definition: dirfns.cc:123