====== 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(); }