Files
qt5-legatus-legacy/Lts/Viewer/SituationMap/SymbologyXML/symbol_exporter.cpp
T
2026-08-13 18:33:10 +02:00

1138 lines
35 KiB
C++
Executable File

/**
* @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 <NGLLogger/NGLLoggerBootstrap.h>
#include <QtDebug>
#include <QBrush>
#include <QBuffer>
#include <QFont>
#include <QFontDatabase>
#include <QFontMetrics>
#include <QGraphicsPathItem>
#include <QGraphicsScene>
#include <QMetaType>
#include <QPainter>
#include <QPainterPath>
#include <QPen>
#include <cmath>
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
QLinkedList<Primitive*>p = symbol.getPrimitives();
QLinkedListIterator<Primitive*> 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<QGraphicsItem*, Primitive*> *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
QLinkedList<Primitive*>p = symbol.getPrimitives();
QLinkedListIterator<Primitive*> 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<QGraphicsItem*, Primitive*> *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<Primitive*>();
if(prim->type() == Primitive::TEXT) {
// Primitive::TEXT:
CustomGraphicsItemGroup* ggroup = dynamic_cast<CustomGraphicsItemGroup*>(g);
if(ggroup) {
QPolygonF points = prim->getPoints();
if(points.size()!=2) {
return nullptr;
}
ggroup->setTransform(QTransform());
ggroup->setPos(0, 0);
const QList<QGraphicsItem*> 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<qreal>(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<CustomGraphicsItemGroup*>(g);
if(ggroup) {
QPolygonF points = prim->getPoints();
if(points.size()!=2) {
return nullptr;
}
const QList<QGraphicsItem*> 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<qreal>(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<QGraphicsPathItem*>(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<qreal>(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<QGraphicsItem*> 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<QGraphicsPathItem*>(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*>(&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<qreal>() << 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*>(&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);
QLinkedList<Primitive*>plist = secIconSymbol->getPrimitives();
// linewidth:
double resultLinewidth = primitive_p->getLineWidth();
if(resultLinewidth < 0) {
QLinkedListIterator<Primitive*> 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<Primitive*> 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*>(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*>(&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*>(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