File indexing completed on 2024-05-05 04:51:43

0001 /*
0002     SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "k3bdatamultisessionimportdialog.h"
0007 #include "k3bcore.h"
0008 #include "k3bdatadoc.h"
0009 #include "k3btoc.h"
0010 #include "k3bdevice.h"
0011 #include "k3bdevicemanager.h"
0012 #include "k3bdiskinfo.h"
0013 #include "k3biso9660.h"
0014 #include "k3bmedium.h"
0015 #include "k3bmediacache.h"
0016 
0017 #include "../k3bapplication.h"
0018 #include "../k3b.h"
0019 
0020 #include <KIconLoader>
0021 #include <KLocalizedString>
0022 #include <KMessageBox>
0023 
0024 #include <QMap>
0025 #include <QCursor>
0026 #include <QFont>
0027 #include <QDialogButtonBox>
0028 #include <QLabel>
0029 #include <QLayout>
0030 #include <QPushButton>
0031 #include <QTreeWidget>
0032 #include <QVBoxLayout>
0033 
0034 namespace {
0035     class SessionInfo
0036     {
0037     public:
0038         SessionInfo()
0039             : sessionNumber( 0 ),
0040               device( 0 ) {}
0041 
0042         SessionInfo( int num, K3b::Device::Device* dev )
0043             : sessionNumber( num ),
0044               device( dev ) {}
0045 
0046         int sessionNumber;
0047         K3b::Device::Device* device;
0048     };
0049 
0050     typedef QMap<QTreeWidgetItem*, SessionInfo> Sessions;
0051 }
0052 
0053 
0054 class K3b::DataMultisessionImportDialog::Private
0055 {
0056 public:
0057     K3b::DataDoc* doc;
0058     QTreeWidget* sessionView;
0059     QPushButton* okButton;
0060 
0061     Sessions sessions;
0062 };
0063 
0064 
0065 K3b::DataDoc* K3b::DataMultisessionImportDialog::importSession( K3b::DataDoc* doc, QWidget* parent )
0066 {
0067     K3b::DataMultisessionImportDialog dlg( parent );
0068     dlg.importSession( doc );
0069     dlg.exec();
0070     return dlg.d->doc;
0071 }
0072 
0073 
0074 void K3b::DataMultisessionImportDialog::slotOk()
0075 {
0076     Sessions::const_iterator session = d->sessions.constFind( d->sessionView->currentItem() );
0077     if ( session != d->sessions.constEnd() ) {
0078         QApplication::setOverrideCursor( QCursor(Qt::WaitCursor) );
0079 
0080         K3b::Device::Device* dev = session->device;
0081 
0082         //
0083         // Mkisofs does not properly import joliet filenames from an old session
0084         //
0085         // See bug 79215 for details
0086         //
0087         K3b::Iso9660 iso( dev );
0088         if( iso.open() ) {
0089             if( iso.firstRRDirEntry() == 0 && iso.jolietLevel() > 0 )
0090                 KMessageBox::error( this,
0091                                     i18n("<p>K3b found session containing Joliet information for long filenames "
0092                                          "but no Rock Ridge extensions."
0093                                          "<p>The filenames in the imported session will be converted to a restricted "
0094                                          "character set in the new session. This character set is based on the ISO 9660 "
0095                                          "settings in the K3b project. K3b is not able to display these converted filenames yet."),
0096                                     i18n("Session Import Warning") );
0097             iso.close();
0098         }
0099 
0100         if( !d->doc ) {
0101             d->doc = static_cast<K3b::DataDoc*>( k3bappcore->k3bMainWindow()->slotNewDataDoc() );
0102         }
0103 
0104         d->doc->setBurner( dev );
0105         d->doc->importSession( dev, session->sessionNumber );
0106 
0107         QApplication::restoreOverrideCursor();
0108 
0109         done( 0 );
0110     }
0111 }
0112 
0113 
0114 void K3b::DataMultisessionImportDialog::slotCancel()
0115 {
0116     reject();
0117 }
0118 
0119 
0120 void K3b::DataMultisessionImportDialog::importSession( K3b::DataDoc* doc )
0121 {
0122     d->doc = doc;
0123     updateMedia();
0124     slotSelectionChanged();
0125 }
0126 
0127 
0128 void K3b::DataMultisessionImportDialog::updateMedia()
0129 {
0130     d->sessionView->clear();
0131     d->sessions.clear();
0132 
0133     QList<K3b::Device::Device*> devices = k3bcore->deviceManager()->allDevices();
0134 
0135     bool haveMedium = false;
0136     for( QList<K3b::Device::Device *>::const_iterator it = devices.constBegin();
0137          it != devices.constEnd(); ++it ) {
0138         K3b::Medium medium = k3bappcore->mediaCache()->medium( *it );
0139 
0140         if ( medium.diskInfo().mediaType() & K3b::Device::MEDIA_WRITABLE &&
0141              medium.diskInfo().diskState() == K3b::Device::STATE_INCOMPLETE ) {
0142             addMedium( medium );
0143             haveMedium = true;
0144         }
0145         else if ( !medium.diskInfo().empty() &&
0146                   medium.diskInfo().mediaType() & ( K3b::Device::MEDIA_DVD_PLUS_RW|K3b::Device::MEDIA_DVD_RW_OVWR ) ) {
0147             addMedium( medium );
0148             haveMedium = true;
0149         }
0150     }
0151 
0152     if ( !haveMedium ) {
0153         QTreeWidgetItem* noMediaItem = new QTreeWidgetItem( d->sessionView );
0154         QFont fnt( noMediaItem->font(0) );
0155         fnt.setItalic( true );
0156         noMediaItem->setText( 0, i18n( "Please insert an appendable medium" ) );
0157         noMediaItem->setFont( 0, fnt );
0158     }
0159     else if( QTreeWidgetItem* firstMedium = d->sessionView->topLevelItem(0) ) {
0160         if( firstMedium->childCount() > 0 )
0161             d->sessionView->setCurrentItem( firstMedium->child( firstMedium->childCount()-1 ) );
0162         else
0163             d->sessionView->setCurrentItem( firstMedium );
0164     }
0165 
0166     d->sessionView->setEnabled( haveMedium );
0167 }
0168 
0169 
0170 void K3b::DataMultisessionImportDialog::addMedium( const K3b::Medium& medium )
0171 {
0172     QTreeWidgetItem* mediumItem = new QTreeWidgetItem( d->sessionView );
0173     QFont fnt( mediumItem->font(0) );
0174     fnt.setBold( true );
0175     mediumItem->setText( 0, medium.shortString() );
0176     mediumItem->setFont( 0, fnt );
0177     mediumItem->setIcon( 0, QIcon::fromTheme("media-optical-recordable") );
0178 
0179     const K3b::Device::Toc& toc = medium.toc();
0180     QTreeWidgetItem* sessionItem = 0;
0181     int lastSession = 0;
0182     for ( K3b::Device::Toc::const_iterator it = toc.begin(); it != toc.end(); ++it ) {
0183         const K3b::Device::Track& track = *it;
0184 
0185         if( track.session() != lastSession ) {
0186             lastSession = track.session();
0187             QString sessionInfo;
0188             if ( track.type() == K3b::Device::Track::TYPE_DATA ) {
0189                 K3b::Iso9660 iso( medium.device(), track.firstSector().lba() );
0190                 if ( iso.open() ) {
0191                     sessionInfo = iso.primaryDescriptor().volumeId;
0192                 }
0193             }
0194             else {
0195                 int numAudioTracks = 1;
0196                 while ( it != toc.end()
0197                         && ( *it ).type() == K3b::Device::Track::TYPE_AUDIO
0198                         && ( *it ).session() == lastSession ) {
0199                     ++it;
0200                     ++numAudioTracks;
0201                 }
0202                 --it;
0203                 sessionInfo = i18np("1 audio track", "%1 audio tracks", numAudioTracks );
0204             }
0205 
0206             sessionItem = new QTreeWidgetItem( mediumItem, sessionItem );
0207             sessionItem->setText( 0, i18n( "Session %1", lastSession )
0208                                      + ( sessionInfo.isEmpty() ? QString() : " (" + sessionInfo + ')' ) );
0209             if ( track.type() == K3b::Device::Track::TYPE_AUDIO )
0210                 sessionItem->setIcon( 0, QIcon::fromTheme( "audio-x-generic" ) );
0211             else
0212                 sessionItem->setIcon( 0, QIcon::fromTheme( "application-x-tar" ) );
0213 
0214             d->sessions.insert( sessionItem, SessionInfo( lastSession, medium.device() ) );
0215         }
0216     }
0217 
0218     if( 0 == lastSession ) {
0219         // the medium item in case we have no session info (will always use the last session)
0220         d->sessions.insert( mediumItem, SessionInfo( 0, medium.device() ) );
0221     }
0222     else {
0223         // we have a session item, there is no need to select the medium as a whole
0224         mediumItem->setFlags( mediumItem->flags() ^ Qt::ItemIsSelectable );
0225     }
0226 
0227     mediumItem->setExpanded( true );
0228 }
0229 
0230 
0231 void K3b::DataMultisessionImportDialog::slotSelectionChanged()
0232 {
0233     Sessions::const_iterator session = d->sessions.constFind( d->sessionView->currentItem() );
0234     if ( session != d->sessions.constEnd() ) {
0235         d->okButton->setEnabled( true );
0236     }
0237     else {
0238         d->okButton->setEnabled( false );
0239     }
0240 }
0241 
0242 
0243 K3b::DataMultisessionImportDialog::DataMultisessionImportDialog( QWidget* parent )
0244     : QDialog( parent),
0245       d( new Private() )
0246 {
0247     setModal(true);
0248     setWindowTitle(i18n("Session Import"));
0249     QVBoxLayout* layout = new QVBoxLayout( this );
0250 
0251     QLabel* label = new QLabel( i18n( "Please select a session to import." ), this );
0252     d->sessionView = new QTreeWidget( this );
0253     d->sessionView->setHeaderHidden( true );
0254     d->sessionView->setItemsExpandable( false );
0255     d->sessionView->setRootIsDecorated( false );
0256 
0257     QDialogButtonBox* buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this );
0258     d->okButton = buttonBox->button( QDialogButtonBox::Ok );
0259     connect( buttonBox, SIGNAL(accepted()), SLOT(accept()) );
0260     connect( buttonBox, SIGNAL(rejected()), SLOT(reject()) );
0261 
0262     layout->addWidget( label );
0263     layout->addWidget( d->sessionView );
0264     layout->addWidget( buttonBox );
0265 
0266     connect( k3bappcore->mediaCache(), SIGNAL(mediumChanged(K3b::Device::Device*)),
0267              this, SLOT(updateMedia()) );
0268     connect( d->sessionView, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
0269              this, SLOT(slotSelectionChanged()) );
0270     connect(d->sessionView, SIGNAL(itemActivated(QTreeWidgetItem*,int)), SLOT(slotOk()) );
0271     connect(d->okButton, SIGNAL(clicked()), this, SLOT(slotOk()));
0272     connect(buttonBox->button(QDialogButtonBox::Cancel), SIGNAL(clicked()), this, SLOT(slotCancel()));
0273 }
0274 
0275 
0276 K3b::DataMultisessionImportDialog::~DataMultisessionImportDialog()
0277 {
0278     delete d;
0279 }
0280 
0281 #include "moc_k3bdatamultisessionimportdialog.cpp"