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 <QPolygon> |
19 | |
20 | #include <qbitmap.h> |
21 | #include <qpainter.h> |
22 | #include <qpixmap.h> |
23 | #include <qimage.h> |
24 | #include <qpen.h> |
25 | #include <qbrush.h> |
26 | #include <qpalette.h> |
27 | #include <qcolor.h> |
28 | |
29 | #include <kdebug.h> |
30 | |
31 | #include "kimearea.h" |
32 | #include "kimecommon.h" |
33 | |
34 | |
35 | // The size of Selection Points |
36 | |
37 | SelectionPoint::SelectionPoint(QPoint p, QCursor c) |
38 | { |
39 | point = p; |
40 | state = Normal; |
41 | _cursor = c; |
42 | } |
43 | |
44 | SelectionPoint::~SelectionPoint() { |
45 | } |
46 | |
47 | void SelectionPoint::setState(SelectionPoint::State s) { |
48 | state = s; |
49 | } |
50 | |
51 | SelectionPoint::State SelectionPoint::getState() const { |
52 | return state; |
53 | } |
54 | |
55 | void SelectionPoint::setPoint(QPoint p) { |
56 | point = p; |
57 | } |
58 | |
59 | void SelectionPoint::translate(int dx, int dy) { |
60 | point += QPoint(dx,dy); |
61 | } |
62 | |
63 | |
64 | QPoint SelectionPoint::getPoint() const { |
65 | return point; |
66 | } |
67 | |
68 | QRect SelectionPoint::getRect() const { |
69 | QRect r(0,0,SELSIZE,SELSIZE); |
70 | r.moveCenter(point); |
71 | return r; |
72 | } |
73 | |
74 | QCursor SelectionPoint::cursor() { |
75 | return _cursor; |
76 | } |
77 | |
78 | void SelectionPoint::setCursor(QCursor c) { |
79 | _cursor = c; |
80 | } |
81 | |
82 | |
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 | int d = 1; |
102 | if (scalex > 2) |
103 | d = 0; |
104 | |
105 | QPoint scaledCenter((int)(point.x()*scalex), |
106 | (int)(point.y()*scalex)); |
107 | |
108 | if (state == HighLighted || state == AboutToRemove) { |
109 | QRect r2(0,0,SELSIZE+4,SELSIZE+4); |
110 | |
111 | r2.moveCenter(scaledCenter); |
112 | QColor color(brushColor); |
113 | color.setAlpha(100); |
114 | p->setPen(QPen(color,4,Qt::SolidLine)); |
115 | p->setBrush(Qt::NoBrush); |
116 | p->drawRect(r2); |
117 | |
118 | } |
119 | |
120 | // brushColor.setAlpha(230); |
121 | brushColor.setAlpha(200); |
122 | p->setBrush(QBrush(brushColor,Qt::SolidPattern)); |
123 | |
124 | QColor penColor = Qt::black; |
125 | penColor.setAlpha(120); |
126 | QPen pen(penColor, 2, Qt::SolidLine); |
127 | |
128 | QRect r(0,0,SELSIZE,SELSIZE); |
129 | r.moveCenter( scaledCenter ); |
130 | |
131 | p->setPen(pen); |
132 | p->drawRect(r); |
133 | |
134 | |
135 | } |
136 | |
137 | |
138 | bool Area::highlightArea; |
139 | bool Area::showAlt; |
140 | |
141 | |
142 | Area::Area() |
143 | { |
144 | _finished=false; |
145 | _isSelected=false; |
146 | _name=i18n("noname" ); |
147 | _listViewItem=0L; |
148 | currentHighlighted=-1; |
149 | _type=Area::None; |
150 | } |
151 | |
152 | Area* Area::clone() const |
153 | { |
154 | Area* areaClone = new Area(); |
155 | areaClone->setArea( *this ); |
156 | return areaClone; |
157 | } |
158 | |
159 | QPolygon Area::coords() const { |
160 | return _coords; |
161 | } |
162 | |
163 | QString Area::getHTMLAttributes() const |
164 | { |
165 | QString retStr="" ; |
166 | |
167 | AttributeIterator it = attributeIterator(); |
168 | while (it.hasNext()) |
169 | { |
170 | it.next(); |
171 | retStr+=it.key()+"=\"" +it.value()+"\" " ; |
172 | } |
173 | |
174 | return retStr; |
175 | } |
176 | |
177 | void Area::resetSelectionPointState() { |
178 | setSelectionPointStates(SelectionPoint::Normal); |
179 | } |
180 | |
181 | void Area::setSelectionPointStates(SelectionPoint::State st) { |
182 | for (int i=0;i<_selectionPoints.size();i++) { |
183 | _selectionPoints.at(i)->setState(st); |
184 | } |
185 | } |
186 | |
187 | |
188 | |
189 | |
190 | void Area::deleteSelectionPoints() { |
191 | for (int i=0;i<_selectionPoints.size();i++) { |
192 | delete _selectionPoints.at(i); |
193 | } |
194 | _selectionPoints.clear(); |
195 | } |
196 | |
197 | Area::~Area() { |
198 | deleteSelectionPoints(); |
199 | } |
200 | |
201 | bool Area::contains(const QPoint &) const { |
202 | return false; |
203 | } |
204 | |
205 | QString Area::getHTMLCode() const { |
206 | return "" ; |
207 | } |
208 | |
209 | QString Area::attribute(const QString & name) const |
210 | { |
211 | return _attributes[name.toLower()]; |
212 | } |
213 | |
214 | void Area::setAttribute(const QString & name, const QString & value) |
215 | { |
216 | _attributes.insert(name.toLower(), value); |
217 | if (value.isEmpty()) |
218 | _attributes.remove(name.toLower()); |
219 | } |
220 | |
221 | AttributeIterator Area::attributeIterator() const |
222 | { |
223 | return AttributeIterator(_attributes); |
224 | } |
225 | |
226 | bool Area::setCoords(const QString &) { |
227 | return true; |
228 | } |
229 | |
230 | void Area::moveSelectionPoint(SelectionPoint*, const QPoint &) |
231 | {} |
232 | |
233 | // Default implementation; is specified by subclasses |
234 | QString Area::coordsToString() const |
235 | { |
236 | return "" ; |
237 | } |
238 | |
239 | |
240 | Area::ShapeType Area::type() const { |
241 | return _type; |
242 | } |
243 | |
244 | void Area::setArea(const Area & copy) |
245 | { |
246 | deleteSelectionPoints(); |
247 | _coords.clear(); |
248 | _coords += copy.coords(); |
249 | currentHighlighted=-1; |
250 | |
251 | SelectionPointList points = copy.selectionPoints(); |
252 | for (int i=0; i<points.size(); i++) { |
253 | SelectionPoint* np = |
254 | new SelectionPoint(points.at(i)->getPoint(),points.at(i)->cursor()); |
255 | _selectionPoints.append(np); |
256 | } |
257 | |
258 | _finished=copy.finished(); |
259 | _isSelected=copy.isSelected(); |
260 | _rect = copy.rect(); |
261 | |
262 | AttributeIterator it = copy.attributeIterator(); |
263 | while (it.hasNext()) { |
264 | it.next(); |
265 | setAttribute(it.key(),it.value()); |
266 | } |
267 | |
268 | setMoving(copy.isMoving()); |
269 | } |
270 | |
271 | void Area::setFinished(bool b, bool ) { |
272 | _finished=b; |
273 | } |
274 | |
275 | |
276 | void Area::setListViewItem(QTreeWidgetItem* item) { |
277 | _listViewItem=item; |
278 | } |
279 | |
280 | void Area::deleteListViewItem() |
281 | { |
282 | delete _listViewItem; |
283 | _listViewItem = 0L; |
284 | } |
285 | |
286 | |
287 | void Area::setRect(const QRect & r) |
288 | { |
289 | _rect=r; |
290 | updateSelectionPoints(); |
291 | } |
292 | |
293 | QRect Area::rect() const { |
294 | return _rect; |
295 | } |
296 | |
297 | void Area::setMoving(bool b) { |
298 | _isMoving=b; |
299 | } |
300 | |
301 | |
302 | void Area::moveBy(int dx, int dy) { |
303 | _rect.translate(dx,dy); |
304 | _coords.translate(dx,dy); |
305 | |
306 | for (int i=0;i < _selectionPoints.size(); i++) { |
307 | _selectionPoints.at(i)->translate(dx,dy); |
308 | } |
309 | } |
310 | |
311 | |
312 | void Area::moveTo(int x, int y) { |
313 | int dx = x-rect().left(); |
314 | int dy = y-rect().top(); |
315 | moveBy(dx,dy); |
316 | } |
317 | |
318 | int Area::countSelectionPoints() const |
319 | { |
320 | return selectionPoints().size(); |
321 | } |
322 | |
323 | int Area::addCoord(const QPoint & p) |
324 | { |
325 | _coords.resize(_coords.size()+1); |
326 | _coords.setPoint(_coords.size()-1,p); |
327 | _selectionPoints.append(new SelectionPoint(p,QCursor(Qt::PointingHandCursor))); |
328 | setRect(_coords.boundingRect()); |
329 | |
330 | return _coords.size()-1; |
331 | } |
332 | |
333 | void Area::insertCoord(int pos, const QPoint & p) |
334 | { |
335 | _coords.resize(_coords.size()+1); |
336 | |
337 | |
338 | for (int i=_coords.size()-1;i>pos;i--) { |
339 | _coords.setPoint(i,_coords.point(i-1)); |
340 | } |
341 | _coords.setPoint(pos, p); |
342 | |
343 | _selectionPoints.insert(pos,new SelectionPoint(p,QCursor(Qt::PointingHandCursor))); |
344 | setRect(_coords.boundingRect()); |
345 | } |
346 | |
347 | void Area::removeCoord(int pos) { |
348 | |
349 | int count =_coords.size(); |
350 | |
351 | if (count<4){ |
352 | kDebug() << "Danger : trying to remove coordinate from Area with less than 4 coordinates !" ; |
353 | return; |
354 | } |
355 | |
356 | for (int i=pos;i<(count-1);i++) |
357 | _coords.setPoint(i, _coords.point(i+1)); |
358 | |
359 | _coords.resize(count-1); |
360 | delete _selectionPoints.takeAt(pos); |
361 | setRect(_coords.boundingRect()); |
362 | } |
363 | |
364 | bool Area::removeSelectionPoint(SelectionPoint * p) |
365 | { |
366 | if (_selectionPoints.contains(p)) |
367 | { |
368 | removeCoord(_selectionPoints.indexOf(p)); |
369 | return true; |
370 | } |
371 | |
372 | return false; |
373 | } |
374 | |
375 | |
376 | void Area::moveCoord(int pos, const QPoint & p) { |
377 | _coords.setPoint(pos,p); |
378 | _selectionPoints.at(pos)->setPoint(p); |
379 | setRect(_coords.boundingRect()); |
380 | } |
381 | |
382 | void Area::setSelected(bool b) |
383 | { |
384 | _isSelected=b; |
385 | if (_listViewItem) { |
386 | _listViewItem->setSelected(b); |
387 | } |
388 | } |
389 | |
390 | void Area::highlightSelectionPoint(int number){ |
391 | currentHighlighted=number; |
392 | } |
393 | |
394 | QRect Area::selectionRect() const { |
395 | QRect r = rect(); |
396 | r.translate(-SELSIZE*2,-SELSIZE*2); |
397 | r.setSize(r.size()+QSize(SELSIZE*4,SELSIZE*4)); |
398 | |
399 | return r; |
400 | } |
401 | |
402 | void Area::setPenAndBrush(QPainter* p) { |
403 | QBrush brush(Qt::NoBrush); |
404 | if (highlightArea) { |
405 | QColor back = Qt::white; |
406 | back.setAlpha(80); |
407 | brush = QBrush(back,Qt::SolidPattern); |
408 | } |
409 | |
410 | p->setBrush(brush); |
411 | |
412 | QColor front = Qt::white; |
413 | front.setAlpha(200); |
414 | p->setPen(QPen(front,1)); |
415 | } |
416 | |
417 | |
418 | void Area::drawAlt(QPainter* p) |
419 | { |
420 | double x,y; |
421 | |
422 | double scalex = p->matrix().m11(); |
423 | // double scaley = p.matrix().m12(); |
424 | |
425 | QMatrix oldMatrix = p->matrix(); |
426 | |
427 | p->setMatrix(QMatrix(1,oldMatrix.m12(), oldMatrix.m21(), 1, oldMatrix.dx(), oldMatrix.dy() )); |
428 | |
429 | x = (rect().x()+rect().width()/2)*scalex; |
430 | y = (rect().y()+rect().height()/2)*scalex; |
431 | |
432 | QFontMetrics metrics = p->fontMetrics(); |
433 | |
434 | int w = metrics.width(attribute("alt" )); |
435 | x -= w/2; |
436 | y += metrics.height()/4; |
437 | |
438 | |
439 | |
440 | if (highlightArea) { |
441 | p->setPen(Qt::black); |
442 | } else { |
443 | p->setPen(QPen(QColor("white" ),1)); |
444 | } |
445 | |
446 | p->drawText(myround(x),myround(y),attribute("alt" )); |
447 | |
448 | p->setMatrix(oldMatrix); |
449 | } |
450 | |
451 | void Area::draw(QPainter * p) |
452 | { |
453 | |
454 | // Only draw the selection points at base class |
455 | // the rest is done in the derived classes |
456 | if (_isSelected) { |
457 | // We do not want to have the selection points |
458 | // scaled, so calculate the unscaled version |
459 | double scalex = p->matrix().m11(); |
460 | QMatrix oldMatrix = p->matrix(); |
461 | p->setMatrix(QMatrix(1,oldMatrix.m12(), |
462 | oldMatrix.m21(), 1, |
463 | oldMatrix.dx(), |
464 | oldMatrix.dy() )); |
465 | |
466 | for (int i=0; i<_selectionPoints.size(); i++) { |
467 | _selectionPoints.at(i)->draw(p,scalex); |
468 | } |
469 | p->setMatrix(oldMatrix); |
470 | } |
471 | |
472 | if (showAlt) { |
473 | drawAlt(p); |
474 | } |
475 | |
476 | } |
477 | |
478 | SelectionPoint* Area::onSelectionPoint(const QPoint & p, double zoom) const |
479 | { |
480 | |
481 | for (int i=0; i<_selectionPoints.size(); i++) { |
482 | SelectionPoint* sp = _selectionPoints.at(i); |
483 | |
484 | QRect r = sp->getRect(); |
485 | |
486 | r.moveCenter(sp->getPoint()*zoom); |
487 | |
488 | if (r.contains(p)) |
489 | { |
490 | return sp; |
491 | } |
492 | } |
493 | |
494 | return 0L; |
495 | } |
496 | |
497 | |
498 | |
499 | |
500 | /** |
501 | * returns only the part of the image which is |
502 | * covered by the area |
503 | */ |
504 | QPixmap Area::cutOut(const QImage & image) |
505 | { |
506 | if ( 0>=rect().width() || |
507 | 0>=rect().height() || |
508 | !rect().intersects(image.rect()) ) |
509 | { |
510 | QPixmap dummyPix(10,10); |
511 | dummyPix.fill(); |
512 | return dummyPix; |
513 | } |
514 | |
515 | // Get the mask from the subclasses |
516 | QBitmap mask=getMask(); |
517 | |
518 | // The rectangle which is part of the image |
519 | QRect partOfImage=rect(); |
520 | QRect partOfMask(0,0,mask.width(),mask.height()); |
521 | |
522 | |
523 | // If the area is outside of the image make the |
524 | // preview smaller |
525 | if ( (rect().x()+rect().width()) > image.width() ) { |
526 | partOfImage.setWidth( image.width()-rect().x() ); |
527 | partOfMask.setWidth( image.width()-rect().x() ); |
528 | } |
529 | |
530 | if ( (rect().x() < 0) ) { |
531 | partOfImage.setX(0); |
532 | partOfMask.setX(myabs(rect().x())); |
533 | } |
534 | |
535 | if ( (rect().y()+rect().height()) > image.height() ) { |
536 | partOfImage.setHeight( image.height()-rect().y() ); |
537 | partOfMask.setHeight ( image.height()-rect().y() ); |
538 | } |
539 | |
540 | if ( (rect().y() < 0) ) { |
541 | partOfImage.setY(0); |
542 | partOfMask.setY(myabs(rect().y())); |
543 | } |
544 | |
545 | QImage tempImage=mask.toImage().copy(partOfMask); |
546 | mask = QPixmap::fromImage(tempImage); |
547 | |
548 | // partOfImage = partOfImage.normalize(); |
549 | QImage cut=image.copy(partOfImage); |
550 | |
551 | QPixmap pix; |
552 | |
553 | // partOfMask = partOfMask.normalize(); |
554 | if (!partOfMask.isValid()) |
555 | kDebug() << "PartofMask not valid : " << partOfMask.x() << "," << partOfMask.y() << "," |
556 | << partOfMask.width() << "," << partOfMask.height() << "," << endl; |
557 | |
558 | /* |
559 | QBitmap mask2(partOfMask.width(), partOfMask.height()); |
560 | QPainter p4(&mask2); |
561 | p4.drawPixmap( QPoint(0,0) ,mask,partOfMask); |
562 | p4.flush(); |
563 | p4.end(); |
564 | */ |
565 | |
566 | pix = QPixmap::fromImage(cut); |
567 | |
568 | // setHighlightedPixmap(cut, mask); |
569 | |
570 | QPixmap retPix(pix.width(),pix.height()); |
571 | QPainter p3(&retPix); |
572 | |
573 | // if transparent image fill the background |
574 | // with gimp-like rectangles |
575 | if (!pix.mask().isNull()) { |
576 | QPixmap backPix(32,32); |
577 | |
578 | // Gimp like transparent rectangle |
579 | QPainter p2(&backPix); |
580 | p2.fillRect(0,0,32,32,QColor(156,149,156)); |
581 | p2.fillRect(0,16,16,16,QColor(98,105,98)); |
582 | p2.fillRect(16,0,16,16,QColor(98,105,98)); |
583 | |
584 | p3.setPen(QPen()); |
585 | p3.fillRect(0,0,pix.width(),pix.height(),QBrush(QColor("black" ),backPix)); |
586 | } |
587 | |
588 | |
589 | p3.drawPixmap(QPoint(0,0),pix); |
590 | p3.end(); |
591 | retPix.setMask(mask); |
592 | |
593 | return retPix; |
594 | } |
595 | |
596 | QBitmap Area::getMask() const |
597 | { |
598 | QBitmap b; |
599 | return b; |
600 | } |
601 | |
602 | /******************************************************************** |
603 | * RECTANGLE |
604 | *******************************************************************/ |
605 | |
606 | |
607 | RectArea::RectArea() |
608 | : Area() |
609 | { |
610 | _type=Area::Rectangle; |
611 | QPoint p(0,0); |
612 | _selectionPoints.append(new SelectionPoint(p,Qt::SizeFDiagCursor)); |
613 | _selectionPoints.append(new SelectionPoint(p,Qt::SizeBDiagCursor)); |
614 | _selectionPoints.append(new SelectionPoint(p,Qt::SizeBDiagCursor)); |
615 | _selectionPoints.append(new SelectionPoint(p,Qt::SizeFDiagCursor)); |
616 | _selectionPoints.append(new SelectionPoint(p,Qt::SizeVerCursor)); |
617 | _selectionPoints.append(new SelectionPoint(p,Qt::SizeHorCursor)); |
618 | _selectionPoints.append(new SelectionPoint(p,Qt::SizeVerCursor)); |
619 | _selectionPoints.append(new SelectionPoint(p,Qt::SizeHorCursor)); |
620 | } |
621 | |
622 | RectArea::~RectArea() { |
623 | } |
624 | |
625 | Area* RectArea::clone() const |
626 | { |
627 | Area* areaClone = new RectArea(); |
628 | areaClone->setArea( *this ); |
629 | return areaClone; |
630 | } |
631 | |
632 | void RectArea::draw(QPainter * p) |
633 | { |
634 | setPenAndBrush(p); |
635 | |
636 | QRect r(rect()); |
637 | r.setWidth(r.width()+1); |
638 | r.setHeight(r.height()+1); |
639 | p->drawRect(r); |
640 | |
641 | Area::draw(p); |
642 | } |
643 | |
644 | QBitmap RectArea::getMask() const |
645 | { |
646 | QBitmap mask(rect().width(),rect().height()); |
647 | |
648 | mask.fill(Qt::color0); |
649 | QPainter p(&mask); |
650 | p.setBackground(QBrush(Qt::color0)); |
651 | p.setPen(Qt::color1); |
652 | p.setBrush(Qt::color1); |
653 | mask.fill(Qt::color1); |
654 | p.end(); |
655 | |
656 | return mask; |
657 | } |
658 | |
659 | QString RectArea::coordsToString() const |
660 | { |
661 | QString retStr=QString("%1,%2,%3,%4" ) |
662 | .arg(rect().left()) |
663 | .arg(rect().top()) |
664 | .arg(rect().right()) |
665 | .arg(rect().bottom()); |
666 | |
667 | return retStr; |
668 | } |
669 | |
670 | bool RectArea::contains(const QPoint & p) const{ |
671 | return rect().contains(p); |
672 | } |
673 | |
674 | void RectArea::moveSelectionPoint(SelectionPoint* selectionPoint, const QPoint & p) |
675 | { |
676 | selectionPoint->setPoint(p); |
677 | int i = _selectionPoints.indexOf(selectionPoint); |
678 | |
679 | QRect r2(_rect); |
680 | switch (i) { |
681 | case 0 : |
682 | _rect.setLeft(p.x()); |
683 | _rect.setTop(p.y()); |
684 | break; |
685 | case 1 : |
686 | _rect.setRight(p.x()); |
687 | _rect.setTop(p.y()); |
688 | break; |
689 | case 2 : |
690 | _rect.setLeft(p.x()); |
691 | _rect.setBottom(p.y()); |
692 | break; |
693 | case 3 : |
694 | _rect.setRight(p.x()); |
695 | _rect.setBottom(p.y()); |
696 | break; |
697 | case 4 : // top line |
698 | _rect.setTop(p.y()); |
699 | break; |
700 | case 5 : // right line |
701 | _rect.setRight(p.x()); |
702 | break; |
703 | case 6 : // bottom |
704 | _rect.setBottom(p.y()); |
705 | break; |
706 | case 7 : // left |
707 | _rect.setLeft(p.x()); |
708 | break; |
709 | |
710 | } |
711 | if (! _rect.isValid()) |
712 | _rect=r2; |
713 | |
714 | updateSelectionPoints(); |
715 | } |
716 | |
717 | void RectArea::updateSelectionPoints() |
718 | { |
719 | int d = 2; |
720 | QRect r(_rect); |
721 | r.adjust(0,0,1,1); |
722 | int xmid = r.left()+(r.width()/d); |
723 | int ymid = r.top()+(r.height()/d); |
724 | |
725 | |
726 | _selectionPoints[0]->setPoint(r.topLeft()); |
727 | _selectionPoints[1]->setPoint(r.topRight()); |
728 | _selectionPoints[2]->setPoint(r.bottomLeft()); |
729 | _selectionPoints[3]->setPoint(r.bottomRight()); |
730 | _selectionPoints[4]->setPoint(QPoint(xmid,r.top())); |
731 | _selectionPoints[5]->setPoint(QPoint(r.right(),ymid)); |
732 | _selectionPoints[6]->setPoint(QPoint(xmid,r.bottom())); |
733 | _selectionPoints[7]->setPoint(QPoint(r.left(),ymid)); |
734 | } |
735 | |
736 | bool RectArea::setCoords(const QString & s) |
737 | { |
738 | _finished=true; |
739 | |
740 | const QStringList list = s.split("," ); |
741 | QRect r; |
742 | bool ok=true; |
743 | QStringList::ConstIterator it = list.begin(); |
744 | r.setLeft((*it).toInt(&ok,10));it++; |
745 | r.setTop((*it).toInt(&ok,10));it++; |
746 | r.setRight((*it).toInt(&ok,10));it++; |
747 | r.setBottom((*it).toInt(&ok,10)); |
748 | if (ok) { |
749 | setRect(r); |
750 | return true; |
751 | } else { |
752 | return false; |
753 | } |
754 | } |
755 | |
756 | QString RectArea::getHTMLCode() const { |
757 | QString retStr; |
758 | retStr+="<area " ; |
759 | retStr+="shape=\"rect\" " ; |
760 | |
761 | retStr+=getHTMLAttributes(); |
762 | |
763 | retStr+="coords=\"" +coordsToString()+"\" " ; |
764 | retStr+="/>" ; |
765 | return retStr; |
766 | |
767 | } |
768 | |
769 | /******************************************************************** |
770 | * CIRCLE |
771 | *******************************************************************/ |
772 | |
773 | |
774 | CircleArea::CircleArea() |
775 | : Area() |
776 | { |
777 | _type = Area::Circle; |
778 | QPoint p(0,0); |
779 | _selectionPoints.append(new SelectionPoint(p,Qt::SizeFDiagCursor)); |
780 | _selectionPoints.append(new SelectionPoint(p,Qt::SizeBDiagCursor)); |
781 | _selectionPoints.append(new SelectionPoint(p,Qt::SizeBDiagCursor)); |
782 | _selectionPoints.append(new SelectionPoint(p,Qt::SizeFDiagCursor)); |
783 | } |
784 | |
785 | CircleArea::~CircleArea() { |
786 | } |
787 | |
788 | Area* CircleArea::clone() const |
789 | { |
790 | Area* areaClone = new CircleArea(); |
791 | areaClone->setArea( *this ); |
792 | return areaClone; |
793 | } |
794 | |
795 | void CircleArea::draw(QPainter * p) |
796 | { |
797 | setPenAndBrush(p); |
798 | |
799 | QRect r(_rect); |
800 | r.setWidth(r.width()+1); |
801 | r.setHeight(r.height()+1); |
802 | p->drawEllipse(r); |
803 | |
804 | Area::draw(p); |
805 | } |
806 | |
807 | QBitmap CircleArea::getMask() const |
808 | { |
809 | QBitmap mask(_rect.width(),_rect.height()); |
810 | |
811 | mask.fill(Qt::color0); |
812 | QPainter p(&mask); |
813 | p.setBackground(QBrush(Qt::color0)); |
814 | p.setPen(Qt::color1); |
815 | p.setBrush(Qt::color1); |
816 | p.drawPie(QRect(0,0,_rect.width(),_rect.height()),0,5760); |
817 | p.end(); |
818 | |
819 | |
820 | return mask; |
821 | |
822 | } |
823 | |
824 | QString CircleArea::coordsToString() const |
825 | { |
826 | QString retStr=QString("%1,%2,%3" ) |
827 | .arg(_rect.center().x()) |
828 | .arg(_rect.center().y()) |
829 | .arg(_rect.width()/2); |
830 | |
831 | return retStr; |
832 | } |
833 | |
834 | bool CircleArea::contains(const QPoint & p) const |
835 | { |
836 | QRegion r(_rect,QRegion::Ellipse); |
837 | return r.contains(p); |
838 | } |
839 | |
840 | void CircleArea::moveSelectionPoint(SelectionPoint* selectionPoint, const QPoint & p) |
841 | { |
842 | selectionPoint->setPoint(p); |
843 | |
844 | int i = _selectionPoints.indexOf(selectionPoint); |
845 | |
846 | // The code below really sucks, but I have no better idea. |
847 | // it only makes sure that the circle is perfectly round |
848 | |
849 | QPoint newPoint; |
850 | int diff=myabs(p.x()-_rect.center().x()); |
851 | if (myabs(p.y()-_rect.center().y())>diff) |
852 | diff=myabs(p.y()-_rect.center().y()); |
853 | |
854 | newPoint.setX( p.x()-_rect.center().x()<0 |
855 | ? _rect.center().x()-diff |
856 | : _rect.center().x()+diff); |
857 | |
858 | newPoint.setY( p.y()-_rect.center().y()<0 |
859 | ? _rect.center().y()-diff |
860 | : _rect.center().y()+diff); |
861 | |
862 | switch (i) { |
863 | case 0 : if (newPoint.x() < _rect.center().x() && |
864 | newPoint.y() < _rect.center().y()) |
865 | { |
866 | _rect.setLeft(newPoint.x()); |
867 | _rect.setTop(newPoint.y()); |
868 | } |
869 | break; |
870 | case 1 : if (newPoint.x() > _rect.center().x() && |
871 | newPoint.y() < _rect.center().y()) |
872 | { |
873 | _rect.setRight(newPoint.x()); |
874 | _rect.setTop(newPoint.y()); |
875 | } |
876 | break; |
877 | case 2 : if (newPoint.x() < _rect.center().x() && |
878 | newPoint.y() > _rect.center().y()) |
879 | { |
880 | _rect.setLeft(newPoint.x()); |
881 | _rect.setBottom(newPoint.y()); |
882 | } |
883 | break; |
884 | case 3 : if (newPoint.x() > _rect.center().x() && |
885 | newPoint.y() > _rect.center().y()) |
886 | { |
887 | _rect.setRight(newPoint.x()); |
888 | _rect.setBottom(newPoint.y()); |
889 | } |
890 | break; |
891 | } |
892 | |
893 | |
894 | |
895 | updateSelectionPoints(); |
896 | |
897 | } |
898 | |
899 | void CircleArea::setRect(const QRect & r) |
900 | { |
901 | QRect r2 = r; |
902 | if ( r2.height() != r2.width() ) |
903 | r2.setHeight( r2.width() ); |
904 | |
905 | Area::setRect(r2); |
906 | } |
907 | |
908 | |
909 | void CircleArea::updateSelectionPoints() |
910 | { |
911 | _selectionPoints[0]->setPoint(_rect.topLeft()); |
912 | _selectionPoints[1]->setPoint(_rect.topRight()); |
913 | _selectionPoints[2]->setPoint(_rect.bottomLeft()); |
914 | _selectionPoints[3]->setPoint(_rect.bottomRight()); |
915 | } |
916 | |
917 | bool CircleArea::setCoords(const QString & s) |
918 | { |
919 | _finished=true; |
920 | const QStringList list = s.split("," ); |
921 | bool ok=true; |
922 | QStringList::ConstIterator it = list.begin(); |
923 | int x=(*it).toInt(&ok,10);it++; |
924 | int y=(*it).toInt(&ok,10);it++; |
925 | int rad=(*it).toInt(&ok,10); |
926 | if (!ok) return false; |
927 | QRect r; |
928 | r.setWidth(rad*2); |
929 | r.setHeight(rad*2); |
930 | r.moveCenter(QPoint(x,y)); |
931 | setRect(r); |
932 | return true; |
933 | } |
934 | |
935 | QString CircleArea::getHTMLCode() const { |
936 | QString retStr; |
937 | retStr+="<area " ; |
938 | retStr+="shape=\"circle\" " ; |
939 | |
940 | retStr+=getHTMLAttributes(); |
941 | |
942 | retStr+="coords=\"" +coordsToString()+"\" " ; |
943 | retStr+="/>" ; |
944 | return retStr; |
945 | |
946 | } |
947 | |
948 | |
949 | /******************************************************************** |
950 | * POLYGON |
951 | *******************************************************************/ |
952 | |
953 | |
954 | PolyArea::PolyArea() |
955 | : Area() |
956 | { |
957 | _type = Area::Polygon; |
958 | } |
959 | |
960 | PolyArea::~PolyArea() { |
961 | } |
962 | |
963 | Area* PolyArea::clone() const |
964 | { |
965 | Area* areaClone = new PolyArea(); |
966 | areaClone->setArea( *this ); |
967 | return areaClone; |
968 | } |
969 | |
970 | void PolyArea::draw(QPainter * p) |
971 | { |
972 | setPenAndBrush(p); |
973 | |
974 | if (_finished) |
975 | p->drawPolygon( _coords.constData(),_coords.count()); |
976 | else { |
977 | p->drawPolyline(_coords.constData(),_coords.count()); |
978 | } |
979 | |
980 | Area::draw(p); |
981 | } |
982 | |
983 | QBitmap PolyArea::getMask() const |
984 | { |
985 | QBitmap mask(_rect.width(),_rect.height()); |
986 | |
987 | mask.fill(Qt::color0); |
988 | QPainter p(&mask); |
989 | p.setBackground(QBrush(Qt::color0)); |
990 | p.setPen(Qt::color1); |
991 | p.setBrush(Qt::color1); |
992 | p.setClipping(true); |
993 | QRegion r(_coords); |
994 | r.translate(-_rect.left(),-_rect.top()); |
995 | p.setClipRegion(r); |
996 | p.fillRect(QRect(0,0,_rect.width(),_rect.height()),Qt::color1); |
997 | p.end(); |
998 | |
999 | return mask; |
1000 | } |
1001 | |
1002 | QString PolyArea::coordsToString() const |
1003 | { |
1004 | QString retStr; |
1005 | |
1006 | for (int i=0;i<_coords.count();i++) { |
1007 | retStr.append(QString("%1,%2," ) |
1008 | .arg(_coords.point(i).x()) |
1009 | .arg(_coords.point(i).y())); |
1010 | } |
1011 | |
1012 | retStr.remove(retStr.length()-1,1); |
1013 | |
1014 | return retStr; |
1015 | } |
1016 | |
1017 | int PolyArea::distance(const QPoint &p1, const QPoint &p2) |
1018 | { |
1019 | QPoint temp = p1-p2; |
1020 | return temp.manhattanLength(); |
1021 | } |
1022 | |
1023 | bool PolyArea::isBetween(const QPoint &p, const QPoint &p1, const QPoint &p2) |
1024 | { |
1025 | int dist = distance(p,p1)+distance(p,p2)-distance(p1,p2); |
1026 | |
1027 | if (myabs(dist)<1) |
1028 | return true; |
1029 | else |
1030 | return false; |
1031 | } |
1032 | |
1033 | void PolyArea::simplifyCoords() |
1034 | { |
1035 | if (_coords.size()<4) |
1036 | return; |
1037 | |
1038 | QPoint p = _coords.point(0) - _coords.point(1); |
1039 | |
1040 | int i = 1; |
1041 | |
1042 | |
1043 | while( (i<_coords.size()) && (_coords.size() > 3) ) |
1044 | { |
1045 | p = _coords.point(i-1) - _coords.point(i); |
1046 | |
1047 | if (p.manhattanLength() < 3) |
1048 | removeCoord(i); |
1049 | else |
1050 | i++; |
1051 | } |
1052 | |
1053 | p = _coords.point(0) - _coords.point(1); |
1054 | |
1055 | double angle2; |
1056 | double angle1; |
1057 | |
1058 | if (p.y()==0) |
1059 | angle1 = 1000000000; |
1060 | else |
1061 | angle1 = (double) p.x() / (double) p.y(); |
1062 | |
1063 | i=2; |
1064 | |
1065 | while( (i<_coords.size()) && (_coords.size() > 3) ) |
1066 | { |
1067 | p = _coords.point(i-1) - _coords.point(i); |
1068 | |
1069 | if (p.y()==0) |
1070 | angle2 = 1000000000; |
1071 | else |
1072 | angle2 = (double) p.x() / (double) p.y(); |
1073 | |
1074 | if ( angle2==angle1 ) |
1075 | { |
1076 | kDebug() << "removing " << i-1; |
1077 | removeCoord(i-1); |
1078 | } |
1079 | else |
1080 | { |
1081 | i++; |
1082 | kDebug() << "skipping " << i-1 << " cause " << angle1 << "!= " << angle2; |
1083 | angle1 = angle2; |
1084 | |
1085 | } |
1086 | |
1087 | } |
1088 | |
1089 | |
1090 | |
1091 | } |
1092 | |
1093 | |
1094 | int PolyArea::addCoord(const QPoint & p) |
1095 | { |
1096 | if (_coords.size()<3) |
1097 | { |
1098 | return Area::addCoord(p); |
1099 | } |
1100 | |
1101 | if (_coords.point(_coords.size()-1) == p) |
1102 | { |
1103 | kDebug() << "equal Point added" ; |
1104 | return -1; |
1105 | |
1106 | } |
1107 | |
1108 | int n=_coords.size(); |
1109 | |
1110 | // QPoint temp = p-_coords.point(0); |
1111 | int nearest = 0; |
1112 | int olddist = distance(p,_coords.point(0)); |
1113 | int mindiff = 999999999; |
1114 | |
1115 | // find the two points, which are the nearest one to the new point |
1116 | for (int i=1; i <= n; i++) |
1117 | { |
1118 | int dist = distance(p,_coords.point(i%n)); |
1119 | int dist2 = distance(_coords.point(i-1),_coords.point(i%n)); |
1120 | int diff = myabs(dist+olddist-dist2); |
1121 | if ( diff<mindiff ) |
1122 | { |
1123 | mindiff = diff; |
1124 | nearest = i%n; |
1125 | } |
1126 | olddist=dist; |
1127 | } |
1128 | |
1129 | insertCoord(nearest, p); |
1130 | |
1131 | return nearest; |
1132 | |
1133 | } |
1134 | |
1135 | bool PolyArea::contains(const QPoint & p) const |
1136 | { |
1137 | // A line can't contain a point |
1138 | if (_coords.count() >2 ) { |
1139 | QRegion r(_coords); |
1140 | return r.contains(p); |
1141 | } |
1142 | else |
1143 | return false; |
1144 | } |
1145 | |
1146 | void PolyArea::moveSelectionPoint(SelectionPoint* selectionPoint, const QPoint & p) |
1147 | { |
1148 | selectionPoint->setPoint(p); |
1149 | |
1150 | int i = _selectionPoints.indexOf(selectionPoint); |
1151 | _coords.setPoint(i,p); |
1152 | _rect=_coords.boundingRect(); |
1153 | } |
1154 | |
1155 | void PolyArea::updateSelectionPoints() |
1156 | { |
1157 | for (int i = 0; i < _selectionPoints.size(); ++i) { |
1158 | _selectionPoints.at(i)->setPoint(_coords.point(i)); |
1159 | } |
1160 | } |
1161 | |
1162 | bool PolyArea::setCoords(const QString & s) |
1163 | { |
1164 | _finished=true; |
1165 | const QStringList list = s.split("," ); |
1166 | _coords.clear(); |
1167 | _selectionPoints.clear(); |
1168 | |
1169 | for (QStringList::ConstIterator it = list.begin(); it !=list.end(); ++it) |
1170 | { |
1171 | bool ok=true; |
1172 | int newXCoord=(*it).toInt(&ok,10); |
1173 | if (!ok) return false; |
1174 | it++; |
1175 | if (it==list.end()) break; |
1176 | int newYCoord=(*it).toInt(&ok,10); |
1177 | if (!ok) return false; |
1178 | insertCoord(_coords.size(), QPoint(newXCoord,newYCoord)); |
1179 | } |
1180 | |
1181 | return true; |
1182 | |
1183 | } |
1184 | |
1185 | QString PolyArea::getHTMLCode() const { |
1186 | QString retStr; |
1187 | retStr+="<area " ; |
1188 | retStr+="shape=\"poly\" " ; |
1189 | |
1190 | retStr+=getHTMLAttributes(); |
1191 | |
1192 | retStr+="coords=\"" +coordsToString()+"\" " ; |
1193 | retStr+="/>" ; |
1194 | return retStr; |
1195 | |
1196 | } |
1197 | |
1198 | void PolyArea::setFinished(bool b, bool removeLast = true) |
1199 | { |
1200 | // The last Point is the same as the first |
1201 | // so delete it |
1202 | if (b && removeLast) { |
1203 | _coords.resize(_coords.size()-1); |
1204 | _selectionPoints.removeLast(); |
1205 | } |
1206 | |
1207 | _finished = b; |
1208 | } |
1209 | |
1210 | QRect PolyArea::selectionRect() const |
1211 | { |
1212 | QRect r = _rect; |
1213 | |
1214 | r.translate(-10,-10); |
1215 | r.setSize(r.size()+QSize(21,21)); |
1216 | |
1217 | return r; |
1218 | } |
1219 | |
1220 | |
1221 | |
1222 | /******************************************************************** |
1223 | * DEFAULT |
1224 | *******************************************************************/ |
1225 | |
1226 | |
1227 | DefaultArea::DefaultArea() |
1228 | : Area() |
1229 | { |
1230 | _type=Area::Default; |
1231 | } |
1232 | |
1233 | DefaultArea::~DefaultArea() { |
1234 | } |
1235 | |
1236 | Area* DefaultArea::clone() const |
1237 | { |
1238 | Area* areaClone = new DefaultArea(); |
1239 | areaClone->setArea( *this ); |
1240 | return areaClone; |
1241 | } |
1242 | |
1243 | void DefaultArea::draw(QPainter *) |
1244 | {} |
1245 | |
1246 | |
1247 | QString DefaultArea::getHTMLCode() const { |
1248 | QString retStr; |
1249 | retStr+="<area " ; |
1250 | retStr+="shape=\"default\" " ; |
1251 | |
1252 | retStr+=getHTMLAttributes(); |
1253 | |
1254 | retStr+="/>" ; |
1255 | return retStr; |
1256 | |
1257 | } |
1258 | |
1259 | |
1260 | /******************************************************************** |
1261 | * AreaSelection |
1262 | *******************************************************************/ |
1263 | |
1264 | AreaSelection::AreaSelection() |
1265 | : Area() |
1266 | { |
1267 | _areas = new AreaList(); |
1268 | _name = "Selection" ; |
1269 | invalidate(); |
1270 | } |
1271 | |
1272 | AreaSelection::~AreaSelection() { |
1273 | delete _areas; |
1274 | } |
1275 | |
1276 | Area* AreaSelection::clone() const |
1277 | { |
1278 | AreaSelection* areaClone = new AreaSelection(); |
1279 | |
1280 | // we want a deep copy of the Areas |
1281 | AreaListIterator it=getAreaListIterator(); |
1282 | while (it.hasNext()) { |
1283 | areaClone->add( it.next()->clone() ); |
1284 | } |
1285 | |
1286 | return areaClone; |
1287 | } |
1288 | |
1289 | |
1290 | void AreaSelection::add(Area *a) |
1291 | { |
1292 | // if a selection of areas was added get the areas of it |
1293 | AreaSelection *selection=0L; |
1294 | if ( (selection = dynamic_cast <AreaSelection*> ( a ) ) ) { |
1295 | AreaList list = selection->getAreaList(); |
1296 | Area* area; |
1297 | foreach(area,list) { |
1298 | if ( !_areas->contains( area )) { |
1299 | _areas->append( area ); // Must come before area->setSelected |
1300 | area->setSelected( true ); |
1301 | } |
1302 | } |
1303 | } else { |
1304 | if ( !_areas->contains( a )) { |
1305 | _areas->append( a ); // Must come before a->setSelected |
1306 | a->setSelected( true ); |
1307 | } |
1308 | } |
1309 | |
1310 | invalidate(); |
1311 | } |
1312 | |
1313 | |
1314 | void AreaSelection::setSelectionPointStates(SelectionPoint::State st) { |
1315 | AreaListIterator it=getAreaListIterator(); |
1316 | while(it.hasNext()) { |
1317 | it.next()->setSelectionPointStates( st ); |
1318 | } |
1319 | } |
1320 | |
1321 | void AreaSelection::updateSelectionPointStates() { |
1322 | SelectionPoint::State st = SelectionPoint::Normal; |
1323 | |
1324 | if (_areas->count() > 1) |
1325 | st = SelectionPoint::Inactive; |
1326 | |
1327 | setSelectionPointStates(st); |
1328 | } |
1329 | |
1330 | |
1331 | void AreaSelection::remove(Area *a) |
1332 | { |
1333 | if (!_areas->contains(a)) |
1334 | return; |
1335 | |
1336 | a->setSelected( false ); |
1337 | _areas->removeAt(_areas->indexOf(a)); |
1338 | invalidate(); |
1339 | } |
1340 | |
1341 | void AreaSelection::reset() |
1342 | { |
1343 | AreaListIterator it=getAreaListIterator(); |
1344 | while (it.hasNext()) { |
1345 | it.next()->setSelected( false ); |
1346 | } |
1347 | |
1348 | _areas->clear(); |
1349 | invalidate(); |
1350 | } |
1351 | |
1352 | bool AreaSelection::contains(const QPoint & p) const |
1353 | { |
1354 | AreaListIterator it=getAreaListIterator(); |
1355 | while (it.hasNext()) { |
1356 | if ( it.next()->contains( p ) ) { |
1357 | return true; |
1358 | } |
1359 | } |
1360 | |
1361 | return false; |
1362 | } |
1363 | |
1364 | SelectionPoint* AreaSelection::onSelectionPoint(const QPoint & p, double zoom) const |
1365 | { |
1366 | |
1367 | if (_areas->count() != 1) |
1368 | return 0L; |
1369 | |
1370 | return _areas->first()->onSelectionPoint(p,zoom); |
1371 | } |
1372 | |
1373 | void AreaSelection::moveSelectionPoint(SelectionPoint* selectionPoint, const QPoint & p) |
1374 | { |
1375 | // It's only possible to move a SelectionPoint if only one Area is selected |
1376 | if (_areas->count() != 1) |
1377 | return; |
1378 | |
1379 | _areas->first()->moveSelectionPoint(selectionPoint,p); |
1380 | |
1381 | invalidate(); |
1382 | } |
1383 | |
1384 | |
1385 | void AreaSelection::moveBy(int dx, int dy) |
1386 | { |
1387 | AreaListIterator it=getAreaListIterator(); |
1388 | while (it.hasNext()) { |
1389 | it.next()->moveBy(dx,dy); |
1390 | } |
1391 | |
1392 | Area::moveBy( dx, dy ); |
1393 | invalidate(); |
1394 | } |
1395 | |
1396 | QString AreaSelection::typeString() const |
1397 | { |
1398 | // if there is only one Area selected |
1399 | // show the name of that Area |
1400 | if ( _areas->count()==0 ) |
1401 | return "" ; |
1402 | else if ( _areas->count()==1 ) |
1403 | return _areas->first()->typeString(); |
1404 | else |
1405 | return i18n("Number of Areas" ); |
1406 | |
1407 | } |
1408 | |
1409 | Area::ShapeType AreaSelection::type() const |
1410 | { |
1411 | // if there is only one Area selected |
1412 | // take the type of that Area |
1413 | if ( _areas->count()==0 ) |
1414 | return Area::None; |
1415 | else if ( _areas->count()==1 ) |
1416 | return _areas->first()->type(); |
1417 | else |
1418 | return Area::Selection; |
1419 | } |
1420 | |
1421 | void AreaSelection::resetSelectionPointState() { |
1422 | updateSelectionPointStates(); |
1423 | } |
1424 | |
1425 | void AreaSelection::updateSelectionPoints() |
1426 | { |
1427 | AreaListIterator it=getAreaListIterator(); |
1428 | while (it.hasNext()) { |
1429 | it.next()->updateSelectionPoints(); |
1430 | } |
1431 | |
1432 | invalidate(); |
1433 | } |
1434 | |
1435 | |
1436 | |
1437 | QRect AreaSelection::selectionRect() const |
1438 | { |
1439 | if (!_selectionCacheValid) { |
1440 | _selectionCacheValid=true; |
1441 | QRect r; |
1442 | AreaListIterator it=getAreaListIterator(); |
1443 | while (it.hasNext()) { |
1444 | r = r | it.next()->selectionRect(); |
1445 | } |
1446 | _cachedSelectionRect=r; |
1447 | } |
1448 | |
1449 | return _cachedSelectionRect; |
1450 | } |
1451 | |
1452 | int AreaSelection::count() const { |
1453 | return _areas->count(); |
1454 | } |
1455 | |
1456 | bool AreaSelection::isEmpty() const |
1457 | { |
1458 | return _areas->isEmpty(); |
1459 | } |
1460 | |
1461 | |
1462 | AreaList AreaSelection::getAreaList() const { |
1463 | AreaList list(*_areas); |
1464 | return list; |
1465 | } |
1466 | |
1467 | AreaListIterator AreaSelection::getAreaListIterator() const { |
1468 | AreaListIterator it(*_areas); |
1469 | return it; |
1470 | } |
1471 | |
1472 | void AreaSelection::setArea(const Area & copy) |
1473 | { |
1474 | Area *area = copy.clone(); |
1475 | AreaSelection *selection = dynamic_cast<AreaSelection*>(area); |
1476 | if (selection) |
1477 | setAreaSelection(*selection); |
1478 | else { |
1479 | Area::setArea(copy); |
1480 | invalidate(); |
1481 | } |
1482 | } |
1483 | |
1484 | void AreaSelection::setAreaSelection(const AreaSelection & copy) |
1485 | { |
1486 | AreaList* areasCopy = copy._areas; |
1487 | |
1488 | if (_areas->count() != areasCopy->count()) |
1489 | return; |
1490 | |
1491 | AreaListIterator it(*_areas); |
1492 | AreaListIterator it2(*areasCopy); |
1493 | while (it.hasNext()) { |
1494 | it.next()->setArea(*it2.next()); |
1495 | } |
1496 | |
1497 | Area::setArea(copy); |
1498 | invalidate(); |
1499 | } |
1500 | |
1501 | void AreaSelection::setAreaList( const AreaList & areas ) |
1502 | { |
1503 | delete _areas; |
1504 | _areas = new AreaList(areas); |
1505 | invalidate(); |
1506 | } |
1507 | |
1508 | void AreaSelection::setRect(const QRect & r) |
1509 | { |
1510 | if ( _areas->count()==1 ) |
1511 | { |
1512 | _areas->first()->setRect(r); |
1513 | } |
1514 | |
1515 | invalidate(); |
1516 | _rect=rect(); |
1517 | updateSelectionPoints(); |
1518 | } |
1519 | |
1520 | QRect AreaSelection::rect() const |
1521 | { |
1522 | if (!_rectCacheValid) |
1523 | { |
1524 | _rectCacheValid=true; |
1525 | QRect r; |
1526 | AreaListIterator it=getAreaListIterator(); |
1527 | |
1528 | while (it.hasNext()) { |
1529 | r = r | it.next()->rect(); |
1530 | } |
1531 | |
1532 | _cachedRect=r; |
1533 | } |
1534 | |
1535 | return _cachedRect; |
1536 | } |
1537 | |
1538 | |
1539 | int AreaSelection::addCoord(const QPoint & p) |
1540 | { |
1541 | if ( _areas->count()==1 ) |
1542 | { |
1543 | return _areas->first()->addCoord(p); |
1544 | invalidate(); |
1545 | } |
1546 | |
1547 | return 0; |
1548 | } |
1549 | |
1550 | void AreaSelection::insertCoord(int pos, const QPoint & p) |
1551 | { |
1552 | if ( _areas->count()==1 ) |
1553 | { |
1554 | _areas->first()->insertCoord(pos, p); |
1555 | invalidate(); |
1556 | } |
1557 | } |
1558 | |
1559 | void AreaSelection::removeCoord(int pos) |
1560 | { |
1561 | if ( _areas->count()==1 ) |
1562 | { |
1563 | _areas->first()->removeCoord(pos); |
1564 | invalidate(); |
1565 | } |
1566 | } |
1567 | |
1568 | bool AreaSelection::removeSelectionPoint(SelectionPoint* p) |
1569 | { |
1570 | bool result=false; |
1571 | |
1572 | if ( _areas->count()==1 ) |
1573 | { |
1574 | result = _areas->first()->removeSelectionPoint(p); |
1575 | invalidate(); |
1576 | } |
1577 | |
1578 | return result; |
1579 | } |
1580 | |
1581 | const SelectionPointList & AreaSelection::selectionPoints() const |
1582 | { |
1583 | if ( _areas->count()==1 ) |
1584 | { |
1585 | return _areas->first()->selectionPoints(); |
1586 | } |
1587 | |
1588 | return _selectionPoints; |
1589 | } |
1590 | |
1591 | |
1592 | void AreaSelection::moveCoord(int pos,const QPoint & p) |
1593 | { |
1594 | if ( _areas->count()==1 ) |
1595 | { |
1596 | _areas->first()->moveCoord(pos,p); |
1597 | invalidate(); |
1598 | } |
1599 | } |
1600 | |
1601 | void AreaSelection::highlightSelectionPoint(int i) |
1602 | { |
1603 | if ( _areas->count()==1 ) |
1604 | { |
1605 | _areas->first()->highlightSelectionPoint(i); |
1606 | invalidate(); |
1607 | } |
1608 | } |
1609 | |
1610 | |
1611 | QPolygon AreaSelection::coords() const |
1612 | { |
1613 | if ( _areas->count()==1 ) |
1614 | { |
1615 | return _areas->first()->coords(); |
1616 | } |
1617 | |
1618 | return Area::coords(); |
1619 | } |
1620 | |
1621 | QString AreaSelection::attribute(const QString & name) const |
1622 | { |
1623 | if ( _areas->count()==1 ) |
1624 | { |
1625 | return _areas->first()->attribute(name); |
1626 | } |
1627 | |
1628 | return Area::attribute(name); |
1629 | } |
1630 | |
1631 | void AreaSelection::setAttribute(const QString & name, const QString & value) |
1632 | { |
1633 | AreaListIterator it=getAreaListIterator(); |
1634 | |
1635 | while (it.hasNext()) { |
1636 | it.next()->setAttribute(name,value); |
1637 | } |
1638 | |
1639 | Area::setAttribute(name,value); |
1640 | } |
1641 | |
1642 | AttributeIterator AreaSelection::attributeIterator() const |
1643 | { |
1644 | if ( _areas->count()==1 ) |
1645 | { |
1646 | return _areas->first()->attributeIterator(); |
1647 | } |
1648 | |
1649 | return AttributeIterator(_attributes); |
1650 | } |
1651 | |
1652 | void AreaSelection::setMoving(bool b) |
1653 | { |
1654 | AreaListIterator it=getAreaListIterator(); |
1655 | |
1656 | while (it.hasNext()) { |
1657 | it.next()->setMoving(b); |
1658 | } |
1659 | |
1660 | Area::setMoving(b); |
1661 | } |
1662 | |
1663 | bool AreaSelection::isMoving() const |
1664 | { |
1665 | if ( _areas->count()==1 ) |
1666 | { |
1667 | return _areas->first()->isMoving(); |
1668 | } |
1669 | |
1670 | return Area::isMoving(); |
1671 | } |
1672 | |
1673 | |
1674 | /** |
1675 | * Checks if an area is outside the rectangle parameter |
1676 | * returns false if an area has no pixel in common with the rectangle parameter |
1677 | **/ |
1678 | bool AreaSelection::allAreasWithin(const QRect & r) const |
1679 | { |
1680 | if ( ! r.contains(rect()) ) |
1681 | { |
1682 | AreaListIterator it=getAreaListIterator(); |
1683 | |
1684 | while (it.hasNext()) { |
1685 | if (!it.next()->rect().intersects(r)) |
1686 | return false; |
1687 | } |
1688 | } |
1689 | |
1690 | return true; |
1691 | } |
1692 | |
1693 | |
1694 | void AreaSelection::draw(QPainter *) |
1695 | {} |
1696 | |
1697 | void AreaSelection::invalidate() { |
1698 | _selectionCacheValid=false; |
1699 | _rectCacheValid=false; |
1700 | updateSelectionPointStates(); |
1701 | } |
1702 | |
1703 | |
1704 | |