File indexing completed on 2021-12-21 13:27:55

0001 /**
0002  * Copyright (C) 2012 Martin Sandsmark <martin.sandsmark@kde.org>
0003  *
0004  * This program is free software; you can redistribute it and/or modify it under
0005  * the terms of the GNU General Public License as published by the Free Software
0006  * Foundation; either version 2 of the License, or (at your option) any later
0007  * version.
0008  *
0009  * This program is distributed in the hope that it will be useful, but WITHOUT ANY
0010  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
0011  * PARTICULAR PURPOSE. See the GNU General Public License for more details.
0012  *
0013  * You should have received a copy of the GNU General Public License along with
0014  * this program.  If not, see <http://www.gnu.org/licenses/>.
0015  */
0016 
0017 #include "lyricswidget.h"
0018 
0019 #include <QDomDocument>
0020 #include <QNetworkAccessManager>
0021 #include <QNetworkReply>
0022 #include <QIcon>
0023 #include <QAction>
0024 #include <QUrlQuery>
0025 #include <KLocalizedString>
0026 #include <KActionCollection>
0027 #include <KToggleAction>
0028 #include <KConfigGroup>
0029 #include <KSharedConfig>
0030 
0031 #include "actioncollection.h"
0032 #include "iconsupport.h"
0033 #include "juk_debug.h"
0034 #include "juktag.h"
0035 
0036 static const QUrl BASE_LYRICS_URL = QUrl("https://lyrics.fandom.com/");
0037 
0038 using namespace IconSupport; // ""_icon
0039 using namespace ActionCollection; // ""_act
0040 
0041 LyricsWidget::LyricsWidget(QWidget* parent)
0042   : QTextBrowser(parent)
0043   , m_networkAccessManager(new QNetworkAccessManager)
0044   , m_lyricsCurrent(false)
0045 {
0046     setMinimumWidth(200);
0047     setReadOnly(true);
0048     setWordWrapMode(QTextOption::WordWrap);
0049     setOpenExternalLinks(true);
0050 
0051     KToggleAction *show = new KToggleAction("view-media-lyrics"_icon,
0052                                             i18n("Show &Lyrics"), this);
0053     ActionCollection::actions()->addAction("showLyrics", show);
0054     connect(show, SIGNAL(toggled(bool)), this, SLOT(setVisible(bool)));
0055 
0056     KConfigGroup config(KSharedConfig::openConfig(), "LyricsWidget");
0057     bool shown = config.readEntry("Show", true);
0058     show->setChecked(shown);
0059     setVisible(shown);
0060 }
0061 
0062 LyricsWidget::~LyricsWidget()
0063 {
0064     delete m_networkAccessManager;
0065     saveConfig();
0066 }
0067 
0068 void LyricsWidget::saveConfig()
0069 {
0070     KConfigGroup config(KSharedConfig::openConfig(), "LyricsWidget");
0071     config.writeEntry("Show", "showLyrics"_act->isChecked());
0072 }
0073 
0074 void LyricsWidget::makeLyricsRequest()
0075 {
0076     m_lyricsCurrent = true;
0077 
0078     if(m_playingFile.isNull()) {
0079         setHtml(i18n("<i>No file playing.</i>"));
0080         return;
0081     }
0082 
0083     m_title = m_playingFile.tag()->artist() + " &#8211; " + m_playingFile.tag()->title();
0084     setHtml(i18n("<i>Loading...</i>"));
0085 
0086     // lyrics.fandom.com seems to be unavailable as well now so give a better error message
0087     // and stop pinging the server
0088     if(1) {
0089         setHtml(i18n("<i>Lyrics are currently unavailable for %1 (no available lyrics provider)</i>").arg(m_title));
0090         return;
0091     }
0092 
0093     QUrl listUrl = BASE_LYRICS_URL;
0094     listUrl.setPath("/api.php");
0095 
0096     QUrlQuery listUrlQuery;
0097     listUrlQuery.addQueryItem("action", "lyrics");
0098     listUrlQuery.addQueryItem("func", "getSong");
0099     listUrlQuery.addQueryItem("fmt", "xml");
0100     listUrlQuery.addQueryItem("artist", m_playingFile.tag()->artist());
0101     listUrlQuery.addQueryItem("song", m_playingFile.tag()->title());
0102     listUrl.setQuery(listUrlQuery);
0103 
0104     connect(m_networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(receiveListReply(QNetworkReply*)));
0105     m_networkAccessManager->get(QNetworkRequest(listUrl));
0106 }
0107 
0108 void LyricsWidget::playing(const FileHandle &file)
0109 {
0110     m_playingFile = file;
0111     m_lyricsCurrent = false;
0112 
0113     if(isVisible()) {
0114         makeLyricsRequest();
0115     }
0116 }
0117 
0118 void LyricsWidget::showEvent(QShowEvent *)
0119 {
0120     if(!m_lyricsCurrent) {
0121         makeLyricsRequest();
0122     }
0123 }
0124 
0125 void LyricsWidget::receiveListReply(QNetworkReply* reply)
0126 {
0127     disconnect(m_networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(receiveListReply(QNetworkReply*)));
0128     if (reply->error() != QNetworkReply::NoError) {
0129         qCWarning(JUK_LOG) << "Error while fetching lyrics: " << reply->errorString();
0130         setHtml(i18n("<span style='color:red'>Error while retrieving lyrics!</span>"));
0131         return;
0132     }
0133 
0134     QDomDocument document;
0135     document.setContent(reply);
0136     QString artist = document.elementsByTagName("artist").at(0).toElement().text();
0137     QString title = document.elementsByTagName("song").at(0).toElement().text();
0138 
0139     QUrl url = BASE_LYRICS_URL;
0140     url.setPath("/api.php");
0141 
0142     QUrlQuery urlQuery;
0143     urlQuery.addQueryItem("action", "query");
0144     urlQuery.addQueryItem("prop", "revisions");
0145     urlQuery.addQueryItem("rvprop", "content");
0146     urlQuery.addQueryItem("format", "xml");
0147     urlQuery.addQueryItem("titles", artist + ':' + title);
0148     url.setQuery(urlQuery);
0149 
0150     connect(m_networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(receiveLyricsReply(QNetworkReply*)));
0151     m_networkAccessManager->get(QNetworkRequest(url));
0152 }
0153 
0154 void LyricsWidget::receiveLyricsReply(QNetworkReply* reply)
0155 {
0156     disconnect(m_networkAccessManager, SIGNAL(finished(QNetworkReply*)), this, SLOT(receiveLyricsReply(QNetworkReply*)));
0157     if (reply->error() != QNetworkReply::NoError) {
0158         qCWarning(JUK_LOG) << "Error while fetching lyrics: " << reply->errorString();
0159         setHtml(i18n("<span style='color:red'>Error while retrieving lyrics!</span>"));
0160         return;
0161     }
0162     const QUrlQuery replyUrlQuery(reply->url());
0163     QString titlesUrlPart = replyUrlQuery.queryItemValue(QStringLiteral("titles"), QUrl::FullyEncoded);
0164     if (titlesUrlPart.isEmpty()) {
0165         // default homepage, but this code path should never happen at this point.
0166         titlesUrlPart = QStringLiteral("Lyrics_Wiki");
0167     }
0168     const QString lyricsUrl = BASE_LYRICS_URL.toString() + QStringLiteral("wiki/") + titlesUrlPart;
0169 
0170     QString content = QString::fromUtf8(reply->readAll());
0171     int lIndex = content.indexOf("&lt;lyrics&gt;");
0172     int rIndex = content.indexOf("&lt;/lyrics&gt;");
0173     if (lIndex == -1 || rIndex == -1) {
0174         qCWarning(JUK_LOG) << Q_FUNC_INFO << "Unable to find lyrics in text";
0175         setText(i18n("No lyrics available."));
0176         return;
0177     }
0178     lIndex += 15; // We skip the tag
0179     content = content.mid(lIndex, rIndex - lIndex).trimmed();
0180     content.replace('\n', "<br />");
0181     //setText(content);
0182     setHtml("<h1>" + m_title + "</h1>" +
0183             content +
0184             i18n("<br /><br /><i>Lyrics provided by <a href='%1'>LyricWiki</a></i>", lyricsUrl));
0185 }