initial import
[vym] / headingobj.cpp
diff --git a/headingobj.cpp b/headingobj.cpp
new file mode 100644 (file)
index 0000000..80d614a
--- /dev/null
@@ -0,0 +1,271 @@
+#include "headingobj.h"
+#include <qregexp.h>
+
+/////////////////////////////////////////////////////////////////
+// HeadingObj
+/////////////////////////////////////////////////////////////////
+HeadingObj::HeadingObj() : MapObj()
+{
+//    cout << "Const HeadingObj ()\n";
+    init ();
+}
+
+HeadingObj::HeadingObj(QGraphicsScene *s) :MapObj(s)
+{
+//    cout << "Const HeadingObj (s)\n";
+    init ();
+}
+
+HeadingObj::~HeadingObj()
+{
+//     cout << "Destr. HeadingObj "<<qPrintable(heading)<<endl;
+       while (!textline.isEmpty())
+               delete textline.takeFirst();
+}
+
+void HeadingObj::init()
+{
+    textwidth=40;
+    color=QColor ("black");
+    font=QFont();
+       heading="";
+}
+
+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));
+}
+
+//QGraphicsSimpleTextItem* HeadingObj::newLine(QString s)
+QGraphicsTextItem* HeadingObj::newLine(QString s)
+{
+    //QGraphicsSimpleTextItem *t=new QGraphicsSimpleTextItem (s,0,scene);
+    QGraphicsTextItem *t=new QGraphicsTextItem (s,0,scene);
+    t->setFont (font);
+    t->setZValue(Z_TEXT);
+       // TextItem
+    t->setDefaultTextColor(color);
+       // SimpleTextItem
+    //t->setBrush(color);
+    return t;
+}
+
+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>"))
+       {
+               QGraphicsTextItem *t=new QGraphicsTextItem ();
+               t->setFont (font);
+               t->setZValue(Z_TEXT);
+               t->setHtml (s);
+               t->setDefaultTextColor(color);
+               scene->addItem (t);
+               textline.append (t);
+               setVisibility (visible);
+               move (absPos.x(),absPos.y());
+               calcBBoxSize();
+               return;
+       }
+
+       // 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.search (s,i);
+               if (k>=0)
+               {
+                       br=re.cap(0).length();
+                       i=k;
+               } else
+                       i=s.find (" ",i,false);
+               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;
+                                               }
+                                       }
+                               } 
+                       }         
+               }                   
+    }
+       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::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();
+}
+