diff --git a/Element.cpp b/Element.cpp index 897407a..25cec14 100644 --- a/Element.cpp +++ b/Element.cpp @@ -41,3 +41,89 @@ Element::~Element() { _allocator->free(_id); } + +void Element::read(const QDomElement& obj) +{ + QList attributeNames = _propertiesAttributes(); + + // Fill up properties. + int count = metaObject()->propertyCount(); + for (int i=0; iproperty(i); + + // If property is writable, try to find it and rewrite it. + if (property.isWritable()) + { + // Name of property. + const char* propertyName = property.name(); + + // Always ignore objectName default property. + if (QString(propertyName) == QString("objectName")) + continue; + + // Check in attributes. + else if (attributeNames.contains(propertyName)) + { + if (obj.hasAttribute(propertyName)) + setProperty(propertyName, obj.attribute(propertyName)); + } + + // Check in children. + else + { + // Find element. + QDomElement propertyElem = obj.firstChildElement(propertyName); + if (!propertyElem.isNull()) + { + // Set property. + setProperty(propertyName, propertyElem.text()); + } + } + } + } +} + +void Element::write(QDomElement& obj) +{ + QList attributeNames = _propertiesAttributes(); + + // Write up classname. + obj.setAttribute("className", metaObject()->className()); + + // Fill up properties. + int count = metaObject()->propertyCount(); + for (int i=0; iproperty(i); + + // If property is writable, try to find it and rewrite it. + if (property.isWritable() && property.isReadable()) + { + // Name of property. + const char* propertyName = property.name(); + qDebug() << "Read " << propertyName << " : " << property.read(this) << endl; + QString propertyValue = property.read(this).toString(); + + // Add to attributes. + if (attributeNames.contains(propertyName)) + { + obj.setAttribute(propertyName, propertyValue); + } + + // Add to children. + else + { + QDomElement propertyNode = obj.ownerDocument().createElement(propertyName); + QDomText text = obj.ownerDocument().createTextNode(propertyValue); + propertyNode.appendChild(text); + obj.appendChild(propertyNode); + } + } + } +} + +QList Element::_propertiesAttributes() const +{ + return QList() << "name" << "locked"; +} diff --git a/Element.h b/Element.h index 394a685..5c6aa5f 100644 --- a/Element.h +++ b/Element.h @@ -24,6 +24,9 @@ #include #include +#include +#include + #include "UidAllocator.h" Q_DECLARE_METATYPE(uid) @@ -61,6 +64,12 @@ public: virtual QIcon getIcon() const { return QIcon(); } + virtual void read(const QDomElement& obj); + virtual void write(QDomElement& obj); + +protected: + virtual QList _propertiesAttributes() const; + private: uid _id; QString _name; diff --git a/MainWindow.cpp b/MainWindow.cpp index fe76f3c..c573696 100644 --- a/MainWindow.cpp +++ b/MainWindow.cpp @@ -1901,7 +1901,7 @@ bool MainWindow::saveFile(const QString &fileName) return false; } - ProjectWriter writer(mappingManager); + ProjectWriter writer(this); if (writer.writeFile(&file)) { setCurrentFile(fileName); diff --git a/Paint.h b/Paint.h index 9f829ea..12b31ff 100644 --- a/Paint.h +++ b/Paint.h @@ -37,8 +37,6 @@ #include "Element.h" -Q_DECLARE_METATYPE(GLfloat) - /** * A Paint is a style that can be applied when drawing potentially any shape. * @@ -96,13 +94,19 @@ protected: QColor color; public: - Color(uid id=NULL_UID) : Paint(id) {} + Q_INVOKABLE Color(int id=NULL_UID) : Paint(id) {} Color(const QColor& color_, uid id=NULL_UID) : Paint(id), color(color_) {} QColor getColor() const { return color; } void setColor(const QColor& color_) { color = color_; } virtual QString getType() const { return "color"; } + + virtual QIcon getIcon() const { + QPixmap pixmap(100,100); + pixmap.fill(color); + return QIcon(pixmap); + } }; /** @@ -114,8 +118,8 @@ class Texture : public Paint { Q_OBJECT - Q_PROPERTY(GLfloat x READ getX WRITE setX) - Q_PROPERTY(GLfloat y READ getY WRITE setY) + Q_PROPERTY(float x READ getX WRITE setX) + Q_PROPERTY(float y READ getY WRITE setY) protected: GLuint textureId; @@ -231,6 +235,7 @@ class Media : public Texture protected: QString uri; public: + Q_INVOKABLE Media(int id=NULL_UID) : Texture(id) {} Media(const QString uri_, bool live, double rate, uid id=NULL_UID); virtual ~Media(); const QString getUri() const diff --git a/ProjectReader.cpp b/ProjectReader.cpp index 18809de..4987538 100644 --- a/ProjectReader.cpp +++ b/ProjectReader.cpp @@ -42,9 +42,9 @@ bool ProjectReader::readFile(QIODevice *device) QDomElement root = doc.documentElement(); // The handling of the version number will get fancier as we go. - if (root.tagName() != "project" || root.attribute("version") != "0.1") + if (root.tagName() != "project" || root.attribute("version") != MM::VERSION) { - _xml.raiseError(QObject::tr("The file is not a mapmap version 0.1 file.")); + _xml.raiseError(QObject::tr("The file is not a mapmap version %1 file.").arg(MM::VERSION)); return false; } @@ -64,350 +64,430 @@ QString ProjectReader::errorString() const void ProjectReader::parseProject(const QDomElement& project) { - QDomElement paints = project.firstChildElement("paints"); - QDomElement mappings = project.firstChildElement("mappings"); + // TODO: this is dangerous if we have + MappingManager& manager = _window->getMappingManager(); + manager.clearAll(); + + QDomElement paints = project.firstChildElement(ProjectAttributes::PAINTS); + QDomElement mappings = project.firstChildElement(ProjectAttributes::MAPPINGS); // Parse paints. - QDomNode paint = paints.firstChild(); - while (!paint.isNull()) + QDomNode paintNode = paints.firstChild(); + while (!paintNode.isNull()) { - parsePaint(paint.toElement()); - paint = paint.nextSibling(); + Paint::ptr paint = parsePaint(paintNode.toElement()); + + if (paint.isNull()) + { + qDebug() << "Problem creating paint." << endl; + } + else + { + manager.addPaint(paint); + _window->addPaintItem(paint->getId(), paint->getIcon(), paint->getName()); + } + paintNode = paintNode.nextSibling(); } - // Parse mappings. - QDomNode mapping = mappings.firstChild(); - while (!mapping.isNull()) - { - parseMapping(mapping.toElement()); - mapping = mapping.nextSibling(); - } -} - -void ProjectReader::parsePaint(const QDomElement& paint) -{ - QString paintAttrId = paint.attribute("id", QString::number(NULL_UID)); - QString paintAttrName = paint.attribute("name", ""); - QString paintAttrType = paint.attribute("type", ""); - - if (paintAttrType == "media" || paintAttrType == "image") - { - QString uri = paint.firstChildElement("uri").text(); - QString x = paint.firstChildElement("x").text(); - QString y = paint.firstChildElement("y").text(); - QString rate = paint.firstChildElement("rate").text(); - - uid id = _window->createMediaPaint(paintAttrId.toInt(), uri, x.toFloat(), y.toFloat(), paintAttrType == "image", false, rate.toDouble()); - if (id == NULL_UID) - _xml.raiseError(QObject::tr("Cannot create media with uri %1.").arg(uri)); - } - else if (paintAttrType == "color") - { - QString rgb = paint.firstChildElement("rgb").text(); - QColor color(rgb); - - uid id = _window->createColorPaint(paintAttrId.toInt(), color); - if (id == NULL_UID) - _xml.raiseError(QObject::tr("Cannot create color with RGB hex code %1.").arg(rgb)); - - } - else - _xml.raiseError(QObject::tr("Unsupported paint type: %1.").arg(paintAttrType)); - -} - -void ProjectReader::parseMapping(const QDomElement& mapping) -{ - uid id = NULL_UID; - QString mappingAttrId = mapping.attribute("id", QString::number(NULL_UID)); - QString mappingAttrPaintId = mapping.attribute("paint_id", QString::number(NULL_UID)); - QString mappingAttrType = mapping.attribute("type", ""); - - bool isLocked = (mapping.attribute("locked", QString::number(1)) == "1"); - bool isSolo = (mapping.attribute("solo", QString::number(1)) == "1"); - bool isVisible = (mapping.attribute("visible", QString::number(1)) == "1"); - - // Get destination shape. - QDomElement dst = mapping.firstChildElement("destination"); - QVector dstPoints; - - if (mappingAttrType == "triangle_texture") - { - // Parse destination triangle. - _parseTriangle(dst, dstPoints); - - // Get / parse source shape. - QDomElement src = mapping.firstChildElement("source"); - QVector srcPoints; - _parseTriangle(src, srcPoints); - - id = _window->createTriangleTextureMapping(mappingAttrId.toInt(), mappingAttrPaintId.toInt(), srcPoints, dstPoints); - - if (id == NULL_UID) - _xml.raiseError(QObject::tr("Cannot create triangle texture mapping")); - } - else if (mappingAttrType == "mesh_texture") - { - // Parse destination mesh. - int nColumns; - int nRows; - _parseMesh(dst, dstPoints, nColumns, nRows); - - // Get / parse source shape. - QDomElement src = mapping.firstChildElement("source"); - QVector srcPoints; - _parseMesh(src, srcPoints, nColumns, nRows); - - id = _window->createMeshTextureMapping(mappingAttrId.toInt(), mappingAttrPaintId.toInt(), nColumns, nRows, srcPoints, dstPoints); - - if (id == NULL_UID) - _xml.raiseError(QObject::tr("Cannot create mesh texture mapping")); - - } - else if (mappingAttrType == "ellipse_texture") - { - // Parse destination ellipse. - _parseEllipse(dst, dstPoints); - - // Get / parse source shape. - QDomElement src = mapping.firstChildElement("source"); - QVector srcPoints; - _parseEllipse(src, srcPoints); - - id = _window->createEllipseTextureMapping(mappingAttrId.toInt(), mappingAttrPaintId.toInt(), srcPoints, dstPoints); - - if (id == NULL_UID) - _xml.raiseError(QObject::tr("Cannot create ellipse texture mapping")); - } - else if (mappingAttrType == "triangle_color") - { - // Parse destination triangle. - _parseTriangle(dst, dstPoints); - - id = _window->createTriangleColorMapping(mappingAttrId.toInt(), mappingAttrPaintId.toInt(), dstPoints); - - if (id == NULL_UID) - _xml.raiseError(QObject::tr("Cannot create triangle color mapping")); - } - else if (mappingAttrType == "quad_color") - { - // Parse destination quad. - _parseQuad(dst, dstPoints); - - id = _window->createQuadColorMapping(mappingAttrId.toInt(), mappingAttrPaintId.toInt(), dstPoints); - - if (id == NULL_UID) - _xml.raiseError(QObject::tr("Cannot create quad color mapping")); - } - else if (mappingAttrType == "ellipse_color") - { - // Parse destination ellipse. - _parseEllipse(dst, dstPoints); - - id = _window->createEllipseColorMapping(mappingAttrId.toInt(), mappingAttrPaintId.toInt(), dstPoints); - - if (id == NULL_UID) - _xml.raiseError(QObject::tr("Cannot create ellipse color mapping")); - } - else - _xml.raiseError(QObject::tr("Unsupported mapping type: %1.").arg(mappingAttrType)); - - // and then set some more attributes: - if (id != NULL_UID) - { - _window->setMappingVisible(id, isVisible); - _window->setMappingSolo (id, isSolo); - _window->setMappingLocked (id, isLocked); - } -} - -void ProjectReader::_parseStandardShape(const QString& type, const QDomElement& shape, QVector& points, int nVertices) -{ - // Check that the element is really a triangle. - QString typeAttr = shape.attribute("shape", ""); - if (typeAttr != type) - _xml.raiseError(QObject::tr("Wrong shape type \"%1\" for destination: expected \"%2\".").arg(typeAttr).arg(type)); - - // Reset list of points. - points.clear(); - - // Add vertices. - QDomElement vertex = shape.firstChildElement("vertex"); - while (!vertex.isNull()) - { - points.push_back(_parseVertex(vertex)); - vertex = vertex.nextSiblingElement("vertex"); - } - - if (nVertices >= 0 && points.size() != nVertices) - _xml.raiseError(QObject::tr("Shape of type '%1' has %2 vertices: expected %3.").arg(type).arg(points.size()).arg(nVertices)); -} - -void ProjectReader::_parseQuad(const QDomElement& quad, QVector& points) -{ - _parseStandardShape("quad", quad, points, 4); -} - -void ProjectReader::_parseTriangle(const QDomElement& triangle, QVector& points) -{ - _parseStandardShape("triangle", triangle, points, 3); -} - -void ProjectReader::_parseEllipse(const QDomElement& ellipse, QVector& points) -{ - _parseStandardShape("ellipse", ellipse, points); - if (points.size() != 4 && points.size() != 5) - _xml.raiseError(QObject::tr("Shape has %1 vertices: expected 4 or 5.").arg(points.size())); -} - -void ProjectReader::_parseMesh(const QDomElement& mesh, QVector& points, int& nColumns, int& nRows) -{ - // Check that the element is really a mash. - QString type = mesh.attribute("shape", ""); - if (type != "mesh") - _xml.raiseError(QObject::tr("Wrong shape type for destination: %1.").arg(type)); - - // Reset list of points. - points.clear(); - - // Check columns and rows. - nColumns = mesh.firstChildElement("dimensions").attribute("columns").toInt(); - nRows = mesh.firstChildElement("dimensions").attribute("rows").toInt(); - - // Add vertices. - QDomElement vertex = mesh.firstChildElement("vertex"); - while (!vertex.isNull()) - { - points.push_back(_parseVertex(vertex)); - vertex = vertex.nextSiblingElement("vertex"); - } - - if (points.size() != nColumns*nRows) - _xml.raiseError(QObject::tr("Shape has wrong number of vertices.")); -} - - -QPointF ProjectReader::_parseVertex(const QDomElement& vertex) -{ - return QPointF( - vertex.attribute("x", "0").toFloat(), - vertex.attribute("y", "0").toFloat() - ); -} - - -//void ProjectReader::readProject() -//{ -// // FIXME: avoid asserts -// Q_ASSERT(_xml.isStartElement() && _xml.name() == "project"); -// -// while(! _xml.atEnd() && ! _xml.hasError()) +// // Parse mappings. +// QDomNode mappingNode = mappings.firstChild(); +// while (!mappingNode.isNull()) // { -// /* Read next element.*/ -// QXmlStreamReader::TokenType token = _xml.readNext(); -// /* If token is just StartDocument, we'll go to next.*/ -// if (token == QXmlStreamReader::StartDocument) +// Mapping::ptr mapping = parseMapping(mappingNode.toElement()); +// if (mapping.isNull()) // { -// continue; +// qDebug() << "Problem creating mapping." << endl; // } -// /* If token is StartElement, we'll see if we can read it.*/ -// else if (token == QXmlStreamReader::StartElement) +// else // { -// if (_xml.name() == "paints") -// continue; -// else if (_xml.name() == "paint") -// { -// std::cout << " * paint" << std::endl; -// readPaint(); -// } -// else if (_xml.name() == "mappings") -// continue; -// else if (_xml.name() == "mapping") -// { -// std::cout << " * mapping " << std::endl; -// readMapping(); // NULL); -// } -// else -// { -// std::cout << " * skip element " << _xml.name().string() << std::endl; -// //_xml.skipCurrentElement(); -// } // } -// } // while -// _xml.clear(); -//} // -//void ProjectReader::readMapping() +// mappingNode = mappingNode.nextSibling(); +// } +} + +Paint::ptr ProjectReader::parsePaint(const QDomElement& paintElem) +{ + QString className = paintElem.attribute(ProjectAttributes::CLASS_NAME); + int id = paintElem.attribute(ProjectAttributes::ID, QString::number(NULL_UID)).toInt(); + + qDebug() << "Found paint with classname: " << className << endl; + + const QMetaObject* metaObject = MetaObjectRegistry::instance().getMetaObject(className); + if (metaObject) + { + // Create new instance. + Paint::ptr paint (qobject_cast(metaObject->newInstance( Q_ARG(int, id)) )); + if (paint.isNull()) + { + qDebug() << QObject::tr("Problem at creation of paint.") << endl; +// _xml.raiseError(QObject::tr("Problem at creation of paint.")); + } + else + qDebug() << "Created new instance with id: " << paint->getId(); + + paint->read(paintElem); + + return paint; + } + + else + { + _xml.raiseError(QObject::tr("Unable to create paint of type '%1'.").arg(className)); + return Paint::ptr(); + } +} +// +//Mapping::ptr ProjectReader::parseMapping(const QDomElement& mappingElem) //{ -// // FIXME: we assume an Image mapping -// Q_ASSERT(_xml.isStartElement() && _xml.name() == "mapping"); -// const QString *paint_id_attr; -// QXmlStreamAttributes attributes = _xml.attributes(); +// QString className = mappingElem.attribute(ProjectAttributes::CLASS_NAME); +// int id = mappingElem.attribute(ProjectAttributes::ID, QString::number(NULL_UID)).toInt(); +// int paintId = mappingElem.attribute(ProjectAttributes::PAINT_ID, QString::number(NULL_UID)).toInt(); +// QString name = mappingElem.attribute(ProjectAttributes::NAME, ""); // -// if (attributes.hasAttribute("", "paint_id")) -// paint_id_attr = attributes.value("", "paint_id").string(); +// qDebug() << "Found mapping with classname: " << className << endl; // -// std::cout << " * " << "with paint ID " << paint_id_attr << std::endl; -// -// //QString title = _xml.readElementText(); -// //item->setText(0, title); -//} -// -//void ProjectReader::readPaint() -//{ -// // FIXME: we assume an Image mapping -// Q_ASSERT(_xml.isStartElement() && _xml.name() == "paint"); -// const QString *paint_id_attr; -// const QString *uri_attr; -// const QString *typeAttrValue; -// QXmlStreamAttributes attributes = _xml.attributes(); -// -// if (attributes.hasAttribute("", "name")) -// paint_id_attr = attributes.value("", "name").string(); -// if (attributes.hasAttribute("", "type")) -// typeAttrValue = attributes.value("", "type").string(); -// -// std::cout << "Found " << typeAttrValue->toStdString() << -// " paint " << paint_id_attr->toStdString() << std::endl; -// -// /* Next element... */ -// _xml.readNext(); -// // /* -// // * We're going to loop over the things because the order might change. -// // * We'll continue the loop until we hit an EndElement. -// // */ -// while(! (_xml.tokenType() == QXmlStreamReader::EndElement && -// _xml.name() == "paint")) +// const QMetaObject* metaObject = MetaObjectRegistry::instance().getMetaObject(className); +// if (metaObject) // { -// if (_xml.tokenType() == QXmlStreamReader::StartElement) -// { -// if (_xml.name() == "uri") +// // Get paint and shape. +// Paint::ptr paint = _window->getMappingManager().getPaintById(paintId); +// +// // Create new instance. +// Mapping::ptr mapping (qobject_cast(metaObject->newInstance( Q_ARG(Paint::ptr, paint), Q_ARG(int, id)) )); +// if (!mapping) +// _xml.raiseError(QObject::tr("Problem at creation of mapping.")); +// else +// qDebug() << "Created new instance with id: " << mapping->getId(); +// +// // Fill up properties. +// int count = metaObject->propertyCount(); +// for (int i=0; iproperty(i); +// +// // If property is writable, try to find it and rewrite it. +// if (property.isWritable()) // { -// /* ...go to the next. */ -// _xml.readNext(); -// /* -// * This elements needs to contain Characters so we know it's -// * actually data, if it's not we'll leave. -// */ -// if(_xml.tokenType() != QXmlStreamReader::Characters) +// const char* propertyName = property.name(); +// +// // Find element. +// QDomElement propertyElem = mappingElem.firstChildElement(propertyName); +// if (!propertyElem.isNull()) // { -// // pass +// mapping->setProperty(propertyName, QVariant(propertyElem.text())); // } -// //uri_attr = _xml.text().toString(); -// //std::cout << "uri " << uri_attr.toStdString() << std::endl; -// } -// else if (_xml.name() == "width") -// { -// // pass -// } -// else if (_xml.name() == "height") -// { -// // pass // } // } -// _xml.readNext(); +// +// // Gather shapes. +// MappingManager& manager = _window->getMappingManager(); +// manager.addMapping(mapping); +// _window->createMeshTextureMapping(mapping->getId(), mapping->getPaint()->getId(), ) +// +// +// return mapping; // } // -// // TODO: call this->_manager->getController->createPaint(...) +// else +// { +// _xml.raiseError(QObject::tr("Unable to create paint of type '%1'.").arg(className)); +// return Paint::ptr(); +// } //} +// +//Mapping::ptr ProjectReader::parseMapping(const QDomElement& mapping) +//{ +// uid id = NULL_UID; +// QString mappingAttrId = mapping.attribute("id", QString::number(NULL_UID)); +// QString mappingAttrPaintId = mapping.attribute("paint_id", QString::number(NULL_UID)); +// QString mappingAttrType = mapping.attribute("type", ""); +// +// bool isLocked = (mapping.attribute("locked", QString::number(1)) == "1"); +// bool isSolo = (mapping.attribute("solo", QString::number(1)) == "1"); +// bool isVisible = (mapping.attribute("visible", QString::number(1)) == "1"); +// +// // Get destination shape. +// QDomElement dst = mapping.firstChildElement("destination"); +// QVector dstPoints; +// +// if (mappingAttrType == "triangle_texture") +// { +// // Parse destination triangle. +// _parseTriangle(dst, dstPoints); +// +// // Get / parse source shape. +// QDomElement src = mapping.firstChildElement("source"); +// QVector srcPoints; +// _parseTriangle(src, srcPoints); +// +// id = _window->createTriangleTextureMapping(mappingAttrId.toInt(), mappingAttrPaintId.toInt(), srcPoints, dstPoints); +// +// if (id == NULL_UID) +// _xml.raiseError(QObject::tr("Cannot create triangle texture mapping")); +// } +// else if (mappingAttrType == "mesh_texture") +// { +// // Parse destination mesh. +// int nColumns; +// int nRows; +// _parseMesh(dst, dstPoints, nColumns, nRows); +// +// // Get / parse source shape. +// QDomElement src = mapping.firstChildElement("source"); +// QVector srcPoints; +// _parseMesh(src, srcPoints, nColumns, nRows); +// +// id = _window->createMeshTextureMapping(mappingAttrId.toInt(), mappingAttrPaintId.toInt(), nColumns, nRows, srcPoints, dstPoints); +// +// if (id == NULL_UID) +// _xml.raiseError(QObject::tr("Cannot create mesh texture mapping")); +// +// } +// else if (mappingAttrType == "ellipse_texture") +// { +// // Parse destination ellipse. +// _parseEllipse(dst, dstPoints); +// +// // Get / parse source shape. +// QDomElement src = mapping.firstChildElement("source"); +// QVector srcPoints; +// _parseEllipse(src, srcPoints); +// +// id = _window->createEllipseTextureMapping(mappingAttrId.toInt(), mappingAttrPaintId.toInt(), srcPoints, dstPoints); +// +// if (id == NULL_UID) +// _xml.raiseError(QObject::tr("Cannot create ellipse texture mapping")); +// } +// else if (mappingAttrType == "triangle_color") +// { +// // Parse destination triangle. +// _parseTriangle(dst, dstPoints); +// +// id = _window->createTriangleColorMapping(mappingAttrId.toInt(), mappingAttrPaintId.toInt(), dstPoints); +// +// if (id == NULL_UID) +// _xml.raiseError(QObject::tr("Cannot create triangle color mapping")); +// } +// else if (mappingAttrType == "quad_color") +// { +// // Parse destination quad. +// _parseQuad(dst, dstPoints); +// +// id = _window->createQuadColorMapping(mappingAttrId.toInt(), mappingAttrPaintId.toInt(), dstPoints); +// +// if (id == NULL_UID) +// _xml.raiseError(QObject::tr("Cannot create quad color mapping")); +// } +// else if (mappingAttrType == "ellipse_color") +// { +// // Parse destination ellipse. +// _parseEllipse(dst, dstPoints); +// +// id = _window->createEllipseColorMapping(mappingAttrId.toInt(), mappingAttrPaintId.toInt(), dstPoints); +// +// if (id == NULL_UID) +// _xml.raiseError(QObject::tr("Cannot create ellipse color mapping")); +// } +// else +// _xml.raiseError(QObject::tr("Unsupported mapping type: %1.").arg(mappingAttrType)); +// +// // and then set some more attributes: +// if (id != NULL_UID) +// { +// _window->setMappingVisible(id, isVisible); +// _window->setMappingSolo (id, isSolo); +// _window->setMappingLocked (id, isLocked); +// } +//} +// +//void ProjectReader::_parseStandardShape(const QString& type, const QDomElement& shape, QVector& points, int nVertices) +//{ +// // Check that the element is really a triangle. +// QString typeAttr = shape.attribute("shape", ""); +// if (typeAttr != type) +// _xml.raiseError(QObject::tr("Wrong shape type \"%1\" for destination: expected \"%2\".").arg(typeAttr).arg(type)); +// +// // Reset list of points. +// points.clear(); +// +// // Add vertices. +// QDomElement vertex = shape.firstChildElement("vertex"); +// while (!vertex.isNull()) +// { +// points.push_back(_parseVertex(vertex)); +// vertex = vertex.nextSiblingElement("vertex"); +// } +// +// if (nVertices >= 0 && points.size() != nVertices) +// _xml.raiseError(QObject::tr("Shape of type '%1' has %2 vertices: expected %3.").arg(type).arg(points.size()).arg(nVertices)); +//} +// +//void ProjectReader::_parseQuad(const QDomElement& quad, QVector& points) +//{ +// _parseStandardShape("quad", quad, points, 4); +//} +// +//void ProjectReader::_parseTriangle(const QDomElement& triangle, QVector& points) +//{ +// _parseStandardShape("triangle", triangle, points, 3); +//} +// +//void ProjectReader::_parseEllipse(const QDomElement& ellipse, QVector& points) +//{ +// _parseStandardShape("ellipse", ellipse, points); +// if (points.size() != 4 && points.size() != 5) +// _xml.raiseError(QObject::tr("Shape has %1 vertices: expected 4 or 5.").arg(points.size())); +//} +// +//void ProjectReader::_parseMesh(const QDomElement& mesh, QVector& points, int& nColumns, int& nRows) +//{ +// // Check that the element is really a mash. +// QString type = mesh.attribute("shape", ""); +// if (type != "mesh") +// _xml.raiseError(QObject::tr("Wrong shape type for destination: %1.").arg(type)); +// +// // Reset list of points. +// points.clear(); +// +// // Check columns and rows. +// nColumns = mesh.firstChildElement("dimensions").attribute("columns").toInt(); +// nRows = mesh.firstChildElement("dimensions").attribute("rows").toInt(); +// +// // Add vertices. +// QDomElement vertex = mesh.firstChildElement("vertex"); +// while (!vertex.isNull()) +// { +// points.push_back(_parseVertex(vertex)); +// vertex = vertex.nextSiblingElement("vertex"); +// } +// +// if (points.size() != nColumns*nRows) +// _xml.raiseError(QObject::tr("Shape has wrong number of vertices.")); +//} +// +// +//QPointF ProjectReader::_parseVertex(const QDomElement& vertex) +//{ +// return QPointF( +// vertex.attribute("x", "0").toFloat(), +// vertex.attribute("y", "0").toFloat() +// ); +//} +// +// +////void ProjectReader::readProject() +////{ +//// // FIXME: avoid asserts +//// Q_ASSERT(_xml.isStartElement() && _xml.name() == "project"); +//// +//// while(! _xml.atEnd() && ! _xml.hasError()) +//// { +//// /* Read next element.*/ +//// QXmlStreamReader::TokenType token = _xml.readNext(); +//// /* If token is just StartDocument, we'll go to next.*/ +//// if (token == QXmlStreamReader::StartDocument) +//// { +//// continue; +//// } +//// /* If token is StartElement, we'll see if we can read it.*/ +//// else if (token == QXmlStreamReader::StartElement) +//// { +//// if (_xml.name() == "paints") +//// continue; +//// else if (_xml.name() == "paint") +//// { +//// std::cout << " * paint" << std::endl; +//// readPaint(); +//// } +//// else if (_xml.name() == "mappings") +//// continue; +//// else if (_xml.name() == "mapping") +//// { +//// std::cout << " * mapping " << std::endl; +//// readMapping(); // NULL); +//// } +//// else +//// { +//// std::cout << " * skip element " << _xml.name().string() << std::endl; +//// //_xml.skipCurrentElement(); +//// } +//// } +//// } // while +//// _xml.clear(); +////} +//// +////void ProjectReader::readMapping() +////{ +//// // FIXME: we assume an Image mapping +//// Q_ASSERT(_xml.isStartElement() && _xml.name() == "mapping"); +//// const QString *paint_id_attr; +//// QXmlStreamAttributes attributes = _xml.attributes(); +//// +//// if (attributes.hasAttribute("", "paint_id")) +//// paint_id_attr = attributes.value("", "paint_id").string(); +//// +//// std::cout << " * " << "with paint ID " << paint_id_attr << std::endl; +//// +//// //QString title = _xml.readElementText(); +//// //item->setText(0, title); +////} +//// +////void ProjectReader::readPaint() +////{ +//// // FIXME: we assume an Image mapping +//// Q_ASSERT(_xml.isStartElement() && _xml.name() == "paint"); +//// const QString *paint_id_attr; +//// const QString *uri_attr; +//// const QString *typeAttrValue; +//// QXmlStreamAttributes attributes = _xml.attributes(); +//// +//// if (attributes.hasAttribute("", "name")) +//// paint_id_attr = attributes.value("", "name").string(); +//// if (attributes.hasAttribute("", "type")) +//// typeAttrValue = attributes.value("", "type").string(); +//// +//// std::cout << "Found " << typeAttrValue->toStdString() << +//// " paint " << paint_id_attr->toStdString() << std::endl; +//// +//// /* Next element... */ +//// _xml.readNext(); +//// // /* +//// // * We're going to loop over the things because the order might change. +//// // * We'll continue the loop until we hit an EndElement. +//// // */ +//// while(! (_xml.tokenType() == QXmlStreamReader::EndElement && +//// _xml.name() == "paint")) +//// { +//// if (_xml.tokenType() == QXmlStreamReader::StartElement) +//// { +//// if (_xml.name() == "uri") +//// { +//// /* ...go to the next. */ +//// _xml.readNext(); +//// /* +//// * This elements needs to contain Characters so we know it's +//// * actually data, if it's not we'll leave. +//// */ +//// if(_xml.tokenType() != QXmlStreamReader::Characters) +//// { +//// // pass +//// } +//// //uri_attr = _xml.text().toString(); +//// //std::cout << "uri " << uri_attr.toStdString() << std::endl; +//// } +//// else if (_xml.name() == "width") +//// { +//// // pass +//// } +//// else if (_xml.name() == "height") +//// { +//// // pass +//// } +//// } +//// _xml.readNext(); +//// } +//// +//// // TODO: call this->_manager->getController->createPaint(...) +////} diff --git a/ProjectReader.h b/ProjectReader.h index 4fcf71a..c6d5cb5 100644 --- a/ProjectReader.h +++ b/ProjectReader.h @@ -24,6 +24,10 @@ #include "Mapping.h" #include "Paint.h" +#include "MetaObjectRegistry.h" +// TODO: replace with ProjectAttributes.h +#include "ProjectWriter.h" + class ProjectReader { public: @@ -34,15 +38,15 @@ public: private: void readProject(); void parseProject(const QDomElement& project); - void parsePaint(const QDomElement& paint); - void parseMapping(const QDomElement& mapping); - - void _parseStandardShape(const QString& type, const QDomElement& shape, QVector& points, int nVertices=-1); - void _parseQuad(const QDomElement& quad, QVector& points); - void _parseTriangle(const QDomElement& triangle, QVector& points); - void _parseMesh(const QDomElement& mesh, QVector& points, int& nColumns, int& nRows); - void _parseEllipse(const QDomElement& ellipse, QVector& points); - QPointF _parseVertex(const QDomElement& vertex); + Paint::ptr parsePaint(const QDomElement& paint); +// Mapping::ptr parseMapping(const QDomElement& mapping); +// +// void _parseStandardShape(const QString& type, const QDomElement& shape, QVector& points, int nVertices=-1); +// void _parseQuad(const QDomElement& quad, QVector& points); +// void _parseTriangle(const QDomElement& triangle, QVector& points); +// void _parseMesh(const QDomElement& mesh, QVector& points, int& nColumns, int& nRows); +// void _parseEllipse(const QDomElement& ellipse, QVector& points); +// QPointF _parseVertex(const QDomElement& vertex); // void readPaint(); //Paint *item); // void readMapping(); //Mapping *item); diff --git a/ProjectWriter.cpp b/ProjectWriter.cpp index 851e372..657c28c 100644 --- a/ProjectWriter.cpp +++ b/ProjectWriter.cpp @@ -20,159 +20,168 @@ #include "ProjectWriter.h" #include -ProjectWriter::ProjectWriter(MappingManager *manager) : - _manager(manager) +const char* ProjectAttributes::CLASS_NAME = "className"; +const char* ProjectAttributes::PAINTS = "paints"; +const char* ProjectAttributes::MAPPINGS = "mappings"; +const char* ProjectAttributes::ID = "id"; +const char* ProjectAttributes::NAME = "name"; + +ProjectWriter::ProjectWriter(MainWindow *window) : + _window(window) { _xml.setAutoFormatting(true); } bool ProjectWriter::writeFile(QIODevice *device) { - _xml.setDevice(device); - - _xml.writeStartDocument(); - _xml.writeDTD(""); - _xml.writeStartElement("project"); - _xml.writeAttribute("version", "0.1"); // Similar to pkg-config version numbers. + MappingManager& manager = _window->getMappingManager(); + QDomDocument doc; + QDomElement project = doc.createElement("project"); + project.setAttribute("version", MM::VERSION); - _xml.writeStartElement("paints"); - for (int i = 0; i < _manager->nPaints(); i++) - writeItem(_manager->getPaint(i).data()); - _xml.writeEndElement(); + QDomElement paints = doc.createElement("paints"); - _xml.writeStartElement("mappings"); - for (int i = 0; i < _manager->nMappings(); i++) - writeItem(_manager->getMapping(i).data()); - _xml.writeEndElement(); + for (int i=0; iwrite(paint); + paints.appendChild(paint); + } + + project.appendChild(paints); + doc.appendChild(project); + + QTextStream out(device); + out << "" << endl; + out << "" << endl; + out << doc.toString(2); - _xml.writeEndElement(); - _xml.writeEndDocument(); return true; } -void ProjectWriter::writeItem(Paint *item) -{ - _xml.writeStartElement("paint"); - _xml.writeAttribute("id", QString::number(item->getId())); - //_xml.writeAttribute("name", item->getName()); - _xml.writeAttribute("type", item->getType()); - - if (item->getType() == "media") - { - // FIXME: check paint type before casting to Media - Media *media = (Media *) item; - - _xml.writeTextElement("uri", media->getUri()); - { - std::ostringstream os; - os << media->getX(); - _xml.writeTextElement("x", os.str().c_str()); - } - - { - std::ostringstream os; - os << media->getY(); - _xml.writeTextElement("y", os.str().c_str()); - } - - { - std::ostringstream os; - os << media->getRate(); - _xml.writeTextElement("rate", os.str().c_str()); - } - - _xml.writeEndElement(); - //_xml.writeEmptyElement("hello"); - } - else if (item->getType() == "image") - { - // FIXME: check paint type before casting to Image - Image *media = (Image *) item; - - _xml.writeTextElement("uri", media->getUri()); - { - std::ostringstream os; - os << media->getX(); - _xml.writeTextElement("x", os.str().c_str()); - } - - { - std::ostringstream os; - os << media->getY(); - _xml.writeTextElement("y", os.str().c_str()); - } - - _xml.writeEndElement(); - //_xml.writeEmptyElement("hello"); - } - else if (item->getType() == "color") - { - // FIXME: check paint type before casting to Image - Color *color = (Color *) item; - - _xml.writeTextElement("rgb", color->getColor().name()); - _xml.writeEndElement(); - } - else - qDebug() << "Unknown type, cannot save: " << item->getType() << endl; -} - -void ProjectWriter::writeShapeVertices(MShape *shape) -{ - if (shape->getType() == "mesh") { - Mesh* mesh = (Mesh*) shape; - _xml.writeStartElement("dimensions"); - _xml.writeAttribute("columns", QString::number(mesh->nColumns())); - _xml.writeAttribute("rows", QString::number(mesh->nRows())); - _xml.writeEndElement(); // vertex - } - - for (int i = 0; i < shape->nVertices(); i++) - { - const QPointF& point = shape->getVertex(i); - _xml.writeStartElement("vertex"); - _xml.writeAttribute("x", QString::number(point.x())); - _xml.writeAttribute("y", QString::number(point.y())); - _xml.writeEndElement(); // vertex - } -} - -void ProjectWriter::writeItem(Mapping *item) -{ - _xml.writeStartElement("mapping"); - qDebug() << "ID: " << item->getId() << endl; - _xml.writeAttribute("id", QString::number(item->getId())); - _xml.writeAttribute("paint_id", QString::number(item->getPaint()->getId())); - _xml.writeAttribute("type", item->getType()); - - // boolean attributes: - _xml.writeAttribute("locked", QString::number((int) item->isLocked() ? 1 : 0)); - _xml.writeAttribute("solo", QString::number((int) item->isSolo() ? 1 : 0)); - _xml.writeAttribute("visible", QString::number((int) item->isVisible() ? 1 : 0)); - - MShape *shape = item->getShape().data(); - _xml.writeStartElement("destination"); - _xml.writeAttribute("shape", shape->getType()); - writeShapeVertices(shape); - _xml.writeEndElement(); // shape - - if (item->getType().endsWith("_texture")) - { - TextureMapping *tex = (TextureMapping *) item; - shape = tex->getInputShape().data(); - - _xml.writeStartElement("source"); - _xml.writeAttribute("shape", shape->getType()); - writeShapeVertices(shape); - _xml.writeEndElement(); // shape - - _xml.writeEndElement(); // mapping - } - else if (item->getType().endsWith("_color")) - { - _xml.writeEndElement(); // mapping - } - else - qDebug() << "Unknown type, cannot save: " << item->getType() << endl; -} - +//void ProjectWriter::writeItem(Paint *item) +//{ +// _xml.writeStartElement("paint"); +// _xml.writeAttribute("id", QString::number(item->getId())); +// //_xml.writeAttribute("name", item->getName()); +// _xml.writeAttribute("type", item->getType()); +// +// if (item->getType() == "media") +// { +// // FIXME: check paint type before casting to Media +// Media *media = (Media *) item; +// +// _xml.writeTextElement("uri", media->getUri()); +// { +// std::ostringstream os; +// os << media->getX(); +// _xml.writeTextElement("x", os.str().c_str()); +// } +// +// { +// std::ostringstream os; +// os << media->getY(); +// _xml.writeTextElement("y", os.str().c_str()); +// } +// +// { +// std::ostringstream os; +// os << media->getRate(); +// _xml.writeTextElement("rate", os.str().c_str()); +// } +// +// _xml.writeEndElement(); +// //_xml.writeEmptyElement("hello"); +// } +// else if (item->getType() == "image") +// { +// // FIXME: check paint type before casting to Image +// Image *media = (Image *) item; +// +// _xml.writeTextElement("uri", media->getUri()); +// { +// std::ostringstream os; +// os << media->getX(); +// _xml.writeTextElement("x", os.str().c_str()); +// } +// +// { +// std::ostringstream os; +// os << media->getY(); +// _xml.writeTextElement("y", os.str().c_str()); +// } +// +// _xml.writeEndElement(); +// //_xml.writeEmptyElement("hello"); +// } +// else if (item->getType() == "color") +// { +// // FIXME: check paint type before casting to Image +// Color *color = (Color *) item; +// +// _xml.writeTextElement("rgb", color->getColor().name()); +// _xml.writeEndElement(); +// } +// else +// qDebug() << "Unknown type, cannot save: " << item->getType() << endl; +//} +// +//void ProjectWriter::writeShapeVertices(MShape *shape) +//{ +// if (shape->getType() == "mesh") { +// Mesh* mesh = (Mesh*) shape; +// _xml.writeStartElement("dimensions"); +// _xml.writeAttribute("columns", QString::number(mesh->nColumns())); +// _xml.writeAttribute("rows", QString::number(mesh->nRows())); +// _xml.writeEndElement(); // vertex +// } +// +// for (int i = 0; i < shape->nVertices(); i++) +// { +// const QPointF& point = shape->getVertex(i); +// _xml.writeStartElement("vertex"); +// _xml.writeAttribute("x", QString::number(point.x())); +// _xml.writeAttribute("y", QString::number(point.y())); +// _xml.writeEndElement(); // vertex +// } +//} +// +//void ProjectWriter::writeItem(Mapping *item) +//{ +// _xml.writeStartElement("mapping"); +// qDebug() << "ID: " << item->getId() << endl; +// _xml.writeAttribute("id", QString::number(item->getId())); +// _xml.writeAttribute("paint_id", QString::number(item->getPaint()->getId())); +// _xml.writeAttribute("type", item->getType()); +// +// // boolean attributes: +// _xml.writeAttribute("locked", QString::number((int) item->isLocked() ? 1 : 0)); +// _xml.writeAttribute("solo", QString::number((int) item->isSolo() ? 1 : 0)); +// _xml.writeAttribute("visible", QString::number((int) item->isVisible() ? 1 : 0)); +// +// MShape *shape = item->getShape().data(); +// _xml.writeStartElement("destination"); +// _xml.writeAttribute("shape", shape->getType()); +// writeShapeVertices(shape); +// _xml.writeEndElement(); // shape +// +// if (item->getType().endsWith("_texture")) +// { +// TextureMapping *tex = (TextureMapping *) item; +// shape = tex->getInputShape().data(); +// +// _xml.writeStartElement("source"); +// _xml.writeAttribute("shape", shape->getType()); +// writeShapeVertices(shape); +// _xml.writeEndElement(); // shape +// +// _xml.writeEndElement(); // mapping +// } +// else if (item->getType().endsWith("_color")) +// { +// _xml.writeEndElement(); // mapping +// } +// else +// qDebug() << "Unknown type, cannot save: " << item->getType() << endl; +//} +// diff --git a/ProjectWriter.h b/ProjectWriter.h index 737e71b..028d29b 100644 --- a/ProjectWriter.h +++ b/ProjectWriter.h @@ -17,22 +17,44 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#ifndef PROJECT_WRITER_H_ +#define PROJECT_WRITER_H_ #include #include "MappingManager.h" #include "Mapping.h" #include "Paint.h" +#include "MainWindow.h" + +#include "Shapes.h" + +class ProjectAttributes +{ +public: + static const char* CLASS_NAME; + static const char* PAINTS; + static const char* MAPPINGS; + + static const char* ID; + static const char* NAME; + static const char* PAINT_ID; +}; class ProjectWriter { - public: - ProjectWriter (MappingManager *manager); +public: + ProjectWriter (MainWindow *window); bool writeFile (QIODevice *device); private: - void writeItem (Paint *item); - void writeItem (Mapping *item); - void writeShapeVertices (MShape *shape); + void writeProject(); +// void writePaint(Paint::ptr paint); +// void writeItem (Paint *item); +// void writeItem (Mapping *item); +// void writeShapeVertices (MShape *shape); + QXmlStreamWriter _xml; - MappingManager *_manager; + MainWindow *_window; }; + +#endif diff --git a/main.cpp b/main.cpp index fe8eeef..6c653f5 100644 --- a/main.cpp +++ b/main.cpp @@ -12,6 +12,9 @@ #include "MM.h" #include "MainWindow.h" #include "MainApplication.h" + +#include "MetaObjectRegistry.h" + #include #include @@ -42,10 +45,33 @@ public: } }; +void initRegistry() +{ + MetaObjectRegistry& registry = MetaObjectRegistry::instance(); + + // Paints. + registry.add(); + registry.add(); + registry.add(); + + // Mappings. + registry.add(); + registry.add(); + + // Shapes. + registry.add(); + registry.add(); + registry.add(); + registry.add(); +} + int main(int argc, char *argv[]) { set_env_vars_if_needed(); + // Initialize meta-object registry. + initRegistry(); + MainApplication app(argc, argv); #if USING_QT_5