/****************************************************************************
** ui.h extension file, included from the uic-generated form implementation.
**
** If you wish to add, delete or rename functions or slots use
** Qt Designer which will update this file, preserving your code. Create an
** init() function in place of a constructor, and a destroy() function in
** place of a destructor.
*****************************************************************************/

#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>

#include <qmessagebox.h>
#include <qapplication.h>

// The number of ticks for the progress bar.
#ifndef TOTAL_PROGRESS
#define TOTAL_PROGRESS 100
#endif

void Configurator::initMe ( QApplication *pApp )
{
	int iRet        = 0;
	bool bState     = false;
	m_pNewProcess   = NULL;
	m_iCurrentStep  = 0; // number of files to compile
	m_iCompileStep  = 0; // which compile step qdvdauthor or plugins or qrender
	m_qtTime.start ( );
	m_iTotalSteps   = getCompileSteps ( );
	progressBarCompile->setTotalSteps ( TOTAL_PROGRESS );

	// For now we only have included propper support for xine-lib
	QString qsLib ( "libxine.so" );
	if ( ! checkLibraryExists ( qsLib ) )
		checkVideoXine->setEnabled ( false );
	// disable VLC support for now.
//	qsLib = QString ("libvlc.so");
//	qsLib = QString ("libvlc.a");
	qsLib = QString ( "NoNoNoVLCForBeta1" );
	if ( ! checkLibraryExists ( qsLib ) )
		checkVideoVLC->setEnabled ( false );
	qsLib = QString ( "mplayer" );
	QString qsTempFile;
	qsTempFile = QString ( "/tmp/%1_out.txt" ).arg ( getlogin ( ) );
	iRet = system ( (const char *)QString ( "which %1 > %2 2>/dev/null").arg(qsLib).arg ( qsTempFile ) );
	QFileInfo fileInfo ( qsTempFile );
	// Okay we can not find it, so we wont bother asking the user ...
	if ( fileInfo.size ( ) < 5 )
		checkVideoMPlayer->setEnabled ( false );

	if ( ! ( checkVideoXine->isEnabled    ( ) ||
	         checkVideoMPlayer->isEnabled ( ) ||
	         checkVideoVLC->isEnabled     ( ) ) )  {
		// Okay did not find any media player installed so we choose MPlayer per default.
		checkVideoMPlayer->setEnabled ( true );
		checkVideoMPlayer->setChecked ( true );
	}
	if ( checkVideoXine->isEnabled    ( ) )
		checkVideoXine->setChecked    ( true );
	if ( checkVideoMPlayer->isEnabled ( ) )
		checkVideoMPlayer->setChecked ( true );
	if ( checkVideoVLC->isEnabled     ( ) )
		checkVideoVLC->setChecked     ( true );

	// Last we set the lineEdits to reflect the current environment variables.
	QString qsInstallDir  ( getenv  (      "PREFIX" ) );
	QString qsSystemPath  ( getenv  ( "SYSTEM_PATH" ) );
	QString qsIncludePath = QString ( QString ( getenv ( "INCLUDEPATH" ) ) + " " + QString ( getenv ( "ADD_INCLUDEDIR" ) ) );
	if  ( ! qsInstallDir.isEmpty ( ) )
		editInstallDir->setText ( qsInstallDir );
	if  ( ! qsSystemPath.isEmpty ( ) )
		editSystemPath->setText ( qsSystemPath );
	else
		editSystemPath->setText ( editInstallDir->text ( ) );

	editQtDir3->setText ( QString( getenv  ( "QTDIR" ) ) );
	if ( getenv ( "QTDIR3" ) )
		editQtDir3->setText ( QString ( getenv ( "QTDIR3" ) ) );
	editQtDir4->setText         ( QString ( getenv ( "QTDIR4" ) ) );
	editLDLibraryPath->setText  ( QString ( getenv ( "LD_LIBRARY_PATH" ) ) );
	editIncludePath->setText    ( QString ( qsIncludePath ) );
	if ( getenv ( "CORES" ) )
		editMakeOptions->setText ( QString ( "-j %1" ).arg ( getenv ( "CORES" ) ) );
	// Here we check if an executable exists already ...
	QFileInfo theFile ( "../bin/qdvdauthor" );
	if ( ( theFile.exists ( ) ) && ( theFile.size ( ) > 1 ) )
		bState = true;
	buttonExecute->setEnabled ( bState );
	if ( bState )  {
		// the next check is to see if we can find kdesu
		if ( findGuiSU ( ).isEmpty ( ) )
			bState = false;
	}
	buttonInstall->setEnabled ( bState );

	connect( pApp, SIGNAL ( aboutToQuit ( ) ), this, SLOT ( slotAboutToQuit ( ) ) );
}

QString Configurator::findGuiSU()
{
	int iRet;
	uint t;
	QString qsReturn;
 	char arraySUs[3][8] = {"kdesu", "xsu", "gnomesu"};
	QString qsFileName;
	qsFileName = QString ( "/tmp/%1_out.txt" ).arg ( getlogin ( ) );
	QFileInfo fileInfo( qsFileName );
	for (t=0;t<3;t++)	{
		// the next check is to see if we can find kdesu
		iRet = system ((const char *)QString ("which %1 > %2 2>/dev/null").arg(arraySUs[t]).arg ( qsFileName ) );
		fileInfo.setFile( qsFileName );
		// Okay we cna not find it, so we wont bother asking the user ...
		if (fileInfo.size() > 4)	{
			qsReturn = QString ("%1").arg(arraySUs[t]);
			return qsReturn;
		}
	}
	return qsReturn;
}

bool Configurator::checkLibraryExists ( QString &libName )
{
	// in a shell script it would look like this :
	// cat /etc/ld.so.conf | while read lib_path
	// do
	//    if [ -e $lib_path/$lib_name ]
	//        found.
	//    fi;
	// done; 
	QFileInfo fileInfo;
	// The standard libraries are not in the ld.so.conf file ?!?!!?
	fileInfo = QFileInfo ( QString ( "/lib/" ) + libName );
	if ( fileInfo.exists ( ) )
		return true;
	fileInfo = QFileInfo ( editQtDir3->text ( ) + QString ( "/lib/" ) + libName );
	if ( fileInfo.exists ( ) )
		return true;
	fileInfo = QFileInfo ( QString ( "/usr/lib/" ) + libName );
	if ( fileInfo.exists ( ) )
		return true;
	fileInfo  = QFileInfo( "/etc/ld.so.conf" );
	if ( fileInfo.exists ( ) )  {
		QFile file( "/etc/ld.so.conf" );
		if ( file.open( IO_ReadOnly ) ) {
			QTextStream stream( &file );
			QString libPath;
			while ( !stream.atEnd ( ) ) {
//printf ("Seraching for <%s> under <%s> total <%s>\n", (const char *)libName, (const char *)libPath, (const char *)QString (libPath + QString("/") + libName));
				libPath = stream.readLine ( );
				fileInfo = QFileInfo ( libPath + QString ( "/" ) + libName );
				if ( fileInfo.exists ( ) )  {
					file.close   ( );
					return true;
				}
			}
		}
		file.close ( );
	}

	return false;
}

void Configurator::slotCompile ( )
{
	QCursor myCursor ( QCursor::WaitCursor );
	int iRet = 0;
	uint t;
	m_iTotalSteps = getCompileSteps  ( );
	tabWidget2->setCurrentPage      ( 2 );
	progressBarCompile->setProgress ( 0 );
	buttonExecute->setEnabled ( false );
	if ( m_pNewProcess )	{
		if (m_pNewProcess->isRunning())
			return;
		else
			delete m_pNewProcess;
	}

	m_pNewProcess   =  new QProcess ( this );
	connect ( m_pNewProcess, SIGNAL ( readyReadStdout ( ) ), this, SLOT ( slotReadFromStdout ( ) ) );
	connect ( m_pNewProcess, SIGNAL ( readyReadStderr ( ) ), this, SLOT ( slotReadFromStderr ( ) ) );
	connect ( m_pNewProcess, SIGNAL ( processExited   ( ) ), this, SLOT ( slotProcessExited  ( ) ) );
	m_iCompileStep = 0; // once we get into slotProcessExited we have to decide what to do next.
	// I.e. 1 == compile qplayer/qslideshow/qdvdauthor
	//      2 == compile plugins/libjhead
	//      3 == compile ffmpeg/qrender ( Qt4 )
	QStringList listEnv;
	QString qsQtDir = editQtDir3->text ( );
	if ( qsQtDir.isEmpty ( ) )
		qsQtDir = getenv ( "QTDIR3" );
	if ( qsQtDir.isEmpty ( ) )
		qsQtDir = getenv ( "QTDIR"  );
	listEnv.append ( QString ( "QTDIR=%1" ).arg ( qsQtDir ) );
	//listEnv.append ( QString ( "PATH=%1/bin" ).arg ( editQtDir->text ( ) ) );
	QString qsPrefix;
	if ( editInstallDir->text  ( ).isEmpty ( ) )
		qsPrefix = QString ( "PREFIX=/usr" );
	else
		qsPrefix = QString ( "PREFIX=%1" ).arg ( editInstallDir->text ( ) );
	listEnv.append ( qsPrefix );

	if ( editSystemPath->text ( ).isEmpty ( ) )  {
		qsPrefix.replace  ( "PREFIX", "SYSTEM_PATH" );
		listEnv.append    ( qsPrefix );
	}
	else
		listEnv.append ( QString ( "SYSTEM_PATH=%1" ).arg ( editSystemPath->text ( ) ) );

	if ( checkDebug->isOn  ( ) )
		listEnv.append ( QString ( "DEBUG_QDVDAUTHOR=debug" ) );

	if ( ! editLDLibraryPath->text ( ).isEmpty ( ) )
		listEnv.append ( QString("LD_LIBRARY_PATH=%1").arg ( editLDLibraryPath->text ( ) ) );
	if ( ! editIncludePath->text ( ).isEmpty ( ) )
		listEnv.append ( QString("ADD_INCLUDEDIR=%1").arg  ( editIncludePath->text   ( ) ) );
	if ( checkVideoXine->isOn    ( ) )
		listEnv.append   ( "WITH_XINE_SUPPORT=1" );
	if ( checkVideoMPlayer->isOn ( ) )
		listEnv.append   ( "WITH_MPLAYER_SUPPORT=1" );
	if ( checkVideoVLC->isOn     ( ) )
		listEnv.append   ( "WITH_VLC_SUPPORT=1" );

	if ( ! checkVideoXine->isOn ( ) && ! checkVideoMPlayer->isOn ( ) && ! checkVideoVLC->isOn ( ) )
		 listEnv.append ( "WITH_MPLAYER_SUPPORT=1" );

	QString qtLib1    ( "libqt-mt.so"  );
	QString qtLib2    ( "libqt.so"     );
	if ( checkLibraryExists ( qtLib1 ) )
		listEnv.append  ( "QT_LIB=qt-mt");
	else if ( checkLibraryExists ( qtLib2 ) )
		listEnv.append  ( "QT_LIB=qt" );

	QString qsPath = getenv ( "PATH" );
	qsPath = "PATH=" + qsQtDir + "/bin/:" + qsPath + "/usr/local/bin/";
	m_qsUsersPath = qsPath;
	listEnv.append ( qsPath );
	// This var will tell the qplayer.pro file to not to create qmake_image_collection ...
	listEnv.append ( "QMAKE_IMAGES=yes" );

	// Here we print the newly added environment variables.
	textOutput->clear ( );
	for ( QStringList::Iterator it = listEnv.begin ( ); it != listEnv.end ( ); ++it )  {
		textOutput->append ( *it + QString ( "\n" ) );
		putenv ( (char *)( (const char *)*it ) );
	}

	// let us set the env of the calling process rather then just
	// create our own environment with only the environment we set.
//	for ( uint t=0; t<listEnv.count ( ); t++ )
//		putenv ( (char *)( (const char *)listEnv [t] ) );

	// qdvdauthor.pro needs those files to physically be there ... Go figure !
	iRet = system ( "touch ../bin/qdvdauthor ../bin/qslideshow ../bin/qplayer ../bin/qrender" );
	// Next we should remove the Makefile's so we build with new media engine - support.
	if ( hasMediaEngineSelectionChanged ( ) )
		iRet = system ( "rm Makefile ../qrender/Makefile ../qdvdauthor/Makefile ../qdvdauthor/qplayer/Makefile ../qdvdauthor/qslideshow/Makefile" );
	m_pNewProcess->setWorkingDirectory (QDir ("../"));

	// Next we create the Makefiles
	iRet = system ( QString ( "cd ../qdvdauthor; %1/bin/qmake qdvdauthor.pro; cd .." ).arg ( qsQtDir ) );
	if ( m_pCheckQPlayer->isChecked ( ) )
		iRet = system ( QString ( "cd ../qdvdauthor/qplayer; %1/bin/qmake qplayer.pro; cd ../.." ).arg ( qsQtDir ) );
	if ( m_pCheckQSlideshow->isChecked ( ) ) 
		iRet = system ( QString ( "cd ../qdvdauthor/qslideshow; %1/bin/qmake qslideshow.pro; cd ../.." ).arg ( qsQtDir ) );
//	if ( ( m_pCheckQRender->isChecked ( ) ) && ( ! m_pCheckLocalFFMpeg->isChecked ( ) ) )
//		iRet = system ( QString ( "cd ../qrender; %1/bin/qmake qrender.pro; cd .." ).arg ( editQtDir3->text ( ) ) );

	// And here we generate the make file and compile the application.
	m_pNewProcess->addArgument ( QString ( "%1/bin/qmake" ).arg ( qsQtDir ) );
	m_pNewProcess->addArgument ( "all.pro" );

	m_pNewProcess->start ( );
	// wait for a second until qmake is done ..
	while ( m_pNewProcess->isRunning ( ) )
		sleep ( 1 );

	m_iCompileStep = 1;
	m_pNewProcess->clearArguments   ( );
	QApplication::setOverrideCursor ( myCursor );

	m_pNewProcess->addArgument   ( QString ( "make" ) );
	if ( ! editMakeOptions->text ( ).isEmpty ( ) )  {
		// Here we need to split the line ...
		QStringList listArgs = QStringList::split ( " ", editMakeOptions->text ( ) );
		for ( t=0; t<listArgs.count ( ); t++ )
			m_pNewProcess->addArgument ( listArgs[t] );
	}

	m_pNewProcess->start ( &listEnv );
	m_qtTime.restart     ( );
}

bool Configurator::hasMediaEngineSelectionChanged()
{
	// Here we check if the selection has changed. Meaning that qplayer/MEDIA_CONFIG.h has changed.
	bool bHasChanged = true;
	bool bMPlayerSupport, bXineSupport, bVLCSupport;
	QString qsLine;
	QString qsFileName;

	qsFileName = QString ("../qdvdauthor/Makefile");
	QFileInfo fileInfo(qsFileName);
	if (!fileInfo.exists())
		return false;

	qsFileName = QString ("../qdvdauthor/qplayer/MEDIA_CONFIG.h");
	QFile file( qsFileName );
	bMPlayerSupport = bXineSupport = bVLCSupport = false;
	// First we pars the config file.
	if (file.exists())	{
		if ( file.open( IO_ReadOnly ) ) {
			bHasChanged = false;
			while ( !file.atEnd() ) {
				file.readLine (qsLine, 1000);
				// parse for MPLAYER_SUPPORT, XINE_SUPPORT, or VLC_SUPPORT
				if (qsLine.find("MPLAYER_SUPPORT") > -1 )
					bMPlayerSupport = true;
				else if (qsLine.find("XINE_SUPPORT") > -1 )
					bXineSupport = true;
				else if (qsLine.find("VLC_SUPPORT") > -1 )
					bVLCSupport = true;
			}
        }
        file.close();
	}
	// next we determine if the selection has changed.
	if ( bMPlayerSupport != (checkVideoMPlayer->isOn()) )
		bHasChanged = true;
	if ( bXineSupport != (checkVideoXine->isOn()) )
		bHasChanged = true;
	if ( bVLCSupport != (checkVideoVLC->isOn()) )
		bHasChanged = true;
	return bHasChanged;
}

void Configurator::slotReadFromStdout()
{
// Here for now manually but later automagically.
//static int iCounter =0;
//iCounter ++;
//printf ("<%d>\n", iCounter);
//	QString stdOut = QString("%1 > ").arg(iCounter);
//	stdOut += m_pNewProcess->readStdout();
	QString stdOut = m_pNewProcess->readStdout();
	if (stdOut.length() < 5)
		return;
	textOutput->append (stdOut);
	// and here we take care of the progress bar.
	m_iCurrentStep ++;
	if (m_iCurrentStep > m_iTotalSteps)
		m_iCurrentStep = m_iTotalSteps;
	float fProgress = ((float)(m_iCurrentStep) / (float)(m_iTotalSteps) ) * TOTAL_PROGRESS;
	progressBarCompile->setProgress ( (int)fProgress );

	uint iElapsedSeconds = (int) ((float)m_qtTime.elapsed()/1000.0);
	QString qsTimeString ("0 sec");
	if (iElapsedSeconds < 60 )
		qsTimeString = QString ("%1 sec").arg(iElapsedSeconds);
	else	{
		uint iMinutes, iSeconds;
		iMinutes = (uint)(iElapsedSeconds / 60.0);
		iSeconds = iElapsedSeconds - 60*iMinutes;
		qsTimeString.sprintf("%02d:%02d", iMinutes, iSeconds);
	}
	setCaption (tr("Configurator for qdvdautor <%1>").arg(qsTimeString));
}

void Configurator::slotReadFromStderr()
{
	static QColor errorColor = QColor ( 255, 0, 0 );
	QString strError = m_pNewProcess->readStderr ( );
	if ( strError.length ( ) < 2 )
		return;
	// Okay, I don't know why I get all these QSettings errors. Must be in configurator ...
	if (strError.find ("QSettings:") > -1)
		return;

	QColor stdColor = textOutput->color();
	if (strError.lower().find ("error") > -1)
		errorColor = QColor ( 255,   0, 0 );
	else 
		errorColor = QColor ( 220, 220, 0 );
	textOutput->setColor ( errorColor );
	textOutput->append   (   strError );
	textOutput->setColor (   stdColor );
}

void Configurator::slotProcessExited ( )
{
	// At this point we have qdvdauthor / qslideshow / qplayer
	// next are the plugins, libjhead, qrender, and local-ffmpeg
	bool bState = false;
	slotReadFromStdout ( );
	slotReadFromStderr ( );

	QString qsQtDir = getenv ( "QTDIR" );
	if ( getenv ( "QTDIR3" ) )
		qsQtDir = getenv ( "QTDIR3" );
	if ( ! editQtDir3->text ( ).isEmpty ( ) )
		qsQtDir = editQtDir3->text  ( );

	QStringList listEnv;
	QString qsPath = getenv ( "PATH" );
	qsPath = "PATH=" + qsQtDir + "/bin/:.:" + qsPath;
	qsPath = m_qsUsersPath;
	listEnv.append ( qsPath );

	listEnv.append ( QString ( "QTDIR=%1" ).arg ( qsQtDir ) );
	m_pNewProcess->clearArguments ( );
	if ( m_iCompileStep == 1 )  {
		m_iCompileStep = 2;
		if ( m_pCheckLibJHead->isChecked ( ) )  {
			m_pNewProcess->setWorkingDirectory ( QDir ( "../addons" ) );
			m_pNewProcess->addArgument  (    "bash" );
			//m_pNewProcess->addArgument  (      "-c" ); // SuSe32 does not work
			m_pNewProcess->addArgument  ( "make.sh" );
			textOutput->append   ( "Build addons\n" );
			m_pNewProcess->start ( &listEnv );
			return;
		}
	}
	if ( m_iCompileStep == 2 )  {
		m_iCompileStep = 3;
		if ( m_pCheckPlugins->isChecked ( ) )  {
			m_pNewProcess->setWorkingDirectory ( QDir ( "../qdvdauthor/plugins" ) );
			m_pNewProcess->addArgument (    "bash" );
			//m_pNewProcess->addArgument (      "-c" );
			m_pNewProcess->addArgument ( "make.sh" );
			textOutput->append  ( "Build qdvdauthor/plugins\n" );
			m_pNewProcess->start( &listEnv );
			return;
		}
	}

	if ( m_iCompileStep >= 3 )  {
		// Adjust environment to Qt 4.x.
		if ( getenv ( "QTDIR4" ) )
			qsQtDir = getenv ( "QTDIR4" );
		if ( ! editQtDir4->text ( ).isEmpty ( ) )
			qsQtDir = editQtDir4->text  ( );
		listEnv.clear  ( );
		qsPath = m_qsUsersPath;
		qsPath = "PATH=" + qsQtDir + "/bin:" + qsPath.right ( qsPath.length ( ) - 5 );
		QString qsPrefix;
		if ( editInstallDir->text  ( ).isEmpty ( ) )
			qsPrefix = QString ( "PREFIX=/usr" );
		else
			qsPrefix = QString ( "PREFIX=%1" ).arg ( editInstallDir->text ( ) );
		listEnv.append ( qsPrefix );

		if ( editSystemPath->text ( ).isEmpty ( ) )  {
			qsPrefix.replace  ( "PREFIX", "SYSTEM_PATH" );
			listEnv.append    ( qsPrefix );
		}
		else
			listEnv.append ( QString ( "SYSTEM_PATH=%1" ).arg ( editSystemPath->text ( ) ) );

		listEnv.append ( qsPath );
 		listEnv.append ( QString ( "QTDIR=%1" ).arg ( qsQtDir ) );
		if ( m_pCheckLocalFFMpeg->isChecked ( ) )
			listEnv.append ( "STATIC_FFMPEG=1" );
		else
			listEnv.append ( "SYSTEM_FFMPEG=1" );
	}
	if ( m_iCompileStep == 3 )  {
		// qrender will be built as part of the local_=ffmpeg.sh - script.
		m_iCompileStep  = 0;
		m_pNewProcess->setWorkingDirectory ( QDir ( "../qrender" ) );
		if ( m_pCheckQRender->isChecked ( ) && m_pCheckLocalFFMpeg->isChecked ( ) )  {
			m_pNewProcess->addArgument (            "bash" );
			//m_pNewProcess->addArgument (              "-c" );// does not work on SoSE 11.0
			m_pNewProcess->addArgument ( "local_ffmpeg.sh" );
			m_pNewProcess->addArgument ( "-s" );
			textOutput->append   ( "Build static ffmpeg\n" );
			m_pNewProcess->start ( &listEnv );
			return;
		}
	}
	if ( m_iCompileStep == 4 )  {
		m_iCompileStep = 5;
		m_pNewProcess->clearArguments   ( );
		m_pNewProcess->setWorkingDirectory ( QDir ( "../qrender" ) );
		if ( m_pCheckQRender->isChecked ( ) )  {
			textOutput->append   ( "Build qrender\n" );
			m_pNewProcess->addArgument ( QString ( "%1/bin/qmake" ).arg ( qsQtDir ) );
			m_pNewProcess->start ( &listEnv );
			return;
		}
	}
	if ( m_iCompileStep == 5 )  {
		m_iCompileStep = 0;
		m_pNewProcess->clearArguments ( );
		m_pNewProcess->setWorkingDirectory ( QDir ( "../qrender" ) );
		if ( m_pCheckQRender->isChecked ( ) )  {
			m_pNewProcess->addArgument ( "make" );
			m_pNewProcess->start ( &listEnv );
			return;
		}
	}

	progressBarCompile->setProgress ( TOTAL_PROGRESS );
	m_iCurrentStep = 0;
	// And here we check if the executable exists ...
	QFileInfo theFile ( "../bin/qdvdauthor" );
	if ( ( theFile.exists ( ) ) && ( theFile.size ( ) > 1 ) )
		bState = true;
		
	buttonExecute->setEnabled ( bState );
	if ( bState )  {
		QApplication::restoreOverrideCursor ( );

		// the next check is to see if we can find kdesu
		if (findGuiSU ( ).isEmpty ( ) )
			bState = false;
	}
	buttonInstall->setEnabled ( bState );

	// Exactly the same handling of the title as under slotReadFromStdout
	uint iElapsedSeconds = (int) ((float)m_qtTime.elapsed()/1000.0);
	QString qsTimeString ("0 sec");
	if ( iElapsedSeconds < 60 )
		qsTimeString = QString ( "%1 sec" ).arg ( iElapsedSeconds );
	else	{
		uint iMinutes, iSeconds;
		iMinutes = (uint)(iElapsedSeconds / 60.0);
		iSeconds = iElapsedSeconds - 60*iMinutes;
		qsTimeString.sprintf("%02d:%02d", iMinutes, iSeconds);
	}

	setCaption (tr("Configurator for qdvdautor <%1>").arg(qsTimeString));
}

int Configurator::getCompileSteps ()
{
	int iStepCounter, iUIFiles, iHeaderFiles, iObjectHeader ,iExtra;
	QStringList fileList;
	QString     qsPath;
	bool        bFirst;
	// This function checks how many steps the compilation process approximately has.
//	QStringList fileList;
// 	5 *.ui + 2 *.h (object) + .h(normal) - .ui/* -.moc/* -.obj/*
	QStringList listSource, listGenerated;
	// Here we init the directory array
	listSource.append    ( "../qdvdauthor"                 );
	listSource.append    ( "../qdvdauthor/qplayer"         );
	listSource.append    ( "../qdvdauthor/qplayer/engines" );
	listSource.append    ( "../qdvdauthor/qslideshow"      );
	listGenerated.append ( "../qdvdauthor/.ui"             );
	listGenerated.append ( "../qdvdauthor/.moc"            );
	listGenerated.append ( "../qdvdauthor/.obj"            );

	if ( m_pCheckQRender->isChecked ( ) )  {
		listSource.append    ( "../qrender/"     );
        	listGenerated.append ( "../qrender/.ui"  );
		listGenerated.append ( "../qrender/.moc" );
		listGenerated.append ( "../qredner/.obj" );
		// Note: If we compile ffmpeg, we'll be off by a heck-uf-a-lot
	}

	// Add the libjhead dependand stuff
	listSource.append    ( "../addons/jhead/libjhead"      );
        listGenerated.append ( "../addons/jhead/libjhead/.ui"  );
	listGenerated.append ( "../addons/jhead/libjhead/.moc" );
	listGenerated.append ( "../addons/jhead/libjhead/.obj" );	

	listSource.append    ( "../qdvdauthor/plugins/simpledvd"       );
	listGenerated.append ( "../qdvdauthor/plugins/simpledvd/.ui"   );
	listGenerated.append ( "../qdvdauthor/plugins/simpledvd/.moc"  );
	listGenerated.append ( "../qdvdauthor/plugins/simpledvd/.obj"  );

	listSource.append    ( "../qdvdauthor/plugins/complexdvd"      );
	listGenerated.append ( "../qdvdauthor/plugins/complexdvd/.ui"  );
	listGenerated.append ( "../qdvdauthor/plugins/complexdvd/.moc" );
	listGenerated.append ( "../qdvdauthor/plugins/complexdvd/.obj" );

	// Next we change into the source directory
	QDir theDir ("../qdvdauthor");

	iUIFiles = iHeaderFiles = iObjectHeader = iExtra = 0;
	// obtain with : `find . -name "*.h" -exec grep Q_OBJECT {} \; -print | grep -v Q_OBJECT | grep -v "/.ui/" | wc -l`
	iObjectHeader = 83; // 39;
	// obtain through trial and error
	iExtra        = 19;
	// now we get the rest of the information ...
	theDir.setNameFilter("*.ui");
	bFirst = true;
	QStringList::iterator it = listSource.begin ( );
	while ( it != listSource.end ( ) )  {
		qsPath = *it++;
		theDir.setPath ( qsPath );
		fileList = theDir.entryList();
		iUIFiles += fileList.count();
		if ( bFirst )  {	// the first entry we dont want to change directories
			theDir.setPath("..");
			bFirst = false;
		}
	}
	bFirst    = true;
	iUIFiles *= 5;
	theDir.setNameFilter("*.h");
	it = listSource.begin ( );
	while ( it != listSource.end ( ) )  {
		qsPath = *it++;
		theDir.setPath ( qsPath );
		fileList = theDir.entryList();
		iHeaderFiles += fileList.count();
		if ( bFirst )  { // the first entry we dont want to change directories
			theDir.setPath("..");
			bFirst = false;
		}
	}
	// finally we adjust for object headers count.
	iObjectHeader *= 2;
	// Here we calculate the total steps required
	iStepCounter = iUIFiles + iHeaderFiles + iObjectHeader + iExtra;
//printf ("<%d> = <%d><%d><%d><%d>\n", iStepCounter, iUIFiles, iHeaderFiles, iObjectHeader, iExtra);
	// Next is to take into account if the user disabled some MediaEngines ...
	if (checkVideoXine->isOn())
		 iStepCounter -= 6;
	if (checkVideoMPlayer->isOn())
		 iStepCounter -= 6;
	if (checkVideoVLC->isOn())
		 iStepCounter -= 6;

	theDir.setNameFilter("*");
	it = listGenerated.begin ( );
	while ( it != listGenerated.end ( ) )  {
		qsPath = *it++;
		theDir.setPath  ( qsPath );
		fileList = theDir.entryList();
		iStepCounter -= fileList.count();
		theDir.setPath("..");
	}

	// and then we substract the files / objects already created.
	theDir.setPath ("..");
	// Okay, for now manually until I found a good algol ...
//	iStepCounter = 270;	// MPlayer and Xine support
//	iStepCounter = 276;	// VLC, MPlayer and Xine support
//printf ( "iStepCounter = <%d>\n", iStepCounter );
	return iStepCounter;
}

void Configurator::slotMakeClean()
{
	int iRet = 0;
	tabWidget2->setCurrentPage(2);
	progressBarCompile->setProgress (0);
	buttonExecute->setEnabled( false );
	textOutput->clear();
	if (m_pNewProcess)
		delete m_pNewProcess;

	m_pNewProcess  = new QProcess ( this );
	connect ( m_pNewProcess, SIGNAL ( readyReadStdout ( ) ), this, SLOT ( slotReadFromStdout ( ) ) );
	connect ( m_pNewProcess, SIGNAL ( processExited   ( ) ), this, SLOT ( slotProcessExited  ( ) ) );

	m_pNewProcess->setWorkingDirectory ( QDir ( ".." ) );
	// And here we generate the make file and compile the application.
	m_pNewProcess->addArgument ( QString ( "make"  ) );
	m_pNewProcess->addArgument ( QString ( "clean" ) );
	m_pNewProcess->start ( );
	iRet = system ( "rm ../bin/qdvdautor; rm ../bin/qslideshow; rm ../bin/qplayer; rm ../bin/configurator; rm ../bin/qrender; rm ../bin/core*");
	iRet = system ( "rm ../qdvdauthor/i18n/*.qm ../qdvdauthor/CONFIG.h ../qdvdauthor/qplayer/MEDIA_CONFIG.h 2>&1 > /dev/null" );
	iRet = system ( "../addons/make.sh clean" );
	iRet = system ( "../qdvdauthor/plugins/make.sh clean" );
	buttonExecute->setEnabled( false );
	buttonInstall->setEnabled( false );
}

void Configurator::slotExecute ( )
{
	int iRet = 0;
	iRet = system ( "../bin/qdvdauthor &" );
}

void Configurator::slotInstall ( )
{
	// Due to security risks it is a major problem to generate a GUI to ask for the root password
	// and then execute something with root privileges.
	// 1) The standard command would look like 
	//    su - root -c /tmp/make_install.sh
	//    which does not work because su is asking for the password on the console (tty) rather 
	//    then through stdin.
	// 2) Another solution through the sticky bit I could not figure out unless we start configure 
	//    as root, which would defeat its purpose
	// 3) Tools like expectk etc need extra packages.
	// 4) Generating a new task with a virtual tty device would probably solve the issue, but this 
	//    would baloon this function quite a bit (I guess. Any takers here ?)
	//
	// 5) The way I decided to implement it is to use kdesu if present and otherwise disable the 
	//    install-button.
	//
	/////////////////////////////////////////////////////////////////////////////////////////////////
	uint t;
	bool bCanWriteToInstallDir;
	QString qsPassword, qsQTDir, qsQTDir4;
	QString qsPath = editInstallDir->text ( );
	
	if ( m_pNewProcess )  {
		if ( m_pNewProcess->isRunning ( ) )
			return;
		else
			delete m_pNewProcess;
		m_pNewProcess = NULL;
	}
	bCanWriteToInstallDir = false;
	// First we check if we can write to the chosen directory ...
	QFile file ( editInstallDir->text ( ) + QString ( "/bin/test_file" ) );
	if  ( file.open ( IO_WriteOnly ) )  {
		bCanWriteToInstallDir = true;
		file.close  ( );
		file.remove ( );
	}
	// Here we give the user a hint ...
	QDir theDir ( qsPath );
	
	for ( t=0; t<2; t++ )  {
		if ( ! theDir.exists ( ) )  {
			QMessageBox::warning ( this, "Directory missing.",
				QString ( "Could not find the directory \n%1\n"
					  "Please make sure this directory exists first." ).arg ( qsPath ),
				QMessageBox::Ok, QMessageBox::NoButton );
			return;
		}
		qsPath = editInstallDir->text ( ) + QString ( "/bin" );
		theDir.setPath(qsPath);
	}
	// the next check is to see if we can find kdesu
	QString qsGuiSU = findGuiSU ( );
	if ( qsGuiSU.isEmpty ( ) )
		bCanWriteToInstallDir = true;

	m_iTotalSteps  = 24;
	m_iCurrentStep =  0;
	tabWidget2->setCurrentPage      ( 2 );
	progressBarCompile->setProgress ( 0 );

	m_pNewProcess   =  new QProcess ( this );
	connect ( m_pNewProcess, SIGNAL ( readyReadStdout ( ) ), this, SLOT ( slotReadFromStdout ( ) ) );
	connect ( m_pNewProcess, SIGNAL ( processExited   ( ) ), this, SLOT ( slotProcessExited  ( ) ) );
	QStringList listEnv;

	// Here we print the newly added environment variables.
	// This does not work since we start out in /root after changing to become root to install
//	m_pNewProcess->setWorkingDirectory (QDir ("../qdvdauthor/"));
	// Did not know how to handle this in one line so I create another bash script ...
	qsQTDir = QString ( getenv ( "QTDIR" ) );
	if ( getenv ( "QTDIR3" ) )
		qsQTDir = QString ( getenv ( "QTDIR3" ) );
	if ( qsQTDir.isEmpty ( ) )
	  qsQTDir = searchQTDir ( );
	else
	  qsQTDir = QString ( "export QTDIR=%1\n" ).arg ( qsQTDir );

	if ( getenv ( "QTDIR4" ) )
	  qsQTDir4 = getenv ( "QTDIR4" );
	if ( ! editQtDir4->text ( ).isEmpty ( ) )
	  qsQTDir4 = editQtDir4->text  ( );
	if ( qsQTDir4.isEmpty ( ) )
	  qsQTDir4 = qsQTDir;

	theDir = QDir::current ( );
	theDir.cdUp  ( );
	file.setName ( "/tmp/make_install.sh" );
	if ( file.open ( IO_WriteOnly ) ) {
		QTextStream stream ( &file );
		stream << "#!/bin/sh\n\n";//  << qsQTDir << QString ( "make -C %1 install\n" ).arg ( theDir.absPath ( ) );
		stream << qsQTDir << "\n";
		stream << "cd " << theDir.absPath ( ) << "\n"; // change into the main QDVDAUthor source dir
		stream << "cd qdvdauthor; make install; cd ..\n";
		if ( m_pCheckQPlayer->isChecked   ( ) )
			stream << "cd qdvdauthor/qplayer; make install; cd ../..\n";
		if ( m_pCheckQSlideshow->isChecked( ) )
			stream << "cd qdvdauthor/qslideshow; make install; cd ../..\n";
		if ( m_pCheckLibJHead->isChecked  ( ) )
			stream << "cd addons; ./make.sh install; cd ..\n";
		if ( m_pCheckPlugins->isChecked   ( ) )
			stream << "cd qdvdauthor/plugins; ./make.sh install; cd ../..\n\n";
		stream << "export QTDIR=" << qsQTDir4 << "\n";
		if ( m_pCheckQRender->isChecked   ( ) )
			stream << "cd qrender; make install; cd ..\n";
		file.close ( );
	}
	chmod ( "/tmp/make_install.sh", S_IEXEC | S_IRUSR | S_IWRITE | S_IROTH | S_IXOTH | S_IWOTH );

	if (!bCanWriteToInstallDir)	{
		if ( qsGuiSU == QString ( "kdesu" ) )  {
			m_pNewProcess->addArgument ( "kdesu" );
			m_pNewProcess->addArgument (    "-n" );
			m_pNewProcess->addArgument (    "-t" );
			m_pNewProcess->addArgument (    "-c" );
		}
		else if ( qsGuiSU == QString ( "xsu" ) )   {
			m_pNewProcess->addArgument (        "xsu" );
			m_pNewProcess->addArgument ( "--username" );
			m_pNewProcess->addArgument (       "root" );
			m_pNewProcess->addArgument (  "--message" );
			m_pNewProcess->addArgument ( "Please type in the root password");
			m_pNewProcess->addArgument (  "--command" );
		}
		else if ( qsGuiSU == QString ( "gnomesu" ) )  {
			m_pNewProcess->addArgument (        "xsu" );
			m_pNewProcess->addArgument ( "--username" );
			m_pNewProcess->addArgument (       "root" );
			m_pNewProcess->addArgument (  "--message" );
			m_pNewProcess->addArgument ( "Please type in the root password");
			m_pNewProcess->addArgument (  "--command" );
		}
	}
	m_pNewProcess->addArgument ( "/tmp/make_install.sh" );

	m_pNewProcess->start ( );
}

void Configurator::slotOkay ( )
{
/*	const char *pQtDir = editQtDir->text();
	setenv ("QTDIR", pQtDir, 1);
	if (radioVideoXine->isOn())
		setenv ("VIDEO_LIB", "xine", 1);
	else if (radioVideoMPlayer->isOn())
		setenv ("VIDEO_LIB", "mplayer", 1);
	// And here we generate the make file and compile the application.
	system ("cd ../qdvdauthor; qmake qdvdauthor.pro");
*/
	if ( m_pNewProcess )
        	m_pNewProcess->tryTerminate ( );
	accept ( );
}

void Configurator::slotAboutToQuit()
{
	if (m_pNewProcess)
        	m_pNewProcess->tryTerminate();
}

void Configurator::slotInfoXine()
{
	if (checkVideoXine->isEnabled ())
		QMessageBox::information (NULL, QString ("Xine Library"),
		QString ("This library is installed and should work for all purposes.\n"
			"You can also install and use MPlayer or the VLC libraries\n"
			"and use one of them instead of xine to display the media streams.\n\n"

			"Please note that each media player backend has advantages and disadvantages\n"),
			QMessageBox::Ok ,  QMessageBox::NoButton);
	else
		QMessageBox::warning (NULL, QString ("Xine not installed."),
		QString ("Attention, xine is not installed, thus you \n"
			"should choose MPlayer or VLC instead.\n\n"

			"http://www.xinehq.de\n"),
			QMessageBox::Ok ,  QMessageBox::NoButton);
}

void Configurator::slotInfoMPlayer()
{
	if (checkVideoMPlayer->isEnabled ())
		QMessageBox::information (NULL, QString ("MPLayer executable"),
		QString ("This player is installed and should work for all purposes.\n"
			"You can also install xine-lib or vlc-lib and compile 'Q' DVD-Author\n"
			"to use this library instead.\n\n"),
			QMessageBox::Ok ,  QMessageBox::NoButton);
	else
		QMessageBox::warning (NULL, QString ("MPlayer not installed."),
		QString ("Attention, MPlayer is not installed, thus you \n"
			"should choose xine instead.\n\n"
			
			"http://www.mplayerhq.hu\n"),
			QMessageBox::Ok ,  QMessageBox::NoButton);
}

void Configurator::slotInfoVLC()
{
	if (checkVideoVLC->isEnabled ())
		QMessageBox::information (NULL, QString ("VLC library"),
		QString ("This library is installed and should work for all purposes.\n"
			"You can also install xine-lib or MPlayer and compile 'Q' DVD-Author\n"
			"to use this library instead.\n\n" 
			),
			QMessageBox::Ok ,  QMessageBox::NoButton);
	else
		QMessageBox::warning (NULL, QString ("VLC not installed."),
		QString ("Attention, VLC is not installed, thus you \n"
			"should choose xine instead.\n\n"
			
			"Note: Currently the videolan - project does not release a libvlc.so\n"
			"thus VLC support is currently disabled.\n\n"

			"If VLC is installed please ensure that the path is\n"
			"in /etc/ld.so.conf.\n\n"
			
			"http://www.videolan.orrg\n"),
			QMessageBox::Ok ,  QMessageBox::NoButton);
}

QString Configurator::searchQTDir ()
{
  // This function will create a script to search for the missing QTDIR
  QString qsReturn ("find_qt_dir ()\n"
      "{\n"
      "export QTDIR=$(\n"
      "ls -d1 $1/qt* 2>/dev/null |\n"
      "(while read dir\n"
      "do\n"
      "  if [ -e $dir/bin/moc ];\n"
      "  then\n"
      "    export qtVersion=`$dir/bin/moc -v 2>&1 | awk -F\"(\" '{printf $2}' | awk '{print $2}' | awk -F \")\" '{print $1}' | awk -F. '{printf (\"%.2d%.2d%.2d\", $1, $2, $3);}'`;\n"
      "    if [ $qtVersion -gt 030100 ] && [ $qtVersion -lt 040000 ];\n"
      "    then\n"
      "      echo $dir\n"
      "    fi;\n"
      "    break;\n"
      "  fi;\n"
      "done;\n"
      "))\n"
      "}\n"
      "\n"
      "check_qt_dir ()\n"
      "{\n"
      "if [ -z \"$QTDIR\" ];\n"
      "then\n"
      "  find_qt_dir /usr/lib\n"
      "  if [ -z \"$QTDIR\" ];\n"
      "  then\n"
      "    find_qt_dir /usr/lib64\n"
      "    if [ -z \"$QTDIR\" ];\n"
      "    then\n"
      "      find_qt_dir /usr/local/lib\n"
      "      if [ -z \"$QTDIR\" ];\n"
      "      then\n"
      "        find_qt_dir /usr/local/lib64\n"
      "      fi;\n"
      "    fi;\n"
      "  fi;\n"
      "fi;\n"
      "if [ ! -z \"$QTDIR\" ] \n"
      "then\n"
      "        export PATH=$QTDIR/bin:$PATH\n"
      "        export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$QTDIR/lib\n"
      "fi;\n"
      "}\n"
      "\n"
      "check_qt_dir\n"
      "\n"
      "\n");
  return qsReturn;
}

void Configurator::slotQRender( bool bChecked )
{
	m_pCheckLocalFFMpeg->setEnabled ( bChecked );
	editQtDir4->setEnabled ( bChecked );
}

void Configurator::slotHelpPath()
{
  QMessageBox::information ( NULL, tr ( "Paths" ),
    tr ( "The difference between Prefix, and system path is that prefix defines the dir where the files will be installed and the system path defines the dir where the binary expects the files to be installed.\n"
         "This is important for people who want to create an rpm package in a different directory then the final install place.\n"
         "In general you can leave both paths to be the same.\n\n"),
    QMessageBox::Ok ,  QMessageBox::NoButton );
}

void Configurator::slotPrefixChanged( const QString &qsNewPrefix )
{
  editSystemPath->setText ( qsNewPrefix );
}
