1 /***************************************************************************
2  *   Copyright (C) 2010 by Andres Cabrera                                  *
3  *   mantaraya36@gmail.com                                                 *
4  *                                                                         *
5  *   This program is free software; you can redistribute it and/or modify  *
6  *   it under the terms of the GNU General Public License as published by  *
7  *   the Free Software Foundation; either version 3 of the License, or     *
8  *   (at your option) any later version.                                   *
9  *                                                                         *
10  *   This program is distributed in the hope that it will be useful,       *
11  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
12  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
13  *   GNU General Public License for more details.                          *
14  *                                                                         *
15  *   You should have received a copy of the GNU General Public License     *
16  *   along with this program; if not, write to the                         *
17  *   Free Software Foundation, Inc.,                                       *
18  *   51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.              *
19  ***************************************************************************/
20 
21 #include "baseview.h"
22 #include "highlighter.h"
23 #include "texteditor.h"
24 #include "opentryparser.h"
25 
BaseView(QWidget * parent,OpEntryParser * opcodeTree)26 BaseView::BaseView(QWidget *parent, OpEntryParser *opcodeTree) :
27 	QScrollArea(parent), m_opcodeTree(opcodeTree)
28 {
29 	QPalette p = palette();
30 	m_mainEditor = new TextEditLineNumbers(this);
31     m_mainEditor->setProperty("name", "mainEditor");
32 	m_orcEditor = new TextEditor(this);
33     m_orcEditor->setProperty("name", "orcEditor");
34 	m_scoreEditor = new ScoreEditor(this);
35     m_scoreEditor->setProperty("name", "scoreEditor");
36 	m_optionsEditor = new TextEditor(this);
37     m_optionsEditor->setProperty("name", "optionsEditor");
38 	m_optionsEditor->setMaximumHeight(60);
39 	p.setColor(QPalette::WindowText, QColor("darkRed"));
40 	p.setColor(static_cast<QPalette::ColorRole>(9), QColor(200, 200, 200));
41 	m_optionsEditor->setPalette(p);
42 	m_optionsEditor->setTextColor(QColor("darkGreen"));
43 	m_filebEditor = new FileBEditor(this);
44 	m_otherEditor = new TextEditor(this);
45 	p.setColor(QPalette::WindowText, QColor("darkGreen"));
46 	p.setColor(static_cast<QPalette::ColorRole>(9), QColor(200, 200, 200));
47 	m_otherEditor->setPalette(p);
48 	m_otherEditor->setTextColor(QColor("darkGreen"));
49 	m_otherCsdEditor = new TextEditor(this);
50 	p.setColor(QPalette::WindowText, QColor("gray"));
51 	p.setColor(static_cast<QPalette::ColorRole>(9), QColor(200, 200, 200));
52 	m_otherCsdEditor->setPalette(p);
53 	m_otherCsdEditor->setTextColor(QColor("gray"));
54 	m_widgetEditor = new TextEditor(this);
55     m_appEditor = new TextEditor(this);
56     editors << m_mainEditor << m_orcEditor << m_scoreEditor << m_optionsEditor << m_filebEditor
57 			<< m_otherEditor << m_otherCsdEditor << m_widgetEditor << m_appEditor;
58 	splitter = new QSplitter(this); // Deleted with parent
59 	splitter->setOrientation(Qt::Vertical);
60 	splitter->setSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored);
61 	splitter->setContextMenuPolicy (Qt::NoContextMenu);
62 
63 	QStackedLayout *l = new QStackedLayout(this);  // Deleted with parent
64 	l->addWidget(splitter);
65 	setLayout(l);
66 	m_mode = EDIT_CSOUND_MODE;
67 	m_highlighter.setOpcodeNameList(opcodeTree->opcodeNameList());
68 	m_highlighter.setDocument(m_mainEditor->document());
69 	m_viewMode = 0;
70 	m_appProperties.used = false;
71 }
72 
~BaseView()73 BaseView::~BaseView()
74 {
75 }
76 
setFullText(QString text,bool goToTop)77 void BaseView::setFullText(QString text, bool goToTop)
78 {
79 	// Load Embedded Files ------------------------
80 	// Must be done initially to remove the files for both view modes
81 	clearFileBText();
82     while (text.contains("<CsFileB ") && text.contains("</CsFileB>")) {
83 		bool endsWithBreak = false;
84 		if (text.indexOf("</CsFileB>") < text.indexOf("<CsFileB ")) {
85 			qDebug()  << " File corrupt, not loading remaining CsFileB sections.";
86 			break;
87 		}
88 		if (text.indexOf("</CsFileB>") + 10 < text.size() && text[text.indexOf("</CsFileB>") + 10] == '\n' ) {
89 			endsWithBreak = true;
90 		}
91 		QString currentFileText = text.mid(text.indexOf("<CsFileB "),
92 										   text.indexOf("</CsFileB>") - text.indexOf("<CsFileB ") + 10
93 										   + (endsWithBreak ? 1:0));
94 		text.remove(text.indexOf("<CsFileB "), currentFileText.size());
95 		appendFileBText(currentFileText);
96 	}
97 	int startIndex,endIndex, offset, endoffset;
98 	QString tag, sectionText;
99 	// Get app info text. This text will never be visible in the full editor, so it is here
100 	sectionText = "";
101 	tag = "CsApp";
102 	startIndex = text.indexOf("<" + tag + ">");
103 	endIndex = text.indexOf("</" + tag + ">", startIndex) + tag.size() + 3;
104 	endoffset = text.size() > endIndex
105 			&& text[endIndex] == '\n' ? 1: 0;
106 	if (startIndex >= 0 && endIndex > startIndex) {
107 		sectionText = text.mid(startIndex, endIndex - startIndex + endoffset);
108 		text.remove(sectionText);
109 		QDomDocument d;
110 		if (!d.setContent(sectionText)) {
111 			qDebug()  << "Error parsing CsApp. Section will be discarded.";
112 		} else {
113 			QDomNodeList csapp = d.elementsByTagName("CsApp");
114 			QDomElement p = csapp.item(0).toElement();
115 			m_appProperties.appName = p.firstChildElement("appName").firstChild().nodeValue();
116 			m_appProperties.targetDir = p.firstChildElement("targetDir").firstChild().nodeValue();
117 			m_appProperties.author = p.firstChildElement("author").firstChild().nodeValue();
118 			m_appProperties.version = p.firstChildElement("version").firstChild().nodeValue();
119 			m_appProperties.date = p.firstChildElement("date").firstChild().nodeValue();
120 			m_appProperties.email = p.firstChildElement("email").firstChild().nodeValue();
121 			m_appProperties.website = p.firstChildElement("website").firstChild().nodeValue();
122 			m_appProperties.instructions = p.firstChildElement("instructions").firstChild().nodeValue();
123 			m_appProperties.autorun = p.firstChildElement("autorun").firstChild().nodeValue() == "true";
124 			m_appProperties.showRun = p.firstChildElement("showRun").firstChild().nodeValue() == "true";
125 			m_appProperties.saveState = p.firstChildElement("saveState").firstChild().nodeValue() == "true";
126 			m_appProperties.runMode = p.firstChildElement("runMode").firstChild().nodeValue().toInt();
127 			m_appProperties.newParser = p.firstChildElement("newParser").firstChild().nodeValue() == "true";
128 			m_appProperties.useSdk = p.firstChildElement("useSdk").firstChild().nodeValue() == "true";
129 			m_appProperties.useCustomPaths = p.firstChildElement("useCustomPaths").firstChild().nodeValue() == "true";
130 			m_appProperties.libDir = p.firstChildElement("libDir").firstChild().nodeValue();
131 			m_appProperties.opcodeDir = p.firstChildElement("opcodeDir").firstChild().nodeValue();
132 			m_appProperties.used = true;
133 		}
134 	}
135 	if (m_viewMode < 2) {  // Unified view
136 		m_mainEditor->setUndoRedoEnabled(false);
137 		QTextCursor cursor = m_mainEditor->textCursor();
138 		cursor.select(QTextCursor::Document);
139 		cursor.insertText(text);
140 		m_mainEditor->setTextCursor(cursor);  // TODO implement for multiple views
141 		if (goToTop) {
142 			m_mainEditor->moveCursor(QTextCursor::Start);
143 		}
144 		m_mainEditor->setUndoRedoEnabled(true);
145 	}
146 	else { // Split view
147 		// Find orchestra section
148 		sectionText = "";
149 		tag = "CsInstruments";
150 		startIndex = text.indexOf("<" + tag + ">");
151 		offset = text.size() > startIndex + tag.size() + 2
152 				&& text[startIndex +  tag.size() + 2] == '\n' ? 1: 0;
153 		endIndex = text.indexOf("</" + tag + ">") + tag.size() + 3;
154 		endoffset = text.size() > endIndex
155 				&& text[endIndex] == '\n' ? 1: 0;
156 		if (startIndex >= 0 && endIndex > startIndex) {
157 			sectionText = text.mid(startIndex, endIndex - startIndex + endoffset);
158 			text.remove(sectionText);
159 		}
160 		m_orcEditor->setUndoRedoEnabled(false);
161 		setOrc(sectionText.mid(tag.size() + 2 + offset, sectionText.size() - (tag.size()*2) - 5 - offset - endoffset));
162 		m_orcEditor->setUndoRedoEnabled(true);
163 		// Find score section
164 		sectionText = "";
165 		tag = "CsScore";
166 		startIndex = text.indexOf("<" + tag + ">");
167 		offset = text.size() > startIndex + tag.size() + 2
168 				&& text[startIndex +  tag.size() + 2] == '\n' ? 1: 0;
169 		endIndex = text.indexOf("</" + tag + ">") + tag.size() + 3;
170 		endoffset = text.size() > endIndex
171 				&& text[endIndex] == '\n' ? 1: 0;
172 		if (startIndex >= 0 && endIndex > startIndex) {
173 			sectionText = text.mid(startIndex, endIndex - startIndex + endoffset);
174 			text.remove(sectionText);
175 		}
176 		//	m_scoreEditor->setUndoRedoEnabled(false);
177 		setSco(sectionText.mid(tag.size() + 2 + offset, sectionText.size() - (tag.size()*2) - 5 - offset - endoffset));
178 		//	m_scoreEditor->setUndoRedoEnabled(true);
179 		// Set options text
180 		sectionText = "";
181 		tag = "CsOptions";
182 		startIndex = text.indexOf("<" + tag + ">");
183 		offset = text.size() > startIndex + tag.size() + 2
184 				&& text[startIndex +  tag.size() + 2] == '\n' ? 1: 0;
185 		endIndex = text.indexOf("</" + tag + ">") + tag.size() + 3;
186 		endoffset = text.size() > endIndex
187 				&& text[endIndex] == '\n' ? 1: 0;
188 		if (startIndex >= 0 && endIndex > startIndex) {
189 			sectionText = text.mid(startIndex, endIndex - startIndex + endoffset);
190 			text.remove(sectionText);
191 		}
192 		m_optionsEditor->setUndoRedoEnabled(false);
193 		setOptionsText(sectionText.mid(tag.size() + 2 + offset, sectionText.size() - (tag.size()*2) - 5 - offset - endoffset));
194 		m_optionsEditor->setUndoRedoEnabled(true);
195 
196 		// Remaining text inside CsSynthesizer tags
197 		sectionText = "";
198 		tag = "CsoundSynthesizer";
199 		startIndex = text.indexOf("<" + tag + ">");
200 		offset = text.size() > startIndex + tag.size() + 2
201 				&& text[startIndex +  tag.size() + 2] == '\n' ? 1: 0;
202 		endIndex = text.indexOf("</" + tag + ">") + tag.size() + 3;
203 		endoffset = text.size() > endIndex
204 				&& text[endIndex] == '\n' ? 1: 0;
205 		if (startIndex >= 0 && endIndex > startIndex) {
206 			sectionText = text.mid(startIndex, endIndex - startIndex + endoffset);
207 			text.remove(sectionText);
208 		}
209 		m_otherCsdEditor->setUndoRedoEnabled(false);
210 		setOtherCsdText(sectionText.mid(tag.size() + 2 + offset, sectionText.size() - (tag.size()*2) - 5 - offset - endoffset));
211 		m_otherCsdEditor->setUndoRedoEnabled(true);
212 		// Remaining text after all this
213 		m_otherEditor->setUndoRedoEnabled(false);
214 		setOtherText(text);
215 		m_otherEditor->setUndoRedoEnabled(true);
216 	}
217 }
218 
setBasicText(QString text)219 void BaseView::setBasicText(QString text)
220 {
221 	if (m_viewMode < 2) {  // Unified view
222 		QTextCursor cursor = m_mainEditor->textCursor();
223 		cursor.select(QTextCursor::Document);
224 		cursor.insertText(text);
225 		m_mainEditor->setTextCursor(cursor);  // TODO implement for multiple views
226 	}
227 	else {
228 		qDebug()  << "Not implemented for Split view.";
229 	}
230 }
231 
setFileType(editor_mode_t mode)232 void BaseView::setFileType(editor_mode_t mode)
233 {
234 	m_highlighter.setMode(mode);
235 	m_mode = mode;
236 }
237 
setFont(QFont font)238 void BaseView::setFont(QFont font)
239 {
240 	m_mainEditor->setFont(font);
241 	m_orcEditor->setFont(font);
242 	m_scoreEditor->setFont(font);
243 	m_optionsEditor->setFont(font);
244 	//  m_filebEditor->setFont(font);
245 	m_otherEditor->setFont(font);
246 	m_otherCsdEditor->setFont(font);
247 	m_widgetEditor->setFont(font);
248 	m_appEditor->setFont(font);
249 }
250 
setFontPointSize(float size)251 void BaseView::setFontPointSize(float size)
252 {
253 	m_mainEditor->setFontPointSize(size);
254 	m_orcEditor->setFontPointSize(size);
255 	m_scoreEditor->setFontPointSize(size);
256 	m_optionsEditor->setFontPointSize(size);
257 	//  m_filebEditor->setFontPointSize(size);
258 	m_otherEditor->setFontPointSize(size);
259 	m_otherCsdEditor->setFontPointSize(size);
260 	m_widgetEditor->setFontPointSize(size);
261 	m_appEditor->setFontPointSize(size);
262 }
263 
setTabStopWidth(int width)264 void BaseView::setTabStopWidth(int width)
265 {
266 	m_mainEditor->setTabStopWidth(width);
267 	m_orcEditor->setTabStopWidth(width);
268 	m_scoreEditor->setTabStopWidth(width);
269 	m_optionsEditor->setTabStopWidth(width);
270 	//  m_filebEditor->setTabStopWidth(width);
271 	m_otherEditor->setTabStopWidth(width);
272 	m_otherCsdEditor->setTabStopWidth(width);
273 	m_widgetEditor->setTabStopWidth(width);
274 	m_appEditor->setTabStopWidth(width);
275 }
276 
setTabIndents(bool indents)277 void BaseView::setTabIndents(bool indents)
278 {
279 	m_mainEditor->setTabIndents(indents);
280 }
281 
setLineWrapMode(QTextEdit::LineWrapMode mode)282 void BaseView::setLineWrapMode(QTextEdit::LineWrapMode mode)
283 {
284 	m_mainEditor->setLineWrapMode(mode);
285 	m_orcEditor->setLineWrapMode(mode);
286 	m_scoreEditor->setLineWrapMode(mode);
287 	m_optionsEditor->setLineWrapMode(mode);
288 	//  m_filebEditor->setLineWrapMode(mode);
289 	m_otherEditor->setLineWrapMode(mode);
290 	m_otherCsdEditor->setLineWrapMode(mode);
291 	m_widgetEditor->setLineWrapMode(mode);
292 	m_appEditor->setLineWrapMode(mode);
293 }
294 
setColorVariables(bool color)295 void BaseView::setColorVariables(bool color)
296 {
297 	m_highlighter.setColorVariables(color);
298 }
299 
setBackgroundColor(QColor color)300 void BaseView::setBackgroundColor(QColor color)
301 {
302     // before it was setPalette, but that does not work runtime.
303     m_mainEditor->setStyleSheet("QTextEdit { background-color: "+color.name() + "}");
304 }
305 
setTextColor(QColor color)306 void BaseView::setTextColor(QColor color)
307 {
308     // before it was setPalette, but that does not work runtime.
309     m_mainEditor->setStyleSheet("QTextEdit { color: " + color.name() + "}");
310 }
311 
setColors(QColor text,QColor background)312 void BaseView::setColors(QColor text, QColor background) {
313     auto sheet = QString("QTextEdit { color: %1; background-color: %2; }")
314             .arg(text.name())
315             .arg(background.name());
316     m_mainEditor->setStyleSheet(sheet);
317 }
318 
319 
setOrc(QString text)320 void BaseView::setOrc(QString text)
321 {
322 	if (m_viewMode < 2) { // View is not split
323 		if (m_mode != 0) {
324 			qDebug()  << "Current file is not a csd file. Text not inserted!";
325 			return;
326 		}
327 		QString csdText = getBasicText();
328         if (csdText.contains("<CsInstruments>") && csdText.contains("</CsInstruments>")) {
329 			QString preText = csdText.mid(0, csdText.indexOf("<CsInstruments>") + 15);
330 			QString postText = csdText.mid(csdText.lastIndexOf("</CsInstruments>"));
331 			if (!text.startsWith("\n")) {
332 				text.prepend("\n");
333 			}
334 			if (!text.endsWith("\n")) {
335 				text.append("\n");
336 			}
337 			csdText = preText + text + postText;
338 			setBasicText(csdText);
339 		}
340 		else {
341 			qDebug()  << "Orchestra section not found in csd. Text not inserted!";
342 		}
343 	}
344 	else { // Split view
345 		m_orcEditor->setPlainText(text);
346 	}
347 }
348 
setSco(QString text)349 void BaseView::setSco(QString text)
350 {
351 	if (m_viewMode < 2) { // View is not split
352 		if (m_mode != 0) {
353 			qDebug()  << "Current file is not a csd file. Text not inserted!";
354 			return;
355 		}
356 		QString csdText = getBasicText();
357         if (csdText.contains("<CsScore") && csdText.contains("</CsScore>")) {
358 			int scoreTag = csdText.indexOf("<CsScore");
359 			QString preText = csdText.mid(0, csdText.indexOf(">",scoreTag) + 1);
360 			QString postText = csdText.mid(csdText.lastIndexOf("</CsScore>"));
361 			if (!text.startsWith("\n")) {
362 				text.prepend("\n");
363 			}
364 			if (!text.endsWith("\n")) {
365 				text.append("\n");
366 			}
367 			csdText = preText + text + postText;
368 			setBasicText(csdText);
369 		}
370 		else {
371 			qDebug()  << "Orchestra section not found in csd. Text not inserted!";
372 		}
373 	}
374 	else {
375 		m_scoreEditor->setPlainText(text);
376 	}
377 }
378 
clearFileBText()379 void BaseView::clearFileBText()
380 {
381 	m_filebEditor->clear();
382 }
383 
appendFileBText(QString text)384 void BaseView::appendFileBText(QString text)
385 {
386 	m_filebEditor->appendText(text);
387 }
388 
setOptionsText(QString text)389 void BaseView::setOptionsText(QString text)
390 {
391 	if (m_viewMode < 2) { // View is not split
392 		if (m_mode != 0) {
393 			qDebug()  << "Current file is not a csd file. Text not inserted!";
394 			return;
395 		}
396 		// It would be better just to select the CsOptions portion and change that but this should do the trick too.
397 		QString csdText = getBasicText();
398         if (csdText.contains("<CsOptions>") && csdText.contains("</CsOptions>")) {
399 			QString preText = csdText.mid(0, csdText.indexOf("<CsOptions>") + 11);
400 			QString postText = csdText.mid(csdText.lastIndexOf("</CsOptions>"));
401 			if (!text.startsWith("\n")) {
402 				text.prepend("\n");
403 			}
404 			if (!text.endsWith("\n")) {
405 				text.append("\n");
406 			}
407 			csdText = preText + text + postText;
408 			setBasicText(csdText);
409 		}
410 		else {
411 			qDebug()  << "Orchestra section not found in csd. Text not inserted!";
412 		}
413 	}
414 	else {
415 		m_optionsEditor->setText(text);
416 		m_optionsEditor->moveCursor(QTextCursor::Start);
417 	}
418 
419 }
420 
setLadspaText(QString text)421 void BaseView::setLadspaText(QString text)
422 {
423 	if (m_viewMode < 2) { // View is not split
424 		if (m_mode != 0) {
425 			qDebug()  << "Current file is not a csd file. Text not inserted!";
426 			return;
427 		}
428 		QTextCursor cursor;
429 		cursor = m_mainEditor->textCursor();
430 		m_mainEditor->moveCursor(QTextCursor::Start);
431 		if (m_mainEditor->find("<csLADSPA>") && m_mainEditor->find("</csLADSPA>")) {
432 			QString curText = getBasicText();
433 			int index = curText.indexOf("<csLADSPA>");
434 			int endIndex = curText.indexOf("</csLADSPA>") + 11;
435 			if (curText.size() > endIndex + 1 && curText[endIndex + 1] == '\n') {
436 				endIndex++; // Include last line break
437 			}
438 			curText.remove(index, endIndex - index);
439 			curText.insert(index, text);
440 			setBasicText(curText);
441 			m_mainEditor->moveCursor(QTextCursor::Start);
442 		}
443 		else { //csLADSPA section not present, or incomplete
444 			m_mainEditor->find("<CsoundSynthesizer>"); //cursor moves there
445 			m_mainEditor->moveCursor(QTextCursor::EndOfLine);
446 			m_mainEditor->insertPlainText(QString("\n") + text + QString("\n"));
447 		}
448 	}
449 	else {
450 		qDebug()  << "Not implemented for split view";
451 	}
452 }
453 
setCabbageText(QString text)454 void BaseView::setCabbageText(QString text)
455 {
456 	if (m_viewMode < 2) { // View is not split
457 		if (m_mode != 0) {
458 			qDebug()  << "Current file is not a csd file. Text not inserted!";
459 			return;
460 		}
461 		QTextCursor cursor;
462 		cursor = m_mainEditor->textCursor();
463 		m_mainEditor->moveCursor(QTextCursor::Start);
464 		if (m_mainEditor->find("<Cabbage>") && m_mainEditor->find("</Cabbage>")) {
465 			QString curText = getBasicText();
466 			int index = curText.indexOf("<Cabbage>");
467 			int endIndex = curText.indexOf("</Cabbage>") + 10;
468 			if (curText.size() > endIndex + 1 && curText[endIndex + 1] == '\n') {
469 				endIndex++; // Include last line break
470 			}
471 			curText.remove(index, endIndex - index);
472 			curText.insert(index, text);
473 			setBasicText(curText);
474 			m_mainEditor->moveCursor(QTextCursor::Start);
475 		}
476 		else { //Cabbage section not present, or incomplete
477 			m_mainEditor->find("<CsoundSynthesizer>"); //cursor moves there
478 			m_mainEditor->moveCursor(QTextCursor::EndOfLine);
479 			m_mainEditor->insertPlainText(QString("\n") + text + QString("\n"));
480 		}
481 	}
482 	else {
483 		qDebug()  << "Not implemented for split view";
484 	}
485 }
486 
487 
488 
getCabbageText()489 QString BaseView::getCabbageText()
490 {
491 	QString cabbageText = QString();
492 	if (m_viewMode < 2) { // View is not split
493 		if (m_mode != 0) {
494 			qDebug()  << "Current file is not a csd file.";
495 			return cabbageText;
496 		}
497 		QTextCursor cursor;
498 		//cursor = m_mainEditor->textCursor();
499 		//m_mainEditor->moveCursor(QTextCursor::Start); // is it necessary?
500 		if (m_mainEditor->find("<Cabbage>") && m_mainEditor->find("</Cabbage>")) {
501 			QString curText = getBasicText();
502 
503 			int startIndex = curText.indexOf("<Cabbage>");
504 			int endIndex = curText.indexOf("</Cabbage>") + 10;
505 			cabbageText = curText.mid(startIndex, endIndex-startIndex);
506 			m_mainEditor->moveCursor(QTextCursor::Start);
507 		}
508 		else { //Cabbage section not present, or incomplete
509 			qDebug() << "No <Cabbage> section found.";
510 		}
511 
512 	}
513 	else {
514 		qDebug()  << "Not implemented for split view";
515 	}
516 	return cabbageText;
517 }
518 
519 
520 
setOtherCsdText(QString text)521 void BaseView::setOtherCsdText(QString text)
522 {
523 	if (m_viewMode < 2) { // View is not split
524 		if (m_mode != 0) {
525 			qDebug()  << "Current file is not a csd file. Text not inserted!";
526 			return;
527 		}
528 		QTextCursor cursor;
529 		cursor = m_mainEditor->textCursor();
530 		m_mainEditor->moveCursor(QTextCursor::Start);
531 		m_mainEditor->find("</CsoundSynthesizer>");
532 		m_mainEditor->insertPlainText(text); // TODO this is a bit flakey. What happens if there is already text there?
533 	}
534 	else {
535 		m_otherCsdEditor->setText(text);
536 		m_otherCsdEditor->moveCursor(QTextCursor::Start);
537 	}
538 }
539 
setOtherText(QString text)540 void BaseView::setOtherText(QString text)
541 {
542 	if (m_viewMode < 2) { // View is not split
543 		if (m_mode != 0) {
544 			qDebug()  << "Current file is not a csd file. Text not inserted!";
545 			return;
546 		}
547 		QTextCursor cursor;
548 		cursor = m_mainEditor->textCursor();
549 		m_mainEditor->moveCursor(QTextCursor::Start);
550 		m_mainEditor->insertPlainText(text); // TODO this is a bit flakey. What happens if there is already text there?
551 	}
552 	else {
553 		m_otherEditor->setText(text);
554 		m_otherEditor->moveCursor(QTextCursor::Start);
555 	}
556 }
557 
setAppText(QString text)558 void BaseView::setAppText(QString text)
559 {
560 	m_appEditor->setPlainText(text);
561 }
562 
setAppProperties(AppProperties properties)563 void BaseView::setAppProperties(AppProperties properties)
564 {
565 	m_appProperties = properties;
566 }
567 
toggleLineArea()568 void BaseView::toggleLineArea()
569 {
570 	showLineArea(!m_mainEditor->lineAreaVisble());
571 }
572 
toggleParameterMode()573 void BaseView::toggleParameterMode()
574 {
575 	m_mainEditor->setParameterMode(!m_mainEditor->getParameterMode());
576 }
577 
showLineArea(bool visible)578 void BaseView::showLineArea(bool visible)
579 {
580     m_mainEditor->setLineAreaVisible(visible);
581 }
582 
getBasicText()583 QString BaseView::getBasicText()
584 {
585 	//   What Csound needs (no widgets, misc text, etc.)
586 	// TODO implement modes
587 	QString text;
588 	if (m_viewMode < 2) {
589 		text = m_mainEditor->toPlainText(); // csd without extra sections
590 		if (m_viewMode & 16) {
591 			text += m_filebEditor->toPlainText();
592 		}
593 	}
594 	else {
595 		text = m_orcEditor->toPlainText();
596 	}
597 	return text;
598 }
599 
getFullText()600 QString BaseView::getFullText()
601 {
602 	QString text;
603 	if (m_viewMode < 2) { // View is not split
604 		text = m_mainEditor->toPlainText();
605 		int closeIndex = text.lastIndexOf("</CsoundSynthesizer>");
606 		QString fileBText = getFileB();
607 		if (!fileBText.isEmpty()) {
608 			if (closeIndex > 0) { // Embedded files must be within synthesizer
609 				text.insert(closeIndex,fileBText);
610 			}
611 			else {
612 				text += getFileB();
613 			}
614 		}
615 	}
616 	else { // Split view
617 		QString sectionText;
618 		sectionText = m_otherEditor->toPlainText();
619 		if (!sectionText.isEmpty()) {
620 			text += sectionText;
621 		}
622 		text += "<CsoundSynthesizer>\n";
623 		sectionText = m_optionsEditor->toPlainText();
624 		if (!sectionText.isEmpty()) {
625 			text += "<CsOptions>\n" + sectionText + "</CsOptions>\n";
626 		}
627 		text += "<CsInstruments>\n" + m_orcEditor->toPlainText() + "</CsInstruments>\n";
628 		text += "<CsScore>\n" + m_scoreEditor->getPlainText() + "</CsScore>\n";
629 		sectionText = getFileB();
630 		if (!sectionText.isEmpty()) {
631 			text += sectionText;
632 		}
633 		sectionText = m_otherCsdEditor->toPlainText();
634 		if (!sectionText.isEmpty()) {
635 			text += sectionText;
636 		}
637 		text += "</CsoundSynthesizer>";
638 	}
639 	if (!text.endsWith("\n")) {
640 		text += "\n";
641 	}
642 	text += getAppText();
643 	return text;
644 }
645 
getOrc()646 QString BaseView::getOrc()
647 {
648 	QString text = "";
649 	if (m_viewMode < 2) { // A single editor (orc and sco are not split)
650 		text = m_mainEditor->toPlainText();
651 		text = text.mid(text.lastIndexOf("<CsInstruments>" )+ 15);
652 		text.remove(text.lastIndexOf("</CsInstruments>"), text.size());
653 	}
654 	else {
655 		text = m_orcEditor->toPlainText();
656 	}
657 	return text;
658 }
659 
getSco()660 QString BaseView::getSco()
661 {
662 	QString text = "";
663 	if (m_viewMode < 2) {
664 		text = m_mainEditor->toPlainText();
665 		int scoreTag = text.lastIndexOf("<CsScore");
666 		text = text.mid(text.indexOf(">",scoreTag) + 1);
667 		text.remove(text.lastIndexOf("</CsScore>"), text.size());
668 	}
669 	else { // Split view
670 		text = m_scoreEditor->getPlainText();
671 	}
672 	return text;
673 }
674 
getOptionsText()675 QString BaseView::getOptionsText()
676 {
677 	// Returns text without tags
678 	QString text = "";
679 	if (m_viewMode < 2) {// A single editor (orc and sco are not split)
680 		QString edText = m_mainEditor->toPlainText();
681 		int index = edText.indexOf("<CsOptions>");
682 		if (index >= 0 && edText.contains("</CsOptions>")) {
683 			text = edText.mid(index + 11, edText.indexOf("</CsOptions>") - index - 11);
684 		}
685 	}
686 	else { //  Split view
687 		text = m_optionsEditor->toPlainText();
688 	}
689 	return text;
690 }
691 
getFileB()692 QString BaseView::getFileB()
693 {
694 	return m_filebEditor->toPlainText();
695 }
696 
getExtraCsdText()697 QString BaseView::getExtraCsdText()
698 {
699 	// All other tags like version and licence with tags. For text that is being edited in the text editor
700 	return m_otherCsdEditor->toPlainText();
701 }
702 
getExtraText()703 QString BaseView::getExtraText()
704 {
705 	// Text outside any known tags. For text that is being edited in the text editor
706 	return m_otherEditor->toPlainText();
707 }
708 
getAppText()709 QString BaseView::getAppText()
710 {
711 	if (!m_appProperties.used) {
712 		return QString();
713 	}
714 	QString appText;
715 	QXmlStreamWriter s(&appText);
716 	s.setAutoFormatting(true);
717 	s.writeStartElement("CsApp");
718 	//  s.writeAttribute("type", getWidgetType());
719 
720 	s.writeTextElement("appName", m_appProperties.appName);
721 	s.writeTextElement("targetDir", m_appProperties.targetDir);
722 	s.writeTextElement("author", m_appProperties.author);
723 	s.writeTextElement("version", m_appProperties.version);
724 	s.writeTextElement("date", m_appProperties.date);
725 	s.writeTextElement("email", m_appProperties.email);
726 	s.writeTextElement("website", m_appProperties.website);
727 	s.writeTextElement("instructions", m_appProperties.instructions);
728 
729 	s.writeTextElement("autorun", m_appProperties.autorun ? "true" : "false");
730 	s.writeTextElement("showRun", m_appProperties.showRun ? "true" : "false");
731 	s.writeTextElement("saveState", m_appProperties.saveState ? "true" : "false");
732 	s.writeTextElement("runMode", QString::number((int)m_appProperties.runMode));
733 	s.writeTextElement("newParser", m_appProperties.newParser ? "true" : "false");
734 
735 	s.writeTextElement("useSdk", m_appProperties.useSdk ? "true" : "false");
736 
737 	s.writeTextElement("useCustomPaths", m_appProperties.useCustomPaths ? "true" : "false");
738 	s.writeTextElement("libDir", m_appProperties.libDir);
739 	s.writeTextElement("opcodeDir", m_appProperties.opcodeDir);
740 
741 	s.writeEndElement();
742 
743 	appText += "\n";
744 	return appText;
745 }
746 
getAppProperties()747 AppProperties BaseView::getAppProperties()
748 {
749 	return m_appProperties;
750 }
751 
752 
753 //void BaseView::setOpcodeNameList(QStringList list)
754 //{
755 //  m_highlighter.setOpcodeNameList(list);
756 //}
757 
758 //void BaseView::setOpcodeTree(OpEntryParser *opcodeTree)
759 //{
760 //  m_opcodeTree = opcodeTree;
761 //}
762 
hideAllEditors()763 void BaseView::hideAllEditors()
764 {
765 	m_mainEditor->hide();
766 	m_orcEditor->hide();
767 	m_scoreEditor->hide();
768 	m_optionsEditor->hide();
769 	m_filebEditor->hide();
770 	m_otherEditor->hide();
771 	m_otherCsdEditor->hide();
772 	m_widgetEditor->hide();
773 	m_appEditor->hide();
774 	for (int i = 0; i < 9; i++) {
775 		QSplitterHandle *h = splitter->handle(i);
776 		if (h) {
777 			h->hide();
778 		}
779 	}
780 }
781 
clearUndoRedoStack()782 void BaseView::clearUndoRedoStack()
783 {
784 	if (m_viewMode < 2) {
785 		m_mainEditor->document()->setModified(false);
786 		//		m_mainEditor->document()->clearUndoRedoStacks();
787 	} else {
788 		m_orcEditor->document()->setModified(false);
789 		m_scoreEditor->clearUndoRedoStacks();
790 		m_optionsEditor->document()->setModified(false);
791 		m_filebEditor->clearUndoRedoStacks();
792 		m_otherEditor->document()->setModified(false);
793 		m_otherCsdEditor->document()->setModified(false);
794 		m_widgetEditor->document()->setModified(false);
795 		m_appEditor->document()->setModified(false);
796 		//		m_orcEditor->document()->clearUndoRedoStacks();
797 		//		m_scoreEditor->clearUndoRedoStacks();
798 		//		m_optionsEditor->document()->clearUndoRedoStacks();
799 		//		m_filebEditor->clearUndoRedoStacks();
800 		//		m_otherEditor->document()->clearUndoRedoStacks();
801 		//		m_otherCsdEditor->document()->clearUndoRedoStacks();
802 		//		m_widgetEditor->document()->clearUndoRedoStacks();
803 	}
804 }
805