File indexing completed on 2024-04-28 04:50:20

0001 /*
0002     SPDX-FileCopyrightText: 2010-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 "k3baudiocdview.h"
0009 #include "k3baudiorippingdialog.h"
0010 #include "k3baudiotrackmodel.h"
0011 #include "k3bviewcolumnadjuster.h"
0012 
0013 #include "k3bappdevicemanager.h"
0014 #include "k3btoc.h"
0015 #include "k3bdiskinfo.h"
0016 #include "k3bdevicehandler.h"
0017 #include "k3bmedium.h"
0018 #include "k3bmsf.h"
0019 #include "k3bstdguiitems.h"
0020 #include "k3bapplication.h"
0021 #include "k3bthememanager.h"
0022 #include "k3baudiocdtrackdrag.h"
0023 #include "k3bthemedlabel.h"
0024 #include "k3bcddb.h"
0025 #include "k3bmediacache.h"
0026 #include "k3bmodelutils.h"
0027 
0028 #include <KComboBox>
0029 #include <KLineEdit>
0030 #include <KConfig>
0031 #include <KStandardAction>
0032 #include <KIconLoader>
0033 #include <KLocalizedString>
0034 #include <KNotification>
0035 #include <KActionMenu>
0036 #include <KMessageBox>
0037 #include <KToolBarSpacerAction>
0038 #include <KActionCollection>
0039 #include <KToolBar>
0040 
0041 #include <QDate>
0042 #include <QDebug>
0043 #include <QItemSelectionModel>
0044 #include <QList>
0045 #include <QFont>
0046 #include <QKeyEvent>
0047 #include <QAction>
0048 #include <QDialog>
0049 #include <QDialogButtonBox>
0050 #include <QFormLayout>
0051 #include <QLabel>
0052 #include <QMenu>
0053 #include <QSpinBox>
0054 #include <QTreeView>
0055 #include <QVBoxLayout>
0056 
0057 #include <KCDDB/Genres>
0058 #include <KCDDB/CDInfo>
0059 #include <KCDDB/Client>
0060 #include "categories.h"
0061 
0062 namespace mu = K3b::ModelUtils;
0063 
0064 class K3b::AudioCdView::Private
0065 {
0066 public:
0067     KActionCollection* actionCollection;
0068     QMenu* popupMenu;
0069 
0070     AudioTrackModel* trackModel;
0071     QTreeView* trackView;
0072     KToolBar* toolBox;
0073     QLabel* labelLength;
0074 
0075 
0076     QLabel* busyInfoLabel;
0077 };
0078 
0079 
0080 K3b::AudioCdView::AudioCdView( QWidget* parent )
0081     : MediaContentsView( true,
0082                             Medium::ContentAudio,
0083                             Device::MEDIA_CD_ALL,
0084                             Device::STATE_INCOMPLETE | Device::STATE_COMPLETE,
0085                             parent ),
0086       d( new Private )
0087 {
0088     QVBoxLayout* mainGrid = new QVBoxLayout( mainWidget() );
0089 
0090     // toolbox
0091     // ----------------------------------------------------------------------------------
0092     d->toolBox = new KToolBar( mainWidget() );
0093     d->labelLength = new QLabel( d->toolBox );
0094     d->labelLength->setAlignment( Qt::AlignVCenter | Qt::AlignRight );
0095     d->labelLength->setContentsMargins( 0, 0, style()->pixelMetric( QStyle::PM_LayoutRightMargin ), 0 );
0096 
0097     // the track view
0098     // ----------------------------------------------------------------------------------
0099     d->trackModel = new AudioTrackModel( this );
0100     d->trackView = new QTreeView( mainWidget() );
0101     d->trackView->setSelectionMode( QAbstractItemView::ExtendedSelection );
0102     d->trackView->setModel( d->trackModel );
0103     d->trackView->setRootIsDecorated( false );
0104     d->trackView->setContextMenuPolicy( Qt::CustomContextMenu );
0105     d->trackView->setDragEnabled( true );
0106     d->trackView->installEventFilter( this );
0107     ViewColumnAdjuster* vca = new ViewColumnAdjuster( d->trackView );
0108     vca->addFixedColumn( AudioTrackModel::TrackNumberColumn );
0109     vca->addFixedColumn( AudioTrackModel::LengthColumn );
0110     vca->setColumnMargin( AudioTrackModel::LengthColumn, 10 );
0111 
0112     connect( d->trackView, SIGNAL(customContextMenuRequested(QPoint)),
0113              this, SLOT(slotContextMenu(QPoint)) );
0114     connect( d->trackView->selectionModel(), SIGNAL(selectionChanged(QItemSelection,QItemSelection)),
0115              this, SLOT(slotTrackSelectionChanged()) );
0116     connect( k3bcore->mediaCache(), SIGNAL(mediumCddbChanged(K3b::Device::Device*)),
0117              this, SLOT(slotCddbChanged(K3b::Device::Device*)) );
0118 
0119     mainGrid->addWidget( d->toolBox );
0120     mainGrid->addWidget( d->trackView );
0121     mainGrid->setSpacing( 0 );
0122     mainGrid->setContentsMargins( 0, 0, 0, 0 );
0123 
0124     initActions();
0125 
0126     // setup the toolbox
0127     d->toolBox->addAction( d->actionCollection->action( "start_rip" ) );
0128     d->toolBox->addSeparator();
0129     d->toolBox->addAction( d->actionCollection->action( "load_cd_info" ) );
0130     d->toolBox->addAction( d->actionCollection->action( "save_cddb_local" ) );
0131     d->toolBox->addAction( d->actionCollection->action( "edit_track_cddb" ) );
0132     d->toolBox->addAction( d->actionCollection->action( "edit_album_cddb" ) );
0133     d->toolBox->addSeparator();
0134     d->toolBox->addAction( d->actionCollection->action( "show_data_part" ) );
0135     d->toolBox->addAction( new KToolBarSpacerAction( d->toolBox ) );
0136     d->toolBox->addWidget( d->labelLength );
0137 
0138     slotTrackSelectionChanged();
0139 
0140     setLeftPixmap( Theme::MEDIA_LEFT );
0141     setRightPixmap( Theme::MEDIA_AUDIO );
0142 
0143     d->busyInfoLabel = new ThemedLabel( i18n("Searching for Artist information..."), this );
0144     d->busyInfoLabel->setFrameStyle( QFrame::Box|QFrame::Plain );
0145     d->busyInfoLabel->setContentsMargins( 6, 6, 6, 6 );
0146     d->busyInfoLabel->hide();
0147 }
0148 
0149 
0150 K3b::AudioCdView::~AudioCdView()
0151 {
0152     delete d;
0153 }
0154 
0155 
0156 KActionCollection* K3b::AudioCdView::actionCollection() const
0157 {
0158     return d->actionCollection;
0159 }
0160 
0161 
0162 void K3b::AudioCdView::reloadMedium()
0163 {
0164     d->trackModel->setMedium( medium() );
0165 
0166     loadCdInfo();
0167 
0168     actionCollection()->action( "show_data_part" )->setEnabled( medium().content() & Medium::ContentData );
0169     actionCollection()->action( "read_cd_text" )->setEnabled( !medium().cdText().isEmpty() );
0170 
0171     // update the title
0172     // ----------------
0173     updateTitle();
0174 
0175     // update the length label
0176     // -----------------------
0177     d->labelLength->setText( i18np("1 track (%2)",
0178                                   "%1 tracks (%2)",
0179                                   medium().toc().count(),
0180                                   medium().toc().length().toString()) );
0181 
0182     slotTrackSelectionChanged();
0183 
0184     enableInteraction( true );
0185 }
0186 
0187 
0188 void K3b::AudioCdView::updateTitle()
0189 {
0190     QString title = d->trackModel->cddbInfo().get( KCDDB::Title ).toString();
0191     QString artist = d->trackModel->cddbInfo().get( KCDDB::Artist ).toString();
0192     if( !title.isEmpty() ) {
0193         QString s( title );
0194         if( !artist.isEmpty() )
0195             s += " (" + artist + ')';
0196         setTitle( s );
0197     }
0198     else {
0199         setTitle( i18n("Audio CD") );
0200     }
0201 }
0202 
0203 
0204 void K3b::AudioCdView::initActions()
0205 {
0206     d->actionCollection = new KActionCollection( this );
0207     
0208     QAction* actionCheckTracks = new QAction( this );
0209     d->actionCollection->addAction( "check_tracks", actionCheckTracks );
0210     connect( actionCheckTracks, SIGNAL(triggered(bool)), this, SLOT(slotCheck()) );
0211     
0212     QAction* actionUncheckTracks = new QAction( this );
0213     d->actionCollection->addAction( "uncheck_tracks", actionUncheckTracks );
0214     connect( actionUncheckTracks, SIGNAL(triggered(bool)), this, SLOT(slotUncheck()) );
0215     
0216     QAction* actionEditTrackInfo = new QAction( QIcon::fromTheme( "document-properties" ), i18n("Edit Track Info..."), this );
0217     actionEditTrackInfo->setToolTip( i18n( "Edit current track information" ) );
0218     actionEditTrackInfo->setStatusTip( actionEditTrackInfo->toolTip() );
0219     d->actionCollection->addAction( "edit_track_cddb", actionEditTrackInfo );
0220     connect( actionEditTrackInfo, SIGNAL(triggered(bool)), this, SLOT(slotEditTrackCddb()) );
0221     
0222     QAction* actionEditAlbumInfo = new QAction( QIcon::fromTheme( "help-about" ), i18n("Edit Album Info..."), this );
0223     actionEditAlbumInfo->setToolTip( i18n( "Edit album information" ) );
0224     actionEditAlbumInfo->setStatusTip( actionEditAlbumInfo->toolTip() );
0225     d->actionCollection->addAction( "edit_album_cddb", actionEditAlbumInfo );
0226     connect( actionEditAlbumInfo, SIGNAL(triggered(bool)), this, SLOT(slotEditAlbumCddb()) );
0227     
0228     QAction* actionStartRip = new QAction( QIcon::fromTheme( "tools-rip-audio-cd" ), i18n("Start Ripping"), this );
0229     actionStartRip->setToolTip( i18n( "Start audio ripping process" ) );
0230     actionStartRip->setStatusTip( actionStartRip->toolTip() );
0231     d->actionCollection->addAction( "start_rip", actionStartRip );
0232     connect( actionStartRip, SIGNAL(triggered(bool)), this, SLOT(startRip()) );
0233     
0234     QAction* actionQueryCddb = new QAction( QIcon::fromTheme( "download" ), i18n("Query CD Database"), this );
0235     actionQueryCddb->setToolTip( i18n( "Look for information on CDDB" ) );
0236     actionQueryCddb->setStatusTip( actionQueryCddb->toolTip() );
0237     d->actionCollection->addAction( "query_cddb", actionQueryCddb );
0238     connect( actionQueryCddb, SIGNAL(triggered(bool)), this, SLOT(queryCddb()) );
0239     
0240     QAction* actionReadCdText = new QAction( QIcon::fromTheme( "media-optical" ), i18n("Read CD-Text"), this );
0241     actionReadCdText->setToolTip( i18n( "Read CD-Text information" ) );
0242     actionReadCdText->setStatusTip( actionReadCdText->toolTip() );
0243     d->actionCollection->addAction( "read_cd_text", actionReadCdText );
0244     connect( actionReadCdText, SIGNAL(triggered(bool)), this, SLOT(readCdText()) );
0245         
0246     KActionMenu* actionQueryInfo = new KActionMenu( QIcon::fromTheme( "view-refresh" ), i18n("Load CD Info"), this );
0247     actionQueryInfo->setToolTip( i18n( "Load track and album information" ) );
0248     actionQueryInfo->setStatusTip( actionQueryInfo->toolTip() );
0249     actionQueryInfo->addAction( actionQueryCddb );
0250     actionQueryInfo->addAction( actionReadCdText );
0251     d->actionCollection->addAction( "load_cd_info", actionQueryInfo );
0252     connect( actionQueryInfo, SIGNAL(triggered(bool)), this, SLOT(loadCdInfo()) );
0253     
0254     QAction* actionSaveCddb = new QAction( QIcon::fromTheme( "document-save" ), i18n("Save CD Info Locally"), this );
0255     actionSaveCddb->setToolTip( i18n( "Save track and album information to the local CDDB cache" ) );
0256     actionSaveCddb->setStatusTip( actionSaveCddb->toolTip() );
0257     d->actionCollection->addAction( "save_cddb_local", actionSaveCddb );
0258     connect( actionSaveCddb, SIGNAL(triggered(bool)), this, SLOT(slotSaveCddbLocally()) );
0259     
0260     QAction* actionShowDataPart = new QAction( QIcon::fromTheme( "media-optical-data" ), i18n("Show Data Part"), this );
0261     actionShowDataPart->setToolTip( i18n("Mounts the data part of CD") );
0262     actionShowDataPart->setStatusTip( actionShowDataPart->toolTip() );
0263     d->actionCollection->addAction( "show_data_part", actionShowDataPart );
0264     connect( actionShowDataPart, SIGNAL(triggered(bool)), this, SLOT(slotShowDataPart()) );
0265     
0266     QAction* actionSelectAll = KStandardAction::selectAll( d->trackView, SLOT(selectAll()), actionCollection() );
0267 
0268     // setup the popup menu
0269     d->popupMenu = new QMenu( this );
0270     d->popupMenu->addAction( actionCheckTracks );
0271     d->popupMenu->addAction( actionUncheckTracks );
0272     d->popupMenu->addSeparator();
0273     d->popupMenu->addAction( actionSelectAll );
0274     d->popupMenu->addSeparator();
0275     d->popupMenu->addAction( actionEditTrackInfo );
0276     d->popupMenu->addAction( actionEditAlbumInfo );
0277     d->popupMenu->addSeparator();
0278     d->popupMenu->addAction( d->actionCollection->action( "start_rip" ) );
0279     connect( d->popupMenu, SIGNAL(aboutToShow()), this, SLOT(slotContextMenuAboutToShow()) );
0280 }
0281 
0282 
0283 void K3b::AudioCdView::slotContextMenu( const QPoint& p )
0284 {
0285     d->popupMenu->popup( d->trackView->mapToGlobal( p ) );
0286 }
0287 
0288 
0289 void K3b::AudioCdView::slotContextMenuAboutToShow()
0290 {
0291     QAction *actionCheckTracks = actionCollection()->action("check_tracks");
0292     QAction *actionUncheckTracks = actionCollection()->action("uncheck_tracks");
0293     const QModelIndexList selectedRows = d->trackView->selectionModel()->selectedRows();
0294 
0295     if ( !selectedRows.empty() ) {
0296         const Qt::CheckState commonState = mu::commonCheckState( selectedRows );
0297         actionCheckTracks->setVisible( commonState != Qt::Checked );
0298         actionCheckTracks->setText( selectedRows.count() == 1 ? i18n("Check Track") : i18n("Check Tracks") );
0299         actionUncheckTracks->setVisible( commonState != Qt::Unchecked );
0300         actionUncheckTracks->setText( selectedRows.count() == 1 ? i18n("Uncheck Track") : i18n("Uncheck Tracks") );
0301     } else {
0302         actionCheckTracks->setVisible( false );
0303         actionUncheckTracks->setVisible( false );
0304     }
0305 }
0306 
0307 
0308 void K3b::AudioCdView::slotTrackSelectionChanged()
0309 {
0310     actionCollection()->action("edit_track_cddb")->setEnabled( d->trackView->selectionModel()->hasSelection() );
0311 }
0312 
0313 
0314 void K3b::AudioCdView::startRip()
0315 {
0316     QList<int> trackIndices = d->trackModel->checkedTrackIndices();
0317     if( trackIndices.count() == 0 ) {
0318         KMessageBox::error( this, i18n("Please select the tracks to rip."),
0319                             i18n("No Tracks Selected") );
0320     }
0321     else {
0322         AudioRippingDialog rip( medium(),
0323                                 d->trackModel->cddbInfo(),
0324                                 trackIndices,
0325                                 this );
0326  
0327         rip.setDelayedInitialization( true );
0328         rip.exec();
0329     }
0330 }
0331 
0332 
0333 void K3b::AudioCdView::slotEditTrackCddb()
0334 {
0335     const QModelIndexList selection = d->trackView->selectionModel()->selectedRows();
0336     if( !selection.isEmpty() ) {
0337         QDialog dialog( this );
0338         if( selection.size() > 1 )
0339             dialog.setWindowTitle( i18n( "Multiple Tracks" ) );
0340         else
0341             dialog.setWindowTitle( i18n( "CDDB Track %1", selection.first().data( AudioTrackModel::TrackNumberRole ).toInt() ) );
0342         dialog.setModal(true);
0343 
0344         KLineEdit* editTitle = new KLineEdit( mu::commonText( selection, AudioTrackModel::TitleRole ), this );
0345         KLineEdit* editArtist = new KLineEdit( mu::commonText( selection, AudioTrackModel::ArtistRole ), this );
0346         KLineEdit* editExtInfo = new KLineEdit( mu::commonText( selection, AudioTrackModel::CommentRole ), this );
0347         
0348         QFrame* line = new QFrame( this );
0349         line->setFrameShape( QFrame::HLine );
0350         line->setFrameShadow( QFrame::Sunken );
0351 
0352         QFormLayout* form = new QFormLayout(this);
0353         form->addRow( i18n("Title:"), editTitle );
0354         form->addRow( line );
0355         form->addRow( i18n("Artist:"), editArtist );
0356         form->addRow( i18n("Extra info:"), editExtInfo );
0357         form->setContentsMargins( 0, 0, 0, 0 );
0358 
0359         QDialogButtonBox* buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this );
0360         connect( buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()) );
0361         connect( buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()) );
0362 
0363         QVBoxLayout* dlgLayout = new QVBoxLayout( &dialog );
0364         dlgLayout->addLayout( form );
0365         dlgLayout->addWidget( buttonBox );
0366 
0367         editTitle->setFocus( Qt::TabFocusReason );
0368 
0369         // load album's artist by default if no artist is specified yet
0370         if ( editArtist->text().isEmpty() )
0371             editArtist->setText( d->trackModel->cddbInfo().get( KCDDB::Artist ).toString() );
0372 
0373         if( dialog.exec() == QDialog::Accepted ) {
0374             mu::setCommonText( d->trackModel, selection, editTitle->text(), AudioTrackModel::TitleRole );
0375             mu::setCommonText( d->trackModel, selection, editArtist->text(), AudioTrackModel::ArtistRole );
0376             mu::setCommonText( d->trackModel, selection, editExtInfo->text(), AudioTrackModel::CommentRole );
0377         }
0378     }
0379 }
0380 
0381 
0382 void K3b::AudioCdView::slotEditAlbumCddb()
0383 {
0384     QDialog dialog( this);
0385     dialog.setWindowTitle(i18n("Album CDDB"));
0386     dialog.setModal(true);
0387 
0388     KLineEdit* editTitle = new KLineEdit( d->trackModel->cddbInfo().get( KCDDB::Title ).toString(), this );
0389     KLineEdit* editArtist = new KLineEdit( d->trackModel->cddbInfo().get( KCDDB::Artist ).toString(), this );
0390     KLineEdit* editExtInfo = new KLineEdit( d->trackModel->cddbInfo().get( KCDDB::Comment ).toString(), this );
0391     QSpinBox* spinYear = new QSpinBox( this );
0392     spinYear->setRange( 1, 9999 );
0393     if ( d->trackModel->cddbInfo().get( KCDDB::Year ).toInt() == 0 ) {
0394         spinYear->setValue( QDate::currentDate().year() ); // set the current year to default if no year specified yet
0395     } else {
0396         spinYear->setValue( d->trackModel->cddbInfo().get( KCDDB::Year ).toInt() );
0397     }
0398     QFrame* line = new QFrame( this );
0399     line->setFrameShape( QFrame::HLine );
0400     line->setFrameShadow( QFrame::Sunken );
0401     KComboBox* comboGenre = new KComboBox( this );
0402     comboGenre->addItems( KCDDB::Genres().i18nList() );
0403     KComboBox* comboCat = new KComboBox( this );
0404     comboCat->addItems( KCDDB::Categories().i18nList() );
0405 
0406     QString genre = d->trackModel->cddbInfo().get( KCDDB::Genre ).toString();
0407     QString cat = d->trackModel->cddbInfo().get( KCDDB::Category ).toString();
0408 
0409     for( int i = 0; i < comboCat->count(); ++i ) {
0410         if( comboCat->itemText(i) == cat ) {
0411             comboCat->setCurrentIndex(i);
0412             break;
0413         }
0414     }
0415     for( int i = 0; i < comboGenre->count(); ++i ) {
0416         if( comboGenre->itemText(i) == genre ) {
0417             comboGenre->setCurrentIndex(i);
0418             break;
0419         }
0420     }
0421 
0422     QFormLayout* form = new QFormLayout(this);
0423     form->addRow( i18n("Title:"), editTitle );
0424     form->addRow( i18n("Artist:"), editArtist );
0425     form->addRow( i18n("Extra info:"), editExtInfo );
0426     form->addRow( i18n("Genre:"), comboGenre );
0427     form->addRow( i18n("Year:"), spinYear );
0428     form->addRow( line );
0429     form->addRow( i18n("Category:"), comboCat );
0430     form->setContentsMargins( 0, 0, 0, 0 );
0431 
0432     QDialogButtonBox* buttonBox = new QDialogButtonBox( QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this );
0433     connect( buttonBox, SIGNAL(accepted()), &dialog, SLOT(accept()) );
0434     connect( buttonBox, SIGNAL(rejected()), &dialog, SLOT(reject()) );
0435 
0436     QVBoxLayout* dlgLayout = new QVBoxLayout( &dialog );
0437     dlgLayout->addLayout( form );
0438     dlgLayout->addWidget( buttonBox );
0439 
0440     editTitle->setFocus(Qt::TabFocusReason);
0441 
0442     if( dialog.exec() == QDialog::Accepted ) {
0443         KCDDB::CDInfo cddbInfo = d->trackModel->cddbInfo();
0444         cddbInfo.set( KCDDB::Title, editTitle->text() );
0445         cddbInfo.set( KCDDB::Artist, editArtist->text() );
0446         cddbInfo.set( KCDDB::Comment, editExtInfo->text() );
0447         cddbInfo.set( KCDDB::Category, KCDDB::Categories().i18n2cddb( comboCat->currentText() ) );
0448         cddbInfo.set( KCDDB::Genre, KCDDB::Genres().i18n2cddb( comboGenre->currentText() ) );
0449         cddbInfo.set( KCDDB::Year, spinYear->value() );
0450         d->trackModel->setCddbInfo( cddbInfo );
0451 
0452         updateTitle();
0453     }
0454 }
0455 
0456 
0457 void K3b::AudioCdView::loadCdInfo()
0458 {
0459     // cddb vs. cd-text
0460     // ----------------
0461     if( !medium().cddbInfo().isValid() ) {
0462         readCdText();
0463     } else {
0464         //slotCddbChanged( medium().device() );
0465         queryCddb();
0466     }
0467 }
0468 
0469 
0470 void K3b::AudioCdView::queryCddb()
0471 {
0472     enableInteraction( false );
0473     k3bcore->mediaCache()->lookupCddb( medium().device() );
0474 }
0475 
0476 
0477 void K3b::AudioCdView::readCdText()
0478 {
0479     if( !medium().cdText().isEmpty() ) {
0480         // simulate a cddb entry with the cdtext data
0481         KCDDB::CDInfo cddbInfo;
0482         cddbInfo.set( KCDDB::Artist, medium().cdText().performer() );
0483         cddbInfo.set( KCDDB::Title, medium().cdText().title() );
0484         cddbInfo.set( KCDDB::Comment, medium().cdText().message() );
0485 
0486         for( int i = 0; i < medium().cdText().count(); ++i ) {
0487             cddbInfo.track( i ).set( KCDDB::Title, medium().cdText()[i].title() );
0488             cddbInfo.track( i ).set( KCDDB::Artist, medium().cdText()[i].performer() );
0489             cddbInfo.track( i ).set( KCDDB::Comment, medium().cdText()[i].message() );
0490         }
0491 
0492         d->trackModel->setCddbInfo( cddbInfo );
0493     }
0494 }
0495 
0496 
0497 bool K3b::AudioCdView::eventFilter( QObject* obj, QEvent* event )
0498 {
0499     if( event->type() == QEvent::KeyPress ) {
0500         // Due to limitation of default implementation of QTreeView
0501         // checking items with Space key doesn't work for columns other than first.
0502         // Using below code a user can do that.
0503         QKeyEvent* keyEvent = static_cast<QKeyEvent*>( event );
0504         if( keyEvent->key() == Qt::Key_Space ) {
0505             if( keyEvent->modifiers().testFlag( Qt::ControlModifier ) ) {
0506                 QItemSelectionModel* selectionModel = d->trackView->selectionModel();
0507                 QModelIndex current = d->trackView->currentIndex();
0508                 selectionModel->select( current, QItemSelectionModel::Toggle | QItemSelectionModel::Rows );
0509             } else {
0510                 slotToggle();
0511             }
0512             return true;
0513         }
0514     }
0515     return MediaContentsView::eventFilter( obj, event );
0516 }
0517 
0518 
0519 void K3b::AudioCdView::slotSaveCddbLocally()
0520 {
0521     KCDDB::Client cddbClient;
0522     cddbClient.config().load();
0523     cddbClient.store( d->trackModel->cddbInfo(), CDDB::createTrackOffsetList( d->trackModel->medium().toc() ) );
0524 }
0525 
0526 
0527 void K3b::AudioCdView::slotCheck()
0528 {
0529     foreach( const QModelIndex& index, d->trackView->selectionModel()->selectedRows() ) {
0530         d->trackModel->setData( index, Qt::Checked, Qt::CheckStateRole );
0531     }
0532 }
0533 
0534 
0535 void K3b::AudioCdView::slotUncheck()
0536 {
0537     foreach( const QModelIndex& index, d->trackView->selectionModel()->selectedRows() ) {
0538         d->trackModel->setData( index, Qt::Unchecked, Qt::CheckStateRole );
0539     }
0540 }
0541 
0542 
0543 void K3b::AudioCdView::slotToggle()
0544 {
0545     mu::toggleCommonCheckState( d->trackModel, d->trackView->selectionModel()->selectedRows() );
0546 }
0547 
0548 
0549 void K3b::AudioCdView::slotShowDataPart()
0550 {
0551     k3bappcore->appDeviceManager()->mountDisk( medium().device() );
0552 }
0553 
0554 
0555 void K3b::AudioCdView::slotCddbChanged( K3b::Device::Device* dev )
0556 {
0557     if ( medium().device() == dev ) {
0558         // we only use the manually edited cddb in the model
0559         d->trackModel->setCddbInfo( medium().cddbInfo() );
0560     }
0561 }
0562 
0563 
0564 void K3b::AudioCdView::showBusyLabel( bool b )
0565 {
0566     if( !b ) {
0567         actionCollection()->action( "start_rip" )->setEnabled( true );
0568         d->trackView->setEnabled( true );
0569         d->busyInfoLabel->hide();
0570     }
0571     else {
0572         // the themed label is a cut label, thus its size hint is
0573         // based on the cut text, we force it to be full
0574         d->busyInfoLabel->resize( width(), height() );
0575         d->busyInfoLabel->resize( d->busyInfoLabel->sizeHint() );
0576         int x = (width() - d->busyInfoLabel->width())/2;
0577         int y = (height() - d->busyInfoLabel->height())/2;
0578         QRect r( QPoint( x, y ), d->busyInfoLabel->size() );
0579         d->busyInfoLabel->setGeometry( r );
0580         d->busyInfoLabel->show();
0581 
0582         d->trackView->setEnabled( false );
0583         enableInteraction( false );
0584     }
0585 }
0586 
0587 
0588 void K3b::AudioCdView::enableInteraction( bool b )
0589 {
0590     // we leave the track view enabled in default disabled mode
0591     // since drag'n'drop to audio projects does not need an inserted CD
0592     actionCollection()->action( "start_rip" )->setEnabled( b );
0593     if( b )
0594         showBusyLabel( false );
0595 }
0596 
0597 #include "moc_k3baudiocdview.cpp"