File indexing completed on 2024-07-14 04:16:08

0001 /***************************************************************************
0002                           imagemap.cpp  -  description
0003                              -------------------
0004     begin                : Wed Apr 4 2001
0005     copyright            : (C) 2001 by Jan Schäfer
0006     email                : j_schaef@informatik.uni-kl.de
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 "imagemap.h"
0019 #include "kimagemapeditor.h"
0020 
0021 #include <QBitmap>
0022 #include <QMouseEvent>
0023 #include <QPainter>
0024 #include <QPixmap>
0025 #include <QResizeEvent>
0026 
0027 int round(double d) {
0028     if ( (d-((int) d)) < 0.5 )
0029         return (int) d;
0030     else
0031         return ((int) d)+1;
0032 }
0033 
0034 ImageMap::ImageMap(QWidget *parent,KImageMapEditor* _imageMapEditor)
0035     : QScrollArea(parent)
0036 {
0037     imageMapEditor=_imageMapEditor;
0038 //  setPicture(QImage());
0039     currentAction=None;
0040     currentArea=0L;
0041     eraseOldArea=false;
0042     oldArea=0L;
0043     _zoom=1;
0044     widget()->setMouseTracking(true);
0045 
0046 
0047 }
0048 
0049 ImageMap::~ImageMap(){
0050 }
0051 
0052 void ImageMap::setPicture(const QImage &_image) {
0053     image=_image;
0054     zoomedImage.convertFromImage(image);
0055     setZoom(_zoom);
0056 }
0057 
0058 void ImageMap::setZoom(double z) {
0059     _zoom=z;
0060     imageRect.setHeight(image.height()*_zoom);
0061     imageRect.setWidth(image.width()*_zoom);
0062     zoomedImage=QPixmap(imageRect.width(),imageRect.height());
0063     QPainter p(&zoomedImage);
0064     p.scale(z,z);
0065     QPixmap pix;
0066     pix.convertFromImage(image);
0067     // if the picture has transparent areas,
0068     // fill them with Gimp like background
0069     if (pix.mask()) {
0070     QPixmap backPix(32,32);
0071     QPainter p2(&backPix);
0072     p2.fillRect(0,0,32,32,QColor(156,149,156));
0073     p2.fillRect(0,16,16,16,QColor(98,105,98));
0074     p2.fillRect(16,0,16,16,QColor(98,105,98));
0075     p2.flush();
0076     p.setPen(QPen());
0077     p.fillRect(imageRect.left(),imageRect.top(),imageRect.width(),imageRect.height(),QBrush(QColor("black"),backPix));
0078     }
0079     p.drawPixmap(imageRect.left(),imageRect.top(),pix);
0080     p.flush();
0081     resizeContents(visibleWidth()>imageRect.width() ? visibleWidth() : imageRect.width(),
0082                                  visibleHeight()>imageRect.height() ? visibleHeight() : imageRect.height());
0083     repaintContents(0,0,contentsWidth(),contentsHeight(),true);
0084 }
0085 
0086 QPoint ImageMap::translateFromZoom(const QPoint & p) const {
0087     return QPoint(p.x()/_zoom,p.y()/_zoom);
0088 }
0089 
0090 QPoint ImageMap::translateToZoom(const QPoint & p) const {
0091     return QPoint(round(p.x()*_zoom),round(p.y()*_zoom));
0092 }
0093 
0094 QRect ImageMap::translateToZoom(const QRect & r) const {
0095     return QRect(round(r.x()*_zoom),round(r.y()*_zoom),
0096                              round(r.width()*_zoom),round(r.height()*_zoom));
0097 }
0098 
0099 void ImageMap::mouseDoubleClickEvent(QMouseEvent* e) {
0100     QPoint point=e->pos();
0101     point-=imageRect.topLeft();
0102     point=translateFromZoom(point);
0103     if ( currentAction==None &&
0104         (currentArea=imageMapEditor->onArea(point)))
0105         imageMapEditor->showTagEditor(currentArea);
0106 
0107 }
0108 
0109 void ImageMap::mousePressEvent(QMouseEvent* e) {
0110     drawStart=e->pos();
0111     // Check if it's on picture if not
0112     // move it to the picture's border
0113     if (!imageRect.contains(drawStart)) {
0114         if (drawStart.x()>imageRect.right())
0115             drawStart.setX(imageRect.right());
0116         if (drawStart.x()<imageRect.left())
0117             drawStart.setX(imageRect.left());
0118         if (drawStart.y()>imageRect.bottom())
0119             drawStart.setY(imageRect.bottom());
0120         if (drawStart.y()<imageRect.top())
0121             drawStart.setY(imageRect.top());
0122     }
0123 
0124     // Translate it to picture coordinates
0125     drawStart-=imageRect.topLeft();
0126     drawStart=translateFromZoom(drawStart);
0127     if (currentArea)
0128         oldArea=new Area(*currentArea);
0129 
0130     if ( currentAction==None ) {
0131         if (e->button()==Qt::RightButton) {
0132             currentArea=imageMapEditor->onArea(drawStart);
0133             imageMapEditor->select(currentArea);
0134             imageMapEditor->slotShowPopupMenu(e->globalPos());
0135         } else
0136         if ((currentArea=imageMapEditor->selected()) &&
0137             (currentSelectionPoint=currentArea->onSelectionPoint(drawStart)))
0138         {
0139                 currentAction=MoveSelectionPoint;
0140         } else
0141         if ((currentArea=imageMapEditor->onArea(drawStart))) {
0142             currentAction=MoveArea;
0143             imageMapEditor->select(currentArea);
0144         } else
0145         if (imageMapEditor->currentShapeType()!=Area::None) {
0146             currentArea=new Area(imageMapEditor->currentShapeType());
0147           currentArea->setRect(QRect(drawStart,drawStart));
0148           currentArea->setSelected(false);
0149           if (imageMapEditor->selected())
0150             imageMapEditor->selected()->setSelected(false);
0151             switch (currentArea->type()) {
0152                 case Area::Rectangle : currentAction=DrawRectangle; break;
0153                 case Area::Circle : currentAction=DrawCircle; break;
0154                 case Area::Polygon :
0155                     currentAction=DrawPolygon;
0156                 currentArea->addCoord(drawStart);
0157                 currentSelectionPoint=currentArea->selectionPoints()->last();
0158 
0159                     break;
0160                 default: break;
0161             }
0162         }
0163     // Clicked with the arrow at an areafree position
0164     else {
0165         currentArea=0L;
0166         imageMapEditor->deselectAll();
0167     }
0168     } else
0169     if ( currentAction==DrawPolygon) {
0170 
0171     }
0172 
0173     QRect r;
0174     if (oldArea)
0175         r=oldArea->selectionRect();
0176     if (currentArea) {
0177         r= r | currentArea->selectionRect();
0178         repaintContents(translateToZoom(r),false);
0179     }
0180 
0181 }
0182 
0183 void ImageMap::mouseReleaseEvent(QMouseEvent *e) {
0184     drawEnd=e->pos();
0185 
0186     // Check if it's on picture if not
0187     // move it to the picture's border
0188     if (!imageRect.contains(drawEnd)) {
0189         if (drawEnd.x()>imageRect.right())
0190             drawEnd.setX(imageRect.right());
0191         if (drawEnd.x()<imageRect.left())
0192             drawEnd.setX(imageRect.left());
0193         if (drawEnd.y()>imageRect.bottom())
0194             drawEnd.setY(imageRect.bottom());
0195         if (drawEnd.y()<imageRect.top())
0196             drawEnd.setY(imageRect.top());
0197     }
0198     // Translate it to picture coordinates
0199     drawEnd-=imageRect.topLeft();
0200     drawEnd=translateFromZoom(drawEnd);
0201 
0202     if (currentAction==DrawCircle || currentAction==DrawRectangle) {
0203         imageMapEditor->addArea(currentArea);
0204         imageMapEditor->select(currentArea);
0205         //imageMapEditor->slotAreaChanged(currentArea);
0206         currentAction=None;
0207   } else
0208     if (currentAction==DrawPolygon) {
0209         // If the number of Polygonpoints is more than 2
0210         // and clicked on the first PolygonPoint or
0211         // the right Button was pressed the Polygon is finished
0212     if ((currentArea->selectionPoints()->count()>2)
0213         && (currentArea->selectionPoints()->first()->contains(drawEnd)
0214          || (e->button()==Qt::RightButton)))
0215     {
0216             currentArea->setFinished(true);
0217         imageMapEditor->addArea(currentArea);
0218         currentAction=None;
0219         } else
0220         {
0221         currentArea->addCoord(drawEnd);
0222         currentSelectionPoint=currentArea->selectionPoints()->last();
0223     }
0224 
0225 //          currentArea->addCoord(drawEnd);
0226 //          currentSelectionPoint=currentArea->selectionPoints()->last();
0227     } else
0228     if (currentAction==MoveArea || currentAction==MoveSelectionPoint) {
0229         imageMapEditor->slotAreaChanged(currentArea);
0230         currentAction=None;
0231   }
0232   else {
0233     currentAction=None;
0234   }
0235     imageMapEditor->slotChangeStatusCoords(drawEnd.x(),drawEnd.y());
0236     imageMapEditor->slotUpdateSelectionCoords();
0237 
0238     if (currentArea)
0239         repaintArea(*currentArea);
0240 //  repaintContents(0,0,contentsWidth(),contentsHeight(),false);
0241 }
0242 
0243 
0244 void ImageMap::mouseMoveEvent(QMouseEvent *e) {
0245         drawCurrent=e->pos();
0246 
0247         // If outside the image
0248         // set it to the border
0249         if (!imageRect.contains(drawCurrent)) {
0250         if (drawCurrent.x()>imageRect.right())
0251             drawCurrent.setX(imageRect.right());
0252         if (drawCurrent.x()<imageRect.left())
0253             drawCurrent.setX(imageRect.left());
0254         if (drawCurrent.y()>imageRect.bottom())
0255             drawCurrent.setY(imageRect.bottom());
0256         if (drawCurrent.y()<imageRect.top())
0257             drawCurrent.setY(imageRect.top());
0258         }
0259 
0260         // Translate to image coordinates
0261         drawCurrent-=imageRect.topLeft();
0262         drawCurrent=translateFromZoom(drawCurrent);
0263 
0264         if (currentAction==DrawRectangle) {
0265             // To avoid flicker, only repaint the minimum rect
0266             QRect oldRect=translateToZoom(currentArea->rect());
0267             currentArea->setRect(QRect(drawStart,drawCurrent).normalize());
0268             QRect newRect=translateToZoom(currentArea->rect());
0269             QRect r=oldRect | newRect;
0270             repaintContents(r,false);
0271             imageMapEditor->slotUpdateSelectionCoords(currentArea->rect());
0272         } else
0273         if (currentAction==DrawCircle) {
0274             QRect oldRect=translateToZoom(currentArea->rect());
0275             currentArea->setRect(QRect(drawStart,drawCurrent).normalize());
0276             QRect newRect=translateToZoom(currentArea->rect());
0277             QRect r=oldRect | newRect;
0278             repaintContents(r,false);
0279             imageMapEditor->slotUpdateSelectionCoords(currentArea->rect());
0280         } else
0281         if ( currentAction==DrawPolygon ) {
0282             QRect oldRect=translateToZoom(currentArea->rect());
0283             currentArea->moveSelectionPoint(currentSelectionPoint,drawCurrent);
0284             QRect newRect=translateToZoom(currentArea->rect());
0285             QRect r=oldRect | newRect;
0286             repaintContents(r,false);
0287             imageMapEditor->slotUpdateSelectionCoords(currentArea->rect());
0288         } else
0289         if ( currentAction==MoveArea ) {
0290             QRect oldRect=translateToZoom(currentArea->selectionRect());
0291             currentArea->translate((drawCurrent-drawStart).x(),(drawCurrent-drawStart).y());
0292             QRect newRect=translateToZoom(currentArea->selectionRect());
0293             QRect r=oldRect | newRect;
0294             repaintContents(r,false);
0295             drawStart=drawCurrent;
0296             imageMapEditor->slotUpdateSelectionCoords();
0297         } else
0298         if ( currentAction==MoveSelectionPoint ) {
0299             QRect oldRect=translateToZoom(currentArea->selectionRect());
0300             currentArea->moveSelectionPoint(currentSelectionPoint,drawCurrent);
0301             QRect newRect=translateToZoom(currentArea->selectionRect());
0302             QRect r=oldRect | newRect;
0303             repaintContents(r,false);
0304             imageMapEditor->slotUpdateSelectionCoords();
0305         }
0306         imageMapEditor->slotChangeStatusCoords(drawCurrent.x(),drawCurrent.y());
0307 }
0308 
0309 void ImageMap::resizeEvent(QResizeEvent* e) {
0310     QScrollArea::resizeEvent(e);
0311     int width=(int) (image.width()*_zoom);
0312     int height=(int) (image.height()*_zoom);
0313     if (visibleWidth()>width)
0314         width=visibleWidth();
0315     if (visibleHeight()>height)
0316         height=visibleHeight();
0317 
0318     resizeContents(width,height);
0319 
0320     imageRect.setLeft(0);
0321     imageRect.setTop(0);
0322     imageRect.setHeight(image.height()*_zoom);
0323     imageRect.setWidth(image.width()*_zoom);
0324 
0325 }
0326 
0327 void ImageMap::repaintArea(const Area & a) {
0328     repaintContents(translateToZoom(a.selectionRect()),false);
0329 }
0330 
0331 void ImageMap::drawContents(QPainter* p,int clipx,int clipy,int clipw,int cliph) {
0332 //  qCDebug(KIMAGEMAPEDITOR_LOG) << "drawing\n";
0333 //  p.scale(rect.width()*2,rect.height()*2);
0334 //  if (e->rect()!=rect()) {
0335 //      p.setClipping(true);
0336 //      p.setClipRect(e->rect());
0337 //  } else
0338 /*  if (currentAction==DrawRectangle) {
0339         p->setClipping(true);
0340         QRect r(currentArea->rect());
0341         r.translate(imageRect.left()-5,imageRect.top()-5);
0342         r.setSize(r.size()+QSize(10,10));
0343         p->setClipRegion(r);
0344     }
0345 */
0346 
0347     QRect updateRect(clipx,clipy,clipw,cliph);
0348   QPixmap doubleBuffer(updateRect.size());        // Pixmap for double-buffering
0349   QPainter p2(&doubleBuffer);
0350     p2.drawPixmap(0,0,zoomedImage,clipx,clipy,clipw,cliph);
0351     p2.translate(-updateRect.x(), -updateRect.y());
0352     p2.scale(_zoom,_zoom);
0353 
0354     AreaList *list=imageMapEditor->areaList();
0355     for (Area* s=list->first();s != 0L; s=list->next())
0356         s->draw(p2);
0357 
0358     // Draw the current drawing Area
0359     if (currentAction != MoveArea &&
0360             currentAction != MoveSelectionPoint &&
0361             currentAction != None)
0362     {
0363         currentArea->draw(p2);
0364     }
0365 
0366   p2.end();
0367 
0368   // Copy the double buffer into the widget
0369   p->drawPixmap(clipx,clipy,doubleBuffer);
0370     // Erase background without flicker
0371     QRegion region(contentsX(),contentsY(),visibleWidth(),visibleHeight());
0372     region=region.subtract(QRegion(imageRect));
0373     for (int i=0;i<region.rects().count();i++) {
0374         p->eraseRect(region.rects()[i]);
0375     }
0376 
0377 
0378     // Draw our picture
0379 //  p->drawPixmap(imageRect.left(),imageRect.top(),zoomedImage);
0380 //
0381 //
0382 //  p->scale(_zoom,_zoom);
0383 //  p->translate(imageRect.left(),imageRect.top());
0384 //
0385 //  AreaList *list=imageMapEditor->areaList();
0386 //  for (Area* s=list->first();s != 0L; s=list->next())
0387 //      s->draw(*p);
0388 //
0389 //  // Draw the current drawing Area
0390 //  if (currentAction != MoveArea &&
0391 //          currentAction != MoveSelectionPoint &&
0392 //          currentAction != None)
0393 //  {
0394 //      currentArea->draw(*p);
0395 //  }
0396 
0397 
0398 }