/****************************************************************************
** SourceFileEntry - class
**
** Created: Tue Mar 22 12:09:08 2004
**      by: Varol Okan using kate editor
**
** This class is a simple container class to store the info
** for a entry in the Source File List.
**
****************************************************************************/

#include <qfileinfo.h>
#include <qimage.h>
#include <qdom.h>
#include <qdatetime.h>

#include "global.h"
#include "utils.h"
#include "xml_dvd.h"
#include "messagebox.h"
#include "sourcefileentry.h"
	 
Subtitles::entry::entry ()
{
  iIndex = 0;
  iTimeStart = -1;
  iTimeStop  = -1;
}

Subtitles::entry &Subtitles::entry::operator = ( Subtitles::entry &theOther )
{
  iIndex      = theOther.iIndex;
  qsTimeStart = theOther.qsTimeStart;
  qsTimeStop  = theOther.qsTimeStop;
  iTimeStart  = theOther.iTimeStart;
  iTimeStop   = theOther.iTimeStop;
  qsText      = theOther.qsText;
  return *this;
}

Subtitles::Subtitles ()
{
  subColors[0]  = QColor ( TRANSPARENT_COLOR       );
  subColors[1]  = QColor ( START_HIGHLIGHTED_COLOR );
  subColors[2]  = QColor ( START_SELECTED_COLOR    );
  subColors[3]  = QColor ( START_FRAME_COLOR       );
  iTransparency = 0;
}

Subtitles::~Subtitles ()
{
  for (uint t=0;t<listOfSubtitles.count(); t++)
    delete listOfSubtitles[t];
  listOfSubtitles.clear ();
}

Subtitles &Subtitles::operator = ( Subtitles &theOther )
{
  uint t;
  iTransparency = theOther.iTransparency;
  font          = theOther.font;
  rect          = theOther.rect;
  alignment     = theOther.alignment;

  for (int t=0;t<MAX_COLORS;t++)
    subColors[t] = theOther.subColors[t];
  
  if ( listOfSubtitles.count () ) {
    for ( t=0;t<theOther.listOfSubtitles.count();t++) 
      delete listOfSubtitles[t];
  }
  listOfSubtitles.clear ();

  for ( t=0;t<theOther.listOfSubtitles.count();t++) {
    entry *pNewEntry = new entry;
    *pNewEntry = *theOther.listOfSubtitles[t];
    listOfSubtitles.append ( pNewEntry );
  }

  return *this;
}

bool Subtitles::readProjectFile ( QDomNode &xmlNode )
{
  QString     qsAttribute, infoName, infoText;
  QDomNode    infoNode;
  QDomElement infoElement, theElement = xmlNode.toElement();
  infoName  = theElement.tagName();

  qsAttribute = theElement.attributeNode ( SUBTITLES_TRANSPARENCY ).value();
  if ( ! qsAttribute.isEmpty ( ) )
    iTransparency = qsAttribute.toInt ();
  qsAttribute = theElement.attributeNode ( SUBTITLES_FONT ).value();
  if ( ! qsAttribute.isEmpty ( ) ) {
    QFont theFont;
    if (theFont.fromString ( qsAttribute ))
      font = theFont;
  }
  qsAttribute = theElement.attributeNode ( SUBTITLES_RECT ).value();
  if ( ! qsAttribute.isEmpty ( ) ) {
    // QString "x,y,width,height" 
    QStringList list = QStringList::split ( ",", qsAttribute );
    QRect theRect;
    if (list.count() == 4)
      theRect = QRect(list[0].toInt(), list[1].toInt(),  list[2].toInt(),  list[3].toInt() );
    rect = theRect;
  }
  qsAttribute = theElement.attributeNode ( SUBTITLES_ALIGNMENT ).value();
  if ( ! qsAttribute.isEmpty ( ) ) {
    // QString "x,y,width,height" 
    QStringList list = QStringList::split ( ",", qsAttribute );
    QPoint theAlignment;
    if (list.count() == 2)
      theAlignment = QPoint( list[0].toInt(), list[1].toInt() );
    alignment = theAlignment;
  }
  qsAttribute = theElement.attributeNode ( SUBTITLES_COLORS ) .value ();
  if ( ! qsAttribute.isEmpty ( ) ) {
    QStringList list = QStringList::split ( ",", qsAttribute );
    if ( list.count() == MAX_COLORS ) {
      subColors[0].setNamedColor ( list[0] ); 
      subColors[1].setNamedColor ( list[1] ); 
      subColors[2].setNamedColor ( list[2] ); 
      subColors[3].setNamedColor ( list[3] ); 
    }
  }
  
  infoNode = theElement.firstChild ();  
  while (!infoNode.isNull())	{
    infoElement = infoNode.toElement();
    // Okay, here we read the stored data from the xml file.
    infoName = infoElement.tagName();
    infoText = infoElement.text ();
    if (SUBTITLES_SUBTITLE_FILE == infoName)	{
      qsTempFile = infoText;
    }
    else if (SUBTITLES_SUBTITLE_ENTRY == infoName)	{
      Subtitles::entry *pNewEntry = new entry;
      qsAttribute = infoElement.attributeNode ( SUBTITLES_SUBTITLE_INDEX ).value();
      if (!qsAttribute.isEmpty())
	pNewEntry->iIndex = qsAttribute.toInt ();
      qsAttribute = infoElement.attributeNode ( SUBTITLES_SUBTITLE_START ).value();
      if (!qsAttribute.isEmpty())
	pNewEntry->qsTimeStart = qsAttribute;
      qsAttribute = infoElement.attributeNode ( SUBTITLES_SUBTITLE_STOP ).value();
      if (!qsAttribute.isEmpty())
	pNewEntry->qsTimeStop = qsAttribute;
      pNewEntry->iTimeStart = getTimeFromString ( pNewEntry->qsTimeStart );
      pNewEntry->iTimeStop  = getTimeFromString ( pNewEntry->qsTimeStop  );

      pNewEntry->qsText = infoText;

      listOfSubtitles.append ( pNewEntry );
    }
    infoNode = infoNode.nextSibling ();
  }

  return true;
}

bool Subtitles::writeProjectFile ( QDomElement &inElement )
{
  uint t;
  QDomDocument xmlDoc = inElement.ownerDocument();
  QDomElement  infoElement, tmpFileElement, theElement;
  QDomText     text;  
  entry       *pEntry;

  if (listOfSubtitles.count() < 1)
    return true;

  theElement = xmlDoc.createElement ( SOURCE_OBJECT_SUBTITLES );


  // Here we set the attributes of the <dvdauthor> tag
  theElement.setAttribute( SUBTITLES_TRANSPARENCY, QString ("%1").arg ( (int)iTransparency ) );
  theElement.setAttribute( SUBTITLES_FONT, font.toString ( ) );

  //  inElement.appendChild ( theElement );
  //  return true;

  theElement.setAttribute( SUBTITLES_RECT, QString ("%1,%2,%3,%4").arg(rect.x ( ) ).arg(rect.y ( ) ).arg(rect.width ( ) ).arg(rect.height ( ) ) );
  theElement.setAttribute( SUBTITLES_ALIGNMENT, QString ("%1,%2").arg(alignment.x ( ) ).arg(alignment.y ( ) ) );
  theElement.setAttribute( SUBTITLES_COLORS, QString ("%1,%2,%3,%4").arg(subColors[0].name() ).arg(subColors[1].name() ).arg(subColors[2].name() ).arg(subColors[3].name() ) );

  // store the temp file name too ...
  if ( ! qsTempFile.isEmpty () ) {
    tmpFileElement = xmlDoc.createElement( SUBTITLES_SUBTITLE_FILE );
    text = xmlDoc.createTextNode( qsTempFile );
    tmpFileElement.appendChild( text );
    theElement.appendChild ( tmpFileElement );
  }

  if (listOfSubtitles.count() > 0)	{
    for (t=0;t<listOfSubtitles.count();t++)	{
      pEntry = listOfSubtitles[t];
      infoElement = xmlDoc.createElement( SUBTITLES_SUBTITLE_ENTRY );
      infoElement.setAttribute( SUBTITLES_SUBTITLE_INDEX, QString ("%1").arg( pEntry->iIndex ) );
      infoElement.setAttribute( SUBTITLES_SUBTITLE_START, pEntry->qsTimeStart );
      infoElement.setAttribute( SUBTITLES_SUBTITLE_STOP,  pEntry->qsTimeStop  );

      text = xmlDoc.createTextNode( pEntry->qsText );
      infoElement.appendChild( text );
      
      theElement.appendChild ( infoElement );
    }
  }

  inElement.appendChild ( theElement );
  return true;
}

long Subtitles::getTimeFromString ( QString &qsTime )
{
  long iMSeconds = -1;
  QTime theTime;
  iMSeconds = (long)theTime.msecsTo ( QTime::fromString ( qsTime ) );

  return iMSeconds;
}

QString Subtitles::getStringFromTime ( long iMSTime )
{
  QString qsReturn;
  QTime theTime;
  theTime  = theTime.addMSecs ( iMSTime );
  qsReturn = theTime.toString ( "hh:mm:ss.zzz" );
  return qsReturn;
}

QString Subtitles::getXMLFileName ()
{
  QFileInfo fileInfo ( qsTempFile );
  QString qsReturn;

  qsReturn = QString ("%1/%2.xml").arg( fileInfo.filePath () ).arg ( fileInfo.baseName () );
  return qsReturn;
}

TranscodeInterface::TranscodeInterface ()
{
	iVideoBitrate = 0;
	fFrameRate    = 0.0f;
	iAudioBitrate = 0;
	iSample       = 0;
	iStartingAt   = 0;
	iEndingAt     = 0;
	bTranscoding  = false;
	bRemuxOnly    = false; 
}

TranscodeInterface::~TranscodeInterface ()
{

}

TranscodeInterface & TranscodeInterface::operator = (TranscodeInterface &theOther)
{
	qsVideoFormat = theOther.qsVideoFormat;
	qsVideoType   = theOther.qsVideoType;
	qsResolution  = theOther.qsResolution;
	iVideoBitrate = theOther.iVideoBitrate;
	fFrameRate    = theOther.fFrameRate;
	qsRatio       = theOther.qsRatio;
	qsAudioFormat = theOther.qsAudioFormat;
	qsAudioType   = theOther.qsAudioType;
	iAudioBitrate = theOther.iAudioBitrate;
	iSample       = theOther.iSample;
	iStartingAt   = theOther.iStartingAt;
	iEndingAt     = theOther.iEndingAt;
	bTranscoding  = theOther.bTranscoding;
	bRemuxOnly    = theOther.bRemuxOnly;
	qsTempFile    = theOther.qsTempFile;
	return *this;
}

bool TranscodeInterface::operator == (const TranscodeInterface &theOther)
{
	if ( 	( qsVideoFormat == theOther.qsVideoFormat ) && 
		( qsVideoType   == theOther.qsVideoType   ) &&
		( qsResolution  == theOther.qsResolution  ) &&
		( iVideoBitrate == theOther.iVideoBitrate ) &&
		( fFrameRate    == theOther.fFrameRate    ) &&
		( qsRatio       == theOther.qsRatio       ) &&
		( qsAudioFormat == theOther.qsAudioFormat ) &&
		( qsAudioType   == theOther.qsAudioType   ) &&
		( iAudioBitrate == theOther.iAudioBitrate ) &&
		( iSample       == theOther.iSample       ) &&
		( bRemuxOnly    == theOther.bRemuxOnly    ) &&
		( qsTempFile    == theOther.qsTempFile    ) )
		// The following can be different but the transcoding will still output the same Format.
//		( iEndingAt - iStartingAt == theOther.iEndingAt - theOther.iStartingAt ) )
		return true;
	return false;
}

bool TranscodeInterface::operator != (const TranscodeInterface &theOther)
{
	return !(*this == theOther);
}

bool TranscodeInterface::readProjectFile  (QDomNode &xmlNode)
{
  QString qsAttribute;
  QDomElement theElement = xmlNode.toElement();

  qsAttribute = theElement.attributeNode ( TRANSCODE_VIDEO_FORMAT ).value();
  if ( ! qsAttribute.isEmpty())
    qsVideoFormat = qsAttribute;
  qsAttribute = theElement.attributeNode ( TRANSCODE_VIDEO_TYPE ).value();
  if ( ! qsAttribute.isEmpty())
    qsVideoType = qsAttribute;
  qsAttribute = theElement.attributeNode ( TRANSCODE_RESOLUTION ).value();
  if ( ! qsAttribute.isEmpty())
    qsResolution = qsAttribute;
  qsAttribute = theElement.attributeNode ( TRANSCODE_VIDEO_BITRATE ).value();
  if ( ! qsAttribute.isEmpty())
    iVideoBitrate = qsAttribute.toInt ();
  qsAttribute = theElement.attributeNode ( TRANSCODE_FRAME_RATE ).value();
  if ( ! qsAttribute.isEmpty())
    fFrameRate = qsAttribute.toFloat ();
  qsAttribute = theElement.attributeNode ( TRANSCODE_RATIO ).value();
  if ( ! qsAttribute.isEmpty())
    qsRatio = qsAttribute;
  qsAttribute = theElement.attributeNode ( TRANSCODE_AUDIO_FORMAT ).value();
  if ( ! qsAttribute.isEmpty())
    qsAudioFormat = qsAttribute;
  qsAttribute = theElement.attributeNode ( TRANSCODE_AUDIO_TYPE ).value();
  if ( ! qsAttribute.isEmpty())
    qsAudioType = qsAttribute;
  qsAttribute = theElement.attributeNode ( TRANSCODE_AUDIO_BITRATE ).value();
  if ( ! qsAttribute.isEmpty())
    iAudioBitrate = qsAttribute.toInt ();
  qsAttribute = theElement.attributeNode ( TRANSCODE_SAMPLE_RATE ).value();
  if ( ! qsAttribute.isEmpty())
    iSample = qsAttribute.toInt();
  qsAttribute = theElement.attributeNode ( TRANSCODE_STARTING_AT ).value();
  if ( ! qsAttribute.isEmpty())
    iStartingAt = qsAttribute.toInt();
  qsAttribute = theElement.attributeNode ( TRANSCODE_ENDING_AT ).value();
  if ( ! qsAttribute.isEmpty())
    iEndingAt = qsAttribute.toInt ();
  
  // Always get the TempFileName, empty or not ... here I come ... you can't run ...
  qsTempFile = theElement.text ();    
  
  return true;
}

bool TranscodeInterface::writeProjectFile (QDomElement &theElement)
{
	// Here we set the attributes of the <TranscodeInterface> tag
	if (!qsVideoFormat.isNull())
		theElement.setAttribute( TRANSCODE_VIDEO_FORMAT, qsVideoFormat );
	if (!qsVideoType.isNull())
		theElement.setAttribute( TRANSCODE_VIDEO_TYPE, qsVideoType );
	if (!qsResolution.isNull())
		theElement.setAttribute( TRANSCODE_RESOLUTION, qsResolution );
	if (iVideoBitrate > 0)
		theElement.setAttribute( TRANSCODE_VIDEO_BITRATE, QString ("%1").arg(iVideoBitrate) );
	if (fFrameRate > 0.0)
		theElement.setAttribute( TRANSCODE_FRAME_RATE, QString ("%1").arg(fFrameRate) );
	if (!qsRatio.isNull())
		theElement.setAttribute( TRANSCODE_RATIO, qsRatio );
	if (!qsAudioFormat.isNull())
		theElement.setAttribute( TRANSCODE_AUDIO_FORMAT, qsAudioFormat );
	if (!qsAudioType.isNull())
		theElement.setAttribute( TRANSCODE_AUDIO_TYPE, qsAudioType );
	if (iAudioBitrate > 0)
		theElement.setAttribute( TRANSCODE_AUDIO_BITRATE, QString ("%1").arg(iAudioBitrate) );
	if (iSample > 0)
		theElement.setAttribute( TRANSCODE_SAMPLE_RATE, QString ("%1").arg(iSample) );
	if (iStartingAt > 0)
		theElement.setAttribute( TRANSCODE_STARTING_AT, QString ("%1").arg(iStartingAt) );
	if (iEndingAt > 0)
		theElement.setAttribute( TRANSCODE_ENDING_AT, QString ("%1").arg(iEndingAt) );
	if ( ! qsTempFile.isEmpty ( ) ) {	  
	  QDomDocument xmlDoc = theElement.ownerDocument( );
	  QDomText     text   = xmlDoc.createTextNode ( qsTempFile );
	  theElement.appendChild( text );
	}

	return true;
}

SourceFileInfo::SourceFileInfo ()
{
	pPreview       = NULL;
	bAutotranscode = true;
	pTranscodeInterface = NULL;
	pSubtitles     = NULL;
	bUpdateInfo    = false;
	iPause         =  0;
	iMSecPreview   =  0;
	iTitleset      = -1;
}

SourceFileInfo::~SourceFileInfo ()
{
	if (pPreview)
		delete pPreview;
	if (pTranscodeInterface)
		delete pTranscodeInterface;
	if ( pSubtitles )
	  delete pSubtitles;
}

// The filename for the dvdauthor.xml file depends on the pre-processing
QString SourceFileInfo::getFileName ()
{
  if ( pSubtitles && ( ! pSubtitles->qsTempFile.isEmpty () ) )
    return pSubtitles->qsTempFile;
  if ( pTranscodeInterface ) {
    if ( ! pTranscodeInterface->qsTempFile.isEmpty () )
      return pTranscodeInterface->qsTempFile;
    else {
      // nothing in so we should create the file name
      Utils     theUtils;
      QFileInfo fileInfo ( qsFileName );
      return QString ( "%1/%2.mpeg2" ).arg ( theUtils.getTempPath ( fileInfo.baseName () ) ).arg(fileInfo.baseName () );
    }
  }
  return qsFileName;
}

SourceFileEntry::SourceFileEntry ()
{
	iTitleset     = -1;
	iTitle        = -1;
	iPause        =  0;
	bIsSlideshow  = false;
	bSoundSource  = false;
	sizeThumbnail = QSize (150, 150);
}

SourceFileEntry::~SourceFileEntry()
{
	uint t;
	for (t=0;t<listFileInfos.count();t++)	
		delete listFileInfos[t];
}

bool SourceFileEntry::readProjectFile  (QDomNode &xmlNode)
{
	QString qsAttribute, infoName, infoText;

	QDomNode    infoNode, transcodeNode;
	QDomElement infoElement;
	QDomElement theElement = xmlNode.toElement();

	QDomAttr a = theElement.attributeNode ( SOURCE_OBJECT_DISPLAY_NAME );
	qsDisplayName = a.value();
	a = theElement.attributeNode ( SOURCE_OBJECT_PRE );
	qsPre = a.value();
	a = theElement.attributeNode ( SOURCE_OBJECT_POST );
	qsPost = a.value();
	qsAttribute = theElement.attributeNode ( SOURCE_OBJECT_IS_SOUND_SOURCE ).value();
	bSoundSource = false;
	if ( (!qsAttribute.isEmpty ()) && (qsAttribute == QString ("true")) )
	  bSoundSource = true;
	qsAttribute = theElement.attributeNode ( SOURCE_OBJECT_PAUSE ).value();
	if (!qsAttribute.isEmpty ())
	  iPause = qsAttribute.toInt();

	QDomNode sourceNode = theElement.firstChild();
	while (!sourceNode.isNull() )	{
		theElement = sourceNode.toElement();
		// Okay, here we read the stored data from the xml file.
		QString tagName = theElement.tagName();
		// Okay, this is ugly but after all it is the simplest of all xml file structure.
		// No need to get fancy ...
		if (SOURCE_OBJECT_INFO == tagName)	{
			SourceFileInfo *pFileInfos = new SourceFileInfo;
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_SIZE).value();
			if ( ! qsAttribute.isEmpty ( ) )
				pFileInfos->qsSize = qsAttribute;
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_RESOLUTION).value();
			if ( ! qsAttribute.isEmpty ( ) )
				pFileInfos->qsResolution = qsAttribute;
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_FPS).value();
			if ( ! qsAttribute.isEmpty ( ) )
				pFileInfos->qsFPS = qsAttribute;
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_RATIO).value();
			if ( ! qsAttribute.isEmpty ( ) )
				pFileInfos->qsRatio = qsAttribute;
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_LENGTH).value();
			if ( ! qsAttribute.isEmpty ( ) )
				pFileInfos->qsLength = qsAttribute;
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_VIDEO_FORMAT).value();
			if ( ! qsAttribute.isEmpty ( ) )
				pFileInfos->qsVideoFormat = qsAttribute;
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_AUDIO_FORMAT).value();
			if ( ! qsAttribute.isEmpty ( ) )
				pFileInfos->qsAudioFormat = qsAttribute;
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_STATUS).value();
			if ( ! qsAttribute.isEmpty ( ) )
				pFileInfos->qsStatus = qsAttribute;
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_BITS).value();
			if ( ! qsAttribute.isEmpty ( ) )
				pFileInfos->qsBits = qsAttribute;
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_SAMPLE).value();
			if ( ! qsAttribute.isEmpty ( ) )
				pFileInfos->qsSample = qsAttribute;
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_BPS).value();
			if ( ! qsAttribute.isEmpty ( ) )
				pFileInfos->qsBPS = qsAttribute;
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_PAUSE).value();
			if ( ! qsAttribute.isEmpty ( ) )
			  pFileInfos->iPause = qsAttribute.toInt();
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_TITLESET).value();
			if ( ! qsAttribute.isEmpty ( ) )
			  pFileInfos->iTitleset = qsAttribute.toInt();
			qsAttribute = theElement.attributeNode (SOURCE_OBJECT_AUTOTRANSCODE).value();
			pFileInfos->bAutotranscode = true;
			if ( ! qsAttribute.isEmpty ( ) )
			  pFileInfos->bAutotranscode = ( qsAttribute == QString ("true") );
			qsAttribute = theElement.attributeNode ( SOURCE_OBJECT_MSEC_OFFSET ).value ( );
			if ( ! qsAttribute.isEmpty ( ) )
			  pFileInfos->iMSecPreview = qsAttribute.toInt ( );

			infoNode = theElement.firstChild ();
			while (!infoNode.isNull())	{
				infoElement = infoNode.toElement();
				// Okay, here we read the stored data from the xml file.
				infoName = infoElement.tagName();
				infoText = infoElement.text ();
				if (SOURCE_OBJECT_FILE_NAME == infoName)	{
					if (!infoText.isEmpty())
						pFileInfos->qsFileName = infoText;
				}
				else if (SOURCE_OBJECT_CHAPTERS == infoName)	{
					if (!infoText.isEmpty())
						pFileInfos->listChapters = QStringList::split (",", infoText);
				}
				else if (SOURCE_OBJECT_PROPERTIES == infoName)	{
					qsAttribute = infoElement.attributeNode (SOURCE_PROPERTIES_POST).value();
					if (!qsAttribute.isEmpty())
						pFileInfos->qsPostCommand = qsAttribute;
					qsAttribute = infoElement.attributeNode (SOURCE_PROPERTIES_PRE).value();
					if (!qsAttribute.isEmpty())
						pFileInfos->qsPreCommand = qsAttribute;
					qsAttribute = infoElement.attributeNode (SOURCE_PROPERTIES_PAUSE).value();
					if (!qsAttribute.isEmpty())
						pFileInfos->iPause = qsAttribute.toInt();
				}
				else if (SOURCE_OBJECT_TRANSCODE == infoName)	{
					if ( pFileInfos->pTranscodeInterface)
						delete pFileInfos->pTranscodeInterface;
					pFileInfos->pTranscodeInterface = new TranscodeInterface;
					pFileInfos->pTranscodeInterface->readProjectFile (infoNode);
				}
				else if (SOURCE_OBJECT_SUBTITLES == infoName)	{
					if ( pFileInfos->pSubtitles)
						delete pFileInfos->pSubtitles;
					pFileInfos->pSubtitles = new Subtitles;
					pFileInfos->pSubtitles->readProjectFile (infoNode);
				}
				infoNode = infoNode.nextSibling ();
			}
			listFileInfos.append (pFileInfos);
		}
		else if (SOURCE_OBJECT_CHAPTERS == tagName)	{
			infoText = theElement.text ();
			listChapters = QStringList::split ( QString (","), infoText);
		}
		// Otherwise go to the next node ...
		sourceNode = sourceNode.nextSibling();
	}
	return true;
}

bool SourceFileEntry::writeProjectFile (QDomElement &theElement, bool bAutosave)
{
	// This check means that the slideshow has not yet been finished, thus we should not bother to
	// store this record since the mpeg does probably not exist.
	if (bIsSlideshow && bAutosave)	{
		MessageBox::warning (NULL,QObject::tr("Warning"), QObject::tr ("Warning, the slideshow \n%1\nis not finished.\nThe SourceFileEntry will not be stored.").arg(qsDisplayName), QMessageBox::Ok, QMessageBox::NoButton);
		return true;
	}
	uint t;
	QDomDocument xmlDoc = theElement.ownerDocument();
	QDomElement sourceNode = xmlDoc.createElement( SOURCE_OBJECT );	// <FrameObject>

	QDomElement fileElement, infoElement, chapterElement, transcodeElement, subtitlesElement, propertiesElement; //tag;
	QDomElement tag;
	QDomText text;
	// Here we set the attributes of the <dvdauthor> tag
	if ( ! qsDisplayName.isNull() )
		sourceNode.setAttribute( SOURCE_OBJECT_DISPLAY_NAME, qsDisplayName );
	if ( ! qsPre.isNull() )
		sourceNode.setAttribute( SOURCE_OBJECT_PRE, qsPre );
	if ( ! qsPost.isNull() )
		sourceNode.setAttribute( SOURCE_OBJECT_POST, qsPost );
	if (bSoundSource)
		sourceNode.setAttribute( SOURCE_OBJECT_IS_SOUND_SOURCE, "true" );
	sourceNode.setAttribute( SOURCE_OBJECT_PAUSE, QString ("%1").arg (iPause) ); 

	if (listFileInfos.count() > 0)	{
		for (t=0;t<listFileInfos.count();t++)	{
			infoElement = xmlDoc.createElement( SOURCE_OBJECT_INFO );
			if (!listFileInfos[t]->qsSize.isNull())
				infoElement.setAttribute( SOURCE_OBJECT_SIZE, listFileInfos[t]->qsSize );
			if (!listFileInfos[t]->qsResolution.isNull())
				infoElement.setAttribute( SOURCE_OBJECT_RESOLUTION, listFileInfos[t]->qsResolution );
			if (!listFileInfos[t]->qsFPS.isNull())
				infoElement.setAttribute( SOURCE_OBJECT_FPS, listFileInfos[t]->qsFPS );
			if (!listFileInfos[t]->qsRatio.isNull())
				infoElement.setAttribute( SOURCE_OBJECT_RATIO, listFileInfos[t]->qsRatio );
			if (!listFileInfos[t]->qsLength.isNull())
				infoElement.setAttribute( SOURCE_OBJECT_LENGTH, listFileInfos[t]->qsLength );
			if (!listFileInfos[t]->qsVideoFormat.isNull())
				infoElement.setAttribute( SOURCE_OBJECT_VIDEO_FORMAT, listFileInfos[t]->qsVideoFormat );
			if (!listFileInfos[t]->qsAudioFormat.isNull())
				infoElement.setAttribute( SOURCE_OBJECT_AUDIO_FORMAT, listFileInfos[t]->qsAudioFormat );
			if (!listFileInfos[t]->qsStatus.isNull())
				infoElement.setAttribute( SOURCE_OBJECT_STATUS, listFileInfos[t]->qsStatus );
			if (!listFileInfos[t]->qsBits.isNull())
				infoElement.setAttribute( SOURCE_OBJECT_BITS, listFileInfos[t]->qsBits );
			if (!listFileInfos[t]->qsSample.isNull())
				infoElement.setAttribute( SOURCE_OBJECT_SAMPLE, listFileInfos[t]->qsSample );
			if (!listFileInfos[t]->qsBPS.isNull())
				infoElement.setAttribute( SOURCE_OBJECT_BPS, listFileInfos[t]->qsBPS );
			if ( listFileInfos[t]->iPause !=-1 )
			        infoElement.setAttribute( SOURCE_OBJECT_PAUSE, QString ("%1").arg(listFileInfos[t]->iPause) );
			if ( listFileInfos[t]->iTitleset != -1 )
			        infoElement.setAttribute( SOURCE_OBJECT_TITLESET, QString ("%1").arg(listFileInfos[t]->iTitleset) );
			if ( listFileInfos[t]->bAutotranscode == false )
			        infoElement.setAttribute( SOURCE_OBJECT_AUTOTRANSCODE, "false" );
			if ( listFileInfos[t]->iMSecPreview !=-1 )
			        infoElement.setAttribute( SOURCE_OBJECT_MSEC_OFFSET, QString ("%1").arg(listFileInfos[t]->iMSecPreview) );
			// Here we create another level in the XML tree for name and chapter ...
				// First the file name
				fileElement = xmlDoc.createElement( SOURCE_OBJECT_FILE_NAME );
				text = xmlDoc.createTextNode(listFileInfos[t]->qsFileName);
				fileElement.appendChild( text );
				infoElement.appendChild( fileElement );
				// Second the properties (Post / Pre, and Pause)
				propertiesElement = xmlDoc.createElement( SOURCE_OBJECT_PROPERTIES );
				if (!listFileInfos[t]->qsPostCommand.isNull())
					propertiesElement.setAttribute( SOURCE_PROPERTIES_POST, listFileInfos[t]->qsPostCommand );
				if (!listFileInfos[t]->qsPreCommand.isNull())
					propertiesElement.setAttribute( SOURCE_PROPERTIES_PRE, listFileInfos[t]->qsPreCommand );
				propertiesElement.setAttribute( SOURCE_PROPERTIES_PAUSE, QString ("%1").arg(listFileInfos[t]->iPause ));
				infoElement.appendChild( propertiesElement );
				// Then chapters if avail.
				if (listFileInfos[t]->listChapters.count() > 0)	{
					chapterElement = xmlDoc.createElement( SOURCE_OBJECT_CHAPTERS );
					text = xmlDoc.createTextNode(listFileInfos[t]->listChapters.join(QString(",")));
					chapterElement.appendChild( text );
					infoElement.appendChild( chapterElement );
				}
				// next to last the TranscodeInterface if any.
				if (listFileInfos[t]->pTranscodeInterface)	{
					transcodeElement = xmlDoc.createElement( SOURCE_OBJECT_TRANSCODE );
					listFileInfos[t]->pTranscodeInterface->writeProjectFile (transcodeElement);
					infoElement.appendChild( transcodeElement );
				}
				// And finally the TranscodeInterface if any.
				if (listFileInfos[t]->pSubtitles)	{
				  //					subtitlesElement = xmlDoc.createElement ( SOURCE_OBJECT_SUBTITLES );
					listFileInfos[t]->pSubtitles->writeProjectFile ( infoElement );
					//					listFileInfos[t]->pSubtitles->writeProjectFile ( subtitlesElement );
					//					infoElement.appendChild ( subtitlesElement );
				}
			sourceNode.appendChild( infoElement );
		}
	}
	if (listChapters.count() > 0)	{
//printf ("SourceFileEntry::writeProjectFile <%d><%s>\n", listChapters.count (), (const char *)listChapters[0]);
		chapterElement = xmlDoc.createElement( SOURCE_OBJECT_CHAPTERS );
		sourceNode.appendChild( chapterElement );
		text = xmlDoc.createTextNode(listChapters.join(QString(",")));
		chapterElement.appendChild( text );
	}

	theElement.appendChild( sourceNode );
	return true;
}

SourceFileEntry *SourceFileEntry::flatClone ()
{
  // Clones this SourceFileEntries without the deep copy of the 
  // SourceFileInfos.
  SourceFileEntry *pClone = new SourceFileEntry;

  pClone->listFileInfos = listFileInfos;
  pClone->qsDisplayName = qsDisplayName;
  pClone->listChapters  = listChapters;
  pClone->bSoundSource  = bSoundSource;
  pClone->bIsSlideshow  = bIsSlideshow;
  pClone->iJumpStart    = iJumpStart;
  pClone->iTitleset     = iTitleset;
  pClone->iTitle        = iTitle;
  pClone->qsPre         = qsPre;
  pClone->qsPost        = qsPost;
  pClone->iPause        = iPause;  
  
  return pClone;
}

SourceFileEntry & SourceFileEntry::operator = (SourceFileEntry &theOther)
{
	uint t;
	SourceFileInfo *pInfo;
	// First we take care of the entries in the list. Please note that we should keep the current ones around
	// in case we are cloning this entry.
	QValueList<SourceFileInfo *> listTemp2;
	for (t=0;t<theOther.listFileInfos.count();t++)	{
		pInfo = new SourceFileInfo ();
		*pInfo = *theOther.listFileInfos[t];
		listTemp2.append (pInfo);
	}
	// Now we should be save here to remove the entries ...	
	for (t=0;t<listFileInfos.count ();t++)
		delete listFileInfos[t];
	listFileInfos.clear();

	listFileInfos = listTemp2;

	qsDisplayName = theOther.qsDisplayName;
	listChapters  = theOther.listChapters;
	bSoundSource  = theOther.bSoundSource;
	bIsSlideshow  = theOther.bIsSlideshow;
	iJumpStart    = theOther.iJumpStart;
	iTitleset     = theOther.iTitleset;
	iTitle        = theOther.iTitle;
	qsPre         = theOther.qsPre;
	qsPost        = theOther.qsPost;
	iPause        = theOther.iPause;

	return *this;
}

SourceFileInfo & SourceFileInfo::operator = (SourceFileInfo &theOther)
{
	qsFileName     = theOther.qsFileName;
	qsSize         = theOther.qsSize;
	qsResolution   = theOther.qsResolution;
	qsFPS          = theOther.qsFPS;
	qsRatio        = theOther.qsRatio;
	qsLength       = theOther.qsLength;
	qsAudioFormat  = theOther.qsAudioFormat;
	qsVideoFormat  = theOther.qsVideoFormat;
	qsStatus       = theOther.qsStatus;
	qsBits         = theOther.qsBits;
	qsSample       = theOther.qsSample;
	qsBPS          = theOther.qsBPS;
	listChapters   = theOther.listChapters;
	qsPreCommand   = theOther.qsPreCommand;
	qsPostCommand  = theOther.qsPostCommand;
	iPause         = theOther.iPause;
	iMSecPreview   = theOther.iMSecPreview;  
	iTitleset      = theOther.iTitleset;
	bAutotranscode = theOther.bAutotranscode;
	if (theOther.pTranscodeInterface)	{
		if (!pTranscodeInterface)
			pTranscodeInterface = new TranscodeInterface ();
		*(pTranscodeInterface) = *(theOther.pTranscodeInterface);
	}
	else if (pTranscodeInterface)	{
		delete pTranscodeInterface;
		pTranscodeInterface = NULL;
	}
	if (theOther.pSubtitles)	{
		if ( ! pSubtitles )
			pSubtitles = new Subtitles;
		*(pSubtitles) = *(theOther.pSubtitles);
	}
	else if ( pSubtitles )	{
		delete pSubtitles;
		pSubtitles = NULL;
	}
	return *this;
}

