2 #include "playlist/PrettyItemDelegate.h"
3 #include "networkaccess.h"
4 #include "videowidget.h"
5 #include "minisplitter.h"
8 QMap<QString, QAction*>* globalActions();
9 QMap<QString, QMenu*>* globalMenus();
10 QNetworkAccessManager* networkAccessManager();
13 MediaView::MediaView(QWidget *parent) : QWidget(parent) {
15 QBoxLayout *layout = new QHBoxLayout();
18 splitter = new MiniSplitter(this);
19 splitter->setChildrenCollapsible(false);
21 sortBar = new THBlackBar(this);
22 mostRelevantAction = new THAction(tr("Most relevant"), this);
23 connect(mostRelevantAction, SIGNAL(triggered()), this, SLOT(searchMostRelevant()), Qt::QueuedConnection);
24 sortBar->addAction(mostRelevantAction);
25 mostRecentAction = new THAction(tr("Most recent"), this);
26 connect(mostRecentAction, SIGNAL(triggered()), this, SLOT(searchMostRecent()), Qt::QueuedConnection);
27 sortBar->addAction(mostRecentAction);
28 mostViewedAction = new THAction(tr("Most viewed"), this);
29 connect(mostViewedAction, SIGNAL(triggered()), this, SLOT(searchMostViewed()), Qt::QueuedConnection);
30 sortBar->addAction(mostViewedAction);
32 listView = new QListView(this);
33 listView->setItemDelegate(new Playlist::PrettyItemDelegate(this));
34 listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
37 listView->setDragEnabled(true);
38 listView->setAcceptDrops(true);
39 listView->setDropIndicatorShown(true);
40 listView->setDragDropMode(QAbstractItemView::InternalMove);
43 listView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
44 listView->setFrameShape( QFrame::NoFrame );
45 listView->setAttribute(Qt::WA_MacShowFocusRect, false);
46 listView->setMinimumSize(320,240);
48 // respond to the user doubleclicking a playlist item
49 connect(listView, SIGNAL(activated(const QModelIndex &)), this, SLOT(itemActivated(const QModelIndex &)));
51 listModel = new ListModel(this);
52 connect(listModel, SIGNAL(activeRowChanged(int)), this, SLOT(activeRowChanged(int)));
53 // needed to restore the selection after dragndrop
54 connect(listModel, SIGNAL(needSelectionFor(QList<Video*>)), this, SLOT(selectVideos(QList<Video*>)));
55 listView->setModel(listModel);
57 connect(listView->selectionModel(),
58 SIGNAL(selectionChanged ( const QItemSelection & , const QItemSelection & )),
59 this, SLOT(selectionChanged ( const QItemSelection & , const QItemSelection & )));
61 playlistWidget = new PlaylistWidget(this, sortBar, listView);
62 // playlistWidget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
64 splitter->addWidget(playlistWidget);
66 videoWidget = new VideoWidget(this);
67 videoWidget->setMinimumSize(320,240);
68 // videoWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
70 splitter->addWidget(videoWidget);
72 loadingWidget = new LoadingWidget(this);
73 loadingWidget->setMinimumSize(320,240);
74 // loadingWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
75 splitter->addWidget(loadingWidget);
78 sizes << 320 << 640 << 640;
79 splitter->setSizes(sizes);
81 layout->addWidget(splitter);
85 MediaView::~MediaView() {
89 void MediaView::initialize() {
90 connect(videoWidget, SIGNAL(doubleClicked()), The::globalActions()->value("fullscreen"), SLOT(trigger()));
91 videoWidget->setContextMenuPolicy(Qt::CustomContextMenu);
92 connect(videoWidget, SIGNAL(customContextMenuRequested(QPoint)),
93 this, SLOT(showVideoContextMenu(QPoint)));
96 void MediaView::setMediaObject(Phonon::MediaObject *mediaObject) {
97 this->mediaObject = mediaObject;
98 Phonon::createPath(this->mediaObject, videoWidget);
99 // connect(mediaObject, SIGNAL(aboutToFinish()), this, SLOT(aboutToFinish()));
100 connect(mediaObject, SIGNAL(finished()), this, SLOT(skip()));
101 connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
102 this, SLOT(stateChanged(Phonon::State, Phonon::State)));
103 connect(mediaObject, SIGNAL(currentSourceChanged(Phonon::MediaSource)),
104 this, SLOT(currentSourceChanged(Phonon::MediaSource)));
105 // connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64)));
106 connect(mediaObject, SIGNAL(bufferStatus(int)), loadingWidget, SLOT(bufferStatus(int)));
109 void MediaView::search(SearchParams *searchParams) {
110 this->searchParams = searchParams;
112 // this implies that the enum and the bar action order is the same
113 sortBar->setCheckedAction(searchParams->sortBy()-1);
115 listModel->search(searchParams);
116 listView->setFocus();
119 void MediaView::disappear() {
123 void MediaView::stateChanged(Phonon::State newState, Phonon::State /* oldState */)
127 case Phonon::ErrorState:
128 qDebug() << "Phonon error:" << mediaObject->errorString() << mediaObject->errorType();
129 // recover from errors by skipping to the next video
133 case Phonon::PlayingState:
135 loadingWidget->hide();
139 case Phonon::StoppedState:
141 // play() has already been called when setting the source
142 // but Phonon on Linux needs a little more help to start playback
146 case Phonon::PausedState:
150 case Phonon::BufferingState:
154 case Phonon::LoadingState:
163 void MediaView::pause() {
164 switch( mediaObject->state() ) {
165 case Phonon::PlayingState:
166 mediaObject->pause();
174 void MediaView::fullscreen() {
177 splitterState = splitter->saveState();
178 videoWidget->setParent(0);
179 videoWidget->showFullScreen();
181 videoWidget->setFullScreen(!videoWidget->isFullScreen());
186 void MediaView::exitFullscreen() {
189 videoWidget->setParent(this);
190 splitter->addWidget(videoWidget);
191 videoWidget->showNormal();
192 splitter->restoreState(splitterState);
194 videoWidget->setFullScreen(false);
199 void MediaView::stop() {
200 listModel->abortSearch();
202 mediaObject->clear();
205 void MediaView::activeRowChanged(int row) {
206 Video *video = listModel->videoAt(row);
209 // immediately show the loading widget
211 loadingWidget->setVideo(video);
212 loadingWidget->show();
214 mediaObject->pause();
216 connect(video, SIGNAL(gotStreamUrl(QUrl)), SLOT(gotStreamUrl(QUrl)));
217 video->loadStreamUrl();
219 // see you in gotStreamUrl...
223 void MediaView::gotStreamUrl(QUrl streamUrl) {
226 mediaObject->setCurrentSource(streamUrl);
229 // ensure we always have 10 videos ahead
230 listModel->searchNeeded();
232 // ensure active item is visible
233 int row = listModel->activeRow();
235 QModelIndex index = listModel->index(row, 0, QModelIndex());
236 listView->scrollTo(index, QAbstractItemView::EnsureVisible);
240 void MediaView::itemActivated(const QModelIndex &index) {
241 if (listModel->rowExists(index.row()))
242 listModel->setActiveRow(index.row());
243 // the user doucleclicked on the "Search More" item
244 else listModel->searchMore();
247 void MediaView::aboutToFinish() {
249 int nextRow = listModel->nextRow();
250 if (nextRow == -1) return;
251 Video* video = listModel->videoAt(nextRow);
252 QUrl streamUrl = video->streamUrl();
253 qDebug() << "Enqueing" << streamUrl;
254 mediaObject->enqueue(streamUrl);
258 void MediaView::currentSourceChanged(const Phonon::MediaSource source) {
259 qDebug() << "Source changed:" << source.url();
262 void MediaView::skip() {
263 int nextRow = listModel->nextRow();
264 if (nextRow == -1) return;
265 listModel->setActiveRow(nextRow);
268 void MediaView::openWebPage() {
269 Video* video = listModel->activeVideo();
271 mediaObject->pause();
272 QDesktopServices::openUrl(video->webpage());
275 void MediaView::removeSelected() {
276 if (!listView->selectionModel()->hasSelection()) return;
277 QModelIndexList indexes = listView->selectionModel()->selectedIndexes();
278 listModel->removeIndexes(indexes);
281 void MediaView::selectVideos(QList<Video*> videos) {
282 foreach (Video *video, videos) {
283 QModelIndex index = listModel->indexForVideo(video);
284 listView->selectionModel()->select(index, QItemSelectionModel::Select);
285 listView->scrollTo(index, QAbstractItemView::EnsureVisible);
289 void MediaView::selectionChanged(const QItemSelection & /*selected*/, const QItemSelection & /*deselected*/) {
290 const bool gotSelection = listView->selectionModel()->hasSelection();
291 The::globalActions()->value("remove")->setEnabled(gotSelection);
292 The::globalActions()->value("moveUp")->setEnabled(gotSelection);
293 The::globalActions()->value("moveDown")->setEnabled(gotSelection);
296 void MediaView::moveUpSelected() {
297 if (!listView->selectionModel()->hasSelection()) return;
298 QModelIndexList indexes = listView->selectionModel()->selectedIndexes();
299 listModel->move(indexes, true);
302 void MediaView::moveDownSelected() {
303 if (!listView->selectionModel()->hasSelection()) return;
304 QModelIndexList indexes = listView->selectionModel()->selectedIndexes();
305 listModel->move(indexes, false);
308 void MediaView::showVideoContextMenu(QPoint point) {
309 The::globalMenus()->value("video")->popup(videoWidget->mapToGlobal(point));
312 void MediaView::searchMostRelevant() {
313 searchParams->setSortBy(SearchParams::SortByRelevance);
314 search(searchParams);
317 void MediaView::searchMostRecent() {
318 searchParams->setSortBy(SearchParams::SortByNewest);
319 search(searchParams);
322 void MediaView::searchMostViewed() {
323 searchParams->setSortBy(SearchParams::SortByViewCount);
324 search(searchParams);