/****************************************************************************
** DialogOverlay
**
**   Created : Sat July 4 22:05:28 2009
**        by : Varol Okan using Kate
** Copyright : (c) Varol Okan
**   License : GPL v 2.0
**
****************************************************************************/

#include <qdir.h>
#include <qtimer.h>
#include <qslider.h>
#include <qlayout.h>
#include <qcursor.h>
#include <qspinbox.h>
#include <qpainter.h>
#include <qfileinfo.h>
#include <qpushbutton.h>
#include <qscrollview.h>
#include <qapplication.h>

#include "global.h"
#include "dvdmenu.h"
#include "messagebox.h"
#include "qdvdauthor.h"
#include "menuobject.h"
#include "imageobject.h"
#include "overlayobject.h"
#include "dialogoverlay.h"
#include "dialoganimation.h"

static const char *xpmRotate[] = {
"32 32 9 1",
"       c None",
".      c #060904",
"+      c #363735",
"@      c #626461",
"#      c #848683",
"$      c #A3A5A2",
"%      c #C8CAC7",
"&      c #DDDFDC",
"*      c #F9FBF7",
"         ......                 ",
"      ..@$&**#@..               ",
"     .$**********..  .          ",
"   .+&****&******+....          ",
"   +***&+.....***&#*&.          ",
"  .&**#..  .....*****.          ",
" .$**#.    .   ..&&&*.          ",
" .**&.         .+&&**..         ",
" @**+.         .%****..         ",
".$**.         ..........        ",
".&*&.             .###..        ",
".**%.             .#$$.         ",
".&*&.             .&&%.         ",
".$**.             .&&$.         ",
" @**+.            +&&@.         ",
" .**%.           .%&&..         ",
" .$**#.         .@&&$.          ",
"  .&&&#..      .#%&%.           ",
"  .+&&&%+.....+%&&&+.           ",
"   .+&&&&&&%%&&&&%+.            ",
"    ..$&&&&&&&&&$..             ",
"      ..@$%&%$@..               ",
"        ........                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                "};

static const char *xpmMove[] = {
"32 32 9 1",
"       c None",
".      c #050804",
"+      c #A3A5A1",
"@      c #B5B7B4",
"#      c #C0C2BF",
"$      c #CFD1CE",
"%      c #DBDDDA",
"&      c #E9EBE8",
"*      c #F2F4F1",
"            .                   ",
"           .@.                  ",
"          .$*$.                 ",
"         .$***$.                ",
"        .$*****$.               ",
"       .@*******@.              ",
"        .$****&$..              ",
"     .   .$**&$..  .            ",
"    .@.   .*&*.. ..+.           ",
"   .$*$.  .*&*. ..#%#.          ",
"  .$***$...&&&...#%%%#.         ",
" .$****&**&&&&&&&%%%%%#.        ",
".@****&&&&&&&&%%%%%%%%%+.       ",
" .$*&&&&**&&&%%&&%%%%%#..       ",
"  .$&&&#...&%%...#%%%#..        ",
"   .#&#.. .&%&. ..#%#..         ",
"    .@.. ..&%&.. ..+..          ",
"     .. ..#%%%#.. ...           ",
"        .#%%%%%#..              ",
"       .+%%%%%$$+.              ",
"        .#%%%$$@..              ",
"         .#%$$@..               ",
"          .#$@..                ",
"           .+..                 ",
"            ..                  ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                "};

static const char *xpmZoom[] = {
"32 32 9 1",
"       c None",
".      c #060A07",
"+      c #262828",
"@      c #505860",
"#      c #9FA29F",
"$      c #8EB2D3",
"%      c #C6C8C5",
"&      c #D4D6D3",
"*      c #F0F2EF",
"       .....                    ",
"     .@%**&#@.                  ",
"   .+********&+.                ",
"  .#**%@+.+@&**#.               ",
"  +**#.@$$$@.#**+.              ",
" .&*#+$$$$$$$+#*&.              ",
" @*&.$$$@.@$$$.%*@.             ",
".#*@@$$$@.@$$$@@*#.             ",
".&*+$$@@...@@$$+*&.             ",
".**.$$.......$$.**.             ",
".&*+$$@@...@@$$+**.             ",
".#*@@$$$@.@$$$@@*&.             ",
" @*%.$$$@.@$$$.%&&.             ",
" .&*@+$$$$$$$+@&&%.             ",
"  +*&@.@$$$@.@&&&&@.            ",
"  .@&&%@+.+@%&&&&&&+.           ",
"   .+%&&&&&&&&%&&&&%.           ",
"    ..@#%&%#@..@&%%%%.          ",
"      ........ .+%%%%#.         ",
"                ..%%%%.         ",
"                 ..@%@.         ",
"                   ...          ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                "};

static const char *xpmShear[] = {
"32 32 9 1",
"       c None",
".      c #000100",
"+      c #0B0D09",
"@      c #B1B3B0",
"#      c #DFE1DE",
"$      c #E8EAE7",
"%      c #EBEDEA",
"&      c #F2F4F0",
"*      c #F8FAF7",
"........                        ",
".******+                        ",
".******+                        ",
".****&*+                        ",
".**&&&*+.                       ",
".*&&&&&@+                       ",
".***&&&&@+                      ",
".++++@&%%@+                     ",
"    .+@%%%@+                    ",
"      +@%$$@+                   ",
"       +@$$$@++++.              ",
"        +@$$$%%%%.              ",
"         +@$####%.              ",
"          +%####%.              ",
"          +$####$.              ",
"          +$####$.              ",
"          +$$$$$$.              ",
"          ........              ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                ",
"                                "};

// Init static member variables
Rgba DialogOverlay::m_keepColor = Rgba ( 0xFF000000 );

DialogOverlay::Preview::Preview ( DialogOverlay *pDialog, QWidget *pParent, const char *pName, WFlags theFlags )
  : QLabel ( pParent, pName, theFlags )
{
  m_pDialog = pDialog;
}

DialogOverlay::Preview::~Preview ( )
{

}

void DialogOverlay::Preview::mousePressEvent ( QMouseEvent *pEvent )
{
  m_pDialog->slotSliderPressed    ( );
  m_currentPos = pEvent->pos      ( );
  m_iButton   |= ( pEvent->button ( ) == LeftButton  ) ? 1 : 0;
  m_iButton   |= ( pEvent->button ( ) == RightButton ) ? 2 : 0;
  m_iButton   |= ( pEvent->button ( ) == MidButton   ) ? 4 : 0;

  QPixmap pix;
  if ( m_iButton == 1 )
    pix = QPixmap ( xpmMove );
  else if ( m_iButton == 2 )
    pix = QPixmap ( xpmRotate );
  else if ( m_iButton == 3 )
    pix = QPixmap ( xpmZoom );
  else if ( m_iButton == 4 )
    pix = QPixmap ( xpmShear );
  if (  ! pix.isNull ( ) )  {
    QCursor myCursor ( pix, 0, 0 );
    QApplication::setOverrideCursor ( myCursor );
  }
}

void DialogOverlay::Preview::mouseReleaseEvent ( QMouseEvent * )
{
  QApplication::restoreOverrideCursor ( );
  m_pDialog->slotSliderReleased ( );
  m_iButton = 0;
}

void DialogOverlay::Preview::mouseMoveEvent ( QMouseEvent *pEvent )
{
  int iDeltaX = m_currentPos.x ( ) - pEvent->pos ( ).x ( );
  int iDeltaY = m_currentPos.y ( ) - pEvent->pos ( ).y ( );

  if ( m_iButton == 1 )       // LeftButton
    m_pDialog->moveBy  ( iDeltaX,  iDeltaY );
  else if ( m_iButton == 2 )  // RightButton
    m_pDialog->rotateBy( iDeltaX + iDeltaY );
  else if ( m_iButton == 3 )  // Left + Right Button
    m_pDialog->zoomBy  ( iDeltaX,  iDeltaY );
  else if ( m_iButton == 4 )  // MidButton
    m_pDialog->shearBy ( iDeltaX,  iDeltaY );

  m_currentPos = pEvent->pos ( );
}

DialogOverlay::Item::Item ( QIconView *pIconView, const QPixmap &thePix )
  : QIconViewItem ( pIconView )
{
  m_pixmap     = thePix;
  refreshIcon ( );
}

void DialogOverlay::Item::calcRect ( const QString &string )
{
  QIconViewItem::calcRect ( string );
  QRect rect  ( 0, 0, 1, 1 );
  setTextRect ( rect );
  setItemRect ( pixmapRect ( ) );
}

void DialogOverlay::Item::refreshIcon ( )
{
  QPixmap pixCheck, thePix;
  int iX, iY, iWidth, iHeight;
  QColor clrBlue ( 120, 120, 255 );

  iWidth  = m_pixmap.width  ( );
  iHeight = m_pixmap.height ( );

  int  iSize = iWidth;
  if ( iSize < iHeight )
       iSize = iHeight;
  if ( iSize < 16 )
       iSize = 16;
  thePix = QPixmap ( iSize + 2, iSize + 2 );
  thePix.fill ( 0xFFFA74 );

  iX = (int)( ( iSize - iWidth  ) / 2.0 ) + 1;
  iY = (int)( ( iSize - iHeight ) / 2.0 ) + 1;

  copyBlt ( &thePix, iX, iY, &m_pixmap );

  // Frame the pix
  QPainter thePainter ( &thePix );
  thePainter.setPen   ( clrBlue );
  thePainter.drawLine (       0,       0, iSize+1,       0 );
  thePainter.drawLine ( iSize+1,       0, iSize+1, iSize+1 );
  thePainter.drawLine ( iSize+1, iSize+1,       0, iSize+1 );
  thePainter.drawLine (       0, iSize+1,       0,       0 );
  setPixmap ( thePix );
}

DialogOverlay::DialogOverlay ( QWidget* parent, const char* name, bool modal, WFlags fl )
  : uiDialogOverlay   ( parent, name, modal, fl )
{
  m_pBackground      = NULL;
  m_pOverlay         = NULL;
  m_pOrigOverlay     = NULL;
  m_pMenuObject      = NULL;
  m_pNoOverlayObject = NULL;
  m_pPreview         = NULL;
  m_pScrollView      = NULL;
  m_iThumbSize       =   60;

  QGridLayout *pLayout;
  uint iFlags = 0;

#if (QT_VERSION > 0x0301FF)
  iFlags = Qt::WNoAutoErase;
#else
  iFlags = Qt::WPaintClever;
#endif

  pLayout       = new QGridLayout ( m_pLabelPreview, 1, 1, 2, 2, "pFramePreviewLayout");
  m_pScrollView = new QScrollView ( m_pLabelPreview, "m_pScrollView", iFlags );
  m_pPreview    = new Preview     ( this, m_pScrollView,  "pPreview", iFlags );
  m_pScrollView->addChild ( m_pPreview );
  m_pPreview->resize      (  720, 480  );
  pLayout->addWidget      ( m_pScrollView, 0, 0 );
}

DialogOverlay::~DialogOverlay ( )
{
  if ( m_pMenuObject )
       m_pMenuObject->setActive ( m_bStoredActiveState );

  if ( m_pOverlay )
    delete m_pOverlay;
  if ( m_pOrigOverlay )
    delete m_pOrigOverlay;
  if ( m_pNoOverlayObject )
    delete m_pNoOverlayObject;

  m_pOverlay         = NULL;
  m_pOrigOverlay     = NULL;
  m_pNoOverlayObject = NULL;
}

void DialogOverlay::initMe ( MenuObject *pMenuObject, QPixmap *pBackground )
{
  m_pBackground = pBackground;
  m_pMenuObject = pMenuObject;

  if ( m_pMenuObject )  {
    QWidget       *pColorTab = m_pTabWidget->page ( 1 );
    OverlayObject *pOverlay  = ( OverlayObject *)m_pMenuObject->overlay ( );
    bool bIsMask  = true;
    if ( pOverlay )
         bIsMask = pOverlay->isMask ( );
    m_pTabWidget->setTabEnabled ( pColorTab, bIsMask );
  }

  connect ( m_pSliderOffsetX,   SIGNAL ( sliderPressed    ( ) ), this, SLOT ( slotSliderPressed  ( ) ) );
  connect ( m_pSliderOffsetY,   SIGNAL ( sliderPressed    ( ) ), this, SLOT ( slotSliderPressed  ( ) ) );
  connect ( m_pSliderRotate,    SIGNAL ( sliderPressed    ( ) ), this, SLOT ( slotSliderPressed  ( ) ) );
  connect ( m_pSliderShearX,    SIGNAL ( sliderPressed    ( ) ), this, SLOT ( slotSliderPressed  ( ) ) );
  connect ( m_pSliderShearY,    SIGNAL ( sliderPressed    ( ) ), this, SLOT ( slotSliderPressed  ( ) ) );
  connect ( m_pSliderScaleX,    SIGNAL ( sliderPressed    ( ) ), this, SLOT ( slotSliderPressed  ( ) ) );
  connect ( m_pSliderScaleY,    SIGNAL ( sliderPressed    ( ) ), this, SLOT ( slotSliderPressed  ( ) ) );
  connect ( m_pSliderRed,       SIGNAL ( sliderPressed    ( ) ), this, SLOT ( slotSliderPressed  ( ) ) );
  connect ( m_pSliderGreen,     SIGNAL ( sliderPressed    ( ) ), this, SLOT ( slotSliderPressed  ( ) ) );
  connect ( m_pSliderBlue,      SIGNAL ( sliderPressed    ( ) ), this, SLOT ( slotSliderPressed  ( ) ) );
  connect ( m_pSliderAlpha,     SIGNAL ( sliderPressed    ( ) ), this, SLOT ( slotSliderPressed  ( ) ) );

  connect ( m_pSliderOffsetX,   SIGNAL ( sliderReleased   ( ) ), this, SLOT ( slotSliderReleased ( ) ) );
  connect ( m_pSliderOffsetY,   SIGNAL ( sliderReleased   ( ) ), this, SLOT ( slotSliderReleased ( ) ) );
  connect ( m_pSliderRotate,    SIGNAL ( sliderReleased   ( ) ), this, SLOT ( slotSliderReleased ( ) ) );
  connect ( m_pSliderShearX,    SIGNAL ( sliderReleased   ( ) ), this, SLOT ( slotSliderReleased ( ) ) );
  connect ( m_pSliderShearY,    SIGNAL ( sliderReleased   ( ) ), this, SLOT ( slotSliderReleased ( ) ) );
  connect ( m_pSliderScaleX,    SIGNAL ( sliderReleased   ( ) ), this, SLOT ( slotSliderReleased ( ) ) );
  connect ( m_pSliderScaleY,    SIGNAL ( sliderReleased   ( ) ), this, SLOT ( slotSliderReleased ( ) ) );
  connect ( m_pSliderRed,       SIGNAL ( sliderReleased   ( ) ), this, SLOT ( slotSliderReleased ( ) ) );
  connect ( m_pSliderGreen,     SIGNAL ( sliderReleased   ( ) ), this, SLOT ( slotSliderReleased ( ) ) );
  connect ( m_pSliderBlue,      SIGNAL ( sliderReleased   ( ) ), this, SLOT ( slotSliderReleased ( ) ) );
  connect ( m_pSliderAlpha,     SIGNAL ( sliderReleased   ( ) ), this, SLOT ( slotSliderReleased ( ) ) );

  connect ( m_pSliderOffsetX,   SIGNAL ( sliderMoved  ( int ) ), this, SLOT ( slotOffsetX    ( int ) ) );
  connect ( m_pSliderOffsetY,   SIGNAL ( sliderMoved  ( int ) ), this, SLOT ( slotOffsetY    ( int ) ) );
  connect ( m_pSliderRotate,    SIGNAL ( sliderMoved  ( int ) ), this, SLOT ( slotRotate     ( int ) ) );
  connect ( m_pSliderScaleX,    SIGNAL ( sliderMoved  ( int ) ), this, SLOT ( slotScaleX     ( int ) ) );
  connect ( m_pSliderScaleY,    SIGNAL ( sliderMoved  ( int ) ), this, SLOT ( slotScaleY     ( int ) ) );
  connect ( m_pSliderShearX,    SIGNAL ( sliderMoved  ( int ) ), this, SLOT ( slotShearX     ( int ) ) );
  connect ( m_pSliderShearY,    SIGNAL ( sliderMoved  ( int ) ), this, SLOT ( slotShearY     ( int ) ) );
  connect ( m_pSliderRed,       SIGNAL ( sliderMoved  ( int ) ), this, SLOT ( slotRed        ( int ) ) );
  connect ( m_pSliderGreen,     SIGNAL ( sliderMoved  ( int ) ), this, SLOT ( slotGreen      ( int ) ) );
  connect ( m_pSliderBlue,      SIGNAL ( sliderMoved  ( int ) ), this, SLOT ( slotBlue       ( int ) ) );
  connect ( m_pSliderAlpha,     SIGNAL ( sliderMoved  ( int ) ), this, SLOT ( slotAlpha      ( int ) ) );

  connect ( m_pButtonReset,     SIGNAL ( clicked ( ) ), this, SLOT ( slotReset     ( ) ) );
  connect ( m_pButtonNoOverlay, SIGNAL ( clicked ( ) ), this, SLOT ( slotNoOverlay ( ) ) );
  connect ( m_pButtonAnimation, SIGNAL ( clicked ( ) ), this, SLOT ( slotAnimation ( ) ) );

  QTimer::singleShot ( 50, this, SLOT ( slotInitLibrary ( ) ) );
}

void DialogOverlay::accept ( )
{
  keepStaticVariables ( );
  m_pOverlay = NULL;  /// Don't delete in destructor
  QDialog::accept ( );
}

void DialogOverlay::reject ( )
{
  m_pMenuObject->setOverlay ( m_pOrigOverlay );
  m_pOverlay     = NULL;  // Was deleted by above function call
  m_pOrigOverlay = NULL;  // Is now taken byt the MenuObject
  QDialog::reject ( );
}

void DialogOverlay::slotNoOverlay ( )
{
  m_pMenuObject->setOverlay ( NULL );
  m_pOverlay = NULL;  // Was deleted by above function call
  QDialog::accept ( );
}

void DialogOverlay::keepStaticVariables ( )
{
  if ( ! m_pOverlay )
    return;

  m_keepColor = m_pOverlay->color  ( );
}

void DialogOverlay::setStaticVariables ( )
{
  if ( ! m_pOverlay )
    return;

  m_pOverlay->setColor ( m_keepColor );
}

void DialogOverlay::slotInitLibrary ( )
{
  QCursor myCursor     ( QCursor::WaitCursor );
  QApplication::setOverrideCursor ( myCursor );

  // build all library tab.
  int iCounter=0, t;
  bool bFound = false;
  QDir     theDir;
  QString  qsPath;
  QStringList listFiles;
  QIconView *pIconView = m_pIconView;

  qsPath = QString ("%1/share/qdvdauthor/masks/simple").arg ( Global::qsSystemPath );
  for ( t=0; t<2; t++ )  {
    if ( theDir.exists ( qsPath ) )  {
      theDir.cd ( qsPath );
      listFiles = theDir.entryList ( QDir::Files, QDir::Name );
      if ( listFiles.count ( ) > 0 )  {
        QFileInfo fileInfo;
        QString qsFileName, qsFile;
        QSize grid ( m_iThumbSize, m_iThumbSize );
        Item *pItem = NULL;
        bFound = true;

        pIconView->setAutoArrange   ( true );
        pIconView->setSelectionMode ( QIconView::Single );  // QIconView::NoSelection );
        pIconView->setItemsMovable  ( FALSE );
        pIconView->setResizeMode    ( QIconView::Adjust );
        pIconView->arrangeItemsInGrid ( grid, TRUE );

        for ( int t=0; t<(int)listFiles.count ( ); t++ ) {
          qsFileName = qsPath + "/" + listFiles[t];
          QPixmap thePix;
          QImage  theImage ( qsFileName );

          if ( theImage.isNull ( ) )
            continue;

          if ( ( theImage.width ( ) > m_iThumbSize ) || ( theImage.height ( ) > m_iThumbSize ) )
            theImage = theImage.smoothScale ( m_iThumbSize, m_iThumbSize, QImage::ScaleMin );

          thePix.convertFromImage ( theImage );

          pItem = new Item ( pIconView, thePix );
          pItem->setKey ( qsFileName );

          if ( ++iCounter >= 3 )  {
            iCounter = 0;
            qApp->processEvents ( 100 ); // do some event processing ...
          }
        }
        connect ( pIconView, SIGNAL ( mouseButtonClicked ( int, QIconViewItem *, const QPoint & ) ), this, SLOT ( slotClicked ( int, QIconViewItem *, const QPoint & ) ) );
      }
      qsPath = QString ("%1/share/qdvdauthor/masks/frames").arg ( Global::qsSystemPath );
      pIconView = m_pIconViewFrames;
    }
  }
  if ( ! bFound )  {
    QApplication::restoreOverrideCursor ( );
    QString qsHtml;
    qsHtml  = tr ( "The mask library could not be found in the system path under:\n" );
    qsHtml += Global::qsSystemPath + "/share/qdvdauthor/masks\n\n";
    qsHtml += tr ( "You can get the library from : http://qdvdauthor.sf.net using the following commands.\n\n" );
    qsHtml += "cd /tmp\n";
    qsHtml += "wget http://qdvdauthor.sf.net/data/masks.tar.bz2\n";
    qsHtml += QString ( "cd " ) + Global::qsSystemPath + "/share/qdvdauthor\n";
    qsHtml += "sudo tar -xjf /tmp/masks.tar.bz2\n\n";

    MessageBox::html ( NULL, tr( "Mask Library missing" ), qsHtml );
    return;
  }

  if ( m_pMenuObject )  {
     m_bStoredActiveState = m_pMenuObject->isActive ( );
     m_pMenuObject->setActive ( false );

     m_pOverlay = new OverlayObject ( m_pMenuObject );
     if ( m_pMenuObject->overlay ( ) ) {
       OverlayObject    *pCurrentOverlay = ( OverlayObject *)m_pMenuObject->overlay ( );
       m_pOrigOverlay =  new OverlayObject ( m_pMenuObject );
      *m_pOrigOverlay = *pCurrentOverlay;
      *m_pOverlay     = *pCurrentOverlay;
       m_pOverlay->setOverlay ( m_pOverlay->fileName ( ) );
     }
     else
       setStaticVariables ( );

     ImageObject *pImage = (ImageObject *)m_pMenuObject;
     m_pMenuObject->setOverlay (  NULL   );
     m_pNoOverlayObject  = (ImageObject *)pImage->clone ( );
     m_pMenuObject->setOverlay ( m_pOverlay );
     setValues ( );
  }

  QApplication::restoreOverrideCursor ( );
}

void DialogOverlay::slotReset ( )
{
  OverlayObject defaultOverlay ( NULL, NULL );
  *m_pOverlay = defaultOverlay;
  setValues ( );
}

void DialogOverlay::slotAnimation ( )
{
  if ( ! m_pOverlay )
    return;

  QString qsAnimation = m_pOverlay->animation ( );
  QString qsDummy;

  DVDMenu *pDVDMenu = Global::pApp->getCurrentSubMenu ( );
  if ( pDVDMenu )
       pDVDMenu->slotAnimateObject ( qsAnimation, DialogAnimation::TypeOverlay, qsDummy );

  m_pOverlay->setAnimation ( qsAnimation );
}

void DialogOverlay::slotClicked ( int iButton, QIconViewItem *pItm, const QPoint & )
{
  if ( ! pItm )
    return;

  if ( iButton != Qt::LeftButton )
    return;

  Item  *pItem    = (Item *)pItm;
  QImage theImage ( pItem->key ( ) );
  if ( theImage.isNull ( ) )
    return;

  bool bIsMask = ( pItem->iconView ( ) == m_pIconView );
  QWidget *pColorTab = m_pTabWidget->page ( 1 );

  m_pOverlay->setOverlay ( pItem->key ( ) );
  m_pOverlay->setIsMask  ( bIsMask );

  m_pTabWidget->setTabEnabled ( pColorTab, bIsMask );
  drawOverlay ( );
}

void DialogOverlay::slotSliderPressed ( )
{
  if ( m_pOverlay )
       m_pOverlay->setFastDraw ( true );
  drawOverlay ( );
}

void DialogOverlay::slotSliderReleased ( )
{
  if ( m_pOverlay )
       m_pOverlay->setFastDraw ( false );
  drawOverlay ( );
}

void DialogOverlay::rotateBy ( int iDelta )
{
  if ( ! m_pOverlay )
    return;

  float fRotate;
  fRotate = m_pOverlay->rotate ( ) - (float)iDelta / 4.0f;

  if ( fRotate  > 360.0f )
       fRotate -= 360.0f;
  if ( fRotate  <-360.0f )
       fRotate += 360.0f;

  setRotate ( fRotate );
}

void DialogOverlay::shearBy ( int iDeltaX, int iDeltaY )
{
  if ( ! m_pOverlay )
    return;

  float fShearX, fShearY;
  fShearX = m_pOverlay->shearX ( ) - (float)iDeltaX / 500.0;
  fShearY = m_pOverlay->shearY ( ) - (float)iDeltaY / 500.0;

  setShear ( fShearX, fShearY );
}

void DialogOverlay::moveBy ( int iDeltaX, int iDeltaY )
{
  if ( ! m_pOverlay )
    return;

  int iOffsetX = m_pOverlay->offset ( ).x ( ) - iDeltaX;
  int iOffsetY = m_pOverlay->offset ( ).y ( ) - iDeltaY;

  setOffset ( iOffsetX, iOffsetY );
}

void DialogOverlay::zoomBy ( int iDeltaX, int iDeltaY )
{
  if ( ! m_pOverlay )
    return;

  float fScaleX, fScaleY;
  fScaleX = m_pOverlay->scaleX ( ) - iDeltaX / 500.0;
  fScaleY = m_pOverlay->scaleY ( ) - iDeltaY / 500.0;

  if ( fScaleX < 0.0f )
       fScaleX = -fScaleX;
  if ( fScaleY < 0.0f )
       fScaleY = -fScaleY;

  setScale ( fScaleX, fScaleY );
}

void DialogOverlay::setValues ( )
{
  setRotate ( m_pOverlay->rotate ( ) );
  setColor  ( m_pOverlay->color  ( ) );
  setOffset ( m_pOverlay->offset ( ).x ( ), m_pOverlay->offset ( ).y ( ) );
  setScale  ( m_pOverlay->scaleX ( ),       m_pOverlay->scaleY ( ) );
  setShear  ( m_pOverlay->shearX ( ),       m_pOverlay->shearY ( ) );
}

void DialogOverlay::setOffset ( int iOffsetX, int iOffsetY )
{
  if ( ! m_pOverlay || ! m_pNoOverlayObject )
    return;

  m_pOverlay->setOffset ( iOffsetX, iOffsetY );

  int iValueX = (int)( ( iOffsetX * 1000.0 ) / m_pNoOverlayObject->image ( ).width  ( ) );
  int iValueY = (int)( ( iOffsetY * 1000.0 ) / m_pNoOverlayObject->image ( ).height ( ) );
  m_pSliderOffsetX->setValue ( iValueX );
  m_pSliderOffsetY->setValue ( iValueY );

  drawOverlay ( );
}

void DialogOverlay::setColor ( Rgba &color )
{
  m_pOverlay->setColor ( color );

  m_pSliderRed  ->setValue ( color.red   ( ) );
  m_pSliderGreen->setValue ( color.green ( ) );
  m_pSliderBlue ->setValue ( color.blue  ( ) );
  m_pSliderAlpha->setValue ( color.alpha ( ) );
  drawOverlay ( );
}

void DialogOverlay::setRotate ( float fRotate )
{
  if ( ! m_pOverlay )
    return;

  m_pOverlay->setRotate ( fRotate );
  int iRotate = (int)( fRotate * 1000.0f / 360.0f );
  m_pSliderRotate->setValue ( iRotate );

  drawOverlay ( );
}

void DialogOverlay::setScale ( float fScaleX, float fScaleY )
{
  if ( ! m_pOverlay )
    return;

  m_pOverlay->setScale ( fScaleX, fScaleY );
  int  iValueX = 0; 
  int  iValueY = 0; 
  if ( fScaleX<= 1.0f )
       iValueX = (int)( fScaleX * 1000.0f - 1000.0f );
  else
       iValueX = (int)( fScaleX *  250.0f -    1.0f );
  if ( fScaleY<= 1.0f )
       iValueY = (int)( fScaleY * 1000.0f - 1000.0f );
  else
       iValueY = (int)( fScaleY *  250.0f -    1.0f );

  m_pSliderScaleX->setValue ( iValueX );
  m_pSliderScaleY->setValue ( iValueY );

  drawOverlay ( );
}

void DialogOverlay::setShear ( float fShearX, float fShearY )
{
  if ( ! m_pOverlay )
    return;

  m_pOverlay->setShear ( fShearX, fShearY );

  int iValueX = (int)( fShearX * 1000.0 );
  int iValueY = (int)( fShearY * 1000.0 );
  m_pSliderShearX->setValue  (  iValueX );
  m_pSliderShearY->setValue  (  iValueY );

  drawOverlay ( );
}

void DialogOverlay::slotRotate ( int iValue )
{
  // iValue [-1000 .. +1000]
  if ( ! m_pOverlay )
    return;

  float fRotate = (float)iValue / 1000.0f * 360.0f;
  m_pOverlay->setRotate ( fRotate );
  drawOverlay ( );
}

void DialogOverlay::slotOffsetX ( int iValue )
{
  // iValue [-1000 .. +1000]
  if ( ! m_pOverlay )
    return;

  iValue = (int)( ( iValue ) / 1000.0 * m_pNoOverlayObject->image ( ).width ( ) );

  m_pOverlay->setOffset ( iValue, m_pOverlay->offset ( ).y ( ) );
  drawOverlay ( );
}

void DialogOverlay::slotOffsetY ( int iValue )
{
  // iValue [-1000 .. +1000]
  if ( ! m_pOverlay )
    return;

  iValue = (int)( ( iValue ) / 1000.0 * m_pNoOverlayObject->image ( ).width ( ) );

  m_pOverlay->setOffset ( m_pOverlay->offset ( ).x ( ), iValue );
  drawOverlay ( );
}

void DialogOverlay::slotScaleX ( int iValue )
{
  // iValue [-1000 .. +1000]
  if ( ! m_pOverlay )
    return;

  float fScaleX;
  if ( iValue < 0 )
    fScaleX = ( 1000 + iValue ) / 1000.0f; // min Zoom = 0%
  else
    fScaleX = 1.0f + iValue / 250.0f;     // Max Zoom = 500%

  m_pOverlay->setScale ( fScaleX, m_pOverlay->scaleY ( ) );
  drawOverlay ( );
}

void DialogOverlay::slotScaleY ( int iValue )
{
  // iValue [-1000 .. +1000]
  if ( ! m_pOverlay )
    return;

  float fScaleY;
  if ( iValue < 0 )
    fScaleY = ( 1000 + iValue ) / 1000.0f; // min Zoom = 0%
  else
    fScaleY = 1.0f + iValue / 250.0f;     // Max Zoom = 500%

  m_pOverlay->setScale ( m_pOverlay->scaleX ( ), fScaleY );
  drawOverlay ( );
}

void DialogOverlay::slotShearX ( int iValue )
{
  // iValue [-1000 .. +1000]
  if ( ! m_pOverlay )
    return;

  float fShearX, fShearY;
  fShearX = (float)iValue / 1000.0;
  fShearY = m_pOverlay->shearY ( );
  m_pOverlay->setShear ( fShearX, fShearY );
  drawOverlay ( );
}

void DialogOverlay::slotShearY ( int iValue )
{
  // iValue [-1000 .. +1000]
  if ( ! m_pOverlay )
    return;

  float fShearX, fShearY;
  fShearY = (float)iValue / 1000.0;
  fShearX = m_pOverlay->shearX ( );
  m_pOverlay->setShear ( fShearX, fShearY );
  drawOverlay ( );
}

void DialogOverlay::slotRed ( int iValue )
{
  // iValue [0 .. 255]
  if ( ! m_pOverlay )
    return;

  Rgba color = m_pOverlay->color ( );
  color.setRed ( iValue );
  m_pOverlay->setColor ( color );
  drawOverlay ( );
}

void DialogOverlay::slotGreen ( int iValue )
{
  // iValue [0 .. 255]
  if ( ! m_pOverlay )
    return;

  Rgba color = m_pOverlay->color ( );
  color.setGreen ( iValue );
  m_pOverlay->setColor ( color );
  drawOverlay ( );
}

void DialogOverlay::slotBlue ( int iValue )
{
  // iValue [0 .. 255]
  if ( ! m_pOverlay )
    return;

  Rgba color = m_pOverlay->color ( );
  color.setBlue ( iValue );
  m_pOverlay->setColor ( color );
  drawOverlay ( );
}

void DialogOverlay::slotAlpha ( int iValue )
{
  // iValue [0 .. 255]
  if ( ! m_pOverlay )
    return;

  Rgba color = m_pOverlay->color ( );
  color.setAlpha ( iValue );
  m_pOverlay->setColor ( color );
  drawOverlay ( );
}

bool DialogOverlay::isChecked ( QString &qsString )
{
  QStringList::iterator it = m_listEnabled.begin ( );
  while ( it != m_listEnabled.end ( ) )  {
    if ( *it++ == qsString )
      return true;
  }

  return false;
}

void DialogOverlay::drawOverlay ( )
{
  if ( ! m_pMenuObject )
    return;

  QPixmap  thePixmap = *m_pBackground;
  QPainter thePainter ( &thePixmap );

  m_pMenuObject->drawContents ( &thePainter );

  m_pPreview->setPaletteBackgroundPixmap  ( thePixmap );
  m_pPreview->resize ( thePixmap.width ( ), thePixmap.height ( ) );
}
