00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026 #include "kpixmapregionselectorwidget.h"
00027 #include <QtGui/QPainter>
00028 #include <QtGui/QColor>
00029 #include <QtGui/QImage>
00030 #include <QLabel>
00031 #include <QtGui/QLayout>
00032 #include <QRubberBand>
00033 #include <kdebug.h>
00034 #include <kicon.h>
00035 #include <klocale.h>
00036 #include <kmenu.h>
00037 #include <kaction.h>
00038 #include <stdlib.h>
00039 #include <QtGui/QCursor>
00040 #include <QtGui/QApplication>
00041 #include <QMouseEvent>
00042 #include "kactioncollection.h"
00043
00044 class KPixmapRegionSelectorWidget::Private
00045 {
00046 public:
00047 Private(KPixmapRegionSelectorWidget *q): q(q) {}
00048
00049 KPixmapRegionSelectorWidget *q;
00050
00055 void updatePixmap();
00056
00057 QRect calcSelectionRectangle( const QPoint &startPoint, const QPoint & endPoint );
00058
00059 enum CursorState { None=0, Resizing, Moving };
00060 CursorState m_state;
00061
00062 QPixmap m_unzoomedPixmap;
00063 QPixmap m_originalPixmap;
00064 QPixmap m_linedPixmap;
00065 QRect m_selectedRegion;
00066 QLabel *m_label;
00067
00068 QPoint m_tempFirstClick;
00069 double m_forcedAspectRatio;
00070
00071 int m_maxWidth, m_maxHeight;
00072 double m_zoomFactor;
00073
00074 QRubberBand *m_rubberBand;
00075 };
00076
00077 KPixmapRegionSelectorWidget::KPixmapRegionSelectorWidget( QWidget *parent)
00078 : QWidget( parent ), d(new Private(this))
00079 {
00080 QHBoxLayout * hboxLayout=new QHBoxLayout( this );
00081
00082 hboxLayout->addStretch();
00083 QVBoxLayout * vboxLayout=new QVBoxLayout();
00084 hboxLayout->addItem(vboxLayout);
00085
00086 vboxLayout->addStretch();
00087 d->m_label = new QLabel(this);
00088 d->m_label->setAttribute(Qt::WA_NoSystemBackground,true);
00089 d->m_label->installEventFilter( this );
00090
00091 vboxLayout->addWidget(d->m_label);
00092 vboxLayout->addStretch();
00093
00094 hboxLayout->addStretch();
00095
00096 d->m_forcedAspectRatio=0;
00097
00098 d->m_zoomFactor=1.0;
00099 d->m_rubberBand = new QRubberBand(QRubberBand::Rectangle, d->m_label);
00100 d->m_rubberBand->hide();
00101 }
00102
00103 KPixmapRegionSelectorWidget::~KPixmapRegionSelectorWidget()
00104 {
00105 delete d;
00106 }
00107
00108 QPixmap KPixmapRegionSelectorWidget::pixmap() const
00109 {
00110 return d->m_unzoomedPixmap;
00111 }
00112
00113 void KPixmapRegionSelectorWidget::setPixmap( const QPixmap &pixmap )
00114 {
00115 Q_ASSERT(!pixmap.isNull());
00116 d->m_originalPixmap = pixmap;
00117 d->m_unzoomedPixmap = pixmap;
00118 d->m_label->setPixmap( pixmap );
00119 resetSelection();
00120 }
00121
00122 void KPixmapRegionSelectorWidget::resetSelection()
00123 {
00124 d->m_selectedRegion = d->m_originalPixmap.rect();
00125 d->m_rubberBand->hide();
00126 d->updatePixmap();
00127 }
00128
00129 QRect KPixmapRegionSelectorWidget::selectedRegion() const
00130 {
00131 return d->m_selectedRegion;
00132 }
00133
00134 void KPixmapRegionSelectorWidget::setSelectedRegion(const QRect &rect)
00135 {
00136 if (!rect.isValid()) resetSelection();
00137 else
00138 {
00139 d->m_selectedRegion=rect;
00140 d->updatePixmap();
00141
00142 QRect r=unzoomedSelectedRegion();
00143 }
00144 }
00145
00146 void KPixmapRegionSelectorWidget::Private::updatePixmap()
00147 {
00148 Q_ASSERT(!m_originalPixmap.isNull());
00149 if (m_originalPixmap.isNull()) { m_label->setPixmap(m_originalPixmap); return; }
00150 if (m_selectedRegion.width()>m_originalPixmap.width()) m_selectedRegion.setWidth( m_originalPixmap.width() );
00151 if (m_selectedRegion.height()>m_originalPixmap.height()) m_selectedRegion.setHeight( m_originalPixmap.height() );
00152
00153 QPainter painter;
00154 if (m_linedPixmap.isNull())
00155 {
00156 m_linedPixmap = m_originalPixmap;
00157 QPainter p(&m_linedPixmap);
00158 p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
00159 p.fillRect(m_linedPixmap.rect(), QColor(0, 0, 0, 100));
00160 }
00161
00162 QPixmap pixmap = m_linedPixmap;
00163 painter.begin(&pixmap);
00164 painter.drawPixmap( m_selectedRegion.topLeft(),
00165 m_originalPixmap, m_selectedRegion );
00166
00167
00168 painter.end();
00169
00170 m_label->setPixmap(pixmap);
00171
00172 qApp->sendPostedEvents(0,QEvent::LayoutRequest);
00173
00174 if (m_selectedRegion == m_originalPixmap.rect())
00175 m_rubberBand->hide();
00176 else
00177 {
00178 m_rubberBand->setGeometry(QRect(m_selectedRegion.topLeft(),
00179 m_selectedRegion.size()));
00180
00181
00182
00183
00184 if (m_state!=None) m_rubberBand->show();
00185 }
00186
00187 }
00188
00189
00190 KMenu *KPixmapRegionSelectorWidget::createPopupMenu()
00191 {
00192 KMenu *popup=new KMenu(this );
00193 KActionCollection *actions=new KActionCollection(popup);
00194 popup->setObjectName( "PixmapRegionSelectorPopup");
00195 popup->addTitle(i18n("Image Operations"));
00196
00197 QAction *action = actions->addAction("rotateclockwise");
00198 action->setText(i18n("&Rotate Clockwise"));
00199 action->setIcon( KIcon( "object-rotate-right" ) );
00200 connect( action, SIGNAL( triggered( bool ) ), this, SLOT(rotateClockwise()) );
00201
00202 popup->addAction(action);
00203
00204 action = actions->addAction("rotatecounterclockwise");
00205 action->setText(i18n("Rotate &Counterclockwise"));
00206 action->setIcon( KIcon( "object-rotate-left" ) );
00207 connect( action, SIGNAL( triggered( bool ) ), this, SLOT(rotateCounterclockwise()) );
00208
00209 popup->addAction(action);
00210
00211
00212
00213
00214
00215 return popup;
00216 }
00217
00218 void KPixmapRegionSelectorWidget::rotate(RotateDirection direction)
00219 {
00220 int w=d->m_originalPixmap.width();
00221 int h=d->m_originalPixmap.height();
00222 QImage img=d->m_unzoomedPixmap.toImage();
00223 if(direction == Rotate90)
00224 img = img.transformed(QTransform().rotate(90.0));
00225 else if(direction == Rotate180)
00226 img = img.transformed(QTransform().rotate(180.0));
00227 else
00228 img = img.transformed(QTransform().rotate(270.0));
00229
00230 d->m_unzoomedPixmap=QPixmap::fromImage(img);
00231
00232 img=d->m_originalPixmap.toImage();
00233 if(direction == Rotate90)
00234 img = img.transformed(QTransform().rotate(90.0));
00235 else if(direction == Rotate180)
00236 img = img.transformed(QTransform().rotate(180.0));
00237 else
00238 img = img.transformed(QTransform().rotate(270.0));
00239
00240 d->m_originalPixmap=QPixmap::fromImage(img);
00241
00242 d->m_linedPixmap=QPixmap();
00243
00244 if (d->m_forcedAspectRatio>0 && d->m_forcedAspectRatio!=1)
00245 resetSelection();
00246 else
00247 {
00248 switch (direction)
00249 {
00250 case ( Rotate90 ):
00251 {
00252 int x=h-d->m_selectedRegion.y()-d->m_selectedRegion.height();
00253 int y=d->m_selectedRegion.x();
00254 d->m_selectedRegion.setRect(x, y, d->m_selectedRegion.height(), d->m_selectedRegion.width() );
00255 d->updatePixmap();
00256
00257
00258
00259 } break;
00260 case ( Rotate270 ):
00261 {
00262 int x=d->m_selectedRegion.y();
00263 int y=w-d->m_selectedRegion.x()-d->m_selectedRegion.width();
00264 d->m_selectedRegion.setRect(x, y, d->m_selectedRegion.height(), d->m_selectedRegion.width() );
00265 d->updatePixmap();
00266
00267
00268 } break;
00269 default: resetSelection();
00270 }
00271 }
00272 }
00273
00274 void KPixmapRegionSelectorWidget::rotateClockwise()
00275 {
00276 rotate(Rotate90);
00277 }
00278
00279 void KPixmapRegionSelectorWidget::rotateCounterclockwise()
00280 {
00281 rotate(Rotate270);
00282 }
00283
00284 bool KPixmapRegionSelectorWidget::eventFilter(QObject *obj, QEvent *ev)
00285 {
00286 if ( ev->type() == QEvent::MouseButtonPress )
00287 {
00288 QMouseEvent *mev= (QMouseEvent *)(ev);
00289
00290
00291 if ( mev->button() == Qt::RightButton )
00292 {
00293 KMenu *popup = createPopupMenu( );
00294 popup->exec( mev->globalPos() );
00295 delete popup;
00296 return true;
00297 }
00298
00299 QCursor cursor;
00300
00301 if ( d->m_selectedRegion.contains( mev->pos() )
00302 && d->m_selectedRegion!=d->m_originalPixmap.rect() )
00303 {
00304 d->m_state=Private::Moving;
00305 cursor.setShape( Qt::SizeAllCursor );
00306 d->m_rubberBand->show();
00307 }
00308 else
00309 {
00310 d->m_state=Private::Resizing;
00311 cursor.setShape( Qt::CrossCursor );
00312 }
00313 QApplication::setOverrideCursor(cursor);
00314
00315 d->m_tempFirstClick=mev->pos();
00316
00317
00318 return true;
00319 }
00320
00321 if ( ev->type() == QEvent::MouseMove )
00322 {
00323 QMouseEvent *mev= (QMouseEvent *)(ev);
00324
00325
00326
00327 if ( d->m_state == Private::Resizing )
00328 {
00329 setSelectedRegion (
00330 d->calcSelectionRectangle( d->m_tempFirstClick, mev->pos() ) );
00331 }
00332 else if (d->m_state == Private::Moving )
00333 {
00334 int mevx = mev->x();
00335 int mevy = mev->y();
00336 bool mouseOutside=false;
00337 if ( mevx < 0 )
00338 {
00339 d->m_selectedRegion.translate(-d->m_selectedRegion.x(),0);
00340 mouseOutside=true;
00341 }
00342 else if ( mevx > d->m_originalPixmap.width() )
00343 {
00344 d->m_selectedRegion.translate(d->m_originalPixmap.width()-d->m_selectedRegion.width()-d->m_selectedRegion.x(),0);
00345 mouseOutside=true;
00346 }
00347 if ( mevy < 0 )
00348 {
00349 d->m_selectedRegion.translate(0,-d->m_selectedRegion.y());
00350 mouseOutside=true;
00351 }
00352 else if ( mevy > d->m_originalPixmap.height() )
00353 {
00354 d->m_selectedRegion.translate(0,d->m_originalPixmap.height()-d->m_selectedRegion.height()-d->m_selectedRegion.y());
00355 mouseOutside=true;
00356 }
00357 if (mouseOutside) { d->updatePixmap(); return true; };
00358
00359 d->m_selectedRegion.translate( mev->x()-d->m_tempFirstClick.x(),
00360 mev->y()-d->m_tempFirstClick.y() );
00361
00362
00363 if (d->m_selectedRegion.x() < 0)
00364 d->m_selectedRegion.translate(-d->m_selectedRegion.x(),0);
00365 else if (d->m_selectedRegion.right() > d->m_originalPixmap.width())
00366 d->m_selectedRegion.translate(-(d->m_selectedRegion.right()-d->m_originalPixmap.width()),0);
00367
00368 if (d->m_selectedRegion.y() < 0)
00369 d->m_selectedRegion.translate(0,-d->m_selectedRegion.y());
00370 else if (d->m_selectedRegion.bottom() > d->m_originalPixmap.height())
00371 d->m_selectedRegion.translate(0,-(d->m_selectedRegion.bottom()-d->m_originalPixmap.height()));
00372
00373 d->m_tempFirstClick=mev->pos();
00374 d->updatePixmap();
00375 }
00376 return true;
00377 }
00378
00379 if ( ev->type() == QEvent::MouseButtonRelease )
00380 {
00381 QMouseEvent *mev= (QMouseEvent *)(ev);
00382
00383 if ( d->m_state == Private::Resizing && mev->pos() == d->m_tempFirstClick)
00384 resetSelection();
00385
00386 d->m_state=Private::None;
00387 QApplication::restoreOverrideCursor();
00388 d->m_rubberBand->hide();
00389 return true;
00390 }
00391
00392 QWidget::eventFilter(obj, ev);
00393 return false;
00394 }
00395
00396 QRect KPixmapRegionSelectorWidget::Private::calcSelectionRectangle( const QPoint & startPoint, const QPoint & _endPoint )
00397 {
00398 QPoint endPoint = _endPoint;
00399 if ( endPoint.x() < 0 ) endPoint.setX(0);
00400 else if ( endPoint.x() > m_originalPixmap.width() ) endPoint.setX(m_originalPixmap.width());
00401 if ( endPoint.y() < 0 ) endPoint.setY(0);
00402 else if ( endPoint.y() > m_originalPixmap.height() ) endPoint.setY(m_originalPixmap.height());
00403 int w=abs(startPoint.x()-endPoint.x());
00404 int h=abs(startPoint.y()-endPoint.y());
00405
00406 if (m_forcedAspectRatio>0)
00407 {
00408 double aspectRatio=w/double(h);
00409
00410 if (aspectRatio>m_forcedAspectRatio)
00411 h=(int)(w/m_forcedAspectRatio);
00412 else
00413 w=(int)(h*m_forcedAspectRatio);
00414 }
00415
00416 int x,y;
00417 if ( startPoint.x() < endPoint.x() )
00418 x=startPoint.x();
00419 else
00420 x=startPoint.x()-w;
00421 if ( startPoint.y() < endPoint.y() )
00422 y=startPoint.y();
00423 else
00424 y=startPoint.y()-h;
00425
00426 if (x<0)
00427 {
00428 w+=x;
00429 x=0;
00430 h=(int)(w/m_forcedAspectRatio);
00431
00432 if ( startPoint.y() > endPoint.y() )
00433 y=startPoint.y()-h;
00434 }
00435 else if (x+w>m_originalPixmap.width())
00436 {
00437 w=m_originalPixmap.width()-x;
00438 h=(int)(w/m_forcedAspectRatio);
00439
00440 if ( startPoint.y() > endPoint.y() )
00441 y=startPoint.y()-h;
00442 }
00443 if (y<0)
00444 {
00445 h+=y;
00446 y=0;
00447 w=(int)(h*m_forcedAspectRatio);
00448
00449 if ( startPoint.x() > endPoint.x() )
00450 x=startPoint.x()-w;
00451 }
00452 else if (y+h>m_originalPixmap.height())
00453 {
00454 h=m_originalPixmap.height()-y;
00455 w=(int)(h*m_forcedAspectRatio);
00456
00457 if ( startPoint.x() > endPoint.x() )
00458 x=startPoint.x()-w;
00459 }
00460
00461 return QRect(x,y,w,h);
00462 }
00463
00464 QRect KPixmapRegionSelectorWidget::unzoomedSelectedRegion() const
00465 {
00466 return QRect((int)(d->m_selectedRegion.x()/d->m_zoomFactor),
00467 (int)(d->m_selectedRegion.y()/d->m_zoomFactor),
00468 (int)(d->m_selectedRegion.width()/d->m_zoomFactor),
00469 (int)(d->m_selectedRegion.height()/d->m_zoomFactor));
00470 }
00471
00472 QImage KPixmapRegionSelectorWidget::selectedImage() const
00473 {
00474 QImage origImage=d->m_unzoomedPixmap.toImage();
00475 return origImage.copy(unzoomedSelectedRegion());
00476 }
00477
00478 void KPixmapRegionSelectorWidget::setSelectionAspectRatio(int width, int height)
00479 {
00480 d->m_forcedAspectRatio=width/double(height);
00481 }
00482
00483 void KPixmapRegionSelectorWidget::setFreeSelectionAspectRatio()
00484 {
00485 d->m_forcedAspectRatio=0;
00486 }
00487
00488 void KPixmapRegionSelectorWidget::setMaximumWidgetSize(int width, int height)
00489 {
00490 d->m_maxWidth=width;
00491 d->m_maxHeight=height;
00492
00493 d->m_originalPixmap=d->m_unzoomedPixmap;
00494 if (d->m_selectedRegion == d->m_originalPixmap.rect()) d->m_selectedRegion=QRect();
00495
00496
00497
00498
00499 if ( !d->m_originalPixmap.isNull() &&
00500 ( d->m_originalPixmap.width() > d->m_maxWidth ||
00501 d->m_originalPixmap.height() > d->m_maxHeight ) )
00502 {
00503
00504 QImage image=d->m_originalPixmap.toImage();
00505 d->m_originalPixmap=QPixmap::fromImage( image.scaled( width, height, Qt::KeepAspectRatio,Qt::SmoothTransformation ) );
00506 double oldZoomFactor = d->m_zoomFactor;
00507 d->m_zoomFactor=d->m_originalPixmap.width()/(double)d->m_unzoomedPixmap.width();
00508
00509 if (d->m_selectedRegion.isValid())
00510 {
00511 d->m_selectedRegion=
00512 QRect((int)(d->m_selectedRegion.x()*d->m_zoomFactor/oldZoomFactor),
00513 (int)(d->m_selectedRegion.y()*d->m_zoomFactor/oldZoomFactor),
00514 (int)(d->m_selectedRegion.width()*d->m_zoomFactor/oldZoomFactor),
00515 (int)(d->m_selectedRegion.height()*d->m_zoomFactor/oldZoomFactor) );
00516 }
00517 }
00518
00519 if (!d->m_selectedRegion.isValid()) d->m_selectedRegion = d->m_originalPixmap.rect();
00520
00521 d->m_linedPixmap=QPixmap();
00522 d->updatePixmap();
00523 resize(d->m_label->width(), d->m_label->height());
00524 }
00525
00526 #include "kpixmapregionselectorwidget.moc"