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"