2018-02-27 18:06:05 +01:00
/*
* Strawberry Music Player
* This file was part of Clementine .
* Copyright 2010 , David Sansome < me @ davidsansome . com >
2023-05-14 11:34:55 +02:00
* Copyright 2019 - 2023 , Jonas Kvinge < jonas @ jkvinge . net >
2018-02-27 18:06:05 +01:00
*
* Strawberry is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* Strawberry 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 Strawberry . If not , see < http : //www.gnu.org/licenses/>.
2018-08-09 18:39:44 +02:00
*
2018-02-27 18:06:05 +01:00
*/
# include "config.h"
2018-05-01 00:41:33 +02:00
# include <QtGlobal>
2019-07-08 22:10:43 +02:00
# include <QGuiApplication>
2021-02-26 21:03:51 +01:00
# include <QtConcurrentRun>
# include <QFuture>
# include <QFutureWatcher>
2019-07-08 22:10:43 +02:00
# include <QScreen>
2018-05-01 00:41:33 +02:00
# include <QWidget>
2018-02-27 18:06:05 +01:00
# include <QDialog>
2018-05-01 00:41:33 +02:00
# include <QDir>
2020-02-09 02:29:35 +01:00
# include <QFile>
2018-05-01 00:41:33 +02:00
# include <QFileInfo>
2018-02-27 18:06:05 +01:00
# include <QMimeData>
2020-02-09 02:29:35 +01:00
# include <QSet>
# include <QList>
2018-05-01 00:41:33 +02:00
# include <QVariant>
# include <QString>
2020-07-18 04:05:07 +02:00
# include <QRegularExpression>
2018-05-01 00:41:33 +02:00
# include <QUrl>
# include <QImage>
# include <QImageWriter>
# include <QPixmap>
# include <QIcon>
# include <QRect>
# include <QFileDialog>
# include <QLabel>
2020-02-09 02:29:35 +01:00
# include <QAction>
2021-02-26 21:03:51 +01:00
# include <QActionGroup>
# include <QMenu>
2020-02-09 02:29:35 +01:00
# include <QSettings>
2018-05-01 00:41:33 +02:00
# include <QtEvents>
2018-02-27 18:06:05 +01:00
2023-03-18 20:03:07 +01:00
# include "utilities/filenameconstants.h"
2022-12-28 03:12:00 +01:00
# include "utilities/strutils.h"
# include "utilities/mimeutils.h"
2023-03-18 20:03:07 +01:00
# include "utilities/coveroptions.h"
# include "utilities/coverutils.h"
2023-04-17 21:12:12 +02:00
# include "utilities/screenutils.h"
2021-02-26 21:03:51 +01:00
# include "core/application.h"
2018-05-01 00:41:33 +02:00
# include "core/song.h"
2018-02-27 18:06:05 +01:00
# include "core/iconloader.h"
2023-05-14 11:34:55 +02:00
# include "core/tagreaderclient.h"
2018-02-27 18:06:05 +01:00
2023-01-08 15:40:54 +01:00
# include "collection/collectionfilteroptions.h"
2018-05-01 00:41:33 +02:00
# include "collection/collectionbackend.h"
2023-05-14 11:34:55 +02:00
# include "settings/coverssettingspage.h"
2019-07-07 21:14:24 +02:00
# include "internet/internetservices.h"
# include "internet/internetservice.h"
2018-05-01 00:41:33 +02:00
# include "albumcoverchoicecontroller.h"
# include "albumcoverfetcher.h"
# include "albumcoverloader.h"
# include "albumcoversearcher.h"
2021-02-26 21:03:51 +01:00
# include "albumcoverimageresult.h"
2018-05-01 00:41:33 +02:00
# include "coverfromurldialog.h"
2019-07-07 21:14:24 +02:00
# include "currentalbumcoverloader.h"
2018-02-27 18:06:05 +01:00
const char * AlbumCoverChoiceController : : kLoadImageFileFilter = QT_TR_NOOP ( " Images (*.png *.jpg *.jpeg *.bmp *.gif *.xpm *.pbm *.pgm *.ppm *.xbm) " ) ;
const char * AlbumCoverChoiceController : : kSaveImageFileFilter = QT_TR_NOOP ( " Images (*.png *.jpg *.jpeg *.bmp *.xpm *.pbm *.ppm *.xbm) " ) ;
const char * AlbumCoverChoiceController : : kAllFilesFilter = QT_TR_NOOP ( " All files (*) " ) ;
QSet < QString > * AlbumCoverChoiceController : : sImageExtensions = nullptr ;
2021-07-11 07:40:57 +02:00
AlbumCoverChoiceController : : AlbumCoverChoiceController ( QWidget * parent )
: QWidget ( parent ) ,
app_ ( nullptr ) ,
cover_searcher_ ( nullptr ) ,
cover_fetcher_ ( nullptr ) ,
save_file_dialog_ ( nullptr ) ,
cover_from_url_dialog_ ( nullptr ) ,
cover_from_file_ ( nullptr ) ,
cover_to_file_ ( nullptr ) ,
cover_from_url_ ( nullptr ) ,
search_for_cover_ ( nullptr ) ,
separator1_ ( nullptr ) ,
unset_cover_ ( nullptr ) ,
delete_cover_ ( nullptr ) ,
clear_cover_ ( nullptr ) ,
separator2_ ( nullptr ) ,
show_cover_ ( nullptr ) ,
search_cover_auto_ ( nullptr ) ,
save_embedded_cover_override_ ( false ) {
2018-02-27 18:06:05 +01:00
2024-04-09 23:20:26 +02:00
cover_from_file_ = new QAction ( IconLoader : : Load ( QStringLiteral ( " document-open " ) ) , tr ( " Load cover from disk... " ) , this ) ;
cover_to_file_ = new QAction ( IconLoader : : Load ( QStringLiteral ( " document-save " ) ) , tr ( " Save cover to disk... " ) , this ) ;
cover_from_url_ = new QAction ( IconLoader : : Load ( QStringLiteral ( " download " ) ) , tr ( " Load cover from URL... " ) , this ) ;
search_for_cover_ = new QAction ( IconLoader : : Load ( QStringLiteral ( " search " ) ) , tr ( " Search for album covers... " ) , this ) ;
unset_cover_ = new QAction ( IconLoader : : Load ( QStringLiteral ( " list-remove " ) ) , tr ( " Unset cover " ) , this ) ;
delete_cover_ = new QAction ( IconLoader : : Load ( QStringLiteral ( " list-remove " ) ) , tr ( " Delete cover " ) , this ) ;
clear_cover_ = new QAction ( IconLoader : : Load ( QStringLiteral ( " list-remove " ) ) , tr ( " Clear cover " ) , this ) ;
2021-02-26 21:03:51 +01:00
separator1_ = new QAction ( this ) ;
separator1_ - > setSeparator ( true ) ;
2024-04-09 23:20:26 +02:00
show_cover_ = new QAction ( IconLoader : : Load ( QStringLiteral ( " zoom-in " ) ) , tr ( " Show fullsize... " ) , this ) ;
2018-02-27 18:06:05 +01:00
2018-08-29 21:42:24 +02:00
search_cover_auto_ = new QAction ( tr ( " Search automatically " ) , this ) ;
2018-02-27 18:06:05 +01:00
search_cover_auto_ - > setCheckable ( true ) ;
search_cover_auto_ - > setChecked ( false ) ;
2021-02-26 21:03:51 +01:00
separator2_ = new QAction ( this ) ;
separator2_ - > setSeparator ( true ) ;
2018-02-27 18:06:05 +01:00
2019-03-12 00:01:52 +01:00
ReloadSettings ( ) ;
2018-02-27 18:06:05 +01:00
}
2021-06-21 15:38:58 +02:00
AlbumCoverChoiceController : : ~ AlbumCoverChoiceController ( ) = default ;
2018-02-27 18:06:05 +01:00
2019-07-07 21:14:24 +02:00
void AlbumCoverChoiceController : : Init ( Application * app ) {
app_ = app ;
2023-04-21 20:20:53 +02:00
cover_fetcher_ = new AlbumCoverFetcher ( app_ - > cover_providers ( ) , app - > network ( ) , this ) ;
2019-07-07 21:14:24 +02:00
cover_searcher_ = new AlbumCoverSearcher ( QIcon ( " :/pictures/cdcase.png " ) , app , this ) ;
cover_searcher_ - > Init ( cover_fetcher_ ) ;
2021-01-26 16:48:04 +01:00
QObject : : connect ( cover_fetcher_ , & AlbumCoverFetcher : : AlbumCoverFetched , this , & AlbumCoverChoiceController : : AlbumCoverFetched ) ;
2019-07-07 21:14:24 +02:00
}
2019-03-11 23:07:11 +01:00
void AlbumCoverChoiceController : : ReloadSettings ( ) {
QSettings s ;
2023-05-14 11:34:55 +02:00
s . beginGroup ( CoversSettingsPage : : kSettingsGroup ) ;
cover_options_ . cover_type = static_cast < CoverOptions : : CoverType > ( s . value ( CoversSettingsPage : : kSaveType , static_cast < int > ( CoverOptions : : CoverType : : Cache ) ) . toInt ( ) ) ;
cover_options_ . cover_filename = static_cast < CoverOptions : : CoverFilename > ( s . value ( CoversSettingsPage : : kSaveFilename , static_cast < int > ( CoverOptions : : CoverFilename : : Pattern ) ) . toInt ( ) ) ;
cover_options_ . cover_pattern = s . value ( CoversSettingsPage : : kSavePattern , " %albumartist-%album " ) . toString ( ) ;
cover_options_ . cover_overwrite = s . value ( CoversSettingsPage : : kSaveOverwrite , false ) . toBool ( ) ;
cover_options_ . cover_lowercase = s . value ( CoversSettingsPage : : kSaveLowercase , false ) . toBool ( ) ;
cover_options_ . cover_replace_spaces = s . value ( CoversSettingsPage : : kSaveReplaceSpaces , false ) . toBool ( ) ;
2019-03-11 23:07:11 +01:00
s . endGroup ( ) ;
2023-05-14 11:34:55 +02:00
cover_types_ = AlbumCoverLoaderOptions : : LoadTypes ( ) ;
2019-03-11 23:07:11 +01:00
}
2018-02-27 18:06:05 +01:00
QList < QAction * > AlbumCoverChoiceController : : GetAllActions ( ) {
2021-02-26 21:03:51 +01:00
return QList < QAction * > ( ) < < show_cover_
< < cover_to_file_
< < separator1_
< < cover_from_file_
< < cover_from_url_
< < search_for_cover_
< < separator2_
< < unset_cover_
< < clear_cover_
< < delete_cover_ ;
2018-02-27 18:06:05 +01:00
}
2023-04-09 22:26:17 +02:00
AlbumCoverImageResult AlbumCoverChoiceController : : LoadImageFromFile ( Song * song ) {
2018-04-06 22:13:11 +02:00
2023-05-14 11:34:55 +02:00
if ( ! song - > url ( ) . isValid ( ) | | ! song - > url ( ) . isLocalFile ( ) ) {
return AlbumCoverImageResult ( ) ;
}
2018-02-27 18:06:05 +01:00
2021-02-26 21:03:51 +01:00
QString cover_file = QFileDialog : : getOpenFileName ( this , tr ( " Load cover from disk " ) , GetInitialPathForFileDialog ( * song , QString ( ) ) , tr ( kLoadImageFileFilter ) + " ;; " + tr ( kAllFilesFilter ) ) ;
2023-04-09 22:26:17 +02:00
if ( cover_file . isEmpty ( ) ) return AlbumCoverImageResult ( ) ;
2018-02-27 18:06:05 +01:00
2021-02-26 21:03:51 +01:00
QFile file ( cover_file ) ;
2023-05-14 11:34:55 +02:00
if ( ! file . open ( QIODevice : : ReadOnly ) ) {
2021-08-09 23:32:26 +02:00
qLog ( Error ) < < " Failed to open cover file " < < cover_file < < " for reading: " < < file . errorString ( ) ;
2021-09-19 19:31:34 +02:00
emit Error ( tr ( " Failed to open cover file %1 for reading: %2 " ) . arg ( cover_file , file . errorString ( ) ) ) ;
2023-05-14 11:34:55 +02:00
return AlbumCoverImageResult ( ) ;
}
2023-07-02 00:29:19 +02:00
AlbumCoverImageResult result ;
2023-05-14 11:34:55 +02:00
result . image_data = file . readAll ( ) ;
file . close ( ) ;
if ( result . image_data . isEmpty ( ) ) {
qLog ( Error ) < < " Cover file " < < cover_file < < " is empty. " ;
emit Error ( tr ( " Cover file %1 is empty. " ) . arg ( cover_file ) ) ;
return AlbumCoverImageResult ( ) ;
}
if ( result . image . loadFromData ( result . image_data ) ) {
result . cover_url = QUrl : : fromLocalFile ( cover_file ) ;
result . mime_type = Utilities : : MimeTypeFromData ( result . image_data ) ;
2021-08-09 23:32:26 +02:00
}
2021-02-26 21:03:51 +01:00
return result ;
}
QUrl AlbumCoverChoiceController : : LoadCoverFromFile ( Song * song ) {
2023-05-14 11:34:55 +02:00
if ( ! song - > url ( ) . isValid ( ) | | ! song - > url ( ) . isLocalFile ( ) | | song - > effective_albumartist ( ) . isEmpty ( ) | | song - > album ( ) . isEmpty ( ) ) return QUrl ( ) ;
2021-02-26 21:03:51 +01:00
QString cover_file = QFileDialog : : getOpenFileName ( this , tr ( " Load cover from disk " ) , GetInitialPathForFileDialog ( * song , QString ( ) ) , tr ( kLoadImageFileFilter ) + " ;; " + tr ( kAllFilesFilter ) ) ;
2023-05-14 11:34:55 +02:00
if ( cover_file . isEmpty ( ) | | QImage ( cover_file ) . isNull ( ) ) return QUrl ( ) ;
2021-02-26 21:03:51 +01:00
2022-03-22 21:09:05 +01:00
switch ( get_save_album_cover_type ( ) ) {
2023-03-18 20:03:07 +01:00
case CoverOptions : : CoverType : : Embedded :
2021-02-26 21:03:51 +01:00
if ( song - > save_embedded_cover_supported ( ) ) {
2023-05-14 11:34:55 +02:00
SaveCoverEmbeddedToCollectionSongs ( * song , cover_file ) ;
return QUrl ( ) ;
2021-02-26 21:03:51 +01:00
}
2022-07-26 20:37:06 +02:00
[[fallthrough]] ;
2023-03-18 20:03:07 +01:00
case CoverOptions : : CoverType : : Cache :
case CoverOptions : : CoverType : : Album : {
2023-05-14 11:34:55 +02:00
const QUrl cover_url = QUrl : : fromLocalFile ( cover_file ) ;
2021-02-26 21:03:51 +01:00
SaveArtManualToSong ( song , cover_url ) ;
return cover_url ;
}
2018-02-27 18:06:05 +01:00
}
2021-02-26 21:03:51 +01:00
return QUrl ( ) ;
2018-02-27 18:06:05 +01:00
}
2023-04-09 22:26:17 +02:00
void AlbumCoverChoiceController : : SaveCoverToFileManual ( const Song & song , const AlbumCoverImageResult & result ) {
2018-02-27 18:06:05 +01:00
2024-04-09 23:20:26 +02:00
QString initial_file_name = QStringLiteral ( " / " ) ;
2019-03-11 23:07:11 +01:00
if ( ! song . effective_albumartist ( ) . isEmpty ( ) ) {
initial_file_name = initial_file_name + song . effective_albumartist ( ) ;
}
initial_file_name = initial_file_name + " - " + ( song . effective_album ( ) . isEmpty ( ) ? tr ( " unknown " ) : song . effective_album ( ) ) + " .jpg " ;
initial_file_name = initial_file_name . toLower ( ) ;
2024-04-09 23:20:26 +02:00
initial_file_name . replace ( QRegularExpression ( QStringLiteral ( " \\ s " ) ) , QStringLiteral ( " - " ) ) ;
2023-03-18 20:03:07 +01:00
initial_file_name . remove ( QRegularExpression ( QString ( kInvalidFatCharactersRegex ) , QRegularExpression : : CaseInsensitiveOption ) ) ;
2018-02-27 18:06:05 +01:00
QString save_filename = QFileDialog : : getSaveFileName ( this , tr ( " Save album cover " ) , GetInitialPathForFileDialog ( song , initial_file_name ) , tr ( kSaveImageFileFilter ) + " ;; " + tr ( kAllFilesFilter ) ) ;
2021-02-26 21:03:51 +01:00
if ( save_filename . isEmpty ( ) ) return ;
2018-02-27 18:06:05 +01:00
2021-02-26 21:03:51 +01:00
QFileInfo fileinfo ( save_filename ) ;
if ( fileinfo . suffix ( ) . isEmpty ( ) ) {
2018-02-27 18:06:05 +01:00
save_filename . append ( " .jpg " ) ;
2021-02-26 21:03:51 +01:00
fileinfo . setFile ( save_filename ) ;
2018-02-27 18:06:05 +01:00
}
2021-03-07 00:53:33 +01:00
if ( ! QImageWriter : : supportedImageFormats ( ) . contains ( fileinfo . completeSuffix ( ) . toUtf8 ( ) . toLower ( ) ) ) {
2021-02-26 21:03:51 +01:00
save_filename = Utilities : : PathWithoutFilenameExtension ( save_filename ) + " .jpg " ;
fileinfo . setFile ( save_filename ) ;
}
2024-04-09 23:20:26 +02:00
if ( result . is_jpeg ( ) & & fileinfo . completeSuffix ( ) . compare ( QLatin1String ( " jpg " ) , Qt : : CaseInsensitive ) = = 0 ) {
2021-02-26 21:03:51 +01:00
QFile file ( save_filename ) ;
2023-05-14 11:34:55 +02:00
if ( ! file . open ( QIODevice : : WriteOnly ) ) {
2021-08-09 23:32:26 +02:00
qLog ( Error ) < < " Failed to open cover file " < < save_filename < < " for writing: " < < file . errorString ( ) ;
2021-09-19 19:31:34 +02:00
emit Error ( tr ( " Failed to open cover file %1 for writing: %2 " ) . arg ( save_filename , file . errorString ( ) ) ) ;
2023-05-14 11:34:55 +02:00
file . close ( ) ;
return ;
}
if ( file . write ( result . image_data ) < = 0 ) {
qLog ( Error ) < < " Failed writing cover to file " < < save_filename < < file . errorString ( ) ;
emit Error ( tr ( " Failed writing cover to file %1: %2 " ) . arg ( save_filename , file . errorString ( ) ) ) ;
file . close ( ) ;
return ;
2021-08-09 23:32:26 +02:00
}
2023-05-14 11:34:55 +02:00
file . close ( ) ;
2021-02-26 21:03:51 +01:00
}
else {
2023-04-09 22:26:17 +02:00
if ( ! result . image . save ( save_filename ) ) {
2021-09-19 19:31:34 +02:00
qLog ( Error ) < < " Failed writing cover to file " < < save_filename ;
emit Error ( tr ( " Failed writing cover to file %1. " ) . arg ( save_filename ) ) ;
}
2021-02-26 21:03:51 +01:00
}
2018-02-27 18:06:05 +01:00
}
QString AlbumCoverChoiceController : : GetInitialPathForFileDialog ( const Song & song , const QString & filename ) {
2018-10-02 00:38:52 +02:00
2018-05-01 00:41:33 +02:00
// Art automatic is first to show user which cover the album may be using now;
// The song is using it if there's no manual path but we cannot use manual path here because it can contain cached paths
2023-05-14 11:34:55 +02:00
if ( song . art_automatic_is_valid ( ) ) {
return song . art_automatic ( ) . toLocalFile ( ) ;
2018-02-27 18:06:05 +01:00
}
2023-05-14 11:34:55 +02:00
// If no automatic art, start in the song's folder
if ( ! song . url ( ) . isEmpty ( ) & & song . url ( ) . isValid ( ) & & song . url ( ) . isLocalFile ( ) & & song . url ( ) . toLocalFile ( ) . contains ( ' / ' ) ) {
2018-02-27 18:06:05 +01:00
return song . url ( ) . toLocalFile ( ) . section ( ' / ' , 0 , - 2 ) + filename ;
}
2019-07-07 21:14:24 +02:00
return QDir : : home ( ) . absolutePath ( ) + filename ;
2018-02-27 18:06:05 +01:00
}
2023-05-14 11:34:55 +02:00
void AlbumCoverChoiceController : : LoadCoverFromURL ( Song * song ) {
2018-10-02 00:38:52 +02:00
2023-05-14 11:34:55 +02:00
if ( ! song - > url ( ) . isValid ( ) | | ! song - > url ( ) . isLocalFile ( ) | | song - > effective_albumartist ( ) . isEmpty ( ) | | song - > album ( ) . isEmpty ( ) ) return ;
2018-02-27 18:06:05 +01:00
2023-04-09 22:26:17 +02:00
const AlbumCoverImageResult result = LoadImageFromURL ( ) ;
2023-05-14 11:34:55 +02:00
if ( ! result . image . isNull ( ) ) {
SaveCoverAutomatic ( song , result ) ;
2018-02-27 18:06:05 +01:00
}
2018-10-02 00:38:52 +02:00
2018-02-27 18:06:05 +01:00
}
2023-04-09 22:26:17 +02:00
AlbumCoverImageResult AlbumCoverChoiceController : : LoadImageFromURL ( ) {
2021-02-26 21:03:51 +01:00
2023-04-21 20:20:53 +02:00
if ( ! cover_from_url_dialog_ ) { cover_from_url_dialog_ = new CoverFromURLDialog ( app_ - > network ( ) , this ) ; }
2021-02-26 21:03:51 +01:00
return cover_from_url_dialog_ - > Exec ( ) ;
}
2023-05-14 11:34:55 +02:00
void AlbumCoverChoiceController : : SearchForCover ( Song * song ) {
2018-03-04 14:10:50 +01:00
2023-05-14 11:34:55 +02:00
if ( ! song - > url ( ) . isValid ( ) | | ! song - > url ( ) . isLocalFile ( ) | | song - > effective_albumartist ( ) . isEmpty ( ) | | song - > album ( ) . isEmpty ( ) ) return ;
2018-02-27 18:06:05 +01:00
// Get something sensible to stick in the search box
2023-04-09 22:26:17 +02:00
AlbumCoverImageResult result = SearchForImage ( song ) ;
if ( result . is_valid ( ) ) {
2023-05-14 11:34:55 +02:00
SaveCoverAutomatic ( song , result ) ;
2018-02-27 18:06:05 +01:00
}
2018-10-02 00:38:52 +02:00
2018-02-27 18:06:05 +01:00
}
2023-04-09 22:26:17 +02:00
AlbumCoverImageResult AlbumCoverChoiceController : : SearchForImage ( Song * song ) {
2021-02-26 21:03:51 +01:00
2023-05-14 11:34:55 +02:00
if ( ! song - > url ( ) . isValid ( ) | | ! song - > url ( ) . isLocalFile ( ) | | song - > effective_albumartist ( ) . isEmpty ( ) | | song - > album ( ) . isEmpty ( ) ) return AlbumCoverImageResult ( ) ;
2021-02-26 21:03:51 +01:00
QString album = song - > effective_album ( ) ;
2024-03-02 19:48:19 +01:00
album = Song : : AlbumRemoveDiscMisc ( album ) ;
2021-02-26 21:03:51 +01:00
// Get something sensible to stick in the search box
return cover_searcher_ - > Exec ( song - > effective_albumartist ( ) , album ) ;
}
2023-05-14 11:34:55 +02:00
void AlbumCoverChoiceController : : UnsetCover ( Song * song ) {
2021-02-26 21:03:51 +01:00
2023-05-14 11:34:55 +02:00
if ( ! song - > url ( ) . isValid ( ) | | ! song - > url ( ) . isLocalFile ( ) | | song - > effective_albumartist ( ) . isEmpty ( ) | | song - > album ( ) . isEmpty ( ) ) return ;
2018-02-27 18:06:05 +01:00
2023-05-14 11:34:55 +02:00
UnsetAlbumCoverForSong ( song ) ;
2018-02-27 18:06:05 +01:00
}
2023-05-14 11:34:55 +02:00
void AlbumCoverChoiceController : : ClearCover ( Song * song ) {
2018-02-27 18:06:05 +01:00
2023-05-14 11:34:55 +02:00
if ( ! song - > url ( ) . isValid ( ) | | ! song - > url ( ) . isLocalFile ( ) | | song - > effective_albumartist ( ) . isEmpty ( ) | | song - > album ( ) . isEmpty ( ) ) return ;
2021-02-26 21:03:51 +01:00
2023-05-14 11:34:55 +02:00
ClearAlbumCoverForSong ( song ) ;
2021-02-26 21:03:51 +01:00
}
2023-05-14 11:34:55 +02:00
bool AlbumCoverChoiceController : : DeleteCover ( Song * song , const bool unset ) {
2021-02-26 21:03:51 +01:00
2023-05-14 11:34:55 +02:00
if ( ! song - > url ( ) . isValid ( ) | | ! song - > url ( ) . isLocalFile ( ) | | song - > effective_albumartist ( ) . isEmpty ( ) | | song - > album ( ) . isEmpty ( ) ) return false ;
2021-02-26 21:03:51 +01:00
2023-05-14 11:34:55 +02:00
if ( song - > art_embedded ( ) & & song - > save_embedded_cover_supported ( ) ) {
SaveCoverEmbeddedToCollectionSongs ( * song , AlbumCoverImageResult ( ) ) ;
2021-02-26 21:03:51 +01:00
}
bool success = true ;
2023-05-14 11:34:55 +02:00
if ( song - > art_automatic ( ) . isValid ( ) & & song - > art_automatic ( ) . isLocalFile ( ) ) {
const QString art_automatic = song - > art_automatic ( ) . toLocalFile ( ) ;
2021-09-19 19:31:34 +02:00
QFile file ( art_automatic ) ;
if ( file . exists ( ) ) {
if ( file . remove ( ) ) {
2021-02-26 21:03:51 +01:00
song - > clear_art_automatic ( ) ;
}
2021-09-19 19:31:34 +02:00
else {
success = false ;
qLog ( Error ) < < " Failed to delete cover file " < < art_automatic < < file . errorString ( ) ;
emit Error ( tr ( " Failed to delete cover file %1: %2 " ) . arg ( art_automatic , file . errorString ( ) ) ) ;
}
2021-02-26 21:03:51 +01:00
}
else song - > clear_art_automatic ( ) ;
}
else song - > clear_art_automatic ( ) ;
2023-05-14 11:34:55 +02:00
if ( song - > art_manual ( ) . isValid ( ) & & song - > art_manual ( ) . isLocalFile ( ) ) {
const QString art_manual = song - > art_manual ( ) . toLocalFile ( ) ;
2021-09-19 19:31:34 +02:00
QFile file ( art_manual ) ;
if ( file . exists ( ) ) {
if ( file . remove ( ) ) {
2021-02-26 21:03:51 +01:00
song - > clear_art_manual ( ) ;
}
2021-09-19 19:31:34 +02:00
else {
success = false ;
qLog ( Error ) < < " Failed to delete cover file " < < art_manual < < file . errorString ( ) ;
emit Error ( tr ( " Failed to delete cover file %1: %2 " ) . arg ( art_manual , file . errorString ( ) ) ) ;
}
2021-02-26 21:03:51 +01:00
}
else song - > clear_art_manual ( ) ;
}
else song - > clear_art_manual ( ) ;
2021-03-07 03:43:49 +01:00
if ( success ) {
2023-05-14 11:34:55 +02:00
if ( unset ) UnsetCover ( song ) ;
else ClearCover ( song ) ;
2021-03-07 03:43:49 +01:00
}
2021-02-26 21:03:51 +01:00
return success ;
2018-09-10 21:58:57 +02:00
}
2019-07-09 01:05:42 +02:00
void AlbumCoverChoiceController : : ShowCover ( const Song & song , const QImage & image ) {
2018-09-10 21:58:57 +02:00
2023-05-14 11:34:55 +02:00
if ( ! image . isNull ( ) ) {
QPixmap pixmap = QPixmap : : fromImage ( image ) ;
if ( ! pixmap . isNull ( ) ) {
pixmap . setDevicePixelRatio ( devicePixelRatioF ( ) ) ;
ShowCover ( song , pixmap ) ;
return ;
}
}
for ( const AlbumCoverLoaderOptions : : Type type : cover_types_ ) {
switch ( type ) {
case AlbumCoverLoaderOptions : : Type : : Unset : {
if ( song . art_unset ( ) ) {
return ;
}
break ;
}
case AlbumCoverLoaderOptions : : Type : : Manual : {
QPixmap pixmap ;
if ( song . art_manual_is_valid ( ) & & song . art_manual ( ) . isLocalFile ( ) & & pixmap . load ( song . art_manual ( ) . toLocalFile ( ) ) ) {
2023-03-23 05:33:22 +01:00
pixmap . setDevicePixelRatio ( devicePixelRatioF ( ) ) ;
ShowCover ( song , pixmap ) ;
2023-05-14 11:34:55 +02:00
return ;
}
break ;
}
case AlbumCoverLoaderOptions : : Type : : Embedded : {
if ( song . art_embedded ( ) & & ! song . url ( ) . isEmpty ( ) & & song . url ( ) . isValid ( ) & & song . url ( ) . isLocalFile ( ) ) {
const QImage image_embedded_cover = TagReaderClient : : Instance ( ) - > LoadEmbeddedArtAsImageBlocking ( song . url ( ) . toLocalFile ( ) ) ;
if ( ! image_embedded_cover . isNull ( ) ) {
QPixmap pixmap = QPixmap : : fromImage ( image_embedded_cover ) ;
if ( ! pixmap . isNull ( ) ) {
pixmap . setDevicePixelRatio ( devicePixelRatioF ( ) ) ;
ShowCover ( song , pixmap ) ;
return ;
}
}
}
break ;
}
case AlbumCoverLoaderOptions : : Type : : Automatic : {
QPixmap pixmap ;
if ( song . art_automatic_is_valid ( ) & & song . art_automatic ( ) . isLocalFile ( ) & & pixmap . load ( song . art_automatic ( ) . toLocalFile ( ) ) ) {
pixmap . setDevicePixelRatio ( devicePixelRatioF ( ) ) ;
ShowCover ( song , pixmap ) ;
return ;
}
break ;
2023-03-23 05:33:22 +01:00
}
}
2018-09-10 21:58:57 +02:00
}
}
void AlbumCoverChoiceController : : ShowCover ( const Song & song , const QPixmap & pixmap ) {
2018-02-27 18:06:05 +01:00
QDialog * dialog = new QDialog ( this ) ;
dialog - > setAttribute ( Qt : : WA_DeleteOnClose , true ) ;
// Use Artist - Album as the window title
QString title_text ( song . effective_albumartist ( ) ) ;
if ( ! song . effective_album ( ) . isEmpty ( ) ) title_text + = " - " + song . effective_album ( ) ;
QLabel * label = new QLabel ( dialog ) ;
2018-09-10 21:58:57 +02:00
label - > setPixmap ( pixmap ) ;
2018-02-27 18:06:05 +01:00
2018-05-01 00:41:33 +02:00
// Add (WxHpx) to the title before possibly resizing
2020-05-29 17:45:00 +02:00
title_text + = " ( " + QString : : number ( pixmap . width ( ) ) + " x " + QString : : number ( pixmap . height ( ) ) + " px) " ;
2018-02-27 18:06:05 +01:00
2018-05-01 00:41:33 +02:00
// If the cover is larger than the screen, resize the window 85% seems to be enough to account for title bar and taskbar etc.
2023-04-17 21:12:12 +02:00
QScreen * screen = Utilities : : GetScreen ( this ) ;
2020-01-05 19:14:25 +01:00
QRect screenGeometry = screen - > availableGeometry ( ) ;
2019-07-08 22:10:43 +02:00
int desktop_height = screenGeometry . height ( ) ;
int desktop_width = screenGeometry . width ( ) ;
2018-02-27 18:06:05 +01:00
2018-05-01 00:41:33 +02:00
// Resize differently if monitor is in portrait mode
2018-02-27 18:06:05 +01:00
if ( desktop_width < desktop_height ) {
2021-03-21 18:53:02 +01:00
const int new_width = static_cast < int > ( static_cast < double > ( desktop_width ) * 0.95 ) ;
2020-05-29 17:45:00 +02:00
if ( new_width < pixmap . width ( ) ) {
2023-06-06 23:18:49 +02:00
label - > setPixmap ( pixmap . scaledToWidth ( static_cast < int > ( new_width * pixmap . devicePixelRatioF ( ) ) , Qt : : SmoothTransformation ) ) ;
2018-02-27 18:06:05 +01:00
}
}
else {
2021-03-21 18:53:02 +01:00
const int new_height = static_cast < int > ( static_cast < double > ( desktop_height ) * 0.85 ) ;
2020-05-29 17:45:00 +02:00
if ( new_height < pixmap . height ( ) ) {
2023-06-06 23:18:49 +02:00
label - > setPixmap ( pixmap . scaledToHeight ( static_cast < int > ( new_height * pixmap . devicePixelRatioF ( ) ) , Qt : : SmoothTransformation ) ) ;
2018-02-27 18:06:05 +01:00
}
}
dialog - > setWindowTitle ( title_text ) ;
2020-05-29 17:45:00 +02:00
# if (QT_VERSION >= QT_VERSION_CHECK(5, 15, 0))
2023-03-23 05:33:22 +01:00
dialog - > setFixedSize ( label - > pixmap ( Qt : : ReturnByValue ) . size ( ) / pixmap . devicePixelRatioF ( ) ) ;
2020-05-29 17:45:00 +02:00
# else
2023-03-23 05:33:22 +01:00
dialog - > setFixedSize ( label - > pixmap ( ) - > size ( ) / pixmap . devicePixelRatioF ( ) ) ;
2020-05-29 17:45:00 +02:00
# endif
2018-02-27 18:06:05 +01:00
dialog - > show ( ) ;
}
2021-09-12 21:24:22 +02:00
quint64 AlbumCoverChoiceController : : SearchCoverAutomatically ( const Song & song ) {
2018-02-27 18:06:05 +01:00
2021-09-12 21:24:22 +02:00
quint64 id = cover_fetcher_ - > FetchAlbumCover ( song . effective_albumartist ( ) , song . album ( ) , song . title ( ) , true ) ;
2018-02-27 18:06:05 +01:00
2023-05-14 11:34:55 +02:00
cover_fetching_tasks_ . insert ( id , song ) ;
2018-02-27 18:06:05 +01:00
2020-04-20 18:03:18 +02:00
return id ;
2018-02-27 18:06:05 +01:00
}
2023-04-09 22:26:17 +02:00
void AlbumCoverChoiceController : : AlbumCoverFetched ( const quint64 id , const AlbumCoverImageResult & result , const CoverSearchStatistics & statistics ) {
2018-02-27 18:06:05 +01:00
2019-09-15 20:27:32 +02:00
Q_UNUSED ( statistics ) ;
2018-02-27 18:06:05 +01:00
Song song ;
if ( cover_fetching_tasks_ . contains ( id ) ) {
song = cover_fetching_tasks_ . take ( id ) ;
}
2023-04-09 22:26:17 +02:00
if ( result . is_valid ( ) ) {
2021-02-26 21:03:51 +01:00
SaveCoverAutomatic ( & song , result ) ;
2018-02-27 18:06:05 +01:00
}
emit AutomaticCoverSearchDone ( ) ;
}
2023-05-14 11:34:55 +02:00
void AlbumCoverChoiceController : : SaveArtEmbeddedToSong ( Song * song , const bool art_embedded ) {
2019-07-07 21:14:24 +02:00
if ( ! song - > is_valid ( ) ) return ;
2023-05-14 11:34:55 +02:00
song - > set_art_embedded ( art_embedded ) ;
song - > set_art_unset ( false ) ;
2019-07-07 21:14:24 +02:00
2023-02-18 14:09:27 +01:00
if ( song - > source ( ) = = Song : : Source : : Collection ) {
2023-05-14 11:34:55 +02:00
app_ - > collection_backend ( ) - > UpdateEmbeddedAlbumArtAsync ( song - > effective_albumartist ( ) , song - > album ( ) , art_embedded ) ;
2021-02-26 21:03:51 +01:00
}
if ( * song = = app_ - > current_albumcover_loader ( ) - > last_song ( ) ) {
app_ - > current_albumcover_loader ( ) - > LoadAlbumCover ( * song ) ;
}
}
2023-05-14 11:34:55 +02:00
void AlbumCoverChoiceController : : SaveArtManualToSong ( Song * song , const QUrl & art_manual ) {
2018-02-27 18:06:05 +01:00
2021-02-26 21:03:51 +01:00
if ( ! song - > is_valid ( ) ) return ;
song - > set_art_manual ( art_manual ) ;
2023-05-14 11:34:55 +02:00
song - > set_art_unset ( false ) ;
2021-02-26 21:03:51 +01:00
// Update the backends.
switch ( song - > source ( ) ) {
2023-02-18 14:09:27 +01:00
case Song : : Source : : Collection :
2023-05-14 11:34:55 +02:00
app_ - > collection_backend ( ) - > UpdateManualAlbumArtAsync ( song - > effective_albumartist ( ) , song - > album ( ) , art_manual ) ;
2021-02-26 21:03:51 +01:00
break ;
2023-02-18 14:09:27 +01:00
case Song : : Source : : LocalFile :
case Song : : Source : : CDDA :
case Song : : Source : : Device :
case Song : : Source : : Stream :
case Song : : Source : : RadioParadise :
case Song : : Source : : SomaFM :
case Song : : Source : : Unknown :
2021-02-26 21:03:51 +01:00
break ;
2023-02-18 14:09:27 +01:00
case Song : : Source : : Tidal :
case Song : : Source : : Qobuz :
case Song : : Source : : Subsonic :
2023-07-21 05:55:24 +02:00
InternetServicePtr service = app_ - > internet_services ( ) - > ServiceBySource ( song - > source ( ) ) ;
2021-02-26 21:03:51 +01:00
if ( ! service ) break ;
if ( service - > artists_collection_backend ( ) ) {
2023-05-14 11:34:55 +02:00
service - > artists_collection_backend ( ) - > UpdateManualAlbumArtAsync ( song - > effective_albumartist ( ) , song - > album ( ) , art_manual ) ;
2021-02-26 21:03:51 +01:00
}
if ( service - > albums_collection_backend ( ) ) {
2023-05-14 11:34:55 +02:00
service - > albums_collection_backend ( ) - > UpdateManualAlbumArtAsync ( song - > effective_albumartist ( ) , song - > album ( ) , art_manual ) ;
2021-02-26 21:03:51 +01:00
}
if ( service - > songs_collection_backend ( ) ) {
2023-05-14 11:34:55 +02:00
service - > songs_collection_backend ( ) - > UpdateManualAlbumArtAsync ( song - > effective_albumartist ( ) , song - > album ( ) , art_manual ) ;
2021-02-26 21:03:51 +01:00
}
break ;
2019-07-07 21:14:24 +02:00
}
2018-02-27 18:06:05 +01:00
2020-04-20 18:03:18 +02:00
if ( * song = = app_ - > current_albumcover_loader ( ) - > last_song ( ) ) {
2019-07-07 21:14:24 +02:00
app_ - > current_albumcover_loader ( ) - > LoadAlbumCover ( * song ) ;
2018-02-27 18:06:05 +01:00
}
}
2023-05-14 11:34:55 +02:00
void AlbumCoverChoiceController : : ClearAlbumCoverForSong ( Song * song ) {
if ( ! song - > is_valid ( ) ) return ;
song - > set_art_unset ( false ) ;
song - > set_art_embedded ( false ) ;
song - > clear_art_automatic ( ) ;
song - > clear_art_manual ( ) ;
if ( song - > source ( ) = = Song : : Source : : Collection ) {
app_ - > collection_backend ( ) - > ClearAlbumArtAsync ( song - > effective_albumartist ( ) , song - > album ( ) , false ) ;
}
if ( * song = = app_ - > current_albumcover_loader ( ) - > last_song ( ) ) {
app_ - > current_albumcover_loader ( ) - > LoadAlbumCover ( * song ) ;
}
}
void AlbumCoverChoiceController : : UnsetAlbumCoverForSong ( Song * song ) {
if ( ! song - > is_valid ( ) ) return ;
song - > set_art_unset ( true ) ;
song - > set_art_embedded ( false ) ;
song - > clear_art_manual ( ) ;
song - > clear_art_automatic ( ) ;
if ( song - > source ( ) = = Song : : Source : : Collection ) {
app_ - > collection_backend ( ) - > UnsetAlbumArtAsync ( song - > effective_albumartist ( ) , song - > album ( ) ) ;
}
if ( * song = = app_ - > current_albumcover_loader ( ) - > last_song ( ) ) {
app_ - > current_albumcover_loader ( ) - > LoadAlbumCover ( * song ) ;
}
}
2023-04-09 22:26:17 +02:00
QUrl AlbumCoverChoiceController : : SaveCoverToFileAutomatic ( const Song * song , const AlbumCoverImageResult & result , const bool force_overwrite ) {
2019-03-11 23:07:11 +01:00
2021-02-26 21:03:51 +01:00
return SaveCoverToFileAutomatic ( song - > source ( ) ,
song - > effective_albumartist ( ) ,
song - > effective_album ( ) ,
song - > album_id ( ) ,
2023-06-15 21:06:18 +02:00
QFileInfo ( song - > url ( ) . toLocalFile ( ) ) . path ( ) ,
2021-02-26 21:03:51 +01:00
result ,
force_overwrite ) ;
2019-03-11 23:07:11 +01:00
}
2021-02-26 21:03:51 +01:00
QUrl AlbumCoverChoiceController : : SaveCoverToFileAutomatic ( const Song : : Source source ,
const QString & artist ,
const QString & album ,
const QString & album_id ,
const QString & album_dir ,
2023-04-09 22:26:17 +02:00
const AlbumCoverImageResult & result ,
2021-02-26 21:03:51 +01:00
const bool force_overwrite ) {
2018-02-27 18:06:05 +01:00
2024-04-09 23:20:26 +02:00
QString filepath = CoverUtils : : CoverFilePath ( cover_options_ , source , artist , album , album_id , album_dir , result . cover_url , QStringLiteral ( " jpg " ) ) ;
2019-07-07 21:14:24 +02:00
if ( filepath . isEmpty ( ) ) return QUrl ( ) ;
2018-05-01 00:41:33 +02:00
2021-02-26 21:03:51 +01:00
QFile file ( filepath ) ;
// Don't overwrite when saving in album dir if the filename is set to pattern unless "force_overwrite" is set.
2023-03-18 20:03:07 +01:00
if ( source = = Song : : Source : : Collection & & ! cover_options_ . cover_overwrite & & ! force_overwrite & & get_save_album_cover_type ( ) = = CoverOptions : : CoverType : : Album & & cover_options_ . cover_filename = = CoverOptions : : CoverFilename : : Pattern & & file . exists ( ) ) {
2021-02-26 21:03:51 +01:00
while ( file . exists ( ) ) {
QFileInfo fileinfo ( file . fileName ( ) ) ;
file . setFileName ( fileinfo . path ( ) + " /0 " + fileinfo . fileName ( ) ) ;
}
filepath = file . fileName ( ) ;
}
2023-05-14 11:34:55 +02:00
if ( ! result . image_data . isEmpty ( ) & & result . is_jpeg ( ) ) {
2021-02-26 21:03:51 +01:00
if ( file . open ( QIODevice : : WriteOnly ) ) {
2023-04-09 22:26:17 +02:00
if ( file . write ( result . image_data ) > 0 ) {
2023-05-14 11:34:55 +02:00
return QUrl : : fromLocalFile ( filepath ) ;
2021-08-09 23:32:26 +02:00
}
else {
qLog ( Error ) < < " Failed to write cover to file " < < file . fileName ( ) < < file . errorString ( ) ;
2021-09-19 19:31:34 +02:00
emit Error ( tr ( " Failed to write cover to file %1: %2 " ) . arg ( file . fileName ( ) , file . errorString ( ) ) ) ;
2021-08-09 23:32:26 +02:00
}
2021-02-26 21:03:51 +01:00
file . close ( ) ;
}
2021-08-09 23:32:26 +02:00
else {
qLog ( Error ) < < " Failed to open cover file " < < file . fileName ( ) < < " for writing: " < < file . errorString ( ) ;
2021-09-19 19:31:34 +02:00
emit Error ( tr ( " Failed to open cover file %1 for writing: %2 " ) . arg ( file . fileName ( ) , file . errorString ( ) ) ) ;
2021-08-09 23:32:26 +02:00
}
2021-02-26 21:03:51 +01:00
}
else {
2023-05-14 11:34:55 +02:00
if ( result . image . save ( filepath , " JPG " ) ) {
return QUrl : : fromLocalFile ( filepath ) ;
}
2021-02-26 21:03:51 +01:00
}
2023-05-14 11:34:55 +02:00
return QUrl ( ) ;
2021-02-26 21:03:51 +01:00
}
2023-05-14 11:34:55 +02:00
void AlbumCoverChoiceController : : SaveCoverEmbeddedToCollectionSongs ( const Song & song , const AlbumCoverImageResult & result ) {
2021-02-26 21:03:51 +01:00
2023-05-14 11:34:55 +02:00
SaveCoverEmbeddedToCollectionSongs ( song , QString ( ) , result . image_data , result . mime_type ) ;
2021-02-26 21:03:51 +01:00
}
2023-05-14 11:34:55 +02:00
void AlbumCoverChoiceController : : SaveCoverEmbeddedToCollectionSongs ( const Song & song , const QString & cover_filename , const QByteArray & image_data , const QString & mime_type ) {
2021-02-26 21:03:51 +01:00
2023-05-14 11:34:55 +02:00
if ( song . source ( ) = = Song : : Source : : Collection ) {
SaveCoverEmbeddedToCollectionSongs ( song . effective_albumartist ( ) , song . effective_album ( ) , cover_filename , image_data , mime_type ) ;
}
else {
SaveCoverEmbeddedToSong ( song , cover_filename , image_data , mime_type ) ;
}
2019-03-11 23:07:11 +01:00
2021-02-26 21:03:51 +01:00
}
2023-05-14 11:34:55 +02:00
void AlbumCoverChoiceController : : SaveCoverEmbeddedToCollectionSongs ( const QString & effective_albumartist , const QString & effective_album , const QString & cover_filename , const QByteArray & image_data , const QString & mime_type ) {
2021-02-26 21:03:51 +01:00
# if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
2023-05-14 11:34:55 +02:00
QFuture < SongList > future = QtConcurrent : : run ( & CollectionBackend : : GetAlbumSongs , app_ - > collection_backend ( ) , effective_albumartist , effective_album , CollectionFilterOptions ( ) ) ;
2021-02-26 21:03:51 +01:00
# else
2023-07-21 06:10:44 +02:00
QFuture < SongList > future = QtConcurrent : : run ( & * app_ - > collection_backend ( ) , & CollectionBackend : : GetAlbumSongs , effective_albumartist , effective_album , CollectionFilterOptions ( ) ) ;
2021-02-26 21:03:51 +01:00
# endif
2023-05-14 11:34:55 +02:00
QFutureWatcher < SongList > * watcher = new QFutureWatcher < SongList > ( ) ;
QObject : : connect ( watcher , & QFutureWatcher < SongList > : : finished , this , [ this , watcher , cover_filename , image_data , mime_type ] ( ) {
const SongList collection_songs = watcher - > result ( ) ;
watcher - > deleteLater ( ) ;
for ( const Song & collection_song : collection_songs ) {
SaveCoverEmbeddedToSong ( collection_song , cover_filename , image_data , mime_type ) ;
}
} ) ;
watcher - > setFuture ( future ) ;
2018-02-27 18:06:05 +01:00
2021-02-26 21:03:51 +01:00
}
2023-05-14 11:34:55 +02:00
void AlbumCoverChoiceController : : SaveCoverEmbeddedToSong ( const Song & song , const QString & cover_filename , const QByteArray & image_data , const QString & mime_type ) {
2018-02-27 18:06:05 +01:00
2023-05-14 11:34:55 +02:00
QMutexLocker l ( & mutex_cover_save_tasks_ ) ;
cover_save_tasks_ . append ( song ) ;
const bool art_embedded = ! image_data . isNull ( ) ;
TagReaderReply * reply = app_ - > tag_reader_client ( ) - > SaveEmbeddedArt ( song . url ( ) . toLocalFile ( ) , TagReaderClient : : SaveCoverOptions ( cover_filename , image_data , mime_type ) ) ;
QObject : : connect ( reply , & TagReaderReply : : Finished , this , [ this , reply , song , art_embedded ] ( ) { SaveEmbeddedCoverFinished ( reply , song , art_embedded ) ; } ) ;
2018-02-27 18:06:05 +01:00
}
bool AlbumCoverChoiceController : : IsKnownImageExtension ( const QString & suffix ) {
if ( ! sImageExtensions ) {
sImageExtensions = new QSet < QString > ( ) ;
2024-04-09 23:20:26 +02:00
( * sImageExtensions ) < < QStringLiteral ( " png " ) < < QStringLiteral ( " jpg " ) < < QStringLiteral ( " jpeg " ) < < QStringLiteral ( " bmp " ) < < QStringLiteral ( " gif " ) < < QStringLiteral ( " xpm " ) < < QStringLiteral ( " pbm " ) < < QStringLiteral ( " pgm " ) < < QStringLiteral ( " ppm " ) < < QStringLiteral ( " xbm " ) ;
2018-02-27 18:06:05 +01:00
}
return sImageExtensions - > contains ( suffix ) ;
}
bool AlbumCoverChoiceController : : CanAcceptDrag ( const QDragEnterEvent * e ) {
for ( const QUrl & url : e - > mimeData ( ) - > urls ( ) ) {
const QString suffix = QFileInfo ( url . toLocalFile ( ) ) . suffix ( ) . toLower ( ) ;
if ( IsKnownImageExtension ( suffix ) ) return true ;
}
2019-04-08 18:46:11 +02:00
return e - > mimeData ( ) - > hasImage ( ) ;
2018-02-27 18:06:05 +01:00
}
2023-05-14 11:34:55 +02:00
void AlbumCoverChoiceController : : SaveCover ( Song * song , const QDropEvent * e ) {
2018-02-27 18:06:05 +01:00
for ( const QUrl & url : e - > mimeData ( ) - > urls ( ) ) {
2018-09-10 21:58:57 +02:00
2018-02-27 18:06:05 +01:00
const QString filename = url . toLocalFile ( ) ;
const QString suffix = QFileInfo ( filename ) . suffix ( ) . toLower ( ) ;
if ( IsKnownImageExtension ( suffix ) ) {
2023-03-18 20:03:07 +01:00
if ( get_save_album_cover_type ( ) = = CoverOptions : : CoverType : : Embedded & & song - > save_embedded_cover_supported ( ) ) {
2023-05-14 11:34:55 +02:00
SaveCoverEmbeddedToCollectionSongs ( * song , filename ) ;
2021-02-26 21:03:51 +01:00
}
else {
SaveArtManualToSong ( song , url ) ;
}
2023-05-14 11:34:55 +02:00
return ;
2018-02-27 18:06:05 +01:00
}
}
if ( e - > mimeData ( ) - > hasImage ( ) ) {
QImage image = qvariant_cast < QImage > ( e - > mimeData ( ) - > imageData ( ) ) ;
if ( ! image . isNull ( ) ) {
2023-05-14 11:34:55 +02:00
SaveCoverAutomatic ( song , AlbumCoverImageResult ( image ) ) ;
2018-02-27 18:06:05 +01:00
}
}
}
2021-02-26 21:03:51 +01:00
2023-04-09 22:26:17 +02:00
QUrl AlbumCoverChoiceController : : SaveCoverAutomatic ( Song * song , const AlbumCoverImageResult & result ) {
2021-02-26 21:03:51 +01:00
QUrl cover_url ;
switch ( get_save_album_cover_type ( ) ) {
2023-03-18 20:03:07 +01:00
case CoverOptions : : CoverType : : Embedded : {
2021-02-26 21:03:51 +01:00
if ( song - > save_embedded_cover_supported ( ) ) {
2023-05-14 11:34:55 +02:00
SaveCoverEmbeddedToCollectionSongs ( * song , result ) ;
2021-02-26 21:03:51 +01:00
break ;
}
}
2022-07-26 20:37:06 +02:00
[[fallthrough]] ;
2023-03-18 20:03:07 +01:00
case CoverOptions : : CoverType : : Cache :
case CoverOptions : : CoverType : : Album : {
2021-02-26 21:03:51 +01:00
cover_url = SaveCoverToFileAutomatic ( song , result ) ;
if ( ! cover_url . isEmpty ( ) ) SaveArtManualToSong ( song , cover_url ) ;
break ;
}
}
return cover_url ;
}
2023-05-14 11:34:55 +02:00
void AlbumCoverChoiceController : : SaveEmbeddedCoverFinished ( TagReaderReply * reply , Song song , const bool art_embedded ) {
2021-02-26 21:03:51 +01:00
2023-05-14 11:34:55 +02:00
if ( ! cover_save_tasks_ . contains ( song ) ) return ;
cover_save_tasks_ . removeAll ( song ) ;
2021-02-26 21:03:51 +01:00
2023-05-14 11:34:55 +02:00
if ( reply - > is_successful ( ) ) {
SaveArtEmbeddedToSong ( & song , art_embedded ) ;
}
else {
emit Error ( tr ( " Could not save cover to file %1. " ) . arg ( song . url ( ) . toLocalFile ( ) ) ) ;
2021-03-07 05:43:56 +01:00
}
2021-02-26 21:03:51 +01:00
}