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