]> git.sur5r.net Git - minitube/blob - src/MainWindow.cpp
Will unified mode ever work?
[minitube] / src / MainWindow.cpp
1 #include "MainWindow.h"
2 #include "spacer.h"
3 #include "constants.h"
4 #include "iconloader/qticonloader.h"
5 #include "global.h"
6 #include "videodefinition.h"
7 #include "fontutils.h"
8
9 MainWindow::MainWindow() :
10         aboutView(0),
11         mediaObject(0),
12         audioOutput(0),
13         m_fullscreen(false) {
14
15     // views mechanism
16     history = new QStack<QWidget*>();
17     views = new QStackedWidget(this);
18
19     // views
20     searchView = new SearchView(this);
21     connect(searchView, SIGNAL(search(QString)), this, SLOT(showMedia(QString)));
22     views->addWidget(searchView);
23
24     mediaView = new MediaView(this);
25     views->addWidget(mediaView);
26
27     toolbarSearch = new SearchLineEdit(this);
28     toolbarSearch->setFont(qApp->font());
29     toolbarSearch->setMinimumWidth(toolbarSearch->fontInfo().pixelSize()*15);
30     connect(toolbarSearch, SIGNAL(search(const QString&)), searchView, SLOT(watch(const QString&)));
31
32     // build ui
33     createActions();
34     createMenus();
35     createToolBars();
36     createStatusBar();
37
38     initPhonon();
39     mediaView->setMediaObject(mediaObject);
40
41     // remove that useless menu/toolbar context menu
42     this->setContextMenuPolicy(Qt::NoContextMenu);
43
44     // mediaView init stuff thats needs actions
45     mediaView->initialize();
46
47     // restore window position
48     readSettings();
49
50     // cool toolbar on the Mac
51     // this is too buggy to be enabled
52     // setUnifiedTitleAndToolBarOnMac(true);
53
54     // event filter to block ugly toolbar tooltips
55     qApp->installEventFilter(this);
56
57     // show the initial view
58     showWidget(searchView);
59
60     setCentralWidget(views);
61 }
62
63 MainWindow::~MainWindow() {
64     delete history;
65 }
66
67 bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
68     if (event->type() == QEvent::ToolTip) {
69         // kill tooltips
70         return true;
71     } else {
72         // standard event processing
73         return QObject::eventFilter(obj, event);
74     }
75 }
76
77 void MainWindow::createActions() {
78
79     QMap<QString, QAction*> *actions = The::globalActions();
80
81     stopAct = new QAction(QtIconLoader::icon("media-playback-stop"), tr("&Stop"), this);
82     stopAct->setStatusTip(tr("Stop playback and go back to the search view"));
83     stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
84     actions->insert("stop", stopAct);
85     connect(stopAct, SIGNAL(triggered()), this, SLOT(stop()));
86
87     skipAct = new QAction(QtIconLoader::icon("media-skip-forward"), tr("S&kip"), this);
88     skipAct->setStatusTip(tr("Skip to the next video"));
89     skipAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Right) << QKeySequence(Qt::Key_MediaNext));
90     skipAct->setEnabled(false);
91     actions->insert("skip", skipAct);
92     connect(skipAct, SIGNAL(triggered()), mediaView, SLOT(skip()));
93
94     pauseAct = new QAction(QtIconLoader::icon("media-playback-pause"), tr("&Pause"), this);
95     pauseAct->setStatusTip(tr("Pause playback"));
96     pauseAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Space) << QKeySequence(Qt::Key_MediaPlay));
97     pauseAct->setEnabled(false);
98     actions->insert("pause", pauseAct);
99     connect(pauseAct, SIGNAL(triggered()), mediaView, SLOT(pause()));
100
101     fullscreenAct = new QAction(QtIconLoader::icon("view-fullscreen"), tr("&Full Screen"), this);
102     fullscreenAct->setStatusTip(tr("Go full screen"));
103     fullscreenAct->setShortcut(QKeySequence(Qt::ALT + Qt::Key_Return));
104     fullscreenAct->setShortcutContext(Qt::ApplicationShortcut);
105     actions->insert("fullscreen", fullscreenAct);
106     connect(fullscreenAct, SIGNAL(triggered()), this, SLOT(fullscreen()));
107
108     compactViewAct = new QAction(tr("&Compact mode"), this);
109     compactViewAct->setStatusTip(tr("Hide the playlist and the toolbar"));
110     compactViewAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return));
111     compactViewAct->setCheckable(true);
112     compactViewAct->setChecked(false);
113     compactViewAct->setEnabled(false);
114     actions->insert("compactView", compactViewAct);
115     connect(compactViewAct, SIGNAL(toggled(bool)), this, SLOT(compactView(bool)));
116
117     webPageAct = new QAction(tr("Open the &YouTube page"), this);
118     webPageAct->setStatusTip(tr("Go to the YouTube video page and pause playback"));
119     webPageAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Y));
120     webPageAct->setEnabled(false);
121     actions->insert("webpage", webPageAct);
122     connect(webPageAct, SIGNAL(triggered()), mediaView, SLOT(openWebPage()));
123
124     copyPageAct = new QAction(tr("Copy the YouTube &link"), this);
125     copyPageAct->setStatusTip(tr("Copy the current video YouTube link to the clipboard"));
126     copyPageAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L));
127     copyPageAct->setEnabled(false);
128     actions->insert("pagelink", copyPageAct);
129     connect(copyPageAct, SIGNAL(triggered()), mediaView, SLOT(copyWebPage()));
130
131     copyLinkAct = new QAction(tr("Copy the video stream &URL"), this);
132     copyLinkAct->setStatusTip(tr("Copy the current video stream URL to the clipboard"));
133     copyLinkAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U));
134     copyLinkAct->setEnabled(false);
135     actions->insert("videolink", copyLinkAct);
136     connect(copyLinkAct, SIGNAL(triggered()), mediaView, SLOT(copyVideoLink()));
137
138     removeAct = new QAction(tr("&Remove"), this);
139     removeAct->setStatusTip(tr("Remove the selected videos from the playlist"));
140     removeAct->setShortcuts(QList<QKeySequence>() << QKeySequence("Del") << QKeySequence("Backspace"));
141     removeAct->setEnabled(false);
142     actions->insert("remove", removeAct);
143     connect(removeAct, SIGNAL(triggered()), mediaView, SLOT(removeSelected()));
144
145     moveUpAct = new QAction(tr("Move &Up"), this);
146     moveUpAct->setStatusTip(tr("Move up the selected videos in the playlist"));
147     moveUpAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Up));
148     moveUpAct->setEnabled(false);
149     actions->insert("moveUp", moveUpAct);
150     connect(moveUpAct, SIGNAL(triggered()), mediaView, SLOT(moveUpSelected()));
151
152     moveDownAct = new QAction(tr("Move &Down"), this);
153     moveDownAct->setStatusTip(tr("Move down the selected videos in the playlist"));
154     moveDownAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Down));
155     moveDownAct->setEnabled(false);
156     actions->insert("moveDown", moveDownAct);
157     connect(moveDownAct, SIGNAL(triggered()), mediaView, SLOT(moveDownSelected()));
158
159     clearAct = new QAction(tr("&Clear recent keywords"), this);
160     clearAct->setMenuRole(QAction::ApplicationSpecificRole);
161     clearAct->setShortcuts(QList<QKeySequence>()
162                            << QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Delete)
163                            << QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Backspace));
164     clearAct->setStatusTip(tr("Clear the search history. Cannot be undone."));
165     clearAct->setEnabled(true);
166     actions->insert("clearRecentKeywords", clearAct);
167     connect(clearAct, SIGNAL(triggered()), SLOT(clearRecentKeywords()));
168
169     quitAct = new QAction(tr("&Quit"), this);
170     quitAct->setMenuRole(QAction::QuitRole);
171     quitAct->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Q")) << QKeySequence(Qt::CTRL + Qt::Key_W));
172     quitAct->setStatusTip(tr("Bye"));
173     actions->insert("quit", quitAct);
174     connect(quitAct, SIGNAL(triggered()), this, SLOT(quit()));
175
176     siteAct = new QAction(tr("&Website"), this);
177     siteAct->setShortcut(QKeySequence::HelpContents);
178     siteAct->setStatusTip(tr("%1 on the Web").arg(Constants::APP_NAME));
179     actions->insert("site", siteAct);
180     connect(siteAct, SIGNAL(triggered()), this, SLOT(visitSite()));
181
182     donateAct = new QAction(tr("Make a &donation"), this);
183     donateAct->setStatusTip(tr("Please support the continued development of %1").arg(Constants::APP_NAME));
184     actions->insert("donate", donateAct);
185     connect(donateAct, SIGNAL(triggered()), this, SLOT(donate()));
186
187     aboutAct = new QAction(tr("&About"), this);
188     aboutAct->setMenuRole(QAction::AboutRole);
189     aboutAct->setStatusTip(tr("Info about %1").arg(Constants::APP_NAME));
190     actions->insert("about", aboutAct);
191     connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
192
193     // Invisible actions
194
195     searchFocusAct = new QAction(this);
196     searchFocusAct->setShortcut(QKeySequence::Find);
197     searchFocusAct->setStatusTip(tr("Search"));
198     actions->insert("search", searchFocusAct);
199     connect(searchFocusAct, SIGNAL(triggered()), this, SLOT(searchFocus()));
200     addAction(searchFocusAct);
201
202     volumeUpAct = new QAction(this);
203     volumeUpAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Plus) << QKeySequence(Qt::Key_VolumeUp));
204     actions->insert("volume-up", volumeUpAct);
205     connect(volumeUpAct, SIGNAL(triggered()), this, SLOT(volumeUp()));
206     addAction(volumeUpAct);
207
208     volumeDownAct = new QAction(this);
209     volumeDownAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Minus) << QKeySequence(Qt::Key_VolumeDown));
210     actions->insert("volume-down", volumeDownAct);
211     connect(volumeDownAct, SIGNAL(triggered()), this, SLOT(volumeDown()));
212     addAction(volumeDownAct);
213
214     volumeMuteAct = new QAction(this);
215     volumeMuteAct->setIcon(QtIconLoader::icon("audio-volume-high"));
216     volumeMuteAct->setStatusTip(tr("Mute volume"));
217     volumeMuteAct->setShortcuts(QList<QKeySequence>()
218                                 << QKeySequence(tr("Ctrl+M"))
219                                 << QKeySequence(Qt::Key_VolumeMute));
220     actions->insert("volume-mute", volumeMuteAct);
221     connect(volumeMuteAct, SIGNAL(triggered()), SLOT(volumeMute()));
222     addAction(volumeMuteAct);
223
224     QAction *definitionAct = new QAction(this);
225     definitionAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_D));
226     /*
227     QMenu *definitionMenu = new QMenu(this);
228     foreach (QString definition, VideoDefinition::getDefinitionNames()) {
229         definitionMenu->addAction(definition);
230     }
231     definitionAct->setMenu(definitionMenu);
232     */
233     actions->insert("definition", definitionAct);
234     connect(definitionAct, SIGNAL(triggered()), SLOT(toggleDefinitionMode()));
235     addAction(definitionAct);
236
237     // common action properties
238     foreach (QAction *action, actions->values()) {
239
240         // add actions to the MainWindow so that they work
241         // when the menu is hidden
242         addAction(action);
243
244         // never autorepeat.
245         // unexperienced users tend to keep keys pressed for a "long" time
246         action->setAutoRepeat(false);
247
248         // set to something more meaningful then the toolbar text
249         // HELP! how to remove tooltips altogether?!
250         if (!action->statusTip().isEmpty())
251             action->setToolTip(action->statusTip());
252
253         // show keyboard shortcuts in the status bar
254         if (!action->shortcut().isEmpty())
255             action->setStatusTip(action->statusTip() + " (" + action->shortcut().toString(QKeySequence::NativeText) + ")");
256
257         // no icons in menus
258         action->setIconVisibleInMenu(false);
259
260     }
261
262 }
263
264 void MainWindow::createMenus() {
265
266     QMap<QString, QMenu*> *menus = The::globalMenus();
267
268     fileMenu = menuBar()->addMenu(tr("&Application"));
269     // menus->insert("file", fileMenu);
270     fileMenu->addAction(clearAct);
271 #ifndef APP_MAC
272     fileMenu->addSeparator();
273 #endif
274     fileMenu->addAction(quitAct);
275
276     playlistMenu = menuBar()->addMenu(tr("&Playlist"));
277     menus->insert("playlist", playlistMenu);
278     playlistMenu->addAction(removeAct);
279     playlistMenu->addSeparator();
280     playlistMenu->addAction(moveUpAct);
281     playlistMenu->addAction(moveDownAct);
282
283     viewMenu = menuBar()->addMenu(tr("&Video"));
284     menus->insert("video", viewMenu);
285     viewMenu->addAction(stopAct);
286     viewMenu->addAction(pauseAct);
287     viewMenu->addAction(skipAct);
288     viewMenu->addSeparator();
289     viewMenu->addAction(webPageAct);
290     viewMenu->addAction(copyPageAct);
291     viewMenu->addAction(copyLinkAct);
292     viewMenu->addSeparator();
293     viewMenu->addAction(compactViewAct);
294     viewMenu->addAction(fullscreenAct);
295
296     helpMenu = menuBar()->addMenu(tr("&Help"));
297     helpMenu->addAction(siteAct);
298     helpMenu->addAction(donateAct);
299     helpMenu->addAction(aboutAct);
300 }
301
302 void MainWindow::createToolBars() {
303
304     setUnifiedTitleAndToolBarOnMac(true);
305
306     mainToolBar = new QToolBar(this);
307 #if QT_VERSION < 0x040600 | defined(APP_MAC)
308     mainToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
309 #else
310     mainToolBar->setToolButtonStyle(Qt::ToolButtonFollowStyle);
311 #endif
312     mainToolBar->setFloatable(false);
313     mainToolBar->setMovable(false);
314
315 #ifdef APP_MAC
316     mainToolBar->setIconSize(QSize(32, 32));
317 #endif
318
319     mainToolBar->addAction(stopAct);
320     mainToolBar->addAction(pauseAct);
321     mainToolBar->addAction(skipAct);
322     mainToolBar->addAction(fullscreenAct);
323
324     mainToolBar->addWidget(new Spacer());
325
326     QFont smallerFont = FontUtils::small();
327     currentTime = new QLabel(mainToolBar);
328     currentTime->setFont(smallerFont);
329     mainToolBar->addWidget(currentTime);
330
331     mainToolBar->addWidget(new Spacer());
332
333     seekSlider = new Phonon::SeekSlider(this);
334     seekSlider->setIconVisible(false);
335     seekSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
336     mainToolBar->addWidget(seekSlider);
337
338     mainToolBar->addWidget(new Spacer());
339
340     totalTime = new QLabel(mainToolBar);
341     totalTime->setFont(smallerFont);
342     mainToolBar->addWidget(totalTime);
343
344     mainToolBar->addWidget(new Spacer());
345
346     mainToolBar->addAction(volumeMuteAct);
347
348     volumeSlider = new Phonon::VolumeSlider(this);
349     volumeSlider->setMuteVisible(false);
350     // qDebug() << volumeSlider->children();
351     // status tip for the volume slider
352     QSlider* volumeQSlider = volumeSlider->findChild<QSlider*>();
353     if (volumeQSlider)
354         volumeQSlider->setStatusTip(tr("Press %1 to raise the volume, %2 to lower it").arg(
355                 volumeUpAct->shortcut().toString(QKeySequence::NativeText), volumeDownAct->shortcut().toString(QKeySequence::NativeText)));
356     // this makes the volume slider smaller
357     volumeSlider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
358     mainToolBar->addWidget(volumeSlider);
359
360     mainToolBar->addWidget(new Spacer());
361
362     toolbarSearch->setStatusTip(searchFocusAct->statusTip());
363     mainToolBar->addWidget(toolbarSearch);
364
365     mainToolBar->addWidget(new Spacer());
366
367     addToolBar(mainToolBar);
368 }
369
370 void MainWindow::createStatusBar() {
371
372     // remove ugly borders on OSX
373     // also remove excessive spacing
374     statusBar()->setStyleSheet("::item{border:0 solid} QToolBar {padding:0;spacing:0;margin:0}");
375
376     QToolBar *toolBar = new QToolBar(this);
377     toolBar->setToolButtonStyle(Qt::ToolButtonTextOnly);
378     toolBar->addAction(The::globalActions()->value("definition"));
379     statusBar()->addPermanentWidget(toolBar);
380
381     statusBar()->show();
382 }
383
384 void MainWindow::readSettings() {
385     QSettings settings;
386     restoreGeometry(settings.value("geometry").toByteArray());
387     setDefinitionMode(settings.value("definition", VideoDefinition::getDefinitionNames().first()).toString());
388     audioOutput->setVolume(settings.value("volume", 1).toDouble());
389     audioOutput->setMuted(settings.value("volumeMute").toBool());
390 }
391
392 void MainWindow::writeSettings() {
393     // do not save geometry when in full screen
394     if (m_fullscreen)
395         return;
396     QSettings settings;
397     settings.setValue("geometry", saveGeometry());
398     settings.setValue("volume", audioOutput->volume());
399     settings.setValue("volumeMute", audioOutput->isMuted());
400     mediaView->saveSplitterState();
401 }
402
403 void MainWindow::goBack() {
404     if ( history->size() > 1 ) {
405         history->pop();
406         QWidget *widget = history->pop();
407         showWidget(widget);
408     }
409 }
410
411 void MainWindow::showWidget ( QWidget* widget ) {
412
413     setUpdatesEnabled(false);
414
415     // call hide method on the current view
416     View* oldView = dynamic_cast<View *> (views->currentWidget());
417     if (oldView) {
418         oldView->disappear();
419     }
420
421     // call show method on the new view
422     View* newView = dynamic_cast<View *> (widget);
423     if (newView) {
424         newView->appear();
425         QMap<QString,QVariant> metadata = newView->metadata();
426         QString windowTitle = metadata.value("title").toString();
427         if (windowTitle.length())
428             windowTitle += " - ";
429         setWindowTitle(windowTitle + Constants::APP_NAME);
430         statusBar()->showMessage((metadata.value("description").toString()));
431     }
432
433     stopAct->setEnabled(widget == mediaView);
434     fullscreenAct->setEnabled(widget == mediaView);
435     compactViewAct->setEnabled(widget == mediaView);
436     webPageAct->setEnabled(widget == mediaView);
437     copyPageAct->setEnabled(widget == mediaView);
438     copyLinkAct->setEnabled(widget == mediaView);
439     aboutAct->setEnabled(widget != aboutView);
440
441     // toolbar only for the mediaView
442     mainToolBar->setVisible(widget == mediaView && !compactViewAct->isChecked());
443
444     setUpdatesEnabled(true);
445
446     QWidget *oldWidget = views->currentWidget();
447     views->setCurrentWidget(widget);
448
449 #ifdef APP_MAC
450     // crossfade only on OSX
451     // where we can be sure of video performance
452     fadeInWidget(oldWidget, widget);
453 #endif
454
455     history->push(widget);
456 }
457
458 void MainWindow::fadeInWidget(QWidget *oldWidget, QWidget *newWidget) {
459     if (faderWidget) faderWidget->close();
460     if (!oldWidget || !newWidget) {
461         // qDebug() << "no widgets";
462         return;
463     }
464     faderWidget = new FaderWidget(newWidget);
465     faderWidget->start(QPixmap::grabWidget(oldWidget));
466 }
467
468 void MainWindow::about() {
469     if (!aboutView) {
470         aboutView = new AboutView(this);
471         views->addWidget(aboutView);
472     }
473     showWidget(aboutView);
474 }
475
476 void MainWindow::visitSite() {
477     QUrl url(Constants::WEBSITE);
478     statusBar()->showMessage(QString(tr("Opening %1").arg(url.toString())));
479     QDesktopServices::openUrl(url);
480 }
481
482 void MainWindow::donate() {
483     QUrl url(QString(Constants::WEBSITE) + "#donate");
484     statusBar()->showMessage(QString(tr("Opening %1").arg(url.toString())));
485     QDesktopServices::openUrl(url);
486 }
487
488 void MainWindow::quit() {
489     writeSettings();
490     qApp->quit();
491 }
492
493 void MainWindow::closeEvent(QCloseEvent *event) {
494     quit();
495     QWidget::closeEvent(event);
496 }
497
498 /*
499 void MainWindow::showSettings() {
500     if (!settingsView) {
501         settingsView = new SettingsView(this);
502         views->addWidget(settingsView);
503     }
504     showWidget(settingsView);
505 }*/
506
507 void MainWindow::showSearch() {
508     showWidget(searchView);
509     currentTime->clear();
510     totalTime->clear();
511 }
512
513 void MainWindow::showMedia(QString query) {
514     SearchParams *searchParams = new SearchParams();
515     searchParams->setKeywords(query);
516     mediaView->search(searchParams);
517     showWidget(mediaView);
518 }
519
520 void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState */) {
521
522     // qDebug() << "Phonon state: " << newState;
523
524     switch (newState) {
525
526     case Phonon::ErrorState:
527         if (mediaObject->errorType() == Phonon::FatalError) {
528             statusBar()->showMessage(tr("Fatal error: %1").arg(mediaObject->errorString()));
529         } else {
530             statusBar()->showMessage(tr("Error: %1").arg(mediaObject->errorString()));
531         }
532         break;
533
534          case Phonon::PlayingState:
535         pauseAct->setEnabled(true);
536         pauseAct->setIcon(QtIconLoader::icon("media-playback-pause"));
537         pauseAct->setText(tr("&Pause"));
538         pauseAct->setStatusTip(tr("Pause playback") + " (" +  pauseAct->shortcut().toString(QKeySequence::NativeText) + ")");
539         skipAct->setEnabled(true);
540         break;
541
542          case Phonon::StoppedState:
543         pauseAct->setEnabled(false);
544         skipAct->setEnabled(false);
545         break;
546
547          case Phonon::PausedState:
548         skipAct->setEnabled(true);
549         pauseAct->setEnabled(true);
550         pauseAct->setIcon(QtIconLoader::icon("media-playback-start"));
551         pauseAct->setText(tr("&Play"));
552         pauseAct->setStatusTip(tr("Resume playback") + " (" +  pauseAct->shortcut().toString(QKeySequence::NativeText) + ")");
553         break;
554
555          case Phonon::BufferingState:
556          case Phonon::LoadingState:
557         skipAct->setEnabled(true);
558         pauseAct->setEnabled(false);
559         currentTime->clear();
560         totalTime->clear();
561         break;
562
563          default:
564         ;
565     }
566 }
567
568 void MainWindow::stop() {
569     mediaView->stop();
570     showSearch();
571 }
572
573 void MainWindow::fullscreen() {
574
575     setUpdatesEnabled(false);
576
577     // No compact view action when in full screen
578     compactViewAct->setVisible(m_fullscreen);
579     compactViewAct->setChecked(false);
580
581     // Also no Youtube action since it opens a new window
582     webPageAct->setVisible(m_fullscreen);
583     copyPageAct->setVisible(m_fullscreen);
584     copyLinkAct->setVisible(m_fullscreen);
585
586     stopAct->setVisible(m_fullscreen);
587
588     // workaround: prevent focus on the search bar
589     // it steals the Space key needed for Play/Pause
590     mainToolBar->setEnabled(m_fullscreen);
591
592     // Hide anything but the video
593     mediaView->setPlaylistVisible(m_fullscreen);
594     statusBar()->setVisible(m_fullscreen);
595
596 #ifndef APP_MAC
597     menuBar()->setVisible(m_fullscreen);
598 #endif
599
600 #ifdef APP_MAC
601     // make the actions work when video is fullscreen (on the Mac)
602     QMap<QString, QAction*> *actions = The::globalActions();
603     foreach (QAction *action, actions->values()) {
604         if (m_fullscreen) {
605             action->setShortcutContext(Qt::WindowShortcut);
606         } else {
607             action->setShortcutContext(Qt::ApplicationShortcut);
608         }
609     }
610 #endif
611
612     if (m_fullscreen) {
613         // use setShortucs instead of setShortcut
614         // the latter seems not to work
615         fullscreenAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::ALT + Qt::Key_Return));
616         fullscreenAct->setText(tr("&Full Screen"));
617         stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
618
619         mainToolBar->show();
620         if (m_maximized) showMaximized();
621         else showNormal();
622
623         // Make sure the window has focus (Mac)
624         activateWindow();
625
626     } else {
627         stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_MediaStop));
628         fullscreenAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::ALT + Qt::Key_Return));
629         fullscreenAct->setText(tr("Exit &Full Screen"));
630         m_maximized = isMaximized();
631
632         // save geometry now, if the user quits when in full screen
633         // geometry won't be saved
634         writeSettings();
635
636         mainToolBar->hide();
637         showFullScreen();
638     }
639
640     m_fullscreen = !m_fullscreen;
641
642     setUpdatesEnabled(true);
643 }
644
645 void MainWindow::compactView(bool enable) {
646
647     setUpdatesEnabled(false);
648
649     mainToolBar->setVisible(!enable);
650     mainToolBar->setEnabled(!enable);
651     mediaView->setPlaylistVisible(!enable);
652     statusBar()->setVisible(!enable);
653
654 #ifndef APP_MAC
655     menuBar()->setVisible(!enable);
656 #endif
657
658     // ensure focus does not end up to the search box
659     // as it would steal the Space shortcut
660     // toolbarSearch->setEnabled(!enable);
661
662     if (enable) {
663         stopAct->setShortcut(QString(""));
664         QList<QKeySequence> shortcuts;
665         // for some reason it is important that ESC comes first
666         shortcuts << QKeySequence(Qt::CTRL + Qt::Key_Return) << QKeySequence(Qt::Key_Escape);
667         compactViewAct->setShortcuts(shortcuts);
668     } else {
669         compactViewAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return));
670         stopAct->setShortcut(QKeySequence(Qt::Key_Escape));
671     }
672
673     setUpdatesEnabled(true);
674 }
675
676 void MainWindow::searchFocus() {
677     QWidget *view = views->currentWidget();
678     if (view == mediaView) {
679         toolbarSearch->selectAll();
680         toolbarSearch->setFocus();
681     }
682 }
683
684 void MainWindow::initPhonon() {
685     // Phonon initialization
686     if (mediaObject) delete mediaObject;
687     if (audioOutput) delete audioOutput;
688     mediaObject = new Phonon::MediaObject(this);
689     mediaObject->setTickInterval(100);
690     connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
691             this, SLOT(stateChanged(Phonon::State, Phonon::State)));
692     connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64)));
693     connect(mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64)));
694     seekSlider->setMediaObject(mediaObject);
695     audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this);
696     connect(audioOutput, SIGNAL(volumeChanged(qreal)), this, SLOT(volumeChanged(qreal)));
697     connect(audioOutput, SIGNAL(mutedChanged(bool)), this, SLOT(volumeMutedChanged(bool)));
698     volumeSlider->setAudioOutput(audioOutput);
699     Phonon::createPath(mediaObject, audioOutput);
700 }
701
702 void MainWindow::tick(qint64 time) {
703     if (time <= 0) {
704         currentTime->clear();
705         return;
706     }
707
708     currentTime->setText(formatTime(time));
709
710     // remaining time
711     const qint64 remainingTime = mediaObject->remainingTime();
712     currentTime->setStatusTip(tr("Remaining time: %1").arg(formatTime(remainingTime)));
713
714 }
715
716 void MainWindow::totalTimeChanged(qint64 time) {
717     if (time <= 0) {
718         totalTime->clear();
719         return;
720     }
721     totalTime->setText(formatTime(time));
722 }
723
724 QString MainWindow::formatTime(qint64 time) {
725     QTime displayTime;
726     displayTime = displayTime.addMSecs(time);
727     QString timeString;
728     // 60 * 60 * 1000 = 3600000
729     if (time > 3600000)
730         timeString = displayTime.toString("h:mm:ss");
731     else
732         timeString = displayTime.toString("m:ss");
733     return timeString;
734 }
735
736 void MainWindow::volumeUp() {
737     qreal newVolume = volumeSlider->audioOutput()->volume() + .1;
738     if (newVolume > volumeSlider->maximumVolume())
739         newVolume = volumeSlider->maximumVolume();
740     volumeSlider->audioOutput()->setVolume(newVolume);
741 }
742
743 void MainWindow::volumeDown() {
744     qreal newVolume = volumeSlider->audioOutput()->volume() - .1;
745     if (newVolume < 0)
746         newVolume = 0;
747     volumeSlider->audioOutput()->setVolume(newVolume);
748 }
749
750 void MainWindow::volumeMute() {
751     volumeSlider->audioOutput()->setMuted(!volumeSlider->audioOutput()->isMuted());
752 }
753
754 void MainWindow::volumeChanged(qreal newVolume) {
755     // automatically unmute when volume changes
756     if (volumeSlider->audioOutput()->isMuted())
757         volumeSlider->audioOutput()->setMuted(false);
758     statusBar()->showMessage(tr("Volume at %1%").arg(newVolume*100));
759 }
760
761 void MainWindow::volumeMutedChanged(bool muted) {
762     if (muted) {
763         volumeMuteAct->setIcon(QtIconLoader::icon("audio-volume-muted"));
764         statusBar()->showMessage(tr("Volume is muted"));
765     } else {
766         volumeMuteAct->setIcon(QtIconLoader::icon("audio-volume-high"));
767         statusBar()->showMessage(tr("Volume is unmuted"));
768     }
769 }
770
771 void MainWindow::setDefinitionMode(QString definitionName) {
772     QAction *definitionAct = The::globalActions()->value("definition");
773     definitionAct->setText(definitionName);
774     definitionAct->setStatusTip(tr("Maximum video definition set to %1").arg(definitionAct->text())
775                                 + " (" +  definitionAct->shortcut().toString(QKeySequence::NativeText) + ")");
776     statusBar()->showMessage(definitionAct->statusTip());
777     QSettings settings;
778     settings.setValue("definition", definitionName);
779 }
780
781 void MainWindow::toggleDefinitionMode() {
782     QSettings settings;
783     QString currentDefinition = settings.value("definition").toString();
784     QStringList definitionNames = VideoDefinition::getDefinitionNames();
785     int currentIndex = definitionNames.indexOf(currentDefinition);
786     int nextIndex = 0;
787     if (currentIndex != definitionNames.size() - 1) {
788         nextIndex = currentIndex + 1;
789     }
790     QString nextDefinition = definitionNames.at(nextIndex);
791     setDefinitionMode(nextDefinition);
792 }
793
794 void MainWindow::showFullscreenToolbar(bool show) {
795     if (!m_fullscreen) return;
796
797     if (show) {
798         mainToolBar->show();
799     } else {
800         mainToolBar->hide();
801     }
802     mainToolBar->setEnabled(show);
803 }
804
805 void MainWindow::showFullscreenPlaylist(bool show) {
806     if (!m_fullscreen) return;
807     mediaView->setPlaylistVisible(show);
808 }
809
810 void MainWindow::clearRecentKeywords() {
811     QSettings settings;
812     settings.remove("recentKeywords");
813     searchView->updateRecentKeywords();
814     statusBar()->showMessage(tr("Your privacy is now safe"));
815 }