#include <QDebug>
#include <QRegExp>
#include <QGraphicsScene>
#include "headingobj.h"
extern bool debug;
/////////////////////////////////////////////////////////////////
// HeadingObj
/////////////////////////////////////////////////////////////////
HeadingObj::HeadingObj(QGraphicsItem *parent) :MapObj(parent)
{
//qDebug() << "Const HeadingObj (s) ";
init ();
}
HeadingObj::~HeadingObj()
{
// qDebug() << "Destr. HeadingObj "<<heading;
while (!textline.isEmpty())
delete textline.takeFirst();
}
void HeadingObj::init()
{
textwidth=40;
color=QColor ("black");
font=QFont();
heading="";
angle=0;
}
void HeadingObj::copy(HeadingObj *other)
{
MapObj::copy (other);
textwidth=other->textwidth;
color=other->color;
font=other->font;
setText (other->text() );
}
void HeadingObj::move(double x, double y)
{
MapObj::move(x,y);
qreal h; // height of a textline
qreal ho; // offset of height while drawing all lines
if (!textline.isEmpty() )
h=textline.first()->boundingRect().height();
else
h=2;
ho=0;
for (int i=0; i<textline.size(); ++i)
{
textline.at(i)->setPos(x,y+ho);
ho=ho+h;
}
}
void HeadingObj::moveBy(double x, double y)
{
move (x+absPos.x(),y+absPos.y() );
}
void HeadingObj::positionBBox()
{
bbox.setX (absPos.x());
bbox.setY (absPos.y());
}
void HeadingObj::calcBBoxSize()
{
qreal w=0;
qreal h=0;
// Using Backspace an empty heading might easily be created, then there
// would be textline.first()==NULL This can be worked around by the following, but
// then no selection would be visible, thus we prevent it in ::setText()
if (!textline.isEmpty() )
{
for (int i=0; i<textline.size(); i++)
{
h+=textline.at(i)->boundingRect().height();
if (w<textline.at(i)->boundingRect().width() )
w=textline.at(i)->boundingRect().width();
}
}
bbox.setSize (QSizeF(w,h));
}
QGraphicsTextItem* HeadingObj::newLine(QString s)
{
QGraphicsTextItem *t=new QGraphicsTextItem (s,parentItem());
t->setFont (font);
t->setZValue(dZ_TEXT);
t->setDefaultTextColor(color);
t->setRotation (angle);
return t;
}
void HeadingObj::setTransformOriginPoint (const QPointF & p)
{
for (int i=0; i<textline.size(); i++)
{
textline.at(i)->setTransformOriginPoint (p);
}
}
void HeadingObj::setRotation (const qreal &a)
{
angle=a;
for (int i=0; i<textline.size(); i++)
textline.at(i)->setRotation (angle);
}
qreal HeadingObj::getRotation()
{
return angle;
}
void HeadingObj::setText (QString s)
{
heading=s;
// remove old textlines and prepare generating new ones
while (!textline.isEmpty())
delete textline.takeFirst();
if (s.startsWith("<html>")||
s.startsWith("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.0//EN\" \"http://www.w3.org/TR/REC-html40/strict.dtd\">")
)
{
QGraphicsTextItem *t=new QGraphicsTextItem ();
t->setFont (font);
t->setZValue(dZ_TEXT);
t->setHtml (s);
t->setDefaultTextColor(color);
t->setRotation (angle);
scene()->addItem (t);
textline.append (t);
} else
{
// prevent empty textline, so at least a small selection stays
// visible for this heading
if (s.length()==0) s=" ";
int i=0; // index for actual search for ws
int j=0; // index of last ws
int k=0; // index of "<br>" or similar linebreak
int br=0; // width of found break, e.g. for <br> it is 4
QRegExp re("<br.*/>");
re.setMinimal (true);
// set the text and wrap lines
while (s.length()>0)
{
// ok, some people wanted manual linebreaks, here we go
k=re.indexIn (s,i);
if (k>=0)
{
br=re.cap(0).length();
i=k;
} else
i=s.indexOf (" ",i);
if (i<0 && j==0)
{ // no ws found at all in s
// append whole s
textline.append (newLine(s));
s="";
} else
{
if (i<0 && j>0)
{ // no ws found in actual search
if (s.length()<=textwidth)
{
textline.append (newLine(s));
s="";
} else
{
textline.append (newLine(s.left(j)));
s=s.mid(j+1,s.length());
j=0;
}
} else
{
if (i>= 0 && i<=static_cast <int> (textwidth))
{ // there is a ws in textwidth
if (br>0)
{
// here is a linebreak
textline.append (newLine(s.left(i)));
s=s.mid(i+br,s.length());
i=0;
j=0;
br=0;
} else
{
j=i;
i++;
}
} else
{
if (i>static_cast <int> (textwidth) )
{
if (j>0)
{ // a ws out of textwidth, but we have also one in
textline.append (newLine(s.left(j)));
s=s.mid(j+1,s.length());
i=0;
j=0;
} else
{ // a ws out of text, but none in
textline.append (newLine(s.left(i)));
s=s.mid(i+1,s.length());
i=0;
}
}
}
}
}
}
} // ASCII heading with multiple lines
setVisibility (visible);
move (absPos.x(),absPos.y());
calcBBoxSize();
}
QString HeadingObj::text ()
{
return heading;
}
void HeadingObj::setFont (QFont f)
{
if (font!=f)
{
font=f;
setText (text());
}
}
QFont HeadingObj::getFont()
{
return font;
}
void HeadingObj::setColor (QColor c)
{
if (color!=c)
{
color=c;
for (int i=0; i<textline.size(); ++i)
// TextItem
textline.at(i)->setDefaultTextColor(c);
// SimpleTextItem
//textline.at(i)->setBrush(c);
}
}
QColor HeadingObj::getColor()
{
return color;
}
void HeadingObj::setZValue (double z)
{
for (int i=0; i<textline.size(); ++i)
textline.at(i)->setZValue (z);
}
void HeadingObj::setVisibility (bool v)
{
MapObj::setVisibility(v);
for (int i=0; i<textline.size(); ++i)
if (v)
textline.at(i)->show();
else
textline.at(i)->hide();
}
qreal HeadingObj::getHeight ()
{
return bbox.height();
}
qreal HeadingObj::getWidth()
{
return bbox.width();
}