~ubuntu-branches/ubuntu/saucy/clementine/saucy

« back to all changes in this revision

Viewing changes to src/internet/internetmodel.cpp

  • Committer: Package Import Robot
  • Author(s): Thomas PIERSON
  • Date: 2012-01-01 20:43:39 UTC
  • mfrom: (1.1.1)
  • Revision ID: package-import@ubuntu.com-20120101204339-lsb6nndwhfy05sde
Tags: 1.0.1+dfsg-1
New upstream release. (Closes: #653926, #651611, #657391)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* This file is part of Clementine.
 
2
   Copyright 2010, David Sansome <me@davidsansome.com>
 
3
 
 
4
   Clementine is free software: you can redistribute it and/or modify
 
5
   it under the terms of the GNU General Public License as published by
 
6
   the Free Software Foundation, either version 3 of the License, or
 
7
   (at your option) any later version.
 
8
 
 
9
   Clementine is distributed in the hope that it will be useful,
 
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
12
   GNU General Public License for more details.
 
13
 
 
14
   You should have received a copy of the GNU General Public License
 
15
   along with Clementine.  If not, see <http://www.gnu.org/licenses/>.
 
16
*/
 
17
 
 
18
#include "digitallyimportedservicebase.h"
 
19
#include "icecastservice.h"
 
20
#include "jamendoservice.h"
 
21
#include "magnatuneservice.h"
 
22
#include "internetmimedata.h"
 
23
#include "internetmodel.h"
 
24
#include "internetservice.h"
 
25
#include "savedradio.h"
 
26
#include "somafmservice.h"
 
27
#include "groovesharkservice.h"
 
28
#include "core/logging.h"
 
29
#include "core/mergedproxymodel.h"
 
30
#include "smartplaylists/generatormimedata.h"
 
31
 
 
32
#ifdef HAVE_LIBLASTFM
 
33
  #include "lastfmservice.h"
 
34
#endif
 
35
#ifdef HAVE_SPOTIFY
 
36
  #include "spotifyservice.h"
 
37
#endif
 
38
 
 
39
#include <QMimeData>
 
40
#include <QtDebug>
 
41
 
 
42
using smart_playlists::Generator;
 
43
using smart_playlists::GeneratorMimeData;
 
44
using smart_playlists::GeneratorPtr;
 
45
 
 
46
QMap<QString, InternetService*>* InternetModel::sServices = NULL;
 
47
 
 
48
InternetModel::InternetModel(BackgroundThread<Database>* db_thread,
 
49
                       TaskManager* task_manager, PlayerInterface* player,
 
50
                       CoverProviders* cover_providers,
 
51
                       GlobalSearch* global_search, QObject* parent)
 
52
  : QStandardItemModel(parent),
 
53
    db_thread_(db_thread),
 
54
    merged_model_(new MergedProxyModel(this)),
 
55
    task_manager_(task_manager),
 
56
    player_(player),
 
57
    cover_providers_(cover_providers),
 
58
    global_search_(global_search)
 
59
{
 
60
  if (!sServices) {
 
61
    sServices = new QMap<QString, InternetService*>;
 
62
  }
 
63
  Q_ASSERT(sServices->isEmpty());
 
64
 
 
65
  merged_model_->setSourceModel(this);
 
66
 
 
67
  AddService(new DigitallyImportedService(this));
 
68
  AddService(new IcecastService(this));
 
69
  AddService(new JamendoService(this));
 
70
#ifdef HAVE_LIBLASTFM
 
71
  AddService(new LastFMService(this));
 
72
#endif
 
73
  AddService(new GroovesharkService(this));
 
74
  AddService(new MagnatuneService(this));
 
75
  AddService(new SavedRadio(this));
 
76
  AddService(new SkyFmService(this));
 
77
  AddService(new SomaFMService(this));
 
78
#ifdef HAVE_SPOTIFY
 
79
  AddService(new SpotifyService(this));
 
80
#endif
 
81
}
 
82
 
 
83
void InternetModel::AddService(InternetService *service) {
 
84
  QStandardItem* root = service->CreateRootItem();
 
85
  if (!root) {
 
86
    qLog(Warning) << "Internet service" << service->name() << "did not return a root item";
 
87
    return;
 
88
  }
 
89
 
 
90
  root->setData(Type_Service, Role_Type);
 
91
  root->setData(QVariant::fromValue(service), Role_Service);
 
92
 
 
93
  invisibleRootItem()->appendRow(root);
 
94
  qLog(Debug) << "Adding internet service:" << service->name();
 
95
  sServices->insert(service->name(), service);
 
96
 
 
97
  connect(service, SIGNAL(StreamError(QString)), SIGNAL(StreamError(QString)));
 
98
  connect(service, SIGNAL(StreamMetadataFound(QUrl,Song)), SIGNAL(StreamMetadataFound(QUrl,Song)));
 
99
  connect(service, SIGNAL(OpenSettingsAtPage(SettingsDialog::Page)), SIGNAL(OpenSettingsAtPage(SettingsDialog::Page)));
 
100
  connect(service, SIGNAL(AddToPlaylistSignal(QMimeData*)), SIGNAL(AddToPlaylist(QMimeData*)));
 
101
  connect(service, SIGNAL(destroyed()), SLOT(ServiceDeleted()));
 
102
 
 
103
  service->ReloadSettings();
 
104
}
 
105
 
 
106
void InternetModel::RemoveService(InternetService* service) {
 
107
  if (!sServices->contains(service->name()))
 
108
    return;
 
109
 
 
110
  // Find and remove the root item that this service created
 
111
  for (int i=0 ; i<invisibleRootItem()->rowCount() ; ++i) {
 
112
    QStandardItem* item = invisibleRootItem()->child(i);
 
113
    if (!item || item->data(Role_Service).value<InternetService*>() == service) {
 
114
      invisibleRootItem()->removeRow(i);
 
115
      break;
 
116
    }
 
117
  }
 
118
 
 
119
  // Remove the service from the list
 
120
  sServices->remove(service->name());
 
121
 
 
122
  // Disconnect the service
 
123
  disconnect(service, 0, this, 0);
 
124
}
 
125
 
 
126
void InternetModel::ServiceDeleted() {
 
127
  InternetService* service = qobject_cast<InternetService*>(sender());
 
128
  if (service)
 
129
    RemoveService(service);
 
130
}
 
131
 
 
132
InternetService* InternetModel::ServiceByName(const QString& name) {
 
133
  if (sServices->contains(name))
 
134
    return sServices->value(name);
 
135
  return NULL;
 
136
}
 
137
 
 
138
InternetService* InternetModel::ServiceForItem(const QStandardItem* item) const {
 
139
  return ServiceForIndex(indexFromItem(item));
 
140
}
 
141
 
 
142
InternetService* InternetModel::ServiceForIndex(const QModelIndex& index) const {
 
143
  QModelIndex current_index = index;
 
144
  while (current_index.isValid()) {
 
145
    InternetService* service = current_index.data(Role_Service).value<InternetService*>();
 
146
    if (service) {
 
147
      return service;
 
148
    }
 
149
    current_index = current_index.parent();
 
150
  }
 
151
  return NULL;
 
152
}
 
153
 
 
154
Qt::ItemFlags InternetModel::flags(const QModelIndex& index) const {
 
155
  Qt::ItemFlags flags = Qt::ItemIsSelectable |
 
156
                        Qt::ItemIsEnabled |
 
157
                        Qt::ItemIsDropEnabled;
 
158
  if (IsPlayable(index)) {
 
159
    flags |= Qt::ItemIsDragEnabled;
 
160
  }
 
161
  return flags;
 
162
}
 
163
 
 
164
bool InternetModel::hasChildren(const QModelIndex& parent) const {
 
165
  if (parent.data(Role_CanLazyLoad).toBool())
 
166
    return true;
 
167
  return QStandardItemModel::hasChildren(parent);
 
168
}
 
169
 
 
170
int InternetModel::rowCount(const QModelIndex& parent) const {
 
171
  if (parent.data(Role_CanLazyLoad).toBool()) {
 
172
    QStandardItem* item = itemFromIndex(parent);
 
173
    InternetService* service = ServiceForItem(item);
 
174
    if (service) {
 
175
      item->setData(false, Role_CanLazyLoad);
 
176
      service->LazyPopulate(item);
 
177
    }
 
178
  }
 
179
 
 
180
  return QStandardItemModel::rowCount(parent);
 
181
}
 
182
 
 
183
bool InternetModel::IsPlayable(const QModelIndex& index) const {
 
184
  QVariant behaviour = index.data(Role_PlayBehaviour);
 
185
  if (!behaviour.isValid())
 
186
    return false;
 
187
 
 
188
  PlayBehaviour pb = PlayBehaviour(behaviour.toInt());
 
189
  return (pb == PlayBehaviour_SingleItem || PlayBehaviour_UseSongLoader);
 
190
}
 
191
 
 
192
QStringList InternetModel::mimeTypes() const {
 
193
  return QStringList() << "text/uri-list";
 
194
}
 
195
 
 
196
QMimeData* InternetModel::mimeData(const QModelIndexList& indexes) const {
 
197
  // Special case for when the user double clicked on a special item.
 
198
  if (indexes.count() == 1 &&
 
199
      indexes[0].data(Role_PlayBehaviour).toInt() ==
 
200
          PlayBehaviour_DoubleClickAction) {
 
201
    InternetModel::ServiceForIndex(indexes[0])->ItemDoubleClicked(itemFromIndex(indexes[0]));
 
202
    return NULL;
 
203
  }
 
204
 
 
205
  if (indexes.count() == 1 &&
 
206
      indexes[0].data(Role_Type).toInt() == Type_SmartPlaylist) {
 
207
    GeneratorPtr generator =
 
208
        InternetModel::ServiceForIndex(indexes[0])->CreateGenerator(itemFromIndex(indexes[0]));
 
209
    if (!generator)
 
210
      return NULL;
 
211
    GeneratorMimeData* data = new GeneratorMimeData(generator);
 
212
    data->setData(LibraryModel::kSmartPlaylistsMimeType, QByteArray());
 
213
    data->name_for_new_playlist_ = this->data(indexes.first()).toString();
 
214
    return data;
 
215
  }
 
216
 
 
217
  QList<QUrl> urls;
 
218
  QModelIndexList new_indexes;
 
219
 
 
220
  QModelIndex last_valid_index;
 
221
  foreach (const QModelIndex& index, indexes) {
 
222
    if (!IsPlayable(index))
 
223
      continue;
 
224
 
 
225
    last_valid_index = index;
 
226
    if (index.data(Role_Type).toInt() == Type_UserPlaylist) {
 
227
      // Get children
 
228
      int row = 0;
 
229
      int column = 0;
 
230
      QModelIndex child = index.child(row, column);
 
231
      while (child.isValid()) {
 
232
        new_indexes << child;
 
233
        urls << child.data(Role_Url).toUrl();
 
234
        child = index.child(++row, column);
 
235
      }
 
236
    } else {
 
237
      new_indexes = indexes;
 
238
      urls << index.data(Role_Url).toUrl();
 
239
    }
 
240
  }
 
241
 
 
242
  if (urls.isEmpty())
 
243
    return NULL;
 
244
 
 
245
  InternetMimeData* data = new InternetMimeData(this);
 
246
  data->setUrls(urls);
 
247
  data->indexes = new_indexes;
 
248
  data->name_for_new_playlist_ = InternetModel::ServiceForIndex(last_valid_index)->name();
 
249
 
 
250
  return data;
 
251
}
 
252
 
 
253
bool InternetModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column, const QModelIndex& parent) {
 
254
  if (action == Qt::IgnoreAction) {
 
255
    return false;
 
256
  }
 
257
  if (parent.data(Role_CanBeModified).toBool()) {
 
258
    InternetModel::ServiceForIndex(parent)->DropMimeData(data, parent);
 
259
  }
 
260
 
 
261
  return true;
 
262
}
 
263
 
 
264
void InternetModel::ShowContextMenu(const QModelIndex& merged_model_index,
 
265
                                 const QPoint& global_pos) {
 
266
  InternetService* service = ServiceForIndex(merged_model_index);
 
267
  if (service)
 
268
    service->ShowContextMenu(merged_model_->mapToSource(merged_model_index), global_pos);
 
269
}
 
270
 
 
271
void InternetModel::ReloadSettings() {
 
272
  foreach (InternetService* service, sServices->values()) {
 
273
    service->ReloadSettings();
 
274
  }
 
275
}