1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2010 Robert Bieber
12 * This program is free software; you 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 option) 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
, QWidget
*parent
) :
33 QWidget(parent
), statusLabel(statusLabel
)
40 parseStatus
= tr("Empty document");
44 SkinDocument::SkinDocument(QLabel
* statusLabel
, QString file
, QWidget
*parent
):
45 QWidget(parent
), fileName(file
), statusLabel(statusLabel
)
50 /* Loading the file */
51 if(QFile::exists(fileName
))
54 fin
.open(QFile::ReadOnly
);
55 editor
->document()->setPlainText(QString(fin
.readAll()));
56 saved
= editor
->document()->toPlainText();
57 editor
->setTextCursor(QTextCursor(editor
->document()->begin()));
61 /* Setting the title */
62 QStringList decomposed
= fileName
.split('/');
63 title
= decomposed
.last();
66 SkinDocument::~SkinDocument()
72 void SkinDocument::connectPrefs(PreferencesDialog
* prefs
)
74 QObject::connect(prefs
, SIGNAL(accepted()),
75 this, SLOT(settingsChanged()));
76 QObject::connect(prefs
, SIGNAL(accepted()),
77 highlighter
, SLOT(loadSettings()));
80 bool SkinDocument::requestClose()
82 /* Storing the response in blockUpdate will also block updates to the
83 status bar if the tab is being closed */
84 if(editor
->document()->toPlainText() != saved
)
86 /* Spawning the "Are you sure?" dialog */
87 QMessageBox
confirm(this);
88 confirm
.setWindowTitle(tr("Confirm Close"));
89 confirm
.setText(title
+ tr(" has been modified."));
90 confirm
.setInformativeText(tr("Do you want to save your changes?"));
91 confirm
.setStandardButtons(QMessageBox::Save
| QMessageBox::Discard
92 | QMessageBox::Cancel
);
93 confirm
.setDefaultButton(QMessageBox::Save
);
94 int confirmation
= confirm
.exec();
98 case QMessageBox::Save
:
100 /* After calling save, make sure the user actually went through */
101 if(editor
->document()->toPlainText() != saved
)
107 case QMessageBox::Discard
:
111 case QMessageBox::Cancel
:
122 void SkinDocument::setupUI()
124 /* Setting up the text edit */
125 layout
= new QHBoxLayout
;
126 editor
= new CodeEditor(this);
127 editor
->setLineWrapMode(QPlainTextEdit::NoWrap
);
128 layout
->addWidget(editor
);
132 /* Attaching the syntax highlighter */
133 highlighter
= new SkinHighlighter(editor
->document());
135 /* Setting up the model */
136 model
= new ParseTreeModel("");
138 /* Connecting the editor's signal */
139 QObject::connect(editor
, SIGNAL(textChanged()),
140 this, SLOT(codeChanged()));
141 QObject::connect(editor
, SIGNAL(cursorPositionChanged()),
142 this, SLOT(cursorChanged()));
147 void SkinDocument::settingsChanged()
149 /* Setting the editor colors */
151 settings
.beginGroup("SkinDocument");
153 QColor fg
= settings
.value("fgColor", Qt::black
).value
<QColor
>();
154 QColor bg
= settings
.value("bgColor", Qt::white
).value
<QColor
>();
156 palette
.setColor(QPalette::All
, QPalette::Base
, bg
);
157 palette
.setColor(QPalette::All
, QPalette::Text
, fg
);
158 editor
->setPalette(palette
);
160 QColor highlight
= settings
.value("errorColor", Qt::red
).value
<QColor
>();
161 editor
->setErrorColor(highlight
);
163 /* Setting the font */
164 QFont
def("Monospace");
165 def
.setStyleHint(QFont::TypeWriter
);
166 QFont family
= settings
.value("fontFamily", def
).value
<QFont
>();
167 family
.setPointSize(settings
.value("fontSize", 12).toInt());
168 editor
->setFont(family
);
176 void SkinDocument::cursorChanged()
178 if(editor
->isError(editor
->textCursor().blockNumber() + 1))
180 QTextCursor line
= editor
->textCursor();
181 line
.movePosition(QTextCursor::StartOfLine
);
182 line
.movePosition(QTextCursor::EndOfLine
, QTextCursor::KeepAnchor
);
183 skin_parse(line
.selectedText().toAscii());
184 if(skin_error_line() > 0)
185 parseStatus
= tr("Error on line ") +
186 QString::number(line
.blockNumber() + 1) + tr(": ") +
187 skin_error_message();
188 statusLabel
->setText(parseStatus
);
190 else if(editor
->hasErrors())
192 parseStatus
= tr("Errors in document");
193 statusLabel
->setText(parseStatus
);
198 void SkinDocument::codeChanged()
203 if(editor
->document()->isEmpty())
205 parseStatus
= tr("Empty document");
206 statusLabel
->setText(parseStatus
);
210 editor
->clearErrors();
211 parseStatus
= model
->changeTree(editor
->document()->
212 toPlainText().toAscii());
213 if(skin_error_line() > 0)
214 parseStatus
= tr("Errors in document");
215 statusLabel
->setText(parseStatus
);
217 /* Highlighting if an error was found */
218 if(skin_error_line() > 0)
220 editor
->addError(skin_error_line());
222 /* Now we're going to attempt parsing again at each line, until we find
223 one that won't error out*/
224 QTextDocument
doc(editor
->document()->toPlainText());
226 while(skin_error_line() > 0 && !doc
.isEmpty())
228 QTextCursor
rest(&doc
);
230 for(int i
= 0; i
< skin_error_line(); i
++)
231 rest
.movePosition(QTextCursor::NextBlock
,
232 QTextCursor::KeepAnchor
);
233 if(skin_error_line() == doc
.blockCount())
234 rest
.movePosition(QTextCursor::End
, QTextCursor::KeepAnchor
);
236 rest
.removeSelectedText();
237 base
+= skin_error_line();
239 skin_parse(doc
.toPlainText().toAscii());
241 if(skin_error_line() > 0)
242 editor
->addError(base
+ skin_error_line());
247 if(editor
->document()->toPlainText() != saved
)
248 emit
titleChanged(title
+ QChar('*'));
250 emit
titleChanged(title
);
256 void SkinDocument::save()
258 QFile
fout(fileName
);
266 fout
.open(QFile::WriteOnly
);
267 fout
.write(editor
->document()->toPlainText().toAscii());
270 saved
= editor
->document()->toPlainText();
271 QStringList decompose
= fileName
.split('/');
272 title
= decompose
.last();
273 emit
titleChanged(title
);
277 void SkinDocument::saveAs()
279 /* Determining the directory to open */
280 QString directory
= fileName
;
283 settings
.beginGroup("SkinDocument");
285 directory
= settings
.value("defaultDirectory", "").toString();
287 fileName
= QFileDialog::getSaveFileName(this, tr("Save Document"),
288 directory
, fileFilter());
289 directory
= fileName
;
293 directory
.chop(fileName
.length() - fileName
.lastIndexOf('/') - 1);
294 settings
.setValue("defaultDirectory", directory
);
297 QFile
fout(fileName
);
298 fout
.open(QFile::WriteOnly
);
299 fout
.write(editor
->document()->toPlainText().toAscii());
302 saved
= editor
->document()->toPlainText();
303 QStringList decompose
= fileName
.split('/');
304 title
= decompose
[decompose
.count() - 1];
305 emit
titleChanged(title
);