1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-08-07 06:36:55 +02:00

Create copyable artist and album page links

This commit is contained in:
Leo Franchi
2012-06-17 00:09:03 +02:00
parent b1b9ee46db
commit 89ab3344d4
11 changed files with 187 additions and 30 deletions

View File

@@ -97,6 +97,48 @@ GlobalActionManager::openLinkFromQuery( const query_ptr& query ) const
} }
QUrl
GlobalActionManager::copyOpenLink( const query_ptr& query ) const
{
const QUrl link = openLinkFromQuery( query );
QClipboard* cb = QApplication::clipboard();
QByteArray data = link.toEncoded();
data.replace( "'", "%27" ); // QUrl doesn't encode ', which it doesn't have to. Some apps don't like ' though, and want %27. Both are valid.
cb->setText( data );
return link;
}
QUrl
GlobalActionManager::copyOpenLink( const artist_ptr& artist ) const
{
const QUrl link( QString( "%1/artist/%2" ).arg( hostname() ).arg( artist->name() ) );
QClipboard* cb = QApplication::clipboard();
QByteArray data = link.toEncoded();
data.replace( "'", "%27" ); // QUrl doesn't encode ', which it doesn't have to. Some apps don't like ' though, and want %27. Both are valid.
cb->setText( data );
return link;
}
QUrl
GlobalActionManager::copyOpenLink( const album_ptr& album ) const
{
const QUrl link( QString( "%1/album/%2/%3" ).arg( hostname() ).arg( album->artist().isNull() ? QString() : album->artist()->name() ).arg( album->name()) );
QClipboard* cb = QApplication::clipboard();
QByteArray data = link.toEncoded();
data.replace( "'", "%27" ); // QUrl doesn't encode ', which it doesn't have to. Some apps don't like ' though, and want %27. Both are valid.
cb->setText( data );
return link;
}
QUrl QUrl
GlobalActionManager::openLink( const QString& title, const QString& artist, const QString& album ) const GlobalActionManager::openLink( const QString& title, const QString& artist, const QString& album ) const
{ {

View File

@@ -43,6 +43,11 @@ public:
virtual ~GlobalActionManager(); virtual ~GlobalActionManager();
QUrl openLinkFromQuery( const Tomahawk::query_ptr& query ) const; QUrl openLinkFromQuery( const Tomahawk::query_ptr& query ) const;
QUrl copyOpenLink( const Tomahawk::artist_ptr& artist ) const;
QUrl copyOpenLink( const Tomahawk::album_ptr& album ) const;
QUrl copyOpenLink( const Tomahawk::query_ptr& query ) const;
QUrl openLink( const QString& title, const QString& artist, const QString& album ) const; QUrl openLink( const QString& title, const QString& artist, const QString& album ) const;
public slots: public slots:

View File

@@ -55,6 +55,8 @@ public:
AlbumInfoWidget( const Tomahawk::album_ptr& album, QWidget* parent = 0 ); AlbumInfoWidget( const Tomahawk::album_ptr& album, QWidget* parent = 0 );
~AlbumInfoWidget(); ~AlbumInfoWidget();
Tomahawk::album_ptr album() const { return m_album; }
virtual QWidget* widget() { return this; } virtual QWidget* widget() { return this; }
virtual Tomahawk::playlistinterface_ptr playlistInterface() const; virtual Tomahawk::playlistinterface_ptr playlistInterface() const;

View File

@@ -66,6 +66,8 @@ public:
*/ */
void load( const Tomahawk::artist_ptr& artist ); void load( const Tomahawk::artist_ptr& artist );
Tomahawk::artist_ptr artist() const { return m_artist; }
virtual QWidget* widget() { return this; } virtual QWidget* widget() { return this; }
virtual Tomahawk::playlistinterface_ptr playlistInterface() const; virtual Tomahawk::playlistinterface_ptr playlistInterface() const;

View File

@@ -54,6 +54,8 @@ public:
TrackInfoWidget( const Tomahawk::query_ptr& query, QWidget* parent = 0 ); TrackInfoWidget( const Tomahawk::query_ptr& query, QWidget* parent = 0 );
~TrackInfoWidget(); ~TrackInfoWidget();
Tomahawk::query_ptr query() const { return m_query; }
virtual QWidget* widget() { return this; } virtual QWidget* widget() { return this; }
virtual Tomahawk::playlistinterface_ptr playlistInterface() const; virtual Tomahawk::playlistinterface_ptr playlistInterface() const;

View File

@@ -568,6 +568,8 @@ SourceTreeView::onCustomContextMenu( const QPoint& pos )
setupMenus(); setupMenus();
const QList< QAction* > customActions = model()->data( m_contextMenuIndex, SourcesModel::CustomActionRole ).value< QList< QAction* > >();
if ( model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::StaticPlaylist || if ( model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::StaticPlaylist ||
model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::AutomaticPlaylist || model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::AutomaticPlaylist ||
model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::Station ) model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ) == SourcesModel::Station )
@@ -586,6 +588,12 @@ SourceTreeView::onCustomContextMenu( const QPoint& pos )
else if ( !item->source().isNull() ) else if ( !item->source().isNull() )
m_privacyMenu.exec( mapToGlobal( pos ) ); m_privacyMenu.exec( mapToGlobal( pos ) );
} }
else if ( !customActions.isEmpty() )
{
QMenu customMenu;
customMenu.addActions( customActions );
customMenu.exec( mapToGlobal( pos ) );
}
} }

View File

@@ -107,39 +107,43 @@ SourcesModel::data( const QModelIndex& index, int role ) const
switch ( role ) switch ( role )
{ {
case Qt::SizeHintRole: case Qt::SizeHintRole:
return QSize( 0, 18 ); return QSize( 0, 18 );
case SourceTreeItemRole: case SourceTreeItemRole:
return QVariant::fromValue< SourceTreeItem* >( item ); return QVariant::fromValue< SourceTreeItem* >( item );
case SourceTreeItemTypeRole: case SourceTreeItemTypeRole:
return item->type(); return item->type();
case Qt::DisplayRole: case Qt::DisplayRole:
case Qt::EditRole: case Qt::EditRole:
return item->text(); return item->text();
case Qt::DecorationRole: case Qt::DecorationRole:
return item->icon(); return item->icon();
case SourcesModel::SortRole: case SourcesModel::SortRole:
return item->peerSortValue(); return item->peerSortValue();
case SourcesModel::IDRole: case SourcesModel::IDRole:
return item->IDValue(); return item->IDValue();
case SourcesModel::LatchedOnRole: case SourcesModel::LatchedOnRole:
{
if ( item->type() == Collection )
{ {
if ( item->type() == Collection ) SourceItem* cItem = qobject_cast< SourceItem* >( item );
{ return cItem->localLatchedOn();
SourceItem* cItem = qobject_cast< SourceItem* >( item );
return cItem->localLatchedOn();
}
return false;
} }
case SourcesModel::LatchedRealtimeRole: return false;
}
case SourcesModel::LatchedRealtimeRole:
{
if ( item->type() == Collection )
{ {
if ( item->type() == Collection ) SourceItem* cItem = qobject_cast< SourceItem* >( item );
{ return cItem->localLatchMode() == Tomahawk::PlaylistModes::RealTime;
SourceItem* cItem = qobject_cast< SourceItem* >( item );
return cItem->localLatchMode() == Tomahawk::PlaylistModes::RealTime;
}
return false;
} }
return false;
}
case SourcesModel::CustomActionRole:
{
return QVariant::fromValue< QList< QAction* > >( item->customActions() );
}
case Qt::ToolTipRole: case Qt::ToolTipRole:
if ( !item->tooltip().isEmpty() ) if ( !item->tooltip().isEmpty() )
return item->tooltip(); return item->tooltip();

View File

@@ -28,6 +28,9 @@
#include "Typedefs.h" #include "Typedefs.h"
#include "Source.h" #include "Source.h"
#include <QList>
#include <QAction>
class QMimeData; class QMimeData;
class SourceTreeItem; class SourceTreeItem;
@@ -72,7 +75,8 @@ public:
SortRole = Qt::UserRole + 12, SortRole = Qt::UserRole + 12,
IDRole = Qt::UserRole + 13, IDRole = Qt::UserRole + 13,
LatchedOnRole = Qt::UserRole + 14, LatchedOnRole = Qt::UserRole + 14,
LatchedRealtimeRole = Qt::UserRole + 15 LatchedRealtimeRole = Qt::UserRole + 15,
CustomActionRole = Qt::UserRole + 16 // QList< QAction* >
}; };
SourcesModel( QObject* parent = 0 ); SourcesModel( QObject* parent = 0 );
@@ -149,4 +153,6 @@ private:
Tomahawk::ViewPage* m_viewPageDelayedCacheItem; Tomahawk::ViewPage* m_viewPageDelayedCacheItem;
}; };
Q_DECLARE_METATYPE( QList< QAction* > )
#endif // SOURCESMODEL_H #endif // SOURCESMODEL_H

View File

@@ -70,6 +70,7 @@ public:
virtual void setDropType( DropType type ) { m_dropType = type; } virtual void setDropType( DropType type ) { m_dropType = type; }
virtual DropType dropType() const { return m_dropType; } virtual DropType dropType() const { return m_dropType; }
virtual bool isBeingPlayed() const { return false; } virtual bool isBeingPlayed() const { return false; }
virtual QList< QAction* > customActions() const { return QList< QAction* >(); }
/// don't call me unless you are a sourcetreeitem. i prefer this to making everyone a friend /// don't call me unless you are a sourcetreeitem. i prefer this to making everyone a friend
void beginRowsAdded( int from, int to ) { emit beginChildRowsAdded( from, to ); } void beginRowsAdded( int from, int to ) { emit beginChildRowsAdded( from, to ); }

View File

@@ -17,11 +17,24 @@
*/ */
#include "TemporaryPageItem.h" #include "TemporaryPageItem.h"
#include "GlobalActionManager.h"
#include "ViewManager.h" #include "ViewManager.h"
#include "widgets/infowidgets/AlbumInfoWidget.h" #include "widgets/infowidgets/AlbumInfoWidget.h"
#include "widgets/infowidgets/ArtistInfoWidget.h" #include "widgets/infowidgets/ArtistInfoWidget.h"
#include "widgets/infowidgets/TrackInfoWidget.h" #include "widgets/infowidgets/TrackInfoWidget.h"
#include "widgets/SearchWidget.h" #include "widgets/SearchWidget.h"
#include "utils/Closure.h"
#include <QAction>
namespace {
enum LinkType {
ArtistLink,
AlbumLink,
TrackLink
};
}
using namespace Tomahawk; using namespace Tomahawk;
@@ -31,14 +44,39 @@ TemporaryPageItem::TemporaryPageItem ( SourcesModel* mdl, SourceTreeItem* parent
, m_icon( QIcon( RESPATH "images/playlist-icon.png" ) ) , m_icon( QIcon( RESPATH "images/playlist-icon.png" ) )
, m_sortValue( sortValue ) , m_sortValue( sortValue )
{ {
QAction* action = 0;
if ( dynamic_cast< ArtistInfoWidget* >( page ) ) if ( dynamic_cast< ArtistInfoWidget* >( page ) )
{
action = new QAction( tr( "Copy Artist Link" ), this );
action->setProperty( "linkType", (int)ArtistLink );
m_icon = QIcon( RESPATH "images/artist-icon.png" ); m_icon = QIcon( RESPATH "images/artist-icon.png" );
}
else if ( dynamic_cast< AlbumInfoWidget* >( page ) ) else if ( dynamic_cast< AlbumInfoWidget* >( page ) )
{
action = new QAction( tr( "Copy Album Link" ), this );
action->setProperty( "linkType", (int)AlbumLink );
m_icon = QIcon( RESPATH "images/album-icon.png" ); m_icon = QIcon( RESPATH "images/album-icon.png" );
}
else if ( dynamic_cast< TrackInfoWidget* >( page ) ) else if ( dynamic_cast< TrackInfoWidget* >( page ) )
{
action = new QAction( tr( "Copy Track Link" ), this );
action->setProperty( "linkType", (int)TrackLink );
m_icon = QIcon( RESPATH "images/track-icon-sidebar.png" ); m_icon = QIcon( RESPATH "images/track-icon-sidebar.png" );
}
else if ( dynamic_cast< SearchWidget* >( page ) ) else if ( dynamic_cast< SearchWidget* >( page ) )
{
m_icon = QIcon( RESPATH "images/search-icon.png" ); m_icon = QIcon( RESPATH "images/search-icon.png" );
}
if ( action )
{
m_customActions << action;
NewClosure( action, SIGNAL( triggered() ), this, SLOT( linkActionTriggered( QAction* ) ), action );
}
model()->linkSourceItemToPage( this, page ); model()->linkSourceItemToPage( this, page );
} }
@@ -95,3 +133,41 @@ TemporaryPageItem::removeFromList()
deleteLater(); deleteLater();
} }
void
TemporaryPageItem::linkActionTriggered( QAction* action )
{
Q_ASSERT( action );
if ( !action )
return;
const LinkType type = (LinkType)action->property( "linkType" ).toInt();
switch( type )
{
case ArtistLink:
{
ArtistInfoWidget* aPage = dynamic_cast< ArtistInfoWidget* >( m_page );
Q_ASSERT( aPage );
GlobalActionManager::instance()->copyOpenLink( aPage->artist() );
break;
}
case AlbumLink:
{
AlbumInfoWidget* aPage = dynamic_cast< AlbumInfoWidget* >( m_page );
Q_ASSERT( aPage );
GlobalActionManager::instance()->copyOpenLink( aPage->album() );
break;
}
case TrackLink:
{
TrackInfoWidget* tPage = dynamic_cast< TrackInfoWidget* >( m_page );
Q_ASSERT( tPage );
GlobalActionManager::instance()->copyOpenLink( tPage->query() );
break;
}
}
}

View File

@@ -22,6 +22,8 @@
#include "items/SourceTreeItem.h" #include "items/SourceTreeItem.h"
#include "ViewPage.h" #include "ViewPage.h"
class QAction;
class TemporaryPageItem : public SourceTreeItem class TemporaryPageItem : public SourceTreeItem
{ {
Q_OBJECT Q_OBJECT
@@ -34,6 +36,7 @@ public:
virtual QIcon icon() const; virtual QIcon icon() const;
virtual int peerSortValue() const; virtual int peerSortValue() const;
virtual int IDValue() const; virtual int IDValue() const;
virtual QList< QAction* > customActions() const { return m_customActions; }
Tomahawk::ViewPage* page() const { return m_page; } Tomahawk::ViewPage* page() const { return m_page; }
virtual bool isBeingPlayed() const { return m_page->isBeingPlayed(); } virtual bool isBeingPlayed() const { return m_page->isBeingPlayed(); }
@@ -44,10 +47,16 @@ public slots:
signals: signals:
bool removed(); bool removed();
private slots:
void linkActionTriggered( QAction* );
private: private:
Tomahawk::ViewPage* m_page; Tomahawk::ViewPage* m_page;
QIcon m_icon; QIcon m_icon;
int m_sortValue; int m_sortValue;
QList< QAction* > m_customActions;
}; };
Q_DECLARE_METATYPE( QAction* )
#endif // TEMPORARYPAGEITEM_H #endif // TEMPORARYPAGEITEM_H