From 43f77804ae9e4578732dffb8ae819ec39a6583e8 Mon Sep 17 00:00:00 2001 From: Flavio Tordini Date: Sun, 21 Sep 2014 18:46:47 +0200 Subject: [PATCH] Snapshots --- minitube.pro | 33 ++++++--- resources.qrc | 1 + sounds/snapshot.wav | Bin 0 -> 68982 bytes src/loadingwidget.cpp | 2 +- src/mainwindow.cpp | 75 ++++++++++++-------- src/mainwindow.h | 11 ++- src/mediaview.cpp | 100 ++++++++++++++++++++++----- src/mediaview.h | 13 +++- src/snapshotpreview.cpp | 104 ++++++++++++++++++++++++++++ src/snapshotpreview.h | 63 +++++++++++++++++ src/snapshotsettings.cpp | 144 +++++++++++++++++++++++++++++++++++++++ src/snapshotsettings.h | 55 +++++++++++++++ src/videoareawidget.cpp | 38 +++++------ src/videoareawidget.h | 29 +++++--- 14 files changed, 582 insertions(+), 86 deletions(-) create mode 100755 sounds/snapshot.wav create mode 100644 src/snapshotpreview.cpp create mode 100644 src/snapshotpreview.h create mode 100644 src/snapshotsettings.cpp create mode 100644 src/snapshotsettings.h diff --git a/minitube.pro b/minitube.pro index dd6c5c8..4f9bca7 100644 --- a/minitube.pro +++ b/minitube.pro @@ -9,18 +9,19 @@ DEFINES += APP_NAME="$$APP_NAME" APP_UNIX_NAME = minitube DEFINES += APP_UNIX_NAME="$$APP_UNIX_NAME" -DEFINES *= QT_NO_DEBUG_OUTPUT +DEFINES += APP_PHONON +DEFINES += APP_PHONON_SEEK +DEFINES += APP_SNAPSHOT + +#DEFINES *= QT_NO_DEBUG_OUTPUT DEFINES *= QT_USE_QSTRINGBUILDER -DEFINES += QT_STRICT_ITERATORS +DEFINES *= QT_STRICT_ITERATORS TARGET = $${APP_UNIX_NAME} QT += network xml sql script - qt:greaterThan(QT_MAJOR_VERSION, 4) { contains(QT, gui): QT *= widgets -} else { - QT += phonon } include(src/qtsingleapplication/qtsingleapplication.pri) @@ -90,7 +91,10 @@ HEADERS += \ src/channelview.h \ src/channelitemdelegate.h \ src/jsfunctions.h \ - src/seekslider.h + src/seekslider.h \ + src/snapshotsettings.h \ + src/snapshotpreview.h \ + src/datautils.h SOURCES += src/main.cpp \ src/searchlineedit.cpp \ src/urllineedit.cpp \ @@ -153,7 +157,10 @@ SOURCES += src/main.cpp \ src/channelview.cpp \ src/channelitemdelegate.cpp \ src/jsfunctions.cpp \ - src/seekslider.cpp + src/seekslider.cpp \ + src/snapshotsettings.cpp \ + src/snapshotpreview.cpp \ + src/datautils.cpp RESOURCES += resources.qrc DESTDIR = build/target/ OBJECTS_DIR = build/obj/ @@ -168,7 +175,14 @@ include(locale/locale.pri) # deploy DISTFILES += CHANGES COPYING unix:!mac { - INCLUDEPATH += /usr/include/phonon + + qt:greaterThan(QT_MAJOR_VERSION, 4) { + LIBS += -lphonon4qt5 + INCLUDEPATH += /usr/include/phonon4qt5 + } else { + QT += phonon + INCLUDEPATH += /usr/include/phonon + } QT += dbus HEADERS += src/gnomeglobalshortcutbackend.h SOURCES += src/gnomeglobalshortcutbackend.cpp @@ -215,3 +229,6 @@ unix:!mac { icon512.files += data/512x512/minitube.png } mac|win32|contains(DEFINES, APP_UBUNTU):include(local/local.pri) + +OTHER_FILES += \ + sounds/snapshot.wav diff --git a/resources.qrc b/resources.qrc index 2f15768..6353887 100644 --- a/resources.qrc +++ b/resources.qrc @@ -63,5 +63,6 @@ images/badge.png images/badge3.png images/badge4.png + sounds/snapshot.wav diff --git a/sounds/snapshot.wav b/sounds/snapshot.wav new file mode 100755 index 0000000000000000000000000000000000000000..182f13d4ad7d04b85077fcab530b4ced32371df6 GIT binary patch literal 68982 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

®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 IU}3}fKakpZ!~g&Q literal 0 HcmV?d00001 diff --git a/src/loadingwidget.cpp b/src/loadingwidget.cpp index 1a3701e..6ba8af1 100644 --- a/src/loadingwidget.cpp +++ b/src/loadingwidget.cpp @@ -62,13 +62,13 @@ LoadingWidget::LoadingWidget(QWidget *parent) : QWidget(parent) { void LoadingWidget::setVideo(Video *video) { QFont titleFont; - titleFont.setStyleName("Light"); #ifdef APP_MAC titleFont.setFamily("Helvetica Neue"); #endif #ifdef APP_WIN titleFont.setFamily("Segoe UI Light"); #endif + titleFont.setStyleName("Light"); int smallerDimension = qMin(height(), width()); titleFont.setPixelSize(smallerDimension / 12); titleFont.setHintingPreference(QFont::PreferNoHinting); diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index e0a0fb8..9ea7777 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -269,7 +269,7 @@ void MainWindow::createActions() { stopAct->setShortcuts(QList() << QKeySequence(Qt::Key_Escape) << QKeySequence(Qt::Key_MediaStop)); stopAct->setEnabled(false); actions->insert("stop", stopAct); - connect(stopAct, SIGNAL(triggered()), this, SLOT(stop())); + connect(stopAct, SIGNAL(triggered()), SLOT(stop())); skipBackwardAct = new QAction( Utils::icon("media-skip-backward"), @@ -458,7 +458,7 @@ void MainWindow::createActions() { action = new QAction(Utils::icon("media-playback-start"), tr("&Manually Start Playing"), this); action->setStatusTip(tr("Manually start playing videos")); - action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B)); + action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_T)); action->setCheckable(true); connect(action, SIGNAL(toggled(bool)), SLOT(setManualPlay(bool))); actions->insert("manualplay", action); @@ -482,12 +482,13 @@ void MainWindow::createActions() { connect(action, SIGNAL(triggered()), mediaView, SLOT(downloadVideo())); actions->insert("download", action); - /* - action = new QAction(tr("&Snapshot"), this); - action->setShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_S)); +#ifdef APP_SNAPSHOT + action = new QAction(tr("Take &Snapshot"), this); + action->setShortcut(QKeySequence(Qt::Key_F9)); + action->setEnabled(false); actions->insert("snapshot", action); connect(action, SIGNAL(triggered()), mediaView, SLOT(snapshot())); - */ +#endif action = new QAction(tr("&Subscribe to Channel"), this); action->setProperty("originalText", action->text()); @@ -573,6 +574,7 @@ void MainWindow::createActions() { actions->insert("related-videos", action); action = new QAction(tr("Open in &Browser..."), this); + action->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_B)); action->setEnabled(false); actions->insert("open-in-browser", action); connect(action, SIGNAL(triggered()), mediaView, SLOT(openInBrowser())); @@ -642,14 +644,16 @@ void MainWindow::createMenus() { videoMenu->addAction(The::globalActions()->value("related-videos")); videoMenu->addAction(findVideoPartsAct); videoMenu->addSeparator(); - videoMenu->addAction(webPageAct); - videoMenu->addSeparator(); videoMenu->addAction(The::globalActions()->value("subscribe-channel")); +#ifdef APP_SNAPSHOT videoMenu->addSeparator(); - videoMenu->addAction(The::globalActions()->value("download")); + videoMenu->addAction(The::globalActions()->value("snapshot")); +#endif + videoMenu->addSeparator(); + videoMenu->addAction(webPageAct); videoMenu->addAction(copyLinkAct); videoMenu->addAction(The::globalActions()->value("open-in-browser")); - // videoMenu->addAction(The::globalActions()->value("snapshot")); + videoMenu->addAction(The::globalActions()->value("download")); QMenu* viewMenu = menuBar()->addMenu(tr("&View")); menus->insert("view", viewMenu); @@ -719,16 +723,14 @@ void MainWindow::createToolBars() { currentTime->setFont(smallerFont); mainToolBar->addWidget(currentTime); -#ifdef APP_PHONON_SEEK mainToolBar->addWidget(new Spacer()); + +#ifdef APP_PHONON_SEEK seekSlider = new Phonon::SeekSlider(this); - seekSlider->setVisible(false); seekSlider->setIconVisible(false); seekSlider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); mainToolBar->addWidget(seekSlider); -#endif - - mainToolBar->addWidget(new Spacer()); +#else slider = new SeekSlider(this); slider->setEnabled(false); slider->setTracking(false); @@ -736,15 +738,16 @@ void MainWindow::createToolBars() { slider->setOrientation(Qt::Horizontal); slider->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred); mainToolBar->addWidget(slider); +#endif + /* mainToolBar->addWidget(new Spacer()); - totalTime = new QLabel(mainToolBar); totalTime->setFont(smallerFont); mainToolBar->addWidget(totalTime); + */ mainToolBar->addWidget(new Spacer()); - mainToolBar->addAction(volumeMuteAct); #ifdef APP_PHONON @@ -931,8 +934,8 @@ void MainWindow::showWidget(QWidget* widget, bool transition) { setUpdatesEnabled(true); #ifdef APP_EXTRA - if (transition && (oldWidget != mediaView || - !mediaView->getVideoArea()->isVideoShown())) + // if (transition && (oldWidget != mediaView || !mediaView->getVideoArea()->isVideoShown())) + if (transition) Extra::fadeInWidget(oldWidget, widget); #endif @@ -1021,7 +1024,7 @@ bool MainWindow::confirmQuit() { void MainWindow::showHome(bool transition) { showWidget(homeView, transition); currentTime->clear(); - totalTime->clear(); + // totalTime->clear(); } void MainWindow::showMedia(SearchParams *searchParams) { @@ -1076,7 +1079,7 @@ void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState case Phonon::LoadingState: pauseAct->setEnabled(false); currentTime->clear(); - totalTime->clear(); + // totalTime->clear(); // stopAct->setEnabled(true); break; @@ -1087,8 +1090,8 @@ void MainWindow::stateChanged(Phonon::State newState, Phonon::State /* oldState #endif void MainWindow::stop() { - mediaView->stop(); showHome(); + mediaView->stop(); } void MainWindow::resizeEvent(QResizeEvent*) { @@ -1329,21 +1332,24 @@ void MainWindow::tick(qint64 time) { const qint64 remainingTime = mediaObject->remainingTime(); currentTime->setStatusTip(tr("Remaining time: %1").arg(formatTime(remainingTime))); - slider->blockSignals(true); +#ifndef APP_PHONON_SEEK const qint64 totalTime = mediaObject->totalTime(); + slider->blockSignals(true); // qWarning() << totalTime << time << time * 100 / totalTime; if (totalTime > 0 && time > 0 && !slider->isSliderDown() && mediaObject->state() == Phonon::PlayingState) slider->setValue(time * slider->maximum() / totalTime); slider->blockSignals(false); #endif + +#endif } void MainWindow::totalTimeChanged(qint64 time) { if (time <= 0) { - totalTime->clear(); + // totalTime->clear(); return; } - totalTime->setText(formatTime(time)); + // totalTime->setText(formatTime(time)); /* slider->blockSignals(true); @@ -1377,8 +1383,8 @@ void MainWindow::volumeUp() { void MainWindow::volumeDown() { #ifdef APP_PHONON qreal newVolume = volumeSlider->audioOutput()->volume() - .1; - if (newVolume < 0) - newVolume = 0; + if (newVolume < 0.) + newVolume = 0.; volumeSlider->audioOutput()->setVolume(newVolume); #endif } @@ -1394,6 +1400,21 @@ void MainWindow::volumeChanged(qreal newVolume) { // automatically unmute when volume changes if (volumeSlider->audioOutput()->isMuted()) volumeSlider->audioOutput()->setMuted(false); + + bool isZero = volumeSlider->property("zero").toBool(); + bool styleChanged = false; + if (newVolume == 0. && !isZero) { + volumeSlider->setProperty("zero", true); + styleChanged = true; + } else if (newVolume > 0. && isZero) { + volumeSlider->setProperty("zero", false); + styleChanged = true; + } + if (styleChanged) { + QSlider* volumeQSlider = volumeSlider->findChild(); + style()->unpolish(volumeQSlider); + style()->polish(volumeQSlider); + } #endif statusBar()->showMessage(tr("Volume at %1%").arg((int)(newVolume*100))); } diff --git a/src/mainwindow.h b/src/mainwindow.h index 67bb0c4..be9ff14 100644 --- a/src/mainwindow.h +++ b/src/mainwindow.h @@ -51,8 +51,12 @@ public: ~MainWindow(); #ifdef APP_PHONON_SEEK Phonon::SeekSlider* getSeekSlider() { return seekSlider; } -#endif +#else QSlider* getSlider() { return slider; } +#endif +#ifdef APP_PHONON + Phonon::AudioOutput* getAudioOutput() { return audioOutput; } +#endif void readSettings(); void writeSettings(); static void printHelp(); @@ -207,17 +211,18 @@ private: QAction *regionAction; // phonon - QSlider *slider; #ifdef APP_PHONON #ifdef APP_PHONON_SEEK Phonon::SeekSlider *seekSlider; +#else + QSlider *slider; #endif Phonon::VolumeSlider *volumeSlider; Phonon::MediaObject *mediaObject; Phonon::AudioOutput *audioOutput; #endif QLabel *currentTime; - QLabel *totalTime; + // QLabel *totalTime; // fullscreen bool m_fullscreen; diff --git a/src/mediaview.cpp b/src/mediaview.cpp index 5287af0..13691a1 100644 --- a/src/mediaview.cpp +++ b/src/mediaview.cpp @@ -46,6 +46,10 @@ $END_LICENSE */ #include "channelaggregator.h" #include "utils.h" #include "ytuser.h" +#ifdef APP_SNAPSHOT +#include "snapshotsettings.h" +#endif +#include "datautils.h" namespace The { NetworkAccess* http(); @@ -61,6 +65,9 @@ MediaView* MediaView::instance() { MediaView::MediaView(QWidget *parent) : QWidget(parent), stopped(false), + #ifdef APP_SNAPSHOT + snapshotSettings(0), + #endif downloadItem(0) { } void MediaView::initialize() { @@ -145,6 +152,9 @@ void MediaView::initialize() { << The::globalActions()->value("pagelink") << The::globalActions()->value("videolink") << The::globalActions()->value("open-in-browser") + #ifdef APP_SNAPSHOT + << The::globalActions()->value("snapshot") + #endif << The::globalActions()->value("findVideoParts") << The::globalActions()->value("skip") << The::globalActions()->value("previous") @@ -156,8 +166,10 @@ void MediaView::initialize() { << The::globalActions()->value("buffer") << The::globalActions()->value("email"); +#ifndef APP_PHONON_SEEK QSlider *slider = MainWindow::instance()->getSlider(); connect(slider, SIGNAL(valueChanged(int)), SLOT(sliderMoved(int))); +#endif } #ifdef APP_PHONON @@ -196,7 +208,7 @@ void MediaView::search(SearchParams *searchParams) { setVideoSource(new YTSearch(searchParams, this)); } -void MediaView::setVideoSource(VideoSource *videoSource, bool addToHistory) { +void MediaView::setVideoSource(VideoSource *videoSource, bool addToHistory, bool back) { stopped = false; #ifdef APP_ACTIVATION @@ -220,6 +232,11 @@ void MediaView::setVideoSource(VideoSource *videoSource, bool addToHistory) { history.append(videoSource); } +#ifdef APP_EXTRA + if (history.size() > 1) + Extra::slideTransition(playlistView->viewport(), playlistView->viewport(), back); +#endif + playlistModel->setVideoSource(videoSource); sidebar->showPlaylist(); @@ -230,6 +247,8 @@ void MediaView::setVideoSource(VideoSource *videoSource, bool addToHistory) { SearchParams *searchParams = getSearchParams(); bool isChannel = searchParams && !searchParams->author().isEmpty(); playlistView->setClickableAuthors(!isChannel); + + } void MediaView::searchAgain() { @@ -246,7 +265,7 @@ void MediaView::goBack() { int currentIndex = getHistoryIndex(); if (currentIndex > 0) { VideoSource *previousVideoSource = history.at(currentIndex - 1); - setVideoSource(previousVideoSource, false); + setVideoSource(previousVideoSource, false, true); } } } @@ -283,7 +302,11 @@ void MediaView::disappear() { } void MediaView::handleError(QString /* message */) { +#ifdef APP_PHONON_SEEK + mediaObject->play(); +#else QTimer::singleShot(500, this, SLOT(startPlaying())); +#endif } #ifdef APP_PHONON @@ -352,9 +375,16 @@ void MediaView::stop() { #endif currentVideoId.clear(); +#ifndef APP_PHONON_SEEK QSlider *slider = MainWindow::instance()->getSlider(); slider->setEnabled(false); slider->setValue(0); +#endif + + if (snapshotSettings) { + delete snapshotSettings; + snapshotSettings = 0; + } } const QString & MediaView::getCurrentVideoId() { @@ -384,7 +414,7 @@ void MediaView::activeRowChanged(int row) { connect(video, SIGNAL(gotStreamUrl(QUrl)), SLOT(gotStreamUrl(QUrl)), Qt::UniqueConnection); connect(video, SIGNAL(errorStreamUrl(QString)), - SLOT(handleError(QString)), Qt::UniqueConnection); + SLOT(skip()), Qt::UniqueConnection); video->loadStreamUrl(); // video title in titlebar @@ -422,9 +452,16 @@ void MediaView::activeRowChanged(int row) { foreach (QAction *action, currentVideoActions) action->setEnabled(true); +#ifndef APP_PHONON_SEEK QSlider *slider = MainWindow::instance()->getSlider(); slider->setEnabled(false); slider->setValue(0); +#endif + + if (snapshotSettings) { + delete snapshotSettings; + snapshotSettings = 0; + } // see you in gotStreamUrl... } @@ -445,7 +482,7 @@ void MediaView::gotStreamUrl(QUrl streamUrl) { currentVideoId = video->id(); -#ifdef Q_OS_LINUX_NO +#ifdef APP_PHONON_SEEK mediaObject->setCurrentSource(streamUrl); mediaObject->play(); #else @@ -493,8 +530,8 @@ void MediaView::downloadStatusChanged() { break; case Finished: // qDebug() << "Finished" << mediaObject->state(); -#ifdef Q_OS_LINUX - // MainWindow::instance()->getSeekSlider()->setEnabled(mediaObject->isSeekable()); +#ifdef APP_PHONON_SEEK + MainWindow::instance()->getSeekSlider()->setEnabled(mediaObject->isSeekable()); #endif break; case Failed: @@ -524,15 +561,15 @@ void MediaView::startPlaying() { QString source = downloadItem->currentFilename(); qDebug() << "Playing" << source << QFile::exists(source); #ifdef APP_PHONON - mediaObject->setCurrentSource(source); + mediaObject->setCurrentSource(QUrl::fromLocalFile(source)); mediaObject->play(); #endif -#ifdef Q_OS_LINUX - // MainWindow::instance()->getSeekSlider()->setEnabled(false); -#endif - +#ifdef APP_PHONON_SEEK + MainWindow::instance()->getSeekSlider()->setEnabled(false); +#else QSlider *slider = MainWindow::instance()->getSlider(); slider->setEnabled(true); +#endif } void MediaView::itemActivated(const QModelIndex &index) { @@ -791,16 +828,44 @@ void MediaView::downloadVideo() { MainWindow::instance()->showMessage(message); } -/* +#ifdef APP_SNAPSHOT void MediaView::snapshot() { + qint64 currentTime = mediaObject->currentTime() / 1000; + QImage image = videoWidget->snapshot(); - qDebug() << image.size(); + if (image.isNull()) { + qWarning() << "Null snapshot"; + return; + } - const QPixmap& pixmap = QPixmap::grabWindow(videoWidget->winId()); - // qDebug() << pixmap.size(); + // QPixmap pixmap = QPixmap::grabWindow(videoWidget->winId()); + QPixmap pixmap = QPixmap::fromImage(image.scaled(videoWidget->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation)); videoAreaWidget->showSnapshotPreview(pixmap); + + Video* video = playlistModel->activeVideo(); + if (!video) return; + + QString location = SnapshotSettings::getCurrentLocation(); + QString basename = video->title(); + QString format = video->duration() > 3600 ? "h_mm_ss" : "m_ss"; + basename += " (" + QTime().addSecs(currentTime).toString(format) + ")"; + basename = DataUtils::stringToFilename(basename); + QString filename = location + "/" + basename + ".png"; + qDebug() << filename; + image.save(filename, "PNG"); + + if (snapshotSettings) delete snapshotSettings; + snapshotSettings = new SnapshotSettings(videoWidget); + snapshotSettings->setSnapshot(pixmap, filename); + QStatusBar *statusBar = MainWindow::instance()->statusBar(); +#ifdef APP_EXTRA + Extra::fadeInWidget(statusBar, statusBar); +#endif + statusBar->clearMessage(); + statusBar->insertPermanentWidget(0, snapshotSettings); + snapshotSettings->show(); } -*/ +#endif void MediaView::fullscreen() { videoAreaWidget->setParent(0); @@ -831,6 +896,8 @@ void MediaView::startDownloading() { void MediaView::sliderMoved(int value) { #ifdef APP_PHONON +#ifndef APP_PHONON_SEEK + if (currentVideoSize <= 0 || !downloadItem || !mediaObject->isSeekable()) return; @@ -855,6 +922,7 @@ void MediaView::sliderMoved(int value) { mediaObject->seek(offsetToTime(offset)); } #endif +#endif } qint64 MediaView::offsetToTime(qint64 offset) { diff --git a/src/mediaview.h b/src/mediaview.h index 29dcc5b..84146d7 100644 --- a/src/mediaview.h +++ b/src/mediaview.h @@ -42,6 +42,9 @@ class DownloadItem; class PlaylistView; class SidebarWidget; class VideoSource; +#ifdef APP_SNAPSHOT +class SnapshotSettings; +#endif namespace The { QHash* globalActions(); @@ -70,7 +73,7 @@ public: public slots: void search(SearchParams *searchParams); - void setVideoSource(VideoSource *videoSource, bool addToHistory = true); + void setVideoSource(VideoSource *videoSource, bool addToHistory = true, bool back = false); void pause(); void stop(); void skip(); @@ -91,7 +94,9 @@ public slots: void setPlaylistVisible(bool visible=true); void saveSplitterState(); void downloadVideo(); - // void snapshot(); +#ifdef APP_SNAPSHOT + void snapshot(); +#endif void fullscreen(); void findVideoParts(); void relatedVideos(); @@ -160,6 +165,10 @@ private: QList currentVideoActions; qint64 currentVideoSize; + +#ifdef APP_SNAPSHOT + SnapshotSettings *snapshotSettings; +#endif }; #endif // __MEDIAVIEW_H__ diff --git a/src/snapshotpreview.cpp b/src/snapshotpreview.cpp new file mode 100644 index 0000000..9766a20 --- /dev/null +++ b/src/snapshotpreview.cpp @@ -0,0 +1,104 @@ +/* $BEGIN_LICENSE + +This file is part of Minitube. +Copyright 2009, Flavio Tordini + +Minitube is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Minitube is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Minitube. If not, see . + +$END_LICENSE */ + +#include "snapshotpreview.h" +#include "mainwindow.h" + +SnapshotPreview::SnapshotPreview(QWidget *parent) : QWidget(parent), +#ifdef APP_PHONON + mediaObject(0), + audioOutput(0) +#endif + { + setAttribute(Qt::WA_ShowWithoutActivating); + setWindowFlags(Qt::FramelessWindowHint); +#if QT_VERSION >= 0x050000 + setWindowFlags(Qt::WindowDoesNotAcceptFocus); +#endif + + setAttribute(Qt::WA_StaticContents); + setAttribute(Qt::WA_OpaquePaintEvent); + setAttribute(Qt::WA_NoSystemBackground); + setEnabled(false); + setFocusPolicy(Qt::NoFocus); + + timeLine = new QTimeLine(300, this); + timeLine->setCurveShape(QTimeLine::LinearCurve); + timeLine->setFrameRange(0, 20); + connect(timeLine, SIGNAL(frameChanged(int)), SLOT(update())); + + timer = new QTimer(this); + timer->setSingleShot(true); + timer->setInterval(1500); + connect(timer, SIGNAL(timeout()), SLOT(finish())); + + hide(); +} + +void SnapshotPreview::start(QWidget *widget, const QPixmap &pixmap, bool soundOnly) { +#ifdef APP_PHONON + if (!mediaObject) { + mediaObject = new Phonon::MediaObject(this); + audioOutput = new Phonon::AudioOutput(Phonon::NotificationCategory, this); + Phonon::createPath(mediaObject, audioOutput); + } + mediaObject->setCurrentSource(QUrl("qrc:///sounds/snapshot.wav")); + mediaObject->play(); +#endif + if (soundOnly) return; + + resize(pixmap.size()); +#if defined(APP_MAC) || defined(APP_WIN) + QPoint pos = widget->mapToGlobal(widget->pos()); + pos.setY(pos.y() + ((widget->height() - pixmap.height()) / 2)); + pos.setX(pos.x() + ((widget->width() - pixmap.width()) / 2)); + move(pos); +#else + QPoint pos; + pos.setY((widget->height() - pixmap.height()) / 2); + pos.setX((widget->width() - pixmap.width()) / 2); + move(pos); + setParent(widget); +#endif + + this->pixmap = pixmap; +#ifndef APP_MAC + timeLine->start(); +#endif + timer->start(); + if (isVisible()) update(); + else show(); +} + +void SnapshotPreview::paintEvent(QPaintEvent *e) { + Q_UNUSED(e); + QPainter p(this); + if (timeLine->state() == QTimeLine::Running) { + p.fillRect(rect(), Qt::white); + const qreal opacity = timeLine->currentFrame() / 20.; + p.setOpacity(opacity); + } + p.drawPixmap(0, 0, pixmap); +} + +void SnapshotPreview::finish() { + hide(); + emit done(); +} diff --git a/src/snapshotpreview.h b/src/snapshotpreview.h new file mode 100644 index 0000000..2bb7540 --- /dev/null +++ b/src/snapshotpreview.h @@ -0,0 +1,63 @@ +/* $BEGIN_LICENSE + +This file is part of Minitube. +Copyright 2009, Flavio Tordini + +Minitube is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Minitube is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Minitube. If not, see . + +$END_LICENSE */ + +#ifndef SNAPSHOTPREVIEW_H +#define SNAPSHOTPREVIEW_H + +#include +#if QT_VERSION >= 0x050000 +#include +#endif + +#ifdef APP_PHONON +#include +#include +#include +#endif + +class SnapshotPreview : public QWidget { + + Q_OBJECT + +public: + SnapshotPreview(QWidget *parent = 0); + void start(QWidget *widget, const QPixmap &pixmap, bool soundOnly); + +signals: + void done(); + +protected: + void paintEvent(QPaintEvent *e); + +private slots: + void finish(); + +private: + QPixmap pixmap; + QTimeLine *timeLine; + QPoint offset; + QTimer *timer; +#ifdef APP_PHONON + Phonon::MediaObject *mediaObject; + Phonon::AudioOutput *audioOutput; +#endif +}; + +#endif // SNAPSHOTPREVIEW_H diff --git a/src/snapshotsettings.cpp b/src/snapshotsettings.cpp new file mode 100644 index 0000000..bfe5275 --- /dev/null +++ b/src/snapshotsettings.cpp @@ -0,0 +1,144 @@ +/* $BEGIN_LICENSE + +This file is part of Minitube. +Copyright 2009, Flavio Tordini + +Minitube is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Minitube is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Minitube. If not, see . + +$END_LICENSE */ + +#include "snapshotsettings.h" +#include "mainwindow.h" +#include +#ifdef APP_MAC +#include "macutils.h" +#endif + +SnapshotSettings::SnapshotSettings(QWidget *parent) : QWidget(parent) { + QBoxLayout *layout = new QHBoxLayout(this); + layout->setContentsMargins(5, 0, 10, 0); + layout->setSpacing(5); + + thumb = new QToolButton(); + thumb->setStyleSheet("border:0"); + thumb->setCursor(Qt::PointingHandCursor); + connect(thumb, SIGNAL(clicked()), SLOT(openFile())); + layout->addWidget(thumb); + + message = new QLabel(); + connect(message, SIGNAL(linkActivated(QString)), this, SLOT(showFile())); + layout->addWidget(message); + + changeFolderButton = new QPushButton(); + changeFolderButton->setAttribute(Qt::WA_MacMiniSize); + changeFolderButton->setText(tr("Change location...")); + connect(changeFolderButton, SIGNAL(clicked()), SLOT(changeFolder())); + layout->addWidget(changeFolderButton); +} + +void SnapshotSettings::setSnapshot(const QPixmap &pixmap, const QString &filename) { + QPixmap p = pixmap.scaledToHeight(message->sizeHint().height()); + QIcon icon(p); + thumb->setIcon(icon); + thumb->setIconSize(p.size()); + // thumb->setPixmap(pixmap.scaledToHeight(message->sizeHint().height())); + + this->filename = filename; + QFileInfo fileInfo(filename); + QString path = fileInfo.absolutePath(); + QString display = displayPath(path); + + QString msg = tr("Snapshot saved to %1") + .arg("%1") + .arg(display); + message->setText(msg); +} + +void SnapshotSettings::setCurrentLocation(const QString &location) { + QSettings settings; + settings.setValue("snapshotsFolder", location); +} + +QString SnapshotSettings::getCurrentLocation() { + QSettings settings; + QString location = settings.value("snapshotsFolder").toString(); + if (location.isEmpty() || !QFile::exists(location)) { +#if QT_VERSION >= 0x050000 + location = QStandardPaths::writableLocation(QStandardPaths::PicturesLocation); +#else + location = QDesktopServices::storageLocation(QDesktopServices::PicturesLocation); +#endif + } + return location; +} + +QString SnapshotSettings::displayPath(const QString &path) { +#if QT_VERSION >= 0x050000 + QString home = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); +#else + QString home = QDesktopServices::storageLocation(QDesktopServices::HomeLocation); +#endif + QString displayPath = path; + displayPath = displayPath.remove(home + "/"); + return displayPath; +} + +void SnapshotSettings::changeFolder() { + QString path; +#ifdef APP_MAC + QFileDialog* dialog = new QFileDialog(this); + dialog->setFileMode(QFileDialog::Directory); + dialog->setOptions(QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks | QFileDialog::ReadOnly); +#if QT_VERSION >= 0x050000 + path = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); +#else + path = QDesktopServices::storageLocation(QDesktopServices::HomeLocation); +#endif + dialog->setDirectory(path); + dialog->open(this, SLOT(folderChosen(const QString &))); +#else + +#if QT_VERSION >= 0x050000 + path = QStandardPaths::writableLocation(QStandardPaths::HomeLocation); +#else + path = QDesktopServices::storageLocation(QDesktopServices::HomeLocation); +#endif + QString folder = QFileDialog::getExistingDirectory(window(), QString(), + path, + QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks | QFileDialog::ReadOnly); + folderChosen(folder); +#endif +} + +void SnapshotSettings::folderChosen(const QString &dir) { + if (!dir.isEmpty()) { + setCurrentLocation(dir); + QString status = tr("Snapshots location changed."); + MainWindow::instance()->showMessage(status); + } +} + +void SnapshotSettings::showFile() { + QFileInfo info(filename); +#ifdef APP_MAC + mac::showInFinder(info.absoluteFilePath()); +#else + QUrl url = QUrl::fromLocalFile(info.absolutePath()); + QDesktopServices::openUrl(url); +#endif +} + +void SnapshotSettings::openFile() { + QDesktopServices::openUrl(QUrl::fromLocalFile(filename)); +} diff --git a/src/snapshotsettings.h b/src/snapshotsettings.h new file mode 100644 index 0000000..5a8acfe --- /dev/null +++ b/src/snapshotsettings.h @@ -0,0 +1,55 @@ +/* $BEGIN_LICENSE + +This file is part of Minitube. +Copyright 2009, Flavio Tordini + +Minitube is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 3 of the License, or +(at your option) any later version. + +Minitube is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with Minitube. If not, see . + +$END_LICENSE */ + +#ifndef SNAPSHOTSETTINGS_H +#define SNAPSHOTSETTINGS_H + +#include +#if QT_VERSION >= 0x050000 +#include +#endif + +class SnapshotSettings : public QWidget { + + Q_OBJECT + +public: + SnapshotSettings(QWidget *parent = 0); + void setSnapshot(const QPixmap &pixmap, const QString &filename); + + static void setCurrentLocation(const QString &location); + static QString getCurrentLocation(); + static QString displayPath(const QString &path); + +private slots: + void changeFolder(); + void folderChosen(const QString &folder); + void showFile(); + void openFile(); + +private: + QToolButton *thumb; + QLabel *message; + QPushButton *changeFolderButton; + QString filename; + +}; + +#endif // SNAPSHOTSETTINGS_H diff --git a/src/videoareawidget.cpp b/src/videoareawidget.cpp index ee64a20..4adc47e 100644 --- a/src/videoareawidget.cpp +++ b/src/videoareawidget.cpp @@ -19,25 +19,21 @@ along with Minitube. If not, see . $END_LICENSE */ #include "videoareawidget.h" +#include "video.h" +#include "loadingwidget.h" +#include "playlistmodel.h" #include "videomimedata.h" #include "mainwindow.h" -#ifdef APP_EXTRA -#include "extra.h" -#endif #ifdef Q_OS_MAC #include "macutils.h" #endif +#include "snapshotpreview.h" VideoAreaWidget::VideoAreaWidget(QWidget *parent) : QWidget(parent), videoWidget(0) { QBoxLayout *vLayout = new QVBoxLayout(this); vLayout->setMargin(0); vLayout->setSpacing(0); - QPalette p = palette(); - p.setBrush(QPalette::Window, Qt::black); - setPalette(p); - setAutoFillBackground(true); - // hidden message widget messageLabel = new QLabel(this); messageLabel->setOpenExternalLinks(true); @@ -52,9 +48,11 @@ VideoAreaWidget::VideoAreaWidget(QWidget *parent) : QWidget(parent), videoWidget stackedLayout = new QStackedLayout(); vLayout->addLayout(stackedLayout); - // snapshotPreview = new QLabel(this); - // stackedLayout->addWidget(snapshotPreview); - +#ifdef APP_SNAPSHOT + snapshotPreview = new SnapshotPreview(); + connect(stackedLayout, SIGNAL(currentChanged(int)), snapshotPreview, SLOT(hide())); +#endif + setAcceptDrops(true); setMouseTracking(true); setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); @@ -92,26 +90,24 @@ void VideoAreaWidget::showLoading(Video *video) { loadingWidget->setVideo(video); } -/* -void VideoAreaWidget::showSnapshotPreview(QPixmap pixmap) { - snapshotPreview->setPixmap(pixmap); - stackedLayout->setCurrentWidget(snapshotPreview); -#ifdef APP_EXTRA - Extra::flashInWidget(snapshotPreview); +#ifdef APP_SNAPSHOT +void VideoAreaWidget::showSnapshotPreview(const QPixmap &pixmap) { + bool soundOnly = false; +#ifdef APP_MAC + soundOnly = MainWindow::instance()->isReallyFullScreen(); #endif - QTimer::singleShot(1500, this, SLOT(hideSnapshotPreview())); + snapshotPreview->start(videoWidget, pixmap, soundOnly); } void VideoAreaWidget::hideSnapshotPreview() { - stackedLayout->setCurrentWidget(videoWidget); + } -*/ +#endif void VideoAreaWidget::clear() { loadingWidget->clear(); messageLabel->hide(); messageLabel->clear(); - // snapshotPreview->clear(); stackedLayout->setCurrentWidget(loadingWidget); } diff --git a/src/videoareawidget.h b/src/videoareawidget.h index 3673f69..e40d38f 100644 --- a/src/videoareawidget.h +++ b/src/videoareawidget.h @@ -21,10 +21,15 @@ $END_LICENSE */ #ifndef VIDEOAREAWIDGET_H #define VIDEOAREAWIDGET_H -#include -#include "video.h" -#include "loadingwidget.h" -#include "playlistmodel.h" +#include +#if QT_VERSION >= 0x050000 +#include +#endif + +class Video; +class LoadingWidget; +class PlaylistModel; +class SnapshotPreview; class VideoAreaWidget : public QWidget { @@ -41,7 +46,9 @@ public: void setListModel(PlaylistModel *listModel) { this->listModel = listModel; } - // void showSnapshotPreview(QPixmap pixmap); +#ifdef APP_SNAPSHOT + void showSnapshotPreview(const QPixmap &pixmap); +#endif bool isVideoShown() { return stackedLayout->currentWidget() == videoWidget; } signals: @@ -56,17 +63,23 @@ protected: void dropEvent(QDropEvent *event); private slots: - // void hideSnapshotPreview(); +#ifdef APP_SNAPSHOT + void hideSnapshotPreview(); +#endif private: QStackedLayout *stackedLayout; QWidget *videoWidget; LoadingWidget *loadingWidget; + +#ifdef APP_SNAPSHOT + SnapshotPreview *snapshotPreview; +#endif + PlaylistModel *listModel; QLabel *messageLabel; - // QLabel *snapshotPreview; - QPoint dragPosition; + QPoint dragPosition; }; #endif // VIDEOAREAWIDGET_H -- 2.39.5