/** * @RDE_HEADER@ * $Id$ * $HeadURL$ * $Author$ */ #include "symbol_exporter.h" #include "primitive.h" #include "symbol_table.h" #include "attribute_data.h" #include "symbol_custom_graphics_item_group.h" // test #include #include #include #include #include #include #include #include #include #include #include #include #include #include namespace SymbologyXML { #define BOUNDING_RECT 423 #define HEADQUARTER_LINE 424 #define REDUCE_LINEWIDTH_F 4./5 // 80 % #define LINEWIDTH_FRAME_SOLID 0.04 #define LINEWIDTH_FRAME_DASHED_DOTTED 0.08 #define LINEWIDTH_HEADQUARTER 0.06 static const bool BLACK_AND_WHITE_DOTTED_LINE = true; static QFont* defaultFont = nullptr; static const QFont::StyleStrategy defaultStyleStrategy = QFont::PreferAntialias; bool isColorOfOwnForce(const QColor& color) { // Sind wir bei der 'eigenen' Partei? (Hack über die Farben) return ( ( (color.red() == 0xFF) && (color.green() == 0x0 ) && (color.blue() == 0x0 ) ) // color of team 'red' (0xFF0000) || ( (color.red() == 0xFF) && (color.green() == 0x7F) && (color.blue() == 0x7F) ) // lightcolor of team 'red' (0xFF7F7F) ); } void SymbolExporter::drawFrameSymbol(const Symbol& symbol, const SymbolTypes::AdditionalSymbolData& additionalData, QGraphicsScene* scene, const QColor& color, const QColor& fillColor, double z, bool antialias) { Q_UNUSED(antialias); SymbolTypes::t_affil affil = symbol.getAffil(); Primitive::t_linestyle linestyleSymbol = Primitive::SOLID; if((affil == SymbolTypes::ASSUMED_FRIEND) || (affil == SymbolTypes::SUSPECT) || (affil == SymbolTypes::PENDING)) { linestyleSymbol = Primitive::DOTTED; } else { if(additionalData.m_uncertainty == SymbolTypes::UNCERTAINTY_UNCERTAIN) { linestyleSymbol = Primitive::DOTTED; } else if(additionalData.m_state == SymbolTypes::STATE_ANTICIPATED) { linestyleSymbol = Primitive::DASHED; } } // Draw all primitives of the frame symbol QLinkedListp = symbol.getPrimitives(); QLinkedListIterator piter(p); while ( piter.hasNext() ) { Primitive prim = *piter.next(); double lineWidth = prim.getLineWidth(); if(lineWidth >= 0) { if(linestyleSymbol == Primitive::SOLID) { lineWidth = LINEWIDTH_FRAME_SOLID; } else { lineWidth = LINEWIDTH_FRAME_DASHED_DOTTED; } prim.setLineStyle(linestyleSymbol); } else { // lineWidth < 0 : prim.setLineStyle(Primitive::SOLID); } if (additionalData.m_filltype == SymbolTypes::FILLTYPE_OUTLINED) { prim.setLineWidth(lineWidth*2.0); } else { prim.setLineWidth(lineWidth); } bool isAttrib = true; // filltype: if(prim.fill()) { // prims with filltype == FILLED : e.g. small filled rectangles for t_dimen activity prim.setLineStyle(Primitive::SOLID); isAttrib = false; } else { prim.setFill(additionalData.m_filltype == SymbolTypes::FILLTYPE_FILLED); } QGraphicsItem *gitem = nullptr; if(BLACK_AND_WHITE_DOTTED_LINE && (linestyleSymbol == Primitive::DOTTED) && (prim.getLineStyle() == Primitive::DOTTED)) { // additional prim (white): Primitive prim2(prim); prim2.setLineStyle(Primitive::SOLID); prim2.setFill(false); gitem = SymbolExporter::drawPrimitive(prim2, Qt::white, fillColor, z, isAttrib); if(gitem) { scene->addItem(gitem); gitem->setZValue(z); } // current prim (black-dotted): gitem = SymbolExporter::drawPrimitive(prim, Qt::black, fillColor, z, isAttrib); } else { gitem = SymbolExporter::drawPrimitive(prim, color, fillColor, z, isAttrib); } if(gitem) { scene->addItem(gitem); gitem->setZValue(z); } } } // void SymbolExporter::drawFrameSymbol(const Symbol& symbol, ... void SymbolExporter::drawHeadquarterPrims(QGraphicsScene *scene, bool headquarter, SymbolTypes::t_dimen dimen, SymbolTypes::t_affil affil, const QColor& color) { QGraphicsItem *hqItem = nullptr; const auto items = scene->items(); for (QGraphicsItem *item : items) { if (item->data(HEADQUARTER_LINE).toBool()) { hqItem = item; break; } } if (hqItem) { scene->removeItem(hqItem); delete hqItem; } if (headquarter) { // headquarter: QGraphicsLineItem *hqLine = new QGraphicsLineItem(); QPen hqLinePen; hqLinePen.setWidthF(LINEWIDTH_HEADQUARTER); hqLinePen.setColor(color); hqLine->setPen(hqLinePen); hqLine->setData(HEADQUARTER_LINE, true); QRectF frameRect = Symbol::getSymbolFrameRect(dimen, affil); hqLine->setLine(frameRect.left(), frameRect.center().y(), frameRect.left(), -2.0); scene->addItem(hqLine); } } void SymbolExporter::drawSymbol(const Symbol& symbol, const SymbolTypes::t_symbolTableCont& symTableCont, QGraphicsScene* scene, const QColor& color, const QColor& fillColor, double z, bool isAttrib, bool antialias, QFont* font_p, QMap *mapItemPrimitives_p, bool drawBoundRect) { Q_UNUSED(fillColor); // If this Symbol should be tracked in the Primitives-Map, clear the map first if ( mapItemPrimitives_p ) { mapItemPrimitives_p->clear(); } // Draw all primitives (and ICONS/TEXTS) of the given Symbol QLinkedListp = symbol.getPrimitives(); QLinkedListIterator piter(p); while ( piter.hasNext() ) { Primitive *item = piter.next(); SymbolExporter::drawSymbolPrimitive(item, symTableCont, scene, item->getColor().isValid() ? item->getColor() : color, item->getColor().isValid() ? item->getColor() : color, z, isAttrib, mapItemPrimitives_p, drawBoundRect); } // while if ( symbol.getTextType() != Symbol::TEXT_UNDEFINED ) { #if defined (SYMBOL_TEXT_IN_BLACK) && (SYMBOL_TEXT_IN_BLACK == 1) // Sind wir bei der 'eigenen' Partei? (Hack über die Farben) if ( isColorOfOwnForce(color) ) { drawSymbolText(symbol, scene, Qt::black, antialias, font_p); } else { drawSymbolText(symbol, scene, color, antialias, font_p); } #else drawSymbolText(symbol, scene, color, antialias, font_p); #endif // #if defined (SYMBOL_TEXT_IN_BLACK)... } } // void SymbolExporter::drawSymbol(Symbol* symbol, SymbolTable* symTableSectorIcons_p...) void SymbolExporter::drawSymbolPrimitive(Primitive *primitive, const SymbolTypes::t_symbolTableCont& symTableCont, QGraphicsScene* scene, const QColor& color, const QColor& fillColor, double z, bool isAttrib, QMap *mapItemPrimitives_p, bool drawBoundRect) { QGraphicsItem *gitem = nullptr; if(primitive->type() == Primitive::ICON) { gitem = SymbolExporter::drawICON(*primitive, symTableCont, scene, color, fillColor, z, isAttrib, drawBoundRect); } else if(primitive->type() == Primitive::TEXT) { gitem = SymbolExporter::drawText(*primitive, symTableCont, scene, color, fillColor, z, isAttrib, drawBoundRect); } else { gitem = SymbolExporter::drawPrimitive(*primitive, color, fillColor, z, isAttrib, drawBoundRect); if(gitem) { scene->addItem(gitem); } } if(gitem) { if(!isAttrib) { gitem->setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable); } gitem->setSelected(false); gitem->setZValue(z); if(mapItemPrimitives_p) { mapItemPrimitives_p->operator[](gitem) = primitive; } } } #ifdef APP6C void SymbolExporter::drawSymbolText(const Symbol &symbol, QGraphicsScene* scene, const QColor& color, bool antialias, QFont* font_p) { // first check if we really need to draw text bool bEmpty = true; for (int i=0; bEmpty && i<(int)symbol.getTextType(); ++i) { bEmpty = symbol.getText(i+1).isEmpty(); } if(bEmpty) return; // Find a fixed Font, if possible QFont font = SymbolExporter::getMatchFont(font_p, antialias); // Font ist ausgewaehlt, weiter gehts: QFontMetricsF metrics(font); for (int i=0; i<(int)symbol.getTextType(); ++i) { QString txt = symbol.getText(i+1); if(txt.length()>0) { Symbol::t_alignment align = symbol.getTextAlign(i+1); QGraphicsSimpleTextItem *textItem = scene->addSimpleText(txt, font); textItem->setBrush(color); textItem->setZValue(0.9); // QRectF metricsRect = metrics.boundingRect(txt); // no effect // metricsRect.moveCenter(QPointF(0.0, 0.0)); // no effect double textHeight = metrics.height(); double textWidth = metrics.width(txt); double maxWidth, maxHeight, leftX, topY; if(i == 1) { maxWidth = 1.7; maxHeight = 0.8; } else { maxWidth = 1.4; maxHeight = 0.4; } if(align == Symbol::LEFT || align == Symbol::RIGHT) { maxWidth /= 2.0; } double scaleX = maxWidth / textWidth; double scaleY = maxHeight / textHeight; double scale = 1; if(scaleX > scaleY) { scale = scaleY; } else { scale = scaleX; } textItem->setTransform(QTransform::fromScale(scale, -scale), true); textHeight*=scale; textWidth*=scale; if(i == 0) { topY = 0.35+textHeight; } else if(i == 1) { topY = textHeight/2; } else { topY = -0.35; } switch (align) { case Symbol::LEFT: leftX = -0.7; break; case Symbol::RIGHT: leftX = 0.7-textWidth; break; case Symbol::CENTER: default: leftX = -textWidth/2.0; break; } textItem->setPos(leftX, topY); //////////////////////////////////////////////////////////////////////// // replaced by rotation in PixmapSymboCache: //////////////////////////////////////////////////////////////////////// // // rotation of 'text', // int rotAngle = 60; // textItem->setRotation(rotAngle); // angle is interpreted clockwise; // // Qt4.6 introduced setRotation Otherwise try: // // textItem->rotate(rotAngle); // angle is interpreted clockwise; // // textItem->setTransform( QTransform().rotate(rotAngle), true ); // angle is interpreted clockwise; // // QTransform transView; // transView.rotate(-rotAngle); // angle is interpreted counterclockwise // textItem->setPos( transView.map(QPointF(leftX,topY)) ); //////////////////////////////////////////////////////////////////////// } } // for } // void SymbolExporter::drawSymbolText(const Symbol &symbol, ... #else void SymbolExporter::drawSymbolText(const Symbol &symbol, QGraphicsScene* scene, const QColor& color, bool antialias, QFont* font_p) { // first check if we really need to draw text bool bEmpty = true; for (int i=0; bEmpty && i<(int)symbol.getTextType(); ++i) { bEmpty = symbol.getText(i+1).isEmpty(); } if(bEmpty) return; // Find a fixed Font, if possible QFont font = SymbolExporter::getMatchFont(font_p, antialias); // Font ist ausgewaehlt, weiter gehts: QFontMetricsF metrics(font); // TextBox Width double len = (double)symbol.maxStringLength(); double textBoxW = len* metrics.maxWidth(); // TextBox Height Symbol::t_text textType = symbol.getTextType(); double textBoxLineH = metrics.lineSpacing(); double textBoxH = (double)(textBoxLineH*textType + (int)textType-1); // Scale TextBox double maxWidth; switch (textType) { case Symbol::TEXT1: maxWidth = 1.7; break; case Symbol::TEXT2: maxWidth = 1.5; break; case Symbol::TEXT3: default: maxWidth = 1.3; break; } double scale = maxWidth/textBoxW; // Add Text QRectF textBox(0.0, 0.0, textBoxW, textBoxH); textBox.moveCenter(QPointF(0.0, 0.0)); for (int i=0; i<(int)textType; ++i) { QString txt = symbol.getText(i+1); Symbol::t_alignment align = symbol.getTextAlign(i+1); QGraphicsTextItem *textItem = scene->addText(txt, font); textItem->setDefaultTextColor(color); QRectF metricsRect = metrics.boundingRect(txt); metricsRect.moveCenter(QPointF(0.0, 0.0)); QPointF center = textItem->boundingRect().center(); textItem->setZValue(0.9); textItem->setTransform(QTransform::fromScale(scale, -scale), true); // Place horizontal according to alignment double moveX = -center.x(); switch (align) { case Symbol::LEFT: moveX = moveX-(metricsRect.left()-textBox.left()); break; case Symbol::RIGHT: moveX = moveX+(textBox.right()-metricsRect.right()); break; case Symbol::CENTER: default: // Do nothing, it's x-centered by default break; } moveX = moveX*scale; // Place vertical according to text-type double moveY = center.y(); switch (textType) { case Symbol::TEXT3: moveY = moveY - ((i-1)*metricsRect.height()); break; case Symbol::TEXT2: moveY = moveY - ((i==0?-1:1)*(metricsRect.height()/2.0)); break; case Symbol::TEXT1: default: // Do nothing, it's y-centered by default break; } moveY = moveY*scale; textItem->moveBy(moveX, moveY); } } // void SymbolExporter::drawSymbolText(const Symbol &symbol, ... #endif QFont SymbolExporter::getMatchFont(QFont* font_p, bool antialias) { QFont retFont; if(font_p) { retFont = fontMatch(*font_p); } else { if(!defaultFont) { defaultFont = new QFont(QStringLiteral("Monospace"), 10); defaultFont->setStyleStrategy(defaultStyleStrategy); QFont matchFont = fontMatch(*defaultFont); delete defaultFont; defaultFont = new QFont(matchFont); } retFont = *defaultFont; } QFont::StyleStrategy styleStrategy = QFont::PreferAntialias; if(!antialias) { styleStrategy = QFont::NoAntialias; } if(styleStrategy != retFont.styleStrategy()) { retFont.setStyleStrategy(styleStrategy); retFont = fontMatch(retFont); } retFont.setBold(true); return retFont; } QFont SymbolExporter::fontMatch(const QFont &font) { QFont retFont = font; if(!font.exactMatch()) { QFontDatabase fdb; QStringList fontFamilies = fdb.families(QFontDatabase::Latin); for (int i = 0; i < fontFamilies.size(); ++i) { QFont tmpFont(fontFamilies.at(i), 10); if ( tmpFont.fixedPitch() ) { retFont = tmpFont; break; } } } return retFont; } QGraphicsItem* SymbolExporter::redraw(QGraphicsItem *g, bool drawBoundRect) { Primitive *prim = g->data(primitiveKey).value(); if(prim->type() == Primitive::TEXT) { // Primitive::TEXT: CustomGraphicsItemGroup* ggroup = dynamic_cast(g); if(ggroup) { QPolygonF points = prim->getPoints(); if(points.size()!=2) { return nullptr; } ggroup->setTransform(QTransform()); ggroup->setPos(0, 0); const QList children = ggroup->childItems(); for(int i = children.size() - 1; i >=0 ; i--) { QGraphicsItem *child = children.at(i); child->setTransform(QTransform()); child->setPos(0, 0); if(child->data(BOUNDING_RECT).toBool()) { ggroup->removeFromGroup(child); delete child; } } QRectF wantedBox(points.at(0), points.at(1)); // prim->text kann auch mehrzeilig sein: int metricFlags = 0; QFontMetrics metrics(SymbolExporter::getMatchFont(nullptr, true)); // einzeilig war mal: QRectF boundingBox = // QRectF(0, 0, metrics.width(prim->text()), metrics.height()); QSize textSize = metrics.size(metricFlags, prim->text()); QRectF boundingBox = QRectF(0, 0, textSize.width(), textSize.height()); int baselinePixel = 0; if(prim->text().contains(QStringLiteral("\n"))) { baselinePixel = 2; } boundingBox.setHeight(boundingBox.height() + baselinePixel); qreal dx, dy, dtaken; dx = wantedBox.width() / boundingBox.width(); dy = wantedBox.height() / boundingBox.height(); dtaken = qMin(dx, dy); ggroup->moveBy(-boundingBox.width()*dtaken/2, boundingBox.height()*dtaken/2); ggroup->setTransform(QTransform::fromScale(dtaken, -dtaken), true); ggroup->moveBy(wantedBox.center().x(), wantedBox.center().y()); if(drawBoundRect) { QGraphicsRectItem *selectRect = new QGraphicsRectItem(); QPen rectpen(Qt::DotLine); rectpen.setColor(Qt::red); rectpen.setWidthF(0.01); selectRect->setData(BOUNDING_RECT, true); selectRect->setPen(rectpen); selectRect->setBrush(Qt::NoBrush); selectRect->setRect(wantedBox); ggroup->addToGroup(selectRect); } // rotate: double angle = prim->getRotation(); ggroup->setTransform(QTransform().rotate(angle), true); // rotation point is not the center of ggroup ! :-( // ggroup->update(); return ggroup; } } else if(prim->type() == Primitive::ICON) { // Primitive::ICON: CustomGraphicsItemGroup* ggroup = dynamic_cast(g); if(ggroup) { QPolygonF points = prim->getPoints(); if(points.size()!=2) { return nullptr; } const QList children = ggroup->childItems(); for(int i = children.size() - 1; i >=0 ; i--) { QGraphicsItem *child = children.at(i); if(child->data(BOUNDING_RECT).toBool()) { ggroup->removeFromGroup(child); delete child; } } ggroup->setTransform(QTransform()); ggroup->setPos(0, 0); QRectF wantedBox(points.at(0), points.at(1)); #ifdef NEVER bool scalingOfLinewidth = false; // false == linewidth will not be changed if (scalingOfLinewidth) { // war mal so: ( nur proportional !!!) : QRectF boundingBox = ggroup->boundingRect(); qreal dtaken = qMin(wantedBox.width() / boundingBox.width(), wantedBox.height() / boundingBox.height()); ggroup->setTransform(QTransform::fromScale(dtaken, dtaken), true); ggroup->moveBy(-boundingBox.center().x()*dtaken, -boundingBox.center().y()*dtaken); ggroup->moveBy(wantedBox.center().x(), wantedBox.center().y()); } else #endif { // let the linewith's be constant bool proport = !(prim->scalemode() == Primitive::Scalemode_Unproport); scaleGeometry(ggroup, wantedBox, proport); } if(drawBoundRect) { QGraphicsRectItem *selectRect = new QGraphicsRectItem(); QPen rectpen(Qt::DotLine); rectpen.setColor(Qt::red); rectpen.setWidthF(0.01); selectRect->setData(BOUNDING_RECT, true); selectRect->setPen(rectpen); selectRect->setBrush(Qt::NoBrush); selectRect->setRect(wantedBox); ggroup->addToGroup(selectRect); } // rotate: double angle = prim->getRotation(); QPointF centerF = ggroup->boundingRect().center(); ggroup->setTransform(QTransform()); ggroup->setTransform(QTransform().translate(centerF.x(), centerF.y()) .rotate(angle).translate(-centerF.x(), -centerF.y())); // ggroup->update(); return ggroup; } } else { // other Primitives: QGraphicsPathItem* pathItem = dynamic_cast(g); if(pathItem) { QPainterPath path = SymbolExporter::createPath(prim, false); pathItem->setPath(path); // rotate: double angle = prim->getRotation(); double cx = 0.0; double cy = 0.0; prim->getCenter(cx, cy); pathItem->setTransform(QTransform()); pathItem->setTransform(QTransform().translate(cx, cy).rotate(angle).translate(-cx, -cy)); // pathItem->update(); } } return g; } void SymbolExporter::scaleGeometry(QGraphicsItemGroup* ggroup, const QRectF &wantedBox, bool proport) { // test NGL::INGLLogger &mLogger = // test NGL::NGLLoggerBootstrap::getNGLRootLogger().getNGLLogger( "SymbolEditor" ); // try and try a scale, at least it seams as if its ok // and do not vis Qt-errors ! qreal last_scalex = -1; qreal scalex = 0; qreal scaley = scalex; QRectF boundingBox; int countWhile = 0; while((qAbs(last_scalex - scalex) > 0.001) && (countWhile < 10) && // max tries ((scalex < 0.999) || (scalex > 1.001))) { // dtaken should go to 1.000 // set new scalex, scaley: boundingBox = ggroup->boundingRect(); qreal dx, dy; dx = wantedBox.width() / boundingBox.width(); dy = wantedBox.height() / boundingBox.height(); last_scalex = scalex; if(proport) { scalex = qMin(dx, dy); scaley = scalex; } else { scalex = dx; scaley = dy; } // test ERROR_LOG(mLogger) << "scaleGeometry: countWhile = " << countWhile // test << "scalex = " << scalex ; SymbolExporter::tryScaleGeometry(ggroup, scalex, scaley); ++countWhile; } ggroup->moveBy(-boundingBox.center().x()*scalex, -boundingBox.center().y()*scaley); ggroup->moveBy(wantedBox.center().x(), wantedBox.center().y()); } void SymbolExporter::tryScaleGeometry(QGraphicsItemGroup* ggroup, qreal scalex, qreal scaley) { // items from group : QList gi_l; while(ggroup->childItems().size() > 0) { QGraphicsItem* gi_p = ggroup->childItems().at(0); gi_l << gi_p; ggroup->removeFromGroup(gi_p); } // QTransform matrix; matrix.scale(scalex, scaley); for(QGraphicsItem* gi_p : qAsConst(gi_l)) { QGraphicsPathItem* pathItem = dynamic_cast(gi_p); if(pathItem) { QPainterPath painterPath = matrix.map(pathItem->path()); pathItem->setPath(painterPath); } } // items to group : while(gi_l.size() > 0) { ggroup->addToGroup(gi_l.at(0)); gi_l.takeAt(0); } } QGraphicsItem* SymbolExporter::drawPrimitive(const Primitive& primitive, const QColor& color, const QColor& fillColor, double z, bool isAttrib, bool drawBoundRect) { Q_UNUSED(drawBoundRect); Primitive *item = const_cast(&primitive); QColor localColor = color; if (item->getColor().isValid()) { localColor = item->getColor(); localColor.setAlpha(color.alpha()); // Evtl. nur wenn mapItemPrimitives_p != 0 } QBrush brush; QPen pen; double pWidth = item->getLineWidth(); if ( isAttrib ) { if(item->fill()) { // filled : if(pWidth < 0.0) { pen.setColor(QColor(0,0,0,0)); pWidth = 0.0; } else if(pWidth == 0.0) { //pen.setColor(localColor); QColor blackAlpha = Qt::black; blackAlpha.setAlpha(localColor.alpha()); pen.setColor(blackAlpha); } else { pen.setColor(localColor); } } else { // outlined : pen.setColor(localColor); if(pWidth < 0.0) { return nullptr; } } brush.setColor(fillColor); } else { // !isAttrib : pen.setColor(localColor); brush.setColor(fillColor); } pen.setWidthF(pWidth); brush.setStyle(item->fill()?(Qt::SolidPattern):(Qt::NoBrush)); // pen style: switch (item->getLineStyle()) { case Primitive::DASHED_DOTTED: pen.setStyle(Qt::DashDotLine); break; case Primitive::DOTTED: pen.setDashPattern(QVector() << 1 << 1); // the same length for dot and space // war mal so: pen.setStyle(Qt::DotLine); break; case Primitive::DASHED: pen.setStyle(Qt::DashLine); break; case Primitive::SOLID: default: pen.setStyle(Qt::SolidLine); break; } // switch pen.setCapStyle(Qt::FlatCap); pen.setJoinStyle(Qt::BevelJoin); QPainterPath qpath = SymbolExporter::createPath(item, isAttrib); if ( !qpath.isEmpty() ) { QGraphicsPathItem *pathItem = new QGraphicsPathItem(qpath); QVariant data = QVariant::fromValue(item); pathItem->setData(primitiveKey, data); // primitiveKey=42 from symbolexporter.h pathItem->setPen(pen); pathItem->setBrush(brush); // rotate: double angle = item->getRotation(); double cx, cy; item->getCenter(cx, cy); if(angle != 0.0) { pathItem->setTransform(QTransform()); pathItem->setTransform(QTransform().translate(cx, cy).rotate(angle).translate(-cx, -cy)); } // pathItem->setZValue(z); return pathItem; } // if ( !qpath.isEmpty() ) return nullptr; } // SymbolExporter::drawPrimitive QGraphicsItem* SymbolExporter::drawICON(const Primitive& primitive, const SymbolTypes::t_symbolTableCont& symTableCont, QGraphicsScene* scene, const QColor& color, const QColor& fillColor, double z, bool isAttrib, bool drawBoundRect) { if ( ! scene) return nullptr; CustomGraphicsItemGroup * ggroup = nullptr; Primitive *primitive_p = const_cast(&primitive); if(primitive_p->type() == Primitive::ICON) { SymbolTypes::t_sectoricon primIconId = (SymbolTypes::t_sectoricon)primitive_p->icon(); SymbolTypes::t_icon_type iconType = primitive_p->iconType(); SymbolTable* symTableSectorIcons_p = nullptr; if ( (iconType>= 0) && (iconType < SymbolTypes::ICON_TYPE_END) && (symTableCont.size() == SymbolTypes::ICON_TYPE_END) ) { symTableSectorIcons_p = symTableCont[iconType]; } // endgueltige id des (Sub-)Symbols ermitteln. // Dazu je nach iconType den passenden Offset einbezuiehen: int tmpID = -1; switch (iconType) { case SymbolTypes::ICON_TYPE_SECTOR_ICON: tmpID = SymbolTable::getSectorIconSymbolID(primIconId); break; case SymbolTypes::ICON_TYPE_INTRINSIC_MOBILITY: tmpID = SymbolTable::getIntrinsicMobilitySymbolID( (SymbolTypes::t_intrinsicmob)primIconId ); break; case SymbolTypes::ICON_TYPE_VEHICLE: tmpID = SymbolTable::getVehicleSymbolID( (SymbolTypes::t_vehicle)primIconId ); break; case SymbolTypes::ICON_TYPE_ARMING: tmpID = SymbolTable::getArmingSymbolID( (SymbolTypes::t_arming)primIconId ); break; case SymbolTypes::ICON_TYPE_MISC: tmpID = SymbolTable::getMiscSymbolID( (SymbolTypes::t_misc)primIconId ); break; case SymbolTypes::ICON_TYPE_UNDEFINED: case SymbolTypes::ICON_TYPE_END: { // emtpy - avoiding compiler warning } } // switch // Und nun mit der endgueltige id des (Sub-)Symbols den passdenden SymboTable // um das (Sub-)Symbol bitten: if ( symTableSectorIcons_p && symTableSectorIcons_p->contains(tmpID) ) { Symbol *secIconSymbol = new Symbol(*(symTableSectorIcons_p->value(tmpID))); ggroup = new CustomGraphicsItemGroup(); scene->addItem(ggroup); QLinkedListplist = secIconSymbol->getPrimitives(); // linewidth: double resultLinewidth = primitive_p->getLineWidth(); if(resultLinewidth < 0) { QLinkedListIterator piterlw(plist); while(piterlw.hasNext()) { Primitive *subPrim = piterlw.next(); if(subPrim->getLineWidth() > resultLinewidth) { resultLinewidth = subPrim->getLineWidth(); } } if(resultLinewidth < 0) { resultLinewidth = 0; } if(primitive_p->position() != SymbolTypes::SECTORMAIN) { resultLinewidth = resultLinewidth * REDUCE_LINEWIDTH_F; } if(primitive_p->rectpos() == SymbolTypes::SECTOR_RECTPOS_LARGE) { resultLinewidth = resultLinewidth * 2; } primitive_p->setLineWidth(resultLinewidth); } // :linewidth QLinkedListIterator piter(plist); while ( piter.hasNext() ) { Primitive *prim = piter.next(); if(prim->getLineWidth() > 0) { prim->setLineWidth(primitive_p->getLineWidth()); } QGraphicsItem *gitem = SymbolExporter::drawPrimitive(*prim, color, fillColor, z, isAttrib); if(gitem) { gitem->setData(primitiveKey, QVariant()); ggroup->addToGroup(gitem); } } // while ggroup->setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable); ggroup->setSelected(false); QVariant temp; temp.setValue(primitive_p); ggroup->setData(primitiveKey, temp); redraw(ggroup, drawBoundRect); ggroup->setSelected(false); ggroup->setZValue(z); delete secIconSymbol; }// if ( symTableSectorIcons_p.contains(tmpID) ) } // if(primitive_p->type() == Primitive::ICON) return ggroup; } // QGraphicsItem* SymbolExporter::drawICON QGraphicsItem* SymbolExporter::drawText(const Primitive &primitive, const SymbolTypes::t_symbolTableCont& symTableCont, QGraphicsScene* scene, const QColor& color, const QColor& fillColor, double z, bool isAttrib, bool drawBoundRect) { Q_UNUSED(symTableCont); Q_UNUSED(fillColor); Q_UNUSED(isAttrib); Q_UNUSED(drawBoundRect); if ( ! scene) return nullptr; QColor finalColor = color; #if defined (SYMBOL_TEXT_IN_BLACK) && (SYMBOL_TEXT_IN_BLACK == 1) // Sind wir bei der 'eigenen' Partei? (Hack über die Farben) if ( isColorOfOwnForce(color) ) { finalColor = Qt::black; } #endif // #if defined (SYMBOL_TEXT_IN_BLACK)... CustomGraphicsItemGroup * ggroup = nullptr; Primitive *primitive_p = const_cast(&primitive); if(primitive_p->type() == Primitive::TEXT) { ggroup = new CustomGraphicsItemGroup(); scene->addItem(ggroup); QGraphicsSimpleTextItem *gitem = new QGraphicsSimpleTextItem(); gitem->setBrush(finalColor); gitem->setFont(SymbolExporter::getMatchFont(nullptr, true)); gitem->setText(primitive_p->text()); ggroup->addToGroup(gitem); ggroup->setFlags(QGraphicsItem::ItemIsSelectable|QGraphicsItem::ItemIsMovable); ggroup->setSelected(false); QVariant temp; temp.setValue(primitive_p); ggroup->setData(primitiveKey, temp); // primitiveKey=42 from symbolexporter.h redraw(ggroup, drawBoundRect); ggroup->setSelected(false); ggroup->setZValue(z); } return ggroup; } // QGraphicsItem* SymbolExporter::drawText QPainterPath SymbolExporter::createPath(const Primitive* primitive_p, bool isAttrib) { QPainterPath qpath; double w, h, xmin, ymin; QPolygonF points = primitive_p->getPoints(); switch (primitive_p->type()) { case Primitive::ELLIPSE : { w = fabs(points.at(0).x()-points.at(1).x()); h = fabs(points.at(0).y()-points.at(1).y()); xmin = std::min(points.at(0).x(), points.at(1).x()); ymin = std::min(points.at(0).y(), points.at(1).y()); if ( primitive_p->closed() || (primitive_p->getExtent() >= 360.0) ) { qpath.addEllipse(xmin, ymin, w, h); } else { if ( primitive_p->fill() && !isAttrib ) { qpath.moveTo(xmin+(w/2.0), ymin+(h/2.0)); } else { qpath.arcMoveTo(xmin, ymin, w, h, -(primitive_p->getStartAngle()) ); } qpath.arcTo(xmin, ymin, w, h, -(primitive_p->getStartAngle()), -(primitive_p->getExtent()) ); } } break; case Primitive::LINE : { qpath.moveTo(points.at(0)); qpath.lineTo(points.at(1)); } break; case Primitive::POLYGON : { qpath.addPolygon(points); if ( primitive_p->closed() ) { qpath.closeSubpath(); } } break; case Primitive::RECT : { // TODO: QRectF rect(points.at(0), points.at(1)) ?? w = fabs(points.at(0).x()-points.at(1).x()); h = fabs(points.at(0).y()-points.at(1).y()); xmin = std::min(points.at(0).x(), points.at(1).x()); ymin = std::min(points.at(0).y(), points.at(1).y()); qpath.addRect(xmin, ymin, w, h); } break; default : break; } return qpath; } // QPainterPath SymbolExporter::createPath(Primitive* primitive, bool isAttrib) Primitive *SymbolExporter::newPrimitiveICON(SymbolTypes::t_icon_type iconType, SymbolTypes::t_sector_position pos, SymbolTypes::t_sector_rectpos rectpos, int id) { Primitive *p = new Primitive(Primitive::ICON); p->setIcon(id); p->setIconType(iconType); QRectF rect = SymbolTypes::getDefaultRect(pos, rectpos); QPolygonF poly; poly.append(rect.topLeft()); poly.append(rect.bottomRight()); p->setPoints(poly); p->setPosition(pos); p->setRectpos(rectpos); p->setLineWidth(-1); // will be set in drawICON return p; } Symbol *SymbolExporter::newSecIconSymbol(const SymbolTypes::t_symbolTableCont& symTableCont, SymbolTypes::t_icon_type iconType, int iconId) { if(iconId == SymbolTypes::SECICON_UNDEFINED) { // undefined return nullptr; } SymbolTable* symTableSectorIcons_p = nullptr; if((iconType>= 0) && (iconType < SymbolTypes::ICON_TYPE_END) && (symTableCont.size() == SymbolTypes::ICON_TYPE_END)) { symTableSectorIcons_p = symTableCont[iconType]; } int tmpID = -1; switch (iconType) { case SymbolTypes::ICON_TYPE_SECTOR_ICON: tmpID = SymbolTable::getSectorIconSymbolID((SymbolTypes::t_sectoricon)iconId); break; case SymbolTypes::ICON_TYPE_INTRINSIC_MOBILITY: tmpID = SymbolTable::getIntrinsicMobilitySymbolID( (SymbolTypes::t_intrinsicmob)iconId ); break; case SymbolTypes::ICON_TYPE_VEHICLE: tmpID = SymbolTable::getVehicleSymbolID( (SymbolTypes::t_vehicle)iconId ); break; case SymbolTypes::ICON_TYPE_ARMING: tmpID = SymbolTable::getArmingSymbolID( (SymbolTypes::t_arming)iconId ); break; case SymbolTypes::ICON_TYPE_MISC: tmpID = SymbolTable::getMiscSymbolID( (SymbolTypes::t_misc)iconId ); break; case SymbolTypes::ICON_TYPE_UNDEFINED: case SymbolTypes::ICON_TYPE_END: break; } // switch if(!symTableSectorIcons_p || !symTableSectorIcons_p->contains(tmpID)) { return nullptr; } Symbol *secIconSymbol = new Symbol(*(symTableSectorIcons_p->value(tmpID))); return secIconSymbol; } }; // namespace SymbologyXML