3 Copyright (c) 2012 Jakob Leben & Tim Blechmann
4 http://www.audiosynth.com
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include "cmd_line.hpp"
22 #include "doc_list.hpp"
23 #include "documents_dialog.hpp"
24 #include "find_replace_tool.hpp"
25 #include "goto_line_tool.hpp"
26 #include "lookup_dialog.hpp"
27 #include "main_window.hpp"
28 #include "multi_editor.hpp"
29 #include "popup_text_input.hpp"
30 #include "post_window.hpp"
31 #include "session_switch_dialog.hpp"
32 #include "sessions_dialog.hpp"
33 #include "tool_box.hpp"
34 #include "../core/main.hpp"
35 #include "../core/doc_manager.hpp"
36 #include "../core/session_manager.hpp"
37 #include "../core/sc_server.hpp"
38 #include "code_editor/sc_editor.hpp"
39 #include "settings/dialog.hpp"
42 #include <QApplication>
43 #include <QFileDialog>
45 #include <QGridLayout>
46 #include <QInputDialog>
49 #include <QMessageBox>
53 #include <QVBoxLayout>
58 MainWindow
* MainWindow::mInstance
= 0;
60 MainWindow::MainWindow(Main
* main
) :
70 setCorner( Qt::BottomLeftCorner
, Qt::LeftDockWidgetArea
);
72 // Construct status bar:
74 mLangStatus
= new StatusLabel();
75 mLangStatus
->setText("Inactive");
76 mServerStatus
= new StatusLabel();
77 onServerStatusReply(0, 0, 0, 0, 0, 0);
79 mStatusBar
= statusBar();
80 mStatusBar
->addPermanentWidget( new QLabel("Interpreter:") );
81 mStatusBar
->addPermanentWidget( mLangStatus
);
82 mStatusBar
->addPermanentWidget( new QLabel("Server:") );
83 mStatusBar
->addPermanentWidget( mServerStatus
);
86 mEditors
= new MultiEditor(main
);
90 mCmdLine
= new CmdLine("Command Line:");
91 connect(mCmdLine
, SIGNAL(invoked(QString
, bool)),
92 main
->scProcess(), SLOT(evaluateCode(QString
, bool)));
94 mFindReplaceTool
= new TextFindReplacePanel
;
96 mGoToLineTool
= new GoToLineTool();
97 connect(mGoToLineTool
, SIGNAL(activated(int)), this, SLOT(hideToolBox()));
99 mToolBox
= new ToolBox
;
100 mToolBox
->addWidget(mCmdLine
);
101 mToolBox
->addWidget(mFindReplaceTool
);
102 mToolBox
->addWidget(mGoToLineTool
);
106 mDocListDock
= new DocumentsDock(main
->documentManager(), this);
107 mDocListDock
->setObjectName("documents-dock");
108 addDockWidget(Qt::RightDockWidgetArea
, mDocListDock
);
109 mDocListDock
->hide();
112 mPostDock
= new PostDock(this);
113 mPostDock
->setObjectName("post-dock");
114 addDockWidget(Qt::LeftDockWidgetArea
, mPostDock
);
117 QVBoxLayout
*center_box
= new QVBoxLayout
;
118 center_box
->setContentsMargins(0,0,0,0);
119 center_box
->setSpacing(0);
120 center_box
->addWidget(mEditors
);
121 center_box
->addWidget(mToolBox
);
123 QWidget
*central
= new QWidget
;
124 central
->setLayout(center_box
);
125 setCentralWidget(central
);
127 // Session management
128 connect(main
->sessionManager(), SIGNAL(saveSessionRequest(Session
*)),
129 this, SLOT(saveSession(Session
*)));
130 connect(main
->sessionManager(), SIGNAL(switchSessionRequest(Session
*)),
131 this, SLOT(switchSession(Session
*)));
132 connect(main
->sessionManager(), SIGNAL(currentSessionNameChanged()),
133 this, SLOT(updateWindowTitle()));
134 // A system for easy evaluation of pre-defined code:
135 connect(&mCodeEvalMapper
, SIGNAL(mapped(QString
)),
136 this, SIGNAL(evaluateCode(QString
)));
137 connect(this, SIGNAL(evaluateCode(QString
,bool)),
138 main
->scProcess(), SLOT(evaluateCode(QString
,bool)));
139 // Interpreter: post output
140 connect(main
->scProcess(), SIGNAL( scPost(QString
) ),
141 mPostDock
->mPostWindow
, SLOT( post(QString
) ) );
142 // Interpreter: monitor running state
143 connect(main
->scProcess(), SIGNAL( stateChanged(QProcess::ProcessState
) ),
144 this, SLOT( onInterpreterStateChanged(QProcess::ProcessState
) ) );
145 // Interpreter: forward status messages
146 connect(main
->scProcess(), SIGNAL(statusMessage(const QString
&)),
147 this, SLOT(showStatusMessage(const QString
&)));
149 // Document list interaction
150 connect(mDocListDock
->list(), SIGNAL(clicked(Document
*)),
151 mEditors
, SLOT(setCurrent(Document
*)));
152 connect(mEditors
, SIGNAL(currentDocumentChanged(Document
*)),
153 mDocListDock
->list(), SLOT(setCurrent(Document
*)),
154 Qt::QueuedConnection
);
156 // Update actions on document change
157 connect(mEditors
, SIGNAL(currentDocumentChanged(Document
*)),
158 this, SLOT(onCurrentDocumentChanged(Document
*)));
159 // Document management
160 DocumentManager
*docMng
= main
->documentManager();
161 connect(docMng
, SIGNAL(changedExternally(Document
*)),
162 this, SLOT(onDocumentChangedExternally(Document
*)));
163 connect(docMng
, SIGNAL(recentsChanged()),
164 this, SLOT(updateRecentDocsMenu()));
166 connect(main
, SIGNAL(applySettingsRequest(Settings::Manager
*)),
167 this, SLOT(applySettings(Settings::Manager
*)));
170 connect(mToolBox
->closeButton(), SIGNAL(clicked()), this, SLOT(hideToolBox()));
172 connect(main
->scResponder(), SIGNAL(serverRunningChanged(bool,QString
,int)), this, SLOT(onServerRunningChanged(bool,QString
,int)));
173 connect(main
->scServer(), SIGNAL(updateServerStatus(int,int,int,int,float,float)), this, SLOT(onServerStatusReply(int,int,int,int,float,float)));
178 // Must be called after createAtions(), because it accesses an action:
179 onServerRunningChanged(false, "", 0);
181 mServerStatus
->addAction( action(ServerToggleRunning
) );
182 mServerStatus
->setContextMenuPolicy(Qt::ActionsContextMenu
);
184 // Initialize recent documents menu
185 updateRecentDocsMenu();
188 icon
.addFile(":/icons/sc-cube-128");
189 icon
.addFile(":/icons/sc-cube-48");
190 icon
.addFile(":/icons/sc-cube-32");
191 icon
.addFile(":/icons/sc-cube-16");
192 QApplication::setWindowIcon(icon
);
197 void MainWindow::createActions()
199 Settings::Manager
*settings
= mMain
->settings();
200 settings
->beginGroup("IDE/shortcuts");
205 mActions
[Quit
] = act
= new QAction(
206 QIcon::fromTheme("application-exit"), tr("&Quit..."), this);
207 act
->setShortcut(tr("Ctrl+Q", "Quit application"));
208 act
->setStatusTip(tr("Quit SuperCollider IDE"));
209 QObject::connect( act
, SIGNAL(triggered()), this, SLOT(onQuit()) );
211 mActions
[DocNew
] = act
= new QAction(
212 QIcon::fromTheme("document-new"), tr("&New"), this);
213 act
->setShortcut(tr("Ctrl+N", "New document"));
214 act
->setStatusTip(tr("Create a new document"));
215 connect(act
, SIGNAL(triggered()), this, SLOT(newDocument()));
217 mActions
[DocOpen
] = act
= new QAction(
218 QIcon::fromTheme("document-open"), tr("&Open..."), this);
219 act
->setShortcut(tr("Ctrl+O", "Open document"));
220 act
->setStatusTip(tr("Open an existing file"));
221 connect(act
, SIGNAL(triggered()), this, SLOT(openDocument()));
223 mActions
[DocSave
] = act
= new QAction(
224 QIcon::fromTheme("document-save"), tr("&Save"), this);
225 act
->setShortcut(tr("Ctrl+S", "Save document"));
226 act
->setStatusTip(tr("Save the current document"));
227 connect(act
, SIGNAL(triggered()), this, SLOT(saveDocument()));
229 mActions
[DocSaveAs
] = act
= new QAction(
230 QIcon::fromTheme("document-save-as"), tr("Save &As..."), this);
231 act
->setShortcut(tr("Ctrl+Shift+S", "Save &As..."));
232 act
->setStatusTip(tr("Save the current document into a different file"));
233 connect(act
, SIGNAL(triggered()), this, SLOT(saveDocumentAs()));
235 mActions
[DocSaveAll
] = act
= new QAction(
236 QIcon::fromTheme("document-save"), tr("Save All..."), this);
237 act
->setShortcut(tr("Ctrl+Alt+S", "Save all documents"));
238 act
->setStatusTip(tr("Save all open documents"));
239 connect(act
, SIGNAL(triggered()), this, SLOT(saveAllDocuments()));
241 mActions
[DocClose
] = act
= new QAction(
242 QIcon::fromTheme("window-close"), tr("&Close"), this);
243 act
->setShortcut(tr("Ctrl+W", "Close document"));
244 act
->setStatusTip(tr("Close the current document"));
245 connect(act
, SIGNAL(triggered()), this, SLOT(closeDocument()));
247 mActions
[DocCloseAll
] = act
= new QAction(
248 QIcon::fromTheme("window-close"), tr("Close All..."), this);
249 act
->setShortcut(tr("Ctrl+Shift+W", "Close all documents"));
250 act
->setStatusTip(tr("Close all documents"));
251 connect(act
, SIGNAL(triggered()), this, SLOT(closeAllDocuments()));
253 mActions
[DocReload
] = act
= new QAction(
254 QIcon::fromTheme("view-refresh"), tr("&Reload"), this);
255 act
->setShortcut(tr("F5", "Reload document"));
256 act
->setStatusTip(tr("Reload the current document"));
257 connect(act
, SIGNAL(triggered()), this, SLOT(reloadDocument()));
259 mActions
[ClearRecentDocs
] = act
= new QAction(tr("Clear", "Clear recent documents"), this);
260 connect(act
, SIGNAL(triggered()),
261 Main::instance()->documentManager(), SLOT(clearRecents()));
264 mActions
[NewSession
] = act
= new QAction(
265 QIcon::fromTheme("document-new"), tr("&New Session"), this);
266 act
->setStatusTip(tr("Open a new session"));
267 connect(act
, SIGNAL(triggered()), this, SLOT(newSession()));
269 mActions
[SaveSessionAs
] = act
= new QAction(
270 QIcon::fromTheme("document-save-as"), tr("Save Session &As..."), this);
271 act
->setStatusTip(tr("Save the current session with a different name"));
272 connect(act
, SIGNAL(triggered()), this, SLOT(saveCurrentSessionAs()));
274 mActions
[ManageSessions
] = act
= new QAction(
275 tr("&Manage Sessions..."), this);
276 connect(act
, SIGNAL(triggered()), this, SLOT(openSessionsDialog()));
278 mActions
[OpenSessionSwitchDialog
] = act
= new QAction(
279 tr("&Switch Session..."), this);
280 connect(act
, SIGNAL(triggered()), this, SLOT(showSwitchSessionDialog()));
281 act
->setShortcut(tr("Ctrl+Shift+Q", "Switch Session"));
284 mActions
[Find
] = act
= new QAction(
285 QIcon::fromTheme("edit-find"), tr("&Find..."), this);
286 act
->setShortcut(tr("Ctrl+F", "Find"));
287 act
->setStatusTip(tr("Find text in document"));
288 connect(act
, SIGNAL(triggered()), this, SLOT(showFindTool()));
290 mActions
[Replace
] = act
= new QAction(
291 QIcon::fromTheme("edit-replace"), tr("&Replace..."), this);
292 act
->setShortcut(tr("Ctrl+R", "Replace"));
293 act
->setStatusTip(tr("Find and replace text in document"));
294 connect(act
, SIGNAL(triggered()), this, SLOT(showReplaceTool()));
297 mActions
[ShowCmdLine
] = act
= new QAction(tr("&Command Line"), this);
298 act
->setStatusTip(tr("Command line for quick code evaluation"));
299 act
->setShortcut(tr("Ctrl+E", "Show command line"));
300 connect(act
, SIGNAL(triggered()), this, SLOT(showCmdLine()));
302 mActions
[ShowGoToLineTool
] = act
= new QAction(tr("&Go To Line"), this);
303 act
->setStatusTip(tr("Tool to jump to a line by number"));
304 act
->setShortcut(tr("Ctrl+G", "Show go-to-line tool"));
305 connect(act
, SIGNAL(triggered()), this, SLOT(showGoToLineTool()));
307 mActions
[CloseToolBox
] = act
= new QAction(
308 QIcon::fromTheme("window-close"), tr("&Close Tool Panel"), this);
309 act
->setStatusTip(tr("Close any open tool panel"));
310 act
->setShortcut(tr("Esc", "Close tool box"));
311 connect(act
, SIGNAL(triggered()), this, SLOT(hideToolBox()));
313 mActions
[ShowFullScreen
] = act
= new QAction(tr("&Full Screen"), this);
314 act
->setCheckable(false);
315 act
->setShortcut(tr("Ctrl+Shift+F", "Show ScIDE in Full Screen"));
316 connect(act
, SIGNAL(triggered()), this, SLOT(toggleFullScreen()));
318 mActions
[ClearPostWindow
] = act
= new QAction(
319 QIcon::fromTheme("window-clearpostwindow"), tr("Clear Post Window"), this);
320 act
->setStatusTip(tr("Clear Post Window"));
321 act
->setShortcut(tr("Ctrl+Shift+C", "Clear Post Window"));
322 connect(act
, SIGNAL(triggered()), mPostDock
->mPostWindow
, SLOT(clear()));
324 mActions
[FocusPostWindow
] = act
= new QAction( tr("Focus Post Window"), this);
325 act
->setStatusTip(tr("Focus Post Window"));
326 act
->setShortcut(tr("Ctrl+L", "Focus Post Window"));
327 connect(act
, SIGNAL(triggered()), mPostDock
->mPostWindow
, SLOT(setFocus()));
329 mActions
[LookupReferences
] = act
= new QAction(
330 QIcon::fromTheme("window-lookupreferences"), tr("Look Up References"), this);
331 act
->setShortcut(tr("Ctrl+Shift+U", "Look Up References"));
332 connect(act
, SIGNAL(triggered()), this, SLOT(lookupReferences()));
334 mActions
[LookupDefinition
] = act
= new QAction(
335 QIcon::fromTheme("window-lookupdefinition"), tr("Look Up Definition"), this);
336 act
->setShortcut(tr("Ctrl+Shift+I", "Look Up Definition"));
337 connect(act
, SIGNAL(triggered()), this, SLOT(lookupDefinition()));
339 mActions
[LookupDocumentation
] = act
= new QAction(
340 QIcon::fromTheme("window-lookupDocumentation"), tr("Look Up Documentation"), this);
341 act
->setShortcut(tr("Ctrl+Shift+D", "Look Up Documentation"));
342 connect(act
, SIGNAL(triggered()), this, SLOT(lookupDocumentation()));
345 mActions
[OpenDefinition
] = act
= new QAction(tr("Open Class/Method Definition"), this);
346 act
->setShortcut(tr("Ctrl+I", "Open definition of selected class or method"));
347 connect(act
, SIGNAL(triggered(bool)), this, SLOT(openDefinition()));
349 mActions
[FindReferences
] = act
= new QAction(tr("Find References"), this);
350 act
->setShortcut(tr("Ctrl+U", "Find References"));
351 connect(act
, SIGNAL(triggered(bool)), this, SLOT(findReferences()));
354 mActions
[ShowSettings
] = act
= new QAction(tr("&Configure IDE..."), this);
355 act
->setStatusTip(tr("Show configuration dialog"));
356 connect(act
, SIGNAL(triggered()), this, SLOT(showSettings()));
360 mActions
[Help
] = act
= new QAction(
361 QIcon::fromTheme("system-help"), tr("Open Help Browser"), this);
362 act
->setStatusTip(tr("Open help."));
363 connect(act
, SIGNAL(triggered()), this, SLOT(openHelp()));
365 mActions
[HelpForSelection
] = act
= new QAction(
366 QIcon::fromTheme("system-help"), tr("&Help for Selection"), this);
367 act
->setShortcut(tr("Ctrl+D", "Help for selection"));
368 act
->setStatusTip(tr("Find help for selected text"));
369 connect(act
, SIGNAL(triggered()), this, SLOT(openDocumentation()));
372 mActions
[ServerToggleRunning
] = act
= new QAction(tr("Boot or quit server"), this);
373 act
->setShortcut(tr("Ctrl+B", "Boot or quit default server"));
374 connect(act
, SIGNAL(triggered()), this, SLOT(serverToggleRunning()));
376 mActions
[ServerReboot
] = act
= new QAction(tr("Reboot server"), this);
377 act
->setShortcut(tr("Ctrl+Shift+B", "Reboot default server"));
378 connect(act
, SIGNAL(triggered()), this, SLOT(serverReboot()));
380 mActions
[ServerShowMeters
] = act
= new QAction(tr("Show server meter"), this);
381 act
->setShortcut(tr("Ctrl+M", "Show server meter"));
382 connect(act
, SIGNAL(triggered()), this, SLOT(serverShowMeters()));
384 mActions
[ServerDumpNodeTree
] = act
= new QAction(tr("Dump node tree"), this);
385 act
->setShortcut(tr("Ctrl+T", "Dump node tree"));
386 connect(act
, SIGNAL(triggered()), this, SLOT(serverDumpNodeTree()));
388 mActions
[ServerDumpNodeTreeWithControls
] = act
= new QAction(tr("Dump node tree with controls"), this);
389 act
->setShortcut(tr("Ctrl+Shift+T", "Dump node tree with controls"));
390 connect(act
, SIGNAL(triggered()), this, SLOT(serverDumpNodeTreeWithControls()));
392 settings
->endGroup(); // IDE/shortcuts;
395 // Add actions to settings
396 for (int i
= 0; i
< ActionCount
; ++i
)
397 settings
->addAction( mActions
[i
] );
400 void MainWindow::createMenus()
405 menu
= new QMenu(tr("&File"), this);
406 menu
->addAction( mActions
[DocNew
] );
407 menu
->addAction( mActions
[DocOpen
] );
408 mRecentDocsMenu
= menu
->addMenu(tr("Open Recent", "Open a recent document"));
409 connect(mRecentDocsMenu
, SIGNAL(triggered(QAction
*)),
410 this, SLOT(onRecentDocAction(QAction
*)));
411 menu
->addAction( mActions
[DocSave
] );
412 menu
->addAction( mActions
[DocSaveAs
] );
413 menu
->addAction( mActions
[DocSaveAll
] );
414 menu
->addSeparator();
415 menu
->addAction( mActions
[DocReload
] );
416 menu
->addSeparator();
417 menu
->addAction( mActions
[DocClose
] );
418 menu
->addAction( mActions
[DocCloseAll
] );
419 menu
->addSeparator();
420 menu
->addAction( mActions
[Quit
] );
422 menuBar()->addMenu(menu
);
424 menu
= new QMenu(tr("&Session"), this);
425 menu
->addAction( mActions
[NewSession
] );
426 menu
->addAction( mActions
[SaveSessionAs
] );
427 submenu
= menu
->addMenu(tr("&Open Session"));
428 connect(submenu
, SIGNAL(triggered(QAction
*)),
429 this, SLOT(onOpenSessionAction(QAction
*)));
430 mSessionsMenu
= submenu
;
431 updateSessionsMenu();
432 menu
->addSeparator();
433 menu
->addAction( mActions
[ManageSessions
] );
434 menu
->addAction( mActions
[OpenSessionSwitchDialog
] );
436 menuBar()->addMenu(menu
);
438 menu
= new QMenu(tr("&Edit"), this);
439 menu
->addAction( mEditors
->action(MultiEditor::Undo
) );
440 menu
->addAction( mEditors
->action(MultiEditor::Redo
) );
441 menu
->addSeparator();
442 menu
->addAction( mEditors
->action(MultiEditor::Cut
) );
443 menu
->addAction( mEditors
->action(MultiEditor::Copy
) );
444 menu
->addAction( mEditors
->action(MultiEditor::Paste
) );
445 menu
->addSeparator();
446 menu
->addAction( mActions
[Find
] );
447 menu
->addAction( mActions
[Replace
] );
448 menu
->addSeparator();
449 menu
->addAction( mEditors
->action(MultiEditor::IndentLineOrRegion
) );
450 menu
->addAction( mEditors
->action(MultiEditor::ToggleComment
) );
451 menu
->addAction( mEditors
->action(MultiEditor::ToggleOverwriteMode
) );
452 menu
->addAction( mEditors
->action(MultiEditor::SelectRegion
) );
454 menuBar()->addMenu(menu
);
456 menu
= new QMenu(tr("&View"), this);
457 submenu
= new QMenu(tr("&Docks"), this);
458 submenu
->addAction( mPostDock
->toggleViewAction() );
459 submenu
->addAction( mDocListDock
->toggleViewAction() );
460 menu
->addMenu(submenu
);
461 menu
->addSeparator();
462 submenu
= menu
->addMenu(tr("&Tool Panels"));
463 submenu
->addAction( mActions
[Find
] );
464 submenu
->addAction( mActions
[Replace
] );
465 submenu
->addAction( mActions
[ShowCmdLine
] );
466 submenu
->addAction( mActions
[ShowGoToLineTool
] );
467 submenu
->addSeparator();
468 submenu
->addAction( mActions
[CloseToolBox
] );
469 menu
->addSeparator();
470 menu
->addAction( mEditors
->action(MultiEditor::EnlargeFont
) );
471 menu
->addAction( mEditors
->action(MultiEditor::ShrinkFont
) );
472 menu
->addAction( mEditors
->action(MultiEditor::ResetFontSize
) );
473 menu
->addSeparator();
474 menu
->addAction( mEditors
->action(MultiEditor::ShowWhitespace
) );
475 menu
->addSeparator();
476 menu
->addAction( mEditors
->action(MultiEditor::NextDocument
) );
477 menu
->addAction( mEditors
->action(MultiEditor::PreviousDocument
) );
478 menu
->addSeparator();
479 menu
->addAction( mEditors
->action(MultiEditor::SplitHorizontally
) );
480 menu
->addAction( mEditors
->action(MultiEditor::SplitVertically
) );
481 menu
->addAction( mEditors
->action(MultiEditor::RemoveCurrentSplit
) );
482 menu
->addAction( mEditors
->action(MultiEditor::RemoveAllSplits
) );
483 menu
->addSeparator();
484 menu
->addAction( mActions
[FocusPostWindow
] );
485 menu
->addAction( mActions
[ClearPostWindow
] );
486 menu
->addSeparator();
487 menu
->addAction( mActions
[ShowFullScreen
] );
488 menu
->addSeparator();
489 menu
->addAction( mActions
[OpenDefinition
] );
490 menu
->addAction( mActions
[LookupDefinition
] );
491 menu
->addAction( mActions
[FindReferences
] );
492 menu
->addAction( mActions
[LookupReferences
] );
494 menuBar()->addMenu(menu
);
496 menu
= new QMenu(tr("&Language"), this);
497 menu
->addAction( mMain
->scProcess()->action(SCProcess::StartSCLang
) );
498 menu
->addAction( mMain
->scProcess()->action(SCProcess::StopSCLang
) );
499 menu
->addAction( mMain
->scProcess()->action(SCProcess::RestartSCLang
) );
500 menu
->addAction( mMain
->scProcess()->action(SCProcess::RecompileClassLibrary
) );
501 menu
->addSeparator();
502 menu
->addAction( mActions
[ServerToggleRunning
] );
503 menu
->addAction( mActions
[ServerReboot
] );
504 menu
->addAction( mActions
[ServerShowMeters
] );
505 menu
->addAction( mActions
[ServerDumpNodeTree
] );
506 menu
->addAction( mActions
[ServerDumpNodeTreeWithControls
] );
507 menu
->addSeparator();
508 menu
->addAction( mEditors
->action(MultiEditor::EvaluateCurrentDocument
) );
509 menu
->addAction( mEditors
->action(MultiEditor::EvaluateRegion
) );
510 menu
->addAction( mEditors
->action(MultiEditor::EvaluateLine
) );
511 menu
->addSeparator();
512 menu
->addAction( mMain
->scProcess()->action(ScIDE::SCProcess::RunMain
) );
513 menu
->addAction( mMain
->scProcess()->action(ScIDE::SCProcess::StopMain
) );
515 menuBar()->addMenu(menu
);
517 menu
= new QMenu(tr("&Settings"), this);
518 menu
->addAction( mActions
[ShowSettings
] );
520 menuBar()->addMenu(menu
);
522 menu
= new QMenu(tr("&Help"), this);
523 menu
->addAction( mActions
[Help
] );
524 menu
->addAction( mActions
[HelpForSelection
] );
525 menu
->addAction( mActions
[LookupDocumentation
] );
527 menuBar()->addMenu(menu
);
530 void MainWindow::saveWindowState()
532 Settings::Manager
*settings
= Main::settings();
533 settings
->beginGroup("IDE/mainWindow");
534 settings
->setValue("geometry", this->saveGeometry().toBase64());
535 settings
->setValue("state", this->saveState().toBase64());
536 settings
->endGroup();
539 void MainWindow::restoreWindowState()
541 Settings::Manager
*settings
= Main::settings();
542 settings
->beginGroup("IDE/mainWindow");
544 QByteArray geom
= QByteArray::fromBase64( settings
->value("geometry").value
<QByteArray
>() );
546 restoreGeometry(geom
);
548 setWindowState( windowState() & ~Qt::WindowFullScreen
| Qt::WindowMaximized
);
550 QByteArray state
= QByteArray::fromBase64( settings
->value("state").value
<QByteArray
>() );
551 if (!state
.isEmpty())
554 settings
->endGroup();
557 void MainWindow::focusCodeEditor()
559 if (mEditors
->currentEditor())
560 mEditors
->currentEditor()->setFocus();
562 mEditors
->setFocus();
565 void MainWindow::newSession()
567 if (promptSaveDocs())
568 mMain
->sessionManager()->newSession();
571 void MainWindow::saveCurrentSessionAs()
573 QString name
= QInputDialog::getText( this,
574 "Save Current Session",
575 "Enter a name for the session:" );
577 if (name
.isEmpty()) return;
579 mMain
->sessionManager()->saveSessionAs(name
);
581 updateSessionsMenu();
584 void MainWindow::onOpenSessionAction( QAction
* action
)
586 openSession(action
->text());
589 void MainWindow::switchSession( Session
*session
)
592 session
->beginGroup("mainWindow");
593 QByteArray geom
= QByteArray::fromBase64( session
->value("geometry").value
<QByteArray
>() );
594 QByteArray state
= QByteArray::fromBase64( session
->value("state").value
<QByteArray
>() );
597 // Workaround for Qt bug 4397:
598 setWindowState(Qt::WindowNoState
);
601 restoreGeometry(geom
);
602 if (!state
.isEmpty())
605 updateClockWidget(isFullScreen());
608 mEditors
->switchSession(session
);
613 void MainWindow::saveSession( Session
*session
)
615 session
->beginGroup("mainWindow");
616 session
->setValue("geometry", this->saveGeometry().toBase64());
617 session
->setValue("state", this->saveState().toBase64());
620 mEditors
->saveSession(session
);
623 void MainWindow::openSessionsDialog()
625 QPointer
<MainWindow
> mainwin(this);
626 SessionsDialog
dialog(mMain
->sessionManager(), this);
629 mainwin
->updateSessionsMenu();
632 QAction
*MainWindow::action( ActionRole role
)
634 Q_ASSERT( role
< ActionCount
);
635 return mActions
[role
];
638 bool MainWindow::quit()
640 if (!promptSaveDocs())
650 void MainWindow::onQuit()
655 void MainWindow::onCurrentDocumentChanged( Document
* doc
)
659 mActions
[DocSave
]->setEnabled(doc
);
660 mActions
[DocSaveAs
]->setEnabled(doc
);
661 mActions
[DocClose
]->setEnabled(doc
);
663 ScCodeEditor
*editor
= mEditors
->currentEditor();
664 mFindReplaceTool
->setEditor( editor
);
665 mGoToLineTool
->setEditor( editor
);
668 void MainWindow::onDocumentChangedExternally( Document
*doc
)
673 mDocDialog
= new DocumentsDialog(DocumentsDialog::ExternalChange
, this);
674 mDocDialog
->addDocument(doc
);
675 connect(mDocDialog
, SIGNAL(finished(int)), this, SLOT(onDocDialogFinished()));
679 void MainWindow::onDocDialogFinished()
681 mDocDialog
->deleteLater();
685 void MainWindow::updateRecentDocsMenu()
687 mRecentDocsMenu
->clear();
689 const QStringList
&recent
= mMain
->documentManager()->recents();
691 foreach( const QString
& path
, recent
)
692 mRecentDocsMenu
->addAction(path
);
694 if (!recent
.isEmpty()) {
695 mRecentDocsMenu
->addSeparator();
696 mRecentDocsMenu
->addAction(mActions
[ClearRecentDocs
]);
700 void MainWindow::onRecentDocAction( QAction
*action
)
702 mMain
->documentManager()->open(action
->text());
705 void MainWindow::onInterpreterStateChanged( QProcess::ProcessState state
)
711 case QProcess::NotRunning
:
715 case QProcess::Starting
:
717 color
= QColor(255,255,0);
719 case QProcess::Running
:
725 mLangStatus
->setText(text
);
726 mLangStatus
->setTextColor(color
);
730 void MainWindow::onServerStatusReply(int ugens
, int synths
, int groups
, int synthDefs
, float avgCPU
, float peakCPU
)
732 QString statusString
=
733 QString("%1% %2% %3u %4s %5g %6d")
734 .arg(avgCPU
, 5, 'f', 2)
735 .arg(peakCPU
, 5, 'f', 2)
741 mServerStatus
->setText(statusString
);
744 void MainWindow::onServerRunningChanged(bool running
, const QString
&, int)
746 QAction
*serverStatusAction
= mActions
[ServerToggleRunning
];
748 mServerStatus
->setTextColor( running
? Qt::green
: Qt::white
);
750 onServerStatusReply(0, 0, 0, 0, 0, 0);
752 serverStatusAction
->setText( tr("&Boot Server") );
753 serverStatusAction
->setStatusTip(tr("Boot sound synthesis server"));
755 serverStatusAction
->setText( tr("&Quit Server") );
756 serverStatusAction
->setStatusTip(tr("Quit sound synthesis server"));
760 void MainWindow::closeEvent(QCloseEvent
*event
)
762 if(!quit()) event
->ignore();
765 bool MainWindow::close( Document
*doc
)
767 if (doc
->textDocument()->isModified())
769 QMessageBox::StandardButton ret
;
770 ret
= QMessageBox::warning(
772 tr("SuperCollider IDE"),
773 tr("There are unsaved changes in document '%1'.\n\n"
774 "Do you want to save it?").arg(doc
->title()),
775 QMessageBox::Save
| QMessageBox::Discard
| QMessageBox::Cancel
,
776 QMessageBox::Save
// the default
780 case QMessageBox::Cancel
:
782 case QMessageBox::Save
:
783 if (!MainWindow::save(doc
))
790 Main::instance()->documentManager()->close(doc
);
794 bool MainWindow::reload( Document
*doc
)
796 if (doc
->filePath().isEmpty())
799 if (doc
->textDocument()->isModified())
801 QMessageBox::StandardButton ret
;
802 ret
= QMessageBox::warning(
804 tr("SuperCollider IDE"),
805 tr("There are unsaved changes in document '%1'.\n\n"
806 "Do you want to reload it?").arg(doc
->title()),
807 QMessageBox::Yes
| QMessageBox::No
,
808 QMessageBox::No
// the default
810 if (ret
== QMessageBox::No
)
814 return Main::instance()->documentManager()->reload(doc
);
817 bool MainWindow::save( Document
*doc
, bool forceChoose
)
819 DocumentManager
*mng
= Main::instance()->documentManager();
820 if (forceChoose
|| doc
->filePath().isEmpty()) {
821 QFileDialog
dialog(mInstance
);
822 dialog
.setAcceptMode( QFileDialog::AcceptSave
);
824 QStringList filters
= (QStringList()
825 << "SuperCollider Document(*.scd)"
826 << "SuperCollider Class file(*.sc)"
830 dialog
.setNameFilters(filters
);
831 dialog
.setDefaultSuffix("scd");
833 if (dialog
.exec() == QDialog::Accepted
)
834 return mng
->saveAs(doc
, dialog
.selectedFiles()[0]);
838 return mng
->save(doc
);
841 void MainWindow::newDocument()
843 mMain
->documentManager()->create();
846 void MainWindow::openDocument()
848 QFileDialog
dialog (this, Qt::Dialog
);
849 dialog
.setModal(true);
850 dialog
.setWindowModality(Qt::ApplicationModal
);
852 dialog
.setFileMode( QFileDialog::ExistingFiles
);
854 ScCodeEditor
* currentEditor
= mEditors
->currentEditor();
856 Document
* currentDocument
= currentEditor
->document();
857 QFileInfo
filePath (currentDocument
->filePath());
858 dialog
.setDirectory(filePath
.dir());
864 << "SuperCollider(*.scd *.sc)"
865 << "SCDoc(*.schelp)";
866 dialog
.setNameFilters(filters
);
870 QStringList filenames
= dialog
.selectedFiles();
871 foreach(QString filename
, filenames
)
872 mMain
->documentManager()->open(filename
);
876 void MainWindow::saveDocument()
878 ScCodeEditor
*editor
= mEditors
->currentEditor();
881 Document
*doc
= editor
->document();
884 MainWindow::save(doc
);
887 void MainWindow::saveDocumentAs()
889 ScCodeEditor
*editor
= mEditors
->currentEditor();
892 Document
*doc
= editor
->document();
895 MainWindow::save(doc
, true);
898 void MainWindow::saveAllDocuments()
900 QList
<Document
*> docs
= mMain
->documentManager()->documents();
901 foreach (Document
*doc
, docs
)
902 if (!MainWindow::save(doc
))
906 void MainWindow::reloadDocument()
908 ScCodeEditor
*editor
= mEditors
->currentEditor();
911 Q_ASSERT(editor
->document());
912 MainWindow::reload(editor
->document());
915 void MainWindow::closeDocument()
917 ScCodeEditor
*editor
= mEditors
->currentEditor();
920 Q_ASSERT(editor
->document());
921 MainWindow::close( editor
->document() );
924 void MainWindow::closeAllDocuments()
926 if (promptSaveDocs()) {
927 QList
<Document
*> docs
= mMain
->documentManager()->documents();
928 foreach (Document
*doc
, docs
)
929 mMain
->documentManager()->close(doc
);
933 bool MainWindow::promptSaveDocs()
935 QList
<Document
*> docs
= mMain
->documentManager()->documents();
936 QList
<Document
*> unsavedDocs
;
937 foreach(Document
* doc
, docs
)
938 if(doc
->textDocument()->isModified())
939 unsavedDocs
.append(doc
);
941 if (unsavedDocs
.count())
943 DocumentsDialog
dialog(unsavedDocs
, DocumentsDialog::Quit
, this);
952 void MainWindow::updateWindowTitle()
954 Session
*session
= mMain
->sessionManager()->currentSession();
955 ScCodeEditor
*editor
= mEditors
->currentEditor();
956 Document
*doc
= editor
? editor
->document() : 0;
961 title
.append(session
->name());
962 if (doc
) title
.append(": ");
966 if (!doc
->filePath().isEmpty()) {
967 QFileInfo info
= QFileInfo(doc
->filePath());
968 QString pathString
= info
.dir().path();
970 QString homePath
= QDir::homePath();
971 if (pathString
.startsWith(homePath
))
972 pathString
.replace(0, homePath
.size(), QString("~"));
974 QString titleString
= QString("%1 (%2)").arg(info
.fileName(), pathString
);
976 title
.append( titleString
);
978 title
.append( "Untitled" );
981 if (!title
.isEmpty())
984 title
.append("SuperCollider IDE");
986 setWindowTitle(title
);
989 void MainWindow::toggleFullScreen()
991 if (isFullScreen()) {
992 setWindowState(windowState() & ~Qt::WindowFullScreen
);
994 updateClockWidget(false);
996 setWindowState(windowState() | Qt::WindowFullScreen
);
998 updateClockWidget(true);
1002 void MainWindow::updateClockWidget(bool isFullScreen
)
1004 if (!isFullScreen
) {
1010 if (mClockLabel
== NULL
) {
1011 mClockLabel
= new StatusClockLabel(this);
1012 statusBar()->insertWidget(0, mClockLabel
);
1017 void MainWindow::openSession(const QString
&sessionName
)
1019 if (promptSaveDocs())
1020 mMain
->sessionManager()->openSession( sessionName
);
1023 void MainWindow::openDefinition()
1025 QWidget
* focussedWidget
= QApplication::focusWidget();
1027 int indexOfMethod
= focussedWidget
->metaObject()->indexOfMethod("openDefinition()");
1028 if (indexOfMethod
!= -1)
1029 QMetaObject::invokeMethod( focussedWidget
, "openDefinition", Qt::DirectConnection
);
1032 void MainWindow::lookupDefinition()
1034 LookupDialog
dialog(mEditors
);
1038 void MainWindow::lookupDocumentation()
1040 PopupTextInput
* dialog
= new PopupTextInput(tr("Look up Documentation For"), this);
1042 bool success
= dialog
->exec();
1044 Main::openDocumentation(dialog
->textValue());
1049 void MainWindow::findReferences()
1051 QWidget
* focussedWidget
= QApplication::focusWidget();
1053 int indexOfMethod
= focussedWidget
->metaObject()->indexOfMethod("findReferences()");
1054 if (indexOfMethod
!= -1)
1055 QMetaObject::invokeMethod( focussedWidget
, "findReferences", Qt::DirectConnection
);
1058 void MainWindow::lookupReferences()
1060 ReferencesDialog
dialog(parentWidget());
1065 void MainWindow::showStatusMessage( QString
const & string
)
1067 mStatusBar
->showMessage(string
, 3000);
1070 void MainWindow::applySettings( Settings::Manager
* settings
)
1072 mEditors
->applySettings(settings
);
1073 mPostDock
->mPostWindow
->applySettings(settings
);
1074 mCmdLine
->applySettings(settings
);
1078 void MainWindow::updateSessionsMenu()
1080 mSessionsMenu
->clear();
1081 QStringList sessions
= mMain
->sessionManager()->availableSessions();
1082 foreach (const QString
& session
, sessions
)
1083 mSessionsMenu
->addAction( session
);
1086 void MainWindow::showSwitchSessionDialog()
1088 SessionSwitchDialog
* dialog
= new SessionSwitchDialog(this);
1089 int result
= dialog
->exec();
1091 if (result
== QDialog::Accepted
)
1092 openSession(dialog
->activeElement());
1097 void MainWindow::showCmdLine()
1099 mToolBox
->setCurrentWidget( mCmdLine
);
1102 mCmdLine
->setFocus(Qt::OtherFocusReason
);
1105 void MainWindow::showGoToLineTool()
1107 ScCodeEditor
*editor
= mEditors
->currentEditor();
1108 mGoToLineTool
->setValue( editor
? editor
->textCursor().blockNumber() + 1 : 0 );
1110 mToolBox
->setCurrentWidget( mGoToLineTool
);
1113 mGoToLineTool
->setFocus();
1116 void MainWindow::showFindTool()
1118 mFindReplaceTool
->setMode( TextFindReplacePanel::Find
);
1119 mFindReplaceTool
->initiate();
1121 mToolBox
->setCurrentWidget( mFindReplaceTool
);
1124 mFindReplaceTool
->setFocus(Qt::OtherFocusReason
);
1127 void MainWindow::showReplaceTool()
1129 mFindReplaceTool
->setMode( TextFindReplacePanel::Replace
);
1130 mFindReplaceTool
->initiate();
1132 mToolBox
->setCurrentWidget( mFindReplaceTool
);
1135 mFindReplaceTool
->setFocus(Qt::OtherFocusReason
);
1138 void MainWindow::hideToolBox()
1141 ScCodeEditor
*editor
= mEditors
->currentEditor();
1143 // This slot is mapped to Escape, so also clear highlighting
1144 // whenever invoked:
1145 editor
->clearSearchHighlighting();
1146 if (!editor
->hasFocus())
1147 editor
->setFocus(Qt::OtherFocusReason
);
1151 void MainWindow::showSettings()
1153 Settings::Dialog
dialog(mMain
->settings());
1154 dialog
.resize(700,400);
1155 int result
= dialog
.exec();
1156 if( result
== QDialog::Accepted
)
1157 mMain
->applySettings();
1160 void MainWindow::openDocumentation()
1162 QWidget
* focussedWidget
= QApplication::focusWidget();
1164 bool documentationOpened
= false;
1166 int indexOfMethod
= focussedWidget
->metaObject()->indexOfMethod("openDocumentation()");
1167 if (indexOfMethod
!= -1)
1168 QMetaObject::invokeMethod( focussedWidget
, "openDocumentation", Qt::DirectConnection
,
1169 Q_RETURN_ARG(bool, documentationOpened
) );
1171 if (!documentationOpened
)
1175 void MainWindow::openHelp()
1177 QString code
= QString("Help.gui");
1178 Main::scProcess()->evaluateCode(code
, true);
1181 void MainWindow::serverToggleRunning()
1183 ScServer
*scServer
= Main::scServer();
1185 if (scServer
->isRunning())
1191 void MainWindow::serverReboot()
1193 ScServer
*scServer
= Main::scServer();
1197 void MainWindow::serverShowMeters()
1199 Main::evaluateCode("ScIDE.defaultServer.meter", true);
1202 void MainWindow::serverDumpNodeTree()
1204 ScServer
*scServer
= Main::scServer();
1205 scServer
->queryAllNodes(false);
1208 void MainWindow::serverDumpNodeTreeWithControls()
1210 ScServer
*scServer
= Main::scServer();
1211 scServer
->queryAllNodes(true);
1214 void MainWindow::dragEnterEvent( QDragEnterEvent
* event
)
1216 if (event
->mimeData()->hasUrls()) {
1217 foreach (QUrl url
, event
->mimeData()->urls()) {
1218 if (url
.scheme() == QString("file")) { // LATER: use isLocalFile
1219 // LATER: check mime type ?
1220 event
->acceptProposedAction();
1227 void MainWindow::dropEvent( QDropEvent
* event
)
1229 const QMimeData
* data
= event
->mimeData();
1230 if (data
->hasUrls()) {
1231 foreach (QUrl url
, data
->urls()) {
1232 if (url
.scheme() == QString("file")) // LATER: use isLocalFile
1233 Main::documentManager()->open(url
.toLocalFile());
1238 //////////////////////////// StatusLabel /////////////////////////////////
1240 StatusLabel::StatusLabel(QWidget
*parent
) : QLabel(parent
)
1242 setAutoFillBackground(true);
1244 setAlignment(Qt::AlignCenter
);
1245 setBackground(Qt::black
);
1246 setTextColor(Qt::white
);
1248 QFont
font("Monospace");
1249 font
.setStyleHint(QFont::Monospace
);
1254 void StatusLabel::setBackground(const QBrush
& brush
)
1256 QPalette
plt(palette());
1257 plt
.setBrush(QPalette::Window
, brush
);
1261 void StatusLabel::setTextColor(const QColor
& color
)
1263 QPalette
plt(palette());
1264 plt
.setColor(QPalette::WindowText
, color
);
1268 //////////////////////////// StatusClockLabel ////////////////////////////
1270 StatusClockLabel::StatusClockLabel(QWidget
* parent
):
1273 setTextColor(Qt::green
);
1274 mTimerId
= startTimer(1000);
1278 StatusClockLabel::~StatusClockLabel()
1280 killTimer(mTimerId
);
1283 void StatusClockLabel::timerEvent(QTimerEvent
*e
)
1285 if (e
->timerId() == mTimerId
)
1289 void StatusClockLabel::updateTime()
1291 setText(QTime::currentTime().toString());
1294 } // namespace ScIDE