File indexing completed on 2024-04-21 04:50:10

0001 /*
0002     SPDX-FileCopyrightText: 1998-2010 Sebastian Trueg <trueg@k3b.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 
0007 #include "k3bemptydiscwaiter.h"
0008 #include "k3bmediacache.h"
0009 #include "k3bapplication.h"
0010 #include "k3bdevice.h"
0011 #include "k3bdeviceglobals.h"
0012 #include "k3bdevicehandler.h"
0013 #include "k3bglobals.h"
0014 #include "k3bcore.h"
0015 #include "k3biso9660.h"
0016 #include "k3bblankingjob.h"
0017 #include "k3bbusywidget.h"
0018 #include "k3bdvdformattingjob.h"
0019 
0020 #include <KConfig>
0021 #include <KConfigGroup>
0022 #include <KSharedConfig>
0023 #include <KIconLoader>
0024 #include <KLocalizedString>
0025 #include <KNotification>
0026 #include <KGuiItem>
0027 #include <KMessageBox>
0028 
0029 #include <QEventLoop>
0030 #include <QTimer>
0031 #include <QFont>
0032 #include <QApplication>
0033 #include <QDialogButtonBox>
0034 #include <QGridLayout>
0035 #include <QLabel>
0036 #include <QLayout>
0037 #include <QProgressDialog>
0038 #include <QPushButton>
0039 #include <QToolTip>
0040 
0041 
0042 class K3b::EmptyDiscWaiter::Private
0043 {
0044 public:
0045     Private()
0046         : erasingInfoDialog(0) {
0047         dialogVisible = false;
0048         inLoop = false;
0049         mediumChanged = 0;
0050         blockMediaChange = false;
0051     }
0052 
0053     K3b::Device::Device* device;
0054 
0055     Device::MediaTypes wantedMediaType;
0056     Device::MediaStates wantedMediaState;
0057     Msf wantedMinMediaSize;
0058 
0059     Device::MediaType result;
0060     int dialogVisible;
0061     bool inLoop;
0062 
0063     bool blockMediaChange;
0064     int mediumChanged;
0065 
0066     bool canceled;
0067 
0068     bool waitingDone;
0069 
0070     QLabel* labelRequest;
0071     QLabel* labelFoundMedia;
0072     QLabel* pixLabel;
0073 
0074     QProgressDialog* erasingInfoDialog;
0075 };
0076 
0077 
0078 
0079 K3b::EmptyDiscWaiter::EmptyDiscWaiter( K3b::Device::Device* device, QWidget* parent )
0080     : QDialog( parent ),
0081       d( new Private() )
0082 {
0083     setWindowTitle(i18n("Waiting for Disk"));
0084     setModal(true);
0085 
0086     d->device = device;
0087 
0088     // setup the gui
0089     // -----------------------------
0090     d->labelRequest = new QLabel( this );
0091     d->labelRequest->setAlignment( Qt::AlignLeft | Qt::AlignVCenter );
0092     d->labelFoundMedia = new QLabel( this );
0093     d->pixLabel = new QLabel( this );
0094     d->pixLabel->setAlignment( Qt::AlignHCenter | Qt::AlignTop );
0095 
0096     QFont f( d->labelFoundMedia->font() );
0097     f.setBold(true);
0098     d->labelFoundMedia->setFont( f );
0099 
0100     QDialogButtonBox* buttonBox = new QDialogButtonBox( this );
0101 
0102     QPushButton* cancelButton = buttonBox->addButton( QDialogButtonBox::Cancel );
0103     connect( cancelButton, SIGNAL(clicked()), this, SLOT(slotCancel()) );
0104 
0105     QPushButton* ejectButton = new QPushButton( this );
0106     KGuiItem::assign( ejectButton, KGuiItem( i18n("Eject"), QString::fromLatin1( "media-eject" ) ) );
0107     buttonBox->addButton( ejectButton, QDialogButtonBox::NoRole );
0108     connect( ejectButton, SIGNAL(clicked()), this, SLOT(slotEject()) );
0109 
0110     QPushButton* loadButton = buttonBox->addButton( i18n("Load"), QDialogButtonBox::NoRole );
0111     connect( loadButton, SIGNAL(clicked()), this, SLOT(slotLoad()) );
0112 
0113     QVBoxLayout* box = new QVBoxLayout( this );
0114     QHBoxLayout* hbox = new QHBoxLayout( this );
0115 
0116     hbox->addWidget(d->pixLabel);
0117     QVBoxLayout* vbox = new QVBoxLayout( this );
0118     vbox->addWidget(new QLabel(i18n("Found medium:"), this));
0119     vbox->addWidget(d->labelFoundMedia);
0120     vbox->addWidget(d->labelRequest);
0121     hbox->addLayout( vbox );
0122     box->addLayout( hbox );
0123     box->addWidget(buttonBox);
0124     // -----------------------------
0125 
0126     connect( k3bappcore->mediaCache(), SIGNAL(mediumChanged(K3b::Device::Device*)),
0127              this, SLOT(slotMediumChanged(K3b::Device::Device*)) );
0128 }
0129 
0130 
0131 K3b::EmptyDiscWaiter::~EmptyDiscWaiter()
0132 {
0133     delete d;
0134 }
0135 
0136 
0137 K3b::Device::MediaType K3b::EmptyDiscWaiter::waitForDisc( Device::MediaStates mediaState,
0138                                                           Device::MediaTypes mediaType,
0139                                                           const K3b::Msf& minMediaSize,
0140                                                           const QString& message )
0141 {
0142     if ( d->inLoop ) {
0143         qCritical() << "Recursive call detected." << Qt::endl;
0144         return Device::MEDIA_UNKNOWN;
0145     }
0146 
0147     qDebug() << "Waiting for medium" << mediaState << mediaType << message;
0148 
0149     d->wantedMediaState = mediaState;
0150     d->wantedMediaType = mediaType;
0151     d->wantedMinMediaSize = minMediaSize;
0152     d->dialogVisible = false;
0153     d->canceled = false;
0154     d->waitingDone = false;
0155     d->blockMediaChange = false;
0156     d->mediumChanged = 0;
0157 
0158     // FIXME: reproducibility race?
0159     if (message.isEmpty())
0160         d->labelRequest->setText( Medium::mediaRequestString( d->wantedMediaType, d->wantedMediaState, minMediaSize, d->device ) );
0161     else
0162         d->labelRequest->setText( message );
0163 
0164     if( d->wantedMediaType & K3b::Device::MEDIA_WRITABLE_DVD )
0165         d->pixLabel->setPixmap( KIconLoader::global()->loadIcon( "media-optical-dvd",
0166                                                                  KIconLoader::NoGroup, KIconLoader::SizeMedium ) );
0167     else
0168         d->pixLabel->setPixmap( KIconLoader::global()->loadIcon( "media-optical-recordable",
0169                                                                  KIconLoader::NoGroup, KIconLoader::SizeMedium ) );
0170 
0171     adjustSize();
0172 
0173     slotMediumChanged( d->device );
0174 
0175     //
0176     // in case we already found a medium and thus the dialog is not shown entering
0177     // the loop only causes problems (since there is no dialog yet the user could
0178     // not have canceled yet
0179     //
0180     if( !d->waitingDone ) {
0181         d->inLoop = true;
0182         enterLoop();
0183     }
0184     return d->result;
0185 }
0186 
0187 void K3b::EmptyDiscWaiter::enterLoop()
0188 {
0189     QEventLoop eventLoop;
0190     connect(this, SIGNAL(leaveModality()),
0191             &eventLoop, SLOT(quit()));
0192     eventLoop.exec();
0193 }
0194 
0195 int K3b::EmptyDiscWaiter::exec()
0196 {
0197     return waitForDisc();
0198 }
0199 
0200 
0201 void K3b::EmptyDiscWaiter::slotMediumChanged( K3b::Device::Device* dev )
0202 {
0203     qDebug() << dev->blockDeviceName();
0204     if( d->canceled || d->device != dev )
0205         return;
0206 
0207     //
0208     // This slot may open dialogs which enter a new event loop and that
0209     // may result in another call to this slot if a medium changes while
0210     // a dialog is open
0211     //
0212     if( d->blockMediaChange ) {
0213         d->mediumChanged++;
0214         return;
0215     }
0216 
0217     d->blockMediaChange = true;
0218 
0219     bool formatWithoutAsking = KConfigGroup( KSharedConfig::openConfig(), QStringLiteral("General Options") ).readEntry( "auto rewritable erasing", false );
0220 
0221     K3b::Medium medium = k3bappcore->mediaCache()->medium( dev );
0222 
0223     d->labelFoundMedia->setText( medium.shortString( Medium::NoStringFlags ) );
0224 
0225     if( medium.diskInfo().diskState() == K3b::Device::STATE_NO_MEDIA ) {
0226         continueWaiting();
0227         d->blockMediaChange = false;
0228         return;
0229     }
0230 
0231 //   QString mediaState;
0232 //   if( medium.diskInfo().diskState() == K3b::Device::STATE_COMPLETE )
0233 //     mediaState = i18n("complete");
0234 //   else if( medium.diskInfo().diskState() == K3b::Device::STATE_INCOMPLETE )
0235 //     mediaState = i18n("appendable");
0236 //   else if( medium.diskInfo().diskState() == K3b::Device::STATE_EMPTY )
0237 //     mediaState = i18n("empty");
0238 
0239 //   if( !mediaState.isEmpty() )
0240 //     mediaState = " (" + mediaState +")";
0241 
0242     // /////////////////////////////////////////////////////////////
0243     //
0244     // BD-RE handling
0245     //
0246     // /////////////////////////////////////////////////////////////
0247     if ( (d->wantedMediaType & K3b::Device::MEDIA_BD_RE) &&
0248          (medium.diskInfo().mediaType() & K3b::Device::MEDIA_BD_RE) ) {
0249 
0250         qDebug() << "------ found BD-RE as wanted.";
0251 
0252 #ifdef _MSC_VER
0253 #pragma message ("WARNING: FIXME: We need to preformat empty BD-RE just like we do with empty DVD+RW")
0254 #else
0255 #warning FIXME: We need to preformat empty BD-RE just like we do with empty DVD+RW
0256 #endif
0257 
0258         if( d->wantedMediaState == K3b::Device::STATE_EMPTY &&
0259             ( d->wantedMinMediaSize <= medium.diskInfo().capacity() ||
0260               IsOverburnAllowed( d->wantedMinMediaSize, medium.diskInfo().capacity() ) ) ) {
0261             // check if the media contains a filesystem
0262             K3b::Iso9660 isoF( d->device );
0263             bool hasIso = isoF.open();
0264 
0265             if( formatWithoutAsking ||
0266                 !hasIso ||
0267                 KMessageBox::warningContinueCancel( parentWidgetToUse(),
0268                                                     i18n("Found %1 medium in %2 - %3. Should it be overwritten?",
0269                                                          QLatin1String("BD-RE"),
0270                                                          d->device->vendor(),
0271                                                          d->device->description()),
0272                                                     i18n("Found %1", QLatin1String("BD-RE")),
0273                                                     KStandardGuiItem::overwrite(),
0274                                                     KGuiItem(i18n("&Eject"), "media-eject") ) == KMessageBox::Continue ) {
0275                 finishWaiting( K3b::Device::MEDIA_BD_RE );
0276             }
0277             else {
0278                 qDebug() << "starting devicehandler: no BD-RE overwrite";
0279                 K3b::eject( d->device );
0280                 continueWaiting();
0281             }
0282         }
0283 
0284         //
0285         // We want a BD-RE not necessarily empty. No problem, just use this one. Because incomplete and complete
0286         // are handled the same everywhere (isofs is grown).
0287         //
0288         else if ( d->wantedMediaState != Device::STATE_EMPTY &&
0289                   ( d->wantedMinMediaSize <= medium.actuallyRemainingSize() ||
0290                     IsOverburnAllowed( d->wantedMinMediaSize, medium.diskInfo().capacity(), medium.actuallyUsedCapacity() ) ) ) {
0291             finishWaiting( K3b::Device::MEDIA_BD_RE );
0292         }
0293         else {
0294             qDebug() << "BD-RE medium too small";
0295             continueWaiting();
0296         }
0297     }
0298 
0299     // /////////////////////////////////////////////////////////////
0300     //
0301     // DVD+RW handling
0302     //
0303     // /////////////////////////////////////////////////////////////
0304 
0305     // DVD+RW: if empty we need to preformat. Although growisofs does it before writing doing it here
0306     //         allows better control and a progress bar. If it's not empty we should check if there is
0307     //         already a filesystem on the medium.
0308     else if( (d->wantedMediaType & K3b::Device::MEDIA_DVD_PLUS_RW) &&
0309              (medium.diskInfo().mediaType() & K3b::Device::MEDIA_DVD_PLUS_RW) ) {
0310 
0311         qDebug() << "------ found DVD+RW as wanted.";
0312 
0313         if( medium.diskInfo().diskState() == K3b::Device::STATE_EMPTY ) {
0314             if( d->wantedMediaState & K3b::Device::STATE_EMPTY &&
0315                 ( d->wantedMinMediaSize <= medium.diskInfo().capacity() ||
0316                   IsOverburnAllowed( d->wantedMinMediaSize, medium.diskInfo().capacity() ) ) ) {
0317                 // special case for the formatting job which wants to preformat on it's own!
0318                 if( d->wantedMediaState & K3b::Device::STATE_COMPLETE &&
0319                     d->wantedMediaState & K3b::Device::STATE_EMPTY ) {
0320                     qDebug() << "special case: DVD+RW for the formatting job.";
0321                     finishWaiting( K3b::Device::MEDIA_DVD_PLUS_RW );
0322                 }
0323                 else {
0324                     // empty - preformat without asking
0325                     prepareErasingDialog();
0326 
0327                     K3b::DvdFormattingJob job( this );
0328                     job.setDevice( d->device );
0329                     job.setFormattingMode( FormattingQuick );
0330                     job.setForce( false );
0331                     job.setForceNoEject( true );
0332 
0333                     d->erasingInfoDialog->reset();
0334                     d->erasingInfoDialog->setLabelText( i18n("Preformatting DVD+RW") );
0335                     d->erasingInfoDialog->setRange( 0, 100 );
0336                     connect( &job, SIGNAL(finished(bool)), this, SLOT(slotErasingFinished(bool)) );
0337                     connect( &job, SIGNAL(percent(int)), d->erasingInfoDialog, SLOT(setValue(int)) );
0338                     connect( d->erasingInfoDialog, SIGNAL(cancelClicked()), &job, SLOT(cancel()) );
0339                     job.start( medium.diskInfo() );
0340                     d->erasingInfoDialog->exec();
0341                 }
0342             }
0343             else {
0344                 qDebug() << "starting devicehandler: empty DVD+RW where a non-empty was requested.";
0345                 continueWaiting();
0346             }
0347         }
0348         else {
0349             //
0350             // We have a DVD+RW medium which is already preformatted
0351             //
0352             if( d->wantedMediaState == K3b::Device::STATE_EMPTY ) {
0353                 if ( d->wantedMinMediaSize <= medium.diskInfo().capacity() ||
0354                      IsOverburnAllowed( d->wantedMinMediaSize, medium.diskInfo().capacity() ) ) {
0355                     // check if the media contains a filesystem
0356                     K3b::Iso9660 isoF( d->device );
0357                     bool hasIso = isoF.open();
0358 
0359                     if( formatWithoutAsking ||
0360                         !hasIso ||
0361                         KMessageBox::warningContinueCancel( parentWidgetToUse(),
0362                                                             i18n("Found %1 medium in %2 - %3. "
0363                                                                  "Should it be overwritten?",
0364                                                                  QString("DVD+RW"),
0365                                                                  d->device->vendor(),
0366                                                                  d->device->description()),
0367                                                             i18n("Found %1",QString("DVD+RW")),
0368                                                             KStandardGuiItem::overwrite(),
0369                                                             KGuiItem(i18n("&Eject"), "media-eject") ) == KMessageBox::Continue ) {
0370                         finishWaiting( K3b::Device::MEDIA_DVD_PLUS_RW );
0371                     }
0372                     else {
0373                         qDebug() << "starting devicehandler: no DVD+RW overwrite";
0374                         K3b::eject( d->device );
0375                         continueWaiting();
0376                     }
0377                 }
0378                 else {
0379                     qDebug() << "starting devicehandler: DVD+RW too small";
0380                     continueWaiting();
0381                 }
0382             }
0383 
0384             //
0385             // We want a DVD+RW not necessarily empty. No problem, just use this one. Because incomplete and complete
0386             // are handled the same everywhere (isofs is grown).
0387             //
0388             else if ( d->wantedMinMediaSize <= medium.actuallyRemainingSize() ||
0389                       IsOverburnAllowed( d->wantedMinMediaSize, medium.diskInfo().capacity(), medium.actuallyUsedCapacity() ) ) {
0390                 finishWaiting( K3b::Device::MEDIA_DVD_PLUS_RW );
0391             }
0392             else {
0393                 qDebug() << "starting devicehandler: DVD+RW too small";
0394                 continueWaiting();
0395             }
0396         }
0397     } // --- DVD+RW --------
0398 
0399 
0400     // /////////////////////////////////////////////////////////////
0401     //
0402     // DVD-RW handling
0403     //
0404     // /////////////////////////////////////////////////////////////
0405 
0406     //
0407     // DVD-RW in sequential mode can be empty. DVD-RW in restricted overwrite mode is always complete.
0408     //
0409     else if( (d->wantedMediaType & (K3b::Device::MEDIA_DVD_RW|
0410                                     K3b::Device::MEDIA_DVD_RW_SEQ|
0411                                     K3b::Device::MEDIA_DVD_RW_OVWR) ) &&
0412              (medium.diskInfo().mediaType() & (K3b::Device::MEDIA_DVD_RW|
0413                                                K3b::Device::MEDIA_DVD_RW_SEQ|
0414                                                K3b::Device::MEDIA_DVD_RW_OVWR) ) ) {
0415 
0416         qDebug() << "------ found DVD-R(W) as wanted.";
0417 
0418         // we format in the following cases:
0419         // seq. incr. and not empty and empty requested
0420         // seq. incr. and restr. overwri. requested
0421         // restr. ovw. and seq. incr. requested
0422 
0423         // we have exactly what was requested (K3b never requests a specific
0424         // size for read-only cases, thus using remainingSize() is perfectly fine)
0425         if( (d->wantedMediaType & medium.diskInfo().mediaType()) &&
0426             (d->wantedMediaState & medium.diskInfo().diskState()) &&
0427             ( d->wantedMinMediaSize <= medium.actuallyRemainingSize() ||
0428               IsOverburnAllowed( d->wantedMinMediaSize, medium.diskInfo().capacity(), medium.actuallyUsedCapacity() ) ) ) {
0429             finishWaiting( medium.diskInfo().mediaType() );
0430         }
0431 
0432         // DVD-RW in restr. overwrite may just be overwritten
0433         else if( (medium.diskInfo().mediaType() & K3b::Device::MEDIA_DVD_RW_OVWR) &&
0434                  (d->wantedMediaType & K3b::Device::MEDIA_DVD_RW_OVWR) ) {
0435             if( d->wantedMediaState == K3b::Device::STATE_EMPTY &&
0436                 ( d->wantedMinMediaSize <= medium.diskInfo().capacity() ||
0437                   IsOverburnAllowed( d->wantedMinMediaSize, medium.diskInfo().capacity() ) ) ) {
0438 
0439                 qDebug() << "------ DVD-RW restricted overwrite.";
0440 
0441                 // check if the media contains a filesystem
0442                 K3b::Iso9660 isoF( d->device );
0443                 bool hasIso = isoF.open();
0444 
0445                 if( formatWithoutAsking ||
0446                     !hasIso ||
0447                     KMessageBox::warningContinueCancel( parentWidgetToUse(),
0448                                                         i18n("Found %1 medium in %2 - %3. "
0449                                                              "Should it be overwritten?",
0450                                                              K3b::Device::mediaTypeString(medium.diskInfo().mediaType()),
0451                                                              d->device->vendor(),
0452                                                              d->device->description()),
0453                                                         i18n("Found %1",QString("DVD-RW")),
0454                                                         KStandardGuiItem::overwrite(),
0455                                                         KGuiItem(i18n("&Eject"), "media-eject")) == KMessageBox::Continue ) {
0456                     finishWaiting( K3b::Device::MEDIA_DVD_RW_OVWR );
0457                 }
0458                 else {
0459                     qDebug() << "starting devicehandler: no DVD-RW overwrite.";
0460                     K3b::eject( d->device );
0461                     continueWaiting();
0462                 }
0463             }
0464 
0465             // no need to check the size here. K3b never asks for non-empty media by size
0466             else if( !(d->wantedMediaState & K3b::Device::STATE_EMPTY ) ) {
0467                 // check if the media contains a filesystem
0468                 K3b::Iso9660 isoF( d->device );
0469                 bool hasIso = isoF.open();
0470 
0471                 if( hasIso ) {
0472                     finishWaiting( K3b::Device::MEDIA_DVD_RW_OVWR );
0473                 }
0474                 else {
0475                     qDebug() << "starting devicehandler: empty DVD-RW where a non-empty was requested.";
0476                     continueWaiting();
0477                 }
0478             }
0479 
0480             //
0481             // We want a DVD-RW overwrite not necessarily empty. No problem, just use this one. Because incomplete and complete
0482             // are handled the same everywhere (isofs is grown).
0483             //
0484             else if ( d->wantedMinMediaSize <= medium.actuallyRemainingSize() ||
0485                       IsOverburnAllowed( d->wantedMinMediaSize, medium.diskInfo().capacity(), medium.actuallyUsedCapacity() ) ) {
0486                 finishWaiting( K3b::Device::MEDIA_DVD_RW_OVWR );
0487             }
0488             else {
0489                 qDebug() << "starting devicehandler: DVD-RW too small";
0490                 continueWaiting();
0491             }
0492         }
0493 
0494         // formatting
0495         else if( ( (d->wantedMediaType & K3b::Device::MEDIA_DVD_RW_OVWR) &&
0496                    (medium.diskInfo().mediaType() & K3b::Device::MEDIA_DVD_RW_SEQ) &&
0497                    !(d->wantedMediaType & K3b::Device::MEDIA_DVD_RW_SEQ) ) ||
0498 
0499                  ( (d->wantedMediaType & K3b::Device::MEDIA_DVD_RW_SEQ) &&
0500                    (medium.diskInfo().mediaType() & K3b::Device::MEDIA_DVD_RW_OVWR) &&
0501                    !(d->wantedMediaType & K3b::Device::MEDIA_DVD_RW_OVWR) ) ||
0502 
0503                  ( (d->wantedMediaType & K3b::Device::MEDIA_DVD_RW_SEQ) &&
0504                    (medium.diskInfo().mediaType() & K3b::Device::MEDIA_DVD_RW_SEQ) &&
0505                    (d->wantedMediaState & K3b::Device::STATE_EMPTY) &&
0506                    (medium.diskInfo().diskState() != K3b::Device::STATE_EMPTY) ) ) {
0507 
0508             qDebug() << "------ DVD-RW needs to be formatted.";
0509 
0510             if( formatWithoutAsking ||
0511                 KMessageBox::warningContinueCancel( parentWidgetToUse(),
0512                                                     i18n("Found %1 medium in %2 - %3. "
0513                                                          "Should it be formatted?",
0514                                                          K3b::Device::mediaTypeString(medium.diskInfo().mediaType()),
0515                                                          d->device->vendor(),
0516                                                          d->device->description()),
0517                                                     i18n("Found %1",QString("DVD-RW")),
0518                                                     KGuiItem(i18n("&Format"), "tools-media-optical-format"),
0519                                                     KGuiItem(i18n("&Eject"), "media-eject")) == KMessageBox::Continue ) {
0520 
0521                 qDebug() << "------ formatting DVD-RW.";
0522 
0523                 prepareErasingDialog();
0524 
0525                 K3b::DvdFormattingJob job( this );
0526                 job.setDevice( d->device );
0527                 // we prefer the current mode of the media if no special mode has been requested
0528                 job.setMode( ( (d->wantedMediaType & K3b::Device::MEDIA_DVD_RW_SEQ) &&
0529                                (d->wantedMediaType & K3b::Device::MEDIA_DVD_RW_OVWR) )
0530                              ? ( medium.diskInfo().mediaType() == K3b::Device::MEDIA_DVD_RW_OVWR
0531                                  ? K3b::WritingModeRestrictedOverwrite
0532                                  : K3b::WritingModeIncrementalSequential )
0533                              : ( (d->wantedMediaType & K3b::Device::MEDIA_DVD_RW_SEQ)
0534                                  ? K3b::WritingModeIncrementalSequential
0535                                  : K3b::WritingModeRestrictedOverwrite ) );
0536                 job.setFormattingMode( FormattingQuick );
0537                 job.setForce( false );
0538                 job.setForceNoEject(true);
0539 
0540                 d->erasingInfoDialog->reset();
0541                 d->erasingInfoDialog->setLabelText( i18n("Formatting DVD-RW") );
0542                 d->erasingInfoDialog->setRange( 0, 100 );
0543                 connect( &job, SIGNAL(finished(bool)), this, SLOT(slotErasingFinished(bool)) );
0544                 connect( &job, SIGNAL(percent(int)), d->erasingInfoDialog, SLOT(setValue(int)) );
0545                 connect( d->erasingInfoDialog, SIGNAL(cancelClicked()), &job, SLOT(cancel()) );
0546                 job.start( medium.diskInfo() );
0547                 d->erasingInfoDialog->exec();
0548             }
0549             else {
0550                 qDebug() << "starting devicehandler: no DVD-RW formatting.";
0551                 K3b::eject( d->device );
0552                 continueWaiting();
0553             }
0554         }
0555         else {
0556             qDebug() << "------ nothing useful found.";
0557             continueWaiting();
0558         }
0559     } // --- DVD-RW ------
0560 
0561 
0562     // /////////////////////////////////////////////////////////////
0563     //
0564     // CD-RW handling
0565     //
0566     // /////////////////////////////////////////////////////////////
0567 
0568     // format CD-RW
0569     else if( medium.diskInfo().mediaType() == Device::MEDIA_CD_RW &&
0570              (d->wantedMediaType & medium.diskInfo().mediaType()) &&
0571              (d->wantedMediaState & K3b::Device::STATE_EMPTY) &&
0572              !medium.diskInfo().empty() &&
0573              medium.diskInfo().rewritable() ) {
0574 
0575         if( formatWithoutAsking ||
0576             KMessageBox::questionTwoActions(parentWidgetToUse(),
0577                                             i18n("Found rewritable medium in %1 - %2. "
0578                                                  "Should it be erased?",d->device->vendor(),d->device->description()),
0579                                             i18n("Found Rewritable Disk"),
0580                                             KGuiItem(i18n("E&rase"), "tools-media-optical-erase"),
0581                                             KGuiItem(i18n("&Eject"), "media-eject") ) == KMessageBox::PrimaryAction ) {
0582 
0583 
0584             prepareErasingDialog();
0585 
0586             // start a k3bblankingjob
0587             d->erasingInfoDialog->reset();
0588             d->erasingInfoDialog->setLabelText( i18n("Erasing CD-RW") );
0589             d->erasingInfoDialog->setRange( 0, 0 );
0590 
0591             // the user may be using cdrdao for erasing as cdrecord does not work
0592             WritingApp erasingApp = K3b::WritingAppAuto;
0593             if( KSharedConfig::openConfig()->group( QStringLiteral("General Options") ).readEntry( "Show advanced GUI", false ) ) {
0594                 erasingApp = K3b::writingAppFromString( KSharedConfig::openConfig()->group( QStringLiteral("CDRW Erasing") ).readEntry( "writing_app" ) );
0595             }
0596 
0597             K3b::BlankingJob job( this );
0598             job.setDevice( d->device );
0599             job.setFormattingMode( FormattingQuick );
0600             job.setForce(true);
0601             job.setForceNoEject(true);
0602             job.setSpeed( 0 ); // Auto
0603             job.setWritingApp( erasingApp );
0604             connect( &job, SIGNAL(finished(bool)), this, SLOT(slotErasingFinished(bool)) );
0605             connect( d->erasingInfoDialog, SIGNAL(cancelClicked()), &job, SLOT(cancel()) );
0606             job.start();
0607             d->erasingInfoDialog->exec();
0608         }
0609         else {
0610             qDebug() << "starting devicehandler: no CD-RW overwrite.";
0611             K3b::eject( d->device );
0612             continueWaiting();
0613         }
0614     }
0615 
0616     // /////////////////////////////////////////////////////////////
0617     //
0618     // All the non-rewritable media types are handled here
0619     //
0620     // /////////////////////////////////////////////////////////////
0621 
0622     // we have exactly what was requested (K3b never requests a specific
0623     // size for read-only cases, thus using remainingSize() is perfectly fine)
0624     else if( (d->wantedMediaType & medium.diskInfo().mediaType()) &&
0625              (d->wantedMediaState & medium.diskInfo().diskState()) &&
0626              (d->wantedMinMediaSize <= medium.actuallyRemainingSize() ||
0627               IsOverburnAllowed( d->wantedMinMediaSize, medium.diskInfo().capacity(), medium.actuallyUsedCapacity() )) ) {
0628         finishWaiting( medium.diskInfo().mediaType() );
0629     }
0630 
0631     // this is for CD drives that are not able to determine the state of a disk
0632     else if( medium.diskInfo().diskState() == K3b::Device::STATE_UNKNOWN &&
0633              medium.diskInfo().mediaType() == K3b::Device::MEDIA_CD_ROM &&
0634              d->wantedMediaType & K3b::Device::MEDIA_CD_ROM ) {
0635         finishWaiting( medium.diskInfo().mediaType() );
0636     }
0637 
0638     else {
0639         qDebug() << "------ nothing useful found.";
0640         continueWaiting();
0641     }
0642 
0643     // handle queued medium changes
0644     d->blockMediaChange = false;
0645     if( d->mediumChanged > 0 ) {
0646         d->mediumChanged--;
0647         slotMediumChanged( dev );
0648     }
0649 }
0650 
0651 
0652 void K3b::EmptyDiscWaiter::showDialog()
0653 {
0654     // we need to show the dialog if not done already
0655     if( !d->dialogVisible ) {
0656 
0657         KNotification::event( "WaitingForMedium", i18n("Waiting for Medium") );
0658 
0659         d->dialogVisible = true;
0660         //clear it.
0661         setAttribute(Qt::WA_DeleteOnClose,false);
0662         setWindowModality( Qt::NonModal );
0663         setResult( 0 );
0664         show();
0665     }
0666 }
0667 
0668 
0669 void K3b::EmptyDiscWaiter::continueWaiting()
0670 {
0671     showDialog();
0672 }
0673 
0674 
0675 void K3b::EmptyDiscWaiter::slotCancel()
0676 {
0677     qDebug() << "slotCancel() ";
0678     d->canceled = true;
0679     finishWaiting( Device::MEDIA_UNKNOWN );
0680 }
0681 
0682 
0683 void K3b::EmptyDiscWaiter::slotEject()
0684 {
0685     K3b::unmount( d->device );
0686     K3b::Device::eject( d->device );
0687 }
0688 
0689 
0690 void K3b::EmptyDiscWaiter::slotLoad()
0691 {
0692     K3b::Device::load( d->device );
0693 }
0694 
0695 
0696 void K3b::EmptyDiscWaiter::finishWaiting( Device::MediaType type )
0697 {
0698     qDebug() << "finishWaiting() ";
0699 
0700     d->waitingDone = true;
0701     d->result = type;
0702 
0703     if( d->dialogVisible )
0704         hide();
0705 
0706     if( d->inLoop ) {
0707         d->inLoop = false;
0708         qDebug() << "exitLoop ";
0709         emit leaveModality();
0710     }
0711 }
0712 
0713 
0714 void K3b::EmptyDiscWaiter::slotErasingFinished( bool success )
0715 {
0716     if( success ) {
0717         // close the dialog thus ending it's event loop -> back to slotMediumChanged
0718         d->erasingInfoDialog->hide();
0719     }
0720     else {
0721         K3b::Device::eject( d->device );
0722         KMessageBox::error( d->erasingInfoDialog, i18n("Erasing failed.") );
0723         d->erasingInfoDialog->hide(); // close the dialog thus ending it's event loop -> back to slotMediumChanged
0724     }
0725 }
0726 
0727 
0728 K3b::Device::MediaType K3b::EmptyDiscWaiter::wait( K3b::Device::Device* device,
0729                                                    Device::MediaStates mediaState,
0730                                                    Device::MediaTypes mediaType,
0731                                                    const K3b::Msf& minMediaSize,
0732                                                    const QString& message,
0733                                                    QWidget* parent )
0734 {
0735     if( device != 0 ) {
0736         K3b::EmptyDiscWaiter d( device, parent ? parent : qApp->activeWindow() );
0737         return d.waitForDisc( mediaState, mediaType, minMediaSize, message );
0738     }
0739     else {
0740         return Device::MEDIA_UNKNOWN;
0741     }
0742 }
0743 
0744 
0745 void K3b::EmptyDiscWaiter::prepareErasingDialog()
0746 {
0747     // we hide the emptydiskwaiter so the info dialog needs to have the same parent
0748     if( !d->erasingInfoDialog )
0749         d->erasingInfoDialog = new QProgressDialog( parentWidget() );
0750 
0751     //
0752     // hide the dialog
0753     //
0754     if( d->dialogVisible ) {
0755         hide();
0756         d->dialogVisible = false;
0757     }
0758 }
0759 
0760 
0761 QWidget* K3b::EmptyDiscWaiter::parentWidgetToUse()
0762 {
0763     // we might also show dialogs if the discwaiter widget is not visible yet
0764     if( d->dialogVisible )
0765         return this;
0766     else
0767         return parentWidget();
0768 }
0769 
0770 
0771 K3b::Device::MediaType K3b::EmptyDiscWaiter::waitForMedium( K3b::Device::Device* device,
0772                                                             Device::MediaStates mediaState,
0773                                                             Device::MediaTypes mediaType,
0774                                                             const K3b::Msf& minMediaSize,
0775                                                             const QString& message )
0776 {
0777     // this is only needed for the formatting
0778     return wait( device, mediaState, mediaType, minMediaSize, message, d->erasingInfoDialog );
0779 }
0780 
0781 
0782 bool K3b::EmptyDiscWaiter::questionYesNo( const QString& text,
0783                                           const QString& caption,
0784                                           const KGuiItem& buttonYes,
0785                                           const KGuiItem& buttonNo )
0786 {
0787     return ( KMessageBox::questionTwoActions( parentWidgetToUse(),
0788                                               text,
0789                                               caption,
0790                                               buttonYes,
0791                                               buttonNo ) == KMessageBox::PrimaryAction );
0792 }
0793 
0794 
0795 void K3b::EmptyDiscWaiter::blockingInformation( const QString& text,
0796                                                 const QString& caption )
0797 {
0798     KMessageBox::information( this, text, caption );
0799 }
0800 
0801 #include "moc_k3bemptydiscwaiter.cpp"