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 <qpainter.h>
00028 #include <qcolor.h>
00029 #include <qimage.h>
00030 #include <qlayout.h>
00031 #include <kimageeffect.h>
00032 #include <kdebug.h>
00033 #include <klocale.h>
00034 #include <kpopupmenu.h>
00035 #include <kaction.h>
00036 #include <stdlib.h>
00037 #include <qcursor.h>
00038 #include <qapplication.h>
00039
00040 KPixmapRegionSelectorWidget::KPixmapRegionSelectorWidget( QWidget *parent,
00041 const char *name) : QWidget( parent, name)
00042 {
00043 QHBoxLayout * hboxLayout=new QHBoxLayout( this );
00044
00045 hboxLayout->addStretch();
00046 QVBoxLayout * vboxLayout=new QVBoxLayout( hboxLayout );
00047
00048 vboxLayout->addStretch();
00049 m_label = new QLabel(this, "pixmapHolder");
00050 m_label->setBackgroundMode( Qt::NoBackground );
00051 m_label->installEventFilter( this );
00052
00053 vboxLayout->addWidget(m_label);
00054 vboxLayout->addStretch();
00055
00056 hboxLayout->addStretch();
00057
00058 m_forcedAspectRatio=0;
00059
00060 m_zoomFactor=1.0;
00061 }
00062
00063 KPixmapRegionSelectorWidget::~KPixmapRegionSelectorWidget()
00064 {
00065 }
00066
00067 void KPixmapRegionSelectorWidget::setPixmap( const QPixmap &pixmap )
00068 {
00069 Q_ASSERT(!pixmap.isNull());
00070 m_originalPixmap = pixmap;
00071 m_unzoomedPixmap = pixmap;
00072 m_label->setPixmap( pixmap );
00073 resetSelection();
00074 }
00075
00076 void KPixmapRegionSelectorWidget::resetSelection()
00077 {
00078 m_selectedRegion = m_originalPixmap.rect();
00079 updatePixmap();
00080 }
00081
00082 QRect KPixmapRegionSelectorWidget::selectedRegion() const
00083 {
00084 return m_selectedRegion;
00085 }
00086
00087 void KPixmapRegionSelectorWidget::setSelectedRegion(const QRect &rect)
00088 {
00089 if (!rect.isValid()) resetSelection();
00090 else
00091 {
00092 m_selectedRegion=rect;
00093 updatePixmap();
00094
00095 QRect r=unzoomedSelectedRegion();
00096 }
00097 }
00098
00099 void KPixmapRegionSelectorWidget::updatePixmap()
00100 {
00101 Q_ASSERT(!m_originalPixmap.isNull()); if(m_originalPixmap.isNull()) { m_label->setPixmap(m_originalPixmap); return; }
00102 if (m_selectedRegion.width()>m_originalPixmap.width()) m_selectedRegion.setWidth( m_originalPixmap.width() );
00103 if (m_selectedRegion.height()>m_originalPixmap.height()) m_selectedRegion.setHeight( m_originalPixmap.height() );
00104
00105 QPainter painter;
00106 if (m_linedPixmap.isNull())
00107 {
00108 m_linedPixmap = m_originalPixmap;
00109
00110 painter.begin(&m_linedPixmap);
00111 painter.setRasterOp( Qt::XorROP );
00112 painter.fillRect(0,0,m_linedPixmap.width(), m_linedPixmap.height(),
00113 QBrush( QColor(255,255,255), Qt::BDiagPattern) );
00114 painter.end();
00115
00116 QImage image=m_linedPixmap.convertToImage();
00117 image=KImageEffect::fade(image, (float)0.4, QColor(0,0,0));
00118 m_linedPixmap.convertFromImage(image);
00119 }
00120
00121 QPixmap pixmap = m_linedPixmap;
00122
00123 painter.begin(&pixmap);
00124 painter.drawPixmap( m_selectedRegion.topLeft(),
00125 m_originalPixmap, m_selectedRegion );
00126
00127 painter.setPen( QColor(255,255,255) );
00128 painter.setRasterOp( Qt::XorROP );
00129
00130 painter.drawRect( m_selectedRegion );
00131
00132 painter.end();
00133
00134 m_label->setPixmap(pixmap);
00135 }
00136
00137
00138 KPopupMenu *KPixmapRegionSelectorWidget::createPopupMenu()
00139 {
00140 KPopupMenu *popup=new KPopupMenu(this, "PixmapRegionSelectorPopup");
00141 popup->insertTitle(i18n("Image Operations"));
00142
00143 KAction *action = new KAction(i18n("&Rotate Clockwise"), "rotate_cw",
00144 0, this, SLOT(rotateClockwise()),
00145 popup, "rotateclockwise");
00146 action->plug(popup);
00147
00148 action = new KAction(i18n("Rotate &Counterclockwise"), "rotate_ccw",
00149 0, this, SLOT(rotateCounterclockwise()),
00150 popup, "rotatecounterclockwise");
00151 action->plug(popup);
00152
00153
00154
00155
00156
00157 return popup;
00158 }
00159
00160 void KPixmapRegionSelectorWidget::rotate(KImageEffect::RotateDirection direction)
00161 {
00162 int w=m_originalPixmap.width();
00163 int h=m_originalPixmap.height();
00164 QImage img=m_unzoomedPixmap.convertToImage();
00165 img= KImageEffect::rotate(img, direction);
00166 m_unzoomedPixmap.convertFromImage(img);
00167
00168 img=m_originalPixmap.convertToImage();
00169 img= KImageEffect::rotate(img, direction);
00170 m_originalPixmap.convertFromImage(img);
00171
00172 m_linedPixmap=QPixmap();
00173
00174 if (m_forcedAspectRatio>0 && m_forcedAspectRatio!=1)
00175 resetSelection();
00176 else
00177 {
00178 switch (direction)
00179 {
00180 case ( KImageEffect::Rotate90 ):
00181 {
00182 int x=h-m_selectedRegion.y()-m_selectedRegion.height();
00183 int y=m_selectedRegion.x();
00184 m_selectedRegion.setRect(x, y, m_selectedRegion.height(), m_selectedRegion.width() );
00185 updatePixmap();
00186 } break;
00187 case ( KImageEffect::Rotate270 ):
00188 {
00189 int x=m_selectedRegion.y();
00190 int y=w-m_selectedRegion.x()-m_selectedRegion.width();
00191 m_selectedRegion.setRect(x, y, m_selectedRegion.height(), m_selectedRegion.width() );
00192 updatePixmap();
00193 } break;
00194 default: resetSelection();
00195 }
00196 }
00197 }
00198
00199 void KPixmapRegionSelectorWidget::rotateClockwise()
00200 {
00201 rotate(KImageEffect::Rotate90);
00202 }
00203
00204 void KPixmapRegionSelectorWidget::rotateCounterclockwise()
00205 {
00206 rotate(KImageEffect::Rotate270);
00207 }
00208
00209 bool KPixmapRegionSelectorWidget::eventFilter(QObject *obj, QEvent *ev)
00210 {
00211 if ( ev->type() == QEvent::MouseButtonPress )
00212 {
00213 QMouseEvent *mev= (QMouseEvent *)(ev);
00214
00215
00216 if ( mev->button() == RightButton )
00217 {
00218 KPopupMenu *popup = createPopupMenu( );
00219 popup->exec( mev->globalPos() );
00220 delete popup;
00221 return TRUE;
00222 };
00223
00224 QCursor cursor;
00225
00226 if ( m_selectedRegion.contains( mev->pos() )
00227 && m_selectedRegion!=m_originalPixmap.rect() )
00228 {
00229 m_state=Moving;
00230 cursor.setShape( Qt::SizeAllCursor );
00231 }
00232 else
00233 {
00234 m_state=Resizing;
00235 cursor.setShape( Qt::CrossCursor );
00236 }
00237 QApplication::setOverrideCursor(cursor);
00238
00239 m_tempFirstClick=mev->pos();
00240
00241
00242 return TRUE;
00243 }
00244
00245 if ( ev->type() == QEvent::MouseMove )
00246 {
00247 QMouseEvent *mev= (QMouseEvent *)(ev);
00248
00249
00250
00251 if ( m_state == Resizing )
00252 {
00253 setSelectedRegion (
00254 calcSelectionRectangle( m_tempFirstClick, mev->pos() ) );
00255 }
00256 else if (m_state == Moving )
00257 {
00258 int mevx = mev->x();
00259 int mevy = mev->y();
00260 bool mouseOutside=false;
00261 if ( mevx < 0 )
00262 {
00263 m_selectedRegion.moveBy(-m_selectedRegion.x(),0);
00264 mouseOutside=true;
00265 }
00266 else if ( mevx > m_originalPixmap.width() )
00267 {
00268 m_selectedRegion.moveBy(m_originalPixmap.width()-m_selectedRegion.width()-m_selectedRegion.x(),0);
00269 mouseOutside=true;
00270 }
00271 if ( mevy < 0 )
00272 {
00273 m_selectedRegion.moveBy(0,-m_selectedRegion.y());
00274 mouseOutside=true;
00275 }
00276 else if ( mevy > m_originalPixmap.height() )
00277 {
00278 m_selectedRegion.moveBy(0,m_originalPixmap.height()-m_selectedRegion.height()-m_selectedRegion.y());
00279 mouseOutside=true;
00280 }
00281 if (mouseOutside) { updatePixmap(); return TRUE; };
00282
00283 m_selectedRegion.moveBy( mev->x()-m_tempFirstClick.x(),
00284 mev->y()-m_tempFirstClick.y() );
00285
00286
00287 if (m_selectedRegion.x() < 0)
00288 m_selectedRegion.moveBy(-m_selectedRegion.x(),0);
00289 else if (m_selectedRegion.right() > m_originalPixmap.width())
00290 m_selectedRegion.moveBy(-(m_selectedRegion.right()-m_originalPixmap.width()),0);
00291
00292 if (m_selectedRegion.y() < 0)
00293 m_selectedRegion.moveBy(0,-m_selectedRegion.y());
00294 else if (m_selectedRegion.bottom() > m_originalPixmap.height())
00295 m_selectedRegion.moveBy(0,-(m_selectedRegion.bottom()-m_originalPixmap.height()));
00296
00297 m_tempFirstClick=mev->pos();
00298 updatePixmap();
00299 }
00300 return TRUE;
00301 }
00302
00303 if ( ev->type() == QEvent::MouseButtonRelease )
00304 {
00305 QMouseEvent *mev= (QMouseEvent *)(ev);
00306
00307 if ( m_state == Resizing && mev->pos() == m_tempFirstClick)
00308 resetSelection();
00309
00310 m_state=None;
00311 QApplication::restoreOverrideCursor();
00312
00313 return TRUE;
00314 }
00315
00316 QWidget::eventFilter(obj, ev);
00317 return FALSE;
00318 }
00319
00320 QRect KPixmapRegionSelectorWidget::calcSelectionRectangle( const QPoint & startPoint, const QPoint & _endPoint )
00321 {
00322 QPoint endPoint = _endPoint;
00323 if ( endPoint.x() < 0 ) endPoint.setX(0);
00324 else if ( endPoint.x() > m_originalPixmap.width() ) endPoint.setX(m_originalPixmap.width());
00325 if ( endPoint.y() < 0 ) endPoint.setY(0);
00326 else if ( endPoint.y() > m_originalPixmap.height() ) endPoint.setY(m_originalPixmap.height());
00327 int w=abs(startPoint.x()-endPoint.x());
00328 int h=abs(startPoint.y()-endPoint.y());
00329
00330 if (m_forcedAspectRatio>0)
00331 {
00332 double aspectRatio=w/double(h);
00333
00334 if (aspectRatio>m_forcedAspectRatio)
00335 h=(int)(w/m_forcedAspectRatio);
00336 else
00337 w=(int)(h*m_forcedAspectRatio);
00338 }
00339
00340 int x,y;
00341 if ( startPoint.x() < endPoint.x() )
00342 x=startPoint.x();
00343 else
00344 x=startPoint.x()-w;
00345 if ( startPoint.y() < endPoint.y() )
00346 y=startPoint.y();
00347 else
00348 y=startPoint.y()-h;
00349
00350 if (x<0)
00351 {
00352 w+=x;
00353 x=0;
00354 h=(int)(w/m_forcedAspectRatio);
00355
00356 if ( startPoint.y() > endPoint.y() )
00357 y=startPoint.y()-h;
00358 }
00359 else if (x+w>m_originalPixmap.width())
00360 {
00361 w=m_originalPixmap.width()-x;
00362 h=(int)(w/m_forcedAspectRatio);
00363
00364 if ( startPoint.y() > endPoint.y() )
00365 y=startPoint.y()-h;
00366 }
00367 if (y<0)
00368 {
00369 h+=y;
00370 y=0;
00371 w=(int)(h*m_forcedAspectRatio);
00372
00373 if ( startPoint.x() > endPoint.x() )
00374 x=startPoint.x()-w;
00375 }
00376 else if (y+h>m_originalPixmap.height())
00377 {
00378 h=m_originalPixmap.height()-y;
00379 w=(int)(h*m_forcedAspectRatio);
00380
00381 if ( startPoint.x() > endPoint.x() )
00382 x=startPoint.x()-w;
00383 }
00384
00385 return QRect(x,y,w,h);
00386 }
00387
00388 QRect KPixmapRegionSelectorWidget::unzoomedSelectedRegion() const
00389 {
00390 return QRect((int)(m_selectedRegion.x()/m_zoomFactor),
00391 (int)(m_selectedRegion.y()/m_zoomFactor),
00392 (int)(m_selectedRegion.width()/m_zoomFactor),
00393 (int)(m_selectedRegion.height()/m_zoomFactor));
00394 }
00395
00396 QImage KPixmapRegionSelectorWidget::selectedImage() const
00397 {
00398 QImage origImage=m_unzoomedPixmap.convertToImage();
00399 return origImage.copy(unzoomedSelectedRegion());
00400 }
00401
00402 void KPixmapRegionSelectorWidget::setSelectionAspectRatio(int width, int height)
00403 {
00404 m_forcedAspectRatio=width/double(height);
00405 }
00406
00407 void KPixmapRegionSelectorWidget::setFreeSelectionAspectRatio()
00408 {
00409 m_forcedAspectRatio=0;
00410 }
00411
00412 void KPixmapRegionSelectorWidget::setMaximumWidgetSize(int width, int height)
00413 {
00414 m_maxWidth=width;
00415 m_maxHeight=height;
00416
00417 m_originalPixmap=m_unzoomedPixmap;
00418 if (m_selectedRegion == m_originalPixmap.rect()) m_selectedRegion=QRect();
00419
00420
00421
00422
00423 if ( !m_originalPixmap.isNull() &&
00424 ( m_originalPixmap.width() > m_maxWidth ||
00425 m_originalPixmap.height() > m_maxHeight ) )
00426 {
00427
00428 QImage image=m_originalPixmap.convertToImage();
00429 m_originalPixmap.convertFromImage( image.smoothScale( width, height, QImage::ScaleMin ) );
00430 double oldZoomFactor = m_zoomFactor;
00431 m_zoomFactor=m_originalPixmap.width()/(double)m_unzoomedPixmap.width();
00432
00433 if (m_selectedRegion.isValid())
00434 {
00435 m_selectedRegion=
00436 QRect((int)(m_selectedRegion.x()*m_zoomFactor/oldZoomFactor),
00437 (int)(m_selectedRegion.y()*m_zoomFactor/oldZoomFactor),
00438 (int)(m_selectedRegion.width()*m_zoomFactor/oldZoomFactor),
00439 (int)(m_selectedRegion.height()*m_zoomFactor/oldZoomFactor) );
00440 }
00441 }
00442
00443 if (!m_selectedRegion.isValid()) m_selectedRegion = m_originalPixmap.rect();
00444
00445 m_linedPixmap=QPixmap();
00446 updatePixmap();
00447 resize(m_label->width(), m_label->height());
00448 }
00449
00450 #include "kpixmapregionselectorwidget.moc"