Update non optionnals sources to qt5

This commit is contained in:
Chocobozzz 2015-04-11 22:52:31 +02:00
parent ded70d6555
commit 8b226c2171
71 changed files with 714 additions and 658 deletions

View File

@ -28,6 +28,7 @@
#include <QCoreApplication>
#include <QDateTime>
#include <QStringList>
#include <QtMessageHandler>
#include <glib.h>
@ -43,7 +44,7 @@ const char* kDefaultLogLevels = "GstEnginePipeline:2,*:3";
static const char* kMessageHandlerMagic = "__logging_message__";
static const int kMessageHandlerMagicLength = strlen(kMessageHandlerMagic);
static QtMsgHandler sOriginalMessageHandler = nullptr;
static QtMessageHandler sOriginalMessageHandler = nullptr;
void GLog(const char* domain, int level, const char* message, void* user_data) {
switch (level) {
@ -67,9 +68,9 @@ void GLog(const char* domain, int level, const char* message, void* user_data) {
}
}
static void MessageHandler(QtMsgType type, const char* message) {
if (strncmp(kMessageHandlerMagic, message, kMessageHandlerMagicLength) == 0) {
fprintf(stderr, "%s\n", message + kMessageHandlerMagicLength);
static void MessageHandler(QtMsgType type, const QMessageLogContext &context, const QString &message) {
if (strncmp(kMessageHandlerMagic, message.toLocal8Bit().data(), kMessageHandlerMagicLength) == 0) {
fprintf(stderr, "%s\n", message.toLocal8Bit().data() + kMessageHandlerMagicLength);
return;
}
@ -88,7 +89,7 @@ static void MessageHandler(QtMsgType type, const char* message) {
break;
}
for (const QString& line : QString::fromLocal8Bit(message).split('\n')) {
for (const QString& line : message.split('\n')) {
CreateLogger(level, "unknown", -1) << line.toLocal8Bit().constData();
}
@ -106,7 +107,7 @@ void Init() {
// Catch other messages from Qt
if (!sOriginalMessageHandler) {
sOriginalMessageHandler = qInstallMsgHandler(MessageHandler);
sOriginalMessageHandler = qInstallMessageHandler(MessageHandler);
}
}
@ -204,9 +205,9 @@ QDebug CreateLogger(Level level, const QString& class_name, int line) {
QDebug ret(type);
ret.nospace() << kMessageHandlerMagic << QDateTime::currentDateTime()
.toString("hh:mm:ss.zzz")
.toAscii()
.toLatin1()
.constData() << level_name
<< function_line.leftJustified(32).toAscii().constData();
<< function_line.leftJustified(32).toLatin1().constData();
return ret.space();
}
@ -214,9 +215,9 @@ QDebug CreateLogger(Level level, const QString& class_name, int line) {
QString CXXDemangle(const QString& mangled_function) {
int status;
char* demangled_function = abi::__cxa_demangle(
mangled_function.toAscii().constData(), nullptr, nullptr, &status);
mangled_function.toLatin1().constData(), nullptr, nullptr, &status);
if (status == 0) {
QString ret = QString::fromAscii(demangled_function);
QString ret = QString::fromLatin1(demangled_function);
free(demangled_function);
return ret;
}
@ -257,7 +258,7 @@ void DumpStackTrace() {
backtrace_symbols(reinterpret_cast<void**>(&callstack), callstack_size);
// Start from 1 to skip ourself.
for (int i = 1; i < callstack_size; ++i) {
qLog(Debug) << DemangleSymbol(QString::fromAscii(symbols[i]));
qLog(Debug) << DemangleSymbol(QString::fromLatin1(symbols[i]));
}
free(symbols);
#else

View File

@ -265,13 +265,14 @@ QSqlDatabase Database::Connect() {
StaticInit();
{
QSqlQuery set_fts_tokenizer("SELECT fts3_tokenizer(:name, :pointer)", db);
QSqlQuery set_fts_tokenizer(db);
set_fts_tokenizer.prepare("SELECT fts3_tokenizer(:name, :pointer)");
set_fts_tokenizer.bindValue(":name", "unicode");
set_fts_tokenizer.bindValue(
":pointer", QByteArray(reinterpret_cast<const char*>(&sFTSTokenizer),
sizeof(&sFTSTokenizer)));
if (!set_fts_tokenizer.exec()) {
qLog(Warning) << "Couldn't register FTS3 tokenizer";
qLog(Warning) << "Couldn't register FTS3 tokenizer : " << set_fts_tokenizer.lastError();
}
// Implicit invocation of ~QSqlQuery() when leaving the scope
// to release any remaining database locks!
@ -290,12 +291,13 @@ QSqlDatabase Database::Connect() {
if (!injected_database_name_.isNull()) filename = injected_database_name_;
// Attach the db
QSqlQuery q("ATTACH DATABASE :filename AS :alias", db);
QSqlQuery q(db);
q.prepare("ATTACH DATABASE :filename AS :alias");
q.bindValue(":filename", filename);
q.bindValue(":alias", key);
if (!q.exec()) {
qFatal("Couldn't attach external database '%s'",
key.toAscii().constData());
key.toLatin1().constData());
}
}
@ -310,10 +312,10 @@ QSqlDatabase Database::Connect() {
attached_databases_[key].schema_.isEmpty())
continue;
// Find out if there are any tables in this database
QSqlQuery q(QString(
QSqlQuery q(db);
q.prepare(QString(
"SELECT ROWID FROM %1.sqlite_master"
" WHERE type='table'").arg(key),
db);
" WHERE type='table'").arg(key));
if (!q.exec() || !q.next()) {
q.finish();
ExecSchemaCommandsFromFile(db, attached_databases_[key].schema_, 0);
@ -360,7 +362,8 @@ void Database::RecreateAttachedDb(const QString& database_name) {
{
QSqlDatabase db(Connect());
QSqlQuery q("DETACH DATABASE :alias", db);
QSqlQuery q(db);
q.prepare("DETACH DATABASE :alias");
q.bindValue(":alias", database_name);
if (!q.exec()) {
qLog(Warning) << "Failed to detach database" << database_name;
@ -391,12 +394,13 @@ void Database::AttachDatabaseOnDbConnection(const QString& database_name,
AttachDatabase(database_name, database);
// Attach the db
QSqlQuery q("ATTACH DATABASE :filename AS :alias", db);
QSqlQuery q(db);
q.prepare("ATTACH DATABASE :filename AS :alias");
q.bindValue(":filename", database.filename_);
q.bindValue(":alias", database_name);
if (!q.exec()) {
qFatal("Couldn't attach external database '%s'",
database_name.toAscii().constData());
database_name.toLatin1().constData());
}
}
@ -405,7 +409,8 @@ void Database::DetachDatabase(const QString& database_name) {
{
QSqlDatabase db(Connect());
QSqlQuery q("DETACH DATABASE :alias", db);
QSqlQuery q(db);
q.prepare("DETACH DATABASE :alias");
q.bindValue(":alias", database_name);
if (!q.exec()) {
qLog(Warning) << "Failed to detach database" << database_name;
@ -448,10 +453,10 @@ void Database::UpdateDatabaseSchema(int version, QSqlDatabase& db) {
}
void Database::UrlEncodeFilenameColumn(const QString& table, QSqlDatabase& db) {
QSqlQuery select(QString("SELECT ROWID, filename FROM %1").arg(table), db);
QSqlQuery update(
QString("UPDATE %1 SET filename=:filename WHERE ROWID=:id").arg(table),
db);
QSqlQuery select(db);
select.prepare(QString("SELECT ROWID, filename FROM %1").arg(table));
QSqlQuery update(db);
update.prepare(QString("UPDATE %1 SET filename=:filename WHERE ROWID=:id").arg(table));
select.exec();
if (CheckErrors(select)) return;
while (select.next()) {
@ -545,12 +550,11 @@ QStringList Database::SongsTables(QSqlDatabase& db, int schema_version) const {
// look for the tables in attached dbs
for (const QString& key : attached_databases_.keys()) {
QSqlQuery q(
QString(
QSqlQuery q(db);
q.prepare(QString(
"SELECT NAME FROM %1.sqlite_master"
" WHERE type='table' AND name='songs' OR name LIKE '%songs'")
.arg(key),
db);
.arg(key));
if (q.exec()) {
while (q.next()) {
QString tab_name = key + "." + q.value(0).toString();
@ -587,7 +591,7 @@ bool Database::IntegrityCheck(QSqlDatabase db) {
bool ok = false;
bool error_reported = false;
// Ask for 10 error messages at most.
QSqlQuery q(QString("PRAGMA integrity_check(10)"), db);
QSqlQuery q("PRAGMA integrity_check(10)", db);
while (q.next()) {
QString message = q.value(0).toString();

View File

@ -183,12 +183,14 @@ void MergedProxyModel::SourceModelReset() {
// Delete all mappings
DeleteAllMappings();
// Reset the proxy
beginResetModel();
// Clear the containers
p_->mappings_.clear();
merge_points_.clear();
// Reset the proxy
reset();
endResetModel();
}
void MergedProxyModel::SubModelReset() {
@ -497,7 +499,8 @@ void MergedProxyModel::LayoutChanged() {
const int new_row = merge_points_[key].row();
if (old_row != new_row) {
reset();
beginResetModel();
endResetModel();
return;
}
}

View File

@ -29,6 +29,7 @@
#include "covers/albumcoverfetcher.h"
#include "engines/enginebase.h"
#include "engines/gstengine.h"
#include "engines/gstenginepipeline.h"
#include "globalsearch/searchprovider.h"
#include "internet/digitally/digitallyimportedclient.h"
#include "internet/core/geolocator.h"
@ -53,7 +54,6 @@ class GstEnginePipeline;
class QNetworkReply;
void RegisterMetaTypes() {
qRegisterMetaType<ColumnAlignmentMap>("ColumnAlignmentMap");
qRegisterMetaType<const char*>("const char*");
qRegisterMetaType<CoverSearchResult>("CoverSearchResult");
qRegisterMetaType<CoverSearchResults>("CoverSearchResults");

View File

@ -22,6 +22,7 @@
#include <QSyntaxHighlighter>
#include <QValidator>
#include <QTextEdit>
#include "core/song.h"

View File

@ -29,7 +29,7 @@
class PoTranslator : public QTranslator {
public:
QString translate(const char* context, const char* source_text,
const char* disambiguation = 0) const {
const char* disambiguation = 0, int n = -1) const {
QString ret = QTranslator::translate(context, source_text, disambiguation);
if (!ret.isEmpty()) return ret;
return QTranslator::translate(nullptr, source_text, disambiguation);

View File

@ -40,7 +40,6 @@ bool QxtGlobalShortcutBackend::DoRegister() {
void QxtGlobalShortcutBackend::AddShortcut(QAction* action) {
if (action->shortcut().isEmpty()) return;
QxtGlobalShortcut* shortcut = new QxtGlobalShortcut(action->shortcut(), this);
connect(shortcut, SIGNAL(activated()), action, SLOT(trigger()));
shortcuts_ << shortcut;

View File

@ -23,6 +23,7 @@
#include "globalshortcutbackend.h"
class QxtGlobalShortcut;
class QAction;
class QxtGlobalShortcutBackend : public GlobalShortcutBackend {
public:

View File

@ -24,6 +24,7 @@
#include <QNetworkReply>
#include <QStringList>
#include <QXmlStreamReader>
#include <QUrlQuery>
#include "core/closure.h"
#include "core/logging.h"
@ -79,14 +80,14 @@ bool AmazonCoverProvider::StartSearch(const QString& artist,
const QByteArray data_to_sign =
QString("GET\n%1\n%2\n%3")
.arg(url.host(), url.path(), query_items.join("&"))
.toAscii();
.toLatin1();
const QByteArray signature(Utilities::HmacSha256(
QByteArray::fromBase64(kSecretAccessKeyB64), data_to_sign));
// Add the signature to the request
encoded_args << EncodedArg("Signature",
QUrl::toPercentEncoding(signature.toBase64()));
url.setEncodedQueryItems(encoded_args);
QUrlQuery url_query;
url_query.addQueryItem("Signature", QUrl::toPercentEncoding(signature.toBase64()));
url.setQuery(url_query);
QNetworkReply* reply = network_->get(QNetworkRequest(url));
NewClosure(reply, SIGNAL(finished()), this,

View File

@ -22,6 +22,7 @@
#include <functional>
#include <QXmlStreamReader>
#include <QUrlQuery>
#include "core/closure.h"
#include "core/network.h"
@ -46,8 +47,10 @@ bool MusicbrainzCoverProvider::StartSearch(const QString& artist,
QString query = QString("release:\"%1\" AND artist:\"%2\"")
.arg(album.trimmed().replace('"', "\\\""))
.arg(artist.trimmed().replace('"', "\\\""));
url.addQueryItem("query", query);
url.addQueryItem("limit", "5");
QUrlQuery url_query;
url_query.addQueryItem("query", query);
url_query.addQueryItem("limit", "5");
url.setQuery(url_query);
QNetworkRequest request(url);
QNetworkReply* reply = network_->get(request);

View File

@ -5,9 +5,8 @@
<interface name='org.mpris.MediaPlayer2.TrackList'>
<method name='GetTracksMetadata'>
<arg direction='in' name='TrackIds' type='ao'/>
<arg direction='out' name='Metadata' type='aa{sv}'>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="TrackMetadata" />
</arg>
<arg direction='out' name='Metadata' type='aa{sv}'/>
<annotation name="com.trolltech.QtDBus.QtTypeName.Out0" value="TrackMetadata" />
</method>
<method name='AddTrack'>
<arg direction='in' name='Uri' type='s'/>
@ -25,19 +24,17 @@
<arg name='CurrentTrack' type='o'/>
</signal>
<signal name='TrackAdded'>
<arg name='Metadata' type='a{sv}'>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="TrackMetadata"/>
</arg>
<arg name='Metadata' type='a{sv}'/>
<arg name='AfterTrack' type='o'/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In0" value="TrackMetadata"/>
</signal>
<signal name='TrackRemoved'>
<arg name='TrackId' type='o'/>
</signal>
<signal name='TrackMetadataChanged'>
<arg name='TrackId' type='o'/>
<arg name='Metadata' type='a{sv}'>
<annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="TrackMetadata"/>
</arg>
<arg name='Metadata' type='a{sv}'/>
<annotation name="com.trolltech.QtDBus.QtTypeName.In1" value="TrackMetadata"/>
</signal>
<property name='Tracks' type='ao' access='read'/>
<property name='CanEditTracks' type='b' access='read'/>

View File

@ -36,11 +36,10 @@ DeviceDatabaseBackend::DeviceList DeviceDatabaseBackend::GetAllDevices() {
DeviceList ret;
QSqlQuery q(
"SELECT ROWID, unique_id, friendly_name, size, icon,"
QSqlQuery q(db);
q.prepare("SELECT ROWID, unique_id, friendly_name, size, icon,"
" transcode_mode, transcode_format"
" FROM devices",
db);
" FROM devices");
q.exec();
if (db_->CheckErrors(q)) return ret;
@ -65,13 +64,12 @@ int DeviceDatabaseBackend::AddDevice(const Device& device) {
ScopedTransaction t(&db);
// Insert the device into the devices table
QSqlQuery q(
"INSERT INTO devices ("
QSqlQuery q(db);
q.prepare("INSERT INTO devices ("
" unique_id, friendly_name, size, icon,"
" transcode_mode, transcode_format)"
" VALUES (:unique_id, :friendly_name, :size, :icon,"
" :transcode_mode, :transcode_format)",
db);
" :transcode_mode, :transcode_format)");
q.bindValue(":unique_id", device.unique_id_);
q.bindValue(":friendly_name", device.friendly_name_);
q.bindValue(":size", device.size_);
@ -103,7 +101,8 @@ void DeviceDatabaseBackend::RemoveDevice(int id) {
ScopedTransaction t(&db);
// Remove the device from the devices table
QSqlQuery q("DELETE FROM devices WHERE ROWID=:id", db);
QSqlQuery q(db);
q.prepare("DELETE FROM devices WHERE ROWID=:id");
q.bindValue(":id", id);
q.exec();
if (db_->CheckErrors(q)) return;
@ -125,14 +124,13 @@ void DeviceDatabaseBackend::SetDeviceOptions(int id,
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(
"UPDATE devices"
QSqlQuery q(db);
q.prepare("UPDATE devices"
" SET friendly_name=:friendly_name,"
" icon=:icon_name,"
" transcode_mode=:transcode_mode,"
" transcode_format=:transcode_format"
" WHERE ROWID=:id",
db);
" WHERE ROWID=:id");
q.bindValue(":friendly_name", friendly_name);
q.bindValue(":icon_name", icon_name);
q.bindValue(":transcode_mode", mode);

View File

@ -155,7 +155,7 @@ void DeviceProperties::UpdateHardwareInfo() {
AddHardwareInfo(row++, tr("Model"), lister->DeviceModel(id));
AddHardwareInfo(row++, tr("Manufacturer"), lister->DeviceManufacturer(id));
for (const QString& key : info.keys()) {
AddHardwareInfo(row++, tr(key.toAscii()), info[key].toString());
AddHardwareInfo(row++, tr(key.toLatin1()), info[key].toString());
}
ui_->hardware_info->sortItems(0);

View File

@ -709,7 +709,7 @@ GstElement* GstEngine::CreateElement(const QString& factoryName,
QString name = factoryName + "-" + QString::number(next_element_id_++);
GstElement* element = gst_element_factory_make(
factoryName.toAscii().constData(), name.toAscii().constData());
factoryName.toLatin1().constData(), name.toLatin1().constData());
if (!element) {
emit Error(QString(

View File

@ -413,7 +413,7 @@ bool GstEnginePipeline::InitFromString(const QString& pipeline) {
pipeline_ = gst_pipeline_new("pipeline");
GstElement* new_bin =
CreateDecodeBinFromString(pipeline.toAscii().constData());
CreateDecodeBinFromString(pipeline.toLatin1().constData());
if (!new_bin) {
return false;
}

View File

@ -28,8 +28,8 @@ GlobalSearchSettingsPage::GlobalSearchSettingsPage(SettingsDialog* dialog)
: SettingsPage(dialog), ui_(new Ui::GlobalSearchSettingsPage) {
ui_->setupUi(this);
ui_->sources->header()->setResizeMode(0, QHeaderView::Stretch);
ui_->sources->header()->setResizeMode(1, QHeaderView::ResizeToContents);
ui_->sources->header()->setSectionResizeMode(0, QHeaderView::Stretch);
ui_->sources->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
warning_icon_ = IconLoader::Load("dialog-warning");

View File

@ -22,9 +22,10 @@
#include <cmath>
#include <limits>
#include <qjson/parser.h>
#include <QStringList>
#include <QJsonParseError>
#include <QJsonDocument>
#include <QJsonObject>
#include "core/closure.h"
#include "core/logging.h"
@ -97,16 +98,15 @@ void Geolocator::RequestFinished(QNetworkReply* reply) {
return;
}
QJson::Parser parser;
bool ok = false;
QVariant result = parser.parse(reply, &ok);
if (!ok) {
QJsonParseError error;
QJsonDocument json_document = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
emit Finished(LatLng());
return;
}
QVariantMap map = result.toMap();
QString latlng = map["latlng"].toString();
QJsonObject json_object = json_document.object();
QString latlng = json_object["latlng"].toString();
LatLng ll(latlng);
emit Finished(ll);

View File

@ -29,8 +29,8 @@ InternetShowSettingsPage::InternetShowSettingsPage(SettingsDialog* parent)
: SettingsPage(parent), ui_(new Ui::InternetShowSettingsPage) {
ui_->setupUi(this);
ui_->sources->header()->setResizeMode(0, QHeaderView::Stretch);
ui_->sources->header()->setResizeMode(1, QHeaderView::ResizeToContents);
ui_->sources->header()->setSectionResizeMode(0, QHeaderView::Stretch);
ui_->sources->header()->setSectionResizeMode(1, QHeaderView::ResizeToContents);
}
void InternetShowSettingsPage::Load() {

View File

@ -23,8 +23,10 @@
#include <QDesktopServices>
#include <QStringList>
#include <QUrl>
#include <qjson/parser.h>
#include <QUrlQuery>
#include <QJsonParseError>
#include <QJsonDocument>
#include <QJsonObject>
#include "core/closure.h"
#include "core/logging.h"
@ -49,24 +51,29 @@ void OAuthenticator::StartAuthorisation(const QString& oauth_endpoint,
server->Listen();
QUrl url = QUrl(oauth_endpoint);
url.addQueryItem("response_type", "code");
url.addQueryItem("client_id", client_id_);
QUrlQuery url_query;
url_query.addQueryItem("response_type", "code");
url_query.addQueryItem("client_id", client_id_);
QUrl redirect_url;
QUrlQuery redirect_url_query;
const QString port = QString::number(server->url().port());
if (redirect_style_ == RedirectStyle::REMOTE) {
redirect_url = QUrl(kRemoteURL);
redirect_url.addQueryItem("port", port);
redirect_url_query.addQueryItem("port", port);
} else if (redirect_style_ == RedirectStyle::REMOTE_WITH_STATE) {
redirect_url = QUrl(kRemoteURL);
url.addQueryItem("state", port);
url_query.addQueryItem("state", port);
} else {
redirect_url = server->url();
}
url.addQueryItem("redirect_uri", redirect_url.toString());
url.addQueryItem("scope", scope);
url_query.addQueryItem("redirect_uri", redirect_url.toString());
url_query.addQueryItem("scope", scope);
url.setQuery(url_query);
redirect_url.setQuery(redirect_url_query);
NewClosure(server, SIGNAL(Finished()), this, &OAuthenticator::RedirectArrived,
server, redirect_url);
@ -78,7 +85,7 @@ void OAuthenticator::RedirectArrived(LocalRedirectServer* server, QUrl url) {
server->deleteLater();
QUrl request_url = server->request_url();
qLog(Debug) << Q_FUNC_INFO << request_url;
RequestAccessToken(request_url.queryItemValue("code").toUtf8(), url);
RequestAccessToken(QUrlQuery(request_url).queryItemValue("code").toUtf8(), url);
}
QByteArray OAuthenticator::ParseHttpRequest(const QByteArray& request) const {
@ -126,19 +133,20 @@ void OAuthenticator::FetchAccessTokenFinished(QNetworkReply* reply) {
return;
}
QJson::Parser parser;
bool ok = false;
QVariantMap result = parser.parse(reply, &ok).toMap();
if (!ok) {
QJsonParseError error;
QJsonDocument json_document = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qLog(Error) << "Failed to parse oauth reply";
return;
}
qLog(Debug) << result;
QJsonObject json_result = json_document.object();
qLog(Debug) << json_result;
access_token_ = result["access_token"].toString();
refresh_token_ = result["refresh_token"].toString();
SetExpiryTime(result["expires_in"].toInt());
access_token_ = json_result["access_token"].toString();
refresh_token_ = json_result["refresh_token"].toString();
SetExpiryTime(json_result["expires_in"].toInt());
emit Finished();
}
@ -178,14 +186,13 @@ void OAuthenticator::SetExpiryTime(int expires_in_seconds) {
void OAuthenticator::RefreshAccessTokenFinished(QNetworkReply* reply) {
reply->deleteLater();
QJson::Parser parser;
bool ok = false;
QVariantMap result = parser.parse(reply, &ok).toMap();
access_token_ = result["access_token"].toString();
if (result.contains("refresh_token")) {
refresh_token_ = result["refresh_token"].toString();
QJsonObject json_result = QJsonDocument::fromJson(reply->readAll()).object();
access_token_ = json_result["access_token"].toString();
if (json_result.contains("refresh_token")) {
refresh_token_ = json_result["refresh_token"].toString();
}
SetExpiryTime(result["expires_in"].toInt());
SetExpiryTime(json_result["expires_in"].toInt());
emit Finished();
}

View File

@ -19,10 +19,11 @@
#include "digitallyimportedclient.h"
#include <qjson/parser.h>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include "core/logging.h"
#include "core/network.h"
@ -52,7 +53,7 @@ void DigitallyImportedClient::SetAuthorisationHeader(
req->setRawHeader("Authorization", "Basic " +
QString("%1:%2")
.arg(kApiUsername, kApiPassword)
.toAscii()
.toLatin1()
.toBase64());
}
@ -82,32 +83,30 @@ DigitallyImportedClient::AuthReply DigitallyImportedClient::ParseAuthReply(
return ret;
}
QJson::Parser parser;
QVariantMap data = parser.parse(reply).toMap();
QJsonObject json_root_object = QJsonDocument::fromJson(reply->readAll()).object();
if (!data.contains("subscriptions")) {
if (json_root_object["subscriptions"].isUndefined()) {
return ret;
}
QVariantList subscriptions =
data.value("subscriptions", QVariantList()).toList();
if (subscriptions.isEmpty() ||
subscriptions[0].toMap().value("status").toString() != "active") {
QJsonArray json_subscriptions = json_root_object["subscriptions"].toArray();
if (json_subscriptions.isEmpty() ||
json_subscriptions[0].toObject()["status"].toString() != "active") {
ret.error_reason_ = tr("You do not have an active subscription");
return ret;
}
if (!data.contains("first_name") || !data.contains("last_name") ||
!subscriptions[0].toMap().contains("expires_on") ||
!data.contains("listen_key"))
if (json_root_object["first_name"].isUndefined() || json_root_object["last_name"].isUndefined() ||
json_subscriptions[0].toObject()["expires_on"].isUndefined() ||
json_root_object["listen_key"].isUndefined())
return ret;
ret.success_ = true;
ret.first_name_ = data["first_name"].toString();
ret.last_name_ = data["last_name"].toString();
ret.first_name_ = json_root_object["first_name"].toString();
ret.last_name_ = json_root_object["last_name"].toString();
ret.expires_ = QDateTime::fromString(
subscriptions[0].toMap()["expires_on"].toString(), Qt::ISODate);
ret.listen_hash_ = data["listen_key"].toString();
json_subscriptions[0].toObject()["expires_on"].toString(), Qt::ISODate);
ret.listen_hash_ = json_root_object["listen_key"].toString();
return ret;
}
@ -123,30 +122,28 @@ DigitallyImportedClient::ChannelList DigitallyImportedClient::ParseChannelList(
QNetworkReply* reply) const {
ChannelList ret;
QJson::Parser parser;
QVariantMap data = parser.parse(reply).toMap();
QJsonObject json_root_object = QJsonDocument::fromJson(reply->readAll()).object();
if (!data.contains("channel_filters")) return ret;
if (json_root_object["channel_filters"].isUndefined()) return ret;
QVariantList filters = data["channel_filters"].toList();
QJsonArray json_filters = json_root_object["channel_filters"].toArray();
for (const QVariant& filter : filters) {
for (const QJsonValue & filter: json_filters) {
// Find the filter called "All"
QVariantMap filter_map = filter.toMap();
if (filter_map.value("name", QString()).toString() != "All") continue;
QJsonObject json_filter = filter.toObject();
if (json_filter["name"].toString() != "All") continue;
// Add all its stations to the result
QVariantList channels =
filter_map.value("channels", QVariantList()).toList();
for (const QVariant& channel_var : channels) {
QVariantMap channel_map = channel_var.toMap();
QJsonArray json_channels = json_filter["channels"].toArray();
for (const QJsonValue& channel_var : json_channels) {
QJsonObject json_channel = channel_var.toObject();
Channel channel;
channel.art_url_ = QUrl(channel_map.value("asset_url").toString());
channel.description_ = channel_map.value("description").toString();
channel.director_ = channel_map.value("channel_director").toString();
channel.key_ = channel_map.value("key").toString();
channel.name_ = channel_map.value("name").toString();
channel.art_url_ = QUrl(json_channel["asset_url"].toString());
channel.description_ = json_channel["description"].toString();
channel.director_ = json_channel["channel_director"].toString();
channel.key_ = json_channel["key"].toString();
channel.name_ = json_channel["name"].toString();
ret << channel;
}

View File

@ -35,9 +35,11 @@
#include <QNetworkRequest>
#include <QPushButton>
#include <QTimer>
#include <qjson/parser.h>
#include <qjson/serializer.h>
#include <QUrlQuery>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QJsonArray>
#include "qtiocompressor.h"
@ -215,7 +217,7 @@ int GroovesharkService::SimpleSearch(const QString& query) {
void GroovesharkService::SimpleSearchFinished(QNetworkReply* reply, int id) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
SongList songs = ExtractSongs(result);
emit SimpleSearchResults(id, songs);
}
@ -238,12 +240,12 @@ int GroovesharkService::SearchAlbums(const QString& query) {
void GroovesharkService::SearchAlbumsFinished(QNetworkReply* reply, int id) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QVariantList albums = result["albums"].toList();
QJsonObject result = ExtractResult(reply).object();
QJsonArray json_albums = result["albums"].toArray();
QList<quint64> ret;
for (const QVariant& v : albums) {
quint64 album_id = v.toMap()["AlbumID"].toULongLong();
for (const QJsonValue& v : json_albums) {
quint64 album_id = v.toObject()["AlbumID"].toString().toULongLong();
GetAlbumSongs(album_id);
ret << album_id;
}
@ -263,7 +265,7 @@ void GroovesharkService::GetAlbumSongs(quint64 album_id) {
void GroovesharkService::GetAlbumSongsFinished(QNetworkReply* reply,
quint64 album_id) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
SongList songs = ExtractSongs(result);
emit AlbumSongsLoaded(album_id, songs);
@ -291,7 +293,7 @@ void GroovesharkService::SearchSongsFinished(QNetworkReply* reply) {
if (reply != last_search_reply_) return;
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
SongList songs = ExtractSongs(result);
app_->task_manager()->SetTaskFinished(task_search_id_);
task_search_id_ = 0;
@ -311,7 +313,7 @@ void GroovesharkService::InitCountry() {
// Get country info
QNetworkReply* reply_country = CreateRequest("getCountry", QList<Param>());
if (WaitForReply(reply_country)) {
country_ = ExtractResult(reply_country);
country_ = ExtractResult(reply_country).object().toVariantMap();
}
reply_country->deleteLater();
}
@ -332,12 +334,12 @@ QUrl GroovesharkService::GetStreamingUrlFromSongId(const QString& song_id,
reply->deleteLater();
if (reply_has_timeouted) return QUrl();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
server_id->clear();
server_id->append(result["StreamServerID"].toString());
stream_key->clear();
stream_key->append(result["StreamKey"].toString());
*length_nanosec = result["uSecs"].toLongLong() * 1000;
*length_nanosec = result["uSecs"].toString().toLongLong() * 1000;
// Keep in mind that user has request to listen to this song
last_songs_ids_.append(song_id.toInt());
last_artists_ids_.append(artist_id.toInt());
@ -375,7 +377,7 @@ void GroovesharkService::SessionCreated(QNetworkReply* reply) {
return;
}
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
if (!result["success"].toBool()) {
qLog(Error) << "Grooveshark returned an error during session creation";
}
@ -397,7 +399,7 @@ void GroovesharkService::AuthenticateSession() {
void GroovesharkService::Authenticated(QNetworkReply* reply) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
// Check if the user has been authenticated correctly
QString error;
if (!result["success"].toBool() || result["UserID"].toInt() == 0) {
@ -700,7 +702,7 @@ void GroovesharkService::RetrieveUserPlaylists() {
void GroovesharkService::UserPlaylistsRetrieved(QNetworkReply* reply) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
QList<PlaylistInfo> playlists = ExtractPlaylistInfo(result);
for (const PlaylistInfo& playlist_info : playlists) {
@ -737,7 +739,7 @@ void GroovesharkService::PlaylistSongsRetrieved(QNetworkReply* reply,
: &playlists_[playlist_id];
playlist_info->item_->removeRows(0, playlist_info->item_->rowCount());
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
SongList songs = ExtractSongs(result);
SortSongsAlphabeticallyIfNeeded(&songs);
@ -778,7 +780,7 @@ void GroovesharkService::UserFavoritesRetrieved(QNetworkReply* reply,
favorites_->removeRows(0, favorites_->rowCount());
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
SongList songs = ExtractSongs(result);
SortSongsAlphabeticallyIfNeeded(&songs);
@ -812,7 +814,7 @@ void GroovesharkService::UserLibrarySongsRetrieved(QNetworkReply* reply,
library_->removeRows(0, library_->rowCount());
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
SongList songs = ExtractSongs(result);
SortSongsAlphabeticallyIfNeeded(&songs);
@ -841,7 +843,7 @@ void GroovesharkService::RetrievePopularSongsMonth() {
void GroovesharkService::PopularSongsMonthRetrieved(QNetworkReply* reply) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
SongList songs = ExtractSongs(result);
app_->task_manager()->IncreaseTaskProgress(task_popular_id_, 50, 100);
@ -867,7 +869,7 @@ void GroovesharkService::RetrievePopularSongsToday() {
void GroovesharkService::PopularSongsTodayRetrieved(QNetworkReply* reply) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
SongList songs = ExtractSongs(result);
app_->task_manager()->IncreaseTaskProgress(task_popular_id_, 50, 100);
@ -893,7 +895,7 @@ void GroovesharkService::RetrieveSubscribedPlaylists() {
void GroovesharkService::SubscribedPlaylistsRetrieved(QNetworkReply* reply) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
QList<PlaylistInfo> playlists = ExtractPlaylistInfo(result);
for (const PlaylistInfo& playlist_info : playlists) {
@ -924,9 +926,10 @@ void GroovesharkService::RetrieveAutoplayTags() {
void GroovesharkService::AutoplayTagsRetrieved(QNetworkReply* reply) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QVariantMap::const_iterator it;
QJsonObject result = ExtractResult(reply).object();
QJsonObject::const_iterator it;
if (!stations_) return;
for (it = result.constBegin(); it != result.constEnd(); ++it) {
int id = it.key().toInt();
QString name = it.value().toString().toLower();
@ -955,9 +958,9 @@ Song GroovesharkService::StartAutoplayTag(int tag_id,
reply->deleteLater();
if (reply_has_timeouted) return Song();
QVariantMap result = ExtractResult(reply);
autoplay_state = result["autoplayState"].toMap();
return ExtractSong(result["nextSong"].toMap());
QJsonObject result = ExtractResult(reply).object();
autoplay_state = result["autoplayState"].toObject().toVariantMap();
return ExtractSong(result["nextSong"].toObject());
}
Song GroovesharkService::StartAutoplay(QVariantMap& autoplay_state) {
@ -978,9 +981,9 @@ Song GroovesharkService::StartAutoplay(QVariantMap& autoplay_state) {
reply->deleteLater();
if (reply_has_timeouted) return Song();
QVariantMap result = ExtractResult(reply);
autoplay_state = result["autoplayState"].toMap();
return ExtractSong(result["nextSong"].toMap());
QJsonObject result = ExtractResult(reply).object();
autoplay_state = result["autoplayState"].toObject().toVariantMap();
return ExtractSong(result["nextSong"].toObject());
}
Song GroovesharkService::GetAutoplaySong(QVariantMap& autoplay_state) {
@ -992,9 +995,9 @@ Song GroovesharkService::GetAutoplaySong(QVariantMap& autoplay_state) {
reply->deleteLater();
if (reply_has_timeouted) return Song();
QVariantMap result = ExtractResult(reply);
autoplay_state = result["autoplayState"].toMap();
return ExtractSong(result["nextSong"].toMap());
QJsonObject result = ExtractResult(reply).object();
autoplay_state = result["autoplayState"].toObject().toVariantMap();
return ExtractSong(result["nextSong"].toObject());
}
void GroovesharkService::MarkStreamKeyOver30Secs(const QString& stream_key,
@ -1010,7 +1013,7 @@ void GroovesharkService::MarkStreamKeyOver30Secs(const QString& stream_key,
void GroovesharkService::StreamMarked(QNetworkReply* reply) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
if (!result["success"].toBool()) {
qLog(Warning) << "Grooveshark markStreamKeyOver30Secs failed";
}
@ -1030,7 +1033,7 @@ void GroovesharkService::MarkSongComplete(const QString& song_id,
void GroovesharkService::SongMarkedAsComplete(QNetworkReply* reply) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
if (!result["success"].toBool()) {
qLog(Warning) << "Grooveshark markSongComplete failed";
}
@ -1177,8 +1180,8 @@ void GroovesharkService::GetSongUrlToShare(int song_id) {
void GroovesharkService::SongUrlToShareReceived(QNetworkReply* reply) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
if (!result["url"].isValid()) return;
QJsonObject result = ExtractResult(reply).object();
if (result["url"].isUndefined()) return;
QString url = result["url"].toString();
ShowUrlBox(tr("Grooveshark song's URL"), url);
}
@ -1199,8 +1202,8 @@ void GroovesharkService::GetPlaylistUrlToShare(int playlist_id) {
void GroovesharkService::PlaylistUrlToShareReceived(QNetworkReply* reply) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
if (!result["url"].isValid()) return;
QJsonObject result = ExtractResult(reply).object();
if (result["url"].isUndefined()) return;
QString url = result["url"].toString();
ShowUrlBox(tr("Grooveshark playlist's URL"), url);
}
@ -1249,7 +1252,7 @@ void GroovesharkService::PlaylistSongsSet(QNetworkReply* reply, int playlist_id,
reply->deleteLater();
app_->task_manager()->SetTaskFinished(task_id);
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
if (!result["success"].toBool()) {
qLog(Warning) << "Grooveshark setPlaylistSongs failed";
return;
@ -1289,8 +1292,8 @@ void GroovesharkService::CreateNewPlaylist() {
void GroovesharkService::NewPlaylistCreated(QNetworkReply* reply,
const QString& name) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
if (!result["success"].toBool() || !result["playlistID"].isValid()) {
QJsonObject result = ExtractResult(reply).object();
if (!result["success"].toBool() || result["playlistID"].isUndefined()) {
qLog(Warning) << "Grooveshark createPlaylist failed";
return;
}
@ -1336,7 +1339,7 @@ void GroovesharkService::DeletePlaylist(int playlist_id) {
void GroovesharkService::PlaylistDeleted(QNetworkReply* reply,
int playlist_id) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
if (!result["success"].toBool()) {
qLog(Warning) << "Grooveshark deletePlaylist failed";
return;
@ -1384,7 +1387,7 @@ void GroovesharkService::RenamePlaylist(int playlist_id) {
void GroovesharkService::PlaylistRenamed(QNetworkReply* reply, int playlist_id,
const QString& new_name) {
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
if (!result["success"].toBool()) {
qLog(Warning) << "Grooveshark renamePlaylist failed";
return;
@ -1411,7 +1414,7 @@ void GroovesharkService::UserFavoriteSongAdded(QNetworkReply* reply,
reply->deleteLater();
app_->task_manager()->SetTaskFinished(task_id);
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
if (!result["success"].toBool()) {
qLog(Warning) << "Grooveshark addUserFavoriteSong failed";
return;
@ -1447,7 +1450,7 @@ void GroovesharkService::UserLibrarySongAdded(QNetworkReply* reply,
reply->deleteLater();
app_->task_manager()->SetTaskFinished(task_id);
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
if (!result["success"].toBool()) {
qLog(Warning) << "Grooveshark addUserLibrarySongs failed";
return;
@ -1536,7 +1539,7 @@ void GroovesharkService::SongsRemovedFromFavorites(QNetworkReply* reply,
app_->task_manager()->SetTaskFinished(task_id);
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
if (!result["success"].toBool()) {
qLog(Warning) << "Grooveshark removeUserFavoriteSongs failed";
return;
@ -1595,7 +1598,7 @@ void GroovesharkService::SongsRemovedFromLibrary(QNetworkReply* reply,
app_->task_manager()->SetTaskFinished(task_id);
reply->deleteLater();
QVariantMap result = ExtractResult(reply);
QJsonObject result = ExtractResult(reply).object();
if (!result["success"].toBool()) {
qLog(Warning) << "Grooveshark removeUserLibrarySongs failed";
return;
@ -1606,11 +1609,12 @@ void GroovesharkService::SongsRemovedFromLibrary(QNetworkReply* reply,
QNetworkReply* GroovesharkService::CreateRequest(const QString& method_name,
const QList<Param>& params,
bool use_https) {
QVariantMap request_params;
request_params.insert("method", method_name);
QJsonDocument json_document;
QJsonObject json_request_params;
json_request_params.insert("method", QJsonValue(method_name));
QVariantMap header;
header.insert("wsKey", kApiKey);
QJsonObject json_header;
json_header.insert("wsKey", QJsonValue(kApiKey));
if (session_id_.isEmpty()) {
if (method_name != "startSession") {
// It's normal to not have a session_id when calling startSession.
@ -1618,26 +1622,28 @@ QNetworkReply* GroovesharkService::CreateRequest(const QString& method_name,
qLog(Warning) << "Session ID is empty: will not be added to query";
}
} else {
header.insert("sessionID", session_id_);
json_header.insert("sessionID", QJsonValue(session_id_));
}
request_params.insert("header", header);
json_request_params["header"] = json_header;
QVariantMap parameters;
QJsonObject json_parameters;
for (const Param& param : params) {
parameters.insert(param.first, param.second);
json_parameters.insert(param.first, QJsonValue(param.second.toString()));
}
request_params.insert("parameters", parameters);
json_request_params["parameters"] = json_parameters;
QJson::Serializer serializer;
QByteArray post_params = serializer.serialize(request_params);
json_document.setObject(json_request_params);
QByteArray post_params = json_document.toBinaryData();
QUrl url(kUrl);
if (use_https) {
url.setScheme("https");
}
url.setQueryItems(
QUrlQuery url_query;
url_query.setQueryItems(
QList<QPair<QString, QString>>() << QPair<QString, QString>(
"sig", Utilities::HmacMd5(api_key_, post_params).toHex()));
url.setQuery(url_query);
QNetworkRequest req(url);
QNetworkReply* reply = network_->post(req, post_params);
@ -1673,20 +1679,24 @@ bool GroovesharkService::WaitForReply(QNetworkReply* reply) {
return true;
}
QVariantMap GroovesharkService::ExtractResult(QNetworkReply* reply) {
QJson::Parser parser;
bool ok;
QVariantMap result = parser.parse(reply, &ok).toMap();
if (!ok) {
QJsonDocument GroovesharkService::ExtractResult(QNetworkReply* reply) {
reply->deleteLater();
QJsonParseError error;
QJsonDocument json_document = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qLog(Error) << "Error while parsing Grooveshark result";
}
QVariantList errors = result["errors"].toList();
QVariantList::iterator it;
for (it = errors.begin(); it != errors.end(); ++it) {
QVariantMap error = (*it).toMap();
qLog(Error) << "Grooveshark error: (" << error["code"].toInt() << ") "
<< error["message"].toString();
switch (error["code"].toInt()) {
QJsonObject json_object = json_document.object();
QJsonArray json_errors = json_object["errors"].toArray();
for(const QJsonValue & error : json_errors) {
QJsonObject json_error = error.toObject();
qLog(Error) << "Grooveshark error: (" << json_error["code"].toInt() << ") "
<< json_error["message"].toString();
switch (json_error["code"].toInt()) {
case 100: // User auth required
case 102: // User premium required
case 300: // Session required
@ -1697,7 +1707,10 @@ QVariantMap GroovesharkService::ExtractResult(QNetworkReply* reply) {
break;
}
}
return result["result"].toMap();
QJsonDocument doc_ret;
doc_ret.setObject(json_object["result"].toObject());
return doc_ret;
}
namespace {
@ -1709,24 +1722,26 @@ bool CompareSongs(const QVariant& song1, const QVariant& song2) {
if (song1_sort == song2_sort) {
// Favorite songs have a "TSFavorited" and (currently) no "Sort" field
return song1_map["TSFavorited"].toString() <
song2_map["TSFavorited"].toString();
song2_map["TSFavorited"].toString();
}
return song1_sort < song2_sort;
}
} // namespace
} // namespace
SongList GroovesharkService::ExtractSongs(const QVariantMap& result) {
QVariantList result_songs = result["songs"].toList();
SongList GroovesharkService::ExtractSongs(const QJsonObject& result) {
QVariantList result_songs = result["songs"].toArray().toVariantList();
// We don't automatically sort QJsonValue because it doesn't implement swap and so I think it simplier like that
// https://bugreports.qt.io/browse/QTBUG-44944
qStableSort(result_songs.begin(), result_songs.end(), CompareSongs);
SongList songs;
for (int i = 0; i < result_songs.size(); ++i) {
QVariantMap result_song = result_songs[i].toMap();
songs << ExtractSong(result_song);
songs << ExtractSong(QJsonObject::fromVariantMap(result_song));
}
return songs;
}
Song GroovesharkService::ExtractSong(const QVariantMap& result_song) {
Song GroovesharkService::ExtractSong(const QJsonObject& result_song) {
Song song;
if (!result_song.isEmpty()) {
int song_id = result_song["SongID"].toInt();
@ -1765,11 +1780,11 @@ Song GroovesharkService::ExtractSong(const QVariantMap& result_song) {
return song;
}
QList<int> GroovesharkService::ExtractSongsIds(const QVariantMap& result) {
QVariantList result_songs = result["songs"].toList();
QList<int> GroovesharkService::ExtractSongsIds(const QJsonObject& result) {
QJsonArray result_songs = result["songs"].toArray();
QList<int> songs_ids;
for (int i = 0; i < result_songs.size(); ++i) {
QVariantMap result_song = result_songs[i].toMap();
QJsonObject result_song = result_songs[i].toObject();
int song_id = result_song["SongID"].toInt();
songs_ids << song_id;
}
@ -1798,16 +1813,16 @@ int GroovesharkService::ExtractSongId(const QUrl& url) {
}
QList<GroovesharkService::PlaylistInfo> GroovesharkService::ExtractPlaylistInfo(
const QVariantMap& result) {
QVariantList playlists_qvariant = result["playlists"].toList();
const QJsonObject result) {
QJsonArray json_playlists = result["playlists"].toArray();
QList<PlaylistInfo> playlists;
// Get playlists info
for (const QVariant& playlist_qvariant : playlists_qvariant) {
QVariantMap playlist = playlist_qvariant.toMap();
int playlist_id = playlist["PlaylistID"].toInt();
QString playlist_name = playlist["PlaylistName"].toString();
for (const QJsonValue& playlist : json_playlists) {
QJsonObject json_playlist = playlist.toObject();
int playlist_id = json_playlist["PlaylistID"].toInt();
QString playlist_name = json_playlist["PlaylistName"].toString();
playlists << PlaylistInfo(playlist_id, playlist_name);
}

View File

@ -106,8 +106,8 @@ class GroovesharkService : public InternetService {
void GetPlaylistUrlToShare(int playlist_id);
// Start autoplay for the given tag_id, fill the autoplay_state, returns a
// first song to play
Song StartAutoplayTag(int tag_id, QVariantMap& autoplay_state);
Song StartAutoplay(QVariantMap& autoplay_state);
Song StartAutoplayTag(int tag_id, QVariantMap &autoplay_state);
Song StartAutoplay(QVariantMap &autoplay_state);
// Get another autoplay song. autoplay_state is the autoplay_state received
// from StartAutoplayTag
Song GetAutoplaySong(QVariantMap& autoplay_state);
@ -232,22 +232,22 @@ class GroovesharkService : public InternetService {
// seconds. Returns false if reply has timeouted
bool WaitForReply(QNetworkReply* reply);
// Convenient function for extracting result from reply
QVariantMap ExtractResult(QNetworkReply* reply);
QJsonDocument ExtractResult(QNetworkReply* reply);
// Convenient function for extracting songs from grooveshark result. result
// should be the "result" field of most Grooveshark replies
SongList ExtractSongs(const QVariantMap& result);
SongList ExtractSongs(const QJsonObject &result);
// Convenient function for extracting song from grooveshark result.
// result_song should be the song field ('song', 'nextSong', ...) of the
// Grooveshark reply
Song ExtractSong(const QVariantMap& result_song);
Song ExtractSong(const QJsonObject &result_song);
// Convenient functions for extracting Grooveshark songs ids
QList<int> ExtractSongsIds(const QVariantMap& result);
QList<int> ExtractSongsIds(const QJsonObject &result);
QList<int> ExtractSongsIds(const QList<QUrl>& urls);
int ExtractSongId(
const QUrl& url); // Returns 0 if url is not a Grooveshark url
// Convenient function for extracting basic playlist info (only 'id' and
// 'name': QStandardItem still need to be created), and sort them by name
QList<PlaylistInfo> ExtractPlaylistInfo(const QVariantMap& result);
QList<PlaylistInfo> ExtractPlaylistInfo(const QJsonObject result);
void ResetSessionId();
@ -308,7 +308,7 @@ class GroovesharkService : public InternetService {
QString password_; // In fact, password's md5 hash
QString user_id_;
QString session_id_;
QMap<QString, QVariant> country_;
QVariantMap country_;
// The last artists and songs ids th users has listened to. Used for autoplay
QList<int> last_artists_ids_;
QList<int> last_songs_ids_;

View File

@ -43,7 +43,8 @@ QStringList IcecastBackend::GetGenresAlphabetical(const QString& filter) {
QString sql = QString("SELECT DISTINCT genre FROM %1 %2 ORDER BY genre")
.arg(kTableName, where);
QSqlQuery q(sql, db);
QSqlQuery q(db);
q.prepare(sql);
if (!filter.isEmpty()) {
q.bindValue(":filter", QString("%" + filter + "%"));
}
@ -69,7 +70,8 @@ QStringList IcecastBackend::GetGenresByPopularity(const QString& filter) {
" %2"
" GROUP BY genre"
" ORDER BY count DESC").arg(kTableName, where);
QSqlQuery q(sql, db);
QSqlQuery q(db);
q.prepare(sql);
if (!filter.isEmpty()) {
q.bindValue(":filter", QString("%" + filter + "%"));
}
@ -109,7 +111,8 @@ IcecastBackend::StationList IcecastBackend::GetStations(const QString& filter,
if (!where_clauses.isEmpty()) {
sql += " WHERE " + where_clauses.join(" AND ");
}
QSqlQuery q(sql, db);
QSqlQuery q(db);
q.prepare(sql);
for (const QString& value : bound_items) {
q.addBindValue(value);
}
@ -134,7 +137,8 @@ IcecastBackend::StationList IcecastBackend::GetStations(const QString& filter,
bool IcecastBackend::IsEmpty() {
QMutexLocker l(db_->Mutex());
QSqlDatabase db = db_->Connect();
QSqlQuery q(QString("SELECT ROWID FROM %1 LIMIT 1").arg(kTableName), db);
QSqlQuery q(db);
q.prepare(QString("SELECT ROWID FROM %1 LIMIT 1").arg(kTableName));
q.exec();
return !q.next();
}
@ -146,17 +150,16 @@ void IcecastBackend::ClearAndAddStations(const StationList& stations) {
ScopedTransaction t(&db);
// Remove all existing items
QSqlQuery q(QString("DELETE FROM %1").arg(kTableName), db);
QSqlQuery q(db);
q.prepare(QString("DELETE FROM %1").arg(kTableName));
q.exec();
if (db_->CheckErrors(q)) return;
q = QSqlQuery(
QString(
q.prepare(QString(
"INSERT INTO %1 (name, url, mime_type, bitrate,"
" channels, samplerate, genre)"
" VALUES (:name, :url, :mime_type, :bitrate,"
" :channels, :samplerate, :genre)").arg(kTableName),
db);
" :channels, :samplerate, :genre)").arg(kTableName));
// Add these ones
for (const Station& station : stations) {

View File

@ -46,7 +46,8 @@ void IcecastModel::Reset() {
LazyPopulate(root_);
reset();
beginResetModel();
endResetModel();
}
void IcecastModel::LazyPopulate(IcecastItem* parent) {

View File

@ -21,9 +21,8 @@
#include "jamendodynamicplaylist.h"
#include <QEventLoop>
#include <QHttp>
#include <QHttpRequestHeader>
#include <QtDebug>
#include <QUrlQuery>
#include "core/logging.h"
#include "core/network.h"
@ -119,35 +118,36 @@ QString JamendoDynamicPlaylist::OrderSpec(OrderBy by, OrderDirection dir) {
void JamendoDynamicPlaylist::Fetch() {
QUrl url(kUrl);
url.addQueryItem("pn", QString::number(current_page_++));
url.addQueryItem("n", QString::number(kPageSize));
url.addQueryItem("order", OrderSpec(order_by_, order_direction_));
QUrlQuery url_query;
url_query.addQueryItem("pn", QString::number(current_page_++));
url_query.addQueryItem("n", QString::number(kPageSize));
url_query.addQueryItem("order", OrderSpec(order_by_, order_direction_));
url.setQuery(url_query);
// TODO
// We have to use QHttp here because there's no way to disable Keep-Alive
// with QNetworkManager.
QHttpRequestHeader header(
"GET", QString(url.encodedPath() + "?" + url.encodedQuery()));
header.setValue("Host", url.encodedHost());
QHttp http(url.host());
http.request(header);
QNetworkAccessManager network(this);
QNetworkRequest req(url);
QNetworkReply *reply = network.get(req);
// Wait for the reply
{
QEventLoop event_loop;
connect(&http, SIGNAL(requestFinished(int, bool)), &event_loop,
SLOT(quit()));
connect(reply, SIGNAL(finished()), &event_loop, SLOT(quit()));
event_loop.exec();
}
if (http.error() != QHttp::NoError) {
qLog(Warning) << "HTTP error returned from Jamendo:" << http.errorString()
reply->deleteLater();
if (reply->error() != QNetworkReply::NoError) {
qLog(Warning) << "HTTP error returned from Jamendo:" << reply->errorString()
<< ", url:" << url.toString();
return;
}
// The reply will contain one track ID per line
QStringList lines = QString::fromAscii(http.readAll()).split('\n');
QStringList lines = QString::fromLatin1(reply->readAll()).split('\n');
// Get the songs from the database
SongList songs = backend_->GetSongsByForeignId(

View File

@ -289,9 +289,9 @@ void JamendoService::InsertTrackIds(const TrackIdList& ids) const {
ScopedTransaction t(&db);
QSqlQuery insert(QString("INSERT INTO %1 (%2) VALUES (:id)")
.arg(kTrackIdsTable, kTrackIdsColumn),
db);
QSqlQuery insert(db);
insert.prepare(QString("INSERT INTO %1 (%2) VALUES (:id)")
.arg(kTrackIdsTable, kTrackIdsColumn));
for (int id : ids) {
insert.bindValue(":id", id);

View File

@ -31,6 +31,7 @@
#include <QSet>
#include <QSettings>
#include <QXmlStreamReader>
#include <QUrlQuery>
#include "magnatuneservice.h"
#include "internet/core/internetmodel.h"
@ -49,8 +50,8 @@ MagnatuneDownloadDialog::MagnatuneDownloadDialog(MagnatuneService* service,
current_reply_(nullptr),
next_row_(0) {
ui_->setupUi(this);
ui_->albums->header()->setResizeMode(QHeaderView::ResizeToContents);
ui_->albums->header()->setResizeMode(1, QHeaderView::Fixed);
ui_->albums->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
ui_->albums->header()->setSectionResizeMode(1, QHeaderView::Fixed);
ui_->albums->header()->resizeSection(1, 150);
ui_->albums->setItemDelegateForColumn(1, new ProgressItemDelegate(this));
@ -126,8 +127,10 @@ void MagnatuneDownloadDialog::DownloadNext() {
QUrl url(MagnatuneService::kDownloadUrl);
url.setUserName(service_->username());
url.setPassword(service_->password());
url.addQueryItem("id", MagnatuneService::kPartnerId);
url.addQueryItem("sku", sku);
QUrlQuery url_query;
url_query.addQueryItem("id", MagnatuneService::kPartnerId);
url_query.addQueryItem("sku", sku);
current_reply_ = network_->get(QNetworkRequest(url));

View File

@ -227,7 +227,7 @@ Song MagnatuneService::ReadTrack(QXmlStreamReader& reader) {
if (name == "url") {
QUrl url;
// Magnatune's URLs are already encoded
url.setEncodedUrl(value.toLocal8Bit());
url.setUrl(value.toLocal8Bit());
url.setScheme("magnatune");
song.set_url(url);
}

View File

@ -19,9 +19,13 @@
#include "itunessearchpage.h"
#include <qjson/parser.h>
#include <QMessageBox>
#include <QNetworkReply>
#include <QUrlQuery>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QJsonArray>
#include "core/closure.h"
#include "core/network.h"
@ -47,7 +51,9 @@ void ITunesSearchPage::SearchClicked() {
emit Busy(true);
QUrl url(QUrl::fromEncoded(kUrlBase));
url.addQueryItem("term", ui_->query->text());
QUrlQuery url_query;
url_query.addQueryItem("term", ui_->query->text());
url.setQuery(url_query);
QNetworkReply* reply = network_->get(QNetworkRequest(url));
NewClosure(reply, SIGNAL(finished()), this,
@ -67,37 +73,38 @@ void ITunesSearchPage::SearchFinished(QNetworkReply* reply) {
return;
}
QJson::Parser parser;
QVariant data = parser.parse(reply);
QJsonParseError error;
QJsonDocument json_document = QJsonDocument::fromJson(reply->readAll(), &error);
// Was it valid JSON?
if (data.isNull()) {
if (error.error != QJsonParseError::NoError) {
QMessageBox::warning(
this, tr("Failed to fetch podcasts"),
tr("There was a problem parsing the response from the iTunes Store"));
return;
}
QJsonObject json_data = json_document.object();
// Was there an error message in the JSON?
if (data.toMap().contains("errorMessage")) {
if (!json_data["errorMessage"].isUndefined()) {
QMessageBox::warning(this, tr("Failed to fetch podcasts"),
data.toMap()["errorMessage"].toString());
json_data["errorMessage"].toString());
return;
}
for (const QVariant& result_variant : data.toMap()["results"].toList()) {
QVariantMap result(result_variant.toMap());
if (result["kind"].toString() != "podcast") {
for (const QJsonValue& result : json_data["results"].toArray()) {
QJsonObject json_result = result.toObject();
if (json_result["kind"].toString() != "podcast") {
continue;
}
Podcast podcast;
podcast.set_author(result["artistName"].toString());
podcast.set_title(result["trackName"].toString());
podcast.set_url(result["feedUrl"].toUrl());
podcast.set_link(result["trackViewUrl"].toUrl());
podcast.set_image_url_small(QUrl(result["artworkUrl30"].toString()));
podcast.set_image_url_large(QUrl(result["artworkUrl100"].toString()));
podcast.set_author(json_result["artistName"].toString());
podcast.set_title(json_result["trackName"].toString());
podcast.set_url(QUrl(json_result["feedUrl"].toString()));
podcast.set_link(QUrl(json_result["trackViewUrl"].toString()));
podcast.set_image_url_small(QUrl(json_result["artworkUrl30"].toString()));
podcast.set_image_url_large(QUrl(json_result["artworkUrl100"].toString()));
model()->appendRow(model()->CreatePodcastItem(podcast));
}

View File

@ -47,11 +47,11 @@ void PodcastBackend::Subscribe(Podcast* podcast) {
ScopedTransaction t(&db);
// Insert the podcast.
QSqlQuery q("INSERT INTO podcasts (" + Podcast::kColumnSpec +
QSqlQuery q(db);
q.prepare("INSERT INTO podcasts (" + Podcast::kColumnSpec +
")"
" VALUES (" +
Podcast::kBindSpec + ")",
db);
Podcast::kBindSpec + ")");
podcast->BindToQuery(&q);
q.exec();
@ -86,13 +86,14 @@ void PodcastBackend::Unsubscribe(const Podcast& podcast) {
ScopedTransaction t(&db);
// Remove the podcast.
QSqlQuery q("DELETE FROM podcasts WHERE ROWID = :id", db);
QSqlQuery q(db);
q.prepare("DELETE FROM podcasts WHERE ROWID = :id");
q.bindValue(":id", podcast.database_id());
q.exec();
if (db_->CheckErrors(q)) return;
// Remove all episodes in the podcast
q = QSqlQuery("DELETE FROM podcast_episodes WHERE podcast_id = :id", db);
q.prepare("DELETE FROM podcast_episodes WHERE podcast_id = :id");
q.bindValue(":id", podcast.database_id());
q.exec();
if (db_->CheckErrors(q)) return;
@ -104,11 +105,11 @@ void PodcastBackend::Unsubscribe(const Podcast& podcast) {
void PodcastBackend::AddEpisodes(PodcastEpisodeList* episodes,
QSqlDatabase* db) {
QSqlQuery q("INSERT INTO podcast_episodes (" + PodcastEpisode::kColumnSpec +
QSqlQuery q(*db);
q.prepare("INSERT INTO podcast_episodes (" + PodcastEpisode::kColumnSpec +
")"
" VALUES (" +
PodcastEpisode::kBindSpec + ")",
*db);
PodcastEpisode::kBindSpec + ")");
for (auto it = episodes->begin(); it != episodes->end(); ++it) {
it->BindToQuery(&q);
@ -136,14 +137,13 @@ void PodcastBackend::UpdateEpisodes(const PodcastEpisodeList& episodes) {
QSqlDatabase db(db_->Connect());
ScopedTransaction t(&db);
QSqlQuery q(
"UPDATE podcast_episodes"
QSqlQuery q(db);
q.prepare("UPDATE podcast_episodes"
" SET listened = :listened,"
" listened_date = :listened_date,"
" downloaded = :downloaded,"
" local_url = :local_url"
" WHERE ROWID = :id",
db);
" WHERE ROWID = :id");
for (const PodcastEpisode& episode : episodes) {
q.bindValue(":listened", episode.listened());
@ -166,7 +166,8 @@ PodcastList PodcastBackend::GetAllSubscriptions() {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("SELECT ROWID, " + Podcast::kColumnSpec + " FROM podcasts", db);
QSqlQuery q(db);
q.prepare("SELECT ROWID, " + Podcast::kColumnSpec + " FROM podcasts");
q.exec();
if (db_->CheckErrors(q)) return ret;
@ -185,10 +186,10 @@ Podcast PodcastBackend::GetSubscriptionById(int id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("SELECT ROWID, " + Podcast::kColumnSpec +
QSqlQuery q(db);
q.prepare("SELECT ROWID, " + Podcast::kColumnSpec +
" FROM podcasts"
" WHERE ROWID = :id",
db);
" WHERE ROWID = :id");
q.bindValue(":id", id);
q.exec();
if (!db_->CheckErrors(q) && q.next()) {
@ -204,10 +205,10 @@ Podcast PodcastBackend::GetSubscriptionByUrl(const QUrl& url) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("SELECT ROWID, " + Podcast::kColumnSpec +
QSqlQuery q(db);
q.prepare("SELECT ROWID, " + Podcast::kColumnSpec +
" FROM podcasts"
" WHERE url = :url",
db);
" WHERE url = :url");
q.bindValue(":url", url.toEncoded());
q.exec();
if (!db_->CheckErrors(q) && q.next()) {
@ -223,11 +224,11 @@ PodcastEpisodeList PodcastBackend::GetEpisodes(int podcast_id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
QSqlQuery q(db);
q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
" FROM podcast_episodes"
" WHERE podcast_id = :id"
" ORDER BY publication_date DESC",
db);
" ORDER BY publication_date DESC");
q.bindValue(":db", podcast_id);
q.exec();
if (db_->CheckErrors(q)) return ret;
@ -247,10 +248,10 @@ PodcastEpisode PodcastBackend::GetEpisodeById(int id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
QSqlQuery q(db);
q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
" FROM podcast_episodes"
" WHERE ROWID = :id",
db);
" WHERE ROWID = :id");
q.bindValue(":db", id);
q.exec();
if (!db_->CheckErrors(q) && q.next()) {
@ -266,10 +267,10 @@ PodcastEpisode PodcastBackend::GetEpisodeByUrl(const QUrl& url) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
QSqlQuery q(db);
q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
" FROM podcast_episodes"
" WHERE url = :url",
db);
" WHERE url = :url");
q.bindValue(":url", url.toEncoded());
q.exec();
if (!db_->CheckErrors(q) && q.next()) {
@ -285,11 +286,11 @@ PodcastEpisode PodcastBackend::GetEpisodeByUrlOrLocalUrl(const QUrl& url) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
QSqlQuery q(db);
q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
" FROM podcast_episodes"
" WHERE url = :url"
" OR local_url = :url",
db);
" OR local_url = :url");
q.bindValue(":url", url.toEncoded());
q.exec();
if (!db_->CheckErrors(q) && q.next()) {
@ -306,11 +307,11 @@ PodcastEpisodeList PodcastBackend::GetOldDownloadedEpisodes(
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
QSqlQuery q(db);
q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
" FROM podcast_episodes"
" WHERE downloaded = 'true'"
" AND listened_date <= :max_listened_date",
db);
" AND listened_date <= :max_listened_date");
q.bindValue(":max_listened_date", max_listened_date.toTime_t());
q.exec();
if (db_->CheckErrors(q)) return ret;
@ -330,12 +331,12 @@ PodcastEpisode PodcastBackend::GetOldestDownloadedListenedEpisode() {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
QSqlQuery q(db);
q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
" FROM podcast_episodes"
" WHERE downloaded = 'true'"
" AND listened = 'true'"
" ORDER BY listened_date ASC",
db);
" ORDER BY listened_date ASC");
q.exec();
if (db_->CheckErrors(q)) return ret;
q.next();
@ -350,11 +351,11 @@ PodcastEpisodeList PodcastBackend::GetNewDownloadedEpisodes() {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
QSqlQuery q(db);
q.prepare("SELECT ROWID, " + PodcastEpisode::kColumnSpec +
" FROM podcast_episodes"
" WHERE downloaded = 'true'"
" AND listened = 'false'",
db);
" AND listened = 'false'");
q.exec();
if (db_->CheckErrors(q)) return ret;

View File

@ -114,7 +114,7 @@ void PodcastParser::ParseChannel(QXmlStreamReader* reader, Podcast* ret) const {
if (name == "title") {
ret->set_title(reader->readElementText());
} else if (name == "link" && lower_namespace.isEmpty()) {
ret->set_link(QUrl::fromEncoded(reader->readElementText().toAscii()));
ret->set_link(QUrl::fromEncoded(reader->readElementText().toLatin1()));
} else if (name == "description") {
ret->set_description(reader->readElementText());
} else if (name == "owner" && lower_namespace == kItunesNamespace) {
@ -126,7 +126,7 @@ void PodcastParser::ParseChannel(QXmlStreamReader* reader, Podcast* ret) const {
} else if (name == "link" && lower_namespace == kAtomNamespace &&
ret->url().isEmpty() &&
reader->attributes().value("rel") == "self") {
ret->set_url(QUrl::fromEncoded(reader->readElementText().toAscii()));
ret->set_url(QUrl::fromEncoded(reader->readElementText().toLatin1()));
} else if (name == "item") {
ParseItem(reader, ret);
} else {
@ -152,7 +152,7 @@ void PodcastParser::ParseImage(QXmlStreamReader* reader, Podcast* ret) const {
const QStringRef name = reader->name();
if (name == "url") {
ret->set_image_url_large(
QUrl::fromEncoded(reader->readElementText().toAscii()));
QUrl::fromEncoded(reader->readElementText().toLatin1()));
} else {
Utilities::ConsumeCurrentElement(reader);
}
@ -231,7 +231,7 @@ void PodcastParser::ParseItem(QXmlStreamReader* reader, Podcast* ret) const {
const QString type = reader->attributes().value("type").toString();
if (type.startsWith("audio/") || type.startsWith("x-audio/")) {
episode.set_url(QUrl::fromEncoded(
reader->attributes().value("url").toString().toAscii()));
reader->attributes().value("url").toString().toLatin1()));
}
Utilities::ConsumeCurrentElement(reader);
} else if (name == "author" && lower_namespace == kItunesNamespace) {
@ -293,9 +293,9 @@ void PodcastParser::ParseOutline(QXmlStreamReader* reader,
podcast.set_description(attributes.value("description").toString());
podcast.set_title(attributes.value("text").toString());
podcast.set_image_url_large(QUrl::fromEncoded(
attributes.value("imageHref").toString().toAscii()));
attributes.value("imageHref").toString().toLatin1()));
podcast.set_url(QUrl::fromEncoded(
attributes.value("xmlUrl").toString().toAscii()));
attributes.value("xmlUrl").toString().toLatin1()));
ret->feeds.append(podcast);
// Consume any children and the EndElement.

View File

@ -20,6 +20,7 @@
#include "podcasturlloader.h"
#include <QNetworkReply>
#include <QUrlQuery>
#include "podcastparser.h"
#include "core/closure.h"
@ -73,14 +74,15 @@ QUrl PodcastUrlLoader::FixPodcastUrl(const QString& url_text) {
QUrl PodcastUrlLoader::FixPodcastUrl(const QUrl& url_orig) {
QUrl url(url_orig);
QUrlQuery url_query(url);
// Replace schemes
if (url.scheme().isEmpty() || url.scheme() == "feed" ||
url.scheme() == "itpc" || url.scheme() == "itms") {
url.setScheme("http");
} else if (url.scheme() == "zune" && url.host() == "subscribe" &&
!url.queryItems().isEmpty()) {
url = QUrl(url.queryItems()[0].second);
!url_query.queryItems().isEmpty()) {
url = QUrl(url_query.queryItems()[0].second);
}
return url;

View File

@ -25,9 +25,11 @@
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QTimer>
#include <qjson/parser.h>
#include <qjson/serializer.h>
#include <QUrlQuery>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonParseError>
#include <QJsonArray>
#include "internet/core/internetmodel.h"
#include "internet/core/oauthenticator.h"
@ -217,7 +219,7 @@ void SoundCloudService::RetrieveUserData() {
void SoundCloudService::RetrieveUserTracks() {
QList<Param> parameters;
parameters << Param("oauth_token", access_token_);
QNetworkReply* reply = CreateRequest("me/tracks", parameters);
QNetworkReply* reply = CreateRequest("/me/tracks", parameters);
NewClosure(reply, SIGNAL(finished()), this,
SLOT(UserTracksRetrieved(QNetworkReply*)), reply);
}
@ -225,7 +227,7 @@ void SoundCloudService::RetrieveUserTracks() {
void SoundCloudService::UserTracksRetrieved(QNetworkReply* reply) {
reply->deleteLater();
SongList songs = ExtractSongs(ExtractResult(reply));
SongList songs = ExtractSongs(ExtractResult(reply).array());
// Fill results list
for (const Song& song : songs) {
QStandardItem* child = CreateSongItem(song);
@ -236,7 +238,7 @@ void SoundCloudService::UserTracksRetrieved(QNetworkReply* reply) {
void SoundCloudService::RetrieveUserActivities() {
QList<Param> parameters;
parameters << Param("oauth_token", access_token_);
QNetworkReply* reply = CreateRequest("me/activities", parameters);
QNetworkReply* reply = CreateRequest("/me/activities", parameters);
NewClosure(reply, SIGNAL(finished()), this,
SLOT(UserActivitiesRetrieved(QNetworkReply*)), reply);
}
@ -244,7 +246,7 @@ void SoundCloudService::RetrieveUserActivities() {
void SoundCloudService::UserActivitiesRetrieved(QNetworkReply* reply) {
reply->deleteLater();
QList<QStandardItem*> activities = ExtractActivities(ExtractResult(reply));
QList<QStandardItem*> activities = ExtractActivities(ExtractResult(reply).object());
// Fill results list
for (QStandardItem* activity : activities) {
user_activities_->appendRow(activity);
@ -254,7 +256,7 @@ void SoundCloudService::UserActivitiesRetrieved(QNetworkReply* reply) {
void SoundCloudService::RetrieveUserPlaylists() {
QList<Param> parameters;
parameters << Param("oauth_token", access_token_);
QNetworkReply* reply = CreateRequest("me/playlists", parameters);
QNetworkReply* reply = CreateRequest("/me/playlists", parameters);
NewClosure(reply, SIGNAL(finished()), this,
SLOT(UserPlaylistsRetrieved(QNetworkReply*)), reply);
}
@ -262,12 +264,12 @@ void SoundCloudService::RetrieveUserPlaylists() {
void SoundCloudService::UserPlaylistsRetrieved(QNetworkReply* reply) {
reply->deleteLater();
QList<QVariant> playlists = ExtractResult(reply).toList();
for (const QVariant& playlist : playlists) {
QMap<QString, QVariant> playlist_map = playlist.toMap();
QJsonArray json_playlists = ExtractResult(reply).array();
for (const QJsonValue& playlist : json_playlists) {
QJsonObject json_playlist = playlist.toObject();
QStandardItem* playlist_item = CreatePlaylistItem(playlist_map["title"].toString());
SongList songs = ExtractSongs(playlist_map["tracks"]);
QStandardItem* playlist_item = CreatePlaylistItem(json_playlist["title"].toString());
SongList songs = ExtractSongs(json_playlist["tracks"].toArray());
for (const Song& song : songs) {
playlist_item->appendRow(CreateSongItem(song));
}
@ -299,7 +301,7 @@ void SoundCloudService::DoSearch() {
QList<Param> parameters;
parameters << Param("q", pending_search_);
QNetworkReply* reply = CreateRequest("tracks", parameters);
QNetworkReply* reply = CreateRequest("/tracks", parameters);
const int id = next_pending_search_id_++;
NewClosure(reply, SIGNAL(finished()), this,
SLOT(SearchFinished(QNetworkReply*, int)), reply, id);
@ -308,7 +310,7 @@ void SoundCloudService::DoSearch() {
void SoundCloudService::SearchFinished(QNetworkReply* reply, int task_id) {
reply->deleteLater();
SongList songs = ExtractSongs(ExtractResult(reply));
SongList songs = ExtractSongs(ExtractResult(reply).array());
// Fill results list
for (const Song& song : songs) {
QStandardItem* child = CreateSongItem(song);
@ -328,7 +330,7 @@ void SoundCloudService::ClearSearchResults() {
int SoundCloudService::SimpleSearch(const QString& text) {
QList<Param> parameters;
parameters << Param("q", text);
QNetworkReply* reply = CreateRequest("tracks", parameters);
QNetworkReply* reply = CreateRequest("/tracks", parameters);
const int id = next_pending_search_id_++;
NewClosure(reply, SIGNAL(finished()), this,
SLOT(SimpleSearchFinished(QNetworkReply*, int)), reply, id);
@ -338,7 +340,7 @@ int SoundCloudService::SimpleSearch(const QString& text) {
void SoundCloudService::SimpleSearchFinished(QNetworkReply* reply, int id) {
reply->deleteLater();
SongList songs = ExtractSongs(ExtractResult(reply));
SongList songs = ExtractSongs(ExtractResult(reply).array());
emit SimpleSearchResults(id, songs);
}
@ -372,12 +374,15 @@ QNetworkReply* SoundCloudService::CreateRequest(const QString& ressource_name,
QUrl url(kUrl);
url.setPath(ressource_name);
QUrlQuery url_query;
url.addQueryItem("client_id", kApiClientId);
url_query.addQueryItem("client_id", kApiClientId);
for (const Param& param : params) {
url.addQueryItem(param.first, param.second);
url_query.addQueryItem(param.first, param.second);
}
url.setQuery(url_query);
qLog(Debug) << "Request Url: " << url.toEncoded();
QNetworkRequest req(url);
@ -386,7 +391,7 @@ QNetworkReply* SoundCloudService::CreateRequest(const QString& ressource_name,
return reply;
}
QVariant SoundCloudService::ExtractResult(QNetworkReply* reply) {
QJsonDocument SoundCloudService::ExtractResult(QNetworkReply* reply) {
if (reply->error() != QNetworkReply::NoError) {
qLog(Error) << "Error when retrieving SoundCloud results:"
<< reply->errorString() << QString(" (%1)").arg(reply->error());
@ -396,16 +401,16 @@ QVariant SoundCloudService::ExtractResult(QNetworkReply* reply) {
reply->error() == QNetworkReply::AuthenticationRequiredError) {
// In case of access denied errors (invalid token?) logout
Logout();
return QVariant();
return QJsonDocument();
}
}
QJson::Parser parser;
bool ok;
QVariant result = parser.parse(reply, &ok);
if (!ok) {
QJsonParseError error;
QJsonDocument document = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qLog(Error) << "Error while parsing SoundCloud result";
}
return result;
return document;
}
void SoundCloudService::RetrievePlaylist(int playlist_id,
@ -416,7 +421,7 @@ void SoundCloudService::RetrievePlaylist(int playlist_id,
QList<Param> parameters;
parameters << Param("oauth_token", access_token_);
QNetworkReply* reply =
CreateRequest("playlists/" + QString::number(playlist_id), parameters);
CreateRequest("/playlists/" + QString::number(playlist_id), parameters);
NewClosure(reply, SIGNAL(finished()), this,
SLOT(PlaylistRetrieved(QNetworkReply*, int)), reply, request_id);
}
@ -425,42 +430,41 @@ void SoundCloudService::PlaylistRetrieved(QNetworkReply* reply,
int request_id) {
if (!pending_playlists_requests_.contains(request_id)) return;
PlaylistInfo playlist_info = pending_playlists_requests_.take(request_id);
QVariant res = ExtractResult(reply);
SongList songs = ExtractSongs(res.toMap()["tracks"]);
QJsonDocument res = ExtractResult(reply);
SongList songs = ExtractSongs(res.object()["tracks"].toArray());
for (const Song& song : songs) {
QStandardItem* child = CreateSongItem(song);
playlist_info.item_->appendRow(child);
}
}
QList<QStandardItem*> SoundCloudService::ExtractActivities(const QVariant& result) {
QList<QStandardItem*> SoundCloudService::ExtractActivities(const QJsonObject& result) {
QList<QStandardItem*> activities;
QVariantList q_variant_list = result.toMap()["collection"].toList();
for (const QVariant& q : q_variant_list) {
QMap<QString, QVariant> activity = q.toMap();
const QString type = activity["type"].toString();
QJsonArray q_list = result["collection"].toArray();
for (const QJsonValue& q : q_list) {
QJsonObject json_activity = q.toObject();
const QString type = json_activity["type"].toString();
if (type == "track") {
Song song = ExtractSong(activity["origin"].toMap());
Song song = ExtractSong(json_activity["origin"].toObject());
if (song.is_valid()) {
activities << CreateSongItem(song);
}
} else if (type == "playlist") {
QMap<QString, QVariant> origin_map = activity["origin"].toMap();
QJsonObject json_origin = json_activity["origin"].toObject();
QStandardItem* playlist_item =
CreatePlaylistItem(origin_map["title"].toString());
CreatePlaylistItem(json_origin["title"].toString());
activities << playlist_item;
RetrievePlaylist(origin_map["id"].toInt(), playlist_item);
RetrievePlaylist(json_origin["id"].toInt(), playlist_item);
}
}
return activities;
}
SongList SoundCloudService::ExtractSongs(const QVariant& result) {
SongList SoundCloudService::ExtractSongs(const QJsonArray & result) {
SongList songs;
QVariantList q_variant_list = result.toList();
for (const QVariant& q : q_variant_list) {
Song song = ExtractSong(q.toMap());
for (const QJsonValue& q : result) {
Song song = ExtractSong(q.toObject());
if (song.is_valid()) {
songs << song;
}
@ -468,14 +472,16 @@ SongList SoundCloudService::ExtractSongs(const QVariant& result) {
return songs;
}
Song SoundCloudService::ExtractSong(const QVariantMap& result_song) {
Song SoundCloudService::ExtractSong(const QJsonObject& result_song) {
Song song;
if (!result_song.isEmpty() && result_song["streamable"].toBool()) {
QUrl stream_url = result_song["stream_url"].toUrl();
stream_url.addQueryItem("client_id", kApiClientId);
QUrl stream_url(result_song["stream_url"].toString());
QUrlQuery stream_url_query;
stream_url_query.addQueryItem("client_id", kApiClientId);
stream_url.setQuery(stream_url_query);
song.set_url(stream_url);
QString username = result_song["user"].toMap()["username"].toString();
QString username = result_song["user"].toObject()["username"].toString();
// We don't have a real artist name, but username is the most similar thing
// we have
song.set_artist(username);
@ -486,7 +492,7 @@ Song SoundCloudService::ExtractSong(const QVariantMap& result_song) {
QString genre = result_song["genre"].toString();
song.set_genre(genre);
float bpm = result_song["bpm"].toFloat();
float bpm = result_song["bpm"].toDouble();
song.set_bpm(bpm);
QVariant cover = result_song["artwork_url"];

View File

@ -26,6 +26,7 @@
class NetworkAccessManager;
class OAuthenticator;
class SearchBoxWidget;
class QJsonDocument;
class QMenu;
class QNetworkReply;
@ -101,11 +102,11 @@ class SoundCloudService : public InternetService {
QNetworkReply* CreateRequest(const QString& ressource_name,
const QList<QPair<QString, QString>>& params);
// Convenient function for extracting result from reply
QVariant ExtractResult(QNetworkReply* reply);
QJsonDocument ExtractResult(QNetworkReply* reply);
// Returns items directly, as activities can be playlists or songs
QList<QStandardItem*> ExtractActivities(const QVariant& result);
SongList ExtractSongs(const QVariant& result);
Song ExtractSong(const QVariantMap& result_song);
QList<QStandardItem*> ExtractActivities(const QJsonObject &result);
SongList ExtractSongs(const QJsonArray &result);
Song ExtractSong(const QJsonObject& result_song);
QStandardItem* root_;
QStandardItem* search_;

View File

@ -29,6 +29,7 @@
#include <QSortFilterProxyModel>
#include <QSslConfiguration>
#include <QXmlStreamReader>
#include <QUrlQuery>
#include "core/application.h"
#include "core/closure.h"
@ -209,10 +210,12 @@ void SubsonicService::Ping() {
QUrl SubsonicService::BuildRequestUrl(const QString& view) const {
QUrl url(working_server_ + "/rest/" + view + ".view");
url.addQueryItem("v", kApiVersion);
url.addQueryItem("c", kApiClientName);
url.addQueryItem("u", username_);
url.addQueryItem("p", QString("enc:" + password_.toUtf8().toHex()));
QUrlQuery url_query;
url_query.addQueryItem("v", kApiVersion);
url_query.addQueryItem("c", kApiClientName);
url_query.addQueryItem("u", username_);
url_query.addQueryItem("p", QString("enc:" + password_.toUtf8().toHex()));
url.setQuery(url_query);
return url;
}
@ -496,9 +499,11 @@ void SubsonicLibraryScanner::OnGetAlbumFinished(QNetworkReply* reply) {
void SubsonicLibraryScanner::GetAlbumList(int offset) {
QUrl url = service_->BuildRequestUrl("getAlbumList2");
url.addQueryItem("type", "alphabeticalByName");
url.addQueryItem("size", QString::number(kAlbumChunkSize));
url.addQueryItem("offset", QString::number(offset));
QUrlQuery url_query;
url_query.addQueryItem("type", "alphabeticalByName");
url_query.addQueryItem("size", QString::number(kAlbumChunkSize));
url_query.addQueryItem("offset", QString::number(offset));
url.setQuery(url_query);
QNetworkReply* reply = service_->Send(url);
NewClosure(reply, SIGNAL(finished()), this,
SLOT(OnGetAlbumListFinished(QNetworkReply*, int)), reply, offset);
@ -506,7 +511,9 @@ void SubsonicLibraryScanner::GetAlbumList(int offset) {
void SubsonicLibraryScanner::GetAlbum(const QString& id) {
QUrl url = service_->BuildRequestUrl("getAlbum");
url.addQueryItem("id", id);
QUrlQuery url_query;
url_query.addQueryItem("id", id);
url.setQuery(url_query);
QNetworkReply* reply = service_->Send(url);
NewClosure(reply, SIGNAL(finished()), this,
SLOT(OnGetAlbumFinished(QNetworkReply*)), reply);

View File

@ -17,6 +17,8 @@
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
*/
#include <QUrlQuery>
#include "subsonicservice.h"
#include "subsonicurlhandler.h"
@ -29,6 +31,8 @@ UrlHandler::LoadResult SubsonicUrlHandler::StartLoading(const QUrl& url) {
return LoadResult();
QUrl newurl = service_->BuildRequestUrl("stream");
newurl.addQueryItem("id", url.host());
QUrlQuery url_query;
url_query.addQueryItem("id", url.host());
newurl.setQuery(url_query);
return LoadResult(url, LoadResult::TrackAvailable, newurl);
}

View File

@ -111,8 +111,8 @@ void LibraryBackend::ChangeDirPath(int id, const QString& old_path,
ScopedTransaction t(&db);
// Do the dirs table
QSqlQuery q(
QString("UPDATE %1 SET path=:path WHERE ROWID=:id").arg(dirs_table_), db);
QSqlQuery q(db);
q.prepare(QString("UPDATE %1 SET path=:path WHERE ROWID=:id").arg(dirs_table_));
q.bindValue(":path", new_path);
q.bindValue(":id", id);
q.exec();
@ -124,24 +124,24 @@ void LibraryBackend::ChangeDirPath(int id, const QString& old_path,
const int path_len = old_url.length();
// Do the subdirs table
q = QSqlQuery(QString(
q = QSqlQuery(db);
q.prepare(QString(
"UPDATE %1 SET path=:path || substr(path, %2)"
" WHERE directory=:id")
.arg(subdirs_table_)
.arg(path_len),
db);
.arg(path_len));
q.bindValue(":path", new_url);
q.bindValue(":id", id);
q.exec();
if (db_->CheckErrors(q)) return;
// Do the songs table
q = QSqlQuery(QString(
q = QSqlQuery(db);
q.prepare(QString(
"UPDATE %1 SET filename=:path || substr(filename, %2)"
" WHERE directory=:id")
.arg(songs_table_)
.arg(path_len),
db);
.arg(path_len));
q.bindValue(":path", new_url);
q.bindValue(":id", id);
q.exec();
@ -156,7 +156,8 @@ DirectoryList LibraryBackend::GetAllDirectories() {
DirectoryList ret;
QSqlQuery q(QString("SELECT ROWID, path FROM %1").arg(dirs_table_), db);
QSqlQuery q(db);
q.prepare(QString("SELECT ROWID, path FROM %1").arg(dirs_table_));
q.exec();
if (db_->CheckErrors(q)) return ret;
@ -177,10 +178,10 @@ SubdirectoryList LibraryBackend::SubdirsInDirectory(int id) {
}
SubdirectoryList LibraryBackend::SubdirsInDirectory(int id, QSqlDatabase& db) {
QSqlQuery q(QString(
QSqlQuery q(db);
q.prepare(QString(
"SELECT path, mtime FROM %1"
" WHERE directory = :dir").arg(subdirs_table_),
db);
" WHERE directory = :dir").arg(subdirs_table_));
q.bindValue(":dir", id);
q.exec();
if (db_->CheckErrors(q)) return SubdirectoryList();
@ -201,9 +202,9 @@ void LibraryBackend::UpdateTotalSongCount() {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(QString("SELECT COUNT(*) FROM %1 WHERE unavailable = 0")
.arg(songs_table_),
db);
QSqlQuery q(db);
q.prepare(QString("SELECT COUNT(*) FROM %1 WHERE unavailable = 0")
.arg(songs_table_));
q.exec();
if (db_->CheckErrors(q)) return;
if (!q.next()) return;
@ -225,10 +226,10 @@ void LibraryBackend::AddDirectory(const QString& path) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(QString(
QSqlQuery q(db);
q.prepare(QString(
"INSERT INTO %1 (path, subdirs)"
" VALUES (:path, 1)").arg(dirs_table_),
db);
" VALUES (:path, 1)").arg(dirs_table_));
q.bindValue(":path", db_path);
q.exec();
if (db_->CheckErrors(q)) return;
@ -250,15 +251,15 @@ void LibraryBackend::RemoveDirectory(const Directory& dir) {
ScopedTransaction transaction(&db);
// Delete the subdirs that were in this directory
QSqlQuery q(
QString("DELETE FROM %1 WHERE directory = :id").arg(subdirs_table_), db);
QSqlQuery q(db);
q.prepare(QString("DELETE FROM %1 WHERE directory = :id").arg(subdirs_table_));
q.bindValue(":id", dir.id);
q.exec();
if (db_->CheckErrors(q)) return;
// Now remove the directory itself
q = QSqlQuery(QString("DELETE FROM %1 WHERE ROWID = :id").arg(dirs_table_),
db);
q = QSqlQuery(db);
q.prepare(QString("DELETE FROM %1 WHERE ROWID = :id").arg(dirs_table_));
q.bindValue(":id", dir.id);
q.exec();
if (db_->CheckErrors(q)) return;
@ -272,10 +273,10 @@ SongList LibraryBackend::FindSongsInDirectory(int id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(
QSqlQuery q(db);
q.prepare(
QString("SELECT ROWID, " + Song::kColumnSpec +
" FROM %1 WHERE directory = :directory").arg(songs_table_),
db);
" FROM %1 WHERE directory = :directory").arg(songs_table_));
q.bindValue(":directory", id);
q.exec();
if (db_->CheckErrors(q)) return SongList();
@ -292,25 +293,22 @@ SongList LibraryBackend::FindSongsInDirectory(int id) {
void LibraryBackend::AddOrUpdateSubdirs(const SubdirectoryList& subdirs) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery find_query(
QString(
QSqlQuery find_query(db);
find_query.prepare(QString(
"SELECT ROWID FROM %1"
" WHERE directory = :id AND path = :path").arg(subdirs_table_),
db);
QSqlQuery add_query(QString(
" WHERE directory = :id AND path = :path").arg(subdirs_table_));
QSqlQuery add_query(db);
add_query.prepare(QString(
"INSERT INTO %1 (directory, path, mtime)"
" VALUES (:id, :path, :mtime)").arg(subdirs_table_),
db);
QSqlQuery update_query(
QString(
" VALUES (:id, :path, :mtime)").arg(subdirs_table_));
QSqlQuery update_query(db);
update_query.prepare(QString(
"UPDATE %1 SET mtime = :mtime"
" WHERE directory = :id AND path = :path").arg(subdirs_table_),
db);
QSqlQuery delete_query(
QString(
" WHERE directory = :id AND path = :path").arg(subdirs_table_));
QSqlQuery delete_query(db);
delete_query.prepare(QString(
"DELETE FROM %1"
" WHERE directory = :id AND path = :path").arg(subdirs_table_),
db);
" WHERE directory = :id AND path = :path").arg(subdirs_table_));
ScopedTransaction transaction(&db);
for (const Subdirectory& subdir : subdirs) {
@ -349,25 +347,24 @@ void LibraryBackend::AddOrUpdateSongs(const SongList& songs) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery check_dir(
QString("SELECT ROWID FROM %1 WHERE ROWID = :id").arg(dirs_table_), db);
QSqlQuery add_song(QString("INSERT INTO %1 (" + Song::kColumnSpec +
QSqlQuery check_dir(db);
check_dir.prepare(QString("SELECT ROWID FROM %1 WHERE ROWID = :id").arg(dirs_table_));
QSqlQuery add_song(db);
add_song.prepare(QString("INSERT INTO %1 (" + Song::kColumnSpec +
")"
" VALUES (" +
Song::kBindSpec + ")").arg(songs_table_),
db);
QSqlQuery update_song(QString("UPDATE %1 SET " + Song::kUpdateSpec +
" WHERE ROWID = :id").arg(songs_table_),
db);
QSqlQuery add_song_fts(
QString("INSERT INTO %1 (ROWID, " + Song::kFtsColumnSpec +
Song::kBindSpec + ")").arg(songs_table_));
QSqlQuery update_song(db);
update_song.prepare(QString("UPDATE %1 SET " + Song::kUpdateSpec +
" WHERE ROWID = :id").arg(songs_table_));
QSqlQuery add_song_fts(db);
add_song_fts.prepare(QString("INSERT INTO %1 (ROWID, " + Song::kFtsColumnSpec +
")"
" VALUES (:id, " +
Song::kFtsBindSpec + ")").arg(fts_table_),
db);
QSqlQuery update_song_fts(QString("UPDATE %1 SET " + Song::kFtsUpdateSpec +
" WHERE ROWID = :id").arg(fts_table_),
db);
Song::kFtsBindSpec + ")").arg(fts_table_));
QSqlQuery update_song_fts(db);
update_song_fts.prepare(QString("UPDATE %1 SET " + Song::kFtsUpdateSpec +
" WHERE ROWID = :id").arg(fts_table_));
ScopedTransaction transaction(&db);
@ -440,9 +437,9 @@ void LibraryBackend::UpdateMTimesOnly(const SongList& songs) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(QString("UPDATE %1 SET mtime = :mtime WHERE ROWID = :id")
.arg(songs_table_),
db);
QSqlQuery q(db);
q.prepare(QString("UPDATE %1 SET mtime = :mtime WHERE ROWID = :id")
.arg(songs_table_));
ScopedTransaction transaction(&db);
for (const Song& song : songs) {
@ -458,10 +455,10 @@ void LibraryBackend::DeleteSongs(const SongList& songs) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery remove(
QString("DELETE FROM %1 WHERE ROWID = :id").arg(songs_table_), db);
QSqlQuery remove_fts(
QString("DELETE FROM %1 WHERE ROWID = :id").arg(fts_table_), db);
QSqlQuery remove(db);
remove.prepare(QString("DELETE FROM %1 WHERE ROWID = :id").arg(songs_table_));
QSqlQuery remove_fts(db);
remove_fts.prepare(QString("DELETE FROM %1 WHERE ROWID = :id").arg(fts_table_));
ScopedTransaction transaction(&db);
for (const Song& song : songs) {
@ -485,10 +482,10 @@ void LibraryBackend::MarkSongsUnavailable(const SongList& songs,
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery remove(QString("UPDATE %1 SET unavailable = %2 WHERE ROWID = :id")
QSqlQuery remove(db);
remove.prepare(QString("UPDATE %1 SET unavailable = %2 WHERE ROWID = :id")
.arg(songs_table_)
.arg(int(unavailable)),
db);
.arg(int(unavailable)));
ScopedTransaction transaction(&db);
for (const Song& song : songs) {
@ -612,14 +609,14 @@ SongList LibraryBackend::GetSongsByForeignId(const QStringList& ids,
QString in = ids.join(",");
QSqlQuery q(
QString(
QSqlQuery q(db);
q.prepare(
QString(
"SELECT %2.ROWID, " + Song::kColumnSpec +
", %2.%3"
" FROM %2, %1"
" WHERE %2.%3 IN (%4) AND %1.ROWID = %2.ROWID AND unavailable = 0")
.arg(songs_table_, table, column, in),
db);
.arg(songs_table_, table, column, in));
q.exec();
if (db_->CheckErrors(q)) return SongList();
@ -644,10 +641,10 @@ SongList LibraryBackend::GetSongsById(const QStringList& ids,
QSqlDatabase& db) {
QString in = ids.join(",");
QSqlQuery q(QString("SELECT ROWID, " + Song::kColumnSpec +
QSqlQuery q(db);
q.prepare(QString("SELECT ROWID, " + Song::kColumnSpec +
" FROM %1"
" WHERE ROWID IN (%2)").arg(songs_table_, in),
db);
" WHERE ROWID IN (%2)").arg(songs_table_, in));
q.exec();
if (db_->CheckErrors(q)) return SongList();
@ -722,11 +719,11 @@ void LibraryBackend::UpdateCompilations() {
// in the same
// directory
QSqlQuery q(
QSqlQuery q(db);
q.prepare(
QString(
"SELECT effective_albumartist, album, filename, sampler "
"FROM %1 WHERE unavailable = 0 ORDER BY album").arg(songs_table_),
db);
"FROM %1 WHERE unavailable = 0 ORDER BY album").arg(songs_table_));
q.exec();
if (db_->CheckErrors(q)) return;
@ -754,21 +751,21 @@ void LibraryBackend::UpdateCompilations() {
}
// Now mark the songs that we think are in compilations
QSqlQuery update(
QSqlQuery update(db);
update.prepare(
QString(
"UPDATE %1"
" SET sampler = :sampler,"
" effective_compilation = ((compilation OR :sampler OR "
"forced_compilation_on) AND NOT forced_compilation_off) + 0"
" WHERE album = :album AND unavailable = 0").arg(songs_table_),
db);
QSqlQuery find_songs(
" WHERE album = :album AND unavailable = 0").arg(songs_table_));
QSqlQuery find_songs(db);
find_songs.prepare(
QString(
"SELECT ROWID, " + Song::kColumnSpec +
" FROM %1"
" WHERE album = :album AND sampler = :sampler AND unavailable = 0")
.arg(songs_table_),
db);
.arg(songs_table_));
SongList deleted_songs;
SongList added_songs;
@ -932,7 +929,8 @@ void LibraryBackend::UpdateManualAlbumArt(const QString& artist,
" WHERE album = :album AND unavailable = 0").arg(songs_table_));
if (!artist.isNull()) sql += " AND artist = :artist";
QSqlQuery q(sql, db);
QSqlQuery q(db);
q.prepare(sql);
q.bindValue(":art", art);
q.bindValue(":album", album);
if (!artist.isNull()) q.bindValue(":artist", artist);
@ -987,7 +985,8 @@ void LibraryBackend::ForceCompilation(const QString& album,
" WHERE album = :album AND unavailable = 0").arg(songs_table_));
if (!artist.isEmpty()) sql += " AND artist = :artist";
QSqlQuery q(sql, db);
QSqlQuery q(db);
q.prepare(sql);
q.bindValue(":forced_compilation_on", on ? 1 : 0);
q.bindValue(":forced_compilation_off", on ? 0 : 1);
q.bindValue(":album", album);
@ -1025,7 +1024,8 @@ SongList LibraryBackend::FindSongs(const smart_playlists::Search& search) {
// Run the query
SongList ret;
QSqlQuery query(sql, db);
QSqlQuery query(db);
query.prepare(sql);
query.exec();
if (db_->CheckErrors(query)) return ret;
@ -1052,13 +1052,13 @@ void LibraryBackend::IncrementPlayCount(int id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(QString(
QSqlQuery q(db);
q.prepare(QString(
"UPDATE %1 SET playcount = playcount + 1,"
" lastplayed = :now,"
" score = " +
QString(kNewScoreSql).arg("1.0") +
" WHERE ROWID = :id").arg(songs_table_),
db);
" WHERE ROWID = :id").arg(songs_table_));
q.bindValue(":now", QDateTime::currentDateTime().toTime_t());
q.bindValue(":id", id);
q.exec();
@ -1075,12 +1075,12 @@ void LibraryBackend::IncrementSkipCount(int id, float progress) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(QString(
QSqlQuery q(db);
q.prepare(QString(
"UPDATE %1 SET skipcount = skipcount + 1,"
" score = " +
QString(kNewScoreSql).arg(progress) +
" WHERE ROWID = :id").arg(songs_table_),
db);
" WHERE ROWID = :id").arg(songs_table_));
q.bindValue(":id", id);
q.exec();
if (db_->CheckErrors(q)) return;
@ -1095,11 +1095,11 @@ void LibraryBackend::ResetStatistics(int id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(QString(
QSqlQuery q(db);
q.prepare(QString(
"UPDATE %1 SET playcount = 0, skipcount = 0,"
" lastplayed = -1, score = 0"
" WHERE ROWID = :id").arg(songs_table_),
db);
" WHERE ROWID = :id").arg(songs_table_));
q.bindValue(":id", id);
q.exec();
if (db_->CheckErrors(q)) return;
@ -1128,10 +1128,10 @@ void LibraryBackend::UpdateSongsRating(const QList<int>& id_list,
id_str_list << QString::number(i);
}
QString ids = id_str_list.join(",");
QSqlQuery q(QString(
QSqlQuery q(db);
q.prepare(QString(
"UPDATE %1 SET rating = :rating"
" WHERE ROWID IN (%2)").arg(songs_table_, ids),
db);
" WHERE ROWID IN (%2)").arg(songs_table_, ids));
q.bindValue(":rating", rating);
q.exec();
if (db_->CheckErrors(q)) return;

View File

@ -151,7 +151,8 @@ void LibraryModel::Init(bool async) {
new LibraryItem(LibraryItem::Type_LoadingIndicator, root_);
loading->display_text = tr("Loading...");
loading->lazy_loaded = true;
reset();
beginResetModel();
endResetModel();
// Show a loading indicator in the status bar too.
init_task_id_ = app_->task_manager()->StartTask(tr("Loading songs"));

View File

@ -166,7 +166,8 @@ QSqlQuery LibraryQuery::Exec(QSqlDatabase db, const QString& songs_table,
sql.replace("%fts_table_noprefix", fts_table.section('.', -1, -1));
sql.replace("%fts_table", fts_table);
query_ = QSqlQuery(sql, db);
query_ = QSqlQuery(db);
query_.prepare(sql);
// Bind values
for (const QVariant& value : bound_values_) {

View File

@ -69,14 +69,14 @@
#include "tagreadermessages.pb.h"
#include "qtsingleapplication.h"
#include "qtsinglecoreapplication.h"
#include "singleapplication.h"
#include "singlecoreapplication.h"
#include <glib-object.h>
#include <glib.h>
#include <gst/gst.h>
#include <echonest/Config.h>
#include <echonest5/Config.h>
#ifdef HAVE_SPOTIFY_DOWNLOADER
#include <QtCrypto>
@ -109,28 +109,18 @@ const QDBusArgument& operator>>(const QDBusArgument& arg, QImage& image);
// Load sqlite plugin on windows and mac.
#include <QtPlugin>
Q_IMPORT_PLUGIN(qsqlite)
Q_IMPORT_PLUGIN(QSQLiteDriverPlugin)
namespace {
void LoadTranslation(const QString& prefix, const QString& path,
const QString& language) {
#if QT_VERSION < 0x040700
// QTranslator::load will try to open and read "clementine" if it exists,
// without checking if it's a file first.
// This was fixed in Qt 4.7
QFileInfo maybe_clementine_directory(path + "/clementine");
if (maybe_clementine_directory.exists() &&
!maybe_clementine_directory.isFile())
return;
#endif
QTranslator* t = new PoTranslator;
if (t->load(prefix + "_" + language, path))
QCoreApplication::installTranslator(t);
else
delete t;
QTextCodec::setCodecForTr(QTextCodec::codecForLocale());
}
void IncreaseFDLimit() {
@ -272,10 +262,10 @@ int main(int argc, char* argv[]) {
}
#endif
QCoreApplication::setApplicationName("Clementine");
QCoreApplication::setApplicationName("Clementine-qt5");
QCoreApplication::setApplicationVersion(CLEMENTINE_VERSION_DISPLAY);
QCoreApplication::setOrganizationName("Clementine");
QCoreApplication::setOrganizationDomain("clementine-player.org");
QCoreApplication::setOrganizationName("Clementine-qt5");
QCoreApplication::setOrganizationDomain("clementine-player-qt5.org");
// This makes us show up nicely in gnome-volume-control
#if !GLIB_CHECK_VERSION(2, 36, 0)
@ -298,7 +288,7 @@ int main(int argc, char* argv[]) {
// Clementine running without needing an X server.
// This MUST be done before parsing the commandline options so QTextCodec
// gets the right system locale for filenames.
QtSingleCoreApplication a(argc, argv);
SingleCoreApplication a(argc, argv);
CheckPortable();
crash_reporting.SetApplicationPath(a.applicationFilePath());
@ -307,16 +297,6 @@ int main(int argc, char* argv[]) {
if (!options.Parse()) return 1;
logging::SetLevels(options.log_levels());
if (a.isRunning()) {
if (options.is_empty()) {
qLog(Info)
<< "Clementine is already running - activating existing window";
}
if (a.sendMessage(options.Serialize(), 5000)) {
return 0;
}
// Couldn't send the message so start anyway
}
}
#ifdef Q_OS_DARWIN
@ -335,7 +315,7 @@ int main(int argc, char* argv[]) {
// Output the version, so when people attach log output to bug reports they
// don't have to tell us which version they're using.
qLog(Info) << "Clementine" << CLEMENTINE_VERSION_DISPLAY;
qLog(Info) << "Clementine-qt5" << CLEMENTINE_VERSION_DISPLAY;
// Seed the random number generators.
time_t t = time(nullptr);
@ -344,7 +324,7 @@ int main(int argc, char* argv[]) {
IncreaseFDLimit();
QtSingleApplication a(argc, argv);
SingleApplication a(argc, argv);
// A bug in Qt means the wheel_scroll_lines setting gets ignored and replaced
// with the default value of 3 in QApplicationPrivate::initialize.
@ -363,11 +343,6 @@ int main(int argc, char* argv[]) {
a.setQuitOnLastWindowClosed(false);
// Do this check again because another instance might have started by now
if (a.isRunning() && a.sendMessage(options.Serialize(), 5000)) {
return 0;
}
#ifndef Q_OS_DARWIN
// Gnome on Ubuntu has menu icons disabled by default. I think that's a bad
// idea, and makes some menus in Clementine look confusing.
@ -491,10 +466,8 @@ int main(int argc, char* argv[]) {
#ifdef HAVE_DBUS
QObject::connect(&mpris, SIGNAL(RaiseMainWindow()), &w, SLOT(Raise()));
#endif
QObject::connect(&a, SIGNAL(messageReceived(QByteArray)), &w,
SLOT(CommandlineOptionsReceived(QByteArray)));
w.CommandlineOptionsReceived(options);
w.CommandlineOptionsReceived(options);
int ret = a.exec();
#ifdef Q_OS_LINUX

View File

@ -20,8 +20,11 @@
#include <QCoreApplication>
#include <QNetworkReply>
#include <QStringList>
#include <qjson/parser.h>
#include <QUrlQuery>
#include <QJsonParseError>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include "core/closure.h"
#include "core/logging.h"
@ -50,7 +53,9 @@ void AcoustidClient::Start(int id, const QString& fingerprint,
<< Param("fingerprint", fingerprint);
QUrl url(kUrl);
url.setQueryItems(parameters);
QUrlQuery url_query;
url_query.setQueryItems(parameters);
url.setQuery(url_query);
QNetworkRequest req(url);
QNetworkReply* reply = network_->get(req);
@ -94,15 +99,17 @@ void AcoustidClient::RequestFinished(QNetworkReply* reply, int request_id) {
return;
}
QJson::Parser parser;
bool ok = false;
QVariantMap result = parser.parse(reply, &ok).toMap();
if (!ok) {
QJsonParseError error;
QJsonDocument json_document = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
emit Finished(request_id, QStringList());
return;
}
QString status = result["status"].toString();
QJsonObject json_object = json_document.object();
QString status = json_object["status"].toString();
if (status != "ok") {
emit Finished(request_id, QStringList());
return;
@ -113,18 +120,18 @@ void AcoustidClient::RequestFinished(QNetworkReply* reply, int request_id) {
// -then sort results by number of sources (the results are originally
// unsorted but results with more sources are likely to be more accurate)
// -keep only the ids, as sources where useful only to sort the results
QVariantList results = result["results"].toList();
QJsonArray json_results = json_object["results"].toArray();
// List of <id, nb of sources> pairs
QList<IdSource> id_source_list;
for (const QVariant& v : results) {
QVariantMap r = v.toMap();
if (r.contains("recordings")) {
QVariantList recordings = r["recordings"].toList();
for (const QVariant& recording : recordings) {
QVariantMap o = recording.toMap();
if (o.contains("id")) {
for (const QJsonValue& v : json_results) {
QJsonObject r = v.toObject();
if (!r["recordings"].isUndefined()) {
QJsonArray json_recordings = r["recordings"].toArray();
for (const QJsonValue& recording : json_recordings) {
QJsonObject o = recording.toObject();
if (!o["id"].isUndefined()) {
id_source_list << IdSource(o["id"].toString(), o["sources"].toInt());
}
}

View File

@ -44,7 +44,7 @@ Chromaprinter::~Chromaprinter() {}
GstElement* Chromaprinter::CreateElement(const QString& factory_name,
GstElement* bin) {
GstElement* ret = gst_element_factory_make(
factory_name.toAscii().constData(), factory_name.toAscii().constData());
factory_name.toLatin1().constData(), factory_name.toLatin1().constData());
if (ret && bin) gst_bin_add(GST_BIN(bin), ret);

View File

@ -21,6 +21,7 @@
#include <QNetworkReply>
#include <QSet>
#include <QXmlStreamReader>
#include <QUrlQuery>
#include "core/closure.h"
#include "core/logging.h"
@ -50,7 +51,9 @@ void MusicBrainzClient::Start(int id, const QStringList& mbid_list) {
parameters << Param("inc", "artists+releases+media");
QUrl url(kTrackUrl + mbid);
url.setQueryItems(parameters);
QUrlQuery url_query;
url_query.setQueryItems(parameters);
url.setQuery(url_query);
QNetworkRequest req(url);
QNetworkReply* reply = network_->get(req);
@ -74,7 +77,9 @@ void MusicBrainzClient::StartDiscIdRequest(const QString& discid) {
parameters << Param("inc", "artists+recordings");
QUrl url(kDiscUrl + discid);
url.setQueryItems(parameters);
QUrlQuery url_query;
url_query.setQueryItems(parameters);
url.setQuery(url_query);
QNetworkRequest req(url);
QNetworkReply* reply = network_->get(req);

View File

@ -180,7 +180,7 @@ void OutgoingDataCreator::SendClementineInfo() {
QString version =
QString("%1 %2").arg(QCoreApplication::applicationName(),
QCoreApplication::applicationVersion());
info->set_version(version.toAscii());
info->set_version(version.toLatin1());
SendDataToClients(&msg);
}

View File

@ -78,14 +78,13 @@ PlaylistBackend::PlaylistList PlaylistBackend::GetPlaylists(
condition = " WHERE " + condition_list.join(" OR ");
}
QSqlQuery q(
"SELECT ROWID, name, last_played, dynamic_playlist_type,"
QSqlQuery q(db);
q.prepare("SELECT ROWID, name, last_played, dynamic_playlist_type,"
" dynamic_playlist_data, dynamic_playlist_backend,"
" special_type, ui_path, is_favorite"
" FROM playlists"
" " +
condition + " ORDER BY ui_order",
db);
condition + " ORDER BY ui_order");
q.exec();
if (db_->CheckErrors(q)) return ret;
@ -110,13 +109,12 @@ PlaylistBackend::Playlist PlaylistBackend::GetPlaylist(int id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(
"SELECT ROWID, name, last_played, dynamic_playlist_type,"
QSqlQuery q(db);
q.prepare("SELECT ROWID, name, last_played, dynamic_playlist_type,"
" dynamic_playlist_data, dynamic_playlist_backend,"
" special_type, ui_path, is_favorite"
" FROM playlists"
" WHERE ROWID=:id",
db);
" WHERE ROWID=:id");
q.bindValue(":id", id);
q.exec();
if (db_->CheckErrors(q)) return Playlist();
@ -293,23 +291,22 @@ void PlaylistBackend::SavePlaylist(int playlist, const PlaylistItemList& items,
qLog(Debug) << "Saving playlist" << playlist;
QSqlQuery clear("DELETE FROM playlist_items WHERE playlist = :playlist", db);
QSqlQuery insert(
"INSERT INTO playlist_items"
QSqlQuery clear(db);
clear.prepare("DELETE FROM playlist_items WHERE playlist = :playlist");
QSqlQuery insert(db);
insert.prepare("INSERT INTO playlist_items"
" (playlist, type, library_id, radio_service, " +
Song::kColumnSpec +
")"
" VALUES (:playlist, :type, :library_id, :radio_service, " +
Song::kBindSpec + ")",
db);
QSqlQuery update(
"UPDATE playlists SET "
Song::kBindSpec + ")");
QSqlQuery update(db);
update.prepare("UPDATE playlists SET "
" last_played=:last_played,"
" dynamic_playlist_type=:dynamic_type,"
" dynamic_playlist_data=:dynamic_data,"
" dynamic_playlist_backend=:dynamic_backend"
" WHERE ROWID=:playlist",
db);
" WHERE ROWID=:playlist");
ScopedTransaction transaction(&db);
@ -350,10 +347,10 @@ int PlaylistBackend::CreatePlaylist(const QString& name,
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q(
QSqlQuery q(db);
q.prepare(
"INSERT INTO playlists (name, special_type)"
" VALUES (:name, :special_type)",
db);
" VALUES (:name, :special_type)");
q.bindValue(":name", name);
q.bindValue(":special_type", special_type);
q.exec();
@ -365,8 +362,10 @@ int PlaylistBackend::CreatePlaylist(const QString& name,
void PlaylistBackend::RemovePlaylist(int id) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery delete_playlist("DELETE FROM playlists WHERE ROWID=:id", db);
QSqlQuery delete_items("DELETE FROM playlist_items WHERE playlist=:id", db);
QSqlQuery delete_playlist(db);
delete_playlist.prepare("DELETE FROM playlists WHERE ROWID=:id");
QSqlQuery delete_items(db);
delete_items.prepare("DELETE FROM playlist_items WHERE playlist=:id");
delete_playlist.bindValue(":id", id);
delete_items.bindValue(":id", id);
@ -385,7 +384,8 @@ void PlaylistBackend::RemovePlaylist(int id) {
void PlaylistBackend::RenamePlaylist(int id, const QString& new_name) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("UPDATE playlists SET name=:name WHERE ROWID=:id", db);
QSqlQuery q(db);
q.prepare("UPDATE playlists SET name=:name WHERE ROWID=:id");
q.bindValue(":name", new_name);
q.bindValue(":id", id);
@ -396,8 +396,8 @@ void PlaylistBackend::RenamePlaylist(int id, const QString& new_name) {
void PlaylistBackend::FavoritePlaylist(int id, bool is_favorite) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("UPDATE playlists SET is_favorite=:is_favorite WHERE ROWID=:id",
db);
QSqlQuery q(db);
q.prepare("UPDATE playlists SET is_favorite=:is_favorite WHERE ROWID=:id");
q.bindValue(":is_favorite", is_favorite ? 1 : 0);
q.bindValue(":id", id);
@ -410,11 +410,12 @@ void PlaylistBackend::SetPlaylistOrder(const QList<int>& ids) {
QSqlDatabase db(db_->Connect());
ScopedTransaction transaction(&db);
QSqlQuery q("UPDATE playlists SET ui_order=-1", db);
QSqlQuery q(db);
q.prepare("UPDATE playlists SET ui_order=-1");
q.exec();
if (db_->CheckErrors(q)) return;
q = QSqlQuery("UPDATE playlists SET ui_order=:index WHERE ROWID=:id", db);
q.prepare("UPDATE playlists SET ui_order=:index WHERE ROWID=:id");
for (int i = 0; i < ids.count(); ++i) {
q.bindValue(":index", i);
q.bindValue(":id", ids[i]);
@ -428,7 +429,8 @@ void PlaylistBackend::SetPlaylistOrder(const QList<int>& ids) {
void PlaylistBackend::SetPlaylistUiPath(int id, const QString& path) {
QMutexLocker l(db_->Mutex());
QSqlDatabase db(db_->Connect());
QSqlQuery q("UPDATE playlists SET ui_path=:path WHERE ROWID=:id", db);
QSqlQuery q(db);
q.prepare("UPDATE playlists SET ui_path=:path WHERE ROWID=:id");
ScopedTransaction transaction(&db);

View File

@ -220,7 +220,7 @@ bool PlaylistDelegateBase::helpEvent(QHelpEvent* event, QAbstractItemView* view,
// Special case: we want newlines in the comment tooltip
if (index.column() == Playlist::Column_Comment) {
text = Qt::escape(index.data(Qt::ToolTipRole).toString());
text = index.data(Qt::ToolTipRole).toString().toHtmlEscaped();
text.replace("\\r\\n", "<br />");
text.replace("\\n", "<br />");
text.replace("\r\n", "<br />");
@ -436,7 +436,7 @@ QString NativeSeparatorsDelegate::displayText(const QVariant& value,
if (value.type() == QVariant::Url) {
url = value.toUrl();
} else if (string_value.contains("://")) {
url = QUrl::fromEncoded(string_value.toAscii());
url = QUrl::fromEncoded(string_value.toLatin1());
} else {
return QDir::toNativeSeparators(string_value);
}

View File

@ -27,7 +27,7 @@
#include "covers/currentartloader.h"
#include "ui/qt_blurimage.h"
#include <QCleanlooksStyle>
#include <QCommonStyle>
#include <QClipboard>
#include <QPainter>
#include <QHeaderView>
@ -39,6 +39,7 @@
#include <QSortFilterProxyModel>
#include <QScrollBar>
#include <QTimeLine>
#include <QMimeData>
#include <math.h>
@ -60,7 +61,7 @@ const int PlaylistView::kDefaultBlurRadius = 0;
const int PlaylistView::kDefaultOpacityLevel = 40;
PlaylistProxyStyle::PlaylistProxyStyle(QStyle* base)
: QProxyStyle(base), cleanlooks_(new QCleanlooksStyle) {}
: QProxyStyle(base), common_style_(new QCommonStyle) {}
void PlaylistProxyStyle::drawControl(ControlElement element,
const QStyleOption* option,
@ -85,7 +86,7 @@ void PlaylistProxyStyle::drawControl(ControlElement element,
}
if (element == CE_ItemViewItem)
cleanlooks_->drawControl(element, option, painter, widget);
common_style_->drawControl(element, option, painter, widget);
else
QProxyStyle::drawControl(element, option, painter, widget);
}
@ -96,7 +97,7 @@ void PlaylistProxyStyle::drawPrimitive(PrimitiveElement element,
const QWidget* widget) const {
if (element == QStyle::PE_PanelItemViewRow ||
element == QStyle::PE_PanelItemViewItem)
cleanlooks_->drawPrimitive(element, option, painter, widget);
common_style_->drawPrimitive(element, option, painter, widget);
else
QProxyStyle::drawPrimitive(element, option, painter, widget);
}
@ -132,7 +133,7 @@ PlaylistView::PlaylistView(QWidget* parent)
drag_over_(false),
dynamic_controls_(new DynamicPlaylistControls(this)) {
setHeader(header_);
header_->setMovable(true);
header_->setSectionsMovable(true);
setStyle(style_);
setMouseTracking(true);

View File

@ -26,7 +26,7 @@
#include "playlist.h"
class QCleanlooksStyle;
class QCommonStyle;
class Application;
class DynamicPlaylistControls;
@ -40,7 +40,7 @@ class QTimeLine;
// that uses Gtk to paint row backgrounds, ignoring any custom brush or palette
// the caller set in the QStyleOption. That breaks our currently playing track
// animation, which relies on the background painted by Qt to be transparent.
// This proxy style uses QCleanlooksStyle to paint the affected elements.
// This proxy style uses QCommonStyle to paint the affected elements.
// This class is used by the global search view as well.
class PlaylistProxyStyle : public QProxyStyle {
public:
@ -51,7 +51,7 @@ class PlaylistProxyStyle : public QProxyStyle {
QPainter* painter, const QWidget* widget) const;
private:
std::unique_ptr<QCleanlooksStyle> cleanlooks_;
std::unique_ptr<QCommonStyle> common_style_;
};
class PlaylistView : public QTreeView {

View File

@ -118,7 +118,7 @@ SearchTermWidget::SearchTermWidget(LibraryBackend* library, QWidget* parent)
// Set stylesheet
QFile stylesheet_file(":/smartplaylistsearchterm.css");
stylesheet_file.open(QIODevice::ReadOnly);
QString stylesheet = QString::fromAscii(stylesheet_file.readAll());
QString stylesheet = QString::fromLatin1(stylesheet_file.readAll());
const QColor base(222, 97, 97, 128);
stylesheet.replace("%light2", Utilities::ColorToRgba(base.lighter(140)));
stylesheet.replace("%light", Utilities::ColorToRgba(base.lighter(120)));

View File

@ -59,7 +59,7 @@ SongInfoBase::SongInfoBase(QWidget* parent)
// Set stylesheet
QFile stylesheet(":/songinfo.css");
stylesheet.open(QIODevice::ReadOnly);
setStyleSheet(QString::fromAscii(stylesheet.readAll()));
setStyleSheet(QString::fromLatin1(stylesheet.readAll()));
connect(fetcher_, SIGNAL(ResultReady(int, SongInfoFetcher::Result)),
SLOT(ResultReady(int, SongInfoFetcher::Result)));

View File

@ -20,11 +20,12 @@
#include <QImage>
#include <QVBoxLayout>
#include <QXmlStreamWriter>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <echonest/Artist.h>
#include <qjson/parser.h>
#include "core/closure.h"
#include "core/logging.h"
#include "songkickconcertwidget.h"
@ -107,22 +108,23 @@ void SongkickConcerts::FetchSongkickCalendar(const QString& artist_id, int id) {
}
void SongkickConcerts::CalendarRequestFinished(QNetworkReply* reply, int id) {
QJson::Parser parser;
bool ok = false;
QVariant result = parser.parse(reply, &ok);
reply->deleteLater();
if (!ok) {
QJsonParseError error;
QJsonDocument json_document = QJsonDocument::fromJson(reply->readAll(), &error);
if (error.error != QJsonParseError::NoError) {
qLog(Error) << "Error parsing Songkick reply";
emit Finished(id);
return;
}
QVariantMap root = result.toMap();
QVariantMap results_page = root["resultsPage"].toMap();
QVariantMap results = results_page["results"].toMap();
QVariantList events = results["event"].toList();
QJsonObject json_root = json_document.object();
QJsonObject json_results_page = json_root["resultsPage"].toObject();
QJsonObject json_results = json_results_page["results"].toObject();
QJsonArray json_events = json_results["event"].toArray();
if (events.isEmpty()) {
if (json_events.isEmpty()) {
emit Finished(id);
return;
}
@ -130,21 +132,21 @@ void SongkickConcerts::CalendarRequestFinished(QNetworkReply* reply, int id) {
QWidget* container = new QWidget;
QVBoxLayout* layout = new QVBoxLayout(container);
for (const QVariant& v : events) {
QVariantMap event = v.toMap();
QString display_name = event["displayName"].toString();
QString start_date = event["start"].toMap()["date"].toString();
QString city = event["location"].toMap()["city"].toString();
QString uri = event["uri"].toString();
for (const QJsonValue& v : json_events) {
QJsonObject json_event = v.toObject();
QString display_name = json_event["displayName"].toString();
QString start_date = json_event["start"].toObject()["date"].toString();
QString city = json_event["location"].toObject()["city"].toString();
QString uri = json_event["uri"].toString();
// Try to get the lat/lng coordinates of the venue.
QVariantMap venue = event["venue"].toMap();
const bool valid_latlng = venue["lng"].isValid() && venue["lat"].isValid();
QJsonObject json_venue = json_event["venue"].toObject();
const bool valid_latlng = !json_venue["lng"].isUndefined() && !json_venue["lat"].isUndefined();
if (valid_latlng && latlng_.IsValid()) {
static const int kFilterDistanceMetres = 250 * 1e3; // 250km
Geolocator::LatLng latlng(venue["lat"].toString(),
venue["lng"].toString());
Geolocator::LatLng latlng(json_venue["lat"].toString(),
json_venue["lng"].toString());
if (latlng_.IsValid() && latlng.IsValid()) {
int distance_metres = latlng_.Distance(latlng);
if (distance_metres > kFilterDistanceMetres) {
@ -159,8 +161,8 @@ void SongkickConcerts::CalendarRequestFinished(QNetworkReply* reply, int id) {
widget->Init(display_name, uri, start_date, city);
if (valid_latlng) {
widget->SetMap(venue["lat"].toString(), venue["lng"].toString(),
venue["displayName"].toString());
widget->SetMap(json_venue["lat"].toString(), json_venue["lng"].toString(),
json_venue["displayName"].toString());
}
layout->addWidget(widget);

View File

@ -21,6 +21,7 @@
#include <QDesktopServices>
#include <QMouseEvent>
#include <QTextDocument>
#include <QUrlQuery>
#include "songinfotextview.h"
#include "ui_songkickconcertwidget.h"
@ -58,7 +59,7 @@ void SongKickConcertWidget::ReloadSettings() {
void SongKickConcertWidget::Init(const QString& title, const QString& url,
const QString& date, const QString& location) {
ui_->title->setText(
QString("<a href=\"%1\">%2</a>").arg(Qt::escape(url), Qt::escape(title)));
QString("<a href=\"%1\">%2</a>").arg(url.toHtmlEscaped(), title.toHtmlEscaped()));
if (!location.isEmpty()) {
ui_->location->setText(location);
@ -96,10 +97,12 @@ void SongKickConcertWidget::SetMap(const QString& lat, const QString& lng,
ui_->map->show();
map_url_ = QUrl("https://maps.google.com/");
map_url_.addQueryItem("ll", QString("%1,%2").arg(lat, lng));
QUrlQuery map_url_query;
map_url_query.addQueryItem("ll", QString("%1,%2").arg(lat, lng));
if (!venue_name.isEmpty()) {
map_url_.addQueryItem("q", venue_name);
map_url_query.addQueryItem("q", venue_name);
}
map_url_.setQuery(map_url_query);
// Request the static map image
const QUrl url(QString(kStaticMapUrl).arg(QString::number(kStaticMapWidth),

View File

@ -37,7 +37,7 @@ UltimateLyricsProvider::UltimateLyricsProvider()
void UltimateLyricsProvider::FetchInfo(int id, const Song& metadata) {
// Get the text codec
const QTextCodec* codec =
QTextCodec::codecForName(charset_.toAscii().constData());
QTextCodec::codecForName(charset_.toLatin1().constData());
if (!codec) {
qLog(Warning) << "Invalid codec" << charset_;
emit Finished(id);
@ -100,7 +100,7 @@ void UltimateLyricsProvider::LyricsFetched() {
}
const QTextCodec* codec =
QTextCodec::codecForName(charset_.toAscii().constData());
QTextCodec::codecForName(charset_.toLatin1().constData());
const QString original_content = codec->toUnicode(reply->readAll());
QString lyrics;

View File

@ -54,7 +54,7 @@ TranscodeDialog::TranscodeDialog(QWidget* parent)
finished_success_(0),
finished_failed_(0) {
ui_->setupUi(this);
ui_->files->header()->setResizeMode(QHeaderView::ResizeToContents);
ui_->files->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
log_ui_->setupUi(log_dialog_);
QPushButton* clear_button =

View File

@ -47,9 +47,9 @@ TranscoderPreset::TranscoderPreset(Song::FileType type, const QString& name,
GstElement* Transcoder::CreateElement(const QString& factory_name,
GstElement* bin, const QString& name) {
GstElement* ret = gst_element_factory_make(
factory_name.toAscii().constData(),
name.isNull() ? factory_name.toAscii().constData()
: name.toAscii().constData());
factory_name.toLatin1().constData(),
name.isNull() ? factory_name.toLatin1().constData()
: name.toLatin1().constData());
if (ret && bin) gst_bin_add(GST_BIN(bin), ret);

View File

@ -39,6 +39,7 @@
#include <QList>
#include <QMenu>
#include <QUrl>
#include <QMimeData>
const char* AlbumCoverChoiceController::kLoadImageFileFilter = QT_TR_NOOP(
"Images (*.png *.jpg *.jpeg *.bmp *.gif *.xpm *.pbm *.pgm *.ppm *.xbm)");

View File

@ -461,21 +461,20 @@ void EditTagDialog::UpdateSummaryTab(const Song& song) {
app_->album_cover_loader()->LoadImageAsync(cover_options_, song);
QString summary =
"<b>" + Qt::escape(song.PrettyTitleWithArtist()) + "</b><br/>";
"<b>" + song.PrettyTitleWithArtist().toHtmlEscaped() + "</b><br/>";
bool art_is_set = true;
if (song.has_manually_unset_cover()) {
summary += Qt::escape(tr("Cover art manually unset"));
summary += tr("Cover art manually unset").toHtmlEscaped();
art_is_set = false;
} else if (!song.art_manual().isEmpty()) {
summary += Qt::escape(tr("Cover art set from %1").arg(song.art_manual()));
summary += tr("Cover art set from %1").arg(song.art_manual()).toHtmlEscaped();
} else if (song.has_embedded_cover()) {
summary += Qt::escape(tr("Cover art from embedded image"));
summary += tr("Cover art from embedded image");
} else if (!song.art_automatic().isEmpty()) {
summary += Qt::escape(
tr("Cover art loaded automatically from %1").arg(song.art_automatic()));
summary += tr("Cover art loaded automatically from %1").arg(song.art_automatic()).toHtmlEscaped();
} else {
summary += Qt::escape(tr("Cover art not set"));
summary += tr("Cover art not set").toHtmlEscaped();
art_is_set = false;
}

View File

@ -38,7 +38,7 @@
**
****************************************************************************/
#include <QtGui>
#include <QWidget>
#include "flowlayout.h"
//! [1]

View File

@ -39,7 +39,7 @@ GlobalShortcutsSettingsPage::GlobalShortcutsSettingsPage(SettingsDialog* dialog)
grabber_(new GlobalShortcutGrabber) {
ui_->setupUi(this);
ui_->shortcut_options->setEnabled(false);
ui_->list->header()->setResizeMode(QHeaderView::ResizeToContents);
ui_->list->header()->setSectionResizeMode(QHeaderView::ResizeToContents);
setWindowIcon(IconLoader::Load("input-keyboard"));
settings_.beginGroup(GlobalShortcuts::kSettingsGroup);

View File

@ -951,7 +951,6 @@ MainWindow::~MainWindow() {
void MainWindow::ReloadSettings() {
#ifndef Q_OS_DARWIN
bool show_tray = settings_.value("showtray", true).toBool();
tray_icon_->SetVisible(show_tray);
if (!show_tray && !isVisible()) show();
#endif

View File

@ -57,7 +57,7 @@ QtSystemTrayIcon::QtSystemTrayIcon(QObject* parent)
QFile pattern_file(":/now_playing_tooltip.txt");
pattern_file.open(QIODevice::ReadOnly);
pattern_ = QString::fromAscii(pattern_file.readAll());
pattern_ = QString::fromLatin1(pattern_file.readAll());
connect(tray_, SIGNAL(activated(QSystemTrayIcon::ActivationReason)),
SLOT(Clicked(QSystemTrayIcon::ActivationReason)));
@ -216,7 +216,7 @@ void QtSystemTrayIcon::SetVisible(bool visible) { tray_->setVisible(visible); }
void QtSystemTrayIcon::SetNowPlaying(const Song& song,
const QString& image_path) {
#ifdef Q_WS_WIN
#ifdef Q_OS_WIN
// Windows doesn't support HTML in tooltips, so just show something basic
tray_->setToolTip(song.PrettyTitleWithArtist());
return;
@ -230,14 +230,14 @@ void QtSystemTrayIcon::SetNowPlaying(const Song& song,
clone.replace("%appName", QCoreApplication::applicationName());
clone.replace("%titleKey", tr("Title") % ":");
clone.replace("%titleValue", Qt::escape(song.PrettyTitle()));
clone.replace("%titleValue", song.PrettyTitle().toHtmlEscaped());
clone.replace("%artistKey", tr("Artist") % ":");
clone.replace("%artistValue", Qt::escape(song.artist()));
clone.replace("%artistValue", song.artist().toHtmlEscaped());
clone.replace("%albumKey", tr("Album") % ":");
clone.replace("%albumValue", Qt::escape(song.album()));
clone.replace("%albumValue", song.album().toHtmlEscaped());
clone.replace("%lengthKey", tr("Length") % ":");
clone.replace("%lengthValue", Qt::escape(song.PrettyLength()));
clone.replace("%lengthValue", song.PrettyLength().toHtmlEscaped());
if (columns == 2) {
QString final_path =

View File

@ -53,7 +53,7 @@ void ErrorDialog::UpdateContent() {
QString html;
for (const QString& message : current_messages_) {
if (!html.isEmpty()) html += "<hr/>";
html += Qt::escape(message);
html += message.toHtmlEscaped();
}
ui_->messages->setHtml(html);
}

View File

@ -47,7 +47,7 @@
#include <QToolButton>
#include <QToolTip>
#include <QVBoxLayout>
#include <QWindowsStyle>
#include <QCommonStyle>
using namespace Core;
using namespace Internal;
@ -128,7 +128,7 @@ void FancyTabProxyStyle::drawControl(ControlElement element,
p->drawText(text_rect, textFlags, text);
p->setPen(selected ? QColor(60, 60, 60)
: Utils::StyleHelper::panelTextColor());
#ifndef Q_WS_MAC
#ifndef Q_OS_MAC
if (widget) {
const QString fader_key = "tab_" + text + "_fader";
const QString animation_key = "tab_" + text + "_animation";
@ -253,7 +253,7 @@ void FancyTab::setFader(float value) {
FancyTabBar::FancyTabBar(QWidget* parent) : QWidget(parent) {
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Expanding);
setStyle(new QWindowsStyle);
setStyle(new QCommonStyle);
setMinimumWidth(qMax(2 * m_rounding, 40));
setAttribute(Qt::WA_Hover, true);
setFocusPolicy(Qt::NoFocus);
@ -439,7 +439,7 @@ void FancyTabBar::paintTab(QPainter* painter, int tabIndex) const {
painter->drawText(tabTextRect, textFlags, tabText);
painter->setPen(selected ? QColor(60, 60, 60)
: Utils::StyleHelper::panelTextColor());
#ifndef Q_WS_MAC
#ifndef Q_OS_MAC
if (!selected) {
painter->save();
int fader = int(m_tabs[tabIndex]->fader());

View File

@ -29,8 +29,7 @@ ForceScrollPerPixel::ForceScrollPerPixel(QAbstractItemView* item_view,
bool ForceScrollPerPixel::eventFilter(QObject* object, QEvent* event) {
if (object == item_view_ && event->type() != QEvent::Destroy &&
event->type() != QEvent::WinIdChange &&
event->type() != QEvent::AccessibilityPrepare) {
event->type() != QEvent::WinIdChange) {
item_view_->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
item_view_->verticalScrollBar()->setSingleStep(20);
}

View File

@ -108,7 +108,7 @@ void GroupedIconView::rowsInserted(const QModelIndex& parent, int start,
}
void GroupedIconView::dataChanged(const QModelIndex& topLeft,
const QModelIndex& bottomRight) {
const QModelIndex& bottomRight, const QVector<int> &) {
QListView::dataChanged(topLeft, bottomRight);
LayoutItems();
}

View File

@ -72,7 +72,7 @@ class GroupedIconView : public QListView {
void resizeEvent(QResizeEvent* e);
// QAbstractItemView
void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& = QVector<int>());
QModelIndex indexAt(const QPoint& p) const;
void rowsInserted(const QModelIndex& parent, int start, int end);
void setSelection(const QRect& rect,

View File

@ -290,8 +290,8 @@ void NowPlayingWidget::UpdateDetailsText() {
// TODO: Make this configurable
html += QString("<i>%1</i><br/>%2<br/>%3").arg(
Qt::escape(metadata_.PrettyTitle()), Qt::escape(metadata_.artist()),
Qt::escape(metadata_.album()));
metadata_.PrettyTitle().toHtmlEscaped(), metadata_.artist().toHtmlEscaped(),
metadata_.album().toHtmlEscaped());
html += "</p>";
details_->setHtml(html);

View File

@ -30,12 +30,12 @@
#include "stylehelper.h"
#include <QtGui/QPixmapCache>
#include <QtGui/QWidget>
#include <QWidget>
#include <QtCore/QRect>
#include <QtGui/QPainter>
#include <QtGui/QApplication>
#include <QApplication>
#include <QtGui/QPalette>
#include <QtGui/QStyleOption>
#include <QStyleOption>
#include <QtCore/QObject>
// Clamps float color values within (0, 255)
@ -47,7 +47,7 @@ static int clamp(float x) {
namespace Utils {
qreal StyleHelper::sidebarFontSize() {
#if defined(Q_WS_MAC)
#if defined(Q_OS_MAC)
return 10;
#else
return 7.5;

View File

@ -30,8 +30,8 @@
#ifndef STYLEHELPER_H
#define STYLEHELPER_H
#include <QtGui/QColor>
#include <QtGui/QStyle>
#include <QColor>
#include <QStyle>
#include "ui/qt_blurimage.h"

View File

@ -63,13 +63,15 @@ TEST_F(ScopedTransactionTest, RollbackOnDtor) {
ScopedTransaction t(&database_);
database_.exec("INSERT INTO foo (bar) VALUES (42)");
QSqlQuery q("SELECT * FROM foo", database_);
QSqlQuery q(database_);
q.prepare("SELECT * FROM foo");
ASSERT_TRUE(q.exec());
ASSERT_TRUE(q.next());
EXPECT_EQ(42, q.value(0).toInt());
}
QSqlQuery q("SELECT * FROM foo", database_);
QSqlQuery q(database_);
q.prepare("SELECT * FROM foo");
ASSERT_TRUE(q.exec());
ASSERT_FALSE(q.next());
}
@ -83,7 +85,8 @@ TEST_F(ScopedTransactionTest, Commit) {
t.Commit();
}
QSqlQuery q("SELECT * FROM foo", database_);
QSqlQuery q(database_);
q.prepare("SELECT * FROM foo");
ASSERT_TRUE(q.exec());
ASSERT_TRUE(q.next());
EXPECT_EQ(42, q.value(0).toInt());

View File

@ -17,8 +17,6 @@
#include <QApplication>
#include <QFile>
#include <QWebFrame>
#include <QWebPage>
#include <QXmlStreamWriter>
#include <QtDebug>