1 #include "MainWindow.h"
4 #include "iconloader/qticonloader.h"
7 MainWindow::MainWindow() {
14 history = new QStack<QWidget*>();
15 views = new QStackedWidget(this);
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);
24 // lazy initialized views
28 toolbarSearch = new SearchLineEdit(this);
29 toolbarSearch->setFont(qApp->font());
30 // toolbarSearch->setMinimumWidth(200);
31 connect(toolbarSearch, SIGNAL(search(const QString&)), searchView, SLOT(watch(const QString&)));
39 // remove that useless menu/toolbar context menu
40 this->setContextMenuPolicy(Qt::NoContextMenu);
42 // mediaView init stuff thats needs actions
43 mediaView->initialize();
45 // restore window position
48 // show the initial view
49 showWidget(searchView);
51 setCentralWidget(views);
55 QLabel* message = new QLabel(this);
56 message->setText(QString("A new version of %1 is available.").arg(Constants::APP_NAME));
57 message->setMargin(10);
58 message->setAlignment(Qt::AlignCenter);
60 message->setBackgroundRole(QPalette::ToolTipBase);
61 message->setForegroundRole(QPalette::ToolTipText);
62 message->setAutoFillBackground(true);
63 QDockWidget *dockWidget = new QDockWidget("", this, 0);
64 dockWidget->setTitleBarWidget(0);
65 dockWidget->setWidget(message);
66 dockWidget->setFeatures(QDockWidget::DockWidgetClosable);
67 addDockWidget(Qt::TopDockWidgetArea, dockWidget);
72 MainWindow::~MainWindow() {
76 void MainWindow::createActions() {
78 QMap<QString, QAction*> *actions = The::globalActions();
81 settingsAct = new QAction(tr("&Preferences..."), this);
82 settingsAct->setStatusTip(tr(QString("Configure ").append(Constants::APP_NAME).toUtf8()));
84 settingsAct->setMenuRole(QAction::PreferencesRole);
85 actions->insert("settings", settingsAct);
86 connect(settingsAct, SIGNAL(triggered()), this, SLOT(showSettings()));
89 backAct = new QAction(QIcon(":/images/go-previous.png"), tr("&Back"), this);
90 backAct->setEnabled(false);
91 backAct->setShortcut(QKeySequence(Qt::ALT + Qt::Key_Left));
92 backAct->setStatusTip(tr("Go to the previous view"));
93 actions->insert("back", backAct);
94 connect(backAct, SIGNAL(triggered()), this, SLOT(goBack()));
96 stopAct = new QAction(QtIconLoader::icon("media-stop", QIcon(":/images/stop.png")), tr("&Stop"), this);
97 stopAct->setStatusTip(tr("Stop playback and go back to the search view"));
98 stopAct->setShortcut(QKeySequence(Qt::Key_Escape));
99 actions->insert("stop", stopAct);
100 connect(stopAct, SIGNAL(triggered()), this, SLOT(stop()));
102 skipAct = new QAction(QtIconLoader::icon("media-skip-forward", QIcon(":/images/skip.png")), tr("S&kip"), this);
103 skipAct->setStatusTip(tr("Skip to the next video"));
104 skipAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Right));
105 skipAct->setEnabled(false);
106 actions->insert("skip", skipAct);
107 connect(skipAct, SIGNAL(triggered()), mediaView, SLOT(skip()));
109 pauseAct = new QAction(QtIconLoader::icon("media-pause", QIcon(":/images/pause.png")), tr("&Pause"), this);
110 pauseAct->setStatusTip(tr("Pause playback"));
111 pauseAct->setShortcut(QKeySequence(Qt::Key_Space));
112 pauseAct->setEnabled(false);
113 actions->insert("pause", pauseAct);
114 connect(pauseAct, SIGNAL(triggered()), mediaView, SLOT(pause()));
116 fullscreenAct = new QAction(QtIconLoader::icon("view-fullscreen", QIcon(":/images/view-fullscreen.png")), tr("&Full Screen"), this);
117 fullscreenAct->setStatusTip(tr("Go full screen"));
118 fullscreenAct->setShortcut(QKeySequence(Qt::ALT + Qt::Key_Enter));
119 fullscreenAct->setShortcutContext(Qt::ApplicationShortcut);
120 actions->insert("fullscreen", fullscreenAct);
121 connect(fullscreenAct, SIGNAL(triggered()), this, SLOT(fullscreen()));
124 // icon should be document-save but it is ugly
125 downloadAct = new QAction(QtIconLoader::icon("go-down", QIcon(":/images/go-down.png")), tr("&Download"), this);
126 downloadAct->setStatusTip(tr("Download this video"));
127 downloadAct->setShortcut(tr("Ctrl+S"));
128 actions.insert("download", downloadAct);
129 connect(downloadAct, SIGNAL(triggered()), this, SLOT(download()));
132 webPageAct = new QAction(QtIconLoader::icon("internet-web-browser", QIcon(":/images/internet-web-browser.png")), tr("&YouTube"), this);
133 webPageAct->setStatusTip(tr("Open the YouTube video page"));
134 webPageAct->setShortcut(tr("Ctrl+Y"));
135 webPageAct->setEnabled(false);
136 actions->insert("webpage", webPageAct);
137 connect(webPageAct, SIGNAL(triggered()), mediaView, SLOT(openWebPage()));
139 removeAct = new QAction(tr("&Remove"), this);
140 removeAct->setStatusTip(tr("Remove the selected videos from the playlist"));
141 QList<QKeySequence> shortcuts;
142 shortcuts << QKeySequence("Del") << QKeySequence("Backspace");
143 removeAct->setShortcuts(shortcuts);
144 removeAct->setEnabled(false);
145 actions->insert("remove", removeAct);
146 connect(removeAct, SIGNAL(triggered()), mediaView, SLOT(removeSelected()));
148 moveUpAct = new QAction(QtIconLoader::icon("go-up", QIcon(":/images/go-up.png")), tr("Move &Up"), this);
149 moveUpAct->setStatusTip(tr("Move up the selected videos in the playlist"));
150 moveUpAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Up));
151 moveUpAct->setEnabled(false);
152 actions->insert("moveUp", moveUpAct);
153 connect(moveUpAct, SIGNAL(triggered()), mediaView, SLOT(moveUpSelected()));
155 moveDownAct = new QAction(QtIconLoader::icon("go-down", QIcon(":/images/go-down.png")), tr("Move &Down"), this);
156 moveDownAct->setStatusTip(tr("Move down the selected videos in the playlist"));
157 moveDownAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Down));
158 moveDownAct->setEnabled(false);
159 actions->insert("moveDown", moveDownAct);
160 connect(moveDownAct, SIGNAL(triggered()), mediaView, SLOT(moveDownSelected()));
162 quitAct = new QAction(tr("&Quit"), this);
163 quitAct->setMenuRole(QAction::QuitRole);
164 quitAct->setShortcut(tr("Ctrl+Q"));
165 quitAct->setStatusTip(tr("Bye"));
166 actions->insert("quit", quitAct);
167 connect(quitAct, SIGNAL(triggered()), this, SLOT(quit()));
169 siteAct = new QAction(tr("&Website"), this);
170 siteAct->setShortcut(QKeySequence::HelpContents);
171 siteAct->setStatusTip(tr("%1 on the Web").arg(Constants::APP_NAME));
172 actions->insert("site", siteAct);
173 connect(siteAct, SIGNAL(triggered()), this, SLOT(visitSite()));
175 donateAct = new QAction(tr("&Donate via PayPal"), this);
176 donateAct->setStatusTip(tr("Please support the continued development of %1").arg(Constants::APP_NAME));
177 actions->insert("donate", donateAct);
178 connect(donateAct, SIGNAL(triggered()), this, SLOT(donate()));
180 aboutAct = new QAction(tr("&About"), this);
181 aboutAct->setMenuRole(QAction::AboutRole);
182 aboutAct->setStatusTip(tr("Info about %1").arg(Constants::APP_NAME));
183 actions->insert("about", aboutAct);
184 connect(aboutAct, SIGNAL(triggered()), this, SLOT(about()));
186 searchFocusAct = new QAction(tr("&Search"), this);
187 searchFocusAct->setShortcut(QKeySequence::Find);
188 actions->insert("search", searchFocusAct);
189 connect(searchFocusAct, SIGNAL(triggered()), this, SLOT(searchFocus()));
190 addAction(searchFocusAct);
192 // common action properties
193 foreach (QAction *action, actions->values()) {
195 // unexperienced users tend to keep keys pressed for a "long" time
196 action->setAutoRepeat(false);
197 action->setToolTip(action->statusTip());
200 // OSX does not use icons in menus
201 action->setIconVisibleInMenu(false);
208 void MainWindow::createMenus() {
210 QMap<QString, QMenu*> *menus = The::globalMenus();
212 fileMenu = menuBar()->addMenu(tr("&Application"));
213 // menus->insert("file", fileMenu);
215 fileMenu->addAction(settingsAct);
216 fileMenu->addSeparator();
218 fileMenu->addAction(quitAct);
220 playlistMenu = menuBar()->addMenu(tr("&Playlist"));
221 menus->insert("playlist", playlistMenu);
222 playlistMenu->addAction(removeAct);
223 playlistMenu->addSeparator();
224 playlistMenu->addAction(moveUpAct);
225 playlistMenu->addAction(moveDownAct);
227 viewMenu = menuBar()->addMenu(tr("&Video"));
228 menus->insert("video", viewMenu);
229 // viewMenu->addAction(backAct);
230 viewMenu->addAction(stopAct);
231 viewMenu->addAction(pauseAct);
232 viewMenu->addAction(skipAct);
233 viewMenu->addSeparator();
234 viewMenu->addAction(webPageAct);
235 viewMenu->addSeparator();
236 viewMenu->addAction(fullscreenAct);
238 helpMenu = menuBar()->addMenu(tr("&Help"));
239 helpMenu->addAction(siteAct);
240 helpMenu->addAction(donateAct);
241 helpMenu->addAction(aboutAct);
244 void MainWindow::createToolBars() {
246 setToolButtonStyle(Qt::ToolButtonTextUnderIcon);
248 mainToolBar = new QToolBar(this);
249 mainToolBar->setFloatable(false);
250 mainToolBar->setMovable(false);
253 smallerFont.setPointSize(smallerFont.pointSize()*.85);
254 mainToolBar->setFont(smallerFont);
256 mainToolBar->setIconSize(QSize(32,32));
257 // mainToolBar->addAction(backAct);
258 mainToolBar->addAction(stopAct);
259 mainToolBar->addAction(pauseAct);
260 mainToolBar->addAction(skipAct);
261 mainToolBar->addAction(fullscreenAct);
263 seekSlider = new Phonon::SeekSlider(this);
264 seekSlider->setIconVisible(false);
265 Spacer *seekSliderSpacer = new Spacer(mainToolBar, seekSlider);
266 seekSliderSpacer->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
267 mainToolBar->addWidget(seekSliderSpacer);
269 volumeSlider = new Phonon::VolumeSlider(this);
270 // this makes the volume slider smaller
271 volumeSlider->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
272 mainToolBar->addWidget(new Spacer(mainToolBar, volumeSlider));
274 mainToolBar->addWidget(new Spacer(mainToolBar, toolbarSearch));
276 addToolBar(mainToolBar);
279 void MainWindow::createStatusBar() {
283 void MainWindow::readSettings() {
285 restoreGeometry(settings.value("geometry").toByteArray());
288 void MainWindow::writeSettings() {
290 settings.setValue("geometry", saveGeometry());
293 void MainWindow::goBack() {
294 if ( history->size() > 1 ) {
296 QWidget *widget = history->pop();
301 void MainWindow::showWidget ( QWidget* widget ) {
303 // call hide method on the current view
304 View* oldView = dynamic_cast<View *> (views->currentWidget());
305 if (oldView != NULL) {
306 oldView->disappear();
309 // call show method on the new view
310 View* newView = dynamic_cast<View *> (widget);
311 if (newView != NULL) {
313 QMap<QString,QVariant> metadata = newView->metadata();
314 QString windowTitle = metadata.value("title").toString();
315 if (windowTitle.length())
316 windowTitle += " - ";
317 setWindowTitle(windowTitle + Constants::APP_NAME);
318 setStatusTip(metadata.value("description").toString());
321 // backAct->setEnabled(history->size() > 1);
322 // settingsAct->setEnabled(widget != settingsView);
323 stopAct->setEnabled(widget == mediaView);
324 fullscreenAct->setEnabled(widget == mediaView);
325 webPageAct->setEnabled(widget == mediaView);
326 aboutAct->setEnabled(widget != aboutView);
328 // cool toolbar on the Mac
329 setUnifiedTitleAndToolBarOnMac(widget == mediaView);
331 // toolbar only for the mediaView
332 mainToolBar->setVisible(widget == mediaView);
334 history->push(widget);
335 fadeInWidget(views->currentWidget(), widget);
336 views->setCurrentWidget(widget);
340 void MainWindow::fadeInWidget(QWidget *oldWidget, QWidget *newWidget) {
341 if (faderWidget) faderWidget->close();
342 if (!oldWidget || !newWidget || oldWidget == mediaView || newWidget == mediaView) return;
343 QPixmap frozenView = QPixmap::grabWidget(oldWidget);
344 faderWidget = new FaderWidget(newWidget);
345 faderWidget->start(frozenView);
348 void MainWindow::about() {
350 aboutView = new AboutView(this);
351 views->addWidget(aboutView);
353 showWidget(aboutView);
356 void MainWindow::visitSite() {
357 QUrl url(Constants::WEBSITE);
358 statusBar()->showMessage(QString(tr("Opening %1").arg(url.toString())));
359 QDesktopServices::openUrl(url);
362 void MainWindow::donate() {
363 QUrl url(QString(Constants::WEBSITE) + "#donate");
364 statusBar()->showMessage(QString(tr("Opening %1").arg(url.toString())));
365 QDesktopServices::openUrl(url);
368 void MainWindow::quit() {
373 void MainWindow::closeEvent(QCloseEvent *event) {
375 QWidget::closeEvent(event);
378 void MainWindow::showSettings() {
380 settingsView = new SettingsView(this);
381 views->addWidget(settingsView);
383 showWidget(settingsView);
386 void MainWindow::showSearch() {
387 showWidget(searchView);
390 void MainWindow::showMedia(QString query) {
392 mediaView->setMediaObject(mediaObject);
393 SearchParams *searchParams = new SearchParams();
394 searchParams->setKeywords(query);
395 mediaView->search(searchParams);
396 showWidget(mediaView);
399 void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState */) {
401 // qDebug() << "Phonon state: " << newState;
405 case Phonon::ErrorState:
406 if (mediaObject->errorType() == Phonon::FatalError) {
407 setStatusTip("Something went REALLY wrong: " + mediaObject->errorString());
409 setStatusTip("Something went wrong: " + mediaObject->errorString());
413 case Phonon::PlayingState:
414 pauseAct->setEnabled(true);
415 pauseAct->setIcon(QtIconLoader::icon("media-pause", QIcon(":/images/pause.png")));
416 pauseAct->setText(tr("&Pause"));
417 pauseAct->setStatusTip(tr("Pause playback"));
418 skipAct->setEnabled(true);
421 case Phonon::StoppedState:
422 pauseAct->setEnabled(false);
423 skipAct->setEnabled(false);
426 case Phonon::PausedState:
427 skipAct->setEnabled(true);
428 pauseAct->setEnabled(true);
429 pauseAct->setIcon(QtIconLoader::icon("media-play", QIcon(":/images/play.png")));
430 pauseAct->setText(tr("&Play"));
431 pauseAct->setStatusTip(tr("Resume playback"));
434 case Phonon::BufferingState:
435 case Phonon::LoadingState:
436 skipAct->setEnabled(true);
437 pauseAct->setEnabled(false);
445 void MainWindow::stop() {
450 void MainWindow::fullscreen() {
452 mediaView->exitFullscreen();
453 fullscreenAct->setShortcut(QKeySequence(Qt::ALT + Qt::Key_Enter));
454 fullscreenAct->setText(tr("&Full Screen"));
455 stopAct->setShortcut(QKeySequence(Qt::Key_Escape));
457 mediaView->fullscreen();
458 stopAct->setShortcut(QString(""));
459 fullscreenAct->setShortcut(QKeySequence(Qt::Key_Escape));
460 fullscreenAct->setText(tr("Exit &Full Screen"));
462 m_fullscreen = !m_fullscreen;
465 void MainWindow::searchFocus() {
466 QWidget *view = views->currentWidget();
467 if (view == mediaView) {
468 toolbarSearch->setFocus();
472 void MainWindow::initPhonon() {
473 // Phonon initialization
474 if (mediaObject) delete mediaObject;
475 if (audioOutput) delete audioOutput;
476 mediaObject = new Phonon::MediaObject(this);
477 connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
478 this, SLOT(stateChanged(Phonon::State, Phonon::State)));
479 seekSlider->setMediaObject(mediaObject);
480 audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this);
481 volumeSlider->setAudioOutput(audioOutput);
482 Phonon::createPath(mediaObject, audioOutput);