1 /* This file is part of the KDE libraries
2 Copyright (C) 2004 Antonio Larrosa <larrosa@kde.org
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.
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.
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., 59 Temple Place - Suite 330,
17 Boston, MA 02111-1307, USA.
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.
26 #include "kpixmapregionselectorwidget.h"
31 #include <kimageeffect.h>
34 #include <kpopupmenu.h>
38 #include <qapplication.h>
42 KPixmapRegionSelectorWidget::KPixmapRegionSelectorWidget( QWidget
*parent
,
43 const char *name
) : QWidget( parent
, name
)
45 QHBoxLayout
* hboxLayout
=new QHBoxLayout( this );
47 hboxLayout
->addStretch();
48 QVBoxLayout
* vboxLayout
=new QVBoxLayout( hboxLayout
);
50 vboxLayout
->addStretch();
51 m_label
= new QLabel(this, "pixmapHolder");
52 m_label
->setBackgroundMode( Qt::NoBackground
);
53 m_label
->installEventFilter( this );
55 vboxLayout
->addWidget(m_label
);
56 vboxLayout
->addStretch();
58 hboxLayout
->addStretch();
60 m_forcedAspectRatio
=0;
65 KPixmapRegionSelectorWidget::~KPixmapRegionSelectorWidget()
69 void KPixmapRegionSelectorWidget::setPixmap( const QPixmap
&pixmap
)
71 Q_ASSERT(!pixmap
.isNull()); //This class isn't designed to deal with null pixmaps.
72 m_originalPixmap
= pixmap
;
73 m_unzoomedPixmap
= pixmap
;
74 m_label
->setPixmap( pixmap
);
78 void KPixmapRegionSelectorWidget::resetSelection()
80 m_selectedRegion
= m_originalPixmap
.rect();
84 QRect
KPixmapRegionSelectorWidget::selectedRegion() const
86 return m_selectedRegion
;
89 void KPixmapRegionSelectorWidget::setSelectedRegion(const QRect
&rect
)
91 if (!rect
.isValid()) resetSelection();
94 m_selectedRegion
=rect
;
97 QRect r
=unzoomedSelectedRegion();
101 void KPixmapRegionSelectorWidget::updatePixmap()
103 Q_ASSERT(!m_originalPixmap
.isNull()); if(m_originalPixmap
.isNull()) { m_label
->setPixmap(m_originalPixmap
); return; }
104 if (m_selectedRegion
.width()>m_originalPixmap
.width()) m_selectedRegion
.setWidth( m_originalPixmap
.width() );
105 if (m_selectedRegion
.height()>m_originalPixmap
.height()) m_selectedRegion
.setHeight( m_originalPixmap
.height() );
108 if (m_linedPixmap
.isNull())
110 m_linedPixmap
= m_originalPixmap
;
112 painter
.begin(&m_linedPixmap
);
113 painter
.setRasterOp( Qt::XorROP
);
114 painter
.fillRect(0,0,m_linedPixmap
.width(), m_linedPixmap
.height(),
115 QBrush( QColor(255,255,255), Qt::BDiagPattern
) );
118 QImage image
=m_linedPixmap
.convertToImage();
119 image
=KImageEffect::fade(image
, 0.4, QColor(0,0,0));
120 m_linedPixmap
.convertFromImage(image
);
123 QPixmap pixmap
= m_linedPixmap
;
125 painter
.begin(&pixmap
);
126 painter
.drawPixmap( m_selectedRegion
.topLeft(),
127 m_originalPixmap
, m_selectedRegion
);
129 painter
.setPen( QColor(255,255,255) );
130 painter
.setRasterOp( Qt::XorROP
);
132 painter
.drawRect( m_selectedRegion
);
136 m_label
->setPixmap(pixmap
);
139 KPopupMenu
*KPixmapRegionSelectorWidget::createPopupMenu()
141 KPopupMenu
*popup
=new KPopupMenu(this, "PixmapRegionSelectorPopup");
142 popup
->insertTitle(i18n("Image Operations"));
144 KAction
*action
= new KAction(i18n("&Rotate Clockwise"), "rotate_cw",
145 0, this, SLOT(rotateClockwise()),
146 popup
, "rotateclockwise");
149 action
= new KAction(i18n("Rotate &Counterclockwise"), "rotate_ccw",
150 0, this, SLOT(rotateCounterclockwise()),
151 popup
, "rotatecounterclockwise");
155 I wonder if it would be appropiate to have here an "Open with..." option to
156 edit the image (antlarr)
161 void KPixmapRegionSelectorWidget::rotate(KImageEffect::RotateDirection direction
)
163 int w
=m_originalPixmap
.width();
164 int h
=m_originalPixmap
.height();
165 QImage img
=m_unzoomedPixmap
.convertToImage();
166 img
= KImageEffect::rotate(img
, direction
);
167 m_unzoomedPixmap
.convertFromImage(img
);
169 img
=m_originalPixmap
.convertToImage();
170 img
= KImageEffect::rotate(img
, direction
);
171 m_originalPixmap
.convertFromImage(img
);
173 m_linedPixmap
=QPixmap();
175 if (m_forcedAspectRatio
>0 && m_forcedAspectRatio
!=1)
181 case ( KImageEffect::Rotate90
):
183 int x
=h
-m_selectedRegion
.y()-m_selectedRegion
.height();
184 int y
=m_selectedRegion
.x();
185 m_selectedRegion
.setRect(x
, y
, m_selectedRegion
.height(), m_selectedRegion
.width() );
188 case ( KImageEffect::Rotate270
):
190 int x
=m_selectedRegion
.y();
191 int y
=w
-m_selectedRegion
.x()-m_selectedRegion
.width();
192 m_selectedRegion
.setRect(x
, y
, m_selectedRegion
.height(), m_selectedRegion
.width() );
195 default: resetSelection();
200 void KPixmapRegionSelectorWidget::rotateClockwise()
202 rotate(KImageEffect::Rotate90
);
205 void KPixmapRegionSelectorWidget::rotateCounterclockwise()
207 rotate(KImageEffect::Rotate270
);
212 bool KPixmapRegionSelectorWidget::eventFilter(QObject
*obj
, QEvent
*ev
)
214 if ( ev
->type() == QEvent::MouseButtonPress
)
216 QMouseEvent
*mev
= (QMouseEvent
*)(ev
);
217 //kdDebug() << QString("click at %1,%2").arg( mev->x() ).arg( mev->y() ) << endl;
219 if ( mev
->button() == RightButton
)
221 KPopupMenu
*popup
= createPopupMenu( );
222 popup
->exec( mev
->globalPos() );
228 if ( m_selectedRegion
.contains( mev
->pos() )
229 && m_selectedRegion
!=m_originalPixmap
.rect() )
232 cursor
=QCursor(Qt::SizeAllCursor
);
237 cursor
=QCursor(Qt::CrossCursor
);
239 QApplication::setOverrideCursor(cursor
);
241 m_tempFirstClick
=mev
->pos();
246 if ( ev
->type() == QEvent::MouseMove
)
248 QMouseEvent
*mev
= (QMouseEvent
*)(ev
);
250 //kdDebug() << QString("move to %1,%2").arg( mev->x() ).arg( mev->y() ) << endl;
252 if ( m_state
== Resizing
)
255 calcSelectionRectangle( m_tempFirstClick
, mev
->pos() ) );
257 else if (m_state
== Moving
)
261 bool mouseOutside
=false;
264 m_selectedRegion
.moveBy(-m_selectedRegion
.x(),0);
267 else if ( mevx
> m_originalPixmap
.width() )
269 m_selectedRegion
.moveBy(m_originalPixmap
.width()-m_selectedRegion
.width()-m_selectedRegion
.x(),0);
274 m_selectedRegion
.moveBy(0,-m_selectedRegion
.y());
277 else if ( mevy
> m_originalPixmap
.height() )
279 m_selectedRegion
.moveBy(0,m_originalPixmap
.height()-m_selectedRegion
.height()-m_selectedRegion
.y());
282 if (mouseOutside
) { updatePixmap(); return TRUE
; };
284 m_selectedRegion
.moveBy( mev
->x()-m_tempFirstClick
.x(),
285 mev
->y()-m_tempFirstClick
.y() );
287 // Check that the region has not fallen outside the image
288 if (m_selectedRegion
.x() < 0)
289 m_selectedRegion
.moveBy(-m_selectedRegion
.x(),0);
290 else if (m_selectedRegion
.right() > m_originalPixmap
.width())
291 m_selectedRegion
.moveBy(-(m_selectedRegion
.right()-m_originalPixmap
.width()),0);
293 if (m_selectedRegion
.y() < 0)
294 m_selectedRegion
.moveBy(0,-m_selectedRegion
.y());
295 else if (m_selectedRegion
.bottom() > m_originalPixmap
.height())
296 m_selectedRegion
.moveBy(0,-(m_selectedRegion
.bottom()-m_originalPixmap
.height()));
298 m_tempFirstClick
=mev
->pos();
304 if ( ev
->type() == QEvent::MouseButtonRelease
)
306 QMouseEvent
*mev
= (QMouseEvent
*)(ev
);
308 if ( m_state
== Resizing
&& mev
->pos() == m_tempFirstClick
)
312 QApplication::restoreOverrideCursor();
317 QWidget::eventFilter(obj
, ev
);
321 QRect
KPixmapRegionSelectorWidget::calcSelectionRectangle( const QPoint
& startPoint
, const QPoint
& _endPoint
)
323 QPoint endPoint
= _endPoint
;
324 if ( endPoint
.x() < 0 ) endPoint
.setX(0);
325 else if ( endPoint
.x() > m_originalPixmap
.width() ) endPoint
.setX(m_originalPixmap
.width());
326 if ( endPoint
.y() < 0 ) endPoint
.setY(0);
327 else if ( endPoint
.y() > m_originalPixmap
.height() ) endPoint
.setY(m_originalPixmap
.height());
328 int w
=abs(startPoint
.x()-endPoint
.x());
329 int h
=abs(startPoint
.y()-endPoint
.y());
331 if (m_forcedAspectRatio
>0)
333 double aspectRatio
=w
/double(h
);
335 if (aspectRatio
>m_forcedAspectRatio
)
336 h
=(int)(w
/m_forcedAspectRatio
);
338 w
=(int)(h
*m_forcedAspectRatio
);
342 if ( startPoint
.x() < endPoint
.x() )
346 if ( startPoint
.y() < endPoint
.y() )
355 h
=(int)(w
/m_forcedAspectRatio
);
357 if ( startPoint
.y() > endPoint
.y() )
360 else if (x
+w
>m_originalPixmap
.width())
362 w
=m_originalPixmap
.width()-x
;
363 h
=(int)(w
/m_forcedAspectRatio
);
365 if ( startPoint
.y() > endPoint
.y() )
372 w
=(int)(h
*m_forcedAspectRatio
);
374 if ( startPoint
.x() > endPoint
.x() )
377 else if (y
+h
>m_originalPixmap
.height())
379 h
=m_originalPixmap
.height()-y
;
380 w
=(int)(h
*m_forcedAspectRatio
);
382 if ( startPoint
.x() > endPoint
.x() )
386 return QRect(x
,y
,w
,h
);
389 QRect
KPixmapRegionSelectorWidget::unzoomedSelectedRegion() const
391 return QRect((int)(m_selectedRegion
.x()/m_zoomFactor
),
392 (int)(m_selectedRegion
.y()/m_zoomFactor
),
393 (int)(m_selectedRegion
.width()/m_zoomFactor
),
394 (int)(m_selectedRegion
.height()/m_zoomFactor
));
397 QImage
KPixmapRegionSelectorWidget::selectedImage() const
399 QImage origImage
=m_unzoomedPixmap
.convertToImage();
400 return origImage
.copy(unzoomedSelectedRegion());
403 void KPixmapRegionSelectorWidget::setSelectionAspectRatio(int width
, int height
)
405 m_forcedAspectRatio
=width
/double(height
);
408 void KPixmapRegionSelectorWidget::setFreeSelectionAspectRatio()
410 m_forcedAspectRatio
=0;
413 void KPixmapRegionSelectorWidget::setMaximumWidgetSize(int width
, int height
)
418 m_originalPixmap
=m_unzoomedPixmap
;
419 if (m_selectedRegion
== m_originalPixmap
.rect()) m_selectedRegion
=QRect();
421 // kdDebug() << QString(" original Pixmap :") << m_originalPixmap.rect() << endl;
422 // kdDebug() << QString(" unzoomed Pixmap : %1 x %2 ").arg(m_unzoomedPixmap.width()).arg(m_unzoomedPixmap.height()) << endl;
424 if ( !m_originalPixmap
.isNull() &&
425 ( m_originalPixmap
.width() > m_maxWidth
||
426 m_originalPixmap
.height() > m_maxHeight
) )
428 /* We have to resize the pixmap to get it complete on the screen */
429 QImage image
=m_originalPixmap
.convertToImage();
430 m_originalPixmap
.convertFromImage( image
.smoothScale( width
, height
, QImage::ScaleMin
) );
431 //m_originalPixmap.convertFromImage( KImageEffect::sample( image, width, height ) );
432 double oldZoomFactor
= m_zoomFactor
;
433 m_zoomFactor
=m_originalPixmap
.width()/(double)m_unzoomedPixmap
.width();
435 if (m_selectedRegion
.isValid())
438 QRect((int)(m_selectedRegion
.x()*m_zoomFactor
/oldZoomFactor
),
439 (int)(m_selectedRegion
.y()*m_zoomFactor
/oldZoomFactor
),
440 (int)(m_selectedRegion
.width()*m_zoomFactor
/oldZoomFactor
),
441 (int)(m_selectedRegion
.height()*m_zoomFactor
/oldZoomFactor
) );
445 if (!m_selectedRegion
.isValid()) m_selectedRegion
= m_originalPixmap
.rect();
447 m_linedPixmap
=QPixmap();
449 resize(m_label
->width(), m_label
->height());
452 #include "kpixmapregionselectorwidget.moc"