diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -283,7 +283,13 @@ context/AppletModel.cpp context/ContextDock.cpp context/ContextView.cpp - context/LyricsManager.cpp +) + +##################################################################### +# LYRICS +##################################################################### +set( liblyrics_SRCS + lyrics/LyricsManager.cpp ) ##################################################################### @@ -442,7 +448,6 @@ scripting/scriptengine/AmarokEqualizerScript.cpp scripting/scriptengine/AmarokInfoScript.cpp scripting/scriptengine/AmarokKNotifyScript.cpp - scripting/scriptengine/AmarokLyricsScript.cpp scripting/scriptengine/AmarokNetworkScript.cpp scripting/scriptengine/AmarokOSDScript.cpp scripting/scriptengine/AmarokPlaylistManagerScript.cpp @@ -588,6 +593,7 @@ ${libcontextview_SRCS} ${libcollectionbrowser_SRCS} ${libconfigdialog_SRCS} + ${liblyrics_SRCS} ${libplaylist_SRCS} ${aggregatecollection_SRCS} ${libpodcasts_SRCS} diff --git a/src/OpmlParser.h b/src/OpmlParser.h --- a/src/OpmlParser.h +++ b/src/OpmlParser.h @@ -63,7 +63,7 @@ * Note the work is performed in a separate thread * @return Returns true on success and false on failure */ - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; bool read( const QUrl &url ); bool read( QIODevice *device ); @@ -84,8 +84,8 @@ QList results() const { return m_outlines; } protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; Q_SIGNALS: diff --git a/src/OpmlWriter.h b/src/OpmlWriter.h --- a/src/OpmlWriter.h +++ b/src/OpmlWriter.h @@ -45,7 +45,7 @@ * Note the work is performed in a separate thread * @return Returns true on success and false on failure */ - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; QIODevice *device() { return m_xmlWriter->device(); } @@ -72,8 +72,8 @@ QXmlStreamWriter *m_xmlWriter; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; diff --git a/src/amarokurls/BookmarkGroup.cpp b/src/amarokurls/BookmarkGroup.cpp --- a/src/amarokurls/BookmarkGroup.cpp +++ b/src/amarokurls/BookmarkGroup.cpp @@ -211,14 +211,12 @@ void BookmarkGroup::deleteChild( BookmarkViewItemPtr item ) { - if ( typeid( * item ) == typeid( BookmarkGroup ) ) + if ( auto group = BookmarkGroupPtr::dynamicCast( item ) ) { - BookmarkGroupPtr group = BookmarkGroupPtr::staticCast( item ); m_childGroups.removeAll( group ); } - else if ( typeid( * item ) == typeid( AmarokUrl ) ) + else if ( auto bookmark = AmarokUrlPtr::dynamicCast( item ) ) { - AmarokUrlPtr bookmark = AmarokUrlPtr::staticCast( item ); m_childBookmarks.removeAll( bookmark ); } } diff --git a/src/amarokurls/BookmarkModel.cpp b/src/amarokurls/BookmarkModel.cpp --- a/src/amarokurls/BookmarkModel.cpp +++ b/src/amarokurls/BookmarkModel.cpp @@ -108,13 +108,10 @@ { if( index.column() == Name ) { - if ( typeid( * item ) == typeid( BookmarkGroup ) ) + if ( BookmarkGroupPtr::dynamicCast( item ) ) return QVariant( QIcon::fromTheme( "folder-bookmark" ) ); - else if ( typeid( * item ) == typeid( AmarokUrl ) ) - { - AmarokUrl * url = static_cast( item.data() ); + else if ( auto url = AmarokUrlPtr::dynamicCast( item ) ) return The::amarokUrlHandler()->iconForCommand( url->command() ); - } } } @@ -236,7 +233,7 @@ return Qt::ItemIsEnabled | Qt::ItemIsDropEnabled; BookmarkViewItemPtr item = BookmarkViewItemPtr::staticCast( m_viewItems.value( index.internalId() ) ); - if ( typeid( * item ) == typeid( BookmarkGroup ) ) + if ( BookmarkGroupPtr::dynamicCast( item ) ) { if ( index.column() != Command ) return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDropEnabled | Qt::ItemIsDragEnabled; @@ -338,16 +335,10 @@ BookmarkViewItemPtr item = m_viewItems.value( index.internalId() ); - if ( typeid( * item ) == typeid( BookmarkGroup ) ) { - BookmarkGroupPtr playlistGroup = BookmarkGroupPtr::staticCast( item ); - groups << playlistGroup; - } - else - { - AmarokUrlPtr bookmark = AmarokUrlPtr::dynamicCast( item ); - if( bookmark ) - bookmarks << bookmark; - } + if ( auto group = BookmarkGroupPtr::dynamicCast( item ) ) + groups << group; + else if( auto bookmark = AmarokUrlPtr::dynamicCast( item ) ) + bookmarks << bookmark; } debug() << "adding " << groups.count() << " groups and " << bookmarks.count() << " bookmarks"; diff --git a/src/amarokurls/BookmarkTreeView.cpp b/src/amarokurls/BookmarkTreeView.cpp --- a/src/amarokurls/BookmarkTreeView.cpp +++ b/src/amarokurls/BookmarkTreeView.cpp @@ -73,10 +73,8 @@ { BookmarkViewItemPtr item = BookmarkModel::instance()->data( index, 0xf00d ).value(); - if ( typeid( *item ) == typeid( AmarokUrl ) ) { - AmarokUrl * bookmark = static_cast< AmarokUrl* >( item.data() ); + if ( auto bookmark = AmarokUrlPtr::dynamicCast( item ) ) bookmark->run(); - } } } @@ -144,11 +142,8 @@ DEBUG_BLOCK foreach( BookmarkViewItemPtr item, selectedItems() ) { - if( typeid( * item ) == typeid( AmarokUrl ) ) - { - AmarokUrlPtr bookmark = AmarokUrlPtr::staticCast( item ); + if( auto bookmark = AmarokUrlPtr::dynamicCast( item ) ) bookmark->run(); - } } } @@ -282,10 +277,10 @@ { BookmarkViewItemPtr item = BookmarkModel::instance()->data( sourceIndex, 0xf00d ).value(); - if ( typeid( * item ) == typeid( AmarokUrl ) ) { + if ( auto bookmark = AmarokUrlPtr::dynamicCast( item ) ) + { debug() << "a url was selected..."; - AmarokUrl bookmark = *static_cast< AmarokUrl* >( item.data() ); - emit( bookmarkSelected( bookmark ) ); + emit( bookmarkSelected( *bookmark ) ); } } } diff --git a/src/browsers/CollectionSortFilterProxyModel.h b/src/browsers/CollectionSortFilterProxyModel.h --- a/src/browsers/CollectionSortFilterProxyModel.h +++ b/src/browsers/CollectionSortFilterProxyModel.h @@ -36,19 +36,18 @@ class CollectionSortFilterProxyModel : public QSortFilterProxyModel { public: - explicit CollectionSortFilterProxyModel( QObject * parent = 0 ); + explicit CollectionSortFilterProxyModel( QObject *parent = nullptr ); virtual ~CollectionSortFilterProxyModel(); - bool hasChildren(const QModelIndex &parent) const; + virtual bool hasChildren(const QModelIndex &parent) const override; protected: - virtual bool lessThan( const QModelIndex &left, const QModelIndex &right ) const; + virtual bool lessThan( const QModelIndex &left, const QModelIndex &right ) const override; + virtual bool filterAcceptsRow( int source_row, const QModelIndex & source_parent ) const override; private: QCollator *m_col; - /** Tries to compute a year for the album using the track years. */ - int albumYear( Meta::AlbumPtr album ) const; CollectionTreeItem* treeItem( const QModelIndex &index ) const; bool lessThanTrack( const QModelIndex &left, const QModelIndex &right ) const; diff --git a/src/browsers/CollectionSortFilterProxyModel.cpp b/src/browsers/CollectionSortFilterProxyModel.cpp --- a/src/browsers/CollectionSortFilterProxyModel.cpp +++ b/src/browsers/CollectionSortFilterProxyModel.cpp @@ -57,6 +57,24 @@ return sourceModel()->hasChildren(sourceParent); } +bool +CollectionSortFilterProxyModel::filterAcceptsRow( int source_row, const QModelIndex& source_parent ) const +{ + bool stringAccepted = QSortFilterProxyModel::filterAcceptsRow( source_row, source_parent ); + + if( AmarokConfig::showYears()) + { + QModelIndex index = sourceModel()->index( source_row, 0, source_parent ); + if( treeItem( index )->isAlbumItem() ) + { + bool yearLoaded = index.data( PrettyTreeRoles::YearRole ) >= 0; + return yearLoaded && stringAccepted; + } + } + + return stringAccepted; +} + bool CollectionSortFilterProxyModel::lessThan( const QModelIndex &left, const QModelIndex &right ) const { @@ -138,8 +156,8 @@ // compare by year if( AmarokConfig::showYears() ) { - int leftYear = albumYear( leftAlbum ); - int rightYear = albumYear( rightAlbum ); + int leftYear = left.data( PrettyTreeRoles::YearRole ).toInt(); + int rightYear = right.data( PrettyTreeRoles::YearRole ).toInt(); if( leftYear < rightYear ) return false; // left album is newer @@ -162,8 +180,8 @@ bool CollectionSortFilterProxyModel::lessThanItem( const QModelIndex &left, const QModelIndex &right ) const { - Meta::DataPtr leftData = Meta::DataPtr::dynamicCast( treeItem(left)->data() ); - Meta::DataPtr rightData = Meta::DataPtr::dynamicCast( treeItem(right)->data() ); + Meta::DataPtr leftData = treeItem(left)->data(); + Meta::DataPtr rightData = treeItem(right)->data(); if( !leftData || !rightData ) { @@ -190,20 +208,3 @@ { return static_cast( index.internalPointer() ); } - -int -CollectionSortFilterProxyModel::albumYear( Meta::AlbumPtr album ) const -{ - if( album->name().isEmpty() ) // an unnamed album has no year - return 0; - - Meta::TrackList tracks = album->tracks(); - if( !tracks.isEmpty() ) - { - Meta::YearPtr year = tracks.first()->year(); - if( year && (year->year() != 0) ) - return year->year(); - } - return 0; -} - diff --git a/src/browsers/CollectionTreeItemModelBase.h b/src/browsers/CollectionTreeItemModelBase.h --- a/src/browsers/CollectionTreeItemModelBase.h +++ b/src/browsers/CollectionTreeItemModelBase.h @@ -37,7 +37,9 @@ class Collection; } class CollectionTreeItem; +class QMutex; class QTimeLine; +class TrackLoaderJob; typedef QPair CollectionRoot; @@ -48,6 +50,8 @@ { Q_OBJECT + friend class TrackLoaderJob; + public: CollectionTreeItemModelBase(); virtual ~CollectionTreeItemModelBase(); @@ -142,6 +146,15 @@ Collections::QueryMaker::QueryType mapCategoryToQueryType( int levelType ) const; + /** + * This function is thread-safe + */ + void tracksLoaded( Meta::AlbumPtr album, const QModelIndex &index, const Meta::TrackList &tracks ); + + QMutex *m_loadingAlbumsMutex; + QHash m_years; + mutable QSet m_loadingAlbums; + protected: /** Adds the query maker to the running queries and connects the slots */ void addQueryMaker( CollectionTreeItem* item, diff --git a/src/browsers/CollectionTreeItemModelBase.cpp b/src/browsers/CollectionTreeItemModelBase.cpp --- a/src/browsers/CollectionTreeItemModelBase.cpp +++ b/src/browsers/CollectionTreeItemModelBase.cpp @@ -35,9 +35,12 @@ #include "widgets/PrettyTreeRoles.h" #include +#include +#include #include #include +#include #include #include #include @@ -47,6 +50,31 @@ using namespace Meta; +class TrackLoaderJob : public ThreadWeaver::Job +{ +public: + TrackLoaderJob( const QModelIndex &index, const Meta::AlbumPtr &album, CollectionTreeItemModelBase *model ) + : m_index( index ) + , m_album( album ) + , m_model( model ) + { + } + +protected: + void run( ThreadWeaver::JobPointer self, ThreadWeaver::Thread *thread ) override + { + Q_UNUSED( self ) + Q_UNUSED( thread ) + + m_model->tracksLoaded( m_album, m_index, m_album->tracks() ); + } + +private: + QModelIndex m_index; + Meta::AlbumPtr m_album; + CollectionTreeItemModelBase *m_model; +}; + inline uint qHash( const Meta::DataPtr &data ) { return qHash( data.data() ); @@ -61,6 +89,7 @@ CollectionTreeItemModelBase::CollectionTreeItemModelBase( ) : QAbstractItemModel() + , m_loadingAlbumsMutex( new QMutex ) , m_rootItem( 0 ) , m_animFrame( 0 ) , m_loading1( QPixmap( QStandardPaths::locate( QStandardPaths::GenericDataLocation, "amarok/images/loading1.png" ) ) ) @@ -84,6 +113,8 @@ if( m_rootItem ) m_rootItem->deleteLater(); + + delete m_loadingAlbumsMutex; } Qt::ItemFlags CollectionTreeItemModelBase::flags(const QModelIndex & index) const @@ -247,14 +278,26 @@ { QString name = album->prettyName(); // add years for named albums (if enabled) - if( AmarokConfig::showYears() && !album->name().isEmpty() ) + if( AmarokConfig::showYears() ) { - Meta::TrackList tracks = album->tracks(); - if( !tracks.isEmpty() ) + if( m_years.contains( album.data() ) ) { - Meta::YearPtr year = tracks.first()->year(); - if( year && (year->year() != 0) ) - name.prepend( QString("%1 - ").arg( year->name() ) ); + int year = m_years.value( album.data() ); + + if( year > 0 ) + name.prepend( QString("%1 - ").arg( year ) ); + } + else if( !album->name().isEmpty() ) + { + QMutexLocker locker( m_loadingAlbumsMutex ); + if( !m_loadingAlbums.contains( album ) ) + { + m_loadingAlbums.insert( album ); + + auto nonConstThis = const_cast( this ); + auto job = QSharedPointer::create( itemIndex( item ), album, nonConstThis ); + ThreadWeaver::Queue::instance()->enqueue( job ); + } } } return name; @@ -276,6 +319,26 @@ case PrettyTreeRoles::HasCoverRole: return AmarokConfig::showAlbumArt(); + + case PrettyTreeRoles::YearRole: + { + if( m_years.contains( album.data() ) ) + return m_years.value( album.data() ); + + else if( !album->name().isEmpty() ) + { + QMutexLocker locker( m_loadingAlbumsMutex ); + if( !m_loadingAlbums.contains( album ) ) + { + m_loadingAlbums.insert( album ); + + auto nonConstThis = const_cast( this ); + auto job = QSharedPointer::create( itemIndex( item ), album, nonConstThis ); + ThreadWeaver::Queue::instance()->enqueue( job ); + } + } + return -1; + } } } else if( item->isDataItem() ) @@ -503,7 +566,8 @@ return createIndex( item->row(), 0, item ); } -void CollectionTreeItemModelBase::listForLevel(int level, Collections::QueryMaker * qm, CollectionTreeItem * parent) +void +CollectionTreeItemModelBase::listForLevel(int level, Collections::QueryMaker * qm, CollectionTreeItem * parent) { if( qm && parent ) { @@ -615,6 +679,42 @@ return type; } +void +CollectionTreeItemModelBase::tracksLoaded( Meta::AlbumPtr album, const QModelIndex &index, const Meta::TrackList& tracks ) +{ + DEBUG_BLOCK + + if( !album ) + return; + + QMutexLocker locker( m_loadingAlbumsMutex ); + m_loadingAlbums.remove( album ); + + if( !index.isValid() ) + return; + + int year = 0; + + if( !tracks.isEmpty() ) + { + Meta::YearPtr yearPtr = tracks.first()->year(); + if( yearPtr ) + year = yearPtr->year(); + + debug() << "Valid album year found:" << year; + } + + // Set the year in the thread associated with this + auto lambda = [=] () { + if( !m_years.contains( album.data() ) || m_years.value( album.data() ) != year ) + { + m_years[ album.data() ] = year; + emit dataChanged( index, index ); + } + }; + QTimer::singleShot( 0, this, lambda ); +} + void CollectionTreeItemModelBase::addQueryMaker( CollectionTreeItem* item, Collections::QueryMaker *qm ) const @@ -668,57 +768,57 @@ // TODO /** Small helper function to convert a list of e.g. tracks to a list of DataPtr */ -template +template static Meta::DataList -convertToDataList( const ListType& list ) +convertToDataList( const QList& list ) { Meta::DataList data; - foreach( PointerType p, list ) + for( const auto &p : list ) data << Meta::DataPtr::staticCast( p ); return data; } void CollectionTreeItemModelBase::newTracksReady( Meta::TrackList res ) { - newDataReady( convertToDataList( res ) ); + newDataReady( convertToDataList( res ) ); } void CollectionTreeItemModelBase::newArtistsReady( Meta::ArtistList res ) { - newDataReady( convertToDataList( res ) ); + newDataReady( convertToDataList( res ) ); } void CollectionTreeItemModelBase::newAlbumsReady( Meta::AlbumList res ) { - newDataReady( convertToDataList( res ) ); + newDataReady( convertToDataList( res ) ); } void CollectionTreeItemModelBase::newGenresReady( Meta::GenreList res ) { - newDataReady( convertToDataList( res ) ); + newDataReady( convertToDataList( res ) ); } void CollectionTreeItemModelBase::newComposersReady( Meta::ComposerList res ) { - newDataReady( convertToDataList( res ) ); + newDataReady( convertToDataList( res ) ); } void CollectionTreeItemModelBase::newYearsReady( Meta::YearList res ) { - newDataReady( convertToDataList( res ) ); + newDataReady( convertToDataList( res ) ); } void CollectionTreeItemModelBase::newLabelsReady( Meta::LabelList res ) { - newDataReady( convertToDataList( res ) ); + newDataReady( convertToDataList( res ) ); } void diff --git a/src/configdialog/ConfigDialog.h b/src/configdialog/ConfigDialog.h --- a/src/configdialog/ConfigDialog.h +++ b/src/configdialog/ConfigDialog.h @@ -52,13 +52,13 @@ void updateButtons(); protected Q_SLOTS: - void updateSettings() Q_DECL_OVERRIDE; - void updateWidgets() Q_DECL_OVERRIDE; - void updateWidgetsDefault() Q_DECL_OVERRIDE; + void updateSettings() override; + void updateWidgets() override; + void updateWidgetsDefault() override; protected: - bool hasChanged() Q_DECL_OVERRIDE; - bool isDefault() Q_DECL_OVERRIDE; + bool hasChanged() override; + bool isDefault() override; private: QList m_pageList; diff --git a/src/configdialog/dialogs/CollectionConfig.h b/src/configdialog/dialogs/CollectionConfig.h --- a/src/configdialog/dialogs/CollectionConfig.h +++ b/src/configdialog/dialogs/CollectionConfig.h @@ -30,9 +30,9 @@ explicit CollectionConfig( Amarok2ConfigDialog* parent ); virtual ~CollectionConfig(); - bool hasChanged() Q_DECL_OVERRIDE; - bool isDefault() Q_DECL_OVERRIDE; - void updateSettings() Q_DECL_OVERRIDE; + bool hasChanged() override; + bool isDefault() override; + void updateSettings() override; private: CollectionSetup* m_collectionSetup; diff --git a/src/configdialog/dialogs/DatabaseConfig.h b/src/configdialog/dialogs/DatabaseConfig.h --- a/src/configdialog/dialogs/DatabaseConfig.h +++ b/src/configdialog/dialogs/DatabaseConfig.h @@ -32,9 +32,9 @@ DatabaseConfig( Amarok2ConfigDialog* parent, KConfigSkeleton *config ); virtual ~DatabaseConfig(); - virtual bool hasChanged() Q_DECL_OVERRIDE; - virtual bool isDefault() Q_DECL_OVERRIDE; - virtual void updateSettings() Q_DECL_OVERRIDE; + virtual bool hasChanged() override; + virtual bool isDefault() override; + virtual void updateSettings() override; public Q_SLOTS: void toggleExternalConfigAvailable( int checkBoxState ); diff --git a/src/configdialog/dialogs/GeneralConfig.h b/src/configdialog/dialogs/GeneralConfig.h --- a/src/configdialog/dialogs/GeneralConfig.h +++ b/src/configdialog/dialogs/GeneralConfig.h @@ -28,9 +28,9 @@ explicit GeneralConfig( Amarok2ConfigDialog* parent ); virtual ~GeneralConfig(); - bool hasChanged() Q_DECL_OVERRIDE; - bool isDefault() Q_DECL_OVERRIDE; - void updateSettings() Q_DECL_OVERRIDE; + bool hasChanged() override; + bool isDefault() override; + void updateSettings() override; }; #endif diff --git a/src/configdialog/dialogs/MetadataConfig.h b/src/configdialog/dialogs/MetadataConfig.h --- a/src/configdialog/dialogs/MetadataConfig.h +++ b/src/configdialog/dialogs/MetadataConfig.h @@ -32,9 +32,9 @@ explicit MetadataConfig( Amarok2ConfigDialog *parent ); virtual ~MetadataConfig(); - bool isDefault() Q_DECL_OVERRIDE; - bool hasChanged() Q_DECL_OVERRIDE; - void updateSettings() Q_DECL_OVERRIDE; + bool isDefault() override; + bool hasChanged() override; + void updateSettings() override; Q_SIGNALS: void changed(); diff --git a/src/configdialog/dialogs/NotificationsConfig.h b/src/configdialog/dialogs/NotificationsConfig.h --- a/src/configdialog/dialogs/NotificationsConfig.h +++ b/src/configdialog/dialogs/NotificationsConfig.h @@ -32,9 +32,9 @@ explicit NotificationsConfig( Amarok2ConfigDialog* parent ); virtual ~NotificationsConfig(); - bool hasChanged() Q_DECL_OVERRIDE; - bool isDefault() Q_DECL_OVERRIDE; - void updateSettings() Q_DECL_OVERRIDE; + bool hasChanged() override; + bool isDefault() override; + void updateSettings() override; Q_SIGNALS: void changed(); @@ -50,8 +50,8 @@ OSDWidget::Alignment m_oldAlignment; uint m_oldYOffset; - void hideEvent( QHideEvent* ); - void showEvent( QShowEvent* ); + void hideEvent( QHideEvent* ) override; + void showEvent( QShowEvent* ) override; }; #endif diff --git a/src/configdialog/dialogs/PlaybackConfig.h b/src/configdialog/dialogs/PlaybackConfig.h --- a/src/configdialog/dialogs/PlaybackConfig.h +++ b/src/configdialog/dialogs/PlaybackConfig.h @@ -29,9 +29,9 @@ explicit PlaybackConfig( Amarok2ConfigDialog* parent ); virtual ~PlaybackConfig(); - bool hasChanged() Q_DECL_OVERRIDE; - bool isDefault() Q_DECL_OVERRIDE; - void updateSettings() Q_DECL_OVERRIDE; + bool hasChanged() override; + bool isDefault() override; + void updateSettings() override; private Q_SLOTS: void configurePhonon(); diff --git a/src/configdialog/dialogs/PluginsConfig.h b/src/configdialog/dialogs/PluginsConfig.h --- a/src/configdialog/dialogs/PluginsConfig.h +++ b/src/configdialog/dialogs/PluginsConfig.h @@ -32,9 +32,9 @@ explicit PluginsConfig( Amarok2ConfigDialog *parent ); virtual ~PluginsConfig(); - void updateSettings() Q_DECL_OVERRIDE; - bool hasChanged() Q_DECL_OVERRIDE; - bool isDefault() Q_DECL_OVERRIDE; + void updateSettings() override; + bool hasChanged() override; + bool isDefault() override; public Q_SLOTS: void slotConfigChanged( bool changed ); diff --git a/src/configdialog/dialogs/ScriptsConfig.h b/src/configdialog/dialogs/ScriptsConfig.h --- a/src/configdialog/dialogs/ScriptsConfig.h +++ b/src/configdialog/dialogs/ScriptsConfig.h @@ -39,9 +39,9 @@ explicit ScriptsConfig( Amarok2ConfigDialog *parent ); virtual ~ScriptsConfig(); - void updateSettings() Q_DECL_OVERRIDE; - bool hasChanged() Q_DECL_OVERRIDE; - bool isDefault() Q_DECL_OVERRIDE; + void updateSettings() override; + bool hasChanged() override; + bool isDefault() override; public Q_SLOTS: void slotConfigChanged( bool changed ); diff --git a/src/context/AmarokContextPackageStructure.h b/src/context/AmarokContextPackageStructure.h --- a/src/context/AmarokContextPackageStructure.h +++ b/src/context/AmarokContextPackageStructure.h @@ -27,7 +27,7 @@ Q_OBJECT public: - virtual void initPackage(KPackage::Package *package) Q_DECL_OVERRIDE; + virtual void initPackage(KPackage::Package *package) override; }; #endif // AMAROKCONTEXTPACKAGESTRUCTURE_H diff --git a/src/context/AppletModel.h b/src/context/AppletModel.h --- a/src/context/AppletModel.h +++ b/src/context/AppletModel.h @@ -49,10 +49,10 @@ explicit AppletModel(AppletLoader *loader, QObject *parent = Q_NULLPTR); virtual ~AppletModel(); - virtual int rowCount(const QModelIndex& parent) const Q_DECL_OVERRIDE; - virtual QVariant data(const QModelIndex& index, int role) const Q_DECL_OVERRIDE; - virtual bool setData(const QModelIndex& index, const QVariant& value, int role) Q_DECL_OVERRIDE; - virtual QHash< int, QByteArray > roleNames() const Q_DECL_OVERRIDE; + virtual int rowCount(const QModelIndex& parent) const override; + virtual QVariant data(const QModelIndex& index, int role) const override; + virtual bool setData(const QModelIndex& index, const QVariant& value, int role) override; + virtual QHash< int, QByteArray > roleNames() const override; AppletLoader* loader() const { return m_loader; } @@ -134,8 +134,8 @@ void enabledAppletsChanged(); protected: - bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const Q_DECL_OVERRIDE; - bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const Q_DECL_OVERRIDE; + bool lessThan(const QModelIndex &source_left, const QModelIndex &source_right) const override; + bool filterAcceptsRow(int source_row, const QModelIndex &source_parent) const override; private: AppletModel *m_appletModel; diff --git a/src/context/ContextView.cpp b/src/context/ContextView.cpp --- a/src/context/ContextView.cpp +++ b/src/context/ContextView.cpp @@ -176,5 +176,3 @@ } } // Context namespace - -#include diff --git a/src/context/LyricsManager.h b/src/context/LyricsManager.h deleted file mode 100644 --- a/src/context/LyricsManager.h +++ /dev/null @@ -1,129 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Leo Franchi * - * * - * 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 2 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 . * - ****************************************************************************************/ - -#ifndef LYRICS_MANAGER_H -#define LYRICS_MANAGER_H - -#include "amarok_export.h" - -#include -#include -#include - -class LyricsSubject; - -struct LyricsData -{ - QString text; - QString title; - QString artist; - QUrl site; - - void clear() - { - text.clear(); - title.clear(); - artist.clear(); - site.clear(); - } -}; - -class AMAROK_EXPORT LyricsObserver -{ - public: - LyricsObserver(); - explicit LyricsObserver( LyricsSubject* ); - virtual ~LyricsObserver(); - - /** - * A lyrics script has returned new lyrics. - */ - virtual void newLyrics( const LyricsData &lyrics ) { Q_UNUSED( lyrics ); } - /** - * A lyrics script has returned a list of suggested URLs for correct lyrics. - */ - virtual void newSuggestions( const QVariantList &suggestions ) { Q_UNUSED( suggestions ); } - /** - * A lyrics script has returned some generic message that they want to be displayed. - */ - virtual void lyricsMessage( const QString& key, const QString &val ) { Q_UNUSED( key ); Q_UNUSED( val ); } - - private: - LyricsSubject *m_subject; -}; - -class LyricsSubject -{ - public: - void attach( LyricsObserver *observer ); - void detach( LyricsObserver *observer ); - - protected: - LyricsSubject() {} - virtual ~LyricsSubject() {} - - void sendNewLyrics( const LyricsData &lyrics ); - void sendNewSuggestions( const QVariantList &suggestions ); - void sendLyricsMessage( const QString &key, const QString &val ); - - private: - QList m_observers; -}; - -class AMAROK_EXPORT LyricsManager : public LyricsSubject -{ - public: - static LyricsManager* self() - { - if( !s_self ) - s_self = new LyricsManager(); - - return s_self; - } - - void lyricsResult( const QString& lyrics, bool cached = false ); - void lyricsResultHtml( const QString& lyrics, bool cached = false ); - void lyricsError( const QString &error ); - void lyricsNotFound( const QString& notfound ); - - /** - * Sets the given lyrics for the track with the given URL. - * - * @param trackUrl The URL of the track. - * @param lyrics The new lyrics. - */ - void setLyricsForTrack( const QString &trackUrl, const QString &lyrics ) const; - - /** - * Tests if the given lyrics are empty. - * - * @param lyrics The lyrics which will be tested. - * - * @return true if the given lyrics are empty, otherwise false. - */ - bool isEmpty( const QString &lyrics ) const; - - private: - LyricsManager() : LyricsSubject() { s_self = this; } - - bool showCached(); - - static LyricsManager* s_self; -}; - -Q_DECLARE_METATYPE( LyricsData ); - -#endif diff --git a/src/context/LyricsManager.cpp b/src/context/LyricsManager.cpp deleted file mode 100644 --- a/src/context/LyricsManager.cpp +++ /dev/null @@ -1,271 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2007 Leo Franchi * - * Copyright (c) 2009 Seb Ruiz * - * * - * 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 2 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 . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "LyricsManager" - -#include "LyricsManager.h" - -#include "EngineController.h" -#include "core/meta/Meta.h" -#include "core/support/Debug.h" -#include "core-impl/collections/support/CollectionManager.h" - -#include -#include - -#include - -//////////////////////////////////////////////////////////////// -//// CLASS LyricsObserver -/////////////////////////////////////////////////////////////// - -LyricsObserver::LyricsObserver() - : m_subject( 0 ) -{ - qRegisterMetaType("LyricsData"); -} - -LyricsObserver::LyricsObserver( LyricsSubject *s ) - : m_subject( s ) -{ - m_subject->attach( this ); -} - -LyricsObserver::~LyricsObserver() -{ - if( m_subject ) - m_subject->detach( this ); -} - -//////////////////////////////////////////////////////////////// -//// CLASS LyricsSubject -/////////////////////////////////////////////////////////////// - -void LyricsSubject::sendNewLyrics( const LyricsData &lyrics ) -{ - DEBUG_BLOCK - foreach( LyricsObserver* obs, m_observers ) - { - obs->newLyrics( lyrics ); - } -} - -void LyricsSubject::sendNewSuggestions( const QVariantList &sug ) -{ - DEBUG_BLOCK - foreach( LyricsObserver* obs, m_observers ) - { - obs->newSuggestions( sug ); - } -} - -void LyricsSubject::sendLyricsMessage( const QString &key, const QString &val ) -{ - DEBUG_BLOCK - foreach( LyricsObserver* obs, m_observers ) - { - obs->lyricsMessage( key, val ); - } -} - -void LyricsSubject::attach( LyricsObserver *obs ) -{ - if( !obs || m_observers.indexOf( obs ) != -1 ) - return; - m_observers.append( obs ); -} - -void LyricsSubject::detach( LyricsObserver *obs ) -{ - int index = m_observers.indexOf( obs ); - if( index != -1 ) m_observers.removeAt( index ); -} - -//////////////////////////////////////////////////////////////// -//// CLASS LyricsManager -/////////////////////////////////////////////////////////////// - -LyricsManager* LyricsManager::s_self = 0; - -void -LyricsManager::lyricsResult( const QString& lyricsXML, bool cached ) //SLOT -{ - DEBUG_BLOCK - Q_UNUSED( cached ); - - QXmlStreamReader xml( lyricsXML ); - while( xml.readNextStartElement() ) - { - if( xml.name() == QLatin1String("lyric") ) - { - Meta::TrackPtr currentTrack = The::engineController()->currentTrack(); - if( !currentTrack ) - return; - - QString lyrics( xml.readElementText() ); - if( !isEmpty( lyrics ) ) - { - // overwrite cached lyrics (as either there were no lyircs available previously OR - // the user exlicitly agreed to overwrite the lyrics) - debug() << "setting cached lyrics..."; - currentTrack->setCachedLyrics( lyrics ); // TODO: setLyricsByPath? - } - else if( !isEmpty( currentTrack->cachedLyrics() ) ) - { - // we found nothing, so if we have cached lyrics, use it! - debug() << "using cached lyrics..."; - lyrics = currentTrack->cachedLyrics(); - } - else - { - lyricsError( i18n("Retrieved lyrics is empty") ); - return; - } - - QString artist = currentTrack->artist() ? currentTrack->artist()->name() : QString(); - LyricsData data = { lyrics, currentTrack->name(), artist, QUrl() }; - sendNewLyrics( data ); - return; - } - else if( xml.name() == QLatin1String("suggestions") ) - { - QVariantList suggestions; - while( xml.readNextStartElement() ) - { - if( xml.name() != QLatin1String("suggestion") ) - continue; - - const QXmlStreamAttributes &a = xml.attributes(); - - QString artist = a.value( QLatin1String("artist") ).toString(); - QString title = a.value( QLatin1String("title") ).toString(); - QString url = a.value( QLatin1String("url") ).toString(); - - if( !url.isEmpty() ) - suggestions << ( QStringList() << title << artist << url ); - xml.skipCurrentElement(); - } - - debug() << "got" << suggestions.size() << "suggestions"; - if( suggestions.isEmpty() ) - sendLyricsMessage( "notFound", "notfound" ); - else - sendNewSuggestions( suggestions ); - return; - } - xml.skipCurrentElement(); - } - - if( xml.hasError() ) - { - warning() << "errors occurred during reading lyrics xml result:" << xml.errorString(); - lyricsError( i18n("Lyrics data could not be parsed") ); - } -} - -void -LyricsManager::lyricsResultHtml( const QString& lyricsHTML, bool cached ) -{ - DEBUG_BLOCK - Q_UNUSED( cached ) - - // we don't need to deal with suggestions here, because - // we assume the script has called showLyrics if they could - // be suggestions. this is for HTML display only - - Meta::TrackPtr currentTrack = The::engineController()->currentTrack(); - if( currentTrack && !isEmpty( lyricsHTML ) ) - { - QString artist = currentTrack->artist() ? currentTrack->artist()->name() : QString(); - LyricsData data = { lyricsHTML, currentTrack->name(), artist, QUrl() }; - sendNewLyrics( data ); - - // overwrite cached lyrics (as either there were no lyircs available previously OR - // the user exlicitly agreed to overwrite the lyrics) - currentTrack->setCachedLyrics( lyricsHTML ); - } -} - -void -LyricsManager::lyricsError( const QString &error ) -{ - DEBUG_BLOCK - if( !showCached() ) - { - sendLyricsMessage( "error", error ); - } -} - - -void -LyricsManager::lyricsNotFound( const QString& notfound ) -{ - DEBUG_BLOCK - if( !showCached() ) - sendLyricsMessage( "notfound", notfound ); -} - - -bool LyricsManager::showCached() -{ - DEBUG_BLOCK - //if we have cached lyrics there is absolutely no point in not showing these.. - Meta::TrackPtr currentTrack = The::engineController()->currentTrack(); - if( currentTrack && !isEmpty( currentTrack->cachedLyrics() ) ) - { - // TODO: add some sort of feedback that we could not fetch new ones - // so we are showing a cached result - debug() << "showing cached lyrics!"; - - QString lyrics = currentTrack->cachedLyrics(); - QString artist = currentTrack->artist() ? currentTrack->artist()->name() : QString(); - LyricsData data = { lyrics, currentTrack->name(), artist, QUrl() }; - sendNewLyrics( data ); - return true; - } - return false; -} - -void LyricsManager::setLyricsForTrack( const QString &trackUrl, const QString &lyrics ) const -{ - DEBUG_BLOCK - - Meta::TrackPtr track = CollectionManager::instance()->trackForUrl( QUrl( trackUrl ) ); - - if( track ) - track->setCachedLyrics( lyrics ); - else - debug() << QString("could not find a track for the given URL (%1) - ignoring.").arg( trackUrl ); -} - -bool LyricsManager::isEmpty( const QString &lyrics ) const -{ - QTextEdit testItem; - - // Set the text of the TextItem. - if( Qt::mightBeRichText( lyrics ) ) - testItem.setHtml( lyrics ); - else - testItem.setPlainText( lyrics ); - - // Get the plaintext content. - // We use toPlainText() to strip all Html formatting, - // so we can test if there's any text given. - QString testText = testItem.toPlainText().trimmed(); - - return testText.isEmpty(); -} diff --git a/src/context/applets/albums/plugin/AlbumItem.h b/src/context/applets/albums/plugin/AlbumItem.h --- a/src/context/applets/albums/plugin/AlbumItem.h +++ b/src/context/applets/albums/plugin/AlbumItem.h @@ -61,11 +61,11 @@ // overloaded from Meta::Observer using Observer::metadataChanged; - virtual void metadataChanged( Meta::AlbumPtr album ) Q_DECL_OVERRIDE; + virtual void metadataChanged( Meta::AlbumPtr album ) override; - virtual int type() const Q_DECL_OVERRIDE; + virtual int type() const override; - virtual bool operator<( const QStandardItem &other ) const Q_DECL_OVERRIDE; + virtual bool operator<( const QStandardItem &other ) const override; private Q_SLOTS: /** Updates the item after metadataChanged was called. diff --git a/src/context/applets/albums/plugin/AlbumsModel.h b/src/context/applets/albums/plugin/AlbumsModel.h --- a/src/context/applets/albums/plugin/AlbumsModel.h +++ b/src/context/applets/albums/plugin/AlbumsModel.h @@ -62,7 +62,7 @@ Mode mode() const; void setMode( Mode mode ); - QHash roleNames() const Q_DECL_OVERRIDE; + virtual QHash roleNames() const override; signals: void modeChanged(); @@ -77,9 +77,9 @@ * added more recently than all of the tracks in the album * referenced by @param right. */ - bool lessThan( const QModelIndex &left, const QModelIndex &right ) const; + virtual bool lessThan( const QModelIndex &left, const QModelIndex &right ) const override; - bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const Q_DECL_OVERRIDE; + virtual bool filterAcceptsRow( int sourceRow, const QModelIndex &sourceParent ) const override; private: Mode m_mode; diff --git a/src/context/applets/albums/plugin/AlbumsPlugin.cpp b/src/context/applets/albums/plugin/AlbumsPlugin.cpp --- a/src/context/applets/albums/plugin/AlbumsPlugin.cpp +++ b/src/context/applets/albums/plugin/AlbumsPlugin.cpp @@ -32,7 +32,7 @@ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - void registerTypes(const char* uri) Q_DECL_OVERRIDE + void registerTypes(const char* uri) override { Q_ASSERT(uri == QLatin1String("org.kde.amarok.albums")); diff --git a/src/context/applets/albums/plugin/TrackItem.h b/src/context/applets/albums/plugin/TrackItem.h --- a/src/context/applets/albums/plugin/TrackItem.h +++ b/src/context/applets/albums/plugin/TrackItem.h @@ -54,11 +54,11 @@ // overloaded from Meta::Observer using Observer::metadataChanged; - virtual void metadataChanged( Meta::TrackPtr track ) Q_DECL_OVERRIDE; + virtual void metadataChanged( Meta::TrackPtr track ) override; - virtual int type() const Q_DECL_OVERRIDE; + virtual int type() const override; - virtual bool operator<( const QStandardItem &other ) const Q_DECL_OVERRIDE; + virtual bool operator<( const QStandardItem &other ) const override; private: Meta::TrackPtr m_track; diff --git a/src/context/applets/analyzer/plugin/AnalyzerBase.h b/src/context/applets/analyzer/plugin/AnalyzerBase.h --- a/src/context/applets/analyzer/plugin/AnalyzerBase.h +++ b/src/context/applets/analyzer/plugin/AnalyzerBase.h @@ -50,11 +50,11 @@ public: enum WindowFunction { - Rectangular = 0, - Hann = 1, - Nuttall = 2, - Lanczos = 3, - Sine = 4 + Rectangular, + Hann, + Nuttall, + Lanczos, + Sine }; Q_ENUM(WindowFunction) diff --git a/src/context/applets/analyzer/plugin/AnalyzerBase.cpp b/src/context/applets/analyzer/plugin/AnalyzerBase.cpp --- a/src/context/applets/analyzer/plugin/AnalyzerBase.cpp +++ b/src/context/applets/analyzer/plugin/AnalyzerBase.cpp @@ -49,7 +49,7 @@ { DEBUG_BLOCK - qRegisterMetaType(); + qRegisterMetaType("WindowFunction"); m_minFreq = config().readEntry( "minFreq", 50.0 ); m_maxFreq = config().readEntry( "maxFreq", 15000.0 ); diff --git a/src/context/applets/analyzer/plugin/AnalyzerPlugin.cpp b/src/context/applets/analyzer/plugin/AnalyzerPlugin.cpp --- a/src/context/applets/analyzer/plugin/AnalyzerPlugin.cpp +++ b/src/context/applets/analyzer/plugin/AnalyzerPlugin.cpp @@ -31,7 +31,7 @@ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - void registerTypes(const char* uri) Q_DECL_OVERRIDE + void registerTypes(const char* uri) override { Q_ASSERT(uri == QLatin1String("org.kde.amarok.analyzer")); diff --git a/src/context/applets/analyzer/plugin/BlockAnalyzer.h b/src/context/applets/analyzer/plugin/BlockAnalyzer.h --- a/src/context/applets/analyzer/plugin/BlockAnalyzer.h +++ b/src/context/applets/analyzer/plugin/BlockAnalyzer.h @@ -51,7 +51,7 @@ explicit BlockAnalyzer( QQuickItem *parent = Q_NULLPTR ); - Renderer* createRenderer() const Q_DECL_OVERRIDE; + Renderer* createRenderer() const override; FallSpeed fallSpeed() const { return m_fallSpeed; } void setFallSpeed( FallSpeed fallSpeed ); @@ -74,8 +74,8 @@ void refreshRateChanged( qreal ); protected: - virtual void geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) Q_DECL_OVERRIDE; - virtual Analyzer::Worker* createWorker() const Q_DECL_OVERRIDE; + virtual void geometryChanged(const QRectF& newGeometry, const QRectF& oldGeometry) override; + virtual Analyzer::Worker* createWorker() const override; virtual void paletteChange( const QPalette& ); void drawBackground( const QPalette &palette ); diff --git a/src/context/applets/analyzer/plugin/BlockRenderer.h b/src/context/applets/analyzer/plugin/BlockRenderer.h --- a/src/context/applets/analyzer/plugin/BlockRenderer.h +++ b/src/context/applets/analyzer/plugin/BlockRenderer.h @@ -43,14 +43,14 @@ BlockRenderer() {} protected: - QOpenGLFramebufferObject* createFramebufferObject(const QSize &size) Q_DECL_OVERRIDE + QOpenGLFramebufferObject* createFramebufferObject(const QSize &size) override { QOpenGLFramebufferObject* fo = new QOpenGLFramebufferObject(size); fo->setAttachment(QOpenGLFramebufferObject::CombinedDepthStencil); return fo; } - void render() Q_DECL_OVERRIDE + void render() override { QOpenGLPaintDevice d; d.setSize(framebufferObject()->size()); @@ -86,7 +86,7 @@ } } - void synchronize(QQuickFramebufferObject *item) Q_DECL_OVERRIDE + void synchronize(QQuickFramebufferObject *item) override { auto analyzer = qobject_cast(item); if (!analyzer) diff --git a/src/context/applets/analyzer/plugin/BlockWorker.h b/src/context/applets/analyzer/plugin/BlockWorker.h --- a/src/context/applets/analyzer/plugin/BlockWorker.h +++ b/src/context/applets/analyzer/plugin/BlockWorker.h @@ -43,7 +43,7 @@ void finished(); protected: - void analyze() Q_DECL_OVERRIDE; + void analyze() override; private: struct Fadebar diff --git a/src/context/applets/currenttrack/plugin/CurrentPlugin.cpp b/src/context/applets/currenttrack/plugin/CurrentPlugin.cpp --- a/src/context/applets/currenttrack/plugin/CurrentPlugin.cpp +++ b/src/context/applets/currenttrack/plugin/CurrentPlugin.cpp @@ -32,7 +32,7 @@ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - void registerTypes(const char* uri) Q_DECL_OVERRIDE + void registerTypes(const char* uri) override { Q_ASSERT(uri == QLatin1String("org.kde.amarok.currenttrack")); diff --git a/src/context/applets/info/plugin/InfoPlugin.cpp b/src/context/applets/info/plugin/InfoPlugin.cpp --- a/src/context/applets/info/plugin/InfoPlugin.cpp +++ b/src/context/applets/info/plugin/InfoPlugin.cpp @@ -32,7 +32,7 @@ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - void registerTypes(const char* uri) Q_DECL_OVERRIDE + void registerTypes(const char* uri) override { Q_ASSERT(uri == QLatin1String("org.kde.amarok.info")); diff --git a/src/context/applets/lyrics/plugin/LyricsEngine.h b/src/context/applets/lyrics/plugin/LyricsEngine.h --- a/src/context/applets/lyrics/plugin/LyricsEngine.h +++ b/src/context/applets/lyrics/plugin/LyricsEngine.h @@ -18,14 +18,13 @@ #ifndef AMAROK_LYRICS_ENGINE #define AMAROK_LYRICS_ENGINE -#include "context/LyricsManager.h" #include "core/meta/Meta.h" #include #include #include -class LyricsEngine : public QObject, public LyricsObserver +class LyricsEngine : public QObject { Q_OBJECT Q_PROPERTY(QString text READ text NOTIFY lyricsChanged) @@ -39,12 +38,11 @@ public: explicit LyricsEngine( QObject* parent = Q_NULLPTR ); - // reimplemented from LyricsObserver - void newLyrics( const LyricsData &lyrics ) Q_DECL_OVERRIDE; - void newSuggestions( const QVariantList &suggest ) Q_DECL_OVERRIDE; - void lyricsMessage( const QString& key, const QString& val ) Q_DECL_OVERRIDE; + void newLyrics( const Meta::TrackPtr &track ); + void newSuggestions( const QVariantList &suggest ); + void lyricsMessage( const QString& key, const QString& val ); - QString text() const { return m_lyrics.text; } + QString text() const { return m_lyrics; } QVariantList suggestions() const { return m_suggestions; } bool fetching() const { return m_fetching; } qreal position() const; @@ -56,7 +54,6 @@ void setFont( const QString &font ); Q_INVOKABLE void refetchLyrics() const; - Q_INVOKABLE void fetchLyrics( const QString &artist, const QString &title, const QString &url ); Q_INVOKABLE QStringList availableFonts() const; Q_SIGNALS: @@ -73,11 +70,9 @@ void onTrackMetadataChanged( Meta::TrackPtr track ); private: - void setLyrics( const LyricsData &lyrics ); void clearLyrics(); - void refetchLyrics(); - LyricsData m_lyrics; + QString m_lyrics; QVariantList m_suggestions; bool m_fetching; bool m_isUpdateInProgress; diff --git a/src/context/applets/lyrics/plugin/LyricsEngine.cpp b/src/context/applets/lyrics/plugin/LyricsEngine.cpp --- a/src/context/applets/lyrics/plugin/LyricsEngine.cpp +++ b/src/context/applets/lyrics/plugin/LyricsEngine.cpp @@ -20,140 +20,69 @@ #include "LyricsEngine.h" #include "EngineController.h" -#include "scripting/scriptmanager/ScriptManager.h" #include "core/support/Amarok.h" #include "core/support/Debug.h" +#include "lyrics/LyricsManager.h" #include #include LyricsEngine::LyricsEngine( QObject* parent ) : QObject( parent ) - , LyricsObserver( LyricsManager::self() ) , m_fetching( false ) , m_isUpdateInProgress( false ) { EngineController* engine = The::engineController(); + LyricsManager* lyricsManager = LyricsManager::instance(); connect( engine, &EngineController::trackChanged, this, &LyricsEngine::update ); connect( engine, &EngineController::trackMetadataChanged, this, &LyricsEngine::onTrackMetadataChanged ); connect( engine, &EngineController::trackPositionChanged, this, &LyricsEngine::positionChanged ); + connect( lyricsManager, &LyricsManager::newLyrics, this, &LyricsEngine::newLyrics ); + connect( lyricsManager, &LyricsManager::newSuggestions, this, &LyricsEngine::newSuggestions ); } void LyricsEngine::onTrackMetadataChanged( Meta::TrackPtr track ) { DEBUG_BLOCK // Only update if the lyrics have changed. - QString artist = track->artist() ? track->artist()->name() : QString(); - if( m_lyrics.artist != artist || - m_lyrics.title != track->name() || - m_lyrics.text != track->cachedLyrics() ) + if( m_lyrics != track->cachedLyrics() ) update(); } void LyricsEngine::update() { - if( m_isUpdateInProgress ) - return; - - m_isUpdateInProgress = true; - - // -- get current title and artist - Meta::TrackPtr currentTrack = The::engineController()->currentTrack(); - if( !currentTrack ) + Meta::TrackPtr track = The::engineController()->currentTrack(); + if( !track ) { - debug() << "no current track"; - m_lyrics.clear(); - emit lyricsChanged(); - m_isUpdateInProgress = false; + clearLyrics(); return; } - QString title = currentTrack->name(); - QString artist = currentTrack->artist() ? currentTrack->artist()->name() : QString(); - - // -- clean up title - const QString magnatunePreviewString = QLatin1String( "PREVIEW: buy it at www.magnatune.com" ); - if( title.contains(magnatunePreviewString, Qt::CaseSensitive) ) - title = title.remove( " (" + magnatunePreviewString + ')' ); - if( artist.contains(magnatunePreviewString, Qt::CaseSensitive) ) - artist = artist.remove( " (" + magnatunePreviewString + ')' ); - - if( title.isEmpty() && currentTrack ) - { - /* If title is empty, try to use pretty title. - The fact that it often (but not always) has "artist name" together, can be bad, - but at least the user will hopefully get nice suggestions. */ - QString prettyTitle = currentTrack->prettyName(); - int h = prettyTitle.indexOf( QLatin1Char('-') ); - if ( h != -1 ) - { - title = prettyTitle.mid( h + 1 ).trimmed(); - if( title.contains(magnatunePreviewString, Qt::CaseSensitive) ) - title = title.remove( " (" + magnatunePreviewString + ')' ); - - if( artist.isEmpty() ) - { - artist = prettyTitle.mid( 0, h ).trimmed(); - if( artist.contains(magnatunePreviewString, Qt::CaseSensitive) ) - artist = artist.remove( " (" + magnatunePreviewString + ')' ); - } - } - } - - LyricsData lyrics = { currentTrack->cachedLyrics(), title, artist, QUrl() }; - - // Check if the title, the artist and the lyrics are still the same. - if( !lyrics.text.isEmpty() && (lyrics.text == m_lyrics.text) ) + if( LyricsManager::instance()->isEmpty( track->cachedLyrics() ) ) { - debug() << "nothing changed:" << lyrics.title; - newLyrics( lyrics ); - m_isUpdateInProgress = false; + clearLyrics(); return; } - // don't rely on caching for streams - const bool cached = !LyricsManager::self()->isEmpty( lyrics.text ) - && !The::engineController()->isStream(); - - if( cached ) - { - newLyrics( lyrics ); - } - else - { - // no lyrics, and no lyrics script! - if( !ScriptManager::instance()->lyricsScriptRunning() ) - { - debug() << "no lyrics script running"; - clearLyrics(); - disconnect( ScriptManager::instance(), &ScriptManager::lyricsScriptStarted, this, 0 ); - connect( ScriptManager::instance(), &ScriptManager::lyricsScriptStarted, this, &LyricsEngine::update ); - m_isUpdateInProgress = false; - return; - } - - // fetch by lyrics script - clearLyrics(); - m_fetching = true; - emit fetchingChanged(); - ScriptManager::instance()->notifyFetchLyrics( lyrics.artist, lyrics.title, "", currentTrack ); - } - m_isUpdateInProgress = false; + newLyrics( track ); } -void LyricsEngine::newLyrics( const LyricsData &lyrics ) +void LyricsEngine::newLyrics( const Meta::TrackPtr &track ) { DEBUG_BLOCK - m_lyrics = lyrics; + if( track != The::engineController()->currentTrack() ) + return; + + m_lyrics = track->cachedLyrics(); emit lyricsChanged(); m_fetching = false; @@ -197,36 +126,7 @@ if( !currentTrack ) return; - ScriptManager::instance()->notifyFetchLyrics( m_lyrics.artist, m_lyrics.title, "", currentTrack ); -} - -void LyricsEngine::refetchLyrics() -{ - DEBUG_BLOCK - - auto currentTrack = The::engineController()->currentTrack(); - - if( currentTrack ) - ScriptManager::instance()->notifyFetchLyrics( currentTrack->artist()->name(), - currentTrack->name(), "", currentTrack ); - - m_fetching = true; - emit fetchingChanged(); -} - -void LyricsEngine::fetchLyrics(const QString& artist, const QString& title, const QString& url) -{ - DEBUG_BLOCK - - if( !QUrl( url ).isValid() ) - return; - - debug() << "clicked suggestion" << url; - - ScriptManager::instance()->notifyFetchLyrics( artist, title, url, Meta::TrackPtr() ); - - m_fetching = true; - emit fetchingChanged(); + LyricsManager::instance()->loadLyrics( currentTrack, true ); } qreal LyricsEngine::fontSize() const diff --git a/src/context/applets/lyrics/plugin/LyricsPlugin.cpp b/src/context/applets/lyrics/plugin/LyricsPlugin.cpp --- a/src/context/applets/lyrics/plugin/LyricsPlugin.cpp +++ b/src/context/applets/lyrics/plugin/LyricsPlugin.cpp @@ -32,7 +32,7 @@ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - void registerTypes(const char* uri) Q_DECL_OVERRIDE + void registerTypes(const char* uri) override { Q_ASSERT(uri == QLatin1String("org.kde.amarok.lyrics")); diff --git a/src/context/applets/photos/plugin/PhotosPlugin.cpp b/src/context/applets/photos/plugin/PhotosPlugin.cpp --- a/src/context/applets/photos/plugin/PhotosPlugin.cpp +++ b/src/context/applets/photos/plugin/PhotosPlugin.cpp @@ -32,7 +32,7 @@ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - void registerTypes(const char* uri) Q_DECL_OVERRIDE + void registerTypes(const char* uri) override { Q_ASSERT(uri == QLatin1String("org.kde.amarok.photos")); diff --git a/src/context/applets/wikipedia/plugin/WikipediaPlugin.cpp b/src/context/applets/wikipedia/plugin/WikipediaPlugin.cpp --- a/src/context/applets/wikipedia/plugin/WikipediaPlugin.cpp +++ b/src/context/applets/wikipedia/plugin/WikipediaPlugin.cpp @@ -32,7 +32,7 @@ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - void registerTypes(const char* uri) Q_DECL_OVERRIDE + void registerTypes(const char* uri) override { Q_ASSERT(uri == QLatin1String("org.kde.amarok.wikipedia")); diff --git a/src/context/qml_plugin/src/PixmapItem.h b/src/context/qml_plugin/src/PixmapItem.h --- a/src/context/qml_plugin/src/PixmapItem.h +++ b/src/context/qml_plugin/src/PixmapItem.h @@ -40,8 +40,8 @@ QPixmap source() const { return m_source; } bool valid() const { return !m_source.isNull(); } - QSGNode* updatePaintNode( QSGNode * oldNode, UpdatePaintNodeData * updatePaintNodeData ) Q_DECL_OVERRIDE; - void geometryChanged( const QRectF &newGeometry, const QRectF &oldGeometry ) Q_DECL_OVERRIDE; + QSGNode* updatePaintNode( QSGNode * oldNode, UpdatePaintNodeData * updatePaintNodeData ) override; + void geometryChanged( const QRectF &newGeometry, const QRectF &oldGeometry ) override; signals: void sourceChanged(); diff --git a/src/context/qml_plugin/src/Plugin.cpp b/src/context/qml_plugin/src/Plugin.cpp --- a/src/context/qml_plugin/src/Plugin.cpp +++ b/src/context/qml_plugin/src/Plugin.cpp @@ -33,7 +33,7 @@ Q_PLUGIN_METADATA(IID QQmlExtensionInterface_iid) public: - void registerTypes(const char* uri) Q_DECL_OVERRIDE + void registerTypes(const char* uri) override { Q_ASSERT(uri == QLatin1String("org.kde.amarok.qml")); diff --git a/src/context/qml_plugin/src/RatingItem.h b/src/context/qml_plugin/src/RatingItem.h --- a/src/context/qml_plugin/src/RatingItem.h +++ b/src/context/qml_plugin/src/RatingItem.h @@ -144,11 +144,11 @@ protected: - virtual void mousePressEvent( QMouseEvent* e ) Q_DECL_OVERRIDE; - virtual void hoverMoveEvent( QHoverEvent* e ) Q_DECL_OVERRIDE; - virtual void hoverEnterEvent( QHoverEvent* e ) Q_DECL_OVERRIDE; - virtual void hoverLeaveEvent( QHoverEvent* e ) Q_DECL_OVERRIDE; - virtual void paint( QPainter* painter ) Q_DECL_OVERRIDE; + virtual void mousePressEvent( QMouseEvent* e ) override; + virtual void hoverMoveEvent( QHoverEvent* e ) override; + virtual void hoverEnterEvent( QHoverEvent* e ) override; + virtual void hoverLeaveEvent( QHoverEvent* e ) override; + virtual void paint( QPainter* painter ) override; private: class Private; diff --git a/src/core-impl/collections/daap/daapreader/Reader.h b/src/core-impl/collections/daap/daapreader/Reader.h --- a/src/core-impl/collections/daap/daapreader/Reader.h +++ b/src/core-impl/collections/daap/daapreader/Reader.h @@ -126,12 +126,12 @@ WorkerThread( const QByteArray &data, Reader* reader, Collections::DaapCollection *coll ); virtual ~WorkerThread(); - virtual bool success() const Q_DECL_OVERRIDE; + virtual bool success() const override; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void run(ThreadWeaver::JobPointer self=QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void run(ThreadWeaver::JobPointer self=QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ diff --git a/src/core-impl/collections/db/sql/SqlMeta.h b/src/core-impl/collections/db/sql/SqlMeta.h --- a/src/core-impl/collections/db/sql/SqlMeta.h +++ b/src/core-impl/collections/db/sql/SqlMeta.h @@ -26,6 +26,7 @@ #include "amarok_sqlcollection_export.h" #include "FileType.h" +#include #include #include #include @@ -423,28 +424,33 @@ * The path should point to a valid image. * Note: setImage will not delete the already set image. */ - void setImage( const QString &path ); + void setImage( const QString &path ); - /** Finds or creates a magic value in the database which tells Amarok not to auto fetch an image since it has been explicitly unset. - */ - int unsetImageId() const; + /** Finds or creates a magic value in the database which tells Amarok not to auto fetch an image since it has been explicitly unset. + */ + int unsetImageId() const; - private: Collections::SqlCollection* const m_collection; + enum TracksLoadingStatus + { + NotLoaded, + Loading, + Loaded + }; - QString m_name; - int m_id; // the id of this album in the database - int m_artistId; + const QString m_name; + const int m_id; // the id of this album in the database + const int m_artistId; int m_imageId; mutable QString m_imagePath; // path read from the database mutable bool m_hasImage; // true if we have an original image mutable bool m_hasImageChecked; // true if hasImage was checked mutable int m_unsetImageId; // this is the id of the unset magic value in the image sql database static const QString AMAROK_UNSET_MAGIC; - bool m_tracksLoaded; + TracksLoadingStatus m_tracksLoaded; bool m_suppressAutoFetch; Meta::ArtistPtr m_artist; Meta::TrackList m_tracks; @@ -478,6 +484,7 @@ const QString m_name; bool m_tracksLoaded; + bool m_tracksLoading; Meta::TrackList m_tracks; QMutex m_mutex; diff --git a/src/core-impl/collections/db/sql/SqlMeta.cpp b/src/core-impl/collections/db/sql/SqlMeta.cpp --- a/src/core-impl/collections/db/sql/SqlMeta.cpp +++ b/src/core-impl/collections/db/sql/SqlMeta.cpp @@ -59,8 +59,6 @@ #include #include -#include - // additional constants namespace Meta @@ -1471,7 +1469,7 @@ , m_hasImage( false ) , m_hasImageChecked( false ) , m_unsetImageId( -1 ) - , m_tracksLoaded( false ) + , m_tracksLoaded( NotLoaded ) , m_suppressAutoFetch( false ) , m_mutex( QMutex::Recursive ) { @@ -1488,37 +1486,59 @@ SqlAlbum::invalidateCache() { QMutexLocker locker( &m_mutex ); - m_tracksLoaded = false; + m_tracksLoaded = NotLoaded; m_hasImage = false; m_hasImageChecked = false; m_tracks.clear(); } TrackList SqlAlbum::tracks() { + bool startQuery = false; + { QMutexLocker locker( &m_mutex ); - if( m_tracksLoaded ) + if( m_tracksLoaded == Loaded ) return m_tracks; + else if( m_tracksLoaded == NotLoaded ) + { + startQuery = true; + m_tracksLoaded = Loading; + } } - // when running the query maker don't lock. might lead to deadlock via registry - Collections::SqlQueryMaker *qm = static_cast< Collections::SqlQueryMaker* >( m_collection->queryMaker() ); - qm->setQueryType( Collections::QueryMaker::Track ); - qm->addMatch( Meta::AlbumPtr( this ) ); - qm->orderBy( Meta::valDiscNr ); - qm->orderBy( Meta::valTrackNr ); - qm->orderBy( Meta::valTitle ); - qm->setBlocking( true ); - qm->run(); + if( startQuery ) + { + // when running the query maker don't lock. might lead to deadlock via registry + Collections::SqlQueryMaker *qm = static_cast< Collections::SqlQueryMaker* >( m_collection->queryMaker() ); + qm->setQueryType( Collections::QueryMaker::Track ); + qm->addMatch( Meta::AlbumPtr( this ) ); + qm->orderBy( Meta::valDiscNr ); + qm->orderBy( Meta::valTrackNr ); + qm->orderBy( Meta::valTitle ); + qm->setBlocking( true ); + qm->run(); + { + QMutexLocker locker( &m_mutex ); + m_tracks = qm->tracks(); + m_tracksLoaded = Loaded; + delete qm; + return m_tracks; + } + } + else { - QMutexLocker locker( &m_mutex ); - m_tracks = qm->tracks(); - m_tracksLoaded = true; - delete qm; - return m_tracks; + // Wait for tracks to be loaded + forever + { + QMutexLocker locker( &m_mutex ); + if( m_tracksLoaded == Loaded ) + return m_tracks; + else + QThread::yieldCurrentThread(); + } } } @@ -1610,8 +1630,7 @@ if( size > 1 && size < 1000 ) { image = image.scaled( size, size, Qt::KeepAspectRatio, Qt::SmoothTransformation ); - std::thread thread( QOverload::of( &QImage::save ), image, cachedImagePath, "PNG", -1 ); - thread.detach(); + image.save( cachedImagePath, "PNG", -1 ); } return image; @@ -1654,10 +1673,11 @@ if( m_name.isEmpty() ) return; - QMutexLocker locker( &m_mutex ); if( image.isNull() ) return; + QMutexLocker locker( &m_mutex ); + // removeImage() will destroy all scaled cached versions of the artwork // and remove references from the database if required. removeImage(); @@ -1667,8 +1687,7 @@ while( QFile(path).exists() ) path += '_'; // not that nice but it shouldn't happen that often. - std::thread thread( QOverload::of( &QImage::save ), image, path, "JPG", -1 ); - thread.detach(); + image.save( path, "JPG", -1 ); setImage( path ); locker.unlock(); @@ -1917,23 +1936,22 @@ void SqlAlbum::setImage( const QString &path ) { - if( m_imagePath == path ) - return; if( m_name.isEmpty() ) // the empty album never has an image return; QMutexLocker locker( &m_mutex ); - QString imagePath = path; + if( m_imagePath == path ) + return; QString query = "SELECT id FROM images WHERE path = '%1'"; - query = query.arg( m_collection->sqlStorage()->escape( imagePath ) ); + query = query.arg( m_collection->sqlStorage()->escape( path ) ); QStringList res = m_collection->sqlStorage()->query( query ); if( res.isEmpty() ) { QString insert = QString( "INSERT INTO images( path ) VALUES ( '%1' )" ) - .arg( m_collection->sqlStorage()->escape( imagePath ) ); + .arg( m_collection->sqlStorage()->escape( path ) ); m_imageId = m_collection->sqlStorage()->insert( insert, "images" ); } else @@ -1945,7 +1963,7 @@ .arg( QString::number( m_imageId ), QString::number( m_id ) ); m_collection->sqlStorage()->query( query ); - m_imagePath = imagePath; + m_imagePath = path; m_hasImage = true; m_hasImageChecked = true; CoverCache::invalidateAlbum( this ); diff --git a/src/core-impl/collections/ipodcollection/jobs/IpodCopyTracksJob.h b/src/core-impl/collections/ipodcollection/jobs/IpodCopyTracksJob.h --- a/src/core-impl/collections/ipodcollection/jobs/IpodCopyTracksJob.h +++ b/src/core-impl/collections/ipodcollection/jobs/IpodCopyTracksJob.h @@ -49,7 +49,7 @@ const QPointer &collection, const Transcoding::Configuration &configuration, bool goingToRemoveSources ); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; public Q_SLOTS: void abort(); @@ -116,8 +116,8 @@ QSet m_copyErrors; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; diff --git a/src/core-impl/collections/ipodcollection/jobs/IpodDeleteTracksJob.h b/src/core-impl/collections/ipodcollection/jobs/IpodDeleteTracksJob.h --- a/src/core-impl/collections/ipodcollection/jobs/IpodDeleteTracksJob.h +++ b/src/core-impl/collections/ipodcollection/jobs/IpodDeleteTracksJob.h @@ -30,7 +30,7 @@ public: explicit IpodDeleteTracksJob( const Meta::TrackList &sources, const QPointer &collection ); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; Q_SIGNALS: // signals for progress operation: @@ -47,8 +47,8 @@ void failed(ThreadWeaver::JobPointer); protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; private: Meta::TrackList m_sources; diff --git a/src/core-impl/collections/ipodcollection/jobs/IpodParseTracksJob.h b/src/core-impl/collections/ipodcollection/jobs/IpodParseTracksJob.h --- a/src/core-impl/collections/ipodcollection/jobs/IpodParseTracksJob.h +++ b/src/core-impl/collections/ipodcollection/jobs/IpodParseTracksJob.h @@ -42,9 +42,9 @@ void abort(); protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; Q_SIGNALS: // signals for progress operation: diff --git a/src/core-impl/collections/ipodcollection/jobs/IpodWriteDatabaseJob.h b/src/core-impl/collections/ipodcollection/jobs/IpodWriteDatabaseJob.h --- a/src/core-impl/collections/ipodcollection/jobs/IpodWriteDatabaseJob.h +++ b/src/core-impl/collections/ipodcollection/jobs/IpodWriteDatabaseJob.h @@ -33,7 +33,7 @@ public: explicit IpodWriteDatabaseJob( IpodCollection *collection ); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ @@ -45,8 +45,8 @@ void failed(ThreadWeaver::JobPointer); protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; private: IpodCollection *m_coll; diff --git a/src/core-impl/collections/mediadevicecollection/handler/MediaDeviceHandler.h b/src/core-impl/collections/mediadevicecollection/handler/MediaDeviceHandler.h --- a/src/core-impl/collections/mediadevicecollection/handler/MediaDeviceHandler.h +++ b/src/core-impl/collections/mediadevicecollection/handler/MediaDeviceHandler.h @@ -381,7 +381,7 @@ * @return Whether or not the copy was successful, i.e. m_success */ - virtual bool success() const; + virtual bool success() const override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ @@ -405,9 +405,9 @@ /** * Reimplemented, simply runs the parse method. */ - virtual void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + virtual void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; private: bool m_success; ///< Whether or not the parse was successful @@ -445,7 +445,7 @@ * @return Whether or not the copy was successful, i.e. m_success */ - virtual bool success() const; + virtual bool success() const override; Q_SIGNALS: @@ -493,9 +493,9 @@ /** * Reimplemented, simply runs the copy track method. */ - virtual void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + virtual void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; private: bool m_success; ///< Whether or not the copy was successful diff --git a/src/core-impl/collections/mediadevicecollection/playlist/MediaDeviceUserPlaylistProvider.cpp b/src/core-impl/collections/mediadevicecollection/playlist/MediaDeviceUserPlaylistProvider.cpp --- a/src/core-impl/collections/mediadevicecollection/playlist/MediaDeviceUserPlaylistProvider.cpp +++ b/src/core-impl/collections/mediadevicecollection/playlist/MediaDeviceUserPlaylistProvider.cpp @@ -35,7 +35,7 @@ #include -static const int USERPLAYLIST_DB_VERSION = 2; +// static const int USERPLAYLIST_DB_VERSION = 2; static const QString key("AMAROK_USERPLAYLIST"); namespace Playlists { diff --git a/src/core-impl/collections/mtpcollection/handler/MtpHandler.h b/src/core-impl/collections/mtpcollection/handler/MtpHandler.h --- a/src/core-impl/collections/mtpcollection/handler/MtpHandler.h +++ b/src/core-impl/collections/mtpcollection/handler/MtpHandler.h @@ -261,12 +261,12 @@ WorkerThread( int numrawdevices, LIBMTP_raw_device_t* rawdevices, MtpHandler* handler ); virtual ~WorkerThread(); - virtual bool success() const Q_DECL_OVERRIDE; + virtual bool success() const override; protected: - virtual void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + virtual void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ diff --git a/src/core-impl/collections/nepomukcollection/NepomukInquirer.h b/src/core-impl/collections/nepomukcollection/NepomukInquirer.h --- a/src/core-impl/collections/nepomukcollection/NepomukInquirer.h +++ b/src/core-impl/collections/nepomukcollection/NepomukInquirer.h @@ -51,9 +51,9 @@ void failed(ThreadWeaver::JobPointer); protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; private: QString m_query; diff --git a/src/core-impl/collections/playdarcollection/PlaydarCollection.cpp b/src/core-impl/collections/playdarcollection/PlaydarCollection.cpp --- a/src/core-impl/collections/playdarcollection/PlaydarCollection.cpp +++ b/src/core-impl/collections/playdarcollection/PlaydarCollection.cpp @@ -57,7 +57,7 @@ PlaydarCollectionFactory::init() { DEBUG_BLOCK - m_controller = new Playdar::Controller( this ); + m_controller = new Playdar::Controller; connect( m_controller, &Playdar::Controller::playdarReady, this, &PlaydarCollectionFactory::playdarReady ); connect( m_controller, &Playdar::Controller::playdarError, diff --git a/src/core-impl/collections/support/MemoryQueryMaker.h b/src/core-impl/collections/support/MemoryQueryMaker.h --- a/src/core-impl/collections/support/MemoryQueryMaker.h +++ b/src/core-impl/collections/support/MemoryQueryMaker.h @@ -47,37 +47,37 @@ MemoryQueryMaker( QWeakPointer mc, const QString &collectionId ); virtual ~MemoryQueryMaker(); - virtual void run() Q_DECL_OVERRIDE; - virtual void abortQuery(); + virtual void run() override; + virtual void abortQuery() override; - virtual QueryMaker* setQueryType( QueryType type ); + virtual QueryMaker* setQueryType( QueryType type ) override; - virtual QueryMaker* addReturnValue( qint64 value ); - virtual QueryMaker* addReturnFunction( ReturnFunction function, qint64 value ); - virtual QueryMaker* orderBy( qint64 value, bool descending = false ); + virtual QueryMaker* addReturnValue( qint64 value ) override; + virtual QueryMaker* addReturnFunction( ReturnFunction function, qint64 value ) override; + virtual QueryMaker* orderBy( qint64 value, bool descending = false ) override; - virtual QueryMaker* addMatch( const Meta::TrackPtr &track ); - virtual QueryMaker* addMatch( const Meta::ArtistPtr &artist, ArtistMatchBehaviour behaviour = TrackArtists ); - virtual QueryMaker* addMatch( const Meta::AlbumPtr &album ); - virtual QueryMaker* addMatch( const Meta::ComposerPtr &composer ); - virtual QueryMaker* addMatch( const Meta::GenrePtr &genre ); - virtual QueryMaker* addMatch( const Meta::YearPtr &year ); - virtual QueryMaker* addMatch( const Meta::LabelPtr &label ); + virtual QueryMaker* addMatch( const Meta::TrackPtr &track ) override; + virtual QueryMaker* addMatch( const Meta::ArtistPtr &artist, ArtistMatchBehaviour behaviour = TrackArtists ) override; + virtual QueryMaker* addMatch( const Meta::AlbumPtr &album ) override; + virtual QueryMaker* addMatch( const Meta::ComposerPtr &composer ) override; + virtual QueryMaker* addMatch( const Meta::GenrePtr &genre ) override; + virtual QueryMaker* addMatch( const Meta::YearPtr &year ) override; + virtual QueryMaker* addMatch( const Meta::LabelPtr &label ) override; - virtual QueryMaker* addFilter( qint64 value, const QString &filter, bool matchBegin, bool matchEnd ); - virtual QueryMaker* excludeFilter( qint64 value, const QString &filter, bool matchBegin, bool matchEnd ); + virtual QueryMaker* addFilter( qint64 value, const QString &filter, bool matchBegin, bool matchEnd ) override; + virtual QueryMaker* excludeFilter( qint64 value, const QString &filter, bool matchBegin, bool matchEnd ) override; - virtual QueryMaker* addNumberFilter( qint64 value, qint64 filter, NumberComparison compare ); - virtual QueryMaker* excludeNumberFilter( qint64 value, qint64 filter, NumberComparison compare ); + virtual QueryMaker* addNumberFilter( qint64 value, qint64 filter, NumberComparison compare ) override; + virtual QueryMaker* excludeNumberFilter( qint64 value, qint64 filter, NumberComparison compare ) override; - virtual QueryMaker* limitMaxResultSize( int size ); + virtual QueryMaker* limitMaxResultSize( int size ) override; - virtual QueryMaker* beginAnd(); - virtual QueryMaker* beginOr(); - virtual QueryMaker* endAndOr(); + virtual QueryMaker* beginAnd() override; + virtual QueryMaker* beginOr() override; + virtual QueryMaker* endAndOr() override; - virtual QueryMaker* setAlbumQueryMode( AlbumQueryMode mode ); - virtual QueryMaker* setLabelQueryMode( LabelQueryMode mode ); + virtual QueryMaker* setAlbumQueryMode( AlbumQueryMode mode ) override; + virtual QueryMaker* setLabelQueryMode( LabelQueryMode mode ) override; private Q_SLOTS: void done( ThreadWeaver::JobPointer job ); diff --git a/src/core-impl/collections/support/jobs/WriteTagsJob.h b/src/core-impl/collections/support/jobs/WriteTagsJob.h --- a/src/core-impl/collections/support/jobs/WriteTagsJob.h +++ b/src/core-impl/collections/support/jobs/WriteTagsJob.h @@ -39,11 +39,11 @@ public: WriteTagsJob( const QString &path, const Meta::FieldHash &changes, bool respectConfig = true ); - virtual void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + virtual void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ diff --git a/src/core-impl/meta/proxy/MetaProxyWorker.h b/src/core-impl/meta/proxy/MetaProxyWorker.h --- a/src/core-impl/meta/proxy/MetaProxyWorker.h +++ b/src/core-impl/meta/proxy/MetaProxyWorker.h @@ -43,11 +43,11 @@ explicit Worker( const QUrl &url, Collections::TrackProvider *provider = 0 ); //TrackForUrlWorker virtual methods - virtual void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + virtual void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; Q_SIGNALS: void finishedLookup( Meta::TrackPtr track ); diff --git a/src/core-impl/meta/timecode/TimecodeMeta.cpp b/src/core-impl/meta/timecode/TimecodeMeta.cpp --- a/src/core-impl/meta/timecode/TimecodeMeta.cpp +++ b/src/core-impl/meta/timecode/TimecodeMeta.cpp @@ -556,7 +556,7 @@ TrackList TimecodeGenre::tracks() { - return tracks(); + return m_tracks; } void diff --git a/src/core-impl/playlists/types/file/PlaylistFileLoaderJob.h b/src/core-impl/playlists/types/file/PlaylistFileLoaderJob.h --- a/src/core-impl/playlists/types/file/PlaylistFileLoaderJob.h +++ b/src/core-impl/playlists/types/file/PlaylistFileLoaderJob.h @@ -38,9 +38,9 @@ explicit PlaylistFileLoaderJob( const PlaylistFilePtr &playlist ); protected: - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ diff --git a/src/core/support/Debug_p.h b/src/core/support/Debug_p.h --- a/src/core/support/Debug_p.h +++ b/src/core/support/Debug_p.h @@ -42,19 +42,19 @@ { open(WriteOnly); } - bool isSequential() const Q_DECL_OVERRIDE + bool isSequential() const override { return true; } - qint64 readData(char *, qint64) Q_DECL_OVERRIDE + qint64 readData(char *, qint64) override { return 0; } - qint64 readLineData(char *, qint64) Q_DECL_OVERRIDE + qint64 readLineData(char *, qint64) override { return 0; } - qint64 writeData(const char *, qint64 len) Q_DECL_OVERRIDE + qint64 writeData(const char *, qint64 len) override { return len; } diff --git a/src/covermanager/CoverFetchQueue.h b/src/covermanager/CoverFetchQueue.h --- a/src/covermanager/CoverFetchQueue.h +++ b/src/covermanager/CoverFetchQueue.h @@ -83,13 +83,7 @@ unsigned int page = 0, Meta::AlbumPtr album = Meta::AlbumPtr(0) ); - bool contains( const Meta::AlbumPtr album ) const; - int index( const Meta::AlbumPtr album ) const; - int size() const; - bool isEmpty() const; - void clear(); - const CoverFetchUnit::Ptr take( const Meta::AlbumPtr album ); public Q_SLOTS: void remove( const CoverFetchUnit::Ptr unit ); @@ -100,6 +94,9 @@ private: void add( const CoverFetchUnit::Ptr unit ); + bool contains( const Meta::AlbumPtr album ) const; + int index( const Meta::AlbumPtr album ) const; + const CoverFetchUnit::Ptr take( const Meta::AlbumPtr album ); CoverFetchUnitList m_queue; Q_DISABLE_COPY( CoverFetchQueue ) diff --git a/src/covermanager/CoverFetchQueue.cpp b/src/covermanager/CoverFetchQueue.cpp --- a/src/covermanager/CoverFetchQueue.cpp +++ b/src/covermanager/CoverFetchQueue.cpp @@ -16,6 +16,7 @@ #include "CoverFetchQueue.h" + CoverFetchQueue::CoverFetchQueue( QObject *parent ) : QObject( parent ) { @@ -98,18 +99,6 @@ add( AmarokSharedPointer< CoverFetchUnit >( new CoverFetchUnit( payload ) ) ); } -int -CoverFetchQueue::size() const -{ - return m_queue.size(); -} - -bool -CoverFetchQueue::isEmpty() const -{ - return m_queue.isEmpty(); -} - void CoverFetchQueue::clear() { @@ -158,7 +147,7 @@ const CoverFetchUnit::Ptr CoverFetchQueue::take( const Meta::AlbumPtr album ) { - for( int i = 0, end = this->size(); i < end; ++i ) + for( int i = 0, end = m_queue.size(); i < end; ++i ) { const CoverFetchUnit::Ptr unit = m_queue.at( i ); if( unit->album() == album ) diff --git a/src/covermanager/CoverFetcher.h b/src/covermanager/CoverFetcher.h --- a/src/covermanager/CoverFetcher.h +++ b/src/covermanager/CoverFetcher.h @@ -31,6 +31,7 @@ class CoverFetchQueue; class CoverFoundDialog; +class QThread; namespace KIO { class Job; } @@ -62,7 +63,7 @@ void slotFetch( CoverFetchUnit::Ptr unit ); /// Handle result of a fetch job - void slotResult( const QUrl &url, QByteArray data, NetworkAccessManagerProxy::Error e ); + void slotResult( const QUrl &url, const QByteArray &data, NetworkAccessManagerProxy::Error e ); /// Cover found dialog is closed by the user void slotDialogFinished(); @@ -80,9 +81,8 @@ void queueQueryForAlbum( Meta::AlbumPtr album ); - const int m_limit; //!< maximum number of concurrent fetches CoverFetchQueue *m_queue; //!< current fetch queue - Meta::AlbumList m_queueLater; //!< put here if m_queue exceeds m_limit + QThread *m_queueThread; QHash< QUrl, CoverFetchUnit::Ptr > m_urls; QHash< const CoverFetchUnit::Ptr, QImage > m_selectedImages; diff --git a/src/covermanager/CoverFetcher.cpp b/src/covermanager/CoverFetcher.cpp --- a/src/covermanager/CoverFetcher.cpp +++ b/src/covermanager/CoverFetcher.cpp @@ -32,17 +32,19 @@ #include "CoverFoundDialog.h" #include "CoverFetchUnit.h" -#include -#include - #include #include +#include #include #include #include -CoverFetcher* CoverFetcher::s_instance = 0; +#include +#include + + +CoverFetcher* CoverFetcher::s_instance = nullptr; CoverFetcher* CoverFetcher::instance() @@ -55,29 +57,36 @@ if( s_instance ) { delete s_instance; - s_instance = 0; + s_instance = nullptr; } } CoverFetcher::CoverFetcher() : QObject() - , m_limit( 10 ) { DEBUG_BLOCK setObjectName( "CoverFetcher" ); qRegisterMetaType("CoverFetchUnit::Ptr"); - m_queue = new CoverFetchQueue( this ); + s_instance = this; + + m_queueThread = new QThread( this ); + m_queueThread->start(); + m_queue = new CoverFetchQueue; + m_queue->moveToThread( m_queueThread ); + connect( m_queue, &CoverFetchQueue::fetchUnitAdded, this, &CoverFetcher::slotFetch ); - s_instance = this; connect( The::networkAccessManager(), &NetworkAccessManagerProxy::requestRedirectedReply, this, &CoverFetcher::fetchRequestRedirected ); } CoverFetcher::~CoverFetcher() { + m_queue->deleteLater(); + m_queueThread->quit(); + m_queueThread->wait(); } void @@ -89,7 +98,7 @@ switch( fetchSource() ) { case CoverFetch::LastFm: - m_queue->add( album, CoverFetch::Interactive, fetchSource() ); + QTimer::singleShot( 0, m_queue, [=] () { m_queue->add( album, CoverFetch::Interactive, fetchSource() ); } ); break; case CoverFetch::Discogs: @@ -105,29 +114,23 @@ void CoverFetcher::queueAlbum( Meta::AlbumPtr album ) { - if( m_queue->size() > m_limit ) - m_queueLater.append( album ); - else - m_queue->add( album, CoverFetch::Automatic ); + QTimer::singleShot( 0, m_queue, [=] () { m_queue->add( album, CoverFetch::Automatic ); } ); debug() << "Queueing automatic cover fetch for:" << album->name(); } void CoverFetcher::queueAlbums( Meta::AlbumList albums ) { foreach( Meta::AlbumPtr album, albums ) { - if( m_queue->size() > m_limit ) - m_queueLater.append( album ); - else - m_queue->add( album, CoverFetch::Automatic ); + QTimer::singleShot( 0, m_queue, [=] () { m_queue->add( album, CoverFetch::Automatic ); } ); } } void CoverFetcher::queueQuery( Meta::AlbumPtr album, const QString &query, int page ) { - m_queue->addQuery( query, fetchSource(), page, album ); + QTimer::singleShot( 0, m_queue, [=] () { m_queue->addQuery( query, fetchSource(), page, album ); } ); debug() << QString( "Queueing cover fetch query: '%1' (page %2)" ).arg( query, QString::number( page ) ); } @@ -180,17 +183,17 @@ } void -CoverFetcher::slotResult( const QUrl &url, QByteArray data, NetworkAccessManagerProxy::Error e ) +CoverFetcher::slotResult( const QUrl &url, const QByteArray &data, NetworkAccessManagerProxy::Error e ) { DEBUG_BLOCK if( !m_urls.contains( url ) ) return; - debug() << "Data dump from the result: " << data; +// debug() << "Data dump from the result: " << data; const CoverFetchUnit::Ptr unit( m_urls.take( url ) ); if( !unit ) { - m_queue->remove( unit ); + QTimer::singleShot( 0, m_queue, [=] () { m_queue->remove( unit ); } ); return; } @@ -204,13 +207,13 @@ switch( payload->type() ) { case CoverFetchPayload::Info: - m_queue->add( unit->album(), unit->options(), payload->source(), data ); - m_queue->remove( unit ); + QTimer::singleShot( 0, m_queue, [=] () { m_queue->add( unit->album(), unit->options(), payload->source(), data ); + m_queue->remove( unit ); } ); break; case CoverFetchPayload::Search: - m_queue->add( unit->options(), fetchSource(), data ); - m_queue->remove( unit ); + QTimer::singleShot( 0, m_queue, [=] () { m_queue->add( unit->options(), fetchSource(), data ); + m_queue->remove( unit ); } ); break; case CoverFetchPayload::Art: @@ -261,7 +264,7 @@ if( reader.read( &image ) ) { showCover( unit, image, metadata ); - m_queue->remove( unit ); + QTimer::singleShot( 0, m_queue, [=] () { m_queue->remove( unit ); } ); return; } } @@ -353,7 +356,7 @@ return; } - m_dialog = new CoverFoundDialog( unit, data, static_cast( parent() ) ); + m_dialog = new CoverFoundDialog( unit, data ); connect( m_dialog.data(), &CoverFoundDialog::newCustomQuery, this, &CoverFetcher::queueQuery ); connect( m_dialog.data(), &CoverFoundDialog::accepted, @@ -384,8 +387,7 @@ void CoverFetcher::abortFetch( CoverFetchUnit::Ptr unit ) { - m_queue->remove( unit ); - m_queueLater.removeAll( unit->album() ); + QTimer::singleShot( 0, m_queue, [=] () { m_queue->remove( unit ); } ); m_selectedImages.remove( unit ); QList urls = m_urls.keys( unit ); foreach( const QUrl &url, urls ) @@ -404,16 +406,19 @@ switch( state ) { case Success: + { if( !albumName.isEmpty() ) { const QString text = i18n( "Retrieved cover successfully for '%1'.", albumName ); Amarok::Logger::shortMessage( text ); debug() << "Finished successfully for album" << albumName; } - album->setImage( m_selectedImages.take( unit ) ); + QImage image = m_selectedImages.take( unit ); + std::thread thread( std::bind( &Meta::Album::setImage, album, image ) ); + thread.detach(); abortFetch( unit ); break; - + } case Error: if( !albumName.isEmpty() ) { @@ -448,21 +453,7 @@ break; } - m_queue->remove( unit ); - - if( !m_queueLater.isEmpty() ) - { - const int diff = m_limit - m_queue->size(); - if( diff > 0 ) - { - for( int i = 0; i < diff && !m_queueLater.isEmpty(); ++i ) - { - Meta::AlbumPtr album = m_queueLater.takeFirst(); - // automatic fetching only uses Last.fm as source - m_queue->add( album, CoverFetch::Automatic, CoverFetch::LastFm ); - } - } - } + QTimer::singleShot( 0, m_queue, [=] () { m_queue->remove( unit ); } ); emit finishedSingle( static_cast< int >( state ) ); } diff --git a/src/dialogs/TagDialog.h b/src/dialogs/TagDialog.h --- a/src/dialogs/TagDialog.h +++ b/src/dialogs/TagDialog.h @@ -64,9 +64,6 @@ using Observer::metadataChanged; void metadataChanged( Meta::AlbumPtr album ); - Q_SIGNALS: - void lyricsChanged( const QString& ); - private Q_SLOTS: void accept(); void cancelPressed(); @@ -175,13 +172,6 @@ void updateCover(); void setControlsAccessability(); - /** - * Stores changes to labels for a specific track - * @arg track Track to store the labels to - * @arg labels The new set of labels for the track - */ - void saveLabels( Meta::TrackPtr track, const QStringList &labels ); - /** Writes all the tags to all the tracks. This finally updates the Meta::Tracks */ @@ -205,6 +195,7 @@ bool m_perTrack; Meta::TrackList m_tracks; Meta::TrackPtr m_currentTrack; + Meta::AlbumPtr m_currentAlbum; int m_currentTrackNum; /** True if m_storedTags contains changed. diff --git a/src/dialogs/TagDialog.cpp b/src/dialogs/TagDialog.cpp --- a/src/dialogs/TagDialog.cpp +++ b/src/dialogs/TagDialog.cpp @@ -49,6 +49,9 @@ #include +#include + + namespace Meta { namespace Field { const QString LABELS = "labels"; @@ -127,20 +130,20 @@ Amarok::config( "TagDialog" ).writeEntry( "CurrentTab", ui->qTabWidget->currentIndex() ); - if( m_currentTrack && m_currentTrack->album() ) - unsubscribeFrom( m_currentTrack->album() ); + if( m_currentAlbum ) + unsubscribeFrom( m_currentAlbum ); delete ui; } void TagDialog::metadataChanged( Meta::AlbumPtr album ) { - if( !m_currentTrack || !m_currentTrack->album() ) + if( m_currentAlbum ) return; // If the metadata of the current album has changed, reload the cover - if( album == m_currentTrack->album() ) + if( album == m_currentAlbum ) updateCover(); // TODO: if the lyrics changed: should we show a warning and ask the user @@ -607,14 +610,15 @@ // there is a logical problem here. // if the track itself changes (e.g. because it get's a new album) // then we don't re-subscribe - if( m_currentTrack && m_currentTrack->album() ) - unsubscribeFrom( m_currentTrack->album() ); + if( m_currentAlbum ) + unsubscribeFrom( m_currentAlbum ); m_currentTrack = m_tracks.at( num ); + m_currentAlbum = m_currentTrack->album(); m_currentTrackNum = num; - if( m_currentTrack && m_currentTrack->album() ) - subscribeTo( m_currentTrack->album() ); + if( m_currentAlbum ) + subscribeTo( m_currentAlbum ); setControlsAccessability(); updateButtons(); @@ -675,23 +679,22 @@ void TagDialog::showCoverMenu( const QPoint &pos ) { - Meta::AlbumPtr album = m_currentTrack->album(); - if( !album ) + if( !m_currentAlbum ) return; // TODO: warning or something? - QAction *displayCoverAction = new DisplayCoverAction( this, album ); - QAction *unsetCoverAction = new UnsetCoverAction( this, album ); + QAction *displayCoverAction = new DisplayCoverAction( this, m_currentAlbum ); + QAction *unsetCoverAction = new UnsetCoverAction( this, m_currentAlbum ); - if( !album->hasImage() ) + if( !m_currentAlbum->hasImage() ) { displayCoverAction->setEnabled( false ); unsetCoverAction->setEnabled( false ); } QMenu *menu = new QMenu( this ); menu->addAction( displayCoverAction ); - menu->addAction( new FetchCoverAction( this, album ) ); - menu->addAction( new SetCustomCoverAction( this, album ) ); + menu->addAction( new FetchCoverAction( this, m_currentAlbum ) ); + menu->addAction( new SetCustomCoverAction( this, m_currentAlbum ) ); menu->addAction( unsetCoverAction ); menu->exec( ui->pixmap_cover->mapToGlobal(pos) ); @@ -729,13 +732,13 @@ QString curTrackName = fnt.elidedText( m_currentTrack->name().toHtmlEscaped(), Qt::ElideRight, len ); QString curTrackPretName = fnt.elidedText( m_currentTrack->prettyName().toHtmlEscaped(), Qt::ElideRight, len ); - if( m_currentTrack->album() ) - curTrackAlbName = fnt.elidedText( m_currentTrack->album()->name().toHtmlEscaped(), Qt::ElideRight, len ); + if( m_currentAlbum ) + curTrackAlbName = fnt.elidedText( m_currentAlbum->name().toHtmlEscaped(), Qt::ElideRight, len ); if( m_currentTrack->artist() ) curArtistName = fnt.elidedText( m_currentTrack->artist()->name().toHtmlEscaped(), Qt::ElideRight, len ); - if( m_currentTrack->album() && m_currentTrack->album()->name().isEmpty() ) + if( m_currentAlbum && m_currentAlbum->name().isEmpty() ) { if( !m_currentTrack->name().isEmpty() ) { @@ -747,7 +750,7 @@ else niceTitle = curTrackPretName; } - else if( m_currentTrack->album() ) + else if( m_currentAlbum ) niceTitle = i18n( "%1 by %2 on %3" , curTrackName, curArtistName, curTrackAlbName ); else if( m_currentTrack->artist() ) niceTitle = i18n( "%1 by %2" , curTrackName, curArtistName ); @@ -1217,13 +1220,13 @@ return; // -- get the album - Meta::AlbumPtr album = m_currentTrack->album(); + Meta::AlbumPtr album = m_currentAlbum; if( !m_perTrack ) { foreach( Meta::TrackPtr track, m_tracks ) { if( track->album() != album ) - album = 0; + album = nullptr; } } @@ -1280,90 +1283,78 @@ ui->pushButton_musicbrainz->setEnabled( editable ); } -void -TagDialog::saveLabels( Meta::TrackPtr track, const QStringList &labels ) -{ - if( !track ) - return; - - QHash labelMap; - foreach( const Meta::LabelPtr &label, track->labels() ) - { - labelMap.insert( label->name(), label ); - } - - // labels to remove - foreach( const QString &label, labelMap.keys().toSet() - labels.toSet() ) - { - track->removeLabel( labelMap.value( label ) ); - } - - // labels to add - foreach( const QString &label, labels.toSet() - labelMap.keys().toSet() ) - { - track->addLabel( label ); - } -} - - void TagDialog::saveTags() { setTagsToTrack(); - foreach( Meta::TrackPtr track, m_tracks ) + for( auto &track : m_tracks ) { QVariantMap data = m_storedTags[ track ]; //there is really no need to write to the file if only info m_stored in the db has changed if( !data.isEmpty() ) { debug() << "File info changed...."; - if( data.contains( Meta::Field::SCORE ) ) - track->statistics()->setScore( data.value( Meta::Field::SCORE ).toInt() ); - if( data.contains( Meta::Field::RATING ) ) - track->statistics()->setRating( data.value( Meta::Field::RATING ).toInt() ); - if( data.contains( Meta::Field::LYRICS ) ) + auto lambda = [=] () mutable { - track->setCachedLyrics( data.value( Meta::Field::LYRICS ).toString() ); - emit lyricsChanged( track->uidUrl() ); - } - - saveLabels( track, data.value( Meta::Field::LABELS ).toStringList() ); - - Meta::TrackEditorPtr ec = track->editor(); - if( !ec ) - { - debug() << "Track" << track->prettyUrl() << "does not have Meta::TrackEditor. Skipping."; - continue; - } + if( data.contains( Meta::Field::SCORE ) ) + track->statistics()->setScore( data.value( Meta::Field::SCORE ).toInt() ); + if( data.contains( Meta::Field::RATING ) ) + track->statistics()->setRating( data.value( Meta::Field::RATING ).toInt() ); + if( data.contains( Meta::Field::LYRICS ) ) + track->setCachedLyrics( data.value( Meta::Field::LYRICS ).toString() ); + + QStringList labels = data.value( Meta::Field::LABELS ).toStringList(); + QHash labelMap; + for( const auto &label : track->labels() ) + labelMap.insert( label->name(), label ); + + // labels to remove + for( const auto &label : labelMap.keys().toSet() - labels.toSet() ) + track->removeLabel( labelMap.value( label ) ); + + // labels to add + for( const auto &label : labels.toSet() - labelMap.keys().toSet() ) + track->addLabel( label ); + + Meta::TrackEditorPtr ec = track->editor(); + if( !ec ) + { + debug() << "Track" << track->prettyUrl() << "does not have Meta::TrackEditor. Skipping."; + return; + } - ec->beginUpdate(); - if( data.contains( Meta::Field::TITLE ) ) - ec->setTitle( data.value( Meta::Field::TITLE ).toString() ); - if( data.contains( Meta::Field::COMMENT ) ) - ec->setComment( data.value( Meta::Field::COMMENT ).toString() ); - if( data.contains( Meta::Field::ARTIST ) ) - ec->setArtist( data.value( Meta::Field::ARTIST ).toString() ); - if( data.contains( Meta::Field::ALBUM ) ) - ec->setAlbum( data.value( Meta::Field::ALBUM ).toString() ); - if( data.contains( Meta::Field::GENRE ) ) - ec->setGenre( data.value( Meta::Field::GENRE ).toString() ); - if( data.contains( Meta::Field::COMPOSER ) ) - ec->setComposer( data.value( Meta::Field::COMPOSER ).toString() ); - if( data.contains( Meta::Field::YEAR ) ) - ec->setYear( data.value( Meta::Field::YEAR ).toInt() ); - if( data.contains( Meta::Field::TRACKNUMBER ) ) - ec->setTrackNumber( data.value( Meta::Field::TRACKNUMBER ).toInt() ); - if( data.contains( Meta::Field::DISCNUMBER ) ) - ec->setDiscNumber( data.value( Meta::Field::DISCNUMBER ).toInt() ); - if( data.contains( Meta::Field::BPM ) ) - ec->setBpm( data.value( Meta::Field::BPM ).toDouble() ); - if( data.contains( Meta::Field::ALBUMARTIST ) ) - ec->setAlbumArtist( data.value( Meta::Field::ALBUMARTIST ).toString() ); - - ec->endUpdate(); - // note: the track should by itself emit a collectionUpdated signal if needed + ec->beginUpdate(); + + if( data.contains( Meta::Field::TITLE ) ) + ec->setTitle( data.value( Meta::Field::TITLE ).toString() ); + if( data.contains( Meta::Field::COMMENT ) ) + ec->setComment( data.value( Meta::Field::COMMENT ).toString() ); + if( data.contains( Meta::Field::ARTIST ) ) + ec->setArtist( data.value( Meta::Field::ARTIST ).toString() ); + if( data.contains( Meta::Field::ALBUM ) ) + ec->setAlbum( data.value( Meta::Field::ALBUM ).toString() ); + if( data.contains( Meta::Field::GENRE ) ) + ec->setGenre( data.value( Meta::Field::GENRE ).toString() ); + if( data.contains( Meta::Field::COMPOSER ) ) + ec->setComposer( data.value( Meta::Field::COMPOSER ).toString() ); + if( data.contains( Meta::Field::YEAR ) ) + ec->setYear( data.value( Meta::Field::YEAR ).toInt() ); + if( data.contains( Meta::Field::TRACKNUMBER ) ) + ec->setTrackNumber( data.value( Meta::Field::TRACKNUMBER ).toInt() ); + if( data.contains( Meta::Field::DISCNUMBER ) ) + ec->setDiscNumber( data.value( Meta::Field::DISCNUMBER ).toInt() ); + if( data.contains( Meta::Field::BPM ) ) + ec->setBpm( data.value( Meta::Field::BPM ).toDouble() ); + if( data.contains( Meta::Field::ALBUMARTIST ) ) + ec->setAlbumArtist( data.value( Meta::Field::ALBUMARTIST ).toString() ); + + ec->endUpdate(); + // note: the track should by itself emit a collectionUpdated signal if needed + }; + std::thread thread( lambda ); + thread.detach(); } } } diff --git a/src/dynamic/BiasSolver.h b/src/dynamic/BiasSolver.h --- a/src/dynamic/BiasSolver.h +++ b/src/dynamic/BiasSolver.h @@ -88,13 +88,13 @@ Meta::TrackList solution(); /// Politely asks the thread to give up and finish ASAP. - void requestAbort(); + virtual void requestAbort() override; /** * Returns true if the solver was successful, false if it was * aborted or encountered some other error. */ - virtual bool success() const; + virtual bool success() const override; /** * Choose whether the BiasSolver instance should delete itself after the query. @@ -119,9 +119,9 @@ static void outdateUniverse(); protected: - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; Q_SIGNALS: /** a job must implement the following signals for the progress bar diff --git a/src/lyrics/LyricsManager.h b/src/lyrics/LyricsManager.h new file mode 100644 --- /dev/null +++ b/src/lyrics/LyricsManager.h @@ -0,0 +1,73 @@ +/**************************************************************************************** + * Copyright (c) 2007 Leo Franchi * + * * + * 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 2 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 . * + ****************************************************************************************/ + +#ifndef LYRICS_MANAGER_H +#define LYRICS_MANAGER_H + +#include "amarok_export.h" +#include "core/meta/Meta.h" +#include "network/NetworkAccessManagerProxy.h" + +#include +#include +#include +#include + + +class AMAROK_EXPORT LyricsManager : public QObject +{ + Q_OBJECT + + public: + static LyricsManager* instance() + { + if( !s_self ) + s_self = new LyricsManager(); + + return s_self; + } + + /** + * Tests if the given lyrics are empty. + * + * @param lyrics The lyrics which will be tested. + * + * @return true if the given lyrics are empty, otherwise false. + */ + bool isEmpty( const QString &lyrics ) const; + + void newTrack( Meta::TrackPtr track ); + void lyricsResult( const QByteArray& lyrics, Meta::TrackPtr track ); + void lyricsLoaded( const QUrl &url, const QByteArray &data, NetworkAccessManagerProxy::Error err ); + void loadLyrics( Meta::TrackPtr track, bool overwrite = false ); + + signals: + void newLyrics( Meta::TrackPtr ); + void newSuggestions( QVariantList ); + void error( QString ); + + private: + LyricsManager(); + + void sanitizeTitle( QString &title ); + void sanitizeArtist( QString &artist ); + + static LyricsManager* s_self; + + QMap m_trackMap; +}; + +#endif diff --git a/src/lyrics/LyricsManager.cpp b/src/lyrics/LyricsManager.cpp new file mode 100644 --- /dev/null +++ b/src/lyrics/LyricsManager.cpp @@ -0,0 +1,275 @@ +/**************************************************************************************** + * Copyright (c) 2007 Leo Franchi * + * Copyright (c) 2009 Seb Ruiz * + * * + * 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 2 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 . * + ****************************************************************************************/ + +#define DEBUG_PREFIX "LyricsManager" + +#include "LyricsManager.h" + +#include "EngineController.h" +#include "core/meta/Meta.h" +#include "core/support/Debug.h" +#include "core-impl/collections/support/CollectionManager.h" + +#include +#include +#include + +#include + + +#define APIURL "http://lyrics.wikia.com/api.php?action=query&prop=revisions&rvprop=content&format=xml&titles=" + + +LyricsManager* LyricsManager::s_self = 0; + +LyricsManager::LyricsManager() +{ + s_self = this; + connect( The::engineController(), &EngineController::trackChanged, this, &LyricsManager::newTrack ); +} + +void +LyricsManager::newTrack( Meta::TrackPtr track ) +{ + loadLyrics( track ); +} + +void +LyricsManager::lyricsResult( const QByteArray& lyricsXML, Meta::TrackPtr track ) //SLOT +{ + DEBUG_BLOCK + + QXmlStreamReader xml( lyricsXML ); + while( !xml.atEnd() ) + { + xml.readNext(); + + if( xml.name() == QStringLiteral("lyric") || xml.name() == QStringLiteral( "lyrics" ) ) + { + QString lyrics( xml.readElementText() ); + if( !isEmpty( lyrics ) ) + { + // overwrite cached lyrics (as either there were no lyircs available previously OR + // the user exlicitly agreed to overwrite the lyrics) + debug() << "setting cached lyrics..."; + track->setCachedLyrics( lyrics ); // TODO: setLyricsByPath? + emit newLyrics( track ); + } + else + { + ::error() << i18n("Retrieved lyrics is empty"); + return; + } + } + else if( xml.name() == QLatin1String("suggestions") ) + { + QVariantList suggestions; + while( xml.readNextStartElement() ) + { + if( xml.name() != QLatin1String("suggestion") ) + continue; + + const QXmlStreamAttributes &a = xml.attributes(); + + QString artist = a.value( QLatin1String("artist") ).toString(); + QString title = a.value( QLatin1String("title") ).toString(); + QString url = a.value( QLatin1String("url") ).toString(); + + if( !url.isEmpty() ) + suggestions << ( QStringList() << title << artist << url ); + + xml.skipCurrentElement(); + } + + debug() << "got" << suggestions.size() << "suggestions"; + + if( !suggestions.isEmpty() ) + emit newSuggestions( suggestions ); + + return; + } + } + + if( xml.hasError() ) + { + warning() << "errors occurred during reading lyrics xml result:" << xml.errorString(); + emit error( i18n("Lyrics data could not be parsed") ); + } +} + +void LyricsManager::loadLyrics( Meta::TrackPtr track, bool overwrite ) +{ + DEBUG_BLOCK + + if( !track ) + { + debug() << "no current track"; + return; + } + + // -- get current title and artist + QString title = track->name(); + QString artist = track->artist() ? track->artist()->name() : QString(); + + sanitizeTitle( title ); + sanitizeArtist( artist ); + + if( !isEmpty( track->cachedLyrics() ) && !overwrite ) + { + debug() << "Lyrics already cached."; + return; + } + + QUrl url( APIURL + artist + ':' + title ); + m_trackMap.insert( url, track ); + NetworkAccessManagerProxy::instance()->getData( url, this, &LyricsManager::lyricsLoaded ); +} + +void LyricsManager::lyricsLoaded( const QUrl& url, const QByteArray& data, NetworkAccessManagerProxy::Error err ) +{ + DEBUG_BLOCK + + if( err.code ) + { + warning() << "A network error occurred:" << err.description; + return; + } + + Meta::TrackPtr track = m_trackMap.take( url ); + if( !track ) + { + warning() << "No track belongs to this url:" << url.url(); + return; + } + + QDomDocument document; + document.setContent( data ); + auto list = document.elementsByTagName( QStringLiteral( "rev" ) ); + if( list.isEmpty() ) + { + if( track->album() && track->album()->albumArtist() ) + { + QString albumArtist = track->album()->albumArtist()->name(); + QString artist = track->artist() ? track->artist()->name() : QString(); + QString title = track->name(); + sanitizeTitle( title ); + sanitizeArtist( artist ); + sanitizeArtist( albumArtist ); + + //Try with album artist + if( url == QUrl( APIURL + artist + ':' + title ) && albumArtist != artist ) + { + debug() << "Try again with album artist."; + + QUrl newUrl( APIURL + albumArtist + ':' + title ); + m_trackMap.insert( newUrl, track ); + NetworkAccessManagerProxy::instance()->getData( newUrl, this, &LyricsManager::lyricsLoaded ); + return; + } + } + + debug() << "No lyrics found for track:" << track->name(); + return; + } + + QString rev = list.at( 0 ).toElement().text(); + if( rev.contains( QStringLiteral( "lyrics" ) ) ) + { + int lindex = rev.indexOf( QStringLiteral( "" ) ); + int rindex = rev.indexOf( QStringLiteral( "" ) ); + lyricsResult( (rev.mid( lindex, rindex - lindex ) + "" ).toUtf8(), track ); + } + else if( rev.contains( QStringLiteral( "lyric" ) ) ) + { + int lindex = rev.indexOf( QStringLiteral( "" ) ); + int rindex = rev.indexOf( QStringLiteral( "" ) ); + lyricsResult( (rev.mid( lindex, rindex - lindex ) + "" ).toUtf8(), track ); + } + else if( rev.contains( QStringLiteral( "#REDIRECT" ) ) ) + { + debug() << "Redirect:" << data; + + int lindex = rev.indexOf( QStringLiteral( "#REDIRECT [[" ) ) + 12; + int rindex = rev.indexOf( QStringLiteral( "]]" ) ); + QStringList list = rev.mid( lindex, rindex - lindex ).split( ':' ); + if( list.size() == 2 ) + { + list[0] = list[0].replace( '&', QStringLiteral( "%26" ) ); + list[1] = list[1].replace( '&', QStringLiteral( "%26" ) ); + QUrl newUrl( APIURL + list.join( ':' ) ); + m_trackMap.insert( newUrl, track ); + NetworkAccessManagerProxy::instance()->getData( newUrl, this, &LyricsManager::lyricsLoaded ); + } + } + else + warning() << "No lyrics found in data:" << data; +} + +void LyricsManager::sanitizeTitle( QString& title ) +{ + const QString magnatunePreviewString = QLatin1String( "PREVIEW: buy it at www.magnatune.com" ); + + if( title.contains(magnatunePreviewString, Qt::CaseSensitive) ) + title = title.remove( " (" + magnatunePreviewString + ')' ); + + title = title.remove( QStringLiteral( "(Live)" ) ); + title = title.remove( QStringLiteral( "(live)" ) ); + title = title.replace( '`', QStringLiteral( "'" ) ); + title = title.replace( '&', QStringLiteral( "%26" ) ); +} + +void LyricsManager::sanitizeArtist( QString& artist ) +{ + const QString magnatunePreviewString = QLatin1String( "PREVIEW: buy it at www.magnatune.com" ); + + if( artist.contains(magnatunePreviewString, Qt::CaseSensitive) ) + artist = artist.remove( " (" + magnatunePreviewString + ')' ); + + // strip "featuring " from the artist + int strip = artist.toLower().indexOf( " ft. "); + if ( strip != -1 ) + artist = artist.mid( 0, strip ); + + strip = artist.toLower().indexOf( " feat. " ); + if ( strip != -1 ) + artist = artist.mid( 0, strip ); + + strip = artist.toLower().indexOf( " featuring " ); + if ( strip != -1 ) + artist = artist.mid( 0, strip ); + + artist = artist.replace( '`', QStringLiteral( "'" ) ); + artist = artist.replace( '&', QStringLiteral( "%26" ) ); +} + +bool LyricsManager::isEmpty( const QString &lyrics ) const +{ + QTextEdit testItem; + + // Set the text of the TextItem. + if( Qt::mightBeRichText( lyrics ) ) + testItem.setHtml( lyrics ); + else + testItem.setPlainText( lyrics ); + + // Get the plaintext content. + // We use toPlainText() to strip all Html formatting, + // so we can test if there's any text given. + QString testText = testItem.toPlainText().trimmed(); + + return testText.isEmpty(); +} diff --git a/src/musicbrainz/MusicBrainzXmlParser.h b/src/musicbrainz/MusicBrainzXmlParser.h --- a/src/musicbrainz/MusicBrainzXmlParser.h +++ b/src/musicbrainz/MusicBrainzXmlParser.h @@ -36,7 +36,7 @@ explicit MusicBrainzXmlParser( const QString &doc ); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; int type(); @@ -80,8 +80,8 @@ QVariantMap m_currentTrackInfo; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; diff --git a/src/musicbrainz/MusicDNSAudioDecoder.h b/src/musicbrainz/MusicDNSAudioDecoder.h --- a/src/musicbrainz/MusicDNSAudioDecoder.h +++ b/src/musicbrainz/MusicDNSAudioDecoder.h @@ -62,7 +62,7 @@ explicit MusicDNSAudioDecoder( const Meta::TrackList &tracks, const int sampleLength = DEFAULT_SAMPLE_LENGTH ); virtual ~MusicDNSAudioDecoder(); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; Q_SIGNALS: void trackDecoded( const Meta::TrackPtr, const QString ); @@ -82,8 +82,8 @@ int m_sampleLength; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; diff --git a/src/musicbrainz/MusicDNSXmlParser.h b/src/musicbrainz/MusicDNSXmlParser.h --- a/src/musicbrainz/MusicDNSXmlParser.h +++ b/src/musicbrainz/MusicDNSXmlParser.h @@ -27,7 +27,7 @@ Q_OBJECT public: explicit MusicDNSXmlParser(QString &doc ); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; QStringList puid(); private: @@ -52,8 +52,8 @@ void failed(ThreadWeaver::JobPointer); protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; diff --git a/src/playlist/PlaylistController.cpp b/src/playlist/PlaylistController.cpp --- a/src/playlist/PlaylistController.cpp +++ b/src/playlist/PlaylistController.cpp @@ -612,7 +612,7 @@ { /*ignore*/ } - else if( typeid( *track.data() ) == typeid( MetaFile::Track ) ) + else if( MetaFile::TrackPtr::dynamicCast( track ) ) { QUrl cuesheet = MetaCue::CueFileSupport::locateCueSheet( track->playableUrl() ); if( !cuesheet.isEmpty() ) @@ -622,7 +622,7 @@ { Meta::TrackList cueTracks = MetaCue::CueFileSupport::generateTimeCodeTracks( track, cueMap ); if( !cueTracks.isEmpty() ) - modifiedList << cueTracks; + modifiedList << cueTracks; else modifiedList << track; } diff --git a/src/playlistgenerator/ConstraintSolver.h b/src/playlistgenerator/ConstraintSolver.h --- a/src/playlistgenerator/ConstraintSolver.h +++ b/src/playlistgenerator/ConstraintSolver.h @@ -51,10 +51,8 @@ // overloaded ThreadWeaver::Job functions bool canBeExecuted(); - bool success() const; - - public Q_SLOTS: - void requestAbort(); + virtual bool success() const override; + virtual void requestAbort() override; Q_SIGNALS: void readyToRun(); @@ -71,9 +69,9 @@ void failed(ThreadWeaver::JobPointer); protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; // from ThreadWeaver::Job + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; // from ThreadWeaver::Job private Q_SLOTS: void receiveQueryMakerData( Meta::TrackList ); diff --git a/src/playlistmanager/PlaylistManager.cpp b/src/playlistmanager/PlaylistManager.cpp --- a/src/playlistmanager/PlaylistManager.cpp +++ b/src/playlistmanager/PlaylistManager.cpp @@ -234,9 +234,8 @@ void PlaylistManager::removePlaylist( Playlists::PlaylistPtr playlist, int category ) { - if( typeid( *playlist.data() ) == typeid( SyncedPlaylist ) ) + if( auto syncedPlaylist = SyncedPlaylistPtr::dynamicCast( playlist ) ) { - SyncedPlaylistPtr syncedPlaylist = SyncedPlaylistPtr::dynamicCast( playlist ); //TODO: this might be wrong if there were multiple playlists from the same provider. //remove the specific child playlist, not all from same provider. syncedPlaylist->removePlaylistsFrom( playlist->provider() ); diff --git a/src/scanner/AbstractDirectoryWatcher.h b/src/scanner/AbstractDirectoryWatcher.h --- a/src/scanner/AbstractDirectoryWatcher.h +++ b/src/scanner/AbstractDirectoryWatcher.h @@ -57,7 +57,7 @@ public: AbstractDirectoryWatcher(); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; void abort(); /** Pauses the emitting of the scan signal */ @@ -88,8 +88,8 @@ /** Adds the given directory to the list of directories for the next scan. */ void addDirToList( const QString &directory ); - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; QTimer* m_delayedScanTimer; KDirWatch *m_watcher; diff --git a/src/scanner/GenericScannerJob.h b/src/scanner/GenericScannerJob.h --- a/src/scanner/GenericScannerJob.h +++ b/src/scanner/GenericScannerJob.h @@ -77,10 +77,10 @@ ~GenericScannerJob(); /* ThreadWeaver::Job virtual methods */ - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; virtual void abort(); - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; Q_SIGNALS: void started( GenericScanManager::ScanType type ); diff --git a/src/scripting/scriptengine/AmarokLyricsScript.h b/src/scripting/scriptengine/AmarokLyricsScript.h deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokLyricsScript.h +++ /dev/null @@ -1,56 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Leo Franchi * - * Copyright (c) 2008 Peter ZHOU * - * * - * 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 2 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 . * - ****************************************************************************************/ - -#ifndef AMAROK_LYRICS_SCRIPT_H -#define AMAROK_LYRICS_SCRIPT_H - -#include "core/meta/forward_declarations.h" - -#include - -class QScriptEngine; -class QByteArray; - -namespace AmarokScript -{ - // SCRIPTDOX Amarok.Lyrics - class AmarokLyricsScript : public QObject - { - Q_OBJECT - - public: - explicit AmarokLyricsScript( QScriptEngine* scriptEngine ); - - Q_INVOKABLE void showLyrics( const QString& lyrics ) const; - - Q_INVOKABLE void showLyricsHtml( const QString& lyrics ) const; - Q_INVOKABLE void showLyricsError( const QString& error ) const; - Q_INVOKABLE void showLyricsNotFound( const QString& msg ) const; - - Q_INVOKABLE QString escape( const QString& str ); - - Q_INVOKABLE void setLyricsForTrack( const QString& trackUrl , const QString& lyrics ) const; - Q_INVOKABLE QString toUtf8( const QByteArray& lyrics, const QString& encoding = "UTF-8" ); - Q_INVOKABLE QString QStringtoUtf8( const QString& lyrics, const QString& encoding = "UTF-8" ); - Q_INVOKABLE QByteArray fromUtf8( const QString& str, const QString& encoding ); - - Q_SIGNALS: - void fetchLyrics( const QString& artist, const QString& title, const QString&, Meta::TrackPtr ); - }; -} - -#endif diff --git a/src/scripting/scriptengine/AmarokLyricsScript.cpp b/src/scripting/scriptengine/AmarokLyricsScript.cpp deleted file mode 100644 --- a/src/scripting/scriptengine/AmarokLyricsScript.cpp +++ /dev/null @@ -1,121 +0,0 @@ -/**************************************************************************************** - * Copyright (c) 2008 Leo Franchi * - * Copyright (c) 2008 Peter ZHOU * - * * - * 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 2 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 . * - ****************************************************************************************/ - -#define DEBUG_PREFIX "AmarokLyricsScript" - -#include "AmarokLyricsScript.h" - -#include "EngineController.h" -#include "scripting/scriptmanager/ScriptManager.h" -#include "context/LyricsManager.h" -#include "core/meta/Meta.h" -#include "core/support/Amarok.h" -#include "core/support/Debug.h" - -#include -#include -#include -#include - -using namespace AmarokScript; - - -AmarokLyricsScript::AmarokLyricsScript( QScriptEngine *engine ) - : QObject( engine ) -{ - QScriptValue scriptObject = engine->newQObject( this, QScriptEngine::AutoOwnership, - QScriptEngine::ExcludeSuperClassContents ); - engine->globalObject().property( "Amarok" ).setProperty( "Lyrics", scriptObject ); - connect( ScriptManager::instance(), &ScriptManager::fetchLyrics, - this, &AmarokLyricsScript::fetchLyrics ); -} - -void -AmarokLyricsScript::showLyrics( const QString &lyrics ) const -{ - DEBUG_BLOCK - Meta::TrackPtr track = The::engineController()->currentTrack(); - if( !track ) - return; - LyricsManager::self()->lyricsResult( lyrics, false ); -} - -void -AmarokLyricsScript::showLyricsHtml( const QString &lyrics ) const -{ - DEBUG_BLOCK - Meta::TrackPtr track = The::engineController()->currentTrack(); - if( !track ) - return; - LyricsManager::self()->lyricsResultHtml( lyrics, false ); -} - -void -AmarokLyricsScript::showLyricsError( const QString &error ) const -{ - DEBUG_BLOCK - LyricsManager::self()->lyricsError( error ); -} - - -void -AmarokLyricsScript::showLyricsNotFound( const QString &msg ) const -{ - DEBUG_BLOCK - LyricsManager::self()->lyricsNotFound( msg ); -} - - -QString -AmarokLyricsScript::escape( const QString &str ) -{ - return str.toHtmlEscaped(); -} - -void -AmarokLyricsScript::setLyricsForTrack( const QString &trackUrl, const QString &lyrics ) const -{ - LyricsManager::self()->setLyricsForTrack( trackUrl, lyrics ); -} - -QString -AmarokLyricsScript::toUtf8( const QByteArray &lyrics, const QString &encoding ) -{ - QTextCodec* codec = QTextCodec::codecForName( encoding.toUtf8() ); - if( !codec ) - return QString(); - return codec->toUnicode( lyrics ); -} - -QString -AmarokLyricsScript::QStringtoUtf8( const QString &lyrics, const QString &encoding ) -{ - QTextCodec* codec = QTextCodec::codecForName( encoding.toUtf8() ); - if( !codec ) - return QString(); - return codec->toUnicode( lyrics.toLatin1() ); -} - -QByteArray -AmarokLyricsScript::fromUtf8( const QString &str, const QString &encoding ) -{ - QTextCodec* codec = QTextCodec::codecForName( encoding.toUtf8() ); - if( !codec ) - return QByteArray(); - - return codec->fromUnicode( str ); -} diff --git a/src/scripting/scriptmanager/ScriptItem.cpp b/src/scripting/scriptmanager/ScriptItem.cpp --- a/src/scripting/scriptmanager/ScriptItem.cpp +++ b/src/scripting/scriptmanager/ScriptItem.cpp @@ -37,7 +37,6 @@ #include "scripting/scriptengine/AmarokEngineScript.h" #include "scripting/scriptengine/AmarokInfoScript.h" #include "scripting/scriptengine/AmarokKNotifyScript.h" -#include "scripting/scriptengine/AmarokLyricsScript.h" #include "scripting/scriptengine/AmarokNetworkScript.h" #include "scripting/scriptengine/AmarokOSDScript.h" #include "scripting/scriptengine/AmarokPlaylistScript.h" @@ -292,10 +291,6 @@ AmarokScript::QueryMakerPrototype::init( m_engine.data() ); const QString &category = m_info.category(); - if( category.contains( QLatin1String("Lyrics") ) ) - { - new AmarokScript::AmarokLyricsScript( m_engine.data() ); - } if( category.contains( QLatin1String("Scriptable Service") ) ) { new StreamItem( m_engine.data() ); diff --git a/src/scripting/scripts/CMakeLists.txt b/src/scripting/scripts/CMakeLists.txt --- a/src/scripting/scripts/CMakeLists.txt +++ b/src/scripting/scripts/CMakeLists.txt @@ -1,6 +1,5 @@ #add_subdirectory( radio_station_service ) #add_subdirectory( librivox_service ) -add_subdirectory( lyrics_lyricwiki ) #add_subdirectory( qtscript_debug ) #add_subdirectory( script_console ) diff --git a/src/scripting/scripts/lyrics_lyricwiki/CMakeLists.txt b/src/scripting/scripts/lyrics_lyricwiki/CMakeLists.txt deleted file mode 100644 --- a/src/scripting/scripts/lyrics_lyricwiki/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -install( FILES - main.js - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/lyrics_lyricwiki -) - -kcoreaddons_desktop_to_json("" script.desktop) - -install( FILES ${CMAKE_CURRENT_BINARY_DIR}/script.json - DESTINATION ${KDE_INSTALL_DATADIR}/amarok/scripts/lyrics_lyricwiki -) diff --git a/src/scripting/scripts/lyrics_lyricwiki/main.js b/src/scripting/scripts/lyrics_lyricwiki/main.js deleted file mode 100644 --- a/src/scripting/scripts/lyrics_lyricwiki/main.js +++ /dev/null @@ -1,284 +0,0 @@ -/************************************************************************** -* Amarok 2 lyrics script to fetch lyrics from lyrics.wikia.com * -* (formerly lyricwiki.org) * -* * -* Copyright * -* (C) 2008 Aaron Reichman * -* (C) 2008 Leo Franchi * -* (C) 2008 Mark Kretschmann * -* (C) 2008 Peter ZHOU * -* (C) 2009 Jakob Kummerow * -* * -* 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 2 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, write to the * -* Free Software Foundation, Inc., * -* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. * -**************************************************************************/ - -/* GLOBAL VARIABLES */ -// template for the xml object that will be populated and passed to Amarok.Lyrics.showLyrics() -XML = "{lyrics}"; -// if we change variable xml it will not reinitialized on next lyrics request, so we will get lyrics from previous song -// because of that we need temp variable -NEWXML = ""; -// maximum numbers that we can follow by #REDIRECT [[Band:Song]] -MAXREDIRECTS = 3; -// url to get lyrics using mediawiki API -APIURL = "http://lyrics.wikia.com/api.php?action=query&prop=revisions&rvprop=content&format=xml&titles="; -// urlified artist and title will be here after initialization -ARTIST = ""; -TITLE = ""; -// the error message that is displayed if no lyrics were found or there was an error while trying to fetch them -ERRORMSG = "Lyrics not found. Sorry."; - -var embedLyrics = Amarok.Script.readConfig("embedLyrics", false); - -function readEmbeddedLyrics() -{ - var track = Amarok.Engine.currentTrack(); - var embeddedLyrics = track.tags["lyrics"]; - if( embeddedLyrics != undefined && embeddedLyrics !== "" ) - { - Amarok.debug( "Using embedded lyrics for track \"" + track.title + "\"" ); - Amarok.Lyrics.showLyricsHtml( embeddedLyrics ); - return true; - } - return false; -} - -function embed( lyricsXML ) -{ - if( !embedLyrics ) - return; - - Amarok.Xml.setReaderData( lyricsXML ); - var lyrics = Amarok.Xml.readFirstElementWithName( "lyric" ); - if( lyrics !== "" ) - { - Amarok.Engine.currentTrack().changeTags( { "lyrics":lyrics }, false ); - Amarok.debug( "Writing lyrics to track." ); - Amarok.debug( lyrics ); - return; - } -} - -/* receives a Wiki page (in XML format) that contains url to lyric of the requested song - this API function can correct our tags - for example we trying to receive lyrics for Nightwish:Nightwish_-_Sleepwalker (incorrect tags) - this API functions will redirect us to Nightwish:Sleepwalker (correct tags) -*/ -function onHelpReceived( response ) -{ - try - { - if( response.length == 0 ) - Amarok.Lyrics.showLyricsError( ERRORMSG ); - else - { - Amarok.Xml.setDomObjectData(response); - var urlstr = Amarok.Xml.textOfFirstDomElementWithName( "url" ); - var capture; - if(capture = /.+\/([^?=:]+:[^?=:]+)$/.exec(urlstr)) - { - // matched url is like this one: http://lyrics.wikia.com/Nightwish:Sleepwalker - // but not like this: http://lyrics.wikia.com/index.php?title=Nightwish:Sleepwalker&action=edit - var url = APIURL + capture[1]; - // this zero will not allow to execute this function again - new Downloader( url, new Function("response", "onLyricsReceived(response, 0)") ); - } - else - { - Amarok.Lyrics.showLyricsNotFound( ERRORMSG ); - } - } - } - catch( err ) - { - Amarok.Lyrics.showLyricsError( ERRORMSG ); - Amarok.debug( "script error in function onHelpReceived: " + err ); - } -} - -/* receives a Wiki page (in XML format) using wikimedia API and extracts lyrics from it */ -function onLyricsReceived( response, redirects ) -{ - try - { - if( response.length == 0 ) - Amarok.Lyrics.showLyricsError( "Unable to contact server - no website returned" ); // TODO: this should be i18n able - else - { - Amarok.Xml.setDomObjectData(response); - - var capture; - response = Amarok.Xml.textOfFirstDomElementWithName( "rev" ); - - if(capture = /<(lyrics?>)/i.exec(response)) - { // ok, lyrics found - // lyrycs can be between or tags - // such variant can be in one response: national lyrics english lyrics - // example: http://lyrics.wikia.com/api.php?action=query&prop=revisions&titles=Flёur:Колыбельная_для_Солнца&rvprop=content&format=xml - // we can not use lazy regexp because qt script don't understand it - // so let's extract lyrics with string functions - - var lindex = response.indexOf("<" + capture[1]) + capture[1].length + 1; - var rindex = response.indexOf(" upper && words[i].charAt(upper).toUpperCase() == "I" ) { - upper++; - } - } - // if the word starts with an apostrophe or parenthesis, the next character has to be uppercase - if ( words[i].charAt(0) == "'" || words[i].charAt(0) == "(" ) { - upper++; - } - // finally, perform the capitalization - if ( upper < words[i].length ) { - words[i] = words[i].substring( 0, upper ).toUpperCase() + words[i].substring( upper ); - } else { - words[i] = words[i].toUpperCase(); - } - // now take care of more special cases - // names like "McSomething" - if ( words[i].substring( 0, 2 ) == "Mc" ) { - words[i] = "Mc" + words[i][2].toUpperCase() + words[i].substring( 3 ); - } - // URI-encode the word - words[i] = encodeURIComponent( words[i] ); - } - // join the words back together and return the result - var result = words.join( "_" ); - return result; - } catch ( err ) { - Amarok.debug ( "script error in function URLify: " + err ); - } -} - -// convert all HTML entities to their applicable characters -function entityDecode(string) -{ - try - { - var convertxml = "" + string + ""; - if(Amarok.Xml.setDomObjectData(convertxml)) - { // xml is valid - return Amarok.Xml.textOfFirstDomElementWithName( "entity" ); - } - - return string; - } - catch( err ) - { - Amarok.debug( "script error in function entityDecode: " + err ); - } -} - -// entry point -function getLyrics( artist, title, url, track ) -{ - if( readEmbeddedLyrics() ) - return; - try - { - // save artist and title for later display now - NEWXML = XML.replace( "{artist}", Amarok.Lyrics.escape( artist ) ); - NEWXML = NEWXML.replace( "{title}", Amarok.Lyrics.escape( title ) ); - - // strip "featuring " from the artist - var strip = artist.toLowerCase().indexOf( " ft. "); - if ( strip != -1 ) { - artist = artist.substring( 0, strip ); - } - strip = artist.toLowerCase().indexOf( " feat. " ); - if ( strip != -1 ) { - artist = artist.substring( 0, strip ); - } - strip = artist.toLowerCase().indexOf( " featuring " ); - if ( strip != -1 ) { - artist = artist.substring( 0, strip ); - } - - // URLify artist and title - ARTIST = artist = URLify( entityDecode(artist) ); - TITLE = title = URLify( entityDecode(title) ); - - // assemble the (encoded!) URL, build a QUrl out of it and dispatch the download request - var url = APIURL + artist + ":" + title; - Amarok.debug( "request URL: " + url.toString() ); - // there was no redirections yet - new Downloader( url, new Function("response", "onLyricsReceived(response, -1)") ); - } - catch( err ) - { - Amarok.debug( "error: " + err ); - } -} - - -Amarok.Window.addSettingsSeparator(); -Amarok.Window.addSettingsMenu( "LyricWiki" ); -Amarok.Window.addCustomAction( "LyricWiki", "EmbedLyrics", "Embed Lyrics" ); -Amarok.Window.LyricWiki.EmbedLyrics.checkable = true; -Amarok.Window.LyricWiki.EmbedLyrics.checked = embedLyrics; -Amarok.Window.LyricWiki.EmbedLyrics.toggled.connect( function( checked ) { - embedLyrics = checked; - Amarok.Script.writeConfig( "embedLyrics", embedLyrics ); - } ); - -Amarok.Lyrics.fetchLyrics.connect( getLyrics ); diff --git a/src/scripting/scripts/lyrics_lyricwiki/script.desktop b/src/scripting/scripts/lyrics_lyricwiki/script.desktop deleted file mode 100644 --- a/src/scripting/scripts/lyrics_lyricwiki/script.desktop +++ /dev/null @@ -1,79 +0,0 @@ -[Desktop Entry] -Icon=view-pim-journal -Type=script -ServiceTypes=KPluginInfo - -Name=Lyricwiki -Name[bs]=Lyricwiki -Name[ca]=Lyricwiki -Name[ca@valencia]=Lyricwiki -Name[cs]=Lyricwiki -Name[da]=Lyricwiki -Name[de]=Lyricwiki -Name[el]=Lyricwiki -Name[en_GB]=Lyricwiki -Name[es]=Lyricwiki -Name[fi]=Lyricwiki -Name[fr]=LyricWiki -Name[gl]=Lyricwiki -Name[hu]=Lyricwiki -Name[id]=Lyricwiki -Name[it]=Lyricwiki -Name[nl]=Lyricwiki -Name[pl]=Lyricwiki -Name[pt]=Lyricwiki -Name[pt_BR]=Lyricwiki -Name[ro]=Lyricwiki -Name[sk]=Lyricwiki -Name[sl]=Lyricwiki -Name[sr]=Лириквики -Name[sr@ijekavian]=Лириквики -Name[sr@ijekavianlatin]=LyricWiki -Name[sr@latin]=LyricWiki -Name[sv]=Lyricwiki -Name[tr]=Lyricwiki -Name[uk]=Lyricwiki -Name[x-test]=xxLyricwikixx -Name[zh_TW]=Lyricwiki -Comment=A script to fetch lyrics from lyricwiki.org -Comment[bs]=Skripta za dobavljanje tekstova pjesama sa lyricwiki.org -Comment[ca]=Un script per recuperar lletres des de lyricwiki.org -Comment[ca@valencia]=Un script per recuperar lletres des de lyricwiki.org -Comment[cs]=Skript pro stažení textů písní z lyricwiki.org -Comment[da]=Et script til at hente sangtekster fra lyricwiki.org -Comment[de]=Ein Skript, um Liedtexte von lyricwiki.org zu holen -Comment[el]=Σενάριο για μεταφορά στίχων από το lyricwiki.org -Comment[en_GB]=A script to fetch lyrics from lyricwiki.org -Comment[es]=Un guion para recuperar letras desde lyricwiki.org -Comment[fi]=Skripti, joka hakee laulun sanat lyricwiki.orgista -Comment[fr]=Un script pour télécharger des paroles depuis lyricwiki.org -Comment[gl]=Un script para obter letras de lyricwiki.org. -Comment[hu]=Egy parancsfájl dalszövegek letöltéséhez a lyricwiki.org oldalról -Comment[id]=Script untuk menarik lirik dari lyricwiki.org -Comment[it]=Uno script per scaricare i testi da lyricwiki.org -Comment[nl]=Een script om liedteksten op te halen uit lyricwiki.org -Comment[pl]=Skrypt do pobieranie słów z lyricwiki.org -Comment[pt]=Um programa para obter letras musicais a partir do lyricwiki.org -Comment[pt_BR]=Um script para baixar letras de músicas a partir do lyricwiki.org -Comment[ro]=Script ce obține versuri de la lyricwiki.org -Comment[sk]=Skript na stiahnutie textu z lyricwiki.org -Comment[sl]=Skript za pridobivanje besedil iz lyricwiki.org -Comment[sr]=Скрипта за добављање стихова са Лириквикија -Comment[sr@ijekavian]=Скрипта за добављање стихова са Лириквикија -Comment[sr@ijekavianlatin]=Skripta za dobavljanje stihova sa LyricWikija -Comment[sr@latin]=Skripta za dobavljanje stihova sa LyricWikija -Comment[sv]=Ett skript för att hämta sångtexter från lyricwiki.org -Comment[tr]=Lyricwiki.org şarkı sözleri getirmek için bir betik -Comment[uk]=Скрипт для отримання слів пісень з lyricwiki.org -Comment[x-test]=xxA script to fetch lyrics from lyricwiki.orgxx -Comment[zh_TW]=從 lyricwiki.org 抓取歌詞的文稿 - -X-KDE-PluginInfo-Author=Aaron Reichman -X-KDE-PluginInfo-Email=reldruh@gmail.com -X-KDE-PluginInfo-Name=LyricWiki -X-KDE-PluginInfo-Version=.3 -X-KDE-PluginInfo-Category=Lyrics -X-KDE-PluginInfo-Depends=Amarok2.0 -X-KDE-PluginInfo-License=LGPL -X-KDE-PluginInfo-BugAddress=submit@bugs.kde.org -X-KDE-PluginInfo-EnabledByDefault=true diff --git a/src/services/ServiceSqlQueryMaker.cpp b/src/services/ServiceSqlQueryMaker.cpp --- a/src/services/ServiceSqlQueryMaker.cpp +++ b/src/services/ServiceSqlQueryMaker.cpp @@ -96,10 +96,9 @@ struct ServiceSqlQueryMaker::Private { - enum QueryType { NONE, TRACK, ARTIST, ALBUM, ALBUMARTIST, GENRE, COMPOSER, YEAR, CUSTOM }; - enum {TRACKS_TABLE = 1, ALBUMS_TABLE = 2, ARTISTS_TABLE = 4, GENRE_TABLE = 8, ALBUMARTISTS_TABLE = 16 }; + enum { TRACKS_TABLE = 1, ALBUMS_TABLE = 2, ARTISTS_TABLE = 4, GENRE_TABLE = 8, ALBUMARTISTS_TABLE = 16 }; int linkedTables; - QueryType queryType; + QueryMaker::QueryType queryType; QString query; QString queryReturnValues; QString queryFrom; @@ -125,7 +124,7 @@ //d->includedBuilder = true; //d->collectionRestriction = false; - d->queryType = Private::NONE; + d->queryType = QueryMaker::None; d->linkedTables = 0; d->withoutDuplicates = false; d->maxResultSize = -1; @@ -145,7 +144,7 @@ void ServiceSqlQueryMaker::run() { - if( d->queryType == Private::NONE ) + if( d->queryType == QueryMaker::None ) return; //better error handling? if( d->worker && !d->worker->isFinished() ) { @@ -177,14 +176,14 @@ switch( type ) { case QueryMaker::Track: //make sure to keep this method in sync with handleTracks(QStringList) and the SqlTrack ctor - if( d->queryType == Private::NONE ) + if( d->queryType == QueryMaker::None ) { QString prefix = m_metaFactory->tablePrefix(); //d->queryFrom = ' ' + prefix + "_tracks"; d->withoutDuplicates = true; d->queryFrom = ' ' + prefix + "_tracks"; - d->queryType = Private::TRACK; + d->queryType = QueryMaker::Track; d->queryReturnValues = m_metaFactory->getTrackSqlRows() + ',' + m_metaFactory->getAlbumSqlRows() + ',' + m_metaFactory->getArtistSqlRows() + ',' + @@ -204,27 +203,27 @@ return this; case QueryMaker::Artist: - if( d->queryType == Private::NONE ) + if( d->queryType == QueryMaker::None ) { QString prefix = m_metaFactory->tablePrefix(); d->queryFrom = ' ' + prefix + "_tracks"; d->linkedTables |= Private::ARTISTS_TABLE; d->linkedTables |= Private::ALBUMS_TABLE; - d->queryType = Private::ARTIST; + d->queryType = QueryMaker::Artist; d->withoutDuplicates = true; d->queryReturnValues = m_metaFactory->getArtistSqlRows(); d->queryOrderBy += " GROUP BY " + prefix + "_tracks.id"; //fixes the same track being shown several times due to being in several genres } return this; case QueryMaker::AlbumArtist: - if( d->queryType == Private::NONE ) + if( d->queryType == QueryMaker::None ) { QString prefix = m_metaFactory->tablePrefix(); d->queryFrom = ' ' + prefix + "_tracks"; d->linkedTables |= Private::ALBUMARTISTS_TABLE; - d->queryType = Private::ALBUMARTIST; + d->queryType = QueryMaker::AlbumArtist; d->withoutDuplicates = true; d->queryReturnValues = QString( "albumartists.id, " ) + "albumartists.name, " + @@ -234,11 +233,11 @@ return this; case QueryMaker::Album: - if( d->queryType == Private::NONE ) + if( d->queryType == QueryMaker::None ) { QString prefix = m_metaFactory->tablePrefix(); d->queryFrom = ' ' + prefix + "_tracks"; - d->queryType = Private::ALBUM; + d->queryType = QueryMaker::Album; d->linkedTables |= Private::ALBUMS_TABLE; d->linkedTables |= Private::ARTISTS_TABLE; d->withoutDuplicates = true; @@ -252,21 +251,21 @@ case QueryMaker::Composer: /* if( d->queryType == Private::NONE ) { - d->queryType = Private::COMPOSER; + d->queryType = QueryMaker::Composer; d->withoutDuplicates = true; - d->linkedTables |= Private::COMPOSER_TAB; + d->linkedTables |= QueryMaker::Composer_TAB; d->queryReturnValues = "composer.name, composer.id"; }*/ return this; case QueryMaker::Genre: - if( d->queryType == Private::NONE ) + if( d->queryType == QueryMaker::None ) { QString prefix = m_metaFactory->tablePrefix(); d->queryFrom = ' ' + prefix + "_genre"; - d->queryType = Private::GENRE; - //d->linkedTables |= Private::ALBUMS_TABLE; - //d->linkedTables |= Private::GENRE_TABLE; + d->queryType = QueryMaker::Genre; + //d->linkedTables |= QueryMaker::Albums_TABLE; + //d->linkedTables |= QueryMaker::Genre_TABLE; d->withoutDuplicates = true; d->queryReturnValues = m_metaFactory->getGenreSqlRows(); d->queryOrderBy = " GROUP BY " + prefix +"_genre.name"; // HAVING COUNT ( " + prefix +"_genre.name ) > 10 "; @@ -365,7 +364,7 @@ d->linkedTables |= Private::ALBUMS_TABLE; d->linkedTables |= Private::ARTISTS_TABLE; - if( d->queryType == Private::GENRE ) + if( d->queryType == QueryMaker::Genre ) d->linkedTables |= Private::GENRE_TABLE; if( serviceAlbum ) { @@ -392,12 +391,12 @@ // if ( d->queryType == Private::TRACK ) { //d->queryFrom = ' ' + prefix + "_tracks"; - d->linkedTables |= Private::ALBUMS_TABLE; + d->linkedTables |= Private::ALBUMS_TABLE; //} else //d->queryFrom = ' ' + prefix + "_albums"; //if ( d->queryType == Private::ARTIST ) - //d->linkedTables |= Private::ARTISTS_TABLE; + //d->linkedTables |= Private::ARTISTS_TABLE; d->linkedTables |= Private::GENRE_TABLE; d->queryMatch += QString( " AND " + prefix + "_genre.name = '%1'" ).arg( serviceGenre->name() ); @@ -436,7 +435,7 @@ return this; } //a few hacks needed by some of the speedup code: - if ( d->queryType == Private::GENRE ) + if ( d->queryType == QueryMaker::Genre ) { QString prefix = m_metaFactory->tablePrefix(); d->queryFrom = ' ' + prefix + "_tracks"; @@ -595,35 +594,36 @@ /*case Private::CUSTOM: emit newResultReady( result ); break;*/ - case Private::TRACK: + case QueryMaker::Track: handleTracks( result ); break; - case Private::ARTIST: - case Private::ALBUMARTIST: + case QueryMaker::Artist: + case QueryMaker::AlbumArtist: handleArtists( result ); break; - case Private::ALBUM: + case QueryMaker::Album: handleAlbums( result ); break; - case Private::GENRE: + case QueryMaker::Genre: handleGenres( result ); break; - /* case Private::COMPOSER: + /* case QueryMaker::Composer: handleComposers( result ); break; case Private::YEAR: handleYears( result ); break;*/ - case Private::NONE: + case QueryMaker::None: debug() << "Warning: queryResult with queryType == NONE"; default: break; } } else { - switch( d->queryType ) { + switch( d->queryType ) + { case QueryMaker::Custom: emit newResultReady( QStringList() ); break; @@ -648,9 +648,10 @@ case QueryMaker::Year: emit newYearsReady( Meta::YearList() ); break; - - case QueryMaker::None: - debug() << "Warning: queryResult with queryType == NONE"; + case QueryMaker::None: + debug() << "Warning: queryResult with queryType == NONE"; + default: + break; } } diff --git a/src/services/ampache/AmpacheSettings.h b/src/services/ampache/AmpacheSettings.h --- a/src/services/ampache/AmpacheSettings.h +++ b/src/services/ampache/AmpacheSettings.h @@ -36,9 +36,9 @@ virtual ~AmpacheSettings(); - virtual void save() Q_DECL_OVERRIDE; - virtual void load() Q_DECL_OVERRIDE; - virtual void defaults() Q_DECL_OVERRIDE; + virtual void save() override; + virtual void load() override; + virtual void defaults() override; private: diff --git a/src/services/gpodder/GpodderServiceSettings.h b/src/services/gpodder/GpodderServiceSettings.h --- a/src/services/gpodder/GpodderServiceSettings.h +++ b/src/services/gpodder/GpodderServiceSettings.h @@ -38,9 +38,9 @@ virtual ~GpodderServiceSettings(); - void save() Q_DECL_OVERRIDE; - void load() Q_DECL_OVERRIDE; - void defaults() Q_DECL_OVERRIDE; + void save() override; + void load() override; + void defaults() override; private Q_SLOTS: void testLogin(); diff --git a/src/services/jamendo/JamendoXmlParser.h b/src/services/jamendo/JamendoXmlParser.h --- a/src/services/jamendo/JamendoXmlParser.h +++ b/src/services/jamendo/JamendoXmlParser.h @@ -48,7 +48,7 @@ * The function that starts the actual work. Inherited from ThreadWeaver::Job * Note the work is performed in a separate thread */ - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; /** * Destructor @@ -121,8 +121,8 @@ bool m_aborted; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; #endif diff --git a/src/services/magnatune/MagnatuneDatabaseWorker.h b/src/services/magnatune/MagnatuneDatabaseWorker.h --- a/src/services/magnatune/MagnatuneDatabaseWorker.h +++ b/src/services/magnatune/MagnatuneDatabaseWorker.h @@ -37,7 +37,7 @@ ~MagnatuneDatabaseWorker(); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; void fetchMoodMap(); void fetchTrackswithMood( const QString &mood, int noOfTracks, ServiceSqlRegistry * registry ); @@ -80,8 +80,8 @@ ServiceSqlRegistry * m_registry; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; #endif diff --git a/src/services/magnatune/MagnatuneInfoParser.cpp b/src/services/magnatune/MagnatuneInfoParser.cpp --- a/src/services/magnatune/MagnatuneInfoParser.cpp +++ b/src/services/magnatune/MagnatuneInfoParser.cpp @@ -245,7 +245,7 @@ void MagnatuneInfoParser::userPageDownloadComplete( KJob * downLoadJob ) { - if ( !downLoadJob->error() == 0 ) + if ( downLoadJob->error() ) { //TODO: error handling here return ; diff --git a/src/services/magnatune/MagnatuneStore.cpp b/src/services/magnatune/MagnatuneStore.cpp --- a/src/services/magnatune/MagnatuneStore.cpp +++ b/src/services/magnatune/MagnatuneStore.cpp @@ -440,24 +440,23 @@ //be an album or a track Meta::DataPtr dataPtr = selectedItem->data(); - if ( typeid( * dataPtr.data() ) == typeid( Meta::MagnatuneTrack ) ) { - + if ( auto track = AmarokSharedPointer::dynamicCast( dataPtr ) ) + { debug() << "is right type (track)"; - Meta::MagnatuneTrack * track = static_cast ( dataPtr.data() ); m_currentAlbum = static_cast ( track->album().data() ); m_downloadAlbumButton->setEnabled( true ); - - } else if ( typeid( * dataPtr.data() ) == typeid( Meta::MagnatuneAlbum ) ) { - - m_currentAlbum = static_cast ( dataPtr.data() ); + } + else if ( auto album = AmarokSharedPointer::dynamicCast( dataPtr ) ) + { + m_currentAlbum = album.data(); debug() << "is right type (album) named " << m_currentAlbum->name(); m_downloadAlbumButton->setEnabled( true ); - } else { - + } + else + { debug() << "is wrong type"; m_downloadAlbumButton->setEnabled( false ); - } } diff --git a/src/services/magnatune/MagnatuneXmlParser.h b/src/services/magnatune/MagnatuneXmlParser.h --- a/src/services/magnatune/MagnatuneXmlParser.h +++ b/src/services/magnatune/MagnatuneXmlParser.h @@ -50,7 +50,7 @@ * The function that starts the actual work. Inherited from ThreadWeaver::Job * Note the work is performed in a separate thread */ - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; /** * Destructor @@ -139,8 +139,8 @@ MagnatuneDatabaseHandler * m_dbHandler; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; #endif diff --git a/src/services/mp3tunes/Mp3tunesWorkers.h b/src/services/mp3tunes/Mp3tunesWorkers.h --- a/src/services/mp3tunes/Mp3tunesWorkers.h +++ b/src/services/mp3tunes/Mp3tunesWorkers.h @@ -34,7 +34,7 @@ Mp3tunesLoginWorker( Mp3tunesLocker* locker, const QString &username, const QString &password ); ~Mp3tunesLoginWorker(); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ @@ -56,8 +56,8 @@ QString m_username; QString m_password; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; /** @@ -70,7 +70,7 @@ explicit Mp3tunesArtistFetcher( Mp3tunesLocker * locker ); ~Mp3tunesArtistFetcher(); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ @@ -90,8 +90,8 @@ Mp3tunesLocker* m_locker; QList m_artists; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; /** @@ -104,7 +104,7 @@ Mp3tunesAlbumWithArtistIdFetcher( Mp3tunesLocker * locker, int artistId ); ~Mp3tunesAlbumWithArtistIdFetcher(); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ @@ -125,8 +125,8 @@ Mp3tunesLocker* m_locker; QList m_albums; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; /** @@ -139,7 +139,7 @@ Mp3tunesTrackWithAlbumIdFetcher( Mp3tunesLocker * locker, int albumId ); ~Mp3tunesTrackWithAlbumIdFetcher(); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ @@ -160,8 +160,8 @@ Mp3tunesLocker* m_locker; QList m_tracks; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; /** @@ -174,7 +174,7 @@ Mp3tunesTrackWithArtistIdFetcher( Mp3tunesLocker * locker, int artistId ); ~Mp3tunesTrackWithArtistIdFetcher(); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ @@ -194,8 +194,8 @@ Mp3tunesLocker* m_locker; QList m_tracks; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; @@ -209,7 +209,7 @@ Mp3tunesSearchMonkey( Mp3tunesLocker * locker, QString query, int searchFor ); ~Mp3tunesSearchMonkey(); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ @@ -233,8 +233,8 @@ Mp3tunesLocker* m_locker; Mp3tunesSearchResult m_result; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; /** @@ -247,7 +247,7 @@ Mp3tunesSimpleUploader( Mp3tunesLocker * locker, QStringList tracklist ); ~Mp3tunesSimpleUploader(); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ @@ -269,8 +269,8 @@ Mp3tunesLocker* m_locker; QStringList m_tracklist; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; /** @@ -283,7 +283,7 @@ Mp3tunesTrackFromFileKeyFetcher( Mp3tunesLocker * locker, QString filekey ); ~Mp3tunesTrackFromFileKeyFetcher(); - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; Q_SIGNALS: /** This signal is emitted when this job is being processed by a thread. */ @@ -305,8 +305,8 @@ QString m_filekey; protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; }; #endif diff --git a/src/statsyncing/jobs/MatchTracksJob.h b/src/statsyncing/jobs/MatchTracksJob.h --- a/src/statsyncing/jobs/MatchTracksJob.h +++ b/src/statsyncing/jobs/MatchTracksJob.h @@ -38,7 +38,7 @@ public: explicit MatchTracksJob( const ProviderPtrList &providers, QObject *parent = 0 ); - virtual bool success() const; + virtual bool success() const override; /** * Binary OR of MetaValues.h Meta::val* flags that are used to compare tracks @@ -90,9 +90,9 @@ void failed(ThreadWeaver::JobPointer); protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; private: /** diff --git a/src/statsyncing/jobs/SynchronizeTracksJob.h b/src/statsyncing/jobs/SynchronizeTracksJob.h --- a/src/statsyncing/jobs/SynchronizeTracksJob.h +++ b/src/statsyncing/jobs/SynchronizeTracksJob.h @@ -92,9 +92,9 @@ void failed(ThreadWeaver::JobPointer); protected: - void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) Q_DECL_OVERRIDE; - void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) Q_DECL_OVERRIDE; + void defaultBegin(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void defaultEnd(const ThreadWeaver::JobPointer& job, ThreadWeaver::Thread *thread) override; + void run(ThreadWeaver::JobPointer self = QSharedPointer(), ThreadWeaver::Thread *thread = 0) override; private Q_SLOTS: void slotTrackScrobbled( const ScrobblingServicePtr &service, const Meta::TrackPtr &track ); diff --git a/src/widgets/BoxWidget.h b/src/widgets/BoxWidget.h --- a/src/widgets/BoxWidget.h +++ b/src/widgets/BoxWidget.h @@ -45,7 +45,7 @@ QBoxLayout* layout() const; protected: - virtual void childEvent(QChildEvent* event) Q_DECL_OVERRIDE; + virtual void childEvent(QChildEvent* event) override; }; #endif // BOXWIDGET_H diff --git a/src/widgets/PrettyTreeRoles.h b/src/widgets/PrettyTreeRoles.h --- a/src/widgets/PrettyTreeRoles.h +++ b/src/widgets/PrettyTreeRoles.h @@ -41,7 +41,9 @@ DecoratorRole = Qt::UserRole + 58, /** True if the item has a cover that should be displayed */ - HasCoverRole = Qt::UserRole + 59 + HasCoverRole = Qt::UserRole + 59, + + YearRole = Qt::UserRole + 60 }; }