1 /***************************************************************************
2                           kimearea.cpp  -  description
3                              -------------------
4     begin                : Thu Jun 14 2001
5     copyright            : (C) 2001 by Jan Schaefer
6     email                : janschaefer@users.sourceforge.net
7  ***************************************************************************/
8 
9 /***************************************************************************
10  *                                                                         *
11  *   This program is free software; you can redistribute it and/or modify  *
12  *   it under the terms of the GNU General Public License as published by  *
13  *   the Free Software Foundation; either version 2 of the License, or     *
14  *   (at your option) any later version.                                   *
15  *                                                                         *
16  ***************************************************************************/
17 
18 #include "kimearea.h"
19 
20 #include <QBitmap>
21 #include <QBrush>
22 #include <QColor>
23 #include <QImage>
24 #include <QPainter>
25 #include <QPalette>
26 #include <QPen>
27 #include <QPixmap>
28 #include <QPolygon>
29 
30 #include "kimagemapeditor_debug.h"
31 
32 #include "kimecommon.h"
33 
34 
35 // The size of Selection Points
36 
SelectionPoint(QPoint p,QCursor c)37 SelectionPoint::SelectionPoint(QPoint p, QCursor c)
38 {
39   point = p;
40   state = Normal;
41   _cursor = c;
42 }
43 
~SelectionPoint()44 SelectionPoint::~SelectionPoint() {
45 }
46 
setState(SelectionPoint::State s)47 void SelectionPoint::setState(SelectionPoint::State s) {
48   state = s;
49 }
50 
getState() const51 SelectionPoint::State SelectionPoint::getState() const {
52   return state;
53 }
54 
setPoint(QPoint p)55 void SelectionPoint::setPoint(QPoint p) {
56   point = p;
57 }
58 
translate(int dx,int dy)59 void SelectionPoint::translate(int dx, int dy) {
60   point += QPoint(dx,dy);
61 }
62 
63 
getPoint() const64 QPoint SelectionPoint::getPoint() const {
65   return point;
66 }
67 
getRect() const68 QRect SelectionPoint::getRect() const {
69   QRect r(0,0,SELSIZE,SELSIZE);
70   r.moveCenter(point);
71   return r;
72 }
73 
cursor()74 QCursor SelectionPoint::cursor() {
75   return _cursor;
76 }
77 
setCursor(QCursor c)78 void SelectionPoint::setCursor(QCursor c) {
79   _cursor = c;
80 }
81 
82 
draw(QPainter * p,double scalex)83 void SelectionPoint::draw(QPainter* p, double scalex) {
84   QColor brushColor;
85 
86   switch (state) {
87   case Normal:
88     brushColor = Qt::white;
89     break;
90   case HighLighted:
91     brushColor = Qt::green;
92     break;
93   case AboutToRemove:
94     brushColor = Qt::red;
95     break;
96   case Inactive:
97     brushColor = Qt::gray;
98     break;
99   }
100 
101   QPoint scaledCenter((int)(point.x()*scalex),
102 		      (int)(point.y()*scalex));
103 
104   if (state == HighLighted || state == AboutToRemove) {
105     QRect r2(0,0,SELSIZE+4,SELSIZE+4);
106 
107     r2.moveCenter(scaledCenter);
108     QColor color(brushColor);
109     color.setAlpha(100);
110     p->setPen(QPen(color,4,Qt::SolidLine));
111     p->setBrush(Qt::NoBrush);
112     p->drawRect(r2);
113 
114   }
115 
116   //  brushColor.setAlpha(230);
117   brushColor.setAlpha(200);
118   p->setBrush(QBrush(brushColor,Qt::SolidPattern));
119 
120   QColor penColor = Qt::black;
121   penColor.setAlpha(120);
122   QPen pen(penColor, 2, Qt::SolidLine);
123 
124   QRect r(0,0,SELSIZE,SELSIZE);
125   r.moveCenter( scaledCenter );
126 
127   p->setPen(pen);
128   p->drawRect(r);
129 
130 
131 }
132 
133 
134 bool Area::highlightArea;
135 bool Area::showAlt;
136 
137 
Area()138 Area::Area()
139 {
140 	_finished=false;
141 	_isSelected=false;
142 	_name=i18n("noname");
143 	_listViewItem = nullptr;
144 	currentHighlighted=-1;
145 	_type=Area::None;
146 }
147 
clone() const148 Area* Area::clone() const
149 {
150 	Area* areaClone = new Area();
151 	areaClone->setArea( *this );
152 	return areaClone;
153 }
154 
coords() const155 QPolygon Area::coords() const {
156 	return _coords;
157 }
158 
getHTMLAttributes() const159 QString Area::getHTMLAttributes() const
160 {
161 	QString retStr="";
162 
163 	AttributeIterator it = attributeIterator();
164 	while (it.hasNext())
165 	{
166 	  it.next();
167     retStr+=it.key()+"=\""+it.value()+"\" ";
168 	}
169 
170   return retStr;
171 }
172 
resetSelectionPointState()173 void Area::resetSelectionPointState() {
174   setSelectionPointStates(SelectionPoint::Normal);
175 }
176 
setSelectionPointStates(SelectionPoint::State st)177 void Area::setSelectionPointStates(SelectionPoint::State st) {
178   for (int i=0;i<_selectionPoints.size();i++) {
179     _selectionPoints.at(i)->setState(st);
180   }
181 }
182 
183 
184 
185 
deleteSelectionPoints()186 void Area::deleteSelectionPoints() {
187   for (int i=0;i<_selectionPoints.size();i++) {
188     delete _selectionPoints.at(i);
189   }
190   _selectionPoints.clear();
191 }
192 
~Area()193 Area::~Area() {
194   deleteSelectionPoints();
195 }
196 
contains(const QPoint &) const197 bool Area::contains(const QPoint &) const {
198   return false;
199 }
200 
getHTMLCode() const201 QString Area::getHTMLCode() const {
202   return "";
203 }
204 
attribute(const QString & name) const205 QString Area::attribute(const QString & name) const
206 {
207   return _attributes[name.toLower()];
208 }
209 
setAttribute(const QString & name,const QString & value)210 void Area::setAttribute(const QString & name, const QString & value)
211 {
212   _attributes.insert(name.toLower(), value);
213   if (value.isEmpty())
214      _attributes.remove(name.toLower());
215 }
216 
attributeIterator() const217 AttributeIterator Area::attributeIterator() const
218 {
219   return AttributeIterator(_attributes);
220 }
221 
setCoords(const QString &)222 bool Area::setCoords(const QString &) {
223   return true;
224 }
225 
moveSelectionPoint(SelectionPoint *,const QPoint &)226 void Area::moveSelectionPoint(SelectionPoint*, const QPoint &)
227 {}
228 
229 // Default implementation; is specified by subclasses
coordsToString() const230 QString Area::coordsToString() const
231 {
232   return "";
233 }
234 
235 
type() const236 Area::ShapeType Area::type() const {
237 	return _type;
238 }
239 
setArea(const Area & copy)240 void Area::setArea(const Area & copy)
241 {
242   deleteSelectionPoints();
243   _coords.clear();
244   _coords += copy.coords();
245   currentHighlighted=-1;
246 
247   SelectionPointList points = copy.selectionPoints();
248   for (int i=0; i<points.size(); i++) {
249     SelectionPoint* np =
250       new SelectionPoint(points.at(i)->getPoint(),points.at(i)->cursor());
251     _selectionPoints.append(np);
252   }
253 
254   _finished=copy.finished();
255   _isSelected=copy.isSelected();
256   _rect = copy.rect();
257 
258   AttributeIterator it = copy.attributeIterator();
259   while (it.hasNext()) {
260     it.next();
261     setAttribute(it.key(),it.value());
262   }
263 
264   setMoving(copy.isMoving());
265 }
266 
setFinished(bool b,bool)267 void Area::setFinished(bool b, bool ) {
268   _finished=b;
269 }
270 
271 
setListViewItem(QTreeWidgetItem * item)272 void Area::setListViewItem(QTreeWidgetItem* item) {
273 	_listViewItem=item;
274 }
275 
deleteListViewItem()276 void Area::deleteListViewItem()
277 {
278 	delete _listViewItem;
279 	_listViewItem = nullptr;
280 }
281 
282 
setRect(const QRect & r)283 void Area::setRect(const QRect & r)
284 {
285   _rect=r;
286 	updateSelectionPoints();
287 }
288 
rect() const289 QRect Area::rect() const {
290 	return _rect;
291 }
292 
setMoving(bool b)293 void Area::setMoving(bool b) {
294   _isMoving=b;
295 }
296 
297 
moveBy(int dx,int dy)298 void Area::moveBy(int dx, int dy) {
299   _rect.translate(dx,dy);
300   _coords.translate(dx,dy);
301 
302   for (int i=0;i < _selectionPoints.size(); i++) {
303     _selectionPoints.at(i)->translate(dx,dy);
304   }
305 }
306 
307 
moveTo(int x,int y)308 void Area::moveTo(int x, int y) {
309 	int dx = x-rect().left();
310 	int dy = y-rect().top();
311 	moveBy(dx,dy);
312 }
313 
countSelectionPoints() const314 int Area::countSelectionPoints() const
315 {
316   return selectionPoints().size();
317 }
318 
addCoord(const QPoint & p)319 int Area::addCoord(const QPoint & p)
320 {
321   _coords.resize(_coords.size()+1);
322   _coords.setPoint(_coords.size()-1,p);
323   _selectionPoints.append(new SelectionPoint(p,QCursor(Qt::PointingHandCursor)));
324   setRect(_coords.boundingRect());
325 
326   return _coords.size()-1;
327 }
328 
insertCoord(int pos,const QPoint & p)329 void Area::insertCoord(int pos, const QPoint & p)
330 {
331   _coords.resize(_coords.size()+1);
332 
333 
334   for (int i=_coords.size()-1;i>pos;i--) {
335     _coords.setPoint(i,_coords.point(i-1));
336   }
337   _coords.setPoint(pos, p);
338 
339   _selectionPoints.insert(pos,new SelectionPoint(p,QCursor(Qt::PointingHandCursor)));
340   setRect(_coords.boundingRect());
341 }
342 
removeCoord(int pos)343 void Area::removeCoord(int pos) {
344 
345   int count =_coords.size();
346 
347   if (count<4){
348     qCDebug(KIMAGEMAPEDITOR_LOG) << "Danger : trying to remove coordinate from Area with less than 4 coordinates !";
349     return;
350   }
351 
352   for (int i=pos;i<(count-1);i++)
353     _coords.setPoint(i, _coords.point(i+1));
354 
355   _coords.resize(count-1);
356   delete _selectionPoints.takeAt(pos);
357   setRect(_coords.boundingRect());
358 }
359 
removeSelectionPoint(SelectionPoint * p)360 bool Area::removeSelectionPoint(SelectionPoint * p)
361 {
362   if (_selectionPoints.contains(p))
363   {
364     removeCoord(_selectionPoints.indexOf(p));
365     return true;
366   }
367 
368   return false;
369 }
370 
371 
moveCoord(int pos,const QPoint & p)372 void Area::moveCoord(int pos, const QPoint & p) {
373   _coords.setPoint(pos,p);
374   _selectionPoints.at(pos)->setPoint(p);
375   setRect(_coords.boundingRect());
376 }
377 
setSelected(bool b)378 void Area::setSelected(bool b)
379 {
380   _isSelected=b;
381   if (_listViewItem) {
382     _listViewItem->setSelected(b);
383   }
384 }
385 
highlightSelectionPoint(int number)386 void Area::highlightSelectionPoint(int number){
387 	currentHighlighted=number;
388 }
389 
selectionRect() const390 QRect Area::selectionRect() const {
391   QRect r = rect();
392   r.translate(-SELSIZE*2,-SELSIZE*2);
393   r.setSize(r.size()+QSize(SELSIZE*4,SELSIZE*4));
394 
395   return r;
396 }
397 
setPenAndBrush(QPainter * p)398 void Area::setPenAndBrush(QPainter* p) {
399   QBrush brush(Qt::NoBrush);
400   if (highlightArea) {
401     QColor back = Qt::white;
402     back.setAlpha(80);
403     brush = QBrush(back,Qt::SolidPattern);
404   }
405 
406   p->setBrush(brush);
407 
408   QColor front = Qt::white;
409   front.setAlpha(200);
410   p->setPen(QPen(front,1));
411 }
412 
413 
drawAlt(QPainter * p)414 void Area::drawAlt(QPainter* p)
415 {
416   double x,y;
417 
418   const double scalex = p->transform().m11();
419 //  double scaley = p.matrix().m12();
420 
421   const QTransform oldTransform = p->transform();
422 
423   p->setTransform(QTransform(1,oldTransform.m12(), oldTransform.m21(), 1, oldTransform.dx(), oldTransform.dy() ));
424 
425   x = (rect().x()+rect().width()/2)*scalex;
426   y = (rect().y()+rect().height()/2)*scalex;
427 
428   const QFontMetrics metrics = p->fontMetrics();
429 
430   const int w = metrics.boundingRect(attribute("alt")).width();
431   x -= w/2;
432   y += metrics.height()/4;
433 
434 
435 
436   if (highlightArea)  {
437     p->setPen(Qt::black);
438   } else  {
439     p->setPen(QPen(QColor("white"),1));
440   }
441 
442   p->drawText(myround(x),myround(y),attribute("alt"));
443 
444   p->setTransform(oldTransform);
445 }
446 
draw(QPainter * p)447 void Area::draw(QPainter * p)
448 {
449 
450   // Only draw the selection points at base class
451   // the rest is done in the derived classes
452   if (_isSelected)  {
453     // We do not want to have the selection points
454     // scaled, so calculate the unscaled version
455     const double scalex = p->transform().m11();
456     const QTransform oldTransform = p->transform();
457     p->setTransform(QTransform(1,oldTransform.m12(),
458 			 oldTransform.m21(), 1,
459 			 oldTransform.dx(),
460 			 oldTransform.dy() ));
461 
462     for (int i=0; i<_selectionPoints.size(); i++) {
463       _selectionPoints.at(i)->draw(p,scalex);
464     }
465     p->setTransform(oldTransform);
466   }
467 
468   if (showAlt) {
469     drawAlt(p);
470   }
471 
472 }
473 
onSelectionPoint(const QPoint & p,double zoom) const474 SelectionPoint* Area::onSelectionPoint(const QPoint & p, double zoom) const
475 {
476 
477   for (int i=0; i<_selectionPoints.size(); i++) {
478     SelectionPoint* sp = _selectionPoints.at(i);
479 
480     QRect r = sp->getRect();
481 
482     r.moveCenter(sp->getPoint()*zoom);
483 
484     if (r.contains(p))
485     {
486       return sp;
487     }
488   }
489 
490   return nullptr;
491 }
492 
493 
494 
495 
496 /**
497  * returns only the part of the image which is
498  * covered by the area
499  */
cutOut(const QImage & image)500 QPixmap Area::cutOut(const QImage & image)
501 {
502 	if ( 0>=rect().width()  ||
503 			 0>=rect().height() ||
504        !rect().intersects(image.rect())   )
505 	{
506 		QPixmap dummyPix(10,10);
507 		dummyPix.fill();
508 		return dummyPix;
509 	}
510 
511 	// Get the mask from the subclasses
512 	QBitmap mask=getMask();
513 
514 	// The rectangle which is part of the image
515 	QRect partOfImage=rect();
516 	QRect partOfMask(0,0,mask.width(),mask.height());
517 
518 
519 	// If the area is outside of the image make the
520 	// preview smaller
521 	if ( (rect().x()+rect().width()) > image.width() ) {
522 		partOfImage.setWidth( image.width()-rect().x() );
523 		partOfMask.setWidth(  image.width()-rect().x() );
524 	}
525 
526 	if ( (rect().x() < 0) ) {
527 		partOfImage.setX(0);
528 		partOfMask.setX(myabs(rect().x()));
529 	}
530 
531 	if ( (rect().y()+rect().height()) > image.height() ) {
532 		partOfImage.setHeight( image.height()-rect().y() );
533 		partOfMask.setHeight ( image.height()-rect().y() );
534 	}
535 
536 	if ( (rect().y() < 0) ) {
537 		partOfImage.setY(0);
538 		partOfMask.setY(myabs(rect().y()));
539 	}
540 
541         QImage tempImage=mask.toImage().copy(partOfMask);
542 	mask = QPixmap::fromImage(tempImage);
543 
544 //  partOfImage = partOfImage.normalize();
545 	QImage cut=image.copy(partOfImage);
546 
547 	QPixmap pix;
548 
549 //  partOfMask = partOfMask.normalize();
550 	if (!partOfMask.isValid())
551 	   qCDebug(KIMAGEMAPEDITOR_LOG) << "PartofMask not valid : " << partOfMask.x() << "," << partOfMask.y() << ","
552                 << partOfMask.width() << "," << partOfMask.height() << ",";
553 
554 /*
555 	QBitmap mask2(partOfMask.width(), partOfMask.height());
556 	QPainter p4(&mask2);
557 	p4.drawPixmap( QPoint(0,0) ,mask,partOfMask);
558 	p4.flush();
559 	p4.end();
560 */
561 
562 	pix = QPixmap::fromImage(cut);
563 
564 	//	setHighlightedPixmap(cut, mask);
565 
566 	QPixmap retPix(pix.width(),pix.height());
567   QPainter p3(&retPix);
568 
569 	// if transparent image fill the background
570 	// with gimp-like rectangles
571 	if (!pix.mask().isNull()) {
572   	QPixmap backPix(32,32);
573 
574   	// Gimp like transparent rectangle
575   	QPainter p2(&backPix);
576   	p2.fillRect(0,0,32,32,QColor(156,149,156));
577   	p2.fillRect(0,16,16,16,QColor(98,105,98));
578   	p2.fillRect(16,0,16,16,QColor(98,105,98));
579 
580   	p3.setPen(QPen());
581   	p3.fillRect(0,0,pix.width(),pix.height(),QBrush(QColor("black"),backPix));
582 	}
583 
584 
585 	p3.drawPixmap(QPoint(0,0),pix);
586 	p3.end();
587 	retPix.setMask(mask);
588 
589 	return retPix;
590 }
591 
getMask() const592 QBitmap Area::getMask() const
593 {
594 	QBitmap b;
595 	return b;
596 }
597 
598 /********************************************************************
599  * RECTANGLE
600  *******************************************************************/
601 
602 
RectArea()603 RectArea::RectArea()
604 	: Area()
605 {
606   _type=Area::Rectangle;
607   QPoint p(0,0);
608   _selectionPoints.append(new SelectionPoint(p,Qt::SizeFDiagCursor));
609   _selectionPoints.append(new SelectionPoint(p,Qt::SizeBDiagCursor));
610   _selectionPoints.append(new SelectionPoint(p,Qt::SizeBDiagCursor));
611   _selectionPoints.append(new SelectionPoint(p,Qt::SizeFDiagCursor));
612   _selectionPoints.append(new SelectionPoint(p,Qt::SizeVerCursor));
613   _selectionPoints.append(new SelectionPoint(p,Qt::SizeHorCursor));
614   _selectionPoints.append(new SelectionPoint(p,Qt::SizeVerCursor));
615   _selectionPoints.append(new SelectionPoint(p,Qt::SizeHorCursor));
616 }
617 
~RectArea()618 RectArea::~RectArea() {
619 }
620 
clone() const621 Area* RectArea::clone() const
622 {
623 	Area* areaClone = new RectArea();
624 	areaClone->setArea( *this );
625 	return areaClone;
626 }
627 
draw(QPainter * p)628 void RectArea::draw(QPainter * p)
629 {
630   setPenAndBrush(p);
631 
632   QRect r(rect());
633   r.setWidth(r.width()+1);
634   r.setHeight(r.height()+1);
635   p->drawRect(r);
636 
637   Area::draw(p);
638 }
639 
getMask() const640 QBitmap RectArea::getMask() const
641 {
642 	QBitmap mask(rect().width(),rect().height());
643 
644 	mask.fill(Qt::color0);
645 	QPainter p(&mask);
646 	p.setBackground(QBrush(Qt::color0));
647 	p.setPen(Qt::color1);
648 	p.setBrush(Qt::color1);
649 	mask.fill(Qt::color1);
650 	p.end();
651 
652 	return mask;
653 }
654 
coordsToString() const655 QString RectArea::coordsToString() const
656 {
657 	QString retStr=QString("%1,%2,%3,%4")
658 					.arg(rect().left())
659 					.arg(rect().top())
660 					.arg(rect().right())
661 					.arg(rect().bottom());
662 
663 	return retStr;
664 }
665 
contains(const QPoint & p) const666 bool RectArea::contains(const QPoint & p) const{
667 	return rect().contains(p);
668 }
669 
moveSelectionPoint(SelectionPoint * selectionPoint,const QPoint & p)670 void RectArea::moveSelectionPoint(SelectionPoint* selectionPoint, const QPoint & p)
671 {
672 	selectionPoint->setPoint(p);
673  	int i = _selectionPoints.indexOf(selectionPoint);
674 
675  	QRect r2(_rect);
676  	switch (i) {
677 	case 0 :
678 	  _rect.setLeft(p.x());
679 	  _rect.setTop(p.y());
680 	  break;
681 	case 1 :
682 	  _rect.setRight(p.x());
683 	  _rect.setTop(p.y());
684 	  break;
685 	case 2 :
686 	  _rect.setLeft(p.x());
687 	  _rect.setBottom(p.y());
688 	  break;
689 	case 3 :
690 	  _rect.setRight(p.x());
691 	  _rect.setBottom(p.y());
692 	  break;
693 	case 4 : // top line
694 	  _rect.setTop(p.y());
695 	  break;
696 	case 5 : // right line
697 	  _rect.setRight(p.x());
698 	  break;
699 	case 6 : // bottom
700 	  _rect.setBottom(p.y());
701 	  break;
702 	case 7 : // left
703 	  _rect.setLeft(p.x());
704 	  break;
705 
706  	}
707  	if (! _rect.isValid())
708 	  _rect=r2;
709 
710  	updateSelectionPoints();
711 }
712 
updateSelectionPoints()713 void RectArea::updateSelectionPoints()
714 {
715   int d = 2;
716   QRect r(_rect);
717   r.adjust(0,0,1,1);
718   int xmid = r.left()+(r.width()/d);
719   int ymid = r.top()+(r.height()/d);
720 
721 
722   _selectionPoints[0]->setPoint(r.topLeft());
723   _selectionPoints[1]->setPoint(r.topRight());
724   _selectionPoints[2]->setPoint(r.bottomLeft());
725   _selectionPoints[3]->setPoint(r.bottomRight());
726   _selectionPoints[4]->setPoint(QPoint(xmid,r.top()));
727   _selectionPoints[5]->setPoint(QPoint(r.right(),ymid));
728   _selectionPoints[6]->setPoint(QPoint(xmid,r.bottom()));
729   _selectionPoints[7]->setPoint(QPoint(r.left(),ymid));
730 }
731 
setCoords(const QString & s)732 bool RectArea::setCoords(const QString & s)
733 {
734 	_finished=true;
735 
736 	const QStringList list = s.split(',');
737 	QRect r;
738  	bool ok=true;
739  	QStringList::ConstIterator it = list.begin();
740 	r.setLeft((*it).toInt(&ok,10));it++;
741 	r.setTop((*it).toInt(&ok,10));it++;
742 	r.setRight((*it).toInt(&ok,10));it++;
743 	r.setBottom((*it).toInt(&ok,10));
744 	if (ok) {
745 	  setRect(r);
746 	  return true;
747 	} else {
748 	  return false;
749 	}
750 }
751 
getHTMLCode() const752 QString RectArea::getHTMLCode() const {
753 	QString retStr;
754 	retStr+="<area ";
755 	retStr+="shape=\"rect\" ";
756 
757 	retStr+=getHTMLAttributes();
758 
759 	retStr+="coords=\""+coordsToString()+"\" ";
760 	retStr+="/>";
761 	return retStr;
762 
763 }
764 
765 /********************************************************************
766  * CIRCLE
767  *******************************************************************/
768 
769 
CircleArea()770 CircleArea::CircleArea()
771 	: Area()
772 {
773   _type = Area::Circle;
774   QPoint p(0,0);
775   _selectionPoints.append(new SelectionPoint(p,Qt::SizeFDiagCursor));
776   _selectionPoints.append(new SelectionPoint(p,Qt::SizeBDiagCursor));
777   _selectionPoints.append(new SelectionPoint(p,Qt::SizeBDiagCursor));
778   _selectionPoints.append(new SelectionPoint(p,Qt::SizeFDiagCursor));
779 }
780 
~CircleArea()781 CircleArea::~CircleArea() {
782 }
783 
clone() const784 Area* CircleArea::clone() const
785 {
786 	Area* areaClone = new CircleArea();
787 	areaClone->setArea( *this );
788 	return areaClone;
789 }
790 
draw(QPainter * p)791 void CircleArea::draw(QPainter * p)
792 {
793   setPenAndBrush(p);
794 
795   QRect r(_rect);
796   r.setWidth(r.width()+1);
797   r.setHeight(r.height()+1);
798   p->drawEllipse(r);
799 
800   Area::draw(p);
801 }
802 
getMask() const803 QBitmap CircleArea::getMask() const
804 {
805 	QBitmap mask(_rect.width(),_rect.height());
806 
807 	mask.fill(Qt::color0);
808 	QPainter p(&mask);
809 	p.setBackground(QBrush(Qt::color0));
810 	p.setPen(Qt::color1);
811 	p.setBrush(Qt::color1);
812 	p.drawPie(QRect(0,0,_rect.width(),_rect.height()),0,5760);
813 	p.end();
814 
815 
816 	return mask;
817 
818 }
819 
coordsToString() const820 QString CircleArea::coordsToString() const
821 {
822 	QString retStr=QString("%1,%2,%3")
823 					.arg(_rect.center().x())
824 					.arg(_rect.center().y())
825 					.arg(_rect.width()/2);
826 
827 	return retStr;
828 }
829 
contains(const QPoint & p) const830 bool CircleArea::contains(const QPoint & p) const
831 {
832 	QRegion r(_rect,QRegion::Ellipse);
833 	return r.contains(p);
834 }
835 
moveSelectionPoint(SelectionPoint * selectionPoint,const QPoint & p)836 void CircleArea::moveSelectionPoint(SelectionPoint* selectionPoint, const QPoint & p)
837 {
838   selectionPoint->setPoint(p);
839 
840   int i = _selectionPoints.indexOf(selectionPoint);
841 
842   // The code below really sucks, but I have no better idea.
843   // it only makes sure that the circle is perfectly round
844 
845   QPoint newPoint;
846   int diff=myabs(p.x()-_rect.center().x());
847   if (myabs(p.y()-_rect.center().y())>diff)
848     diff=myabs(p.y()-_rect.center().y());
849 
850   newPoint.setX( p.x()-_rect.center().x()<0
851 		 ? _rect.center().x()-diff
852 		 :	_rect.center().x()+diff);
853 
854   newPoint.setY( p.y()-_rect.center().y()<0
855 		 ? _rect.center().y()-diff
856 		 :	_rect.center().y()+diff);
857 
858   switch (i) {
859   case 0 : if (newPoint.x() < _rect.center().x() &&
860 	       newPoint.y() < _rect.center().y())
861     {
862       _rect.setLeft(newPoint.x());
863       _rect.setTop(newPoint.y());
864     }
865     break;
866   case 1 : if (newPoint.x() > _rect.center().x() &&
867 	       newPoint.y() < _rect.center().y())
868     {
869       _rect.setRight(newPoint.x());
870       _rect.setTop(newPoint.y());
871     }
872     break;
873   case 2 : if (newPoint.x() < _rect.center().x() &&
874 	       newPoint.y() > _rect.center().y())
875     {
876       _rect.setLeft(newPoint.x());
877       _rect.setBottom(newPoint.y());
878     }
879     break;
880   case 3 : if (newPoint.x() > _rect.center().x() &&
881 	       newPoint.y() > _rect.center().y())
882     {
883       _rect.setRight(newPoint.x());
884       _rect.setBottom(newPoint.y());
885     }
886     break;
887   }
888 
889 
890 
891   updateSelectionPoints();
892 
893 }
894 
setRect(const QRect & r)895 void CircleArea::setRect(const QRect & r)
896 {
897 	QRect r2 = r;
898 	if ( r2.height() != r2.width() )
899 	   r2.setHeight( r2.width() );
900 
901 	Area::setRect(r2);
902 }
903 
904 
updateSelectionPoints()905 void CircleArea::updateSelectionPoints()
906 {
907   _selectionPoints[0]->setPoint(_rect.topLeft());
908   _selectionPoints[1]->setPoint(_rect.topRight());
909   _selectionPoints[2]->setPoint(_rect.bottomLeft());
910   _selectionPoints[3]->setPoint(_rect.bottomRight());
911 }
912 
setCoords(const QString & s)913 bool CircleArea::setCoords(const QString & s)
914 {
915 	_finished=true;
916 	const QStringList list = s.split(',');
917  	bool ok=true;
918  	QStringList::ConstIterator it = list.begin();
919  	int x=(*it).toInt(&ok,10);it++;
920  	int y=(*it).toInt(&ok,10);it++;
921  	int rad=(*it).toInt(&ok,10);
922  	if (!ok) return false;
923  	QRect r;
924  	r.setWidth(rad*2);
925  	r.setHeight(rad*2);
926  	r.moveCenter(QPoint(x,y));
927  	setRect(r);
928 	return true;
929 }
930 
getHTMLCode() const931 QString CircleArea::getHTMLCode() const {
932 	QString retStr;
933 	retStr+="<area ";
934 	retStr+="shape=\"circle\" ";
935 
936 	retStr+=getHTMLAttributes();
937 
938 	retStr+="coords=\""+coordsToString()+"\" ";
939 	retStr+="/>";
940 	return retStr;
941 
942 }
943 
944 
945 /********************************************************************
946  * POLYGON
947  *******************************************************************/
948 
949 
PolyArea()950 PolyArea::PolyArea()
951 	: Area()
952 {
953   _type = Area::Polygon;
954 }
955 
~PolyArea()956 PolyArea::~PolyArea() {
957 }
958 
clone() const959 Area* PolyArea::clone() const
960 {
961 	Area* areaClone = new PolyArea();
962 	areaClone->setArea( *this );
963 	return areaClone;
964 }
965 
draw(QPainter * p)966 void PolyArea::draw(QPainter * p)
967 {
968   setPenAndBrush(p);
969 
970   if (_finished)
971     p->drawPolygon( _coords.constData(),_coords.count());
972   else {
973     p->drawPolyline(_coords.constData(),_coords.count());
974   }
975 
976   Area::draw(p);
977 }
978 
getMask() const979 QBitmap PolyArea::getMask() const
980 {
981 	QBitmap mask(_rect.width(),_rect.height());
982 
983 	mask.fill(Qt::color0);
984 	QPainter p(&mask);
985 	p.setBackground(QBrush(Qt::color0));
986 	p.setPen(Qt::color1);
987 	p.setBrush(Qt::color1);
988  	p.setClipping(true);
989  	QRegion r(_coords);
990  	r.translate(-_rect.left(),-_rect.top());
991  	p.setClipRegion(r);
992  	p.fillRect(QRect(0,0,_rect.width(),_rect.height()),Qt::color1);
993 	p.end();
994 
995 	return mask;
996 }
997 
coordsToString() const998 QString PolyArea::coordsToString() const
999 {
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 
distance(const QPoint & p1,const QPoint & p2)1013 int PolyArea::distance(const QPoint &p1, const QPoint &p2)
1014 {
1015   QPoint temp = p1-p2;
1016   return temp.manhattanLength();
1017 }
1018 
isBetween(const QPoint & p,const QPoint & p1,const QPoint & p2)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 
simplifyCoords()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 
addCoord(const QPoint & p)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 
contains(const QPoint & p) const1131 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 
moveSelectionPoint(SelectionPoint * selectionPoint,const QPoint & p)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 
updateSelectionPoints()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 
setCoords(const QString & s)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 
getHTMLCode() const1181 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 
setFinished(bool b,bool removeLast=true)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 
selectionRect() const1206 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 
DefaultArea()1223 DefaultArea::DefaultArea()
1224 	: Area()
1225 {
1226 	_type=Area::Default;
1227 }
1228 
~DefaultArea()1229 DefaultArea::~DefaultArea() {
1230 }
1231 
clone() const1232 Area* DefaultArea::clone() const
1233 {
1234 	Area* areaClone = new DefaultArea();
1235 	areaClone->setArea( *this );
1236 	return areaClone;
1237 }
1238 
draw(QPainter *)1239 void DefaultArea::draw(QPainter *)
1240 {}
1241 
1242 
getHTMLCode() const1243 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 
AreaSelection()1260 AreaSelection::AreaSelection()
1261 	: Area()
1262 {
1263 	_areas = new AreaList();
1264 	_name = "Selection";
1265 	invalidate();
1266 }
1267 
~AreaSelection()1268 AreaSelection::~AreaSelection() {
1269 	delete _areas;
1270 }
1271 
clone() const1272 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 
add(Area * a)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 
setSelectionPointStates(SelectionPoint::State st)1310 void AreaSelection::setSelectionPointStates(SelectionPoint::State st) {
1311   AreaListIterator it=getAreaListIterator();
1312   while(it.hasNext()) {
1313     it.next()->setSelectionPointStates( st );
1314   }
1315 }
1316 
updateSelectionPointStates()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 
remove(Area * a)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 
reset()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 
contains(const QPoint & p) const1348 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 
onSelectionPoint(const QPoint & p,double zoom) const1360 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 
moveSelectionPoint(SelectionPoint * selectionPoint,const QPoint & p)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 
moveBy(int dx,int dy)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 
typeString() const1392 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 
type() const1405 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 
resetSelectionPointState()1417 void AreaSelection::resetSelectionPointState() {
1418   updateSelectionPointStates();
1419 }
1420 
updateSelectionPoints()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 
selectionRect() const1433 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 
count() const1448 int AreaSelection::count() const {
1449   return _areas->count();
1450 }
1451 
isEmpty() const1452 bool AreaSelection::isEmpty() const
1453 {
1454   return _areas->isEmpty();
1455 }
1456 
1457 
getAreaList() const1458 AreaList AreaSelection::getAreaList() const {
1459   AreaList list(*_areas);
1460   return list;
1461 }
1462 
getAreaListIterator() const1463 AreaListIterator AreaSelection::getAreaListIterator() const {
1464   AreaListIterator it(*_areas);
1465   return it;
1466 }
1467 
setArea(const Area & copy)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 
setAreaSelection(const AreaSelection & copy)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 
setAreaList(const AreaList & areas)1497 void AreaSelection::setAreaList( const AreaList & areas )
1498 {
1499   delete _areas;
1500   _areas = new AreaList(areas);
1501   invalidate();
1502 }
1503 
setRect(const QRect & r)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 
rect() const1516 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 
addCoord(const QPoint & p)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 
insertCoord(int pos,const QPoint & p)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 
removeCoord(int pos)1555 void AreaSelection::removeCoord(int pos)
1556 {
1557 	if ( _areas->count()==1 )
1558 	{
1559 		_areas->first()->removeCoord(pos);
1560 		invalidate();
1561 	}
1562 }
1563 
removeSelectionPoint(SelectionPoint * p)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 
selectionPoints() const1577 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 
moveCoord(int pos,const QPoint & p)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 
highlightSelectionPoint(int i)1597 void AreaSelection::highlightSelectionPoint(int i)
1598 {
1599 	if ( _areas->count()==1 )
1600 	{
1601 		_areas->first()->highlightSelectionPoint(i);
1602 		invalidate();
1603 	}
1604 }
1605 
1606 
coords() const1607 QPolygon AreaSelection::coords() const
1608 {
1609 	if ( _areas->count()==1 )
1610 	{
1611 		return _areas->first()->coords();
1612 	}
1613 
1614 	return Area::coords();
1615 }
1616 
attribute(const QString & name) const1617 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 
setAttribute(const QString & name,const QString & value)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 
attributeIterator() const1638 AttributeIterator AreaSelection::attributeIterator() const
1639 {
1640 	if ( _areas->count()==1 )
1641 	{
1642 		return _areas->first()->attributeIterator();
1643 	}
1644 
1645   return AttributeIterator(_attributes);
1646 }
1647 
setMoving(bool b)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 
isMoving() const1659 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  **/
allAreasWithin(const QRect & r) const1674 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 
draw(QPainter *)1690 void AreaSelection::draw(QPainter *)
1691 {}
1692 
invalidate()1693 void AreaSelection::invalidate() {
1694   _selectionCacheValid=false;
1695   _rectCacheValid=false;
1696   updateSelectionPointStates();
1697 }
1698 
1699 
1700