/*****************************************************************************
 ** Class SubtitlesGui
 **
 ** This is a sub-project to 'Q' DVD-Author to handle the subtitles - tab
 ** of the main application
 **
 *****************************************************************************/
#include <unistd.h>

#include <qtable.h>
#include <qimage.h>
#include <qlayout.h>
#include <qslider.h>
#include <qpainter.h>
#include <qlistbox.h>
#include <qfileinfo.h>
#include <qtextedit.h>
#include <qcombobox.h>
#include <qlineedit.h>
#include <qlcdnumber.h>
#include <qtabwidget.h>
#include <qdragobject.h>
#include <qpushbutton.h>
#include <qcolordialog.h>
#include <qfontdatabase.h>

#include "global.h"
#include "importsrt.h"
#include "exportsrt.h"
#include "messagebox.h"
#include "qdvdauthor.h"
#include "subtitlesgui.h"
#include "listviewmedia.h"
#include "sourcefileentry.h"
#include "qplayer/mediacreator.h"

MediaLabel::MediaLabel ( SubtitlesGui *pSubtitlesGui, QWidget *pParent, const char *pName, WFlags flags )
  : QLabel ( pParent, pName, flags )
{
  setAcceptDrops ( true );
  setText ( "<FONT COLOR=ORANGE SIZE=+5><CENTER>Please drag<BR>a<BR>video source</CENTER></FONT>" );
  m_pSubtitlesGui = pSubtitlesGui;
}

MediaLabel::~MediaLabel ( )
{
}

void MediaLabel::dropEvent ( QDropEvent *pEvent ) 
{
  QImage  theImage;
  QString theText;

  if ( QImageDrag::decode( pEvent, theImage ) )
    m_pSubtitlesGui->insertDraggedObject ( pEvent, theImage );
  if ( QTextDrag::decode( pEvent, theText ) )
    m_pSubtitlesGui->insertDraggedText   ( pEvent, theText  );
}

void MediaLabel::dragEnterEvent( QDragEnterEvent *pEvent )
{
  pEvent->accept( QTextDrag::canDecode  ( pEvent ) ||
		  QImageDrag::canDecode ( pEvent )  );
}


SubtitlesGui::SubtitlesGui ( QDVDAuthor *pDVDAuthor, QWidget *pParent, const char *pName, WFlags flags)
  : uiSubtitles ( pParent, pName, flags )
{
  m_pTableSubtitles->setShowGrid ( true );
  m_pTableSubtitles->setNumCols  ( 4 );
  m_pDVDAuthor      = pDVDAuthor;
  m_pLayout         = NULL;
  m_pDragLabel      = NULL;
  m_pSubtitles      = NULL;
  m_pSourceFileInfo = NULL;
  m_pMediaInterface = NULL;
  m_iAlignement     = Qt::AlignLeft;
  m_strStartTime    = QString ("00:00:00.000");
  m_strEndTime      = QString ("00:00:00.000");
  m_pButtonAppend->hide   ( );
  m_pButtonPrepend->hide  ( );
  m_pButtonTextOnly->hide ( );
  initMe  ( );
}

SubtitlesGui::~SubtitlesGui ()
{
  // If the app is closed then we should store the info...
  releaseSourceFileInfo ( );

  if ( m_pDragLabel )
    delete m_pDragLabel;
}

void SubtitlesGui::initMe ()
{
  m_pLayout    = new QGridLayout ( m_pFramePreview ); 
  m_pDragLabel = new MediaLabel  ( this, m_pFramePreview );
 
  m_pLayout->addWidget (m_pDragLabel, 0, 0);

  m_pMediaInterface = MediaCreator::createPreferredWidget (m_pFramePreview, "MediaWidget"); // ,(void *)pExistingMediaEngine);

  // This is take care of in the polish ( ) function for Xine and not necessary for MPlayer ...
  m_pMediaInterface->initMediaEngine    ( );
  m_pMediaInterface->getWidget()->setAcceptDrops ( true );
  m_pMediaInterface->getWidget()->hide  ( );
  m_pTableSubtitles->setNumRows ( 0 );
  m_pEditTransparency->setText ( "0.00" );

  // Next we init the font selection...
  QFontDatabase database;
  //  setTransparency (0.0);
  QStringList listFonts = database.families();
  m_pListFonts->insertStringList(listFonts);
  // Next we search for a good starting font ...
  uint t, iIndex;
  for (iIndex=0;iIndex<m_pListFonts->count();iIndex++)	{
    if (m_pListFonts->text(iIndex) == QString ("Arial"))
      break;
    else if (m_pListFonts->text(iIndex) == QString ("Courier"))
      break;
    else if (m_pListFonts->text(iIndex) == QString ("Times New Roman"))
      break;
    else if (m_pListFonts->text(iIndex) == QString ("Times"))
      break;
    else if (m_pListFonts->text(iIndex) == QString ("Nimbus Sans L"))
      break;
  }
  QString fontName = m_pListFonts->text(iIndex);

  m_pEditX->setText( "0" );
  m_pEditY->setText( "0" );
  m_pEditWidth->setText  ( "720" );
  m_pEditHeight->setText ( "480" );

  QStringList listStyles = database.styles (fontName);
  m_pComboFontStyle->insertStringList (listStyles);
  QString styleName = m_pComboFontStyle->text(0);
  m_pComboFontStyle->setCurrentItem(0);

  // Here we get the sizes of the font.
  QValueList<int> listSizes = database.pointSizes(fontName);
  if (listSizes.isEmpty())	{
    listSizes = database.smoothSizes(fontName, styleName);
    if (listSizes.isEmpty())	{
      listSizes = database.standardSizes();
    }
  }
  // So lets say we can set the fontFamily at least ...
  m_pListFonts->setCurrentItem(iIndex);
  // And here we take care of the FontSize ...
  iIndex = 0;
  for (t=0;t<listSizes.count();t++)	{
    m_pComboFontSizes->insertItem (QString ("%1").arg(listSizes[t]));
    if (listSizes[t] < 11)	// Lets get at least a nice big raedable size
      iIndex = t;
  }
  m_pComboFontSizes->setCurrentItem (iIndex);

  QString qsScripts("Unicode Latin Greek Cyrillic Armenian Georgian Runic Ogham SpacingModifiers CombiningMarks"
		    "Hebrew Arabic Syriac Thaana"
		    "Devanagari Bengali Gurmukhi Gujarati Oriya Tamil Telugu Kannada Malayalam Sinhala Thai Lao Tibetan Myanmar Khmer"
		    "Han Hiragana Katakana Hangul Bopomofo Yi"
		    "Ethiopic Cherokee CanadianAboriginal Mongolian"
		    "CurrencySymbols LetterlikeSymbols NumberForms MathematicalOperators TechnicalSymbols GeometricSymbols MiscellaneousSymbols EnclosedAndSquare Braille");
  QStringList listScripts = QStringList::split (QString (" "), qsScripts);
  m_pComboScript->insertStringList(listScripts);
  m_pComboScript->setCurrentItem(1);

  QPainter thePainter (m_pFrameBackgroundColor);
  thePainter.drawLine(0, 0, m_pFrameBackgroundColor->width(), m_pFrameFontColor->height());
	
  m_pTextEdit->setTextFormat(PlainText);
  
  // Finally we set up the callback routines ...
  connect ( m_pListFonts,        SIGNAL ( highlighted (int)), this, SLOT(slotFontFamilyChanged(int)));
  connect ( m_pComboFontStyle,   SIGNAL ( activated   (int)), this, SLOT(slotFontStyleChanged(int)));
  connect ( m_pComboFontSizes,   SIGNAL ( activated   (int)), this, SLOT(slotFontSizeChanged(int)));
  connect ( m_pComboScript,      SIGNAL ( activated   (int)), this, SLOT(slotScriptChanged(int)));
  connect ( m_pButtonLeft,       SIGNAL ( toggled    (bool)), this, SLOT(slotLeft(bool)));
  connect ( m_pButtonCenter,     SIGNAL ( toggled    (bool)), this, SLOT(slotCenter(bool)));
  connect ( m_pButtonRight,      SIGNAL ( toggled    (bool)), this, SLOT(slotRight(bool)));
  connect ( m_pButtonJustify,    SIGNAL ( toggled    (bool)), this, SLOT(slotJustify(bool)));
  connect ( m_pButtonVCenter,    SIGNAL ( toggled    (bool)), this, SLOT(slotVCenter(bool)));
  connect ( m_pButtonFit,        SIGNAL ( toggled    (bool)), this, SLOT(slotFit(bool)));
  connect ( m_pButtonStrikeout,  SIGNAL ( toggled    (bool)), this, SLOT(slotStrikeout(bool)));
  connect ( m_pButtonUnderline,  SIGNAL ( toggled    (bool)), this, SLOT(slotUnderline(bool)));
  connect ( m_pMediaInterface,   SIGNAL ( signalNewPosition ( int, const QString & ) ), this, SLOT ( slotNewPosition( int, const QString & ) ) );
  connect ( m_pMediaInterface,   SIGNAL ( signalNewPosition ( long ) ),                 this, SLOT ( slotNewPosition( long ) ) );
  connect ( m_pButtonBackgroundColor,SIGNAL(clicked() ), this, SLOT ( slotBackgroundColor() ) );
  connect ( m_pButtonFontColor,  SIGNAL ( clicked ( ) ), this, SLOT ( slotFontColor     ( ) ) );
  connect ( m_pButtonCloseSource,SIGNAL ( clicked ( ) ), this, SLOT ( slotCloseSource   ( ) ) );
  connect ( m_pButtonFB,         SIGNAL ( clicked ( ) ), this, SLOT ( slotMediaFB       ( ) ) );
  connect ( m_pButtonBack,       SIGNAL ( clicked ( ) ), this, SLOT ( slotMediaBack     ( ) ) );
  connect ( m_pButtonStop,       SIGNAL ( clicked ( ) ), this, SLOT ( slotMediaStop     ( ) ) );
  connect ( m_pButtonPlay,       SIGNAL ( clicked ( ) ), this, SLOT ( slotMediaPlay     ( ) ) );
  connect ( m_pButtonPlayStop,   SIGNAL ( clicked ( ) ), this, SLOT ( slotMediaPlayStop ( ) ) );
  connect ( m_pButtonFF,         SIGNAL ( clicked ( ) ), this, SLOT ( slotMediaFF       ( ) ) );
  connect ( m_pButtonAddNew,     SIGNAL ( clicked ( ) ), this, SLOT ( slotAddNew        ( ) ) );
  connect ( m_pButtonStart,      SIGNAL ( clicked ( ) ), this, SLOT ( slotStart         ( ) ) );
  connect ( m_pButtonEnd,        SIGNAL ( clicked ( ) ), this, SLOT ( slotEnd           ( ) ) );
  connect ( m_pButtonImport,     SIGNAL ( clicked ( ) ), this, SLOT ( slotImport        ( ) ) );
  connect ( m_pButtonExport,     SIGNAL ( clicked ( ) ), this, SLOT ( slotExport        ( ) ) ); 
  connect ( m_pButtonClear,      SIGNAL ( clicked ( ) ), this, SLOT ( slotClear         ( ) ) ); 
  connect ( m_pButtonDelete,     SIGNAL ( clicked ( ) ), this, SLOT ( slotDelete        ( ) ) ); 
  connect ( m_pButtonPrepend,    SIGNAL ( clicked ( ) ), this, SLOT ( slotPrepend       ( ) ) );
  connect ( m_pButtonAppend,     SIGNAL ( clicked ( ) ), this, SLOT ( slotAppend        ( ) ) );
  connect ( m_pButtonTextOnly,   SIGNAL ( clicked ( ) ), this, SLOT ( slotTextOnly      ( ) ) );
  connect ( m_pButtonSearchText, SIGNAL ( clicked ( ) ), this, SLOT ( slotSearchText    ( ) ) );

  connect ( m_pSliderVolume,       SIGNAL ( sliderMoved ( int ) ), this, SLOT ( slotVolumeChanged       ( int ) ) );
  connect ( m_pSliderTransparency, SIGNAL ( sliderMoved ( int ) ), this, SLOT ( slotTransparencyChanged ( int ) ) );
  connect ( m_pSliderPos,          SIGNAL ( sliderMoved ( int ) ), this, SLOT ( slotPositionChanged     ( int ) ) );
  updateButtons();
}

void SubtitlesGui::updateButtons ()
{
  if (m_pButtonLeft->isOn())
    m_pButtonLeft->setPixmap (QPixmap ().fromMimeSource("text_cleft.png"));
  else
    m_pButtonLeft->setPixmap (QPixmap ().fromMimeSource("text_left.png"));
  
  if (m_pButtonCenter->isOn())
    m_pButtonCenter->setPixmap (QPixmap ().fromMimeSource("text_ccenter.png"));
  else
    m_pButtonCenter->setPixmap (QPixmap ().fromMimeSource("text_center.png"));
  
  if (m_pButtonRight->isOn())
    m_pButtonRight->setPixmap (QPixmap ().fromMimeSource("text_cright.png"));
  else
    m_pButtonRight->setPixmap (QPixmap ().fromMimeSource("text_right.png"));
  
  if (m_pButtonJustify->isOn())
    m_pButtonJustify->setPixmap (QPixmap ().fromMimeSource("text_cjustify.png"));
  else
    m_pButtonJustify->setPixmap (QPixmap ().fromMimeSource("text_justify.png"));
  
  if (m_pButtonVCenter->isOn())
    m_pButtonVCenter->setPixmap (QPixmap ().fromMimeSource("text_cvcenter.png"));
  else
    m_pButtonVCenter->setPixmap (QPixmap ().fromMimeSource("text_vcenter.png"));
  
  if (m_pButtonFit->isOn())
    m_pButtonFit->setPixmap (QPixmap ().fromMimeSource("text_cfit.png"));
  else
    m_pButtonFit->setPixmap (QPixmap ().fromMimeSource("text_fit.png"));
  
  if (m_pButtonUnderline->isOn())
    m_pButtonUnderline->setPixmap (QPixmap ().fromMimeSource("text_cunderline.png"));
  else
    m_pButtonUnderline->setPixmap (QPixmap ().fromMimeSource("text_underline.png"));
  
  if (m_pButtonStrikeout->isOn())
    m_pButtonStrikeout->setPixmap (QPixmap ().fromMimeSource("text_cstrikeout.png"));
  else
    m_pButtonStrikeout->setPixmap (QPixmap ().fromMimeSource("text_strikeout.png"));
}

void SubtitlesGui::resetMediaWidget ()
{
  if ( m_pDragLabel ) {
    int iWidth, iHeight;
    iWidth  = m_pFramePreview->geometry ().width();
    iHeight = m_pFramePreview->geometry ().height();

    m_pDragLabel->show ( );
    m_pDragLabel->setGeometry ( 0, 0, iWidth, iHeight );
    m_pDragLabel->setText  ( "<FONT COLOR=ORANGE SIZE=+5><CENTER>Please drag<BR>a<BR>video source</CENTER></FONT>" );
    m_pTabSubtitles->setTabLabel ( m_pTabSubtitles->page ( 0 ), "No source selected." );
  }
}

///////////////////////////////////////////////////////////
//
// signal/slot handler
//
//////////////////////////////////////////////////////////
void SubtitlesGui::slotNewPosition(int iPos, const QString &qsTime )
{
  // iPos [0 .. 65535]
  // printf ("SubtitlesGui::slotNewPosition <%d><%s>\n", iPos, (const char *)qsTime);
  m_pSliderPos->setValue (iPos);
  m_strCurrentTime = qsTime.left ( 12 );
  m_pLCDNumberTime->display ( m_strCurrentTime );
}

void SubtitlesGui::slotNewPosition( long iTimeInMS )
{
  static uint iCurrentSubtitle = 0;
  static bool bCleared = false;
  uint t, iCounter;
  Subtitles::entry *pEntry;
  // Here we set the subtitle to the current one
  // Note: I tried to optimize this function for speed ...
  if ( m_pSubtitles ) {
  
    iCounter = m_pSubtitles->listOfSubtitles.count();
    for (t=iCurrentSubtitle;t<iCounter;t++) {
      pEntry = m_pSubtitles->listOfSubtitles[t];
      if ( ( iTimeInMS < pEntry->iTimeStop ) && ( iTimeInMS >= pEntry->iTimeStart ) )  {
	// found in time range
        if ( t != iCurrentSubtitle ) { // deon't need to redraw the same text over again
	  m_pTextEdit->setText ( pEntry->qsText );
	  m_pTextEdit->setAlignment ( m_iAlignement );
	  iCurrentSubtitle = t;
	  displayRow ( t );
	  bCleared = false;
        }
	return;
      }
      else if ( ( ! bCleared ) && ( iTimeInMS > m_pSubtitles->listOfSubtitles[ iCurrentSubtitle ]->iTimeStop ) ) {
	// clear the text if it is out of bound.
	m_pTextEdit->setText ( "" );
	m_pTableSubtitles->clearSelection ( );
	bCleared = true;
      }
      else if ( iTimeInMS < pEntry->iTimeStart )
      	break;
    } // could not find the entry in the first loop ...
    for (t=0;t<iCurrentSubtitle;t++) {
      pEntry = m_pSubtitles->listOfSubtitles[t];
      if ( ( iTimeInMS < pEntry->iTimeStop ) && ( iTimeInMS >= pEntry->iTimeStart ) )  {
        if ( t != iCurrentSubtitle ) {
	  m_pTextEdit->setText ( pEntry->qsText );
	  m_pTextEdit->setAlignment ( m_iAlignement );
	  bCleared = false;
	  iCurrentSubtitle = t;
	  displayRow ( t );
	}
	return;
      }
      else if ( ( ! bCleared ) && ( iTimeInMS > m_pSubtitles->listOfSubtitles[ iCurrentSubtitle ]->iTimeStop ) ) {
	bCleared = true;
	m_pTextEdit->setText ( "" );
	m_pTableSubtitles->clearSelection ( );
      }
      else if ( iTimeInMS < pEntry->iTimeStop )
	return;
    }
  }
}

void SubtitlesGui::slotCloseSource ()
{
  if ( m_pDragLabel )  {
    if ( ! m_pDragLabel->isVisible ( ) ) {
      // case we have dropped a movie and played at least a bit of it.
      int iWidth, iHeight;
      iWidth  = m_pFramePreview->geometry ( ).width ( );
      iHeight = m_pFramePreview->geometry ( ).height( );
      
      m_pMediaInterface->stop ( );
      m_pLayout->remove ( m_pMediaInterface->getWidget ( ) );
      m_pMediaInterface->getWidget( )->hide ( );
      
      //      resetMediaWidget      ( );      
      m_pLayout->addWidget  ( m_pDragLabel, 0, 0 );
      //      releaseSourceFileInfo ( );
    }
    resetMediaWidget      ( );      
    releaseSourceFileInfo ( );
    //    else if ( m_pDragLabel->text ( ) != "No source selected." ) {
    //      // case we have dropped a movie but have not yet started playing him.
    //      resetMediaWidget      ( );      
    //      releaseSourceFileInfo ( );
    //    }  
  }
}

void SubtitlesGui::slotMediaFB ()
{
  if ( ( m_pMediaInterface ) && ( m_pSourceFileInfo ) )
    m_pMediaInterface->setSpeed ( 0.25 );
}

void SubtitlesGui::slotMediaBack ()
{
  if ( ( m_pMediaInterface ) && ( m_pSourceFileInfo ) )
    m_pMediaInterface->setSpeed ( 0.5 );
}

void SubtitlesGui::slotMediaStop ()
{
  if ( ( m_pMediaInterface ) && ( m_pSourceFileInfo ) ) 
    m_pMediaInterface->pause ( );
}

void SubtitlesGui::slotMediaPlay ()
{
  if ( ( m_pMediaInterface ) && ( m_pSourceFileInfo ) ) {
    // Need the info from the tabel in the structure for easier access ...
    createSubtitles ();

    int iWidth, iHeight;
    QFileInfo fileInfo;
    QString qsFileName;
    iWidth  = m_pFramePreview->geometry ().width();
    iHeight = m_pFramePreview->geometry ().height();
    m_pLayout->remove           ( m_pDragLabel );
    m_pDragLabel->hide          ( );
    m_pMediaInterface->getWidget( )->show ( );
    m_pMediaInterface->getWidget( )->setGeometry ( 0, 0, iWidth, iHeight );

    m_pLayout->addWidget        ( m_pMediaInterface->getWidget (), 0, 0 );
    m_pMediaInterface->playMRL  ( m_pSourceFileInfo->qsFileName );
    fileInfo.setFile ( m_pSourceFileInfo->qsFileName );
    m_pTabSubtitles->setTabLabel ( m_pTabSubtitles->page ( 0 ), fileInfo.fileName () );
    //    printf ("SubtitlesGui::slotMediaPlay  ( ) - <%s>\n",  m_pSourceFileInfo->qsFileName.ascii() );
  }
}

void SubtitlesGui::slotMediaPlayStop ()
{
  if ( ( m_pMediaInterface ) && ( m_pSourceFileInfo ) ) {
    if ( ! m_pMediaInterface->isPlaying () )
      m_pMediaInterface->play ( );
    sleep ( 5 );
    m_pMediaInterface->pause ( );
  }
}

void SubtitlesGui::slotMediaFF ()
{
  if ( ( m_pMediaInterface ) && ( m_pSourceFileInfo ) )
    m_pMediaInterface->setSpeed ( 2.0 );
}

void SubtitlesGui::slotAddNew ()
{
  // This function will take the vlaues of m_pLCDNumberStart m_pLCDNumberEnd
  // and stuff it in the appropriate spot in the table.
  // Some sanity check are beeing made to prevent two entries at the same time.
  //  printf ("SubtitlesGui::slotAddNew ( %s - %s )\n", m_strStartTime.ascii(), m_strEndTime.ascii());
  uint t;
  int   iRow = 0;
  long  iStartTime, iEndTime;
  QTime timeStart, timeEnd, nullTime;
  Subtitles::entry *pEntry, *pNewEntry, *pNextEntry = NULL;

  if ( m_pTextEdit->text ().length () < 2 )
    return;
  
  timeStart = QTime::fromString ( m_strStartTime );
  timeEnd   = QTime::fromString ( m_strEndTime   );
  // first we should convert the times into mseconds ...
  iStartTime = nullTime.msecsTo ( timeStart );
  iEndTime   = nullTime.msecsTo ( timeEnd   );

  if ( iStartTime > iEndTime ) {
    long iTemp = iStartTime;
    iStartTime = iEndTime;
    iEndTime   = iTemp;  
  }

  if ( ! m_pSubtitles )
    m_pSubtitles = new Subtitles;

  for (t=0;t<m_pSubtitles->listOfSubtitles.count ();t++) {
    pEntry = m_pSubtitles->listOfSubtitles[t];
    iRow = t+1;

    //    printf (  "SubtitlesGui::slotAddNew () iStart=%ld > pEntry->iStart=%ld row=%d\n", iStartTime, pEntry->iTimeStart, iRow );
    if ( iStartTime >= pEntry->iTimeStart )
      continue;
    if ( t > 0 )
      pEntry = m_pSubtitles->listOfSubtitles[t-1];
    //    printf ( "SubtitlesGui::slotAddNew () IN !!!\n" );

    if ( ( iStartTime > pEntry->iTimeStart ) && ( iStartTime <= pEntry->iTimeStop   ) ) {
      // In this case. The new entry starts inside an already existing entry.
      //  ....[start] ....[newStart]....[end]... time ->
      
      // So we should change the current existing entry
      pEntry->iTimeStop  = iStartTime-1; // move the end before the start of the new entry ...
      if ( pEntry->iTimeStop < 0 )  // should never happen but ...
	pEntry->iTimeStop = 0;
      pEntry->qsTimeStop = m_pSubtitles->getStringFromTime ( pEntry->iTimeStop );
    }
    
    //    if ( t+1 < m_pSubtitles->listOfSubtitles.count () ) {
      pNextEntry =  m_pSubtitles->listOfSubtitles[t];
      if ( iEndTime >= pNextEntry->iTimeStart ) {
	// here we move the start of the next entry after the end of the new entry
	//  ....[end] ....[startNew]....[start]....[endNew]... time ->
	
	pNextEntry->iTimeStart   = iEndTime + 1;
	pNextEntry->qsTimeStart  = m_pSubtitles->getStringFromTime ( pNextEntry->iTimeStart );
	if ( pNextEntry->iTimeStart > pNextEntry->iTimeStop ) {
	  pNextEntry->iTimeStop  = pNextEntry->iTimeStart + 100; // make at least 100 mSecs 
	  pNextEntry->qsTimeStop = m_pSubtitles->getStringFromTime ( pNextEntry->iTimeStop );
	}
      }
      //    }
    // and exit the loop ...
    break;
  }
  // TODO: do the scaling until we are in normal teritory again 
  // I.e. until start < end.
  pNewEntry = new Subtitles::entry;
  pNewEntry->qsTimeStart = m_pSubtitles->getStringFromTime ( iStartTime );
  pNewEntry->qsTimeStop  = m_pSubtitles->getStringFromTime ( iEndTime   );
  pNewEntry->iTimeStart  = iStartTime;
  pNewEntry->iTimeStop   = iEndTime;
  pNewEntry->qsText      = m_pTextEdit->text ();

  QValueList<Subtitles::entry *>::iterator iter;
  iter = m_pSubtitles->listOfSubtitles.find ( pNextEntry );
  m_pSubtitles->listOfSubtitles.insert ( iter, pNewEntry );

  //  printf ("SubtitlesGui::slotAddNew () iRow = %d\n", iRow);

  //  m_pTableSubtitles->insertRows ( iRow, 1 );
  //  m_pTableSubtitles->setText    ( iRow, 1, pNewEntry->qsTimeStart );
  //  m_pTableSubtitles->setText    ( iRow, 2, pNewEntry->qsTimeStop  );
  //  m_pTableSubtitles->setText    ( iRow, 3, pNewEntry->qsText      );

  // Last is to fix the index ...
  for ( t=0;t< m_pSubtitles->listOfSubtitles.count ();t++)
    m_pSubtitles->listOfSubtitles[t]->iIndex = t;

  createTableEntries ();
  
  //  for ( t=0;t<(uint)m_pTableSubtitles->numRows();t++)
  //    m_pTableSubtitles->setText    ( iRow, 0, QString ("%1").arg( t ) );

  //  printf ("\n\n");
}

void SubtitlesGui::slotStart ()
{
  m_pLCDNumberStart->display ( m_strCurrentTime );
  m_strStartTime = m_strCurrentTime;
}

void SubtitlesGui::slotEnd ()
{
  m_pLCDNumberEnd->display ( m_strCurrentTime );
  if ( m_pMediaInterface->isPlaying ( ) )
    m_pMediaInterface->pause ( );
  m_strEndTime = m_strCurrentTime;
}

void SubtitlesGui::slotImport ()
{
  uint t;
  Subtitles::entry *pEntry;
  Import::Srt theImporter;
  if ( theImporter.import ( ) ) {
    m_pTableSubtitles->setNumRows ( theImporter.m_listOfEntries.count() );
    for (t=0;t<theImporter.m_listOfEntries.count();t++) {
      pEntry = theImporter.m_listOfEntries[t];
      m_pTableSubtitles->setText (t, 0, QString ("%1").arg(pEntry->iIndex ) );
      m_pTableSubtitles->setText (t, 1, pEntry->qsTimeStart );
      m_pTableSubtitles->setText (t, 2, pEntry->qsTimeStop  );
      m_pTableSubtitles->setText (t, 3, pEntry->qsText      );
    }
    createSubtitles ();
  }
}

void SubtitlesGui::slotClear ()
{
  if ( m_pTableSubtitles->numRows () > 10 ) 
    if ( MessageBox::warning ( NULL, tr("Attention:"), tr("Are you sure you want to delete all subtitles ?"), QMessageBox::Yes, QMessageBox::No ) == QMessageBox::No )
      return;

  if ( m_pSourceFileInfo && m_pSourceFileInfo->pSubtitles ) {
    delete m_pSourceFileInfo->pSubtitles;
    m_pSourceFileInfo->pSubtitles = NULL;
  }
  if ( m_pSubtitles )
    delete m_pSubtitles;
  m_pSubtitles = NULL;
  m_pTableSubtitles->setNumRows ( 0 );
}

bool SubtitlesGui::createSubtitles ()
{
  uint t;
  if ( m_pSubtitles )
    delete m_pSubtitles;
  m_pSubtitles = NULL;

  // If no subtitles ... then we should leave m_pSubtitles NULL
  if ( m_pTableSubtitles->numRows () < 1 )
    return true;

  int iHAlignment, iVAlignment;
  Subtitles::entry *pEntry;
  QRect theRect ( m_pEditX->text().toInt (),  m_pEditY->text().toInt (),  m_pEditWidth->text().toInt (),  m_pEditHeight->text().toInt () );

  iVAlignment = 1; // bottom ...
  if ( m_pButtonVCenter->isOn() )
    iVAlignment = 2;

  iHAlignment = 1;
  if ( m_pButtonLeft->isOn() )
    iHAlignment = 2;
  else if ( m_pButtonRight->isOn() )
    iHAlignment = 3;
  else if ( m_pButtonJustify->isOn() )
    iHAlignment = 4;

  m_pSubtitles = new Subtitles;
  m_pSubtitles->font          = m_qfFont;
  m_pSubtitles->rect          = theRect;
  m_pSubtitles->alignment     = QPoint ( iHAlignment, iVAlignment );
  m_pSubtitles->iTransparency = (unsigned char)( m_pEditTransparency->text().toFloat () * 255.0 );
  m_pSubtitles->subColors[0]  = m_pFrameBackgroundColor->paletteBackgroundColor ();
  m_pSubtitles->subColors[1]  = m_pFrameFontColor      ->paletteBackgroundColor ();
  
  //printf ("SubtitlesGui::createSubtitles <%d>\n",m_pTableSubtitles->numRows () );
  for (t=0;t<(uint)m_pTableSubtitles->numRows ();t++) {
    pEntry = new Subtitles::entry;
    //    pEntry->iIndex      = t;
    pEntry->iIndex      = m_pTableSubtitles->text ( t, 0 ).toInt();
    pEntry->qsTimeStart = m_pTableSubtitles->text ( t, 1 ).stripWhiteSpace ( );
    pEntry->qsTimeStop  = m_pTableSubtitles->text ( t, 2 ).stripWhiteSpace ( );
    pEntry->qsText      = m_pTableSubtitles->text ( t, 3 );
    pEntry->iTimeStart  = m_pSubtitles->getTimeFromString ( pEntry->qsTimeStart );
    pEntry->iTimeStop   = m_pSubtitles->getTimeFromString ( pEntry->qsTimeStop  );
    m_pSubtitles->listOfSubtitles.append ( pEntry );
  }
  return true;
}

void SubtitlesGui::createTableEntries ()
{
  uint t;
  Subtitles::entry *pEntry;
  if ( ! m_pSubtitles )
    return;
  
  m_pTableSubtitles->setNumRows ( m_pSubtitles->listOfSubtitles.count() );
  for (t=0;t<m_pSubtitles->listOfSubtitles.count();t++) {
    pEntry = m_pSubtitles->listOfSubtitles[t];
    m_pTableSubtitles->setText (t, 0, QString ("%1").arg(pEntry->iIndex ) );
    m_pTableSubtitles->setText (t, 1, pEntry->qsTimeStart );
    m_pTableSubtitles->setText (t, 2, pEntry->qsTimeStop  );
    m_pTableSubtitles->setText (t, 3, pEntry->qsText      );
  }
  m_pEditX     ->setText( QString ("%1").arg ( m_pSubtitles->rect.x     ( ) ) );
  m_pEditY     ->setText( QString ("%1").arg ( m_pSubtitles->rect.y     ( ) ) );
  if (  m_pSubtitles->rect.width ( ) > 5 )
    m_pEditWidth ->setText( QString ("%1").arg ( m_pSubtitles->rect.width ( ) ) );
  if (  m_pSubtitles->rect.height ( ) > 5 )
    m_pEditHeight->setText( QString ("%1").arg ( m_pSubtitles->rect.height( ) ) );
}

void SubtitlesGui::slotDelete ()
{
  int t;
  QValueList<int> rows;
  for ( t=0;t<m_pTableSubtitles->numRows ();t++) {
    if ( m_pTableSubtitles->isRowSelected ( t, true ) )
      rows.append ( t );
  }
  QMemArray<int> array ( rows.count () );
  for (t=0;t<(int)rows.count ();t++)
    array[t] = rows[t];

  m_pTableSubtitles->removeRows ( array );
  createSubtitles ();
}

void SubtitlesGui::slotExport ()
{
  Export::Srt theExporter;
  if ( createSubtitles () )
    theExporter.exportSrt ( m_pSubtitles );
}

void SubtitlesGui::slotPrepend ()
{

}

void SubtitlesGui::slotAppend ()
{

}

void SubtitlesGui::slotTextOnly ()
{

}

void SubtitlesGui::slotSearchText ()
{

}

void SubtitlesGui::slotFontColor ()
{
  QColor newColor = QColorDialog::getColor(m_foregroundColor, this);
  setForegroundColor (newColor);
}

void SubtitlesGui::slotBackgroundColor ()
{
  QColor newColor = QColorDialog::getColor(m_backgroundColor, this);
  setBackgroundColor (newColor);
}

void SubtitlesGui::slotFontFamilyChanged(int)
{
  updateFont(0);
}

void SubtitlesGui::slotFontStyleChanged(int)
{
  updateFont(1);
}

void SubtitlesGui::slotFontSizeChanged(int)
{
  updateFont(2);
}

void SubtitlesGui::slotScriptChanged(int)
{
  updateFont(0);
}

void SubtitlesGui::slotLeft (bool)
{
  if (m_pButtonLeft->isOn())	{
    m_pButtonCenter->setOn(false);
    m_pButtonRight->setOn(false);
    m_pButtonJustify->setOn(false);
  }
  updateFont(2);
}

void SubtitlesGui::slotCenter (bool)
{
  if (m_pButtonCenter->isOn())	{
    m_pButtonLeft->setOn(false);
    m_pButtonRight->setOn(false);
    m_pButtonJustify->setOn(false);
  }
  updateFont(2);
}

void SubtitlesGui::slotRight (bool)
{
  if (m_pButtonRight->isOn())	{
    m_pButtonCenter->setOn(false);
    m_pButtonLeft->setOn(false);
    m_pButtonJustify->setOn(false);
  }
  updateFont(2);
}

void SubtitlesGui::slotJustify (bool)
{
  if (m_pButtonJustify->isOn())	{
    m_pButtonCenter->setOn(false);
    m_pButtonRight->setOn(false);
    m_pButtonLeft->setOn(false);
  }
  updateFont(2);
}

void SubtitlesGui::slotVCenter (bool)
{
  updateFont(2);
}

void SubtitlesGui::slotFit (bool bFitForIt)
{
  // here we enable - disable the coordinates if the user wants to
  // fit the box to the text extension.
  m_pEditWidth-> setEnabled(!bFitForIt);
  m_pEditHeight->setEnabled(!bFitForIt);
  updateFont(2);
}

void SubtitlesGui::slotUnderline (bool)
{
  updateFont(2);
}

void SubtitlesGui::slotStrikeout (bool)
{
  updateFont(2);
}

void SubtitlesGui::slotVolumeChanged ( int iVolume )
{
  float fVolume = (float) (100 - iVolume ) / 100.0;
  //  printf ("SubtitlesGui::slotVolumeChanged ( %d->%f )\n", iVolume, fVolume);
  if ( m_pMediaInterface )
    m_pMediaInterface->setVolume ( fVolume );
}

void SubtitlesGui::slotPositionChanged ( int iPosition)
{
  if ( m_pMediaInterface )
    m_pMediaInterface->setPosition ( iPosition );
}

void SubtitlesGui::slotTransparencyChanged ( int iValue )
{
  float fValue = (float)iValue / 255.0;
  QString qsValue;
  qsValue.sprintf ( "%0.2f", fValue );
  m_pEditTransparency->setText ( qsValue );
}

int SubtitlesGui::findString (QStringList &list, QString string)
{
  for (uint t=0;t<list.count();t++)	{
    if (list[t] == string)
      return t;
  }
  return -1;
}

void SubtitlesGui::updateFont(uint iSwitch)
{
  uint t;
  int iIndex;
  // First see what styles are avail ...
  QFontDatabase database;
  QString fontName  = m_pListFonts->text(m_pListFonts->currentItem());
  QString styleName = m_pComboFontStyle->text(m_pComboFontStyle->currentItem());
  int iFontSize     = m_pComboFontSizes->text(m_pComboFontSizes->currentItem()).toInt();

  QSize size = m_pTextEdit->size ( );
  m_pTextEdit->setFixedSize ( size );

  switch (iSwitch)	{
  case 0:	{
    // The fontName has changed, so we need to get the styles avail for this new font.
    QStringList listStyles = database.styles (fontName);
    m_pComboFontStyle->clear();
    m_pComboFontStyle->insertStringList (listStyles);
    iIndex = findString(listStyles, styleName);
    if (iIndex == -1)
      iIndex = 0;
    styleName = m_pComboFontStyle->text(iIndex);
    m_pComboFontStyle->setCurrentItem(iIndex);
  }
  case 1:
    // The style has changed
    m_pComboFontSizes->clear();
    QValueList<int> listSizes = database.pointSizes(fontName);
    if (listSizes.isEmpty())	{
      listSizes = database.smoothSizes(fontName, styleName);
      if (listSizes.isEmpty())	{
	listSizes = database.standardSizes();
      }
    }
    iIndex = 0;
    for (t=0;t<listSizes.count();t++)	{
      m_pComboFontSizes->insertItem (QString ("%1").arg(listSizes[t]));
      if (listSizes[t] == iFontSize)
	iIndex = t;
    }
    m_pComboFontSizes->setCurrentItem (iIndex);
  }
  QString qsText = m_pTextEdit->text();
  int iAlignement;
  iAlignement = Qt::AlignLeft;
  if (m_pButtonCenter->isOn())
    iAlignement =  Qt::AlignHCenter;
  else if (m_pButtonRight->isOn())
    iAlignement = Qt::AlignRight;
  else if (m_pButtonJustify->isOn())
    iAlignement = Qt::AlignJustify;
  
  m_pTextEdit->setText(qsText);
  // and last we update the TextEdit accordingly
  if (m_pButtonVCenter->isOn())
    iAlignement |= Qt::AlignVCenter;
  else
    iAlignement |= Qt::AlignTop;
  m_iAlignement = iAlignement;
  m_pTextEdit->setAlignment ( iAlignement );
  updateButtons ();
  m_pTextEdit->setFont(getFont());
}

QFont &SubtitlesGui::getFont ()
{
  QFontDatabase database;

  QString qsFamily = m_pListFonts->text(m_pListFonts->currentItem());
  QString qsStyle  = m_pComboFontStyle->text(m_pComboFontStyle->currentItem());
  int iPointSize   = m_pComboFontSizes->text(m_pComboFontSizes->currentItem()).toInt();
  m_qfFont =  database.font(qsFamily, qsStyle, iPointSize );
  m_qfFont.setUnderline (m_pButtonUnderline->isOn());
  m_qfFont.setStrikeOut (m_pButtonStrikeout->isOn());

  return m_qfFont;
}

void SubtitlesGui::setBackgroundColor  ( const QColor &newColor )
{
  // Check if the user pressed cancel ...
  if (!newColor.isValid())
    return;
  m_pFrameBackgroundColor->setPaletteBackgroundColor(newColor);
  update();
  m_pTextEdit->setPaletteBackgroundColor   (newColor);
  m_backgroundColor = newColor;
}

void SubtitlesGui::setForegroundColor (QColor &newColor)
{
  m_pFrameFontColor->setPaletteBackgroundColor(newColor);
  m_pTextEdit->setPaletteForegroundColor (newColor);
  m_foregroundColor = newColor;
}

void SubtitlesGui::insertDraggedObject ( QDropEvent *pDropEvent, QImage &theImage )
{
  //  MenuObject *pMenuObject = NULL;
  // The first thing to check is if this drop was initiated in the Toolbar
  if ( pDropEvent->source() && (QString("m_pListViewAllSources") == pDropEvent->source()->name()) ) {
    QFileInfo fileInfo;
    ListViewMedia   *pListViewMedia   = (ListViewMedia *)pDropEvent->source();
    SourceFileEntry *pSourceFileEntry = pListViewMedia->draggingSourceFileEntry();
    SourceFileInfo  *pSourceFileInfo  = pListViewMedia->draggingSourceFileInfo();
    if ( pSourceFileEntry && pSourceFileEntry->bSoundSource )  {	// No adding of a sound source !
      MessageBox::warning (NULL, tr("Can not add."), tr ("This is a sound source.\nI can currently not add this type of source.\n"), QMessageBox::Ok, QMessageBox::NoButton);
      return;
    }
    if ( pSourceFileEntry && pSourceFileEntry->bIsSlideshow )	{
      MessageBox::warning (NULL, tr("Can not add."), tr ("The slideshow is still beeing created.\nI can not add it at this moment.\n"), QMessageBox::Ok, QMessageBox::NoButton);
      return;
    }
    if ( ( ! pSourceFileInfo ) && ( pSourceFileEntry ) ) // Okay here we split between adding one button
      pSourceFileInfo = pSourceFileEntry->listFileInfos[0];
    if ( ! pSourceFileInfo )
      return; // error
    
    QPixmap theBackground;
    releaseSourceFileInfo ();
    // insert the sourceFileInfo ...
    theImage = *pSourceFileInfo->pPreview;
    theImage = theImage.smoothScale ( m_pDragLabel->size(), QImage::ScaleMin );
    theBackground.convertFromImage ( theImage );
    m_pDragLabel->setPixmap ( theBackground );

    m_pSourceFileInfo = pSourceFileInfo;
    fileInfo.setFile ( pSourceFileInfo->qsFileName );
    m_pTabSubtitles->setTabLabel ( m_pTabSubtitles->page ( 0 ), fileInfo.fileName () );
    pListViewMedia->resetDragging();
    initNewSourceFileInfo ();
  }
}

void SubtitlesGui::insertDraggedText (QDropEvent *, QString &theDroppedText )
{
  // theText should hold the name to a movie file ...
  QString theFile = theDroppedText;
  theFile.remove ( "file:" );

  QFileInfo fileInfo ( theFile );
  if ( fileInfo.exists () && m_pDVDAuthor ) {
    SourceFileInfo *pSourceFileInfo;
    QImage  theImage = QImage::fromMimeSource ( "to_vcd.png" );
    QPixmap thePixmap;
    pSourceFileInfo = findSourceFileInfo ( theFile );
    if ( ! pSourceFileInfo ) {
      QStringList listOfMovies;
      listOfMovies.append        ( theFile );
      m_pDVDAuthor->addMovieList ( listOfMovies );
      pSourceFileInfo = findSourceFileInfo ( theFile );
    }
    if ( ! pSourceFileInfo )
      return;

    // clear up the current subtitles ...
    releaseSourceFileInfo ();
    m_pSourceFileInfo = pSourceFileInfo;
    theImage = *m_pSourceFileInfo->pPreview;

    theImage = theImage.smoothScale ( m_pDragLabel->size(), QImage::ScaleMin );
    thePixmap.convertFromImage ( theImage  );
    m_pDragLabel->setPixmap    ( thePixmap );
    // And finally set the tab label and clear the current subtitles ...
    m_pTabSubtitles->setTabLabel ( m_pTabSubtitles->page ( 0 ), fileInfo.fileName () );
    initNewSourceFileInfo ();
  }
}

// returns the SourceFileInfo of the given file name or NULL
SourceFileInfo *SubtitlesGui::findSourceFileInfo ( QString &theFile )
{
  uint t, i;
  SourceFileEntry *pEntry;

  if ( ! m_pDVDAuthor )
    return NULL;

  // Okay we assume a movie file. Now lets check if this file is already in a sourceFileEntry ...
  for ( t=0;t<(uint)m_pDVDAuthor->sourceFileCount ( );t++) {
    pEntry =  m_pDVDAuthor->sourceFileEntry ( t );
    for ( i=0;i<pEntry->listFileInfos.count ( ); i++ ) {
      if ( pEntry->listFileInfos[t]->qsFileName == theFile ) {
	return pEntry->listFileInfos[t];
      }
    }
  }
  return NULL;
}

void SubtitlesGui::releaseSourceFileInfo ()
{
  // this function connects the sourcefileinfo object and the subtitles object.

  // first we create the subtitles locally to have the latest and greatest ...
  if ( m_pSourceFileInfo ) {
    createSubtitles ( );

    if ( m_pSourceFileInfo->pSubtitles )
      delete m_pSourceFileInfo->pSubtitles;
    if ( m_pSubtitles ) {
      QFileInfo fileInfo ( m_pSourceFileInfo->qsFileName );
      m_pSubtitles->qsTempFile = QString ("%1/%2/%3/subtitles.vob").arg (Global::qsTempPath).arg (Global::qsProjectName).arg (fileInfo.baseName ());
    }
    // next we move the local subtitles object into the sourceFileInfo  - object
    m_pSourceFileInfo->pSubtitles = m_pSubtitles;
 

    m_pSubtitles = NULL;
    // Okaye we can release the SourceFileInfo - object.
    m_pSourceFileInfo = NULL;
    // lastly we clear the table entries.
    m_pTableSubtitles->setNumRows ( 0 );
  }
}

Subtitles *SubtitlesGui::getSubtitles ( bool bCreateNew )
{
  if ( bCreateNew ) {
    // We will create a vanilla Subtitles - object
    if ( m_pSubtitles )
      delete m_pSubtitles;
    m_pSubtitles = new Subtitles;
    m_pTableSubtitles->setNumRows ( 0 );
  }
  else // Or the default we create the Subtitles from the table.
    createSubtitles ( );

  return m_pSubtitles;
}

void SubtitlesGui::initNewSourceFileInfo ()
{
  if ( m_pSourceFileInfo &&  m_pSourceFileInfo->pSubtitles && m_pSubtitles ) {
    if (MessageBox::warning (NULL, QObject::tr("What should I keep ?"), 
          QObject::tr ("I detected that there are already Subtitle in the Dialog and in the Source.\n\nShould I delete the Subtitles in the Dialog ?\n"), 
	  QMessageBox::Yes, QMessageBox::No) == QMessageBox::No )
	    return; // Note at this point table and Subtitles-object are in sync
  }

  if ( m_pSubtitles )
    delete m_pSubtitles;
  m_pSubtitles = NULL;

  if ( ! m_pSourceFileInfo )
    return;

  Utils theUtils;
  int iWidth, iHeight;
  iWidth  = theUtils.getWHFromResolution ( m_pSourceFileInfo->qsResolution, true );
  iHeight = theUtils.getWHFromResolution ( m_pSourceFileInfo->qsResolution, false );
  if ( ! iWidth )
    iWidth = 720;
  if ( ! iHeight ) 
    iHeight = 480;

  m_pEditX->setText( "0" );
  m_pEditY->setText( "0" );
  m_pEditWidth->setText  ( QString ("%1").arg( iWidth  ) );
  m_pEditHeight->setText ( QString ("%1").arg( iHeight ) );
  m_pEditTransparency->setText ( "0.00" );

  if ( ! m_pSourceFileInfo->pSubtitles ) {
    m_pTableSubtitles->setNumRows ( 0 );
    return;
  }

  m_pSubtitles = m_pSourceFileInfo->pSubtitles;
  QString qsValue;
  int iFontSize = m_pSubtitles->font.pointSize ();
  qsValue.sprintf ("%0.2f", (float)m_pSubtitles->iTransparency / 255.0 );
  m_pEditTransparency->setText ( qsValue );
  m_pSliderTransparency->setValue ( m_pSubtitles->iTransparency );
  m_pFrameBackgroundColor->setPaletteBackgroundColor    ( m_pSubtitles->subColors  [0] );
  m_pFrameFontColor->setPaletteBackgroundColor          ( m_pSubtitles->subColors  [1] );
  m_pTextEdit->setPaletteBackgroundColor                ( m_pSubtitles->subColors  [0] );
  m_pTextEdit->setPaletteForegroundColor                ( m_pSubtitles->subColors  [1] );
  m_pListFonts->setCurrentItem ( m_pListFonts->findItem ( m_pSubtitles->font.family( ) ) );
  if ( iFontSize > 0 )
    m_pComboFontSizes->setCurrentText                   ( QString("%1").arg(iFontSize) );

  createTableEntries ( );
  m_pSubtitles = NULL;

  createSubtitles    ( );
  updateFont ( 2 );
}

void SubtitlesGui::displayRow ( int iRow )
{
  if ( ! m_pTableSubtitles ) 
    return;
  m_pTableSubtitles->ensureCellVisible ( iRow,   1 );
  m_pTableSubtitles->ensureCellVisible ( iRow+9, 1 );
  m_pTableSubtitles->clearSelection    (           );
  m_pTableSubtitles->selectRow         ( iRow      );
}
