File indexing completed on 2024-09-15 03:57:31
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 }