/****************************************************************************
** qdvdauthor.h file.
**
** This file handles the user input to generate a DVD menu.
** Please note that this is work in progress and depends also oin the
** developement of dvdauthor, which is at the moment in version 0.67.
** Future versions of dvdauthort might need changes to this file.
**
*****************************************************************************/
#include <iostream>
#include <sys/stat.h>

#include <qsignalmapper.h>
#include <qstylefactory.h>
#include <qapplication.h>
#include <qprogressbar.h>
#include <qinputdialog.h>
#include <qtranslator.h>
#include <qfiledialog.h>
#include <qtextcodec.h>
#include <qpopupmenu.h>
#include <qcombobox.h>
#include <qlistview.h>
#include <qlineedit.h>
#include <qtextedit.h>
#include <qpainter.h>
#include <qlistbox.h>
#include <qcursor.h>
#include <qtimer.h>
#include <qframe.h>
#include <qfile.h>
#include <qdir.h>

// Include the generated config files ...
#include "CONFIG.h"

#include "global.h"
#include "utils.h"
#include "sourcefileentry.h"
#include "uidialogabout.h"
#include "uinewwizard.h"
#include "templatewizard.h"
#include "dialogtemp.h"
#include "uidialogrenderpreview.h"
#include "messagebox.h"
#include "dialogsetup.h"
#include "dialogslide.h"
#include "qdvdauthor.h"
#include "dialogexecute.h"
#include "buttonobject.h"
#include "movieobject.h"
#include "colortoolbar.h"
#include "sourcetoolbar.h"
#include "structuretoolbar.h"
#include "dvdmenu.h"
#include "xml_dvd.h"
#include "xml_dvdauthor.h"
#include "qdvdauthorinit.h"
#include "undobuffer.h"
#include "dvdmenuundoobject.h"
#include "menupreview.h"
#include "qplayer/mediacreator.h"
#include "qrender/startmenurender.h"
#include "importkino.h"
#include "importdvdauthor.h"
#include "exportdvdauthor.h"
#include "subtitlesgui.h"
#include "templatedownload.h"
#include "dialogconvert.h"

#define TEMP_SUBTITLES_COLOR0 0x00FEFFFE
#define TEMP_SUBTITLES_COLOR1 0xFFFFFFFF
#define TEMP_SUBTITLES_COLOR2 0xFFFFFFFE
#define TEMP_SUBTITLES_COLOR3 0xFFFFFEFF

QDVDAuthor::QDVDAuthor ()
{
        Utils theUtils;
	// Init the variables
	m_bAutosaving          = false;
	m_bModified            = false;
	m_pVMGMenu             = NULL;
	m_pTranslator          = NULL;
	m_pLanguagePopup       = NULL;
	m_pStylesPopup         = NULL;
	m_pTimerAutosave       = NULL;
	m_pDialogExecute       = NULL;
	m_pTemplateWizard      = NULL;
	m_pSubtitlesGui        = NULL;
	m_iAutosave            = 60;	// autosave every minute ...
	m_iMaxHistoryFiles     = 10;
	m_qsStyle              = theUtils.currentStyleName ( ); //QString ("Default");

	// Next we load init files and init the callbacks and GUI parts.
	initMe();

	// And disabling the Undo/Redo/Cut/Copy/Paste - option because nothing is selected and undo is empty
	editUndoAction->setEnabled(false);
	editRedoAction->setEnabled(false);
	editCutAction->setEnabled(false);
	editCopyAction->setEnabled(false);
	editPasteAction->setEnabled(false);
}

QDVDAuthor::~QDVDAuthor ()
{
	uint t;
	SaveIni ();

	// This might not be needed sinc e the destructor of the Widget takes care of this ... 
	delete m_pSourceToolbar;
	delete m_pStructureToolbar;
	for (t=0;t<m_listToolsPaths.count();t++)
		delete m_listToolsPaths[t];
	for (t=0;t<m_listHistoryPix.count();t++)
		delete m_listHistoryPix[t];
	m_iAutosave = 0;
	setAutosave ();	// Note : must be done AFTER calling SaveIni () ...

	// Just for good measure ...
	m_listToolsPaths.clear();
}

void QDVDAuthor::initMe()
{
	setDockMenuEnabled  (false);
	// Manually create the MenuHistory popup - menu.
	m_pMenuHistory = new QPopupMenu( this );
	// we want to insert the MenuHistory after the second menuentry (Open Project)
	fileMenu->insertItem( fileOpenRecentAction->iconSet(), tr( "Open &Recent" ), m_pMenuHistory , -1, 2);
	fileOpenRecent_Action->addTo( m_pMenuHistory );
	m_pProgressSize->setTotalSteps ( 1000 );

	LoadIni          ( );
	initLanguages    ( );
	initStyles       ( );
//	initSubtitlesTab ( );
	// Next we start the timer to delete all temp file older Than ...
	if (Global::iDeleteTempOlderThan > -1)
		QTimer::singleShot (30000, this, SLOT(slotDeleteTempOlderThan ()));
	
	// Here we create the Structure, and the SourceFile ToolBars.
	m_pSourceToolbar    = new SourceToolBar(QString("SourceToolBar"), this, this, false, "SourceToolBar");
	m_pStructureToolbar = new StructureToolBar(QString("StructureToolBar"), this, this, false, "StructureToolBar");
	m_pColorToolbar     = new ColorToolBar (QString ("ColorToolBar"), this, this, false, "ColorToolBar");

	// Here we assign the icons to the actions ...
	fileExitAction->setIconSet    ( QIconSet( QPixmap::fromMimeSource( "exit.png" ) ) );
	fileNewAction->setIconSet     ( QIconSet( QPixmap::fromMimeSource( "filenew" ) ) );
	fileOpenAction->setIconSet    ( QIconSet( QPixmap::fromMimeSource( "fileopen" ) ) );
	fileSaveAction->setIconSet    ( QIconSet( QPixmap::fromMimeSource( "filesave" ) ) );
	fileSaveAsAction->setIconSet  ( QIconSet( QPixmap::fromMimeSource( "filesaveas" ) ) );
	filePrintAction->setIconSet   ( QIconSet( QPixmap::fromMimeSource( "print" ) ) );
	editUndoAction->setIconSet    ( QIconSet( QPixmap::fromMimeSource( "undo" ) ) );
	editRedoAction->setIconSet    ( QIconSet( QPixmap::fromMimeSource( "redo" ) ) );
	m_pActionUndoStack->setIconSet( QIconSet( QPixmap::fromMimeSource( "text_left.png" ) ) );
	editCutAction->setIconSet     ( QIconSet( QPixmap::fromMimeSource( "editcut" ) ) );
	editCopyAction->setIconSet    ( QIconSet( QPixmap::fromMimeSource( "editcopy" ) ) );
	editPasteAction->setIconSet   ( QIconSet( QPixmap::fromMimeSource( "editpaste" ) ) );
	editFindAction->setIconSet    ( QIconSet( QPixmap::fromMimeSource( "searchfind" ) ) );

	connect (m_pTabWidgetMain,         SIGNAL(currentChanged(QWidget *)), this, SLOT(slotTabChanged(QWidget *)));
	connect (m_pActionAddMovie,        SIGNAL(activated()),   this, SLOT(slotEditAddMovie()));
	connect (m_pActionAddSlideshow,    SIGNAL(activated()),   this, SLOT(slotEditAddSlideshow()));
	connect (m_pActionAddSubMenu,      SIGNAL(activated()),   this, SLOT(slotAddSubMenu()));
	connect (m_pActionAddFiles,        SIGNAL(activated()),   this, SLOT(slotAddFiles()));
	connect (m_pActionAddDirectory,    SIGNAL(activated()),   this, SLOT(slotAddDirectory()));
	connect (m_pActionAddFromTemplate, SIGNAL(activated()),   this, SLOT(slotAddFromTemplate()));
	connect (m_pActionCreateDVD,       SIGNAL(activated()),   this, SLOT(slotCreateDVD()));
	connect (m_pActionUndoStack,       SIGNAL(activated()),   this, SLOT(slotUndoStack()));
	connect (m_pActionFeedback,        SIGNAL(activated()),   this, SLOT(slotFeedback()));
	connect (m_pActionTempSpace,       SIGNAL(activated()),   this, SLOT(slotDialogTemp()));
	connect (m_pActionTemplateDownload,SIGNAL(activated()),   this, SLOT(slotTemplateDownload()));
	connect (m_pActionImportDvdauthor, SIGNAL(activated()),   this, SLOT(slotImportDvdauthor()));
	connect (m_pActionImportKino,      SIGNAL(activated()),   this, SLOT(slotImportKino()));
	connect (m_pActionConvert,         SIGNAL(activated()),   this, SLOT(slotConvert()));
	connect (m_pMenuHistory,           SIGNAL(activated(int)),this, SLOT(slotChangeHistory(int) ) );
	connect (m_pComboSource,           SIGNAL(highlighted(const QString &)), this, SLOT(slotCreateXml(const QString &)));
}

// Called only once from main.cpp
void QDVDAuthor::postInit ( bool bSkipCheck )
{
	// next we check if the program was terminated through a crash or similar ...
	QString qsAutosaveFile = QDir::homeDirPath();
	qsAutosaveFile.append(AUTOSAVE_FILE_NAME);
	QFile autosaveFile(qsAutosaveFile);
	if ( autosaveFile.exists () && ! bSkipCheck )	{
	  setAutosave ( true ); // stop autosave
		if (MessageBox::information (this, tr("Found recover file"), 
		  tr("Attention, I found a recovery file.\n"
		     "This usually indicates that 'Q'DVD-Author crashed.\n\n"
		     "Do you want to recover the previous contents ?"), QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)	{
			fileOpen (qsAutosaveFile);
			fileSaveAs ();
		}
		else
			autosaveFile.remove ();
		setAutosave ( false ); // activate autosave
	}
	// Finally we set this one flag ... If the Dragged movie should create a ImageButton or a MovieButton.
	if (m_pVMGMenu)
		m_pVMGMenu->getMenuPreview()->setImageButton (getDragNDropContainer()->bImageButton);
}

void QDVDAuthor::polish ()
{
  Utils   theUtils;
  QString qsLang;
  int     t, iID;

  CFormMain::polish ( );
  initSubtitlesTab  ( );
  if ( Global::qsLanguage == QString ("en") )
       return;
  // Lastly we want to have the check in the right place ...
  qsLang = theUtils.iso639 ( Global::qsLanguage );
  for ( t=0;t<(int)m_pLanguagePopup->count ();t++) {
    iID = m_pLanguagePopup->idAt ( t );
    if ( qsLang == m_pLanguagePopup->text ( iID ) )
      m_pLanguagePopup->setItemChecked ( iID, true );
    else
      m_pLanguagePopup->setItemChecked ( iID, false );
  }
}

void QDVDAuthor::initSubtitlesTab ()
{
  int      t, iNrOfTabs = m_pTabWidgetMain->count ();
  for (t=0;t< iNrOfTabs;t++)
    if ( m_pTabWidgetMain->label( t ) == QString (SUBTITLES_TAB) )
      break;
  QWidget      *pWidget = m_pTabWidgetMain->page ( t );
  QGridLayout  *pLayout = new QGridLayout  ( pWidget );
  m_pSubtitlesGui       = new SubtitlesGui ( this, pWidget );
  pLayout->addWidget ( m_pSubtitlesGui, 0, 0 );
  m_pTabWidgetMain->setTabLabel (pWidget, tr("SubPictures (Subtitles)"));
  m_pTabWidgetMain->setCurrentPage ( 0 );
}

void QDVDAuthor::initLanguages()
{
	uint t;
	Utils theUtils;
	// Here we search the required directory for translation files and set the menu items 
	// under 'Tools->Languages'
	QDir theFiles (PREFIX_DIRECTORY); // e.g. /usr/local
	theFiles.cd (PREFIX_DIRECTORY"/share/qdvdauthor");
	theFiles.setNameFilter ("qdvdauthor_*.qm");
	QStringList listFiles = theFiles.entryList ();
	
	// Here we create the sub-menu for the additional languafges ...
	if (m_pLanguagePopup)
		delete m_pLanguagePopup;
	m_pLanguagePopup = new QPopupMenu ( this );
	m_pLanguagePopup->setCheckable ( true );
	tools->insertItem( toolsLanguagesAction->iconSet(), tr( "Languages" ), m_pLanguagePopup );
	QAction *pActionLanguage = new QAction (this, "languageEnglish");
	pActionLanguage->setText( "English" );
	pActionLanguage->setMenuText( "English" );
	pActionLanguage->addTo( m_pLanguagePopup );
	//	pActionLanguage->setOn ( true );

	for (t=0;t<listFiles.count();t++)	{
		// First we try to extract the language ...
		pActionLanguage = new QAction (this, QString ("language%1").arg(t));
		pActionLanguage->setText( theUtils.iso639(listFiles[t]) );
		pActionLanguage->setMenuText( theUtils.iso639(listFiles[t].mid (listFiles[t].length()-5,2)) );
		pActionLanguage->addTo( m_pLanguagePopup );
	}
	connect( m_pLanguagePopup, SIGNAL( activated(int) ), this, SLOT( slotChangeLanguage(int) ) );
}

void QDVDAuthor::slotChangeLanguage (int iID)
{
  // The first thing is to co-relate the ID to the language ...
  QString qsID ("en");	// Default = english
  QDir theFiles (PREFIX_DIRECTORY); // e.g. /usr/local
  theFiles.cd (PREFIX_DIRECTORY"/share/qdvdauthor");
  theFiles.setNameFilter ("qdvdauthor_*.qm");
  QStringList listFiles = theFiles.entryList ();
  // Now that we have the file list in the same order as they were generated, we can find the right one ...
  int iIndexOfID = m_pLanguagePopup->indexOf(iID);
  if (0 <= iIndexOfID-1)	// extract something like "de"
    qsID = listFiles[iIndexOfID-1].mid (listFiles[iIndexOfID-1].length()-5,2);
  
  for (int t=0;t<(int)m_pLanguagePopup->count();t++)
    m_pLanguagePopup->setItemChecked ( m_pLanguagePopup->idAt ( t ), ( t == iIndexOfID ) );
  
  // Here we install the language the user has chosen ...
  QTranslator *pTrans = new QTranslator( 0 );
  // Under ~/.qdvdauthor/
  QString qsLang = QString(QString (PREFIX_DIRECTORY"/share/qdvdauthor/qdvdauthor_%1.qm").arg(qsID));
  if (m_pTranslator)	{
    qApp->removeTranslator ( m_pTranslator );
    delete m_pTranslator;
    m_pTranslator = NULL;	// Just for consistency ...
  }
  pTrans->load( qsLang );
  m_pTranslator = pTrans;
  qApp->installTranslator( m_pTranslator );
  Global::qsLanguage = qsID;
  languageChange();
}

void QDVDAuthor::initStyles ()
{
	// First we create the popup menu ...
	if (m_pStylesPopup)
		delete m_pStylesPopup;
	m_pStylesPopup = new QPopupMenu( this );
	m_pStylesPopup->setCheckable( TRUE );
	tools->insertItem( tr("&Style") , m_pStylesPopup );

	// Okay we expect some action here
	QActionGroup *ag = new QActionGroup( this, 0 );
	ag->setExclusive( TRUE );
	// Here we map the emmited signal to a defined sender, so the receiving slot knows where 
	// the signal came from
	QSignalMapper *styleMapper = new QSignalMapper( this );
	connect( styleMapper, SIGNAL( mapped( const QString& ) ), this, SLOT( slotChangeStyle( const QString& ) ) );
	// Here we retrieve the list of available styles.
	QStringList list = QStyleFactory::keys();
	list.sort();
	// In order to generate the accel-keys we need to ensure the uniqueness of each key ...
	QDict<int> stylesDict( 17, FALSE );
	for ( QStringList::Iterator it = list.begin(); it != list.end(); ++it ) {
		QString styleStr = *it;
		QString styleAccel = styleStr;
		if ( stylesDict[styleAccel.left(1)] ) {
			for ( uint i = 0; i < styleAccel.length(); i++ ) {
				if ( !stylesDict[styleAccel.mid( i, 1 )] ) {
					stylesDict.insert(styleAccel.mid( i, 1 ), (const int *)1);
					styleAccel = styleAccel.insert( i, '&' );
					break;
				}
			}
		} 
		else	{
			stylesDict.insert(styleAccel.left(1), (const int *)1);
			styleAccel = "&"+styleAccel;
		}
		QAction *a = new QAction( styleStr, QIconSet(), styleAccel, 0, ag, 0, ag->isExclusive() );
		connect( a, SIGNAL( activated() ), styleMapper, SLOT(map()) );
		styleMapper->setMapping( a, a->text() );
	}
	ag->addTo(m_pStylesPopup);
}

void QDVDAuthor::slotChangeStyle (const QString &qsStyle)
{
	m_qsStyle = qsStyle;
	qApp->setStyle(qsStyle);
	if(qsStyle == "Platinum") {
		QPalette p( QColor( 239, 239, 239 ) );
		qApp->setPalette( p, TRUE );
		qApp->setFont( QApplication::font(), TRUE );
	} 
	else if(qsStyle == "Windows")
	    qApp->setFont( QApplication::font(), TRUE );
	else if(qsStyle == "CDE") {
		QPalette p( QColor( 75, 123, 130 ) );
		p.setColor( QPalette::Active,   QColorGroup::Base, QColor( 55, 77, 78 ) );
		p.setColor( QPalette::Inactive, QColorGroup::Base, QColor( 55, 77, 78 ) );
		p.setColor( QPalette::Disabled, QColorGroup::Base, QColor( 55, 77, 78 ) );
		p.setColor( QPalette::Active,   QColorGroup::Highlight, Qt::white );
		p.setColor( QPalette::Active,   QColorGroup::HighlightedText, QColor( 55, 77, 78 ) );
		p.setColor( QPalette::Inactive, QColorGroup::Highlight, Qt::white );
		p.setColor( QPalette::Inactive, QColorGroup::HighlightedText, QColor( 55, 77, 78 ) );
		p.setColor( QPalette::Disabled, QColorGroup::Highlight, Qt::white );
		p.setColor( QPalette::Disabled, QColorGroup::HighlightedText, QColor( 55, 77, 78 ) );
		p.setColor( QPalette::Active,   QColorGroup::Foreground, Qt::white );
		p.setColor( QPalette::Active,   QColorGroup::Text, Qt::white );
		p.setColor( QPalette::Active,   QColorGroup::ButtonText, Qt::white );
		p.setColor( QPalette::Inactive, QColorGroup::Foreground, Qt::white );
		p.setColor( QPalette::Inactive, QColorGroup::Text, Qt::white );
		p.setColor( QPalette::Inactive, QColorGroup::ButtonText, Qt::white );
		p.setColor( QPalette::Disabled, QColorGroup::Foreground, Qt::lightGray );
		p.setColor( QPalette::Disabled, QColorGroup::Text, Qt::lightGray );
		p.setColor( QPalette::Disabled, QColorGroup::ButtonText, Qt::lightGray );
		qApp->setPalette( p, TRUE );
		qApp->setFont( QFont( "times", QApplication::font().pointSize() ), TRUE );
	} 
	else if(qsStyle == "Motif" || qsStyle == "MotifPlus") {
		QPalette p( QColor( 192, 192, 192 ) );
		qApp->setPalette( p, TRUE );
		qApp->setFont( QApplication::font(), TRUE );
	}
}

QString QDVDAuthor::getUniqueMenuTitle (QString qsInput, int iNumber, DVDMenu *pDVDMenu)
{
	uint t;
	QString qsTitle, qsTemp;

	if (iNumber == 0)
		qsTitle = qsInput;
	else
		qsTitle = QString ("%1_%2").arg(iNumber).arg(qsInput);

	for (t=0;t<m_listDVDMenus.count();t++)	{
		if (m_listDVDMenus[t] == pDVDMenu)
			continue;
		if (qsTitle == m_listDVDMenus[t]->getInterface()->qsMenuName)	{
			return getUniqueMenuTitle (qsInput, iNumber + 1, pDVDMenu);
		}
	}
	return qsTitle;
}

void QDVDAuthor::addDVDMenu (DVDMenu *pDVDMenu, bool bVMGM)
{
	QString qsTitle;
	
	// This check ensures we add only unique Tab names.
	qsTitle = getUniqueMenuTitle (pDVDMenu->getInterface()->qsMenuName, 0, pDVDMenu);
	if (qsTitle != pDVDMenu->getInterface()->qsMenuName)	{
		pDVDMenu->getInterface()->qsMenuName = qsTitle;
		//		pDVDMenu->setTabLabel (qsTitle);
	}
	pDVDMenu->setTabLabel (qsTitle);

	if (bVMGM)
		m_pVMGMenu = pDVDMenu;
	else
		m_listDVDMenus.append(pDVDMenu);

	m_pColorToolbar->setDVDMenu (pDVDMenu);
	pDVDMenu->getMenuPreview()->setImageButton(m_dragNDropContainer.bImageButton);
	connect (this, SIGNAL(signalVisibleRegion(bool)), pDVDMenu, SLOT(slotVisibleRegion (bool)));
	pDVDMenu->slotVisibleRegion(m_bVisibleRegion);
}

// The foillowing functions are only used in DVDMenu::slotRequestSourceFiles ()
int QDVDAuthor::getFreeSourceSlot()
{
	return (int)m_pSourceToolbar->getFreeSourceSlot();
}

void QDVDAuthor::addMovieList (QStringList &listMovies, QString *pTitle)
{
	m_pSourceToolbar->addMovieList (listMovies, pTitle);
}

int QDVDAuthor::sourceFileCount()
{
	return (int)m_pSourceToolbar->sourceFileCount();
}

SourceFileEntry *QDVDAuthor::sourceFileEntry(uint iEntryNumber)
{
	return m_pSourceToolbar->sourceFileEntry(iEntryNumber);
}

SourceFileEntry *QDVDAuthor::getSourceEntryByDisplayName(QString &qsDisplayName)
{
	int t;
	for (t=0;t<sourceFileCount();t++)	{
		if (sourceFileEntry(t)->qsDisplayName == qsDisplayName)
			return sourceFileEntry(t);
	}
	return NULL;
}

void QDVDAuthor::updateSourceFileInfo ( SourceFileInfo *pInfo )
{
  m_pSourceToolbar->updateListViewItem ( pInfo );
}

void QDVDAuthor::addSound (QStringList &listSoundFiles)
{
	if (!checkForNewProject ())
		return;
	m_pSourceToolbar->addSound(listSoundFiles);
}

void QDVDAuthor::setColor (uint iWhichColor, QColor theColor)
{
	m_pColorToolbar->setColor(iWhichColor, theColor);
}

void QDVDAuthor::removeSourceFileEntry (SourceFileEntry *pSourceFileEntry)
{
	// This function is called from an UndoObject (hint: add_sound)
	m_pSourceToolbar->removeEntry(pSourceFileEntry);
}

void QDVDAuthor::appendSourceFileEntry (SourceFileEntry *pSourceFileEntry)
{
	// This function is called from an UndoObject (hint: add_sound)
	m_pSourceToolbar->appendSourceFileEntry(pSourceFileEntry);
}

void QDVDAuthor::removedSourceEntry (SourceFileEntry *pEntry)
{
	// This function is called after a SourceFileEntry has been deleted from the
	// SourceToolBar - class.
	// We should remove all subsequent dependencies (buttons connected with movie files, or background sound files ...)
	uint t;
	QFileInfo fileInfo;
	QString qsFileName;

	m_pVMGMenu->removeSourceEntry(pEntry->qsDisplayName);
	for (t=0;t<m_listDVDMenus.count();t++)
		m_listDVDMenus[t]->removeSourceEntry(pEntry->qsDisplayName);
}

bool QDVDAuthor::isSourceEntryUsed(QString &qsInquireEntry)
{
	uint t;
	// This function is called when the user wants to delete a SourceFileEntry
	// it returns true if the entry is in use.
	if (m_pVMGMenu->isSourceEntryUsed (qsInquireEntry))
		return true;
	// next we step through all sub-menus ...
	for (t=0;t<m_listDVDMenus.count();t++)	{
		if (m_listDVDMenus[t]->isSourceEntryUsed (qsInquireEntry))
			return true;
	}
	return false;
}

void QDVDAuthor::replaceSourceDisplayName (QString &qsOriginalDisplayName, QString &qsNewDisplayName)
{
	// This function is called when the user changed the DisplayName of a SourceFileEntry
	// DialogMovie::accept()->SourceToolBar::slotEditMovie->QDVDAuthor::replaceSourceDisplayName()
	uint t;
	
	m_pVMGMenu->replaceSourceDisplayName (qsOriginalDisplayName, qsNewDisplayName);
	for (t=0;t<m_listDVDMenus.count();t++)	
		m_listDVDMenus[t]->replaceSourceDisplayName (qsOriginalDisplayName, qsNewDisplayName);

	slotUpdateStructure ();
}

QValueList<DVDMenu *> &QDVDAuthor::getSubMenus( )
{
	return m_listDVDMenus;
}

MediaInfo *QDVDAuthor::getMediaInfo ()
{
	if (!m_pSourceToolbar)
		return NULL;
	return m_pSourceToolbar->getMediaInfo ();
}

DragNDropContainer *QDVDAuthor::getDragNDropContainer()
{
	return &m_dragNDropContainer;
}

void QDVDAuthor::slotUpdateStructure ()
{
	int t;
	QListViewItem *pMainItem;

	pMainItem = m_pStructureToolbar->clean ( true );

	for (t=(int)m_listDVDMenus.count()-1;t>=0;t--)
		m_listDVDMenus[t]->createStructure (pMainItem);
	if (m_pVMGMenu)
		m_pVMGMenu->createStructure (pMainItem);
	slotUpdateMenuBar();
}

void QDVDAuthor::slotUndoStack ()
{
	// This function will call the Undo - stack GUI of the current menu
	DVDMenu *pMenu = getCurrentSubMenu ();
	if (!pMenu)
		return;
	pMenu->showUndoStack ();
}

void QDVDAuthor::slotRenameCurrentSubMenu ()
{
	// Here we remove the current SubMenu ...
  QString qsSubMenuName, qsNewName;
	bool bOkay;
	DVDMenu *pMenu = getCurrentSubMenu ();
	if (pMenu == m_pVMGMenu)	{
		MessageBox::information (NULL, tr ("Can not change VMGM name"),
		tr ("I can not change the name of the VMGM\n"), QMessageBox::Ok);
		return;
	}
	if ( pMenu )  
	  qsNewName = pMenu->getInterface()->qsMenuName;
	qsSubMenuName = m_pTabWidgetMain->tabLabel(m_pTabWidgetMain->currentPage());
	qsNewName = QInputDialog::getText (tr("Sub Menu Name"), tr("Please give the new SubMenu Name"),
			QLineEdit::Normal, qsNewName, &bOkay, this );
	if (!bOkay)
		return;
	if (qsNewName.isEmpty())
		return;
	if (pMenu)	{
		pMenu->getInterface()->qsMenuName = qsNewName;
		m_pTabWidgetMain->setTabLabel (m_pTabWidgetMain->currentPage(), qsNewName);
	}
	slotUpdateStructure();
}

void QDVDAuthor::slotCloneCurrentSubMenu ()
{
  // Here we remove the current SubMenu ...
  DVDMenu *pMenu = getCurrentSubMenu ( );
  pMenu  = pMenu->clone ( );
  if ( pMenu->getInterface ( )->qsMenuName == QString ( VMGM_LABEL ) ) {
    QString qsNewTitle = tr ( "Cloned VMGM" );
    pMenu->getInterface ( )->qsMenuName = qsNewTitle;
    m_pTabWidgetMain->setTabLabel  ( m_pTabWidgetMain->currentPage ( ), qsNewTitle );
  }

  addDVDMenu ( pMenu );
  slotUpdateStructure();
}

void QDVDAuthor::slotRemoveCurrentSubMenu ()
{
	// Here we remove the current SubMenu ...
	QString qsSubMenuName;
	qsSubMenuName = m_pTabWidgetMain->tabLabel(m_pTabWidgetMain->currentPage());
	DVDMenu *pMenu = getCurrentSubMenu ();
	if (pMenu == m_pVMGMenu)	{
		MessageBox::information (NULL, tr ("Can not remove VMGM"),
		tr ("I can not remove the main VMGM\n"), QMessageBox::Ok);
		return;
	}
	int iReturn = MessageBox::warning (NULL, tr ("Warning, deleting Sub Menu"),
		tr ("Are you sure you want to remove this sub-menu ?\n"
		    "All data will be lost permanently."), QMessageBox::Yes|QMessageBox::Default,  QMessageBox::No|QMessageBox::Escape);
		if (iReturn == QMessageBox::Yes)
			m_pTabWidgetMain->removePage(m_pTabWidgetMain->currentPage());

	m_listDVDMenus.remove (pMenu);
	delete pMenu;
	slotUpdateStructure();
}


void QDVDAuthor::slotDeleteTempOlderThan ()
{
	// This function will check if there is outdated Temp data which ought to get inhilated.
	if (Global::iDeleteTempOlderThan < 0)
		return;

	uint t;
	Utils theUtils;
	QStringList listToBeDeleted;
	QStringList listOfProjects = theUtils.getProjectsFromTempPath();
	QString qsProjectTemp;
	QFileInfo fileInfo;
	QDateTime currentTime = QDateTime::currentDateTime();
	QDateTime modificationTime;

	for (t=0;t<listOfProjects.count();t++)	{
		qsProjectTemp = Global::qsTempPath + QString ("/") + listOfProjects[t];

		fileInfo.setFile (qsProjectTemp + QString ("/background.jpg"));
		if ( ! fileInfo.exists() )
			fileInfo.setFile (qsProjectTemp + "/" + QString (VMGM_LABEL"/background.jpg"));
		if ( ! fileInfo.exists() )
			continue;
		modificationTime = fileInfo.lastModified();
		if (modificationTime.secsTo (currentTime) > Global::iDeleteTempOlderThan * 60*60*24)
			listToBeDeleted.append (qsProjectTemp);
	}	
	
	// First we check if there was some old data found ...
	if (listToBeDeleted.count () > 0)	{
		// Next we ask the user if he wants to delete the data.
		if (MessageBox::warning (NULL, tr("Deleting temp data."), tr("Attention, I found some temp data which exceeds the timeframe\n") +
			tr ("you have set in the SetupDialog (Tools->Setup ...)\n\n") +
			listToBeDeleted.join ("\n") +
			tr ("\n\nDo you want to delete the temp data ?"), 
					 QMessageBox::Yes|QMessageBox::Default, QMessageBox::No|QMessageBox::Escape) == QMessageBox::Yes)	{
			for (t=0;t<listToBeDeleted.count ();t++)
				theUtils.recRmdir (listToBeDeleted[t], "draggedImage");
		}
	}
}

void QDVDAuthor::slotTabChanged (QWidget *pWidget)
{
  // Here we  need to take care of two things
  // 1) The Tab has changed to a SubMenu (including vmgm)
  // 2) the tab has changed into the XML tab -=> Create XML output
  QString qsTabLabel = m_pTabWidgetMain->tabLabel(pWidget);
  int t, i;
  if (qsTabLabel == QString(VMGM_LABEL))	{
    DVDMenu *pMenu = getCurrentSubMenu ();
    if (pMenu)
      m_pColorToolbar->setDVDMenu (pMenu);
    slotUpdateMenuBar ();
  }
  // The last tab is the one to dispaly the XML code
  else if (qsTabLabel == m_pTabWidgetMain->label(m_pTabWidgetMain->count()-1))	{
    m_pComboSource->clear();
    m_pComboSource->insertItem ( QString ("") );
    m_pComboSource->insertItem ( DVDAUTHOR_XML );
    m_pComboSource->insertItem ( m_pVMGMenu->name() );
    for (t=0;t<sourceFileCount();t++) {
      SourceFileEntry *pEntry = sourceFileEntry ( t );
      for (i=0;i< (int) pEntry->listFileInfos.count(); i++) {
	SourceFileInfo *pInfo = pEntry->listFileInfos[i];
	if ( pInfo && pInfo->pSubtitles ) {
	  QFileInfo fileInfo ( pInfo->qsFileName );
	  QString qsSpumuxFile = QString ("%1.xml").arg ( fileInfo.baseName () );
	  m_pComboSource->insertItem ( qsSpumuxFile );
	}
      }
    }
    
    m_pTextEditXml->clear();
    for (uint t=0;t<m_listDVDMenus.count();t++)
      m_pComboSource->insertItem(m_listDVDMenus[t]->name());
  }
  else	{
    DVDMenu *pMenu = getCurrentSubMenu ();
    if (pMenu)
      m_pColorToolbar->setDVDMenu (pMenu);
    slotUpdateMenuBar ();
  }
}

void QDVDAuthor::slotAboutToShowMenu ( )
{
  DVDMenu    *pCurrentMenu;
  VMGMenu    *pVMGM = (VMGMenu *)getVMGMenu ( );
  QPopupMenu *pMenu = pVMGM->getPopupMenu   ( );
  pCurrentMenu = getCurrentSubMenu ( );
  if ( ! pCurrentMenu )
    return;

  // this enables / disables [Store as Template ...]
  if ( pCurrentMenu->getInterface ()->qsBackgroundFileName.isEmpty () )
    pMenu->setItemEnabled ( pMenu->idAt ( 5 ), false );
  else
    pMenu->setItemEnabled ( pMenu->idAt ( 5 ), true );

  Utils theUtil;
  int  iFormat = theUtil.getFormat ( pCurrentMenu->getInterface ( )->iWidth, pCurrentMenu->getInterface ( )->iHeight );
  bool bPal, bNtsc;
  bPal = bNtsc = true;
  if ( iFormat >= FORMAT_PAL1 )
    bNtsc = false;
  if ( iFormat <= FORMAT_NTSC4 )
    bPal = false;
  if ( iFormat == FORMAT_NONE )
    bNtsc = false;

  pMenu->setItemVisible ( pMenu->idAt ( 2 ), bNtsc ); // [Convert To PAL]
  pMenu->setItemVisible ( pMenu->idAt ( 3 ), bPal  ); // [Convert To NTSC]
}

void QDVDAuthor::slotConvert ( ) 
{
  // This function will allow the user to convert a whole project into 
  // one format.
  DialogConvert *pConverter = new DialogConvert ( this );
  pConverter->exec ( );
}

void QDVDAuthor::slotConvertCurrentMenu ( bool bPal ) 
{
  DVDMenu *pDVDMenu = getCurrentSubMenu ( );
  if ( ! pDVDMenu )
    return;

  QCursor myCursor (QCursor::WaitCursor);
  QApplication::setOverrideCursor (myCursor);

  DialogConvert converter ( this );
  converter.convert ( pDVDMenu, bPal );

  QApplication::restoreOverrideCursor ();
}

void QDVDAuthor::slotImportKino ()
{
  // import Kino's smil format. This will generate only a single
  // SourceFileEntry with a list of all SourceFileInfo - bjects.
  Import::Kino theImporter ( this );

  if ( theImporter.import () ) {
    appendSourceFileEntry ( theImporter.getEntry () );
    slotUpdateStructure();
  }
}

void QDVDAuthor::slotImportDvdauthor ()
{
  Import::DVDAuthor theImporter ( this );
  // this is the main function to start the import filter.
  if ( theImporter.import () ) 
    importDvdauthor ( &theImporter );
}

void QDVDAuthor::importDvdauthor ( void *pVoid )
{
  uint t;
  QValueList        <DVDMenu *> listOfSubMenus;
  DVDMenu                      *pDVDMenu;
  QValueList<SourceFileEntry *> listOfSourceFileEntries;
  Import::DVDAuthor *pImporter = (Import::DVDAuthor *)pVoid;

  pDVDMenu = pImporter->takeVMGMenu ();
  // We should have all required information if it return true 
  if ( ! pDVDMenu ) {
    pImporter->clear ( true );
    return;
  }

  cleanUp ();
  listOfSubMenus          = pImporter->takeDVDMenus ();
  listOfSourceFileEntries = pImporter->takeSourceFileEntries ();
  if ( pDVDMenu ) {
    DVDMenu *pVMGMenu = m_pVMGMenu;
    addDVDMenu ( pDVDMenu, true );
    delete pVMGMenu;
  }
  pDVDMenu->initBackground ( pDVDMenu->getInterface()->qsMovieFileName );

  for (t=0;t<listOfSubMenus.count(); t++) {
    pDVDMenu = listOfSubMenus[t];
    if ( pDVDMenu ) {
      addDVDMenu ( pDVDMenu );
      pDVDMenu->initBackground ( pDVDMenu->getInterface()->qsMovieFileName );
    }
  }

  for (t=0;t<listOfSourceFileEntries.count();t++)
    appendSourceFileEntry ( listOfSourceFileEntries[t] );
  slotUpdateStructure();
}

void QDVDAuthor::slotUpdateMenuBar ()
{
  // Standard is to set undo / redo to false
  DVDMenu *pMenu = getCurrentSubMenu ( );
  editUndoAction->setEnabled(false);
  editRedoAction->setEnabled(false);
  if (!pMenu)
    return;
  
  // Then we check if there is something in the buffer.
  int iUndoCount = pMenu->getUndoBuffer()->count();
  if (iUndoCount > 0)
    editUndoAction->setEnabled(true);
  iUndoCount = pMenu->getUndoBuffer()->countRedo();
  if (iUndoCount > 0)
    editRedoAction->setEnabled(true);
}

void QDVDAuthor::slotExportDVDAuthorXML()
{
  Export::DVDAuthor theExporter ( this );
  theExporter.exportXml ();
}

void QDVDAuthor::slotFeedback ()
{
  // First let us  make sure the temp dir exists...
  getTempFile ( QString() );
  // then let us collect some feedback data 
  QDir feedbackDir (Global::qsTempPath + QString ("/") + Global::qsProjectName + QString ("/feedback"));
  if (!feedbackDir.exists())
    feedbackDir.mkdir (feedbackDir.absPath(), TRUE);

  if (!feedbackDir.exists())	{
    MessageBox::information (NULL, tr ("Error creating directory"),
	tr ("\nCould not create direcory :\n"
	    "%1\n"
	    "Please check access rights etc.").arg(feedbackDir.absPath()), QMessageBox::Ok, QMessageBox::NoButton);
    return;
  }
  // Here we get the project file.
  slotAutosave ();
  QString qsBashName   = QString ("%1/feedback.sh").arg(Global::qsTempPath);
  QString qsBashScript = Global::qsBashString;
  qsBashScript += QString ("mkdir -p \"%1/%2/feedback\"\n").arg(Global::qsTempPath).arg(Global::qsProjectName);
  qsBashScript += QString ("cd \"%1/%2/\"\n").arg(Global::qsTempPath).arg(Global::qsProjectName);
  qsBashScript += QString ("cp ~/.qdvdauthor/*.ini \"%1/%2/feedback/\"\n").arg(Global::qsTempPath).arg(Global::qsProjectName);
  qsBashScript += QString ("cp ~/.qdvdauthor/autosave.xml \"%1/%2/feedback/\"\n").arg(Global::qsTempPath).arg(Global::qsProjectName);
  qsBashScript += QString ("cp \"%1\" \"%2/%3/feedback/\" 2> /dev/null\n").arg(Global::qsProjectFileName).arg(Global::qsTempPath).arg(Global::qsProjectName);
  qsBashScript += QString ("find . > feedback/temp_filelist\n");
  qsBashScript += QString ("find . -name \"*.xml\" -exec tar -rf feedback/xml_files.tar {} \\;\n");
  qsBashScript += QString ("find . -name \"*.txt\" -exec tar -rf feedback/txt_files.tar {} \\;\n");
  qsBashScript += QString ("tar -czf \"%1/%2/feedback.tar.gz\" feedback/*\n").arg(Global::qsTempPath).arg(Global::qsProjectName);
  qsBashScript += QString ("rm -r feedback\n");
  QFile bashFile (qsBashName);
  if ( bashFile.open( IO_WriteOnly ) ) {
    QTextStream stream( &bashFile );
    stream << qsBashScript;
    bashFile.close();
  }
  else	{
    MessageBox::information (NULL, tr ("Error creating script file"),
        tr ("\nCould not create script file :\n"
	    "%1\n"
	    "Please check access rights etc.").arg(qsBashName), QMessageBox::Ok, QMessageBox::NoButton);
    return;
  }
  // And here we grant read/write/execute permission.
  chmod ((const char *)qsBashName, S_IEXEC | S_IRUSR | S_IWRITE);
  
  // And now execute the script ...
  if ( system (qsBashName) == -1 )
	return;
  MessageBox::information (NULL, tr ("Collected Feedback Data"),
      tr ("\nWhen sending feedback, please attach the file :\n"
	  "%1/%2/feedback.tar.gz\n").arg(Global::qsTempPath).arg(Global::qsProjectName), QMessageBox::Ok, QMessageBox::NoButton);
}

void QDVDAuthor::slotEditAddMovie ()
{
	m_pSourceToolbar->slotAddMovie ();
}

void QDVDAuthor::slotEditAddSlideshow ()
{
	m_pSourceToolbar->slotAddSlideshow();
}

void QDVDAuthor::slotStructureClicked(QListViewItem *pItem)
{
	m_pVMGMenu->slotStructureClicked(pItem);
}

void QDVDAuthor::filePrint()
{
	MessageBox::warning (this, tr("Warning"), tr ("Not implemented Yet"), (int)QMessageBox::Ok, (int)QMessageBox::NoButton);
}

void QDVDAuthor::fileExit()
{
	close();
}

void QDVDAuthor::slotCalculateSize ()
{
	uint t, i, megaBytes=1024*1024;
	unsigned long iMaxDVDSize = (unsigned long) (4.3 * 1024 * 1024 * 1024); // ==> 4.3 GBytes
	unsigned long iDVDSize = 0;
	SourceFileEntry *pEntry;
	SourceFileInfo  *pInfo;
	QTime theLength, zeroTime;
	QString qsSize;
	float fPercentage;
	// This function will update the SizeSlider
	// This is the first and very basic version
	
	// Per menu I take 20 MBytes + 15 MBytes/minute
	// Per video I will calculate 8MBits/second
	QValueList<DVDMenu *> listMenus = getSubMenus ();
	for (t=0;t<listMenus.count();t++)	{
		iDVDSize += 20*megaBytes;
		iDVDSize += listMenus[t]->getInterface ()->timeDuration.second() * megaBytes / 60 * 15;
	}
	uint iSourceEntryCount = sourceFileCount();
	for (t=0;t<iSourceEntryCount;t++)	{
		pEntry = sourceFileEntry(t);
		for (i=0;i<pEntry->listFileInfos.count();i++)	{
			pInfo = pEntry->listFileInfos[i];
			if (pInfo->qsLength.isEmpty())
				continue;
			if (pInfo->qsLength.find (':') == 1)
				pInfo->qsLength = QString ('0' + pInfo->qsLength);
			theLength=QTime().fromString(pInfo->qsLength);
			// a rough estimate wo consideration of bps is 1.2Mb/sec
			iDVDSize += zeroTime.secsTo (theLength) * (long)(megaBytes*1.2); //QTime().fromString(pInfo->qsLength)) * megaBytes/2;
		}
	}

	fPercentage = (float)( (double)iDVDSize / (double)iMaxDVDSize);
	if (fPercentage > 1.0)
		fPercentage = 1.0;
	m_pProgressSize->setProgress ( (int)(fPercentage * 1000) );
	// Change color from green to red ...
	m_pLabelSize->setPaletteBackgroundColor ( QColor ((int)(fPercentage*250.0), (int)((1.0-fPercentage) * 250.0), 0) );
	if (iDVDSize > 1024*megaBytes)
		qsSize.sprintf ("%0.2f GB", (double)iDVDSize /(1024.0*megaBytes));
	else if (iDVDSize > megaBytes)
		qsSize.sprintf ("%0.2f MB", (double)iDVDSize / megaBytes);
	else if (iDVDSize > 1024)
		qsSize.sprintf ("%0.2f kB", (double)iDVDSize / 1024.0);
	else 
		qsSize.sprintf ("%d B", (int)iDVDSize);
	m_pLabelSize->setText (qsSize);
}

void QDVDAuthor::slotAddFromTemplate ()
{
	// This function will handle the template Dialog.
	if ( ! m_pTemplateWizard )	{
		m_pTemplateWizard = new TemplateWizard (this);
		m_pTemplateWizard->initMe (this);
	}
	if ( ! m_pTemplateWizard )
		return;
	// Note we use show here in order to have DragNDrop working.
	m_pTemplateWizard->showDialog ( );
}

void QDVDAuthor::slotDeleteTemplateWizard()
{
	if ( m_pTemplateWizard )
		delete m_pTemplateWizard;
	m_pTemplateWizard = NULL;
}

void QDVDAuthor::slotAddSubMenu()
{
	QString qsNewTabLabel = QString ("SubMenu %1").arg(m_listDVDMenus.count()+1);
	DVDMenu *pNewMenu = new DVDMenu(this);
	pNewMenu->getInterface()->qsMenuName = qsNewTabLabel;
	pNewMenu->getInterface()->iTitleset  = m_listDVDMenus.count() + 2;
	pNewMenu->getInterface()->iMenu      = 0;
	pNewMenu->setTabLabel(qsNewTabLabel);
	addDVDMenu(pNewMenu);
	slotUpdateStructure();
}

DVDMenu *QDVDAuthor::getVMGMenu ()
{
  return m_pVMGMenu;
}

DVDMenu *QDVDAuthor::getCurrentSubMenu ()
{
	// determines the SubMenu which is currently selected in the main Tab widget
	QString qsSubMenuName;
	if (!m_pVMGMenu)
		return NULL;
	qsSubMenuName = m_pTabWidgetMain->tabLabel(m_pTabWidgetMain->currentPage());
	return getSubMenuByName (qsSubMenuName);
}

DVDMenu *QDVDAuthor::getSubMenuByName(QString qsSubMenuName)
{
	uint t;
	if (m_pVMGMenu->getInterface()->qsMenuName == qsSubMenuName)	{
		return m_pVMGMenu;
	}
	for (t=0;t<m_listDVDMenus.count();t++)	{
		if (m_listDVDMenus[t]->getInterface()->qsMenuName == qsSubMenuName)	{
			return m_listDVDMenus[t];
		}
	}
	return NULL;
}

void QDVDAuthor::slotAddFiles()
{
  QMessageBox theMessage ("Warning", "This function is not yet implemented", QMessageBox::Information, (int)QMessageBox::Ok, (int)QMessageBox::NoButton, (int)QMessageBox::NoButton, NULL, tr("info"), false );
}

void QDVDAuthor::slotAddDirectory()
{
  QMessageBox theMessage ("Warning", "This function is not yet implemented", QMessageBox::Information, (int)QMessageBox::Ok, (int)QMessageBox::NoButton, (int)QMessageBox::NoButton, NULL, tr("info"), false );
}

void QDVDAuthor::slotGenerateMasks()
{
	int iMenuCounter = 0;
	QString qsFileName;
	QString qsHeader (tr("Generating Masks ..."));
	QString qsText (tr("Please be patient, I am generating the masks for the Menus.\n"));

	QMessageBox *pTheMessage = new QMessageBox (qsHeader, qsText, QMessageBox::Information, (int)QMessageBox::Ok, (int)QMessageBox::NoButton, (int)QMessageBox::NoButton, NULL, tr("info"), false );
	pTheMessage->show();
	pTheMessage->setText(qsText);

	DVDMenu *pMenu = m_pVMGMenu;
	while (iMenuCounter <= (int)m_listDVDMenus.count())	{
		qsFileName  = getTempFile(pMenu->name()) + QString("/") + QString(HIGHLIGHTED_NAME);
		pMenu->createMask (qsFileName, HIGHLIGHTED_MASK);
		qsFileName = getTempFile (pMenu->name()) + QString ("/") + QString(SELECTED_NAME);
		pMenu->createMask (qsFileName, SELECTED_MASK);
		qsFileName = getTempFile (pMenu->name()) + QString ("/") + QString(BACKGROUND_NAME);
		pMenu->createMask(qsFileName, BACKGROUND_IMG);
		pMenu = m_listDVDMenus[iMenuCounter++];
	}
	createMenuXml();
	delete pTheMessage;
}

void QDVDAuthor::editUndo()
{
	DVDMenu *pCurrentDVDMenu = getCurrentSubMenu ();
	if (!pCurrentDVDMenu)	{
		editUndoAction->setEnabled(false);
		editRedoAction->setEnabled(false);
		return;
	}
	DVDMenuUndoObject *pUndoObject = (DVDMenuUndoObject *)pCurrentDVDMenu->getUndoBuffer()->pop();
	if (pUndoObject)	{
		// We set the re-do option active ...
		editRedoAction->setEnabled(true);
		pUndoObject->undo (pCurrentDVDMenu);
	}
	// Check if we are at the end ...
	if (pCurrentDVDMenu->getUndoBuffer()->count() == 0)
		editUndoAction->setEnabled(false);
}

void QDVDAuthor::editRedo()
{
	DVDMenu *pCurrentDVDMenu = getCurrentSubMenu ();
	if (!pCurrentDVDMenu)	{
		editUndoAction->setEnabled(false);
		editRedoAction->setEnabled(false);
		return;
	}
	DVDMenuUndoObject *pUndoObject = (DVDMenuUndoObject *)pCurrentDVDMenu->getUndoBuffer()->popRedo();
	if (pUndoObject)	{
		editUndoAction->setEnabled(true);
		pUndoObject->redo (pCurrentDVDMenu);
	}
	else	// The redo returnd nothing, meaning that the stack is empty ...
		editRedoAction->setEnabled(false);
}

void QDVDAuthor::editCut()
{

}

void QDVDAuthor::editPaste()
{

}

void QDVDAuthor::editFind()
{

}

void QDVDAuthor::helpIndex()
{

}

void QDVDAuthor::helpContents()
{

}

void QDVDAuthor::helpAbout()
{
  QString qsAbout;
  qsAbout  = QString ("<h3><p align=\"center\">'Q' DVD-Author</p></h3>\n");
  qsAbout += QString (          "<p align=\"center\">By<br>"             );
  qsAbout += QString (             "<u>Varol Okan</u><br>"               );
  qsAbout += QString (                     "<br>"                        );
  qsAbout += QString (             "Ver: %1 (build:%2)<br>"              ).arg(QDVDAUTHOR_VERSION_NUMBER).arg(__DATE__);
  qsAbout += QString ("<a href=\"http://qdvdauthor.sf.net\">http://qdvdauthor.sourceforge.com</a></p>");
  uiDialogAbout dialogAbout (this);
  dialogAbout.m_pLabelAbout->setText ( qsAbout );
  dialogAbout.exec();
}

void QDVDAuthor::LoadIni ()
{
  QFileInfo fileInfo;
  QString   qsAbsPath;
  // Load the paths of the tools from the ini-file
  QDVDAuthorInit *pInit = new QDVDAuthorInit (&m_dragNDropContainer);
  m_listHistory      = pInit->getHistory      ();
  m_listHistoryPix   = pInit->getHistoryPix   ();
  m_iMaxHistoryFiles = pInit->maxHistoryFiles ();
  m_iAutosave        = pInit->getAutosave     ();
  m_listToolsPaths   = pInit->getToolsPaths   ();
  if (m_listToolsPaths.count() == 0)	{
    // If no paths are yet in the ini-file (meaning the first time start)
    // Then we call DialogSetup::slotScanSystem, to get there ...
    Utils theUtils;
    m_listToolsPaths = theUtils.scanSystem();
  }
  if (!m_listHistory.empty())	{
    fileInfo.setFile (m_listHistory.last());
    qsAbsPath = fileInfo.absFilePath();
    //		setCurrentPath (qsAbsPath);
  }
  // Finally we connect the Menu ...
  buildHistoryEntries ();
  setAutosave         ();
  
  MediaCreator::setPreferredEngine (pInit->preferredEngine());
  m_bVisibleRegion = pInit->visibleRegion();
  toolsVisibleRegionAction->setOn (m_bVisibleRegion);
  emit (signalVisibleRegion ( m_bVisibleRegion ));
  slotChangeStyle (pInit->getStyle());
  
  if( Global::qsLanguage != "en" )	{
    // Here we install the language the user has chosen ...
    QTranslator *pTrans = new QTranslator( 0 );
    // Under ~/.qdvdauthor/
    QString qsLang = QString(QString (PREFIX_DIRECTORY"/share/qdvdauthor/qdvdauthor_%1.qm").arg(Global::qsLanguage));
    if (m_pTranslator)	{
      qApp->removeTranslator ( m_pTranslator );
      delete m_pTranslator;
      m_pTranslator = NULL;	// Just for consistency ...
    }
    pTrans->load( qsLang );
    m_pTranslator = pTrans;
    qApp->installTranslator( m_pTranslator );
    languageChange();
  }
  
  delete pInit;
}

void QDVDAuthor::SaveIni ()
{
	// And then we store the ini - file ...
	QDVDAuthorInit *pInit = new QDVDAuthorInit (m_listToolsPaths, &m_dragNDropContainer);
	pInit->setHistory       (m_iMaxHistoryFiles, m_listHistory, m_listHistoryPix);
	pInit->setAutosave      (m_iAutosave);
	pInit->setVisibleRegion (m_bVisibleRegion);
	pInit->setStyle         (m_qsStyle);
	pInit->saveIniFile      ();
	// after all's said and done, I can dump this object...
	delete pInit;
}

void QDVDAuthor::setAutosave (bool bStopAutosave)
{
	// This function will create a QTimer (if neccesary) and call slotAutosave every so often
	if (bStopAutosave)	{
		if (m_pTimerAutosave)
			m_pTimerAutosave->stop();
		return;
	}
	if (m_iAutosave < 1)	{
		if (m_pTimerAutosave)	{
			m_pTimerAutosave->stop();
			delete m_pTimerAutosave;
		}
		m_pTimerAutosave = NULL;
		// No Autosave file to keep.
		QString qsAutosaveFile = QDir::homeDirPath();
		qsAutosaveFile.append(AUTOSAVE_FILE_NAME);
		QFile autosaveFile(qsAutosaveFile);
		autosaveFile.remove ();
	}
	if (m_pTimerAutosave)
		m_pTimerAutosave->changeInterval (m_iAutosave * 1000);
	else	{
		m_pTimerAutosave = new QTimer( this );
		connect( m_pTimerAutosave, SIGNAL(timeout()), this, SLOT(slotAutosave()) );
		m_pTimerAutosave->start( m_iAutosave * 1000);
	}
}

void QDVDAuthor::slotAutosave ()
{
  //printf ( "%s::%s::%d\n", __FILE__, __FUNCTION__, __LINE__ );
  // This function will create the autosave-project file
  QString qsAutosaveFile = QDir::homeDirPath();
  qsAutosaveFile.append(AUTOSAVE_FILE_NAME);
  m_bAutosaving = true;
  fileSave(qsAutosaveFile);
  m_bAutosaving = false;
}

void QDVDAuthor::addHistory (QString qsNewFile)
{
	int iIndex;
	QFileInfo  fileInfo (qsNewFile);
	QString qsAbsPath = fileInfo.absFilePath();
	// First we make a screenshot of the current VMGMenu
	updateHistoryPix ();
	
	// Here we add the file to the history and ensure it is only one time in the history ...
	iIndex = m_listHistory.findIndex (qsNewFile);
	if (iIndex > -1)	{	// That should keep them in synch ...
		m_listHistory.remove(qsNewFile);
		QPixmap *pPixmap = m_listHistoryPix[iIndex];
		m_listHistoryPix.remove (pPixmap);
		delete pPixmap;
	}
	if ((int)m_listHistory.count() > m_iMaxHistoryFiles)	{
		m_listHistory.remove(m_listHistory.first());
		QPixmap *pPixmap = m_listHistoryPix.first();
		m_listHistoryPix.remove(pPixmap);
		delete pPixmap;
	}
	m_listHistory.append(qsNewFile);
	m_listHistoryPix.append (new QPixmap());

	Global::qsCurrentPath = qsAbsPath;
	buildHistoryEntries     ();
}

void QDVDAuthor::buildHistoryEntries ()
{
	int t;
	QAction *pAction = NULL;
	// Here we clear the menu and re-build the entries according to the current values in
	// m_listHistory.
	m_pMenuHistory->clear ();
	for (t=(int)m_listHistory.count()-1; t>=0; t--)	{
		// First let us take care of the pixmap ... 
		if ((!m_listHistoryPix[t]) || (m_listHistoryPix[t]->isNull())	)	{
			QImage theImage(QImage().fromMimeSource( "error.jpg" ));
			theImage = theImage.smoothScale(m_dragNDropContainer.sizeThumbnail);
			QPixmap *pThePix =  new QPixmap();
			pThePix->convertFromImage (theImage);
			if (m_listHistoryPix[t])	// delete the old pixmap ...
				delete m_listHistoryPix[t];
			m_listHistoryPix[t] = pThePix;
		}
		pAction = new QAction ( this, QString ("history%1").arg(t) );
		pAction->setIconSet (*m_listHistoryPix[t] );
		pAction->setText    ( m_listHistory[t] );
		pAction->setMenuText( m_listHistory[t] );
		pAction->addTo(m_pMenuHistory);
	}
}

void QDVDAuthor::slotChangeHistory (int iID)
{
	// Called when the user clicks on a Historical Project file from the MainMenu
	int iIndexOfID = m_pMenuHistory->indexOf(iID);
	if (0 <= iIndexOfID)	{
		iIndexOfID = m_listHistory.count() - iIndexOfID - 1;
		if (iIndexOfID < 0)
			iIndexOfID = 0;
		QString qsProjectFile = m_listHistory[iIndexOfID];
//		addHistory (qsProjectFile);
		fileOpen   (qsProjectFile);
	}
}

void QDVDAuthor::updateHistoryPix ()
{
	int iIndex;
	if (!m_pVMGMenu)
		return;
	// If there is no current project then we skip it ...
	if (Global::qsProjectFileName.isEmpty())
		return;
	// If the current project is not in the list (Should never happen though).
	iIndex = m_listHistory.findIndex(Global::qsProjectFileName);
	if (iIndex < 0)
		return;

	QString  qsFileName;
	QImage   theImage;
	QPixmap *pCurrentPix = NULL;

	qsFileName = getTempFile (m_pVMGMenu->name() + QString ("/") + QString(BACKGROUND_NAME));
	m_pVMGMenu->createMask(qsFileName, BACKGROUND_IMG, true);
	QFileInfo fileInfo(qsFileName);
	
	if (!fileInfo.exists())
		return;
	theImage.load(qsFileName);
	theImage = theImage.smoothScale(m_dragNDropContainer.sizeThumbnail, QImage::ScaleMin);

	pCurrentPix = m_listHistoryPix[iIndex];
	if (!pCurrentPix)	// delete the old pixmap ...
		pCurrentPix = new QPixmap();
	pCurrentPix->convertFromImage (theImage);
	buildHistoryEntries();
}

//////////////////////////////////////////////////////////////////////////////////////////
//
// Here we have the routines which create the DVD structure.
//
///////////////////////////////////////////////////////////////////////////////////////////
void QDVDAuthor::slotCreateSVCD()
{
	MessageBox::information (NULL, tr ("Not implemented yet"),
		tr ("This function is not yet implemented.\n"), QMessageBox::Ok);
		return;
}

void QDVDAuthor::slotCreateVCD()
{
	MessageBox::information (NULL, tr ("Not implemented yet"),
		tr ("This function is not yet implemented.\n"), QMessageBox::Ok);
}

void QDVDAuthor::slotCreateDVD()
{
	// This function is invoked when the user wants to create the menu structure.
	// THus this function does the following
	// create /tmp/spumux.xml
	// create /tmp/dvdauthor.xml
	// invoke spumux -> output to dialog
	// invoke dvdauthor, but use dummy vob files rather then the original (hiuge) ones.

        m_pSubtitlesGui->releaseSourceFileInfo ();
	// This command will generate the Project path under the temp directory. This'll ensure the directory is present and writable for the temp data
	createTempDirStructure ();
	QString qsTempPath = getTempFile (QString());

	// The following line is already called from slotGenerateMasks
//	createMenuXml ();	// create spumux.xml
	createSubtitlesXml ();  // create all xml files for those files which have subtitles.
	createDvdauthorXml ();	// create dvdauthor.xml
	// And then we create the script to generate all those funky files ...
	createDVD ();
}

void QDVDAuthor::createMenuXml ()
{
  uint t;
  Export::Spumux spumux;
  spumux.createXml   ( m_pVMGMenu );
  for (t=0;t<m_listDVDMenus.count();t++)
    spumux.createXml ( m_listDVDMenus[t] );
}

void QDVDAuthor::createSubtitlesXml ()
{
  uint i, t, iCount;
  Export::Spumux   spumux;
  SourceFileEntry *pEntry;
  SourceFileInfo  *pInfo;  
  iCount = sourceFileCount ( );

  for (t=0;t<iCount;t++) {
    pEntry = sourceFileEntry ( t );
    for (i=0;i<pEntry->listFileInfos.count ();i++) {
      pInfo = pEntry->listFileInfos[i];
      // the following two calls go in concert ...
      renderSubtitles  ( pInfo );
      spumux.createXml ( pInfo );
    }
  }
}

// The following function will display the XML code for the specified Submenu (spumux)
// or the dvdauthor.xml - file in the XML - tab.
void QDVDAuthor::slotCreateXml(const QString &qsWhich)
{
  uint t, i;
  bool bFound = false;
  QString fileSpumux;
  Export::Spumux spumux;
  SourceFileEntry *pEntry = NULL;
  QFileInfo fileInfo;

  createTempDirStructure ();
  if (qsWhich.isEmpty())	{
    m_pTextEditXml->clear();
    return;
  }
  if (qsWhich == QString (DVDAUTHOR_XML)) 	{
    createDvdauthorXml ();
    fileSpumux = getTempFile(QString(DVDAUTHOR_XML));
  }
  else if (qsWhich == m_pVMGMenu->name())	{
    spumux.createXml ( m_pVMGMenu );
    fileSpumux = getTempFile(m_pVMGMenu->name()) + QString ("/menu.xml");
  }
  else {
    for (t=0;t<m_listDVDMenus.count();t++)	{
      if (qsWhich == m_listDVDMenus[t]->name())	{
	// Here we create the xml - file in the temp dir.
	spumux.createXml ( m_listDVDMenus[t] );
	fileSpumux = getTempFile(m_listDVDMenus[t]->name()) + QString ("/menu.xml");
	bFound = true;
	break;
      }
    }
    if ( ! bFound ) {
      for ( t=0; t< (uint) sourceFileCount ();t++ ) {
	pEntry = sourceFileEntry ( t );
	if ( ! pEntry )
	  continue;
	for (i=0;i<pEntry->listFileInfos.count();i++) {
	  SourceFileInfo *pInfo = pEntry->listFileInfos[i];
	  fileInfo.setFile ( pInfo->qsFileName );
	  fileSpumux = QString ("%1.xml").arg ( fileInfo.baseName ( ) );
	  if ( qsWhich == fileSpumux ) {
	    spumux.createXml ( pInfo );
	    fileSpumux = QString ("%1/subtitles.xml").arg ( getTempFile( fileInfo.baseName ( ) ) );
	    break;
	  }
	}
      }
    }
  }

  fileInfo.setFile ( fileSpumux );
  if ( ! fileInfo.exists () )
    return;
  // Finally we read in the xml file.
  m_pTextEditXml->clear();
  QFile file( fileSpumux ); // Read the text from a file
  if ( file.open( IO_ReadOnly ) ) {
    QTextStream stream( &file );
    m_pTextEditXml->setText( stream.read() );
  }
}

void QDVDAuthor::createDvdauthorXml ()
{
  Export::DVDAuthor theExporter ( this );
  theExporter.createXml ();
}

QRect QDVDAuthor::getSubtitlesRect ( SourceFileInfo *pInfo )
{
  QRect theRect;
  Utils theUtils;
  int iVideoWidth, iVideoHeight;
  Subtitles *pSubtitles = pInfo->pSubtitles;
  int        iFontSize  = pSubtitles->font.pointSize ();

  if ( iFontSize == -1 ) {
       iFontSize = pSubtitles->font.pixelSize ();
       if ( iFontSize == -1 )
	    iFontSize = 24;
  }
  iFontSize *= 3;

  iVideoWidth  = theUtils.getWHFromResolution ( pInfo->qsResolution, true  );
  iVideoHeight = theUtils.getWHFromResolution ( pInfo->qsResolution, false );
  if ( iVideoWidth  < 350 ) // out of spec ?
       iVideoWidth  = 720;
  if ( iVideoHeight < 240 ) // out of spec ?
       iVideoHeight = 480;
  
  theRect = pSubtitles->rect;
  // Try to figure out if the user was too lazy to input values ...
  if ( ( pSubtitles->rect.x() == 0 ) && ( pSubtitles->rect.y() == 0 ) ) {
    if ( ( ( pSubtitles->rect.width  () == iVideoWidth  ) && 
	   ( pSubtitles->rect.height () == iVideoHeight )  ) ||   // rect == video's rect
	 ( ( pSubtitles->rect.width  () == 0            ) && 
	   ( pSubtitles->rect.height () == 0            )  )  ) { // or rect is empty
      theRect = QRect ( 0, iVideoHeight - 45 - iFontSize, iVideoWidth, iFontSize );
    }
  }
  return theRect;
}

void QDVDAuthor::renderSubtitles ( SourceFileInfo *pInfo )
{
  // Here we handle this in just one function as we can call 
  // qApp->processEvents ( 100 ); // process for 100 ms
  if ( ! pInfo )
    return;

  Subtitles *pSubtitles = pInfo->pSubtitles;
  if ( ! pSubtitles )
    return;

  int       t, iTotalCount, iWidth, iHeight;
  QString   qsThePath, qsFileName, qsStart;
  QRgb      colors[ 4 ];
  Utils     theUtils;
  QImage    theImage;
  QRect     theRect;
  QPainter  thePainter; // ( &theDrawingBoard  )\\;
  QFileInfo fileInfo   ( pInfo->qsFileName );
  Subtitles::entry *pEntry;
  // Okay the subtitles should be named like $TMP/$PROJ/BASE_NAME/sub_<start>.png
  qsThePath = theUtils.getTempFile( fileInfo.baseName () );
  QDir tempDir (qsThePath);
  if ( ! tempDir.exists ( ) )
    tempDir.mkdir ( qsThePath );
  qsThePath += QString ("/sub_");

  // get the rect of the video ...
  iWidth  = theUtils.getWHFromResolution ( pInfo->qsResolution, true  );
  iHeight = theUtils.getWHFromResolution ( pInfo->qsResolution, false );
  if ( iWidth  < 350 )
       iWidth  = 720;
  if ( iHeight < 240 )
       iHeight = 480;

  // get the rect for the subtitles. Try to be clever about it.
  theRect = getSubtitlesRect ( pInfo );
  pSubtitles->rect = theRect;

  colors[0]  = pSubtitles->subColors[0].rgb() & 0x00FFFFFF;
  colors[1]  = pSubtitles->subColors[1].rgb() & 0x00FFFFFF;
  colors[2]  = pSubtitles->subColors[2].rgb() & 0x00FFFFFF;
  colors[3]  = pSubtitles->subColors[3].rgb() & 0x00FFFFFF;
  colors[0] |= ( pSubtitles->iTransparency << 24 );
  colors[1] |= 0xff000000; // make the text opaque
  colors[2] |= 0xff000000; // make the text opaque
  colors[3] |= 0xff000000; // make the text opaque
  
  //colors[0] = TEMP_SUBTITLES_COLOR0 | (pSubtitles->iTransparency << 24);
  //colors[1] = TEMP_SUBTITLES_COLOR1;
  //colors[2] = TEMP_SUBTITLES_COLOR2;
  //colors[3] = TEMP_SUBTITLES_COLOR3;

  // The most basic progressbar ...
  QProgressBar progress ( this );
  QRect boundingRect;
  QPen  thePen ( pSubtitles->subColors[1], 2, Qt::DashDotLine);

  int iFlags = Qt::DontClip|Qt::WordBreak|Qt::AlignHCenter|Qt::AlignVCenter;
  // Only 4 colors avail. Sorry no aliasing.
  pSubtitles->font.setStyleStrategy ( QFont::NoAntialias );
  iTotalCount = (int)pSubtitles->listOfSubtitles.count ();

  for (t=0;t<iTotalCount; t++) {
    pEntry = pSubtitles->listOfSubtitles[t];
    qsStart = pEntry->qsTimeStart;
    qsStart.remove ( ":"      );
    qsStart.replace( ".", "_" );
    qsFileName = QString ("%1%2.png").arg ( qsThePath ).arg( qsStart );

    // First we should fill the drawing board with the propper background  color.
    QPixmap theDrawingBoard ( iWidth, iHeight );
    thePainter.begin ( &theDrawingBoard  ); {
      theDrawingBoard.fill ( pSubtitles->subColors[0] );
      thePainter.setPen   ( thePen );
      thePainter.setBrush ( QBrush ( pSubtitles->subColors[0] ) );
      thePainter.setFont  ( pSubtitles->font );
     
      pEntry->rect = theRect;
      // Here we draw onto the drawing board
      thePainter.drawText(theRect, iFlags, pEntry->qsText, -1, &boundingRect);
      if ( ( boundingRect.width() > theRect.width() ) || ( boundingRect.height() > theRect.height() ) )
	pEntry->rect = boundingRect; // in case the bounding rect was too big ...
      
      // create new dimensioned pixmap
      QPixmap thePixmap = QPixmap ( pEntry->rect.width(), pEntry->rect.height () );
#if ( QT_VERSION > 0x0301FF )
      copyBlt ( &thePixmap, 0, 0, &theDrawingBoard,  pEntry->rect.x(),  pEntry->rect.y(),  pEntry->rect.width(),  pEntry->rect.height());
#else
      bitBlt ( &thePixmap, 0, 0, &theDrawingBoard,  pEntry->rect.x(),  pEntry->rect.y(),  pEntry->rect.width(),  pEntry->rect.height(), Qt::CopyROP);      
#endif
      theImage = thePixmap.convertToImage ();
    }  thePainter.end ();
    //    if ( pSubtitles->iTransparency > 1 )
    theImage.setAlphaBuffer ( true );
    // and finally we save the rendered image and show some progress ...
    theUtils.reduceColors ( theImage, 4, (QRgb *)&colors );

    //    QRgb theColor;
    //    int i;
    //    // 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 ) ) {
    //	  theColor = pSubtitles->subColors[t].rgb() & 0x00FFFFFF;
    //	  if ( t == 0 )
    //	    theColor |= ( pSubtitles->iTransparency << 24 );
    //	  else
    //	    theColor |= 0xff000000;
    //	  theImage.setColor ( t, theColor);
    //	}
    //      }
    //    }    
    theImage.save ( qsFileName, "PNG", 100);  // 100%== No compression. png image

    progress.setProgress ( (int)((float)t / iTotalCount * 100.0) );
    if ( t%10 == 0 ) 
      qApp->processEvents ( 100 ); // do some event processing ...
  }
  // that's it ...
}

bool QDVDAuthor::checkForNewProject ()
{
	if (Global::qsProjectPath.isEmpty())	{
		newWizard ();
		return false;
	}
	return true;
}

bool QDVDAuthor::checkHealth ()
{
	// This function checks if all is in order
	// o  There is a background image.
	//    - If not only a standard VideoDVD is created without menu.
	// o  There are buttons defined
	//    - Wether through a mask, or manually defined.
	// o  There is enough space on the defined temp - path.
	//    - approximately by adding all sizes together.
	// o  And the temp drive should be writeable.
        uint t;
	CDVDMenuInterface *pInterface = m_pVMGMenu->getInterface();
	// primary implementation only checks for Background, and mask images.
	if (Global::qsTempPath.isEmpty())	{
		MessageBox::warning ( this, tr ("Error, missing temp path."),
			tr ("You forgot to specify a temp path.\n"
				"I can not build this DVD without temp path.\n"
				"Please define the missing temp path first.\n"),
				QMessageBox::Ok, QMessageBox::NoButton);
		return false;
	}
	else	{
		// Check if we can write to the temp path.
		QFile file( Global::qsTempPath + QString ("/test_file") );
		if ( !file.open( IO_WriteOnly ) )	{
			MessageBox::warning ( this, tr ("Error, can't write to temp."),
				tr ("I can not write to the specified temp directory.\n%1\n"
					"Please verify the temp path and try again.\n").arg(Global::qsTempPath),
					QMessageBox::Ok, QMessageBox::NoButton);
			return false;
		}
		else	{
        	file.close();
			file.remove();
		}
	}
	if (Global::qsProjectPath.isEmpty())	{
		if (MessageBox::warning ( this, tr ("Error, missing DVD path."),
			tr ("You forgot to specify the DVD path.\n"
				"I can not build this DVD without a DVD path.\n"
				"Do you want to define the missing DVD path now ?\n"),
				QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
				slotSetup();
		return false;
	}
	else	{
		// Check if we can write to the projectPath.
		QFile file( Global::qsProjectPath + QString ("/test_file") );
		if ( !file.open( IO_WriteOnly ) )	{
			if (MessageBox::warning ( this, tr ("Error, can't write to project path."),
				tr ("I can not write to the specified Project directory.\n%1\n"
					 "Do you want to change the specified path now ?\n").arg(Global::qsProjectPath),
					QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)
				slotSetup();
			return false;
		}
		else	{
        	file.close();
			file.remove();
		}
	}
	if (pInterface->qsBackgroundFileName.isEmpty())	{
		if (MessageBox::warning ( this, tr ("No background defined."),
			tr ("You did not define a background image.\n"
				"Do you want to create a VideoDVD without Menu ?\n"),
				QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)	{
			// Here we create a Video DVD without a menu
		}
		// otherwise we abort here.
		else
			return false;
	}

	QValueList<ButtonObject *> listButtons;
	listButtons = m_pVMGMenu->getButtons();
	if ( ( pInterface->qsHighlightedMaskFileName.isEmpty ( ) ) && 
	     ( pInterface->qsSelectedMaskFileName.isEmpty    ( ) ) &&
	     ( listButtons.count ( ) == 0) )	{
	  if ( MessageBox::warning ( this, tr ("No button masks defined."),
				     tr ("You did not define any buttons.\n"
					 "Do you want to create a VideoDVD without Menu ?\n"),
				     QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)	{
	    // Here we create a Video DVD without a menu
	  }
	  // otherwise we abort here.
	  else
	    return false;
	}

	// Check if buttons are overlapping each other ...
	QString qsOverlappingButtons;
	qsOverlappingButtons = m_pVMGMenu->checkButtonsOverlapping ( );
	for (t=0;t<m_listDVDMenus.count ();t++)
	  qsOverlappingButtons += m_listDVDMenus[t]->checkButtonsOverlapping ( );
	
	if ( qsOverlappingButtons.length () > 1 ) {
	  qsOverlappingButtons  = tr ( "Found buttons overlapping.<BR>I will correct these but the buttons might not look exactly the way you positioned them.<BR>" ) + qsOverlappingButtons;
	  qsOverlappingButtons += tr ( "<BR>Do you want to manually correct the buttons positions ?" );
	  if ( MessageBox::html ( this, tr( "Found Buttons overlapping." ), qsOverlappingButtons, QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes )
	    return false;
	}

	if (m_pSourceToolbar->sourceFileCount() < 1)	{
		if (MessageBox::warning ( this, tr ("No movies defined."),
			tr ("You did not select any movies.\n"
				"Do you want to create a DVD with Menu and no movies ?\n"),
				QMessageBox::Yes, QMessageBox::No) == QMessageBox::Yes)	{
			// Here we create a Video DVD without movie files.
		}
		// otherwise we abort here.
		else
			return false;
	}
	// Here we check if there is already a dvd in place where the new one should be
	QDir projectDir (Global::qsProjectPath + QString ("/VIDEO_TS/"));
	QStringList listFiles = projectDir.entryList ("*");
	if (listFiles.count() > 2)	{	// the two standard directories . and ..
	  QString stringFiles;
	  for (t=0;t<listFiles.count();t++)	{
	    if ( (listFiles[t] == ".") || (listFiles[t] == "..") )
	      continue;
	    stringFiles += QString ("%1\n").arg(listFiles[t]);
	  }
	  int iReturn = MessageBox::warning ( this, tr ("DVD files found."),
		tr ("I found DVD files most likely from a previous run.\n%1"
		    "Do you want to remove those files first ?\n").arg(stringFiles),
		     QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel );
	  if ( iReturn == QMessageBox::Cancel )
	    return false;
	  else if ( iReturn == QMessageBox::Yes)	{
	    // Here we remove all files under Global::qsProjectPath/VIDEO_TS/
	    for (t=0;t<listFiles.count();t++)	{
	      if ( (listFiles[t] == ".") || (listFiles[t] == "..") )
		continue;
	      projectDir.remove (listFiles[t]);
	    }
	  }
	  
	}

	return true;
}

QString QDVDAuthor::getTempFile (QString qsOrigFileName)
{
	Utils theUtil;
	return theUtil.getTempFile (qsOrigFileName);
}

/*******************************************************************************************************
/tmp/ProjectName/+-> dragged Image files.
                 |
                 +->Movie 1/ --> clean.avi -=> Cleaned movie file or non-existant
                 +->Movie 2/ --> clean.avi -=> Cleaned movie file or non-existant
                 +->Movie 3/ --> clean.avi -=> Cleaned movie file or non-existant
                 +->Movie N/ --> clean.avi -=> Cleaned movie file or non-existant
                 |
                 +->Sub Menu 1_menu.mpg                       -=> final movie with sound and buttons.
                 +->Sub Menu 1/ +-> background/ +-> clip.wav
                 |              +-> background/ +-> clean.avi -=> cleaned up movie stream
                 |              +-> background/ +-> clip.avi  -=> Extracted timeframe of input-moviebackground
                 |              +-> background/ +-> menu.m2v  -=> final mpeg2enc menu movie (no sound)
                 |              +-> background/ +-> menu.mp2  -=> sound fileif neccesary
                 |              +-> background/ +-> menu.mpg  -=> final movie with sound
                 |              +-> background/ +-> menu.xml  -=> spumux - file
                 |              +-> background/ +-> -- Extracted images --
                 |              +-> background/ +-> rendered_-- Extracted images --
                 |              |
                 |              +-> Button 1/ +-> clip.wav
                 |              |             +-> clean.avi-=> cleaned up movie stream
                 |              |             +-> clip.avi -=> Extracted timeframe of [movie x]
                 |              |             +-> -- Extracted images -- 
                 |              +-> Button 2/ +-> clip.wav
                 |              |             +-> clip.avi -=> Extracted timeframe of [movie y]
                 |              |             +-> -- Extracted images -- 
                 |              +->MovieObject+-> clip.wav
                 |                            +-> clip.avi -=> Extracted timeframe of [movie z]
                 |                            +-> -- Extracted images -- 
                 |
                 +->Sub Menu 2_menu.mpg
                 +->Sub Menu 2/ +-> background/ +-> clip.wav
                                +-> background/ +-> clip.avi
                                +-> background/ +-> menu.m2v
                                +-> background/ +-> menu.mp2
                                +-> background/ +-> menu.mpg
                                +-> background/ +-> menu.xml
                                +-> background/ +-> -- Extracted images --
                                +-> background/ +-> rendered_-- Extracted images --
                                |
                                +-> Button 1/ +-> clip.wav
                                |             +-> clip.avi -=> Extracted timeframe of [movie a]
                                |             +-> -- Extracted images -- 
                                +-> Button 2/ +-> clip.wav
                                |             +-> clip.avi -=> Extracted timeframe of [movie b]
                                |             +-> -- Extracted images -- 
                                +-> Button 3/ +-> clip.wav
                                              +-> clip.avi -=> Extracted timeframe of [movie c]
                                              +-> -- Extracted images -- 
********************************************************************************/
void QDVDAuthor::createTempDirStructure ()
{
	QString qsTempDir = Global::qsTempPath + QString ("/") +  Global::qsProjectName + QString ("/");
	QString qsCurrentDir;
	// we take this to check if the temp drive exists and if not, then we will create one ...
	QDir tempDir (qsTempDir);
	if (!tempDir.exists())
		tempDir.mkdir (qsTempDir);
	// this test is done only once 'cause if we can create this directory the we should have no problems 
	// creating sub directories ...
	if (!tempDir.exists())	{
		MessageBox::warning ( NULL, QObject::tr ("Could not create temp directory"),
		QObject::tr ("Failed to create temp directory\n"
			"%1").arg (qsTempDir),
			QMessageBox::Ok, QMessageBox::NoButton);
			return;
	}
	// First we create a sub-directory for every SourceFileEntry in the project
	
	// Then we create a subdirectroy for each menu.
	DVDMenu *pMenu = m_pVMGMenu;
	int iMenuCounter = 0;
	while (iMenuCounter <= (int)m_listDVDMenus.count())	{
		qsCurrentDir = qsTempDir + pMenu->name();
		tempDir.setPath (qsCurrentDir);
		if (!tempDir.exists())
			tempDir.mkdir (qsCurrentDir);
		// Inside each menu we create 
		// background
		qsCurrentDir = qsTempDir + pMenu->name() + QString ("/background");
		tempDir.setPath (qsCurrentDir);
		if (!tempDir.exists())
			tempDir.mkdir (qsCurrentDir);

		// one dir for each MovieObject (Note that Buttons / ObjectCollections can contain a MovieObject)
		QValueList <MovieObject *> listMovieClips = pMenu->getMovieObjects ();
		for (uint t=0;t<listMovieClips.count();t++)	{
			qsCurrentDir = qsTempDir + pMenu->name() + QString ("/") + listMovieClips[t]->name();
			tempDir.setPath (qsCurrentDir);
			if (!tempDir.exists())
				tempDir.mkdir (qsCurrentDir);
		}
		// and finally we increase the menuCounter and get the next menu ...
		pMenu = m_listDVDMenus[iMenuCounter++];
	}	// end of loop ...
	// done.
}

void QDVDAuthor::createDVD ()
{
	int t;
	// Note: All the logic has been put into the config file and is created in QDVDAuthorInit.
	if (!checkHealth())
		return;

	// First let us create the directory under the temp - drive
	QString qsBackgroundFileName;
	QString qsMenuName;
	// Ensure that the temp drive is present, otherwise create it.
	// Error message if not possible.
	QString qsTempPath = getTempFile (QString());
	QStringList stringList;

	int iMenuCounter = 0;
	DVDMenu *pMenu = m_pVMGMenu;

	QDVDAuthorInit *pInit = new QDVDAuthorInit (&m_dragNDropContainer);
	pInit->setHistory    (m_iMaxHistoryFiles, m_listHistory, m_listHistoryPix);
	pInit->setAutosave   (m_iAutosave);
	pInit->setStyle      (m_qsStyle);
	pInit->setToolsPaths (m_listToolsPaths);
	// Here we go through all Menus (including VMGM) and generate the appropriate commands.
	pInit->appendPreProcessing ();
	for (t=0;t<sourceFileCount ();t++)	{
		SourceFileEntry *pEntry = sourceFileEntry(t);
		pInit->appendConvert (pEntry);
	}

	while (iMenuCounter <= (int)m_listDVDMenus.count() )	{
		qsMenuName = getTempFile (  pMenu->name () );
		qsBackgroundFileName = getTempFile (pMenu->name()) + QString ("/") + QString(BACKGROUND_NAME);
		// If we have a movie background we ought to get the name right ...
		if (!pMenu->getInterface()->qsMovieFileName.isEmpty())
			qsBackgroundFileName = pMenu->getInterface()->qsMovieFileName;
		if ( ! pMenu->isEmpty () ) 
		  pInit->appendMenu (pMenu, qsMenuName, qsBackgroundFileName);
		pMenu = m_listDVDMenus[iMenuCounter++];
	}	// end of loop ...
	pInit->appendPostProcessing ();

	// In case the Dialog does already exist, we want to delete it before we use it again, to free memory.
	if (m_pDialogExecute)
		delete m_pDialogExecute;

	// And finally we call the CommandQueue - Dialog.
	m_pDialogExecute = new DialogExecute(pInit->getList());
	connect (m_pDialogExecute, SIGNAL (signalGenerateMasks())    , this, SLOT ( slotGenerateMasks()     ));
	connect (m_pDialogExecute, SIGNAL (signalRenderMenu(QString)), this, SLOT ( slotRenderMenu(QString) ));
	m_pDialogExecute->setInit(pInit);
	m_pDialogExecute->exec();
	// Please note that the pInit - object is now destroyed in the DialogExecute
}
 
void QDVDAuthor::slotRenderMenu (QString qsMenuName)
{
	// Called from DialogExecute::slotRenderMenu
	DVDMenu *pMenu = getSubMenuByName (qsMenuName);
	if (pMenu)	{
		// We can't just call pMenu->renderMenu() now because 
		// there could be a request already in the FIFO
		// So this call will check for that, and then call pMenu->renderMenu()
		StartMenuRender startMenuRender (pMenu);
		// Note that the rendering is now done in the main thread OR 
		// we wait for the background thread to terminate
		startMenuRender.renderDVDMenu ();
//		while (!pMenu->renderingDone ())
//			sleep (1);
	}
}

void QDVDAuthor::returnFromRenderMenu ()
{
	// This function is called when the DVDMenu is done rendering the menu to a movie file.
	// SInce this is a non-blocking operation, we can not handle this in 
	// one function (slotRenderMenu() but we have to have two functions here instead.
	if (m_pDialogExecute)
		m_pDialogExecute->returnFromRenderMenu();
}

void QDVDAuthor::slotSetup()
{
	uint t;
	// Calling the setup dialog.
	DialogSetup *pDialog = new DialogSetup (this);
	pDialog->setToolsPaths (m_listToolsPaths);
	pDialog->setHistory    (m_iMaxHistoryFiles, m_listHistory, m_listHistoryPix);
	pDialog->setAutosave   (m_iAutosave);
	pDialog->setStyle      (m_qsStyle);
	// Here we set up the data of the Setup dialog ...
	pDialog->m_pEditProjectPath->setText(Global::qsProjectPath);
	pDialog->m_pEditProjectName->setText(Global::qsProjectName);
	pDialog->m_pEditTempPath   ->setText(Global::qsTempPath);
	pDialog->setDragNDrop (&m_dragNDropContainer);

	if (pDialog->exec() == QDialog::Rejected)
		return;

	if (pDialog->modifiedToolsPaths())
		m_listToolsPaths = pDialog->getToolsPathsList ();

	Global::qsProjectPath 	= pDialog->m_pEditProjectPath->text();
	Global::qsProjectName	= pDialog->m_pEditProjectName->text();
	Global::qsTempPath	= pDialog->m_pEditTempPath->text();
	// Note that the DragNDrop stuff is taken care off in the dialog already ...
	QFileInfo fileInfo ( Global::qsProjectFileName );
	setCaption ( QString ("'Q' DVD-Author :<%1> %2").arg( Global::qsProjectName ).arg( fileInfo.fileName ()) );

	// Next, lets check if the Max HistoryFiles have become less 
	// AND we have now more then allowed in the history ...
	if ((int)m_listHistory.count() > pDialog->maxHistoryFiles())	{
		uint iCounter = m_listHistory.count();
		// First we delete the Pixmap objhects
		for (t=pDialog->maxHistoryFiles();t<iCounter;t++)
		  delete m_listHistoryPix[t];
		// then we remove the values from the list ...
		for (t=pDialog->maxHistoryFiles();t<iCounter;t++)	{
			m_listHistory.remove (m_listHistory.last());
			m_listHistoryPix.remove (m_listHistoryPix.last());
		}
		buildHistoryEntries();
	}
	m_iMaxHistoryFiles = pDialog->maxHistoryFiles();

	if (pDialog->resetHistory())	{
		m_listHistory.clear();
		for (t=0;t<m_listHistoryPix.count();t++)
			delete m_listHistoryPix[t];
		m_listHistoryPix.clear ();
		buildHistoryEntries();
	}
	if (m_iAutosave != pDialog->getAutosave ())	{
		m_iAutosave = pDialog->getAutosave ();
		setAutosave ();
	}
	// Here we set the ImageButton / MovieButton flag in all menus ...
	if (m_pVMGMenu)
		m_pVMGMenu->getMenuPreview()->setImageButton (getDragNDropContainer()->bImageButton);
	for (t=0;t<m_listDVDMenus.count();t++)
		m_listDVDMenus[t]->getMenuPreview()->setImageButton (getDragNDropContainer()->bImageButton);
	delete pDialog;
}

void QDVDAuthor::slotDialogTemp ()
{
	DialogTemp *pDialog = new DialogTemp (this);

	pDialog->exec();
	delete pDialog;
}

void QDVDAuthor::slotTemplateDownload ( )
{
  TemplateDownload theDialog ( this );

  theDialog.exec ( );
}

void QDVDAuthor::slotVisibleRegion(bool)
{
	// This signal is intercepted from all DVDMenu's which in turn 
	// will set the flag to draw or not to draw the visible region 
	// in m_pPreviewMenu ...
	m_bVisibleRegion = toolsVisibleRegionAction->isOn();
	emit (signalVisibleRegion ( m_bVisibleRegion ));
}

void QDVDAuthor::fileNew()
{
	cleanUp();
	slotCalculateSize();
	newWizard ();
}

void QDVDAuthor::newWizard ()
{
	uiNewWizard *pWizard = new uiNewWizard (this);
	QFileInfo fileInfo (Global::qsProjectFileName);

	pWizard->m_pEditProjectName->setText(Global::qsProjectName);	//fileInfo.baseName());
	pWizard->m_pEditDVDPath    ->setText(Global::qsProjectPath);
	pWizard->m_pEditTempPath   ->setText(Global::qsTempPath);
	if (pWizard->exec() == QDialog::Rejected)
		return;

	Global::qsProjectName = pWizard->m_pEditProjectName->text(); // QString ( PROJECT_FILENAME );
	Global::qsProjectPath = pWizard->m_pEditDVDPath    ->text(); // QString ("");
	Global::qsTempPath    = pWizard->m_pEditTempPath   ->text(); // QString ("./");
	addHistory (Global::qsProjectFileName);
	delete pWizard;
}

bool QDVDAuthor::cleanUp()
{
	// here we close all Menus, unload the SourceFileEntries and re-set all other variables
	uint t;
	int iReturn;
	// First we should check back if that is what the user wants ...
//	iReturn = MessageBox::warning ( this, QString ("Closing current Session."),
//		QString ("This will close the current Project.\nAre you sure ?"),
//		QMessageBox::Yes, QMessageBox::No);
//	if (iReturn == QMessageBox::No)
//		return false;
	if ( (m_pVMGMenu->getInterface()->bModified) || (m_bModified) )	{
		// Now we see if there is something to loose which might be worth saving ...
		iReturn = MessageBox::warning ( this, tr ("File not saved"),
			tr ("The current modifications have not been save to the file. \nDo you want to save the project now ?"),
			QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel);
		if (iReturn == QMessageBox::Yes)
			fileSave ();
		else if (iReturn == QMessageBox::Cancel)
			return false;
	}

	// Okay let us start with deleting the SubMenus ...
	for (t=0;t<m_listDVDMenus.count();t++)
		delete m_listDVDMenus[t];
	m_listDVDMenus.clear();

	// Here we delete the Main VMGM - menu ...
	delete m_pVMGMenu;
	m_pVMGMenu = NULL;
	VMGMenu *pVMGMenu = new VMGMenu (this);
	addDVDMenu(pVMGMenu, true);

	// Next on the list are the SourceFileEntries ...
	m_pSourceToolbar->clear();
	
	// And finally re-set the variables ...
	Global::qsProjectFileName = QString ( PROJECT_FILENAME );
	m_bModified = false;
//	Global::qsProjectPath = QString ("");
	Global::qsCurrentPath = QString ("./");
//	for (t=0;t<m_listToolsPaths.count();t++)
//		delete m_listToolsPaths[t];
//	m_listToolsPaths.clear();
	return true;
}

void QDVDAuthor::fileOpen ()
{
	// First let the user pick a new project to open.
	QString qsProjectFileName = QFileDialog::getOpenFileName(Global::qsCurrentPath, tr("Project Files (*.xml *.XML)"), this, tr("Open Project file dialog"), tr ("Open Project File"));
	// Sanity check .. Did te user choose a new project file ?
	if (qsProjectFileName.isNull ())
		return;
	addHistory (qsProjectFileName);
	fileOpen   (qsProjectFileName);
}

void QDVDAuthor::fileOpen (QString qsProjectFileName)
{
	bool bError = false;
	// This function reads in a project file.
	if (!cleanUp())
		return;
	QFileInfo fileInfo  (qsProjectFileName);
	QString qsPath = fileInfo.dirPath ( TRUE );
	Global::qsCurrentPath = qsPath;

	// Assign the file
	QFile projectFile(qsProjectFileName);
	if (!projectFile.open(IO_ReadWrite))
		return;
	// Try to get the right xml contents ...
	QDomDocument xmlDoc( XML_DOCTYPE );
	if (!xmlDoc.setContent (&projectFile))	{
		// Error handling ...
		projectFile.close();
		int iReturn = MessageBox::warning ( this, tr ("xml project file seems to be defective."),
			tr ("Do you want to try to load another project file ?"),
			QMessageBox::Yes, QMessageBox::No);
		if (iReturn == QMessageBox::Yes)
			fileOpen ();	// Okay, user wants to specify another project file.
		return;
	}

	// Here is the main loop to extract the info ...
	QDomElement docElem = xmlDoc.documentElement();
	QDomNode xmlNode = docElem.firstChild();
	// First we take care of the QDVDAuthor variables ...
	while( !xmlNode.isNull() ) {
		QDomElement searchXMLTree = xmlNode.toElement();
		if (DVDAUTHOR == searchXMLTree.tagName () )	{
			bError = !readProjectFile (searchXMLTree);
		}
		else if (DVDAUTHOR_ROOT_VMGM == searchXMLTree.tagName () )	{
			m_pVMGMenu->readProjectFile(searchXMLTree);
			m_pVMGMenu->updateDVDMenu();
		}
		else if (DVDAUTHOR_ROOT_MENU == searchXMLTree.tagName () )	{
			DVDMenu *pDVDMenu = new DVDMenu(this);
			addDVDMenu(pDVDMenu);
			pDVDMenu->readProjectFile(searchXMLTree);
			pDVDMenu->updateDVDMenu();
		}
		else
			printf ("Warning: QDVDAuthor::fileOpen -=> wrong XML Node <%s>\nContinuing ...\n",
					(const char *)searchXMLTree.tagName());

		if (bError)
			break;
		// Go to the next node ...
		xmlNode = xmlNode.nextSibling();
	}
	projectFile.close();
	if (bError)	{
		MessageBox::warning ( this, tr ("Error occured reading project file."),
			tr ("An unknown error occured when trying to read teh project xml file."),
			QMessageBox::Ok, QMessageBox::NoButton);
		return;
	}
	// Setting of the variables ...
	m_bModified = false;
	Global::qsProjectFileName = qsProjectFileName;
	DVDMenu *pMenu = getCurrentSubMenu ();
	if (pMenu)
		m_pColorToolbar->setDVDMenu (pMenu);

	// And finally we update the HistoryPixmap ...
	updateHistoryPix();
	// Okay why should we have an outdated copy around ?
	slotAutosave ();
	slotCalculateSize();
	fileInfo.setFile ( Global::qsProjectFileName );
	setCaption ( QString ("'Q' DVD-Author :<%1> %2").arg( Global::qsProjectName ).arg( fileInfo.fileName ()) );
}

bool QDVDAuthor::readProjectFile (QDomNode &xmlNode)
{
  QString qsVersionNumber;
	
  QDomElement theElement = xmlNode.parentNode().toElement();
  QDomAttr attribute;

  attribute = theElement.attributeNode ( THE_PROJECT_NAME );
  if (!attribute.isNull())
    Global::qsProjectName = attribute.value();
  
  // Here we get the DVDAuthor Nodes ...
  QDomNode xmlDVDAuthor = xmlNode.firstChild();
  while ( !xmlDVDAuthor.isNull () )	{
    // Okay, here we retain the stored data from the xml file.
    theElement = xmlDVDAuthor.toElement();
    QString tagName = theElement.tagName();
    QString nodeText = theElement.text ();
    // Okay, this is ugly but after all it is the simplest of all xml file structure.
    // No need to get fancy ...
    if (tagName == QDVDAUTHOR_VERSION)
      qsVersionNumber = nodeText;
    else if (tagName == DVDAUTHOR_TEMP_PATH)
      Global::qsTempPath = nodeText;
    else if (tagName == DVDAUTHOR_PROJECT_PATH)
      Global::qsProjectPath = nodeText;
    else if (tagName == DVDAUTHOR_CURRENT_PATH)
      Global::qsCurrentPath = nodeText;
    else if (tagName == SOURCE_OBJECT)	{
      SourceFileEntry *pNewEntry = new SourceFileEntry;
      pNewEntry->readProjectFile(xmlDVDAuthor);
      m_pSourceToolbar->appendSourceFileEntry(pNewEntry);
    }
    else if (tagName == SOURCE_OBJECT_SUBTITLES)	{
      if ( m_pSubtitlesGui ) {
	Subtitles *pSubtitles = m_pSubtitlesGui->getSubtitles ( true );
	if ( pSubtitles )
	     pSubtitles->readProjectFile    ( xmlDVDAuthor );
	// And lets create the table for these subtitles ...
	m_pSubtitlesGui->createTableEntries ( );
      }
    }
    else
      printf ("Warning: QDVDAuthor::readProjectFile -=> wrong XML Node <%s>\nContinuing ...\n",
	      (const char *)tagName);
    // So lets get the next sibling ... until we hit the end of DVDMenu ...
    xmlDVDAuthor = xmlDVDAuthor.nextSibling();
  }
  return true;
}

bool QDVDAuthor::writeProjectFile(QDomElement &rootElement)
{
	QDomDocument xmlDoc = rootElement.ownerDocument();
	
	if (!Global::qsProjectName.isNull())
		rootElement.setAttribute( THE_PROJECT_NAME,   Global::qsProjectName );

	QDomElement rootDVDAuthor = xmlDoc.createElement( DVDAUTHOR );
	rootElement.appendChild ( rootDVDAuthor );
	// Okay, the main Node is created, now all DVDAuthor related information belon under it.
		QDomElement tag = xmlDoc.createElement( QDVDAUTHOR_VERSION );
		rootDVDAuthor.appendChild ( tag );
		QDomText text = xmlDoc.createTextNode ( QDVDAUTHOR_VERSION_NUMBER );
		tag.appendChild ( text );

		tag = xmlDoc.createElement   ( DVDAUTHOR_CURRENT_PATH );
		rootDVDAuthor.appendChild    ( tag );
		text = xmlDoc.createTextNode ( Global::qsCurrentPath );
		tag.appendChild ( text );

		tag = xmlDoc.createElement   ( DVDAUTHOR_TEMP_PATH );
		rootDVDAuthor.appendChild    ( tag );
		text = xmlDoc.createTextNode ( Global::qsTempPath );
		tag.appendChild ( text );

		tag = xmlDoc.createElement   ( DVDAUTHOR_PROJECT_PATH );
		rootDVDAuthor.appendChild    ( tag );
		text = xmlDoc.createTextNode ( Global::qsProjectPath );
		tag.appendChild ( text );

		if ( m_pSubtitlesGui ) {
		  Subtitles *pSubtitles = m_pSubtitlesGui->getSubtitles ();
		  if ( pSubtitles ) 
		       pSubtitles->writeProjectFile ( rootDVDAuthor );
		}
	// Here we write the SourceFileEntry - records ...
	int t;
	for (t=0;t<m_pSourceToolbar->sourceFileCount();t++)	
		m_pSourceToolbar->sourceFileEntry(t)->writeProjectFile ( rootDVDAuthor, m_bAutosaving );
		
	return true;
}

void QDVDAuthor::fileSave()
{
	// Here we check if the user is stil using the default filename ...
	if (Global::qsProjectFileName == QString (PROJECT_FILENAME))
		return fileSaveAs();
	// first we save the current project
	fileSave (Global::qsProjectFileName);
	// Then we save the same info again as autosave, so that in case of a crash we are up to date.
	slotAutosave ();
	// Now we handle the preview - pixmap of the Recent drop down menu ...
	updateHistoryPix();
	m_bModified = false;
	return;
}

void QDVDAuthor::fileSave(QString qsFileName)
{
	uint t;
	QFile projectFile(qsFileName);
	if (!projectFile.open(IO_WriteOnly))
		return;

	QFileInfo fileInfo ( qsFileName );
	QFileInfo autoInfo ( AUTOSAVE_FILE_NAME );

	if ( fileInfo.fileName () != autoInfo.fileName () )
	  setCaption ( QString ("'Q' DVD-Author :<%1> %2").arg( Global::qsProjectName ).arg( fileInfo.fileName ()) );

	QDomDocument xmlDoc( XML_DOCTYPE );
	QDomElement mainElement = xmlDoc.createElement( DVD_PROJECT );
	xmlDoc.appendChild ( mainElement );
	// First we store the data from the QDVDAuthor - class
	writeProjectFile   ( mainElement );

	// next in line is the VMGMenu - class
	m_pVMGMenu->writeProjectFile (mainElement);

	// And lastly we store the infos in all SubMenus ...
	for (t=0;t<m_listDVDMenus.count();t++) 
		m_listDVDMenus[t]->writeProjectFile(mainElement); 
	//QString xml = xmlDoc.toString();
	//printf ("%s\n", (const char *)xml);
	/** 
	 * Write the file as a stream 
	 */ 
	QTextStream ofs(&projectFile); 
	ofs.setEncoding( QTextStream::UnicodeUTF8 ); 
	// header is needed to support special characters 
	ofs << "<?xml version=\"1.0\" encoding=\""  
	<< ofs.codec()->name()  
	<< "\"?>\n"; 
	ofs << xmlDoc.toString().ascii(); 
	projectFile.close();
}

void QDVDAuthor::fileSaveAs()
{
	QString qsProjectFileName = QFileDialog::getSaveFileName(Global::qsCurrentPath, tr ("Project Files (*.xml)"), this, tr("Save file dialog"), tr("Save File As ..."));
	if (qsProjectFileName.isNull ())
		return;

	QFileInfo fileInfo(qsProjectFileName);
	QString qsPath = fileInfo.dirPath ( TRUE );
	Global::qsCurrentPath = qsPath;
	// Here we check if the user wants to use unnamed.xml -the default-
	// In this case we change the name slightly, so we have a clue it has bee initialized.
	if (fileInfo.fileName() == QString (PROJECT_FILENAME))
		qsProjectFileName = fileInfo.filePath() + QString ("unnamed.xml");

	Global::qsProjectFileName = qsProjectFileName;
	m_bModified = true;

	fileInfo = QFileInfo(qsProjectFileName);
	if (fileInfo.extension(FALSE).isEmpty())	// Indication there is no extension ...
		Global::qsProjectFileName += QString (".xml");

	fileSave();
}

QString QDVDAuthor::getImageFilter ()
{
	return QString("*.jpg *.jpeg *.png *.xbm *.bmp *.JPG *.JPEG *.PNG *.XBM *.BMP");
}

QString QDVDAuthor::getMovieFilter ()
{
	return QString ("*.mpg *.mpeg *.avi *.mwa *.mov *.wma *.vro *.vob *.m2v *.dv *.wmv *.mjpeg *.mve *.asf *.asx *.MPG *.MPEG *.AVI *.MWA *.MOV *.WMA *.VRO *.VOB *.M2V *.DV *.WMV *.MJPEG *.MVE *.ASF *.ASX");
}

QString QDVDAuthor::getSoundFilter ()
{
	return QString("*.wav *.mp3 *.mp2 *.mpa *.mpega *.ogg *.ac3 *.WAV *.MP3 *.MP2 *.MPA *.MPEGA *.OGG *.AC3");
}
