1
0
Fork 0
forked from len0rd/rockbox

Theme Editor: Added code generate/undo functionality to SkinViewer

git-svn-id: svn://svn.rockbox.org/rockbox/trunk@27704 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
Robert Bieber 2010-08-05 00:43:33 +00:00
parent 4674518787
commit 054a85fdca
15 changed files with 154 additions and 39 deletions

View file

@ -311,8 +311,6 @@ void RBViewport::saveGeometry()
node->modParam(static_cast<int>(origin.y()), baseParam + 1); node->modParam(static_cast<int>(origin.y()), baseParam + 1);
node->modParam(static_cast<int>(bounds.width()), baseParam + 2); node->modParam(static_cast<int>(bounds.width()), baseParam + 2);
node->modParam(static_cast<int>(bounds.height()), baseParam + 3); node->modParam(static_cast<int>(bounds.height()), baseParam + 3);
doc->genCode();
} }
void RBViewport::alignLeft() void RBViewport::alignLeft()

View file

@ -428,7 +428,7 @@ void EditorWindow::shiftTab(int index)
ui->actionCopy->setEnabled(false); ui->actionCopy->setEnabled(false);
ui->actionPaste->setEnabled(false); ui->actionPaste->setEnabled(false);
ui->actionFind_Replace->setEnabled(false); ui->actionFind_Replace->setEnabled(false);
viewer->setScene(0); viewer->connectSkin(0);
} }
else if(widget->type() == TabContent::Config) else if(widget->type() == TabContent::Config)
{ {
@ -441,7 +441,7 @@ void EditorWindow::shiftTab(int index)
ui->actionCopy->setEnabled(false); ui->actionCopy->setEnabled(false);
ui->actionPaste->setEnabled(false); ui->actionPaste->setEnabled(false);
ui->actionFind_Replace->setEnabled(false); ui->actionFind_Replace->setEnabled(false);
viewer->setScene(0); viewer->connectSkin(0);
} }
else if(widget->type() == TabContent::Skin) else if(widget->type() == TabContent::Skin)
{ {
@ -465,7 +465,8 @@ void EditorWindow::shiftTab(int index)
sizeColumns(); sizeColumns();
/* Syncing the preview */ /* Syncing the preview */
viewer->setScene(doc->scene()); viewer->connectSkin(doc);
} }
@ -513,7 +514,7 @@ void EditorWindow::closeProject()
dynamic_cast<SkinDocument*>(doc)->setProject(project); dynamic_cast<SkinDocument*>(doc)->setProject(project);
if(i == ui->editorTabs->currentIndex()) if(i == ui->editorTabs->currentIndex())
{ {
viewer->setScene(dynamic_cast<SkinDocument*>(doc)->scene()); viewer->connectSkin(dynamic_cast<SkinDocument*>(doc));
} }
} }
} }
@ -630,7 +631,7 @@ void EditorWindow::configFileChanged(QString configFile)
dynamic_cast<SkinDocument*>(doc)->setProject(project); dynamic_cast<SkinDocument*>(doc)->setProject(project);
if(i == ui->editorTabs->currentIndex()) if(i == ui->editorTabs->currentIndex())
{ {
viewer->setScene(dynamic_cast<SkinDocument*>(doc)->scene()); viewer->connectSkin(dynamic_cast<SkinDocument*>(doc));
} }
} }
} }
@ -858,7 +859,7 @@ void EditorWindow::loadProjectFile(QString fileName)
dynamic_cast<SkinDocument*>(doc)->setProject(project); dynamic_cast<SkinDocument*>(doc)->setProject(project);
if(i == ui->editorTabs->currentIndex()) if(i == ui->editorTabs->currentIndex())
{ {
viewer->setScene(dynamic_cast<SkinDocument*>(doc)->scene()); viewer->connectSkin(dynamic_cast<SkinDocument*>(doc));
} }
} }
} }

View file

@ -36,7 +36,8 @@ const int SkinDocument::updateInterval = 500;
SkinDocument::SkinDocument(QLabel* statusLabel, ProjectModel* project, SkinDocument::SkinDocument(QLabel* statusLabel, ProjectModel* project,
DeviceState* device, QWidget *parent) DeviceState* device, QWidget *parent)
:TabContent(parent), statusLabel(statusLabel), :TabContent(parent), statusLabel(statusLabel),
project(project), device(device) project(project), device(device),
treeInSync(true)
{ {
setupUI(); setupUI();
@ -53,7 +54,7 @@ SkinDocument::SkinDocument(QLabel* statusLabel, QString file,
QWidget *parent) QWidget *parent)
:TabContent(parent), fileName(file), :TabContent(parent), fileName(file),
statusLabel(statusLabel), project(project), statusLabel(statusLabel), project(project),
device(device) device(device), treeInSync(true)
{ {
setupUI(); setupUI();
blockUpdate = false; blockUpdate = false;
@ -163,6 +164,9 @@ void SkinDocument::setupUI()
/* Setting up the model */ /* Setting up the model */
model = new ParseTreeModel(""); model = new ParseTreeModel("");
QObject::connect(model, SIGNAL(dataChanged(QModelIndex,QModelIndex)),
this, SLOT(modelChanged()));
/* Connecting the editor's signal */ /* Connecting the editor's signal */
QObject::connect(editor, SIGNAL(textChanged()), QObject::connect(editor, SIGNAL(textChanged()),
this, SLOT(codeChanged())); this, SLOT(codeChanged()));
@ -260,6 +264,10 @@ void SkinDocument::codeChanged()
editor->clearErrors(); editor->clearErrors();
parseStatus = model->changeTree(editor->document()-> parseStatus = model->changeTree(editor->document()->
toPlainText().toAscii()); toPlainText().toAscii());
treeInSync = true;
emit antiSync(false);
if(skin_error_line() > 0) if(skin_error_line() > 0)
parseStatus = tr("Errors in document"); parseStatus = tr("Errors in document");
statusLabel->setText(parseStatus); statusLabel->setText(parseStatus);
@ -313,6 +321,12 @@ void SkinDocument::codeChanged()
} }
void SkinDocument::modelChanged()
{
treeInSync = false;
emit antiSync(true);
}
void SkinDocument::save() void SkinDocument::save()
{ {
QFile fout(fileName); QFile fout(fileName);

View file

@ -66,7 +66,6 @@ public:
QString title() const{ return titleText; } QString title() const{ return titleText; }
QString getStatus(){ return parseStatus; } QString getStatus(){ return parseStatus; }
CodeEditor* getEditor(){ return editor; } CodeEditor* getEditor(){ return editor; }
void genCode(){ editor->document()->setPlainText(model->genCode()); }
void setProject(ProjectModel* project){ this->project = project; } void setProject(ProjectModel* project){ this->project = project; }
void save(); void save();
@ -84,14 +83,21 @@ public:
void showFind(){ findReplace->show(); } void showFind(){ findReplace->show(); }
void hideFind(){ findReplace->hide(); } void hideFind(){ findReplace->hide(); }
bool isSynced(){ return treeInSync; }
signals: signals:
void antiSync(bool outOfSync);
public slots: public slots:
void settingsChanged(); void settingsChanged();
void cursorChanged(); void cursorChanged();
void parseCode(){ codeChanged(); }
void genCode(){ editor->document()->setPlainText(model->genCode()); }
private slots: private slots:
void codeChanged(); void codeChanged();
void modelChanged();
void deviceChanged(){ scene(); } void deviceChanged(){ scene(); }
private: private:
@ -122,6 +128,8 @@ private:
QTime lastUpdate; QTime lastUpdate;
static const int updateInterval; static const int updateInterval;
QTimer checkUpdate; QTimer checkUpdate;
bool treeInSync;
}; };
#endif // SKINDOCUMENT_H #endif // SKINDOCUMENT_H

View file

@ -54,9 +54,38 @@ void SkinViewer::changeEvent(QEvent *e)
} }
} }
void SkinViewer::setScene(QGraphicsScene *scene) void SkinViewer::connectSkin(SkinDocument *skin)
{ {
ui->viewer->setScene(scene); if(skin)
{
ui->viewer->setScene(skin->scene());
QObject::connect(skin, SIGNAL(antiSync(bool)),
ui->codeGenButton, SLOT(setEnabled(bool)));
QObject::connect(skin, SIGNAL(antiSync(bool)),
ui->codeUndoButton, SLOT(setEnabled(bool)));
QObject::connect(ui->codeGenButton, SIGNAL(pressed()),
skin, SLOT(genCode()));
QObject::connect(ui->codeUndoButton, SIGNAL(pressed()),
skin, SLOT(parseCode()));
doc = skin;
}
else
{
ui->viewer->setScene(0);
doc = 0;
}
bool antiSync;
if(skin && !skin->isSynced())
antiSync = true;
else
antiSync = false;
ui->codeGenButton->setEnabled(antiSync);
ui->codeUndoButton->setEnabled(antiSync);
} }
void SkinViewer::zoomIn() void SkinViewer::zoomIn()

View file

@ -25,6 +25,8 @@
#include <QWidget> #include <QWidget>
#include <QGraphicsScene> #include <QGraphicsScene>
#include "skindocument.h"
namespace Ui { namespace Ui {
class SkinViewer; class SkinViewer;
} }
@ -35,18 +37,22 @@ public:
SkinViewer(QWidget *parent = 0); SkinViewer(QWidget *parent = 0);
~SkinViewer(); ~SkinViewer();
void setScene(QGraphicsScene* scene); void connectSkin(SkinDocument* skin);
public slots: public slots:
void zoomIn(); void zoomIn();
void zoomOut(); void zoomOut();
void zoomEven(); void zoomEven();
private slots:
protected: protected:
void changeEvent(QEvent *e); void changeEvent(QEvent *e);
private: private:
Ui::SkinViewer *ui; Ui::SkinViewer *ui;
SkinDocument* doc;
}; };
#endif // SKINVIEWER_H #endif // SKINVIEWER_H

View file

@ -26,6 +26,34 @@
</item> </item>
<item> <item>
<layout class="QHBoxLayout" name="horizontalLayout"> <layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QToolButton" name="codeGenButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/resources/resources/applications-system.png</normaloff>:/resources/resources/applications-system.png</iconset>
</property>
</widget>
</item>
<item>
<widget class="QToolButton" name="codeUndoButton">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources.qrc">
<normaloff>:/resources/resources/edit-undo.png</normaloff>:/resources/resources/edit-undo.png</iconset>
</property>
</widget>
</item>
<item> <item>
<spacer name="horizontalSpacer"> <spacer name="horizontalSpacer">
<property name="orientation"> <property name="orientation">

View file

@ -40,7 +40,7 @@ ParseTreeModel::ParseTreeModel(const char* document, QObject* parent):
this->tree = skin_parse(document); this->tree = skin_parse(document);
if(tree) if(tree)
this->root = new ParseTreeNode(tree); this->root = new ParseTreeNode(tree, this);
else else
this->root = 0; this->root = 0;
@ -77,7 +77,7 @@ QString ParseTreeModel::changeTree(const char *document)
return error; return error;
} }
ParseTreeNode* temp = new ParseTreeNode(test); ParseTreeNode* temp = new ParseTreeNode(test, this);
if(root) if(root)
{ {
@ -364,3 +364,17 @@ QGraphicsScene* ParseTreeModel::render(ProjectModel* project,
return scene; return scene;
} }
void ParseTreeModel::paramChanged(ParseTreeNode *param)
{
QModelIndex index = indexFromPointer(param);
emit dataChanged(index, index);
}
QModelIndex ParseTreeModel::indexFromPointer(ParseTreeNode *p)
{
/* Recursively finding an index for an arbitrary pointer within the tree */
if(!p->getParent())
return QModelIndex();
return index(p->getRow(), 0, indexFromPointer(p->getParent()));
}

View file

@ -53,6 +53,8 @@ public:
QString genCode(); QString genCode();
/* Changes the parse tree to a new document */ /* Changes the parse tree to a new document */
QString changeTree(const char* document); QString changeTree(const char* document);
/* Model implementation stuff */
QModelIndex index(int row, int column, const QModelIndex& parent) const; QModelIndex index(int row, int column, const QModelIndex& parent) const;
QModelIndex parent(const QModelIndex &child) const; QModelIndex parent(const QModelIndex &child) const;
int rowCount(const QModelIndex &parent) const; int rowCount(const QModelIndex &parent) const;
@ -74,6 +76,8 @@ public:
return fallback; return fallback;
} }
void paramChanged(ParseTreeNode* param);
QModelIndex indexFromPointer(ParseTreeNode* p);
private: private:
ParseTreeNode* root; ParseTreeNode* root;

View file

@ -36,19 +36,21 @@ int ParseTreeNode::openConditionals = 0;
bool ParseTreeNode::breakFlag = false; bool ParseTreeNode::breakFlag = false;
/* Root element constructor */ /* Root element constructor */
ParseTreeNode::ParseTreeNode(struct skin_element* data) ParseTreeNode::ParseTreeNode(struct skin_element* data, ParseTreeModel* model)
: parent(0), element(0), param(0), children() : parent(0), element(0), param(0), children(), model(model)
{ {
while(data) while(data)
{ {
children.append(new ParseTreeNode(data, this)); children.append(new ParseTreeNode(data, this, model));
data = data->next; data = data->next;
} }
} }
/* Normal element constructor */ /* Normal element constructor */
ParseTreeNode::ParseTreeNode(struct skin_element* data, ParseTreeNode* parent) ParseTreeNode::ParseTreeNode(struct skin_element* data, ParseTreeNode* parent,
: parent(parent), element(data), param(0), children() ParseTreeModel* model)
: parent(parent), element(data), param(0),
children(), model(model)
{ {
switch(element->type) switch(element->type)
{ {
@ -58,29 +60,30 @@ ParseTreeNode::ParseTreeNode(struct skin_element* data, ParseTreeNode* parent)
{ {
if(element->params[i].type == skin_tag_parameter::CODE) if(element->params[i].type == skin_tag_parameter::CODE)
children.append(new ParseTreeNode(element->params[i].data.code, children.append(new ParseTreeNode(element->params[i].data.code,
this)); this, model));
else else
children.append(new ParseTreeNode(&element->params[i], this)); children.append(new ParseTreeNode(&element->params[i], this,
model));
} }
break; break;
case CONDITIONAL: case CONDITIONAL:
for(int i = 0; i < element->params_count; i++) for(int i = 0; i < element->params_count; i++)
children.append(new ParseTreeNode(&data->params[i], this)); children.append(new ParseTreeNode(&data->params[i], this, model));
for(int i = 0; i < element->children_count; i++) for(int i = 0; i < element->children_count; i++)
children.append(new ParseTreeNode(data->children[i], this)); children.append(new ParseTreeNode(data->children[i], this, model));
break; break;
case LINE_ALTERNATOR: case LINE_ALTERNATOR:
for(int i = 0; i < element->children_count; i++) for(int i = 0; i < element->children_count; i++)
{ {
children.append(new ParseTreeNode(data->children[i], this)); children.append(new ParseTreeNode(data->children[i], this, model));
} }
break; break;
case VIEWPORT: case VIEWPORT:
for(int i = 0; i < element->params_count; i++) for(int i = 0; i < element->params_count; i++)
children.append(new ParseTreeNode(&data->params[i], this)); children.append(new ParseTreeNode(&data->params[i], this, model));
/* Deliberate fall-through here */ /* Deliberate fall-through here */
case LINE: case LINE:
@ -89,7 +92,7 @@ case VIEWPORT:
for(struct skin_element* current = data->children[i]; current; for(struct skin_element* current = data->children[i]; current;
current = current->next) current = current->next)
{ {
children.append(new ParseTreeNode(current, this)); children.append(new ParseTreeNode(current, this, model));
} }
} }
break; break;
@ -100,8 +103,10 @@ case VIEWPORT:
} }
/* Parameter constructor */ /* Parameter constructor */
ParseTreeNode::ParseTreeNode(skin_tag_parameter *data, ParseTreeNode *parent) ParseTreeNode::ParseTreeNode(skin_tag_parameter *data, ParseTreeNode *parent,
: parent(parent), element(0), param(data), children() ParseTreeModel *model)
: parent(parent), element(0), param(data),
children(), model(model)
{ {
} }
@ -1085,5 +1090,7 @@ void ParseTreeNode::modParam(QVariant value, int index)
param->data.number = value.toInt(); param->data.number = value.toInt();
} }
model->paramChanged(this);
} }
} }

View file

@ -34,9 +34,11 @@
class ParseTreeNode class ParseTreeNode
{ {
public: public:
ParseTreeNode(struct skin_element* data); ParseTreeNode(struct skin_element* data, ParseTreeModel* model);
ParseTreeNode(struct skin_element* data, ParseTreeNode* parent); ParseTreeNode(struct skin_element* data, ParseTreeNode* parent,
ParseTreeNode(struct skin_tag_parameter* data, ParseTreeNode* parent); ParseTreeModel* model);
ParseTreeNode(struct skin_tag_parameter* data, ParseTreeNode* parent,
ParseTreeModel* model);
virtual ~ParseTreeNode(); virtual ~ParseTreeNode();
QString genCode() const; QString genCode() const;
@ -84,6 +86,8 @@ private:
static bool breakFlag; static bool breakFlag;
QGraphicsItem* rendered; QGraphicsItem* rendered;
ParseTreeModel* model;
}; };
#endif // PARSETREENODE_H #endif // PARSETREENODE_H

View file

@ -23,6 +23,7 @@
<file>resources/edit-cut.png</file> <file>resources/edit-cut.png</file>
<file>resources/edit-paste.png</file> <file>resources/edit-paste.png</file>
<file>resources/edit-find-replace.png</file> <file>resources/edit-find-replace.png</file>
<file>resources/applications-system.png</file>
</qresource> </qresource>
<qresource prefix="/render"> <qresource prefix="/render">
<file alias="scenebg.png">resources/render/scenebg.png</file> <file alias="scenebg.png">resources/render/scenebg.png</file>

View file

@ -1,8 +1,8 @@
The files edit-cut.png, edit-copy.png, edit-paste.png, edit-find-replace.png, The files applications-system.png, edit-cut.png, edit-copy.png, edit-paste.png,
edit-undo.png, edit-redo.png, ffwd.png, rwnd.png, play.png, pause.png, edit-find-replace.png, edit-undo.png, edit-redo.png, ffwd.png, rwnd.png,
document-new.png, document-open.png, document-save-as.png, and document-save.png play.png, pause.png, document-new.png, document-open.png, document-save-as.png,
came from the Tango Desktop Project (http://www.tango.freedesktop.org) and are and document-save.png came from the Tango Desktop Project
in the public domain. (http://www.tango.freedesktop.org) and are in the public domain.
The files zoomin.png, zoomout.png, and zoomeven.png came from the Tango Project The files zoomin.png, zoomout.png, and zoomeven.png came from the Tango Project
with modifications by Robert Bieber, also in the public domain. with modifications by Robert Bieber, also in the public domain.

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -182,7 +182,8 @@ OTHER_FILES += README \
resources/edit-paste.png \ resources/edit-paste.png \
resources/edit-cut.png \ resources/edit-cut.png \
resources/edit-copy.png \ resources/edit-copy.png \
resources/edit-find-replace.png resources/edit-find-replace.png \
resources/applications-system.png
FORMS += gui/editorwindow.ui \ FORMS += gui/editorwindow.ui \
gui/preferencesdialog.ui \ gui/preferencesdialog.ui \
gui/configdocument.ui \ gui/configdocument.ui \