kpixmapregionselectorwidget.cpp
/* This file is part of the KDE libraries
Copyright (C) 2004 Antonio Larrosa <larrosa@kde.org
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
/* NOTE: There are two copies of this .h and the .cpp file, with subtle differences.
* One copy is in kdelibs/kdeui, and the other copy is in kdepim/libkdepim
* This is because kdepim has to remain backwards compatible. Any changes
* to either file should be made to the other.
*/
#include "kpixmapregionselectorwidget.h"
#include <qpainter.h>
#include <qcolor.h>
#include <qimage.h>
#include <qlayout.h>
#include <kimageeffect.h>
#include <kdebug.h>
#include <klocale.h>
#include <kpopupmenu.h>
#include <kaction.h>
#include <stdlib.h>
#include <qcursor.h>
#include <qapplication.h>
KPixmapRegionSelectorWidget::KPixmapRegionSelectorWidget( QWidget *parent,
const char *name) : QWidget( parent, name)
{
QHBoxLayout * hboxLayout=new QHBoxLayout( this );
hboxLayout->addStretch();
QVBoxLayout * vboxLayout=new QVBoxLayout( hboxLayout );
vboxLayout->addStretch();
m_label = new QLabel(this, "pixmapHolder");
m_label->setBackgroundMode( Qt::NoBackground );
m_label->installEventFilter( this );
vboxLayout->addWidget(m_label);
vboxLayout->addStretch();
hboxLayout->addStretch();
m_forcedAspectRatio=0;
m_zoomFactor=1.0;
}
KPixmapRegionSelectorWidget::~KPixmapRegionSelectorWidget()
{
}
void KPixmapRegionSelectorWidget::setPixmap( const QPixmap &pixmap )
{
Q_ASSERT(!pixmap.isNull()); //This class isn't designed to deal with null pixmaps.
m_originalPixmap = pixmap;
m_unzoomedPixmap = pixmap;
m_label->setPixmap( pixmap );
resetSelection();
}
void KPixmapRegionSelectorWidget::resetSelection()
{
m_selectedRegion = m_originalPixmap.rect();
updatePixmap();
}
QRect KPixmapRegionSelectorWidget::selectedRegion() const
{
return m_selectedRegion;
}
void KPixmapRegionSelectorWidget::setSelectedRegion(const QRect &rect)
{
if (!rect.isValid()) resetSelection();
else
{
m_selectedRegion=rect;
updatePixmap();
QRect r=unzoomedSelectedRegion();
}
}
void KPixmapRegionSelectorWidget::updatePixmap()
{
Q_ASSERT(!m_originalPixmap.isNull()); if(m_originalPixmap.isNull()) { m_label->setPixmap(m_originalPixmap); return; }
if (m_selectedRegion.width()>m_originalPixmap.width()) m_selectedRegion.setWidth( m_originalPixmap.width() );
if (m_selectedRegion.height()>m_originalPixmap.height()) m_selectedRegion.setHeight( m_originalPixmap.height() );
QPainter painter;
if (m_linedPixmap.isNull())
{
m_linedPixmap = m_originalPixmap;
painter.begin(&m_linedPixmap);
painter.setRasterOp( Qt::XorROP );
painter.fillRect(0,0,m_linedPixmap.width(), m_linedPixmap.height(),
QBrush( QColor(255,255,255), Qt::BDiagPattern) );
painter.end();
QImage image=m_linedPixmap.convertToImage();
image=KImageEffect::fade(image, (float)0.4, QColor(0,0,0));
m_linedPixmap.convertFromImage(image);
}
QPixmap pixmap = m_linedPixmap;
painter.begin(&pixmap);
painter.drawPixmap( m_selectedRegion.topLeft(),
m_originalPixmap, m_selectedRegion );
painter.setPen( QColor(255,255,255) );
painter.setRasterOp( Qt::XorROP );
painter.drawRect( m_selectedRegion );
painter.end();
m_label->setPixmap(pixmap);
}
KPopupMenu *KPixmapRegionSelectorWidget::createPopupMenu()
{
KPopupMenu *popup=new KPopupMenu(this, "PixmapRegionSelectorPopup");
popup->insertTitle(i18n("Image Operations"));
KAction *action = new KAction(i18n("&Rotate Clockwise"), "rotate_cw",
0, this, SLOT(rotateClockwise()),
popup, "rotateclockwise");
action->plug(popup);
action = new KAction(i18n("Rotate &Counterclockwise"), "rotate_ccw",
0, this, SLOT(rotateCounterclockwise()),
popup, "rotatecounterclockwise");
action->plug(popup);
/*
I wonder if it would be appropiate to have here an "Open with..." option to
edit the image (antlarr)
*/
return popup;
}
void KPixmapRegionSelectorWidget::rotate(KImageEffect::RotateDirection direction)
{
int w=m_originalPixmap.width();
int h=m_originalPixmap.height();
QImage img=m_unzoomedPixmap.convertToImage();
img= KImageEffect::rotate(img, direction);
m_unzoomedPixmap.convertFromImage(img);
img=m_originalPixmap.convertToImage();
img= KImageEffect::rotate(img, direction);
m_originalPixmap.convertFromImage(img);
m_linedPixmap=QPixmap();
if (m_forcedAspectRatio>0 && m_forcedAspectRatio!=1)
resetSelection();
else
{
switch (direction)
{
case ( KImageEffect::Rotate90 ):
{
int x=h-m_selectedRegion.y()-m_selectedRegion.height();
int y=m_selectedRegion.x();
m_selectedRegion.setRect(x, y, m_selectedRegion.height(), m_selectedRegion.width() );
updatePixmap();
} break;
case ( KImageEffect::Rotate270 ):
{
int x=m_selectedRegion.y();
int y=w-m_selectedRegion.x()-m_selectedRegion.width();
m_selectedRegion.setRect(x, y, m_selectedRegion.height(), m_selectedRegion.width() );
updatePixmap();
} break;
default: resetSelection();
}
}
}
void KPixmapRegionSelectorWidget::rotateClockwise()
{
rotate(KImageEffect::Rotate90);
}
void KPixmapRegionSelectorWidget::rotateCounterclockwise()
{
rotate(KImageEffect::Rotate270);
}
bool KPixmapRegionSelectorWidget::eventFilter(QObject *obj, QEvent *ev)
{
if ( ev->type() == QEvent::MouseButtonPress )
{
QMouseEvent *mev= (QMouseEvent *)(ev);
//kdDebug() << QString("click at %1,%2").arg( mev->x() ).arg( mev->y() ) << endl;
if ( mev->button() == RightButton )
{
KPopupMenu *popup = createPopupMenu( );
popup->exec( mev->globalPos() );
delete popup;
return TRUE;
};
QCursor cursor;
if ( m_selectedRegion.contains( mev->pos() )
&& m_selectedRegion!=m_originalPixmap.rect() )
{
m_state=Moving;
cursor.setShape( Qt::SizeAllCursor );
}
else
{
m_state=Resizing;
cursor.setShape( Qt::CrossCursor );
}
QApplication::setOverrideCursor(cursor);
m_tempFirstClick=mev->pos();
return TRUE;
}
if ( ev->type() == QEvent::MouseMove )
{
QMouseEvent *mev= (QMouseEvent *)(ev);
//kdDebug() << QString("move to %1,%2").arg( mev->x() ).arg( mev->y() ) << endl;
if ( m_state == Resizing )
{
setSelectedRegion (
calcSelectionRectangle( m_tempFirstClick, mev->pos() ) );
}
else if (m_state == Moving )
{
int mevx = mev->x();
int mevy = mev->y();
bool mouseOutside=false;
if ( mevx < 0 )
{
m_selectedRegion.moveBy(-m_selectedRegion.x(),0);
mouseOutside=true;
}
else if ( mevx > m_originalPixmap.width() )
{
m_selectedRegion.moveBy(m_originalPixmap.width()-m_selectedRegion.width()-m_selectedRegion.x(),0);
mouseOutside=true;
}
if ( mevy < 0 )
{
m_selectedRegion.moveBy(0,-m_selectedRegion.y());
mouseOutside=true;
}
else if ( mevy > m_originalPixmap.height() )
{
m_selectedRegion.moveBy(0,m_originalPixmap.height()-m_selectedRegion.height()-m_selectedRegion.y());
mouseOutside=true;
}
if (mouseOutside) { updatePixmap(); return TRUE; };
m_selectedRegion.moveBy( mev->x()-m_tempFirstClick.x(),
mev->y()-m_tempFirstClick.y() );
// Check that the region has not fallen outside the image
if (m_selectedRegion.x() < 0)
m_selectedRegion.moveBy(-m_selectedRegion.x(),0);
else if (m_selectedRegion.right() > m_originalPixmap.width())
m_selectedRegion.moveBy(-(m_selectedRegion.right()-m_originalPixmap.width()),0);
if (m_selectedRegion.y() < 0)
m_selectedRegion.moveBy(0,-m_selectedRegion.y());
else if (m_selectedRegion.bottom() > m_originalPixmap.height())
m_selectedRegion.moveBy(0,-(m_selectedRegion.bottom()-m_originalPixmap.height()));
m_tempFirstClick=mev->pos();
updatePixmap();
}
return TRUE;
}
if ( ev->type() == QEvent::MouseButtonRelease )
{
QMouseEvent *mev= (QMouseEvent *)(ev);
if ( m_state == Resizing && mev->pos() == m_tempFirstClick)
resetSelection();
m_state=None;
QApplication::restoreOverrideCursor();
return TRUE;
}
QWidget::eventFilter(obj, ev);
return FALSE;
}
QRect KPixmapRegionSelectorWidget::calcSelectionRectangle( const QPoint & startPoint, const QPoint & _endPoint )
{
QPoint endPoint = _endPoint;
if ( endPoint.x() < 0 ) endPoint.setX(0);
else if ( endPoint.x() > m_originalPixmap.width() ) endPoint.setX(m_originalPixmap.width());
if ( endPoint.y() < 0 ) endPoint.setY(0);
else if ( endPoint.y() > m_originalPixmap.height() ) endPoint.setY(m_originalPixmap.height());
int w=abs(startPoint.x()-endPoint.x());
int h=abs(startPoint.y()-endPoint.y());
if (m_forcedAspectRatio>0)
{
double aspectRatio=w/double(h);
if (aspectRatio>m_forcedAspectRatio)
h=(int)(w/m_forcedAspectRatio);
else
w=(int)(h*m_forcedAspectRatio);
}
int x,y;
if ( startPoint.x() < endPoint.x() )
x=startPoint.x();
else
x=startPoint.x()-w;
if ( startPoint.y() < endPoint.y() )
y=startPoint.y();
else
y=startPoint.y()-h;
if (x<0)
{
w+=x;
x=0;
h=(int)(w/m_forcedAspectRatio);
if ( startPoint.y() > endPoint.y() )
y=startPoint.y()-h;
}
else if (x+w>m_originalPixmap.width())
{
w=m_originalPixmap.width()-x;
h=(int)(w/m_forcedAspectRatio);
if ( startPoint.y() > endPoint.y() )
y=startPoint.y()-h;
}
if (y<0)
{
h+=y;
y=0;
w=(int)(h*m_forcedAspectRatio);
if ( startPoint.x() > endPoint.x() )
x=startPoint.x()-w;
}
else if (y+h>m_originalPixmap.height())
{
h=m_originalPixmap.height()-y;
w=(int)(h*m_forcedAspectRatio);
if ( startPoint.x() > endPoint.x() )
x=startPoint.x()-w;
}
return QRect(x,y,w,h);
}
QRect KPixmapRegionSelectorWidget::unzoomedSelectedRegion() const
{
return QRect((int)(m_selectedRegion.x()/m_zoomFactor),
(int)(m_selectedRegion.y()/m_zoomFactor),
(int)(m_selectedRegion.width()/m_zoomFactor),
(int)(m_selectedRegion.height()/m_zoomFactor));
}
QImage KPixmapRegionSelectorWidget::selectedImage() const
{
QImage origImage=m_unzoomedPixmap.convertToImage();
return origImage.copy(unzoomedSelectedRegion());
}
void KPixmapRegionSelectorWidget::setSelectionAspectRatio(int width, int height)
{
m_forcedAspectRatio=width/double(height);
}
void KPixmapRegionSelectorWidget::setFreeSelectionAspectRatio()
{
m_forcedAspectRatio=0;
}
void KPixmapRegionSelectorWidget::setMaximumWidgetSize(int width, int height)
{
m_maxWidth=width;
m_maxHeight=height;
m_originalPixmap=m_unzoomedPixmap;
if (m_selectedRegion == m_originalPixmap.rect()) m_selectedRegion=QRect();
// kdDebug() << QString(" original Pixmap :") << m_originalPixmap.rect() << endl;
// kdDebug() << QString(" unzoomed Pixmap : %1 x %2 ").arg(m_unzoomedPixmap.width()).arg(m_unzoomedPixmap.height()) << endl;
if ( !m_originalPixmap.isNull() &&
( m_originalPixmap.width() > m_maxWidth ||
m_originalPixmap.height() > m_maxHeight ) )
{
/* We have to resize the pixmap to get it complete on the screen */
QImage image=m_originalPixmap.convertToImage();
m_originalPixmap.convertFromImage( image.smoothScale( width, height, QImage::ScaleMin ) );
double oldZoomFactor = m_zoomFactor;
m_zoomFactor=m_originalPixmap.width()/(double)m_unzoomedPixmap.width();
if (m_selectedRegion.isValid())
{
m_selectedRegion=
QRect((int)(m_selectedRegion.x()*m_zoomFactor/oldZoomFactor),
(int)(m_selectedRegion.y()*m_zoomFactor/oldZoomFactor),
(int)(m_selectedRegion.width()*m_zoomFactor/oldZoomFactor),
(int)(m_selectedRegion.height()*m_zoomFactor/oldZoomFactor) );
}
}
if (!m_selectedRegion.isValid()) m_selectedRegion = m_originalPixmap.rect();
m_linedPixmap=QPixmap();
updatePixmap();
resize(m_label->width(), m_label->height());
}
#include "kpixmapregionselectorwidget.moc"
KPixmapRegionSelectorWidget::selectedRegion
QRect selectedRegion() const
Returns the selected region ( in zoomed pixmap coordinates )
Definition: kpixmapregionselectorwidget.cpp:82
KPixmapRegionSelectorWidget::KPixmapRegionSelectorWidget
KPixmapRegionSelectorWidget(QWidget *parent=0L, const char *name=0L)
Constructor for a KPixmapRegionSelectorWidget.
Definition: kpixmapregionselectorwidget.cpp:40
KPixmapRegionSelectorWidget::~KPixmapRegionSelectorWidget
~KPixmapRegionSelectorWidget()
Destructor for a KPixmapRegionSelectorWidget.
Definition: kpixmapregionselectorwidget.cpp:63
KPixmapRegionSelectorWidget::setFreeSelectionAspectRatio
void setFreeSelectionAspectRatio()
Allows the user to do a selection which has any aspect ratio.
Definition: kpixmapregionselectorwidget.cpp:407
KImageEffect::rotate
static QImage rotate(QImage &src, RotateDirection r)
klocale.h
KPixmapRegionSelectorWidget::rotateClockwise
void rotateClockwise()
Rotates the current image 90º clockwise.
Definition: kpixmapregionselectorwidget.cpp:199
KPixmapRegionSelectorWidget::unzoomedSelectedRegion
QRect unzoomedSelectedRegion() const
Returns the selected region ( in unzoomed, original pixmap coordinates )
Definition: kpixmapregionselectorwidget.cpp:388
KPixmapRegionSelectorWidget::setPixmap
void setPixmap(const QPixmap &pixmap)
Sets the pixmap which will be shown for the user to select a region from.
Definition: kpixmapregionselectorwidget.cpp:67
KImageEffect::RotateDirection
RotateDirection
KPixmapRegionSelectorWidget::setSelectedRegion
void setSelectedRegion(const QRect &rect)
Sets the selected region to be rect (in zoomed pixmap coordinates)
Definition: kpixmapregionselectorwidget.cpp:87
KPixmapRegionSelectorWidget::resetSelection
void resetSelection()
Resets the selection to use the whole image.
Definition: kpixmapregionselectorwidget.cpp:76
KImageEffect::fade
static QImage & fade(QImage &image, float val, const QColor &color)
KAction
Class to encapsulate user-driven action or event.
Definition: kaction.h:202
KImageEffect::Rotate90
KPixmapRegionSelectorWidget::setMaximumWidgetSize
void setMaximumWidgetSize(int width, int height)
Sets the maximum size for the widget.
Definition: kpixmapregionselectorwidget.cpp:412
KPixmapRegionSelectorWidget::rotateCounterclockwise
void rotateCounterclockwise()
Rotates the current image 90º counterclockwise.
Definition: kpixmapregionselectorwidget.cpp:204
KPixmapRegionSelectorWidget::selectedImage
QImage selectedImage() const
Definition: kpixmapregionselectorwidget.cpp:396
KImageEffect::Rotate270
KAction::plug
virtual int plug(QWidget *widget, int index=-1)
"Plug" or insert this action into a given widget.
Definition: kaction.cpp:618
KPixmapRegionSelectorWidget::setSelectionAspectRatio
void setSelectionAspectRatio(int width, int height)
Sets the aspect ration that the selected subimage should have.
Definition: kpixmapregionselectorwidget.cpp:402
KPixmapRegionSelectorWidget::pixmap
QPixmap pixmap() const
Definition: kpixmapregionselectorwidget.h:69
KPixmapRegionSelectorWidget::rotate
void rotate(KImageEffect::RotateDirection direction)
Rotates the image as specified by the direction parameter, also tries to rotate the selected region s...
Definition: kpixmapregionselectorwidget.cpp:160
KPixmapRegionSelectorWidget::createPopupMenu
virtual KPopupMenu * createPopupMenu()
Creates a KPopupMenu with the menu that appears when clicking with the right button on the label...
Definition: kpixmapregionselectorwidget.cpp:138

KDE Home | KDE Accessibility Home | Description of Access Keys