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:
@@ -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
|
||||||
{
|
{
|
||||||
|
@@ -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:
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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;
|
||||||
|
|
||||||
|
@@ -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 ) );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@@ -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();
|
||||||
|
@@ -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
|
||||||
|
@@ -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 ); }
|
||||||
|
@@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@@ -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
|
||||||
|
Reference in New Issue
Block a user