• Skip to content
  • Skip to link menu
  • KDE API Reference
  • kdelibs-4.8.5 API Reference
  • KDE Home
  • Contact Us
 

KDEUI

  • kdeui
  • widgets
kpixmapregionselectorwidget.cpp
Go to the documentation of this file.
1 /* This file is part of the KDE libraries
2  Copyright (C) 2004 Antonio Larrosa <larrosa@kde.org
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public License
15  along with this library; see the file COPYING.LIB. If not, write to
16  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  Boston, MA 02110-1301, USA.
18 */
19 
20 /* NOTE: There are two copies of this .h and the .cpp file, with subtle differences.
21  * One copy is in kdelibs/kdeui, and the other copy is in kdepim/libkdepim
22  * This is because kdepim has to remain backwards compatible. Any changes
23  * to either file should be made to the other.
24  */
25 
26 #include "kpixmapregionselectorwidget.h"
27 #include <QtGui/QPainter>
28 #include <QtGui/QColor>
29 #include <QtGui/QImage>
30 #include <QLabel>
31 #include <QtGui/QLayout>
32 #include <QRubberBand>
33 #include <kdebug.h>
34 #include <kicon.h>
35 #include <klocale.h>
36 #include <kmenu.h>
37 #include <kaction.h>
38 #include <stdlib.h>
39 #include <QtGui/QCursor>
40 #include <QtGui/QApplication>
41 #include <QMouseEvent>
42 #include "kactioncollection.h"
43 
44 class KPixmapRegionSelectorWidget::Private
45 {
46 public:
47  Private(KPixmapRegionSelectorWidget *q): q(q) {}
48 
49  KPixmapRegionSelectorWidget *q;
50 
55  void updatePixmap();
56 
57  QRect calcSelectionRectangle( const QPoint &startPoint, const QPoint & endPoint );
58 
59  enum CursorState { None=0, Resizing, Moving };
60  CursorState m_state;
61 
62  QPixmap m_unzoomedPixmap;
63  QPixmap m_originalPixmap;
64  QPixmap m_linedPixmap;
65  QRect m_selectedRegion;
66  QLabel *m_label;
67 
68  QPoint m_tempFirstClick;
69  double m_forcedAspectRatio;
70 
71  int m_maxWidth, m_maxHeight;
72  double m_zoomFactor;
73 
74  QRubberBand *m_rubberBand;
75 };
76 
77 KPixmapRegionSelectorWidget::KPixmapRegionSelectorWidget( QWidget *parent)
78  : QWidget( parent ), d(new Private(this))
79 {
80  QHBoxLayout * hboxLayout=new QHBoxLayout( this );
81 
82  hboxLayout->addStretch();
83  QVBoxLayout * vboxLayout=new QVBoxLayout();
84  hboxLayout->addItem(vboxLayout);
85 
86  vboxLayout->addStretch();
87  d->m_label = new QLabel(this);
88  d->m_label->setAttribute(Qt::WA_NoSystemBackground,true);//setBackgroundMode( Qt::NoBackground );
89  d->m_label->installEventFilter( this );
90 
91  vboxLayout->addWidget(d->m_label);
92  vboxLayout->addStretch();
93 
94  hboxLayout->addStretch();
95 
96  d->m_forcedAspectRatio=0;
97 
98  d->m_zoomFactor=1.0;
99  d->m_rubberBand = new QRubberBand(QRubberBand::Rectangle, d->m_label);
100  d->m_rubberBand->hide();
101 }
102 
103 KPixmapRegionSelectorWidget::~KPixmapRegionSelectorWidget()
104 {
105  delete d;
106 }
107 
108 QPixmap KPixmapRegionSelectorWidget::pixmap() const
109 {
110  return d->m_unzoomedPixmap;
111 }
112 
113 void KPixmapRegionSelectorWidget::setPixmap( const QPixmap &pixmap )
114 {
115  Q_ASSERT(!pixmap.isNull()); //This class isn't designed to deal with null pixmaps.
116  d->m_originalPixmap = pixmap;
117  d->m_unzoomedPixmap = pixmap;
118  d->m_label->setPixmap( pixmap );
119  resetSelection();
120 }
121 
122 void KPixmapRegionSelectorWidget::resetSelection()
123 {
124  d->m_selectedRegion = d->m_originalPixmap.rect();
125  d->m_rubberBand->hide();
126  d->updatePixmap();
127 }
128 
129 QRect KPixmapRegionSelectorWidget::selectedRegion() const
130 {
131  return d->m_selectedRegion;
132 }
133 
134 void KPixmapRegionSelectorWidget::setSelectedRegion(const QRect &rect)
135 {
136  if (!rect.isValid()) resetSelection();
137  else
138  {
139  d->m_selectedRegion=rect;
140  d->updatePixmap();
141 
142  QRect r=unzoomedSelectedRegion();
143  }
144 }
145 
146 void KPixmapRegionSelectorWidget::Private::updatePixmap()
147 {
148  Q_ASSERT(!m_originalPixmap.isNull());
149  if (m_originalPixmap.isNull()) { m_label->setPixmap(m_originalPixmap); return; }
150  if (m_selectedRegion.width()>m_originalPixmap.width()) m_selectedRegion.setWidth( m_originalPixmap.width() );
151  if (m_selectedRegion.height()>m_originalPixmap.height()) m_selectedRegion.setHeight( m_originalPixmap.height() );
152 
153  QPainter painter;
154  if (m_linedPixmap.isNull())
155  {
156  m_linedPixmap = m_originalPixmap;
157  QPainter p(&m_linedPixmap);
158  p.setCompositionMode(QPainter::CompositionMode_SourceAtop);
159  p.fillRect(m_linedPixmap.rect(), QColor(0, 0, 0, 100));
160  }
161 
162  QPixmap pixmap = m_linedPixmap;
163  painter.begin(&pixmap);
164  painter.drawPixmap( m_selectedRegion.topLeft(),
165  m_originalPixmap, m_selectedRegion );
166 
167 
168  painter.end();
169 
170  m_label->setPixmap(pixmap);
171 
172  qApp->sendPostedEvents(0,QEvent::LayoutRequest);
173 
174  if (m_selectedRegion == m_originalPixmap.rect())//d->m_label->rect()) //### CHECK!
175  m_rubberBand->hide();
176  else
177  {
178  m_rubberBand->setGeometry(QRect(m_selectedRegion.topLeft(),
179  m_selectedRegion.size()));
180 
181 /* m_rubberBand->setGeometry(QRect(m_label -> mapToGlobal(m_selectedRegion.topLeft()),
182  m_selectedRegion.size()));
183 */
184  if (m_state!=None) m_rubberBand->show();
185  }
186 
187 }
188 
189 
190 KMenu *KPixmapRegionSelectorWidget::createPopupMenu()
191 {
192  KMenu *popup=new KMenu(this );
193  KActionCollection *actions=new KActionCollection(popup);
194  popup->setObjectName( "PixmapRegionSelectorPopup");
195  popup->addTitle(i18n("Image Operations"));
196 
197  QAction *action = actions->addAction("rotateclockwise");
198  action->setText(i18n("&Rotate Clockwise"));
199  action->setIcon( KIcon( "object-rotate-right" ) );
200  connect( action, SIGNAL(triggered(bool)), this, SLOT(rotateClockwise()) );
201 
202  popup->addAction(action);
203 
204  action = actions->addAction("rotatecounterclockwise");
205  action->setText(i18n("Rotate &Counterclockwise"));
206  action->setIcon( KIcon( "object-rotate-left" ) );
207  connect( action, SIGNAL(triggered(bool)), this, SLOT(rotateCounterclockwise()) );
208 
209  popup->addAction(action);
210 
211 /*
212  I wonder if it would be appropriate to have here an "Open with..." option to
213  edit the image (antlarr)
214 */
215  return popup;
216 }
217 
218 void KPixmapRegionSelectorWidget::rotate(RotateDirection direction)
219 {
220  int w=d->m_originalPixmap.width();
221  int h=d->m_originalPixmap.height();
222  QImage img=d->m_unzoomedPixmap.toImage();
223  if(direction == Rotate90)
224  img = img.transformed(QTransform().rotate(90.0));
225  else if(direction == Rotate180)
226  img = img.transformed(QTransform().rotate(180.0));
227  else
228  img = img.transformed(QTransform().rotate(270.0));
229 
230  d->m_unzoomedPixmap=QPixmap::fromImage(img);
231 
232  img=d->m_originalPixmap.toImage();
233  if(direction == Rotate90)
234  img = img.transformed(QTransform().rotate(90.0));
235  else if(direction == Rotate180)
236  img = img.transformed(QTransform().rotate(180.0));
237  else
238  img = img.transformed(QTransform().rotate(270.0));
239 
240  d->m_originalPixmap=QPixmap::fromImage(img);
241 
242  d->m_linedPixmap=QPixmap();
243 
244  if (d->m_forcedAspectRatio>0 && d->m_forcedAspectRatio!=1)
245  resetSelection();
246  else
247  {
248  switch (direction)
249  {
250  case ( Rotate90 ):
251  {
252  int x=h-d->m_selectedRegion.y()-d->m_selectedRegion.height();
253  int y=d->m_selectedRegion.x();
254  d->m_selectedRegion.setRect(x, y, d->m_selectedRegion.height(), d->m_selectedRegion.width() );
255  d->updatePixmap();
256 // qApp->sendPostedEvents(0,QEvent::LayoutRequest);
257 // updatePixmap();
258 
259  } break;
260  case ( Rotate270 ):
261  {
262  int x=d->m_selectedRegion.y();
263  int y=w-d->m_selectedRegion.x()-d->m_selectedRegion.width();
264  d->m_selectedRegion.setRect(x, y, d->m_selectedRegion.height(), d->m_selectedRegion.width() );
265  d->updatePixmap();
266 // qApp->sendPostedEvents(0,QEvent::LayoutRequest);
267 // updatePixmap();
268  } break;
269  default: resetSelection();
270  }
271  }
272 
273  emit pixmapRotated();
274 }
275 
276 void KPixmapRegionSelectorWidget::rotateClockwise()
277 {
278  rotate(Rotate90);
279 }
280 
281 void KPixmapRegionSelectorWidget::rotateCounterclockwise()
282 {
283  rotate(Rotate270);
284 }
285 
286 bool KPixmapRegionSelectorWidget::eventFilter(QObject *obj, QEvent *ev)
287 {
288  if ( ev->type() == QEvent::MouseButtonPress )
289  {
290  QMouseEvent *mev= (QMouseEvent *)(ev);
291  //kDebug() << QString("click at %1,%2").arg( mev->x() ).arg( mev->y() );
292 
293  if ( mev->button() == Qt::RightButton )
294  {
295  KMenu *popup = createPopupMenu( );
296  popup->exec( mev->globalPos() );
297  delete popup;
298  return true;
299  }
300 
301  QCursor cursor;
302 
303  if ( d->m_selectedRegion.contains( mev->pos() )
304  && d->m_selectedRegion!=d->m_originalPixmap.rect() )
305  {
306  d->m_state=Private::Moving;
307  cursor.setShape( Qt::SizeAllCursor );
308  d->m_rubberBand->show();
309  }
310  else
311  {
312  d->m_state=Private::Resizing;
313  cursor.setShape( Qt::CrossCursor );
314  }
315  QApplication::setOverrideCursor(cursor);
316 
317  d->m_tempFirstClick=mev->pos();
318 
319 
320  return true;
321  }
322 
323  if ( ev->type() == QEvent::MouseMove )
324  {
325  QMouseEvent *mev= (QMouseEvent *)(ev);
326 
327  //kDebug() << QString("move to %1,%2").arg( mev->x() ).arg( mev->y() );
328 
329  if ( d->m_state == Private::Resizing )
330  {
331  setSelectedRegion (
332  d->calcSelectionRectangle( d->m_tempFirstClick, mev->pos() ) );
333  }
334  else if (d->m_state == Private::Moving )
335  {
336  int mevx = mev->x();
337  int mevy = mev->y();
338  bool mouseOutside=false;
339  if ( mevx < 0 )
340  {
341  d->m_selectedRegion.translate(-d->m_selectedRegion.x(),0);
342  mouseOutside=true;
343  }
344  else if ( mevx > d->m_originalPixmap.width() )
345  {
346  d->m_selectedRegion.translate(d->m_originalPixmap.width()-d->m_selectedRegion.width()-d->m_selectedRegion.x(),0);
347  mouseOutside=true;
348  }
349  if ( mevy < 0 )
350  {
351  d->m_selectedRegion.translate(0,-d->m_selectedRegion.y());
352  mouseOutside=true;
353  }
354  else if ( mevy > d->m_originalPixmap.height() )
355  {
356  d->m_selectedRegion.translate(0,d->m_originalPixmap.height()-d->m_selectedRegion.height()-d->m_selectedRegion.y());
357  mouseOutside=true;
358  }
359  if (mouseOutside) { d->updatePixmap(); return true; };
360 
361  d->m_selectedRegion.translate( mev->x()-d->m_tempFirstClick.x(),
362  mev->y()-d->m_tempFirstClick.y() );
363 
364  // Check that the region has not fallen outside the image
365  if (d->m_selectedRegion.x() < 0)
366  d->m_selectedRegion.translate(-d->m_selectedRegion.x(),0);
367  else if (d->m_selectedRegion.right() > d->m_originalPixmap.width())
368  d->m_selectedRegion.translate(-(d->m_selectedRegion.right()-d->m_originalPixmap.width()),0);
369 
370  if (d->m_selectedRegion.y() < 0)
371  d->m_selectedRegion.translate(0,-d->m_selectedRegion.y());
372  else if (d->m_selectedRegion.bottom() > d->m_originalPixmap.height())
373  d->m_selectedRegion.translate(0,-(d->m_selectedRegion.bottom()-d->m_originalPixmap.height()));
374 
375  d->m_tempFirstClick=mev->pos();
376  d->updatePixmap();
377  }
378  return true;
379  }
380 
381  if ( ev->type() == QEvent::MouseButtonRelease )
382  {
383  QMouseEvent *mev= (QMouseEvent *)(ev);
384 
385  if ( d->m_state == Private::Resizing && mev->pos() == d->m_tempFirstClick)
386  resetSelection();
387 
388  d->m_state=Private::None;
389  QApplication::restoreOverrideCursor();
390  d->m_rubberBand->hide();
391  return true;
392  }
393 
394  QWidget::eventFilter(obj, ev);
395  return false;
396 }
397 
398 QRect KPixmapRegionSelectorWidget::Private::calcSelectionRectangle( const QPoint & startPoint, const QPoint & _endPoint )
399 {
400  QPoint endPoint = _endPoint;
401  if ( endPoint.x() < 0 ) endPoint.setX(0);
402  else if ( endPoint.x() > m_originalPixmap.width() ) endPoint.setX(m_originalPixmap.width());
403  if ( endPoint.y() < 0 ) endPoint.setY(0);
404  else if ( endPoint.y() > m_originalPixmap.height() ) endPoint.setY(m_originalPixmap.height());
405  int w=abs(startPoint.x()-endPoint.x());
406  int h=abs(startPoint.y()-endPoint.y());
407 
408  if (m_forcedAspectRatio>0)
409  {
410  double aspectRatio=w/double(h);
411 
412  if (aspectRatio>m_forcedAspectRatio)
413  h=(int)(w/m_forcedAspectRatio);
414  else
415  w=(int)(h*m_forcedAspectRatio);
416  }
417 
418  int x,y;
419  if ( startPoint.x() < endPoint.x() )
420  x=startPoint.x();
421  else
422  x=startPoint.x()-w;
423  if ( startPoint.y() < endPoint.y() )
424  y=startPoint.y();
425  else
426  y=startPoint.y()-h;
427 
428  if (x<0)
429  {
430  w+=x;
431  x=0;
432  h=(int)(w/m_forcedAspectRatio);
433 
434  if ( startPoint.y() > endPoint.y() )
435  y=startPoint.y()-h;
436  }
437  else if (x+w>m_originalPixmap.width())
438  {
439  w=m_originalPixmap.width()-x;
440  h=(int)(w/m_forcedAspectRatio);
441 
442  if ( startPoint.y() > endPoint.y() )
443  y=startPoint.y()-h;
444  }
445  if (y<0)
446  {
447  h+=y;
448  y=0;
449  w=(int)(h*m_forcedAspectRatio);
450 
451  if ( startPoint.x() > endPoint.x() )
452  x=startPoint.x()-w;
453  }
454  else if (y+h>m_originalPixmap.height())
455  {
456  h=m_originalPixmap.height()-y;
457  w=(int)(h*m_forcedAspectRatio);
458 
459  if ( startPoint.x() > endPoint.x() )
460  x=startPoint.x()-w;
461  }
462 
463  return QRect(x,y,w,h);
464 }
465 
466 QRect KPixmapRegionSelectorWidget::unzoomedSelectedRegion() const
467 {
468  return QRect((int)(d->m_selectedRegion.x()/d->m_zoomFactor),
469  (int)(d->m_selectedRegion.y()/d->m_zoomFactor),
470  (int)(d->m_selectedRegion.width()/d->m_zoomFactor),
471  (int)(d->m_selectedRegion.height()/d->m_zoomFactor));
472 }
473 
474 QImage KPixmapRegionSelectorWidget::selectedImage() const
475 {
476  QImage origImage=d->m_unzoomedPixmap.toImage();
477  return origImage.copy(unzoomedSelectedRegion());
478 }
479 
480 void KPixmapRegionSelectorWidget::setSelectionAspectRatio(int width, int height)
481 {
482  d->m_forcedAspectRatio=width/double(height);
483 }
484 
485 void KPixmapRegionSelectorWidget::setFreeSelectionAspectRatio()
486 {
487  d->m_forcedAspectRatio=0;
488 }
489 
490 void KPixmapRegionSelectorWidget::setMaximumWidgetSize(int width, int height)
491 {
492  d->m_maxWidth=width;
493  d->m_maxHeight=height;
494 
495  if (d->m_selectedRegion == d->m_originalPixmap.rect()) d->m_selectedRegion=QRect();
496  d->m_originalPixmap=d->m_unzoomedPixmap;
497 
498 // kDebug() << QString(" original Pixmap :") << d->m_originalPixmap.rect();
499 // kDebug() << QString(" unzoomed Pixmap : %1 x %2 ").arg(d->m_unzoomedPixmap.width()).arg(d->m_unzoomedPixmap.height());
500 
501  if ( !d->m_originalPixmap.isNull() &&
502  ( d->m_originalPixmap.width() > d->m_maxWidth ||
503  d->m_originalPixmap.height() > d->m_maxHeight ) )
504  {
505  /* We have to resize the pixmap to get it complete on the screen */
506  QImage image=d->m_originalPixmap.toImage();
507  d->m_originalPixmap=QPixmap::fromImage( image.scaled( width, height, Qt::KeepAspectRatio,Qt::SmoothTransformation ) );
508  double oldZoomFactor = d->m_zoomFactor;
509  d->m_zoomFactor=d->m_originalPixmap.width()/(double)d->m_unzoomedPixmap.width();
510 
511  if (d->m_selectedRegion.isValid())
512  {
513  d->m_selectedRegion=
514  QRect((int)(d->m_selectedRegion.x()*d->m_zoomFactor/oldZoomFactor),
515  (int)(d->m_selectedRegion.y()*d->m_zoomFactor/oldZoomFactor),
516  (int)(d->m_selectedRegion.width()*d->m_zoomFactor/oldZoomFactor),
517  (int)(d->m_selectedRegion.height()*d->m_zoomFactor/oldZoomFactor) );
518  }
519  }
520 
521  if (!d->m_selectedRegion.isValid()) d->m_selectedRegion = d->m_originalPixmap.rect();
522 
523  d->m_linedPixmap=QPixmap();
524  d->updatePixmap();
525  resize(d->m_label->width(), d->m_label->height());
526 }
527 
528 #include "kpixmapregionselectorwidget.moc"
This file is part of the KDE documentation.
Documentation copyright © 1996-2013 The KDE developers.
Generated on Thu Feb 21 2013 11:06:50 by doxygen 1.8.1 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

KDEUI

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

kdelibs-4.8.5 API Reference

Skip menu "kdelibs-4.8.5 API Reference"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal