File indexing completed on 2024-04-28 04:50:04

0001 /*
0002     SPDX-FileCopyrightText: 2003-2009 Sebastian Trueg <trueg@k3b.org>
0003     SPDX-FileCopyrightText: 2010 Michal Malek <michalm@jabster.pl>
0004     SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org>
0005 
0006     SPDX-License-Identifier: GPL-2.0-or-later
0007 */
0008 
0009 #include "k3bimagewritingdialog.h"
0010 #include "k3biso9660imagewritingjob.h"
0011 #include "k3bbinimagewritingjob.h"
0012 #include "k3bcuefileparser.h"
0013 #include "k3bclonetocreader.h"
0014 #include "k3baudiocuefilewritingjob.h"
0015 #include "k3bclonejob.h"
0016 #include "k3bmediacache.h"
0017 #include "k3bapplication.h"
0018 
0019 #include <config-k3b.h>
0020 
0021 #include "k3btempdirselectionwidget.h"
0022 #include "k3bdevicemanager.h"
0023 #include "k3bdevice.h"
0024 #include "k3bwriterselectionwidget.h"
0025 #include "k3bburnprogressdialog.h"
0026 #include "k3bstdguiitems.h"
0027 #include "k3bmd5job.h"
0028 #include "k3bdatamodewidget.h"
0029 #include "k3bglobals.h"
0030 #include "k3bwritingmodewidget.h"
0031 #include "k3bcore.h"
0032 #include "k3biso9660.h"
0033 #include "k3btoc.h"
0034 #include "k3btrack.h"
0035 #include "k3bcdtext.h"
0036 
0037 #include <KComboBox>
0038 #include <KConfig>
0039 #include <KSharedConfig>
0040 #include <KColorScheme>
0041 #include <KIconLoader>
0042 #include <KIO/Global>
0043 #include <KLocalizedString>
0044 #include <KMessageBox>
0045 #include <KStandardGuiItem>
0046 #include <KUrlRequester>
0047 #include <kio_version.h>
0048 
0049 #include <QFile>
0050 #include <QFileInfo>
0051 #include <QList>
0052 #include <QMap>
0053 #include <QMimeData>
0054 #include <QUrl>
0055 #include <QClipboard>
0056 #include <QDragEnterEvent>
0057 #include <QDropEvent>
0058 #include <QFont>
0059 #include <QFontMetrics>
0060 #include <QApplication>
0061 #include <QCheckBox>
0062 #include <QInputDialog>
0063 #include <QComboBox>
0064 #include <QGridLayout>
0065 #include <QGroupBox>
0066 #include <QHeaderView>
0067 #include <QLabel>
0068 #include <QLayout>
0069 #include <QMenu>
0070 #include <QProgressBar>
0071 #include <QPushButton>
0072 #include <QSpinBox>
0073 #include <QTabWidget>
0074 #include <QToolTip>
0075 #include <QTreeWidget>
0076 
0077 namespace {
0078 
0079     enum ImageType {
0080         IMAGE_UNKNOWN,
0081         IMAGE_ISO,
0082         IMAGE_CUE_BIN,
0083         IMAGE_AUDIO_CUE,
0084         IMAGE_CDRDAO_TOC,
0085         IMAGE_CDRECORD_CLONE,
0086         IMAGE_RAW
0087     };
0088 
0089 } // namespace
0090 
0091 class K3b::ImageWritingDialog::Private
0092 {
0093 public:
0094     Private()
0095         : md5SumItem(0),
0096           haveMd5Sum( false ),
0097           foundImageType( IMAGE_UNKNOWN ),
0098           imageForced( false ) {
0099     }
0100 
0101     WriterSelectionWidget* writerSelectionWidget;
0102     QCheckBox* checkDummy;
0103     QCheckBox* checkNoFix;
0104     QCheckBox* checkCacheImage;
0105     QCheckBox* checkVerify;
0106     DataModeWidget* dataModeWidget;
0107     WritingModeWidget* writingModeWidget;
0108     QSpinBox* spinCopies;
0109 
0110     KUrlRequester* editImagePath;
0111     KComboBox* comboRecentImages;
0112     QComboBox* comboImageType;
0113 
0114     QTreeWidget* infoView;
0115     TempDirSelectionWidget* tempDirSelectionWidget;
0116 
0117     QTreeWidgetItem* md5SumItem;
0118     QString lastCheckedFile;
0119 
0120     K3b::Md5Job* md5Job;
0121     bool haveMd5Sum;
0122 
0123     ImageType foundImageType;
0124 
0125     QMap<int,int> imageTypeSelectionMap;
0126     QMap<int,int> imageTypeSelectionMapRev;
0127     QString imageFile;
0128     QString tocFile;
0129 
0130     QTabWidget* optionTabbed;
0131 
0132     QWidget* advancedTab;
0133     QWidget* tempPathTab;
0134     bool advancedTabVisible;
0135     bool tempPathTabVisible;
0136 
0137     int advancedTabIndex;
0138     int tempPathTabIndex;
0139 
0140     bool imageForced;
0141 
0142     QColor infoTextColor;
0143     QColor negativeTextColor;
0144     QColor normalTextColor;
0145 
0146     static KIO::filesize_t volumeSpaceSize( const Iso9660& iso );
0147     void createIso9660InfoItems( Iso9660* );
0148     void createCdrecordCloneItems( const QString&, const QString& );
0149     void createCueBinItems( const QString&, const QString& );
0150     void createAudioCueItems( const CueFileParser& cp );
0151     int currentImageType();
0152     QString imagePath() const;
0153 };
0154 
0155 
0156 KIO::filesize_t K3b::ImageWritingDialog::Private::volumeSpaceSize( const Iso9660& isoFs )
0157 {
0158     return static_cast<KIO::filesize_t>( isoFs.primaryDescriptor().volumeSpaceSize*2048 );
0159 }
0160 
0161 
0162 void K3b::ImageWritingDialog::Private::createIso9660InfoItems( K3b::Iso9660* isoF )
0163 {
0164     QTreeWidgetItem* isoRootItem = new QTreeWidgetItem( infoView );
0165     isoRootItem->setText( 0, i18n("Detected:") );
0166     isoRootItem->setText( 1, i18n("ISO 9660 image") );
0167     isoRootItem->setForeground( 0, infoTextColor );
0168     isoRootItem->setIcon( 1, QIcon::fromTheme( "application-x-cd-image") );
0169     isoRootItem->setTextAlignment( 0, Qt::AlignRight );
0170 
0171     const KIO::filesize_t size = K3b::filesize( QUrl::fromLocalFile(isoF->fileName()) );
0172     const KIO::filesize_t volumeSpaceSize = Private::volumeSpaceSize( *isoF );
0173 
0174     QTreeWidgetItem* item = new QTreeWidgetItem( infoView );
0175     item->setText( 0, i18n("Filesize:") );
0176     item->setForeground( 0, infoTextColor );
0177     item->setTextAlignment( 0, Qt::AlignRight );
0178     if( size < volumeSpaceSize ) {
0179         item->setText( 1, i18n("%1 (different than declared volume size)", KIO::convertSize( size )) );
0180         item->setForeground( 1, negativeTextColor );
0181         item->setIcon( 1, QIcon::fromTheme( "dialog-error") );
0182 
0183         item = new QTreeWidgetItem( infoView );
0184         item->setText( 0, i18n("Volume Size:") );
0185         item->setText( 1, KIO::convertSize( volumeSpaceSize ) );
0186         item->setForeground( 0, infoTextColor );
0187         item->setTextAlignment( 0, Qt::AlignRight );
0188     }
0189     else {
0190         item->setText( 1, KIO::convertSize( size ) );
0191     }
0192 
0193     item = new QTreeWidgetItem( infoView );
0194     item->setText( 0, i18n("System Id:") );
0195     item->setText( 1, isoF->primaryDescriptor().systemId.isEmpty()
0196                       ? QString("-")
0197                       : isoF->primaryDescriptor().systemId );
0198     item->setForeground( 0, infoTextColor );
0199     item->setTextAlignment( 0, Qt::AlignRight );
0200 
0201     item = new QTreeWidgetItem( infoView );
0202     item->setText( 0, i18n("Volume Id:") );
0203     item->setText( 1, isoF->primaryDescriptor().volumeId.isEmpty()
0204                       ? QString("-")
0205                       : isoF->primaryDescriptor().volumeId );
0206     item->setForeground( 0, infoTextColor );
0207     item->setTextAlignment( 0, Qt::AlignRight );
0208 
0209     item = new QTreeWidgetItem( infoView );
0210     item->setText( 0, i18n("Volume Set Id:") );
0211     item->setText( 1, isoF->primaryDescriptor().volumeSetId.isEmpty()
0212                                 ? QString("-")
0213                                 : isoF->primaryDescriptor().volumeSetId );
0214     item->setForeground( 0, infoTextColor );
0215     item->setTextAlignment( 0, Qt::AlignRight );
0216 
0217     item = new QTreeWidgetItem( infoView );
0218     item->setText( 0, i18n("Publisher Id:") );
0219     item->setText( 1, isoF->primaryDescriptor().publisherId.isEmpty()
0220                                 ? QString("-")
0221                                 : isoF->primaryDescriptor().publisherId );
0222     item->setForeground( 0, infoTextColor );
0223     item->setTextAlignment( 0, Qt::AlignRight );
0224 
0225     item = new QTreeWidgetItem( infoView );
0226     item->setText( 0, i18n("Preparer Id:") );
0227     item->setText( 1, isoF->primaryDescriptor().preparerId.isEmpty()
0228                                 ? QString("-") : isoF->primaryDescriptor().preparerId );
0229     item->setForeground( 0, infoTextColor );
0230     item->setTextAlignment( 0, Qt::AlignRight );
0231 
0232     item = new QTreeWidgetItem( infoView );
0233     item->setText( 0, i18n("Application Id:") );
0234     item->setText( 1, isoF->primaryDescriptor().applicationId.isEmpty()
0235                       ? QString("-")
0236                       : isoF->primaryDescriptor().applicationId );
0237     item->setForeground( 0, infoTextColor );
0238     item->setTextAlignment( 0, Qt::AlignRight );
0239 }
0240 
0241 
0242 void K3b::ImageWritingDialog::Private::createCdrecordCloneItems( const QString& tocFile, const QString& imageFile )
0243 {
0244     QTreeWidgetItem* isoRootItem = new QTreeWidgetItem( infoView );
0245     isoRootItem->setText( 0, i18n("Detected:") );
0246     isoRootItem->setText( 1, i18n("Cdrecord clone image") );
0247     isoRootItem->setForeground( 0, infoTextColor );
0248     isoRootItem->setIcon( 1, QIcon::fromTheme( "application-x-cd-image") );
0249     isoRootItem->setTextAlignment( 0, Qt::AlignRight );
0250 
0251     QTreeWidgetItem* item = new QTreeWidgetItem( infoView );
0252     item->setText( 0, i18n("Filesize:") );
0253     item->setText( 1, KIO::convertSize( K3b::filesize(QUrl::fromLocalFile(imageFile)) ) );
0254     item->setForeground( 0, infoTextColor );
0255     item->setTextAlignment( 0, Qt::AlignRight );
0256 
0257     item = new QTreeWidgetItem( infoView );
0258     item->setText( 0, i18n("Image file:") );
0259     item->setText( 1, imageFile );
0260     item->setForeground( 0, infoTextColor );
0261     item->setTextAlignment( 0, Qt::AlignRight );
0262 
0263     item = new QTreeWidgetItem( infoView );
0264     item->setText( 0, i18n("TOC file:") );
0265     item->setText( 1, tocFile );
0266     item->setForeground( 0, infoTextColor );
0267     item->setTextAlignment( 0, Qt::AlignRight );
0268 }
0269 
0270 
0271 void K3b::ImageWritingDialog::Private::createCueBinItems( const QString& cueFile, const QString& imageFile )
0272 {
0273     QTreeWidgetItem* isoRootItem = new QTreeWidgetItem( infoView );
0274     isoRootItem->setText( 0, i18n("Detected:") );
0275     isoRootItem->setText( 1, i18n("Cue/bin image") );
0276     isoRootItem->setForeground( 0, infoTextColor );
0277     isoRootItem->setIcon( 1, QIcon::fromTheme( "application-x-cd-image") );
0278     isoRootItem->setTextAlignment( 0, Qt::AlignRight );
0279 
0280     QTreeWidgetItem* item = new QTreeWidgetItem( infoView );
0281     item->setText( 0, i18n("Filesize:") );
0282     item->setText( 1, KIO::convertSize( K3b::filesize(QUrl::fromLocalFile(imageFile)) ) );
0283     item->setForeground( 0, infoTextColor );
0284     item->setTextAlignment( 0, Qt::AlignRight );
0285 
0286     item = new QTreeWidgetItem( infoView );
0287     item->setText( 0, i18n("Image file:") );
0288     item->setText( 1, imageFile );
0289     item->setForeground( 0, infoTextColor );
0290     item->setTextAlignment( 0, Qt::AlignRight );
0291 
0292     item = new QTreeWidgetItem( infoView );
0293     item->setText( 0, i18n("Cue file:") );
0294     item->setText( 1, cueFile );
0295     item->setForeground( 0, infoTextColor );
0296     item->setTextAlignment( 0, Qt::AlignRight );
0297 }
0298 
0299 
0300 void K3b::ImageWritingDialog::Private::createAudioCueItems( const K3b::CueFileParser& cp )
0301 {
0302     QTreeWidgetItem* rootItem = new QTreeWidgetItem( infoView );
0303     rootItem->setText( 0, i18n("Detected:") );
0304     rootItem->setText( 1, i18n("Audio Cue Image") );
0305     rootItem->setForeground( 0, infoTextColor );
0306     rootItem->setIcon( 1, QIcon::fromTheme( "audio-x-generic") );
0307     rootItem->setTextAlignment( 0, Qt::AlignRight );
0308 
0309     QTreeWidgetItem* trackParent = new QTreeWidgetItem( infoView );
0310     trackParent->setText( 0, i18np("One track", "%1 tracks", cp.toc().count() ) );
0311     trackParent->setText( 1, cp.toc().length().toString() );
0312     if( !cp.cdText().isEmpty() ) {
0313         trackParent->setText( 1,
0314                               QString("%1 (%2 - %3)")
0315                               .arg(trackParent->text(1))
0316                               .arg(cp.cdText().performer())
0317                               .arg(cp.cdText().title()) );
0318     }
0319 
0320     int i = 1;
0321     foreach( const K3b::Device::Track& track, cp.toc() ) {
0322 
0323         QTreeWidgetItem* trackItem = new QTreeWidgetItem( trackParent );
0324         trackItem->setText( 0, i18n("Track") + ' ' + QString::number(i).rightJustified( 2, '0' ) );
0325         trackItem->setText( 1, "    " + ( i < cp.toc().count()
0326                                         ? track.length().toString()
0327                                         : QString("??:??:??") ) );
0328 
0329         if( !cp.cdText().isEmpty() && (cp.cdText().count() > 0) &&!cp.cdText()[i-1].isEmpty() )
0330             trackItem->setText( 1,
0331                                 QString("%1 (%2 - %3)")
0332                                 .arg(trackItem->text(1))
0333                                 .arg(cp.cdText()[i-1].performer())
0334                                 .arg(cp.cdText()[i-1].title()) );
0335 
0336         ++i;
0337     }
0338 
0339     trackParent->setExpanded( true );
0340 }
0341 
0342 
0343 int K3b::ImageWritingDialog::Private::currentImageType()
0344 {
0345     if( comboImageType->currentIndex() == 0 )
0346         return foundImageType;
0347     else
0348         return imageTypeSelectionMap[comboImageType->currentIndex()];
0349 }
0350 
0351 
0352 QString K3b::ImageWritingDialog::Private::imagePath() const
0353 {
0354     return K3b::convertToLocalUrl( editImagePath->url() ).toLocalFile();
0355 }
0356 
0357 
0358 K3b::ImageWritingDialog::ImageWritingDialog( QWidget* parent )
0359     : K3b::InteractionDialog( parent,
0360                             i18n("Burn Image"),
0361                             "iso cue toc",
0362                             START_BUTTON|CANCEL_BUTTON,
0363                             START_BUTTON,
0364                             "image writing" ) // config group
0365 {
0366     d = new Private();
0367     const KColorScheme colorScheme( QPalette::Normal, KColorScheme::View );
0368     d->infoTextColor = palette().color( QPalette::Disabled, QPalette::Text );
0369     d->negativeTextColor = colorScheme.foreground( KColorScheme::NegativeText ).color();
0370     d->normalTextColor = colorScheme.foreground( KColorScheme::NormalText ).color();
0371 
0372     setAcceptDrops( true );
0373 
0374     setupGui();
0375 
0376     d->md5Job = new K3b::Md5Job( 0, this );
0377     connect( d->md5Job, SIGNAL(finished(bool)),
0378              this, SLOT(slotMd5JobFinished(bool)) );
0379     connect( d->md5Job, SIGNAL(percent(int)),
0380              this, SLOT(slotMd5JobPercent(int)) );
0381 
0382     connect( d->writerSelectionWidget, SIGNAL(writerChanged()),
0383              this, SLOT(slotToggleAll()) );
0384     connect( d->writerSelectionWidget, SIGNAL(writingAppChanged(K3b::WritingApp)),
0385              this, SLOT(slotToggleAll()) );
0386     connect( d->writerSelectionWidget, SIGNAL(writerChanged(K3b::Device::Device*)),
0387              d->writingModeWidget, SLOT(setDevice(K3b::Device::Device*)) );
0388     connect( d->comboImageType, SIGNAL(activated(int)),
0389              this, SLOT(slotToggleAll()) );
0390     connect( d->writingModeWidget, SIGNAL(writingModeChanged(WritingMode)),
0391              this, SLOT(slotToggleAll()) );
0392     connect( d->editImagePath, SIGNAL(textChanged(QString)),
0393              this, SLOT(slotUpdateImage(QString)) );
0394     connect( d->checkDummy, SIGNAL(toggled(bool)),
0395              this, SLOT(slotToggleAll()) );
0396     connect( d->checkCacheImage, SIGNAL(toggled(bool)),
0397              this, SLOT(slotToggleAll()) );
0398 }
0399 
0400 
0401 K3b::ImageWritingDialog::~ImageWritingDialog()
0402 {
0403     d->md5Job->cancel();
0404 
0405     KConfigGroup c( KSharedConfig::openConfig(), configGroup() );
0406     QStringList recentImages;
0407     // do not store more than 10 recent images
0408     for ( int i = 0; i < d->comboRecentImages->count() && recentImages.count() < 10; ++i ) {
0409         QString image = d->comboRecentImages->itemText( i );
0410         if ( !recentImages.contains( image ) )
0411             recentImages += image;
0412     }
0413     c.writePathEntry( "recent images", recentImages );
0414 
0415     delete d;
0416 }
0417 
0418 
0419 void K3b::ImageWritingDialog::init()
0420 {
0421     KConfigGroup c( KSharedConfig::openConfig(), configGroup() );
0422 
0423     if( !d->imageForced ) {
0424         // when opening the dialog first the default settings are loaded and afterwards we set the
0425         // last written image because that's what most users want
0426         QString image = c.readPathEntry( "last written image", QString() );
0427         if( QFile::exists( image ) )
0428             d->editImagePath->setUrl( QUrl::fromLocalFile( image ) );
0429 
0430         d->comboRecentImages->clear();
0431     }
0432 
0433     d->comboRecentImages->addItems( c.readPathEntry( "recent images", QStringList() ) );
0434 }
0435 
0436 
0437 void K3b::ImageWritingDialog::setupGui()
0438 {
0439     QWidget* frame = K3b::InteractionDialog::mainWidget();
0440 
0441     // image
0442     // -----------------------------------------------------------------------
0443     QGroupBox* groupImageUrl = new QGroupBox( i18n("Image to Burn"), frame );
0444     d->comboRecentImages = new KComboBox( true, this );
0445     d->comboRecentImages->setSizeAdjustPolicy( QComboBox::AdjustToMinimumContentsLengthWithIcon );
0446     d->editImagePath = new KUrlRequester( d->comboRecentImages, groupImageUrl );
0447     d->editImagePath->setMode( KFile::File|KFile::ExistingOnly );
0448     d->editImagePath->setWindowTitle( i18n("Choose Image File") );
0449 #if KIO_VERSION >= QT_VERSION_CHECK(5, 108, 0)
0450     d->editImagePath->setNameFilters({
0451         i18n("Image Files") + " (*.iso *.toc *.ISO *.TOC *.cue *.CUE)",
0452         i18n("ISO 9660 Image Files") + " (*.iso *.ISO)",
0453         i18n("Cue Files") + " (*.cue *.CUE)",
0454         i18n("Cdrdao TOC Files and Cdrecord Clone Images") + " (*.toc *.TOC)",
0455         i18n("All Files") + " (*)",
0456     });
0457 #else
0458     d->editImagePath->setFilter( "*.iso *.toc *.ISO *.TOC *.cue *.CUE|" + i18n("Image Files")
0459                                 + '\n'
0460                                 + "*.iso *.ISO|" + i18n("ISO 9660 Image Files")
0461                                 + '\n'
0462                                 + "*.cue *.CUE|" + i18n("Cue Files")
0463                                 + '\n'
0464                                 + "*.toc *.TOC|" + i18n("Cdrdao TOC Files and Cdrecord Clone Images")
0465                                 + '\n'
0466                                 + "*|" + i18n("All Files") );
0467 #endif
0468     QHBoxLayout* groupImageUrlLayout = new QHBoxLayout( groupImageUrl );
0469     groupImageUrlLayout->addWidget( d->editImagePath );
0470 
0471     QGroupBox* groupImageType = new QGroupBox( i18n("Image Type"), frame );
0472     QHBoxLayout* groupImageTypeLayout = new QHBoxLayout( groupImageType );
0473     d->comboImageType = new QComboBox( groupImageType );
0474     groupImageTypeLayout->addWidget( d->comboImageType );
0475     groupImageTypeLayout->addStretch( 1 );
0476     d->comboImageType->addItem( i18n("Auto Detection") );
0477     d->comboImageType->addItem(i18n("ISO 9660 filesystem image"));
0478     d->comboImageType->addItem( i18n("Cue/bin image") );
0479     d->comboImageType->addItem( i18n("Audio cue file") );
0480     d->comboImageType->addItem( i18n("Cdrdao TOC file") );
0481     d->comboImageType->addItem( i18n("Cdrecord clone image") );
0482     d->comboImageType->addItem(i18n("Plain data image"));
0483     d->imageTypeSelectionMap[1] = IMAGE_ISO;
0484     d->imageTypeSelectionMap[2] = IMAGE_CUE_BIN;
0485     d->imageTypeSelectionMap[3] = IMAGE_AUDIO_CUE;
0486     d->imageTypeSelectionMap[4] = IMAGE_CDRDAO_TOC;
0487     d->imageTypeSelectionMap[5] = IMAGE_CDRECORD_CLONE;
0488     d->imageTypeSelectionMap[6] = IMAGE_RAW;
0489     d->imageTypeSelectionMapRev[IMAGE_ISO] = 1;
0490     d->imageTypeSelectionMapRev[IMAGE_CUE_BIN] = 2;
0491     d->imageTypeSelectionMapRev[IMAGE_AUDIO_CUE] = 3;
0492     d->imageTypeSelectionMapRev[IMAGE_CDRDAO_TOC] = 4;
0493     d->imageTypeSelectionMapRev[IMAGE_CDRECORD_CLONE] = 5;
0494     d->imageTypeSelectionMapRev[IMAGE_RAW] = 6;
0495 
0496 
0497     // image info
0498     // -----------------------------------------------------------------------
0499     d->infoView = new QTreeWidget( frame );
0500     d->infoView->setColumnCount( 2 );
0501     d->infoView->headerItem()->setText( 0, "key" );
0502     d->infoView->headerItem()->setText( 1, "value" );
0503     d->infoView->setHeaderHidden( true );
0504     d->infoView->setSelectionMode( QAbstractItemView::NoSelection );
0505     d->infoView->setItemsExpandable( false );
0506     d->infoView->setRootIsDecorated( false );
0507     d->infoView->header()->setSectionResizeMode( 0, QHeaderView::ResizeToContents );
0508     d->infoView->setFocusPolicy( Qt::NoFocus );
0509     d->infoView->setVerticalScrollMode( QAbstractItemView::ScrollPerPixel );
0510     d->infoView->setContextMenuPolicy( Qt::CustomContextMenu );
0511     //d->infoView->setNoItemText( i18n("No image file selected") );
0512     //d->infoView->setSorting( -1 );
0513     //d->infoView->setAlternateBackground( QColor() );
0514     //d->infoView->setFullWidth(true);
0515     //d->infoView->setSelectionMode( Q3ListView::NoSelection );
0516     //d->infoView->setHScrollBarMode( Q3ScrollView::AlwaysOff );
0517 
0518     connect( d->infoView, SIGNAL(customContextMenuRequested(QPoint)),
0519             this, SLOT(slotContextMenuRequested(QPoint)) );
0520 
0521     d->writerSelectionWidget = new K3b::WriterSelectionWidget( frame );
0522     d->writerSelectionWidget->setWantedMediumType( K3b::Device::MEDIA_WRITABLE );
0523     d->writerSelectionWidget->setWantedMediumState( K3b::Device::STATE_EMPTY );
0524 
0525     // options
0526     // -----------------------------------------------------------------------
0527     d->optionTabbed = new QTabWidget( frame );
0528 
0529     QWidget* optionTab = new QWidget( d->optionTabbed );
0530     QGridLayout* optionTabLayout = new QGridLayout( optionTab );
0531     optionTabLayout->setAlignment( Qt::AlignTop );
0532 
0533     QGroupBox* writingModeGroup = new QGroupBox( i18n("Writing Mode"), optionTab );
0534     d->writingModeWidget = new K3b::WritingModeWidget( writingModeGroup );
0535     QHBoxLayout* writingModeGroupLayout = new QHBoxLayout( writingModeGroup );
0536     writingModeGroupLayout->addWidget( d->writingModeWidget );
0537 
0538     // copies --------
0539     QGroupBox* groupCopies = new QGroupBox( i18n("Copies"), optionTab );
0540     QLabel* pixLabel = new QLabel( groupCopies );
0541     pixLabel->setPixmap( QIcon::fromTheme("tools-media-optical-copy").pixmap(KIconLoader::SizeMedium) );
0542     pixLabel->setScaledContents( false );
0543     d->spinCopies = new QSpinBox( groupCopies );
0544     d->spinCopies->setMinimum( 1 );
0545     d->spinCopies->setMaximum( 999 );
0546     QHBoxLayout* groupCopiesLayout = new QHBoxLayout( groupCopies );
0547     groupCopiesLayout->addWidget( pixLabel );
0548     groupCopiesLayout->addWidget( d->spinCopies );
0549     // -------- copies
0550 
0551     QGroupBox* optionGroup = new QGroupBox( i18n("Settings"), optionTab );
0552     d->checkDummy = K3b::StdGuiItems::simulateCheckbox( optionGroup );
0553     d->checkCacheImage = K3b::StdGuiItems::createCacheImageCheckbox( optionGroup );
0554     d->checkVerify = K3b::StdGuiItems::verifyCheckBox( optionGroup );
0555     QVBoxLayout* optionGroupLayout = new QVBoxLayout( optionGroup );
0556     optionGroupLayout->addWidget( d->checkDummy );
0557     optionGroupLayout->addWidget( d->checkCacheImage );
0558     optionGroupLayout->addWidget( d->checkVerify );
0559     optionGroupLayout->addStretch( 1 );
0560 
0561     optionTabLayout->addWidget( writingModeGroup, 0, 0 );
0562     optionTabLayout->addWidget( groupCopies, 1, 0 );
0563     optionTabLayout->addWidget( optionGroup, 0, 1, 2, 1 );
0564     optionTabLayout->setRowStretch( 1, 1 );
0565     optionTabLayout->setColumnStretch( 1, 1 );
0566 
0567     d->optionTabbed->addTab( optionTab, i18n("Settings") );
0568 
0569 
0570     // image tab ------------------------------------
0571     d->tempPathTab = new QWidget( d->optionTabbed );
0572     QGridLayout* imageTabGrid = new QGridLayout( d->tempPathTab );
0573 
0574     d->tempDirSelectionWidget = new K3b::TempDirSelectionWidget( d->tempPathTab );
0575 
0576     imageTabGrid->addWidget( d->tempDirSelectionWidget, 0, 0 );
0577 
0578     d->tempPathTabIndex = d->optionTabbed->addTab( d->tempPathTab, i18n("&Image") );
0579     d->tempPathTabVisible = true;
0580     // -------------------------------------------------------------
0581 
0582 
0583     // advanced ---------------------------------
0584     d->advancedTab = new QWidget( d->optionTabbed );
0585     QGridLayout* advancedTabLayout = new QGridLayout( d->advancedTab );
0586     advancedTabLayout->setAlignment( Qt::AlignTop );
0587 
0588     d->dataModeWidget = new K3b::DataModeWidget( d->advancedTab );
0589     d->checkNoFix = K3b::StdGuiItems::startMultisessionCheckBox( d->advancedTab );
0590 
0591     advancedTabLayout->addWidget( new QLabel( i18n("Data mode:"), d->advancedTab ), 0, 0 );
0592     advancedTabLayout->addWidget( d->dataModeWidget, 0, 1 );
0593     advancedTabLayout->addWidget( d->checkNoFix, 1, 0, 1, 3 );
0594     advancedTabLayout->setRowStretch( 2, 1 );
0595     advancedTabLayout->setColumnStretch( 2, 1 );
0596 
0597     d->advancedTabIndex = d->optionTabbed->addTab( d->advancedTab, i18n("Advanced") );
0598     d->advancedTabVisible = true;
0599     // -----------------------------------------------------------------------
0600 
0601 
0602 
0603 
0604     QGridLayout* grid = new QGridLayout( frame );
0605     grid->setContentsMargins( 0, 0, 0, 0 );
0606 
0607     grid->addWidget( groupImageUrl, 0, 0 );
0608     grid->addWidget( groupImageType, 0, 1 );
0609     grid->setColumnStretch( 0, 1 );
0610     grid->addWidget( d->infoView, 1, 0, 1, 2 );
0611     grid->addWidget( d->writerSelectionWidget, 2, 0, 1, 2 );
0612     grid->addWidget( d->optionTabbed, 3, 0, 1, 2 );
0613 
0614     grid->setRowStretch( 1, 1 );
0615 
0616 
0617     d->comboImageType->setWhatsThis( i18n("<p><b>Image types supported by K3b:</p>"
0618                                          "<p><b>Plain image</b><br/>"
0619                                          "Plain images are written as is to the medium using "
0620                                          "a single data track. Typical plain images are iso "
0621                                          "images as created by K3b's data project."
0622                                          "<p><b>Cue/bin images</b><br/>"
0623                                          "Cue/bin images consist of a cue file describing the "
0624                                          "table of contents of the medium and an image file "
0625                                          "which contains the actual data. The data will be "
0626                                          "written to the medium according to the cue file."
0627                                          "<p><b>Audio Cue image</b><br/>"
0628                                          "Audio cue images are a special kind of cue/bin image "
0629                                          "containing an image of an audio CD. The actual audio "
0630                                          "data can be encoded using any audio format supported "
0631                                          "by K3b. Audio cue files can also be imported into "
0632                                          "K3b audio projects which allows one to change the order "
0633                                          "and add or remove tracks."
0634                                          "<p><b>Cdrecord clone images</b><br/>"
0635                                          "K3b creates a cdrecord clone image of a single-session "
0636                                          "CD when copying a CD in clone mode. These images can "
0637                                          "be reused here."
0638                                          "<p><b>Cdrdao TOC files</b><br/>"
0639                                          "K3b supports writing cdrdao's own image format, the toc "
0640                                          "files.") );
0641 }
0642 
0643 
0644 void K3b::ImageWritingDialog::slotStartClicked()
0645 {
0646     d->md5Job->cancel();
0647 
0648     // save the path
0649     KConfigGroup grp( KSharedConfig::openConfig(), configGroup() );
0650     grp.writePathEntry( "last written image", d->imagePath() );
0651 
0652     if( d->imageFile.isEmpty() )
0653         d->imageFile = d->imagePath();
0654     if( d->tocFile.isEmpty() )
0655         d->tocFile = d->imagePath();
0656 
0657     // create a progresswidget
0658     K3b::BurnProgressDialog dlg( parentWidget() );
0659 
0660     // create the job
0661     K3b::BurnJob* job = 0;
0662     switch( d->currentImageType() ) {
0663     case IMAGE_CDRECORD_CLONE:
0664     {
0665         K3b::CloneJob* _job = new K3b::CloneJob( &dlg, this );
0666         _job->setWriterDevice( d->writerSelectionWidget->writerDevice() );
0667         _job->setImagePath( d->imageFile );
0668         _job->setSimulate( d->checkDummy->isChecked() );
0669         _job->setWriteSpeed( d->writerSelectionWidget->writerSpeed() );
0670         _job->setCopies( d->checkDummy->isChecked() ? 1 : d->spinCopies->value() );
0671         _job->setOnlyBurnExistingImage( true );
0672 
0673         job = _job;
0674     }
0675     break;
0676 
0677     case IMAGE_AUDIO_CUE:
0678     {
0679         K3b::AudioCueFileWritingJob* job_ = new K3b::AudioCueFileWritingJob( &dlg, this );
0680 
0681         job_->setBurnDevice( d->writerSelectionWidget->writerDevice() );
0682         job_->setSpeed( d->writerSelectionWidget->writerSpeed() );
0683         job_->setSimulate( d->checkDummy->isChecked() );
0684         job_->setWritingMode( d->writingModeWidget->writingMode() );
0685         job_->setCueFile( d->tocFile );
0686         job_->setCopies( d->checkDummy->isChecked() ? 1 : d->spinCopies->value() );
0687         job_->setOnTheFly( !d->checkCacheImage->isChecked() );
0688         job_->setTempDir( d->tempDirSelectionWidget->tempPath() );
0689 
0690         job = job_;
0691     }
0692     break;
0693 
0694     case IMAGE_CUE_BIN:
0695         // for now the K3b::BinImageWritingJob decides if it's a toc or a cue file
0696     case IMAGE_CDRDAO_TOC:
0697     {
0698         K3b::BinImageWritingJob* job_ = new K3b::BinImageWritingJob( &dlg, this );
0699 
0700         job_->setWriter( d->writerSelectionWidget->writerDevice() );
0701         job_->setSpeed( d->writerSelectionWidget->writerSpeed() );
0702         job_->setTocFile( d->tocFile );
0703         job_->setSimulate(d->checkDummy->isChecked());
0704         job_->setMulti( false /*d->checkNoFix->isChecked()*/ );
0705         job_->setCopies( d->checkDummy->isChecked() ? 1 : d->spinCopies->value() );
0706 
0707         job = job_;
0708     }
0709     break;
0710 
0711     case IMAGE_RAW:
0712     case IMAGE_ISO:
0713     {
0714         if (d->currentImageType() == IMAGE_ISO) {
0715             K3b::Iso9660 isoFs(d->imageFile);
0716             if (isoFs.open()) {
0717                 if (K3b::filesize(QUrl::fromLocalFile(d->imageFile)) < Private::volumeSpaceSize(isoFs)) {
0718                     if (KMessageBox::questionTwoActions(this,
0719                                                         i18n("<p>The actual file size does not match the size declared in the file header. "
0720                                                              "If it has been downloaded make sure the download is complete.</p>"
0721                                                              "<p>Only continue if you know what you are doing.</p>"),
0722                                                         i18n("Warning"),
0723                                                         KStandardGuiItem::cont(),
0724                                                         KStandardGuiItem::cancel() ) == KMessageBox::SecondaryAction )
0725                         return;
0726                 }
0727             }
0728         }
0729 
0730         // TODO: it needs a NON ISO 9660 images testcase
0731         K3b::Iso9660ImageWritingJob* job_ = new K3b::Iso9660ImageWritingJob( &dlg );
0732 
0733         job_->setBurnDevice( d->writerSelectionWidget->writerDevice() );
0734         job_->setSpeed( d->writerSelectionWidget->writerSpeed() );
0735         job_->setSimulate( d->checkDummy->isChecked() );
0736         job_->setWritingMode( d->writingModeWidget->writingMode() );
0737         job_->setVerifyData( d->checkVerify->isChecked() );
0738         job_->setNoFix( d->checkNoFix->isChecked() );
0739         job_->setDataMode( d->dataModeWidget->dataMode() );
0740         job_->setImagePath( d->imageFile );
0741         job_->setCopies( d->checkDummy->isChecked() ? 1 : d->spinCopies->value() );
0742 
0743         job = job_;
0744     }
0745     break;
0746 
0747     default:
0748         qDebug() << "(K3b::ImageWritingDialog) this should really not happen!";
0749         break;
0750     }
0751 
0752     if( job ) {
0753         job->setWritingApp( d->writerSelectionWidget->writingApp() );
0754 
0755         hide();
0756 
0757         dlg.startJob(job);
0758 
0759         delete job;
0760 
0761         if( KConfigGroup( KSharedConfig::openConfig(), QStringLiteral("General Options") ).readEntry( "keep action dialogs open", false ) )
0762             show();
0763         else
0764             close();
0765     }
0766 }
0767 
0768 
0769 void K3b::ImageWritingDialog::slotUpdateImage( const QString& )
0770 {
0771     QString path = d->imagePath();
0772 
0773     // check the image types
0774 
0775     d->haveMd5Sum = false;
0776     d->md5Job->cancel();
0777     d->infoView->clear();
0778     //d->infoView->header()->resizeSection( 0, 20 );
0779     d->md5SumItem = 0;
0780     d->foundImageType = IMAGE_UNKNOWN;
0781     d->tocFile.truncate(0);
0782     d->imageFile.truncate(0);
0783 
0784     QFileInfo info( path );
0785     if( info.isFile() ) {
0786 
0787         // ------------------------------------------------
0788         // Test for iso9660 image
0789         // ------------------------------------------------
0790         K3b::Iso9660 isoF( path );
0791         if( isoF.open() ) {
0792 #ifdef K3B_DEBUG
0793             isoF.debug();
0794 #endif
0795 
0796             d->createIso9660InfoItems( &isoF );
0797             isoF.close();
0798             calculateMd5Sum( path );
0799 
0800             d->foundImageType = IMAGE_ISO;
0801             d->imageFile = path;
0802         }
0803 
0804         if( d->foundImageType == IMAGE_UNKNOWN ) {
0805 
0806             // check for cdrecord clone image
0807             // try both path and path.toc as tocfiles
0808             K3b::CloneTocReader cr;
0809 
0810             if( path.right(4) == ".toc" ) {
0811                 cr.openFile( path );
0812                 if( cr.isValid() ) {
0813                     d->tocFile = path;
0814                     d->imageFile = cr.imageFilename();
0815                 }
0816             }
0817             if( d->imageFile.isEmpty() ) {
0818                 cr.openFile( path + ".toc" );
0819                 if( cr.isValid() ) {
0820                     d->tocFile = cr.filename();
0821                     d->imageFile = cr.imageFilename();
0822                 }
0823             }
0824 
0825             if( !d->imageFile.isEmpty() ) {
0826                 // we have a cdrecord clone image
0827                 d->createCdrecordCloneItems( d->tocFile, d->imageFile );
0828                 calculateMd5Sum( d->imageFile );
0829 
0830                 d->foundImageType = IMAGE_CDRECORD_CLONE;
0831             }
0832         }
0833 
0834         if( d->foundImageType == IMAGE_UNKNOWN ) {
0835 
0836             // check for cue/bin stuff
0837             // once again we try both path and path.cue
0838             K3b::CueFileParser cp;
0839 
0840             if( path.right(4).toLower() == ".cue" )
0841                 cp.openFile( path );
0842             else if( path.right(4).toLower() == ".bin" )
0843                 cp.openFile( path.left( path.length()-3) + "cue" );
0844 
0845             if( cp.isValid() ) {
0846                 d->tocFile = cp.filename();
0847                 d->imageFile = cp.imageFilename();
0848             }
0849 
0850             if( d->imageFile.isEmpty() ) {
0851                 cp.openFile( path + ".cue" );
0852                 if( cp.isValid() ) {
0853                     d->tocFile = cp.filename();
0854                     d->imageFile = cp.imageFilename();
0855                 }
0856             }
0857 
0858             if( !d->imageFile.isEmpty() ) {
0859                 // we have a cue file
0860                 if( cp.toc().contentType() == K3b::Device::AUDIO ) {
0861                     d->foundImageType = IMAGE_AUDIO_CUE;
0862                     d->createAudioCueItems( cp );
0863                 }
0864                 else {
0865                     d->foundImageType = IMAGE_CUE_BIN;  // we cannot be sure if writing will work... :(
0866                     d->createCueBinItems( d->tocFile, d->imageFile );
0867                     calculateMd5Sum( d->imageFile );
0868                 }
0869             }
0870         }
0871 
0872         if( d->foundImageType == IMAGE_UNKNOWN ) {
0873             // TODO: check for cdrdao tocfile
0874         }
0875 
0876         // TODO: treat unusable image to opaque
0877         if (d->foundImageType == IMAGE_UNKNOWN) {
0878             if (KMessageBox::questionTwoActions(this,
0879                                                 i18n("Type of image file is not recognizable. Do you want to burn it anyway?"),
0880                                                 i18n("Unknown image type"),
0881                                                 KGuiItem(i18n("Burn")),
0882                                                 KStandardGuiItem::cancel()) == KMessageBox::PrimaryAction) {
0883                 d->foundImageType = IMAGE_RAW;
0884                 d->imageFile = path;
0885             }
0886         }
0887 
0888         if( d->foundImageType == IMAGE_UNKNOWN ) {
0889             QTreeWidgetItem* item = new QTreeWidgetItem( d->infoView );
0890             if ( !info.isReadable() ) {
0891                 item->setText( 0, i18n("Unable to read image file") );
0892             } else {
0893                 item->setText( 0, i18n("Seems not to be a usable image") );
0894             }
0895             item->setForeground( 0, d->negativeTextColor );
0896             item->setIcon( 0, QIcon::fromTheme( "dialog-error") );
0897         }
0898         else {
0899             // remember as recent image
0900             int i = 0;
0901             while ( i < d->comboRecentImages->count() && d->comboRecentImages->itemText(i) != path )
0902                 ++i;
0903             if ( i == d->comboRecentImages->count() )
0904                 d->comboRecentImages->insertItem( 0, path );
0905         }
0906     }
0907     else {
0908         QTreeWidgetItem* item = new QTreeWidgetItem( d->infoView );
0909         item->setText( 0, i18n("File not found") );
0910         item->setForeground( 0, d->negativeTextColor );
0911         item->setIcon( 0, QIcon::fromTheme( "dialog-error") );
0912     }
0913 
0914     slotToggleAll();
0915 }
0916 
0917 
0918 void K3b::ImageWritingDialog::toggleAll()
0919 {
0920 
0921     K3b::Medium medium = k3bappcore->mediaCache()->medium( d->writerSelectionWidget->writerDevice() );
0922 
0923     // set usable writing apps
0924     // for now we only restrict ourselves in case of CD images
0925     switch( d->currentImageType() ) {
0926     case IMAGE_CDRDAO_TOC:
0927         d->writerSelectionWidget->setSupportedWritingApps( K3b::WritingAppCdrdao );
0928         break;
0929     case IMAGE_CDRECORD_CLONE:
0930         d->writerSelectionWidget->setSupportedWritingApps( K3b::WritingAppCdrecord );
0931         break;
0932     default: {
0933         K3b::WritingApps apps = K3b::WritingAppCdrecord;
0934         if (d->currentImageType() == IMAGE_ISO || d->currentImageType() == IMAGE_RAW) {
0935             // DVD/BD is always ISO here
0936             apps |= K3b::WritingAppGrowisofs;
0937         }
0938         if ( K3b::Device::isCdMedia( medium.diskInfo().mediaType() ) )
0939             apps |= K3b::WritingAppCdrdao;
0940 
0941         d->writerSelectionWidget->setSupportedWritingApps( apps );
0942         break;
0943     }
0944     }
0945 
0946     // set a wanted media type
0947     // some image types can be put on any medium, some only on CD
0948     if (d->currentImageType() == IMAGE_ISO ||
0949         d->currentImageType() == IMAGE_RAW ||
0950         d->currentImageType() == IMAGE_UNKNOWN) {
0951         d->writerSelectionWidget->setWantedMediumType( K3b::Device::MEDIA_WRITABLE );
0952     }
0953     else {
0954         d->writerSelectionWidget->setWantedMediumType( K3b::Device::MEDIA_WRITABLE_CD );
0955     }
0956 
0957     // set wanted image size
0958     if (d->currentImageType() == IMAGE_ISO || d->currentImageType() == IMAGE_RAW)
0959         d->writerSelectionWidget->setWantedMediumSize( K3b::filesize( QUrl::fromLocalFile(d->imagePath()) )/2048 );
0960     else
0961         d->writerSelectionWidget->setWantedMediumSize( Msf() );
0962 
0963     // cdrecord clone and cue both need DAO
0964     if( d->writerSelectionWidget->writingApp() != K3b::WritingAppCdrdao
0965         && ( d->currentImageType() == IMAGE_ISO ||
0966              d->currentImageType() == IMAGE_AUDIO_CUE ) )
0967         d->writingModeWidget->determineSupportedModesFromMedium( medium );
0968     else
0969         d->writingModeWidget->setSupportedModes( K3b::WritingModeSao );
0970 
0971     // enable the Write-Button if we found a valid image or the user forced an image type
0972     setButtonEnabled( START_BUTTON, d->writerSelectionWidget->writerDevice()
0973                       && d->currentImageType() != IMAGE_UNKNOWN
0974                       && QFile::exists( d->imagePath() ) );
0975 
0976     // some stuff is only available for iso and opaque images
0977     if (d->currentImageType() == IMAGE_ISO || d->currentImageType() == IMAGE_RAW) {
0978         d->checkVerify->show();
0979         if( !d->advancedTabVisible ) {
0980             d->advancedTabIndex = d->optionTabbed->addTab( d->advancedTab, i18n("Advanced") );
0981         }
0982         d->advancedTabVisible = true;
0983         if( d->checkDummy->isChecked() ) {
0984             d->checkVerify->setEnabled( false );
0985             d->checkVerify->setChecked( false );
0986         }
0987         else
0988             d->checkVerify->setEnabled( true );
0989     }
0990     else {
0991         if( d->advancedTabVisible ) {
0992             d->optionTabbed->removeTab( d->advancedTabIndex );
0993         }
0994         d->advancedTabVisible = false;
0995         d->checkVerify->hide();
0996     }
0997 
0998 
0999     // and some other stuff only makes sense for audio cues
1000     if( d->currentImageType() == IMAGE_AUDIO_CUE ) {
1001         if( !d->tempPathTabVisible )
1002             d->tempPathTabIndex = d->optionTabbed->addTab( d->tempPathTab, i18n("&Image") );
1003         d->tempPathTabVisible = true;
1004         d->tempDirSelectionWidget->setDisabled( !d->checkCacheImage->isChecked() );
1005     }
1006     else {
1007         if( d->tempPathTabVisible ) {
1008             d->optionTabbed->removeTab( d->tempPathTabIndex );
1009         }
1010         d->tempPathTabVisible = false;
1011     }
1012     d->checkCacheImage->setVisible( d->currentImageType() == IMAGE_AUDIO_CUE );
1013 
1014     d->spinCopies->setEnabled( !d->checkDummy->isChecked() );
1015 
1016 
1017     if( QTreeWidgetItem* item = d->infoView->topLevelItem( 0 ) ) {
1018         item->setForeground( 1,
1019                              d->currentImageType() != d->foundImageType
1020                              ? d->negativeTextColor : d->normalTextColor );
1021     }
1022 }
1023 
1024 
1025 void K3b::ImageWritingDialog::setImage( const QUrl& url )
1026 {
1027     d->imageForced = true;
1028     d->editImagePath->setUrl( url );
1029 }
1030 
1031 
1032 void K3b::ImageWritingDialog::calculateMd5Sum( const QString& file )
1033 {
1034     d->haveMd5Sum = false;
1035 
1036     if( !d->md5SumItem ) {
1037         d->md5SumItem = new QTreeWidgetItem( d->infoView );
1038     }
1039 
1040     d->md5SumItem->setText( 0, i18n("MD5 Sum:") );
1041     d->md5SumItem->setForeground( 0, d->infoTextColor );
1042     d->md5SumItem->setTextAlignment( 0, Qt::AlignRight );
1043 
1044     if( file != d->lastCheckedFile ) {
1045 
1046         QProgressBar* progress = new QProgressBar( d->infoView );
1047         progress->setMaximumHeight( fontMetrics().height() );
1048         progress->setRange( 0, 100 );
1049         progress->setValue( 0 );
1050         d->infoView->setItemWidget( d->md5SumItem, 1, progress );
1051         d->lastCheckedFile = file;
1052         d->md5Job->setFile( file );
1053         d->md5Job->start();
1054     }
1055     else
1056         slotMd5JobFinished( true );
1057 }
1058 
1059 
1060 void K3b::ImageWritingDialog::slotMd5JobPercent( int p )
1061 {
1062     QWidget* widget = d->infoView->itemWidget( d->md5SumItem, 1 );
1063     if( QProgressBar* progress = qobject_cast<QProgressBar*>( widget ) )
1064     {
1065         progress->setValue( p );
1066     }
1067 }
1068 
1069 
1070 void K3b::ImageWritingDialog::slotMd5JobFinished( bool success )
1071 {
1072     if( success ) {
1073         d->md5SumItem->setText( 1, d->md5Job->hexDigest() );
1074         d->md5SumItem->setIcon( 1, QIcon::fromTheme("dialog-information") );
1075         d->haveMd5Sum = true;
1076     }
1077     else {
1078         d->md5SumItem->setForeground( 1, d->negativeTextColor );
1079         if( d->md5Job->hasBeenCanceled() )
1080             d->md5SumItem->setText( 1, i18n("Calculation canceled") );
1081         else
1082             d->md5SumItem->setText( 1, i18n("Calculation failed") );
1083         d->md5SumItem->setIcon( 1, QIcon::fromTheme("dialog-error") );
1084         d->lastCheckedFile.truncate(0);
1085     }
1086 
1087     // Hide progress bar
1088     d->infoView->setItemWidget( d->md5SumItem, 1, 0 );
1089 }
1090 
1091 
1092 void K3b::ImageWritingDialog::slotContextMenuRequested( const QPoint& pos )
1093 {
1094     if( !d->haveMd5Sum )
1095         return;
1096 
1097     QMenu popup;
1098     QAction *copyItem = popup.addAction( i18n("Copy checksum to clipboard") );
1099     QAction *compareItem = popup.addAction( i18n("Compare checksum...") );
1100 
1101     QAction *act = popup.exec( d->infoView->mapToGlobal( pos ) );
1102 
1103     if( act == compareItem ) {
1104         bool ok;
1105         QString md5sumToCompare = QInputDialog::getText( this,
1106                                                          i18n("MD5 Sum Check"),
1107                                                          i18n("Please insert the MD5 Sum to compare:"),
1108                                                          QLineEdit::Normal,
1109                                                          QString(),
1110                                                          &ok );
1111         if( ok ) {
1112             if( md5sumToCompare.toLower().toUtf8() == d->md5Job->hexDigest().toLower() )
1113                 KMessageBox::information( this, i18n("The MD5 Sum of %1 equals that specified.",d->imagePath()),
1114                                           i18n("MD5 Sums Equal") );
1115             else
1116                 KMessageBox::error( this, i18n("The MD5 Sum of %1 differs from that specified.",d->imagePath()),
1117                                     i18n("MD5 Sums Differ") );
1118         }
1119     }
1120     else if( act == copyItem ) {
1121         QApplication::clipboard()->setText( d->md5Job->hexDigest().toLower(), QClipboard::Clipboard );
1122     }
1123 }
1124 
1125 
1126 void K3b::ImageWritingDialog::loadSettings( const KConfigGroup& c )
1127 {
1128     d->writingModeWidget->loadConfig( c );
1129     d->checkDummy->setChecked( c.readEntry("simulate", false ) );
1130     d->checkNoFix->setChecked( c.readEntry("multisession", false ) );
1131     d->checkCacheImage->setChecked( !c.readEntry("on_the_fly", true ) );
1132 
1133     d->dataModeWidget->loadConfig(c);
1134 
1135     d->spinCopies->setValue( c.readEntry( "copies", 1 ) );
1136 
1137     d->checkVerify->setChecked( c.readEntry( "verify_data", false ) );
1138 
1139     d->writerSelectionWidget->loadConfig( c );
1140 
1141     if( !d->imageForced ) {
1142         QString image = c.readPathEntry( "image path", c.readPathEntry( "last written image", QString() ) );
1143         if( QFile::exists( image ) )
1144             d->editImagePath->setUrl( QUrl::fromLocalFile( image ) );
1145     }
1146 
1147     QString imageType = c.readEntry( "image type", "auto" );
1148     int x = 0;
1149     if( imageType == "iso9660" )
1150         x = d->imageTypeSelectionMapRev[IMAGE_ISO];
1151     else if( imageType == "cue-bin" )
1152         x = d->imageTypeSelectionMapRev[IMAGE_CUE_BIN];
1153     else if( imageType == "audio-cue" )
1154         x = d->imageTypeSelectionMapRev[IMAGE_AUDIO_CUE];
1155     else if( imageType == "cdrecord-clone" )
1156         x = d->imageTypeSelectionMapRev[IMAGE_CDRECORD_CLONE];
1157     else if( imageType == "cdrdao-toc" )
1158         x = d->imageTypeSelectionMapRev[IMAGE_CDRDAO_TOC];
1159     else if (imageType == "opaque")
1160         x = d->imageTypeSelectionMapRev[IMAGE_RAW];
1161 
1162     d->comboImageType->setCurrentIndex( x );
1163 
1164     d->tempDirSelectionWidget->setTempPath( K3b::defaultTempPath() );
1165 
1166     slotToggleAll();
1167 }
1168 
1169 
1170 void K3b::ImageWritingDialog::saveSettings( KConfigGroup c )
1171 {
1172     d->writingModeWidget->saveConfig( c ),
1173         c.writeEntry( "simulate", d->checkDummy->isChecked() );
1174     c.writeEntry( "multisession", d->checkNoFix->isChecked() );
1175     c.writeEntry( "on_the_fly", !d->checkCacheImage->isChecked() );
1176     d->dataModeWidget->saveConfig(c);
1177 
1178     c.writeEntry( "verify_data", d->checkVerify->isChecked() );
1179 
1180     d->writerSelectionWidget->saveConfig( c );
1181 
1182     c.writePathEntry( "image path", d->imagePath() );
1183 
1184     c.writeEntry( "copies", d->spinCopies->value() );
1185 
1186     QString imageType;
1187     if( d->comboImageType->currentIndex() == 0 )
1188         imageType = "auto";
1189     else {
1190         switch( d->imageTypeSelectionMap[d->comboImageType->currentIndex()] ) {
1191         case IMAGE_ISO:
1192             imageType = "iso9660";
1193             break;
1194         case IMAGE_CUE_BIN:
1195             imageType = "cue-bin";
1196             break;
1197         case IMAGE_AUDIO_CUE:
1198             imageType = "audio-cue";
1199             break;
1200         case IMAGE_CDRECORD_CLONE:
1201             imageType = "cdrecord-clone";
1202             break;
1203         case IMAGE_CDRDAO_TOC:
1204             imageType = "cdrdao-toc";
1205             break;
1206         case IMAGE_RAW:
1207             imageType = "opaque";
1208             break;
1209         }
1210     }
1211     c.writeEntry( "image type", imageType );
1212 
1213     if( d->tempDirSelectionWidget->isEnabled() )
1214         d->tempDirSelectionWidget->saveConfig();
1215 }
1216 
1217 
1218 void K3b::ImageWritingDialog::dragEnterEvent( QDragEnterEvent* e )
1219 {
1220     e->setAccepted( e->mimeData()->hasUrls() );
1221 }
1222 
1223 
1224 void K3b::ImageWritingDialog::dropEvent( QDropEvent* e )
1225 {
1226     QList<QUrl> urls = e->mimeData()->urls();
1227     if( !urls.isEmpty() ) {
1228         d->editImagePath->setUrl( urls.first() );
1229     }
1230 }
1231 
1232 #include "moc_k3bimagewritingdialog.cpp"