]> git.sur5r.net Git - minitube/commitdiff
Snapshots
authorFlavio Tordini <flavio.tordini@gmail.com>
Sun, 21 Sep 2014 16:46:47 +0000 (18:46 +0200)
committerFlavio <flavio.tordini@gmail.com>
Sun, 21 Sep 2014 16:46:47 +0000 (18:46 +0200)
14 files changed:
minitube.pro
resources.qrc
sounds/snapshot.wav [new file with mode: 0755]
src/loadingwidget.cpp
src/mainwindow.cpp
src/mainwindow.h
src/mediaview.cpp
src/mediaview.h
src/snapshotpreview.cpp [new file with mode: 0644]
src/snapshotpreview.h [new file with mode: 0644]
src/snapshotsettings.cpp [new file with mode: 0644]
src/snapshotsettings.h [new file with mode: 0644]
src/videoareawidget.cpp
src/videoareawidget.h

index dd6c5c8422183b9b109dfa4159e038319d9811c6..4f9bca7ff8df4d057fb67f7ea891b2bebc8f4b58 100644 (file)
@@ -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
index 2f15768cf2ba22cf74e3bebc699987307302b10b..6353887b16854cab2d5a15809de786b08c23670f 100644 (file)
@@ -63,5 +63,6 @@
         <file>images/badge.png</file>
         <file>images/badge3.png</file>
         <file>images/badge4.png</file>
+        <file>sounds/snapshot.wav</file>
     </qresource>
 </RCC>
diff --git a/sounds/snapshot.wav b/sounds/snapshot.wav
new file mode 100755 (executable)
index 0000000..182f13d
Binary files /dev/null and b/sounds/snapshot.wav differ
index 1a3701ea93ecc8ac23fda900a6abb1a5d1838579..6ba8af106b7b1a43fd86fab82b47bdfbe49a7d4b 100644 (file)
@@ -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);
index e0a0fb8fcb91a367c45b1ed8b37812feeda77024..9ea7777b1c29fa42f7c58a832dcd258ba5219a85 100644 (file)
@@ -269,7 +269,7 @@ void MainWindow::createActions() {
     stopAct->setShortcuts(QList<QKeySequence>() << 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<QSlider*>();
+        style()->unpolish(volumeQSlider);
+        style()->polish(volumeQSlider);
+    }
 #endif
     statusBar()->showMessage(tr("Volume at %1%").arg((int)(newVolume*100)));
 }
index 67bb0c4cfef9749c329cd34c21e98825e47000da..be9ff146f3894fceab465b563cb567a1559a72d5 100644 (file)
@@ -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;
index 5287af0051f70800e59537d33cc6afbeed3e2f98..13691a10fdaf114001df6b2026db6f8e03a1f465 100644 (file)
@@ -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) {
index 29dcc5b3f3f50969c6bda1de76675f918943a49d..84146d7d2e105918b4ec832682fcdd79eb7111ea 100644 (file)
@@ -42,6 +42,9 @@ class DownloadItem;
 class PlaylistView;
 class SidebarWidget;
 class VideoSource;
+#ifdef APP_SNAPSHOT
+class SnapshotSettings;
+#endif
 
 namespace The {
 QHash<QString, QAction*>* 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<QAction*> 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 (file)
index 0000000..9766a20
--- /dev/null
@@ -0,0 +1,104 @@
+/* $BEGIN_LICENSE
+
+This file is part of Minitube.
+Copyright 2009, Flavio Tordini <flavio.tordini@gmail.com>
+
+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 <http://www.gnu.org/licenses/>.
+
+$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 (file)
index 0000000..2bb7540
--- /dev/null
@@ -0,0 +1,63 @@
+/* $BEGIN_LICENSE
+
+This file is part of Minitube.
+Copyright 2009, Flavio Tordini <flavio.tordini@gmail.com>
+
+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 <http://www.gnu.org/licenses/>.
+
+$END_LICENSE */
+
+#ifndef SNAPSHOTPREVIEW_H
+#define SNAPSHOTPREVIEW_H
+
+#include <QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets>
+#endif
+
+#ifdef APP_PHONON
+#include <phonon/audiooutput.h>
+#include <phonon/mediaobject.h>
+#include <phonon/videowidget.h>
+#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 (file)
index 0000000..bfe5275
--- /dev/null
@@ -0,0 +1,144 @@
+/* $BEGIN_LICENSE
+
+This file is part of Minitube.
+Copyright 2009, Flavio Tordini <flavio.tordini@gmail.com>
+
+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 <http://www.gnu.org/licenses/>.
+
+$END_LICENSE */
+
+#include "snapshotsettings.h"
+#include "mainwindow.h"
+#include <QDesktopServices>
+#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("<a href='showFile' style='text-decoration:none; color:palette(text); font-weight:bold'>%1</a>")
+                .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 (file)
index 0000000..5a8acfe
--- /dev/null
@@ -0,0 +1,55 @@
+/* $BEGIN_LICENSE
+
+This file is part of Minitube.
+Copyright 2009, Flavio Tordini <flavio.tordini@gmail.com>
+
+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 <http://www.gnu.org/licenses/>.
+
+$END_LICENSE */
+
+#ifndef SNAPSHOTSETTINGS_H
+#define SNAPSHOTSETTINGS_H
+
+#include <QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets>
+#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
index ee64a2084df54539114e3748efc51de00f933d69..4adc47ee0c639a1711039d9e885efa82324e6098 100644 (file)
@@ -19,25 +19,21 @@ along with Minitube.  If not, see <http://www.gnu.org/licenses/>.
 $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);
 }
 
index 3673f6913af2a3b8e8753aab0c5ac522d5f5ec33..e40d38fa582e3d49ccfb0146f36b2a52c15e5988 100644 (file)
@@ -21,10 +21,15 @@ $END_LICENSE */
 #ifndef VIDEOAREAWIDGET_H
 #define VIDEOAREAWIDGET_H
 
-#include <QWidget>
-#include "video.h"
-#include "loadingwidget.h"
-#include "playlistmodel.h"
+#include <QtGui>
+#if QT_VERSION >= 0x050000
+#include <QtWidgets>
+#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