From 7130f1caac7fa1d70fea37ea380c5e274123e208 Mon Sep 17 00:00:00 2001 From: Flavio Date: Mon, 28 Jan 2013 10:30:43 +0100 Subject: [PATCH] Don't interrupt playback if current video is contained in the new results --- src/mediaview.cpp | 34 +++++------ src/mediaview.h | 3 +- src/playlistmodel.cpp | 137 +++++++++++++++++++++++++++--------------- src/playlistmodel.h | 9 ++- 4 files changed, 111 insertions(+), 72 deletions(-) diff --git a/src/mediaview.cpp b/src/mediaview.cpp index d329fee..26895ce 100644 --- a/src/mediaview.cpp +++ b/src/mediaview.cpp @@ -28,7 +28,7 @@ namespace The { NetworkAccess* http(); -QMap* globalActions(); +QHash* globalActions(); QMap* globalMenus(); QNetworkAccessManager* networkAccessManager(); } @@ -145,7 +145,6 @@ void MediaView::search(SearchParams *searchParams) { searchParams->keywords().startsWith("https://")) { QString videoId = YTSearch::videoIdFromUrl(searchParams->keywords()); if (!videoId.isEmpty()) { - qDebug() << "single video"; YTSingleVideoSource *singleVideoSource = new YTSingleVideoSource(this); singleVideoSource->setVideoId(videoId); setVideoSource(singleVideoSource); @@ -185,6 +184,8 @@ void MediaView::setVideoSource(VideoSource *videoSource, bool addToHistory) { SearchParams *searchParams = getSearchParams(); bool isChannel = searchParams && !searchParams->author().isEmpty(); playlistView->setClickableAuthors(!isChannel); + + The::globalActions()->value("related-videos")->setEnabled(true); } void MediaView::searchAgain() { @@ -280,23 +281,19 @@ void MediaView::stop() { } } +Video* MediaView::getCurrentVideo() { + Video *currentVideo = 0; + if (downloadItem) + currentVideo = downloadItem->getVideo(); + return currentVideo; +} + void MediaView::activeRowChanged(int row) { if (reallyStopped) return; Video *video = playlistModel->videoAt(row); if (!video) return; - // Do not stop/start playing if the first video result is the current video - if (row == 0 && !history.isEmpty()) { - Video *currentVideo = 0; - if (downloadItem && downloadItem->getVideo()) - currentVideo = downloadItem->getVideo(); - if (currentVideo && playlistModel->videoAt(row)->webpage() == currentVideo->webpage()) { - The::globalActions()->value("related-videos")->setEnabled(false); - return; - } - } - errorTimer->stop(); videoAreaWidget->showLoading(video); @@ -333,7 +330,6 @@ void MediaView::activeRowChanged(int row) { The::globalActions()->value("related-videos")->setEnabled(true); // see you in gotStreamUrl... - } void MediaView::gotStreamUrl(QUrl streamUrl) { @@ -518,11 +514,12 @@ void MediaView::aboutToFinish() { } void MediaView::playbackFinished() { - qDebug() << __PRETTY_FUNCTION__ << mediaObject->currentTime(); - // qDebug() << "finished" << mediaObject->currentTime() << mediaObject->totalTime(); + const int totalTime = mediaObject->totalTime(); + const int currentTime = mediaObject->currentTime(); + qDebug() << __PRETTY_FUNCTION__ << mediaObject->currentTime() << totalTime; // add 10 secs for imprecise Phonon backends (VLC, Xine) - if (mediaObject->currentTime() + 10000 < mediaObject->totalTime()) { - // mediaObject->seek(mediaObject->currentTime()); + if (currentTime > 0 && currentTime + 10000 < totalTime) { + // mediaObject->seek(currentTime); QTimer::singleShot(500, this, SLOT(playbackResume())); } else { QAction* stopAfterThisAction = The::globalActions()->value("stopafterthis"); @@ -805,6 +802,7 @@ void MediaView::relatedVideos() { YTSingleVideoSource *singleVideoSource = new YTSingleVideoSource(); singleVideoSource->setVideoId(video->id()); setVideoSource(singleVideoSource); + The::globalActions()->value("related-videos")->setEnabled(false); } void MediaView::shareViaTwitter() { diff --git a/src/mediaview.h b/src/mediaview.h index 3f14e73..8277707 100644 --- a/src/mediaview.h +++ b/src/mediaview.h @@ -19,7 +19,7 @@ class SidebarWidget; class VideoSource; namespace The { - QMap* globalActions(); + QHash* globalActions(); } class MediaView : public QWidget, public View { @@ -37,6 +37,7 @@ public: const QList & getHistory() { return history; } int getHistoryIndex(); PlaylistModel* getPlaylistModel() { return playlistModel; } + Video* getCurrentVideo(); public slots: void search(SearchParams *searchParams); diff --git a/src/playlistmodel.cpp b/src/playlistmodel.cpp index bdd0b4d..e14fbd2 100644 --- a/src/playlistmodel.cpp +++ b/src/playlistmodel.cpp @@ -4,6 +4,7 @@ #include "ytsearch.h" #include "video.h" #include "searchparams.h" +#include "mediaview.h" static const int maxItems = 10; static const QString recentKeywordsKey = "recentKeywords"; @@ -13,11 +14,11 @@ PlaylistModel::PlaylistModel(QWidget *parent) : QAbstractListModel(parent) { videoSource = 0; searching = false; canSearchMore = true; + firstSearch = false; m_activeVideo = 0; m_activeRow = -1; skip = 1; max = 0; - hoveredRow = -1; authorHovered = false; authorPressed = false; @@ -96,7 +97,7 @@ QVariant PlaylistModel::data(const QModelIndex &index, int role) const { return QVariant(); } -void PlaylistModel::setActiveRow( int row) { +void PlaylistModel::setActiveRow(int row, bool notify) { if ( rowExists( row ) ) { m_activeRow = row; @@ -108,7 +109,7 @@ void PlaylistModel::setActiveRow( int row) { emit dataChanged( createIndex( oldactiverow, 0 ), createIndex( oldactiverow, columnCount() - 1 ) ); emit dataChanged( createIndex( m_activeRow, 0 ), createIndex( m_activeRow, columnCount() - 1 ) ); - emit activeRowChanged(row); + if (notify) emit activeRowChanged(row); } else { m_activeRow = -1; @@ -151,8 +152,8 @@ void PlaylistModel::setVideoSource(VideoSource *videoSource) { reset(); this->videoSource = videoSource; - connect(videoSource, SIGNAL(gotVideo(Video*)), - SLOT(addVideo(Video*)), Qt::UniqueConnection); + connect(videoSource, SIGNAL(gotVideos(QList)), + SLOT(addVideos(QList)), Qt::UniqueConnection); connect(videoSource, SIGNAL(finished(int)), SLOT(searchFinished(int)), Qt::UniqueConnection); connect(videoSource, SIGNAL(error(QString)), @@ -164,6 +165,7 @@ void PlaylistModel::setVideoSource(VideoSource *videoSource) { void PlaylistModel::searchMore(int max) { if (searching) return; searching = true; + firstSearch = skip == 1; this->max = max; errorMessage.clear(); videoSource->loadVideos(max, skip); @@ -198,6 +200,9 @@ void PlaylistModel::searchFinished(int total) { if (!videoSource->getSuggestions().isEmpty()) emit haveSuggestions(videoSource->getSuggestions()); + + if (firstSearch && !videos.isEmpty()) + handleFirstVideo(videos.first()); } void PlaylistModel::searchError(QString message) { @@ -206,61 +211,79 @@ void PlaylistModel::searchError(QString message) { emit dataChanged( createIndex( maxItems, 0 ), createIndex( maxItems, columnCount() - 1 ) ); } -void PlaylistModel::addVideo(Video* video) { - - connect(video, SIGNAL(gotThumbnail()), SLOT(updateThumbnail()), Qt::UniqueConnection); - video->loadThumbnail(); +void PlaylistModel::addVideos(QList newVideos) { + if (newVideos.isEmpty()) return; + + bool isFirstVideo = videos.isEmpty(); - beginInsertRows(QModelIndex(), videos.size(), videos.size()); - videos << video; + beginInsertRows(QModelIndex(), videos.size(), videos.size() + newVideos.size() - 1); + videos.append(newVideos); endInsertRows(); - - // first result! - if (videos.size() == 1) { - // manualplay + foreach (Video* video, newVideos) { + connect(video, SIGNAL(gotThumbnail()), + SLOT(updateThumbnail()), Qt::UniqueConnection); + video->loadThumbnail(); + } + + // if (isFirstVideo) handleFirstVideo(newVideos.first()); +} + +void PlaylistModel::handleFirstVideo(Video *video) { + + int currentVideoRow = rowForCloneVideo(MediaView::instance()->getCurrentVideo()); + if (currentVideoRow != -1) setActiveRow(currentVideoRow, false); + else { QSettings settings; if (!settings.value("manualplay", false).toBool()) setActiveRow(0); + } - if (videoSource->metaObject()->className() == QLatin1String("YTSearch")) { - - static const int maxRecentElements = 10; - - YTSearch *search = dynamic_cast(videoSource); - SearchParams *searchParams = search->getSearchParams(); - - // save keyword - QString query = searchParams->keywords(); - if (!query.isEmpty() && !searchParams->isTransient()) { - if (query.startsWith("http://")) { - // Save the video title - query += "|" + videos.first()->title(); - } - QStringList keywords = settings.value(recentKeywordsKey).toStringList(); - keywords.removeAll(query); - keywords.prepend(query); - while (keywords.size() > maxRecentElements) - keywords.removeLast(); - settings.setValue(recentKeywordsKey, keywords); - } + QSettings settings; + if (!settings.value("manualplay", false).toBool()) { + int newActiveRow = rowForCloneVideo(MediaView::instance()->getCurrentVideo()); + if (newActiveRow != -1) setActiveRow(newActiveRow, false); + else setActiveRow(0); + } - // save channel - QString channel = searchParams->author(); - if (!channel.isEmpty() && !searchParams->isTransient()) { - if (!video->authorUri().isEmpty()) - channel = video->authorUri() + "|" + video->author(); - QStringList channels = settings.value(recentChannelsKey).toStringList(); - channels.removeAll(channel); - channels.prepend(channel); - while (channels.size() > maxRecentElements) - channels.removeLast(); - settings.setValue(recentChannelsKey, channels); + if (videoSource->metaObject()->className() == QLatin1String("YTSearch")) { + + static const int maxRecentElements = 10; + + YTSearch *search = dynamic_cast(videoSource); + SearchParams *searchParams = search->getSearchParams(); + + // save keyword + QString query = searchParams->keywords(); + if (!query.isEmpty() && !searchParams->isTransient()) { + if (query.startsWith("http://")) { + // Save the video title + query += "|" + videos.first()->title(); } + QStringList keywords = settings.value(recentKeywordsKey).toStringList(); + keywords.removeAll(query); + keywords.prepend(query); + while (keywords.size() > maxRecentElements) + keywords.removeLast(); + settings.setValue(recentKeywordsKey, keywords); } + // save channel + QString channel = searchParams->author(); + if (!channel.isEmpty() && !searchParams->isTransient()) { + QString value; + if (!video->authorUri().isEmpty() && video->authorUri() != video->author()) + value = video->authorUri() + "|" + video->author(); + else value = video->author(); + QStringList channels = settings.value(recentChannelsKey).toStringList(); + channels.removeAll(value); + channels.removeAll(channel); + channels.prepend(value); + while (channels.size() > maxRecentElements) + channels.removeLast(); + settings.setValue(recentChannelsKey, channels); + } } - } void PlaylistModel::updateThumbnail() { @@ -314,15 +337,20 @@ void PlaylistModel::removeIndexes(QModelIndexList &indexes) { Qt::DropActions PlaylistModel::supportedDropActions() const { - return Qt::MoveAction; + return Qt::CopyAction; +} + +Qt::DropActions PlaylistModel::supportedDragActions() const { + return Qt::CopyAction; } Qt::ItemFlags PlaylistModel::flags(const QModelIndex &index) const { - if (index.isValid()) + if (index.isValid()) { if (index.row() == videos.size()) { // don't drag the "show 10 more" item return Qt::ItemIsEnabled | Qt::ItemIsSelectable; } else return (Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsDragEnabled); + } return Qt::ItemIsDropEnabled; } @@ -391,6 +419,15 @@ bool PlaylistModel::dropMimeData(const QMimeData *data, } +int PlaylistModel::rowForCloneVideo(Video *video) const { + if (!video) return -1; + for (int i = 0; i < videos.size(); ++i) { + Video *v = videos.at(i); + if (v->id() == video->id()) return i; + } + return -1; +} + int PlaylistModel::rowForVideo(Video* video) { return videos.indexOf(video); } diff --git a/src/playlistmodel.h b/src/playlistmodel.h index ccaee5a..6b665a3 100644 --- a/src/playlistmodel.h +++ b/src/playlistmodel.h @@ -38,12 +38,13 @@ public: Qt::ItemFlags flags(const QModelIndex &index) const; QStringList mimeTypes() const; Qt::DropActions supportedDropActions() const; + Qt::DropActions supportedDragActions() const; QMimeData* mimeData( const QModelIndexList &indexes ) const; bool dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent); - void setActiveRow( int row ); + void setActiveRow(int row , bool notify = true); bool rowExists( int row ) const { return (( row >= 0 ) && ( row < videos.size() ) ); } int activeRow() const { return m_activeRow; } // returns -1 if there is no active row int nextRow() const; @@ -55,7 +56,7 @@ public: Video* videoAt( int row ) const; Video* activeVideo() const; - bool hasVideo(Video *video) const { return videos.contains(video); } + int rowForCloneVideo(Video *video) const; VideoSource* getVideoSource() { return videoSource; } void setVideoSource(VideoSource *videoSource); @@ -64,7 +65,7 @@ public: public slots: void searchMore(); void searchNeeded(); - void addVideo(Video* video); + void addVideos(QList newVideos); void searchFinished(int total); void searchError(QString message); void updateThumbnail(); @@ -83,11 +84,13 @@ signals: void haveSuggestions(const QStringList &suggestions); private: + void handleFirstVideo(Video* video); void searchMore(int max); VideoSource *videoSource; bool searching; bool canSearchMore; + bool firstSearch; QList videos; int skip; -- 2.39.5