#include "PicSceneLoader.h" #include "picscene.h" #include "pictextitem.h" #include "PicImageItem.h" #include "PicDateItem.h" #include "PicScheduleShiftItem.h" #include "piccodeitem.h" #include "PicCounterItem.h" #include #include #include #include #include #include #include #include namespace { PicTextItem* createSceneItem(SourceType sourceType) { switch (sourceType) { case IMAGE: return new PicImageItem(); case DATETIME: return new PicDateItem(); case SCHEDULE_SHIFT: return new PicScheduleShiftItem(); case CODE: return new PicCodeItem(); case COUNTER: return new PicCounterItem(); case TEXT: case UNKNOWN: default: return new PicTextItem(nullptr, nullptr, sourceType); } } SourceType sourceTypeFromAttrs(const QXmlStreamAttributes& attrs) { if (!attrs.hasAttribute("sourceType")) { return SourceType::UNKNOWN; } bool ok = false; int value = attrs.value("sourceType").toInt(&ok); if (!ok) { return SourceType::UNKNOWN; } if (value < SourceType::UNKNOWN || value > SourceType::COUNTER) { return SourceType::UNKNOWN; } return static_cast(value); } bool parseVbFileElement(QXmlStreamReader& reader, PicScene* scene) { float posX = 0.0f; float posY = 0.0f; bool condition = false; int catchStartValue = -1; int catchValue = -1; QXmlStreamAttributes itemAttrs; QString htmlCData; while (!reader.atEnd()) { QXmlStreamReader::TokenType token = reader.readNext(); if (token == QXmlStreamReader::StartElement) { const QString elementName = reader.name().toString(); if (elementName == "pointer_x") { posX = reader.readElementText().toDouble(); } else if (elementName == "pointer_y") { posY = reader.readElementText().toDouble(); } else if (elementName == "Condition") { condition = reader.readElementText().toInt() != 0; } else if (elementName == "CatchStartValue") { catchStartValue = reader.readElementText().toInt(); } else if (elementName == "CatchValue") { catchValue = reader.readElementText().toInt(); } else if (elementName == "itemAttrs") { itemAttrs = reader.attributes(); reader.skipCurrentElement(); } else if (elementName == "html_src") { reader.skipCurrentElement(); } else { reader.skipCurrentElement(); } } else if (reader.isCDATA()) { htmlCData += reader.text().toString(); } else if (token == QXmlStreamReader::EndElement && reader.name() == "VBfile") { break; } } SourceType sourceType = sourceTypeFromAttrs(itemAttrs); PicTextItem* item = createSceneItem(sourceType); if (!item) { qWarning() << "PicSceneLoader: skip invalid VBfile item"; return true; } item->setAttrs(itemAttrs); item->setPos(posX, posY); item->SpecialConditions = condition; item->CatchCnt1StartValue = catchStartValue; item->CatchCnt1CurrValue = catchValue; if (!htmlCData.isEmpty()) { item->setHtml(htmlCData); } scene->addItem(item); return true; } } // namespace namespace PicSceneLoader { PicScene* createSceneFromFile(const QString& xmlFilename) { QFile file(xmlFilename); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { qWarning() << "PicSceneLoader: failed to open" << xmlFilename << file.errorString(); return nullptr; } QXmlStreamReader reader(&file); PicScene* scene = new PicScene(); while (!reader.atEnd()) { reader.readNext(); if (reader.isStartElement() && reader.name() == "VBfiles") { while (reader.readNextStartElement()) { if (reader.name() == "VBfile") { if (!parseVbFileElement(reader, scene)) { delete scene; return nullptr; } } else { reader.skipCurrentElement(); } } } } if (reader.hasError()) { qWarning() << "PicSceneLoader: XML parse error" << reader.errorString() << "at" << reader.lineNumber() << ":" << reader.columnNumber(); delete scene; return nullptr; } return scene; } QImage previewSceneFromFile(const QString &xmlFilename) { QScopedPointer scene(createSceneFromFile(xmlFilename)); if (!scene) { return QImage(); } QRectF contentRect = scene->itemsBoundingRect(); if (!contentRect.isValid() || contentRect.isEmpty()) { return QImage(1, 1, QImage::Format_ARGB32_Premultiplied); } QSize imageSize(qMax(1, int(std::ceil(contentRect.width()))), qMax(1, int(std::ceil(contentRect.height())))); QImage image(imageSize, QImage::Format_ARGB32_Premultiplied); image.fill(Qt::transparent); QPainter painter(&image); painter.setRenderHint(QPainter::Antialiasing, true); painter.setRenderHint(QPainter::SmoothPixmapTransform, true); scene->render(&painter, QRectF(QPointF(0, 0), imageSize), contentRect); painter.end(); return image; } } // namespace PicSceneLoader