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
octave-qt-link.cc
Go to the documentation of this file.
1 /*
2 
3 Copyright (C) 2013 John W. Eaton
4 Copyright (C) 2011-2013 Jacob Dawid
5 Copyright (C) 2011-2013 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  connect (this, SIGNAL (execute_interpreter_signal (void)),
51  command_interpreter, SLOT (execute (void)));
52 
53  command_interpreter->moveToThread (main_thread);
54 
55  main_thread->start ();
56 }
57 
59 
60 void
62 {
64 }
65 
66 bool
68 {
69  emit exit_signal (status);
70 
71  return true;
72 }
73 
74 bool
75 octave_qt_link::do_edit_file (const std::string& file)
76 {
77  emit edit_file_signal (QString::fromStdString (file));
78 
79  return true;
80 }
81 
82 bool
83 octave_qt_link::do_prompt_new_edit_file (const std::string& file)
84 {
85  QSettings *settings = resource_manager::get_settings ();
86 
87  if (settings->value ("editor/create_new_file",false).toBool ())
88  return true;
89 
90  QFileInfo file_info (QString::fromStdString (file));
91  QStringList btn;
92  QStringList role;
93  role << "AcceptRole" << "AcceptRole";
94  btn << tr ("Yes") << tr ("No");
95 
97  tr ("File\n%1\ndoes not exist. Do you want to create it?").
98  arg (QDir::currentPath () + QDir::separator ()
99  + QString::fromStdString (file)),
100  tr ("Octave Editor"), "quest", btn, tr ("Yes"), role );
101 
102  // Wait while the user is responding to message box.
104  // The GUI has sent a signal and the process has been awakened.
105  QString answer = uiwidget_creator.get_dialog_button ();
106 
107  return (answer == tr ("Yes"));
108 }
109 
110 int
111 octave_qt_link::do_message_dialog (const std::string& dlg,
112  const std::string& msg,
113  const std::string& title)
114 {
115  uiwidget_creator.signal_dialog (QString::fromStdString (msg),
116  QString::fromStdString (title),
117  QString::fromStdString (dlg),
118  QStringList (), QString (),
119  QStringList ());
120 
121  // Wait while the user is responding to message box.
123 
124  // The GUI has sent a signal and the process has been awakened.
126 }
127 
128 std::string
129 octave_qt_link::do_question_dialog (const std::string& msg,
130  const std::string& title,
131  const std::string& btn1,
132  const std::string& btn2,
133  const std::string& btn3,
134  const std::string& btndef)
135 {
136  QStringList btn;
137  QStringList role;
138  role << "AcceptRole" << "AcceptRole" << "AcceptRole";
139  btn << QString::fromStdString (btn1);
140  if (btn2 == "")
141  role.removeAt (0);
142  else
143  btn << QString::fromStdString (btn2);
144  btn << QString::fromStdString (btn3);
145 
146  uiwidget_creator.signal_dialog (QString::fromStdString (msg),
147  QString::fromStdString (title),
148  "quest",
149  btn,
150  QString::fromStdString (btndef),
151  role);
152 
153  // Wait while the user is responding to message box.
155 
156  // The GUI has sent a signal and the process has been awakened.
157  return uiwidget_creator.get_dialog_button ().toStdString ();
158 }
159 
160 static QStringList
161 make_qstring_list (const std::list<std::string>& lst)
162 {
163  QStringList retval;
164 
165  for (std::list<std::string>::const_iterator it = lst.begin ();
166  it != lst.end (); it++)
167  {
168  retval.append (QString::fromStdString (*it));
169  }
170 
171  return retval;
172 }
173 
174 static QStringList
176 {
177  QStringList retval;
178 
179  // We have pairs of data, first being the list of extensions
180  // exta;exb;extc etc second the name to use as filter name
181  // (optional). Qt wants a a list of filters in the format of
182  // 'FilterName (space separated exts)'.
183 
184  for (octave_link::filter_list::const_iterator it = lst.begin ();
185  it != lst.end (); it++)
186  {
187  QString ext = QString::fromStdString (it->first);
188  QString name = QString::fromStdString (it->second);
189 
190  // Strip out extensions from name and replace ';' with spaces in
191  // list.
192 
193  name.replace (QRegExp ("\\(.*\\)"), "");
194  ext.replace (";", " ");
195 
196  if (name.length () == 0)
197  {
198  // No name field. Build one from the extensions.
199  name = ext.toUpper () + " Files";
200  }
201 
202  retval.append (name + " (" + ext + ")");
203  }
204 
205  return retval;
206 }
207 
208 std::pair<std::list<int>, int>
209 octave_qt_link::do_list_dialog (const std::list<std::string>& list,
210  const std::string& mode,
211  int width, int height,
212  const std::list<int>& initial,
213  const std::string& name,
214  const std::list<std::string>& prompt,
215  const std::string& ok_string,
216  const std::string& cancel_string)
217 {
219  QString::fromStdString (mode),
220  width, height,
221  QList<int>::fromStdList (initial),
222  QString::fromStdString (name),
223  make_qstring_list (prompt),
224  QString::fromStdString (ok_string),
225  QString::fromStdString (cancel_string));
226 
227  // Wait while the user is responding to message box.
229 
230  // The GUI has sent a signal and the process has been awakened.
231  const QIntList *selected = uiwidget_creator.get_list_index ();
233 
234  return std::pair<std::list<int>, int> (selected->toStdList (), ok);
235 }
236 
237 std::list<std::string>
238 octave_qt_link::do_input_dialog (const std::list<std::string>& prompt,
239  const std::string& title,
240  const std::list<float>& nr,
241  const std::list<float>& nc,
242  const std::list<std::string>& defaults)
243 {
244  std::list<std::string> retval;
245 
247  QString::fromStdString (title),
248  QFloatList::fromStdList (nr),
249  QFloatList::fromStdList (nc),
250  make_qstring_list (defaults));
251 
252  // Wait while the user is responding to message box.
254 
255  // The GUI has sent a signal and the process has been awakened.
256  const QStringList *inputLine = uiwidget_creator.get_string_list ();
257 
258  for (QStringList::const_iterator it = inputLine->begin ();
259  it != inputLine->end (); it++)
260  {
261  retval.push_back (it->toStdString ());
262  }
263 
264  return retval;
265 }
266 
267 std::list<std::string>
269  const std::string& title,
270  const std::string& filename,
271  const std::string& dirname,
272  const std::string& multimode)
273 {
274  std::list<std::string> retval;
275 
277  QString::fromStdString (title),
278  QString::fromStdString (filename),
279  QString::fromStdString (dirname),
280  QString::fromStdString (multimode));
281 
282  // Wait while the user is responding to dialog.
284 
285  // Add all the file dialog results to a string list.
286  const QStringList *inputLine = uiwidget_creator.get_string_list ();
287 
288  for (QStringList::const_iterator it = inputLine->begin ();
289  it != inputLine->end (); it++)
290  retval.push_back (it->toStdString ());
291 
292  retval.push_back (uiwidget_creator.get_dialog_path ()->toStdString ());
293  retval.push_back ((QString ("%1").arg (
294  uiwidget_creator.get_dialog_result ())).toStdString ());
295 
296  return retval;
297 }
298 
299 int
301  const std::string& dir,
302  bool addpath_option)
303 {
304  int retval = -1;
305 
306  QString qdir = QString::fromStdString (dir);
307  QString qfile = QString::fromStdString (file);
308 
309  QString msg
310  = (addpath_option
311  ? tr ("The file %1 does not exist in the load path. To 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)
312  : tr ("The file %1 is shadowed by a file with the same name in the load path. To debug the function you are editing, change to the directory %2.").arg (qfile).arg (qdir));
313 
314  QString title = tr ("Change Directory or Add Directory to Load Path");
315 
316  QString cd_txt = tr ("Change Directory");
317  QString addpath_txt = tr ("Add Directory to Load Path");
318  QString cancel_txt = tr ("Cancel");
319 
320  QStringList btn;
321  QStringList role;
322  btn << cd_txt;
323  role << "AcceptRole";
324  if (addpath_option)
325  {
326  btn << addpath_txt;
327  role << "AcceptRole";
328  }
329  btn << cancel_txt;
330  role << "AcceptRole";
331 
332  uiwidget_creator.signal_dialog (msg, title, "quest", btn, cancel_txt, role);
333 
334  // Wait while the user is responding to message box.
336 
337  QString result = uiwidget_creator.get_dialog_button ();
338 
339  if (result == cd_txt)
340  retval = 1;
341  else if (result == addpath_txt)
342  retval = 2;
343 
344  return retval;
345 }
346 
347 void
348 octave_qt_link::do_change_directory (const std::string& dir)
349 {
350  emit change_directory_signal (QString::fromStdString (dir));
351 }
352 
353 void
355 {
356  emit execute_command_in_terminal_signal (QString::fromStdString (command));
357 }
358 
359 void
361  const std::list<workspace_element>& ws)
362 {
363  QString scopes;
364  QStringList symbols;
365  QStringList class_names;
366  QStringList dimensions;
367  QStringList values;
368  QIntList complex_flags;
369 
370  for (std::list<workspace_element>::const_iterator it = ws.begin ();
371  it != ws.end (); it++)
372  {
373  scopes.append (it->scope ());
374  symbols.append (QString::fromStdString (it->symbol ()));
375  class_names.append (QString::fromStdString (it->class_name ()));
376  dimensions.append (QString::fromStdString (it->dimension ()));
377  values.append (QString::fromStdString (it->value ()));
378  complex_flags.append (it->complex_flag ());
379  }
380 
381  emit set_workspace_signal (top_level, scopes, symbols, class_names,
382  dimensions, values, complex_flags);
383 }
384 
385 void
387 {
388  emit clear_workspace_signal ();
389 }
390 
391 void
393 {
394  QStringList qt_hist;
395 
396  for (octave_idx_type i = 0; i < hist.length (); i++)
397  qt_hist.append (QString::fromStdString (hist[i]));
398 
399  emit set_history_signal (qt_hist);
400 }
401 
402 void
403 octave_qt_link::do_append_history (const std::string& hist_entry)
404 {
405  emit append_history_signal (QString::fromStdString (hist_entry));
406 }
407 
408 void
410 {
411  emit clear_history_signal ();
412 }
413 
414 void
416 {
417 }
418 
419 void
421 {
422 }
423 
424 void
425 octave_qt_link::do_enter_debugger_event (const std::string& file, int line)
426 {
427  do_insert_debugger_pointer (file, line);
428 
429  emit enter_debugger_signal ();
430 }
431 
432 void
434 {
435  do_delete_debugger_pointer (file, line);
436 }
437 
438 void
440 {
441  emit exit_debugger_signal ();
442 }
443 
444 void
446  const std::string& file, int line)
447 {
448  emit update_breakpoint_marker_signal (insert, QString::fromStdString (file),
449  line);
450 }
451 
452 void
453 octave_qt_link::do_set_default_prompts (std::string& ps1, std::string& ps2,
454  std::string& ps4)
455 {
456  ps1 = ">> ";
457  ps2 = "";
458  ps4 = "";
459 }
460 
461 
462 void
463 octave_qt_link::do_insert_debugger_pointer (const std::string& file, int line)
464 {
465  emit insert_debugger_pointer_signal (QString::fromStdString (file), line);
466 }
467 
468 void
469 octave_qt_link::do_delete_debugger_pointer (const std::string& file, int line)
470 {
471  emit delete_debugger_pointer_signal (QString::fromStdString (file), line);
472 }
473 
474 
475 bool
476 octave_qt_link::file_in_path (const std::string& file, const std::string& dir)
477 {
478 
479  bool ok = false;
480  bool addpath_option = true;
481 
482  std::string curr_dir = octave_env::get_current_directory ();
483 
484  if (same_file (curr_dir, dir))
485  ok = true;
486  else
487  {
488  bool dir_in_load_path = load_path::contains_canonical (dir);
489 
490  std::string base_file = octave_env::base_pathname (file);
491  std::string lp_file = load_path::find_file (base_file);
492 
493  if (dir_in_load_path)
494  {
495  if (same_file (lp_file, file))
496  ok = true;
497  }
498  else
499  {
500  // File directory is not in path. Is the file in the path in
501  // the current directory? If so, then changing the current
502  // directory will be needed. Adding directory to path is
503  // not enough because the file in the current directory would
504  // still be found.
505 
506  if (same_file (lp_file, base_file))
507  {
508  if (same_file (curr_dir, dir))
509  ok = true;
510  else
511  addpath_option = false;
512  }
513  }
514  }
515 
516  if (! ok)
517  {
518  int action = debug_cd_or_addpath_error (file, dir, addpath_option);
519  switch (action)
520  {
521  case 1:
522  Fcd (ovl (dir));
523  ok = true;
524  break;
525 
526  case 2:
527  load_path::prepend (dir);
528  ok = true;
529  break;
530 
531  default:
532  break;
533  }
534  }
535 
536  return ok;
537 }
538 
539 void
541 {
542  emit show_preferences_signal ();
543 }
544 
545 void
546 octave_qt_link::do_show_doc (const std::string& file)
547 {
548  emit show_doc_signal (QString::fromStdString (file));
549 }
550 
551 void
553 {
555 }