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(tr("Alt+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(tr("Esc"));
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(tr("Ctrl+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(tr("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(tr("Alt+Return"));
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(tr("Ctrl+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(tr("Ctrl+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("Minitube on the Web"));
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 // seekSlider->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum);
266 mainToolBar->addWidget(new Spacer(mainToolBar, seekSlider));
268 volumeSlider = new Phonon::VolumeSlider(this);
269 // this makes the volume slider smaller...
270 volumeSlider->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
271 mainToolBar->addWidget(new Spacer(mainToolBar, volumeSlider));
273 // mainToolBar->addSeparator();
274 // mainToolBar->addAction(downloadAct);
275 // mainToolBar->addAction(webPageAct);
277 // toolbarSearch->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Maximum);
278 mainToolBar->addWidget(new Spacer(mainToolBar, toolbarSearch));
280 addToolBar(mainToolBar);
283 void MainWindow::createStatusBar() {
285 statusBar()->setBackgroundRole(QPalette::Dark);
286 // statusBar()->setAutoFillBackground(true);
289 void MainWindow::readSettings() {
291 restoreGeometry(settings.value("geometry").toByteArray());
294 void MainWindow::writeSettings() {
296 settings.setValue("geometry", saveGeometry());
299 void MainWindow::goBack() {
300 if ( history->size() > 1 ) {
302 QWidget *widget = history->pop();
307 void MainWindow::showWidget ( QWidget* widget ) {
309 // call hide method on the current view
310 View* oldView = dynamic_cast<View *> (views->currentWidget());
311 if (oldView != NULL) {
312 oldView->disappear();
315 // call show method on the new view
316 View* newView = dynamic_cast<View *> (widget);
317 if (newView != NULL) {
319 QMap<QString,QVariant> metadata = newView->metadata();
320 QString windowTitle = metadata.value("title").toString();
321 if (windowTitle.length())
322 windowTitle += " - ";
323 setWindowTitle(windowTitle + Constants::APP_NAME);
324 setStatusTip(metadata.value("description").toString());
327 // backAct->setEnabled(history->size() > 1);
328 stopAct->setEnabled(widget == mediaView);
329 fullscreenAct->setEnabled(widget == mediaView);
330 webPageAct->setEnabled(widget == mediaView);
331 // settingsAct->setEnabled(widget != settingsView);
332 aboutAct->setEnabled(widget != aboutView);
333 // toolbar only for the mediaView
335 // This is cool on the Mac
336 // But does not respect layouts, maybe it's a Qt bug
337 // setUnifiedTitleAndToolBarOnMac(widget == mediaView);
339 mainToolBar->setVisible(widget == mediaView);
341 history->push(widget);
342 fadeInWidget(views->currentWidget(), widget);
343 views->setCurrentWidget(widget);
347 void MainWindow::fadeInWidget(QWidget *oldWidget, QWidget *newWidget) {
348 if (faderWidget) faderWidget->close();
349 if (!oldWidget || !newWidget || oldWidget == mediaView || newWidget == mediaView) return;
350 QPixmap frozenView = QPixmap::grabWidget(oldWidget);
351 faderWidget = new FaderWidget(newWidget);
352 faderWidget->start(frozenView);
355 void MainWindow::about() {
357 aboutView = new AboutView(this);
358 views->addWidget(aboutView);
360 showWidget(aboutView);
363 void MainWindow::visitSite() {
364 QUrl url(Constants::WEBSITE);
365 statusBar()->showMessage(QString(tr("Opening %1").arg(url.toString())));
366 QDesktopServices::openUrl(url);
369 void MainWindow::donate() {
370 QUrl url(QString(Constants::WEBSITE) + "#donate");
371 statusBar()->showMessage(QString(tr("Opening %1").arg(url.toString())));
372 QDesktopServices::openUrl(url);
375 void MainWindow::quit() {
380 void MainWindow::closeEvent(QCloseEvent *event) {
382 QWidget::closeEvent(event);
385 void MainWindow::showSettings() {
387 settingsView = new SettingsView(this);
388 views->addWidget(settingsView);
390 showWidget(settingsView);
393 void MainWindow::showSearch() {
394 showWidget(searchView);
397 void MainWindow::showMedia(QString query) {
399 mediaView->setMediaObject(mediaObject);
400 SearchParams *searchParams = new SearchParams();
401 searchParams->setKeywords(query);
402 mediaView->search(searchParams);
403 showWidget(mediaView);
406 void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState */) {
408 // qDebug() << "Phonon state: " << newState;
412 case Phonon::ErrorState:
413 if (mediaObject->errorType() == Phonon::FatalError) {
414 setStatusTip("Something went REALLY wrong: " + mediaObject->errorString());
416 setStatusTip("Something went wrong: " + mediaObject->errorString());
420 case Phonon::PlayingState:
421 pauseAct->setEnabled(true);
422 pauseAct->setIcon(QtIconLoader::icon("media-pause", QIcon(":/images/pause.png")));
423 pauseAct->setText(tr("&Pause"));
424 pauseAct->setStatusTip(tr("Pause playback"));
425 skipAct->setEnabled(true);
428 case Phonon::StoppedState:
429 pauseAct->setEnabled(false);
430 skipAct->setEnabled(false);
433 case Phonon::PausedState:
434 skipAct->setEnabled(true);
435 pauseAct->setEnabled(true);
436 pauseAct->setIcon(QtIconLoader::icon("media-play", QIcon(":/images/play.png")));
437 pauseAct->setText(tr("&Play"));
438 pauseAct->setStatusTip(tr("Resume playback"));
441 case Phonon::BufferingState:
442 case Phonon::LoadingState:
443 skipAct->setEnabled(true);
444 pauseAct->setEnabled(false);
452 void MainWindow::stop() {
457 void MainWindow::fullscreen() {
459 mediaView->exitFullscreen();
460 fullscreenAct->setShortcut(tr("Alt+Return"));
461 fullscreenAct->setText(tr("&Full Screen"));
462 stopAct->setShortcut(tr("Esc"));
464 mediaView->fullscreen();
465 stopAct->setShortcut(tr(""));
466 fullscreenAct->setShortcut(tr("Esc"));
467 fullscreenAct->setText(tr("Exit &Full Screen"));
469 m_fullscreen = !m_fullscreen;
472 void MainWindow::searchFocus() {
473 QWidget *view = views->currentWidget();
474 if (view == mediaView) {
475 toolbarSearch->setFocus();
479 void MainWindow::initPhonon() {
480 // Phonon initialization
481 if (mediaObject) delete mediaObject;
482 if (audioOutput) delete audioOutput;
483 mediaObject = new Phonon::MediaObject(this);
484 connect(mediaObject, SIGNAL(stateChanged(Phonon::State, Phonon::State)),
485 this, SLOT(stateChanged(Phonon::State, Phonon::State)));
486 seekSlider->setMediaObject(mediaObject);
487 audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this);
488 volumeSlider->setAudioOutput(audioOutput);
489 Phonon::createPath(mediaObject, audioOutput);