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::ToolTip) {
96 // standard event processing
97 return QObject::eventFilter(obj, event);
101 void MainWindow::createActions() {
103 QMap<QString, QAction*> *actions = The::globalActions();
105 stopAct = new QAction(QtIconLoader::icon("media-playback-stop"), tr("&Stop"), this);
106 stopAct->setStatusTip(tr("Stop playback and go back to the search view"));
107 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
108 stopAct->setEnabled(false);
109 actions->insert("stop", stopAct);
110 connect(stopAct, SIGNAL(triggered()), this, SLOT(stop()));
112 skipAct = new QAction(QtIconLoader::icon("media-skip-forward"), tr("S&kip"), this);
113 skipAct->setStatusTip(tr("Skip to the next video"));
114 skipAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Right) << QKeySequence(Qt::Key_MediaNext));
115 skipAct->setEnabled(false);
116 actions->insert("skip", skipAct);
117 connect(skipAct, SIGNAL(triggered()), mediaView, SLOT(skip()));
119 pauseAct = new QAction(QtIconLoader::icon("media-playback-pause"), tr("&Pause"), this);
120 pauseAct->setStatusTip(tr("Pause playback"));
121 pauseAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Space) << QKeySequence(Qt::Key_MediaPlay));
122 pauseAct->setEnabled(false);
123 actions->insert("pause", pauseAct);
124 connect(pauseAct, SIGNAL(triggered()), mediaView, SLOT(pause()));
126 fullscreenAct = new QAction(QtIconLoader::icon("view-fullscreen"), tr("&Full Screen"), this);
127 fullscreenAct->setStatusTip(tr("Go full screen"));
128 fullscreenAct->setShortcut(QKeySequence(Qt::ALT + Qt::Key_Return));
129 fullscreenAct->setShortcutContext(Qt::ApplicationShortcut);
130 #if QT_VERSION >= 0x040600
131 fullscreenAct->setPriority(QAction::LowPriority);
133 actions->insert("fullscreen", fullscreenAct);
134 connect(fullscreenAct, SIGNAL(triggered()), this, SLOT(fullscreen()));
136 compactViewAct = new QAction(tr("&Compact mode"), this);
137 compactViewAct->setStatusTip(tr("Hide the playlist and the toolbar"));
138 compactViewAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Return));
139 compactViewAct->setCheckable(true);
140 compactViewAct->setChecked(false);
141 compactViewAct->setEnabled(false);
142 actions->insert("compactView", compactViewAct);
143 connect(compactViewAct, SIGNAL(toggled(bool)), this, SLOT(compactView(bool)));
145 webPageAct = new QAction(tr("Open the &YouTube page"), this);
146 webPageAct->setStatusTip(tr("Go to the YouTube video page and pause playback"));
147 webPageAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Y));
148 webPageAct->setEnabled(false);
149 actions->insert("webpage", webPageAct);
150 connect(webPageAct, SIGNAL(triggered()), mediaView, SLOT(openWebPage()));
152 copyPageAct = new QAction(tr("Copy the YouTube &link"), this);
153 copyPageAct->setStatusTip(tr("Copy the current video YouTube link to the clipboard"));
154 copyPageAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_L));
155 copyPageAct->setEnabled(false);
156 actions->insert("pagelink", copyPageAct);
157 connect(copyPageAct, SIGNAL(triggered()), mediaView, SLOT(copyWebPage()));
159 copyLinkAct = new QAction(tr("Copy the video stream &URL"), this);
160 copyLinkAct->setStatusTip(tr("Copy the current video stream URL to the clipboard"));
161 copyLinkAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_U));
162 copyLinkAct->setEnabled(false);
163 actions->insert("videolink", copyLinkAct);
164 connect(copyLinkAct, SIGNAL(triggered()), mediaView, SLOT(copyVideoLink()));
166 removeAct = new QAction(tr("&Remove"), this);
167 removeAct->setStatusTip(tr("Remove the selected videos from the playlist"));
168 removeAct->setShortcuts(QList<QKeySequence>() << QKeySequence("Del") << QKeySequence("Backspace"));
169 removeAct->setEnabled(false);
170 actions->insert("remove", removeAct);
171 connect(removeAct, SIGNAL(triggered()), mediaView, SLOT(removeSelected()));
173 moveUpAct = new QAction(tr("Move &Up"), this);
174 moveUpAct->setStatusTip(tr("Move up the selected videos in the playlist"));
175 moveUpAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Up));
176 moveUpAct->setEnabled(false);
177 actions->insert("moveUp", moveUpAct);
178 connect(moveUpAct, SIGNAL(triggered()), mediaView, SLOT(moveUpSelected()));
180 moveDownAct = new QAction(tr("Move &Down"), this);
181 moveDownAct->setStatusTip(tr("Move down the selected videos in the playlist"));
182 moveDownAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Down));
183 moveDownAct->setEnabled(false);
184 actions->insert("moveDown", moveDownAct);
185 connect(moveDownAct, SIGNAL(triggered()), mediaView, SLOT(moveDownSelected()));
187 clearAct = new QAction(tr("&Clear recent keywords"), this);
188 clearAct->setMenuRole(QAction::ApplicationSpecificRole);
189 clearAct->setShortcuts(QList<QKeySequence>()
190 << QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Delete)
191 << QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Backspace));
192 clearAct->setStatusTip(tr("Clear the search history. Cannot be undone."));
193 clearAct->setEnabled(true);
194 actions->insert("clearRecentKeywords", clearAct);
195 connect(clearAct, SIGNAL(triggered()), SLOT(clearRecentKeywords()));
197 quitAct = new QAction(tr("&Quit"), this);
198 quitAct->setMenuRole(QAction::QuitRole);
199 quitAct->setShortcuts(QList<QKeySequence>() << QKeySequence(tr("Ctrl+Q")) << QKeySequence(Qt::CTRL + Qt::Key_W));
200 quitAct->setStatusTip(tr("Bye"));
201 actions->insert("quit", quitAct);
202 connect(quitAct, SIGNAL(triggered()), this, SLOT(close()));
204 siteAct = new QAction(tr("&Website"), this);
205 siteAct->setShortcut(QKeySequence::HelpContents);
206 siteAct->setStatusTip(tr("%1 on the Web").arg(Constants::APP_NAME));
207 actions->insert("site", siteAct);
208 connect(siteAct, SIGNAL(triggered()), this, SLOT(visitSite()));
210 donateAct = new QAction(tr("Make a &donation"), this);
211 donateAct->setStatusTip(tr("Please support the continued development of %1").arg(Constants::APP_NAME));
212 actions->insert("donate", donateAct);
213 connect(donateAct, SIGNAL(triggered()), this, SLOT(donate()));
215 aboutAct = new QAction(tr("&About"), this);
216 aboutAct->setMenuRole(QAction::AboutRole);
217 aboutAct->setStatusTip(tr("Info about %1").arg(Constants::APP_NAME));
218 actions->insert("about", aboutAct);
219 connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
223 searchFocusAct = new QAction(this);
224 searchFocusAct->setShortcut(QKeySequence::Find);
225 searchFocusAct->setStatusTip(tr("Search"));
226 actions->insert("search", searchFocusAct);
227 connect(searchFocusAct, SIGNAL(triggered()), this, SLOT(searchFocus()));
228 addAction(searchFocusAct);
230 volumeUpAct = new QAction(this);
231 volumeUpAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Plus) << QKeySequence(Qt::Key_VolumeUp));
232 actions->insert("volume-up", volumeUpAct);
233 connect(volumeUpAct, SIGNAL(triggered()), this, SLOT(volumeUp()));
234 addAction(volumeUpAct);
236 volumeDownAct = new QAction(this);
237 volumeDownAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Minus) << QKeySequence(Qt::Key_VolumeDown));
238 actions->insert("volume-down", volumeDownAct);
239 connect(volumeDownAct, SIGNAL(triggered()), this, SLOT(volumeDown()));
240 addAction(volumeDownAct);
242 volumeMuteAct = new QAction(this);
243 volumeMuteAct->setIcon(QtIconLoader::icon("audio-volume-high"));
244 volumeMuteAct->setStatusTip(tr("Mute volume"));
245 volumeMuteAct->setShortcuts(QList<QKeySequence>()
246 << QKeySequence(tr("Ctrl+M"))
247 << QKeySequence(Qt::Key_VolumeMute));
248 actions->insert("volume-mute", volumeMuteAct);
249 connect(volumeMuteAct, SIGNAL(triggered()), SLOT(volumeMute()));
250 addAction(volumeMuteAct);
252 QAction *definitionAct = new QAction(this);
253 definitionAct->setIcon(QtIconLoader::icon("video-display"));
254 definitionAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_D));
256 QMenu *definitionMenu = new QMenu(this);
257 foreach (QString definition, VideoDefinition::getDefinitionNames()) {
258 definitionMenu->addAction(definition);
260 definitionAct->setMenu(definitionMenu);
262 actions->insert("definition", definitionAct);
263 connect(definitionAct, SIGNAL(triggered()), SLOT(toggleDefinitionMode()));
264 addAction(definitionAct);
269 action = new QAction(tr("&Autoplay"), this);
270 action->setStatusTip(tr("Automatically start playing videos"));
271 action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_P));
272 action->setCheckable(true);
273 connect(action, SIGNAL(toggled(bool)), SLOT(setAutoplay(bool)));
274 actions->insert("autoplay", action);
277 action = new QAction(tr("&Downloads"), this);
278 action->setStatusTip(tr("Show details about video downloads"));
279 action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_J));
280 action->setCheckable(true);
281 action->setIcon(QtIconLoader::icon("go-down"));
282 action->setVisible(false);
283 connect(action, SIGNAL(toggled(bool)), SLOT(toggleDownloads(bool)));
284 actions->insert("downloads", action);
286 action = new QAction(tr("&Download"), this);
287 action->setStatusTip(tr("Download the current video"));
288 action->setShortcut(QKeySequence::Save);
289 action->setIcon(QtIconLoader::icon("go-down"));
290 action->setEnabled(false);
291 #if QT_VERSION >= 0x040600
292 action->setPriority(QAction::LowPriority);
294 connect(action, SIGNAL(triggered()), mediaView, SLOT(downloadVideo()));
295 actions->insert("download", action);
297 // common action properties
298 foreach (QAction *action, actions->values()) {
300 // add actions to the MainWindow so that they work
301 // when the menu is hidden
305 // unexperienced users tend to keep keys pressed for a "long" time
306 action->setAutoRepeat(false);
308 // set to something more meaningful then the toolbar text
309 // HELP! how to remove tooltips altogether?!
310 if (!action->statusTip().isEmpty())
311 action->setToolTip(action->statusTip());
313 // show keyboard shortcuts in the status bar
314 if (!action->shortcut().isEmpty())
315 action->setStatusTip(action->statusTip() + " (" + action->shortcut().toString(QKeySequence::NativeText) + ")");
318 action->setIconVisibleInMenu(false);
324 void MainWindow::createMenus() {
326 QMap<QString, QMenu*> *menus = The::globalMenus();
328 fileMenu = menuBar()->addMenu(tr("&Application"));
329 // menus->insert("file", fileMenu);
330 fileMenu->addAction(clearAct);
332 fileMenu->addSeparator();
334 fileMenu->addAction(quitAct);
336 playlistMenu = menuBar()->addMenu(tr("&Playlist"));
337 menus->insert("playlist", playlistMenu);
338 playlistMenu->addAction(removeAct);
339 playlistMenu->addSeparator();
340 playlistMenu->addAction(moveUpAct);
341 playlistMenu->addAction(moveDownAct);
343 viewMenu = menuBar()->addMenu(tr("&Video"));
344 menus->insert("video", viewMenu);
345 viewMenu->addAction(stopAct);
346 viewMenu->addAction(pauseAct);
347 viewMenu->addAction(skipAct);
348 viewMenu->addSeparator();
349 viewMenu->addAction(The::globalActions()->value("download"));
350 viewMenu->addSeparator();
351 viewMenu->addAction(webPageAct);
352 viewMenu->addAction(copyPageAct);
353 viewMenu->addAction(copyLinkAct);
354 viewMenu->addSeparator();
355 viewMenu->addAction(compactViewAct);
356 viewMenu->addAction(fullscreenAct);
358 extern void qt_mac_set_dock_menu(QMenu *);
359 qt_mac_set_dock_menu(viewMenu);
362 helpMenu = menuBar()->addMenu(tr("&Help"));
363 helpMenu->addAction(siteAct);
364 #if !defined(APP_MAC) && !defined(APP_WIN)
365 helpMenu->addAction(donateAct);
367 helpMenu->addAction(aboutAct);
370 void MainWindow::createToolBars() {
372 setUnifiedTitleAndToolBarOnMac(true);
374 mainToolBar = new QToolBar(this);
375 #if QT_VERSION < 0x040600 | defined(APP_MAC)
376 mainToolBar->setToolButtonStyle(Qt::ToolButtonIconOnly);
377 #elif defined(APP_WIN)
378 mainToolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
379 mainToolBar->setStyleSheet(
381 "background: qlineargradient(x1:0, y1:0, x2:0, y2:1, stop:0 #fafcfd, stop:.5 #e6f0fa, stop:.51 #dde9f7, stop:1 #dde9f7);"
383 "border-bottom: 1px solid #a0afc3;"
386 mainToolBar->setToolButtonStyle(Qt::ToolButtonFollowStyle);
388 mainToolBar->setFloatable(false);
389 mainToolBar->setMovable(false);
391 #if defined(APP_MAC) | defined(APP_WIN)
392 mainToolBar->setIconSize(QSize(32, 32));
395 mainToolBar->addAction(stopAct);
396 mainToolBar->addAction(pauseAct);
397 mainToolBar->addAction(skipAct);
398 mainToolBar->addAction(fullscreenAct);
399 mainToolBar->addAction(The::globalActions()->value("download"));
401 mainToolBar->addWidget(new Spacer());
403 QFont smallerFont = FontUtils::small();
404 currentTime = new QLabel(mainToolBar);
405 currentTime->setFont(smallerFont);
406 mainToolBar->addWidget(currentTime);
408 mainToolBar->addWidget(new Spacer());
410 seekSlider = new Phonon::SeekSlider(this);
411 seekSlider->setIconVisible(false);
412 seekSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
413 mainToolBar->addWidget(seekSlider);
416 mainToolBar->addWidget(new Spacer());
417 slider = new QSlider(this);
418 slider->setOrientation(Qt::Horizontal);
419 slider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
420 mainToolBar->addWidget(slider);
423 mainToolBar->addWidget(new Spacer());
425 totalTime = new QLabel(mainToolBar);
426 totalTime->setFont(smallerFont);
427 mainToolBar->addWidget(totalTime);
429 mainToolBar->addWidget(new Spacer());
431 mainToolBar->addAction(volumeMuteAct);
433 volumeSlider = new Phonon::VolumeSlider(this);
434 volumeSlider->setMuteVisible(false);
435 // qDebug() << volumeSlider->children();
436 // status tip for the volume slider
437 QSlider* volumeQSlider = volumeSlider->findChild<QSlider*>();
439 volumeQSlider->setStatusTip(tr("Press %1 to raise the volume, %2 to lower it").arg(
440 volumeUpAct->shortcut().toString(QKeySequence::NativeText), volumeDownAct->shortcut().toString(QKeySequence::NativeText)));
441 // this makes the volume slider smaller
442 volumeSlider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
443 mainToolBar->addWidget(volumeSlider);
445 mainToolBar->addWidget(new Spacer());
447 toolbarSearch->setStatusTip(searchFocusAct->statusTip());
448 mainToolBar->addWidget(toolbarSearch);
450 mainToolBar->addWidget(new Spacer());
452 addToolBar(mainToolBar);
455 void MainWindow::createStatusBar() {
457 // remove ugly borders on OSX
458 // also remove excessive spacing
459 statusBar()->setStyleSheet("::item{border:0 solid} QToolBar {padding:0;spacing:0;margin:0;border:0}");
461 QToolBar *toolBar = new QToolBar(this);
462 toolBar->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
463 toolBar->setIconSize(QSize(16, 16));
464 toolBar->addAction(The::globalActions()->value("downloads"));
465 // toolBar->addAction(The::globalActions()->value("autoplay"));
466 toolBar->addAction(The::globalActions()->value("definition"));
467 statusBar()->addPermanentWidget(toolBar);
472 void MainWindow::readSettings() {
474 restoreGeometry(settings.value("geometry").toByteArray());
477 move(x(), y() + mainToolBar->height() + 8);
479 setDefinitionMode(settings.value("definition", VideoDefinition::getDefinitionNames().first()).toString());
480 audioOutput->setVolume(settings.value("volume", 1).toDouble());
481 audioOutput->setMuted(settings.value("volumeMute").toBool());
484 void MainWindow::writeSettings() {
488 // do not save geometry when in full screen
490 settings.setValue("geometry", saveGeometry());
493 settings.setValue("volume", audioOutput->volume());
494 settings.setValue("volumeMute", audioOutput->isMuted());
495 mediaView->saveSplitterState();
498 void MainWindow::goBack() {
499 if ( history->size() > 1 ) {
501 QWidget *widget = history->pop();
506 void MainWindow::showWidget ( QWidget* widget ) {
508 setUpdatesEnabled(false);
510 // call hide method on the current view
511 View* oldView = dynamic_cast<View *> (views->currentWidget());
513 oldView->disappear();
516 // call show method on the new view
517 View* newView = dynamic_cast<View *> (widget);
520 QMap<QString,QVariant> metadata = newView->metadata();
521 QString windowTitle = metadata.value("title").toString();
522 if (windowTitle.length())
523 windowTitle += " - ";
524 setWindowTitle(windowTitle + Constants::APP_NAME);
525 statusBar()->showMessage((metadata.value("description").toString()));
528 stopAct->setEnabled(widget == mediaView);
529 fullscreenAct->setEnabled(widget == mediaView);
530 compactViewAct->setEnabled(widget == mediaView);
531 webPageAct->setEnabled(widget == mediaView);
532 copyPageAct->setEnabled(widget == mediaView);
533 copyLinkAct->setEnabled(widget == mediaView);
534 aboutAct->setEnabled(widget != aboutView);
535 The::globalActions()->value("download")->setEnabled(widget == mediaView);
536 The::globalActions()->value("downloads")->setChecked(widget == downloadView);
538 // toolbar only for the mediaView
539 /* mainToolBar->setVisible(
540 (widget == mediaView && !compactViewAct->isChecked())
541 || widget == downloadView
544 setUpdatesEnabled(true);
546 QWidget *oldWidget = views->currentWidget();
547 views->setCurrentWidget(widget);
550 // crossfade only on OSX
551 // where we can be sure of video performance
552 fadeInWidget(oldWidget, widget);
555 history->push(widget);
558 void MainWindow::fadeInWidget(QWidget *oldWidget, QWidget *newWidget) {
559 if (faderWidget) faderWidget->close();
560 if (!oldWidget || !newWidget) {
561 // qDebug() << "no widgets";
564 faderWidget = new FaderWidget(newWidget);
565 faderWidget->start(QPixmap::grabWidget(oldWidget));
568 void MainWindow::about() {
570 aboutView = new AboutView(this);
571 views->addWidget(aboutView);
573 showWidget(aboutView);
576 void MainWindow::visitSite() {
577 QUrl url(Constants::WEBSITE);
578 statusBar()->showMessage(QString(tr("Opening %1").arg(url.toString())));
579 QDesktopServices::openUrl(url);
582 void MainWindow::donate() {
583 QUrl url(QString(Constants::WEBSITE) + "#donate");
584 statusBar()->showMessage(QString(tr("Opening %1").arg(url.toString())));
585 QDesktopServices::openUrl(url);
588 void MainWindow::quit() {
593 void MainWindow::closeEvent(QCloseEvent *event) {
594 if (DownloadManager::instance()->activeItems() > 0) {
596 msgBox.setIconPixmap(QPixmap(":/images/app.png").scaled(64, 64, Qt::KeepAspectRatio, Qt::SmoothTransformation));
597 msgBox.setText(tr("Do you want to exit %1 with a download in progress?").arg(Constants::APP_NAME));
598 msgBox.setInformativeText(tr("If you close %1 now, this download will be cancelled.").arg(Constants::APP_NAME));
599 msgBox.setModal(true);
601 msgBox.addButton(tr("Close and cancel download"), QMessageBox::RejectRole);
602 QPushButton *waitButton = msgBox.addButton(tr("Wait for download to finish"), QMessageBox::ActionRole);
606 if (msgBox.clickedButton() == waitButton) {
613 QWidget::closeEvent(event);
616 void MainWindow::showSearch() {
617 showWidget(searchView);
618 currentTime->clear();
622 void MainWindow::showMedia(SearchParams *searchParams) {
623 mediaView->search(searchParams);
624 showWidget(mediaView);
627 void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState */) {
629 // qDebug() << "Phonon state: " << newState;
633 case Phonon::ErrorState:
634 if (mediaObject->errorType() == Phonon::FatalError) {
635 statusBar()->showMessage(tr("Fatal error: %1").arg(mediaObject->errorString()));
637 statusBar()->showMessage(tr("Error: %1").arg(mediaObject->errorString()));
641 case Phonon::PlayingState:
642 pauseAct->setEnabled(true);
643 pauseAct->setIcon(QtIconLoader::icon("media-playback-pause"));
644 pauseAct->setText(tr("&Pause"));
645 pauseAct->setStatusTip(tr("Pause playback") + " (" + pauseAct->shortcut().toString(QKeySequence::NativeText) + ")");
646 skipAct->setEnabled(true);
647 // stopAct->setEnabled(true);
650 case Phonon::StoppedState:
651 pauseAct->setEnabled(false);
652 skipAct->setEnabled(false);
653 // stopAct->setEnabled(false);
656 case Phonon::PausedState:
657 skipAct->setEnabled(true);
658 pauseAct->setEnabled(true);
659 pauseAct->setIcon(QtIconLoader::icon("media-playback-start"));
660 pauseAct->setText(tr("&Play"));
661 pauseAct->setStatusTip(tr("Resume playback") + " (" + pauseAct->shortcut().toString(QKeySequence::NativeText) + ")");
662 // stopAct->setEnabled(true);
665 case Phonon::BufferingState:
666 case Phonon::LoadingState:
667 skipAct->setEnabled(true);
668 pauseAct->setEnabled(false);
669 currentTime->clear();
671 // stopAct->setEnabled(true);
679 void MainWindow::stop() {
684 void MainWindow::fullscreen() {
686 // No compact view action when in full screen
687 compactViewAct->setVisible(m_fullscreen);
688 compactViewAct->setChecked(false);
690 // Also no Youtube action since it opens a new window
691 webPageAct->setVisible(m_fullscreen);
692 copyPageAct->setVisible(m_fullscreen);
693 copyLinkAct->setVisible(m_fullscreen);
695 stopAct->setVisible(m_fullscreen);
697 // workaround: prevent focus on the search bar
698 // it steals the Space key needed for Play/Pause
699 toolbarSearch->setEnabled(m_fullscreen);
701 // Hide anything but the video
702 mediaView->setPlaylistVisible(m_fullscreen);
703 statusBar()->setVisible(m_fullscreen);
706 menuBar()->setVisible(m_fullscreen);
710 // make the actions work when video is fullscreen (on the Mac)
711 QMap<QString, QAction*> *actions = The::globalActions();
712 foreach (QAction *action, actions->values()) {
714 action->setShortcutContext(Qt::WindowShortcut);
716 action->setShortcutContext(Qt::ApplicationShortcut);
725 // use setShortcuts instead of setShortcut
726 // the latter seems not to work
727 fullscreenAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::ALT + Qt::Key_Return));
728 fullscreenAct->setText(tr("&Full Screen"));
729 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
732 setCentralWidget(views);
735 mediaView->setFocus();
738 if (m_maximized) showMaximized();
742 // Make sure the window has focus
749 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_MediaStop));
750 fullscreenAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::ALT + Qt::Key_Return));
751 fullscreenAct->setText(tr("Exit &Full Screen"));
752 m_maximized = isMaximized();
754 // save geometry now, if the user quits when in full screen
755 // geometry won't be saved
761 QTimer::singleShot(0, views, SLOT(showFullScreen()));
769 m_fullscreen = !m_fullscreen;
773 void MainWindow::compactView(bool enable) {
775 mediaView->setPlaylistVisible(!enable);
776 statusBar()->setVisible(!enable);
779 menuBar()->setVisible(!enable);
783 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_MediaStop));
784 compactViewAct->setShortcuts(
785 QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Return)
786 << QKeySequence(Qt::Key_Escape));
788 // ensure focus does not end up to the search box
789 // as it would steal the Space shortcut
790 mediaView->setFocus();
792 compactViewAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_Return));
793 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
798 void MainWindow::searchFocus() {
799 QWidget *view = views->currentWidget();
800 if (view == mediaView) {
801 toolbarSearch->selectAll();
802 toolbarSearch->setFocus();
806 void MainWindow::initPhonon() {
807 // Phonon initialization
808 if (mediaObject) delete mediaObject;
809 if (audioOutput) delete audioOutput;
810 mediaObject = new Phonon::MediaObject(this);
811 mediaObject->setTickInterval(100);
812 connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
813 this, SLOT(stateChanged(Phonon::State, Phonon::State)));
814 connect(mediaObject, SIGNAL(tick(qint64)), this, SLOT(tick(qint64)));
815 connect(mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64)));
816 seekSlider->setMediaObject(mediaObject);
817 audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this);
818 connect(audioOutput, SIGNAL(volumeChanged(qreal)), this, SLOT(volumeChanged(qreal)));
819 connect(audioOutput, SIGNAL(mutedChanged(bool)), this, SLOT(volumeMutedChanged(bool)));
820 volumeSlider->setAudioOutput(audioOutput);
821 Phonon::createPath(mediaObject, audioOutput);
824 void MainWindow::tick(qint64 time) {
826 currentTime->clear();
830 currentTime->setText(formatTime(time));
833 const qint64 remainingTime = mediaObject->remainingTime();
834 currentTime->setStatusTip(tr("Remaining time: %1").arg(formatTime(remainingTime)));
837 slider->blockSignals(true);
838 slider->setValue(time/1000);
839 slider->blockSignals(false);
843 void MainWindow::totalTimeChanged(qint64 time) {
848 totalTime->setText(formatTime(time));
851 slider->blockSignals(true);
852 slider->setMaximum(time/1000);
853 slider->blockSignals(false);
858 QString MainWindow::formatTime(qint64 time) {
860 displayTime = displayTime.addMSecs(time);
862 // 60 * 60 * 1000 = 3600000
864 timeString = displayTime.toString("h:mm:ss");
866 timeString = displayTime.toString("m:ss");
870 void MainWindow::volumeUp() {
871 qreal newVolume = volumeSlider->audioOutput()->volume() + .1;
872 if (newVolume > volumeSlider->maximumVolume())
873 newVolume = volumeSlider->maximumVolume();
874 volumeSlider->audioOutput()->setVolume(newVolume);
877 void MainWindow::volumeDown() {
878 qreal newVolume = volumeSlider->audioOutput()->volume() - .1;
881 volumeSlider->audioOutput()->setVolume(newVolume);
884 void MainWindow::volumeMute() {
885 volumeSlider->audioOutput()->setMuted(!volumeSlider->audioOutput()->isMuted());
888 void MainWindow::volumeChanged(qreal newVolume) {
889 // automatically unmute when volume changes
890 if (volumeSlider->audioOutput()->isMuted())
891 volumeSlider->audioOutput()->setMuted(false);
892 statusBar()->showMessage(tr("Volume at %1%").arg(newVolume*100));
895 void MainWindow::volumeMutedChanged(bool muted) {
897 volumeMuteAct->setIcon(QtIconLoader::icon("audio-volume-muted"));
898 statusBar()->showMessage(tr("Volume is muted"));
900 volumeMuteAct->setIcon(QtIconLoader::icon("audio-volume-high"));
901 statusBar()->showMessage(tr("Volume is unmuted"));
905 void MainWindow::setDefinitionMode(QString definitionName) {
906 QAction *definitionAct = The::globalActions()->value("definition");
907 definitionAct->setText(definitionName);
908 definitionAct->setStatusTip(tr("Maximum video definition set to %1").arg(definitionAct->text())
909 + " (" + definitionAct->shortcut().toString(QKeySequence::NativeText) + ")");
910 statusBar()->showMessage(definitionAct->statusTip());
912 settings.setValue("definition", definitionName);
915 void MainWindow::toggleDefinitionMode() {
917 QString currentDefinition = settings.value("definition").toString();
918 QStringList definitionNames = VideoDefinition::getDefinitionNames();
919 int currentIndex = definitionNames.indexOf(currentDefinition);
921 if (currentIndex != definitionNames.size() - 1) {
922 nextIndex = currentIndex + 1;
924 QString nextDefinition = definitionNames.at(nextIndex);
925 setDefinitionMode(nextDefinition);
928 void MainWindow::showFullscreenToolbar(bool show) {
929 if (!m_fullscreen) return;
930 mainToolBar->setVisible(show);
933 void MainWindow::showFullscreenPlaylist(bool show) {
934 if (!m_fullscreen) return;
935 mediaView->setPlaylistVisible(show);
938 void MainWindow::clearRecentKeywords() {
940 settings.remove("recentKeywords");
941 searchView->updateRecentKeywords();
942 statusBar()->showMessage(tr("Your privacy is now safe"));
946 void MainWindow::setAutoplay(bool enabled) {
948 settings.setValue("autoplay", QVariant::fromValue(enabled));
952 void MainWindow::updateDownloadMessage(QString message) {
953 The::globalActions()->value("downloads")->setText(message);
956 void MainWindow::downloadsFinished() {
957 The::globalActions()->value("downloads")->setText(tr("&Downloads"));
958 statusBar()->showMessage(tr("Downloads complete"));
961 void MainWindow::toggleDownloads(bool show) {
964 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_MediaStop));
965 The::globalActions()->value("downloads")->setShortcuts(
966 QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_J)
967 << QKeySequence(Qt::Key_Escape));
969 The::globalActions()->value("downloads")->setShortcuts(
970 QList<QKeySequence>() << QKeySequence(Qt::CTRL + Qt::Key_J));
971 stopAct->setShortcuts(QList<QKeySequence>() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop));
975 downloadView = new DownloadView(this);
976 views->addWidget(downloadView);
978 if (show) showWidget(downloadView);
982 void MainWindow::startToolbarSearch(QString query) {
984 query = query.trimmed();
986 // check for empty query
987 if (query.length() == 0) {
991 SearchParams *searchParams = new SearchParams();
992 searchParams->setKeywords(query);
995 showMedia(searchParams);