summaryrefslogtreecommitdiffstats
path: root/src/projects/k3baudiotrackview.cpp
diff options
context:
space:
mode:
authortpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-03 02:15:56 +0000
committertpearson <tpearson@283d02a7-25f6-0310-bc7c-ecb5cbfe19da>2010-02-03 02:15:56 +0000
commit50b48aec6ddd451a6d1709c0942477b503457663 (patch)
treea9ece53ec06fd0a2819de7a2a6de997193566626 /src/projects/k3baudiotrackview.cpp
downloadk3b-50b48aec6ddd451a6d1709c0942477b503457663.tar.gz
k3b-50b48aec6ddd451a6d1709c0942477b503457663.zip
Added abandoned KDE3 version of K3B
git-svn-id: svn://anonsvn.kde.org/home/kde/branches/trinity/applications/k3b@1084400 283d02a7-25f6-0310-bc7c-ecb5cbfe19da
Diffstat (limited to 'src/projects/k3baudiotrackview.cpp')
-rw-r--r--src/projects/k3baudiotrackview.cpp1005
1 files changed, 1005 insertions, 0 deletions
diff --git a/src/projects/k3baudiotrackview.cpp b/src/projects/k3baudiotrackview.cpp
new file mode 100644
index 0000000..1af6a5c
--- /dev/null
+++ b/src/projects/k3baudiotrackview.cpp
@@ -0,0 +1,1005 @@
+/*
+ *
+ * $Id: k3baudiotrackview.cpp 689561 2007-07-18 15:19:38Z trueg $
+ * Copyright (C) 2004 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This file is part of the K3b project.
+ * Copyright (C) 1998-2007 Sebastian Trueg <trueg@k3b.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ * See the file "COPYING" for the exact licensing terms.
+ */
+
+#include <config.h>
+
+#include "k3baudiotrackview.h"
+#include "k3baudiotrackviewitem.h"
+#include "k3baudiodatasourceviewitem.h"
+#include "k3baudiotrack.h"
+#include "k3baudiodatasource.h"
+#include "k3baudiotrackdialog.h"
+#include "k3baudiodoc.h"
+#include "k3baudiozerodata.h"
+#include "k3baudiotracksplitdialog.h"
+#include "k3baudiofile.h"
+#include "k3baudiotrackplayer.h"
+#include "k3baudiocdtrackdrag.h"
+#include "k3baudiocdtracksource.h"
+#include "k3baudiotracktrmlookupdialog.h"
+#include "k3baudiodatasourceeditwidget.h"
+#include "k3baudiotrackaddingdialog.h"
+
+#include <k3bview.h>
+#include <k3blistviewitemanimator.h>
+#include <k3baudiodecoder.h>
+#include <k3bmsfedit.h>
+
+#include <qheader.h>
+#include <qtimer.h>
+#include <qdragobject.h>
+#include <qpoint.h>
+#include <qptrlist.h>
+#include <qstringlist.h>
+#include <qevent.h>
+#include <qpixmap.h>
+#include <qpainter.h>
+#include <qlayout.h>
+#include <qlabel.h>
+#include <qvaluelist.h>
+
+#include <kurl.h>
+#include <kurldrag.h>
+#include <klocale.h>
+#include <kaction.h>
+#include <kpopupmenu.h>
+#include <kiconloader.h>
+#include <kapplication.h>
+#include <kmessagebox.h>
+#include <kdialogbase.h>
+
+
+K3bAudioTrackView::K3bAudioTrackView( K3bAudioDoc* doc, QWidget* parent, const char* name )
+ : K3bListView( parent, name ),
+ m_doc(doc),
+ m_updatingColumnWidths(false),
+ m_currentMouseOverItem(0),
+ m_currentlyPlayingTrack(0)
+{
+ m_player = new K3bAudioTrackPlayer( m_doc, this );
+ connect( m_player, SIGNAL(playingTrack(K3bAudioTrack*)), this,
+ SLOT(showPlayerIndicator(K3bAudioTrack*)) );
+ connect( m_player, SIGNAL(paused(bool)), this, SLOT(togglePauseIndicator(bool)) );
+ connect( m_player, SIGNAL(stopped()), this, SLOT(removePlayerIndicator()) );
+
+ setItemMargin( 5 );
+ setAcceptDrops( true );
+ setDropVisualizer( true );
+ setAllColumnsShowFocus( true );
+ setDragEnabled( true );
+ // setSelectionModeExt( KListView::Konqueror ); // FileManager in KDE3
+ setSelectionModeExt( KListView::Extended );
+ setItemsMovable( false );
+ setAlternateBackground( QColor() ); // disable alternate colors
+
+ setNoItemText( i18n("Use drag'n'drop to add audio files to the project.") + "\n"
+ + i18n("After that press the burn button to write the CD." ) );
+
+ setupColumns();
+ setupActions();
+
+ m_playerItemAnimator = new K3bListViewItemAnimator( this );
+
+ m_animationTimer = new QTimer( this );
+ connect( m_animationTimer, SIGNAL(timeout()), this, SLOT(slotAnimation()) );
+
+ m_autoOpenTrackTimer = new QTimer( this );
+ connect( m_autoOpenTrackTimer, SIGNAL(timeout()), this, SLOT(slotDragTimeout()) );
+
+ connect( this, SIGNAL(dropped(QDropEvent*, QListViewItem*, QListViewItem*)),
+ this, SLOT(slotDropped(QDropEvent*, QListViewItem*, QListViewItem*)) );
+ connect( this, SIGNAL(contextMenu(KListView*, QListViewItem*, const QPoint&)),
+ this, SLOT(showPopupMenu(KListView*, QListViewItem*, const QPoint&)) );
+ connect( this, SIGNAL(doubleClicked(QListViewItem*, const QPoint&, int)),
+ this, SLOT(slotProperties()) );
+
+ connect( doc, SIGNAL(changed()),
+ this, SLOT(slotChanged()) );
+ connect( doc, SIGNAL(trackChanged(K3bAudioTrack*)),
+ this, SLOT(slotTrackChanged(K3bAudioTrack*)) );
+ connect( doc, SIGNAL(trackRemoved(K3bAudioTrack*)),
+ this, SLOT(slotTrackRemoved(K3bAudioTrack*)) );
+
+ slotChanged();
+
+ // a little background pix hack because I am simply incapable of doing it another way. :(
+// static QPixmap s_bgPix("/tmp/trueg/audio_bg.png");
+// setK3bBackgroundPixmap( s_bgPix, TOP_LEFT );
+}
+
+
+K3bAudioTrackView::~K3bAudioTrackView()
+{
+}
+
+
+void K3bAudioTrackView::setupColumns()
+{
+ addColumn( i18n("No.") );
+ addColumn( i18n("Artist (CD-Text)") );
+ addColumn( i18n("Title (CD-Text)") );
+ addColumn( i18n("Type") );
+ addColumn( i18n("Length") );
+ addColumn( i18n("Filename") );
+
+ setColumnAlignment( 3, Qt::AlignHCenter );
+ setColumnAlignment( 4, Qt::AlignHCenter );
+
+ setColumnWidthMode( 1, Manual );
+ setColumnWidthMode( 2, Manual );
+ setColumnWidthMode( 3, Manual );
+ setColumnWidthMode( 4, Manual );
+ setColumnWidthMode( 5, Manual );
+
+ header()->setResizeEnabled( false );
+ header()->setClickEnabled( false );
+ setSorting( -1 );
+}
+
+
+void K3bAudioTrackView::setupActions()
+{
+ m_actionCollection = new KActionCollection( this );
+ m_popupMenu = new KPopupMenu( this );
+
+ m_actionProperties = new KAction( i18n("Properties"), "misc",
+ KShortcut(), this, SLOT(slotProperties()),
+ actionCollection(), "track_properties" );
+ m_actionRemove = new KAction( i18n( "Remove" ), "editdelete",
+ Key_Delete, this, SLOT(slotRemove()),
+ actionCollection(), "track_remove" );
+
+ m_actionAddSilence = new KAction( i18n("Add Silence") + "...", "misc",
+ KShortcut(), this, SLOT(slotAddSilence()),
+ actionCollection(), "track_add_silence" );
+ m_actionMergeTracks = new KAction( i18n("Merge Tracks"), "misc",
+ KShortcut(), this, SLOT(slotMergeTracks()),
+ actionCollection(), "track_merge" );
+ m_actionSplitSource = new KAction( i18n("Source to Track"), "misc",
+ KShortcut(), this, SLOT(slotSplitSource()),
+ actionCollection(), "source_split" );
+ m_actionSplitTrack = new KAction( i18n("Split Track..."), 0,
+ KShortcut(), this, SLOT(slotSplitTrack()),
+ actionCollection(), "track_split" );
+ m_actionEditSource = new KAction( i18n("Edit Source..."), 0,
+ KShortcut(), this, SLOT(slotEditSource()),
+ actionCollection(), "source_edit" );
+ m_actionPlayTrack = new KAction( i18n("Play Track"), "player_play",
+ KShortcut(), this, SLOT(slotPlayTrack()),
+ actionCollection(), "track_play" );
+#ifdef HAVE_MUSICBRAINZ
+ KAction* mbAction = new KAction( i18n("Musicbrainz Lookup"), "musicbrainz", 0, this,
+ SLOT(slotQueryMusicBrainz()),
+ actionCollection(), "project_audio_musicbrainz" );
+ mbAction->setToolTip( i18n("Try to determine meta information over the internet") );
+#endif
+}
+
+
+bool K3bAudioTrackView::acceptDrag(QDropEvent* e) const
+{
+ // the first is for built-in item moving, the second for dropping urls, the third for dropping audio tracks
+ return ( KListView::acceptDrag(e) || KURLDrag::canDecode(e) || K3bAudioCdTrackDrag::canDecode(e) );
+}
+
+
+QDragObject* K3bAudioTrackView::dragObject()
+{
+ QPtrList<QListViewItem> list = selectedItems();
+
+ if( list.isEmpty() )
+ return 0;
+
+ KURL::List urls;
+
+ for( QPtrListIterator<QListViewItem> it(list); it.current(); ++it ) {
+ QListViewItem* item = *it;
+ // we simply ignore open track items to not include files twice
+ // we also don't want the invisible source items
+ QListViewItem* parentItem = K3bListView::parentItem(item);
+ if( !item->isOpen() && ( !parentItem || parentItem->isOpen() ) ) {
+ if( K3bAudioDataSourceViewItem* sourceItem = dynamic_cast<K3bAudioDataSourceViewItem*>( item ) ) {
+ if( K3bAudioFile* file = dynamic_cast<K3bAudioFile*>( sourceItem->source() ) )
+ urls.append( KURL::fromPathOrURL(file->filename()) );
+ }
+ else {
+ K3bAudioTrackViewItem* trackItem = static_cast<K3bAudioTrackViewItem*>( item );
+ K3bAudioDataSource* source = trackItem->track()->firstSource();
+ while( source ) {
+ if( K3bAudioFile* file = dynamic_cast<K3bAudioFile*>( source ) )
+ urls.append( KURL::fromPathOrURL(file->filename()) );
+ source = source->next();
+ }
+ }
+ }
+ }
+
+ return new KURLDrag( urls, viewport() );
+}
+
+
+void K3bAudioTrackView::slotDropped( QDropEvent* e, QListViewItem* parent, QListViewItem* after )
+{
+ m_autoOpenTrackTimer->stop();
+
+ if( !e->isAccepted() )
+ return;
+
+ m_dropTrackAfter = 0;
+ m_dropTrackParent = 0;
+ m_dropSourceAfter = 0;
+ if( after ) {
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>( after ) ) {
+ m_dropTrackAfter = tv->track();
+ }
+ else if( K3bAudioDataSourceViewItem* sv = dynamic_cast<K3bAudioDataSourceViewItem*>( after ) ) {
+ m_dropSourceAfter = sv->source();
+ }
+ }
+
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>( parent ) ) {
+ m_dropTrackParent = tv->track();
+ }
+
+ //
+ // In case the sources are not shown we do not want to handle them because the average
+ // user would be confused otherwise
+ //
+ if( m_dropTrackParent && !m_trackItemMap[m_dropTrackParent]->showingSources() ) {
+ kdDebug() << "(K3bAudioTrackView) dropped after track which does not show it's sources." << endl;
+ m_dropTrackAfter = m_dropTrackParent;
+ m_dropTrackParent = 0;
+ }
+
+ if( e->source() == viewport() ) {
+
+ bool copyItems = (e->action() == QDropEvent::Copy);
+
+ // 1. tracks (with some of their sources) -> move complete tracks around
+ // 2. sources (multiple sources) -> move the sources to the destination track
+ // 3. tracks and sources (the latter without their track) -> ignore the latter sources
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+
+ //
+ // remove all sources which belong to one of the selected tracks since they will be
+ // moved along with their tracks
+ //
+ QPtrListIterator<K3bAudioDataSource> srcIt( sources );
+ while( srcIt.current() ) {
+ if( tracks.containsRef( srcIt.current()->track() ) )
+ sources.removeRef( *srcIt );
+ else
+ ++srcIt;
+ }
+
+ //
+ // Now move (or copy) all the tracks
+ //
+ for( QPtrListIterator<K3bAudioTrack> it( tracks ); it.current(); ++it ) {
+ K3bAudioTrack* track = *it;
+ if( m_dropTrackParent ) {
+ m_dropTrackParent->merge( copyItems ? track->copy() : track, m_dropSourceAfter );
+ }
+ else if( m_dropTrackAfter ) {
+ if( copyItems )
+ track->copy()->moveAfter( m_dropTrackAfter );
+ else
+ track->moveAfter( m_dropTrackAfter );
+ }
+ else {
+ if( copyItems )
+ track->copy()->moveAhead( m_doc->firstTrack() );
+ else
+ track->moveAhead( m_doc->firstTrack() );
+ }
+ }
+
+ //
+ // now move (or copy) the sources
+ //
+ for( QPtrListIterator<K3bAudioDataSource> it( sources ); it.current(); ++it ) {
+ K3bAudioDataSource* source = *it;
+ if( m_dropTrackParent ) {
+ if( m_dropSourceAfter ) {
+ if( copyItems )
+ source->copy()->moveAfter( m_dropSourceAfter );
+ else
+ source->moveAfter( m_dropSourceAfter );
+ }
+ else {
+ if( copyItems )
+ source->copy()->moveAhead( m_dropTrackParent->firstSource() );
+ else
+ source->moveAhead( m_dropTrackParent->firstSource() );
+ }
+ }
+ else {
+ // create a new track
+ K3bAudioTrack* track = new K3bAudioTrack( m_doc );
+
+ // special case: the source we remove from the track is the last and the track
+ // will be deleted.
+ if( !copyItems && m_dropTrackAfter == source->track() && m_dropTrackAfter->numberSources() == 1 )
+ m_dropTrackAfter = m_dropTrackAfter->prev();
+
+ if( copyItems )
+ track->addSource( source->copy() );
+ else
+ track->addSource( source );
+
+ if( m_dropTrackAfter ) {
+ track->moveAfter( m_dropTrackAfter );
+ m_dropTrackAfter = track;
+ }
+ else {
+ track->moveAhead( m_doc->firstTrack() );
+ m_dropTrackAfter = track;
+ }
+ }
+ }
+ }
+ else if( K3bAudioCdTrackDrag::canDecode( e ) ) {
+ kdDebug() << "(K3bAudioTrackView) audiocdtrack dropped." << endl;
+ K3bDevice::Toc toc;
+ K3bDevice::Device* dev = 0;
+ K3bCddbResultEntry cddb;
+ QValueList<int> trackNumbers;
+
+ K3bAudioCdTrackDrag::decode( e, toc, trackNumbers, cddb, &dev );
+
+ // for now we just create one source
+ for( QValueList<int>::const_iterator it = trackNumbers.begin();
+ it != trackNumbers.end(); ++it ) {
+ int trackNumber = *it;
+
+ K3bAudioCdTrackSource* source = new K3bAudioCdTrackSource( toc, trackNumber, cddb, dev );
+ if( m_dropTrackParent ) {
+ source->moveAfter( m_dropSourceAfter );
+ if( m_dropSourceAfter )
+ m_dropSourceAfter = source;
+ }
+ else {
+ K3bAudioTrack* track = new K3bAudioTrack();
+ track->setPerformer( cddb.artists[trackNumber-1] );
+ track->setTitle( cddb.titles[trackNumber-1] );
+ track->addSource( source );
+ if( m_dropTrackAfter )
+ track->moveAfter( m_dropTrackAfter );
+ else
+ m_doc->addTrack( track, 0 );
+
+ m_dropTrackAfter = track;
+ }
+ }
+ }
+ else{
+ m_dropUrls.clear();
+ if( KURLDrag::decode( e, m_dropUrls ) ) {
+ //
+ // This is a small (not to ugly) hack to circumvent problems with the
+ // event queues: the url adding dialog will be non-modal regardless of
+ // the settings in case we open it directly.
+ //
+ QTimer::singleShot( 0, this, SLOT(slotAddUrls()) );
+ }
+ }
+
+ showAllSources();
+
+ // now grab that focus
+ setFocus();
+}
+
+
+void K3bAudioTrackView::slotAddUrls()
+{
+ K3bAudioTrackAddingDialog::addUrls( m_dropUrls, m_doc, m_dropTrackAfter, m_dropTrackParent, m_dropSourceAfter, this );
+}
+
+
+void K3bAudioTrackView::slotChanged()
+{
+ kdDebug() << "(K3bAudioTrackView::slotChanged)" << endl;
+ // we only need to add new items here. Everything else is done in the
+ // specific slots below
+ K3bAudioTrack* track = m_doc->firstTrack();
+ bool newTracks = false;
+ while( track ) {
+ bool newTrack;
+ getTrackViewItem( track, &newTrack );
+ if( newTrack )
+ newTracks = true;
+ track = track->next();
+ }
+
+ if( newTracks ) {
+ m_animationTimer->start(200);
+ showAllSources();
+ }
+
+ header()->setShown( m_doc->numOfTracks() > 0 );
+
+ kdDebug() << "(K3bAudioTrackView::slotChanged) finished" << endl;
+}
+
+
+K3bAudioTrackViewItem* K3bAudioTrackView::getTrackViewItem( K3bAudioTrack* track, bool* isNewItem )
+{
+ QMap<K3bAudioTrack*, K3bAudioTrackViewItem*>::iterator itemIt = m_trackItemMap.find(track);
+ if( itemIt == m_trackItemMap.end() ) {
+ kdDebug() << "(K3bAudioTrackView) new track " << track << endl;
+ K3bAudioTrackViewItem* prevItem = 0;
+ if( track->prev() && m_trackItemMap.contains( track->prev() ) )
+ prevItem = m_trackItemMap[track->prev()];
+ K3bAudioTrackViewItem* newItem = new K3bAudioTrackViewItem( this, prevItem, track );
+ //
+ // disable the item until the files have been analysed
+ // so the user may not change the cd-text until the one from the
+ // file is loaded.
+ //
+ // Since for some reason QT thinks it's bad to open disabled items
+ // we need to open it before disabling it
+ //
+ newItem->showSources( track->numberSources() != 1 );
+ newItem->setEnabled( false );
+ m_trackItemMap[track] = newItem;
+
+ if( isNewItem )
+ *isNewItem = true;
+ return newItem;
+ }
+ else {
+ if( isNewItem )
+ *isNewItem = false;
+ return *itemIt;
+ }
+}
+
+
+void K3bAudioTrackView::slotTrackChanged( K3bAudioTrack* track )
+{
+ kdDebug() << "(K3bAudioTrackView::slotTrackChanged( " << track << " )" << endl;
+
+ //
+ // There may be some tracks around that have not been added to the list yet
+ // (and might never). We ignore them until they are in the list and then
+ // we create the item in slotChanged
+ //
+ if( track->inList() ) {
+ K3bAudioTrackViewItem* item = getTrackViewItem(track);
+ item->updateSourceItems();
+
+ if( track->numberSources() > 1 )
+ item->showSources(true);
+
+ // the length might have changed
+ item->repaint();
+
+ // FIXME: only do this if the position really changed
+ // move the item if the position has changed
+ if( track->prev() && m_trackItemMap.contains(track->prev()) )
+ item->moveItem( m_trackItemMap[track->prev()] );
+ else if( !track->prev() ) {
+ takeItem( item );
+ insertItem( item );
+ }
+
+ // start the animation in case new sources have been added
+ m_animationTimer->start( 200 );
+
+ showAllSources();
+ }
+ kdDebug() << "(K3bAudioTrackView::slotTrackChanged( " << track << " ) finished" << endl;
+}
+
+
+void K3bAudioTrackView::slotTrackRemoved( K3bAudioTrack* track )
+{
+ kdDebug() << "(K3bAudioTrackView::slotTrackRemoved( " << track << " )" << endl;
+ if ( m_playerItemAnimator->item() == m_trackItemMap[track] ) {
+ m_playerItemAnimator->stop();
+ }
+ delete m_trackItemMap[track];
+ m_trackItemMap.erase(track);
+}
+
+
+void K3bAudioTrackView::showAllSources()
+{
+ // TODO: add an action to show all sources
+
+ QListViewItem* item = firstChild();
+ while( item ) {
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>( item ) )
+ tv->showSources( tv->track()->numberSources() != 1 );
+ item = item->nextSibling();
+ }
+}
+
+
+void K3bAudioTrackView::keyPressEvent( QKeyEvent* e )
+{
+ // showAllSources();
+
+ K3bListView::keyPressEvent(e);
+}
+
+
+void K3bAudioTrackView::keyReleaseEvent( QKeyEvent* e )
+{
+ // showAllSources();
+
+ K3bListView::keyReleaseEvent(e);
+}
+
+
+void K3bAudioTrackView::contentsMouseMoveEvent( QMouseEvent* e )
+{
+ // showAllSources();
+
+ K3bListView::contentsMouseMoveEvent( e );
+}
+
+
+void K3bAudioTrackView::focusOutEvent( QFocusEvent* e )
+{
+ // showAllSources();
+
+ K3bListView::focusOutEvent( e );
+}
+
+
+void K3bAudioTrackView::resizeEvent( QResizeEvent* e )
+{
+ K3bListView::resizeEvent(e);
+
+ resizeColumns();
+}
+
+
+void K3bAudioTrackView::contentsDragMoveEvent( QDragMoveEvent* event )
+{
+ K3bAudioTrackViewItem* item = findTrackItem( event->pos() );
+ if( m_currentMouseOverItem != item ) {
+ showAllSources(); // hide previous sources
+ m_currentMouseOverItem = item;
+ }
+ if( m_currentMouseOverItem )
+ m_autoOpenTrackTimer->start( 1000 ); // 1 sec
+
+ K3bListView::contentsDragMoveEvent( event );
+}
+
+
+void K3bAudioTrackView::contentsDragLeaveEvent( QDragLeaveEvent* e )
+{
+ m_autoOpenTrackTimer->stop();
+ K3bListView::contentsDragLeaveEvent( e );
+}
+
+
+K3bAudioTrackViewItem* K3bAudioTrackView::findTrackItem( const QPoint& pos ) const
+{
+ QListViewItem* parent = 0;
+ QListViewItem* after = 0;
+ K3bAudioTrackView* that = const_cast<K3bAudioTrackView*>(this);
+ that->findDrop( pos, parent, after );
+ if( parent )
+ return static_cast<K3bAudioTrackViewItem*>( parent );
+ else if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>(after) )
+ return tv;
+ else if( K3bAudioDataSourceViewItem* sv = dynamic_cast<K3bAudioDataSourceViewItem*>(after) )
+ return sv->trackViewItem();
+ else
+ return 0;
+}
+
+
+void K3bAudioTrackView::resizeColumns()
+{
+ if( m_updatingColumnWidths ) {
+ kdDebug() << "(K3bAudioTrackView) already updating column widths." << endl;
+ return;
+ }
+
+ m_updatingColumnWidths = true;
+
+ // now properly resize the columns
+ // minimal width for type, length, pregap
+ // fixed for filename
+ // expand for cd-text
+ int titleWidth = header()->fontMetrics().width( header()->label(1) );
+ int artistWidth = header()->fontMetrics().width( header()->label(2) );
+ int typeWidth = header()->fontMetrics().width( header()->label(3) );
+ int lengthWidth = header()->fontMetrics().width( header()->label(4) );
+ int filenameWidth = header()->fontMetrics().width( header()->label(5) );
+
+ for( QListViewItemIterator it( this ); it.current(); ++it ) {
+ artistWidth = QMAX( artistWidth, it.current()->width( fontMetrics(), this, 1 ) );
+ titleWidth = QMAX( titleWidth, it.current()->width( fontMetrics(), this, 2 ) );
+ typeWidth = QMAX( typeWidth, it.current()->width( fontMetrics(), this, 3 ) );
+ lengthWidth = QMAX( lengthWidth, it.current()->width( fontMetrics(), this, 4 ) );
+ filenameWidth = QMAX( filenameWidth, it.current()->width( fontMetrics(), this, 5 ) );
+ }
+
+ // add a margin
+ typeWidth += 10;
+ lengthWidth += 10;
+
+ // these always need to be completely visible
+ setColumnWidth( 3, typeWidth );
+ setColumnWidth( 4, lengthWidth );
+
+ int remaining = visibleWidth() - typeWidth - lengthWidth - columnWidth(0);
+
+ // now let's see if there is enough space for all
+ if( remaining >= artistWidth + titleWidth + filenameWidth ) {
+ remaining -= filenameWidth;
+ remaining -= (titleWidth + artistWidth);
+ setColumnWidth( 1, artistWidth + remaining/2 );
+ setColumnWidth( 2, titleWidth + remaining/2 );
+ setColumnWidth( 5, filenameWidth );
+ }
+ else if( remaining >= artistWidth + titleWidth + 20 ) {
+ setColumnWidth( 1, artistWidth );
+ setColumnWidth( 2, titleWidth );
+ setColumnWidth( 5, remaining - artistWidth - titleWidth );
+ }
+ else {
+ setColumnWidth( 1, remaining/3 );
+ setColumnWidth( 2, remaining/3 );
+ setColumnWidth( 5, remaining/3 );
+ }
+
+ triggerUpdate();
+ m_updatingColumnWidths = false;
+}
+
+
+void K3bAudioTrackView::slotAnimation()
+{
+ resizeColumns();
+ QListViewItem* item = firstChild();
+
+ bool animate = false;
+
+ while( item ) {
+ K3bAudioTrackViewItem* trackItem = dynamic_cast<K3bAudioTrackViewItem*>(item);
+ if( trackItem->animate() )
+ animate = true;
+ else
+ trackItem->setEnabled( true ); // files analysed, cd-text loaded
+ item = item->nextSibling();
+ }
+
+ if( !animate ) {
+ m_animationTimer->stop();
+ }
+}
+
+
+void K3bAudioTrackView::slotDragTimeout()
+{
+ m_autoOpenTrackTimer->stop();
+
+ if( m_currentMouseOverItem ) {
+ m_currentMouseOverItem->showSources( true );
+ }
+}
+
+
+void K3bAudioTrackView::getSelectedItems( QPtrList<K3bAudioTrack>& tracks,
+ QPtrList<K3bAudioDataSource>& sources )
+{
+ tracks.clear();
+ sources.clear();
+
+ QPtrList<QListViewItem> items = selectedItems();
+ for( QPtrListIterator<QListViewItem> it( items ); it.current(); ++it ) {
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>( *it ) )
+ tracks.append( tv->track() );
+ else {
+ K3bAudioDataSourceViewItem* sv = static_cast<K3bAudioDataSourceViewItem*>( *it );
+ // do not select hidden source items or unfinished source files
+ if( sv->trackViewItem()->showingSources() &&
+ !(sv->source()->isValid() && sv->source()->length() == 0) )
+ sources.append( sv->source() );
+ }
+ }
+}
+
+
+void K3bAudioTrackView::slotRemove()
+{
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+
+ //
+ // remove all sources which belong to one of the selected tracks since they will be
+ // deleted along with their tracks
+ //
+ QPtrListIterator<K3bAudioDataSource> srcIt( sources );
+ while( srcIt.current() ) {
+ if( tracks.containsRef( srcIt.current()->track() ) )
+ sources.removeRef( *srcIt );
+ else
+ ++srcIt;
+ }
+
+ //
+ // Now delete all the tracks
+ //
+ for( QPtrListIterator<K3bAudioTrack> it( tracks ); it.current(); ++it )
+ delete *it;
+
+ //
+ // Now delete all the sources
+ //
+ for( QPtrListIterator<K3bAudioDataSource> it( sources ); it.current(); ++it )
+ delete *it;
+}
+
+
+void K3bAudioTrackView::slotAddSilence()
+{
+ QListViewItem* item = selectedItems().first();
+ if( item ) {
+ //
+ // create a simple dialog for asking the length of the silence
+ //
+ KDialogBase dlg( KDialogBase::Plain,
+ i18n("Add Silence"),
+ KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Ok,
+ this );
+ QHBoxLayout* dlgLayout = new QHBoxLayout( dlg.plainPage(), 0, KDialog::spacingHint() );
+ dlgLayout->setAutoAdd( true );
+ (void)new QLabel( i18n("Length of silence:"), dlg.plainPage() );
+ K3bMsfEdit* msfEdit = new K3bMsfEdit( dlg.plainPage() );
+ msfEdit->setValue( 150 ); // 2 seconds default
+ msfEdit->setFocus();
+
+ if( dlg.exec() == QDialog::Accepted ) {
+ K3bAudioZeroData* zero = new K3bAudioZeroData( msfEdit->value() );
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>(item) ) {
+ tv->track()->addSource( zero );
+ }
+ else if( K3bAudioDataSourceViewItem* sv = dynamic_cast<K3bAudioDataSourceViewItem*>(item) ) {
+ zero->moveAfter( sv->source() );
+ }
+ }
+ }
+}
+
+
+void K3bAudioTrackView::slotMergeTracks()
+{
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+
+ // we simply merge the selected tracks ignoring any eventually selected sources
+ K3bAudioTrack* firstTrack = tracks.first();
+ tracks.remove();
+ while( K3bAudioTrack* mergeTrack = tracks.first() ) {
+ tracks.remove();
+ firstTrack->merge( mergeTrack, firstTrack->lastSource() );
+ }
+}
+
+
+void K3bAudioTrackView::slotSplitSource()
+{
+ QListViewItem* item = selectedItems().first();
+ if( K3bAudioDataSourceViewItem* sv = dynamic_cast<K3bAudioDataSourceViewItem*>(item) ) {
+ // create a new track
+ K3bAudioTrack* track = new K3bAudioTrack( m_doc );
+ K3bAudioTrack* trackAfter = sv->source()->track();
+ if( trackAfter->numberSources() == 1 )
+ trackAfter = trackAfter->prev();
+ track->addSource( sv->source()->take() );
+ track->moveAfter( trackAfter );
+
+ // let's see if it's a file because in that case we can reuse the metainfo :)
+ // TODO: maybe add meta data to sources
+ if( K3bAudioFile* file = dynamic_cast<K3bAudioFile*>( track->firstSource() ) ) {
+ track->setArtist( file->decoder()->metaInfo( K3bAudioDecoder::META_ARTIST ) );
+ track->setTitle( file->decoder()->metaInfo( K3bAudioDecoder::META_TITLE ) );
+ track->setSongwriter( file->decoder()->metaInfo( K3bAudioDecoder::META_SONGWRITER ) );
+ track->setComposer( file->decoder()->metaInfo( K3bAudioDecoder::META_COMPOSER ) );
+ track->setCdTextMessage( file->decoder()->metaInfo( K3bAudioDecoder::META_COMMENT ) );
+ }
+ }
+}
+
+
+void K3bAudioTrackView::slotSplitTrack()
+{
+ QListViewItem* item = selectedItems().first();
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>(item) ) {
+ K3bAudioTrackSplitDialog::splitTrack( tv->track(), this );
+ }
+}
+
+
+void K3bAudioTrackView::slotEditSource()
+{
+ QListViewItem* item = selectedItems().first();
+
+ K3bAudioDataSource* source = 0;
+ if( K3bAudioDataSourceViewItem* sv = dynamic_cast<K3bAudioDataSourceViewItem*>(item) )
+ source = sv->source();
+ else if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>(item) )
+ source = tv->track()->firstSource();
+
+ if( source ) {
+ KDialogBase dlg( KDialogBase::Plain,
+ i18n("Edit Audio Track Source"),
+ KDialogBase::Ok|KDialogBase::Cancel,
+ KDialogBase::Ok,
+ this,
+ 0,
+ true,
+ true );
+ QVBoxLayout* lay = new QVBoxLayout( dlg.plainPage() );
+ lay->setMargin( 0 );
+ lay->setSpacing( KDialog::spacingHint() );
+ lay->setAutoAdd( true );
+ K3bAudioDataSourceEditWidget* editW = new K3bAudioDataSourceEditWidget( dlg.plainPage() );
+ editW->loadSource( source );
+ if( dlg.exec() == QDialog::Accepted )
+ editW->saveSource();
+ }
+}
+
+
+void K3bAudioTrackView::showPopupMenu( KListView*, QListViewItem* item, const QPoint& pos )
+{
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+
+ int numTracks = tracks.count();
+ int numSources = sources.count();
+
+ // build the menu
+ m_popupMenu->clear();
+
+ if( numTracks >= 1 ) {
+ m_actionPlayTrack->plug( m_popupMenu );
+ m_popupMenu->insertSeparator();
+ }
+
+ if( item )
+ m_actionRemove->plug( m_popupMenu );
+
+ if( numSources + numTracks == 1 )
+ m_actionAddSilence->plug( m_popupMenu );
+
+ if( numSources == 1 && numTracks == 0 ) {
+ m_popupMenu->insertSeparator();
+ m_actionSplitSource->plug( m_popupMenu );
+ m_actionEditSource->plug( m_popupMenu );
+ }
+ else if( numTracks == 1 && numSources == 0 ) {
+ m_popupMenu->insertSeparator();
+
+
+
+ if( K3bAudioTrackViewItem* tv = dynamic_cast<K3bAudioTrackViewItem*>(item) )
+ if( tv->track()->length().lba() > 60 )
+ m_actionSplitTrack->plug( m_popupMenu );
+
+ m_actionEditSource->plug( m_popupMenu );
+
+ }
+ else if( numTracks > 1 ) {
+ m_popupMenu->insertSeparator();
+ m_actionMergeTracks->plug( m_popupMenu );
+ }
+
+ m_actionProperties->plug( m_popupMenu );
+ m_popupMenu->insertSeparator();
+ static_cast<K3bView*>(m_doc->view())->actionCollection()->action( "project_burn" )->plug( m_popupMenu );
+
+ m_popupMenu->popup( pos );
+}
+
+
+void K3bAudioTrackView::slotProperties()
+{
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+
+ // TODO: add tracks from sources to tracks
+
+ if( !tracks.isEmpty() ) {
+ K3bAudioTrackDialog d( tracks, this );
+ d.exec();
+ }
+ else {
+ static_cast<K3bView*>(m_doc->view())->slotProperties();
+ }
+}
+
+
+void K3bAudioTrackView::slotPlayTrack()
+{
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+ if( tracks.count() > 0 )
+ m_player->playTrack( tracks.first() );
+}
+
+
+void K3bAudioTrackView::showPlayerIndicator( K3bAudioTrack* track )
+{
+ removePlayerIndicator();
+ m_currentlyPlayingTrack = track;
+ K3bAudioTrackViewItem* item = getTrackViewItem( track );
+ item->setPixmap( 1, SmallIcon( "player_play" ) );
+ m_playerItemAnimator->setItem( item, 1 );
+}
+
+
+void K3bAudioTrackView::togglePauseIndicator( bool b )
+{
+ if( m_currentlyPlayingTrack ) {
+ if( b )
+ m_playerItemAnimator->setPixmap( SmallIcon( "player_pause" ) );
+ else
+ m_playerItemAnimator->setPixmap( SmallIcon( "player_play" ) );
+ }
+}
+
+
+void K3bAudioTrackView::removePlayerIndicator()
+{
+ if( m_currentlyPlayingTrack )
+ getTrackViewItem( m_currentlyPlayingTrack )->setPixmap( 1, QPixmap() );
+ m_playerItemAnimator->stop();
+ m_currentlyPlayingTrack = 0;
+}
+
+
+void K3bAudioTrackView::slotQueryMusicBrainz()
+{
+#ifdef HAVE_MUSICBRAINZ
+ QPtrList<K3bAudioTrack> tracks;
+ QPtrList<K3bAudioDataSource> sources;
+ getSelectedItems( tracks, sources );
+
+ if( tracks.isEmpty() ) {
+ KMessageBox::sorry( this, i18n("Please select an audio track.") );
+ return;
+ }
+
+ // only one may use the tracks at the same time
+ if( m_currentlyPlayingTrack &&
+ tracks.containsRef( m_currentlyPlayingTrack ) )
+ m_player->stop();
+
+ // now do the lookup on the files.
+ K3bAudioTrackTRMLookupDialog dlg( this );
+ dlg.lookup( tracks );
+#endif
+}
+
+#include "k3baudiotrackview.moc"