/*
    Copyright (C) 2000 - 2001 Kai Heitkamp, kai@kde.org

    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation; either version 2 of the License, or
    (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program; if not, write to the Free Software
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.

 */

#include <ctype.h>
#include <stdlib.h>
#include <string.h>

#include <qlineedit.h>
#include <qpushbutton.h>
#include <qcheckbox.h>
#include <qlabel.h>
#include <qcombobox.h>
#include <qprogressbar.h>
#include <qmultilineedit.h>
#include <qtabwidget.h>
#include <qinputdialog.h>
#include <qfile.h>
#include <qtextstream.h>

#include <kapplication.h>
#include <kurl.h>
#include <kurldrag.h>
#include <kfiledialog.h>
#include <kconfig.h>
#include <kmessagebox.h>
#include <klocale.h>
#include <kdebug.h>

#include "mastercd.h"
#include "mastercd.moc"
#include "imagetype.h"
#include "tracklistviewitem.h"

MasterCD::MasterCD(QWidget *parent, const char *name ) : MasterCD_GUI(parent, name, true) {
	//Reset
	existsSession = false;
	MS_Start = 0;
	MS_End = 0;
	FS_Size = 0;

	//allow drag 'n drop
 	setAcceptDrops( true );

	//Read config
	config = kapp->config();
	config->setGroup( "Config - mastercd" );

	QTabWidget_Data->setCurrentPage( config->readNumEntry( "QTabWidget_Data" ) );

	QCheckBox_BootableCD->setChecked( config->readBoolEntry("QCheckBox_BootableCD") );
	QCheckBox_Multisession->setChecked( config->readBoolEntry("QCheckBox_Multisession") );
	QCheckBox_LeaveImage->setChecked( config->readBoolEntry("QCheckBox_LeaveImage") );
	QCheckBox_ignoresize->setChecked( config->readBoolEntry("QCheckBox_ignoresize") );
	QCheckBox_Simulate->setChecked( config->readBoolEntry("QCheckBox_Simulate") );
	QCheckBox_nofix->setChecked( config->readBoolEntry("QCheckBox_nofix") );
	QCheckBox_EjectCD->setChecked( config->readBoolEntry("QCheckBox_EjectCD") );
	QCheckBox_Force->setChecked( config->readBoolEntry("QCheckBox_Force") );

	QComboBox_CDRWBlanking->setCurrentItem( config->readNumEntry("QComboBox_CDRWBlanking") );
	QComboBox_WriterSpeed->setCurrentItem( config->readNumEntry("QComboBox_WriterSpeed") );

	QLineEdit_VolumeID->setText( config->readEntry( "QLineEdit_VolumeID" ) );
	QLineEdit_Publisher->setText( config->readEntry( "QLineEdit_Publisher" ) );
	QLineEdit_Preparer->setText( config->readEntry( "QLineEdit_Preparer" ) );
	QLineEdit_AppID->setText( config->readEntry( "QLineEdit_AppID" ) );

	if ( QCheckBox_Multisession->isChecked() ){
		QCheckBox_nofix->setChecked( false );
		QCheckBox_nofix->setEnabled( false );
		QTabWidget_Data->setTabEnabled( multisession, true );
	}
	else{
		QTabWidget_Data->setTabEnabled( multisession, false );
	}

	if ( config->readEntry( "QLineEdit_ImageFile" ) == "" ) {
		QLineEdit_ImageFile->setText( "/tmp/cd.iso" );
	}
	else {
		QLineEdit_ImageFile->setText( config->readEntry( "QLineEdit_ImageFile" ) );
	}

	QLineEdit_BootImage->setText( config->readEntry( "QLineEdit_BootImage" ) );

	if ( QLineEdit_BootImage->text() != "" ) {
		QPushButton_BootImage->setEnabled( true );
		QLineEdit_BootImage->setEnabled( true );
		QCheckBox_BootableCD->setChecked( true );
	}
	else {
		QCheckBox_BootableCD->setChecked( false );
	}

	config->setGroup( "Config - mastercd_data" );
	QListBox_SourceDirs->insertStringList( config->readListEntry( "QListBox_SourceDirs" ) );
	QListBox_ExcludeDirs->insertStringList( config->readListEntry( "QListBox_ExcludeDirs" ) );
	QListBox_ExcludeFiles->insertStringList( config->readListEntry( "QListBox_ExcludeFiles" ) );

	//Read Image-Type from config file and display it
	config->setGroup("Image-Type");
	QLabel_ImageType->setText( config->readEntry( "Name" ) );

	//Check for RW-Device
	config->setGroup( "CD-Writer" );
	if ( config->readEntry( "isRW" ) == "false" )
	{
	QComboBox_CDRWBlanking->clear();
	QComboBox_CDRWBlanking->insertItem(i18n( "Non-RW!" ));
	QComboBox_CDRWBlanking->setEnabled( false );
	}

	//Read program paths into public variables
	config->setGroup("Program paths");
	mkisofs = config->readEntry("mkisofs_path");
	cdrecord = config->readEntry("cdrecord_path");
}

MasterCD::~MasterCD(){
	existsSession = false;
	MS_Start = 0;
	MS_End = 0;
	FS_Size = 0;
}

void MasterCD::dragEnterEvent( QDragEnterEvent* event ){
	event->accept( QUrlDrag::canDecode( event ) );
}

void MasterCD::dropEvent( QDropEvent *event ){
	QString tmp;
 	KURL url;
	QStringList files;

	if ( QUrlDrag::decodeLocalFiles( event, files ) ) {
		if ( QTabWidget_Data->currentPageIndex() != 2  ){
	  	for (QStringList::Iterator i=files.begin(); i!=files.end(); ++i){
      	url.setPath( *i );
	      if ( KMimeType::findByURL( url, 0, true )->name() == "inode/directory" ){
					tmp = (*i);
					tmp.append( "/" );
					addItems( tmp, QTabWidget_Data->currentPageIndex() );
				}
			}
		}
	}
}

//'SourceDirs-Button' or 'ExcludeDirs-Button' or 'ExcludeFiles-Button' clicked
void MasterCD::slot_TabWidget_add(){
	if ( QTabWidget_Data->currentPageIndex() != 2  ){
		QString dir = KFileDialog::getExistingDirectory();
		if ( !dir ) return; //If user clicked 'cancel', return
		addItems( dir, QTabWidget_Data->currentPageIndex() );
	}
	else{
		bool ok = false;
		QString file = QInputDialog::getText( i18n( "KOnCD - Set exclude files" ), i18n( "Please enter an exclude file, wildcards are permitted.\nFor example: *.wav , *.x?m , text.* ..." ), QLineEdit::Normal, "*", &ok, this );
		if ( !ok ) return; //If user clicked 'cancel', return
		if ( file.find( "/" ) ){
			KMessageBox::error( 0, i18n("Directories are not allowed.\nPlease enter filenames only."), i18n("KOnCD - Data CD - Error") );
			return;
		}
		addItems( file, QTabWidget_Data->currentPageIndex() );
	}
}

//Add items
void MasterCD::addItems( QString item, int tabIndex ){
	int trackcount = 0;
	int tc0 = QListBox_SourceDirs->count();
	int tc1 = QListBox_ExcludeDirs->count();
	int tc2 = QListBox_ExcludeFiles->count();

	switch ( tabIndex ){
		case 0:	//Source dirs
						do {
							if ( item == QListBox_SourceDirs->text( trackcount ) ){
								KMessageBox::error( 0, i18n("The directory already exists in the tracklist."), i18n("KOnCD - Data CD - Error") );
								return;
							}
						trackcount++;
						}
						while ( trackcount < tc0 );

						QListBox_SourceDirs->insertItem( item );
            break;

		case 1:	//Exclude dirs
						do {
							if ( item == QListBox_ExcludeDirs->text( trackcount ) ){
								KMessageBox::error( 0, i18n("The directory already exists in the tracklist."), i18n("KOnCD - Data CD - Error") );
								return;
							}
						trackcount++;
						}
						while ( trackcount < tc1 );

						item.remove( item.length() -1 , 1 );
						QListBox_ExcludeDirs->insertItem( item );
            break;

		case 2:	//Exclude files
						do {
							if ( item == QListBox_ExcludeFiles->text( trackcount ) ){
								KMessageBox::error( 0, i18n("The file already exists in the filelist."), i18n("KOnCD - Data CD - Error") );
								return;
							}
						trackcount++;
						}
						while ( trackcount < tc2 );

						QListBox_ExcludeFiles->insertItem( item );
            break;
	}
}

//Delete item(s)
void MasterCD::slot_deleteTrack(){
	switch ( QTabWidget_Data->currentPageIndex() ){
		case 0:
						QListBox_SourceDirs->removeItem( QListBox_SourceDirs->currentItem() );
            break;

		case 1:
						QListBox_ExcludeDirs->removeItem( QListBox_ExcludeDirs->currentItem() );
            break;

		case 2:
						QListBox_ExcludeFiles->removeItem( QListBox_ExcludeFiles->currentItem() );
            break;
	}
}

//delete all entrys in current QListBox
void MasterCD::slot_deleteAllTracks(){
	switch ( QTabWidget_Data->currentPageIndex() ){
		case 0:
						QListBox_SourceDirs->clear();
            break;

		case 1:
						QListBox_ExcludeDirs->clear();
            break;

		case 2:
						QListBox_ExcludeFiles->clear();
            break;
	}
}

//'ImageFile-Button' clicked
void MasterCD::slot_setImageFile(){
	QLineEdit_ImageFile->setText( KFileDialog::getSaveFileName() );
}

//'BootImage-Button' clicked
void MasterCD::slot_setBootImage(){
	QLineEdit_BootImage->setText( KFileDialog::getOpenFileName() );
}

//'Image-Type Button' clicked
void MasterCD::slot_imageType(){
	ImageType *sdlg = new ImageType;
	sdlg->show();

	//Read Image-Type from config file and display it
	config->setGroup("Image-Type");
	QLabel_ImageType->setText( config->readEntry( "Name" ) );
}

//'QCheckBox_BootableCD' clicked , toggle BootableCD-QLineEdit and -Button
void MasterCD::slot_toggleBootableCD(){
	QPushButton_BootImage->setEnabled( QCheckBox_BootableCD->isChecked() ? true:false );
	QLineEdit_BootImage->setEnabled( QCheckBox_BootableCD->isChecked() ? true:false );
	QLineEdit_BootImage->setText( "" );
}

//'QCheckBox_Burn on-the-fly' clicked
void MasterCD::slot_toggle_onthefly(){
	QCheckBox_Multisession->setEnabled( QCheckBox_onthefly->isChecked() ? false:true );
	QCheckBox_Multisession->setChecked( false );
	QPushButton_ImageFile->setEnabled( QCheckBox_onthefly->isChecked() ? false:true );
	QLineEdit_ImageFile->setEnabled( QCheckBox_onthefly->isChecked() ? false:true );
	QLineEdit_ImageFile->setText( "" );
	QCheckBox_LeaveImage->setEnabled( QCheckBox_onthefly->isChecked() ? false:true );
	QCheckBox_LeaveImage->setChecked( false );
	QCheckBox_CreateImage->setEnabled( QCheckBox_onthefly->isChecked() ? false:true );
	QCheckBox_CreateImage->setChecked( QCheckBox_onthefly->isChecked() ? false:true );
	QCheckBox_BootableCD->setEnabled( QCheckBox_onthefly->isChecked() ? false:true );
	QCheckBox_BootableCD->setChecked( false );
	QPushButton_BootImage->setEnabled( false );
	QLineEdit_BootImage->setEnabled( false );
	QLineEdit_BootImage->setText( "" );
	if ( ! QCheckBox_nofix->isEnabled() ) QCheckBox_nofix->setEnabled( true );
	if ( ! QListBox_SourceDirs->isEnabled() ) QListBox_SourceDirs->setEnabled( true );
	if ( ! QPushButton_SourceDir->isEnabled() ) QPushButton_SourceDir->setEnabled( true );
	if ( ! QPushButton_DeleteTrack->isEnabled() ) QPushButton_DeleteTrack->setEnabled( true );
}

//'QCheckBox_WriteCD' clicked
void MasterCD::slot_toggleWriteCD(){
	QCheckBox_EjectCD->setEnabled( QCheckBox_WriteCD->isChecked() ? true:false );
	QCheckBox_EjectCD->setChecked( false );
	QCheckBox_nofix->setEnabled( QCheckBox_WriteCD->isChecked() ? true:false );
	QCheckBox_nofix->setChecked( false );
	QCheckBox_Simulate->setEnabled( QCheckBox_WriteCD->isChecked() ? true:false );
	QCheckBox_Simulate->setChecked( false );
	QCheckBox_Force->setEnabled( QCheckBox_WriteCD->isChecked() ? true:false );
	QCheckBox_Force->setChecked( false );
	QCheckBox_ignoresize->setEnabled( QCheckBox_WriteCD->isChecked() ? true:false );
	QCheckBox_ignoresize->setChecked( false );
	QCheckBox_LeaveImage->setChecked( false );
	if ( ! QCheckBox_onthefly->isChecked() ) QCheckBox_LeaveImage->setEnabled( QCheckBox_WriteCD->isChecked() ? true:false );
}

//'QCheckBox_CreateImage' clicked
void MasterCD::slot_toggleCreateImage(){
	QCheckBox_BootableCD->setEnabled( QCheckBox_CreateImage->isChecked() ? true:false );
	QCheckBox_BootableCD->setChecked( false );
	QPushButton_BootImage->setEnabled( false );
	QLineEdit_BootImage->setEnabled( false );
	QLineEdit_BootImage->setText( "" );
	QListBox_SourceDirs->setEnabled( QCheckBox_CreateImage->isChecked() ? true:false );
	QPushButton_SourceDir->setEnabled( QCheckBox_CreateImage->isChecked() ? true:false );
	QPushButton_DeleteTrack->setEnabled( QCheckBox_CreateImage->isChecked() ? true:false );
}

//'QCheckBox_Multisession' clicked
void MasterCD::slot_multisession(){
	QCheckBox_nofix->setEnabled( QCheckBox_Multisession->isChecked() ? false:true );
	QTabWidget_Data->setTabEnabled( multisession, QCheckBox_Multisession->isChecked() ? true:false );
	if ( QCheckBox_nofix->isChecked() ) QCheckBox_nofix->setChecked( false );
}

//'Start-Button' clicked
void MasterCD::slot_start(){
	//Check for QCheckBox_onthefly
	if ( QCheckBox_onthefly->isChecked() ) {
		//Check for SourceDirs,
		if ( QListBox_SourceDirs->count() == 0 ) {
			KMessageBox::error( 0, i18n("Invalid Source Directories."), i18n("KOnCD - Data CD - Error") );
			return;
		}
		//Check QCheckBox_WriteCD
		if ( ! QCheckBox_WriteCD->isChecked() ) {
			KMessageBox::error( 0, i18n("You must enable 'Write CD'!"), i18n("KOnCD - Data CD - Error") );
			return;
		}
		slot_PrintSize();
		return;
	}

	//--CheckBox_CreateImage is true--
	if ( QCheckBox_CreateImage->isChecked() ) {
		//If not valid Source-Dirs specified
		if ( QListBox_SourceDirs->count() == 0 ) {
			KMessageBox::error( 0, i18n("Invalid Source-Directories."), i18n("KOnCD - Data CD - Error") );
			return;
		}
		//If not valid Image-File specified
		if( QLineEdit_ImageFile->text() == "" ) {
			KMessageBox::error( 0, i18n("Invalid Image-File."), i18n("KOnCD - Data CD - Error") );
			return;
		}
		//If QCheckBox_BootableCD enabled and not valid Boot-Image specified
		if( QCheckBox_BootableCD->isChecked() && QLineEdit_BootImage->text() == "" ) {
			KMessageBox::error( 0, i18n("Invalid Boot-Image."), i18n("KOnCD - Data CD - Error") );
			return;
		}
		//Check for ImageType
		if( QLabel_ImageType->text() == "" ) {
			KMessageBox::error( 0, i18n("Invalid Image-Type."), i18n("KOnCD - Data CD - Error") );
			return;
		}
		//
		if( KListView_toclist->childCount() != 0 && MS_End == 0 ) {
			KMessageBox::error( 0, i18n("You need to select any session to import!\nIf you create a new multisession CD, you don't need to import a session!"), i18n("KOnCD - Data CD - Error") );
			return;
		}

		//Create the CD-Image
		else slot_makeImage();
	}

	//--CheckBox_WriteCD is true--
	if ( QCheckBox_WriteCD->isChecked() && ! QCheckBox_CreateImage->isChecked() ) {
		//If the Imagefile exists, than write the CD
		if ( ! QFile::exists( QLineEdit_ImageFile->text() ) ) {
			KMessageBox::error( 0, i18n("The Imagefile does not exist!"), i18n("KOnCD - Data CD - Error") );
			return;
		}
		//Write the CD
		slot_writeCD();
		}
}

//---Create CD-Image with mkisofs---
void MasterCD::slot_makeImage(){
	kdDebug() << "Last session startsector: " << MS_Start << endl;
	kdDebug() << "New session startsector: " << MS_End << endl;

	if ( existsSession == true ) kdDebug() << "A session is available." << endl;
	if ( existsSession == false ) kdDebug() << "A session isn't available." << endl;

	int trackcount, tc;

	//KProcess arguments
	process.clearArguments();
 	process << mkisofs;

	//Arguments for multisession
	if ( QCheckBox_Multisession->isChecked() && existsSession == true ) {
		char tmp[50];
		QString dev;
		config->setGroup("CD-Writer");
		dev = config->readEntry("SCSI-Target");
		dev = dev.mid( 4, 5 );
		process << "-M" << dev;
		sprintf( tmp, "%d,%d", MS_Start, MS_End );
	 	process << "-C" << tmp;
	}

	//Image-Type
	config->setGroup("Image-Type");
	if ( config->readBoolEntry( "Allowlongfilenames" ) ) process << "-l";
	if ( config->readBoolEntry( "Rockridgeextensions" ) ) process << "-R";
	if ( config->readBoolEntry( "Rockridgewithanonymity" ) ) process << "-r";
	if ( config->readBoolEntry( "Jolietextensions" ) ) process << "-J";
	if ( config->readBoolEntry( "Omittrailingperiods" ) ) process << "-d";
	if ( config->readBoolEntry( "Dontusedeepdirrelocations" ) ) process << "-D";
	if ( config->readBoolEntry( "Allowfilesbeginningwithadot" ) ) process << "-L";
	if ( config->readBoolEntry( "Omitisoversionnumbers" ) ) process << "-N";
	if ( config->readBoolEntry( "Dontincludebackupfiles" ) ) process << "-no-bak";
	if ( config->readBoolEntry( "DontuseRR" ) ) process << "-no-rr";
	if ( config->readBoolEntry( "CreateTRANS_TBLfiles" ) ) process << "-T";
	if ( config->readBoolEntry( "HideRR_MOVEDdir" ) ) process << "-hide-rr-moved";
	if ( config->readBoolEntry( "FollowSymbolicLinks" ) ) process << "-f";
	if ( config->readBoolEntry( "HideTRANS_TBLfiles" ) ) process << "-hide-joliet-trans-tbl";
	if ( config->readBoolEntry( "Untranslatedfiles" ) ) process << "-U";

	//Bootable CD
	if( QCheckBox_BootableCD->isChecked() ) process << "-b" << QLineEdit_BootImage->text() << "-c" << "boot_catalog";

	//CD-Identification
	if( QLineEdit_AppID->text() != "" ) process << "-A" << QLineEdit_AppID->text();
	if( QLineEdit_Publisher->text() != "" ) process << "-P" << QLineEdit_Publisher->text();
	if( QLineEdit_Preparer->text() != "" ) process << "-p" << QLineEdit_Preparer->text();
	if( QLineEdit_VolumeID->text() != "" ) process << "-V" << QLineEdit_VolumeID->text();

	//Image-File
	process << "-o" << QLineEdit_ImageFile->text();

	//Add exclude-files to the process
	if ( QListBox_ExcludeFiles->count() != 0 ) {
		trackcount = 0;
		tc = QListBox_ExcludeFiles->count();
		do {
			process << "-m" << QListBox_ExcludeFiles->text( trackcount );
			trackcount++;
		}
		while ( trackcount < tc );
	}

	//Add exclude-dirs to the process
	if ( QListBox_ExcludeDirs->count() != 0 ) {
		trackcount = 0;
		tc = QListBox_ExcludeDirs->count();
		do {
			process << "-x" << QListBox_ExcludeDirs->text( trackcount );
			trackcount++;
		}
		while ( trackcount < tc );
	}

	//Add the source-dirs to the process
	trackcount = 0;
	tc = QListBox_SourceDirs->count();
	do {
		process << QListBox_SourceDirs->text( trackcount );
		trackcount++;
	}
	while ( trackcount < tc );

	//Connect the Abort-Button from ImgProOut-Dialog to Abort-Handler
	connect( imgprocoutdlg.Button, SIGNAL(clicked()), this, SLOT(abort_handler()));

	//Connect the 'processExited' Signal to the 'slotBurnProcessFinished' Slot
	connect( &process, SIGNAL(processExited(KProcess *)), this, SLOT(slot_makeImageProcessExited(KProcess *)));

	//Connect with slotRecStderr to update KProgress (Write- / Buffer-Status) and StatusLine
	connect( &process, SIGNAL(receivedStdout (KProcess *, char *, int) ), this, SLOT(slot_makeImageStdout(KProcess *, char *, int) ));
	connect( &process, SIGNAL(receivedStderr (KProcess *, char *, int) ), this, SLOT(slot_makeImageStdout(KProcess *, char *, int) ));

	//Start KProcess
	if( ! process.start( KProcess::NotifyOnExit, KProcess::AllOutput ) ){
		KMessageBox::error( 0, i18n("Could not start mkisofs!"), i18n("KOnCD - Data CD - Error") );
		process.disconnect();
		return;
	}

	imgprocoutdlg.StatusLabel -> setText( i18n("Creating CD-Image...") );
	if ( ! imgprocoutdlg.isVisible() ) imgprocoutdlg.show();
}

//---Write CD with cdrecord---
void MasterCD::slot_writeCD(){
	//KProcess argument
	process.clearArguments();
	process << cdrecord << "-v";

	//Set the CD-Writer first
	config->setGroup("CD-Writer");
	process << config->readEntry("SCSI-Target");

	//Set Burn-Proof
	if( config->readBoolEntry("BurnProof") ) process << "driveropts=burnproof";

	//Set CD-Writer Options to KProcess
	if( QCheckBox_EjectCD->isChecked() ) process << "-eject";
	if( QCheckBox_Force->isChecked() ) process << "-force";
	if( QCheckBox_Multisession->isChecked() ) process << "-multi";
	if( QCheckBox_Simulate->isChecked() ) process << "-dummy";
	if( QCheckBox_nofix->isChecked() ) process << "-nofix";
	if( QCheckBox_ignoresize->isChecked() ) process << "-ignsize";

	//Set fifo size
	switch( config->readNumEntry("Fifosize") )
	{
	 	case 0:	process << "fs=4m";
						break;
	 	case 1: process << "fs=8m";
						break;
	 	case 2: process << "fs=12m";
						break;
	 	case 3: process << "fs=16m";
						break;
	 	case 4: process << "fs=20m";
						break;
	 	case 5: process << "fs=24m";
						break;
		case 6: process << "fs=28m";
						break;
		case 7: process << "fs=32m";
						break;
	}

	//Set CD-RW Options to KProcess
	switch( QComboBox_CDRWBlanking->currentItem() )
	{
	 	case 1:	process << "blank=all";
						break;
	 	case 2: process << "blank=fast";
						break;
	 	case 3: process << "blank=track";
						break;
	 	case 4: process << "blank=unreserve";
						break;
	 	case 5: process << "blank=trtrail";
						break;
	 	case 6: process << "blank=unclose";
						break;
		case 7: process << "blank=session";
						break;
	}

	//Set CD-Writer Speed to KProcess
	switch( QComboBox_WriterSpeed -> currentItem() )
	{
   	case 0:	process << "speed=1";
						break;
   	case 1:	process << "speed=2";
						break;
   	case 2:	process << "speed=4";
						break;
   	case 3:	process << "speed=6";
						break;
   	case 4:	process << "speed=8";
						break;
   	case 5:	process << "speed=10";
						break;
   	case 6:	process << "speed=12";
						break;
   	case 7:	process << "speed=16";
						break;
   	case 8:	process << "speed=20";
						break;
   	case 9:	process << "speed=24";
						break;
	}

	//Set the Image
	process << QLineEdit_ImageFile->text();

	//Connect the Abort-Button from ImgProOut-Dialog to Abort-Handler
	connect( procoutdlg.QPushButton_OK, SIGNAL(clicked()), this, SLOT(abort_handler()));

	//Connect the 'processExited' Signal to the 'slotProcessFinished' Slot
	connect( &process, SIGNAL(processExited(KProcess *)), this, SLOT(slot_burnProcessExited(KProcess *)));

	//Connect with slotRecStderr to update KProgress (Write- / Buffer-Status) and StatusLine
	connect( &process, SIGNAL(receivedStdout (KProcess *, char *, int) ), this, SLOT(slot_burnRecStderr (KProcess *, char *, int) ));
	connect( &process, SIGNAL(receivedStderr (KProcess *, char *, int) ), this, SLOT(slot_burnRecStderr (KProcess *, char *, int) ));

	//Start KProcess
	if( ! process.start( KProcess::NotifyOnExit, KProcess::AllOutput ) ){
		KMessageBox::error( 0, i18n("Could not start cdrecord!"), i18n("KOnCD - Data CD - Error") );
		process.disconnect();
		return;
	}

	if ( ! procoutdlg.isVisible() ) procoutdlg.show();
}

//'Calculate-Button' clicked
void MasterCD::slot_calculateSize() {
	//If not valid Source-Dirs specified
	if( QListBox_SourceDirs->count() == 0 ) {
		QLabel_DataSize->setText( "0 MB" );
		return;
	}

	if( calcprocess.isRunning() ) {
		calcprocess.kill();
		QLabel_DataSize->setText( "0 MB" );
		QPushButton_Start->setEnabled( true );
		QPushButton_Quit->setEnabled( true );
		QPushButton_Calculate->setText( i18n( "&Calculate" ) );
		setCaption( i18n( "KOnCD - Data CD" ) );
		return;
	}

	int trackcount, tc;

	QPushButton_Start->setEnabled( false );
	QPushButton_Quit->setEnabled( false );
	QPushButton_Calculate->setText( i18n( "Working..." ) );
	setCaption( i18n( "KOnCD - Data CD: Calculating CD-Image Size" ) );

	//Start KProcess for calculating ISO-Image size with mkisofs
	calcprocess.clearArguments();
 	calcprocess << mkisofs << "-print-size";

	//Follow symbolic links ?
	config->setGroup( "Image-Type" );
	if ( config->readBoolEntry( "FollowSymbolicLinks" ) ) calcprocess << "-f";

	//Add exclude-files to the process
	if ( QListBox_ExcludeFiles->count() != 0 ) {
		trackcount = 0;
		tc = QListBox_ExcludeFiles->count();
		do {
			calcprocess << "-m" << QListBox_ExcludeFiles->text( trackcount );
			trackcount++;
		}
		while ( trackcount < tc );
	}

	//Add exclude-dirs to the process
	if ( QListBox_ExcludeDirs->count() != 0 ) {
		trackcount = 0;
		tc = QListBox_ExcludeDirs->count();
		do {
			calcprocess << "-x" << QListBox_ExcludeDirs->text( trackcount );
			trackcount++;
		}
		while ( trackcount < tc );
	}

	//Add the source-dirs to the process
	trackcount = 0;
	tc = QListBox_SourceDirs->count();
	do {
		calcprocess << QListBox_SourceDirs->text( trackcount );
		trackcount++;
	}
	while ( trackcount < tc );

	QLabel_DataSize->setText( "? MB" );

	//Connect the 'processExited' Signal to the 'slotProcessFinished' Slot
	connect( &calcprocess, SIGNAL(processExited(KProcess *)), this, SLOT(slot_calculateProcessExited(KProcess *)));

	//Connect with all Signals from KProcess to Slot 'slotRecStderr'
	connect( &calcprocess, SIGNAL(receivedStdout (KProcess *, char *, int) ), this, SLOT(slot_calculateRecStderr (KProcess *, char *, int) ));
	connect( &calcprocess, SIGNAL(receivedStderr (KProcess *, char *, int) ), this, SLOT(slot_calculateRecStderr (KProcess *, char *, int) ));

	//Start KProcess
	if( ! calcprocess.start( KProcess::NotifyOnExit, KProcess::AllOutput ) ){
		KMessageBox::error( 0, i18n("Could not start mkisofs!"), i18n("KOnCD - Data CD - Error") );
		calcprocess.disconnect();
		return;
	}
}

//KProcess outout analysis
void MasterCD::slot_calculateRecStderr( KProcess *, char *buffer, int buflen ) {
	char *c, buf[1024];

	if( !buflen ) {
		return;
	}
	memset( buf, 0, sizeof( buf ) );
	strncpy( buf, buffer, buflen > (int) sizeof( buf ) ? sizeof(buf) - 1 : buflen );

	if( strstr( buf, "written =" ) ) {
		if( (c = strrchr( buf, ' ' ) ) ) {

			int s = atoi( c ) * 2 / 1024;

			// debugging
			kdDebug() << "Calculated size: " << atoi( c ) << " extents" << ", complies: " << s << " MB" << endl;

			char tmp[50];
			sprintf( tmp, "%d MB", s );
			QLabel_DataSize->setText( tmp );

			if( s > 650 && s < 730 ) {
				KMessageBox::information( 0, i18n("The CD-Image is now over 650 MB!\n"
																				  "The 'Ignore medium size' option must be enabled\n"
																  				"and use a CD-R 700 or higher!\n"
																					"Note: Your CD writer must support this." ), i18n("KOnCD - Data CD - Info") );
				QCheckBox_ignoresize->setChecked( true );
				return;
			}
			if( s > 800 ) {
				KMessageBox::information( 0, i18n("The CD-Image is now over 800 MB!\n"
   																				"You cannot write that much data to a CD-R!" ), i18n("KOnCD - Data CD - Info") );
				return;
			}

		}
	}
}

//KProcess finished
void MasterCD::slot_calculateProcessExited(KProcess *rcproc) {
	calcprocess.disconnect();

	//Check, if KProcess exited normally...
	if( rcproc->exitStatus() != 0 ) {
		QString statusout;
		statusout.sprintf( I18N_NOOP( "Exit status: %d" ), rcproc->exitStatus() );
		KMessageBox::error( 0, i18n("An error has occurred!"), i18n("KOnCD - Data CD - Error") );
	}

	QPushButton_Start->setEnabled( true );
	QPushButton_Quit->setEnabled( true );
	QPushButton_Calculate->setText(i18n("&Calculate"));
	setCaption( i18n( "KOnCD - Data CD" ) );
}

//---Write CD on-the-fly---
void MasterCD::slot_writeCD_onthefly(){
	char tmp[50];
	int trackcount, tc;

	//Set args for mkisofs
 	shellProcess << mkisofs;

	//Image-Type
	config->setGroup("Image-Type");
	if ( config->readBoolEntry( "Allowlongfilenames" ) ) shellProcess << "-l";
	if ( config->readBoolEntry( "Rockridgeextensions" ) ) shellProcess << "-R";
	if ( config->readBoolEntry( "Rockridgewithanonymity" ) ) shellProcess << "-r";
	if ( config->readBoolEntry( "Jolietextensions" ) ) shellProcess << "-J";
	if ( config->readBoolEntry( "Omittrailingperiods" ) ) shellProcess << "-d";
	if ( config->readBoolEntry( "Dontusedeepdirrelocations" ) ) shellProcess << "-D";
	if ( config->readBoolEntry( "Allowfilesbeginningwithadot" ) ) shellProcess << "-L";
	if ( config->readBoolEntry( "Omitisoversionnumbers" ) ) shellProcess << "-N";
	if ( config->readBoolEntry( "Dontincludebackupfiles" ) ) shellProcess << "-no-bak";
	if ( config->readBoolEntry( "DontuseRR" ) ) shellProcess << "-no-rr";
	if ( config->readBoolEntry( "CreateTRANS_TBLfiles" ) ) shellProcess << "-T";
	if ( config->readBoolEntry( "HideRR_MOVEDdir" ) ) shellProcess << "-hide-rr-moved";
	if ( config->readBoolEntry( "FollowSymbolicLinks" ) ) shellProcess << "-f";
	if ( config->readBoolEntry( "HideTRANS_TBLfiles" ) ) shellProcess << "-hide-joliet-trans-tbl";
	if ( config->readBoolEntry( "Untranslatedfiles" ) ) shellProcess << "-U";

	//Add CD-Identification
	if( QLineEdit_VolumeID->text() != "" ){
		QString volumeid;
		volumeid.append( "-V '" );
		volumeid.append( QLineEdit_VolumeID->text() );
		volumeid.append( "'" );
		shellProcess << volumeid;
	}

	if( QLineEdit_Publisher->text() != "" ){
		QString publisher;
		publisher.append( "-P '" );
		publisher.append( QLineEdit_Publisher->text() );
		publisher.append( "'" );
		shellProcess << publisher;
	}

	if( QLineEdit_Preparer->text() != "" ){
		QString preparer;
		preparer.append( "-p '" );
		preparer.append( QLineEdit_Preparer->text() );
		preparer.append( "'" );
		shellProcess << preparer;
	}

	if( QLineEdit_AppID->text() != "" ){
		QString appid;
		appid.append( "-A '" );
		appid.append( QLineEdit_AppID->text() );
		appid.append( "'" );
		shellProcess << appid;
	}

	//Add exclude-files to the process
	if ( QListBox_ExcludeFiles->count() != 0 ) {
		trackcount = 0;
		tc = QListBox_ExcludeFiles->count();
		do {
			shellProcess << "-m" << QListBox_ExcludeFiles->text( trackcount );
			trackcount++;
		}
		while ( trackcount < tc );
	}

	//Add exclude-dirs to the process
	if ( QListBox_ExcludeDirs->count() != 0 ) {
		trackcount = 0;
		tc = QListBox_ExcludeDirs->count();
		do {
			shellProcess << "-x" << QListBox_ExcludeDirs->text( trackcount );
			trackcount++;
		}
		while ( trackcount < tc );
	}

	//Add the source-dirs to the process
	QString sdirs;
	trackcount = 0;
	tc = QListBox_SourceDirs->count();
	do {
		sdirs.append( "'" );
		sdirs.append( QListBox_SourceDirs->text( trackcount ) );
		sdirs.append( "'" );
		shellProcess << sdirs;
		trackcount++;
	}
	while ( trackcount < tc );

	//For KShellProcess
	shellProcess << "|";

	//Set args for cdrecord
	shellProcess << cdrecord << "-v";

	//Set the CD-Writer first
	config->setGroup("CD-Writer");
	shellProcess << config->readEntry("SCSI-Target");

	//Set Burn-Proof
	if( config->readBoolEntry("BurnProof") ) shellProcess << "driveropts=burnproof";

	//Set CD-Writer Options to KProcess
	if( QCheckBox_EjectCD->isChecked() ) shellProcess << "-eject";
	if( QCheckBox_Force->isChecked() ) shellProcess << "-force";
	if( QCheckBox_Simulate->isChecked() ) shellProcess << "-dummy";
	if( QCheckBox_nofix->isChecked() ) shellProcess << "-nofix";
	if( QCheckBox_ignoresize->isChecked() ) shellProcess << "-ignsize";

	//Set fifo size
	switch( config->readNumEntry("Fifosize") )
	{
	 	case 0:	shellProcess << "fs=4m";
						break;
	 	case 1: shellProcess << "fs=8m";
						break;
	 	case 2: shellProcess << "fs=12m";
						break;
	 	case 3: shellProcess << "fs=16m";
						break;
	 	case 4: shellProcess << "fs=20m";
						break;
	 	case 5: shellProcess << "fs=24m";
						break;
		case 6: shellProcess << "fs=28m";
						break;
		case 7: shellProcess << "fs=32m";
						break;
	}

	//Set CD-RW Options to KProcess
	switch( QComboBox_CDRWBlanking->currentItem() )
	{
	 	case 1:	shellProcess << "blank=all";
						break;
	 	case 2: shellProcess << "blank=fast";
						break;
	 	case 3: shellProcess << "blank=track";
						break;
	 	case 4: shellProcess << "blank=unreserve";
						break;
	 	case 5: shellProcess << "blank=trtrail";
						break;
	 	case 6: shellProcess << "blank=unclose";
						break;
		case 7: shellProcess << "blank=session";
						break;
	}

	//Set CD-Writer Speed to KProcess
	switch( QComboBox_WriterSpeed -> currentItem() )
	{
   	case 0:	shellProcess << "speed=1";
						break;
   	case 1:	shellProcess << "speed=2";
						break;
   	case 2:	shellProcess << "speed=4";
						break;
   	case 3:	shellProcess << "speed=6";
						break;
   	case 4:	shellProcess << "speed=8";
						break;
   	case 5:	shellProcess << "speed=10";
						break;
   	case 6:	shellProcess << "speed=12";
						break;
   	case 7:	shellProcess << "speed=16";
						break;
   	case 8:	shellProcess << "speed=20";
						break;
   	case 9:	shellProcess << "speed=24";
						break;
	}

	//Set filesystem size
	sprintf( tmp, "tsize=%d", FS_Size );
	shellProcess << tmp;

	//Last arg
	shellProcess << "-";

	//Connect the Abort-Button from ImgProOut-Dialog to Abort-Handler
	connect( procoutdlg.QPushButton_OK, SIGNAL(clicked()), this, SLOT(abort_handler()));

	//Connect the 'processExited' Signal to the 'slotProcessFinished' Slot
	connect( &shellProcess, SIGNAL(processExited(KProcess *)), this, SLOT(slot_burnProcessExited(KProcess *)));

	//Connect with slotRecStderr to update KProgress (Write- / Buffer-Status) and StatusLine
	connect( &shellProcess, SIGNAL(receivedStdout (KProcess *, char *, int) ), this, SLOT(slot_burnRecStderr (KProcess *, char *, int) ));
	connect( &shellProcess, SIGNAL(receivedStderr (KProcess *, char *, int) ), this, SLOT(slot_burnRecStderr (KProcess *, char *, int) ));

	//Start KProcess
	if( ! shellProcess.start( KProcess::NotifyOnExit, KProcess::AllOutput ) ){
		KMessageBox::error( 0, i18n("Could not start cdrecord!"), i18n("KOnCD - Data CD - Error") );
		shellProcess.disconnect();
		return;
	}

	procoutdlg.StatusLabel -> setText( i18n("Prepare for write...") );
}

//KProcess outout analysis
void MasterCD::slot_burnRecStderr(KProcess *, char *buffer, int buflen) {
	char *c, buf[1024];
	int wrote, total, load;

	if( !buflen ) {
		return;
	}
	memset( buf, 0, sizeof( buf ) );
	strncpy( buf, buffer, buflen > (int) sizeof( buf ) ? sizeof(buf) - 1 : buflen );

	//Add cdrecord messages to the output window
	procoutdlg.Output->append( buf );
	//Go to the end of the output text
	procoutdlg.Output->setCursorPosition( procoutdlg.Output->length(), 0 );

	//Blanking a CD-RW
	if( strstr( buf, "Blanking" )) {
		procoutdlg.StatusLabel -> setText( i18n("Blanking the CDRW...") );
	}

	//Burn without Fixating
	if( strstr( buf, "Writing  time:" )) {
		procoutdlg.StatusLabel -> setText( i18n("Burn-Process complete.") );
	}

	//Fixating the CD-R
	if( strstr( buf, "Fixating..." )) {
		procoutdlg.StatusLabel -> setText( i18n("Writing TOC...") );
	}

	//	//Burn with Fixating
	if( strstr( buf, "Fixating time:" )) {
		procoutdlg.StatusLabel -> setText( i18n("Burn-Process complete.") );
   	}

	if( strstr( buf, "MB written" )) {
		c = strchr( buf, ':' );
		if( c && *c ) {
			c = strtok( c, ":\r\t " );
			if( c ) {
				wrote = atoi( c );
				c = strtok( NULL, "\r\t " );
				c = strtok( NULL, "\r\t " );
				if( c ) {
					total = atoi( c );
					c = strtok( NULL, "\r" );
					c = strstr( c, "fifo " );
					if( c ) {
						c = strtok( c + 5, "%\r\t " );
						if( c ) {
							load = atoi( c );
							procoutdlg.WriteProgress->setProgress( total ? wrote * 100 / total : 0 );
							procoutdlg.BufferProgress->setProgress( load );

							if( ( total == wrote ) ) {
								procoutdlg.StatusLabel->setText( i18n("Writing TOC...") );
							}

							if( wrote ) {
								if( QCheckBox_Simulate->isChecked() ) {
									procoutdlg.StatusLabel->setText( i18n("Writing CD in dummy mode...") );
								}
								else {
									if ( QCheckBox_Multisession->isChecked() ){
										procoutdlg.StatusLabel->setText( i18n("Writing CD in multi session mode...") );
									}
									else{
										procoutdlg.StatusLabel->setText( i18n("Writing CD in single session mode...") );
									}
								}
							}
						}
					}
				}
			}
		}
	}

}

//KProcess finished
void MasterCD::slot_burnProcessExited(KProcess *rcproc) {
	process.disconnect();

	//Check, if KProcess exited normally...
	if( rcproc->normalExit() ) {
 			if( rcproc->exitStatus() != 0 ) {
				switch ( rcproc->exitStatus() )
				{
					case 13:		procoutdlg.StatusLabel -> setText( i18n( "Error: You don't have enough permissions!" ) );
										break;

					case 19:		procoutdlg.StatusLabel -> setText( i18n( "Error: Can't open SCSI-Driver!" ) );
										break;

					case 254:	procoutdlg.StatusLabel -> setText( i18n( "Error: Corrupt CD in the Writer-Device!" ) );
										break;

					case 255:	procoutdlg.StatusLabel -> setText( i18n( "Error: No CD in the Writer-Device!" ) );
										break;
				}
				QString statusout;
				statusout.sprintf( I18N_NOOP( "Exit status: %d" ), rcproc->exitStatus() );
				KMessageBox::error( 0, I18N_NOOP("An error has occurred!\n" + statusout ), i18n("KOnCD - Data CD - Error") );
				procoutdlg.QPushButton_OK->setText( i18n( "&OK" ) );
				return;
			}
		//If 'Leave Image' CheckBox false, delete the Imagefile
		if ( rcproc->exitStatus() == 0 && ! QCheckBox_LeaveImage->isChecked() && ! QCheckBox_onthefly->isChecked() ) QFile::remove( QLineEdit_ImageFile->text() );
		procoutdlg.QPushButton_OK->setText( i18n( "&OK" ) );
	}
}

//KProcess outout analysis
void MasterCD::slot_makeImageStdout( KProcess *, char *buffer, int buflen ) {
	char *c, buf[1024];

	if( !buflen ) {
		return;
	}
	memset( buf, 0, sizeof( buf ) );
	strncpy( buf, buffer, buflen > (int) sizeof( buf ) ? sizeof(buf) - 1 : buflen );

	//Add cdrecord messages to the output window
	imgprocoutdlg.Output->append( buf );
	//Go to the end of the output text
	imgprocoutdlg.Output->setCursorPosition( imgprocoutdlg.Output->length(), 0 );

	if( strstr( buf, "extents written" ) ) {
		imgprocoutdlg.ImgProgress->setProgress( 100 );
		return;
	}

	if( strstr( buf, "% done" ) ) {
		if( (c = strtok( buf, "%" ) ) ) {
			imgprocoutdlg.ImgProgress->setProgress( atoi( c ) );
		}
	}
}

//KProcess finished
void MasterCD::slot_makeImageProcessExited(KProcess *rcproc) {
	process.disconnect();

	//Check, if KProcess exited normally...
	if( rcproc->normalExit() ) {
 			if( rcproc->exitStatus() != 0 ) {
				if( rcproc->exitStatus() == 13 ) imgprocoutdlg.StatusLabel -> setText( i18n( "Error: You don't have enough permissions!" ) );
				QString statusout;
				statusout.sprintf( I18N_NOOP( "Exit status: %d" ), rcproc->exitStatus() );
				KMessageBox::error( 0, I18N_NOOP("An error has occurred!\n" + statusout), i18n("KOnCD - Data CD - Error") );
				imgprocoutdlg.Button->setText( i18n( "&OK" ) );
				return;
			}
			//If CheckBox 'Write CD' checked, close the dialog and write the CD
			else if ( QCheckBox_WriteCD->isChecked() ){
				imgprocoutdlg.StatusLabel -> setText( i18n("Image creating completed.") );
				//Close ProcessDialog
				imgprocoutdlg.close();
				slot_writeCD();
			}
			else {
				imgprocoutdlg.StatusLabel -> setText( i18n("Image creating completed.") );
				imgprocoutdlg.Button->setText( i18n( "&OK" ) );
			}
	}
}

//KProcess for multisession info
void MasterCD::slot_MSInfo() {
	if ( KListView_toclist->childCount() == 0) return;

	//KProcess arguments
	process.clearArguments();

 	process << cdrecord;

	config->setGroup("CD-Writer");
	process << config->readEntry("SCSI-Target") << "-msinfo";

	//Connect the Abort-Button from ImgProOut-Dialog to Abort-Handler
	connect( imgprocoutdlg.Button, SIGNAL(clicked()), this, SLOT(abort_handler()));

	//Connect the 'processExited' Signal
	connect( &process, SIGNAL(processExited(KProcess *)), this, SLOT( slot_MSInfoExited( KProcess * ) ));

	//Connect with slotRecStderr to update KProgress
	connect( &process, SIGNAL(receivedStdout(KProcess *, char *, int) ), this, SLOT( slot_MSOutput(KProcess *, char *, int ) ));
	connect( &process, SIGNAL(receivedStderr(KProcess *, char *, int) ), this, SLOT( slot_MSOutput(KProcess *, char *, int ) ));

	//Start KProcess
	if(! process.start( KProcess::NotifyOnExit, KProcess::AllOutput ) ){
		KMessageBox::error( 0, i18n("Could not start cdrecord!"), i18n("KOnCD - Data CD - Error") );
		process.disconnect();
		return;
	}

	QPushButton_Start->setEnabled( false );
	QPushButton_Quit->setEnabled( false );
	QPushButton_getMSInfo->setEnabled( false );
	QPushButton_Calculate->setEnabled( false );
	setCaption( i18n( "KOnCD - Data CD - Receiving Multisession Info..." ) );
}

//KProcess Analyse for msinfo output
void MasterCD::slot_MSOutput( KProcess *, char *s, int n ){
	char *c, *b, buf[1024];

	if( !n ) return;

	memset( buf, 0, sizeof( buf ) );
	strncpy( buf, s, n > (int) sizeof( buf ) ? sizeof(buf) - 1 : n );

	//Add cdrecord messages to the output window
	imgprocoutdlg.Output->append( buf );
	//Go to the end of the output text
	imgprocoutdlg.Output->setCursorPosition( imgprocoutdlg.Output->length(), 0 );

	c = strtok( buf, "\n" );
	while( c ) {
  	if( (b = strchr( c, ',' )) && isdigit( *c ) ) {
  		b = strtok( c, ",\n" );
  		if( b ) MS_Start = atoi( b );
  		b = strtok( NULL, ",\n" );
  		if( b ) MS_End = atoi( b );
  	}
		c = strtok( NULL, "\n" );
	}
}

//KProcess 'msinfo' finished
void MasterCD::slot_MSInfoExited(KProcess *rcproc) {
	process.disconnect();

	QPushButton_Start->setEnabled( true );
	QPushButton_Quit->setEnabled( true );
	QPushButton_getMSInfo->setEnabled( true );
	QPushButton_Calculate->setEnabled( true );
	setCaption( i18n( "KOnCD - Data CD" ) );

	if( rcproc->exitStatus() != 0 ) {
		QString statusout;
		statusout.sprintf( I18N_NOOP( "Exit status: %d" ), rcproc->exitStatus() );
		KMessageBox::error( 0, I18N_NOOP("An error has occurred!\n" + statusout), i18n("KOnCD - Data CD - Error") );
		imgprocoutdlg.Button->setText( i18n( "&OK" ) );
		return;
	}

	QString tmp;
	MS_Start = KListView_toclist->selectedItem()->text( 1 ).toInt( 0 );
	QTextLabel_lastsession->setText( KListView_toclist->selectedItem()->text( 1 ) );
	QTextLabel_newsession->setText( tmp.setNum( MS_End ) );
	existsSession = true;
}

//Receive toc infos
void MasterCD::slot_TocInfo(){
	//KProcess arguments
	process.clearArguments();

 	process << cdrecord;

	config->setGroup("CD-Writer");
	process << config->readEntry("SCSI-Target") << "-toc";

	//Connect the Abort-Button from ImgProOut-Dialog to Abort-Handler
	connect( imgprocoutdlg.Button, SIGNAL(clicked()), this, SLOT(abort_handler()));

	//Connect the 'processExited' Signal
	connect( &process, SIGNAL(processExited(KProcess *)), this, SLOT( slot_TocInfoExited( KProcess * ) ));

	//Connect with slotRecStderr to update KProgress
	connect( &process, SIGNAL(receivedStdout(KProcess *, char *, int) ), this, SLOT( slot_TocInfoStdout(KProcess *, char *, int ) ));
	connect( &process, SIGNAL(receivedStderr(KProcess *, char *, int) ), this, SLOT( slot_TocInfoStdout(KProcess *, char *, int ) ));

	//Start KProcess
	if( ! process.start( KProcess::NotifyOnExit, KProcess::AllOutput ) ){
		KMessageBox::error( 0, i18n("Could not start cdrecord!"), i18n("KOnCD - Data CD - Error") );
		process.disconnect();
		return;
	}

	KListView_toclist->clear();
	MS_Start = 0;
	MS_End = 0;
	QPushButton_Start->setEnabled( false );
	QPushButton_Quit->setEnabled( false );
	QPushButton_getMSInfo->setEnabled( false );
	QPushButton_Calculate->setEnabled( false );
	setCaption( i18n( "KOnCD - Data CD - Receiving TOC Info..." ) );
}

//KProcess analysis
void MasterCD::slot_TocInfoStdout( KProcess *, char *buffer, int buflen ){
	char *a, *track[100], buf[1024];
	QString sector[100], length[100], tlength[100], mode[100];
	int size[100], alltracks, count;

	if( !buflen ) {
		return;
	}
	memset( buf, 0, sizeof( buf ) );
	strncpy( buf, buffer, buflen > (int) sizeof( buf ) ? sizeof(buf) - 1 : buflen );

	if( strstr( buf, "Cannot read TOC header" ) ) {
		existsSession = false;
		KMessageBox::information( 0, i18n("There does not seem to be a session on the CD.\nYou cannot import a session!"), i18n("KOnCD - Data CD - Info") );
		return;
	}

	if( strstr( buf, "last" ) ) {
		a = strstr( buf, "last" );
		a = strtok( a, "\n" );
		alltracks = atoi( strchr( a, ' ' ) );
		alltracks++;

		count = 0;
		do {
			track[count] = strstr( buf, "track:" );
			track[count] = strtok( track[count], "\n" );
			count++;
		}
		while ( count < alltracks );

		count = 0;
		do {
			sector[count] = strstr( track[count], "lba:" );
			sector[count] = sector[count].left( sector[count].find( " (" ) );
			sector[count] = sector[count].mid( sector[count].findRev( " " ), sector[count].length() );

			length[count] = strstr( track[count], ")" ) + 2;
			length[count] = length[count].left( length[count].find( " adr:" ) );

			if ( count != 0 ){
				int min, sec, provioustime;
				min = length[count].mid( 0, 2 ).toInt( 0 );
				sec = length[count].mid( 3, 2 ).toInt( 0 );
				provioustime = length[count - 1].mid( 0, 2 ).toInt( 0 ) * 60 + length[count - 1].mid( 3, 2 ).toInt( 0 );
				QTime time( 0, min, sec ), use;
				use = time.addSecs( - provioustime );
				tlength[count] = use.toString();
    	}

			mode[count] = strstr( track[count], "mode:" );

			int bytespersector;
			switch ( mode[count].toInt( 0 ) )
			{
				case -1:	bytespersector = 2352;
									break;
				case 1:		bytespersector = 2324;
									break;
				case 2:		bytespersector = 2048;
									break;
				default:	bytespersector = 2048;
									break;
			}
			if ( count != 0 ) size[count] = ( sector[count].toInt( 0 ) - sector[count - 1].toInt( 0 ) ) * bytespersector / 1048576;

			count++;
		}
		while ( count < alltracks );

		count = 1;
		do {
			new TrackListViewItem( KListView_toclist, count, sector[count - 1], tlength[count], size[count] );
			count++;
		}
		while ( count < alltracks );
	}

}

//KProcess 'TocInfo' finished
void MasterCD::slot_TocInfoExited(KProcess *rcproc){
	process.disconnect();

	QPushButton_Start->setEnabled( true );
	QPushButton_Quit->setEnabled( true );
	QPushButton_getMSInfo->setEnabled( true );
	QPushButton_Calculate->setEnabled( true );
	setCaption( i18n( "KOnCD - Data CD" ) );

	if( rcproc->exitStatus() != 0 ) {
		QString statusout;
		statusout.sprintf( I18N_NOOP( "Exit status: %d" ), rcproc->exitStatus() );
		KMessageBox::error( 0, I18N_NOOP("An error has occurred!\n" + statusout), i18n("KOnCD - Data CD - Error") );
		imgprocoutdlg.Button->setText( i18n( "&OK" ) );
		return;
	}
}

//KProcess for printsize
void MasterCD::slot_PrintSize(){
	int trackcount, tc;

	//KProcess arguments
	process.clearArguments();
 	process << mkisofs << "-print-size";


	//Follow symbolic links ?
	config->setGroup( "Image-Type" );
	if ( config->readBoolEntry( "FollowSymbolicLinks" ) ) process << "-f";

	//Add exclude-files to the process
	if ( QListBox_ExcludeFiles->count() != 0 ) {
		trackcount = 0;
		tc = QListBox_ExcludeFiles->count();
		do {
			process << "-m";
			process << QListBox_ExcludeFiles->text( trackcount );
			trackcount++;
		}
		while ( trackcount < tc );
	}

	//Add exclude-dirs to the process
	if ( QListBox_ExcludeDirs->count() != 0 ) {
		trackcount = 0;
		tc = QListBox_ExcludeDirs->count();
		do {
			process << "-x";
			process << QListBox_ExcludeDirs->text( trackcount );
			trackcount++;
		}
		while ( trackcount < tc );
	}

	//Add the source-dirs to the process
	trackcount = 0;
	tc = QListBox_SourceDirs->count();
	do {
		process << QListBox_SourceDirs->text( trackcount );
		trackcount++;
	}
	while ( trackcount < tc );

	//Connect the Abort-Button from ImgProOut-Dialog to Abort-Handler
	connect( imgprocoutdlg.Button, SIGNAL(clicked()), this, SLOT(abort_handler()));

	//Connect the 'processExited' Signal
	connect( &process, SIGNAL(processExited(KProcess *)), this, SLOT( slot_PrintSizeExited( KProcess * ) ));

	//Connect with slotRecStderr to update KProgress
	connect( &process, SIGNAL(receivedStdout(KProcess *, char *, int) ), this, SLOT( slot_PrintSizeOutput(KProcess *, char *, int ) ));
	connect( &process, SIGNAL(receivedStderr(KProcess *, char *, int) ), this, SLOT( slot_PrintSizeOutput(KProcess *, char *, int ) ));

	//Start KProcess
	if( ! process.start( KProcess::NotifyOnExit, KProcess::AllOutput ) ){
		KMessageBox::error( 0, i18n("Could not start cdrecord!"), i18n("KOnCD - Data CD - Error") );
		process.disconnect();
		return;
	}

	procoutdlg.StatusLabel -> setText( i18n("Retrieve filesystem size...") );
	if ( ! procoutdlg.isVisible() ) procoutdlg.show();
}

//KProcess Analyse for print-size
void MasterCD::slot_PrintSizeOutput( KProcess *, char *s, int n ){
	char *c, buf[1024];

	if( !n ) return;

	memset( buf, 0, sizeof( buf ) );
	strncpy( buf, s, n > (int) sizeof( buf ) ? sizeof(buf) - 1 : n );

	if( strstr( buf, "written =" ) ) {
		if( (c = strrchr( buf, ' ' ) ) ) {
			FS_Size = atoi( c ) * 2048;

			// debugging
			kdDebug() << "FS_Size: " << FS_Size << " extents" << endl;
			kdDebug() << "Data size: " << FS_Size / 1024 << " KB" << endl;
		}
	}
}

//KProcess 'print-size' finished
void MasterCD::slot_PrintSizeExited(KProcess *rcproc) {
	process.disconnect();

	//Check, if KProcess exited normally...
	if( rcproc->exitStatus() != 0 ) {
		QString statusout;
		statusout.sprintf( I18N_NOOP( "Exit status: %d" ), rcproc->exitStatus() );
		KMessageBox::error( 0, I18N_NOOP("An error has occurred!\n" + statusout), i18n("KOnCD - Data CD - Error") );
		procoutdlg.QPushButton_OK->setText( i18n( "&OK" ) );
		return;
	}
	else{
		//Write CD on-the-fly
		slot_writeCD_onthefly();
	}
}

//Abort-Handler
void MasterCD::abort_handler(){
  if ( process.isRunning() ){
    int pid = process.getPid();
    process.kill();
    waitpid( pid, 0, 0 );
  }

  if ( shellProcess.isRunning() ){
    int pid = shellProcess.getPid();
    shellProcess.kill();
    waitpid( pid, 0, 0 );
  }

	imgprocoutdlg.StatusLabel->setText( i18n("Creating CD image...") );
	imgprocoutdlg.Output->setText( "" );
	imgprocoutdlg.ImgProgress->setProgress( 0 );
	if ( imgprocoutdlg.isVisible() ) imgprocoutdlg.close();

	procoutdlg.setCaption( i18n( "KOnCD - Writing CD..." ) );
	procoutdlg.StatusLabel->setText( i18n( "Prepare for write..." ) );
	procoutdlg.Output->setText( "" );
	procoutdlg.WriteProgress->setProgress( 0 );
	procoutdlg.BufferProgress->setProgress( 0 );
	if ( procoutdlg.isVisible() ) procoutdlg.close();

	process.disconnect();
	shellProcess.disconnect();
}

//'Quit-Button' clicked
void MasterCD::slot_quit(){

	//Write config
	config->setGroup( "Config - mastercd" );

	config->writeEntry( "QTabWidget_Data", QTabWidget_Data->currentPageIndex() );

	config->writeEntry( "QCheckBox_BootableCD", QCheckBox_BootableCD->isChecked() );
	config->writeEntry( "QCheckBox_Multisession", QCheckBox_Multisession->isChecked() );
	config->writeEntry( "QCheckBox_LeaveImage", QCheckBox_LeaveImage->isChecked() );
	config->writeEntry( "QCheckBox_ignoresize", QCheckBox_ignoresize->isChecked() );
	config->writeEntry( "QCheckBox_Simulate", QCheckBox_Simulate->isChecked() );
	config->writeEntry( "QCheckBox_nofix", QCheckBox_nofix->isChecked() );
	config->writeEntry( "QCheckBox_EjectCD", QCheckBox_EjectCD->isChecked() );
	config->writeEntry( "QCheckBox_Force", QCheckBox_Force->isChecked() );

	config->writeEntry( "QComboBox_CDRWBlanking", QComboBox_CDRWBlanking->currentItem() );
	config->writeEntry( "QComboBox_WriterSpeed", QComboBox_WriterSpeed->currentItem() );

	config->writeEntry( "QLineEdit_VolumeID", QLineEdit_VolumeID->text() );
	config->writeEntry( "QLineEdit_Publisher", QLineEdit_Publisher->text() );
	config->writeEntry( "QLineEdit_Preparer", QLineEdit_Preparer->text() );
	config->writeEntry( "QLineEdit_AppID", QLineEdit_AppID->text() );

	config->writeEntry( "QLineEdit_ImageFile", QLineEdit_ImageFile->text() );
	config->writeEntry( "QLineEdit_BootImage", QLineEdit_BootImage->text() );

	//set group
	config->setGroup( "Config - mastercd_data" );

	//write all entrys in a QStringList
	trackcount = 0;
	tc = QListBox_SourceDirs->count();
	QStringList sdirs;
	do {
		sdirs.append( QListBox_SourceDirs->text( trackcount ) );
		trackcount++;
	}
	while ( trackcount < tc );

	//write QStringList in configfile
	config->writeEntry( "QListBox_SourceDirs", sdirs );

	//write all entrys in a QStringList
	trackcount = 0;
	tc = QListBox_ExcludeDirs->count();
	QStringList exdirs;
	do {
		exdirs.append( QListBox_ExcludeDirs->text( trackcount ) );
		trackcount++;
	}
	while ( trackcount < tc );

	//write QStringList in configfile
	config->writeEntry( "QListBox_ExcludeDirs", exdirs );

	//write all entrys in a QStringList
	trackcount = 0;
	tc = QListBox_ExcludeFiles->count();
	QStringList exfiles;
	do {
		exfiles.append( QListBox_ExcludeFiles->text( trackcount ) );
		trackcount++;
	}
	while ( trackcount < tc );

	//write QStringList in configfile
	config->writeEntry( "QListBox_ExcludeFiles", exfiles );

	//close MasterCD dialog
	close();
}
