1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
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 "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()
36 children
.append(new ParseTreeNode(data
, this));
41 /* Normal element constructor */
42 ParseTreeNode::ParseTreeNode(struct skin_element
* data
, ParseTreeNode
* parent
)
43 : parent(parent
), element(data
), param(0), children()
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
,
55 children
.append(new ParseTreeNode(&element
->params
[i
], this));
59 /* CONDITIONAL and SUBLINES fall through to the same code */
62 for(int i
= 0; i
< element
->children_count
; i
++)
64 children
.append(new ParseTreeNode(data
->children
[i
], this));
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));
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
102 if(children
[0]->element
->type
== TAG
)
103 buffer
.append(TAGSYM
);
104 buffer
.append(children
[0]->genCode());
105 if(children
[0]->element
->type
== TAG
)
107 for(int i
= 1; i
< children
.count(); i
++)
108 buffer
.append(children
[i
]->genCode());
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)
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
);
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
);
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
);
176 for(char* cursor
= element
->text
; *cursor
; cursor
++)
178 if(find_escape_character(*cursor
))
179 buffer
.append(TAGSYM
);
180 buffer
.append(*cursor
);
185 buffer
.append(COMMENTSYM
);
186 buffer
.append(element
->text
);
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
);
204 case skin_tag_parameter::NUMERIC
:
205 buffer
.append(QString::number(param
->data
.numeric
, 10));
208 case skin_tag_parameter::DEFAULT
:
209 buffer
.append(DEFAULTSYM
);
212 case skin_tag_parameter::CODE
:
213 buffer
.append(QObject::tr("This doesn't belong here"));
220 for(int i
= 0; i
< children
.count(); i
++)
221 buffer
.append(children
[i
]->genCode());
227 /* A more or less random hashing algorithm */
228 int ParseTreeNode::genHash() const
234 hash
+= element
->type
;
235 switch(element
->type
)
241 hash
+= element
->children_count
;
245 for(unsigned int i
= 0; i
< strlen(element
->tag
->name
); i
++)
246 hash
+= element
->tag
->name
[i
];
251 for(unsigned int i
= 0; i
< strlen(element
->text
); i
++)
254 hash
+= element
->text
[i
] % element
->type
;
256 hash
+= element
->text
[i
] % element
->type
* 2;
268 case skin_tag_parameter::DEFAULT
:
269 case skin_tag_parameter::CODE
:
272 case skin_tag_parameter::NUMERIC
:
273 hash
+= param
->data
.numeric
* (param
->data
.numeric
/ 4);
276 case skin_tag_parameter::STRING
:
277 for(unsigned int i
= 0; i
< strlen(param
->data
.text
); i
++)
280 hash
+= param
->data
.text
[i
] * 2;
282 hash
+= param
->data
.text
[i
];
288 for(int i
= 0; i
< children
.count(); i
++)
290 hash
+= children
[i
]->genHash();
296 ParseTreeNode
* ParseTreeNode::child(int row
)
298 if(row
< 0 || row
>= children
.count())
301 return children
[row
];
304 int ParseTreeNode::numChildren() const
306 return children
.count();
310 QVariant
ParseTreeNode::data(int column
) const
314 case ParseTreeModel::typeColumn
:
317 switch(element
->type
)
320 return QObject::tr("Viewport");
323 return QObject::tr("Logical Line");
326 return QObject::tr("Alternator");
329 return QObject::tr("Comment");
332 return QObject::tr("Conditional Tag");
335 return QObject::tr("Tag");
338 return QObject::tr("Plaintext");
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");
360 return QObject::tr("Root");
365 case ParseTreeModel::valueColumn
:
368 switch(element
->type
)
378 return QString(element
->text
);
381 return QString(element
->tag
->name
);
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");
407 case ParseTreeModel::lineColumn
:
409 return QString::number(element
->line
, 10);
419 int ParseTreeNode::getRow() const
424 return parent
->children
.indexOf(const_cast<ParseTreeNode
*>(this));
427 ParseTreeNode
* ParseTreeNode::getParent() const
432 ParseTreeNode::~ParseTreeNode()
434 for(int i
= 0; i
< children
.count(); i
++)