1 /*
2 Copyright (C) 2008, 2009 Andres Cabrera
3 mantaraya36@gmail.com
4
5 This file is part of CsoundQt.
6
7 CsoundQt is free software; you can redistribute it
8 and/or modify it under the terms of the GNU Lesser General Public
9 License as published by the Free Software Foundation; either
10 version 2.1 of the License, or (at your option) any later version.
11
12 CsoundQt is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU Lesser General Public License for more details.
16
17 You should have received a copy of the GNU Lesser General Public
18 License along with Csound; if not, write to the Free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
20 02111-1307 USA
21 */
22
23 #include "configdialog.h"
24 #include "console.h"
25 #include "dockhelp.h"
26 #include "documentpage.h"
27 #include "highlighter.h"
28 #include "inspector.h"
29 #include "opentryparser.h"
30 #include "options.h"
31 #include "qutecsound.h"
32 #include "widgetpanel.h"
33 #include "utilitiesdialog.h"
34 #include "graphicwindow.h"
35 #include "keyboardshortcuts.h"
36 #include "liveeventframe.h"
37 #include "about.h"
38 #include "eventsheet.h"
39 #include "appwizard.h"
40 #include "midihandler.h"
41 #include "midilearndialog.h"
42 #include "livecodeeditor.h"
43 #include "csoundhtmlview.h"
44 #include <thread>
45
46
47 #ifdef Q_OS_WIN
48 #include <ole2.h> // for OleInitialize() FLTK bug workaround
49 #endif
50
51
52 #ifdef QCS_PYTHONQT
53 #include "pythonconsole.h"
54 #endif
55 #ifdef QCS_DEBUGGER
56 #include "debugpanel.h"
57 #endif
58
59 // One day remove these from here for nicer abstraction....
60 #include "csoundengine.h"
61 #include "documentview.h"
62 #include "widgetlayout.h"
63
64 #ifdef QCS_RTMIDI
65 #include "RtMidi.h"
66 #endif
67
68 #ifdef Q_OS_WIN32
69 static const QString SCRIPT_NAME = "csoundqt_run_script-XXXXXX.bat";
70 #else
71 static const QString SCRIPT_NAME = "csoundqt_run_script-XXXXXX.sh";
72 #endif
73
74 #define MAX_THREAD_COUNT 32 // to enable up to MAX_THREAD_COUNT documents/consoles have messageDispatchers
75
76 #define INSPECTOR_UPDATE_PERIOD_MS 2000
77
78
CsoundQt(QStringList fileNames)79 CsoundQt::CsoundQt(QStringList fileNames)
80 {
81 m_closing = false;
82 m_resetPrefs = false;
83 utilitiesDialog = NULL;
84 curCsdPage = -1;
85 configureTab = 0;
86 // initialDir = QDir::current().path();
87 initialDir = QCoreApplication::applicationDirPath();
88 setWindowTitle("CsoundQt[*]");
89 // resize(780,550);
90 m_fullScreenComponent = QString();
91 #ifdef QCS_USE_NEW_ICON
92 // setWindowIcon(QIcon(":/images/qtcs-alt.svg"));
93 setWindowIcon(QIcon(":/images/qtcs-alt.png"));
94 #else
95 setWindowIcon(QIcon(":/images/qtcs.png"));
96 #endif
97 //Does this take care of the decimal separator for different locales?
98 QLocale::setDefault(QLocale::system());
99 curPage = -1;
100 m_options = new Options(&m_configlists);
101
102 #ifdef Q_OS_MAC
103 // this->setUnifiedTitleAndToolBarOnMac(true);
104 // The unified toolbar has rendering problems if opengl is used, which happens
105 // when any QtQuick widget is in use - that is the case with the MIDI keyboard widgetu
106 #endif
107
108
109 // Create GUI panels
110
111 helpPanel = new DockHelp(this);
112 helpPanel->setAllowedAreas(Qt::RightDockWidgetArea |
113 Qt::BottomDockWidgetArea |
114 Qt::LeftDockWidgetArea);
115 helpPanel->setObjectName("helpPanel");
116
117 // QLabel *helpTitle = new QLabel("Help", helpPanel);
118 // helpTitle->setStyleSheet("qproperty-alignment: AlignCenter; padding: 3px; font-size: 9pt; ");
119 // helpPanel->setTitleBarWidget(helpTitle);
120
121 helpPanel->show();
122 addDockWidget(Qt::RightDockWidgetArea, helpPanel);
123
124 #ifdef Q_OS_WIN
125 // Call OleInitialize to enable clipboard together with FLTK libraries
126 HRESULT result = OleInitialize(NULL);
127 if (result) {
128 qDebug()<<"Problem with OleInitialization" << result;
129 }
130 #endif
131
132 widgetPanel = new WidgetPanel(this);
133 widgetPanel->setFocusPolicy(Qt::NoFocus);
134 widgetPanel->setAllowedAreas(Qt::RightDockWidgetArea |
135 Qt::BottomDockWidgetArea |
136 Qt::LeftDockWidgetArea);
137 widgetPanel->setObjectName("widgetPanel");
138 widgetPanel->show();
139 addDockWidget(Qt::RightDockWidgetArea, widgetPanel);
140 tabifyDockWidget(helpPanel, widgetPanel);
141
142 m_console = new DockConsole(this);
143 m_console->setObjectName("m_console");
144 m_console->setFeatures(QDockWidget::DockWidgetMovable |
145 QDockWidget::DockWidgetClosable);
146 QLabel *consoleTitle = new QLabel("Console", m_console);
147 consoleTitle->setStyleSheet("qproperty-alignment: AlignCenter; padding: 3px; font-size: 9pt; ");
148 m_console->setTitleBarWidget(consoleTitle);
149
150 // m_console->setAllowedAreas(Qt::RightDockWidgetArea | Qt::BottomDockWidgetArea);
151 // addDockWidget(Qt::BottomDockWidgetArea, m_console);
152 addDockWidget(Qt::RightDockWidgetArea, m_console);
153
154 m_inspector = new Inspector(this);
155 m_inspector->parseText(QString());
156 m_inspector->setObjectName("Inspector");
157 addDockWidget(Qt::LeftDockWidgetArea, m_inspector);
158 m_inspector->hide();
159
160 #ifdef QCS_DEBUGGER
161 m_debugPanel = new DebugPanel(this);
162 m_debugPanel->setObjectName("Debug Panel");
163 m_debugPanel->hide();
164 connect(m_debugPanel, SIGNAL(runSignal()), this, SLOT(runDebugger()));
165 connect(m_debugPanel, SIGNAL(pauseSignal()), this, SLOT(pauseDebugger()));
166 connect(m_debugPanel, SIGNAL(continueSignal()), this, SLOT(continueDebugger()));
167 connect(m_debugPanel, SIGNAL(addInstrumentBreakpoint(double, int)),
168 this, SLOT(addInstrumentBreakpoint(double, int)));
169 connect(m_debugPanel, SIGNAL(removeInstrumentBreakpoint(double)),
170 this, SLOT(removeInstrumentBreakpoint(double)));
171 connect(m_debugPanel, SIGNAL(addBreakpoint(int, int, int)),
172 this, SLOT(addBreakpoint(int, int, int)));
173 connect(m_debugPanel, SIGNAL(removeBreakpoint(int, int)),
174 this, SLOT(removeBreakpoint(int, int)));
175 addDockWidget(Qt::RightDockWidgetArea, m_debugPanel);
176 m_debugEngine = NULL;
177 #endif
178
179 #ifdef QCS_PYTHONQT
180 m_pythonConsole = new PythonConsole(this);
181 addDockWidget(Qt::LeftDockWidgetArea, m_pythonConsole);
182 m_pythonConsole->setObjectName("Python Console");
183 m_pythonConsole->show();
184 #endif
185
186 m_scratchPad = new QDockWidget(this);
187 addDockWidget(Qt::LeftDockWidgetArea, m_scratchPad);
188 m_scratchPad->setObjectName("Interactive Code Pad");
189 m_scratchPad->setWindowTitle(tr("Interactive Code Pad"));
190 m_scratchPad->hide();
191 connect(helpPanel, SIGNAL(openManualExample(QString)), this, SLOT(openManualExample(QString)));
192
193 QSettings settings("csound", "qutecsound");
194 settings.beginGroup("GUI");
195 m_options->theme = settings.value("theme", "breeze").toString();
196 if(settings.contains("windowState")) {
197 restoreState(settings.value("windowState").toByteArray());
198 }
199 settings.endGroup();
200
201 settings.beginGroup("Options");
202 settings.beginGroup("Editor");
203 // necessary to get it before htmlview is created
204 m_options->debugPort = settings.value("debugPort", 34711).toInt();
205 m_options->highlightingTheme = settings.value("higlightingTheme", "light").toString();
206 settings.endGroup();
207
208 m_server = new QLocalServer();
209 connect(m_server, SIGNAL(newConnection()), this, SLOT(onNewConnection()));
210
211
212 #if defined(QCS_QTHTML)
213 #ifdef USE_WEBENGINE // set the remote debugging port for chromium based web browser here
214 //TODO: change it when user changes
215 if (m_options->debugPort) {
216 qDebug()<<"Set port "<< m_options->debugPort << " for remote html debugging";
217 qputenv("QTWEBENGINE_REMOTE_DEBUGGING",
218 QString::number(m_options->debugPort).toLocal8Bit().data() );
219 }
220
221 #endif
222 csoundHtmlView = new CsoundHtmlView(this);
223 csoundHtmlView->setFocusPolicy(Qt::NoFocus);
224 csoundHtmlView->setAllowedAreas(Qt::RightDockWidgetArea |
225 Qt::BottomDockWidgetArea |
226 Qt::LeftDockWidgetArea);
227 csoundHtmlView->setObjectName("csoundHtmlView");
228 csoundHtmlView->setWindowTitle(tr("HTML View"));
229 csoundHtmlView->setOptions(m_options);
230 addDockWidget(Qt::LeftDockWidgetArea, csoundHtmlView);
231 csoundHtmlView->hide();
232 #endif
233
234 focusMapper = new QSignalMapper(this);
235 createActions(); // Must be before readSettings: this sets default shortcuts
236 createMenus();
237 // TODO: take care that the position is stored when toolbars or panels are
238 // moved/resized. maybe.
239 createStatusBar();
240 createToolBars();
241 readSettings();
242 this->setToolbarIconSize(m_options->toolbarIconSize);
243
244 // this section was above before, check that it does not create problems...
245 // Later: find a way to recreate Midi Handler, if API jack/alsa or similar is changed
246 midiHandler = new MidiHandler(m_options->rtMidiApi, this);
247 m_midiLearn = new MidiLearnDialog(this);
248 m_midiLearn->setModal(false);
249 midiHandler->setMidiLearner(m_midiLearn);
250
251 // Must be after readSettings() to save last state // was: isVisible()
252 // in some reason reported always false
253 bool widgetsVisible = !widgetPanel->isHidden();
254 // To avoid showing and reshowing panels during initial load
255 showWidgetsAct->setChecked(false);
256 // Hide until CsoundQt has finished loading
257 widgetPanel->hide();
258 // Must be after readSettings() to save last state
259 bool scratchPadVisible = !m_scratchPad->isHidden();
260 if (scratchPadVisible)
261 m_scratchPad->hide(); // Hide until CsoundQt has finished loading
262 documentTabs = new QTabWidget (this);
263 documentTabs->setTabsClosable(true);
264 connect(documentTabs, SIGNAL(currentChanged(int)), this, SLOT(changePage(int)));
265 // To force changing to clicked tab before closing
266 connect(documentTabs, SIGNAL(tabCloseRequested(int)),
267 documentTabs, SLOT(setCurrentIndex(int)));
268 connect(documentTabs, SIGNAL(tabCloseRequested(int)), closeTabAct, SLOT(trigger()));
269 setCentralWidget(documentTabs);
270 documentTabs->setDocumentMode(true);
271 modIcon.addFile(":/images/modIcon2.png", QSize(), QIcon::Normal);
272 modIcon.addFile(":/images/modIcon.png", QSize(), QIcon::Disabled);
273 documentTabs->setMinimumSize(QSize(500, 500));
274
275 // set shortcuts to change between tabs,Alt +<tab no>
276 // example from: https://stackoverflow.com/questions/10160232/qt-designer-shortcut-to-another-tab
277 // Setup a signal mapper to avoid creating custom slots for each tab
278 // it is possible to switch it out from Cinfigure->Editor
279 if (m_options->tabShortcutActive) {
280 QSignalMapper *mapper = new QSignalMapper(this);
281 // Setup the shortcut for tabs 1..10
282 for (int i=0; i<10; i++) {
283 int key = (i==9) ? 0 : i+1;
284 #ifdef Q_OS_MACOS
285 QShortcut *shortcut = new QShortcut(QKeySequence(Qt::META + (Qt::Key_0 + key)), this);
286 #else
287 QShortcut *shortcut = new QShortcut(QKeySequence(Qt::ALT + (Qt::Key_0 + key)), this);
288 #endif
289 connect(shortcut, SIGNAL(activated()), mapper, SLOT(map()));
290 mapper->setMapping(shortcut, i); // tab 0 -> Alt+1, tab 1 -> Alt + 2 etc tab 9 -> Alt + 0
291 }
292 // Wire the signal mapper to the tab widget index change slot
293 connect(mapper, SIGNAL(mapped(int)), documentTabs, SLOT(setCurrentIndex(int)));
294 #ifdef Q_OS_MACOS
295 QShortcut *tabLeft = new QShortcut(QKeySequence(Qt::META + Qt::Key_Left), this);
296 QShortcut *tabRight = new QShortcut(QKeySequence(Qt::META + Qt::Key_Right), this);
297 #else
298 QShortcut *tabLeft = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_Left), this);
299 QShortcut *tabRight = new QShortcut(QKeySequence(Qt::ALT + Qt::Key_Right), this);
300 #endif
301 connect(tabLeft, SIGNAL(activated()), this, SLOT(pageLeft()));
302 connect(tabRight, SIGNAL(activated()), this, SLOT(pageRight()));
303 }
304
305 fillFileMenu(); // Must be placed after readSettings to include recent Files
306 fillFavoriteMenu(); // Must be placed after readSettings to know directory
307 fillScriptsMenu(); // Must be placed after readSettings to know directory
308 m_opcodeTree = new OpEntryParser(":/opcodes.xml");
309 m_opcodeTree->setUdos(m_inspector->getUdosMap());
310 LiveCodeEditor *liveeditor = new LiveCodeEditor(m_scratchPad, m_opcodeTree);
311 liveeditor->setSizePolicy(QSizePolicy::Expanding,QSizePolicy::Expanding);
312 connect(liveeditor, SIGNAL(evaluate(QString)), this, SLOT(evaluate(QString)));
313 connect(liveeditor, SIGNAL(enableCsdMode(bool)),
314 scratchPadCsdModeAct, SLOT(setChecked(bool)));
315 // connect(scratchPadCsdModeAct, SIGNAL(toggled(bool)),
316 // liveeditor, SLOT(setCsdMode(bool)));
317 m_scratchPad->setWidget(liveeditor);
318 m_scratchPad->setFocusProxy(liveeditor->getDocumentView());
319 scratchPadCsdModeAct->setChecked(true);
320
321 if (documentPages.size() == 0) { // No files yet open. Open default
322 newFile();
323 }
324
325 // try to find directory for manual, if not set
326 QString docDir = QString(); //m_options->csdocdir;
327 QString index = docDir + QString("/index.html");
328 QStringList possibleDirectories;
329 #ifdef Q_OS_LINUX
330 possibleDirectories << "/usr/share/doc/csound-manual/html/"
331 << "/usr/share/doc/csound-doc/html/";
332 #endif
333 #ifdef Q_OS_FREEBSD
334 possibleDirectories << initialDir+"/../share/doc/csound-manual/html/" << initialDir+"/../share/doc/csound-doc/html/";
335 #endif
336 #ifdef Q_OS_WIN
337 QString programFilesPath = QDir::fromNativeSeparators(getenv("PROGRAMFILES"));
338 QString programFilesPathx86 = QDir::fromNativeSeparators(getenv("PROGRAMFILES(X86)"));
339 possibleDirectories << initialDir +"/doc/manual/" << programFilesPath + "/Csound6/doc/manual/" << programFilesPathx86 + "/Csound6/doc/manual/" << programFilesPath + "/Csound6_x64/doc/manual/";
340 #endif
341 #ifdef Q_OS_MACOS
342 possibleDirectories << initialDir + QString("/../Frameworks/CsoundLib64.framework/Resources/Manual/") << "/Library/Frameworks/CsoundLib64.framework/Resources/Manual/";
343 #endif
344 if (m_options->csdocdir.isEmpty() ||
345 !QFile::exists(m_options->csdocdir+"/index.html") ) {
346 foreach (QString dir, possibleDirectories) {
347 if (QFile::exists(dir+"/index.html")) {
348 docDir = dir;
349 qDebug()<<"Found manual in: "<<docDir;
350 break;
351 }
352 }
353 } else {
354 docDir = m_options->csdocdir;
355 }
356 helpPanel->docDir = docDir;
357 helpPanel->loadFile(docDir + "/index.html");
358
359 applySettings();
360 createQuickRefPdf();
361
362 #ifdef Q_OS_MACOS // workaround to set resotre window size for Mac. Does not work within readSettings()
363 QSettings settings2("csound", "qutecsound");
364 QSize size = settings2.value("GUI/size", QSize(800, 600)).toSize();
365 resize(size);
366 #endif
367
368 //openLogFile();
369
370 // FIXME is there still need for no atexit?
371 int init = csoundInitialize(0);
372 if (init < 0) {
373 qDebug("CsoundEngine::CsoundEngine() Error initializing Csound!\n"
374 "CsoundQt will probably crash if you try to run Csound.");
375 }
376 // To finish settling dock widgets and other stuff before messing with
377 // them (does it actually work?)
378 qApp->processEvents();
379
380 // This is a bad idea, breaks lots of subtle things, like background color
381 // on files loaded from command line
382 #ifndef Q_OS_MACOS // a workaround for showing close buttons on close NB! disable later
383 auto originalStyleSheet = qApp->styleSheet();
384 QFile file(":/appstyle-white.css");
385 file.open(QFile::ReadOnly);
386 QString styleSheet = QLatin1String(file.readAll());
387 originalStyleSheet += styleSheet;
388 qApp->setStyleSheet(originalStyleSheet);
389 #endif
390
391 // Open files passed in the command line. Here to make sure they are the active tab.
392 foreach (QString fileName, fileNames) {
393 if (QFile::exists(fileName)) {
394 qDebug() << "loading file " << fileName;
395 loadFile(fileName, m_options->autoPlay);
396 }
397 else {
398 qDebug() << "CsoundQt::CsoundQt could not open file:" << fileName;
399 }
400 }
401
402 m_closing = false;
403 updateInspector(); //Starts update inspector thread
404
405 // Starts updating things like a list of udos for the current page, etc.
406 updateCurrentPageTask();
407
408 showWidgetsAct->setChecked(widgetsVisible);
409 if (!m_options->widgetsIndependent) {
410 // FIXME: for some reason this produces a move event for widgetlayout with pos (0,0)
411 widgetPanel->setVisible(widgetsVisible);
412 }
413
414 if (scratchPadVisible) { // Reshow scratch panel if necessary
415 m_scratchPad->show();
416 }
417 // Initialize buttons to current state of panels
418 showConsoleAct->setChecked(!m_console->isHidden());
419 showHelpAct->setChecked(!helpPanel->isHidden());
420 showInspectorAct->setChecked(!m_inspector->isHidden());
421 #ifdef QCS_PYTHONQT
422 showPythonConsoleAct->setChecked(!m_pythonConsole->isHidden());
423 #endif
424 showScratchPadAct->setChecked(!m_scratchPad->isHidden());
425
426 //qDebug()<<"Max thread count: "<< QThreadPool::globalInstance()->maxThreadCount();
427 QThreadPool::globalInstance()->setMaxThreadCount(MAX_THREAD_COUNT);
428
429 // Open files saved from last session
430 if (!lastFiles.isEmpty()) {
431 foreach (QString lastFile, lastFiles) {
432 if (lastFile!="" && !lastFile.startsWith("untitled")) {
433 loadFile(lastFile);
434 }
435 }
436 }
437
438 // restore last index after opening the documents
439 if (lastTabIndex < documentPages.size() &&
440 documentTabs->currentIndex() != lastTabIndex) {
441 changePage(lastTabIndex);
442 documentTabs->setCurrentIndex(lastTabIndex);
443 }
444 else {
445 changePage(documentTabs->currentIndex());
446 }
447
448 /*
449 #ifdef Q_OS_LINUX
450 // ---- this is workaround for problem reported by Renè that on first run ival = 16.0/3
451 // gets rounded... Did not find the real reasound
452 // Csound must be started and stopped once, then it works:
453 int oldPage = documentTabs->currentIndex();
454 QString tmp1 = lastUsedDir;
455 QString tmp2 = lastFileDir;
456 makeNewPage(QDir::tempPath()+"/tmp.csd", QCS_DEFAULT_TEMPLATE);
457 save();
458 play(true, -1); // problem, if pulse/alsa in settings but jack has been started
459 QThread::msleep(100); // wait a tiny bit
460 stop();
461 deleteTab(curPage);
462 documentTabs->setCurrentIndex(oldPage);
463 lastUsedDir = tmp1;
464 lastFileDir = tmp2;
465 #endif
466 */
467 }
468
469
~CsoundQt()470 CsoundQt::~CsoundQt()
471 {
472 qDebug() << "CsoundQt::~CsoundQt()";
473 // This function is not called... see closeEvent()
474 }
475
utilitiesMessageCallback(CSOUND * csound,int,const char * fmt,va_list args)476 void CsoundQt::utilitiesMessageCallback(CSOUND *csound,
477 int /*attr*/,
478 const char *fmt,
479 va_list args)
480 {
481 DockConsole *console = (DockConsole *) csoundGetHostData(csound);
482 QString msg;
483 msg = msg.vsprintf(fmt, args);
484 // qDebug() << msg;
485 console->appendMessage(msg);
486 }
487
changePage(int index)488 void CsoundQt::changePage(int index)
489 {
490 // Previous page has already been destroyed here (if it was closed).
491 // Remember this is called when opening, closing or switching tabs (including loading).
492 // First thing to do is blank the HTML page to prevent misfired API calls.
493 if (index < 0) { // No tabs left
494 qDebug() << "CsoundQt::changePage index < 0";
495 return;
496 }
497 if (documentPages.size() > curPage
498 && documentPages.size() > 0
499 && documentPages[curPage]) {
500 #ifdef QCS_DEBUGGER
501 if (documentPages[curPage]->getEngine()->m_debugging) {
502 stop(); // TODO How to better handle this rather than forcing stop?
503 }
504 #endif
505 disconnect(showLiveEventsAct, 0,0,0);
506 disconnect(documentPages[curPage], SIGNAL(stopSignal()),0,0);
507 auto page = documentPages[curPage];
508 page->hideLiveEventPanels();
509 page->showLiveEventControl(false);
510 page->hideWidgets();
511 if (!m_options->widgetsIndependent) {
512 QRect panelGeometry = widgetPanel->geometry();
513 if (!widgetPanel->isFloating()) {
514 panelGeometry.setX(-1);
515 panelGeometry.setY(-1);
516 }
517 widgetPanel->takeWidgetLayout(panelGeometry);
518 } else {
519 page->setWidgetLayoutOuterGeometry(QRect());
520 }
521 }
522 curPage = index;
523 if (curPage >= 0 && curPage < documentPages.size() && documentPages[curPage] != NULL) {
524 auto page = documentPages[curPage];
525 setCurrentFile(page->getFileName());
526 connectActions();
527 page->showLiveEventControl(showLiveEventsAct->isChecked());
528 // documentPages[curPage]->passWidgetClipboard(m_widgetClipboard);
529 if (!m_options->widgetsIndependent) {
530 WidgetLayout *w = page->getWidgetLayout();
531 widgetPanel->addWidgetLayout(w);
532 setWidgetPanelGeometry();
533 } else {
534 WidgetLayout *w = page->getWidgetLayout();
535 w->adjustWidgetSize();
536 }
537 if (!page->getFileName().endsWith(".csd") && !page->getFileName().isEmpty()) {
538 widgetPanel->hide();
539 }
540 else {
541 if (!m_options->widgetsIndependent) {
542 page->showWidgets();
543 widgetPanel->setVisible(showWidgetsAct->isChecked());
544 }
545 else {
546 page->showWidgets(showWidgetsAct->isChecked());
547 }
548 }
549 m_console->setWidget(page->getConsole());
550 runAct->setChecked(page->isRunning());
551 recAct->setChecked(page->isRecording());
552 splitViewAct->setChecked(page->getViewMode() > 1);
553 if (page->getFileName().endsWith(".csd")) {
554 curCsdPage = curPage;
555 // force parsing
556 page->parseUdos(true);
557 }
558 }
559 #if defined(QCS_QTHTML)
560 if (!documentPages.isEmpty()) {
561 updateHtmlView();
562 }
563 #endif
564 m_inspectorNeedsUpdate = true;
565 }
566
pageLeft()567 void CsoundQt::pageLeft()
568 {
569 if (curPage >= 1) {
570 //changePage(curPage-1);
571 documentTabs->setCurrentIndex(curPage-1);
572
573 }
574 }
575
pageRight()576 void CsoundQt::pageRight()
577 {
578 if (curPage < documentPages.count()-1) {
579 //changePage(curPage+1);
580 documentTabs->setCurrentIndex(curPage+1);
581
582 }
583 }
584
setWidgetTooltipsVisible(bool visible)585 void CsoundQt::setWidgetTooltipsVisible(bool visible)
586 {
587 documentPages[curPage]->showWidgetTooltips(visible);
588 }
589
closeExtraPanels()590 void CsoundQt::closeExtraPanels()
591 {
592 if (m_console->isVisible()) {
593 m_console->hide();
594 showConsoleAct->setChecked(false);
595 } else if (helpPanel->isVisible()) {
596 helpPanel->hide();
597 showHelpAct->setChecked(false);
598 }
599 }
600
openExample()601 void CsoundQt::openExample()
602 {
603 QObject *sender = QObject::sender();
604 if (sender == 0)
605 return;
606 QAction *action = static_cast<QAction *>(sender);
607 loadFile(action->data().toString());
608 // saveAs();
609 }
610
openTemplate()611 void CsoundQt::openTemplate()
612 {
613 QObject *sender = QObject::sender();
614 if (sender == 0)
615 return;
616 QAction *action = static_cast<QAction *>(sender);
617
618 QString dir = lastUsedDir;
619 QString templateName = action->data().toString();
620 dir += templateName.mid(templateName.lastIndexOf("/") + 1);
621 QString fileName = QFileDialog::getSaveFileName(this, tr("Save Template As"), dir,
622 tr("Known Files (*.csd *.html);;Csound Files (*.csd);;Html files (*.html);;All Files (*)",
623 "Rename and save the template"));
624 if (!fileName.isEmpty()) {
625
626
627 if (QFile::exists(fileName))
628 {
629 QFile::remove(fileName);
630 }
631 bool result = QFile::copy(templateName, fileName); // copy or overwrite
632 if (!result) {
633 qDebug() << "Could not copy the template to " << fileName;
634 return;
635 }
636 loadFile(fileName);
637 } else {
638 qDebug() << "No file selected";
639 }
640
641 }
642
logMessage(QString msg)643 void CsoundQt::logMessage(QString msg)
644 {
645 if (logFile.isOpen()) {
646 logFile.write(msg.toLatin1());
647 }
648 }
649
statusBarMessage(QString message)650 void CsoundQt::statusBarMessage(QString message)
651 {
652 statusBar()->showMessage(message.replace("<br />", " "));
653 }
654
closeEvent(QCloseEvent * event)655 void CsoundQt::closeEvent(QCloseEvent *event)
656 {
657 qDebug() ;
658 m_closing = true;
659 // this->showNormal(); // Don't store full screen size in preferences
660 qApp->processEvents();
661 storeSettings();
662 #ifdef USE_QT_GT_53
663 if (!m_virtualKeyboardPointer.isNull() && m_virtualKeyboard->isVisible()) {
664 showVirtualKeyboard(false);
665 }
666 if (!m_tableEditorPointer.isNull() && m_tableEditor->isVisible()) {
667 showTableEditor(false);
668 }
669 #endif
670 // These two give faster shutdown times as the panels don't have to be
671 // called up as the tabs close
672 showWidgetsAct->setChecked(false);
673 showLiveEventsAct->setChecked(false);
674 // Using this block this causes HTML5 performance to leave a zombie,
675 // not using it causes a crash on exit.
676 while (!documentPages.isEmpty()) {
677 if (!closeTab(true)) { // Don't ask for closing app
678 event->ignore();
679 return;
680 }
681 }
682 foreach (QString tempFile, tempScriptFiles) {
683 QDir().remove(tempFile);
684 }
685 if (logFile.isOpen()) {
686 logFile.close();
687 }
688 showUtilities(false); // Close utilities dialog if open
689 delete helpPanel;
690 // delete closeTabButton;
691 delete m_options;
692 m_closing = true;
693 widgetPanel->close();
694 m_inspector->close();
695 m_console->close();
696 documentTabs->close();
697 m_console->close();
698 delete m_opcodeTree;
699 m_opcodeTree = nullptr;
700 close();
701 }
702
newFile()703 void CsoundQt::newFile()
704 {
705 if (loadFile(":/default.csd") < 0) {
706 return;
707 }
708 documentPages[curPage]->loadTextString(m_options->csdTemplate);
709 documentPages[curPage]->setFileName("");
710 setWindowModified(false);
711 documentTabs->setTabIcon(curPage, modIcon);
712 documentTabs->setTabText(curPage, "default.csd");
713 // documentPages[curPage]->setTabStopWidth(m_options->tabWidth);
714 connectActions();
715 }
716
open()717 void CsoundQt::open()
718 {
719 QStringList fileNames;
720 bool widgetsVisible = widgetPanel->isVisible();
721 if (widgetsVisible && widgetPanel->isFloating())
722 widgetPanel->hide(); // Necessary for Mac, as widget Panel covers open dialog
723 bool helpVisible = helpPanel->isVisible();
724 if (helpVisible && helpPanel->isFloating())
725 helpPanel->hide(); // Necessary for Mac, as widget Panel covers open dialog
726 bool inspectorVisible = m_inspector->isVisible();
727 if (inspectorVisible && m_inspector->isFloating())
728 m_inspector->hide(); // Necessary for Mac, as widget Panel covers open dialog
729 fileNames = QFileDialog::getOpenFileNames(this, tr("Open File"), lastUsedDir ,
730 tr("Known Files (*.csd *.orc *.sco *.py *.inc *.udo *.html);;Csound Files (*.csd *.orc *.sco *.inc *.udo *.CSD *.ORC *.SCO *.INC *.UDO);;Python Files (*.py);;HTML files (*.html);;All Files (*)",
731 "Be careful to respect spacing parenthesis and usage of punctuation"));
732 // if (widgetsVisible) {
733 // if (!m_options->widgetsIndependent) {
734 // // widgetPanel->show();
735 // }
736 // }
737 if (helpVisible)
738 helpPanel->show();
739 if (inspectorVisible)
740 m_inspector->show();
741 foreach (QString fileName, fileNames) {
742 if (!fileName.isEmpty()) {
743 loadFile(fileName, m_options->autoPlay);
744 }
745 }
746 }
747
reload()748 void CsoundQt::reload()
749 {
750 if (documentPages[curPage]->isModified()) {
751 QString fileName = documentPages[curPage]->getFileName();
752 deleteTab();
753 loadFile(fileName);
754 // auto doc = documentPages[curPage];
755
756 } else {
757 QMessageBox::information(nullptr, "Reload", "File was not modified");
758 }
759 }
760
openFromAction()761 void CsoundQt::openFromAction()
762 {
763 QString fileName = static_cast<QAction *>(sender())->data().toString();
764 openFromAction(fileName);
765 }
766
openFromAction(QString fileName)767 void CsoundQt::openFromAction(QString fileName)
768 {
769 if (!fileName.isEmpty()) {
770 if ( (fileName.endsWith(".sco") || fileName.endsWith(".orc"))
771 && m_options->autoJoin) {
772
773 }
774 else {
775 loadCompanionFile(fileName);
776 loadFile(fileName);
777 }
778 }
779 }
780
runScriptFromAction()781 void CsoundQt::runScriptFromAction()
782 {
783 QString fileName = static_cast<QAction *>(sender())->data().toString();
784 runScript(fileName);
785 }
786
runScript(QString fileName)787 void CsoundQt::runScript(QString fileName)
788 {
789 if (!fileName.isEmpty()) {
790 #ifdef QCS_PYTHONQT
791 m_pythonConsole->runScript(fileName);
792 #endif
793 }
794 }
795
createCodeGraph()796 void CsoundQt::createCodeGraph()
797 {
798 QString command = m_options->dot + " -V";
799 #ifdef Q_OS_WIN32
800 // add quotes surrounding dot command if it has spaces in it
801 if (m_options->dot.contains(" "))
802 command.replace(m_options->dot, "\"" + m_options->dot + "\"");
803 // replace linux/mac style directory separators with windows style separators
804 command.replace("/", "\\");
805 #endif
806
807 int ret = system(command.toLatin1());
808 if (ret != 0) {
809 QMessageBox::warning(this, tr("CsoundQt"),
810 tr("Dot executable not found.\n"
811 "Please install graphviz from\n"
812 "www.graphviz.org"));
813 return;
814 }
815 QString dotText = documentPages[curPage]->getDotText();
816 if (dotText.isEmpty()) {
817 qDebug() << "Empty dot text.";
818 return;
819 }
820 qDebug() << dotText;
821 QTemporaryFile file(QDir::tempPath() + QDir::separator() + "CsoundQt-GraphXXXXXX.dot");
822 QTemporaryFile pngFile(QDir::tempPath() + QDir::separator() + "CsoundQt-GraphXXXXXX.png");
823 if (!file.open() || !pngFile.open()) {
824 QMessageBox::warning(this, tr("CsoundQt"),
825 tr("Cannot create temp dot/png file."));
826 return;
827 }
828
829 QTextStream out(&file);
830 out << dotText;
831 file.close();
832 file.open();
833
834 command = "\"" + m_options->dot + "\"" + " -Tpng -o \"" + pngFile.fileName() + "\" \"" + file.fileName() + "\"";
835
836 #ifdef Q_OS_WIN32
837 // remove quotes surrounding dot command if it doesn't have spaces in it
838 if (!m_options->dot.contains(" "))
839 command.replace("\"" + m_options->dot + "\"", m_options->dot);
840 // replace linux/mac style directory separators with windows style separators
841 command.replace("/", "\\");
842 command.prepend("\"");
843 command.append("\"");
844 #endif
845 // qDebug() << command;
846 ret = system(command.toLatin1());
847 if (ret != 0) {
848 qDebug() << "CsoundQt::createCodeGraph() Error running dot";
849 }
850 m_graphic = new GraphicWindow(this);
851 m_graphic->show();
852 m_graphic->openPng(pngFile.fileName());
853 connect(m_graphic, SIGNAL(destroyed()), this, SLOT(closeGraph()));
854 }
855
closeGraph()856 void CsoundQt::closeGraph()
857 {
858 qDebug("CsoundQt::closeGraph()");
859 }
860
save()861 bool CsoundQt::save()
862 {
863 QString fileName = documentPages[curPage]->getFileName();
864 if (fileName.isEmpty() || fileName.startsWith(":/examples/", Qt::CaseInsensitive)) {
865 return saveAs();
866 }
867 else if (documentPages[curPage]->readOnly){
868 if (saveAs()) {
869 documentPages[curPage]->readOnly = false;
870 return true;
871 }
872 else {
873 return false;
874 }
875 }
876 else {
877 return saveFile(fileName);
878 }
879 }
880
copy()881 void CsoundQt::copy()
882 {
883 if (helpPanel->hasFocus()) {
884 helpPanel->copy();
885 }
886 else if (m_console->widgetHasFocus()) {
887 m_console->copy();
888 }
889 else {
890 documentPages[curPage]->copy();
891 }
892 }
893
cut()894 void CsoundQt::cut()
895 {
896 documentPages[curPage]->cut();
897 }
898
paste()899 void CsoundQt::paste()
900 {
901 documentPages[curPage]->paste();
902 }
903
undo()904 void CsoundQt::undo()
905 {
906 // qDebug() << "CsoundQt::undo()";
907 documentPages[curPage]->undo();
908 }
909
redo()910 void CsoundQt::redo()
911 {
912 documentPages[curPage]->redo();
913 }
914
evaluateSection()915 void CsoundQt::evaluateSection()
916 {
917 QString text;
918 if (static_cast<LiveCodeEditor *>(m_scratchPad->widget())->getDocumentView()->hasFocus()) {
919 text = static_cast<LiveCodeEditor *>(m_scratchPad->widget())->getDocumentView()->getActiveText();
920 }
921 else {
922 text = documentPages[curPage]->getActiveSection();
923 }
924 evaluateString(text);
925 }
926
evaluate(QString code)927 void CsoundQt::evaluate(QString code)
928 {
929 QString evalCode;
930 if (code.isEmpty()) { //evaluate current selection in current document
931 if (static_cast<LiveCodeEditor *>(m_scratchPad->widget())->getDocumentView()->hasFocus()) {
932 evalCode = static_cast<LiveCodeEditor *>(m_scratchPad->widget())->getDocumentView()->getActiveText();
933 }
934 else {
935 evalCode = documentPages[curPage]->getActiveText();
936 if (evalCode.count("\n") <= 1) {
937 documentPages[curPage]->gotoNextRow();
938 }
939 }
940 }
941 else {
942 evalCode = code;
943 }
944 if (evalCode.size() > 1) { // evalCode can be \n and that crashes csound...
945 evaluateString(evalCode);
946 }
947 }
948
949
evaluateCsound(QString code)950 void CsoundQt::evaluateCsound(QString code)
951 {
952 #ifdef CSOUND6
953 documentPages[curPage]->sendCodeToEngine(code);
954 #else
955 qDebug() << "evaluateCsound only available in Csound6";
956 #endif
957 }
958
breakpointReached()959 void CsoundQt::breakpointReached()
960 {
961 #ifdef QCS_DEBUGGER
962 Q_ASSERT(m_debugEngine);
963 m_debugPanel->setVariableList(m_debugEngine->getVaribleList());
964 m_debugPanel->setInstrumentList(m_debugEngine->getInstrumentList());
965 documentPages[curPage]->getView()->m_mainEditor->setCurrentDebugLine(m_debugEngine->getCurrentLine());
966 #endif
967 }
968
evaluatePython(QString code)969 void CsoundQt::evaluatePython(QString code)
970 {
971 #ifdef QCS_PYTHONQT
972 m_pythonConsole->evaluate(code);
973 #else
974 (void) code;
975 showNoPythonQtWarning();
976 #endif
977 }
978
evaluateString(QString evalCode)979 void CsoundQt::evaluateString(QString evalCode)
980 {
981 #ifdef CSOUND6
982 TREE *testTree = NULL;
983 if (scratchPadCsdModeAct->isChecked()) {
984 // first check if it is a scoreline, then if it is csound code, if that also that fails, try with python
985 if (QRegExp("[if]\\s*-*[0-9]+\\s+[0-9]+\\s+[0-9]+.*\\n").indexIn(evalCode) >= 0) {
986 sendEvent(evalCode);
987 return;
988 }
989 CSOUND *csound = getEngine(curPage)->getCsound();
990 if (csound!=NULL) {
991 testTree = csoundParseOrc(csound,evalCode.toLocal8Bit()); // return not NULL, if the code is valid
992 if (testTree == NULL) {
993 qDebug() << "Not Csound code or cannot compile";
994 }
995 }
996 if (testTree) { // when the code is csound code, but with errors, it will be sent to python interpreter too
997 evaluateCsound(evalCode);
998 return;
999 }
1000 } else {
1001 evaluatePython(evalCode);
1002 }
1003 #endif
1004 }
1005
setScratchPadMode(bool csdMode)1006 void CsoundQt::setScratchPadMode(bool csdMode)
1007 {
1008 static_cast<LiveCodeEditor *>(m_scratchPad->widget())->setCsdMode(csdMode);
1009 }
1010
setWidgetEditMode(bool active)1011 void CsoundQt::setWidgetEditMode(bool active)
1012 {
1013 for (int i = 0; i < documentPages.size(); i++) {
1014 documentPages[i]->setWidgetEditMode(active);
1015 }
1016 }
1017
duplicate()1018 void CsoundQt::duplicate()
1019 {
1020 qDebug() << "CsoundQt::duplicate()";
1021 documentPages[curPage]->duplicateWidgets();
1022 }
1023
testAudioSetup()1024 void CsoundQt::testAudioSetup()
1025 {
1026 qDebug() << "CsoundQt::testAudioSetup";
1027 loadFile(":/examples/Useful/AudioMidiTest.csd");
1028 widgetPanel->setVisible(true);
1029 widgetPanel->setFocus();
1030 play();
1031 }
1032
checkSyntaxMenuAction()1033 void CsoundQt::checkSyntaxMenuAction()
1034 {
1035 bool prev = m_options->checkSyntaxOnly;
1036 m_options->checkSyntaxOnly = true;
1037 play();
1038 m_options->checkSyntaxOnly = prev;
1039 }
1040
getSaveFileName()1041 QString CsoundQt::getSaveFileName()
1042 {
1043 bool widgetsVisible = widgetPanel->isVisible();
1044 if (widgetsVisible && widgetPanel->isFloating())
1045 widgetPanel->hide(); // Necessary for Mac, as widget Panel covers open dialog
1046 bool helpVisible = helpPanel->isVisible();
1047 if (helpVisible && helpPanel->isFloating())
1048 helpPanel->hide(); // Necessary for Mac, as widget Panel covers open dialog
1049 bool inspectorVisible = m_inspector->isVisible();
1050 if (inspectorVisible && m_inspector->isFloating())
1051 m_inspector->hide(); // Necessary for Mac, as widget Panel covers open dialog
1052 QString dir = lastUsedDir;
1053 QString name = documentPages[curPage]->getFileName();
1054 dir += name.mid(name.lastIndexOf("/") + 1);
1055 QString fileName = QFileDialog::getSaveFileName(
1056 this, tr("Save File As"), dir,
1057 tr("Known Files (*.csd *.orc *.sco *.py *.udo *.html);;"
1058 "Csound Files (*.csd *.orc *.sco *.udo *.inc *.CSD *.ORC"
1059 "*.SCO *.UDO *.INC);;Python Files (*.py);;"
1060 "Html files (*.html);;All Files (*)",
1061 "Be careful to respect spacing parenthesis and usage of punctuation"));
1062 if (widgetsVisible) {
1063 if (!m_options->widgetsIndependent) {
1064 widgetPanel->show(); // Necessary for Mac, as widget Panel covers open dialog
1065 }
1066 }
1067 if (helpVisible)
1068 helpPanel->show(); // Necessary for Mac, as widget Panel covers open dialog
1069 if (inspectorVisible)
1070 m_inspector->show(); // Necessary for Mac, as widget Panel covers open dialog
1071 if (fileName.isEmpty())
1072 return QString("");
1073 if (isOpen(fileName) != -1 && isOpen(fileName) != curPage) {
1074 QMessageBox::critical(this, tr("CsoundQt"),
1075 tr("The file is already open in another tab.\nFile not saved!"),
1076 QMessageBox::Ok | QMessageBox::Default);
1077 return QString("");
1078 }
1079 // if (!fileName.endsWith(".csd",Qt::CaseInsensitive) && !fileName.endsWith(".orc",Qt::CaseInsensitive)
1080 // && !fileName.endsWith(".sco",Qt::CaseInsensitive) && !fileName.endsWith(".txt",Qt::CaseInsensitive)
1081 // && !fileName.endsWith(".udo",Qt::CaseInsensitive))
1082 // fileName += ".csd";
1083 if (fileName.isEmpty()) {
1084 fileName = name;
1085 }
1086 if (!fileName.contains(".")) {
1087 fileName += ".csd";
1088 }
1089 return fileName;
1090 }
1091
createQuickRefPdf()1092 void CsoundQt::createQuickRefPdf()
1093 {
1094 QString tempFileName(QDir::tempPath() + QDir::separator() +
1095 "QuteCsound Quick Reference.pdf");
1096 QString internalFileName = ":/doc/QuteCsound Quick Reference (0.4)-";
1097 internalFileName += m_configlists.languageCodes[m_options->language];
1098 internalFileName += ".pdf";
1099 if (!QFile::exists(internalFileName)) {
1100 internalFileName = ":/doc/QuteCsound Quick Reference (0.4).pdf";
1101 }
1102 // qDebug() << "CsoundQt::createQuickRefPdf() Opening " << internalFileName;
1103 QFile file(internalFileName);
1104 file.open(QIODevice::ReadOnly);
1105 QFile quickRefFile(tempFileName);
1106 quickRefFile.open(QFile::WriteOnly);
1107 QDataStream quickRefIn(&quickRefFile);
1108 quickRefIn << file.readAll();
1109 quickRefFileName = tempFileName;
1110 }
1111
deleteTab(int index)1112 void CsoundQt::deleteTab(int index)
1113 {
1114 if (index == -1) {
1115 index = curPage;
1116 }
1117 disconnect(showLiveEventsAct, 0,0,0);
1118 DocumentPage *d = documentPages[index];
1119 d->stop();
1120 d->showLiveEventControl(false);
1121 d->hideLiveEventPanels();
1122 midiHandler->removeListener(d);
1123 if (!m_options->widgetsIndependent) {
1124 QRect panelGeometry = widgetPanel->geometry();
1125 if (!widgetPanel->isFloating()) {
1126 panelGeometry.setX(-1);
1127 panelGeometry.setY(-1);
1128 }
1129 widgetPanel->takeWidgetLayout(panelGeometry);
1130 }
1131 documentPages.remove(index);
1132 documentTabs->removeTab(index);
1133 delete d;
1134 if (curPage >= documentPages.size()) {
1135 curPage = documentPages.size() - 1;
1136 }
1137 if (curPage < 0)
1138 curPage = 0; // deleting the document page decreases curPage, so must check
1139 }
1140
openLogFile()1141 void CsoundQt::openLogFile()
1142 {
1143 if (logFile.isOpen()) {
1144 logFile.close();
1145 }
1146 logFile.setFileName(m_options->logFile);
1147 if (m_options->logFile.isEmpty())
1148 return;
1149 if (logFile.open(QIODevice::ReadWrite | QIODevice::Text)) {
1150 logFile.readAll();
1151 QString text = "--**-- " + QDateTime::currentDateTime().toString("dd.MM.yyyy hh:mm:ss")
1152 + " CsoundQt Logging Started: "
1153 + "\n";
1154 logFile.write(text.toLatin1());
1155 }
1156 else {
1157 qDebug() << "CsoundQt::openLogFile() Error. Could not open log file! NO logging. " << logFile.fileName();
1158 }
1159 }
1160
showNewFormatWarning()1161 void CsoundQt::showNewFormatWarning()
1162 {
1163 QMessageBox::warning(this, tr("New widget format"),
1164 tr("This version of CsoundQt implements a new format for storing"
1165 " widgets, which enables many of the new widget features you "
1166 "will find now.\n"
1167 "The old format is still read and saved, so you will be able "
1168 "to open files in older versions but some of the features will "
1169 "not be passed to older versions.\n"),
1170 QMessageBox::Ok);
1171 }
1172
setupEnvironment()1173 void CsoundQt::setupEnvironment()
1174 {
1175 if (m_options->sadirActive){
1176 int ret = csoundSetGlobalEnv("SADIR", m_options->sadir.toLocal8Bit().constData());
1177 if (ret != 0) {
1178 qDebug() << "CsoundEngine::runCsound() Error setting SADIR";
1179 }
1180 }
1181 else {
1182 csoundSetGlobalEnv("SADIR", "");
1183 }
1184 if (m_options->ssdirActive){
1185 int ret = csoundSetGlobalEnv("SSDIR", m_options->ssdir.toLocal8Bit().constData());
1186 if (ret != 0) {
1187 qDebug() << "CsoundEngine::runCsound() Error setting SSDIR";
1188 }
1189 }
1190 else {
1191 csoundSetGlobalEnv("SSDIR", "");
1192 }
1193 if (m_options->sfdirActive){
1194 int ret = csoundSetGlobalEnv("SFDIR", m_options->sfdir.toLocal8Bit().constData());
1195 if (ret != 0) {
1196 qDebug() << "CsoundEngine::runCsound() Error setting SFDIR";
1197 }
1198 }
1199 else {
1200 csoundSetGlobalEnv("SFDIR", "");
1201 }
1202 if (m_options->incdirActive){
1203 int ret = csoundSetGlobalEnv("INCDIR", m_options->incdir.toLocal8Bit().constData());
1204 if (ret != 0) {
1205 qDebug() << "CsoundEngine::runCsound() Error setting INCDIR";
1206 }
1207 }
1208 else {
1209 csoundSetGlobalEnv("INCDIR", "");
1210 }
1211 // set rawWavePath for stk opcodes
1212 QString rawWavePath = m_options->rawWaveActive ? m_options->rawWave : QString(getenv("RAWWAVE_PATH"));
1213 if (rawWavePath.isNull()) {
1214 rawWavePath=QString(""); // NULL string may crash csoundInitilaize
1215 }
1216 if ( csoundSetGlobalEnv("RAWWAVE_PATH", rawWavePath.toLocal8Bit().constData()) ) {
1217 qDebug() << "CsoundEngine::runCsound() Error setting RAWWAVE_PATH";
1218 }
1219 #ifdef Q_OS_UNIX
1220 // make sure the the environment variable is set for stk opcodes
1221 setenv("RAWWAVE_PATH",rawWavePath.toLocal8Bit(),1);
1222 #endif
1223 #ifdef Q_OS_WIN
1224 QString envString = "RAWWAVE_PATH="+rawWavePath;
1225 _putenv(envString.toLocal8Bit());
1226 #endif
1227 // csoundGetEnv must be called after Compile or Precompile,
1228 // But I need to set OPCODEDIR before compile.... So I can't know keep the old OPCODEDIR
1229 if (m_options->opcodedirActive) {
1230 csoundSetGlobalEnv("OPCODEDIR", m_options->opcodedir.toLatin1().constData());
1231 }
1232 if (m_options->opcodedir64Active) {
1233 csoundSetGlobalEnv("OPCODEDIR64", m_options->opcodedir64.toLatin1().constData());
1234 }
1235 if (m_options->opcode6dir64Active) {
1236 csoundSetGlobalEnv("OPCODE6DIR64", m_options->opcode6dir64.toLatin1().constData());
1237 }
1238 #ifdef Q_OS_MACOS
1239 // Use bundled opcodes if available
1240 #ifdef USE_DOUBLE
1241 QString opcodedir = initialDir + "/../Frameworks/CsoundLib64.framework/Resources/Opcodes64";
1242 #else
1243 QString opcodedir = initialDir + "/../Frameworks/CsoundLib.framework/Resources/Opcodes";
1244 #endif
1245 if (QFile::exists(opcodedir)) {
1246 #ifdef CSOUND6
1247 #ifdef USE_DOUBLE
1248 csoundSetGlobalEnv("OPCODE6DIR64", opcodedir.toLocal8Bit().constData());
1249 #else
1250 csoundSetGlobalEnv("OPCODE6DIR", opcodedir.toLocal8Bit().constData());
1251 #endif
1252 #else
1253 #ifdef USE_DOUBLE
1254 csoundSetGlobalEnv("OPCODEDIR64", opcodedir.toLocal8Bit().constData());
1255 #else
1256 csoundSetGlobalEnv("OPCODEDIR", opcodedir.toLocal8Bit().constData());
1257 #endif
1258 #endif
1259 }
1260 #endif
1261 }
1262
onNewConnection()1263 void CsoundQt::onNewConnection()
1264 {
1265 qDebug()<<"NEW connection";
1266 QLocalSocket *client = m_server->nextPendingConnection();
1267 connect(client, SIGNAL(disconnected()), client, SLOT(deleteLater()));
1268 connect(client, SIGNAL(readyRead()), this, SLOT(onReadyRead()) );
1269 }
1270
onReadyRead()1271 void CsoundQt::onReadyRead()
1272 {
1273 QLocalSocket *socket = qobject_cast<QLocalSocket *>(sender());
1274 if (!socket || !socket->bytesAvailable())
1275 return;
1276 QByteArray ba = socket->readAll();
1277 if (ba.isEmpty())
1278 return;
1279 else {
1280 QStringList messageParts = QString(ba).split("***");
1281 if (messageParts[0].contains("open")) {
1282 messageParts.removeAt(0); // other parts should be filenames
1283 foreach (QString fileName, messageParts) {
1284 qDebug() << "Call from other instance. Opening "<<fileName;
1285 loadFile(fileName);
1286 //to bring window to front:
1287 this->raise();
1288 this->activateWindow();
1289 this->showNormal();
1290 }
1291 }
1292 }
1293 }
1294
disableInternalRtMidi()1295 void CsoundQt::disableInternalRtMidi()
1296 {
1297 #ifdef QCS_RTMIDI
1298 midiHandler->closeMidiInPort();
1299 midiHandler->closeMidiOutPort();
1300 #endif
1301 }
1302
focusToTab(int tab)1303 void CsoundQt::focusToTab(int tab) {
1304 QDockWidget *panel = nullptr;
1305 QAction * action = nullptr;
1306 qDebug()<<tab;
1307 switch (tab) {
1308 case 1:
1309 qDebug()<<"Raise widgets";
1310 if(m_options->widgetsIndependent) {
1311 QDEBUG << "Widget panel is an independent window";
1312 auto doc = this->documentPages[this->curPage];
1313 auto wl = doc->getWidgetLayout();
1314 if(wl->isVisible()) {
1315 wl->setVisible(false);
1316 showWidgetsAct->setChecked(false);
1317 } else {
1318 // not visible
1319 wl->setVisible(true);
1320 showWidgetsAct->setChecked(true);
1321 }
1322 return;
1323 } else {
1324 panel = widgetPanel;
1325 action = showWidgetsAct;
1326 break;
1327 }
1328 case 2:
1329 qDebug()<<"Raise help";
1330 panel = helpPanel;
1331 action = showHelpAct;
1332 break;
1333 case 3:
1334 qDebug()<<"Raise console";
1335 panel = m_console;
1336 action = showConsoleAct;
1337 break;
1338 case 4:
1339 qDebug()<<"Raise html panel";
1340 #ifdef QCS_QTHTML
1341 panel = csoundHtmlView;
1342 action = showHtml5Act;
1343 #endif
1344 break;
1345 case 5:
1346 qDebug()<<"Raise inspector";
1347 panel = m_inspector;
1348 action = showInspectorAct;
1349 break;
1350 // 6 is Live events that is independent window
1351
1352 case 7:
1353 qDebug()<<"Raise Pyton Console";
1354 #ifdef QCS_PYTHONQT
1355 panel = m_pythonConsole;
1356 action = showPythonConsoleAct;
1357 #endif
1358 break;
1359
1360 case 8:
1361 qDebug()<<"Raise Code Pad";
1362 panel = m_scratchPad;
1363 action = showScratchPadAct;
1364 break;
1365 default:
1366 qDebug() << "focusToTab: unknoun tab" << tab;
1367 return;
1368 }
1369
1370 if(!panel)
1371 return;
1372
1373 if (panel->isFloating() && panel->isVisible()) {
1374 // if as separate window, close it shortcut activated again
1375 QDEBUG << "panel is floating, hiding";
1376 panel->setVisible(false);
1377 action->setChecked(false);
1378 return;
1379 }
1380 if (!panel->isVisible()) {
1381 panel->show();
1382 action->setChecked(true);
1383 }
1384 panel->raise();
1385 }
1386
ambiguosShortcut()1387 void CsoundQt::ambiguosShortcut()
1388 {
1389 QMessageBox::warning(this, tr("Shortcuts changed"),
1390 tr("Ambiguous shortcut. In version 0.9.5 some shortcuts changed, please configure "
1391 "the shourtcuts or set to defaults "
1392 "(Edit/Configure shortcuts/Restore Defaults) "));
1393
1394 }
1395
saveAs()1396 bool CsoundQt::saveAs()
1397 {
1398 QString fileName = getSaveFileName();
1399 if (!fileName.isEmpty() && saveFile(fileName)) {
1400 return true;
1401 }
1402 return false;
1403 }
1404
createApp()1405 void CsoundQt::createApp()
1406 {
1407 QString opcodeDir;
1408 if (!documentPages[curPage]->getFileName().endsWith(".csd")) {
1409 QMessageBox::critical(this, tr("Error"),
1410 tr("You can only create an app with a csd file."));
1411 return;
1412 }
1413 if (documentPages[curPage]->isModified() ||
1414 documentPages[curPage]->getFileName().startsWith(":/")) {
1415 auto but = QMessageBox::question(
1416 this, tr("Save"),
1417 tr("Do you want to save before creating app?"),
1418 QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
1419 if (but == QMessageBox::Yes) {
1420 bool ret = save();
1421 if (!ret) {
1422 qDebug() << "CsoundQt::createApp() Error saving file";
1423 return;
1424 }
1425 } else {
1426 QMessageBox::critical(this, tr("Abort"),
1427 tr("You must save the csd before creating the App!"));
1428 return;
1429 }
1430 }
1431
1432 if (m_options->opcodedirActive) {
1433 // FIXME allow for OPCODEDIR64 if built for doubles
1434 opcodeDir = m_options->opcodedir.toLocal8Bit();
1435 }
1436 else {
1437 #ifdef USE_DOUBLE
1438 #ifdef Q_OS_LINUX
1439 #endif
1440 #ifdef Q_OS_FREEBSD
1441 #endif
1442 #ifdef Q_OS_SOLARIS
1443 #endif
1444 #ifdef Q_OS_WIN32
1445 #endif
1446 #ifdef Q_OS_MACOS
1447 opcodeDir = "/Library/Frameworks/CsoundLib64.framework/Resources/Opcodes";
1448 // opcodeDir = initialDir + "/CsoundQt.app/Contents/Frameworks/CsoundLib64.framework/Resources/Opcodes";
1449 #endif
1450 #else
1451
1452 #ifdef Q_OS_LINUX
1453 #endif
1454 #ifdef Q_OS_FREEBSD
1455 #endif
1456 #ifdef Q_OS_SOLARS
1457 #endif
1458 #ifdef Q_OS_WIN32
1459 #endif
1460 #ifdef Q_OS_MACOS
1461 #ifdef USE_DOUBLE
1462 opcodeDir = "/Library/Frameworks/CsoundLib.framework/Resources/Opcodes";
1463 #else
1464 opcodeDir = "/Library/Frameworks/CsoundLib64.framework/Resources/Opcodes";
1465 #endif
1466 // opcodeDir = initialDir + "/CsoundQt.app/Contents/Frameworks/CsoundLib.framework/Resources/Opcodes";
1467 #endif
1468
1469
1470 #endif
1471 }
1472 QString fullPath = documentPages[curPage]->getFileName();
1473 AppWizard wizard(this, opcodeDir, fullPath, m_options->sdkDir);
1474 AppProperties existingProperties = documentPages[curPage]->getAppProperties();
1475 if (existingProperties.used) {
1476 wizard.setField("appName", QVariant(existingProperties.appName));
1477 wizard.setField("targetDir", QVariant(existingProperties.targetDir));
1478 wizard.setField("author", QVariant(existingProperties.author));
1479 wizard.setField("version", QVariant(existingProperties.version));
1480 wizard.setField("email", QVariant(existingProperties.email));
1481 wizard.setField("website", QVariant(existingProperties.website));
1482 wizard.setField("instructions", QVariant(existingProperties.instructions));
1483 wizard.setField("autorun", QVariant(existingProperties.autorun));
1484 wizard.setField("showRun", QVariant(existingProperties.showRun));
1485 wizard.setField("saveState", QVariant(existingProperties.saveState));
1486 wizard.setField("runMode", QVariant(existingProperties.runMode));
1487 wizard.setField("newParser", QVariant(existingProperties.newParser));
1488 wizard.setField("useSdk", QVariant(existingProperties.useSdk ? 1 : 0));
1489 wizard.setField("useCustomPaths", QVariant(existingProperties.useCustomPaths));
1490 wizard.setField("libDir", QVariant(existingProperties.libDir));
1491 wizard.setField("opcodeDir", QVariant(existingProperties.opcodeDir));
1492 } else { // Put in default values
1493 QString appDir = fullPath.left(fullPath.lastIndexOf(QDir::separator()) );
1494 if (appDir.startsWith(":/")) { // For embedded examples
1495 appDir = QDir::homePath();
1496 }
1497 QString appName = fullPath.mid(fullPath.lastIndexOf(QDir::separator()) + 1);
1498 appName = appName.remove(".csd");
1499 wizard.setField("appName", appName);
1500 wizard.setField("targetDir", appDir);
1501 if (m_options->sdkDir.isEmpty()) { // No sdk,
1502 wizard.setField("customPaths", true);
1503 #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD) || defined(Q_OS_SOLARIS)
1504 wizard.setField("libDir", QCoreApplication::applicationDirPath()+"/../lib");
1505 if (opcodeDir.isEmpty()) {
1506 wizard.setField("opcodeDir", QCoreApplication::applicationDirPath()+"/../lib/csound/plugins64-6.0");
1507 }
1508 #endif
1509 #ifdef Q_OS_WIN32
1510 wizard.setField("libDir", "");
1511 if (opcodeDir.isEmpty()) {
1512 wizard.setField("opcodeDir", "");
1513 }
1514 #endif
1515 #ifdef Q_OS_MACOS
1516 wizard.setField("libDir", "/Library/Frameworks");
1517 #endif
1518 }
1519 }
1520 wizard.exec();
1521 if (wizard.result() == QDialog::Accepted) {
1522 AppProperties properties;
1523 properties.used = true;
1524 properties.appName = wizard.field("appName").toString();
1525 properties.targetDir = wizard.field("targetDir").toString();
1526 properties.author = wizard.field("author").toString();
1527 properties.version = wizard.field("version").toString();
1528 properties.date = QDateTime::currentDateTime().toString("MMMM d yyyy");
1529 properties.email = wizard.field("email").toString();
1530 properties.website = wizard.field("website").toString();
1531 properties.instructions = wizard.field("instructions").toString();
1532 properties.autorun = wizard.field("autorun").toBool();
1533 properties.showRun = wizard.field("showRun").toBool();
1534 properties.saveState = wizard.field("saveState").toBool();
1535 properties.runMode = wizard.field("runMode").toInt();
1536 properties.newParser = wizard.field("newParser").toBool();
1537 properties.useSdk = wizard.field("useSdk").toBool();
1538 properties.useCustomPaths = wizard.field("useCustomPaths").toBool();
1539 properties.libDir = wizard.field("libDir").toString();
1540 properties.opcodeDir = wizard.field("opcodeDir").toString();
1541
1542 documentPages[curPage]->setAppProperties(properties);
1543 bool ret = save(); // Must save to apply properties to file on disk.
1544 if (!ret) {
1545 qDebug() << "CsoundQt::createApp() Error saving file";
1546 return;
1547 }
1548 wizard.makeApp();
1549 }
1550 }
1551
saveNoWidgets()1552 bool CsoundQt::saveNoWidgets()
1553 {
1554 QString fileName = getSaveFileName();
1555 if (fileName != "")
1556 return saveFile(fileName, false);
1557 else
1558 return false;
1559 }
1560
info()1561 void CsoundQt::info()
1562 {
1563 QString text = tr("Full Path:") + " " + documentPages[curPage]->getFileName() + "\n\n";
1564 text += tr("Number of lines (Csound Text):") + " " +
1565 QString::number(documentPages[curPage]->lineCount(true)) + "\n";
1566 text += tr("Number of characters (Csound Text):") + " " +
1567 QString::number(documentPages[curPage]->characterCount(true)) + "\n";
1568 text += tr("Number of lines (total):") + " " +
1569 QString::number(documentPages[curPage]->lineCount()) + "\n";
1570 text += tr("Number of characters (total):") + " " +
1571 QString::number(documentPages[curPage]->characterCount()) + "\n";
1572 text += tr("Number of instruments:") + " " +
1573 QString::number(documentPages[curPage]->instrumentCount()) + "\n";
1574 text += tr("Number of UDOs:") + " " +
1575 QString::number(documentPages[curPage]->udoCount()) + "\n";
1576 text += tr("Number of Widgets:") + " " +
1577 QString::number(documentPages[curPage]->widgetCount()) + "\n";
1578 text += tr("Embedded Files:") + " " +
1579 documentPages[curPage]->embeddedFiles() + "\n";
1580 QMessageBox::information(this, tr("File Information"),
1581 text,
1582 QMessageBox::Ok,
1583 QMessageBox::Ok);
1584 }
1585
closeTab(bool forceCloseApp,int index)1586 bool CsoundQt::closeTab(bool forceCloseApp, int index)
1587 {
1588 if (index == -1) {
1589 index = curPage;
1590 }
1591 // qDebug("CsoundQt::closeTab() curPage = %i documentPages.size()=%i", curPage, documentPages.size());
1592 if (documentPages.size() > 0 && documentPages[index]->isModified()) {
1593 QString message = tr("The document ")
1594 + (documentPages[index]->getFileName() != ""
1595 ? documentPages[index]->getFileName(): "untitled.csd")
1596 + tr("\nhas been modified.\nDo you want to save the changes before closing?");
1597 int ret = QMessageBox::warning(this, tr("CsoundQt"),
1598 message,
1599 QMessageBox::Yes | QMessageBox::Default,
1600 QMessageBox::No,
1601 QMessageBox::Cancel | QMessageBox::Escape);
1602 if (ret == QMessageBox::Cancel)
1603 return false;
1604 else if (ret == QMessageBox::Yes) {
1605 if (!save())
1606 return false;
1607 }
1608 }
1609 if (!forceCloseApp) {
1610 if (documentPages.size() <= 1) {
1611 if (QMessageBox::warning(this, tr("CsoundQt"),
1612 tr("Do you want to exit CsoundQt?"),
1613 QMessageBox::Yes | QMessageBox::Default,
1614 QMessageBox::No) == QMessageBox::Yes)
1615 {
1616 close();
1617 return false;
1618 }
1619 else {
1620 newFile();
1621 curPage = 0;
1622 }
1623 }
1624 }
1625 deleteTab(index);
1626 changePage(curPage);
1627 // storeSettings(); // do not store here, since all tabs are closed on exit
1628 return true;
1629 }
1630
print()1631 void CsoundQt::print()
1632 {
1633 QPrinter printer;
1634 QPrintDialog *dialog = new QPrintDialog(&printer, this);
1635 dialog->setWindowTitle(tr("Print Document"));
1636 // if (editor->textCursor().hasSelection())
1637 // dialog->addEnabledOption(QAbstractPrintDialog::PrintSelection);
1638 if (dialog->exec() != QDialog::Accepted)
1639 return;
1640 documentPages[curPage]->print(&printer);
1641 }
1642
findReplace()1643 void CsoundQt::findReplace()
1644 {
1645 if(this->helpPanel->hasFocus()) {
1646 // TODO : call the help panel find
1647 this->helpPanel->toggleFindBarVisible(true);
1648 return;
1649 }
1650 documentPages[curPage]->findReplace();
1651 }
1652
findString()1653 void CsoundQt::findString()
1654 {
1655 documentPages[curPage]->findString();
1656 }
1657
join(bool ask)1658 bool CsoundQt::join(bool ask)
1659 {
1660 QDialog dialog(this);
1661 dialog.resize(700, 350);
1662 dialog.setModal(true);
1663 QPushButton *okButton = new QPushButton(tr("Ok"));
1664 QPushButton *cancelButton = new QPushButton(tr("Cancel"));
1665
1666 connect(okButton, SIGNAL(released()), &dialog, SLOT(accept()));
1667 connect(cancelButton, SIGNAL(released()), &dialog, SLOT(reject()));
1668
1669 QGridLayout *layout = new QGridLayout(&dialog);
1670 QListWidget *list1 = new QListWidget(&dialog);
1671 QListWidget *list2 = new QListWidget(&dialog);
1672 layout->addWidget(list1, 0, 0);
1673 layout->addWidget(list2, 0, 1);
1674 layout->addWidget(okButton, 1,0);
1675 layout->addWidget(cancelButton, 1,1);
1676 // layout->resize(400, 200);
1677
1678 for (int i = 0; i < documentPages.size(); i++) {
1679 QString name = documentPages[i]->getFileName();
1680 if (name.endsWith(".orc"))
1681 list1->addItem(name);
1682 else if (name.endsWith(".sco"))
1683 list2->addItem(name);
1684 }
1685 QString name = documentPages[curPage]->getFileName();
1686 QList<QListWidgetItem *> itemList = list1->findItems(name, Qt::MatchExactly);
1687 if (itemList.size() == 0) {
1688 itemList = list1->findItems(name.replace(".sco", ".orc"),Qt::MatchExactly);
1689 }
1690 if (itemList.size() > 0) {
1691 list1->setCurrentItem(itemList[0]);
1692 }
1693 QList<QListWidgetItem *> itemList2 = list2->findItems(name.replace(".orc", ".sco"),
1694 Qt::MatchExactly);
1695 if (itemList2.size() == 0) {
1696 itemList2 = list1->findItems(name,Qt::MatchExactly);
1697 }
1698 if (itemList2.size() > 0)
1699 list2->setCurrentItem(itemList2[0]);
1700 if (itemList.size() == 0 || itemList.size() == 0) {
1701 if (!ask) {
1702 QMessageBox::warning(this, tr("Join"),
1703 tr("Please open the orc and sco files in CsoundQt first!"));
1704 }
1705 return false;
1706 }
1707 if (!ask || dialog.exec() == QDialog::Accepted) {
1708 QString orcText = "";
1709 QString scoText = "";
1710 for (int i = 0; i < documentPages.size(); i++) {
1711 QString name = documentPages[i]->getFileName();
1712 if (name == list1->currentItem()->text())
1713 orcText = documentPages[i]->getFullText();
1714 else if (name == list2->currentItem()->text())
1715 scoText = documentPages[i]->getFullText();
1716 }
1717 QString text = "<CsoundSynthesizer>\n<CsOptions>\n</CsOptions>\n<CsInstruments>\n";
1718 text += orcText;
1719 text += "</CsInstruments>\n<CsScore>\n";
1720 text += scoText;
1721 text += "</CsScore>\n</CsoundSynthesizer>\n";
1722 newFile();
1723 documentPages[curPage]->loadTextString(text);
1724 return true;
1725 }
1726 return false;
1727 }
1728
showUtilities(bool show)1729 void CsoundQt::showUtilities(bool show)
1730 {
1731 if (!show) {
1732 if (utilitiesDialog != nullptr && utilitiesDialog->close()) {
1733 utilitiesDialog = nullptr;
1734 }
1735 }
1736 else {
1737 utilitiesDialog = new UtilitiesDialog(this, m_options/*, _configlists*/);
1738 connect(utilitiesDialog, SIGNAL(Close(bool)), showUtilitiesAct, SLOT(setChecked(bool)));
1739 connect(utilitiesDialog, SIGNAL(runUtility(QString)), this, SLOT(runUtility(QString)));
1740 utilitiesDialog->setModal(false);
1741 utilitiesDialog->show();
1742 }
1743 }
1744
inToGet()1745 void CsoundQt::inToGet()
1746 {
1747 documentPages[curPage]->inToGet();
1748 }
1749
getToIn()1750 void CsoundQt::getToIn()
1751 {
1752 documentPages[curPage]->getToIn();
1753 }
1754
updateCsladspaText()1755 void CsoundQt::updateCsladspaText()
1756 {
1757 documentPages[curPage]->updateCsLadspaText();
1758 }
1759
updateCabbageText()1760 void CsoundQt::updateCabbageText()
1761 {
1762 documentPages[curPage]->updateCabbageText();
1763 // check if necessary options for Cabbage
1764 QString optionsText=documentPages[curPage]->getOptionsText().trimmed();
1765 if (!(optionsText.contains("-d") && optionsText.contains("-n"))) {
1766 int answer = QMessageBox::question(this, tr("Insert Cabbage options?"),
1767 tr("There seems to be no Cabbage specific options in <CsOptions>.\n Do you want to insert it?\nNB! Comment your old options out, if necessary!"), QMessageBox::Yes|QMessageBox::No );
1768 if (answer==QMessageBox::Yes) {
1769 if (!optionsText.simplified().isEmpty()) {
1770 optionsText += "\n"; // add newline if there is some text
1771 }
1772 optionsText += "-n -d -+rtmidi=NULL -M0 --midi-key-cps=4 --midi-velocity-amp=5";
1773 documentPages[curPage]->setOptionsText(optionsText);
1774 }
1775 }
1776 QString scoreText = documentPages[curPage]->getSco();
1777 if (scoreText.simplified().isEmpty()) {
1778 int answer = QMessageBox::question(this, tr("Insert scorelines for Cabbage?"),
1779 tr("The score is empty. Cabbage needs some lines "
1780 "to work.\n Do you want to insert it?"),
1781 QMessageBox::Yes|QMessageBox::No );
1782 if (answer==QMessageBox::Yes) {
1783 documentPages[curPage]->setSco("f 0 3600\n"
1784 ";i 1 0 3600 ; don't forget to start your instrument if you are using it as an effect!");
1785 }
1786 }
1787 }
1788
saveWidgetsToQml()1789 void CsoundQt::saveWidgetsToQml()
1790 {
1791 QString qml = documentPages[curPage]->getQml();
1792
1793 //QString dir = lastUsedDir;
1794 QString name = documentPages[curPage]->getFileName();
1795 name.replace(".csd", ".qml");
1796 //dir += name.mid(name.lastIndexOf("/") + 1);
1797 //TODO: get dir from name - extract path
1798 QString fileName = QFileDialog::getSaveFileName(
1799 this, tr("Save Qml File"), name,
1800 tr("QML Files (*.qml *.QML);;All Files (*)",
1801 "Export Widgets to QML"));
1802 if ( !fileName.isEmpty()) { // save to file
1803 QFile file(fileName);
1804
1805 if(file.open(QFile::WriteOnly | QFile::Text)) {
1806 QTextStream stream(&file);
1807 stream << qml;
1808 file.close();
1809 }
1810 }
1811 }
1812
setCurrentAudioFile(const QString fileName)1813 void CsoundQt::setCurrentAudioFile(const QString fileName)
1814 {
1815 currentAudioFile = fileName;
1816 }
1817
play(bool realtime,int index)1818 void CsoundQt::play(bool realtime, int index)
1819 {
1820 qDebug() << "CsoundQt::play...";
1821 // TODO make csound pause if it is already running
1822 int oldPage = curPage;
1823 if (index == -1) {
1824 index = curPage;
1825 }
1826 if (index < 0 && index >= documentPages.size()) {
1827 qDebug() << "CsoundQt::play index out of range " << index;
1828 return;
1829 }
1830 curPage = index;
1831 auto page = documentPages[curPage];
1832
1833 if (page->getFileName().isEmpty()) {
1834 int answer;
1835 if(!m_options->askIfTemporary)
1836 answer= QMessageBox::Ok;
1837 else
1838 answer = QMessageBox::question(this, tr("Run as temporary file?"),
1839 tr("press <b>OK</b>, if you don't care about this file in "
1840 "future.\n Press <b>Save</b>, if you want to save it with "
1841 "given name.\n You can always save the file with <b>Save As</b> "
1842 "also later, if you use the temporary file."),
1843 QMessageBox::Ok|QMessageBox::Save|QMessageBox::Cancel );
1844 bool saved = false;
1845 if (answer==QMessageBox::Save) {
1846 saved = saveAs();
1847 } else if (answer==QMessageBox::Ok) {
1848 auto tempPath = QStandardPaths::writableLocation(QStandardPaths::TempLocation);
1849 if (!tempPath.isEmpty() && saveFile(tempPath + "/csoundqt-temp.csd")) {
1850 saved = true;
1851 } else {
1852 QMessageBox::critical(this,tr("Save error"), tr("Could not save temporary file"));
1853 }
1854 }
1855 if (!saved) {
1856 if (curPage == oldPage) {
1857 runAct->setChecked(false);
1858 }
1859 curPage = oldPage;
1860 return;
1861 }
1862 }
1863 else if (page->isModified()) {
1864 if (m_options->saveChanges && !save()) {
1865 if (curPage == oldPage) {
1866 runAct->setChecked(false);
1867 }
1868 curPage = oldPage;
1869 return;
1870 }
1871 }
1872 QString fileName = page->getFileName();
1873 QString fileName2;
1874 QString msg = "__**__ " + QDateTime::currentDateTime().toString("dd.MM.yyyy hh:mm:ss");
1875 msg += " Play: " + fileName + "\n";
1876 logMessage(msg);
1877 m_options->csdPath = "";
1878 if (fileName.contains('/')) {
1879 //FIXME is it necessary to set the csdPath here?
1880 // m_options->csdPath =
1881 // documentPages[curPage]->fileName.left(documentPages[curPage]->fileName.lastIndexOf('/'));
1882 QDir::setCurrent(fileName.left(fileName.lastIndexOf('/')));
1883 }
1884 #ifdef QCS_PYTHONQT
1885 if (fileName.endsWith(".py",Qt::CaseInsensitive)) {
1886 m_pythonConsole->runScript(fileName);
1887 runAct->setChecked(false);
1888 curPage = documentTabs->currentIndex();
1889 return;
1890 }
1891 #endif
1892 if (fileName.endsWith(".html",Qt::CaseInsensitive)) {
1893 QMessageBox::warning(this,
1894 tr("CsoundQt"),
1895 tr("Csound in html files should be started from html code."),
1896 QMessageBox::Ok);
1897 runAct->setChecked(false);
1898 curPage = documentTabs->currentIndex();
1899 return;
1900 }
1901 if (!fileName.endsWith(".csd",Qt::CaseInsensitive)
1902 && !fileName.endsWith(".py",Qt::CaseInsensitive)) {
1903 if (page->askForFile)
1904 getCompanionFileName();
1905 // FIXME run orc file when sco companion is currently active
1906 if (fileName.endsWith(".sco",Qt::CaseInsensitive)) {
1907 //Must switch filename order when open file is a sco file
1908 fileName2 = fileName;
1909 fileName = page->getCompanionFileName();
1910 } else if (fileName.endsWith(".orc",Qt::CaseInsensitive) &&
1911 page->getCompanionFileName().isEmpty()) {
1912 //TODO: create empty score file
1913 }
1914 else
1915 fileName2 = page->getCompanionFileName();
1916 }
1917 QString runFileName1, runFileName2;
1918 QTemporaryFile csdFile, csdFile2; // TODO add support for orc/sco pairs
1919 runFileName1 = fileName;
1920 if(fileName.startsWith(":/examples/", Qt::CaseInsensitive) || !m_options->saveChanges) {
1921 QDEBUG << "***** Using temporary file for filename" << fileName;
1922 QString tmpFileName = QDir::tempPath();
1923 if (!tmpFileName.endsWith("/") && !tmpFileName.endsWith("\\")) {
1924 tmpFileName += QDir::separator();
1925 }
1926 if (fileName.endsWith(".csd",Qt::CaseInsensitive)) {
1927 tmpFileName += QString("csound-tmpXXXXXXXX.csd");
1928 csdFile.setFileTemplate(tmpFileName);
1929 if (!csdFile.open()) {
1930 qDebug() << "Error creating temporary file " << tmpFileName;
1931 QMessageBox::critical(this, tr("CsoundQt"), tr("Error creating temporary file."),
1932 QMessageBox::Ok);
1933 return;
1934 }
1935 // If example, just copy, since readonly anyway, otherwise get contents from editor.
1936 // Necessary since examples may contain <CsFileB> section with data.
1937 if (!fileName.startsWith(":/examples/", Qt::CaseInsensitive)) {
1938 csdFile.write(page->getBasicText().toLatin1());
1939 } else {
1940 auto fullText = page->getView()->getFullText();
1941 if(!fullText.contains("<CsFileB")) {
1942 csdFile.write(fullText.toLatin1());
1943 } else {
1944 qDebug() << "File has embedded elements via <CsFileB> tag";
1945 QFile file(fileName);
1946 if(!file.open(QFile::ReadOnly)) {
1947 qDebug() << "Could not open file " << fileName;
1948 return;
1949 }
1950 int result = csdFile.write(file.readAll());
1951 file.close();
1952 if (result<=0) {
1953 qDebug()<< "*** ERROR: Failed to copy to example to temporary "
1954 "location ***";
1955 return;
1956 }
1957 }
1958 }
1959 csdFile.flush();
1960 runFileName1 = csdFile.fileName();
1961 }
1962 }
1963 runFileName2 = page->getCompanionFileName();
1964 m_options->docName = fileName;
1965 m_options->fileName1 = runFileName1;
1966 m_options->fileName2 = runFileName2;
1967 m_options->rt = realtime;
1968 if (!m_options->simultaneousRun) {
1969 stopAllOthers();
1970 #if defined(QCS_QTHTML)
1971 csoundHtmlView->stop();
1972 #endif
1973 }
1974 if (curPage == oldPage) {
1975 runAct->setChecked(true); // In case the call comes from a button
1976 }
1977 if (page->usesFltk() && m_options->terminalFLTK) {
1978 runInTerm();
1979 curPage = oldPage;
1980 return;
1981 }
1982 int ret = page->play(m_options);
1983 if (ret == -1) {
1984 QMessageBox::critical(this, "CsoundQt", tr("Internal error running Csound."),
1985 QMessageBox::Ok);
1986 } else if (ret == -2) {
1987 // Error creating temporary file
1988 runAct->setChecked(false);
1989 qDebug() << "CsoundQt::play - Error creating temporary file";
1990 } else if (ret == -3) {
1991 // Csound compilation failed
1992 runAct->setChecked(false);
1993 } else if (ret == 0) {
1994 // No problem: enable widgets
1995 if(m_options->checkSyntaxOnly) {
1996 return;
1997 }
1998 if (m_options->enableWidgets && m_options->showWidgetsOnRun && fileName.endsWith(".csd")) {
1999 if(page->usesFltk()) {
2000 // Don't bring up widget panel if there's an FLTK panel
2001 qDebug() << "Page uses FLTK, CsoundQt's widgets will not be shown";
2002 } else {
2003 if (!m_options->widgetsIndependent) {
2004 if (widgetPanel->isFloating()) {
2005 widgetPanel->setVisible(true);
2006 showWidgetsAct->setChecked(true);
2007 }
2008 }
2009 else {
2010 page->widgetsVisible(true);
2011 showWidgetsAct->setChecked(true);
2012 }
2013 widgetPanel->setFocus(Qt::OtherFocusReason);
2014 page->showLiveEventControl(showLiveEventsAct->isChecked());
2015 page->focusWidgets();
2016 }
2017 }
2018 } else {
2019 qDebug() << "play: Return value not understood!";
2020 return;
2021 }
2022 #if defined(QCS_QTHTML)
2023 if (!documentPages.isEmpty()) {
2024 if ( !m_options->saveChanges ) { // otherwise the htmlview gets updated on save
2025 updateHtmlView();
2026 qDebug()<<"update html on run";
2027 }
2028 DocumentPage *documentPage = documentPages[curPage];
2029 if (!documentPage->getHtmlText().isEmpty()) {
2030 CsoundEngine *engine = documentPage->getEngine();
2031 csoundHtmlView->setCsoundEngine(engine);
2032 }
2033 }
2034 #endif
2035 curPage = oldPage;
2036 }
2037
runInTerm(bool realtime)2038 void CsoundQt::runInTerm(bool realtime)
2039 {
2040 QString fileName = documentPages[curPage]->getFileName();
2041 QTemporaryFile tempFile(QDir::tempPath() + QDir::separator() + "CsoundQtExample-XXXXXX.csd");
2042 tempFile.setAutoRemove(false);
2043 if (fileName.startsWith(":/")) {
2044 if (!tempFile.open()) {
2045 qDebug() << "CsoundQt::runCsound() : Error creating temp file";
2046 runAct->setChecked(false);
2047 return;
2048 }
2049 QString csdText = documentPages[curPage]->getBasicText();
2050 fileName = tempFile.fileName();
2051 tempFile.write(csdText.toLatin1());
2052 tempFile.flush();
2053 if (!tempScriptFiles.contains(fileName))
2054 tempScriptFiles << fileName;
2055 }
2056 // QString script = generateScript(m_options->realtime, fileName);
2057 QString executable = fileName.endsWith(".py") ? m_options->pythonExecutable : "";
2058 QString script = generateScript(realtime, fileName, executable);
2059 QTemporaryFile scriptFile(QDir::tempPath() + QDir::separator() + SCRIPT_NAME);
2060 scriptFile.setAutoRemove(false);
2061 if (!scriptFile.open()) {
2062 runAct->setChecked(false);
2063 return;
2064 }
2065 QTextStream out(&scriptFile);
2066 out << script;
2067 // file.flush();
2068 scriptFile.close();
2069 scriptFile.setPermissions (QFile::ExeOwner| QFile::WriteOwner| QFile::ReadOwner);
2070 QString scriptFileName = scriptFile.fileName();
2071
2072 QString options;
2073 #ifdef Q_OS_LINUX
2074 options = "-e " + scriptFileName;
2075 #endif
2076 #ifdef Q_OS_FREEBSD
2077 options = "-e " + scriptFileName;
2078 #endif
2079 #ifdef Q_OS_SOLARIS
2080 options = "-e " + scriptFileName;
2081 #endif
2082 #ifdef Q_OS_MACOS
2083 options = scriptFileName;
2084 #endif
2085 #ifdef Q_OS_WIN32
2086 options = scriptFileName;
2087 qDebug() << "m_options->terminal == " << m_options->terminal;
2088 #endif
2089 if (execute(m_options->terminal, options)) {
2090 QMessageBox::critical(this, tr("Error running terminal"),
2091 tr("Could not run terminal program:\n %1\n"
2092 "Check environment tab in preferences.").arg(m_options->terminal));
2093 }
2094 runAct->setChecked(false);
2095 if (!tempScriptFiles.contains(scriptFileName))
2096 tempScriptFiles << scriptFileName;
2097 }
2098
pause(int index)2099 void CsoundQt::pause(int index)
2100 {
2101 int docIndex = index;
2102 if (docIndex == -1) {
2103 docIndex = curPage;
2104 }
2105 if (docIndex >= 0 && docIndex < documentPages.size()) {
2106 documentPages[docIndex]->pause();
2107 }
2108 }
2109
stop(int index)2110 void CsoundQt::stop(int index)
2111 {
2112 // Must guarantee that csound has stopped when it returns
2113 int docIndex = index;
2114 if (docIndex == -1) {
2115 docIndex = curPage;
2116 }
2117 if (curPage >= documentPages.size()) {
2118 return; // A bit of a hack to avoid crashing when documents are deleted very quickly...
2119 }
2120 Q_ASSERT(docIndex >= 0);
2121 if (docIndex >= documentPages.size()) {
2122 qDebug() << "CsoundQt::stop : document index" << docIndex
2123 << "out of range (max=" << documentPages.size() << ")";
2124 markStopped();
2125 return;
2126 }
2127 if (documentPages[docIndex]->isRunning()) {
2128 documentPages[docIndex]->stop();
2129
2130 #ifdef Q_OS_WIN
2131 // necessary since sometimes fltk plugin closes the OLE/COM connection on csoundCleanup
2132 HRESULT result = OleInitialize(NULL);
2133 if (result) {
2134 qDebug()<<"Problem with OleInitialization" << result;
2135 }
2136 #endif
2137
2138 }
2139 markStopped();
2140 }
2141
stopAll()2142 void CsoundQt::stopAll()
2143 {
2144 for (int i = 0; i < documentPages.size(); i++) {
2145 documentPages[i]->stop();
2146 }
2147 markStopped();
2148 }
2149
stopAllOthers()2150 void CsoundQt::stopAllOthers()
2151 {
2152 for (int i = 0; i < documentPages.size(); i++) {
2153 if (i != curPage) {
2154 DocumentPage *documentPage = documentPages[i];
2155 documentPage->stop();
2156 }
2157 }
2158 // markStopped();
2159 }
2160
markStopped()2161 void CsoundQt::markStopped()
2162 {
2163 runAct->setChecked(false);
2164 recAct->setChecked(false);
2165 #ifdef QCS_DEBUGGER
2166 m_debugPanel->stopDebug();
2167 #endif
2168 }
2169
perfEnded()2170 void CsoundQt::perfEnded()
2171 {
2172 runAct->setChecked(false);
2173 }
2174
record(bool rec)2175 void CsoundQt::record(bool rec)
2176 {
2177 if (rec) {
2178 if (!documentPages[curPage]->isRunning()) {
2179 play();
2180 }
2181 int ret = documentPages[curPage]->record(m_options->sampleFormat);
2182 if (ret != 0) {
2183 recAct->setChecked(false);
2184 }
2185 }
2186 else {
2187 documentPages[curPage]->stopRecording();
2188 }
2189 }
2190
2191
sendEvent(QString eventLine,double delay)2192 void CsoundQt::sendEvent(QString eventLine, double delay)
2193 {
2194 sendEvent(curCsdPage, eventLine, delay);
2195 }
2196
sendEvent(int index,QString eventLine,double delay)2197 void CsoundQt::sendEvent(int index, QString eventLine, double delay)
2198 {
2199 int docIndex = index;
2200 if (docIndex == -1) {
2201 docIndex = curPage;
2202 }
2203 if (docIndex >= 0 && docIndex < documentPages.size()) {
2204 documentPages[docIndex]->queueEvent(eventLine, delay);
2205 }
2206 }
2207
render()2208 void CsoundQt::render()
2209 {
2210 if (m_options->fileAskFilename) {
2211 QString defaultFile;
2212 if (m_options->fileOutputFilenameActive) {
2213 defaultFile = m_options->fileOutputFilename;
2214 }
2215 else {
2216 defaultFile = lastFileDir;
2217 }
2218 QFileDialog dialog(this,tr("Output Filename"),defaultFile);
2219 dialog.setAcceptMode(QFileDialog::AcceptSave);
2220 // dialog.setConfirmOverwrite(false);
2221 auto extensions = m_configlists.fileTypeExtensions[m_options->fileFileType];
2222 QString filter = QString(m_configlists.fileTypeLongNames[m_options->fileFileType] +
2223 " Files (" + extensions + ")");
2224 dialog.selectNameFilter(filter);
2225 if (dialog.exec() == QDialog::Accepted) {
2226 QString extension = extensions.left(extensions.indexOf(";"));
2227 // Remove the '*' from the extension
2228 extension.remove(0,1);
2229 m_options->fileOutputFilename = dialog.selectedFiles()[0];
2230 if (!m_options->fileOutputFilename.endsWith(".wav")
2231 && !m_options->fileOutputFilename.endsWith(".aif")
2232 && !m_options->fileOutputFilename.endsWith(extension) ) {
2233 m_options->fileOutputFilename += extension;
2234 }
2235 auto outfile = m_options->fileOutputFilename;
2236 if (QFile::exists(outfile)) {
2237 int ret = QMessageBox::warning(this, tr("CsoundQt"),
2238 tr("The file %1 already exists.\n Do you want to overwrite it?")
2239 .arg(outfile),
2240 QMessageBox::Save|QMessageBox::Cancel, QMessageBox::Save);
2241 if (ret == QMessageBox::Cancel)
2242 return;
2243 }
2244 lastFileDir = dialog.directory().path();
2245 }
2246 else {
2247 return;
2248 }
2249 }
2250 QString outName = m_options->fileOutputFilename;
2251 #ifdef Q_OS_WIN32
2252 outName = outName.replace('\\', '/');
2253 #endif
2254 if (outName.isEmpty()) {
2255 outName = "test.wav";
2256 }
2257 setCurrentAudioFile(outName);
2258 play(false);
2259 }
2260
openExternalEditor()2261 void CsoundQt::openExternalEditor()
2262 {
2263 QString name = "";
2264 if (m_options->sfdirActive) {
2265 name = m_options->sfdir + (m_options->sfdir.endsWith("/") ? "" : "/");
2266 }
2267 name += currentAudioFile;
2268 QString optionsText = documentPages[curPage]->getOptionsText();
2269 if (currentAudioFile == "") {
2270 if (!optionsText.contains(QRegExp("\\W-o"))) {
2271 name += "test.wav";
2272 }
2273 else {
2274 optionsText = optionsText.mid(optionsText.indexOf(QRegExp("\\W-o")) + 3);
2275 optionsText = optionsText.left(optionsText.indexOf("\n")).trimmed();
2276 optionsText = optionsText.left(optionsText.indexOf("-")).trimmed();
2277 if (!optionsText.startsWith("dac"))
2278 name += optionsText;
2279 }
2280 }
2281 if (!QFile::exists(name)) {
2282 QMessageBox::critical(this, tr("Render not available"),
2283 tr("Could not find rendered file. Please render before calling"
2284 " external editor."));
2285 }
2286 if (!m_options->waveeditor.isEmpty()) {
2287 name = "\"" + name + "\"";
2288 execute(m_options->waveeditor, name);
2289 }
2290 else {
2291 QDesktopServices::openUrl(QUrl::fromLocalFile (name));
2292 }
2293 }
2294
openExternalPlayer()2295 void CsoundQt::openExternalPlayer()
2296 {
2297 QString name = "";
2298 if (m_options->sfdirActive) {
2299 name = m_options->sfdir + (m_options->sfdir.endsWith("/") ? "" : "/");
2300 }
2301 name += currentAudioFile;
2302 QString optionsText = documentPages[curPage]->getOptionsText();
2303 if (currentAudioFile == "") {
2304 if (!optionsText.contains(QRegExp("\\W-o"))) {
2305 name += "test.wav";
2306 }
2307 else {
2308 optionsText = optionsText.mid(optionsText.indexOf(QRegExp("\\W-o")) + 3);
2309 optionsText = optionsText.left(optionsText.indexOf("\n")).trimmed();
2310 optionsText = optionsText.left(optionsText.indexOf(QRegExp("-"))).trimmed();
2311 if (!optionsText.startsWith("dac"))
2312 name += optionsText;
2313 }
2314 }
2315 if (!QFile::exists(name)) {
2316 QMessageBox::critical(this, tr("Render not available"),
2317 tr("Could not find rendered file. Please render before calling"
2318 " external player."));
2319 }
2320 if (!m_options->waveplayer.isEmpty()) {
2321 name = "\"" + name + "\"";
2322 execute(m_options->waveplayer, name);
2323 }
2324 else {
2325 QDesktopServices::openUrl(QUrl::fromLocalFile (name));
2326 }
2327 }
2328
setEditorFocus()2329 void CsoundQt::setEditorFocus()
2330 {
2331 documentPages[curPage]->setEditorFocus();
2332 this->raise();
2333 }
2334
setHelpEntry()2335 void CsoundQt::setHelpEntry()
2336 {
2337 QString text = documentPages[curPage]->wordUnderCursor();
2338 if (text.startsWith('#')) { // For #define and friends
2339 text.remove(0,1);
2340 }
2341 QString dir = m_options->csdocdir.isEmpty() ? helpPanel->docDir : m_options->csdocdir ;
2342 if (text.startsWith("http://")) {
2343 openExternalBrowser(QUrl(text));
2344 }
2345 else if (!dir.isEmpty()) {
2346 if (text == "0dbfs")
2347 text = "Zerodbfs";
2348 else if (text.contains("CsOptions"))
2349 text = "CommandUnifile";
2350 else if (text.startsWith("chn_"))
2351 text = "chn";
2352 helpPanel->docDir = dir;
2353 QString fileName = dir + "/" + text + ".html";
2354 if (QFile::exists(fileName)) {
2355 helpPanel->loadFile(fileName);
2356 }
2357 // else {
2358 // helpPanel->loadFile(dir + "/index.html");
2359 // }
2360 helpPanel->show();
2361 helpPanel->raise();
2362 helpPanel->focusText();
2363 }
2364 else {
2365 QMessageBox::critical(this, tr("Error"),
2366 tr("HTML Documentation directory not set!\n"
2367 "Please go to Edit->Options->Environment and select directory\n"));
2368 }
2369 }
2370
2371
setFullScreen(bool full)2372 void CsoundQt::setFullScreen(bool full)
2373 {
2374 if (full) {
2375 checkFullScreen();
2376 this->showFullScreen();
2377 m_fullScreenComponent = "mainwindow";
2378 }
2379 else {
2380 this->showNormal();
2381 m_fullScreenComponent = "";
2382 }
2383 }
2384
checkFullScreen()2385 void CsoundQt::checkFullScreen() // checks if some component is already fullscreen and resets it
2386 {
2387 //qDebug()<< " fullScreenComponent: " << m_fullScreenComponent << "state bytes: " << m_preFullScreenState.size();
2388 if ( !m_fullScreenComponent.isEmpty() ) {
2389 if (m_fullScreenComponent == "mainwindow" ) {
2390 viewFullScreenAct->setChecked(false);
2391 } else if (m_fullScreenComponent == "help" ) {
2392 viewHelpFullScreenAct->setChecked(false);
2393 } else if (m_fullScreenComponent == "widgets") {
2394 viewWidgetsFullScreenAct->setChecked(false);
2395 } else if ( m_fullScreenComponent == "editor" ) {
2396 } else if ( m_fullScreenComponent == "html" ) {
2397 viewHtmlFullScreenAct->setChecked(false);
2398 }
2399 }
2400 }
2401
setEditorFullScreen(bool full)2402 void CsoundQt::setEditorFullScreen(bool full)
2403 {
2404 if (full) {
2405 checkFullScreen();
2406 m_preFullScreenState = this->saveState();
2407 QList<QDockWidget *> dockWidgets = findChildren<QDockWidget *>();
2408 foreach (QDockWidget *dockWidget, dockWidgets) {
2409 dockWidget->hide();
2410 }
2411 this->showFullScreen();
2412 m_fullScreenComponent = "editor";
2413 }
2414 else {
2415 this->restoreState(m_preFullScreenState);
2416 this->showNormal(); // to restore titlebar etc
2417 m_fullScreenComponent = "";
2418 }
2419 }
2420
2421
setHtmlFullScreen(bool full)2422 void CsoundQt::setHtmlFullScreen(bool full)
2423 {
2424 #ifdef QCS_QTHTML
2425 if (full) {
2426 checkFullScreen();
2427 m_preFullScreenState = this->saveState();
2428 this->csoundHtmlView->setFloating(true);
2429 #ifdef Q_OS_MACOS
2430 this->csoundHtmlView->showMaximized();
2431 #else
2432 this->csoundHtmlView->showFullScreen();
2433 #endif
2434 m_fullScreenComponent = "html";
2435 }
2436 else {
2437 this->restoreState(m_preFullScreenState);
2438 this->csoundHtmlView->setFloating(false);
2439 //this->showNormal();
2440 m_fullScreenComponent = "";
2441 }
2442 #endif
2443 }
2444
setHelpFullScreen(bool full)2445 void CsoundQt::setHelpFullScreen(bool full)
2446 {
2447 if (full) {
2448 checkFullScreen();
2449 m_preFullScreenState = this->saveState();
2450 this->helpPanel->setFloating(true);
2451 #ifdef Q_OS_MACOS
2452 this->helpPanel->showMaximized();
2453 #else
2454 this->helpPanel->showFullScreen();
2455 #endif
2456 m_fullScreenComponent = "help";
2457 }
2458 else {
2459 this->restoreState(m_preFullScreenState);
2460 //this->showNormal();
2461 m_fullScreenComponent = "";
2462 }
2463 }
2464
setWidgetsFullScreen(bool full)2465 void CsoundQt::setWidgetsFullScreen(bool full)
2466 {
2467 if (full) {
2468 checkFullScreen();
2469 m_preFullScreenState = this->saveState();
2470 if (m_options->widgetsIndependent) {
2471 auto doc = getCurrentDocumentPage();
2472 if(doc == nullptr)
2473 return;
2474 auto wl = doc->getWidgetLayout();
2475 wl->setVisible(true);
2476 #ifdef Q_OS_MACOS
2477 wl->showMaximized();
2478 #else
2479 wl->showFullScreen();
2480 #endif
2481 } else {
2482 this->widgetPanel->setFloating(true);
2483 #ifdef Q_OS_MACOS
2484 this->widgetPanel->showMaximized();
2485 #else
2486 this->widgetPanel->showFullScreen();
2487 #endif
2488 }
2489 m_fullScreenComponent = "widgets";
2490 }
2491 else {
2492 if(m_options->widgetsIndependent) {
2493 auto doc = getCurrentDocumentPage();
2494 if(doc == nullptr)
2495 return;
2496 doc->getWidgetLayout()->showNormal();
2497 m_fullScreenComponent = "";
2498 } else {
2499 this->restoreState(m_preFullScreenState);
2500 //this->showNormal();
2501 m_fullScreenComponent = "";
2502 }
2503
2504 }
2505 }
2506
2507
showDebugger(bool show)2508 void CsoundQt::showDebugger(bool show)
2509 {
2510 #ifdef QCS_DEBUGGER
2511 m_debugPanel->setVisible(show);
2512 #else
2513 (void) show;
2514 #endif
2515 }
2516
showVirtualKeyboard(bool show)2517 void CsoundQt::showVirtualKeyboard(bool show)
2518 {
2519 #ifdef USE_QT_GT_53
2520 if (show) {
2521 // create here to be able to be able to delete in on close and catch destroyed()
2522 // to uncheck action button
2523 m_virtualKeyboard = new QQuickWidget(this);
2524 m_virtualKeyboard->setAttribute(Qt::WA_DeleteOnClose);
2525 m_virtualKeyboardPointer = m_virtualKeyboard; // guarded pointer to check if object is alive
2526 m_virtualKeyboard->setWindowTitle(tr("CsoundQt Virtual Keyboard"));
2527 m_virtualKeyboard->setWindowFlags(Qt::Window);
2528 m_virtualKeyboard->setSource(QUrl("qrc:/QML/VirtualKeyboard.qml"));
2529 QObject *rootObject = m_virtualKeyboard->rootObject();
2530 m_virtualKeyboard->setFocus();
2531 connect(rootObject, SIGNAL(genNote(QVariant, QVariant, QVariant, QVariant)),
2532 this, SLOT(virtualMidiIn(QVariant, QVariant, QVariant, QVariant)));
2533 connect(rootObject, SIGNAL(newCCvalue(int,int,int)), this, SLOT(virtualCCIn(int, int, int)));
2534 m_virtualKeyboard->setVisible(true);
2535 connect(m_virtualKeyboard, SIGNAL(destroyed(QObject*)),
2536 this, SLOT(virtualKeyboardActOff(QObject*)));
2537 } else if (!m_virtualKeyboardPointer.isNull()) { // check if object still existing (i.e not on exit)
2538 m_virtualKeyboard->setVisible(false);
2539 m_virtualKeyboard->close();
2540 }
2541 #else
2542 QMessageBox::warning(this, tr("Qt5 Required"), tr("Qt version > 5.2 is required for the virtual keyboard."));
2543 #endif
2544 }
2545
showTableEditor(bool show)2546 void CsoundQt::showTableEditor(bool show)
2547 {
2548 #ifdef USE_QT_GT_53
2549 if (show) {
2550 m_tableEditor = new QQuickWidget(this); // create here to be able to
2551 m_tableEditor->setAttribute(Qt::WA_DeleteOnClose); // ... be able to delete in on close and catch destroyed() to uncheck action button
2552 m_tableEditorPointer = m_tableEditor; // guarded pointer to check if object is alive
2553 m_tableEditor->setWindowTitle(tr("CsoundQt table editor"));
2554 m_tableEditor->setWindowFlags(Qt::Window);
2555 m_tableEditor->setSource(QUrl("qrc:/QML/TableEditor.qml"));
2556 m_tableEditor->setResizeMode(QQuickWidget::SizeRootObjectToView);
2557 QObject *rootObject = m_tableEditor->rootObject();
2558 m_tableEditor->setFocus();
2559 connect(rootObject, SIGNAL(newSyntax(QString)), this, SLOT(handleTableSyntax(QString)));
2560 // see if selected text contains a ftgen definition, then set in the editor
2561 QString selectedText = getSelectedText();
2562 if (selectedText.contains("ftgen") && selectedText.split(",")[3].simplified()=="7") {
2563 qDebug()<<"This is a ftgen 7 definition: " << selectedText;
2564 QObject *syntaxField = rootObject->findChild<QObject*>("syntaxField");
2565 syntaxField->setProperty("text",QVariant(selectedText.simplified())); // display teh text in QML window
2566 QMetaObject::invokeMethod(rootObject, "syntax2graph",
2567 Q_ARG(QVariant, selectedText.simplified() ),
2568 Q_ARG(QVariant, 0)); // if 0, finds max from the table parameters
2569 }
2570
2571 m_tableEditor->setVisible(true);
2572 connect(m_tableEditor, SIGNAL(destroyed(QObject*)), this, SLOT(tableEditorActOff(QObject*)));
2573 } else if (!m_tableEditorPointer.isNull()) { // check if object still existing (i.e not on exit)
2574 m_tableEditor->setVisible(false);
2575 m_tableEditor->close();
2576 }
2577 #else
2578 QMessageBox::warning(this, tr("Qt5 Required"), tr("Qt version > 5.2 is required for the virtual keyboard."));
2579 #endif
2580
2581 }
2582
virtualKeyboardActOff(QObject * parent)2583 void CsoundQt::virtualKeyboardActOff(QObject *parent)
2584 {
2585 (void) parent;
2586 #ifdef USE_QT_GT_53
2587 //qDebug()<<"VirtualKeyboard destroyed";
2588 if (!m_virtualKeyboardPointer.isNull()) {
2589 // check if object still existing (i.e application not exiting)
2590 if (showVirtualKeyboardAct->isChecked()) {
2591 showVirtualKeyboardAct->setChecked(false);
2592 }
2593 }
2594 #endif
2595 }
2596
tableEditorActOff(QObject * parent)2597 void CsoundQt::tableEditorActOff(QObject *parent)
2598 {
2599 (void) parent;
2600 #ifdef USE_QT_GT_53
2601 //qDebug()<<"VirtualKeyboard destroyed";
2602 if (!m_tableEditorPointer.isNull()) { // check if object still existing (i.e application not exiting)
2603 if (showTableEditorAct->isChecked()) {
2604 showTableEditorAct->setChecked(false);
2605 }
2606 }
2607 #endif
2608 }
2609
2610
showHtml5Gui(bool show)2611 void CsoundQt::showHtml5Gui(bool show)
2612 {
2613 #if defined(QCS_QTHTML)
2614 csoundHtmlView->setVisible(show);
2615 #endif
2616 }
2617
splitView(bool split)2618 void CsoundQt::splitView(bool split)
2619 {
2620 if (split) {
2621 int mode = showOrcAct->isChecked() ? 2 : 0 ;
2622 mode |= showScoreAct->isChecked() ? 4 : 0 ;
2623 mode |= showOptionsAct->isChecked() ? 8 : 0 ;
2624 mode |= showFileBAct->isChecked() ? 16 : 0 ;
2625 mode |= showOtherAct->isChecked() ? 32 : 0 ;
2626 mode |= showOtherCsdAct->isChecked() ? 64 : 0 ;
2627 mode |= showWidgetEditAct->isChecked() ? 128 : 0 ;
2628 if (mode == 0) {
2629 mode = 2+4;
2630 }
2631 documentPages[curPage]->setViewMode(mode);
2632 }
2633 else {
2634 documentPages[curPage]->setViewMode(0);
2635 }
2636 }
2637
showMidiLearn()2638 void CsoundQt::showMidiLearn()
2639 {
2640 m_midiLearn->show();
2641 }
2642
virtualMidiIn(QVariant on,QVariant note,QVariant channel,QVariant velocity)2643 void CsoundQt::virtualMidiIn(QVariant on, QVariant note, QVariant channel, QVariant velocity)
2644 {
2645 std::vector<unsigned char> message;
2646 unsigned char status = (8 << 4) | on.toInt() << 4 | (channel.toInt() -1);
2647 message.push_back(status);
2648 message.push_back(note.toInt());
2649 message.push_back(velocity.toInt());
2650 documentPages[curPage]->queueVirtualMidiIn(message);
2651 }
2652
virtualCCIn(int channel,int cc,int value)2653 void CsoundQt::virtualCCIn(int channel, int cc, int value)
2654 {
2655 //qDebug()<<"CC event: "<<channel<< cc<<value;
2656 std::vector<unsigned char> message;
2657 unsigned char status = (11 << 4 | (channel - 1));
2658 message.push_back(status);
2659 message.push_back(cc);
2660 message.push_back(value);
2661 documentPages[curPage]->queueVirtualMidiIn(message);
2662 }
2663
handleTableSyntax(QString syntax)2664 void CsoundQt::handleTableSyntax(QString syntax)
2665 {
2666 qDebug() << syntax;
2667 insertText(syntax+"\n");
2668 }
2669
openManualExample(QString fileName)2670 void CsoundQt::openManualExample(QString fileName)
2671 {
2672 #ifdef Q_OS_WIN // on windows poper path is not forwarded. Add it if necessary.
2673 if (!fileName.startsWith(helpPanel->docDir)) {
2674 fileName = helpPanel->docDir + fileName;
2675 }
2676 #endif
2677 loadFile(fileName);
2678 }
2679
openExternalBrowser(QUrl url)2680 void CsoundQt::openExternalBrowser(QUrl url)
2681 {
2682 if (!url.isEmpty()) {
2683 if (!m_options->browser.isEmpty()) {
2684 if (QFile::exists(m_options->browser)) {
2685 execute(m_options->browser,"\"" + url.toString() + "\"");
2686 }
2687 else {
2688 QMessageBox::critical(this, tr("Error"),
2689 tr("Could not open external browser:\n%1\nPlease check preferences.").arg(m_options->browser));
2690 }
2691 }
2692 else {
2693 QDesktopServices::openUrl(url);
2694 }
2695 }
2696 else {
2697 QString dir = m_options->csdocdir.isEmpty() ? helpPanel->docDir : m_options->csdocdir ;
2698 if (!dir.isEmpty()) {
2699 url = QUrl ("file://" + dir + "/"
2700 + documentPages[curPage]->wordUnderCursor() + ".html");
2701 if (!m_options->browser.isEmpty()) {
2702 execute(m_options->browser, "\"" + url.toString() + "\"");
2703 }
2704 else {
2705 QDesktopServices::openUrl(url);
2706 }
2707 }
2708 else {
2709 QMessageBox::critical(this,
2710 tr("Error"),
2711 tr("HTML Documentation directory not set!\n"
2712 "Please go to Edit->Options->Environment and select directory\n"));
2713 }
2714 }
2715 }
2716
openPdfFile(QString name)2717 void CsoundQt::openPdfFile(QString name)
2718 {
2719 if (!m_options->pdfviewer.isEmpty()) {
2720 #ifndef Q_OS_MACOS
2721 if (!QFile::exists(m_options->pdfviewer)) {
2722 QMessageBox::critical(this,
2723 tr("Error"),
2724 tr("PDF viewer not found!\n"
2725 "Please go to Edit->Options->Environment and select directory\n"));
2726 }
2727 #endif
2728 QString arg = "\"" + name + "\"";
2729 // qDebug() << arg;
2730 execute(m_options->pdfviewer, arg);
2731 }
2732 else {
2733 QDesktopServices::openUrl(QUrl::fromLocalFile (name));
2734 }
2735 }
2736
openFLOSSManual()2737 void CsoundQt::openFLOSSManual()
2738 {
2739 openExternalBrowser(QUrl("http://en.flossmanuals.net/csound/"));
2740 }
2741
openQuickRef()2742 void CsoundQt::openQuickRef()
2743 {
2744 openPdfFile(quickRefFileName);
2745 }
2746
openOnlineDocumentation()2747 void CsoundQt::openOnlineDocumentation()
2748 {
2749 openExternalBrowser(QUrl("http://csoundqt.github.io/pages/documentation.html"));
2750 }
2751
resetPreferences()2752 void CsoundQt::resetPreferences()
2753 {
2754 int ret = QMessageBox::question (this, tr("Reset Preferences"),
2755 tr("Are you sure you want to revert CsoundQt's "
2756 "preferences\nto their initial default values? "),
2757 QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok);
2758 if (ret == QMessageBox::Ok) {
2759 m_resetPrefs = true;
2760 storeSettings();
2761 QMessageBox::information(this, tr("Reset Preferences"),
2762 tr("Preferences have been reset.\nYou must restart CsoundQt."),
2763 QMessageBox::Ok, QMessageBox::Ok);
2764 }
2765 }
2766
reportBug()2767 void CsoundQt::reportBug()
2768 {
2769 QUrl url("https://github.com/CsoundQt/CsoundQt/issues/new");
2770 if (!m_options->browser.isEmpty()) {
2771 execute(m_options->browser,"\"" + url.toString() + "\"");
2772 }
2773 else {
2774 QDesktopServices::openUrl(url);
2775 }
2776 }
2777
requestFeature()2778 void CsoundQt::requestFeature()
2779 {
2780 QUrl url("https://github.com/CsoundQt/CsoundQt/issues/new");
2781 if (!m_options->browser.isEmpty()) {
2782 execute(m_options->browser,"\"" + url.toString() + "\"");
2783 }
2784 else {
2785 QDesktopServices::openUrl(url);
2786 }
2787 }
2788
chat()2789 void CsoundQt::chat()
2790 {
2791 QUrl url("http://webchat.freenode.net/?channels=#csound");
2792 if (!m_options->browser.isEmpty()) {
2793 execute(m_options->browser,"\"" + url.toString() + "\"");
2794 }
2795 else {
2796 QDesktopServices::openUrl(url);
2797 }
2798 }
2799
openShortcutDialog()2800 void CsoundQt::openShortcutDialog()
2801 {
2802 KeyboardShortcuts dialog(this, m_keyActions);
2803 connect(&dialog, SIGNAL(restoreDefaultShortcuts()), this, SLOT(setDefaultKeyboardShortcuts()));
2804 dialog.exec();
2805 }
2806
downloadManual()2807 void CsoundQt::downloadManual()
2808 {
2809 // NB! must be updated when new manual comes out!
2810 openExternalBrowser(QUrl("https://github.com/csound/csound/releases/download/6.14.0/Csound6.14.0_manual_html.zip"));
2811 QMessageBox::information(this, tr("Set manual path"),
2812 tr("Unzip the manual to any location and set that path"
2813 " in Configure/Enviromnent/Html doc directory"));
2814 }
2815
about()2816 void CsoundQt::about()
2817 {
2818 About *msgBox = new About(this);
2819 msgBox->setWindowFlags(msgBox->windowFlags() | Qt::FramelessWindowHint);
2820 QString text ="<h1>";
2821 text += tr("by: Andres Cabrera, Tarmo Johannes, Eduardo Moguillansky and others") +"</h1><h2>",
2822 text += tr("Version %1").arg(QCS_VERSION) + "</h2><h2>";
2823 text += tr("Released under the LGPLv2 or GPLv3") + "</h2>";
2824 text += tr("Using Csound version:") + QString::number(csoundGetVersion()) + " ";
2825 text += tr("Precision:") + (csoundGetSizeOfMYFLT() == 8 ? "double (64-bit)" : "float (32-bit)") + "<br />";
2826 #ifdef QCS_PYTHONQT
2827 text += tr("Built with PythonQt support.")+ "<br />";
2828 #endif
2829 #ifdef USE_WEBENGINE
2830 text += tr("Html5 support based on QtWebEngine")+"<br />";
2831 #endif
2832 #ifdef USE_WEBKIT
2833 text += tr("Html5 support based on QtWebkit")+"<br />";
2834 #endif
2835 text += "<br />";
2836 text += tr("Spanish translation: Andrés Cabrera and Guillermo Senna") + "<br />";
2837 text += tr("French translation: François Pinot") + "<br />";
2838 text += tr("German translation: Joachim Heintz") + "<br />";
2839 text += tr("Portuguese translation: Victor Lazzarini") + "<br />";
2840 text += tr("Italian translation: Francesco") + "<br />";
2841 text += tr("Turkish translation: Ali Isciler") + "<br />";
2842 text += tr("Finnish translation: Niko Humalamäki") + "<br />";
2843 text += tr("Russian translation: Gleb Rogozinsky") + "<br />";
2844 text += tr("Persian translation: Amin Khoshsabk") + "<br />";
2845 text += tr("Korean translation: Jieun Jun") + "<br />";
2846 text += QString("<center><a href=\"http://csoundqt.github.io\">csoundqt.github.io</a></center>");
2847 text += QString("<center><a href=\"mailto:mantaraya36@gmail.com\">mantaraya36@gmail.com</a><br /> <a href=\"mailto:trmjhnns@gmail.com\">trmjhnns@gmail.com</a> </center><br />");
2848 text += tr("If you find CsoundQt useful, please consider donating to the project:");
2849 text += "<center><a href=\"http://sourceforge.net/donate/index.php?group_id=227265\">Support this project!</a></center><br>";
2850
2851 text += tr("Please file bug reports and feature suggestions in the ");
2852 text += "<a href=\"https://github.com/CsoundQt/CsoundQt/issues\">";
2853 text += tr("CsoundQt tracker") + "</a>.<br><br />";
2854
2855 text +=tr("Mailing Lists:");
2856 text += "<br /><a href=\"http://lists.sourceforge.net/lists/listinfo/qutecsound-users\">Join/Read CsoundQt Mailing List</a><br />";
2857 text += "<a href=\"http://lists.sourceforge.net/lists/listinfo/qutecsound-devel\">Join/Read CsoundQt Developer List</a><br />";
2858 text += "<a href=\"https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND\">Join/Read Csound Mailing List</a><br />";
2859 text += "<a href=\"https://listserv.heanet.ie/cgi-bin/wa?A0=CSOUND-DEV\"> Join/Read Csound Developer List</a><br />";
2860
2861 text += "<br />"+ tr("Other Resources:") + "<br />";
2862 text += "<a href=\"http://csound.github.io\">Csound official homepage</a><br />";
2863 text += "<a href=\"http://www.csoundjournal.com/\">Csound Journal</a><br />";
2864 text += "<a href=\"http://csound.noisepages.com/\">The Csound Blog</a><br />";
2865 text += "<br />" + tr("Supported by:") +"<br />";
2866 text += "<a href=\"http://www.incontri.hmtm-hannover.de/\">Incontri - HMTM Hannover</a><br />";
2867 text += "<a href=\"http://sourceforge.net/project/project_donations.php?group_id=227265\">";
2868 text += tr("And other generous users.") + "</a><br />";
2869
2870 msgBox->getTextEdit()->setOpenLinks(false);
2871 msgBox->setHtmlText(text);
2872 connect(msgBox->getTextEdit(), SIGNAL(anchorClicked(QUrl)), this, SLOT(openExternalBrowser(QUrl)));
2873 msgBox->exec();
2874 delete msgBox;
2875 }
2876
donate()2877 void CsoundQt::donate()
2878 {
2879 openExternalBrowser(QUrl("http://sourceforge.net/donate/index.php?group_id=227265"));
2880 }
2881
documentWasModified()2882 void CsoundQt::documentWasModified()
2883 {
2884 setWindowModified(true);
2885 // qDebug() << "CsoundQt::documentWasModified()";
2886 documentTabs->setTabIcon(curPage, modIcon);
2887 }
2888
configure()2889 void CsoundQt::configure()
2890 {
2891 ConfigDialog dialog(this, m_options, &m_configlists);
2892 dialog.setCurrentTab(configureTab);
2893 // dialog.newParserCheckBox->setEnabled(csoundGetVersion() > 5125);
2894 dialog.multicoreCheckBox->setEnabled(csoundGetVersion() > 5125);
2895 dialog.numThreadsSpinBox->setEnabled(csoundGetVersion() > 5125);
2896 connect(dialog.applyButton, SIGNAL(released()),
2897 this, SLOT(applySettings()));
2898 connect(&dialog, SIGNAL(disableInternalRtMidi()),
2899 this, SLOT(disableInternalRtMidi()) );
2900 connect(dialog.testAudioSetupButton, SIGNAL(released()),
2901 this, SLOT(testAudioSetup()));
2902 if (dialog.exec() == QDialog::Accepted) {
2903 applySettings();
2904 storeSettings();
2905 }
2906 configureTab = dialog.currentTab();
2907 }
2908
applySettings()2909 void CsoundQt::applySettings()
2910 {
2911 // This is called at initialization, when clicking "apply" in the settings dialog
2912 // and when closing it with "OK"
2913 for (int i = 0; i < documentPages.size(); i++) {
2914 setCurrentOptionsForPage(documentPages[i]);
2915 }
2916 auto toolButtonStyle = (m_options->iconText ? Qt::ToolButtonTextUnderIcon :
2917 Qt::ToolButtonIconOnly);
2918
2919 // setUnifiedTitleAndToolBarOnMac(m_options->iconText);
2920 // fileToolBar->setToolButtonStyle(toolButtonStyle);
2921 // editToolBar->setToolButtonStyle(toolButtonStyle);
2922 controlToolBar->setToolButtonStyle(toolButtonStyle);
2923 configureToolBar->setToolButtonStyle(toolButtonStyle);
2924 // fileToolBar->setVisible(m_options->showToolbar);
2925 // editToolBar->setVisible(m_options->showToolbar);
2926 controlToolBar->setVisible(m_options->showToolbar);
2927 configureToolBar->setVisible(m_options->showToolbar);
2928 controlToolBar->setMovable(!(m_options->lockToolbar));
2929 configureToolBar->setMovable(!(m_options->lockToolbar));
2930
2931 QString currentOptions = (m_options->useAPI ? tr("API") : tr("Console")) + " ";
2932 // if (m_options->useAPI) {
2933 // currentOptions += (m_options->thread ? tr("Thread") : tr("NoThread")) + " ";
2934 // }
2935
2936 // Display a summary of options on the status bar
2937 currentOptions += (m_options->saveWidgets ? tr("SaveWidgets") : tr("DontSaveWidgets")) + " ";
2938 QString playOptions = " (Audio:" + m_options->rtAudioModule + " ";
2939 playOptions += "MIDI:" + m_options->rtMidiModule + ")";
2940 playOptions += " (" + (m_options->rtUseOptions ? tr("UseCsoundQtOptions"):
2941 tr("DiscardCsoundQtOptions"));
2942 playOptions += " " + (m_options->rtOverrideOptions? tr("OverrideCsOptions"): tr("")) + ") ";
2943 playOptions += currentOptions;
2944 QString renderOptions =
2945 " ("
2946 + (m_options->fileUseOptions? tr("UseCsoundQtOptions"): tr("DiscardCsoundQtOptions"))
2947 + " ";
2948 renderOptions += "" + (m_options->fileOverrideOptions? tr("OverrideCsOptions"): tr("")) + ") ";
2949 renderOptions += currentOptions;
2950 runAct->setStatusTip(tr("Play") + playOptions);
2951 renderAct->setStatusTip(tr("Render to file") + renderOptions);
2952
2953 if (! m_options->useCsoundMidi) {
2954 QString interfaceNotFoundMessage;
2955 // find midi interface by name; if not found, set to None
2956 // returns 9999 if not found
2957 m_options->midiInterface = midiHandler->findMidiInPortByName(m_options->midiInterfaceName);
2958 midiHandler->setMidiInterface(m_options->midiInterface);
2959 // close port, if 9999
2960 if (m_options->midiInterface==9999 && !m_options->midiInterfaceName.contains("None")) {
2961 qDebug()<<"MIDI In interface "<< m_options->midiInterfaceName << " not found!";
2962 interfaceNotFoundMessage = tr("MIDI In interface ") +
2963 m_options->midiInterfaceName +
2964 tr(" not found!\n Switching to None.\n");
2965 }
2966
2967 m_options->midiOutInterface = midiHandler->findMidiOutPortByName(m_options->midiOutInterfaceName);
2968 midiHandler->setMidiOutInterface(m_options->midiOutInterface);
2969 if (m_options->midiOutInterface == 9999 && !m_options->midiOutInterfaceName.contains("None")) {
2970 qDebug()<<"MIDI Out interface "<< m_options->midiOutInterfaceName << " not found!";
2971 interfaceNotFoundMessage += tr("MIDI Out interface ") +
2972 m_options->midiOutInterfaceName +
2973 tr(" not found!\n Switching to None.");
2974 }
2975 // if (!interfaceNotFoundMessage.isEmpty()) { // probably messagebox alwais is a bit too disturbing. Keep it quiet.
2976 // QMessageBox::warning(this, tr("MIDI interface not found"),
2977 // interfaceNotFoundMessage);
2978 // }
2979 }
2980
2981 fillFavoriteMenu();
2982 fillScriptsMenu();
2983 DocumentView *pad = static_cast<LiveCodeEditor*>(m_scratchPad->widget())->getDocumentView();
2984 pad->setFont(QFont(m_options->font, (int) m_options->fontPointSize));
2985 if (csoundGetVersion() < 5140) {
2986 m_options->newParser = -1; // Don't use new parser flags
2987 }
2988 setupEnvironment();
2989
2990 // set editorBgColor also for inspector, codepad and python console.
2991 // Maybe the latter should use the same color as console?
2992 auto bgColor= m_options->editorBgColor.name();
2993 m_inspector->setStyleSheet(QString("QTreeWidget { background-color: %1; }").arg(bgColor));
2994 m_scratchPad->setStyleSheet(QString("QTextEdit { background-color: %1; }").arg(bgColor));
2995 this->setToolbarIconSize(m_options->toolbarIconSize);
2996 #ifdef QCS_PYTHONQT
2997 m_pythonConsole->setStyleSheet(QString("QTextEdit { background-color: %1; }").arg(m_options->editorBgColor.name()));
2998 #endif
2999 //storeSettings(); // save always when something new is changed
3000 }
3001
setCurrentOptionsForPage(DocumentPage * p)3002 void CsoundQt::setCurrentOptionsForPage(DocumentPage *p)
3003 {
3004 p->setColorVariables(m_options->colorVariables);
3005 p->setTabStopWidth(m_options->tabWidth);
3006 p->setTabIndents(m_options->tabIndents);
3007 p->setLineWrapMode(m_options->wrapLines ? QTextEdit::WidgetWidth : QTextEdit::NoWrap);
3008 p->setAutoComplete(m_options->autoComplete);
3009 p->setAutoParameterMode(m_options->autoParameterMode);
3010 p->setWidgetEnabled(m_options->enableWidgets);
3011 p->showWidgetTooltips(m_options->showTooltips);
3012 p->setKeyRepeatMode(m_options->keyRepeat);
3013 p->setOpenProperties(m_options->openProperties);
3014 p->setFontOffset(m_options->fontOffset);
3015 p->setFontScaling(m_options->fontScaling);
3016 p->setGraphUpdateRate(m_options->graphUpdateRate);
3017 p->setDebugLiveEvents(m_options->debugLiveEvents);
3018 p->setTextFont(QFont(m_options->font,
3019 (int) m_options->fontPointSize));
3020 p->setLineEnding(m_options->lineEnding);
3021 p->setConsoleFont(QFont(m_options->consoleFont,
3022 (int) m_options->consoleFontPointSize));
3023 p->setConsoleColors(m_options->consoleFontColor,
3024 m_options->consoleBgColor);
3025 // p->setEditorBgColor(m_options->editorBgColor);
3026 p->setScriptDirectory(m_options->pythonDir);
3027 p->setPythonExecutable(m_options->pythonExecutable);
3028 p->useOldFormat(m_options->oldFormat);
3029 p->setConsoleBufferSize(m_options->consoleBufferSize);
3030 p->showLineNumbers(m_options->showLineNumberArea);
3031 p->setHighlightingTheme(m_options->highlightingTheme);
3032
3033 int flags = m_options->noBuffer ? QCS_NO_COPY_BUFFER : 0;
3034 flags |= m_options->noPython ? QCS_NO_PYTHON_CALLBACK : 0;
3035 flags |= m_options->noMessages ? QCS_NO_CONSOLE_MESSAGES : 0;
3036 flags |= m_options->noEvents ? QCS_NO_RT_EVENTS : 0;
3037 p->setFlags(flags);
3038 }
3039
runUtility(QString flags)3040 void CsoundQt::runUtility(QString flags)
3041 {
3042 qDebug("CsoundQt::runUtility");
3043 if (m_options->useAPI) {
3044 #ifdef MACOSX_PRE_SNOW
3045 //Remember menu bar to set it after FLTK grabs it
3046 menuBarHandle = GetMenuBar();
3047 #endif
3048 // m_console->reset();
3049 static char *argv[33];
3050 QString name = "";
3051 QString fileFlags = flags.mid(flags.indexOf("\""));
3052 flags.remove(fileFlags);
3053 QStringList indFlags= flags.split(" ",QString::SkipEmptyParts);
3054 QStringList files = fileFlags.split("\"", QString::SkipEmptyParts);
3055 if (indFlags.size() < 2) {
3056 qDebug("CsoundQt::runUtility: Error: empty flags");
3057 return;
3058 }
3059 if (indFlags[0] == "-U") {
3060 indFlags.removeAt(0);
3061 name = indFlags[0];
3062 indFlags.removeAt(0);
3063 }
3064 else {
3065 qDebug("CsoundQt::runUtility: Error: unexpected flag!");
3066 return;
3067 }
3068 int index = 0;
3069 foreach (QString flag, indFlags) {
3070 argv[index] = (char *) calloc(flag.size()+1, sizeof(char));
3071 strcpy(argv[index], flag.toLocal8Bit());
3072 index++;
3073 }
3074 argv[index] = (char *) calloc(files[0].size()+1, sizeof(char));
3075 strcpy(argv[index++], files[0].toLocal8Bit());
3076 argv[index] = (char *) calloc(files[2].size()+1, sizeof(char));
3077 strcpy(argv[index++],files[2].toLocal8Bit());
3078 int argc = index;
3079 CSOUND *csoundU;
3080 csoundU=csoundCreate(0);
3081 csoundSetHostData(csoundU, (void *) m_console);
3082 csoundSetMessageCallback(csoundU, &CsoundQt::utilitiesMessageCallback);
3083 // Utilities always run in the same thread as CsoundQt
3084 csoundRunUtility(csoundU, name.toLocal8Bit(), argc, argv);
3085 csoundDestroy(csoundU);
3086 for (int i = 0; i < argc; i++) {
3087 free(argv[i]);
3088 }
3089 #ifdef MACOSX_PRE_SNOW
3090 // Put menu bar back
3091 SetMenuBar(menuBarHandle);
3092 #endif
3093 }
3094 else {
3095 QString script;
3096 #ifdef Q_OS_WIN32
3097 script = "";
3098 #ifdef USE_DOUBLE
3099 if (m_options->opcodedir64Active)
3100 script += "set OPCODEDIR64=" + m_options->opcodedir64 + "\n";
3101 if (m_options->opcode6dir64Active)
3102 script += "set OPCODE6DIR64=" + m_options->opcode6dir64 + "\n";
3103 #else
3104 if (m_options->opcodedirActive)
3105 script += "set OPCODEDIR=" + m_options->opcodedir + "\n";
3106 #endif
3107 // Only OPCODEDIR left here as it must be present before csound initializes
3108
3109 script += "cd " + QFileInfo(documentPages[curPage]->getFileName()).absolutePath() + "\n";
3110 script += "csound " + flags + "\n";
3111 #else
3112 script = "#!/bin/sh\n";
3113 #ifdef USE_DOUBLE
3114 if (m_options->opcodedir64Active)
3115 script += "set OPCODEDIR64=" + m_options->opcodedir64 + "\n";
3116 if (m_options->opcode6dir64Active)
3117 script += "set OPCODE6DIR64=" + m_options->opcode6dir64 + "\n";
3118 #else
3119 if (m_options->opcodedirActive)
3120 script += "export OPCODEDIR=" + m_options->opcodedir + "\n";
3121 #endif
3122 // Only OPCODEDIR left here as it must be present before csound initializes
3123
3124 script += "cd " + QFileInfo(documentPages[curPage]->getFileName()).absolutePath() + "\n";
3125 #ifdef Q_OS_MACOS
3126 script += "/usr/local/bin/csound " + flags + "\n";
3127 #else
3128 script += "csound " + flags + "\n";
3129 #endif
3130 script += "echo \"\nPress return to continue\"\n";
3131 script += "dummy_var=\"\"\n";
3132 script += "read dummy_var\n";
3133 script += "rm $0\n";
3134 #endif
3135 QFile file(SCRIPT_NAME);
3136 if (!file.open(QIODevice::WriteOnly))
3137 return;
3138
3139 QTextStream out(&file);
3140 out << script;
3141 file.flush();
3142 file.close();
3143 file.setPermissions (QFile::ExeOwner| QFile::WriteOwner| QFile::ReadOwner);
3144
3145 QString options;
3146 #ifdef Q_OS_LINUX
3147 options = "-e " + SCRIPT_NAME;
3148 #endif
3149 #ifdef Q_OS_FREEBSD
3150 options = "-e " + SCRIPT_NAME;
3151 #endif
3152 #ifdef Q_OS_SOLARIS
3153 options = "-e " + SCRIPT_NAME;
3154 #endif
3155 #ifdef Q_OS_MACOS
3156 options = SCRIPT_NAME;
3157 #endif
3158 #ifdef Q_OS_WIN32
3159 options = SCRIPT_NAME;
3160 #endif
3161 execute(m_options->terminal, options);
3162 }
3163 }
3164
3165
updateCurrentPageTask()3166 void CsoundQt::updateCurrentPageTask() {
3167 if (m_closing) {
3168 return; // And don't call this again from the timer
3169 }
3170 Q_ASSERT(documentPages.size() > curPage);
3171 auto currentPage = documentPages[curPage];
3172 if ( !currentPage->getFileName().toLower().endsWith(".udo") ) { // otherwise this marks an unedited .udo file as edited
3173 currentPage->parseUdos();
3174 }
3175 QTimer::singleShot(INSPECTOR_UPDATE_PERIOD_MS, this, SLOT(updateCurrentPageTask()));
3176 }
3177
3178
updateInspector()3179 void CsoundQt::updateInspector()
3180 {
3181 if (m_closing) {
3182 return; // And don't call this again from the timer
3183 }
3184 Q_ASSERT(documentPages.size() > curPage);
3185 if (!m_inspectorNeedsUpdate) {
3186 QTimer::singleShot(INSPECTOR_UPDATE_PERIOD_MS, this, SLOT(updateInspector()));
3187 return; // Retrigger timer, but do no update
3188 }
3189 if (!documentPages[curPage]->getFileName().endsWith(".py")) {
3190 m_inspector->parseText(documentPages[curPage]->getBasicText());
3191 }
3192 else {
3193 m_inspector->parsePythonText(documentPages[curPage]->getBasicText());
3194 }
3195 m_inspectorNeedsUpdate = false;
3196 // this->setParsedUDOs();
3197 QTimer::singleShot(INSPECTOR_UPDATE_PERIOD_MS, this, SLOT(updateInspector()));
3198 }
3199
markInspectorUpdate()3200 void CsoundQt::markInspectorUpdate()
3201 {
3202 // qDebug() << "CsoundQt::markInspectorUpdate()";
3203 m_inspectorNeedsUpdate = true;
3204 }
3205
setDefaultKeyboardShortcuts()3206 void CsoundQt::setDefaultKeyboardShortcuts()
3207 {
3208 // m_keyActions.append(createCodeGraphAct);
3209 newAct->setShortcut(tr("Ctrl+N"));
3210 openAct->setShortcut(tr("Ctrl+O"));
3211 reloadAct->setShortcut(tr("Alt+R"));
3212 saveAct->setShortcut(tr("Ctrl+S"));
3213 saveAsAct->setShortcut(tr("Shift+Ctrl+S"));
3214 createAppAct->setShortcut(tr(""));
3215 closeTabAct->setShortcut(tr("Ctrl+W"));
3216
3217 printAct->setShortcut(tr("Ctrl+P"));
3218 exitAct->setShortcut(tr("Ctrl+Q"));
3219
3220 undoAct->setShortcut(tr("Ctrl+Z"));
3221 redoAct->setShortcut(tr("Shift+Ctrl+Z"));
3222
3223 cutAct->setShortcut(tr("Ctrl+X"));
3224 copyAct->setShortcut(tr("Ctrl+C"));
3225 pasteAct->setShortcut(tr("Ctrl+V"));
3226 duplicateAct->setShortcut(tr("Ctrl+D"));
3227 joinAct->setShortcut(tr(""));
3228 inToGetAct->setShortcut(tr(""));
3229 getToInAct->setShortcut(tr(""));
3230 csladspaAct->setShortcut(tr(""));
3231 findAct->setShortcut(tr("Ctrl+F"));
3232 findAgainAct->setShortcut(tr("Ctrl+G"));
3233 configureAct->setShortcut(tr("Ctrl+,"));
3234 editAct->setShortcut(tr("CTRL+E"));
3235 runAct->setShortcut(tr("CTRL+R"));
3236 runTermAct->setShortcut(QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_T));
3237 pauseAct->setShortcut(tr("Ctrl+Shift+M"));
3238
3239 stopAct->setShortcut(tr("Ctrl+."));
3240 stopAllAct->setShortcut(QKeySequence(Qt::CTRL+Qt::SHIFT+Qt::Key_Period));
3241
3242 recAct->setShortcut(tr("Ctrl+Space"));
3243 renderAct->setShortcut(tr("Alt+F"));
3244 externalPlayerAct->setShortcut(tr(""));
3245 externalEditorAct->setShortcut(tr(""));
3246 focusEditorAct->setShortcut(tr("Ctrl+0"));
3247 raiseHelpAct->setShortcut(tr("Ctrl+2"));
3248 raiseWidgetsAct->setShortcut(tr("Ctrl+1"));
3249 showGenAct->setShortcut(tr(""));
3250 showOverviewAct->setShortcut(tr(""));
3251 raiseConsoleAct->setShortcut(tr("Ctrl+3"));
3252 #ifdef Q_OS_MACOS
3253 viewFullScreenAct->setShortcut(tr("Ctrl+Shift+F"));
3254 #else
3255 viewFullScreenAct->setShortcut(tr("F11"));
3256 #endif
3257
3258 viewEditorFullScreenAct->setShortcut(tr("Alt+Ctrl+0"));
3259 #ifdef QCS_QTHTML
3260 viewHtmlFullScreenAct->setShortcut(tr("Alt+Ctrl+4")); // was H
3261 #endif
3262 viewHelpFullScreenAct->setShortcut(tr("Alt+Ctrl+2")); // was vice versa
3263 viewWidgetsFullScreenAct->setShortcut(tr("Alt+Ctrl+1"));
3264 #ifdef QCS_DEBUGGER
3265 showDebugAct->setShortcut(tr("F5"));
3266 #endif
3267 showVirtualKeyboardAct->setShortcut(tr("Ctrl+Shift+V"));
3268 showTableEditorAct->setShortcut(tr(""));
3269 splitViewAct->setShortcut(tr("Ctrl+Shift+A"));
3270 midiLearnAct->setShortcut(tr("Ctrl+Shift+M"));
3271 createCodeGraphAct->setShortcut(tr("")); // was Ctr +4 save it for html view
3272 raiseInspectorAct->setShortcut(tr("Ctrl+5"));
3273 showLiveEventsAct->setShortcut(tr("Ctrl+6"));
3274
3275 #ifdef QCS_QTHTML
3276 raiseHtml5Act->setShortcut(tr("Ctrl+4")); // Alt-4 was before for Code graph
3277 #endif
3278 openDocumentationAct->setShortcut(tr("F1"));
3279 showUtilitiesAct->setShortcut(tr("Ctrl+9"));
3280
3281 setHelpEntryAct->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_F1));
3282 externalBrowserAct->setShortcut(tr("Shift+Alt+F1"));
3283 showInspectorAct->setShortcut(tr("F5"));
3284
3285 browseBackAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Left));
3286 browseForwardAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Right));
3287 openQuickRefAct->setShortcut(tr(""));
3288 commentAct->setShortcut(tr("Ctrl+/"));
3289 // uncommentAct->setShortcut(tr("Shift+Ctrl+/"));
3290 indentAct->setShortcut(tr("Ctrl+I"));
3291 unindentAct->setShortcut(tr("Shift+Ctrl+I"));
3292 evaluateAct->setShortcut(tr("Shift+Ctrl+E"));
3293 evaluateSectionAct->setShortcut(tr("Shift+Ctrl+W"));
3294 scratchPadCsdModeAct->setShortcut(tr("Shift+Alt+S"));
3295 raisePythonConsoleAct->setShortcut(tr("Ctrl+7"));
3296 raiseScratchPadAct->setShortcut(tr("Ctrl+8"));
3297 killLineAct->setShortcut(tr("Ctrl+K"));
3298 killToEndAct->setShortcut(tr("Shift+Alt+K"));
3299 gotoLineAct->setShortcut(tr("Ctrl+L"));
3300 goBackAct->setShortcut(QKeySequence(Qt::ALT + Qt::Key_Left));
3301 showOrcAct->setShortcut(tr("Shift+Alt+1"));
3302 showScoreAct->setShortcut(tr("Shift+Alt+2"));
3303 showOptionsAct->setShortcut(tr("Shift+Alt+3"));
3304 showFileBAct->setShortcut(tr("Shift+Alt+4"));
3305 showOtherAct->setShortcut(tr("Shift+Alt+5"));
3306 showOtherCsdAct->setShortcut(tr("Shift+Alt+6"));
3307 showWidgetEditAct->setShortcut(tr("Shift+Alt+7"));
3308 lineNumbersAct->setShortcut(tr("Shift+Alt+L"));
3309 parameterModeAct->setShortcut(tr("Shift+Alt+P"));
3310 cabbageAct->setShortcut(tr("Shift+Ctrl+C"));
3311 // showParametersAct->setShortcut(tr("Alt+P"));
3312
3313 checkSyntaxAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U));
3314
3315 storeSettings();
3316 }
3317
showNoPythonQtWarning()3318 void CsoundQt::showNoPythonQtWarning()
3319 {
3320 QMessageBox::warning(this, tr("No PythonQt support"),
3321 tr("This version of CsoundQt has been compiled without PythonQt support.\n"
3322 "Extended Python features are not available"));
3323 qDebug() << "CsoundQt::showNoPythonQtWarning()";
3324 }
3325
showOrc(bool show)3326 void CsoundQt::showOrc(bool show)
3327 {
3328 documentPages[curPage]->showOrc(show);
3329 }
3330
showScore(bool show)3331 void CsoundQt::showScore(bool show)
3332 {
3333 documentPages[curPage]->showScore(show);
3334 }
3335
showOptions(bool show)3336 void CsoundQt::showOptions(bool show)
3337 {
3338 documentPages[curPage]->showOptions(show);
3339 }
3340
showFileB(bool show)3341 void CsoundQt::showFileB(bool show)
3342 {
3343 documentPages[curPage]->showFileB(show);
3344 }
3345
showOther(bool show)3346 void CsoundQt::showOther(bool show)
3347 {
3348 documentPages[curPage]->showOther(show);
3349 }
3350
showOtherCsd(bool show)3351 void CsoundQt::showOtherCsd(bool show)
3352 {
3353 documentPages[curPage]->showOtherCsd(show);
3354 }
3355
showWidgetEdit(bool show)3356 void CsoundQt::showWidgetEdit(bool show)
3357 {
3358 documentPages[curPage]->showWidgetEdit(show);
3359 }
3360
toggleLineArea()3361 void CsoundQt::toggleLineArea()
3362 {
3363 documentPages[curPage]->toggleLineArea();
3364 }
3365
toggleParameterMode()3366 void CsoundQt::toggleParameterMode()
3367 {
3368 documentPages[curPage]->toggleParameterMode();
3369 }
3370
3371 #ifdef QCS_DEBUGGER
3372
runDebugger()3373 void CsoundQt::runDebugger()
3374 {
3375 m_debugEngine = documentPages[curPage]->getEngine();
3376 m_debugEngine->setDebug();
3377
3378 m_debugPanel->setDebugFilename(documentPages[curPage]->getFileName());
3379 connect(m_debugEngine, SIGNAL(breakpointReached()),
3380 this, SLOT(breakpointReached()));
3381 connect(m_debugPanel, SIGNAL(stopSignal()),
3382 this, SLOT(stopDebugger()));
3383 m_debugEngine->setStartingBreakpoints(m_debugPanel->getBreakpoints());
3384
3385 documentPages[curPage]->getView()->m_mainEditor->setCurrentDebugLine(-1);
3386 play();
3387 }
3388
stopDebugger()3389 void CsoundQt::stopDebugger()
3390 {
3391 if (m_debugEngine) {
3392 disconnect(m_debugEngine, SIGNAL(breakpointReached()), 0, 0);
3393 disconnect(m_debugPanel, SIGNAL(stopSignal()), 0, 0);
3394 m_debugEngine->stopDebug();
3395 m_debugEngine = 0;
3396 documentPages[curPage]->getView()->m_mainEditor->setCurrentDebugLine(-1);
3397 }
3398 markStopped();
3399 }
3400
pauseDebugger()3401 void CsoundQt::pauseDebugger()
3402 {
3403 if(m_debugEngine) {
3404 m_debugEngine->pauseDebug();
3405 }
3406 }
3407
continueDebugger()3408 void CsoundQt::continueDebugger()
3409 {
3410 if(m_debugEngine) {
3411 m_debugEngine->continueDebug();
3412 documentPages[curPage]->getView()->m_mainEditor->setCurrentDebugLine(-1);
3413 }
3414 }
3415
addBreakpoint(int line,int instr,int skip)3416 void CsoundQt::addBreakpoint(int line, int instr, int skip)
3417 {
3418 if (instr == 0) {
3419 documentPages[curPage]->getView()->m_mainEditor->markDebugLine(line);
3420 }
3421 if(m_debugEngine) {
3422 m_debugEngine->addBreakpoint(line, instr, skip);
3423 }
3424 }
3425
addInstrumentBreakpoint(double instr,int skip)3426 void CsoundQt::addInstrumentBreakpoint(double instr, int skip)
3427 {
3428 if(m_debugEngine) {
3429 m_debugEngine->addInstrumentBreakpoint(instr, skip);
3430 }
3431 }
3432
removeBreakpoint(int line,int instr)3433 void CsoundQt::removeBreakpoint(int line, int instr)
3434 {
3435 if (instr == 0) {
3436 documentPages[curPage]->getView()->m_mainEditor->unmarkDebugLine(line);
3437 }
3438 if(m_debugEngine) {
3439 m_debugEngine->removeBreakpoint(line, instr);
3440 }
3441 }
3442
removeInstrumentBreakpoint(double instr)3443 void CsoundQt::removeInstrumentBreakpoint(double instr)
3444 {
3445 if(m_debugEngine) {
3446 m_debugEngine->removeInstrumentBreakpoint(instr);
3447 }
3448 }
3449
3450 #endif
3451
3452 //void CsoundQt::showParametersInEditor()
3453 //{
3454 // documentPages[curPage]->showParametersInEditor();
3455 //}
3456
createActions()3457 void CsoundQt::createActions()
3458 {
3459 // Actions that are not connected here depend on the active document, so they are
3460 // connected with connectActions() and are changed when the document changes.
3461 QString theme = m_options->theme;
3462 QString prefix = ":/themes/" + theme + "/";
3463 newAct = new QAction(QIcon(prefix + "gtk-new.png"), tr("&New"), this);
3464 newAct->setStatusTip(tr("Create a new file"));
3465 newAct->setIconText(tr("New"));
3466 newAct->setShortcutContext(Qt::ApplicationShortcut);
3467 connect(newAct, SIGNAL(triggered()), this, SLOT(newFile()));
3468
3469 openAct = new QAction(QIcon(prefix + "gnome-folder.png"), tr("&Open..."), this);
3470 openAct->setStatusTip(tr("Open an existing file"));
3471 openAct->setIconText(tr("Open"));
3472 openAct->setShortcutContext(Qt::ApplicationShortcut);
3473 connect(openAct, SIGNAL(triggered()), this, SLOT(open()));
3474
3475 reloadAct = new QAction(QIcon(prefix + "gtk-reload.png"), tr("Reload"), this);
3476 reloadAct->setStatusTip(tr("Reload file from disk, discarding changes"));
3477 // reloadAct->setIconText(tr("Reload"));
3478 reloadAct->setShortcutContext(Qt::ApplicationShortcut);
3479 connect(reloadAct, SIGNAL(triggered()), this, SLOT(reload()));
3480
3481 saveAct = new QAction(QIcon(prefix + "gnome-dev-floppy.png"), tr("&Save"), this);
3482 saveAct->setStatusTip(tr("Save the document to disk"));
3483 saveAct->setIconText(tr("Save"));
3484 saveAct->setShortcutContext(Qt::ApplicationShortcut);
3485 connect(saveAct, SIGNAL(triggered()), this, SLOT(save()));
3486
3487 saveAsAct = new QAction(tr("Save &As..."), this);
3488 saveAsAct->setStatusTip(tr("Save the document under a new name"));
3489 saveAsAct->setIconText(tr("Save as"));
3490 saveAsAct->setShortcutContext(Qt::ApplicationShortcut);
3491 connect(saveAsAct, SIGNAL(triggered()), this, SLOT(saveAs()));
3492
3493 createAppAct = new QAction(tr("Create App..."), this);
3494 createAppAct->setStatusTip(tr("Create Standalone application"));
3495 createAppAct->setShortcutContext(Qt::ApplicationShortcut);
3496 connect(createAppAct, SIGNAL(triggered()), this, SLOT(createApp()));
3497
3498 saveNoWidgetsAct = new QAction(tr("Export without widgets"), this);
3499 saveNoWidgetsAct->setStatusTip(tr("Save to new file without including widget sections"));
3500 // saveNoWidgetsAct->setIconText(tr("Save as"));
3501 saveNoWidgetsAct->setShortcutContext(Qt::ApplicationShortcut);
3502 connect(saveNoWidgetsAct, SIGNAL(triggered()), this, SLOT(saveNoWidgets()));
3503
3504 closeTabAct = new QAction(tr("Close current tab"), this);
3505 closeTabAct->setStatusTip(tr("Close current tab"));
3506 // closeTabAct->setIconText(tr("Close"));
3507 closeTabAct->setIcon(QIcon(prefix + "gtk-close.png"));
3508 closeTabAct->setShortcutContext(Qt::ApplicationShortcut);
3509 connect(closeTabAct, SIGNAL(triggered()), this, SLOT(closeTab()));
3510
3511 printAct = new QAction(tr("Print"), this);
3512 printAct->setStatusTip(tr("Print current document"));
3513 // printAct->setIconText(tr("Print"));
3514 // closeTabAct->setIcon(QIcon(prefix + "gtk-close.png"));
3515 printAct->setShortcutContext(Qt::ApplicationShortcut);
3516 connect(printAct, SIGNAL(triggered()), this, SLOT(print()));
3517
3518 // for (int i = 0; i < QCS_MAX_RECENT_FILES; i++) {
3519 // QAction *newAction = new QAction(this);
3520 // openRecentAct.append(newAction);
3521 // connect(newAction, SIGNAL(triggered()), this, SLOT(openFromAction()));
3522 // }
3523
3524 infoAct = new QAction(tr("File Information"), this);
3525 infoAct->setStatusTip(tr("Show information for the current file"));
3526 // exitAct->setIconText(tr("Exit"));
3527 infoAct->setShortcutContext(Qt::ApplicationShortcut);
3528 connect(infoAct, SIGNAL(triggered()), this, SLOT(info()));
3529
3530 exitAct = new QAction(tr("E&xit"), this);
3531 exitAct->setStatusTip(tr("Exit the application"));
3532 // exitAct->setIconText(tr("Exit"));
3533 exitAct->setShortcutContext(Qt::ApplicationShortcut);
3534 connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));
3535
3536 createCodeGraphAct = new QAction(tr("View Code &Graph"), this);
3537 createCodeGraphAct->setStatusTip(tr("View Code Graph"));
3538 // createCodeGraphAct->setIconText("Exit");
3539 createCodeGraphAct->setShortcutContext(Qt::ApplicationShortcut);
3540 connect(createCodeGraphAct, SIGNAL(triggered()), this, SLOT(createCodeGraph()));
3541
3542 undoAct = new QAction(QIcon(prefix + "gtk-undo.png"), tr("Undo"), this);
3543 undoAct->setStatusTip(tr("Undo last action"));
3544 undoAct->setIconText(tr("Undo"));
3545 undoAct->setShortcutContext(Qt::ApplicationShortcut);
3546 connect(undoAct, SIGNAL(triggered()), this, SLOT(undo()));
3547
3548 redoAct = new QAction(QIcon(prefix + "gtk-redo.png"), tr("Redo"), this);
3549 redoAct->setStatusTip(tr("Redo last action"));
3550 redoAct->setIconText(tr("Redo"));
3551 redoAct->setShortcutContext(Qt::ApplicationShortcut);
3552 connect(redoAct, SIGNAL(triggered()), this, SLOT(redo()));
3553
3554 cutAct = new QAction(QIcon(prefix + "gtk-cut.png"), tr("Cu&t"), this);
3555 cutAct->setStatusTip(tr("Cut the current selection's contents to the "
3556 "clipboard"));
3557 cutAct->setIconText(tr("Cut"));
3558 cutAct->setShortcutContext(Qt::ApplicationShortcut);
3559 connect(cutAct, SIGNAL(triggered()), this, SLOT(cut()));
3560
3561 copyAct = new QAction(QIcon(prefix + "gtk-copy.png"), tr("&Copy"), this);
3562 copyAct->setStatusTip(tr("Copy the current selection's contents to the "
3563 "clipboard"));
3564 copyAct->setIconText(tr("Copy"));
3565 copyAct->setShortcutContext(Qt::ApplicationShortcut);
3566 connect(copyAct, SIGNAL(triggered()), this, SLOT(copy()));
3567
3568 pasteAct = new QAction(QIcon(prefix + "gtk-paste.png"), tr("&Paste"), this);
3569 pasteAct->setStatusTip(tr("Paste the clipboard's contents into the current "
3570 "selection"));
3571 pasteAct->setIconText(tr("Paste"));
3572 pasteAct->setShortcutContext(Qt::ApplicationShortcut);
3573 connect(pasteAct, SIGNAL(triggered()), this, SLOT(paste()));
3574
3575 joinAct = new QAction(/*QIcon(prefix + "gtk-paste.png"),*/ tr("&Join orc/sco"), this);
3576 joinAct->setStatusTip(tr("Join orc/sco files in a single csd file"));
3577 // joinAct->setIconText(tr("Join"));
3578 joinAct->setShortcutContext(Qt::ApplicationShortcut);
3579 connect(joinAct, SIGNAL(triggered()), this, SLOT(join()));
3580
3581 evaluateAct = new QAction(/*QIcon(prefix + "gtk-paste.png"),*/ tr("Evaluate selection"), this);
3582 evaluateAct->setStatusTip(tr("Evaluate selection in Python Console"));
3583 evaluateAct->setShortcutContext(Qt::ApplicationShortcut);
3584 connect(evaluateAct, SIGNAL(triggered()), this, SLOT(evaluate()));
3585
3586 evaluateSectionAct = new QAction(/*QIcon(prefix + "gtk-paste.png"),*/ tr("Evaluate section"), this);
3587 evaluateSectionAct->setStatusTip(tr("Evaluate current section in Python Console"));
3588 evaluateSectionAct->setShortcutContext(Qt::ApplicationShortcut);
3589 connect(evaluateSectionAct, SIGNAL(triggered()), this, SLOT(evaluateSection()));
3590
3591 scratchPadCsdModeAct = new QAction(tr("Code Pad in Csound Mode"), this);
3592 scratchPadCsdModeAct->setStatusTip(tr("Toggle the mode for the scratch pad between python and csound"));
3593 scratchPadCsdModeAct->setShortcutContext(Qt::ApplicationShortcut);
3594 scratchPadCsdModeAct->setCheckable(true);
3595 connect(scratchPadCsdModeAct, SIGNAL(toggled(bool)), this, SLOT(setScratchPadMode(bool)));
3596
3597 inToGetAct = new QAction(/*QIcon(prefix + "gtk-paste.png"),*/ tr("Invalue->Chnget"), this);
3598 inToGetAct->setStatusTip(tr("Convert invalue/outvalue to chnget/chnset"));
3599 inToGetAct->setShortcutContext(Qt::ApplicationShortcut);
3600 connect(inToGetAct, SIGNAL(triggered()), this, SLOT(inToGet()));
3601
3602 getToInAct = new QAction(/*QIcon(prefix + "gtk-paste.png"),*/ tr("Chnget->Invalue"), this);
3603 getToInAct->setStatusTip(tr("Convert chnget/chnset to invalue/outvalue"));
3604 getToInAct->setShortcutContext(Qt::ApplicationShortcut);
3605 connect(getToInAct, SIGNAL(triggered()), this, SLOT(getToIn()));
3606
3607 csladspaAct = new QAction(/*QIcon(prefix + "gtk-paste.png"),*/ tr("Insert/Update CsLADSPA text"), this);
3608 csladspaAct->setStatusTip(tr("Insert/Update CsLADSPA section to csd file"));
3609 csladspaAct->setShortcutContext(Qt::ApplicationShortcut);
3610 connect(csladspaAct, SIGNAL(triggered()), this, SLOT(updateCsladspaText()));
3611
3612 cabbageAct = new QAction(/*QIcon(prefix + "gtk-paste.png"),*/ tr("Insert/Update Cabbage text"), this);
3613 cabbageAct->setStatusTip(tr("Insert/Update Cabbage section to csd file"));
3614 cabbageAct->setShortcutContext(Qt::ApplicationShortcut);
3615 connect(cabbageAct, SIGNAL(triggered()), this, SLOT(updateCabbageText()));
3616
3617 qmlAct = new QAction(/*QIcon(prefix + "gtk-paste.png"),*/ tr("Export widgets to QML"), this);
3618 qmlAct->setStatusTip(tr("Export widgets in QML format"));
3619 qmlAct->setShortcutContext(Qt::ApplicationShortcut);
3620 connect(qmlAct, SIGNAL(triggered()), this, SLOT(saveWidgetsToQml()));
3621
3622 findAct = new QAction(/*QIcon(prefix + "gtk-paste.png"),*/ tr("&Find and Replace"), this);
3623 findAct->setStatusTip(tr("Find and replace strings in file"));
3624 // findAct->setIconText(tr("Find"));
3625 findAct->setShortcutContext(Qt::ApplicationShortcut);
3626 connect(findAct, SIGNAL(triggered()), this, SLOT(findReplace()));
3627
3628 findAgainAct = new QAction(/*QIcon(prefix + "gtk-paste.png"),*/ tr("Find again"), this);
3629 findAgainAct->setStatusTip(tr("Find next appearance of string"));
3630 // findAct->setIconText(tr("Find"));
3631 findAgainAct->setShortcutContext(Qt::ApplicationShortcut);
3632 connect(findAgainAct, SIGNAL(triggered()), this, SLOT(findString()));
3633
3634 configureAct = new QAction(QIcon(prefix + "control-center2.png"), tr("Configuration"), this);
3635 configureAct->setStatusTip(tr("Open configuration dialog"));
3636 configureAct->setIconText(tr("Configure"));
3637 configureAct->setShortcutContext(Qt::ApplicationShortcut);
3638 connect(configureAct, SIGNAL(triggered()), this, SLOT(configure()));
3639
3640 editAct = new QAction(/*QIcon(prefix + "gtk-media-play-ltr.png"),*/ tr("Widget Edit Mode"), this);
3641 editAct->setStatusTip(tr("Activate Edit Mode for Widget Panel"));
3642 // editAct->setIconText("Play");
3643 editAct->setCheckable(true);
3644 editAct->setShortcutContext(Qt::ApplicationShortcut);
3645 connect(editAct, SIGNAL(triggered(bool)), this, SLOT(setWidgetEditMode(bool)));
3646
3647 runAct = new QAction(QIcon(prefix + "gtk-media-play-ltr.png"), tr("Run Csound"), this);
3648 runAct->setStatusTip(tr("Run current file"));
3649 runAct->setIconText(tr("Run"));
3650 runAct->setCheckable(true);
3651 runAct->setShortcutContext(Qt::ApplicationShortcut);
3652 connect(runAct, SIGNAL(triggered()), this, SLOT(play()));
3653
3654 runTermAct = new QAction(QIcon(prefix + "gtk-media-play-ltr2.png"), tr("Run in Terminal"), this);
3655 runTermAct->setStatusTip(tr("Run in external shell"));
3656 runTermAct->setIconText(tr("Run in Term"));
3657 runTermAct->setShortcutContext(Qt::ApplicationShortcut);
3658 connect(runTermAct, SIGNAL(triggered()), this, SLOT(runInTerm()));
3659
3660 stopAct = new QAction(QIcon(prefix + "gtk-media-stop.png"), tr("Stop"), this);
3661 stopAct->setStatusTip(tr("Stop"));
3662 stopAct->setIconText(tr("Stop"));
3663 stopAct->setShortcutContext(Qt::ApplicationShortcut);
3664 connect(stopAct, SIGNAL(triggered()), this, SLOT(stop()));
3665
3666 pauseAct = new QAction(QIcon(prefix + "gtk-media-pause.png"), tr("Pause"), this);
3667 pauseAct->setStatusTip(tr("Pause"));
3668 pauseAct->setIconText(tr("Pause"));
3669 pauseAct->setShortcutContext(Qt::ApplicationShortcut);
3670 connect(pauseAct, SIGNAL(triggered()), this, SLOT(pause()));
3671
3672 stopAllAct = new QAction(QIcon(prefix + "gtk-media-stop.png"), tr("Stop All"), this);
3673 stopAllAct->setStatusTip(tr("Stop all running documents"));
3674 stopAllAct->setIconText(tr("Stop All"));
3675 stopAllAct->setShortcutContext(Qt::ApplicationShortcut);
3676 connect(stopAllAct, SIGNAL(triggered()), this, SLOT(stopAll()));
3677
3678 recAct = new QAction(QIcon(prefix + "gtk-media-record.png"), tr("Record"), this);
3679 recAct->setStatusTip(tr("Record"));
3680 recAct->setIconText(tr("Record"));
3681 recAct->setCheckable(true);
3682 recAct->setShortcutContext(Qt::ApplicationShortcut);
3683 recAct->setChecked(false);
3684 connect(recAct, SIGNAL(toggled(bool)), this, SLOT(record(bool)));
3685
3686 renderAct = new QAction(QIcon(prefix + "render.png"), tr("Render to file"), this);
3687 renderAct->setStatusTip(tr("Render to file"));
3688 renderAct->setIconText(tr("Render"));
3689 renderAct->setShortcutContext(Qt::ApplicationShortcut);
3690 connect(renderAct, SIGNAL(triggered()), this, SLOT(render()));
3691
3692 testAudioSetupAct = new QAction(QIcon(prefix+"hearing.svg"),
3693 tr("Test Audio Setup"), this);
3694 connect(testAudioSetupAct, SIGNAL(triggered(bool)), this, SLOT(testAudioSetup()));
3695
3696 checkSyntaxAct = new QAction(QIcon(prefix + "scratchpad.png"), tr("Check Syntax"), this);
3697 checkSyntaxAct->setShortcutContext(Qt::ApplicationShortcut);
3698 connect(checkSyntaxAct, SIGNAL(triggered()), this, SLOT(checkSyntaxMenuAction()));
3699
3700 externalPlayerAct = new QAction(QIcon(prefix + "playfile.png"), tr("Play Rendered Audiofile"), this);
3701 externalPlayerAct->setStatusTip(tr("Play rendered audiofile in external application"));
3702 externalPlayerAct->setIconText(tr("Ext. Player"));
3703 externalPlayerAct->setShortcutContext(Qt::ApplicationShortcut);
3704 connect(externalPlayerAct, SIGNAL(triggered()), this, SLOT(openExternalPlayer()));
3705
3706 externalEditorAct = new QAction(QIcon(prefix + "editfile.png"), tr("Edit Rendered Audiofile"), this);
3707 externalEditorAct->setStatusTip(tr("Edit rendered audiofile in External Editor"));
3708 externalEditorAct->setIconText(tr("Ext. Editor"));
3709 externalEditorAct->setShortcutContext(Qt::ApplicationShortcut);
3710 connect(externalEditorAct, SIGNAL(triggered()), this, SLOT(openExternalEditor()));
3711
3712 showWidgetsAct = new QAction(QIcon(prefix + "gnome-mime-application-x-diagram.png"),
3713 tr("Widgets"), this);
3714 showWidgetsAct->setCheckable(true);
3715 //showWidgetsAct->setChecked(true);
3716 showWidgetsAct->setStatusTip(tr("Show Realtime Widgets"));
3717 showWidgetsAct->setIconText(tr("Widgets"));
3718 showWidgetsAct->setShortcutContext(Qt::ApplicationShortcut);
3719
3720 raiseWidgetsAct = new QAction(this);
3721 raiseWidgetsAct->setText(tr("Show/Raise Widgets Panel"));
3722 raiseWidgetsAct->setShortcutContext(Qt::ApplicationShortcut);
3723 connect(raiseWidgetsAct, SIGNAL(triggered()), focusMapper, SLOT(map()));
3724 focusMapper->setMapping(raiseWidgetsAct, 1);
3725 this->addAction(raiseWidgetsAct);
3726
3727 showInspectorAct = new QAction(QIcon(prefix + "edit-find.png"), tr("Inspector"), this);
3728 showInspectorAct->setCheckable(true);
3729 showInspectorAct->setStatusTip(tr("Show Inspector"));
3730 showInspectorAct->setIconText(tr("Inspector"));
3731 showInspectorAct->setShortcutContext(Qt::ApplicationShortcut);
3732 connect(showInspectorAct, SIGNAL(triggered(bool)), m_inspector, SLOT(setVisible(bool)));
3733 connect(m_inspector, SIGNAL(Close(bool)), showInspectorAct, SLOT(setChecked(bool)));
3734
3735 raiseInspectorAct = new QAction(this);
3736 raiseInspectorAct->setText(tr("Show/Raise Inspector Panel"));
3737 raiseInspectorAct->setShortcutContext(Qt::ApplicationShortcut);
3738 connect(raiseInspectorAct, SIGNAL(triggered()), focusMapper, SLOT(map()));
3739 focusMapper->setMapping(raiseInspectorAct, 5);
3740 this->addAction(raiseInspectorAct);
3741
3742 focusEditorAct = new QAction(tr("Focus Text Editor", "Give keyboard focus to the text editor"), this);
3743 focusEditorAct->setStatusTip(tr("Give keyboard focus to the text editor"));
3744 focusEditorAct->setIconText(tr("Editor"));
3745 focusEditorAct->setShortcutContext(Qt::ApplicationShortcut);
3746 connect(focusEditorAct, SIGNAL(triggered()), this, SLOT(setEditorFocus()));
3747
3748 showHelpAct = new QAction(QIcon(prefix + "gtk-info.png"), tr("Help Panel"), this);
3749 showHelpAct->setCheckable(true);
3750 showHelpAct->setChecked(true);
3751 showHelpAct->setStatusTip(tr("Show the Csound Manual Panel"));
3752 showHelpAct->setIconText(tr("Manual"));
3753 showHelpAct->setShortcutContext(Qt::ApplicationShortcut);
3754 // connect(showHelpAct, SIGNAL(toggled(bool)), helpPanel, SLOT(setVisible(bool)));
3755 connect(showHelpAct, SIGNAL(toggled(bool)), helpPanel, SLOT(setVisibleAndRaise(bool)));
3756 connect(helpPanel, SIGNAL(Close(bool)), showHelpAct, SLOT(setChecked(bool)));
3757
3758 raiseHelpAct = new QAction(this);
3759 raiseHelpAct->setText(tr("Show/Raise help panel"));
3760 raiseHelpAct->setShortcutContext(Qt::ApplicationShortcut);
3761 connect(raiseHelpAct, SIGNAL(triggered()), focusMapper, SLOT(map()));
3762 focusMapper->setMapping(raiseHelpAct, 2);
3763 connect(focusMapper, SIGNAL(mapped(int)), this, SLOT(focusToTab(int)));
3764 this->addAction(raiseHelpAct);
3765
3766 showLiveEventsAct = new QAction(QIcon(prefix + "note.png"), tr("Live Events"), this);
3767 showLiveEventsAct->setCheckable(true);
3768 // showLiveEventsAct->setChecked(true); // Unnecessary because it is set by options
3769 showLiveEventsAct->setStatusTip(tr("Show Live Events Panels"));
3770 showLiveEventsAct->setIconText(tr("Live Events"));
3771 showLiveEventsAct->setShortcutContext(Qt::ApplicationShortcut);
3772
3773 showPythonConsoleAct = new QAction(QIcon(prefix + "pyroom.png"), tr("Python Console"), this);
3774 showPythonConsoleAct->setCheckable(true);
3775 // showPythonConsoleAct->setChecked(true); // Unnecessary because it is set by options
3776 showPythonConsoleAct->setStatusTip(tr("Show Python Console"));
3777 showPythonConsoleAct->setIconText(tr("Python"));
3778 showPythonConsoleAct->setShortcutContext(Qt::ApplicationShortcut);
3779 #ifdef QCS_PYTHONQT
3780 connect(showPythonConsoleAct, SIGNAL(triggered(bool)), m_pythonConsole, SLOT(setVisible(bool)));
3781 connect(m_pythonConsole, SIGNAL(Close(bool)), showPythonConsoleAct, SLOT(setChecked(bool)));
3782 #else
3783 connect(showPythonConsoleAct, SIGNAL(triggered()), this, SLOT(showNoPythonQtWarning()));
3784 #endif
3785
3786 raisePythonConsoleAct = new QAction(this);
3787 raisePythonConsoleAct->setText(tr("Show/Raise Python Console"));
3788 raisePythonConsoleAct->setShortcutContext(Qt::ApplicationShortcut);
3789 connect(raisePythonConsoleAct, SIGNAL(triggered()), focusMapper, SLOT(map()));
3790 focusMapper->setMapping(raisePythonConsoleAct, 7);
3791 this->addAction(raisePythonConsoleAct);
3792
3793 showScratchPadAct = new QAction(QIcon(prefix + "scratchpad.png"), tr("CodePad"), this);
3794 showScratchPadAct->setCheckable(true);
3795 // showPythonConsoleAct->setChecked(true); // Unnecessary because it is set by options
3796 showScratchPadAct->setStatusTip(tr("Show Code Pad"));
3797 showScratchPadAct->setIconText(tr("CodePad"));
3798 showScratchPadAct->setShortcutContext(Qt::ApplicationShortcut);
3799 connect(showScratchPadAct, SIGNAL(triggered(bool)), m_scratchPad, SLOT(setVisible(bool)));
3800 connect(m_scratchPad, SIGNAL(visibilityChanged(bool)), showScratchPadAct, SLOT(setChecked(bool)));
3801
3802 raiseScratchPadAct = new QAction(this);
3803 raiseScratchPadAct->setText(tr("Show/Raise Code Pad"));
3804 raiseScratchPadAct->setShortcutContext(Qt::ApplicationShortcut);
3805 connect(raiseScratchPadAct, SIGNAL(triggered()), focusMapper, SLOT(map()));
3806 focusMapper->setMapping(raiseScratchPadAct, 8);
3807 this->addAction(raiseScratchPadAct);
3808
3809 showManualAct = new QAction(/*QIcon(prefix + "gtk-info.png"), */tr("Csound Manual"), this);
3810 showManualAct->setStatusTip(tr("Show the Csound manual in the help panel"));
3811 showManualAct->setShortcutContext(Qt::ApplicationShortcut);
3812 connect(showManualAct, SIGNAL(triggered()), helpPanel, SLOT(showManual()));
3813
3814 downloadManualAct = new QAction(/*QIcon(prefix + "gtk-info.png"), */tr("Download Csound Manual"), this);
3815 downloadManualAct->setStatusTip(tr("Download latest Csound manual"));
3816 downloadManualAct->setShortcutContext(Qt::ApplicationShortcut);
3817 connect(downloadManualAct, SIGNAL(triggered()), this, SLOT(downloadManual()));
3818
3819
3820 showGenAct = new QAction(/*QIcon(prefix + "gtk-info.png"), */tr("GEN Routines"), this);
3821 showGenAct->setStatusTip(tr("Show the GEN Routines Manual page"));
3822 showGenAct->setShortcutContext(Qt::ApplicationShortcut);
3823 connect(showGenAct, SIGNAL(triggered()), helpPanel, SLOT(showGen()));
3824
3825 showOverviewAct = new QAction(/*QIcon(prefix + "gtk-info.png"), */tr("Opcode Overview"), this);
3826 showOverviewAct->setStatusTip(tr("Show opcode overview"));
3827 showOverviewAct->setShortcutContext(Qt::ApplicationShortcut);
3828 connect(showOverviewAct, SIGNAL(triggered()), helpPanel, SLOT(showOverview()));
3829
3830 showOpcodeQuickRefAct = new QAction(/*QIcon(prefix + "gtk-info.png"), */tr("Opcode Quick Reference"), this);
3831 showOpcodeQuickRefAct->setStatusTip(tr("Show opcode quick reference page"));
3832 showOpcodeQuickRefAct->setShortcutContext(Qt::ApplicationShortcut);
3833 connect(showOpcodeQuickRefAct, SIGNAL(triggered()), helpPanel, SLOT(showOpcodeQuickRef()));
3834
3835 showConsoleAct = new QAction(QIcon(prefix + "gksu-root-terminal.png"), tr("Output Console"), this);
3836 showConsoleAct->setCheckable(true);
3837 showConsoleAct->setChecked(true);
3838 showConsoleAct->setStatusTip(tr("Show Csound's message console"));
3839 showConsoleAct->setIconText(tr("Console"));
3840 showConsoleAct->setShortcutContext(Qt::ApplicationShortcut);
3841 connect(showConsoleAct, SIGNAL(toggled(bool)), m_console, SLOT(setVisible(bool)));
3842 connect(m_console, SIGNAL(Close(bool)), showConsoleAct, SLOT(setChecked(bool)));
3843
3844 raiseConsoleAct = new QAction(this);
3845 raiseConsoleAct->setText(tr("Show/Raise Console"));
3846 raiseConsoleAct->setShortcutContext(Qt::ApplicationShortcut);
3847 connect(raiseConsoleAct, SIGNAL(triggered()), focusMapper, SLOT(map()));
3848 focusMapper->setMapping(raiseConsoleAct, 3);
3849 this->addAction(raiseConsoleAct);
3850
3851 viewFullScreenAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("View Fullscreen"), this);
3852 viewFullScreenAct->setCheckable(true);
3853 viewFullScreenAct->setChecked(false);
3854 viewFullScreenAct->setStatusTip(tr("Have CsoundQt occupy all available screen space"));
3855 viewFullScreenAct->setShortcutContext(Qt::ApplicationShortcut);
3856 connect(viewFullScreenAct, SIGNAL(toggled(bool)), this, SLOT(setFullScreen(bool)));
3857
3858 viewEditorFullScreenAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("View Editor Fullscreen"), this);
3859 viewEditorFullScreenAct->setCheckable(true);
3860 viewEditorFullScreenAct->setChecked(false);
3861 viewEditorFullScreenAct->setStatusTip(tr("Have the editor occupy all available screen space"));
3862 viewEditorFullScreenAct->setShortcutContext(Qt::ApplicationShortcut);
3863 connect(viewEditorFullScreenAct, SIGNAL(toggled(bool)), this, SLOT(setEditorFullScreen(bool)));
3864
3865 #ifdef QCS_QTHTML
3866 viewHtmlFullScreenAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("View HTML Fullscreen"), this);
3867 viewHtmlFullScreenAct->setCheckable(true);
3868 viewHtmlFullScreenAct->setChecked(false);
3869 viewHtmlFullScreenAct->setStatusTip(tr("Have the HTML page occupy all available screen space"));
3870 viewHtmlFullScreenAct->setShortcutContext(Qt::ApplicationShortcut);
3871 connect(viewHtmlFullScreenAct, SIGNAL(toggled(bool)), this, SLOT(setHtmlFullScreen(bool)));
3872 #endif
3873 viewHelpFullScreenAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("View Help Fullscreen"), this);
3874 viewHelpFullScreenAct->setCheckable(true);
3875 viewHelpFullScreenAct->setChecked(false);
3876 viewHelpFullScreenAct->setStatusTip(tr("Have the help page occupy all available screen space"));
3877 viewHelpFullScreenAct->setShortcutContext(Qt::ApplicationShortcut);
3878 connect(viewHelpFullScreenAct, SIGNAL(toggled(bool)), this, SLOT(setHelpFullScreen(bool)));
3879
3880 viewWidgetsFullScreenAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("View Widgets Fullscreen"), this);
3881 viewWidgetsFullScreenAct->setCheckable(true);
3882 viewWidgetsFullScreenAct->setChecked(false);
3883 viewWidgetsFullScreenAct->setStatusTip(tr("Have the widgets panel occupy all available screen space"));
3884 viewWidgetsFullScreenAct->setShortcutContext(Qt::ApplicationShortcut);
3885 connect(viewWidgetsFullScreenAct, SIGNAL(toggled(bool)), this, SLOT(setWidgetsFullScreen(bool)));
3886
3887 #ifdef QCS_DEBUGGER
3888 showDebugAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("Show debugger"), this);
3889 showDebugAct->setCheckable(true);
3890 showDebugAct->setChecked(false);
3891 showDebugAct->setStatusTip(tr("Show the Csound debugger"));
3892 showDebugAct->setShortcutContext(Qt::ApplicationShortcut);
3893 connect(showDebugAct, SIGNAL(toggled(bool)), this, SLOT(showDebugger(bool)));
3894 #endif
3895 showVirtualKeyboardAct = new QAction(QIcon(prefix + "midi_keyboard.png"), tr("Show Virtual Keyboard"), this);
3896 showVirtualKeyboardAct->setCheckable(true);
3897 showVirtualKeyboardAct->setChecked(false);
3898 showVirtualKeyboardAct->setStatusTip(tr("Show the Virtual MIDI Keyboard"));
3899 showVirtualKeyboardAct->setIconText(tr("Keyboard"));
3900 showVirtualKeyboardAct->setShortcutContext(Qt::ApplicationShortcut);
3901 connect(showVirtualKeyboardAct, SIGNAL(toggled(bool)), this, SLOT(showVirtualKeyboard(bool)));
3902
3903 showTableEditorAct = new QAction(tr("Show Table editor"), this);
3904 showTableEditorAct->setCheckable(true); // TODO: make it clickable, ie not checkable
3905 showTableEditorAct->setChecked(false);
3906 showTableEditorAct->setStatusTip(tr("Show Table editor"));
3907 showTableEditorAct->setIconText(tr("Table editor"));
3908 showTableEditorAct->setShortcutContext(Qt::ApplicationShortcut);
3909 connect(showTableEditorAct, SIGNAL(toggled(bool)), this, SLOT(showTableEditor(bool)));
3910
3911
3912 #if defined(QCS_QTHTML)
3913 showHtml5Act = new QAction(QIcon(":/images/html5.png"), tr("HTML View"), this);
3914 showHtml5Act->setIconText(tr("HTML"));
3915 showHtml5Act->setCheckable(true);
3916 showHtml5Act->setChecked(true);
3917 showHtml5Act->setStatusTip(tr("Show the HTML view"));
3918 showHtml5Act->setShortcutContext(Qt::ApplicationShortcut);
3919 connect(showHtml5Act, SIGNAL(toggled(bool)), this, SLOT(showHtml5Gui(bool)));
3920 //connect(csoundHtmlView, SIGNAL(Close(bool)), showHtml5Act, SLOT(setChecked(bool)));
3921
3922 raiseHtml5Act = new QAction(this);
3923 raiseHtml5Act->setText(tr("Show/Raise HtmlView"));
3924 raiseHtml5Act->setShortcutContext(Qt::ApplicationShortcut);
3925 connect(raiseHtml5Act, SIGNAL(triggered()), focusMapper, SLOT(map()));
3926 focusMapper->setMapping(raiseHtml5Act, 4);
3927 this->addAction(raiseHtml5Act);
3928 #endif
3929 splitViewAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("Split View"), this);
3930 splitViewAct->setCheckable(true);
3931 splitViewAct->setChecked(false);
3932 splitViewAct->setStatusTip(tr("Toggle between full csd and split text display"));
3933 splitViewAct->setShortcutContext(Qt::ApplicationShortcut);
3934 connect(splitViewAct, SIGNAL(toggled(bool)), this, SLOT(splitView(bool)));
3935
3936 midiLearnAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("MIDI Learn"), this);
3937 midiLearnAct->setStatusTip(tr("Show MIDI Learn Window for widgets"));
3938 midiLearnAct->setShortcutContext(Qt::ApplicationShortcut);
3939 connect(midiLearnAct, SIGNAL(triggered()), this, SLOT(showMidiLearn()));
3940
3941 showOrcAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("Show Orchestra"), this);
3942 showOrcAct->setCheckable(true);
3943 showOrcAct->setChecked(true);
3944 showOrcAct->setEnabled(false);
3945 showOrcAct->setStatusTip(tr("Show orchestra panel in split view"));
3946 showOrcAct->setShortcutContext(Qt::ApplicationShortcut);
3947 connect(showOrcAct, SIGNAL(toggled(bool)), this, SLOT(showOrc(bool)));
3948 connect(splitViewAct, SIGNAL(toggled(bool)), showOrcAct, SLOT(setEnabled(bool)));
3949
3950 showScoreAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("Show Score"), this);
3951 showScoreAct->setCheckable(true);
3952 showScoreAct->setChecked(true);
3953 showScoreAct->setEnabled(false);
3954 showScoreAct->setStatusTip(tr("Show orchestra panel in split view"));
3955 showScoreAct->setShortcutContext(Qt::ApplicationShortcut);
3956 connect(showScoreAct, SIGNAL(toggled(bool)), this, SLOT(showScore(bool)));
3957 connect(splitViewAct, SIGNAL(toggled(bool)), showScoreAct, SLOT(setEnabled(bool)));
3958
3959 showOptionsAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("Show CsOptions"), this);
3960 showOptionsAct->setCheckable(true);
3961 showOptionsAct->setChecked(true);
3962 showOptionsAct->setEnabled(false);
3963 showOptionsAct->setStatusTip(tr("Show CsOptions section panel in split view"));
3964 showOptionsAct->setShortcutContext(Qt::ApplicationShortcut);
3965 connect(showOptionsAct, SIGNAL(toggled(bool)), this, SLOT(showOptions(bool)));
3966 connect(splitViewAct, SIGNAL(toggled(bool)), showOptionsAct, SLOT(setEnabled(bool)));
3967
3968 showFileBAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("Show Embedded files"), this);
3969 showFileBAct->setCheckable(true);
3970 showFileBAct->setChecked(false);
3971 showFileBAct->setEnabled(false);
3972 showFileBAct->setStatusTip(tr("Show Embedded files panel in split view"));
3973 showFileBAct->setShortcutContext(Qt::ApplicationShortcut);
3974 connect(showFileBAct, SIGNAL(toggled(bool)), this, SLOT(showFileB(bool)));
3975 connect(splitViewAct, SIGNAL(toggled(bool)), showFileBAct, SLOT(setEnabled(bool)));
3976
3977 showOtherAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("Show Information Text"), this);
3978 showOtherAct->setCheckable(true);
3979 showOtherAct->setChecked(false);
3980 showOtherAct->setEnabled(false);
3981 showOtherAct->setStatusTip(tr("Show information text panel in split view"));
3982 showOtherAct->setShortcutContext(Qt::ApplicationShortcut);
3983 connect(showOtherAct, SIGNAL(toggled(bool)), this, SLOT(showOther(bool)));
3984 connect(splitViewAct, SIGNAL(toggled(bool)), showOtherAct, SLOT(setEnabled(bool)));
3985
3986 showOtherCsdAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("Show Extra Tags"), this);
3987 showOtherCsdAct->setCheckable(true);
3988 showOtherCsdAct->setChecked(false);
3989 showOtherCsdAct->setEnabled(false);
3990 showOtherCsdAct->setStatusTip(tr("Show extra tags panel in split view"));
3991 showOtherCsdAct->setShortcutContext(Qt::ApplicationShortcut);
3992 connect(showOtherCsdAct, SIGNAL(toggled(bool)), this, SLOT(showOtherCsd(bool)));
3993 connect(splitViewAct, SIGNAL(toggled(bool)), showOtherCsdAct, SLOT(setEnabled(bool)));
3994
3995 showWidgetEditAct = new QAction(/*QIcon(prefix + "gksu-root-terminal.png"),*/ tr("Show Widgets Text"), this);
3996 showWidgetEditAct->setCheckable(true);
3997 showWidgetEditAct->setChecked(false);
3998 showWidgetEditAct->setEnabled(false);
3999 showWidgetEditAct->setStatusTip(tr("Show Widgets text panel in split view"));
4000 showWidgetEditAct->setShortcutContext(Qt::ApplicationShortcut);
4001 connect(showWidgetEditAct, SIGNAL(toggled(bool)), this, SLOT(showWidgetEdit(bool)));
4002 connect(splitViewAct, SIGNAL(toggled(bool)), showWidgetEditAct, SLOT(setEnabled(bool)));
4003
4004 setHelpEntryAct = new QAction(QIcon(prefix + "gtk-info.png"), tr("Opcode Entry"), this);
4005 setHelpEntryAct->setStatusTip(tr("Show Opcode Entry in help panel"));
4006 setHelpEntryAct->setIconText(tr("Manual for opcode"));
4007 setHelpEntryAct->setShortcutContext(Qt::ApplicationShortcut);
4008 connect(setHelpEntryAct, SIGNAL(triggered()), this, SLOT(setHelpEntry()));
4009
4010 browseBackAct = new QAction(tr("Help Back"), this);
4011 browseBackAct->setStatusTip(tr("Go back in help page"));
4012 browseBackAct->setShortcutContext(Qt::ApplicationShortcut);
4013 connect(browseBackAct, SIGNAL(triggered()), helpPanel, SLOT(browseBack()));
4014
4015 browseForwardAct = new QAction(tr("Help Forward"), this);
4016 browseForwardAct->setStatusTip(tr("Go forward in help page"));
4017 browseForwardAct->setShortcutContext(Qt::ApplicationShortcut);
4018 connect(browseForwardAct, SIGNAL(triggered()), helpPanel, SLOT(browseForward()));
4019
4020 externalBrowserAct = new QAction(/*QIcon(prefix + "gtk-info.png"), */ tr("Opcode Entry in External Browser"), this);
4021 externalBrowserAct->setStatusTip(tr("Show Opcode Entry in external browser"));
4022 externalBrowserAct->setShortcutContext(Qt::ApplicationShortcut);
4023 connect(externalBrowserAct, SIGNAL(triggered()), this, SLOT(openExternalBrowser()));
4024
4025 openDocumentationAct = new QAction(/*QIcon(prefix + "gtk-info.png"), */ tr("CsoundQt Documentation (online)"), this);
4026 openDocumentationAct->setStatusTip(tr("open CsoundQt Documentation in browser"));
4027 openDocumentationAct->setShortcutContext(Qt::ApplicationShortcut);
4028 connect(openDocumentationAct, SIGNAL(triggered()), this, SLOT(openOnlineDocumentation()));
4029
4030 openQuickRefAct = new QAction(/*QIcon(prefix + "gtk-info.png"), */ tr("Quick Reference Guide"), this);
4031 openQuickRefAct->setStatusTip(tr("Open Quick Reference Guide in PDF viewer"));
4032 openQuickRefAct->setShortcutContext(Qt::ApplicationShortcut);
4033 connect(openQuickRefAct, SIGNAL(triggered()), this, SLOT(openQuickRef()));
4034
4035 showUtilitiesAct = new QAction(QIcon(prefix + "gnome-devel.png"), tr("Utilities"), this);
4036 showUtilitiesAct->setCheckable(true);
4037 showUtilitiesAct->setChecked(false);
4038 showUtilitiesAct->setStatusTip(tr("Show the Csound Utilities dialog"));
4039 showUtilitiesAct->setIconText(tr("Utilities"));
4040 showUtilitiesAct->setShortcutContext(Qt::ApplicationShortcut);
4041 connect(showUtilitiesAct, SIGNAL(triggered(bool)), this, SLOT(showUtilities(bool)));
4042
4043 setShortcutsAct = new QAction(tr("Keyboard Shortcuts"), this);
4044 setShortcutsAct->setStatusTip(tr("Set Keyboard Shortcuts"));
4045 setShortcutsAct->setIconText(tr("Set Shortcuts"));
4046 setShortcutsAct->setShortcutContext(Qt::ApplicationShortcut);
4047 connect(setShortcutsAct, SIGNAL(triggered()), this, SLOT(openShortcutDialog()));
4048
4049 commentAct = new QAction(tr("Comment/Uncomment"), this);
4050 commentAct->setStatusTip(tr("Comment/Uncomment selection"));
4051 commentAct->setShortcutContext(Qt::ApplicationShortcut);
4052 // commentAct->setIconText(tr("Comment"));
4053 // connect(commentAct, SIGNAL(triggered()), this, SLOT(controlD()));
4054
4055 // uncommentAct = new QAction(tr("Uncomment"), this);
4056 // uncommentAct->setStatusTip(tr("Uncomment selection"));
4057 // uncommentAct->setShortcutContext(Qt::ApplicationShortcut);
4058 // uncommentAct->setIconText(tr("Uncomment"));
4059 // connect(uncommentAct, SIGNAL(triggered()), this, SLOT(uncomment()));
4060
4061 indentAct = new QAction(tr("Indent"), this);
4062 indentAct->setStatusTip(tr("Indent selection"));
4063 indentAct->setShortcutContext(Qt::ApplicationShortcut);
4064 // indentAct->setIconText(tr("Indent"));
4065 // connect(indentAct, SIGNAL(triggered()), this, SLOT(indent()));
4066
4067 unindentAct = new QAction(tr("Unindent"), this);
4068 unindentAct->setStatusTip(tr("Unindent selection"));
4069 unindentAct->setShortcutContext(Qt::ApplicationShortcut);
4070 // unindentAct->setIconText(tr("Unindent"));
4071 // connect(unindentAct, SIGNAL(triggered()), this, SLOT(unindent()));
4072
4073 killLineAct = new QAction(tr("Kill Line"), this);
4074 killLineAct->setStatusTip(tr("Completely delete current line"));
4075 killLineAct->setShortcutContext(Qt::ApplicationShortcut);
4076
4077 killToEndAct = new QAction(tr("Kill to End of Line"), this);
4078 killToEndAct->setStatusTip(tr("Delete everything from cursor to the end of the current line"));
4079 killToEndAct->setShortcutContext(Qt::ApplicationShortcut);
4080
4081 gotoLineAct = new QAction(tr("Goto Line"), this);
4082 gotoLineAct->setStatusTip(tr("Go to a given line"));
4083 gotoLineAct->setShortcutContext(Qt::ApplicationShortcut);
4084 connect(gotoLineAct, SIGNAL(triggered()), this, SLOT(gotoLineDialog()));
4085
4086 goBackAct = new QAction(tr("Go Back"), this);
4087 goBackAct->setStatusTip(tr("Go back to previous position"));
4088 goBackAct->setShortcutContext(Qt::ApplicationShortcut);
4089 connect(goBackAct, &QAction::triggered, [this]() { this->getCurrentDocumentPage()->goBackToPreviousPosition(); });
4090
4091 aboutAct = new QAction(tr("&About CsoundQt"), this);
4092 aboutAct->setStatusTip(tr("Show the application's About box"));
4093 // aboutAct->setIconText(tr("About"));
4094 aboutAct->setShortcutContext(Qt::ApplicationShortcut);
4095 connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
4096
4097 donateAct = new QAction(tr("Donate to CsoundQt"), this);
4098 donateAct->setStatusTip(tr("Donate to support development of CsoundQt"));
4099 // aboutAct->setIconText(tr("About"));
4100 donateAct->setShortcutContext(Qt::ApplicationShortcut);
4101 connect(donateAct, SIGNAL(triggered()), this, SLOT(donate()));
4102
4103 // aboutQtAct = new QAction(tr("About &Qt"), this);
4104 // aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
4105 //// aboutQtAct->setIconText(tr("About Qt"));
4106 // aboutQtAct->setShortcutContext(Qt::ApplicationShortcut);
4107 // connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
4108
4109 resetPreferencesAct = new QAction(tr("Reset Preferences"), this);
4110 resetPreferencesAct->setStatusTip(tr("Reset CsoundQt's preferences to their original default state"));
4111 resetPreferencesAct->setShortcutContext(Qt::ApplicationShortcut);
4112 connect(resetPreferencesAct, SIGNAL(triggered()), this, SLOT(resetPreferences()));
4113
4114 reportBugAct = new QAction(tr("Report a Bug"), this);
4115 reportBugAct->setStatusTip(tr("Report a bug in CsoundQt's Bug Tracker"));
4116 reportBugAct->setShortcutContext(Qt::ApplicationShortcut);
4117 connect(reportBugAct, SIGNAL(triggered()), this, SLOT(reportBug()));
4118
4119 requestFeatureAct = new QAction(tr("Request a Feature (please add label \'Enhancement\')"), this);
4120 requestFeatureAct->setStatusTip(tr("Request a feature in CsoundQt's Feature Tracker"));
4121 requestFeatureAct->setShortcutContext(Qt::ApplicationShortcut);
4122 connect(requestFeatureAct, SIGNAL(triggered()), this, SLOT(requestFeature()));
4123
4124 chatAct = new QAction(tr("Csound IRC Chat"), this);
4125 chatAct->setStatusTip(tr("Open the IRC chat channel #csound in your browser"));
4126 chatAct->setShortcutContext(Qt::ApplicationShortcut);
4127 connect(chatAct, SIGNAL(triggered()), this, SLOT(chat()));
4128
4129 duplicateAct = new QAction(tr("Duplicate Widgets"), this);
4130 duplicateAct->setShortcutContext(Qt::ApplicationShortcut);
4131 connect(duplicateAct, SIGNAL(triggered()), this, SLOT(duplicate()));
4132
4133 lineNumbersAct = new QAction(tr("Show/hide line number area"),this);
4134 lineNumbersAct->setShortcutContext(Qt::ApplicationShortcut);
4135 connect(lineNumbersAct,SIGNAL(triggered()), this, SLOT(toggleLineArea()));
4136
4137 parameterModeAct = new QAction(tr("Toggle parameter mode"),this);
4138 connect(parameterModeAct,SIGNAL(triggered()), this, SLOT(toggleParameterMode()));
4139
4140 // showParametersAct = new QAction(tr("Show available parameters"),this);
4141 // connect(showParametersAct,SIGNAL(triggered()), this, SLOT(showParametersInEditor()));
4142
4143 setKeyboardShortcutsList();
4144 setDefaultKeyboardShortcuts();
4145 }
4146
setKeyboardShortcutsList()4147 void CsoundQt::setKeyboardShortcutsList()
4148 {
4149 m_keyActions.append(newAct);
4150 m_keyActions.append(openAct);
4151 m_keyActions.append(reloadAct);
4152 m_keyActions.append(saveAct);
4153 m_keyActions.append(saveAsAct);
4154 m_keyActions.append(createAppAct);
4155 m_keyActions.append(closeTabAct);
4156 m_keyActions.append(printAct);
4157 m_keyActions.append(exitAct);
4158 m_keyActions.append(createCodeGraphAct);
4159 m_keyActions.append(undoAct);
4160 m_keyActions.append(redoAct);
4161 m_keyActions.append(cutAct);
4162 m_keyActions.append(copyAct);
4163 m_keyActions.append(pasteAct);
4164 m_keyActions.append(duplicateAct);
4165 m_keyActions.append(joinAct);
4166 m_keyActions.append(inToGetAct);
4167 m_keyActions.append(getToInAct);
4168 m_keyActions.append(csladspaAct);
4169 m_keyActions.append(cabbageAct);
4170 m_keyActions.append(findAct);
4171 m_keyActions.append(findAgainAct);
4172 m_keyActions.append(configureAct);
4173 m_keyActions.append(editAct);
4174 m_keyActions.append(runAct);
4175 m_keyActions.append(runTermAct);
4176 m_keyActions.append(stopAct);
4177 m_keyActions.append(pauseAct);
4178 m_keyActions.append(stopAllAct);
4179 m_keyActions.append(recAct);
4180 m_keyActions.append(renderAct);
4181 m_keyActions.append(commentAct);
4182 m_keyActions.append(indentAct);
4183 m_keyActions.append(unindentAct);
4184 m_keyActions.append(externalPlayerAct);
4185 m_keyActions.append(externalEditorAct);
4186 m_keyActions.append(focusEditorAct);
4187 m_keyActions.append(raiseWidgetsAct);
4188 m_keyActions.append(showInspectorAct);
4189 m_keyActions.append(raiseHelpAct);
4190 m_keyActions.append(showGenAct);
4191 m_keyActions.append(showOverviewAct);
4192 m_keyActions.append(raiseConsoleAct);
4193 m_keyActions.append(raiseInspectorAct);
4194 m_keyActions.append(showLiveEventsAct);
4195 m_keyActions.append(raisePythonConsoleAct);
4196 m_keyActions.append(raiseScratchPadAct);
4197 m_keyActions.append(showUtilitiesAct);
4198 m_keyActions.append(showVirtualKeyboardAct);
4199 m_keyActions.append(showTableEditorAct);
4200 m_keyActions.append(checkSyntaxAct);
4201 #if defined(QCS_QTHTML)
4202 m_keyActions.append(raiseHtml5Act);
4203 #endif
4204 m_keyActions.append(setHelpEntryAct);
4205 m_keyActions.append(browseBackAct);
4206 m_keyActions.append(browseForwardAct);
4207 m_keyActions.append(externalBrowserAct);
4208 m_keyActions.append(openQuickRefAct);
4209 m_keyActions.append(openDocumentationAct);
4210 // m_keyActions.append(showOpcodeQuickRefAct);
4211 m_keyActions.append(infoAct);
4212 m_keyActions.append(viewFullScreenAct);
4213 m_keyActions.append(viewEditorFullScreenAct);
4214 #if defined(QCS_QTHTML)
4215 m_keyActions.append(viewHtmlFullScreenAct);
4216 #endif
4217 m_keyActions.append(viewHelpFullScreenAct);
4218 m_keyActions.append(viewWidgetsFullScreenAct);
4219 #ifdef QCS_DEBUGGER
4220 m_keyActions.append(showDebugAct);
4221 #endif
4222 m_keyActions.append(splitViewAct);
4223 m_keyActions.append(midiLearnAct);
4224 m_keyActions.append(killLineAct);
4225 m_keyActions.append(killToEndAct);
4226 m_keyActions.append(gotoLineAct);
4227 m_keyActions.append(goBackAct);
4228 m_keyActions.append(evaluateAct);
4229 m_keyActions.append(evaluateSectionAct);
4230 m_keyActions.append(scratchPadCsdModeAct);
4231 m_keyActions.append(showOrcAct);
4232 m_keyActions.append(showScoreAct);
4233 m_keyActions.append(showOptionsAct);
4234 m_keyActions.append(showFileBAct);
4235 m_keyActions.append(showOtherAct);
4236 m_keyActions.append(showOtherCsdAct);
4237 m_keyActions.append(showWidgetEditAct);
4238 m_keyActions.append(lineNumbersAct);
4239 m_keyActions.append(parameterModeAct);
4240 // m_keyActions.append(showParametersAct);
4241 }
4242
connectActions()4243 void CsoundQt::connectActions()
4244 {
4245 DocumentPage * doc = documentPages[curPage];
4246
4247 disconnect(commentAct, 0, 0, 0);
4248 // disconnect(uncommentAct, 0, 0, 0);
4249 disconnect(indentAct, 0, 0, 0);
4250 disconnect(unindentAct, 0, 0, 0);
4251 disconnect(killLineAct, 0, 0, 0);
4252 disconnect(killToEndAct, 0, 0, 0);
4253 // disconnect(gotoLineAct, 0, 0, 0);
4254 // disconnect(findAct, 0, 0, 0);
4255 // disconnect(findAgainAct, 0, 0, 0);
4256 connect(commentAct, SIGNAL(triggered()), doc, SLOT(comment()));
4257 // connect(uncommentAct, SIGNAL(triggered()), doc, SLOT(uncomment()));
4258 connect(indentAct, SIGNAL(triggered()), doc, SLOT(indent()));
4259 connect(unindentAct, SIGNAL(triggered()), doc, SLOT(unindent()));
4260 connect(killLineAct, SIGNAL(triggered()), doc, SLOT(killLine()));
4261 connect(killToEndAct, SIGNAL(triggered()), doc, SLOT(killToEnd()));
4262 // connect(gotoLineAct, SIGNAL(triggered()), doc, SLOT(gotoLineDialog()));
4263 // disconnect(doc, SIGNAL(copyAvailable(bool)), 0, 0);
4264 // disconnect(doc, SIGNAL(copyAvailable(bool)), 0, 0);
4265 //TODO put these back
4266 // connect(doc, SIGNAL(copyAvailable(bool)),
4267 // cutAct, SLOT(setEnabled(bool)));
4268 // connect(doc, SIGNAL(copyAvailable(bool)),
4269 // copyAct, SLOT(setEnabled(bool)));
4270
4271 // disconnect(doc, SIGNAL(textChanged()), 0, 0);
4272 // disconnect(doc, SIGNAL(cursorPositionChanged()), 0, 0);
4273
4274 // disconnect(widgetPanel, SIGNAL(widgetsChanged(QString)),0,0);
4275 // connect(widgetPanel, SIGNAL(widgetsChanged(QString)),
4276 // doc, SLOT(setMacWidgetsText(QString)) );
4277
4278 // Connect inspector actions to document
4279 disconnect(m_inspector, 0, 0, 0);
4280 connect(m_inspector, SIGNAL(jumpToLine(int)),
4281 doc, SLOT(jumpToLine(int)));
4282 disconnect(m_inspector, 0, 0, 0);
4283 connect(m_inspector, SIGNAL(jumpToLine(int)),
4284 doc, SLOT(jumpToLine(int)));
4285 connect(m_inspector, SIGNAL(Close(bool)), showInspectorAct, SLOT(setChecked(bool)));
4286
4287 disconnect(showLiveEventsAct, 0,0,0);
4288 connect(showLiveEventsAct, SIGNAL(toggled(bool)), doc, SLOT(showLiveEventControl(bool)));
4289 disconnect(doc, 0,0,0);
4290 connect(doc, SIGNAL(liveEventsVisible(bool)), showLiveEventsAct, SLOT(setChecked(bool)));
4291 connect(doc, SIGNAL(stopSignal()), this, SLOT(markStopped()));
4292 connect(doc, SIGNAL(setHelpSignal()), this, SLOT(setHelpEntry()));
4293 connect(doc, SIGNAL(closeExtraPanelsSignal()), this, SLOT(closeExtraPanels()));
4294 connect(doc, SIGNAL(currentTextUpdated()), this, SLOT(markInspectorUpdate()));
4295
4296 connect(doc->getView(), SIGNAL(opcodeSyntaxSignal(QString)),
4297 this, SLOT(statusBarMessage(QString)));
4298
4299 connect(doc, SIGNAL(modified()), this, SLOT(documentWasModified()));
4300 // connect(documentPages[curPage], SIGNAL(setWidgetClipboardSignal(QString)),
4301 // this, SLOT(setWidgetClipboard(QString)));
4302 connect(doc, SIGNAL(setCurrentAudioFile(QString)),
4303 this, SLOT(setCurrentAudioFile(QString)));
4304 connect(doc, SIGNAL(evaluatePythonSignal(QString)),
4305 this, SLOT(evaluateString(QString)));
4306
4307 disconnect(showWidgetsAct, 0,0,0);
4308 if (m_options->widgetsIndependent) {
4309 connect(showWidgetsAct, SIGNAL(triggered(bool)), doc, SLOT(showWidgets(bool)));
4310 auto wl = doc->getWidgetLayout();
4311 connect(wl, SIGNAL(windowStatus(bool)), showWidgetsAct, SLOT(setChecked(bool)));
4312 // connect(widgetPanel, SIGNAL(Close(bool)), showWidgetsAct, SLOT(setChecked(bool)));
4313 }
4314 else {
4315 // connect(showWidgetsAct, SIGNAL(triggered(bool)), widgetPanel, SLOT(setVisible(bool)));
4316 connect(showWidgetsAct, SIGNAL(triggered(bool)), widgetPanel, SLOT(showAndRaise(bool)));
4317
4318 connect(widgetPanel, SIGNAL( Close(bool)), showWidgetsAct, SLOT(setChecked(bool)));
4319 }
4320 }
4321
getExamplePath(QString dir)4322 QString CsoundQt::getExamplePath(QString dir)
4323 {
4324 QString examplePath;
4325 #ifdef Q_OS_WIN32
4326 examplePath = qApp->applicationDirPath() + "/Examples/" + dir;
4327 if (!QDir(examplePath).exists()) {
4328 QString programFilesPath= QDir::fromNativeSeparators(getenv("PROGRAMFILES"));
4329 examplePath = programFilesPath + "/Csound6/bin/Examples/" + dir; // NB! with csound6.0.6 no Floss/mCcurdy/Stria examples there. Copy manually
4330 //qDebug()<<"Windows examplepath: "<<examplePath;
4331 }
4332 #endif
4333 #ifdef Q_OS_MAC
4334 examplePath = qApp->applicationDirPath() + "/../Resources/" + dir;
4335 qDebug() << examplePath;
4336 #endif
4337 #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
4338 examplePath = qApp->applicationDirPath() + "/../share/examples/CsoundQt/" + dir;
4339 QStringList possiblePaths;
4340 possiblePaths << qApp->applicationDirPath() + "/Examples/" << "~/.local/share/csoundqt/Examples/"
4341 << "/usr/share/csoundqt/Examples/" << qApp->applicationDirPath() + "/../src/Examples/"
4342 << qApp->applicationDirPath() + "/../../csoundqt/src/Examples/"
4343 << "/../../qutecsound/src/Examples/"
4344 << "~/.local/share/qutecsound/Examples/" << "/usr/share/qutecsound/Examples/"
4345 << qApp->applicationDirPath() + "/../share/csoundqt/Examples/";
4346
4347 foreach (QString path, possiblePaths) {
4348 path += dir;
4349 if (QDir(path).exists()) {
4350 examplePath = path;
4351 break;
4352 }
4353 }
4354 if (examplePath.isEmpty()) {
4355 qDebug() << "Path to extended examples not found!";
4356 } else {
4357 qDebug() << "ExamplePath: " << examplePath;
4358 }
4359
4360 #endif
4361 #ifdef Q_OS_SOLARIS
4362 examplePath = qApp->applicationDirPath() + "/Examples/" + dir;
4363 if (!QDir(examplePath).exists()) {
4364 examplePath = "/usr/share/qutecsound/Examples/" + dir;
4365 }
4366 if (!QDir(examplePath).exists()) {
4367 examplePath = qApp->applicationDirPath() + "/../src/Examples/" + dir;
4368 }
4369 #endif
4370 return examplePath;
4371 }
4372
createMenus()4373 void CsoundQt::createMenus()
4374 {
4375 fileMenu = menuBar()->addMenu(tr("File"));
4376 fileMenu->addAction(newAct);
4377 fileMenu->addAction(openAct);
4378 fileMenu->addAction(saveAct);
4379 fileMenu->addAction(saveAsAct);
4380 fileMenu->addAction(saveNoWidgetsAct);
4381 fileMenu->addAction(qmlAct);
4382 // fileMenu->addAction(createAppAct);
4383 fileMenu->addAction(reloadAct);
4384 fileMenu->addAction(closeTabAct);
4385 fileMenu->addAction(printAct);
4386 fileMenu->addAction(infoAct);
4387 fileMenu->addSeparator();
4388 recentMenu = fileMenu->addMenu(tr("Recent files"));
4389 templateMenu = fileMenu->addMenu(tr("Templates"));
4390 fileMenu->addSeparator();
4391 fileMenu->addAction(exitAct);
4392
4393 editMenu = menuBar()->addMenu(tr("Edit"));
4394 editMenu->addAction(undoAct);
4395 editMenu->addAction(redoAct);
4396 editMenu->addSeparator();
4397 editMenu->addAction(cutAct);
4398 editMenu->addAction(copyAct);
4399 editMenu->addAction(pasteAct);
4400 editMenu->addAction(evaluateAct);
4401 editMenu->addAction(evaluateSectionAct);
4402 editMenu->addAction(scratchPadCsdModeAct);
4403
4404 editMenu->addSeparator();
4405 editMenu->addAction(findAct);
4406 editMenu->addAction(findAgainAct);
4407 editMenu->addAction(gotoLineAct);
4408 // editMenu->addAction(goBackAct);
4409 editMenu->addSeparator();
4410 editMenu->addAction(commentAct);
4411 // editMenu->addAction(uncommentAct);
4412 editMenu->addAction(indentAct);
4413 editMenu->addAction(unindentAct);
4414 // editMenu->addAction(killLineAct);
4415 // editMenu->addAction(killToEndAct);
4416 editMenu->addAction(lineNumbersAct);
4417 editMenu->addAction(parameterModeAct);
4418 editMenu->addSeparator();
4419 editMenu->addAction(joinAct);
4420 editMenu->addAction(inToGetAct);
4421 editMenu->addAction(getToInAct);
4422 // editMenu->addAction(csladspaAct);
4423 // editMenu->addAction(cabbageAct);
4424 editMenu->addSeparator();
4425 editMenu->addAction(editAct);
4426 editMenu->addSeparator();
4427 editMenu->addAction(configureAct);
4428 editMenu->addAction(setShortcutsAct);
4429
4430 controlMenu = menuBar()->addMenu(tr("Control"));
4431 controlMenu->addAction(runAct);
4432 controlMenu->addAction(runTermAct);
4433 controlMenu->addAction(pauseAct);
4434 controlMenu->addAction(renderAct);
4435 controlMenu->addAction(recAct);
4436 controlMenu->addAction(stopAct);
4437 controlMenu->addAction(stopAllAct);
4438 controlMenu->addSeparator();
4439 controlMenu->addAction(externalEditorAct);
4440 controlMenu->addAction(externalPlayerAct);
4441 controlMenu->addAction(checkSyntaxAct);
4442 controlMenu->addSeparator();
4443 controlMenu->addAction(testAudioSetupAct);
4444
4445
4446 viewMenu = menuBar()->addMenu(tr("View"));
4447 viewMenu->addAction(focusEditorAct);
4448 viewMenu->addAction(showWidgetsAct);
4449 viewMenu->addAction(showHelpAct);
4450 viewMenu->addAction(showConsoleAct);
4451 viewMenu->addAction(showUtilitiesAct);
4452 viewMenu->addAction(createCodeGraphAct);
4453 viewMenu->addAction(showInspectorAct);
4454 viewMenu->addAction(showLiveEventsAct);
4455 #ifdef QCS_PYTHONQT
4456 viewMenu->addAction(showPythonConsoleAct);
4457 #endif
4458 viewMenu->addAction(showScratchPadAct);
4459 #if defined(QCS_QTHTML)
4460 viewMenu->addAction(showHtml5Act);
4461 #endif
4462 viewMenu->addAction(showUtilitiesAct);
4463 #ifdef QCS_DEBUGGER
4464 viewMenu->addAction(showDebugAct);
4465 #endif
4466 viewMenu->addAction(midiLearnAct);
4467 #ifdef USE_QT5
4468 viewMenu->addAction(showVirtualKeyboardAct);
4469 viewMenu->addAction(showTableEditorAct);
4470 #endif
4471 viewMenu->addSeparator();
4472 viewMenu->addAction(viewFullScreenAct);
4473 viewMenu->addAction(viewEditorFullScreenAct);
4474 #if defined(QCS_QTHTML)
4475 viewMenu->addAction(viewHtmlFullScreenAct);
4476 #endif
4477 viewMenu->addAction(viewHelpFullScreenAct);
4478 viewMenu->addAction(viewWidgetsFullScreenAct);
4479 viewMenu->addSeparator();
4480 viewMenu->addAction(splitViewAct);
4481 viewMenu->addSeparator();
4482 viewMenu->addAction(showOrcAct);
4483 viewMenu->addAction(showScoreAct);
4484 viewMenu->addAction(showOptionsAct);
4485 viewMenu->addAction(showFileBAct);
4486 viewMenu->addAction(showOtherAct);
4487 viewMenu->addAction(showOtherCsdAct);
4488 viewMenu->addAction(showWidgetEditAct);
4489
4490 QStringList tutFiles;
4491 QStringList basicsFiles;
4492 QStringList realtimeInteractionFiles;
4493 QStringList featuresFiles;
4494
4495 QStringList livecollFiles;
4496 QStringList widgetFiles;
4497 QStringList synthFiles;
4498 QStringList musicFiles;
4499 QStringList usefulFiles;
4500 QStringList exampleFiles;
4501 QStringList htmlFiles;
4502 QList<QStringList> subMenus;
4503 QStringList subMenuNames;
4504
4505 livecollFiles << ":/examples/Live Collection/Live_Accordizer.csd"
4506 << ":/examples/Live Collection/Live_Delay_Feedback.csd"
4507 << ":/examples/Live Collection/Live_Granular.csd"
4508 << ":/examples/Live Collection/Live_RM_AM.csd";
4509
4510 subMenus << livecollFiles;
4511 subMenuNames << tr("Live Collection");
4512
4513 widgetFiles.append(":/examples/Widgets/Widget_Panel.csd");
4514 widgetFiles.append(":/examples/Widgets/Label_Widget.csd");
4515 widgetFiles.append(":/examples/Widgets/Display_Widget.csd");
4516 widgetFiles.append(":/examples/Widgets/Slider_Widget.csd");
4517 widgetFiles.append(":/examples/Widgets/Scrollnumber_Widget.csd");
4518 widgetFiles.append(":/examples/Widgets/SpinBox_Widget.csd");
4519 widgetFiles.append(":/examples/Widgets/Graph_Widget.csd");
4520 widgetFiles.append(":/examples/Widgets/Button_Widget.csd");
4521 widgetFiles.append(":/examples/Widgets/Checkbox_Widget.csd");
4522 widgetFiles.append(":/examples/Widgets/Menu_Widget.csd");
4523 widgetFiles.append(":/examples/Widgets/Controller_Widget.csd");
4524 widgetFiles.append(":/examples/Widgets/Lineedit_Widget.csd");
4525 widgetFiles.append(":/examples/Widgets/Scope_Widget.csd");
4526 widgetFiles.append(":/examples/Widgets/Tableplot_Widget.csd");
4527 widgetFiles.append(":/examples/Widgets/String_Channels.csd");
4528 widgetFiles.append(":/examples/Widgets/Presets.csd");
4529 widgetFiles.append(":/examples/Widgets/Reserved_Channels.csd");
4530
4531 subMenus << widgetFiles;
4532 subMenuNames << "Widgets";
4533
4534 synthFiles.append(":/examples/Synths/Additive_Synth.csd");
4535 synthFiles.append(":/examples/Synths/Imitative_Additive.csd");
4536 synthFiles.append(":/examples/Synths/Simple_Subtractive.csd");
4537 synthFiles.append(":/examples/Synths/Simple_FM_Synth.csd");
4538 synthFiles.append(":/examples/Synths/Phase_Mod_Synth.csd");
4539 synthFiles.append(":/examples/Synths/Formant_Synth.csd");
4540 synthFiles.append(":/examples/Synths/Mono_Synth.csd");
4541 synthFiles.append(":/examples/Synths/B6_Hammond.csd");
4542 synthFiles.append(":/examples/Synths/Diffamator.csd");
4543 synthFiles.append(":/examples/Synths/Sruti-Drone_Box.csd");
4544 synthFiles.append(":/examples/Synths/Pipe_Synth.csd");
4545 synthFiles.append(":/examples/Synths/Piano_phase.csd");
4546 synthFiles.append(":/examples/Synths/String_Phaser.csd");
4547 synthFiles.append(":/examples/Synths/Waveform_Mix.csd");
4548 synthFiles.append(":/examples/Synths/Scanned_Synthesis_Sandbox.csd");
4549 subMenus << synthFiles;
4550 subMenuNames << "Synths";
4551
4552
4553 musicFiles.append(":/examples/Music/Boulanger-Trapped_in_Convert.csd");
4554 musicFiles.append(":/examples/Music/Chowning-Stria.csd");
4555 musicFiles.append(":/examples/Music/Kung-Xanadu.csd");
4556 musicFiles.append(":/examples/Music/Riley-In_C.csd");
4557 musicFiles.append(":/examples/Music/Stockhausen-Studie_II.csd");
4558 musicFiles.append(":/examples/Music/Bach-Invention_1.csd");
4559
4560 subMenus << musicFiles;
4561 subMenuNames << tr("Music");
4562
4563 usefulFiles.append(":/examples/Useful/SpectrumAnalyzer.csd");
4564 usefulFiles.append(":/examples/Useful/IO_Test.csd");
4565 usefulFiles.append(":/examples/Useful/MIDI_IO_Test.csd");
4566 usefulFiles.append(":/examples/Useful/Audio_Input_Test.csd");
4567 usefulFiles.append(":/examples/Useful/Audio_Output_Test.csd");
4568 usefulFiles.append(":/examples/Useful/Audio_Thru_Test.csd");
4569 usefulFiles.append(":/examples/Useful/MIDI_Recorder.csd");
4570 usefulFiles.append(":/examples/Useful/MIDI_Layering.csd");
4571 usefulFiles.append(":/examples/Useful/ASCII_Key.csd");
4572 usefulFiles.append(":/examples/Useful/Monome_basic.csd");
4573 usefulFiles.append(":/examples/Useful/SF_Play_from_buffer.csd");
4574 usefulFiles.append(":/examples/Useful/SF_Play_from_buffer_2.csd");
4575 usefulFiles.append(":/examples/Useful/SF_Play_from_HD.csd");
4576 usefulFiles.append(":/examples/Useful/SF_Play_from_HD_2.csd");
4577 usefulFiles.append(":/examples/Useful/SF_Snippets_Player.csd");
4578 usefulFiles.append(":/examples/Useful/Multichannel_Player.csd");
4579 usefulFiles.append(":/examples/Useful/Mixdown_Player.csd");
4580 usefulFiles.append(":/examples/Useful/SF_Record.csd");
4581 usefulFiles.append(":/examples/Useful/File_to_Text.csd");
4582 usefulFiles.append(":/examples/Useful/Envelope_Extractor.csd");
4583 usefulFiles.append(":/examples/Useful/Pitch_Tracker.csd");
4584 usefulFiles.append(":/examples/Useful/SF_Splitter.csd");
4585 usefulFiles.append(":/examples/Useful/SF_Merger.csd");
4586
4587 subMenus << usefulFiles;
4588 subMenuNames << tr("Useful");
4589
4590 exampleFiles.append(":/examples/Miscellaneous/MIDI_Tunings.csd");
4591 exampleFiles.append(":/examples/Miscellaneous/Keyboard_Control.csd");
4592 exampleFiles.append(":/examples/Miscellaneous/Just_Intonation.csd");
4593 exampleFiles.append(":/examples/Miscellaneous/Mouse_Control.csd");
4594 exampleFiles.append(":/examples/Miscellaneous/Autotuner.csd");
4595 exampleFiles.append(":/examples/Miscellaneous/Event_Panel.csd");
4596 exampleFiles.append(":/examples/Miscellaneous/Score_Tricks.csd");
4597 exampleFiles.append(":/examples/Miscellaneous/Simple_Convolution.csd");
4598 exampleFiles.append(":/examples/Miscellaneous/Universal_Convolution.csd");
4599 exampleFiles.append(":/examples/Miscellaneous/Cross_Synthesis.csd");
4600 exampleFiles.append(":/examples/Miscellaneous/SF_Granular.csd");
4601 exampleFiles.append(":/examples/Miscellaneous/Oscillator_Aliasing.csd");
4602 exampleFiles.append(":/examples/Miscellaneous/Filter_lab.csd");
4603 exampleFiles.append(":/examples/Miscellaneous/Pvstencil.csd");
4604 exampleFiles.append(":/examples/Miscellaneous/Matrix.csd");
4605 exampleFiles.append(":/examples/Miscellaneous/Rms.csd");
4606 exampleFiles.append(":/examples/Miscellaneous/Reinit_Example.csd");
4607 exampleFiles.append(":/examples/Miscellaneous/No_Reinit.csd");
4608 exampleFiles.append(":/examples/Miscellaneous/Mincer_Loop.csd");
4609 exampleFiles.append(":/examples/Miscellaneous/Circle_Map.csd");
4610 exampleFiles.append(":/examples/Miscellaneous/Binaural_Panning.csd");
4611 exampleFiles.append(":/examples/Miscellaneous/Spatialization.csd");
4612 exampleFiles.append(":/examples/Miscellaneous/Spatialization_5.1.csd");
4613 exampleFiles.append(":/examples/Miscellaneous/Pseudostereo.csd");
4614 exampleFiles.append(":/examples/Miscellaneous/Noise_Reduction.csd");
4615
4616 subMenus << exampleFiles;
4617 subMenuNames << tr("Miscellaneous");
4618
4619 htmlFiles.append(":/examples/Html5 Support/Minimal_Html_Example.csd");
4620 htmlFiles.append(":/examples/Html5 Support/Styled_Sliders.csd");
4621 htmlFiles.append(":/examples/Html5 Support/Html_file_in_CsoundQt.html");
4622 subMenus << htmlFiles;
4623 subMenuNames << tr("Html5 support");
4624
4625 QMenu *examplesMenu = menuBar()->addMenu(tr("Examples"));
4626 QAction *newAction;
4627 QMenu *submenu;
4628
4629 basicsFiles.append(":/examples/Getting Started/Basics/Hello World.csd");
4630 basicsFiles.append(":/examples/Getting Started/Basics/Document Structure.csd");
4631 basicsFiles.append(":/examples/Getting Started/Basics/Basic Elements Opcodes.csd");
4632 basicsFiles.append(":/examples/Getting Started/Basics/Basic Elements Variables.csd");
4633 basicsFiles.append(":/examples/Getting Started/Basics/Getting Help.csd");
4634 basicsFiles.append(":/examples/Getting Started/Basics/Instrument Control.csd");
4635 basicsFiles.append(":/examples/Getting Started/Basics/Realtime Instrument Control.csd");
4636 basicsFiles.append(":/examples/Getting Started/Basics/Routing.csd");
4637
4638 QMenu *tutorialMenu = examplesMenu->addMenu(tr("Getting Started"));
4639 submenu = tutorialMenu->addMenu(tr("Basics"));
4640 foreach (QString fileName, basicsFiles) {
4641 QString name = fileName.mid(fileName.lastIndexOf("/") + 1).replace("_", " ").remove(".csd");
4642 newAction = submenu->addAction(name);
4643 newAction->setData(fileName);
4644 connect(newAction,SIGNAL(triggered()), this, SLOT(openExample()));
4645 }
4646
4647 realtimeInteractionFiles.append(":/examples/Getting Started/Realtime_Interaction/Creating_Widgets.csd");
4648 realtimeInteractionFiles.append(":/examples/Getting Started/Realtime_Interaction/Widgets_Invalue.csd");
4649 realtimeInteractionFiles.append(":/examples/Getting Started/Realtime_Interaction/Widgets_Outvalue.csd");
4650 realtimeInteractionFiles.append(":/examples/Getting Started/Realtime_Interaction/Widgets_Buttontypes.csd");
4651 realtimeInteractionFiles.append(":/examples/Getting Started/Realtime_Interaction/Widgets_Checkbox.csd");
4652 realtimeInteractionFiles.append(":/examples/Getting Started/Realtime_Interaction/Live_Audio_Input.csd");
4653 realtimeInteractionFiles.append(":/examples/Getting Started/Realtime_Interaction/MIDI_Receiving_Notes.csd");
4654 realtimeInteractionFiles.append(":/examples/Getting Started/Realtime_Interaction/MIDI_Synth.csd");
4655 realtimeInteractionFiles.append(":/examples/Getting Started/Realtime_Interaction/MIDI_Control_Data.csd");
4656 realtimeInteractionFiles.append(":/examples/Getting Started/Realtime_Interaction/MIDI_Assign_Controllers.csd");
4657 realtimeInteractionFiles.append(":/examples/Getting Started/Realtime_Interaction/OpenSoundControl.csd");
4658
4659 submenu = tutorialMenu->addMenu(tr("Realtime Interaction"));
4660 foreach (QString fileName, realtimeInteractionFiles) {
4661 QString name = fileName.mid(fileName.lastIndexOf("/") + 1).replace("_", " ").remove(".csd");
4662 newAction = submenu->addAction(name);
4663 newAction->setData(fileName);
4664 connect(newAction,SIGNAL(triggered()), this, SLOT(openExample()));
4665 }
4666
4667 featuresFiles.append(":/examples/Getting Started/Language_Features/Function_Tables_1.csd");
4668 featuresFiles.append(":/examples/Getting Started/Language_Features/Function_Tables_2.csd");
4669 featuresFiles.append(":/examples/Getting Started/Language_Features/Loops_1.csd");
4670 featuresFiles.append(":/examples/Getting Started/Language_Features/Loops_2.csd");
4671 featuresFiles.append(":/examples/Getting Started/Language_Features/Console_Print.csd");
4672 featuresFiles.append(":/examples/Getting Started/Language_Features/Writing_Audio_Files.csd");
4673 featuresFiles.append(":/examples/Getting Started/Language_Features/Using_Udos.csd");
4674
4675 submenu = tutorialMenu->addMenu(tr("Language Features"));
4676 foreach (QString fileName, featuresFiles) {
4677 QString name = fileName.mid(fileName.lastIndexOf("/") + 1).replace("_", " ").remove(".csd");
4678 newAction = submenu->addAction(name);
4679 newAction->setData(fileName);
4680 connect(newAction,SIGNAL(triggered()), this, SLOT(openExample()));
4681 }
4682
4683 tutFiles.append(":/examples/Getting Started/Toots/Toot1.csd");
4684 tutFiles.append(":/examples/Getting Started/Toots/Toot2.csd");
4685 tutFiles.append(":/examples/Getting Started/Toots/Toot3.csd");
4686 tutFiles.append(":/examples/Getting Started/Toots/Toot4.csd");
4687 tutFiles.append(":/examples/Getting Started/Toots/Toot5.csd");
4688
4689 submenu = tutorialMenu->addMenu("Toots");
4690 foreach (QString fileName, tutFiles) {
4691 QString name = fileName.mid(fileName.lastIndexOf("/") + 1).replace("_", " ").remove(".csd");
4692 newAction = submenu->addAction(name);
4693 newAction->setData(fileName);
4694 connect(newAction,SIGNAL(triggered()), this, SLOT(openExample()));
4695 }
4696
4697 //FLOSS Manual Examples
4698 QString flossManPath = getExamplePath("FLOSS Manual Examples");
4699 if (QDir(flossManPath).exists()) {
4700 QMenu *flossmanMenu = examplesMenu->addMenu(tr("FLOSS Manual Examples"));
4701 flossmanMenu->addAction(tr("Read FLOSS Manual Online"),this, SLOT(openFLOSSManual()));
4702 flossmanMenu->addSeparator();
4703 QStringList subDirs = QDir(flossManPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
4704 foreach (QString subDir, subDirs) {
4705 QString dirName = subDir.mid(subDir.lastIndexOf("/") + 1).replace("_", " ").remove(".csd");
4706 submenu = flossmanMenu->addMenu(dirName);
4707 QStringList filters;
4708 filters << "*.csd";
4709 QStringList flossManFiles = QDir(flossManPath + "/" + subDir).entryList(filters,QDir::Files);
4710 foreach (QString fileName, flossManFiles) {
4711 // QString name = fileName.mid(fileName.lastIndexOf("/") + 1).replace("_", " ").remove(".csd");
4712 newAction = submenu->addAction(fileName);
4713 newAction->setData(flossManPath + "/" + subDir + "/" + fileName);
4714 connect(newAction,SIGNAL(triggered()), this, SLOT(openExample()));
4715 }
4716 }
4717 } else {
4718 qDebug() << "Warning: Could not find FLOSS Manual Examples.";
4719 }
4720
4721
4722 //McCurdy Collection
4723 QString mcCurdyPath = getExamplePath("McCurdy Collection");
4724 if (QDir(mcCurdyPath).exists()) {
4725 QMenu *mccurdyMenu = examplesMenu->addMenu(tr("McCurdy Collection"));
4726 QStringList subDirs = QDir(mcCurdyPath).entryList(QDir::AllDirs | QDir::NoDotAndDotDot);
4727 foreach (QString subDir, subDirs) {
4728 QString dirName = subDir.mid(subDir.lastIndexOf("/") + 1).replace("_", " ").remove(".csd");
4729 submenu = mccurdyMenu->addMenu(dirName);
4730 QStringList filters;
4731 filters << "*.csd";
4732 QStringList mcCurdyFiles = QDir(mcCurdyPath + "/" + subDir).entryList(filters,QDir::Files);
4733 foreach (QString fileName, mcCurdyFiles) {
4734 // QString name = fileName.mid(fileName.lastIndexOf("/") + 1).replace("_", " ").remove(".csd");
4735 newAction = submenu->addAction(fileName);
4736 newAction->setData(mcCurdyPath + "/" + subDir + "/" + fileName);
4737 connect(newAction,SIGNAL(triggered()), this, SLOT(openExample()));
4738 }
4739 }
4740 } else {
4741 qDebug() << "Warning: Could not find McCurdy Collection.";
4742 }
4743
4744 // Add the rest
4745 for (int i = 0; i < subMenus.size(); i++) {
4746 submenu = examplesMenu->addMenu(subMenuNames[i]);
4747 foreach (QString fileName, subMenus[i]) {
4748 QString name = fileName.mid(fileName.lastIndexOf("/") + 1).replace("_", " ").remove(".csd");
4749 newAction = submenu->addAction(name);
4750 newAction->setData(fileName);
4751 connect(newAction,SIGNAL(triggered()), this, SLOT(openExample()));
4752 }
4753 if (subMenuNames[i] == "Synths") {
4754 QString striaPath = getExamplePath("Stria Synth");
4755 if (QDir(striaPath).exists()) {
4756 QMenu *striaMenu = submenu->addMenu(tr("Stria Synth"));
4757 QStringList filters;
4758 filters << "*.csd" << "*.pdf";
4759 QStringList striaFiles = QDir(striaPath).entryList(filters,QDir::Files);
4760 foreach (QString fileName, striaFiles) {
4761 // QString name = fileName.mid(fileName.lastIndexOf("/") + 1).replace("_", " ").remove(".csd");
4762 newAction = striaMenu->addAction(fileName);
4763 newAction->setData(striaPath + QDir::separator() + fileName);
4764 connect(newAction,SIGNAL(triggered()), this, SLOT(openExample()));
4765 }
4766 } else {
4767 qDebug() << "Warning: Could not find Stria Synth files.";
4768 }
4769 }
4770 }
4771
4772
4773 favoriteMenu = menuBar()->addMenu(tr("Favorites"));
4774 #ifdef QCS_PYTHONQT
4775 scriptsMenu = menuBar()->addMenu(tr("Scripts"));
4776 scriptsMenu->hide();
4777 #endif
4778
4779 menuBar()->addSeparator();
4780
4781 helpMenu = menuBar()->addMenu(tr("Help"));
4782 helpMenu->addAction(openDocumentationAct);
4783 helpMenu->addAction(setHelpEntryAct);
4784 helpMenu->addAction(externalBrowserAct);
4785 // helpMenu->addSeparator();
4786 // helpMenu->addAction(browseBackAct);
4787 // helpMenu->addAction(browseForwardAct);
4788 helpMenu->addSeparator();
4789 helpMenu->addAction(showManualAct);
4790 helpMenu->addAction(downloadManualAct);
4791 helpMenu->addAction(showOverviewAct);
4792 // helpMenu->addAction(showOpcodeQuickRefAct);
4793 helpMenu->addAction(showGenAct);
4794 // helpMenu->addAction(openQuickRefAct);
4795 helpMenu->addSeparator();
4796 helpMenu->addAction(resetPreferencesAct);
4797 helpMenu->addSeparator();
4798 // helpMenu->addAction(requestFeatureAct);
4799 // helpMenu->addAction(chatAct);
4800 helpMenu->addSeparator();
4801 helpMenu->addAction(reportBugAct);
4802 helpMenu->addAction(aboutAct);
4803 // helpMenu->addAction(donateAct);
4804 // uhelpMenu->addAction(aboutQtAct);
4805
4806 }
4807
fillFileMenu()4808 void CsoundQt::fillFileMenu()
4809 {
4810 recentMenu->clear();
4811 for (int i = 0; i < recentFiles.size(); i++) {
4812 if (i < recentFiles.size() && recentFiles[i] != "") {
4813 QAction *a = recentMenu->addAction(recentFiles[i], this, SLOT(openFromAction()));
4814 a->setData(recentFiles[i]);
4815 }
4816 }
4817 templateMenu->clear();
4818 QString templatePath = m_options->templateDir;
4819 if (templatePath.isEmpty() || !QDir(templatePath).exists()) {
4820 #ifdef Q_OS_WIN32
4821 templatePath = qApp->applicationDirPath() + "/templates/";
4822 #endif
4823 #ifdef Q_OS_MAC
4824 templatePath = qApp->applicationDirPath() + "/../templates/";
4825 qDebug() << templatePath;
4826 #endif
4827 #if defined(Q_OS_LINUX) || defined(Q_OS_FREEBSD)
4828 templatePath = qApp->applicationDirPath() + "/templates/";
4829 if (!QDir(templatePath).exists()) {
4830 templatePath = qApp->applicationDirPath() + "/../templates/";
4831 }
4832 if (!QDir(templatePath).exists()) { // for out of tree builds
4833 templatePath = qApp->applicationDirPath() + "/../../csoundqt/templates/";
4834 }
4835 if (!QDir(templatePath).exists()) { // for out of tree builds
4836 templatePath = qApp->applicationDirPath() + "/../../qutecsound/templates/";
4837 }
4838 if (!QDir(templatePath).exists()) {
4839 templatePath = "/usr/share/csoundqt/templates/";
4840 }
4841 #endif
4842 #ifdef Q_OS_SOLARIS
4843 templatePath = qApp->applicationDirPath() + "/templates/";
4844 if (!QDir(templatePath).exists()) {
4845 templatePath = "/usr/share/qutecsound/templates/";
4846 }
4847 if (!QDir(templatePath).exists()) {
4848 templatePath = qApp->applicationDirPath() + "/../src/templates/";
4849 }
4850 #endif
4851 }
4852 QStringList filters;
4853 filters << "*.csd"<<"*.html";
4854 QStringList templateFiles = QDir(templatePath).entryList(filters,QDir::Files);
4855 foreach (QString fileName, templateFiles) {
4856 QAction *newAction = templateMenu->addAction(fileName, this,
4857 SLOT(openTemplate()));
4858 newAction->setData(templatePath + QDir::separator() + fileName);
4859 }
4860 }
4861
fillFavoriteMenu()4862 void CsoundQt::fillFavoriteMenu()
4863 {
4864 favoriteMenu->clear();
4865 if (!m_options->favoriteDir.isEmpty()) {
4866 QDir dir(m_options->favoriteDir);
4867 fillFavoriteSubMenu(dir.absolutePath(), favoriteMenu, 0);
4868 }
4869 else {
4870 favoriteMenu->addAction(tr("Set the Favourites folder in the Configuration Window"),
4871 this, SLOT(configure()));
4872 }
4873 }
4874
fillFavoriteSubMenu(QDir dir,QMenu * m,int depth)4875 void CsoundQt::fillFavoriteSubMenu(QDir dir, QMenu *m, int depth)
4876 {
4877 QStringList filters;
4878 filters << "*.csd" << "*.orc" << "*.sco" << "*.udo" << "*.inc" << "*.py";
4879 dir.setNameFilters(filters);
4880 QStringList files = dir.entryList(QDir::Files,QDir::Name);
4881 QStringList dirs = dir.entryList(QDir::AllDirs,QDir::Name);
4882 if (depth > m_options->menuDepth)
4883 return;
4884 for (int i = 0; i < dirs.size() && i < 64; i++) {
4885 QDir newDir(dir.absolutePath() + "/" + dirs[i]);
4886 newDir.setNameFilters(filters);
4887 QStringList newFiles = dir.entryList(QDir::Files,QDir::Name);
4888 QStringList newDirs = dir.entryList(QDir::AllDirs,QDir::Name);
4889 if (newFiles.size() > 0 || newDirs.size() > 0) {
4890 if (dirs[i] != "." && dirs[i] != "..") {
4891 QMenu *menu = m->addMenu(dirs[i]);
4892 fillFavoriteSubMenu(newDir.absolutePath(), menu, depth + 1);
4893 }
4894 }
4895 }
4896 for (int i = 0; i < files.size() && i < 64; i++) {
4897 QAction *newAction = m->addAction(files[i],
4898 this, SLOT(openFromAction()));
4899 newAction->setData(dir.absoluteFilePath(files[i]));
4900 }
4901 }
4902
fillScriptsMenu()4903 void CsoundQt::fillScriptsMenu()
4904 {
4905 #ifdef QCS_PYTHONQT
4906 scriptsMenu->clear();
4907 QString dirName = m_options->pythonDir.isEmpty() ? DEFAULT_SCRIPT_DIR : m_options->pythonDir;
4908 QDir dir(dirName);
4909 if (dir.count() > 0) {
4910 fillScriptsSubMenu(dir.absolutePath(), scriptsMenu, 0);
4911 scriptsMenu->addSeparator();
4912 QMenu *editMenu = scriptsMenu->addMenu("Edit");
4913 fillEditScriptsSubMenu(dir.absolutePath(), editMenu, 0);
4914 }
4915 #endif
4916 }
4917
fillScriptsSubMenu(QDir dir,QMenu * m,int depth)4918 void CsoundQt::fillScriptsSubMenu(QDir dir, QMenu *m, int depth)
4919 {
4920 QStringList filters;
4921 filters << "*.py";
4922 dir.setNameFilters(filters);
4923 QStringList files = dir.entryList(QDir::Files,QDir::Name);
4924 QStringList dirs = dir.entryList(QDir::AllDirs,QDir::Name);
4925 if (depth > m_options->menuDepth)
4926 return;
4927 for (int i = 0; i < dirs.size() && i < 64; i++) {
4928 QDir newDir(dir.absolutePath() + "/" + dirs[i]);
4929 newDir.setNameFilters(filters);
4930 QStringList newFiles = dir.entryList(QDir::Files,QDir::Name);
4931 QStringList newDirs = dir.entryList(QDir::AllDirs,QDir::Name);
4932 if (newFiles.size() > 0 || newDirs.size() > 0) {
4933 if (dirs[i] != "." && dirs[i] != "..") {
4934 QMenu *menu = m->addMenu(dirs[i]);
4935 fillScriptsSubMenu(newDir.absolutePath(), menu, depth + 1);
4936 }
4937 }
4938 }
4939 for (int i = 0; i < files.size() && i < 64; i++) {
4940 QAction *newAction = m->addAction(files[i],
4941 this, SLOT(runScriptFromAction()));
4942 newAction->setData(dir.absoluteFilePath(files[i]));
4943 }
4944 }
4945
fillEditScriptsSubMenu(QDir dir,QMenu * m,int depth)4946 void CsoundQt::fillEditScriptsSubMenu(QDir dir, QMenu *m, int depth)
4947 {
4948 QStringList filters;
4949 filters << "*.py";
4950 dir.setNameFilters(filters);
4951 QStringList files = dir.entryList(QDir::Files,QDir::Name);
4952 QStringList dirs = dir.entryList(QDir::AllDirs,QDir::Name);
4953 if (depth > m_options->menuDepth)
4954 return;
4955 for (int i = 0; i < dirs.size() && i < 64; i++) {
4956 QDir newDir(dir.absolutePath() + "/" + dirs[i]);
4957 newDir.setNameFilters(filters);
4958 QStringList newFiles = dir.entryList(QDir::Files,QDir::Name);
4959 QStringList newDirs = dir.entryList(QDir::AllDirs,QDir::Name);
4960 if (newFiles.size() > 0 || newDirs.size() > 0) {
4961 if (dirs[i] != "." && dirs[i] != "..") {
4962 QMenu *menu = m->addMenu(dirs[i]);
4963 fillEditScriptsSubMenu(newDir.absolutePath(), menu, depth + 1);
4964 }
4965 }
4966 }
4967 for (int i = 0; i < files.size() && i < 64; i++) {
4968 QAction *newAction = m->addAction(files[i],
4969 this, SLOT(openFromAction()));
4970 newAction->setData(dir.absoluteFilePath(files[i]));
4971 }
4972 }
4973
4974 //#include "flowlayout.h"
4975
createToolBars()4976 void CsoundQt::createToolBars()
4977 {
4978 // fileToolBar = addToolBar(tr("File"));
4979 // fileToolBar->setObjectName("fileToolBar");
4980 // fileToolBar->addAction(newAct);
4981 // fileToolBar->addAction(openAct);
4982 // fileToolBar->addAction(saveAct);
4983
4984 // editToolBar = addToolBar(tr("Edit"));
4985 // editToolBar->setObjectName("editToolBar");
4986 // editToolBar->addAction(undoAct);
4987 // editToolBar->addAction(redoAct);
4988 // editToolBar->addAction(cutAct);
4989 // editToolBar->addAction(copyAct);
4990 // editToolBar->addAction(pasteAct);
4991
4992 // QDockWidget *toolWidget = new QDockWidget(tr("Tools"), this);
4993 // QWidget *w = new QWidget(toolWidget);
4994 // FlowLayout * flowlayout = new FlowLayout(w);
4995 // toolWidget->setWidget(w);
4996 // w->setLayout(flowlayout);
4997 // QVector<QAction *> actions;
4998 // actions << runAct << pauseAct << stopAct << recAct << runTermAct << renderAct;
4999 // foreach (QAction * act, actions) {
5000 // QToolButton *b = new QToolButton(w);
5001 // b->setDefaultAction(act);
5002 // flowlayout->addWidget(b);
5003 // }
5004 // addDockWidget(Qt::AllDockWidgetAreas, toolWidget);
5005 // toolWidget->show();
5006 const int iconSize = this->m_options->toolbarIconSize;
5007 controlToolBar = addToolBar(tr("Control"));
5008 controlToolBar->setObjectName("controlToolBar");
5009 controlToolBar->addAction(runAct);
5010 controlToolBar->addAction(pauseAct);
5011 controlToolBar->addAction(stopAct);
5012 controlToolBar->addAction(recAct);
5013 controlToolBar->addSeparator();
5014 controlToolBar->addAction(runTermAct);
5015 controlToolBar->addAction(renderAct);
5016 // controlToolBar->addAction(externalEditorAct);
5017 // controlToolBar->addAction(externalPlayerAct);
5018 controlToolBar->addAction(configureAct);
5019 controlToolBar->setIconSize(QSize(iconSize, iconSize));
5020 controlToolBar->setFloatable(false);
5021
5022 configureToolBar = addToolBar(tr("Panels"));
5023 configureToolBar->setObjectName("panelToolBar");
5024 #if defined(QCS_QTHTML)
5025 // configureToolBar->addAction(showHtml5Act);
5026 #endif
5027 configureToolBar->addAction(showWidgetsAct);
5028 configureToolBar->addAction(showHelpAct);
5029 configureToolBar->addAction(showConsoleAct);
5030 configureToolBar->addAction(showInspectorAct);
5031 // configureToolBar->addAction(showLiveEventsAct);
5032 configureToolBar->addAction(showVirtualKeyboardAct);
5033 //configureToolBar->addAction(showTableEditorAct);
5034
5035 #ifdef QCS_PYTHONQT
5036 configureToolBar->addAction(showPythonConsoleAct);
5037 #endif
5038 // configureToolBar->addAction(showScratchPadAct);
5039 // configureToolBar->addAction(showUtilitiesAct);
5040 configureToolBar->setFloatable(false);
5041
5042 Qt::ToolButtonStyle toolButtonStyle = (m_options->iconText?
5043 Qt::ToolButtonTextUnderIcon: Qt::ToolButtonIconOnly);
5044 // fileToolBar->setToolButtonStyle(toolButtonStyle);
5045 // editToolBar->setToolButtonStyle(toolButtonStyle);
5046 controlToolBar->setToolButtonStyle(toolButtonStyle);
5047 configureToolBar->setToolButtonStyle(toolButtonStyle);
5048 configureToolBar->setIconSize(QSize(iconSize, iconSize));
5049 // test Mac
5050 #ifdef Q_OS_MAC
5051
5052 if (m_options->theme=="breeze-dark") {
5053 QColor textColor = QGuiApplication::palette().color(QPalette::Text);
5054 qDebug() << "Textcolor: " << textColor;
5055 QString styleString = QString("color: %1").arg(textColor.name());
5056 controlToolBar->setStyleSheet(styleString);
5057 configureToolBar->setStyleSheet(styleString);
5058 }
5059 #endif
5060 }
5061
setToolbarIconSize(int size)5062 void CsoundQt::setToolbarIconSize(int size) {
5063 controlToolBar->setIconSize(QSize(size, size));
5064 controlToolBar->setStyleSheet("QToolBar { padding: 0 3px }");
5065 configureToolBar->setIconSize(QSize(size, size));
5066 }
5067
createStatusBar()5068 void CsoundQt::createStatusBar()
5069 {
5070 auto statusbar = statusBar();
5071 statusbar->showMessage(tr("Ready"));
5072 // TODO: add widgets on the right
5073 }
5074
readSettings()5075 void CsoundQt::readSettings()
5076 {
5077 QSettings settings("csound", "qutecsound");
5078 int settingsVersion = settings.value("settingsVersion", 0).toInt();
5079 // Version 1 to remove "-d" from additional command line flags
5080 // Version 2 to save default keyboard shortcuts (weren't saved previously)
5081 // Version 2 to add "*" to jack client name
5082 // version 4 to signal that many shotcuts have been changed
5083 if (settingsVersion>0 && settingsVersion<4) {
5084 QMessageBox::warning(this, tr("Settings changed"),
5085 tr("In this version the shortcuts for showing panels changed. "
5086 "See ... for more information. Please Use "
5087 "'Edit/Keyboard shortcuts/Restore Defaults' to activate it."));
5088 }
5089
5090 settings.beginGroup("GUI");
5091 m_options->theme = settings.value("theme", "breeze").toString();
5092 QPoint pos = settings.value("pos", QPoint(200, 200)).toPoint();
5093 QSize size = settings.value("size", QSize(600, 500)).toSize();
5094 resize(size); // does not work here for MacOS Mojave
5095 move(pos);
5096 if (settings.contains("dockstate")) {
5097 restoreState(settings.value("dockstate").toByteArray());
5098 }
5099 lastUsedDir = settings.value("lastuseddir", "").toString();
5100 lastFileDir = settings.value("lastfiledir", "").toString();
5101 // showLiveEventsAct->setChecked(settings.value("liveEventsActive", true).toBool());
5102 m_options->language = m_configlists.languageCodes.indexOf(settings.value("language", QLocale::system().name()).toString());
5103 if (m_options->language < 0)
5104 m_options->language = 0;
5105 recentFiles.clear();
5106 recentFiles = settings.value("recentFiles").toStringList();
5107 setDefaultKeyboardShortcuts();
5108 QHash<QString, QVariant> actionList = settings.value("shortcuts").toHash();
5109 if (actionList.count() != 0) {
5110 QHashIterator<QString, QVariant> i(actionList);
5111 while (i.hasNext()) {
5112 i.next();
5113 QString shortcut = i.value().toString();
5114 foreach (QAction *act, m_keyActions) {
5115 if (act->text().remove("&") == i.key()) {
5116 act->setShortcut(shortcut);
5117 break;
5118 }
5119 }
5120 }
5121 }
5122 // else { // No shortcuts are stored
5123 // setDefaultKeyboardShortcuts();
5124 // }
5125 settings.endGroup();
5126 settings.beginGroup("Options");
5127 settings.beginGroup("Editor");
5128 #ifdef Q_OS_MACOS
5129 m_options->font = settings.value("font", "Menlo").toString();
5130 m_options->fontPointSize = settings.value("fontsize", 12).toDouble();
5131 #endif
5132 #ifdef Q_OS_WIN
5133 m_options->font = settings.value("font", "Consolas").toString();
5134 m_options->fontPointSize = settings.value("fontsize", 11).toDouble();
5135 #endif
5136 #ifdef Q_OS_LINUX
5137 m_options->font = settings.value("font", "Liberation Mono").toString();
5138 m_options->fontPointSize = settings.value("fontsize", 11).toDouble();
5139 #endif
5140 m_options->showLineNumberArea = settings.value("showLineNumberArea", true).toBool();
5141
5142 #ifdef Q_OS_WIN
5143 m_options->lineEnding = settings.value("lineEnding", 1).toInt();
5144 #else
5145 m_options->lineEnding = settings.value("lineEnding", 0).toInt();
5146 #endif
5147
5148 m_options->consoleFont = settings.value("consolefont", "Courier").toString();
5149 m_options->consoleFontPointSize = settings.value("consolefontsize", 10).toDouble();
5150
5151 m_options->consoleFontColor = settings.value("consoleFontColor",
5152 QVariant(QColor(Qt::black))).value<QColor>();
5153 m_options->consoleBgColor = settings.value("consoleBgColor",
5154 QVariant(QColor(Qt::white))).value<QColor>();
5155 m_options->editorBgColor = settings.value("editorBgColor",
5156 QVariant(QColor(Qt::white))).value<QColor>();
5157
5158 m_options->tabWidth = settings.value("tabWidth", 24).toInt();
5159 m_options->tabIndents = settings.value("tabIndents", false).toBool();
5160 // m_options->colorVariables = settings.value("colorvariables", true).toBool();
5161 m_options->highlightingTheme = settings.value("highlightingTheme", "light").toString();
5162 m_options->colorVariables = m_options->highlightingTheme != "none";
5163 m_options->autoPlay = settings.value("autoplay", false).toBool();
5164 m_options->autoJoin = settings.value("autoJoin", true).toBool();
5165 m_options->menuDepth = settings.value("menuDepth", 3).toInt();
5166 m_options->saveChanges = settings.value("savechanges", false).toBool();
5167 m_options->askIfTemporary = settings.value("askIfTemporary", false).toBool();
5168 m_options->rememberFile = settings.value("rememberfile", true).toBool();
5169 m_options->saveWidgets = settings.value("savewidgets", true).toBool();
5170 m_options->widgetsIndependent = settings.value("widgetsIndependent", false).toBool();
5171 m_options->iconText = settings.value("iconText", false).toBool();
5172 m_options->showToolbar = settings.value("showToolbar", true).toBool();
5173 m_options->lockToolbar = settings.value("lockToolbar", true).toBool();
5174 m_options->toolbarIconSize = settings.value("toolbarIconSize", 20).toInt();
5175 m_options->wrapLines = settings.value("wrapLines", true).toBool();
5176 m_options->autoComplete = settings.value("autoComplete", true).toBool();
5177 m_options->autoParameterMode = settings.value("autoParameterMode", true).toBool();
5178 m_options->enableWidgets = settings.value("enableWidgets", true).toBool();
5179 m_options->showWidgetsOnRun = settings.value("showWidgetsOnRun", true).toBool();
5180 m_options->showTooltips = settings.value("showTooltips", true).toBool();
5181 m_options->enableFLTK = settings.value("enableFLTK", true).toBool();
5182 m_options->terminalFLTK = settings.value("terminalFLTK", true).toBool();
5183 m_options->oldFormat = settings.value("oldFormat", false).toBool();
5184 m_options->openProperties = settings.value("openProperties", true).toBool();
5185 m_options->fontOffset = settings.value("fontOffset", 0.0).toDouble();
5186 m_options->fontScaling = settings.value("fontScaling", 1.0).toDouble();
5187 m_options->graphUpdateRate = settings.value("graphUpdateRate", 30).toInt();
5188 lastFiles = settings.value("lastfiles", QStringList()).toStringList();
5189 lastTabIndex = settings.value("lasttabindex", "").toInt();
5190 m_options->debugPort = settings.value("debugPort",34711).toInt();
5191 m_options->tabShortcutActive = settings.value("tabShortcutActive", true).toBool();
5192 settings.endGroup();
5193 settings.beginGroup("Run");
5194 m_options->useAPI = settings.value("useAPI", true).toBool();
5195 m_options->keyRepeat = settings.value("keyRepeat", false).toBool();
5196 m_options->debugLiveEvents = settings.value("debugLiveEvents", false).toBool();
5197 m_options->consoleBufferSize = settings.value("consoleBufferSize", 1024).toInt();
5198 m_options->checkSyntaxBeforeRun = settings.value("checkSyntaxBeforeRun", false).toBool();
5199 m_options->midiInterface = settings.value("midiInterface", 9999).toInt();
5200 m_options->midiInterfaceName = settings.value("midiInterfaceName", "None").toString();
5201 m_options->midiOutInterface = settings.value("midiOutInterface", 9999).toInt();
5202 m_options->midiOutInterfaceName = settings.value("midiOutInterfaceName", "None").toString();
5203 m_options->noBuffer = settings.value("noBuffer", false).toBool();
5204 m_options->noPython = settings.value("noPython", false).toBool();
5205 m_options->noMessages = settings.value("noMessages", false).toBool();
5206 m_options->noEvents = settings.value("noEvents", false).toBool();
5207
5208
5209 //experimental: enable setting internal RtMidi API in settings file. See RtMidi.h
5210 #ifdef QCS_RTMIDI
5211 QString rtMidiApiString = settings.value("rtMidiApi","UNSPECIFIED").toString();
5212 if (rtMidiApiString.toUpper()=="LINUX_ALSA" )
5213 m_options->rtMidiApi = RtMidi::LINUX_ALSA;
5214 else if (rtMidiApiString.toUpper()=="UNIX_JACK" )
5215 m_options->rtMidiApi = RtMidi::UNIX_JACK;
5216 else if (rtMidiApiString.toUpper()=="MACOSX_CORE" )
5217 m_options->rtMidiApi = RtMidi::MACOSX_CORE;
5218 else if (rtMidiApiString.toUpper()=="WINDOWS_MM" )
5219 m_options->rtMidiApi = RtMidi::WINDOWS_MM;
5220 else
5221 m_options->rtMidiApi = RtMidi::UNSPECIFIED;
5222 #endif
5223
5224 m_options->bufferSize = settings.value("bufferSize", 1024).toInt();
5225 m_options->bufferSizeActive = settings.value("bufferSizeActive", false).toBool();
5226 m_options->HwBufferSize = settings.value("HwBufferSize", 1024).toInt();
5227 m_options->HwBufferSizeActive = settings.value("HwBufferSizeActive", false).toBool();
5228 m_options->dither = settings.value("dither", false).toBool();
5229 m_options->newParser = settings.value("newParser", false).toBool();
5230 m_options->multicore = settings.value("multicore", false).toBool();
5231 m_options->numThreads = settings.value("numThreads", 1).toInt();
5232 m_options->additionalFlags = settings.value("additionalFlags", "").toString();
5233 m_options->useSystemSamplerate = settings.value("useSystemSamplerate", false).toBool();
5234 m_options->samplerate = settings.value("overrideSamplerate", 0).toInt();
5235 m_options->overrideNumChannels = settings.value("overrideNumChannels", false).toBool();
5236 m_options->numChannels = settings.value("numChannels", 0).toInt();
5237 m_options->realtimeFlag = settings.value("realtimeFlag", false).toBool();
5238 m_options->sampleAccurateFlag = settings.value("sampleAccurateFlag", false).toBool();
5239 if (settingsVersion < 1)
5240 m_options->additionalFlags.remove("-d"); // remove old -d preference, as it is fixed now.
5241 m_options->additionalFlagsActive = settings.value("additionalFlagsActive", false).toBool();
5242 m_options->fileUseOptions = settings.value("fileUseOptions", true).toBool();
5243 m_options->fileOverrideOptions = settings.value("fileOverrideOptions", false).toBool();
5244 m_options->fileAskFilename = settings.value("fileAskFilename", false).toBool();
5245 m_options->filePlayFinished = settings.value("filePlayFinished", false).toBool();
5246 m_options->fileFileType = settings.value("fileFileType", 0).toInt();
5247 m_options->fileSampleFormat = settings.value("fileSampleFormat", 1).toInt();
5248 m_options->fileInputFilenameActive = settings.value("fileInputFilenameActive", false).toBool();
5249 m_options->fileInputFilename = settings.value("fileInputFilename", "").toString();
5250 m_options->fileOutputFilenameActive = settings.value("fileOutputFilenameActive", false).toBool();
5251 m_options->fileOutputFilename = settings.value("fileOutputFilename", "").toString();
5252 m_options->rtUseOptions = settings.value("rtUseOptions", true).toBool();
5253 m_options->rtOverrideOptions = settings.value("rtOverrideOptions", false).toBool();
5254 m_options->rtAudioModule = settings.value("rtAudioModule", "pa_cb").toString();
5255 if (m_options->rtAudioModule.isEmpty()) { m_options->rtAudioModule = "pa_cb"; }
5256 m_options->rtInputDevice = settings.value("rtInputDevice", "adc").toString();
5257 m_options->rtOutputDevice = settings.value("rtOutputDevice", "dac").toString();
5258 m_options->rtJackName = settings.value("rtJackName", "").toString();
5259 if (settingsVersion < 2) {
5260 if (!m_options->rtJackName.endsWith("*"))
5261 m_options->rtJackName.append("*");
5262 }
5263 m_options->rtMidiModule = settings.value("rtMidiModule", "portmidi").toString();
5264 if (m_options->rtMidiModule.isEmpty()) { m_options->rtMidiModule = "portmidi"; }
5265 m_options->rtMidiInputDevice = settings.value("rtMidiInputDevice", "0").toString();
5266 m_options->rtMidiOutputDevice = settings.value("rtMidiOutputDevice", "").toString();
5267 m_options->useCsoundMidi = settings.value("useCsoundMidi", false).toBool();
5268 m_options->simultaneousRun = settings.value("simultaneousRun", "").toBool();
5269 m_options->sampleFormat = settings.value("sampleFormat", 0).toInt();
5270 settings.endGroup();
5271 settings.beginGroup("Environment");
5272 #ifdef Q_OS_MAC
5273 m_options->csdocdir = settings.value("csdocdir", DEFAULT_HTML_DIR).toString();
5274 #else
5275 m_options->csdocdir = settings.value("csdocdir", "").toString();
5276 #endif
5277 m_options->opcodedir = settings.value("opcodedir","").toString();
5278 m_options->opcodedirActive = settings.value("opcodedirActive",false).toBool();
5279 m_options->opcodedir64 = settings.value("opcodedir64","").toString();
5280 m_options->opcodedir64Active = settings.value("opcodedir64Active",false).toBool();
5281 m_options->opcode6dir64 = settings.value("opcode6dir64","").toString();
5282 m_options->opcode6dir64Active = settings.value("opcode6dir64Active",false).toBool();
5283 m_options->sadir = settings.value("sadir","").toString();
5284 m_options->sadirActive = settings.value("sadirActive","").toBool();
5285 m_options->ssdir = settings.value("ssdir","").toString();
5286 m_options->ssdirActive = settings.value("ssdirActive","").toBool();
5287 m_options->sfdir = settings.value("sfdir","").toString();
5288 m_options->sfdirActive = settings.value("sfdirActive","").toBool();
5289 m_options->incdir = settings.value("incdir","").toString();
5290 m_options->incdirActive = settings.value("incdirActive","").toBool();
5291 m_options->rawWave = settings.value("rawWave","").toString();
5292 m_options->rawWaveActive = settings.value("rawWaveActive","").toBool();
5293 m_options->defaultCsd = settings.value("defaultCsd","").toString();
5294 m_options->defaultCsdActive = settings.value("defaultCsdActive","").toBool();
5295 m_options->favoriteDir = settings.value("favoriteDir","").toString();
5296 m_options->pythonDir = settings.value("pythonDir","").toString();
5297 m_options->pythonExecutable = settings.value("pythonExecutable","python").toString();
5298 m_options->csoundExecutable = settings.value("csoundExecutable","csound").toString();
5299 m_options->logFile = settings.value("logFile",DEFAULT_LOG_FILE).toString();
5300 m_options->sdkDir = settings.value("sdkDir","").toString();
5301 m_options->templateDir = settings.value("templateDir","").toString();
5302 m_options->opcodexmldir = settings.value("opcodexmldir", "").toString();
5303 m_options->opcodexmldirActive = settings.value("opcodexmldirActive","").toBool();
5304 settings.endGroup();
5305 settings.beginGroup("External");
5306 m_options->terminal = settings.value("terminal", DEFAULT_TERM_EXECUTABLE).toString();
5307 m_options->browser = settings.value("browser", DEFAULT_BROWSER_EXECUTABLE).toString();
5308 m_options->dot = settings.value("dot", DEFAULT_DOT_EXECUTABLE).toString();
5309 m_options->waveeditor = settings.value("waveeditor",
5310 DEFAULT_WAVEEDITOR_EXECUTABLE
5311 ).toString();
5312 m_options->waveplayer = settings.value("waveplayer",
5313 DEFAULT_WAVEPLAYER_EXECUTABLE
5314 ).toString();
5315 m_options->pdfviewer = settings.value("pdfviewer",
5316 DEFAULT_PDFVIEWER_EXECUTABLE
5317 ).toString();
5318 settings.endGroup();
5319 settings.beginGroup("Template");
5320 m_options->csdTemplate = settings.value("csdTemplate", QCS_DEFAULT_TEMPLATE).toString();
5321 settings.endGroup();
5322 settings.endGroup();
5323 if (settingsVersion < 3 && settingsVersion > 0) {
5324 showNewFormatWarning();
5325 m_options->csdTemplate = QCS_DEFAULT_TEMPLATE;
5326 }
5327 }
5328
storeSettings()5329 void CsoundQt::storeSettings()
5330 {
5331 qDebug();
5332 QStringList files;
5333 if (m_options->rememberFile) {
5334 for (int i = 0; i < documentPages.size(); i++ ) {
5335 files.append(documentPages[i]->getFileName());
5336 }
5337 }
5338 // sometimes settings are stored in startup when there is no pages open
5339 int lastIndex = (documentPages.size()==0) ? 0 : documentTabs->currentIndex();
5340 if (documentPages.size() > 0) {
5341 writeSettings(files, lastIndex);
5342 } else {
5343 qDebug() << "No files open. Will not store settings (for any case - testing)";
5344 }
5345 }
5346
writeSettings(QStringList openFiles,int lastIndex)5347 void CsoundQt::writeSettings(QStringList openFiles, int lastIndex)
5348 {
5349 QSettings settings("csound", "qutecsound");
5350 if (!m_resetPrefs) {
5351 // Version 1 when clearing additional flags, version 2 when setting jack client to *
5352 // version 3 to store that new widget format warning has been shown.
5353 // version 4 to signal that the many shortcuts have been changed
5354 settings.setValue("settingsVersion", 4);
5355 }
5356 else {
5357 settings.remove("");
5358 }
5359 settings.beginGroup("GUI");
5360 if (!m_resetPrefs) {
5361 settings.setValue("pos", pos());
5362 settings.setValue("size", size());
5363 settings.setValue("dockstate", saveState());
5364 settings.setValue("lastuseddir", lastUsedDir);
5365 settings.setValue("lastfiledir", lastFileDir);
5366 settings.setValue("language", m_configlists.languageCodes[m_options->language]);
5367 // settings.setValue("liveEventsActive", showLiveEventsAct->isChecked());
5368 settings.setValue("recentFiles", recentFiles);
5369 settings.setValue("theme", m_options->theme);
5370 settings.setValue("windowState", saveState());
5371 settings.setValue("windowGeometry", saveGeometry());
5372 }
5373 else {
5374 settings.remove("");
5375 }
5376 QHash<QString, QVariant> shortcuts;
5377 foreach (QAction *act, m_keyActions) {
5378 shortcuts[act->text().remove("&")] = QVariant(act->shortcut().toString());
5379 }
5380 settings.setValue("shortcuts", QVariant(shortcuts));
5381 settings.endGroup();
5382 settings.beginGroup("Options");
5383 settings.beginGroup("Editor");
5384 if (!m_resetPrefs) {
5385 settings.setValue("font", m_options->font );
5386 settings.setValue("fontsize", m_options->fontPointSize);
5387 settings.setValue("showLineNumberArea", m_options->showLineNumberArea);
5388 settings.setValue("lineEnding", m_options->lineEnding);
5389 settings.setValue("consolefont", m_options->consoleFont );
5390 settings.setValue("consolefontsize", m_options->consoleFontPointSize);
5391 settings.setValue("consoleFontColor", QVariant(m_options->consoleFontColor));
5392 settings.setValue("consoleBgColor", QVariant(m_options->consoleBgColor));
5393 settings.setValue("editorBgColor", QVariant(m_options->editorBgColor));
5394 settings.setValue("tabWidth", m_options->tabWidth );
5395 settings.setValue("tabIndents", m_options->tabIndents);
5396 settings.setValue("colorvariables", m_options->colorVariables);
5397 settings.setValue("highlightingTheme", m_options->highlightingTheme);
5398 settings.setValue("autoplay", m_options->autoPlay);
5399 settings.setValue("autoJoin", m_options->autoJoin);
5400 settings.setValue("menuDepth", m_options->menuDepth);
5401 settings.setValue("savechanges", m_options->saveChanges);
5402 settings.setValue("askIfTemporary", m_options->askIfTemporary);
5403 settings.setValue("rememberfile", m_options->rememberFile);
5404 settings.setValue("savewidgets", m_options->saveWidgets);
5405 settings.setValue("widgetsIndependent", m_options->widgetsIndependent);
5406 settings.setValue("iconText", m_options->iconText);
5407 settings.setValue("showToolbar", m_options->showToolbar);
5408 settings.setValue("lockToolbar", m_options->lockToolbar);
5409 settings.setValue("toolbarIconSize", m_options->toolbarIconSize);
5410 settings.setValue("wrapLines", m_options->wrapLines);
5411 settings.setValue("autoComplete", m_options->autoComplete);
5412 settings.setValue("autoParameterMode", m_options->autoParameterMode);
5413 settings.setValue("enableWidgets", m_options->enableWidgets);
5414 settings.setValue("showWidgetsOnRun", m_options->showWidgetsOnRun);
5415 settings.setValue("graphUpdateRate", m_options->graphUpdateRate);
5416 settings.setValue("showTooltips", m_options->showTooltips);
5417 settings.setValue("enableFLTK", m_options->enableFLTK);
5418 settings.setValue("terminalFLTK", m_options->terminalFLTK);
5419 settings.setValue("oldFormat", m_options->oldFormat);
5420 settings.setValue("openProperties", m_options->openProperties);
5421 settings.setValue("fontOffset", m_options->fontOffset);
5422 settings.setValue("fontScaling", m_options->fontScaling);
5423 settings.setValue("lastfiles", openFiles);
5424 settings.setValue("lasttabindex", lastIndex);
5425 settings.setValue("debugPort", m_options->debugPort);
5426 settings.setValue("tabShortcutActive", m_options->tabShortcutActive);
5427 }
5428 else {
5429 settings.remove("");
5430 }
5431 settings.endGroup();
5432 settings.beginGroup("Run");
5433 if (!m_resetPrefs) {
5434 settings.setValue("useAPI", m_options->useAPI);
5435 settings.setValue("keyRepeat", m_options->keyRepeat);
5436 settings.setValue("debugLiveEvents", m_options->debugLiveEvents);
5437 settings.setValue("consoleBufferSize", m_options->consoleBufferSize);
5438 settings.setValue("midiInterface", m_options->midiInterface);
5439 settings.setValue("midiInterfaceName", m_options->midiInterfaceName);
5440 settings.setValue("midiOutInterface", m_options->midiOutInterface);
5441 settings.setValue("midiOutInterfaceName", m_options->midiOutInterfaceName);
5442 settings.setValue("noBuffer", m_options->noBuffer);
5443 settings.setValue("noPython", m_options->noPython);
5444 settings.setValue("noMessages", m_options->noMessages);
5445 settings.setValue("noEvents", m_options->noEvents);
5446 settings.setValue("bufferSize", m_options->bufferSize);
5447 settings.setValue("bufferSizeActive", m_options->bufferSizeActive);
5448 settings.setValue("HwBufferSize",m_options->HwBufferSize);
5449 settings.setValue("HwBufferSizeActive", m_options->HwBufferSizeActive);
5450 settings.setValue("dither", m_options->dither);
5451 settings.setValue("realtimeFlag", m_options->realtimeFlag);
5452 settings.setValue("sampleAccurateFlag", m_options->sampleAccurateFlag);
5453 settings.setValue("newParser", m_options->newParser);
5454 settings.setValue("multicore", m_options->multicore);
5455 settings.setValue("numThreads", m_options->numThreads);
5456 settings.setValue("useSystemSamplerate", m_options->useSystemSamplerate);
5457 settings.setValue("overrideSamplerate", m_options->samplerate);
5458 settings.setValue("overrideNumChannels", m_options->overrideNumChannels);
5459 settings.setValue("numChannels", m_options->numChannels);
5460
5461 settings.setValue("additionalFlags", m_options->additionalFlags);
5462 settings.setValue("additionalFlagsActive", m_options->additionalFlagsActive);
5463 settings.setValue("fileUseOptions", m_options->fileUseOptions);
5464 settings.setValue("fileOverrideOptions", m_options->fileOverrideOptions);
5465 settings.setValue("fileAskFilename", m_options->fileAskFilename);
5466 settings.setValue("filePlayFinished", m_options->filePlayFinished);
5467 settings.setValue("fileFileType", m_options->fileFileType);
5468 settings.setValue("fileSampleFormat", m_options->fileSampleFormat);
5469 settings.setValue("fileInputFilenameActive", m_options->fileInputFilenameActive);
5470 settings.setValue("fileInputFilename", m_options->fileInputFilename);
5471 settings.setValue("fileOutputFilenameActive", m_options->fileOutputFilenameActive);
5472 settings.setValue("fileOutputFilename", m_options->fileOutputFilename);
5473 settings.setValue("rtUseOptions", m_options->rtUseOptions);
5474 settings.setValue("rtOverrideOptions", m_options->rtOverrideOptions);
5475 settings.setValue("rtAudioModule", m_options->rtAudioModule);
5476 settings.setValue("rtInputDevice", m_options->rtInputDevice);
5477 settings.setValue("rtOutputDevice", m_options->rtOutputDevice);
5478 settings.setValue("rtJackName", m_options->rtJackName);
5479 settings.setValue("rtMidiModule", m_options->rtMidiModule);
5480 settings.setValue("rtMidiInputDevice", m_options->rtMidiInputDevice);
5481 settings.setValue("rtMidiOutputDevice", m_options->rtMidiOutputDevice);
5482 settings.setValue("useCsoundMidi", m_options->useCsoundMidi);
5483 settings.setValue("simultaneousRun", m_options->simultaneousRun);
5484 settings.setValue("sampleFormat", m_options->sampleFormat);
5485 settings.setValue("checkSyntaxBeforeRun", m_options->checkSyntaxBeforeRun);
5486 }
5487 else {
5488 settings.remove("");
5489 }
5490 settings.endGroup();
5491 settings.beginGroup("Environment");
5492 if (!m_resetPrefs) {
5493 settings.setValue("csdocdir", m_options->csdocdir);
5494 settings.setValue("opcodedir",m_options->opcodedir);
5495 settings.setValue("opcodedirActive",m_options->opcodedirActive);
5496 settings.setValue("opcodedir64",m_options->opcodedir64);
5497 settings.setValue("opcodedir64Active",m_options->opcodedir64Active);
5498 settings.setValue("opcode6dir64",m_options->opcode6dir64);
5499 settings.setValue("opcode6dir64Active",m_options->opcode6dir64Active);
5500 settings.setValue("sadir",m_options->sadir);
5501 settings.setValue("sadirActive",m_options->sadirActive);
5502 settings.setValue("ssdir",m_options->ssdir);
5503 settings.setValue("ssdirActive",m_options->ssdirActive);
5504 settings.setValue("sfdir",m_options->sfdir);
5505 settings.setValue("sfdirActive",m_options->sfdirActive);
5506 settings.setValue("incdir",m_options->incdir);
5507 settings.setValue("incdirActive",m_options->incdirActive);
5508 settings.setValue("rawWave",m_options->rawWave);
5509 settings.setValue("rawWaveActive",m_options->rawWaveActive);
5510 settings.setValue("defaultCsd",m_options->defaultCsd);
5511 settings.setValue("defaultCsdActive",m_options->defaultCsdActive);
5512 settings.setValue("favoriteDir",m_options->favoriteDir);
5513 settings.setValue("pythonDir",m_options->pythonDir);
5514 settings.setValue("pythonExecutable",m_options->pythonExecutable);
5515 settings.setValue("csoundExecutable", m_options->csoundExecutable);
5516 settings.setValue("logFile",m_options->logFile);
5517 settings.setValue("sdkDir",m_options->sdkDir);
5518 settings.setValue("templateDir",m_options->templateDir);
5519 settings.setValue("opcodexmldir", m_options->opcodexmldir); // TEST can be that this is the reason for crash MacOS - dir set wrong from corrupted plist file
5520 settings.setValue("opcodexmldirActive",m_options->opcodexmldirActive);
5521 }
5522 else {
5523 settings.remove("");
5524 }
5525 settings.endGroup();
5526 settings.beginGroup("External");
5527 if (!m_resetPrefs) {
5528 settings.setValue("terminal", m_options->terminal);
5529 settings.setValue("browser", m_options->browser);
5530 settings.setValue("dot", m_options->dot);
5531 settings.setValue("waveeditor", m_options->waveeditor);
5532 settings.setValue("waveplayer", m_options->waveplayer);
5533 settings.setValue("pdfviewer", m_options->pdfviewer);
5534 }
5535 else {
5536 settings.remove("");
5537 }
5538 settings.endGroup();
5539 settings.beginGroup("Template");
5540 settings.setValue("csdTemplate", m_options->csdTemplate);
5541 settings.endGroup();
5542 settings.endGroup();
5543
5544 settings.sync();
5545 }
5546
clearSettings()5547 void CsoundQt::clearSettings()
5548 {
5549 QSettings settings("csound", "qutecsound");
5550 settings.remove("");
5551 settings.beginGroup("GUI");
5552 settings.beginGroup("Shortcuts");
5553 settings.remove("");
5554 settings.endGroup();
5555 settings.endGroup();
5556 settings.beginGroup("Options");
5557 settings.remove("");
5558 settings.beginGroup("Editor");
5559 settings.remove("");
5560 settings.endGroup();
5561 settings.beginGroup("Run");
5562 settings.remove("");
5563 settings.endGroup();
5564 settings.beginGroup("Environment");
5565 settings.remove("");
5566 settings.endGroup();
5567 settings.beginGroup("External");
5568 settings.remove("");
5569 settings.endGroup();
5570 settings.endGroup();
5571
5572 settings.sync();
5573 }
5574
execute(QString executable,QString options)5575 int CsoundQt::execute(QString executable, QString options)
5576 {
5577 int ret = 0;
5578
5579 #ifdef Q_OS_MAC
5580 QString commandLine = "open -a \"" + executable + "\" " + options;
5581 #endif
5582 #ifdef Q_OS_LINUX
5583 QString commandLine = "\"" + executable + "\" " + options;
5584 #endif
5585 #ifdef Q_OS_FREEBSD
5586 QString commandLine = "\"" + executable + "\" " + options;
5587 #endif
5588 #ifdef Q_OS_HAIKU
5589 QString commandLine = "\"" + executable + "\" " + options;
5590 #endif
5591 #ifdef Q_OS_SOLARIS
5592 QString commandLine = "\"" + executable + "\" " + options;
5593 #endif
5594 #ifdef Q_OS_WIN32
5595 QString commandLine = "\"" + executable + "\" " + (executable.startsWith("cmd")? " /k " : " ") + options;
5596 auto command_line = commandLine.toUtf8();
5597 qDebug() << "command_line: " << command_line;
5598 std::thread system_thread([command_line]{std::system(command_line);});
5599 system_thread.detach();
5600 #else
5601 QString path = documentPages[curPage]->getFilePath();
5602 if (path.startsWith(":/examples/", Qt::CaseInsensitive)) {
5603 // example or other embedded file
5604 path = QDir::tempPath(); // copy of example is saved there
5605 }
5606 qDebug() << "CsoundQt::execute " << commandLine << path;
5607 QProcess *p = new QProcess(this);
5608 p->setWorkingDirectory(path);
5609 p->start(commandLine);
5610 Q_PID id = p->pid();
5611 qDebug() << "Launched external program with id:" << id;
5612 ret = !p->waitForStarted() ? 1 : 0;
5613 #endif
5614 return ret;
5615 }
5616
loadFileFromSystem(QString fileName)5617 int CsoundQt::loadFileFromSystem(QString fileName)
5618 {
5619 return loadFile(fileName,m_options->autoPlay);
5620 }
5621
changeNewLines(QByteArray & line)5622 void changeNewLines(QByteArray &line) {
5623 while(line.contains("\r\n")) {
5624 line.replace("\r\n", "\n");
5625 }
5626 while (line.contains("\r")) {
5627 line.replace("\r", "\n");
5628 }
5629 }
5630
fillCompanionSco(QString & fileName,QString & text)5631 void fillCompanionSco(QString &fileName, QString &text) {
5632 auto companionFileName = fileName.replace(".orc", ".sco");
5633 if (!QFile::exists(companionFileName))
5634 return;
5635 text.prepend("<CsoundSynthesizer>\n<CsOptions>\n</CsOptions>\n<CsInstruments>\n");
5636 text.append("\n</CsInstruments>\n<CsScore>\n");
5637 QFile companionFile(companionFileName);
5638 if (!companionFile.open(QFile::ReadOnly))
5639 return;
5640 while (!companionFile.atEnd()) {
5641 QByteArray line = companionFile.readLine();
5642 changeNewLines(line);
5643 QTextDecoder decoder(QTextCodec::codecForLocale());
5644 text = text + decoder.toUnicode(line);
5645 if (!line.endsWith("\n"))
5646 text.append("\n");
5647 }
5648 text.append("</CsScore>\n</CsoundSynthesizer>\n");
5649 }
5650
fillCompanionOrc(QString & fileName,QString & text)5651 void fillCompanionOrc(QString &fileName, QString &text) {
5652 auto companionFileName = fileName.replace(".sco", ".orc");
5653 if (!QFile::exists(companionFileName))
5654 return;
5655 QFile companionFlle(companionFileName);
5656 QString orcText = "";
5657 if (!companionFlle.open(QFile::ReadOnly))
5658 return;
5659 while (!companionFlle.atEnd()) {
5660 QByteArray line = companionFlle.readLine();
5661 changeNewLines(line);
5662 QTextDecoder decoder(QTextCodec::codecForLocale());
5663 orcText = orcText + decoder.toUnicode(line);
5664 if (!line.endsWith("\n"))
5665 orcText += "\n";
5666 }
5667 text.prepend("\n</CsInstruments>\n<CsScore>\n");
5668 text.prepend(orcText);
5669 text.prepend("<CsoundSynthesizer>\n<CsOptions>\n</CsOptions>\n<CsInstruments>\n");
5670 text += "</CsScore>\n</CsoundSynthesizer>\n";
5671 }
5672
loadFile(QString fileName,bool runNow)5673 int CsoundQt::loadFile(QString fileName, bool runNow)
5674 {
5675 if (fileName.endsWith(".pdf")) {
5676 openPdfFile(fileName);
5677 return 0;
5678 }
5679 int index = isOpen(fileName);
5680 if (index != -1) {
5681 documentTabs->setCurrentIndex(index);
5682 changePage(index);
5683 return index;
5684 }
5685 QFile file(fileName);
5686 if (!file.open(QFile::ReadOnly)) {
5687 QMessageBox::warning(this, tr("CsoundQt"),
5688 tr("Cannot read file %1:\n%2.")
5689 .arg(fileName)
5690 .arg(file.errorString()));
5691 return -1;
5692 }
5693 QApplication::setOverrideCursor(Qt::WaitCursor);
5694
5695 QString text;
5696 QStringList lines;
5697 bool inEncFile = false;
5698 while (!file.atEnd()) {
5699 QByteArray line = file.readLine();
5700 if (line.contains("<CsFileB ")) {
5701 inEncFile = true;
5702 }
5703 if (!inEncFile) {
5704 changeNewLines(line);
5705 QTextDecoder decoder(QTextCodec::codecForLocale());
5706 // text = text + decoder.toUnicode(line);
5707 if (!line.endsWith("\n"))
5708 text += "\n";
5709 lines << text + decoder.toUnicode(line);
5710 }
5711 else {
5712 // text += line;
5713 lines << line;
5714 if (line.contains("</CsFileB>" && !line.contains("<CsFileB " )) ) {
5715 inEncFile = false;
5716 }
5717 }
5718 }
5719 text = lines.join("");
5720 if (m_options->autoJoin) {
5721 // QString companionFileName = fileName;
5722 if (fileName.endsWith(".orc"))
5723 fillCompanionSco(fileName, text);
5724 else if (fileName.endsWith(".sco"))
5725 fillCompanionOrc(fileName, text);
5726 }
5727
5728 if (fileName == ":/default.csd") {
5729 fileName = QString("");
5730 }
5731
5732 if (!makeNewPage(fileName, text)) {
5733 QApplication::restoreOverrideCursor();
5734 return -1;
5735 }
5736
5737 if (!m_options->autoJoin &&
5738 (fileName.endsWith(".sco") ||
5739 fileName.endsWith(".orc")) ) {
5740 // load companion, when the new page is made, otherwise isOpen works uncorrect
5741 loadCompanionFile(fileName);
5742 }
5743
5744 if (m_options->autoJoin &&
5745 (fileName.endsWith(".sco") || fileName.endsWith(".orc"))) {
5746 fileName.chop(4);
5747 fileName += ".csd";
5748 documentPages[curPage]->setFileName(fileName); // Must update internal name
5749 setCurrentFile(fileName);
5750 if (!QFile::exists(fileName))
5751 save();
5752 else
5753 saveAs();
5754 } else {
5755 documentPages[curPage]->setModified(false);
5756 setWindowModified(false);
5757 documentTabs->setTabIcon(curPage, QIcon());
5758 }
5759
5760 if (fileName.startsWith(m_options->csdocdir) && !m_options->csdocdir.isEmpty()) {
5761 documentPages[curPage]->readOnly = true;
5762 }
5763 QApplication::restoreOverrideCursor();
5764
5765 // FIXME put back
5766 // widgetPanel->clearHistory();
5767 if (runNow) {
5768 play();
5769 }
5770 return curPage;
5771 }
5772
makeNewPage(QString fileName,QString text)5773 bool CsoundQt::makeNewPage(QString fileName, QString text)
5774 {
5775 if (documentPages.size() >= MAX_THREAD_COUNT) {
5776 QMessageBox::warning(this, tr("Document number limit"),
5777 tr("Please close a document before opening another."));
5778 return false;
5779 }
5780 DocumentPage *newPage = new DocumentPage(this, m_opcodeTree, &m_configlists, m_midiLearn);
5781 int insertPoint = curPage + 1;
5782 curPage += 1;
5783 if (documentPages.size() == 0) {
5784 insertPoint = 0;
5785 curPage = 0;
5786 }
5787 documentPages.insert(insertPoint, newPage);
5788 // documentPages[curPage]->setOpcodeNameList(m_opcodeTree->opcodeNameList());
5789 documentPages[curPage]->showLiveEventControl(false);
5790 setCurrentOptionsForPage(documentPages[curPage]);
5791
5792 // Must set before sending text to set highlighting mode
5793 documentPages[curPage]->setFileName(fileName);
5794
5795 #ifdef QCS_PYTHONQT
5796 documentPages[curPage]->getEngine()->setPythonConsole(m_pythonConsole);
5797 #endif
5798
5799 connectActions();
5800 // connect(documentPages[curPage], SIGNAL(currentTextUpdated()), this, SLOT(markInspectorUpdate()));
5801 // connect(documentPages[curPage], SIGNAL(modified()), this, SLOT(documentWasModified()));
5802 // // connect(documentPages[curPage], SIGNAL(setWidgetClipboardSignal(QString)),
5803 // // this, SLOT(setWidgetClipboard(QString)));
5804 // connect(documentPages[curPage], SIGNAL(setCurrentAudioFile(QString)),
5805 // this, SLOT(setCurrentAudioFile(QString)));
5806 // connect(documentPages[curPage], SIGNAL(evaluatePythonSignal(QString)),
5807 // this, SLOT(evaluatePython(QString)));
5808 auto page = documentPages[curPage];
5809 page->loadTextString(text);
5810 if (m_options->widgetsIndependent) {
5811 // documentPages[curPage]->setWidgetLayoutOuterGeometry(documentPages[curPage]->getWidgetLayoutOuterGeometry());
5812 page->getWidgetLayout()->setGeometry(page->getWidgetLayoutOuterGeometry());
5813 }
5814 // setWidgetPanelGeometry();
5815
5816 if (!fileName.startsWith(":/")) { // Don't store internal examples in recents menu
5817 lastUsedDir = fileName;
5818 lastUsedDir.resize(fileName.lastIndexOf(QRegExp("[/]")) + 1);
5819 }
5820 if (recentFiles.count(fileName) == 0 && fileName!="" && !fileName.startsWith(":/")) {
5821 recentFiles.prepend(fileName);
5822 if (recentFiles.size() > QCS_MAX_RECENT_FILES)
5823 recentFiles.removeLast();
5824 fillFileMenu();
5825 }
5826 documentTabs->insertTab(curPage, page->getView(),"");
5827 documentTabs->setCurrentIndex(curPage);
5828
5829 midiHandler->addListener(page);
5830 page->getEngine()->setMidiHandler(midiHandler);
5831
5832 setCurrentOptionsForPage(page); // Redundant but does the trick of setting the font properly now that stylesheets are being used...
5833 // storeSettings(); // try: do not store on making new page still...
5834 return true;
5835 }
5836
loadCompanionFile(const QString & fileName)5837 bool CsoundQt::loadCompanionFile(const QString &fileName)
5838 {
5839 QString companionFileName = fileName;
5840 if (fileName.endsWith(".orc")) {
5841 companionFileName.replace(".orc", ".sco");
5842 }
5843 else if (fileName.endsWith(".sco")) {
5844 companionFileName.replace(".sco", ".orc");
5845 }
5846 else {
5847 return false;
5848 }
5849 if (QFile::exists(companionFileName)) {
5850 return (loadFile(companionFileName) != -1);
5851 }
5852 return false;
5853 }
5854
saveFile(const QString & fileName,bool saveWidgets)5855 bool CsoundQt::saveFile(const QString &fileName, bool saveWidgets)
5856 {
5857 // qDebug("CsoundQt::saveFile");
5858 // update htmlview on Save
5859 #if defined(QCS_QTHTML)
5860 if (!documentPages.isEmpty()) {
5861 qDebug()<<"Update html on save";
5862 updateHtmlView();
5863 }
5864 #endif
5865 QString text;
5866 QApplication::setOverrideCursor(Qt::WaitCursor);
5867 if (!m_options->widgetsIndependent) { // Update outer geometry information for writing
5868 QWidget *s = widgetPanel->widget();
5869 // widgetPanel->applySize(); //Store size of outer panel as size of widget
5870 if (s != 0) {
5871 QRect panelGeometry = widgetPanel->geometry();
5872 if (!widgetPanel->isFloating()) {
5873 panelGeometry.setX(-1);
5874 panelGeometry.setY(-1);
5875 }
5876 documentPages[curPage]->setWidgetLayoutOuterGeometry(panelGeometry);
5877 } else {
5878 documentPages[curPage]->setWidgetLayoutOuterGeometry(QRect());
5879 }
5880 }
5881 if (m_options->saveWidgets && saveWidgets)
5882 text = documentPages[curPage]->getFullText();
5883 else
5884 text = documentPages[curPage]->getBasicText();
5885 QApplication::restoreOverrideCursor();
5886
5887 if (fileName != documentPages[curPage]->getFileName()) {
5888 documentPages[curPage]->setFileName(fileName);
5889 setCurrentFile(fileName);
5890 }
5891 lastUsedDir = fileName;
5892 lastUsedDir.resize(fileName.lastIndexOf("/") + 1);
5893 if (recentFiles.count(fileName) == 0) {
5894 recentFiles.prepend(fileName);
5895 recentFiles.removeLast();
5896 fillFileMenu();
5897 }
5898 QFile file(fileName);
5899 if (!file.open(QFile::WriteOnly)) {
5900 QMessageBox::warning(this, tr("Application"),
5901 tr("Cannot write file %1:\n%2.")
5902 .arg(fileName)
5903 .arg(file.errorString()));
5904 return false;
5905 }
5906
5907 QTextStream out(&file);
5908 out << text;
5909 documentPages[curPage]->setModified(false);
5910 setWindowModified(false);
5911 documentTabs->setTabIcon(curPage, QIcon());
5912 return true;
5913 }
5914
setCurrentFile(const QString & fileName)5915 void CsoundQt::setCurrentFile(const QString &fileName)
5916 {
5917 QString shownName;
5918 if (fileName.isEmpty())
5919 shownName = "untitled.csd";
5920 else
5921 shownName = strippedName(fileName);
5922
5923 setWindowTitle(tr("%1[*] - %2").arg(shownName).arg(tr("CsoundQt")));
5924 documentTabs->setTabText(curPage, shownName);
5925 // updateWidgets();
5926 }
5927
strippedName(const QString & fullFileName)5928 QString CsoundQt::strippedName(const QString &fullFileName)
5929 {
5930 return QFileInfo(fullFileName).fileName();
5931 }
5932
generateScript(bool realtime,QString tempFileName,QString executable)5933 QString CsoundQt::generateScript(bool realtime, QString tempFileName, QString executable)
5934 {
5935 #ifndef Q_OS_WIN32
5936 QString script = "#!/bin/sh\n";
5937 #else
5938 QString script = "";
5939 #endif
5940 QString cmdLine = "";
5941 // Only OPCODEDIR left here as it must be present before csound initializes
5942 // The problem is that it can't be passed when using the API...
5943 #ifdef USE_DOUBLE
5944 if (m_options->opcodedir64Active)
5945 script += "export OPCODEDIR64=" + m_options->opcodedir64 + "\n";
5946 if (m_options->opcode6dir64Active)
5947 script += "export OPCODE6DIR64=" + m_options->opcode6dir64 + "\n";
5948 #else
5949 if (m_options->opcodedirActive)
5950 script += "export OPCODEDIR=" + m_options->opcodedir + "\n";
5951 #endif
5952
5953 #ifndef Q_OS_WIN32
5954 script += "cd " + QFileInfo(documentPages[curPage]->getFileName()).absolutePath() + "\n";
5955 #else
5956 QString script_cd = "@pushd " + QFileInfo(documentPages[curPage]->getFileName()).absolutePath() + "\n";
5957 script_cd.replace("/", "\\");
5958 script += script_cd;
5959 #endif
5960
5961 if (executable.isEmpty()) {
5962 cmdLine = m_options->csoundExecutable+ " ";
5963 qDebug()<<cmdLine;
5964 //#ifdef Q_OS_MAC
5965 // cmdLine = "/usr/local/bin/csound ";
5966 //#else
5967 // cmdLine = "csound ";
5968 //#endif
5969 m_options->rt = (realtime && m_options->rtUseOptions)
5970 || (!realtime && m_options->fileUseOptions);
5971 cmdLine += m_options->generateCmdLineFlags() + " ";
5972 }
5973 else {
5974 cmdLine = executable + " ";
5975 }
5976
5977 if (tempFileName == ""){
5978 QString fileName = documentPages[curPage]->getFileName();
5979 if (documentPages[curPage]->getCompanionFileName() != "") {
5980 QString companionFile = documentPages[curPage]->getCompanionFileName();
5981 if (fileName.endsWith(".orc"))
5982 cmdLine += "\"" + fileName
5983 + "\" \""+ companionFile + "\" ";
5984 else
5985 cmdLine += "\"" + companionFile
5986 + "\" \""+ fileName + "\" ";
5987 }
5988 else if (fileName.endsWith(".csd",Qt::CaseInsensitive)) {
5989 cmdLine += "\"" + fileName + "\" ";
5990 }
5991 }
5992 else {
5993 cmdLine += "\"" + tempFileName + "\" ";
5994 }
5995 // m_options->rt = (realtime and m_options->rtUseOptions)
5996 // or (!realtime and m_options->fileUseOptions);
5997 // cmdLine += m_options->generateCmdLineFlags();
5998 script += "echo \"" + cmdLine + "\"\n";
5999 script += cmdLine + "\n";
6000
6001 #ifndef Q_OS_WIN32
6002 script += "echo \"\nPress return to continue\"\n";
6003 script += "dummy_var=\"\"\n";
6004 script += "read dummy_var\n";
6005 script += "rm $0\n";
6006 #else
6007 script += "@echo.\n";
6008 script += "@pause\n";
6009 script += "@exit\n";
6010 #endif
6011 return script;
6012 }
6013
getCompanionFileName()6014 void CsoundQt::getCompanionFileName()
6015 {
6016 QString fileName = "";
6017 QDialog dialog(this);
6018 dialog.resize(400, 200);
6019 dialog.setModal(true);
6020 QPushButton *button = new QPushButton(tr("Ok"));
6021
6022 connect(button, SIGNAL(released()), &dialog, SLOT(accept()));
6023
6024 QSplitter *splitter = new QSplitter(&dialog);
6025 QListWidget *list = new QListWidget(&dialog);
6026 QCheckBox *checkbox = new QCheckBox(tr("Do not ask again"), &dialog);
6027 splitter->addWidget(list);
6028 splitter->addWidget(checkbox);
6029 splitter->addWidget(button);
6030 splitter->resize(400, 200);
6031 splitter->setOrientation(Qt::Vertical);
6032 QString extensionComplement = "";
6033 if (documentPages[curPage]->getFileName().endsWith(".orc"))
6034 extensionComplement = ".sco";
6035 else if (documentPages[curPage]->getFileName().endsWith(".sco"))
6036 extensionComplement = ".orc";
6037 else if (documentPages[curPage]->getFileName().endsWith(".udo"))
6038 extensionComplement = ".csd";
6039 else if (documentPages[curPage]->getFileName().endsWith(".inc"))
6040 extensionComplement = ".csd";
6041
6042 for (int i = 0; i < documentPages.size(); i++) {
6043 QString name = documentPages[i]->getFileName();
6044 if (name.endsWith(extensionComplement))
6045 list->addItem(name);
6046 }
6047 QList<QListWidgetItem *> itemList = list->findItems(
6048 documentPages[curPage]->getCompanionFileName(),
6049 Qt::MatchExactly);
6050 if (itemList.size() > 0)
6051 list->setCurrentItem(itemList[0]);
6052 dialog.exec();
6053 QListWidgetItem *item = list->currentItem();
6054 if (!item) {
6055 qDebug() << "Empty list. Create empty score file";
6056 QString companion = "";
6057 if (documentPages[curPage]->getFileName().endsWith(".orc")) {
6058 // create an empty score file to run the orchestra scorelessly
6059
6060 #ifdef USE_QT5
6061 companion = QStandardPaths::writableLocation(QStandardPaths::TempLocation) + "/empty.sco"; // QT >5.0
6062 QFile f(companion); // does it create it here
6063 #else
6064 companion = QDesktopServices::storageLocation(QDesktopServices::TempLocation) + "/empty.sco";
6065 #endif
6066 f.open(QIODevice::ReadWrite | QIODevice::Text);
6067 f.close();
6068 qDebug() << "Created empty score file as companion: " << companion;
6069 }
6070 documentPages[curPage]->setCompanionFileName(companion);
6071 return;
6072 }
6073 QString itemText = item->text();
6074 if (checkbox->isChecked())
6075 documentPages[curPage]->askForFile = false;
6076 documentPages[curPage]->setCompanionFileName(itemText);
6077 for (int i = 0; i < documentPages.size(); i++) {
6078 if (documentPages[i]->getFileName() == documentPages[curPage]->getCompanionFileName()
6079 && !documentPages[i]->getFileName().endsWith(".csd")) {
6080 documentPages[i]->setCompanionFileName(documentPages[curPage]->getFileName());
6081 documentPages[i]->askForFile = documentPages[curPage]->askForFile;
6082 break;
6083 }
6084 }
6085 }
6086
setWidgetPanelGeometry()6087 void CsoundQt::setWidgetPanelGeometry()
6088 {
6089 QRect geometry = documentPages[curPage]->getWidgetLayoutOuterGeometry();
6090 // qDebug() << "CsoundQt::setWidgetPanelGeometry() " << geometry;
6091 if (geometry.width() <= 0 || geometry.width() > 4096) {
6092 geometry.setWidth(400);
6093 qDebug() << "Warning: width invalid.";
6094 }
6095 if (geometry.height() <= 0 || geometry.height() > 4096) {
6096 geometry.setHeight(300);
6097 qDebug() << "Warning: height invalid.";
6098 }
6099 if (geometry.x() < 0 || geometry.x() > 4096) {
6100 geometry.setX(20);
6101 qDebug() << "Warning: X position invalid.";
6102 }
6103 if (geometry.y() < 0 || geometry.y() > 4096) {
6104 geometry.setY(0);
6105 qDebug() << "Warning: Y position invalid.";
6106 }
6107 // qDebug() << "geom " << widgetPanel->geometry() << " frame " << widgetPanel->frameGeometry();
6108 widgetPanel->setGeometry(geometry);
6109 }
6110
isOpen(QString fileName)6111 int CsoundQt::isOpen(QString fileName)
6112 {
6113 int open = -1;
6114 int i = 0;
6115 for (i = 0; i < documentPages.size(); i++) {
6116 if (documentPages[i]->getFileName() == fileName) {
6117 open = i;
6118 break;
6119 }
6120 }
6121 return open;
6122 }
6123
6124 //void *CsoundQt::getCurrentCsound()
6125 //{
6126 // return (void *)documentPages[curCsdPage]->getCsound();
6127 //}
6128
setDocument(int index)6129 QString CsoundQt::setDocument(int index)
6130 {
6131 QString name = QString();
6132 if (index < documentTabs->count() && index >= 0) {
6133 documentTabs->setCurrentIndex(index);
6134 name = documentPages[index]->getFileName();
6135 }
6136 return name;
6137 }
6138
insertText(QString text,int index,int section)6139 void CsoundQt::insertText(QString text, int index, int section)
6140 {
6141 if (index == -1) {
6142 index = curPage;
6143 }
6144 if (section == -1) {
6145 if (index < documentTabs->count() && index >= 0) {
6146 documentPages[index]->insertText(text);
6147 }
6148 }
6149 else {
6150 qDebug() << "Not implemented for sections";
6151 }
6152 }
6153
setCsd(QString text,int index)6154 void CsoundQt::setCsd(QString text, int index)
6155 {
6156 if (index == -1) {
6157 index = curPage;
6158 }
6159 if (index < documentTabs->count() && index >= 0) {
6160 documentPages[index]->setBasicText(text);
6161 }
6162 }
6163
setFullText(QString text,int index)6164 void CsoundQt::setFullText(QString text, int index)
6165 {
6166 if (index == -1) {
6167 index = curPage;
6168 }
6169 if (index < documentTabs->count() && index >= 0) {
6170 documentPages[index]->setFullText(text);
6171 }
6172 }
6173
setOrc(QString text,int index)6174 void CsoundQt::setOrc(QString text, int index)
6175 {
6176 if (index == -1) {
6177 index = curPage;
6178 }
6179 if (index < documentTabs->count() && index >= 0) {
6180 documentPages[index]->setOrc(text);
6181 }
6182 }
6183
setSco(QString text,int index)6184 void CsoundQt::setSco(QString text, int index)
6185 {
6186 if (index == -1) {
6187 index = curPage;
6188 }
6189 if (index < documentTabs->count() && index >= 0) {
6190 documentPages[index]->setSco(text);
6191 }
6192 }
6193
setWidgetsText(QString text,int index)6194 void CsoundQt::setWidgetsText(QString text, int index)
6195 {
6196 if (index == -1) {
6197 index = curPage;
6198 }
6199 if (index < documentTabs->count() && index >= 0) {
6200 documentPages[index]->setWidgetsText(text);
6201 }
6202 }
6203
setPresetsText(QString text,int index)6204 void CsoundQt::setPresetsText(QString text, int index)
6205 {
6206 if (index == -1) {
6207 index = curPage;
6208 }
6209 if (index < documentTabs->count() && index >= 0) {
6210 documentPages[index]->setPresetsText(text);
6211 }
6212 }
6213
setOptionsText(QString text,int index)6214 void CsoundQt::setOptionsText(QString text, int index)
6215 {
6216 if (index == -1) {
6217 index = curPage;
6218 }
6219 if (index < documentTabs->count() && index >= 0) {
6220 documentPages[index]->setOptionsText(text);
6221 }
6222 }
6223
getDocument(QString name)6224 int CsoundQt::getDocument(QString name)
6225 {
6226 int index = curPage;
6227 if (!name.isEmpty()) {
6228 index = -1;
6229 for (int i = 0; i < documentPages.size(); i++) {
6230 QString fileName = documentPages[i]->getFileName();
6231 QString relName = fileName.mid(fileName.lastIndexOf("/")+1);
6232 if (name == fileName || name == relName ) {
6233 index = i;
6234 break;
6235 }
6236 }
6237 }
6238 return index;
6239 }
6240
getSelectedText(int index,int section)6241 QString CsoundQt::getSelectedText(int index, int section)
6242 {
6243 QString text = QString();
6244 if (index == -1) {
6245 index = curPage;
6246 }
6247 if (index < documentTabs->count() && index >= 0) {
6248 text = documentPages[index]->getSelectedText(section);
6249 }
6250 return text;
6251 }
6252
getCsd(int index)6253 QString CsoundQt::getCsd(int index)
6254 {
6255 QString text = QString();
6256 if (index == -1) {
6257 index = curPage;
6258 }
6259 if (index < documentTabs->count() && index >= 0) {
6260 text = documentPages[index]->getBasicText();
6261 }
6262 return text;
6263 }
6264
getFullText(int index)6265 QString CsoundQt::getFullText(int index)
6266 {
6267 QString text = QString();
6268 if (index == -1) {
6269 index = curPage;
6270 }
6271 if (index < documentTabs->count() && index >= 0) {
6272 text = documentPages[index]->getFullText();
6273 }
6274 return text;
6275 }
6276
getOrc(int index)6277 QString CsoundQt::getOrc(int index)
6278 {
6279 QString text = QString();
6280 if (index == -1) {
6281 index = curPage;
6282 }
6283 if (index < documentTabs->count() && index >= 0) {
6284 text = documentPages[index]->getOrc();
6285 }
6286 return text;
6287 }
6288
getSco(int index)6289 QString CsoundQt::getSco(int index)
6290 {
6291 QString text = QString();
6292 if (index == -1) {
6293 index = curPage;
6294 }
6295 if (index < documentTabs->count() && index >= 0) {
6296 text = documentPages[index]->getSco();
6297 }
6298 return text;
6299 }
6300
getWidgetsText(int index)6301 QString CsoundQt::getWidgetsText(int index)
6302 {
6303 QString text = QString();
6304 if (index == -1) {
6305 index = curPage;
6306 }
6307 if (index < documentTabs->count() && index >= 0) {
6308 text = documentPages[index]->getWidgetsText();
6309 }
6310 return text;
6311 }
6312
getSelectedWidgetsText(int index)6313 QString CsoundQt::getSelectedWidgetsText(int index)
6314 {
6315 QString text = QString();
6316 if (index == -1) {
6317 index = curPage;
6318 }
6319 if (index < documentTabs->count() && index >= 0) {
6320 text = documentPages[index]->getSelectedWidgetsText();
6321 }
6322 return text;
6323 }
6324
getPresetsText(int index)6325 QString CsoundQt::getPresetsText(int index)
6326 {
6327 QString text = QString();
6328 if (index == -1) {
6329 index = curPage;
6330 }
6331 if (index < documentTabs->count() && index >= 0) {
6332 text = documentPages[index]->getPresetsText();
6333 }
6334 return text;
6335 }
6336
getOptionsText(int index)6337 QString CsoundQt::getOptionsText(int index)
6338 {
6339 QString text = QString();
6340 if (index == -1) {
6341 index = curPage;
6342 }
6343 if (index < documentTabs->count() && index >= 0) {
6344 text = documentPages[index]->getOptionsText();
6345 }
6346 return text;
6347 }
6348
getFileName(int index)6349 QString CsoundQt::getFileName(int index)
6350 {
6351 QString text = QString();
6352 if (index == -1) {
6353 index = curPage;
6354 }
6355 if (index < documentTabs->count() && index >= 0) {
6356 text = documentPages[index]->getFileName();
6357 }
6358 return text;
6359 }
6360
getFilePath(int index)6361 QString CsoundQt::getFilePath(int index)
6362 {
6363 QString text = QString();
6364 if (index == -1) {
6365 index = curPage;
6366 }
6367 if (index < documentTabs->count() && index >= 0) {
6368 text = documentPages[index]->getFilePath();
6369 }
6370 return text;
6371 }
6372
6373
6374
setChannelValue(QString channel,double value,int index)6375 void CsoundQt::setChannelValue(QString channel, double value, int index)
6376 {
6377
6378 if (index == -1) {
6379 index = curPage;
6380 }
6381 if (index < documentTabs->count() && index >= 0) {
6382 documentPages[index]->setChannelValue(channel, value);
6383 }
6384 }
6385
getChannelValue(QString channel,int index)6386 double CsoundQt::getChannelValue(QString channel, int index)
6387 {
6388 double value = 0.0;
6389 if (index == -1) {
6390 index = curPage;
6391 }
6392 if (index < documentTabs->count() && index >= 0) {
6393 value = documentPages[index]->getChannelValue(channel);
6394 }
6395 return value;
6396 }
6397
setChannelString(QString channel,QString value,int index)6398 void CsoundQt::setChannelString(QString channel, QString value, int index)
6399 {
6400 if (index == -1) {
6401 index = curPage;
6402 }
6403 if (index < documentTabs->count() && index >= 0) {
6404 documentPages[index]->setChannelString(channel, value);
6405 }
6406 }
6407
getChannelString(QString channel,int index)6408 QString CsoundQt::getChannelString(QString channel, int index)
6409 {
6410 QString value = "";
6411 if (index == -1) {
6412 index = curPage;
6413 }
6414 if (index < documentTabs->count() && index >= 0) {
6415 value = documentPages[index]->getChannelString(channel);
6416 }
6417 return value;
6418 }
6419
setWidgetProperty(QString widgetid,QString property,QVariant value,int index)6420 void CsoundQt::setWidgetProperty(QString widgetid, QString property, QVariant value, int index)
6421 {
6422 if (index == -1) {
6423 index = curPage;
6424 }
6425 if (index < documentTabs->count() && index >= 0) {
6426 documentPages[index]->setWidgetProperty(widgetid, property, value);
6427 }
6428 }
6429
getWidgetProperty(QString widgetid,QString property,int index)6430 QVariant CsoundQt::getWidgetProperty(QString widgetid, QString property, int index)
6431 {
6432 QVariant value;
6433 if (index == -1) {
6434 index = curPage;
6435 }
6436 if (index < documentTabs->count() && index >= 0) {
6437 value = documentPages[index]->getWidgetProperty(widgetid, property);
6438 }
6439 return value;
6440 }
6441
6442
createNewLabel(int x,int y,QString channel,int index)6443 QString CsoundQt::createNewLabel(int x , int y , QString channel, int index)
6444 {
6445 if (index == -1) {
6446 index = curPage;
6447 }
6448 if (index < documentTabs->count() && index >= 0) {
6449 return documentPages[index]->createNewLabel(x,y,channel);
6450 }
6451 return QString();
6452 }
6453
createNewDisplay(int x,int y,QString channel,int index)6454 QString CsoundQt::createNewDisplay(int x , int y , QString channel, int index)
6455 {
6456 if (index == -1) {
6457 index = curPage;
6458 }
6459 if (index < documentTabs->count() && index >= 0) {
6460 return documentPages[index]->createNewDisplay(x,y,channel);
6461 }
6462 return QString();
6463 }
6464
createNewScrollNumber(int x,int y,QString channel,int index)6465 QString CsoundQt::createNewScrollNumber(int x , int y , QString channel, int index)
6466 {
6467 if (index == -1) {
6468 index = curPage;
6469 }
6470 if (index < documentTabs->count() && index >= 0) {
6471 return documentPages[index]->createNewScrollNumber(x,y,channel);
6472 }
6473 return QString();
6474 }
6475
createNewLineEdit(int x,int y,QString channel,int index)6476 QString CsoundQt::createNewLineEdit(int x , int y , QString channel, int index)
6477 {
6478 if (index == -1) {
6479 index = curPage;
6480 }
6481 if (index < documentTabs->count() && index >= 0) {
6482 return documentPages[index]->createNewLineEdit(x,y,channel);
6483 }
6484 return QString();
6485 }
6486
createNewSpinBox(int x,int y,QString channel,int index)6487 QString CsoundQt::createNewSpinBox(int x , int y , QString channel, int index)
6488 {
6489 if (index == -1) {
6490 index = curPage;
6491 }
6492 if (index < documentTabs->count() && index >= 0) {
6493 return documentPages[index]->createNewSpinBox(x,y,channel);
6494 }
6495 return QString();
6496 }
6497
createNewSlider(int x,int y,QString channel,int index)6498 QString CsoundQt::createNewSlider(int x, int y, QString channel, int index)
6499 {
6500 if (index == -1) {
6501 index = curPage;
6502 }
6503 if (index < documentTabs->count() && index >= 0) {
6504 return documentPages[index]->createNewSlider(x,y, channel);
6505 }
6506 return QString();
6507 }
6508
createNewButton(int x,int y,QString channel,int index)6509 QString CsoundQt::createNewButton(int x , int y , QString channel, int index)
6510 {
6511 if (index == -1) {
6512 index = curPage;
6513 }
6514 if (index < documentTabs->count() && index >= 0) {
6515 return documentPages[index]->createNewButton(x,y,channel);
6516 }
6517 return QString();
6518 }
6519
createNewKnob(int x,int y,QString channel,int index)6520 QString CsoundQt::createNewKnob(int x , int y , QString channel, int index)
6521 {
6522 if (index == -1) {
6523 index = curPage;
6524 }
6525 if (index < documentTabs->count() && index >= 0) {
6526 return documentPages[index]->createNewKnob(x,y,channel);
6527 }
6528 return QString();
6529 }
6530
createNewCheckBox(int x,int y,QString channel,int index)6531 QString CsoundQt::createNewCheckBox(int x , int y , QString channel, int index)
6532 {
6533 if (index == -1) {
6534 index = curPage;
6535 }
6536 if (index < documentTabs->count() && index >= 0) {
6537 return documentPages[index]->createNewCheckBox(x,y,channel);
6538 }
6539 return QString();
6540 }
6541
createNewMenu(int x,int y,QString channel,int index)6542 QString CsoundQt::createNewMenu(int x , int y , QString channel, int index)
6543 {
6544 if (index == -1) {
6545 index = curPage;
6546 }
6547 if (index < documentTabs->count() && index >= 0) {
6548 return documentPages[index]->createNewMenu(x,y,channel);
6549 }
6550 return QString();
6551 }
6552
createNewMeter(int x,int y,QString channel,int index)6553 QString CsoundQt::createNewMeter(int x , int y , QString channel, int index)
6554 {
6555 if (index == -1) {
6556 index = curPage;
6557 }
6558 if (index < documentTabs->count() && index >= 0) {
6559 return documentPages[index]->createNewMeter(x,y,channel);
6560 }
6561 return QString();
6562 }
6563
createNewConsole(int x,int y,QString channel,int index)6564 QString CsoundQt::createNewConsole(int x , int y , QString channel, int index)
6565 {
6566 if (index == -1) {
6567 index = curPage;
6568 }
6569 if (index < documentTabs->count() && index >= 0) {
6570 return documentPages[index]->createNewConsole(x,y,channel);
6571 }
6572 return QString();
6573 }
6574
createNewGraph(int x,int y,QString channel,int index)6575 QString CsoundQt::createNewGraph(int x , int y , QString channel, int index)
6576 {
6577 if (index == -1) {
6578 index = curPage;
6579 }
6580 if (index < documentTabs->count() && index >= 0) {
6581 return documentPages[index]->createNewGraph(x,y,channel);
6582 }
6583 return QString();
6584 }
6585
createNewScope(int x,int y,QString channel,int index)6586 QString CsoundQt::createNewScope(int x , int y , QString channel, int index)
6587 {
6588 if (index == -1) {
6589 index = curPage;
6590 }
6591 if (index < documentTabs->count() && index >= 0) {
6592 return documentPages[index]->createNewScope(x,y,channel);
6593 }
6594 return QString();
6595 }
6596
getWidgetUuids(int index)6597 QStringList CsoundQt::getWidgetUuids(int index)
6598 {
6599 if (index == -1) {
6600 index = curPage;
6601 }
6602 if (index < documentTabs->count() && index >= 0) {
6603 return documentPages[index]->getWidgetUuids();
6604 }
6605 return QStringList();
6606 }
6607
listWidgetProperties(QString widgetid,int index)6608 QStringList CsoundQt::listWidgetProperties(QString widgetid, int index)
6609 {
6610 if (index == -1) {
6611 index = curPage;
6612 }
6613 if (index < documentTabs->count() && index >= 0) {
6614 return documentPages[index]->listWidgetProperties(widgetid);
6615 }
6616 return QStringList();
6617 }
6618
destroyWidget(QString widgetid,int index)6619 bool CsoundQt::destroyWidget(QString widgetid,int index)
6620 {
6621 if (index == -1) {
6622 index = curPage;
6623 }
6624 if (index < documentTabs->count() && index >= 0) {
6625 return documentPages[index]->destroyWidget(widgetid);
6626 }
6627 return false;
6628 }
6629
getSheet(int index,int sheetIndex)6630 EventSheet* CsoundQt::getSheet(int index, int sheetIndex)
6631 {
6632 if (index == -1) {
6633 index = curPage;
6634 }
6635 if (index < documentTabs->count() && index >= 0) {
6636 return documentPages[index]->getSheet(sheetIndex);
6637 }
6638 else {
6639 return NULL;
6640 }
6641 }
6642
getEngine(int index)6643 CsoundEngine *CsoundQt::getEngine(int index)
6644 {
6645 if (index == -1) {
6646 index = curPage;
6647 }
6648 if (index < documentTabs->count() && index >= 0) {
6649 return documentPages[index]->getEngine();
6650 }
6651 else {
6652 return NULL;
6653 }
6654 }
6655
startServer()6656 bool CsoundQt::startServer()
6657 {
6658 m_server->removeServer("csoundqt"); // for any case, if socket was not cleard due crash before
6659 return m_server->listen("csoundqt");
6660 }
6661
6662 #if defined(QCS_QTHTML)
updateHtmlView()6663 void CsoundQt::updateHtmlView()
6664 {
6665 QString htmlText = documentPages[curPage]->getHtmlText();
6666 if (!htmlText.isEmpty()) {
6667 ///csoundHtmlView->setCsoundEngine(getEngine(curPage));
6668 csoundHtmlView->load(documentPages[curPage]);
6669 } else {
6670 csoundHtmlView->clear();
6671 }
6672 }
6673 #endif
6674
getSheet(int index,QString sheetName)6675 EventSheet* CsoundQt::getSheet(int index, QString sheetName)
6676 {
6677 if (index == -1) {
6678 index = curPage;
6679 }
6680 if (index < documentTabs->count() && index >= 0) {
6681 return documentPages[index]->getSheet(sheetName);
6682 }
6683 else {
6684 return NULL;
6685 }
6686 }
6687
6688 //void CsoundQt::newCurve(Curve * curve)
6689 //{
6690 // newCurveBuffer.append(curve);
6691 //}
6692 //
6693
loadPreset(int preSetIndex,int index)6694 void CsoundQt::loadPreset(int preSetIndex, int index) {
6695 if (index == -1) {
6696 index = curPage;
6697 }
6698 if (index < documentTabs->count() && index >= 0) {
6699 return documentPages[index]->loadPreset(preSetIndex);
6700 }
6701 else {
6702 return;
6703 }
6704 }
6705
setParsedUDOs()6706 void CsoundQt::setParsedUDOs() {
6707 auto udos = m_inspector->getParsedUDOs();
6708 auto doc = documentPages[curPage];
6709 doc->setParsedUDOs(udos);
6710 }
6711
gotoLineDialog()6712 void CsoundQt::gotoLineDialog() {
6713 auto doc = this->getCurrentDocumentPage();
6714 doc->gotoLineDialog();
6715 }
6716