blob: 0b80416d3a99a3a5056149fa99e83d9b5e5c09c6 [file] [log] [blame]
Robert Bieber565cd002010-05-26 21:13:14 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2010 Robert Bieber
11 *
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.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22
23#include "parsetreemodel.h"
Robert Bieber5943f4c2010-06-01 19:55:20 +000024#include "symbols.h"
25
26#include <cstdlib>
27
Robert Bieber565cd002010-05-26 21:13:14 +000028#include <QObject>
29
Robert Biebera9848ce2010-06-01 21:25:02 +000030ParseTreeModel::ParseTreeModel(const char* document, QObject* parent):
Robert Bieber565cd002010-05-26 21:13:14 +000031 QAbstractItemModel(parent)
32{
Robert Bieber98436262010-05-30 01:20:05 +000033 this->tree = skin_parse(document);
Robert Biebere5a3ec22010-06-02 20:36:30 +000034
35 if(tree)
36 this->root = new ParseTreeNode(tree);
37 else
38 this->root = 0;
Robert Bieber75560842010-06-17 06:59:46 +000039
40 scene = new QGraphicsScene();
Robert Bieber565cd002010-05-26 21:13:14 +000041}
42
43
44ParseTreeModel::~ParseTreeModel()
45{
Robert Bieber98436262010-05-30 01:20:05 +000046 if(root)
47 delete root;
48 if(tree)
49 skin_free_tree(tree);
Robert Bieber565cd002010-05-26 21:13:14 +000050}
51
Robert Bieber98436262010-05-30 01:20:05 +000052QString ParseTreeModel::genCode()
Robert Bieber6980c1e2010-05-29 00:04:04 +000053{
Robert Bieberf3491e92010-06-06 03:35:40 +000054 if(root)
55 return root->genCode();
56 else
57 return "";
Robert Bieber6980c1e2010-05-29 00:04:04 +000058}
59
Robert Bieber0e44ce92010-06-07 20:29:46 +000060QString ParseTreeModel::changeTree(const char *document)
Robert Biebere5a3ec22010-06-02 20:36:30 +000061{
62 struct skin_element* test = skin_parse(document);
63
64 if(!test)
Robert Bieber0e44ce92010-06-07 20:29:46 +000065 {
66 QString error = tr("Error on line ") +
67 QString::number(skin_error_line())
68 + tr(": ") + QString(skin_error_message());
69 return error;
70 }
Robert Biebere5a3ec22010-06-02 20:36:30 +000071
72 ParseTreeNode* temp = new ParseTreeNode(test);
73 if(root && temp->genHash() == root->genHash())
74 {
75 delete temp;
Robert Bieber0e44ce92010-06-07 20:29:46 +000076 return tr("Document Parses Successfully");
Robert Biebere5a3ec22010-06-02 20:36:30 +000077 }
78
79 if(root)
80 {
81 emit beginRemoveRows(QModelIndex(), 0, root->numChildren() - 1);
82 delete root;
83 emit endRemoveRows();
84 }
85
86 root = temp;
87
88 emit beginInsertRows(QModelIndex(), 0, temp->numChildren() - 1);
89 emit endInsertRows();
90
Robert Bieber0e44ce92010-06-07 20:29:46 +000091 return tr("Document Parses Successfully");
Robert Biebere5a3ec22010-06-02 20:36:30 +000092
93}
94
Robert Bieber565cd002010-05-26 21:13:14 +000095QModelIndex ParseTreeModel::index(int row, int column,
96 const QModelIndex& parent) const
97{
Robert Bieber9f2e1b12010-05-30 01:47:35 +000098 if(!hasIndex(row, column, parent))
99 return QModelIndex();
100
101 ParseTreeNode* foundParent;
102
103 if(parent.isValid())
104 foundParent = static_cast<ParseTreeNode*>(parent.internalPointer());
105 else
106 foundParent = root;
107
108 if(row < foundParent->numChildren() && row >= 0)
109 return createIndex(row, column, foundParent->child(row));
110 else
111 return QModelIndex();
Robert Bieber565cd002010-05-26 21:13:14 +0000112}
113
114QModelIndex ParseTreeModel::parent(const QModelIndex &child) const
115{
Robert Bieber9f2e1b12010-05-30 01:47:35 +0000116 if(!child.isValid())
117 return QModelIndex();
118
119 ParseTreeNode* foundParent = static_cast<ParseTreeNode*>
120 (child.internalPointer())->getParent();
121
122 if(foundParent == root)
123 return QModelIndex();
124
125 return createIndex(foundParent->getRow(), 0, foundParent);
Robert Bieber565cd002010-05-26 21:13:14 +0000126}
127
128int ParseTreeModel::rowCount(const QModelIndex &parent) const
129{
Robert Biebere5a3ec22010-06-02 20:36:30 +0000130 if(!root)
131 return 0;
132
Robert Bieber9f2e1b12010-05-30 01:47:35 +0000133 if(!parent.isValid())
134 return root->numChildren();
135
Robert Bieber5943f4c2010-06-01 19:55:20 +0000136 if(parent.column() != typeColumn)
Robert Bieber9f2e1b12010-05-30 01:47:35 +0000137 return 0;
138
139 return static_cast<ParseTreeNode*>(parent.internalPointer())->numChildren();
Robert Bieber565cd002010-05-26 21:13:14 +0000140}
141
142int ParseTreeModel::columnCount(const QModelIndex &parent) const
143{
Robert Bieber69dce7c2010-06-03 20:05:55 +0000144 if(parent.isValid())
145 return numColumns;
146 else
147 return numColumns;
Robert Bieber565cd002010-05-26 21:13:14 +0000148}
Robert Bieber5943f4c2010-06-01 19:55:20 +0000149
Robert Bieber565cd002010-05-26 21:13:14 +0000150QVariant ParseTreeModel::data(const QModelIndex &index, int role) const
151{
Robert Bieber9f2e1b12010-05-30 01:47:35 +0000152 if(!index.isValid())
153 return QVariant();
154
155 if(role != Qt::DisplayRole)
156 return QVariant();
157
158 return static_cast<ParseTreeNode*>(index.internalPointer())->
159 data(index.column());
Robert Bieber565cd002010-05-26 21:13:14 +0000160}
Robert Bieber5943f4c2010-06-01 19:55:20 +0000161
162QVariant ParseTreeModel::headerData(int col, Qt::Orientation orientation,
163 int role) const
164{
165 if(orientation != Qt::Horizontal)
166 return QVariant();
167
168 if(col >= numColumns)
169 return QVariant();
170
171 if(role != Qt::DisplayRole)
172 return QVariant();
173
174 switch(col)
175 {
176 case typeColumn:
177 return QObject::tr("Type");
178
179 case lineColumn:
180 return QObject::tr("Line");
181
182 case valueColumn:
183 return QObject::tr("Value");
184 }
185
186 return QVariant();
187}
188
189Qt::ItemFlags ParseTreeModel::flags(const QModelIndex &index) const
190{
191 Qt::ItemFlags retval = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
192
193 ParseTreeNode* element = static_cast<ParseTreeNode*>
194 (index.internalPointer());
Robert Bieber27996962010-06-01 20:19:51 +0000195
196 if((element->isParam()
197 || element->getElement()->type == TEXT
198 || element->getElement()->type == COMMENT)
199 && index.column() == valueColumn)
200 {
Robert Bieber5943f4c2010-06-01 19:55:20 +0000201 retval |= Qt::ItemIsEditable;
Robert Bieber27996962010-06-01 20:19:51 +0000202 }
Robert Bieber5943f4c2010-06-01 19:55:20 +0000203
204 return retval;
205}
206
207bool ParseTreeModel::setData(const QModelIndex &index, const QVariant &value,
208 int role)
209{
210 if(role != Qt::EditRole)
211 return false;
212
213 if(index.column() != valueColumn)
214 return false;
215
Robert Bieber27996962010-06-01 20:19:51 +0000216 ParseTreeNode* node = static_cast<ParseTreeNode*>
Robert Bieber5943f4c2010-06-01 19:55:20 +0000217 (index.internalPointer());
218
Robert Bieber27996962010-06-01 20:19:51 +0000219 if(node->isParam())
Robert Bieber5943f4c2010-06-01 19:55:20 +0000220 {
Robert Bieber27996962010-06-01 20:19:51 +0000221 struct skin_tag_parameter* param = node->getParam();
222
223 /* Now that we've established that we do, in fact, have a parameter,
224 * set it to its new value if an acceptable one has been entered
225 */
226 if(value.toString().trimmed() == QString(QChar(DEFAULTSYM)))
227 {
228 if(islower(param->type_code))
229 param->type = skin_tag_parameter::DEFAULT;
230 else
231 return false;
232 }
233 else if(tolower(param->type_code) == 's'
234 || tolower(param->type_code) == 'f')
235 {
236 if(param->type == skin_tag_parameter::STRING)
237 free(param->data.text);
238
239 param->type = skin_tag_parameter::STRING;
240 param->data.text = strdup(value.toString().trimmed().toAscii());
241 }
242 else if(tolower(param->type_code) == 'i')
243 {
244 if(!value.canConvert(QVariant::Int))
245 return false;
246
247 param->type = skin_tag_parameter::NUMERIC;
248 param->data.numeric = value.toInt();
249 }
Robert Bieber5943f4c2010-06-01 19:55:20 +0000250 else
Robert Bieber27996962010-06-01 20:19:51 +0000251 {
Robert Bieber5943f4c2010-06-01 19:55:20 +0000252 return false;
Robert Bieber27996962010-06-01 20:19:51 +0000253 }
Robert Bieber5943f4c2010-06-01 19:55:20 +0000254 }
255 else
256 {
Robert Bieber27996962010-06-01 20:19:51 +0000257 struct skin_element* element = node->getElement();
258
259 if(element->type != COMMENT && element->type != TEXT)
260 return false;
261
Robert Bieber64321ad2010-06-10 21:02:44 +0000262 free(element->data);
263 element->data = strdup(value.toString().trimmed().toAscii());
Robert Bieber5943f4c2010-06-01 19:55:20 +0000264 }
265
266 emit dataChanged(index, index);
267 return true;
268}
Robert Bieber75560842010-06-17 06:59:46 +0000269
270QGraphicsScene* ParseTreeModel::render(ProjectModel* project)
271{
272 scene->clear();
273
274 /* First we set the screen size */
275 int screenWidth = safeSetting(project, "#screenwidth", "300").toInt();
276 int screenHeight = safeSetting(project, "#screenheight", "200").toInt();
277 scene->addRect(0, 0, screenWidth, screenHeight);
278
279 return scene;
280}