/****************************************************************************
** MenuPreview class
**
**   Created : Tue Feb 02 22:06:51 2004
**        by : Varol Okan using Kate
** Copyright : (c) Varol Okan
**   License : GPL v 2.0
**
** This class is the encapsulation of the MenuPreview.
**
** The MenuPreview is derived off the ButtonPreview and used 
** to display a DVD Menu.
** The ButtonPreview is the preview class used in the ButtonObject
** to display the different levels of a buttonObject.
**
**
****************************************************************************/

#include <sys/stat.h>
#include <sys/types.h>
#include <stdlib.h>

#include <qfiledialog.h>
#include <qdragobject.h>
#include <qpopupmenu.h>
#include <qiconview.h>
#include <qlineedit.h>
#include <qcheckbox.h>
#include <qtextedit.h>
#include <qpainter.h>
#include <qregexp.h>
#include <qcursor.h>
#include <qtimer.h>
#include <qimage.h>

#include "win32.h"
#include "global.h"
#include "qdvdauthor.h"
#include "layoutwizard.h"
#include "dvdmenuundoobject.h"
#include "xml_dvd.h"
#include "buttonpreview.h"
#include "dialogtextfont.h"
#include "dialogbutton.h"
#include "menupreview.h"
#include "menuobject.h"
#include "frameobject.h"
#include "maskobject.h"
#include "textobject.h"
#include "imageobject.h"
#include "movieobject.h"
#include "buttonobject.h"
#include "shadowobject.h"
#include "sourcefileentry.h"
#include "objectcollection.h"
#include "listviewmedia.h"
#include "dialogresize.h"
#include "dialogshadow.h"
#include "dialoglibrary.h"
#include "messagebox.h"
#include "filepreviewdialog.h"
#include "qplayer/engines/dummywidget.h"
#include "qplayer/mediacreator.h"
#include "qplayer/mediainfo.h"

#include "dialogthumbnail.h"
#include "dialogimage2.h"
#include "dialogalign.h"
#include "dialogoverlay.h"

MenuPreview::MenuPreview(QWidget * parent, const char * name, WFlags f)
  : ButtonPreview   ( parent, name, f ),
    m_pDialogButton ( NULL )
{
  initMe (NULL);
  setAcceptDrops(true);

  connect ( &m_selectionObject, SIGNAL ( signalMoveOnStack ( MenuObject *, int ) ), this, SLOT ( slotMoveOnStack ( MenuObject *, int ) ) );
  connect ( &m_selectionObject, SIGNAL ( signalShadowMe    ( MenuObject * ) ),      this, SLOT ( slotAddShadow   ( MenuObject * ) ) );
  connect ( &m_selectionObject, SIGNAL ( signalOverlayMe   ( MenuObject * ) ),      this, SLOT ( slotAddOverlay  ( MenuObject * ) ) );
  connect ( &m_selectionObject, SIGNAL ( signalDeleteMe    ( MenuObject * ) ),      this, SLOT ( slotDeleteObject( MenuObject * ) ) );
  connect ( &m_selectionObject, SIGNAL ( signalUndoMe      ( MenuObject * ) ),      this, SLOT ( slotUndoObject  ( MenuObject * ) ) );
  connect ( &m_selectionObject, SIGNAL ( signalAlignSelection ( ) ), this, SLOT ( slotAlignSelection  ( ) ) );
}

MenuPreview::~MenuPreview()
{
  if ( m_pDialogButton )
    delete m_pDialogButton;
  m_pDialogButton = NULL;
}

MenuPreview &MenuPreview::operator = ( MenuPreview &theOther )
{
  m_bIsSubMenu   = theOther.m_bIsSubMenu;
  m_bIsMovieMenu = theOther.m_bIsMovieMenu;
  m_pPgcColors   = theOther.m_pPgcColors;
  m_bImageButton = theOther.m_bImageButton;
  m_doubleBuffer = theOther.m_doubleBuffer;
  ButtonPreview *pMe    = (ButtonPreview *)this;
  ButtonPreview *pOther = (ButtonPreview *)&theOther;
  *pMe = *pOther;

  uint t;
  MenuObject  *pObject;
  // At this point we have new objects but none of them are connected to any signals / slots ...
  for ( t=0; t<objectCount ( ); t++ ) {
    pObject  = menuObject ( t );
    if ( ! pObject )
      continue;

    pObject->disconnect ( );
    connectStdSlots ( pObject, true );
  }

  return *this;
}

void MenuPreview::initMe ( Rgba *pColors )
{
  m_iCreateObjectStyle = TypeNone;
  m_iPointerState      = StateNormal;
  m_pActiveObject      = NULL;
  m_pDialogButton      = NULL;
  m_bIsSubMenu         = false;
  m_bIsMovieMenu       = false;
  m_bImageButton       = true;
  m_pPgcColors         = pColors;
}

void MenuPreview::clear ( Rgba *pColors )
{
  uint t;
  if ( m_pDialogButton )
    delete m_pDialogButton;
  m_pDialogButton = NULL;

  initMe ( pColors );

  // Clear the undoBuffer and create an new one.
  if ( m_pUndoBuffer )
    delete m_pUndoBuffer;
  m_pUndoBuffer = new UndoBuffer ( MAX_UNDO_DEPTH );

  for ( t=0; t<m_listMenuObjects.count ( ); t++ )
    delete m_listMenuObjects.at ( t );
  m_listMenuObjects.clear ( );
  m_backgroundPixmap = QPixmap ( );
}

void MenuPreview::setIsSubMenu ( bool bIsSubmenu )
{
	// This function is only here to flag that the MenuPreview is part of a SubMenu and
	// Not a VMGM, or something else.
	m_bIsSubMenu = bIsSubmenu;
}

void MenuPreview::setIsMovieMenu(bool bIsMovieMenu)
{
	// This function is only here to flag that the MenuPreview is part of a SubMenu and
	// Not a VMGM, or something else.
	m_bIsMovieMenu = bIsMovieMenu;
}

void MenuPreview::setImageButton  (bool bImageButton)
{
	m_bImageButton = bImageButton;
}

bool MenuPreview::createContextMenu ( QPoint globalPos )
{
  Utils theUtil;
  bool bPal  = true;
  bool bNtsc = true;
  if ( theUtil.getFormat( m_backgroundPixmap.width ( ), m_backgroundPixmap.height ( ) ) >= FORMAT_PAL1 )
    bNtsc = false;
  if ( theUtil.getFormat( m_backgroundPixmap.width ( ), m_backgroundPixmap.height ( ) ) <= FORMAT_NTSC4 )
    bPal  = false;

  QPopupMenu *pMenu = new QPopupMenu (this);
  pMenu->insertItem ( tr ("Add Frame"), this, SLOT ( slotAddFrameObject ( ) ) );
  pMenu->insertItem ( tr ("Add Text") , this, SLOT ( slotAddTextObject  ( ) ) );
  pMenu->insertItem ( tr ("Add Image"), this, SLOT ( slotAddImageObject ( ) ) );
  pMenu->insertItem ( tr ("Add Movie"), this, SLOT ( slotAddMovieObject ( ) ) );
  pMenu->insertItem ( tr ("Add From Library ..."), this, SLOT ( slotAddFromLibrary ( ) ) );
  if ( Global::pCopyObject )
    pMenu->insertItem ( tr ("Paste (%1)").arg ( Global::pCopyObject->objectType ( ) ), this, SLOT ( slotPaste ( ) ) );
  //pMenu->insertItem ( tr ("Add Collection"), this, SLOT(slotAddCollection()));
  //	if (m_bIsMovieMenu)	{
  pMenu->insertSeparator ( );
  pMenu->insertItem ( tr ( "Properties ..." ), this, SLOT ( slotEditTimeline ( ) ) );
  //	}
  if (m_bIsSubMenu)	{
    pMenu->insertSeparator ( );
    pMenu->insertItem ( tr ( "Rename Menu"), this, SLOT ( slotRenameMenu ( ) ) );
    pMenu->insertItem ( tr ( "Delete Menu"), this, SLOT ( slotDeleteMenu ( ) ) );
  }
  pMenu->insertItem   (tr ("Clone Menu"), this, SLOT ( slotCloneMenu ( ) ) );
  if ( bNtsc )
    pMenu->insertItem (tr ("Convert to PAL" ), this, SLOT ( slotConvertToPAL  ( ) ) );
  if ( bPal  )
    pMenu->insertItem (tr ("Convert to NTSC"), this, SLOT ( slotConvertToNTSC ( ) ) );
  pMenu->exec(globalPos);

  delete pMenu;
  return true;
}

void MenuPreview::mouseDoubleClickEvent	(QMouseEvent *pEvent)
{
  m_pActiveObject = NULL;
  // First we let the base class have it ...
  ButtonPreview::mouseDoubleClickEvent(pEvent);
}

void MenuPreview::mousePressEvent (QMouseEvent *pEvent)
{
  // First we let the base class have it ...
  m_bMouseEventDone = false;
  if ( m_selectionObject.mousePressEvent ( pEvent ) )
    return;

  if ( m_iPointerState != StateSelected )
    ButtonPreview::mousePressEvent ( pEvent );
  // Here we check if the mouse click appeared withtin one of the MenuObjects,
  // in which case the Object will take over the mouse handling ...
  if (m_bMouseEventDone) {
    m_iPointerState = StateNormal; // added to change state after Add Shadow was selected from ContextMenu...
    return;
  }

  //  char arrayState[][30]={ "StateUnknown", "StateNormal", "StateMoveSelected", "StateReadyToCreate", "StateCreating", "StateSelecting", "StateSelected" };
  //  printf ("MenuPreview::mousePressEvent pointerState<%s>\n", arrayState[m_iPointerState]);

  QPoint      thePos  = pEvent->pos ( );
  MenuObject *pObject = childContains ( thePos );

  if ( ( pObject != NULL ) && ( m_iPointerState != StateSelected ) )	{
    m_pActiveObject = pObject;
    update();
    return;
  }
  // Okay the user actually clicked in the MenuPreview ...
  // The left mouse button was clicked.
  // If the user is in creation mode, then we handle this one
  if ( pEvent->button ( ) == LeftButton )  {
    // if the state is not StateReadyToCreate then we want to select
    if ( m_iPointerState == StateReadyToCreate )  {
      m_iPointerState = StateCreating;
      drawBackground   ( m_doubleBuffer );
      setMouseTracking ( true );
    }
    else if ( m_iPointerState == StateSelected )  {
      if ( m_selectionObject.mouseOver ( pEvent->pos ( ) ) ) {
        m_iPointerState = StateMoveSelected;
        m_selectionObject.setMoveState ( false );
        m_selectionObject.setCurrentMousePos ( (QPoint &) pEvent->pos ( ) );
        drawBackground   ( m_doubleBuffer );
        setMouseTracking ( true );

        UndoBuffer *pUndo = Global::pApp->getUndoBuffer ( );
        if ( pUndo )
             pUndo->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::MOVED_OBJECT, &m_selectionObject, this ) );
      }
    }
    else  {
      if ( m_backgroundPixmap.isNull () )
        return;
      m_iPointerState = StateSelecting;
      setMouseCursor ( MouseCrossCursor );  // signals to be awaiting the next mouse click
      // which will then generate the rectangle for this text button.
      m_selectionObject.clear ( );
      m_pActiveObject = &m_selectionObject;
      drawBackground   ( m_doubleBuffer );
    }
    // Okay, at this point we know the user is creating an object.
    m_rectCurrentObject.setX(pEvent->pos().x());
    m_rectCurrentObject.setY(pEvent->pos().y());
    return;
  }
  // The right mousebutton was pressed means that we should display the context drop down menu.
  setMouseCursor ( MousePointerCursor );
  m_iPointerState = StateNormal;

  createContextMenu ( pEvent->globalPos  ( ) );
}

void MenuPreview::mouseReleaseEvent ( QMouseEvent *pEvent )
{
  // The user is doing something. Let us activate the drawing algol.
  m_rectCurrentObject.setRight  ( pEvent->pos( ).x ( ) );
  m_rectCurrentObject.setBottom ( pEvent->pos( ).y ( ) );

  //  char arrayState[][30]={ "StateUnknown", "StateNormal", "StateMoveSelected", "StateReadyToCreate", "StateCreating", "StateSelecting", "StateSelected" };
  //  printf ("MenuPreview::mouseReleaseEvent pointerState<%s>\n", arrayState[m_iPointerState]);

  if ( pEvent->button ( ) == LeftButton )  {
    m_doubleBuffer = QPixmap ( );
    switch ( m_iPointerState ) {
    case StateMoveSelected:  {
      m_iPointerState = StateSelected;
      m_selectionObject.setMoveState ( false );
      updatePixmap ( );
      if ( m_selectionObject.mouseOver ( pEvent->pos ( ) ) )  {
        DVDMenuUndoObject *pUndo = (DVDMenuUndoObject *) undoBuffer ( )->last ( );
        if ( pUndo && ! pUndo->hasMoved ( ) )  {
          undoBuffer  ( )->removeLast   ( );
          delete pUndo;
          Global::pApp->updateUndoStack ( );
        }
      }
      return;
    }
    case StateCreating: {
      // First we let the base class have it ...
      m_bMouseEventDone = false;
      ButtonPreview::mouseReleaseEvent(pEvent);
      // Here we check if the mouse click appeared withtin one of the MenuObjects,
      // in which case the Object will take over the mouse handling ...
      if ( m_bMouseEventDone ) 
        setMouseTracking ( false );

      m_pActiveObject = NULL;
      switch ( m_iCreateObjectStyle )	{
      case FrameType :
        createFrameObject ();
        break;
      case TextType :
        createTextObject();
        break;
      case ImageType :
        createImageObject();
      break;
      case MovieType :
        createMovieObject ();
        break;
      } // switch createObjectStyle
      m_iPointerState = StateNormal;
      return;
    } // end of case StateCreating
    case StateSelected: {
      m_pActiveObject = NULL;
      m_iPointerState = StateNormal;
      m_selectionObject.setMoveState ( false );
      update ( );
      setMouseTracking ( false );
      return;
    }
    case StateSelecting: {
      if ( m_selectionObject.getCount () > 0 ) {
        m_iPointerState = StateSelected;
        setMouseTracking ( true ); // to change cursor shapes.
      }
      else {
        m_iPointerState = StateNormal;
        setMouseTracking ( false );
      }
      setMouseCursor ( MousePointerCursor );
      update ();
      return;
    }
    case StateNormal:        // nothing to do if we are in Normal Mouse Mode
    case StateReadyToCreate: // Should neve happen ...
    case StateUnknown:       // Something went wrong ...
    default:                 // should never get here
      if ( m_pActiveObject )
           m_pActiveObject->mouseReleaseEvent ( pEvent ); // will call updatePixmap
      else
           updatePixmap  ( );
      m_pActiveObject  = NULL;
      setMouseTracking ( false );
      return;
    }
  } //  end if LeftButton
}

void MenuPreview::mouseMoveEvent (QMouseEvent *pEvent)
{
  //  char arrayState[][30]={ "StateUnknown", "StateNormal", "StateMoveSelected", "StateReadyToCreate", "StateCreating", "StateSelecting", "StateSelected" };
  //  printf ("MenuPreview::mouseMoveEvent pointerState<%s>\n", arrayState[m_iPointerState]);

  switch ( m_iPointerState ) {
  // The one state I dont need to care ...
  case StateReadyToCreate:
    return;
  case StateMoveSelected:
    m_selectionObject.mouseMoveEvent ( pEvent );
    { // doubleBuffer does move the objecs as well, which I don't want
      // I simply want to get rid of the flicker ...
      QPixmap temp ( m_doubleBuffer );
      QPainter thePainter;
      thePainter.begin ( &temp, this );
      m_selectionObject.drawSelected ( &thePainter );
      thePainter.end ( );
      bitBlt ( this, 0, 0, &temp );
    }
  break;
  case StateSelected: {
    // this case will take care of the state when multile objects have been selected
    // and now the user is aboout to move those selected objects around.
    // for this in-between-state, we want to display the mouse move cursor
    // if inside one of the selected objects.
    //    if ( m_selectionObject.mouseOver ( pEvent->pos () ) )
    bool bMouseOver =  m_selectionObject.mouseOver ( pEvent->pos () );
    //    printf ( "MenuPreview::mouseMoveEvent mouseOver<%s> - <%dx%d>\n", bMouseOver ? "true" : "false", pEvent->pos().x(), pEvent->pos().y() );
    if ( bMouseOver )
      setMouseCursor ( MouseMoveCursor    );
    else 
      setMouseCursor ( MousePointerCursor );
    //    m_selectionObject.mouseMoveEvent ( pEvent );
    //update ( );
    return;
  }
  case StateSelecting:
  case StateCreating: {
    // Okay at this point we have m_rectCurrentObject.x, and .y set
    // Here we draw the dynamicly changing size of the rect.

    // First we clear the contents of the previous rectangle
    int iX, iY;
    iX  = pEvent->pos ( ).x ( );
    iY  = pEvent->pos ( ).y ( );
    m_rectCurrentObject.setRight  ( iX );
    m_rectCurrentObject.setBottom ( iY );

    // Double buffering ...
    QPen     thePen   ( QColor ( 255,  30,  30 ), 2, Qt::DashDotLine );
    QBrush   theBrush ( QColor ( 100, 255, 100 ),  Qt::Dense6Pattern );
    QPainter thePainter;
    QPixmap doubleBuffer;
    if ( m_doubleBuffer.isNull( ) )
      thePainter.begin      ( this );
    else {
      doubleBuffer = QPixmap ( m_doubleBuffer );
      thePainter.begin  ( &doubleBuffer, this );
    }

    if ( m_iPointerState  == StateSelecting ) {
      thePen = QPen  ( QColor ( 100, 255, 100 ), 1, Qt::SolidLine );
      thePainter.setBrush ( theBrush );
      checkSelection ( ); // Any objects added to m_selectionObject ?
    }
    else
      thePen = QPen (QColor (255, 30,30), 2, Qt::DashDotLine);

    thePainter.setPen   ( thePen );
    m_selectionObject.drawSelected ( &thePainter );
    thePainter.drawRect ( m_rectCurrentObject    );
    thePainter.drawText ( iX+5, iY+15, QString   ( "%1 : %2" ).arg( m_rectCurrentObject.width ( ) ).arg( m_rectCurrentObject.height ( ) ) );

    thePainter.end ( );  
    if ( ! m_doubleBuffer.isNull ( ) )
      bitBlt ( this, 0, 0, &doubleBuffer );
  }
  break;
  case StateUnknown:
  case StateNormal:
  default:
    // This part will move the active object(s) around ...
    //  if ( m_pActiveObject && m_iPointerState != StateSelecting ) {
    if ( m_pActiveObject ) {
      m_pActiveObject->mouseMoveEvent(pEvent);
      update ( );
      return;
    }
  }
}

void MenuPreview::checkSelection ()
{
  // Check if any object has been captured by the selection box.
  uint t;
  m_selectionObject.clear ( );
  QRect rect = m_rectCurrentObject.normalize ();
  for ( t=0;t<m_listMenuObjects.count ( );t++) {
    if ( rect.intersects ( m_listMenuObjects.at ( t )->boundingRect ( ) ) ) {
      MenuObject *pObject = m_listMenuObjects.at ( t );
      m_selectionObject.append ( pObject, false );
    }
  }
}

void MenuPreview::slotEditTimeline ( )
{
  emit ( signalEditTimeline ( ) );
}

void MenuPreview::slotCut ( )
{
  if ( ! m_pActiveObject )
    return;
  m_pActiveObject->slotCut ( );
}

void MenuPreview::slotCopy ( )
{
  if ( ! m_pActiveObject )
    return;
  m_pActiveObject->slotCopy ( );
}

void MenuPreview::slotPaste ( )
{
  if ( ! Global::pCopyObject )
    return;

  MenuObject *pNewObject = NULL;
  if ( ( Global::pCopyObject->objectType ( ) == QString ( OBJECT_COLLECTION ) ) ||
       ( Global::pCopyObject->objectType ( ) == QString ( SELECTION_OBJECT  ) ) ) {
    ObjectCollection *pCollection =  (ObjectCollection *) Global::pCopyObject;
    int t, iCount = pCollection->getCount ( );
    for ( t=0; t<iCount; t++ ) {
      pNewObject = pCollection->getObject ( t )->clone ( this );
      paste ( pNewObject );
    }
  }
  else {
    pNewObject = Global::pCopyObject->clone ( this );
    paste ( pNewObject );
  }
  if ( pNewObject )
       undoBuffer ( )->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::NEW_OBJECT, pNewObject ) );
}

void MenuPreview::paste ( MenuObject *pNewObject )
{
  QRegExp rx;
  QString qsNewName;
  // In order to see the new object I will move it 10 x 10 ...
  QRect theRect = pNewObject->rect ( );
  int iWidth  = theRect.width  ( );
  int iHeight = theRect.height ( );
  theRect.setX ( theRect.x ( ) - 10 );
  theRect.setY ( theRect.y ( ) - 10 );
  theRect.setWidth    ( iWidth  );
  theRect.setHeight   ( iHeight );
  pNewObject->setRect ( theRect );

  // assign a unique object name ...
  qsNewName = pNewObject->name ( );
  // Here we remove the prefix 
  rx.setPattern ( "Copy\\s*\\(\\d*\\)" );
  qsNewName.remove ( rx );
  rx.setPattern ( "^Copy" );
  qsNewName.remove ( rx );
  rx.setPattern ( "^\\s*" );
  qsNewName.remove ( rx );
  // to get a true unique name ...
  qsNewName = uniqueObjectName ( QString ( "Copy " ), qsNewName );
  pNewObject->setName ( qsNewName );

  //pNewObject->mouseReleaseEvent ( NULL );
  connectStdSlots ( pNewObject, true );
  addMenuObject   ( pNewObject );
  pNewObject->mouseReleaseEvent ( NULL );
}

QString MenuPreview::getMovieFileName ( MovieObject * /*pMovieObject*/, QStringList &list )
{
  QFileInfo fileInfo;
  QString   qsFullFileName;
  QDVDAuthor *pDVDAuthor = Global::pApp;
  if ( pDVDAuthor ) {
    SourceFileEntry *pEntry = pDVDAuthor->getSourceEntryByDisplayName ( list[1] );
    if ( pEntry ) {
      SourceFileInfo *pInfo = pEntry->listFileInfos[0];
      if ( list.count ( ) == 4 ) {
	for ( unsigned int t=0; t<list.count ( ); t++ ) {
	  pInfo = pEntry->listFileInfos[t];
	  fileInfo.setFile ( pInfo->qsFileName );
	  if ( fileInfo.fileName ( ) == list[2] )
	    break;
	}
      }
      qsFullFileName = pInfo->qsFileName;
    }
  }
  return qsFullFileName;
}

void MenuPreview::dropEvent ( QDropEvent *pDropEvent )
{
  QImage  theImage;
  QString theText;
  //  printf ( "%s::%s : %d  <%s>\n", __FILE__, __FUNCTION__, __LINE__, pDropEvent->format ( ) );

  if ( QImageDrag::decode ( pDropEvent, theImage ) )  {
    if ( theImage.isNull  ( ) )
      return;
    // insert Image, movie or ButtonObject.
    insertDraggedObject    ( pDropEvent, theImage);
    // And check if it comes with text or image only ...
    if ( QTextDrag::decode ( pDropEvent, theText ) )  {
      insertDraggedText    ( pDropEvent, theText );
      emit ( signalDroppedSomething ( DroppedImageAndText ) );
    }
  }
  else if ( QTextDrag::decode ( pDropEvent, theText ) )  {
    QString qsURL = theText;
    qsURL    = qsURL.remove ( "file://" );
    theImage = QImage       ( qsURL );
    if ( theImage.isNull    (   )   ) {
      // Insert TextObject
      insertDraggedText ( pDropEvent, theText );
      emit ( signalDroppedSomething ( DroppedText ) );
    }
    else {
      // insert Image, movie or ButtonObject.
      // Oha, I could decode the URL to a QImage ... let us have some fun now ...
      QFileInfo fileInfo ( qsURL );
      theText = fileInfo.baseName ( );
      MenuObject *pImageObject, *pTextObject;

      // Next we should get the DND Size ...
      //  theImage = theImage.smoothScale ( 150, 150, QImage::ScaleMin );
      // insert Image, movie or ButtonObject.
      pImageObject = insertDraggedImage ( pDropEvent, theImage, false ); //insertDraggedObject ( pDropEvent, theImage );
      // And check if it comes with text or image only ...
      pTextObject  = insertDraggedText  ( pDropEvent,  theText, false );
      emit ( signalDroppedSomething ( DroppedImageAndText ) );

      undoBuffer ( )->push ( new DVDMenuUndoObject(DVDMenuUndoObject::DRAGGED_IMAGE, pImageObject, pTextObject ) );
    }
  }
  else if ( QIconDrag::canDecode ( pDropEvent ) ) {
    // Get the Frame of the QIconView ...
    QWidget *pDropParent = pDropEvent->source ( );
    if ( pDropParent ) {
      // get the IconView
      pDropParent = pDropParent->parentWidget ( );
      if ( pDropParent && ( pDropParent->isA  ( "QIconView" ) ) ) {
	QIconView     *pView = (QIconView *)pDropParent;
	QIconViewItem *pItem = NULL;
	
	pItem = pView->firstItem ( );
	QValueList<QIconViewItem *> tempList;
	while ( pItem ) {
	  if  ( pItem->isSelected ( ) ) {
	    // If it is coming from "m_pIconViewThumbnails" then we create a ButtonObject
	    // else we create a ImageObject.
	    if ( pDropParent->name ( ) == QString ( "m_pIconViewThumbnails" ) )
	      tempList.append ( pItem );
	    else {
	      QImage   theImage;
	      QPixmap *pPixmap = pItem->pixmap ( );
	      if ( pPixmap ) {
		theImage = pPixmap->convertToImage ( );
		if ( pDropParent->name ( ) == QString ( "pIconViewLibrary" ) )
		  insertDraggedThumbnail ( pDropEvent, theImage ); // coming from the Library dialog.
		else
		  insertDraggedImage     ( pDropEvent, theImage );
	      }
	    }
	  }
	  pItem = pItem->nextItem ( );
	}
	if ( tempList.count ( ) > 0 )
	  insertDraggedChapters ( pDropEvent, tempList );
      }
    }
  }
}

MenuObject *MenuPreview::insertDraggedThumbnail ( QDropEvent *pDropEvent, QImage &theImage )
{
  // This function is called when a drop event from the Library dialog occured.
  // returns either an ImageObject or a ButtonObject
  QWidget *pDropParent = pDropEvent->source ( );
  // Just to make sure ...
  if ( pDropParent ) {
    pDropParent = pDropParent->parentWidget ( );
    if ( pDropParent && ( pDropParent->isA  ( "QIconView" ) ) ) {
      ImageObject *pImageObject = (ImageObject *)insertDraggedImage ( pDropEvent, theImage, false );
      pImageObject->manipulator  ( ).listColorKeys.append ( new ImageManipulator::colorKeying ( qRgb ( 254, 255, 254 ), 0.0f ) );
      //pImageObject->updatePixmap ( );
      if ( DialogLibrary::m_bCreateButtonMask ) {
	ButtonObject *pButtonObject = new ButtonObject ( this );
	QString qsAction ( "jump+-+vmgm+-+" );
	// First we remove the ImageObject ( the one we just added )

	Rgba colorHighlighted ( START_HIGHLIGHTED_COLOR );
	Rgba colorSelected    ( START_SELECTED_COLOR    );
	if ( m_pPgcColors )   {
	  colorHighlighted = m_pPgcColors[1];
	  colorSelected    = m_pPgcColors[2];
	}

	pImageObject->resetStructureItem ( );
	m_listMenuObjects.remove    ( pImageObject );
	pButtonObject->appendNormal ( pImageObject );
	pButtonObject->setRect      ( pImageObject->rect ( ) );
	pButtonObject->setName      ( newButtonName ( ) );
	pButtonObject->setAction    ( qsAction );
	pButtonObject->createMask   ( m_pPgcColors );

	// and here we append the button object as a new item in the MenuObject list.
	m_listMenuObjects.append    ( pButtonObject );
	m_pActiveObject = NULL;

	// And finally we connect everything ...
	connectStdSlots ( pButtonObject, true );
	undoBuffer ( )->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::DRAGGED_BUTTON, pButtonObject ) );

	emit ( signalUpdateStructure ( ) );
	updatePixmap ( ); // already done with insertDraggedImage ( ... )
	return pButtonObject;
      }
      else  // Here we only create an ImageObject, no button.
	return pImageObject;
    }
  }
  return NULL;
}

MenuObject *MenuPreview::insertDraggedText (QDropEvent *pEvent, QString &theText, bool bAddUndo )
{
  QRect rect;
  if ( pEvent )
  rect = QRect ( pEvent->pos ( ).x ( ), pEvent->pos ( ).y ( ), 1, 1 );

  TextObject *pTextObject = new TextObject ( this );
  pTextObject->setRect     ( rect );
  pTextObject->setText     ( theText );
  m_listMenuObjects.append ( pTextObject);

  // Here we connect the signal to the slot ...
  connectStdSlots ( pTextObject, true );

  if ( bAddUndo  )
    undoBuffer ( )->push ( new DVDMenuUndoObject(DVDMenuUndoObject::DRAGGED_TEXT, pTextObject ) );
  emit ( signalUpdateStructure ( ) );
  updatePixmap ( );
  return pTextObject;
}

MenuObject *MenuPreview::insertDraggedObject ( QDropEvent *pDropEvent, QImage &theImage )
{ 
	MenuObject *pMenuObject = NULL;
	// The first thing to check is if this drop was initiated in the Toolbar
	if ( pDropEvent->source() && (QString("m_pListViewAllSources") == pDropEvent->source ( )->name ( ) ) )  {
		ListViewMedia   *pListViewMedia   = (ListViewMedia *)pDropEvent->source      ( );
		SourceFileEntry *pSourceFileEntry = pListViewMedia->draggingSourceFileEntry  ( );
		SourceFileInfo  *pSourceFileInfo  = pListViewMedia->draggingSourceFileInfo   ( );
		if ( pSourceFileEntry->bSoundSource )  {	// No adding of a sound source !
			MessageBox::warning (NULL, tr("Can not add."), tr ("This is a sound source.\nI can currently not add this type of source.\n"), QMessageBox::Ok, QMessageBox::NoButton);
			return NULL;
		}
		if ( pSourceFileEntry->bIsSlideshow )	{
			MessageBox::warning (NULL, tr("Can not add."), tr ("The slideshow is still beeing created.\nI can not add it at this moment.\n"), QMessageBox::Ok, QMessageBox::NoButton);
			return NULL;
		}
		if ( pSourceFileInfo )  // Okay here we split between adding one button
			pMenuObject = insertDraggedSourceInfo  ( pDropEvent, theImage );  // ButtonObject
		else	// Or we dragged the full SourceEntry and will use the defined Layout
			if (pSourceFileEntry->listFileInfos.count ( ) == 1 ) // Now only one movie in the Entry ... Booooring ...
				pMenuObject = insertDraggedSourceInfo ( pDropEvent, theImage);  // ButtonObject
			else
				pMenuObject = insertDraggedSourceInfo ( pDropEvent, theImage);  //
// FIXME: 
// For now we defer this to the next major release so we can release 0.1.5 some time
// This is supposed to create a whole bunch of menus inclusive backgroud and buttons.
//				pMenuObject = insertDraggedSourceEntry ();	// ObjectCollection
		// Last but not lease we re-set the dragging Sources so we have clean hands ...
		pListViewMedia->resetDragging ( );
	}
	else	// The source came from some source outside QDVDAuthor.
		pMenuObject = insertDraggedImage ( pDropEvent, theImage );  // ImageObject
	return  pMenuObject;
}

MenuObject *MenuPreview::insertDraggedSourceEntry ( QDropEvent *pDropEvent, QImage & )
{
	uint t;
	ObjectCollection *pObjectCollection = new ObjectCollection;
	// The wizard will take care of the spacing plus the overlay
	LayoutWizard    *pWizard = new LayoutWizard;

	ButtonObject    *pButtonObject    = NULL;
	// Note that at this point we KNOW that the source is coming from the ListViewAllSources - toolbar !!!
	ListViewMedia   *pListViewMedia   = (ListViewMedia *)pDropEvent->source     ( );
	SourceFileEntry *pSourceFileEntry = pListViewMedia->draggingSourceFileEntry ( );
	SourceFileInfo  *pSourceFileInfo  = NULL;

	for (t=0;t<pSourceFileEntry->listFileInfos.count();t++)	{
		pSourceFileInfo  = pSourceFileEntry->listFileInfos[t];
		pButtonObject = (ButtonObject *)createButtonObject( );
		pObjectCollection->append (pButtonObject);
	}
	m_listMenuObjects.remove ( pObjectCollection );
	delete pWizard;
	return pObjectCollection;
}

// Comming from the ThumbnailDialog ...
void MenuPreview::insertDraggedChapters ( QDropEvent *pDropEvent, QValueList<QIconViewItem *> &list )
{
  int  iCount  = list.count ( );
  if ( iCount == 0 )
    return;
  else if ( iCount == 1 ) {
    insertDraggedChapter ( pDropEvent, list[0] );
    return;
  }
  // Here we do some magic to arrange the items in the list around the dropped cursor position.
  // The coordinates depend on the coordinates in the IconView where they come from (DialogThumbnail)
  int t;
  QRect boundingRect = list [ 0 ]->rect ( );
  for ( t=1; t<iCount; t++ )
    boundingRect = boundingRect | list[t]->rect ( );

  QValueList<MenuObject *> objectList;
  MenuObject  *pObject = NULL;
  QIconViewItem *pItem = NULL;
  QPoint pos, dropPos  = pDropEvent->pos ( );
  int iX, iY;
  for ( t=0; t<iCount; t++ ) {
    pItem = list [ t ];
    iX = pItem->rect ( ).x ( ) - boundingRect.x ( ) - (int) ( ( float)boundingRect.width  ( ) / 2.0 ) + dropPos.x ( );
    iY = pItem->rect ( ).y ( ) - boundingRect.y ( ) - (int) ( ( float)boundingRect.height ( ) / 2.0 ) + dropPos.y ( );
    pos = QPoint         ( iX, iY );
    pDropEvent->setPoint ( pos );
    pObject = insertDraggedChapter ( pDropEvent, pItem );
    objectList.append  ( pObject );
    if ( ! pItem->text ( ).isEmpty ( ) )
      objectList.append( m_listMenuObjects.last ( ) ); // The TextObject Belongs here too
  }
  pDropEvent->setPoint ( dropPos );
  // And lastly we add one adn only one UndoObject
  undoBuffer ( )->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::DRAGGED_CHAPTERS, objectList ) );
  m_pActiveObject = NULL;
}

MenuObject *MenuPreview::insertDraggedChapter ( QDropEvent *pDropEvent, QIconViewItem *pItem )
{
  if ( ! pItem )
    return NULL;

  QImage   theImage;
  QString  qsFileName, qsChapter;
  QString  qsText    = pItem->text   ( );
  QString  qsAction  = pItem->key    ( );
  QPixmap *pPixmap   = pItem->pixmap ( );
  Utils    theUtils;
  MenuObject *pMenuObject = NULL;

  if ( ! pPixmap )
    return NULL;

  theImage = pPixmap->convertToImage ( );

  QStringList list = QStringList::split ( QString ( STRING_SEPARATOR ), qsAction );
  if ( list.count ( ) < 1 ) 
    return insertDraggedImage ( pDropEvent, theImage, false );
  else if ( list.count ( ) == 3 )
    qsFileName = list[1];
  else // if ( list.count ( ) == 4 )
    qsFileName = list[2];

  qsChapter = list[ list.size ( ) - 1 ];

  // First we create a MenuObject (ImageObject or MovieObject)
  if ( m_bImageButton )
    pMenuObject = insertDraggedImage ( pDropEvent, theImage, false );
  else	{
    long iMSecOffset = theUtils.getMsFromString ( qsChapter );
    pMenuObject = insertDraggedMovie    ( pDropEvent, theImage, iMSecOffset, false );
    QTime theOffset = QTime::fromString ( qsChapter );
    // Here we set the real name of the Movie file and not the one of the screenshot.
    // but qsFileName can either be the DisplayName of a SourceFileEntry or the fileName of a SourceFileInfo
    MovieObject *pMovieObject  =  (MovieObject *) pMenuObject;
    qsFileName = getMovieFileName ( pMovieObject, list );
    pMovieObject->setFile         ( qsFileName  );
    pMovieObject->setOffset       ( theOffset   );
  }

  // But since we want to create a Button here, we remove it again from the object list.
  m_listMenuObjects.remove ( pMenuObject );
  // Okay the image/movie came from the right source so we actually want a button ...
  ButtonObject *pButtonObject = new ButtonObject ( this );
  // Now we generate two copies ...
  FrameObject *pNewSelected, *pNewHighlighted;
  DialogThumbnail::FrameAttr *pFrameAttr = DialogThumbnail::frameAttr ( );
  DialogThumbnail::TextAttr  *pTextAttr  = DialogThumbnail::textAttr  ( );

  Rgba colorHighlighted ( START_HIGHLIGHTED_COLOR );
  Rgba colorSelected    ( START_SELECTED_COLOR    );
  if ( m_pPgcColors )   {
    colorHighlighted = m_pPgcColors[1];
    colorSelected    = m_pPgcColors[2];
  }
  colorSelected.setRgb ( pFrameAttr->color );

  pNewSelected    = new FrameObject;
  pNewHighlighted = new FrameObject;
  pNewSelected   ->setRect    ( pMenuObject->rect ( ) );
  pNewHighlighted->setRect    ( pMenuObject->rect ( ) );
  pNewSelected   ->setFrameWidth ( pFrameAttr->iWidth );
  pNewHighlighted->setFrameWidth ( pFrameAttr->iWidth );
  pNewSelected   ->setFrameStyle ( pFrameAttr->iStyle );
  pNewHighlighted->setFrameStyle ( pFrameAttr->iStyle );
  pNewSelected   ->setFrameJoin  ( pFrameAttr->iJoin  );
  pNewHighlighted->setFrameJoin  ( pFrameAttr->iJoin  );
  // Next we give some color the the diffenrent states
  pNewSelected   ->setFrameColor ( colorSelected      );
  pNewHighlighted->setFrameColor ( colorHighlighted   );

  pButtonObject->appendNormal      ( pMenuObject      );
  pButtonObject->appendSelected    ( pNewSelected     );
  pButtonObject->appendHighlighted ( pNewHighlighted  );

  pButtonObject->setName ( newButtonName ( ) );
  // Next we should give the button the same attributes as the NormalState ...
  // rect and boundingRect are taken care of in drawContent

  // Let us set a default name for the MenuObject first
  pMenuObject->setName ( qsFileName );

  // The we set some action for the ButtonObject.
  pButtonObject->setAction ( qsAction );

  // and here we append the button object as a new item in the MenuObject list.
  m_listMenuObjects.append ( pButtonObject );

  // the following emit will connect the ButtonObject with the SourceFileEntry
  emit ( signalDroppedSomething ( DroppedChapter ) );

  // And finally we connect everything ...
  connectStdSlots ( pButtonObject, true );
  // After all of this we also want to create a text object ...
  unsigned char iTransparency = ( pTextAttr->backgroundColor & 0xFF000000 ) >> 24;
  double        fTransparency = (double)iTransparency / 255.0;
  QRgb backgroundColor = pTextAttr->backgroundColor;
  // At this time (26/01/2007) we have to convert two transparencies to one (from the old DialogTextFont )
  if ( iTransparency > 254 ) {
    backgroundColor = 0xFFFEFFFE; // old color that marks transparency
    fTransparency = 0.0;
  }
  if ( ! qsText.isEmpty ( ) ) {
    qsText = qsText.replace ( ' ', '_' );
    TextObject *pTextObject=(TextObject *)insertDraggedText ( NULL, qsText, false );
    pTextObject->setFont ( pTextAttr->font );
    pTextObject->setBackgroundColor ( QColor ( backgroundColor ) );
    pTextObject->setForegroundColor ( QColor ( pTextAttr->foregroundColor ) );
    pTextObject->modifiers( )->fTransparency = fTransparency;
    pTextObject->setStyleStrategy   ( 123 ); // to signal to DVDMenu::slotDroppedSomething where we're coming from

    // and then re-position those ... calls DVDMenu::slotDroppedSomething
    if ( m_bImageButton )
      emit ( signalDroppedSomething ( DroppedImageAndText ) );
    else
      emit ( signalDroppedSomething ( DroppedMovieAndText ) );

    emit ( signalUpdateStructure ( ) );
    updatePixmap ( );
    if ( qsText.find ( "Chapter" ) > -1 ) {
      // this is to keep "Chapter X" in one line.
      qsText = qsText.replace ( '_', ' ' );
      pTextObject->setText    (  qsText  );
      updatePixmap ( );
    }
  }
  else {
    // and then re-position those ... calls DVDMenu::slotDroppedSomething
    if ( m_bImageButton )
      emit ( signalDroppedSomething ( DroppedImage ) );
    else
      emit ( signalDroppedSomething ( DroppedMovie ) );

    emit ( signalUpdateStructure ( ) );
    updatePixmap ( );
  }
  return pButtonObject;
}

MenuObject *MenuPreview::insertDraggedSourceInfo ( QDropEvent *pDropEvent, QImage &theImage )
{
	QPixmap thePixmap;
	MenuObject *pMenuObject = NULL;
	// Note that at this point we KNOW that the source is coming from the ListViewAllSources - toolbar !!!
	ListViewMedia   *pListViewMedia   = (ListViewMedia *)pDropEvent->source     ( );
	SourceFileEntry *pSourceFileEntry = pListViewMedia->draggingSourceFileEntry ( );
	SourceFileInfo  *pSourceFileInfo  = pListViewMedia->draggingSourceFileInfo  ( );
	if ( !  pSourceFileInfo )
		pSourceFileInfo = pSourceFileEntry->listFileInfos[0];
	if ( !  pSourceFileInfo )  // If still no luck then return ...
		return NULL;
	// First we create a MenuObject (ImageObject or MovieObject)
	if ( m_bImageButton )
		pMenuObject = insertDraggedImage ( pDropEvent, theImage, false );
	else	{
	        pMenuObject = insertDraggedMovie ( pDropEvent, theImage, pSourceFileInfo->iMSecPreview, false );
		// Here we set the real name of the Movie file and not the one of the screenshot.
		((MovieObject *)pMenuObject)->setFile ( pSourceFileInfo->qsFileName );
	}
	// But since we want to create a Button here, we remove it again from the object list.
	m_listMenuObjects.remove ( pMenuObject );

	pMenuObject->resetStructureItem ( );
	// Okay the image/movie came from the right source so we actually want a button ...
	ButtonObject *pButtonObject = new ButtonObject ( this );
	// Now we generate two copies ...
	MenuObject *pNewSelected, *pNewHighlighted;

	Rgba colorHighlighted ( START_HIGHLIGHTED_COLOR );
	Rgba colorSelected    ( START_SELECTED_COLOR    );
	if ( m_pPgcColors )   {
		colorHighlighted = m_pPgcColors[1];
		colorSelected    = m_pPgcColors[2];
	}

	pNewSelected    = new FrameObject;
	pNewHighlighted = new FrameObject;
	pNewSelected   ->setRect ( pMenuObject->rect ( ) );
	pNewHighlighted->setRect ( pMenuObject->rect ( ) );
	((FrameObject *)(pNewSelected))   ->setFrameWidth ( 10 );
	((FrameObject *)(pNewHighlighted))->setFrameWidth ( 10 );
	// Next we give some color the the diffenrent states
	((FrameObject *)(pNewSelected))   ->setFrameColor ( colorSelected );
	((FrameObject *)(pNewHighlighted))->setFrameColor ( colorHighlighted );

	pButtonObject->appendNormal      ( pMenuObject     );
	pButtonObject->appendSelected    ( pNewSelected    );
	pButtonObject->appendHighlighted ( pNewHighlighted );

	pButtonObject->setName ( newButtonName ( ) );
	// Next we should give the button the same attributes as the NormalState ...
	// rect and boundingRect are taken care of in drawContent
//	pButtonObject->setModifiers(*pMenuObject->modifiers());

	// Okay now we should wed the new Button with the SourceFileInfo - entry ...
	QString qsAction = QString ("jump") + QString ( STRING_SEPARATOR );
	QFileInfo fileInfo;
	QString qsFileName;

	// Let us set a default name for the MenuObject first
	fileInfo.setFile ( pSourceFileInfo->qsFileName );
	qsFileName = fileInfo.fileName  ( );
	pMenuObject->setName ( qsFileName );

	// The we set some action for the BUttonObject.
	if ( pSourceFileEntry )
		qsAction += pSourceFileEntry->qsDisplayName + QString ( STRING_SEPARATOR );
	qsAction += qsFileName + QString( STRING_SEPARATOR) + QString ( "00:00:00.000"   );
	pButtonObject->setAction ( qsAction );
	pButtonObject->setSourceFileEntry ( pSourceFileEntry );

	// and here we append the button object as a new item in the MenuObject list.
	m_listMenuObjects.append ( pButtonObject );

	// And finally we connect everything ...
	connectStdSlots ( pButtonObject, true ); // If false, then Dragged SourceFileInfoButtons can not be edited 
	                                         // Is this the bug with double edit dialogs ?
	// disconnect ( pMenuObject );
	// After all of this we also want to create a text object ...
	QString qsWhatDidWeDragg = fileInfo.baseName ( );
	MenuObject *pDroppedText = insertDraggedText ( NULL, qsWhatDidWeDragg, false );
	// and then re-position those ... calls DVDMenu::slotDroppedSomething
	if ( m_bImageButton )
		emit ( signalDroppedSomething ( DroppedImageAndText ) );
	else
		emit ( signalDroppedSomething ( DroppedMovieAndText ) );

	// And last we take care of the Undo stuff
	undoBuffer ( )->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::DRAGGED_BUTTON, pButtonObject, pDroppedText ) );

	emit ( signalUpdateStructure ( ) );
	updatePixmap ( );
	m_pActiveObject = pButtonObject;
	return pButtonObject;
}

// Here we insert a dragged image, which came from somewhere ...
MenuObject *MenuPreview::insertDraggedImage ( QDropEvent *pDropEvent, QImage &theImage, bool bAddUndo )
{
	QImage  theImage2;
	QString qsFileName;
	QRect   theRect;
	int     iWidth, iHeight;
	Utils   theUtil;
	QPoint  thePoint (pDropEvent->pos());

	qsFileName = theUtil.getUniqueTempFile(DRAGGED_IMAGE_NAME);
	theImage.save ( qsFileName, "PNG" );

	iWidth  = theImage.width  ( );
	iHeight = theImage.height ( );
	// Here we resize if neccesary ...
	if(  ( iWidth > 720) || ( iHeight > 576 ) )  {
		int w = 200;
		int h = 200;
		if ( iWidth > iHeight )
		  h = (int)( 200.0/iWidth * iHeight );
		else
		  w = (int)( 200.0/iHeight * iWidth );
		CResizeDialog *pResizeDialog = new CResizeDialog ( );
		pResizeDialog->setImage ( &theImage );
		pResizeDialog->setSize  ( w, h );
		pResizeDialog->exec     ( );
		iWidth  = pResizeDialog->m_pEditWidth ->text().toInt();
		iHeight = pResizeDialog->m_pEditHeight->text().toInt();
//		iFormat = pResizeDialog->m_iFormat;
		if ( iWidth  < 1 )
		     iWidth  = 150;
		if ( iHeight < 1 )
		     iHeight = 150;
		theImage2 = pResizeDialog->m_pPixmapPreview->pixmap ( )->convertToImage ( );
		delete pResizeDialog;
	}
	else	// If not then we simply take the current Image ..
		theImage2 = theImage;
	theRect   = QRect ( thePoint.x ( ), thePoint.y ( ), iWidth, iHeight );
	ImageObject *pImageObject = new ImageObject (this);
	pImageObject->setZoom  ( 1.0f       );
	pImageObject->setRect  ( theRect    );
	pImageObject->setImage ( theImage2  );
	pImageObject->setFile  ( qsFileName );
	m_pActiveObject = pImageObject;

	// And last we connect the signals
	connectStdSlots ( pImageObject, true );
	m_listMenuObjects.append ( pImageObject );

	// And last we take care of the Undo stuff
	if ( bAddUndo )
	     undoBuffer ( )->push  ( new DVDMenuUndoObject ( DVDMenuUndoObject::DRAGGED_IMAGE, (MenuObject *)pImageObject ) );
	emit ( signalUpdateStructure ( ) );
	updatePixmap ( );
	return pImageObject;
}

MenuObject *MenuPreview::insertDraggedMovie (QDropEvent *pDropEvent, QImage &theImage, long iMSecPreviewOffset, bool bAddUndo )
{
	QPixmap thePixmap;
	QRect   theRect;
	int iWidth, iHeight;
	Utils theUtil;
	QPoint thePoint (pDropEvent->pos());

	iWidth  = theImage.width();
	iHeight = theImage.height();
	QSize theSize = theImage.size();
	// Here we resize if neccesary ...
	if(  (theImage.width() > 720) || (theImage.height() > 576) )	{
		CResizeDialog *pResizeDialog = new CResizeDialog ();
		pResizeDialog->setImage(&theImage);
		pResizeDialog->exec ();
		iWidth  = pResizeDialog->m_pEditWidth ->text().toInt();
		iHeight = pResizeDialog->m_pEditHeight->text().toInt();
//		iFormat = pResizeDialog->m_iFormat;
		if (iWidth  < 1) iWidth  = 150;
		if (iHeight < 1) iHeight = 150;
		thePixmap = *pResizeDialog->m_pPixmapPreview->pixmap ();
		delete pResizeDialog;
	}
	else	// If not then we simply take the current Image ..
		thePixmap.convertFromImage (theImage);
	theRect   = QRect(thePoint.x(), thePoint.y(), iWidth, iHeight);
	MovieObject *pMovieObject = new MovieObject (this);
	pMovieObject->setZoom        ( 1.0f );
	pMovieObject->setRect        ( theRect );
	pMovieObject->setPixmap      ( thePixmap );
	pMovieObject->setMSecPreview ( iMSecPreviewOffset );
//	pMovieObject->setFile        ( qsFileName );
	pMovieObject->setMovieSize   ( theSize );
	m_pActiveObject = pMovieObject;
	emit (signalCreatedMovieObject (pMovieObject, true));	// registerToRender

	// And last we connect the signals
	connectStdSlots ( pMovieObject, true );
	m_listMenuObjects.append(pMovieObject);
	// And last we take care of the Undo stuff
	if ( bAddUndo )
	     undoBuffer ( )->push (new DVDMenuUndoObject ( DVDMenuUndoObject::DRAGGED_MOVIE, (MenuObject *)pMovieObject ) );
	// Call QDVDAuthor::
	emit ( signalUpdateStructure ( ) );
	updatePixmap ( );
	return pMovieObject;
}

void MenuPreview::dragEnterEvent ( QDragEnterEvent *pEvent )
{
	// Tell the Widget that we accept ImageDrops ...
	// This is necessary otherwise the dropEvent does not occur.
	pEvent->accept ( QImageDrag::canDecode ( pEvent ) || 
			 QTextDrag::canDecode  ( pEvent ) ||
			 QIconDrag::canDecode  ( pEvent ) );
	setMouseTracking ( false );
}

bool MenuPreview::readProjectFile (QDomNode &theNode)
{
	uint t;
	if ( m_pDialogButton )
		delete m_pDialogButton;
	m_pDialogButton = NULL;
	QDomNode xmlPreview = theNode.firstChild ( );
	while ( !xmlPreview.isNull ( ) )  {
		// Here we created a MenuObject, we also want to
		MenuObject *pNewObject = readObject ( xmlPreview );
		// add it to the list ...
		if ( pNewObject )  {
			pNewObject->readProjectFile ( xmlPreview );
			m_listMenuObjects.append    ( pNewObject );
		}
		// So lets get the next sibling ... until we hit the end of DVDMenu ...
		xmlPreview = xmlPreview.nextSibling();
	}

	// we need to make one more step here 
	// since we stored the Display Name for ButtonObjects and we need the SourceFileEntry pointer ...
	for ( t=0; t<m_listMenuObjects.count ( ); t++ )  {
		if ( m_listMenuObjects.at   ( t )->objectType ( ) == BUTTON_OBJECT )  {
			m_pActiveObject = m_listMenuObjects.at(t);
			emit ( signalRequestSourceFiles ( ) );
		}
	}
	return true;
}

MenuObject *MenuPreview::readObject (QDomNode &objectNode)
{
	// This function wil create an MenuObject-derived object
	// depending on the info from the QDomNode - object
	QDomElement theElement = objectNode.toElement ( );
	QString     tagName    = theElement.tagName   ( );
	QString     nodeText   = theElement.text      ( );

	// Okay, this is ugly but after all it is the simplest of all xml file structure.
	// No need to get fancy ...
	MenuObject *pNewObject = NULL;
	if      ( tagName == FRAME_OBJECT  )
		pNewObject = createFrameObject  ( false );
	else if ( tagName == MASK_OBJECT   )
	        pNewObject = new MaskObject     (  this );
	else if ( tagName == TEXT_OBJECT   )
		pNewObject = createTextObject   ( false );
	else if ( tagName == IMAGE_OBJECT  )
		pNewObject = createImageObject  ( false );
	else if ( tagName == MOVIE_OBJECT  )
		pNewObject = createMovieObject  ( false );
	else if ( tagName == BUTTON_OBJECT )	{
		pNewObject = createButtonObject ( false );
		// A small special handling for the Buttons ...
		// Funky, since the above function itself calls this function here ...
		((ButtonObject *)pNewObject)->readObjects ( objectNode, this );
	}
	else if ( tagName == OBJECT_COLLECTION )  {
		pNewObject = createObjectCollection (false);
		// A small special handling for the Buttons ...
		// Funky, since the above function itself calls this function here ...
		((ObjectCollection *)pNewObject)->readObjects(objectNode, this);
	}
	else if ( tagName == IGNORE_OBJECT )
		pNewObject = NULL;
	else
		printf ("Warning: MenuPreview::readObject -=> wrong XML Node <%s>\nContinuing ...\n",
				(const char *)tagName);
	// And finally, if we created a MenuObject, we also want to
	// add it to the list ...
	if (pNewObject)
		pNewObject->readProjectFile ( objectNode );
	// So lets get the next sibling ... until we hit hte end of DVDMenu ...
	return pNewObject;
}

bool MenuPreview::writeProjectFile (QDomElement &theElement)
{
	uint t;
	for (t=0;t<m_listMenuObjects.count();t++)	{
		if (!m_listMenuObjects.at(t)->writeProjectFile( theElement ))
			return false;
	}
	return true;
}

// The following slots will add a button to the Menu.
void MenuPreview::slotAddFrameObject()
{
  setMouseCursor ( MouseCrossCursor );	// signals to be awaiting the next mouse click
  // which will then generate the rectangle for this text button.
  m_iCreateObjectStyle = FrameType;
  m_iPointerState      = StateReadyToCreate;
}

void MenuPreview::slotAddTextObject()
{
  setMouseCursor ( MouseCrossCursor );	// signals to be awaiting the next mouse click
  // which will then generate the rectangle for this text button.
  m_iCreateObjectStyle = TextType;
  m_iPointerState      = StateReadyToCreate;
}

void MenuPreview::slotAddImageObject ()
{
  setMouseCursor ( MouseCrossCursor );	// signals to be awaiting the next mouse click
  // which will then generate the rectangle for this text button.
  m_iCreateObjectStyle = ImageType;
  m_iPointerState      = StateReadyToCreate;
}

void MenuPreview::slotAddMovieObject ()
{
  setMouseCursor ( MouseCrossCursor );	// signals to be awaiting the next mouse click
  // which will then generate the rectangle for this text button.
  m_iCreateObjectStyle = MovieType;
  m_iPointerState      = StateReadyToCreate;
}

void MenuPreview::slotAddCollection()
{
  setMouseCursor ( MouseCrossCursor );	// signals to be awaiting the next mouse click
  // which will then generate the rectangle for this text button.
  m_iCreateObjectStyle = CollectionType;
  m_iPointerState      = StateReadyToCreate;
}

void MenuPreview::slotAddFromLibrary ( )
{
  emit ( signalLibrary ( ) );
}

void MenuPreview::createAnimationData (QString &qsMenuName, long iMaxFrames)
{
  uint t, i, iCount=0;
  QFile     theFile;
  QFileInfo fileInfo;
  QString qsName;
  QString qsFileName, qsCommand, qsAnimation;
  MenuObject *pMainMenuObject = NULL;
  MenuObject *pMenuObject     = NULL;

  for ( t=0; t<m_listMenuObjects.count ( ); t++ )  {
    // First we check each object if m_qsAnimation is empty
    pMainMenuObject = m_listMenuObjects.at ( t );
    if ( ! pMainMenuObject )
      continue;
    for ( i=0; i<3; i++ )  {  // 0==MainObject / 1==ShadowObject / 2==OverlayObject
      if ( i == 0 )  {
        pMenuObject = pMainMenuObject;
        fileInfo.setFile ( pMainMenuObject->name ( ) );
        qsName = fileInfo.baseName ( );
      }
      else if ( i == 1 )  {
        pMenuObject = pMainMenuObject->shadow ( );
        qsName = "shadow";
      }
      else if ( i == 2 )  {
        pMenuObject = pMainMenuObject->overlay ( );
        if ( pMenuObject )  {
          ImageObject *p = (ImageObject *)pMenuObject;
          fileInfo.setFile ( p->fileName ( ) );
          qsName = fileInfo.baseName ( );
        }
      }
      if ( qsName.isEmpty ( ) )
           qsName = "Something";

      if ( ! pMenuObject || pMenuObject->animation ( ).isEmpty ( ) )
        continue;

      qsAnimation = pMenuObject->animation ( );
      // Next we check if the contents is a fileName (to the data file)
      if ( ( qsAnimation.length   ( )      < 1024 ) && 
           ( qsAnimation.contains ( "\n" ) <    2 )  ) {
        // Assume fileName
        fileInfo.setFile ( qsAnimation );
        if ( fileInfo.exists  ( ) )  {
          pMenuObject->loadAnimationData ( qsAnimation, iMaxFrames );
          continue;
        }
      }

      qsFileName=QString( "%1/%2/%3/%4_%5").arg ( Global::qsTempPath ).arg ( Global::qsProjectName ).arg ( qsMenuName ).arg ( qsName ).arg ( ++iCount );
      if ( isAnimationData ( qsAnimation ) ) {
        // Finally we assume it is a script to generate the data ...
        theFile.setName   ( qsFileName + QString ( ".dat" ) );
        if ( theFile.open ( IO_WriteOnly ) )  {
          QTextStream theStream ( &theFile );
          theStream << qsAnimation;
          theFile.close ( );
        }
      }
      else {
        // Finally we assume it is a script to generate the data ...
        theFile.setName   ( qsFileName + QString ( ".sh" ) );
        if ( theFile.open ( IO_WriteOnly ) )	{
          QTextStream theStream ( &theFile );
          theStream << qsAnimation;
          theFile.close ( );
        }
        // next we change the mode to executable ...
        chmod ( qsFileName + QString ( ".sh" ), 0777 );// S_IEXEC | S_IRUSR | S_IWRITE);
        qsCommand = QString ( "\"%1.sh\" 2>/dev/null > \"%2.dat\"" ).arg ( qsFileName ).arg ( qsFileName );
        //printf ( "%s::%s : %d <%s>\n", __FILE__, __FUNCTION__, __LINE__, qsCommand.ascii() );
        if ( system ( qsCommand ) == -1 )
          return;
      }
      qsFileName += QString ( ".dat" );
      // Check if the file has some size to it ...
      fileInfo.setFile  ( qsFileName );
      if ( fileInfo.size( ) < 1 )	{
        // TODO: write to the conversion log of this menu ...
        continue;
      }
      pMenuObject->loadAnimationData ( qsFileName, iMaxFrames );
    } // MainObjec / ShadowObject / OverlayObject
  }
}

bool MenuPreview::isAnimationData ( QString &qsAnimation )
{
  // Okay this is crude and bad but easy and fast ...
  QStringList list = QStringList::split ( "\n", qsAnimation );
  int t;
  QRegExp rx ( "^\\d*::" );

  for ( t=0; t<(int)list.count ( ); t++ ) {
    if ( list[t].length ( ) < 4 )
      continue;
    if ( list[t][0] == '#' )
      continue;
    if ( list[t].find ( rx ) > -1 ) 
      return true;
    else
      return false;
  }

  return false;
}

MenuObject *MenuPreview::createFrameObject(bool bShowDialog)
{
	FrameObject *pFrameObject = new FrameObject ( this );
	pFrameObject->setRect        ( m_rectCurrentObject );
	pFrameObject->setFrameWidth  ( 4 );
 	pFrameObject->setFrameColor  ( QColor ( START_FRAME_COLOR ) );
	if (bShowDialog)	{
		m_listMenuObjects.append ( pFrameObject );
		emit ( signalUpdateStructure ( ) );
		updatePixmap ( );
	}
	// Here we connect the signal to the slot ...
	connectStdSlots ( pFrameObject, true );
	undoBuffer ( )->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::NEW_OBJECT, pFrameObject ) );

	return pFrameObject;
}

MenuObject *MenuPreview::createTextObject ( bool bShowDialog )
{
	TextObject *pTextObject = NULL;
	if ( bShowDialog )  {
		DialogTextFont fontDialog ( this );
		fontDialog.setRect   (   m_rectCurrentObject  );
		if ( fontDialog.exec ( ) == QDialog::Rejected )
			return NULL;

		pTextObject    = new TextObject (  this  );
		QString qsText = fontDialog.getText (    );
		pTextObject->setText            ( qsText );
//		pTextObject->setRect            ( m_rectCurrentObject );
		pTextObject->setRect            ( fontDialog.getRect ( ) );
		pTextObject->setFont            ( fontDialog.getFont ( ) );
		pTextObject->setAnimation       ( fontDialog.getAnimation ( ) );
		pTextObject->setTextAlign       ( fontDialog.getTextAlign ( ) );
		pTextObject->setBackgroundColor ( fontDialog.getBackgroundColor ( ) );
		pTextObject->setForegroundColor ( fontDialog.getForegroundColor ( ) );
		pTextObject->modifiers ( )->fTransparency = fontDialog.getTransparency ( );
		// Checks wether the user wants to fit the size of the button to the text or not.
		if ( fontDialog.getFit ( ) )  {
			QRect rect = pTextObject->rect ( );
			rect.setWidth  ( 1 );
			rect.setHeight ( 1 );
			pTextObject->setRect      ( rect  );
			pTextObject->setWordBreak ( false ); // allows to keep the line intact
		}
		m_listMenuObjects.append     ( pTextObject );
		emit ( signalUpdateStructure ( ) );

		QRect orig = pTextObject->rect ( );
		updatePixmap ( );
		pTextObject->update   ( );
		if ( rect ( )  !=  orig )  {  // if the rect has changed ...
		  updatePixmap        ( );
		  pTextObject->update ( );
		}
		pTextObject->setWordBreak ( true );
	}
	else
		pTextObject = new TextObject ( this );

	// Here we connect the signal to the slot ...
	connectStdSlots ( pTextObject, true );
	undoBuffer ( )->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::NEW_OBJECT, pTextObject ) );
	return pTextObject;
}

MenuObject *MenuPreview::createImageObject(bool bShowDialog)
{
	ImageObject *pImageObject = NULL;

	if (bShowDialog)	{
	  // The first step is to get the image name
	  QString qsImageFilter = Global::pApp->getImageFilter ( ); //"*.jpg *.jpeg *.png *.xbm *.bmp *.JPG *.JPEG *.PNG *.XBM *.BMP";

	  //	  QString qsImageName = QFileDialog::getOpenFileName(Global::qsCurrentPath, tr("Image Files (*.jpg *.jpeg *.png *.xbm *.bmp *.JPG *.JPEG *.PNG *.XBM *.BMP)"), this,
	  QString qsImageName = FilePreviewDialog::getOpenFileName ( NULL, Global::qsCurrentPath, QString ("Images ( ") + qsImageFilter + QString (" );;All ( * )"), this, 
	      tr("Select image"), tr("Select a image object."));
	  if (qsImageName.isNull())
	    return NULL;

	  QFileInfo fileInfo  (qsImageName);
	  Global::qsCurrentPath = fileInfo.dirPath ( TRUE );

	  // Here we create the Pixmap in the right scale
	  QImage theImage (qsImageName);
	  int iWidth, iHeight;
	  float fZoom;
	  // Keep aspect ratio
	  iWidth  = m_rectCurrentObject.width();
	  iHeight = (int)((float)theImage.height()/theImage.width()*m_rectCurrentObject.width());
	  fZoom = ((float)m_rectCurrentObject.width() / theImage.width());
	  // Convert the image and generate the Pixmap
	  theImage = theImage.smoothScale (iWidth, iHeight);	//, QImage::ScaleMin);
	  // And here we adopt the rect the user has drawn.
	  m_rectCurrentObject.setHeight ( iHeight );
	  // Finally we create the ImageObject
	  pImageObject = new ImageObject( this );
	  pImageObject->setRect  ( m_rectCurrentObject );
	  pImageObject->setZoom  ( fZoom       );  // We want to say Zoom = 1.0 even if the original size is already zoomed.
	  pImageObject->setFile  ( qsImageName );
	  pImageObject->setImage ( theImage    );

	  m_listMenuObjects.append ( pImageObject );
	  emit (signalUpdateStructure ( ) );
	  updatePixmap ( );
	}
	else
	  pImageObject = new ImageObject (this);
	
	// And last we connect the signals
	connectStdSlots ( pImageObject, true );
	undoBuffer ( )->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::NEW_OBJECT, pImageObject ) );

	return pImageObject;
}

MenuObject *MenuPreview::createMovieObject(bool bShowDialog)
{
  MovieObject *pMovieObject = NULL;

  if (bShowDialog)	{
    QPixmap thePixmap;
    // The first step is to get the movie name
    // to speed things up we create a dummyMediaInfo first
    MediaInfo *pMediaInfo = (MediaInfo *) new DummyInfo ();
    QString qsFilter = tr ("Movie Files (%1)").arg(pMediaInfo->getExtensions (true));

    //QString qsMovieName = QFileDialog::getOpenFileName(Global::qsCurrentPath, qsFilter, this, 
    //	tr("Select movie"), tr("Select a movie object."));
    QString qsMovieName = FilePreviewDialog::getOpenFileName ( NULL, Global::qsCurrentPath, QString ("Movies ( ") + qsFilter + QString (" );;All ( * )"), this, tr ( "Select image" ), tr ( "Select a image object." ) );
    if ( qsMovieName.isNull ( ) )
      return NULL;
    QCursor myCursor (QCursor::WaitCursor);
    setCursor (myCursor);
    // Here we need to get a screenshot, thus the dummy won't do !!!
    delete pMediaInfo;

    QFileInfo fileInfo  (qsMovieName);
    Global::qsCurrentPath = fileInfo.dirPath ( TRUE );

    // Here we create the Pixmap in the right scale
    QImage theImage = QImage().fromMimeSource("please_wait.jpg");

    int   iHeight;
    QSize theSize = m_rectCurrentObject.size();
    theImage = theImage.smoothScale (theSize, QImage::ScaleFree);
    // Keep aspect ratio
    iHeight = (int)((float)theImage.height()/theImage.width()*m_rectCurrentObject.width());
    thePixmap.convertFromImage(theImage);
    // Clear memory ...
    theImage = QImage ();
    // And here we adopt the rect the user has drawn.
    m_rectCurrentObject.setHeight(iHeight);
    // Finally we create the ImageObject
    pMovieObject = new MovieObject (this);
    pMovieObject->setRect     (m_rectCurrentObject);
    pMovieObject->setZoom     (1.0f); // We want to say Zoom = 1.0 even if the original size is already zoomed.
    pMovieObject->setFile     (qsMovieName);
    pMovieObject->setPixmap   (thePixmap);
    pMovieObject->setMovieSize(theSize);

    m_listMenuObjects.append  ( pMovieObject );
    emit ( signalUpdateStructure ( ) );
    updatePixmap ( );

    // Next we register to receive a preview image of the movie file ...
    MediaCreator::registerWithMediaScanner (pMovieObject, qsMovieName, pMovieObject->previewImage());

    // We need this to obtain a pointer to the assoziated DVDMenu ...
    emit (signalCreatedMovieObject (pMovieObject, true)); // inclusive render request ...

    myCursor = QCursor(QCursor::ArrowCursor);
    setCursor (myCursor);
  }
  else	{
    pMovieObject = new MovieObject (this);
    // We need this to obtain a pointer to the assoziated DVDMenu ... But no render request ...
    emit (signalCreatedMovieObject (pMovieObject, false));
  }

  // And last we connect the signals
  connectStdSlots ( pMovieObject, true );
  undoBuffer ( )->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::NEW_OBJECT, pMovieObject ) );
  return pMovieObject;
}

MenuObject *MenuPreview::createButtonObject(bool bShowDialog)
{
  ButtonObject *pButtonObject = new ButtonObject (this);

  if (bShowDialog)	{
    m_listMenuObjects.append (pButtonObject);
    emit ( signalUpdateStructure ( ) );
    updatePixmap ( );
  }

  // And finally we connect everything ...
  connectStdSlots ( pButtonObject, true );
  undoBuffer ( )->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::NEW_OBJECT, pButtonObject ) );

  return pButtonObject;
}

MenuObject *MenuPreview::createObjectCollection(bool)
{
	MessageBox::warning (NULL, tr ("Not Implemented yet."), tr ("createObjectCollection : Not Implemented yet."),
		QMessageBox::Ok ,  QMessageBox::Cancel);
	updatePixmap();
	return NULL;
}

void MenuPreview::setVisibleRegion (bool bVisibleOn)
{
	m_bDrawVisibleRegion = bVisibleOn;
	updatePixmap ();
}

void MenuPreview::slotDefineAsButton ( MenuObject *pTheObject )
{
  defineAsButton ( pTheObject, true );
}

ButtonObject *MenuPreview::defineAsButton ( MenuObject *pTheObject, bool bShowDialog )
{
	if ( ! pTheObject )
		return NULL;
	// This is interesting ...
	// first we need to create a ButtonObject,
	// which we then furnish with three copies of this TextObject
	// Namely: Normal, Selected, and Highlighted ...
	m_listMenuObjects.remove ( pTheObject );
	pTheObject->resetStructureItem ( );

	ButtonObject *pButtonObject = new ButtonObject ( this );
	// Now we generate two copies ...
	MenuObject *pNewSelected, *pNewHighlighted;

	Rgba colorTransparent ( TRANSPARENT_COLOR       );
 	Rgba colorHighlighted ( START_HIGHLIGHTED_COLOR );
	Rgba colorSelected    ( START_SELECTED_COLOR    );
	Rgba colorSpare       ( TRANSPARENT_COLOR       );
	if ( m_pPgcColors )   {
		colorTransparent = m_pPgcColors[0];
 		colorHighlighted = m_pPgcColors[1];
		colorSelected    = m_pPgcColors[2];
		colorSpare       = m_pPgcColors[3];
	}

	pNewSelected = pNewHighlighted = NULL;
	if ( pTheObject->objectType ( ) == TEXT_OBJECT )  {
		pNewSelected    = pTheObject->clone ( );
		pNewHighlighted = pTheObject->clone ( );
		// Only the 'normal' object should have a shadow
		pNewSelected   ->setShadow ( NULL );
		pNewHighlighted->setShadow ( NULL );
		// Next we give some color differences for the different states (TextObjects)
		((TextObject *)(pNewSelected))   ->setForegroundColor ( colorSelected    );
		((TextObject *)(pNewHighlighted))->setForegroundColor ( colorHighlighted );
		// Also here we ensure that the Textbackground for selected / highlighted is always transparent
		// The background color has already been put onto the actual background image.
		((TextObject *)(pNewSelected))   ->setBackgroundColor ( colorTransparent );
		((TextObject *)(pNewHighlighted))->setBackgroundColor ( colorTransparent );
		// The layers should not be aliased ...
		((TextObject *)(pNewSelected))   ->setStyleStrategy   ( QFont::NoAntialias );
		((TextObject *)(pNewHighlighted))->setStyleStrategy   ( QFont::NoAntialias );
		// And finally we do not want transparency (yet)
		((TextObject *)(pNewSelected))   ->modifiers()->fTransparency = 0.0f;
		((TextObject *)(pNewHighlighted))->modifiers()->fTransparency = 0.0f;
	}
	else	{// All but Text Objects get a frame for starters
		// Okay we want 1:1 for FrameObjects
		if (pTheObject->objectType() == FRAME_OBJECT )  {
			pNewSelected    = pTheObject->clone();
			pNewHighlighted = pTheObject->clone();
		}
		else	{  // for ImageObject, and MovieObject a standard frame
			pNewSelected    = new FrameObject;
			pNewHighlighted = new FrameObject;
			pNewSelected->setRect        (  pTheObject->rect      ( ) );
			pNewHighlighted->setRect     (  pTheObject->rect      ( ) );
			pNewSelected->setModifiers   ( *pTheObject->modifiers ( ) );
			pNewHighlighted->setModifiers( *pTheObject->modifiers ( ) );
			((FrameObject *)(pNewSelected))->setFrameWidth       ( 10 );
			((FrameObject *)(pNewHighlighted))->setFrameWidth    ( 10 );
		}
		// Next we give some color to the different states
		((FrameObject *)(pNewSelected))   ->setFrameColor ( colorSelected    );
		((FrameObject *)(pNewHighlighted))->setFrameColor ( colorHighlighted );
	}
	pButtonObject->appendNormal      ( pTheObject      );
	pButtonObject->appendSelected    ( pNewSelected    );
	pButtonObject->appendHighlighted ( pNewHighlighted );

	pButtonObject->setName ( newButtonName ( ) );
	// Next we should give the button the same attributes as the NormalState ...
	// rect and boundingRect are taken care of in drawContent
	pButtonObject->setModifiers ( *pTheObject->modifiers ( ) );

	// and here we append the button object as a new item in the MenuObject list.
	m_listMenuObjects.append ( pButtonObject );
	m_pActiveObject = NULL;

	if ( bShowDialog ) {
	  // Create the buttonDialog, so the user can change things around ...
	  slotCreateButtonDialog ( pButtonObject );
	  if ( m_pDialogButton )
	       m_pDialogButton->setButtonCreation ( true );
	}
	// And finally we connect everything ...
	connectStdSlots ( pButtonObject, true );
	return pButtonObject;
}

void MenuPreview::slotCreateButtonDialog ( ButtonObject *pButtonObject )
{
	uint t;
	// Here we generate a list of all Buttons in the current Menu. This is needed in the ButtonDialog
	// to  offer a list of possible targets.
	QStringList listMenuButtons;
	ButtonObject tempButton;

	for (t=0;t<m_listMenuObjects.count();t++)	{
		if (m_listMenuObjects.at(t)->objectType() == tempButton.objectType())	{
			listMenuButtons.append(m_listMenuObjects.at(t)->name());
		}
	}

	// Second step is to invoke the ButtonDialog ...
	m_pDialogButton = new DialogButton ( this );
	m_pDialogButton->initMe ( pButtonObject, this );
	m_pDialogButton->setMenuButtons   ( listMenuButtons );
	m_pDialogButton->show ( );
	connect ( m_pDialogButton, SIGNAL ( signalUpdateStructure ( ) ), this, SLOT ( slotUpdateStructure       ( ) ) );
	connect ( m_pDialogButton, SIGNAL ( signalUpdatePixmap    ( ) ), this, SLOT ( slotUpdatePixmap          ( ) ) );
	connect ( m_pDialogButton, SIGNAL ( destroyed             ( ) ), this, SLOT ( slotDestroyedButtonDialog ( ) ) );

	m_pActiveObject = NULL;
	// Go to DVDAuthor::slotRerquestSourceFiles.
	// Will return to respondSourceFiles() ...
	emit ( signalRequestSourceFiles ( ) );
	// Will return to respondSubMenus() ...
	emit ( signalRequestSubMenus ( ) );
	emit ( signalUpdateStructure ( ) );
}

void MenuPreview::respondSourceFiles (QValueList<SourceFileEntry *>listSourceFileEntries)
{
	// If m_pActiveObject is set this means that we called for the SourceFileList from
	// readObject ...
	if (m_pActiveObject)	{
		ButtonObject *pCreatedButton = (ButtonObject *)m_pActiveObject;
		// Here we connect the Button, which was created in readObject
		uint t;
		for (t=0;t<listSourceFileEntries.count();t++)	{
//			QString qs = pCreatedButton->sourceDisplayName();
// printf ("MenuPreview::respondSourceFiles <%s>\n", (const char *)pCreatedButton->sourceDisplayName());
			if (listSourceFileEntries[t]->qsDisplayName == pCreatedButton->sourceDisplayName())	{
				pCreatedButton->setSourceFileEntry(listSourceFileEntries[t]);
				break;
			}
		}
		// And set this one to NULL
		m_pActiveObject = NULL;
	}
	// First check if this was triggered from slotCreateButtonDialog
	else if ( m_pDialogButton )
	 	  m_pDialogButton->setSourceFiles(listSourceFileEntries);
}

void MenuPreview::respondSubMenus (QStringList listSubMenus)
{
	// Okay, this is the return of the above emit(signalRequestSubMenus()) - call
	// Coming back from DVDMenu::slotRequestSubMenus()
	if (!m_pDialogButton)
		return;
	m_pDialogButton->setSubMenus(listSubMenus);
}

void MenuPreview::slotDestroyedButtonDialog()
{
  // The Button dialog was destroyed. So we should set the pointer to NULL;
  m_pDialogButton = NULL;
}

void MenuPreview::slotUpdateStructure ( )
{
  // simply passes this call on to CDVDMenu ...
  emit ( signalUpdateStructure ( ) );
}

void MenuPreview::slotUpdatePixmap ( )
{
  updatePixmap ( );
}

void MenuPreview::slotUndoObject ( MenuObject *pObject )
{
  printf ( "%s::%s::%d > pObject<%p>\n", __FILE__, __FUNCTION__, __LINE__, pObject );
}

void MenuPreview::slotDeleteObject ( MenuObject *pObject )
{
	// simply do the same as the base class but also update the structureView ...
	ButtonPreview::slotDeleteObject ( pObject );
	updatePixmap ( );
	emit ( signalUpdateStructure ( ) );
}

void MenuPreview::slotAddOverlay ( MenuObject *pObject )
{
  QPixmap thePixmap ( m_backgroundPixmap );
  if ( m_backgroundPixmap.isNull ( ) )
    thePixmap = QPixmap ( 720, 480 );

  // Here we create the background without the current object
  // (we want to move that one around right ?)
  QPainter thePainter(&thePixmap);
  if ( pObject == &m_selectionObject ) {
    for ( uint t=0; t<m_listMenuObjects.count ( ); t++ )  {
      if ( ! m_selectionObject.contains ( m_listMenuObjects.at ( t ) ) )
             m_listMenuObjects.at ( t )->drawContents ( &thePainter );
    }
  }
  else {
    for (  uint t=0; t<m_listMenuObjects.count ( ); t++ )  {
      if ( m_listMenuObjects.at ( t ) != pObject )
           m_listMenuObjects.at ( t )->drawContents ( &thePainter );
    }
  }

  UndoObject *pUndo = new DVDMenuUndoObject ( DVDMenuUndoObject::NEW_OVERLAY, pObject, pObject->overlay ( ) );
  DialogOverlay dialog ( this );
  dialog.initMe        ( pObject,    &thePixmap );
  if ( dialog.exec     ( ) == QDialog::Rejected )  {
    delete pUndo;
    return;
  }
  undoBuffer ( )->push ( pUndo );

  updatePixmap ( );
  Global::pApp->slotUpdateStructure ( );
}

void MenuPreview::slotAddShadow ( MenuObject *pObject )
{
  QPixmap thePixmap ( m_backgroundPixmap );
  if ( m_backgroundPixmap.isNull ( ) )
    thePixmap = QPixmap ( 720, 480 );

  // Here we create the background without the current object
  // (we want to move that one around right ?)
  QPainter thePainter ( &thePixmap );
  if ( pObject == &m_selectionObject ) {
    for ( uint t=0; t<m_listMenuObjects.count ( ); t++ )  {
      if ( ! m_selectionObject.contains ( m_listMenuObjects.at ( t ) ) )
             m_listMenuObjects.at ( t )->drawContents ( &thePainter );
    }
  }
  else {
    for (  uint t=0; t<m_listMenuObjects.count ( ); t++ )  {
      if ( m_listMenuObjects.at ( t ) != pObject )
           m_listMenuObjects.at ( t )->drawContents ( &thePainter );
    }
  }

  UndoObject *pUndo = new DVDMenuUndoObject ( DVDMenuUndoObject::NEW_SHADOW, pObject, pObject->shadow ( ) );
  DialogShadow dialog ( this );
  dialog.initMe       ( pObject,    &thePixmap );
  if ( dialog.exec    ( ) == QDialog::Rejected )  {
    delete pUndo;
    return;
  }
  undoBuffer ( )->push ( pUndo );

  updatePixmap ( );
  Global::pApp->slotUpdateStructure ( );
}

void MenuPreview::slotModifyObject ( MenuObject *pObject )
{
  QPixmap thePixmap ( m_backgroundPixmap );
  if ( m_backgroundPixmap.isNull ( ) )
    thePixmap = QPixmap ( 720, 480 );

  // Here we create the background without the current object
  // (we want to move that one around right ?)
  QPainter thePainter(&thePixmap);
  for ( uint t=0; t<m_listMenuObjects.count ( ); t++ )  {
    if ( m_listMenuObjects.at ( t ) != pObject)
         m_listMenuObjects.at ( t )->drawContents ( &thePainter );
  }

  undoBuffer ( )->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::EDIT_OBJECT, pObject->shadow ( ) ) );

  ImageObject *pImageObject = (ImageObject *)pObject;
  DialogImage2 dialog ( this );
  dialog.initMe       ( pImageObject, &thePixmap );
  if (   dialog.exec  ( )  ==  QDialog::Rejected )
    return;

  if ( ! pObject->shadow ( ) )  {
    // If the user deletes the Shadow, then we should change EDIT_OBJECT to DELETED_OBJECT
    DVDMenuUndoObject *pUndo = (DVDMenuUndoObject *) undoBuffer ( )->last ( );
    if ( pUndo )
         pUndo->changeType ( DVDMenuUndoObject::DELETED_SHADOW );
  }

  updatePixmap ( );
}

void MenuPreview::slotAlignSelection ( )
{
  QPixmap thePixmap ( m_backgroundPixmap );
  if ( m_backgroundPixmap.isNull ( ) )
    thePixmap = QPixmap ( 720, 480 );

  // Here we create the background without the current object
  // (we want to move that one around right ?)
  int t;
  QPainter thePainter(&thePixmap);
  QPtrList <MenuObject> listOfObjectsToDraw;
  listOfObjectsToDraw = m_listMenuObjects;

  for ( t=0; t<m_selectionObject.getCount ( ); t++ )
    listOfObjectsToDraw.remove ( m_selectionObject.getObject ( t ) );

  for ( t=0; t<(int)listOfObjectsToDraw.count ( ); t++ )
    listOfObjectsToDraw.at ( t )->drawContents ( &thePainter );

  DialogAlign theDialog ( this );
  theDialog.initMe ( &m_selectionObject, &thePixmap );
  theDialog.exec   ( );
}

void MenuPreview::slotUnbutton ( ButtonObject *pButton )
{
  uint t=0;
  MenuObject *pObject = NULL;
  // First we disconnect the button from this MenuPreview
  //disconnect ( pButton );
  m_listMenuObjects.remove    ( pButton );
  pButton->resetStructureItem ( );

  for ( t=0; t<pButton->getNormalCount ( ); t++ )  {
    // The we grab the Normal-Object from the ButtonObject
    pObject =  pButton->getNormal ( t );
    pButton->removeNormal   ( pObject );
    // And add the object to this MenuPreview.
    pObject->setCurrentMousePos ( pButton->currentMousePos ( ) );
    m_listMenuObjects.append( pObject );
    pObject->disconnect ( );
    // The StructureItem's parent is currently the ButtonObject. So deleting the button would crash the app
    pObject->resetStructureItem   ( );
    connectStdSlots ( pObject, true );
  }
  // Finally we can delete the button object.
//  delete pButton;
  if ( pButton && pObject )  {
       undoBuffer ( )->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::UNBUTTON, pButton, pObject ) );
  }
  emit ( signalUpdateStructure ( ) );
}

void MenuPreview::slotDeleteMenu ( )
{
	// This function is called when the user wants to delete the current DVDMenu.
	// It passes the request right through to the QDVDAuthor - class
	// NOTE: the timer ensures that we get out of mousePressEvent before deleting this objcet.
	QTimer::singleShot (500, this, SLOT(slotEmitDeleteMe()));
}

void MenuPreview::slotEmitDeleteMe()
{
	emit ( signalDeleteMe ( ) );
}

void MenuPreview::slotRenameMenu()
{
	// This function is called when the user wants to change the name of this SubMenu.
	// It passes the request right through to the main QDVDAuthor class.
	emit ( signalRenameMe ( ) );
}

void MenuPreview::slotCloneMenu()
{
	// This function is called when the user wants to change the name of this SubMenu.
	// It passes the request right through to the main QDVDAuthor class.
	emit ( signalCloneMe ( ) );
}

void MenuPreview::slotConvertToPAL ( )
{
	// This function is called when the user wants to convert the current menu to PAL
	// It passes the request right through to the main QDVDAuthor class.
	emit ( signalConvertMe ( true ) );
}

void MenuPreview::slotConvertToNTSC ( )
{
	// This function is called when the user wants to convert the current menu to NTSC
	// It passes the request right through to the main QDVDAuthor class.
	emit ( signalConvertMe ( false ) );
}

QString &MenuPreview::newButtonName()
{
  // This function searches the existing Buttons for it's names and picks the first name which is not in use.
  uint t, iButtonNr;
  bool bContinue = true;
  iButtonNr = 2;
  ButtonObject tempButton;
  static QString qsButtonName;
  qsButtonName = QString ("Button 1");
  while (bContinue)	{
    bContinue = false;	// default is the assumption we won't find the same name, thus exit after ...
    for (t=0;t<m_listMenuObjects.count();t++)	{
      if (m_listMenuObjects.at(t)->objectType() == tempButton.objectType())	{
	if (m_listMenuObjects.at(t)->name () == qsButtonName)	{
	  qsButtonName = QString ("Button %1").arg(iButtonNr++);
	  bContinue = true;	// crap, got to do it again ...
	  break;
	}
      }
    }
  }
  return qsButtonName;
}

QString MenuPreview::uniqueObjectName ( QString qsPrefix, QString qsSuffix )
{
  uint t, iCounter;
  bool bContinue = true;
  QString qsObjectName;

  iCounter = 1;
  qsObjectName = QString ("%1 %2").arg ( qsPrefix ).arg( qsSuffix );
  while ( bContinue )	{
    bContinue = false;	// default is the assumption we won't find the same name, thus exit after ...
    for ( t=0; t<m_listMenuObjects.count(); t++ )  {
      if ( m_listMenuObjects.at ( t )->name ( ) == qsObjectName )  {
	qsObjectName = QString ("%1(%2) %3").arg ( qsPrefix ).arg ( iCounter++).arg ( qsSuffix );
	bContinue = true;	// crap, got to do it again ...
	break;
      }
    }
  }

  return qsObjectName;
}

void MenuPreview::connectStdSlots (MenuObject *pObject, bool bAddExtraSlots )
{
  //printf ( "%s::%s::%d count<%d> obj<%p>\n", __FILE__, __FUNCTION__, __LINE__, m_listMenuObjects.count ( ), pObject );
  connect (pObject, SIGNAL ( signalUpdateStructure( ) ),                this, SLOT ( slotUpdateStructure( ) ) );
  connect (pObject, SIGNAL ( signalUpdatePixmap   ( ) ),                this, SLOT ( slotUpdatePixmap   ( ) ) );
  connect (pObject, SIGNAL ( signalDefineAsButton ( MenuObject *   ) ), this, SLOT ( slotDefineAsButton ( MenuObject *   ) ) );
  connect (pObject, SIGNAL ( signalDeleteMe       ( MenuObject *   ) ), this, SLOT ( slotDeleteObject   ( MenuObject *   ) ) );
  connect (pObject, SIGNAL ( signalUndoMe         ( MenuObject *   ) ), this, SLOT ( slotUndoObject     ( MenuObject *   ) ) );
  connect (pObject, SIGNAL ( signalShadowMe       ( MenuObject *   ) ), this, SLOT ( slotAddShadow      ( MenuObject *   ) ) );
  connect (pObject, SIGNAL ( signalOverlayMe      ( MenuObject *   ) ), this, SLOT ( slotAddOverlay     ( MenuObject *   ) ) );
  connect (pObject, SIGNAL ( signalMoveOnStack    ( MenuObject *,int) ),this, SLOT ( slotMoveOnStack    ( MenuObject *, int ) ) );
  connect (pObject, SIGNAL ( signalAnimateMe      ( QString &, int, QString ) ), this, SLOT ( slotAnimateObject  ( QString &, int, QString ) ) );
  if ( bAddExtraSlots ) {
    uint i;
    if ( pObject->objectType ( ) == BUTTON_OBJECT )  {
      ButtonObject *pButton = (ButtonObject *)pObject;
      for ( i=0; i < pButton->getNormalCount ( ) ; i++ )  {
	MenuObject *pObject = pButton->getNormal ( (int)i );
	pObject->disconnect ( );
	connectStdSlots ( pObject, false );
      }
      for ( i=0; i<pButton->getSelectedCount ( ) ; i++ )
	connect (  pButton->getSelected     ( i ), SIGNAL ( signalDeleteMe (MenuObject *) ), this, SLOT(slotDeleteObject (MenuObject *) ) );
      for ( i=0; i<pButton->getHighlightedCount ( ) ; i++ )
	connect (  pButton->getHighlighted  ( i ), SIGNAL ( signalDeleteMe (MenuObject *) ), this, SLOT(slotDeleteObject (MenuObject *) ) );

      connect ( pButton, SIGNAL(signalUnbuttonMe(ButtonObject *)), this, SLOT(slotUnbutton(ButtonObject *)));
      connect ( pButton, SIGNAL(signalCreateButtonDialog(ButtonObject *)), this, SLOT(slotCreateButtonDialog(ButtonObject *)));
    }
    else if ( ( pObject->objectType ( ) == IMAGE_OBJECT ) ||
              ( pObject->objectType ( ) == MOVIE_OBJECT ) )
      connect ( pObject, SIGNAL ( signalModifyMe (MenuObject *) ), this, SLOT ( slotModifyObject (MenuObject *) ) );
  }
}

