Theme Editor: Added Show Viewports option to device configuration panel, implemented...
[kugel-rb.git] / utils / themeeditor / gui / skindocument.cpp
blob6863ff5a9de28f7716385a56461a992b4466aaf2
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; 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"
24 #include <QFile>
25 #include <QSettings>
26 #include <QColor>
27 #include <QMessageBox>
28 #include <QFileDialog>
30 #include <iostream>
32 SkinDocument::SkinDocument(QLabel* statusLabel, ProjectModel* project,
33 DeviceState* device, QWidget *parent)
34 :TabContent(parent), statusLabel(statusLabel),
35 project(project), device(device)
37 setupUI();
39 titleText = "Untitled";
40 fileName = "";
41 saved = "";
42 parseStatus = tr("Empty document");
43 blockUpdate = false;
46 SkinDocument::SkinDocument(QLabel* statusLabel, QString file,
47 ProjectModel* project, DeviceState* device,
48 QWidget *parent)
49 :TabContent(parent), fileName(file),
50 statusLabel(statusLabel), project(project),
51 device(device)
53 setupUI();
54 blockUpdate = false;
56 /* Loading the file */
57 if(QFile::exists(fileName))
59 QFile fin(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()));
64 fin.close();
67 /* Setting the title */
68 QStringList decomposed = fileName.split('/');
69 titleText = decomposed.last();
72 SkinDocument::~SkinDocument()
74 highlighter->deleteLater();
75 model->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();
102 switch(confirmation)
104 case QMessageBox::Save:
105 save();
106 /* After calling save, make sure the user actually went through */
107 if(editor->document()->toPlainText() != saved)
108 blockUpdate = false;
109 else
110 blockUpdate = true;
111 break;
113 case QMessageBox::Discard:
114 blockUpdate = true;
115 break;
117 case QMessageBox::Cancel:
118 blockUpdate = false;
119 break;
122 else
123 blockUpdate = true;
125 return blockUpdate;
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);
136 setLayout(layout);
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()));
154 settingsChanged();
157 void SkinDocument::settingsChanged()
159 /* Setting the editor colors */
160 QSettings settings;
161 settings.beginGroup("SkinDocument");
163 QColor fg = settings.value("fgColor", Qt::black).value<QColor>();
164 QColor bg = settings.value("bgColor", Qt::white).value<QColor>();
165 QPalette palette;
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);
180 editor->repaint();
182 settings.endGroup();
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);
205 else
207 emit lineChanged(editor->textCursor().blockNumber() + 1);
212 void SkinDocument::codeChanged()
214 if(blockUpdate)
215 return;
217 if(editor->document()->isEmpty())
219 parseStatus = tr("Empty document");
220 statusLabel->setText(parseStatus);
221 return;
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());
239 int base = 0;
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('*'));
263 else
264 emit titleChanged(titleText);
266 model->render(project, device, &fileName);
268 cursorChanged();
272 void SkinDocument::save()
274 QFile fout(fileName);
276 if(!fout.exists())
278 saveAs();
279 return;
282 fout.open(QFile::WriteOnly);
283 fout.write(editor->document()->toPlainText().toAscii());
284 fout.close();
286 saved = editor->document()->toPlainText();
287 QStringList decompose = fileName.split('/');
288 titleText = decompose.last();
289 emit titleChanged(titleText);
291 scene();
295 void SkinDocument::saveAs()
297 /* Determining the directory to open */
298 QString directory = fileName;
300 QSettings settings;
301 settings.beginGroup("SkinDocument");
302 if(directory == "")
303 directory = settings.value("defaultDirectory", "").toString();
305 fileName = QFileDialog::getSaveFileName(this, tr("Save Document"),
306 directory, fileFilter());
307 directory = fileName;
308 if(fileName == "")
309 return;
311 directory.chop(fileName.length() - fileName.lastIndexOf('/') - 1);
312 settings.setValue("defaultDirectory", directory);
313 settings.endGroup();
315 QFile fout(fileName);
316 fout.open(QFile::WriteOnly);
317 fout.write(editor->document()->toPlainText().toAscii());
318 fout.close();
320 saved = editor->document()->toPlainText();
321 QStringList decompose = fileName.split('/');
322 titleText = decompose[decompose.count() - 1];
323 emit titleChanged(titleText);
325 scene();
329 QString SkinDocument::findSetting(QString key, QString fallback)
331 if(!project)
332 return fallback;
333 else
334 return project->getSetting(key, fallback);