File indexing completed on 2024-04-21 04:20:16

0001 /***************************************************************************
0002                           kimearea.cpp  -  description
0003                              -------------------
0004     begin                : Thu Jun 14 2001
0005     copyright            : (C) 2001 by Jan Schaefer
0006     email                : janschaefer@users.sourceforge.net
0007  ***************************************************************************/
0008 
0009 /***************************************************************************
0010  *                                                                         *
0011  *   This program is free software; you can redistribute it and/or modify  *
0012  *   it under the terms of the GNU General Public License as published by  *
0013  *   the Free Software Foundation; either version 2 of the License, or     *
0014  *   (at your option) any later version.                                   *
0015  *                                                                         *
0016  ***************************************************************************/
0017 
0018 #include "kimearea.h"
0019 
0020 #include <QBitmap>
0021 #include <QBrush>
0022 #include <QColor>
0023 #include <QImage>
0024 #include <QPainter>
0025 #include <QPalette>
0026 #include <QPen>
0027 #include <QPixmap>
0028 #include <QPolygon>
0029 
0030 #include "kimagemapeditor_debug.h"
0031 
0032 #include "kimecommon.h"
0033 
0034 
0035 // The size of Selection Points
0036 
0037 SelectionPoint::SelectionPoint(QPoint p, QCursor c)
0038 {
0039   point = p;
0040   state = Normal;
0041   _cursor = c;
0042 }
0043 
0044 SelectionPoint::~SelectionPoint() {
0045 }
0046 
0047 void SelectionPoint::setState(SelectionPoint::State s) {
0048   state = s;
0049 }
0050 
0051 SelectionPoint::State SelectionPoint::getState() const {
0052   return state;
0053 }
0054 
0055 void SelectionPoint::setPoint(QPoint p) {
0056   point = p;
0057 }
0058 
0059 void SelectionPoint::translate(int dx, int dy) {
0060   point += QPoint(dx,dy);
0061 }
0062 
0063 
0064 QPoint SelectionPoint::getPoint() const {
0065   return point;
0066 }
0067 
0068 QRect SelectionPoint::getRect() const {
0069   QRect r(0,0,SELSIZE,SELSIZE);
0070   r.moveCenter(point);
0071   return r;
0072 }
0073 
0074 QCursor SelectionPoint::cursor() {
0075   return _cursor;
0076 }
0077 
0078 void SelectionPoint::setCursor(QCursor c) {
0079   _cursor = c;
0080 }
0081 
0082 
0083 void SelectionPoint::draw(QPainter* p, double scalex) {
0084   QColor brushColor;
0085 
0086   switch (state) {
0087   case Normal: 
0088     brushColor = Qt::white;
0089     break;
0090   case HighLighted:
0091     brushColor = Qt::green;
0092     break;
0093   case AboutToRemove:
0094     brushColor = Qt::red;
0095     break;
0096   case Inactive:
0097     brushColor = Qt::gray;
0098     break;
0099   }
0100 
0101   QPoint scaledCenter((int)(point.x()*scalex),
0102               (int)(point.y()*scalex));
0103 
0104   if (state == HighLighted || state == AboutToRemove) {
0105     QRect r2(0,0,SELSIZE+4,SELSIZE+4);
0106     
0107     r2.moveCenter(scaledCenter);
0108     QColor color(brushColor);
0109     color.setAlpha(100);
0110     p->setPen(QPen(color,4,Qt::SolidLine));
0111     p->setBrush(Qt::NoBrush);
0112     p->drawRect(r2);
0113     
0114   }
0115 
0116   //  brushColor.setAlpha(230);
0117   brushColor.setAlpha(200);
0118   p->setBrush(QBrush(brushColor,Qt::SolidPattern));
0119 
0120   QColor penColor = Qt::black;
0121   penColor.setAlpha(120);
0122   QPen pen(penColor, 2, Qt::SolidLine);
0123 
0124   QRect r(0,0,SELSIZE,SELSIZE);
0125   r.moveCenter( scaledCenter );
0126   
0127   p->setPen(pen);
0128   p->drawRect(r);
0129 
0130 
0131 }
0132 
0133 
0134 bool Area::highlightArea;
0135 bool Area::showAlt;
0136 
0137 
0138 Area::Area()
0139 {
0140     _finished=false;
0141     _isSelected=false;
0142     _name=i18n("noname");
0143     _listViewItem = nullptr;
0144     currentHighlighted=-1;
0145     _type=Area::None;
0146 }
0147 
0148 Area* Area::clone() const
0149 {
0150     Area* areaClone = new Area();
0151     areaClone->setArea( *this );
0152     return areaClone;
0153 }
0154 
0155 QPolygon Area::coords() const {
0156     return _coords;
0157 }
0158 
0159 QString Area::getHTMLAttributes() const
0160 {
0161     QString retStr="";
0162 
0163     AttributeIterator it = attributeIterator();
0164     while (it.hasNext())
0165     {
0166       it.next();
0167     retStr+=it.key()+"=\""+it.value()+"\" ";
0168     }
0169 
0170   return retStr;
0171 }
0172 
0173 void Area::resetSelectionPointState() {
0174   setSelectionPointStates(SelectionPoint::Normal);
0175 }
0176 
0177 void Area::setSelectionPointStates(SelectionPoint::State st) {
0178   for (int i=0;i<_selectionPoints.size();i++) {
0179     _selectionPoints.at(i)->setState(st);
0180   }
0181 }
0182 
0183 
0184 
0185 
0186 void Area::deleteSelectionPoints() {
0187   for (int i=0;i<_selectionPoints.size();i++) {
0188     delete _selectionPoints.at(i);
0189   }
0190   _selectionPoints.clear();
0191 }
0192 
0193 Area::~Area() {
0194   deleteSelectionPoints();
0195 }
0196 
0197 bool Area::contains(const QPoint &) const {
0198   return false;
0199 }
0200 
0201 QString Area::getHTMLCode() const {
0202   return "";
0203 }
0204 
0205 QString Area::attribute(const QString & name) const
0206 {
0207   return _attributes[name.toLower()];
0208 }
0209 
0210 void Area::setAttribute(const QString & name, const QString & value)
0211 {
0212   _attributes.insert(name.toLower(), value);
0213   if (value.isEmpty())
0214      _attributes.remove(name.toLower());
0215 }
0216 
0217 AttributeIterator Area::attributeIterator() const
0218 {
0219   return AttributeIterator(_attributes);
0220 }
0221 
0222 bool Area::setCoords(const QString &) {
0223   return true;
0224 }
0225 
0226 void Area::moveSelectionPoint(SelectionPoint*, const QPoint &)
0227 {}
0228 
0229 // Default implementation; is specified by subclasses
0230 QString Area::coordsToString() const
0231 {
0232   return "";
0233 }
0234 
0235 
0236 Area::ShapeType Area::type() const {
0237     return _type;
0238 }
0239 
0240 void Area::setArea(const Area & copy)
0241 {
0242   deleteSelectionPoints();
0243   _coords.clear();
0244   _coords += copy.coords();
0245   currentHighlighted=-1;
0246   
0247   SelectionPointList points = copy.selectionPoints();
0248   for (int i=0; i<points.size(); i++) {
0249     SelectionPoint* np = 
0250       new SelectionPoint(points.at(i)->getPoint(),points.at(i)->cursor());
0251     _selectionPoints.append(np);
0252   }
0253    
0254   _finished=copy.finished();
0255   _isSelected=copy.isSelected();
0256   _rect = copy.rect();
0257 
0258   AttributeIterator it = copy.attributeIterator();
0259   while (it.hasNext()) {
0260     it.next();
0261     setAttribute(it.key(),it.value());
0262   }
0263 
0264   setMoving(copy.isMoving());
0265 }
0266 
0267 void Area::setFinished(bool b, bool ) { 
0268   _finished=b; 
0269 }
0270 
0271 
0272 void Area::setListViewItem(QTreeWidgetItem* item) {
0273     _listViewItem=item;
0274 }
0275 
0276 void Area::deleteListViewItem()
0277 {
0278     delete _listViewItem;
0279     _listViewItem = nullptr;
0280 }
0281 
0282 
0283 void Area::setRect(const QRect & r)
0284 {
0285   _rect=r;
0286     updateSelectionPoints();
0287 }
0288 
0289 QRect Area::rect() const {
0290     return _rect;
0291 }
0292 
0293 void Area::setMoving(bool b) {
0294   _isMoving=b;
0295 }
0296 
0297 
0298 void Area::moveBy(int dx, int dy) {
0299   _rect.translate(dx,dy);
0300   _coords.translate(dx,dy);
0301 
0302   for (int i=0;i < _selectionPoints.size(); i++) {
0303     _selectionPoints.at(i)->translate(dx,dy);
0304   }
0305 }
0306 
0307 
0308 void Area::moveTo(int x, int y) {
0309     int dx = x-rect().left();
0310     int dy = y-rect().top();
0311     moveBy(dx,dy);
0312 }
0313 
0314 int Area::countSelectionPoints() const
0315 {
0316   return selectionPoints().size();
0317 }
0318 
0319 int Area::addCoord(const QPoint & p)
0320 {
0321   _coords.resize(_coords.size()+1);
0322   _coords.setPoint(_coords.size()-1,p);
0323   _selectionPoints.append(new SelectionPoint(p,QCursor(Qt::PointingHandCursor)));
0324   setRect(_coords.boundingRect());
0325 
0326   return _coords.size()-1;
0327 }
0328 
0329 void Area::insertCoord(int pos, const QPoint & p)
0330 {
0331   _coords.resize(_coords.size()+1);
0332 
0333 
0334   for (int i=_coords.size()-1;i>pos;i--) {
0335     _coords.setPoint(i,_coords.point(i-1));
0336   }
0337   _coords.setPoint(pos, p);
0338 
0339   _selectionPoints.insert(pos,new SelectionPoint(p,QCursor(Qt::PointingHandCursor)));
0340   setRect(_coords.boundingRect());
0341 }
0342 
0343 void Area::removeCoord(int pos) {
0344 
0345   int count =_coords.size();
0346 
0347   if (count<4){
0348     qCDebug(KIMAGEMAPEDITOR_LOG) << "Danger : trying to remove coordinate from Area with less than 4 coordinates !";
0349     return;
0350   }
0351 
0352   for (int i=pos;i<(count-1);i++)
0353     _coords.setPoint(i, _coords.point(i+1));
0354 
0355   _coords.resize(count-1);
0356   delete _selectionPoints.takeAt(pos);
0357   setRect(_coords.boundingRect());
0358 }
0359 
0360 bool Area::removeSelectionPoint(SelectionPoint * p)
0361 {
0362   if (_selectionPoints.contains(p))
0363   {
0364     removeCoord(_selectionPoints.indexOf(p));
0365     return true;
0366   }
0367 
0368   return false;
0369 }
0370 
0371 
0372 void Area::moveCoord(int pos, const QPoint & p) {
0373   _coords.setPoint(pos,p);
0374   _selectionPoints.at(pos)->setPoint(p);
0375   setRect(_coords.boundingRect());
0376 }
0377 
0378 void Area::setSelected(bool b)
0379 {
0380   _isSelected=b;
0381   if (_listViewItem) {
0382     _listViewItem->setSelected(b);
0383   }
0384 }
0385 
0386 void Area::highlightSelectionPoint(int number){
0387     currentHighlighted=number;
0388 }
0389 
0390 QRect Area::selectionRect() const {
0391   QRect r = rect();
0392   r.translate(-SELSIZE*2,-SELSIZE*2);
0393   r.setSize(r.size()+QSize(SELSIZE*4,SELSIZE*4));
0394 
0395   return r;
0396 }
0397 
0398 void Area::setPenAndBrush(QPainter* p) {
0399   QBrush brush(Qt::NoBrush);
0400   if (highlightArea) {
0401     QColor back = Qt::white;
0402     back.setAlpha(80);
0403     brush = QBrush(back,Qt::SolidPattern);
0404   }
0405 
0406   p->setBrush(brush);
0407   
0408   QColor front = Qt::white;
0409   front.setAlpha(200);
0410   p->setPen(QPen(front,1));
0411 }
0412 
0413 
0414 void Area::drawAlt(QPainter* p)
0415 {
0416   double x,y;
0417 
0418   const double scalex = p->transform().m11();
0419 //  double scaley = p.matrix().m12();
0420 
0421   const QTransform oldTransform = p->transform();
0422 
0423   p->setTransform(QTransform(1,oldTransform.m12(), oldTransform.m21(), 1, oldTransform.dx(), oldTransform.dy() ));
0424 
0425   x = (rect().x()+rect().width()/2)*scalex;
0426   y = (rect().y()+rect().height()/2)*scalex;
0427 
0428   const QFontMetrics metrics = p->fontMetrics();
0429 
0430   const int w = metrics.boundingRect(attribute("alt")).width();
0431   x -= w/2;
0432   y += metrics.height()/4;
0433 
0434 
0435 
0436   if (highlightArea)  {
0437     p->setPen(Qt::black);
0438   } else  {
0439     p->setPen(QPen(QColor("white"),1));
0440   }
0441 
0442   p->drawText(myround(x),myround(y),attribute("alt"));
0443 
0444   p->setTransform(oldTransform);
0445 }
0446 
0447 void Area::draw(QPainter * p)
0448 {
0449 
0450   // Only draw the selection points at base class
0451   // the rest is done in the derived classes
0452   if (_isSelected)  {
0453     // We do not want to have the selection points 
0454     // scaled, so calculate the unscaled version
0455     const double scalex = p->transform().m11();
0456     const QTransform oldTransform = p->transform();
0457     p->setTransform(QTransform(1,oldTransform.m12(),
0458              oldTransform.m21(), 1,
0459              oldTransform.dx(),
0460              oldTransform.dy() ));
0461 
0462     for (int i=0; i<_selectionPoints.size(); i++) {
0463       _selectionPoints.at(i)->draw(p,scalex);
0464     }
0465     p->setTransform(oldTransform);
0466   }
0467 
0468   if (showAlt) {
0469     drawAlt(p);
0470   }
0471 
0472 }
0473 
0474 SelectionPoint* Area::onSelectionPoint(const QPoint & p, double zoom) const
0475 {
0476   
0477   for (int i=0; i<_selectionPoints.size(); i++) {
0478     SelectionPoint* sp = _selectionPoints.at(i);
0479     
0480     QRect r = sp->getRect();
0481 
0482     r.moveCenter(sp->getPoint()*zoom);
0483 
0484     if (r.contains(p))
0485     {
0486       return sp;
0487     }
0488   }
0489 
0490   return nullptr;
0491 }
0492 
0493 
0494 
0495 
0496 /**
0497  * returns only the part of the image which is
0498  * covered by the area
0499  */
0500 QPixmap Area::cutOut(const QImage & image)
0501 {
0502     if ( 0>=rect().width()  ||
0503              0>=rect().height() ||
0504        !rect().intersects(image.rect())   )
0505     {
0506         QPixmap dummyPix(10,10);
0507         dummyPix.fill();
0508         return dummyPix;
0509     }
0510 
0511     // Get the mask from the subclasses
0512     QBitmap mask=getMask();
0513 
0514     // The rectangle which is part of the image
0515     QRect partOfImage=rect();
0516     QRect partOfMask(0,0,mask.width(),mask.height());
0517 
0518 
0519     // If the area is outside of the image make the
0520     // preview smaller
0521     if ( (rect().x()+rect().width()) > image.width() ) {
0522         partOfImage.setWidth( image.width()-rect().x() );
0523         partOfMask.setWidth(  image.width()-rect().x() );
0524     }
0525 
0526     if ( (rect().x() < 0) ) {
0527         partOfImage.setX(0);
0528         partOfMask.setX(myabs(rect().x()));
0529     }
0530 
0531     if ( (rect().y()+rect().height()) > image.height() ) {
0532         partOfImage.setHeight( image.height()-rect().y() );
0533         partOfMask.setHeight ( image.height()-rect().y() );
0534     }
0535 
0536     if ( (rect().y() < 0) ) {
0537         partOfImage.setY(0);
0538         partOfMask.setY(myabs(rect().y()));
0539     }
0540 
0541         QImage tempImage=mask.toImage().copy(partOfMask);
0542     mask = QPixmap::fromImage(tempImage);
0543 
0544 //  partOfImage = partOfImage.normalize();
0545     QImage cut=image.copy(partOfImage);
0546 
0547     QPixmap pix;
0548 
0549 //  partOfMask = partOfMask.normalize();
0550     if (!partOfMask.isValid())
0551        qCDebug(KIMAGEMAPEDITOR_LOG) << "PartofMask not valid : " << partOfMask.x() << "," << partOfMask.y() << ","
0552                 << partOfMask.width() << "," << partOfMask.height() << ",";
0553 
0554 /*
0555     QBitmap mask2(partOfMask.width(), partOfMask.height());
0556     QPainter p4(&mask2);
0557     p4.drawPixmap( QPoint(0,0) ,mask,partOfMask);
0558     p4.flush();
0559     p4.end();
0560 */
0561 
0562     pix = QPixmap::fromImage(cut);
0563 
0564     //  setHighlightedPixmap(cut, mask);
0565 
0566     QPixmap retPix(pix.width(),pix.height());
0567   QPainter p3(&retPix);
0568 
0569     // if transparent image fill the background
0570     // with gimp-like rectangles
0571     if (!pix.mask().isNull()) {
0572     QPixmap backPix(32,32);
0573 
0574     // Gimp like transparent rectangle
0575     QPainter p2(&backPix);
0576     p2.fillRect(0,0,32,32,QColor(156,149,156));
0577     p2.fillRect(0,16,16,16,QColor(98,105,98));
0578     p2.fillRect(16,0,16,16,QColor(98,105,98));
0579 
0580     p3.setPen(QPen());
0581     p3.fillRect(0,0,pix.width(),pix.height(),QBrush(QColor("black"),backPix));
0582     }
0583 
0584 
0585     p3.drawPixmap(QPoint(0,0),pix);
0586     p3.end();
0587     retPix.setMask(mask);
0588 
0589     return retPix;
0590 }
0591 
0592 QBitmap Area::getMask() const
0593 {
0594     QBitmap b;
0595     return b;
0596 }
0597 
0598 /********************************************************************
0599  * RECTANGLE
0600  *******************************************************************/
0601 
0602 
0603 RectArea::RectArea()
0604     : Area()
0605 {
0606   _type=Area::Rectangle;
0607   QPoint p(0,0);
0608   _selectionPoints.append(new SelectionPoint(p,Qt::SizeFDiagCursor));
0609   _selectionPoints.append(new SelectionPoint(p,Qt::SizeBDiagCursor));
0610   _selectionPoints.append(new SelectionPoint(p,Qt::SizeBDiagCursor));
0611   _selectionPoints.append(new SelectionPoint(p,Qt::SizeFDiagCursor));
0612   _selectionPoints.append(new SelectionPoint(p,Qt::SizeVerCursor));
0613   _selectionPoints.append(new SelectionPoint(p,Qt::SizeHorCursor));
0614   _selectionPoints.append(new SelectionPoint(p,Qt::SizeVerCursor));
0615   _selectionPoints.append(new SelectionPoint(p,Qt::SizeHorCursor));
0616 }
0617 
0618 RectArea::~RectArea() {
0619 }
0620 
0621 Area* RectArea::clone() const
0622 {
0623     Area* areaClone = new RectArea();
0624     areaClone->setArea( *this );
0625     return areaClone;
0626 }
0627 
0628 void RectArea::draw(QPainter * p)
0629 {
0630   setPenAndBrush(p);
0631 
0632   QRect r(rect());
0633   r.setWidth(r.width()+1);
0634   r.setHeight(r.height()+1);
0635   p->drawRect(r);
0636 
0637   Area::draw(p);
0638 }
0639 
0640 QBitmap RectArea::getMask() const
0641 {
0642     QBitmap mask(rect().width(),rect().height());
0643 
0644     mask.fill(Qt::color0);
0645     QPainter p(&mask);
0646     p.setBackground(QBrush(Qt::color0));
0647     p.setPen(Qt::color1);
0648     p.setBrush(Qt::color1);
0649     mask.fill(Qt::color1);
0650     p.end();
0651 
0652     return mask;
0653 }
0654 
0655 QString RectArea::coordsToString() const
0656 {
0657     QString retStr=QString("%1,%2,%3,%4")
0658                     .arg(rect().left())
0659                     .arg(rect().top())
0660                     .arg(rect().right())
0661                     .arg(rect().bottom());
0662 
0663     return retStr;
0664 }
0665 
0666 bool RectArea::contains(const QPoint & p) const{
0667     return rect().contains(p);
0668 }
0669 
0670 void RectArea::moveSelectionPoint(SelectionPoint* selectionPoint, const QPoint & p)
0671 {
0672     selectionPoint->setPoint(p);
0673     int i = _selectionPoints.indexOf(selectionPoint);
0674 
0675     QRect r2(_rect);
0676     switch (i) {
0677     case 0 :
0678       _rect.setLeft(p.x());
0679       _rect.setTop(p.y());
0680       break;
0681     case 1 : 
0682       _rect.setRight(p.x());
0683       _rect.setTop(p.y());
0684       break;
0685     case 2 : 
0686       _rect.setLeft(p.x());
0687       _rect.setBottom(p.y());
0688       break;
0689     case 3 : 
0690       _rect.setRight(p.x());
0691       _rect.setBottom(p.y());
0692       break;
0693     case 4 : // top line
0694       _rect.setTop(p.y());
0695       break;
0696     case 5 : // right line
0697       _rect.setRight(p.x());
0698       break;
0699     case 6 : // bottom
0700       _rect.setBottom(p.y());
0701       break;
0702     case 7 : // left
0703       _rect.setLeft(p.x());
0704       break;
0705       
0706     }
0707     if (! _rect.isValid())
0708       _rect=r2;
0709 
0710     updateSelectionPoints();
0711 }
0712 
0713 void RectArea::updateSelectionPoints()
0714 {
0715   int d = 2;
0716   QRect r(_rect);
0717   r.adjust(0,0,1,1);
0718   int xmid = r.left()+(r.width()/d);
0719   int ymid = r.top()+(r.height()/d);
0720   
0721 
0722   _selectionPoints[0]->setPoint(r.topLeft());
0723   _selectionPoints[1]->setPoint(r.topRight());
0724   _selectionPoints[2]->setPoint(r.bottomLeft());
0725   _selectionPoints[3]->setPoint(r.bottomRight());
0726   _selectionPoints[4]->setPoint(QPoint(xmid,r.top()));
0727   _selectionPoints[5]->setPoint(QPoint(r.right(),ymid));
0728   _selectionPoints[6]->setPoint(QPoint(xmid,r.bottom()));
0729   _selectionPoints[7]->setPoint(QPoint(r.left(),ymid));
0730 }
0731 
0732 bool RectArea::setCoords(const QString & s)
0733 {
0734     _finished=true;
0735 
0736     const QStringList list = s.split(',');
0737     QRect r;
0738     bool ok=true;
0739     QStringList::ConstIterator it = list.begin();
0740     r.setLeft((*it).toInt(&ok,10));it++;
0741     r.setTop((*it).toInt(&ok,10));it++;
0742     r.setRight((*it).toInt(&ok,10));it++;
0743     r.setBottom((*it).toInt(&ok,10));
0744     if (ok) {
0745       setRect(r);
0746       return true;
0747     } else {
0748       return false;
0749     }
0750 }
0751 
0752 QString RectArea::getHTMLCode() const {
0753     QString retStr;
0754     retStr+="<area ";
0755     retStr+="shape=\"rect\" ";
0756 
0757     retStr+=getHTMLAttributes();
0758 
0759     retStr+="coords=\""+coordsToString()+"\" ";
0760     retStr+="/>";
0761     return retStr;
0762 
0763 }
0764 
0765 /********************************************************************
0766  * CIRCLE
0767  *******************************************************************/
0768 
0769 
0770 CircleArea::CircleArea()
0771     : Area()
0772 {
0773   _type = Area::Circle;
0774   QPoint p(0,0);
0775   _selectionPoints.append(new SelectionPoint(p,Qt::SizeFDiagCursor));
0776   _selectionPoints.append(new SelectionPoint(p,Qt::SizeBDiagCursor));
0777   _selectionPoints.append(new SelectionPoint(p,Qt::SizeBDiagCursor));
0778   _selectionPoints.append(new SelectionPoint(p,Qt::SizeFDiagCursor));
0779 }
0780 
0781 CircleArea::~CircleArea() {
0782 }
0783 
0784 Area* CircleArea::clone() const
0785 {
0786     Area* areaClone = new CircleArea();
0787     areaClone->setArea( *this );
0788     return areaClone;
0789 }
0790 
0791 void CircleArea::draw(QPainter * p)
0792 {
0793   setPenAndBrush(p);
0794 
0795   QRect r(_rect);
0796   r.setWidth(r.width()+1);
0797   r.setHeight(r.height()+1);
0798   p->drawEllipse(r);
0799 
0800   Area::draw(p);
0801 }
0802 
0803 QBitmap CircleArea::getMask() const
0804 {
0805     QBitmap mask(_rect.width(),_rect.height());
0806 
0807     mask.fill(Qt::color0);
0808     QPainter p(&mask);
0809     p.setBackground(QBrush(Qt::color0));
0810     p.setPen(Qt::color1);
0811     p.setBrush(Qt::color1);
0812     p.drawPie(QRect(0,0,_rect.width(),_rect.height()),0,5760);
0813     p.end();
0814 
0815 
0816     return mask;
0817 
0818 }
0819 
0820 QString CircleArea::coordsToString() const
0821 {
0822     QString retStr=QString("%1,%2,%3")
0823                     .arg(_rect.center().x())
0824                     .arg(_rect.center().y())
0825                     .arg(_rect.width()/2);
0826 
0827     return retStr;
0828 }
0829 
0830 bool CircleArea::contains(const QPoint & p) const
0831 {
0832     QRegion r(_rect,QRegion::Ellipse);
0833     return r.contains(p);
0834 }
0835 
0836 void CircleArea::moveSelectionPoint(SelectionPoint* selectionPoint, const QPoint & p)
0837 {
0838   selectionPoint->setPoint(p);
0839 
0840   int i = _selectionPoints.indexOf(selectionPoint);
0841 
0842   // The code below really sucks, but I have no better idea.
0843   // it only makes sure that the circle is perfectly round
0844 
0845   QPoint newPoint;
0846   int diff=myabs(p.x()-_rect.center().x());
0847   if (myabs(p.y()-_rect.center().y())>diff)
0848     diff=myabs(p.y()-_rect.center().y());
0849 
0850   newPoint.setX( p.x()-_rect.center().x()<0
0851          ? _rect.center().x()-diff
0852          :  _rect.center().x()+diff);
0853 
0854   newPoint.setY( p.y()-_rect.center().y()<0
0855          ? _rect.center().y()-diff
0856          :  _rect.center().y()+diff);
0857 
0858   switch (i) {
0859   case 0 : if (newPoint.x() < _rect.center().x() &&
0860            newPoint.y() < _rect.center().y())
0861     {
0862       _rect.setLeft(newPoint.x());
0863       _rect.setTop(newPoint.y());
0864     }
0865     break;
0866   case 1 : if (newPoint.x() > _rect.center().x() &&
0867            newPoint.y() < _rect.center().y())
0868     {
0869       _rect.setRight(newPoint.x());
0870       _rect.setTop(newPoint.y());
0871     }
0872     break;
0873   case 2 : if (newPoint.x() < _rect.center().x() &&
0874            newPoint.y() > _rect.center().y())
0875     {
0876       _rect.setLeft(newPoint.x());
0877       _rect.setBottom(newPoint.y());
0878     }
0879     break;
0880   case 3 : if (newPoint.x() > _rect.center().x() &&
0881            newPoint.y() > _rect.center().y())
0882     {
0883       _rect.setRight(newPoint.x());
0884       _rect.setBottom(newPoint.y());
0885     }
0886     break;
0887   }
0888 
0889 
0890 
0891   updateSelectionPoints();
0892 
0893 }
0894 
0895 void CircleArea::setRect(const QRect & r)
0896 {
0897     QRect r2 = r;
0898     if ( r2.height() != r2.width() )
0899        r2.setHeight( r2.width() );
0900 
0901     Area::setRect(r2);
0902 }
0903 
0904 
0905 void CircleArea::updateSelectionPoints()
0906 {
0907   _selectionPoints[0]->setPoint(_rect.topLeft());
0908   _selectionPoints[1]->setPoint(_rect.topRight());
0909   _selectionPoints[2]->setPoint(_rect.bottomLeft());
0910   _selectionPoints[3]->setPoint(_rect.bottomRight());
0911 }
0912 
0913 bool CircleArea::setCoords(const QString & s)
0914 {
0915     _finished=true;
0916     const QStringList list = s.split(',');
0917     bool ok=true;
0918     QStringList::ConstIterator it = list.begin();
0919     int x=(*it).toInt(&ok,10);it++;
0920     int y=(*it).toInt(&ok,10);it++;
0921     int rad=(*it).toInt(&ok,10);
0922     if (!ok) return false;
0923     QRect r;
0924     r.setWidth(rad*2);
0925     r.setHeight(rad*2);
0926     r.moveCenter(QPoint(x,y));
0927     setRect(r);
0928     return true;
0929 }
0930 
0931 QString CircleArea::getHTMLCode() const {
0932     QString retStr;
0933     retStr+="<area ";
0934     retStr+="shape=\"circle\" ";
0935 
0936     retStr+=getHTMLAttributes();
0937 
0938     retStr+="coords=\""+coordsToString()+"\" ";
0939     retStr+="/>";
0940     return retStr;
0941 
0942 }
0943 
0944 
0945 /********************************************************************
0946  * POLYGON
0947  *******************************************************************/
0948 
0949 
0950 PolyArea::PolyArea()
0951     : Area()
0952 {
0953   _type = Area::Polygon;
0954 }
0955 
0956 PolyArea::~PolyArea() {
0957 }
0958 
0959 Area* PolyArea::clone() const
0960 {
0961     Area* areaClone = new PolyArea();
0962     areaClone->setArea( *this );
0963     return areaClone;
0964 }
0965 
0966 void PolyArea::draw(QPainter * p)
0967 {
0968   setPenAndBrush(p);
0969 
0970   if (_finished)
0971     p->drawPolygon( _coords.constData(),_coords.count());
0972   else {
0973     p->drawPolyline(_coords.constData(),_coords.count());
0974   }
0975 
0976   Area::draw(p);
0977 }
0978 
0979 QBitmap PolyArea::getMask() const
0980 {
0981     QBitmap mask(_rect.width(),_rect.height());
0982 
0983     mask.fill(Qt::color0);
0984     QPainter p(&mask);
0985     p.setBackground(QBrush(Qt::color0));
0986     p.setPen(Qt::color1);
0987     p.setBrush(Qt::color1);
0988     p.setClipping(true);
0989     QRegion r(_coords);
0990     r.translate(-_rect.left(),-_rect.top());
0991     p.setClipRegion(r);
0992     p.fillRect(QRect(0,0,_rect.width(),_rect.height()),Qt::color1);
0993     p.end();
0994 
0995     return mask;
0996 }
0997 
0998 QString PolyArea::coordsToString() const
0999 {
1000     QString retStr;
1001 
1002     for (int i=0;i<_coords.count();i++) {
1003         retStr.append(QString("%1,%2,")
1004             .arg(_coords.point(i).x())
1005             .arg(_coords.point(i).y()));
1006     }
1007 
1008     retStr.remove(retStr.length()-1,1);
1009 
1010     return retStr;
1011 }
1012 
1013 int PolyArea::distance(const QPoint &p1, const QPoint &p2)
1014 {
1015   QPoint temp = p1-p2;
1016   return temp.manhattanLength();
1017 }
1018 
1019 bool PolyArea::isBetween(const QPoint &p, const QPoint &p1, const QPoint &p2)
1020 {
1021   int dist = distance(p,p1)+distance(p,p2)-distance(p1,p2);
1022 
1023   if (myabs(dist)<1)
1024      return true;
1025   else
1026      return false;
1027 }
1028 
1029 void PolyArea::simplifyCoords()
1030 {
1031   if (_coords.size()<4)
1032      return;
1033 
1034   QPoint p = _coords.point(0) - _coords.point(1);
1035 
1036   int i = 1;
1037 
1038 
1039   while( (i<_coords.size()) && (_coords.size() > 3) )
1040   {
1041     p = _coords.point(i-1) - _coords.point(i);
1042 
1043     if (p.manhattanLength() < 3)
1044       removeCoord(i);
1045     else
1046       i++;
1047   }
1048 
1049   p = _coords.point(0) - _coords.point(1);
1050 
1051   double angle2;
1052   double angle1;
1053 
1054   if (p.y()==0)
1055      angle1 = 1000000000;
1056   else
1057     angle1 = (double) p.x() / (double) p.y();
1058 
1059   i=2;
1060 
1061   while( (i<_coords.size()) && (_coords.size() > 3) )
1062   {
1063     p = _coords.point(i-1) - _coords.point(i);
1064 
1065     if (p.y()==0)
1066         angle2 = 1000000000;
1067     else
1068       angle2 = (double) p.x() / (double) p.y();
1069 
1070     if ( angle2==angle1 )
1071     {
1072       qCDebug(KIMAGEMAPEDITOR_LOG) << "removing " << i-1;
1073       removeCoord(i-1);
1074     }
1075     else
1076     {
1077       i++;
1078       qCDebug(KIMAGEMAPEDITOR_LOG) << "skipping " << i-1 << " cause " << angle1 << "!= " << angle2;
1079       angle1 = angle2;
1080 
1081     }
1082 
1083   }
1084 
1085 
1086 
1087 }
1088 
1089 
1090 int PolyArea::addCoord(const QPoint & p)
1091 {
1092   if (_coords.size()<3)
1093   {
1094      return Area::addCoord(p);
1095   }
1096 
1097   if (_coords.point(_coords.size()-1) == p)
1098   {
1099      qCDebug(KIMAGEMAPEDITOR_LOG) << "equal Point added";
1100      return -1;
1101 
1102   }
1103 
1104   int n=_coords.size();
1105 
1106 //  QPoint temp = p-_coords.point(0);
1107   int nearest = 0;
1108   int olddist = distance(p,_coords.point(0));
1109   int mindiff = 999999999;
1110 
1111   // find the two points, which are the nearest one to the new point
1112   for (int i=1; i <= n; i++)
1113   {
1114     int dist = distance(p,_coords.point(i%n));
1115     int dist2 = distance(_coords.point(i-1),_coords.point(i%n));
1116     int diff = myabs(dist+olddist-dist2);
1117     if ( diff<mindiff )
1118     {
1119       mindiff = diff;
1120       nearest = i%n;
1121     }
1122     olddist=dist;
1123   }
1124 
1125   insertCoord(nearest, p);
1126 
1127   return nearest;
1128 
1129 }
1130 
1131 bool PolyArea::contains(const QPoint & p) const
1132 {
1133     // A line can't contain a point
1134     if (_coords.count() >2 ) {
1135         QRegion r(_coords);
1136         return r.contains(p);
1137     }
1138     else
1139         return false;
1140 }
1141 
1142 void PolyArea::moveSelectionPoint(SelectionPoint* selectionPoint, const QPoint & p)
1143 {
1144   selectionPoint->setPoint(p);
1145 
1146   int i = _selectionPoints.indexOf(selectionPoint);
1147   _coords.setPoint(i,p);
1148   _rect=_coords.boundingRect();
1149 }
1150 
1151 void PolyArea::updateSelectionPoints()
1152 {
1153   for (int i = 0; i < _selectionPoints.size(); ++i) {
1154     _selectionPoints.at(i)->setPoint(_coords.point(i));
1155   }
1156 }
1157 
1158 bool PolyArea::setCoords(const QString & s)
1159 {
1160     _finished=true;
1161     const QStringList list = s.split(',');
1162     _coords.clear();
1163     _selectionPoints.clear();
1164 
1165     for (QStringList::ConstIterator it = list.begin(); it !=list.end(); ++it)
1166     {
1167         bool ok=true;
1168         int newXCoord=(*it).toInt(&ok,10);
1169         if (!ok) return false;
1170         it++;
1171         if (it==list.end()) break;
1172         int newYCoord=(*it).toInt(&ok,10);
1173         if (!ok) return false;
1174         insertCoord(_coords.size(), QPoint(newXCoord,newYCoord));
1175     }
1176 
1177     return true;
1178 
1179 }
1180 
1181 QString PolyArea::getHTMLCode() const {
1182     QString retStr;
1183     retStr+="<area ";
1184     retStr+="shape=\"poly\" ";
1185 
1186     retStr+=getHTMLAttributes();
1187 
1188     retStr+="coords=\""+coordsToString()+"\" ";
1189     retStr+="/>";
1190     return retStr;
1191 
1192 }
1193 
1194 void PolyArea::setFinished(bool b, bool removeLast = true)
1195 {
1196     // The last Point is the same as the first
1197     // so delete it
1198   if (b && removeLast) {
1199     _coords.resize(_coords.size()-1);
1200     _selectionPoints.removeLast();
1201   }
1202 
1203   _finished = b;
1204 }
1205 
1206 QRect PolyArea::selectionRect() const
1207 {
1208     QRect r = _rect;
1209 
1210     r.translate(-10,-10);
1211     r.setSize(r.size()+QSize(21,21));
1212 
1213     return r;
1214 }
1215 
1216 
1217 
1218 /********************************************************************
1219  * DEFAULT
1220  *******************************************************************/
1221 
1222 
1223 DefaultArea::DefaultArea()
1224     : Area()
1225 {
1226     _type=Area::Default;
1227 }
1228 
1229 DefaultArea::~DefaultArea() {
1230 }
1231 
1232 Area* DefaultArea::clone() const
1233 {
1234     Area* areaClone = new DefaultArea();
1235     areaClone->setArea( *this );
1236     return areaClone;
1237 }
1238 
1239 void DefaultArea::draw(QPainter *)
1240 {}
1241 
1242 
1243 QString DefaultArea::getHTMLCode() const {
1244     QString retStr;
1245     retStr+="<area ";
1246     retStr+="shape=\"default\" ";
1247 
1248     retStr+=getHTMLAttributes();
1249 
1250     retStr+="/>";
1251     return retStr;
1252 
1253 }
1254 
1255 
1256 /********************************************************************
1257  * AreaSelection
1258  *******************************************************************/
1259 
1260 AreaSelection::AreaSelection()
1261     : Area()
1262 {
1263     _areas = new AreaList();
1264     _name = "Selection";
1265     invalidate();
1266 }
1267 
1268 AreaSelection::~AreaSelection() {
1269     delete _areas;
1270 }
1271 
1272 Area* AreaSelection::clone() const
1273 {
1274   AreaSelection* areaClone = new AreaSelection();
1275 
1276   // we want a deep copy of the Areas
1277   AreaListIterator it=getAreaListIterator();
1278   while (it.hasNext()) {
1279     areaClone->add( it.next()->clone() );
1280   }
1281 
1282   return areaClone;
1283 }
1284 
1285 
1286 void AreaSelection::add(Area *a)
1287 {
1288   // if a selection of areas was added get the areas of it
1289   AreaSelection *selection = nullptr;
1290   if ( (selection = dynamic_cast <AreaSelection*> ( a ) ) ) {
1291     AreaList list = selection->getAreaList();
1292     Area* area;
1293     foreach(area,list) {
1294       if ( !_areas->contains( area )) {
1295     _areas->append( area );  // Must come before area->setSelected
1296     area->setSelected( true );
1297       }
1298     }
1299   } else {
1300     if ( !_areas->contains( a )) {
1301       _areas->append( a );  // Must come before a->setSelected
1302       a->setSelected( true );
1303     }
1304   }
1305 
1306   invalidate();
1307 }
1308 
1309 
1310 void AreaSelection::setSelectionPointStates(SelectionPoint::State st) {
1311   AreaListIterator it=getAreaListIterator();
1312   while(it.hasNext()) {
1313     it.next()->setSelectionPointStates( st );
1314   }
1315 }
1316 
1317 void AreaSelection::updateSelectionPointStates() {
1318   SelectionPoint::State st = SelectionPoint::Normal;
1319   
1320   if (_areas->count() > 1) 
1321     st = SelectionPoint::Inactive;
1322 
1323   setSelectionPointStates(st);
1324 }
1325 
1326 
1327 void AreaSelection::remove(Area *a)
1328 {
1329   if (!_areas->contains(a))
1330     return;
1331 
1332   a->setSelected( false );
1333   _areas->removeAt(_areas->indexOf(a));
1334   invalidate();
1335 }
1336 
1337 void AreaSelection::reset()
1338 {
1339   AreaListIterator it=getAreaListIterator();
1340   while (it.hasNext()) {
1341     it.next()->setSelected( false );
1342   }
1343 
1344   _areas->clear();
1345   invalidate();
1346 }
1347 
1348 bool AreaSelection::contains(const QPoint & p) const
1349 {
1350   AreaListIterator it=getAreaListIterator();
1351   while (it.hasNext()) {
1352     if ( it.next()->contains( p ) ) {
1353       return true;
1354     }
1355   }
1356 
1357   return false;
1358 }
1359 
1360 SelectionPoint* AreaSelection::onSelectionPoint(const QPoint & p, double zoom) const
1361 {
1362 
1363   if (_areas->count() != 1)
1364     return nullptr;
1365 
1366   return _areas->first()->onSelectionPoint(p,zoom);
1367 }
1368 
1369 void AreaSelection::moveSelectionPoint(SelectionPoint* selectionPoint, const QPoint & p)
1370 {
1371   // It's only possible to move a SelectionPoint if only one Area is selected
1372   if (_areas->count() != 1)
1373     return;
1374 
1375   _areas->first()->moveSelectionPoint(selectionPoint,p);
1376 
1377   invalidate();
1378 }
1379 
1380 
1381 void AreaSelection::moveBy(int dx, int dy)
1382 {
1383   AreaListIterator it=getAreaListIterator();
1384   while (it.hasNext()) {
1385     it.next()->moveBy(dx,dy);
1386   }
1387 
1388   Area::moveBy( dx, dy );
1389   invalidate();
1390 }
1391 
1392 QString AreaSelection::typeString() const
1393 {
1394   // if there is only one Area selected
1395   // show the name of that Area
1396   if ( _areas->count()==0 )
1397     return "";
1398   else if ( _areas->count()==1 )
1399     return _areas->first()->typeString();
1400   else
1401     return i18n("Number of Areas");
1402 
1403 }
1404 
1405 Area::ShapeType AreaSelection::type() const
1406 {
1407   // if there is only one Area selected
1408   // take the type of that Area
1409   if ( _areas->count()==0 )
1410     return Area::None;
1411   else if ( _areas->count()==1 )
1412     return _areas->first()->type();
1413   else
1414     return Area::Selection;
1415 }
1416 
1417 void AreaSelection::resetSelectionPointState() {
1418   updateSelectionPointStates();
1419 }
1420 
1421 void AreaSelection::updateSelectionPoints()
1422 {
1423   AreaListIterator it=getAreaListIterator();
1424   while (it.hasNext()) {
1425     it.next()->updateSelectionPoints();
1426   }
1427 
1428   invalidate();
1429 }
1430 
1431 
1432 
1433 QRect AreaSelection::selectionRect() const
1434 {
1435   if (!_selectionCacheValid) {
1436     _selectionCacheValid=true;
1437     QRect r;
1438     AreaListIterator it=getAreaListIterator();
1439     while (it.hasNext()) {
1440         r = r | it.next()->selectionRect();
1441     }
1442     _cachedSelectionRect=r;
1443   }
1444 
1445   return _cachedSelectionRect;
1446 }
1447 
1448 int AreaSelection::count() const {
1449   return _areas->count();
1450 }
1451 
1452 bool AreaSelection::isEmpty() const
1453 {
1454   return _areas->isEmpty();
1455 }
1456 
1457 
1458 AreaList AreaSelection::getAreaList() const {
1459   AreaList list(*_areas);
1460   return list;
1461 }
1462 
1463 AreaListIterator AreaSelection::getAreaListIterator() const {
1464   AreaListIterator it(*_areas);
1465   return it;
1466 }
1467 
1468 void AreaSelection::setArea(const Area & copy)
1469 {
1470   Area *area = copy.clone();
1471   AreaSelection *selection = dynamic_cast<AreaSelection*>(area);
1472   if (selection)
1473     setAreaSelection(*selection);
1474   else {
1475     Area::setArea(copy);
1476     invalidate();
1477   }
1478 }
1479 
1480 void AreaSelection::setAreaSelection(const AreaSelection & copy)
1481 {
1482   AreaList* areasCopy = copy._areas;
1483 
1484   if (_areas->count() != areasCopy->count())
1485     return;
1486 
1487   AreaListIterator it(*_areas);
1488   AreaListIterator it2(*areasCopy);
1489   while (it.hasNext()) {
1490     it.next()->setArea(*it2.next());
1491   }
1492 
1493   Area::setArea(copy);
1494     invalidate();
1495 }
1496 
1497 void AreaSelection::setAreaList( const AreaList & areas )
1498 {
1499   delete _areas;
1500   _areas = new AreaList(areas);
1501   invalidate();
1502 }
1503 
1504 void AreaSelection::setRect(const QRect & r)
1505 {
1506     if ( _areas->count()==1 )
1507     {
1508         _areas->first()->setRect(r);
1509     }
1510 
1511     invalidate();
1512     _rect=rect();
1513     updateSelectionPoints();
1514 }
1515 
1516 QRect AreaSelection::rect() const
1517 {
1518     if (!_rectCacheValid)
1519     {
1520         _rectCacheValid=true;
1521     QRect r;
1522     AreaListIterator it=getAreaListIterator();
1523 
1524     while (it.hasNext()) {
1525         r = r | it.next()->rect();
1526     }
1527 
1528     _cachedRect=r;
1529   }
1530 
1531   return _cachedRect;
1532 }
1533 
1534 
1535 int AreaSelection::addCoord(const QPoint & p)
1536 {
1537     if ( _areas->count()==1 )
1538     {
1539         return _areas->first()->addCoord(p);
1540         invalidate();
1541     }
1542 
1543   return 0;
1544 }
1545 
1546 void AreaSelection::insertCoord(int pos, const QPoint & p)
1547 {
1548     if ( _areas->count()==1 )
1549     {
1550         _areas->first()->insertCoord(pos, p);
1551         invalidate();
1552     }
1553 }
1554 
1555 void AreaSelection::removeCoord(int pos)
1556 {
1557     if ( _areas->count()==1 )
1558     {
1559         _areas->first()->removeCoord(pos);
1560         invalidate();
1561     }
1562 }
1563 
1564 bool AreaSelection::removeSelectionPoint(SelectionPoint* p)
1565 {
1566   bool result=false;
1567 
1568     if ( _areas->count()==1 )
1569     {
1570         result = _areas->first()->removeSelectionPoint(p);
1571         invalidate();
1572     }
1573 
1574     return result;
1575 }
1576 
1577 const SelectionPointList & AreaSelection::selectionPoints() const
1578 {
1579     if ( _areas->count()==1 )
1580     {
1581         return _areas->first()->selectionPoints();
1582     }
1583 
1584     return _selectionPoints;
1585 }
1586 
1587 
1588 void AreaSelection::moveCoord(int pos,const QPoint & p)
1589 {
1590     if ( _areas->count()==1 )
1591     {
1592         _areas->first()->moveCoord(pos,p);
1593         invalidate();
1594     }
1595 }
1596 
1597 void AreaSelection::highlightSelectionPoint(int i)
1598 {
1599     if ( _areas->count()==1 )
1600     {  
1601         _areas->first()->highlightSelectionPoint(i);
1602         invalidate();
1603     }
1604 }
1605 
1606 
1607 QPolygon AreaSelection::coords() const
1608 {
1609     if ( _areas->count()==1 )
1610     {
1611         return _areas->first()->coords();
1612     }
1613 
1614     return Area::coords();
1615 }
1616 
1617 QString AreaSelection::attribute(const QString & name) const
1618 {
1619     if ( _areas->count()==1 )
1620     {
1621         return _areas->first()->attribute(name);
1622     }
1623 
1624     return Area::attribute(name);
1625 }
1626 
1627 void AreaSelection::setAttribute(const QString & name, const QString & value)
1628 {
1629   AreaListIterator it=getAreaListIterator();
1630 
1631   while (it.hasNext()) {
1632     it.next()->setAttribute(name,value);
1633   }
1634 
1635     Area::setAttribute(name,value);
1636 }
1637 
1638 AttributeIterator AreaSelection::attributeIterator() const
1639 {
1640     if ( _areas->count()==1 )
1641     {
1642         return _areas->first()->attributeIterator();
1643     }
1644 
1645   return AttributeIterator(_attributes);
1646 }
1647 
1648 void AreaSelection::setMoving(bool b)
1649 {
1650   AreaListIterator it=getAreaListIterator();
1651   
1652   while (it.hasNext()) {
1653     it.next()->setMoving(b);
1654   }
1655 
1656     Area::setMoving(b);
1657 }
1658 
1659 bool AreaSelection::isMoving() const
1660 {
1661     if ( _areas->count()==1 )
1662     {
1663         return _areas->first()->isMoving();
1664     }
1665 
1666     return Area::isMoving();
1667 }
1668 
1669 
1670 /**
1671  * Checks if an area is outside the rectangle parameter
1672  * returns false if an area has no pixel in common with the rectangle parameter
1673  **/
1674 bool AreaSelection::allAreasWithin(const QRect & r) const
1675 {
1676   if ( ! r.contains(rect()) )
1677   {
1678     AreaListIterator it=getAreaListIterator();
1679 
1680     while (it.hasNext()) {
1681       if (!it.next()->rect().intersects(r))
1682         return false;
1683     }
1684   }
1685 
1686   return true;
1687 }
1688 
1689 
1690 void AreaSelection::draw(QPainter *)
1691 {}
1692 
1693 void AreaSelection::invalidate() {
1694   _selectionCacheValid=false;
1695   _rectCacheValid=false;
1696   updateSelectionPointStates();
1697 }
1698 
1699