Theme Editor: Made editor highlight all errors in a document, not just the first one
[kugel-rb.git] / utils / themeeditor / skindocument.cpp
blob93c2f6531d3b04e511bb8ddc3c68034d17ba7f08
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");
43 SkinDocument::SkinDocument(QLabel* statusLabel, QString file, QWidget *parent):
44 QWidget(parent), fileName(file), statusLabel(statusLabel)
46 setupUI();
48 /* Loading the file */
49 if(QFile::exists(fileName))
51 QFile fin(fileName);
52 fin.open(QFile::ReadOnly);
53 editor->document()->setPlainText(QString(fin.readAll()));
54 saved = editor->document()->toPlainText();
55 editor->setTextCursor(QTextCursor(editor->document()->begin()));
56 fin.close();
59 /* Setting the title */
60 QStringList decomposed = fileName.split('/');
61 title = decomposed.last();
64 SkinDocument::~SkinDocument()
66 delete highlighter;
67 delete model;
70 void SkinDocument::connectPrefs(PreferencesDialog* prefs)
72 QObject::connect(prefs, SIGNAL(accepted()),
73 this, SLOT(settingsChanged()));
74 QObject::connect(prefs, SIGNAL(accepted()),
75 highlighter, SLOT(loadSettings()));
78 bool SkinDocument::requestClose()
80 if(editor->document()->toPlainText() != saved)
82 /* Spawning the "Are you sure?" dialog */
83 QMessageBox confirm(this);
84 confirm.setWindowTitle(tr("Confirm Close"));
85 confirm.setText(title + tr(" has been modified."));
86 confirm.setInformativeText(tr("Do you want to save your changes?"));
87 confirm.setStandardButtons(QMessageBox::Save | QMessageBox::Discard
88 | QMessageBox::Cancel);
89 confirm.setDefaultButton(QMessageBox::Save);
90 int confirmation = confirm.exec();
92 switch(confirmation)
94 case QMessageBox::Save:
95 save();
96 /* After calling save, make sure the user actually went through */
97 if(editor->document()->toPlainText() != saved)
98 return false;
99 else
100 return true;
102 case QMessageBox::Discard:
103 return true;
105 case QMessageBox::Cancel:
106 return false;
110 return true;
113 void SkinDocument::setupUI()
115 /* Setting up the text edit */
116 layout = new QHBoxLayout;
117 editor = new CodeEditor(this);
118 editor->setLineWrapMode(QPlainTextEdit::NoWrap);
119 layout->addWidget(editor);
121 setLayout(layout);
123 /* Attaching the syntax highlighter */
124 highlighter = new SkinHighlighter(editor->document());
126 /* Setting up the model */
127 model = new ParseTreeModel("");
129 /* Connecting the editor's signal */
130 QObject::connect(editor, SIGNAL(textChanged()),
131 this, SLOT(codeChanged()));
133 settingsChanged();
136 void SkinDocument::settingsChanged()
138 /* Setting the editor colors */
139 QSettings settings;
140 settings.beginGroup("SkinDocument");
142 QColor fg = settings.value("fgColor", Qt::black).value<QColor>();
143 QColor bg = settings.value("bgColor", Qt::white).value<QColor>();
144 QPalette palette;
145 palette.setColor(QPalette::All, QPalette::Base, bg);
146 palette.setColor(QPalette::All, QPalette::Text, fg);
147 editor->setPalette(palette);
149 QColor highlight = settings.value("errorColor", Qt::red).value<QColor>();
150 editor->setErrorColor(highlight);
152 /* Setting the font */
153 QFont def("Monospace");
154 def.setStyleHint(QFont::TypeWriter);
155 QFont family = settings.value("fontFamily", def).value<QFont>();
156 family.setPointSize(settings.value("fontSize", 12).toInt());
157 editor->setFont(family);
159 editor->repaint();
161 settings.endGroup();
165 void SkinDocument::codeChanged()
167 editor->clearErrors();
168 parseStatus = model->changeTree(editor->document()->
169 toPlainText().toAscii());
170 statusLabel->setText(parseStatus);
172 /* Highlighting if an error was found */
173 if(skin_error_line() > 0)
175 editor->addError(skin_error_line());
177 /* Now we're going to attempt parsing again at each line, until we find
178 one that won't error out*/
179 QTextDocument doc(editor->document()->toPlainText());
180 int base = 0;
181 while(skin_error_line() > 0 && !doc.isEmpty())
183 QTextCursor rest(&doc);
185 for(int i = 0; i < skin_error_line(); i++)
186 rest.movePosition(QTextCursor::NextBlock,
187 QTextCursor::KeepAnchor);
188 if(skin_error_line() == doc.blockCount())
189 rest.movePosition(QTextCursor::End, QTextCursor::KeepAnchor);
191 rest.removeSelectedText();
192 base += skin_error_line();
194 skin_parse(doc.toPlainText().toAscii());
196 if(skin_error_line() > 0)
197 editor->addError(base + skin_error_line());
202 if(editor->document()->toPlainText() != saved)
203 emit titleChanged(title + QChar('*'));
204 else
205 emit titleChanged(title);
208 void SkinDocument::save()
210 QFile fout(fileName);
212 if(!fout.exists())
214 saveAs();
215 return;
218 fout.open(QFile::WriteOnly);
219 fout.write(editor->document()->toPlainText().toAscii());
220 fout.close();
222 saved = editor->document()->toPlainText();
223 QStringList decompose = fileName.split('/');
224 title = decompose.last();
225 emit titleChanged(title);
229 void SkinDocument::saveAs()
231 /* Determining the directory to open */
232 QString directory = fileName;
234 QSettings settings;
235 settings.beginGroup("SkinDocument");
236 if(directory == "")
237 directory = settings.value("defaultDirectory", "").toString();
239 fileName = QFileDialog::getSaveFileName(this, tr("Save Document"),
240 directory, fileFilter());
241 directory = fileName;
242 if(fileName == "")
243 return;
245 directory.chop(fileName.length() - fileName.lastIndexOf('/') - 1);
246 settings.setValue("defaultDirectory", directory);
247 settings.endGroup();
249 QFile fout(fileName);
250 fout.open(QFile::WriteOnly);
251 fout.write(editor->document()->toPlainText().toAscii());
252 fout.close();
254 saved = editor->document()->toPlainText();
255 QStringList decompose = fileName.split('/');
256 title = decompose[decompose.count() - 1];
257 emit titleChanged(title);