]> git.sur5r.net Git - minitube/blob - src/MediaView.cpp
Display title and description while video is loading.
[minitube] / src / MediaView.cpp
1 #include "MediaView.h"
2 #include "playlist/PrettyItemDelegate.h"
3 #include "networkaccess.h"
4 #include "videowidget.h"
5 #include "minisplitter.h"
6
7 namespace The {
8     QMap<QString, QAction*>* globalActions();
9     QMap<QString, QMenu*>* globalMenus();
10     QNetworkAccessManager* networkAccessManager();
11 }
12
13 MediaView::MediaView(QWidget *parent) : QWidget(parent) {
14
15     QBoxLayout *layout = new QHBoxLayout();
16     layout->setMargin(0);
17
18     splitter = new MiniSplitter(this);
19     splitter->setChildrenCollapsible(false);
20
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);
31
32     listView = new QListView(this);
33     listView->setItemDelegate(new Playlist::PrettyItemDelegate(this));
34     listView->setSelectionMode(QAbstractItemView::ExtendedSelection);
35
36     // dragndrop
37     listView->setDragEnabled(true);
38     listView->setAcceptDrops(true);
39     listView->setDropIndicatorShown(true);
40     listView->setDragDropMode(QAbstractItemView::InternalMove);
41
42     // cosmetics
43     listView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel);
44     listView->setFrameShape( QFrame::NoFrame );
45     listView->setAttribute(Qt::WA_MacShowFocusRect, false);
46     listView->setMinimumSize(320,240);
47
48     // respond to the user doubleclicking a playlist item
49     connect(listView, SIGNAL(activated(const QModelIndex &)), this, SLOT(itemActivated(const QModelIndex &)));
50
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);
56
57     connect(listView->selectionModel(),
58             SIGNAL(selectionChanged ( const QItemSelection & , const QItemSelection & )),
59             this, SLOT(selectionChanged ( const QItemSelection & , const QItemSelection & )));
60
61     playlistWidget = new PlaylistWidget(this, sortBar, listView);
62     // playlistWidget->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
63
64     splitter->addWidget(playlistWidget);
65
66     videoWidget = new VideoWidget(this);
67     videoWidget->setMinimumSize(320,240);
68     // videoWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
69     videoWidget->hide();
70     splitter->addWidget(videoWidget);
71     
72     loadingWidget = new LoadingWidget(this);
73     loadingWidget->setMinimumSize(320,240);
74     // loadingWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
75     splitter->addWidget(loadingWidget);
76
77     QList<int> sizes;
78     sizes << 320 << 640 << 640;
79     splitter->setSizes(sizes);
80
81     layout->addWidget(splitter);
82     setLayout(layout);
83 }
84
85 MediaView::~MediaView() {
86
87 }
88
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)));
94 }
95
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)));
107 }
108
109 void MediaView::search(SearchParams *searchParams) {
110     this->searchParams = searchParams;
111
112     // this implies that the enum and the bar action order is the same
113     sortBar->setCheckedAction(searchParams->sortBy()-1);
114
115     listModel->search(searchParams);
116     listView->setFocus();
117 }
118
119 void MediaView::disappear() {
120
121 }
122
123 void MediaView::stateChanged(Phonon::State newState, Phonon::State /* oldState */)
124 {
125     switch (newState) {
126
127          case Phonon::ErrorState:
128         qDebug() << "Phonon error:" << mediaObject->errorString() << mediaObject->errorType();
129         // recover from errors by skipping to the next video
130         skip();
131         break;
132
133          case Phonon::PlayingState:
134         qDebug("playing");
135         loadingWidget->hide();
136         videoWidget->show();
137         break;
138
139          case Phonon::StoppedState:
140         qDebug("stopped");
141         // play() has already been called when setting the source
142         // but Phonon on Linux needs a little more help to start playback
143         mediaObject->play();
144         break;
145
146          case Phonon::PausedState:
147         qDebug("paused");
148         break;
149
150          case Phonon::BufferingState:
151         qDebug("buffering");
152         break;
153
154          case Phonon::LoadingState:
155         qDebug("loading");
156         break;
157
158          default:
159         ;
160     }
161 }
162
163 void MediaView::pause() {
164     switch( mediaObject->state() ) {
165     case Phonon::PlayingState:
166         mediaObject->pause();
167         break;
168     default:
169         mediaObject->play();
170         break;
171     }
172 }
173
174 void MediaView::fullscreen() {
175
176 #ifdef Q_WS_MAC
177     splitterState = splitter->saveState();
178     videoWidget->setParent(0);
179     videoWidget->showFullScreen();
180 #else
181     videoWidget->setFullScreen(!videoWidget->isFullScreen());
182 #endif
183
184 }
185
186 void MediaView::exitFullscreen() {
187
188 #ifdef Q_WS_MAC
189     videoWidget->setParent(this);
190     splitter->addWidget(videoWidget);
191     videoWidget->showNormal();
192     splitter->restoreState(splitterState);
193 #else
194     videoWidget->setFullScreen(false);
195 #endif
196
197 }
198
199 void MediaView::stop() {
200     listModel->abortSearch();
201     mediaObject->stop();
202     mediaObject->clear();
203 }
204
205 void MediaView::activeRowChanged(int row) {
206     Video *video = listModel->videoAt(row);
207     if (!video) return;
208
209     // immediately show the loading widget
210     videoWidget->hide();
211     loadingWidget->setVideo(video);
212     loadingWidget->show();
213
214     QUrl streamUrl = video->streamUrl();
215     // qDebug() << "setCurrentSource" << streamUrl.toString();
216
217     // go!
218     mediaObject->setCurrentSource(streamUrl);
219     mediaObject->play();
220
221     // ensure we always have 10 videos ahead
222     listModel->searchNeeded();
223
224     // ensure active item is visible
225     QModelIndex index = listModel->index(row, 0, QModelIndex());
226     listView->scrollTo(index, QAbstractItemView::EnsureVisible);
227 }
228
229 void MediaView::itemActivated(const QModelIndex &index) {
230     if (listModel->rowExists(index.row()))
231         listModel->setActiveRow(index.row());
232     // the user doucleclicked on the "Search More" item
233     else listModel->searchMore();
234 }
235
236 void MediaView::aboutToFinish() {
237     /*
238     int nextRow = listModel->nextRow();
239     if (nextRow == -1) return;
240     Video* video = listModel->videoAt(nextRow);
241     QUrl streamUrl = video->streamUrl();
242     qDebug() << "Enqueing" << streamUrl;
243     mediaObject->enqueue(streamUrl);
244     */
245 }
246
247 void MediaView::currentSourceChanged(const Phonon::MediaSource source) {
248     qDebug() << "Source changed:" << source.url();
249 }
250
251 void MediaView::skip() {
252     int nextRow = listModel->nextRow();
253     if (nextRow == -1) return;
254     listModel->setActiveRow(nextRow);
255 }
256
257 void MediaView::openWebPage() {
258     Video* video = listModel->activeVideo();
259     if (!video) return;
260     mediaObject->pause();
261     QDesktopServices::openUrl(video->webpage());
262 }
263
264 void MediaView::removeSelected() {
265     if (!listView->selectionModel()->hasSelection()) return;
266     QModelIndexList indexes = listView->selectionModel()->selectedIndexes();
267     listModel->removeIndexes(indexes);
268 }
269
270 void MediaView::selectVideos(QList<Video*> videos) {
271     foreach (Video *video, videos) {
272         QModelIndex index = listModel->indexForVideo(video);
273         listView->selectionModel()->select(index, QItemSelectionModel::Select);
274         listView->scrollTo(index, QAbstractItemView::EnsureVisible);
275     }
276 }
277
278 void MediaView::selectionChanged(const QItemSelection & /*selected*/, const QItemSelection & /*deselected*/) {
279     const bool gotSelection = listView->selectionModel()->hasSelection();
280     The::globalActions()->value("remove")->setEnabled(gotSelection);
281     The::globalActions()->value("moveUp")->setEnabled(gotSelection);
282     The::globalActions()->value("moveDown")->setEnabled(gotSelection);
283 }
284
285 void MediaView::moveUpSelected() {
286     if (!listView->selectionModel()->hasSelection()) return;
287     QModelIndexList indexes = listView->selectionModel()->selectedIndexes();
288     listModel->move(indexes, true);
289 }
290
291 void MediaView::moveDownSelected() {
292     if (!listView->selectionModel()->hasSelection()) return;
293     QModelIndexList indexes = listView->selectionModel()->selectedIndexes();
294     listModel->move(indexes, false);
295 }
296
297 void MediaView::showVideoContextMenu(QPoint point) {
298     The::globalMenus()->value("video")->popup(videoWidget->mapToGlobal(point));
299 }
300
301 void MediaView::searchMostRelevant() {
302     searchParams->setSortBy(SearchParams::SortByRelevance);
303     search(searchParams);
304 }
305
306 void MediaView::searchMostRecent() {
307     searchParams->setSortBy(SearchParams::SortByNewest);
308     search(searchParams);
309 }
310
311 void MediaView::searchMostViewed() {
312     searchParams->setSortBy(SearchParams::SortByViewCount);
313     search(searchParams);
314 }