1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2010 Robert Bieber
12 * This program is free software; can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your optiyouon) any later version.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
22 #include "skindocument.h"
27 #include <QMessageBox>
28 #include <QFileDialog>
32 SkinDocument::SkinDocument(QLabel
* statusLabel
, ProjectModel
* project
,
33 DeviceState
* device
, QWidget
*parent
)
34 :TabContent(parent
), statusLabel(statusLabel
),
35 project(project
), device(device
)
39 titleText
= "Untitled";
42 parseStatus
= tr("Empty document");
46 SkinDocument::SkinDocument(QLabel
* statusLabel
, QString file
,
47 ProjectModel
* project
, DeviceState
* device
,
49 :TabContent(parent
), fileName(file
),
50 statusLabel(statusLabel
), project(project
),
56 /* Loading the file */
57 if(QFile::exists(fileName
))
60 fin
.open(QFile::ReadOnly
);
61 editor
->document()->setPlainText(QString(fin
.readAll()));
62 saved
= editor
->document()->toPlainText();
63 editor
->setTextCursor(QTextCursor(editor
->document()->begin()));
67 /* Setting the title */
68 QStringList decomposed
= fileName
.split('/');
69 titleText
= decomposed
.last();
72 SkinDocument::~SkinDocument()
74 highlighter
->deleteLater();
78 void SkinDocument::connectPrefs(PreferencesDialog
* prefs
)
80 QObject::connect(prefs
, SIGNAL(accepted()),
81 this, SLOT(settingsChanged()));
82 QObject::connect(prefs
, SIGNAL(accepted()),
83 highlighter
, SLOT(loadSettings()));
86 bool SkinDocument::requestClose()
88 /* Storing the response in blockUpdate will also block updates to the
89 status bar if the tab is being closed */
90 if(editor
->document()->toPlainText() != saved
)
92 /* Spawning the "Are you sure?" dialog */
93 QMessageBox
confirm(this);
94 confirm
.setWindowTitle(tr("Confirm Close"));
95 confirm
.setText(titleText
+ tr(" has been modified."));
96 confirm
.setInformativeText(tr("Do you want to save your changes?"));
97 confirm
.setStandardButtons(QMessageBox::Save
| QMessageBox::Discard
98 | QMessageBox::Cancel
);
99 confirm
.setDefaultButton(QMessageBox::Save
);
100 int confirmation
= confirm
.exec();
104 case QMessageBox::Save
:
106 /* After calling save, make sure the user actually went through */
107 if(editor
->document()->toPlainText() != saved
)
113 case QMessageBox::Discard
:
117 case QMessageBox::Cancel
:
128 void SkinDocument::setupUI()
130 /* Setting up the text edit */
131 layout
= new QHBoxLayout
;
132 editor
= new CodeEditor(this);
133 editor
->setLineWrapMode(QPlainTextEdit::NoWrap
);
134 layout
->addWidget(editor
);
138 /* Attaching the syntax highlighter */
139 highlighter
= new SkinHighlighter(editor
->document());
141 /* Setting up the model */
142 model
= new ParseTreeModel("");
144 /* Connecting the editor's signal */
145 QObject::connect(editor
, SIGNAL(textChanged()),
146 this, SLOT(codeChanged()));
147 QObject::connect(editor
, SIGNAL(cursorPositionChanged()),
148 this, SLOT(cursorChanged()));
150 /* Connecting to device setting changes */
151 QObject::connect(device
, SIGNAL(settingsChanged()),
152 this, SLOT(deviceChanged()));
157 void SkinDocument::settingsChanged()
159 /* Setting the editor colors */
161 settings
.beginGroup("SkinDocument");
163 QColor fg
= settings
.value("fgColor", Qt::black
).value
<QColor
>();
164 QColor bg
= settings
.value("bgColor", Qt::white
).value
<QColor
>();
166 palette
.setColor(QPalette::All
, QPalette::Base
, bg
);
167 palette
.setColor(QPalette::All
, QPalette::Text
, fg
);
168 editor
->setPalette(palette
);
170 QColor highlight
= settings
.value("errorColor", Qt::red
).value
<QColor
>();
171 editor
->setErrorColor(highlight
);
173 /* Setting the font */
174 QFont
def("Monospace");
175 def
.setStyleHint(QFont::TypeWriter
);
176 QFont family
= settings
.value("fontFamily", def
).value
<QFont
>();
177 family
.setPointSize(settings
.value("fontSize", 12).toInt());
178 editor
->setFont(family
);
186 void SkinDocument::cursorChanged()
188 if(editor
->isError(editor
->textCursor().blockNumber() + 1))
190 QTextCursor line
= editor
->textCursor();
191 line
.movePosition(QTextCursor::StartOfLine
);
192 line
.movePosition(QTextCursor::EndOfLine
, QTextCursor::KeepAnchor
);
193 skin_parse(line
.selectedText().toAscii());
194 if(skin_error_line() > 0)
195 parseStatus
= tr("Error on line ") +
196 QString::number(line
.blockNumber() + 1) + tr(": ") +
197 skin_error_message();
198 statusLabel
->setText(parseStatus
);
200 else if(editor
->hasErrors())
202 parseStatus
= tr("Errors in document");
203 statusLabel
->setText(parseStatus
);
207 emit
lineChanged(editor
->textCursor().blockNumber() + 1);
212 void SkinDocument::codeChanged()
217 if(editor
->document()->isEmpty())
219 parseStatus
= tr("Empty document");
220 statusLabel
->setText(parseStatus
);
224 editor
->clearErrors();
225 parseStatus
= model
->changeTree(editor
->document()->
226 toPlainText().toAscii());
227 if(skin_error_line() > 0)
228 parseStatus
= tr("Errors in document");
229 statusLabel
->setText(parseStatus
);
231 /* Highlighting if an error was found */
232 if(skin_error_line() > 0)
234 editor
->addError(skin_error_line());
236 /* Now we're going to attempt parsing again at each line, until we find
237 one that won't error out*/
238 QTextDocument
doc(editor
->document()->toPlainText());
240 while(skin_error_line() > 0 && !doc
.isEmpty())
242 QTextCursor
rest(&doc
);
244 for(int i
= 0; i
< skin_error_line(); i
++)
245 rest
.movePosition(QTextCursor::NextBlock
,
246 QTextCursor::KeepAnchor
);
247 if(skin_error_line() == doc
.blockCount())
248 rest
.movePosition(QTextCursor::End
, QTextCursor::KeepAnchor
);
250 rest
.removeSelectedText();
251 base
+= skin_error_line();
253 skin_parse(doc
.toPlainText().toAscii());
255 if(skin_error_line() > 0)
256 editor
->addError(base
+ skin_error_line());
261 if(editor
->document()->toPlainText() != saved
)
262 emit
titleChanged(titleText
+ QChar('*'));
264 emit
titleChanged(titleText
);
266 model
->render(project
, device
, &fileName
);
272 void SkinDocument::save()
274 QFile
fout(fileName
);
282 fout
.open(QFile::WriteOnly
);
283 fout
.write(editor
->document()->toPlainText().toAscii());
286 saved
= editor
->document()->toPlainText();
287 QStringList decompose
= fileName
.split('/');
288 titleText
= decompose
.last();
289 emit
titleChanged(titleText
);
293 void SkinDocument::saveAs()
295 /* Determining the directory to open */
296 QString directory
= fileName
;
299 settings
.beginGroup("SkinDocument");
301 directory
= settings
.value("defaultDirectory", "").toString();
303 fileName
= QFileDialog::getSaveFileName(this, tr("Save Document"),
304 directory
, fileFilter());
305 directory
= fileName
;
309 directory
.chop(fileName
.length() - fileName
.lastIndexOf('/') - 1);
310 settings
.setValue("defaultDirectory", directory
);
313 QFile
fout(fileName
);
314 fout
.open(QFile::WriteOnly
);
315 fout
.write(editor
->document()->toPlainText().toAscii());
318 saved
= editor
->document()->toPlainText();
319 QStringList decompose
= fileName
.split('/');
320 titleText
= decompose
[decompose
.count() - 1];
321 emit
titleChanged(titleText
);
325 QString
SkinDocument::findSetting(QString key
, QString fallback
)
330 return project
->getSetting(key
, fallback
);