/****************************************************************************
** DialogCreateTemplate class
**
** Created: Mon Jun 10 22:48:00 2005
**      by: Varol Okan using XEmacs
**
**
****************************************************************************/
#include <sys/types.h>
#include <sys/stat.h>

#include <qnetworkprotocol.h>
#include <qradiobutton.h>
#include <qprogressbar.h>
#include <qmessagebox.h>
#include <qtextedit.h>
#include <qcombobox.h>
#include <qfileinfo.h>
#include <qlineedit.h>
#include <qnetwork.h>
#include <qprocess.h>
#include <qspinbox.h>
#include <qpainter.h>
#include <qcursor.h>
#include <qslider.h>
#include <qregexp.h>
#include <qframe.h>
#include <qdir.h>
#include <qftp.h>

#include "CONFIG.h"
#include "global.h"
#include "utils.h"
#include "dvdmenu.h"
#include "xml_dvd.h"
#include "messagebox.h"
#include "menuobject.h"
#include "textobject.h"
#include "menupreview.h"
#include "buttonobject.h"
#include "qdvdauthorinit.h"
#include "sourcefileentry.h"
#include "objectcollection.h"
#include "dialogcreatetemplate.h"

/////////////////////////////////////////////////////////////////////////////////////////////
//
// Here is the class for the preview ...
//
/////////////////////////////////////////////////////////////////////////////////////////////

CreateTemplatePreview::CreateTemplatePreview ( QWidget *pParent, const char *pName, WFlags flags )
  : QFrame ( pParent, pName, flags )
{
  m_fScale   = 1.0;
  m_pDVDMenu = NULL;
  m_pDialog  = NULL;
}

CreateTemplatePreview::~CreateTemplatePreview ( )
{

}

void CreateTemplatePreview::initMe ( DVDMenu *pMenu, DialogCreateTemplate *pTemplateDialog )
{
  m_pDVDMenu = pMenu;
  m_pDialog  = pTemplateDialog;
  createObjectList ( );
  qInitNetworkProtocols ( );
}

void CreateTemplatePreview::setBackgroundFileName ( const QString &qsFileName )
{
  m_qsBackgroundFileName = qsFileName;
}

QValueList<MenuObject *> &CreateTemplatePreview::getDropZones ( )
{
  return m_listOfDropZones;
}

void CreateTemplatePreview::createObjectList ( )
{
  int t;
  MenuObject *pMenuObject;
  QValueList<ButtonObject *>listOfButtons;
  listOfButtons = m_pDVDMenu->getButtons ();
  for (t=0;t<(int)listOfButtons.count();t++) {
    pMenuObject = (MenuObject *) listOfButtons[t];
    m_listOfMenuObjects.append ( pMenuObject );
  }
  return;
}

void CreateTemplatePreview::mousePressEvent ( QMouseEvent *pEvent )
{
  QFrame::mousePressEvent ( pEvent );

  MenuObject *pObject = isWithinObject ( pEvent->pos ( ) );
  if ( ! pObject )
    return;
  if ( m_listOfDropZones.findIndex ( pObject ) == -1 )
    m_listOfDropZones.append ( pObject );
  else
    m_listOfDropZones.remove ( pObject );
  
  update ( );
}

void CreateTemplatePreview::mouseReleaseEvent ( QMouseEvent *pEvent )
{
  QFrame::mousePressEvent ( pEvent );
}

void CreateTemplatePreview::mouseDoubleClickEvent ( QMouseEvent *pEvent )
{
  QFrame::mousePressEvent ( pEvent );
}

void CreateTemplatePreview::mouseMoveEvent ( QMouseEvent *pEvent )
{
  QFrame::mousePressEvent ( pEvent );
}

void CreateTemplatePreview::paintEvent ( QPaintEvent *pEvent )
{
  QFrame::paintEvent ( pEvent );

  int t;
  QPainter    thePainter ( this );
  MenuObject *pMenuObject;
  QString     qsNumber;
  QRect       rect;
  //void drawText ( int x, int y, const QString &, int len = -1, TextDirection dir = Auto )
  thePainter.setBrush ( Qt::black  );
  thePainter.setPen   ( Qt::yellow );
    
  for (t=0;t<(int)m_listOfDropZones.count ();t++) {
    pMenuObject = m_listOfDropZones[t];
    rect = pMenuObject->boundingRect ( );
    QRect theRect ( (int)(rect.x     ( ) / m_fScale), (int)(rect.y      ( ) / m_fScale),
		    (int)(rect.width ( ) / m_fScale), (int)(rect.height ( ) / m_fScale) );
    qsNumber  = QString ( "%1" ).arg ( t + 1 );
    thePainter.drawRect ( theRect );
    thePainter.drawText ( theRect, Qt::AlignCenter|Qt::DontClip, qsNumber );
  }
}

void CreateTemplatePreview::polish ()
{
  QImage  theImage;
  QPixmap thePix;

  QFrame::polish ( );

  theImage.load ( m_qsBackgroundFileName );

  theImage = theImage.smoothScale ( width(), height(), QImage::ScaleMin );
  thePix.convertFromImage ( theImage );

  // calculate the scale of th preview ..
  int iWidth = 720;
  if ( m_pDVDMenu->getInterface( )->iWidth > 0 )
    iWidth = m_pDVDMenu->getInterface( )->iWidth;
  m_fScale = (float) iWidth / thePix.width ( );

  setFixedWidth  ( thePix.width ( ) );
  setFixedHeight ( thePix.height( ) );
  setBackgroundPixmap ( thePix );
}

MenuObject *CreateTemplatePreview::isWithinObject ( const QPoint &point )
{
  int t;
  MenuObject *pObject;
  QPoint thePoint = point;

  // take care of th scaling etween menu and the slightly smaller preview.
  thePoint.setX ( (int) ( m_fScale * point.x ( ) ) );
  thePoint.setY ( (int) ( m_fScale * point.y ( ) ) );

  // Next compare all objects from the list ...
  for (t=0;t<(int)m_listOfMenuObjects.count ();t++) {
    pObject = m_listOfMenuObjects[t];
    if ( ! pObject )
      continue;
    if ( pObject->boundingRect().contains ( thePoint ) ) {
      //      printf ("   =-> DialogCreateTemplate::isWithinObject <%dx%d> = <%dx%d>x<%dx%d>\n", thePoint.x(), thePoint.y(), pObject->boundingRect().x(), pObject->boundingRect().width (), pObject->boundingRect().y(), pObject->boundingRect().height () );
      return pObject;
    }
  }
  return NULL;
}

void CreateTemplatePreview::ensureUniqueDropZoneName ()
{
  // One requirement for the Templates to work is that the DropZones are uniquely named.
  // This function will take care of this.
  // The last two characters are used as a way to create a unique name.
  // if the last two chars are numbers we will increase this number until we hit uniqueness.
  int t, iUniqueCounter;
  QString qsName;
  QChar c1, c2;

  for (t=0;t<(int)m_listOfDropZones.count( );t++) {
    qsName = m_listOfDropZones[t]->name( );
    while ( ! isUniqueName ( t, qsName ) ) {
      c1 = qsName[ qsName.length ( ) - 1 ];
      c2 = qsName[ qsName.length ( ) - 2 ];
      if ( ( c1.digitValue ( ) == -1 ) || ( c2.digitValue ( ) == -1 ) ) {
	qsName += "00"; // try this if the last two chars are no digits
	m_listOfDropZones[t]->setName ( qsName );
	continue; 
      }
      iUniqueCounter  = 10*c2.digitValue ( );
      iUniqueCounter +=    c1.digitValue ( );
      qsName = qsName.left ( qsName.length () - 2 );
      qsName.sprintf ( "%s%02d", qsName.ascii(), ++iUniqueCounter );
      m_listOfDropZones[t]->setName ( qsName );
    }
  }
}

bool CreateTemplatePreview::isUniqueName ( int iCurrentPos, QString &qsName )
{
  int t;
  for (t=0;t<(int)m_listOfDropZones.count ();t++ ) {
    if ( t == iCurrentPos )
      continue;
    if ( qsName == m_listOfDropZones[t]->name () )
      return false;
  }
  return true;
}

/////////////////////////////////////////////////////////////////////////////////////////////
//
//  Here is the actual Dialog ...
//
/////////////////////////////////////////////////////////////////////////////////////////////

DialogCreateTemplate::DialogCreateTemplate (QWidget *pParent, const char *pName, WFlags f )
	: uiCreateTemplate (pParent, pName, f)
{
  m_pDVDMenu         = NULL;
  m_pFrameProperties = NULL;
  m_bInstallDone     = false;
  m_iStatsID         = -1;
  m_pNewProcess      = NULL;
}

DialogCreateTemplate::~DialogCreateTemplate ()
{
	// The Dialog takes care of the destruction of the generated tabs,
	// so we won't have to do it manually here
}

void DialogCreateTemplate::initMe ( DVDMenu *pDVDMenu )
{
  m_pDVDMenu = pDVDMenu;
  QDVDAuthorInit qInit;
  QString qsAuthor, qsContactInfo;
  // Here we create the main templateFrame
  QGridLayout *pLayout = new QGridLayout( m_pOuterFrame, 1, 1, 11, 6, "WizardPageLayout_2"); 
  m_qsCreateString = "iuuq;00rewebvuips/tpvsdfgpshf/ofu0ufnqmbuft0";
  
  qsAuthor      = qInit.getTemplateAuthor  ( );
  qsContactInfo = qInit.getTemplateContact ( );

  //  m_pFrameProperties = new QFrame     ( m_pOuterFrame, "m_pFrameProperties" );
  m_pFrameProperties = new CreateTemplatePreview ( m_pOuterFrame, "m_pFrameProperties" );
  m_pFrameProperties->setSizePolicy  ( QSizePolicy( (QSizePolicy::SizeType)1, (QSizePolicy::SizeType)1, 2, 2, m_pFrameProperties->sizePolicy().hasHeightForWidth() ) );
  m_pFrameProperties->setFrameShape  ( QFrame::StyledPanel );
  m_pFrameProperties->setFrameShadow ( QFrame::Raised );
  m_pFrameProperties->initMe         ( pDVDMenu, this );
  QString qsTemp;
  for (int t=0; t<(int)m_qsCreateString.length();t++ ) {
    char c = m_qsCreateString.constref ( t );
    qsTemp += --c;
  }
  
  pLayout->addWidget( m_pFrameProperties, 1, 1 );
  QSpacerItem *spacer1 = new QSpacerItem( 20, 2, QSizePolicy::Minimum, QSizePolicy::Expanding );
  pLayout->addItem( spacer1, 0, 1 );
  QSpacerItem *spacer2 = new QSpacerItem( 20, 2, QSizePolicy::Minimum, QSizePolicy::Expanding );
  pLayout->addItem( spacer2, 2, 1 );
  QSpacerItem *spacer3 = new QSpacerItem( 2, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
  pLayout->addItem( spacer3, 1, 2 );
  QSpacerItem *spacer4 = new QSpacerItem( 2, 20, QSizePolicy::Expanding, QSizePolicy::Minimum );
  pLayout->addItem( spacer4, 1, 0 );

  QWidget *pDropZoneTab = m_pTabWidget->page    ( 1 );
  m_pTabWidget->setTabEnabled ( pDropZoneTab, false );
  QWidget *pInstallTab = m_pTabWidget->page     ( 2 );
  m_pTabWidget->setTabEnabled ( pInstallTab,  false );
  m_qsCreateString = qsTemp;

  m_pEditAuthor->setText  ( qsAuthor );
  m_pEditContact->setText ( qsContactInfo );
  
  connect ( m_pButtonCreateTemplate, SIGNAL ( clicked ( ) ), this, SLOT ( slotCreateTemplate ( ) ) );
  connect ( m_pButtonInstall,        SIGNAL ( clicked ( ) ), this, SLOT ( slotInstall        ( ) ) );
  connect ( m_pButtonHelp,           SIGNAL ( clicked ( ) ), this, SLOT ( slotHelp           ( ) ) );
  connect ( m_pButtonUpload,         SIGNAL ( clicked ( ) ), this, SLOT ( slotUpload         ( ) ) );
  connect ( &m_Network,              SIGNAL ( data    ( const QByteArray &, QNetworkOperation * ) ),        this, SLOT ( slotNetworkData ( const QByteArray &, QNetworkOperation * ) ) );
  connect ( &m_Network,              SIGNAL ( finished( QNetworkOperation * ) ), this, SLOT ( slotNetworkFinished ( QNetworkOperation * ) ) );
}

void DialogCreateTemplate::polish ( )
{
  Utils   theUtils;
  QString qsFileName;
  QImage  theImage;
  QPixmap thePix;

  uiCreateTemplate::polish ( );

  qsFileName = theUtils.getTempFile ( m_pDVDMenu->name() + QString ("/") + QString ( BACKGROUND_NAME ) );
  m_pDVDMenu->createMask  ( qsFileName, BACKGROUND_IMG, true );
  QFileInfo fileInfo ( qsFileName );
  
  if ( ! fileInfo.exists ( ) )
    return;
  theImage.load ( qsFileName );
  m_pFrameProperties->setBackgroundFileName ( qsFileName );

  theImage = theImage.smoothScale( 200, 200, QImage::ScaleMin);
  thePix.convertFromImage ( theImage );

  m_pFrameThumbnail->setPaletteBackgroundPixmap ( thePix );
  m_pFrameThumbnail->setMaximumSize ( thePix.size ( ) );  
}

void DialogCreateTemplate::slotCreateTemplate ( ) 
{
  int t;
  QString qsDefineDropZones = tr ( "Define DropZones >>>" );
  QString qsCreateTemplate  = tr ( "Create Template >>>" );
  QString qsExit            = tr ( "Exit" );

  // User clicked on the [Exit] button.
  if ( m_pButtonCreateTemplate->text () == qsExit ) {
    // next we want to make sure the user installed the Template ...
    if ( ! m_bInstallDone ) {
      if ( MessageBox::question ( this, tr ("Template Not Yet Installed"), tr("Do you want to install the template before you exit this dialog ?"), QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes )
	// Okay lets install first ...
	slotInstall ( );
    }
    // and then exit ...
    QDVDAuthorInit qInit;
    QString qsAuthor, qsContactInfo;
    qsAuthor      = m_pEditAuthor->text  ( );
    qsContactInfo = m_pEditContact->text ( );
    
    qInit.setTemplateAuthor  ( qsAuthor );
    qInit.setTemplateContact ( qsContactInfo );

    qInit.saveIniFile ( );
    accept ( );
    return;
  }
  // User clicked on the [Create Template >>>] button.
  else if ( m_pButtonCreateTemplate->text ( ) == qsCreateTemplate ) { 
    QValueList<MenuObject *>list = m_pFrameProperties->getDropZones ( );
    if ( list.count ( ) < 1 ) {
      if ( MessageBox::question ( this, tr("No Drop-Zones defined."), 
				  tr ("No Drop-Zones defines.\nDo you want to select some Drop-Zones (ButtonObjects) for this template ?"), 
				  QMessageBox::Yes, QMessageBox::No ) == QMessageBox::Yes ) {
	m_pTabWidget->setCurrentPage ( 1 );
	return;
      }
    }
    m_pButtonCreateTemplate->setText ( qsExit );
    QCursor myCursor ( QCursor::WaitCursor );
    setCursor        ( myCursor );
    // Here we can create the template ...
    QString qsTemplatePackageFileName = createTemplate ( );
    myCursor = QCursor ( QCursor::ArrowCursor );
    setCursor          ( myCursor );

    if ( qsTemplatePackageFileName.isEmpty () )
      return;
    
    QWidget *pInstallTab = m_pTabWidget->page ( 2 );
    m_pTabWidget->setTabEnabled      ( pInstallTab, true );
    m_pTabWidget->setCurrentPage     ( 2 );
    m_pButtonCreateTemplate->setText ( qsExit );
    return;
  }
  // User clicked on the [Define DropZones >>>] button.
  
  // first verify if all required data was entered.
  QLineEdit *arrayRequiredInfo[] = { m_pEditAuthor, m_pEditVersion, m_pEditHeader, m_pEditFileName };
  for ( t=0;t<4;t++) {
    if ( arrayRequiredInfo[t]->text().isEmpty ( ) ) {
      MessageBox::warning ( this, tr("Missing information."), 
			    tr ("One or multiple required information is missing.") );
      m_pTabWidget->setCurrentPage ( 0 );
      return;
    }
  }

  QWidget *pDefineDropZonesTab = m_pTabWidget->page ( 1 );
  m_pTabWidget->setTabEnabled      ( pDefineDropZonesTab, true );
  m_pTabWidget->setCurrentPage     ( 1 );
  m_pButtonCreateTemplate->setText ( qsCreateTemplate );
}

void DialogCreateTemplate::slotHelp ( )
{
  QString qsHeader, qsHtml;
  qsHeader = tr ( "Create a template." );

  if ( m_pTabWidget->currentPageIndex ( ) == 0 ) {
    qsHtml  = tr ( "This dialog helps you create a template from an existing DVD menu.<P>" );
    qsHtml += tr ( "The mandatory information is marked with a red <FONT><B>X</B></FONT>.<P>" );
  }
  else if ( m_pTabWidget->currentPageIndex ( ) == 1 ) {
    qsHtml  = tr ( "In this tab you will have to select the active DropZones or the Template.<P>" );
    qsHtml += tr ( "Please note that you can only use ButtonObjects as DropZone." );
  }
  else if ( m_pTabWidget->currentPageIndex ( ) == 2 ) {
    qsHtml  = tr ( "Here you can Install the Template to your compuer.<P>" );
    qsHtml += tr ( "Please also consider to upload your template for other users to use." );
  }

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

void DialogCreateTemplate::slotInstall ( )
{
  // Sanity check if the user specified any DropZone(s)
  QValueList<MenuObject *>listOfDropZones = m_pFrameProperties->getDropZones ();

  if ( listOfDropZones.count () < 1 ) {
    if ( MessageBox::warning ( this, tr ("No Drop Zones specified."), 
			       tr("No Drop Zones specified,\nAre you sure you want to install this template ?"), 
			       QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
      return;
  }

  // Okay at this point I should have all required information ... lets get started ...
  QString qsPrefixDir;
  QString qsInstallDir = PREFIX_DIRECTORY"/share/qdvdauthor/";
  if ( m_pRadioLocally->isChecked ( ) )
    qsInstallDir = QDir::homeDirPath ( ) + "/.qdvdauthor/";
  qsPrefixDir = qsInstallDir;

  qsInstallDir += getTypePath ( );
  qsInstallDir += m_pEditFileName->text ();
  // Check if the template already exists ...
  QDir theInstallDir ( qsInstallDir );
  QString qsCommand;
  qsCommand = Global::qsBashString;

  if ( theInstallDir.exists ( ) ) {
    if ( MessageBox::warning ( this, tr ("Template exists already"), 
			       tr("A Template with this name exists already.\n Do you want to replace it ?"), 
			       QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No ) {
      m_pTabWidget->setCurrentPage ( 0 );
      m_pEditFileName->setSelection( 0, m_pEditFileName->text( ).length ( ) );
      return;
    }
    // First we should remove the current directory.
    qsCommand += QString ( "rm -r %1\n" ).arg ( qsInstallDir );
    //system ( qsCommand.ascii () );
  }

  QString qsExecutable;
  QFile theFile;
  QDir theDir ( qsInstallDir );
  if ( ! theDir.exists ( ) )
    qsCommand += QString ( "mkdir -p %1;\n" ).arg ( qsInstallDir );
  qsCommand += QString ( "cd %1; tar -xzf %2/%3.tar.gz\n" ).arg ( qsPrefixDir ).arg ( Global::qsTempPath ).arg ( m_pEditFileName->text ( ) );
  // Last we use the same routine to install as in TemplateDownload ...
  
  qsExecutable = QString ( "%1/execute.sh" ).arg ( Global::qsTempPath );
  theFile.setName  ( qsExecutable );
  if ( theFile.open( IO_WriteOnly ) ) {
    QTextStream stream( &theFile );
    stream << qsCommand;
    theFile.close ( );
  }
  chmod ((const char *)QString( qsExecutable ), S_IEXEC | S_IRUSR | S_IWRITE);
  
  installToSystem ( qsExecutable, m_pRadioLocally->isChecked ( ) );

  m_bInstallDone = true;
}

#define graph(x) x##in
#define draw cd
QString DialogCreateTemplate::findGuiSU ( )
{
  uint t;
  QString qsReturn;
  char *arraySUs[3] = {"kdesu", "xsu", "gnomesu"};
  QFileInfo fileInfo("/tmp/out.txt");
  for (t=0;t<3;t++)	{
    // the next check is to see if we can find kdesu
    system ((const char *)QString ("which %1 > %2/out.txt 2>/dev/null").arg( arraySUs[t] ).arg ( Global::qsTempPath ) );
    fileInfo.setFile("/tmp/out.txt");
    // Okay we cna not find it, so we wont bother asking the user ...
    if (fileInfo.size() > 4)	{
      qsReturn = QString ("%1").arg( arraySUs[t] );
      return qsReturn;
    }
  }
  return qsReturn;
}

void DialogCreateTemplate::installToSystem ( QString &qsCommand, bool bInstallLocally )
{
  if ( m_pNewProcess )	{
    if ( m_pNewProcess->isRunning ( ) )
      return;
    else 
      delete m_pNewProcess;
  }

  m_pNewProcess  = new QProcess ( this );
  connect( m_pNewProcess, SIGNAL ( readyReadStdout ( ) ), this, SLOT ( slotReadFromProcess ( ) ) );
  connect( m_pNewProcess, SIGNAL ( readyReadStderr ( ) ), this, SLOT ( slotReadFromProcess ( ) ) );
  connect( m_pNewProcess, SIGNAL ( processExited   ( ) ), this, SLOT ( slotProcessExited   ( ) ) );
  
  if ( ! bInstallLocally ) {
    // the next check is to see if we can find kdesu
    QString qsGuiSU = findGuiSU ( );
    if ( qsGuiSU.isEmpty ( ) ) {
      MessageBox::information (NULL, tr ( "Could not find kdesu, xsu, or gnomesu" ),
        tr ( "Without kdesu, xsu, or gnomesu I can not istall them templates in %1/share/qdvdauthor/.\n").
	arg ( PREFIX_DIRECTORY ), QMessageBox::Ok ,  QMessageBox::NoButton);
      return;
    }  
    if (qsGuiSU == QString ("kdesu"))	{
      m_pNewProcess->addArgument ("kdesu");
      m_pNewProcess->addArgument ("-n");
      m_pNewProcess->addArgument ("-t");
      m_pNewProcess->addArgument ("-c");
    }
    else if (qsGuiSU == QString ("xsu"))	{
      m_pNewProcess->addArgument ("xsu");
      m_pNewProcess->addArgument ("--username");
      m_pNewProcess->addArgument ("root");
      m_pNewProcess->addArgument ("--message");
      m_pNewProcess->addArgument ("Please type in the root password");
      m_pNewProcess->addArgument ("--command");
    }
    else if (qsGuiSU == QString ("gnomesu"))	{
      m_pNewProcess->addArgument ("xsu");
      m_pNewProcess->addArgument ("--username");
      m_pNewProcess->addArgument ("root");
      m_pNewProcess->addArgument ("--message");
      m_pNewProcess->addArgument ("Please type in the root password");
      m_pNewProcess->addArgument ("--command");
    }
  }
  m_pNewProcess->addArgument ( qsCommand );
  
  m_pNewProcess->start ();
}

void DialogCreateTemplate::slotReadFromProcess  ( )
{
  if ( ! m_pNewProcess )
    return;
  QString stdOut = m_pNewProcess->readStdout ( );
  if (stdOut.length() > 5)
    m_pEditOutput->append ( stdOut );
  QString stdErr = m_pNewProcess->readStderr ( );
  if (stdErr.length() > 5)
    m_pEditOutput->append ( stdErr );
}

void DialogCreateTemplate::slotProcessExited ()
{
  slotReadFromProcess ( );
  m_pProgressUpload->setProgress ( 100, 100 );

  m_pEditOutput->append ( tr( "Finished Installing the templates.") );
}

QString DialogCreateTemplate::getTypePath ()
{
  QString qsPath;
  qsPath = "static/";
  if ( m_pComboType->currentText () == QString ( "Animated" ) )
       qsPath = "animated/";
  else if ( m_pComboType->currentText () == QString ( "Transition" ) )
    qsPath= "transition/";
  return qsPath;
}

QString DialogCreateTemplate::createTemplate ( )
{
  // This function will 
  // 1) create the directory under Global::qsTempPath
  // 2) create the template in this directory
  // 3) tar, gz the result
  QString qsCommand, qsTemplatePath;
  QDir theDir;

  qsTemplatePath = QString ( "%1/%2%3").arg ( Global::qsTempPath ).arg ( getTypePath ( ) ).arg ( m_pEditFileName->text ( ) );
  qsCommand = QString ( "mkdir -p \"%1/background\"" ).arg ( qsTemplatePath );
  system ( qsCommand.ascii () );

  theDir = QDir ( qsTemplatePath );
  if ( ! theDir.exists () ) {
    MessageBox::warning ( this, tr ( "Failed to create temp directory" ), 
			  tr( "Failed to create Temp directory\n\n%1\n\nPlease make sure you have read/write permission to %2." )
			  .arg ( qsTemplatePath ).arg ( Global::qsTempPath ) );
    QString qsTemp;
    return qsTemp;
  }
  
  m_pFrameProperties->ensureUniqueDropZoneName ( );
  if ( ! createTemplateXml ( qsTemplatePath ) )
    return qsTemplatePath;
  if ( ! createBackground ( qsTemplatePath ) )
    return qsTemplatePath;
  
  // These two functions are for convenience ...
  //  createIndexXml ( );
  //  createWebHtml  ( );

  qsTemplatePath = QString ( "%2%3").arg ( getTypePath ( ) ).arg ( m_pEditFileName->text ( ) );
  qsCommand = QString ( "cd %1; tar -czf %2.tar.gz %3" ).arg( Global::qsTempPath ).arg( m_pEditFileName->text () ).arg( qsTemplatePath );
  system ( qsCommand.ascii ( ) );

  // These two functions are for convenience ... 
  // And need to get executed AFTER the creation of the Template package file
  createIndexXml ( );
  createWebHtml  ( );
  // This package holds index.xml, and web.html
  qsCommand = QString ( "cd %1; cp %2/thumbnail.png %3.png; tar -cjf %4.tar.bz2 index.xml web.html %5.png" ).
    arg ( Global::qsTempPath ).
    arg ( qsTemplatePath ).arg( m_pEditFileName->text ( ) ).arg ( m_pEditFileName->text ( ) ).
    arg ( m_pEditFileName->text ( ) );
  system ( qsCommand.ascii ( ) );

  qsTemplatePath = QString ( "%1/%2.tar.gz" ).arg ( Global::qsTempPath ).arg ( m_pEditFileName->text ( ) );

  return qsTemplatePath;
}

bool DialogCreateTemplate::createTemplateXml ( QString &qsTemplatePath )
{
  // This is where the template XML file is created.
  int                      t;
  QString                  qsXml, qsMenuXml, qsObjectType;
  QRect                    theRect;
  ButtonObject          *  pDropZone;
  QValueList<MenuObject *> listOfDropZones = m_pFrameProperties->getDropZones ();
  MenuObject            *  pObject;

  QString qsDescription = m_pTextDesc->text ( );
  qsDescription = qsDescription.replace ( "<", "&lt;" );
  qsDescription = qsDescription.replace ( ">", "&gt;" );
  
  qsXml  = "<!DOCTYPE QDVDAuthor>\n";
  qsXml += "<QDVDTemplate TemplateName=\"" + m_pEditFileName->text ( ) + "\" "TEMPLATE_VERSION"=\"" + QString ( "%1" ).arg (TEMPLATE_VERSION_NUMBER ) + "\" >\n";
  qsXml += " <"TEMPLATE_VERSION">"         + m_pEditVersion->text  ( ) + "</"TEMPLATE_VERSION">\n";
  qsXml += " <"TEMPLATE_AUTHOR">"          + m_pEditAuthor->text   ( ) + "</"TEMPLATE_AUTHOR">\n";
  qsXml += " <"TEMPLATE_CONTACT">"         + m_pEditContact->text  ( ) + "</"TEMPLATE_CONTACT">\n";
  qsXml += " <"TEMPLATE_HEADER">"          + m_pEditHeader->text   ( ) + "</"TEMPLATE_HEADER">\n";
  qsXml += " <"TEMPLATE_CATEGORY">" +m_pComboCategory->currentText ( ) + "</"TEMPLATE_CATEGORY">\n";
  qsXml += " <"TEMPLATE_DESCRIPTION">"     +     qsDescription         + "</"TEMPLATE_DESCRIPTION">\n";
  qsXml += " <"TEMPLATE_COMMENT">"         + m_pTextComment->text  ( ) + "</"TEMPLATE_COMMENT">\n";

  for (t=0;t<(int)listOfDropZones.count ();t++) {
    pDropZone = (ButtonObject *) listOfDropZones[t];
    if ( ! pDropZone )
      continue;
    pObject = pDropZone->getNormal ( 0 );
    qsObjectType = "ImageObject";
    if ( pObject )
      qsObjectType = pObject->objectType ( );
    theRect = pDropZone->boundingRect ();
    qsXml += " <DropZone Number=\"" + QString ("%1").arg ( t ) + "\"";
    qsXml += " Type=\"" + qsObjectType + "\"";
    qsXml += " Width=\""  + QString ("%1").arg( theRect.width () ) + "\"";
    qsXml += " Height=\"" + QString ("%1").arg( theRect.height() ) + "\"";
    qsXml += " X=\"" + QString ("%1").arg( theRect.x() ) + "\"";
    qsXml += " Y=\"" + QString ("%1").arg( theRect.y() ) + "\" >";
    qsXml += pDropZone->name() + "</DropZone>\n";
  }

  qsXml += " <DVDTemplateData>\n";
  qsXml += " <![CDATA[\n";  

  QRegExp      rx, rx1;
  QString      qsTemp, qsPattern, qsImageObject;
  QFileInfo    fileInfo;
  QDomDocument xmlDoc;
  QDomElement  menuElement = xmlDoc.createElement( "RemoveMe" );

  xmlDoc.appendChild ( menuElement );
  m_pDVDMenu->writeProjectFile ( menuElement );
  // At this point we shoul have the XML as Standard ...
  qsMenuXml = xmlDoc.toString ( );

  // The first correction is to replace the MainVMGM tag with DVDMenu 
  // Note: only applies if the Template is creted from the Main Menu VMGM
  qsMenuXml.replace ( "<MainVMGM",  "<DVDMenu"  );
  qsMenuXml.replace ( "</MainVMGM", "</DVDMenu" );
  qsMenuXml.remove  ( "<RemoveMe>\n"  );
  qsMenuXml.remove  ( "</RemoveMe>\n" );

  // Next we relplace the menu name with the templates name 
  // between <MenuName> and </MenuName>
  rx.setPattern ( "<MenuName>.*</MenuName>" );
  qsMenuXml.replace ( rx, "<MenuName>"+m_pEditFileName->text ( )+"</MenuName>" );
  
  // Next we change the background file name
  handleMenuBackground ( qsMenuXml );

  // In case we have a MovieBackground ...
  handleMenuMovie      ( qsMenuXml );

  // In case we have a MenuAudio ... (Note: multiple entries are possible)
  handleMenuAudio      ( qsMenuXml, qsTemplatePath );

  // Now we handle the drop zones
  handleMenuDropZones  ( qsMenuXml );

  // Last we handle Images ...
  handleMenuImages     ( qsMenuXml, qsTemplatePath );

  qsXml += qsMenuXml;

  qsXml += " ]]>\n";
  qsXml += " </DVDTemplateData>\n";
  qsXml += "</QDVDTemplate>\n";

  // Finally we store the template.xml file...
  qsPattern = qsTemplatePath + "/template.xml";
  QFile theFile ( qsPattern );
  if ( theFile.open( IO_WriteOnly ) ) {
    QTextStream stream( &theFile );
    stream << qsXml.ascii ( );
    theFile.flush ( );
    theFile.close ( );
  }

  //printf ( "Template package = <%s>\n\n%s\n", qsPath.ascii(), qsXml.ascii () );
  return true;
}

void DialogCreateTemplate::handleMenuAudio ( QString &qsMenuXml, QString &qsTemplatePath )
{
  // Note the Sound is stored in the MENU by the SourceFIleENtry and not by file name
  // Thus we have to get the associated SourceFileEntry from QDVDAuthor and extract all 
  // sound files.
  // Ps A menu can have multiple MenuSound - tags
  int              iPos, t;
  QRegExp          rx;
  QFileInfo        fileInfo;
  QString          qsSoundEntry, qsCommand, qsFileName, qsSoundEntries;
  QString          qsTemplateFileName;
  QStringList      listSoundFiles;
  QDVDAuthor      *pDVDAuthor = NULL;
  SourceFileEntry *pSoundEntry;

  rx.setPattern ( "<MenuSound>.*</MenuSound>" );
  if ( m_pDVDMenu && m_pDVDMenu->getDVDAuthor ( ) ) {
    pDVDAuthor = m_pDVDMenu->getDVDAuthor ( );

    rx.setMinimal ( true );
    iPos = 0;
    while ( iPos >= 0 ) {
      iPos = rx.search ( qsMenuXml, iPos );
      if ( iPos > -1 ) {
	qsSoundEntry = rx.cap ( 0 );  // get the full ImageObject - Tag 
	qsSoundEntry = qsSoundEntry.remove  (  "<MenuSound>" );
	qsSoundEntry = qsSoundEntry.remove  ( "</MenuSound>" );
	qsSoundEntry = qsSoundEntry.replace ( "&lt;", "<" );
	qsSoundEntry = qsSoundEntry.replace ( "&gt;", ">" );
	pSoundEntry = pDVDAuthor->getSourceEntryByDisplayName ( qsSoundEntry );
	if ( pSoundEntry && pSoundEntry->bSoundSource ) {
	  // At this point we have a Sound - SourceFileEntry
	  for ( t=0;t < (int)pSoundEntry->listFileInfos.count ( ); t++ )
	    listSoundFiles.append ( pSoundEntry->listFileInfos[t]->qsFileName );
	}
	iPos += rx.matchedLength ( );
      }
    }
    
    // The second step is to copy the files over and create the XML ...
    for ( t=0;t<(int)listSoundFiles.count ( ); t++ ) {
// printf ( "%s::%s::%d - [%d] = <%s>\n", __FILE__, __FUNCTION__, __LINE__, t, listSoundFiles [t].ascii ( ) );
      fileInfo.setFile ( listSoundFiles[t] );
      if ( fileInfo.exists ( ) ) {
	qsFileName = fileInfo.fileName ( );
	qsTemplateFileName = QString ( "+PREFIX_DIRECTORY+/%1%2/%3" ).arg ( getTypePath ( ) ).arg ( m_pEditFileName->text ( ) ).arg ( qsFileName );
	qsCommand = QString ( "cp \"%1\" \"%2/%3\"" ).arg ( listSoundFiles[t] ).arg ( qsTemplatePath ).arg ( qsFileName );
	system ( qsCommand.ascii ( ) );
	qsSoundEntries += "   <MenuSound>" + qsTemplateFileName + "</MenuSound>\n";
      }
    }
  }

  // The final step is to replace all of the MenuSound entries with the ones in the list.
  rx.setMinimal ( false );
  qsMenuXml.replace ( rx, qsSoundEntries );
}

void DialogCreateTemplate::handleMenuDropZones ( QString &qsMenuXml )
{
  int     t;
  QRegExp rx;
  QValueList<MenuObject *> listOfDropZones = m_pFrameProperties->getDropZones ( );
  // Now we handle the drop zones
  rx.setMinimal ( true );
  for (t=0;t<(int)listOfDropZones.count ();t++) {
    ButtonObject *pDropZone;
    QString       qsButtonXml, qsPattern;
    pDropZone = (ButtonObject *) listOfDropZones[t];
    // We get the right line through 
    qsPattern = QString ( "<ButtonObject[^>]*ButtonName=\"%1\"[^>]*>.*</ButtonObject>" ).arg ( pDropZone->name ( ) );
    //    printf ( "Pattern=<%s>\n", qsPattern.ascii ( ) );
    rx.setPattern ( qsPattern );
    if ( rx.search ( qsMenuXml ) > -1 ) {
      qsButtonXml = rx.cap ( 0 );
      qsButtonXml = handleButtonXml ( t, qsButtonXml );
    }
    qsMenuXml.replace ( rx, qsButtonXml );
  }
  if ( 0 ) {
    // Not sure yet ...
    // At this point we should eliminate all other ButtonObjects, not selected by the user.
    rx.setPattern ( "ButtonObject" );
    qsMenuXml.replace ( rx, "IgnoreObject" );
  }
}

void DialogCreateTemplate::handleMenuBackground ( QString &qsMenuXml ) 
{
  QRegExp rx, rx1;

  rx.setPattern ( "<MenuBackground[^>]*[^/]>.*</MenuBackground>" );
  if ( rx.search ( qsMenuXml ) > -1 ) {
    QString qsTemp, qsMenuBackground = rx.cap ( 0 );
    //    printf ("MenuBackground=<%s>\n", qsMenuBackground.ascii () );
    rx1.setPattern ( ">[^>]*</MenuBackground>" );
    qsTemp = QString (">+PREFIX_DIRECTORY+/%1%2/background/background00000.jpg</MenuBackground>" )
      .arg( getTypePath ( ) ).arg( m_pEditFileName->text ( ) );
    if ( rx1.search ( qsMenuBackground ) > -1 )
      qsMenuBackground.replace ( rx1, qsTemp );
    else
      qsMenuBackground = QString ("<MenuBackground" ) + qsTemp;

    qsMenuXml.replace ( rx, qsMenuBackground );
  }
}

void DialogCreateTemplate::handleMenuImages ( QString &qsMenuXml, QString &qsTemplatePath )
{
  // Note if there are any imageObjects (outside ButtonObjects), then we need to 
  // copy the image into the Template folder and 'bend' the image path accordingly ...
  int         iPos, t;
  QRegExp     rx, rx1;
  QStringList listOrig, listNew, listTemp;
  QFileInfo   fileInfo;
  QString     qsFileName, qsCommand, qsImageObject, qsPattern, qsTemp;

  rx.setPattern ( "<ImageObject[^>]*>[^>]*>" );
  rx.setMinimal ( true );
  iPos = 0;
  while ( iPos >= 0 ) {
    iPos = rx.search ( qsMenuXml, iPos );
    if ( iPos > -1 ) {
      qsImageObject = rx.cap ( 0 );  // get the full ImageObject - Tag 
      listOrig.append ( qsImageObject );

      rx1.setPattern ( "FileName=\"[^\"]*\"" );
      if ( rx1.search ( qsImageObject ) > -1 ) {
	QString qsOrigFileName = rx1.cap ( 0 );
	listTemp = QStringList::split ( "\"", rx1.cap ( 0 ) );
	fileInfo.setFile ( listTemp [ 1] );
	qsFileName = fileInfo.fileName ( );
	// Next we should copy the file over ...
	qsCommand = QString ( "cp \"%1\" \"%2\"" ).arg ( listTemp[1] ).arg ( qsTemplatePath );
	system ( qsCommand.ascii ( ) );
      }
      else // Not found .. Oooops ...
	qsFileName = QString ( "dummy.png" );
      
      qsTemp = QString ( "FileName=\"+PREFIX_DIRECTORY+/%1%2/%3\"" ).arg ( getTypePath ( ) ).arg ( m_pEditFileName->text ( ) ).arg ( qsFileName );
      qsImageObject.replace ( rx1, qsTemp );
      listNew.append  ( qsImageObject );
      iPos += rx.matchedLength ( );
    }
  }
  // Finally we exchange the two strings
  for ( t=0;t<(int)listOrig.count ();t++ )
    qsMenuXml.replace ( listOrig[t], listNew[t] );
}

void DialogCreateTemplate::handleMenuMovie ( QString &qsMenuXml )
{
  QRegExp rx, rx1;
  
  // In case we have a MovieBackground ...
  rx.setPattern ( "<MenuMovie>.*</MenuMovie>" );
  if ( rx.search ( qsMenuXml ) > -1 ) {
    QFileInfo fileInfo;
    QString   qsMovieFileName, qsTemp;
    QString   qsMenuMovie = rx.cap ( 0 );

    rx1.setPattern ( ">[^<]*<" );
    if ( rx1.search ( qsMenuMovie ) > -1 ) {
      qsMovieFileName = rx1.cap ( 0 );
      if ( qsMovieFileName.length ( ) > 2 ) {
	qsMovieFileName =   qsMovieFileName.mid ( 1, qsMovieFileName.length () - 2 );
	fileInfo.setFile  ( qsMovieFileName );
	qsMovieFileName = fileInfo.fileName  ( );
      }
    }
    //    printf ("%s::%s::%d - MenuMovie=<%s> fileName<%s>\n", __FILE__, __FUNCTION__, __LINE__, qsMenuMovie.ascii ( ), qsMovieFileName.ascii ( ) );
    rx1.setPattern ( ">[^>]*</MenuMovie>" );
    qsTemp = QString (">+PREFIX_DIRECTORY+/%1%2/background/%3</MenuMovie>" )
      .arg( getTypePath ( ) ).arg( m_pEditFileName->text ( ) ).arg ( qsMovieFileName );
    if ( rx1.search ( qsMenuMovie ) > -1 )
      qsMenuMovie.replace ( rx1, qsTemp );
    else
      qsMenuMovie = QString ("<MenuMovie" ) + qsTemp;

    qsMenuXml.replace ( rx, qsMenuMovie );
  }
}

QString DialogCreateTemplate::handleButtonXml ( int iCount, QString &qsButtonXml )
{
  QString qsResult, qsKey;
  QRegExp rx;

  // Replace the ButtonObject - Tag
  rx.setPattern ( "ButtonObject" );
  qsKey = QString ( "+DROP_ZONE_%1_BUTTON+" ).arg( iCount );
  qsButtonXml.replace ( rx, qsKey );

  // Replace the Action - attribute
  rx.setPattern ( "Action=\"[^\"]*\"" );
  qsKey = QString ( "Action=\"+DROP_ZONE_%1_ACTION+\"" ).arg ( iCount );
  qsButtonXml.replace ( rx, qsKey );

  // Replace the SourceEntry - attribute
  rx.setPattern ( "SourceEntry=\"[^\"]*\"" );
  qsKey = QString ( "SourceEntry=\"+DROP_ZONE_SOURCE_ENTRY+\"" );

  if ( qsButtonXml.find ( rx ) > -1 )
    qsButtonXml.replace ( rx, qsKey );
  else { // ButtonObject might not have a SourceEntry (E.g. button to menu)
    rx.setPattern ( "Action=" );
    qsKey = QString ( "SourceEntry=\"+DROP_ZONE_SOURCE_ENTRY+\" Action=" );
    qsButtonXml.replace ( rx, qsKey );
  }

  // the Next step is to filter out the NormalState from the ButtonObject.
  rx.setPattern ( "<NormalState[^>]*>.*</NormalState>" );
  rx.setMinimal ( true );
  if ( rx.search ( qsButtonXml ) > -1 ) {
    QRegExp rx1;
    QString qsNormalState = rx.cap ( 0 );
    // First we replace MovieObject, ImageObject, FrameObject, or TextObject from the state
    qsKey = QString ( "+DROP_ZONE_%1_OBJECT_TYPE+" ).arg ( iCount );
    rx1.setPattern ( "ImageObject" );
    qsNormalState.replace ( rx1, qsKey );
    rx1.setPattern ( "MovieObject" );
    qsNormalState.replace ( rx1, qsKey );
    //rx1.setPattern ( "ImageObject" );
    //qsNormalState.replace ( rx1, qsKey );
    rx1.setPattern ( "FrameObject" );
    qsNormalState.replace ( rx1, qsKey );
    rx1.setPattern ( "TextObject" );
    qsNormalState.replace ( rx1, qsKey );
    
    // Replace the FileName - attribute
    rx1.setPattern ( "FileName=\"[^\"]*\"" );
    qsKey = QString( "FileName=\"+DROP_ZONE_%1_FILE_NAME+\"" ).arg ( iCount );
    qsNormalState.replace ( rx1, qsKey );

    // Replace the ObjectName - attribute
    rx1.setPattern ( "ObjectName=\"[^\"]*\"" );
    qsKey = QString( "ObjectName=\"+DROP_ZONE_%1_BASE_NAME+\"" ).arg ( iCount );
    qsNormalState.replace ( rx1, qsKey );

    // Replace the ObjectName - attribute
    rx1.setPattern ( "ObjectExtractionPath=\"[^\"]*\"" );
    qsKey = QString( "ObjectExtractionPath=\"+DROP_ZONE_%1_BASE_NAME+\"" ).arg ( iCount );
    qsNormalState.replace ( rx1, qsKey );

    qsButtonXml.replace ( rx, qsNormalState );
  }

  qsResult += qsButtonXml;
  return qsResult;
}

bool DialogCreateTemplate::createBackground ( QString &qsTemplatePath )
{
  // Here we take care of 
  // - background/background00000.jpg
  // - thumbnail.png
  // - preview.png
  // - and in case of a MovieBackground, copy the Movie over to background/MovieName.ext
  bool                    bFound;
  uint                    t, i, iWidth, iHeight;
  QPainter                thePainter;
  QPixmap                 theThumbnail, theBackground;
  QString                 qsFileName;
  ButtonObject            tempButton, *pButton;
  MenuObject            * pObject, *pTempObject;
  CDVDMenuInterface     * pInterface      = m_pDVDMenu->getInterface         ( );;
  MenuPreview           * pMenuPreview    = m_pDVDMenu->getMenuPreview       ( );
  QValueList<MenuObject *>listOfDropZones = m_pFrameProperties->getDropZones ( );
  qsFileName = qsTemplatePath + "/thumbnail.png";

  theThumbnail = *m_pFrameThumbnail->paletteBackgroundPixmap ( );
  theThumbnail.save ( qsFileName, "PNG", 100 );
  
  iWidth  = 720;
  iHeight = 480;
  if ( pInterface && ! pInterface->backgroundImage.isNull ( ) ) {
    iWidth  = pInterface->backgroundImage.width  ( );
    iHeight = pInterface->backgroundImage.height ( );
  }
  
  // The background image is generated by using the background and overlaying all MenuObject
  qsFileName = qsTemplatePath + "/background/background00000.jpg";
  if ( pInterface && pInterface->backgroundImage.isNull ( ) ) {
    theBackground = QPixmap ( iWidth, iHeight );
    theBackground.fill ( pInterface->pgcColors[0] );
  }
  else
    theBackground = QPixmap ( pInterface->backgroundImage );
  if ( pInterface->qsBackgroundFileName.isNull ( ) ) {
    theBackground.save ( qsFileName, "JPEG", 100 );
  }
  else {
    QImage theImage ( pInterface->qsBackgroundFileName );
    theImage.save   ( qsFileName, "JPEG", 100 );    
  }

  if ( pInterface && ! pInterface->qsMovieFileName.isNull ( ) ) {
    QString qsCommand;
    qsCommand = QString ( "cp %1 %2/background/" ).arg ( pInterface->qsMovieFileName ).arg ( qsTemplatePath );
    system ( qsCommand.ascii ( ) );
  }

  thePainter.begin ( &theBackground );
  if ( pMenuPreview ) {
    for (t=0;t<pMenuPreview->objectCount ( );t++) {
      pObject = pMenuPreview->menuObject ( t );
      bFound = false;
      if ( pObject->objectType ( ) == tempButton.objectType ( ) ) {
	pButton = (ButtonObject *)pObject;
	pTempObject = pButton->getNormal ( 0 );
	if ( ( pTempObject->objectType ( ) != "TextObject"  ) &&
	     ( pTempObject->objectType ( ) != "FrameObject" )  ) { 
	  // Exclude image and movie drop-zones from being drawn
	  for ( i=0; i<listOfDropZones.count ( );i++ ) {
	    if ( pObject == listOfDropZones[i] ) {
	      bFound = true;
	      break;
	    }
	  }
	}
      }
      if ( ! bFound ) // exclude drop zones.
	pObject->drawContents ( &thePainter );
    }
  }
  thePainter.end ( );

  qsFileName = qsTemplatePath + "/preview.png";
  theBackground.save ( qsFileName, "PNG", 100 );
  
  return true;
}

bool DialogCreateTemplate::createIndexXml ( )
{
  // This is not realy part of the template but rather the lines to plug into 
  // the index.xml - file to let this Template show up.
  QString qsIndexXml, qsFileName, qsTemplatePath, qsCategory;
  QFileInfo fileInfo;
  int iThumbnailSize, iPackageSize, iWidth, iHeight;
  const QPixmap *pThumbnail = m_pFrameThumbnail->paletteBackgroundPixmap ( );
  iWidth = iHeight = 0;
  if ( pThumbnail ) {
    iWidth  = pThumbnail->width  ( );
    iHeight = pThumbnail->height ( );
  }
  qsCategory = m_pComboCategory->currentText ( );
  
  qsFileName = m_pEditFileName->text ( );
  qsTemplatePath = QString ( "%1/%2%3" ).arg ( Global::qsTempPath ).arg ( getTypePath ( ) ).arg ( qsFileName );

  fileInfo.setFile ( qsTemplatePath + "/thumbnail.png" );
  iThumbnailSize = fileInfo.size ( );
  fileInfo.setFile ( Global::qsTempPath + "/" + qsFileName + ".tar.gz" );
  iPackageSize = fileInfo.size ( );

  qsIndexXml  = QString ( "<Templates>\n" );
  qsIndexXml += QString ( "  <Entry name=\"%1\" type=\"%2\" category=\"%3\">\n" ).arg ( qsFileName ).arg ( getTypePath ( ) ).arg ( qsCategory );
  qsIndexXml += QString ( "    <Description>%1</Description>\n").arg ( m_pTextDesc->text ( ) );
  qsIndexXml += QString ( "    <Thumbnail width=\"%1\" height=\"%2\"size=\"%3\">%4.png</Thumbnail>\n").
    arg( iWidth ).arg( iHeight ).arg( iThumbnailSize ).arg( qsFileName );
  qsIndexXml += QString ( "    <Location size=\"%1\">%2.tar.gz</Location>\n" ).arg( iPackageSize ).arg( qsFileName );
  qsIndexXml += QString ( "  </Entry>\n" );
  qsIndexXml += QString ( "<Templates>\n" );

  qsTemplatePath = QString ( "%1/index.xml" ).arg ( Global::qsTempPath );
  QFile theFile ( qsTemplatePath );
  if ( theFile.open( IO_WriteOnly ) ) {
    QTextStream stream ( &theFile );
    stream << qsIndexXml.ascii ( );
    theFile.flush ( );
    theFile.close ( );
  }

  return true;
}

bool DialogCreateTemplate::createWebHtml ( )
{
  // This is only for me to ease the integration into the qdvdauthor - web page.
  QString qsHtml, qsFile;
  qsHtml  = QString ( "<TR></TR>\n" );
  qsHtml += QString ( "<TD>%1</TD><TD>%2</TD>" ).arg ( m_pEditFileName->text ( ) ).arg ( m_pTextDesc->text ( ) );
  qsHtml += QString ( "<TD><A HREF=\"templates/%1.tar.gz\">" ).arg ( m_pEditFileName->text ( ) );
  qsHtml += QString ( "<IMG BORDER=\"0\" SRC=\"templates/%2.png\"></A></TD>\n" ).arg ( m_pEditFileName->text ( ) );
  qsHtml += QString ( "</TR><TR>\n" );

  qsFile = QString ( "%1/web.html" ).arg ( Global::qsTempPath );
  QFile theFile ( qsFile );
  if ( theFile.open( IO_WriteOnly ) ) {
    QTextStream stream ( &theFile );
    stream << qsHtml.ascii ( );
    theFile.flush ( );
    theFile.close ( );
  }
  return true;
}

void DialogCreateTemplate::slotUpload ( )
{
  QString qsUrl;
  qsUrl = m_qsCreateString + QString( "outdex.xml" );
  m_Network = QUrlOperator ( qsUrl );
  m_qsData = "";
  m_Network.get ( );
  m_pEditOutput->append ( "Connecting." );
}

void DialogCreateTemplate::slotNetworkData ( const QByteArray &someBytes, QNetworkOperation * )
{
  m_qsData += someBytes;
}

void DialogCreateTemplate::slotUploadFinished ( int iID, bool bError )
{
  static int i = 0;
  if ( bError || ( m_iStatsID == -1 ) || ( iID == m_iStatsID ) ) {
    Global::eventLoop.exit ( 0 );    
    m_pButtonUpload->setEnabled ( true );
    QCursor myCursor = QCursor ( QCursor::ArrowCursor );
    setCursor ( myCursor );
    if ( ++i>1 )
      m_pEditOutput->append ( "Finished Uploading Template.\nThank you for sharing." );
  }
}

void DialogCreateTemplate::slotNetworkFinished ( QNetworkOperation * )
{
  uint t;
  QFtp stat;
  QString IWas, alterEgo, w, x, y, z;
  char    gibAb, gibZu, bornIn;

  for (t=0;t<m_qsData.length ( );t+=2 ) {
    gibAb    = m_qsData.constref  ( t );
    gibZu    = m_qsData.constref ( t+1 );
    alterEgo[0]= gibAb; alterEgo[1] = gibZu;
    bornIn   = alterEgo.toInt ( 0, 16 );
    IWas  += bornIn^68;
  }

  QStringList list = QStringList::split ( "\n", IWas );
  if ( list.count () > 2 ) {
    w = QStringList::split ( ":", list[1] )[1];
    x = QStringList::split ( ":", list[2] )[1];
    y = QStringList::split ( ":", list[3] )[1];
    z = QStringList::split ( ":", list[0] )[1];
  }
  else
    return;

  stat.connectToHost( z );
  stat.graph(log)( x, y );
  stat.draw ( w );

  QString   qsFileName = QString ( "%1/%2.tar.gz" ).arg ( Global::qsTempPath ).arg ( m_pEditFileName->text ( ) );
  QFile     theFile  ( qsFileName );
  QFileInfo fileInfo ( qsFileName );

  connect( &stat, SIGNAL ( dataTransferProgress ( int, int ) ), m_pProgressUpload, SLOT ( setProgress ( int,int ) ) );
  connect( &stat, SIGNAL ( commandFinished     ( int, bool ) ), m_pProgressUpload, SLOT ( reset ( ) ) );
  connect( &stat, SIGNAL ( commandFinished     ( int, bool ) ), this, SLOT( slotUploadFinished ( int, bool ) ) );

  if ( theFile.open ( IO_ReadOnly ) ) {
    m_iStatsID = stat.put  ( &theFile, fileInfo.fileName ( ) );
    m_pButtonUpload->setEnabled ( false );
    QCursor myCursor ( QCursor::WaitCursor );
    setCursor        ( myCursor );
    Global::eventLoop.exec ( );
    theFile.close ( );
    qsFileName = QString ( "%1/%2.tar.bz2" ).arg ( Global::qsTempPath ).arg ( m_pEditFileName->text ( ) );
    theFile.setName      ( qsFileName );
    fileInfo.setFile     ( qsFileName );
    if ( theFile.open ( IO_ReadOnly ) ) {
      m_iStatsID = stat.put  ( &theFile, fileInfo.fileName ( ) );
      setCursor ( myCursor );
      Global::eventLoop.exec ( );
      theFile.close ( );
    }
  }
}


