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/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
);
118 QVBoxLayout
*center_box
= new QVBoxLayout
;
119 center_box
->setContentsMargins(0,0,0,0);
120 center_box
->setSpacing(0);
121 center_box
->addWidget(mEditors
);
122 center_box
->addWidget(mToolBox
);
124 QWidget
*central
= new QWidget
;
125 central
->setLayout(center_box
);
126 setCentralWidget(central
);
128 // Session management
129 connect(main
->sessionManager(), SIGNAL(saveSessionRequest(Session
*)),
130 this, SLOT(saveSession(Session
*)));
131 connect(main
->sessionManager(), SIGNAL(switchSessionRequest(Session
*)),
132 this, SLOT(switchSession(Session
*)));
133 connect(main
->sessionManager(), SIGNAL(currentSessionNameChanged()),
134 this, SLOT(updateWindowTitle()));
135 // A system for easy evaluation of pre-defined code:
136 connect(&mCodeEvalMapper
, SIGNAL(mapped(QString
)),
137 this, SIGNAL(evaluateCode(QString
)));
138 connect(this, SIGNAL(evaluateCode(QString
,bool)),
139 main
->scProcess(), SLOT(evaluateCode(QString
,bool)));
140 // Interpreter: post output
141 connect(main
->scProcess(), SIGNAL( scPost(QString
) ),
142 mPostDock
->mPostWindow
, SLOT( post(QString
) ) );
143 // Interpreter: monitor running state
144 connect(main
->scProcess(), SIGNAL( stateChanged(QProcess::ProcessState
) ),
145 this, SLOT( onInterpreterStateChanged(QProcess::ProcessState
) ) );
146 // Interpreter: forward status messages
147 connect(main
->scProcess(), SIGNAL(statusMessage(const QString
&)),
148 this, SLOT(showStatusMessage(const QString
&)));
150 // Document list interaction
151 connect(mDocListDock
->list(), SIGNAL(clicked(Document
*)),
152 mEditors
, SLOT(setCurrent(Document
*)));
153 connect(mEditors
, SIGNAL(currentDocumentChanged(Document
*)),
154 mDocListDock
->list(), SLOT(setCurrent(Document
*)),
155 Qt::QueuedConnection
);
157 // Update actions on document change
158 connect(mEditors
, SIGNAL(currentDocumentChanged(Document
*)),
159 this, SLOT(onCurrentDocumentChanged(Document
*)));
160 // Document management
161 DocumentManager
*docMng
= main
->documentManager();
162 connect(docMng
, SIGNAL(changedExternally(Document
*)),
163 this, SLOT(onDocumentChangedExternally(Document
*)));
164 connect(docMng
, SIGNAL(recentsChanged()),
165 this, SLOT(updateRecentDocsMenu()));
167 connect(main
, SIGNAL(applySettingsRequest(Settings::Manager
*)),
168 this, SLOT(applySettings(Settings::Manager
*)));
171 connect(mToolBox
->closeButton(), SIGNAL(clicked()), this, SLOT(hideToolBox()));
173 connect(main
->scResponder(), SIGNAL(serverRunningChanged(bool,QString
,int)), this, SLOT(onServerRunningChanged(bool,QString
,int)));
174 connect(main
->scServer(), SIGNAL(updateServerStatus(int,int,int,int,float,float)), this, SLOT(onServerStatusReply(int,int,int,int,float,float)));
179 // Must be called after createAtions(), because it accesses an action:
180 onServerRunningChanged(false, "", 0);
182 mServerStatus
->addAction( action(ToggleServerRunning
) );
183 mServerStatus
->setContextMenuPolicy(Qt::ActionsContextMenu
);
185 // Initialize recent documents menu
186 updateRecentDocsMenu();
189 icon
.addFile(":/icons/sc-cube-128");
190 icon
.addFile(":/icons/sc-cube-48");
191 icon
.addFile(":/icons/sc-cube-32");
192 icon
.addFile(":/icons/sc-cube-16");
193 QApplication::setWindowIcon(icon
);
198 void MainWindow::createActions()
200 Settings::Manager
*settings
= mMain
->settings();
201 settings
->beginGroup("IDE/shortcuts");
206 mActions
[Quit
] = act
= new QAction(
207 QIcon::fromTheme("application-exit"), tr("&Quit..."), this);
208 act
->setShortcut(tr("Ctrl+Q", "Quit application"));
209 act
->setStatusTip(tr("Quit SuperCollider IDE"));
210 QObject::connect( act
, SIGNAL(triggered()), this, SLOT(onQuit()) );
212 mActions
[DocNew
] = act
= new QAction(
213 QIcon::fromTheme("document-new"), tr("&New"), this);
214 act
->setShortcut(tr("Ctrl+N", "New document"));
215 act
->setStatusTip(tr("Create a new document"));
216 connect(act
, SIGNAL(triggered()), this, SLOT(newDocument()));
218 mActions
[DocOpen
] = act
= new QAction(
219 QIcon::fromTheme("document-open"), tr("&Open..."), this);
220 act
->setShortcut(tr("Ctrl+O", "Open document"));
221 act
->setStatusTip(tr("Open an existing file"));
222 connect(act
, SIGNAL(triggered()), this, SLOT(openDocument()));
224 mActions
[DocSave
] = act
= new QAction(
225 QIcon::fromTheme("document-save"), tr("&Save"), this);
226 act
->setShortcut(tr("Ctrl+S", "Save document"));
227 act
->setStatusTip(tr("Save the current document"));
228 connect(act
, SIGNAL(triggered()), this, SLOT(saveDocument()));
230 mActions
[DocSaveAs
] = act
= new QAction(
231 QIcon::fromTheme("document-save-as"), tr("Save &As..."), this);
232 act
->setShortcut(tr("Ctrl+Shift+S", "Save &As..."));
233 act
->setStatusTip(tr("Save the current document into a different file"));
234 connect(act
, SIGNAL(triggered()), this, SLOT(saveDocumentAs()));
236 mActions
[DocSaveAll
] = act
= new QAction(
237 QIcon::fromTheme("document-save"), tr("Save All..."), this);
238 act
->setShortcut(tr("Ctrl+Alt+S", "Save all documents"));
239 act
->setStatusTip(tr("Save all open documents"));
240 connect(act
, SIGNAL(triggered()), this, SLOT(saveAllDocuments()));
242 mActions
[DocClose
] = act
= new QAction(
243 QIcon::fromTheme("window-close"), tr("&Close"), this);
244 act
->setShortcut(tr("Ctrl+W", "Close document"));
245 act
->setStatusTip(tr("Close the current document"));
246 connect(act
, SIGNAL(triggered()), this, SLOT(closeDocument()));
248 mActions
[DocCloseAll
] = act
= new QAction(
249 QIcon::fromTheme("window-close"), tr("Close All..."), this);
250 act
->setShortcut(tr("Ctrl+Shift+W", "Close all documents"));
251 act
->setStatusTip(tr("Close all documents"));
252 connect(act
, SIGNAL(triggered()), this, SLOT(closeAllDocuments()));
254 mActions
[DocReload
] = act
= new QAction(
255 QIcon::fromTheme("view-refresh"), tr("&Reload"), this);
256 act
->setShortcut(tr("F5", "Reload document"));
257 act
->setStatusTip(tr("Reload the current document"));
258 connect(act
, SIGNAL(triggered()), this, SLOT(reloadDocument()));
260 mActions
[ClearRecentDocs
] = act
= new QAction(tr("Clear", "Clear recent documents"), this);
261 connect(act
, SIGNAL(triggered()),
262 Main::instance()->documentManager(), SLOT(clearRecents()));
265 mActions
[NewSession
] = act
= new QAction(
266 QIcon::fromTheme("document-new"), tr("&New Session"), this);
267 act
->setStatusTip(tr("Open a new session"));
268 connect(act
, SIGNAL(triggered()), this, SLOT(newSession()));
270 mActions
[SaveSessionAs
] = act
= new QAction(
271 QIcon::fromTheme("document-save-as"), tr("Save Session &As..."), this);
272 act
->setStatusTip(tr("Save the current session with a different name"));
273 connect(act
, SIGNAL(triggered()), this, SLOT(saveCurrentSessionAs()));
275 mActions
[ManageSessions
] = act
= new QAction(
276 tr("&Manage Sessions..."), this);
277 connect(act
, SIGNAL(triggered()), this, SLOT(openSessionsDialog()));
279 mActions
[OpenSessionSwitchDialog
] = act
= new QAction(
280 tr("&Switch Session..."), this);
281 connect(act
, SIGNAL(triggered()), this, SLOT(showSwitchSessionDialog()));
282 act
->setShortcut(tr("Ctrl+Shift+Q", "Switch Session"));
285 mActions
[Find
] = act
= new QAction(
286 QIcon::fromTheme("edit-find"), tr("&Find..."), this);
287 act
->setShortcut(tr("Ctrl+F", "Find"));
288 act
->setStatusTip(tr("Find text in document"));
289 connect(act
, SIGNAL(triggered()), this, SLOT(showFindTool()));
291 mActions
[Replace
] = act
= new QAction(
292 QIcon::fromTheme("edit-replace"), tr("&Replace..."), this);
293 act
->setShortcut(tr("Ctrl+R", "Replace"));
294 act
->setStatusTip(tr("Find and replace text in document"));
295 connect(act
, SIGNAL(triggered()), this, SLOT(showReplaceTool()));
298 mActions
[ShowCmdLine
] = act
= new QAction(tr("&Command Line"), this);
299 act
->setStatusTip(tr("Command line for quick code evaluation"));
300 act
->setShortcut(tr("Ctrl+E", "Show command line"));
301 connect(act
, SIGNAL(triggered()), this, SLOT(showCmdLine()));
303 mActions
[ShowGoToLineTool
] = act
= new QAction(tr("&Go To Line"), this);
304 act
->setStatusTip(tr("Tool to jump to a line by number"));
305 act
->setShortcut(tr("Ctrl+G", "Show go-to-line tool"));
306 connect(act
, SIGNAL(triggered()), this, SLOT(showGoToLineTool()));
308 mActions
[CloseToolBox
] = act
= new QAction(
309 QIcon::fromTheme("window-close"), tr("&Close Tool Panel"), this);
310 act
->setStatusTip(tr("Close any open tool panel"));
311 act
->setShortcut(tr("Esc", "Close tool box"));
312 connect(act
, SIGNAL(triggered()), this, SLOT(hideToolBox()));
314 mActions
[ShowFullScreen
] = act
= new QAction(tr("&Full Screen"), this);
315 act
->setCheckable(false);
316 act
->setShortcut(tr("Ctrl+Shift+F", "Show ScIDE in Full Screen"));
317 connect(act
, SIGNAL(triggered()), this, SLOT(toggleFullScreen()));
319 mActions
[ClearPostWindow
] = act
= new QAction(
320 QIcon::fromTheme("window-clearpostwindow"), tr("Clear Post Window"), this);
321 act
->setStatusTip(tr("Clear Post Window"));
322 act
->setShortcut(tr("Ctrl+Shift+C", "Clear Post Window"));
323 connect(act
, SIGNAL(triggered()), mPostDock
->mPostWindow
, SLOT(clear()));
325 mActions
[LookupReferences
] = act
= new QAction(
326 QIcon::fromTheme("window-lookupreferences"), tr("Lookup References"), this);
327 act
->setShortcut(tr("Ctrl+Shift+U", "Lookup References"));
328 connect(act
, SIGNAL(triggered()), this, SLOT(lookupReferences()));
330 mActions
[LookupDefinition
] = act
= new QAction(
331 QIcon::fromTheme("window-lookupdefinition"), tr("Lookup Definition"), this);
332 act
->setShortcut(tr("Ctrl+Shift+I", "Lookup Definition"));
333 connect(act
, SIGNAL(triggered()), this, SLOT(lookupDefinition()));
335 mActions
[LookupDocumentation
] = act
= new QAction(
336 QIcon::fromTheme("window-lookupDocumentation"), tr("Lookup Documentation"), this);
337 act
->setShortcut(tr("Ctrl+Shift+D", "Lookup Documentation"));
338 connect(act
, SIGNAL(triggered()), this, SLOT(lookupDocumentation()));
341 mActions
[OpenDefinition
] = act
= new QAction(tr("Open Class/Method Definition"), this);
342 act
->setShortcut(tr("Ctrl+I", "Open definition of selected class or method"));
343 connect(act
, SIGNAL(triggered(bool)), this, SLOT(openDefinition()));
345 mActions
[FindReferences
] = act
= new QAction(tr("Find References"), this);
346 act
->setShortcut(tr("Ctrl+U", "Find References"));
347 connect(act
, SIGNAL(triggered(bool)), this, SLOT(findReferences()));
350 mActions
[ShowSettings
] = act
= new QAction(tr("&Configure IDE..."), this);
351 act
->setStatusTip(tr("Show configuration dialog"));
352 connect(act
, SIGNAL(triggered()), this, SLOT(showSettings()));
356 mActions
[Help
] = act
= new QAction(
357 QIcon::fromTheme("system-help"), tr("Open Help Browser"), this);
358 act
->setStatusTip(tr("Open help."));
359 connect(act
, SIGNAL(triggered()), this, SLOT(openHelp()));
361 mActions
[HelpForSelection
] = act
= new QAction(
362 QIcon::fromTheme("system-help"), tr("&Help for Selection"), this);
363 act
->setShortcut(tr("Ctrl+D", "Help for selection"));
364 act
->setStatusTip(tr("Find help for selected text"));
365 connect(act
, SIGNAL(triggered()), this, SLOT(openDocumentation()));
368 mActions
[ToggleServerRunning
] = act
= new QAction(this);
369 connect(act
, SIGNAL(triggered()), this, SLOT(toggleServerRunning()));
371 settings
->endGroup(); // IDE/shortcuts;
373 // Add actions to settings
374 for (int i
= 0; i
< ActionCount
; ++i
)
375 settings
->addAction( mActions
[i
] );
378 void MainWindow::createMenus()
383 menu
= new QMenu(tr("&File"), this);
384 menu
->addAction( mActions
[DocNew
] );
385 menu
->addAction( mActions
[DocOpen
] );
386 mRecentDocsMenu
= menu
->addMenu(tr("Open Recent", "Open a recent document"));
387 connect(mRecentDocsMenu
, SIGNAL(triggered(QAction
*)),
388 this, SLOT(onRecentDocAction(QAction
*)));
389 menu
->addAction( mActions
[DocSave
] );
390 menu
->addAction( mActions
[DocSaveAs
] );
391 menu
->addAction( mActions
[DocSaveAll
] );
392 menu
->addSeparator();
393 menu
->addAction( mActions
[DocReload
] );
394 menu
->addSeparator();
395 menu
->addAction( mActions
[DocClose
] );
396 menu
->addAction( mActions
[DocCloseAll
] );
397 menu
->addSeparator();
398 menu
->addAction( mActions
[Quit
] );
400 menuBar()->addMenu(menu
);
402 menu
= new QMenu(tr("&Session"), this);
403 menu
->addAction( mActions
[NewSession
] );
404 menu
->addAction( mActions
[SaveSessionAs
] );
405 submenu
= menu
->addMenu(tr("&Open Session"));
406 connect(submenu
, SIGNAL(triggered(QAction
*)),
407 this, SLOT(onOpenSessionAction(QAction
*)));
408 mSessionsMenu
= submenu
;
409 updateSessionsMenu();
410 menu
->addSeparator();
411 menu
->addAction( mActions
[ManageSessions
] );
412 menu
->addAction( mActions
[OpenSessionSwitchDialog
] );
414 menuBar()->addMenu(menu
);
416 menu
= new QMenu(tr("&Edit"), this);
417 menu
->addAction( mEditors
->action(MultiEditor::Undo
) );
418 menu
->addAction( mEditors
->action(MultiEditor::Redo
) );
419 menu
->addSeparator();
420 menu
->addAction( mEditors
->action(MultiEditor::Cut
) );
421 menu
->addAction( mEditors
->action(MultiEditor::Copy
) );
422 menu
->addAction( mEditors
->action(MultiEditor::Paste
) );
423 menu
->addSeparator();
424 menu
->addAction( mActions
[Find
] );
425 menu
->addAction( mActions
[Replace
] );
426 menu
->addSeparator();
427 menu
->addAction( mEditors
->action(MultiEditor::IndentLineOrRegion
) );
428 menu
->addAction( mEditors
->action(MultiEditor::ToggleComment
) );
429 menu
->addAction( mEditors
->action(MultiEditor::ToggleOverwriteMode
) );
430 menu
->addAction( mEditors
->action(MultiEditor::SelectRegion
) );
431 menu
->addSeparator();
432 menu
->addAction( mActions
[OpenDefinition
] );
433 menu
->addAction( mActions
[FindReferences
] );
435 menuBar()->addMenu(menu
);
437 menu
= new QMenu(tr("&View"), this);
438 submenu
= new QMenu(tr("&Docks"), this);
439 submenu
->addAction( mPostDock
->toggleViewAction() );
440 submenu
->addAction( mDocListDock
->toggleViewAction() );
441 menu
->addMenu(submenu
);
442 menu
->addSeparator();
443 submenu
= menu
->addMenu(tr("&Tool Panels"));
444 submenu
->addAction( mActions
[Find
] );
445 submenu
->addAction( mActions
[Replace
] );
446 submenu
->addAction( mActions
[ShowCmdLine
] );
447 submenu
->addAction( mActions
[ShowGoToLineTool
] );
448 submenu
->addSeparator();
449 submenu
->addAction( mActions
[CloseToolBox
] );
450 menu
->addSeparator();
451 menu
->addAction( mEditors
->action(MultiEditor::EnlargeFont
) );
452 menu
->addAction( mEditors
->action(MultiEditor::ShrinkFont
) );
453 menu
->addAction( mEditors
->action(MultiEditor::ResetFontSize
) );
454 menu
->addSeparator();
455 menu
->addAction( mEditors
->action(MultiEditor::ShowWhitespace
) );
456 menu
->addSeparator();
457 menu
->addAction( mEditors
->action(MultiEditor::NextDocument
) );
458 menu
->addAction( mEditors
->action(MultiEditor::PreviousDocument
) );
459 menu
->addSeparator();
460 menu
->addAction( mEditors
->action(MultiEditor::SplitHorizontally
) );
461 menu
->addAction( mEditors
->action(MultiEditor::SplitVertically
) );
462 menu
->addAction( mEditors
->action(MultiEditor::RemoveCurrentSplit
) );
463 menu
->addAction( mEditors
->action(MultiEditor::RemoveAllSplits
) );
464 menu
->addSeparator();
465 menu
->addAction( mActions
[ClearPostWindow
] );
466 menu
->addSeparator();
467 menu
->addAction( mActions
[ShowFullScreen
] );
468 menu
->addSeparator();
469 menu
->addAction( mActions
[LookupDocumentation
] );
470 menu
->addAction( mActions
[LookupDefinition
] );
471 menu
->addAction( mActions
[LookupReferences
] );
473 menuBar()->addMenu(menu
);
475 menu
= new QMenu(tr("&Language"), this);
476 menu
->addAction( mMain
->scProcess()->action(SCProcess::StartSCLang
) );
477 menu
->addAction( mMain
->scProcess()->action(SCProcess::StopSCLang
) );
478 menu
->addAction( mMain
->scProcess()->action(SCProcess::RestartSCLang
) );
479 menu
->addAction( mMain
->scProcess()->action(SCProcess::RecompileClassLibrary
) );
480 menu
->addSeparator();
481 menu
->addAction( mEditors
->action(MultiEditor::EvaluateCurrentDocument
) );
482 menu
->addAction( mEditors
->action(MultiEditor::EvaluateRegion
) );
483 menu
->addAction( mEditors
->action(MultiEditor::EvaluateLine
) );
484 menu
->addSeparator();
485 menu
->addAction( mMain
->scProcess()->action(ScIDE::SCProcess::RunMain
) );
486 menu
->addAction( mMain
->scProcess()->action(ScIDE::SCProcess::StopMain
) );
488 menuBar()->addMenu(menu
);
490 menu
= new QMenu(tr("&Settings"), this);
491 menu
->addAction( mActions
[ShowSettings
] );
493 menuBar()->addMenu(menu
);
495 menu
= new QMenu(tr("&Help"), this);
496 menu
->addAction( mActions
[Help
] );
497 menu
->addAction( mActions
[HelpForSelection
] );
499 menuBar()->addMenu(menu
);
502 void MainWindow::saveWindowState()
504 Settings::Manager
*settings
= Main::settings();
505 settings
->beginGroup("IDE/mainWindow");
506 settings
->setValue("geometry", this->saveGeometry().toBase64());
507 settings
->setValue("state", this->saveState().toBase64());
508 settings
->endGroup();
511 void MainWindow::restoreWindowState()
513 Settings::Manager
*settings
= Main::settings();
514 settings
->beginGroup("IDE/mainWindow");
516 QByteArray geom
= QByteArray::fromBase64( settings
->value("geometry").value
<QByteArray
>() );
518 restoreGeometry(geom
);
520 setWindowState( windowState() & ~Qt::WindowFullScreen
| Qt::WindowMaximized
);
522 QByteArray state
= QByteArray::fromBase64( settings
->value("state").value
<QByteArray
>() );
523 if (!state
.isEmpty())
526 settings
->endGroup();
529 void MainWindow::newSession()
531 if (promptSaveDocs())
532 mMain
->sessionManager()->newSession();
535 void MainWindow::saveCurrentSessionAs()
537 QString name
= QInputDialog::getText( this,
538 "Save Current Session",
539 "Enter a name for the session:" );
541 if (name
.isEmpty()) return;
543 mMain
->sessionManager()->saveSessionAs(name
);
545 updateSessionsMenu();
548 void MainWindow::onOpenSessionAction( QAction
* action
)
550 openSession(action
->text());
553 void MainWindow::switchSession( Session
*session
)
556 session
->beginGroup("mainWindow");
557 QByteArray geom
= QByteArray::fromBase64( session
->value("geometry").value
<QByteArray
>() );
558 QByteArray state
= QByteArray::fromBase64( session
->value("state").value
<QByteArray
>() );
561 // Workaround for Qt bug 4397:
562 setWindowState(Qt::WindowNoState
);
565 restoreGeometry(geom
);
566 if (!state
.isEmpty())
569 updateClockWidget(isFullScreen());
572 mEditors
->switchSession(session
);
577 void MainWindow::saveSession( Session
*session
)
579 session
->beginGroup("mainWindow");
580 session
->setValue("geometry", this->saveGeometry().toBase64());
581 session
->setValue("state", this->saveState().toBase64());
584 mEditors
->saveSession(session
);
587 void MainWindow::openSessionsDialog()
589 QPointer
<MainWindow
> mainwin(this);
590 SessionsDialog
dialog(mMain
->sessionManager(), this);
593 mainwin
->updateSessionsMenu();
596 QAction
*MainWindow::action( ActionRole role
)
598 Q_ASSERT( role
< ActionCount
);
599 return mActions
[role
];
602 bool MainWindow::quit()
604 if (!promptSaveDocs())
614 void MainWindow::onQuit()
619 void MainWindow::onCurrentDocumentChanged( Document
* doc
)
623 mActions
[DocSave
]->setEnabled(doc
);
624 mActions
[DocSaveAs
]->setEnabled(doc
);
625 mActions
[DocClose
]->setEnabled(doc
);
627 CodeEditor
*editor
= mEditors
->currentEditor();
628 mFindReplaceTool
->setEditor( editor
);
629 mGoToLineTool
->setEditor( editor
);
632 void MainWindow::onDocumentChangedExternally( Document
*doc
)
637 mDocDialog
= new DocumentsDialog(DocumentsDialog::ExternalChange
, this);
638 mDocDialog
->addDocument(doc
);
639 connect(mDocDialog
, SIGNAL(finished(int)), this, SLOT(onDocDialogFinished()));
643 void MainWindow::onDocDialogFinished()
645 mDocDialog
->deleteLater();
649 void MainWindow::updateRecentDocsMenu()
651 mRecentDocsMenu
->clear();
653 const QStringList
&recent
= mMain
->documentManager()->recents();
655 foreach( const QString
& path
, recent
)
656 mRecentDocsMenu
->addAction(path
);
658 if (!recent
.isEmpty()) {
659 mRecentDocsMenu
->addSeparator();
660 mRecentDocsMenu
->addAction(mActions
[ClearRecentDocs
]);
664 void MainWindow::onRecentDocAction( QAction
*action
)
666 mMain
->documentManager()->open(action
->text());
669 void MainWindow::onInterpreterStateChanged( QProcess::ProcessState state
)
675 case QProcess::NotRunning
:
679 case QProcess::Starting
:
681 color
= QColor(255,255,0);
683 case QProcess::Running
:
689 mLangStatus
->setText(text
);
690 mLangStatus
->setTextColor(color
);
694 void MainWindow::onServerStatusReply(int ugens
, int synths
, int groups
, int synthDefs
, float avgCPU
, float peakCPU
)
696 QString statusString
=
697 QString("%1% %2% %3u %4s %5g %6d")
698 .arg(avgCPU
, 5, 'f', 2)
699 .arg(peakCPU
, 5, 'f', 2)
705 mServerStatus
->setText(statusString
);
708 void MainWindow::onServerRunningChanged(bool running
, const QString
&, int)
710 QAction
*serverStatusAction
= mActions
[ToggleServerRunning
];
712 mServerStatus
->setTextColor( running
? Qt::green
: Qt::white
);
714 onServerStatusReply(0, 0, 0, 0, 0, 0);
716 serverStatusAction
->setText( tr("&Boot Server") );
717 serverStatusAction
->setStatusTip(tr("Boot sound synthesis server"));
719 serverStatusAction
->setText( tr("&Quit Server") );
720 serverStatusAction
->setStatusTip(tr("Quit sound synthesis server"));
724 void MainWindow::closeEvent(QCloseEvent
*event
)
726 if(!quit()) event
->ignore();
729 bool MainWindow::close( Document
*doc
)
731 if (doc
->textDocument()->isModified())
733 QMessageBox::StandardButton ret
;
734 ret
= QMessageBox::warning(
736 tr("SuperCollider IDE"),
737 tr("There are unsaved changes in document '%1'.\n\n"
738 "Do you want to save it?").arg(doc
->title()),
739 QMessageBox::Save
| QMessageBox::Discard
| QMessageBox::Cancel
,
740 QMessageBox::Save
// the default
744 case QMessageBox::Cancel
:
746 case QMessageBox::Save
:
747 if (!MainWindow::save(doc
))
754 Main::instance()->documentManager()->close(doc
);
758 bool MainWindow::reload( Document
*doc
)
760 if (doc
->filePath().isEmpty())
763 if (doc
->textDocument()->isModified())
765 QMessageBox::StandardButton ret
;
766 ret
= QMessageBox::warning(
768 tr("SuperCollider IDE"),
769 tr("There are unsaved changes in document '%1'.\n\n"
770 "Do you want to reload it?").arg(doc
->title()),
771 QMessageBox::Yes
| QMessageBox::No
,
772 QMessageBox::No
// the default
774 if (ret
== QMessageBox::No
)
778 return Main::instance()->documentManager()->reload(doc
);
781 bool MainWindow::save( Document
*doc
, bool forceChoose
)
783 DocumentManager
*mng
= Main::instance()->documentManager();
784 if (forceChoose
|| doc
->filePath().isEmpty()) {
785 QFileDialog
dialog(mInstance
);
786 dialog
.setAcceptMode( QFileDialog::AcceptSave
);
788 QStringList filters
= (QStringList()
789 << "SuperCollider Document(*.scd)"
790 << "SuperCollider Class file(*.sc)"
794 dialog
.setNameFilters(filters
);
795 dialog
.setDefaultSuffix("scd");
797 if (dialog
.exec() == QDialog::Accepted
)
798 return mng
->saveAs(doc
, dialog
.selectedFiles()[0]);
802 return mng
->save(doc
);
805 void MainWindow::newDocument()
807 mMain
->documentManager()->create();
810 void MainWindow::openDocument()
812 QFileDialog
dialog (this, Qt::Dialog
);
813 dialog
.setModal(true);
814 dialog
.setWindowModality(Qt::ApplicationModal
);
816 dialog
.setFileMode( QFileDialog::ExistingFiles
);
818 CodeEditor
* currentEditor
= mEditors
->currentEditor();
820 Document
* currentDocument
= currentEditor
->document();
821 QFileInfo
filePath (currentDocument
->filePath());
822 dialog
.setDirectory(filePath
.dir());
828 << "SuperCollider(*.scd *.sc)"
829 << "SCDoc(*.schelp)";
830 dialog
.setNameFilters(filters
);
834 QStringList filenames
= dialog
.selectedFiles();
835 foreach(QString filename
, filenames
)
836 mMain
->documentManager()->open(filename
);
840 void MainWindow::saveDocument()
842 CodeEditor
*editor
= mEditors
->currentEditor();
845 Document
*doc
= editor
->document();
848 MainWindow::save(doc
);
851 void MainWindow::saveDocumentAs()
853 CodeEditor
*editor
= mEditors
->currentEditor();
856 Document
*doc
= editor
->document();
859 MainWindow::save(doc
, true);
862 void MainWindow::saveAllDocuments()
864 QList
<Document
*> docs
= mMain
->documentManager()->documents();
865 foreach (Document
*doc
, docs
)
866 if (!MainWindow::save(doc
))
870 void MainWindow::reloadDocument()
872 CodeEditor
*editor
= mEditors
->currentEditor();
875 Q_ASSERT(editor
->document());
876 MainWindow::reload(editor
->document());
879 void MainWindow::closeDocument()
881 CodeEditor
*editor
= mEditors
->currentEditor();
884 Q_ASSERT(editor
->document());
885 MainWindow::close( editor
->document() );
888 void MainWindow::closeAllDocuments()
890 if (promptSaveDocs()) {
891 QList
<Document
*> docs
= mMain
->documentManager()->documents();
892 foreach (Document
*doc
, docs
)
893 mMain
->documentManager()->close(doc
);
897 bool MainWindow::promptSaveDocs()
899 QList
<Document
*> docs
= mMain
->documentManager()->documents();
900 QList
<Document
*> unsavedDocs
;
901 foreach(Document
* doc
, docs
)
902 if(doc
->textDocument()->isModified())
903 unsavedDocs
.append(doc
);
905 if (unsavedDocs
.count())
907 DocumentsDialog
dialog(unsavedDocs
, DocumentsDialog::Quit
, this);
916 void MainWindow::updateWindowTitle()
918 Session
*session
= mMain
->sessionManager()->currentSession();
919 CodeEditor
*editor
= mEditors
->currentEditor();
920 Document
*doc
= editor
? editor
->document() : 0;
925 title
.append(session
->name());
926 if (doc
) title
.append(": ");
930 if (!doc
->filePath().isEmpty()) {
931 QFileInfo info
= QFileInfo(doc
->filePath());
932 QString pathString
= info
.dir().path();
934 QString homePath
= QDir::homePath();
935 if (pathString
.startsWith(homePath
))
936 pathString
.replace(0, homePath
.size(), QString("~"));
938 QString titleString
= QString("%1 (%2)").arg(info
.fileName(), pathString
);
940 title
.append( titleString
);
942 title
.append( "Untitled" );
945 if (!title
.isEmpty())
948 title
.append("SuperCollider IDE");
950 setWindowTitle(title
);
953 void MainWindow::toggleFullScreen()
955 if (isFullScreen()) {
956 setWindowState(windowState() & ~Qt::WindowFullScreen
);
958 updateClockWidget(false);
960 setWindowState(windowState() | Qt::WindowFullScreen
);
962 updateClockWidget(true);
966 void MainWindow::updateClockWidget(bool isFullScreen
)
974 if (mClockLabel
== NULL
) {
975 mClockLabel
= new StatusClockLabel(this);
976 statusBar()->insertWidget(0, mClockLabel
);
981 void MainWindow::openSession(const QString
&sessionName
)
983 if (promptSaveDocs())
984 mMain
->sessionManager()->openSession( sessionName
);
987 void MainWindow::openDefinition()
989 QWidget
* focussedWidget
= QApplication::focusWidget();
991 int indexOfMethod
= focussedWidget
->metaObject()->indexOfMethod("openDefinition()");
992 if (indexOfMethod
!= -1)
993 QMetaObject::invokeMethod( focussedWidget
, "openDefinition", Qt::DirectConnection
);
996 void MainWindow::lookupDefinition()
998 LookupDialog
dialog(mEditors
);
1002 void MainWindow::lookupDocumentation()
1004 PopupTextInput
* dialog
= new PopupTextInput(tr("Lookup Documentation For"), this);
1006 bool success
= dialog
->exec();
1008 Main::openDocumentation(dialog
->textValue());
1013 void MainWindow::findReferences()
1015 QWidget
* focussedWidget
= QApplication::focusWidget();
1017 int indexOfMethod
= focussedWidget
->metaObject()->indexOfMethod("findReferences()");
1018 if (indexOfMethod
!= -1)
1019 QMetaObject::invokeMethod( focussedWidget
, "findReferences", Qt::DirectConnection
);
1022 void MainWindow::lookupReferences()
1024 ReferencesDialog
dialog(parentWidget());
1029 void MainWindow::showStatusMessage( QString
const & string
)
1031 mStatusBar
->showMessage(string
, 3000);
1034 void MainWindow::applySettings( Settings::Manager
* settings
)
1036 mEditors
->applySettings(settings
);
1037 mPostDock
->mPostWindow
->applySettings(settings
);
1038 mCmdLine
->applySettings(settings
);
1042 void MainWindow::updateSessionsMenu()
1044 mSessionsMenu
->clear();
1045 QStringList sessions
= mMain
->sessionManager()->availableSessions();
1046 foreach (const QString
& session
, sessions
)
1047 mSessionsMenu
->addAction( session
);
1050 void MainWindow::showSwitchSessionDialog()
1052 SessionSwitchDialog
* dialog
= new SessionSwitchDialog(this);
1053 int result
= dialog
->exec();
1055 if (result
== QDialog::Accepted
)
1056 openSession(dialog
->activeElement());
1061 void MainWindow::showCmdLine()
1063 mToolBox
->setCurrentWidget( mCmdLine
);
1066 mCmdLine
->setFocus(Qt::OtherFocusReason
);
1069 void MainWindow::showGoToLineTool()
1071 CodeEditor
*editor
= mEditors
->currentEditor();
1072 mGoToLineTool
->setValue( editor
? editor
->textCursor().blockNumber() + 1 : 0 );
1074 mToolBox
->setCurrentWidget( mGoToLineTool
);
1077 mGoToLineTool
->setFocus();
1080 void MainWindow::showFindTool()
1082 mFindReplaceTool
->setMode( TextFindReplacePanel::Find
);
1083 mFindReplaceTool
->initiate();
1085 mToolBox
->setCurrentWidget( mFindReplaceTool
);
1088 mFindReplaceTool
->setFocus(Qt::OtherFocusReason
);
1091 void MainWindow::showReplaceTool()
1093 mFindReplaceTool
->setMode( TextFindReplacePanel::Replace
);
1094 mFindReplaceTool
->initiate();
1096 mToolBox
->setCurrentWidget( mFindReplaceTool
);
1099 mFindReplaceTool
->setFocus(Qt::OtherFocusReason
);
1102 void MainWindow::hideToolBox()
1105 CodeEditor
*editor
= mEditors
->currentEditor();
1107 // This slot is mapped to Escape, so also clear highlighting
1108 // whenever invoked:
1109 editor
->clearSearchHighlighting();
1110 if (!editor
->hasFocus())
1111 editor
->setFocus(Qt::OtherFocusReason
);
1115 void MainWindow::showSettings()
1117 Settings::Dialog
dialog(mMain
->settings());
1118 dialog
.resize(700,400);
1119 int result
= dialog
.exec();
1120 if( result
== QDialog::Accepted
)
1121 mMain
->applySettings();
1124 void MainWindow::openDocumentation()
1126 QWidget
* focussedWidget
= QApplication::focusWidget();
1128 bool documentationOpened
= false;
1130 int indexOfMethod
= focussedWidget
->metaObject()->indexOfMethod("openDocumentation()");
1131 if (indexOfMethod
!= -1)
1132 QMetaObject::invokeMethod( focussedWidget
, "openDocumentation", Qt::DirectConnection
,
1133 Q_RETURN_ARG(bool, documentationOpened
) );
1135 if (!documentationOpened
)
1139 void MainWindow::openHelp()
1141 QString code
= QString("Help.gui");
1142 Main::scProcess()->evaluateCode(code
, true);
1145 void MainWindow::toggleServerRunning()
1147 ScServer
*scServer
= Main::scServer();
1149 if (scServer
->isRunning())
1155 void MainWindow::dragEnterEvent( QDragEnterEvent
* event
)
1157 if (event
->mimeData()->hasUrls()) {
1158 foreach (QUrl url
, event
->mimeData()->urls()) {
1159 if (url
.scheme() == QString("file")) { // LATER: use isLocalFile
1160 // LATER: check mime type ?
1161 event
->acceptProposedAction();
1168 void MainWindow::dropEvent( QDropEvent
* event
)
1170 const QMimeData
* data
= event
->mimeData();
1171 if (data
->hasUrls()) {
1172 foreach (QUrl url
, data
->urls()) {
1173 if (url
.scheme() == QString("file")) // LATER: use isLocalFile
1174 Main::documentManager()->open(url
.toLocalFile());
1179 //////////////////////////// StatusLabel /////////////////////////////////
1181 StatusLabel::StatusLabel(QWidget
*parent
) : QLabel(parent
)
1183 setAutoFillBackground(true);
1185 setAlignment(Qt::AlignCenter
);
1186 setBackground(Qt::black
);
1187 setTextColor(Qt::white
);
1189 QFont
font("Monospace");
1190 font
.setStyleHint(QFont::Monospace
);
1195 void StatusLabel::setBackground(const QBrush
& brush
)
1197 QPalette
plt(palette());
1198 plt
.setBrush(QPalette::Window
, brush
);
1202 void StatusLabel::setTextColor(const QColor
& color
)
1204 QPalette
plt(palette());
1205 plt
.setColor(QPalette::WindowText
, color
);
1209 //////////////////////////// StatusClockLabel ////////////////////////////
1211 StatusClockLabel::StatusClockLabel(QWidget
* parent
):
1214 setTextColor(Qt::green
);
1215 mTimerId
= startTimer(1000);
1219 StatusClockLabel::~StatusClockLabel()
1221 killTimer(mTimerId
);
1224 void StatusClockLabel::timerEvent(QTimerEvent
*e
)
1226 if (e
->timerId() == mTimerId
)
1230 void StatusClockLabel::updateTime()
1232 setText(QTime::currentTime().toString());
1235 } // namespace ScIDE