From 21e09af48084f62cd5e2bf72545a9c769dbbde3c Mon Sep 17 00:00:00 2001 From: bieber Date: Sat, 29 May 2010 00:04:04 +0000 Subject: [PATCH] Theme Editor: Got code generation tentatively working along with a solid C++ tree structure for WPS parse trees git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26367 a1c6a512-1295-4272-9138-f99709370657 --- utils/themeeditor/main.cpp | 15 +- utils/themeeditor/parsetreemodel.cpp | 11 +- utils/themeeditor/parsetreemodel.h | 6 +- utils/themeeditor/parsetreenode.cpp | 274 +++++++++++++++++------- utils/themeeditor/{main.cpp => parsetreenode.h} | 50 +++-- utils/themeeditor/skin_parser.c | 26 +-- utils/themeeditor/skin_parser.h | 10 +- 7 files changed, 262 insertions(+), 130 deletions(-) rewrite utils/themeeditor/parsetreenode.cpp (86%) copy utils/themeeditor/{main.cpp => parsetreenode.h} (59%) diff --git a/utils/themeeditor/main.cpp b/utils/themeeditor/main.cpp index 49e870c36..27ce2da23 100644 --- a/utils/themeeditor/main.cpp +++ b/utils/themeeditor/main.cpp @@ -27,6 +27,7 @@ extern "C" #include #include +#include #include #include @@ -36,15 +37,21 @@ extern "C" int main(int argc, char* argv[]) { - char doc[] = "%Vd(U);Hey\n%?bl(test,3,5,2,1)"; + char doc[] = "#Comment\n%Vd(U);Hey\n%?bl(test,3,5,2,1)"; struct skin_element* test = skin_parse(doc); - skin_debug_tree(test); + ParseTreeNode tree(test); + std::cout << "----" << std::endl; + if(std::string(doc) == tree.genCode().toStdString()) + std::cout << "Code in/out matches" << std::endl; + else + std::cout << "Match error" << std::endl; - skin_free_tree(test); + skin_free_tree(test); +/* QApplication app(argc, argv); QTreeView tree; @@ -53,7 +60,7 @@ int main(int argc, char* argv[]) tree.show(); return app.exec(); - +*/ return 0; } diff --git a/utils/themeeditor/parsetreemodel.cpp b/utils/themeeditor/parsetreemodel.cpp index aa5fb5cdb..c99f166c4 100644 --- a/utils/themeeditor/parsetreemodel.cpp +++ b/utils/themeeditor/parsetreemodel.cpp @@ -26,8 +26,8 @@ ParseTreeModel::ParseTreeModel(char* wps, QObject* parent): QAbstractItemModel(parent) { - this->wps = skin_parse(wps); - this->root = new ParseTreeNode(this->wps, 0, true); + this->tree = skin_parse(wps); + this->root = new ParseTreeNode(tree, 0); } @@ -36,6 +36,12 @@ ParseTreeModel::~ParseTreeModel() delete root; } +QString genCode() +{ + return QString(); +} + +/* QModelIndex ParseTreeModel::index(int row, int column, const QModelIndex& parent) const { @@ -98,3 +104,4 @@ QVariant ParseTreeModel::data(const QModelIndex &index, int role) const ParseTreeNode* item = static_cast(index.internalPointer()); return item->data(index.column()); } +*/ diff --git a/utils/themeeditor/parsetreemodel.h b/utils/themeeditor/parsetreemodel.h index 78484eb5f..64365ed03 100644 --- a/utils/themeeditor/parsetreemodel.h +++ b/utils/themeeditor/parsetreemodel.h @@ -43,15 +43,19 @@ public: ParseTreeModel(char* wps, QObject* parent = 0); virtual ~ParseTreeModel(); + QString genCode(); + + /* QModelIndex index(int row, int column, const QModelIndex& parent) const; QModelIndex parent(const QModelIndex &child) const; int rowCount(const QModelIndex &parent) const; int columnCount(const QModelIndex &parent) const; QVariant data(const QModelIndex &index, int role) const; + */ private: ParseTreeNode* root; - struct skin_element* wps; + struct skin_element* tree; }; diff --git a/utils/themeeditor/parsetreenode.cpp b/utils/themeeditor/parsetreenode.cpp dissimilarity index 86% index 77ec897dd..ccfac615b 100644 --- a/utils/themeeditor/parsetreenode.cpp +++ b/utils/themeeditor/parsetreenode.cpp @@ -1,74 +1,200 @@ -#include "parsetreenode.h" - -ParseTreeNode::ParseTreeNode(struct skin_element* data, ParseTreeNode* parent, - bool tree) -{ - - if(tree) - { - while(data) - { - appendChild(new ParseTreeNode(data, this, false)); - data = data->next; - } - parentLink = 0; - } - else - { - element = data; - parentLink = parent; - } - -} - -ParseTreeNode::ParseTreeNode(struct skin_tag_parameter* param, - ParseTreeNode* parent) - :parentLink(parent), element(0), param(param) -{ - -} - - -ParseTreeNode::~ParseTreeNode() -{ - qDeleteAll(children); -} - -void ParseTreeNode::appendChild(ParseTreeNode* child) -{ - children.append(child); -} - -ParseTreeNode* ParseTreeNode::child(int row) -{ - return children[row]; -} - -int ParseTreeNode::childCount() const -{ - return children.count(); -} - -int ParseTreeNode::columnCount() const -{ - return 2; -} - -QVariant ParseTreeNode::data(int column) const -{ - if(column == 0) - return element->type; - else - return element->line; -} -int ParseTreeNode::row() const -{ - if(parentLink) - return parentLink->children.indexOf(const_cast(this)); - return 0; -} - -ParseTreeNode* ParseTreeNode::parent() -{ - return parentLink; -} +/*************************************************************************** + * __________ __ ___. + * Open \______ \ ____ ____ | | _\_ |__ _______ ___ + * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / + * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < + * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ + * \/ \/ \/ \/ \/ + * $Id$ + * + * Copyright (C) 2010 Robert Bieber + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY + * KIND, either express or implied. + * + ****************************************************************************/ + +extern "C" +{ +#include "symbols.h" +} + +#include "parsetreenode.h" + +/* Root element constructor */ +ParseTreeNode::ParseTreeNode(struct skin_element* data) + : parent(0), element(0), param(0), children() +{ + while(data) + { + children.append(new ParseTreeNode(data, this)); + data = data->next; + } +} + +/* Normal element constructor */ +ParseTreeNode::ParseTreeNode(struct skin_element* data, ParseTreeNode* parent) + : parent(parent), element(data), param(0), children() +{ + switch(element->type) + { + + case TAG: + for(int i = 0; i < element->params_count; i++) + { + if(element->params[i].type == skin_tag_parameter::CODE) + children.append(new ParseTreeNode(element->params[i].data.code, + this)); + else + children.append(new ParseTreeNode(&element->params[i], this)); + } + break; + + /* CONDITIONAL and SUBLINES fall through to the same code */ + case CONDITIONAL: + case SUBLINES: + for(int i = 0; i < element->children_count; i++) + { + children.append(new ParseTreeNode(data->children[i], this)); + } + break; + + case LINE: + for(struct skin_element* current = data->children[0]; current; + current = current->next) + { + children.append(new ParseTreeNode(current, this)); + } + break; + + default: + break; + } +} + +/* Parameter constructor */ +ParseTreeNode::ParseTreeNode(skin_tag_parameter *data, ParseTreeNode *parent) + : parent(parent), element(0), param(data), children() +{ + +} + +QString ParseTreeNode::genCode() const +{ + QString buffer = ""; + + if(element) + { + switch(element->type) + { + case LINE: + for(int i = 0; i < children.count(); i++) + { + /* + Adding a % in case of tag, because the tag rendering code + doesn't insert its own + */ + if(children[i]->element->type == TAG) + buffer.append(TAGSYM); + buffer.append(children[i]->genCode()); + } + break; + + case SUBLINES: + for(int i = 0; i < children.count(); i++) + { + buffer.append(children[i]->genCode()); + if(i != children.count() - 1) + buffer.append(MULTILINESYM); + } + break; + + case CONDITIONAL: + /* Inserts a %?, the tag renderer doesn't deal with the TAGSYM */ + buffer.append(TAGSYM); + buffer.append(CONDITIONSYM); + buffer.append(children[0]->genCode()); + + /* Inserting the sublines */ + buffer.append(ENUMLISTOPENSYM); + for(int i = 1; i < children.count(); i++) + { + buffer.append(children[i]->genCode()); + if(i != children.count() - 1) + buffer.append(ENUMLISTSEPERATESYM); + } + buffer.append(ENUMLISTCLOSESYM); + break; + + case TAG: + /* When generating code, we DO NOT insert the leading TAGSYM, leave + * the calling functions to handle that + */ + buffer.append(element->name); + + if(element->params_count > 0) + { + /* Rendering parameters if there are any */ + buffer.append(ARGLISTOPENSYM); + for(int i = 0; i < children.count(); i++) + { + buffer.append(children[i]->genCode()); + if(i != children.count() - 1) + buffer.append(ARGLISTSEPERATESYM); + } + buffer.append(ARGLISTCLOSESYM); + } + break; + + case NEWLINE: + buffer.append('\n'); + break; + + case TEXT: + buffer.append(element->text); + break; + + case COMMENT: + buffer.append(COMMENTSYM); + buffer.append(element->text); + break; + } + } + else if(param) + { + switch(param->type) + { + case skin_tag_parameter::STRING: + buffer.append(param->data.text); + break; + + case skin_tag_parameter::NUMERIC: + buffer.append(QString::number(param->data.numeric, 10)); + break; + + case skin_tag_parameter::DEFAULT: + buffer.append(DEFAULTSYM); + break; + + } + } + else + { + for(int i = 0; i < children.count(); i++) + buffer.append(children[i]->genCode()); + } + + return buffer; +} +/* +ParseTreeNode* child(int row); +int numChildren() const; +QVariant data(int column) const; +int getRow() const; +ParseTreeNode* getParent(); +*/ diff --git a/utils/themeeditor/main.cpp b/utils/themeeditor/parsetreenode.h similarity index 59% copy from utils/themeeditor/main.cpp copy to utils/themeeditor/parsetreenode.h index 49e870c36..4d8c4ebc1 100644 --- a/utils/themeeditor/main.cpp +++ b/utils/themeeditor/parsetreenode.h @@ -19,41 +19,39 @@ * ****************************************************************************/ +#ifndef PARSETREENODE_H +#define PARSETREENODE_H + extern "C" { #include "skin_parser.h" -#include "skin_debug.h" } -#include -#include - -#include -#include - -#include "parsetreemodel.h" +#include +#include +#include -int main(int argc, char* argv[]) +class ParseTreeNode { +public: + ParseTreeNode(struct skin_element* data); + ParseTreeNode(struct skin_element* data, ParseTreeNode* parent); + ParseTreeNode(struct skin_tag_parameter* data, ParseTreeNode* parent); - char doc[] = "%Vd(U);Hey\n%?bl(test,3,5,2,1)"; - - struct skin_element* test = skin_parse(doc); - - skin_debug_tree(test); + QString genCode() const; - skin_free_tree(test); + ParseTreeNode* child(int row); + int numChildren() const; + QVariant data(int column) const; + int getRow() const; + ParseTreeNode* getParent(); +private: + ParseTreeNode* parent; + struct skin_element* element; + struct skin_tag_parameter* param; + QList children; - QApplication app(argc, argv); - - QTreeView tree; - ParseTreeModel model(doc); - tree.setModel(&model); - tree.show(); - - return app.exec(); - - return 0; -} +}; +#endif // PARSETREENODE_H diff --git a/utils/themeeditor/skin_parser.c b/utils/themeeditor/skin_parser.c index a6c5ea41a..2f68cdf1c 100644 --- a/utils/themeeditor/skin_parser.c +++ b/utils/themeeditor/skin_parser.c @@ -103,7 +103,14 @@ struct skin_element* skin_parse(char* document) else to_write = &(last->next); - if(sublines) + if(*cursor == '\n') + { + *to_write = skin_alloc_element(); + skin_parse_newline(*to_write, &cursor); + if(!last) + return NULL; + } + else if(sublines) { *to_write = skin_parse_sublines(&cursor); last = *to_write; @@ -202,23 +209,6 @@ struct skin_element* skin_parse_line_optional(char** document, int conditional) } } - if(*cursor == '\n') - { - /* Allocating memory if necessary */ - if(root) - { - current->next = skin_alloc_element(); - current = current->next; - } - else - { - current = skin_alloc_element(); - root = current; - } - if(!skin_parse_newline(current, &cursor)) - return NULL; - } - /* Moving up the calling function's pointer */ *document = cursor; diff --git a/utils/themeeditor/skin_parser.h b/utils/themeeditor/skin_parser.h index 7de726bbf..7b3ab13ad 100644 --- a/utils/themeeditor/skin_parser.h +++ b/utils/themeeditor/skin_parser.h @@ -36,13 +36,13 @@ extern char skin_parse_tree[]; /* Possible types of element in a WPS file */ enum skin_element_type { - TEXT, + LINE, + SUBLINES, + CONDITIONAL, + TAG, NEWLINE, + TEXT, COMMENT, - TAG, - CONDITIONAL, - SUBLINES, - LINE }; enum skin_errorcode -- 2.11.4.GIT