Disable automatic conversions from 8-bit strings

This commit is contained in:
Jonas Kvinge
2024-04-11 02:56:01 +02:00
parent 58944993b8
commit 0c6872b352
310 changed files with 2501 additions and 2332 deletions

View File

@@ -62,6 +62,7 @@
#include "core/song.h"
#include "core/iconloader.h"
#include "core/tagreaderclient.h"
#include "core/settings.h"
#include "collection/collectionfilteroptions.h"
#include "collection/collectionbackend.h"
@@ -131,7 +132,7 @@ void AlbumCoverChoiceController::Init(Application *app) {
app_ = app;
cover_fetcher_ = new AlbumCoverFetcher(app_->cover_providers(), app->network(), this);
cover_searcher_ = new AlbumCoverSearcher(QIcon(":/pictures/cdcase.png"), app, this);
cover_searcher_ = new AlbumCoverSearcher(QIcon(QStringLiteral(":/pictures/cdcase.png")), app, this);
cover_searcher_->Init(cover_fetcher_);
QObject::connect(cover_fetcher_, &AlbumCoverFetcher::AlbumCoverFetched, this, &AlbumCoverChoiceController::AlbumCoverFetched);
@@ -140,11 +141,11 @@ void AlbumCoverChoiceController::Init(Application *app) {
void AlbumCoverChoiceController::ReloadSettings() {
QSettings s;
Settings s;
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_pattern = s.value(CoversSettingsPage::kSavePattern, QStringLiteral("%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();
@@ -175,7 +176,7 @@ AlbumCoverImageResult AlbumCoverChoiceController::LoadImageFromFile(Song *song)
return AlbumCoverImageResult();
}
QString cover_file = QFileDialog::getOpenFileName(this, tr("Load cover from disk"), GetInitialPathForFileDialog(*song, QString()), tr(kLoadImageFileFilter) + ";;" + tr(kAllFilesFilter));
QString cover_file = QFileDialog::getOpenFileName(this, tr("Load cover from disk"), GetInitialPathForFileDialog(*song, QString()), tr(kLoadImageFileFilter) + QStringLiteral(";;") + tr(kAllFilesFilter));
if (cover_file.isEmpty()) return AlbumCoverImageResult();
QFile file(cover_file);
@@ -206,7 +207,7 @@ QUrl AlbumCoverChoiceController::LoadCoverFromFile(Song *song) {
if (!song->url().isValid() || !song->url().isLocalFile() || song->effective_albumartist().isEmpty() || song->album().isEmpty()) return QUrl();
QString cover_file = QFileDialog::getOpenFileName(this, tr("Load cover from disk"), GetInitialPathForFileDialog(*song, QString()), tr(kLoadImageFileFilter) + ";;" + tr(kAllFilesFilter));
QString cover_file = QFileDialog::getOpenFileName(this, tr("Load cover from disk"), GetInitialPathForFileDialog(*song, QString()), tr(kLoadImageFileFilter) + QStringLiteral(";;") + tr(kAllFilesFilter));
if (cover_file.isEmpty() || QImage(cover_file).isNull()) return QUrl();
switch (get_save_album_cover_type()) {
@@ -235,23 +236,23 @@ void AlbumCoverChoiceController::SaveCoverToFileManual(const Song &song, const A
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 + QLatin1Char('-') + (song.effective_album().isEmpty() ? tr("unknown") : song.effective_album()) + QStringLiteral(".jpg");
initial_file_name = initial_file_name.toLower();
initial_file_name.replace(QRegularExpression(QStringLiteral("\\s")), QStringLiteral("-"));
initial_file_name.remove(QRegularExpression(QString(kInvalidFatCharactersRegex), QRegularExpression::CaseInsensitiveOption));
initial_file_name.remove(QRegularExpression(QLatin1String(kInvalidFatCharactersRegex), QRegularExpression::CaseInsensitiveOption));
QString save_filename = QFileDialog::getSaveFileName(this, tr("Save album cover"), GetInitialPathForFileDialog(song, initial_file_name), tr(kSaveImageFileFilter) + ";;" + tr(kAllFilesFilter));
QString save_filename = QFileDialog::getSaveFileName(this, tr("Save album cover"), GetInitialPathForFileDialog(song, initial_file_name), tr(kSaveImageFileFilter) + QStringLiteral(";;") + tr(kAllFilesFilter));
if (save_filename.isEmpty()) return;
QFileInfo fileinfo(save_filename);
if (fileinfo.suffix().isEmpty()) {
save_filename.append(".jpg");
save_filename.append(QStringLiteral(".jpg"));
fileinfo.setFile(save_filename);
}
if (!QImageWriter::supportedImageFormats().contains(fileinfo.completeSuffix().toUtf8().toLower())) {
save_filename = Utilities::PathWithoutFilenameExtension(save_filename) + ".jpg";
save_filename = Utilities::PathWithoutFilenameExtension(save_filename) + QStringLiteral(".jpg");
fileinfo.setFile(save_filename);
}
@@ -289,8 +290,8 @@ QString AlbumCoverChoiceController::GetInitialPathForFileDialog(const Song &song
}
// If no automatic art, start in the song's folder
if (!song.url().isEmpty() && song.url().isValid() && song.url().isLocalFile() && song.url().toLocalFile().contains('/')) {
return song.url().toLocalFile().section('/', 0, -2) + filename;
if (!song.url().isEmpty() && song.url().isValid() && song.url().isLocalFile() && song.url().toLocalFile().contains(QLatin1Char('/'))) {
return song.url().toLocalFile().section(QLatin1Char('/'), 0, -2) + filename;
}
return QDir::home().absolutePath() + filename;
@@ -422,7 +423,7 @@ void AlbumCoverChoiceController::ShowCover(const Song &song, const QImage &image
for (const AlbumCoverLoaderOptions::Type type : cover_types_) {
switch (type) {
case AlbumCoverLoaderOptions::Type::Unset: {
case AlbumCoverLoaderOptions::Type::Unset:{
if (song.art_unset()) {
return;
}
@@ -472,13 +473,13 @@ void AlbumCoverChoiceController::ShowCover(const Song &song, const QPixmap &pixm
// Use Artist - Album as the window title
QString title_text(song.effective_albumartist());
if (!song.effective_album().isEmpty()) title_text += " - " + song.effective_album();
if (!song.effective_album().isEmpty()) title_text += QStringLiteral(" - ") + song.effective_album();
QLabel *label = new QLabel(dialog);
label->setPixmap(pixmap);
// Add (WxHpx) to the title before possibly resizing
title_text += " (" + QString::number(pixmap.width()) + "x" + QString::number(pixmap.height()) + "px)";
title_text += QStringLiteral(" (") + QString::number(pixmap.width()) + QLatin1Char('x') + QString::number(pixmap.height()) + QStringLiteral("px)");
// If the cover is larger than the screen, resize the window 85% seems to be enough to account for title bar and taskbar etc.
QScreen *screen = Utilities::GetScreen(this);
@@ -663,7 +664,7 @@ QUrl AlbumCoverChoiceController::SaveCoverToFileAutomatic(const Song::Source sou
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()) {
while (file.exists()) {
QFileInfo fileinfo(file.fileName());
file.setFileName(fileinfo.path() + "/0" + fileinfo.fileName());
file.setFileName(fileinfo.path() + QStringLiteral("/0") + fileinfo.fileName());
}
filepath = file.fileName();
}

View File

@@ -33,6 +33,8 @@
#include "albumcoverexport.h"
#include "ui_albumcoverexport.h"
#include "core/settings.h"
const char *AlbumCoverExport::kSettingsGroup = "AlbumCoverExport";
AlbumCoverExport::AlbumCoverExport(QWidget *parent) : QDialog(parent), ui_(new Ui_AlbumCoverExport) {
@@ -47,17 +49,17 @@ AlbumCoverExport::~AlbumCoverExport() { delete ui_; }
AlbumCoverExport::DialogResult AlbumCoverExport::Exec() {
QSettings s;
Settings s;
s.beginGroup(kSettingsGroup);
// Restore last accepted settings
ui_->fileName->setText(s.value("fileName", "cover").toString());
ui_->fileName->setText(s.value("fileName", QStringLiteral("cover")).toString());
ui_->doNotOverwrite->setChecked(static_cast<OverwriteMode>(s.value("overwrite", static_cast<int>(OverwriteMode::None)).toInt()) == OverwriteMode::None);
ui_->overwriteAll->setChecked(static_cast<OverwriteMode>(s.value("overwrite", static_cast<int>(OverwriteMode::All)).toInt()) == OverwriteMode::All);
ui_->overwriteSmaller->setChecked(static_cast<OverwriteMode>(s.value("overwrite", static_cast<int>(OverwriteMode::Smaller)).toInt()) == OverwriteMode::Smaller);
ui_->forceSize->setChecked(s.value("forceSize", false).toBool());
ui_->width->setText(s.value("width", "").toString());
ui_->height->setText(s.value("height", "").toString());
ui_->width->setText(s.value("width", QLatin1String("")).toString());
ui_->height->setText(s.value("height", QLatin1String("")).toString());
ui_->export_downloaded->setChecked(s.value("export_downloaded", true).toBool());
ui_->export_embedded->setChecked(s.value("export_embedded", false).toBool());

View File

@@ -320,8 +320,8 @@ void AlbumCoverFetcherSearch::ProviderCoverFetchFinished(QNetworkReply *reply) {
}
else {
QString mimetype = reply->header(QNetworkRequest::ContentTypeHeader).toString();
if (mimetype.contains(';')) {
mimetype = mimetype.left(mimetype.indexOf(';'));
if (mimetype.contains(QLatin1Char(';'))) {
mimetype = mimetype.left(mimetype.indexOf(QLatin1Char(';')));
}
if (ImageUtils::SupportedImageMimeTypes().contains(mimetype, Qt::CaseInsensitive) || ImageUtils::SupportedImageFormats().contains(mimetype, Qt::CaseInsensitive)) {
QByteArray image_data = reply->readAll();

View File

@@ -41,7 +41,7 @@ class AlbumCoverImageResult {
QImage image;
bool is_valid() const { return !image_data.isNull() || !image.isNull(); }
bool is_jpeg() const { return mime_type == "image/jpeg" && !image_data.isEmpty(); }
bool is_jpeg() const { return mime_type == QStringLiteral("image/jpeg") && !image_data.isEmpty(); }
};
Q_DECLARE_METATYPE(AlbumCoverImageResult)

View File

@@ -21,6 +21,7 @@
#include <QSettings>
#include "core/settings.h"
#include "settings/coverssettingspage.h"
AlbumCoverLoaderOptions::AlbumCoverLoaderOptions(const Options _options, const QSize _desired_scaled_size, const qreal _device_pixel_ratio, const Types &_types)
@@ -33,21 +34,21 @@ AlbumCoverLoaderOptions::Types AlbumCoverLoaderOptions::LoadTypes() {
Types cover_types;
QSettings s;
Settings s;
s.beginGroup(CoversSettingsPage::kSettingsGroup);
const QStringList all_cover_types = QStringList() << QStringLiteral("art_unset") << QStringLiteral("art_embedded") << QStringLiteral("art_manual") << QStringLiteral("art_automatic");
const QStringList cover_types_strlist = s.value(CoversSettingsPage::kTypes, all_cover_types).toStringList();
for (const QString &cover_type_str : cover_types_strlist) {
if (cover_type_str == "art_unset") {
if (cover_type_str == QStringLiteral("art_unset")) {
cover_types << AlbumCoverLoaderOptions::Type::Unset;
}
else if (cover_type_str == "art_embedded") {
else if (cover_type_str == QStringLiteral("art_embedded")) {
cover_types << AlbumCoverLoaderOptions::Type::Embedded;
}
else if (cover_type_str == "art_manual") {
else if (cover_type_str == QStringLiteral("art_manual")) {
cover_types << AlbumCoverLoaderOptions::Type::Manual;
}
else if (cover_type_str == "art_automatic") {
else if (cover_type_str == QStringLiteral("art_automatic")) {
cover_types << AlbumCoverLoaderOptions::Type::Automatic;
}
}

View File

@@ -70,6 +70,7 @@
#include "core/tagreaderclient.h"
#include "core/database.h"
#include "core/sqlrow.h"
#include "core/settings.h"
#include "utilities/strutils.h"
#include "utilities/fileutils.h"
#include "utilities/imageutils.h"
@@ -218,7 +219,7 @@ void AlbumCoverManager::Init() {
QObject::connect(ui_->action_load, &QAction::triggered, this, &AlbumCoverManager::LoadSelectedToPlaylist);
// Restore settings
QSettings s;
Settings s;
s.beginGroup(kSettingsGroup);
if (s.contains("geometry")) {
@@ -279,12 +280,12 @@ void AlbumCoverManager::closeEvent(QCloseEvent *e) {
void AlbumCoverManager::LoadGeometry() {
QSettings s;
Settings s;
s.beginGroup(kSettingsGroup);
if (s.contains("geometry")) {
if (s.contains(QStringLiteral("geometry"))) {
restoreGeometry(s.value("geometry").toByteArray());
}
if (s.contains("splitter_state")) {
if (s.contains(QStringLiteral("splitter_state"))) {
ui_->splitter->restoreState(s.value("splitter_state").toByteArray());
}
else {
@@ -300,7 +301,7 @@ void AlbumCoverManager::LoadGeometry() {
void AlbumCoverManager::SaveSettings() {
QSettings s;
Settings s;
s.beginGroup(kSettingsGroup);
s.setValue("geometry", saveGeometry());
s.setValue("splitter_state", ui_->splitter->saveState());
@@ -397,7 +398,7 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem *current) {
display_text = album_info.album;
}
else {
display_text = album_info.album_artist + " - " + album_info.album;
display_text = album_info.album_artist + QStringLiteral(" - ") + album_info.album;
}
AlbumItem *album_item = new AlbumItem(icon_nocover_item_, display_text, ui_->albums);
@@ -413,7 +414,7 @@ void AlbumCoverManager::ArtistChanged(QListWidgetItem *current) {
album_item->setToolTip(album_info.album);
}
else {
album_item->setToolTip(album_info.album_artist + " - " + album_info.album);
album_item->setToolTip(album_info.album_artist + QStringLiteral(" - ") + album_info.album);
}
album_item->setData(Role_ArtEmbedded, album_info.art_embedded);
@@ -497,7 +498,7 @@ bool AlbumCoverManager::ShouldHide(const AlbumItem &album_item, const QString &f
return false;
}
QStringList query = filter.split(' ');
QStringList query = filter.split(QLatin1Char(' '));
for (const QString &s : query) {
bool in_text = album_item.text().contains(s, Qt::CaseInsensitive);
bool in_albumartist = album_item.data(Role_AlbumArtist).toString().contains(s, Qt::CaseInsensitive);
@@ -558,7 +559,7 @@ void AlbumCoverManager::UpdateStatusText() {
.arg(fetch_statistics_.missing_images_);
if (fetch_statistics_.bytes_transferred_ > 0) {
message += ", " + tr("%1 transferred").arg(Utilities::PrettySize(fetch_statistics_.bytes_transferred_));
message += QStringLiteral(", ") + tr("%1 transferred").arg(Utilities::PrettySize(fetch_statistics_.bytes_transferred_));
}
statusBar()->showMessage(message);
@@ -632,7 +633,7 @@ Song AlbumCoverManager::AlbumItemAsSong(AlbumItem *album_item) {
QString title = album_item->data(Role_Album).toString();
QString artist_name = album_item->data(Role_AlbumArtist).toString();
if (!artist_name.isEmpty()) {
result.set_title(artist_name + " - " + title);
result.set_title(artist_name + QStringLiteral(" - ") + title);
}
else {
result.set_title(title);
@@ -876,7 +877,7 @@ SongList AlbumCoverManager::GetSongsInAlbum(const QModelIndex &idx) const {
QSqlDatabase db(collection_backend_->db()->Connect());
CollectionQuery q(db, collection_backend_->songs_table(), collection_backend_->fts_table());
q.SetColumnSpec("ROWID," + Song::kColumnSpec);
q.SetColumnSpec(QStringLiteral("ROWID,") + Song::kColumnSpec);
q.AddWhere(QStringLiteral("album"), idx.data(Role_Album).toString());
q.SetOrderBy(QStringLiteral("disc, track, title"));

View File

@@ -220,7 +220,7 @@ void AlbumCoverSearcher::SearchFinished(const quint64 id, const CoverProviderSea
QStandardItem *item = new QStandardItem;
item->setIcon(no_cover_icon_);
item->setText(result.artist + " - " + result.album);
item->setText(result.artist + QStringLiteral(" - ") + result.album);
item->setData(result.image_url, Role_ImageURL);
item->setData(new_id, Role_ImageRequestId);
item->setData(false, Role_ImageFetchFinished);

View File

@@ -84,7 +84,7 @@ void CoverExportRunnable::ProcessAndExportCover() {
if (dialog_result_.export_downloaded_ && song_.art_manual_is_valid()) {
const QString cover_path = song_.art_manual().toLocalFile();
if (image.load(cover_path)) {
extension = cover_path.section('.', -1);
extension = cover_path.section(QLatin1Char('.'), -1);
}
}
break;
@@ -92,7 +92,7 @@ void CoverExportRunnable::ProcessAndExportCover() {
if (dialog_result_.export_downloaded_ && song_.art_automatic_is_valid()) {
const QString cover_path = song_.art_automatic().toLocalFile();
if (image.load(cover_path)) {
extension = cover_path.section('.', -1);
extension = cover_path.section(QLatin1Char('.'), -1);
}
}
break;
@@ -110,8 +110,8 @@ void CoverExportRunnable::ProcessAndExportCover() {
image = image.scaled(QSize(dialog_result_.width_, dialog_result_.height_), Qt::IgnoreAspectRatio);
}
QString cover_dir = song_.url().toLocalFile().section('/', 0, -2);
QString new_file = cover_dir + '/' + dialog_result_.filename_ + '.' + (song_.art_embedded() ? QStringLiteral("jpg") : extension);
QString cover_dir = song_.url().toLocalFile().section(QLatin1Char('/'), 0, -2);
QString new_file = cover_dir + QLatin1Char('/') + dialog_result_.filename_ + QLatin1Char('.') + (song_.art_embedded() ? QStringLiteral("jpg") : extension);
// If the file exists, do not override!
if (dialog_result_.overwrite_ == AlbumCoverExport::OverwriteMode::None && QFile::exists(new_file)) {
@@ -177,7 +177,7 @@ void CoverExportRunnable::ExportCover() {
if (dialog_result_.export_downloaded_ && song_.art_manual_is_valid()) {
cover_path = song_.art_manual().toLocalFile();
if (image.load(cover_path)) {
extension = cover_path.section('.', -1);
extension = cover_path.section(QLatin1Char('.'), -1);
}
}
break;
@@ -185,7 +185,7 @@ void CoverExportRunnable::ExportCover() {
if (dialog_result_.export_downloaded_ && song_.art_automatic_is_valid()) {
cover_path = song_.art_automatic().toLocalFile();
if (image.load(cover_path)) {
extension = cover_path.section('.', -1);
extension = cover_path.section(QLatin1Char('.'), -1);
}
}
break;
@@ -198,8 +198,8 @@ void CoverExportRunnable::ExportCover() {
return;
}
QString cover_dir = song_.url().toLocalFile().section('/', 0, -2);
QString new_file = cover_dir + '/' + dialog_result_.filename_ + '.' + extension;
QString cover_dir = song_.url().toLocalFile().section(QLatin1Char('/'), 0, -2);
QString new_file = cover_dir + QLatin1Char('/') + dialog_result_.filename_ + QLatin1Char('.') + extension;
// If the file exists, do not override!
if (dialog_result_.overwrite_ == AlbumCoverExport::OverwriteMode::None && QFile::exists(new_file)) {

View File

@@ -30,6 +30,7 @@
#include <QSettings>
#include "core/logging.h"
#include "core/settings.h"
#include "coverprovider.h"
#include "coverproviders.h"
@@ -56,7 +57,7 @@ void CoverProviders::ReloadSettings() {
all_providers.insert(provider->order(), provider->name());
}
QSettings s;
Settings s;
s.beginGroup(CoversSettingsPage::kSettingsGroup);
QStringList providers_enabled = s.value(CoversSettingsPage::kProviders, QStringList() << all_providers.values()).toStringList();
s.endGroup();

View File

@@ -63,6 +63,6 @@ QString CoverSearchStatistics::AverageDimensions() const {
return QStringLiteral("0x0");
}
return QString::number(chosen_width_ / chosen_images_) + "x" + QString::number(chosen_height_ / chosen_images_);
return QString::number(chosen_width_ / chosen_images_) + QLatin1Char('x') + QString::number(chosen_height_ / chosen_images_);
}

View File

@@ -43,7 +43,7 @@ CoverSearchStatisticsDialog::CoverSearchStatisticsDialog(QWidget *parent)
details_layout_->setSpacing(0);
setStyleSheet(
"#details {"
QStringLiteral("#details {"
" background-color: palette(base);"
"}"
"#details QLabel[type=\"label\"] {"
@@ -54,7 +54,7 @@ CoverSearchStatisticsDialog::CoverSearchStatisticsDialog(QWidget *parent)
"#details QLabel[type=\"value\"] {"
" font-weight: bold;"
" max-width: 100px;"
"}");
"}"));
}
CoverSearchStatisticsDialog::~CoverSearchStatisticsDialog() { delete ui_; }
@@ -92,8 +92,8 @@ void CoverSearchStatisticsDialog::AddLine(const QString &label, const QString &v
QLabel *label1 = new QLabel(label);
QLabel *label2 = new QLabel(value);
label1->setProperty("type", "label");
label2->setProperty("type", "value");
label1->setProperty("type", QStringLiteral("label"));
label2->setProperty("type", QStringLiteral("value"));
QHBoxLayout *layout = new QHBoxLayout;
layout->addWidget(label1);

View File

@@ -41,7 +41,7 @@ using std::make_unique;
CurrentAlbumCoverLoader::CurrentAlbumCoverLoader(Application *app, QObject *parent)
: QObject(parent),
app_(app),
temp_file_pattern_(QDir::tempPath() + "/strawberry-cover-XXXXXX.jpg"),
temp_file_pattern_(QDir::tempPath() + QStringLiteral("/strawberry-cover-XXXXXX.jpg")),
id_(0) {
options_.options = AlbumCoverLoaderOptions::Option::RawImageData | AlbumCoverLoaderOptions::Option::OriginalImage | AlbumCoverLoaderOptions::Option::ScaledImage;

View File

@@ -47,8 +47,10 @@
#include "jsoncoverprovider.h"
#include "deezercoverprovider.h"
const char *DeezerCoverProvider::kApiUrl = "https://api.deezer.com";
const int DeezerCoverProvider::kLimit = 10;
namespace {
constexpr char kApiUrl[] = "https://api.deezer.com";
constexpr int kLimit = 10;
}
DeezerCoverProvider::DeezerCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(QStringLiteral("Deezer"), true, false, 2.0, true, true, app, network, parent) {}
@@ -72,27 +74,27 @@ bool DeezerCoverProvider::StartSearch(const QString &artist, const QString &albu
QString query = artist;
if (album.isEmpty() && !title.isEmpty()) {
resource = QStringLiteral("search/track");
if (!query.isEmpty()) query.append(" ");
if (!query.isEmpty()) query.append(QLatin1Char(' '));
query.append(title);
}
else {
resource = QStringLiteral("search/album");
if (!album.isEmpty()) {
if (!query.isEmpty()) query.append(" ");
if (!query.isEmpty()) query.append(QLatin1Char(' '));
query.append(album);
}
}
const ParamList params = ParamList() << Param("output", "json")
<< Param("q", query)
<< Param("limit", QString::number(kLimit));
const ParamList params = ParamList() << Param(QStringLiteral("output"), QStringLiteral("json"))
<< Param(QStringLiteral("q"), query)
<< Param(QStringLiteral("limit"), QString::number(kLimit));
QUrlQuery url_query;
for (const Param &param : params) {
url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(param.first)), QString::fromLatin1(QUrl::toPercentEncoding(param.second)));
}
QUrl url(kApiUrl + QStringLiteral("/") + resource);
QUrl url(QLatin1String(kApiUrl) + QLatin1Char('/') + resource);
url.setQuery(url_query);
QNetworkRequest req(url);
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
@@ -237,7 +239,7 @@ void DeezerCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id)
continue;
}
QString type = obj_album[QStringLiteral("type")].toString();
if (type != "album") {
if (type != QStringLiteral("album")) {
Error(QStringLiteral("Invalid Json reply, data array value album object has incorrect type returned"), obj_album);
continue;
}

View File

@@ -55,9 +55,6 @@ class DeezerCoverProvider : public JsonCoverProvider {
void Error(const QString &error, const QVariant &debug = QVariant()) override;
private:
static const char *kApiUrl;
static const int kLimit;
QList<QNetworkReply*> replies_;
};

View File

@@ -126,28 +126,28 @@ void DiscogsCoverProvider::FlushRequests() {
void DiscogsCoverProvider::SendSearchRequest(SharedPtr<DiscogsCoverSearchContext> search) {
ParamList params = ParamList() << Param("format", "album")
<< Param("artist", search->artist.toLower())
<< Param("release_title", search->album.toLower());
ParamList params = ParamList() << Param(QStringLiteral("format"), QStringLiteral("album"))
<< Param(QStringLiteral("artist"), search->artist.toLower())
<< Param(QStringLiteral("release_title"), search->album.toLower());
switch (search->type) {
case DiscogsCoverType::Master:
params << Param("type", "master");
params << Param(QStringLiteral("type"), QStringLiteral("master"));
break;
case DiscogsCoverType::Release:
params << Param("type", "release");
params << Param(QStringLiteral("type"), QStringLiteral("release"));
break;
}
QNetworkReply *reply = CreateRequest(QUrl(kUrlSearch), params);
QNetworkReply *reply = CreateRequest(QUrl(QString::fromLatin1(kUrlSearch)), params);
QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, search]() { HandleSearchReply(reply, search->id); });
}
QNetworkReply *DiscogsCoverProvider::CreateRequest(QUrl url, const ParamList &params_provided) {
ParamList params = ParamList() << Param("key", QByteArray::fromBase64(kAccessKeyB64))
<< Param("secret", QByteArray::fromBase64(kSecretKeyB64))
ParamList params = ParamList() << Param(QStringLiteral("key"), QString::fromLatin1(QByteArray::fromBase64(kAccessKeyB64)))
<< Param(QStringLiteral("secret"), QString::fromLatin1(QByteArray::fromBase64(kSecretKeyB64)))
<< params_provided;
QUrlQuery url_query;
@@ -157,8 +157,8 @@ QNetworkReply *DiscogsCoverProvider::CreateRequest(QUrl url, const ParamList &pa
using EncodedParam = QPair<QByteArray, QByteArray>;
for (const Param &param : params) {
EncodedParam encoded_param(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
query_items << QString(encoded_param.first + "=" + encoded_param.second);
url_query.addQueryItem(encoded_param.first, encoded_param.second);
query_items << QString::fromLatin1(encoded_param.first) + QLatin1Char('=') + QString::fromLatin1(encoded_param.second);
url_query.addQueryItem(QString::fromLatin1(encoded_param.first), QString::fromLatin1(encoded_param.second));
}
url.setQuery(url_query);
@@ -167,7 +167,7 @@ QNetworkReply *DiscogsCoverProvider::CreateRequest(QUrl url, const ParamList &pa
const QByteArray signature(Utilities::HmacSha256(QByteArray::fromBase64(kSecretKeyB64), data_to_sign));
// Add the signature to the request
url_query.addQueryItem(QStringLiteral("Signature"), QUrl::toPercentEncoding(signature.toBase64()));
url_query.addQueryItem(QStringLiteral("Signature"), QString::fromLatin1(QUrl::toPercentEncoding(QString::fromLatin1(signature.toBase64()))));
QNetworkRequest req(url);
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
@@ -427,7 +427,7 @@ void DiscogsCoverProvider::HandleReleaseReply(QNetworkReply *reply, const int se
continue;
}
QString type = obj_image[QStringLiteral("type")].toString();
if (type != "primary") {
if (type != QStringLiteral("primary")) {
continue;
}
int width = obj_image[QStringLiteral("width")].toInt();

View File

@@ -46,9 +46,11 @@
#include "albumcoverfetcher.h"
#include "lastfmcoverprovider.h"
const char *LastFmCoverProvider::kUrl = "https://ws.audioscrobbler.com/2.0/";
const char *LastFmCoverProvider::kApiKey = "211990b4c96782c05d1536e7219eb56e";
const char *LastFmCoverProvider::kSecret = "80fd738f49596e9709b1bf9319c444a8";
namespace {
constexpr char kUrl[] = "https://ws.audioscrobbler.com/2.0/";
constexpr char kApiKey[] = "211990b4c96782c05d1536e7219eb56e";
constexpr char kSecret[] = "80fd738f49596e9709b1bf9319c444a8";
} // namespace
LastFmCoverProvider::LastFmCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(QStringLiteral("Last.fm"), true, false, 1.0, true, false, app, network, parent) {}
@@ -74,21 +76,21 @@ bool LastFmCoverProvider::StartSearch(const QString &artist, const QString &albu
if (album.isEmpty() && !title.isEmpty()) {
method = QStringLiteral("track.search");
type = QStringLiteral("track");
if (!query.isEmpty()) query.append(" ");
if (!query.isEmpty()) query.append(QLatin1Char(' '));
query.append(title);
}
else {
method = QStringLiteral("album.search");
type = QStringLiteral("album");
if (!album.isEmpty()) {
if (!query.isEmpty()) query.append(" ");
if (!query.isEmpty()) query.append(QLatin1Char(' '));
query.append(album);
}
}
ParamList params = ParamList() << Param("api_key", kApiKey)
<< Param("lang", QLocale().name().left(2).toLower())
<< Param("method", method)
ParamList params = ParamList() << Param(QStringLiteral("api_key"), QLatin1String(kApiKey))
<< Param(QStringLiteral("lang"), QLocale().name().left(2).toLower())
<< Param(QStringLiteral("method"), method)
<< Param(type, query);
std::sort(params.begin(), params.end());
@@ -96,21 +98,21 @@ bool LastFmCoverProvider::StartSearch(const QString &artist, const QString &albu
QUrlQuery url_query;
QString data_to_sign;
for (const Param &param : params) {
url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(param.first)), QString::fromLatin1(QUrl::toPercentEncoding(param.second)));
data_to_sign += param.first + param.second;
}
data_to_sign += kSecret;
data_to_sign += QLatin1String(kSecret);
QByteArray const digest = QCryptographicHash::hash(data_to_sign.toUtf8(), QCryptographicHash::Md5);
QString signature = QString::fromLatin1(digest.toHex()).rightJustified(32, '0').toLower();
QString signature = QString::fromLatin1(digest.toHex()).rightJustified(32, QLatin1Char('0')).toLower();
url_query.addQueryItem(QUrl::toPercentEncoding(QStringLiteral("api_sig")), QUrl::toPercentEncoding(signature));
url_query.addQueryItem(QUrl::toPercentEncoding(QStringLiteral("format")), QUrl::toPercentEncoding(QStringLiteral("json")));
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(QStringLiteral("api_sig"))), QString::fromLatin1(QUrl::toPercentEncoding(signature)));
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(QStringLiteral("format"))), QString::fromLatin1(QUrl::toPercentEncoding(QStringLiteral("json"))));
QUrl url(kUrl);
QUrl url(QString::fromLatin1(kUrl));
QNetworkRequest req(url);
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
req.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
QNetworkReply *reply = network_->post(req, url_query.toString(QUrl::FullyEncoded).toUtf8());
replies_ << reply;
QObject::connect(reply, &QNetworkReply::finished, this, [this, reply, id, type]() { QueryFinished(reply, id, type); });
@@ -172,7 +174,7 @@ void LastFmCoverProvider::QueryFinished(QNetworkReply *reply, const int id, cons
QJsonValue value_matches;
if (type == "album") {
if (type == QStringLiteral("album")) {
if (obj_results.contains(QStringLiteral("albummatches"))) {
value_matches = obj_results[QStringLiteral("albummatches")];
}
@@ -182,7 +184,7 @@ void LastFmCoverProvider::QueryFinished(QNetworkReply *reply, const int id, cons
return;
}
}
else if (type == "track") {
else if (type == QStringLiteral("track")) {
if (obj_results.contains(QStringLiteral("trackmatches"))) {
value_matches = obj_results[QStringLiteral("trackmatches")];
}
@@ -234,7 +236,7 @@ void LastFmCoverProvider::QueryFinished(QNetworkReply *reply, const int id, cons
}
QString artist = obj[QStringLiteral("artist")].toString();
QString album;
if (type == "album") {
if (type == QStringLiteral("album")) {
album = obj[QStringLiteral("name")].toString();
}
@@ -308,7 +310,7 @@ QByteArray LastFmCoverProvider::GetReplyData(QNetworkReply *reply) {
if (json_obj.contains(QStringLiteral("error")) && json_obj.contains(QStringLiteral("message"))) {
int code = json_obj[QStringLiteral("error")].toInt();
QString message = json_obj[QStringLiteral("message")].toString();
error = "Error: " + QString::number(code) + ": " + message;
error = QStringLiteral("Error: ") + QString::number(code) + QStringLiteral(": ") + message;
}
}
if (error.isEmpty()) {
@@ -337,10 +339,10 @@ void LastFmCoverProvider::Error(const QString &error, const QVariant &debug) {
LastFmCoverProvider::LastFmImageSize LastFmCoverProvider::ImageSizeFromString(const QString &size) {
if (size == "small") return LastFmImageSize::Small;
else if (size == "medium") return LastFmImageSize::Medium;
else if (size == "large") return LastFmImageSize::Large;
else if (size == "extralarge") return LastFmImageSize::ExtraLarge;
if (size == QStringLiteral("small")) return LastFmImageSize::Small;
else if (size == QStringLiteral("medium")) return LastFmImageSize::Medium;
else if (size == QStringLiteral("large")) return LastFmImageSize::Large;
else if (size == QStringLiteral("extralarge")) return LastFmImageSize::ExtraLarge;
else return LastFmImageSize::Unknown;
}

View File

@@ -62,10 +62,6 @@ class LastFmCoverProvider : public JsonCoverProvider {
void Error(const QString &error, const QVariant &debug = QVariant()) override;
private:
static const char *kUrl;
static const char *kApiKey;
static const char *kSecret;
QList<QNetworkReply*> replies_;
};

View File

@@ -44,10 +44,12 @@
#include "jsoncoverprovider.h"
#include "musicbrainzcoverprovider.h"
const char *MusicbrainzCoverProvider::kReleaseSearchUrl = "https://musicbrainz.org/ws/2/release/";
const char *MusicbrainzCoverProvider::kAlbumCoverUrl = "https://coverartarchive.org/release/%1/front";
const int MusicbrainzCoverProvider::kLimit = 8;
const int MusicbrainzCoverProvider::kRequestsDelay = 1000;
namespace {
constexpr char kReleaseSearchUrl[] = "https://musicbrainz.org/ws/2/release/";
constexpr char kAlbumCoverUrl[] = "https://coverartarchive.org/release/%1/front";
constexpr int kLimit = 8;
constexpr int kRequestsDelay = 1000;
} // namespace
MusicbrainzCoverProvider::MusicbrainzCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(QStringLiteral("MusicBrainz"), true, false, 1.5, true, false, app, network, parent),
@@ -89,14 +91,14 @@ bool MusicbrainzCoverProvider::StartSearch(const QString &artist, const QString
void MusicbrainzCoverProvider::SendSearchRequest(const SearchRequest &request) {
QString query = QStringLiteral("release:\"%1\" AND artist:\"%2\"").arg(request.album.trimmed().replace('"', QLatin1String("\\\"")), request.artist.trimmed().replace('"', QLatin1String("\\\"")));
QString query = QStringLiteral("release:\"%1\" AND artist:\"%2\"").arg(request.album.trimmed().replace(QLatin1Char('"'), QLatin1String("\\\"")), request.artist.trimmed().replace(QLatin1Char('"'), QLatin1String("\\\"")));
QUrlQuery url_query;
url_query.addQueryItem(QStringLiteral("query"), query);
url_query.addQueryItem(QStringLiteral("limit"), QString::number(kLimit));
url_query.addQueryItem(QStringLiteral("fmt"), QStringLiteral("json"));
QUrl url(kReleaseSearchUrl);
QUrl url(QString::fromLatin1(kReleaseSearchUrl));
url.setQuery(url_query);
QNetworkRequest req(url);
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
@@ -214,7 +216,7 @@ void MusicbrainzCoverProvider::HandleSearchReply(QNetworkReply *reply, const int
QString album = obj_release[QStringLiteral("title")].toString();
CoverProviderSearchResult cover_result;
QUrl url(QString(kAlbumCoverUrl).arg(id));
QUrl url(QString::fromLatin1(kAlbumCoverUrl).arg(id));
cover_result.artist = artist;
cover_result.album = album;
cover_result.image_url = url;

View File

@@ -64,11 +64,6 @@ class MusicbrainzCoverProvider : public JsonCoverProvider {
void Error(const QString &error, const QVariant &debug = QVariant()) override;
private:
static const char *kReleaseSearchUrl;
static const char *kAlbumCoverUrl;
static const int kLimit;
static const int kRequestsDelay;
QTimer *timer_flush_requests_;
QQueue<SearchRequest> queue_search_requests_;
QList<QNetworkReply*> replies_;

View File

@@ -100,13 +100,13 @@ void MusixmatchCoverProvider::HandleSearchReply(QNetworkReply *reply, const int
return;
}
QByteArray data = reply->readAll();
const QByteArray data = reply->readAll();
if (data.isEmpty()) {
Error(QStringLiteral("Empty reply received from server."));
emit SearchFinished(id, results);
return;
}
QString content = data;
const QString content = QString::fromUtf8(data);
const QString data_begin = QStringLiteral("<script id=\"__NEXT_DATA__\" type=\"application/json\">");
const QString data_end = QStringLiteral("</script>");
if (!content.contains(data_begin) || !content.contains(data_end)) {

View File

@@ -39,6 +39,7 @@
#include "core/application.h"
#include "core/networkaccessmanager.h"
#include "core/logging.h"
#include "core/settings.h"
#include "utilities/timeconstants.h"
#include "albumcoverfetcher.h"
#include "jsoncoverprovider.h"
@@ -112,7 +113,7 @@ void OpenTidalCoverProvider::CancelSearch(const int id) {
void OpenTidalCoverProvider::LoadSession() {
QSettings s;
Settings s;
s.beginGroup(kSettingsGroup);
token_type_ = s.value("token_type").toString();
access_token_ = s.value("access_token").toString();
@@ -155,7 +156,7 @@ void OpenTidalCoverProvider::Login() {
login_in_progress_ = true;
last_login_attempt_ = QDateTime::currentDateTime();
QUrl url(kAuthUrl);
QUrl url(QString::fromLatin1(kAuthUrl));
QNetworkRequest req(url);
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
req.setRawHeader("Authorization", "Basic " + QByteArray(QByteArray::fromBase64(kApiClientIdB64) + ":" + QByteArray::fromBase64(kApiClientSecretB64)).toBase64());
@@ -208,7 +209,7 @@ void OpenTidalCoverProvider::LoginFinished(QNetworkReply *reply) {
login_time_ = QDateTime::currentDateTime().toSecsSinceEpoch();
expires_in_ = json_obj[QStringLiteral("expires_in")].toInt();
QSettings s;
Settings s;
s.beginGroup(kSettingsGroup);
s.setValue("token_type", token_type_);
s.setValue("access_token", access_token_);
@@ -293,23 +294,23 @@ void OpenTidalCoverProvider::SendSearchRequest(SearchRequestPtr search_request)
QString query = search_request->artist;
if (!search_request->album.isEmpty()) {
if (!query.isEmpty()) query.append(" ");
if (!query.isEmpty()) query.append(QLatin1Char(' '));
query.append(search_request->album);
}
else if (!search_request->title.isEmpty()) {
if (!query.isEmpty()) query.append(" ");
if (!query.isEmpty()) query.append(QLatin1Char(' '));
query.append(search_request->title);
}
QUrlQuery url_query;
url_query.addQueryItem(QStringLiteral("query"), QUrl::toPercentEncoding(query));
url_query.addQueryItem(QStringLiteral("query"), QString::fromUtf8(QUrl::toPercentEncoding(query)));
url_query.addQueryItem(QStringLiteral("limit"), QString::number(kLimit));
url_query.addQueryItem(QStringLiteral("countryCode"), QStringLiteral("US"));
QUrl url(QString(kApiUrl) + QStringLiteral("/search"));
QUrl url(QLatin1String(kApiUrl) + QStringLiteral("/search"));
url.setQuery(url_query);
QNetworkRequest req(url);
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/vnd.tidal.v1+json");
req.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/vnd.tidal.v1+json"));
req.setRawHeader("Authorization", token_type_.toUtf8() + " " + access_token_.toUtf8());
QNetworkReply *reply = network_->get(req);

View File

@@ -46,7 +46,9 @@
#include "jsoncoverprovider.h"
#include "qobuzcoverprovider.h"
constexpr int QobuzCoverProvider::kLimit = 10;
namespace {
constexpr int kLimit = 10;
}
QobuzCoverProvider::QobuzCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(QStringLiteral("Qobuz"), true, true, 2.0, true, true, app, network, parent),
@@ -71,34 +73,34 @@ bool QobuzCoverProvider::StartSearch(const QString &artist, const QString &album
QString query = artist;
if (album.isEmpty() && !title.isEmpty()) {
resource = QStringLiteral("track/search");
if (!query.isEmpty()) query.append(" ");
if (!query.isEmpty()) query.append(QLatin1Char(' '));
query.append(title);
}
else {
resource = QStringLiteral("album/search");
if (!album.isEmpty()) {
if (!query.isEmpty()) query.append(" ");
if (!query.isEmpty()) query.append(QLatin1Char(' '));
query.append(album);
}
}
ParamList params = ParamList() << Param("query", query)
<< Param("limit", QString::number(kLimit))
<< Param("app_id", service_->app_id().toUtf8());
ParamList params = ParamList() << Param(QStringLiteral("query"), query)
<< Param(QStringLiteral("limit"), QString::number(kLimit))
<< Param(QStringLiteral("app_id"), service_->app_id());
std::sort(params.begin(), params.end());
QUrlQuery url_query;
for (const Param &param : params) {
url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(param.first)), QString::fromLatin1(QUrl::toPercentEncoding(param.second)));
}
QUrl url(QString(QobuzService::kApiUrl) + QStringLiteral("/") + resource);
QUrl url(QLatin1String(QobuzService::kApiUrl) + QLatin1Char('/') + resource);
url.setQuery(url_query);
QNetworkRequest req(url);
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
req.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
req.setRawHeader("X-App-Id", service_->app_id().toUtf8());
req.setRawHeader("X-User-Auth-Token", service_->user_auth_token().toUtf8());
QNetworkReply *reply = network_->get(req);

View File

@@ -59,8 +59,6 @@ class QobuzCoverProvider : public JsonCoverProvider {
void Error(const QString &error, const QVariant &debug = QVariant()) override;
private:
static const int kLimit;
QobuzServicePtr service_;
QList<QNetworkReply*> replies_;
};

View File

@@ -45,6 +45,7 @@
#include "core/application.h"
#include "core/networkaccessmanager.h"
#include "core/logging.h"
#include "core/settings.h"
#include "utilities/randutils.h"
#include "utilities/timeconstants.h"
#include "internet/localredirectserver.h"
@@ -52,14 +53,16 @@
#include "jsoncoverprovider.h"
#include "spotifycoverprovider.h"
const char *SpotifyCoverProvider::kSettingsGroup = "Spotify";
const char *SpotifyCoverProvider::kOAuthAuthorizeUrl = "https://accounts.spotify.com/authorize";
const char *SpotifyCoverProvider::kOAuthAccessTokenUrl = "https://accounts.spotify.com/api/token";
const char *SpotifyCoverProvider::kOAuthRedirectUrl = "http://localhost:63111/";
const char *SpotifyCoverProvider::kClientIDB64 = "ZTZjY2Y2OTQ5NzY1NGE3NThjOTAxNWViYzdiMWQzMTc=";
const char *SpotifyCoverProvider::kClientSecretB64 = "N2ZlMDMxODk1NTBlNDE3ZGI1ZWQ1MzE3ZGZlZmU2MTE=";
const char *SpotifyCoverProvider::kApiUrl = "https://api.spotify.com/v1";
const int SpotifyCoverProvider::kLimit = 10;
namespace {
constexpr char kSettingsGroup[] = "Spotify";
constexpr char kOAuthAuthorizeUrl[] = "https://accounts.spotify.com/authorize";
constexpr char kOAuthAccessTokenUrl[] = "https://accounts.spotify.com/api/token";
constexpr char kOAuthRedirectUrl[] = "http://localhost:63111/";
constexpr char kClientIDB64[] = "ZTZjY2Y2OTQ5NzY1NGE3NThjOTAxNWViYzdiMWQzMTc=";
constexpr char kClientSecretB64[] = "N2ZlMDMxODk1NTBlNDE3ZGI1ZWQ1MzE3ZGZlZmU2MTE=";
constexpr char kApiUrl[] = "https://api.spotify.com/v1";
constexpr int kLimit = 10;
} // namespace
SpotifyCoverProvider::SpotifyCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(QStringLiteral("Spotify"), true, true, 2.5, true, true, app, network, parent),
@@ -70,7 +73,7 @@ SpotifyCoverProvider::SpotifyCoverProvider(Application *app, SharedPtr<NetworkAc
refresh_login_timer_.setSingleShot(true);
QObject::connect(&refresh_login_timer_, &QTimer::timeout, this, &SpotifyCoverProvider::RequestNewAccessToken);
QSettings s;
Settings s;
s.beginGroup(kSettingsGroup);
access_token_ = s.value("access_token").toString();
refresh_token_ = s.value("refresh_token").toString();
@@ -100,7 +103,7 @@ SpotifyCoverProvider::~SpotifyCoverProvider() {
void SpotifyCoverProvider::Authenticate() {
QUrl redirect_url(kOAuthRedirectUrl);
QUrl redirect_url(QString::fromLatin1(kOAuthRedirectUrl));
if (!server_) {
server_ = new LocalRedirectServer(this);
@@ -126,22 +129,22 @@ void SpotifyCoverProvider::Authenticate() {
}
code_verifier_ = Utilities::CryptographicRandomString(44);
code_challenge_ = QString(QCryptographicHash::hash(code_verifier_.toUtf8(), QCryptographicHash::Sha256).toBase64(QByteArray::Base64UrlEncoding));
if (code_challenge_.lastIndexOf(QChar('=')) == code_challenge_.length() - 1) {
code_challenge_ = QString::fromLatin1(QCryptographicHash::hash(code_verifier_.toUtf8(), QCryptographicHash::Sha256).toBase64(QByteArray::Base64UrlEncoding));
if (code_challenge_.lastIndexOf(QLatin1Char('=')) == code_challenge_.length() - 1) {
code_challenge_.chop(1);
}
const ParamList params = ParamList() << Param("client_id", QByteArray::fromBase64(kClientIDB64))
<< Param("response_type", "code")
<< Param("redirect_uri", redirect_url.toString())
<< Param("state", code_challenge_);
const ParamList params = ParamList() << Param(QStringLiteral("client_id"), QString::fromLatin1(QByteArray::fromBase64(kClientIDB64)))
<< Param(QStringLiteral("response_type"), QStringLiteral("code"))
<< Param(QStringLiteral("redirect_uri"), redirect_url.toString())
<< Param(QStringLiteral("state"), code_challenge_);
QUrlQuery url_query;
for (const Param &param : params) {
url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(param.first)), QString::fromLatin1(QUrl::toPercentEncoding(param.second)));
}
QUrl url(kOAuthAuthorizeUrl);
QUrl url(QString::fromLatin1(kOAuthAuthorizeUrl));
url.setQuery(url_query);
const bool result = QDesktopServices::openUrl(url);
@@ -160,7 +163,7 @@ void SpotifyCoverProvider::Deauthenticate() {
expires_in_ = 0;
login_time_ = 0;
QSettings s;
Settings s;
s.beginGroup(kSettingsGroup);
s.remove("access_token");
s.remove("refresh_token");
@@ -186,7 +189,7 @@ void SpotifyCoverProvider::RedirectArrived() {
else if (url_query.hasQueryItem(QStringLiteral("code")) && url_query.hasQueryItem(QStringLiteral("state"))) {
qLog(Debug) << "Spotify: Authorization URL Received" << url;
QString code = url_query.queryItemValue(QStringLiteral("code"));
QUrl redirect_url(kOAuthRedirectUrl);
QUrl redirect_url(QString::fromLatin1(kOAuthRedirectUrl));
redirect_url.setPort(server_->url().port());
RequestAccessToken(code, redirect_url);
}
@@ -212,17 +215,17 @@ void SpotifyCoverProvider::RequestAccessToken(const QString &code, const QUrl &r
refresh_login_timer_.stop();
ParamList params = ParamList() << Param("client_id", QByteArray::fromBase64(kClientIDB64))
<< Param("client_secret", QByteArray::fromBase64(kClientSecretB64));
ParamList params = ParamList() << Param(QStringLiteral("client_id"), QLatin1String(kClientIDB64))
<< Param(QStringLiteral("client_secret"), QLatin1String(kClientSecretB64));
if (!code.isEmpty() && !redirect_url.isEmpty()) {
params << Param("grant_type", "authorization_code");
params << Param("code", code);
params << Param("redirect_uri", redirect_url.toString());
params << Param(QStringLiteral("grant_type"), QStringLiteral("authorization_code"));
params << Param(QStringLiteral("code"), code);
params << Param(QStringLiteral("redirect_uri"), redirect_url.toString());
}
else if (!refresh_token_.isEmpty() && is_enabled()) {
params << Param("grant_type", "refresh_token");
params << Param("refresh_token", refresh_token_);
params << Param(QStringLiteral("grant_type"), QStringLiteral("refresh_token"));
params << Param(QStringLiteral("refresh_token"), refresh_token_);
}
else {
return;
@@ -230,14 +233,14 @@ void SpotifyCoverProvider::RequestAccessToken(const QString &code, const QUrl &r
QUrlQuery url_query;
for (const Param &param : params) {
url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(param.first)), QString::fromLatin1(QUrl::toPercentEncoding(param.second)));
}
QUrl new_url(kOAuthAccessTokenUrl);
QUrl new_url(QString::fromLatin1(kOAuthAccessTokenUrl));
QNetworkRequest req(new_url);
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QString auth_header_data = QByteArray::fromBase64(kClientIDB64) + QStringLiteral(":") + QByteArray::fromBase64(kClientSecretB64);
req.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
QString auth_header_data = QString::fromLatin1(QByteArray::fromBase64(kClientIDB64)) + QLatin1Char(':') + QString::fromLatin1(QByteArray::fromBase64(kClientSecretB64));
req.setRawHeader("Authorization", "Basic " + auth_header_data.toUtf8().toBase64());
QByteArray query = url_query.toString(QUrl::FullyEncoded).toUtf8();
@@ -334,7 +337,7 @@ void SpotifyCoverProvider::AccessTokenRequestFinished(QNetworkReply *reply) {
expires_in_ = json_obj[QStringLiteral("expires_in")].toInt();
login_time_ = QDateTime::currentDateTime().toSecsSinceEpoch();
QSettings s;
Settings s;
s.beginGroup(kSettingsGroup);
s.setValue("access_token", access_token_);
s.setValue("refresh_token", refresh_token_);
@@ -366,32 +369,32 @@ bool SpotifyCoverProvider::StartSearch(const QString &artist, const QString &alb
if (album.isEmpty() && !title.isEmpty()) {
type = QStringLiteral("track");
extract = QStringLiteral("tracks");
if (!query.isEmpty()) query.append(" ");
if (!query.isEmpty()) query.append(QLatin1Char(' '));
query.append(title);
}
else {
type = QStringLiteral("album");
extract = QStringLiteral("albums");
if (!album.isEmpty()) {
if (!query.isEmpty()) query.append(" ");
if (!query.isEmpty()) query.append(QLatin1Char(' '));
query.append(album);
}
}
ParamList params = ParamList() << Param("q", query)
<< Param("type", type)
<< Param("limit", QString::number(kLimit));
ParamList params = ParamList() << Param(QStringLiteral("q"), query)
<< Param(QStringLiteral("type"), type)
<< Param(QStringLiteral("limit"), QString::number(kLimit));
QUrlQuery url_query;
for (const Param &param : params) {
url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(param.first)), QString::fromLatin1(QUrl::toPercentEncoding(param.second)));
}
QUrl url(kApiUrl + QStringLiteral("/search"));
QUrl url(QLatin1String(kApiUrl) + QStringLiteral("/search"));
url.setQuery(url_query);
QNetworkRequest req(url);
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
req.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
req.setRawHeader("Authorization", "Bearer " + access_token_.toUtf8());
QNetworkReply *reply = network_->get(req);

View File

@@ -70,15 +70,6 @@ class SpotifyCoverProvider : public JsonCoverProvider {
void RequestAccessToken(const QString &code = QString(), const QUrl &redirect_url = QUrl());
private:
static const char *kSettingsGroup;
static const char *kClientIDB64;
static const char *kClientSecretB64;
static const char *kOAuthAuthorizeUrl;
static const char *kOAuthAccessTokenUrl;
static const char *kOAuthRedirectUrl;
static const char *kApiUrl;
static const int kLimit;
LocalRedirectServer *server_;
QStringList login_errors_;
QString code_verifier_;

View File

@@ -45,7 +45,9 @@
#include "jsoncoverprovider.h"
#include "tidalcoverprovider.h"
constexpr int TidalCoverProvider::kLimit = 10;
namespace {
constexpr int kLimit = 10;
}
TidalCoverProvider::TidalCoverProvider(Application *app, SharedPtr<NetworkAccessManager> network, QObject *parent)
: JsonCoverProvider(QStringLiteral("Tidal"), true, true, 2.5, true, true, app, network, parent),
@@ -72,31 +74,31 @@ bool TidalCoverProvider::StartSearch(const QString &artist, const QString &album
QString query = artist;
if (album.isEmpty() && !title.isEmpty()) {
resource = QStringLiteral("search/tracks");
if (!query.isEmpty()) query.append(" ");
if (!query.isEmpty()) query.append(QLatin1Char(' '));
query.append(title);
}
else {
resource = QStringLiteral("search/albums");
if (!album.isEmpty()) {
if (!query.isEmpty()) query.append(" ");
if (!query.isEmpty()) query.append(QLatin1Char(' '));
query.append(album);
}
}
ParamList params = ParamList() << Param("query", query)
<< Param("limit", QString::number(kLimit))
<< Param("countryCode", service_->country_code());
ParamList params = ParamList() << Param(QStringLiteral("query"), query)
<< Param(QStringLiteral("limit"), QString::number(kLimit))
<< Param(QStringLiteral("countryCode"), service_->country_code());
QUrlQuery url_query;
for (const Param &param : params) {
url_query.addQueryItem(QUrl::toPercentEncoding(param.first), QUrl::toPercentEncoding(param.second));
url_query.addQueryItem(QString::fromLatin1(QUrl::toPercentEncoding(param.first)), QString::fromLatin1(QUrl::toPercentEncoding(param.second)));
}
QUrl url(QString(TidalService::kApiUrl) + QStringLiteral("/") + resource);
QUrl url(QLatin1String(TidalService::kApiUrl) + QLatin1Char('/') + resource);
url.setQuery(url_query);
QNetworkRequest req(url);
req.setAttribute(QNetworkRequest::RedirectPolicyAttribute, QNetworkRequest::NoLessSafeRedirectPolicy);
req.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
req.setHeader(QNetworkRequest::ContentTypeHeader, QStringLiteral("application/x-www-form-urlencoded"));
if (service_->oauth() && !service_->access_token().isEmpty()) req.setRawHeader("authorization", "Bearer " + service_->access_token().toUtf8());
else if (!service_->session_id().isEmpty()) req.setRawHeader("X-Tidal-SessionId", service_->session_id().toUtf8());
@@ -252,7 +254,7 @@ void TidalCoverProvider::HandleSearchReply(QNetworkReply *reply, const int id) {
<< qMakePair(QStringLiteral("750x750"), QSize(750, 750))
<< qMakePair(QStringLiteral("640x640"), QSize(640, 640));
for (const QPair<QString, QSize> &cover_size : cover_sizes) {
QUrl cover_url(QStringLiteral("%1/images/%2/%3.jpg").arg(TidalService::kResourcesUrl, cover, cover_size.first));
QUrl cover_url(QStringLiteral("%1/images/%2/%3.jpg").arg(QLatin1String(TidalService::kResourcesUrl), cover).arg(cover_size.first));
cover_result.image_url = cover_url;
cover_result.image_size = cover_size.second;
results << cover_result;

View File

@@ -63,8 +63,6 @@ class TidalCoverProvider : public JsonCoverProvider {
void Error(const QString &error, const QVariant &debug = QVariant()) override;
private:
static const int kLimit;
TidalServicePtr service_;
QList<QNetworkReply*> replies_;
};