PageRenderTime 161ms CodeModel.GetById 57ms RepoModel.GetById 1ms app.codeStats 1ms

/libgui/src/main-window.cc

https://bitbucket.org/ttl/octave-ttl
C++ | 2354 lines | 1776 code | 460 blank | 118 comment | 127 complexity | e67221535b71e6a2f58a858c179bf5bf MD5 | raw file
Possible License(s): GPL-3.0, LGPL-2.0

Large files files are truncated, but you can click here to view the full file

  1. /*
  2. Copyright (C) 2013-2015 John W. Eaton
  3. Copyright (C) 2011-2015 Jacob Dawid
  4. This file is part of Octave.
  5. Octave is free software; you can redistribute it and/or modify it
  6. under the terms of the GNU General Public License as published by the
  7. Free Software Foundation; either version 3 of the License, or (at your
  8. option) any later version.
  9. Octave is distributed in the hope that it will be useful, but WITHOUT
  10. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  12. for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with Octave; see the file COPYING. If not, see
  15. <http://www.gnu.org/licenses/>.
  16. */
  17. #ifdef HAVE_CONFIG_H
  18. #include <config.h>
  19. #endif
  20. #include <QKeySequence>
  21. #include <QApplication>
  22. #include <QLabel>
  23. #include <QMenuBar>
  24. #include <QMenu>
  25. #include <QAction>
  26. #include <QSettings>
  27. #include <QStyle>
  28. #include <QToolBar>
  29. #include <QDesktopServices>
  30. #include <QDesktopWidget>
  31. #include <QFileDialog>
  32. #include <QMessageBox>
  33. #include <QIcon>
  34. #include <QTextStream>
  35. #include <QThread>
  36. #include <QDateTime>
  37. #include <QDebug>
  38. #include <utility>
  39. #ifdef HAVE_QSCINTILLA
  40. #include "file-editor.h"
  41. #endif
  42. #include "main-window.h"
  43. #include "settings-dialog.h"
  44. #include "shortcut-manager.h"
  45. #include "__init_qt__.h"
  46. #include "Array.h"
  47. #include "cmd-edit.h"
  48. #include "url-transfer.h"
  49. #include "builtin-defun-decls.h"
  50. #include "defaults.h"
  51. #include "symtab.h"
  52. #include "version.h"
  53. #include "utils.h"
  54. static file_editor_interface *
  55. create_default_editor (QWidget *p)
  56. {
  57. #ifdef HAVE_QSCINTILLA
  58. return new file_editor (p);
  59. #else
  60. return 0;
  61. #endif
  62. }
  63. main_window::main_window (QWidget *p)
  64. : QMainWindow (p),
  65. _workspace_model (new workspace_model ()),
  66. status_bar (new QStatusBar ()),
  67. command_window (new terminal_dock_widget (this)),
  68. history_window (new history_dock_widget (this)),
  69. file_browser_window (new files_dock_widget (this)),
  70. doc_browser_window (new documentation_dock_widget (this)),
  71. editor_window (create_default_editor (this)),
  72. workspace_window (new workspace_view (this)),
  73. _settings_dlg (0),
  74. find_files_dlg (0),
  75. release_notes_window (0),
  76. community_news_window (0),
  77. _octave_qt_link (0),
  78. _clipboard (QApplication::clipboard ()),
  79. _cmd_queue (QList<octave_cmd *> ()), // no command pending
  80. _cmd_processing (1),
  81. _cmd_queue_mutex (),
  82. _dbg_queue (new QStringList ()), // no debug pending
  83. _dbg_processing (1),
  84. _dbg_queue_mutex (),
  85. _prevent_readline_conflicts (true)
  86. {
  87. QSettings *settings = resource_manager::get_settings ();
  88. bool connect_to_web = true;
  89. QDateTime last_checked;
  90. int serial = 0;
  91. _active_dock = 0;
  92. if (settings)
  93. {
  94. connect_to_web
  95. = settings->value ("news/allow_web_connection", true).toBool ();
  96. last_checked
  97. = settings->value ("news/last_time_checked", QDateTime ()).toDateTime ();
  98. serial = settings->value ("news/last_news_item", 0).toInt ();
  99. }
  100. QDateTime current = QDateTime::currentDateTime ();
  101. QDateTime one_day_ago = current.addDays (-1);
  102. if (connect_to_web
  103. && (! last_checked.isValid () || one_day_ago > last_checked))
  104. load_and_display_community_news (serial);
  105. // We have to set up all our windows, before we finally launch octave.
  106. construct ();
  107. }
  108. main_window::~main_window (void)
  109. {
  110. // Destroy the terminal first so that STDERR stream is redirected back
  111. // to its original pipe to capture error messages at exit.
  112. delete editor_window; // first one for dialogs of modified editor-tabs
  113. delete command_window;
  114. delete workspace_window;
  115. delete doc_browser_window;
  116. delete file_browser_window;
  117. delete history_window;
  118. delete status_bar;
  119. delete _workspace_model;
  120. if (find_files_dlg)
  121. {
  122. delete find_files_dlg;
  123. find_files_dlg = 0;
  124. }
  125. if (release_notes_window)
  126. {
  127. delete release_notes_window;
  128. release_notes_window = 0;
  129. }
  130. if (_settings_dlg)
  131. {
  132. delete _settings_dlg;
  133. _settings_dlg = 0;
  134. }
  135. if (community_news_window)
  136. {
  137. delete community_news_window;
  138. community_news_window = 0;
  139. }
  140. delete _octave_qt_link;
  141. }
  142. // catch focus changes and determine the active dock widget
  143. void
  144. main_window::focus_changed (QWidget *, QWidget *new_widget)
  145. {
  146. octave_dock_widget* dock = 0;
  147. QWidget *w_new = new_widget; // get a copy of new focus widget
  148. QWidget *start = w_new; // Save it as start of our search
  149. int count = 0; // fallback to prevent endless loop
  150. while (w_new && w_new != _main_tool_bar && count < 100)
  151. {
  152. dock = qobject_cast <octave_dock_widget *> (w_new);
  153. if (dock)
  154. break; // it is a QDockWidget ==> exit loop
  155. #ifdef HAVE_QSCINTILLA
  156. if (qobject_cast <octave_qscintilla *> (w_new))
  157. {
  158. dock = static_cast<octave_dock_widget *> (editor_window);
  159. break; // it is the editor window ==> exit loop
  160. }
  161. #endif
  162. w_new = qobject_cast <QWidget *> (w_new->previousInFocusChain ());
  163. if (w_new == start)
  164. break; // we have arrived where we began ==> exit loop
  165. count++;
  166. }
  167. // editor needs extra handling
  168. octave_dock_widget *edit_dock_widget =
  169. static_cast<octave_dock_widget *> (editor_window);
  170. // if new dock has focus, emit signal and store active focus
  171. // except editor changes to a dialog (dock=0)
  172. if ((dock || _active_dock != edit_dock_widget) && (dock != _active_dock))
  173. {
  174. // signal to all dock widgets for updating the style
  175. emit active_dock_changed (_active_dock, dock);
  176. if (edit_dock_widget == dock)
  177. emit editor_focus_changed (true);
  178. else if (edit_dock_widget == _active_dock)
  179. emit editor_focus_changed (false);
  180. _active_dock = dock;
  181. }
  182. }
  183. bool
  184. main_window::command_window_has_focus (void) const
  185. {
  186. return command_window->has_focus ();
  187. }
  188. void
  189. main_window::focus_command_window (void)
  190. {
  191. command_window->focus ();
  192. }
  193. void
  194. main_window::new_file (const QString& commands)
  195. {
  196. emit new_file_signal (commands);
  197. }
  198. void
  199. main_window::open_file (const QString& file_name)
  200. {
  201. emit open_file_signal (file_name);
  202. }
  203. void
  204. main_window::report_status_message (const QString& statusMessage)
  205. {
  206. status_bar->showMessage (statusMessage, 1000);
  207. }
  208. void
  209. main_window::handle_save_workspace_request (void)
  210. {
  211. QString file =
  212. QFileDialog::getSaveFileName (this, tr ("Save Workspace As"), ".", 0, 0,
  213. QFileDialog::DontUseNativeDialog);
  214. if (! file.isEmpty ())
  215. octave_link::post_event (this, &main_window::save_workspace_callback,
  216. file.toStdString ());
  217. }
  218. void
  219. main_window::handle_load_workspace_request (const QString& file_arg)
  220. {
  221. QString file = file_arg;
  222. if (file.isEmpty ())
  223. file = QFileDialog::getOpenFileName (this, tr ("Load Workspace"), ".", 0, 0,
  224. QFileDialog::DontUseNativeDialog);
  225. if (! file.isEmpty ())
  226. octave_link::post_event (this, &main_window::load_workspace_callback,
  227. file.toStdString ());
  228. }
  229. void
  230. main_window::handle_clear_workspace_request (void)
  231. {
  232. octave_link::post_event (this, &main_window::clear_workspace_callback);
  233. }
  234. void
  235. main_window::handle_rename_variable_request (const QString& old_name,
  236. const QString& new_name)
  237. {
  238. name_pair names (old_name.toStdString (), new_name.toStdString ());
  239. octave_link::post_event (this, &main_window::rename_variable_callback,
  240. names);
  241. }
  242. void
  243. main_window::handle_undo_request (void)
  244. {
  245. octave_link::post_event (this, &main_window::command_window_undo_callback);
  246. }
  247. void
  248. main_window::handle_clear_command_window_request (void)
  249. {
  250. octave_link::post_event (this, &main_window::clear_command_window_callback);
  251. }
  252. void
  253. main_window::handle_clear_history_request (void)
  254. {
  255. octave_link::post_event (this, &main_window::clear_history_callback);
  256. }
  257. bool
  258. main_window::focus_console_after_command ()
  259. {
  260. QSettings *settings = resource_manager::get_settings ();
  261. return settings->value ("terminal/focus_after_command",false).toBool ();
  262. }
  263. void
  264. main_window::execute_command_in_terminal (const QString& command)
  265. {
  266. octave_cmd_exec *cmd = new octave_cmd_exec (command);
  267. queue_command (cmd);
  268. if (focus_console_after_command ())
  269. focus_command_window ();
  270. }
  271. void
  272. main_window::run_file_in_terminal (const QFileInfo& info)
  273. {
  274. octave_link::post_event (this, &main_window::run_file_callback, info);
  275. if (focus_console_after_command ())
  276. focus_command_window ();
  277. }
  278. void
  279. main_window::run_file_callback (const QFileInfo& info)
  280. {
  281. octave_cmd_eval *cmd = new octave_cmd_eval (info);
  282. queue_command (cmd);
  283. }
  284. void
  285. main_window::queue_command (octave_cmd* cmd)
  286. {
  287. _cmd_queue_mutex.lock ();
  288. _cmd_queue.append (cmd); // queue command and type
  289. _cmd_queue_mutex.unlock ();
  290. if (_cmd_processing.tryAcquire ()) // if callback not processing, post event
  291. octave_link::post_event (this, &main_window::execute_command_callback);
  292. }
  293. void
  294. main_window::handle_new_figure_request (void)
  295. {
  296. octave_link::post_event (this, &main_window::new_figure_callback);
  297. }
  298. void
  299. main_window::open_online_documentation_page (void)
  300. {
  301. QDesktopServices::openUrl (QUrl ("http://octave.org/doc/interpreter"));
  302. }
  303. void
  304. main_window::display_release_notes (void)
  305. {
  306. if (! release_notes_window)
  307. {
  308. std::string news_file = Voct_etc_dir + "/NEWS";
  309. QString news;
  310. QFile *file = new QFile (QString::fromStdString (news_file));
  311. if (file->open (QFile::ReadOnly))
  312. {
  313. QTextStream *stream = new QTextStream (file);
  314. news = stream->readAll ();
  315. if (! news.isEmpty ())
  316. {
  317. news.prepend ("<pre>");
  318. news.append ("</pre>");
  319. }
  320. else
  321. news = (tr ("The release notes file '%1' is empty.")
  322. . arg (QString::fromStdString (news_file)));
  323. }
  324. else
  325. news = (tr ("The release notes file '%1' cannot be read.")
  326. . arg (QString::fromStdString (news_file)));
  327. release_notes_window = new QWidget;
  328. QTextBrowser *browser = new QTextBrowser (release_notes_window);
  329. browser->setText (news);
  330. QVBoxLayout *vlayout = new QVBoxLayout;
  331. vlayout->addWidget (browser);
  332. release_notes_window->setLayout (vlayout);
  333. release_notes_window->setWindowTitle (tr ("Octave Release Notes"));
  334. browser->document()->adjustSize ();
  335. // center the window on the screen where octave is running
  336. QDesktopWidget *m_desktop = QApplication::desktop ();
  337. int screen = m_desktop->screenNumber (this); // screen of the main window
  338. QRect screen_geo = m_desktop->availableGeometry (screen);
  339. int win_x = screen_geo.width (); // width of the screen
  340. int win_y = screen_geo.height (); // height of the screen
  341. int reln_x = std::min (480, win_x-80); // desired width of release notes
  342. int reln_y = std::min (640, win_y-80); // desired height of release notes
  343. release_notes_window->resize (reln_x, reln_y); // set size
  344. release_notes_window->move (20, 0); // move to the top left corner
  345. }
  346. if (! release_notes_window->isVisible ())
  347. release_notes_window->show ();
  348. else if (release_notes_window->isMinimized ())
  349. release_notes_window->showNormal ();
  350. release_notes_window->setWindowIcon (QIcon (_release_notes_icon));
  351. release_notes_window->raise ();
  352. release_notes_window->activateWindow ();
  353. }
  354. void
  355. news_reader::process (void)
  356. {
  357. QString html_text;
  358. if (connect_to_web)
  359. {
  360. // Run this part in a separate thread so Octave can continue to
  361. // run while we wait for the page to load. Then emit the signal
  362. // to display it when we have the page contents.
  363. QString url = base_url + "/" + page;
  364. std::ostringstream buf;
  365. url_transfer octave_dot_org (url.toStdString (), buf);
  366. if (octave_dot_org.is_valid ())
  367. {
  368. Array<std::string> param;
  369. octave_dot_org.http_get (param);
  370. if (octave_dot_org.good ())
  371. html_text = QString::fromStdString (buf.str ());
  372. }
  373. if (html_text.contains ("this-is-the-gnu-octave-community-news-page"))
  374. {
  375. if (serial >= 0)
  376. {
  377. QSettings *settings = resource_manager::get_settings ();
  378. if (settings)
  379. {
  380. settings->setValue ("news/last_time_checked",
  381. QDateTime::currentDateTime ());
  382. settings->sync ();
  383. }
  384. QString tag ("community-news-page-serial=");
  385. int b = html_text.indexOf (tag);
  386. if (b)
  387. {
  388. b += tag.length ();
  389. int e = html_text.indexOf ("\n", b);
  390. QString tmp = html_text.mid (b, e-b);
  391. int curr_page_serial = tmp.toInt ();
  392. if (curr_page_serial > serial)
  393. {
  394. if (settings)
  395. {
  396. settings->setValue ("news/last_news_item",
  397. curr_page_serial);
  398. settings->sync ();
  399. }
  400. }
  401. else
  402. return;
  403. }
  404. else
  405. return;
  406. }
  407. }
  408. else
  409. html_text = QString
  410. (tr ("<html>\n"
  411. "<body>\n"
  412. "<p>\n"
  413. "Octave's community news source seems to be unavailable.\n"
  414. "</p>\n"
  415. "<p>\n"
  416. "For the latest news, please check\n"
  417. "<a href=\"http://octave.org/community-news.html\">http://octave.org/community-news.html</a>\n"
  418. "when you have a connection to the web (link opens in an external browser).\n"
  419. "</p>\n"
  420. "<p>\n"
  421. "<small><em>&mdash; The Octave Developers, ") + OCTAVE_RELEASE_DATE + "</em></small>\n"
  422. "</p>\n"
  423. "</body>\n"
  424. "</html>\n");
  425. }
  426. else
  427. html_text = QString
  428. (tr ("<html>\n"
  429. "<body>\n"
  430. "<p>\n"
  431. "Connecting to the web to display the latest Octave Community news has been disabled.\n"
  432. "</p>\n"
  433. "<p>\n"
  434. "For the latest news, please check\n"
  435. "<a href=\"http://octave.org/community-news.html\">http://octave.org/community-news.html</a>\n"
  436. "when you have a connection to the web (link opens in an external browser)\n"
  437. "or enable web connections for news in Octave's network settings dialog.\n"
  438. "</p>\n"
  439. "<p>\n"
  440. "<small><em>&mdash; The Octave Developers, ") + OCTAVE_RELEASE_DATE + "</em></small>\n"
  441. "</p>\n"
  442. "</body>\n"
  443. "</html>\n");
  444. emit display_news_signal (html_text);
  445. emit finished ();
  446. }
  447. void
  448. main_window::load_and_display_community_news (int serial)
  449. {
  450. QSettings *settings = resource_manager::get_settings ();
  451. bool connect_to_web
  452. = (settings
  453. ? settings->value ("news/allow_web_connection", true).toBool ()
  454. : true);
  455. QString base_url = "http://octave.org";
  456. QString page = "community-news.html";
  457. QThread *worker_thread = new QThread;
  458. news_reader *reader = new news_reader (base_url, page, serial,
  459. connect_to_web);
  460. reader->moveToThread (worker_thread);
  461. connect (reader, SIGNAL (display_news_signal (const QString&)),
  462. this, SLOT (display_community_news (const QString&)));
  463. connect (worker_thread, SIGNAL (started (void)),
  464. reader, SLOT (process ()));
  465. connect (reader, SIGNAL (finished (void)), worker_thread, SLOT (quit ()));
  466. connect (reader, SIGNAL (finished (void)), reader, SLOT (deleteLater ()));
  467. connect (worker_thread, SIGNAL (finished (void)),
  468. worker_thread, SLOT (deleteLater ()));
  469. worker_thread->start ();
  470. }
  471. void
  472. main_window::display_community_news (const QString& news)
  473. {
  474. if (! community_news_window)
  475. {
  476. community_news_window = new QWidget;
  477. QTextBrowser *browser = new QTextBrowser (community_news_window);
  478. browser->setHtml (news);
  479. browser->setObjectName ("OctaveNews");
  480. browser->setOpenExternalLinks (true);
  481. QVBoxLayout *vlayout = new QVBoxLayout;
  482. vlayout->addWidget (browser);
  483. community_news_window->setLayout (vlayout);
  484. community_news_window->setWindowTitle (tr ("Octave Community News"));
  485. // center the window on the screen where octave is running
  486. QDesktopWidget *m_desktop = QApplication::desktop ();
  487. int screen = m_desktop->screenNumber (this); // screen of the main window
  488. QRect screen_geo = m_desktop->availableGeometry (screen);
  489. int win_x = screen_geo.width (); // width of the screen
  490. int win_y = screen_geo.height (); // height of the screen
  491. int news_x = std::min (640, win_x-80); // desired width of news window
  492. int news_y = std::min (480, win_y-80); // desired height of news window
  493. community_news_window->resize (news_x, news_y); // set size and center
  494. community_news_window->move ((win_x - community_news_window->width ())/2,
  495. (win_y - community_news_window->height ())/2);
  496. }
  497. if (! community_news_window->isVisible ())
  498. community_news_window->show ();
  499. else if (community_news_window->isMinimized ())
  500. community_news_window->showNormal ();
  501. // same icon as release notes
  502. community_news_window->setWindowIcon (QIcon (_release_notes_icon));
  503. community_news_window->raise ();
  504. community_news_window->activateWindow ();
  505. }
  506. void
  507. main_window::open_bug_tracker_page (void)
  508. {
  509. QDesktopServices::openUrl (QUrl ("http://octave.org/bugs.html"));
  510. }
  511. void
  512. main_window::open_octave_packages_page (void)
  513. {
  514. QDesktopServices::openUrl (QUrl ("http://octave.org/packages.html"));
  515. }
  516. void
  517. main_window::open_agora_page (void)
  518. {
  519. QDesktopServices::openUrl (QUrl ("http://agora.octave.org"));
  520. }
  521. void
  522. main_window::open_contribute_page (void)
  523. {
  524. QDesktopServices::openUrl (QUrl ("http://octave.org/donate.html"));
  525. }
  526. void
  527. main_window::open_developer_page (void)
  528. {
  529. QDesktopServices::openUrl (QUrl ("http://octave.org/get-involved.html"));
  530. }
  531. void
  532. main_window::process_settings_dialog_request (const QString& desired_tab)
  533. {
  534. if (_settings_dlg) // _settings_dlg is a guarded pointer!
  535. { // here the dialog is still open and called once again
  536. if (! desired_tab.isEmpty ())
  537. _settings_dlg->show_tab (desired_tab);
  538. return;
  539. }
  540. _settings_dlg = new settings_dialog (this, desired_tab);
  541. connect (_settings_dlg, SIGNAL (apply_new_settings ()),
  542. this, SLOT (request_reload_settings ()));
  543. _settings_dlg->setModal (false);
  544. _settings_dlg->setAttribute (Qt::WA_DeleteOnClose);
  545. _settings_dlg->show ();
  546. }
  547. void
  548. main_window::request_reload_settings ()
  549. {
  550. QSettings *settings = resource_manager::get_settings ();
  551. if (settings)
  552. emit settings_changed (settings);
  553. }
  554. void
  555. main_window::notice_settings (const QSettings *settings)
  556. {
  557. // QSettings pointer is checked before emitting.
  558. // the widget's icons (when floating)
  559. QString icon_set
  560. = settings->value ("DockWidgets/widget_icon_set", "NONE").toString ();
  561. static struct
  562. {
  563. QString name;
  564. QString path;
  565. }
  566. widget_icon_data[] =
  567. {
  568. // array of possible icon sets (name, path (complete for NONE))
  569. // the first entry here is the default!
  570. {"NONE", ":/actions/icons/logo.png"},
  571. {"GRAPHIC", ":/actions/icons/graphic_logo_"},
  572. {"LETTER", ":/actions/icons/letter_logo_"},
  573. {"", ""} // end marker has empty name
  574. };
  575. int count = 0;
  576. int icon_set_found = 0; // default
  577. while (!widget_icon_data[count].name.isEmpty ())
  578. {
  579. // while not end of data
  580. if (widget_icon_data[count].name == icon_set)
  581. {
  582. // data of desired icon set found
  583. icon_set_found = count;
  584. break;
  585. }
  586. count++;
  587. }
  588. QString icon;
  589. foreach (octave_dock_widget *widget, dock_widget_list ())
  590. {
  591. QString name = widget->objectName ();
  592. if (! name.isEmpty ())
  593. { // if children has a name
  594. icon = widget_icon_data[icon_set_found].path; // prefix or octave-logo
  595. if (widget_icon_data[icon_set_found].name != "NONE")
  596. icon = icon + name + ".png"; // add widget name and ext.
  597. widget->setWindowIcon (QIcon (icon));
  598. }
  599. }
  600. if (widget_icon_data[icon_set_found].name != "NONE")
  601. _release_notes_icon = widget_icon_data[icon_set_found].path
  602. + "ReleaseWidget.png";
  603. else
  604. _release_notes_icon = ":/actions/icons/logo.png";
  605. int icon_size = settings->value ("toolbar_icon_size",16).toInt ();
  606. _main_tool_bar->setIconSize (QSize (icon_size,icon_size));
  607. if (settings->value ("show_status_bar",true).toBool ())
  608. status_bar->show ();
  609. else
  610. status_bar->hide ();
  611. _prevent_readline_conflicts =
  612. settings->value ("shortcuts/prevent_readline_conflicts", true).toBool ();
  613. configure_shortcuts ();
  614. set_global_shortcuts (command_window_has_focus ());
  615. _suppress_dbg_location =
  616. ! settings->value ("terminal/print_debug_location", false).toBool ();
  617. resource_manager::update_network_settings ();
  618. }
  619. void
  620. main_window::confirm_shutdown_octave (void)
  621. {
  622. bool closenow = true;
  623. QSettings *settings = resource_manager::get_settings ();
  624. if (settings->value ("prompt_to_exit", false).toBool ())
  625. {
  626. int ans = QMessageBox::question (this, tr ("Octave"),
  627. tr ("Are you sure you want to exit Octave?"),
  628. QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
  629. if (ans != QMessageBox::Ok)
  630. closenow = false;
  631. }
  632. #ifdef HAVE_QSCINTILLA
  633. if (closenow)
  634. closenow = editor_window->check_closing ();
  635. #endif
  636. _octave_qt_link->shutdown_confirmation (closenow);
  637. // Awake the worker thread so that it continues shutting down (or not).
  638. _octave_qt_link->waitcondition.wakeAll ();
  639. }
  640. void
  641. main_window::prepare_to_exit (void)
  642. {
  643. write_settings ();
  644. }
  645. void
  646. main_window::exit_app (int status)
  647. {
  648. qApp->exit (status);
  649. }
  650. void
  651. main_window::reset_windows (void)
  652. {
  653. QSettings *settings = resource_manager::get_default_settings ();
  654. set_window_layout (settings);
  655. showNormal (); // make sure main window is not minimized
  656. }
  657. void
  658. main_window::change_directory (const QString& dir)
  659. {
  660. // Remove existing entry, if any, then add new directory at top and
  661. // mark it as the current directory. Finally, update the file list
  662. // widget.
  663. int index = _current_directory_combo_box->findText (dir);
  664. if (index >= 0)
  665. _current_directory_combo_box->removeItem (index);
  666. _current_directory_combo_box->insertItem (0, dir);
  667. _current_directory_combo_box->setCurrentIndex (0);
  668. }
  669. void
  670. main_window::browse_for_directory (void)
  671. {
  672. QString dir
  673. = QFileDialog::getExistingDirectory (this, tr ("Browse directories"), 0,
  674. QFileDialog::ShowDirsOnly |
  675. QFileDialog::DontUseNativeDialog);
  676. set_current_working_directory (dir);
  677. // FIXME: on Windows systems, the command window freezes after the
  678. // previous actions. Forcing the focus appears to unstick it.
  679. focus_command_window ();
  680. }
  681. void
  682. main_window::set_current_working_directory (const QString& dir)
  683. {
  684. // Change to dir if it is an existing directory.
  685. QString xdir = dir.isEmpty () ? "." : dir;
  686. QFileInfo fileInfo (xdir);
  687. if (fileInfo.exists () && fileInfo.isDir ())
  688. octave_link::post_event (this, &main_window::change_directory_callback,
  689. xdir.toStdString ());
  690. }
  691. void
  692. main_window::change_directory_up (void)
  693. {
  694. set_current_working_directory ("..");
  695. }
  696. // Slot that is called if return is pressed in the line edit of the
  697. // combobox to change to a new directory or a directory that is already
  698. // in the drop down list.
  699. void
  700. main_window::accept_directory_line_edit (void)
  701. {
  702. // Get new directory name, and change to it if it is new. Otherwise,
  703. // the combo box will triggers the "activated" signal to change to the
  704. // directory.
  705. QString dir = _current_directory_combo_box->currentText ();
  706. int index = _current_directory_combo_box->findText (dir);
  707. if (index < 0)
  708. set_current_working_directory (dir);
  709. }
  710. void
  711. main_window::handle_enter_debugger (void)
  712. {
  713. setWindowTitle ("Octave (Debugging)");
  714. _debug_continue->setEnabled (true);
  715. _debug_step_into->setEnabled (true);
  716. _debug_step_over->setEnabled (true);
  717. _debug_step_out->setEnabled (true);
  718. _debug_quit->setEnabled (true);
  719. #ifdef HAVE_QSCINTILLA
  720. editor_window->handle_enter_debug_mode ();
  721. #endif
  722. }
  723. void
  724. main_window::handle_exit_debugger (void)
  725. {
  726. setWindowTitle ("Octave");
  727. _debug_continue->setEnabled (false);
  728. _debug_step_into->setEnabled (false);
  729. _debug_step_over->setEnabled (false);
  730. _debug_step_out->setEnabled (false);
  731. _debug_quit->setEnabled (false);
  732. #ifdef HAVE_QSCINTILLA
  733. editor_window->handle_exit_debug_mode ();
  734. #endif
  735. }
  736. void
  737. main_window::debug_continue (void)
  738. {
  739. queue_debug ("cont");
  740. }
  741. void
  742. main_window::debug_step_into (void)
  743. {
  744. queue_debug ("in");
  745. }
  746. void
  747. main_window::debug_step_over (void)
  748. {
  749. queue_debug ("step");
  750. }
  751. void
  752. main_window::debug_step_out (void)
  753. {
  754. queue_debug ("out");
  755. }
  756. void
  757. main_window::debug_quit (void)
  758. {
  759. queue_debug ("quit");
  760. }
  761. void
  762. main_window::handle_insert_debugger_pointer_request (const QString& file,
  763. int line)
  764. {
  765. bool cmd_focus = command_window_has_focus ();
  766. emit insert_debugger_pointer_signal (file, line);
  767. if (cmd_focus)
  768. focus_command_window ();
  769. }
  770. void
  771. main_window::handle_delete_debugger_pointer_request (const QString& file,
  772. int line)
  773. {
  774. bool cmd_focus = command_window_has_focus ();
  775. emit delete_debugger_pointer_signal (file, line);
  776. if (cmd_focus)
  777. focus_command_window ();
  778. }
  779. void
  780. main_window::handle_update_breakpoint_marker_request (bool insert,
  781. const QString& file,
  782. int line)
  783. {
  784. bool cmd_focus = command_window_has_focus ();
  785. emit update_breakpoint_marker_signal (insert, file, line);
  786. if (cmd_focus)
  787. focus_command_window ();
  788. }
  789. void
  790. main_window::show_about_octave (void)
  791. {
  792. std::string message
  793. = octave_name_version_copyright_copying_warranty_and_bugs (true);
  794. QMessageBox::about (this, tr ("About Octave"),
  795. QString::fromStdString (message));
  796. }
  797. void
  798. main_window::closeEvent (QCloseEvent *e)
  799. {
  800. e->ignore ();
  801. octave_cmd_exec *cmd = new octave_cmd_exec ("exit");
  802. queue_command (cmd);
  803. }
  804. void
  805. main_window::read_settings (void)
  806. {
  807. QSettings *settings = resource_manager::get_settings ();
  808. if (!settings)
  809. {
  810. qDebug ("Error: QSettings pointer from resource manager is NULL.");
  811. return;
  812. }
  813. set_window_layout (settings);
  814. // restore the list of the last directories
  815. QStringList curr_dirs
  816. = settings->value ("MainWindow/current_directory_list").toStringList ();
  817. for (int i=0; i < curr_dirs.size (); i++)
  818. {
  819. _current_directory_combo_box->addItem (curr_dirs.at (i));
  820. }
  821. emit settings_changed (settings);
  822. }
  823. void
  824. main_window::init_terminal_size (void)
  825. {
  826. emit init_terminal_size_signal ();
  827. }
  828. void
  829. main_window::set_window_layout (QSettings *settings)
  830. {
  831. #if ! defined (Q_OS_WIN32)
  832. restoreState (settings->value ("MainWindow/windowState").toByteArray ());
  833. restoreGeometry (settings->value ("MainWindow/geometry").toByteArray ());
  834. #endif
  835. // Restore the geometry of all dock-widgets
  836. foreach (octave_dock_widget *widget, dock_widget_list ())
  837. {
  838. QString name = widget->objectName ();
  839. if (! name.isEmpty ())
  840. {
  841. bool floating = settings->value
  842. ("DockWidgets/" + name + "Floating", false).toBool ();
  843. bool visible = settings->value
  844. ("DockWidgets/" + name + "Visible", true).toBool ();
  845. // If floating, make window from widget.
  846. if (floating)
  847. widget->make_window ();
  848. else if (! widget->parent ()) // should not be floating but is
  849. widget->make_widget (false); // no docking, just reparent
  850. #if ! defined (Q_OS_WIN32)
  851. // restore geometry
  852. QVariant val = settings->value ("DockWidgets/" + name);
  853. widget->restoreGeometry (val.toByteArray ());
  854. #endif
  855. // make widget visible if desired
  856. if (floating && visible) // floating and visible
  857. {
  858. if (settings->value ("DockWidgets/" + widget->objectName () + "_minimized").toBool ())
  859. widget->showMinimized ();
  860. else
  861. widget->setVisible (true);
  862. }
  863. else
  864. {
  865. widget->make_widget ();
  866. widget->setVisible (visible); // not floating -> show
  867. }
  868. }
  869. }
  870. #if defined (Q_OS_WIN32)
  871. restoreState (settings->value ("MainWindow/windowState").toByteArray ());
  872. restoreGeometry (settings->value ("MainWindow/geometry").toByteArray ());
  873. #endif
  874. show ();
  875. }
  876. void
  877. main_window::write_settings (void)
  878. {
  879. QSettings *settings = resource_manager::get_settings ();
  880. if (!settings)
  881. {
  882. qDebug ("Error: QSettings pointer from resource manager is NULL.");
  883. return;
  884. }
  885. settings->setValue ("MainWindow/geometry", saveGeometry ());
  886. settings->setValue ("MainWindow/windowState", saveState ());
  887. // write the list of recent used directories
  888. QStringList curr_dirs;
  889. for (int i=0; i<_current_directory_combo_box->count (); i++)
  890. {
  891. curr_dirs.append (_current_directory_combo_box->itemText (i));
  892. }
  893. settings->setValue ("MainWindow/current_directory_list", curr_dirs);
  894. settings->sync ();
  895. }
  896. // Connecting the signals emitted when the visibility of a widget changes.
  897. // This has to be done after the window is shown (see octave-gui.cc)
  898. void
  899. main_window::connect_visibility_changed (void)
  900. {
  901. foreach (octave_dock_widget *widget, dock_widget_list ())
  902. widget->connect_visibility_changed ();
  903. #ifdef HAVE_QSCINTILLA
  904. editor_window->enable_menu_shortcuts (false);
  905. #endif
  906. }
  907. void
  908. main_window::copyClipboard (void)
  909. {
  910. if (_current_directory_combo_box->hasFocus ())
  911. {
  912. QLineEdit * edit = _current_directory_combo_box->lineEdit ();
  913. if (edit && edit->hasSelectedText ())
  914. {
  915. QClipboard *clipboard = QApplication::clipboard ();
  916. clipboard->setText (edit->selectedText ());
  917. }
  918. }
  919. else
  920. emit copyClipboard_signal ();
  921. }
  922. void
  923. main_window::pasteClipboard (void)
  924. {
  925. if (_current_directory_combo_box->hasFocus ())
  926. {
  927. QLineEdit * edit = _current_directory_combo_box->lineEdit ();
  928. QClipboard *clipboard = QApplication::clipboard ();
  929. QString str = clipboard->text ();
  930. if (edit && str.length () > 0)
  931. {
  932. edit->insert (str);
  933. }
  934. }
  935. else
  936. emit pasteClipboard_signal ();
  937. }
  938. void
  939. main_window::selectAll (void)
  940. {
  941. if (_current_directory_combo_box->hasFocus ())
  942. {
  943. QLineEdit * edit = _current_directory_combo_box->lineEdit ();
  944. if (edit)
  945. {
  946. edit->selectAll ();
  947. }
  948. }
  949. else
  950. emit selectAll_signal ();
  951. }
  952. // Connect the signals emitted when the Octave thread wants to create
  953. // a dialog box of some sort. Perhaps a better place for this would be
  954. // as part of the QUIWidgetCreator class. However, mainWindow currently
  955. // is not a global variable and not accessible for connecting.
  956. void
  957. main_window::connect_uiwidget_links ()
  958. {
  959. connect (&uiwidget_creator,
  960. SIGNAL (create_dialog (const QString&, const QString&,
  961. const QString&, const QStringList&,
  962. const QString&, const QStringList&)),
  963. this,
  964. SLOT (handle_create_dialog (const QString&, const QString&,
  965. const QString&, const QStringList&,
  966. const QString&, const QStringList&)));
  967. // Register QIntList so that list of ints may be part of a signal.
  968. qRegisterMetaType<QIntList> ("QIntList");
  969. connect (&uiwidget_creator,
  970. SIGNAL (create_listview (const QStringList&, const QString&,
  971. int, int, const QIntList&,
  972. const QString&, const QStringList&,
  973. const QString&, const QString&)),
  974. this,
  975. SLOT (handle_create_listview (const QStringList&, const QString&,
  976. int, int, const QIntList&,
  977. const QString&, const QStringList&,
  978. const QString&, const QString&)));
  979. // Register QFloatList so that list of floats may be part of a signal.
  980. qRegisterMetaType<QFloatList> ("QFloatList");
  981. connect (&uiwidget_creator,
  982. SIGNAL (create_inputlayout (const QStringList&, const QString&,
  983. const QFloatList&, const QFloatList&,
  984. const QStringList&)),
  985. this,
  986. SLOT (handle_create_inputlayout (const QStringList&, const QString&,
  987. const QFloatList&,
  988. const QFloatList&,
  989. const QStringList&)));
  990. connect (&uiwidget_creator,
  991. SIGNAL (create_filedialog (const QStringList &,const QString&,
  992. const QString&, const QString&,
  993. const QString&)),
  994. this,
  995. SLOT (handle_create_filedialog (const QStringList &, const QString&,
  996. const QString&, const QString&,
  997. const QString&)));
  998. }
  999. // Create a message dialog with specified string, buttons and decorative
  1000. // text.
  1001. void
  1002. main_window::handle_create_dialog (const QString& message,
  1003. const QString& title,
  1004. const QString& icon,
  1005. const QStringList& button,
  1006. const QString& defbutton,
  1007. const QStringList& role)
  1008. {
  1009. MessageDialog *message_dialog = new MessageDialog (message, title, icon,
  1010. button, defbutton, role);
  1011. message_dialog->setAttribute (Qt::WA_DeleteOnClose);
  1012. message_dialog->show ();
  1013. }
  1014. // Create a list dialog with specified list, initially selected, mode,
  1015. // view size and decorative text.
  1016. void
  1017. main_window::handle_create_listview (const QStringList& list,
  1018. const QString& mode,
  1019. int wd, int ht,
  1020. const QIntList& initial,
  1021. const QString& name,
  1022. const QStringList& prompt,
  1023. const QString& ok_string,
  1024. const QString& cancel_string)
  1025. {
  1026. ListDialog *list_dialog = new ListDialog (list, mode, wd, ht,
  1027. initial, name, prompt,
  1028. ok_string, cancel_string);
  1029. list_dialog->setAttribute (Qt::WA_DeleteOnClose);
  1030. list_dialog->show ();
  1031. }
  1032. // Create an input dialog with specified prompts and defaults, title and
  1033. // row/column size specifications.
  1034. void
  1035. main_window::handle_create_inputlayout (const QStringList& prompt,
  1036. const QString& title,
  1037. const QFloatList& nr,
  1038. const QFloatList& nc,
  1039. const QStringList& defaults)
  1040. {
  1041. InputDialog *input_dialog = new InputDialog (prompt, title, nr, nc,
  1042. defaults);
  1043. input_dialog->setAttribute (Qt::WA_DeleteOnClose);
  1044. input_dialog->show ();
  1045. }
  1046. void
  1047. main_window::handle_create_filedialog (const QStringList& filters,
  1048. const QString& title,
  1049. const QString& filename,
  1050. const QString& dirname,
  1051. const QString& multimode)
  1052. {
  1053. FileDialog *file_dialog = new FileDialog (filters, title, filename,
  1054. dirname, multimode);
  1055. file_dialog->setAttribute (Qt::WA_DeleteOnClose);
  1056. file_dialog->show ();
  1057. }
  1058. // Main subroutine of the constructor
  1059. void
  1060. main_window::construct (void)
  1061. {
  1062. _closing = false; // flag for editor files when closed
  1063. setWindowIcon (QIcon (":/actions/icons/logo.png"));
  1064. workspace_window->setModel (_workspace_model);
  1065. connect (_workspace_model, SIGNAL (model_changed (void)),
  1066. workspace_window, SLOT (handle_model_changed (void)));
  1067. // Create and set the central widget. QMainWindow takes ownership of
  1068. // the widget (pointer) so there is no need to delete the object upon
  1069. // destroying this main_window.
  1070. QWidget *dummyWidget = new QWidget ();
  1071. dummyWidget->setObjectName ("CentralDummyWidget");
  1072. dummyWidget->resize (10, 10);
  1073. dummyWidget->setSizePolicy (QSizePolicy::Minimum, QSizePolicy::Minimum);
  1074. dummyWidget->hide ();
  1075. setCentralWidget (dummyWidget);
  1076. construct_menu_bar ();
  1077. construct_tool_bar ();
  1078. connect (qApp, SIGNAL (aboutToQuit ()),
  1079. this, SLOT (prepare_to_exit ()));
  1080. connect (qApp, SIGNAL (focusChanged (QWidget*, QWidget*)),
  1081. this, SLOT(focus_changed (QWidget*, QWidget*)));
  1082. connect (this, SIGNAL (settings_changed (const QSettings *)),
  1083. this, SLOT (notice_settings (const QSettings *)));
  1084. connect (this, SIGNAL (editor_focus_changed (bool)),
  1085. this, SLOT (set_global_edit_shortcuts (bool)));
  1086. connect (this, SIGNAL (editor_focus_changed (bool)),
  1087. editor_window, SLOT (enable_menu_shortcuts (bool)));
  1088. connect (file_browser_window, SIGNAL (load_file_signal (const QString&)),
  1089. this, SLOT (handle_load_workspace_request (const QString&)));
  1090. connect (file_browser_window, SIGNAL (find_files_signal (const QString&)),
  1091. this, SLOT (find_files (const QString&)));
  1092. connect_uiwidget_links ();
  1093. setWindowTitle ("Octave");
  1094. setDockOptions (QMainWindow::AnimatedDocks
  1095. | QMainWindow::AllowNestedDocks
  1096. | QMainWindow::AllowTabbedDocks);
  1097. addDockWidget (Qt::RightDockWidgetArea, command_window);
  1098. addDockWidget (Qt::RightDockWidgetArea, doc_browser_window);
  1099. tabifyDockWidget (command_window, doc_browser_window);
  1100. #ifdef HAVE_QSCINTILLA
  1101. addDockWidget (Qt::RightDockWidgetArea, editor_window);
  1102. tabifyDockWidget (command_window, editor_window);
  1103. #endif
  1104. addDockWidget (Qt::LeftDockWidgetArea, file_browser_window);
  1105. addDockWidget (Qt::LeftDockWidgetArea, workspace_window);
  1106. addDockWidget (Qt::LeftDockWidgetArea, history_window);
  1107. int win_x = QApplication::desktop ()->width ();
  1108. int win_y = QApplication::desktop ()->height ();
  1109. if (win_x > 960)
  1110. win_x = 960;
  1111. if (win_y > 720)
  1112. win_y = 720;
  1113. setGeometry (0, 0, win_x, win_y);
  1114. setStatusBar (status_bar);
  1115. construct_octave_qt_link ();
  1116. #ifdef HAVE_QSCINTILLA
  1117. connect (this,
  1118. SIGNAL (insert_debugger_pointer_signal (const QString&, int)),
  1119. editor_window,
  1120. SLOT (handle_insert_debugger_pointer_request (const QString&, int)));
  1121. connect (this,
  1122. SIGNAL (delete_debugger_pointer_signal (const QString&, int)),
  1123. editor_window,
  1124. SLOT (handle_delete_debugger_pointer_request (const QString&, int)));
  1125. connect (this,
  1126. SIGNAL (update_breakpoint_marker_signal (bool, const QString&, int)),
  1127. editor_window,
  1128. SLOT (handle_update_breakpoint_marker_request (bool,
  1129. const QString&,
  1130. int)));
  1131. #endif
  1132. octave_link::post_event (this, &main_window::resize_command_window_callback);
  1133. install___init_qt___functions ();
  1134. Fregister_graphics_toolkit (ovl ("qt"));
  1135. configure_shortcuts ();
  1136. }
  1137. void
  1138. main_window::handle_octave_ready ()
  1139. {
  1140. // actions after the startup files are executed
  1141. QSettings *settings = resource_manager::get_settings ();
  1142. QDir startup_dir = QDir (); // current octave dir after startup
  1143. if (settings->value ("restore_octave_dir").toBool ())
  1144. {
  1145. // restore last dir from previous session
  1146. QStringList curr_dirs
  1147. = settings->value ("MainWindow/current_directory_list").toStringList ();
  1148. startup_dir = QDir (curr_dirs.at (0)); // last dir in previous session
  1149. }
  1150. else if (! settings->value ("octave_startup_dir").toString ().isEmpty ())
  1151. {
  1152. // do not restore but there is a startup dir configured
  1153. startup_dir = QDir (settings->value ("octave_startup_dir").toString ());
  1154. }
  1155. if (! startup_dir.exists ())
  1156. {
  1157. // the configured startup dir does not exist, take actual one
  1158. startup_dir = QDir ();
  1159. }
  1160. set_current_working_directory (startup_dir.absolutePath ());
  1161. #ifdef HAVE_QSCINTILLA
  1162. // Octave ready, determine whether to create an empty script.
  1163. // This can not be done when the editor is created because all functions
  1164. // must be known for the lexer's auto completion informations
  1165. editor_window->empty_script (true, false);
  1166. #endif
  1167. focus_command_window (); // make sure that the command window has focus
  1168. }
  1169. void
  1170. main_window::construct_octave_qt_link (void)
  1171. {
  1172. _octave_qt_link = new octave_qt_link (this);
  1173. connect (_octave_qt_link, SIGNAL (confirm_shutdown_signal ()),
  1174. this, SLOT (confirm_shutdown_octave ()));
  1175. connect (_octave_qt_link, SIGNAL (exit_app_signal (int)),
  1176. this, SLOT (exit_app (int)));
  1177. connect (_octave_qt_link,
  1178. SIGNAL (set_workspace_signal
  1179. (bool, const QString&, const QStringList&,
  1180. const QStringList&, const QStringList&,
  1181. const QStringList&, const QIntList&)),
  1182. _workspace_model,
  1183. SLOT (set_workspace
  1184. (bool, const QString&, const QStringList&,
  1185. const QStringList&, const QStringList&,
  1186. const QStringList&, const QIntList&)));
  1187. connect (_octave_qt_link, SIGNAL (clear_workspace_signal ()),
  1188. _workspace_model, SLOT (clear_workspace ()));
  1189. connect (_octave_qt_link, SIGNAL (change_directory_signal (QString)),
  1190. this, SLOT (change_directory (QString)));
  1191. connect (_octave_qt_link, SIGNAL (change_directory_signal (QString)),
  1192. file_browser_window, SLOT (update_octave_directory (QString)));
  1193. connect (_octave_qt_link, SIGNAL (change_directory_signal (QString)),
  1194. editor_window, SLOT (update_octave_directory (QString)));
  1195. connect (_octave_qt_link,
  1196. SIGNAL (execute_command_in_terminal_signal (QString)),
  1197. this, SLOT (execute_command_in_terminal (QString)));
  1198. connect (_octave_qt_link,
  1199. SIGNAL (set_history_signal (const QStringList&)),
  1200. history_window, SLOT (set_history (const QStringList&)));
  1201. connect (_octave_qt_link,
  1202. SIGNAL (append_history_signal (const QString&)),
  1203. history_window, SLOT (append_history (const QString&)));
  1204. connect (_octave_qt_link,
  1205. SIGNAL (clear_history_signal (void)),
  1206. history_window, SLOT (clear_history (void)));
  1207. connect (_octave_qt_link, SIGNAL (enter_debugger_signal ()),
  1208. this, SLOT (handle_enter_debugger ()));
  1209. connect (_octave_qt_link, SIGNAL (exit_debugger_signal ()),
  1210. this, SLOT (handle_exit_debugger ()));
  1211. connect (_octave_qt_link,
  1212. SIGNAL (show_preferences_signal (void)),
  1213. this, SLOT (process_settings_dialog_request ()));
  1214. #ifdef HAVE_QSCINTILLA
  1215. connect (_octave_qt_link,
  1216. SIGNAL (edit_file_signal (const QString&)),
  1217. editor_window,
  1218. SLOT (handle_edit_file_request (const QString&)));
  1219. #endif
  1220. connect (_octave_qt_link,
  1221. SIGNAL (insert_debugger_pointer_signal (const QString&, int)),
  1222. this,
  1223. SLOT (handle_insert_debugger_pointer_request (const QString&, int)));
  1224. connect (_octave_qt_link,
  1225. SIGNAL (delete_debugger_pointer_signal (const QString&, int)),
  1226. this,
  1227. SLOT (handle_delete_debugger_pointer_request (const QString&, int)));
  1228. connect (_octave_qt_link,
  1229. SIGNAL (update_breakpoint_marker_signal (bool, const QString&, int)),
  1230. this,
  1231. SLOT (handle_update_breakpoint_marker_request (bool, const QString&,
  1232. int)));
  1233. connect (_octave_qt_link,
  1234. SIGNAL (show_doc_signal (const QString &)),
  1235. this, SLOT (handle_show_doc (const QString &)));
  1236. connect (_workspace_model,
  1237. SIGNAL (rename_variable (const QString&, const QString&)),
  1238. this,
  1239. SLOT (handle_rename_variable_request (const QString&,
  1240. const QString&)));
  1241. connect (command_window, SIGNAL (interrupt_signal (void)),
  1242. _octave_qt_link, SLOT (terminal_interrupt (void)));
  1243. _octave_qt_link->execute_interpreter ();
  1244. octave_link::connect_link (_octave_qt_link);
  1245. }
  1246. void
  1247. main_window::construct_menu_bar (void)
  1248. {
  1249. QMenuBar *menu_bar = menuBar ();
  1250. construct_file_menu (menu_bar);
  1251. construct_edit_menu (menu_bar);
  1252. construct_debug_menu (menu_bar);
  1253. construct_window_menu (menu_bar);
  1254. construct_help_menu (menu_bar);
  1255. construct_news_menu (menu_bar);
  1256. }
  1257. QAction*
  1258. main_window::add_action (QMenu *menu, const QIcon &icon, const QString &text,
  1259. const char *member, const QWidget *receiver)
  1260. {
  1261. QAction *a;
  1262. if (receiver)
  1263. a = menu->addAction (icon, text, receiver, member);
  1264. else
  1265. a = menu->addAction (icon, text, this, member);
  1266. addAction (a); // important for shortcut context
  1267. a->setShortcutContext (Qt::ApplicationShortcut);
  1268. return a;
  1269. }
  1270. void
  1271. main_window::enable_menu_shortcuts (bool enable)
  1272. {
  1273. QHash<QMenu*, QStringList>::const_iterator i = _hash_menu_text.constBegin();
  1274. while (i != _hash_menu_text.constEnd())
  1275. {
  1276. i.key ()->setTitle (i.value ().at (! enable));
  1277. ++i;
  1278. }
  1279. }
  1280. QMenu*
  1281. main_window::m_add_menu (QMenuBar *p, QString name)
  1282. {
  1283. QMenu *menu = p->addMenu (name);
  1284. QString base_name = name; // get a copy
  1285. // replace intended '&' ("&&") by a temp. string
  1286. base_name.replace ("&&","___octave_amp_replacement___");
  1287. // remove single '&' (shortcut)
  1288. base_name.remove ("&");
  1289. // restore intended '&'
  1290. base_name.replace ("___octave_amp_replacement___","&&");
  1291. // remember names with and without shortcut
  1292. _hash_menu_text[menu] = QStringList () << name << base_name;
  1293. return menu;
  1294. }
  1295. void
  1296. main_window::construct_file_menu (QMenuBar *p)
  1297. {
  1298. QMenu *file_menu = m_add_menu (p, tr ("&File"));
  1299. construct_new_menu (file_menu);
  1300. _open_action
  1301. = file_menu->addAction (QIcon (":/actions/icons/folder_documents.png"),
  1302. tr ("Open..."));
  1303. _open_action->setShortcutContext (Qt::ApplicationShortcut);
  1304. _open_action->setToolTip (tr ("Open an existing file in editor"));
  1305. #ifdef HAVE_QSCINTILLA
  1306. editor_window->insert_new_open_actions (_new_script_action,
  1307. _new_function_action,
  1308. _open_action);
  1309. file_menu->addMenu (editor_window->get_mru_menu ());
  1310. #endif
  1311. file_menu->addSeparator ();
  1312. _load_workspace_action
  1313. = file_menu->addAction (tr ("Load Workspace..."));
  1314. _save_workspace_action
  1315. = file_menu->addAction (tr ("Save Workspace As..."));
  1316. file_menu->addSeparator ();
  1317. _preferences_action
  1318. = file_menu->addAction (QIcon (":/actions/icons/configure.png"),
  1319. tr ("Preferences..."));
  1320. file_menu->addSeparator ();
  1321. _exit_action = file_menu->addAction (tr ("Exit"));
  1322. _exit_action->setShortcutContext (Qt::ApplicationShortcut);
  1323. connect (_preferences_action, SIGNAL (triggered ()),
  1324. this, SLOT (process_settings_dialog_request ()));
  1325. #ifdef HAVE_QSCINTILLA
  1326. connect (_open_action, SIGNAL (triggered ()),
  1327. editor_window, SLOT (request_open_file ()));
  1328. #endif
  1329. connect (_load_workspace_action, SIGNAL (triggered ()),
  1330. this, SLOT (handle_load_workspace_request ()));
  1331. connect (_save_workspace_action, SIGNAL (triggered ()),
  1332. this, SLOT (handle_save_workspace_request ()));
  1333. connect (_exit_action, SIGNAL (triggered ()),
  1334. this, SLOT (close ()));
  1335. }
  1336. void
  1337. main_window::construct_new_menu (QMenu *p)
  1338. {
  1339. QMenu *new_menu = p->addMenu (tr ("New"));
  1340. _new_script_action
  1341. = new_menu->addAction (QIcon (":/actions/icons/filenew.png"),
  1342. tr ("New Script"));
  1343. _new_script_action->setShortcutContext (Qt::ApplicationShortcut);
  1344. _new_function_action = new_menu->addAction (tr ("New Function..."));
  1345. _new_function_action->setEnabled (true);
  1346. _new_function_action->setShortcutContext (Qt::ApplicationShortcut);
  1347. _new_figure_action = new_menu->addAction (tr ("New Figure"));
  1348. _new_figure_action->setEnabled (true);
  1349. #ifdef HAVE_QSCINTILLA
  1350. connect (_new_script_action, SIGNAL (triggered ()),
  1351. editor_window, SLOT (request_new_script ()));
  1352. connect (_new_function_action, SIGNAL (triggered ()),
  1353. editor_window, SLOT (request_new_function ()));
  1354. #endif
  1355. connect (_new_figure_action, SIGNAL (triggered ()),
  1356. this, SLOT (handle_new_figure_request ()));
  1357. }
  1358. void
  1359. main_w

Large files files are truncated, but you can click here to view the full file