/****************************************************************************
** dvdmenu.cpp file.
**
**   Created :
**        by : Varol Okan
** Copyright : (c) Varol Okan
**   License : GPL v 2.0
**
** This is the main class for the DVDMenu.
**
*****************************************************************************/
#include <stdlib.h>	// for system ()

#include <qdesktopwidget.h>
#include <qapplication.h>
#include <qfiledialog.h>
#include <qtabwidget.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include <qpainter.h>
#include <qmenubar.h>
#include <qaction.h>
#include <qlayout.h>
#include <qcursor.h>
#include <qimage.h>
#include <qtimer.h>
#include <qdom.h>

#include "xml_dvd.h"
#include "dvdmenu.h"
#include "mediainfo.h"
#include "qdvdauthor.h"
#include "messagebox.h"
#include "textobject.h"
#include "dialogmovie.h"
#include "menupreview.h"
#include "movieobject.h"
#include "frameobject.h"
#include "cachethumbs.h"
#include "dialogresize.h"
#include "qimagehelper.h"
#include "buttonobject.h"
#include "xml_slideshow.h"
#include "dialoganimation.h"
#include "sourcefileentry.h"
#include "objectcollection.h"
#include "structuretoolbar.h"
#include "dvdmenuundoobject.h"
#include "filepreviewdialog.h"
#include "dialogcreatetemplate.h"
#include "uidialogrenderpreview.h"
#include "qrender/startmenurender.h"
#include "qplayer/engines/dummywidget.h"

//////////////////////////////////////////////////////////////
//
// The Interface class ...
//
//////////////////////////////////////////////////////////////

CDVDMenuInterface::CDVDMenuInterface ()
{
	initMe ();
}

CDVDMenuInterface::~CDVDMenuInterface ()
{
  unsigned int t;
  for ( t=0; t<listSoundEntries.count ( ); t++ )
    delete listSoundEntries[t];
  listSoundEntries.clear ( );

  for ( t=0; t<listIntroVobs.count ( ); t++ ) 
    delete listIntroVobs[t];
  listIntroVobs.clear ( );

  for ( t=0; t<listExtroVobs.count ( ); t++ ) 
    delete listExtroVobs[t];
  listExtroVobs.clear ( );
}

void CDVDMenuInterface::initMe ()
{
        uint t;
	bModified                 = false;
	bIsSubMenu                = false;
	bMovieBackgroundHasSound  = false;
	qsBackgroundFileName      = QString ("");
	qsMovieFileName           = QString ("");
	qsMenuName                = QString (VMGM_LABEL);
	qsResizeAlgo              = QString (QT_RESIZE_ALGO);
	qsAnimation               = QString ("");
	iStretchType              = StretchToFit;
	posOffset                 = QSize (0, 0);
	iFormat                   = FORMAT_NONE;
	iWidth                    = 0;
	iHeight                   = 0;
	qsRatio                   = QString ("4:3");
	iTitleset                 = -1;
	iMenu                     = -1;
	pgcColors[0]              = Rgba ( TRANSPARENT_COLOR       );
	pgcColors[1]              = Rgba ( START_HIGHLIGHTED_COLOR );
	pgcColors[2]              = Rgba ( START_SELECTED_COLOR    );
	pgcColors[3]              = Rgba ( START_FRAME_COLOR       );
	timeDuration              = timeDuration.fromString ("00:00:01");
	qsSelectedMaskFileName    = QString ("");
	qsHighlightedMaskFileName = QString ("");
	for (t=0;t< listIntroVobs.count();t++)
	  delete listIntroVobs[t];
	listIntroVobs.clear ();
	for (t=0;t< listExtroVobs.count();t++)
	  delete listExtroVobs[t];
	listExtroVobs.clear ();
}

///////////////////////////////////////////////
//
// This function loads the xml project file
// specified by the  user.
//
// The file specs are defined in xml_dvd.h
//
////////////////////////////////////////////////
bool CDVDMenuInterface::readProjectFile ( QDomNode &theNode, float fLoadVersion )
{
	QDomElement theElement;// = theNode.toElement();
	QString  tagName;// = theElement.tagName();
	QString  nodeText;// = theElement.text ();
	int      t;
	QDomAttr a;

	for ( t=0; t<(int)listSoundEntries.count ( ); t++ )
	  delete listSoundEntries[t];
	listSoundEntries.clear();
	QDomNode xmlMenuVariables = theNode.firstChild();
	while ( !xmlMenuVariables.isNull () )	{
		// Okay, here we retain the stored data from the xml file.
		theElement = xmlMenuVariables.toElement();
		tagName    = theElement.tagName();
		nodeText   = theElement.text ();
		// Okay, this is ugly but after all it is the simplest of all xml file structure.
		// No need to get fancy ...
		if (tagName == MENU_HIGHLIGHTED_MASK)
			qsHighlightedMaskFileName = nodeText;
		else if (tagName == MENU_SELECTED_MASK)
			qsSelectedMaskFileName = nodeText;
		else if (tagName == MENU_SOUND) {
		  //listSoundEntries.append (nodeText);
		  Audio      *pAudio   = NULL;
		  QDomNode    xmlAudio = theElement.firstChild ( );
		  while ( !xmlAudio.isNull ( ) )  {
		    pAudio = new Audio;
		    if ( fLoadVersion > 1.0101 )
		      pAudio->readProjectFile( xmlAudio );
		    else {
		      pAudio->qsFileName   = nodeText;
		      pAudio->qsIso639     = Global::qsDefaultLanguage;
		      pAudio->iAudioNumber = listSoundEntries.count( );
		    }
		    listSoundEntries.append  ( pAudio );
		    xmlAudio = xmlAudio.nextSibling ( );
		  }
		}
		else if (tagName == MENU_MOVIE)
			qsMovieFileName = nodeText;
		else if (tagName == MENU_OFFSET)
			timeOffset = timeOffset.fromString (nodeText);
		else if (tagName == MENU_DURATION)
			timeDuration = timeDuration.fromString (nodeText);
		else if (tagName == MENU_ANIMATION)
			qsAnimation = nodeText;
		else if (tagName == MENU_BACKGROUND)	{
			int iOffsetX, iOffsetY;
			iOffsetX = iOffsetY = 0;
			a = theElement.attributeNode ( MENU_RESIZE_ALGO );
			qsResizeAlgo = a.value();
			if (qsResizeAlgo.isEmpty())
				qsResizeAlgo = QString ( QT_RESIZE_ALGO );
			a = theElement.attributeNode ( MENU_STRETCH_TYPE );
			if (!a.value().isEmpty())
				iStretchType = a.value().toInt();
			a = theElement.attributeNode ( MENU_OFFSET_X );
			if (!a.value().isEmpty())
				iOffsetX = a.value().toInt();
			a = theElement.attributeNode ( MENU_OFFSET_Y );
			if (!a.value().isEmpty())
				iOffsetY = a.value().toInt();
			posOffset = QSize (iOffsetX, iOffsetY);
			qsBackgroundFileName = nodeText;
		}
		else if (tagName == MENU_MASK_COLORS)	{
		  QStringList listColors = QStringList::split (",", nodeText);
		  for ( uint t=0; t<listColors.count ( ); t++ )  {
		    if ( t>= MAX_MASK_COLORS )
		      continue;
		    pgcColors[t].fromString ( listColors[t] );
		  }
		}
		else if (tagName == MENU_NAME)
			qsMenuName = nodeText;
		else if (tagName == MENU_PRE)
			qsPre = nodeText;
		else if (tagName == MENU_PAUSE)
			qsPause = nodeText;
		else if (tagName == MENU_POST)
			qsPost = nodeText;
		else if (tagName == MENU_INTRO) {
		  CXmlDVDAuthor::vob_struct *pVob = NULL;
		  QDomNode    xmlIntro = theElement.firstChild();
		  QDomElement theIntro;
		  while ( !xmlIntro.isNull () )	{
		    pVob = new CXmlDVDAuthor::vob_struct;

		    theIntro = xmlIntro.toElement();
		    pVob->readXml ( &theIntro );
		    listIntroVobs.append ( pVob );
		    xmlIntro = xmlIntro.nextSibling ( );
		  }
		}
		else if (tagName == MENU_EXTRO) {
		  CXmlDVDAuthor::vob_struct *pVob = NULL;
		  QDomNode    xmlExtro = theElement.firstChild();
		  QDomElement theExtro;
		  while ( !xmlExtro.isNull () )	{
		    pVob = new CXmlDVDAuthor::vob_struct;

		    theExtro = xmlExtro.toElement();
		    pVob->readXml ( &theExtro );
		    listExtroVobs.append ( pVob );
		    xmlExtro = xmlExtro.nextSibling ( );
		  }
		}
		// So lets get the next sibling ... until we hit hte end of DVDMenu ...
		xmlMenuVariables = xmlMenuVariables.nextSibling();
	}
	bModified = false;
	return true;
}

bool CDVDMenuInterface::writeProjectFile (QDomElement &rootDVDMenu)
{
	QDomDocument xmlDoc = rootDVDMenu.ownerDocument();

	uint i;
	QDomElement tag;
	QString qsFormat ("hh:mm:ss.zzz");
	QDomText t;

	t = xmlDoc.createTextNode(qsBackgroundFileName);
	
	if (!qsHighlightedMaskFileName.isEmpty())	{
		tag = xmlDoc.createElement( MENU_HIGHLIGHTED_MASK );
		rootDVDMenu.appendChild( tag );
		t = xmlDoc.createTextNode(qsHighlightedMaskFileName);
		tag.appendChild( t );
	}
	if (!qsSelectedMaskFileName.isEmpty())	{
		tag = xmlDoc.createElement( MENU_SELECTED_MASK );
		rootDVDMenu.appendChild( tag );
		t = xmlDoc.createTextNode(qsSelectedMaskFileName);
		tag.appendChild( t );
	}
	if ( timeOffset.isValid())	{
		tag = xmlDoc.createElement( MENU_OFFSET );
		rootDVDMenu.appendChild( tag );
		t = xmlDoc.createTextNode(timeOffset.toString (qsFormat));
		tag.appendChild( t );
	}
	if (timeDuration.isValid())	{
		tag = xmlDoc.createElement( MENU_DURATION );
		rootDVDMenu.appendChild( tag );
		t = xmlDoc.createTextNode(timeDuration.toString (qsFormat));
		tag.appendChild( t );
	}
	if ( ! qsAnimation.isEmpty())	{
		tag = xmlDoc.createElement( MENU_ANIMATION );
		rootDVDMenu.appendChild( tag );
		t = xmlDoc.createTextNode(qsAnimation);
		tag.appendChild( t );
	}
	if ( listSoundEntries.count ( ) != 0 )  {
	  tag = xmlDoc.createElement ( MENU_SOUND );
	  for ( i=0; i<listSoundEntries.count ( ); i++ )
	    listSoundEntries[i]->writeProjectFile ( tag );
	  rootDVDMenu.appendChild ( tag );
	}
	if (!qsMovieFileName.isEmpty())	{
		tag = xmlDoc.createElement( MENU_MOVIE );
		rootDVDMenu.appendChild( tag );
		t = xmlDoc.createTextNode(qsMovieFileName);
		tag.appendChild( t );
	}
	if (!qsBackgroundFileName.isEmpty())	{
		tag = xmlDoc.createElement( MENU_BACKGROUND );
		rootDVDMenu.appendChild( tag );
		t = xmlDoc.createTextNode(qsBackgroundFileName);
		tag.setAttribute ( MENU_RESIZE_ALGO, qsResizeAlgo );
		tag.setAttribute ( MENU_STRETCH_TYPE, QString ("%1").arg(iStretchType));
		tag.setAttribute ( MENU_OFFSET_X, QString ("%1").arg(posOffset.width ()));
		tag.setAttribute ( MENU_OFFSET_Y, QString ("%1").arg(posOffset.height()));
		tag.appendChild  ( t );
	}
	if (!qsMenuName.isEmpty())	{
		tag = xmlDoc.createElement( MENU_NAME );
		rootDVDMenu.appendChild( tag );
		t = xmlDoc.createTextNode(qsMenuName);
		tag.appendChild( t );
	}
	if (!qsPre.isEmpty())	{
		tag = xmlDoc.createElement( MENU_PRE );
		rootDVDMenu.appendChild( tag );
		t = xmlDoc.createTextNode(qsPre);
		tag.appendChild( t );
	}
	if (!qsPause.isEmpty())	{
		tag = xmlDoc.createElement( MENU_PAUSE );
		rootDVDMenu.appendChild( tag );
		t = xmlDoc.createTextNode(qsPause);
		tag.appendChild( t );
	}
	if (!qsPost.isEmpty())	{
		tag = xmlDoc.createElement( MENU_POST );
		rootDVDMenu.appendChild( tag );
		t = xmlDoc.createTextNode(qsPost);
		tag.appendChild( t );
	}
	if ( listIntroVobs.count() > 0 ) {
		tag = xmlDoc.createElement( MENU_INTRO );
		rootDVDMenu.appendChild( tag );
		for (i=0;i<listIntroVobs.count();i++)
		  listIntroVobs[i]->writeXml (&xmlDoc, &tag);
	}
	if ( listExtroVobs.count() > 0 ) {
		tag = xmlDoc.createElement( MENU_EXTRO );
		rootDVDMenu.appendChild( tag );
		for (i=0;i<listExtroVobs.count();i++)
		  listExtroVobs[i]->writeXml (&xmlDoc, &tag);
	}
	// Here we take care of the mask colors
	QString qsColors;
	for ( int i=0; i<MAX_MASK_COLORS; i++ )
	  qsColors += pgcColors[i].toString ( ) + ",";
	
	tag = xmlDoc.createElement ( MENU_MASK_COLORS );
	rootDVDMenu.appendChild    ( tag );
	t = xmlDoc.createTextNode  ( qsColors );
	tag.appendChild ( t );

	return true;
}

CDVDMenuInterface &CDVDMenuInterface::operator =( CDVDMenuInterface &theOther )
{
  // variables.
  bModified                 = theOther.bModified;
  bIsSubMenu                = theOther.bIsSubMenu;
  qsMenuName                = theOther.qsMenuName;

  // the following entries belong to the movie background
  qsMovieFileName           = theOther.qsMovieFileName;
  bMovieBackgroundHasSound  = theOther.bMovieBackgroundHasSound;
  timeOffset                = theOther.timeOffset;
  timeDuration              = theOther.timeDuration;
  // The following var is the background image or screenshot of the Movie ...
  qsBackgroundFileName      = theOther.qsBackgroundFileName;

  qsSelectedMaskFileName    = theOther.qsSelectedMaskFileName;
  qsHighlightedMaskFileName = theOther.qsHighlightedMaskFileName;
  qsResizeAlgo              = theOther.qsResizeAlgo;
  qsAnimation               = theOther.qsAnimation;
  iStretchType              = theOther.iStretchType;	// StretchToFit, BlackBorders, CutOffset
  posOffset                 = theOther.posOffset;
  iFormat                   = theOther.iFormat;
  iWidth                    = theOther.iWidth;
  iHeight                   = theOther.iHeight;
  iTitleset                 = theOther.iTitleset;
  iMenu                     = theOther.iMenu;
  qsRatio                   = theOther.qsRatio;

  // generated by importdvdauthor.cpp::buildMenuFromPgc()
  int t;
  CXmlDVDAuthor::vob_struct *pNewVob, *pOrigVob;
  Audio *pAudio = NULL;
  for ( t=0; t<(int)listSoundEntries.count ( ); t++ )
    delete listSoundEntries[t];
  listSoundEntries.clear ( );
  for ( t=0; t<(int)theOther.listSoundEntries.count ( ); t++ ) {
     pAudio = new Audio;
    *pAudio = *theOther.listSoundEntries[t];
    listSoundEntries.append ( pAudio );
  }

  for ( t=0; t<(int)listIntroVobs.count ( ); t++ )
    delete listIntroVobs[t];
  listIntroVobs.clear ( );
  for ( t=0; t<(int)theOther.listIntroVobs.count ( ); t++ ) {
    pOrigVob = theOther.listIntroVobs[t];
    pNewVob  = new CXmlDVDAuthor::vob_struct;
    pNewVob->file     = pOrigVob->file;
    pNewVob->chapters = pOrigVob->chapters;
    pNewVob->pause    = pOrigVob->pause;
    listIntroVobs.append ( pNewVob );
  }

  for ( t=0; t<(int)listExtroVobs.count ( ); t++ )
    delete listExtroVobs[t];
  listExtroVobs.clear ( );
  for ( t=0; t<(int)theOther.listExtroVobs.count ( ); t++ )  {
    pOrigVob = theOther.listExtroVobs[t];
    pNewVob  = new CXmlDVDAuthor::vob_struct;
    pNewVob->file     = pOrigVob->file;
    pNewVob->chapters = pOrigVob->chapters;
    pNewVob->pause    = pOrigVob->pause;
    listExtroVobs.append ( pNewVob );
  }

  qsPre               = theOther.qsPre;
  qsPause             = theOther.qsPause;
  qsPost              = theOther.qsPost;

  backgroundImage     = theOther.backgroundImage;
  highlightedMask     = theOther.highlightedMask;
  selectedMask        = theOther.selectedMask;

  for (t=0; t<MAX_MASK_COLORS; t++ )
    pgcColors[t] = theOther.pgcColors[t];

  return *this;
}

bool CDVDMenuInterface::operator == ( CDVDMenuInterface &theOther )
{
  bool bReturn = (
     ( bModified                 == theOther.bModified                 ) &&
     ( bIsSubMenu                == theOther.bIsSubMenu                ) &&
     ( qsMenuName                == theOther.qsMenuName                ) &&
     ( qsMovieFileName           == theOther.qsMovieFileName           ) &&
     ( bMovieBackgroundHasSound  == theOther.bMovieBackgroundHasSound  ) &&
     ( timeOffset                == theOther.timeOffset                ) &&
     ( timeDuration              == theOther.timeDuration              ) &&
     ( qsBackgroundFileName      == theOther.qsBackgroundFileName      ) &&
     ( qsSelectedMaskFileName    == theOther.qsSelectedMaskFileName    ) &&
     ( qsHighlightedMaskFileName == theOther.qsHighlightedMaskFileName ) &&
     ( qsResizeAlgo              == theOther.qsResizeAlgo              ) &&
     ( qsAnimation               == theOther.qsAnimation               ) &&
     ( iStretchType              == theOther.iStretchType              ) &&
     ( posOffset                 == theOther.posOffset                 ) &&
     ( iFormat                   == theOther.iFormat                   ) &&
     ( iWidth                    == theOther.iWidth                    ) &&
     ( iHeight                   == theOther.iHeight                   ) &&
     ( iTitleset                 == theOther.iTitleset                 ) &&
     ( iMenu                     == theOther.iMenu                     ) &&
     ( qsRatio                   == theOther.qsRatio                   ) &&
     ( qsPre                     == theOther.qsPre                     ) &&
     ( qsPause                   == theOther.qsPause                   ) &&
     ( qsPost                    == theOther.qsPost                    ) );
//     ( backgroundImage           == theOther.backgroundImage           ) &&
//     ( highlightedMask           == theOther.highlightedMask           ) &&
//     ( selectedMask              == theOther.selectedMask              ) );
  if ( ! bReturn )
    return false;

  // generated by importdvdauthor.cpp::buildMenuFromPgc()
  if ( listSoundEntries.count ( ) != theOther.listSoundEntries.count ( ) )
    return false;
  if ( listIntroVobs.count ( ) != theOther.listIntroVobs.count ( ) )
    return false;
  if ( listExtroVobs.count ( ) != theOther.listExtroVobs.count ( ) )
    return false;

  QValueList<Audio *>::iterator itAudio1 = listSoundEntries.begin ( );
  QValueList<Audio *>::iterator itAudio2 = theOther.listSoundEntries.begin ( );
  while  ( itAudio1 != listSoundEntries.end ( ) )  {
    if ( ! ( *(*itAudio1++) == *(*itAudio2++) ) )
      return false;
  }

  QValueList <CXmlDVDAuthor::vob_struct *>::iterator itVob1 = listIntroVobs.begin ( );
  QValueList <CXmlDVDAuthor::vob_struct *>::iterator itVob2 = theOther.listIntroVobs.begin ( );
  while ( itVob1 != listIntroVobs.end ( ) )  {
    if ( ! ( *(*itVob1++) == *(*itVob2++) ) )
      return false;
  }
  itVob1 = listExtroVobs.begin ( );
  itVob2 = theOther.listExtroVobs.begin ( );
  while ( itVob1 != listExtroVobs.end ( ) )  {
    if ( ! ( *(*itVob1++) == *(*itVob2++) ) )
      return false;
  }

  int t;
  for ( t=0; t<MAX_MASK_COLORS; t++ )  {
    if ( pgcColors[t] != theOther.pgcColors[t] )
      return false;
  }

  return true;
}

//////////////////////////////////////////////////////////////
//
// The Main class
//
//////////////////////////////////////////////////////////////

VMGMenu::VMGMenu ()
{
}

VMGMenu::VMGMenu (QDVDAuthor *pDVDAuthor)
	: DVDMenu (pDVDAuthor)
{
  m_pDVDMenuMenu = NULL;
  // Main Menu VMGM is always at thir location ...
  getInterface     ( )->iTitleset = 0;
  getInterface     ( )->iMenu     = 0;
  CreateToolBar	   ( pDVDAuthor );
  CreateMenuEntry  ( pDVDAuthor );
  slotUpdateStructure ( );
}

VMGMenu::~VMGMenu ( )
{
  delete m_pDVDMenuMenu;
  delete m_pToolBar;

  delete m_pActionCreateDVD;
  delete m_pActionAddAudio;
  delete m_pActionAddBackgrnd;
  delete m_pActionAddSlide;
  delete m_pActionToolbarCreateDVD;
  delete m_pActionToolbarAddAudio;
  delete m_pActionToolbarAddBackgrnd;
  delete m_pActionToolbarAddSlide;

  delete m_pActionRenameMenu;
  delete m_pActionDeleteMenu;
  delete m_pActionCloneMenu;
  delete m_pActionConvertToPAL;
  delete m_pActionConvertToNTSC;
  delete m_pActionStoreMenu;
  delete m_pActionSnapshot;
  delete m_pActionAddFrame;
  delete m_pActionAddText;
  delete m_pActionAddImage;
  delete m_pActionAddMovie;
  delete m_pActionAddBackground;
  delete m_pActionAddSound;
  delete m_pActionAddIntro;
  delete m_pActionAddExtro;
  delete m_pActionAddFromLibrary;
}

void VMGMenu::CreateToolBar (QDVDAuthor *pDVDAuthor)
{
  QIconSet iconTBToDVD        = QIconSet ( QPixmap().fromMimeSource( "to_dvd.png" ));
  QIconSet iconTBAddAudio     = QIconSet ( QPixmap().fromMimeSource( "add_audio.png" ));
  QIconSet iconTBAddImage     = QIconSet ( QPixmap().fromMimeSource( "add_image.png" ));
  QIconSet iconTBAddSlide     = QIconSet ( QPixmap().fromMimeSource( "add_slideshow.png" ));
  QIconSet iconTBAddMenuSlide = QIconSet ( QPixmap().fromMimeSource( "add_menuslide.png" ));
  iconTBToDVD.setIconSize        ( QIconSet::Small, QSize (48, 48) );
  iconTBAddAudio.setIconSize     ( QIconSet::Small, QSize (48, 48) );
  iconTBAddImage.setIconSize     ( QIconSet::Small, QSize (48, 48) );
  iconTBAddSlide.setIconSize     ( QIconSet::Small, QSize (48, 48) );
  iconTBAddMenuSlide.setIconSize ( QIconSet::Small, QSize (48, 48) );

  // Create some action ...
  m_pActionCreateDVD           = new QAction ( pDVDAuthor, "createDVD" );
  m_pActionAddBackgrnd         = new QAction ( pDVDAuthor, "addAudio" );
  m_pActionAddAudio            = new QAction ( pDVDAuthor, "addImage" );
  m_pActionAddSlide            = new QAction ( pDVDAuthor, "addSlide" );
  m_pActionAddMenuSlide        = new QAction ( pDVDAuthor, "addMenuSlide" );
  m_pActionToolbarCreateDVD    = new QAction ( pDVDAuthor, "tbCreateDVD" );
  m_pActionToolbarAddBackgrnd  = new QAction ( pDVDAuthor, "tbAddAudio" );
  m_pActionToolbarAddAudio     = new QAction ( pDVDAuthor, "tbAddImage" );
  m_pActionToolbarAddSlide     = new QAction ( pDVDAuthor, "tbAddSlide" );
  m_pActionToolbarAddMenuSlide = new QAction ( pDVDAuthor, "tbAddMenuSlide" );
  m_pActionRenameMenu          = new QAction ( pDVDAuthor, "renameMenu" );
  m_pActionDeleteMenu          = new QAction ( pDVDAuthor, "deleteMenu" );
  m_pActionCloneMenu           = new QAction ( pDVDAuthor, "cloneMenu"  );
  m_pActionConvertToPAL        = new QAction ( pDVDAuthor, "convertToPAL" );
  m_pActionConvertToNTSC       = new QAction ( pDVDAuthor, "convertToNTSC" );
  m_pActionStoreMenu           = new QAction ( pDVDAuthor, "storMenu" );
  m_pActionSnapshot            = new QAction ( pDVDAuthor, "snapshot" );
  m_pActionAddFrame            = new QAction ( pDVDAuthor, "addFrame" );
  m_pActionAddText             = new QAction ( pDVDAuthor, "addText"  );
  m_pActionAddImage            = new QAction ( pDVDAuthor, "addImage" );
  m_pActionAddMovie            = new QAction ( pDVDAuthor, "addMovie" );	
  m_pActionAddBackground       = new QAction ( pDVDAuthor, "addbackground" );
  m_pActionAddSound            = new QAction ( pDVDAuthor, "addsound" );
  m_pActionAddIntro            = new QAction ( pDVDAuthor, "addintro" );
  m_pActionAddExtro            = new QAction ( pDVDAuthor, "addextro" );
  m_pActionAddFromLibrary      = new QAction ( pDVDAuthor, "addFromLibrary" );

  m_pActionToolbarCreateDVD->setIconSet    ( iconTBToDVD );
  m_pActionToolbarCreateDVD->setText       ( tr( "Create DVD" ) );
  m_pActionCreateDVD->setMenuText          ( tr( "&Create DVD" ) );

  m_pActionToolbarAddAudio->setIconSet     ( iconTBAddAudio );
  m_pActionToolbarAddAudio->setText        ( tr( "Add Audio" ) );
  m_pActionAddAudio->setMenuText           ( tr( "Add &Audio" ) );

  m_pActionToolbarAddBackgrnd->setIconSet  ( iconTBAddImage );
  m_pActionToolbarAddBackgrnd->setText     ( tr( "Add Background" ) );
  m_pActionAddBackgrnd->setIconSet         ( iconTBAddImage );
  m_pActionAddBackgrnd->setMenuText        ( tr( "Add &Background" ) );

  m_pActionToolbarAddSlide->setIconSet     ( iconTBAddSlide );
  m_pActionToolbarAddSlide->setText        ( tr( "Add Slide" ) );
  m_pActionAddSlide->setMenuText           ( tr( "Add &Slide" ) );

  m_pActionToolbarAddMenuSlide->setIconSet ( iconTBAddMenuSlide );
  m_pActionToolbarAddMenuSlide->setText    ( tr( "Add MenuSlide" ) );
  m_pActionAddMenuSlide->setMenuText       ( tr( "Add &MenuSlide" ) );

  languageChange ( );

  // Here we create the ToolBar
  m_pToolBar = new QToolBar( "", pDVDAuthor, DockTop );

  m_pActionToolbarCreateDVD   ->addTo( m_pToolBar );
  m_pActionToolbarAddBackgrnd ->addTo( m_pToolBar );
  m_pActionToolbarAddAudio    ->addTo( m_pToolBar );
  m_pActionToolbarAddSlide    ->addTo( m_pToolBar );
  m_pToolBar->addSeparator    ( );
  m_pActionToolbarAddMenuSlide->addTo( m_pToolBar );

  connect( m_pActionToolbarCreateDVD,    SIGNAL( activated() ), pDVDAuthor, SLOT( slotCreateDVD ( ) ) );
  connect( m_pActionToolbarAddAudio,     SIGNAL( activated() ), this, SLOT( slotAddSound        ( ) ) );
  connect( m_pActionToolbarAddBackgrnd,  SIGNAL( activated() ), this, SLOT( slotAddBackground   ( ) ) );
  connect( m_pActionToolbarAddSlide,     SIGNAL( activated() ), pDVDAuthor, SLOT( slotEditAddSlideshow( ) ) );
  connect( m_pActionToolbarAddMenuSlide, SIGNAL( activated() ), pDVDAuthor, SLOT( slotActivatePlugin  ( ) ) );
}

void VMGMenu::languageChange ( )
{
//  if ( m_pDVDMenuMenu )
//       m_pDVDMenuMenu->changeItem ( 0, tr ( "DVD&Menu" ) );

  Global::pApp->m_pMenuBar->changeItem ( 3333, tr( "DVD&Menu" ) ); //, m_pDVDMenuMenu, 0, 3 );
//  pDVDAuthor->m_pMenuBar->insertItem ( tr( "DVD&Menu" ), m_pDVDMenuMenu, 0, 3 );

  m_pActionRenameMenu->setMenuText    ( tr( "&Rename Menu" ) );
  m_pActionCloneMenu->setMenuText     ( tr( "&Clone Menu" ) );
  m_pActionConvertToPAL->setMenuText  ( tr( "Convert to &PAL" ) );
  m_pActionConvertToNTSC->setMenuText ( tr( "Convert to &NTSC" ) );
  m_pActionDeleteMenu->setMenuText    ( tr( "&Delete Menu" ) );
  m_pActionStoreMenu->setMenuText     ( tr( "Store &as Template ..." ) );
  m_pActionSnapshot->setMenuText      ( tr( "&Snapshot ..." ) );

  m_pActionAddFrame->setMenuText      ( tr( "Add &Frame" ) );
  m_pActionAddText ->setMenuText      ( tr( "Add &Text" ) );
  m_pActionAddImage->setMenuText      ( tr( "Add &Image" ) );
  m_pActionAddMovie->setMenuText      ( tr( "Add &Movie" ) );
  m_pActionAddBackground->setMenuText ( tr( "Add &Background" ) );
  m_pActionAddSound->setMenuText      ( tr( "Add S&ound" ) );
  m_pActionAddIntro->setMenuText      ( tr( "Add &Intro" ) );
  m_pActionAddExtro->setMenuText      ( tr( "Add &Extro" ) );
  m_pActionAddFromLibrary->setMenuText( tr( "Add From &Library ..." ) );
}

void VMGMenu::CreateMenuEntry (QDVDAuthor *pDVDAuthor)
{
  QImage  image;
  QPixmap pix;

  image = QImage::fromMimeSource ( "add_audio.png" ).smoothScale ( 22, 22 );
  pix.convertFromImage ( image );
  QIconSet iconAddAudio = QIconSet ( pix );

  image = QImage::fromMimeSource ( "add_image.png" ).smoothScale ( 22, 22 );
  pix.convertFromImage ( image );
  QIconSet iconAddImage = QIconSet ( pix );

  m_pActionAddSound->setIconSet      ( iconAddAudio );
  m_pActionAddBackground->setIconSet ( iconAddImage );

  // menubar
  m_pDVDMenuMenu = new QPopupMenu (   pDVDAuthor   );
  m_pActionRenameMenu->addTo      ( m_pDVDMenuMenu );
  m_pActionCloneMenu->addTo       ( m_pDVDMenuMenu );
  m_pActionConvertToPAL->addTo    ( m_pDVDMenuMenu );
  m_pActionConvertToNTSC->addTo   ( m_pDVDMenuMenu );
  m_pActionDeleteMenu->addTo      ( m_pDVDMenuMenu );
  m_pActionStoreMenu->addTo       ( m_pDVDMenuMenu );
  m_pActionSnapshot->addTo        ( m_pDVDMenuMenu );
  m_pDVDMenuMenu->insertSeparator ( );
  m_pActionAddFrame->addTo        ( m_pDVDMenuMenu );
  m_pActionAddText ->addTo        ( m_pDVDMenuMenu );
  m_pActionAddImage->addTo        ( m_pDVDMenuMenu );
  m_pActionAddMovie->addTo        ( m_pDVDMenuMenu );
  m_pActionAddFromLibrary->addTo  ( m_pDVDMenuMenu );
  m_pDVDMenuMenu->insertSeparator ( );
  m_pActionAddBackground->addTo   ( m_pDVDMenuMenu );  // icon
  m_pActionAddSound->addTo        ( m_pDVDMenuMenu );  // icon
  m_pActionAddIntro->addTo        ( m_pDVDMenuMenu );
  m_pActionAddExtro->addTo        ( m_pDVDMenuMenu );

  pDVDAuthor->m_pMenuBar->insertItem ( tr( "DVD&Menu" ), m_pDVDMenuMenu, 3333, 3 );

  m_pActionStoreMenu->setEnabled  ( false );
  connect( m_pDVDMenuMenu, SIGNAL ( aboutToShow ( ) ), pDVDAuthor, SLOT ( slotAboutToShowMenu ( ) ) );

  // signals and slots connections
  connect( m_pActionCreateDVD,     SIGNAL( activated() ), pDVDAuthor, SLOT( slotCreateDVD ( ) ) );
  connect( m_pActionAddAudio,	   SIGNAL( activated() ), this, SLOT( slotAddSound        ( ) ) );
  connect( m_pActionAddBackgrnd,   SIGNAL( activated() ), this, SLOT( slotAddBackground   ( ) ) );
  connect( m_pActionAddSlide,	   SIGNAL( activated() ), pDVDAuthor, SLOT( slotEditAddSlideshow  ( ) ) );
  connect( m_pActionAddMenuSlide,  SIGNAL( activated() ), pDVDAuthor, SLOT( slotActivatePlugin    ( ) ) );
  connect( m_pActionRenameMenu,	   SIGNAL( activated() ), pDVDAuthor, SLOT( slotRenameCurrentSubMenu   ( ) ) );
  connect( m_pActionCloneMenu,	   SIGNAL( activated() ), pDVDAuthor, SLOT( slotCloneCurrentSubMenu    ( ) ) );
  connect( m_pActionDeleteMenu,	   SIGNAL( activated() ), pDVDAuthor, SLOT( slotRemoveCurrentSubMenu   ( ) ) );
  connect( m_pActionAddFromLibrary,SIGNAL( activated() ), pDVDAuthor, SLOT( slotAddFromLibrary         ( ) ) );
  connect( m_pActionConvertToPAL,  SIGNAL( activated() ), getMenuPreview  ( ), SLOT( slotConvertToPAL  ( ) ) );
  connect( m_pActionConvertToNTSC, SIGNAL( activated() ), getMenuPreview  ( ), SLOT( slotConvertToNTSC ( ) ) );
  connect( m_pActionStoreMenu,     SIGNAL( activated() ), this, SLOT( slotStoreMenuAsTemplate          ( ) ) );
  connect( m_pActionSnapshot,      SIGNAL( activated() ), this, SLOT( slotSnapshot        ( ) ) );
  connect( m_pActionAddFrame,      SIGNAL( activated() ), this, SLOT( slotAddFrameObject  ( ) ) );
  connect( m_pActionAddText,       SIGNAL( activated() ), this, SLOT( slotAddTextObject   ( ) ) );
  connect( m_pActionAddImage,      SIGNAL( activated() ), this, SLOT( slotAddImageObject  ( ) ) );
  connect( m_pActionAddMovie,      SIGNAL( activated() ), this, SLOT( slotAddMovieObject  ( ) ) );
  connect( m_pActionAddBackground, SIGNAL( activated() ), this, SLOT( slotAddBackground   ( ) ) );
  connect( m_pActionAddSound,      SIGNAL( activated() ), this, SLOT( slotAddSound        ( ) ) );
  connect( m_pActionAddIntro,      SIGNAL( activated() ), this, SLOT( slotAddIntro        ( ) ) );
  connect( m_pActionAddExtro,      SIGNAL( activated() ), this, SLOT( slotAddExtro        ( ) ) );
}

QToolBar *VMGMenu::getToolBar()
{
  return m_pToolBar;
}

QPopupMenu *VMGMenu::getPopupMenu ()
{
  return m_pDVDMenuMenu;
}

DVDMenu::DVDMenu ( )
{
}

DVDMenu::DVDMenu  ( QDVDAuthor * )
	: QObject ( )
{
  m_pPixmapMenu          = NULL;
  m_pDialogRenderPreview = NULL;
  m_pStructureItem       = NULL;
  m_pTabLayout           = NULL;
  m_pLayout1             = NULL;
  m_pLayout3             = NULL;
  m_pDVDMenuTab          = NULL;
  m_iTotalFramesToRender = 0;
  m_iCurrentFrameToRender= 0;

  CreateTab ( getDVDAuthor ( )->m_pTabWidgetMain );
  slotUpdateStructure ( );
}

DVDMenu::~DVDMenu ()
{
  delete m_pDVDMenuTab;
  if ( m_pStructureItem )
    delete m_pStructureItem;
}

UndoBuffer *DVDMenu::getUndoBuffer ( )
{
  if ( m_pPixmapMenu )
    return m_pPixmapMenu->undoBuffer ( );
  return NULL;
}

MenuPreview *DVDMenu::getMenuPreview ( )
{
  return m_pPixmapMenu;
}

void DVDMenu::clear ( )
{
  // This function will re-set the menu
  getInterface   ( )->initMe ( );
  getMenuPreview ( )->clear  ( getInterface()->pgcColors );
  getUndoBuffer  ( )->clear  ( );
}

bool DVDMenu::isEmpty ()
{
	// Checks if the menu has more then the default values.
	CDVDMenuInterface *p = getInterface();
	if (	(p->bModified == false) && 
		(p->listSoundEntries.count() < 1)         && 
		(p->qsMovieFileName.isEmpty())            &&
		(p->qsBackgroundFileName.isEmpty())       && 
		(p->qsSelectedMaskFileName.isEmpty())     && 
		(p->qsHighlightedMaskFileName.isEmpty ()) &&
		(p->iStretchType          ==  0) && 
		(p->posOffset.width()     ==  0) && 
		(p->posOffset.height()    ==  0) && 
		(p->iFormat               ==  0) &&
		(p->iWidth                ==  0) && 
		(p->iHeight               ==  0) && 
		(p->qsRatio == QString ("4:3") ) &&
		(p->backgroundImage.isNull ( ) ) && 
		(p->highlightedMask.isNull ( ) ) && 
		(p->selectedMask.isNull    ( ) ) &&
		(getMenuPreview()->objectCount() == 0)	)
		return true;
	/* Not checked ...
	QString qsMenuName;
	QString qsResizeAlgo;
	bool    bIsSubMenu;
	bool    bMovieBackgroundHasSound;
	QTime   timeOffset;
	QTime   timeDuration;
	QColor  pgcColors[MAX_MASK_COLORS];
	*/
	return false;
}

QString DVDMenu::checkDuration ( )
{
  bool bDummy1 = true;
  bool bDummy2 = true;
  return checkDuration ( bDummy1, bDummy2 );
}

QString DVDMenu::checkDuration ( bool &bCheckMovies, bool &bCheckAudio )
{
  QString qsReturn, qsFormat ( "hh:mm:ss.zzz" );
  // Here we compare the Duration of the menu with the duration of all MovieObjects
  uint  t, i;
  bool  bFound = false, bFoundIssues = false;
  bool  bCheckMovieButtons, bCheckAudioLength;
  long long iDuration, iDifference;
  QTime     zeroTime, timeMenu = getInterface( )->timeDuration;
  Audio    *pAudio;

  bCheckMovieButtons = bCheckMovies;
  bCheckAudioLength  = bCheckAudio;
  bCheckMovies = false; // return, no MovieLength difference found
  bCheckAudio  = false; // return no AudioLength difference found

  iDuration = zeroTime.msecsTo ( timeMenu );
  qsReturn  = tr ( "<P><FONT COLOR=\"ORANGE\"><B><U>%1 : Duration = %2 sec</U></B></FONT><BR><HR>" ).arg ( name ( ) ).arg ( (int)(iDuration / 1000 ) );
  if ( zeroTime.msecsTo ( timeMenu ) < 1000 ) {
    qsReturn += tr ( "This Menu does not seem to have a valid length. Its Duration is set to 0 seconds.<P>" );
    return qsReturn;
  }

  ButtonObject     tempButton,     *pButton;
  MovieObject      tempMovie,      *pMovieObject;
  ObjectCollection tempCollection, *pCollection;
  MenuObject      *pMenuObject;
  SourceFileEntry *pEntry;
  SourceFileInfo  *pInfo;
  Utils            theUtils;
  QStringList               listNames;
  QValueList<MovieObject *> listMovies;// = getMovieObjects ( );
  if ( bCheckMovieButtons )  {
    for ( t=0; t<getMenuPreview ( )->objectCount ( ); t++ )  {
      pMenuObject = getMenuPreview ( )->menuObject ( t );
      if ( pMenuObject->objectType ( ) == tempButton.objectType ( ) )  {
        pButton = (ButtonObject *)pMenuObject;
        for ( i=0; i<pButton->getNormalCount ( ); i++ )  {
          if ( pButton->getNormal ( i )->objectType ( ) == tempMovie.objectType ( ) ) {
            pMovieObject = (MovieObject *)pButton->getNormal ( i );
            listMovies.append ( pMovieObject );
            listNames.append  ( pButton->name ( ) );
          }
        }
      }
      else if ( pMenuObject->objectType ( ) == tempCollection.objectType ( ) )  {
        pCollection = (ObjectCollection *)pMenuObject;
        for ( i=0; i<(uint)pCollection->getCount ( ); i++ )  {
          if ( pCollection->getObject ( i )->objectType ( ) == tempMovie.objectType ( ) ) {
            pMovieObject = (MovieObject *)pCollection->getObject ( i );
            listMovies.append ( pMovieObject );
            listNames.append  ( pMovieObject->name ( ) );
          }
        }
      }
      else if ( pMenuObject->objectType ( ) == tempMovie.objectType ( ) ) {
        pMovieObject = (MovieObject *)pMenuObject;
        listMovies.append ( pMovieObject );
        listNames.append  ( pMovieObject->name ( ) );
      }
    }
  }

  // After we have the list of MovieObjects and associated names, we can see if they actually 
  // are different in length.
  for ( t=0; t<listMovies.count ( ); t++ ) {
    pMovieObject = listMovies[t];
    if ( ! pMovieObject )
      continue;

    iDifference = pMovieObject->duration ( ).msecsTo ( timeMenu );
    if ( iDifference > 1000 ) {
      bFoundIssues = true;
      bFound       = true;
      qsReturn += tr ( "MovieObject <FONT COLOR=\"BLUE\"><B>%1</B></FONT> is <FONT COLOR=\"RED\"><B>%2</B></FONT> sec shorter then the menu duration." ).arg ( listNames[t] ).arg ( (int)( iDifference / 1000 ) );
    }
    else if ( iDifference < -1000 ) {
      bFoundIssues = true;
      bFound       = true;
      qsReturn += tr ( "MovieObject <FONT COLOR=\"BLUE\"><B>%1</B></FONT> is <FONT COLOR=\"RED\"><B>%2</B></FONT> sec longer then the menu duration." ).arg ( listNames[t] ).arg ( (int)( -iDifference / 1000 ) );
    }
    if ( bFound )  {
      if ( pMovieObject->loop ( ) == MovieObject::Stop )
        qsReturn += tr ( " Movie will stop after %1." ).arg ( pMovieObject->duration ( ).toString ( qsFormat ) );
      if ( pMovieObject->loop ( ) == MovieObject::Stretch )
        qsReturn += tr ( " Movie will stretch to %1." ).arg ( timeMenu.toString ( qsFormat ) );
      if ( pMovieObject->loop ( ) == MovieObject::Loop )
        qsReturn += tr ( " Movie will loop every %1." ).arg ( pMovieObject->duration ( ).toString ( qsFormat ) );
      qsReturn += "<BR>";
      bCheckMovies = true;
    }
    bFound = false;
  }

  qsReturn += "<P>";
  // Next we check the length of the attached SoundEntries.
  if ( bCheckAudioLength )  {
    for ( t=0; t<getInterface ( )->listSoundEntries.count ( ); t++ ) {
      pAudio  =  getInterface ( )->listSoundEntries[t];
      if ( ! pAudio )
        continue;

      // How to extract the info from the data in the SourceToolbar ???
      iDuration = 0;
      pEntry = getDVDAuthor ( )->getSourceEntryByDisplayName ( pAudio->qsFileName );
      if ( ! pEntry )
        continue;
      for ( i=0; i<pEntry->listFileInfos.count ( ); i++ ) {
        pInfo = pEntry->listFileInfos[i];
        if ( ! pInfo )
          continue;
        iDuration += theUtils.getMsFromString ( pInfo->qsLength );
      }

      iDifference = iDuration - zeroTime.msecsTo ( timeMenu );
      QTime timeDiff;
      if ( iDifference > 1000 ) {
        timeDiff = timeDiff.addMSecs ( iDifference );
        QString qsDiff;
        if ( iDifference > 60000 ) // Oly need this if > 60 seconds
             qsDiff = QString ( " <FONT COLOR=\"RED\"><B>(%1)</B></FONT> " ).arg ( timeDiff.toString ( "hh.mm.ss.zzz" ) );
        bFoundIssues   = true;
        bCheckAudio    = true; // Return info to caller
        qsReturn += tr ( "Menu audio file<FONT COLOR=\"BLUE\"><B>%1</B></FONT> is <FONT COLOR=\"RED\"><B>%2</B></FONT> sec longer %3then the menu duration.<BR>" ).arg ( pEntry->qsDisplayName ).arg ( (int)( iDifference / 1000 ) ).arg ( qsDiff );
      }
      else if ( iDifference < -1000 ) {
        timeDiff = timeDiff.addMSecs ( -iDifference );
        QString qsDiff;
        if ( iDifference > 60000 ) // Oly need this if > 60 seconds
             qsDiff = QString ( " <FONT COLOR=\"RED\"><B>(%1)</B></FONT> " ).arg ( timeDiff.toString ( "hh.mm.ss.zzz" ) );
        bFoundIssues   = true;
        bCheckAudio    = true;  // Return info to caller
        qsReturn += tr ( "Menu duration <FONT COLOR=\"BLUE\"><B>%1</B></FONT> is <FONT COLOR=\"RED\"><B>%2</B></FONT> sec shorter %3then the menu audio file.<BR>" ).arg ( pEntry->qsDisplayName ).arg ( (int)( -iDifference / 1000 ) ).arg ( qsDiff );
      }
    }
  }

  if ( ! bFoundIssues )
   qsReturn = QString ( );

  return qsReturn;
}

bool DVDMenu::readProjectFile ( QDomNode &theNode, float fLoadVersion )
{
	QDomElement theElement = theNode.toElement ( );
	QString tagName;
	QString nodeText;
	
	QDomAttr a = theElement.attributeNode ( MENU_FORMAT );
	m_DVDMenuInterface.iFormat = a.value().toInt();
	a = theElement.attributeNode ( MENU_WIDTH );
	m_DVDMenuInterface.iWidth  = a.value().toInt();
	a = theElement.attributeNode ( MENU_HEIGHT );
	m_DVDMenuInterface.iHeight = a.value().toInt();
	a = theElement.attributeNode ( MENU_RATIO );
	if ( ! a.value().isEmpty() )
	  m_DVDMenuInterface.qsRatio = a.value();
	a = theElement.attributeNode ( MENU_TITLESET_NR );
	if ( ! a.value().isEmpty() )
	  m_DVDMenuInterface.iTitleset = a.value().toInt();
	a = theElement.attributeNode ( MENU_MENU_NR );
	if ( ! a.value().isEmpty() )
	  m_DVDMenuInterface.iMenu = a.value().toInt();
	
	QDomNode xmlMenu = theNode.firstChild();
	while (!xmlMenu.isNull())	{
		// Okay, here we retain the stored data from the xml file.
		theElement = xmlMenu.toElement  ( );
		tagName    = theElement.tagName ( );
		nodeText   = theElement.text    ( );

		if (DVDAUTHOR_MENU == tagName)	{
			// Let us take care of the DVDMenus properties first
		  if ( ! m_DVDMenuInterface.readProjectFile ( xmlMenu, fLoadVersion ) )
				return false;
// Might be wrong. I get the info for the SourceToolbar already through the SourceEntry.
//			if ( getDVDAuthor ( ) )
//			     getDVDAuthor ( )->addSound ( m_DVDMenuInterface.listSoundFiles );
		}
		else if (DVDAUTHOR_PREVIEW == tagName)	{
			// before we read in the infos in ButtonPreview::readProjectFile
			m_pPixmapMenu->readProjectFile (xmlMenu);
		}
		else
			printf ("Warning: DVDMenu::readProjectFile -=> wrong XML Node <%s>\nContinuing ...\n", (const char *)tagName);
		// So lets get the next sibling ... until we hit hte end of DVDMenu ...
		xmlMenu = xmlMenu.nextSibling();
	}
	if ( ! m_DVDMenuInterface.qsBackgroundFileName.isEmpty ( ) ) {
	  QImage tempImage (m_DVDMenuInterface.qsBackgroundFileName );
	  int iWidth  = m_DVDMenuInterface.iWidth;
	  int iHeight = m_DVDMenuInterface.iHeight;
	  if ( ( iWidth > 10 ) && ( iHeight > 10 )  )
	    m_DVDMenuInterface.backgroundImage.convertFromImage ( tempImage.smoothScale ( iWidth, iHeight, QImage::ScaleFree ) );
	  else
	    m_DVDMenuInterface.backgroundImage.convertFromImage ( tempImage );
	  m_pPixmapMenu->setPixmap ( (const QPixmap &) m_DVDMenuInterface.backgroundImage );
	  refresh ( );
	}
	// If it is the Main Menu we are loading, we won't need to set the name.
	if ( m_DVDMenuInterface.qsMenuName != QString ( VMGM_LABEL ) )
		setTabLabel ( m_DVDMenuInterface.qsMenuName );

	if ( getUndoBuffer ( ) )
	     getUndoBuffer ( )->clear ( );

	return true;
}

bool DVDMenu::writeProjectFile ( QDomElement &rootElement )
{
  QDomDocument xmlDoc = rootElement.ownerDocument();
  QDomElement rootDVDMenu;
  if (m_DVDMenuInterface.bIsSubMenu)
    rootDVDMenu = xmlDoc.createElement( DVDAUTHOR_ROOT_MENU );
  else
    rootDVDMenu = xmlDoc.createElement( DVDAUTHOR_ROOT_VMGM );

  QDomElement dvdMenu = xmlDoc.createElement( DVDAUTHOR_MENU );
  QDomElement dvdPreview = xmlDoc.createElement( DVDAUTHOR_PREVIEW );

  // We set the Main menu attributes here ...
  rootDVDMenu.setAttribute ( MENU_FORMAT, QString("%1").arg(m_DVDMenuInterface.iFormat)  );
  rootDVDMenu.setAttribute ( MENU_WIDTH,  QString("%1").arg(m_DVDMenuInterface.iWidth)   );
  rootDVDMenu.setAttribute ( MENU_HEIGHT, QString("%1").arg(m_DVDMenuInterface.iHeight)  );
  rootDVDMenu.setAttribute ( MENU_RATIO, m_DVDMenuInterface.qsRatio );
  if ( m_DVDMenuInterface.iTitleset > -1 )
    rootDVDMenu.setAttribute ( MENU_TITLESET_NR,QString("%1").arg ( m_DVDMenuInterface.iTitleset ) );
  if ( m_DVDMenuInterface.iMenu > -1 )
    rootDVDMenu.setAttribute ( MENU_MENU_NR,    QString("%1").arg ( m_DVDMenuInterface.iMenu  ) );

  // We encapsulate the Previe, and the DVDMenu variables from each other so the reading is uniform.
  rootDVDMenu.appendChild ( dvdMenu );
  rootDVDMenu.appendChild ( dvdPreview );
  rootElement.appendChild ( rootDVDMenu );

  // Okay, the main Node is created, now all DVDAuthor related information belon under it.
  if (!m_DVDMenuInterface.writeProjectFile( dvdMenu ))
    return false;
  return m_pPixmapMenu->writeProjectFile( dvdPreview );
}

void DVDMenu::slotAddFrameObject (bool bFinalDestiny)
{
  // Tricky using the same function for two different calls
  if ( bFinalDestiny )  {
    if ( m_pPixmapMenu )
         m_pPixmapMenu->slotAddFrameObject ( );
  }
  else	{
    DVDMenu *pMenu = getDVDAuthor ( )->getCurrentSubMenu ( );
    if ( pMenu )
         pMenu->slotAddFrameObject(true);
  }
}

void DVDMenu::slotAddTextObject  (bool bFinalDestiny)
{
  // Tricky using the same function for two different calls
  if ( bFinalDestiny )  {
    if ( m_pPixmapMenu )
         m_pPixmapMenu->slotAddTextObject ( );
  }
  else	{
    DVDMenu *pMenu = getDVDAuthor ( )->getCurrentSubMenu ( );
    if ( pMenu )
         pMenu->slotAddTextObject ( true );
  }
}

void DVDMenu::slotAddImageObject (bool bFinalDestiny)
{
  // Tricky using the same function for two different calls
  if ( bFinalDestiny )  {
    if ( m_pPixmapMenu )
         m_pPixmapMenu->slotAddImageObject ( );
  }
  else	{
    DVDMenu *pMenu = getDVDAuthor ( )->getCurrentSubMenu ( );
    if ( pMenu )
         pMenu->slotAddImageObject(true);
  }
}

void DVDMenu::slotAddMovieObject (bool bFinalDestiny)
{
  // Tricky using the same function for two different calls
  if ( bFinalDestiny )  {
    if ( m_pPixmapMenu )
      m_pPixmapMenu->slotAddMovieObject ( );
  }
  else	{
    DVDMenu *pMenu = getDVDAuthor ( )->getCurrentSubMenu ( );
    if ( pMenu )
         pMenu->slotAddMovieObject ( true );
  }
}

QString DVDMenu::name()
{
  return getDVDAuthor ( )->m_pTabWidgetMain->tabLabel ( m_pDVDMenuTab );
}

void DVDMenu::setTabLabel(QString &qsNewLabel)
{
  bool bIsSubMenu = true;
  getDVDAuthor ( )->m_pTabWidgetMain->setTabLabel ( m_pDVDMenuTab, qsNewLabel );
  // Okay since we can not change the name of the VMGM, this ought to be a sub menu
  // As such we should enable the user to rename, or delete it.
  // Note: Rename, Delete is done in the QDVDAuthor - class
  if (VMGM_LABEL == qsNewLabel)
    bIsSubMenu = false;

  m_pPixmapMenu->setIsSubMenu    (bIsSubMenu);
  m_DVDMenuInterface.bIsSubMenu = bIsSubMenu;
}

void DVDMenu::modifyColor ( uint iWhichColor, Rgba theColor, bool bCalledFromDialog )
{
  // printf ("DVDMenu::modifyColor <%d> <%d> <%s>\n", iWhichColor, bCalledFromDialog, (const char *)theColor.name());
  uint t;
  // This function is called from ColorToolbar click mouse event or from a ButtonObject ...
  // This function changes the colors according to the following rules :
  // There are 4 colors available :
  // -	1 = Transparent color
  // -	2 = Highlighted color
  // -	3 = Selected color
  // -	4 = -=> FREE <=-
  
  // 1)	The first color change is associated to the 4'th color but only if the change comes from the dialog
  //		After all if the user clicks on the ColorToolbar then he should know what he is doing.
  // 2)	The second color change will affect all Buttons (Selected or Highlighted)
  //		a)	If only one ButtonObject in menu, then don't care
  //		b)	Else ask user to confirm
  //			-NO  : return
  //			-YES :  Go through all ButtonObjects of this menu and change this color
  //		c)	Change ColorToolbar ...
  //		d)	Change all ButtonObjects colors ...
  static bool bFirstModification = true;
  QValueList <ButtonObject *> listButtons = getButtons();

  if (bFirstModification && bCalledFromDialog)	{
    iWhichColor = MAX_MASK_COLORS - 1;
    //		theColor = m_DVDMenuInterface.pgcColors[MAX_MASK_COLORS - 1];
    bFirstModification = false;
  }
  else if (listButtons.count () > 1)	{
    // Double check if the user really wants to affect all ButtonObjects.
    // This is done when we have more then one ButtonObject int this Menu ...
    QString qsWhichColor ("Highlighted");
    if (iWhichColor == SELECTED_MASK)
      qsWhichColor = QString ("Selected");

    if (MessageBox::warning ( NULL, tr("Change all colors ?"), tr("This modification will change will affect all %1 colors.\n"
								  "Do you want to proceed ?").arg(qsWhichColor), QMessageBox::Yes|QMessageBox::Default, QMessageBox::No|QMessageBox::Escape ) == QMessageBox::No)
      return;
  }

  // The next check is to ensure that we have a unique color.
  // In order to give the User control, I will simply bump up one color (red) by one bit
  for (t=0;t<MAX_MASK_COLORS;t++)	{
    if (m_DVDMenuInterface.pgcColors[t] == theColor)	{
      if (theColor.red() > 0)
	theColor.setRgb ( theColor.red ( ) - 1, theColor.green ( ), theColor.blue ( ), theColor.alpha ( ) );
      else
	theColor.setRgb ( theColor.red ( ) + 1, theColor.green ( ), theColor.blue ( ), theColor.alpha ( ) );
    }
  }

  Rgba oldColor = m_DVDMenuInterface.pgcColors[iWhichColor];
  // Here we propagate the color change through all ButtonObjects.
  for (t=0;t<listButtons.count();t++)
    listButtons[t]->replaceColor ( theColor, oldColor );
  // Next we set the color in the DVDMenuInterface (The most important one)
  m_DVDMenuInterface.pgcColors[iWhichColor] = theColor;
  // And finally we set the color in the m_pColorToolbar of DVDAuthor
  getDVDAuthor ( )->setColor ( iWhichColor, theColor );
}

// Standard initialization Functions.
void DVDMenu::CreateTab ( QTabWidget *pTabWidgetMain )
{
	// The insertIndex is a bit tricky
	int iInsertIndex = pTabWidgetMain->count ( ) - 3;
	iInsertIndex += getDVDAuthor ( )->tabVisible ( QDVDAuthor::TabDVDLayout    ) ? 0 : 1;
	iInsertIndex += getDVDAuthor ( )->tabVisible ( QDVDAuthor::TabSubtitles    ) ? 0 : 1;
	iInsertIndex += getDVDAuthor ( )->tabVisible ( QDVDAuthor::TabDVDAuthorXml ) ? 0 : 1;

	QPixmap backgroundPixmap = QPixmap().fromMimeSource ("checkered.png");

	m_pDVDMenuTab = new QWidget     ( pTabWidgetMain, "m_pDVDMenuTab" );
	m_pTabLayout  = new QGridLayout ( m_pDVDMenuTab, 1, 1, 6, 2, "m_pTabLayout");
	m_pLayout1    = new QGridLayout ( 0, 1, 1, 0, 6, "m_pLayout1");

	// Here we get the available screen resolution (all screens)
	// We want to keep the old style for resolutions above 1024x768 
	// But for lower res we need to use a scrollview to be able to
	// use QDVDAuthor.
	int iScreenWidth, iScreenHeight, iScreens, t;
	bool bUseScrollView = false;
	QScrollView *m_pScrollView = NULL;
	QDesktopWidget desktop;
	iScreenWidth = iScreenHeight = 0;
	iScreens = desktop.numScreens();
	for (t=0;t<iScreens;t++)	{
		iScreenWidth  += desktop.screenGeometry(t).width();
		iScreenHeight += desktop.screenGeometry(t).height();
	}
	uint iFlags = Qt::WStaticContents;
#if (QT_VERSION > 0x0301FF)
	iFlags |= Qt::WNoAutoErase;
#else
	iFlags |= Qt::WPaintClever;
#endif
	QFrame *pFrame = new QFrame ( m_pDVDMenuTab, "innerFrame" );
	pFrame->setFrameShape  ( QLabel::Box );
	pFrame->setFrameShadow ( QLabel::Raised );
	pFrame->setLineWidth   ( 2 );
	pFrame->setMargin      ( 0 );
	m_pLayout1->addWidget  ( pFrame, 0, 0 );

	m_pLayout3  = new QGridLayout  ( pFrame, 1, 1, 4, -1  );
	char *pScroll = getenv ( "QDVD_SCROLL" );
	int iUseScrollView = 0;
	if ( pScroll ) {
	  QString qsScroll ( "yes" );
	  if ( qsScroll == pScroll )
	    iUseScrollView = +1;
	  else
	    iUseScrollView = -1;
	}
	// check the views dimensions, and the environment (yes will force to use the scrollview, no will inhibit it)
	if ( (iUseScrollView == 1 )     ||
	     ( ( (iScreenHeight <= 768) || (iScreenWidth <= 1024) ) && ( iUseScrollView != -1 ) ) )  {
		bUseScrollView = true;
		// Here we embed the MenuPreview into a ScrollView object ...
		m_pScrollView = new QScrollView ( pFrame,        "usingScrollView", iFlags );// Don't change the name. Used in ButtonPreview !
		m_pPixmapMenu = new MenuPreview ( m_pScrollView, "m_pPixmapMenu",   iFlags );
	}
	else
		m_pPixmapMenu = new MenuPreview ( pFrame, "m_pPixmapMenu", iFlags   );

	m_pPixmapMenu->setLineWidth              ( 0 );
	m_pPixmapMenu->setMargin                 ( 0 );
	m_pPixmapMenu->setScaledContents         ( TRUE );
	m_pPixmapMenu->setPaletteBackgroundPixmap( backgroundPixmap );
	m_pPixmapMenu->setFocusPolicy( QWidget::StrongFocus         );
	m_pPixmapMenu->initMe        ( m_DVDMenuInterface.pgcColors );
	
	if ( bUseScrollView )     {
	  m_pScrollView->addChild ( m_pPixmapMenu );
	  m_pPixmapMenu->resize   ( 720, 480 );
	  m_pLayout3->addWidget   ( m_pScrollView, 0, 0 );
	}
	else
	  m_pLayout3->addWidget   ( m_pPixmapMenu, 0, 0 );

	m_pTabLayout->addLayout   ( m_pLayout1, 0, 0 );

	// Insert the tab as the second from the back (xml/subpictures are last).
	pTabWidgetMain->insertTab ( m_pDVDMenuTab, QString(VMGM_LABEL), iInsertIndex );
	pTabWidgetMain->setCurrentPage ( iInsertIndex );

	connect( m_pPixmapMenu, SIGNAL(signalUpdateStructure()),     this, SLOT( slotUpdateStructure     ( ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalDroppedSomething(uint)),this, SLOT( slotDroppedSomething( uint) ) );
	connect( m_pPixmapMenu, SIGNAL(signalRequestSourceFiles()),  this, SLOT( slotRequestSourceFiles  ( ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalRequestSubMenus()),     this, SLOT( slotRequestSubMenus     ( ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalEditTimeline()),        this, SLOT( slotEditTimeline        ( ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalDeleteMe  ( ) ),     getDVDAuthor ( ), SLOT( slotRemoveCurrentSubMenu ( ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalRenameMe  ( ) ),     getDVDAuthor ( ), SLOT( slotRenameCurrentSubMenu ( ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalCloneMe   ( ) ),     getDVDAuthor ( ), SLOT( slotCloneCurrentSubMenu  ( ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalLibrary   ( ) ),     getDVDAuthor ( ), SLOT( slotAddFromLibrary       ( ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalConvertMe ( bool )), getDVDAuthor ( ), SLOT( slotConvertCurrentMenu   ( bool ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalMaskColorChanged  (Rgba, Rgba)),     this, SLOT(slotMaskColorChanged  ( Rgba, Rgba          ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalCreatedMovieObject(MovieObject *, bool)),this, SLOT(slotCreatedMovieObject( MovieObject *, bool     ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalAnimateObject(QString &, int, QString )),this, SLOT(slotAnimateObject     ( QString &, int, QString ) ) );
}

// Public slots. Here are the main actors from the GUI.
void DVDMenu::slotSnapshot ( )
{
  // This function will open the CreateTemplate - dialog.
  DVDMenu *pMenu = getDVDAuthor ( )->getCurrentSubMenu ( );
  if ( ! pMenu )
    pMenu = this;

  QDVDAuthor *pDVDAuthor = getDVDAuthor ( );
  if ( ! pDVDAuthor )
    return;

  QString qsExtensions = pDVDAuthor->getImageFilter   ( );
  QString qsFileName   = QFileDialog::getSaveFileName ( Global::qsCurrentPath, tr ( "Image File ( " + qsExtensions + " )" ) );
  if ( qsFileName.isEmpty ( ) )
    return;

  createMask ( qsFileName, BACKGROUND_IMG, true );
}

void DVDMenu::slotStoreMenuAsTemplate ( )
{
  // This function will open the CreateTemplate - dialog.
  DVDMenu *pMenu = getDVDAuthor ( )->getCurrentSubMenu ( );
  if ( ! pMenu )
    pMenu = this;

  DialogCreateTemplate theDialog;
  theDialog.initMe     ( pMenu );
  theDialog.exec          ( );
}

void DVDMenu::slotDroppedSomething(uint iWhatDidIDrop)
{
	// This function is initiated by m_pPixmapMenu::signalDroppedSomething, meaning we know
	// that the last object is the one we are interested in.
	int    iY, iX, iLastObject;
	QRect  rectImage, rectText, rect;
	QPoint textAlign (Qt::AlignHCenter, Qt::AlignVCenter);
	TextObject  tempObject, *pTextObject;
	// Get the minimum objects ...
	iLastObject                       = m_pPixmapMenu->objectCount() - 1;
	MenuObject *pObject               = m_pPixmapMenu->menuObject (iLastObject);
	DragNDropContainer *pDNDContainer = getDVDAuthor ( )->getDragNDropContainer ( );
	// Sanity check are you all there ?
	if (!pObject || !pDNDContainer)
		return;

	switch (iWhatDidIDrop)	{
	case MenuPreview::DroppedImage :
	case MenuPreview::DroppedMovie :
	  //nothin' to be done.
	break;
	case MenuPreview::DroppedChapter : {
	  ButtonObject tempButton;
	  // in this case we also need to set the SourceFileEntry of the ButtonObject
	  if ( pObject->objectType ( ) != tempButton.objectType ( ) )
	    return;
	  ButtonObject    *pButton = NULL;
	  pButton = (ButtonObject *)pObject;
	  SourceFileEntry *pEntry  = NULL;
	  QString qsDisplayName;
	  QString qsAction = pButton->action ( );
	  QStringList list = QStringList::split ( QString ( STRING_SEPARATOR ), qsAction );
	  //qsFileName    = list[ list.size ( ) - 3 ];
	  qsDisplayName = list[ 1 ];
	  pEntry = getDVDAuthor ( )->getSourceEntryByDisplayName ( qsDisplayName );
	  pButton->setSourceFileEntry ( pEntry );
	}
	break;
	case MenuPreview::DroppedText  :
	case MenuPreview::DroppedImageAndText :
	case MenuPreview::DroppedMovieAndText :
		// Stacked first the image, and last the Text, thus need to move the
		// text to the defined space (BOTTOM / TOP / LEFT / RIGHT) of image.
		// Sanity check are you a text Object ?
		if (pObject->objectType() != tempObject.objectType())
			return;
		pTextObject = (TextObject *)pObject;
		// Then we set the attributes defined in the SetupDialog.
		if ( pTextObject->getStyleStrategy ( ) == 123 )
		  // If we come from DroppedChapters (DialogThumbnails) we do NOT want to change those ...
		  pTextObject->setStyleStrategy    ( (int)QFont::PreferAntialias );
		else {
		  pTextObject->setFont             ( pDNDContainer->font );
		  pTextObject->setForegroundColor  ( pDNDContainer->colorForeground );
		}
		pTextObject->setTextAlign ( textAlign );
		pTextObject->update ( );
		rect = pTextObject->rect ( );
		// Done with the Text only object, now we handle DroppedImageAndText
		if (	(iWhatDidIDrop == MenuPreview::DroppedImageAndText) || 
			(iWhatDidIDrop == MenuPreview::DroppedMovieAndText) )	{
			MenuObject *pImageOrMovieButton = m_pPixmapMenu->menuObject (iLastObject-1);
			// Sanity check are you all there ?
			if (!pImageOrMovieButton)
				return;
			// and obtain the coordinates ...
			rectImage = pImageOrMovieButton->rect ();
			rectText  = pTextObject ->rect ();
// This is now handled in  > slotCreatedMovieObject (pMovieObject) <

//			if (MenuPreview::DroppedMovieAndText == iWhatDidIDrop)	{
//				// we dropped a button with the first normal - object beeing the MovieObject
//				MovieObject *pMovieObject = (MovieObject *)((ButtonObject *)pImageOrMovieButton)->getNormal (0);
//				// And here we connect the Menu to the MovieObject. This is needed to get all infos
//				// required for the rendering process
//				// the 'true'=RegisterToRender. Now we don't want that when we load from xml file right 
//				pMovieObject->setDVDMenu (this, true);	
//			}
			switch (getDVDAuthor ( )->getDragNDropContainer()->iTextPosition)	{
			case DragNDropContainer::TEXT_POS_TOP    :
				iX = (int)((float)rectImage.width() / 2.0 + rectImage.x() - rectText.width() / 2.0);
				rect = QRect(iX, rectImage.y()-rectText.height(), rectImage.width(), rectText.height());
			break;
			case DragNDropContainer::TEXT_POS_LEFT   :
				iY = (int)((float)rectImage.height() / 2.0 - (float)rectText.height() / 2.0 + rectImage.y());
				rect = QRect(rectImage.x()-rectText.width(), iY, rectText.width(), rectText.height());
			break;
			case DragNDropContainer::TEXT_POS_RIGHT  :
				iY = (int)((float)rectImage.height() / 2.0 - (float)rectText.height() / 2.0 + rectImage.y());
				rect = QRect(rectImage.x()+rectImage.width(), iY, rectText.width(), rectText.height());
			break;
			case DragNDropContainer::TEXT_POS_BOTTOM :
			case DragNDropContainer::TEXT_POS_UNDEF  :
			default :
				iX = (int)((float)rectImage.width() / 2.0 + rectImage.x() - rectText.width() / 2.0);
				rect = QRect (iX, rectImage.y()+rectImage.height(), rectText.width(), rectText.height());
			break;
			}
		}
		pTextObject->setRect (rect);
	break;
	}
	slotUpdateStructure ();
}

void DVDMenu::slotCreatedMovieObject (MovieObject *pMovieObject, bool bRegisterToRender)
{
  if ( pMovieObject )
       pMovieObject->setDVDMenu ( this, bRegisterToRender );
}

void DVDMenu::slotMaskColorChanged( Rgba theColor, Rgba oldColor )
{
// printf ("DVDMenu::slotMaskColorChanged <%s> <%s>\n", (const char *)theColor.name(), (const char *)oldColor.name());
  // This function is called when the user changes the color of the
  // Selected, or the Highlighted Mask from within the ButtonDialog.
  uint t, iWhichColor = MAX_MASK_COLORS - 1;
  for ( t=0; t<MAX_MASK_COLORS; t++ )  {
    if ( m_DVDMenuInterface.pgcColors[t] == oldColor )	{
      iWhichColor = t;
      break;
    }
  }
  // The rest is handled in this function.
  modifyColor ( iWhichColor, theColor, true );
}

// This function is called from the MovieDialog, when the [change Size ...] button is pressed.
void DVDMenu::changeSize ( )
{
  if ( ( m_DVDMenuInterface.qsBackgroundFileName.isEmpty ( ) ) ||
       ( m_DVDMenuInterface.backgroundImage.isNull       ( ) ) )
    return;

  QString fileName = getInterface ( )->qsBackgroundFileName;

  if ( fileName.isNull ( ) ) {
    fileName = getInterface()->qsMovieFileName;

    if ( fileName.isNull ( ) )
      return;
    readBackgroundFile ( fileName );
  }
  QString *pResizeAlgo = NULL;
  if ( ! m_DVDMenuInterface.qsResizeAlgo.isEmpty ( ) )
    pResizeAlgo = &m_DVDMenuInterface.qsResizeAlgo;
  addBackground ( fileName, pResizeAlgo, true );
}

// This function is called from the [Add Background] - button.
void DVDMenu::readBackgroundFile ( QString &fileName )
{
  Utils      theUtil;
  QTime      zeroTime;
  QString    qsExtensions;
  QFileInfo  backgroundInfo ( fileName );
  MediaInfo *pMediaInfo = getDVDAuthor ( )->getMediaInfo ( );
  qsExtensions = pMediaInfo->getExtensions ( true );

  if (qsExtensions.find ( "."+backgroundInfo.extension ( FALSE  ) ) > -1 )  {
    getInterface ( )->qsMovieFileName = fileName;
    // Okay let us get the first frame of the game as a screenshot ...
    pMediaInfo->setFileName ( fileName, true ); //, false );
    QImage theImage = pMediaInfo->getScreenshot( 0 );
    getInterface ( )->timeOffset   = zeroTime;
    getInterface ( )->timeDuration = zeroTime.addMSecs ( pMediaInfo->getLength ( ) );
    getInterface ( )->qsPause      = "0";  // no pause for MovieBackgrounds
    // Then we save the screenshot in the temp dir
    fileName = theUtil.getTempFile ( backgroundInfo.baseName ( ) )+QString( ".png" );
    theImage.save ( fileName, "PNG" );
  }
  else  {  // Not a movie file, then we should reset this ...
    getInterface ( )->qsMovieFileName = QString ( );
    if ( getInterface ( )->qsPause == "0" )
         getInterface ( )->qsPause = "inf";
  }
}

// This function is called from the [Add Background] - button.
void DVDMenu::slotAddBackground()
{
  Utils theUtil;
  QString qsExtensions;

  QDVDAuthor *pDVDAuthor = getDVDAuthor ( );
  if ( ! pDVDAuthor )
    return;

  DVDMenu *pMenu = pDVDAuthor->getCurrentSubMenu ( );
  if ( pMenu && pMenu != this )  {
       pMenu->slotAddBackground ( );
       return;
  }

  if ( ! pDVDAuthor->checkForNewProject ( ) )
    return;

  QString qsImageFilter      = pDVDAuthor->getImageFilter ( );
  QString qsMovieFilter      = pDVDAuthor->getMovieFilter ( );
  MediaInfo *pMediaInfo      = pDVDAuthor->getMediaInfo   ( );
  void *pExistingMediaEngine = NULL;
  if ( pMediaInfo )
       pExistingMediaEngine  = pMediaInfo->getMediaEngine   ( );

  //  QString fileName = QFileDialog::getOpenFileName ( Global::qsCurrentPath, QString ("Images (") + qsImageFilter + QString (");;Movies (") + qsMovieFilter + QString (");;All (*)"));
  QString fileName = FilePreviewDialog::getOpenFileName ( pExistingMediaEngine, Global::qsCurrentPath, QString ("Images ( ") + qsImageFilter + QString (" );;Movies ( ") + qsMovieFilter + QString (" );;All ( * )"));

  if (fileName.isNull())
    return;

  QFileInfo fileInfo  ( fileName );
  QString qsPath = fileInfo.dirPath ( TRUE );
  Global::qsCurrentPath = qsPath;

  initBackground ( fileName );
}

void DVDMenu::initBackground ( QString &fileName )
{
  if ( fileName.isEmpty ( ) )
    return;
  readBackgroundFile ( fileName );
  addBackground      ( fileName );
}

void DVDMenu::addBackground ( QString &fileName, QString *pResizeAlgo, bool bForceDialog )
{
	bool bOpenDialog = bForceDialog;
	QString qsResizeAlgo ( QT_RESIZE_ALGO );
	QPixmap theBackground = QPixmap ( fileName );
	// Now we check if the image has already the right format for PAL / NTSC / SECAM
	int iHeight = theBackground.height ( );
	int iWidth  = theBackground.width  ( );
	int iFormat = getFormat (iWidth, iHeight);
	// And we might need those ...
	int iStretchType = m_DVDMenuInterface.iStretchType;
	QSize posOffset  = m_DVDMenuInterface.posOffset;
	QString qsRatio  = m_DVDMenuInterface.qsRatio;
	if ( (pResizeAlgo) && (iFormat == FORMAT_NONE) )	{
		iWidth        = m_DVDMenuInterface.iWidth;
		iHeight       = m_DVDMenuInterface.iHeight;
		iFormat       = getFormat ( iWidth,iHeight );
		qsResizeAlgo  = *pResizeAlgo;
		theBackground = QPixmap   ( 1, 1 );
	}
	else if ( (iFormat == FORMAT_NONE) || ( bForceDialog ) ) {
		int iReturn = MessageBox::warning (NULL, tr ("Wrong IMAGE size (%1 x %2)").arg(iWidth).arg(iHeight),
			tr ("This image is neither PAL, nor NTSC. For a DVD the size has to fit either :\n"
			    "NTSC -> 720x480, 704x480, 352x480, 352x240 (29.97 Hz)\n"
			    "PAL    -> 720x576, 704x576, 352x576, 352x288 (25 Hz)\n"
			    "You need to resize this image sooner or later. Do you want to resize now ?"), 
			QMessageBox::Yes|QMessageBox::Default,  QMessageBox::No|QMessageBox::Escape);
		if (iReturn == QMessageBox::Yes)
			bOpenDialog = true;
	}
	else {
	  m_DVDMenuInterface.backgroundImage = QPixmap  ( theBackground );
	  m_pPixmapMenu->setPixmap  (  (const  QPixmap &) theBackground );
	}
	if ( bOpenDialog )  {
		// save some memory while doing all the resize work etc.
		theBackground = QPixmap (1,1);
		CResizeDialog resizeDialog;
		resizeDialog.m_posOffset    = posOffset;
		resizeDialog.m_iFormat      = iFormat;
		resizeDialog.m_iStretchType = iStretchType;
		resizeDialog.setFilename(fileName);
		resizeDialog.m_pComboAspect->setCurrentText ( qsRatio );
		if (resizeDialog.exec () == QDialog::Rejected)
			return;
		iWidth       = resizeDialog.m_pEditWidth ->text().toInt();
		iHeight      = resizeDialog.m_pEditHeight->text().toInt();
		qsRatio      = resizeDialog.m_pComboAspect->currentText();
		iFormat      = resizeDialog.m_iFormat;
		iStretchType = resizeDialog.m_iStretchType;
		posOffset    = resizeDialog.m_posOffset;
		if (iWidth < 1)
			iWidth = 720;
		if (iHeight < 1)
			iHeight = 480;
		qsResizeAlgo = resizeDialog.comboResizeAlgorithm->currentText();
		theBackground = *resizeDialog.m_pPixmapPreview->pixmap ();
		m_DVDMenuInterface.backgroundImage = theBackground;
		m_pPixmapMenu->setPixmap ( (const QPixmap &) theBackground);
	}
	getUndoBuffer ( )->push ( new DVDMenuUndoObject(DVDMenuUndoObject::NEW_BACKGROUND, (QPixmap &) *m_pPixmapMenu->paletteBackgroundPixmap(), &m_DVDMenuInterface));

	// This has to be done AFTER the undo-object has been created.
//	m_pPixmapMenu->setPixmap ( (const QPixmap &) theBackground);
	// And finally we set the interface (to store the dvd project file in DVDAuthor class)
	m_DVDMenuInterface.qsBackgroundFileName = fileName;
	m_DVDMenuInterface.iFormat              = iFormat;
	m_DVDMenuInterface.iWidth               = iWidth;
	m_DVDMenuInterface.iHeight              = iHeight;
	m_DVDMenuInterface.qsRatio              = qsRatio;
	m_DVDMenuInterface.qsResizeAlgo         = qsResizeAlgo;
	m_DVDMenuInterface.iStretchType         = iStretchType;
	m_DVDMenuInterface.posOffset            = posOffset;
	m_DVDMenuInterface.bModified            = true;
	// Okay we should also add something to the QListView
	if (!m_selectedMask.isNull())
		setMask (m_DVDMenuInterface.qsSelectedMaskFileName, SELECTED_MASK );
	if (!m_highlightedMask.isNull())
		setMask (m_DVDMenuInterface.qsHighlightedMaskFileName, HIGHLIGHTED_MASK );
	
	refresh ();
}

void DVDMenu::refresh()
{
  slotUpdateStructure ( );
  if ( m_pPixmapMenu )	{
    m_pPixmapMenu->update       ( );
    m_pPixmapMenu->updatePixmap ( );
  }
}

void DVDMenu::slotAnimateObject ( QString &qsTempAnim, int iType, QString qsFontName )
{
  // This function gets the Animation Dialog
  // Within this dialog, you can create a script
  // (or hardcode) Attributes of the object.
  // Before rendering the menu the script will 
  // get executed and all data sent to stdout 
  // will be captured in the data file, wich 
  // will provide the data for the animation.
  QString qsEmpty, qsAnimation;
  DialogAnimation dialog;

  if ( DialogAnimation::TypeText == iType )
    dialog.setFontName ( qsFontName );

  qsAnimation = qsTempAnim;
  // anim, total Frames, FPS
  dialog.initMe ( qsAnimation, framesToRender ( ), fps ( ), iType );
  if ( dialog.exec ( )  == QDialog::Accepted )
    qsAnimation = dialog.string ( );

  // And then we set the passed QString object.
  if ( qsAnimation.length ( ) < 5)
    qsTempAnim = qsEmpty;
  else
    qsTempAnim = qsAnimation;
}

void DVDMenu::slotAddSound ( )
{
  QDVDAuthor *pDVDAuthor = getDVDAuthor ( );
  if ( ! pDVDAuthor )
    return;

  DVDMenu *pMenu = pDVDAuthor->getCurrentSubMenu ( );
  if ( pMenu && pMenu != this )  {
       pMenu->slotAddSound ( );
       return;
  }

  if ( ! pDVDAuthor->checkForNewProject ( ) )
    return;

  uint t, iCounter=0;
  SourceFileEntry *pEntry;
  for (t=0;t<m_DVDMenuInterface.listSoundEntries.count ();t++)	{
    pEntry = pDVDAuthor->getSourceEntryByDisplayName ( m_DVDMenuInterface.listSoundEntries[t]->qsFileName );
    if ( ! pEntry )
      break;
    iCounter += pEntry->listFileInfos.count();
  }
  if (iCounter > 7)	{
    MessageBox::warning (NULL, tr ("Too many sound files"),
			 tr ("A DVD can at a maximum take 8 soundtracks.\n"), QMessageBox::Ok,  QMessageBox::NoButton);
    return;
  }

  QStringList listAddMovies, listFileNames;
  QString   qsFileName, qsExtension;
  QFileInfo fileInfo;
  QString   qsMovieFilter    = pDVDAuthor->getMovieFilter ( );
  QString   qsFilter         = pDVDAuthor->getSoundFilter ( );
  QString   qsDialogFilter   = tr ("Sound Files (") + qsFilter + QString(")");

  listFileNames = FilePreviewDialog::getOpenFileNames ( Global::qsCurrentPath, QString::null, m_pPixmapMenu, "SoundFilesDialog", tr( "Select sound files" ), &qsDialogFilter );

  if ( listFileNames.count ( ) < 1)
    return;

  // Just making sure we did select Audio files (simple extensions based selection)
  for ( t=0; t<listFileNames.count ( ); t++ ) {
    qsFileName = listFileNames[t];
    fileInfo.setFile ( qsFileName );
    qsExtension = fileInfo.extension ( FALSE ).lower ( );
    if ( qsMovieFilter.find ( qsExtension ) > -1 ) {
      listAddMovies.append  ( qsFileName  );
      listFileNames.remove  ( qsFileName  );
    }
  }

  if ( iCounter+listFileNames.count ( ) > 7 )	{
    MessageBox::warning (NULL, tr ("Too many sound files"),
			 tr ("A DVD can at a maximum take 8 soundtracks.\nI will only use the first %1 files.").arg(8-iCounter), QMessageBox::Ok,  QMessageBox::NoButton);
    QStringList listFileNames2 = listFileNames;
    listFileNames.clear ();
    for (t=0;t<8-iCounter;t++)
      listFileNames.append (listFileNames2[t]);
  }

  fileInfo.setFile ( listFileNames[0] );
  QString qsPath = fileInfo.dirPath ( TRUE );
  Global::qsCurrentPath = qsPath;

  if ( listAddMovies.count  ( ) > 0 )
    pDVDAuthor->addMovieList( listAddMovies );

  if ( listFileNames.count  ( ) > 0 )  {
    pDVDAuthor->addSound    ( listFileNames );
    // After we added the sound to the SourceToolBar I would like to add this here ...
    // The last one is the one just created.
    SourceFileEntry *pNewEntry = pDVDAuthor->sourceFileEntry ( pDVDAuthor->sourceFileCount ( ) -1 );
    if ( ! pNewEntry )
      return;

    int iFreeAudioNumber = 0;
    for ( t=0; t<m_DVDMenuInterface.listSoundEntries.count ( ); t++ )  {
      if ( iFreeAudioNumber == m_DVDMenuInterface.listSoundEntries[t]->iAudioNumber ) {
        iFreeAudioNumber ++;
        t = 0;
      }
    }
    if ( iFreeAudioNumber > 7 ) {
      // Error
      pDVDAuthor->removeSourceFileEntry ( pNewEntry );
      return;
    }

    Audio *pNewAudio = new Audio;
    pNewAudio->iAudioNumber = iFreeAudioNumber;
    pNewAudio->qsIso639     = Global::qsDefaultLanguage;
    pNewAudio->qsFileName   = pNewEntry->qsDisplayName;
    m_DVDMenuInterface.listSoundEntries.append ( pNewAudio );

    // Lastly we check if the duration is right
    bool bCheckMovies, bCheckAudio;
    bCheckMovies = false;
    bCheckAudio  = true;
    QString qsDifference = checkDuration ( bCheckMovies, bCheckAudio );
    if ( bCheckAudio )  {
      // Okay we should display waht has to be said
      QSize size ( 750, 300 );
      qsDifference += tr ( "&nbsp;<p><b>Do you want to adjust the length of the menu now ?</b><p>" );
      int iRet = MessageBox::html ( getMenuPreview ( ), tr ( "Found issues." ), qsDifference, size, QMessageBox::Yes, QMessageBox::No );
      if ( iRet == QMessageBox::Yes )
        slotEditTimeline ( );
    }
  }
  slotUpdateStructure ( );
}

void DVDMenu::slotAddIntro ( )
{
  void      *pExistingMediaEngine = NULL;
  MediaInfo *pMediaInfo    = getDVDAuthor()->getMediaInfo   ( );
  QString    qsMovieFilter = getDVDAuthor()->getMovieFilter ( );
  if ( pMediaInfo )
    pExistingMediaEngine   = pMediaInfo->getMediaEngine   ( );

  QString qsFileName = FilePreviewDialog::getOpenFileName ( pExistingMediaEngine, Global::qsCurrentPath, QString ("Movies ( ") + qsMovieFilter + QString ( ");;All ( * )"));

  if ( qsFileName.isNull ( ) )
    return;

  CXmlDVDAuthor::vob_struct *pVobInfo = new CXmlDVDAuthor::vob_struct;
  pVobInfo->file = qsFileName;
  pVobInfo->pause = "once";

  UndoBuffer *pBuffer = getUndoBuffer ( );
  if ( pBuffer )
       pBuffer->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::EDIT_MENU, this ) );

  QValueList<CXmlDVDAuthor::vob_struct *>::iterator it = m_DVDMenuInterface.listIntroVobs.begin ( );
  while ( it != m_DVDMenuInterface.listIntroVobs.end ( ) )
    delete *it++;

  m_DVDMenuInterface.listIntroVobs.clear  ( );
  m_DVDMenuInterface.listIntroVobs.append ( pVobInfo );
  slotUpdateStructure ( );
}

void DVDMenu::slotAddExtro ( )
{
  void      *pExistingMediaEngine = NULL;
  MediaInfo *pMediaInfo    = getDVDAuthor()->getMediaInfo   ( );
  QString    qsMovieFilter = getDVDAuthor()->getMovieFilter ( );
  if ( pMediaInfo )
    pExistingMediaEngine   = pMediaInfo->getMediaEngine   ( );

  QString qsFileName = FilePreviewDialog::getOpenFileName ( pExistingMediaEngine, Global::qsCurrentPath, QString ("Movies ( ") + qsMovieFilter + QString ( ");;All ( * )"));

  if ( qsFileName.isNull ( ) )
    return;

  CXmlDVDAuthor::vob_struct *pVobInfo = new CXmlDVDAuthor::vob_struct;
  pVobInfo->file = qsFileName;
  pVobInfo->pause = "multi";

  UndoBuffer *pBuffer = getUndoBuffer ( );
  if ( pBuffer )
       pBuffer->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::EDIT_MENU, this ) );

  QValueList<CXmlDVDAuthor::vob_struct *>::iterator it = m_DVDMenuInterface.listExtroVobs.begin ( );
  while ( it != m_DVDMenuInterface.listExtroVobs.end ( ) )
    delete *it++;
  m_DVDMenuInterface.listExtroVobs.clear  ( );
  m_DVDMenuInterface.listExtroVobs.append ( pVobInfo );
  slotUpdateStructure ( );
}

void DVDMenu::removeBackgroundAudio ( QString &qsAudioEntry, bool /* bRequestConfirmation */ )
{
  // This function will remove the backgroundAudio from this menu and check if the 
  // entry is used in another menu. If not it will remove the Entry from the SourceToolbar as well.
  QDVDAuthor  *pDVDAuthor = getDVDAuthor ( );
  SourceFileEntry *pEntry = NULL;
  if ( pDVDAuthor ) {
    // At this point we should actually check if the audio entry is used in other menus
    QValueList<DVDMenu *> listOfSubMenus = pDVDAuthor->getSubMenus ( );
    listOfSubMenus.prepend ( pDVDAuthor->getVMGMenu ( ) );
    for ( unsigned int t=0; t<listOfSubMenus.count ( ); t++ ) {
      if ( listOfSubMenus[t] == this )
	continue;
      if ( listOfSubMenus[t]->isSourceEntryUsed ( qsAudioEntry ) ) {
	// So this audio is used in another SubMenu, So let's leave it in the SourceTolbar
	removeSourceEntry ( qsAudioEntry );
	return;
      }
    }
    // At this point we are sure the background audio was only used by this DVDMenu
    // So we can savely remove the whole entry from the SourceToolbar and all ...
    pEntry = pDVDAuthor->getSourceEntryByDisplayName ( qsAudioEntry );
  }
  if ( pEntry )
    removeSourceFileEntry ( pEntry );
}

void DVDMenu::removeSourceEntry ( QString &qsRemoveName )
{
  uint t, i, iRemoved;
  QStringList listButtonAction, listMultiple;
  QString qsTemp;
  QValueList<ButtonObject *> listButtons = getButtons ( );
  ButtonObject *pButton;
  iRemoved = 0;
  // the first step is to remove all entries from the Interface (which
  // holds the list of the sound files).
  for (t=0;t<m_DVDMenuInterface.listSoundEntries.count();t++)	{
    Audio *pAudio = m_DVDMenuInterface.listSoundEntries[t];
    qsTemp = pAudio->qsFileName;
    if ( qsTemp == qsRemoveName ) {
      iRemoved += m_DVDMenuInterface.listSoundEntries.remove ( pAudio );
      delete pAudio;
    }
  }

  // The second step is to check all button objects...
  qsTemp = QString ( );
  for ( t=0; t<listButtons.count ( );t++ )  {
    pButton = listButtons[t];
    if ( ! pButton )
      continue;
    listMultiple = pButton->getPlayMultipleList ( );
    // here we dwell into the buttons supposed action ...
    listButtonAction = QStringList::split ( STRING_SEPARATOR, pButton->action ( ) );
    if ( ( listButtonAction.count ( ) == 3 ) || ( listButtonAction.count ( ) == 4 ) )  {
      // Here we got ourself a button connected to something ...
      if ( listButtonAction[1] == qsRemoveName )  {
	pButton->setAction ( qsTemp );
	pButton->setSourceFileEntry ( NULL );
	iRemoved ++;
      }
    }
    if ( listMultiple.count ( ) > 0 ) { 
      QStringList listTemp = listMultiple;
      // here we dwell into buttons which play multiple files
      for ( i=0; i<listTemp.count ( ); i++ ) {
	listButtonAction = QStringList::split ( STRING_SEPARATOR, listTemp[i] );
	// Here we got ourself a button connected to something ...
	if ( listButtonAction[1] == qsRemoveName )  {
	  listMultiple.remove ( listTemp[i] );
	  iRemoved ++;
	}
      } // end for loop
      if ( iRemoved > 0 ) {
	// Set the first PlayMultiple entry to also be the buttonAction
	if ( listMultiple.count ( ) > 0 ) {
	  pButton->setAction ( listMultiple[0] );
	  pButton->setSourceFileEntry ( getEntryFromButtonAction ( pButton->action ( ) ) );
	}
	// if only one entry remains, then we have a simple buton left.
	if ( listMultiple.count ( ) == 1 )
	  listMultiple.clear ( );
	pButton->setPlayMultipleList  ( listMultiple );
      }
    } // end else
  } // end for listButtons
  
  if ( iRemoved > 0 )
    slotUpdateStructure ( );
}

void DVDMenu::removeSourceFileEntry (SourceFileEntry *pSourceFileEntry)
{
  getDVDAuthor ( )->removeSourceFileEntry ( pSourceFileEntry );
  removeSourceEntry ( pSourceFileEntry->qsDisplayName );
}

void DVDMenu::appendSourceFileEntry ( SourceFileEntry *pSourceFileEntry )
{
  int t, iFreeAudioNumber = 0;
  for ( t=0; t<(int)m_DVDMenuInterface.listSoundEntries.count ( ); t++ ) {
    if ( iFreeAudioNumber == m_DVDMenuInterface.listSoundEntries[t]->iAudioNumber ) {
      iFreeAudioNumber ++;
      t = 0;
    }
  }
  if ( iFreeAudioNumber > 7 ) {
    // Error 
    return;
  }
  getDVDAuthor ( )->appendSourceFileEntry ( pSourceFileEntry );

  Audio *pAudio = new Audio;
  pAudio->iAudioNumber = iFreeAudioNumber;
  pAudio->qsIso639     = Global::qsDefaultLanguage;
  pAudio->qsFileName   = pSourceFileEntry->qsDisplayName;
  m_DVDMenuInterface.listSoundEntries.append ( pAudio );
  slotUpdateStructure ( );
}

bool DVDMenu::isSourceEntryUsed ( QString &qsInquireEntry )
{
  uint t, i;
  QString qsAction;
  QStringList listButtonAction;
  // This function is called when the user wants to delete a SourceFileEntry
  // it returns true if the entry is in use.

  // Two steps : The first is to check all entries in the DVDMenu->interface
  CDVDMenuInterface *pInterface = getInterface();
  for (t=0;t<pInterface->listSoundEntries.count();t++)	{
    if (pInterface->listSoundEntries[t]->qsFileName == qsInquireEntry)
      return true;
  }

  // The second step is to check all button objects...
  QStringList listMultiple;
  QValueList<ButtonObject *> listButtons = getButtons ( );
  for ( t=0; t<listButtons.count ( ); t++ )  {
    listMultiple = listButtons[t]->getPlayMultipleList ( );
    if ( listMultiple.count ( ) < 1 ) {
      // here we dwell into the buttons supposed action ...
      listButtonAction = QStringList::split ( STRING_SEPARATOR,  listButtons[t]->action ( ) );
      if ( ( listButtonAction.count ( ) == 3 ) || 
	   ( listButtonAction.count ( ) == 4 ) ) {
	// Here we got ourself a button connected to something ...
	if ( ( listButtonAction[1] == qsInquireEntry ) ||
	     ( listButtonAction[2] == qsInquireEntry ) )
	  return true;
      }
    }
    else {
      // here we dwell into buttons which play multiple files
      for ( i=0; i<listMultiple.count ( ); i++ ) {
	listButtonAction = QStringList::split ( STRING_SEPARATOR, listMultiple[i] );
	// Here we got ourself a button connected to something ...
	if ( ( listButtonAction[1] == qsInquireEntry ) || 
	     ( listButtonAction[2] == qsInquireEntry ) )
	  return true;
      } // end for loop
    } // end else
  }
  return false;
}

void DVDMenu::replaceSourceDisplayName (QString &qsOriginalDisplayName, QString &qsNewDisplayName)
{
  uint t, i;
  QString qsAction;
  // This function is called when the user changed the DisplayName of a SourceFileEntry
  // DialogMovie::accept()->SourceToolBar::slotEditMovie->QDVDAuthor::replaceSourceDisplayName()

  // Two steps : The first is to change all entries from the Interface ...
  CDVDMenuInterface *pInterface = getInterface();
  for (t=0;t<pInterface->listSoundEntries.count();t++)	{
    if (pInterface->listSoundEntries[t]->qsFileName == qsOriginalDisplayName)
      pInterface->listSoundEntries[t]->qsFileName = qsNewDisplayName;
  }

  // The second step is to go through all buttons and see what they are up to ...
  QValueList<ButtonObject *> listButtons = getButtons();
  QStringList listButtonAction, listMultiple;
  for ( t=0; t<listButtons.count ( ); t++ )  {
    listMultiple = listButtons[t]->getPlayMultipleList ( );
    // here we dwell into the buttons supposed action ...
    listButtonAction = QStringList::split(STRING_SEPARATOR,  listButtons[t]->action());
    if ( ( listButtonAction.count ( ) == 3 ) || 
	 ( listButtonAction.count ( ) == 4 ) )  {
      // Here we got ourself a button connected to something ...
      if ( listButtonAction[1] == qsOriginalDisplayName )  {
	   listButtonAction[1]  = qsNewDisplayName;
	qsAction = listButtonAction.join ( STRING_SEPARATOR );
	listButtons[t]->setAction ( qsAction );
      }
    }
    if ( listMultiple.count ( ) > 0 ) {
      // here we dwell into buttons which play multiple files
      for ( i=0; i<listMultiple.count ( ); i++ ) {
	listButtonAction = QStringList::split ( STRING_SEPARATOR, listMultiple[i] );
	if ( ( listButtonAction.count ( ) == 3 ) || 
	     ( listButtonAction.count ( ) == 4 ) )  {
	  // Here we got ourself a button connected to something ...
	  if ( listButtonAction[1] == qsOriginalDisplayName )  {
	       listButtonAction[1]  = qsNewDisplayName;
	    qsAction = listButtonAction.join(STRING_SEPARATOR);
	    listButtons[t]->setAction (qsAction);
	  }
	}
      }
    }
  }
}

void DVDMenu::replaceMenuName ( QString &qsOriginalMenuName, QString &qsNewMenuName )
{
  uint t;
  QString qsAction;
  // This function is called when the user changed the MenuName.
  // Here we'll check if any button is currently assigned to this menu and change it if required.

  QValueList<ButtonObject *> listButtons = getButtons ( );
  QStringList listButtonAction, listMultiple;
  for ( t=0; t<listButtons.count ( ); t++ )  {
    // here we dwell into the buttons supposed action ...
    listButtonAction = QStringList::split ( STRING_SEPARATOR, listButtons[t]->action ( ) );
    if ( listButtonAction.count ( ) == 2 )  {
      // Here we got ourself a button connected to something ...
      if ( listButtonAction[1] == qsOriginalMenuName)	{
	   listButtonAction[1]  = qsNewMenuName;
	   qsAction = listButtonAction.join ( STRING_SEPARATOR );
	   listButtons[t]->setAction ( qsAction );
      }
    }

    // Note: for ListPlayMultiple only the last entry could possibly be a menu
    listMultiple = listButtons[t]->getPlayMultipleList ( );
    if ( listMultiple.count ( ) > 0 ) {
      qsAction = listMultiple.last ( );
      listButtonAction = QStringList::split ( STRING_SEPARATOR, qsAction );
      if ( listButtonAction.count ( ) == 2 ) {
	// Here we got ourself a button connected to something ...
	if ( listButtonAction[1] == qsOriginalMenuName )  {
	  listButtonAction[1]  = qsNewMenuName;
	  listMultiple.remove ( qsAction );
	  qsAction = listButtonAction.join ( STRING_SEPARATOR );
	  listMultiple.append ( qsAction );
	  listButtons[t]->setPlayMultipleList ( listMultiple );
	}
      }
    }
  }
}

QString DVDMenu::checkButtonsOverlapping   ( )
{
  uint    t, i;
  QString qsReturn;
  QRect   theRect;
  ButtonObject *pButton1, *pButton2;

  QValueList<ButtonObject *>listOfButtons = getButtons ( );
  // None or only one button, return empty
  if ( listOfButtons.count() < 2 )
    return qsReturn;

  for (t=0;t<listOfButtons.count();t++) {
    pButton1 = listOfButtons[t];
    if ( ! pButton1 )
      continue;
    theRect  = pButton1->boundingRect ( );
    for (i=t+1;i<listOfButtons.count ();i++) {
      pButton2 = listOfButtons[i];
      if ( ! pButton2 ) 
	continue;
      if ( theRect.intersects ( pButton2->boundingRect ( ) ) ) {
	// create the header info ...
	if ( qsReturn.isEmpty ( ) )
	  qsReturn = QString ( "<BR><B>[%1]</B><BR>" ).arg ( name ( ) );
	qsReturn  += tr ( "Button <B>[%1]</B> overlapping <B>[%2]</B><BR>" ).arg ( pButton1->name ( ) ).arg ( pButton2->name ( ) );
      }
    }
  }

  return qsReturn;
}

void DVDMenu::slotAddHighlightedMask()
{
  if ( ! getDVDAuthor ( )->checkForNewProject ())
    return;

  QString qsImageFilter      = getDVDAuthor ( )->getImageFilter ( );
  MediaInfo *pMediaInfo      = getDVDAuthor ( )->getMediaInfo   ( );
  void *pExistingMediaEngine = NULL;
  if ( pMediaInfo )
    pExistingMediaEngine  = pMediaInfo->getMediaEngine   ( );
  
  QString fileName = FilePreviewDialog::getOpenFileName ( pExistingMediaEngine, Global::qsCurrentPath, QString ("Images ( ") + qsImageFilter + QString ( ");;All ( * )"));
  //  QString fileName = QFileDialog::getOpenFileName ( Global::qsCurrentPath, QString ("Images (") + qsImageFilter + QString (");;Movies (") + qsMovieFilter + QString (");;All (*)"));
  //  QString fileName = QFileDialog::getOpenFileName ( Global::qsCurrentPath, tr ("Images (")+qsFilter+QString(")"));
  if (fileName.isNull())
    return;

  QFileInfo fileInfo  (fileName);
  QString qsPath = fileInfo.dirPath ( TRUE );
  Global::qsCurrentPath = qsPath;

  m_DVDMenuInterface.qsHighlightedMaskFileName = fileName;
  setMask(fileName, HIGHLIGHTED_MASK);
}

void DVDMenu::slotAddSelectedMask()
{
  if ( ! getDVDAuthor ( )->checkForNewProject ( ) )
    return;

  QString qsImageFilter      = getDVDAuthor ( )->getImageFilter ( );
  MediaInfo *pMediaInfo      = getDVDAuthor ( )->getMediaInfo ( );
  void *pExistingMediaEngine = NULL;
  if ( pMediaInfo )
    pExistingMediaEngine  = pMediaInfo->getMediaEngine   ( );

  QString fileName = FilePreviewDialog::getOpenFileName ( pExistingMediaEngine, Global::qsCurrentPath, QString ("Images ( ") + qsImageFilter + QString (" );;All ( * )"));
  //QString fileName = QFileDialog::getOpenFileName ( Global::qsCurrentPath, tr ("Images (")+qsFilter+QString(")"));
  if (fileName.isNull())
    return;

  QFileInfo fileInfo  (fileName);
  QString qsPath = fileInfo.dirPath ( TRUE );
  Global::qsCurrentPath = qsPath;

  m_DVDMenuInterface.qsSelectedMaskFileName = fileName;
  setMask(fileName, SELECTED_MASK);
}

void DVDMenu::setMask (QString & fileName, uint iWhichMask)
{
	QImageHelper theMask (fileName, 0);
	// Sanity check ...
	uint iColorCount = theMask.countColors (); //theMask);

	if ( iColorCount > MAX_MASK_COLORS )	{
		int iReturn = MessageBox::warning (NULL, tr ("Image has too many colors"),
			tr ("This mask has too many colors. Only 4 colors are allowed for the mask.\n\n"
			"Do you want to decrease the number of colors to 4 ?"
			    ), QMessageBox::Yes|QMessageBox::Default,  QMessageBox::No|QMessageBox::Escape);
			if (iReturn == QMessageBox::Yes)
				theMask.dither (MAX_MASK_COLORS);
	}
	//

	// Dialog to choose the transparent color from ...

	//

	// Here we ensure that there is a background Image present.
	if (m_DVDMenuInterface.backgroundImage.isNull())	{
		displayMask(iWhichMask);
		slotUpdateStructure();
		return;
	}

	QImage theBackground = m_DVDMenuInterface.backgroundImage.convertToImage();
	int x, y, xMax, yMax;
	QRgb thePixel, theMaskColor = 0x00000000;
	// Here is the algol, to filter out the transparent background color of the mask
	// and overlay the remaining pixel to the background.

	// This test is to ensure that the smallest dimensions are taken from both images.
	xMax = (theMask.width () < theBackground.width ()) ? theMask.width () : theBackground.width ();
	yMax = (theMask.height() < theBackground.height()) ? theMask.height() : theBackground.height();

	theMaskColor = theMask.getMaskColor ();

	for (y=0;y<yMax;y++)	{
		for (x=0;x<xMax;x++)	{
			thePixel = theMask.pixel(x, y);
//			if ( (thePixel != theMaskColor) && (thePixel != 0xff000000) )
			if (thePixel != theMaskColor)
				theBackground.setPixel (x, y, thePixel);
		}
	}

	if (iWhichMask == SELECTED_MASK)	{
		m_selectedMask.convertFromImage ( theBackground );
		// and then we should keep the mask itself as well (remember we might have changed the color depth).
		m_DVDMenuInterface.selectedMask = theMask;
	}
	else if (iWhichMask == HIGHLIGHTED_MASK)	{
		m_highlightedMask.convertFromImage ( theBackground );
		m_DVDMenuInterface.highlightedMask = theMask;
	}

	displayMask (iWhichMask);
	slotUpdateStructure ();
}

void DVDMenu::createMask(QString &qsFileName, int iWhichMask, bool bForceDrawing)
{
  // Called from QDVDAuthor::createDVD()
  uint t, i, iWidth, iHeight;
  // This function is called from QDVDAuthor::createMenuXml() and will first create the
  // 4 colored mask and then store it to a file.
  QPixmap theMask;
  QPainter thePainter;
  ButtonObject *pButton;

  iWidth  = 720;
  iHeight = 480;
  if ( ! m_DVDMenuInterface.backgroundImage.isNull() ) {
    iWidth  = m_DVDMenuInterface.backgroundImage.width ();
    iHeight = m_DVDMenuInterface.backgroundImage.height();
  }

  // Here we draw the appropriate mask.
  theMask  = QPixmap ( iWidth, iHeight, QPixmap::defaultDepth (), QPixmap::NoOptim );
  theMask.fill ( m_DVDMenuInterface.pgcColors[0].rgb ( ) );

  // Check if we draw the Background image
  if (iWhichMask == BACKGROUND_IMG)	{
    if ( ! m_DVDMenuInterface.backgroundImage.isNull ( ) )
      theMask = QPixmap ( m_DVDMenuInterface.backgroundImage );

    thePainter.begin ( &theMask );
    // Note, when we have a MovieMenu we want a plain background
    if (  ( ! isMovieMenu ( ) ) || ( bForceDrawing )  )  {
      for ( t=0; t<m_pPixmapMenu->objectCount ( );t++ )
        m_pPixmapMenu->menuObject ( t )->drawContents ( &thePainter );
    }
    thePainter.end ( );
    theMask.save   ( qsFileName, "JPEG", 100 );
    return;
  }

  QValueList <ButtonObject *> listButtons = getButtons();
  QRgb colors[4];
  //colors[0] = 0x00FEFFFE; // transparency color.
  colors[0] = 0xFFFFFFFF;
  colors[1] = 0xFF0000FF;
  colors[2] = 0xFF00FF00;
  colors[3] = 0xFFFF0000;
  // Here we draw the Selected or the highlighted mask
  thePainter.begin ( &theMask );
  for ( t=0;t<listButtons.count ();t++) {
    // Since we experienced problems with antialiasing text, we will temporarly change the button colors
    // to be very close together. This way no antialiasing should be performed (QFont::NoAntialias did not work)
    pButton = listButtons[t];
    pButton->replaceColor ( colors[0], m_DVDMenuInterface.pgcColors[0] );
    pButton->replaceColor ( colors[1], m_DVDMenuInterface.pgcColors[1] );
    pButton->replaceColor ( colors[2], m_DVDMenuInterface.pgcColors[2] );
    pButton->replaceColor ( colors[3], m_DVDMenuInterface.pgcColors[3] );
    pButton->drawContents ( &thePainter, iWhichMask );
    pButton->replaceColor ( m_DVDMenuInterface.pgcColors[0], colors[0] );
    pButton->replaceColor ( m_DVDMenuInterface.pgcColors[1], colors[1] );
    pButton->replaceColor ( m_DVDMenuInterface.pgcColors[2], colors[2] );
    pButton->replaceColor ( m_DVDMenuInterface.pgcColors[3], colors[3] );
  }
  thePainter.end ( );
  Utils theUtils;

  //theMask.save ( "/tmp/t0.png", "PNG", 100 );
  QImage theImage = theMask.convertToImage ( );

  //theImage.save ( "/tmp/t1.png", "PNG", 100 );
  theUtils.reduceColors ( theImage, 4, (QRgb *)&colors );
  //theImage.save ( "/tmp/t2.png", "PNG", 100 );
  theImage.setAlphaBuffer ( true );
  //theImage.save ( "/tmp/t3.png", "PNG", 100 );
  // Finally we replace the color entries with the original colors ...
  for (t=0;t<MAX_MASK_COLORS;t++) {
    for (i=t;i<MAX_MASK_COLORS;i++) {
      if ( theImage.color ( i ) == theImage.color ( t ) )
	theImage.setColor ( t, (m_DVDMenuInterface.pgcColors[t].rgb ( ) ) );
      //theImage.setColor ( t, (m_DVDMenuInterface.pgcColors[t].rgb ( ) ) | 0xFF000000 );
    }
  }
  theImage.save ( qsFileName, "PNG", 100 );
}

float DVDMenu::fps ()
{
	float fFPS;
	int  iFormat = getFormat (getInterface()->iWidth, getInterface()->iHeight);

	// The first thing we specify is the video settings ...
	fFPS = 29.97f;		// NTSC
	if (iFormat > 4)
		fFPS = 25.0f;	// PAL
	return fFPS;
}

long DVDMenu::framesToRender ( )
{
	float fDeltaSeconds, fFormatFactor;
	long iNumberOfTotalFrames;

	// The first thing we specify is the video settings ...
	fFormatFactor = fps ( );
	fDeltaSeconds = QTime().msecsTo ( getInterface ( )->timeDuration ) / 1000.0; //  10.0f;

	iNumberOfTotalFrames = (long)(fDeltaSeconds * fFormatFactor);
	return iNumberOfTotalFrames;
}

void DVDMenu::renderMenu()
{
	// This function will take the already extracted images from the menu background
	// and render the final frames (Think movieObjects)

	// Note: This function is usually called from StartMenuRender::renderDVDMenu ()
	//       though nothing is preventing you from calling this function directly.

	QDir theDir;
	QPixmap thePixmap;
	QString qsFullPath;
	long iNumberOfTotalFrames = framesToRender ();

	qsFullPath = QString ("%1/%2/%3/background/").arg(Global::qsTempPath) .arg(Global::qsProjectName).arg(getInterface()->qsMenuName);

	// Okay here we get the Directory list of the extracted image files from the directory
	theDir.setPath(qsFullPath);
	theDir.setNameFilter ("0*.jpg");
	if (theDir.count () == 0)	{
		// Okay nothing extracted, let us assume we have a backgournd image and NOT a movie.
		theDir.cd ("..");
		theDir.setNameFilter ("*"BACKGROUND_NAME); //*background.jpg");
	}

	m_iTotalFramesToRender = iNumberOfTotalFrames;
	m_iCurrentFrameToRender = 0;

	m_pDialogRenderPreview = new uiDialogRenderPreview ( getDVDAuthor ( ) );
	m_pDialogRenderPreview->show ();
	thePixmap = getMenuPreview()->renderMenu (getInterface(), 1, 2);
	m_pDialogRenderPreview->m_pLabelPreview->setFixedSize (thePixmap.size());
	m_pDialogRenderPreview->setProgressData (&thePixmap, 1, m_iTotalFramesToRender);
	m_pDialogRenderPreview->setCaption (QString ("Render Menu : %1").arg(name()));

	// the last step before rendering the Menu is to make sure that all the clips have been extracted.
	QCursor myCursor (QCursor::WaitCursor);
	QApplication::setOverrideCursor (myCursor);

	// In order to extract all infos we need at least one thread ...
	int iMaxThreads = Global::iMaxRunningThreads;
	if ( Global::iMaxRunningThreads < 1 )
		Global::iMaxRunningThreads = 1;
	QValueList<MovieObject *>  listMovieObjects = getMovieObjects();
	for (uint t=0;t<listMovieObjects.count ( ); t++)
	  listMovieObjects[t]->startConverting ( false );
	// at this point we are sure that all required MovieObjects for this menu are in the Queue.
	// Next is to wait for all clips to be converted before we continue.
	StartMenuRender::waitForExtraction (this);

	// This function will now create the data files for the animated objects 
	// I.e. we will run the script, which the user has provided and load the 
	//      output into memory of the MenuObject
	getMenuPreview()->createAnimationData (getInterface()->qsMenuName, framesToRender ());

	// And here we restore the number of threads again to its previous value.
	Global::iMaxRunningThreads = iMaxThreads;
	QApplication::restoreOverrideCursor ();

	// And finally we can render the menu
	QTimer::singleShot (0, this, SLOT(slotRenderFrame()));
/* This code would be executed to keep everything in one function but then we could not update the progress Dialog !
	for (t=0;t<iNumberOfTotalFrames;t++)	{
		thePixmap = getMenuPreview()->renderMenu (getInterface()->qsMenuName, t, iNumberOfTotalFrames);
		qsFileName.sprintf ("%s%08d.png", (const char *)qsFullPath, t);
		
		// Okay we have the newly rendered background image ... display some progress ...
		if (m_pDialogRenderPreview)	{
			m_pDialogRenderPreview->setProgressData (&thePixmap, t, iNumberOfTotalFrames);
//			QApplication::postEvent(m_pDialogRenderPreview, new QTimerEvent(PROGRESS_EVENT));
//			m_pDialogRenderPreview->repaint ();
		}

		printf ("Rendering Frame <%X> <%d> of <%d> File <%s>\n",m_pDialogRenderPreview, t, iNumberOfTotalFrames, (const char *)qsFileName);
		thePixmap.save (qsFileName, "PNG", 100); //"PNG");
	}
	// Phew done. Lets get back to StartMenuRender ...
	
	// this will release the main threat ...
	if (m_pDialogRenderPreview)
		m_pDialogRenderPreview->reject ();
//	delete m_pDialogRenderPreview;
//	m_pDialogRenderPreview = NULL;
*/
}

void DVDMenu::slotRenderFrame ()
{
	bool bPNG  = Global::bPNGRender;
	QPixmap thePixmap;
	QString qsFullPath, qsFileName;
	qsFullPath = QString ("%1/%2/%3/background/rendered_").arg(Global::qsTempPath).arg(Global::qsProjectName).arg(getInterface()->qsMenuName);
	thePixmap  = getMenuPreview()->renderMenu (getInterface(), m_iCurrentFrameToRender++, m_iTotalFramesToRender);
	qsFileName.sprintf ("%s%08ld.%s", (const char *)qsFullPath, m_iCurrentFrameToRender, bPNG ? "png" : "jpg" );
		
	// Okay we have the newly rendered background image ... display some progress ...
	if (m_pDialogRenderPreview)
		m_pDialogRenderPreview->setProgressData (&thePixmap, m_iCurrentFrameToRender, m_iTotalFramesToRender);

	//	printf ("Rendering Frame <%d> of <%d> File <%s>\n", m_iCurrentFrameToRender, m_iTotalFramesToRender, (const char *)qsFileName);
        if ( bPNG )
		thePixmap.save ( qsFileName, "PNG",  100 );
	else
		thePixmap.save ( qsFileName, "JPEG", 100 );
	if (m_iCurrentFrameToRender <= m_iTotalFramesToRender-1)
		QTimer::singleShot (0, this, SLOT(slotRenderFrame()));
	else	{	// The last frame has been rendered.
		// Okay first we get the first frames of all MovieObjects again ...
		getMenuPreview()->renderMenu (getInterface(), 0, m_iTotalFramesToRender);
		// Next we get the original background image back
		qsFileName = QString ("%1/%2/%3/"BACKGROUND_NAME).arg(Global::qsTempPath).arg(Global::qsProjectName).arg(getInterface()->qsMenuName);
		thePixmap.load ( qsFileName );
		getMenuPreview()->setPixmap ( thePixmap );
		// And last but not least we return from this render - task.
		m_iTotalFramesToRender  = 0;
		m_iCurrentFrameToRender = 0;
		if (m_pDialogRenderPreview)
			delete m_pDialogRenderPreview;
		m_pDialogRenderPreview = NULL;
		getDVDAuthor ( )->returnFromRenderMenu ();
	}
}

bool DVDMenu::renderingDone ()
{
	// This function will return if the rendering process is finished or still ongoing.
	if (!m_pDialogRenderPreview)
		return true;
	return false;
}

Rgba DVDMenu::getColor (int iNumber)
{
  if ( iNumber < MAX_MASK_COLORS )
    return m_DVDMenuInterface.pgcColors[iNumber];
  Rgba   dummy;
  return dummy;
}

void DVDMenu::slotEditTimeline ( )
{
  if ( isEmpty ( ) )
    return;

  CDVDMenuInterface origInterface;
  origInterface = *getInterface ( );
  DVDMenuUndoObject *pUndo = new DVDMenuUndoObject ( DVDMenuUndoObject::EDIT_MENU, this );

  DialogMovie movieDialog ( NULL );
  movieDialog.initMe      ( this );
  connect ( &movieDialog, SIGNAL ( signalSetThumbnail ( long ) ), this, SLOT ( slotBackgroundFromDialog ( long ) ) ); // calls SourceToolbar::slotSetThumbnail ( long )
  movieDialog.exec        (      );

  disconnect ( this, SLOT ( slotBackgroundFromDialog ( long ) ) );

  if ( ! ( origInterface == *getInterface ( ) ) )  {
    // If something has changed here, we should inseryt an undo step.
    UndoBuffer *pBuffer = getUndoBuffer ( );
    if ( pBuffer )
         pBuffer->push ( pUndo );
  }
  else
    delete pUndo;
}

void DVDMenu::slotBackgroundFromDialog ( long iMSecOffset )
{
  // called in case we have a MovieBackground and the user wants to change the backround image.
  MediaInfo *pMediaInfo = getDVDAuthor ( )->getMediaInfo ( );

  if ( pMediaInfo && ! getInterface ( )->qsMovieFileName.isEmpty ( ) ) {
    Utils      theUtil;
    QString    qsExtensions, qsFileName;
    QFileInfo  backgroundInfo ( qsFileName );

    // Okay let us get the first frame of the game as a screenshot ...
    pMediaInfo->setFileName ( getInterface ( )->qsMovieFileName, false );
    QImage theImage = pMediaInfo->getScreenshot( iMSecOffset );
    qsFileName = theUtil.getTempFile ( backgroundInfo.baseName ( ) )+QString( ".png" );
    theImage.save ( qsFileName, "PNG" );
    getInterface  ( )->qsBackgroundFileName = qsFileName;
    updateDVDMenu ( );
  }
}

bool DVDMenu::isMovieMenu ( )
{
	uint t;
	MenuObject *pMenuObject;
	QValueList<MovieObject *>listMovieObjects = getMovieObjects ();
	if (listMovieObjects.count() > 0)
		return true;

	// The second possibility is that the background itself is a movie 
	if ( ! getInterface()->qsMovieFileName.isEmpty ( ) )
	  return true;

	// The third possibility is that this menu has some kind of animation.
	if ( ! getInterface()->qsAnimation.isEmpty ())
		return true;
	
	// Finally the fourth possibility is to have animated objects
	for ( t=0; t<getMenuPreview ( )->objectCount ( ); t++ )  {
		pMenuObject = getMenuPreview ( )->menuObject ( t );
		if ( ! pMenuObject->animation( ).isEmpty ( ) )
			return true;
		if ( pMenuObject->shadow ( ) && ! pMenuObject->shadow ( )->animation ( ).isEmpty ( ) )
			return true;
		if ( pMenuObject->overlay( ) && ! pMenuObject->overlay( )->animation ( ).isEmpty ( ) )
			return true;
	}

	return false;
}

QValueList<MovieObject *> &DVDMenu::getMovieObjects()
{
	static QValueList<MovieObject *> listReturn;
	listReturn.clear ();
	uint t, i;
	MenuObject *pMenuObject;

	for ( t=0; t<getMenuPreview ( )->objectCount ( ); t++ )  {
		pMenuObject = getMenuPreview ( )->menuObject ( t );
		if (pMenuObject->objectType ( ) == BUTTON_OBJECT )  {
			ButtonObject *pButton = (ButtonObject *)pMenuObject;
			for (i=0;i< pButton->getNormalCount ( ); i++ )  {
				if (pButton->getNormal ( i )->objectType ( ) == MOVIE_OBJECT )
					listReturn.append ( (MovieObject *)pButton->getNormal ( i ) );
			}
		}
		else if (pMenuObject->objectType() == OBJECT_COLLECTION )  {
			ObjectCollection *pCollection = (ObjectCollection *)pMenuObject;
			for (i=0;i< (uint)pCollection->getCount ( );i++)	{
				if ( pCollection->getObject ( i )->objectType ( ) == MOVIE_OBJECT )
					listReturn.append ( (MovieObject *)pCollection->getObject ( i ) );
			}
		}
		else if ( pMenuObject->objectType ( ) == MOVIE_OBJECT )
			listReturn.append ( (MovieObject *)pMenuObject );
	}
	return listReturn;
}

QValueList<ButtonObject *> &DVDMenu::getButtons()
{
  static QValueList<ButtonObject *> listReturn;

  uint t, i;
  listReturn.clear();
  ButtonObject tempButton;
  ObjectCollection tempCollection;
  MenuObject *pMenuObject;
  for (t=0;t<getMenuPreview()->objectCount();t++)	{
    pMenuObject = getMenuPreview()->menuObject(t);
    if (pMenuObject->objectType() == tempButton.objectType())
      listReturn.append((ButtonObject *)pMenuObject);
    else if (pMenuObject->objectType() == tempCollection.objectType())	{
      ObjectCollection *pCollection = (ObjectCollection *)pMenuObject;
      for (i=0;i< (uint)pCollection->getCount();i++)	{
	if (pCollection->getObject(i)->objectType () == tempButton.objectType())	
	  listReturn.append((ButtonObject *)pCollection->getObject(i));
      }
    }
  }
  return listReturn;
}

SourceFileEntry *DVDMenu::getEntryFromButtonAction ( QString &qsAction )
{
  SourceFileEntry *pEntry = NULL;
  QStringList list = QStringList::split ( STRING_SEPARATOR, qsAction );
  pEntry = getDVDAuthor ( )->getSourceEntryByDisplayName ( list[1] );
  return pEntry;
}

SourceFileInfo *DVDMenu::getInfoFromButtonAction  ( QString &qsAction )
{
  uint t;
  QFileInfo fileInfo;
  SourceFileEntry *pEntry = NULL;
  QStringList list = QStringList::split ( STRING_SEPARATOR, qsAction );
  pEntry = getDVDAuthor ( )->getSourceEntryByDisplayName ( list[1] );
  if ( ! pEntry )
    return NULL;
  if ( pEntry->listFileInfos.count ( ) == 1 )
    return pEntry->listFileInfos[0];

  if ( list.count ( ) == 4 ) {
    for  ( t=0 ; t<pEntry->listFileInfos.count ( ); t++ ) {
      fileInfo.setFile ( pEntry->listFileInfos[t]->qsFileName );
      if ( fileInfo.fileName ( ) == list[2] )
	return pEntry->listFileInfos[t];
    }
  }
  return NULL;
}

DVDMenu *DVDMenu::getMenuFromButtonAction  ( QString &qsAction )
{
  QStringList list = QStringList::split ( STRING_SEPARATOR, qsAction );
  QString qsMenuName = list[1];
  if ( qsMenuName == "vmgm" )
       qsMenuName  = VMGM_LABEL;

  return getDVDAuthor ( )->getSubMenuByName ( qsMenuName );
}

QValueList<SourceFileEntry *> &DVDMenu::getSourceFileEntries ( bool bIncludePlayMultiple )
{
  // Returns a list of all SourceFileEntries which belong to this menu.
  // Note: the list holds only one entry for an SourceFileEntry even if
  //       the menu holds multiple references to it.
  static QValueList<SourceFileEntry *> listReturn;
  QValueList<ButtonObject *> listButtons = getButtons ( );
  QStringList   listMultiple;
  //  ButtonObject  tempButton;
  ButtonObject    *pButton;
  SourceFileEntry *pEntry;
  bool bFound;
  uint t, i;

  listReturn.clear ( );
  for  ( t=0; t<listButtons.count ( ); t++ )  {
    bFound  = false;
    pButton = listButtons[t];
    pEntry  = pButton->sourceFileEntry ( );
    // If no SourceEntry in ReturnList than insert it.
    // Else check if not already inserted.
    if ( (int)listReturn.count ( ) > 0 )  {
      //Check if the SourceEntry isn't already inserted.
      for  ( int k=0; k<(int)listReturn.count ( ); k++ )  {
        if ( pEntry == listReturn[k] )  {
          bFound = true;
          break;
        }
      }
    }
    //If SourceEntry not found then insert it.
    if ( ! bFound && pEntry )
      listReturn.append ( pEntry );

    listMultiple = pButton->getPlayMultipleList ( );
    for ( i=0; i<listMultiple.count ( ); i++ )  {
      pEntry = getEntryFromButtonAction ( listMultiple[i] );
      bFound = false;
      if ( pEntry ) {
        for  ( int k=0; k<(int)listReturn.count ( ); k++ )  {
          if ( pEntry == listReturn[k] )  {
            bFound = true;
            break;
          }
        }
        //If SourceEntry not found then insert it.
        if ( ! bFound && pEntry && bIncludePlayMultiple )
          listReturn.append ( pEntry );
      }
    }
  }
  return listReturn;
}

QValueList<SourceFileInfo *> &DVDMenu::getSourceFileInfos()
{
  // This function will return all SourceFileEntries actually used in this Menu.
  static QValueList<SourceFileInfo *> listReturn;
  QValueList<ButtonObject *> listButtons = getButtons ( );

  SourceFileInfo *pInfo = NULL;
  ButtonObject   *pButton;
  QStringList listMultiple;
  uint t, i;
  bool bFound = false;

  listReturn.clear();

  for ( t=0; t<listButtons.count ( ); t++ )  {
    pButton = listButtons[t];
    pInfo   = pButton->sourceFileInfo ( );
    bFound  = false;
    if ( pInfo ) {
      for  ( int k=0; k<(int)listReturn.count ( ); k++ )  {
	if ( pInfo == listReturn[k] )  {
	  bFound = true;
	  break;
	}
      }
      if ( ! bFound )
	listReturn.append( pInfo );
    }

    listMultiple = pButton->getPlayMultipleList ( );
    for ( i=0; i<listMultiple.count ( ); i++ ) {
      pInfo  = getInfoFromButtonAction ( listMultiple[i] );
      bFound = false;
      if ( pInfo ) {
	for  ( int k=0; k<(int)listReturn.count ( ); k++ )  {
	  if ( pInfo == listReturn[k] )  {
	    bFound = true;
	    break;
	  }
	}
	if ( ! bFound )
	  listReturn.append( pInfo );
      }
    }
  }
  return listReturn;
}

void DVDMenu::displayMask (uint iWhichMask)
{
	QPixmap *pMask;
	pMask = &m_highlightedMask;
	if (iWhichMask == SELECTED_MASK)
		pMask = &m_selectedMask;
	else if (iWhichMask == BACKGROUND_IMG)
		pMask = &m_DVDMenuInterface.backgroundImage;
	if (pMask->isNull())
		return;
	// And finally set the pixmap back again ...
	m_pPixmapMenu->setPixmap(*pMask);
}
/*
void DVDMenu::displayMask (uint iWhichMask)
{
printf ("DisplayMask <%d>\n", iWhichMask);
	// Here is the algol, to filter out the transparent background color of the mask
	// and overlay the remaining pixel to the background.
	QImage theBackground = QImage (m_DVDMenuInterface.qsBackgroundFileName);
	int x, y, xMax, yMax;
	QRgb thePixel, theMaskColor = 0x00000000;
	QPixmap oldPixmap;
	QImage *pMask;

	pMask = &m_DVDMenuInterface.highlightedMask;
	if (iWhichMask == SELECTED_MASK)
		pMask = &m_DVDMenuInterface.selectedMask;
	else if (iWhichMask == BACKGROUND_IMG)	{
		oldPixmap.convertFromImage ( theBackground );
		// And finally set the pixmap back again ...
		m_pPixmapMenu->setPixmap(oldPixmap);
		return;
	}

	// This test is to ensure that the smallest dimensions are taken from both images.
	xMax = (pMask->width () < theBackground.width ()) ? pMask->width () : theBackground.width ();
	yMax = (pMask->height() < theBackground.height()) ? pMask->height() : theBackground.height();

	// Here we set all pixels accordingly. If the mask's background color
	QImageHelper theImage (*pMask);
	QColor colorBackground = theImage.getBackgroundColor ();
	// Sanity check ...
	uint iColorCount = theImage.countColors (theImage);

	for (y=0;y<yMax;y++)	{
		for (x=0;x<xMax;x++)	{
			thePixel = pMask->pixel(x, y);
			if ( (thePixel != theMaskColor) && (thePixel != 0xff000000) )
				theBackground.setPixel (x, y, thePixel);
		}
	}
	oldPixmap.convertFromImage ( theBackground );
	// And finally set the pixmap back again ...
	m_pPixmapMenu->setPixmap(oldPixmap);
}
*/

void DVDMenu::slotStructureClicked ( StructureItem *pItem )
{
	if (!pItem)
		return;
	// Next we check if the user actually clicked on a BACKGROUND,HIGHLIGHTED, or SELECTED Mask of this Menu
	// Note: the Name of the Menu ought to be unique !!!
	if (pItem->text(0) == tr ("Background"))	{
		if (pItem->parent()->text(1) == m_DVDMenuInterface.qsMenuName)
			displayMask (BACKGROUND_IMG);	
	}
	else if (pItem->text(0) == tr (" Highlighted"))	{
		if (pItem->parent()->parent()->text(1)  == m_DVDMenuInterface.qsMenuName)
			displayMask (HIGHLIGHTED_MASK);
	}
	else if (pItem->text(0) == tr (" Selected"))	{
		if (pItem->parent()->parent()->text(1)  == m_DVDMenuInterface.qsMenuName)
			displayMask (SELECTED_MASK);
	}
}

int DVDMenu::getFormat (int iWidth, int iHeight)
{
  Utils theUtil;
  return theUtil.getFormat ( iWidth, iHeight );
}

CDVDMenuInterface * DVDMenu::getInterface ()
{
  return &m_DVDMenuInterface;
}

QDVDAuthor *DVDMenu::getDVDAuthor ()
{
  return Global::pApp;
}

// This slot is called when the DialogButton is created (in MenuPreview, or ButtonObject)
void DVDMenu::slotRequestSourceFiles ( )
{
  int t;
  int iSourceFileCount = getDVDAuthor ( )->sourceFileCount ( );
  // Let us get the actual list of Source files ...
  QValueList<SourceFileEntry *> listSourceFileEntries;
  for ( t=0; t<iSourceFileCount; t++ )
    listSourceFileEntries.append    ( getDVDAuthor ( )->sourceFileEntry ( t ) );
  m_pPixmapMenu->respondSourceFiles ( listSourceFileEntries );
}

// This slot is called when the DialogButton is created (in MenuPreview, or ButtonObject)
void DVDMenu::slotRequestSubMenus()
{
	uint t;
	static QStringList listSubMenus;
	listSubMenus.clear();
	QValueList<DVDMenu *> listDVDMenus = getDVDAuthor ( )->getSubMenus ( );
	
	for (t=0;t<listDVDMenus.count();t++)	{
		listSubMenus.append (listDVDMenus[t]->name());
	}
	m_pPixmapMenu->respondSubMenus(listSubMenus);
}

void DVDMenu::updateDVDMenu ( bool bDisplayError )
{
  // Check if we already have background specified ...
  if (m_DVDMenuInterface.qsBackgroundFileName.isEmpty())
    return;
  // If we have, then lets check if the file exists.
  QString qsFileName = m_DVDMenuInterface.qsBackgroundFileName;
  QFileInfo fileInfo ( qsFileName );
  if ( ! fileInfo.exists ( ) )  {	// So most likely the Background was generated from a movie background
    if ( ! m_DVDMenuInterface.qsMovieFileName.isEmpty ( ) )  {
      qsFileName = m_DVDMenuInterface.qsMovieFileName;
      fileInfo.setFile (qsFileName);
      if ( fileInfo.exists ( ) )  {
	// So now we're talking. The movie file exists
	// All we have to do is to re-generate the backgfround file.
	Utils theUtil;
	MediaInfo *pMediaInfo = getDVDAuthor ( )->getMediaInfo ( );
	pMediaInfo->setFileName ( qsFileName, false );
	QImage theImage = pMediaInfo->getScreenshot(0);
	// Then we save the screenshot in the temp dir
	m_DVDMenuInterface.qsBackgroundFileName = theUtil.getTempFile(fileInfo.baseName())+QString (".png");
	theImage.save (m_DVDMenuInterface.qsBackgroundFileName, "PNG");
	updateDVDMenu (m_DVDMenuInterface.qsBackgroundFileName);
	return;
      }
    }
    if ( bDisplayError )
      MessageBox::warning ( NULL, tr ("File not found !"),
       tr ("Warning, could not find file %1.").arg(qsFileName), QMessageBox::Ok, QMessageBox::NoButton );
    return;
  }
  updateDVDMenu ( m_DVDMenuInterface.qsBackgroundFileName );
}

void DVDMenu::updateDVDMenu (QString qsFileName)
{
	// Okay to tackle the background image generation
	QImageHelper theImage;
	QPixmap thePreview (qsFileName);
	QImageHelper theFile;
	int iDeltaX, iDeltaY, iResizeAlgorithm;

	iDeltaX = iDeltaY = iResizeAlgorithm = 0;
	// determine the algo ID which was stored as the name of the Algo ...
	QStringList listAvailAlgos = theFile.getAvailableResizeAlgorithms();
	for (uint t=0;t<listAvailAlgos.count();t++)	{
		if (listAvailAlgos[t] == m_DVDMenuInterface.qsResizeAlgo)
			iResizeAlgorithm = t;
	}

	m_pPixmapMenu->fitDVDMenuBackground (&thePreview, iResizeAlgorithm, m_DVDMenuInterface.iStretchType, m_DVDMenuInterface.posOffset, m_DVDMenuInterface.iWidth, m_DVDMenuInterface.iHeight);

	m_pPixmapMenu->setFixedSize (m_DVDMenuInterface.iWidth, m_DVDMenuInterface.iHeight);
	m_pPixmapMenu->setPixmap ( (const QPixmap &) thePreview);
	m_DVDMenuInterface.backgroundImage = thePreview;
}

DVDMenu *DVDMenu::clone ( )
{
  DVDMenu *pMenu = new DVDMenu ( getDVDAuthor ( ) );
  CDVDMenuInterface *pNewInterface = pMenu->getInterface ( );
  CDVDMenuInterface *pMyInterface  = getInterface ( );
  *pNewInterface  = *pMyInterface;

  MenuPreview   *pNewPreview = pMenu->getMenuPreview ( );
  MenuPreview   *pMyPreview  = getMenuPreview ( );
 *pNewPreview = *pMyPreview;

  return pMenu;
}

void DVDMenu::fitObjectDimension (MenuObject *pObject)
{
  // This function is currently obsolete and not used.
  // It will center all images/movies to the real sizes and center the result.
  uint t, i;
  int iDeltaX, iDeltaY;
  ButtonObject tempButton;
  MovieObject  tempMovie;
  ImageObject  tempImage;
  FrameObject  tempFrame;
  ObjectCollection tempCollection;
  MenuObject  *pMenuObject;
  QString      qsObjectType;
  QImage       theImage;
  QRect        theRect;

  for (t=0;t<getMenuPreview()->objectCount();t++)	{
    pMenuObject = getMenuPreview()->menuObject(t);
    if ( ! pMenuObject )	// error checking
      continue;
    // If the object is specified, then we only want to handle that 
    // one object and nothing else.
    if ( (pObject) && (pMenuObject != pObject) )
      continue;
    if (pMenuObject->objectType() == tempButton.objectType())	{
      ButtonObject *pButton = (ButtonObject *)pMenuObject;
      for (i=0;i<pButton->getNormalCount();i++)	{
	qsObjectType = pButton->getNormal(i)->objectType();
	if ( 	(qsObjectType == tempMovie.objectType()) ||
		(qsObjectType == tempImage.objectType()) ||
		(qsObjectType == tempCollection.objectType()) )
	  fitObjectDimension (pButton->getNormal (i));
      }
      // And finally adjust the frames ...
      if ( pButton->getNormalCount() > 0 )	{
	for (i=0;i<pButton->getSelectedCount();i++)	{
	  if (pButton->getSelected(i)->objectType() == tempFrame.objectType())
	    pButton->getSelected(i)->setRect ( pButton->getNormal(0)->rect () );
	}
	for (i=0;i<pButton->getHighlightedCount();i++)	{
	  if (pButton->getHighlighted(i)->objectType() == tempFrame.objectType())
	    pButton->getHighlighted(i)->setRect ( pButton->getNormal(0)->rect () );
	}
      }
    }
    else if (pMenuObject->objectType() == tempCollection.objectType())	{
      ObjectCollection *pCollection = (ObjectCollection *)pMenuObject;
      for (i=0;i< (uint)pCollection->getCount();i++)	{
	qsObjectType = pCollection->getObject(i)->objectType ();
	if ( 	(qsObjectType == tempMovie.objectType ()) ||
		(qsObjectType == tempImage.objectType ()) ||
		(qsObjectType == tempButton.objectType()) ||
		(qsObjectType == tempCollection.objectType()) )
	  fitObjectDimension (pCollection->getObject (i));
      }
    }
    else if ( ( pMenuObject->objectType ( ) == tempMovie.objectType ( ) )  || 
	      ( pMenuObject->objectType ( ) == tempImage.objectType ( ) ) ) {
      // Disregard Text / Frame objects ... Here is the center place.
      ImageObject *pImageObject = (ImageObject *)pMenuObject;
      theRect    = pImageObject->rect  ( );
      theImage   = pImageObject->image ( );
      //printf ("DVDMenu::fitObjectDimension <%s> <%dx%d> =  <%dx%d>\n", (const char *) pImageObject->fileName (), theRect.width(), theRect.height(), thePixmap.width(), thePixmap.height());
      if (        theImage.width ( ) != pImageObject->rect ( ).width ( ) )	{
	iDeltaX = theImage.width ( )  - pImageObject->rect ( ).width ( );
	theRect.setX ( theRect.x ( ) + (int)( iDeltaX / 2.0 ) );
	theRect.setWidth   ( theImage.width ( ) );
      }
      if ( theImage.height ( ) != pImageObject->rect ( ).height ( ) )  {
	iDeltaY = theImage.height ( ) - pImageObject->rect ( ).height ( );
	theRect.setY  ( theRect.y ( ) + (int) ( iDeltaY / 2.0 ) );
	theRect.setHeight   ( theImage.height ( ) );
      }
      pImageObject->setRect ( theRect );
    }
  }
}

void DVDMenu::slotVisibleRegion (bool bEnable)
{
  m_pPixmapMenu->setVisibleRegion (bEnable);
}

void DVDMenu::slotUpdateStructure ( )
{
  if ( getDVDAuthor ( ) )
       getDVDAuthor ( )->slotUpdateStructure ( );
}

void DVDMenu::createIntroExtroMenu ( QPoint globalPos, bool bIntro, QString &qsFile )
{
  CXmlDVDAuthor::vob_struct *pVob = NULL;
  QString qsIntroExtro = QString ( "Extro" );  
  QPopupMenu *pMenu    = new QPopupMenu( getMenuPreview ( ) );
  QFileInfo fileInfo;
  uint t;
  if ( bIntro )
    qsIntroExtro = QString  ( "Intro" );

  pMenu->insertItem ( tr ( "Remove %1" ).arg ( qsIntroExtro ), 1 );
  if ( pMenu->exec  ( globalPos ) > -1 ) {
    UndoBuffer *pBuffer = getUndoBuffer ( );
    if ( pBuffer )
         pBuffer->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::EDIT_MENU, this ) );

    // Only one menu item, thus we can figure here if the user selected this one ...
    if ( bIntro ) {
      for ( t=0; t<getInterface ( )->listIntroVobs.count ( ); t++ ) {
	pVob = getInterface ( )->listIntroVobs[t];
	fileInfo.setFile ( pVob->file );
	if ( fileInfo.fileName ( ) == qsFile ) {
	  getInterface ( )->listIntroVobs.remove ( pVob );
	  delete pVob;
	}
      }
    }
    else {
      for ( t=0; t<getInterface ( )->listExtroVobs.count ( ); t++ ) {
	pVob = getInterface ( )->listExtroVobs[t];
	fileInfo.setFile ( pVob->file );
	if ( fileInfo.fileName ( ) == qsFile ) {
	  getInterface ( )->listExtroVobs.remove ( pVob );
	  delete pVob;
	}
      }
    }
  }
  delete pMenu;
  slotUpdateStructure ( );
}

void DVDMenu::createTransitionsXml ( )
{
  // Here we only create the xml files, and the start / end images.
  Utils             theUtils;
  DVDMenu          *pDVDMenu    = NULL;
  ButtonObject     *pButton     = NULL;
  ButtonTransition *pTransition = NULL;

  QImage  theImage;
  QString qsTempPath  = theUtils.getTempFile (  ""  );
  CDVDMenuInterface   * pInterface = getInterface ( );

  QValueList<ButtonObject *> list = getButtons ( );
  QValueList<ButtonObject *>::iterator it = list.begin ( );
  while ( it != list.end ( ) )  {
    pButton = *it++;
    pTransition = pButton->getTransition ( );
    if ( ( ! pTransition ) || ( pTransition->bUserFile ) )
      continue;

    QString qsName      = pInterface->qsMenuName + "/" + pButton->name ( );
    pTransition->qsName = qsName; // E.g. "Main VMGM/Button 1"
    theUtils.recMkdir   ( qsTempPath + qsName );
    qsName += "/transition.vob";
    pTransition->qsTransitionVideoFileName = qsTempPath + qsName; // E.g. "/tmp/TestProjec/Main VMGM/Button 1/transition.vob"

    // Next we create the start image.
    QString qsStartName = qsTempPath + pTransition->qsName + "/start.jpg";
    createMask ( qsStartName, BACKGROUND_IMG, true );
    QImage startImage ( qsStartName );
    // and then the end image.
    qsName = qsTempPath + pTransition->qsName + "/end.jpg";
    SourceFileInfo *pInfo = pButton->sourceFileInfo ( );
    if ( ! pInfo )  {
      pDVDMenu = pButton->dvdMenu ( );
      if ( pDVDMenu )  {
           pDVDMenu->createMask ( qsName, BACKGROUND_IMG, true );
           pTransition->iFormat = pDVDMenu->getInterface ( )->iFormat;
           QImage endImage ( qsName );
           if ( startImage.size ( ) != endImage.size ( ) )  {
             startImage = startImage.smoothScale  ( endImage.size ( ) );
             startImage.save  ( qsStartName, "JPEG", 100 );
           }
      }
    }
    else  {
      // Now let us request the acutal screenshot. Note, this could be to a chapter of a video.
      pTransition->iFormat  = pInfo->format ( );
      MediaInfo *pMediaInfo = Global::pApp->getMediaInfo ( );
      bool bFound = false;
      if ( pMediaInfo )  {
        long iMSecOffset = pButton->getOffset ( );
        pMediaInfo->setFileName ( pInfo->qsFileName, false );
        theImage = pMediaInfo->getScreenshot ( iMSecOffset );
        if ( ! theImage.isNull ( ) )  {
               theImage.save   ( qsName, "JPEG", 100 );
               if ( theImage.size ( ) != startImage.size ( ) )  {
                 startImage = startImage.smoothScale  ( theImage.size ( ) );
                 startImage.save  ( qsStartName, "JPEG", 100 );
               }
               bFound = true;
        }
        if ( ! bFound )  {
          // Just to ensure we have a image for the end :
          Cache::Thumbs::Entry *pCache = Global::pThumbsCache->find ( pInfo->qsFileName );
          if ( pCache )  {
            if ( ! pCache->arrayOfThumbs )
                   pCache->loadImages  ( );
            pCache->arrayOfThumbs[0]->save ( qsName, "JPEG", 100 );
          }
          else if ( pInfo->pPreview )
                    pInfo->pPreview->save  ( qsName, "JPEG", 100 );
        }
      }
    }

    // Finally we can create the Transitions xml file
    CXmlSlideshow *pSlideshow = pTransition->createSlideshow ( );
    QString qsFileName = pSlideshow->slideshow_name;
    qsFileName.replace ( "/", "_" );
    qsFileName = theUtils.getTempFile ( "" ) + pTransition->qsName + "/" + qsFileName + ".xml";
    pSlideshow->writeXml ( qsFileName );
  }
}

// Called from StructureToolbar::createContextMenu 
void DVDMenu::createSoundMenu ( QPoint globalPos, QString &qsFile )
{
  SourceFileEntry *pSourceFileEntry = NULL;
  QPopupMenu *pMenu    = new QPopupMenu( getMenuPreview ( ) );    
  QFileInfo fileInfo;
  QString qsFileName;
  uint t;

  pMenu->insertItem ( tr ( "Remove Audio" ), 1 );
  if ( pMenu->exec  ( globalPos ) > -1 ) {
    // Only one menu item, thus we can figure here if the user selected this one ...
    for ( t=0; t<getInterface ( )->listSoundEntries.count ( ); t++ ) {
      Audio *pAudio = getInterface()->listSoundEntries[t];
      if ( pAudio && ( pAudio->qsFileName == qsFile ) ) {
	getInterface ( )->listSoundEntries.remove ( pAudio );
	delete pAudio;
	if ( getDVDAuthor ( ) )
	  pSourceFileEntry = getDVDAuthor ( )->getSourceEntryByDisplayName ( qsFile );
	if ( pSourceFileEntry )
	  removeSourceFileEntry ( pSourceFileEntry );
      }
    }
  }
  delete pMenu;
  slotUpdateStructure ( );
}

StructureItem *DVDMenu::createStructure ( StructureItem *pMainItem )
{
  StructureItem *pMenuItem;
  StructureItem *pMaskItem;
  StructureItem *pButtonItem;
  StructureItem *pTemp, *pNext;
  QString qsEmpty;
  uint t, iCountButtons = 0;
  MenuObject *pObject;

  if ( ! pMainItem )  {
    for ( t=0; t<m_pPixmapMenu->objectCount ( ); t++ )  {
      pObject  = m_pPixmapMenu->menuObject ( t );
      pTemp    = pObject->createStructure ( NULL );
    }
    m_pStructureItem = NULL;
    return NULL;
  }


  if ( ! m_pStructureItem ) {
    m_pStructureItem = new StructureItem ( getMenuPreview ( ), StructureItem::SubMenu, pMainItem, pMainItem->lastChild ( ), m_DVDMenuInterface.qsMenuName );
    m_pStructureItem->setExpandable ( TRUE );
    m_pStructureItem->setOpen       ( TRUE );
  }
  else 
    m_pStructureItem->setText ( m_DVDMenuInterface.qsMenuName, qsEmpty );

  QString qsButtonMasks = tr ( "Button Masks" );
  QString qsButtons     = tr ( "Specified Buttons" );
  QString qsBackground  = tr ( "Background" );
  QString qsSoundFiles  = tr ( "Sound File(s)" );
  QString qsIntroFile   = tr ( "Intro File" );
  QString qsExtroFile   = tr ( "Extro File" );

  // Delete all but the MenuObjects ( Buttons and all )
  pTemp = (StructureItem *)m_pStructureItem->firstChild ( );
  while ( pTemp )  {
    pNext = (StructureItem *)pTemp->nextSibling ( );
    if  ( pTemp->text ( 0 ) == qsButtonMasks )
      delete  pTemp;
    else if ( pTemp->text ( 0 ) == qsBackground )
      delete  pTemp;
    else if ( pTemp->text ( 0 ).find ( qsSoundFiles ) > -1 )
      delete  pTemp;
    else if ( pTemp->text ( 0 ).find ( qsIntroFile ) > -1 )
      delete  pTemp;
    else if ( pTemp->text ( 0 ).find ( qsExtroFile ) > -1 )
      delete  pTemp;
    pTemp   = pNext;
  }

  // Here is the rest of the Main Menu ...
  QString qsFileName, qsName;
  if ( ( ! m_DVDMenuInterface.qsHighlightedMaskFileName.isEmpty ( ) ) || 
       ( ! m_DVDMenuInterface.qsSelectedMaskFileName.isEmpty    ( ) ) )  {
    qsFileName  = QFileInfo ( m_DVDMenuInterface.qsHighlightedMaskFileName ).fileName ( );
    pMaskItem   = (StructureItem *)pTemp->nextSibling ( );
    if ( ! pMaskItem ) {
      pMaskItem = new StructureItem ( m_pStructureItem, StructureItem::Unknown, qsButtonMasks, qsFileName );
      pMaskItem->setExpandable ( TRUE );
    }
    else if ( pMaskItem->text ( 1 ) != qsFileName )
      pMaskItem->setText ( 1, qsFileName );

    qsFileName = QFileInfo ( m_DVDMenuInterface.qsHighlightedMaskFileName ).fileName ( );
    pMenuItem = new StructureItem(pMaskItem, StructureItem::Highlighted, tr (" Highlighted"), qsFileName);
    pMenuItem->setExpandable (TRUE);

    qsName = tr ("to images");
    pButtonItem = new StructureItem ( pMenuItem, StructureItem::Button, tr ("Button 1"), qsName);
    pButtonItem->setExpandable (TRUE);
    new StructureItem ( pButtonItem, StructureItem::Geometry, tr ("Geometry"), QString ("22, 23, 50, 100"));

    // Here is the info for the Selected Mask
    qsFileName = QFileInfo (m_DVDMenuInterface.qsSelectedMaskFileName).fileName ();
    pMenuItem = new StructureItem ( pMaskItem, StructureItem::Selected, tr (" Selected"), qsFileName);
    pMenuItem->setExpandable (TRUE);
    qsName = tr ("to images");
    pButtonItem = new StructureItem ( pMenuItem, StructureItem::Button, tr ("Button 1"), qsName);
    pButtonItem->setExpandable (TRUE);
    new StructureItem ( pButtonItem, StructureItem::Geometry, tr ("Geometry"), QString ("22, 23, 50, 100"));
  }

  pTemp = NULL;  //(StructureItem *)m_pStructureItem->firstChild  ( );

  for ( t=0; t<m_DVDMenuInterface.listIntroVobs.count ( ); t++ )   {
    qsFileName = QFileInfo ( m_DVDMenuInterface.listIntroVobs[t]->file ).fileName ( );
    pTemp = new StructureItem ( this, StructureItem::Intro, m_pStructureItem, pTemp, QString ("%1[%2]").arg ( qsIntroFile ).arg(t), qsFileName );
  }
  for ( t=0; t<m_DVDMenuInterface.listExtroVobs.count ( ); t++ )  {
    qsFileName = QFileInfo ( m_DVDMenuInterface.listExtroVobs[t]->file ).fileName ( );
    pTemp = new StructureItem ( this, StructureItem::Extro, m_pStructureItem, pTemp, QString ("%1[%2]").arg ( qsExtroFile ).arg(t), qsFileName );
  }
  if ( ! m_DVDMenuInterface.qsMovieFileName.isEmpty ( ) )  {
    qsFileName = QFileInfo ( m_DVDMenuInterface.qsMovieFileName ).fileName ( );
    pTemp = new StructureItem ( m_pPixmapMenu, StructureItem::Background, m_pStructureItem, pTemp, qsBackground, qsFileName );
  }
  else if ( ! m_DVDMenuInterface.qsBackgroundFileName.isEmpty ( ) )  {
    qsFileName = QFileInfo ( m_DVDMenuInterface.qsBackgroundFileName ).fileName ( );
    pTemp = new StructureItem ( m_pPixmapMenu, StructureItem::Background, m_pStructureItem, pTemp, qsBackground, qsFileName );
  }
  for ( t=0; t<m_DVDMenuInterface.listSoundEntries.count ( ); t++ )
    pTemp = new StructureItem ( this, StructureItem::Audio, m_pStructureItem, pTemp, QString ( "%1 %2").arg ( qsSoundFiles ).arg(t), m_DVDMenuInterface.listSoundEntries[t]->qsFileName );

  // The second time we go through the list of menuObjects we take everything in the order we receive it ...
  for ( t=0; t<m_pPixmapMenu->objectCount ( ); t++ )  {
    pObject  = m_pPixmapMenu->menuObject ( t );
    if ( pObject->objectType ( ) !=  BUTTON_OBJECT )  {
      pTemp  = pObject->createStructure ( m_pStructureItem );
    }
  }

  // And at the end, we list all Buttons.
  pMenuItem  = (StructureItem *)m_pStructureItem->firstChild ( );
  while ( pMenuItem ) {
    if  ( pMenuItem->text ( 0 ) == qsButtons )
      break;
    pMenuItem = (StructureItem *)pMenuItem->nextSibling ( );
  }
  if ( ! pMenuItem ) {
    // If we get herem, then we did not have ButtonObjects previously,
    // and we have to create a root node for the buttons to come.
    pMenuItem = new StructureItem( this, StructureItem::Buttons, m_pStructureItem, m_pStructureItem->lastChild ( ), qsButtons );
    pMenuItem->setExpandable ( TRUE );
    pMenuItem->setOpen       ( TRUE );
  }
  pTemp = NULL;

  // And we want to have the buttons at the end ...
  for ( t=0; t<m_pPixmapMenu->objectCount ( ); t++ )  {
    pObject =  m_pPixmapMenu->menuObject ( t );
    if ( pObject->objectType ( ) ==  BUTTON_OBJECT )  {
      pTemp = pObject->createStructure ( pMenuItem );
      iCountButtons ++;
    }
  }

  // If there were no buttons, then we don't need to show this in the structure ...
  if ( ! iCountButtons )
    delete pMenuItem;

  return m_pStructureItem;
}

