Theme Editor: Committed FS#11477 to add a DECIMAL parameter type in the parser and...
[kugel-rb.git] / utils / themeeditor / models / parsetreemodel.cpp
blob66c96213abca852a48ea6142e7048becf78915f3
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 ****************************************************************************/
23 #include "parsetreemodel.h"
24 #include "symbols.h"
25 #include "rbscreen.h"
26 #include "rbrenderinfo.h"
28 #include <cstdlib>
30 #include <QObject>
31 #include <QPixmap>
32 #include <QMap>
33 #include <QDir>
35 #include <iostream>
37 ParseTreeModel::ParseTreeModel(const char* document, QObject* parent):
38 QAbstractItemModel(parent)
40 this->tree = skin_parse(document);
42 if(tree)
43 this->root = new ParseTreeNode(tree);
44 else
45 this->root = 0;
47 scene = new QGraphicsScene();
51 ParseTreeModel::~ParseTreeModel()
53 if(root)
54 delete root;
55 if(tree)
56 skin_free_tree(tree);
59 QString ParseTreeModel::genCode()
61 if(root)
62 return root->genCode();
63 else
64 return "";
67 QString ParseTreeModel::changeTree(const char *document)
69 struct skin_element* test = skin_parse(document);
71 if(!test)
73 QString error = tr("Error on line ") +
74 QString::number(skin_error_line())
75 + tr(": ") + QString(skin_error_message());
76 return error;
79 ParseTreeNode* temp = new ParseTreeNode(test);
81 if(root)
83 emit beginRemoveRows(QModelIndex(), 0, root->numChildren() - 1);
84 delete root;
85 emit endRemoveRows();
88 root = temp;
90 emit beginInsertRows(QModelIndex(), 0, temp->numChildren() - 1);
91 emit endInsertRows();
93 return tr("Document Parses Successfully");
97 QModelIndex ParseTreeModel::index(int row, int column,
98 const QModelIndex& parent) const
100 if(!hasIndex(row, column, parent))
101 return QModelIndex();
103 ParseTreeNode* foundParent;
105 if(parent.isValid())
106 foundParent = static_cast<ParseTreeNode*>(parent.internalPointer());
107 else
108 foundParent = root;
110 if(row < foundParent->numChildren() && row >= 0)
111 return createIndex(row, column, foundParent->child(row));
112 else
113 return QModelIndex();
116 QModelIndex ParseTreeModel::parent(const QModelIndex &child) const
118 if(!child.isValid())
119 return QModelIndex();
121 ParseTreeNode* foundParent = static_cast<ParseTreeNode*>
122 (child.internalPointer())->getParent();
124 if(foundParent == root)
125 return QModelIndex();
127 return createIndex(foundParent->getRow(), 0, foundParent);
130 int ParseTreeModel::rowCount(const QModelIndex &parent) const
132 if(!root)
133 return 0;
135 if(!parent.isValid())
136 return root->numChildren();
138 if(parent.column() != typeColumn)
139 return 0;
141 return static_cast<ParseTreeNode*>(parent.internalPointer())->numChildren();
144 int ParseTreeModel::columnCount(const QModelIndex &parent) const
146 if(parent.isValid())
147 return numColumns;
148 else
149 return numColumns;
152 QVariant ParseTreeModel::data(const QModelIndex &index, int role) const
154 if(!index.isValid())
155 return QVariant();
157 if(role != Qt::DisplayRole)
158 return QVariant();
160 return static_cast<ParseTreeNode*>(index.internalPointer())->
161 data(index.column());
164 QVariant ParseTreeModel::headerData(int col, Qt::Orientation orientation,
165 int role) const
167 if(orientation != Qt::Horizontal)
168 return QVariant();
170 if(col >= numColumns)
171 return QVariant();
173 if(role != Qt::DisplayRole)
174 return QVariant();
176 switch(col)
178 case typeColumn:
179 return QObject::tr("Type");
181 case lineColumn:
182 return QObject::tr("Line");
184 case valueColumn:
185 return QObject::tr("Value");
188 return QVariant();
191 Qt::ItemFlags ParseTreeModel::flags(const QModelIndex &index) const
193 Qt::ItemFlags retval = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
195 ParseTreeNode* element = static_cast<ParseTreeNode*>
196 (index.internalPointer());
198 if((element->isParam()
199 || element->getElement()->type == TEXT
200 || element->getElement()->type == COMMENT)
201 && index.column() == valueColumn)
203 retval |= Qt::ItemIsEditable;
206 return retval;
209 bool ParseTreeModel::setData(const QModelIndex &index, const QVariant &value,
210 int role)
212 if(role != Qt::EditRole)
213 return false;
215 if(index.column() != valueColumn)
216 return false;
218 ParseTreeNode* node = static_cast<ParseTreeNode*>
219 (index.internalPointer());
221 if(node->isParam())
223 struct skin_tag_parameter* param = node->getParam();
225 /* Now that we've established that we do, in fact, have a parameter,
226 * set it to its new value if an acceptable one has been entered
228 if(value.toString().trimmed() == QString(QChar(DEFAULTSYM)))
230 if(islower(param->type_code))
231 param->type = skin_tag_parameter::DEFAULT;
232 else
233 return false;
235 else if(tolower(param->type_code) == 's'
236 || tolower(param->type_code) == 'f')
238 if(param->type == skin_tag_parameter::STRING)
239 free(param->data.text);
241 param->type = skin_tag_parameter::STRING;
242 param->data.text = strdup(value.toString().trimmed().toAscii());
244 else if(tolower(param->type_code) == 'i')
246 if(!value.canConvert(QVariant::Int))
247 return false;
249 param->type = skin_tag_parameter::INTEGER;
250 param->data.number = value.toInt();
252 else
254 return false;
257 else
259 struct skin_element* element = node->getElement();
261 if(element->type != COMMENT && element->type != TEXT)
262 return false;
264 free(element->data);
265 element->data = strdup(value.toString().trimmed().toAscii());
268 emit dataChanged(index, index);
269 return true;
272 QGraphicsScene* ParseTreeModel::render(ProjectModel* project,
273 DeviceState* device, const QString* file)
275 scene->clear();
277 /* Setting the background */
278 scene->setBackgroundBrush(QBrush(QPixmap(":/render/scenebg.png")));
280 /* Preparing settings */
281 QMap<QString, QString> settings;
282 if(project)
283 settings = project->getSettings();
285 /* Setting themebase if it can't be derived from the project */
286 if(settings.value("themebase", "") == "" && file && QFile::exists(*file))
288 QDir base(*file);
289 base.cdUp();
290 settings.insert("themebase", base.canonicalPath());
293 /* Finding imagebase and determining remote/wps status */
294 bool remote = false;
295 bool wps = false;
296 if(file)
298 QString skinFile = *file;
299 QStringList decomp = skinFile.split("/");
300 skinFile = decomp[decomp.count() - 1];
301 skinFile.chop(skinFile.length() - skinFile.lastIndexOf("."));
302 settings.insert("imagepath", settings.value("themebase","") + "/wps/" +
303 skinFile);
305 decomp = file->split(".");
306 QString extension = decomp.last();
307 if(extension[0] == 'r')
308 remote = true;
309 if(extension.right(3) == "wps")
310 wps = true;
313 /* Rendering SBS, if necessary */
314 RBScreen* sbsScreen = 0;
315 if(wps && device->data("rendersbs").toBool())
317 QString sbsFile = settings.value(remote ? "rsbs" : "sbs", "");
318 sbsFile.replace("/.rockbox" , settings.value("themebase",""));
320 if(QFile::exists(sbsFile))
322 QFile sbs(sbsFile);
323 sbs.open(QFile::ReadOnly | QFile::Text);
324 ParseTreeModel sbsModel(QString(sbs.readAll()).toAscii());
326 if(sbsModel.root != 0)
328 RBRenderInfo sbsInfo(&sbsModel, project, &settings, device,
329 sbsScreen);
331 sbsScreen = new RBScreen(sbsInfo, remote);
332 scene->addItem(sbsScreen);
334 sbsInfo = RBRenderInfo(&sbsModel, project, &settings, device,
335 sbsScreen);
336 sbsModel.root->render(sbsInfo);
342 RBScreen* screen = 0;
343 RBRenderInfo info(this, project, &settings, device, screen, sbsScreen);
345 /* Adding the screen */
346 if(sbsScreen)
347 screen = new RBScreen(info, remote, sbsScreen->getCustomUI());
348 else
349 screen = new RBScreen(info, remote);
351 if(!sbsScreen)
352 scene->addItem(screen);
354 info = RBRenderInfo(this, project, &settings, device, screen, sbsScreen);
357 /* Rendering the tree */
358 if(root)
359 root->render(info);
361 return scene;