Commit 01d13d4b authored by Bart Cerneels's avatar Bart Cerneels
Browse files

Grey out playlist items when unplayable.

Patch by Sandeep Raghuraman

BUG: 263640
REVIEW: 102181
GUI:
parent 7a342e53
......@@ -8,6 +8,7 @@ Version 2.4.4-Beta 1
* Display current timestamp in tray tooltip. (BR 278445)
CHANGES:
* Mark unplayble tracks in the playlist. Patch by Sandeep Raghuraman. (BR 263640)
* Current track applet: show number of artists instead of genres. (BR 261077)
BUGFIXES:
......
......@@ -72,7 +72,13 @@ AudioCdTrack::prettyUrl() const
bool
AudioCdTrack::isPlayable() const
{
return true;
KUrl trackUrl = playableUrl();
QFileInfo trackFileInfo = QFileInfo( trackUrl.toLocalFile() );
//track can be played only if it's readable
if( trackFileInfo.exists() && trackFileInfo.isFile() && trackFileInfo.isReadable() )
return true;
return false;
}
bool
......
......@@ -29,6 +29,7 @@ target_link_libraries(amarok_collection-daapcollection
${KDE4_THREADWEAVER_LIBRARIES}
${KDE4_KDNSSD_LIBS}
${QT_QTNETWORK_LIBRARY}
${KDE4_SOLID_LIBS}
)
if(APPLE)
......
......@@ -18,6 +18,8 @@
#include "DaapCollection.h"
#include <Solid/Networking>
using namespace Meta;
DaapTrack::DaapTrack( Collections::DaapCollection *collection, const QString &host, quint16 port, const QString &dbId, const QString &itemId, const QString &format)
......@@ -75,6 +77,10 @@ DaapTrack::prettyUrl() const
bool
DaapTrack::isPlayable() const
{
//daap tracks are accessed over the network, so check if network connectivity is present
if( Solid::Networking::status() != Solid::Networking::Connected )
return false;
return true;
}
......
......@@ -157,7 +157,12 @@ MediaDeviceTrack::prettyUrl() const
bool
MediaDeviceTrack::isPlayable() const
{
return true;
KUrl trackUrl = playableUrl();
QFileInfo trackFileInfo = QFileInfo( trackUrl.pathOrUrl() );
if( trackFileInfo.exists() && trackFileInfo.isFile() && trackFileInfo.isReadable() )
return true;
return false;
}
bool
......
......@@ -22,6 +22,7 @@
#include "covermanager/CoverFetchingActions.h"
#include "core/capabilities/ActionsCapability.h"
#include <Solid/Networking>
#include <QAction>
......@@ -73,6 +74,9 @@ UpnpTrack::prettyUrl() const
bool
UpnpTrack::isPlayable() const
{
if( Solid::Networking::status() != Solid::Networking::Connected )
return false;
return true;
}
......
......@@ -35,6 +35,7 @@
#include "amarokurls/PlayUrlRunner.h"
#include <QAction>
#include <QFileInfo>
#include <QList>
#include <QWeakPointer>
#include <QString>
......@@ -253,7 +254,12 @@ Track::setUidUrl( const QString &newUid ) const
bool
Track::isPlayable() const
{
//simple implementation, check Internet connectivity or ping server?
KUrl trackUrl = playableUrl();
QFileInfo trackFileInfo = QFileInfo( trackUrl.pathOrUrl() );
if( !( trackFileInfo.exists() && trackFileInfo.isFile() && trackFileInfo.isReadable() ) )
return false;
return true;
}
......
......@@ -21,6 +21,8 @@
#include "core/meta/Meta.h"
#include "core-impl/meta/default/DefaultMetaTypes.h"
#include <Solid/Networking>
#include <QWeakPointer>
#include <QString>
......@@ -93,7 +95,9 @@ Track::uidUrl() const
bool
Track::isPlayable() const
{
//simple implementation, check Internet connectivity or ping server?
if( Solid::Networking::status() != Solid::Networking::Connected )
return false;
return true;
}
......
......@@ -4,6 +4,7 @@
* Copyright (c) 2008 Nikolaj Hald Nielsen <nhn@kde.org> *
* Copyright (c) 2009 Téo Mrnjavac <teo@kde.org> *
* Copyright (c) 2010 Nanno Langstraat <langstr@gmail.com> *
* Copyright (c) 2011 Sandeep Raghuraman <sandy.8925@gmail.com> *
* *
* 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 *
......@@ -91,13 +92,37 @@ Playlist::StandardTrackNavigator::chooseNextTrack( bool repeatPlaylist )
if( m_onlyQueue )
return 0;
int nextRow = m_model->activeRow() + 1; // 'activeRow()' may be -1.
Meta::TrackPtr track;
bool playableTrackFound = false;
int nextRow;
//search for a playable track in order from right after the currently active track till the end
for( nextRow = m_model->activeRow() + 1 ; nextRow < m_model->qaim()->rowCount() ; nextRow++ ) // 'activeRow()' may be -1.
{
track = m_model->trackAt(nextRow);
if( track->isPlayable() )
{
playableTrackFound = true;
break;
}
}
if( nextRow >= m_model->qaim()->rowCount() )
if( repeatPlaylist )
nextRow = 0; // This row is still invalid if 'rowCount() == 0'.
//if no playable track was found and the playlist needs to be repeated, search from top of playlist till currently active track
if( !playableTrackFound && repeatPlaylist )
{
//nextRow=0; This row is still invalid if 'rowCount() == 0'.
for( nextRow = 0 ; nextRow < m_model->activeRow() ; nextRow++)
{
track = m_model->trackAt( nextRow );
if( track->isPlayable() )
{
playableTrackFound = true;
break;
}
}
}
if( m_model->rowExists( nextRow ) )
if( playableTrackFound && m_model->rowExists( nextRow ) )
return m_model->idAt( nextRow );
else
return 0;
......
......@@ -54,9 +54,11 @@ Playlist::TrackNavigator::queueId( const quint64 id )
void
Playlist::TrackNavigator::queueIds( const QList<quint64> &ids )
{
Meta::TrackPtr track;
foreach( quint64 id, ids )
{
if( !m_queue.contains( id ) )
track = m_model->trackForId( id );
if( !m_queue.contains( id ) && track->isPlayable() )
m_queue.enqueue( id );
}
}
......
......@@ -57,8 +57,8 @@ Playlist::ViewCommon::trackMenu( QWidget *parent, const QModelIndex *index, cons
menu->addActions( parentCheckActions( parent, trackActionsFor( parent, index ) ) );
menu->addSeparator();
QList<QAction*> albumActionsList = parentCheckActions( parent, albumActionsFor( index ) );
if ( !albumActionsList.isEmpty() )
QList<QAction *> albumActionsList = parentCheckActions( parent, albumActionsFor( index ) );
if( !albumActionsList.isEmpty() )
{
// there are no cover actions if the song/album is not in the collection
KMenu *menuCover = new KMenu( i18n( "Album" ), menu );
......@@ -76,10 +76,10 @@ Playlist::ViewCommon::trackMenu( QWidget *parent, const QModelIndex *index, cons
}
QList<QAction*>
QList<QAction *>
Playlist::ViewCommon::actionsFor( QWidget *parent, const QModelIndex *index )
{
QList<QAction*> actions;
QList<QAction *> actions;
QAction *separator = new QAction( parent );
separator->setSeparator( true );
......@@ -87,8 +87,8 @@ Playlist::ViewCommon::actionsFor( QWidget *parent, const QModelIndex *index )
actions << parentCheckActions( parent, trackActionsFor( parent, index ) );
actions << separator;
QList<QAction*> albumActionsList = parentCheckActions( parent, albumActionsFor( index ) );
if ( !albumActionsList.isEmpty() )
QList<QAction *> albumActionsList = parentCheckActions( parent, albumActionsFor( index ) );
if( !albumActionsList.isEmpty() )
{
actions << albumActionsList;
actions << separator;
......@@ -102,10 +102,10 @@ Playlist::ViewCommon::actionsFor( QWidget *parent, const QModelIndex *index )
}
QList<QAction*>
QList<QAction *>
Playlist::ViewCommon::trackActionsFor( QWidget *parent, const QModelIndex *index )
{
QList<QAction*> actions;
QList<QAction *> actions;
Meta::TrackPtr track = index->data( Playlist::TrackRole ).value< Meta::TrackPtr >();
......@@ -114,40 +114,56 @@ Playlist::ViewCommon::trackActionsFor( QWidget *parent, const QModelIndex *index
const bool isQueued = index->data( Playlist::QueuePositionRole ).toInt() != 0;
const QString queueText = !isQueued ? i18n( "Queue Track" ) : i18n( "Dequeue Track" );
if( m_cueTrackAction == 0 )
//display "Queue track" option only if the track is playable
if( track->isPlayable() )
{
m_cueTrackAction = new QAction( KIcon( "media-track-queue-amarok" ), queueText, parent );
}
else
{
m_cueTrackAction->disconnect();
m_cueTrackAction->setText( queueText );
}
if( isQueued )
QObject::connect( m_cueTrackAction, SIGNAL( triggered() ), parent, SLOT( dequeueSelection() ) );
else
QObject::connect( m_cueTrackAction, SIGNAL( triggered() ), parent, SLOT( queueSelection() ) );
if( m_cueTrackAction == 0 )
{
m_cueTrackAction = new QAction( KIcon( "media-track-queue-amarok" ), queueText, parent );
}
else
{
m_cueTrackAction->disconnect();
m_cueTrackAction->setText( queueText );
}
actions << m_cueTrackAction;
if( isQueued )
QObject::connect( m_cueTrackAction, SIGNAL(triggered()),
parent, SLOT(dequeueSelection()) );
else
QObject::connect( m_cueTrackAction, SIGNAL(triggered()),
parent, SLOT(queueSelection()) );
actions << m_cueTrackAction;
}
//actions << separator;
const bool isCurrentTrack = index->data( Playlist::ActiveTrackRole ).toBool();
if( m_stopAfterTrackAction == 0 )
//display "Stop after this track" option only if track is playable. not sure if this check is really needed
if( track->isPlayable() )
{
m_stopAfterTrackAction = new QAction( KIcon( "media-playback-stop-amarok" ), i18n( "Stop Playing After This Track" ), parent );
QObject::connect( m_stopAfterTrackAction, SIGNAL( triggered() ), parent, SLOT( stopAfterTrack() ) );
if( m_stopAfterTrackAction == 0 )
{
m_stopAfterTrackAction = new QAction( KIcon( "media-playback-stop-amarok" ),
i18n( "Stop Playing After This Track" ), parent );
QObject::connect( m_stopAfterTrackAction, SIGNAL(triggered()),
parent, SLOT(stopAfterTrack()) );
}
actions << m_stopAfterTrackAction;
}
actions << m_stopAfterTrackAction;
//actions << separator;
if( m_removeTracTrackAction == 0 )
{
m_removeTracTrackAction = new QAction( KIcon( "media-track-remove-amarok" ), i18n( "Remove From Playlist" ), parent );
QObject::connect( m_removeTracTrackAction, SIGNAL( triggered() ), parent, SLOT( removeSelection() ) );
m_removeTracTrackAction = new QAction( KIcon( "media-track-remove-amarok" ),
i18n( "Remove From Playlist" ), parent );
QObject::connect( m_removeTracTrackAction, SIGNAL(triggered()),
parent, SLOT(removeSelection()) );
}
actions << m_removeTracTrackAction;
......@@ -156,13 +172,14 @@ Playlist::ViewCommon::trackActionsFor( QWidget *parent, const QModelIndex *index
{
//actions << separator;
QList<QAction*> globalCurrentTrackActions = The::globalCurrentTrackActions()->actions();
QList<QAction *> globalCurrentTrackActions = The::globalCurrentTrackActions()->actions();
foreach( QAction *action, globalCurrentTrackActions )
actions << action;
if( track->hasCapabilityInterface( Capabilities::Capability::Actions ) )
{
QScopedPointer< Capabilities::ActionsCapability > ac( track->create<Capabilities::ActionsCapability>() );
QScopedPointer<Capabilities::ActionsCapability>
ac( track->create<Capabilities::ActionsCapability>() );
if ( ac )
actions.append( ac->actions() );
}
......@@ -172,8 +189,10 @@ Playlist::ViewCommon::trackActionsFor( QWidget *parent, const QModelIndex *index
{
if( m_findInSourceAction == 0 )
{
m_findInSourceAction = new QAction( KIcon( "edit-find" ), i18n( "Show in Media Sources" ), parent );
QObject::connect( m_findInSourceAction, SIGNAL( triggered() ), parent, SLOT( findInSource() ) );
m_findInSourceAction = new QAction( KIcon( "edit-find" ),
i18n( "Show in Media Sources" ), parent );
QObject::connect( m_findInSourceAction, SIGNAL(triggered()),
parent, SLOT(findInSource()) );
}
actions << m_findInSourceAction;
}
......@@ -181,17 +200,18 @@ Playlist::ViewCommon::trackActionsFor( QWidget *parent, const QModelIndex *index
return actions;
}
QList<QAction*>
QList<QAction *>
Playlist::ViewCommon::albumActionsFor( const QModelIndex *index )
{
QList<QAction*> actions;
QList<QAction *> actions;
Meta::TrackPtr track = index->data( Playlist::TrackRole ).value< Meta::TrackPtr >();
Meta::AlbumPtr album = track->album();
if( album )
{
QScopedPointer< Capabilities::ActionsCapability > ac( album->create<Capabilities::ActionsCapability>() );
QScopedPointer<Capabilities::ActionsCapability>
ac( album->create<Capabilities::ActionsCapability>() );
if( ac )
actions.append( ac->actions() );
}
......@@ -200,18 +220,19 @@ Playlist::ViewCommon::albumActionsFor( const QModelIndex *index )
}
QList<QAction*>
QList<QAction *>
Playlist::ViewCommon::multiSourceActionsFor( QWidget *parent, const QModelIndex *index )
{
QList<QAction*> actions;
QList<QAction *> actions;
Meta::TrackPtr track = index->data( Playlist::TrackRole ).value< Meta::TrackPtr >();
const bool isMultiSource = index->data( Playlist::MultiSourceRole ).toBool();
if( isMultiSource )
{
QAction *selectSourceAction = new QAction( KIcon( "media-playlist-repeat" ), i18n( "Select Source" ), parent );
QObject::connect( selectSourceAction, SIGNAL( triggered() ), parent, SLOT( selectSource() ) );
QAction *selectSourceAction = new QAction( KIcon( "media-playlist-repeat" ),
i18n( "Select Source" ), parent );
QObject::connect( selectSourceAction, SIGNAL(triggered()), parent, SLOT(selectSource()) );
actions << selectSourceAction;
}
......@@ -220,23 +241,24 @@ Playlist::ViewCommon::multiSourceActionsFor( QWidget *parent, const QModelIndex
}
QList<QAction*>
QList<QAction *>
Playlist::ViewCommon::editActionsFor( QWidget *parent, const QModelIndex *index )
{
QList<QAction*> actions;
QList<QAction *> actions;
Meta::TrackPtr track = index->data( Playlist::TrackRole ).value< Meta::TrackPtr >();
QAction *editAction = new QAction( KIcon( "media-track-edit-amarok" ), i18n( "Edit Track Details" ), parent );
QAction *editAction = new QAction( KIcon( "media-track-edit-amarok" ),
i18n( "Edit Track Details" ), parent );
editAction->setProperty( "popupdropper_svg_id", "edit" );
QObject::connect( editAction, SIGNAL( triggered() ), parent, SLOT( editTrackInformation() ) );
QObject::connect( editAction, SIGNAL(triggered()), parent, SLOT(editTrackInformation()) );
actions << editAction;
return actions;
}
QList<QAction*>
Playlist::ViewCommon::parentCheckActions( QObject *parent, QList<QAction*> actions )
QList<QAction *>
Playlist::ViewCommon::parentCheckActions( QObject *parent, QList<QAction *> actions )
{
foreach( QAction *action, actions )
{
......@@ -246,4 +268,3 @@ Playlist::ViewCommon::parentCheckActions( QObject *parent, QList<QAction*> actio
return actions;
}
......@@ -3,6 +3,7 @@
* Copyright (c) 2008-2009 Nikolaj Hald Nielsen <nhn@kde.org> *
* Copyright (c) 2008 Soren Harward <stharward@gmail.com> *
* Copyright (c) 2010 Nanno Langstraat <langstr@gmail.com> *
* Copyright (c) 2011 Sandeep Raghuraman <sandy.8925@gmail.com> *
* *
* 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 *
......@@ -503,12 +504,31 @@ void Playlist::PrettyItemDelegate::paintItem( const LayoutItemConfig &config,
painter->drawPixmap( currentItemX, rowOffsetY + 4, moodbar );
}
}
//actual playlist item text is drawn here
else
{
//TODO: get rid of passing TrackPtr as data, use custom role instead
Meta::TrackPtr track = index.data( TrackRole ).value<Meta::TrackPtr>();
QString text = textIndex.data( Qt::DisplayRole ).toString();
text = element.prefix() + text + element.suffix();
text = QFontMetricsF( font ).elidedText( text, Qt::ElideRight, itemWidth );
painter->drawText( currentItemX, rowOffsetY, itemWidth, rowHeight, alignment, text );
//if the track can't be played, it should be grayed out to show that it is unavailable
if( !track->isPlayable() )
{
painter->save();
QPen grayPen = painter->pen();
grayPen.setColor( QColor( 127, 127, 127 ) );
painter->setPen( grayPen );
painter->drawText( currentItemX, rowOffsetY, itemWidth, rowHeight, alignment,
text );
painter->restore();
}
else
{
painter->drawText( currentItemX, rowOffsetY, itemWidth, rowHeight, alignment,
text );
}
}
currentItemX += itemWidth;
}
......
......@@ -17,6 +17,7 @@
#include "AmpacheMeta.h"
#include "core/support/Debug.h"
#include <Solid/Networking>
using namespace Meta;
......@@ -49,3 +50,11 @@ QList< QAction * > Meta::AmpacheTrack::currentTrackActions()
return actions;
}
bool
AmpacheTrack::isPlayable() const
{
if( Solid::Networking::status() != Solid::Networking::Connected )
return true;
return false;
}
......@@ -46,6 +46,7 @@ public:
virtual QString sourceDescription() { return "The Ampache music server project: http://Ampache.org"; }
virtual QPixmap emblem() { return QPixmap( KStandardDirs::locate( "data", "amarok/images/emblem-ampache.png" ) ); }
virtual QString scalableEmblem() { return KStandardDirs::locate( "data", "amarok/images/emblem-ampache-scalable.svgz" ); }
virtual bool isPlayable() const;
virtual QList< QAction *> currentTrackActions();
......
......@@ -60,6 +60,7 @@ install(TARGETS ampache_account_login DESTINATION ${INSTALL_TARGETS_DEFAULT_ARGS
${KDE4_KIO_LIBS}
${KDE4_THREADWEAVER_LIBRARIES}
${QT_QTXML_LIBRARY}
${KDE4_SOLID_LIBS}
)
if( LIBLASTFM_FOUND )
target_link_libraries(amarok_service_ampache
......
......@@ -36,6 +36,7 @@
#include <KLocale>
#include <KSharedPtr>
#include <KStandardDirs>
#include <Solid/Networking>
#include <QWeakPointer>
#include <QUrl>
......@@ -178,7 +179,9 @@ Track::uidUrl() const
bool
Track::isPlayable() const
{
//we could check connectivity here...
if( Solid::Networking::status() != Solid::Networking::Connected )
return false;
return !d->trackPath.isEmpty();
}
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment