/* This file is part of libtdepim. Copyright (C) 2004 Antonio Larrosa #include #include #include #include #include #include #include #include #include #include #include using namespace KPIM; KPixmapRegionSelectorWidget::KPixmapRegionSelectorWidget( TQWidget *parent, const char *name) : TQWidget( parent, name) { TQHBoxLayout * hboxLayout=new TQHBoxLayout( this ); hboxLayout->addStretch(); TQVBoxLayout * vboxLayout=new TQVBoxLayout( hboxLayout ); vboxLayout->addStretch(); m_label = new TQLabel(this, "pixmapHolder"); m_label->setBackgroundMode( TQt::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 TQPixmap &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(); } TQRect KPixmapRegionSelectorWidget::selectedRegion() const { return m_selectedRegion; } void KPixmapRegionSelectorWidget::setSelectedRegion(const TQRect &rect) { if (!rect.isValid()) resetSelection(); else { m_selectedRegion=rect; updatePixmap(); TQRect 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() ); TQPainter painter; if (m_linedPixmap.isNull()) { m_linedPixmap = m_originalPixmap; painter.begin(&m_linedPixmap); painter.setRasterOp( TQt::XorROP ); painter.fillRect(0,0,m_linedPixmap.width(), m_linedPixmap.height(), TQBrush( TQColor(255,255,255), TQt::BDiagPattern) ); painter.end(); TQImage image=m_linedPixmap.convertToImage(); image=KImageEffect::fade(image, 0.4, TQColor(0,0,0)); m_linedPixmap.convertFromImage(image); } TQPixmap pixmap = m_linedPixmap; painter.begin(&pixmap); painter.drawPixmap( m_selectedRegion.topLeft(), m_originalPixmap, m_selectedRegion ); painter.setPen( TQColor(255,255,255) ); painter.setRasterOp( TQt::XorROP ); painter.drawRect( m_selectedRegion ); painter.end(); m_label->setPixmap(pixmap); } TDEPopupMenu *KPixmapRegionSelectorWidget::createPopupMenu() { TDEPopupMenu *popup=new TDEPopupMenu(this, "PixmapRegionSelectorPopup"); popup->insertTitle(i18n("Image Operations")); TDEAction *action = new TDEAction(i18n("&Rotate Clockwise"), "object-rotate-right", 0, TQT_TQOBJECT(this), TQT_SLOT(rotateClockwise()), TQT_TQOBJECT(popup), "rotateclockwise"); action->plug(popup); action = new TDEAction(i18n("Rotate &Counterclockwise"), "object-rotate-left", 0, TQT_TQOBJECT(this), TQT_SLOT(rotateCounterclockwise()), TQT_TQOBJECT(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(); TQImage 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=TQPixmap(); 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(TQObject *obj, TQEvent *ev) { if ( ev->type() == TQEvent::MouseButtonPress ) { TQMouseEvent *mev= (TQMouseEvent *)(ev); //kdDebug() << TQString("click at %1,%2").arg( mev->x() ).arg( mev->y() ) << endl; if ( mev->button() == Qt::RightButton ) { TDEPopupMenu *popup = createPopupMenu( ); popup->exec( mev->globalPos() ); delete popup; return TRUE; }; TQCursor cursor; if ( m_selectedRegion.contains( mev->pos() ) && m_selectedRegion!=m_originalPixmap.rect() ) { m_state=Moving; cursor=TQCursor(TQt::SizeAllCursor); } else { m_state=Resizing; cursor=TQCursor(TQt::CrossCursor); } TQApplication::setOverrideCursor(cursor); m_tempFirstClick=mev->pos(); return TRUE; } if ( ev->type() == TQEvent::MouseMove ) { TQMouseEvent *mev= (TQMouseEvent *)(ev); //kdDebug() << TQString("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() == TQEvent::MouseButtonRelease ) { TQMouseEvent *mev= (TQMouseEvent *)(ev); if ( m_state == Resizing && mev->pos() == m_tempFirstClick) resetSelection(); m_state=None; TQApplication::restoreOverrideCursor(); return TRUE; } TQWidget::eventFilter(obj, ev); return FALSE; } TQRect KPixmapRegionSelectorWidget::calcSelectionRectangle( const TQPoint & startPoint, const TQPoint & _endPoint ) { TQPoint 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 TQRect(x,y,w,h); } TQRect KPixmapRegionSelectorWidget::unzoomedSelectedRegion() const { return TQRect((int)(m_selectedRegion.x()/m_zoomFactor), (int)(m_selectedRegion.y()/m_zoomFactor), (int)(m_selectedRegion.width()/m_zoomFactor), (int)(m_selectedRegion.height()/m_zoomFactor)); } TQImage KPixmapRegionSelectorWidget::selectedImage() const { TQImage 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=TQRect(); // kdDebug() << TQString(" original Pixmap :") << m_originalPixmap.rect() << endl; // kdDebug() << TQString(" 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 */ TQImage image=m_originalPixmap.convertToImage(); m_originalPixmap.convertFromImage( image.smoothScale( width, height, TQ_ScaleMin ) ); //m_originalPixmap.convertFromImage( KImageEffect::sample( image, width, height ) ); double oldZoomFactor = m_zoomFactor; m_zoomFactor=m_originalPixmap.width()/(double)m_unzoomedPixmap.width(); if (m_selectedRegion.isValid()) { m_selectedRegion= TQRect((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=TQPixmap(); updatePixmap(); resize(m_label->width(), m_label->height()); } #include "kpixmapregionselectorwidget.moc"