|
|
|
/* ============================================================
|
|
|
|
*
|
|
|
|
* This file is a part of digiKam project
|
|
|
|
* http://www.digikam.org
|
|
|
|
*
|
|
|
|
* Date : 2004-08-22
|
|
|
|
* Description : a generic widget to display a panel to choose
|
|
|
|
* a rectangular image area.
|
|
|
|
*
|
|
|
|
* Copyright (C) 2004-2008 by Gilles Caulier <caulier dot gilles at gmail dot com>
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it
|
|
|
|
* and/or modify it under the terms of the GNU General
|
|
|
|
* Public License as published by the Free Software Foundation;
|
|
|
|
* either version 2, or (at your option)
|
|
|
|
* any later version.
|
|
|
|
*
|
|
|
|
* This program 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 General Public License for more details.
|
|
|
|
*
|
|
|
|
* ============================================================ */
|
|
|
|
|
|
|
|
// C++ includes.
|
|
|
|
|
|
|
|
#include <cmath>
|
|
|
|
|
|
|
|
// TQt includes.
|
|
|
|
|
|
|
|
#include <tqpainter.h>
|
|
|
|
#include <tqpixmap.h>
|
|
|
|
#include <tqpen.h>
|
|
|
|
#include <tqtimer.h>
|
|
|
|
|
|
|
|
// KDE includes.
|
|
|
|
|
|
|
|
#include <kcursor.h>
|
|
|
|
|
|
|
|
// Local includes.
|
|
|
|
|
|
|
|
#include "ddebug.h"
|
|
|
|
#include "paniconwidget.h"
|
|
|
|
#include "paniconwidget.moc"
|
|
|
|
|
|
|
|
namespace Digikam
|
|
|
|
{
|
|
|
|
|
|
|
|
class PanIconWidgetPriv
|
|
|
|
{
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
PanIconWidgetPriv()
|
|
|
|
{
|
|
|
|
moveSelection = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool moveSelection;
|
|
|
|
|
|
|
|
int xpos;
|
|
|
|
int ypos;
|
|
|
|
|
|
|
|
TQRect regionSelection; // Original size image selection.
|
|
|
|
|
|
|
|
TQImage image;
|
|
|
|
};
|
|
|
|
|
|
|
|
PanIconWidget::PanIconWidget(TQWidget *parent, WFlags flags)
|
|
|
|
: TQWidget(parent, 0, flags)
|
|
|
|
{
|
|
|
|
d = new PanIconWidgetPriv;
|
|
|
|
m_flicker = false;
|
|
|
|
m_timerID = 0;
|
|
|
|
m_pixmap = 0;
|
|
|
|
m_zoomFactor = 1.0;
|
|
|
|
|
|
|
|
setBackgroundMode(TQt::NoBackground);
|
|
|
|
setMouseTracking(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
PanIconWidget::~PanIconWidget()
|
|
|
|
{
|
|
|
|
if (m_timerID) killTimer(m_timerID);
|
|
|
|
|
|
|
|
if (m_pixmap) delete m_pixmap;
|
|
|
|
|
|
|
|
delete d;
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::setImage(int previewWidth, int previewHeight, const TQImage& image)
|
|
|
|
{
|
|
|
|
TQSize sz(image.width(), image.height());
|
|
|
|
sz.scale(previewWidth, previewHeight, TQSize::ScaleMin);
|
|
|
|
m_pixmap = new TQPixmap(previewWidth, previewHeight);
|
|
|
|
m_width = sz.width();
|
|
|
|
m_height = sz.height();
|
|
|
|
d->image = image.smoothScale(sz.width(), sz.height());
|
|
|
|
m_orgWidth = image.width();
|
|
|
|
m_orgHeight = image.height();
|
|
|
|
m_zoomedOrgWidth = image.width();
|
|
|
|
m_zoomedOrgHeight = image.height();
|
|
|
|
setFixedSize(m_width, m_height);
|
|
|
|
|
|
|
|
m_rect = TQRect(width()/2-m_width/2, height()/2-m_height/2, m_width, m_height);
|
|
|
|
updatePixmap();
|
|
|
|
m_timerID = startTimer(800);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::setImage(int previewWidth, int previewHeight, const DImg& image)
|
|
|
|
{
|
|
|
|
DImg img(image);
|
|
|
|
setImage(previewWidth, previewHeight, img.copyTQImage());
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::slotZoomFactorChanged(double factor)
|
|
|
|
{
|
|
|
|
if (m_zoomFactor == factor) return;
|
|
|
|
m_zoomFactor = factor;
|
|
|
|
m_zoomedOrgWidth = (int)(m_orgWidth * factor);
|
|
|
|
m_zoomedOrgHeight = (int)(m_orgHeight * factor);
|
|
|
|
updatePixmap();
|
|
|
|
repaint(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::setRegionSelection(const TQRect& regionSelection)
|
|
|
|
{
|
|
|
|
d->regionSelection = regionSelection;
|
|
|
|
m_localRegionSelection.setX( m_rect.x() + (int)((float)d->regionSelection.x() *
|
|
|
|
((float)m_width / (float)m_zoomedOrgWidth)) );
|
|
|
|
|
|
|
|
m_localRegionSelection.setY( m_rect.y() + (int)((float)d->regionSelection.y() *
|
|
|
|
((float)m_height / (float)m_zoomedOrgHeight)) );
|
|
|
|
|
|
|
|
m_localRegionSelection.setWidth( (int)((float)d->regionSelection.width() *
|
|
|
|
((float)m_width / (float)m_zoomedOrgWidth)) );
|
|
|
|
|
|
|
|
m_localRegionSelection.setHeight( (int)((float)d->regionSelection.height() *
|
|
|
|
((float)m_height / (float)m_zoomedOrgHeight)) );
|
|
|
|
|
|
|
|
updatePixmap();
|
|
|
|
repaint(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
TQRect PanIconWidget::getRegionSelection()
|
|
|
|
{
|
|
|
|
return (d->regionSelection);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::setCursorToLocalRegionSelectionCenter()
|
|
|
|
{
|
|
|
|
TQCursor::setPos(mapToGlobal(m_localRegionSelection.center()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::setCenterSelection()
|
|
|
|
{
|
|
|
|
setRegionSelection(TQRect(
|
|
|
|
(int)(((float)m_zoomedOrgWidth / 2.0) - ((float)d->regionSelection.width() / 2.0)),
|
|
|
|
(int)(((float)m_zoomedOrgHeight / 2.0) - ((float)d->regionSelection.height() / 2.0)),
|
|
|
|
d->regionSelection.width(),
|
|
|
|
d->regionSelection.height()));
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::regionSelectionMoved(bool targetDone)
|
|
|
|
{
|
|
|
|
if (targetDone)
|
|
|
|
{
|
|
|
|
updatePixmap();
|
|
|
|
repaint(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
int x = (int)lround( ((float)m_localRegionSelection.x() - (float)m_rect.x() ) *
|
|
|
|
((float)m_zoomedOrgWidth / (float)m_width) );
|
|
|
|
|
|
|
|
int y = (int)lround( ((float)m_localRegionSelection.y() - (float)m_rect.y() ) *
|
|
|
|
((float)m_zoomedOrgHeight / (float)m_height) );
|
|
|
|
|
|
|
|
int w = (int)lround( (float)m_localRegionSelection.width() *
|
|
|
|
((float)m_zoomedOrgWidth / (float)m_width) );
|
|
|
|
|
|
|
|
int h = (int)lround( (float)m_localRegionSelection.height() *
|
|
|
|
((float)m_zoomedOrgHeight / (float)m_height) );
|
|
|
|
|
|
|
|
d->regionSelection.setX(x);
|
|
|
|
d->regionSelection.setY(y);
|
|
|
|
d->regionSelection.setWidth(w);
|
|
|
|
d->regionSelection.setHeight(h);
|
|
|
|
|
|
|
|
emit signalSelectionMoved( d->regionSelection, targetDone );
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::updatePixmap()
|
|
|
|
{
|
|
|
|
// Drawing background and image.
|
|
|
|
m_pixmap->fill(colorGroup().background());
|
|
|
|
bitBlt(m_pixmap, m_rect.x(), m_rect.y(), &d->image, 0, 0);
|
|
|
|
|
|
|
|
TQPainter p(m_pixmap);
|
|
|
|
|
|
|
|
// Drawing selection border
|
|
|
|
|
|
|
|
if (m_flicker) p.setPen(TQPen(TQt::white, 1, TQt::SolidLine));
|
|
|
|
else p.setPen(TQPen(TQt::red, 1, TQt::SolidLine));
|
|
|
|
|
|
|
|
p.drawRect(m_localRegionSelection.x(),
|
|
|
|
m_localRegionSelection.y(),
|
|
|
|
m_localRegionSelection.width(),
|
|
|
|
m_localRegionSelection.height());
|
|
|
|
|
|
|
|
if (m_flicker) p.setPen(TQPen(TQt::red, 1, TQt::DotLine));
|
|
|
|
else p.setPen(TQPen(TQt::white, 1, TQt::DotLine));
|
|
|
|
|
|
|
|
p.drawRect(m_localRegionSelection.x(),
|
|
|
|
m_localRegionSelection.y(),
|
|
|
|
m_localRegionSelection.width(),
|
|
|
|
m_localRegionSelection.height());
|
|
|
|
|
|
|
|
p.end();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::paintEvent(TQPaintEvent*)
|
|
|
|
{
|
|
|
|
bitBlt(this, 0, 0, m_pixmap);
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::setMouseFocus()
|
|
|
|
{
|
|
|
|
raise();
|
|
|
|
d->xpos = m_localRegionSelection.center().x();
|
|
|
|
d->ypos = m_localRegionSelection.center().y();
|
|
|
|
d->moveSelection = true;
|
|
|
|
setCursor( KCursor::sizeAllCursor() );
|
|
|
|
emit signalSelectionTakeFocus();
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::hideEvent(TQHideEvent *e)
|
|
|
|
{
|
|
|
|
TQWidget::hideEvent(e);
|
|
|
|
|
|
|
|
if ( d->moveSelection )
|
|
|
|
{
|
|
|
|
d->moveSelection = false;
|
|
|
|
setCursor( KCursor::arrowCursor() );
|
|
|
|
emit signalHiden();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::mousePressEvent ( TQMouseEvent * e )
|
|
|
|
{
|
|
|
|
if ( (e->button() == Qt::LeftButton || e->button() == Qt::MidButton) &&
|
|
|
|
m_localRegionSelection.contains( e->x(), e->y() ) )
|
|
|
|
{
|
|
|
|
d->xpos = e->x();
|
|
|
|
d->ypos = e->y();
|
|
|
|
d->moveSelection = true;
|
|
|
|
setCursor( KCursor::sizeAllCursor() );
|
|
|
|
emit signalSelectionTakeFocus();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::mouseMoveEvent ( TQMouseEvent * e )
|
|
|
|
{
|
|
|
|
if ( d->moveSelection &&
|
|
|
|
(e->state() == Qt::LeftButton || e->state() == Qt::MidButton) )
|
|
|
|
{
|
|
|
|
int newxpos = e->x();
|
|
|
|
int newypos = e->y();
|
|
|
|
|
|
|
|
m_localRegionSelection.moveBy (newxpos - d->xpos, newypos - d->ypos);
|
|
|
|
|
|
|
|
d->xpos = newxpos;
|
|
|
|
d->ypos = newypos;
|
|
|
|
|
|
|
|
// Perform normalization of selection area.
|
|
|
|
|
|
|
|
if (m_localRegionSelection.left() < m_rect.left())
|
|
|
|
m_localRegionSelection.moveLeft(m_rect.left());
|
|
|
|
|
|
|
|
if (m_localRegionSelection.top() < m_rect.top())
|
|
|
|
m_localRegionSelection.moveTop(m_rect.top());
|
|
|
|
|
|
|
|
if (m_localRegionSelection.right() > m_rect.right())
|
|
|
|
m_localRegionSelection.moveRight(m_rect.right());
|
|
|
|
|
|
|
|
if (m_localRegionSelection.bottom() > m_rect.bottom())
|
|
|
|
m_localRegionSelection.moveBottom(m_rect.bottom());
|
|
|
|
|
|
|
|
updatePixmap();
|
|
|
|
repaint(false);
|
|
|
|
regionSelectionMoved(false);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( m_localRegionSelection.contains( e->x(), e->y() ) )
|
|
|
|
setCursor( KCursor::handCursor() );
|
|
|
|
else
|
|
|
|
setCursor( KCursor::arrowCursor() );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::mouseReleaseEvent ( TQMouseEvent * )
|
|
|
|
{
|
|
|
|
if ( d->moveSelection )
|
|
|
|
{
|
|
|
|
d->moveSelection = false;
|
|
|
|
setCursor( KCursor::arrowCursor() );
|
|
|
|
regionSelectionMoved(true);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void PanIconWidget::timerEvent(TQTimerEvent * e)
|
|
|
|
{
|
|
|
|
if (e->timerId() == m_timerID)
|
|
|
|
{
|
|
|
|
m_flicker = !m_flicker;
|
|
|
|
updatePixmap();
|
|
|
|
repaint(false);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
TQWidget::timerEvent(e);
|
|
|
|
}
|
|
|
|
|
|
|
|
} // NameSpace Digikam
|