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