Double-click on radio items to play
This commit is contained in:
parent
939e4b5264
commit
92db175819
1
TODO
1
TODO
|
@ -10,7 +10,6 @@
|
|||
|
||||
Last.fm:
|
||||
- Artist/tag/etc. radio
|
||||
- Double click from radio list
|
||||
- More types of radio
|
||||
|
||||
Long-term:
|
||||
|
|
|
@ -145,34 +145,33 @@ void LastFMService::AuthenticateReplyFinished() {
|
|||
emit AuthenticationComplete(true);
|
||||
}
|
||||
|
||||
QList<RadioItem::PlaylistData> LastFMService::DataForItem(RadioItem* item) {
|
||||
QList<RadioItem::PlaylistData> ret;
|
||||
QUrl LastFMService::UrlForItem(const RadioItem* item) const {
|
||||
switch (item->type) {
|
||||
case Type_MyRecommendations:
|
||||
return "lastfm://user/" + lastfm::ws::Username + "/recommended";
|
||||
|
||||
case Type_MyLoved:
|
||||
return "lastfm://user/" + lastfm::ws::Username + "/loved";
|
||||
|
||||
case Type_MyNeighbourhood:
|
||||
return "lastfm://user/" + lastfm::ws::Username + "/neighbours";
|
||||
|
||||
case Type_MyRadio:
|
||||
return "lastfm://user/" + lastfm::ws::Username + "/library";
|
||||
}
|
||||
return QUrl();
|
||||
}
|
||||
|
||||
QString LastFMService::TitleForItem(const RadioItem* item) const {
|
||||
const QString user(lastfm::ws::Username);
|
||||
|
||||
switch (item->type) {
|
||||
case Type_MyRecommendations:
|
||||
ret << RadioItem::PlaylistData(user + "'s Recommended Radio",
|
||||
"lastfm://user/" + lastfm::ws::Username + "/recommended");
|
||||
break;
|
||||
|
||||
case Type_MyLoved:
|
||||
ret << RadioItem::PlaylistData(user + "'s Loved Tracks",
|
||||
"lastfm://user/" + lastfm::ws::Username + "/loved");
|
||||
break;
|
||||
|
||||
case Type_MyNeighbourhood:
|
||||
ret << RadioItem::PlaylistData(user + "'s Neighbour Radio",
|
||||
"lastfm://user/" + lastfm::ws::Username + "/neighbours");
|
||||
break;
|
||||
|
||||
case Type_MyRadio:
|
||||
ret << RadioItem::PlaylistData(user + "'s Library",
|
||||
"lastfm://user/" + lastfm::ws::Username + "/library");
|
||||
break;
|
||||
case Type_MyRecommendations: return user + "'s Recommended Radio";
|
||||
case Type_MyLoved: return user + "'s Loved Tracks";
|
||||
case Type_MyNeighbourhood: return user + "'s Neighbour Radio";
|
||||
case Type_MyRadio: return user + "'s Library";
|
||||
}
|
||||
|
||||
return ret;
|
||||
return QString();
|
||||
}
|
||||
|
||||
void LastFMService::StartLoading(const QUrl& url) {
|
||||
|
|
|
@ -33,13 +33,19 @@ class LastFMService : public RadioService {
|
|||
// RadioService
|
||||
RadioItem* CreateRootItem(RadioItem* parent);
|
||||
void LazyPopulate(RadioItem *item);
|
||||
QList<RadioItem::PlaylistData> DataForItem(RadioItem* item);
|
||||
|
||||
QUrl UrlForItem(const RadioItem* item) const;
|
||||
QString TitleForItem(const RadioItem* item) const;
|
||||
|
||||
void ShowContextMenu(RadioItem *item, const QPoint &global_pos);
|
||||
|
||||
void StartLoading(const QUrl& url);
|
||||
void LoadNext(const QUrl& url);
|
||||
|
||||
bool IsPauseAllowed() const { return false; }
|
||||
bool ShowLastFmControls() const { return true; }
|
||||
|
||||
// Last.fm specific stuff
|
||||
bool IsAuthenticated() const;
|
||||
bool IsScrobblingEnabled() const { return scrobbling_enabled_; }
|
||||
void Authenticate(const QString& username, const QString& password);
|
||||
|
|
|
@ -157,6 +157,7 @@ MainWindow::MainWindow(QWidget *parent)
|
|||
connect(radio_model_, SIGNAL(StreamReady(QUrl,QUrl)), player_, SLOT(StreamReady(QUrl,QUrl)));
|
||||
connect(radio_model_, SIGNAL(StreamMetadataFound(QUrl,Song)), playlist_, SLOT(SetStreamMetadata(QUrl,Song)));
|
||||
connect(radio_model_->GetLastFMService(), SIGNAL(ScrobblingEnabledChanged(bool)), SLOT(ScrobblingEnabledChanged(bool)));
|
||||
connect(ui_.radio_view, SIGNAL(doubleClicked(QModelIndex)), SLOT(RadioDoubleClick(QModelIndex)));
|
||||
|
||||
// Tray icon
|
||||
QMenu* tray_menu = new QMenu(this);
|
||||
|
@ -360,3 +361,11 @@ void MainWindow::Love() {
|
|||
radio_model_->GetLastFMService()->Love();
|
||||
ui_.action_love->setEnabled(false);
|
||||
}
|
||||
|
||||
void MainWindow::RadioDoubleClick(const QModelIndex& index) {
|
||||
QModelIndex first_song = playlist_->InsertRadioStations(
|
||||
QList<RadioItem*>() << radio_model_->IndexToItem(index));
|
||||
|
||||
if (first_song.isValid() && player_->GetState() != Engine::Playing)
|
||||
player_->PlayAt(first_song.row());
|
||||
}
|
||||
|
|
|
@ -49,6 +49,7 @@ class MainWindow : public QMainWindow {
|
|||
|
||||
void UpdateTrackPosition();
|
||||
|
||||
void RadioDoubleClick(const QModelIndex& index);
|
||||
void ScrobblingEnabledChanged(bool value);
|
||||
void Love();
|
||||
|
||||
|
|
|
@ -133,7 +133,7 @@ bool Playlist::dropMimeData(const QMimeData* data, Qt::DropAction action, int ro
|
|||
InsertSongs(song_data->songs, row);
|
||||
} else if (const RadioMimeData* radio_data = qobject_cast<const RadioMimeData*>(data)) {
|
||||
// Dragged from the Radio pane
|
||||
InsertRadioStations(radio_data->services, radio_data->urls(), radio_data->titles, row);
|
||||
InsertRadioStations(radio_data->items, row);
|
||||
} else if (data->hasFormat(kRowsMimetype)) {
|
||||
// Dragged from the playlist
|
||||
// Rearranging it is tricky...
|
||||
|
@ -245,17 +245,15 @@ QModelIndex Playlist::InsertSongs(const SongList& songs, int after) {
|
|||
return InsertItems(items, after);
|
||||
}
|
||||
|
||||
QModelIndex Playlist::InsertRadioStations(const QList<RadioService*>& services,
|
||||
const QList<QUrl>& urls,
|
||||
const QStringList& titles, int after) {
|
||||
Q_ASSERT(services.count() == urls.count());
|
||||
Q_ASSERT(services.count() == titles.count());
|
||||
QModelIndex Playlist::InsertRadioStations(const QList<RadioItem*>& items, int after) {
|
||||
QList<PlaylistItem*> playlist_items;
|
||||
foreach (RadioItem* item, items) {
|
||||
if (!item->playable)
|
||||
continue;
|
||||
|
||||
QList<PlaylistItem*> items;
|
||||
for (int i=0 ; i<services.count() ; ++i) {
|
||||
items << new RadioPlaylistItem(services[i], urls[i], titles[i]);
|
||||
playlist_items << new RadioPlaylistItem(item->service, item->Url(), item->Title());
|
||||
}
|
||||
return InsertItems(items, after);
|
||||
return InsertItems(playlist_items, after);
|
||||
}
|
||||
|
||||
QMimeData* Playlist::mimeData(const QModelIndexList& indexes) const {
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
#include "playlistitem.h"
|
||||
#include "song.h"
|
||||
#include "radioitem.h"
|
||||
|
||||
class RadioService;
|
||||
|
||||
|
@ -62,9 +63,7 @@ class Playlist : public QAbstractListModel {
|
|||
// Changing the playlist
|
||||
QModelIndex InsertItems(const QList<PlaylistItem*>& items, int after = -1);
|
||||
QModelIndex InsertSongs(const SongList& items, int after = -1);
|
||||
QModelIndex InsertRadioStations(const QList<RadioService*>& services,
|
||||
const QList<QUrl>& urls,
|
||||
const QStringList& titles, int after = -1);
|
||||
QModelIndex InsertRadioStations(const QList<RadioItem*>& items, int after = -1);
|
||||
QModelIndex InsertPaths(QList<QUrl> urls, int after = -1);
|
||||
void StopAfter(int row);
|
||||
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "radioitem.h"
|
||||
#include "radioservice.h"
|
||||
|
||||
RadioItem::RadioItem(RadioService* _service, int type, const QString& key,
|
||||
RadioItem* parent)
|
||||
|
@ -7,3 +8,11 @@ RadioItem::RadioItem(RadioService* _service, int type, const QString& key,
|
|||
playable(false)
|
||||
{
|
||||
}
|
||||
|
||||
QUrl RadioItem::Url() const {
|
||||
return service->UrlForItem(this);
|
||||
}
|
||||
|
||||
QString RadioItem::Title() const {
|
||||
return service->TitleForItem(this);
|
||||
}
|
||||
|
|
|
@ -15,16 +15,12 @@ class RadioItem : public SimpleTreeItem<RadioItem> {
|
|||
Type_Service,
|
||||
};
|
||||
|
||||
struct PlaylistData {
|
||||
PlaylistData(const QString& _title, const QUrl& _url) : title(_title), url(_url) {}
|
||||
|
||||
QString title;
|
||||
QUrl url;
|
||||
};
|
||||
|
||||
RadioItem(RadioService* _service, int type, const QString& key = QString::null,
|
||||
RadioItem* parent = NULL);
|
||||
|
||||
QUrl Url() const;
|
||||
QString Title() const;
|
||||
|
||||
QIcon icon;
|
||||
RadioService* service;
|
||||
bool playable;
|
||||
|
|
|
@ -3,14 +3,13 @@
|
|||
|
||||
#include <QMimeData>
|
||||
|
||||
class RadioService;
|
||||
class RadioItem;
|
||||
|
||||
class RadioMimeData : public QMimeData {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
QList<RadioService*> services;
|
||||
QList<QString> titles;
|
||||
QList<RadioItem*> items;
|
||||
};
|
||||
|
||||
#endif // RADIOMIMEDATA_H
|
||||
|
|
|
@ -85,20 +85,15 @@ QStringList RadioModel::mimeTypes() const {
|
|||
|
||||
QMimeData* RadioModel::mimeData(const QModelIndexList& indexes) const {
|
||||
QList<QUrl> urls;
|
||||
QList<RadioService*> services;
|
||||
QStringList titles;
|
||||
QList<RadioItem*> items;
|
||||
|
||||
foreach (const QModelIndex& index, indexes) {
|
||||
RadioItem* item = IndexToItem(index);
|
||||
if (!item || !item->service || !item->playable)
|
||||
continue;
|
||||
|
||||
QList<RadioItem::PlaylistData> item_data(item->service->DataForItem(item));
|
||||
foreach (const RadioItem::PlaylistData& data, item_data) {
|
||||
urls << data.url;
|
||||
services << item->service;
|
||||
titles << data.title;
|
||||
}
|
||||
items << item;
|
||||
urls << item->service->UrlForItem(item);
|
||||
}
|
||||
|
||||
if (urls.isEmpty())
|
||||
|
@ -106,8 +101,7 @@ QMimeData* RadioModel::mimeData(const QModelIndexList& indexes) const {
|
|||
|
||||
RadioMimeData* data = new RadioMimeData;
|
||||
data->setUrls(urls);
|
||||
data->services = services;
|
||||
data->titles = titles;
|
||||
data->items = items;
|
||||
|
||||
return data;
|
||||
}
|
||||
|
|
|
@ -21,7 +21,9 @@ class RadioService : public QObject {
|
|||
virtual RadioItem* CreateRootItem(RadioItem* parent) = 0;
|
||||
virtual void LazyPopulate(RadioItem* item) = 0;
|
||||
|
||||
virtual QList<RadioItem::PlaylistData> DataForItem(RadioItem* item) = 0;
|
||||
virtual QUrl UrlForItem(const RadioItem* item) const = 0;
|
||||
virtual QString TitleForItem(const RadioItem* item) const = 0;
|
||||
|
||||
virtual void ShowContextMenu(RadioItem* item, const QPoint& global_pos) {
|
||||
Q_UNUSED(item); Q_UNUSED(global_pos); }
|
||||
|
||||
|
|
Loading…
Reference in New Issue