Theme Editor: Made errors display in status bar when cursor is on error'd line
[kugel-rb.git] / utils / themeeditor / skindocument.cpp
blob9a9bf5c85fd4aeebf910d1d6bd03f1bf3b20a433
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
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"
24 #include <QFile>
25 #include <QSettings>
26 #include <QColor>
27 #include <QMessageBox>
28 #include <QFileDialog>
30 #include <iostream>
32 SkinDocument::SkinDocument(QLabel* statusLabel, QWidget *parent) :
33 QWidget(parent), statusLabel(statusLabel)
35 setupUI();
37 title = "Untitled";
38 fileName = "";
39 saved = "";
40 parseStatus = tr("Empty document");
41 blockUpdate = false;
44 SkinDocument::SkinDocument(QLabel* statusLabel, QString file, QWidget *parent):
45 QWidget(parent), fileName(file), statusLabel(statusLabel)
47 setupUI();
48 blockUpdate = false;
50 /* Loading the file */
51 if(QFile::exists(fileName))
53 QFile fin(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()));
58 fin.close();
61 /* Setting the title */
62 QStringList decomposed = fileName.split('/');
63 title = decomposed.last();
66 SkinDocument::~SkinDocument()
68 delete highlighter;
69 delete model;
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();
96 switch(confirmation)
98 case QMessageBox::Save:
99 save();
100 /* After calling save, make sure the user actually went through */
101 if(editor->document()->toPlainText() != saved)
102 blockUpdate = false;
103 else
104 blockUpdate = true;
105 break;
107 case QMessageBox::Discard:
108 blockUpdate = true;
109 break;
111 case QMessageBox::Cancel:
112 blockUpdate = false;
113 break;
116 else
117 blockUpdate = true;
119 return blockUpdate;
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);
130 setLayout(layout);
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()));
144 settingsChanged();
147 void SkinDocument::settingsChanged()
149 /* Setting the editor colors */
150 QSettings settings;
151 settings.beginGroup("SkinDocument");
153 QColor fg = settings.value("fgColor", Qt::black).value<QColor>();
154 QColor bg = settings.value("bgColor", Qt::white).value<QColor>();
155 QPalette palette;
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);
170 editor->repaint();
172 settings.endGroup();
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()
200 if(blockUpdate)
201 return;
203 if(editor->document()->isEmpty())
205 parseStatus = tr("Empty document");
206 statusLabel->setText(parseStatus);
207 return;
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());
225 int base = 0;
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('*'));
249 else
250 emit titleChanged(title);
252 cursorChanged();
256 void SkinDocument::save()
258 QFile fout(fileName);
260 if(!fout.exists())
262 saveAs();
263 return;
266 fout.open(QFile::WriteOnly);
267 fout.write(editor->document()->toPlainText().toAscii());
268 fout.close();
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;
282 QSettings settings;
283 settings.beginGroup("SkinDocument");
284 if(directory == "")
285 directory = settings.value("defaultDirectory", "").toString();
287 fileName = QFileDialog::getSaveFileName(this, tr("Save Document"),
288 directory, fileFilter());
289 directory = fileName;
290 if(fileName == "")
291 return;
293 directory.chop(fileName.length() - fileName.lastIndexOf('/') - 1);
294 settings.setValue("defaultDirectory", directory);
295 settings.endGroup();
297 QFile fout(fileName);
298 fout.open(QFile::WriteOnly);
299 fout.write(editor->document()->toPlainText().toAscii());
300 fout.close();
302 saved = editor->document()->toPlainText();
303 QStringList decompose = fileName.split('/');
304 title = decompose[decompose.count() - 1];
305 emit titleChanged(title);