Clementine-audio-player-Mac.../src/radio/radiomodel.cpp

225 lines
6.7 KiB
C++
Raw Normal View History

/* This file is part of Clementine.
Copyright 2010, 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 "icecastservice.h"
2010-11-23 18:38:39 +01:00
#include "jamendoservice.h"
#include "magnatuneservice.h"
2009-12-26 22:35:45 +01:00
#include "radiomimedata.h"
2010-11-23 18:38:39 +01:00
#include "radiomodel.h"
#include "radioservice.h"
#include "savedradio.h"
2010-11-23 18:38:39 +01:00
#include "somafmservice.h"
2011-04-22 18:50:29 +02:00
#include "core/logging.h"
#include "core/mergedproxymodel.h"
2009-12-26 22:35:45 +01:00
#ifdef HAVE_LIBLASTFM
#include "lastfmservice.h"
#endif
#ifdef HAVE_SPOTIFY
#include "spotifyservice.h"
#endif
2009-12-26 22:35:45 +01:00
#include <QMimeData>
#include <QtDebug>
QMap<QString, RadioService*>* RadioModel::sServices = NULL;
RadioModel::RadioModel(BackgroundThread<Database>* db_thread,
TaskManager* task_manager, PlayerInterface* player,
QObject* parent)
: QStandardItemModel(parent),
db_thread_(db_thread),
merged_model_(new MergedProxyModel(this)),
task_manager_(task_manager),
player_(player)
{
if (!sServices) {
sServices = new QMap<QString, RadioService*>;
}
Q_ASSERT(sServices->isEmpty());
2009-12-26 22:35:45 +01:00
merged_model_->setSourceModel(this);
#ifdef HAVE_LIBLASTFM
2009-12-26 22:35:45 +01:00
AddService(new LastFMService(this));
#endif
#ifdef HAVE_SPOTIFY
AddService(new SpotifyService(task_manager, this));
#endif
2010-01-18 03:23:55 +01:00
AddService(new SomaFMService(this));
AddService(new MagnatuneService(this));
2010-11-23 18:38:39 +01:00
AddService(new JamendoService(this));
AddService(new IcecastService(this));
AddService(new SavedRadio(this));
2009-12-26 22:35:45 +01:00
}
void RadioModel::AddService(RadioService *service) {
QStandardItem* root = service->CreateRootItem();
if (!root) {
2011-04-22 18:50:29 +02:00
qLog(Warning) << "Radio service" << service->name() << "did not return a root item";
return;
}
root->setData(Type_Service, Role_Type);
root->setData(QVariant::fromValue(service), Role_Service);
invisibleRootItem()->appendRow(root);
qLog(Debug) << "Adding radio service:" << service->name();
sServices->insert(service->name(), service);
2009-12-26 22:35:45 +01:00
connect(service, SIGNAL(StreamError(QString)), SIGNAL(StreamError(QString)));
2009-12-26 23:15:57 +01:00
connect(service, SIGNAL(StreamMetadataFound(QUrl,Song)), SIGNAL(StreamMetadataFound(QUrl,Song)));
2010-08-27 17:42:58 +02:00
connect(service, SIGNAL(OpenSettingsAtPage(SettingsDialog::Page)), SIGNAL(OpenSettingsAtPage(SettingsDialog::Page)));
connect(service, SIGNAL(AddToPlaylistSignal(QMimeData*)), SIGNAL(AddToPlaylist(QMimeData*)));
connect(service, SIGNAL(destroyed()), SLOT(ServiceDeleted()));
}
void RadioModel::RemoveService(RadioService* service) {
if (!sServices->contains(service->name()))
return;
// Find and remove the root item that this service created
for (int i=0 ; i<invisibleRootItem()->rowCount() ; ++i) {
QStandardItem* item = invisibleRootItem()->child(i);
if (!item || item->data(Role_Service).value<RadioService*>() == service) {
invisibleRootItem()->removeRow(i);
break;
}
}
// Remove the service from the list
sServices->remove(service->name());
// Disconnect the service
disconnect(service, 0, this, 0);
}
void RadioModel::ServiceDeleted() {
// qobject_cast doesn't work here with services created by python
RadioService* service = static_cast<RadioService*>(sender());
if (service)
RemoveService(service);
2009-12-26 22:35:45 +01:00
}
RadioService* RadioModel::ServiceByName(const QString& name) {
if (sServices->contains(name))
return sServices->value(name);
2009-12-26 22:35:45 +01:00
return NULL;
}
RadioService* RadioModel::ServiceForItem(const QStandardItem* item) const {
return ServiceForIndex(indexFromItem(item));
}
RadioService* RadioModel::ServiceForIndex(const QModelIndex& index) const {
QModelIndex current_index = index;
while (current_index.isValid()) {
RadioService* service = current_index.data(Role_Service).value<RadioService*>();
if (service) {
return service;
}
current_index = current_index.parent();
}
return NULL;
}
2009-12-26 22:35:45 +01:00
Qt::ItemFlags RadioModel::flags(const QModelIndex& index) const {
if (IsPlayable(index))
2009-12-26 22:35:45 +01:00
return Qt::ItemIsSelectable |
Qt::ItemIsEnabled |
Qt::ItemIsDragEnabled;
return Qt::ItemIsSelectable |
Qt::ItemIsEnabled;
}
bool RadioModel::hasChildren(const QModelIndex& parent) const {
if (parent.data(Role_CanLazyLoad).toBool())
return true;
return QStandardItemModel::hasChildren(parent);
}
int RadioModel::rowCount(const QModelIndex& parent) const {
if (parent.data(Role_CanLazyLoad).toBool()) {
QStandardItem* item = itemFromIndex(parent);
RadioService* service = ServiceForItem(item);
if (service) {
item->setData(false, Role_CanLazyLoad);
service->LazyPopulate(item);
}
}
return QStandardItemModel::rowCount(parent);
}
bool RadioModel::IsPlayable(const QModelIndex& index) const {
QVariant behaviour = index.data(Role_PlayBehaviour);
if (!behaviour.isValid())
return false;
PlayBehaviour pb = PlayBehaviour(behaviour.toInt());
return (pb == PlayBehaviour_SingleItem || PlayBehaviour_UseSongLoader);
}
2009-12-26 22:35:45 +01:00
QStringList RadioModel::mimeTypes() const {
return QStringList() << "text/uri-list";
}
QMimeData* RadioModel::mimeData(const QModelIndexList& indexes) const {
// Special case for when the user double clicked on a special item.
if (indexes.count() == 1 &&
indexes[0].data(Role_PlayBehaviour).toInt() ==
PlayBehaviour_DoubleClickAction) {
RadioModel::ServiceForIndex(indexes[0])->ItemDoubleClicked(itemFromIndex(indexes[0]));
return NULL;
}
2009-12-26 22:35:45 +01:00
QList<QUrl> urls;
QModelIndex last_valid_index;
2009-12-26 22:35:45 +01:00
foreach (const QModelIndex& index, indexes) {
if (!IsPlayable(index))
2009-12-26 22:35:45 +01:00
continue;
last_valid_index = index;
urls << index.data(Role_Url).toUrl();
2009-12-26 22:35:45 +01:00
}
if (urls.isEmpty())
return NULL;
RadioMimeData* data = new RadioMimeData(this);
2009-12-26 22:35:45 +01:00
data->setUrls(urls);
data->indexes = indexes;
data->name_for_new_playlist_ = RadioModel::ServiceForIndex(last_valid_index)->name();
2009-12-26 22:35:45 +01:00
return data;
}
2009-12-29 20:22:02 +01:00
void RadioModel::ShowContextMenu(const QModelIndex& merged_model_index,
const QPoint& global_pos) {
RadioService* service = ServiceForIndex(merged_model_index);
if (service)
service->ShowContextMenu(merged_model_->mapToSource(merged_model_index), global_pos);
2009-12-30 00:01:07 +01:00
}
2010-02-03 19:32:48 +01:00
void RadioModel::ReloadSettings() {
foreach (RadioService* service, sServices->values()) {
2010-02-03 19:32:48 +01:00
service->ReloadSettings();
}
}