/****************************************************************************
** oneclickwizard.cpp
**
**   Created : April 23 2008
**        by : Varol Okan using Kate
** Copyright : (c) Varol Okan
**   License : GPL v 2.0
**
*****************************************************************************/
#include <stdlib.h> 
#include <dlfcn.h>

#include <qdir.h>
#include <qframe.h>
#include <qlabel.h>
#include <qimage.h>
#include <qtimer.h>
#include <qregexp.h>
#include <qlayout.h>
#include <qtoolbox.h>
#include <qspinbox.h>
#include <qgroupbox.h>
#include <qlineedit.h>
#include <qcombobox.h>
#include <qcheckbox.h>
#include <qfileinfo.h>
#include <qpopupmenu.h>
#include <qpushbutton.h>
#include <qinputdialog.h>
#include <qapplication.h>

#include "utils.h"
#include "CONFIG.h"
#include "global.h"
#include "qdvdauthor.h"
#include "messagebox.h"
#include "dialogimages.h"
#include "oneclickwizard.h"
#include "filepreviewdialog.h"

#include "sourcefileentry.h"
#include "xml_slideshow.h"

namespace Input
{

OneClickWizard::Group::Group ( )
{
  pSourceFileEntry = NULL;
  pSlideshow       = NULL;
}

OneClickWizard::OneClickWizard ( QWidget *pParent, const char *pName, bool bModal, WFlags fl )
  : uiOneClickWizard ( pParent, pName, bModal, fl )
{
  m_pLayoutMain = new QHBoxLayout ( m_pFrameMain, 11, 4 );
  m_bCanClose   = true;
  m_iCurrentPlugin       = 0;
  m_bChangeProjectPath   = true;
  m_pVirtualFolderDialog = NULL;
  m_pDestroyFunction     = NULL;
  m_pConfigWidget        = NULL;
  m_pLibrary             = NULL;
  m_pPlugin              = NULL;
  m_pToolBoxGroups       = NULL;
  m_pScrollView          = NULL;

  //m_pGroupDVDParameters->hide ( ); // To be hidden for now I am not sure if this is required here ...
  m_pCheckCreateISO->hide ( );
  m_pCheckAddECC   ->hide ( );
  m_pCheckBurnDVD  ->hide ( );
  m_pEditDevice    ->hide ( );
//  m_pButtonAddImages->setEnabled ( FALSE );

  // Can not create QTolbox without any item, so we have to remove the first item in the constructor.
  createScrollView ( );
  m_pToolBoxGroups->removeItem ( m_pToolBoxGroups->item ( 0 ) );
  GroupView *pGroupView = new GroupView ( m_pToolBoxGroups, (SourceFileEntry *)NULL ); // or this 
  m_pToolBoxGroups->addItem ( pGroupView, QString ( "Groups" ) );

  m_pSpinThreads->setValue ( Global::iMaxRunningThreads );
  m_pFrameSlideshow->hide  ( );

  connect ( this, SIGNAL ( helpClicked ( ) ), this, SLOT ( slotHelp ( ) ) );
  connect ( m_pButtonBrowseTemp,  SIGNAL ( clicked ( ) ), this, SLOT ( slotBrowseTemp    ( ) ) );
  connect ( m_pButtonBrowseDVD,   SIGNAL ( clicked ( ) ), this, SLOT ( slotBrowseDVD     ( ) ) );
  connect ( m_pButtonUp,          SIGNAL ( clicked ( ) ), this, SLOT ( slotGroupUp       ( ) ) );
  connect ( m_pButtonDown,        SIGNAL ( clicked ( ) ), this, SLOT ( slotGroupDown     ( ) ) );
  connect ( m_pButtonDelete,      SIGNAL ( clicked ( ) ), this, SLOT ( slotGroupDelete   ( ) ) );
  connect ( m_pButtonRename,      SIGNAL ( clicked ( ) ), this, SLOT ( slotGroupRename   ( ) ) );
  connect ( m_pButtonAddVideos,   SIGNAL ( clicked ( ) ), this, SLOT ( slotAddVideos     ( ) ) );
  connect ( m_pButtonAddImages,   SIGNAL ( clicked ( ) ), this, SLOT ( slotAddImages     ( ) ) );
  connect ( m_pToolBoxGroups,     SIGNAL ( currentChanged( int ) ), this, SLOT ( slotCurrentGroup ( int ) ) );
  connect ( m_pComboPlugins,      SIGNAL ( activated    (  int ) ), this, SLOT ( slotChangePlugin ( int ) ) );
  connect ( m_pCheckCreateISO,    SIGNAL ( toggled      ( bool ) ), this, SLOT ( slotCreateISO ( bool ) ) );
  connect ( m_pCheckBurnDVD,      SIGNAL ( toggled      ( bool ) ), this, SLOT ( slotBurnDVD   ( bool ) ) );
  connect ( pGroupView,           SIGNAL ( contextMenuRequested( QListViewItem *, const QPoint &, int ) ),
            this, SLOT ( slotGroupContextMenu ( QListViewItem *, const QPoint &, int ) ) );
  connect ( m_pEditProjectName,   SIGNAL ( textChanged  (  const QString & ) ), 
            this, SLOT ( slotProjectName  ( const QString & ) ) );
}

/*
 *  Destroys the object and frees any allocated resources
 */
OneClickWizard::~OneClickWizard ( )
{
  deleteGroups ( );
  unloadPlugin ( );
}

void OneClickWizard::deleteGroups ( )
{
  QValueList<Group *>::iterator it = m_listOfGroups.begin ( );
  while ( it != m_listOfGroups.end ( ) )  {
    if ( (*it)->pSourceFileEntry )
      delete (*it)->pSourceFileEntry;
    if ( (*it)->pSlideshow )
      delete (*it)->pSlideshow;
    delete *it++;
  }
  m_listOfGroups.clear ( );
}

bool OneClickWizard::initMe ( )
{
  QString strDirectory   ( Global::qsSystemPath + "/share/qdvdauthor/plugins" );
  int iRet = loadPlugins ( strDirectory );

  if ( iRet > 0 )  {
    uiOneClickWizard::show ( );
    loadPlugin ( 0 );
  }
  return ( iRet > 0 );
}

void OneClickWizard::createScrollView ( )
{
  QGridLayout *pLayout = new QGridLayout ( m_pFrameGroups, 1, 1, 0, 6, "m_pLayout1");
  uint iFlags = Qt::WStaticContents;
#if (QT_VERSION > 0x0301FF)
  iFlags |= Qt::WNoAutoErase;
#else
  iFlags |= Qt::WPaintClever;
#endif
  m_pScrollView    = new QScrollView  ( m_pFrameGroups, "OWToolFRame", iFlags );
  m_pToolBoxGroups = new QToolBox     ( m_pScrollView->viewport ( ), "OWScrollView", iFlags );
  m_pScrollView->addChild             ( m_pToolBoxGroups );
  m_pScrollView->setVScrollBarMode    ( QScrollView::AlwaysOn );
  pLayout->addWidget ( m_pScrollView, 0, 0 );
  QTimer::singleShot ( 10, this, SLOT ( slotResizeScrollView ( ) ) );
}

void OneClickWizard::slotResizeScrollView ( )
{
  int iWidth  = m_pOuterFrame->width   ( ) - 32;
  int iHeight = m_pOuterFrame->height  ( ) - 54;
  int iCount  = m_pToolBoxGroups->count( );
  if ( iWidth  <  50 )
       iWidth  = 200;
  if ( iHeight <  50 )
       iHeight = 200;
  if ( iHeight < iCount * 28 + 120 )
       iHeight = iCount * 28 + 120;
  if ( ( m_pToolBoxGroups->width ( )  != iWidth ) ||
       ( m_pToolBoxGroups->height ( ) != iHeight ) )
         m_pToolBoxGroups->setFixedSize ( iWidth, iHeight );
  // Ugly workaround to refresh to the proper extensions
  // Why don't we have resize signals anywhere ?
  QTimer::singleShot ( 1500, this, SLOT ( slotResizeScrollView ( ) ) );
}

QString OneClickWizard::uniqueGroupName ( QString qsName )
{
  // This fnction will make sure all Groups hold a uniue name.
  int  t, iCount  = 0;
  QString qsGroup, qsReturn;
  bool     bFound = true;
  QRegExp rx ( ".*_\\d" );

  qsReturn = qsName.remove ( rx );
  while ( bFound ) {
    bFound = false;
    for ( t=0; t<m_pToolBoxGroups->count ( ); t++ ) {
      qsGroup = m_pToolBoxGroups->itemLabel ( t );
      if ( qsGroup == qsReturn ) {
        qsReturn    = qsName + QString ( "_%1" ).arg ( ++iCount, 2 );
        bFound      = true; // re-do the while loop
        break; // leave for - loop
      }
    }
  }
  return qsReturn;
}

int OneClickWizard::loadPlugins ( QString &strDirectory )
{
  QDir  theDir ( strDirectory );
  if ( !theDir.exists ( ) )  {
    printf ( "Fatal: Plugin directory <%s> does not exist.\n", strDirectory.ascii ( ) );
    return -1;
  }

  m_pComboPlugins->clear ( );

  theDir.setFilter  ( QDir::Files | QDir::Hidden );
  theDir.setSorting ( QDir::Reversed );
  const QFileInfoList *list = theDir.entryInfoList ( );
  QFileInfoListIterator it ( *list );
  QFileInfo *fi;
  QString qsFileName, qsFilePath;
  //QRegExp rx ( "*\\.so\\.*" ); all plugins
  QRegExp rx ( ".*\\.so$" );
  int iPluginCounter = 0;

  while ( ( fi = it.current   ( ) ) != 0 ) {
    qsFileName = fi->fileName ( );
    if ( qsFileName.find ( rx ) > -1 )  {
      qsFilePath = fi->filePath ( );
      // Okay so we have MyCreate *)pfound a library, lets check the interface ...
      void *pLibrary = dlopen ( qsFilePath.ascii ( ), RTLD_LAZY );
      if ( ! pLibrary ) {
        printf ( "Fatal: Cannot load library <%s>\n       %s\n", qsFilePath.ascii ( ), dlerror ( ) );
        return -1;
      }

      // reset errors
      dlerror ( );

      // load the symbols
      create_t   *pCreateLibrary = (create_t *) dlsym ( pLibrary, "createPlugin" );
      const char *pErrorString   = dlerror (  );
      if ( pErrorString ) {
        printf ( "Cannot load symbol create: %s\n", pErrorString );
        return -1;
      }

      destroy_t *pDestroyLibrary = (destroy_t *) dlsym ( pLibrary, "destroyPlugin" );
      pErrorString = dlerror ( );
      if ( pErrorString ) {
          printf ( "Cannot load symbol destroy: %s\n", pErrorString );
          return -1;
      }

      // create an instance of the class
      Plugin::Interface *pPlugin = pCreateLibrary ( );

      // use the class
      if ( pPlugin )  {
        //printf ( "SUCCESS : Plugin <%s> Name<%s>\n", qsFilePath.ascii ( ), pPlugin->getPluginName ( ).ascii ( ) );
        m_pComboPlugins->insertItem ( pPlugin->getPluginName ( ) ); //qsFileName );
        m_listOfPlugins .append     ( qsFilePath );
        iPluginCounter ++;
      }
      else
        printf ( "Could not create plugin %s\n", qsFilePath.ascii ( ) );
      // destroy the class
      pDestroyLibrary ( pPlugin );
      // unload the triangle library
      dlclose ( pLibrary );
    }
    ++it;
  }

  return iPluginCounter;
}

bool OneClickWizard::loadPlugin ( uint iWhich )
{
  if ( iWhich > m_listOfPlugins.count ( ) )
    return false;

  QString qsFilePath = m_listOfPlugins[iWhich];

  m_pLibrary = dlopen ( qsFilePath.ascii ( ), RTLD_LAZY );
  if ( ! m_pLibrary ) {
    printf ( "Fatal: Cannot load library <%s>\n       %s\n", qsFilePath.ascii ( ), dlerror ( ) );
    return false;
  }

  // reset errors
  dlerror ( );

  // load the symbols
  create_t   *pCreateLibrary = (create_t *) dlsym ( m_pLibrary, "createPlugin" );
  const char *pErrorString   = dlerror (  );

  if ( pErrorString ) {
    printf ( "Cannot load symbol create: %s\n", pErrorString );
    return false;
  }

  m_pDestroyFunction = (destroy_t *) dlsym ( m_pLibrary, "destroyPlugin" );
  pErrorString = dlerror ( );
  if ( pErrorString ) {
    printf ( "Cannot load symbol destroy: %s\n", pErrorString );
    return false;
  }

  // create an instance of the class
  m_pPlugin = pCreateLibrary ( );

  if ( m_pPlugin )  {
    connect ( m_pPlugin, SIGNAL ( signalNewMenuResponse ( int, QString, QString ) ), (QWidget *)parent ( ), SLOT ( slotNewMenuResponse ( int, QString, QString ) ) );
    connect ( m_pPlugin, SIGNAL ( signalNewSource ( Plugin::SourceGroup * ) ), (QWidget *)parent ( ), SLOT ( slotNewSource ( Plugin::SourceGroup * ) ) );
    m_pConfigWidget = m_pPlugin->getConfigWidget ( m_pFrameMain );
    if ( m_pConfigWidget )  {
         m_pLayoutMain->addWidget   ( m_pConfigWidget );
         m_pConfigWidget->show      ( );
    }
  }

  m_iCurrentPlugin = iWhich;
  checkControls ( );
  return true;
}

void OneClickWizard::unloadPlugin ( )
{
  disconnect ( m_pPlugin );

  // destroy the class
  if ( m_pPlugin && m_pDestroyFunction )  {
    m_pDestroyFunction ( m_pPlugin );
  }
  m_pDestroyFunction = NULL;
  m_pConfigWidget    = NULL;
  m_pPlugin          = NULL;

  // unload the triangle library
  if ( m_pLibrary )
    dlclose ( m_pLibrary );
  m_pLibrary = NULL;
}

void OneClickWizard::checkControls ( )
{
  int iSourceFileEntries = 0;
  int iSlideshows        = 0;

  // See what we got ...
  QValueList<Group *>::iterator it = m_listOfGroups.begin ( );
  while ( it != m_listOfGroups.end ( ) ) {
    if ( (*it)->pSourceFileEntry )
      iSourceFileEntries ++;
    if ( (*it)->pSlideshow )
      iSlideshows ++;
    it++;
  }
  int iTotals = iSourceFileEntries + iSlideshows;

  // Take care of Button Up / Down 
  slotCurrentGroup ( m_pToolBoxGroups->currentIndex ( ) );

  bool bShow = ( iTotals > 0 );
  m_pButtonDelete->setEnabled ( bShow );
  m_pButtonRename->setEnabled ( bShow );

  if ( iSlideshows > 1 )
    m_pFrameSlideshow->show ( );
  else
    m_pFrameSlideshow->hide ( );

  QWidget *pConfigPage = QWizard::page ( 1 );
  QWidget *pPluginPage = QWizard::page ( 2 );

  if ( m_pConfigWidget )  {
    setAppropriate   ( pPluginPage, TRUE );
    setFinishEnabled ( pPluginPage, bShow );
    setNextEnabled   ( pConfigPage, bShow );
    setFinishEnabled ( pConfigPage, FALSE );
  }
  else  {
    setAppropriate   ( pPluginPage, FALSE );
    setFinishEnabled ( pConfigPage, bShow );
    setNextEnabled   ( pConfigPage, FALSE );
  }
  if ( m_pToolBoxGroups->count ( ) == 0 )  {
    GroupView *pGroupView = new GroupView ( m_pToolBoxGroups, (SourceFileEntry *)NULL );
    m_pToolBoxGroups->addItem ( pGroupView, uniqueGroupName ( QString ( "Groups" ) ) );
  }
}

void OneClickWizard::slotChangePlugin ( int iNewPluginIdx )
{
  if ( m_iCurrentPlugin == iNewPluginIdx )
    return;

  unloadPlugin ( );
  loadPlugin ( iNewPluginIdx );
}

void OneClickWizard::slotHelp ( )
{
  QString qsText;
  if ( indexOf ( currentPage ( ) ) == 0 )  {
    qsText  = tr ( "<CENTER><B>Specify the Project name, and the temp / project directories</B></CENTER><br>" );
    qsText += tr ( "<B>Name : </B>This is the name of the project. The name is used for the project file.<br>" );
    qsText += tr ( "<B>Temp Dir : </B>This directory will hold temporary data which can be very large ( Typical temp data for a full DVD ~9GBytes )<br>" );
    qsText += tr ( "<B>DVD  Dir : </B>This is the directory where the DVD files will be created. You can preview the dvd through xine dvd://DVD-Dir/<P>" );

    qsText += tr ( "<B>DVD Parameters : </B><br><ul>" );
    qsText += tr ( "<li><B>Create ISO Image : </B>this check will create a DVD iso image which can be burned using e.g. K3b</li>" );
    qsText += tr ( "<li><B>Add ECC : </B>Add Error Correction Code to the ISO image. This will increase the size of the final DVD file but will add redundency informtion such that the player can correct errors through e.g. scratches on the DVD.</li>" );
    qsText += tr ( "<li><B>Burn to DVD : </B>If checked will burn the final DVD to the device specified.</li></ul>" );
  }
  else  {
    qsText += tr ( "<CENTER><B>This page allows you to create Groups.</B></CENTER><P>" );
    qsText += tr ( "<B><U>General : </U></B><br>" );
    qsText += tr ( "To create a DVD you need source files. Either video or images.<br>" );
    qsText += tr ( "You have to <U>create groups</U> on this page which will then be used for the DVD.<br>" );
    qsText += tr ( "Each Group corresponds to one button on a DVD menu.<br>" );
    qsText += tr ( "Each Group can consist of multiple source videos or of a selection of images for the slideshow creation process.<P>" );

    qsText += tr ( "<B>Add / Group Videos : </B>This button will open a dialog to create Groups of videos.<br>" );
    qsText += tr ( "<B>Add / Group Images : </B>This button will open a dialog to create Groups of slideshows.<br>" );
    qsText += tr ( "<B>Max Nr Of Buttons : </B>Parameter used to restrict the number of buttons per DVD menu<br>" );
    qsText += tr ( "<B>Choose Audio For Menus : </B>This button will let you choose either <U>one</U> or <U>multiple audio files</U> which are to be used for the DVD menus. These files are either used in sequence or randomly.<br>" );
    qsText += tr ( "<B>Select Plugin : </B>The creation of the actual DVD structure has been put in plugins. This allows for an easy and fast way to implement more vareiety for the creation process. If the plugin has a config window it will be displayed on an additional page.<P>" );

    qsText += tr ( "<B>Finish : </B>This button will finally create the DVD structure. This process might take a few minutes depending on the number of groups and DVD menus.<P>" );

    qsText += tr ( "<B>Note :</B>It is possible to <U>re-order the videos</U> inside a group through drag and drop." );
  }
  MessageBox::html ( this, tr ( "Help" ), qsText, QSize ( 650, 450 ) );
}

void OneClickWizard::slotProjectName( const QString &newName )
{
  QString qsPath = Global::qsTempPath + "/" + newName;
  m_pLabelTempPath->setText ( qsPath );
  if ( m_bChangeProjectPath )
    qsPath = Global::qsTempPath + "/" + newName + "/dvd";
  else
    qsPath = Global::qsProjectPath;

  m_pLabelDVDPath->setText  ( qsPath );
  Global::qsProjectName = newName;
}

void OneClickWizard::slotBrowseTemp ( )
{
  // This function will browse for the directory where the DVD is to be build.
  QString qsPathName = QFileDialog::getExistingDirectory ( m_pLabelTempPath->text ( ) );
  if  ( ( qsPathName.isEmpty ( ) ) || ( qsPathName.isNull( ) ) )
    return;

  Global::qsTempPath = qsPathName;
  slotProjectName ( Global::qsProjectName );
}

void OneClickWizard::slotBrowseDVD ( )
{
  // This function will browse for the directory where the DVD is to be build.
  QString qsPathName = QFileDialog::getExistingDirectory ( m_pLabelDVDPath->text ( ) );
  if  ( ( qsPathName.isEmpty ( ) ) || ( qsPathName.isNull( ) ) )
    return;

  m_bChangeProjectPath  = false;
  Global::qsProjectPath = qsPathName;
  slotProjectName ( Global::qsProjectName );
}

void OneClickWizard::slotGroupUp ( )
{
  GroupView *pGroupView  = (GroupView *)m_pToolBoxGroups->currentItem ( );
  if ( ! pGroupView )
    return;

  int iIndex = m_pToolBoxGroups->currentIndex ( );
  m_pToolBoxGroups->removeItem ( pGroupView );
  m_pToolBoxGroups->insertItem ( ( iIndex > 0 ) ? iIndex-1 : 0, pGroupView, pGroupView->groupName ( ) );
  m_pToolBoxGroups->setCurrentItem ( pGroupView );
}

void OneClickWizard::slotGroupDown ( )
{
  GroupView *pGroupView  = (GroupView *)m_pToolBoxGroups->currentItem ( );
  if ( ! pGroupView )
    return;

  int iIndex = m_pToolBoxGroups->currentIndex ( );
  m_pToolBoxGroups->removeItem ( pGroupView );
  m_pToolBoxGroups->insertItem ( iIndex+1, pGroupView, pGroupView->groupName ( ) );
  m_pToolBoxGroups->setCurrentItem ( pGroupView );
}

void OneClickWizard::slotGroupDelete ( )
{
  GroupView *pGroupView  = (GroupView *)m_pToolBoxGroups->currentItem ( );
  if ( ! pGroupView )
    return;

  if ( MessageBox::warning ( this, tr ( "Delete Group" ), tr ( "Are you sure you want to delete the group:\n%1 ?" ).arg ( pGroupView->groupName ( ) ), QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
      return;
  QValueList<Group *>::iterator it = m_listOfGroups.begin ( );
  while ( it != m_listOfGroups.end ( ) )  {
    if ( (*it)->pSourceFileEntry == pGroupView->sourceFileEntry ( ) )  {
      delete pGroupView->sourceFileEntry ( );
      m_listOfGroups.erase ( it );
      break;
    }
    it++;
  }
  delete pGroupView;
  checkControls ( );
}

void OneClickWizard::slotGroupRename ( )
{
  GroupView *pGroupView  = (GroupView *)m_pToolBoxGroups->currentItem ( );
  if ( ! pGroupView )
    return;

  int iIdx = m_pToolBoxGroups->currentIndex ( );
  QString qsCurrent = m_pToolBoxGroups->itemLabel ( iIdx );
  QString qsHeader  = tr ( "Enter name for current group." );
  QString qsLabel   = tr ( "Enter Group Name : " );
  QString qsTitle   = QInputDialog::getText ( qsHeader, qsLabel, QLineEdit::Normal, qsCurrent );
  if ( qsTitle.isEmpty ( ) )
    return;

  m_pToolBoxGroups->setItemLabel ( iIdx, qsTitle );
  pGroupView->setGroupName ( qsTitle );
}

void OneClickWizard::slotAddVideos ( )
{
  DialogFiles fileDialog ( this );
  fileDialog.initMe      ( );
  if ( fileDialog.exec   ( ) == QDialog::Rejected )
    return;

  // Basic test to remove empty Groups ...
  for ( int t=0; t<m_pToolBoxGroups->count ( ); t++ )  {
    QListView *pList = (QListView *)m_pToolBoxGroups->item ( t );
    if ( pList->childCount ( ) < 1 )  {
      m_pToolBoxGroups->removeItem ( pList );
      delete pList;
    }
  }

  QValueList<SourceFileEntry *>newList = fileDialog.getGroups ( );
  // If we have something selected, then we should display the MaxNrOfButtons per menu
  QValueList<SourceFileEntry *>::iterator it = newList.begin  ( );
  Group *pGroup = NULL;

  while ( it != newList.end ( ) )  {
    pGroup = new Group;
    pGroup->pSourceFileEntry = *it++;
    addGroup ( pGroup->pSourceFileEntry );
    m_listOfGroups.append ( pGroup );
  }
  checkControls ( );
}

GroupView *OneClickWizard::addGroup ( SourceFileEntry *pEntry )
{
  int       t;
  bool      bAlternate = true;
  QFileInfo fileInfo;
  QPixmap   thePixmap, errorPixmap;
  SourceFileInfo *pInfo = NULL;
  Cache::Thumbs::Entry *pCache;
  GroupView::Item *pItem      = NULL;
  GroupView       *pGroupView = new GroupView ( m_pToolBoxGroups, pEntry ); // or this 
  QImage theImage ( QImage ( ).fromMimeSource ( "error.jpg" ) );

  theImage = theImage.smoothScale ( GroupView::m_iSize, GroupView::m_iSize );
  errorPixmap.convertFromImage ( theImage );

  for ( t=(int)pEntry->listFileInfos.count ( )-1; t>=0; t-- ) {
    pInfo = pEntry->listFileInfos[t];
    pCache = Global::pThumbsCache->find ( pInfo->qsFileName );
    fileInfo.setFile ( pInfo->qsFileName );
    bAlternate = ! bAlternate;
    pItem = new GroupView::Item ( pGroupView, fileInfo.fileName ( ), bAlternate );
    pItem->pSourceFileInfo = pInfo;
    if ( pCache )  {
      pItem->pCache = pCache;
      if ( ! pCache->arrayOfThumbs )
	pCache->loadImages ( );
      if ( pCache->arrayOfThumbs && pCache->arrayOfThumbs[0] ) {
	theImage = pCache->arrayOfThumbs[0]->smoothScale ( GroupView::m_iSize, GroupView::m_iSize, QImage::ScaleMin );
	thePixmap.convertFromImage ( theImage );
	pItem->setPixmap ( 0, thePixmap );
      }
      else
	pItem->setPixmap ( 0, errorPixmap );
    }
    else
      pItem->setPixmap ( 0, errorPixmap );
  }
  connect  ( pGroupView, SIGNAL ( contextMenuRequested ( QListViewItem *, const QPoint &, int ) ), this, SLOT ( slotGroupContextMenu ( QListViewItem *, const QPoint &, int ) ) );

  // And finally we can add the listBox to the ToolBox
  m_pToolBoxGroups->addItem ( pGroupView, uniqueGroupName ( pEntry->qsDisplayName ) );
  return pGroupView;
}

GroupView *OneClickWizard::addGroup ( CXmlSlideshow *pSlideshow )
{
  if ( ! pSlideshow )
    return NULL;

  int       t;
  bool      bBitmapSet = false;
  bool      bAlternate =  true;
  QFileInfo fileInfo;
  QPixmap   thePixmap, errorPixmap;
  Cache::Thumbs::Entry       *pCache  = NULL;
  CXmlSlideshow::time_object *pXmlObj = NULL;
  CXmlSlideshow::img_struct  *pXmlImg = NULL;
  CXmlSlideshow::vid_struct  *pXmlVid = NULL;
  CXmlSlideshow::img_struct   tempImg;
  CXmlSlideshow::vid_struct   tempVid;
  GroupView::Item *pItem       = NULL;
  GroupView       *pGroupView  = new GroupView ( m_pToolBoxGroups, NULL, NULL, pSlideshow );
  QImage theImage ( QImage ( ).fromMimeSource ( "error.jpg" ) );

  theImage = theImage.smoothScale ( GroupView::m_iSize, GroupView::m_iSize );
  errorPixmap.convertFromImage    ( theImage );

  uint iCount = pSlideshow->count ( );
  for ( t=(int)iCount-1; t>=0; t-- ) {
    pItem      = NULL;
    bBitmapSet = false;
    pXmlObj = pSlideshow->getTimeObject ( t );
    if ( ! pXmlObj ) // || t > 100 ) // Only the first 100 images for performance issues
      continue;

    bAlternate = ! bAlternate;

    if ( pXmlObj->node_name == tempImg.node_name )  {
      pXmlImg = (CXmlSlideshow::img_struct *)pXmlObj;
      pCache  = Global::pThumbsCache->find ( pXmlImg->src, true );
      fileInfo.setFile ( pXmlImg->src );
      pItem = new GroupView::Item ( pGroupView, fileInfo.fileName ( ), bAlternate );
    }
    else if ( pXmlObj->node_name == tempVid.node_name )  {
      pXmlVid = (CXmlSlideshow::vid_struct *)pXmlObj;
      pCache  = Global::pThumbsCache->find ( pXmlVid->src, false );
      fileInfo.setFile ( pXmlVid->src );
      pItem = new GroupView::Item ( pGroupView, fileInfo.fileName ( ), bAlternate );
    }
    if ( ! pItem )
      continue;

    if ( pCache )  {
      pItem->pCache = pCache;
      if ( ! pCache->arrayOfThumbs )
             pCache->loadImages  ( );
      if ( pCache->arrayOfThumbs && pCache->arrayOfThumbs[0] ) {
        if ( pCache->getMatrix ( ) )  {
             theImage = pCache->arrayOfThumbs[0]->xForm ( *pCache->getMatrix ( ) );
             theImage = theImage.smoothScale ( GroupView::m_iSize, GroupView::m_iSize, QImage::ScaleMin );
        }
        else
          theImage = pCache->arrayOfThumbs[0]->smoothScale ( GroupView::m_iSize, GroupView::m_iSize, QImage::ScaleMin );
        thePixmap.convertFromImage ( theImage );
        pItem->setPixmap ( 0, thePixmap );
        bBitmapSet = true;
      }
    }
    if ( ! bBitmapSet )
      pItem->setPixmap ( 0, errorPixmap );
  }

  connect  ( pGroupView, SIGNAL ( contextMenuRequested ( QListViewItem *, const QPoint &, int ) ), this, SLOT ( slotGroupContextMenu ( QListViewItem *, const QPoint &, int ) ) );

  // And finally we can add the listBox to the ToolBox
  m_pToolBoxGroups->addItem ( pGroupView, uniqueGroupName ( pSlideshow->slideshow_name ) );
  return pGroupView;
}

void OneClickWizard::slotGroupContextMenu ( QListViewItem *pSelItem, const QPoint &pos, int )
{
  QPopupMenu *pMenu   = new QPopupMenu  ( this );
  int iIDs[4];
  iIDs[0] = pMenu->insertItem ( tr ( "to &Group ..." ), 1 ); // play in player
  iIDs[1] = pMenu->insertItem ( tr ( "&Play" ),         2 ); // play in player2
  pMenu->insertSeparator ( );
  iIDs[2] = pMenu->insertItem ( tr ( "&Add" ),          3 ); // add a new entry
  iIDs[3] = pMenu->insertItem ( tr ( "&Remove" ),       4 ); // remove this one entry

  if ( ! pSelItem )  {
    pMenu->setItemEnabled ( iIDs[0], false );
    pMenu->setItemEnabled ( iIDs[1], false );
    pMenu->setItemEnabled ( iIDs[3], false );
  }
  else if ( m_pToolBoxGroups->count ( ) < 2 )
    pMenu->setItemEnabled ( iIDs[0], false );

  int iID = pMenu->exec  ( pos );

  GroupView::Item *pItem = (GroupView::Item *)pSelItem;
  GroupView *pGroupView  = (GroupView *)m_pToolBoxGroups->currentItem ( );

  if ( iID == 1 )         // toGroup
    toSourceGroup  ( );
  else if ( iID == 2 )  { // Play
    if ( pItem && pItem->pCache )
      play ( pItem->pCache->qsFileName );
  }
  else if ( iID == 3 )    // Add
    addSourceToGroup ( pGroupView );
  else if ( iID == 4 )  { // Remove
    if ( pItem )
      delete pItem;
  }
}

void OneClickWizard::toSourceGroup ( )
{
  // Pops open a new QListBox based Dialog.
  // No Ok / Cancel et. simply clicking on the
  // VirtualFolder Item will assign the object to this folder.
  int t;
  bool bAlternate = false;
  if ( m_pVirtualFolderDialog )
    delete m_pVirtualFolderDialog;

  m_pVirtualFolderDialog = new QListBox ( NULL, "Test", Qt::WType_Dialog | Qt::WShowModal | Qt::WStyle_NoBorder  | Qt::WStyle_StaysOnTop );
  m_pVirtualFolderDialog->resize ( 200, 450 );

  for ( t=0; t<m_pToolBoxGroups->count ( ); t++ ) {
    //m_pVirtualFolderDialog->insertItem ( pFolder->text ( 0 ) );
    //new QListBoxText ( m_pVirtualFolderDialog, pFolder->text ( 0 ) );
    bAlternate = ! bAlternate;
    new DialogFiles::VFSelectItem ( bAlternate, m_pVirtualFolderDialog, m_pToolBoxGroups->itemLabel ( t ) );
  }
  connect ( m_pVirtualFolderDialog, SIGNAL ( pressed ( QListBoxItem * ) ), this, SLOT ( slotSourceToSourceGroup ( QListBoxItem * ) ) );
  m_pVirtualFolderDialog->show ( );
}

void OneClickWizard::slotSourceToSourceGroup ( QListBoxItem *pSelItem )
{
  bool      bSelected  = true;
  int       t, i;
  QFileInfo fileInfo;
  QImage    theImage;
  QPixmap   thePixmap;
  GroupView *pTargetGroup = NULL;
  GroupView *pSourceGroup = NULL;
  GroupView::Item *pSourceItem, *pTargetItem;

  // This function is only called from m_pVirtualFolderDialog
  disconnect ( m_pVirtualFolderDialog );
  if ( pSelItem ) {
    // First we get th GroupView where we want to move this item to.
    QString qsEntryName  =  pSelItem->text ( );
    for  ( t=0; t<m_pToolBoxGroups->count ( ); t++ ) {
      if ( m_pToolBoxGroups->itemLabel   ( t ) == qsEntryName ) {
	pTargetGroup = (GroupView *)m_pToolBoxGroups->item(  t  );
	break;
      }
    }
    pSourceGroup = (GroupView *)m_pToolBoxGroups->currentItem ( );
    if ( pTargetGroup && pSourceGroup )  {
      // First we have to get the selected items
      pSourceItem  = (GroupView::Item *)pSourceGroup->currentItem ( );
      if ( pSourceItem )  {
	// gotcha ...
	pTargetItem = new GroupView::Item ( pTargetGroup, pSourceItem->text ( 0 ), true );
	const QPixmap *pPixmap = pSourceItem->pixmap ( 0 );
	if ( pPixmap )
	  pTargetItem->setPixmap ( 0, *pPixmap );
	pTargetItem->pSourceFileInfo = pSourceItem->pSourceFileInfo;
	pTargetItem->pCache          = pSourceItem->pCache;
	// FInally we can delete the source item
	delete pSourceItem;
      }

      // And finally we give som visual feedback
      for ( t=0; t<9; t++ )  {
	m_pVirtualFolderDialog->setSelected ( pSelItem, bSelected );
	bSelected = ! bSelected;
	for ( i=0; i<10; i++ )  {
	  usleep ( 8000 ); // 8 ms
	  qApp->processEvents ( );
	}
      }
    }
  }
  delete m_pVirtualFolderDialog;
  m_pVirtualFolderDialog = NULL;
  if ( pTargetGroup )
    QTimer::singleShot ( 10, pTargetGroup, SLOT ( slotAlternateColors ( ) ) );
  if ( pSourceGroup )
    QTimer::singleShot ( 10, pSourceGroup, SLOT ( slotAlternateColors ( ) ) );
}


void OneClickWizard::play ( QString qsFileName )
{
  QString qsCommand;
  qsCommand = Global::qsExternalPlayer + " " + qsFileName + " &";

  int iRet = system ( qsCommand.ascii ( ) );
  iRet++; // avoid compiler to complain.
}

void OneClickWizard::addSourceToGroup ( GroupView *pGroupView )
{
  int t;
  QFileInfo        fileInfo;
  QImage           theImage;
  QPixmap          thePixmap;
  QString          qsMovieFilter;
  QStringList      list;
  GroupView::Item *pItem;
  qsMovieFilter =  Global::pApp->getImageFilter ( );
  if ( pGroupView->sourceFileEntry ( ) )
    qsMovieFilter =  Global::pApp->getMovieFilter ( );

  list          =  FilePreviewDialog::getOpenFileNames ( NULL, Global::qsCurrentPath, QString ("Movies ( ") + qsMovieFilter + QString (" );;All ( * )"));
  if ( list.count ( ) < 1 )
    return;

  Cache::Thumbs::Entry *pEntry = NULL;
  for ( t=(int)list.count ( )-1; t>=0; t-- ) {
    pEntry = Global::pThumbsCache->find ( list[t] );
    fileInfo.setFile ( list[t] );
    if ( pEntry )  {
      pItem  = new GroupView::Item ( pGroupView, fileInfo.fileName ( ), true );
      if ( ! pEntry->arrayOfThumbs )
             pEntry->loadImages  ( );
      theImage = pEntry->arrayOfThumbs[0]->smoothScale ( GroupView::m_iSize, GroupView::m_iSize, QImage::ScaleMin );
    }
    else {
      // No cache entry exists. So we have to create one.
      pEntry   = Global::pThumbsCache->append ( list[t], pGroupView );
      pItem    = new GroupView::Item ( pGroupView, fileInfo.fileName ( ), true );
      theImage = QImage ( ).fromMimeSource( "please_wait.jpg" );
      theImage = theImage.smoothScale ( GroupView::m_iSize, GroupView::m_iSize, QImage::ScaleMin );
      m_bCanClose = false;
    }
    thePixmap.convertFromImage ( theImage );
    pItem->setPixmap ( 0, thePixmap );
    pItem->pCache = pEntry;
  }
  QTimer::singleShot ( 10, pGroupView, SLOT ( slotAlternateColors ( ) ) );
}

void OneClickWizard::slotAddImages ( )
{
  DialogImages fileDialog ( this );
  fileDialog.initMe     ( );
  if ( fileDialog.exec  ( ) == QDialog::Rejected )
    return;

  // Basic test to remove empty Groups ...
  for ( int t=0; t<m_pToolBoxGroups->count ( ); t++ )  {
    QListView *pList = (QListView *)m_pToolBoxGroups->item ( t );
    if ( pList->childCount ( ) < 1 )  {
      m_pToolBoxGroups->removeItem ( pList );
      delete pList;
    }
  }

  CXmlSlideshow *pSlideshow;
  QValueList<CXmlSlideshow *>newList = fileDialog.getSlideshows ( );
  // If we have something selected, then we should display the MaxNrOfButtons per menu

  if ( newList.count ( ) > 0 )  {
    QValueList<CXmlSlideshow *>::iterator it = newList.begin  ( );
    Group *pGroup = NULL;

    while (  it != newList.end ( ) )  {
      pGroup     = new Group;
      pSlideshow = new CXmlSlideshow;
     *pSlideshow = *(*it++);
      pGroup->pSlideshow = pSlideshow;
      addGroup  ( pGroup->pSlideshow );
      m_listOfGroups.append ( pGroup );
    }
  }

  checkControls ( );
}

void OneClickWizard::slotCurrentGroup ( int iCurrentGroup )
{
  int iCount = m_pToolBoxGroups->count ( );
  bool bUp, bDown;
  bUp = bDown = false;
  if ( iCount > 1 )  {
    bUp = bDown = true;
    if ( iCurrentGroup == 0 )
      bUp   = false;
    if ( iCurrentGroup == iCount-1 )
      bDown = false;
  }
  m_pButtonUp  ->setEnabled ( bUp   );
  m_pButtonDown->setEnabled ( bDown );
}

void OneClickWizard::slotCreateISO ( bool bOn )
{
	m_pCheckAddECC->setEnabled ( bOn );
}

void OneClickWizard::slotBurnDVD ( bool bOn )
{
	m_pEditDevice->setEnabled ( bOn );
}

void OneClickWizard::accept ( )
{
  if ( ! m_bCanClose ) {
    if ( MessageBox::warning ( this, tr ( "Can't close." ), tr ( "Can not close dialog while waiting for MediaScanner to finish.\nDo you want to force Quit ?" ), QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
      return;
  }

  Global::qsProjectPath = m_pLabelDVDPath->text ( );

  Utils theUtils;
  theUtils.recMkdir ( Global::qsTempPath    );
  theUtils.recMkdir ( Global::qsProjectPath );

  if ( m_pFrameSlideshow->isVisible ( ) )
       Global::iMaxRunningThreads = m_pSpinThreads->value ( );
  if ( Global::iMaxRunningThreads < 1 )
       Global::iMaxRunningThreads = 1;

  groupsToPlugin ( );

  // Once we are at this point we can delete the stored objects ...
  deleteGroups ( );

  uiOneClickWizard::accept ( );
}

void OneClickWizard::groupsToPlugin ( )
{
  // This function will convert the SourceFileEntries, or the CXmlSlideshow objects
  // into a format suitable for the plugins.
  QValueList<Group *>::iterator it = m_listOfGroups.begin ( );
  Group *pSource  = NULL;
  while ( it != m_listOfGroups.end ( ) )  {
    pSource = *it++;
    Plugin::SourceGroup *pGroup = new Plugin::SourceGroup;
    pGroup->enType   = Plugin::SourceGroup::NTSC;
    if ( m_pComboType->currentText ( ) == "PAL" )
      pGroup->enType = Plugin::SourceGroup::PAL;

    if ( pSource->pSourceFileEntry )
      sourceFileToPlugin ( pGroup, pSource->pSourceFileEntry );
    else
      slideshowToPlugin  ( pGroup, pSource->pSlideshow );

    if ( m_pPlugin )
         m_pPlugin->addGroup ( pGroup );
  }
  // Here we'll create the DVD. The plugin will directly call back QDVDAuthor
  if ( m_pPlugin )  {
       m_pPlugin->setTempPath    ( Global::qsTempPath    );
       m_pPlugin->setProjectName ( Global::qsProjectName );
       m_pPlugin->execute ( );
  }
}

void OneClickWizard::sourceFileToPlugin ( Plugin::SourceGroup *pGroup, SourceFileEntry *pEntry )
{
  QDate date ( 2008,  1,  8 );
  QTime time (   12, 22, 44 );

  QValueList<SourceFileInfo *>::iterator itInfo;
  Utils theUtils;
  SourceFileInfo *pInfo      = NULL;
  QImage         *pPreview   = NULL;

  pGroup->qsGroupName        = pEntry->qsDisplayName;
  pGroup->bSlideshow         = false;
  pGroup->bCreateChapterMenu = false;

  // The following is currently not used ...
  pGroup->dateStart          = QDateTime ( date, time );
  date = date.addDays ( 10 );
  pGroup->dateEnd            = QDateTime ( date, time );
  ////////////////////////////////////////////////////////
  itInfo = pEntry->listFileInfos.begin ( );
  while ( itInfo != pEntry->listFileInfos.end ( ) )  {
    pInfo = *itInfo++;
    // Make sure the Group has a sceenshot associated with
    if ( pGroup->qsScreenshot.isEmpty ( ) )  {
      if ( pInfo->pPreview && !pInfo->pPreview->isNull ( ) ) 
        pPreview = pInfo->pPreview;
      else  {
        Cache::Thumbs::Entry *pCache;
        pCache = Global::pThumbsCache->find ( pInfo->qsFileName );
        if ( pCache && pCache->arrayOfThumbs && pCache->arrayOfThumbs[0] )
          pPreview = pCache->arrayOfThumbs[0];
      }
      QFileInfo fileInfo ( pInfo->qsFileName );
      QString qsScreenshot = theUtils.getUniqueTempFile ( fileInfo.baseName ( ) + ".png" );
      pPreview->save ( qsScreenshot, "PNG", 100 );
      pGroup->qsScreenshot = qsScreenshot;
    }
    Plugin::SourceGroup::SourceEntry *pSourceEntry = new Plugin::SourceGroup::SourceEntry;
    pSourceEntry->qsFileName = pInfo->qsFileName;
    pSourceEntry->iLength    = theUtils.getMsFromString ( pInfo->qsLength );
    pGroup->listFiles.append ( pSourceEntry );
  }
  // In case no screenshot could be found ... Sorry we have an issue here
  if ( pGroup->qsScreenshot.isEmpty ( ) )  {
    QImage theImage ( QImage ( ).fromMimeSource ( "error.jpg" ) );
    QString qsScreenshot = theUtils.getUniqueTempFile ( "error_group.png" );
    theImage.save ( qsScreenshot, "PNG", 100 );
    pGroup->qsScreenshot = qsScreenshot;
  }
}

void OneClickWizard::slideshowToPlugin ( Plugin::SourceGroup *pGroup, CXmlSlideshow *pSlideshow )
{
  QDate date ( 2008,  1,  8 );
  QTime time (   12, 22, 44 );

  unsigned int     t, iCount;
  CXmlSlideshow::time_object *pXmlObj = NULL;
  CXmlSlideshow::img_struct  *pXmlImg = NULL;
  CXmlSlideshow::img_struct   tempImg;
  CXmlSlideshow::vid_struct   tempVid;

  pGroup->qsGroupName         = pSlideshow->slideshow_name;
  pGroup->bSlideshow          = true;
  pGroup->bCreateChapterMenu  = false;
  pGroup->iFilterLength       = (int)( pSlideshow->filter_delay * 1000.0f );
  pGroup->qsBackground        = pSlideshow->background;
  pGroup->listFilter          = pSlideshow->validFilterNames;
  pGroup->listAudio           = pSlideshow->audio_list;
  pGroup->iFlags  =   pSlideshow->imgBkgImg ( ) ? 1 : 0;
  pGroup->iFlags |=   pSlideshow->intro_page    ? 2 : 0;
  pGroup->iFlags |= ( pSlideshow->yres == 576 ) ? 4 : 0;
  pGroup->iFlags |=   pSlideshow->kenBurns  ( ) ? 8 : 0;

  // The following is currently not used ...
  pGroup->dateStart           = QDateTime ( date, time );
  date = date.addDays ( 10 );
  pGroup->dateEnd             = QDateTime ( date, time );
  ////////////////////////////////////////////////////////
  iCount = pSlideshow->count ( );
  for ( t=0; t<iCount; t++ )  {
    pXmlObj = pSlideshow->getTimeObject ( t );
    pXmlImg = NULL;
    if ( pXmlObj->node_name == tempImg.node_name )  {
      pXmlImg = (CXmlSlideshow::img_struct *)pXmlObj;
      // Make sure the Group has a sceenshot associated with
      if ( pGroup->qsScreenshot.isEmpty ( ) )  {
           pGroup->qsScreenshot = pXmlImg->src;
        if ( pXmlImg->pMatrix )  {
           QString qsFileName = Global::qsTempPath + QString ( "/temp_%1.png" ).arg ( t );
           QImage img ( pXmlImg->src );
           img  = img.xForm ( *pXmlImg->pMatrix );
           img.save   ( qsFileName, "PNG", 100 );
           pGroup->qsScreenshot = qsFileName;
        }
      }
    }
    else if ( pXmlObj->node_name == tempVid.node_name )
      pXmlImg = (CXmlSlideshow::img_struct *)pXmlObj;
    if ( ! pXmlImg )
      continue;

    Plugin::SourceGroup::SourceEntry *pSourceEntry = new Plugin::SourceGroup::SourceEntry;
    pSourceEntry->qsFileName = pXmlImg->src;
    pSourceEntry->bVidSource = ( pXmlObj->node_name == tempVid.node_name );
    if ( pXmlImg->fDuration > 0.0f )
      pSourceEntry->iLength  = (unsigned long)( pXmlImg->fDuration * 1000.0 ); // in MSec
    else
      pSourceEntry->iLength  = (unsigned long)( pSlideshow->delay  * 1000.0 ); // in MSec
    pGroup->listFiles.append ( pSourceEntry );
  }
  // In case no screenshot could be found ... Sorry we have an issue here
  if ( pGroup->qsScreenshot.isEmpty ( ) )  {
    Utils theUtils;
    QImage theImage ( QImage ( ).fromMimeSource ( "error.jpg" ) );
    QString qsScreenshot = theUtils.getUniqueTempFile ( "error_group.png" );
    theImage.save ( qsScreenshot, "PNG", 100 );
    pGroup->qsScreenshot = qsScreenshot;
  }
}

/*
void OneClickWizard::slotChooseAudio ( )
{
  AssignMenuAudio dialogAssign ( this );
  dialogAssign.exec ( );

  return;
  // This function will pre-populate the structures for DVD creation.
  // Note: this is hardcoded stuff to files on my harddrive such as to test the plugin system
  // Once this is deemed usable I will continue work on the OneClickDVD wizrd and wrap up this
  // function.
//printf ( "Load Test data\n" );
  uint t, j;
  QDate date ( 2008,  1,  8 );
  QTime time (   12, 22, 44 );

  for ( t=0; t<10; t++ )  {
    Plugin::SourceGroup *pGroup = new Plugin::SourceGroup;
    pGroup->enType              = Plugin::SourceGroup::NTSC;
    pGroup->qsGroupName         = QString ( "Group %1" ).arg ( t );
    pGroup->qsScreenshot        = "/tmp/OneClick/screenshot.jpg";
    pGroup->bCreateChapterMenu  = false;
    pGroup->bSlideshow          = false;
    pGroup->dateStart           = QDateTime ( date, time );
    date = date.addDays ( 10 );
    pGroup->dateEnd             = QDateTime ( date, time );

    for ( j=0; j<5; j++ )  {
      Plugin::SourceGroup::SourceEntry *pEntry = new Plugin::SourceGroup::SourceEntry;
      pEntry->iLength = 448.820;
      pEntry->qsFileName.sprintf ( "/tmp/OneClick/vid%02d.mpg", t*5+j );
      pGroup->listFiles.append ( pEntry );
//printf ( "%s\n", pEntry->qsFileName.ascii ( ) );
    }
    if ( m_pPlugin )
         m_pPlugin->addGroup ( pGroup );
  }
  // Here we'll create the DVD
  if ( m_pPlugin )
       m_pPlugin->execute ( );
}
*/

}; // End namespace Input
