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