blob: 1c7de7cc259db65a4d8732ebbf112b42ca1c8e82 [file] [log] [blame]
Robert Bieber6980c1e2010-05-29 00:04:04 +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
Robert Bieber6980c1e2010-05-29 00:04:04 +000022#include "symbols.h"
Robert Bieber0a054b22010-06-01 16:44:52 +000023#include "tag_table.h"
Robert Bieber6980c1e2010-05-29 00:04:04 +000024
Robert Bieber565cd002010-05-26 21:13:14 +000025#include "parsetreenode.h"
Robert Bieber5943f4c2010-06-01 19:55:20 +000026#include "parsetreemodel.h"
Robert Bieber565cd002010-05-26 21:13:14 +000027
Robert Bieberd3027052010-06-23 07:18:22 +000028#include "rbimage.h"
Robert Bieber97427042010-07-02 00:20:36 +000029#include "rbprogressbar.h"
Robert Bieber14238742010-07-10 06:43:50 +000030#include "rbtoucharea.h"
Robert Bieberd3027052010-06-23 07:18:22 +000031
Robert Biebere1d8a3d2010-06-21 20:11:58 +000032#include <iostream>
Robert Bieber13e97cd2010-07-07 22:25:42 +000033#include <cmath>
Robert Bieberd1a392a2010-08-09 19:37:23 +000034#include <cassert>
35
36#include <QDebug>
Robert Biebere1d8a3d2010-06-21 20:11:58 +000037
Robert Bieber496bcf32010-06-02 07:48:48 +000038int ParseTreeNode::openConditionals = 0;
Robert Bieber32ff4e92010-07-04 01:39:57 +000039bool ParseTreeNode::breakFlag = false;
Robert Bieber496bcf32010-06-02 07:48:48 +000040
Robert Bieber6980c1e2010-05-29 00:04:04 +000041/* Root element constructor */
Robert Bieber054a85f2010-08-05 00:43:33 +000042ParseTreeNode::ParseTreeNode(struct skin_element* data, ParseTreeModel* model)
43 : parent(0), element(0), param(0), children(), model(model)
Robert Bieber565cd002010-05-26 21:13:14 +000044{
Robert Bieber6980c1e2010-05-29 00:04:04 +000045 while(data)
Robert Bieber8ea056d2010-05-27 19:57:15 +000046 {
Robert Bieber054a85f2010-08-05 00:43:33 +000047 children.append(new ParseTreeNode(data, this, model));
Robert Bieber6980c1e2010-05-29 00:04:04 +000048 data = data->next;
49 }
50}
51
52/* Normal element constructor */
Robert Bieber054a85f2010-08-05 00:43:33 +000053ParseTreeNode::ParseTreeNode(struct skin_element* data, ParseTreeNode* parent,
54 ParseTreeModel* model)
55 : parent(parent), element(data), param(0),
56 children(), model(model)
Robert Bieber6980c1e2010-05-29 00:04:04 +000057{
58 switch(element->type)
59 {
60
61 case TAG:
62 for(int i = 0; i < element->params_count; i++)
Robert Bieber8ea056d2010-05-27 19:57:15 +000063 {
Robert Bieber6980c1e2010-05-29 00:04:04 +000064 if(element->params[i].type == skin_tag_parameter::CODE)
65 children.append(new ParseTreeNode(element->params[i].data.code,
Robert Bieber054a85f2010-08-05 00:43:33 +000066 this, model));
Robert Bieber6980c1e2010-05-29 00:04:04 +000067 else
Robert Bieber054a85f2010-08-05 00:43:33 +000068 children.append(new ParseTreeNode(&element->params[i], this,
69 model));
Robert Bieber8ea056d2010-05-27 19:57:15 +000070 }
Robert Bieber6980c1e2010-05-29 00:04:04 +000071 break;
72
Robert Bieber6980c1e2010-05-29 00:04:04 +000073 case CONDITIONAL:
Robert Bieber64321ad2010-06-10 21:02:44 +000074 for(int i = 0; i < element->params_count; i++)
Robert Bieber054a85f2010-08-05 00:43:33 +000075 children.append(new ParseTreeNode(&data->params[i], this, model));
Robert Bieber64321ad2010-06-10 21:02:44 +000076 for(int i = 0; i < element->children_count; i++)
Robert Bieber054a85f2010-08-05 00:43:33 +000077 children.append(new ParseTreeNode(data->children[i], this, model));
Robert Bieber64321ad2010-06-10 21:02:44 +000078 break;
79
Jonathan Gordondc347852010-07-04 02:04:14 +000080 case LINE_ALTERNATOR:
Robert Bieber6980c1e2010-05-29 00:04:04 +000081 for(int i = 0; i < element->children_count; i++)
82 {
Robert Bieber054a85f2010-08-05 00:43:33 +000083 children.append(new ParseTreeNode(data->children[i], this, model));
Robert Bieber6980c1e2010-05-29 00:04:04 +000084 }
85 break;
86
Robert Bieber3c95dbb2010-06-11 19:51:34 +000087case VIEWPORT:
88 for(int i = 0; i < element->params_count; i++)
Robert Bieber054a85f2010-08-05 00:43:33 +000089 children.append(new ParseTreeNode(&data->params[i], this, model));
Robert Bieber3c95dbb2010-06-11 19:51:34 +000090 /* Deliberate fall-through here */
91
Robert Bieber6980c1e2010-05-29 00:04:04 +000092 case LINE:
Robert Bieber47cd8782010-06-01 18:31:58 +000093 for(int i = 0; i < data->children_count; i++)
Robert Bieber6980c1e2010-05-29 00:04:04 +000094 {
Robert Bieber47cd8782010-06-01 18:31:58 +000095 for(struct skin_element* current = data->children[i]; current;
96 current = current->next)
97 {
Robert Bieber054a85f2010-08-05 00:43:33 +000098 children.append(new ParseTreeNode(current, this, model));
Robert Bieber47cd8782010-06-01 18:31:58 +000099 }
Robert Bieber6980c1e2010-05-29 00:04:04 +0000100 }
101 break;
102
103 default:
104 break;
105 }
106}
107
108/* Parameter constructor */
Robert Bieber054a85f2010-08-05 00:43:33 +0000109ParseTreeNode::ParseTreeNode(skin_tag_parameter *data, ParseTreeNode *parent,
110 ParseTreeModel *model)
111 : parent(parent), element(0), param(data),
112 children(), model(model)
Robert Bieber6980c1e2010-05-29 00:04:04 +0000113{
114
115}
116
Robert Bieberd8827b52010-06-18 21:10:01 +0000117ParseTreeNode::~ParseTreeNode()
118{
119 for(int i = 0; i < children.count(); i++)
120 delete children[i];
121}
122
Robert Bieber6980c1e2010-05-29 00:04:04 +0000123QString ParseTreeNode::genCode() const
124{
125 QString buffer = "";
126
127 if(element)
128 {
129 switch(element->type)
130 {
Jonathan Gordon35b09cb2010-06-13 03:13:01 +0000131 case UNKNOWN:
132 break;
Robert Bieberd1659d62010-06-01 07:11:23 +0000133 case VIEWPORT:
Robert Bieber1b613f52010-06-11 08:03:32 +0000134 /* Generating the Viewport tag, if necessary */
135 if(element->tag)
136 {
137 buffer.append(TAGSYM);
138 buffer.append(element->tag->name);
139 buffer.append(ARGLISTOPENSYM);
140 for(int i = 0; i < element->params_count; i++)
141 {
142 buffer.append(children[i]->genCode());
143 if(i != element->params_count - 1)
Teruaki Kawashima24b0b382010-11-07 12:29:19 +0000144 buffer.append(ARGLISTSEPARATESYM);
Robert Bieber1b613f52010-06-11 08:03:32 +0000145 }
146 buffer.append(ARGLISTCLOSESYM);
Robert Biebere25c9032010-06-02 06:41:41 +0000147 buffer.append('\n');
Robert Bieber1b613f52010-06-11 08:03:32 +0000148 }
149
150 for(int i = element->params_count; i < children.count(); i++)
Robert Biebere25c9032010-06-02 06:41:41 +0000151 buffer.append(children[i]->genCode());
152 break;
153
Robert Bieber6980c1e2010-05-29 00:04:04 +0000154 case LINE:
155 for(int i = 0; i < children.count(); i++)
156 {
Robert Bieber6980c1e2010-05-29 00:04:04 +0000157 buffer.append(children[i]->genCode());
158 }
Robert Bieber66d9ab22010-06-10 21:52:53 +0000159 if(openConditionals == 0
Robert Bieber5d4b8e02010-08-05 06:25:53 +0000160 && !(parent && parent->element->type == LINE_ALTERNATOR)
161 && !(children.count() > 0 &&
162 children[children.count() - 1]->getElement()->type
163 == COMMENT))
Robert Bieber66d9ab22010-06-10 21:52:53 +0000164 {
Robert Bieber496bcf32010-06-02 07:48:48 +0000165 buffer.append('\n');
Robert Bieber66d9ab22010-06-10 21:52:53 +0000166 }
Robert Bieber6980c1e2010-05-29 00:04:04 +0000167 break;
168
Jonathan Gordondc347852010-07-04 02:04:14 +0000169 case LINE_ALTERNATOR:
Robert Bieber6980c1e2010-05-29 00:04:04 +0000170 for(int i = 0; i < children.count(); i++)
171 {
172 buffer.append(children[i]->genCode());
173 if(i != children.count() - 1)
174 buffer.append(MULTILINESYM);
175 }
Robert Bieber66d9ab22010-06-10 21:52:53 +0000176 if(openConditionals == 0)
177 buffer.append('\n');
Robert Bieber6980c1e2010-05-29 00:04:04 +0000178 break;
179
180 case CONDITIONAL:
Robert Bieber496bcf32010-06-02 07:48:48 +0000181 openConditionals++;
Robert Bieber66d9ab22010-06-10 21:52:53 +0000182
183 /* Inserting the tag part */
Robert Bieber6980c1e2010-05-29 00:04:04 +0000184 buffer.append(TAGSYM);
185 buffer.append(CONDITIONSYM);
Robert Bieber66d9ab22010-06-10 21:52:53 +0000186 buffer.append(element->tag->name);
187 if(element->params_count > 0)
188 {
189 buffer.append(ARGLISTOPENSYM);
190 for(int i = 0; i < element->params_count; i++)
191 {
192 buffer.append(children[i]->genCode());
193 if( i != element->params_count - 1)
Teruaki Kawashima24b0b382010-11-07 12:29:19 +0000194 buffer.append(ARGLISTSEPARATESYM);
Robert Bieber66d9ab22010-06-10 21:52:53 +0000195 buffer.append(ARGLISTCLOSESYM);
196 }
197 }
Robert Bieber6980c1e2010-05-29 00:04:04 +0000198
199 /* Inserting the sublines */
200 buffer.append(ENUMLISTOPENSYM);
Robert Bieber66d9ab22010-06-10 21:52:53 +0000201 for(int i = element->params_count; i < children.count(); i++)
Robert Bieber6980c1e2010-05-29 00:04:04 +0000202 {
203 buffer.append(children[i]->genCode());
204 if(i != children.count() - 1)
Teruaki Kawashima24b0b382010-11-07 12:29:19 +0000205 buffer.append(ENUMLISTSEPARATESYM);
Robert Bieber6980c1e2010-05-29 00:04:04 +0000206 }
207 buffer.append(ENUMLISTCLOSESYM);
Robert Bieber496bcf32010-06-02 07:48:48 +0000208 openConditionals--;
Robert Bieber6980c1e2010-05-29 00:04:04 +0000209 break;
210
211 case TAG:
Robert Bieber66d9ab22010-06-10 21:52:53 +0000212 buffer.append(TAGSYM);
Robert Bieber0a054b22010-06-01 16:44:52 +0000213 buffer.append(element->tag->name);
Robert Bieber6980c1e2010-05-29 00:04:04 +0000214
215 if(element->params_count > 0)
216 {
217 /* Rendering parameters if there are any */
218 buffer.append(ARGLISTOPENSYM);
219 for(int i = 0; i < children.count(); i++)
220 {
221 buffer.append(children[i]->genCode());
222 if(i != children.count() - 1)
Teruaki Kawashima24b0b382010-11-07 12:29:19 +0000223 buffer.append(ARGLISTSEPARATESYM);
Robert Bieber6980c1e2010-05-29 00:04:04 +0000224 }
225 buffer.append(ARGLISTCLOSESYM);
226 }
Robert Biebere472c392010-07-03 23:31:08 +0000227 if(element->tag->params[strlen(element->tag->params) - 1] == '\n')
228 buffer.append('\n');
Robert Bieber6980c1e2010-05-29 00:04:04 +0000229 break;
230
Robert Bieber6980c1e2010-05-29 00:04:04 +0000231 case TEXT:
Robert Bieber64321ad2010-06-10 21:02:44 +0000232 for(char* cursor = (char*)element->data; *cursor; cursor++)
Robert Bieberf16adb02010-06-02 05:55:41 +0000233 {
234 if(find_escape_character(*cursor))
235 buffer.append(TAGSYM);
236 buffer.append(*cursor);
237 }
Robert Bieber6980c1e2010-05-29 00:04:04 +0000238 break;
239
240 case COMMENT:
241 buffer.append(COMMENTSYM);
Robert Bieber64321ad2010-06-10 21:02:44 +0000242 buffer.append((char*)element->data);
Robert Bieber27996962010-06-01 20:19:51 +0000243 buffer.append('\n');
Robert Bieber6980c1e2010-05-29 00:04:04 +0000244 break;
245 }
246 }
247 else if(param)
248 {
249 switch(param->type)
250 {
251 case skin_tag_parameter::STRING:
Robert Bieberf16adb02010-06-02 05:55:41 +0000252 for(char* cursor = param->data.text; *cursor; cursor++)
253 {
254 if(find_escape_character(*cursor))
255 buffer.append(TAGSYM);
256 buffer.append(*cursor);
257 }
Robert Bieber6980c1e2010-05-29 00:04:04 +0000258 break;
259
Robert Bieber15488a02010-07-15 06:24:11 +0000260 case skin_tag_parameter::INTEGER:
261 buffer.append(QString::number(param->data.number, 10));
262 break;
263
264 case skin_tag_parameter::DECIMAL:
265 buffer.append(QString::number(param->data.number / 10., 'f', 1));
Robert Bieber6980c1e2010-05-29 00:04:04 +0000266 break;
267
268 case skin_tag_parameter::DEFAULT:
269 buffer.append(DEFAULTSYM);
270 break;
271
Robert Bieber98436262010-05-30 01:20:05 +0000272 case skin_tag_parameter::CODE:
273 buffer.append(QObject::tr("This doesn't belong here"));
274 break;
275
Robert Bieber6980c1e2010-05-29 00:04:04 +0000276 }
Robert Bieber8ea056d2010-05-27 19:57:15 +0000277 }
278 else
279 {
Robert Bieber6980c1e2010-05-29 00:04:04 +0000280 for(int i = 0; i < children.count(); i++)
281 buffer.append(children[i]->genCode());
Robert Bieber8ea056d2010-05-27 19:57:15 +0000282 }
283
Robert Bieber6980c1e2010-05-29 00:04:04 +0000284 return buffer;
Robert Bieber565cd002010-05-26 21:13:14 +0000285}
Robert Bieber98436262010-05-30 01:20:05 +0000286
Robert Biebere5a3ec22010-06-02 20:36:30 +0000287/* A more or less random hashing algorithm */
288int ParseTreeNode::genHash() const
289{
290 int hash = 0;
Robert Bieber64321ad2010-06-10 21:02:44 +0000291 char *text;
Robert Biebere5a3ec22010-06-02 20:36:30 +0000292
293 if(element)
294 {
295 hash += element->type;
296 switch(element->type)
297 {
Jonathan Gordon35b09cb2010-06-13 03:13:01 +0000298 case UNKNOWN:
299 break;
Robert Biebere5a3ec22010-06-02 20:36:30 +0000300 case VIEWPORT:
301 case LINE:
Jonathan Gordondc347852010-07-04 02:04:14 +0000302 case LINE_ALTERNATOR:
Robert Biebere5a3ec22010-06-02 20:36:30 +0000303 case CONDITIONAL:
304 hash += element->children_count;
305 break;
306
307 case TAG:
308 for(unsigned int i = 0; i < strlen(element->tag->name); i++)
309 hash += element->tag->name[i];
310 break;
311
312 case COMMENT:
313 case TEXT:
Robert Bieber64321ad2010-06-10 21:02:44 +0000314 text = (char*)element->data;
315 for(unsigned int i = 0; i < strlen(text); i++)
Robert Biebere5a3ec22010-06-02 20:36:30 +0000316 {
317 if(i % 2)
Robert Bieber64321ad2010-06-10 21:02:44 +0000318 hash += text[i] % element->type;
Robert Biebere5a3ec22010-06-02 20:36:30 +0000319 else
Robert Bieber64321ad2010-06-10 21:02:44 +0000320 hash += text[i] % element->type * 2;
Robert Biebere5a3ec22010-06-02 20:36:30 +0000321 }
322 break;
323 }
324
325 }
326
327 if(param)
328 {
329 hash += param->type;
330 switch(param->type)
331 {
332 case skin_tag_parameter::DEFAULT:
333 case skin_tag_parameter::CODE:
334 break;
335
Robert Bieber15488a02010-07-15 06:24:11 +0000336 case skin_tag_parameter::INTEGER:
337 hash += param->data.number * (param->data.number / 4);
Robert Biebere5a3ec22010-06-02 20:36:30 +0000338 break;
339
340 case skin_tag_parameter::STRING:
341 for(unsigned int i = 0; i < strlen(param->data.text); i++)
342 {
343 if(i % 2)
344 hash += param->data.text[i] * 2;
345 else
346 hash += param->data.text[i];
347 }
348 break;
Robert Bieber15488a02010-07-15 06:24:11 +0000349
350 case skin_tag_parameter::DECIMAL:
351 hash += param->data.number;
352 break;
Robert Biebere5a3ec22010-06-02 20:36:30 +0000353 }
354 }
355
356 for(int i = 0; i < children.count(); i++)
357 {
358 hash += children[i]->genHash();
359 }
360
361 return hash;
362}
363
Robert Bieber98436262010-05-30 01:20:05 +0000364ParseTreeNode* ParseTreeNode::child(int row)
365{
366 if(row < 0 || row >= children.count())
367 return 0;
368
369 return children[row];
370}
371
372int ParseTreeNode::numChildren() const
373{
Robert Biebere5a3ec22010-06-02 20:36:30 +0000374 return children.count();
Robert Bieber98436262010-05-30 01:20:05 +0000375}
376
377
378QVariant ParseTreeNode::data(int column) const
379{
380 switch(column)
381 {
Robert Bieber5943f4c2010-06-01 19:55:20 +0000382 case ParseTreeModel::typeColumn:
Robert Bieber98436262010-05-30 01:20:05 +0000383 if(element)
384 {
385 switch(element->type)
386 {
Jonathan Gordon35b09cb2010-06-13 03:13:01 +0000387 case UNKNOWN:
388 return QObject::tr("Unknown");
Robert Bieberd1659d62010-06-01 07:11:23 +0000389 case VIEWPORT:
390 return QObject::tr("Viewport");
391
Robert Bieber98436262010-05-30 01:20:05 +0000392 case LINE:
393 return QObject::tr("Logical Line");
394
Jonathan Gordondc347852010-07-04 02:04:14 +0000395 case LINE_ALTERNATOR:
Robert Bieber98436262010-05-30 01:20:05 +0000396 return QObject::tr("Alternator");
397
398 case COMMENT:
399 return QObject::tr("Comment");
400
401 case CONDITIONAL:
402 return QObject::tr("Conditional Tag");
403
404 case TAG:
405 return QObject::tr("Tag");
406
Robert Bieber98436262010-05-30 01:20:05 +0000407 case TEXT:
408 return QObject::tr("Plaintext");
409 }
410 }
411 else if(param)
412 {
413 switch(param->type)
414 {
415 case skin_tag_parameter::STRING:
416 return QObject::tr("String");
417
Robert Bieber15488a02010-07-15 06:24:11 +0000418 case skin_tag_parameter::INTEGER:
419 return QObject::tr("Integer");
420
421 case skin_tag_parameter::DECIMAL:
422 return QObject::tr("Decimal");
Robert Bieber98436262010-05-30 01:20:05 +0000423
424 case skin_tag_parameter::DEFAULT:
425 return QObject::tr("Default Argument");
426
427 case skin_tag_parameter::CODE:
428 return QObject::tr("This doesn't belong here");
429 }
430 }
431 else
432 {
433 return QObject::tr("Root");
434 }
435
436 break;
437
Robert Bieber5943f4c2010-06-01 19:55:20 +0000438 case ParseTreeModel::valueColumn:
Robert Bieber98436262010-05-30 01:20:05 +0000439 if(element)
440 {
441 switch(element->type)
442 {
Jonathan Gordon35b09cb2010-06-13 03:13:01 +0000443 case UNKNOWN:
Robert Bieberd1659d62010-06-01 07:11:23 +0000444 case VIEWPORT:
Robert Bieber98436262010-05-30 01:20:05 +0000445 case LINE:
Jonathan Gordondc347852010-07-04 02:04:14 +0000446 case LINE_ALTERNATOR:
Robert Bieber98436262010-05-30 01:20:05 +0000447 return QString();
448
Robert Bieber64321ad2010-06-10 21:02:44 +0000449 case CONDITIONAL:
450 return QString(element->tag->name);
451
Robert Bieber98436262010-05-30 01:20:05 +0000452 case TEXT:
453 case COMMENT:
Robert Bieber64321ad2010-06-10 21:02:44 +0000454 return QString((char*)element->data);
Robert Bieber98436262010-05-30 01:20:05 +0000455
Robert Bieber98436262010-05-30 01:20:05 +0000456 case TAG:
Robert Bieber0a054b22010-06-01 16:44:52 +0000457 return QString(element->tag->name);
Robert Bieber98436262010-05-30 01:20:05 +0000458 }
459 }
460 else if(param)
461 {
462 switch(param->type)
463 {
464 case skin_tag_parameter::DEFAULT:
465 return QObject::tr("-");
466
467 case skin_tag_parameter::STRING:
468 return QString(param->data.text);
469
Robert Bieber15488a02010-07-15 06:24:11 +0000470 case skin_tag_parameter::INTEGER:
471 return QString::number(param->data.number, 10);
472
473 case skin_tag_parameter::DECIMAL:
474 return QString::number(param->data.number / 10., 'f', 1);
Robert Bieber98436262010-05-30 01:20:05 +0000475
476 case skin_tag_parameter::CODE:
477 return QObject::tr("Seriously, something's wrong here");
Robert Bieber15488a02010-07-15 06:24:11 +0000478
Robert Bieber98436262010-05-30 01:20:05 +0000479 }
480 }
481 else
482 {
483 return QString();
484 }
485 break;
486
Robert Bieber5943f4c2010-06-01 19:55:20 +0000487 case ParseTreeModel::lineColumn:
Robert Bieber98436262010-05-30 01:20:05 +0000488 if(element)
489 return QString::number(element->line, 10);
490 else
491 return QString();
492 break;
493 }
494
495 return QVariant();
496}
497
498
499int ParseTreeNode::getRow() const
500{
501 if(!parent)
502 return -1;
503
504 return parent->children.indexOf(const_cast<ParseTreeNode*>(this));
505}
506
507ParseTreeNode* ParseTreeNode::getParent() const
508{
509 return parent;
510}
511
Robert Bieberac9287b2010-06-22 07:55:50 +0000512/* This version is called for the root node and for viewports */
Robert Bieberd8827b52010-06-18 21:10:01 +0000513void ParseTreeNode::render(const RBRenderInfo& info)
Robert Bieber98436262010-05-30 01:20:05 +0000514{
Robert Bieberd8827b52010-06-18 21:10:01 +0000515 /* Parameters don't get rendered */
516 if(!element && param)
517 return;
518
519 /* If we're at the root, we need to render each viewport */
520 if(!element && !param)
521 {
522 for(int i = 0; i < children.count(); i++)
523 {
524 children[i]->render(info);
525 }
526
527 return;
528 }
529
Robert Biebere1d8a3d2010-06-21 20:11:58 +0000530 if(element->type != VIEWPORT)
Robert Bieberd8827b52010-06-18 21:10:01 +0000531 {
Robert Biebere1d8a3d2010-06-21 20:11:58 +0000532 std::cerr << QObject::tr("Error in parse tree").toStdString()
533 << std::endl;
534 return;
Robert Bieberd8827b52010-06-18 21:10:01 +0000535 }
Robert Biebere1d8a3d2010-06-21 20:11:58 +0000536
Robert Bieber49865b22010-08-04 09:16:52 +0000537 rendered = new RBViewport(element, info, this);
Robert Bieberac9287b2010-06-22 07:55:50 +0000538
539 for(int i = element->params_count; i < children.count(); i++)
540 children[i]->render(info, dynamic_cast<RBViewport*>(rendered));
Robert Bieberd3027052010-06-23 07:18:22 +0000541
Robert Bieber98436262010-05-30 01:20:05 +0000542}
Robert Bieberd8827b52010-06-18 21:10:01 +0000543
Robert Bieber449a8952010-06-29 06:14:36 +0000544/* This version is called for logical lines, tags, conditionals and such */
Robert Bieber9d6b5d62010-06-29 20:39:45 +0000545void ParseTreeNode::render(const RBRenderInfo &info, RBViewport* viewport,
546 bool noBreak)
Robert Bieberac9287b2010-06-22 07:55:50 +0000547{
Robert Bieber92882f22010-08-06 07:53:19 +0000548 if(!element)
549 return;
550
Robert Bieberac9287b2010-06-22 07:55:50 +0000551 if(element->type == LINE)
552 {
553 for(int i = 0; i < children.count(); i++)
554 children[i]->render(info, viewport);
Robert Bieber32ff4e92010-07-04 01:39:57 +0000555 if(!noBreak && !breakFlag)
Robert Biebera54bfaa2010-07-01 20:30:19 +0000556 viewport->newLine();
Robert Bieber6f067932010-07-07 08:41:36 +0000557 else
558 viewport->flushText();
Robert Bieber32ff4e92010-07-04 01:39:57 +0000559
560 if(breakFlag)
561 breakFlag = false;
Robert Bieber273b9d62010-06-25 05:14:13 +0000562 }
563 else if(element->type == TEXT)
564 {
565 viewport->write(QString(static_cast<char*>(element->data)));
Robert Bieberac9287b2010-06-22 07:55:50 +0000566 }
567 else if(element->type == TAG)
568 {
Robert Bieberaa13a532010-06-29 05:23:22 +0000569 if(!execTag(info, viewport))
570 viewport->write(evalTag(info).toString());
Robert Bieber32ff4e92010-07-04 01:39:57 +0000571 if(element->tag->flags & NOBREAK)
572 breakFlag = true;
Robert Bieber449a8952010-06-29 06:14:36 +0000573 }
574 else if(element->type == CONDITIONAL)
575 {
576 int child = evalTag(info, true, element->children_count).toInt();
Robert Bieberd1a392a2010-08-09 19:37:23 +0000577 int max = children.count() - element->params_count;
578 if(child < max)
579 {
Robert Bieberb22077c2010-07-29 06:41:33 +0000580 children[element->params_count + child]
581 ->render(info, viewport, true);
Robert Bieberd1a392a2010-08-09 19:37:23 +0000582 }
Robert Bieberaa13a532010-06-29 05:23:22 +0000583 }
Jonathan Gordondc347852010-07-04 02:04:14 +0000584 else if(element->type == LINE_ALTERNATOR)
Robert Bieber3ecef7d2010-06-29 19:59:33 +0000585 {
586 /* First we build a list of the times for each branch */
587 QList<double> times;
588 for(int i = 0; i < children.count() ; i++)
589 times.append(findBranchTime(children[i], info));
590
Robert Bieber13e97cd2010-07-07 22:25:42 +0000591 double totalTime = 0;
592 for(int i = 0; i < children.count(); i++)
593 totalTime += times[i];
594
Robert Bieber3ecef7d2010-06-29 19:59:33 +0000595 /* Now we figure out which branch to select */
Robert Bieberde9ba102010-07-07 20:56:16 +0000596 double timeLeft = info.device()->data(QString("simtime")).toDouble();
Robert Bieber13e97cd2010-07-07 22:25:42 +0000597
598 /* Skipping any full cycles */
599 timeLeft -= totalTime * std::floor(timeLeft / totalTime);
600
Robert Bieber3ecef7d2010-06-29 19:59:33 +0000601 int branch = 0;
602 while(timeLeft > 0)
603 {
604 timeLeft -= times[branch];
605 if(timeLeft >= 0)
606 branch++;
607 else
608 break;
609 if(branch >= times.count())
610 branch = 0;
611 }
612
613 /* In case we end up on a disabled branch, skip ahead. If we find that
614 * all the branches are disabled, don't render anything
615 */
616 int originalBranch = branch;
617 while(times[branch] == 0)
618 {
619 branch++;
620 if(branch == originalBranch)
621 {
622 branch = -1;
623 break;
624 }
625 if(branch >= times.count())
626 branch = 0;
627 }
628
629 /* ...and finally render the selected branch */
630 if(branch >= 0)
Robert Bieber9d6b5d62010-06-29 20:39:45 +0000631 children[branch]->render(info, viewport, true);
Robert Bieber3ecef7d2010-06-29 19:59:33 +0000632 }
Robert Bieberaa13a532010-06-29 05:23:22 +0000633}
Robert Bieber5300c702010-06-26 05:51:07 +0000634
Robert Bieberaa13a532010-06-29 05:23:22 +0000635bool ParseTreeNode::execTag(const RBRenderInfo& info, RBViewport* viewport)
636{
Robert Bieberac9287b2010-06-22 07:55:50 +0000637
Robert Bieberaa13a532010-06-29 05:23:22 +0000638 QString filename;
639 QString id;
Robert Bieber81149792010-06-30 19:35:00 +0000640 int x, y, tiles, tile, maxWidth, maxHeight, width, height;
641 char c, hAlign, vAlign;
Robert Bieberaa13a532010-06-29 05:23:22 +0000642 RBImage* image;
Robert Bieber6dd974a2010-08-13 06:04:32 +0000643 QPixmap temp;
Robert Bieberdfc109a2010-08-13 19:14:54 +0000644 RBFont* fLoad;
Robert Bieberaa13a532010-06-29 05:23:22 +0000645
646 /* Two switch statements to narrow down the tag name */
647 switch(element->tag->name[0])
648 {
649
Robert Bieberd2ed5942010-06-30 07:00:05 +0000650 case 'a':
651 switch(element->tag->name[1])
652 {
653 case 'c':
654 /* %ac */
655 viewport->alignText(RBViewport::Center);
656 return true;
657
658 case 'l':
659 /* %al */
660 viewport->alignText(RBViewport::Left);
661 return true;
662
663 case 'r':
664 /* %ar */
665 viewport->alignText(RBViewport::Right);
666 return true;
Robert Bieber71b561e2010-07-05 19:02:40 +0000667
668 case 'x':
669 /* %ax */
Robert Bieber1ee2cdd2010-08-12 23:05:53 +0000670 info.screen()->RtlMirror();
Robert Bieber71b561e2010-07-05 19:02:40 +0000671 return true;
672
673 case 'L':
674 /* %aL */
675 if(info.device()->data("rtl").toBool())
676 viewport->alignText(RBViewport::Right);
677 else
678 viewport->alignText(RBViewport::Left);
679 return true;
680
681 case 'R':
682 /* %aR */
683 if(info.device()->data("rtl").toBool())
684 viewport->alignText(RBViewport::Left);
685 else
686 viewport->alignText(RBViewport::Right);
687 return true;
Robert Bieberd2ed5942010-06-30 07:00:05 +0000688 }
689
Robert Bieber81149792010-06-30 19:35:00 +0000690 return false;
Robert Bieberd2ed5942010-06-30 07:00:05 +0000691
Robert Bieber97427042010-07-02 00:20:36 +0000692 case 'p':
693 switch(element->tag->name[1])
694 {
695 case 'b':
696 /* %pb */
Robert Bieberc5025c72010-08-05 19:05:36 +0000697 new RBProgressBar(viewport, info, this);
Robert Bieber97427042010-07-02 00:20:36 +0000698 return true;
Robert Bieber64af2b32010-07-12 06:07:50 +0000699
700 case 'v':
701 /* %pv */
702 if(element->params_count > 0)
703 {
Robert Bieberc5025c72010-08-05 19:05:36 +0000704 new RBProgressBar(viewport, info, this, true);
Robert Bieber64af2b32010-07-12 06:07:50 +0000705 return true;
706 }
707 else
708 return false;
Robert Bieber97427042010-07-02 00:20:36 +0000709 }
710
711 return false;
712
Robert Bieber13e97cd2010-07-07 22:25:42 +0000713 case 's':
714 switch(element->tag->name[1])
715 {
716 case '\0':
717 /* %s */
718 viewport->scrollText(info.device()->data("simtime").toDouble());
719 return true;
720 }
721
722 return false;
723
Robert Bieber35150b62010-06-30 21:28:11 +0000724 case 'w':
725 switch(element->tag->name[1])
726 {
727 case 'd':
Robert Bieber8219cfe2010-07-03 21:56:29 +0000728 /* %wd */
Robert Bieber2f68e5b2010-07-03 22:57:42 +0000729 info.screen()->breakSBS();
Robert Bieber35150b62010-06-30 21:28:11 +0000730 return true;
731
732 case 'e':
Robert Bieber8219cfe2010-07-03 21:56:29 +0000733 /* %we */
734 /* Totally extraneous */
Robert Bieber35150b62010-06-30 21:28:11 +0000735 return true;
736
737 case 'i':
Robert Bieber8219cfe2010-07-03 21:56:29 +0000738 /* %wi */
Robert Bieber35150b62010-06-30 21:28:11 +0000739 viewport->enableStatusBar();
740 return true;
741 }
742
743 return false;
744
Robert Bieberaa13a532010-06-29 05:23:22 +0000745 case 'x':
746 switch(element->tag->name[1])
Robert Bieberac9287b2010-06-22 07:55:50 +0000747 {
Robert Bieberaa13a532010-06-29 05:23:22 +0000748 case 'd':
749 /* %xd */
Robert Bieberac9287b2010-06-22 07:55:50 +0000750
Robert Bieber5729be42011-01-22 08:45:59 +0000751 /* Breaking up into cases, getting the id first */
752 if(element->params_count == 1)
Robert Bieberd3027052010-06-23 07:18:22 +0000753 {
Robert Bieber5729be42011-01-22 08:45:59 +0000754 /* The old fashioned style */
755 id = "";
756 id.append(element->params[0].data.text[0]);
Robert Bieberaa13a532010-06-29 05:23:22 +0000757 }
758 else
759 {
Robert Bieber5729be42011-01-22 08:45:59 +0000760 id = QString(element->params[0].data.text);
Robert Bieberd3027052010-06-23 07:18:22 +0000761 }
762
Robert Bieber5729be42011-01-22 08:45:59 +0000763
Robert Bieber3313ab82010-06-29 07:15:41 +0000764 if(info.screen()->getImage(id))
Robert Bieber6d615662010-06-23 20:18:31 +0000765 {
Robert Bieber5729be42011-01-22 08:45:59 +0000766 /* Fetching the image if available */
Robert Bieber3313ab82010-06-29 07:15:41 +0000767 image = new RBImage(*(info.screen()->getImage(id)), viewport);
Robert Bieber5729be42011-01-22 08:45:59 +0000768 }
769 else
770 {
771 image = 0;
772 }
773
774 /* Now determining the particular tile to load */
775 if(element->params_count == 1)
776 {
777 c = element->params[0].data.text[1];
778
779 if(c == '\0')
780 {
781 tile = 1;
782 }
783 else
784 {
785 if(isupper(c))
786 tile = c - 'A' + 25;
787 else
788 tile = c - 'a';
789 }
790
791 }else{
792 /* If the next param is just an int, use it as the tile */
793 if(element->params[1].type == skin_tag_parameter::INTEGER)
794 {
795 tile = element->params[1].data.number - 1;
796 }
797 else
798 {
799 tile = children[1]->evalTag(info, true,
800 image->numTiles()).toInt();
801
802 /* Adding the offset if there is one */
803 if(element->params_count == 3)
804 tile += element->params[2].data.number;
805 if(tile < 0)
806 {
807 /* If there is no image for the current status, then
808 * just refrain from showing anything
809 */
810 delete image;
811 return true;
812 }
813 }
814 }
815
816 if(image)
817 {
Robert Bieberaa13a532010-06-29 05:23:22 +0000818 image->setTile(tile);
819 image->show();
Robert Bieberbfc20972010-08-05 07:28:01 +0000820 image->enableMovement();
Robert Bieber6d615662010-06-23 20:18:31 +0000821 }
Robert Bieber3313ab82010-06-29 07:15:41 +0000822
Robert Bieberaa13a532010-06-29 05:23:22 +0000823 return true;
Robert Bieber6d615662010-06-23 20:18:31 +0000824
Robert Bieberaa13a532010-06-29 05:23:22 +0000825 case 'l':
826 /* %xl */
827 id = element->params[0].data.text;
Robert Bieber6dd974a2010-08-13 06:04:32 +0000828 if(element->params[1].data.text == QString("__list_icons__"))
829 {
830 filename = info.settings()->value("iconset", "");
831 filename.replace(".rockbox",
832 info.settings()->value("themebase"));
833 temp.load(filename);
834 if(!temp.isNull())
835 {
836 tiles = temp.height() / temp.width();
837 }
838 }
839 else
840 {
841 filename = info.settings()->value("imagepath", "") + "/" +
842 element->params[1].data.text;
843 tiles = 1;
844 }
Robert Bieber15488a02010-07-15 06:24:11 +0000845 x = element->params[2].data.number;
846 y = element->params[3].data.number;
Robert Bieberaa13a532010-06-29 05:23:22 +0000847 if(element->params_count > 4)
Robert Bieber15488a02010-07-15 06:24:11 +0000848 tiles = element->params[4].data.number;
Robert Bieber6d615662010-06-23 20:18:31 +0000849
Robert Bieberaa13a532010-06-29 05:23:22 +0000850 info.screen()->loadImage(id, new RBImage(filename, tiles, x, y,
Robert Bieberbfc20972010-08-05 07:28:01 +0000851 this, viewport));
Robert Bieberaa13a532010-06-29 05:23:22 +0000852 return true;
Robert Bieberdeab1bb2010-06-23 19:41:30 +0000853
Robert Bieberaa13a532010-06-29 05:23:22 +0000854 case '\0':
855 /* %x */
856 id = element->params[0].data.text;
857 filename = info.settings()->value("imagepath", "") + "/" +
858 element->params[1].data.text;
Robert Bieber15488a02010-07-15 06:24:11 +0000859 x = element->params[2].data.number;
860 y = element->params[3].data.number;
Robert Bieberbfc20972010-08-05 07:28:01 +0000861 image = new RBImage(filename, 1, x, y, this, viewport);
862 info.screen()->loadImage(id, image);
863 image->show();
864 image->enableMovement();
865
Robert Bieberaa13a532010-06-29 05:23:22 +0000866 return true;
Robert Bieberac9287b2010-06-22 07:55:50 +0000867
868 }
Robert Bieberaa13a532010-06-29 05:23:22 +0000869
Robert Bieber81149792010-06-30 19:35:00 +0000870 return false;
871
872 case 'C':
873 switch(element->tag->name[1])
874 {
875 case 'd':
876 /* %Cd */
877 info.screen()->showAlbumArt(viewport);
878 return true;
879
880 case 'l':
881 /* %Cl */
Robert Bieber15488a02010-07-15 06:24:11 +0000882 x = element->params[0].data.number;
883 y = element->params[1].data.number;
884 maxWidth = element->params[2].data.number;
885 maxHeight = element->params[3].data.number;
Robert Bieber81149792010-06-30 19:35:00 +0000886 hAlign = element->params_count > 4
887 ? element->params[4].data.text[0] : 'c';
888 vAlign = element->params_count > 5
889 ? element->params[5].data.text[0] : 'c';
890 width = info.device()->data("artwidth").toInt();
891 height = info.device()->data("artheight").toInt();
892 info.screen()->setAlbumArt(new RBAlbumArt(viewport, x, y, maxWidth,
893 maxHeight, width, height,
Robert Bieber265ee152010-08-05 08:03:32 +0000894 this, hAlign, vAlign));
Robert Bieber81149792010-06-30 19:35:00 +0000895 return true;
896 }
897
898 return false;
Robert Bieberaa13a532010-06-29 05:23:22 +0000899
900 case 'F':
901
902 switch(element->tag->name[1])
903 {
904
905 case 'l':
906 /* %Fl */
Robert Bieber15488a02010-07-15 06:24:11 +0000907 x = element->params[0].data.number;
Robert Bieberaa13a532010-06-29 05:23:22 +0000908 filename = info.settings()->value("themebase", "") + "/fonts/" +
909 element->params[1].data.text;
Robert Bieberdfc109a2010-08-13 19:14:54 +0000910 fLoad = new RBFont(filename);
911 if(!fLoad->isValid())
912 dynamic_cast<RBScene*>(info.screen()->scene())
913 ->addWarning(QObject::tr("Missing font file: ") + filename);
914 info.screen()->loadFont(x, fLoad);
Robert Bieberaa13a532010-06-29 05:23:22 +0000915 return true;
916
917 }
918
Robert Bieber81149792010-06-30 19:35:00 +0000919 return false;
Robert Bieberaa13a532010-06-29 05:23:22 +0000920
Robert Bieber14238742010-07-10 06:43:50 +0000921 case 'T':
922 switch(element->tag->name[1])
923 {
924 case '\0':
925 /* %T */
926 if(element->params_count < 5)
927 return false;
Robert Bieber15488a02010-07-15 06:24:11 +0000928 int x = element->params[0].data.number;
929 int y = element->params[1].data.number;
930 int width = element->params[2].data.number;
931 int height = element->params[3].data.number;
Robert Bieber14238742010-07-10 06:43:50 +0000932 QString action(element->params[4].data.text);
Robert Bieber5c478722011-03-20 04:20:13 +0000933 RBTouchArea* temp = new RBTouchArea(width, height, action, info,
934 viewport);
Robert Bieber14238742010-07-10 06:43:50 +0000935 temp->setPos(x, y);
936 return true;
937 }
938
939 return false;
940
Robert Bieberaa13a532010-06-29 05:23:22 +0000941 case 'V':
942
943 switch(element->tag->name[1])
944 {
945
946 case 'b':
947 /* %Vb */
948 viewport->setBGColor(RBScreen::
949 stringToColor(QString(element->params[0].
950 data.text),
951 Qt::white));
952 return true;
953
954 case 'd':
955 /* %Vd */
956 id = element->params[0].data.text;
957 info.screen()->showViewport(id);
958 return true;
959
960 case 'f':
961 /* %Vf */
962 viewport->setFGColor(RBScreen::
963 stringToColor(QString(element->params[0].
964 data.text),
965 Qt::black));
966 return true;
967
Robert Bieber26a2f812010-07-01 21:49:55 +0000968 case 'p':
969 /* %Vp */
Robert Bieber15488a02010-07-15 06:24:11 +0000970 viewport->showPlaylist(info, element->params[0].data.number,
Robert Bieberb4131692010-08-15 02:04:06 +0000971 children[1]);
Robert Bieber26a2f812010-07-01 21:49:55 +0000972 return true;
973
Robert Bieberaa13a532010-06-29 05:23:22 +0000974 case 'I':
975 /* %VI */
976 info.screen()->makeCustomUI(element->params[0].data.text);
977 return true;
978
979 }
980
Robert Bieber81149792010-06-30 19:35:00 +0000981 return false;
Robert Bieberaa13a532010-06-29 05:23:22 +0000982
983 case 'X':
984
985 switch(element->tag->name[1])
986 {
987 case '\0':
988 /* %X */
989 filename = QString(element->params[0].data.text);
Robert Bieberd1a392a2010-08-09 19:37:23 +0000990 info.screen()->setBackdrop(filename);
Robert Bieberaa13a532010-06-29 05:23:22 +0000991 return true;
992 }
993
Robert Bieber81149792010-06-30 19:35:00 +0000994 return false;
Robert Bieberaa13a532010-06-29 05:23:22 +0000995
Robert Bieberac9287b2010-06-22 07:55:50 +0000996 }
Robert Bieberaa13a532010-06-29 05:23:22 +0000997
998 return false;
999
1000}
1001
1002QVariant ParseTreeNode::evalTag(const RBRenderInfo& info, bool conditional,
1003 int branches)
1004{
Robert Bieber3313ab82010-06-29 07:15:41 +00001005 if(!conditional)
1006 {
Robert Bieberf4c06f32010-08-12 18:47:05 +00001007 if(element->tag->name[0] == 'c' && !info.device()->data("cc").toBool())
1008 return QString();
1009
Robert Bieberdad98102010-08-03 05:47:59 +00001010 if(QString(element->tag->name) == "Sx")
1011 return element->params[0].data.text;
Robert Bieber6358d412010-07-08 06:54:08 +00001012 return info.device()->data(QString(element->tag->name),
1013 element->params_count, element->params);
Robert Bieber3313ab82010-06-29 07:15:41 +00001014 }
1015 else
1016 {
1017 /* If we're evaluating for a conditional, we return the child branch
1018 * index that should be selected. For true/false values, this is
1019 * 0 for true, 1 for false, and we also have to make sure not to
1020 * ever exceed the number of available children
1021 */
1022
1023 int child;
1024 QVariant val = info.device()->data("?" + QString(element->tag->name));
1025 if(val.isNull())
Robert Bieber6358d412010-07-08 06:54:08 +00001026 val = info.device()->data(QString(element->tag->name),
1027 element->params_count, element->params);
Robert Bieber3313ab82010-06-29 07:15:41 +00001028
1029 if(val.isNull())
1030 {
1031 child = 1;
1032 }
1033 else if(QString(element->tag->name) == "bl")
1034 {
1035 /* bl has to be scaled to the number of available children, but it
1036 * also has an initial -1 value for an unknown state */
1037 child = val.toInt();
1038 if(child == -1)
1039 {
1040 child = 0;
1041 }
1042 else
1043 {
1044 child = ((branches - 1) * child / 100) + 1;
1045 }
1046 }
Robert Bieber64af2b32010-07-12 06:07:50 +00001047 else if(QString(element->tag->name) == "pv")
1048 {
1049 /* ?pv gets scaled to the number of available children, sandwiched
1050 * in between mute and 0/>0dB. I assume a floor of -50dB for the
1051 * time being
1052 */
1053 int dB = val.toInt();
1054
1055 if(dB < -50)
1056 child = 0;
1057 else if(dB == 0)
1058 child = branches - 2;
1059 else if(dB > 0)
1060 child = branches - 1;
1061 else
1062 {
1063 int options = branches - 3;
1064 child = (options * (dB + 50)) / 50;
1065 }
1066 }
Robert Bieber3313ab82010-06-29 07:15:41 +00001067 else if(QString(element->tag->name) == "px")
1068 {
1069 child = val.toInt();
1070 child = branches * child / 100;
1071 }
1072 else if(val.type() == QVariant::Bool)
1073 {
1074 /* Boolean values have to be reversed, because conditionals are
1075 * always of the form %?tag<true|false>
1076 */
1077 if(val.toBool())
1078 child = 0;
1079 else
1080 child = 1;
1081 }
Robert Bieber68756cc2010-07-05 19:12:52 +00001082 else if(element->tag->name[0] == 'i' || element->tag->name[0] == 'I'
1083 || element->tag->name[0] == 'f' || element->tag->name[0] == 'F')
1084 {
1085 if(info.device()->data("id3available").toBool())
1086 child = 0;
1087 else
1088 child = 1;
1089 }
Robert Bieberf055cee2010-08-12 18:40:35 +00001090 else if(val.type() == QVariant::String)
1091 {
1092 if(val.toString().length() > 0)
1093 child = 0;
1094 else
1095 child = 1;
1096 }
Robert Bieber3313ab82010-06-29 07:15:41 +00001097 else
1098 {
1099 child = val.toInt();
1100 }
1101
1102 if(child < 0)
1103 child = 0;
1104
1105 if(child < branches)
1106 return child;
Robert Bieberb22077c2010-07-29 06:41:33 +00001107 else if(branches == 1)
1108 return 2;
Robert Bieber3313ab82010-06-29 07:15:41 +00001109 else
1110 return branches - 1;
1111 }
Robert Bieberac9287b2010-06-22 07:55:50 +00001112}
Robert Bieber3ecef7d2010-06-29 19:59:33 +00001113
1114double ParseTreeNode::findBranchTime(ParseTreeNode *branch,
1115 const RBRenderInfo& info)
1116{
1117 double retval = 2;
1118 for(int i = 0; i < branch->children.count(); i++)
1119 {
1120 ParseTreeNode* current = branch->children[i];
1121 if(current->element->type == TAG)
1122 {
1123 if(current->element->tag->name[0] == 't'
1124 && current->element->tag->name[1] == '\0')
1125 {
Robert Bieber15488a02010-07-15 06:24:11 +00001126 retval = current->element->params[0].data.number / 10.;
Robert Bieber3ecef7d2010-06-29 19:59:33 +00001127 }
1128 }
1129 else if(current->element->type == CONDITIONAL)
1130 {
1131 retval = findConditionalTime(current, info);
1132 }
1133 }
1134 return retval;
1135}
1136
1137double ParseTreeNode::findConditionalTime(ParseTreeNode *conditional,
1138 const RBRenderInfo& info)
1139{
1140 int child = conditional->evalTag(info, true,
1141 conditional->children.count()).toInt();
Robert Bieberf657e492010-08-05 08:49:34 +00001142 if(child >= conditional->children.count())
1143 child = conditional->children.count() - 1;
1144
Robert Bieber3ecef7d2010-06-29 19:59:33 +00001145 return findBranchTime(conditional->children[child], info);
1146}
Robert Bieber49865b22010-08-04 09:16:52 +00001147
1148void ParseTreeNode::modParam(QVariant value, int index)
1149{
1150 if(element)
1151 {
Robert Bieberc5025c72010-08-05 19:05:36 +00001152 if(index < 0)
Robert Bieber49865b22010-08-04 09:16:52 +00001153 return;
Robert Bieberc5025c72010-08-05 19:05:36 +00001154 while(index >= children.count())
1155 {
1156 /* Padding children with defaults until we make the necessary
1157 * parameter available
1158 */
1159 skin_tag_parameter* newParam = new skin_tag_parameter;
1160 newParam->type = skin_tag_parameter::DEFAULT;
1161 /* We'll need to manually delete the extra parameters in the
1162 * destructor
1163 */
1164 extraParams.append(children.count());
1165
1166 children.append(new ParseTreeNode(newParam, this, model));
1167 element->params_count++;
1168 }
1169
Robert Bieber49865b22010-08-04 09:16:52 +00001170 children[index]->modParam(value);
1171 }
1172 else if(param)
1173 {
1174 if(value.type() == QVariant::Double)
1175 {
1176 param->type = skin_tag_parameter::DECIMAL;
1177 param->data.number = static_cast<int>(value.toDouble() * 10);
1178 }
1179 else if(value.type() == QVariant::String)
1180 {
1181 param->type = skin_tag_parameter::STRING;
1182 free(param->data.text);
1183 param->data.text = strdup(value.toString().toStdString().c_str());
1184 }
1185 else if(value.type() == QVariant::Int)
1186 {
1187 param->type = skin_tag_parameter::INTEGER;
1188 param->data.number = value.toInt();
1189 }
1190
Robert Bieber054a85f2010-08-05 00:43:33 +00001191 model->paramChanged(this);
1192
Robert Bieber49865b22010-08-04 09:16:52 +00001193 }
1194}