PageRenderTime 108ms CodeModel.GetById 3ms RepoModel.GetById 0ms 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
  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_window::construct_edit_menu (QMenuBar *p)
  1360. {
  1361. QMenu *edit_menu = m_add_menu (p, tr ("&Edit"));
  1362. QKeySequence ctrl_shift = Qt::ControlModifier + Qt::ShiftModifier;
  1363. _undo_action
  1364. = edit_menu->addAction (QIcon (":/actions/icons/undo.png"), tr ("Undo"));
  1365. edit_menu->addSeparator ();
  1366. _copy_action
  1367. = edit_menu->addAction (QIcon (":/actions/icons/editcopy.png"),
  1368. tr ("Copy"), this, SLOT (copyClipboard ()));
  1369. _paste_action
  1370. = edit_menu->addAction (QIcon (":/actions/icons/editpaste.png"),
  1371. tr ("Paste"), this, SLOT (pasteClipboard ()));
  1372. _select_all_action
  1373. = edit_menu->addAction (tr ("Select All"), this, SLOT (selectAll ()));
  1374. _clear_clipboard_action
  1375. = edit_menu->addAction (tr ("Clear Clipboard"), this,
  1376. SLOT (clear_clipboard ()));
  1377. edit_menu->addSeparator ();
  1378. _find_files_action = edit_menu->addAction (tr ("Find Files..."));
  1379. edit_menu->addSeparator ();
  1380. _clear_command_window_action
  1381. = edit_menu->addAction (tr ("Clear Command Window"));
  1382. _clear_command_history_action
  1383. = edit_menu->addAction (tr ("Clear Command History"));
  1384. _clear_workspace_action
  1385. = edit_menu->addAction (tr ("Clear Workspace"));
  1386. connect (_find_files_action, SIGNAL (triggered ()),
  1387. this, SLOT (find_files ()));
  1388. connect (_clear_command_window_action, SIGNAL (triggered ()),
  1389. this, SLOT (handle_clear_command_window_request ()));
  1390. connect (_clear_command_history_action, SIGNAL (triggered ()),
  1391. this, SLOT (handle_clear_history_request ()));
  1392. connect (_clear_workspace_action, SIGNAL (triggered ()),
  1393. this, SLOT (handle_clear_workspace_request ()));
  1394. connect (_clipboard, SIGNAL (changed (QClipboard::Mode)),
  1395. this, SLOT (clipboard_has_changed (QClipboard::Mode)));
  1396. clipboard_has_changed (QClipboard::Clipboard);
  1397. }
  1398. QAction *
  1399. main_window::construct_debug_menu_item (const char *icon, const QString& item,
  1400. const char *member)
  1401. {
  1402. QAction *action = add_action (_debug_menu, QIcon (icon), item, member);
  1403. action->setEnabled (false);
  1404. #ifdef HAVE_QSCINTILLA
  1405. editor_window->debug_menu ()->addAction (action);
  1406. editor_window->toolbar ()->addAction (action);
  1407. #endif
  1408. return action;
  1409. }
  1410. void
  1411. main_window::construct_debug_menu (QMenuBar *p)
  1412. {
  1413. _debug_menu = m_add_menu (p, tr ("De&bug"));
  1414. _debug_step_over = construct_debug_menu_item
  1415. (":/actions/icons/db_step.png", tr ("Step"),
  1416. SLOT (debug_step_over ()));
  1417. _debug_step_into = construct_debug_menu_item
  1418. (":/actions/icons/db_step_in.png", tr ("Step In"),
  1419. SLOT (debug_step_into ()));
  1420. _debug_step_out = construct_debug_menu_item
  1421. (":/actions/icons/db_step_out.png", tr ("Step Out"),
  1422. SLOT (debug_step_out ()));
  1423. _debug_continue = construct_debug_menu_item
  1424. (":/actions/icons/db_cont.png", tr ("Continue"),
  1425. SLOT (debug_continue ()));
  1426. _debug_menu->addSeparator ();
  1427. #ifdef HAVE_QSCINTILLA
  1428. editor_window->debug_menu ()->addSeparator ();
  1429. #endif
  1430. _debug_quit = construct_debug_menu_item
  1431. (":/actions/icons/db_stop.png", tr ("Quit Debug Mode"),
  1432. SLOT (debug_quit ()));
  1433. }
  1434. QAction *
  1435. main_window::construct_window_menu_item (QMenu *p, const QString& item,
  1436. bool checkable, QWidget *widget)
  1437. {
  1438. QAction *action = p->addAction (QIcon (), item);
  1439. addAction (action); // important for shortcut context
  1440. action->setCheckable (checkable);
  1441. action->setShortcutContext (Qt::ApplicationShortcut);
  1442. if (widget) // might be zero for editor_window
  1443. {
  1444. if (checkable)
  1445. {
  1446. // action for visibilty of dock widget
  1447. connect (action, SIGNAL (toggled (bool)),
  1448. widget, SLOT (setVisible (bool)));
  1449. connect (widget, SIGNAL (active_changed (bool)),
  1450. action, SLOT (setChecked (bool)));
  1451. }
  1452. else
  1453. {
  1454. // action for focus of dock widget
  1455. connect (action, SIGNAL (triggered ()), widget, SLOT (focus ()));
  1456. }
  1457. }
  1458. return action;
  1459. }
  1460. void
  1461. main_window::construct_window_menu (QMenuBar *p)
  1462. {
  1463. QMenu *window_menu = m_add_menu (p, tr ("&Window"));
  1464. _show_command_window_action = construct_window_menu_item
  1465. (window_menu, tr ("Show Command Window"), true, command_window);
  1466. _show_history_action = construct_window_menu_item
  1467. (window_menu, tr ("Show Command History"), true, history_window);
  1468. _show_file_browser_action = construct_window_menu_item
  1469. (window_menu, tr ("Show File Browser"), true, file_browser_window);
  1470. _show_workspace_action = construct_window_menu_item
  1471. (window_menu, tr ("Show Workspace"), true, workspace_window);
  1472. _show_editor_action = construct_window_menu_item
  1473. (window_menu, tr ("Show Editor"), true, editor_window);
  1474. _show_documentation_action = construct_window_menu_item
  1475. (window_menu, tr ("Show Documentation"), true, doc_browser_window);
  1476. window_menu->addSeparator ();
  1477. _command_window_action = construct_window_menu_item
  1478. (window_menu, tr ("Command Window"), false, command_window);
  1479. _history_action = construct_window_menu_item
  1480. (window_menu, tr ("Command History"), false, history_window);
  1481. _file_browser_action = construct_window_menu_item
  1482. (window_menu, tr ("File Browser"), false, file_browser_window);
  1483. _workspace_action = construct_window_menu_item
  1484. (window_menu, tr ("Workspace"), false, workspace_window);
  1485. _editor_action = construct_window_menu_item
  1486. (window_menu, tr ("Editor"), false, editor_window);
  1487. _documentation_action = construct_window_menu_item
  1488. (window_menu, tr ("Documentation"), false, doc_browser_window);
  1489. window_menu->addSeparator ();
  1490. _reset_windows_action = add_action (window_menu, QIcon (),
  1491. tr ("Reset Default Window Layout"), SLOT (reset_windows ()));
  1492. }
  1493. void
  1494. main_window::construct_help_menu (QMenuBar *p)
  1495. {
  1496. QMenu *help_menu = m_add_menu (p, tr ("&Help"));
  1497. construct_documentation_menu (help_menu);
  1498. help_menu->addSeparator ();
  1499. _report_bug_action = add_action (help_menu, QIcon (),
  1500. tr ("Report Bug"), SLOT (open_bug_tracker_page ()));
  1501. _octave_packages_action = add_action (help_menu, QIcon (),
  1502. tr ("Octave Packages"), SLOT (open_octave_packages_page ()));
  1503. _agora_action = add_action (help_menu, QIcon (),
  1504. tr ("Share Code"), SLOT (open_agora_page ()));
  1505. _contribute_action = add_action (help_menu, QIcon (),
  1506. tr ("Contribute to Octave"), SLOT (open_contribute_page ()));
  1507. _developer_action = add_action (help_menu, QIcon (),
  1508. tr ("Octave Developer Resources"), SLOT (open_developer_page ()));
  1509. help_menu->addSeparator ();
  1510. _about_octave_action = add_action (help_menu, QIcon (),
  1511. tr ("About Octave"), SLOT (show_about_octave ()));
  1512. }
  1513. void
  1514. main_window::construct_documentation_menu (QMenu *p)
  1515. {
  1516. QMenu *doc_menu = p->addMenu (tr ("Documentation"));
  1517. _ondisk_doc_action = add_action (doc_menu, QIcon (),
  1518. tr ("On Disk"), SLOT (focus ()), doc_browser_window);
  1519. _online_doc_action = add_action (doc_menu, QIcon (),
  1520. tr ("Online"), SLOT (open_online_documentation_page ()));
  1521. }
  1522. void
  1523. main_window::construct_news_menu (QMenuBar *p)
  1524. {
  1525. QMenu *news_menu = m_add_menu (p, tr ("&News"));
  1526. _release_notes_action = add_action (news_menu, QIcon (),
  1527. tr ("Release Notes"), SLOT (display_release_notes ()));
  1528. _current_news_action = add_action (news_menu, QIcon (),
  1529. tr ("Community News"), SLOT (load_and_display_community_news ()));
  1530. }
  1531. void
  1532. main_window::construct_tool_bar (void)
  1533. {
  1534. _main_tool_bar = addToolBar ("Main");
  1535. _main_tool_bar->setObjectName ("MainToolBar");
  1536. _main_tool_bar->addAction (_new_script_action);
  1537. _main_tool_bar->addAction (_open_action);
  1538. _main_tool_bar->addSeparator ();
  1539. _main_tool_bar->addAction (_copy_action);
  1540. _main_tool_bar->addAction (_paste_action);
  1541. _main_tool_bar->addAction (_undo_action);
  1542. _main_tool_bar->addSeparator ();
  1543. _current_directory_combo_box = new QComboBox (this);
  1544. _current_directory_combo_box->setFixedWidth (current_directory_width);
  1545. _current_directory_combo_box->setEditable (true);
  1546. _current_directory_combo_box->setInsertPolicy (QComboBox::NoInsert);
  1547. _current_directory_combo_box->setToolTip (tr ("Enter directory name"));
  1548. _current_directory_combo_box->setMaxVisibleItems (
  1549. current_directory_max_visible);
  1550. _current_directory_combo_box->setMaxCount (current_directory_max_count);
  1551. QSizePolicy sizePol (QSizePolicy::Expanding, QSizePolicy::Preferred);
  1552. _current_directory_combo_box->setSizePolicy (sizePol);
  1553. // addWidget takes ownership of the objects so there is no
  1554. // need to delete these upon destroying this main_window.
  1555. _main_tool_bar->addWidget (new QLabel (tr ("Current Directory: ")));
  1556. _main_tool_bar->addWidget (_current_directory_combo_box);
  1557. QAction *current_dir_up = _main_tool_bar->addAction (
  1558. QIcon (":/actions/icons/up.png"),
  1559. tr ("One directory up"));
  1560. QAction *current_dir_search = _main_tool_bar->addAction (
  1561. QIcon (":/actions/icons/folder.png"),
  1562. tr ("Browse directories"));
  1563. connect (_current_directory_combo_box, SIGNAL (activated (QString)),
  1564. this, SLOT (set_current_working_directory (QString)));
  1565. connect (_current_directory_combo_box->lineEdit (), SIGNAL (returnPressed ()),
  1566. this, SLOT (accept_directory_line_edit ()));
  1567. connect (current_dir_search, SIGNAL (triggered ()),
  1568. this, SLOT (browse_for_directory ()));
  1569. connect (current_dir_up, SIGNAL (triggered ()),
  1570. this, SLOT (change_directory_up ()));
  1571. connect (_undo_action, SIGNAL (triggered ()),
  1572. this, SLOT (handle_undo_request ()));
  1573. }
  1574. void
  1575. main_window::save_workspace_callback (const std::string& file)
  1576. {
  1577. Fsave (ovl (file));
  1578. }
  1579. void
  1580. main_window::load_workspace_callback (const std::string& file)
  1581. {
  1582. Fload (ovl (file));
  1583. octave_link::set_workspace (true, symbol_table::workspace_info ());
  1584. }
  1585. void
  1586. main_window::clear_workspace_callback (void)
  1587. {
  1588. Fclear ();
  1589. }
  1590. void
  1591. main_window::rename_variable_callback (const main_window::name_pair& names)
  1592. {
  1593. /* bool status = */ symbol_table::rename (names.first, names.second);
  1594. // if (status)
  1595. octave_link::set_workspace (true, symbol_table::workspace_info ());
  1596. // else
  1597. // ; // we need an octave_link action that runs a GUI error option.
  1598. }
  1599. void
  1600. main_window::command_window_undo_callback (void)
  1601. {
  1602. command_editor::undo ();
  1603. command_editor::redisplay ();
  1604. }
  1605. void
  1606. main_window::clear_command_window_callback (void)
  1607. {
  1608. command_editor::kill_full_line ();
  1609. command_editor::clear_screen ();
  1610. }
  1611. void
  1612. main_window::resize_command_window_callback (void)
  1613. {
  1614. command_editor::resize_terminal ();
  1615. }
  1616. void
  1617. main_window::set_screen_size_callback (const int_pair& sz)
  1618. {
  1619. command_editor::set_screen_size (sz.first, sz.second);
  1620. }
  1621. void
  1622. main_window::clear_history_callback (void)
  1623. {
  1624. Fhistory (ovl ("-c"));
  1625. }
  1626. void
  1627. main_window::execute_command_callback ()
  1628. {
  1629. bool repost = false; // flag for reposting event for this callback
  1630. if (! _cmd_queue.isEmpty ()) // list can not be empty here, just to make sure
  1631. {
  1632. _cmd_queue_mutex.lock (); // critical path
  1633. octave_cmd *cmd = _cmd_queue.takeFirst ();
  1634. if (_cmd_queue.isEmpty ())
  1635. _cmd_processing.release (); // cmd queue empty, processing will stop
  1636. else
  1637. repost = true; // not empty, repost at end
  1638. _cmd_queue_mutex.unlock ();
  1639. cmd->execute ();
  1640. delete cmd;
  1641. }
  1642. if (repost) // queue not empty, so repost event for further processing
  1643. octave_link::post_event (this, &main_window::execute_command_callback);
  1644. }
  1645. void
  1646. main_window::new_figure_callback (void)
  1647. {
  1648. Fbuiltin (ovl ("figure"));
  1649. Fdrawnow ();
  1650. }
  1651. void
  1652. main_window::change_directory_callback (const std::string& directory)
  1653. {
  1654. Fcd (ovl (directory));
  1655. }
  1656. // The next callbacks are invoked by GUI buttons. Those buttons
  1657. // should only be active when we are doing debugging, which means that
  1658. // Octave is waiting for input in get_debug_input. Calling
  1659. // command_editor::interrupt will force readline to return even if it
  1660. // has not read any input, and then get_debug_input will return,
  1661. // allowing the evaluator to continue and execute the next statement.
  1662. void
  1663. main_window::queue_debug (QString debug_cmd)
  1664. {
  1665. _dbg_queue_mutex.lock ();
  1666. _dbg_queue->append (debug_cmd); // queue command
  1667. _dbg_queue_mutex.unlock ();
  1668. if (_dbg_processing.tryAcquire ()) // if callback not processing, post event
  1669. octave_link::post_event (this, &main_window::execute_debug_callback);
  1670. }
  1671. void
  1672. main_window::execute_debug_callback ()
  1673. {
  1674. bool repost = false; // flag for reposting event for this callback
  1675. if (!_dbg_queue->isEmpty ()) // list can not be empty here, just to make sure
  1676. {
  1677. _dbg_queue_mutex.lock (); // critical path
  1678. QString debug = _dbg_queue->takeFirst ();
  1679. if (_dbg_queue->isEmpty ())
  1680. _dbg_processing.release (); // cmd queue empty, processing will stop
  1681. else
  1682. repost = true; // not empty, repost at end
  1683. _dbg_queue_mutex.unlock ();
  1684. if (debug == "step")
  1685. {
  1686. Fdb_next_breakpoint_quiet (ovl (_suppress_dbg_location));
  1687. Fdbstep ();
  1688. }
  1689. else if (debug == "cont")
  1690. {
  1691. Fdb_next_breakpoint_quiet (ovl (_suppress_dbg_location));
  1692. Fdbcont ();
  1693. }
  1694. else if (debug == "quit")
  1695. Fdbquit ();
  1696. else
  1697. {
  1698. Fdb_next_breakpoint_quiet (ovl (_suppress_dbg_location));
  1699. Fdbstep (ovl (debug.toStdString ()));
  1700. }
  1701. command_editor::interrupt (true);
  1702. }
  1703. if (repost) // queue not empty, so repost event for further processing
  1704. octave_link::post_event (this, &main_window::execute_debug_callback);
  1705. }
  1706. void
  1707. main_window::find_files (const QString &start_dir)
  1708. {
  1709. if (! find_files_dlg)
  1710. {
  1711. find_files_dlg = new find_files_dialog (this);
  1712. connect (find_files_dlg, SIGNAL (finished (int)),
  1713. this, SLOT (find_files_finished (int)));
  1714. connect (find_files_dlg, SIGNAL (dir_selected (const QString &)),
  1715. file_browser_window,
  1716. SLOT (set_current_directory (const QString&)));
  1717. connect (find_files_dlg, SIGNAL (file_selected (const QString &)),
  1718. this, SLOT (open_file (const QString &)));
  1719. find_files_dlg->setWindowModality (Qt::NonModal);
  1720. }
  1721. if (! find_files_dlg->isVisible ())
  1722. {
  1723. find_files_dlg->show ();
  1724. }
  1725. find_files_dlg->set_search_dir (start_dir);
  1726. find_files_dlg->activateWindow ();
  1727. }
  1728. void
  1729. main_window::find_files_finished (int)
  1730. {
  1731. }
  1732. void
  1733. main_window::set_global_edit_shortcuts (bool editor_has_focus)
  1734. {
  1735. // this slot is called when editor gets/loses focus
  1736. if (editor_has_focus)
  1737. { // disable shortcuts that are also provided by the editor itself
  1738. QKeySequence no_key = QKeySequence ();
  1739. _copy_action->setShortcut (no_key);
  1740. _paste_action->setShortcut (no_key);
  1741. _undo_action->setShortcut (no_key);
  1742. _select_all_action->setShortcut (no_key);
  1743. }
  1744. else
  1745. { // editor loses focus, set the global shortcuts
  1746. shortcut_manager::set_shortcut (_copy_action, "main_edit:copy");
  1747. shortcut_manager::set_shortcut (_paste_action, "main_edit:paste");
  1748. shortcut_manager::set_shortcut (_undo_action, "main_edit:undo");
  1749. shortcut_manager::set_shortcut (_select_all_action, "main_edit:select_all");
  1750. }
  1751. // dis-/enable global menu depending on editor's focus
  1752. enable_menu_shortcuts (! editor_has_focus);
  1753. }
  1754. void
  1755. main_window::configure_shortcuts ()
  1756. {
  1757. // file menu
  1758. shortcut_manager::set_shortcut (_open_action, "main_file:open_file");
  1759. shortcut_manager::set_shortcut (_new_script_action, "main_file:new_file");
  1760. shortcut_manager::set_shortcut (_new_function_action, "main_file:new_function");
  1761. shortcut_manager::set_shortcut (_new_function_action, "main_file:new_figure");
  1762. shortcut_manager::set_shortcut (_load_workspace_action, "main_file:load_workspace");
  1763. shortcut_manager::set_shortcut (_save_workspace_action, "main_file:save_workspace");
  1764. shortcut_manager::set_shortcut (_preferences_action, "main_file:preferences");
  1765. shortcut_manager::set_shortcut (_exit_action,"main_file:exit");
  1766. // edit menu
  1767. shortcut_manager::set_shortcut (_copy_action, "main_edit:copy");
  1768. shortcut_manager::set_shortcut (_paste_action, "main_edit:paste");
  1769. shortcut_manager::set_shortcut (_undo_action, "main_edit:undo");
  1770. shortcut_manager::set_shortcut (_select_all_action, "main_edit:select_all");
  1771. shortcut_manager::set_shortcut (_clear_clipboard_action, "main_edit:clear_clipboard");
  1772. shortcut_manager::set_shortcut (_find_files_action, "main_edit:find_in_files");
  1773. shortcut_manager::set_shortcut (_clear_command_history_action, "main_edit:clear_history");
  1774. shortcut_manager::set_shortcut (_clear_command_window_action, "main_edit:clear_command_window");
  1775. shortcut_manager::set_shortcut (_clear_workspace_action, "main_edit:clear_workspace");
  1776. // debug menu
  1777. shortcut_manager::set_shortcut (_debug_step_over, "main_debug:step_over");
  1778. shortcut_manager::set_shortcut (_debug_step_into, "main_debug:step_into");
  1779. shortcut_manager::set_shortcut (_debug_step_out, "main_debug:step_out");
  1780. shortcut_manager::set_shortcut (_debug_continue, "main_debug:continue");
  1781. shortcut_manager::set_shortcut (_debug_quit, "main_debug:quit");
  1782. // window menu
  1783. shortcut_manager::set_shortcut (_show_command_window_action, "main_window:show_command");
  1784. shortcut_manager::set_shortcut (_show_history_action, "main_window:show_history");
  1785. shortcut_manager::set_shortcut (_show_workspace_action, "main_window:show_workspace");
  1786. shortcut_manager::set_shortcut (_show_file_browser_action, "main_window:show_file_browser");
  1787. shortcut_manager::set_shortcut (_show_editor_action, "main_window:show_editor");
  1788. shortcut_manager::set_shortcut (_show_documentation_action, "main_window:show_doc");
  1789. shortcut_manager::set_shortcut (_command_window_action, "main_window:command");
  1790. shortcut_manager::set_shortcut (_history_action, "main_window:history");
  1791. shortcut_manager::set_shortcut (_workspace_action, "main_window:workspace");
  1792. shortcut_manager::set_shortcut (_file_browser_action, "main_window:file_browser");
  1793. shortcut_manager::set_shortcut (_editor_action, "main_window:editor");
  1794. shortcut_manager::set_shortcut (_documentation_action, "main_window:doc");
  1795. shortcut_manager::set_shortcut (_reset_windows_action, "main_window:reset");
  1796. // help menu
  1797. shortcut_manager::set_shortcut (_ondisk_doc_action, "main_help:ondisk_doc");
  1798. shortcut_manager::set_shortcut (_online_doc_action, "main_help:online_doc");
  1799. shortcut_manager::set_shortcut (_report_bug_action, "main_help:report_bug");
  1800. shortcut_manager::set_shortcut (_octave_packages_action, "main_help:packages");
  1801. shortcut_manager::set_shortcut (_agora_action, "main_help:agora");
  1802. shortcut_manager::set_shortcut (_contribute_action, "main_help:contribute");
  1803. shortcut_manager::set_shortcut (_developer_action, "main_help:developer");
  1804. shortcut_manager::set_shortcut (_about_octave_action, "main_help:about");
  1805. // news menu
  1806. shortcut_manager::set_shortcut (_release_notes_action, "main_news:release_notes");
  1807. shortcut_manager::set_shortcut (_current_news_action, "main_news:community_news");
  1808. }
  1809. void
  1810. main_window::set_global_shortcuts (bool set_shortcuts)
  1811. {
  1812. // this slot is called when the terminal gets/loses focus
  1813. // return if the user don't want to use readline shortcuts
  1814. if (! _prevent_readline_conflicts)
  1815. return;
  1816. if (set_shortcuts)
  1817. { // terminal loses focus: set the global shortcuts
  1818. configure_shortcuts ();
  1819. }
  1820. else
  1821. { // terminal gets focus: disable some shortcuts
  1822. QKeySequence no_key = QKeySequence ();
  1823. // file menu
  1824. _open_action->setShortcut (no_key);
  1825. _new_script_action->setShortcut (no_key);
  1826. _new_function_action->setShortcut (no_key);
  1827. _new_function_action->setShortcut (no_key);
  1828. _load_workspace_action->setShortcut (no_key);
  1829. _save_workspace_action->setShortcut (no_key);
  1830. _preferences_action->setShortcut (no_key);
  1831. _exit_action->setShortcut (no_key);
  1832. // edit menu
  1833. _select_all_action->setShortcut (no_key);
  1834. _clear_clipboard_action->setShortcut (no_key);
  1835. _find_files_action->setShortcut (no_key);
  1836. _clear_command_history_action->setShortcut (no_key);
  1837. _clear_command_window_action->setShortcut (no_key);
  1838. _clear_workspace_action->setShortcut (no_key);
  1839. // window menu
  1840. _reset_windows_action->setShortcut (no_key);
  1841. // help menu
  1842. _ondisk_doc_action->setShortcut (no_key);
  1843. _online_doc_action->setShortcut (no_key);
  1844. _report_bug_action->setShortcut (no_key);
  1845. _octave_packages_action->setShortcut (no_key);
  1846. _agora_action->setShortcut (no_key);
  1847. _contribute_action->setShortcut (no_key);
  1848. _developer_action->setShortcut (no_key);
  1849. _about_octave_action->setShortcut (no_key);
  1850. // news menu
  1851. _release_notes_action->setShortcut (no_key);
  1852. _current_news_action->setShortcut (no_key);
  1853. }
  1854. }
  1855. void
  1856. main_window::set_screen_size (int ht, int wd)
  1857. {
  1858. octave_link::post_event (this, &main_window::set_screen_size_callback,
  1859. int_pair (ht, wd));
  1860. }
  1861. void
  1862. main_window::handle_show_doc (const QString& file)
  1863. {
  1864. doc_browser_window->setVisible (true);
  1865. emit show_doc_signal (file);
  1866. }
  1867. void
  1868. main_window::clipboard_has_changed (QClipboard::Mode cp_mode)
  1869. {
  1870. if (cp_mode == QClipboard::Clipboard)
  1871. {
  1872. if (_clipboard->text ().isEmpty ())
  1873. {
  1874. _paste_action->setEnabled (false);
  1875. _clear_clipboard_action->setEnabled (false);
  1876. }
  1877. else
  1878. {
  1879. _paste_action->setEnabled (true);
  1880. _clear_clipboard_action->setEnabled (true);
  1881. }
  1882. }
  1883. }
  1884. void
  1885. main_window::clear_clipboard ()
  1886. {
  1887. _clipboard->clear (QClipboard::Clipboard);
  1888. }