mirror of
https://github.com/tomahawk-player/tomahawk.git
synced 2025-07-31 11:20:22 +02:00
Support copying and parsing station and automatic playlist tomahawk:// links
This commit is contained in:
@@ -84,6 +84,48 @@ GlobalActionManager::openLinkFromQuery( const Tomahawk::query_ptr& query ) const
|
|||||||
return link;
|
return link;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GlobalActionManager::copyPlaylistToClipboard( const Tomahawk::dynplaylist_ptr& playlist )
|
||||||
|
{
|
||||||
|
QUrl link( "tomahawk://station/create/" );
|
||||||
|
|
||||||
|
if( playlist->generator()->type() != "echonest" ) {
|
||||||
|
qDebug() << "Only echonest generators are supported";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
link.addEncodedQueryItem( "type", "echonest" );
|
||||||
|
link.addQueryItem( "title", playlist->title() );
|
||||||
|
link.addQueryItem( "plmode", QString::number( static_cast<int>( playlist->mode() ) ) );
|
||||||
|
|
||||||
|
QList< Tomahawk::dyncontrol_ptr > controls = playlist->generator()->controls();
|
||||||
|
foreach( const Tomahawk::dyncontrol_ptr& c, controls ) {
|
||||||
|
if( c->selectedType() == "Artist" ) {
|
||||||
|
if( c->match().toInt() == Echonest::DynamicPlaylist::ArtistType )
|
||||||
|
link.addQueryItem( "artist_limit", c->input() );
|
||||||
|
else
|
||||||
|
link.addQueryItem( "artist", c->input() );
|
||||||
|
} else if( c->selectedType() == "Artist Description" ) {
|
||||||
|
link.addQueryItem( "description", c->input() );
|
||||||
|
} else {
|
||||||
|
QString name = c->selectedType().toLower().replace( " ", "_" );
|
||||||
|
Echonest::DynamicPlaylist::PlaylistParam p = static_cast< Echonest::DynamicPlaylist::PlaylistParam >( c->match().toInt() );
|
||||||
|
// if it is a max, set that too
|
||||||
|
if( p == Echonest::DynamicPlaylist::MaxTempo || p == Echonest::DynamicPlaylist::MaxDuration || p == Echonest::DynamicPlaylist::MaxLoudness
|
||||||
|
|| p == Echonest::DynamicPlaylist::MaxDanceability || p == Echonest::DynamicPlaylist::MaxEnergy || p == Echonest::DynamicPlaylist::ArtistMaxFamiliarity
|
||||||
|
|| p == Echonest::DynamicPlaylist::ArtistMaxHotttnesss || p == Echonest::DynamicPlaylist::SongMaxHotttnesss || p == Echonest::DynamicPlaylist::ArtistMaxLatitude
|
||||||
|
|| p == Echonest::DynamicPlaylist::ArtistMaxLongitude )
|
||||||
|
name += "_max";
|
||||||
|
|
||||||
|
link.addQueryItem( name, c->input() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QClipboard* cb = QApplication::clipboard();
|
||||||
|
cb->setText( link.toEncoded() );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
GlobalActionManager::copyToClipboard( const Tomahawk::query_ptr& query ) const
|
GlobalActionManager::copyToClipboard( const Tomahawk::query_ptr& query ) const
|
||||||
{
|
{
|
||||||
@@ -323,7 +365,12 @@ GlobalActionManager::handleStationCommand( const QUrl& url )
|
|||||||
}
|
}
|
||||||
QString title = url.queryItemValue( "title" );
|
QString title = url.queryItemValue( "title" );
|
||||||
QString type = url.queryItemValue( "type" );
|
QString type = url.queryItemValue( "type" );
|
||||||
Tomahawk::dynplaylist_ptr pl = Tomahawk::DynamicPlaylist::create( SourceList::instance()->getLocal(), uuid(), title, QString(), QString(), Tomahawk::OnDemand, false, type );
|
Tomahawk::GeneratorMode m = Tomahawk::OnDemand;
|
||||||
|
if( url.hasQueryItem( "plmode" ) && url.queryItemValue( "plmode" ).toInt() == 1 )
|
||||||
|
m = Tomahawk::Static;
|
||||||
|
|
||||||
|
Tomahawk::dynplaylist_ptr pl = Tomahawk::DynamicPlaylist::create( SourceList::instance()->getLocal(), uuid(), title, QString(), QString(), m, false, type );
|
||||||
|
pl->setMode( m );
|
||||||
QList< Tomahawk::dyncontrol_ptr > controls;
|
QList< Tomahawk::dyncontrol_ptr > controls;
|
||||||
QPair< QString, QString > param;
|
QPair< QString, QString > param;
|
||||||
foreach( param, url.queryItems() ) {
|
foreach( param, url.queryItems() ) {
|
||||||
@@ -332,14 +379,98 @@ GlobalActionManager::handleStationCommand( const QUrl& url )
|
|||||||
c->setInput( param.second );
|
c->setInput( param.second );
|
||||||
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistRadioType ) );
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistRadioType ) );
|
||||||
controls << c;
|
controls << c;
|
||||||
} /*else if( param.first == "hotttnesss" ) { TODO
|
} else if( param.first == "artist_limit" ) {
|
||||||
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Artist" );
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Artist" );
|
||||||
c->setInput( param.second );
|
c->setInput( param.second );
|
||||||
c->setMatch( 0 );
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistType ) );
|
||||||
controls << c;
|
controls << c;
|
||||||
} */
|
} else if( param.first == "description" ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Artist Description" );
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistDescriptionType ) );
|
||||||
|
controls << c;
|
||||||
|
} else if( param.first == "variety" ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Variety" );
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Variety ) );
|
||||||
|
controls << c;
|
||||||
|
} else if( param.first.startsWith( "tempo" ) ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Tempo" );
|
||||||
|
int extra = param.first.endsWith( "_max" ) ? -1 : 0;
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinTempo + extra ) );
|
||||||
|
controls << c;
|
||||||
|
} else if( param.first.startsWith( "duration" ) ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Duration" );
|
||||||
|
int extra = param.first.endsWith( "_max" ) ? -1 : 0;
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinDuration + extra ) );
|
||||||
|
controls << c;
|
||||||
|
} else if( param.first.startsWith( "loudness" ) ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Loudness" );
|
||||||
|
int extra = param.first.endsWith( "_max" ) ? -1 : 0;
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinLoudness + extra ) );
|
||||||
|
controls << c;
|
||||||
|
} else if( param.first.startsWith( "danceability" ) ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Danceability" );
|
||||||
|
int extra = param.first.endsWith( "_max" ) ? 1 : 0;
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinDanceability + extra ) );
|
||||||
|
controls << c;
|
||||||
|
} else if( param.first.startsWith( "energy" ) ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Energy" );
|
||||||
|
int extra = param.first.endsWith( "_max" ) ? 1 : 0;
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::MinEnergy + extra ) );
|
||||||
|
controls << c;
|
||||||
|
} else if( param.first.startsWith( "artist_familiarity" ) ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Artist Familiarity" );
|
||||||
|
int extra = param.first.endsWith( "_max" ) ? -1 : 0;
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinFamiliarity + extra ) );
|
||||||
|
controls << c;
|
||||||
|
} else if( param.first.startsWith( "artist_hotttnesss" ) ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Artist Hotttnesss" );
|
||||||
|
int extra = param.first.endsWith( "_max" ) ? -1 : 0;
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinFamiliarity + extra ) );
|
||||||
|
controls << c;
|
||||||
|
} else if( param.first.startsWith( "song_hotttnesss" ) ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Song Hotttnesss" );
|
||||||
|
int extra = param.first.endsWith( "_max" ) ? -1 : 0;
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::SongMinHotttnesss + extra ) );
|
||||||
|
controls << c;
|
||||||
|
} else if( param.first.startsWith( "longitude" ) ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Longitude" );
|
||||||
|
int extra = param.first.endsWith( "_max" ) ? 1 : 0;
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinLongitude + extra ) );
|
||||||
|
controls << c;
|
||||||
|
} else if( param.first.startsWith( "latitude" ) ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Latitude" );
|
||||||
|
int extra = param.first.endsWith( "_max" ) ? 1 : 0;
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::ArtistMinLatitude + extra ) );
|
||||||
|
controls << c;
|
||||||
|
} else if( param.first == "key" ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Key" );
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Key ) );
|
||||||
|
controls << c;
|
||||||
|
} else if( param.first == "mode" ) {
|
||||||
|
Tomahawk::dyncontrol_ptr c = pl->generator()->createControl( "Mode" );
|
||||||
|
c->setInput( param.second );
|
||||||
|
c->setMatch( QString::number( (int)Echonest::DynamicPlaylist::Mode ) );
|
||||||
|
controls << c;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
pl->createNewRevision( uuid(), pl->currentrevision(), type, controls );
|
if( m == Tomahawk::OnDemand )
|
||||||
|
pl->createNewRevision( uuid(), pl->currentrevision(), type, controls );
|
||||||
|
else
|
||||||
|
pl->createNewRevision( uuid(), pl->currentrevision(), type, controls, pl->entries() );
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -21,6 +21,8 @@
|
|||||||
#define GLOBALACTIONMANAGER_H
|
#define GLOBALACTIONMANAGER_H
|
||||||
|
|
||||||
#include "playlist.h"
|
#include "playlist.h"
|
||||||
|
#include "query.h"
|
||||||
|
#include "playlist/dynamic/DynamicPlaylist.h"
|
||||||
#include "dllmacro.h"
|
#include "dllmacro.h"
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
@@ -34,7 +36,9 @@ public:
|
|||||||
virtual ~GlobalActionManager();
|
virtual ~GlobalActionManager();
|
||||||
|
|
||||||
QUrl openLinkFromQuery( const Tomahawk::query_ptr& query ) const;
|
QUrl openLinkFromQuery( const Tomahawk::query_ptr& query ) const;
|
||||||
|
|
||||||
void copyToClipboard( const Tomahawk::query_ptr& query ) const;
|
void copyToClipboard( const Tomahawk::query_ptr& query ) const;
|
||||||
|
void copyPlaylistToClipboard( const Tomahawk::dynplaylist_ptr& playlist );
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
bool parseTomahawkLink( const QString& link );
|
bool parseTomahawkLink( const QString& link );
|
||||||
|
@@ -111,7 +111,6 @@ Tomahawk::EchonestControl::summary() const
|
|||||||
void
|
void
|
||||||
Tomahawk::EchonestControl::setInput(const QString& input)
|
Tomahawk::EchonestControl::setInput(const QString& input)
|
||||||
{
|
{
|
||||||
// TODO generate widgets
|
|
||||||
m_data.second = input;
|
m_data.second = input;
|
||||||
updateWidgetsFromData();
|
updateWidgetsFromData();
|
||||||
}
|
}
|
||||||
@@ -119,7 +118,6 @@ Tomahawk::EchonestControl::setInput(const QString& input)
|
|||||||
void
|
void
|
||||||
Tomahawk::EchonestControl::setMatch(const QString& match)
|
Tomahawk::EchonestControl::setMatch(const QString& match)
|
||||||
{
|
{
|
||||||
// TODO generate widgets
|
|
||||||
m_matchData = match;
|
m_matchData = match;
|
||||||
updateWidgetsFromData();
|
updateWidgetsFromData();
|
||||||
}
|
}
|
||||||
@@ -289,7 +287,7 @@ Tomahawk::EchonestControl::updateWidgets()
|
|||||||
m_match = QWeakPointer< QWidget >( match );
|
m_match = QWeakPointer< QWidget >( match );
|
||||||
m_input = QWeakPointer< QWidget >( combo );
|
m_input = QWeakPointer< QWidget >( combo );
|
||||||
} else if( selectedType() == "Sorting" ) {
|
} else if( selectedType() == "Sorting" ) {
|
||||||
m_currentType = Echonest::DynamicPlaylist::Key;
|
m_currentType = Echonest::DynamicPlaylist::Sort;
|
||||||
|
|
||||||
QComboBox* match = new QComboBox();
|
QComboBox* match = new QComboBox();
|
||||||
match->addItem( tr( "Ascending" ), 0 );
|
match->addItem( tr( "Ascending" ), 0 );
|
||||||
|
@@ -33,6 +33,7 @@
|
|||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QStyledItemDelegate>
|
#include <QStyledItemDelegate>
|
||||||
#include <QSize>
|
#include <QSize>
|
||||||
|
#include <globalactionmanager.h>
|
||||||
|
|
||||||
using namespace Tomahawk;
|
using namespace Tomahawk;
|
||||||
|
|
||||||
@@ -119,6 +120,7 @@ void
|
|||||||
SourceTreeView::setupMenus()
|
SourceTreeView::setupMenus()
|
||||||
{
|
{
|
||||||
m_playlistMenu.clear();
|
m_playlistMenu.clear();
|
||||||
|
m_roPlaylistMenu.clear();
|
||||||
|
|
||||||
bool readonly = true;
|
bool readonly = true;
|
||||||
SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt();
|
SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt();
|
||||||
@@ -136,14 +138,22 @@ SourceTreeView::setupMenus()
|
|||||||
m_loadPlaylistAction = m_playlistMenu.addAction( tr( "&Load Playlist" ) );
|
m_loadPlaylistAction = m_playlistMenu.addAction( tr( "&Load Playlist" ) );
|
||||||
m_renamePlaylistAction = m_playlistMenu.addAction( tr( "&Rename Playlist" ) );
|
m_renamePlaylistAction = m_playlistMenu.addAction( tr( "&Rename Playlist" ) );
|
||||||
m_playlistMenu.addSeparator();
|
m_playlistMenu.addSeparator();
|
||||||
|
|
||||||
|
m_copyPlaylistAction = m_playlistMenu.addAction( tr( "&Copy Playlist Link" ) );
|
||||||
m_deletePlaylistAction = m_playlistMenu.addAction( tr( "&Delete %1" ).arg( SourcesModel::rowTypeToString( type ) ) );
|
m_deletePlaylistAction = m_playlistMenu.addAction( tr( "&Delete %1" ).arg( SourcesModel::rowTypeToString( type ) ) );
|
||||||
|
|
||||||
|
m_roPlaylistMenu.addAction( m_copyPlaylistAction );
|
||||||
|
|
||||||
m_deletePlaylistAction->setEnabled( !readonly );
|
m_deletePlaylistAction->setEnabled( !readonly );
|
||||||
m_renamePlaylistAction->setEnabled( !readonly );
|
m_renamePlaylistAction->setEnabled( !readonly );
|
||||||
|
|
||||||
|
if ( type == SourcesModel::StaticPlaylist )
|
||||||
|
m_copyPlaylistAction->setText( tr( "&Export Playlist" ) );
|
||||||
|
|
||||||
connect( m_loadPlaylistAction, SIGNAL( triggered() ), SLOT( loadPlaylist() ) );
|
connect( m_loadPlaylistAction, SIGNAL( triggered() ), SLOT( loadPlaylist() ) );
|
||||||
connect( m_renamePlaylistAction, SIGNAL( triggered() ), SLOT( renamePlaylist() ) );
|
connect( m_renamePlaylistAction, SIGNAL( triggered() ), SLOT( renamePlaylist() ) );
|
||||||
connect( m_deletePlaylistAction, SIGNAL( triggered() ), SLOT( deletePlaylist() ) );
|
connect( m_deletePlaylistAction, SIGNAL( triggered() ), SLOT( deletePlaylist() ) );
|
||||||
|
connect( m_copyPlaylistAction, SIGNAL( triggered() ), SLOT( copyPlaylistLink() ) );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -223,6 +233,22 @@ SourceTreeView::deletePlaylist()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
SourceTreeView::copyPlaylistLink()
|
||||||
|
{
|
||||||
|
QModelIndex idx = m_contextMenuIndex;
|
||||||
|
if ( !idx.isValid() )
|
||||||
|
return;
|
||||||
|
|
||||||
|
SourcesModel::RowType type = ( SourcesModel::RowType )model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ).toInt();
|
||||||
|
if( type == SourcesModel::AutomaticPlaylist || type == SourcesModel::Station )
|
||||||
|
{
|
||||||
|
DynamicPlaylistItem* item = itemFromIndex< DynamicPlaylistItem >( m_contextMenuIndex );
|
||||||
|
dynplaylist_ptr playlist = item->dynPlaylist();
|
||||||
|
GlobalActionManager::instance()->copyPlaylistToClipboard( playlist );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
SourceTreeView::renamePlaylist()
|
SourceTreeView::renamePlaylist()
|
||||||
@@ -252,6 +278,8 @@ SourceTreeView::onCustomContextMenu( const QPoint& pos )
|
|||||||
PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex );
|
PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex );
|
||||||
if( item->playlist()->author()->isLocal() )
|
if( item->playlist()->author()->isLocal() )
|
||||||
m_playlistMenu.exec( mapToGlobal( pos ) );
|
m_playlistMenu.exec( mapToGlobal( pos ) );
|
||||||
|
else if( model()->data( m_contextMenuIndex, SourcesModel::SourceTreeItemTypeRole ) != SourcesModel::StaticPlaylist )
|
||||||
|
m_roPlaylistMenu.exec( mapToGlobal( pos ) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -53,6 +53,7 @@ private slots:
|
|||||||
|
|
||||||
void loadPlaylist();
|
void loadPlaylist();
|
||||||
void deletePlaylist();
|
void deletePlaylist();
|
||||||
|
void copyPlaylistLink();
|
||||||
|
|
||||||
void onCustomContextMenu( const QPoint& pos );
|
void onCustomContextMenu( const QPoint& pos );
|
||||||
protected:
|
protected:
|
||||||
@@ -77,9 +78,11 @@ private:
|
|||||||
QModelIndex m_contextMenuIndex;
|
QModelIndex m_contextMenuIndex;
|
||||||
|
|
||||||
QMenu m_playlistMenu;
|
QMenu m_playlistMenu;
|
||||||
|
QMenu m_roPlaylistMenu;
|
||||||
QAction* m_loadPlaylistAction;
|
QAction* m_loadPlaylistAction;
|
||||||
QAction* m_renamePlaylistAction;
|
QAction* m_renamePlaylistAction;
|
||||||
QAction* m_deletePlaylistAction;
|
QAction* m_deletePlaylistAction;
|
||||||
|
QAction* m_copyPlaylistAction;
|
||||||
|
|
||||||
bool m_dragging;
|
bool m_dragging;
|
||||||
QRect m_dropRect;
|
QRect m_dropRect;
|
||||||
|
Reference in New Issue
Block a user