summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--GUI_SS2015.pro2
-rw-r--r--ellipse.cpp6
-rw-r--r--ellipse.h6
-rw-r--r--interactioncanvas.cpp127
-rw-r--r--interactioncanvas.h7
-rw-r--r--line.cpp77
-rw-r--r--line.h18
-rw-r--r--mainwindow.cpp54
-rw-r--r--mainwindow.h13
-rw-r--r--mainwindow.ui18
-rw-r--r--polygon.cpp65
-rw-r--r--polygon.h5
-rw-r--r--rectangle.cpp53
-rw-r--r--rectangle.h4
14 files changed, 416 insertions, 39 deletions
diff --git a/GUI_SS2015.pro b/GUI_SS2015.pro
index 49d6038..aa989cc 100644
--- a/GUI_SS2015.pro
+++ b/GUI_SS2015.pro
@@ -4,7 +4,7 @@
#
#-------------------------------------------------
-QT += core gui
+QT += core gui xml
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
diff --git a/ellipse.cpp b/ellipse.cpp
index dc0f4f8..d3c924e 100644
--- a/ellipse.cpp
+++ b/ellipse.cpp
@@ -28,3 +28,9 @@ void Ellipse::draw(QPainter *painter)
painter->drawEllipse(m_rectangle);
}
+
+
+QString Ellipse::className()
+{
+ return "Ellipse";
+}
diff --git a/ellipse.h b/ellipse.h
index 6d27c9b..617357f 100644
--- a/ellipse.h
+++ b/ellipse.h
@@ -9,9 +9,11 @@ class Ellipse : public Rectangle
public:
Ellipse();
- // Line interface
-public:
virtual void draw(QPainter *painter);
+
+ // Line interface
+protected:
+ virtual QString className();
};
#endif // ELLIPSE_H
diff --git a/interactioncanvas.cpp b/interactioncanvas.cpp
index 80a4317..3236be1 100644
--- a/interactioncanvas.cpp
+++ b/interactioncanvas.cpp
@@ -1,7 +1,7 @@
#include "interactioncanvas.h"
InteractionCanvas::InteractionCanvas(QWidget *parent)
- :QLabel(parent)
+ : QLabel(parent)
{
setFocusPolicy(Qt::StrongFocus);
setMouseTracking(true);
@@ -9,19 +9,27 @@ InteractionCanvas::InteractionCanvas(QWidget *parent)
m_SelectedLine = NULL;
}
-InteractionCanvas::~InteractionCanvas()
+void InteractionCanvas::clearLines()
{
- for(int i = 0; i < m_Lines.size(); i++)
+ for (int i = 0; i < m_Lines.size(); i++)
{
delete m_Lines[i];
- m_Lines.removeAt(i);
}
- if(m_NewLine)
+
+ m_Lines.clear();
+}
+
+InteractionCanvas::~InteractionCanvas()
+{
+ clearLines();
+
+ if (m_NewLine)
{
delete m_NewLine;
m_NewLine = NULL;
}
- if(m_SelectedLine)
+
+ if (m_SelectedLine)
{
delete m_SelectedLine;
m_SelectedLine = NULL;
@@ -66,22 +74,100 @@ void InteractionCanvas::addPolygon()
changeSelectedLine(tmpLine);
}
+void InteractionCanvas::read(QFile *file)
+{
+ m_fileName.setContent(file, false);
+
+ QDomElement root = m_fileName.documentElement();
+
+ if (root.tagName() == "geometric_objects")
+ {
+ QDomElement child = root.firstChildElement();
+
+ Line *line = NULL;
+
+ clearLines();
+
+ while (!child.isNull())
+ {
+ line = NULL;
+
+ if (child.tagName() == "Line")
+ {
+ line = new Line();
+ }
+
+ if (child.tagName() == "Rectangle")
+ {
+ line = new Rectangle();
+ }
+
+ if (child.tagName() == "Ellipse")
+ {
+ line = new Ellipse();
+ }
+
+ if (child.tagName() == "Polygon")
+ {
+ line = new Polygon();
+ }
+
+ if (line != NULL)
+ {
+ line->fromDomElement(child);
+ line->setSelected(false);
+ m_Lines.append(line);
+ }
+
+ child = child.nextSiblingElement();
+ }
+ }
+}
+
+void InteractionCanvas::write(QFile *file)
+{
+ const int IndentSize = 4;
+
+ m_fileName.clear();
+
+ QDomElement root = m_fileName.createElement("geometric_objects");
+
+ m_fileName.appendChild(root);
+
+ QListIterator<Line *> childs(m_Lines);
+
+ Line *child = NULL;
+
+ while (childs.hasNext())
+ {
+ child = childs.next();
+
+ root.appendChild(child->toDomElement(&m_fileName));
+ }
+
+ QTextStream out(file);
+ m_fileName.save(out, IndentSize);
+}
+
void InteractionCanvas::mouseMoveEvent(QMouseEvent *mouseEvent)
{
qDebug() << "InteractionCanvas:" << mouseEvent->pos();
if (mouseEvent->buttons() == Qt::LeftButton)
{
- if(m_SelectedLine)
+ if (m_SelectedLine)
{
m_SelectedLine->move(m_LastMousePosition, mouseEvent->pos());
}
- if(m_NewLine)
+
+ if (m_NewLine)
{
m_NewLine->setP2(mouseEvent->pos());
}
+
update();
}
+
m_LastMousePosition = mouseEvent->pos();
}
@@ -92,7 +178,7 @@ void InteractionCanvas::mousePressEvent(QMouseEvent *mouseEvent)
if (mouseEvent->button() == Qt::LeftButton)
{
- if(!m_SelectedLine)
+ if (!m_SelectedLine)
{
m_MousePressPoint = mouseEvent->pos();
m_LastMousePosition = m_MousePressPoint;
@@ -105,14 +191,16 @@ void InteractionCanvas::mousePressEvent(QMouseEvent *mouseEvent)
if (mouseEvent->button() == Qt::RightButton)
{
changeSelectedLine(NULL);
- for(int i = 0; i < m_Lines.size() && !m_SelectedLine; i++)
+
+ for (int i = 0; i < m_Lines.size() && !m_SelectedLine; i++)
{
- if(m_Lines[i]->isHit(mouseEvent->pos()))
+ if (m_Lines[i]->isHit(mouseEvent->pos()))
{
changeSelectedLine(m_Lines[i]);
}
}
}
+
update();
}
@@ -122,7 +210,7 @@ void InteractionCanvas::mouseReleaseEvent(QMouseEvent *mouseEvent)
if (mouseEvent->button() == Qt::LeftButton)
{
- if(m_NewLine)
+ if (m_NewLine)
{
m_MouseReleasePoint = mouseEvent->pos();
m_NewLine->setP2(m_MouseReleasePoint);
@@ -140,12 +228,14 @@ void InteractionCanvas::keyPressEvent(QKeyEvent *keyEvent)
qDebug() << "InteractionCanvas: Key: pressed:" << keyEvent->key() << "(" <<
keyEvent->text() << ")" << (keyEvent->isAutoRepeat() ? "druck" : "");
- if(!m_Lines.isEmpty() && keyEvent->key() == Qt::Key_Z && keyEvent->modifiers() == Qt::ControlModifier)
+ if (!m_Lines.isEmpty() && keyEvent->key() == Qt::Key_Z &&
+ keyEvent->modifiers() == Qt::ControlModifier)
{
- if(m_SelectedLine == m_Lines.last())
+ if (m_SelectedLine == m_Lines.last())
{
m_SelectedLine = NULL;
}
+
delete m_Lines.last();
m_Lines.removeLast();
update();
@@ -155,7 +245,7 @@ void InteractionCanvas::keyPressEvent(QKeyEvent *keyEvent)
void InteractionCanvas::keyReleaseEvent(QKeyEvent *keyEvent)
{
qDebug() << "InteractionCanvas: Key: released:" << keyEvent->key() << "(" <<
- keyEvent->text() << ")" << (keyEvent->isAutoRepeat() ? "druck" : "");
+ keyEvent->text() << ")" << (keyEvent->isAutoRepeat() ? "druck" : "");
}
/**
@@ -165,12 +255,13 @@ void InteractionCanvas::keyReleaseEvent(QKeyEvent *keyEvent)
*/
void InteractionCanvas::changeSelectedLine(Line *newSelectedLine)
{
- if(m_SelectedLine)
+ if (m_SelectedLine)
{
m_SelectedLine->setSelected(false);
m_SelectedLine = NULL;
}
- if(newSelectedLine)
+
+ if (newSelectedLine)
{
m_SelectedLine = newSelectedLine;
m_SelectedLine->setSelected(true);
@@ -185,7 +276,7 @@ void InteractionCanvas::addNewLine(Line *newLine)
m_NewLine = NULL;
}
- if(newLine)
+ if (newLine)
{
m_NewLine = new Line();
}
diff --git a/interactioncanvas.h b/interactioncanvas.h
index 397865d..d87165e 100644
--- a/interactioncanvas.h
+++ b/interactioncanvas.h
@@ -24,6 +24,10 @@ public:
void addEllipse();
void addPolygon();
+ //QDom methods
+ void read(QFile *file);
+ void write(QFile *file);
+
protected:
void mouseMoveEvent(QMouseEvent *mouseEvent);
void mousePressEvent(QMouseEvent *mouseEvent);
@@ -34,6 +38,7 @@ protected:
private:
void changeSelectedLine(Line *newSelectedLine);
void addNewLine(Line *newLine);
+ void clearLines();
QList<Line *> m_Lines;
Line *m_NewLine;
@@ -42,6 +47,8 @@ private:
QPoint m_MouseReleasePoint;
QPoint m_LastMousePosition;
+ QDomDocument m_fileName;
+
protected:
void paintEvent(QPaintEvent *paintEvent);
};
diff --git a/line.cpp b/line.cpp
index 5f7e171..2d19874 100644
--- a/line.cpp
+++ b/line.cpp
@@ -1,7 +1,7 @@
#include "line.h"
Line::Line()
- :QLine()
+ : QLine()
{
m_selected = true;
}
@@ -25,7 +25,7 @@ void Line::setSelected(bool selected)
void Line::draw(QPainter *painter)
{
- if(m_selected)
+ if (m_selected)
{
QPen penTemp(Qt::DotLine);
penTemp.setColor(Qt::red);
@@ -47,15 +47,16 @@ void Line::draw(QPainter *painter)
void Line::move(const QPoint &oldPoint, const QPoint &newPoint)
{
- if(m_selected)
+ if (m_selected)
{
QPoint offset = newPoint - oldPoint;
QVector3D vecOld(oldPoint);
- if(vecOld.distanceToPoint(QVector3D(p1())) < 5)
+
+ if (vecOld.distanceToPoint(QVector3D(p1())) < 5)
{
setP1(p1() + offset);
}
- else if(vecOld.distanceToPoint(QVector3D(p2())) < 5)
+ else if (vecOld.distanceToPoint(QVector3D(p2())) < 5)
{
setP2(p2() + offset);
}
@@ -66,3 +67,69 @@ void Line::move(const QPoint &oldPoint, const QPoint &newPoint)
}
}
}
+
+QDomElement Line::toDomElement(QDomDocument *doc)
+{
+ QDomElement e = doc->createElement(className());
+ attributesToDom(doc, e);
+ return e;
+}
+
+bool Line::attributesToDom(QDomDocument *doc, QDomElement &e)
+{
+ if (e.isNull())
+ {
+ qDebug() << className() << "::attributesToDom Error: NULL element passed.";
+ return false;
+ }
+ else
+ {
+ e.setAttribute("x1", p1().rx());
+ e.setAttribute("y1", p1().ry());
+ e.setAttribute("x2", p2().rx());
+ e.setAttribute("y2", p2().ry());
+
+ return true;
+ }
+}
+
+bool Line::fromDomElement(const QDomElement &e)
+{
+ if (e.isNull())
+ {
+ qDebug() << className() << "::fromQDomElement Error: NULL element passed.";
+ return false;
+ }
+
+ if (className() != e.tagName())
+ {
+ qDebug() << className() << "::fromQDomElement Error: Invalid element type: " <<
+ e.tagName() << " instead of " << className();
+ return false;
+ }
+
+ return attributesFromDom(e);
+}
+
+bool Line::attributesFromDom(const QDomElement &e)
+{
+ if (e.isNull())
+ {
+ qDebug() << className() << "::attributesFromDom Error: NULL element passed.";
+ return false;
+ }
+ else
+ {
+ QPoint newP1(e.attribute("x1", "0").toInt(), e.attribute("y1", "0").toInt());
+ QPoint newP2(e.attribute("x2", "0").toInt(), e.attribute("y2", "0").toInt());
+
+ setPoints(newP1, newP2);
+
+ return true;
+ }
+}
+
+QString Line::className()
+{
+ return "Line";
+}
diff --git a/line.h b/line.h
index ffdb5d7..115c1e8 100644
--- a/line.h
+++ b/line.h
@@ -4,18 +4,30 @@
#include <QLine>
#include <QPainter>
#include <QVector3D>
+#include <QDomElement>
+
+#include <QDebug>
class Line : public QLine
{
public:
Line();
- virtual bool isHit(const QPoint & clickPoint);
+ virtual bool isHit(const QPoint &clickPoint);
void setSelected(bool selected);
- virtual void draw(QPainter * painter);
- virtual void move(const QPoint & oldPoint, const QPoint & newPoint);
+ virtual void draw(QPainter *painter);
+ virtual void move(const QPoint &oldPoint, const QPoint &newPoint);
+
+ // QDOM methods
+ QDomElement toDomElement(QDomDocument *doc);
+ bool fromDomElement(const QDomElement &e);
+
protected:
+ virtual bool attributesToDom(QDomDocument *doc, QDomElement &e);
+ virtual bool attributesFromDom(const QDomElement &e);
+ virtual QString className();
+
bool m_selected;
};
diff --git a/mainwindow.cpp b/mainwindow.cpp
index 656b8c9..5df38a5 100644
--- a/mainwindow.cpp
+++ b/mainwindow.cpp
@@ -6,6 +6,7 @@ MainWindow::MainWindow(QWidget *parent) :
ui(new Ui::MainWindow)
{
ui->setupUi(this);
+ lastUsedFile = NULL;
}
MainWindow::~MainWindow()
@@ -42,6 +43,57 @@ void MainWindow::on_actionPreferences_triggered()
delete tmp;
}
+void MainWindow::on_actionLoad_triggered()
+{
+ QString fileName = QFileDialog::getOpenFileName(this, tr("Load an XML file"),
+ QStandardPaths::standardLocations(QStandardPaths::HomeLocation).at(0),
+ tr("XML File (*.xml *.Xml *.XML)"), 0, QFileDialog::DontUseNativeDialog);
+
+ if(lastUsedFile)
+ {
+ delete lastUsedFile;
+ lastUsedFile = NULL;
+ }
+
+ lastUsedFile = new QFile(fileName);
+
+ if (lastUsedFile->exists())
+ {
+ ui->interactionCanvasPlaceholder->read(lastUsedFile);
+ }
+
+}
+
+void MainWindow::on_actionSave_triggered()
+{
+ if (!lastUsedFile)
+ {
+ on_actionSave_As_triggered();
+ }
+
+ lastUsedFile->open(QFile::ReadWrite | QFile::Truncate);
+
+ ui->interactionCanvasPlaceholder->write(lastUsedFile);
+
+ lastUsedFile->close();
+}
+
+void MainWindow::on_actionSave_As_triggered()
+{
+ QString fileName = QFileDialog::getSaveFileName(this, tr("Load an XML file"),
+ QStandardPaths::standardLocations(QStandardPaths::HomeLocation).at(0),
+ tr("XML File (*.xml *.Xml *.XML)"), 0, QFileDialog::DontUseNativeDialog);
+
+ if (lastUsedFile)
+ {
+ delete lastUsedFile;
+ lastUsedFile = NULL;
+ }
+
+ lastUsedFile = new QFile(fileName);
+
+ on_actionSave_triggered();
+}
void MainWindow::on_actionLanguage_triggered()
{
@@ -100,7 +152,7 @@ void MainWindow::mouseMoveEvent(QMouseEvent *mouseEvent)
qDebug() << "MainWindow:" << mouseEvent->pos();
}
-void MainWindow::loadLanguage(const QString& rLanguageFile)
+void MainWindow::loadLanguage(const QString &rLanguageFile)
{
// remove the old translator
qApp->removeTranslator(&m_translator);
diff --git a/mainwindow.h b/mainwindow.h
index 43dbb29..d855081 100644
--- a/mainwindow.h
+++ b/mainwindow.h
@@ -4,6 +4,13 @@
#include <QMainWindow>
#include <QDebug>
#include <QMouseEvent>
+#include <QFileDialog>
+#include <QStandardPaths>
+#include <QMessageBox>
+
+#include <QDomDocument>
+#include <QDomElement>
+
#include "dlgpreferences.h"
#include "interactioncanvas.h"
#include "languagedialog.h"
@@ -37,10 +44,16 @@ private slots:
void on_actionDraw_Polygon_triggered();
void changeEvent(QEvent *event);
+private slots:
+ void on_actionLoad_triggered();
+ void on_actionSave_triggered();
+ void on_actionSave_As_triggered();
+
private:
Ui::MainWindow *ui;
QTranslator m_translator; // contains the translations for this application
+ QFile *lastUsedFile;
};
#endif // MAINWINDOW_H
diff --git a/mainwindow.ui b/mainwindow.ui
index 9e55b3a..d551437 100644
--- a/mainwindow.ui
+++ b/mainwindow.ui
@@ -38,6 +38,9 @@
<property name="title">
<string>Fi&amp;le</string>
</property>
+ <addaction name="actionLoad"/>
+ <addaction name="actionSave"/>
+ <addaction name="actionSave_As"/>
<addaction name="actionExit"/>
</widget>
<widget class="QMenu" name="menuEdir">
@@ -105,6 +108,21 @@
<string>Draw P&amp;olygon</string>
</property>
</action>
+ <action name="actionLoad">
+ <property name="text">
+ <string>L&amp;oad</string>
+ </property>
+ </action>
+ <action name="actionSave">
+ <property name="text">
+ <string>&amp;Save</string>
+ </property>
+ </action>
+ <action name="actionSave_As">
+ <property name="text">
+ <string>S&amp;ave As</string>
+ </property>
+ </action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<customwidgets>
diff --git a/polygon.cpp b/polygon.cpp
index d8b71b7..c785e7b 100644
--- a/polygon.cpp
+++ b/polygon.cpp
@@ -38,19 +38,20 @@ void Polygon::draw(QPainter *painter)
void Polygon::move(const QPoint &oldPoint, const QPoint &newPoint)
{
- if(m_selected)
+ if (m_selected)
{
QPoint offset = newPoint - oldPoint;
QVector3D vecOld(oldPoint);
- if(vecOld.distanceToPoint(QVector3D(m_polygon.point(0))) < 5)
+
+ if (vecOld.distanceToPoint(QVector3D(m_polygon.point(0))) < 5)
{
m_polygon.replace(0, m_polygon.point(0) + offset);
}
- else if(vecOld.distanceToPoint(QVector3D(m_polygon.point(1))) < 5)
+ else if (vecOld.distanceToPoint(QVector3D(m_polygon.point(1))) < 5)
{
m_polygon.replace(1, m_polygon.point(1) + offset);
}
- else if(vecOld.distanceToPoint(QVector3D(m_polygon.point(2))) < 5)
+ else if (vecOld.distanceToPoint(QVector3D(m_polygon.point(2))) < 5)
{
m_polygon.replace(2, m_polygon.point(2) + offset);
}
@@ -62,3 +63,59 @@ void Polygon::move(const QPoint &oldPoint, const QPoint &newPoint)
}
}
}
+
+bool Polygon::attributesToDom(QDomDocument *doc, QDomElement &e)
+{
+ if (e.isNull())
+ {
+ qDebug() << className() << "::attributesToDom Error: NULL element passed.";
+ return false;
+ }
+ else
+ {
+ QDomElement tmp;
+
+ foreach(QPoint point, m_polygon.toList())
+ {
+ tmp = doc->createElement("Point");
+
+ tmp.setAttribute("x", point.rx());
+ tmp.setAttribute("y", point.ry());
+
+ e.appendChild(tmp);
+ }
+
+ return true;
+ }
+}
+
+bool Polygon::attributesFromDom(const QDomElement &e)
+{
+ if (e.isNull())
+ {
+ qDebug() << className() << "::attributesFromDom Error: NULL element passed.";
+ return false;
+ }
+ else
+ {
+ QDomElement child = e.firstChildElement("Point");
+
+ m_polygon.clear();
+
+ while(!child.isNull())
+ {
+ QPoint tmp(child.attribute("x", "0").toInt(), child.attribute("y", "0").toInt());
+
+ m_polygon.append(tmp);
+
+ child = child.nextSiblingElement("Point");
+ }
+
+ return true;
+ }
+}
+
+QString Polygon::className()
+{
+ return "Polygon";
+}
diff --git a/polygon.h b/polygon.h
index 6b76300..0a40947 100644
--- a/polygon.h
+++ b/polygon.h
@@ -18,6 +18,11 @@ public:
protected:
QPolygon m_polygon;
+
+ virtual bool attributesToDom(QDomDocument *doc, QDomElement &e);
+ virtual bool attributesFromDom(const QDomElement &e);
+ virtual QString className();
+
};
#endif // POLYGON_H
diff --git a/rectangle.cpp b/rectangle.cpp
index 1a58add..edc8749 100644
--- a/rectangle.cpp
+++ b/rectangle.cpp
@@ -40,23 +40,24 @@ void Rectangle::draw(QPainter *painter)
void Rectangle::move(const QPoint &oldPoint, const QPoint &newPoint)
{
- if(m_selected)
+ if (m_selected)
{
QPoint offset = newPoint - oldPoint;
QVector3D vecOld(oldPoint);
- if(vecOld.distanceToPoint(QVector3D(m_rectangle.topLeft())) < 5)
+
+ if (vecOld.distanceToPoint(QVector3D(m_rectangle.topLeft())) < 5)
{
m_rectangle.setTopLeft(m_rectangle.topLeft() + offset);
}
- else if(vecOld.distanceToPoint(QVector3D(m_rectangle.topRight())) < 5)
+ else if (vecOld.distanceToPoint(QVector3D(m_rectangle.topRight())) < 5)
{
m_rectangle.setTopRight(m_rectangle.topRight() + offset);
}
- else if(vecOld.distanceToPoint(QVector3D(m_rectangle.bottomLeft())) < 5)
+ else if (vecOld.distanceToPoint(QVector3D(m_rectangle.bottomLeft())) < 5)
{
m_rectangle.setBottomLeft(m_rectangle.bottomLeft() + offset);
}
- else if(vecOld.distanceToPoint(QVector3D(m_rectangle.bottomRight())) < 5)
+ else if (vecOld.distanceToPoint(QVector3D(m_rectangle.bottomRight())) < 5)
{
m_rectangle.setBottomRight(m_rectangle.bottomRight() + offset);
}
@@ -67,3 +68,45 @@ void Rectangle::move(const QPoint &oldPoint, const QPoint &newPoint)
}
}
}
+
+
+bool Rectangle::attributesToDom(QDomDocument *doc, QDomElement &e)
+{
+ if (e.isNull())
+ {
+ qDebug() << className() << "::attributesToDom Error: NULL element passed.";
+ return false;
+ }
+ else
+ {
+ e.setAttribute("x1", m_rectangle.topLeft().rx());
+ e.setAttribute("y1", m_rectangle.topLeft().ry());
+ e.setAttribute("x2", m_rectangle.bottomRight().rx());
+ e.setAttribute("y2", m_rectangle.bottomRight().ry());
+
+ return true;
+ }
+}
+
+bool Rectangle::attributesFromDom(const QDomElement &e)
+{
+ if (e.isNull())
+ {
+ qDebug() << className() << "::attributesFromDom Error: NULL element passed.";
+ return false;
+ }
+ else
+ {
+ m_rectangle.setTopLeft(QPoint(e.attribute("x1", "0").toInt(),
+ e.attribute("y1", "0").toInt()));
+ m_rectangle.setBottomRight(QPoint(e.attribute("x2", "0").toInt(),
+ e.attribute("y2", "0").toInt()));
+
+ return true;
+ }
+}
+
+QString Rectangle::className()
+{
+ return "Rectangle";
+}
diff --git a/rectangle.h b/rectangle.h
index cf29bb4..2c9ce05 100644
--- a/rectangle.h
+++ b/rectangle.h
@@ -16,6 +16,10 @@ public:
protected:
QRect m_rectangle;
+
+ virtual bool attributesToDom(QDomDocument *doc, QDomElement &e);
+ virtual bool attributesFromDom(const QDomElement &e);
+ virtual QString className();
};
#endif // RECTANGLE_H