
// This is the implementation of the ComplexDVD plugin for QDVDAuthor.

#include <stdlib.h>

#include <qprogressdialog.h>
#include <qradiobutton.h>
#include <qapplication.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qgroupbox.h>
#include <qfileinfo.h>
#include <qcombobox.h>
#include <qlayout.h>
#include <qcursor.h>
#include <qimage.h>
#include <qtimer.h>

#include "uisimpledvd.h"
#include "simpledvd.h"

// The class factories
extern "C"  Plugin::Interface *createPlugin ( ) {
    return new Plugin::ComplexDVD;
}
extern "C" void destroyPlugin ( Plugin::Interface *pDeleteMe ) {
    delete pDeleteMe;
}

#include "../../CONFIG.h"

#ifndef SYSTEM_DIRECTORY
#define SYSTEM_DIRECTORY "/usr"
#endif

namespace Plugin
{

ComplexDVD::ComplexDVD ( )
{
  srand ( (unsigned)time ( NULL ) );
  m_iNrOfMenus    = 0;
  m_pConfigWidget = NULL;
  m_qsPluginName  = "ComplexDVD" + QString ( " -%1-" ).arg ( getPluginVersion ( ), 0, 'f', 2 );
  QTimer::singleShot ( 10, this, SLOT ( slotInitTimer ( ) ) );
}

ComplexDVD::~ComplexDVD ( )
{
  if ( m_pConfigWidget )
    delete m_pConfigWidget;
  m_pConfigWidget = NULL;
}

QWidget *ComplexDVD::getConfigWidget ( QWidget *pParent )
{
  // Note this widget has to be destroyed in the library
  m_pConfigWidget = new uiControls ( pParent );
  return m_pConfigWidget;
}

void ComplexDVD::slotInitTimer ( )
{
  QStringList list;
  list.append ( "Random"      );// 11009
  list.append ( "Nature"      );//  2497
  list.append ( "3D-graphics" );//   787
  list.append ( "Animals"     );//   567
  list.append ( "Anime"       );//  1573
  list.append ( "Art"         );//    84
  list.append ( "Cars"        );//   708
  list.append ( "cartoons"    );//   450
  list.append ( "Computer"    );//   777
  list.append ( "Fantasy"     );//   169
  list.append ( "Flowers"     );//   370
  list.append ( "Games"       );//   420
  list.append ( "Girls"       );//  1463
  list.append ( "Holiday"     );//    23
  list.append ( "Military"    );//    13
  list.append ( "Movies"      );//   483
  list.append ( "Music"       );//    52
  list.append ( "Space"       );//   573

  m_listNumberOfImages.append ( 11009 );
  m_listNumberOfImages.append (  2497 );
  m_listNumberOfImages.append (   787 );
  m_listNumberOfImages.append (   567 );
  m_listNumberOfImages.append (  1573 );
  m_listNumberOfImages.append (    84 );
  m_listNumberOfImages.append (   708 );
  m_listNumberOfImages.append (   450 );
  m_listNumberOfImages.append (   777 );
  m_listNumberOfImages.append (   169 );
  m_listNumberOfImages.append (   370 );
  m_listNumberOfImages.append (   420 );
  m_listNumberOfImages.append (  1463 );
  m_listNumberOfImages.append (    23 );
  m_listNumberOfImages.append (    13 );
  m_listNumberOfImages.append (   483 );
  m_listNumberOfImages.append (    52 );
  m_listNumberOfImages.append (   573 );

  if ( m_pConfigWidget )
       m_pConfigWidget->m_pComboType->insertStringList ( list );

  connect ( m_pConfigWidget->m_pCheckRandomImages, SIGNAL ( toggled ( bool ) ), this, SLOT ( slotRandomImages ( bool ) ) );
  connect ( m_pConfigWidget->m_pRadioWPA,          SIGNAL ( clicked ( ) ), this, SLOT ( slotWPArchive    ( ) ) );
  connect ( m_pConfigWidget->m_pRadioHDRCreme,     SIGNAL ( clicked ( ) ), this, SLOT ( slotHDRCreme     ( ) ) );
  connect ( m_pConfigWidget->m_pRadioDreamScene,   SIGNAL ( clicked ( ) ), this, SLOT ( slotDreamScene   ( ) ) );
}

void ComplexDVD::slotRandomImages ( bool bOn )
{
  m_pConfigWidget->m_pGroupRandom->setEnabled ( bOn );
  m_pConfigWidget->m_pGroupVideos->setEnabled ( bOn );
}

void ComplexDVD::slotWPArchive ( )
{
  bool bOn = m_pConfigWidget->m_pRadioWPA->isChecked ( );
  m_pConfigWidget->m_pComboType->setEnabled       (   bOn );
  m_pConfigWidget->m_pRadioHDRCreme->setChecked   ( ! bOn );
  m_pConfigWidget->m_pRadioDreamScene->setChecked ( ! bOn );
}

void ComplexDVD::slotHDRCreme ( )
{
  bool bOn = m_pConfigWidget->m_pRadioHDRCreme->isChecked ( );
  m_pConfigWidget->m_pComboType->setEnabled       ( ! bOn );
  m_pConfigWidget->m_pRadioWPA->setChecked        ( ! bOn );
  m_pConfigWidget->m_pRadioDreamScene->setChecked ( ! bOn );
}

void ComplexDVD::slotDreamScene ( )
{
  bool bOn = m_pConfigWidget->m_pRadioDreamScene->isChecked ( );
  m_pConfigWidget->m_pComboType->setEnabled     ( ! bOn );
  m_pConfigWidget->m_pRadioWPA->setChecked      ( ! bOn );
  m_pConfigWidget->m_pRadioHDRCreme->setChecked ( ! bOn );
}

QString ComplexDVD::getDuration ( QString &qsFile )
{
  QString qsDuration ( "00:00:01.000" );
  if ( m_pConfigWidget->m_pRadioDreamScene->isChecked ( ) )  {
    QString qsCommand, qsTempFile;
    qsTempFile = QString ( "%1/length.txt" ).arg ( m_qsTempPath );
    qsCommand  = QString ( "ffmpeg -i \"%1\" 2>&1 | grep Duration | awk '{ print $2 }' | sed 's/,//g' > %2" ).arg ( qsFile ).arg ( qsTempFile );
    printf ( "getDuration : %s\n", qsCommand.ascii ( ) );
    int iRet   = system  ( qsCommand.ascii ( ) ); iRet = iRet;
    QFile file ( qsTempFile );
    if ( file.exists ( ) )  {
      if ( file.open( IO_ReadOnly ) )  {
        QTextStream stream( &file );
        while ( ! stream.atEnd ( ) )
          qsDuration = stream.readLine ( );
        file.close ( );
      }
      if ( qsDuration.length ( ) < 5 )
        qsDuration = "00:00:10.001"; // defaulting to 10 seconds
    }
  }
  return qsDuration;
}


void ComplexDVD::getRandomBackground ( )
{
  // gets random images off of InterFaceLift.com and stores them in /tmp
  int iOffset = 1;
  QString qsCommand, qsTempPath, qsTarget, qsExt;
  qsTempPath = m_qsTempPath + "/" + m_qsProjectName;

  QDialog   progressDialog    ( NULL );
  QGridLayout  progressLayout ( &progressDialog );
  QProgressBar progressBar    ( &progressDialog );
  progressLayout.addWidget    ( &progressBar, 0, 0 );
  progressDialog.resize       ( QSize(550, 50).expandedTo ( progressDialog.minimumSizeHint ( ) ) );
  progressDialog.setCaption   ( tr ( "Receiving random images." ) );
  progressDialog.show         ( );
  progressBar.setTotalSteps   ( m_iNrOfMenus );
  qApp->processEvents         ( 100 );

  if ( m_pConfigWidget && m_pConfigWidget->m_pCheckMainMenu && 
       m_pConfigWidget->m_pCheckMainMenu->isChecked ( ) )
       iOffset ++;

  qsExt = "jpg";
  if ( m_pConfigWidget->m_pRadioDreamScene->isChecked ( ) )
    qsExt = "vob";

  qsCommand = QString ( "if [ -e %1/menu_1.%2 ]; then rm %3/menu_*.%4 >/dev/null 2>&1; fi" ).arg ( qsTempPath ).arg ( qsExt ).arg ( qsTempPath ).arg ( qsExt );
  int iRet  = system ( qsCommand.ascii ( ) );

  for ( int t=0; t<m_iNrOfMenus; t++ )  {
    qsTarget  = QString   ( "\"%1/menu_%2.%3\"" ).arg ( qsTempPath ).arg ( t + iOffset ).arg ( qsExt );
    qsCommand = getImgCmd ( qsTarget );

    progressDialog.show     ( ); // why does this dlg disappear ? 
    progressDialog.raise    ( );
    progressBar.setProgress ( t + iOffset );
    qApp->processEvents     ( 10 );

    iRet = system ( qsCommand.ascii ( ) );
  }
}

QString ComplexDVD::getImgCmd ( QString &qsTarget )
{

//    qsCommand=QString ( "POTD=`wget -qO - 'interfacelift.com/wallpaper/index.php?sort=random&aspect=&widescreen&w=1280&h=800' | grep \"download</a>\" | sed -e \"s,.*href=\\\",,\" -e \"s,\\\",,\" | awk 'NR==\"3\" {print}' | awk '{ gsub(/dl\\/wallpaper\\//,\"\");gsub(/>download<\\/a>/,\"\");print}'`; wget -q -O \"%1/menu_%2.jpg\"  interfacelift.com/wallpaper/downloads$POTD" ).arg ( qsTempPath ).arg ( t + iOffset );
  int iIdx, iRandom;
  QString  qsRandom, qsCommand;

  if ( m_pConfigWidget->m_pRadioWPA->isChecked ( ) )  {
    // Get images from WallpapersArchive.com
    iIdx = m_pConfigWidget->m_pComboType->currentItem ( );
    if ( iIdx == 0 ) // random :
         iIdx = ( rand ( ) % ( m_pConfigWidget->m_pComboType->count ( ) - 1 ) ) + 1;
    iRandom   = ( rand ( ) % m_listNumberOfImages[iIdx] );
    qsRandom  = m_pConfigWidget->m_pComboType->text ( iIdx );

    qsCommand=QString ( "PICURL=`wget -qO - 'wallpapersarchive.com/%1/wallpaper%2/' | grep \"img src=\\\"http://www.wallpapersarchive.com/wallpapers/\" | sed -e \"s/.*src=\\\"//g\" -e \"s/\\\".*//\"`; wget -q --user-agent=MSIE -O %3 $PICURL" ).arg ( qsRandom ).arg ( iRandom ).arg ( qsTarget );
  }
  else if ( m_pConfigWidget->m_pRadioHDRCreme->isChecked ( ) ) {
    // Get images from HDRCreme instead
    iRandom      = ( rand ( ) % 558 + 1 );
    int iRandom2 = ( rand ( ) % 20  + 1 );
//    qsCommand=QString ( "PICURL=`wget -qO - 'hdrcreme.com/photo-gallery?page=%1' | grep imgGalleri | sed -e \"s,.*href=\\\",,\" -e \"s,\\\".*,,\" | head -%2 | tail -1`; PICURL=`wget -qO - hdrcreme.com$PICURL | grep showimagepic | sed -e \"s,.*src=\\\",,\" -e \"s,\\\".*,,\"`; wget -q --user-agent=MSIE -O %3 $PICURL" ).arg ( iRandom ).arg ( iRandom2 ).arg ( qsTarget );
    qsCommand=QString ( "PREURL=http://hdrcreme.com`wget -qO - 'hdrcreme.com/photo-gallery?page=%1' | grep imgGalleri | sed -e \"s,.*href=\\\",,\" -e \"s,\\\".*,,\" | head -%2 | tail -1`; PICURL=`wget -qO - \"$PREURL\" | grep showimagepic | sed -e \"s,.*jQuery.*,,g\"  -e \"s,.*<img ,,g\" | sed -e \"s,.*src=\\\",,\" -e\"s,\\\".*,,g\"`; wget -q --user-agent=MSIE -O %3 $PICURL" ).arg ( iRandom ).arg ( iRandom2 ).arg ( qsTarget );
  }
  else  { // Get background videos from DreamScene
    QString qsScreenshot = qsTarget;
    qsScreenshot = qsScreenshot.replace ( ".vob", ".jpg" );
    iRandom = ( rand ( ) % 205 + 1 );
    qsCommand  = "#!/bin/bash\n";
    qsCommand += "outFile=/tmp/Dream.zip\n";
    qsCommand += "dstDir=" + m_qsTempPath + "\n";
    qsCommand += "cd $dstDir\n";
    qsCommand += "# Retrieve the actual zip file\n";
    qsCommand += QString ( "wget --user-agent=MSIE --post-data=\"Cmd=DownloadFile&ID=%1\" http://www.dreamscene.org/load.php -O $dstDir/Dream.zip\n" ). arg ( iRandom );
    qsCommand += "file=`unzip -Z Dream.zip | grep \"b- defN\" | awk '{ for ( i=9;i<=NF;i++) printf $i " " }'`\n";
    qsCommand += "files=`unzip -o Dream.zip`\n";
    qsCommand += "echo \"ffmpeg -i \"$file\" -ar 48000 -ab 224k -ac 2 -acodec ac3 -y -s 720x480 -b 9900k -f vob " + qsTarget + "\"\n";
    qsCommand += "# For the background we need good quality video/audio which is properly scaled.\n";
    qsCommand += "ffmpeg -i $file -ar 48000 -ab 224k -ac 2 -acodec ac3 -y -s 720x480 -b 9900k -f vob " + qsTarget + "\n";
    qsCommand += "ffmpeg  -an -y -t 00:00:01  -vframes 1 -i " + qsTarget + " -y -f image2 " + qsScreenshot + "\n";
  }

printf ( "%s\n", qsCommand.ascii () );
  return qsCommand;
}

void ComplexDVD::createMainMenu ( )
{
  // creates a MainMenu with only one Button to the next Menu.
  // This is for the user to fill in 
  SourceGroup::type theType = SourceGroup::NTSC; // pGroup->enType;
  QString qsMenuName = QString ( "Menu 1" ); // this will be converted to VMGM due to the 1
  QString qsMenuXML, qsCommand, qsMenuBackground, qsDuration, qsMenuMovie;

  qsMenuBackground = m_qsTempPath + "/" + m_qsProjectName + "/MainMenu.jpg";
  if ( m_pConfigWidget->m_pRadioDreamScene->isChecked ( ) )
    qsMenuMovie = QString ( "<MenuMovie>%1/%2/MainMenu.vob</MenuMovie>\n" ).arg ( m_qsTempPath ).arg ( m_qsProjectName );

  qsCommand = QString ( "rm \"%1\" >/dev/null 2>&1" ).arg ( qsMenuBackground );
  int iRet  = system ( qsCommand.ascii ( ) );

  qsCommand = getImgCmd ( qsMenuBackground );
  iRet = system ( qsCommand.ascii ( ) );
  qsDuration = getDuration ( qsMenuBackground );

  qsMenuXML += "<MainVMGM MenuWidth=\"720\" TitlesetNr=\"0\" MenuHeight=\"480\" MenuFormat=\"1\" MenuRatio=\"4:3\" MenuNr=\"0\" >\n";
  qsMenuXML += "  <MenuVariables>\n";
  qsMenuXML += "   <MenuOffset>00:00:00.000</MenuOffset>\n";
  qsMenuXML += "   <MenuDuration>" + qsDuration + "</MenuDuration>\n";
  qsMenuXML += qsMenuMovie;
  qsMenuXML += "   <MenuBackground ResizeAlgo=\"Normal Qt\" OffsetX=\"0\" OffsetY=\"0\" StretchType=\"0\" >" + qsMenuBackground + "</MenuBackground>\n";
  qsMenuXML += "   <MenuName>Main Menu VMGM</MenuName>\n";
  qsMenuXML += "   <MaskColors>#00fefffe,#a0ff1414,#a0fa9632,#ff0f0fff,</MaskColors>\n";
  qsMenuXML += "  </MenuVariables>\n";
  qsMenuXML += "  <PreviewVariables>\n";
  qsMenuXML += "   <ButtonObject Action=\"jump+-+Menu 2+-+\" PreAction=\"\" ButtonName=\"Button 1\" >\n";
  qsMenuXML += "    <NormalState>\n";
  qsMenuXML += "     <TextObject BackgroundColor=\"#ffffe866\" TextAlign=\"4,64\" ForegroundColor=\"#ffff1437\" Font=\"Courier,26,-1,5,75,0,0,0,0,0\" Text=\"First Menu\" >\n";
  qsMenuXML += "      <MenuObject Width=\"231\" X=\"257\" Y=\"210\" Height=\"45\" ObjectName=\"First Menu\" />\n";
  qsMenuXML += "     </TextObject>\n";
  qsMenuXML += "    </NormalState>\n";
  qsMenuXML += "    <SelectedState>\n";
  qsMenuXML += "     <TextObject StyleStrategy=\"256\" TextAlign=\"4,64\" ForegroundColor=\"#a0ff1414\" Font=\"Courier,26,-1,5,75,0,0,0,0,0\" Text=\"First Menu\">\n";
  qsMenuXML += "      <MenuObject Width=\"231\" X=\"257\" Y=\"210\" Height=\"45\" ObjectName=\"First Menu\" />\n";
  qsMenuXML += "     </TextObject>\n";
  qsMenuXML += "    </SelectedState>\n";
  qsMenuXML += "    <HighlightedState>\n";
  qsMenuXML += "     <TextObject StyleStrategy=\"256\" TextAlign=\"4,64\" ForegroundColor=\"#a0fa9632\" Font=\"Courier,26,-1,5,75,0,0,0,0,0\" Text=\"First Menu\">\n";
  qsMenuXML += "      <MenuObject Width=\"231\" X=\"257\" Y=\"210\" Height=\"45\" ObjectName=\"First Menu\" />\n";
  qsMenuXML += "     </TextObject>\n";
  qsMenuXML += "    </HighlightedState>\n";
  qsMenuXML += "    <MenuObject Width=\"231\" X=\"257\" Y=\"210\" Height=\"45\" ObjectName=\"Button 1\" />\n";
  qsMenuXML += "   </ButtonObject>\n";
  qsMenuXML += "  </PreviewVariables>\n";
  qsMenuXML += " </MainVMGM>\n";

  emit ( signalNewMenuResponse ( theType, qsMenuName, qsMenuXML ) );
}

bool ComplexDVD::execute ( )
{
  int iButtonsPerMenu = 6;
  // Here we create the DVD Structure for the given input arameters
  QValueList<SourceGroup *>::iterator it = m_listOfGroups.begin ( );
  SourceGroup *pGroup = NULL;
  int iMenuNumber, iCount;
  iMenuNumber = iCount = 0;
  // First we should add the Groups ( SourceFIleEntries ...
  while ( it != m_listOfGroups.end ( ) )  {
    pGroup = *it++;
    emit ( signalNewSource ( pGroup ) );
  }

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

  // The next iteration we generate the DVDMenus.
  m_iNrOfMenus  = (int)( ( m_listOfGroups.count ( ) + iButtonsPerMenu - 1 ) / iButtonsPerMenu );

  // Here we eval if we should snap some random images off of the internet
  if ( m_pConfigWidget && m_pConfigWidget->m_pCheckRandomImages && 
       m_pConfigWidget->m_pCheckRandomImages->isChecked ( ) )
    getRandomBackground ( );
  if ( m_pConfigWidget && m_pConfigWidget->m_pCheckMainMenu && 
       m_pConfigWidget->m_pCheckMainMenu->isChecked ( ) )  {
    createMainMenu ( );
    iMenuNumber ++;
  }

  int iProgress   = 0;
  int iSlideCount = 1;
  QDialog   progressDialog    ( NULL );
  QGridLayout  progressLayout ( &progressDialog );
  QProgressBar progressBar    ( &progressDialog );
  progressLayout.addWidget    ( &progressBar, 0, 0 );
  progressDialog.resize       ( QSize(550, 50).expandedTo ( progressDialog.minimumSizeHint ( ) ) );
  progressDialog.setCaption   ( tr ( "Creating [Menu 1]" ) );
  progressDialog.show         ( );
  progressBar.setTotalSteps   ( (int)m_listOfGroups.count ( ) );
  progressBar.setProgress     ( iProgress++  );
  qApp->processEvents         ( 500 );

  QValueList<SourceGroup *> listGroups;
  it = m_listOfGroups.begin  ( );
  while ( it != m_listOfGroups.end  ( ) )  {
    pGroup = *it++;
    // Next we create the Menus required ...
    // The number of menus depends on the max number of buttons per menu ( m_iButtonsPerMenu )
    listGroups.append ( pGroup );
    if ( iCount++ >= iButtonsPerMenu - 1 )  {
      SourceGroup::type theType = pGroup->enType;
      QString qsMenuXML = getMenuXML ( listGroups, ++iMenuNumber, iSlideCount );
      listGroups.clear ( );

      QString qsMenuName = QString ( "Menu %1" ).arg ( iMenuNumber );
      progressDialog.setCaption ( tr ( "Creating [%1]" ).arg ( qsMenuName ) );

      // Create the DVDMenu
      emit ( signalNewMenuResponse ( theType, qsMenuName, qsMenuXML ) );
      iCount = 0;
    }
    progressBar.setProgress ( iProgress++ );
    qApp->processEvents     ( 10 );
  }
  if ( iCount > 0 )  {
      SourceGroup::type theType = pGroup->enType;
      QString qsMenuName, qsMenuXML;
      qsMenuName.sprintf ( "Menu %d", ++iMenuNumber );
      qsMenuXML = getMenuXML ( listGroups, iMenuNumber, iSlideCount );
      listGroups.clear ( );

      // Create the DVDMenu
      //printf ( "%s\n\n\n", qsMenuXML.ascii ( ) );
      emit ( signalNewMenuResponse ( theType, qsMenuName, qsMenuXML ) );
  }
  QApplication::restoreOverrideCursor ( );
  return true;
}

QString ComplexDVD::getMenuXML ( QValueList<SourceGroup *> &list, int iMenuNumber, int &iSlideCount )
{
  QFileInfo fileInfo;
  QString qsMenuXML, qsBackgroundFile, qsMenuName, qsFileName, qsGroupName, qsDuration, qsMenuMovie;
  QString qsHeight = "480";
  QString qsButtonName, qsFrameName, qsObjectName, qsJumpTo, qsX, qsY, qsW, qsH, qsTempPath;
  int iX, iY, iCount = 0;
  SourceGroup *pGroup = NULL;
  if ( list.count ( ) < 1 )
    return qsMenuXML;

  qsTempPath = m_qsTempPath + "/" + m_qsProjectName;
  qsBackgroundFile = SYSTEM_DIRECTORY"/share/qdvdauthor/plugins/complexdvd/background.jpg";
  if ( m_pConfigWidget && m_pConfigWidget->m_pCheckRandomImages && 
       m_pConfigWidget->m_pCheckRandomImages->isChecked ( ) )  {
    if ( m_pConfigWidget->m_pRadioDreamScene->isChecked ( ) )
      qsMenuMovie = QString ( "<MenuMovie>%1/menu_%2.vob</MenuMovie>\n" ).arg ( qsTempPath ).arg ( iMenuNumber );
    qsBackgroundFile = QString ( "%1/menu_%2.jpg" ).arg ( qsTempPath ).arg ( iMenuNumber );
  }

  qsDuration = getDuration ( qsBackgroundFile );
  qsMenuName.sprintf ( "Menu %d", iMenuNumber );
  pGroup = list[0];
  if ( pGroup->enType == SourceGroup::PAL )
    qsHeight = "576";

  qsMenuXML += " <DVDMenu MenuWidth=\"720\" MenuHeight=\""+qsHeight+"\" MenuFormat=\"0\" MenuRatio=\"4:3\" >\n";
  qsMenuXML += "  <MenuVariables>\n";
  qsMenuXML += "   <MenuOffset>00:00:00.000</MenuOffset>\n";
  qsMenuXML += "   <MenuDuration>" + qsDuration + "</MenuDuration>\n";
  qsMenuXML += qsMenuMovie;
  qsMenuXML += "   <MenuBackground ResizeAlgo=\"Normal Qt\" OffsetX=\"0\" OffsetY=\"0\" StretchType=\"2\" >" + qsBackgroundFile + "</MenuBackground>\n";
  qsMenuXML += "   <MenuName>" + qsMenuName + "</MenuName>\n";
  qsMenuXML += "   <MaskColors>#00fefffe,#a0ff1414,#a0fa9632,#ff0f0fff,</MaskColors>\n";
  qsMenuXML += "  </MenuVariables>\n";
  qsMenuXML += "  <PreviewVariables>\n";

  // Transparent area - Top
  qsMenuXML += "   <TextObject BackgroundColor=\"#ffaaff5a\" TextAlign=\"4,64\" ForegroundColor=\"#fff15735\" Font=\"Sans Serif,20,-1,5,75,0,0,0,0,0\" Text=\"\" >\n";
  qsMenuXML += "    <MenuObject Width=\"740\" X=\"0\" Y=\"35\" Height=\"150\" ObjectName=\"\" >\n";
  qsMenuXML += "     <Modifiers Transparency=\"0.60\" />\n";
  qsMenuXML += "    </MenuObject>\n";
  qsMenuXML += "   </TextObject>\n";

  // Transparent area - Bottom
  qsMenuXML += "   <TextObject BackgroundColor=\"#fff4f5f4\" TextAlign=\"4,64\" ForegroundColor=\"#ff000000\" Font=\"Courier,12,-1,5,50,0,0,0,0,0\" Text=\"\" >\n";
  qsMenuXML += "    <MenuObject Width=\"740\" X=\"-8\" Y=\"285\" Height=\"150\" ObjectName=\"\" >\n";
  qsMenuXML += "     <Modifiers Transparency=\"0.60\" />\n";
  qsMenuXML += "    </MenuObject>\n";
  qsMenuXML += "   </TextObject>\n";

  // Next we take care of the Buttons ...
  QValueList<SourceGroup *>::iterator it;
  it = list.begin ( );
  while ( it != list.end ( ) )  {
    pGroup = *it++;

    if ( ! pGroup )
       continue;

    qsFileName  = "";
    qsGroupName = pGroup->qsGroupName;
    if ( pGroup->bSlideshow )  {
      qsGroupName.sprintf ( "[%02d] - %s", iSlideCount++, (const char *)pGroup->qsGroupName.utf8 ( ) );
      qsFileName  = pGroup->qsGroupName + ".vob+-+00:00:00.000";
    }
    else if ( pGroup->listFiles.size ( ) > 0 )  {
      fileInfo.setFile ( pGroup->listFiles[0]->qsFileName );
      qsFileName = fileInfo.fileName ( );
      if ( qsFileName.length ( ) > 0 )
        qsFileName += "+-+00:00:00.000";
    }
//jump+-+[01] - cordes.mpg+-+001_capture001.mpeg+-+00:00:00.000
    qsJumpTo = QString ( "jump+-+%1+-+%2" ).arg ( qsGroupName ).arg ( qsFileName );
    qsButtonName  = QString ( "Button %1" ).arg ( ++iCount );
    qsObjectName  = QString ( "Object_%1" ).arg (   iCount );
    qsFrameName   = QString ( "Frame %1"  ).arg (   iCount );
    iX  = ( iCount-1 )%3 * 210 + 90;
    iY  = ( iCount > 3 ) ? 400 : 150;
    qsX = QString ( "%1" ).arg ( iX );
    qsY = QString ( "%1" ).arg ( iY );

    // First we create the assiciated TextObject
    qsMenuXML += "   <TextObject TextAlign=\"4,64\" ForegroundColor=\"#fff15735\" Font=\"Sans Serif,16,-1,5,75,0,0,0,0,0\" Text=\""+pGroup->qsGroupName+"\" >\n";
    qsMenuXML += "    <MenuObject Width=\"150\" X=\""+qsX+"\" Y=\""+qsY+"\" Height=\"41\" ObjectName=\""+pGroup->qsGroupName+"\" />\n";
    qsMenuXML += "   </TextObject>\n";

    iY = ( iCount > 3 ) ? 295 : 45;

    QRect r = scaleScreenshot ( pGroup->qsScreenshot, 150, 115 );

    qsX = QString ( "%1" ).arg ( iX + r.left ( ) );
    qsY = QString ( "%1" ).arg ( iY + r.top  ( ) );
    qsW = QString ( "%1" ).arg ( r.width  ( ) );
    qsH = QString ( "%1" ).arg ( r.height ( ) );

    // Next we create the ButtonObject for the video jump+-+vmgm+-+
    qsMenuXML += "   <ButtonObject Action=\""+qsJumpTo+"\" ButtonName=\""+qsButtonName+"\"  SourceEntry=\""+qsGroupName+"\" >\n";
    qsMenuXML += "    <NormalState>\n";
    qsMenuXML += "     <ImageObject FileName=\""+pGroup->qsScreenshot+"\" >\n";
    qsMenuXML += "      <Manipulator>\n";
    qsMenuXML += "       <Modifiers/>\n";
    qsMenuXML += "      </Manipulator>\n";
    qsMenuXML += "      <MenuObject Width=\""+qsW+"\" X=\""+qsX+"\" Y=\""+qsY+"\" Height=\""+qsH+"\" ObjectName=\""+qsObjectName+"\" ObjectExtractionPath=\""+qsObjectName+"\" />\n";
    qsMenuXML += "     </ImageObject>\n";
    qsMenuXML += "    </NormalState>\n";

    qsMenuXML += "    <SelectedState>\n";
    qsMenuXML += "     <FrameObject Width=\"10\" Color=\"#a0ff1414\" >\n";
    qsMenuXML += "      <MenuObject Width=\""+qsW+"\" X=\""+qsX+"\" Y=\""+qsY+"\" Height=\""+qsH+"\" ObjectName=\""+qsFrameName+"\" />\n";
    qsMenuXML += "     </FrameObject>\n";
    qsMenuXML += "    </SelectedState>\n";
    qsMenuXML += "    <HighlightedState>\n";
    qsMenuXML += "     <FrameObject Width=\"10\" Color=\"#ff0f0fff\" >\n";
    qsMenuXML += "      <MenuObject Width=\""+qsW+"\" X=\""+qsX+"\" Y=\""+qsY+"\" Height=\""+qsH+"\" ObjectName=\""+qsFrameName+"\" />\n";
    qsMenuXML += "     </FrameObject>\n";
    qsMenuXML += "    </HighlightedState>\n";
    qsMenuXML += "    <MenuObject Width=\""+qsW+"\" X=\""+qsX+"\" Y=\""+qsY+"\" Height=\""+qsH+"\" ObjectName=\""+qsButtonName+"\" />\n";
    qsMenuXML += "   </ButtonObject>\n";
  }
  // Create prev/next buttons
  int  iNrOfMenus = m_iNrOfMenus;
  if ( m_pConfigWidget->m_pCheckMainMenu->isChecked ( ) )
       iNrOfMenus ++;

  bool bPrev = ( iMenuNumber > 1 );
  bool bNext = ( iMenuNumber < iNrOfMenus );
  qsMenuXML += getMenuButtons ( bPrev, bNext, iMenuNumber );

  qsMenuXML += "  </PreviewVariables>\n";
  qsMenuXML += " </DVDMenu>\n";

  return qsMenuXML;
}

QString ComplexDVD::getMenuButtons ( bool bPrev, bool bNext, int iMenuNumber )
{
  QString qsMenuXML, qsMenuName;
  // The three buttons to the previous, next and Main menu ...
  QString qsButtonPrev = SYSTEM_DIRECTORY"/share/qdvdauthor/plugins/complexdvd/prev.png";
  QString qsButtonMain = SYSTEM_DIRECTORY"/share/qdvdauthor/plugins/complexdvd/main.png";
  QString qsButtonNext = SYSTEM_DIRECTORY"/share/qdvdauthor/plugins/complexdvd/next.png";
  if ( bPrev )  {
    if ( iMenuNumber < 3 )
      qsMenuName = QString ( "vmgm" );
    else
      qsMenuName = QString ( "Menu %1" ).arg ( iMenuNumber - 1 );
    qsMenuXML += "   <ButtonObject Action=\"jump+-+"+qsMenuName+"+-+\" ButtonName=\"Button 7\" >\n";
    qsMenuXML += "    <NormalState>\n";
    qsMenuXML += "     <ImageObject FileName=\""+qsButtonPrev+"\" >\n";
    qsMenuXML += "      <Manipulator>\n";
    qsMenuXML += "       <Modifiers/>\n";
    qsMenuXML += "       <ColorKey Color=\"#fffefffe\" />\n";
    qsMenuXML += "      </Manipulator>\n";
    qsMenuXML += "      <MenuObject Width=\"60\" X=\"253\" Y=\"212\" Height=\"45\" ObjectName=\"PrevImg\" ObjectExtractionPath=\"PrevImg\" />\n";
    qsMenuXML += "     </ImageObject>\n";
    qsMenuXML += "    </NormalState>\n";
    qsMenuXML += "    <SelectedState>\n";
    qsMenuXML += "     <MaskObject Color=\"#a0ff1414\" />\n";
    qsMenuXML += "    </SelectedState>\n";
    qsMenuXML += "    <HighlightedState>\n";
    qsMenuXML += "     <MaskObject Color=\"#a0fa9632\" />\n";
    qsMenuXML += "    </HighlightedState>\n";
    qsMenuXML += "    <MenuObject Width=\"60\" X=\"253\" Y=\"212\" Height=\"45\" ObjectName=\"ButtonPrev\" />\n";
    qsMenuXML += "   </ButtonObject>\n";
  }
  if ( bNext )  {
    qsMenuName = QString ( "Menu %1" ).arg ( iMenuNumber + 1 );
    qsMenuXML += "   <ButtonObject Action=\"jump+-+"+qsMenuName+"+-+\" ButtonName=\"Button 8\" >\n";
    qsMenuXML += "    <NormalState>\n";
    qsMenuXML += "     <ImageObject FileName=\""+qsButtonNext+"\" >\n";
    qsMenuXML += "      <Manipulator>\n";
    qsMenuXML += "       <Modifiers/>\n";
    qsMenuXML += "       <ColorKey Color=\"#fffefffe\" />\n";
    qsMenuXML += "      </Manipulator>\n";
    qsMenuXML += "      <MenuObject Width=\"60\" X=\"378\" Y=\"213\" Height=\"45\" ObjectName=\"NextImg\" ObjectExtractionPath=\"NextImg\" />\n";
    qsMenuXML += "     </ImageObject>\n";
    qsMenuXML += "    </NormalState>\n";
    qsMenuXML += "    <SelectedState>\n";
    qsMenuXML += "     <MaskObject Color=\"#a0ff1414\" />\n";
    qsMenuXML += "    </SelectedState>\n";
    qsMenuXML += "    <HighlightedState>\n";
    qsMenuXML += "     <MaskObject Color=\"#a0fa9632\" />\n";
    qsMenuXML += "    </HighlightedState>\n";
    qsMenuXML += "    <MenuObject Width=\"60\" X=\"378\" Y=\"213\" Height=\"45\" ObjectName=\"ButtonNext\" />\n";
    qsMenuXML += "   </ButtonObject>\n";
  }
  // Button to the Main Menu ..
  qsMenuXML += "   <ButtonObject Action=\"jump+-+vmgm+-+\" ButtonName=\"Button 9\" >\n";
  qsMenuXML += "    <NormalState>\n";
  qsMenuXML += "     <ImageObject FileName=\""+qsButtonMain+"\" >\n";
  qsMenuXML += "      <Manipulator>\n";
  qsMenuXML += "       <Modifiers/>\n";
  qsMenuXML += "       <ColorKey Color=\"#fffefffe\" />\n";
  qsMenuXML += "      </Manipulator>\n";
  qsMenuXML += "      <MenuObject Width=\"60\" X=\"315\" Y=\"206\" Height=\"56\" ObjectName=\"MainImg\" ObjectExtractionPath=\"MainImg\" />\n";
  qsMenuXML += "     </ImageObject>\n";
  qsMenuXML += "    </NormalState>\n";
  qsMenuXML += "    <SelectedState>\n";
  qsMenuXML += "     <MaskObject Color=\"#a0ff1414\" />\n";
  qsMenuXML += "    </SelectedState>\n";
  qsMenuXML += "    <HighlightedState>\n";
  qsMenuXML += "     <MaskObject Color=\"#a0fa9632\" />\n";
  qsMenuXML += "    </HighlightedState>\n";
  qsMenuXML += "    <MenuObject Width=\"60\" X=\"315\" Y=\"206\" Height=\"56\" ObjectName=\"ButtonMain\" />\n";
  qsMenuXML += "   </ButtonObject>\n";

  return   qsMenuXML;
}

QRect ComplexDVD::scaleScreenshot ( QString &qsScreenshot, int iWidth, int iHeight )
{
  QRect rect ( 0, 0, iWidth, iHeight );
  QFileInfo fileInfo  ( qsScreenshot );
  if ( ! fileInfo.exists ( ) )
    return rect;

  QString qsTemp = m_qsTempPath + "/" + fileInfo.baseName ( ) + ".png";
  QImage image ( qsScreenshot );
  if (   image.isNull ( ) )
    return rect;

  int x, y, w, h;
  double fScaleX = ( (double)image.height ( ) / image.width  ( ) );
  double fScaleY = ( (double)image.width  ( ) / image.height ( ) );
  x = 0; y = 0; w = iWidth; h = iHeight;

  if ( fScaleX <= fScaleY )  {
    // Here we are scaling based on the width
//    h = (int)( fScaleX * iHeight );
    h = (int)( fScaleX * iWidth );
    y = (int)( (double)( iHeight - h ) / 2.0 );
  }
  else  {
    // Here we are scaling based on the height
    w = (int)( fScaleY * iWidth );
    x = (int)( (double)( iWidth - w ) / 2.0 );
  }

  rect = QRect ( x, y, w, h );
  return rect;
}

}; // end namespace Plugin

