File indexing completed on 2024-04-28 04:50:21
0001 /* 0002 SPDX-FileCopyrightText: 2011 Michal Malek <michalm@jabster.pl> 0003 SPDX-FileCopyrightText: 1998-2008 Sebastian Trueg <trueg@k3b.org> 0004 0005 SPDX-License-Identifier: GPL-2.0-or-later 0006 */ 0007 0008 #include "k3baudiotrackmodel.h" 0009 #include "k3baudiocdtrackdrag.h" 0010 0011 #include "k3bmedium.h" 0012 #include "k3bcdtext.h" 0013 0014 #include <KLocalizedString> 0015 0016 #include <KCDDB/CDInfo> 0017 0018 #include <QMimeData> 0019 #include <QFont> 0020 0021 Q_DECLARE_METATYPE( K3b::Medium ) 0022 Q_DECLARE_METATYPE( K3b::Msf ) 0023 0024 0025 class K3b::AudioTrackModel::Private 0026 { 0027 public: 0028 K3b::Medium medium; 0029 KCDDB::CDInfo cddbCache; 0030 0031 QVector<bool> itemCheckedList; 0032 0033 QString getField( KCDDB::Type field ) const; 0034 QString getField( KCDDB::Type field, int trackIndex ) const; 0035 }; 0036 0037 0038 QString K3b::AudioTrackModel::Private::getField( KCDDB::Type field ) const 0039 { 0040 QString s = cddbCache.get( field ).toString(); 0041 if ( s.isEmpty() ) { 0042 s = medium.cddbInfo().get( field ).toString(); 0043 } 0044 if ( s.isEmpty() ) { 0045 switch( field ) { 0046 case KCDDB::Title: 0047 s = medium.cdText().title(); 0048 break; 0049 case KCDDB::Artist: 0050 s = medium.cdText().performer(); 0051 break; 0052 case KCDDB::Comment: 0053 s = medium.cdText().message(); 0054 break; 0055 default: 0056 break; 0057 } 0058 } 0059 0060 return s; 0061 } 0062 0063 0064 QString K3b::AudioTrackModel::Private::getField( KCDDB::Type field, int trackIndex ) const 0065 { 0066 QString s = cddbCache.track( trackIndex ).get( field ).toString(); 0067 if ( s.isEmpty() ) { 0068 s = medium.cddbInfo().track( trackIndex ).get( field ).toString(); 0069 } 0070 if ( s.isEmpty() ) { 0071 switch( field ) { 0072 case KCDDB::Title: 0073 s = medium.cdText().track( trackIndex ).title(); 0074 break; 0075 case KCDDB::Artist: 0076 s = medium.cdText().track( trackIndex ).performer(); 0077 break; 0078 case KCDDB::Comment: 0079 s = medium.cdText().track( trackIndex ).message(); 0080 break; 0081 default: 0082 break; 0083 } 0084 } 0085 0086 return s; 0087 } 0088 0089 0090 0091 K3b::AudioTrackModel::AudioTrackModel( QObject* parent ) 0092 : QAbstractItemModel( parent ), 0093 d( new Private() ) 0094 { 0095 } 0096 0097 0098 K3b::AudioTrackModel::~AudioTrackModel() 0099 { 0100 delete d; 0101 } 0102 0103 0104 void K3b::AudioTrackModel::setMedium( const K3b::Medium& medium ) 0105 { 0106 beginResetModel(); 0107 d->medium = medium; 0108 d->itemCheckedList.resize( d->medium.toc().count() ); 0109 for ( int i = 0; i < d->medium.toc().count(); ++i ) { 0110 if( d->medium.toc()[i].type() == K3b::Device::Track::TYPE_AUDIO ) 0111 d->itemCheckedList[i] = true; 0112 else 0113 d->itemCheckedList[i] = false; 0114 } 0115 endResetModel(); 0116 } 0117 0118 0119 void K3b::AudioTrackModel::setCddbInfo( const KCDDB::CDInfo& data ) 0120 { 0121 beginResetModel(); 0122 d->cddbCache = data; 0123 endResetModel(); 0124 } 0125 0126 0127 KCDDB::CDInfo K3b::AudioTrackModel::cddbInfo() const 0128 { 0129 return d->cddbCache; 0130 } 0131 0132 0133 K3b::Medium K3b::AudioTrackModel::medium() const 0134 { 0135 return d->medium; 0136 } 0137 0138 0139 int K3b::AudioTrackModel::columnCount( const QModelIndex& parent ) const 0140 { 0141 Q_UNUSED( parent ); 0142 return NumColumns; 0143 } 0144 0145 0146 QVariant K3b::AudioTrackModel::headerData( int section, Qt::Orientation orientation, int role ) const 0147 { 0148 Q_UNUSED( orientation ); 0149 0150 if ( role == Qt::DisplayRole ) { 0151 switch( section ) { 0152 case TrackNumberColumn: 0153 return i18nc( "audio track number", "No." ); 0154 case ArtistColumn: 0155 return i18n( "Artist" ); 0156 case TitleColumn: 0157 return i18nc( "audio track title", "Title" ); 0158 case LengthColumn: 0159 return i18n( "Length" ); 0160 } 0161 } 0162 0163 return QVariant(); 0164 } 0165 0166 0167 QVariant K3b::AudioTrackModel::data( const QModelIndex& index, int role ) const 0168 { 0169 // qDebug() << index << role; 0170 0171 // FIXME: add a cache for all the values that can be changed (maybe a local KCDDB::CDInfo) 0172 // which will then be the first choice for all values 0173 0174 int trackIndex = index.row(); 0175 0176 switch( role ) { 0177 case MediumRole: 0178 return QVariant::fromValue( d->medium ); 0179 0180 case TrackNumberRole: 0181 return trackIndex+1; 0182 0183 case ArtistRole: 0184 return d->getField( KCDDB::Artist, trackIndex ); 0185 0186 case TitleRole: 0187 return d->getField( KCDDB::Title, trackIndex ); 0188 0189 case CommentRole: 0190 return d->getField( KCDDB::Comment, trackIndex ); 0191 0192 case LengthRole: 0193 return QVariant::fromValue( d->medium.toc()[trackIndex].length() ); 0194 0195 case Qt::DisplayRole: 0196 case Qt::EditRole: 0197 switch( index.column() ) { 0198 case TrackNumberColumn: 0199 return trackIndex+1; 0200 case ArtistColumn: 0201 return d->getField( KCDDB::Artist, trackIndex ); 0202 case TitleColumn: 0203 { 0204 if( d->medium.toc()[trackIndex].type() == Device::Track::TYPE_DATA ) 0205 return i18n( "Data Track" ); 0206 else 0207 return d->getField( KCDDB::Title, trackIndex ); 0208 } 0209 case LengthColumn: 0210 return d->medium.toc()[trackIndex].length().toString(); 0211 } 0212 break; 0213 0214 case Qt::CheckStateRole: 0215 if ( index.column() == TrackNumberColumn ) { 0216 return trackChecked( trackIndex ) ? Qt::Checked : Qt::Unchecked; 0217 } 0218 break; 0219 0220 case Qt::TextAlignmentRole: 0221 if ( index.column() == LengthColumn ) { 0222 return Qt::AlignHCenter; 0223 } 0224 break; 0225 0226 case Qt::FontRole: 0227 if( d->medium.toc()[trackIndex].type() == Device::Track::TYPE_DATA ) 0228 { 0229 QFont font; 0230 font.setItalic( true ); 0231 return font; 0232 } 0233 } 0234 0235 return QVariant(); 0236 } 0237 0238 0239 Qt::ItemFlags K3b::AudioTrackModel::flags( const QModelIndex& index ) const 0240 { 0241 Qt::ItemFlags f = Qt::ItemFlags(); 0242 0243 if ( index.isValid() && index.row() >= 0 && index.row() < d->medium.toc().count() && 0244 d->medium.toc()[index.row()].type() == K3b::Device::Track::TYPE_AUDIO ) { 0245 0246 f |= Qt::ItemIsSelectable | Qt::ItemIsDragEnabled | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable; 0247 0248 switch( index.column() ) { 0249 case ArtistColumn: 0250 case TitleColumn: 0251 f |= Qt::ItemIsEditable; 0252 break; 0253 } 0254 } 0255 0256 return f; 0257 } 0258 0259 0260 QModelIndex K3b::AudioTrackModel::index( int row, int column, const QModelIndex& parent ) const 0261 { 0262 if ( !parent.isValid() && 0263 row < d->medium.toc().count() && 0264 column < NumColumns ) { 0265 return createIndex( row, column ); 0266 } 0267 else { 0268 return QModelIndex(); 0269 } 0270 } 0271 0272 0273 QModelIndex K3b::AudioTrackModel::parent( const QModelIndex& ) const 0274 { 0275 return QModelIndex(); 0276 } 0277 0278 0279 int K3b::AudioTrackModel::rowCount( const QModelIndex& parent ) const 0280 { 0281 if ( !parent.isValid() ) { 0282 // FIXME: only use audio tracks 0283 return d->medium.toc().count(); 0284 } 0285 else { 0286 return 0; 0287 } 0288 } 0289 0290 0291 void K3b::AudioTrackModel::setTrackChecked( int track, bool checked ) 0292 { 0293 if ( track >= 0 && track < d->itemCheckedList.count() ) { 0294 d->itemCheckedList[track] = checked; 0295 emit dataChanged( index( track, TrackNumberColumn ), index( track, TrackNumberColumn ) ); 0296 } 0297 } 0298 0299 0300 bool K3b::AudioTrackModel::trackChecked( int trackIndex ) const 0301 { 0302 if ( trackIndex >= 0 && 0303 trackIndex < d->medium.toc().count() ) { 0304 return d->itemCheckedList[trackIndex]; 0305 } 0306 else { 0307 return false; 0308 } 0309 } 0310 0311 0312 QList<int> K3b::AudioTrackModel::checkedTrackIndices() const 0313 { 0314 QList<int> l; 0315 for ( int i = 0; i < d->itemCheckedList.count(); ++i ) { 0316 if ( d->itemCheckedList[i] ) { 0317 l.append( i ); 0318 } 0319 } 0320 return l; 0321 } 0322 0323 0324 bool K3b::AudioTrackModel::setData( const QModelIndex& index, const QVariant& value, int role ) 0325 { 0326 if ( index.isValid() ) { 0327 switch ( role ) { 0328 case Qt::EditRole: 0329 switch( index.column() ) { 0330 case ArtistColumn: 0331 d->cddbCache.track( index.row() ).set( KCDDB::Artist, value ); 0332 emit dataChanged( index, index ); 0333 return true; 0334 0335 case TitleColumn: 0336 d->cddbCache.track( index.row() ).set( KCDDB::Title, value ); 0337 emit dataChanged( index, index ); 0338 return true; 0339 } 0340 break; 0341 0342 case Qt::CheckStateRole: 0343 setTrackChecked( index.row(), value.toInt() == Qt::Checked ); 0344 return true; 0345 0346 case ArtistRole: 0347 d->cddbCache.track( index.row() ).set( KCDDB::Artist, value ); 0348 emit dataChanged( index, index ); 0349 return true; 0350 0351 case TitleRole: 0352 d->cddbCache.track( index.row() ).set( KCDDB::Title, value ); 0353 emit dataChanged( index, index ); 0354 return true; 0355 0356 case CommentRole: 0357 d->cddbCache.track( index.row() ).set( KCDDB::Comment, value ); 0358 emit dataChanged( index, index ); 0359 return true; 0360 } 0361 } 0362 0363 return false; 0364 } 0365 0366 0367 QStringList K3b::AudioTrackModel::mimeTypes() const 0368 { 0369 return AudioCdTrackDrag::mimeDataTypes(); 0370 } 0371 0372 0373 QMimeData* K3b::AudioTrackModel::mimeData( const QModelIndexList& indexes ) const 0374 { 0375 // FIXME: Add QDataStream operators to K3b::Medium and encode a complete K3b::Medium in 0376 // the mimedata including the modified cddb. This way, ejecting the medium during the 0377 // d'n'd is not a problem 0378 QList<int> trackNumbers; 0379 foreach( const QModelIndex& index, indexes ) { 0380 if ( index.column() == TrackNumberColumn ) 0381 trackNumbers << index.data( TrackNumberColumn ).toInt(); 0382 } 0383 AudioCdTrackDrag drag( d->medium.toc(), trackNumbers, d->cddbCache, d->medium.device() ); 0384 QMimeData* mime = new QMimeData(); 0385 drag.populateMimeData( mime ); 0386 return mime; 0387 } 0388 0389 0390 void K3b::AudioTrackModel::checkAll() 0391 { 0392 for ( int i = 0; i < d->medium.toc().count(); ++i ) { 0393 d->itemCheckedList[i] = true; 0394 } 0395 emit dataChanged( index( 0, TrackNumberColumn ), index( d->itemCheckedList.count(), TrackNumberColumn ) ); 0396 } 0397 0398 0399 void K3b::AudioTrackModel::uncheckAll() 0400 { 0401 for ( int i = 0; i < d->medium.toc().count(); ++i ) { 0402 d->itemCheckedList[i] = false; 0403 } 0404 emit dataChanged( index( 0, TrackNumberColumn ), index( d->itemCheckedList.count(), TrackNumberColumn ) ); 0405 } 0406 0407 #include "moc_k3baudiotrackmodel.cpp"