Make SongKick results a bit prettier
This commit is contained in:
parent
a7ba3ab927
commit
5940b0ead1
|
@ -282,6 +282,7 @@ set(SOURCES
|
||||||
songinfo/songinfotextview.cpp
|
songinfo/songinfotextview.cpp
|
||||||
songinfo/songinfoview.cpp
|
songinfo/songinfoview.cpp
|
||||||
songinfo/songkickconcerts.cpp
|
songinfo/songkickconcerts.cpp
|
||||||
|
songinfo/songkickconcertwidget.cpp
|
||||||
songinfo/songplaystats.cpp
|
songinfo/songplaystats.cpp
|
||||||
songinfo/ultimatelyricsprovider.cpp
|
songinfo/ultimatelyricsprovider.cpp
|
||||||
songinfo/ultimatelyricsreader.cpp
|
songinfo/ultimatelyricsreader.cpp
|
||||||
|
@ -539,6 +540,7 @@ set(HEADERS
|
||||||
songinfo/songinfotextview.h
|
songinfo/songinfotextview.h
|
||||||
songinfo/songinfoview.h
|
songinfo/songinfoview.h
|
||||||
songinfo/songkickconcerts.h
|
songinfo/songkickconcerts.h
|
||||||
|
songinfo/songkickconcertwidget.h
|
||||||
songinfo/songplaystats.h
|
songinfo/songplaystats.h
|
||||||
songinfo/ultimatelyricsprovider.h
|
songinfo/ultimatelyricsprovider.h
|
||||||
songinfo/ultimatelyricsreader.h
|
songinfo/ultimatelyricsreader.h
|
||||||
|
@ -652,6 +654,7 @@ set(UI
|
||||||
smartplaylists/searchtermwidget.ui
|
smartplaylists/searchtermwidget.ui
|
||||||
smartplaylists/wizardfinishpage.ui
|
smartplaylists/wizardfinishpage.ui
|
||||||
|
|
||||||
|
songinfo/songkickconcertwidget.ui
|
||||||
songinfo/songinfosettingspage.ui
|
songinfo/songinfosettingspage.ui
|
||||||
|
|
||||||
transcoder/transcodedialog.ui
|
transcoder/transcodedialog.ui
|
||||||
|
|
|
@ -126,6 +126,24 @@ QString Ago(int seconds_since_epoch, const QLocale& locale) {
|
||||||
return then.date().toString(locale.dateFormat());
|
return then.date().toString(locale.dateFormat());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString PrettyFutureDate(const QDate& date) {
|
||||||
|
const QDate now = QDate::currentDate();
|
||||||
|
const int delta_days = now.daysTo(date);
|
||||||
|
|
||||||
|
if (delta_days < 0)
|
||||||
|
return QString();
|
||||||
|
if (delta_days == 0)
|
||||||
|
return tr("Today");
|
||||||
|
if (delta_days == 1)
|
||||||
|
return tr("Tomorrow");
|
||||||
|
if (delta_days <= 7)
|
||||||
|
return tr("In %1 days").arg(delta_days);
|
||||||
|
if (delta_days <= 14)
|
||||||
|
return tr("Next week");
|
||||||
|
|
||||||
|
return tr("In %1 weeks").arg(delta_days / 7);
|
||||||
|
}
|
||||||
|
|
||||||
QString PrettySize(quint64 bytes) {
|
QString PrettySize(quint64 bytes) {
|
||||||
QString ret;
|
QString ret;
|
||||||
|
|
||||||
|
|
|
@ -41,6 +41,7 @@ namespace Utilities {
|
||||||
QString WordyTime(quint64 seconds);
|
QString WordyTime(quint64 seconds);
|
||||||
QString WordyTimeNanosec(qint64 nanoseconds);
|
QString WordyTimeNanosec(qint64 nanoseconds);
|
||||||
QString Ago(int seconds_since_epoch, const QLocale& locale);
|
QString Ago(int seconds_since_epoch, const QLocale& locale);
|
||||||
|
QString PrettyFutureDate(const QDate& date);
|
||||||
|
|
||||||
QString ColorToRgba(const QColor& color);
|
QString ColorToRgba(const QColor& color);
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
<number>0</number>
|
<number>0</number>
|
||||||
</property>
|
</property>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QSearchField" name="search">
|
<widget class="QSearchField" name="search" native="true">
|
||||||
<property name="placeholderText" stdset="0">
|
<property name="placeholderText" stdset="0">
|
||||||
<string>Search for anything</string>
|
<string>Search for anything</string>
|
||||||
</property>
|
</property>
|
||||||
|
@ -44,7 +44,7 @@
|
||||||
<item>
|
<item>
|
||||||
<widget class="QStackedWidget" name="results_stack">
|
<widget class="QStackedWidget" name="results_stack">
|
||||||
<property name="currentIndex">
|
<property name="currentIndex">
|
||||||
<number>0</number>
|
<number>1</number>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QWidget" name="results_page">
|
<widget class="QWidget" name="results_page">
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||||
|
@ -97,7 +97,7 @@
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>435</width>
|
<width>435</width>
|
||||||
<height>603</height>
|
<height>605</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||||
|
|
|
@ -40,14 +40,20 @@ SongInfoTextView::SongInfoTextView(QWidget* parent)
|
||||||
ReloadSettings();
|
ReloadSettings();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SongInfoTextView::ReloadSettings() {
|
qreal SongInfoTextView::FontSize() {
|
||||||
QSettings s;
|
QSettings s;
|
||||||
s.beginGroup(kSettingsGroup);
|
s.beginGroup(kSettingsGroup);
|
||||||
|
return s.value("font_size", kDefaultFontSize).toReal();
|
||||||
|
}
|
||||||
|
|
||||||
qreal size = s.value("font_size", kDefaultFontSize).toReal();
|
QFont SongInfoTextView::Font() {
|
||||||
QFont font;
|
QFont font;
|
||||||
font.setPointSizeF(size);
|
font.setPointSizeF(FontSize());
|
||||||
document()->setDefaultFont(font);
|
return font;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SongInfoTextView::ReloadSettings() {
|
||||||
|
document()->setDefaultFont(Font());
|
||||||
}
|
}
|
||||||
|
|
||||||
void SongInfoTextView::resizeEvent(QResizeEvent* e) {
|
void SongInfoTextView::resizeEvent(QResizeEvent* e) {
|
||||||
|
|
|
@ -29,6 +29,9 @@ public:
|
||||||
static const qreal kDefaultFontSize;
|
static const qreal kDefaultFontSize;
|
||||||
static const char* kSettingsGroup;
|
static const char* kSettingsGroup;
|
||||||
|
|
||||||
|
static qreal FontSize();
|
||||||
|
static QFont Font();
|
||||||
|
|
||||||
QSize sizeHint() const;
|
QSize sizeHint() const;
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "songkickconcerts.h"
|
#include "songkickconcerts.h"
|
||||||
|
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
|
#include <QVBoxLayout>
|
||||||
#include <QXmlStreamWriter>
|
#include <QXmlStreamWriter>
|
||||||
|
|
||||||
#include <echonest/Artist.h>
|
#include <echonest/Artist.h>
|
||||||
|
@ -25,7 +26,7 @@
|
||||||
#include <qjson/parser.h>
|
#include <qjson/parser.h>
|
||||||
|
|
||||||
#include "core/closure.h"
|
#include "core/closure.h"
|
||||||
#include "songinfotextview.h"
|
#include "songkickconcertwidget.h"
|
||||||
|
|
||||||
const char* SongkickConcerts::kSongkickArtistBucket = "id:songkick";
|
const char* SongkickConcerts::kSongkickArtistBucket = "id:songkick";
|
||||||
const char* SongkickConcerts::kSongkickArtistCalendarUrl =
|
const char* SongkickConcerts::kSongkickArtistCalendarUrl =
|
||||||
|
@ -98,15 +99,6 @@ void SongkickConcerts::FetchSongkickCalendar(const QString& artist_id, int id) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void SongkickConcerts::CalendarRequestFinished(QNetworkReply* reply, int id) {
|
void SongkickConcerts::CalendarRequestFinished(QNetworkReply* reply, int id) {
|
||||||
static const char* kStaticMapUrl =
|
|
||||||
"http://maps.googleapis.com/maps/api/staticmap"
|
|
||||||
"?key=AIzaSyDDJqmLOeE1mY_EBONhnQmdXbKtasgCtqg"
|
|
||||||
"&sensor=false"
|
|
||||||
"&size=100x100"
|
|
||||||
"&zoom=12"
|
|
||||||
"¢er=%1,%2"
|
|
||||||
"&markers=%1,%2";
|
|
||||||
|
|
||||||
QJson::Parser parser;
|
QJson::Parser parser;
|
||||||
bool ok = false;
|
bool ok = false;
|
||||||
QVariant result = parser.parse(reply, &ok);
|
QVariant result = parser.parse(reply, &ok);
|
||||||
|
@ -117,10 +109,6 @@ void SongkickConcerts::CalendarRequestFinished(QNetworkReply* reply, int id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString html;
|
|
||||||
QXmlStreamWriter writer(&html);
|
|
||||||
SongInfoTextView* text_view = new SongInfoTextView;
|
|
||||||
|
|
||||||
QVariantMap root = result.toMap();
|
QVariantMap root = result.toMap();
|
||||||
QVariantMap results_page = root["resultsPage"].toMap();
|
QVariantMap results_page = root["resultsPage"].toMap();
|
||||||
QVariantMap results = results_page["results"].toMap();
|
QVariantMap results = results_page["results"].toMap();
|
||||||
|
@ -131,55 +119,46 @@ void SongkickConcerts::CalendarRequestFinished(QNetworkReply* reply, int id) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QWidget* container = new QWidget;
|
||||||
|
QVBoxLayout* layout = new QVBoxLayout(container);
|
||||||
|
|
||||||
foreach (const QVariant& v, events) {
|
foreach (const QVariant& v, events) {
|
||||||
QVariantMap event = v.toMap();
|
QVariantMap event = v.toMap();
|
||||||
{
|
QString display_name = event["displayName"].toString();
|
||||||
QString display_name = event["displayName"].toString();
|
QString start_date = event["start"].toMap()["date"].toString();
|
||||||
QVariantMap venue = event["venue"].toMap();
|
QString city = event["location"].toMap()["city"].toString();
|
||||||
const bool valid_latlng =
|
QString uri = event["uri"].toString();
|
||||||
venue["lng"].isValid() && venue["lat"].isValid();
|
|
||||||
|
|
||||||
if (valid_latlng && latlng_.IsValid()) {
|
// Try to get the lat/lng coordinates of the venue.
|
||||||
static const int kFilterDistanceMetres = 250 * 1e3; // 250km
|
QVariantMap venue = event["venue"].toMap();
|
||||||
Geolocator::LatLng latlng(
|
const bool valid_latlng =
|
||||||
venue["lat"].toString(), venue["lng"].toString());
|
venue["lng"].isValid() && venue["lat"].isValid();
|
||||||
if (latlng_.IsValid() && latlng.IsValid()) {
|
|
||||||
int distance_metres = latlng_.Distance(latlng);
|
if (valid_latlng && latlng_.IsValid()) {
|
||||||
if (distance_metres > kFilterDistanceMetres) {
|
static const int kFilterDistanceMetres = 250 * 1e3; // 250km
|
||||||
qLog(Debug) << "Filtered concert:"
|
Geolocator::LatLng latlng(
|
||||||
<< display_name
|
venue["lat"].toString(), venue["lng"].toString());
|
||||||
<< "as too far away:"
|
if (latlng_.IsValid() && latlng.IsValid()) {
|
||||||
<< distance_metres;
|
int distance_metres = latlng_.Distance(latlng);
|
||||||
continue;
|
if (distance_metres > kFilterDistanceMetres) {
|
||||||
}
|
qLog(Debug) << "Filtered concert:"
|
||||||
|
<< display_name
|
||||||
|
<< "as too far away:"
|
||||||
|
<< distance_metres;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.writeStartElement("div");
|
|
||||||
{
|
|
||||||
writer.writeStartElement("a");
|
|
||||||
writer.writeAttribute("href", event["uri"].toString());
|
|
||||||
writer.writeCharacters(display_name);
|
|
||||||
writer.writeEndElement();
|
|
||||||
}
|
|
||||||
if (valid_latlng) {
|
|
||||||
writer.writeStartElement("img");
|
|
||||||
QString maps_url = QString(kStaticMapUrl).arg(
|
|
||||||
venue["lat"].toString(),
|
|
||||||
venue["lng"].toString());
|
|
||||||
writer.writeAttribute("src", maps_url);
|
|
||||||
writer.writeEndElement();
|
|
||||||
|
|
||||||
// QTextDocument does not support loading remote images, so we load
|
|
||||||
// them here and then inject them into the document later.
|
|
||||||
QNetworkRequest request(maps_url);
|
|
||||||
QNetworkReply* reply = network_.get(request);
|
|
||||||
NewClosure(reply, SIGNAL(finished()), this,
|
|
||||||
SLOT(InjectImage(QNetworkReply*, SongInfoTextView*)),
|
|
||||||
reply, text_view);
|
|
||||||
}
|
|
||||||
writer.writeEndElement();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SongKickConcertWidget* widget = new SongKickConcertWidget(container);
|
||||||
|
widget->Init(display_name, uri, start_date, city);
|
||||||
|
|
||||||
|
if (valid_latlng) {
|
||||||
|
widget->SetMap(venue["lat"].toString(), venue["lng"].toString(),
|
||||||
|
venue["displayName"].toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
layout->addWidget(widget);
|
||||||
}
|
}
|
||||||
|
|
||||||
CollapsibleInfoPane::Data data;
|
CollapsibleInfoPane::Data data;
|
||||||
|
@ -187,25 +166,12 @@ void SongkickConcerts::CalendarRequestFinished(QNetworkReply* reply, int id) {
|
||||||
data.id_ = QString("songkick/%1").arg(id);
|
data.id_ = QString("songkick/%1").arg(id);
|
||||||
data.title_ = tr("Upcoming Concerts");
|
data.title_ = tr("Upcoming Concerts");
|
||||||
data.icon_ = QIcon(":providers/songkick.png");
|
data.icon_ = QIcon(":providers/songkick.png");
|
||||||
|
data.contents_ = container;
|
||||||
text_view->SetHtml(html);
|
|
||||||
data.contents_ = text_view;
|
|
||||||
|
|
||||||
emit InfoReady(id, data);
|
emit InfoReady(id, data);
|
||||||
emit Finished(id);
|
emit Finished(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SongkickConcerts::InjectImage(
|
|
||||||
QNetworkReply* reply, SongInfoTextView* text_view) {
|
|
||||||
reply->deleteLater();
|
|
||||||
QImage image;
|
|
||||||
image.load(reply, "png");
|
|
||||||
text_view->document()->addResource(
|
|
||||||
QTextDocument::ImageResource,
|
|
||||||
reply->request().url(),
|
|
||||||
QVariant(image));
|
|
||||||
}
|
|
||||||
|
|
||||||
void SongkickConcerts::GeolocateFinished(Geolocator::LatLng latlng) {
|
void SongkickConcerts::GeolocateFinished(Geolocator::LatLng latlng) {
|
||||||
latlng_ = latlng;
|
latlng_ = latlng;
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ class SongkickConcerts : public SongInfoProvider {
|
||||||
private slots:
|
private slots:
|
||||||
void ArtistSearchFinished(QNetworkReply* reply, int id);
|
void ArtistSearchFinished(QNetworkReply* reply, int id);
|
||||||
void CalendarRequestFinished(QNetworkReply* reply, int id);
|
void CalendarRequestFinished(QNetworkReply* reply, int id);
|
||||||
void InjectImage(QNetworkReply* reply, SongInfoTextView* text_view);
|
|
||||||
void GeolocateFinished(Geolocator::LatLng latlng);
|
void GeolocateFinished(Geolocator::LatLng latlng);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -0,0 +1,147 @@
|
||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||||
|
|
||||||
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Clementine is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "songinfotextview.h"
|
||||||
|
#include "songkickconcertwidget.h"
|
||||||
|
#include "ui_songkickconcertwidget.h"
|
||||||
|
#include "core/closure.h"
|
||||||
|
#include "core/network.h"
|
||||||
|
#include "core/utilities.h"
|
||||||
|
|
||||||
|
#include <QDate>
|
||||||
|
#include <QDesktopServices>
|
||||||
|
#include <QMouseEvent>
|
||||||
|
#include <QTextDocument>
|
||||||
|
|
||||||
|
const int SongKickConcertWidget::kStaticMapWidth = 100;
|
||||||
|
const int SongKickConcertWidget::kStaticMapHeight = 100;
|
||||||
|
|
||||||
|
|
||||||
|
SongKickConcertWidget::SongKickConcertWidget(QWidget* parent)
|
||||||
|
: QWidget(parent),
|
||||||
|
ui_(new Ui_SongKickConcertWidget),
|
||||||
|
network_(new NetworkAccessManager(this))
|
||||||
|
{
|
||||||
|
ui_->setupUi(this);
|
||||||
|
|
||||||
|
// Hide the map by default
|
||||||
|
ui_->map->hide();
|
||||||
|
ui_->map->setFixedSize(kStaticMapWidth, kStaticMapHeight);
|
||||||
|
ui_->map->installEventFilter(this);
|
||||||
|
|
||||||
|
ReloadSettings();
|
||||||
|
}
|
||||||
|
|
||||||
|
SongKickConcertWidget::~SongKickConcertWidget() {
|
||||||
|
delete ui_;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SongKickConcertWidget::ReloadSettings() {
|
||||||
|
QFont font(SongInfoTextView::Font());
|
||||||
|
ui_->title->setFont(font);
|
||||||
|
ui_->date->setFont(font);
|
||||||
|
ui_->location->setFont(font);
|
||||||
|
}
|
||||||
|
|
||||||
|
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)));
|
||||||
|
|
||||||
|
if (!location.isEmpty()) {
|
||||||
|
ui_->location->setText(location);
|
||||||
|
} else {
|
||||||
|
ui_->location->hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!date.isEmpty()) {
|
||||||
|
QDate parsed_date(QDate::fromString(date, Qt::ISODate));
|
||||||
|
QString date_text = Utilities::PrettyFutureDate(parsed_date);
|
||||||
|
|
||||||
|
if (date_text.isEmpty()) {
|
||||||
|
date_text = date;
|
||||||
|
} else {
|
||||||
|
date_text += " (" + date + ")";
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_->date->setText(date_text);
|
||||||
|
} else {
|
||||||
|
ui_->date->hide();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SongKickConcertWidget::SetMap(const QString& lat, const QString& lng,
|
||||||
|
const QString& venue_name) {
|
||||||
|
static const char* kStaticMapUrl =
|
||||||
|
"http://maps.googleapis.com/maps/api/staticmap"
|
||||||
|
"?key=AIzaSyDDJqmLOeE1mY_EBONhnQmdXbKtasgCtqg"
|
||||||
|
"&sensor=false"
|
||||||
|
"&size=%1x%2"
|
||||||
|
"&zoom=12"
|
||||||
|
"¢er=%3,%4"
|
||||||
|
"&markers=%3,%4";
|
||||||
|
|
||||||
|
ui_->map->show();
|
||||||
|
|
||||||
|
map_url_ = QUrl("https://maps.google.com/");
|
||||||
|
map_url_.addQueryItem("ll", QString("%1,%2").arg(lat, lng));
|
||||||
|
if (!venue_name.isEmpty()) {
|
||||||
|
map_url_.addQueryItem("q", venue_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Request the static map image
|
||||||
|
const QUrl url(QString(kStaticMapUrl).arg(
|
||||||
|
QString::number(kStaticMapWidth),
|
||||||
|
QString::number(kStaticMapHeight),
|
||||||
|
lat, lng));
|
||||||
|
QNetworkReply* reply = network_->get(QNetworkRequest(url));
|
||||||
|
NewClosure(reply, SIGNAL(finished()),
|
||||||
|
this, SLOT(MapLoaded(QNetworkReply*)),
|
||||||
|
reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SongKickConcertWidget::MapLoaded(QNetworkReply* reply) {
|
||||||
|
reply->deleteLater();
|
||||||
|
|
||||||
|
QImage image;
|
||||||
|
if (!image.load(reply, "PNG")) {
|
||||||
|
qLog(Warning) << "Failed to load static map image" << reply->url();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Scale it if it was the wrong size.
|
||||||
|
if (image.width() != kStaticMapWidth || image.height() != kStaticMapHeight) {
|
||||||
|
qLog(Warning) << "Scaling static map image" << image.size();
|
||||||
|
image = image.scaled(kStaticMapWidth, kStaticMapHeight, Qt::KeepAspectRatio,
|
||||||
|
Qt::SmoothTransformation);
|
||||||
|
}
|
||||||
|
|
||||||
|
ui_->map->setPixmap(QPixmap::fromImage(image));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SongKickConcertWidget::eventFilter(QObject* object, QEvent* event) {
|
||||||
|
if (object == ui_->map && event->type() == QEvent::MouseButtonRelease) {
|
||||||
|
QMouseEvent* e = dynamic_cast<QMouseEvent*>(event);
|
||||||
|
if (e->button() == Qt::LeftButton) {
|
||||||
|
QDesktopServices::openUrl(map_url_);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QWidget::eventFilter(object, event);
|
||||||
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
/* This file is part of Clementine.
|
||||||
|
Copyright 2012, David Sansome <me@davidsansome.com>
|
||||||
|
|
||||||
|
Clementine is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
Clementine is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with Clementine. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SONGKICKCONCERTWIDGET_H
|
||||||
|
#define SONGKICKCONCERTWIDGET_H
|
||||||
|
|
||||||
|
#include <QUrl>
|
||||||
|
#include <QWidget>
|
||||||
|
|
||||||
|
class Ui_SongKickConcertWidget;
|
||||||
|
|
||||||
|
class QNetworkAccessManager;
|
||||||
|
class QNetworkReply;
|
||||||
|
|
||||||
|
class SongKickConcertWidget : public QWidget {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
SongKickConcertWidget(QWidget* parent = 0);
|
||||||
|
~SongKickConcertWidget();
|
||||||
|
|
||||||
|
static const int kStaticMapWidth;
|
||||||
|
static const int kStaticMapHeight;
|
||||||
|
|
||||||
|
void Init(const QString& title, const QString& url,
|
||||||
|
const QString& date, const QString& location);
|
||||||
|
void SetMap(const QString& lat, const QString& lng,
|
||||||
|
const QString& venue_name);
|
||||||
|
|
||||||
|
// QObject
|
||||||
|
bool eventFilter(QObject* object, QEvent* event);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void ReloadSettings();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void MapLoaded(QNetworkReply* reply);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Ui_SongKickConcertWidget* ui_;
|
||||||
|
QNetworkAccessManager* network_;
|
||||||
|
|
||||||
|
QUrl map_url_;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // SONGKICKCONCERTWIDGET_H
|
|
@ -0,0 +1,99 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>SongKickConcertWidget</class>
|
||||||
|
<widget class="QWidget" name="SongKickConcertWidget">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>571</width>
|
||||||
|
<height>195</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>Form</string>
|
||||||
|
</property>
|
||||||
|
<property name="styleSheet">
|
||||||
|
<string notr="true">#location, #date {
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<property name="margin">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<property name="spacing">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="title">
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="openExternalLinks">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByKeyboard|Qt::LinksAccessibleByMouse|Qt::TextBrowserInteraction|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="date">
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="location">
|
||||||
|
<property name="wordWrap">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
<property name="textInteractionFlags">
|
||||||
|
<set>Qt::LinksAccessibleByMouse|Qt::TextSelectableByKeyboard|Qt::TextSelectableByMouse</set>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="verticalSpacer">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Vertical</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeType">
|
||||||
|
<enum>QSizePolicy::MinimumExpanding</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>0</width>
|
||||||
|
<height>0</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="map">
|
||||||
|
<property name="sizePolicy">
|
||||||
|
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||||
|
<horstretch>0</horstretch>
|
||||||
|
<verstretch>0</verstretch>
|
||||||
|
</sizepolicy>
|
||||||
|
</property>
|
||||||
|
<property name="cursor">
|
||||||
|
<cursorShape>PointingHandCursor</cursorShape>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
Loading…
Reference in New Issue