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