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 #ifndef QUTECSOUND_H
24 #define QUTECSOUND_H
25 
26 #ifdef USE_QT5
27 #include <QtWidgets>
28 #ifdef USE_QT_GT_53
29 #include <QQuickWidget>
30 #include <QQuickItem>
31 #endif
32 #else
33 #include <QtGui>
34 #include <QDesktopServices>
35 #endif
36 #include <QLocalServer>
37 #include <QLocalSocket>
38 
39 #include "types.h"
40 #include "configlists.h"
41 
42 #ifdef MACOSX_PRE_SNOW
43 // Needed to be able to grab menus back from FLTK
44 #include <Carbon/Carbon.h>
45 #endif
46 
47 #define QCS_USE_NEW_ICON
48 
49 class QAction;
50 class QMenu;
51 class QTextEdit;
52 
53 class DockHelp;
54 class WidgetPanel;
55 class Inspector;
56 #ifdef QCS_PYTHONQT
57 class PythonConsole;
58 #endif
59 class DockConsole;
60 class DebugPanel;
61 class OpEntryParser;
62 class Options;
63 class ConfigLists;
64 class DocumentPage;
65 class UtilitiesDialog;
66 class Curve;
67 class GraphicWindow;
68 class KeyboardShortcuts;
69 class EventDispatcher;
70 class EventSheet;
71 class CsoundEngine;
72 class MidiHandler;
73 class MidiLearnDialog;
74 class WidgetLayout;
75 
76 #if defined(QCS_QTHTML)
77 class CsoundHtmlView;
78 #endif
79 
80 class CsoundQt:public QMainWindow
81 {
82 	Q_OBJECT
83 
84 	friend class WidgetPanel; //to pass ud
85 	friend class FileOpenEater; //to pass curPage
86 public:
87     CsoundQt(QStringList fileNames);
88 	~CsoundQt();
89 	static void utilitiesMessageCallback(CSOUND *csound,
90 										 int /*attr*/,
91 										 const char *fmt,
92 										 va_list args);
93 
94 	// Editor
95 	QString setDocument(int index); // Returns document name
96 	void insertText(QString text, int index = -1, int section = -1);
97 	void setCsd(QString text, int index = -1);
98 	void setFullText(QString text, int index = -1);
99 	void setOrc(QString text, int index = -1);
100 	void setSco(QString text, int index = -1);
101 	void setWidgetsText(QString text, int index = -1);
102 	void setPresetsText(QString text, int index = -1);
103 	void setOptionsText(QString text, int index = -1);
104 	int getDocument(QString name = ""); // Returns document index. -1 if not current open
105 	QString getSelectedText(int index = -1, int section = 0);
106 	QString getCsd(int index);
107 	QString getFullText(int index);
108 	QString getOrc(int index);
109 	QString getSco(int index);
110 	QString getWidgetsText(int index);
111 	QString getSelectedWidgetsText(int index);
112 	QString getPresetsText(int index);
113 	QString getOptionsText(int index);
114 	QString getFileName(int index);
115 	QString getFilePath(int index);
116 	// Widgets
117 	void setChannelValue(QString channel, double value, int index = -1);
118 	double getChannelValue(QString channel, int index = -1);
119 	void setChannelString(QString channel, QString value, int index = -1);
120 	QString getChannelString(QString channel, int index = -1);
121 	void setWidgetProperty(QString widgetid, QString property, QVariant value, int index= -1);
122 	QVariant getWidgetProperty(QString widgetid, QString property, int index= -1);
123 	QString createNewLabel(int x = -1, int y = -1, QString channel = QString(), int index = -1);
124 	QString createNewDisplay(int x = -1, int y = -1, QString channel = QString(), int index = -1);
125 	QString createNewScrollNumber(int x = -1, int y = -1, QString channel = QString(), int index = -1);
126 	QString createNewLineEdit(int x = -1, int y = -1, QString channel = QString(), int index = -1);
127 	QString createNewSpinBox(int x = -1, int y = -1, QString channel = QString(), int index = -1);
128 	QString createNewSlider(int x = -1, int y = -1, QString channel = QString(), int index = -1);
129 	QString createNewButton(int x = -1, int y = -1, QString channel = QString(), int index = -1);
130 	QString createNewKnob(int x = -1, int y = -1, QString channel = QString(), int index = -1);
131 	QString createNewCheckBox(int x = -1, int y = -1, QString channel = QString(), int index = -1);
132 	QString createNewMenu(int x = -1, int y = -1, QString channel = QString(), int index = -1);
133 	QString createNewMeter(int x = -1, int y = -1, QString channel = QString(), int index = -1);
134 	QString createNewConsole(int x = -1, int y = -1, QString channel = QString(), int index = -1);
135 	QString createNewGraph(int x = -1, int y = -1, QString channel = QString(), int index = -1);
136 	QString createNewScope(int x = -1, int y = -1, QString channel = QString(), int index = -1);
137 	//    int popKeyPressEvent(); // return ASCII code of key press event for Csound or -1 if no event
138 	//    int popKeyReleaseEvent(); // return ASCII code of key release event for Csound -1 if no
139 	QStringList getWidgetUuids(int index = -1);
140 	QStringList listWidgetProperties(QString widgetid, int index = -1); // widgetid can be eihter uuid (prefered) or channel
141 	bool destroyWidget(QString widgetid, int  index = -1);
142 	void loadPreset(int preSetIndex, int index);
143 	//Live Event Sheets
144 	EventSheet* getSheet(int index = -1, int sheetIndex = -1);
145 	EventSheet* getSheet(int index = -1, QString sheetName = QString());
146 	// Engine
147 	CsoundEngine *getEngine(int index = -1);
148 	OpEntryParser *m_opcodeTree;
149 	void stkCheck();
150 	// localServer
151 	bool startServer();
152 #if defined(QCS_QTHTML)
153 	void updateHtmlView();
154 #endif
155 public slots:
156 	int loadFile(QString fileName, bool runNow = false);
157 	int loadFileFromSystem(QString fileName); // checks for m_options->autoPlay, if the function is called from other class
158 	void newFile();
159 	bool closeTab(bool forceCloseApp = false, int index = -1);
160 	bool saveFile(const QString &fileName, bool saveWidgets = true);
161 	void play(bool realtime = true, int index = -1);
162 	void runInTerm(bool realtime = true);
163 	void pause(int index = -1);
164 	void stop(int index = -1);
165 	void stopAll();
166 	void stopAllOthers();
167 	void markStopped();
168 	void perfEnded();
169 	void render();
170 	void record(bool);
171 	void sendEvent(QString eventLine, double delay = 0);
172 	void sendEvent(int index, QString line, double delay = 0);
173 	void changePage(int index);
174 	void pageLeft();
175 	void pageRight();
176 	void setWidgetTooltipsVisible(bool visible);
177 	void closeExtraPanels(); // to close help and console panels when esc is pressed in the editor
178 
179 	//    void updateWidgets();
180 	void openExample();
181 	void openTemplate();
182 	void logMessage(QString msg);
183     void statusBarMessage(QString message);
184 	//    void registerLiveEvent(QWidget *e);
185 	void evaluateCsound(QString code = QString());
186 	void breakpointReached();
187     void setParsedUDOs();
188 
189 
190 protected:
191 	virtual void closeEvent(QCloseEvent *event);
192 	//    virtual void keyPressEvent(QKeyEvent *event);
193 private slots:
194 	void open();
195 	void reload();
196 	void openFromAction();
197 	void openFromAction(QString fileName);
198 	void runScriptFromAction();
199 	void runScript(QString fileName);
200 	void createCodeGraph();
201 	void closeGraph();
202 	bool save();
203 	bool saveAs();
204 	void createApp();
205 	bool saveNoWidgets();
206 	void info();
207 	// Edition
208 	void copy();
209 	void cut();
210 	void paste();
211 	void undo();
212 	void redo();
213 	void evaluateSection();
214 	void evaluate(QString code = QString());
215 	void evaluatePython(QString code = QString());
216 	void evaluateString(QString evalCode);
217 	void setScratchPadMode(bool csdMode);
218 	void setWidgetEditMode(bool);  // This is not necessary as the action is passed and connected in the widget layout
219 	void duplicate();
220 	void print();
221 	void findReplace();  // Direct to current Page
222 	void findString();  // Direct to current Page
223 	bool join(bool ask = true);
224 	void showUtilities(bool);
225 	void getToIn();
226 	void inToGet();
227 	void updateCsladspaText();
228 	void updateCabbageText();
229     void saveWidgetsToQml();
230 	void setCurrentAudioFile(const QString fileName);
231 	void openExternalEditor();
232 	void openExternalPlayer();
233 	void setEditorFocus();
234 	void setHelpEntry();
235     void setFullScreen(bool full);
236     void checkFullScreen();
237     void setEditorFullScreen(bool full);
238     void setHtmlFullScreen(bool full);
239     void setHelpFullScreen(bool full);
240     void setWidgetsFullScreen(bool full);
241     void showDebugger(bool show);
242 	void showVirtualKeyboard(bool show);
243 	void showTableEditor(bool show);
244 	void virtualKeyboardActOff(QObject *parent=0);
245 	void tableEditorActOff(QObject *parent=0);
246 	void showHtml5Gui(bool show);
247 	void splitView(bool split);
248 	void showMidiLearn();
249 	void virtualMidiIn(QVariant on, QVariant note, QVariant channel, QVariant velocity);
250 	void virtualCCIn(int channel, int cc, int value);
251 	void handleTableSyntax(QString syntax);
252 	void openManualExample(QString fileName);
253 	void openExternalBrowser(QUrl url = QUrl());
254 	void openPdfFile(QString name);
255 	void openFLOSSManual();
256 	void openQuickRef();
257 	void openOnlineDocumentation();
258 	void resetPreferences();
259 	void reportBug();
260 	void requestFeature();
261 	void chat();
262 	void openShortcutDialog();
263 	void downloadManual();
264 	void about();
265 	void donate();
266 	void documentWasModified();
267 	void configure();
268 	void applySettings();
269 	void setCurrentOptionsForPage(DocumentPage *p);
270 	void runUtility(QString flags);
271 	//     void widgetDockLocationChanged(Qt::DockWidgetArea area);
272 	void updateInspector();
273     void updateCurrentPageTask();
274     void markInspectorUpdate(); // Notification that inspector needs update
275 	void setDefaultKeyboardShortcuts();
276 	void showNoPythonQtWarning();
277 	void showOrc(bool);
278 	void showScore(bool);
279 	void showOptions(bool);
280 	void showFileB(bool);
281 	void showOther(bool);
282 	void showOtherCsd(bool);
283 	void showWidgetEdit(bool);
284 	void toggleLineArea();
285 	void toggleParameterMode();
286 //	void showParametersInEditor();
287 	void onNewConnection(); // when new client is connecting to localServer
288 	void onReadyRead(); // when message comes in
289 	void disableInternalRtMidi();
290     void focusToTab(int tab);
291     void ambiguosShortcut();
292     void testAudioSetup();
293     void checkSyntaxMenuAction();
294 
getCurrentDocumentPage()295     DocumentPage *getCurrentDocumentPage() {
296         if(curPage >= documentPages.size())
297             return nullptr;
298         return documentPages[curPage];
299     }
300     void gotoLineDialog();
301 
302 #ifdef QCS_DEBUGGER
303 	void runDebugger();
304 	void stopDebugger();
305 	void pauseDebugger();
306 	void continueDebugger();
307 	void addBreakpoint(int line, int instr, int skip);
308 	void addInstrumentBreakpoint(double instr, int skip);
309 	void removeBreakpoint(int line, int instr);
310 	void removeInstrumentBreakpoint(double instr);
311 #endif
312 private:
313 	void createActions();
314 	void setKeyboardShortcutsList();
315 	void connectActions();
316 	QString getExamplePath(QString dir);
317 	void createMenus();
318 	void fillFileMenu();
319 	void fillFavoriteMenu();
320 	void fillFavoriteSubMenu(QDir dir, QMenu *m, int depth);
321 	void fillScriptsMenu();
322 	void fillScriptsSubMenu(QDir dir, QMenu *m, int depth);
323 	void fillEditScriptsSubMenu(QDir dir, QMenu *m, int depth);
324 	void createToolBars();
325     void createStatusBar();
326 	void readSettings();
327 	void storeSettings();
328 	void writeSettings(QStringList openFiles=QStringList(), int lastIndex = 0);
329 	void clearSettings();
330     void setToolbarIconSize(int size);
331 	int execute(QString executable, QString options);
332 	//    bool saveCurrent();
333 	bool makeNewPage(QString fileName, QString text);
334 	bool loadCompanionFile(const QString &fileName);
335 	void setCurrentFile(const QString &fileName);
336 	QString strippedName(const QString &fullFileName);
337 	QString generateScript(bool realtime = true, QString tempFileName = "", QString executable = "");
338 	void getCompanionFileName();
339 	void setWidgetPanelGeometry();
340 	int isOpen(QString fileName);  // Returns index of document if open -1 if not open
341 	//    void markErrorLine();
342 	QString getSaveFileName();
343 	void createQuickRefPdf();
344 	void deleteTab(int index = -1);
345 	void openLogFile();
346 	void showNewFormatWarning();
347 	void setupEnvironment();
348 	ConfigLists m_configlists;
349 	QTabWidget *documentTabs;
350 	GraphicWindow *m_graphic;  // To display the code graph images
351 	QVector<DocumentPage *> documentPages;
352 	Options *m_options;
353 	DockConsole *m_console;
354 	DockHelp *helpPanel;
355 	WidgetPanel *widgetPanel;  // Dock widget, for containing the widget layout
356 	QDockWidget *m_scratchPad;
357 #ifdef USE_QT_GT_53
358 	QQuickWidget *m_virtualKeyboard, *m_tableEditor;
359 	QPointer <QQuickWidget> m_virtualKeyboardPointer, m_tableEditorPointer; // to control, if the object is deleted
360 #endif
361 #if defined(QCS_QTHTML)
362 public: CsoundHtmlView *csoundHtmlView;
363 #endif
364 private:
365 	//    QString m_widgetClipboard;
366 	Inspector *m_inspector;
367 #ifdef QCS_DEBUGGER
368 	DebugPanel *m_debugPanel;
369 	CsoundEngine *m_debugEngine;
370 #endif
371 #ifdef QCS_PYTHONQT
372 	PythonConsole *m_pythonConsole;
373 #endif
374 	MidiHandler *midiHandler;
375 	MidiLearnDialog *m_midiLearn;
376 	QFile logFile;
377 	QVector<QAction *> m_keyActions; //Actions which have keyboard shortcuts
378 	QMenu *fileMenu;
379 	QMenu *recentMenu;
380 	QMenu *templateMenu;
381 	QMenu *editMenu;
382 	QMenu *controlMenu;
383 	QMenu *viewMenu;
384 	QMenu *favoriteMenu;
385 	QMenu *scriptsMenu;
386 	QMenu *helpMenu;
387 //	QToolBar *fileToolBar;
388 //	QToolBar *editToolBar;
389 	QToolBar *controlToolBar;
390 	QToolBar *configureToolBar;
391 	QAction *newAct;
392 	QAction *openAct;
393 	QAction *reloadAct;
394 	QAction *saveAct;
395 	QAction *saveAsAct;
396 	QAction *createAppAct;
397 	QAction *saveNoWidgetsAct;
398 	QAction *closeTabAct;
399 	QAction *printAct;
400 	QAction *createCodeGraphAct;
401 	QAction *infoAct;
402 	QAction *exitAct;
403 	QList<QAction *> openRecentAct;
404 	QAction *undoAct;
405 	QAction *redoAct;
406 	QAction *cutAct;
407 	QAction *copyAct;
408 	QAction *pasteAct;
409 	QAction *duplicateAct;
410 	QAction *joinAct;
411 	QAction *evaluateAct;
412 	QAction *evaluateSectionAct;
413 	QAction *scratchPadCsdModeAct;
414 	QAction *getToInAct;
415 	QAction *inToGetAct;
416 	QAction *csladspaAct;
417 	QAction *cabbageAct;
418     QAction *qmlAct;
419     QAction *findAct;
420 	QAction *findAgainAct;
421 	QAction *configureAct;
422 	QAction *setShortcutsAct;
423 	QAction *editAct;
424 	QAction *runAct;
425     QAction *testAudioSetupAct;
426     QAction *checkSyntaxAct;
427 	QAction *runTermAct;
428 	QAction *pauseAct;
429 	QAction *stopAct;
430 	QAction *stopAllAct;
431 	QAction *recAct;
432 	QAction *renderAct;
433 	QAction *externalEditorAct;
434 	QAction *externalPlayerAct;
435 	QAction *focusEditorAct;
436 	QAction *showHelpAct;
437     QAction *raiseHelpAct;
438 	QAction *showManualAct;
439 	QAction *downloadManualAct;
440 	QAction *showGenAct;
441 	QAction *showOverviewAct;
442 	QAction *showOpcodeQuickRefAct;
443 	QAction *showConsoleAct;
444     QAction *raiseConsoleAct;
445     QAction *viewFullScreenAct;
446     QAction *viewEditorFullScreenAct;
447     QAction *viewHtmlFullScreenAct;
448     QAction *viewHelpFullScreenAct;
449     QAction *viewWidgetsFullScreenAct;
450 #ifdef QCS_DEBUGGER
451 	QAction *showDebugAct;
452 #endif
453 	QAction *showVirtualKeyboardAct;
454 	QAction *showTableEditorAct;
455 #if defined(QCS_QTHTML)
456 	QAction *showHtml5Act;
457     QAction *raiseHtml5Act;
458 #endif
459 	QAction *midiLearnAct;
460 	QAction *splitViewAct;
461 	QAction *showOrcAct;
462 	QAction *showScoreAct;
463 	QAction *showOptionsAct;
464 	QAction *showFileBAct;
465 	QAction *showOtherAct;
466 	QAction *showOtherCsdAct;
467 	QAction *showWidgetEditAct;
468 	QAction *setHelpEntryAct;
469 	QAction *browseBackAct;
470 	QAction *browseForwardAct;
471 	QAction *externalBrowserAct;
472 	QAction *openQuickRefAct;
473 	QAction *openDocumentationAct;
474 	QAction *showUtilitiesAct;
475 	QAction *showWidgetsAct;
476     QAction *raiseWidgetsAct;
477 
478 	QAction *showInspectorAct;
479     QAction *raiseInspectorAct;
480 	QAction *showLiveEventsAct;
481 	QAction *showPythonConsoleAct;
482     QAction *raisePythonConsoleAct;
483 	QAction *showScratchPadAct;
484     QAction *raiseScratchPadAct;
485 	QAction *commentAct;
486 	//    QAction *uncommentAct;
487 	QAction *indentAct;
488 	QAction *unindentAct;
489 	QAction *killLineAct;
490 	QAction *killToEndAct;
491     QAction *gotoLineAct;
492     QAction *goBackAct;
493 	QAction *aboutAct;
494 	QAction *donateAct;
495 	//    QAction *aboutQtAct;
496 	QAction *resetPreferencesAct;
497 	QAction *reportBugAct;
498 	QAction *requestFeatureAct;
499 	QAction *chatAct;
500 	QAction *lineNumbersAct;
501 	QAction *parameterModeAct;
502 //	QAction *showParametersAct;
503     QSignalMapper *focusMapper;
504 	int curPage;
505 	int curCsdPage;  // To recall last csd visited
506 	int configureTab; // Tab in last configure dialog accepted
507 	QString lastUsedDir;
508 	QString lastFileDir;
509 	QString quickRefFileName;
510 	QStringList recentFiles;
511 	QStringList lastFiles;
512 	QStringList tempScriptFiles; //Remember temp files to delete them later
513 	int lastTabIndex;
514 	bool m_resetPrefs; // Flag to reset preferences to default when closing
515 	bool m_inspectorNeedsUpdate;
516 	bool m_closing; // CsoundQt is closing (to inform timer threads)
517 	UtilitiesDialog *utilitiesDialog;
518 	QIcon modIcon;
519 	QString currentAudioFile;
520 	QString initialDir;
521 	QMutex closemutex;
522 	QLocalServer * m_server; // for receiving 'open file' messages from other instances
523 #ifdef MACOSX_PRE_SNOW
524 	MenuBarHandle menuBarHandle;
525 #endif
526     QByteArray m_preFullScreenState;
527     QString m_fullScreenComponent;
528 };
529 
530 class FileOpenEater : public QObject
531 {
532 	Q_OBJECT
533 public:
FileOpenEater()534 	FileOpenEater() {m_mw = 0;}
setMainWindow(CsoundQt * mainWindow)535 	void setMainWindow(CsoundQt *mainWindow) {
536 		m_mw = mainWindow;
537 		while (!fileEventQueue.isEmpty()) {
538 			QString fileName = fileEventQueue.takeFirst();
539 			qDebug() << "FileOpenEater::setMainWindow  opening file " << fileName << endl;
540 			m_mw->loadFileFromSystem(fileName);
541 		}
542 	}
543 	QStringList fileEventQueue;
544 protected:
eventFilter(QObject * obj,QEvent * event)545 	bool eventFilter(QObject *obj, QEvent *event)
546 	{
547 		if (event->type() == QEvent::FileOpen) {
548 			QFileOpenEvent *fileEvent = static_cast<QFileOpenEvent*>(event);
549 			if (m_mw == 0) {
550 				fileEventQueue << fileEvent->file();
551 			}
552 			else {
553 				m_mw->loadFileFromSystem(fileEvent->file());
554 			}
555 			qDebug() << "FileOpenEater::eventFilter " << fileEvent->file();
556 			return true;
557 		} else {
558 			// standard event processing
559 			return QObject::eventFilter(obj, event);
560 		}
561 	}
562 
563 	CsoundQt *m_mw;
564 };
565 
566 #endif
567