1
0
mirror of https://github.com/tomahawk-player/tomahawk.git synced 2025-07-31 11:20:22 +02:00

Merge branch 'mhd'

This commit is contained in:
Leo Franchi
2012-04-27 19:05:05 -04:00
32 changed files with 627 additions and 246 deletions

View File

@@ -27,6 +27,8 @@
#include "utils/TomahawkUtils.h" #include "utils/TomahawkUtils.h"
#include "utils/Logger.h" #include "utils/Logger.h"
#include "utils/AnimatedSpinner.h"
#include "utils/Closure.h"
#define CHILD_ACCOUNT_HEIGHT 24 #define CHILD_ACCOUNT_HEIGHT 24
@@ -134,9 +136,9 @@ AccountDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option,
QFont authorFont = opt.font; QFont authorFont = opt.font;
authorFont.setItalic( true ); authorFont.setItalic( true );
authorFont.setPointSize( authorFont.pointSize() - 1 ); authorFont.setPointSize( authorFont.pointSize() - 1 );
#ifdef Q_OS_MAC #ifdef Q_OS_MAC
authorFont.setPointSize( authorFont.pointSize() - 1 ); authorFont.setPointSize( authorFont.pointSize() - 1 );
#endif #endif
const QFontMetrics authorMetrics( authorFont ); const QFontMetrics authorMetrics( authorFont );
QFont descFont = authorFont; QFont descFont = authorFont;
@@ -158,7 +160,22 @@ AccountDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option,
QRect checkRect = QRect( leftEdge, checkboxYPos, WRENCH_SIZE, WRENCH_SIZE ); QRect checkRect = QRect( leftEdge, checkboxYPos, WRENCH_SIZE, WRENCH_SIZE );
QStyleOptionViewItemV4 opt2 = opt; QStyleOptionViewItemV4 opt2 = opt;
opt2.rect = checkRect; opt2.rect = checkRect;
drawCheckBox( opt2, painter, opt.widget );
if ( !m_loadingSpinners.contains( index ) )
{
drawCheckBox( opt2, painter, opt.widget );
}
else
{
Q_ASSERT( m_loadingSpinners[ index ] );
if ( m_loadingSpinners[ index ] )
{
const QPixmap pm = m_loadingSpinners[index]->pixmap();
painter->drawPixmap( checkRect, pm );
}
}
leftEdge += WRENCH_SIZE + PADDING / 2; leftEdge += WRENCH_SIZE + PADDING / 2;
// Pixmap // Pixmap
@@ -183,6 +200,7 @@ AccountDelegate::paint ( QPainter* painter, const QStyleOptionViewItem& option,
topt.pos = confRect.topLeft(); topt.pos = confRect.topLeft();
drawConfigWrench( painter, opt, topt ); drawConfigWrench( painter, opt, topt );
m_cachedConfigRects[ index ] = confRect; m_cachedConfigRects[ index ] = confRect;
rightEdge = confRect.left(); rightEdge = confRect.left();
@@ -658,4 +676,40 @@ AccountDelegate::checkRectForIndex( const QStyleOptionViewItem& option, const QM
} }
void
AccountDelegate::startInstalling( const QPersistentModelIndex& idx )
{
qDebug() << "START INSTALLING:" << idx.data( Qt::DisplayRole ).toString();
QStyleOptionViewItemV4 opt;
initStyleOption( &opt, idx );
AnimatedSpinner* anim = new AnimatedSpinner( checkRectForIndex( opt, idx ).size(), true );
_detail::Closure* closure = NewClosure( anim, SIGNAL( requestUpdate() ), this, SLOT( doUpdateIndex( const QPersistentModelIndex& ) ), idx );
closure->setAutoDelete( false );
m_loadingSpinners[ idx ] = anim;
update( idx );
}
void
AccountDelegate::doneInstalling ( const QPersistentModelIndex& idx )
{
qDebug() << "STOP INSTALLING:" << idx.data( Qt::DisplayRole ).toString();
Q_ASSERT( m_loadingSpinners.contains( idx ) );
if ( !m_loadingSpinners.contains( idx ) )
return;
delete m_loadingSpinners.take( idx );
update( idx );
}
void
AccountDelegate::doUpdateIndex( const QPersistentModelIndex& idx )
{
emit update( idx );
}

View File

@@ -22,6 +22,8 @@
#include <QStyledItemDelegate> #include <QStyledItemDelegate>
#include "accounts/AccountModel.h" #include "accounts/AccountModel.h"
class AnimatedSpinner;
namespace Tomahawk namespace Tomahawk
{ {
namespace Accounts namespace Accounts
@@ -38,6 +40,12 @@ public:
virtual void paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const; virtual void paint ( QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index ) const;
virtual QSize sizeHint ( const QStyleOptionViewItem& option, const QModelIndex& index ) const; virtual QSize sizeHint ( const QStyleOptionViewItem& option, const QModelIndex& index ) const;
public slots:
void startInstalling( const QPersistentModelIndex& idx );
void doneInstalling ( const QPersistentModelIndex& idx );
void doUpdateIndex( const QPersistentModelIndex& idx );
protected: protected:
virtual bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index ); virtual bool editorEvent( QEvent* event, QAbstractItemModel* model, const QStyleOptionViewItem& option, const QModelIndex& index );
@@ -64,6 +72,7 @@ private:
mutable QHash< QPersistentModelIndex, QRect > m_cachedStarRects; mutable QHash< QPersistentModelIndex, QRect > m_cachedStarRects;
mutable QHash< QPersistentModelIndex, QRect > m_cachedConfigRects; mutable QHash< QPersistentModelIndex, QRect > m_cachedConfigRects;
mutable QHash< QPersistentModelIndex, QSize > m_sizeHints; mutable QHash< QPersistentModelIndex, QSize > m_sizeHints;
mutable QHash< QPersistentModelIndex, AnimatedSpinner* > m_loadingSpinners;
mutable int m_accountRowHeight; mutable int m_accountRowHeight;
}; };

View File

@@ -44,7 +44,7 @@
#include "AccountDelegate.h" #include "AccountDelegate.h"
#include "database/Database.h" #include "database/Database.h"
#include "network/Servent.h" #include "network/Servent.h"
#include "playlist/dynamic/widgets/LoadingSpinner.h" #include "utils/AnimatedSpinner.h"
#include "accounts/AccountModel.h" #include "accounts/AccountModel.h"
#include "accounts/Account.h" #include "accounts/Account.h"
#include "accounts/AccountManager.h" #include "accounts/AccountManager.h"
@@ -114,6 +114,8 @@ SettingsDialog::SettingsDialog( QWidget *parent )
m_accountProxy = new AccountModelFilterProxy( m_accountModel ); m_accountProxy = new AccountModelFilterProxy( m_accountModel );
m_accountProxy->setSourceModel( m_accountModel ); m_accountProxy->setSourceModel( m_accountModel );
connect( m_accountProxy, SIGNAL( startInstalling( QPersistentModelIndex ) ), accountDelegate, SLOT( startInstalling(QPersistentModelIndex) ) );
connect( m_accountProxy, SIGNAL( doneInstalling( QPersistentModelIndex ) ), accountDelegate, SLOT( doneInstalling(QPersistentModelIndex) ) );
connect( m_accountProxy, SIGNAL( scrollTo( QModelIndex ) ), this, SLOT( scrollTo( QModelIndex ) ) ); connect( m_accountProxy, SIGNAL( scrollTo( QModelIndex ) ), this, SLOT( scrollTo( QModelIndex ) ) );
ui->accountsView->setModel( m_accountProxy ); ui->accountsView->setModel( m_accountProxy );
@@ -130,7 +132,7 @@ SettingsDialog::SettingsDialog( QWidget *parent )
if ( !Servent::instance()->isReady() ) if ( !Servent::instance()->isReady() )
{ {
m_sipSpinner = new LoadingSpinner( ui->accountsView ); m_sipSpinner = new AnimatedSpinner( ui->accountsView );
m_sipSpinner->fadeIn(); m_sipSpinner->fadeIn();
connect( Servent::instance(), SIGNAL( ready() ), this, SLOT( serventReady() ) ); connect( Servent::instance(), SIGNAL( ready() ), this, SLOT( serventReady() ) );

View File

@@ -26,7 +26,7 @@
#include "config.h" #include "config.h"
class LoadingSpinner; class AnimatedSpinner;
class QListWidgetItem; class QListWidgetItem;
class Ui_StackedSettingsDialog; class Ui_StackedSettingsDialog;
class SipPlugin; class SipPlugin;
@@ -112,7 +112,7 @@ private:
bool m_rejected; bool m_rejected;
Tomahawk::Accounts::AccountModel* m_accountModel; Tomahawk::Accounts::AccountModel* m_accountModel;
Tomahawk::Accounts::AccountModelFilterProxy* m_accountProxy; Tomahawk::Accounts::AccountModelFilterProxy* m_accountProxy;
LoadingSpinner* m_sipSpinner; AnimatedSpinner* m_sipSpinner;
}; };
#endif // SETTINGSDIALOG_H #endif // SETTINGSDIALOG_H

View File

@@ -19,7 +19,7 @@
#include "SpotifyAccountConfig.h" #include "SpotifyAccountConfig.h"
#include "SpotifyAccount.h" #include "SpotifyAccount.h"
#include <playlist/dynamic/widgets/LoadingSpinner.h> #include "utils/AnimatedSpinner.h"
#include "ui_SpotifyAccountConfig.h" #include "ui_SpotifyAccountConfig.h"
#include <QListWidget> #include <QListWidget>
@@ -44,7 +44,7 @@ SpotifyAccountConfig::SpotifyAccountConfig( SpotifyAccount *account )
connect( m_ui->passwordEdit, SIGNAL( textChanged( QString ) ), this, SLOT( resetLoginButton() ) ); connect( m_ui->passwordEdit, SIGNAL( textChanged( QString ) ), this, SLOT( resetLoginButton() ) );
loadFromConfig(); loadFromConfig();
m_playlistsLoading = new LoadingSpinner( m_ui->playlistList ); m_playlistsLoading = new AnimatedSpinner( m_ui->playlistList );
} }

View File

@@ -23,7 +23,7 @@
#include <QVariantMap> #include <QVariantMap>
#include <QTimer> #include <QTimer>
class LoadingSpinner; class AnimatedSpinner;
class QShowEvent; class QShowEvent;
namespace Ui namespace Ui
@@ -74,7 +74,7 @@ private slots:
private: private:
Ui::SpotifyConfig* m_ui; Ui::SpotifyConfig* m_ui;
SpotifyAccount* m_account; SpotifyAccount* m_account;
LoadingSpinner* m_playlistsLoading; AnimatedSpinner* m_playlistsLoading;
bool m_loggedInManually; bool m_loggedInManually;
}; };

View File

@@ -96,7 +96,6 @@ set( libGuiSources
playlist/dynamic/widgets/MiscControlWidgets.cpp playlist/dynamic/widgets/MiscControlWidgets.cpp
playlist/dynamic/widgets/CollapsibleControls.cpp playlist/dynamic/widgets/CollapsibleControls.cpp
playlist/dynamic/widgets/DynamicSetupWidget.cpp playlist/dynamic/widgets/DynamicSetupWidget.cpp
playlist/dynamic/widgets/LoadingSpinner.cpp
playlist/topbar/TopBar.cpp playlist/topbar/TopBar.cpp
playlist/topbar/ClearButton.cpp playlist/topbar/ClearButton.cpp
@@ -123,6 +122,7 @@ set( libGuiSources
utils/Closure.cpp utils/Closure.cpp
utils/PixmapDelegateFader.cpp utils/PixmapDelegateFader.cpp
utils/SmartPointerList.h utils/SmartPointerList.h
utils/AnimatedSpinner.cpp
widgets/AnimatedCounterLabel.cpp widgets/AnimatedCounterLabel.cpp
widgets/CheckDirTree.cpp widgets/CheckDirTree.cpp

View File

@@ -144,6 +144,51 @@ GlobalActionManager::shortenLink( const QUrl& url, const QVariant& callbackObj )
} }
void
GlobalActionManager::getShortLink( const playlist_ptr& pl )
{
QVariantMap m;
m[ "title" ] = pl->title();
m[ "creator" ] = pl->author().isNull() ? "" : pl->author()->friendlyName();
QVariantList tracks;
foreach( const plentry_ptr& pl, pl->entries() )
{
if ( pl->query().isNull() )
continue;
QVariantMap track;
track[ "title" ] = pl->query()->track();
track[ "creator" ] = pl->query()->artist();
track[ "album" ] = pl->query()->album();
tracks << track;
}
m[ "track" ] = tracks;
QVariantMap jspf;
jspf["playlist"] = m;
QJson::Serializer s;
QByteArray msg = s.serialize( jspf );
// No built-in Qt facilities for doing a FORM POST. So we build the payload ourselves...
const QByteArray boundary = "----------------------------2434992cccab";
QByteArray data(QByteArray("--" + boundary + "\r\n"));
data += "Content-Disposition: form-data; name=\"data\"; filename=\"playlist.jspf\"\r\n";
data += "Content-Type: application/octet-stream\r\n\r\n";
data += msg;
data += "\r\n\r\n";
data += "--" + boundary + "--\r\n\r\n";
const QUrl url( QString( "%1/p/").arg( hostname() ) );
QNetworkRequest req( url );
req.setHeader( QNetworkRequest::ContentTypeHeader, QString( "multipart/form-data; boundary=%1" ).arg( QString::fromLatin1( boundary ) ) );
QNetworkReply *reply = TomahawkUtils::nam()->post( req, data );
connect( reply, SIGNAL( finished() ), SLOT( postShortenFinished() ) );
connect( reply, SIGNAL( error( QNetworkReply::NetworkError ) ), SLOT( shortenLinkRequestError( QNetworkReply::NetworkError ) ) );
}
QString QString
GlobalActionManager::copyPlaylistToClipboard( const dynplaylist_ptr& playlist ) GlobalActionManager::copyPlaylistToClipboard( const dynplaylist_ptr& playlist )
{ {
@@ -341,18 +386,29 @@ GlobalActionManager::handlePlaylistCommand( const QUrl& url )
if ( parts[ 0 ] == "import" ) if ( parts[ 0 ] == "import" )
{ {
if ( !url.hasQueryItem( "xspf" ) ) if ( !url.hasQueryItem( "xspf" ) && !url.hasQueryItem( "jspf") )
{ {
tDebug() << "No xspf to load..."; tDebug() << "No xspf or jspf to load...";
return false; return false;
} }
QUrl xspf = QUrl::fromUserInput( url.queryItemValue( "xspf" ) ); if ( url.hasQueryItem( "xspf") )
QString title = url.hasQueryItem( "title" ) ? url.queryItemValue( "title" ) : QString(); {
XSPFLoader* l= new XSPFLoader( true, this ); QUrl xspf = QUrl::fromUserInput( url.queryItemValue( "xspf" ) );
l->setOverrideTitle( title ); QString title = url.hasQueryItem( "title" ) ? url.queryItemValue( "title" ) : QString();
l->load( xspf ); XSPFLoader* l= new XSPFLoader( true, this );
connect( l, SIGNAL( ok( Tomahawk::playlist_ptr ) ), this, SLOT( playlistCreatedToShow( Tomahawk::playlist_ptr) ) ); l->setOverrideTitle( title );
l->load( xspf );
connect( l, SIGNAL( ok( Tomahawk::playlist_ptr ) ), this, SLOT( playlistCreatedToShow( Tomahawk::playlist_ptr) ) );
}
else if ( url.hasQueryItem( "jspf" ) )
{
QUrl jspf = QUrl::fromUserInput( url.queryItemValue( "jspf" ) );
QString title = url.hasQueryItem( "title" ) ? url.queryItemValue( "title" ) : QString();
JSPFLoader* l= new JSPFLoader( true, this );
l->setOverrideTitle( title );
l->load( jspf );
connect( l, SIGNAL( ok( Tomahawk::playlist_ptr ) ), this, SLOT( playlistCreatedToShow( Tomahawk::playlist_ptr) ) );
}
} }
else if ( parts [ 0 ] == "new" ) else if ( parts [ 0 ] == "new" )
{ {
@@ -1054,6 +1110,25 @@ GlobalActionManager::shortenLinkRequestFinished()
} }
void
GlobalActionManager::postShortenFinished()
{
QNetworkReply* reply = qobject_cast<QNetworkReply*>( sender() );
Q_ASSERT( reply );
const QByteArray raw = reply->readAll();
qDebug() << "GOT REPLYL" << raw;
const QUrl url = QUrl::fromUserInput( raw );
qDebug() << "GOT POSTED SHORT URL:" << url.toString();
QClipboard* cb = QApplication::clipboard();
QByteArray data = url.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 );
reply->deleteLater();
}
void void
GlobalActionManager::shortenLinkRequestError( QNetworkReply::NetworkError error ) GlobalActionManager::shortenLinkRequestError( QNetworkReply::NetworkError error )
{ {

View File

@@ -57,6 +57,7 @@ public:
public slots: public slots:
void shortenLink( const QUrl& url, const QVariant &callbackObj = QVariant() ); void shortenLink( const QUrl& url, const QVariant &callbackObj = QVariant() );
void getShortLink( const Tomahawk::playlist_ptr& playlist );
bool parseTomahawkLink( const QString& link ); bool parseTomahawkLink( const QString& link );
void waitingForResolved( bool ); void waitingForResolved( bool );
@@ -71,6 +72,7 @@ signals:
private slots: private slots:
void shortenLinkRequestFinished(); void shortenLinkRequestFinished();
void postShortenFinished();
void shortenLinkRequestError( QNetworkReply::NetworkError ); void shortenLinkRequestError( QNetworkReply::NetworkError );
void bookmarkPlaylistCreated( const Tomahawk::playlist_ptr& pl ); void bookmarkPlaylistCreated( const Tomahawk::playlist_ptr& pl );

View File

@@ -408,6 +408,42 @@ TomahawkSettings::doUpgrade( int oldVersion, int newVersion )
setValue( "allaccounts", allAccounts ); setValue( "allaccounts", allAccounts );
endGroup(); endGroup();
} }
else if ( oldVersion == 8 )
{
// Some users got duplicate accounts for some reason, so make them unique if we can
QSet< QString > uniqueFriendlyNames;
beginGroup("accounts");
const QStringList accounts = childGroups();
QStringList allAccounts = value( "allaccounts" ).toStringList();
// qDebug() << "Got accounts to migrate:" << accounts;
foreach ( const QString& account, accounts )
{
if ( !allAccounts.contains( account ) ) // orphan
{
qDebug() << "Found account not in allaccounts list!" << account << "is a dup!";
remove( account );
continue;
}
const QString friendlyName = value( QString( "%1/accountfriendlyname" ).arg( account ) ).toString();
if ( !uniqueFriendlyNames.contains( friendlyName ) )
{
uniqueFriendlyNames.insert( friendlyName );
continue;
}
else
{
// Duplicate..?
qDebug() << "Found duplicate account friendly name:" << account << friendlyName << "is a dup!";
remove( account );
allAccounts.removeAll( account );
}
}
qDebug() << "Ended up with all accounts list:" << allAccounts << "and all accounts:" << childGroups();
setValue( "allaccounts", allAccounts );
endGroup();
}
} }

View File

@@ -28,7 +28,7 @@
#include "DllMacro.h" #include "DllMacro.h"
#define TOMAHAWK_SETTINGS_VERSION 8 #define TOMAHAWK_SETTINGS_VERSION 9
/** /**
* Convenience wrapper around QSettings for tomahawk-specific config * Convenience wrapper around QSettings for tomahawk-specific config

View File

@@ -266,7 +266,7 @@ void
AccountManager::loadFromConfig() AccountManager::loadFromConfig()
{ {
QStringList accountIds = TomahawkSettings::instance()->accounts(); QStringList accountIds = TomahawkSettings::instance()->accounts();
qDebug() << "LOADING ALL ACCOUNTS" << accountIds;
foreach( const QString& accountId, accountIds ) foreach( const QString& accountId, accountIds )
{ {
QString pluginFactory = factoryFromId( accountId ); QString pluginFactory = factoryFromId( accountId );

View File

@@ -29,7 +29,7 @@
using namespace Tomahawk; using namespace Tomahawk;
using namespace Accounts; using namespace Accounts;
#define ACCOUNTMODEL_DEBUG 0 #define ACCOUNTMODEL_DEBUG 1
AccountModel::AccountModel( QObject* parent ) AccountModel::AccountModel( QObject* parent )
: QAbstractListModel( parent ) : QAbstractListModel( parent )
@@ -451,6 +451,7 @@ AccountModel::setData( const QModelIndex& index, const QVariant& value, int role
qDebug() << "Kicked off fetch+install, now waiting"; qDebug() << "Kicked off fetch+install, now waiting";
m_waitingForAtticaInstall.insert( resolver.id() ); m_waitingForAtticaInstall.insert( resolver.id() );
emit startInstalling( index );
AtticaManager::instance()->installResolver( resolver ); AtticaManager::instance()->installResolver( resolver );
return true; return true;
} }
@@ -571,6 +572,10 @@ AccountModel::accountAdded( Account* account )
AccountManager::instance()->enableAccount( account ); AccountManager::instance()->enableAccount( account );
m_waitingForAtticaInstall.remove( attica->atticaId() ); m_waitingForAtticaInstall.remove( attica->atticaId() );
// find index to emit doneInstalling for
const QModelIndex idx = index( i, 0, QModelIndex() );
emit doneInstalling( idx );
} }
if ( thisIsTheOne ) if ( thisIsTheOne )

View File

@@ -94,6 +94,8 @@ signals:
void createAccount( Tomahawk::Accounts::AccountFactory* factory ); void createAccount( Tomahawk::Accounts::AccountFactory* factory );
void scrollTo( const QModelIndex& idx ); void scrollTo( const QModelIndex& idx );
void startInstalling( const QPersistentModelIndex& idx );
void doneInstalling( const QPersistentModelIndex& idx );
private slots: private slots:
void loadData(); void loadData();

View File

@@ -36,6 +36,8 @@ void
AccountModelFilterProxy::setSourceModel( QAbstractItemModel* sourceModel ) AccountModelFilterProxy::setSourceModel( QAbstractItemModel* sourceModel )
{ {
connect( sourceModel, SIGNAL( scrollTo( QModelIndex ) ), this, SLOT( onScrollTo( QModelIndex ) ) ); connect( sourceModel, SIGNAL( scrollTo( QModelIndex ) ), this, SLOT( onScrollTo( QModelIndex ) ) );
connect( sourceModel, SIGNAL( startInstalling( QPersistentModelIndex ) ), this, SLOT( onStartInstalling( QPersistentModelIndex ) ) );
connect( sourceModel, SIGNAL( doneInstalling( QPersistentModelIndex ) ), this, SLOT( onDoneInstalling( QPersistentModelIndex ) ) );
QSortFilterProxyModel::setSourceModel( sourceModel ); QSortFilterProxyModel::setSourceModel( sourceModel );
} }
@@ -70,3 +72,17 @@ AccountModelFilterProxy::onScrollTo( const QModelIndex& idx )
{ {
emit scrollTo( mapFromSource( idx ) ); emit scrollTo( mapFromSource( idx ) );
} }
void
AccountModelFilterProxy::onDoneInstalling( const QPersistentModelIndex& idx )
{
emit doneInstalling( mapFromSource( idx ) );
}
void
AccountModelFilterProxy::onStartInstalling( const QPersistentModelIndex& idx )
{
emit startInstalling( mapFromSource( idx ) );
}

View File

@@ -40,12 +40,18 @@ public:
signals: signals:
void scrollTo( const QModelIndex& idx ); void scrollTo( const QModelIndex& idx );
void startInstalling( const QPersistentModelIndex& idx );
void doneInstalling( const QPersistentModelIndex& idx );
protected: protected:
virtual bool filterAcceptsRow ( int sourceRow, const QModelIndex& sourceParent ) const; virtual bool filterAcceptsRow ( int sourceRow, const QModelIndex& sourceParent ) const;
private slots: private slots:
void onScrollTo( const QModelIndex& idx ); void onScrollTo( const QModelIndex& idx );
void onStartInstalling( const QPersistentModelIndex& idx );
void onDoneInstalling( const QPersistentModelIndex& idx );
private: private:
Tomahawk::Accounts::AccountType m_filterType; Tomahawk::Accounts::AccountType m_filterType;
}; };

View File

@@ -26,7 +26,7 @@
#include <attica/content.h> #include <attica/content.h>
#define ACCOUNTMODELNODE_DEBUG 0 #define ACCOUNTMODELNODE_DEBUG 1
namespace Tomahawk { namespace Tomahawk {

View File

@@ -34,7 +34,7 @@
#include "AlbumModel.h" #include "AlbumModel.h"
#include "ViewManager.h" #include "ViewManager.h"
#include "utils/Logger.h" #include "utils/Logger.h"
#include "dynamic/widgets/LoadingSpinner.h" #include "utils/AnimatedSpinner.h"
#define SCROLL_TIMEOUT 280 #define SCROLL_TIMEOUT 280
@@ -46,7 +46,7 @@ AlbumView::AlbumView( QWidget* parent )
, m_model( 0 ) , m_model( 0 )
, m_proxyModel( 0 ) , m_proxyModel( 0 )
, m_delegate( 0 ) , m_delegate( 0 )
, m_loadingSpinner( new LoadingSpinner( this ) ) , m_loadingSpinner( new AnimatedSpinner( this ) )
, m_overlay( new OverlayWidget( this ) ) , m_overlay( new OverlayWidget( this ) )
, m_inited( false ) , m_inited( false )
{ {

View File

@@ -30,7 +30,7 @@
#include "DllMacro.h" #include "DllMacro.h"
class AlbumModel; class AlbumModel;
class LoadingSpinner; class AnimatedSpinner;
class AlbumItemDelegate; class AlbumItemDelegate;
class DLLEXPORT AlbumView : public QListView, public Tomahawk::ViewPage class DLLEXPORT AlbumView : public QListView, public Tomahawk::ViewPage
@@ -87,7 +87,7 @@ private:
AlbumModel* m_model; AlbumModel* m_model;
AlbumProxyModel* m_proxyModel; AlbumProxyModel* m_proxyModel;
AlbumItemDelegate* m_delegate; AlbumItemDelegate* m_delegate;
LoadingSpinner* m_loadingSpinner; AnimatedSpinner* m_loadingSpinner;
OverlayWidget* m_overlay; OverlayWidget* m_overlay;
bool m_inited; bool m_inited;

View File

@@ -26,7 +26,7 @@
#include "audio/AudioEngine.h" #include "audio/AudioEngine.h"
#include "context/ContextWidget.h" #include "context/ContextWidget.h"
#include "dynamic/widgets/LoadingSpinner.h" #include "utils/AnimatedSpinner.h"
#include "widgets/OverlayWidget.h" #include "widgets/OverlayWidget.h"
#include "ContextMenu.h" #include "ContextMenu.h"
@@ -49,7 +49,7 @@ ArtistView::ArtistView( QWidget* parent )
, m_model( 0 ) , m_model( 0 )
, m_proxyModel( 0 ) , m_proxyModel( 0 )
// , m_delegate( 0 ) // , m_delegate( 0 )
, m_loadingSpinner( new LoadingSpinner( this ) ) , m_loadingSpinner( new AnimatedSpinner( this ) )
, m_updateContextView( true ) , m_updateContextView( true )
, m_contextMenu( new ContextMenu( this ) ) , m_contextMenu( new ContextMenu( this ) )
, m_showModes( true ) , m_showModes( true )

View File

@@ -37,7 +37,7 @@ namespace Tomahawk
}; };
class TreeHeader; class TreeHeader;
class LoadingSpinner; class AnimatedSpinner;
class OverlayWidget; class OverlayWidget;
class TreeModel; class TreeModel;
@@ -108,7 +108,7 @@ private:
TreeModel* m_model; TreeModel* m_model;
TreeProxyModel* m_proxyModel; TreeProxyModel* m_proxyModel;
// PlaylistItemDelegate* m_delegate; // PlaylistItemDelegate* m_delegate;
LoadingSpinner* m_loadingSpinner; AnimatedSpinner* m_loadingSpinner;
bool m_updateContextView; bool m_updateContextView;

View File

@@ -30,13 +30,13 @@
#include "audio/AudioEngine.h" #include "audio/AudioEngine.h"
#include "context/ContextWidget.h" #include "context/ContextWidget.h"
#include "widgets/OverlayWidget.h" #include "widgets/OverlayWidget.h"
#include "dynamic/widgets/LoadingSpinner.h"
#include "utils/TomahawkUtils.h" #include "utils/TomahawkUtils.h"
#include "utils/Logger.h" #include "utils/Logger.h"
#include "utils/Closure.h" #include "utils/Closure.h"
#include "DropJob.h" #include "DropJob.h"
#include "Artist.h" #include "Artist.h"
#include "Album.h" #include "Album.h"
#include "utils/AnimatedSpinner.h"
#define SCROLL_TIMEOUT 280 #define SCROLL_TIMEOUT 280
@@ -50,7 +50,7 @@ TrackView::TrackView( QWidget* parent )
, m_delegate( 0 ) , m_delegate( 0 )
, m_header( new TrackHeader( this ) ) , m_header( new TrackHeader( this ) )
, m_overlay( new OverlayWidget( this ) ) , m_overlay( new OverlayWidget( this ) )
, m_loadingSpinner( new LoadingSpinner( this ) ) , m_loadingSpinner( new AnimatedSpinner( this ) )
, m_resizing( false ) , m_resizing( false )
, m_dragging( false ) , m_dragging( false )
, m_updateContextView( true ) , m_updateContextView( true )

View File

@@ -30,7 +30,7 @@
#include "DllMacro.h" #include "DllMacro.h"
class QAction; class QAction;
class LoadingSpinner; class AnimatedSpinner;
class TrackHeader; class TrackHeader;
class TrackModel; class TrackModel;
class TrackProxyModel; class TrackProxyModel;
@@ -57,7 +57,7 @@ public:
TrackHeader* header() const { return m_header; } TrackHeader* header() const { return m_header; }
OverlayWidget* overlay() const { return m_overlay; } OverlayWidget* overlay() const { return m_overlay; }
Tomahawk::ContextMenu* contextMenu() const { return m_contextMenu; } Tomahawk::ContextMenu* contextMenu() const { return m_contextMenu; }
LoadingSpinner* loadingSpinner() const { return m_loadingSpinner; } AnimatedSpinner* loadingSpinner() const { return m_loadingSpinner; }
QModelIndex hoveredIndex() const { return m_hoveredIndex; } QModelIndex hoveredIndex() const { return m_hoveredIndex; }
QModelIndex contextMenuIndex() const { return m_contextMenuIndex; } QModelIndex contextMenuIndex() const { return m_contextMenuIndex; }
@@ -119,7 +119,7 @@ private:
PlaylistItemDelegate* m_delegate; PlaylistItemDelegate* m_delegate;
TrackHeader* m_header; TrackHeader* m_header;
OverlayWidget* m_overlay; OverlayWidget* m_overlay;
LoadingSpinner* m_loadingSpinner; AnimatedSpinner* m_loadingSpinner;
bool m_resizing; bool m_resizing;
bool m_dragging; bool m_dragging;

View File

@@ -41,7 +41,7 @@
#include "ViewManager.h" #include "ViewManager.h"
#include "dynamic/DynamicView.h" #include "dynamic/DynamicView.h"
#include "DynamicSetupWidget.h" #include "DynamicSetupWidget.h"
#include "LoadingSpinner.h" #include "utils/AnimatedSpinner.h"
#include "utils/Logger.h" #include "utils/Logger.h"
using namespace Tomahawk; using namespace Tomahawk;
@@ -74,7 +74,7 @@ DynamicWidget::DynamicWidget( const Tomahawk::dynplaylist_ptr& playlist, QWidget
connect( m_model, SIGNAL( collapseFromTo( int, int ) ), m_view, SLOT( collapseEntries( int, int ) ) ); connect( m_model, SIGNAL( collapseFromTo( int, int ) ), m_view, SLOT( collapseEntries( int, int ) ) );
connect( m_model, SIGNAL( trackGenerationFailure( QString ) ), this, SLOT( stationFailed( QString ) ) ); connect( m_model, SIGNAL( trackGenerationFailure( QString ) ), this, SLOT( stationFailed( QString ) ) );
m_loading = new LoadingSpinner( m_view ); m_loading = new AnimatedSpinner( m_view );
connect( m_model, SIGNAL( tracksAdded() ), m_loading, SLOT( fadeOut() ) ); connect( m_model, SIGNAL( tracksAdded() ), m_loading, SLOT( fadeOut() ) );
m_setup = new DynamicSetupWidget( playlist, this ); m_setup = new DynamicSetupWidget( playlist, this );

View File

@@ -26,7 +26,7 @@
#include "ViewPage.h" #include "ViewPage.h"
#include "playlist/dynamic/DynamicPlaylistRevision.h" #include "playlist/dynamic/DynamicPlaylistRevision.h"
class LoadingSpinner; class AnimatedSpinner;
class QShowEvent; class QShowEvent;
class QHideEvent; class QHideEvent;
class QSpinBox; class QSpinBox;
@@ -119,7 +119,7 @@ private:
bool m_activePlaylist; bool m_activePlaylist;
// loading animation // loading animation
LoadingSpinner* m_loading; AnimatedSpinner* m_loading;
// setup controls // setup controls
DynamicSetupWidget* m_setup; DynamicSetupWidget* m_setup;

View File

@@ -1,128 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010 Leo Franchi <lfranchi@kde.org>
* Copyright 2010-2011, Jeff Mitchell <jeff@tomahawk-player.org>
*
* Tomahawk 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 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#include "LoadingSpinner.h"
#include <QTimeLine>
#include <QPaintEvent>
#include <QPainter>
#include <QMovie>
#include <QLabel>
#include "utils/TomahawkUtils.h"
#include "utils/Logger.h"
#define ANIM_LENGTH 300
LoadingSpinner::LoadingSpinner( QWidget* parent )
: QWidget( parent )
, m_showHide( new QTimeLine )
{
m_showHide->setDuration( 300 );
m_showHide->setStartFrame( 0 );
m_showHide->setEndFrame( 100 );
m_showHide->setUpdateInterval( 20 );
connect( m_showHide, SIGNAL( frameChanged( int ) ), this, SLOT( update() ) );
connect( m_showHide, SIGNAL( finished() ), this, SLOT( hideFinished() ) );
m_anim = new QMovie( RESPATH "/images/loading-animation.gif" );
m_anim->jumpToNextFrame();
connect( m_anim, SIGNAL( frameChanged( int ) ), this, SLOT( update() ) );
resize( m_anim->currentPixmap().size() );
setSizePolicy( QSizePolicy::Fixed, QSizePolicy::Fixed );
hide();
}
LoadingSpinner::~LoadingSpinner()
{
}
void
LoadingSpinner::fadeIn()
{
if ( isVisible() )
return;
show();
m_anim->start();
m_showHide->setDirection( QTimeLine::Forward );
if ( m_showHide->state() != QTimeLine::Running )
m_showHide->start();
}
void
LoadingSpinner::fadeOut()
{
m_showHide->setDirection( QTimeLine::Backward );
if ( m_showHide->state() != QTimeLine::Running )
m_showHide->start();
}
void
LoadingSpinner::hideFinished()
{
if ( m_showHide->direction() == QTimeLine::Backward )
{
hide();
m_anim->stop();
}
}
QSize
LoadingSpinner::sizeHint() const
{
return m_anim->currentPixmap().size();
}
void
LoadingSpinner::paintEvent( QPaintEvent* ev )
{
Q_UNUSED( ev );
if ( !parentWidget() )
return;
QPoint center( ( parentWidget()->width() / 2 ) - ( width() / 2 ), ( parentWidget()->height() / 2 ) - ( height() / 2 ) );
if ( center != pos() )
{
move( center );
return;
}
QPainter p( this );
if ( m_showHide->state() == QTimeLine::Running )
{ // showing or hiding
p.setOpacity( (qreal)m_showHide->currentValue() );
}
p.drawPixmap( rect(), m_anim->currentPixmap() );
}

View File

@@ -1,56 +0,0 @@
/* === This file is part of Tomahawk Player - <http://tomahawk-player.org> ===
*
* Copyright 2010 Leo Franchi <lfranchi@kde.org>
*
* Tomahawk 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 3 of the License, or
* (at your option) any later version.
*
* Tomahawk is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Tomahawk. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef LOADING_SPINNER_H
#define LOADING_SPINNER_H
#include <QWidget>
#include "DllMacro.h"
class QMovie;
class QTimeLine;
/**
* A small widget that displays an animated loading spinner
*/
class DLLEXPORT LoadingSpinner : public QWidget {
Q_OBJECT
public:
LoadingSpinner( QWidget* parent );
virtual ~LoadingSpinner();
virtual QSize sizeHint() const;
virtual void paintEvent( QPaintEvent* );
public slots:
void fadeIn();
void fadeOut();
private slots:
void hideFinished();
private:
void reposition();
QTimeLine* m_showHide;
QMovie* m_anim;
};
#endif
class QPaintEvent;

View File

@@ -0,0 +1,267 @@
/*
Copyright (C) 2012 Leo Franchi <leo.franchi@kdab.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 Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "AnimatedSpinner.h"
#include <QtCore/QPoint>
#include <QTimeLine>
#include <QDebug>
#include <QDateTime>
#include <QtGui/QApplication>
#include <QtGui/QHideEvent>
#include <QtGui/QPainter>
#include <QtGui/QPaintEvent>
#include <QtGui/QShowEvent>
AnimatedSpinner::AnimatedSpinner( QWidget *parent )
: QWidget( parent )
, m_showHide( new QTimeLine )
, m_animation( new QTimeLine )
, m_currentIndex( -1 )
{
init();
m_radius = 10;
m_armLength = sizeHint().width()/2 - m_radius;
m_armWidth = 5;
m_border = 3;
m_armRect = QRect( m_radius, 0, m_armLength, m_armWidth );
}
AnimatedSpinner::AnimatedSpinner( const QSize size, bool autoStart )
: QWidget()
, m_showHide( new QTimeLine )
, m_animation( new QTimeLine )
, m_currentIndex( -1 )
{
m_pixmap = QPixmap( size );
m_pixmap.fill( Qt::transparent );
init();
if ( size.width() < 30 )
{
m_radius = 4;
m_armLength = size.width()/2 - m_radius;
m_armWidth = 2;
m_border = 2;
m_armRect = QRect( m_radius, 0, m_armLength, m_armWidth );
}
else
{
m_radius = 10;
m_armLength = size.width()/2 - m_radius;
m_armWidth = 5;
m_border = 3;
m_armRect = QRect( m_radius, 0, m_armLength, m_armWidth );
}
if ( autoStart )
fadeIn();
}
void
AnimatedSpinner::init()
{
m_showHide->setDuration( 300 );
m_showHide->setStartFrame( 0 );
m_showHide->setEndFrame( 100 );
m_showHide->setUpdateInterval( 20 );
if( parentWidget() )
connect( m_showHide, SIGNAL( frameChanged( int ) ), this, SLOT( update() ) );
else
connect( m_showHide, SIGNAL( frameChanged( int ) ), this, SLOT( updatePixmap() ) );
connect( m_showHide, SIGNAL( finished() ), this, SLOT( hideFinished() ) );
m_animation->setDuration( 1000 );
m_animation->setStartFrame( 0 );
m_animation->setEndFrame( segmentCount() );
m_animation->setUpdateInterval( 20 );
m_animation->setLoopCount( 0 );
m_animation->setDirection( QTimeLine::Forward );
m_animation->setCurveShape( QTimeLine::LinearCurve );
connect( m_animation, SIGNAL( frameChanged( int ) ), this, SLOT( frameChanged( int ) ) );
m_colors.resize( segmentCount() );
hide();
}
void
AnimatedSpinner::paintEvent(QPaintEvent *event)
{
Q_UNUSED(event);
if ( parentWidget() )
{
QPoint center( ( parentWidget()->width() / 2 ) - ( width() / 2 ), ( parentWidget()->height() / 2 ) - ( height() / 2 ) );
if ( center != pos() )
{
move( center );
return;
}
}
QPainter p(this);
drawFrame( &p, rect() );
}
void
AnimatedSpinner::updatePixmap()
{
Q_ASSERT( !m_pixmap.isNull() );
QPainter p( &m_pixmap );
m_pixmap.fill( Qt::transparent );
drawFrame( &p, m_pixmap.rect() );
p.end();
emit requestUpdate();
}
void
AnimatedSpinner::drawFrame( QPainter* p, const QRect& rect )
{
if ( m_showHide->state() == QTimeLine::Running )
{
// showing or hiding
p->setOpacity( (qreal)m_showHide->currentValue() );
}
p->setRenderHint(QPainter::Antialiasing, true);
p->translate( rect.center() ); // center
const qreal stepRadius = (360 + 2*m_armWidth) / segmentCount();
p->rotate( stepRadius );
for (int segment = 0; segment < segmentCount(); ++segment) {
p->rotate(stepRadius);
QPainterPath arm;
arm.addRoundedRect( m_armRect.adjusted( 0, -m_armWidth/2., 0, -m_armWidth/2 ), m_border, m_border );
p->fillPath( arm, colorForSegment( segment ) );
}
}
void
AnimatedSpinner::fadeIn()
{
if ( parentWidget() && isVisible() )
return;
m_animation->start();
m_showHide->setDirection( QTimeLine::Forward );
if ( m_showHide->state() != QTimeLine::Running )
m_showHide->start();
if ( parentWidget() )
show();
else
updatePixmap();
}
void
AnimatedSpinner::fadeOut()
{
m_showHide->setDirection( QTimeLine::Backward );
if ( m_showHide->state() != QTimeLine::Running )
m_showHide->start();
}
void
AnimatedSpinner::hideFinished()
{
if ( m_showHide->direction() == QTimeLine::Backward )
{
m_animation->stop();
if ( parentWidget() )
hide();
else
updatePixmap();
}
}
QSize
AnimatedSpinner::sizeHint() const
{
return QSize(48, 48);
}
void
AnimatedSpinner::frameChanged( int frame )
{
if ( m_currentIndex == frame || frame > segmentCount()-1 )
return;
m_currentIndex = frame;
Q_ASSERT( frame >= 0 && frame < m_colors.size() );
// calculate colors, save a factor from 1 to 0 behind the current item
m_colors.fill( -1 );
int cur = m_currentIndex, running = 0, tailLength = 5;
while ( m_colors[cur] == -1 )
{
if ( running > tailLength )
m_colors[cur] = 0.; // beyond the tail, draw at base color
else
m_colors[cur] = 1. - ((qreal)running/tailLength); // scale from 1 to 0 along tail
++running;
cur = --cur < 0 ? m_colors.size() - 1 : cur;
}
if ( parentWidget() )
update();
else
updatePixmap();
}
QColor
AnimatedSpinner::colorForSegment( int seg ) const
{
// Highlight color is 227, 227, 227
// Base color is 101, 101, 101
Q_ASSERT( seg < m_colors.size() );
const int comp = 101 + m_colors[seg] * ( 126 );
return QColor(comp, comp, comp, 255);
}
int
AnimatedSpinner::segmentCount() const
{
return 11;
}

View File

@@ -0,0 +1,87 @@
/*
Copyright (C) 2012 Leo Franchi <leo.franchi@kdab.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 Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef ANIMATED_SPINNER_H
#define ANIMATED_SPINNER_H
#include "DllMacro.h"
#include <QtGui/QWidget>
#include <QtCore/QSize>
#include <QtGui/QColor>
#include <QtGui/QPixmap>
#include <QPainter>
class QTimeLine;
class QHideEvent;
class QShowEvent;
class QPaintEvent;
class QTimerEvent;
/**
If you don't pass a parent QWidget, this spinner will
draw into the pixmap instead. If you do, the pixmap will
be invalid.
*/
class DLLEXPORT AnimatedSpinner : public QWidget
{
Q_OBJECT
public:
explicit AnimatedSpinner( QWidget *parent = 0 ); // widget mode
AnimatedSpinner( const QSize size, bool autoStart ); // pixmap mode
QSize sizeHint() const;
QPixmap pixmap() const { return m_pixmap; }
public slots:
void fadeIn();
void fadeOut();
signals:
void requestUpdate();
protected:
void paintEvent(QPaintEvent *event);
private slots:
void updatePixmap();
void hideFinished();
void frameChanged( int );
private:
void init();
void drawFrame( QPainter* p, const QRect& rect );
int segmentCount() const;
QColor colorForSegment( int segment ) const;
QTimeLine* m_showHide;
QTimeLine* m_animation;
// to tweak
int m_radius, m_armLength, m_armWidth, m_border;
QRect m_armRect;
int m_currentIndex;
QVector<qreal> m_colors;
QPixmap m_pixmap;
};
#endif

View File

@@ -25,10 +25,10 @@
#include "SourceList.h" #include "SourceList.h"
#include "ViewManager.h" #include "ViewManager.h"
#include "dynamic/widgets/LoadingSpinner.h"
#include "playlist/AlbumModel.h" #include "playlist/AlbumModel.h"
#include "playlist/PlaylistModel.h" #include "playlist/PlaylistModel.h"
#include "widgets/OverlayWidget.h" #include "widgets/OverlayWidget.h"
#include "utils/AnimatedSpinner.h"
#include "utils/TomahawkUtils.h" #include "utils/TomahawkUtils.h"
#include "utils/Logger.h" #include "utils/Logger.h"

View File

@@ -127,7 +127,7 @@ main( int argc, char *argv[] )
#ifndef ENABLE_HEADLESSs #ifndef ENABLE_HEADLESSs
#ifdef WITH_BREAKPAD #ifdef WITH_BREAKPAD
new BreakPad( QDir::tempPath(), TomahawkSettings::instance()->crashReporterEnabled() ); //new BreakPad( QDir::tempPath(), TomahawkSettings::instance()->crashReporterEnabled() );
#endif #endif
#endif #endif

View File

@@ -226,8 +226,8 @@ SourceTreeView::setupMenus()
} }
if ( type == SourcesModel::StaticPlaylist ) if ( type == SourcesModel::StaticPlaylist )
copyPlaylistAction->setText( tr( "&Export Playlist" ) ); copyPlaylistAction->setText( tr( "&Export Playlist" ) );
connect( loadPlaylistAction, SIGNAL( triggered() ), SLOT( loadPlaylist() ) ); connect( loadPlaylistAction, SIGNAL( triggered() ), SLOT( loadPlaylist() ) );
connect( renamePlaylistAction, SIGNAL( triggered() ), SLOT( renamePlaylist() ) ); connect( renamePlaylistAction, SIGNAL( triggered() ), SLOT( renamePlaylist() ) );
@@ -357,18 +357,22 @@ SourceTreeView::copyPlaylistLink()
} }
else if ( type == SourcesModel::StaticPlaylist ) else if ( type == SourcesModel::StaticPlaylist )
{ {
PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex );
playlist_ptr playlist = item->playlist();
QString suggestedFilename = TomahawkSettings::instance()->playlistDefaultPath() + "/" + playlist->title(); // Disable toma.hk playlist mode until ready
QString filename = QFileDialog::getSaveFileName( TomahawkUtils::tomahawkWindow(), tr( "Save XSPF" ), // GlobalActionManager::instance()->getShortLink( playlist );
suggestedFilename, tr( "Playlists (*.xspf)" ) );
if ( !filename.isEmpty() ) PlaylistItem* item = itemFromIndex< PlaylistItem >( m_contextMenuIndex );
{ playlist_ptr playlist = item->playlist();
QFileInfo playlistAbsoluteFilePath = filename;
TomahawkSettings::instance()->setPlaylistDefaultPath( playlistAbsoluteFilePath.absolutePath() ); QString suggestedFilename = TomahawkSettings::instance()->playlistDefaultPath() + "/" + playlist->title();
GlobalActionManager::instance()->savePlaylistToFile( playlist, filename ); QString filename = QFileDialog::getSaveFileName( TomahawkUtils::tomahawkWindow(), tr( "Save XSPF" ),
} suggestedFilename, tr( "Playlists (*.xspf)" ) );
if ( !filename.isEmpty() )
{
QFileInfo playlistAbsoluteFilePath = filename;
TomahawkSettings::instance()->setPlaylistDefaultPath( playlistAbsoluteFilePath.absolutePath() );
GlobalActionManager::instance()->savePlaylistToFile( playlist, filename );
}
} }
} }