/****************************************************************************
** menu.cpp file.
**
*****************************************************************************/
#include <stdlib.h>	// for system ()

#include <qdesktopwidget.h>
#include <qapplication.h>
#include <qfiledialog.h>
#include <qlineedit.h>
#include <qfileinfo.h>
#include <qcombobox.h>
#include <qpainter.h>
#include <qmenubar.h>
#include <qpixmap.h>
#include <qbitmap.h>
#include <qcursor.h>
#include <qimage.h>
#include <qcolor.h>
#include <qdom.h>

#include <qtimer.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 "dialogresize.h"
#include "qimagehelper.h"
#include "buttonobject.h"
#include "sourcefileentry.h"
#include "dialogundostack.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"
#include "qplayer/sourcefiledialog.h"

#define TEMP_BUTTON_COLOR0 0x00FEFFFE
#define TEMP_BUTTON_COLOR1 0x00FFFFFF
#define TEMP_BUTTON_COLOR2 0x00FFFFFE
#define TEMP_BUTTON_COLOR3 0x00FFFEFF

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

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

CDVDMenuInterface::~CDVDMenuInterface ()
{

}

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]              = QColor (TRANSPARENT_COLOR);
	pgcColors[1]              = QColor (START_HIGHLIGHTED_COLOR);
	pgcColors[2]              = QColor (START_SELECTED_COLOR);
	pgcColors[3]              = QColor (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)
{
	QDomElement theElement;// = theNode.toElement();
	QString tagName;// = theElement.tagName();
	QString nodeText;// = theElement.text ();

	QDomAttr a = theElement.attributeNode ( MENU_TITLESET_NR );
	if ( ! a.value().isEmpty() )
	  iTitleset = a.value().toInt();
	a = theElement.attributeNode ( MENU_MENU_NR );
	if ( ! a.value().isEmpty() )
	  iMenu = a.value().toInt();

	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);
		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++)	{
				QColor theColor (listColors[t]);
				pgcColors[t] = theColor;
			}
		}
		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;

	tag = xmlDoc.createElement( MENU_BACKGROUND );
	rootDVDMenu.appendChild( tag );

	t = xmlDoc.createTextNode(qsBackgroundFileName);
	tag.setAttribute ( MENU_TITLESET_NR, QString ("%1").arg(iTitleset));
	tag.setAttribute ( MENU_MENU_NR, QString ("%1").arg(iMenu));
	
	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)	{
		for (i=0;i<listSoundEntries.count();i++)	{
			tag = xmlDoc.createElement( MENU_SOUND );
			rootDVDMenu.appendChild( tag );
			t = xmlDoc.createTextNode(listSoundEntries[i]);
			tag.appendChild( t );
		}
	}
	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 t=0;t<MAX_MASK_COLORS;t++)
		qsColors += pgcColors[t].name() + ",";
	
	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;
  listSoundEntries         = theOther.listSoundEntries;
  
  // 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;
  
  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[t] = 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[t] = 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;
}

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

VMGMenu::VMGMenu ()
{
}

VMGMenu::VMGMenu (QDVDAuthor *pDVDAuthor)
	: DVDMenu (pDVDAuthor)
{
  // 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_pActionCreateSVCD;
	delete m_pActionCreateVCD;
	delete m_pActionRenameMenu;
	delete m_pActionDeleteMenu;
	delete m_pActionCloneMenu;
	delete m_pActionConvertToPAL;
	delete m_pActionConvertToNTSC;
	delete m_pActionStoreMenu;
	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_pActionAddHighlightedMask;
	delete m_pActionAddSelectedMask;
}

void VMGMenu::CreateToolBar (QDVDAuthor *pDVDAuthor)
{
	QIconSet iconToDVD  = QIconSet (QPixmap().fromMimeSource( "to_dvd.png" ));
	QIconSet iconToVCD  = QIconSet (QPixmap().fromMimeSource( "to_vcd.png" ));
	QIconSet iconToSVCD = QIconSet (QPixmap().fromMimeSource( "to_svcd.png" ));
//	iconSet.setIconSize (QIconSet::Large, QSize (70, 70));
	iconToDVD.setIconSize (QIconSet::Small, QSize (70, 70));
	iconToVCD.setIconSize (QIconSet::Small, QSize (70, 70));
	iconToSVCD.setIconSize(QIconSet::Small, QSize (70, 70));
	// Create some action ...
	m_pActionCreateDVD  = new QAction( pDVDAuthor, "createDVD" );
	m_pActionCreateSVCD = new QAction( pDVDAuthor, "createSVCD" );
	m_pActionCreateVCD  = new QAction( pDVDAuthor, "createVCD" );
	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_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_pActionAddHighlightedMask = new QAction( pDVDAuthor, "addHMask" );
	m_pActionAddSelectedMask    = new QAction( pDVDAuthor, "addSMask" );	
	
	m_pActionCreateDVD->setIconSet( iconToDVD );
	m_pActionCreateDVD->setMenuText( tr( "&Create DVD" ) );
	m_pActionCreateDVD->setAccel( QString::null );
	m_pActionCreateSVCD->setIconSet( iconToSVCD );
	m_pActionCreateSVCD->setMenuText( tr( "&Create SVCD" ) );
	m_pActionCreateSVCD->setAccel( QString::null );
	m_pActionCreateVCD->setIconSet( iconToVCD );
	m_pActionCreateVCD->setMenuText( tr( "&Create VCD" ) );
	m_pActionCreateVCD->setAccel( QString::null );

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

	m_pActionAddFrame->setMenuText( tr( "Add &Frame" ) );
	m_pActionAddFrame->setAccel( QString::null );
	m_pActionAddText ->setMenuText( tr( "Add &Text" ) );
	m_pActionAddText ->setAccel( QString::null );
	m_pActionAddImage->setMenuText( tr( "Add &Image" ) );
	m_pActionAddImage->setAccel( QString::null );
	m_pActionAddMovie->setMenuText( tr( "Add &Movie" ) );
	m_pActionAddMovie->setAccel( QString::null );
	m_pActionAddBackground->setMenuText( tr( "Add &Background" ) );
	m_pActionAddBackground->setAccel( QString::null );
	m_pActionAddSound->setMenuText( tr( "Add &Sound" ) );
	m_pActionAddSound->setAccel( QString::null );
	m_pActionAddIntro->setMenuText( tr( "Add &Intro" ) );
	m_pActionAddIntro->setAccel( QString::null );
	m_pActionAddExtro->setMenuText( tr( "Add &Extro" ) );
	m_pActionAddExtro->setAccel( QString::null );
	m_pActionAddHighlightedMask->setMenuText( tr( "Add &Highlighted Mask" ) );
	m_pActionAddHighlightedMask->setAccel( QString::null );
	m_pActionAddSelectedMask->setMenuText( tr( "Add &Selected Mask" ) );
	m_pActionAddSelectedMask->setAccel( QString::null );

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

	m_pActionCreateDVD ->addTo( m_pToolBar );
////	m_pActionCreateSVCD->addTo( m_pToolBar );
////	m_pActionCreateVCD ->addTo( m_pToolBar );
//	m_pActionRenameMenu->addTo( m_pToolBar );
//	m_pActionDeleteMenu->addTo( m_pToolBar );
//	m_pToolBar->addSeparator();
//	m_pActionAddFrame->addTo( m_pToolBar );
//	m_pActionAddText ->addTo( m_pToolBar );
//	m_pActionAddImage->addTo( m_pToolBar );
//	m_pActionAddMovie->addTo( m_pToolBar );
//	m_pToolBar->addSeparator();
//	m_pActionAddBackground->addTo( m_pToolBar );
//	m_pActionAddSound->addTo( m_pToolBar );
//	m_pActionAddHighlightedMask->addTo( m_pToolBar );
//	m_pActionAddSelectedMask->addTo( m_pToolBar );
}

void VMGMenu::CreateMenuEntry (QDVDAuthor *pDVDAuthor)
{
	// 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_pDVDMenuMenu->insertSeparator    ( );
	m_pActionAddFrame->addTo           ( m_pDVDMenuMenu );
	m_pActionAddText ->addTo           ( m_pDVDMenuMenu );
	m_pActionAddImage->addTo           ( m_pDVDMenuMenu );
	m_pActionAddMovie->addTo           ( m_pDVDMenuMenu );
	m_pDVDMenuMenu->insertSeparator    ( );
	m_pActionAddBackground->addTo      ( m_pDVDMenuMenu );
	m_pActionAddSound->addTo           ( m_pDVDMenuMenu );
	m_pActionAddIntro->addTo           ( m_pDVDMenuMenu );
	m_pActionAddExtro->addTo           ( m_pDVDMenuMenu );
	m_pActionAddHighlightedMask->addTo ( m_pDVDMenuMenu );
	m_pActionAddSelectedMask->addTo    ( m_pDVDMenuMenu );

	pDVDAuthor->m_pMenuBar->insertItem(tr( "&DVDMenu"), m_pDVDMenuMenu, 0, 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_pActionCreateSVCD,	     SIGNAL( activated() ), pDVDAuthor, SLOT( slotCreateSVCD( ) ) );
	connect( m_pActionCreateVCD,	     SIGNAL( activated() ), pDVDAuthor, SLOT( slotCreateVCD ( ) ) );
	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_pActionConvertToPAL,	     SIGNAL( activated() ), getMenuPreview  ( ), SLOT( slotConvertToPAL  ( ) ) );
	connect( m_pActionConvertToNTSC,     SIGNAL( activated() ), getMenuPreview  ( ), SLOT( slotConvertToNTSC ( ) ) );
	connect( m_pActionStoreMenu,	     SIGNAL( activated() ), this, SLOT( slotStoreMenuAsTemplate          ( ) ) );
	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        ( ) ) );
	connect( m_pActionAddHighlightedMask,SIGNAL( activated() ), this, SLOT( slotAddHighlightedMask()) );
	connect( m_pActionAddSelectedMask,   SIGNAL( activated() ), this, SLOT( slotAddSelectedMask ( ) ) );
}

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

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

DVDMenu::DVDMenu ()
{
}

DVDMenu::DVDMenu (QDVDAuthor *pDVDAuthor)
	: QObject ()
{
	m_pDVDAuthor           = pDVDAuthor;
	m_pPixmapMenu          = NULL;
	m_pUndoStackDialog     = NULL;
	m_pDialogRenderPreview = NULL;
	m_iTotalFramesToRender = 0;
	m_iCurrentFrameToRender= 0;
	m_pTabLayout           = NULL;
	m_pLayout1             = NULL;
	m_pLayout2             = NULL;
	m_pLayout3             = NULL;

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

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

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);	
}

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;
}

bool DVDMenu::readProjectFile  (QDomNode &theNode)
{
	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();
	
	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))
				return false;
// Might be wrong. I get the info for the SourceToolbar already through the SourceEntry.
//			if (m_pDVDAuthor)
//				m_pDVDAuthor->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);
	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 );

	// 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 = m_pDVDAuthor->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 = m_pDVDAuthor->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 = m_pDVDAuthor->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 = m_pDVDAuthor->getCurrentSubMenu();
		if (pMenu)
			pMenu->slotAddMovieObject(true);
	}
}

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

void DVDMenu::setTabLabel(QString &qsNewLabel)
{
	bool bIsSubMenu = true;
	m_pDVDAuthor->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, QColor 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());
			else
				theColor.setRgb(theColor.red()+1, theColor.green(), theColor.blue());
		}
	}

	QColor 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
	m_pDVDAuthor->setColor(iWhichColor, theColor);
}

// Standard initialization Functions.
void DVDMenu::CreateTab (QTabWidget *pTabWidgetMain)
{
	QPixmap backgroundPixmap = QPixmap().fromMimeSource ("checkered.png");

	m_pDVDMenuTab = new QWidget( pTabWidgetMain, "m_pDVDMenuTab" );
	m_pTabLayout  = new QGridLayout( m_pDVDMenuTab, 1, 1, 11, 6, "m_pTabLayout");

	m_pLayout1 = new QGridLayout( 0, 1, 1, 0, 6, "m_pLayout1");
	m_pLayout2 = new QHBoxLayout( 0, 0, 6, "m_pLayout2");

	// 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 dimensins, and the environment (yes will force to use the scrollview, no willinhibit 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 );// Dont 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->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_pButtonAddBackground = new QPushButton ( m_pDVDMenuTab, "m_pButtonAddBackground" );
	m_pLayout2->addWidget( m_pButtonAddBackground );

	m_pButtonAddSound = new QPushButton ( m_pDVDMenuTab, "m_pButtonAddSound" );
	m_pLayout2->addWidget( m_pButtonAddSound );

	m_pButtonShowHighlightedMask = new QPushButton( m_pDVDMenuTab, "m_pButtonAddHighlightedMask" );
	m_pLayout2->addWidget( m_pButtonShowHighlightedMask );

	m_pButtonShowSelectedMask = new QPushButton( m_pDVDMenuTab, "m_pButtonAddSelectedMask" );
	m_pLayout2->addWidget( m_pButtonShowSelectedMask );

	m_pLayout1->addLayout( m_pLayout2, 1, 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), pTabWidgetMain->count() - 2);

	m_pButtonAddBackground->setText( tr( "Add Background" ) );
	m_pButtonAddSound->setText( tr( "Add Sound" ) );
	m_pButtonShowHighlightedMask->setText( tr( "Show H-Layer" ) );
	m_pButtonShowSelectedMask->setText( tr( "Show S-Layer" ) );
	pTabWidgetMain->setCurrentPage (pTabWidgetMain->count()-3);

	connect( m_pButtonAddBackground, SIGNAL( clicked() ),        this, SLOT( slotAddBackground       ( ) ) );
	connect( m_pButtonAddSound, SIGNAL( clicked() ),             this, SLOT( slotAddSound            ( ) ) );
	connect( m_pButtonShowHighlightedMask, SIGNAL( clicked() ),  this, SLOT( slotShowHighlightedMask ( ) ) );
	connect( m_pButtonShowSelectedMask, SIGNAL( clicked() ),     this, SLOT( slotShowSelectedMask    ( ) ) );
	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  ( ) ),     m_pDVDAuthor, SLOT( slotRemoveCurrentSubMenu ( ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalRenameMe  ( ) ),     m_pDVDAuthor, SLOT( slotRenameCurrentSubMenu ( ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalCloneMe   ( ) ),     m_pDVDAuthor, SLOT( slotCloneCurrentSubMenu  ( ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalConvertMe ( bool )), m_pDVDAuthor, SLOT( slotConvertCurrentMenu   ( bool ) ) );
	connect( m_pPixmapMenu, SIGNAL(signalMaskColorChanged  (QColor, QColor)),     this, SLOT(slotMaskColorChanged(QColor, QColor)       ) );
	connect( m_pPixmapMenu, SIGNAL(signalCreatedMovieObject(MovieObject *, bool)),this, SLOT(slotCreatedMovieObject(MovieObject *, bool)) );
}

// Public slots. Here are the main actors from the GUI.
void DVDMenu::slotStoreMenuAsTemplate ( )
{
  // This function will open the CreateTemplate - dialog.
  DVDMenu *pMenu = m_pDVDAuthor->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 = m_pDVDAuthor->getDragNDropContainer();
	// Sanity check are you all there ?
	if (!pObject || !pDNDContainer)
		return;

	switch (iWhatDidIDrop)	{
	case MenuPreview::DroppedImage :
	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 thre SetupDialog.
		pTextObject->setFont(pDNDContainer->font);
		pTextObject->setTextAlign (textAlign);
		pTextObject->setForegroundColor (pDNDContainer->colorForeground);
		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 (m_pDVDAuthor->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(QColor theColor, QColor 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 ()
{
  QString fileName = getInterface()->qsBackgroundFileName;

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

  addBackground ( fileName, NULL, true );
}

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

	if (qsExtensions.find ("."+backgroundInfo.extension ( FALSE  ) ) > -1)	{
		m_DVDMenuInterface.qsMovieFileName = fileName;
		// Okay let us get the first frame of the game as a screenshot ...
		pMediaInfo->setFileName(fileName);
		QImage theImage = pMediaInfo->getScreenshot(0);
		getInterface ()->timeOffset = zeroTime;
		getInterface ()->timeDuration = zeroTime.addMSecs (pMediaInfo->getLength());
		// 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();
}

// This function is called from the [Add Background] - button.
void DVDMenu::slotAddBackground()
{
  Utils theUtil;
  QString qsExtensions;
  if (!m_pDVDAuthor->checkForNewProject ())
    return;
  
  QString qsImageFilter      = m_pDVDAuthor->getImageFilter ( );
  QString qsMovieFilter      = m_pDVDAuthor->getMovieFilter ( );
  MediaInfo *pMediaInfo      = getDVDAuthor()->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)
{
	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)	{
				// save some memory while doing all the resize work etc.
				theBackground = QPixmap (1,1);
				CResizeDialog resizeDialog;
				resizeDialog.m_posOffset = posOffset;
				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);
			}
	}
	else {
	  m_DVDMenuInterface.backgroundImage = QPixmap ( theBackground );
	  m_pPixmapMenu->setPixmap ( (const QPixmap &) theBackground );
	}
	m_pPixmapMenu->undoBuffer()->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::showUndoStack ()
{
	if (!m_pUndoStackDialog)	{
		 m_pUndoStackDialog = new DialogUndoStack(getUndoBuffer(), this, NULL);
	}
	m_pUndoStackDialog->buildUndoTree();
	m_pUndoStackDialog->show();
	m_pUndoStackDialog->raise();
}

void DVDMenu::slotAddSound()
{
  QDVDAuthor *pDVDAuthor = getDVDAuthor ( );
  if ( ! pDVDAuthor )
    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]);
    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;
  }
  QString qsFilter = pDVDAuthor->getSoundFilter ();

  //	QStringList listFileNames = QFileDialog::getOpenFileNames ( tr ("Sound Files (")+qsFilter+QString(")"), Global::qsCurrentPath);
  QString qsDialogFilter = tr ("Sound Files (") + qsFilter + QString(")");
  MediaInfo *pMediaInfo      = pDVDAuthor->getMediaInfo ( );
  void *pExistingMediaEngine = NULL;
  if ( pMediaInfo )
    pExistingMediaEngine  = pMediaInfo->getMediaEngine   ( );

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

  if (listFileNames.count() < 1)
    return;
  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]);
  }

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

//	for (t=0;t<listFileNames.count();t++)
//		m_DVDMenuInterface.listSoundFiles.append (listFileNames[t]);
//	slotUpdateStructure ();

  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;
  m_DVDMenuInterface.listSoundEntries.append ( pNewEntry->qsDisplayName );
  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;

  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;

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

void DVDMenu::removeSourceEntry (QString &qsRemoveName)
{
	uint t, iRemoved;
	QStringList listButtonAction;
	QString qsTemp;
	QValueList<ButtonObject *> listButtons = getButtons();
	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++)	{
		qsTemp = m_DVDMenuInterface.listSoundEntries[t];
		if (qsTemp == qsRemoveName)
			iRemoved += m_DVDMenuInterface.listSoundEntries.remove (qsTemp);
	}

	// The second step is to check all button objects...
	qsTemp = QString ();
	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() == 3) || (listButtonAction.count() == 4) )	{
			// Here we got ourself a button connected to something ...
			if (listButtonAction[1] == qsRemoveName)	{
				listButtons[t]->setAction(qsTemp);
				listButtons[t]->setSourceFileEntry(NULL);
				iRemoved ++;
			}
		}
	}

	if (iRemoved > 0)
		slotUpdateStructure ();
}

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

void DVDMenu::appendSourceFileEntry (SourceFileEntry *pSourceFileEntry)
{
	m_pDVDAuthor->appendSourceFileEntry (pSourceFileEntry);
	m_DVDMenuInterface.listSoundEntries.append (pSourceFileEntry->qsDisplayName);
	slotUpdateStructure ();
}

bool DVDMenu::isSourceEntryUsed (QString &qsInquireEntry)
{
	uint t;
	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] == qsInquireEntry)
			return true;
	}

	// The second step is to check all button objects...
	QValueList<ButtonObject *> listButtons = getButtons();
	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() == 3) || (listButtonAction.count() == 4) )	{
			// Here we got ourself a button connected to something ...
			if (listButtonAction[1] == qsInquireEntry)
				return true;
		}
	}
	return false;
}

void DVDMenu::replaceSourceDisplayName (QString &qsOriginalDisplayName, QString &qsNewDisplayName)
{
	uint t;
	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] == qsOriginalDisplayName)
			pInterface->listSoundEntries[t] = qsNewDisplayName;
	}

	// The second step is to go through all buttons and see what they are up to ...
	QValueList<ButtonObject *> listButtons = getButtons();
	QStringList listButtonAction;
	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() == 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);
			}
		}
	}
}

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::slotShowHighlightedMask()
{
  MessageBox::warning (NULL, tr ("Feature missing"),
    tr ("This feature is not yet implemented.\n"), QMessageBox::Ok,  QMessageBox::NoButton);
}

void DVDMenu::slotShowSelectedMask()
{
  MessageBox::warning (NULL, tr ("Feature missing"),
    tr ("This feature is not yet implemented.\n"), QMessageBox::Ok,  QMessageBox::NoButton);
}

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

  QString qsImageFilter      = m_pDVDAuthor->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 (!m_pDVDAuthor->checkForNewProject ())
    return;
  
  QString qsImageFilter      = m_pDVDAuthor->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();
  }
  
  switch (iWhichMask)	{
  case BACKGROUND_IMG:
    // The background image is generated by using the background and overlaying all MenuObject
    if ( m_DVDMenuInterface.backgroundImage.isNull() ) {
      theMask = QPixmap ( iWidth, iHeight );
      theMask.fill ( m_DVDMenuInterface.pgcColors[0] );
    }
    else
      theMask = QPixmap (m_DVDMenuInterface.backgroundImage);
    break;
  case HIGHLIGHTED_MASK:
    theMask = QPixmap  ( iWidth, iHeight );
    theMask.fill ( m_DVDMenuInterface.pgcColors[0] );
    break;
  case SELECTED_MASK:
    theMask = QPixmap ( iWidth, iHeight );
    theMask.fill ( m_DVDMenuInterface.pgcColors[0] );
    break;
  }
  // Here we draw the appropriate mask.
  thePainter.begin(&theMask);
  // Check if we draw the Background image
  if (iWhichMask == BACKGROUND_IMG)	{
    // 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] = TEMP_BUTTON_COLOR0;
  colors[1] = TEMP_BUTTON_COLOR1;
  colors[2] = TEMP_BUTTON_COLOR2;
  colors[3] = TEMP_BUTTON_COLOR3;
  // Here we draw the Selected or the highlighted mask
  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();
  
  QImage theImage = theMask.convertToImage();
  Utils theUtils;

  theUtils.reduceColors ( theImage, 4, (QRgb *)&colors );
  // 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() & 0x00FFFFFF));
    }
  }
  
  // Okay all's in, so we should be good to write to the temp drive ...
  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.97;		// NTSC
	if (iFormat > 4)
		fFPS = 25.0;	// 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 (m_pDVDAuthor);
	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 == 0)
		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 ()
{
	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.png", (const char *)qsFullPath, m_iCurrentFrameToRender);
		
	// 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);
	thePixmap.save (qsFileName, "PNG", 100); //"PNG");
	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;
		m_pDVDAuthor->returnFromRenderMenu ();
	}
}

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

QColor DVDMenu::getColor (int iNumber)
{
	return m_DVDMenuInterface.pgcColors[iNumber];
}

void DVDMenu::slotEditTimeline ()
{
	// This function will allow the modification of the length of the MenuMovie
	DialogMovie movieDialog (NULL);
	movieDialog.initMe(this);
	movieDialog.exec();
}

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;	
	}

	return false;
}

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

	for (t=0;t<getMenuPreview()->objectCount();t++)	{
		pMenuObject = getMenuPreview()->menuObject(t);
		if (pMenuObject->objectType() == tempButton.objectType())	{
			ButtonObject *pButton = (ButtonObject *)pMenuObject;
			for (i=0;i< pButton->getNormalCount();i++)	{
				if (pButton->getNormal(i)->objectType() == tempMovie.objectType())
					listReturn.append((MovieObject *)pButton->getNormal(i));
			}
		}
		else if (pMenuObject->objectType() == tempCollection.objectType())	{
			ObjectCollection *pCollection = (ObjectCollection *)pMenuObject;
			for (i=0;i< (uint)pCollection->getCount();i++)	{
				if (pCollection->getObject(i)->objectType () == tempMovie.objectType())	
					listReturn.append((MovieObject *)pCollection->getObject(i));
			}
		}
		else if (pMenuObject->objectType() == tempMovie.objectType())
			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;
}

QValueList<SourceFileEntry *> &DVDMenu::getSourceFileEntries()
{
	// 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 multipler references to it.
	static QValueList<SourceFileEntry *> listReturn;
	ButtonObject tempButton;
	ButtonObject *pButton;
	SourceFileEntry *pEntry;
	uint t;

	listReturn.clear();
	for (t=0;t<m_pPixmapMenu->objectCount();t++)    {
		if (m_pPixmapMenu->menuObject(t)->objectType() == tempButton.objectType())    {
			bool bFound=false;

			pButton = (ButtonObject *)m_pPixmapMenu->menuObject(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);
		}
	}
	return listReturn;
}

QValueList<SourceFileInfo *> &DVDMenu::getSourceFileInfos()
{
  // This function will return all SourceFileEntries actually used in this Menu.
  static QValueList<SourceFileInfo *> listReturn;
  listReturn.clear();
  SourceFileInfo *pInfo = NULL;
  ButtonObject tempButton;
  ButtonObject *pButton;
  uint t;
  for (t=0;t<m_pPixmapMenu->objectCount();t++)	{
    if (m_pPixmapMenu->menuObject(t)->objectType() == tempButton.objectType())	{
      pButton = (ButtonObject *)m_pPixmapMenu->menuObject(t);
      pInfo = pButton->sourceFileInfo();
      if ( pInfo )
	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(QListViewItem *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 m_pDVDAuthor;
}

// This slot is called when the DialogButton is created (in MenuPreview, or ButtonObject)
void DVDMenu::slotRequestSourceFiles()
{
	int t;
	int iSourceFileCount = m_pDVDAuthor->sourceFileCount();
	// Let us get the actual list of Source files ...
	QValueList<SourceFileEntry *> listSourceFileEntries;
	for (t=0;t<iSourceFileCount;t++)
		listSourceFileEntries.append(m_pDVDAuthor->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 = m_pDVDAuthor->getSubMenus();
	
	for (t=0;t<listDVDMenus.count();t++)	{
		listSubMenus.append (listDVDMenus[t]->name());
	}
	m_pPixmapMenu->respondSubMenus(listSubMenus);
}

void DVDMenu::updateDVDMenu ()
{
	// 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 = m_pDVDAuthor->getMediaInfo ();
				pMediaInfo->setFileName(qsFileName);
				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;
			}
		}
		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;
	QPixmap thePixmap;
	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 ();
			thePixmap = pImageObject->pixmap ();
//printf ("DVDMenu::fitObjectDimension <%s> <%dx%d> =  <%dx%d>\n", (const char *) pImageObject->fileName (), theRect.width(), theRect.height(), thePixmap.width(), thePixmap.height());
			if (thePixmap.width () != pImageObject->rect ().width())	{
				iDeltaX = thePixmap.width () - pImageObject->rect ().width();
				theRect.setX (theRect.x() + (int)(iDeltaX/2.0));
				theRect.setWidth (thePixmap.width ());
			}
			if (thePixmap.height() != pImageObject->rect ().height())	{
				iDeltaY = thePixmap.height () - pImageObject->rect ().height();
				theRect.setY (theRect.y() + (int)(iDeltaY/2.0));
				theRect.setHeight (thePixmap.height ());
			}
			pImageObject->setRect ( theRect );
		}
	}

}

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

void DVDMenu::slotUpdateStructure ()
{
	if (m_pDVDAuthor)
		m_pDVDAuthor->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 ) {
    // 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 ( );
}

// 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++ ) {
      qsFileName = getInterface()->listSoundEntries[t];
      fileInfo.setFile ( qsFileName );
      if ( fileInfo.fileName ( ) == qsFile ) {
	getInterface ( )->listSoundEntries.remove ( qsFileName );
	if ( m_pDVDAuthor )
	  pSourceFileEntry = m_pDVDAuthor->getSourceEntryByDisplayName ( qsFile );
	if ( pSourceFileEntry )
	  removeSourceFileEntry ( pSourceFileEntry );
	  
      }
    }
  }
  delete pMenu;
  slotUpdateStructure ( );
}

QListViewItem *DVDMenu::createStructure (QListViewItem *pMainItem)
{
	QListViewItem *pMainMenuItem;
	QListViewItem *pMenuItem;
	QListViewItem *pMaskItem;
	QListViewItem *pButtonItem;

	pMainMenuItem = new StructureItem(getMenuPreview(), pMainItem, m_DVDMenuInterface.qsMenuName);
	pMainMenuItem->setExpandable (TRUE);
	pMainMenuItem->setOpen (TRUE);

	// Last things first ...
	pMenuItem = new QListViewItem(pMainMenuItem, tr ("Specified Buttons"));
	pMenuItem->setExpandable (TRUE);
	pMenuItem->setOpen (TRUE);

	uint t, iCountButtons = 0;
	ButtonObject tempButton;
	MenuObject *pObject;
	// Duh, the last Button's first ... how strangely dumb ...
	for (t=m_pPixmapMenu->objectCount();t>0;t--)	{
		pObject = m_pPixmapMenu->menuObject(t-1);
		if (pObject->objectType() == tempButton.objectType())	{
			pObject->createStructure (pMenuItem);
			iCountButtons ++;
		}
	}
	// If there were no buttons, then we don't need to show this in the structure ...
	if (!iCountButtons)
		delete pMenuItem;

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

	// 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 = new QListViewItem(pMainMenuItem, tr ("Button Masks"), qsFileName);
		pMaskItem->setExpandable (TRUE);

			qsFileName = QFileInfo (m_DVDMenuInterface.qsHighlightedMaskFileName).fileName ();
			pMenuItem = new QListViewItem(pMaskItem, tr (" Highlighted"), qsFileName);
			pMenuItem->setExpandable (TRUE);
			qsName = tr ("to images");
			pButtonItem = new QListViewItem(pMenuItem, tr ("Button 1"), qsName);
			pButtonItem->setExpandable (TRUE);
				new QListViewItem(pButtonItem, tr ("Geometry"), QString ("22, 23, 50, 100"));


// Here is the info for the Selected Mask
			qsFileName = QFileInfo (m_DVDMenuInterface.qsSelectedMaskFileName).fileName ();
			pMenuItem = new QListViewItem(pMaskItem, tr (" Selected"), qsFileName);
			pMenuItem->setExpandable (TRUE);
			qsName = tr ("to images");
			pButtonItem = new QListViewItem(pMenuItem, tr ("Button 1"), qsName);
			pButtonItem->setExpandable (TRUE);
				new QListViewItem(pButtonItem, tr ("Geometry"), QString ("22, 23, 50, 100"));
	}
//printf ("<%d>\n", m_DVDMenuInterface.listSoundFiles.count());
	for (t=m_DVDMenuInterface.listSoundEntries.count();t>0;t--)	{
		qsFileName = QFileInfo (m_DVDMenuInterface.listSoundEntries[t-1]).fileName ();
		new StructureItem(this, pMainMenuItem, tr ("Sound file(s) %1").arg(t-1), qsFileName);
	}
	if ( ! m_DVDMenuInterface.qsMovieFileName.isEmpty ( ) )	{
		qsFileName = QFileInfo (m_DVDMenuInterface.qsMovieFileName).fileName ();
		new StructureItem(getMenuPreview(), pMainMenuItem, tr ("Background"), qsFileName);
	}
	else if ( ! m_DVDMenuInterface.qsBackgroundFileName.isEmpty ( ) )	{
		qsFileName = QFileInfo (m_DVDMenuInterface.qsBackgroundFileName).fileName ();
		new StructureItem(getMenuPreview(), pMainMenuItem, tr ("Background"), qsFileName);
	}
	for (t=m_DVDMenuInterface.listExtroVobs.count();t>0;t--)	{
		qsFileName = QFileInfo (m_DVDMenuInterface.listExtroVobs[t-1]->file).fileName ();
		new StructureItem(this, pMainMenuItem, tr ("Extro file[%1]").arg(t-1), qsFileName);
	}
	for (t=m_DVDMenuInterface.listIntroVobs.count();t>0;t--)	{
		qsFileName = QFileInfo (m_DVDMenuInterface.listIntroVobs[t-1]->file).fileName ();
		new StructureItem(this, pMainMenuItem, tr ("Intro file[%1]").arg(t-1), qsFileName);
	}

	return pMainMenuItem;
}

