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