]> git.sur5r.net Git - minitube/blob - src/MainWindow.cpp
31398c4abdbd379bd91faa0c6b8c93be94270390
[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
8 MainWindow::MainWindow() :
9         mediaObject(0),
10         audioOutput(0),
11         aboutView(0),
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("Make a &donation"), 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 *definitionAct = new QAction(this);
221     definitionAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_D));
222     /*
223     QMenu *definitionMenu = new QMenu(this);
224     foreach (QString definition, VideoDefinition::getDefinitionNames()) {
225         definitionMenu->addAction(definition);
226     }
227     definitionAct->setMenu(definitionMenu);
228     */
229     actions->insert("definition", definitionAct);
230     connect(definitionAct, SIGNAL(triggered()), SLOT(toggleDefinitionMode()));
231     addAction(definitionAct);
232
233     // common action properties
234     foreach (QAction *action, actions->values()) {
235
236         // add actions to the MainWindow so that they work
237         // when the menu is hidden
238         addAction(action);
239
240         // never autorepeat.
241         // unexperienced users tend to keep keys pressed for a "long" time
242         action->setAutoRepeat(false);
243
244         // set to something more meaningful then the toolbar text
245         // HELP! how to remove tooltips altogether?!
246         if (!action->statusTip().isEmpty())
247             action->setToolTip(action->statusTip());
248
249         // show keyboard shortcuts in the status bar
250         if (!action->shortcut().isEmpty())
251             action->setStatusTip(action->statusTip() + " (" + action->shortcut().toString(QKeySequence::NativeText) + ")");
252
253         // no icons in menus
254         action->setIconVisibleInMenu(false);
255
256     }
257
258 }
259
260 void MainWindow::createMenus() {
261
262     QMap<QString, QMenu*> *menus = The::globalMenus();
263
264     fileMenu = menuBar()->addMenu(tr("&Application"));
265     // menus->insert("file", fileMenu);
266     fileMenu->addAction(clearAct);
267 #ifndef Q_WS_MAC
268     fileMenu->addSeparator();
269 #endif
270     fileMenu->addAction(quitAct);
271
272     playlistMenu = menuBar()->addMenu(tr("&Playlist"));
273     menus->insert("playlist", playlistMenu);
274     playlistMenu->addAction(removeAct);
275     playlistMenu->addSeparator();
276     playlistMenu->addAction(moveUpAct);
277     playlistMenu->addAction(moveDownAct);
278
279     viewMenu = menuBar()->addMenu(tr("&Video"));
280     menus->insert("video", viewMenu);
281     viewMenu->addAction(stopAct);
282     viewMenu->addAction(pauseAct);
283     viewMenu->addAction(skipAct);
284     viewMenu->addSeparator();
285     viewMenu->addAction(webPageAct);
286     viewMenu->addAction(copyPageAct);
287     viewMenu->addAction(copyLinkAct);
288     viewMenu->addSeparator();
289     viewMenu->addAction(compactViewAct);
290     viewMenu->addAction(fullscreenAct);
291
292     helpMenu = menuBar()->addMenu(tr("&Help"));
293     helpMenu->addAction(siteAct);
294     helpMenu->addAction(donateAct);
295     helpMenu->addAction(aboutAct);
296 }
297
298 void MainWindow::createToolBars() {
299
300     mainToolBar = new QToolBar(this);
301 #if QT_VERSION < 0x040600 || defined(Q_WS_MAC)
302     mainToolBar->setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
303 #else
304     mainToolBar->setToolButtonStyle(Qt::ToolButtonFollowStyle);
305 #endif
306     mainToolBar->setFloatable(false);
307     mainToolBar->setMovable(false);
308
309     QFont smallerFont;
310     smallerFont.setPointSize(smallerFont.pointSize()*.85);
311     QFontInfo fontInfo(smallerFont);
312     if (fontInfo.pixelSize() < 10) {
313         smallerFont.setPixelSize(10);
314     }
315     mainToolBar->setFont(smallerFont);
316
317 #ifdef Q_WS_MAC
318     mainToolBar->setIconSize(QSize(32, 32));
319 #endif
320
321     mainToolBar->addAction(stopAct);
322     mainToolBar->addAction(pauseAct);
323     mainToolBar->addAction(skipAct);
324     mainToolBar->addAction(fullscreenAct);
325
326     seekSlider = new Phonon::SeekSlider(this);
327     seekSlider->setIconVisible(false);
328     Spacer *seekSliderSpacer = new Spacer(mainToolBar, seekSlider);
329     seekSliderSpacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
330     mainToolBar->addWidget(seekSliderSpacer);
331
332     volumeSlider = new Phonon::VolumeSlider(this);
333     // qDebug() << volumeSlider->children();
334     // status tip for the volume slider
335     QSlider* volumeQSlider = volumeSlider->findChild<QSlider*>();
336     if (volumeQSlider)
337         volumeQSlider->setStatusTip(tr("Press %1 to raise the volume, %2 to lower it").arg(
338                 volumeUpAct->shortcut().toString(QKeySequence::NativeText), volumeDownAct->shortcut().toString(QKeySequence::NativeText)));
339     // status tip for the mute button
340     QToolButton* muteToolButton = volumeSlider->findChild<QToolButton*>();
341     if (muteToolButton)
342         muteToolButton->setStatusTip(volumeMuteAct->statusTip());
343     // this makes the volume slider smaller
344     volumeSlider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
345     mainToolBar->addWidget(new Spacer(mainToolBar, volumeSlider));
346
347     toolbarSearch->setStatusTip(searchFocusAct->statusTip());
348     mainToolBar->addWidget(new Spacer(mainToolBar, toolbarSearch));
349
350     addToolBar(mainToolBar);
351 }
352
353 void MainWindow::createStatusBar() {
354
355     // remove ugly borders on OSX
356     // also remove excessive spacing
357     statusBar()->setStyleSheet("::item{border:0 solid} QToolBar {padding:0;spacing:0;margin:0}");
358
359     currentTime = new QLabel(this);
360     statusBar()->addPermanentWidget(currentTime);
361
362     totalTime = new QLabel(this);
363     statusBar()->addPermanentWidget(totalTime);
364
365     QToolBar *toolBar = new QToolBar(this);
366     toolBar->setToolButtonStyle(Qt::ToolButtonTextOnly);
367     toolBar->addAction(The::globalActions()->value("definition"));
368     statusBar()->addPermanentWidget(toolBar);
369
370     statusBar()->show();
371 }
372
373 void MainWindow::readSettings() {
374     QSettings settings;
375     restoreGeometry(settings.value("geometry").toByteArray());
376     setDefinitionMode(settings.value("definition", VideoDefinition::getDefinitionNames().first()).toString());
377     audioOutput->setVolume(settings.value("volume", 1).toDouble());
378     audioOutput->setMuted(settings.value("volumeMute").toBool());
379 }
380
381 void MainWindow::writeSettings() {
382     // do not save geometry when in full screen
383     if (m_fullscreen)
384         return;
385     QSettings settings;
386     settings.setValue("geometry", saveGeometry());
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 void MainWindow::setDefinitionMode(QString definitionName) {
758     QAction *definitionAct = The::globalActions()->value("definition");
759     definitionAct->setText(definitionName);
760     definitionAct->setStatusTip(tr("Maximum video definition set to %1").arg(definitionAct->text())
761                                 + " (" +  definitionAct->shortcut().toString(QKeySequence::NativeText) + ")");
762     statusBar()->showMessage(definitionAct->statusTip());
763     QSettings settings;
764     settings.setValue("definition", definitionName);
765 }
766
767 void MainWindow::toggleDefinitionMode() {
768     QSettings settings;
769     QString currentDefinition = settings.value("definition").toString();
770     QStringList definitionNames = VideoDefinition::getDefinitionNames();
771     int currentIndex = definitionNames.indexOf(currentDefinition);
772     int nextIndex = 0;
773     if (currentIndex != definitionNames.size() - 1) {
774         nextIndex = currentIndex + 1;
775     }
776     QString nextDefinition = definitionNames.at(nextIndex);
777     setDefinitionMode(nextDefinition);
778 }
779
780 void MainWindow::showFullscreenToolbar(bool show) {
781     if (!m_fullscreen) return;
782
783     if (show) {
784         mainToolBar->show();
785     } else {
786         mainToolBar->hide();
787     }
788     mainToolBar->setEnabled(show);
789 }
790
791 void MainWindow::showFullscreenPlaylist(bool show) {
792     if (!m_fullscreen) return;
793     mediaView->setPlaylistVisible(show);
794 }
795
796 void MainWindow::clearRecentKeywords() {
797     QSettings settings;
798     settings.remove("recentKeywords");
799     searchView->updateRecentKeywords();
800     statusBar()->showMessage(tr("Your privacy is now safe"));
801 }