/****************************************************************************
** qdvdauthor.h file.
**
**   Created :
**        by : Varol Okan
** Copyright : (c) Varol Okan
**   License : GPL v 2.0
**
** 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 <stdlib.h>

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

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

#include "win32.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 "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 "dvdlayoutgui.h"
#include "templatedownload.h"
#include "dialogconvert.h"
#include "dialoglibrary.h"
#include "oneclickwizard.h"
#include "xml_slideshow.h"
#include "dialogregion.h"
#include "slidedefaults.h"
#include "dialogundostack.h"

#include "render_client.h"
#include "plugins/interface.h"
#include "plugins/menuslide/menuslide.h"

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


QDVDAuthor::QDVDAuthor ()
{
  Global::pApp = this;
  Utils theUtils;
  // Init the variables
  m_bAutosaving          = false;
  m_bModified            = false;
  m_bWait                = false;
  m_bCreateDVDAfterSlideshows = false;
  m_pVMGMenu             = NULL;
  m_pTranslator          = NULL;
  m_pLanguagePopup       = NULL;
  m_pTabsPopup           = NULL;
  m_pPluginsPopup        = NULL;
  m_pStylesPopup         = NULL;
  m_pTimerAutosave       = NULL;
  m_pDialogExecute       = NULL;
  m_pDialogLibrary       = NULL;
  m_pTemplateWizard      = NULL;
  m_pSubtitlesGui        = NULL;
  m_pDVDLayoutGui        = NULL;
  m_pPluginInterface     = NULL;
  m_pUndoStackDialog     = NULL;
  m_mainTabBuffer[0]     = NULL;
  m_mainTabBuffer[1]     = NULL;
  m_mainTabBuffer[2]     = NULL;
  m_pToolbar             = 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 since the destructor of the Widget takes care of this ...
  if ( Global::pSlideDefaults )
    delete Global::pSlideDefaults;
  Global::pSlideDefaults = NULL;

  if ( m_pSubtitlesGui )
    delete m_pSubtitlesGui;
  m_pSubtitlesGui = NULL;

  delete m_pSourceToolbar;
  m_pSourceToolbar = NULL;

  if ( m_pDialogExecute )
      delete m_pDialogExecute;
  m_pDialogExecute = NULL;

  if ( m_pDialogLibrary )
      delete m_pDialogLibrary;
  m_pDialogLibrary = NULL;

  for (t=0;t<Global::listToolsPaths.count();t++)
      delete Global::listToolsPaths[t];
  Global::listToolsPaths.clear ( );

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

  m_iAutosave = 0;
  setAutosave ( );  // Note : must be done AFTER calling SaveIni () ...

  if ( m_pUndoStackDialog )
    delete m_pUndoStackDialog;

  if ( m_pVMGMenu )
       m_pVMGMenu->createStructure     ( NULL );
  for ( t=0; t<m_listDVDMenus.count  ( ); t++ )
    m_listDVDMenus[t]->createStructure ( NULL );

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

  // Clear the static data stored in DIalogFiles.
  Input::DialogFiles::clearMapOfChange ( );

  delete m_pActionToolbarNew;
  delete m_pActionToolbarWizard;
  delete m_pActionToolbarOpen;
  delete m_pActionToolbarSave;
  delete m_pActionToolbarSaveAs;
  delete m_pActionToolbarExit;
  delete m_pToolbar;
  delete m_pStructureToolbar;

  // Just for good measure ...
  Global::listToolsPaths.clear ( );
}

void QDVDAuthor::initMe ( )
{
  setDockMenuEnabled ( false );
  // Manually create the MenuHistory popup - menu.
  m_pToolbar             = new QToolBar   ( "", this, DockTop );
  m_pMenuHistory         = new QPopupMenu ( this );
  Global::pSlideDefaults = new SlideDefaults;
  // 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 );

  initTabs      ( );  // Must be befroe LoadIni
  LoadIni       ( );
  initPlugins   ( );
  initLanguages ( );
  initStyles    ( );

  // 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   ( "SourceToolBar",    this );
  m_pStructureToolbar = new StructureToolBar( m_pSourceToolbar );
  m_pColorToolbar     = new ColorToolBar    ( "ColorToolBar",     this );

  // Here we assign the larger icons for the toolbar
  QImage  image;
  QPixmap pix;

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

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

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

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

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

  image = QImage::fromMimeSource ( "to_dvd.png" ).smoothScale ( 22, 22 );
  pix.convertFromImage ( image );
  QIconSet iconCreateDVD = QIconSet ( pix );
  m_pActionCreateDVD->setIconSet ( iconCreateDVD );

  m_pActionToolbarNew    = new QAction ( this, "actionNew"    );
  m_pActionToolbarWizard = new QAction ( this, "actionWizard" );
  m_pActionToolbarOpen   = new QAction ( this, "actionOpen"   );
  m_pActionToolbarSave   = new QAction ( this, "actionSave"   );
  m_pActionToolbarSaveAs = new QAction ( this, "actionSaveAs" );
  m_pActionToolbarExit   = new QAction ( this, "actionExit"   );

  m_pActionToolbarNew   ->setIconSet ( QIconSet ( QPixmap::fromMimeSource ( "new.png"     ) ) );
  m_pActionToolbarWizard->setIconSet ( QIconSet ( QPixmap::fromMimeSource ( "wizard.png"  ) ) );
  m_pActionToolbarOpen  ->setIconSet ( QIconSet ( QPixmap::fromMimeSource ( "open.png"    ) ) );
  m_pActionToolbarSave  ->setIconSet ( QIconSet ( QPixmap::fromMimeSource ( "save.png"    ) ) );
  m_pActionToolbarSaveAs->setIconSet ( QIconSet ( QPixmap::fromMimeSource ( "save_as.png" ) ) );
  m_pActionToolbarExit  ->setIconSet ( QIconSet ( QPixmap::fromMimeSource ( "exit.png"    ) ) );

  m_pActionToolbarNew   ->setText ( tr ( "New Project" ) );
  m_pActionToolbarWizard->setText ( tr ( "Project Wizard" ) );
  m_pActionToolbarOpen  ->setText ( tr ( "Open Project" ) );
  m_pActionToolbarSave  ->setText ( tr ( "Save" ) );
  m_pActionToolbarSaveAs->setText ( tr ( "Save As" ) );
  m_pActionToolbarExit  ->setText ( tr ( "Exit" ) );

  //  m_pToolbar = new QToolBar ( QString(""), this, DockTop );
  m_pActionToolbarNew->addTo    ( m_pToolbar );
  m_pActionToolbarWizard->addTo ( m_pToolbar );
  m_pActionToolbarOpen->addTo   ( m_pToolbar );
  m_pActionToolbarSave->addTo   ( m_pToolbar );
  m_pActionToolbarSaveAs->addTo ( m_pToolbar );
  m_pActionToolbarExit->addTo   ( m_pToolbar );
  m_pToolbar->addSeparator      ( );

  // Here we assign the icons to the actions ...
  fileNewAction->setIconSet     ( iconNew    );
  fileOpenAction->setIconSet    ( iconOpen   );
  fileSaveAction->setIconSet    ( iconSave   );
  fileSaveAsAction->setIconSet  ( iconSaveAs );
  fileExitAction->setIconSet    ( iconExit   );

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

  m_pActionAddFiles->setEnabled     ( false ); // for now disable as I dont want to implement
  m_pActionAddDirectory->setEnabled ( false ); // this for now.

  QActionGroup *pGroup = new QActionGroup ( this );
  pGroup->add ( m_pActionZoneAll );
  pGroup->add ( m_pActionZone1 );
  pGroup->add ( m_pActionZone2 );
  pGroup->add ( m_pActionZone3 );
  pGroup->add ( m_pActionZone4 );
  pGroup->add ( m_pActionZone5 );
  pGroup->add ( m_pActionZone6 );
  connect (pGroup, SIGNAL ( selected ( QAction * ) ), this, SLOT ( slotZone ( QAction * ) ) );

  connect (m_pActionToolbarNew,      SIGNAL (activated()),  this, SLOT ( fileNew    ( ) ) );
  connect (m_pActionToolbarWizard,   SIGNAL (activated()),  this, SLOT ( slotOneClickDVD( ) ) );
  connect (m_pActionToolbarOpen,     SIGNAL (activated()),  this, SLOT ( fileOpen   ( ) ) );
  connect (m_pActionToolbarSave,     SIGNAL (activated()),  this, SLOT ( fileSave   ( ) ) );
  connect (m_pActionToolbarSaveAs,   SIGNAL (activated()),  this, SLOT ( fileSaveAs ( ) ) );
  connect (m_pActionToolbarExit,     SIGNAL (activated()),  this, SLOT ( fileExit   ( ) ) );

  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_pActionVersions,        SIGNAL ( activated()), this, SLOT ( slotVersions         ( ) ) );
  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_pActionZoneSelect,      SIGNAL ( activated()), this, SLOT ( slotSelectZone       ( ) ) );
  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 ( );
  initDVDLayoutTab  ( );
  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::customEvent ( QCustomEvent *pEvent )
{
  if ( pEvent->type ( ) == EVENT_RENDER_PROGRESS )  {
    Render::Client *pClient = (Render::Client *)pEvent->data ( );
    SourceFileEntry *pEntry =  pClient->sourceFileEntry      ( );
    m_pSourceToolbar->setRenderProgress ( pEntry, pClient->progress ( ) );
  }
  else if ( pEvent->type ( ) == EVENT_RENDER_EXCEPTION )  {
//    Render::Client *pClient = (Render::Client *)pEvent->data ( );

  }
  else if ( pEvent->type ( ) == EVENT_RENDER_EXIT )  {
    Render::Client *pClient = (Render::Client *)pEvent->data ( );
    if ( pClient->sourceFileEntry ( ) )
      eventEntry ( pClient );
    else if ( pClient->buttonTransition ( ) )
      eventTrans ( pClient );
  }
//printf ( "QDVDAuthor::customEvent  : <%X> Event <%d> Client<%p>\n", (unsigned)pthread_self ( ), pEvent->type ( ), pEvent->data ( ) );
}

void QDVDAuthor::eventEntry ( Render::Client *pClient )
{
  SourceFileEntry *pEntry =  pClient->sourceFileEntry ( );
  Render::Manager::unregisterEntry ( pEntry );
  if ( ! m_pSourceToolbar->sourceFileEntryExists ( pEntry ) )  {
    // What to do and how ?? Search all SourceFileInfo's ???
  }
  else  {
    pEntry->bIsSlideshow    = false;
    SourceFileInfo *pInfo   = pEntry->listFileInfos[0];
    if ( pInfo  &&  pInfo->pSlideshow )
         m_pSourceToolbar->slideshowDone ( pEntry );
    m_pSourceToolbar->setRenderProgress  ( pEntry, -1.0 );

    Cache::Thumbs::Entry *pCache = Global::pThumbsCache->find ( pInfo->qsFileName );
    if ( ! pCache )
      Global::pThumbsCache->append ( pInfo->qsFileName, this );
  }
  // Lasty we check if we have all our slideshows in a row.
  if ( m_bCreateDVDAfterSlideshows )  {
    int t;
    for ( t=0 ;t<sourceFileCount ( ); t++ )  {
      SourceFileEntry *pEntry = sourceFileEntry ( t );
      if ( pEntry->bIsSlideshow )
           return;
    }
    // At this point we are engaged to create the DVD and
    // all Slideshows seem to exist.
    engageCreateDVD ( false );
    slotCreateDVD   ( );
  }
}

void QDVDAuthor::eventTrans ( Render::Client *pClient )
{
  ButtonTransition *pTrans = pClient->buttonTransition ( );
  if ( ! buttonTransitionExists ( pTrans ) )  {
    // What to do and how ?? Search all SourceFileInfo's ???
  }
  else  {
    Render::Manager::unregisterTrans ( pTrans );
    pTrans->bFinishedRendering = true;
    slotAutosave ( );
//printf ( "%s::%d > Finished rendering ButtonTransition<%s> <%s>\n", __FILE__, __LINE__, pTrans->qsName.ascii ( ), pTrans->qsTransitionVideoFileName.ascii () );
  }
}

bool QDVDAuthor::buttonTransitionExists ( ButtonTransition *pTrans )
{
  if ( ! pTrans )
    return false;

  // Based on the pointer itself ...
  QValueList<ButtonObject *> buttonList;
  QValueList<DVDMenu      *> menuList = getSubMenus ( );
  QValueList<DVDMenu       *>::iterator itMenu = menuList.begin ( );
  QValueList<ButtonObject *>::iterator it;

  DVDMenu *pMenu = getVMGMenu ( );
  do  {
    buttonList = pMenu->getButtons( );
    it = buttonList.begin ( );
    while (  it != buttonList.end ( ) )  {
      if ( (*it++)->getTransition ( ) == pTrans )
        return true;
    }
    pMenu = *itMenu++;
  } while (  itMenu != menuList.end ( ) );
  return false;
}

void QDVDAuthor::showUndoStack ( )
{
  if ( ! m_pUndoStackDialog )
         m_pUndoStackDialog = new DialogUndoStack ( getUndoBuffer ( ) );

  // This function will call the Undo - stack GUI of the current menu
  DVDMenu *pMenu = getCurrentSubMenu ( );
  if   ( ! pMenu )  {
    m_pUndoStackDialog->setUndoBuffer ( NULL );
    return;
  }
  m_pUndoStackDialog->setUndoBuffer ( pMenu->getUndoBuffer ( ) );
  m_pUndoStackDialog->show          ( );
  m_pUndoStackDialog->raise         ( );
}

void QDVDAuthor::updateUndoStack ( )
{
  if ( ! m_pUndoStackDialog )
    return;

  if ( ! m_pUndoStackDialog->isVisible ( ) )
    return;

  // This function will call the Undo - stack GUI of the current menu
  DVDMenu *pMenu = getCurrentSubMenu ( );
  if   ( ! pMenu )  {
    m_pUndoStackDialog->setUndoBuffer ( NULL );
    return;
  }

  m_pUndoStackDialog->setUndoBuffer ( pMenu->getUndoBuffer ( ) );
}

bool QDVDAuthor::tabVisible ( enTabs tab )
{
  if ( tab == TabDVDLayout )
    return m_pTabsPopup->isItemChecked ( m_pTabsPopup->idAt ( 0 ) );
  else if ( tab == TabSubtitles )
    return m_pTabsPopup->isItemChecked ( m_pTabsPopup->idAt ( 1 ) );
  else if ( tab == TabDVDAuthorXml )
    return m_pTabsPopup->isItemChecked ( m_pTabsPopup->idAt ( 2 ) );
  return true;
}

QWidget *QDVDAuthor::getTabWidget ( enTabs tab, int iSubMenu )
{
  int iNrOfTabs = m_pTabWidgetMain->count ( );

  // The Main Menu is always on tab 1.
  if ( tab == TabMainMenu )
    return m_pTabWidgetMain->page ( 0 );
  else if ( ( tab == TabSubMenu ) && ( iSubMenu < iNrOfTabs ) )
    return m_pTabWidgetMain->page ( iSubMenu );
  else if ( tab == TabDVDLayout )  {
    if ( m_mainTabBuffer[0] )
      return m_mainTabBuffer[0];
    return m_pTabWidgetMain->page ( iNrOfTabs - 3 );
  }
  else if ( tab == TabSubtitles )  {
    if ( m_mainTabBuffer[1] )
      return m_mainTabBuffer[1];
    return m_pTabWidgetMain->page ( iNrOfTabs - 2 );
  }
  else if ( tab == TabDVDAuthorXml )  {
    if ( m_mainTabBuffer[2] )
      return m_mainTabBuffer[2];
    return m_pTabWidgetMain->page ( iNrOfTabs - 1 );
  }
  return NULL;
}

void QDVDAuthor::initSubtitlesTab ( )
{
  QWidget *pWidget = getTabWidget ( TabSubtitles );
  if ( ! pWidget )
    return;
  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::initDVDLayoutTab ( )
{
  QWidget *pWidget = getTabWidget ( TabDVDLayout );
  if ( ! pWidget )
    return;
  QGridLayout *pLayout = new QGridLayout  ( pWidget );
  m_pDVDLayoutGui      = new DVDLayout::Gui ( pWidget );
  pLayout->addWidget ( m_pDVDLayoutGui, 0, 0 );
  m_pTabWidgetMain->setTabLabel    ( pWidget, tr ( "DVD Layout" ) );
  m_pTabWidgetMain->setCurrentPage ( 0 );
}

void QDVDAuthor::initTabs ( )
{
  if ( m_pTabsPopup )
    delete m_pTabsPopup;
  m_pTabsPopup = new QPopupMenu ( this );
  m_pTabsPopup->setCheckable    ( true );
  tools->insertItem ( toolsLanguagesAction->iconSet ( ), tr ( "Tabs" ), m_pTabsPopup );

  QAction *pActionTabs;

  pActionTabs = new QAction ( this, "Layt" );
  pActionTabs->setMenuText  ( "DVD Layout" );
  pActionTabs->addTo        ( m_pTabsPopup );

  pActionTabs = new QAction ( this, "Subs" );
  pActionTabs->setMenuText  (  "Subtitles" );
  pActionTabs->addTo        ( m_pTabsPopup );

  pActionTabs = new QAction ( this, "Xmlo" );
  pActionTabs->setMenuText  ( "XML output" );
  pActionTabs->addTo        ( m_pTabsPopup );

  m_mainTabBuffer[0] = getTabWidget ( TabDVDLayout    );
  m_mainTabBuffer[1] = getTabWidget ( TabSubtitles    );
  m_mainTabBuffer[2] = getTabWidget ( TabDVDAuthorXml );

  connect ( m_pTabsPopup, SIGNAL ( activated ( int ) ), this, SLOT ( slotEnableTabs ( int ) ) );
}

void QDVDAuthor::initPlugins ( )
{
  //  uint t;
  Utils theUtils;
  // Here we search the required directory for translation files and set the menu items 
  // under 'Tools->Plugin'
  QDir theFiles ( Global::qsSystemPath ); // e.g. /usr/local
  bool bReturn = theFiles.cd ( Global::qsSystemPath + "/share/qdvdauthor/plugins" );

  theFiles.setFilter ( QDir::Dirs );
  QStringList listFiles = theFiles.entryList ( );

  // Here we create the sub-menu for the additional languafges ...
  if ( m_pPluginsPopup )
    delete m_pPluginsPopup;
  m_pPluginsPopup = new QPopupMenu ( this );
  m_pPluginsPopup->setCheckable    ( true );
  tools->insertItem( toolsLanguagesAction->iconSet(), tr( "Plugins" ), m_pPluginsPopup );
  QAction *pActionPlugin = new QAction ( this, "plugins" );
  pActionPlugin->setText     ( "Menu Slideshow ..." );
  pActionPlugin->setMenuText ( "Menu Slideshow ..." );
  pActionPlugin->addTo       (    m_pPluginsPopup   );

  if ( bReturn ) {
  /*
    // pActionLanguage->setOn ( true );

    for (t=0;t<listFiles.count();t++)	{
      if ( ( listFiles[t] == "." ) || ( listFiles[t] == "..") )
        continue;
      // First we try to extract the language ...
      pActionPlugin = new QAction (this, QString ("plugin%1").arg(t));
      pActionPlugin->setText( "Something" );
      pActionPlugin->setMenuText( "Something" );
      pActionPlugin->addTo( m_pPluginsPopup );
    }
  */
  }
  connect( m_pPluginsPopup, SIGNAL ( activated ( int ) ), this, SLOT( slotActivatePlugin ( int ) ) );
}

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 ( Global::qsSystemPath ); // e.g. /usr/local
	theFiles.cd ( Global::qsSystemPath + "/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::slotActivatePlugin ( )
{
  slotActivatePlugin ( 0 );
}

void QDVDAuthor::slotActivatePlugin ( int )
{
  // Test for now hard linked against QDVDAuthor.
  // Later to be linked at runtime through usage of dlopen ()
  if ( ! m_pPluginInterface ) {
    m_pPluginInterface = new Plugin::MenuSlideInterface;
    // register callback through slot mechanism ...
    connect ( m_pPluginInterface, SIGNAL ( signalNewMenuResponse ( int, QString, QString  ) ), this, SLOT ( slotPluginCallback ( int, QString, QString ) ) );
  }
  m_pPluginInterface->execute ( );
}

void QDVDAuthor::slotPluginCallback ( int iType, QString qsMenuName, QString qsXMLDVDMenu )
{
  //printf ( "Create Menu [%d]<%s>\n", iType, qsXMLDVDMenu.ascii ( ) );
  QDomDocument domDoc;
  QDomElement  menuElement;
  QString      qsError;
  DVDMenu     *pDVDMenu;
  int iRow, iCol;
  Plugin::SourceGroup::type enType = (Plugin::SourceGroup::type)iType;
  enType = enType;

  QCursor myCursor ( QCursor::WaitCursor );
  setCursor ( myCursor );

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

  pDVDMenu = new DVDMenu ( this );
  qsMenuName = getUniqueMenuTitle ( qsMenuName, 0 );
  pDVDMenu->readProjectFile ( menuElement, 1.0f );
  pDVDMenu->getInterface    ( )->qsMenuName = qsMenuName;
  pDVDMenu->setTabLabel     ( qsMenuName );
  pDVDMenu->updateDVDMenu   ( );
  addDVDMenu ( pDVDMenu );

  slotAutosave        ( );
  slotUpdateStructure ( );

  myCursor = QCursor ( QCursor::ArrowCursor );
  setCursor ( myCursor );
}

void QDVDAuthor::slotEnableTabs ( int iID )
{
  QString  qsTab;
  QWidget *pWidget  = NULL;
  int  iIndexAddTab = -1;
  int  iIndexOfID   =  m_pTabsPopup->indexOf       ( iID );
  bool bChecked     = !m_pTabsPopup->isItemChecked ( iID );
  int  iNrOfTabs    = m_pTabWidgetMain->count ( );
  m_pTabsPopup->setItemChecked  ( iID, bChecked );

  // Get the enabled/disabled state from the Menu
  bool bSubtitle = m_pTabsPopup->isItemChecked ( m_pTabsPopup->idAt ( 1 ) );
  bool bXMLOut   = m_pTabsPopup->isItemChecked ( m_pTabsPopup->idAt ( 2 ) );

  switch ( iIndexOfID )  {
  case 0:  // DVD Layout
    iIndexAddTab = iNrOfTabs  - ( bXMLOut ? 1 : 0 ) - ( bSubtitle ? 1 : 0 );
    pWidget      = getTabWidget ( TabDVDLayout );
    qsTab        = tr ( "DVD Layout" );
  break;
  case 1: // Subtitles
    iIndexAddTab = iNrOfTabs  - ( bXMLOut ? 1 : 0 );
    pWidget      = getTabWidget ( TabSubtitles );
    qsTab        = tr ( "SubPictures (Subtitles)" );
    if ( m_pSubtitlesGui )
         m_pSubtitlesGui->releaseSourceFileInfo ( );
  break;
  case 2: // XML output
    iIndexAddTab = -1;
    pWidget      = getTabWidget ( TabDVDAuthorXml );
    qsTab        = tr ( "XML out" );
  break;
  }

  if ( pWidget )  {
    if ( bChecked )
      m_pTabWidgetMain->insertTab  ( pWidget, qsTab, iIndexAddTab );
    else
      m_pTabWidgetMain->removePage ( pWidget );
  }
  SaveIni ( );
}

void QDVDAuthor::slotChangeLanguage ( int iID )
{
  // The first thing is to co-relate the ID to the language ...
  QString qsID  ( "en" );  // Default = english
  QDir theFiles ( Global::qsSystemPath ); // e.g. /usr/local
  theFiles.cd   ( Global::qsSystemPath + "/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 ( Global::qsSystemPath + "/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 ( );
  VMGMenu *pVMGM = (VMGMenu *)getVMGMenu ( );
  if ( pVMGM )
       pVMGM->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::addDroppedSource ( QString qsText )
{
  QStringList list;
  qsText.remove ( "file://" );
  list.append   ( qsText );
  QFileInfo fileInfo ( qsText );
  QString qsExt = fileInfo.extension ( FALSE );
  QString qsMovieFilter = getMovieFilter   ( );
  if ( qsMovieFilter.find  ( qsExt ) > -1 )
    m_pSourceToolbar->addMovieList ( list );
}

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::editSourceFileInfo ( SourceFileInfo *pInfo )
{
  m_pSourceToolbar->editSourceFileInfo ( pInfo );
}

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

void QDVDAuthor::updateStatusColor ( )
{
  m_pSourceToolbar->updateStatusColor ( );
}

void QDVDAuthor::updateDVDLayout ( SourceFileEntry *pEntry )
{
  if ( m_pDVDLayoutGui )
       m_pDVDLayoutGui->updateEntry ( pEntry );
}

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

void QDVDAuthor::setColor ( uint iWhichColor, Rgba 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) and when importing a dvdauthor.xml file
  m_pSourceToolbar->appendSourceFileEntry ( pSourceFileEntry, true );
}

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;

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

  if ( m_pDVDLayoutGui )
       m_pDVDLayoutGui->refresh ( );
}

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 && 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;
	if ( m_pVMGMenu )	
	     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::slotUpdateDVDLayout ( )
{
  if ( m_pDVDLayoutGui )
       m_pDVDLayoutGui->refresh ( );
}

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

  // Create or return the first item
  pMainItem = m_pStructureToolbar->clean ( true );

  if ( m_pVMGMenu )
       m_pVMGMenu->createStructure     ( pMainItem );
  for ( t=0; t<(int)m_listDVDMenus.count  ( ); t++ )
    m_listDVDMenus[t]->createStructure ( pMainItem );

  slotUpdateMenuBar   ( );
  slotUpdateDVDLayout ( );
}

void QDVDAuthor::slotUndoStack ()
{
  showUndoStack ( );

//  // 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 )
    return;

  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 ) || ( qsNewName.isEmpty ( ) ) )
    return;

  if ( pMenu && ( qsSubMenuName != qsNewName ) )
    replaceMenuName ( pMenu, qsNewName );
}

void QDVDAuthor::replaceMenuName ( DVDMenu *pMenu, QString &qsNewName )
{
  UndoBuffer *pBuffer = pMenu->getUndoBuffer ( );
  if ( pBuffer )
       pBuffer->push ( new DVDMenuUndoObject ( DVDMenuUndoObject::EDIT_MENU, pMenu ) );

  if ( pMenu )  {
    QString qsSubMenuName = pMenu->getInterface ( )->qsMenuName;
    pMenu->getInterface ( )->qsMenuName = qsNewName;
    m_pTabWidgetMain->setTabLabel ( m_pTabWidgetMain->currentPage ( ), qsNewName );
    if ( m_pVMGMenu )
         m_pVMGMenu->replaceMenuName ( qsSubMenuName,  qsNewName );
    for ( unsigned int t=0; t<m_listDVDMenus.count ( ); t++ )
        m_listDVDMenus[t]->replaceMenuName ( qsSubMenuName, qsNewName );
  }
  slotUpdateStructure ( );
}

void QDVDAuthor::slotCloneCurrentSubMenu ()
{
  // Here we remove the current SubMenu ...
  bool bVMGM = false;
  DVDMenu *pMenu, *pOrigMenu = getCurrentSubMenu ( );
  if ( ! pOrigMenu )
    return;

  pMenu  = pOrigMenu->clone ( );
  pMenu->getInterface ( )->iTitleset = -1;
  pMenu->getInterface ( )->iMenu     = -1;

  if ( pMenu->getInterface ( )->qsMenuName == QString ( VMGM_LABEL ) ) {
    bVMGM = true;
    QString qsNewTitle = tr ( "Cloned VMGM" );
    pMenu->getInterface ( )->qsMenuName = qsNewTitle;
    m_pTabWidgetMain->setTabLabel ( m_pTabWidgetMain->currentPage ( ), qsNewTitle );
  }

  addDVDMenu ( pMenu );

  // Adjust buttons in the new menu who pointed to the menu itself, 
  // to point now to the new sub-menu.
  QString qsNewName = pMenu    ->getInterface ( )->qsMenuName;
  QString qsOldName = pOrigMenu->getInterface ( )->qsMenuName;
//  if ( bVMGM )
//       pMenu = (DVDMenu *)m_pVMGMenu;
  pMenu->replaceMenuName ( qsOldName, qsNewName );
  slotUpdateStructure ( );
  updateUndoStack     ( );
}

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


void QDVDAuthor::slotDeleteTempOlderThan ()
{
	// This function will check if there is outdated Temp data which ought to be deleted.
	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 temporary data."), 
			tr ( "Attention, I found some temporary 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 temporary 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
  if ( ! pWidget )
    return;

  int t, i, j;
  if ( pWidget == getTabWidget ( TabMainMenu ) )  {
    DVDMenu *pMenu = getCurrentSubMenu ( );
    if ( pMenu )  {
      m_pColorToolbar->setDVDMenu ( pMenu );
    }
  }
  // The last tab is the one to dispaly the XML code
  else if ( pWidget == getTabWidget ( TabDVDAuthorXml ) )  {
    if ( ! m_pVMGMenu )
      return;
    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 ) {
	  QFileInfo fileInfo ( pInfo->qsFileName );
	  for ( j=0;j<MAX_SUBTITLES; j++ ) {
	    if ( pInfo->arraySubtitles [ j ] ) {
	      QString qsSpumuxFile;
	      qsSpumuxFile.sprintf ("%s_sub%02d.xml", fileInfo.baseName ( ).ascii ( ), pInfo->arraySubtitles[j]->m_iSubtitleNumber );
	      m_pComboSource->insertItem ( qsSpumuxFile );
	    }
	  }
	}
      }
    }

    m_pTextEditXml->clear();
    for (uint t=0;t<m_listDVDMenus.count();t++)
      m_pComboSource->insertItem(m_listDVDMenus[t]->name());
  }
  else if ( pWidget == getTabWidget ( TabSubtitles ) )  {
    // the Subtitles - tab.
    //    if ( m_pSubtitlesGui )
    //         m_pSubtitlesGui->grabKeyboard ( );
  }
  else if ( pWidget == getTabWidget ( TabDVDLayout ) )  {
    // Need to kick off timer to re-generate the screenshots for the DVDMenus
    if ( m_pDVDLayoutGui )
         m_pDVDLayoutGui->refreshMenus ( );
  }
  // Otherwise it must be a submenu
  else  {
    DVDMenu *pMenu = getCurrentSubMenu ( );
    if ( pMenu )
      m_pColorToolbar->setDVDMenu ( pMenu );
  }
  slotUpdateMenuBar ( );

  if ( m_pUndoStackDialog && m_pUndoStackDialog->isVisible ( ) )
       showUndoStack ( );
}

void QDVDAuthor::createContextMenu ( SourceFileEntry *pEntry, QPoint &thePoint )
{
  if ( m_pSourceToolbar )
       m_pSourceToolbar->createContextMenu ( pEntry, thePoint );
}

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 ( ); // deletes VMGMenu and re-creates it.
  listOfSubMenus          = pImporter->takeDVDMenus ( );
  listOfSourceFileEntries = pImporter->takeSourceFileEntries ( );

  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 );
  m_pActionUndoStack->setEnabled( false );
  editCutAction->setEnabled     ( false );
  editCopyAction->setEnabled    ( false );
  editPasteAction->setEnabled   ( false );

  if ( ! pMenu )
    return;

  editCutAction->setEnabled     ( true );
  editCopyAction->setEnabled    ( true );
  editPasteAction->setEnabled   ( true );
  m_pActionUndoStack->setEnabled( true );

  // 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;
  theExporter.exportXml ( );
}

void QDVDAuthor::slotFeedback ()
{
  Utils theUtils;
  // First let us  make sure the temp dir exists...
  getTempFile ( QString() );
  // then let us collect some feedback data 
  QString qsFeedbackDir = Global::qsTempPath + QString ("/") + Global::qsProjectName + QString ("/feedback"); 
  QDir feedbackDir ( qsFeedbackDir );
  if ( ! feedbackDir.exists  ( ) )  {
	if ( ! theUtils.recMkdir ( qsFeedbackDir ) )
		return;
  }

  // Here we get the project file.
  slotAutosave ();
  QString qsBashName   = QString ("%1/feedback.sh").arg(Global::qsTempPath);
  QString qsBashScript = Global::qsBashString;
  qsBashScript += QString ( "mkdir %1/qrender" );
  qsBashScript += QString ( "find /tmp/qrender -name \"*.xml\" -exec cp {} %1/qrender/ \\;" );
  qsBashScript += QString ( "find /tmp/qrender -name \"*.txt\" -exec cp {} %1/qrender/ \\;" );
  qsBashScript += QString ("uname -a > %1/system.txt\n").arg( qsFeedbackDir );
  qsBashScript += QString ("procinfo >> %1/system.txt\n").arg( qsFeedbackDir );
  qsBashScript += QString ("mplayer -vo help -ao help >> %1/system.txt\n").arg( qsFeedbackDir );
  qsBashScript += QString ("echo PREFIX_DIRECTORY="PREFIX_DIRECTORY" >> %1/system.txt\n").arg( qsFeedbackDir );
  qsBashScript += QString ("echo SYSTEM_DIRECTORY="SYSTEM_DIRECTORY" >> %1/system.txt\n").arg( qsFeedbackDir );
  qsBashScript += QString ("echo Global::qsSystemPath="+ Global::qsSystemPath +" >> %1/system.txt\n").arg( qsFeedbackDir );
  qsBashScript += QString ("echo \"QDVDAuthorVersionNumber="QDVDAUTHOR_VERSION_NUMBER"\" >> %1/system.txt\n").arg ( qsFeedbackDir );
  qsBashScript += QString ("echo \"Build ("__DATE__")\" >> %1/system.txt\n").arg ( qsFeedbackDir );
  qsBashScript += QString ("cd \"%1/%2/\"\n").arg(Global::qsTempPath).arg(Global::qsProjectName);
  qsBashScript += QString ("cp \"%1/qrender/*.txt\" \"%2\"\n").arg ( Global::qsTempPath ).arg ( qsFeedbackDir );
  qsBashScript += QString ("cp ~/.qdvdauthor/*.ini \"%1\"\n").arg( qsFeedbackDir );
  qsBashScript += QString ("cp ~/.qdvdauthor/autosave.xml \"%1\"\n").arg( qsFeedbackDir );
  qsBashScript += QString ("cp \"%1\" \"%2\" 2> /dev/null\n").arg(Global::qsProjectFileName).arg( qsFeedbackDir );
  qsBashScript += QString ("find . > feedback/filelist_temp\n");
  qsBashScript += QString ("find " + Global::qsSystemPath + "/share/qdvdauthor > feedback/filelist_sys\n");
  qsBashScript += QString ("find $HOME/.qdvdauthor > feedback/filelist_home\n");
  //qsBashScript += QString ("find . -name \"*.xml\" -exec cp {} %1 \\;\n").arg ( qsFeedbackDir );
  //qsBashScript += QString ("find . -name \"*.txt\" -exec cp {} %1 \\;\n").arg ( qsFeedbackDir );
  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 ( qsBashName.utf8 ( ), S_IEXEC | S_IRUSR | S_IWRITE | S_IROTH | S_IWOTH | S_IXOTH );

  // And now execute the script ...
  if ( system (qsBashName) == -1 )
       return;
  MessageBox::information (NULL, tr ("Collected Feedback Data"),
      tr ("\nPlease email to: QDVDAuthor@users.sf.net and 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 ( StructureItem *pItem )
{
  if ( m_pVMGMenu )
       m_pVMGMenu->slotStructureClicked ( pItem );
}

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, qsFileName;
  float fPercentage;
  QFileInfo fileInfo;
  Utils theUtils;
  // 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];
      qsFileName = pInfo->getFileName ( );
      fileInfo.setFile ( qsFileName );

      if ( pInfo->pTranscodeInterface )  {
        int  iAudioBitrate = pInfo->pTranscodeInterface->iAudioBitrate;
        int  iVideoBitrate = pInfo->pTranscodeInterface->iVideoBitrate;
        long iDuration     = theUtils.getMsFromString ( pInfo->qsLength );

        if ( iDuration == 0 )  {
          if ( fileInfo.exists ( ) )
            iDVDSize += fileInfo.size ( );
          else  {
            fileInfo.setFile ( pInfo->qsFileName );
            iDVDSize += fileInfo.size ( );
          }
        }
        else
          iDVDSize += (int)( (float)iDuration / 1000.0f * ( iAudioBitrate + iVideoBitrate ) / 8.0f );
      }
      else  {
        if ( fileInfo.exists ( ) )
          iDVDSize += fileInfo.size ( );
        else {
          fileInfo.setFile ( pInfo->qsFileName );
          iDVDSize += fileInfo.size ( );
        }
      }
      iDVDSize += getAudioSize ( pInfo );
    }
  }

  fPercentage = (float)( (double)iDVDSize / (double)iMaxDVDSize );
  if ( fPercentage > 1.0 )  {
       iMaxDVDSize = (int)( 2.0 * iMaxDVDSize ); // switch to 8 GByte Dual layer DVDs
       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);
}

unsigned long QDVDAuthor::getAudioSize ( SourceFileInfo *pInfo )
{
  int t;
  Audio *pAudio = NULL;
  unsigned long iSize = 0;
  QFileInfo fileInfo;
  Utils theUtils;

  for ( t=0; t<MAX_AUDIO; t++ )  {
    if ( pInfo->arrayAudio[t] )  {
      pAudio = pInfo->arrayAudio[t];

      if ( pAudio->pTranscodeInterface )  {
        int  iAudioBitrate = pAudio->pTranscodeInterface->iAudioBitrate;
        int  iVideoBitrate = pAudio->pTranscodeInterface->iVideoBitrate;
        long iDuration     = theUtils.getMsFromString ( pInfo->qsLength );
        if ( iDuration == 0 )  {
          fileInfo.setFile ( pAudio->pTranscodeInterface->qsTempFile );
          if ( fileInfo.exists ( ) )
            iSize += fileInfo.size ( );
          else  {
            fileInfo.setFile ( pAudio->qsFileName );
            iSize += fileInfo.size ( );
          }
        }
        else
          iSize += (int)( (float)iDuration/1000.0f * ( iAudioBitrate + iVideoBitrate ) / 8.0f );
      }
      else  {
        fileInfo.setFile ( pAudio->qsFileName );
        iSize += fileInfo.size ( );
      }
    }
  }
  return iSize;
}

/*
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;
  QFileInfo fileInfo;
  // 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->pTranscodeInterface ) {
	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 / 2.0 ); // ( used to be * 1.2mBytes)
      }
      else {
	fileInfo.setFile ( pInfo->qsFileName );
	iDVDSize += fileInfo.size ( );
      }
    }
  }

  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::slotOneClickDVD ( )
{
  // this function will invoke the OneClickDVD wizard
  // the Wizard will collect data from the user input 
  // Video files, Slideshow info, etc.
  //
  // Next the plugin is called to actually generate 
  // SourceFileEntries and DVDMenus from this input.
  //
  ////////////////////////////////////////////////////
  // Last chance to keep previous data
  if ( ! cleanUp ( ) )
    return;

  Input::OneClickWizard magic ( this );
  if (   magic.initMe ( ) )  {
    if ( magic.exec   ( ) == QDialog::Accepted )  {
      m_bModified = true;
    }
  }
  else {
    MessageBox::warning ( NULL, tr ( "No Plugins found" ), 
      tr ( "No Plugins found to create a DVD through this wizard.\nFor information please check : http://qdvdauthor.sf.net\n\n" 
           "You can also try [ Tools -> Check Installation ... ]\n\n"
      ), QMessageBox::Ok, QMessageBox::NoButton );
  }
}

void QDVDAuthor::slotNewMenuResponse ( int iType, QString qsMenuName, QString qsXMLDVDMenu )
{
//printf ( "QDVDAuthor::slotNewMenuResponse <%s>\n", qsXMLDVDMenu.ascii ( ) );
  // Line 443 : slotPluginCallback ( iType, qsMenuName, qsXMLDVDMenu );
  QDomDocument domDoc;
  QDomElement  menuElement;
  QString      qsError;
  DVDMenu     *pDVDMenu;
  int  iRow,   iCol;
  bool bVMGM = false;
  Plugin::SourceGroup::type enType = (Plugin::SourceGroup::type)iType;
  enType = enType;

  QCursor myCursor ( QCursor::WaitCursor );
  setCursor ( myCursor );

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

  if ( qsMenuName.right ( 2 ) == " 1" )  {
    pDVDMenu   = new VMGMenu ( this );
    qsMenuName = VMGM_LABEL;
    delete m_pVMGMenu;
    m_pVMGMenu = NULL;
    bVMGM      = true;
  }
  else  {
    pDVDMenu = new DVDMenu ( this );
    qsMenuName = getUniqueMenuTitle ( qsMenuName, 0 );
  }
  pDVDMenu->readProjectFile ( menuElement, 1.0f );
  pDVDMenu->getInterface    ( )->qsMenuName = qsMenuName;
  pDVDMenu->setTabLabel     ( qsMenuName );
  pDVDMenu->updateDVDMenu   ( );
  addDVDMenu ( pDVDMenu,bVMGM );

  slotAutosave        ( );
  slotUpdateStructure ( );

  myCursor = QCursor ( QCursor::ArrowCursor );
  setCursor ( myCursor );
}

void QDVDAuthor::slotNewSource ( Plugin::SourceGroup *pGroup )
{
  // Coming from OneClickWizard
  if ( ! pGroup )
    return;

  if ( pGroup->bSlideshow )  {
    int iCount = 0;
    // Okay incoming slideshow ...
    CXmlSlideshow *pSlideshow    = new CXmlSlideshow;
    pSlideshow->slideshow_name   = pGroup->qsGroupName;
    pSlideshow->filter_delay     = (float)pGroup->iFilterLength / 1000.0f;
    pSlideshow->background       = pGroup->qsBackground;
    pSlideshow->audio_list       = pGroup->listAudio;
    pSlideshow->validFilterNames = pGroup->listFilter;

    Plugin::SourceGroup::SourceEntry *pEntry;
    CXmlSlideshow::img_struct        *pXmlImg;
    CXmlSlideshow::vid_struct        *pXmlVid;
    QValueList<Plugin::SourceGroup::SourceEntry *>::iterator it = pGroup->listFiles.begin ( );
    while ( it != pGroup->listFiles.end ( ) )  {
      pEntry = *it++;
      if ( pEntry->bVidSource )  {
        pXmlVid = pSlideshow->addVid ( );
        pXmlImg = (CXmlSlideshow::img_struct *)pXmlVid;
      }
      else  {
        pXmlImg = pSlideshow->addImg ( );
        Cache::Thumbs::ImageEntry *pCache = (Cache::Thumbs::ImageEntry *)Global::pThumbsCache->find ( pEntry->qsFileName, true );
        if ( pCache && pCache->pMatrix )
             pXmlImg->pMatrix = new QWMatrix ( *pCache->pMatrix );
      }
      pXmlImg->src       = pEntry->qsFileName;
      pXmlImg->fDuration = (float)pEntry->iLength / 1000.0f;
      if ( iCount == 0 )
        pSlideshow->delay = (float)pEntry->iLength / 1000.0f;
      iCount++;
    }
    pSlideshow->setImgBkgImg  ( ( pGroup->iFlags & 1 ) == 1 );
    pSlideshow->setKenBurns   ( ( pGroup->iFlags & 8 ) == 8 );
    pSlideshow->intro_page =  ( ( pGroup->iFlags & 2 ) == 2 );
    pSlideshow->yres = 480;
    if ( ( pGroup->iFlags & 4 ) == 4 )
       pSlideshow->yres = 576; // Set to PAL

    m_pSourceToolbar->entryFromSlideshow ( pSlideshow );
  }
  else  {
    QStringList list;

    QValueList<Plugin::SourceGroup::SourceEntry *>::iterator it = pGroup->listFiles.begin ( );
    while ( it != pGroup->listFiles.end ( ) )
      list.append ( (*it++)->qsFileName );

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

    addMovieList  ( list, &pGroup->qsGroupName );
  }

  SourceFileEntry *pSourceFileEntry = sourceFileEntry ( sourceFileCount ( ) );
  if ( ! pSourceFileEntry )
    return;
}

void QDVDAuthor::slotAddFromTemplate ()
{
	// This function will handle the template Dialog.
	if ( ! m_pTemplateWizard )	{
		m_pTemplateWizard = new TemplateWizard ( this );
		m_pTemplateWizard->initMe ( );
	}
	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  = -1; //m_listDVDMenus.count() + 2;
  pNewMenu->getInterface ( )->iMenu      = -1; //0;
  pNewMenu->setTabLabel ( qsNewTabLabel );
  addDVDMenu ( pNewMenu );
  slotUpdateStructure ( );
}

void QDVDAuthor::slotAddFromLibrary ( )
{
  QDir theDir;
  QString qsPrefixDir;
  qsPrefixDir = QString ("%1/share/qdvdauthor/buttons").arg ( Global::qsSystemPath );
  if ( !  theDir.exists ( qsPrefixDir ) ) {
    MessageBox::warning ( NULL, tr ( "Library files missing" ), 
      tr ( "Please make sure that the path :\n%1\nexists and is readable.\n\nYou can get the files from here :\nhttp://qdvdauthor.sf.net/data/buttons.tar.bz2" ).arg ( qsPrefixDir ), QMessageBox::Ok, QMessageBox::NoButton );
    return;
  }

  if ( ! m_pDialogLibrary )
    m_pDialogLibrary = new DialogLibrary;

  if ( ! m_pDialogLibrary->isVisible ( ) )
    m_pDialogLibrary->show ( );
}

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

DVDMenu *QDVDAuthor::findMenuFromSourceFileEntry( SourceFileEntry *pEntry )
{
  // FInds the first menu which points to the SourceFIleEntry
  DVDMenu *pDVDMenu  = NULL;
  SourceFileEntry *p = NULL;
  QValueList<SourceFileEntry *> list;
  QValueList<SourceFileEntry *>::iterator it;
  QValueList<DVDMenu *>::iterator itMenu = m_listDVDMenus.begin ( );

  pDVDMenu = getVMGMenu ( );
  do  {
    if ( pDVDMenu )  {
      list = pDVDMenu->getSourceFileEntries ( );
      it   = list.begin ( );
      while ( it != list.end ( ) )  {
        p  = *it++;
        if ( p == pEntry )
          return pDVDMenu;
      }
    }
    pDVDMenu = *itMenu;
  } while ( itMenu++ != m_listDVDMenus.end ( ) );
/*
  if ( pDVDMenu )  {
    list = pDVDMenu->getSourceFileEntries ( );
    it = list.begin ( );
    while ( it != list.end ( ) )  {
      p = *it++;
      if ( p == pEntry )
        return pDVDMenu;
    }
  }

  for ( t=0; t<m_listDVDMenus.count ( ); t++ )  {
    pDVDMenu = m_listDVDMenus[t];
    if ( pDVDMenu )  {
      list = pDVDMenu->getSourceFileEntries ( );
      it = list.begin ( );
      while ( it != list.end ( ) )  {
        p = *it++;
        if ( p == pEntry )
          return pDVDMenu;
      }
    }
  }
*/
  return NULL;
}

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 && 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 ( )
{
  DVDMenu *pDVDMenu = getCurrentSubMenu ( );
  if (  !  pDVDMenu )
    return;

  MenuPreview *pPreview = pDVDMenu->getMenuPreview ( );
  if ( ! pPreview )
    return;

  pPreview->slotCut ( );
}

void QDVDAuthor::editCopy ( )
{
  DVDMenu *pDVDMenu = getCurrentSubMenu ( );
  if (  !  pDVDMenu )
    return;

  MenuPreview *pPreview = pDVDMenu->getMenuPreview ( );
  if ( ! pPreview )
    return;

  pPreview->slotCopy ( );
}

void QDVDAuthor::editPaste ( )
{
  DVDMenu *pDVDMenu = getCurrentSubMenu ( );
  if (  !  pDVDMenu )
    return;

  MenuPreview *pPreview = pDVDMenu->getMenuPreview ( );
  if ( ! pPreview )
    return;

  pPreview->slotPaste ( );
}

void QDVDAuthor::editFind()
{

}

void QDVDAuthor::helpIndex()
{

}

void QDVDAuthor::helpContents()
{

}

void QDVDAuthor::helpGuide ( )
{
  QString qsGuide;
  qsGuide  = QString ("<h3><p align=\"center\">'Q' DVD-Author Quick-Start Guide</p></h3>\n"
		      "How to create a DVD containing a video activated from a menu button:<p>\n"
		      "<ol>\n"
		      "<li>start a new project with <i>File, New Project</i>, accept <i>/tmp</i> "
		      "as a temporary directory, and click on <i>Next</i>, enter a project name, "
		      "and for the path to the DVD use the <i>Browse</i> button and then the "
		      "<i>Create New Folder</i> button,<br><br>\n"
		      "<li>click on the <i>Add Movie</i> button to add a video to the project,<br><br>\n"
		      "<li>click on the <i>Add Background</i> button to load an image file for "
		      "the menu background,<br><br>\n"
		      "<li>(optional) click on the <i>Add Sound</i> button to load a sound file "
		      "for the menu,<br><br>\n"
		      "<li>create menu buttons by using right-click on the workspace background "
		      "image and click on <i>Add Image</i> or <i>Add Text</i>, draw an outline "
		      "rectangle, answer the image or text dialog, and the object will appear,<br><br>\n"
		      "<li>right-click over the image or text to <i>Define as Button</i>, and "
		      "set the <i>Action</i> to <i>jump</i> to the video you have added,<br><br>\n"
		      "<li>click on the <i>DVDAuthor, Create DVD</i> menu option to begin "
		      "exporting, review the suggested commands for suitability, then click on "
		      "<i>OK</i> to begin.\n"
		      "</ol>\n");
  qsGuide += QString ("For more information, go to <a href=\"http://qdvdauthor.sourceforge.net\">http://qdvdauthor.sourceforge.net</a></p>");

  QSize theSize ( 800, 600 );
  MessageBox::html ( this, tr ( "Quick guide" ), qsGuide, theSize );
}

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.sourceforge.net\">http://qdvdauthor.sourceforge.net</a><br>");
  qsAbout += QString ("System Folder at<br>%1/share/qdvdauthor/</p>").arg ( Global::qsSystemPath );
  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     ( );
  pInit->setSlideshowDefaults ( );
//  Global::qsSystemPath   = pInit->systemPath ( );
  Global::listToolsPaths = pInit->getToolsPaths   ( );
  if (Global::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;
    Global::listToolsPaths = theUtils.scanSystem ( );
  }
  if ( ! m_listHistory.empty ( ) )  {
    fileInfo.setFile ( m_listHistory.last ( ) );
    qsAbsPath = fileInfo.absFilePath ( );
    // setCurrentPath (qsAbsPath);
  }
  // Finally we connect the Menu ...
  buildHistoryEntries ( );
  setAutosave         ( );

  if ( m_pTabsPopup )  {
       m_pTabsPopup->setItemChecked ( m_pTabsPopup->idAt ( 0 ), pInit->visibleTabs ( 0 ) );
       m_pTabsPopup->setItemChecked ( m_pTabsPopup->idAt ( 1 ), pInit->visibleTabs ( 1 ) );
       m_pTabsPopup->setItemChecked ( m_pTabsPopup->idAt ( 2 ), pInit->visibleTabs ( 2 ) );
       if ( pInit->visibleTabs ( 0 ) == false )
         m_pTabWidgetMain->removePage ( getTabWidget ( TabDVDLayout    ) );
       if ( pInit->visibleTabs ( 1 ) == false )
         m_pTabWidgetMain->removePage ( getTabWidget ( TabSubtitles    ) );
       if ( pInit->visibleTabs ( 2 ) == false )
         m_pTabWidgetMain->removePage ( getTabWidget ( TabDVDAuthorXml ) );
  }

  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 ( Global::qsSystemPath + "/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 ...
	int t;
	bool bTabs[3];
	bTabs[0] = tabVisible ( TabDVDLayout    );
	bTabs[1] = tabVisible ( TabSubtitles    );
	bTabs[2] = tabVisible ( TabDVDAuthorXml );

	QDVDAuthorInit *pInit = new QDVDAuthorInit ( Global::listToolsPaths, &m_dragNDropContainer );
	pInit->setHistory       ( m_iMaxHistoryFiles, m_listHistory, m_listHistoryPix );
	pInit->setAutosave      ( m_iAutosave      );
	pInit->setVisibleRegion ( m_bVisibleRegion );
	for ( t=0; t<3; t++ )
	  pInit->setVisibleTabs ( t, bTabs[t]      );
	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 ( )
{
  if ( ( ! Global::pApp ) || ( ! this ) )
    return;

  //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 ( );
	SaveIni ( );
}

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) {
    if ( ( Global::qsProjectFileName.find ( PROJECT_FILENAME ) > -1 ) || 
         ( Global::qsProjectFileName.find ( AUTOSAVE_FILE_NAME ) > -1 ) )
      return;
    m_listHistory.append    ( Global::qsProjectFileName );
    m_listHistoryPix.append ( new QPixmap ( ) );
    iIndex = m_listHistory.findIndex ( Global::qsProjectFileName );
  }

  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::slotCreateDVD ( )
{
  if ( m_bCreateDVDAfterSlideshows )  {
    engageCreateDVD  ( false );
    return;
  }
  // 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
  createTransitionsXml ( );
  // 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::createTransitionsXml ( )
{
  DVDMenu *pDVDMenu = getVMGMenu ( );
  pDVDMenu->createTransitionsXml ( );

  QValueList<DVDMenu *> list = getSubMenus ( );
  QValueList<DVDMenu *>::iterator it = list.begin ( );
  while ( it != list.end ( ) )  {
    pDVDMenu = *it++;
    pDVDMenu->createTransitionsXml ( );
  }
}

void QDVDAuthor::createSubtitlesXml ( )
{
  uint i, t, iCount;
  Export::Spumux   spumux;
  SourceFileEntry *pEntry;
  SourceFileInfo  *pInfo;  
  QFileInfo        fileInfo;
  QString          qsInfo;
  QValueList<SourceFileInfo *>listAlreadyRendered;
  iCount = sourceFileCount ( );

  //  QString qsHTML = "<HTML><BODY BGCOLOR=\"BLACK\" text=\"#ff8000\">";
  //  qsHTML += "<TABLE WIDTH=\"100%\" BGCOLOR=\"#7700ff\" BORDER=\"1\"><TR><TD><FONT COLOR=\"#FFD000\"><B>";

  qsInfo  = "<HTML><BODY>";
  qsInfo += tr ( "The subtitles for the following files have been rendered already.<P>" );
  qsInfo += "<FONT COLOR=\"BLUE\"><B>";
  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 ...
      if ( renderSubtitles  ( pInfo ) ) {
	// Already rendered ALL of the subtitles associated with this SourceFileInfo
	// Let's ask the user if he wants to re-render all subtitles.
	fileInfo.setFile ( pInfo->qsFileName );
	qsInfo += fileInfo.fileName ( ) + QString ( "<BR>" );
	listAlreadyRendered.append  ( pInfo );
      }
      else // if the subtitle was rendered here, we have to create the XML file as well
	spumux.createXml ( pInfo );
    }
  }
  qsInfo += "</B></FONT>";

  if ( listAlreadyRendered.count ( ) > 0 ) {
    qsInfo += tr ( "<P>Do you want to re-render all of them ?" );
    qsInfo += "</BODY></HTML>";
    if ( MessageBox::html ( this, tr ( "Subtitles already rendered." ), qsInfo, QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes ) {
      for ( t=0; t<listAlreadyRendered.count ( ); t++ ) {
	pInfo = listAlreadyRendered[t];
	if ( pInfo ) {
	  renderSubtitles  ( pInfo, true );
	  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, j;
  bool bFound = false;
  Utils theUtils;
  QString fileSpumux, qsSubIdx;
  Export::Spumux spumux;
  SourceFileEntry *pEntry = NULL;
  SourceFileInfo  *pInfo  = NULL;
  Subtitles  *pSubtitles  = NULL;
  QFileInfo   fileInfo;

  createTempDirStructure  ( );
  if (    qsWhich.isEmpty ( ) )  {
    m_pTextEditXml->clear ( );
    return;
  }
  if (qsWhich == QString ( DVDAUTHOR_XML ) )  {
    createDvdauthorXml   ( );
    fileSpumux = getTempFile ( QString ( DVDAUTHOR_XML ) );
  }
  else if ( m_pVMGMenu && 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++ ) {
          pInfo = pEntry->listFileInfos [ i ];
          fileInfo.setFile ( pInfo->qsFileName );
          for ( j=0; j<MAX_SUBTITLES; j++ ) {
            pSubtitles = pInfo->arraySubtitles [ j ];
            if ( ! pSubtitles )
              continue;
            // Here we do the translation between what is shown and the actual file name.
            fileSpumux.sprintf ("%s_sub%02d.xml", fileInfo.baseName ( ).ascii ( ), pSubtitles->m_iSubtitleNumber );
            if ( qsWhich == fileSpumux ) {
              // The actual file name looks more like this ...
              qsSubIdx.sprintf ( "/subtitle_%d.xml", pSubtitles->m_iSubtitleNumber );
              fileSpumux = getTempFile ( fileInfo.baseName ( TRUE ) );
              QDir tempDir ( fileSpumux );
              if ( ! tempDir.exists ( ) )
                theUtils.recMkdir   ( fileSpumux );
              spumux.createXml  ( pInfo );
              fileSpumux += qsSubIdx;
              i = pEntry->listFileInfos.count ( );
              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;
  theExporter.createXml ( );
}

bool QDVDAuthor::renderSubtitles ( SourceFileInfo *pInfo, bool bForce )
{
  if ( ( ! pInfo ) || ( pInfo->subtitleCount ( ) < 1 ) )
    return false;

  int        t;
  QString    qsBasePath;
  Utils      theUtils;
  bool       bAlreadyRendered = true;
  Subtitles *pSubtitles, *pAlreadyRendered;
  QValueList<Subtitles *> list;
  QFileInfo  fileInfo   ( pInfo->qsFileName );

  // Okay the subtitles should be named like $TMP/$PROJ/BASE_NAME/sub_<start>.png
  qsBasePath = theUtils.getTempFile( fileInfo.baseName ( true ) );
  QDir tempDir ( qsBasePath );
  if ( ! tempDir.exists ( ) )
    theUtils.recMkdir ( qsBasePath );

  for ( t=0; t<MAX_SUBTITLES; t++ ) {
    pSubtitles = pInfo->arraySubtitles [ t ];
    if ( pSubtitles ) {
      pAlreadyRendered = pSubtitles->render ( qsBasePath, pInfo->qsResolution, pInfo->qsFileName, bForce );
      if ( ! pAlreadyRendered ) {
             bAlreadyRendered = false;
      }
      else
        list.append ( pAlreadyRendered );
    }
  }
  // The logic is thet if any of the subtitles had to be rendered ( did not yet exist ), 
  // then we want to render all subtitles of this file even if it existed.
  if ( ! bAlreadyRendered && list.count ( ) > 0 ) {
    for ( t=0; t<(int)list.count ( ); t++ ) {
      pSubtitles = list [ t ];
      if ( pSubtitles )
           pSubtitles->render ( qsBasePath, pInfo->qsResolution, pInfo->qsFileName, true );
    }
  }
  return bAlreadyRendered;
}

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.
  // o  And a whole bunch of other sanity checks.
  uint t;
  CDVDMenuInterface *pInterface = m_pVMGMenu ? m_pVMGMenu->getInterface ( ) : NULL;

  // First I want to check if the MenuLength is the same as the length of the 
  // associated Audio files, and the same as the MovieObjects within.
  DVDMenu *pDVDMenu = m_pVMGMenu;
  QString qsWarning, qsTemp;
  for ( t=0; t<=m_listDVDMenus.count ( ); t++ ) {
    qsTemp = pDVDMenu->checkDuration ( );
    if ( qsTemp.length ( ) > 1 )
      qsWarning += qsTemp;
    pDVDMenu = m_listDVDMenus[t];
  }
  if ( qsWarning.length ( ) > 1 ) {
    QString qsHTML = "<HTML><BODY BGCOLOR=\"BLACK\" text=\"#ff8000\">";
    qsHTML += "<TABLE WIDTH=\"100%\" BGCOLOR=\"#7700ff\" BORDER=\"1\"><TR><TD><FONT COLOR=\"#FFD000\"><B>";
    qsHTML += tr ( "There are issues with some of the DVDMenu length, which do not line up with the included Audio tracks and/or the associated MovieObjects.<BR>" );
    qsHTML += tr ( "This could cause unintended side effects with the affected menus.<P>" );
    qsHTML += tr ( "Below is the list of all DVDMenus and objects.</B></FONT></TD></TR></TABLE>" );
    qsHTML += qsWarning;
    qsHTML += tr ( "&nbsp;<P><CENTER><FONT COLOR=\"RED\"><B>Do you want to fix them first ?</B></FONT></CENTER>" );
    qsHTML += "</BODY></HTML>";
    if ( MessageBox::html ( this, tr ( "Warning, Menu length differences." ), qsHTML, QSize ( 800, 600 ), 
		       QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes )
      return false;
  }


  // primary implementation only checks for Background image.
  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;
  }

  QString qsBadMenus;
  QValueList<ButtonObject *> listButtons;
  if ( m_pVMGMenu )
       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;
  }
  if ( m_pVMGMenu && listButtons.count ( ) > 36 )
    qsBadMenus += tr ( "   %1  \n" ).arg ( m_pVMGMenu->getInterface ( )->qsMenuName );

  for ( t=0; t<m_listDVDMenus.count ( ); t++ ) {
    QString qsBadMenus;
    listButtons = m_listDVDMenus[t]->getButtons ( );
    if ( listButtons.count  ( ) > 36 )
      qsBadMenus += QString ( " o   %1  \n" ).arg ( m_listDVDMenus[t]->getInterface ( )->qsMenuName );
  }
  // Finally we see if we found some menus with more then 36 buttons.
  if ( qsBadMenus.length ( ) > 1 ) {
    MessageBox::warning ( this, tr ("Too many buttons for Menu."),
      tr ("The DVD spec does allow a max of 36 buttons per DVDMenu.\n"
	  "Please reduce the number of buttons in the following menus :\n%1").arg ( qsBadMenus ),
	  QMessageBox::Ok, QMessageBox::NoButton );
    return false;
  }

  // Check if buttons are overlapping each other ...
  QString qsOverlappingButtons;
  if ( m_pVMGMenu )
    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]);
      if ( t > 15 ) {
	stringFiles += tr ( "... and more files ...\n" );
	break;
      }
    }
    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]);
      }
    }
  }

  // The last check will see if we have some slideshows on-going.
  // If this is the case, then we should wait for the termination
  // of all slideshow creation processes / threads.
  for ( t=0; t<(uint)sourceFileCount ( ); t++ )  {
    SourceFileEntry *pEntry = sourceFileEntry ( t );
    if ( pEntry->bIsSlideshow )  {
      // Okay I found at least one entry that is not yet done converting to a slideshow
      int iReturn = MessageBox::warning ( this, tr ("Slideshow in progress."),
        tr ("There are some slideshows not finished rendering.\n"
        "Do you want to proceed after all slideshows finished or abort ?\n"),
        QMessageBox::Yes, QMessageBox::Cancel );
      if ( iReturn == QMessageBox::Cancel )
        return false;

      engageCreateDVD ( true );
      return false;
    }
  }

  // Add ButtonTransition creation check here ...
  if ( m_pVMGMenu )
       listButtons = m_pVMGMenu->getButtons ( );
  ButtonObject *pButton = NULL;
  QValueList<ButtonObject *>::iterator it = listButtons.begin ( );
  while ( it != listButtons.end ( ) )  {
    pButton = *it++;
    if  (  pButton->getTransition ( ) && pButton->getTransition ( )->bFinishedRendering )
      Render::Manager::unregisterTrans ( pButton->getTransition ( ) );
  }

  for ( t=0; t<m_listDVDMenus.count ( ); t++ )  {
    listButtons = m_listDVDMenus[t]->getButtons ( );
    it = listButtons.begin ( );
    while ( it != listButtons.end ( ) )  {
      pButton = *it++;
      if  (  pButton->getTransition ( ) && pButton->getTransition ( )->bFinishedRendering )
        Render::Manager::unregisterTrans ( pButton->getTransition ( ) );
    }
  }

  return true;
}

void QDVDAuthor::engageCreateDVD ( bool bEngage )
{
  m_bCreateDVDAfterSlideshows = bEngage;
  if ( bEngage )  {
    QCursor myCursor ( QCursor::WaitCursor );
    QApplication::setOverrideCursor ( myCursor );
  }
  else
    QApplication::restoreOverrideCursor ( );

  m_pToolbar->setEnabled         ( !bEngage );
  m_pMenuBar->setEnabled         ( !bEngage );
  m_pColorToolbar->setEnabled    ( !bEngage );
  m_pSourceToolbar->setEnabled   ( !bEngage );
  m_pStructureToolbar->setEnabled( !bEngage );
  m_pTabWidgetMain->setEnabled   ( !bEngage );

  VMGMenu *pMenu = (VMGMenu *)getVMGMenu ( );
  if ( pMenu )  {
    QToolBar *pToolBar = pMenu->getToolBar ( );
    if ( pToolBar )
         pToolBar->setEnabled    ( !bEngage );
  }
  m_pActionCreateDVD->setEnabled (     true );
}

UndoBuffer *QDVDAuthor::getUndoBuffer ( )
{
  DVDMenu *pCurrentDVDMenu = getCurrentSubMenu ( );
  if ( pCurrentDVDMenu )
    return pCurrentDVDMenu->getUndoBuffer ( );
  return NULL;
}

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

void QDVDAuthor::replaceTempPaths ( QString qsNewTempPath )
{
  // This function is called after the user changedthe temp path.
  // All generated temp files will have to get adjusted.

  // First we have to get the orig temp Path
  QString qsOrigTempPath = Global::qsTempPath + QString ("/") +  Global::qsProjectName;

  // Let us go through all SourceFileEntries
  Subtitles       *pSubtitle = NULL;
  SourceFileEntry    *pEntry = NULL;
  SourceFileInfo      *pInfo = NULL;

  QValueList<SourceFileInfo *>::iterator it;
  int iCount, i, t;
  QString qsTemp;

  iCount = sourceFileCount ( );
  for ( t=0; t<iCount; t++ ) {
    pEntry = sourceFileEntry ( t );
    it = pEntry->listFileInfos.begin ( );
    while ( it != pEntry->listFileInfos.end ( ) )  {
      pInfo = *it++;
      if ( pInfo->pTranscodeInterface )  {
        qsTemp = pInfo->pTranscodeInterface->qsTempFile;
        qsTemp.replace ( qsOrigTempPath, qsNewTempPath );
        pInfo->pTranscodeInterface->qsTempFile = qsTemp;
      }
      for ( i=0; i<MAX_SUBTITLES; i++ )  {
        pSubtitle = pInfo->arraySubtitles[ i ];
        if ( ! pSubtitle )
          continue;
        pSubtitle->m_qsTempFile.replace ( qsOrigTempPath, qsNewTempPath );
        pSubtitle->m_qsXmlFile.replace  ( qsOrigTempPath, qsNewTempPath );
      }
      pInfo->qsFileName = pInfo->qsFileName.replace  ( qsOrigTempPath, qsNewTempPath );
    }
  }
}

/*******************************************************************************************************
/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 ()
{
	Utils theUtils;
	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  ( ) )  {
		if ( ! theUtils.recMkdir ( qsTempDir ) )
			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 (Global::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 ( Global::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 ( ) )
		Global::listToolsPaths = pDialog->getToolsPathsList ();

	Global::qsProjectPath = pDialog->m_pEditProjectPath->text();  // Where the DVD is created
	QString qsNewTemp     = pDialog->m_pEditTempPath->text ( ) + "/" + pDialog->m_pEditProjectName->text ( );
	QString qsOldTemp     = Global::qsTempPath + "/" + Global::qsProjectName;
	if ( qsNewTemp != qsOldTemp )  {
		replaceTempPaths ( qsNewTemp );
		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::slotSelectZone ( )
{
  DialogRegion dialog ( this, Global::iRegionalZone );
  if ( dialog.exec  ( ) == QDialog::Accepted )  {
    Global::iRegionalZone = dialog.regionalZone ( );
    setRegionalZone ( );
  }
}

void QDVDAuthor::setRegionalZone ( )
{
  switch ( Global::iRegionalZone )  {
  case 1:
    m_pActionZone1->setOn ( true );
  break;
  case 2:
    m_pActionZone2->setOn ( true );
  break;
  case 3:
    m_pActionZone3->setOn ( true );
  break;
  case 4:
    m_pActionZone4->setOn ( true );
  break;
  case 5:
    m_pActionZone5->setOn ( true );
  break;
  case 6:
    m_pActionZone6->setOn ( true );
  break;
  default:
    m_pActionZoneAll->setOn ( true );
  break;
  }
}

void QDVDAuthor::slotZone ( QAction *pAction )
{
  if ( pAction == m_pActionZoneAll )
    Global::iRegionalZone = 0;
  else if ( pAction == m_pActionZone1 )
    Global::iRegionalZone = 1;
  else if ( pAction == m_pActionZone2 )
    Global::iRegionalZone = 2;
  else if ( pAction == m_pActionZone3 )
    Global::iRegionalZone = 3;
  else if ( pAction == m_pActionZone4 )
    Global::iRegionalZone = 4;
  else if ( pAction == m_pActionZone5 )
    Global::iRegionalZone = 5;
  else if ( pAction == m_pActionZone6 )
    Global::iRegionalZone = 6;
}

void QDVDAuthor::slotVersions ( )
{
  // Here we get the ServerVersion.txt file from the SourceFOrge server and compare
  // with what we have.
  //
  // There are three possibilities from parsing the versions currently on the server.
  // 1) QDVDAuthor or the plugins are newer.
  //    - User must compile or install new version manually.
  // 2) The server has more templates than the users machine.
  //    - Ask user if he wants to install them and switch to the TemplatesDialog.
  // 3) One of the libraries ( masks/Buttons/Transitions ) is outdated.
  //    - Ask user if he wants to DL and install those libraries.
  //////////////////////////////////////////////////////////////////////////////////////

  enum { QDVDAUTHOR=0, MASKS, BUTTONS, TRANSITIONS, MAX_VER };
  enum { LOCAL=0, SERVER, MAX_DEST };
  int t;
  Utils theUtils;
  QString qsHtml;
  QSize   size ( 600, 500 );
  QString qsServerVersion = "http://qdvdauthor.sourceforge.net/data/ServerVersions.txt";
  QString qsLocalVersion  = Global::qsTempPath + "/ServerVersions.txt";
  QString qsLastVersion   = QDir::homeDirPath ( ) + "/.qdvdauthor/ServerVersions.txt";
  QString qsLocalPath     = "file:" + Global::qsTempPath;

  QFile file ( qsLocalVersion );
  if ( file.exists ( ) )
       file.remove ( );

  qInitNetworkProtocols ( );
  // First we get the ServerVersion from the server
  if ( ! theUtils.webToFile ( qsServerVersion, qsLocalPath ) )  {
    qsHtml = tr ( "<font color=\"red\"><b>Could not fetch %1 from server.</b></font><br>" ).arg ( qsServerVersion );
    MessageBox::html ( NULL, tr ( "Version information" ), qsHtml );
    return;
  }
  chmod ( qsLocalVersion.utf8 ( ), S_IWGRP | S_IRGRP | S_IRUSR | S_IWRITE | S_IROTH | S_IWOTH );

  // Next we open the ServerVersion file and read in the latest version information
  // which are currently on the server. ( All values are float )
  float fVersion[MAX_DEST][MAX_VER];
  fVersion[LOCAL][QDVDAUTHOR]  = atof ( QDVDAUTHOR_VERSION_NUMBER );
  fVersion[SERVER][QDVDAUTHOR] = atof ( QDVDAUTHOR_VERSION_NUMBER );
  for ( t=MASKS; t<MAX_VER; t++ )  {
    fVersion[LOCAL][t]  = 1.0f;
    fVersion[SERVER][t] = 1.0f;
  }

  QStringList list, listServerTemplates;
  QMap<QString, float> mapPlugins;
  QString qsFileName, qsLine, qsTemplate;
  QRegExp rx  ( "\\d*\\.\\d+"  ); // floating point 
  QRegExp rx1 ( "^\\S" );
  if ( file.open ( IO_ReadOnly ) )  {
    QTextStream stream ( &file );
    while ( ! stream.atEnd ( ) )  {
      qsLine= stream.readLine( );
      if ( qsLine.length() > 0 )  {
        if ( qsLine[0] ==  '#' )  // Comment line
          continue;
        if ( rx1.search ( qsLine, 0 ) == -1 )  // line must start with a character
          continue;
          list = QStringList::split ( ":", qsLine );
          if ( list.size ( ) == 2 )  {  // Found, so we should have a version information
            float fVer = atof ( list[1] );
            if (      list[0] == "qdvdauthor" )
              fVersion[SERVER][QDVDAUTHOR]  = fVer;
            else if ( list[0] == "masks"      )
              fVersion[SERVER][MASKS]       = fVer;
            else if ( list[0] == "buttons"    )
              fVersion[SERVER][BUTTONS]     = fVer;
            else if ( list[0] == "transitions")
              fVersion[SERVER][TRANSITIONS] = fVer;
            else  {
              // this means we have found a plugin.
              mapPlugins[list[0]] = fVer;
            }
          }
          else  // Not found, so we should have a template name
            listServerTemplates.append ( qsLine );
      }
    }
    file.close ( );
  }
  else  {
    qsHtml = tr ( "<font color=\"red\"><b>Could not open %1 file</b></font><br>" ).arg ( qsLocalVersion );
    MessageBox::html ( NULL, tr ( "Version information" ), qsHtml, size );
    return;
  }

  // At this point we have obtained the versions which are currently on the server. Next we obtain the local versions.
  qsFileName = Global::qsSystemPath + "/share/qdvdauthor/masks/VERSION";
  fVersion[LOCAL][MASKS]       = theUtils.getVersionInfo ( qsFileName );
  qsFileName = Global::qsSystemPath + "/share/qdvdauthor/buttons/VERSION";
  fVersion[LOCAL][BUTTONS]     = theUtils.getVersionInfo ( qsFileName );
  qsFileName = Global::qsSystemPath + "/share/qdvdauthor/slideshow/transitions/VERSION";
  fVersion[LOCAL][TRANSITIONS] = theUtils.getVersionInfo ( qsFileName );

  // A special handling for the QDVDAuthor version mismatch.
  if ( fVersion[LOCAL][QDVDAUTHOR] < fVersion[SERVER][QDVDAUTHOR] )  {
    qsHtml += tr ( "<br><font color=\"red\"><h1>It seems you have an older version of QDVDAuthor.<br>" );
    qsHtml += tr ( "The latest version of QDVDAuthor is %1. You are using version %2<p>" ).arg ( fVersion[SERVER][QDVDAUTHOR] ).arg ( fVersion[LOCAL][QDVDAUTHOR] );
    qsHtml += tr ( "Please update the executable first.</h1></font><p>" );
    MessageBox::html ( NULL, tr ( "QDVDAuthor version outdated." ), qsHtml, size );
    return;
  }

  // DEBUGGING
//  fVersion[LOCAL][MASKS]       = 0.9f;
//  fVersion[LOCAL][BUTTONS]     = 0.9f;
//  fVersion[LOCAL][TRANSITIONS] = 0.9f;

  // Lets compare with the installed version
  bool bNeedUpdate = false;
  for ( t=MASKS; t<MAX_VER; t++ )  {
    if ( fVersion[LOCAL][t] < fVersion[SERVER][t] )
      bNeedUpdate = true;
  }
  if ( bNeedUpdate )  {
    QString qsCommand;
    qsCommand  = Global::qsBashString;

    qsHtml += "<font color=\"ORANGE\"><b>";
    qsHtml += tr ( "There are newer versions available for :" );
    qsHtml += "</b></font><p><font color=\"#FF5050\"><b>";
    if ( fVersion[LOCAL][MASKS] < fVersion[SERVER][MASKS] )  {
      if ( fVersion[LOCAL][MASKS] == 0.0f )
        qsHtml += tr ( "Masks: The masks library is missing on your system.<p>" );
      else
        qsHtml += tr ( "Masks: Version <u>%1</u> of the masks are available. You are using version <u>%2</u><p>" ).arg ( fVersion[SERVER][MASKS], 0, 'f', 2 ).arg ( fVersion[LOCAL][MASKS], 0, 'f', 2 );
      qsCommand += "cd " + Global::qsTempPath + "\n";
      qsCommand += "wget http://qdvdauthor.sourceforge.net/data/masks.tar.bz2 -O masks.tar.bz2\n";
      qsCommand += "cd " + Global::qsSystemPath + "/share/qdvdauthor/\n";
      qsCommand += "tar -xjf " + Global::qsTempPath + "/masks.tar.bz2\n\n";
    }
    if ( fVersion[LOCAL][BUTTONS] < fVersion[SERVER][BUTTONS] )  {
      if ( fVersion[LOCAL][BUTTONS] == 0.0f )
        qsHtml += tr ( "Buttons: The button library is missing on your system.<p>" );
      else
        qsHtml += tr ( "Buttons: Version <u>%1</u> of the buttons are available. You are using version <u>%2</u><p>" ).arg ( fVersion[SERVER][BUTTONS] ).arg ( fVersion[LOCAL][BUTTONS] );
      qsCommand += "cd " + Global::qsTempPath + "\n";
      qsCommand += "wget http://qdvdauthor.sourceforge.net/data/buttons.tar.bz2 -O buttons.tar.bz2\n";
      qsCommand += "cd " + Global::qsSystemPath + "/share/qdvdauthor/\n";
      qsCommand += "tar -xjf " + Global::qsTempPath + "/buttons.tar.bz2\n\n";
    }
    if ( fVersion[LOCAL][TRANSITIONS] < fVersion[SERVER][TRANSITIONS] )  {
      if ( fVersion[LOCAL][TRANSITIONS] == 0.0f )
        qsHtml += tr ( "Transitions: The transitions library is missing on your system.<p>" );
      else
        qsHtml += tr ( "Transitions: Version <u>%1</u> of the transitions are available. You are using version <u>%2</u><p>" ).arg ( fVersion[SERVER][TRANSITIONS] ).arg ( fVersion[LOCAL][TRANSITIONS] );
      qsCommand += "cd " + Global::qsTempPath + "\n";
      qsCommand += "wget http://qdvdauthor.sourceforge.net/data/alpha_trans.tar.bz2 -O alpha_trans.tar.bz2\n";
      qsCommand += "cd " + Global::qsSystemPath + "/share/qdvdauthor/\n";
      qsCommand += "tar -xjf " + Global::qsTempPath + "/alpha_trans.tar.bz2\n\n";
    }
   //printf ( "%s", qsCommand.ascii() );
    qsHtml += "</b></font><p><font color=\"RED\"><b>";
    qsHtml += tr ( "<p>Do you want to download the latest libraries now ?<br>" );
    qsHtml += "</b></font>";
    int iResult = MessageBox::html ( NULL, tr ( "Version information" ), qsHtml, size, QMessageBox::Yes, QMessageBox::No );

    if ( iResult == QMessageBox::Yes )  {
      QString qsGuiSU = theUtils.findGuiSU ( );
      if ( qsGuiSU.length ( ) < 1 )  {
        qsHtml += tr ( "<p>Could not locate any GUI for root<br>Please execute the following commands as root.<p>" );
        qsHtml += qsCommand;
        MessageBox::html ( NULL, tr ( "Version information" ), qsHtml, size );
      }
      else  {
        if ( qsGuiSU == "kdesu" )
             qsGuiSU += " -n -t -c ";
        else if ( qsGuiSU == "xsu" )
                  qsGuiSU += " --username root --message \"Please type in the root password\" --command ";
        else if ( qsGuiSU == "gnomesu" )
                  qsGuiSU += " --username root --message \"Please type in the root password\" --command ";

        QString qsExecutable = Global::qsTempPath + "/execute.sh";
        QFile file ( qsExecutable );
        if ( file.open ( IO_WriteOnly ) ) {
          QTextStream stream ( &file );
          stream << qsCommand;
          file.close ( );
        }
        // And here we grant read/write/execute permission.
        chmod ( qsExecutable.utf8 ( ), S_IEXEC | S_IRUSR | S_IWRITE | S_IROTH | S_IXOTH | S_IWOTH | S_IXGRP | S_IWGRP | S_IRGRP );

        QCursor myCursor ( QCursor::WaitCursor );
        QApplication::setOverrideCursor ( myCursor );
        qsCommand = qsGuiSU + qsExecutable;
        int iRet  = system ( qsCommand.utf8 ( ) );
        QApplication::restoreOverrideCursor ( );
        iRet = iRet; // quiet down compiler
      }
    }
  }
  qsHtml = "";

  // Next we handle the templates.
  list = theUtils.localTemplates ( );
  QStringList::iterator it2, it = list.begin ( );
  while ( it != list.end ( ) )  {
    qsTemplate = *it++ + ".tar.gz";
    it2 = listServerTemplates.begin ( );
    while ( it2 != listServerTemplates.end ( ) )  {
      if  ( qsTemplate == *it2++ )  {
        listServerTemplates.remove ( qsTemplate );
        break;  // out of the inner while loop
      }
    }
  }

  if ( listServerTemplates.size ( ) > 0 )  {
    qsHtml += "<font color=\"ORANGE\"><b>";
    qsHtml += tr ( "There are %1 additional templates available on the server<p>" ).arg ( listServerTemplates.size ( ) );
    qsHtml += "</b></font><font color=\"#008000\"><b>";
    it = listServerTemplates.begin ( );
    while ( it != listServerTemplates.end ( ) )  {
      qsTemplate = *it++;
      qsHtml += tr ( "%1<br>" ).arg ( qsTemplate );
    }
    qsHtml += "</b></font></b><font color=\"RED\"><b>";
    qsHtml += tr ( "<p>Do you want to download the templates ?<br>" );
    qsHtml += "</b></font><b>";
    int iResult = MessageBox::html ( NULL, tr ( "Additional Templates available" ), qsHtml, size, QMessageBox::Yes, QMessageBox::No );
    if ( iResult == QMessageBox::Yes )
         slotTemplateDownload ( );
  }
  else if ( ! bNeedUpdate )  {
    qsHtml  = tr ( "<font color=\"#008000\"><b><p>All libraries and binaries are up-to-date.<p>" );
    qsHtml += tr ( "Thank you.</b></font>" );
    MessageBox::html ( NULL, tr ( "Up-to-date" ), qsHtml );
  }
}

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 ...
  bool bVisibleRegion = toolsVisibleRegionAction->isOn ( );

  emit ( signalVisibleRegion ( bVisibleRegion ) );
  if   ( bVisibleRegion == m_bVisibleRegion )
    return;

  m_bVisibleRegion = bVisibleRegion;
  // If no change occured, then we do not need to save the ini file again.
  SaveIni ( );
}

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

void QDVDAuthor::fileWizard ( )
{
  slotOneClickDVD ( );
}

bool QDVDAuthor::pleaseWait ( )
{
  return m_bWait;
}

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 ...
  if ( m_pVMGMenu )
       m_bModified |= m_pVMGMenu->getInterface ( )->bModified;
  if ( ! m_bModified )  {
    for ( t=0; t<m_listDVDMenus.count ( ); t++ )
      m_bModified |=  m_listDVDMenus[t]->getInterface ( )->bModified;
  }
  if ( 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. \n"
           "Do you want to save the project now ?"),
      QMessageBox::Yes, QMessageBox::No, QMessageBox::Cancel );
    if ( QMessageBox::Yes == iReturn )
         fileSave ( );
    else if ( QMessageBox::Cancel == iReturn )
         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 );
  Global::qsCurrentPath = QString ("./");
  if ( m_pUndoStackDialog )
       m_pUndoStackDialog->setUndoBuffer ( NULL );

  m_bModified = false;
  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 ...
	float fLoadVersion = 1.0f;
	while( !xmlNode.isNull() ) {
		QDomElement searchXMLTree = xmlNode.toElement ( );
		if ( DVDAUTHOR == searchXMLTree.tagName ( ) ) {
			// set the fLoadVersion in this readProjectFile
			bError = ! readProjectFile ( searchXMLTree, fLoadVersion );
		}
		else if ( DVDAUTHOR_ROOT_VMGM == searchXMLTree.tagName ( ) )  {
			m_pVMGMenu->readProjectFile ( searchXMLTree, fLoadVersion );
			m_pVMGMenu->updateDVDMenu   ( false );
		}
		else if ( DVDAUTHOR_ROOT_MENU == searchXMLTree.tagName ( ) )  {
			DVDMenu *pDVDMenu = new DVDMenu(this);
			addDVDMenu ( pDVDMenu );
			pDVDMenu->readProjectFile ( searchXMLTree, fLoadVersion );
			pDVDMenu->updateDVDMenu   ( false );
		}
		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 the 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 ()) );
	m_pTabWidgetMain->setCurrentPage ( 0 );
	if ( m_pDVDLayoutGui )
		QTimer::singleShot ( 1500, m_pDVDLayoutGui, SLOT ( slotPostRead ( ) ) );
}

bool QDVDAuthor::readProjectFile ( QDomNode &xmlNode, float &fLoadVersion )
{
  QString qsVersionNumber;

  QDomElement theElement = xmlNode.parentNode().toElement();
  QDomAttr attribute;

  attribute = theElement.attributeNode ( THE_PROJECT_NAME );
  if ( ! attribute.isNull ( ) )
    Global::qsProjectName = attribute.value ( );

  attribute = theElement.attributeNode ( DVDAUTHOR_ZONE );
  if ( ! attribute.isNull ( ) )
    Global::iRegionalZone = attribute.value ( ).toInt ( );
  setRegionalZone ( );

  // 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) {
      bool bOkay = true;
      qsVersionNumber = nodeText;
      fLoadVersion = qsVersionNumber.toFloat ( &bOkay );
      if ( ! bOkay )
        fLoadVersion = 1.0f;
    }
    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 if ( tagName == DVDAUTHOR_DVDLAYOUT )  {
      if ( m_pDVDLayoutGui )
           m_pDVDLayoutGui->readProjectFile ( xmlDVDAuthor );
    }
    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 );

	if ( Global::iRegionalZone != 0 )
		rootElement.setAttribute ( DVDAUTHOR_ZONE, QString ( "%1" ).arg ( Global::iRegionalZone ) );

	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 );
	}
	if ( m_pDVDLayoutGui )
	     m_pDVDLayoutGui->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 still using the default filename ...
  if ( Global::qsProjectFileName.find ( PROJECT_FILENAME ) > -1 )
    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;
}

void QDVDAuthor::fileSave ( QString qsFileName, bool bSaveAs )
{
  m_bWait = true;

  uint t;
  QFileInfo nameInfo ( qsFileName );
  if ( bSaveAs && ( nameInfo.exists ( ) ) && ( qsFileName.find ( AUTOSAVE_FILE_NAME ) == -1 ) ) {
    if ( MessageBox::information ( this, tr ( "File exists." ),
         tr ( "Attention, the file exists already.\nDo you want to overwrite this file ?" ),
         QMessageBox::Yes, QMessageBox::No) == QMessageBox::No )  {
      m_bWait = false;
      return;
    }
  }

  QFile projectFile ( qsFileName );
  if (  projectFile.open ( IO_WriteOnly ) )  {

    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
    if ( m_pVMGMenu )
         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();
    //xml.replace ( ">", "&gt;" );
    //printf ("%s\n", (const char *)xml);
    /**
     * Write the file as a stream 
     */
    QTextStream ofs ( &projectFile );
    //ofs.setEncoding( QTextStream::UnicodeUTF8 ); 
    ofs.setEncoding ( QTextStream::Latin1 );
    // ^^^ Dat: not QTextStream::UnicodeUTF8, because xmlDoc.toCString()
    //     already emits proper UTF-8, which we keep intact.

    // header is needed to support special characters 
    //ofs << "<?xml version=\"1.0\" encoding=\""  
    //    << ofs.codec()->name()  
    //    << "\"?>\n"; 
    //ofs << xmlDoc.toString().ascii(); 
    ofs << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
    ofs << xmlDoc.toCString ( );

    projectFile.close ( );
  }
  m_bWait = false;
}

void QDVDAuthor::fileSaveAs ( )
{
  QString qsStarting = Global::qsCurrentPath;
  QFileInfo fileInfo ( qsStarting );
  qsStarting = fileInfo.dirPath ( true );
  if ( Global::qsProjectFileName.find ( PROJECT_FILENAME ) > -1 )
    qsStarting = Global::qsCurrentPath + "/" + Global::qsProjectName + ".xml";
  else if ( Global::qsProjectFileName.find ( AUTOSAVE_FILE_NAME ) == -1 )
    qsStarting = Global::qsProjectFileName;

  QString qsProjectFileName = QFileDialog::getSaveFileName(qsStarting, tr ("Project Files (*.xml)"), this, tr("Save file dialog"), tr("Save File As ..."));

  if ( qsProjectFileName.isNull ( ) )
    return;

  fileInfo.setFile ( 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.
  // And will not ask to SaveAs again.
  if ( fileInfo.fileName ( ) == QString ( PROJECT_FILENAME ) )
       qsProjectFileName  = qsPath + QString ( "/unnamed.xml" );

  Global::qsProjectFileName = qsProjectFileName;
  m_bModified = true;

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

  //  fileSave ( );
  // first we save the current project
  fileSave ( Global::qsProjectFileName, true );
  // 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;
}

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

QString QDVDAuthor::getVidFilter ( )
{
  // This is for short vids from the Camera ( used in DialogImages )
  return QString ( "*.avi *.mov *.mpg *.mpeg *.AVI *.MOV *.MPG *.MPEG" );
}

QString QDVDAuthor::getMovieFilter ( )
{
  return QString ( "*.mpg *.mpeg *.mpeg2 *.avi *.mwa *.mov *.wma *.mp4 *.m4v *.ogv *.vro *.vob *.m2v *.mpv *.dv *.wmv *.mjpeg *.mve *.asf *.asx *.flv *.MPG *.MPEG *.MPEG2 *.AVI *.MWA *.MOV *.WMA *.MP4 *.M4V *.OGV *.VRO *.VOB *.M2V *.MPV *.DV *.WMV *.MJPEG *.MVE *.ASF *.ASX *.FLV" );
}

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