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>
57 MainWindow
* MainWindow::mInstance
= 0;
59 MainWindow::MainWindow(Main
* main
) :
67 setCorner( Qt::BottomLeftCorner
, Qt::LeftDockWidgetArea
);
69 // Construct status bar:
71 mLangStatus
= new StatusLabel();
72 mLangStatus
->setText("Inactive");
73 mServerStatus
= new StatusLabel();
74 onServerStatusReply(0, 0, 0, 0, 0, 0);
76 mStatusBar
= statusBar();
77 mStatusBar
->addPermanentWidget( new QLabel("Interpreter:") );
78 mStatusBar
->addPermanentWidget( mLangStatus
);
79 mStatusBar
->addPermanentWidget( new QLabel("Server:") );
80 mStatusBar
->addPermanentWidget( mServerStatus
);
83 mEditors
= new MultiEditor(main
);
87 mCmdLine
= new CmdLine("Command Line:");
88 connect(mCmdLine
, SIGNAL(invoked(QString
, bool)),
89 main
->scProcess(), SLOT(evaluateCode(QString
, bool)));
91 mFindReplaceTool
= new TextFindReplacePanel
;
93 mGoToLineTool
= new GoToLineTool();
94 connect(mGoToLineTool
, SIGNAL(activated(int)), this, SLOT(hideToolBox()));
96 mToolBox
= new ToolBox
;
97 mToolBox
->addWidget(mCmdLine
);
98 mToolBox
->addWidget(mFindReplaceTool
);
99 mToolBox
->addWidget(mGoToLineTool
);
103 mDocListDock
= new DocumentsDock(main
->documentManager(), this);
104 mDocListDock
->setObjectName("documents-dock");
105 addDockWidget(Qt::RightDockWidgetArea
, mDocListDock
);
106 mDocListDock
->hide();
109 mPostDock
= new PostDock(this);
110 mPostDock
->setObjectName("post-dock");
111 addDockWidget(Qt::LeftDockWidgetArea
, mPostDock
);
115 QVBoxLayout
*center_box
= new QVBoxLayout
;
116 center_box
->setContentsMargins(0,0,0,0);
117 center_box
->setSpacing(0);
118 center_box
->addWidget(mEditors
);
119 center_box
->addWidget(mToolBox
);
121 QWidget
*central
= new QWidget
;
122 central
->setLayout(center_box
);
123 setCentralWidget(central
);
125 // Session management
126 connect(main
->sessionManager(), SIGNAL(saveSessionRequest(Session
*)),
127 this, SLOT(saveSession(Session
*)));
128 connect(main
->sessionManager(), SIGNAL(switchSessionRequest(Session
*)),
129 this, SLOT(switchSession(Session
*)));
130 connect(main
->sessionManager(), SIGNAL(currentSessionNameChanged()),
131 this, SLOT(updateWindowTitle()));
132 // A system for easy evaluation of pre-defined code:
133 connect(&mCodeEvalMapper
, SIGNAL(mapped(QString
)),
134 this, SIGNAL(evaluateCode(QString
)));
135 connect(this, SIGNAL(evaluateCode(QString
,bool)),
136 main
->scProcess(), SLOT(evaluateCode(QString
,bool)));
137 // Interpreter: post output
138 connect(main
->scProcess(), SIGNAL( scPost(QString
) ),
139 mPostDock
->mPostWindow
, SLOT( post(QString
) ) );
140 // Interpreter: monitor running state
141 connect(main
->scProcess(), SIGNAL( stateChanged(QProcess::ProcessState
) ),
142 this, SLOT( onInterpreterStateChanged(QProcess::ProcessState
) ) );
143 // Interpreter: forward status messages
144 connect(main
->scProcess(), SIGNAL(statusMessage(const QString
&)),
145 this, SLOT(showMessage(const QString
&)));
147 // Document list interaction
148 connect(mDocListDock
->list(), SIGNAL(clicked(Document
*)),
149 mEditors
, SLOT(setCurrent(Document
*)));
150 connect(mEditors
, SIGNAL(currentDocumentChanged(Document
*)),
151 mDocListDock
->list(), SLOT(setCurrent(Document
*)),
152 Qt::QueuedConnection
);
154 // Update actions on document change
155 connect(mEditors
, SIGNAL(currentDocumentChanged(Document
*)),
156 this, SLOT(onCurrentDocumentChanged(Document
*)));
157 // Document management
158 DocumentManager
*docMng
= main
->documentManager();
159 connect(docMng
, SIGNAL(changedExternally(Document
*)),
160 this, SLOT(onDocumentChangedExternally(Document
*)));
161 connect(docMng
, SIGNAL(recentsChanged()),
162 this, SLOT(updateRecentDocsMenu()));
164 connect(main
, SIGNAL(applySettingsRequest(Settings::Manager
*)),
165 this, SLOT(applySettings(Settings::Manager
*)));
168 connect(mToolBox
->closeButton(), SIGNAL(clicked()), this, SLOT(hideToolBox()));
170 connect(main
->scResponder(), SIGNAL(serverRunningChanged(bool,QString
,int)), this, SLOT(onServerRunningChanged(bool,QString
,int)));
171 connect(main
->scServer(), SIGNAL(updateServerStatus(int,int,int,int,float,float)), this, SLOT(onServerStatusReply(int,int,int,int,float,float)));
176 // Must be called after createAtions(), because it accesses an action:
177 onServerRunningChanged(false, "", 0);
179 mServerStatus
->addAction( action(ToggleServerRunning
) );
180 mServerStatus
->setContextMenuPolicy(Qt::ActionsContextMenu
);
182 // Initialize recent documents menu
183 updateRecentDocsMenu();
186 icon
.addFile(":/icons/sc-cube-128");
187 icon
.addFile(":/icons/sc-cube-48");
188 icon
.addFile(":/icons/sc-cube-32");
189 icon
.addFile(":/icons/sc-cube-16");
190 QApplication::setWindowIcon(icon
);
195 void MainWindow::createActions()
197 Settings::Manager
*settings
= mMain
->settings();
198 settings
->beginGroup("IDE/shortcuts");
203 mActions
[Quit
] = act
= new QAction(
204 QIcon::fromTheme("application-exit"), tr("&Quit..."), this);
205 act
->setShortcut(tr("Ctrl+Q", "Quit application"));
206 act
->setStatusTip(tr("Quit SuperCollider IDE"));
207 QObject::connect( act
, SIGNAL(triggered()), this, SLOT(onQuit()) );
209 mActions
[DocNew
] = act
= new QAction(
210 QIcon::fromTheme("document-new"), tr("&New"), this);
211 act
->setShortcut(tr("Ctrl+N", "New document"));
212 act
->setStatusTip(tr("Create a new document"));
213 connect(act
, SIGNAL(triggered()), this, SLOT(newDocument()));
215 mActions
[DocOpen
] = act
= new QAction(
216 QIcon::fromTheme("document-open"), tr("&Open..."), this);
217 act
->setShortcut(tr("Ctrl+O", "Open document"));
218 act
->setStatusTip(tr("Open an existing file"));
219 connect(act
, SIGNAL(triggered()), this, SLOT(openDocument()));
221 mActions
[DocSave
] = act
= new QAction(
222 QIcon::fromTheme("document-save"), tr("&Save"), this);
223 act
->setShortcut(tr("Ctrl+S", "Save document"));
224 act
->setStatusTip(tr("Save the current document"));
225 connect(act
, SIGNAL(triggered()), this, SLOT(saveDocument()));
227 mActions
[DocSaveAs
] = act
= new QAction(
228 QIcon::fromTheme("document-save-as"), tr("Save &As..."), this);
229 act
->setShortcut(tr("Ctrl+Shift+S", "Save &As..."));
230 act
->setStatusTip(tr("Save the current document into a different file"));
231 connect(act
, SIGNAL(triggered()), this, SLOT(saveDocumentAs()));
233 mActions
[DocSaveAll
] = act
= new QAction(
234 QIcon::fromTheme("document-save"), tr("Save All..."), this);
235 act
->setShortcut(tr("Ctrl+Alt+S", "Save all documents"));
236 act
->setStatusTip(tr("Save all open documents"));
237 connect(act
, SIGNAL(triggered()), this, SLOT(saveAllDocuments()));
239 mActions
[DocClose
] = act
= new QAction(
240 QIcon::fromTheme("window-close"), tr("&Close"), this);
241 act
->setShortcut(tr("Ctrl+W", "Close document"));
242 act
->setStatusTip(tr("Close the current document"));
243 connect(act
, SIGNAL(triggered()), this, SLOT(closeDocument()));
245 mActions
[DocCloseAll
] = act
= new QAction(
246 QIcon::fromTheme("window-close"), tr("Close All..."), this);
247 act
->setShortcut(tr("Ctrl+Shift+W", "Close all documents"));
248 act
->setStatusTip(tr("Close all documents"));
249 connect(act
, SIGNAL(triggered()), this, SLOT(closeAllDocuments()));
251 mActions
[DocReload
] = act
= new QAction(
252 QIcon::fromTheme("view-refresh"), tr("&Reload"), this);
253 act
->setShortcut(tr("F5", "Reload document"));
254 act
->setStatusTip(tr("Reload the current document"));
255 connect(act
, SIGNAL(triggered()), this, SLOT(reloadDocument()));
257 mActions
[ClearRecentDocs
] = act
= new QAction(tr("Clear", "Clear recent documents"), this);
258 connect(act
, SIGNAL(triggered()),
259 Main::instance()->documentManager(), SLOT(clearRecents()));
262 mActions
[NewSession
] = act
= new QAction(
263 QIcon::fromTheme("document-new"), tr("&New Session"), this);
264 act
->setStatusTip(tr("Open a new session"));
265 connect(act
, SIGNAL(triggered()), this, SLOT(newSession()));
267 mActions
[SaveSessionAs
] = act
= new QAction(
268 QIcon::fromTheme("document-save-as"), tr("Save Session &As..."), this);
269 act
->setStatusTip(tr("Save the current session with a different name"));
270 connect(act
, SIGNAL(triggered()), this, SLOT(saveCurrentSessionAs()));
272 mActions
[ManageSessions
] = act
= new QAction(
273 tr("&Manage Sessions..."), this);
274 connect(act
, SIGNAL(triggered()), this, SLOT(openSessionsDialog()));
276 mActions
[OpenSessionSwitchDialog
] = act
= new QAction(
277 tr("&Switch Session..."), this);
278 connect(act
, SIGNAL(triggered()), this, SLOT(showSwitchSessionDialog()));
279 act
->setShortcut(tr("Ctrl+Shift+Q", "Switch Session"));
282 mActions
[Find
] = act
= new QAction(
283 QIcon::fromTheme("edit-find"), tr("&Find..."), this);
284 act
->setShortcut(tr("Ctrl+F", "Find"));
285 act
->setStatusTip(tr("Find text in document"));
286 connect(act
, SIGNAL(triggered()), this, SLOT(showFindTool()));
288 mActions
[Replace
] = act
= new QAction(
289 QIcon::fromTheme("edit-replace"), tr("&Replace..."), this);
290 act
->setShortcut(tr("Ctrl+R", "Replace"));
291 act
->setStatusTip(tr("Find and replace text in document"));
292 connect(act
, SIGNAL(triggered()), this, SLOT(showReplaceTool()));
295 mActions
[ShowCmdLine
] = act
= new QAction(tr("&Command Line"), this);
296 act
->setStatusTip(tr("Command line for quick code evaluation"));
297 act
->setShortcut(tr("Ctrl+E", "Show command line"));
298 connect(act
, SIGNAL(triggered()), this, SLOT(showCmdLine()));
300 mActions
[ShowGoToLineTool
] = act
= new QAction(tr("&Go To Line"), this);
301 act
->setStatusTip(tr("Tool to jump to a line by number"));
302 act
->setShortcut(tr("Ctrl+G", "Show go-to-line tool"));
303 connect(act
, SIGNAL(triggered()), this, SLOT(showGoToLineTool()));
305 mActions
[CloseToolBox
] = act
= new QAction(
306 QIcon::fromTheme("window-close"), tr("&Close Tool Panel"), this);
307 act
->setStatusTip(tr("Close any open tool panel"));
308 act
->setShortcut(tr("Esc", "Close tool box"));
309 connect(act
, SIGNAL(triggered()), this, SLOT(hideToolBox()));
311 mActions
[ShowFullScreen
] = act
= new QAction(tr("&Full Screen"), this);
312 act
->setCheckable(false);
313 act
->setShortcut(tr("Ctrl+Shift+F", "Show ScIDE in Full Screen"));
314 connect(act
, SIGNAL(triggered()), this, SLOT(toggleFullScreen()));
316 mActions
[ClearPostWindow
] = act
= new QAction(
317 QIcon::fromTheme("window-clearpostwindow"), tr("Clear Post Window"), this);
318 act
->setStatusTip(tr("Clear Post Window"));
319 act
->setShortcut(tr("Ctrl+Shift+C", "Clear Post Window"));
320 connect(act
, SIGNAL(triggered()), mPostDock
->mPostWindow
, SLOT(clear()));
322 mActions
[LookupDefinition
] = act
= new QAction(
323 QIcon::fromTheme("window-lookupdefinition"), tr("Lookup Definition"), this);
324 act
->setShortcut(tr("Ctrl+Shift+I", "Lookup Definition"));
325 connect(act
, SIGNAL(triggered()), this, SLOT(lookupDefinition()));
327 mActions
[LookupDocumentation
] = act
= new QAction(
328 QIcon::fromTheme("window-lookupDocumentation"), tr("Lookup Documentation"), this);
329 act
->setShortcut(tr("Ctrl+Shift+D", "Lookup Documentation"));
330 connect(act
, SIGNAL(triggered()), this, SLOT(lookupDocumentation()));
333 mActions
[OpenDefinition
] = act
= new QAction(tr("Open Class/Method Definition"), this);
334 act
->setShortcut(tr("Ctrl+I", "Open definition of selected class or method"));
335 connect(act
, SIGNAL(triggered(bool)), this, SLOT(openDefinition()));
337 mActions
[FindReferences
] = act
= new QAction(tr("Find References"), this);
338 act
->setShortcut(tr("Ctrl+U", "Find References"));
339 connect(act
, SIGNAL(triggered(bool)), this, SLOT(lookupReferences()));
342 mActions
[ShowSettings
] = act
= new QAction(tr("&Configure IDE..."), this);
343 act
->setStatusTip(tr("Show configuration dialog"));
344 connect(act
, SIGNAL(triggered()), this, SLOT(showSettings()));
348 mActions
[Help
] = act
= new QAction(
349 QIcon::fromTheme("system-help"), tr("Open Help Browser"), this);
350 act
->setStatusTip(tr("Open help."));
351 connect(act
, SIGNAL(triggered()), this, SLOT(openHelp()));
353 mActions
[HelpForSelection
] = act
= new QAction(
354 QIcon::fromTheme("system-help"), tr("&Help for Selection"), this);
355 act
->setShortcut(tr("Ctrl+D", "Help for selection"));
356 act
->setStatusTip(tr("Find help for selected text"));
357 connect(act
, SIGNAL(triggered()), this, SLOT(openDocumentation()));
360 mActions
[ToggleServerRunning
] = act
= new QAction(this);
361 connect(act
, SIGNAL(triggered()), this, SLOT(toggleServerRunning()));
363 settings
->endGroup(); // IDE/shortcuts;
365 // Add actions to settings
366 for (int i
= 0; i
< ActionCount
; ++i
)
367 settings
->addAction( mActions
[i
] );
370 void MainWindow::createMenus()
375 menu
= new QMenu(tr("&File"), this);
376 menu
->addAction( mActions
[DocNew
] );
377 menu
->addAction( mActions
[DocOpen
] );
378 mRecentDocsMenu
= menu
->addMenu(tr("Open Recent", "Open a recent document"));
379 connect(mRecentDocsMenu
, SIGNAL(triggered(QAction
*)),
380 this, SLOT(onRecentDocAction(QAction
*)));
381 menu
->addAction( mActions
[DocSave
] );
382 menu
->addAction( mActions
[DocSaveAs
] );
383 menu
->addAction( mActions
[DocSaveAll
] );
384 menu
->addSeparator();
385 menu
->addAction( mActions
[DocReload
] );
386 menu
->addSeparator();
387 menu
->addAction( mActions
[DocClose
] );
388 menu
->addAction( mActions
[DocCloseAll
] );
389 menu
->addSeparator();
390 menu
->addAction( mActions
[Quit
] );
392 menuBar()->addMenu(menu
);
394 menu
= new QMenu(tr("&Session"), this);
395 menu
->addAction( mActions
[NewSession
] );
396 menu
->addAction( mActions
[SaveSessionAs
] );
397 submenu
= menu
->addMenu(tr("&Open Session"));
398 connect(submenu
, SIGNAL(triggered(QAction
*)),
399 this, SLOT(onOpenSessionAction(QAction
*)));
400 mSessionsMenu
= submenu
;
401 updateSessionsMenu();
402 menu
->addSeparator();
403 menu
->addAction( mActions
[ManageSessions
] );
404 menu
->addAction( mActions
[OpenSessionSwitchDialog
] );
406 menuBar()->addMenu(menu
);
408 menu
= new QMenu(tr("&Edit"), this);
409 menu
->addAction( mEditors
->action(MultiEditor::Undo
) );
410 menu
->addAction( mEditors
->action(MultiEditor::Redo
) );
411 menu
->addSeparator();
412 menu
->addAction( mEditors
->action(MultiEditor::Cut
) );
413 menu
->addAction( mEditors
->action(MultiEditor::Copy
) );
414 menu
->addAction( mEditors
->action(MultiEditor::Paste
) );
415 menu
->addSeparator();
416 menu
->addAction( mActions
[Find
] );
417 menu
->addAction( mActions
[Replace
] );
418 menu
->addSeparator();
419 menu
->addAction( mEditors
->action(MultiEditor::IndentLineOrRegion
) );
420 menu
->addAction( mEditors
->action(MultiEditor::ToggleComment
) );
421 menu
->addAction( mEditors
->action(MultiEditor::ToggleOverwriteMode
) );
422 menu
->addAction( mEditors
->action(MultiEditor::SelectRegion
) );
423 menu
->addSeparator();
424 menu
->addAction( mActions
[OpenDefinition
] );
425 menu
->addAction( mActions
[FindReferences
] );
427 menuBar()->addMenu(menu
);
429 menu
= new QMenu(tr("&View"), this);
430 submenu
= new QMenu(tr("&Docks"), this);
431 submenu
->addAction( mPostDock
->toggleViewAction() );
432 submenu
->addAction( mDocListDock
->toggleViewAction() );
433 menu
->addMenu(submenu
);
434 menu
->addSeparator();
435 submenu
= menu
->addMenu(tr("&Tool Panels"));
436 submenu
->addAction( mActions
[Find
] );
437 submenu
->addAction( mActions
[Replace
] );
438 submenu
->addAction( mActions
[ShowCmdLine
] );
439 submenu
->addAction( mActions
[ShowGoToLineTool
] );
440 submenu
->addSeparator();
441 submenu
->addAction( mActions
[CloseToolBox
] );
442 menu
->addSeparator();
443 menu
->addAction( mEditors
->action(MultiEditor::EnlargeFont
) );
444 menu
->addAction( mEditors
->action(MultiEditor::ShrinkFont
) );
445 menu
->addAction( mEditors
->action(MultiEditor::ResetFontSize
) );
446 menu
->addSeparator();
447 menu
->addAction( mEditors
->action(MultiEditor::ShowWhitespace
) );
448 menu
->addSeparator();
449 menu
->addAction( mEditors
->action(MultiEditor::NextDocument
) );
450 menu
->addAction( mEditors
->action(MultiEditor::PreviousDocument
) );
451 menu
->addSeparator();
452 menu
->addAction( mEditors
->action(MultiEditor::SplitHorizontally
) );
453 menu
->addAction( mEditors
->action(MultiEditor::SplitVertically
) );
454 menu
->addAction( mEditors
->action(MultiEditor::RemoveCurrentSplit
) );
455 menu
->addAction( mEditors
->action(MultiEditor::RemoveAllSplits
) );
456 menu
->addSeparator();
457 menu
->addAction( mActions
[ClearPostWindow
] );
458 menu
->addSeparator();
459 menu
->addAction( mActions
[ShowFullScreen
] );
460 menu
->addAction( mActions
[LookupDefinition
] );
461 menu
->addAction( mActions
[LookupDocumentation
] );
463 menuBar()->addMenu(menu
);
465 menu
= new QMenu(tr("&Language"), this);
466 menu
->addAction( mMain
->scProcess()->action(SCProcess::StartSCLang
) );
467 menu
->addAction( mMain
->scProcess()->action(SCProcess::StopSCLang
) );
468 menu
->addAction( mMain
->scProcess()->action(SCProcess::RestartSCLang
) );
469 menu
->addAction( mMain
->scProcess()->action(SCProcess::RecompileClassLibrary
) );
470 menu
->addSeparator();
471 menu
->addAction( mEditors
->action(MultiEditor::EvaluateCurrentDocument
) );
472 menu
->addAction( mEditors
->action(MultiEditor::EvaluateRegion
) );
473 menu
->addAction( mEditors
->action(MultiEditor::EvaluateLine
) );
474 menu
->addSeparator();
475 menu
->addAction( mMain
->scProcess()->action(ScIDE::SCProcess::RunMain
) );
476 menu
->addAction( mMain
->scProcess()->action(ScIDE::SCProcess::StopMain
) );
478 menuBar()->addMenu(menu
);
480 menu
= new QMenu(tr("&Settings"), this);
481 menu
->addAction( mActions
[ShowSettings
] );
483 menuBar()->addMenu(menu
);
485 menu
= new QMenu(tr("&Help"), this);
486 menu
->addAction( mActions
[Help
] );
487 menu
->addAction( mActions
[HelpForSelection
] );
489 menuBar()->addMenu(menu
);
492 void MainWindow::saveWindowState()
494 Settings::Manager
*settings
= Main::settings();
495 settings
->beginGroup("IDE/mainWindow");
496 settings
->setValue("geometry", this->saveGeometry().toBase64());
497 settings
->setValue("state", this->saveState().toBase64());
498 settings
->endGroup();
501 void MainWindow::restoreWindowState()
503 Settings::Manager
*settings
= Main::settings();
504 settings
->beginGroup("IDE/mainWindow");
506 QByteArray geom
= QByteArray::fromBase64( settings
->value("geometry").value
<QByteArray
>() );
508 restoreGeometry(geom
);
510 setWindowState( windowState() & ~Qt::WindowFullScreen
| Qt::WindowMaximized
);
512 QByteArray state
= QByteArray::fromBase64( settings
->value("state").value
<QByteArray
>() );
513 if (!state
.isEmpty())
516 settings
->endGroup();
519 void MainWindow::newSession()
521 if (promptSaveDocs())
522 mMain
->sessionManager()->newSession();
525 void MainWindow::saveCurrentSessionAs()
527 QString name
= QInputDialog::getText( this,
528 "Save Current Session",
529 "Enter a name for the session:" );
531 if (name
.isEmpty()) return;
533 mMain
->sessionManager()->saveSessionAs(name
);
535 updateSessionsMenu();
538 void MainWindow::onOpenSessionAction( QAction
* action
)
540 openSession(action
->text());
543 void MainWindow::switchSession( Session
*session
)
546 session
->beginGroup("mainWindow");
547 QByteArray geom
= QByteArray::fromBase64( session
->value("geometry").value
<QByteArray
>() );
548 QByteArray state
= QByteArray::fromBase64( session
->value("state").value
<QByteArray
>() );
551 // Workaround for Qt bug 4397:
552 setWindowState(Qt::WindowNoState
);
555 restoreGeometry(geom
);
556 if (!state
.isEmpty())
559 updateClockWidget(isFullScreen());
562 mEditors
->switchSession(session
);
567 void MainWindow::saveSession( Session
*session
)
569 session
->beginGroup("mainWindow");
570 session
->setValue("geometry", this->saveGeometry().toBase64());
571 session
->setValue("state", this->saveState().toBase64());
574 mEditors
->saveSession(session
);
577 void MainWindow::openSessionsDialog()
579 QPointer
<MainWindow
> mainwin(this);
580 SessionsDialog
dialog(mMain
->sessionManager(), this);
583 mainwin
->updateSessionsMenu();
586 QAction
*MainWindow::action( ActionRole role
)
588 Q_ASSERT( role
< ActionCount
);
589 return mActions
[role
];
592 bool MainWindow::quit()
594 if (!promptSaveDocs())
604 void MainWindow::onQuit()
609 void MainWindow::onCurrentDocumentChanged( Document
* doc
)
613 mActions
[DocSave
]->setEnabled(doc
);
614 mActions
[DocSaveAs
]->setEnabled(doc
);
615 mActions
[DocClose
]->setEnabled(doc
);
617 CodeEditor
*editor
= mEditors
->currentEditor();
618 mFindReplaceTool
->setEditor( editor
);
619 mGoToLineTool
->setEditor( editor
);
622 void MainWindow::onDocumentChangedExternally( Document
*doc
)
627 mDocDialog
= new DocumentsDialog(DocumentsDialog::ExternalChange
, this);
628 mDocDialog
->addDocument(doc
);
629 connect(mDocDialog
, SIGNAL(finished(int)), this, SLOT(onDocDialogFinished()));
633 void MainWindow::onDocDialogFinished()
635 mDocDialog
->deleteLater();
639 void MainWindow::updateRecentDocsMenu()
641 mRecentDocsMenu
->clear();
643 const QStringList
&recent
= mMain
->documentManager()->recents();
645 foreach( const QString
& path
, recent
)
646 mRecentDocsMenu
->addAction(path
);
648 if (!recent
.isEmpty()) {
649 mRecentDocsMenu
->addSeparator();
650 mRecentDocsMenu
->addAction(mActions
[ClearRecentDocs
]);
654 void MainWindow::onRecentDocAction( QAction
*action
)
656 mMain
->documentManager()->open(action
->text());
659 void MainWindow::onInterpreterStateChanged( QProcess::ProcessState state
)
665 case QProcess::NotRunning
:
669 case QProcess::Starting
:
671 color
= QColor(255,255,0);
673 case QProcess::Running
:
679 mLangStatus
->setText(text
);
680 mLangStatus
->setTextColor(color
);
684 void MainWindow::onServerStatusReply(int ugens
, int synths
, int groups
, int synthDefs
, float avgCPU
, float peakCPU
)
686 QString statusString
=
687 QString("%1% %2% %3u %4s %5g %6d")
688 .arg(avgCPU
, 5, 'f', 2)
689 .arg(peakCPU
, 5, 'f', 2)
695 mServerStatus
->setText(statusString
);
698 void MainWindow::onServerRunningChanged(bool running
, const QString
&, int)
700 QAction
*serverStatusAction
= mActions
[ToggleServerRunning
];
702 mServerStatus
->setTextColor( running
? Qt::green
: Qt::white
);
704 onServerStatusReply(0, 0, 0, 0, 0, 0);
706 serverStatusAction
->setText( tr("&Boot Server") );
707 serverStatusAction
->setStatusTip(tr("Boot sound synthesis server"));
709 serverStatusAction
->setText( tr("&Quit Server") );
710 serverStatusAction
->setStatusTip(tr("Quit sound synthesis server"));
714 void MainWindow::closeEvent(QCloseEvent
*event
)
716 if(!quit()) event
->ignore();
719 bool MainWindow::close( Document
*doc
)
721 if (doc
->textDocument()->isModified())
723 QMessageBox::StandardButton ret
;
724 ret
= QMessageBox::warning(
726 tr("SuperCollider IDE"),
727 tr("There are unsaved changes in document '%1'.\n\n"
728 "Do you want to save it?").arg(doc
->title()),
729 QMessageBox::Save
| QMessageBox::Discard
| QMessageBox::Cancel
,
730 QMessageBox::Save
// the default
734 case QMessageBox::Cancel
:
736 case QMessageBox::Save
:
737 if (!MainWindow::save(doc
))
743 Main::instance()->documentManager()->close(doc
);
747 bool MainWindow::reload( Document
*doc
)
749 if (doc
->filePath().isEmpty())
752 if (doc
->textDocument()->isModified())
754 QMessageBox::StandardButton ret
;
755 ret
= QMessageBox::warning(
757 tr("SuperCollider IDE"),
758 tr("There are unsaved changes in document '%1'.\n\n"
759 "Do you want to reload it?").arg(doc
->title()),
760 QMessageBox::Yes
| QMessageBox::No
,
761 QMessageBox::No
// the default
763 if (ret
== QMessageBox::No
)
767 return Main::instance()->documentManager()->reload(doc
);
770 bool MainWindow::save( Document
*doc
, bool forceChoose
)
772 DocumentManager
*mng
= Main::instance()->documentManager();
773 if (forceChoose
|| doc
->filePath().isEmpty()) {
774 QFileDialog
dialog(mInstance
);
775 dialog
.setAcceptMode( QFileDialog::AcceptSave
);
777 QStringList filters
= (QStringList()
778 << "SuperCollider Document(*.scd)"
779 << "SuperCollider Class file(*.sc)"
783 dialog
.setNameFilters(filters
);
784 dialog
.setDefaultSuffix("scd");
786 if (dialog
.exec() == QDialog::Accepted
)
787 return mng
->saveAs(doc
, dialog
.selectedFiles()[0]);
791 return mng
->save(doc
);
794 void MainWindow::newDocument()
796 mMain
->documentManager()->create();
799 void MainWindow::openDocument()
801 QFileDialog
dialog (this, Qt::Dialog
);
802 dialog
.setModal(true);
803 dialog
.setWindowModality(Qt::ApplicationModal
);
805 dialog
.setFileMode( QFileDialog::ExistingFiles
);
807 CodeEditor
* currentEditor
= mEditors
->currentEditor();
809 Document
* currentDocument
= currentEditor
->document();
810 QFileInfo
filePath (currentDocument
->filePath());
811 dialog
.setDirectory(filePath
.dir());
817 << "SuperCollider(*.scd *.sc)"
818 << "SCDoc(*.schelp)";
819 dialog
.setNameFilters(filters
);
823 QStringList filenames
= dialog
.selectedFiles();
824 foreach(QString filename
, filenames
)
825 mMain
->documentManager()->open(filename
);
829 void MainWindow::saveDocument()
831 CodeEditor
*editor
= mEditors
->currentEditor();
834 Document
*doc
= editor
->document();
837 MainWindow::save(doc
);
840 void MainWindow::saveDocumentAs()
842 CodeEditor
*editor
= mEditors
->currentEditor();
845 Document
*doc
= editor
->document();
848 MainWindow::save(doc
, true);
851 void MainWindow::saveAllDocuments()
853 QList
<Document
*> docs
= mMain
->documentManager()->documents();
854 foreach (Document
*doc
, docs
)
855 if (!MainWindow::save(doc
))
859 void MainWindow::reloadDocument()
861 CodeEditor
*editor
= mEditors
->currentEditor();
864 Q_ASSERT(editor
->document());
865 MainWindow::reload(editor
->document());
868 void MainWindow::closeDocument()
870 CodeEditor
*editor
= mEditors
->currentEditor();
873 Q_ASSERT(editor
->document());
874 MainWindow::close( editor
->document() );
877 void MainWindow::closeAllDocuments()
879 if (promptSaveDocs()) {
880 QList
<Document
*> docs
= mMain
->documentManager()->documents();
881 foreach (Document
*doc
, docs
)
882 mMain
->documentManager()->close(doc
);
886 bool MainWindow::promptSaveDocs()
888 QList
<Document
*> docs
= mMain
->documentManager()->documents();
889 QList
<Document
*> unsavedDocs
;
890 foreach(Document
* doc
, docs
)
891 if(doc
->textDocument()->isModified())
892 unsavedDocs
.append(doc
);
894 if (unsavedDocs
.count())
896 DocumentsDialog
dialog(unsavedDocs
, DocumentsDialog::Quit
, this);
905 void MainWindow::updateWindowTitle()
907 Session
*session
= mMain
->sessionManager()->currentSession();
908 CodeEditor
*editor
= mEditors
->currentEditor();
909 Document
*doc
= editor
? editor
->document() : 0;
914 title
.append(session
->name());
915 if (doc
) title
.append(": ");
919 if (!doc
->filePath().isEmpty()) {
920 QFileInfo info
= QFileInfo(doc
->filePath());
921 QString pathString
= info
.dir().path();
923 QString homePath
= QDir::homePath();
924 if (pathString
.startsWith(homePath
))
925 pathString
.replace(0, homePath
.size(), QString("~"));
927 QString titleString
= QString("%1 (%2)").arg(info
.fileName(), pathString
);
929 title
.append( titleString
);
931 title
.append( "Untitled" );
934 if (!title
.isEmpty())
937 title
.append("SuperCollider IDE");
939 setWindowTitle(title
);
942 void MainWindow::toggleFullScreen()
944 if (isFullScreen()) {
945 setWindowState(windowState() & ~Qt::WindowFullScreen
);
947 updateClockWidget(false);
949 setWindowState(windowState() | Qt::WindowFullScreen
);
951 updateClockWidget(true);
955 void MainWindow::updateClockWidget(bool isFullScreen
)
963 if (mClockLabel
== NULL
) {
964 mClockLabel
= new StatusClockLabel(this);
965 statusBar()->insertWidget(0, mClockLabel
);
970 void MainWindow::openSession(const QString
&sessionName
)
972 if (promptSaveDocs())
973 mMain
->sessionManager()->openSession( sessionName
);
976 void MainWindow::openDefinition()
978 QWidget
* focussedWidget
= QApplication::focusWidget();
980 int indexOfMethod
= focussedWidget
->metaObject()->indexOfMethod("openDefinition()");
981 if (indexOfMethod
!= -1)
982 QMetaObject::invokeMethod( focussedWidget
, "openDefinition", Qt::DirectConnection
);
985 void MainWindow::lookupDefinition()
987 LookupDialog
dialog(mEditors
);
991 void MainWindow::lookupDocumentation()
993 PopupTextInput
* dialog
= new PopupTextInput(tr("Lookup Documentation For"), this);
995 bool success
= dialog
->exec();
997 Main::openDocumentation(dialog
->textValue());
1002 void MainWindow::lookupReferences()
1004 QWidget
* focussedWidget
= QApplication::focusWidget();
1006 int indexOfMethod
= focussedWidget
->metaObject()->indexOfMethod("lookupReferences()");
1007 if (indexOfMethod
!= -1)
1008 QMetaObject::invokeMethod( focussedWidget
, "lookupReferences", Qt::DirectConnection
);
1012 void MainWindow::showMessage( QString
const & string
)
1014 mStatusBar
->showMessage(string
, 3000);
1017 void MainWindow::applySettings( Settings::Manager
* settings
)
1019 mEditors
->applySettings(settings
);
1020 mPostDock
->mPostWindow
->applySettings(settings
);
1021 mCmdLine
->applySettings(settings
);
1025 void MainWindow::updateSessionsMenu()
1027 mSessionsMenu
->clear();
1028 QStringList sessions
= mMain
->sessionManager()->availableSessions();
1029 foreach (const QString
& session
, sessions
)
1030 mSessionsMenu
->addAction( session
);
1033 void MainWindow::showSwitchSessionDialog()
1035 SessionSwitchDialog
* dialog
= new SessionSwitchDialog(this);
1036 int result
= dialog
->exec();
1038 if (result
== QDialog::Accepted
)
1039 openSession(dialog
->activeElement());
1044 void MainWindow::showCmdLine()
1046 mToolBox
->setCurrentWidget( mCmdLine
);
1049 mCmdLine
->setFocus(Qt::OtherFocusReason
);
1052 void MainWindow::showGoToLineTool()
1054 CodeEditor
*editor
= mEditors
->currentEditor();
1055 mGoToLineTool
->setValue( editor
? editor
->textCursor().blockNumber() + 1 : 0 );
1057 mToolBox
->setCurrentWidget( mGoToLineTool
);
1060 mGoToLineTool
->setFocus();
1063 void MainWindow::showFindTool()
1065 mFindReplaceTool
->setMode( TextFindReplacePanel::Find
);
1066 mFindReplaceTool
->initiate();
1068 mToolBox
->setCurrentWidget( mFindReplaceTool
);
1071 mFindReplaceTool
->setFocus(Qt::OtherFocusReason
);
1074 void MainWindow::showReplaceTool()
1076 mFindReplaceTool
->setMode( TextFindReplacePanel::Replace
);
1077 mFindReplaceTool
->initiate();
1079 mToolBox
->setCurrentWidget( mFindReplaceTool
);
1082 mFindReplaceTool
->setFocus(Qt::OtherFocusReason
);
1085 void MainWindow::hideToolBox()
1088 CodeEditor
*editor
= mEditors
->currentEditor();
1090 // This slot is mapped to Escape, so also clear highlighting
1091 // whenever invoked:
1092 editor
->clearSearchHighlighting();
1093 if (!editor
->hasFocus())
1094 editor
->setFocus(Qt::OtherFocusReason
);
1098 void MainWindow::showSettings()
1100 Settings::Dialog
dialog(mMain
->settings());
1101 dialog
.resize(700,400);
1102 int result
= dialog
.exec();
1103 if( result
== QDialog::Accepted
)
1104 mMain
->applySettings();
1107 void MainWindow::openDocumentation()
1109 QWidget
* focussedWidget
= QApplication::focusWidget();
1111 bool documentationOpened
= false;
1113 int indexOfMethod
= focussedWidget
->metaObject()->indexOfMethod("openDocumentation()");
1114 if (indexOfMethod
!= -1)
1115 QMetaObject::invokeMethod( focussedWidget
, "openDocumentation", Qt::DirectConnection
,
1116 Q_RETURN_ARG(bool, documentationOpened
) );
1118 if (!documentationOpened
)
1122 void MainWindow::openHelp()
1124 QString code
= QString("Help.gui");
1125 Main::scProcess()->evaluateCode(code
, true);
1128 void MainWindow::toggleServerRunning()
1130 ScServer
*scServer
= Main::scServer();
1132 if (scServer
->isRunning())
1138 //////////////////////////// StatusLabel /////////////////////////////////
1140 StatusLabel::StatusLabel(QWidget
*parent
) : QLabel(parent
)
1142 setAutoFillBackground(true);
1144 setAlignment(Qt::AlignCenter
);
1145 setBackground(Qt::black
);
1146 setTextColor(Qt::white
);
1148 QFont
font("Monospace");
1149 font
.setStyleHint(QFont::Monospace
);
1154 void StatusLabel::setBackground(const QBrush
& brush
)
1156 QPalette
plt(palette());
1157 plt
.setBrush(QPalette::Window
, brush
);
1161 void StatusLabel::setTextColor(const QColor
& color
)
1163 QPalette
plt(palette());
1164 plt
.setColor(QPalette::WindowText
, color
);
1168 //////////////////////////// StatusClockLabel ////////////////////////////
1170 StatusClockLabel::StatusClockLabel(QWidget
* parent
):
1173 setTextColor(Qt::green
);
1174 mTimerId
= startTimer(1000);
1178 StatusClockLabel::~StatusClockLabel()
1180 killTimer(mTimerId
);
1183 void StatusClockLabel::timerEvent(QTimerEvent
*e
)
1185 if (e
->timerId() == mTimerId
)
1189 void StatusClockLabel::updateTime()
1191 setText(QTime::currentTime().toString());
1194 } // namespace ScIDE