/* * * $Id$ * Copyright (C) 2003 Sebastian Trueg * * This file is part of the K3b project. * Copyright (C) 1998-2007 Sebastian Trueg * * 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. * See the file "COPYING" for the exact licensing terms. */ #include "k3bisoimagewritingdialog.h" #include "k3biso9660imagewritingjob.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include class K3bIsoImageWritingDialog::Private { public: Private() : md5SumItem(0), haveMd5Sum( false ), imageForced( false ) { } K3bListViewItem* md5SumItem; bool haveMd5Sum; TQString lastCheckedFile; bool isIsoImage; bool imageForced; }; K3bIsoImageWritingDialog::K3bIsoImageWritingDialog( TQWidget* parent, const char* name, bool modal ) : K3bInteractionDialog( parent, name, i18n("Burn Iso9660 Image"), i18n("to DVD"), START_BUTTON|CANCEL_BUTTON, START_BUTTON, "DVD image writing", modal ) { d = new Private(); setAcceptDrops(true); setupGui(); m_writerSelectionWidget->setWantedMediumType( K3bDevice::MEDIA_WRITABLE_DVD ); m_writerSelectionWidget->setWantedMediumState( K3bDevice::STATE_EMPTY ); m_writerSelectionWidget->setSupportedWritingApps( K3b::GROWISOFS ); m_writingModeWidget->setSupportedModes( K3b::DAO|K3b::WRITING_MODE_INCR_SEQ|K3b::WRITING_MODE_RES_OVWR ); m_md5Job = new K3bMd5Job( 0, TQT_TQOBJECT(this) ); connect( m_md5Job, TQT_SIGNAL(finished(bool)), this, TQT_SLOT(slotMd5JobFinished(bool)) ); connect( m_md5Job, TQT_SIGNAL(percent(int)), this, TQT_SLOT(slotMd5JobPercent(int)) ); updateImageSize( imagePath() ); connect( m_writerSelectionWidget, TQT_SIGNAL(writerChanged()), this, TQT_SLOT(slotWriterChanged()) ); connect( m_writerSelectionWidget, TQT_SIGNAL(writingAppChanged(int)), this, TQT_SLOT(slotWriterChanged()) ); connect( m_writingModeWidget, TQT_SIGNAL(writingModeChanged(int)), this, TQT_SLOT(slotWriterChanged()) ); connect( m_editImagePath, TQT_SIGNAL(textChanged(const TQString&)), this, TQT_SLOT(updateImageSize(const TQString&)) ); connect( m_checkDummy, TQT_SIGNAL(toggled(bool)), this, TQT_SLOT(slotWriterChanged()) ); } K3bIsoImageWritingDialog::~K3bIsoImageWritingDialog() { delete d; } void K3bIsoImageWritingDialog::init() { if( !d->imageForced ) { // when opening the dialog first the default settings are loaded and afterwards we set the // last written image because that's what most users want KConfig* c = k3bcore->config(); c->setGroup( configGroup() ); TQString image = c->readPathEntry( "last written image" ); if( TQFile::exists( image ) ) m_editImagePath->setURL( image ); } } void K3bIsoImageWritingDialog::setupGui() { TQWidget* frame = mainWidget(); // image // ----------------------------------------------------------------------- TQGroupBox* groupImageUrl = new TQGroupBox( 1, Qt::Horizontal, i18n("Image to Burn"), frame ); m_editImagePath = new KURLRequester( groupImageUrl ); m_editImagePath->setMode( KFile::File|KFile::ExistingOnly ); m_editImagePath->setCaption( i18n("Choose Image File") ); m_editImagePath->setFilter( i18n("*.iso *.ISO|ISO9660 Image Files") + "\n" + i18n("*|All Files") ); connect( m_editImagePath->lineEdit(), TQT_SIGNAL( textChanged ( const TQString & ) ), this, TQT_SLOT( slotWriterChanged() ) ); // image info // ----------------------------------------------------------------------- m_infoView = new K3bListView( frame ); m_infoView->addColumn( "key" ); m_infoView->addColumn( "value" ); m_infoView->header()->hide(); m_infoView->setNoItemText( i18n("No image file selected") ); m_infoView->setSorting( -1 ); m_infoView->setAlternateBackground( TQColor() ); m_infoView->setFullWidth(true); m_infoView->setSelectionMode( TQListView::NoSelection ); connect( m_infoView, TQT_SIGNAL(contextMenu(KListView*, TQListViewItem*, const TQPoint&)), this, TQT_SLOT(slotContextMenu(KListView*, TQListViewItem*, const TQPoint&)) ); m_writerSelectionWidget = new K3bWriterSelectionWidget( frame ); // options // ----------------------------------------------------------------------- TQTabWidget* optionTabbed = new TQTabWidget( frame ); TQWidget* optionTab = new TQWidget( optionTabbed ); TQGridLayout* optionTabLayout = new TQGridLayout( optionTab ); optionTabLayout->setAlignment( TQt::AlignTop ); optionTabLayout->setSpacing( spacingHint() ); optionTabLayout->setMargin( marginHint() ); TQGroupBox* writingModeGroup = new TQGroupBox( 1,Qt::Vertical, i18n("Writing Mode"), optionTab ); writingModeGroup->setInsideMargin( marginHint() ); m_writingModeWidget = new K3bWritingModeWidget( writingModeGroup ); // copies -------- TQGroupBox* groupCopies = new TQGroupBox( 2, Qt::Horizontal, i18n("Copies"), optionTab ); groupCopies->setInsideSpacing( spacingHint() ); groupCopies->setInsideMargin( marginHint() ); TQLabel* pixLabel = new TQLabel( groupCopies ); pixLabel->setPixmap( SmallIcon( "cdcopy", KIcon::SizeMedium ) ); pixLabel->setScaledContents( false ); m_spinCopies = new TQSpinBox( groupCopies ); m_spinCopies->setMinValue( 1 ); m_spinCopies->setMaxValue( 999 ); // -------- copies TQGroupBox* optionGroup = new TQGroupBox( 3,Qt::Vertical, i18n("Settings"), optionTab ); optionGroup->setInsideMargin( marginHint() ); optionGroup->setInsideSpacing( spacingHint() ); m_checkDummy = K3bStdGuiItems::simulateCheckbox( optionGroup ); m_checkVerify = K3bStdGuiItems::verifyCheckBox( optionGroup ); optionTabLayout->addWidget( writingModeGroup, 0, 0 ); optionTabLayout->addWidget( groupCopies, 1, 0 ); optionTabLayout->addMultiCellWidget( optionGroup, 0, 1, 1, 1 ); optionTabLayout->setRowStretch( 1, 1 ); optionTabLayout->setColStretch( 1, 1 ); optionTabbed->addTab( optionTab, i18n("Settings") ); TQGridLayout* grid = new TQGridLayout( frame ); grid->setSpacing( spacingHint() ); grid->setMargin( 0 ); grid->addWidget( groupImageUrl, 0, 0 ); grid->addWidget( m_infoView, 1, 0 ); grid->addWidget( m_writerSelectionWidget, 2, 0 ); grid->addWidget( optionTabbed, 3, 0 ); grid->setRowStretch( 1, 1 ); } void K3bIsoImageWritingDialog::slotStartClicked() { if( !d->isIsoImage ) { if( KMessageBox::warningContinueCancel( this, i18n("The image you selected is not a valid ISO9660 image. " "Are you sure you want to burn it anyway? " "(There may exist other valid image types that are not detected by K3b but " "will work fine.)"), i18n("Burn") ) == KMessageBox::Cancel ) return; } K3bIso9660 isoFs( imagePath() ); if( isoFs.open() ) { if( K3b::imageFilesize( KURL::fromPathOrURL( imagePath() ) ) < (KIO::filesize_t)(isoFs.primaryDescriptor().volumeSpaceSize*2048) ) { if( KMessageBox::questionYesNo( this, i18n("

This image has an invalid file size." "If it has been downloaded make sure the download is complete." "

Only continue if you know what you are doing."), i18n("Warning"), i18n("Continue"), i18n("Cancel") ) == KMessageBox::No ) return; } } m_md5Job->cancel(); // save the path KConfig* c = k3bcore->config(); c->setGroup( configGroup() ); if( c->readPathEntry( "last written image" ).isEmpty() ) c->writePathEntry( "last written image", imagePath() ); // create a progresswidget K3bBurnProgressDialog dlg( kapp->mainWidget(), "burnProgress", true ); // create the job K3bIso9660ImageWritingJob* job = new K3bIso9660ImageWritingJob( &dlg ); job->setBurnDevice( m_writerSelectionWidget->writerDevice() ); job->setSpeed( m_writerSelectionWidget->writerSpeed() ); job->setSimulate( m_checkDummy->isChecked() ); job->setWritingMode( m_writingModeWidget->writingMode() ); job->setVerifyData( m_checkVerify->isChecked() ); job->setCopies( m_checkDummy->isChecked() ? 1 : m_spinCopies->value() ); job->setImagePath( imagePath() ); // HACK (needed since if the medium is forced the stupid K3bIso9660ImageWritingJob defaults to cd writing) job->setWritingApp( K3b::GROWISOFS ); if( !exitLoopOnHide() ) hide(); dlg.startJob( job ); delete job; if( KConfigGroup( k3bcore->config(), "General Options" ).readBoolEntry( "keep action dialogs open", false ) && !exitLoopOnHide() ) show(); else close(); } void K3bIsoImageWritingDialog::updateImageSize( const TQString& path ) { m_md5Job->cancel(); m_infoView->clear(); d->md5SumItem = 0; d->haveMd5Sum = false; d->isIsoImage = false; TQFileInfo info( path ); if( info.isFile() ) { KIO::filesize_t imageSize = K3b::filesize( KURL::fromPathOrURL(path) ); // ------------------------------------------------ // Test for iso9660 image // ------------------------------------------------ K3bIso9660 isoF( path ); if( isoF.open() ) { d->isIsoImage = true; K3bListViewItem* isoRootItem = new K3bListViewItem( m_infoView, m_infoView->lastItem(), i18n("Iso9660 image") ); isoRootItem->setForegroundColor( 0, palette().disabled().foreground() ); isoRootItem->setPixmap( 0, SmallIcon( "cdimage") ); K3bListViewItem* item = new K3bListViewItem( isoRootItem, m_infoView->lastItem(), i18n("Filesize:"), KIO::convertSize( imageSize ) ); item->setForegroundColor( 0, palette().disabled().foreground() ); item = new K3bListViewItem( isoRootItem, m_infoView->lastItem(), i18n("System Id:"), isoF.primaryDescriptor().systemId.isEmpty() ? TQString("-") : isoF.primaryDescriptor().systemId ); item->setForegroundColor( 0, palette().disabled().foreground() ); item = new K3bListViewItem( isoRootItem, m_infoView->lastItem(), i18n("Volume Id:"), isoF.primaryDescriptor().volumeId.isEmpty() ? TQString("-") : isoF.primaryDescriptor().volumeId ); item->setForegroundColor( 0, palette().disabled().foreground() ); item = new K3bListViewItem( isoRootItem, m_infoView->lastItem(), i18n("Volume Set Id:"), isoF.primaryDescriptor().volumeSetId.isEmpty() ? TQString("-") : isoF.primaryDescriptor().volumeSetId ); item->setForegroundColor( 0, palette().disabled().foreground() ); item = new K3bListViewItem( isoRootItem, m_infoView->lastItem(), i18n("Publisher Id:"), isoF.primaryDescriptor().publisherId.isEmpty() ? TQString("-") : isoF.primaryDescriptor().publisherId ); item->setForegroundColor( 0, palette().disabled().foreground() ); item = new K3bListViewItem( isoRootItem, m_infoView->lastItem(), i18n("Preparer Id:"), isoF.primaryDescriptor().preparerId.isEmpty() ? TQString("-") : isoF.primaryDescriptor().preparerId ); item->setForegroundColor( 0, palette().disabled().foreground() ); item = new K3bListViewItem( isoRootItem, m_infoView->lastItem(), i18n("Application Id:"), isoF.primaryDescriptor().applicationId.isEmpty() ? TQString("-") : isoF.primaryDescriptor().applicationId ); item->setForegroundColor( 0, palette().disabled().foreground() ); isoRootItem->setOpen( true ); isoF.close(); } else { K3bListViewItem* item = new K3bListViewItem( m_infoView, m_infoView->lastItem(), i18n("Not an Iso9660 image") ); item->setForegroundColor( 0, TQt::red ); item->setPixmap( 0, SmallIcon( "stop") ); } calculateMd5Sum( path ); } slotWriterChanged(); } void K3bIsoImageWritingDialog::slotWriterChanged() { K3bDevice::Device* dev = m_writerSelectionWidget->writerDevice(); if( dev ) { K3bMedium medium = k3bappcore->mediaCache()->medium( dev ); if( medium.diskInfo().mediaType() & K3bDevice::MEDIA_DVD_PLUS_ALL ) { // no simulation support for DVD+R(W) media m_checkDummy->setChecked(false); m_checkDummy->setEnabled(false); } else { m_checkDummy->setDisabled( false ); } m_writingModeWidget->determineSupportedModesFromMedium( dev ); if( m_checkDummy->isChecked() ) { m_checkVerify->setEnabled( false ); m_checkVerify->setChecked( false ); } else m_checkVerify->setEnabled( true ); m_spinCopies->setEnabled( !m_checkDummy->isChecked() ); } setButtonEnabled( START_BUTTON, dev && !m_editImagePath->lineEdit()->text().isEmpty() ); } void K3bIsoImageWritingDialog::setImage( const KURL& url ) { d->imageForced = true; #if KDE_IS_VERSION(3,4,0) m_editImagePath->setKURL( url ); #else m_editImagePath->setURL( url.path() ); #endif } void K3bIsoImageWritingDialog::calculateMd5Sum( const TQString& file ) { d->haveMd5Sum = false; if( !d->md5SumItem ) d->md5SumItem = new K3bListViewItem( m_infoView, m_infoView->firstChild() ); d->md5SumItem->setText( 0, i18n("Md5 Sum:") ); d->md5SumItem->setForegroundColor( 0, palette().disabled().foreground() ); d->md5SumItem->setProgress( 1, 0 ); d->md5SumItem->setPixmap( 0, SmallIcon( "exec") ); if( file != d->lastCheckedFile ) { d->lastCheckedFile = file; m_md5Job->setFile( file ); m_md5Job->start(); } else slotMd5JobFinished( true ); } void K3bIsoImageWritingDialog::slotMd5JobPercent( int p ) { d->md5SumItem->setProgress( 1, p ); } void K3bIsoImageWritingDialog::slotMd5JobFinished( bool success ) { if( success ) { d->md5SumItem->setText( 1, m_md5Job->hexDigest() ); d->haveMd5Sum = true; } else { d->md5SumItem->setForegroundColor( 1, TQt::red ); if( m_md5Job->hasBeenCanceled() ) d->md5SumItem->setText( 1, i18n("Calculation cancelled") ); else d->md5SumItem->setText( 1, i18n("Calculation failed") ); d->md5SumItem->setPixmap( 0, SmallIcon( "stop") ); d->lastCheckedFile.truncate(0); } d->md5SumItem->setDisplayProgressBar( 1, false ); } void K3bIsoImageWritingDialog::slotContextMenu( KListView*, TQListViewItem*, const TQPoint& pos ) { if( !d->haveMd5Sum ) return; TQPopupMenu popup; int copyItem = popup.insertItem( i18n("Copy checksum to clipboard") ); int compareItem = popup.insertItem( i18n("Compare checksum...") ); int r = popup.exec( pos ); if( r == compareItem ) { bool ok; TQString md5sumToCompare = KInputDialog::getText( i18n("MD5 Sum Check"), i18n("Please insert the MD5 Sum to compare:"), TQString(), &ok, this ); if( ok ) { if( md5sumToCompare.lower().utf8() == m_md5Job->hexDigest().lower() ) KMessageBox::information( this, i18n("The MD5 Sum of %1 equals the specified.").arg(imagePath()), i18n("MD5 Sums Equal") ); else KMessageBox::sorry( this, i18n("The MD5 Sum of %1 differs from the specified.").arg(imagePath()), i18n("MD5 Sums Differ") ); } } else if( r == copyItem ) { TQApplication::clipboard()->setText( m_md5Job->hexDigest().lower(), TQClipboard::Clipboard ); } } void K3bIsoImageWritingDialog::loadUserDefaults( KConfigBase* c ) { m_writingModeWidget->loadConfig( c ); m_checkDummy->setChecked( c->readBoolEntry("simulate", false ) ); m_checkVerify->setChecked( c->readBoolEntry( "verify_data", false ) ); m_spinCopies->setValue( c->readNumEntry( "copies", 1 ) ); m_writerSelectionWidget->loadConfig( c ); if( !d->imageForced ) { TQString image = c->readPathEntry( "image path", c->readPathEntry( "last written image" ) ); if( TQFile::exists( image ) ) m_editImagePath->setURL( image ); } } void K3bIsoImageWritingDialog::saveUserDefaults( KConfigBase* c ) { m_writingModeWidget->saveConfig( c ), c->writeEntry( "simulate", m_checkDummy->isChecked() ); c->writeEntry( "verify_data", m_checkVerify->isChecked() ); c->writeEntry( "copies", m_spinCopies->value() ); m_writerSelectionWidget->saveConfig( c ); c->writePathEntry( "image path", imagePath() ); } void K3bIsoImageWritingDialog::loadK3bDefaults() { m_writerSelectionWidget->loadDefaults(); m_writingModeWidget->setWritingMode( K3b::WRITING_MODE_AUTO ); m_checkDummy->setChecked( false ); m_checkVerify->setChecked( false ); m_spinCopies->setValue( 1 ); } TQString K3bIsoImageWritingDialog::imagePath() const { return K3b::convertToLocalUrl( KURL::fromPathOrURL( m_editImagePath->url() ) ).path(); } void K3bIsoImageWritingDialog::dragEnterEvent( TQDragEnterEvent* e ) { e->accept( KURLDrag::canDecode(e) ); } void K3bIsoImageWritingDialog::dropEvent( TQDropEvent* e ) { KURL::List urls; KURLDrag::decode( e, urls ); #if KDE_IS_VERSION(3,4,0) m_editImagePath->setKURL( urls.first() ); #else m_editImagePath->setURL( urls.first().path() ); #endif } #include "k3bisoimagewritingdialog.moc"