1 #include "MainWindow.h"
4 #include "iconloader/qticonloader.h"
6 #include "videodefinition.h"
8 #include "globalshortcuts.h"
10 #include "gnomeglobalshortcutbackend.h"
13 #include "local/mac/mac_startup.h"
15 #include "downloadmanager.h"
16 #include "youtubesuggest.h"
18 MainWindow::MainWindow() :
26 history = new QStack<QWidget*>();
27 views = new QStackedWidget(this);
28 setCentralWidget(views);
31 searchView = new SearchView(this);
32 connect(searchView, SIGNAL(search(SearchParams*)), this, SLOT(showMedia(SearchParams*)));
33 views->addWidget(searchView);
35 mediaView = new MediaView(this);
36 views->addWidget(mediaView);
38 toolbarSearch = new SearchLineEdit(this);
39 toolbarSearch->setMinimumWidth(toolbarSearch->fontInfo().pixelSize()*15);
40 toolbarSearch->setSuggester(new YouTubeSuggest(this));
41 connect(toolbarSearch, SIGNAL(search(const QString&)), this, SLOT(startToolbarSearch(const QString&)));
50 // mediaView->setSlider(slider);
51 mediaView->setMediaObject(mediaObject);
53 // remove that useless menu/toolbar context menu
54 this->setContextMenuPolicy(Qt::NoContextMenu);
56 // mediaView init stuff thats needs actions
57 mediaView->initialize();
59 // event filter to block ugly toolbar tooltips
60 qApp->installEventFilter(this);
62 // restore window position
65 // show the initial view
66 showWidget(searchView);
69 GlobalShortcuts &shortcuts = GlobalShortcuts::instance();
71 if (GnomeGlobalShortcutBackend::IsGsdAvailable())
72 shortcuts.setBackend(new GnomeGlobalShortcutBackend(&shortcuts));
77 connect(&shortcuts, SIGNAL(PlayPause()), pauseAct, SLOT(trigger()));
78 connect(&shortcuts, SIGNAL(Stop()), this, SLOT(stop()));
79 connect(&shortcuts, SIGNAL(Next()), skipAct, SLOT(trigger()));
81 connect(DownloadManager::instance(), SIGNAL(statusMessageChanged(QString)),
82 SLOT(updateDownloadMessage(QString)));
83 connect(DownloadManager::instance(), SIGNAL(finished()),
84 SLOT(downloadsFinished()));
87 MainWindow::~MainWindow() {
91 bool MainWindow::eventFilter(QObject *obj, QEvent *event) {
92 if (event->type() == QEvent::MouseMove && this->m_fullscreen) {
93 QMouseEvent *mouseEvent = static_cast<QMouseEvent*> (event);
94 int x = mouseEvent->pos().x();
95 int y = mouseEvent->pos().y();
97 if (y < 0 && (obj == this->mainToolBar || !(y <= 10-this->mainToolBar->height() && y >= 0-this->mainToolBar->height() )))
98 this->mainToolBar->setVisible(false);
100 this->mediaView->setPlaylistVisible(false);
103 if (event->type() == QEvent::ToolTip) {
107 // standard event processing
108 return QObject::eventFilter(obj, event);
111 void MainWindow::createActions() {
113 QMap<QString, QAction*> *actions = The::globalActions();
115 stopAct = new QAction(QtIconLoader::icon("media-playback-stop"), tr("&Stop"), this);
116 stopAct->setStatusTip(tr("Stop playback and go back to the search view"));
117 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
118 stopAct->setEnabled(false);
119 actions->insert("stop", stopAct);
120 connect(stopAct, SIGNAL(triggered()), this, SLOT(stop()));
122 skipAct = new QAction(QtIconLoader::icon("media-skip-forward"), tr("S&kip"), this);
123 skipAct->setStatusTip(tr("Skip to the next video"));
124 skipAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Right) << QKeySequence(Qt::Key_MediaNext));
125 skipAct->setEnabled(false);
126 actions->insert("skip", skipAct);
127 connect(skipAct, SIGNAL(triggered()), mediaView, SLOT(skip()));
129 pauseAct = new QAction(QtIconLoader::icon("media-playback-pause"), tr("&Pause"), this);
130 pauseAct->setStatusTip(tr("Pause playback"));
131 pauseAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Space) << QKeySequence(Qt::Key_MediaPlay));
132 pauseAct->setEnabled(false);
133 actions->insert("pause", pauseAct);
134 connect(pauseAct, SIGNAL(triggered()), mediaView, SLOT(pause()));
136 fullscreenAct = new QAction(QtIconLoader::icon("view-fullscreen"), tr("&Full Screen"), this);
137 fullscreenAct->setStatusTip(tr("Go full screen"));
138 fullscreenAct->setShortcut(QKeySequence(Qt::ALT + Qt::Key_Return));
139 fullscreenAct->setShortcutContext(Qt::ApplicationShortcut);
140 #if QT_VERSION >= 0x040600
141 fullscreenAct->setPriority(QAction::LowPriority);
143 actions->insert("fullscreen", fullscreenAct);
144 connect(fullscreenAct, SIGNAL(triggered()), this, SLOT(fullscreen()));
146 compactViewAct = new QAction(tr("&Compact mode"), this);
147 compactViewAct->setStatusTip(tr("Hide the playlist and the toolbar"));
148 compactViewAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return));
149 compactViewAct->setCheckable(true);
150 compactViewAct->setChecked(false);
151 compactViewAct->setEnabled(false);
152 actions->insert("compactView", compactViewAct);
153 connect(compactViewAct, SIGNAL(toggled(bool)), this, SLOT(compactView(bool)));
155 webPageAct = new QAction(tr("Open the &YouTube page"), this);
156 webPageAct->setStatusTip(tr("Go to the YouTube video page and pause playback"));
157 webPageAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Y));
158 webPageAct->setEnabled(false);
159 actions->insert("webpage", webPageAct);
160 connect(webPageAct, SIGNAL(triggered()), mediaView, SLOT(openWebPage()));
162 copyPageAct = new QAction(tr("Copy the YouTube &link"), this);
163 copyPageAct->setStatusTip(tr("Copy the current video YouTube link to the clipboard"));
164 copyPageAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L));
165 copyPageAct->setEnabled(false);
166 actions->insert("pagelink", copyPageAct);
167 connect(copyPageAct, SIGNAL(triggered()), mediaView, SLOT(copyWebPage()));
169 copyLinkAct = new QAction(tr("Copy the video stream &URL"), this);
170 copyLinkAct->setStatusTip(tr("Copy the current video stream URL to the clipboard"));
171 copyLinkAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U));
172 copyLinkAct->setEnabled(false);
173 actions->insert("videolink", copyLinkAct);
174 connect(copyLinkAct, SIGNAL(triggered()), mediaView, SLOT(copyVideoLink()));
176 removeAct = new QAction(tr("&Remove"), this);
177 removeAct->setStatusTip(tr("Remove the selected videos from the playlist"));
178 removeAct->setShortcuts(QList<QKeySequence>() << QKeySequence("Del") << QKeySequence("Backspace"));
179 removeAct->setEnabled(false);
180 actions->insert("remove", removeAct);
181 connect(removeAct, SIGNAL(triggered()), mediaView, SLOT(removeSelected()));
183 moveUpAct = new QAction(tr("Move &Up"), this);
184 moveUpAct->setStatusTip(tr("Move up the selected videos in the playlist"));
185 moveUpAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Up));
186 moveUpAct->setEnabled(false);
187 actions->insert("moveUp", moveUpAct);
188 connect(moveUpAct, SIGNAL(triggered()), mediaView, SLOT(moveUpSelected()));
190 moveDownAct = new QAction(tr("Move &Down"), this);
191 moveDownAct->setStatusTip(tr("Move down the selected videos in the playlist"));
192 moveDownAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Down));
193 moveDownAct->setEnabled(false);
194 actions->insert("moveDown", moveDownAct);
195 connect(moveDownAct, SIGNAL(triggered()), mediaView, SLOT(moveDownSelected()));
197 clearAct = new QAction(tr("&Clear recent searches"), this);
198 clearAct->setMenuRole(QAction::ApplicationSpecificRole);
199 clearAct->setShortcuts(QList<QKeySequence>()
200 << QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Delete)
201 << QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Backspace));
202 clearAct->setStatusTip(tr("Clear the search history. Cannot be undone."));
203 clearAct->setEnabled(true);
204 actions->insert("clearRecentKeywords", clearAct);
205 connect(clearAct, SIGNAL(triggered()), SLOT(clearRecentKeywords()));
207 quitAct = new QAction(tr("&Quit"), this);
208 quitAct->setMenuRole(QAction::QuitRole);
209 quitAct->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Q")) << QKeySequence(Qt::CTRL + Qt::Key_W));
210 quitAct->setStatusTip(tr("Bye"));
211 actions->insert("quit", quitAct);
212 connect(quitAct, SIGNAL(triggered()), this, SLOT(close()));
214 siteAct = new QAction(tr("&Website"), this);
215 siteAct->setShortcut(QKeySequence::HelpContents);
216 siteAct->setStatusTip(tr("%1 on the Web").arg(Constants::APP_NAME));
217 actions->insert("site", siteAct);
218 connect(siteAct, SIGNAL(triggered()), this, SLOT(visitSite()));
220 donateAct = new QAction(tr("Make a &donation"), this);
221 donateAct->setStatusTip(tr("Please support the continued development of %1").arg(Constants::APP_NAME));
222 actions->insert("donate", donateAct);
223 connect(donateAct, SIGNAL(triggered()), this, SLOT(donate()));
225 aboutAct = new QAction(tr("&About"), this);
226 aboutAct->setMenuRole(QAction::AboutRole);
227 aboutAct->setStatusTip(tr("Info about %1").arg(Constants::APP_NAME));
228 actions->insert("about", aboutAct);
229 connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
233 searchFocusAct = new QAction(this);
234 searchFocusAct->setShortcut(QKeySequence::Find);
235 searchFocusAct->setStatusTip(tr("Search"));
236 actions->insert("search", searchFocusAct);
237 connect(searchFocusAct, SIGNAL(triggered()), this, SLOT(searchFocus()));
238 addAction(searchFocusAct);
240 volumeUpAct = new QAction(this);
241 volumeUpAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Plus) << QKeySequence(Qt::Key_VolumeUp));
242 actions->insert("volume-up", volumeUpAct);
243 connect(volumeUpAct, SIGNAL(triggered()), this, SLOT(volumeUp()));
244 addAction(volumeUpAct);
246 volumeDownAct = new QAction(this);
247 volumeDownAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Minus) << QKeySequence(Qt::Key_VolumeDown));
248 actions->insert("volume-down", volumeDownAct);
249 connect(volumeDownAct, SIGNAL(triggered()), this, SLOT(volumeDown()));
250 addAction(volumeDownAct);
252 volumeMuteAct = new QAction(this);
253 volumeMuteAct->setIcon(QtIconLoader::icon("audio-volume-high"));
254 volumeMuteAct->setStatusTip(tr("Mute volume"));
255 volumeMuteAct->setShortcuts(QList<QKeySequence>()
256 << QKeySequence(tr("Ctrl+M"))
257 << QKeySequence(Qt::Key_VolumeMute));
258 actions->insert("volume-mute", volumeMuteAct);
259 connect(volumeMuteAct, SIGNAL(triggered()), SLOT(volumeMute()));
260 addAction(volumeMuteAct);
262 QAction *definitionAct = new QAction(this);
263 definitionAct->setIcon(QtIconLoader::icon("video-display"));
264 definitionAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_D));
266 QMenu *definitionMenu = new QMenu(this);
267 foreach (QString definition, VideoDefinition::getDefinitionNames()) {
268 definitionMenu->addAction(definition);
270 definitionAct->setMenu(definitionMenu);
272 actions->insert("definition", definitionAct);
273 connect(definitionAct, SIGNAL(triggered()), SLOT(toggleDefinitionMode()));
274 addAction(definitionAct);
279 action = new QAction(tr("&Autoplay"), this);
280 action->setStatusTip(tr("Automatically start playing videos"));
281 action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_P));
282 action->setCheckable(true);
283 connect(action, SIGNAL(toggled(bool)), SLOT(setAutoplay(bool)));
284 actions->insert("autoplay", action);
287 action = new QAction(tr("&Downloads"), this);
288 action->setStatusTip(tr("Show details about video downloads"));
289 action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_J));
290 action->setCheckable(true);
291 action->setIcon(QtIconLoader::icon("go-down"));
292 action->setVisible(false);
293 connect(action, SIGNAL(toggled(bool)), SLOT(toggleDownloads(bool)));
294 actions->insert("downloads", action);
296 action = new QAction(tr("&Download"), this);
297 action->setStatusTip(tr("Download the current video"));
298 action->setShortcut(QKeySequence::Save);
299 action->setIcon(QtIconLoader::icon("go-down"));
300 action->setEnabled(false);
301 #if QT_VERSION >= 0x040600
302 action->setPriority(QAction::LowPriority);
304 connect(action, SIGNAL(triggered()), mediaView, SLOT(downloadVideo()));
305 actions->insert("download", action);
307 // common action properties
308 foreach (QAction *action, actions->values()) {
310 // add actions to the MainWindow so that they work
311 // when the menu is hidden
315 // unexperienced users tend to keep keys pressed for a "long" time
316 action->setAutoRepeat(false);
318 // set to something more meaningful then the toolbar text
319 // HELP! how to remove tooltips altogether?!
320 if (!action->statusTip().isEmpty())
321 action->setToolTip(action->statusTip());
323 // show keyboard shortcuts in the status bar
324 if (!action->shortcut().isEmpty())
325 action->setStatusTip(action->statusTip() + " (" + action->shortcut().toString(QKeySequence::NativeText) + ")");
328 action->setIconVisibleInMenu(false);
334 void MainWindow::createMenus() {
336 QMap<QString, QMenu*> *menus = The::globalMenus();
338 fileMenu = menuBar()->addMenu(tr("&Application"));
339 // menus->insert("file", fileMenu);
340 fileMenu->addAction(clearAct);
342 fileMenu->addSeparator();
344 fileMenu->addAction(quitAct);
346 playlistMenu = menuBar()->addMenu(tr("&Playlist"));
347 menus->insert("playlist", playlistMenu);
348 playlistMenu->addAction(removeAct);
349 playlistMenu->addSeparator();
350 playlistMenu->addAction(moveUpAct);
351 playlistMenu->addAction(moveDownAct);
353 viewMenu = menuBar()->addMenu(tr("&Video"));
354 menus->insert("video", viewMenu);
355 viewMenu->addAction(stopAct);
356 viewMenu->addAction(pauseAct);
357 viewMenu->addAction(skipAct);
358 viewMenu->addSeparator();
359 viewMenu->addAction(The::globalActions()->value("download"));
360 viewMenu->addSeparator();
361 viewMenu->addAction(webPageAct);
362 viewMenu->addAction(copyPageAct);
363 viewMenu->addAction(copyLinkAct);
364 viewMenu->addSeparator();
365 viewMenu->addAction(compactViewAct);
366 viewMenu->addAction(fullscreenAct);
368 extern void qt_mac_set_dock_menu(QMenu *);
369 qt_mac_set_dock_menu(viewMenu);
372 helpMenu = menuBar()->addMenu(tr("&Help"));
373 helpMenu->addAction(siteAct);
374 #if !defined(APP_MAC) && !defined(APP_WIN)
375 helpMenu->addAction(donateAct);
377 helpMenu->addAction(aboutAct);
380 void MainWindow::createToolBars() {
382 setUnifiedTitleAndToolBarOnMac(true);
384 mainToolBar = new QToolBar(this);
385 #if QT_VERSION < 0x040600 | defined(APP_MAC)
386 mainToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
387 #elif defined(APP_WIN)
388 mainToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
389 mainToolBar->setStyleSheet(
391 "background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #fafcfd, stop:.5 #e6f0fa, stop:.51 #dde9f7, stop:1 #dde9f7);"
393 "border-bottom: 1px solid #a0afc3;"
396 mainToolBar->setToolButtonStyle(Qt::ToolButtonFollowStyle);
398 mainToolBar->setFloatable(false);
399 mainToolBar->setMovable(false);
401 #if defined(APP_MAC) | defined(APP_WIN)
402 mainToolBar->setIconSize(QSize(32, 32));
405 mainToolBar->addAction(stopAct);
406 mainToolBar->addAction(pauseAct);
407 mainToolBar->addAction(skipAct);
408 mainToolBar->addAction(fullscreenAct);
409 mainToolBar->addAction(The::globalActions()->value("download"));
411 mainToolBar->addWidget(new Spacer());
413 QFont smallerFont = FontUtils::small();
414 currentTime = new QLabel(mainToolBar);
415 currentTime->setFont(smallerFont);
416 mainToolBar->addWidget(currentTime);
418 mainToolBar->addWidget(new Spacer());
420 seekSlider = new Phonon::SeekSlider(this);
421 seekSlider->setIconVisible(false);
422 seekSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
423 mainToolBar->addWidget(seekSlider);
426 mainToolBar->addWidget(new Spacer());
427 slider = new QSlider(this);
428 slider->setOrientation(Qt::Horizontal);
429 slider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
430 mainToolBar->addWidget(slider);
433 mainToolBar->addWidget(new Spacer());
435 totalTime = new QLabel(mainToolBar);
436 totalTime->setFont(smallerFont);
437 mainToolBar->addWidget(totalTime);
439 mainToolBar->addWidget(new Spacer());
441 mainToolBar->addAction(volumeMuteAct);
443 volumeSlider = new Phonon::VolumeSlider(this);
444 volumeSlider->setMuteVisible(false);
445 // qDebug() << volumeSlider->children();
446 // status tip for the volume slider
447 QSlider* volumeQSlider = volumeSlider->findChild<QSlider*>();
449 volumeQSlider->setStatusTip(tr("Press %1 to raise the volume, %2 to lower it").arg(
450 volumeUpAct->shortcut().toString(QKeySequence::NativeText), volumeDownAct->shortcut().toString(QKeySequence::NativeText)));
451 // this makes the volume slider smaller
452 volumeSlider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
453 mainToolBar->addWidget(volumeSlider);
455 mainToolBar->addWidget(new Spacer());
457 toolbarSearch->setStatusTip(searchFocusAct->statusTip());
458 mainToolBar->addWidget(toolbarSearch);
460 mainToolBar->addWidget(new Spacer());
462 addToolBar(mainToolBar);
465 void MainWindow::createStatusBar() {
467 // remove ugly borders on OSX
468 // also remove excessive spacing
469 statusBar()->setStyleSheet("::item{border:0 solid} QToolBar {padding:0;spacing:0;margin:0;border:0}");
471 QToolBar *toolBar = new QToolBar(this);
472 toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
473 toolBar->setIconSize(QSize(16, 16));
474 toolBar->addAction(The::globalActions()->value("downloads"));
475 // toolBar->addAction(The::globalActions()->value("autoplay"));
476 toolBar->addAction(The::globalActions()->value("definition"));
477 statusBar()->addPermanentWidget(toolBar);
482 void MainWindow::readSettings() {
484 restoreGeometry(settings.value("geometry").toByteArray());
487 #ifdef QT_MAC_USE_COCOA
490 move(x(), y() + mainToolBar->height() + 8);
493 setDefinitionMode(settings.value("definition", VideoDefinition::getDefinitionNames().first()).toString());
494 audioOutput->setVolume(settings.value("volume", 1).toDouble());
495 audioOutput->setMuted(settings.value("volumeMute").toBool());
498 void MainWindow::writeSettings() {
502 // do not save geometry when in full screen
504 settings.setValue("geometry", saveGeometry());
507 settings.setValue("volume", audioOutput->volume());
508 settings.setValue("volumeMute", audioOutput->isMuted());
509 mediaView->saveSplitterState();
512 void MainWindow::goBack() {
513 if ( history->size() > 1 ) {
515 QWidget *widget = history->pop();
520 void MainWindow::showWidget ( QWidget* widget ) {
522 setUpdatesEnabled(false);
524 // call hide method on the current view
525 View* oldView = dynamic_cast<View *> (views->currentWidget());
527 oldView->disappear();
530 // call show method on the new view
531 View* newView = dynamic_cast<View *> (widget);
534 QMap<QString,QVariant> metadata = newView->metadata();
535 QString windowTitle = metadata.value("title").toString();
536 if (windowTitle.length())
537 windowTitle += " - ";
538 setWindowTitle(windowTitle + Constants::APP_NAME);
539 statusBar()->showMessage((metadata.value("description").toString()));
542 stopAct->setEnabled(widget == mediaView);
543 fullscreenAct->setEnabled(widget == mediaView);
544 compactViewAct->setEnabled(widget == mediaView);
545 webPageAct->setEnabled(widget == mediaView);
546 copyPageAct->setEnabled(widget == mediaView);
547 copyLinkAct->setEnabled(widget == mediaView);
548 aboutAct->setEnabled(widget != aboutView);
549 The::globalActions()->value("download")->setEnabled(widget == mediaView);
550 The::globalActions()->value("downloads")->setChecked(widget == downloadView);
552 // toolbar only for the mediaView
553 /* mainToolBar->setVisible(
554 (widget == mediaView && !compactViewAct->isChecked())
555 || widget == downloadView
558 setUpdatesEnabled(true);
560 QWidget *oldWidget = views->currentWidget();
561 views->setCurrentWidget(widget);
563 #if defined(APP_MAC) || defined(APP_WIN)
564 // crossfade only on OSX
565 // where we can be sure of video performance
566 fadeInWidget(oldWidget, widget);
569 history->push(widget);
572 void MainWindow::fadeInWidget(QWidget *oldWidget, QWidget *newWidget) {
573 if (faderWidget) faderWidget->close();
574 if (!oldWidget || !newWidget) {
575 // qDebug() << "no widgets";
578 faderWidget = new FaderWidget(newWidget);
579 faderWidget->start(QPixmap::grabWidget(oldWidget));
582 void MainWindow::about() {
584 aboutView = new AboutView(this);
585 views->addWidget(aboutView);
587 showWidget(aboutView);
590 void MainWindow::visitSite() {
591 QUrl url(Constants::WEBSITE);
592 statusBar()->showMessage(QString(tr("Opening %1").arg(url.toString())));
593 QDesktopServices::openUrl(url);
596 void MainWindow::donate() {
597 QUrl url(QString(Constants::WEBSITE) + "#donate");
598 statusBar()->showMessage(QString(tr("Opening %1").arg(url.toString())));
599 QDesktopServices::openUrl(url);
602 void MainWindow::quit() {
607 void MainWindow::closeEvent(QCloseEvent *event) {
608 if (DownloadManager::instance()->activeItems() > 0) {
610 msgBox.setIconPixmap(QPixmap(":/images/app.png").scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
611 msgBox.setText(tr("Do you want to exit %1 with a download in progress?").arg(Constants::APP_NAME));
612 msgBox.setInformativeText(tr("If you close %1 now, this download will be cancelled.").arg(Constants::APP_NAME));
613 msgBox.setModal(true);
615 msgBox.addButton(tr("Close and cancel download"), QMessageBox::RejectRole);
616 QPushButton *waitButton = msgBox.addButton(tr("Wait for download to finish"), QMessageBox::ActionRole);
620 if (msgBox.clickedButton() == waitButton) {
627 QWidget::closeEvent(event);
630 void MainWindow::showSearch() {
631 showWidget(searchView);
632 currentTime->clear();
636 void MainWindow::showMedia(SearchParams *searchParams) {
637 mediaView->search(searchParams);
638 showWidget(mediaView);
641 void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState */) {
643 // qDebug() << "Phonon state: " << newState;
647 case Phonon::ErrorState:
648 if (mediaObject->errorType() == Phonon::FatalError) {
649 statusBar()->showMessage(tr("Fatal error: %1").arg(mediaObject->errorString()));
651 statusBar()->showMessage(tr("Error: %1").arg(mediaObject->errorString()));
655 case Phonon::PlayingState:
656 pauseAct->setEnabled(true);
657 pauseAct->setIcon(QtIconLoader::icon("media-playback-pause"));
658 pauseAct->setText(tr("&Pause"));
659 pauseAct->setStatusTip(tr("Pause playback") + " (" + pauseAct->shortcut().toString(QKeySequence::NativeText) + ")");
660 skipAct->setEnabled(true);
661 // stopAct->setEnabled(true);
664 case Phonon::StoppedState:
665 pauseAct->setEnabled(false);
666 skipAct->setEnabled(false);
667 // stopAct->setEnabled(false);
670 case Phonon::PausedState:
671 skipAct->setEnabled(true);
672 pauseAct->setEnabled(true);
673 pauseAct->setIcon(QtIconLoader::icon("media-playback-start"));
674 pauseAct->setText(tr("&Play"));
675 pauseAct->setStatusTip(tr("Resume playback") + " (" + pauseAct->shortcut().toString(QKeySequence::NativeText) + ")");
676 // stopAct->setEnabled(true);
679 case Phonon::BufferingState:
680 case Phonon::LoadingState:
681 skipAct->setEnabled(true);
682 pauseAct->setEnabled(false);
683 currentTime->clear();
685 // stopAct->setEnabled(true);
693 void MainWindow::stop() {
698 void MainWindow::fullscreen() {
700 // No compact view action when in full screen
701 compactViewAct->setVisible(m_fullscreen);
702 compactViewAct->setChecked(false);
704 // Also no Youtube action since it opens a new window
705 webPageAct->setVisible(m_fullscreen);
706 copyPageAct->setVisible(m_fullscreen);
707 copyLinkAct->setVisible(m_fullscreen);
709 stopAct->setVisible(m_fullscreen);
711 // workaround: prevent focus on the search bar
712 // it steals the Space key needed for Play/Pause
713 toolbarSearch->setEnabled(m_fullscreen);
715 // Hide anything but the video
716 mediaView->setPlaylistVisible(m_fullscreen);
717 statusBar()->setVisible(m_fullscreen);
720 menuBar()->setVisible(m_fullscreen);
724 // make the actions work when video is fullscreen (on the Mac)
725 QMap<QString, QAction*> *actions = The::globalActions();
726 foreach (QAction *action, actions->values()) {
728 action->setShortcutContext(Qt::WindowShortcut);
730 action->setShortcutContext(Qt::ApplicationShortcut);
739 // use setShortcuts instead of setShortcut
740 // the latter seems not to work
741 fullscreenAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::ALT + Qt::Key_Return));
742 fullscreenAct->setText(tr("&Full Screen"));
743 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
746 setCentralWidget(views);
749 mediaView->setFocus();
752 if (m_maximized) showMaximized();
756 // Make sure the window has focus
763 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_MediaStop));
764 fullscreenAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::ALT + Qt::Key_Return));
765 fullscreenAct->setText(tr("Exit &Full Screen"));
766 m_maximized = isMaximized();
768 // save geometry now, if the user quits when in full screen
769 // geometry won't be saved
775 QTimer::singleShot(0, views, SLOT(showFullScreen()));
783 m_fullscreen = !m_fullscreen;
787 void MainWindow::compactView(bool enable) {
789 mediaView->setPlaylistVisible(!enable);
790 statusBar()->setVisible(!enable);
793 menuBar()->setVisible(!enable);
797 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_MediaStop));
798 compactViewAct->setShortcuts(
799 QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Return)
800 << QKeySequence(Qt::Key_Escape));
802 // ensure focus does not end up to the search box
803 // as it would steal the Space shortcut
804 mediaView->setFocus();
806 compactViewAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Return));
807 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
812 void MainWindow::searchFocus() {
813 QWidget *view = views->currentWidget();
814 if (view == mediaView) {
815 toolbarSearch->selectAll();
816 toolbarSearch->setFocus();
820 void MainWindow::initPhonon() {
821 // Phonon initialization
822 if (mediaObject) delete mediaObject;
823 if (audioOutput) delete audioOutput;
824 mediaObject = new Phonon::MediaObject(this);
825 mediaObject->setTickInterval(100);
826 connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
827 this, SLOT(stateChanged(Phonon::State, Phonon::State)));
828 connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64)));
829 connect(mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64)));
830 seekSlider->setMediaObject(mediaObject);
831 audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this);
832 connect(audioOutput, SIGNAL(volumeChanged(qreal)), this, SLOT(volumeChanged(qreal)));
833 connect(audioOutput, SIGNAL(mutedChanged(bool)), this, SLOT(volumeMutedChanged(bool)));
834 volumeSlider->setAudioOutput(audioOutput);
835 Phonon::createPath(mediaObject, audioOutput);
838 void MainWindow::tick(qint64 time) {
840 currentTime->clear();
844 currentTime->setText(formatTime(time));
847 const qint64 remainingTime = mediaObject->remainingTime();
848 currentTime->setStatusTip(tr("Remaining time: %1").arg(formatTime(remainingTime)));
851 slider->blockSignals(true);
852 slider->setValue(time/1000);
853 slider->blockSignals(false);
857 void MainWindow::totalTimeChanged(qint64 time) {
862 totalTime->setText(formatTime(time));
865 slider->blockSignals(true);
866 slider->setMaximum(time/1000);
867 slider->blockSignals(false);
872 QString MainWindow::formatTime(qint64 time) {
874 displayTime = displayTime.addMSecs(time);
876 // 60 * 60 * 1000 = 3600000
878 timeString = displayTime.toString("h:mm:ss");
880 timeString = displayTime.toString("m:ss");
884 void MainWindow::volumeUp() {
885 qreal newVolume = volumeSlider->audioOutput()->volume() + .1;
886 if (newVolume > volumeSlider->maximumVolume())
887 newVolume = volumeSlider->maximumVolume();
888 volumeSlider->audioOutput()->setVolume(newVolume);
891 void MainWindow::volumeDown() {
892 qreal newVolume = volumeSlider->audioOutput()->volume() - .1;
895 volumeSlider->audioOutput()->setVolume(newVolume);
898 void MainWindow::volumeMute() {
899 volumeSlider->audioOutput()->setMuted(!volumeSlider->audioOutput()->isMuted());
902 void MainWindow::volumeChanged(qreal newVolume) {
903 // automatically unmute when volume changes
904 if (volumeSlider->audioOutput()->isMuted())
905 volumeSlider->audioOutput()->setMuted(false);
906 statusBar()->showMessage(tr("Volume at %1%").arg(newVolume*100));
909 void MainWindow::volumeMutedChanged(bool muted) {
911 volumeMuteAct->setIcon(QtIconLoader::icon("audio-volume-muted"));
912 statusBar()->showMessage(tr("Volume is muted"));
914 volumeMuteAct->setIcon(QtIconLoader::icon("audio-volume-high"));
915 statusBar()->showMessage(tr("Volume is unmuted"));
919 void MainWindow::setDefinitionMode(QString definitionName) {
920 QAction *definitionAct = The::globalActions()->value("definition");
921 definitionAct->setText(definitionName);
922 definitionAct->setStatusTip(tr("Maximum video definition set to %1").arg(definitionAct->text())
923 + " (" + definitionAct->shortcut().toString(QKeySequence::NativeText) + ")");
924 statusBar()->showMessage(definitionAct->statusTip());
926 settings.setValue("definition", definitionName);
929 void MainWindow::toggleDefinitionMode() {
931 QString currentDefinition = settings.value("definition").toString();
932 QStringList definitionNames = VideoDefinition::getDefinitionNames();
933 int currentIndex = definitionNames.indexOf(currentDefinition);
935 if (currentIndex != definitionNames.size() - 1) {
936 nextIndex = currentIndex + 1;
938 QString nextDefinition = definitionNames.at(nextIndex);
939 setDefinitionMode(nextDefinition);
942 void MainWindow::showFullscreenToolbar(bool show) {
943 if (!m_fullscreen) return;
944 mainToolBar->setVisible(show);
947 void MainWindow::showFullscreenPlaylist(bool show) {
948 if (!m_fullscreen) return;
949 mediaView->setPlaylistVisible(show);
952 void MainWindow::clearRecentKeywords() {
954 settings.remove("recentKeywords");
955 settings.remove("recentChannels");
956 searchView->updateRecentKeywords();
957 searchView->updateRecentChannels();
958 statusBar()->showMessage(tr("Your privacy is now safe"));
962 void MainWindow::setAutoplay(bool enabled) {
964 settings.setValue("autoplay", QVariant::fromValue(enabled));
968 void MainWindow::updateDownloadMessage(QString message) {
969 The::globalActions()->value("downloads")->setText(message);
972 void MainWindow::downloadsFinished() {
973 The::globalActions()->value("downloads")->setText(tr("&Downloads"));
974 statusBar()->showMessage(tr("Downloads complete"));
977 void MainWindow::toggleDownloads(bool show) {
980 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_MediaStop));
981 The::globalActions()->value("downloads")->setShortcuts(
982 QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_J)
983 << QKeySequence(Qt::Key_Escape));
985 The::globalActions()->value("downloads")->setShortcuts(
986 QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_J));
987 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
991 downloadView = new DownloadView(this);
992 views->addWidget(downloadView);
994 if (show) showWidget(downloadView);
998 void MainWindow::startToolbarSearch(QString query) {
1000 query = query.trimmed();
1002 // check for empty query
1003 if (query.length() == 0) {
1007 SearchParams *searchParams = new SearchParams();
1008 searchParams->setKeywords(query);
1011 showMedia(searchParams);