Theme Editor: Changed default font to monospaced, changed organization for the applic...
[kugel-rb.git] / utils / themeeditor / parsetreenode.cpp
blob3a20b1e0031020a94e4637c6b9eddb20546efc9d
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 "symbols.h"
23 #include "tag_table.h"
25 #include "parsetreenode.h"
26 #include "parsetreemodel.h"
28 int ParseTreeNode::openConditionals = 0;
30 /* Root element constructor */
31 ParseTreeNode::ParseTreeNode(struct skin_element* data)
32 : parent(0), element(0), param(0), children()
34 while(data)
36 children.append(new ParseTreeNode(data, this));
37 data = data->next;
41 /* Normal element constructor */
42 ParseTreeNode::ParseTreeNode(struct skin_element* data, ParseTreeNode* parent)
43 : parent(parent), element(data), param(0), children()
45 switch(element->type)
48 case TAG:
49 for(int i = 0; i < element->params_count; i++)
51 if(element->params[i].type == skin_tag_parameter::CODE)
52 children.append(new ParseTreeNode(element->params[i].data.code,
53 this));
54 else
55 children.append(new ParseTreeNode(&element->params[i], this));
57 break;
59 /* CONDITIONAL and SUBLINES fall through to the same code */
60 case CONDITIONAL:
61 case SUBLINES:
62 for(int i = 0; i < element->children_count; i++)
64 children.append(new ParseTreeNode(data->children[i], this));
66 break;
68 case VIEWPORT:
69 case LINE:
70 for(int i = 0; i < data->children_count; i++)
72 for(struct skin_element* current = data->children[i]; current;
73 current = current->next)
75 children.append(new ParseTreeNode(current, this));
78 break;
80 default:
81 break;
85 /* Parameter constructor */
86 ParseTreeNode::ParseTreeNode(skin_tag_parameter *data, ParseTreeNode *parent)
87 : parent(parent), element(0), param(data), children()
92 QString ParseTreeNode::genCode() const
94 QString buffer = "";
96 if(element)
98 switch(element->type)
101 case VIEWPORT:
102 if(children[0]->element->type == TAG)
103 buffer.append(TAGSYM);
104 buffer.append(children[0]->genCode());
105 if(children[0]->element->type == TAG)
106 buffer.append('\n');
107 for(int i = 1; i < children.count(); i++)
108 buffer.append(children[i]->genCode());
109 break;
111 case LINE:
112 for(int i = 0; i < children.count(); i++)
115 Adding a % in case of tag, because the tag rendering code
116 doesn't insert its own
118 if(children[i]->element->type == TAG)
119 buffer.append(TAGSYM);
120 buffer.append(children[i]->genCode());
122 if(openConditionals == 0)
123 buffer.append('\n');
124 break;
126 case SUBLINES:
127 for(int i = 0; i < children.count(); i++)
129 buffer.append(children[i]->genCode());
130 if(i != children.count() - 1)
131 buffer.append(MULTILINESYM);
133 buffer.append('\n');
134 break;
136 case CONDITIONAL:
137 openConditionals++;
138 /* Inserts a %?, the tag renderer doesn't deal with the TAGSYM */
139 buffer.append(TAGSYM);
140 buffer.append(CONDITIONSYM);
141 buffer.append(children[0]->genCode());
143 /* Inserting the sublines */
144 buffer.append(ENUMLISTOPENSYM);
145 for(int i = 1; i < children.count(); i++)
147 buffer.append(children[i]->genCode());
148 if(i != children.count() - 1)
149 buffer.append(ENUMLISTSEPERATESYM);
151 buffer.append(ENUMLISTCLOSESYM);
152 openConditionals--;
153 break;
155 case TAG:
156 /* When generating code, we DO NOT insert the leading TAGSYM, leave
157 * the calling functions to handle that
159 buffer.append(element->tag->name);
161 if(element->params_count > 0)
163 /* Rendering parameters if there are any */
164 buffer.append(ARGLISTOPENSYM);
165 for(int i = 0; i < children.count(); i++)
167 buffer.append(children[i]->genCode());
168 if(i != children.count() - 1)
169 buffer.append(ARGLISTSEPERATESYM);
171 buffer.append(ARGLISTCLOSESYM);
173 break;
175 case TEXT:
176 for(char* cursor = element->text; *cursor; cursor++)
178 if(find_escape_character(*cursor))
179 buffer.append(TAGSYM);
180 buffer.append(*cursor);
182 break;
184 case COMMENT:
185 buffer.append(COMMENTSYM);
186 buffer.append(element->text);
187 buffer.append('\n');
188 break;
191 else if(param)
193 switch(param->type)
195 case skin_tag_parameter::STRING:
196 for(char* cursor = param->data.text; *cursor; cursor++)
198 if(find_escape_character(*cursor))
199 buffer.append(TAGSYM);
200 buffer.append(*cursor);
202 break;
204 case skin_tag_parameter::NUMERIC:
205 buffer.append(QString::number(param->data.numeric, 10));
206 break;
208 case skin_tag_parameter::DEFAULT:
209 buffer.append(DEFAULTSYM);
210 break;
212 case skin_tag_parameter::CODE:
213 buffer.append(QObject::tr("This doesn't belong here"));
214 break;
218 else
220 for(int i = 0; i < children.count(); i++)
221 buffer.append(children[i]->genCode());
224 return buffer;
227 /* A more or less random hashing algorithm */
228 int ParseTreeNode::genHash() const
230 int hash = 0;
232 if(element)
234 hash += element->type;
235 switch(element->type)
237 case VIEWPORT:
238 case LINE:
239 case SUBLINES:
240 case CONDITIONAL:
241 hash += element->children_count;
242 break;
244 case TAG:
245 for(unsigned int i = 0; i < strlen(element->tag->name); i++)
246 hash += element->tag->name[i];
247 break;
249 case COMMENT:
250 case TEXT:
251 for(unsigned int i = 0; i < strlen(element->text); i++)
253 if(i % 2)
254 hash += element->text[i] % element->type;
255 else
256 hash += element->text[i] % element->type * 2;
258 break;
263 if(param)
265 hash += param->type;
266 switch(param->type)
268 case skin_tag_parameter::DEFAULT:
269 case skin_tag_parameter::CODE:
270 break;
272 case skin_tag_parameter::NUMERIC:
273 hash += param->data.numeric * (param->data.numeric / 4);
274 break;
276 case skin_tag_parameter::STRING:
277 for(unsigned int i = 0; i < strlen(param->data.text); i++)
279 if(i % 2)
280 hash += param->data.text[i] * 2;
281 else
282 hash += param->data.text[i];
284 break;
288 for(int i = 0; i < children.count(); i++)
290 hash += children[i]->genHash();
293 return hash;
296 ParseTreeNode* ParseTreeNode::child(int row)
298 if(row < 0 || row >= children.count())
299 return 0;
301 return children[row];
304 int ParseTreeNode::numChildren() const
306 return children.count();
310 QVariant ParseTreeNode::data(int column) const
312 switch(column)
314 case ParseTreeModel::typeColumn:
315 if(element)
317 switch(element->type)
319 case VIEWPORT:
320 return QObject::tr("Viewport");
322 case LINE:
323 return QObject::tr("Logical Line");
325 case SUBLINES:
326 return QObject::tr("Alternator");
328 case COMMENT:
329 return QObject::tr("Comment");
331 case CONDITIONAL:
332 return QObject::tr("Conditional Tag");
334 case TAG:
335 return QObject::tr("Tag");
337 case TEXT:
338 return QObject::tr("Plaintext");
341 else if(param)
343 switch(param->type)
345 case skin_tag_parameter::STRING:
346 return QObject::tr("String");
348 case skin_tag_parameter::NUMERIC:
349 return QObject::tr("Number");
351 case skin_tag_parameter::DEFAULT:
352 return QObject::tr("Default Argument");
354 case skin_tag_parameter::CODE:
355 return QObject::tr("This doesn't belong here");
358 else
360 return QObject::tr("Root");
363 break;
365 case ParseTreeModel::valueColumn:
366 if(element)
368 switch(element->type)
370 case VIEWPORT:
371 case LINE:
372 case SUBLINES:
373 case CONDITIONAL:
374 return QString();
376 case TEXT:
377 case COMMENT:
378 return QString(element->text);
380 case TAG:
381 return QString(element->tag->name);
384 else if(param)
386 switch(param->type)
388 case skin_tag_parameter::DEFAULT:
389 return QObject::tr("-");
391 case skin_tag_parameter::STRING:
392 return QString(param->data.text);
394 case skin_tag_parameter::NUMERIC:
395 return QString::number(param->data.numeric, 10);
397 case skin_tag_parameter::CODE:
398 return QObject::tr("Seriously, something's wrong here");
401 else
403 return QString();
405 break;
407 case ParseTreeModel::lineColumn:
408 if(element)
409 return QString::number(element->line, 10);
410 else
411 return QString();
412 break;
415 return QVariant();
419 int ParseTreeNode::getRow() const
421 if(!parent)
422 return -1;
424 return parent->children.indexOf(const_cast<ParseTreeNode*>(this));
427 ParseTreeNode* ParseTreeNode::getParent() const
429 return parent;
432 ParseTreeNode::~ParseTreeNode()
434 for(int i = 0; i < children.count(); i++)
435 delete children[i];