• Skip to content
  • Skip to link menu
KDE 4.2 API Reference
  • KDE API Reference
  • kdelibs
  • Sitemap
  • Contact Us
 

KDEUI

kpixmapregionselectorwidget.cpp

Go to the documentation of this file.
00001 /* This file is part of the KDE libraries
00002     Copyright (C) 2004 Antonio Larrosa <larrosa@kde.org
00003 
00004     This library is free software; you can redistribute it and/or
00005     modify it under the terms of the GNU Library General Public
00006     License as published by the Free Software Foundation; either
00007     version 2 of the License, or (at your option) any later version.
00008 
00009     This library is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012     Library General Public License for more details.
00013 
00014     You should have received a copy of the GNU Library General Public License
00015     along with this library; see the file COPYING.LIB.  If not, write to
00016     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017     Boston, MA 02110-1301, USA.
00018 */
00019 
00020 /* NOTE: There are two copies of this .h and the .cpp file, with subtle differences.
00021  * One copy is in kdelibs/kdeui, and the other copy is in kdepim/libkdepim
00022  * This is because kdepim has to remain backwards compatible.  Any changes
00023  * to either file should be made to the other.
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);//setBackgroundMode( Qt::NoBackground );
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()); //This class isn't designed to deal with null pixmaps.
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())//d->m_label->rect()) //### CHECK!
00175         m_rubberBand->hide();
00176    else
00177    {
00178         m_rubberBand->setGeometry(QRect(m_selectedRegion.topLeft(),
00179                                         m_selectedRegion.size()));
00180 
00181 /*        m_rubberBand->setGeometry(QRect(m_label -> mapToGlobal(m_selectedRegion.topLeft()),
00182                                         m_selectedRegion.size()));
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    I wonder if it would be appropriate to have here an "Open with..." option to
00213    edit the image (antlarr)
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 //              qApp->sendPostedEvents(0,QEvent::LayoutRequest);
00257 //              updatePixmap();
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 //              qApp->sendPostedEvents(0,QEvent::LayoutRequest);
00267 //              updatePixmap();
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       //kDebug() << QString("click at  %1,%2").arg( mev->x() ).arg( mev->y() );
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       //kDebug() << QString("move to  %1,%2").arg( mev->x() ).arg( mev->y() );
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          // Check that the region has not fallen outside the image
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 //   kDebug() << QString(" original Pixmap :") << d->m_originalPixmap.rect();
00497 //   kDebug() << QString(" unzoomed Pixmap : %1 x %2 ").arg(d->m_unzoomedPixmap.width()).arg(d->m_unzoomedPixmap.height());
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          /* We have to resize the pixmap to get it complete on the screen */
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"

KDEUI

Skip menu "KDEUI"
  • Main Page
  • Modules
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • Kross
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.5.7
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal