Show track info in context-view as well as artist and album info. Track info is stacked behind lyrics.
This commit is contained in:
committed by
craig.p.drummond
parent
f333fd6399
commit
110ca299c1
@@ -141,6 +141,8 @@
|
||||
88. Open search-widget as soon as user starts typing in view.
|
||||
89. If artist is different to album-artist, then show track title as
|
||||
"title - artist"
|
||||
90. Show track info in context-view as well as artist and album info. Track
|
||||
info is stacked behind lyrics.
|
||||
|
||||
1.3.4
|
||||
-----
|
||||
|
||||
@@ -68,7 +68,7 @@ AlbumView::AlbumView(QWidget *p)
|
||||
connect(text, SIGNAL(anchorClicked(QUrl)), SLOT(playSong(QUrl)));
|
||||
text->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(text, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
||||
setStandardHeader(i18n("Album Information"));
|
||||
setStandardHeader(i18n("Album"));
|
||||
int imageSize=fontMetrics().height()*18;
|
||||
setPicSize(QSize(imageSize, imageSize));
|
||||
clear();
|
||||
|
||||
@@ -57,12 +57,12 @@ private Q_SLOTS:
|
||||
void showContextMenu(const QPoint &pos);
|
||||
void refresh();
|
||||
void clearCache();
|
||||
void searchResponse(const QString &resp, const QString &lang);
|
||||
|
||||
private:
|
||||
void clearDetails();
|
||||
void getTrackListing();
|
||||
void getDetails();
|
||||
void searchResponse(const QString &resp, const QString &lang);
|
||||
void updateDetails(bool preservePos=false);
|
||||
void abort();
|
||||
|
||||
|
||||
@@ -90,7 +90,7 @@ ArtistView::ArtistView(QWidget *parent)
|
||||
connect(text, SIGNAL(anchorClicked(QUrl)), SLOT(show(QUrl)));
|
||||
text->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(text, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
||||
setStandardHeader(i18n("Artist Information"));
|
||||
setStandardHeader(i18n("Artist"));
|
||||
|
||||
int imageHeight=fontMetrics().height()*14;
|
||||
int imageWidth=imageHeight*1.5;
|
||||
|
||||
@@ -68,10 +68,10 @@ private Q_SLOTS:
|
||||
void handleSimilarReply();
|
||||
void show(const QUrl &url);
|
||||
void clearCache();
|
||||
void searchResponse(const QString &resp, const QString &lang);
|
||||
|
||||
private:
|
||||
void loadBio();
|
||||
void searchResponse(const QString &resp, const QString &lang);
|
||||
void loadSimilar();
|
||||
void requestSimilar();
|
||||
QStringList parseSimilarResponse(const QByteArray &resp);
|
||||
|
||||
@@ -36,7 +36,8 @@ class ContextEngine : public QObject
|
||||
public:
|
||||
enum Mode {
|
||||
Artist,
|
||||
Album
|
||||
Album,
|
||||
Track
|
||||
};
|
||||
|
||||
static ContextEngine * create(QObject *parent);
|
||||
|
||||
@@ -366,7 +366,7 @@ void ContextWidget::setWide(bool w)
|
||||
viewSelector=new ViewSelector(standardContext);
|
||||
viewSelector->addItem(i18n("&Artist"), "artist");
|
||||
viewSelector->addItem(i18n("Al&bum"), "album");
|
||||
viewSelector->addItem(i18n("&Lyrics"), "song");
|
||||
viewSelector->addItem(i18n("&Track"), "song");
|
||||
viewSelector->setPalette(palette());
|
||||
connect(viewSelector, SIGNAL(activated(int)), stack, SLOT(setCurrentIndex(int)));
|
||||
}
|
||||
|
||||
@@ -74,13 +74,24 @@ void LastFmEngine::search(const QStringList &query, Mode mode)
|
||||
QUrlQuery urlQuery;
|
||||
#endif
|
||||
|
||||
urlQuery.addQueryItem("method", Artist==mode ? "artist.getInfo" : "album.getInfo");
|
||||
switch (mode) {
|
||||
case Artist:
|
||||
urlQuery.addQueryItem("method", "artist.getInfo");
|
||||
break;
|
||||
case Album:
|
||||
urlQuery.addQueryItem("method", "album.getInfo");
|
||||
urlQuery.addQueryItem("album", fixedQuery.at(1));
|
||||
break;
|
||||
case Track:
|
||||
urlQuery.addQueryItem("method", "track.getInfo");
|
||||
urlQuery.addQueryItem("track", fixedQuery.at(1));
|
||||
break;
|
||||
}
|
||||
|
||||
urlQuery.addQueryItem("api_key", Covers::constLastFmApiKey);
|
||||
urlQuery.addQueryItem("autocorrect", "1");
|
||||
urlQuery.addQueryItem("artist", Covers::fixArtist(fixedQuery.at(0)));
|
||||
if (Album==mode) {
|
||||
urlQuery.addQueryItem("album", fixedQuery.at(1));
|
||||
}
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
url.setQuery(urlQuery);
|
||||
#endif
|
||||
@@ -115,7 +126,20 @@ void LastFmEngine::parseResponse()
|
||||
}
|
||||
|
||||
Mode mode=(Mode)reply->property(constModeProperty).toInt();
|
||||
QString text=Artist==mode ? parseArtistResponse(data) : parseAlbumResponse(data);
|
||||
QString text;
|
||||
|
||||
switch (mode) {
|
||||
case Artist:
|
||||
text=parseResponse(data, QLatin1String("artist"), QLatin1String("bio"));
|
||||
break;
|
||||
case Album:
|
||||
text=parseResponse(data, QLatin1String("album"), QLatin1String("wiki"));
|
||||
break;
|
||||
case Track:
|
||||
text=parseResponse(data, QLatin1String("track"), QLatin1String("wiki"));
|
||||
break;
|
||||
}
|
||||
|
||||
if (!text.isEmpty()) {
|
||||
static const QRegExp constLicense("User-contributed text is available.*");
|
||||
text.remove(constLicense);
|
||||
@@ -141,37 +165,14 @@ void LastFmEngine::parseResponse()
|
||||
emit searchResult(text, text.isEmpty() ? QString() : constLang);
|
||||
}
|
||||
|
||||
QString LastFmEngine::parseArtistResponse(const QByteArray &data)
|
||||
QString LastFmEngine::parseResponse(const QByteArray &data, const QString &firstTag, const QString &secondTag)
|
||||
{
|
||||
DBUG << __FUNCTION__ << data;
|
||||
QXmlStreamReader xml(data);
|
||||
while (xml.readNextStartElement()) {
|
||||
if (QLatin1String("artist")==xml.name()) {
|
||||
if (firstTag==xml.name()) {
|
||||
while (xml.readNextStartElement()) {
|
||||
if (QLatin1String("bio")==xml.name()) {
|
||||
while (xml.readNextStartElement()) {
|
||||
if (QLatin1String("content")==xml.name()) {
|
||||
return xml.readElementText().trimmed();
|
||||
} else {
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
xml.skipCurrentElement();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return QString();
|
||||
}
|
||||
|
||||
QString LastFmEngine::parseAlbumResponse(const QByteArray &data)
|
||||
{
|
||||
QXmlStreamReader xml(data);
|
||||
while (xml.readNextStartElement()) {
|
||||
if (QLatin1String("album")==xml.name()) {
|
||||
while (xml.readNextStartElement()) {
|
||||
if (QLatin1String("wiki")==xml.name()) {
|
||||
if (secondTag==xml.name()) {
|
||||
while (xml.readNextStartElement()) {
|
||||
if (QLatin1String("content")==xml.name()) {
|
||||
return xml.readElementText().trimmed();
|
||||
|
||||
@@ -50,8 +50,7 @@ private Q_SLOTS:
|
||||
void parseResponse();
|
||||
|
||||
private:
|
||||
QString parseArtistResponse(const QByteArray &data);
|
||||
QString parseAlbumResponse(const QByteArray &data);
|
||||
QString parseResponse(const QByteArray &data, const QString &firstTag, const QString &secondTag);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -25,7 +25,9 @@
|
||||
#include "lyricsdialog.h"
|
||||
#include "ultimatelyricsprovider.h"
|
||||
#include "ultimatelyrics.h"
|
||||
#include "contextengine.h"
|
||||
#include "gui/settings.h"
|
||||
#include "gui/covers.h"
|
||||
#include "support/squeezedtextlabel.h"
|
||||
#include "support/utils.h"
|
||||
#include "support/messagebox.h"
|
||||
@@ -41,6 +43,7 @@
|
||||
#include "widgets/textbrowser.h"
|
||||
#include "gui/stdactions.h"
|
||||
#include "mpd/mpdstatus.h"
|
||||
#include "qtiocompressor/qtiocompressor.h"
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
#include <QFileInfo>
|
||||
@@ -54,17 +57,35 @@
|
||||
|
||||
const QLatin1String SongView::constLyricsDir("lyrics/");
|
||||
const QLatin1String SongView::constExtension(".lyrics");
|
||||
const QLatin1String SongView::constCacheDir("tracks/");
|
||||
const QLatin1String SongView::constInfoExt(".html.gz");
|
||||
|
||||
static QString cacheFile(QString artist, QString title, bool createDir=false)
|
||||
static QString infoCacheFileName(const Song &song, const QString &lang, bool createDir)
|
||||
{
|
||||
QString artist=song.artist;
|
||||
QString title=song.title;
|
||||
title.replace("/", "_");
|
||||
artist.replace("/", "_");
|
||||
QString dir=Utils::cacheDir(SongView::constLyricsDir+artist+Utils::constDirSep, createDir);
|
||||
QString dir=Utils::cacheDir(SongView::constCacheDir+Covers::encodeName(artist)+Utils::constDirSep, createDir);
|
||||
|
||||
if (dir.isEmpty()) {
|
||||
return QString();
|
||||
}
|
||||
return dir+title+SongView::constExtension;
|
||||
return dir+Covers::encodeName(title)+"."+lang+SongView::constInfoExt;
|
||||
}
|
||||
|
||||
static QString lyricsCacheFileName(const Song &song, bool createDir=false)
|
||||
{
|
||||
QString artist=song.artist;
|
||||
QString title=song.title;
|
||||
title.replace("/", "_");
|
||||
artist.replace("/", "_");
|
||||
QString dir=Utils::cacheDir(SongView::constLyricsDir+Covers::encodeName(artist)+Utils::constDirSep, createDir);
|
||||
|
||||
if (dir.isEmpty()) {
|
||||
return QString();
|
||||
}
|
||||
return dir+Covers::encodeName(title)+SongView::constExtension;
|
||||
}
|
||||
|
||||
static inline QString mpdFilePath(const QString &songFile)
|
||||
@@ -83,7 +104,7 @@ static inline QString fixNewLines(const QString &o)
|
||||
}
|
||||
|
||||
SongView::SongView(QWidget *p)
|
||||
: View(p)
|
||||
: View(p, QStringList() << i18n("Lyrics:") << i18n("Information:"))
|
||||
, scrollTimer(0)
|
||||
, songPos(0)
|
||||
, currentProvider(-1)
|
||||
@@ -91,12 +112,13 @@ SongView::SongView(QWidget *p)
|
||||
, mode(Mode_Display)
|
||||
, job(0)
|
||||
, currentProv(0)
|
||||
, infoNeedsUpdating(true)
|
||||
{
|
||||
scrollAction = ActionCollection::get()->createAction("scrolllyrics", i18n("Scroll Lyrics"), "go-down");
|
||||
refreshAction = ActionCollection::get()->createAction("refreshlyrics", i18n("Refresh Lyrics"), "view-refresh");
|
||||
editAction = ActionCollection::get()->createAction("editlyrics", i18n("Edit Lyrics"), Icons::self()->editIcon);
|
||||
saveAction = ActionCollection::get()->createAction("savelyrics", i18n("Save Lyrics"), "document-save");
|
||||
cancelAction = ActionCollection::get()->createAction("canceleditlyrics", i18n("Cancel Editing Lyrics"), Icons::self()->cancelIcon);
|
||||
cancelEditAction = ActionCollection::get()->createAction("canceleditlyrics", i18n("Cancel Editing Lyrics"), Icons::self()->cancelIcon);
|
||||
delAction = ActionCollection::get()->createAction("dellyrics", i18n("Delete Lyrics File"), "edit-delete");
|
||||
|
||||
scrollAction->setCheckable(true);
|
||||
@@ -105,16 +127,28 @@ SongView::SongView(QWidget *p)
|
||||
connect(refreshAction, SIGNAL(triggered()), SLOT(update()));
|
||||
connect(editAction, SIGNAL(triggered()), SLOT(edit()));
|
||||
connect(saveAction, SIGNAL(triggered()), SLOT(save()));
|
||||
connect(cancelAction, SIGNAL(triggered()), SLOT(cancel()));
|
||||
connect(cancelEditAction, SIGNAL(triggered()), SLOT(cancel()));
|
||||
connect(delAction, SIGNAL(triggered()), SLOT(del()));
|
||||
connect(UltimateLyrics::self(), SIGNAL(lyricsReady(int, QString)), SLOT(lyricsReady(int, QString)));
|
||||
|
||||
engine=ContextEngine::create(this);
|
||||
refreshInfoAction = ActionCollection::get()->createAction("refreshtrack", i18n("Refresh Track Information"), "view-refresh");
|
||||
cancelInfoJobAction=new Action(Icons::self()->cancelIcon, i18n("Cancel"), this);
|
||||
cancelInfoJobAction->setEnabled(false);
|
||||
connect(refreshInfoAction, SIGNAL(triggered()), SLOT(refreshInfo()));
|
||||
connect(cancelInfoJobAction, SIGNAL(triggered()), SLOT(abortInfoSearch()));
|
||||
connect(engine, SIGNAL(searchResult(QString,QString)), this, SLOT(infoSearchResponse(QString,QString)));
|
||||
|
||||
text->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(text, SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showContextMenu(QPoint)));
|
||||
texts.at(Page_Information)->setContextMenuPolicy(Qt::CustomContextMenu);
|
||||
connect(texts.at(Page_Information), SIGNAL(customContextMenuRequested(QPoint)), this, SLOT(showInfoContextMenu(QPoint)));
|
||||
connect(this, SIGNAL(viewChanged()), this, SLOT(curentViewChanged()));
|
||||
setMode(Mode_Blank);
|
||||
setStandardHeader(i18n("Lyrics"));
|
||||
setStandardHeader(i18n("Track"));
|
||||
clear();
|
||||
toggleScroll();
|
||||
setCurrentView(Settings::self()->contextTrackView());
|
||||
}
|
||||
|
||||
SongView::~SongView()
|
||||
@@ -146,6 +180,7 @@ void SongView::update()
|
||||
void SongView::saveConfig()
|
||||
{
|
||||
Settings::self()->saveContextAutoScroll(scrollAction->isChecked());
|
||||
Settings::self()->saveContextTrackView(currentView());
|
||||
}
|
||||
|
||||
void SongView::search()
|
||||
@@ -253,7 +288,7 @@ void SongView::showContextMenu(const QPoint &pos)
|
||||
case Mode_Edit:
|
||||
menu->addSeparator();
|
||||
menu->addAction(saveAction);
|
||||
menu->addAction(cancelAction);
|
||||
menu->addAction(cancelEditAction);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -266,6 +301,19 @@ void SongView::showContextMenu(const QPoint &pos)
|
||||
delete menu;
|
||||
}
|
||||
|
||||
void SongView::showInfoContextMenu(const QPoint &pos)
|
||||
{
|
||||
QMenu *menu = texts.at(Page_Information)->createStandardContextMenu();
|
||||
menu->addSeparator();
|
||||
if (cancelInfoJobAction->isEnabled()) {
|
||||
menu->addAction(cancelInfoJobAction);
|
||||
} else {
|
||||
menu->addAction(refreshInfoAction);
|
||||
}
|
||||
menu->exec(texts.at(Page_Information)->mapToGlobal(pos));
|
||||
delete menu;
|
||||
}
|
||||
|
||||
void SongView::toggleScroll()
|
||||
{
|
||||
if (scrollAction->isChecked()) {
|
||||
@@ -329,6 +377,90 @@ void SongView::scroll()
|
||||
}
|
||||
}
|
||||
|
||||
void SongView::curentViewChanged()
|
||||
{
|
||||
if (infoNeedsUpdating) {
|
||||
loadInfo();
|
||||
}
|
||||
}
|
||||
|
||||
void SongView::loadInfo()
|
||||
{
|
||||
infoNeedsUpdating=false;
|
||||
foreach (const QString &lang, engine->getLangs()) {
|
||||
QString prefix=engine->getPrefix(lang);
|
||||
QString cachedFile=infoCacheFileName(currentSong, prefix, false);
|
||||
if (QFile::exists(cachedFile)) {
|
||||
QFile f(cachedFile);
|
||||
QtIOCompressor compressor(&f);
|
||||
compressor.setStreamFormat(QtIOCompressor::GzipFormat);
|
||||
if (compressor.open(QIODevice::ReadOnly)) {
|
||||
QByteArray data=compressor.readAll();
|
||||
|
||||
if (!data.isEmpty()) {
|
||||
infoSearchResponse(QString::fromUtf8(data), QString());
|
||||
Utils::touchFile(cachedFile);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
searchForInfo();
|
||||
}
|
||||
|
||||
void SongView::refreshInfo()
|
||||
{
|
||||
if (currentSong.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
foreach (const QString &lang, engine->getLangs()) {
|
||||
QFile::remove(infoCacheFileName(currentSong, engine->getPrefix(lang), false));
|
||||
}
|
||||
searchForInfo();
|
||||
}
|
||||
|
||||
void SongView::searchForInfo()
|
||||
{
|
||||
cancelInfoJobAction->setEnabled(true);
|
||||
engine->search(QStringList() << currentSong.artist << currentSong.title, ContextEngine::Track);
|
||||
showSpinner(false);
|
||||
}
|
||||
|
||||
void SongView::infoSearchResponse(const QString &resp, const QString &lang)
|
||||
{
|
||||
cancelInfoJobAction->setEnabled(false);
|
||||
hideSpinner();
|
||||
|
||||
if (!resp.isEmpty()) {
|
||||
QString str=engine->translateLinks(resp);
|
||||
if (!lang.isEmpty()) {
|
||||
QFile f(infoCacheFileName(currentSong, lang, true));
|
||||
QtIOCompressor compressor(&f);
|
||||
compressor.setStreamFormat(QtIOCompressor::GzipFormat);
|
||||
if (compressor.open(QIODevice::WriteOnly)) {
|
||||
compressor.write(resp.toUtf8().constData());
|
||||
}
|
||||
}
|
||||
setHtml(str, Page_Information);
|
||||
}
|
||||
}
|
||||
|
||||
void SongView::abortInfoSearch()
|
||||
{
|
||||
if (cancelInfoJobAction->isEnabled()) {
|
||||
cancelInfoJobAction->setEnabled(false);
|
||||
engine->cancel();
|
||||
hideSpinner();
|
||||
}
|
||||
}
|
||||
|
||||
void SongView::hideSpinner()
|
||||
{
|
||||
if (!cancelInfoJobAction->isEnabled() && !cancelJobAction->isEnabled()) {
|
||||
View::hideSpinner();
|
||||
}
|
||||
}
|
||||
|
||||
void SongView::abort()
|
||||
{
|
||||
if (job) {
|
||||
@@ -344,9 +476,10 @@ void SongView::abort()
|
||||
// Set lyrics file anyway - so that editing is enabled!
|
||||
lyricsFile=Settings::self()->storeLyricsInMpdDir() && !currentSong.isNonMPD()
|
||||
? mpdFilePath(currentSong)
|
||||
: cacheFile(currentSong.artist, currentSong.title);
|
||||
: lyricsCacheFileName(currentSong);
|
||||
setMode(Mode_Display);
|
||||
}
|
||||
cancelJobAction->setEnabled(false);
|
||||
hideSpinner();
|
||||
}
|
||||
|
||||
@@ -358,6 +491,7 @@ void SongView::update(const Song &s, bool force)
|
||||
|
||||
if (s.isEmpty() || s.title.isEmpty() || s.artist.isEmpty()) {
|
||||
currentSong=s;
|
||||
infoNeedsUpdating=false;
|
||||
clear();
|
||||
abort();
|
||||
return;
|
||||
@@ -389,6 +523,12 @@ void SongView::update(const Song &s, bool force)
|
||||
}
|
||||
|
||||
setHeader(song.title);
|
||||
if (Page_Information==currentView()) {
|
||||
loadInfo();
|
||||
} else {
|
||||
infoNeedsUpdating=true;
|
||||
}
|
||||
|
||||
// Only reset the provider if the refresh was an automatic one or if the song has
|
||||
// changed. Otherwise we'll keep the provider so the user can cycle through the lyrics
|
||||
// offered by the various providers.
|
||||
@@ -438,7 +578,7 @@ void SongView::update(const Song &s, bool force)
|
||||
}
|
||||
|
||||
// Check for cached file...
|
||||
QString file=cacheFile(song.artist, song.title);
|
||||
QString file=lyricsCacheFileName(song);
|
||||
|
||||
/*if (force && QFile::exists(file)) {
|
||||
// Delete the cached lyrics file when the user is force-fully re-fetching the lyrics.
|
||||
@@ -469,6 +609,7 @@ void SongView::downloadFinished()
|
||||
QString lyrics=str.readAll();
|
||||
if (!lyrics.isEmpty()) {
|
||||
text->setText(fixNewLines(lyrics));
|
||||
cancelJobAction->setEnabled(false);
|
||||
hideSpinner();
|
||||
return;
|
||||
}
|
||||
@@ -490,6 +631,7 @@ void SongView::lyricsReady(int id, QString lyrics)
|
||||
if (lyrics.isEmpty()) {
|
||||
getLyrics();
|
||||
} else {
|
||||
cancelJobAction->setEnabled(false);
|
||||
hideSpinner();
|
||||
QString before=text->toHtml();
|
||||
text->setText(fixNewLines(lyrics));
|
||||
@@ -504,7 +646,7 @@ void SongView::lyricsReady(int id, QString lyrics)
|
||||
lyricsFile=QString();
|
||||
if (! ( Settings::self()->storeLyricsInMpdDir() && !currentSong.isNonMPD() &&
|
||||
saveFile(mpdFilePath(currentSong))) ) {
|
||||
saveFile(cacheFile(currentSong.artist, currentSong.title, true));
|
||||
saveFile(lyricsCacheFileName(currentSong, true));
|
||||
}
|
||||
setMode(Mode_Display);
|
||||
}
|
||||
@@ -533,7 +675,7 @@ QString SongView::mpdFileName() const
|
||||
|
||||
QString SongView::cacheFileName() const
|
||||
{
|
||||
return currentSong.artist.isEmpty() || currentSong.title.isEmpty() ? QString() : cacheFile(currentSong.artist, currentSong.title);
|
||||
return currentSong.artist.isEmpty() || currentSong.title.isEmpty() ? QString() : lyricsCacheFileName(currentSong);
|
||||
}
|
||||
|
||||
void SongView::getLyrics()
|
||||
@@ -549,7 +691,7 @@ void SongView::getLyrics()
|
||||
// Set lyrics file anyway - so that editing is enabled!
|
||||
lyricsFile=Settings::self()->storeLyricsInMpdDir() && !currentSong.isNonMPD()
|
||||
? mpdFilePath(currentSong)
|
||||
: cacheFile(currentSong.artist, currentSong.title);
|
||||
: lyricsCacheFileName(currentSong);
|
||||
setMode(Mode_Display);
|
||||
}
|
||||
}
|
||||
@@ -557,6 +699,7 @@ void SongView::getLyrics()
|
||||
void SongView::setMode(Mode m)
|
||||
{
|
||||
if (Mode_Display==m) {
|
||||
cancelJobAction->setEnabled(false);
|
||||
hideSpinner();
|
||||
}
|
||||
if (mode==m) {
|
||||
@@ -565,7 +708,7 @@ void SongView::setMode(Mode m)
|
||||
mode=m;
|
||||
bool editable=Mode_Display==m && !lyricsFile.isEmpty() && (!QFile::exists(lyricsFile) || QFileInfo(lyricsFile).isWritable());
|
||||
saveAction->setEnabled(Mode_Edit==m);
|
||||
cancelAction->setEnabled(Mode_Edit==m);
|
||||
cancelEditAction->setEnabled(Mode_Edit==m);
|
||||
editAction->setEnabled(editable);
|
||||
delAction->setEnabled(editable && !MPDConnection::self()->getDetails().dir.isEmpty() && QFile::exists(mpdFilePath(currentSong)));
|
||||
setEditable(Mode_Edit==m);
|
||||
@@ -587,6 +730,7 @@ bool SongView::setLyricsFromFile(const QString &filePath)
|
||||
QTextStream inputStream(&f);
|
||||
|
||||
text->setText(fixNewLines(inputStream.readAll()));
|
||||
cancelJobAction->setEnabled(false);
|
||||
hideSpinner();
|
||||
f.close();
|
||||
|
||||
|
||||
@@ -32,6 +32,7 @@ class QImage;
|
||||
class Action;
|
||||
class NetworkJob;
|
||||
class QTimer;
|
||||
class ContextEngine;
|
||||
|
||||
class SongView : public View
|
||||
{
|
||||
@@ -43,9 +44,16 @@ class SongView : public View
|
||||
Mode_Edit
|
||||
};
|
||||
|
||||
enum Pages {
|
||||
Page_Lyrics,
|
||||
Page_Information
|
||||
};
|
||||
|
||||
public:
|
||||
static const QLatin1String constLyricsDir;
|
||||
static const QLatin1String constExtension;
|
||||
static const QLatin1String constCacheDir;
|
||||
static const QLatin1String constInfoExt;
|
||||
|
||||
SongView(QWidget *p);
|
||||
~SongView();
|
||||
@@ -66,13 +74,21 @@ public Q_SLOTS:
|
||||
void cancel();
|
||||
void del();
|
||||
void showContextMenu(const QPoint &pos);
|
||||
void showInfoContextMenu(const QPoint &pos);
|
||||
|
||||
private Q_SLOTS:
|
||||
void toggleScroll();
|
||||
void songPosition();
|
||||
void scroll();
|
||||
void curentViewChanged();
|
||||
void refreshInfo();
|
||||
void infoSearchResponse(const QString &resp, const QString &lang);
|
||||
void abortInfoSearch();
|
||||
|
||||
private:
|
||||
void loadInfo();
|
||||
void searchForInfo();
|
||||
void hideSpinner();
|
||||
void abort();
|
||||
QString mpdFileName() const;
|
||||
QString cacheFileName() const;
|
||||
@@ -100,13 +116,18 @@ private:
|
||||
Action *searchAction;
|
||||
Action *editAction;
|
||||
Action *saveAction;
|
||||
Action *cancelAction;
|
||||
Action *cancelEditAction;
|
||||
Action *delAction;
|
||||
Mode mode;
|
||||
QString lyricsFile;
|
||||
QString preEdit;
|
||||
NetworkJob *job;
|
||||
UltimateLyricsProvider *currentProv;
|
||||
|
||||
bool infoNeedsUpdating;
|
||||
Action *refreshInfoAction;
|
||||
Action *cancelInfoJobAction;
|
||||
ContextEngine *engine;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
225
context/view.cpp
225
context/view.cpp
@@ -39,6 +39,11 @@
|
||||
#include <QLocale>
|
||||
#include <QBuffer>
|
||||
#include <QFile>
|
||||
#include <QStackedWidget>
|
||||
#include <QComboBox>
|
||||
#include <QMenu>
|
||||
#include <QMouseEvent>
|
||||
#include <QWheelEvent>
|
||||
|
||||
static QString headerTag;
|
||||
QString View::subTag;
|
||||
@@ -59,31 +64,136 @@ void View::initHeaderTags()
|
||||
subTag=small ? "h3" : "h2";
|
||||
}
|
||||
|
||||
View::View(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, needToUpdate(false)
|
||||
, spinner(0)
|
||||
static TextBrowser * createView(QWidget *parent)
|
||||
{
|
||||
QVBoxLayout *layout=new QVBoxLayout(this);
|
||||
layout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||
header=new QLabel(this);
|
||||
text=new TextBrowser(this);
|
||||
|
||||
layout->setMargin(0);
|
||||
header->setWordWrap(true);
|
||||
header->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
text->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
|
||||
text->setFrameShape(QFrame::NoFrame);
|
||||
|
||||
layout->addItem(new QSpacerItem(1, layout->spacing(), QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||
layout->addWidget(header);
|
||||
layout->addWidget(text);
|
||||
layout->addItem(new QSpacerItem(1, fontMetrics().height()/4, QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||
text->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
TextBrowser *text=new TextBrowser(parent);
|
||||
if (GtkStyle::isActive()) {
|
||||
text->verticalScrollBar()->setAttribute(Qt::WA_OpaquePaintEvent, false);
|
||||
}
|
||||
text->setOpenLinks(false);
|
||||
text->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
|
||||
text->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::MinimumExpanding);
|
||||
text->setFrameShape(QFrame::NoFrame);
|
||||
return text;
|
||||
}
|
||||
|
||||
ViewTextSelector::ViewTextSelector(QWidget *p)
|
||||
: QLabel(p)
|
||||
, current(0)
|
||||
{
|
||||
setAttribute(Qt::WA_Hover, true);
|
||||
menu=new QMenu(this);
|
||||
}
|
||||
|
||||
void ViewTextSelector::addItem(const QString &t)
|
||||
{
|
||||
menu->addAction(t.endsWith(":") ? t.left(t.count()-1) : t, this, SLOT(itemSelected()))->setData(items.count());
|
||||
if (text().isEmpty()) {
|
||||
setText("<b>"+t+"</b>");
|
||||
current=items.count();
|
||||
}
|
||||
items.append(t);
|
||||
}
|
||||
|
||||
void ViewTextSelector::itemSelected()
|
||||
{
|
||||
QAction *act=qobject_cast<QAction *>(sender());
|
||||
if (act) {
|
||||
setCurrentIndex(act->data().toInt());
|
||||
}
|
||||
}
|
||||
|
||||
bool ViewTextSelector::event(QEvent *e)
|
||||
{
|
||||
switch (e->type()) {
|
||||
case QEvent::MouseButtonPress:
|
||||
if (Qt::NoModifier==static_cast<QMouseEvent *>(e)->modifiers() && Qt::LeftButton==static_cast<QMouseEvent *>(e)->button()) {
|
||||
menu->exec(mapToGlobal(static_cast<QMouseEvent *>(e)->pos()));
|
||||
}
|
||||
case QEvent::HoverLeave:
|
||||
setStyleSheet(QString());
|
||||
break;
|
||||
case QEvent::HoverEnter:
|
||||
setStyleSheet(QLatin1String("QLabel{color:palette(highlight);}"));
|
||||
break;
|
||||
case QEvent::Wheel: {
|
||||
int numDegrees = static_cast<QWheelEvent *>(e)->delta() / 8;
|
||||
int numSteps = numDegrees / 15;
|
||||
int newIndex = current;
|
||||
if (numSteps > 0) {
|
||||
for (int i = 0; i < numSteps; ++i) {
|
||||
newIndex++;
|
||||
if (newIndex>=items.count()) {
|
||||
newIndex=0;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (int i = 0; i > numSteps; --i) {
|
||||
newIndex--;
|
||||
if (newIndex<0) {
|
||||
newIndex=items.count()-1;
|
||||
}
|
||||
}
|
||||
}
|
||||
setCurrentIndex(newIndex);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return QLabel::event(e);
|
||||
}
|
||||
|
||||
void ViewTextSelector::setCurrentIndex(int v)
|
||||
{
|
||||
if (v<0 || v>=items.count() || v==current) {
|
||||
return;
|
||||
}
|
||||
current=v;
|
||||
setText("<b>"+items.at(current)+"</b>");
|
||||
emit activated(current);
|
||||
}
|
||||
|
||||
View::View(QWidget *parent, const QStringList &views)
|
||||
: QWidget(parent)
|
||||
, needToUpdate(false)
|
||||
, spinner(0)
|
||||
, selector(0)
|
||||
, stack(0)
|
||||
{
|
||||
QVBoxLayout *layout=new QVBoxLayout(this);
|
||||
layout->setAlignment(Qt::AlignTop | Qt::AlignLeft);
|
||||
header=new QLabel(this);
|
||||
|
||||
if (views.isEmpty()) {
|
||||
TextBrowser *t=createView(this);
|
||||
texts.append(t);
|
||||
} else {
|
||||
stack=new QStackedWidget(this);
|
||||
selector=new ViewTextSelector(this);
|
||||
foreach (const QString &v, views) {
|
||||
TextBrowser *t=createView(stack);
|
||||
selector->addItem(v);
|
||||
stack->addWidget(t);
|
||||
texts.append(t);
|
||||
}
|
||||
connect(selector, SIGNAL(activated(int)), stack, SLOT(setCurrentIndex(int)));
|
||||
connect(selector, SIGNAL(activated(int)), this, SIGNAL(viewChanged()));
|
||||
}
|
||||
|
||||
layout->setMargin(0);
|
||||
header->setWordWrap(true);
|
||||
header->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
|
||||
|
||||
layout->addItem(new QSpacerItem(1, layout->spacing(), QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||
layout->addWidget(header);
|
||||
if (views.isEmpty()) {
|
||||
layout->addWidget(texts.at(0));
|
||||
} else {
|
||||
layout->addWidget(selector);
|
||||
layout->addWidget(stack);
|
||||
}
|
||||
layout->addItem(new QSpacerItem(1, fontMetrics().height()/4, QSizePolicy::Fixed, QSizePolicy::Fixed));
|
||||
setEditable(false);
|
||||
if (headerTag.isEmpty()) {
|
||||
initHeaderTags();
|
||||
@@ -92,6 +202,7 @@ View::View(QWidget *parent)
|
||||
cancelJobAction=new Action(Icons::self()->cancelIcon, i18n("Cancel"), this);
|
||||
cancelJobAction->setEnabled(false);
|
||||
connect(cancelJobAction, SIGNAL(triggered()), SLOT(abort()));
|
||||
text=texts.at(0);
|
||||
}
|
||||
|
||||
View::~View()
|
||||
@@ -102,7 +213,9 @@ View::~View()
|
||||
void View::clear()
|
||||
{
|
||||
setHeader(stdHeader);
|
||||
text->clear();
|
||||
foreach (TextBrowser *t, texts) {
|
||||
t->clear();
|
||||
}
|
||||
}
|
||||
|
||||
void View::setHeader(const QString &str)
|
||||
@@ -112,7 +225,9 @@ void View::setHeader(const QString &str)
|
||||
|
||||
void View::setPicSize(const QSize &sz)
|
||||
{
|
||||
text->setPicSize(sz);
|
||||
foreach (TextBrowser *t, texts) {
|
||||
t->setPicSize(sz);
|
||||
}
|
||||
}
|
||||
|
||||
QSize View::picSize() const
|
||||
@@ -129,7 +244,7 @@ QString View::createPicTag(const QImage &img, const QString &file)
|
||||
return QString();
|
||||
}
|
||||
// No filename given, or file does not exist - therefore encode & scale image.
|
||||
return encode(img.scaled(text->picSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
return encode(img.scaled(texts.at(0)->picSize(), Qt::KeepAspectRatio, Qt::SmoothTransformation));
|
||||
}
|
||||
|
||||
void View::showEvent(QShowEvent *e)
|
||||
@@ -141,7 +256,7 @@ void View::showEvent(QShowEvent *e)
|
||||
QWidget::showEvent(e);
|
||||
}
|
||||
|
||||
void View::showSpinner()
|
||||
void View::showSpinner(bool enableCancel)
|
||||
{
|
||||
if (!spinner) {
|
||||
spinner=new Spinner(this);
|
||||
@@ -149,53 +264,73 @@ void View::showSpinner()
|
||||
}
|
||||
if (!spinner->isActive()) {
|
||||
spinner->start();
|
||||
cancelJobAction->setEnabled(true);
|
||||
if (enableCancel) {
|
||||
cancelJobAction->setEnabled(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void View::hideSpinner()
|
||||
void View::hideSpinner(bool disableCancel)
|
||||
{
|
||||
if (spinner) {
|
||||
spinner->stop();
|
||||
cancelJobAction->setEnabled(false);
|
||||
if (disableCancel) {
|
||||
cancelJobAction->setEnabled(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void View::setEditable(bool e)
|
||||
void View::setEditable(bool e, int index)
|
||||
{
|
||||
text->setReadOnly(!e);
|
||||
text->viewport()->setAutoFillBackground(e);
|
||||
TextBrowser *t=texts.at(index);
|
||||
t->setReadOnly(!e);
|
||||
t->viewport()->setAutoFillBackground(e);
|
||||
}
|
||||
|
||||
void View::setPal(const QPalette &pal, const QColor &linkColor, const QColor &prevLinkColor)
|
||||
{
|
||||
// QTextBrowser seems to save link colour within the HTML, so we need to manually
|
||||
// update this when the palette changes!
|
||||
QString old=text->toHtml();
|
||||
text->setPal(pal);
|
||||
foreach (TextBrowser *t, texts) {
|
||||
// QTextBrowser seems to save link colour within the HTML, so we need to manually
|
||||
// update this when the palette changes!
|
||||
QString old=t->toHtml();
|
||||
t->setPal(pal);
|
||||
old=old.replace("color:"+prevLinkColor.name()+";", "color:"+linkColor.name()+";");
|
||||
t->setHtml(old);
|
||||
}
|
||||
// header uses window/button text - so need to set these now...
|
||||
QPalette hdrPal=pal;
|
||||
hdrPal.setColor(QPalette::WindowText, pal.color(QPalette::Text));
|
||||
hdrPal.setColor(QPalette::ButtonText, pal.color(QPalette::Text));
|
||||
header->setPalette(hdrPal);
|
||||
old=old.replace("color:"+prevLinkColor.name()+";", "color:"+linkColor.name()+";");
|
||||
text->setHtml(old);
|
||||
if (selector) {
|
||||
selector->setPalette(hdrPal);
|
||||
}
|
||||
}
|
||||
|
||||
void View::addEventFilter(QObject *obj)
|
||||
{
|
||||
installEventFilter(obj);
|
||||
text->installEventFilter(obj);
|
||||
text->viewport()->installEventFilter(obj);
|
||||
foreach (TextBrowser *t, texts) {
|
||||
t->installEventFilter(obj);
|
||||
t->viewport()->installEventFilter(obj);
|
||||
}
|
||||
header->installEventFilter(obj);
|
||||
}
|
||||
|
||||
void View::setZoom(int z)
|
||||
{
|
||||
text->setZoom(z);
|
||||
foreach (TextBrowser *t, texts) {
|
||||
t->setZoom(z);
|
||||
}
|
||||
QFont f=header->font();
|
||||
f.setPointSize(f.pointSize()+z);
|
||||
header->setFont(f);
|
||||
|
||||
if (selector) {
|
||||
QFont f=selector->font();
|
||||
f.setPointSize(f.pointSize()+z);
|
||||
selector->setFont(f);
|
||||
}
|
||||
}
|
||||
|
||||
int View::getZoom()
|
||||
@@ -203,16 +338,10 @@ int View::getZoom()
|
||||
return text->zoom();
|
||||
}
|
||||
|
||||
void View::setHtml(const QString &h)
|
||||
void View::setHtml(const QString &h, int index)
|
||||
{
|
||||
text->setText(QLatin1String("<html><head><style type=text/css>a:link {color:")+text->palette().link().color().name()+
|
||||
QLatin1String("; text-decoration:underline;}</style></head><body>")+h+QLatin1String("</body></html>"));
|
||||
}
|
||||
|
||||
void View::searchResponse(const QString &r, const QString &l)
|
||||
{
|
||||
Q_UNUSED(l)
|
||||
text->setText(r);
|
||||
texts.at(index)->setText(QLatin1String("<html><head><style type=text/css>a:link {color:")+text->palette().link().color().name()+
|
||||
QLatin1String("; text-decoration:underline;}</style></head><body>")+h+QLatin1String("</body></html>"));
|
||||
}
|
||||
|
||||
void View::abort()
|
||||
|
||||
@@ -26,21 +26,47 @@
|
||||
|
||||
#include <QWidget>
|
||||
#include <QSize>
|
||||
#include <QLabel>
|
||||
#include "mpd/song.h"
|
||||
|
||||
class QImage;
|
||||
class QLabel;
|
||||
class Spinner;
|
||||
class QNetworkReply;
|
||||
class QLayoutItem;
|
||||
class TextBrowser;
|
||||
class Action;
|
||||
class QStackedWidget;
|
||||
class QMenu;
|
||||
|
||||
class ViewTextSelector : public QLabel
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
ViewTextSelector(QWidget *p);
|
||||
void addItem(const QString &t);
|
||||
bool event(QEvent *e);
|
||||
int currentIndex() const { return current; }
|
||||
void setCurrentIndex(int v);
|
||||
|
||||
Q_SIGNALS:
|
||||
void activated(int);
|
||||
|
||||
private Q_SLOTS:
|
||||
void itemSelected();
|
||||
|
||||
private:
|
||||
int current;
|
||||
QStringList items;
|
||||
QMenu *menu;
|
||||
};
|
||||
|
||||
class View : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
View(QWidget *p);
|
||||
static QString subTag;
|
||||
|
||||
View(QWidget *p, const QStringList &views=QStringList());
|
||||
virtual ~View();
|
||||
|
||||
static QString subHeader(const QString &str) { return "<"+subTag+">"+str+"</"+subTag+">"; }
|
||||
@@ -53,30 +79,36 @@ public:
|
||||
QSize picSize() const;
|
||||
QString createPicTag(const QImage &img, const QString &file);
|
||||
void showEvent(QShowEvent *e);
|
||||
void showSpinner();
|
||||
void hideSpinner();
|
||||
void setEditable(bool e);
|
||||
void showSpinner(bool enableCancel=true);
|
||||
void hideSpinner(bool disableCancel=true);
|
||||
void setEditable(bool e, int index=0);
|
||||
void setPal(const QPalette &pal, const QColor &linkColor, const QColor &prevLinkColor);
|
||||
void addEventFilter(QObject *obj);
|
||||
void setZoom(int z);
|
||||
int getZoom();
|
||||
virtual void update(const Song &s, bool force)=0;
|
||||
void setHtml(const QString &h);
|
||||
void setHtml(const QString &h, int index=0);
|
||||
int currentView() const { return selector ? selector->currentIndex() : -1; }
|
||||
void setCurrentView(int v) { selector->setCurrentIndex(v); }
|
||||
|
||||
Q_SIGNALS:
|
||||
void viewChanged();
|
||||
|
||||
protected Q_SLOTS:
|
||||
virtual void searchResponse(const QString &r, const QString &l);
|
||||
virtual void abort();
|
||||
|
||||
protected:
|
||||
static QString subTag;
|
||||
Song currentSong;
|
||||
QString stdHeader;
|
||||
QLabel *header;
|
||||
TextBrowser *text;
|
||||
bool needToUpdate;
|
||||
Spinner *spinner;
|
||||
Action *cancelJobAction;
|
||||
|
||||
ViewTextSelector *selector;
|
||||
QStackedWidget *stack;
|
||||
TextBrowser *text; // short-cut to first text item...
|
||||
QList<TextBrowser *> texts;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "network/networkaccessmanager.h"
|
||||
#include "support/localize.h"
|
||||
#include "gui/settings.h"
|
||||
#include "gui/covers.h"
|
||||
#include "config.h"
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QUrlQuery>
|
||||
@@ -306,6 +307,10 @@ QString WikipediaEngine::translateLinks(QString text) const
|
||||
void WikipediaEngine::search(const QStringList &query, Mode mode)
|
||||
{
|
||||
titles.clear();
|
||||
// if (Track==mode) {
|
||||
// emit searchResult(QString(), QString());
|
||||
// return;
|
||||
// }
|
||||
requestTitles(fixQuery(query), mode, getPrefix(preferredLangs.first()));
|
||||
}
|
||||
|
||||
@@ -389,6 +394,7 @@ void WikipediaEngine::parseTitles()
|
||||
return;
|
||||
}
|
||||
|
||||
DBUG << titles;
|
||||
getPage(query, mode, hostLang);
|
||||
}
|
||||
|
||||
@@ -413,20 +419,21 @@ void WikipediaEngine::getPage(const QStringList &query, Mode mode, const QString
|
||||
simplifiedTitles.append(t.simplified());
|
||||
}
|
||||
|
||||
while(!queryCopy.isEmpty()) {
|
||||
QString q=queryCopy.join(" ");
|
||||
QString q2=q;
|
||||
q2.remove("."); // A.S.A.P. -> ASAP
|
||||
queries.append(q);
|
||||
if (q2!=q) {
|
||||
queries.append(q2);
|
||||
}
|
||||
QMap<QString, QString> replacements;
|
||||
replacements.insert(QLatin1String("."), QString()); // A.S.A.P. -> ASAP
|
||||
replacements.insert(QLatin1String("-"), QLatin1String("/")); // AC-DC -> AC/DC
|
||||
QMap<QString, QString>::ConstIterator repEnd=replacements.constEnd();
|
||||
|
||||
q2=q;
|
||||
q2.replace("-", "/"); // AC-DC -> AC/DC
|
||||
while (!queryCopy.isEmpty()) {
|
||||
QString q=queryCopy.join(" ");
|
||||
queries.append(q);
|
||||
if (q2!=q) {
|
||||
queries.append(q2);
|
||||
|
||||
for (QMap<QString, QString>::ConstIterator rep=replacements.constBegin(); rep!=repEnd; ++rep) {
|
||||
QString q2=q;
|
||||
q2.replace(rep.key(), rep.value());
|
||||
if (q2!=q) {
|
||||
queries.append(q2);
|
||||
}
|
||||
}
|
||||
|
||||
queryCopy.takeFirst();
|
||||
@@ -445,6 +452,10 @@ void WikipediaEngine::getPage(const QStringList &query, Mode mode, const QString
|
||||
patterns=i18nc("Search pattern for an album, separated by |", "album|score|soundtrack").split("|", QString::SkipEmptyParts);
|
||||
englishPatterns=QString(QLatin1String("album|score|soundtrack")).split("|");
|
||||
break;
|
||||
case Track:
|
||||
// patterns=i18nc("Search pattern for a song, separated by |", "song|track").split("|", QString::SkipEmptyParts);
|
||||
// englishPatterns=QString(QLatin1String("song|track")).split("|");
|
||||
break;
|
||||
}
|
||||
|
||||
foreach (const QString &eng, englishPatterns) {
|
||||
@@ -456,18 +467,19 @@ void WikipediaEngine::getPage(const QStringList &query, Mode mode, const QString
|
||||
DBUG << "Titles" << titles;
|
||||
|
||||
int index=-1;
|
||||
if (mode==Album && 2==query.count()) {
|
||||
DBUG << "Check album";
|
||||
if ((mode==Album || mode==Track) && 2==query.count()) {
|
||||
DBUG << "Check track/album";
|
||||
foreach (const QString &pattern, patterns) {
|
||||
QString q=query.at(1)+" ("+query.at(0)+" "+pattern+")";
|
||||
DBUG << "Try" << q;
|
||||
index=indexOf(simplifiedTitles, q);
|
||||
if (-1!=index) {
|
||||
DBUG << "Matched with '$album ($artist pattern)" << index << q;
|
||||
DBUG << "Matched with '$album/$track ($artist pattern)" << index << q;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (-1==index) {
|
||||
foreach (const QString &q, queries) {
|
||||
DBUG << "Query" << q;
|
||||
@@ -539,9 +551,10 @@ void WikipediaEngine::parsePage()
|
||||
QUrl url=reply->url();
|
||||
QString hostLang=getLang(url);
|
||||
|
||||
QStringList query=reply->property(constQueryProperty).toStringList();
|
||||
Mode mode=(Mode)reply->property(constModeProperty).toInt();
|
||||
if (answer.contains(QLatin1String("{{disambiguation}}")) || answer.contains(QLatin1String("{{disambig}}"))) { // i18n???
|
||||
getPage(reply->property(constQueryProperty).toStringList(), (Mode)reply->property(constModeProperty).toInt(),
|
||||
hostLang);
|
||||
getPage(query, mode, hostLang);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -553,5 +566,11 @@ void WikipediaEngine::parsePage()
|
||||
if (introOnly && resp.isEmpty()) {
|
||||
resp=wikiToHtml(answer, false, reply->url());
|
||||
}
|
||||
emit searchResult(resp, hostLang);
|
||||
|
||||
// For track results, ensure response contains artist name!
|
||||
if (Track==mode && !resp.contains(query.at(0), Qt::CaseInsensitive) && !resp.contains(Covers::fixArtist(query.at(0)), Qt::CaseInsensitive)) {
|
||||
getPage(query, mode, hostLang);
|
||||
} else {
|
||||
emit searchResult(resp, hostLang);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -268,6 +268,7 @@ CacheSettings::CacheSettings(QWidget *parent)
|
||||
new CacheItem(i18n("Artist Information"), Utils::cacheDir(ArtistView::constCacheDir, false), QStringList() << "*"+ArtistView::constInfoExt
|
||||
<< "*"+ArtistView::constSimilarInfoExt << "*.json.gz" << "*.jpg" << "*.png", tree);
|
||||
new CacheItem(i18n("Album Information"), Utils::cacheDir(AlbumView::constCacheDir, false), QStringList() << "*"+AlbumView::constInfoExt << "*.jpg" << "*.png", tree);
|
||||
new CacheItem(i18n("Track Information"), Utils::cacheDir(SongView::constCacheDir, false), QStringList() << "*"+AlbumView::constInfoExt, tree);
|
||||
#ifdef ENABLE_STREAMS
|
||||
new CacheItem(i18n("Stream Listings"), Utils::cacheDir(StreamsModel::constSubDir, false), QStringList() << "*"+StreamsModel::constCacheExt, tree);
|
||||
#endif
|
||||
|
||||
@@ -569,6 +569,11 @@ bool Settings::contextAutoScroll()
|
||||
return cfg.get("contextAutoScroll", false);
|
||||
}
|
||||
|
||||
int Settings::contextTrackView()
|
||||
{
|
||||
return cfg.get("contextTrackView", 0);
|
||||
}
|
||||
|
||||
QString Settings::page()
|
||||
{
|
||||
return cfg.get("page", QString());
|
||||
@@ -1184,6 +1189,11 @@ void Settings::saveContextAutoScroll(bool v)
|
||||
cfg.set("contextAutoScroll", v);
|
||||
}
|
||||
|
||||
void Settings::saveContextTrackView(int v)
|
||||
{
|
||||
cfg.set("contextTrackView", v);
|
||||
}
|
||||
|
||||
void Settings::savePage(const QString &v)
|
||||
{
|
||||
cfg.set("page", v);
|
||||
|
||||
@@ -111,6 +111,7 @@ public:
|
||||
bool contextAlwaysCollapsed();
|
||||
int contextSwitchTime();
|
||||
bool contextAutoScroll();
|
||||
int contextTrackView();
|
||||
QString page();
|
||||
QStringList hiddenPages();
|
||||
#if !defined ENABLE_KDE_SUPPORT && !defined ENABLE_UBUNTU
|
||||
@@ -234,6 +235,7 @@ public:
|
||||
void saveContextAlwaysCollapsed(bool v);
|
||||
void saveContextSwitchTime(int v);
|
||||
void saveContextAutoScroll(bool v);
|
||||
void saveContextTrackView(int v);
|
||||
void savePage(const QString &v);
|
||||
void saveHiddenPages(const QStringList &v);
|
||||
#if !defined ENABLE_KDE_SUPPORT && !defined ENABLE_UBUNTU
|
||||
|
||||
Reference in New Issue
Block a user