File indexing completed on 2024-05-05 04:51:41
0001 /* 0002 SPDX-FileCopyrightText: 2008 Sebastian Trueg <trueg@k3b.org> 0003 SPDX-FileCopyrightText: 2009 Gustavo Pichorim Boiko <gustavo.boiko@kdemail.net> 0004 SPDX-FileCopyrightText: 1998-2009 Sebastian Trueg <trueg@k3b.org> 0005 0006 SPDX-License-Identifier: GPL-2.0-or-later 0007 */ 0008 0009 #include "k3baudioprojectmodel.h" 0010 #include "k3baudiocdtrackdrag.h" 0011 #include "k3baudiocdtracksource.h" 0012 #include "k3baudiodatasource.h" 0013 #include "k3baudiodoc.h" 0014 #include "k3baudiofile.h" 0015 #include "k3baudiotrack.h" 0016 #include "k3baudiotrackaddingdialog.h" 0017 0018 #include <KUrlMimeData> 0019 #include <KLocalizedString> 0020 0021 #include <QMimeData> 0022 #include <QIcon> 0023 #include <QApplication> 0024 0025 0026 // we have K3b::AudioTracks in the first level and K3b::AudioDataSources in the second level 0027 0028 class K3b::AudioProjectModel::Private 0029 { 0030 public: 0031 Private( K3b::AudioDoc* doc, AudioProjectModel* parent ) 0032 : project( doc ), 0033 q( parent ) { 0034 } 0035 0036 K3b::AudioDoc* project; 0037 0038 void _k_trackAboutToBeAdded( int position ); 0039 void _k_trackAdded(); 0040 void _k_trackAboutToBeRemoved( int position ); 0041 void _k_trackRemoved(); 0042 void _k_sourceAboutToBeAdded( K3b::AudioTrack* parent, int position ); 0043 void _k_sourceAdded(); 0044 void _k_sourceAboutToBeRemoved( K3b::AudioTrack* parent, int position ); 0045 void _k_sourceRemoved(); 0046 0047 private: 0048 AudioProjectModel* q; 0049 }; 0050 0051 0052 void K3b::AudioProjectModel::Private::_k_trackAboutToBeAdded( int position ) 0053 { 0054 if( position >= 0 ) { 0055 q->beginInsertRows( QModelIndex(), position, position ); 0056 } 0057 } 0058 0059 0060 void K3b::AudioProjectModel::Private::_k_trackAdded() 0061 { 0062 q->endInsertRows(); 0063 } 0064 0065 0066 void K3b::AudioProjectModel::Private::_k_trackAboutToBeRemoved( int position ) 0067 { 0068 q->beginRemoveRows( QModelIndex(), position, position ); 0069 } 0070 0071 0072 void K3b::AudioProjectModel::Private::_k_trackRemoved() 0073 { 0074 q->endRemoveRows(); 0075 } 0076 0077 0078 void K3b::AudioProjectModel::Private::_k_sourceAboutToBeAdded( K3b::AudioTrack* parent, int position ) 0079 { 0080 q->beginInsertRows( q->indexForTrack( parent ), position, position ); 0081 } 0082 0083 0084 void K3b::AudioProjectModel::Private::_k_sourceAdded() 0085 { 0086 q->endInsertRows(); 0087 } 0088 0089 0090 void K3b::AudioProjectModel::Private::_k_sourceAboutToBeRemoved( K3b::AudioTrack* parent, int position ) 0091 { 0092 q->beginRemoveRows( q->indexForTrack( parent ), position, position ); 0093 } 0094 0095 0096 void K3b::AudioProjectModel::Private::_k_sourceRemoved() 0097 { 0098 q->endRemoveRows(); 0099 } 0100 0101 0102 K3b::AudioProjectModel::AudioProjectModel( K3b::AudioDoc* doc, QObject* parent ) 0103 : QAbstractItemModel( parent ), 0104 d( new Private( doc, this ) ) 0105 { 0106 connect( doc, SIGNAL(trackAboutToBeRemoved(int)), 0107 this, SLOT(_k_trackAboutToBeRemoved(int)), Qt::DirectConnection ); 0108 connect( doc, SIGNAL(trackRemoved(int)), 0109 this, SLOT(_k_trackRemoved()), Qt::DirectConnection ); 0110 connect( doc, SIGNAL(trackAboutToBeAdded(int)), 0111 this, SLOT(_k_trackAboutToBeAdded(int)), Qt::DirectConnection ); 0112 connect( doc, SIGNAL(trackAdded(int)), 0113 this, SLOT(_k_trackAdded()), Qt::DirectConnection ); 0114 0115 connect( doc, SIGNAL(sourceAboutToBeAdded(K3b::AudioTrack*,int)), 0116 this, SLOT(_k_sourceAboutToBeAdded(K3b::AudioTrack*,int)), Qt::DirectConnection ); 0117 connect( doc, SIGNAL(sourceAdded(K3b::AudioTrack*,int)), 0118 this, SLOT(_k_sourceAdded()), Qt::DirectConnection ); 0119 connect( doc, SIGNAL(sourceAboutToBeRemoved(K3b::AudioTrack*,int)), 0120 this, SLOT(_k_sourceAboutToBeRemoved(K3b::AudioTrack*,int)), Qt::DirectConnection ); 0121 connect( doc, SIGNAL(sourceRemoved(K3b::AudioTrack*,int)), 0122 this, SLOT(_k_sourceRemoved()), Qt::DirectConnection ); 0123 } 0124 0125 0126 K3b::AudioProjectModel::~AudioProjectModel() 0127 { 0128 delete d; 0129 } 0130 0131 0132 K3b::AudioDoc* K3b::AudioProjectModel::project() const 0133 { 0134 return d->project; 0135 } 0136 0137 0138 K3b::AudioTrack* K3b::AudioProjectModel::trackForIndex( const QModelIndex& index ) const 0139 { 0140 if ( index.isValid() ) { 0141 QObject* o = static_cast<QObject*>( index.internalPointer() ); 0142 if ( K3b::AudioTrack* track = qobject_cast<K3b::AudioTrack*>( o ) ) 0143 return track; 0144 } 0145 0146 return 0; 0147 } 0148 0149 0150 QModelIndex K3b::AudioProjectModel::indexForTrack( const K3b::AudioTrack* track ) const 0151 { 0152 return createIndex( track->trackNumber()-1, 0, const_cast<AudioTrack*>( track ) ); 0153 } 0154 0155 0156 K3b::AudioDataSource* K3b::AudioProjectModel::sourceForIndex( const QModelIndex& index ) const 0157 { 0158 if ( index.isValid() ) { 0159 QObject* o = static_cast<QObject*>( index.internalPointer() ); 0160 if ( K3b::AudioDataSource* source = qobject_cast<K3b::AudioDataSource*>( o ) ) 0161 return source; 0162 } 0163 0164 return 0; 0165 } 0166 0167 0168 QModelIndex K3b::AudioProjectModel::indexForSource( K3b::AudioDataSource* source ) const 0169 { 0170 int row = 0; 0171 K3b::AudioDataSource* s = source->track()->firstSource(); 0172 while ( s && s != source ) { 0173 ++row; 0174 } 0175 return createIndex( row, 0, source ); 0176 } 0177 0178 0179 int K3b::AudioProjectModel::columnCount( const QModelIndex& ) const 0180 { 0181 return NumColumns; 0182 } 0183 0184 0185 QVariant K3b::AudioProjectModel::data( const QModelIndex& index, int role ) const 0186 { 0187 if ( index.isValid() ) { 0188 K3b::AudioTrack* track = trackForIndex( index ); 0189 K3b::AudioDataSource* source = sourceForIndex( index ); 0190 0191 // track 0192 if ( !source ) { 0193 switch( index.column() ) { 0194 case TrackNumberColumn: 0195 if( role == Qt::DisplayRole ) { 0196 return track->trackNumber(); 0197 } 0198 break; 0199 0200 case ArtistColumn: 0201 if( role == Qt::DisplayRole || 0202 role == Qt::EditRole ) { 0203 return track->artist(); 0204 } 0205 break; 0206 0207 case TitleColumn: 0208 if( role == Qt::DisplayRole || 0209 role == Qt::EditRole ) { 0210 return track->title(); 0211 } 0212 break; 0213 0214 case TypeColumn: 0215 if( role == Qt::DisplayRole && track->firstSource() ) { 0216 return track->firstSource()->type(); 0217 } 0218 break; 0219 0220 case LengthColumn: 0221 if( role == Qt::DisplayRole ) { 0222 return track->length().toString(); 0223 } 0224 break; 0225 0226 case FilenameColumn: 0227 if( role == Qt::DisplayRole && track->firstSource() ) { 0228 return track->firstSource()->sourceComment(); 0229 } 0230 break; 0231 } 0232 } 0233 0234 // source 0235 else { 0236 if( role == Qt::DisplayRole ) { 0237 switch( index.column() ) { 0238 case TypeColumn: 0239 return source->type(); 0240 0241 case LengthColumn: 0242 return source->length().toString(); 0243 0244 case FilenameColumn: 0245 return source->sourceComment(); 0246 } 0247 } 0248 } 0249 } 0250 0251 // some formatting 0252 switch( role ) { 0253 case Qt::FontRole: 0254 switch( index.column() ) { 0255 case TypeColumn: { 0256 QFont f; 0257 f.setItalic( true ); 0258 return f; 0259 } 0260 case FilenameColumn: { 0261 QFont f; 0262 f.setPointSize( f.pointSize() - 2 ); 0263 return f; 0264 } 0265 } 0266 break; 0267 0268 case Qt::ForegroundRole: 0269 if ( index.column() == FilenameColumn ) { 0270 return QPalette().color( QPalette::Disabled, QPalette::Text ); 0271 } 0272 break; 0273 0274 case Qt::TextAlignmentRole: 0275 if ( index.column() == TypeColumn || 0276 index.column() == LengthColumn ) { 0277 return Qt::AlignHCenter; 0278 } 0279 break; 0280 } 0281 0282 return QVariant(); 0283 } 0284 0285 0286 QVariant K3b::AudioProjectModel::headerData( int section, Qt::Orientation orientation, int role ) const 0287 { 0288 Q_UNUSED( orientation ); 0289 if ( role == Qt::DisplayRole ) { 0290 switch( section ) { 0291 case TrackNumberColumn: 0292 return i18nc("audio track number", "No."); 0293 case ArtistColumn: 0294 return i18n("Artist (CD-Text)"); 0295 case TitleColumn: 0296 return i18n("Title (CD-Text)"); 0297 case TypeColumn: 0298 return i18nc("audio type like mp3 or whatever", "Type"); 0299 case LengthColumn: 0300 return i18nc("audio track length", "Length"); 0301 case FilenameColumn: 0302 return i18n("Filename"); 0303 } 0304 } 0305 0306 return QVariant(); 0307 } 0308 0309 0310 Qt::ItemFlags K3b::AudioProjectModel::flags( const QModelIndex& index ) const 0311 { 0312 if ( index.isValid() ) { 0313 Qt::ItemFlags f = Qt::ItemIsSelectable|Qt::ItemIsEnabled|Qt::ItemIsDragEnabled|Qt::ItemIsDropEnabled; 0314 // only tracks are editable, sources are not 0315 if ( !sourceForIndex( index ) && 0316 ( index.column() == ArtistColumn || 0317 index.column() == TitleColumn ) ) { 0318 f |= Qt::ItemIsEditable; 0319 } 0320 return f; 0321 } 0322 else { 0323 return QAbstractItemModel::flags(index)|Qt::ItemIsDropEnabled; 0324 } 0325 } 0326 0327 0328 QModelIndex K3b::AudioProjectModel::index( int row, int column, const QModelIndex& parent ) const 0329 { 0330 if ( !hasIndex( row, column, parent ) ) { 0331 return QModelIndex(); 0332 } 0333 0334 // source 0335 else if ( parent.isValid() && parent.column() == 0 ) { 0336 if ( K3b::AudioTrack* track = trackForIndex( parent ) ) { 0337 if ( K3b::AudioDataSource* source = track->getSource( row ) ) { 0338 return createIndex( row, column, source ); 0339 } 0340 } 0341 } 0342 0343 // track 0344 else if ( !parent.isValid() && row >= 0 && row < d->project->numOfTracks() ) { 0345 return createIndex( row, column, d->project->getTrack( row+1 ) ); 0346 } 0347 0348 return QModelIndex(); 0349 } 0350 0351 0352 QModelIndex K3b::AudioProjectModel::parent( const QModelIndex& index ) const 0353 { 0354 if ( index.isValid() ) { 0355 if ( K3b::AudioDataSource* source = sourceForIndex( index ) ) { 0356 return indexForTrack( source->track() ); 0357 } 0358 } 0359 0360 return QModelIndex(); 0361 } 0362 0363 0364 int K3b::AudioProjectModel::rowCount( const QModelIndex& parent ) const 0365 { 0366 if ( parent.isValid() ) { 0367 K3b::AudioTrack* track = trackForIndex( parent ); 0368 if ( track != 0 && parent.column() == 0 ) { 0369 // first level 0370 return track->numberSources(); 0371 } 0372 else { 0373 // second level 0374 return 0; 0375 } 0376 } 0377 else { 0378 return d->project->numOfTracks(); 0379 } 0380 } 0381 0382 0383 bool K3b::AudioProjectModel::setData( const QModelIndex& index, const QVariant& value, int role ) 0384 { 0385 if ( K3b::AudioTrack* track = trackForIndex( index ) ) { 0386 if ( role == Qt::EditRole ) { 0387 if ( index.column() == ArtistColumn ) { 0388 if( value.toString() != track->artist() ) { 0389 track->setArtist( value.toString() ); 0390 emit dataChanged( index, index ); 0391 return true; 0392 } 0393 } 0394 else if ( index.column() == TitleColumn ) { 0395 if( value.toString() != track->artist() ) { 0396 track->setTitle( value.toString() ); 0397 emit dataChanged( index, index ); 0398 return true; 0399 } 0400 } 0401 } 0402 } 0403 return false; 0404 } 0405 0406 0407 QMimeData* K3b::AudioProjectModel::mimeData( const QModelIndexList& indexes ) const 0408 { 0409 QMimeData* mime = new QMimeData(); 0410 0411 QSet<K3b::AudioTrack*> tracks; 0412 QSet<K3b::AudioDataSource*> sources; 0413 QList<QUrl> urls; 0414 foreach( const QModelIndex& index, indexes ) { 0415 if ( K3b::AudioTrack* track = trackForIndex( index ) ) { 0416 tracks << track; 0417 K3b::AudioDataSource* source = track->firstSource(); 0418 while ( source ) { 0419 if ( K3b::AudioFile* file = dynamic_cast<K3b::AudioFile*>( source ) ) { 0420 if ( !urls.contains( QUrl::fromLocalFile( file->filename() ) ) ) { 0421 urls.append( QUrl::fromLocalFile( file->filename() ) ); 0422 } 0423 } 0424 source = source->next(); 0425 } 0426 } 0427 else if ( K3b::AudioDataSource* source = sourceForIndex( index ) ) { 0428 sources << source; 0429 if ( K3b::AudioFile* file = dynamic_cast<K3b::AudioFile*>( source ) ) { 0430 if ( !urls.contains( QUrl::fromLocalFile( file->filename() ) ) ) { 0431 urls.append( QUrl::fromLocalFile( file->filename() ) ); 0432 } 0433 } 0434 } 0435 } 0436 mime->setUrls(urls); 0437 0438 // the easy road: encode the pointers 0439 if ( !tracks.isEmpty() ) { 0440 QByteArray trackData; 0441 QDataStream trackDataStream( &trackData, QIODevice::WriteOnly ); 0442 foreach( K3b::AudioTrack* track, tracks ) { 0443 trackDataStream << ( qint64 )track; 0444 } 0445 mime->setData( "application/x-k3baudiotrack", trackData ); 0446 } 0447 if ( !sources.isEmpty() ) { 0448 QByteArray sourceData; 0449 QDataStream sourceDataStream( &sourceData, QIODevice::WriteOnly ); 0450 foreach( K3b::AudioDataSource* source, sources ) { 0451 sourceDataStream << ( qint64 )source; 0452 } 0453 mime->setData( "application/x-k3baudiodatasource", sourceData ); 0454 } 0455 0456 return mime; 0457 } 0458 0459 0460 Qt::DropActions K3b::AudioProjectModel::supportedDragActions() const 0461 { 0462 return Qt::MoveAction; 0463 } 0464 0465 0466 Qt::DropActions K3b::AudioProjectModel::supportedDropActions() const 0467 { 0468 return Qt::CopyAction|Qt::MoveAction; 0469 } 0470 0471 0472 QStringList K3b::AudioProjectModel::mimeTypes() const 0473 { 0474 QStringList s = KUrlMimeData::mimeDataTypes(); 0475 s += AudioCdTrackDrag::mimeDataTypes(); 0476 s += QString::fromLatin1( "application/x-k3baudiotrack" ); 0477 s += QString::fromLatin1( "application/x-k3baudiodatasource" ); 0478 return s; 0479 } 0480 0481 0482 bool K3b::AudioProjectModel::dropMimeData( const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent ) 0483 { 0484 // 0485 // Some hints: 0486 // * parent index is a track 0487 // -> if row == -1 something has been dropped onto the track 0488 // -> if row >= 0 in between two sources of the track 0489 // 0490 // * parent index is a source 0491 // -> something has been dropped onto the source 0492 // 0493 // * parent index is invalid 0494 // -> if row == -1, something has been dropped onto the view 0495 // -> if row >= 0 in between two tracks, i.e. tracks row and row+1 0496 // 0497 0498 // 0499 // Actions we perform: 0500 // * dropping onto a track 0501 // -> add new tracks before the track (except if the track already has multiple sources) 0502 // 0503 // * dropping between tracks 0504 // -> add new tracks after the first track (row) 0505 // 0506 // * dropping onto source 0507 // -> add sources before the source 0508 // 0509 // * dropping onto the view 0510 // -> add new tracks at the end 0511 // 0512 0513 Q_UNUSED( column ); 0514 0515 if ( action == Qt::IgnoreAction ) 0516 return true; 0517 0518 K3b::AudioTrack* dropTrackParent = 0; 0519 K3b::AudioTrack* dropTrackAfter = 0; 0520 K3b::AudioDataSource* dropSourceAfter = 0; 0521 if ( K3b::AudioTrack* track = trackForIndex( parent ) ) { 0522 if ( row >= 0 ) { 0523 dropTrackParent = track; 0524 dropSourceAfter = track->getSource( row-1 ); 0525 } 0526 else { 0527 dropTrackAfter = track->prev(); 0528 } 0529 } 0530 else if ( K3b::AudioDataSource* source = sourceForIndex( parent ) ) { 0531 dropTrackParent = source->track(); 0532 dropSourceAfter = source->prev(); 0533 } 0534 else if ( row >= 0 ) { 0535 dropTrackAfter = d->project->getTrack( row ); 0536 } 0537 else { 0538 dropTrackAfter = d->project->lastTrack(); 0539 } 0540 0541 bool copyItems = ( action == Qt::CopyAction ); 0542 0543 // 0544 // decode data 0545 // 0546 QList<K3b::AudioTrack*> tracks; 0547 QList<K3b::AudioDataSource*> sources; 0548 QList<QUrl> urls; 0549 if ( data->hasFormat( "application/x-k3baudiotrack" ) || 0550 data->hasFormat( "application/x-k3baudiodatasource" )) { 0551 0552 QByteArray trackData = data->data( "application/x-k3baudiotrack" ); 0553 QDataStream trackDataStream( trackData ); 0554 while ( !trackDataStream.atEnd() ) { 0555 qint64 p; 0556 trackDataStream >> p; 0557 tracks << ( K3b::AudioTrack* )p; 0558 } 0559 0560 QByteArray sourceData = data->data( "application/x-k3baudiosource" ); 0561 QDataStream sourceDataStream( sourceData ); 0562 while ( !sourceDataStream.atEnd() ) { 0563 qint64 p; 0564 sourceDataStream >> p; 0565 sources << ( K3b::AudioDataSource* )p; 0566 } 0567 0568 // 0569 // remove all sources which belong to one of the selected tracks since they will be 0570 // moved along with their tracks 0571 // 0572 QList<K3b::AudioDataSource*>::iterator srcIt = sources.begin(); 0573 while( srcIt != sources.end() ) { 0574 if( tracks.contains( ( *srcIt )->track() ) ) 0575 srcIt = sources.erase( srcIt ); 0576 else 0577 ++srcIt; 0578 } 0579 0580 0581 // 0582 // Now move (or copy) all the tracks 0583 // 0584 for( QList<K3b::AudioTrack*>::iterator it = tracks.begin(); it != tracks.end(); ++it ) { 0585 K3b::AudioTrack* track = *it; 0586 if( dropTrackParent ) { 0587 dropTrackParent->merge( copyItems ? track->copy() : track, dropSourceAfter ); 0588 } 0589 else if( dropTrackAfter ) { 0590 if( copyItems ) 0591 track->copy()->moveAfter( dropTrackAfter ); 0592 else 0593 track->moveAfter( dropTrackAfter ); 0594 } 0595 else { 0596 if( copyItems ) 0597 track->copy()->moveAhead( d->project->firstTrack() ); 0598 else 0599 track->moveAhead( d->project->firstTrack() ); 0600 } 0601 } 0602 0603 // 0604 // now move (or copy) the sources 0605 // 0606 for( QList<K3b::AudioDataSource*>::iterator it = sources.begin(); it != sources.end(); ++it ) { 0607 K3b::AudioDataSource* source = *it; 0608 if( dropTrackParent ) { 0609 if( dropSourceAfter ) { 0610 if( copyItems ) 0611 source->copy()->moveAfter( dropSourceAfter ); 0612 else 0613 source->moveAfter( dropSourceAfter ); 0614 } 0615 else { 0616 if( copyItems ) 0617 source->copy()->moveAhead( dropTrackParent->firstSource() ); 0618 else 0619 source->moveAhead( dropTrackParent->firstSource() ); 0620 } 0621 } 0622 else { 0623 // create a new track 0624 K3b::AudioTrack* track = new K3b::AudioTrack( d->project ); 0625 0626 // special case: the source we remove from the track is the last and the track 0627 // will be deleted. 0628 if( !copyItems && dropTrackAfter == source->track() && dropTrackAfter && dropTrackAfter->numberSources() == 1 ) 0629 dropTrackAfter = dropTrackAfter->prev(); 0630 0631 if( copyItems ) 0632 track->addSource( source->copy() ); 0633 else 0634 track->addSource( source ); 0635 0636 if( dropTrackAfter ) { 0637 track->moveAfter( dropTrackAfter ); 0638 dropTrackAfter = track; 0639 } 0640 else { 0641 track->moveAhead( d->project->firstTrack() ); 0642 dropTrackAfter = track; 0643 } 0644 } 0645 } 0646 0647 return true; 0648 } 0649 0650 // 0651 // handle tracks from the audio cd view 0652 // 0653 else if ( AudioCdTrackDrag::canDecode( data ) ) { 0654 qDebug() << "audiocdtrack dropped."; 0655 0656 AudioCdTrackDrag drag = AudioCdTrackDrag::fromMimeData( data ); 0657 0658 // for now we just create one source 0659 foreach( int trackNumber, drag.trackNumbers() ) { 0660 qDebug() << trackNumber << "dropped"; 0661 AudioCdTrackSource* source = new AudioCdTrackSource( drag.toc(), 0662 trackNumber, 0663 drag.cddbEntry().track( trackNumber-1 ).get( KCDDB::Artist ).toString(), 0664 drag.cddbEntry().track( trackNumber-1 ).get( KCDDB::Title ).toString(), 0665 drag.cddbEntry().get( KCDDB::Artist ).toString(), 0666 drag.cddbEntry().get( KCDDB::Title ).toString(), 0667 drag.device() ); 0668 if( dropTrackParent ) { 0669 source->moveAfter( dropSourceAfter ); 0670 if( dropSourceAfter ) 0671 dropSourceAfter = source; 0672 } 0673 else { 0674 AudioTrack* track = new AudioTrack(); 0675 track->setPerformer( drag.cddbEntry().track( trackNumber-1 ).get( KCDDB::Artist ).toString() ); 0676 track->setTitle( drag.cddbEntry().track( trackNumber-1 ).get( KCDDB::Title ).toString() ); 0677 track->addSource( source ); 0678 if( dropTrackAfter ) 0679 track->moveAfter( dropTrackAfter ); 0680 else 0681 d->project->addTrack( track, 0 ); 0682 0683 dropTrackAfter = track; 0684 } 0685 } 0686 } 0687 0688 // 0689 // add new tracks 0690 // 0691 else if ( data->hasUrls() ) { 0692 qDebug() << "url list drop"; 0693 QList<QUrl> urls = KUrlMimeData::urlsFromMimeData( data ); 0694 K3b::AudioTrackAddingDialog::addUrls( urls, d->project, dropTrackAfter, dropTrackParent, dropSourceAfter, qApp->activeWindow() ); 0695 return true; 0696 } 0697 0698 return false; 0699 } 0700 0701 0702 #include "moc_k3baudioprojectmodel.cpp"