current work on generic guided editor

This commit is contained in:
Marcel Otte 2016-08-04 07:29:54 +02:00
parent 89cdcb7240
commit 9971c86d09
23 changed files with 468 additions and 315 deletions

View File

@ -1,17 +1,21 @@
set(HEADERS abstractguidededitormodel.h set(HEADERS editormodel.h
guidededitorelement.h editorelementdata.h
guidededitorelementview.h guidededitorelementview.h
guidededitorgroup.h guidededitorgroupview.h
editorgroup.h
flowlayout.h flowlayout.h
editortreenode.h
) )
set(SOURCES guidededitorelementview.cpp set(SOURCES guidededitorelementview.cpp
guidededitorelement.cpp guidededitorgroupview.cpp
abstractguidededitormodel.cpp editorelementdata.cpp
guidededitorgroup.cpp editormodel.cpp
editorgroup.cpp
guidededitorview.cpp guidededitorview.cpp
flowlayout.cpp flowlayout.cpp
editortreenode.cpp
) )
add_library(editor ${HEADERS} ${SOURCES}) add_library(editor ${HEADERS} ${SOURCES})

View File

@ -1,7 +0,0 @@
#include "abstractguidededitormodel.h"
AbstractGuidedEditorModel::AbstractGuidedEditorModel(QObject *parent) : QObject(parent)
{
}

View File

@ -0,0 +1,15 @@
#include "editorelementdata.h"
#include <QString>
EditorElementData::EditorElementData()
{
}
EditorElementData::~EditorElementData()
{
}

View File

@ -0,0 +1,22 @@
#ifndef EDITORELEMENT_H
#define EDITORELEMENT_H
#include <QObject>
#include <QString>
class EditorElementData : public QObject
{
Q_OBJECT
public:
explicit EditorElementData();
~EditorElementData();
private:
QMap<QString, QString> elements;
};
#endif // EDITORELEMENT_H

View File

@ -0,0 +1,8 @@
#include "editorgroup.h"
#include "cstdlib"
#include <QColor>
EditorGroup::EditorGroup(QObject *parent) : QObject(parent)
{
}

27
src/editor/editorgroup.h Normal file
View File

@ -0,0 +1,27 @@
#ifndef GUIDEDEDITORLAYER_H
#define GUIDEDEDITORLAYER_H
#include <QObject>
#include <QString>
#include <QColor>
#include "editorelementdata.h"
class EditorGroup : public QObject
{
Q_OBJECT
public:
explicit EditorGroup(QObject *parent = 0);
private:
QMap<QString, QString> attributes;
QList<EditorElementData*> elements;
signals:
public slots:
};
#endif // GUIDEDEDITORLAYER_H

View File

@ -0,0 +1,7 @@
#include "abstractguidededitormodel.h"
EditorModel::EditorModel(QObject *parent) : QObject(parent)
{
}

View File

@ -5,26 +5,31 @@
#include <QObject> #include <QObject>
#include <memory> #include <memory>
#include <list> #include <list>
#include "guidededitorelement.h" #include "editorelementdata.h"
#include "editorgroup.h"
class AbstractGuidedEditorModel : public QObject class EditorModel : public QObject
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit AbstractGuidedEditorModel(QObject *parent = 0); explicit EditorModel(QObject *parent = 0);
virtual ~AbstractGuidedEditorModel(); virtual ~EditorModel();
virtual uint getCount()=0; virtual uint getCount()=0;
virtual GuidedEditorElement& getElement(uint index) = 0; virtual EditorElementData& getElement(uint index) = 0;
virtual void setElementValue(const uint index, const QString value)= 0; virtual void setElementValue(const uint index, const QString value)= 0;
virtual const std::list<GuidedEditorElement>& getAllElements() = 0; virtual const std::list<EditorElementData>& getAllElements() = 0;
signals: signals:
void dataChanged(); void dataChanged();
void dataChanged(uint index); void dataChanged(uint index);
public slots: public slots:
private:
QList<EditorElementData*> data;
QList<EditorGroup*> groups;
}; };
#endif // ABSTRACTGUIDEDEDITORMODEL_H #endif // ABSTRACTGUIDEDEDITORMODEL_H

View File

@ -0,0 +1,149 @@
#include "editortreenode.h"
EditorTreeNode::EditorTreeNode() {}
EditorTreeNode::EditorTreeNode(T v)
: value(v)
{
}
EditorTreeNode::~EditorTreeNode()
{
if (parent != nullptr) {
remove();
}
}
const EditorTreeNode<T>* EditorTreeNode::nextSibling()
{
if (parent() != nullptr) {
uint i = parent()->children().indexOf(this);
if (i + 1 < parent->children().size())
return parent->children().at(i + 1); //next sibling...
else
return nullptr;
}
return nullptr;
}
const EditorTreeNode<T>* EditorTreeNode::next(TreeWalkStrategy walkStrategy)
{
if (walkStrategy == TreeWalkStrategy::mixture)
// choose node, work through all siblings, choose next node, but don't change branches more than one parent away, except branch is at an end.
if (parent() != nullptr) {
if (nextSibling() != null) // next sibling
return nextSibling();
else // find next children
{
for (auto n : parent->children())
if (n->children().size() > 0)
return n->children().first();
auto siblingOfParent = parent->nextSibling();
while (siblingOfParent != nullptr && siblingOfParent->children().size() == 0) {
if (siblingOfParent->nextSibling() == nullptr)
siblingOfParent = siblingOfParent->parent();
else
siblingOfParent = siblingOfParent->nextSibling();
}
if (siblingOfParent != nullptr)
return siblingOfParent->children().first();
else
return nullptr;
}
} else {
if (children.size() > 0)
return children.first();
else
return nullptr;
}
else if (walkStrategy == TreeWalkStrategy::depthFirst)
if (children().size() > 0)
return children.first();
else {
auto node = this;
while (node->nextSibling() == nullptr && node->parent() != nullptr)
node = node->parent();
return node->nextSibling();
}
else if (walkStrategy == TreeWalkStrategy::breadthFirst)
if (parent != nullptr) {
auto nextOnLvl = nextOnSameLevel();
if (nextOnLvl == nullptr){
for (auto n : this->children)
if (n->children().size() > 0)
return n->children().first();
}
else return nextOnLvl;
}
return nullptr;
}
const EditorTreeNode<T>* EditorTreeNode::getRoot()
{
auto node = this;
while (node->parent() != nullptr)
node = node->parent();
return node;
}
void EditorTreeNode::move(EditorTreeNode<T>* to)
{
this->parent()->children().removeOne(this);
to->children().append(this);
}
void EditorTreeNode::moveChildren(EditorTreeNode<T>* to)
{
for (auto child : children)
child->move(to);
}
void EditorTreeNode::addChild(EditorTreeNode<T>* child)
{
this->children().append(child);
child->setParen(this);
}
bool EditorTreeNode::removeChild(EditorTreeNode<T>* child)
{
this->children().removeOne(child);
}
bool EditorTreeNode::remove()
{
if (parent != nullptr) {
parent->children().removeOne(this);
}
if (children.size() > 0) {
for (auto node : children) {
node->remove();
}
}
}
EditorTreeNode<T>* EditorTreeNode::nextOnSameLevel()
{
if (nextSibling() != nullptr)
return nextSibling();
uint lvl = 1;
auto node = this->parent();
auto pnode = this;
while (lvl > 0 && node != nullptr) {
if (node != pnode->parent() && node->children() > 0) {
node = node->children().first();
--lvl;
} else {
pnode = node;
if (node->nextSibling() != nullptr)
node = node->nextSibling();
else {
if (node->parent() != nullptr) {
node = node->parent();
++lvl;
}
}
}
}
return node;
}

View File

@ -0,0 +1,49 @@
#ifndef EDITORTREENODE_H
#define EDITORTREENODE_H
#include <QList>
enum class TreeWalkStrategy {
depthFirst,
breadthFirst,
mixture
};
template <T>
class EditorTreeNode;
template <T>
class EditorTreeNode {
public:
explicit EditorTreeNode();
explicit EditorTreeNode(T v);
~EditorTreeNode();
const EditorTreeNode<T>* nextSibling();
const EditorTreeNode<T>* parent() { return parent; }
QList<EditorTreeNode<T>*>& children() { return children; }
void setParen(EditorTreeNode<T>* parent) { this->parent = parent; }
T value() { return value; }
const EditorTreeNode<T>* next(TreeWalkStrategy depth_first = TreeWalkStrategy::depthFirst);
const EditorTreeNode<T>* getRoot();
void move(EditorTreeNode<T>* to); // as child!
void moveChildren(EditorTreeNode<T>* to); // move all children
signals:
void nodeDataChanged(EditorTreeNode<T>* node);
void treeChanged(EditorTreeNode<T>* node);
public slots:
void addChild(EditorTreeNode<T>* child);
bool removeChild(EditorTreeNode<T>* child);
bool remove();
private:
T value;
EditorTreeNode<T>* parent = nullptr;
QList<EditorTreeNode<T>*> children;
EditorTreeNode<T>* nextOnSameLevel();
};
#endif // EDITORTREENODE_H

View File

@ -1,85 +0,0 @@
#include "guidededitorelement.h"
#include <QString>
GuidedEditorElement::GuidedEditorElement()
{
}
GuidedEditorElement::~GuidedEditorElement()
{
}
QString GuidedEditorElement::getTitle() const
{
return title;
}
void GuidedEditorElement::setTitle(const QString &value)
{
title = value;
}
QString GuidedEditorElement::getDescription() const
{
return description;
}
void GuidedEditorElement::setDescription(const QString &value)
{
description = value;
}
QString GuidedEditorElement::getExample() const
{
return example;
}
void GuidedEditorElement::setExample(const QString &value)
{
example = value;
}
QString GuidedEditorElement::getSyntaxregex() const
{
return syntaxregex;
}
void GuidedEditorElement::setSyntaxregex(const QString &value)
{
syntaxregex = value;
}
ElementType GuidedEditorElement::getType() const
{
return type;
}
void GuidedEditorElement::setType(const ElementType &value)
{
type = value;
}
QString GuidedEditorElement::getValue() const
{
return value;
}
void GuidedEditorElement::setValue(const QString &value)
{
this->value = value;
}
GuidedEditorGroup *GuidedEditorElement::getGroup() const
{
return this->group;
}
void GuidedEditorElement::setGroup(GuidedEditorGroup *group)
{
this->group = group;
}

View File

@ -1,52 +0,0 @@
#ifndef EDITORELEMENT_H
#define EDITORELEMENT_H
#include <QObject>
#include <QString>
#include "guidededitorgroup.h"
enum class ElementType {
INPUT, CHOOSER, STATIC
};
class GuidedEditorElement : public QObject
{
Q_OBJECT
public:
explicit GuidedEditorElement();
~GuidedEditorElement();
QString getTitle() const;
void setTitle(const QString &value);
QString getDescription() const;
void setDescription(const QString &value);
QString getExample() const;
void setExample(const QString &value);
QString getSyntaxregex() const;
void setSyntaxregex(const QString &value);
ElementType getType() const;
void setType(const ElementType &value);
QString getValue() const;
void setValue(const QString &value);
GuidedEditorGroup* getGroup() const;
void setGroup(GuidedEditorGroup* group);
private:
QString title;
QString description;
QString example;
QString syntaxregex;
ElementType type;
QString value;
GuidedEditorGroup* group;
};
#endif // EDITORELEMENT_H

View File

@ -1,10 +1,10 @@
#include "guidededitorelementview.h" #include "guidededitorelementview.h"
#include <memory>
#include <QVBoxLayout>
#include <QRegExpValidator>
#include <QRegExp>
#include <QLabel> #include <QLabel>
#include <QRegExp>
#include <QRegExpValidator>
#include <QVBoxLayout>
#include <memory>
#include <iostream> #include <iostream>
@ -12,53 +12,17 @@ GuidedEditorElementView::GuidedEditorElementView(QWidget* parent)
: QWidget(parent) : QWidget(parent)
{ {
this->layout = new QVBoxLayout(this); this->layout = new QVBoxLayout(this);
this->title = new QLabel(this);
this->description = new QString();
this->example = new QLabel(this);
this->setLayout(layout); this->setLayout(layout);
this->layout->addWidget(title);
this->layout->addWidget(example);
} }
void GuidedEditorElementView::setElement(GuidedEditorElement* element) void GuidedEditorElementView::render()
{ {
std::cout<<"adding element " << element <<std::endl; for (QWidget* w : this->propertyViews->values())
if(!element) { this->layout->removeWidget(w);
this->title->setText("testtitle"); for (QString prop : this->propertyOrder) {
this->description = new QString("test description"); this->layout->addWidget(this->propertyViews[prop]);
this->example->setText("test example");
this->input = new QLineEdit(this);
this->layout->addWidget(input);
this->update();
return;
} }
// set title
this->title->setText(element->getTitle());
// put description somewhere
this->description = new QString(element->getDescription());
// set example
this->example->setText(element->getExample());
// set input/static part
switch (element->getType()) {
case ElementType::CHOOSER:
this->combobox = new QComboBox(this);
//TODO: data for the combobox ?!
this->layout->addWidget(combobox);
break;
case ElementType::INPUT:
this->input = new QLineEdit(this);
this->layout->addWidget(input);
this->input->setValidator(new QRegExpValidator(QRegExp(element->getSyntaxregex())));
break;
case ElementType::STATIC:
this->staticLabel = new QLabel(this);
this->layout->addWidget(staticLabel);
this->staticLabel->setText(element->getValue());
break;
}
} }
void GuidedEditorElementView::dataChanged() void GuidedEditorElementView::dataChanged()

View File

@ -1,48 +1,39 @@
#ifndef GUIDEDEDITORELEMENTVIEW_H #ifndef GUIDEDEDITORELEMENTVIEW_H
#define GUIDEDEDITORELEMENTVIEW_H #define GUIDEDEDITORELEMENTVIEW_H
#include <QWidget> #include <QComboBox>
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QList>
#include <QVBoxLayout> #include <QVBoxLayout>
#include <QWidget>
#include <memory> #include <memory>
#include <QComboBox>
#include "guidededitorelement.h" #include "editorelementdata.h"
#include "guidededitorgroup.h" #include "editorgroup.h"
#include "guidededitorgroupview.h"
class GuidedEditorElementView : public QWidget {
class GuidedEditorElementView : public QWidget Q_OBJECT
{
Q_OBJECT
public: public:
explicit GuidedEditorElementView(QWidget *parent = 0); explicit GuidedEditorElementView(QWidget* parent = 0);
void setElement(GuidedEditorElement* element);
void render();
signals: signals:
void inputChanged(); void inputChanged();
public slots: public slots:
void dataChanged(); void dataChanged();
private: private:
// layout // layout
QVBoxLayout* layout; QVBoxLayout* layout;
// widget container QList<QString> propertyOrder;
//? QMap<QString, QWidget*> propertyViews;
// title label GuidedEditorGroupView* groupView;
QLabel* title; EditorGroup* group;
// example/regex label EditorElementData* elementData;
QLabel* example;
// mouseover description?
QString* description;
// input field based on element type
QLineEdit* input;
QComboBox* combobox;
QLabel* staticLabel;
// layer information
GuidedEditorGroup* group;
}; };
#endif // GUIDEDEDITORELEMENTVIEW_H #endif // GUIDEDEDITORELEMENTVIEW_H

View File

@ -1,29 +0,0 @@
#include "guidededitorgroup.h"
#include "cstdlib"
#include <QColor>
GuidedEditorGroup::GuidedEditorGroup(QObject *parent) : QObject(parent)
{
this->color = new QColor(rand()%20*10+50, rand()%20*10+50, rand()%20*10+50);
}
QString GuidedEditorGroup::getTitle() const
{
return title;
}
void GuidedEditorGroup::setTitle(const QString &value)
{
title = value;
}
QColor GuidedEditorGroup::getColor() const
{
return *color;
}
void GuidedEditorGroup::setColor(QColor *value)
{
color = value;
}

View File

@ -1,31 +0,0 @@
#ifndef GUIDEDEDITORLAYER_H
#define GUIDEDEDITORLAYER_H
#include <QObject>
#include <QString>
#include <QColor>
class GuidedEditorGroup : public QObject
{
Q_OBJECT
public:
explicit GuidedEditorGroup(QObject *parent = 0);
GuidedEditorGroup(QString title, QObject *parent = 0);
QString getTitle() const;
void setTitle(const QString &value);
QColor getColor() const;
void setColor(QColor *value);
private:
QString title;
QColor *color;
signals:
public slots:
};
#endif // GUIDEDEDITORLAYER_H

View File

@ -0,0 +1,7 @@
#include "guidededitorgroupview.h"
GuidedEditorGroupView::GuidedEditorGroupView(QObject* parent)
: QObject(parent)
{
this->color = new QColor(rand() % 20 * 10 + 50, rand() % 20 * 10 + 50, rand() % 20 * 10 + 50);
}

View File

@ -0,0 +1,20 @@
#ifndef GUIDEDEDITORGROUPVIEW_H
#define GUIDEDEDITORGROUPVIEW_H
#include <QColor>
#include <QObject>
class GuidedEditorGroupView : public QObject {
Q_OBJECT
public:
explicit GuidedEditorGroupView(QObject* parent = 0);
signals:
public slots:
private:
QColor* color;
QString stylesheet;
};
#endif // GUIDEDEDITORGROUPVIEW_H

View File

@ -2,27 +2,29 @@
#include <iostream> #include <iostream>
#include "guidededitorview.h"
#include "guidededitorelementview.h" #include "guidededitorelementview.h"
#include "guidededitorview.h"
GuidedEditorView::GuidedEditorView(QWidget* parent) : QWidget(parent) { GuidedEditorView::GuidedEditorView(QWidget* parent)
editorLayout = new FlowLayout(this); : QWidget(parent)
this->setLayout(editorLayout); {
// tests editorLayout = new FlowLayout(this);
QString style = QString( this->setLayout(editorLayout);
"QWidget {" // tests
"border-radius: 5px;" QString style = QString(
"background: white }" "QWidget {"
"QLabel {border: 2px dashed black; background: gray; " "border-radius: 5px;"
"border-radius: 5px;}" "background: white }"
"QLineEdit {border: 2px dashed black;background: dark-gray;" "QLabel {border: 2px dashed black; background: gray; "
"border-radius: 5px;}"); "border-radius: 5px;}"
this->setStyleSheet(style); "QLineEdit {border: 2px dashed black;background: dark-gray;"
this->addElement(nullptr); "border-radius: 5px;}");
this->setStyleSheet(style);
this->addElement(nullptr);
} }
GuidedEditorView::GuidedEditorView( GuidedEditorView::GuidedEditorView(
AbstractGuidedEditorModel* model, EditorModel* model,
QWidget* parent) QWidget* parent)
: GuidedEditorView(parent) : GuidedEditorView(parent)
{ {
@ -31,11 +33,10 @@ GuidedEditorView::GuidedEditorView(
GuidedEditorView::~GuidedEditorView() {} GuidedEditorView::~GuidedEditorView() {}
void GuidedEditorView::addElement(GuidedEditorElement* element) void GuidedEditorView::addElement(EditorElementData* element)
{ {
std::cout << "adding elementview from element " << element <<std::endl; std::cout << "adding elementview from element " << element << std::endl;
GuidedEditorElementView* elementView = new GuidedEditorElementView(this); GuidedEditorElementView* elementView = new GuidedEditorElementView(this);
elementView->setElement(element);
this->layout()->addWidget(elementView); this->layout()->addWidget(elementView);
//this->update(); //this->update();
} }

View File

@ -1,28 +1,28 @@
#ifndef GUIDEDEDITOR_H #ifndef GUIDEDEDITOR_H
#define GUIDEDEDITOR_H #define GUIDEDEDITOR_H
#include <memory> #include "editormodel.h"
#include <QWidget> #include "editorelementdata.h"
#include "flowlayout.h" #include "flowlayout.h"
#include "guidededitorelement.h" #include <QWidget>
#include "abstractguidededitormodel.h" #include <memory>
class GuidedEditorView : public QWidget { class GuidedEditorView : public QWidget {
Q_OBJECT Q_OBJECT
public: public:
explicit GuidedEditorView(QWidget* parent = 0); explicit GuidedEditorView(QWidget* parent = 0);
GuidedEditorView(AbstractGuidedEditorModel* model, GuidedEditorView(EditorModel* model,
QWidget* parent = 0); QWidget* parent = 0);
~GuidedEditorView(); ~GuidedEditorView();
signals: signals:
public slots: public slots:
void addElement(GuidedEditorElement* element); void addElement(EditorElementData* element);
private: private:
FlowLayout* editorLayout; FlowLayout* editorLayout;
AbstractGuidedEditorModel* model; EditorModel* model;
}; };
#endif // GUIDEDEDITOR_H #endif // GUIDEDEDITOR_H

49
xml/editorelement.xsd Normal file
View File

@ -0,0 +1,49 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://mmo.to"
xmlns="http://mmo.to"
elementFormDefault="qualified">
<xs:element name="element" type="editorelement" />
<xs:complexType name="editorelement">
<xs:element name="title" type="xs:string"/>
<xs:element name="description" type="xs:string"/>
<xs:element name="syntaxes">
<xs:sequence minOccurs="1">
<xs:element name="syntax" type="syntaxregex" />
</xs:sequence>
</xs:element>
<xs:element name="datatype" >
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="text"/>
<xs:enumeration value="integer"/>
<xs:enumeration value="float"/>
<xs:enumeration value="bytes"/>
<xs:enumeration value="bits"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="endianess">
<xs:simpleType>
<xs:restriction base="xs:string">
<xs:enumeration value="little"/>
<xs:enumeration value="middle"/>
<xs:enumeration value="big"/>
</xs:restriction>
</xs:simpleType>
</xs:element>
<xs:element name="length" type="xs:integer" />
<xs:element name="optional" type="xs:boolean" />
<xs:element name="otherprotocol" type="xs:boolean" minOccurs="0" maxOccurs="1"/>
</xs:complexType>
<xs:complexType name="syntaxregex">
<xs:element name="regex" type="xs:string" />
<xs:element name="example" type="xs:string" />
</xs:complexType>
</xs:schema>

20
xml/editorgroup.xsd Normal file
View File

@ -0,0 +1,20 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://mmo.to"
xmlns="http://mmo.to"
elementFormDefault="qualified">
<xs:include schemaLocation="editorelement.xsd"/>
<xs:element name="group" type="groupType" />
<xs:complexType name="groupType">
<xs:element name="title" type="xs:string"/>
<xs:element name="description" type="xs:string"/>
<xs:sequence minOccurs="1">
<xs:element name="element" type="editorelement"/>
<xs:element name="group" type="groupType"/>
</xs:sequence>
<xs:element name="repeatable" type="xs:boolean"/>
</xs:complexType>
</xs:schema>

19
xml/protocol.xsd Normal file
View File

@ -0,0 +1,19 @@
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
targetNamespace="http://mmo.to"
xmlns="http://mmo.to"
elementFormDefault="qualified">
<xs:include schemaLocation="editorgroup.xsd" />
<xs:include schemaLocation="editorelement.xsd" />
<xs:element name="protocol" type="protocolType" />
<xs:complexType name="protocolType">
<xs:element name="title" type="xs:string"/>
<xs:element name="description" type="xs:string"/>
<xs:sequence minOccurs="1">
<xs:element name="group" type="groupType"/>
</xs:sequence>
</xs:complexType>
</xs:schema>