2010-03-24 00:11:46 +01:00
|
|
|
/* This file is part of Clementine.
|
2010-11-20 14:27:10 +01:00
|
|
|
Copyright 2010, David Sansome <me@davidsansome.com>
|
2010-03-24 00:11:46 +01:00
|
|
|
|
|
|
|
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/>.
|
|
|
|
*/
|
|
|
|
|
2010-11-23 18:38:39 +01:00
|
|
|
#include "core/mergedproxymodel.h"
|
2010-11-22 17:57:26 +01:00
|
|
|
#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"
|
2010-02-24 23:26:01 +01:00
|
|
|
#include "savedradio.h"
|
2010-11-23 18:38:39 +01:00
|
|
|
#include "somafmservice.h"
|
2009-12-26 22:35:45 +01:00
|
|
|
|
2010-12-18 18:28:02 +01:00
|
|
|
#ifdef HAVE_LIBLASTFM
|
|
|
|
#include "lastfmservice.h"
|
|
|
|
#endif
|
|
|
|
|
2009-12-26 22:35:45 +01:00
|
|
|
#include <QMimeData>
|
|
|
|
#include <QtDebug>
|
|
|
|
|
2011-01-02 15:49:55 +01:00
|
|
|
QMap<QString, RadioService*>* RadioModel::sServices = NULL;
|
2009-12-26 16:13:38 +01:00
|
|
|
|
2010-06-02 17:58:07 +02:00
|
|
|
RadioModel::RadioModel(BackgroundThread<Database>* db_thread,
|
2010-10-16 19:20:54 +02:00
|
|
|
TaskManager* task_manager, QObject* parent)
|
2011-01-09 19:27:41 +01:00
|
|
|
: QStandardItemModel(parent),
|
2010-06-02 17:58:07 +02:00
|
|
|
db_thread_(db_thread),
|
2010-05-10 13:12:44 +02:00
|
|
|
merged_model_(new MergedProxyModel(this)),
|
2010-08-27 17:42:58 +02:00
|
|
|
task_manager_(task_manager)
|
2009-12-26 16:13:38 +01:00
|
|
|
{
|
2011-01-02 15:49:55 +01:00
|
|
|
if (!sServices) {
|
|
|
|
sServices = new QMap<QString, RadioService*>;
|
|
|
|
}
|
|
|
|
Q_ASSERT(sServices->isEmpty());
|
2009-12-26 22:35:45 +01:00
|
|
|
|
2010-05-09 17:51:04 +02:00
|
|
|
merged_model_->setSourceModel(this);
|
2009-12-26 16:13:38 +01:00
|
|
|
|
2010-12-18 18:28:02 +01:00
|
|
|
#ifdef HAVE_LIBLASTFM
|
2009-12-26 22:35:45 +01:00
|
|
|
AddService(new LastFMService(this));
|
2010-12-18 18:28:02 +01:00
|
|
|
#endif
|
2010-01-18 03:23:55 +01:00
|
|
|
AddService(new SomaFMService(this));
|
2010-05-08 22:56:39 +02:00
|
|
|
AddService(new MagnatuneService(this));
|
2010-11-23 18:38:39 +01:00
|
|
|
AddService(new JamendoService(this));
|
2010-11-22 17:57:26 +01:00
|
|
|
AddService(new IcecastService(this));
|
2010-02-24 23:26:01 +01:00
|
|
|
AddService(new SavedRadio(this));
|
2009-12-26 22:35:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void RadioModel::AddService(RadioService *service) {
|
2011-01-09 19:27:41 +01:00
|
|
|
QStandardItem* root = service->CreateRootItem();
|
2011-01-12 21:18:17 +01:00
|
|
|
if (!root) {
|
|
|
|
qWarning() << "Radio service" << service->name() << "did not return a root item";
|
2011-01-09 19:27:41 +01:00
|
|
|
return;
|
2011-01-12 21:18:17 +01:00
|
|
|
}
|
2011-01-09 19:27:41 +01:00
|
|
|
|
|
|
|
root->setData(Type_Service, Role_Type);
|
|
|
|
root->setData(QVariant::fromValue(service), Role_Service);
|
|
|
|
|
|
|
|
invisibleRootItem()->appendRow(root);
|
2011-01-02 15:49:55 +01:00
|
|
|
sServices->insert(service->name(), service);
|
2009-12-26 22:35:45 +01:00
|
|
|
|
2010-05-18 22:43:10 +02:00
|
|
|
connect(service, SIGNAL(AsyncLoadFinished(PlaylistItem::SpecialLoadResult)), SIGNAL(AsyncLoadFinished(PlaylistItem::SpecialLoadResult)));
|
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)));
|
2011-01-10 23:26:13 +01:00
|
|
|
connect(service, SIGNAL(AddToPlaylistSignal(QMimeData*)), SIGNAL(AddToPlaylist(QMimeData*)));
|
2011-01-12 21:18:17 +01:00
|
|
|
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) {
|
|
|
|
if (invisibleRootItem()->child(i)->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() {
|
2011-01-12 22:20:20 +01:00
|
|
|
// qobject_cast doesn't work here with services created by python
|
|
|
|
RadioService* service = static_cast<RadioService*>(sender());
|
2011-01-12 21:18:17 +01:00
|
|
|
if (service)
|
|
|
|
RemoveService(service);
|
2009-12-26 22:35:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
RadioService* RadioModel::ServiceByName(const QString& name) {
|
2011-01-02 15:49:55 +01:00
|
|
|
if (sServices->contains(name))
|
|
|
|
return sServices->value(name);
|
2009-12-26 22:35:45 +01:00
|
|
|
return NULL;
|
2009-12-26 16:13:38 +01:00
|
|
|
}
|
|
|
|
|
2011-01-09 19:27:41 +01:00
|
|
|
RadioService* RadioModel::ServiceForItem(const QStandardItem* item) const {
|
|
|
|
return ServiceForIndex(indexFromItem(item));
|
2009-12-26 16:13:38 +01:00
|
|
|
}
|
|
|
|
|
2011-01-09 19:27:41 +01:00
|
|
|
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();
|
2009-12-26 16:13:38 +01:00
|
|
|
}
|
2011-01-09 19:27:41 +01:00
|
|
|
return NULL;
|
2009-12-26 16:13:38 +01:00
|
|
|
}
|
2009-12-26 22:35:45 +01:00
|
|
|
|
|
|
|
Qt::ItemFlags RadioModel::flags(const QModelIndex& index) const {
|
2011-01-09 19:27:41 +01:00
|
|
|
if (IsPlayable(index))
|
2009-12-26 22:35:45 +01:00
|
|
|
return Qt::ItemIsSelectable |
|
|
|
|
Qt::ItemIsEnabled |
|
|
|
|
Qt::ItemIsDragEnabled;
|
|
|
|
|
|
|
|
return Qt::ItemIsSelectable |
|
|
|
|
Qt::ItemIsEnabled;
|
|
|
|
}
|
|
|
|
|
2011-01-09 19:27:41 +01:00
|
|
|
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() || behaviour.toInt() == PlayBehaviour_None)
|
|
|
|
return false;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2009-12-26 22:35:45 +01:00
|
|
|
QStringList RadioModel::mimeTypes() const {
|
|
|
|
return QStringList() << "text/uri-list";
|
|
|
|
}
|
|
|
|
|
|
|
|
QMimeData* RadioModel::mimeData(const QModelIndexList& indexes) const {
|
|
|
|
QList<QUrl> urls;
|
2011-01-09 19:27:41 +01:00
|
|
|
QModelIndexList items;
|
2009-12-26 22:35:45 +01:00
|
|
|
|
|
|
|
foreach (const QModelIndex& index, indexes) {
|
2011-01-09 19:27:41 +01:00
|
|
|
if (!IsPlayable(index))
|
2009-12-26 22:35:45 +01:00
|
|
|
continue;
|
|
|
|
|
2011-01-09 19:27:41 +01:00
|
|
|
items << index;
|
|
|
|
urls << index.data(Role_Url).toUrl();
|
2009-12-26 22:35:45 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if (urls.isEmpty())
|
|
|
|
return NULL;
|
|
|
|
|
2011-01-09 19:27:41 +01:00
|
|
|
RadioMimeData* data = new RadioMimeData(this);
|
2009-12-26 22:35:45 +01:00
|
|
|
data->setUrls(urls);
|
2011-01-09 19:27:41 +01:00
|
|
|
data->indexes = indexes;
|
2009-12-26 22:35:45 +01:00
|
|
|
|
|
|
|
return data;
|
|
|
|
}
|
2009-12-29 20:22:02 +01:00
|
|
|
|
2011-01-09 19:27:41 +01:00
|
|
|
void RadioModel::ShowContextMenu(const QModelIndex& merged_model_index,
|
2010-05-09 19:53:27 +02:00
|
|
|
const QPoint& global_pos) {
|
2011-01-09 19:27:41 +01:00
|
|
|
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() {
|
2011-01-02 15:49:55 +01:00
|
|
|
foreach (RadioService* service, sServices->values()) {
|
2010-02-03 19:32:48 +01:00
|
|
|
service->ReloadSettings();
|
|
|
|
}
|
|
|
|
}
|