File indexing completed on 2024-04-28 04:50:20
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 0010 #include "k3baudioprojectconvertingdialog.h" 0011 #include "k3baudioprojectconvertingjob.h" 0012 #include "k3bpatternparser.h" 0013 #include "k3bcddbpatternwidget.h" 0014 #include "k3baudioconvertingoptionwidget.h" 0015 0016 #include "k3baudiodoc.h" 0017 #include "k3baudioview.h" 0018 #include "k3baudiotrack.h" 0019 #include "k3bjobprogressdialog.h" 0020 #include "k3bcore.h" 0021 #include "k3bglobals.h" 0022 #include "k3baudioencoder.h" 0023 0024 #include <KComboBox> 0025 #include <KConfig> 0026 #include <KLocalizedString> 0027 #include <KIO/Global> 0028 #include <KUrlRequester> 0029 #include <KMessageBox> 0030 0031 #include <QDebug> 0032 #include <QDir> 0033 #include <QStringList> 0034 #include <QCheckBox> 0035 #include <QGridLayout> 0036 #include <QHeaderView> 0037 #include <QLabel> 0038 #include <QLayout> 0039 #include <QTabWidget> 0040 #include <QTreeWidget> 0041 0042 #include <KCDDB/CDInfo> 0043 0044 0045 namespace { 0046 KCDDB::CDInfo createCddbEntryFromDoc( K3b::AudioDoc* doc ) 0047 { 0048 KCDDB::CDInfo e; 0049 0050 // global 0051 e.set( KCDDB::Title, doc->title() ); 0052 e.set( KCDDB::Artist, doc->artist() ); 0053 e.set( KCDDB::Comment, doc->cdTextMessage() ); 0054 0055 // tracks 0056 int i = 0; 0057 K3b::AudioTrack* track = doc->firstTrack(); 0058 while( track ) { 0059 e.track( i ).set( KCDDB::Title, track->title() ); 0060 e.track( i ).set( KCDDB::Artist, track->artist() ); 0061 e.track( i ).set( KCDDB::Comment, track->cdTextMessage() ); 0062 0063 track = track->next(); 0064 ++i; 0065 } 0066 0067 return e; 0068 } 0069 } 0070 0071 class K3b::AudioProjectConvertingDialog::Private 0072 { 0073 public: 0074 Private() { 0075 } 0076 0077 QTreeWidget* viewTracks; 0078 QVector<QString> filenames; 0079 QString playlistFilename; 0080 }; 0081 0082 0083 K3b::AudioProjectConvertingDialog::AudioProjectConvertingDialog( K3b::AudioDoc* doc, QWidget *parent ) 0084 : K3b::InteractionDialog( parent, 0085 QString(), 0086 QString(), 0087 START_BUTTON|CANCEL_BUTTON, 0088 START_BUTTON, 0089 "Audio Project Converting" ), // config group 0090 m_doc(doc) 0091 { 0092 d = new Private(); 0093 0094 setupGui(); 0095 0096 setTitle( i18n("Audio Project Conversion"), 0097 i18np("1 track (%2)", "%1 tracks (%2)", 0098 m_doc->numOfTracks(),m_doc->length().toString()) ); 0099 0100 refresh(); 0101 } 0102 0103 0104 K3b::AudioProjectConvertingDialog::~AudioProjectConvertingDialog() 0105 { 0106 delete d; 0107 } 0108 0109 0110 void K3b::AudioProjectConvertingDialog::setupGui() 0111 { 0112 QWidget *frame = mainWidget(); 0113 QGridLayout* Form1Layout = new QGridLayout( frame ); 0114 Form1Layout->setContentsMargins( 0, 0, 0, 0 ); 0115 0116 QTreeWidgetItem* header = new QTreeWidgetItem; 0117 header->setText( 0, i18n( "Filename (relative to base folder)") ); 0118 header->setText( 1, i18n( "Length") ); 0119 header->setText( 2, i18n( "File Size") ); 0120 0121 d->viewTracks = new QTreeWidget( frame ); 0122 d->viewTracks->setSortingEnabled( false ); 0123 d->viewTracks->setAllColumnsShowFocus( true ); 0124 d->viewTracks->setRootIsDecorated( false ); 0125 d->viewTracks->setSelectionMode( QAbstractItemView::NoSelection ); 0126 d->viewTracks->setFocusPolicy( Qt::NoFocus ); 0127 d->viewTracks->setHeaderItem( header ); 0128 d->viewTracks->header()->setStretchLastSection( false ); 0129 d->viewTracks->header()->setSectionResizeMode( 0, QHeaderView::Stretch ); 0130 d->viewTracks->header()->setSectionResizeMode( 1, QHeaderView::ResizeToContents ); 0131 d->viewTracks->header()->setSectionResizeMode( 2, QHeaderView::ResizeToContents ); 0132 0133 QTabWidget* mainTab = new QTabWidget( frame ); 0134 0135 m_optionWidget = new K3b::AudioConvertingOptionWidget( mainTab ); 0136 mainTab->addTab( m_optionWidget, i18n("Settings") ); 0137 0138 0139 // setup filename pattern page 0140 // ------------------------------------------------------------------------------------------- 0141 m_patternWidget = new K3b::CddbPatternWidget( mainTab ); 0142 mainTab->addTab( m_patternWidget, i18n("File Naming") ); 0143 connect( m_patternWidget, SIGNAL(changed()), this, SLOT(refresh()) ); 0144 0145 Form1Layout->addWidget( d->viewTracks, 0, 0 ); 0146 Form1Layout->addWidget( mainTab, 1, 0 ); 0147 Form1Layout->setRowStretch( 0, 1 ); 0148 0149 connect( m_optionWidget, SIGNAL(changed()), this, SLOT(refresh()) ); 0150 } 0151 0152 0153 void K3b::AudioProjectConvertingDialog::slotStartClicked() 0154 { 0155 // check if all filenames differ 0156 if( d->filenames.count() > 1 ) { 0157 bool differ = true; 0158 // the most stupid version to compare but most cds have about 12 tracks 0159 // that's a size where algorithms do not need any optimization! ;) 0160 for( int i = 0; i < d->filenames.count(); ++i ) { 0161 for( int j = i+1; j < d->filenames.count(); ++j ) 0162 if( d->filenames[i] == d->filenames[j] ) { 0163 differ = false; 0164 break; 0165 } 0166 } 0167 0168 if( !differ ) { 0169 KMessageBox::error( this, i18n("Please check the naming pattern. All filenames need to be unique.") ); 0170 return; 0171 } 0172 } 0173 0174 // check if we need to overwrite some files... 0175 QStringList filesToOverwrite; 0176 for( int i = 0; i < d->filenames.count(); ++i ) { 0177 if( QFile::exists( d->filenames[i] ) ) 0178 filesToOverwrite.append( d->filenames[i] ); 0179 } 0180 0181 if( m_optionWidget->createPlaylist() && QFile::exists( d->playlistFilename ) ) 0182 filesToOverwrite.append( d->playlistFilename ); 0183 0184 if( !filesToOverwrite.isEmpty() ) 0185 if( KMessageBox::warningContinueCancelList( this, 0186 i18n("Do you want to overwrite these files?"), 0187 filesToOverwrite, 0188 i18n("Files Exist"), KStandardGuiItem::overwrite() ) 0189 == KMessageBox::Cancel ) 0190 return; 0191 0192 0193 // just generate a fake m_tracks list for now so we can keep most of the methods 0194 // like they are in K3b::AudioRipJob. This way future combination is easier 0195 AudioProjectConvertingJob::Tracks tracksToRip; 0196 if( m_optionWidget->createSingleFile() && !d->filenames.isEmpty() ) { 0197 // Since QMultiMap stores multiple values "from most recently to least recently inserted" 0198 // we will add it in reverse order to rip in ascending order 0199 for( AudioTrack* track = m_doc->lastTrack(); track != 0; track = track->prev() ) 0200 tracksToRip.insert( d->filenames.front(), track->trackNumber() ); 0201 } 0202 else { 0203 for( AudioTrack* track = m_doc->firstTrack(); track != 0; track = track->next() ) 0204 tracksToRip.insert( d->filenames[ track->trackNumber()-1 ], track->trackNumber() ); 0205 } 0206 0207 K3b::AudioEncoder* encoder = m_optionWidget->encoder(); 0208 0209 K3b::JobProgressDialog progressDialog( parentWidget() ); 0210 K3b::AudioProjectConvertingJob job( m_doc, &progressDialog, 0 ); 0211 job.setCddbEntry( createCddbEntryFromDoc( m_doc ) ); 0212 job.setTrackList( tracksToRip ); 0213 job.setEncoder( encoder ); 0214 job.setWriteCueFile( m_optionWidget->createSingleFile() && m_optionWidget->createCueFile() ); 0215 if( m_optionWidget->createPlaylist() ) 0216 job.setWritePlaylist( d->playlistFilename, m_optionWidget->playlistRelativePath() ); 0217 if( encoder ) 0218 job.setFileType( m_optionWidget->extension() ); 0219 0220 hide(); 0221 progressDialog.startJob(&job); 0222 0223 close(); 0224 } 0225 0226 0227 void K3b::AudioProjectConvertingDialog::refresh() 0228 { 0229 #ifdef __GNUC__ 0230 #warning Reuse the code from AudioRippingDialog 0231 #endif 0232 d->viewTracks->clear(); 0233 d->filenames.clear(); 0234 0235 // FIXME: this is bad and needs to be improved 0236 // create a cddb entry from the doc to use in the patternparser 0237 KCDDB::CDInfo cddbEntry = createCddbEntryFromDoc( m_doc ); 0238 0239 QString baseDir = K3b::prepareDir( m_optionWidget->baseDir() ); 0240 0241 QString extension = m_optionWidget->extension(); 0242 0243 KIO::filesize_t overallSize = 0; 0244 0245 if( m_optionWidget->createSingleFile() ) { 0246 QString filename; 0247 long long filesize = 0; 0248 if( m_optionWidget->encoder() == 0 ) { 0249 filesize = m_doc->length().audioBytes() + 44; 0250 } 0251 else { 0252 filesize = m_optionWidget->encoder()->fileSize( extension, m_doc->length() ); 0253 } 0254 0255 if( filesize > 0 ) 0256 overallSize = filesize; 0257 0258 filename = K3b::PatternParser::parsePattern( cddbEntry, 1, 0259 extension, 0260 m_patternWidget->playlistPattern(), 0261 m_patternWidget->replaceBlanks(), 0262 m_patternWidget->blankReplaceString() ); 0263 0264 QTreeWidgetItem* item = new QTreeWidgetItem( d->viewTracks ); 0265 item->setText( 0, filename ); 0266 item->setText( 1, m_doc->length().toString() ); 0267 item->setText( 2, filesize < 0 ? i18n("unknown") : KIO::convertSize( filesize ) ); 0268 0269 d->filenames.append( K3b::fixupPath( baseDir + '/' + filename ) ); 0270 0271 if( m_optionWidget->createCueFile() ) { 0272 QString cueFilename = K3b::PatternParser::parsePattern( cddbEntry, 1, 0273 QLatin1String( "cue" ), 0274 m_patternWidget->playlistPattern(), 0275 m_patternWidget->replaceBlanks(), 0276 m_patternWidget->blankReplaceString() ); 0277 item = new QTreeWidgetItem( d->viewTracks ); 0278 item->setText( 0, cueFilename ); 0279 item->setText( 1, "-" ); 0280 item->setText( 2, "-" ); 0281 } 0282 } 0283 else { 0284 d->filenames.resize( m_doc->numOfTracks() ); 0285 for( AudioTrack* track = m_doc->firstTrack(); track != 0; track = track->next() ) { 0286 long long filesize = 0; 0287 if( m_optionWidget->encoder() == 0 ) { 0288 filesize = track->length().audioBytes() + 44; 0289 } 0290 else { 0291 filesize = m_optionWidget->encoder()->fileSize( extension, track->length() ); 0292 } 0293 0294 if( filesize > 0 ) 0295 overallSize += filesize; 0296 0297 QString filename = K3b::PatternParser::parsePattern( cddbEntry, track->trackNumber(), 0298 extension, 0299 m_patternWidget->filenamePattern(), 0300 m_patternWidget->replaceBlanks(), 0301 m_patternWidget->blankReplaceString() ); 0302 0303 QTreeWidgetItem* item = new QTreeWidgetItem( d->viewTracks ); 0304 item->setText( 0, filename ); 0305 item->setText( 1, track->length().toString() ); 0306 item->setText( 2, filesize < 0 ? i18n("unknown") : KIO::convertSize( filesize ) ); 0307 0308 d->filenames[ track->trackNumber()-1 ] = K3b::fixupPath( baseDir + '/' + filename ); 0309 } 0310 } 0311 0312 // create playlist item 0313 if( m_optionWidget->createPlaylist() ) { 0314 QString filename = K3b::PatternParser::parsePattern( cddbEntry, 1, 0315 QLatin1String( "m3u" ), 0316 m_patternWidget->playlistPattern(), 0317 m_patternWidget->replaceBlanks(), 0318 m_patternWidget->blankReplaceString() ); 0319 0320 QTreeWidgetItem* item = new QTreeWidgetItem( d->viewTracks ); 0321 item->setText( 0, filename ); 0322 item->setText( 1, "-" ); 0323 item->setText( 2, "-" ); 0324 0325 d->playlistFilename = K3b::fixupPath( baseDir + '/' + filename ); 0326 } 0327 0328 if( overallSize > 0 ) 0329 m_optionWidget->setNeededSize( overallSize ); 0330 else 0331 m_optionWidget->setNeededSize( 0 ); 0332 } 0333 0334 0335 void K3b::AudioProjectConvertingDialog::setBaseDir( const QString& path ) 0336 { 0337 m_optionWidget->setBaseDir( path ); 0338 } 0339 0340 0341 void K3b::AudioProjectConvertingDialog::loadSettings( const KConfigGroup& c ) 0342 { 0343 m_optionWidget->loadConfig( c ); 0344 m_patternWidget->loadConfig( c ); 0345 0346 refresh(); 0347 } 0348 0349 0350 void K3b::AudioProjectConvertingDialog::saveSettings( KConfigGroup c ) 0351 { 0352 m_optionWidget->saveConfig( c ); 0353 m_patternWidget->saveConfig( c ); 0354 } 0355 0356 #include "moc_k3baudioprojectconvertingdialog.cpp"