====== Uložení do XML souboru ======
Jeste neumime obrazek editorat, misto toho zkusime cteni a zapisovani do souboru.
Priklad souboru abc.xml, ve kterem je ulozen popis dvou elips a jednoho obdelniku.
Nejprve si popiseme ukladani do souboru - bude snad prehlednejsi nez cteni souboru.
( Muzete se podivat na tutorial: http://www.bogotobogo.com/Qt/Qt5_QtXML_QDomDocument_QDomElement.php )
Do menu "File" na polozku "Save" pripojime nasledujici funkci. \\
**QFileDialog::getSaveFileName** zobrazi dialog a necha uzivatele vybrat jmeno pro ukladany soubor. \\
Pokud by uzivatel ukoncil dialog a nevybral jmeno souboru bude v promenn **fileName** prazdny retezec.
void MainWindow::on_actionSave_triggered ()
{
QString fileName = QFileDialog::getSaveFileName (this, "Save file");
if (fileName != "")
saveFile (fileName);
}
Funkce **saveFile** otevre soubor pro zapis. \\
Pokud se soubor povede otevrit, pripoji na soubor objekt typu **QXmlStreamWriter**. \\
QXmlStreamWriter nam vyrazne usnadni vytvareni XML souboru.
void MainWindow::saveFile (QString fileName)
{
QFile f (fileName);
if (f.open (QFile::WriteOnly))
{
QXmlStreamWriter w (&f);
writeXml (w, scene);
}
}
Fuknce **writeXml** je na konci souboru io.cc \\
Stream writer se neustale predava odkazem **&**, tj. pracujeme stale se stejnym stream writerem. \\
Funkce **writeBegin** vytvori povnny uvod a otevre element/znacku ** \\
Potom **writeXml** v cyklu projde prvky graficke sceny. \\
Prvky sceny jsou odvozene z typu ** QGraphicsItem**. \\
My si vybereme jen prvky, ktere nejsou vnorene do jinych grafickych prvku.
#include
void writeBegin (QXmlStreamWriter & w)
{
w.setAutoFormatting (true);
w.writeStartDocument ();
w.writeStartElement ("data");
}
void writeEnd (QXmlStreamWriter & w)
{
w.writeEndElement(); // end of data
w.writeEndDocument();
}
void writeXml (QXmlStreamWriter & w, QGraphicsScene * scene)
{
writeBegin (w);
for (QGraphicsItem * item : scene->items (Qt::AscendingOrder))
{
if (item->parentItem() == nullptr)
writeItem (w, item);
}
writeEnd (w);
}
====== Určení typu jednotlivých grafických prvků ======
Pomocna funkce **itemType** urci jmeno pouzivane v elementech , atd. \\
Parametr item je ukazatel na **QGraphicsItem** z ktereho jsou odvozeny jine typy, napr. QGraphicsEllipseItem. \\
Priblizne takto :
class QGraphicsItem
{
};
class QAbstractGraphicsShapeItem : public QGraphicsItem
{
};
class QGraphicsEllipseItem : public QAbstractGraphicsShapeItem
{
};
* QGraphicsItem
* QAbstractGraphicsShapeItem
* QGraphicsEllipseItem
Přetypování z odvozene tridy na nadrazenou je v C++ automaticke. \\
Přetypování z nadrazene tridy na odvozenou se nemusi vzdy podarit. \\
Výraz **dynamic_cast** zkusi pretypovat ukazatel a pokud je pretypovani nepodari vrati **nullptr**.
QGraphicsItem * item; // nejaky neznamy objekt, mozna i nullptr
QGraphicsEllipseItem * e = dynamic_cast < QGraphicsEllipseItem * > (item);
if (e != nullptr)
{
/* item je ellipsa, pretypovani se povedlo */
}
A zde je slibovana funkce itemType.
QString itemType (QGraphicsItem * item)
{
QString result = "node";
if (dynamic_cast < QGraphicsRectItem * > (item) != nullptr)
result = "rectangle";
if (dynamic_cast < QGraphicsEllipseItem * > (item) != nullptr)
result = "ellipse";
if (dynamic_cast < QGraphicsLineItem * > (item) != nullptr)
result = "line";
return result;
}
====== Ukládání jednotlivých grafických prvků ======
Funkce **writeItem** vytvori novy XML element, napr. \\
...
Ulozi jednotlive atributy ** x = **, ** y == ** \\
Zjisti zda je prvek typu **QAbstractGraphicsShapeItem**, pokud ano muze ziskat a ulozit vlastnosti **pen** a ** brush**.
if (QAbstractGraphicsShapeItem * shape = dynamic_cast < QAbstractGraphicsShapeItem * > (item))
{
/* promenna shape je deklarovana uvnitr if ( ),
je inicializovana pomoci dynamic_cast
a existuje jen vramci slozenych zavarok, kde je tento komentar. */
}
Pokud prvek obsahuje vnorene prvky, vypiseme vnorene prvky. \\
( v predesle ukazce XML souboru )
for (QGraphicsItem * t : item->childItems ())
writeItem (w, t);
Nakonec uzavreme element, napr pomoci **writeEndElement**.
void writeItem (QXmlStreamWriter & w, QGraphicsItem * item)
{
w.writeStartElement (itemType (item));
w.writeAttribute ("name", item->toolTip());
w.writeAttribute ("x", QString::number ( item->x() ));
w.writeAttribute ("y", QString::number ( item->y() ));
if (QAbstractGraphicsShapeItem * shape = dynamic_cast < QAbstractGraphicsShapeItem * > (item))
{
w.writeAttribute ("pen", penToString (shape->pen()));
w.writeAttribute ("brush", brushToString (shape->brush()));
if (QGraphicsRectItem * r = dynamic_cast < QGraphicsRectItem * > (shape))
{
w.writeAttribute ("width", QString::number ( r->rect().width() ));
w.writeAttribute ("height", QString::number ( r->rect().height() ));
}
if (QGraphicsEllipseItem * e = dynamic_cast < QGraphicsEllipseItem * > (shape))
{
w.writeAttribute ("width", QString::number ( e->rect().width() ));
w.writeAttribute ("height", QString::number ( e->rect().height() ));
}
}
for (QGraphicsItem * t : item->childItems ())
writeItem (w, t);
w.writeEndElement();
}