summaryrefslogtreecommitdiffstats
path: root/utils/themeeditor/models
diff options
context:
space:
mode:
authorRobert Bieber <robby@bieberphoto.com>2010-06-17 05:37:01 +0000
committerRobert Bieber <robby@bieberphoto.com>2010-06-17 05:37:01 +0000
commitca564287ee3f48945d45c7d92be7a83452f53745 (patch)
treed6e502bb604f925240a742b3bac2c813a98c447b /utils/themeeditor/models
parentba07b2055c7eb8f2add96f55cb52b40b9ccb3d63 (diff)
downloadrockbox-ca564287ee3f48945d45c7d92be7a83452f53745.tar.gz
rockbox-ca564287ee3f48945d45c7d92be7a83452f53745.zip
Theme Editor: Moved source files into subdirectories
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26876 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'utils/themeeditor/models')
-rw-r--r--utils/themeeditor/models/parsetreemodel.cpp266
-rw-r--r--utils/themeeditor/models/parsetreemodel.h68
-rw-r--r--utils/themeeditor/models/parsetreenode.cpp474
-rw-r--r--utils/themeeditor/models/parsetreenode.h69
-rw-r--r--utils/themeeditor/models/projectmodel.cpp131
-rw-r--r--utils/themeeditor/models/projectmodel.h60
6 files changed, 1068 insertions, 0 deletions
diff --git a/utils/themeeditor/models/parsetreemodel.cpp b/utils/themeeditor/models/parsetreemodel.cpp
new file mode 100644
index 0000000000..a709ea762f
--- /dev/null
+++ b/utils/themeeditor/models/parsetreemodel.cpp
@@ -0,0 +1,266 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.
+ *
+ ****************************************************************************/
+
+
+#include "parsetreemodel.h"
+#include "symbols.h"
+
+#include <cstdlib>
+
+#include <QObject>
+
+ParseTreeModel::ParseTreeModel(const char* document, QObject* parent):
+ QAbstractItemModel(parent)
+{
+ this->tree = skin_parse(document);
+
+ if(tree)
+ this->root = new ParseTreeNode(tree);
+ else
+ this->root = 0;
+}
+
+
+ParseTreeModel::~ParseTreeModel()
+{
+ if(root)
+ delete root;
+ if(tree)
+ skin_free_tree(tree);
+}
+
+QString ParseTreeModel::genCode()
+{
+ if(root)
+ return root->genCode();
+ else
+ return "";
+}
+
+QString ParseTreeModel::changeTree(const char *document)
+{
+ struct skin_element* test = skin_parse(document);
+
+ if(!test)
+ {
+ QString error = tr("Error on line ") +
+ QString::number(skin_error_line())
+ + tr(": ") + QString(skin_error_message());
+ return error;
+ }
+
+ ParseTreeNode* temp = new ParseTreeNode(test);
+ if(root && temp->genHash() == root->genHash())
+ {
+ delete temp;
+ return tr("Document Parses Successfully");
+ }
+
+ if(root)
+ {
+ emit beginRemoveRows(QModelIndex(), 0, root->numChildren() - 1);
+ delete root;
+ emit endRemoveRows();
+ }
+
+ root = temp;
+
+ emit beginInsertRows(QModelIndex(), 0, temp->numChildren() - 1);
+ emit endInsertRows();
+
+ return tr("Document Parses Successfully");
+
+}
+
+QModelIndex ParseTreeModel::index(int row, int column,
+ const QModelIndex& parent) const
+{
+ if(!hasIndex(row, column, parent))
+ return QModelIndex();
+
+ ParseTreeNode* foundParent;
+
+ if(parent.isValid())
+ foundParent = static_cast<ParseTreeNode*>(parent.internalPointer());
+ else
+ foundParent = root;
+
+ if(row < foundParent->numChildren() && row >= 0)
+ return createIndex(row, column, foundParent->child(row));
+ else
+ return QModelIndex();
+}
+
+QModelIndex ParseTreeModel::parent(const QModelIndex &child) const
+{
+ if(!child.isValid())
+ return QModelIndex();
+
+ ParseTreeNode* foundParent = static_cast<ParseTreeNode*>
+ (child.internalPointer())->getParent();
+
+ if(foundParent == root)
+ return QModelIndex();
+
+ return createIndex(foundParent->getRow(), 0, foundParent);
+}
+
+int ParseTreeModel::rowCount(const QModelIndex &parent) const
+{
+ if(!root)
+ return 0;
+
+ if(!parent.isValid())
+ return root->numChildren();
+
+ if(parent.column() != typeColumn)
+ return 0;
+
+ return static_cast<ParseTreeNode*>(parent.internalPointer())->numChildren();
+}
+
+int ParseTreeModel::columnCount(const QModelIndex &parent) const
+{
+ if(parent.isValid())
+ return numColumns;
+ else
+ return numColumns;
+}
+
+QVariant ParseTreeModel::data(const QModelIndex &index, int role) const
+{
+ if(!index.isValid())
+ return QVariant();
+
+ if(role != Qt::DisplayRole)
+ return QVariant();
+
+ return static_cast<ParseTreeNode*>(index.internalPointer())->
+ data(index.column());
+}
+
+QVariant ParseTreeModel::headerData(int col, Qt::Orientation orientation,
+ int role) const
+{
+ if(orientation != Qt::Horizontal)
+ return QVariant();
+
+ if(col >= numColumns)
+ return QVariant();
+
+ if(role != Qt::DisplayRole)
+ return QVariant();
+
+ switch(col)
+ {
+ case typeColumn:
+ return QObject::tr("Type");
+
+ case lineColumn:
+ return QObject::tr("Line");
+
+ case valueColumn:
+ return QObject::tr("Value");
+ }
+
+ return QVariant();
+}
+
+Qt::ItemFlags ParseTreeModel::flags(const QModelIndex &index) const
+{
+ Qt::ItemFlags retval = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
+
+ ParseTreeNode* element = static_cast<ParseTreeNode*>
+ (index.internalPointer());
+
+ if((element->isParam()
+ || element->getElement()->type == TEXT
+ || element->getElement()->type == COMMENT)
+ && index.column() == valueColumn)
+ {
+ retval |= Qt::ItemIsEditable;
+ }
+
+ return retval;
+}
+
+bool ParseTreeModel::setData(const QModelIndex &index, const QVariant &value,
+ int role)
+{
+ if(role != Qt::EditRole)
+ return false;
+
+ if(index.column() != valueColumn)
+ return false;
+
+ ParseTreeNode* node = static_cast<ParseTreeNode*>
+ (index.internalPointer());
+
+ if(node->isParam())
+ {
+ struct skin_tag_parameter* param = node->getParam();
+
+ /* Now that we've established that we do, in fact, have a parameter,
+ * set it to its new value if an acceptable one has been entered
+ */
+ if(value.toString().trimmed() == QString(QChar(DEFAULTSYM)))
+ {
+ if(islower(param->type_code))
+ param->type = skin_tag_parameter::DEFAULT;
+ else
+ return false;
+ }
+ else if(tolower(param->type_code) == 's'
+ || tolower(param->type_code) == 'f')
+ {
+ if(param->type == skin_tag_parameter::STRING)
+ free(param->data.text);
+
+ param->type = skin_tag_parameter::STRING;
+ param->data.text = strdup(value.toString().trimmed().toAscii());
+ }
+ else if(tolower(param->type_code) == 'i')
+ {
+ if(!value.canConvert(QVariant::Int))
+ return false;
+
+ param->type = skin_tag_parameter::NUMERIC;
+ param->data.numeric = value.toInt();
+ }
+ else
+ {
+ return false;
+ }
+ }
+ else
+ {
+ struct skin_element* element = node->getElement();
+
+ if(element->type != COMMENT && element->type != TEXT)
+ return false;
+
+ free(element->data);
+ element->data = strdup(value.toString().trimmed().toAscii());
+ }
+
+ emit dataChanged(index, index);
+ return true;
+}
diff --git a/utils/themeeditor/models/parsetreemodel.h b/utils/themeeditor/models/parsetreemodel.h
new file mode 100644
index 0000000000..55af549e6c
--- /dev/null
+++ b/utils/themeeditor/models/parsetreemodel.h
@@ -0,0 +1,68 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.
+ *
+ ****************************************************************************/
+
+#include "skin_parser.h"
+#include "skin_debug.h"
+
+#ifndef PARSETREEMODEL_H
+#define PARSETREEMODEL_H
+
+#include <QAbstractItemModel>
+#include <QList>
+
+#include "parsetreenode.h"
+
+class ParseTreeModel : public QAbstractItemModel
+{
+
+ Q_OBJECT
+
+public:
+ /* Constants */
+ static const int numColumns = 3;
+ static const int typeColumn = 0;
+ static const int lineColumn = 1;
+ static const int valueColumn = 2;
+
+ /* Initializes a tree with a skin document in a string */
+ ParseTreeModel(const char* document, QObject* parent = 0);
+ virtual ~ParseTreeModel();
+
+ QString genCode();
+ /* Changes the parse tree to a new document */
+ QString changeTree(const char* document);
+ 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;
+ QVariant headerData(int col, Qt::Orientation orientation, int role) const;
+ Qt::ItemFlags flags(const QModelIndex &index) const;
+ bool setData(const QModelIndex &index, const QVariant &value, int role);
+
+private:
+ ParseTreeNode* root;
+ struct skin_element* tree;
+};
+
+
+
+#endif // PARSETREEMODEL_H
diff --git a/utils/themeeditor/models/parsetreenode.cpp b/utils/themeeditor/models/parsetreenode.cpp
new file mode 100644
index 0000000000..397031aee1
--- /dev/null
+++ b/utils/themeeditor/models/parsetreenode.cpp
@@ -0,0 +1,474 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.
+ *
+ ****************************************************************************/
+
+#include "symbols.h"
+#include "tag_table.h"
+
+#include "parsetreenode.h"
+#include "parsetreemodel.h"
+
+int ParseTreeNode::openConditionals = 0;
+
+/* 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;
+
+ case CONDITIONAL:
+ for(int i = 0; i < element->params_count; i++)
+ children.append(new ParseTreeNode(&data->params[i], this));
+ for(int i = 0; i < element->children_count; i++)
+ children.append(new ParseTreeNode(data->children[i], this));
+ break;
+
+ case SUBLINES:
+ for(int i = 0; i < element->children_count; i++)
+ {
+ children.append(new ParseTreeNode(data->children[i], this));
+ }
+ break;
+
+case VIEWPORT:
+ for(int i = 0; i < element->params_count; i++)
+ children.append(new ParseTreeNode(&data->params[i], this));
+ /* Deliberate fall-through here */
+
+ case LINE:
+ for(int i = 0; i < data->children_count; i++)
+ {
+ for(struct skin_element* current = data->children[i]; 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 UNKNOWN:
+ break;
+ case VIEWPORT:
+ /* Generating the Viewport tag, if necessary */
+ if(element->tag)
+ {
+ buffer.append(TAGSYM);
+ buffer.append(element->tag->name);
+ buffer.append(ARGLISTOPENSYM);
+ for(int i = 0; i < element->params_count; i++)
+ {
+ buffer.append(children[i]->genCode());
+ if(i != element->params_count - 1)
+ buffer.append(ARGLISTSEPERATESYM);
+ }
+ buffer.append(ARGLISTCLOSESYM);
+ buffer.append('\n');
+ }
+
+ for(int i = element->params_count; i < children.count(); i++)
+ buffer.append(children[i]->genCode());
+ break;
+
+ case LINE:
+ for(int i = 0; i < children.count(); i++)
+ {
+ buffer.append(children[i]->genCode());
+ }
+ if(openConditionals == 0
+ && !(parent && parent->element->type == SUBLINES))
+ {
+ buffer.append('\n');
+ }
+ break;
+
+ case SUBLINES:
+ for(int i = 0; i < children.count(); i++)
+ {
+ buffer.append(children[i]->genCode());
+ if(i != children.count() - 1)
+ buffer.append(MULTILINESYM);
+ }
+ if(openConditionals == 0)
+ buffer.append('\n');
+ break;
+
+ case CONDITIONAL:
+ openConditionals++;
+
+ /* Inserting the tag part */
+ buffer.append(TAGSYM);
+ buffer.append(CONDITIONSYM);
+ buffer.append(element->tag->name);
+ if(element->params_count > 0)
+ {
+ buffer.append(ARGLISTOPENSYM);
+ for(int i = 0; i < element->params_count; i++)
+ {
+ buffer.append(children[i]->genCode());
+ if( i != element->params_count - 1)
+ buffer.append(ARGLISTSEPERATESYM);
+ buffer.append(ARGLISTCLOSESYM);
+ }
+ }
+
+ /* Inserting the sublines */
+ buffer.append(ENUMLISTOPENSYM);
+ for(int i = element->params_count; i < children.count(); i++)
+ {
+ buffer.append(children[i]->genCode());
+ if(i != children.count() - 1)
+ buffer.append(ENUMLISTSEPERATESYM);
+ }
+ buffer.append(ENUMLISTCLOSESYM);
+ openConditionals--;
+ break;
+
+ case TAG:
+ buffer.append(TAGSYM);
+ buffer.append(element->tag->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 TEXT:
+ for(char* cursor = (char*)element->data; *cursor; cursor++)
+ {
+ if(find_escape_character(*cursor))
+ buffer.append(TAGSYM);
+ buffer.append(*cursor);
+ }
+ break;
+
+ case COMMENT:
+ buffer.append(COMMENTSYM);
+ buffer.append((char*)element->data);
+ buffer.append('\n');
+ break;
+ }
+ }
+ else if(param)
+ {
+ switch(param->type)
+ {
+ case skin_tag_parameter::STRING:
+ for(char* cursor = param->data.text; *cursor; cursor++)
+ {
+ if(find_escape_character(*cursor))
+ buffer.append(TAGSYM);
+ buffer.append(*cursor);
+ }
+ break;
+
+ case skin_tag_parameter::NUMERIC:
+ buffer.append(QString::number(param->data.numeric, 10));
+ break;
+
+ case skin_tag_parameter::DEFAULT:
+ buffer.append(DEFAULTSYM);
+ break;
+
+ case skin_tag_parameter::CODE:
+ buffer.append(QObject::tr("This doesn't belong here"));
+ break;
+
+ }
+ }
+ else
+ {
+ for(int i = 0; i < children.count(); i++)
+ buffer.append(children[i]->genCode());
+ }
+
+ return buffer;
+}
+
+/* A more or less random hashing algorithm */
+int ParseTreeNode::genHash() const
+{
+ int hash = 0;
+ char *text;
+
+ if(element)
+ {
+ hash += element->type;
+ switch(element->type)
+ {
+ case UNKNOWN:
+ break;
+ case VIEWPORT:
+ case LINE:
+ case SUBLINES:
+ case CONDITIONAL:
+ hash += element->children_count;
+ break;
+
+ case TAG:
+ for(unsigned int i = 0; i < strlen(element->tag->name); i++)
+ hash += element->tag->name[i];
+ break;
+
+ case COMMENT:
+ case TEXT:
+ text = (char*)element->data;
+ for(unsigned int i = 0; i < strlen(text); i++)
+ {
+ if(i % 2)
+ hash += text[i] % element->type;
+ else
+ hash += text[i] % element->type * 2;
+ }
+ break;
+ }
+
+ }
+
+ if(param)
+ {
+ hash += param->type;
+ switch(param->type)
+ {
+ case skin_tag_parameter::DEFAULT:
+ case skin_tag_parameter::CODE:
+ break;
+
+ case skin_tag_parameter::NUMERIC:
+ hash += param->data.numeric * (param->data.numeric / 4);
+ break;
+
+ case skin_tag_parameter::STRING:
+ for(unsigned int i = 0; i < strlen(param->data.text); i++)
+ {
+ if(i % 2)
+ hash += param->data.text[i] * 2;
+ else
+ hash += param->data.text[i];
+ }
+ break;
+ }
+ }
+
+ for(int i = 0; i < children.count(); i++)
+ {
+ hash += children[i]->genHash();
+ }
+
+ return hash;
+}
+
+ParseTreeNode* ParseTreeNode::child(int row)
+{
+ if(row < 0 || row >= children.count())
+ return 0;
+
+ return children[row];
+}
+
+int ParseTreeNode::numChildren() const
+{
+ return children.count();
+}
+
+
+QVariant ParseTreeNode::data(int column) const
+{
+ switch(column)
+ {
+ case ParseTreeModel::typeColumn:
+ if(element)
+ {
+ switch(element->type)
+ {
+ case UNKNOWN:
+ return QObject::tr("Unknown");
+ case VIEWPORT:
+ return QObject::tr("Viewport");
+
+ case LINE:
+ return QObject::tr("Logical Line");
+
+ case SUBLINES:
+ return QObject::tr("Alternator");
+
+ case COMMENT:
+ return QObject::tr("Comment");
+
+ case CONDITIONAL:
+ return QObject::tr("Conditional Tag");
+
+ case TAG:
+ return QObject::tr("Tag");
+
+ case TEXT:
+ return QObject::tr("Plaintext");
+ }
+ }
+ else if(param)
+ {
+ switch(param->type)
+ {
+ case skin_tag_parameter::STRING:
+ return QObject::tr("String");
+
+ case skin_tag_parameter::NUMERIC:
+ return QObject::tr("Number");
+
+ case skin_tag_parameter::DEFAULT:
+ return QObject::tr("Default Argument");
+
+ case skin_tag_parameter::CODE:
+ return QObject::tr("This doesn't belong here");
+ }
+ }
+ else
+ {
+ return QObject::tr("Root");
+ }
+
+ break;
+
+ case ParseTreeModel::valueColumn:
+ if(element)
+ {
+ switch(element->type)
+ {
+ case UNKNOWN:
+ case VIEWPORT:
+ case LINE:
+ case SUBLINES:
+ return QString();
+
+ case CONDITIONAL:
+ return QString(element->tag->name);
+
+ case TEXT:
+ case COMMENT:
+ return QString((char*)element->data);
+
+ case TAG:
+ return QString(element->tag->name);
+ }
+ }
+ else if(param)
+ {
+ switch(param->type)
+ {
+ case skin_tag_parameter::DEFAULT:
+ return QObject::tr("-");
+
+ case skin_tag_parameter::STRING:
+ return QString(param->data.text);
+
+ case skin_tag_parameter::NUMERIC:
+ return QString::number(param->data.numeric, 10);
+
+ case skin_tag_parameter::CODE:
+ return QObject::tr("Seriously, something's wrong here");
+ }
+ }
+ else
+ {
+ return QString();
+ }
+ break;
+
+ case ParseTreeModel::lineColumn:
+ if(element)
+ return QString::number(element->line, 10);
+ else
+ return QString();
+ break;
+ }
+
+ return QVariant();
+}
+
+
+int ParseTreeNode::getRow() const
+{
+ if(!parent)
+ return -1;
+
+ return parent->children.indexOf(const_cast<ParseTreeNode*>(this));
+}
+
+ParseTreeNode* ParseTreeNode::getParent() const
+{
+ return parent;
+}
+
+ParseTreeNode::~ParseTreeNode()
+{
+ for(int i = 0; i < children.count(); i++)
+ delete children[i];
+}
diff --git a/utils/themeeditor/models/parsetreenode.h b/utils/themeeditor/models/parsetreenode.h
new file mode 100644
index 0000000000..7a0807bb0d
--- /dev/null
+++ b/utils/themeeditor/models/parsetreenode.h
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef PARSETREENODE_H
+#define PARSETREENODE_H
+
+#include "skin_parser.h"
+
+#include <QString>
+#include <QVariant>
+#include <QList>
+
+class ParseTreeNode
+{
+public:
+ ParseTreeNode(struct skin_element* data);
+ ParseTreeNode(struct skin_element* data, ParseTreeNode* parent);
+ ParseTreeNode(struct skin_tag_parameter* data, ParseTreeNode* parent);
+ virtual ~ParseTreeNode();
+
+ QString genCode() const;
+ int genHash() const;
+
+ bool isParam() const{ if(param) return true; else return false; }
+ struct skin_tag_parameter* getParam(){ return param;}
+ struct skin_element* getElement(){return element;}
+
+ ParseTreeNode* child(int row);
+ int numChildren() const;
+ QVariant data(int column) const;
+ int getRow() const;
+ ParseTreeNode* getParent() const;
+ ParseTreeNode* getChild(int row) const
+ {
+ if(row < children.count())
+ return children[row];
+ else
+ return 0;
+ }
+
+private:
+ ParseTreeNode* parent;
+ struct skin_element* element;
+ struct skin_tag_parameter* param;
+ QList<ParseTreeNode*> children;
+
+ static int openConditionals;
+
+};
+
+#endif // PARSETREENODE_H
diff --git a/utils/themeeditor/models/projectmodel.cpp b/utils/themeeditor/models/projectmodel.cpp
new file mode 100644
index 0000000000..632e0aa075
--- /dev/null
+++ b/utils/themeeditor/models/projectmodel.cpp
@@ -0,0 +1,131 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.
+ *
+ ****************************************************************************/
+
+
+#include "projectmodel.h"
+#include "editorwindow.h"
+
+#include <QFile>
+#include <QTextStream>
+#include <QMap>
+#include <QDir>
+
+ProjectModel::ProjectModel(QString config, EditorWindow* mainWindow,
+ QObject *parent)
+ : QAbstractListModel(parent),
+ mainWindow(mainWindow)
+{
+ /* Reading the config file */
+ QFile cfg(config);
+ cfg.open(QFile::ReadOnly | QFile::Text);
+ if(!cfg.isReadable())
+ return;
+
+ QTextStream fin(&cfg);
+
+ /* Storing the base directory */
+ QString confDir = config;
+ confDir.chop(confDir.length() - confDir.lastIndexOf('/') - 1);
+ QDir base(confDir);
+ base.cdUp();
+ settings.insert("themebase", base.canonicalPath());
+
+ while(!fin.atEnd())
+ {
+ QString current = fin.readLine();
+ QList<QString> parts = current.split(':');
+
+ /* A valid setting has at least one : */
+ if(parts.count() < 2)
+ continue;
+
+ QString setting;
+ for(int i = 1; i < parts.count(); i++)
+ setting.append(parts[i].trimmed());
+
+ settings.insert(parts[0].trimmed(), setting);
+ }
+
+ cfg.close();
+
+ /* Adding the files, starting with the .cfg */
+ config.replace(base.canonicalPath() + "/", "");
+ files.append(config);
+
+ QList<QString> keys;
+ keys.append("wps");
+ keys.append("rwps");
+ keys.append("sbs");
+ keys.append("rsbs");
+ keys.append("fms");
+ keys.append("rfms");
+
+ for(int i = 0; i < keys.count(); i++)
+ {
+ QString file = settings.value(keys[i], "");
+ if(file != "" && file != "-")
+ {
+ file.replace("/.rockbox/", "");
+ files.append(file);
+ }
+ }
+
+
+}
+
+ProjectModel::~ProjectModel()
+{
+}
+
+int ProjectModel::rowCount(const QModelIndex& parent) const
+{
+ return files.count();
+}
+
+QVariant ProjectModel::data(const QModelIndex &index, int role) const
+{
+ if(!index.isValid())
+ return QVariant();
+
+ if(role != Qt::DisplayRole)
+ return QVariant();
+
+ return files[index.row()];
+}
+
+void ProjectModel::activated(const QModelIndex &index)
+{
+ if(index.row() == 0)
+ {
+ ConfigDocument* doc = new ConfigDocument(settings,
+ settings.value("themebase",
+ "") + "/" +
+ files[index.row()]);
+ QObject::connect(doc, SIGNAL(configFileChanged(QString)),
+ mainWindow, SLOT(configFileChanged(QString)));
+ mainWindow->loadConfigTab(doc);
+ }
+ else
+ {
+ mainWindow->loadTabFromSkinFile(settings.value("themebase", "")
+ + "/" + files[index.row()]);
+ }
+}
diff --git a/utils/themeeditor/models/projectmodel.h b/utils/themeeditor/models/projectmodel.h
new file mode 100644
index 0000000000..6623917420
--- /dev/null
+++ b/utils/themeeditor/models/projectmodel.h
@@ -0,0 +1,60 @@
+/***************************************************************************
+ * __________ __ ___.
+ * 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.
+ *
+ ****************************************************************************/
+
+#ifndef PROJECTMODEL_H
+#define PROJECTMODEL_H
+
+#include <QAbstractListModel>
+#include <QMap>
+
+class EditorWindow;
+
+class ProjectModel : public QAbstractListModel
+{
+Q_OBJECT
+public:
+ static const int numColumns = 2;
+
+ static QString fileFilter()
+ {
+ return QObject::tr("Project Files (*.cfg);;All Files (*.*)");
+ }
+
+ ProjectModel(QString config, EditorWindow* mainWindow, QObject *parent = 0);
+ virtual ~ProjectModel();
+
+ int rowCount(const QModelIndex& parent) const;
+ QVariant data(const QModelIndex &index, int role) const;
+
+ QString getSetting(QString key){ return settings.value(key, ""); }
+
+signals:
+
+public slots:
+ void activated(const QModelIndex& index);
+
+private:
+ EditorWindow* mainWindow;
+ QMap<QString, QString> settings;
+ QList<QString> files;
+};
+
+#endif // PROJECTMODEL_H