/****************************************************************************
** templatewizard.cpp file.
**
** This file implements the TemplateWizardDialog.
**
**   Created :
**        by : Varol Okan
** Copyright : (c) Varol Okan
**   License : GPL v 2.0
**
** The following structure is assumed:
** /usr/share/qdvdauthor/template/static/<TemplateName>/<Files>
** /usr/share/qdvdauthor/template/animated/<TemplateName>/<Files>
** /usr/share/qdvdauthor/template/transition/<TemplateName>/<Files>
**
** Here are the files required :
** template.xml -> holds information about the template, such as comment
**                 NrOfDropZones, coordinates of DropZones etc.
** thumbnail.png-> Image to display in selectionBox ( width=200 )
** background/backgroundXXXXX.jpg where XXXXX = sequenceNo.
** background/background00000.jpg REQUIRED.
** template.mpg -> preview for menus
** dropZone[X].mpg -> default for the dropZone, with X = [1 .. N]
** 
** The requirements are simple: 
** Input, a few user mouse clicks
** Output, one or multiple dvd menu(s)
** 
** Interface to the program : QValueList<DVDMenu *>
** 
*****************************************************************************/

#include <qdir.h>
#include <qtimer.h>
#include <qcursor.h>
#include <qregexp.h>
#include <qlayout.h>
#include <qlistbox.h>
#include <qpainter.h>
#include <qfileinfo.h>
#include <qiconview.h>
#include <qcombobox.h>
#include <qpushbutton.h>

// Include the generated config files ...
#include "CONFIG.h"
#include "xml_dvd.h"
#include "global.h"
#include "utils.h"
#include "qdvdauthor.h"
#include "dvdmenu.h"
#include "messagebox.h"
#include "filepreviewdialog.h"
#include "buttonobject.h"
#include "movieobject.h"
#include "qplayer/mediainfo.h"
#include "qplayer/mediacreator.h"
#include "qplayer/mediacreator.h"

#include "sourcefileentry.h"
#include "templatewizard.h"

/****************************************************************************
** TemplateFrame - class
**
** Simply there to emit a signal when some one clicks in it.
**
*****************************************************************************/
TemplateFrame::TemplateFrame ( TemplateWizard *pWizard, QWidget *pParent, const char *pName, WFlags flags )
	: QFrame (pParent, pName, flags)
{
	m_pTemplateWizard = pWizard;
	setAcceptDrops (TRUE);
}

TemplateFrame::~TemplateFrame ()
{
}

void TemplateFrame::mouseReleaseEvent ( QMouseEvent *pEvent )
{
	emit (signalMouseReleaseEvent (pEvent));
}

void TemplateFrame::dropEvent (QDropEvent *pDropEvent)
{
	// Simply forward to the main object to handle this event.
	if (m_pTemplateWizard)
		m_pTemplateWizard->droppedSomething (pDropEvent);
}

void TemplateFrame::dragEnterEvent(QDragEnterEvent *pEvent)
{
	// Tell the Widget that we accept QTextDrops ...
	// This is necessary otherwise the dropEvent does not occur.
	pEvent->accept (QTextDrag::canDecode(pEvent));
}

ListBoxToolTip::ListBoxToolTip (QListBox* pListBox) : 
	QToolTip(pListBox->viewport()), 
	m_pListBox(pListBox) 
{
}

void ListBoxToolTip::maybeTip(const QPoint& pos) 
{
	// get pointed item
	QListBoxItem* pItem = m_pListBox->itemAt(pos);
	if (pItem == 0)
		return;
	// show tooltip if item is not fully visible
	QRect r = m_pListBox->itemRect(pItem);
	r.setWidth(pItem->width(m_pListBox));
	if (!m_pListBox->viewport()->rect().contains(r))
		tip(r, pItem->text());
}

TemplateWizard::DropZone::DropZone (int i, QString s, QRect r, QString qsType)
{
	bMovie       = false;
	iNumber      = i; 
	iType        = IgnoreObject;
	qsText       = s; 
	rect         = r;
	pPixmap      = NULL;
	if ( qsType == "ImageObject" )
	  iType = ImageObject;
	else if ( qsType == "MovieObject" )
	  iType = MovieObject;
	else if ( qsType == "TextObject" )
	  iType = TextObject;
	else if ( qsType == "FrameObject" )
	  iType = FrameObject;
}

TemplateWizard::DropZone::~DropZone ()
{
  if ( pPixmap )
    delete pPixmap;
}



TemplateWizard::TemplateWizard( QWidget* parent, const char* name, WFlags fl )
    : uiTemplateWizard( parent, name, fl )
{
	m_fScale          = 0.0f;
	m_bDontRestart    = false;
	m_pListBoxToolTip = NULL;
	m_bLocalTemplate  = true;
}

TemplateWizard::~TemplateWizard()
{
	uint t;
	m_bDontRestart = true;
	for (t=0;t<m_listDropZones.count();t++)
		delete m_listDropZones[t];
	if (m_pMediaInterface)	{
		m_pMediaInterface->stop();
		delete m_pMediaInterface;
	}
	if (m_pListBoxToolTip)
		delete m_pListBoxToolTip;
}

void TemplateWizard::hide ()
{
	m_bDontRestart = true;
	if (m_pMediaInterface)
		m_pMediaInterface->stop();

	uiTemplateWizard::hide();
}

// This function refreshes the Templates (in case a new template was added)
// and also the movies on the left side to have the full list of movies available
void TemplateWizard::showDialog ()
{
	show ( );
        initDragList ( );
	initTab ( QString ("static"),     m_pIconViewStatic     );
	initTab ( QString ("animated"),   m_pIconViewAnimated   );
	initTab ( QString ("transition"), m_pIconViewTransition );
}

void TemplateWizard::initMe ( )
{
	refreshComboMenu ( );
	setNextEnabled   ( page ( 0 ), false );
	setFinishEnabled ( page ( 1 ), true  );

	// Create the tooltips ...
	m_pListBoxToolTip  = new ListBoxToolTip (m_pListBoxSources);

	// Here we create the main templateFrame
	QGridLayout *WizardPageLayout_2 = new QGridLayout( m_pOuterFrame, 1, 1, 11, 6, "WizardPageLayout_2"); 
	QSpacerItem *spacer1 = new QSpacerItem( 20, 2, QSizePolicy::Minimum, QSizePolicy::Expanding );
	WizardPageLayout_2->addItem( spacer1, 0, 1 );

	m_pFrameProperties = new TemplateFrame( this, m_pOuterFrame, "m_pFrameProperties" );
	m_pFrameProperties->setSizePolicy  ( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)1, 2, 2, m_pFrameProperties->sizePolicy().hasHeightForWidth() ) );
	m_pFrameProperties->setFrameShape  ( QFrame::StyledPanel );
	m_pFrameProperties->setFrameShadow ( QFrame::Raised );
	connect (m_pFrameProperties, SIGNAL(signalMouseReleaseEvent (QMouseEvent *)), this, SLOT(slotTemplateClicked (QMouseEvent *)));

	WizardPageLayout_2->addWidget( m_pFrameProperties, 1, 1 );
	QSpacerItem *spacer1_2 = new QSpacerItem( 20, 2, QSizePolicy::Minimum, QSizePolicy::Expanding );
	WizardPageLayout_2->addItem( spacer1_2, 2, 1 );
	QSpacerItem *spacer3 = new QSpacerItem( 2, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
	WizardPageLayout_2->addItem( spacer3, 1, 2 );
	QSpacerItem *spacer3_2 = new QSpacerItem( 2, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
	WizardPageLayout_2->addItem( spacer3_2, 1, 0 );

	connect (m_pComboMenu, SIGNAL(activated (const QString &)), this, SLOT(slotTargetMenuChanged (const QString &)));
	resize( QSize(739, 536).expandedTo(minimumSizeHint()) );
	clearWState( WState_Polished );
	initPreview  ();
	// And finally we connect the listBox to some event handler 
	m_pListBoxSources->setHScrollBarMode(QScrollView::AlwaysOff);
	connect (m_pListBoxSources,    SIGNAL( pressed (QListBoxItem  *)), this, SLOT ( slotListBoxClicked  (QListBoxItem  *)));
	connect (m_pIconViewStatic,    SIGNAL( clicked (QIconViewItem *)), this, SLOT ( slotIconViewClicked (QIconViewItem *)));
	connect (m_pIconViewAnimated,  SIGNAL( clicked (QIconViewItem *)), this, SLOT ( slotIconViewClicked (QIconViewItem *)));
	connect (m_pIconViewTransition,SIGNAL( clicked (QIconViewItem *)), this, SLOT ( slotIconViewClicked (QIconViewItem *)));
	connect (m_pButtonDetails,     SIGNAL( clicked ( ) ),              this, SLOT ( slotTemplateDetails ( ) ) );
	connect (this,                 SIGNAL( helpClicked () ),           this, SLOT ( slotHelp () ) );
}

void TemplateWizard::slotPlaybackFinished ()
{
	// TODO: check elapsed time and break this one here if < 2 seconds.
	if ( ! m_bDontRestart )
		m_pMediaInterface->play ();
	m_bDontRestart = false;
}

void TemplateWizard::refreshComboMenu ()
{
	uint t;
	m_pComboMenu->clear ();

	if (m_qsCurrentTemplate.isEmpty())
		m_qsCurrentTemplate = QString ("New Menu");

	// Here we ensure we have a unique name
	m_qsCurrentTemplate = Global::pApp->getUniqueMenuTitle (m_qsCurrentTemplate, 0);

	m_pComboMenu->insertItem (m_qsCurrentTemplate);
	m_pComboMenu->insertItem (VMGM_LABEL);

	DVDMenu *pMainMenu = Global::pApp->getVMGMenu ( );
	QValueList<DVDMenu *> listMenus = Global::pApp->getSubMenus ();
	for (t=0;t<listMenus.count();t++)
		m_pComboMenu->insertItem (listMenus[t]->name());
	// if the main menu is empty, then we should suggest this instead of a new menu ...
	if ( pMainMenu->isEmpty ( ) ) {
	  m_pComboMenu->setCurrentItem  ( 1 );
	  m_pComboMenu->setEditable ( false );
	}
}

void TemplateWizard::initPreview ( )
{
	m_pLabelPreview->hide ( );

	// Here we create the mediaEngine for this dialog.
	MediaInfo *pMediaInfo   = Global::pApp->getMediaInfo ( );
	void      *pMediaEngine = pMediaInfo->getMediaEngine ( );
	m_pMediaInterface = MediaCreator::createPreferredWidget (m_pFramePreview, "TemplateMediaWidget", pMediaEngine);
	connect (m_pMediaInterface, SIGNAL(signalPlaybackFinished()), this, SLOT(slotPlaybackFinished()));
	
	QGridLayout *pVideoLayout = new QGridLayout (m_pFramePreview, 1, 1, 2, 2, "MediaMainLayout");
	pVideoLayout->addWidget (m_pMediaInterface->getWidget(), 0, 0);
	// This is taken care of in the polish () function for Xine and not necessary for MPlayer ...
	m_pMediaInterface->initMediaEngine();
}

void TemplateWizard::initDragList ()
{
	// This function will initialize the ListBox to the left on the second page.
	// It will take the images straight from SourceFileInfo objcts
	uint t, i;
	SourceFileEntry *pEntry;
	SourceFileInfo  *pInfo;
	int iWidth = 125;

	m_listSourceFileDescriptions.clear ();
	m_pListBoxSources->clear ();
	for ( t=0; (int)t<Global::pApp->sourceFileCount  ( ); t++ )  {
		pEntry  = Global::pApp->sourceFileEntry ( t );
		if ( ! pEntry )
			continue;
		if ( pEntry->bSoundSource )
			continue;
		for ( i=0; i<pEntry->listFileInfos.count ( ); i++ )  {
			pInfo = pEntry->listFileInfos[i];
			if ( ( ! pInfo ) || ( ! pInfo->pPreview ) )
				continue;
			QImage tempImage ( *pInfo->pPreview );
			m_pListBoxSources->insertItem (tempImage.smoothScale (iWidth, iWidth, QImage::ScaleMin), pInfo->qsFileName);
			m_listSourceFileDescriptions.append (QString ("%1 : %2").arg(pInfo->qsFileName).arg(pInfo->qsSize));
		}
	}
}

void TemplateWizard::initTab (QString qsWhichTab, QIconView *pIconView)
{
  uint t,  i, iTemplatePath;
  bool        bContinue;
  QStringList listTemplates;
  QString     qsPrefixDir, qsPixmap, qsXMLFile, qsBackgroundFile, qsHomeDir, qsTemplateName;
  QFileInfo   fileInfo;
  QPixmap     thePixmap;
  QDir        theTemplates; 
  QStringList listOfTemplates; // used to keep count of templates
  QSize grid (50, 50);
  qsHomeDir = QDir::homeDirPath ( );

  pIconView->clear ( );
  qsPrefixDir = QString ( "%1/.qdvdauthor/%2" ).arg ( qsHomeDir ).arg ( qsWhichTab );
  for (  iTemplatePath=0; iTemplatePath<2; iTemplatePath++ ) {
    if ( iTemplatePath == 1 ) {
      // for the second run we'll get the system wide installed Templates.
      // Note: lcally installed Templates overrule System wide installed Templates.
      qsPrefixDir = QString ("%1/share/qdvdauthor/%2").arg ( Global::qsSystemPath ).arg(qsWhichTab);
    }

    if ( ! theTemplates.exists (qsPrefixDir) ) {
      if ( iTemplatePath == 0 )
	continue;
      if ( listOfTemplates.count () < 1 )
	new QIconViewItem (pIconView, tr ("No %1 templates found.").arg (qsWhichTab));
      return;
    }

    pIconView->arrangeItemsInGrid ( grid, TRUE );

    theTemplates.cd ( qsPrefixDir, TRUE );
    listTemplates = theTemplates.entryList ( QDir::Dirs, QDir::Name );
    if (listTemplates.count ( ) < 3)	{ // 3 = this dir / parent dir / background file
      if ( iTemplatePath == 0 )
	continue;
      if ( listOfTemplates.count ( ) < 1 )
	new QIconViewItem (pIconView, tr ("No %1 Backgrounds in dir :\n%2").arg(qsWhichTab).arg(qsPrefixDir));
      return;
    }
    for (t=0;t<listTemplates.count ();t++)	{
      // Here we go through all directories and check if the preview is present.
      // if so, then we snap the preview.jpg and create a ListItem
      qsTemplateName = listTemplates[t];
      if ( ( qsTemplateName == ".") || ( qsTemplateName == "..") )
	continue;
      // next we check if the Local Templates already defined this one
      bContinue = false;
      for (i=0;i<listOfTemplates.count();i++) {
	if ( listOfTemplates[i] == qsTemplateName ) {
	  bContinue = true;
	}
      }
      if ( bContinue )
	continue;

      qsPixmap = QString ("%1/%2/%3").arg(qsPrefixDir).arg(qsTemplateName).arg("thumbnail.png");
      fileInfo.setFile (qsPixmap);
      if ( ! fileInfo.exists() )
	continue;
      qsXMLFile = QString ("%1/%2/%3").arg(qsPrefixDir).arg( qsTemplateName ).arg("template.xml");
      fileInfo.setFile (qsXMLFile);
      if ( ! fileInfo.exists() )
	continue;
      qsBackgroundFile = QString ("%1/%2/background/background00000.jpg").arg(qsPrefixDir).arg( qsTemplateName);
      fileInfo.setFile (qsBackgroundFile);
      if ( ! fileInfo.exists() )
	continue;
      listOfTemplates.append ( qsTemplateName );
      thePixmap = QPixmap (qsPixmap);
      new QIconViewItem (pIconView, qsTemplateName, thePixmap);
    }
  }
}

void TemplateWizard::slotIconViewClicked (QIconViewItem *pIconViewItem)
{
  // The user clicked one of the Icons, 
  // so we should get the information, and read in the description from template.xml
  if ( ! pIconViewItem )
    return;
  QString qsDescription, qsFileName, qsType;
  QPixmap thumbnail;
  QFile   theFile;
  QDir    theDir;

  // First we determine where the click came from
  m_bDontRestart = true;
  m_pMediaInterface->stop ();
  qsType = "static";
  if (m_pIconViewAnimated->index (pIconViewItem) != -1)
    qsType = "animated";
  if (m_pIconViewTransition->index (pIconViewItem) != -1)
    qsType = "transition";
  m_qsPathName =  QString ("%1/.qdvdauthor/%2/%3/").arg( QDir::homeDirPath () ).arg( qsType ).arg(pIconViewItem->text());
  m_bLocalTemplate = true;

  // check if this is a local template or a system wide installed template.
  if ( ! theDir.exists ( m_qsPathName ) ) {
    m_bLocalTemplate = false;
    m_qsPathName = QString ("%1/share/qdvdauthor/%2/%3/").arg ( Global::qsSystemPath ).arg( qsType ).arg(pIconViewItem->text());
  }

  QFileInfo fileInfo ( m_qsPathName + QString ( "thumbnail.mpg" ) );
  if ( fileInfo.exists ( ) ) {
    m_pLabelPreview->hide();
    m_pFramePreview->show();
    // first we get the right frame size ...
    thumbnail = QPixmap( m_qsPathName+QString ( "thumbnail.png" ) );
    fileInfo.setFile   ( m_qsPathName+QString ( "thumbnail.png" ) );
    if ( fileInfo.exists ( ) )
      m_pFramePreview->setFixedSize ( thumbnail.size ( ) );
    else
      m_pFramePreview->setFixedSize ( 200, 150 );

    theFile.setName ( m_qsPathName+QString ( "thumbnail.mpg" ) );
    m_pMediaInterface->playMRL ( m_qsPathName + QString ( "thumbnail.mpg" ) );
    m_bDontRestart = false;
  }
  else { 
    thumbnail = QPixmap(m_qsPathName+QString ("thumbnail.png"));
    m_pLabelPreview->show ( );
    m_pFramePreview->hide ( );
    m_pLabelPreview->setPixmap    ( thumbnail );
    m_pLabelPreview->setFixedSize ( thumbnail.size ( ) );
  }

  qsFileName = m_qsPathName + QString ("template.xml");
  qsDescription = readProjectFile (qsFileName, true);
  m_pLabelTemplateDescription->setText (qsDescription);
  refreshComboMenu ();
  m_pComboMenu->setEditable ( true );
  setNextEnabled ( page (0), true );
}

void TemplateWizard::slotTemplateDetails ( )
{
  QString qsInfo;

  qsInfo  = QString ( "Template Name : <B>%1</B><P>" ).arg ( m_qsCurrentTemplate );
  qsInfo += QString ( "Author        : <B>%1</B><BR>").arg ( m_qsTemplateAuthor  );
  qsInfo += QString ( "Contact       : <B>%1</B><BR>").arg ( m_qsTemplateContact );
  qsInfo += QString ( "Version       : <B>%1</B><P>" ).arg ( m_qsTemplateVersion );
  qsInfo += QString ( "Description   : <B>%1</B><P>" ).arg ( m_qsTemplateDescription );
  qsInfo += QString ( "Comment       : <B>%1</B><P>" ).arg ( m_qsTemplateComment );

  MessageBox::html ( this, tr ( "Details for template." ), qsInfo );  
}

void TemplateWizard::slotListBoxClicked (QListBoxItem *pItem)
{
	int iIndex;
	iIndex = m_pListBoxSources->index (pItem);
	if (iIndex < 0 || iIndex > (int)m_listSourceFileDescriptions.count () - 1)
		return;
	m_pLabelInfo->setText (m_listSourceFileDescriptions[iIndex]);
	// Last we create a dragObject ...
	QDragObject *d = new QTextDrag( m_listSourceFileDescriptions[iIndex], this );
	d->setPixmap (QPixmap (*pItem->pixmap ()));
	d->dragCopy();
}

void TemplateWizard::droppedSomething (QDropEvent *pDropEvent)
{
  uint t, i, iHeight;
  QImage  theImage;
  QString theText;
  QPoint  thePos;
  DropZone *pDropZone = NULL;
  SourceFileEntry *pEntry = NULL;
  SourceFileInfo  *pInfo  = NULL;

  if ( ! QTextDrag::decode(pDropEvent, theText) )
    return;

  // The first step is to verify that it was dropped over a DropZone.
  thePos.setX ((int)(pDropEvent->pos().x () / m_fScale));
  thePos.setY ((int)(pDropEvent->pos().y () / m_fScale));

  for (t=0;t<m_listDropZones.count();t++)	{
    if (m_listDropZones[t]->rect.contains (thePos))	{
      pDropZone = m_listDropZones[t];
      break;
    }
  }
  if ( ! pDropZone )
    return;

  // Get the previewImage ...
  for ( t=0; (int)t<Global::pApp->sourceFileCount ( ); t++ )  {
    pEntry = Global::pApp->sourceFileEntry ( t );
    for ( i=0; i<pEntry->listFileInfos.count ( ); i++ )  {
      if ( pEntry && ( theText.contains ( pEntry->listFileInfos[i]->qsFileName ) > 0 ) )  {
        pDropZone->qsFileName = pEntry->listFileInfos[i]->qsFileName;
        pDropZone->bMovie     = true;
        pInfo = pEntry->listFileInfos[i];
        // Exit both loops ...
        t = Global::pApp->sourceFileCount ( );
        i = pEntry->listFileInfos.count   ( );
      }
    }
  }

//  if ( ( pDropZone->iType != DropZone::TextObject ) && ( pDropZone->iType != DropZone::FrameObject ) )  {
    if ( pInfo && pInfo->pPreview )  {
      float fRatio = (float)pInfo->pPreview->height ( ) / pInfo->pPreview->width ( );
      // for the templates we want to use the width as our ruler (I.e. adjust the height of the image according to the ratio
      iHeight = (int)( fRatio * pDropZone->rect.width ( ) );
      theImage = pInfo->pPreview->smoothScale ( (int)( m_fScale * pDropZone->rect.width ( ) ),(int)( m_fScale * iHeight ), QImage::ScaleMin );
      //theImage = pInfo->pPreview->smoothScale ((int)(m_fScale*pDropZone->rect.width()), (int)(m_fScale * pDropZone->rect.height()), QImage::ScaleMin);
    }
    else  {
      theImage = QImage ( ).fromMimeSource( "error.jpg" );
      theImage = theImage.smoothScale ( (int)( m_fScale*pDropZone->rect.width ( ) ), (int)( m_fScale * pDropZone->rect.height ( ) ), QImage::ScaleFree );
    }

    DragNDropContainer *pDND = Global::pApp->getDragNDropContainer ( );
    if ( pDND ? pDND->bImageButton : false ) {
      Utils     theUtil;
      QFileInfo fileInfo ( pDropZone->qsFileName );
      pDropZone->qsImagePreview = theUtil.getTempFile ( fileInfo.baseName ( ) ) + QString (".png");
      theImage.save ( pDropZone->qsImagePreview, "PNG", 100 );
    }

    // Set the DropZoneValues ...
    // Note: theText is "$FileName : $size" so that does not work.
    // pDropZone->qsFileName = theText;
    if ( pDropZone->pPixmap )
      delete pDropZone->pPixmap;
    pDropZone->pPixmap = new QPixmap;
    pDropZone->pPixmap->convertFromImage ( theImage );
//  }
  refreshBackground ( );
}

void TemplateWizard::slotTargetMenuChanged (const QString &qsMenuName)
{
	// Here we check if we have a new or an existing menu.
	bool bEditable = true;

	if ( Global::pApp->getSubMenuByName ( qsMenuName ) )
		bEditable = false;
	m_pComboMenu->setEditable ( bEditable );
}

void TemplateWizard::slotTemplateClicked (QMouseEvent *pMouseEvent)
{
  uint t;
  QPoint mousePos;
  QString qsFileName, qsFilter, qsExtensions;
  DropZone *pDropZone = NULL;

  mousePos.setX ((int)( pMouseEvent->pos ().x() / m_fScale ));
  mousePos.setY ((int)( pMouseEvent->pos ().y() / m_fScale ));

  for (t=0;t<m_listDropZones.count();t++)	{
    if (m_listDropZones[t]->rect.contains (mousePos))	{
      pDropZone = m_listDropZones[t];
      break;
    }
  }
  if ( ! pDropZone )
    return;

  qsFilter   = Global::pApp->getImageFilter ( );
  qsFilter  += " " + Global::pApp->getMovieFilter ( );
  qsFileName = FilePreviewDialog::getOpenFileName ( NULL, Global::qsCurrentPath, tr ("Images/Movies (") + qsFilter + QString (")"));
  if (qsFileName.isNull())
    return;

  QImage theImage;
  Utils  theUtil;

  QFileInfo backgroundInfo (qsFileName);
  MediaInfo *pMediaInfo = Global::pApp->getMediaInfo ( );

  Global::qsCurrentPath = backgroundInfo.dirPath ( TRUE );

  pDropZone->qsFileName = qsFileName;
  qsExtensions = pMediaInfo->getExtensions ( true );
  if (qsExtensions.find ("."+backgroundInfo.extension(FALSE), 0, FALSE) > -1)	{
    pDropZone->bMovie = true;
//    if ( ( pDropZone->iType == DropZone::TextObject ) || ( pDropZone->iType == DropZone::FrameObject ) ) {
//      refreshBackground ( );
//      return;
//    }
    // Okay let us get the first frame of the game as a screenshot ...
    pMediaInfo->setFileName ( qsFileName );
    theImage = pMediaInfo->getScreenshot ( 0 );
    // The we save the screenshot in the temp dir
    qsFileName = theUtil.getTempFile ( backgroundInfo.baseName ( ) ) + QString ( ".png" );
    theImage.save ( qsFileName, "PNG" );
    DragNDropContainer *pDND = Global::pApp->getDragNDropContainer ( );
    if ( pDND && pDND->bImageButton )
         pDropZone->qsImagePreview = qsFileName;
  }
  else  // Not a movie file, then we should reset this ...
    theImage = QImage ( qsFileName );

  if ( ( pDropZone->iType != DropZone::TextObject ) && ( pDropZone->iType != DropZone::FrameObject ) ) {
    theImage = theImage.smoothScale ((int)(m_fScale*pDropZone->rect.width()), (int)(m_fScale * pDropZone->rect.height()), QImage::ScaleMin);

    if (pDropZone->pPixmap)
      delete pDropZone->pPixmap;
    pDropZone->pPixmap = new QPixmap;
    pDropZone->pPixmap->convertFromImage (theImage);
  }
  refreshBackground ( );
}

QString TemplateWizard::readProjectFile (QString qsFileName, bool bHeaderOnly)
{
	QDomDocument xmlDoc( TEMPLATE_DOCTYPE );
	QDomElement  docElem;
	QDomNode     xmlNode;
	int          iX, iY, iWidth, iHeight, iDropZoneNumber;
	uint         t;
	QString      text, qsDropZoneType;
	QRect        rectDropZone;
	// First we take care of the QDVDAuthor variables ...
	QString  qsTemplateName;
	QDomAttr attribute;

	QFile templateFile (qsFileName);
	if ( ! templateFile.open(IO_ReadOnly))
		return qsTemplateName;
	
	if (!xmlDoc.setContent (&templateFile))	{
		// Error handling ...
		templateFile.close();
		MessageBox::warning ( this, tr ("xml template file seems to be defective."),
			tr ("Please try another template file."),
			QMessageBox::Ok, QMessageBox::NoButton);
		return qsTemplateName;
	}

	m_qsTemplateVersion     = "";
	m_qsTemplateAuthor      = "";
	m_qsTemplateContact     = "";
	m_qsTemplateHeader      = "";
	m_qsTemplateDescription = "";
	m_qsTemplateComment     = "";	

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

	// Here is the main loop to extract the info ...
	docElem = xmlDoc.documentElement();
	xmlNode = docElem.firstChild();

	attribute = docElem.attributeNode ( TEMPLATE_NAME );
	if (!attribute.isNull())	{
		qsTemplateName = attribute.value();
		m_qsCurrentTemplate = qsTemplateName;
	}
	attribute = docElem.attributeNode ( TEMPLATE_VERSION );
	if (!attribute.isNull())	{
		QString qsTemplateVersion = attribute.value();
		if ( qsTemplateVersion.toFloat ( ) > TEMPLATE_VERSION_NUMBER+0.09 ) {
		  QMessageBox::information ( NULL, tr ("Template too new"), 
		      tr ("The template was created with an newer version of QDVDAuthor.\nNot all features might work properly.\nPlease consider upgrading to the latest QDVDAuthor version.\n"), 
		      QMessageBox::Ok,  QMessageBox::NoButton);
		}
	}

	while( !xmlNode.isNull() ) {
		QDomElement searchXMLTree = xmlNode.toElement();
		// Okay, here we retain the stored data from the xml file.
		QString tagName  = searchXMLTree.tagName();
		QString nodeText = searchXMLTree.text ();
		// Okay, this is ugly but after all it is the simplest of all xml file structure.
		// No need to get fancy ...
		if ( TEMPLATE_VERSION == tagName )
			m_qsTemplateVersion = nodeText;
		else if ( TEMPLATE_AUTHOR == tagName )
			m_qsTemplateAuthor = nodeText;
		else if ( TEMPLATE_CONTACT == tagName )
			m_qsTemplateContact = nodeText;
		else if ( TEMPLATE_HEADER == tagName )
			m_qsTemplateHeader = nodeText;
		else if ( TEMPLATE_DESCRIPTION == tagName )
			m_qsTemplateDescription = nodeText;
		else if ( TEMPLATE_COMMENT == tagName )
			m_qsTemplateComment = nodeText;
		else if ( ( TEMPLATE_DROPZONE == tagName ) && (!bHeaderOnly) )	{
			attribute = searchXMLTree.attributeNode ( TEMPLATE_DROPZONE_TYPE);
			qsDropZoneType = attribute.value( );
			attribute = searchXMLTree.attributeNode ( TEMPLATE_DROPZONE_NUMBER);
			iDropZoneNumber = attribute.value().toInt();
			attribute = searchXMLTree.attributeNode ( TEMPLATE_DROPZONE_X);
			iX = attribute.value().toInt();
			attribute = searchXMLTree.attributeNode ( TEMPLATE_DROPZONE_Y);
			iY = attribute.value().toInt();
			attribute = searchXMLTree.attributeNode ( TEMPLATE_DROPZONE_WIDTH);
			iWidth = attribute.value().toInt();
			attribute = searchXMLTree.attributeNode ( TEMPLATE_DROPZONE_HEIGHT);
			iHeight = attribute.value().toInt();
			rectDropZone = QRect(iX, iY, iWidth, iHeight);
			DropZone *pDropZone = new DropZone ( iDropZoneNumber, text, rectDropZone, qsDropZoneType );
			m_listDropZones.append (pDropZone);
		}
		else if ( (TEMPLATE_DATA == tagName ) && (!bHeaderOnly) )	{
			m_qsXMLDVDMenu = searchXMLTree.text();
		}
		// So lets get the next sibling ... until we hit hte end of DVDMenu ...
		xmlNode = xmlNode.nextSibling();
	}
	templateFile.close();

	// Okay, once something has been selected means we keep this and enable the next button
	nextButton()->setEnabled (true);
	
	return m_qsTemplateDescription;;
}

/**
 * This function is called when the user clicks on the next button.
 */
void TemplateWizard::next ()
{
	QString qsFileName;
	// The user clicked the next button.
	if (m_qsPathName.isEmpty ())
		return;
	if ( ! m_pComboMenu->editable ( ) )	{
		DVDMenu *pDVDMenu = Global::pApp->getSubMenuByName ( m_pComboMenu->currentText ( ) );
		if ( ( pDVDMenu) && ( ! pDVDMenu->isEmpty () ) )	{
			if (QMessageBox::information (NULL, tr ("Override Menu"), tr ("Warning the menu %1 will be replaced.\nAre you sure ?").arg (m_pComboMenu->currentText()), QMessageBox::Yes,  QMessageBox::No) == QMessageBox::No)
			return;
		}
	}

	QWizard::next ();
	// At this point we should be on the other side ...
	// So first we read in the whole project file.
	qsFileName = m_qsPathName + QString ("template.xml");
	readProjectFile (qsFileName, false);
	// Then we build a simple GUI for the user to provide the neccesary files
	refreshBackground ();
}

void TemplateWizard::refreshBackground ()
{
  uint      t;
  int       iTemp, iX, iY;
  QPixmap   thePixmap;
  QImage    theImage;
  QString   qsFileName;
  QRect     tempRect;
  DropZone *pDropZone;

  theImage = QImage (m_qsPathName + QString ("preview.png"));
  theImage = theImage.smoothScale (m_pFrameProperties->width(), m_pFrameProperties->height(), QImage::ScaleMin);
  thePixmap.convertFromImage(theImage);
  // Next we draw the black DropZones ...
  m_fScale = (float)thePixmap.width() / 720.0;
  QPainter painter( &thePixmap );
  for (t=0;t<m_listDropZones.count();t++)	{
    pDropZone = m_listDropZones[t];
    //    if (m_listDropZones[t]->pPixmap == NULL)	{
    if ( pDropZone->qsFileName.isNull ( ) )	{
      tempRect.setX      ( (int)( m_fScale *  pDropZone->rect.x ( ) ) );
      tempRect.setY      ( (int)( m_fScale *  pDropZone->rect.y ( ) ) );
      tempRect.setWidth  ( (int)( m_fScale * (pDropZone->rect.width ( )+2 ) ) );
      tempRect.setHeight ( (int)( m_fScale * (pDropZone->rect.height( )+2 ) ) );
      painter.setBrush   ( Qt::black  );
      painter.setPen     ( Qt::yellow );
      painter.drawRect ( tempRect ); // nothing dropped in it yet
      painter.drawText ( tempRect, Qt::AlignCenter|Qt::DontClip, QString ( "%1" ).arg ( pDropZone->iNumber + 1 ) );
    }
    else	{
      if ( ( pDropZone->iType != DropZone::TextObject  ) && 
	   ( pDropZone->iType != DropZone::FrameObject )  ) {
	iTemp = (int)( m_fScale * pDropZone->rect.width  ( ) ) - pDropZone->pPixmap->width ( );
	iX    = (int)( m_fScale * pDropZone->rect.x ( ) + (int)(iTemp/2.0));
	iTemp = (int)( m_fScale * pDropZone->rect.height ( ) ) - pDropZone->pPixmap->height ( );
	iY    = (int)( m_fScale * pDropZone->rect.y ( ) + (int)(iTemp/2.0 ) );
	painter.drawPixmap ( iX, iY, *( pDropZone->pPixmap ) );
      }
    }
  }
  m_pFrameProperties->setFixedWidth  ( thePixmap.width  ( ) );
  m_pFrameProperties->setFixedHeight ( thePixmap.height ( ) );
  m_pFrameProperties->setBackgroundPixmap  ( thePixmap );
}

QString TemplateWizard::getSourceEntryName (QString qsFileName)
{
  // This function will check if the file is already part of a SourceFileEntry.
  uint t, i;
  QString qsEntryName;
  SourceFileEntry *pEntry;

  for ( t=0; (int)t<Global::pApp->sourceFileCount ( ); t++ )  {
    pEntry = Global::pApp->sourceFileEntry  ( t );
    for  ( i=0; i<pEntry->listFileInfos.count ( ); i++ )	{
      if ( pEntry->listFileInfos[i]->qsFileName == qsFileName )  {
        qsEntryName = pEntry->qsDisplayName;
        return qsEntryName;
      }
    }
  }
  return qsEntryName;
}

void TemplateWizard::slotHelp ()
{
  QString qsHeader, qsHtml;
  qsHeader = tr ("Wizard for templates.");

  qsHtml  = tr ( "Select <B>One</B> of the templates you like to use and click on [<B>Next ></B>]<P>" );
  qsHtml += tr ( "Don't forget to define if you want to add a new menu or if you wnt to replace an existing menu. This can be done by the ComboBox on the right.<P>" );

  qsHtml += tr ( "In the second stage you have to assign the objects to the DropZones.");
  qsHtml += tr ( "You can do this by dragging the movie from the left side or by clicking into the DropZone itself.<P>" );

  MessageBox::html ( NULL, qsHeader, qsHtml );
}

void TemplateWizard::reject ()
{
	QWizard::reject();
}

// +DROP_ZONE_x_IMOV_TYPE+   Replaces Object with either Image or Movie Object
// +DROP_ZONE_x_OBJECT_TYPE+ Replaces Object with img/mov/text/frame
// +DROP_ZONE_x_BUTTON+      Replaces ButtonObject with IgnoreObject if required
// +DROP_ZONE_x_FILE_NAME+   Replaces with proper file name from the drop
// +DROP_ZONE_x_BASE_NAME+   Replaces the object name
// +DROP_ZONE_x_GEOMETRY+    Replaces the geometry such that it stays cenetered
// +DROP_ZONE_x_MOVIE_SIZE+  
// +DROP_ZONE_x_ACTION+      Replaces with the proper buton action string.
// +DROP_ZONE_SOURCE_ENTRY+  Replaces 
void TemplateWizard::accept ()
{
	// First we are going to replace the DropZone placeholder and then create a DVDMenu.
	uint t;
	int i, iFreeSlot, iX, iY, iWidth, iHeight;
	QString qsAction, qsEntryName, qsEntry, qsPrefixDir, qsMenuName;
	QString qsGeometry, qsCurrentPath, qsType, qsTypeImov, qsExtensions;
	QFileInfo fileInfo;
	QStringList listAddMovies;
	DropZone *pDropZone;
	bool bDropToImage;

	QCursor myCursor (QCursor::WaitCursor);
	setCursor(myCursor);
	qsCurrentPath = Global::qsCurrentPath;
	iFreeSlot = Global::pApp->getFreeSourceSlot ( );
	qsEntryName.sprintf ("[%02d] - source", iFreeSlot);
	
	qsPrefixDir = QString ("%1/.qdvdauthor/").arg( QDir::homeDirPath ( ) );
	if ( ! m_bLocalTemplate ) 
	  qsPrefixDir = QString ("%1/share/qdvdauthor/").arg( Global::qsSystemPath );

	m_qsXMLDVDMenu.replace (QString ("+PREFIX_DIRECTORY+"), qsPrefixDir);
	for ( t=0; t<m_listDropZones.count ( ); t++ )  {
		pDropZone = m_listDropZones[t];
		i = pDropZone->iNumber;

		fileInfo.setFile ( pDropZone->qsFileName );

		bDropToImage = false;
		qsExtensions = Global::pApp->getImageFilter ( );
		if ( qsExtensions.find ( "."+fileInfo.extension ( FALSE ), 0, FALSE ) > -1 )
		  bDropToImage = true;

		if ( pDropZone->qsFileName.isEmpty())	{
			m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_IMOV_TYPE+"  ).arg(i), QString ("IgnoreObject"));
			m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_OBJECT_TYPE+").arg(i), QString ("IgnoreObject"));
			m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_BUTTON+"     ).arg(i), QString ("IgnoreObject"));
			m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_FILE_NAME+"  ).arg(i), QString ());
			m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_BASE_NAME+"  ).arg(i), QString ());
			m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_GEOMETRY+"   ).arg(i), QString ());
			m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_MOVIE_SIZE+" ).arg(i), QString ());
			m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_ACTION+"     ).arg(i), QString ());
			continue;
		}
		
		{ // Next we check this ButtonObject for SourceEntry and set it accordingly
		  QString qsButtonXml, qsPattern, qsSourceEntry;
		  QRegExp rx;
		  // Determine the EntryName by parsing through the currently existng SourceFileEntries and trying to find the defined file.
		  qsSourceEntry = getSourceEntryName ( pDropZone->qsFileName );
		  if ( qsSourceEntry.isEmpty ( ) ) // If this movie is not yet in a SourceFileEntry, then use he newly created one.
		       qsSourceEntry = qsEntryName;
		  qsSourceEntry.replace ( "<", "&lt;" );
		  qsSourceEntry.replace ( ">", "&gt;" );
		  rx.setMinimal ( true );
		  qsPattern = QString ( "DROP_ZONE_%1_BUTTON[^>]*>.*</.DROP_ZONE_%2_BUTTON.>" ).arg ( i ).arg ( i );
		  rx.setPattern ( qsPattern );

		  if ( m_qsXMLDVDMenu.find ( rx ) > -1 ) {
		    qsButtonXml = rx.cap   ( 0 );
		    if ( qsButtonXml.find  ( "+DROP_ZONE_SOURCE_ENTRY+" ) > -1 )
		      qsButtonXml.replace  ( "+DROP_ZONE_SOURCE_ENTRY+", qsSourceEntry );
		    else // Could not find in template ... create on the spot.
		      qsButtonXml.replace  ( "Action=", "SourceEntry=\"" + qsSourceEntry + "\" Action=" );
		  }
		  // TODO: fix this function ...
		  adjustPixmapHeight ( pDropZone->pPixmap, qsButtonXml );

		  m_qsXMLDVDMenu.replace ( rx, qsButtonXml );
		} // end of replacing this buttonObjects DROP_ZONE_SOURCE_ENTRY ...

		// Next we take care of the geometry
		iWidth = iHeight = 0;
		// the pixmap should have the real extensions of the Object
		if ( pDropZone->pPixmap ) {
		  iWidth  = (int) ( pDropZone->pPixmap->width ( ) / m_fScale + 0.5 );
		  iHeight = (int) ( pDropZone->pPixmap->height( ) / m_fScale + 0.5 );
		}
		if ( iWidth  < 2 )
		     iWidth  = pDropZone->rect.width ( );
		if ( iHeight < 2 )
		     iHeight = pDropZone->rect.height( );
		iX = (int)(( pDropZone->rect.width () - iWidth )/2.0 + pDropZone->rect.x());
		iY = (int)(( pDropZone->rect.height() - iHeight)/2.0 + pDropZone->rect.y());
		qsGeometry = QString (" X=\"%1\" Y=\"%2\" Width=\"%3\" Height=\"%4\" ").arg(iX).arg(iY).arg(iWidth).arg(iHeight);

//		m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_FILE_NAME+").arg(i), fileInfo.absFilePath());
		m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_BASE_NAME+").arg(i), fileInfo.baseName());
//		m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_BASE_NAME+").arg(i), fileInfo.fileName());
		m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_BUTTON+"   ).arg(i), QString ("ButtonObject"));
		m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_GEOMETRY+" ).arg(i), qsGeometry);
		qsType = "ImageObject"; // default
		DragNDropContainer *pDND = Global::pApp->getDragNDropContainer ( );
		if ( pDND ? ! pDND->bImageButton : true )  {
		  // Last check is to see if we have a img on our hand
		  if ( ! bDropToImage )
		    qsType = "MovieObject";
		}
		qsTypeImov = qsType;
		// Note we do not want to change Frames or text ...
		if ( pDropZone->iType == DropZone::TextObject )
		  qsType = "TextObject";
		else if ( pDropZone->iType == DropZone::FrameObject )
		  qsType = "FrameObject";

		if ( pDropZone->bMovie )  {
			// Note: if we find the file already in a SourceFileEntry, then we do not need to add it again.
			qsEntry = getSourceEntryName ( pDropZone->qsFileName );
			if (qsEntry.isEmpty())	{ // If nothing has been found in the current SourceFileEntry list
				qsEntry = qsEntryName;
				listAddMovies.append ( pDropZone->qsFileName );
			}
			qsEntry.replace ("<", "&lt;");
			qsEntry.replace (">", "&gt;");
			qsAction = QString ( "jump+-+%1+-+%2+-+00:00:00.000").arg(qsEntry).arg(fileInfo.fileName ( ) );
			m_qsXMLDVDMenu.replace ( QString ( "+DROP_ZONE_%1_IMOV_TYPE+"  ).arg( i ),  qsTypeImov  );
			m_qsXMLDVDMenu.replace ( QString ( "+DROP_ZONE_%1_OBJECT_TYPE+").arg( i ),  qsType      );
			m_qsXMLDVDMenu.replace ( QString ( "+DROP_ZONE_%1_MOVIE_SIZE+" ).arg( i ),  QString ( "720x480" ) );
		}
		else	{	// The image button should jump to the MainMenu  jump+-+vmgm+-+
			qsAction =  QString  ( "jump+-+vmgm+-+" );
			m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_IMOV_TYPE+"  ).arg ( i ), qsTypeImov );
			m_qsXMLDVDMenu.replace (QString ("+DROP_ZONE_%1_OBJECT_TYPE+").arg ( i ), qsType );
		}
		if ( ! bDropToImage && pDND ? pDND->bImageButton : false )
			fileInfo.setFile ( pDropZone->qsImagePreview );

		m_qsXMLDVDMenu.replace ( QString ( "+DROP_ZONE_%1_FILE_NAME+"  ).arg ( i ), fileInfo.absFilePath ( ) );
		m_qsXMLDVDMenu.replace ( QString ( "+DROP_ZONE_%1_ACTION+"     ).arg ( i ), qsAction );
	}
	// In case we missed one ...
	m_qsXMLDVDMenu.replace ( QString ("+DROP_ZONE_SOURCE_ENTRY+"), qsEntryName );
	// Here we remove the PlayMe which is empty ( with or without CR )
	m_qsXMLDVDMenu.remove  ( QString ( "<PlayMe></PlayMe>\n" ) );
	m_qsXMLDVDMenu.remove  ( QString (  "<PlayMe></PlayMe>"  ) );

	if ( listAddMovies.count ( ) )
		Global::pApp->addMovieList (listAddMovies, &qsEntryName);

	// Lastly we replace <MenuSound> with a real deal 
	handleMenuAudio ( );

	QDomDocument domDoc;
	int iRow, iCol;
	QString qsError;

	iRow = iCol = 0;
	domDoc.setContent (m_qsXMLDVDMenu, true, &qsError, &iRow, &iCol);
	//printf ("\n\n%s\n\n", (const char *)m_qsXMLDVDMenu);
	QDomElement  menuElement = domDoc.documentElement();

	float fLoadVersion = m_qsTemplateVersion.toFloat ( );
	// if the menu exist we take this one over
	DVDMenu *pDVDMenu  = Global::pApp->getSubMenuByName ( m_pComboMenu->currentText ( ) );
	if ( pDVDMenu )	{
		qsMenuName = m_pComboMenu->currentText ( );
		pDVDMenu->clear ( );
		pDVDMenu->readProjectFile ( menuElement, fLoadVersion );
		pDVDMenu->getInterface ( )->iTitleset  = -1;
		pDVDMenu->getInterface ( )->iMenu      = -1;
		pDVDMenu->getInterface ( )->qsMenuName = qsMenuName;
		pDVDMenu->setTabLabel  ( qsMenuName );
		pDVDMenu->updateDVDMenu( );
	}
	else	{ // Otherwise we will create a new menu.
		pDVDMenu   = new DVDMenu ( Global::pApp );
		qsMenuName = Global::pApp->getUniqueMenuTitle ( m_pComboMenu->currentText ( ), 0 );
		pDVDMenu->readProjectFile ( menuElement, fLoadVersion );
		pDVDMenu->getInterface    ( )->iTitleset  = -1;
		pDVDMenu->getInterface    ( )->iMenu      = -1;
		pDVDMenu->getInterface    ( )->qsMenuName = qsMenuName;
		pDVDMenu->setTabLabel     ( qsMenuName );
		pDVDMenu->updateDVDMenu   ( );
		Global::pApp->addDVDMenu  ( pDVDMenu );
	}
	Global::qsCurrentPath = qsCurrentPath;

	Global::pApp->slotAutosave ( );
	Global::pApp->slotUpdateStructure ( );
	// Here we have to create the SoourceFileEntry for the DVDAuthorObject
	// Note, the SourceFileEntry holds N SourceFileInfo's
	refreshMovieButtons ( pDVDMenu );
	QWizard::accept();
	QTimer::singleShot (10, Global::pApp, SLOT ( slotDeleteTemplateWizard ( ) ) );
	myCursor = QCursor(QCursor::ArrowCursor);
	setCursor(myCursor);
}

void TemplateWizard::refreshMovieButtons ( DVDMenu *pDVDMenu )
{
  // This function will get the right screenshot for those buttons that were 
  // created from the Media pool (Left side) and have a thumbnail which is
  // NOT the first frame.

  uint t, i;
  MenuObject     *pMenuObject     = NULL;
  MovieObject    *pMovieObject    = NULL;
  ButtonObject   *pButtonObject   = NULL;
  SourceFileInfo *pSourceFileInfo = NULL;
  QValueList<ButtonObject *> listOfButtons;
  if ( pDVDMenu ) {
    listOfButtons = pDVDMenu->getButtons ( );
    for ( t=0; t<listOfButtons.count ( ); t++ ) {
      pButtonObject = listOfButtons[t];
      pSourceFileInfo = pButtonObject->sourceFileInfo ( );
      if ( pSourceFileInfo && pSourceFileInfo->iMSecPreview > 0 ) {
	for ( i=0; i<pButtonObject->getNormalCount ( ); i++ ) {
	  pMenuObject = pButtonObject->getNormal ( i );
	  if ( pMenuObject && pMenuObject->objectType ( ) == QString ( MOVIE_OBJECT ) ) {
	    pMovieObject = (MovieObject *)pMenuObject;
	    if ( pMovieObject->msecPreview   ( ) != pSourceFileInfo->iMSecPreview ) {
	      pMovieObject->setMSecPreview   ( pSourceFileInfo->iMSecPreview );
	      MediaCreator::unregisterFromMediaScanner ( pMovieObject );
	      MediaCreator::registerWithMediaScanner   ( pMovieObject, pMovieObject->fileName ( ), pMovieObject->previewImage ( ), pSourceFileInfo->iMSecPreview );
	    }
	  }
	}
      }
    }
  }
}

void TemplateWizard::adjustPixmapHeight ( QPixmap *pPixmap, QString &qsButtonXml )
{
  if ( ( ! pPixmap ) || ( qsButtonXml.length ( ) < 1 ) )
    return;
  // This function will filter the MenuObject Height attribute out of the ButtonXml
  // and replace it with the properly calculated Height for the dropped in Image/Movie.
  QRegExp rx, rx1;
  QString qsPattern,  qsMenuObjectXml, qsHeight;
  int iPos, iHeight = (int)((float)pPixmap->height ( ) / m_fScale + 0.5 );
  if ( iHeight < 1 )
    return;

  //printf ( "\n\n%s\n----------------\n", qsButtonXml.ascii ( ) );
  qsHeight = QString ( "Height=\"%1\"" ).arg ( iHeight );

  qsPattern = QString ( "MenuObject[^>]*>.*</MenuObject>" );
  rx.setPattern  ( qsPattern );
  rx1.setPattern ( "Height=\".*\"" );
  // A button usually has three objects
  if ( rx.search ( qsButtonXml ) > -1 ) {
    rx.setMinimal  ( true );
    rx1.setMinimal ( true );
    iPos = 0;
    while ( iPos >= 0 ) {
      iPos = rx.search ( qsButtonXml, iPos );
      if ( iPos > -1 ) {
	qsMenuObjectXml = rx.cap ( 0 );
	//printf ( "--------------------------\n%s\n\n", qsMenuObjectXml.ascii ( ) );
	qsMenuObjectXml.replace ( rx1, qsHeight );
	iPos += rx.matchedLength ( );
	qsButtonXml.replace ( rx.cap ( 0 ), qsMenuObjectXml );
      }
    }
  }
  //printf ( "--------------------------\n%s\n\n", qsButtonXml.ascii ( ) );
}

void TemplateWizard::handleMenuAudio ( )
{
  int iPos;
  QRegExp rx;
  QString qsMenuSound, qsSoundFile;
  QStringList listSoundFiles;

  rx.setPattern ( "<MenuSound>.*</MenuSound>" );
  if ( rx.search ( m_qsXMLDVDMenu ) > -1 ) {
    rx.setMinimal ( true );

    iPos = 0;
    while ( iPos >= 0 ) {
      iPos = rx.search ( m_qsXMLDVDMenu, iPos );
      if ( iPos > -1 ) {
	qsSoundFile = rx.cap ( 0 );  // get the full ImageObject - Tag 
	qsSoundFile = qsSoundFile.remove  (  "<MenuSound>" );
	qsSoundFile = qsSoundFile.remove  ( "</MenuSound>" );
	listSoundFiles.append ( qsSoundFile );
	iPos += rx.matchedLength ( );
      }
    }

    if ( listSoundFiles.count () > 0 ) {
      // Okay, we add the sound source
      Global::pApp->checkForNewProject ( );
      Global::pApp->addSound ( listSoundFiles );
      // And the created SourceFileEntry will be the last in the list.
      SourceFileEntry *pEntry = Global::pApp->sourceFileEntry ( Global::pApp->sourceFileCount ( ) - 1 );
      if ( pEntry && pEntry->bSoundSource ) {
	QString qsEntryName = pEntry->qsDisplayName;
	qsEntryName = qsEntryName.replace ( "<", "&lt;" );
	qsEntryName = qsEntryName.replace ( ">", "&gt;" );
	qsMenuSound = "   <MenuSound>" + qsEntryName + "</MenuSound>";
      }
    }
  }
  rx.setMinimal ( false );
  // Finally, we replace the entry with one that the DVDMenu can chew on.
  m_qsXMLDVDMenu.replace ( rx, qsMenuSound );
}
