/****************************************************************************
** ImageObject class
**
** Created: Tue Feb 02 22:06:51 2004
**      by: Varol Okan using Kate
**
** This class is the encapsulation of the ImageObject.
**
** AN ImageObject is a visible object in a DVD Menu.
**
****************************************************************************/
#include <qpushbutton.h>
#include <qpopupmenu.h>
#include <qfileinfo.h>
#include <qlistview.h>
#include <qlineedit.h>
#include <qpainter.h>
#include <qwmatrix.h>
#include <qpixmap.h>
#include <qimage.h>
#include <qdom.h>

#include "xml_dvd.h"
#include "menuobject.h"
#include "frameobject.h"
#include "imageobject.h"
#include "dialogmovie.h"
#include "messagebox.h"
#include "dialogmatrix.h"
#include "dialoggeometry.h"
#include "dialoganimation.h"
#include "structuretoolbar.h"

ImageObject::ImageObject (QWidget *pParent)
	: MenuObject (pParent)
{
	m_qsObjectType = QString (IMAGE_OBJECT);
}

ImageObject::~ImageObject ()
{
}

void ImageObject::setPixmap(QPixmap &thePixmap)
{
	// Note: the Pixmap could be rotated, thus the bounding Rect might
	// be of different size than the width or height of the Pixmap.
	m_pixmap = thePixmap;
}

void ImageObject::setFile (QString fileName)
{
	QString qsExtractionPath;
	QFileInfo fileInfo(fileName);
	m_qsFileName = fileInfo.fileName();
	setName(m_qsFileName);
	qsExtractionPath = fileInfo.baseName ();
	setExtractionPath(qsExtractionPath);
	m_qsFileName = fileName;
//	m_pixmap = QPixmap (fileName);
}

void ImageObject::setZoom (float fZoom)
{
  // For the purpose of this class the Zoom is alreaduy incorporated into m_pixmap ...
  m_imageManipulator.fZoom = fZoom;
}

void ImageObject::setManipulator(ImageManipulator &theOther)
{
  m_imageManipulator = theOther;
}

void ImageObject::setModifiers ( Modifiers &theOther )
{
  Modifiers *pModifier = (Modifiers *)&m_imageManipulator;
  *pModifier = theOther;
}

ImageManipulator &ImageObject::manipulator()
{
  return m_imageManipulator;
}

Modifiers *ImageObject::modifiers()
{
  // Return the base class only ...
  // Note: this is needed to use the same MatrixDialog for text and images.
  return (Modifiers *) &m_imageManipulator;
}

QString &ImageObject::fileName()
{
	return m_qsFileName;
}

QPixmap &ImageObject::pixmap ()
{
	return m_pixmap;
}

float ImageObject::zoom()
{
	return m_imageManipulator.fZoom;
}

void ImageObject::drawContents (QPainter *painter)
{
  // printf ( "%s::%s::%d me<%p> shadow=<%p>\n", __FILE__, __FUNCTION__, __LINE__, this, m_pShadow );
	QWMatrix theMatrix;
	// Here we calculate the center point of gravity (rotation)
	QPoint centerPos;
	centerPos.setX (rect().x() + (int)((float)rect().width () / 2.0));
	centerPos.setY (rect().y() + (int)((float)rect().height() / 2.0));
	// Here we define the cenetered rect.
	QRect theRect ((int)-(rect().width()/ 2.0), (int)-(rect().height()/2.0), rect().width(), rect().height());

	QPen thePen (QColor (255,0,0), 2, Qt::DashDotLine);
	painter->setPen(thePen);

	// From the Qt documentation ...
	// This transformation engine is a three-step pipeline
	// The first step uses the world transformation matrix.
	// The second step uses the window.
	// The third step uses the viewport.

	// First we translate to the appropriate location,
	theMatrix.translate ( (double)centerPos.x ( ), (double)centerPos.y ( ) );

	//. then we apply the other modifications ...
	theMatrix.scale  ( modifiers ( )->fScaleX, modifiers ( )->fScaleY );
	theMatrix.shear  ( manipulator( ).fShearX, manipulator( ).fShearY );
	theMatrix.rotate ( manipulator( ).fRotate );

	// Here we get the rect that encompasses the button for this object.
	m_boundingRect = theMatrix.mapRect(theRect);

	if (m_bDrawRect)
	  drawActiveFrame ( painter );

	painter->setWorldMatrix(theMatrix);

	// Here we re-set the world matrix and translate the newly drawn ... thing ...
	if ( isActive () )
	  painter->drawRect(theRect);
	
	theMatrix.reset();
	painter->setWorldMatrix(theMatrix);
	
	// check if we have a complete transparency, in which case we don't even need to bother...
	if (manipulator().fTransparency == 1.0)
		return;

	if (!m_bDrawRect)	{
                if ( m_pShadow )
	             m_pShadow->drawContents ( painter );

		int t, x, y;
		QRgb thePixel;
		int iSourceHeight = pixmap().height();
		int iSourceWidth  = pixmap().width ();
		int iSourceStartX = 0;
		int iSourceStartY = 0;
		int iTargetStartX = painter->viewport().x() + m_boundingRect.x();
		int iTargetStartY = painter->viewport().y() + m_boundingRect.y();
		// Use the fast method whenever possible
		if (	(manipulator().fRotate       == 0.0) && 
			(manipulator().fShearX       == 0.0) && 
			(manipulator().fShearY       == 0.0) &&
			(manipulator().fTransparency == 0.0) && 
			(manipulator().listColorKeys.count() < 1) )
			bitBlt (painter->device(), iTargetStartX, iTargetStartY, &pixmap(), iSourceStartX, iSourceStartY, iSourceWidth, iSourceHeight, Qt::CopyROP, true);
		// Okay if we can not use bitBlt we have to go through the exact calculations ...
		else	{
			// First we need to create a Pixmap which holds the Target pixels
			QImage theImage = pixmap().convertToImage();
			QColor sourceColor, targetColor, theColor;
			QRgb sourcePixel;
			QImage sourceImg;
			float fTargetTrans, fSourceTrans;
			fTargetTrans = 1.0 - manipulator().fTransparency;
			fSourceTrans = manipulator().fTransparency;
			if (fTargetTrans != 0.0)	{
				QPixmap sourcePix (iSourceWidth, iSourceHeight);
				bitBlt (&sourcePix, 0, 0, painter->device(), iTargetStartX, iTargetStartY, iSourceWidth, iSourceHeight, Qt::CopyROP, true);
				// To get Pixel information we need a QImage however ...
				sourceImg = sourcePix.convertToImage();
				// Now we can get the original Pixel information ...
//				Note: This ought to be done in the updatePixmap () - function
//					- Also there we leave all info untouched which is (0,0,0)
//					- Also when we move AND when fTransparency != 0.0 then we need to do updatePixmap everytime.
			}			
			// Note that this function is actually using the viewport - transformation provided by Qt. The previous bitBlt's
			// did paint directly onto the device, thus we had to manually add the viewport coords. Now we have this info already
			// in the painter and thus we can substract them here.
			iTargetStartX -= painter->viewport().x();
			iTargetStartY -= painter->viewport().y();
			
			// Next we create the min/max Color keys, to check if we ought to filter the pixel out or not
			QValueList<QColor *>listColorKeyMin;
			QValueList<QColor *>listColorKeyMax;
			QColor *pColorMin, *pColorMax;
			if (manipulator().listColorKeys.count() > 0)	{
				int iDelta, iRed, iGreen, iBlue;
				for (t=0;t<(int)manipulator().listColorKeys.count();t++)	{
					iDelta = (int)(manipulator().listColorKeys[t]->fDeltaColor * 255.0);
					theColor = QColor (manipulator().listColorKeys[t]->theColor);
					iRed = theColor.red() - iDelta; iGreen = theColor.green() - iDelta; iBlue = theColor.blue() - iDelta;
					iRed = (iRed < 0) ? 0 : iRed; iGreen = (iGreen < 0) ? 0 : iGreen; iBlue = (iBlue < 0) ? 0 : iBlue;
					pColorMin = new QColor (iRed, iGreen, iBlue);
					iRed = theColor.red() + iDelta; iGreen = theColor.green() + iDelta; iBlue = theColor.blue() + iDelta;
					iRed = (iRed > 255) ? 255 : iRed; iGreen = (iGreen > 255) ? 255 : iGreen; iBlue = (iBlue > 255) ? 255 : iBlue;
					pColorMax = new QColor (iRed, iGreen, iBlue);

					listColorKeyMin.append (pColorMin);
					listColorKeyMax.append (pColorMax);
				}
			}
			for (y=0; y < iSourceHeight; y++)	{
				for (x=0; x < iSourceWidth; x++)	{
					thePixel = theImage.pixel(x+iSourceStartX, y+iSourceStartY);
					thePixel &= 0x00ffffff;			// filter out the transparency part of the color (not used in Qt 3.x)
					if (thePixel != 0x000000)	{	// And check if this is a pixel we need to handle ...
						// If there is a transparency part, or some color we need to filter out, 
						// then  we need to go through this slow loop.
						if ( (fTargetTrans != 0.0) || (manipulator().listColorKeys.count ()) )	{ 
							sourcePixel = sourceImg.pixel(x, y);	// calculate the mix of background and foreground.
							sourceColor = QColor (sourcePixel);
							targetColor = QColor ( thePixel );
							if (filterColorKey ( &targetColor, &listColorKeyMin, &listColorKeyMax ))
								theColor = sourceColor;
							else
								theColor = QColor (
									(int)(fSourceTrans * sourceColor.red()   + (int)(fTargetTrans * targetColor.red())),
									(int)(fSourceTrans * sourceColor.green() + (int)(fTargetTrans * targetColor.green())),
									(int)(fSourceTrans * sourceColor.blue()  + (int)(fTargetTrans * targetColor.blue()))
								); 
							painter->setPen ( theColor );
						}
						else	// No transparency is slightly easier ...
							painter->setPen ( QColor ( thePixel ) );
						painter->drawPoint(x+iTargetStartX, y+iTargetStartY);
					}
				}
			}
			if (manipulator().listColorKeys.count() > 0)	{
				for (t=0;t<(int)manipulator().listColorKeys.count();t++)	{
					delete listColorKeyMin[t];
					delete listColorKeyMax[t];
				}
			}
		}
	}
	// Phew ... This funtion has grown over time ...
}

void ImageObject::drawContents (QPainter *pPainter, int iRenderFrameNumber, int)
{
  // Next is to set the AnimationAttributes
  for (uint t=0; t<m_listAnimationAttributes.count ( ); t++)
    m_listAnimationAttributes[t]->setValue (iRenderFrameNumber);

  // And then we ought to refresh the pixmap ...
  if ( m_listAnimationAttributes.count ( ) > 0 ) {
    updatePixmap ( );
    updateShadow ( );
  }
  // before we can go ahead and draw the contents with the newly set attributes.
  drawContents (pPainter);
}

// This function checks if pColor is within the min/max of one of the color keys.
bool ImageObject::filterColorKey ( QColor *pColor, QValueList<QColor *> *pListColorMin, QValueList<QColor *>*pListColorMax )
{
	int iRed, iGreen, iBlue, t, iColorKeyCount;
	iColorKeyCount = manipulator().listColorKeys.count ();
	if ( ( iColorKeyCount < 1 ) || ( ! pListColorMin ) || ( ! pListColorMax ) )
		return false;
	iRed = pColor->red(); iGreen = pColor->green(); iBlue = pColor->blue ();
	for (t=0;t<iColorKeyCount;t++)	{
//printf ("RGB<%02x%02x%02x> MIN<%02x%02x%02x> MAX<%02x%02x%02x> - ", iRed, iGreen, iBlue, (*pListColorMin)[t]->red  (), (*pListColorMin)[t]->green  (), (*pListColorMin)[t]->blue  (), (*pListColorMax)[t]->red(),(*pListColorMax)[t]->green(), (*pListColorMax)[t]->blue());
		if (	(iRed   >= (*pListColorMin)[t]->red  () && iRed   <= (*pListColorMax)[t]->red  ()) && 
			(iGreen >= (*pListColorMin)[t]->green() && iGreen <= (*pListColorMax)[t]->green()) &&
			(iBlue  >= (*pListColorMin)[t]->blue () && iBlue  <= (*pListColorMax)[t]->blue ()) )
			return true;
	}
	return false;
}

void ImageObject::updatePixmap()
{
	// This function will take the input image and pass it through the whole modifications pipeline,
	// so we get a nice and clean rotated / colored image again.

	// In order to speed up the whole procedure, we set the matrix first to scale the image,
	// then we handle the color functions on the smaller image and lastly we apply the rotation,shearing...
	int iRed, iGreen, iBlue;
	int x, y;
	bool bLighter = true;
	float fAdjust = 0.0;
	QColor theColor;
	QRgb thePix;	// QRgb defined as :  0xAARRGGBB;
	QWMatrix theMatrix;
	// Here we calculate the center point of gravity (rotation)
	QPoint centerPos;

	if (fileName().isEmpty())
		return;

	QImage theImage(fileName());
	if (theImage.isNull())
		return;
	theImage = theImage.smoothScale ( rect ().width(), rect().height(), QImage::ScaleFree);

	centerPos.setX (rect().x() + (int)((float)rect().width () / 2.0));
	centerPos.setY (rect().y() + (int)((float)rect().height() / 2.0));
	// First we translate to the appropriate location,
	theMatrix.translate ((double)centerPos.x(), (double)centerPos.y());
	// then we apply the other modifications ...
	theMatrix.scale  (modifiers()->fScaleX, modifiers()->fScaleY);
//	theMatrix.scale  (manipulator().fZoom, manipulator().fZoom);
	// Here we create the scaled image ...
	theImage = theImage.xForm ( theMatrix );

	// create empty image.
	QImage imageColored = QImage (theImage.width(), theImage.height(), theImage.depth());
	if (manipulator().fBrightness > 0.0)	{
		bLighter = true;
		fAdjust = 100 + manipulator().fBrightness * 300;
	}
	else	{
		bLighter = false;
		fAdjust = 100 + manipulator().fBrightness * -300;
	}
	for (y=0;y<theImage.height();y++)	{
		for (x=0;x<theImage.width();x++)	{
			thePix = theImage.pixel(x, y);
			iRed = (int)((float)qRed(thePix) * manipulator().fRed);
			iBlue = (int)((float)qBlue(thePix) * manipulator().fBlue);
			iGreen = (int)((float)qGreen(thePix) * manipulator().fGreen);

			theColor = QColor (iRed, iGreen, iBlue);
			if (bLighter)
				theColor = theColor.light ((int)fAdjust);
			else
				theColor = theColor.dark ((int)fAdjust);
			// This test is to mask out the transparency color (0, 0, 0)
			if (theColor == QColor (0,0,0))
				theColor = QColor (0,0,1);
			imageColored.setPixel (x, y, theColor.rgb());
		}
	}
	// Next we re-set the matrix ...
	theMatrix.reset ();
	// and plug in the remaining operations ...
	theMatrix.shear  (manipulator().fShearX, manipulator().fShearY);
	theMatrix.rotate (manipulator().fRotate);
	theImage = imageColored.xForm( theMatrix );
	m_pixmap.convertFromImage(theImage);
	emit (signalUpdatePixmap());
}

bool ImageObject::readProjectFile  (QDomNode &theNode)
{
	QDomElement theElement = theNode.toElement();
	// The video node has only attributes and nothing else.
	QDomAttr attribute = theElement.attributeNode ( IMAGE_OBJECT_FILE_NAME );
	if (!attribute.isNull())
		setFile ( attribute.value() );

	QDomNode manNode = theNode.firstChild();
	while (!manNode.isNull())	{
		QDomElement manElement = manNode.toElement();
		if (manElement.tagName() == MANIPULATOR)
			manipulator().readProjectFile (manNode);
		else if (manElement.tagName() == MENU_OBJECT)
			MenuObject::readProjectFile( theNode );

		manNode = manNode.nextSibling();
	}
	this->updatePixmap ();
	return true;
}

bool ImageObject::writeProjectFile (QDomElement &theElement)
{
	QDomDocument xmlDoc = theElement.ownerDocument();
	QDomElement imageNode = xmlDoc.createElement( IMAGE_OBJECT );	// <FrameObject>
	// Here we set the attributes of the <dvdauthor> tag
	if (!m_qsFileName.isNull())
		imageNode.setAttribute( IMAGE_OBJECT_FILE_NAME, m_qsFileName );

	manipulator().writeProjectFile (imageNode);

	theElement.appendChild( imageNode );
	// And here we write the base class ...
	return MenuObject::writeProjectFile( imageNode );
}

void ImageObject::createStructure (QListViewItem *pParentItem)
{
	StructureItem *pButtonItem;
	QFileInfo fileInfo(m_qsFileName);
	QString qsName;
	
	qsName = QString ("Image Object");

	pButtonItem = new StructureItem(this, pParentItem, qsName, fileInfo.fileName());
	pButtonItem->setExpandable (TRUE);

	manipulator ().createStructure (pButtonItem);
	if ( m_pShadow )
	     m_pShadow->createStructure ( pButtonItem );

	new StructureItem(this, pButtonItem, QString ("Geometry"),
		QString ("%1, %2, %3, %4").
		arg(rect().x()).arg(rect().y()).arg(rect().width()).arg(rect().height()));
}

bool ImageObject::mousePressEvent (QMouseEvent *pEvent)
{
	m_currentMousePos = pEvent->pos();
	if (pEvent->button() == Qt::RightButton)	{
		QPoint globalPos = pEvent->globalPos();
		return createContextMenu ( globalPos );
	}
	else {
		m_bDrawRect = true;
	}
	return false;
}

bool ImageObject::mouseReleaseEvent (QMouseEvent *)
{
	m_bDrawRect = false;
	updatePixmap ();
	emit (signalUpdatePixmap());
	emit (signalUpdateStructure());
	return false;
}

bool ImageObject::mouseDoubleClickEvent (QMouseEvent *)
{
	// Back to the MenuPreview - class, where I can handle this request ...
	emit (signalModifyMe(this));
	return false;
}

bool ImageObject::createContextMenu ( QPoint globalPos )
{
        QString qsShadow;
	QPoint globalPos2 = globalPos;
	QPopupMenu *pStackMenu = new QPopupMenu(m_pParent);
	pStackMenu->insertItem ( tr ("Cut") , this, SLOT ( slotCut  ( ) ) );
	pStackMenu->insertItem ( tr ("Copy"), this, SLOT ( slotCopy ( ) ) );
	pStackMenu->insertSeparator ( );
	pStackMenu->insertItem ( tr ("To Front")  , this, SLOT(slotToFront()));
	pStackMenu->insertItem ( tr ("To Back")   , this, SLOT(slotToBack()));
	globalPos.setY ( globalPos.y ( ) - 25 );
	globalPos.setX ( globalPos.x ( ) - pStackMenu->sizeHint().width()); // -100);
	pStackMenu->popup ( globalPos, 1 );

	qsShadow = tr ( "Add Shadow ..." );
	if ( shadow ( ) )
 	   qsShadow = tr ( "Edit Shadow ..." );

	if (m_pContextMenu)
		delete m_pContextMenu;
	m_pContextMenu = new QPopupMenu(m_pParent);
	m_pContextMenu->insertItem ( tr ("Edit ...")      , this, SLOT(slotEdit      ( ) ) );
	m_pContextMenu->insertItem ( tr ("Properties ..."), this, SLOT(slotProperties( ) ) );
	m_pContextMenu->insertItem ( tr ("Matrix ...")    , this, SLOT(slotMatrix    ( ) ) );
	m_pContextMenu->insertItem ( tr ("Delete")        , this, SLOT(slotDelete    ( ) ) );
	m_pContextMenu->insertSeparator();
	m_pContextMenu->insertItem ( tr ("Rotate 90")     , this, SLOT(slotRotate90  ( ) ) );
	m_pContextMenu->insertItem ( tr ("Rotate 180")    , this, SLOT(slotRotate180 ( ) ) );
	m_pContextMenu->insertItem ( tr ("Rotate 270")    , this, SLOT(slotRotate270 ( ) ) );
	m_pContextMenu->insertSeparator();
	m_pContextMenu->insertItem ( qsShadow             , this, SLOT(slotAddShadow ( ) ) );
	m_pContextMenu->insertItem ( tr ("Add Frame")     , this, SLOT(slotAddFrame  ( ) ) );
	m_pContextMenu->insertItem ( tr ("Add Text")      , this, SLOT(slotAddText   ( ) ) );
	m_pContextMenu->insertSeparator();
	m_pContextMenu->insertItem ( tr ("Define as Button") , this, SLOT(slotDefineAsButton()));
	// Blocking call.
	m_pContextMenu->exec(globalPos2, 6);
	delete pStackMenu;
	if (m_pContextMenu)
		delete m_pContextMenu;
	m_pContextMenu = NULL;
	return true;
}

bool ImageObject::mouseMoveEvent (QMouseEvent *pEvent)
{
  // Slightly different behaviour for images.
  // if we stretch X and/or Y separately we'll mess rotation up
  // this is why we have to prevent this. 
  // So the stretch will be reset and ShearX will be used instead ScaleX if rotated.
  int iPos = 0;

  switch ( m_objectState ) {
  case MenuObject::StateScaleLeftX: 
  case MenuObject::StateScaleRightX: {
    iPos = pEvent->pos().x() - m_currentMousePos.x();
    double fZoom   = (double)( iPos / 100.0 );
    if (fZoom > 1.0)
      fZoom = fZoom * 2.0 - 1.0;

    if ( m_objectState == MenuObject::StateScaleLeftX )
      fZoom *= -1;
    if ( modifiers()->fRotate == 0.0 )
      modifiers( )->fScaleX *= ( 1.0 + fZoom );
    else
      modifiers( )->fShearX -= fZoom;
    update   ( );
  }
  break;
  case MenuObject::StateScaleTopY:
  case MenuObject::StateScaleBottomY: {
    iPos = pEvent->pos().y() - m_currentMousePos.y();
    double fZoom   = (double)( iPos / 100.0 );
    if (fZoom > 1.0)
      fZoom = fZoom * 2.0 - 1.0;
    
    if ( m_objectState == MenuObject::StateScaleTopY )
      fZoom *= -1;
    if ( modifiers()->fRotate == 0.0 )
      modifiers( )->fScaleY *= ( 1.0 + fZoom );
    else
      modifiers( )->fShearY += fZoom;
    update   ( );
  }
  break;
  case MenuObject::StateRotate:
    modifiers()->fScaleX = 1.0;
    modifiers()->fScaleY = 1.0;    
  default:
    return MenuObject::mouseMoveEvent ( pEvent );
  }
  m_currentMousePos = pEvent->pos();
  return false;
}


void ImageObject::slotEdit()
{
	mouseDoubleClickEvent(NULL);
}

void ImageObject::slotProperties()
{
	ImageManipulator *pMan= &manipulator();

	DialogGeometry *pGeometry = new DialogGeometry ();
	pGeometry->initMe(rect(), pMan);

	connect ( pGeometry->m_pButtonAnimation, SIGNAL(clicked()), this, SLOT(slotAnimation()) );
	
	if (pGeometry->exec() == QDialog::Accepted)	{
		int iX, iY, iWidth, iHeight;
		iX      = pGeometry->m_pEditX->text().toInt();
		iY      = pGeometry->m_pEditY->text().toInt();
		iWidth  = pGeometry->m_pEditWidth ->text().toInt();
		iHeight = pGeometry->m_pEditHeight->text().toInt();
		QRect rect (iX, iY, iWidth, iHeight);
		
		ImageManipulator::colorKeying *pColorKey;
		ListViewColorItem *pItem;
		uint t;
		float  fDelta;
		QColor theColor;

		// First we should remove all entries in the color Key
		for (t=0;t<pMan->listColorKeys.count();t++)
			delete pMan->listColorKeys[t];
		pMan->listColorKeys.clear();
		// And then we add whats currently in the widget.
		if ( pGeometry->m_pListViewCK->childCount() )	{
			pItem = (ListViewColorItem *)pGeometry->m_pListViewCK->firstChild ();
			while (pItem)	{
				theColor.setNamedColor (pItem->text (0));	// The Color nam is stored in the first text
				fDelta = pItem->text(1).toFloat();		// The delta value is stored in the second column.
				pColorKey = new ImageManipulator::colorKeying ( theColor.rgb(), fDelta );
				pMan->listColorKeys.append ( pColorKey );
				pItem = (ListViewColorItem *)pItem->itemBelow ();
			}
		}
		setRect (rect);
		updatePixmap ( );
		updateShadow ( );
		emit (signalUpdatePixmap());
	}
	delete pGeometry;
}

void ImageObject::slotAnimation ()
{
	// This function gets the Animation Dialog
	// Within this dialog, you can create a script
	// (or hardcode) Attributes of the object.
	// Before rendering the menu the script will 
	// get executed and all data sent to stdout 
	// will be captured in the data file, wich 
	// will provide the data for the animation.
	QString qsEmpty;
	DialogAnimation dialog;
	dialog.initMe ( animation(), 300, 25.0, DialogAnimation::TypeImage );
	if ( dialog.exec () == QDialog::Accepted )
		setAnimation ( dialog.string () );

	if (animation().length () < 5)
		setAnimation ( qsEmpty );
}

void ImageObject::slotRotate90()
{
	rotate (90.0);
}

void ImageObject::slotRotate180()
{
	rotate (180.0);
}

void ImageObject::slotRotate270()
{
	rotate (270.0);
}

void ImageObject::rotate(float fRot)
{
	QWMatrix theMatrix;
	theMatrix.rotate (fRot);
	float fRotate = manipulator().fRotate + fRot;
	if (fRotate > 180.0)
		fRotate -= 360.0;
	manipulator().fRotate = fRotate;
	m_pixmap = m_pixmap.xForm( theMatrix );
	emit (signalUpdatePixmap());
	parent()->update();
}

void ImageObject::slotMatrix()
{
  DialogMatrix *pDialog = new DialogMatrix(MenuObject::parent());
  pDialog->initMe(this);
  connect (this, SIGNAL(signalDeleteMe(MenuObject *)), pDialog, SLOT(slotDeleteObject(MenuObject *)));
  pDialog->show();
}

void ImageObject::slotAddFrame()
{
	MessageBox::warning (NULL, QString ("Not Implemented yet."), QString ("Not Implemented yet."),
		QMessageBox::Ok ,  QMessageBox::Cancel);
}

void ImageObject::slotAddText()
{
	MessageBox::warning (NULL, QString ("Not Implemented yet."), QString ("Not Implemented yet."),
		QMessageBox::Ok ,  QMessageBox::Cancel);
}

void ImageObject::slotDefineAsButton()
{
	emit ( signalDefineAsButton ( this ) );
}

MenuObject *ImageObject::clone( QWidget *pParent )
{
  if ( !pParent )
    pParent = MenuObject::parent ( );
  ImageObject *pNewObject = new ImageObject ( pParent );
  pNewObject->setPixmap ( pixmap   ( ) );
  pNewObject->setFile   ( fileName ( ) );
  pNewObject->setZoom   ( zoom     ( ) );
  // The following two are not really needed, since we get those
  // informations solely from the Normal State - objects ...
  pNewObject->setRect        ( rect        ( ) );
  pNewObject->setManipulator ( manipulator ( ) );
  pNewObject->setAnimation   ( animation   ( ) );
  
  MenuObject *pShadow = shadow ( );
  if ( pShadow )
    pShadow = pShadow->clone ( pNewObject, pParent );
  pNewObject->setShadow (  pShadow   );
  
  return pNewObject;
}

// Called from xyz, when creating the AnimationAttribute objects, which hold the list of values for the attribute to be set.
// Note: only those AnimationAttribute objects are created which are modified during the animation (Menu - video).
AnimationAttribute *ImageObject::getSpecificAttributes (long iMaxNumberOfFrames, QString qsProperty)
{
	AnimationAttribute *pAnimAttr = NULL;

	if (qsProperty == "zoom")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fZoom, &m_imageManipulator.fZoom);
	else if (qsProperty == "rotate")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fRotate, &m_imageManipulator.fRotate);
	else if (qsProperty == "shear.x")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fShearX, &m_imageManipulator.fShearX);
	else if (qsProperty == "shear.y")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fShearY, &m_imageManipulator.fShearY);
	else if (qsProperty == "scale.x")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fScaleX, &m_imageManipulator.fScaleX);
	else if (qsProperty == "scale.y")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fScaleY, &m_imageManipulator.fScaleY);
	else if (qsProperty == "transparency")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fTransparency, &m_imageManipulator.fTransparency);
	else if (qsProperty == "backgroundFileName")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.backgroundFileName, &m_imageManipulator.backgroundFileName);
	else if (qsProperty == "showBackground")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.bShowBackground, &m_imageManipulator.bShowBackground);
	else if (qsProperty == "startPos.x")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fStartX, &m_imageManipulator.fStartX);
	else if (qsProperty == "startPos.y")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fStartY, &m_imageManipulator.fStartY);
	else if (qsProperty == "res.x")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.iXRes, &m_imageManipulator.iXRes);
	else if (qsProperty == "res.y")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.iYRes, &m_imageManipulator.iYRes);
	else if (qsProperty == "aspectRatio")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fAspectRatio, &m_imageManipulator.fAspectRatio);
	else if (qsProperty == "blendColor.red")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fRed, &m_imageManipulator.fRed);
	else if (qsProperty == "blendColor.green")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fGreen, &m_imageManipulator.fGreen);
	else if (qsProperty == "blendColor.blue")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fBlue, &m_imageManipulator.fBlue);
	else if (qsProperty == "brightness")
		pAnimAttr = new AnimationAttribute (iMaxNumberOfFrames, qsProperty, m_imageManipulator.fBrightness, &m_imageManipulator.fBrightness);

	return pAnimAttr;
}

