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&ccedil;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&auml;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