X-Git-Url: https://git.sur5r.net/?a=blobdiff_plain;f=src%2FMainWindow.cpp;h=a7621f19ab5785848048526a2384240cebb9d9bd;hb=0817201dd8aa205f3532c3d850e63786b728e649;hp=f4fff9633e85cc710321bb5e2f97e3029d810a89;hpb=51eda34d76647165056b081174e3c25db423c5ec;p=minitube diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index f4fff96..a7621f1 100755 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -21,13 +21,12 @@ MainWindow::MainWindow() { mediaView = new MediaView(this); views->addWidget(mediaView); - // lazy initialized views + // lazily initialized views aboutView = 0; settingsView = 0; toolbarSearch = new SearchLineEdit(this); toolbarSearch->setFont(qApp->font()); - // toolbarSearch->setMinimumWidth(200); connect(toolbarSearch, SIGNAL(search(const QString&)), searchView, SLOT(watch(const QString&))); // build ui @@ -49,24 +48,6 @@ MainWindow::MainWindow() { showWidget(searchView); setCentralWidget(views); - - // top dock widget - /* - QLabel* message = new QLabel(this); - message->setText(QString("A new version of %1 is available.").arg(Constants::APP_NAME)); - message->setMargin(10); - message->setAlignment(Qt::AlignCenter); - QPalette palette; - message->setBackgroundRole(QPalette::ToolTipBase); - message->setForegroundRole(QPalette::ToolTipText); - message->setAutoFillBackground(true); - QDockWidget *dockWidget = new QDockWidget("", this, 0); - dockWidget->setTitleBarWidget(0); - dockWidget->setWidget(message); - dockWidget->setFeatures(QDockWidget::DockWidgetClosable); - addDockWidget(Qt::TopDockWidgetArea, dockWidget); - */ - } MainWindow::~MainWindow() { @@ -95,20 +76,20 @@ void MainWindow::createActions() { stopAct = new QAction(QtIconLoader::icon("media-stop", QIcon(":/images/stop.png")), tr("&Stop"), this); stopAct->setStatusTip(tr("Stop playback and go back to the search view")); - stopAct->setShortcut(QKeySequence(Qt::Key_Escape)); + stopAct->setShortcuts(QList() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop)); actions->insert("stop", stopAct); connect(stopAct, SIGNAL(triggered()), this, SLOT(stop())); skipAct = new QAction(QtIconLoader::icon("media-skip-forward", QIcon(":/images/skip.png")), tr("S&kip"), this); skipAct->setStatusTip(tr("Skip to the next video")); - skipAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Right)); + skipAct->setShortcuts(QList() << QKeySequence(Qt::CTRL + Qt::Key_Right) << QKeySequence(Qt::Key_MediaNext)); skipAct->setEnabled(false); actions->insert("skip", skipAct); connect(skipAct, SIGNAL(triggered()), mediaView, SLOT(skip())); pauseAct = new QAction(QtIconLoader::icon("media-pause", QIcon(":/images/pause.png")), tr("&Pause"), this); pauseAct->setStatusTip(tr("Pause playback")); - pauseAct->setShortcut(QKeySequence(Qt::Key_Space)); + pauseAct->setShortcuts(QList() << QKeySequence(Qt::Key_Space) << QKeySequence(Qt::Key_MediaPlay)); pauseAct->setEnabled(false); actions->insert("pause", pauseAct); connect(pauseAct, SIGNAL(triggered()), mediaView, SLOT(pause())); @@ -134,7 +115,8 @@ void MainWindow::createActions() { downloadAct = new QAction(QtIconLoader::icon("go-down", QIcon(":/images/go-down.png")), tr("&Download"), this); downloadAct->setStatusTip(tr("Download this video")); downloadAct->setShortcut(tr("Ctrl+S")); - actions.insert("download", downloadAct); + downloadAct->setEnabled(false); + actions->insert("download", downloadAct); connect(downloadAct, SIGNAL(triggered()), this, SLOT(download())); */ @@ -147,9 +129,7 @@ void MainWindow::createActions() { removeAct = new QAction(tr("&Remove"), this); removeAct->setStatusTip(tr("Remove the selected videos from the playlist")); - QList shortcuts; - shortcuts << QKeySequence("Del") << QKeySequence("Backspace"); - removeAct->setShortcuts(shortcuts); + removeAct->setShortcuts(QList() << QKeySequence("Del") << QKeySequence("Backspace")); removeAct->setEnabled(false); actions->insert("remove", removeAct); connect(removeAct, SIGNAL(triggered()), mediaView, SLOT(removeSelected())); @@ -192,19 +172,48 @@ void MainWindow::createActions() { actions->insert("about", aboutAct); connect(aboutAct, SIGNAL(triggered()), this, SLOT(about())); - searchFocusAct = new QAction(tr("&Search"), this); + // Invisible actions + + searchFocusAct = new QAction(this); searchFocusAct->setShortcut(QKeySequence::Find); actions->insert("search", searchFocusAct); connect(searchFocusAct, SIGNAL(triggered()), this, SLOT(searchFocus())); addAction(searchFocusAct); + volumeUpAct = new QAction(this); + volumeUpAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Plus)); + actions->insert("volume-up", volumeUpAct); + connect(volumeUpAct, SIGNAL(triggered()), this, SLOT(volumeUp())); + addAction(volumeUpAct); + + volumeDownAct = new QAction(this); + volumeDownAct->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Minus)); + actions->insert("volume-down", volumeDownAct); + connect(volumeDownAct, SIGNAL(triggered()), this, SLOT(volumeDown())); + addAction(volumeDownAct); + + volumeMuteAct = new QAction(this); + volumeMuteAct->setShortcut(tr("Ctrl+M")); + actions->insert("volume-mute", volumeMuteAct); + connect(volumeMuteAct, SIGNAL(triggered()), this, SLOT(volumeMute())); + addAction(volumeMuteAct); + // common action properties foreach (QAction *action, actions->values()) { + + // add actions to the MainWindow so that they work + // when the menu is hidden + addAction(action); + // never autorepeat. // unexperienced users tend to keep keys pressed for a "long" time action->setAutoRepeat(false); action->setToolTip(action->statusTip()); + // show keyboard shortcuts in the status bar + if (!action->shortcut().isEmpty()) + action->setStatusTip(action->statusTip() + " (" + action->shortcut().toString() + ")"); + // make the actions work when video is fullscreen action->setShortcutContext(Qt::ApplicationShortcut); @@ -223,10 +232,8 @@ void MainWindow::createMenus() { fileMenu = menuBar()->addMenu(tr("&Application")); // menus->insert("file", fileMenu); - /* - fileMenu->addAction(settingsAct); + // fileMenu->addAction(settingsAct); fileMenu->addSeparator(); - */ fileMenu->addAction(quitAct); playlistMenu = menuBar()->addMenu(tr("&Playlist")); @@ -245,6 +252,7 @@ void MainWindow::createMenus() { viewMenu->addSeparator(); viewMenu->addAction(webPageAct); viewMenu->addSeparator(); + // viewMenu->addAction(downloadAct); viewMenu->addAction(compactViewAct); viewMenu->addAction(fullscreenAct); @@ -308,6 +316,9 @@ void MainWindow::readSettings() { } void MainWindow::writeSettings() { + // do not save geometry when in full screen + if (m_fullscreen) + return; QSettings settings; settings.setValue("geometry", saveGeometry()); } @@ -322,6 +333,8 @@ void MainWindow::goBack() { void MainWindow::showWidget ( QWidget* widget ) { + setUpdatesEnabled(false); + // call hide method on the current view View* oldView = dynamic_cast (views->currentWidget()); if (oldView != NULL) { @@ -349,6 +362,12 @@ void MainWindow::showWidget ( QWidget* widget ) { webPageAct->setEnabled(widget == mediaView); aboutAct->setEnabled(widget != aboutView); + /* + // this is not the best place to enable downloads, but the user is informed + // if there really is no video is playing + downloadAct->setEnabled(widget == mediaView); + */ + // cool toolbar on the Mac // setUnifiedTitleAndToolBarOnMac(widget == mediaView); @@ -356,9 +375,16 @@ void MainWindow::showWidget ( QWidget* widget ) { mainToolBar->setVisible(widget == mediaView && !compactViewAct->isChecked()); history->push(widget); + +#ifdef Q_WS_MAC + // crossfade only on OSX + // where we can be sure of video performance fadeInWidget(views->currentWidget(), widget); +#endif + views->setCurrentWidget(widget); + setUpdatesEnabled(true); } void MainWindow::fadeInWidget(QWidget *oldWidget, QWidget *newWidget) { @@ -440,7 +466,7 @@ void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState pauseAct->setEnabled(true); pauseAct->setIcon(QtIconLoader::icon("media-pause", QIcon(":/images/pause.png"))); pauseAct->setText(tr("&Pause")); - pauseAct->setStatusTip(tr("Pause playback")); + pauseAct->setStatusTip(tr("Pause playback") + " (" + pauseAct->shortcut().toString() + ")"); skipAct->setEnabled(true); break; @@ -454,7 +480,7 @@ void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState pauseAct->setEnabled(true); pauseAct->setIcon(QtIconLoader::icon("media-play", QIcon(":/images/play.png"))); pauseAct->setText(tr("&Play")); - pauseAct->setStatusTip(tr("Resume playback")); + pauseAct->setStatusTip(tr("Resume playback") + " (" + pauseAct->shortcut().toString() + ")"); break; case Phonon::BufferingState: @@ -477,28 +503,49 @@ void MainWindow::stop() { void MainWindow::fullscreen() { + setUpdatesEnabled(false); + if (m_fullscreen) { - mediaView->exitFullscreen(); - fullscreenAct->setShortcut(QKeySequence(Qt::ALT + Qt::Key_Return)); + // use setShortucs instead of setShortcut + // the latter seems not to work + fullscreenAct->setShortcuts(QList() << QKeySequence(Qt::ALT + Qt::Key_Return)); fullscreenAct->setText(tr("&Full Screen")); - stopAct->setShortcut(QKeySequence(Qt::Key_Escape)); + stopAct->setShortcuts(QList() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop)); + if (m_maximized) showMaximized(); + else showNormal(); } else { - mediaView->fullscreen(); - stopAct->setShortcut(QString("")); - QList shortcuts; - // for some reason it is importante that ESC comes first - shortcuts << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::ALT + Qt::Key_Return); - fullscreenAct->setShortcuts(shortcuts); + stopAct->setShortcuts(QList() << QKeySequence(Qt::Key_MediaStop)); + fullscreenAct->setShortcuts(QList() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::ALT + Qt::Key_Return)); fullscreenAct->setText(tr("Exit &Full Screen")); + m_maximized = isMaximized(); + + // save geometry now, if the user quits when in full screen + // geometry won't be saved + writeSettings(); + + showFullScreen(); } + + // No compact view action when in full screen compactViewAct->setVisible(m_fullscreen); + // Also no Youtube action since it opens a new window + webPageAct->setVisible(m_fullscreen); + + // Hide anything but the video + mediaView->setPlaylistVisible(m_fullscreen); + mainToolBar->setVisible(m_fullscreen); + statusBar()->setVisible(m_fullscreen); + menuBar()->setVisible(m_fullscreen); m_fullscreen = !m_fullscreen; + setUpdatesEnabled(true); } void MainWindow::compactView(bool enable) { + setUpdatesEnabled(false); + // setUnifiedTitleAndToolBarOnMac(!enable); mediaView->setPlaylistVisible(!enable); mainToolBar->setVisible(!enable); @@ -519,6 +566,7 @@ void MainWindow::compactView(bool enable) { stopAct->setShortcut(QKeySequence(Qt::Key_Escape)); } + setUpdatesEnabled(true); } void MainWindow::searchFocus() { @@ -540,11 +588,17 @@ void MainWindow::initPhonon() { connect(mediaObject, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64))); seekSlider->setMediaObject(mediaObject); audioOutput = new Phonon::AudioOutput(Phonon::VideoCategory, this); + connect(audioOutput, SIGNAL(volumeChanged(qreal)), this, SLOT(volumeChanged(qreal))); + connect(audioOutput, SIGNAL(mutedChanged(bool)), this, SLOT(volumeMutedChanged(bool))); volumeSlider->setAudioOutput(audioOutput); Phonon::createPath(mediaObject, audioOutput); } void MainWindow::tick(qint64 time) { + if (time <= 0) { + currentTime->clear(); + return; + } QTime displayTime(0, (time / 60000) % 60, (time / 1000) % 60); currentTime->setText(displayTime.toString("mm:ss")); // qDebug() << "currentTime" << time << displayTime.toString("mm:ss"); @@ -560,3 +614,120 @@ void MainWindow::totalTimeChanged(qint64 time) { // qDebug() << "totalTime" << time << displayTime.toString("mm:ss"); } +void MainWindow::volumeUp() { + qreal newVolume = volumeSlider->audioOutput()->volume() + .1; + if (newVolume > volumeSlider->maximumVolume()) + newVolume = volumeSlider->maximumVolume(); + volumeSlider->audioOutput()->setVolume(newVolume); +} + +void MainWindow::volumeDown() { + qreal newVolume = volumeSlider->audioOutput()->volume() - .1; + if (newVolume < 0) + newVolume = 0; + volumeSlider->audioOutput()->setVolume(newVolume); +} + +void MainWindow::volumeMute() { + volumeSlider->audioOutput()->setMuted(!volumeSlider->audioOutput()->isMuted()); +} + +void MainWindow::volumeChanged(qreal newVolume) { + // automatically unmute when volume changes + if (volumeSlider->audioOutput()->isMuted()) + volumeSlider->audioOutput()->setMuted(false); + statusBar()->showMessage(tr("Volume at %1%").arg(newVolume*100)); +} + +void MainWindow::volumeMutedChanged(bool muted) { + if (muted) + statusBar()->showMessage(tr("Volume is muted")); + else + statusBar()->showMessage(tr("Volume is unmuted")); +} + +/* +void MainWindow::abortDownload() { + QProgressDialog* dlg = dynamic_cast(this->sender()); + QMap::iterator cur; + QMap::iterator end; + // locate the DownloadResource by its dialog address and trigger abortion + for(cur=m_downloads.begin(), end=m_downloads.end(); cur!=end; cur++){ + if(cur.value().dialog == dlg) cur.key()->abort(); + } +} + +void MainWindow::download() { + if(mediaObject == NULL || mediaObject->currentSource().url().isEmpty()){ + // complain unless video source apperas to be valid + QMessageBox::critical(this, tr("No Video playing"), tr("You must first play the video you intent to download !")); + return; + } + QString filename = QFileDialog::getSaveFileName(this, + tr("Save video as..."), + tr("minitube video.mp4"), + "Video File(*.avi *.mp4)" + ); + if(!filename.isNull()) { + // open destination file and initialize download + DownloadResource res; + res.file = new QFile(filename); + if(res.file->open(QFile::WriteOnly) == true) { + res.dialog = new QProgressDialog(tr("Downloading: ") + res.file->fileName(), + tr("Abort Download"), 0, 100, this); + connect(res.dialog, SIGNAL(canceled()), this, SLOT(abortDownload())); + download(mediaObject->currentSource().url(), res); + }else{ + QMessageBox::critical(this, tr("File creation failed"), res.file->errorString()); + delete res.file; + } + } +} + +void MainWindow::download(const QUrl& url, const DownloadResource& res) { + // create and store request and connect the reply signals + QNetworkReply *r = The::networkAccessManager()->get(QNetworkRequest(url)); + m_downloads.insert(r, res); + connect(r, SIGNAL(finished()), this, SLOT(replyFinished())); + connect(r, SIGNAL(readyRead()), this, SLOT(replyReadyRead())); + connect(r, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(replyError(QNetworkReply::NetworkError))); + connect(r, SIGNAL(downloadProgress(qint64,qint64)), this, SLOT(replyDownloadProgress(qint64,qint64))); + connect(r, SIGNAL(metaDataChanged()), this, SLOT(replyMetaDataChanged())); +} + +void MainWindow::replyReadyRead() { + QNetworkReply* r = dynamic_cast(this->sender()); + m_downloads[r].file->write(r->readAll()); +} + +void MainWindow::replyDownloadProgress(qint64 bytesReceived, qint64 bytesTotal) { + QNetworkReply* r = dynamic_cast(this->sender()); + if (bytesTotal > 0 && bytesReceived >0) + m_downloads[r].dialog->setValue( double(100.0/bytesTotal)*bytesReceived ); // pssst :-X +} + +void MainWindow::replyError(QNetworkReply::NetworkError code) { + QNetworkReply* r = dynamic_cast(this->sender()); + QMessageBox::critical(this, tr("Download failed"), r->errorString()); +} + +void MainWindow::replyFinished() { + QNetworkReply* r = dynamic_cast(this->sender()); + m_downloads[r].dialog->close(); + m_downloads[r].file->close(); + delete m_downloads[r].file; + m_downloads.remove(r); +} + +void MainWindow::replyMetaDataChanged() { + QNetworkReply* r = dynamic_cast(this->sender()); + QUrl url = r->attribute(QNetworkRequest::RedirectionTargetAttribute).toUrl(); + if(url.isValid()) { + // redirect - request new url, but keep the resources + qDebug() << "redirecting to: " << url.toString(); + download(url, m_downloads[r]); + m_downloads.remove(r); + } +} + +*/