Allow dolphin to auto-play previewed media file, click on preview to play/pause videos or audio

Summary:
It is based on D19844.

I did my best to avoid glitches hence the amount of code touched.

Retry after @pekkah D7539
Moved the setting to the information panel context menu, no more timer

Settings screenshot :
{F6700220}

This would mach the same feature in the open/save dialog (although not equivalent)
{F6696456}

FEATURE: 378613
FIXED-IN: 19.08.0
GUI: New information panel context menu option

Test Plan:
Without auto play
  - in dolphin with the information panel opened, and the auto media play feature is disabled (right on the information panel)
  - hover over media files
  - the behavior is the same as before the patch

With auto play
  - in dolphin with the information panel opened, and the auto media play feature is enabled
  - hover over media files
  - media is played automatically
  - hover over another media file, the new media is previewed

Use audio or video file as media.

Reviewers: #dolphin, elvisangelaccio, ngraham

Reviewed By: #dolphin, elvisangelaccio, ngraham

Subscribers: ngraham, broulik, kfm-devel, pekkah

Tags: #dolphin

Differential Revision: https://phabricator.kde.org/D19782
This commit is contained in:
Méven Car 2019-04-14 16:54:54 +02:00
parent cdad6a513e
commit e6c1b97d67
6 changed files with 98 additions and 32 deletions

View file

@ -10,6 +10,10 @@
<label>Previews shown</label> <label>Previews shown</label>
<default>true</default> <default>true</default>
</entry> </entry>
<entry name="previewsAutoPlay" type="Bool">
<label>Auto-Play media files</label>
<default>false</default>
</entry>
<entry name="dateFormat" type="Enum"> <entry name="dateFormat" type="Enum">
<label>Date display format</label> <label>Date display format</label>
<choices> <choices>

View file

@ -176,6 +176,11 @@ void InformationPanel::showContextMenu(const QPoint &pos)
previewAction->setCheckable(true); previewAction->setCheckable(true);
previewAction->setChecked(InformationPanelSettings::previewsShown()); previewAction->setChecked(InformationPanelSettings::previewsShown());
QAction* previewAutoPlayAction = popup.addAction(i18nc("@action:inmenu", "Auto-Play media files"));
previewAutoPlayAction->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start")));
previewAutoPlayAction->setCheckable(true);
previewAutoPlayAction->setChecked(InformationPanelSettings::previewsAutoPlay());
QAction* configureAction = popup.addAction(i18nc("@action:inmenu", "Configure...")); QAction* configureAction = popup.addAction(i18nc("@action:inmenu", "Configure..."));
configureAction->setIcon(QIcon::fromTheme(QStringLiteral("configure"))); configureAction->setIcon(QIcon::fromTheme(QStringLiteral("configure")));
if (m_inConfigurationMode) { if (m_inConfigurationMode) {
@ -213,6 +218,9 @@ void InformationPanel::showContextMenu(const QPoint &pos)
InformationPanelSettings::setDateFormat(dateFormat); InformationPanelSettings::setDateFormat(dateFormat);
m_content->refreshMetaData(); m_content->refreshMetaData();
} else if (action == previewAutoPlayAction) {
InformationPanelSettings::setPreviewsAutoPlay(isChecked);
m_content->setPreviewAutoPlay(isChecked);
} }
} }

View file

@ -86,6 +86,7 @@ InformationPanelContent::InformationPanelContent(QWidget* parent) :
m_phononWidget = new PhononWidget(parent); m_phononWidget = new PhononWidget(parent);
m_phononWidget->hide(); m_phononWidget->hide();
m_phononWidget->setMinimumWidth(minPreviewWidth); m_phononWidget->setMinimumWidth(minPreviewWidth);
m_phononWidget->setAutoPlay(InformationPanelSettings::previewsAutoPlay());
connect(m_phononWidget, &PhononWidget::hasVideoChanged, connect(m_phononWidget, &PhononWidget::hasVideoChanged,
this, &InformationPanelContent::slotHasVideoChanged); this, &InformationPanelContent::slotHasVideoChanged);
@ -157,10 +158,12 @@ InformationPanelContent::~InformationPanelContent()
void InformationPanelContent::showItem(const KFileItem& item) void InformationPanelContent::showItem(const KFileItem& item)
{ {
m_item = item; if (item != m_item) {
m_item = item;
refreshPreview(); refreshPreview();
refreshMetaData(); refreshMetaData();
}
} }
void InformationPanelContent::refreshPreview() void InformationPanelContent::refreshPreview()
@ -173,11 +176,12 @@ void InformationPanelContent::refreshPreview()
setNameLabelText(m_item.text()); setNameLabelText(m_item.text());
if (InformationPanelSettings::previewsShown()) { if (InformationPanelSettings::previewsShown()) {
m_preview->show();
const QUrl itemUrl = m_item.url(); const QUrl itemUrl = m_item.url();
const bool isSearchUrl = itemUrl.scheme().contains(QStringLiteral("search")) && m_item.localPath().isEmpty(); const bool isSearchUrl = itemUrl.scheme().contains(QStringLiteral("search")) && m_item.localPath().isEmpty();
if (isSearchUrl) { if (isSearchUrl) {
m_preview->show();
// in the case of a search-URL the URL is not readable for humans // in the case of a search-URL the URL is not readable for humans
// (at least not useful to show in the Information Panel) // (at least not useful to show in the Information Panel)
m_preview->setPixmap( m_preview->setPixmap(
@ -211,13 +215,26 @@ void InformationPanelContent::refreshPreview()
this, &InformationPanelContent::showIcon); this, &InformationPanelContent::showIcon);
const QString mimeType = m_item.mimetype(); const QString mimeType = m_item.mimetype();
const bool usePhonon = mimeType.startsWith(QLatin1String("audio/")) || mimeType.startsWith(QLatin1String("video/")); const bool isVideo = mimeType.startsWith(QLatin1String("video/"));
const bool usePhonon = mimeType.startsWith(QLatin1String("audio/")) || isVideo;
if (usePhonon) { if (usePhonon) {
if (InformationPanelSettings::previewsAutoPlay() && isVideo) {
// hides the preview now to avoid flickering when the autoplay video starts
m_preview->hide();
} else {
// the video won't play before the preview is displayed
m_preview->show();
}
m_phononWidget->show(); m_phononWidget->show();
m_phononWidget->setUrl(m_item.targetUrl()); m_phononWidget->setUrl(m_item.targetUrl(), isVideo ? PhononWidget::MediaKind::Video : PhononWidget::MediaKind::Audio);
m_phononWidget->setVideoSize(m_preview->size()); m_phononWidget->setVideoSize(m_preview->size());
} else { } else {
// When we don't need it, hide the phonon widget first to avoid flickering
m_phononWidget->hide(); m_phononWidget->hide();
m_preview->show();
} }
} }
} else { } else {
@ -328,6 +345,10 @@ void InformationPanelContent::slotHasVideoChanged(bool hasVideo)
m_preview->setVisible(InformationPanelSettings::previewsShown() && !hasVideo); m_preview->setVisible(InformationPanelSettings::previewsShown() && !hasVideo);
} }
void InformationPanelContent::setPreviewAutoPlay(bool autoPlay) {
m_phononWidget->setAutoPlay(autoPlay);
}
void InformationPanelContent::setNameLabelText(const QString& text) void InformationPanelContent::setNameLabelText(const QString& text)
{ {
QTextOption textOption; QTextOption textOption;

View file

@ -81,6 +81,13 @@ public:
*/ */
void configureShownProperties(); void configureShownProperties();
/*
* Set the auto play media mode for the file previewed
* Eventually starting media playback when turning it on
* But not stopping it when turning it off
*/
void setPreviewAutoPlay(bool autoPlay);
signals: signals:
void urlActivated( const QUrl& url ); void urlActivated( const QUrl& url );
void configurationFinished(); void configurationFinished();

View file

@ -69,11 +69,24 @@ PhononWidget::PhononWidget(QWidget *parent)
{ {
} }
void PhononWidget::setUrl(const QUrl &url) void PhononWidget::setUrl(const QUrl &url, MediaKind kind)
{ {
if (m_url != url) { if (m_url != url) {
stop(); // emits playingStopped() signal
m_url = url; m_url = url;
m_isVideo = kind == MediaKind::Video;
}
if (m_autoPlay) {
play();
} else {
stop();
}
}
void PhononWidget::setAutoPlay(bool autoPlay)
{
m_autoPlay = autoPlay;
if (!m_url.isEmpty() && (m_media == nullptr || m_media->state() != Phonon::State::PlayingState) && m_autoPlay && isVisible()) {
play();
} }
} }
@ -162,12 +175,6 @@ void PhononWidget::stateChanged(Phonon::State newstate)
m_stopButton->show(); m_stopButton->show();
m_playButton->hide(); m_playButton->hide();
break; break;
case Phonon::StoppedState:
if (m_videoPlayer) {
m_videoPlayer->hide();
}
emit hasVideoChanged(false);
Q_FALLTHROUGH();
default: default:
m_stopButton->hide(); m_stopButton->hide();
m_playButton->show(); m_playButton->show();
@ -182,13 +189,14 @@ void PhononWidget::play()
m_media = new Phonon::MediaObject(this); m_media = new Phonon::MediaObject(this);
connect(m_media, &Phonon::MediaObject::stateChanged, connect(m_media, &Phonon::MediaObject::stateChanged,
this, &PhononWidget::stateChanged); this, &PhononWidget::stateChanged);
connect(m_media, &Phonon::MediaObject::hasVideoChanged, connect(m_media, &Phonon::MediaObject::finished,
this, &PhononWidget::slotHasVideoChanged); this, &PhononWidget::finished);
m_seekSlider->setMediaObject(m_media); m_seekSlider->setMediaObject(m_media);
} }
if (!m_videoPlayer) { if (!m_videoPlayer) {
m_videoPlayer = new EmbeddedVideoPlayer(this); m_videoPlayer = new EmbeddedVideoPlayer(this);
m_videoPlayer->installEventFilter(this);
m_topLayout->insertWidget(0, m_videoPlayer); m_topLayout->insertWidget(0, m_videoPlayer);
Phonon::createPath(m_media, m_videoPlayer); Phonon::createPath(m_media, m_videoPlayer);
applyVideoSize(); applyVideoSize();
@ -199,26 +207,32 @@ void PhononWidget::play()
Phonon::createPath(m_media, m_audioOutput); Phonon::createPath(m_media, m_audioOutput);
} }
emit hasVideoChanged(false); if (m_isVideo) {
emit hasVideoChanged(true);
}
m_media->setCurrentSource(m_url); if (m_url != m_media->currentSource().url()) {
m_media->hasVideo(); m_media->setCurrentSource(m_url);
}
m_media->play(); m_media->play();
m_videoPlayer->setVisible(m_isVideo);
}
void PhononWidget::finished()
{
if (m_isVideo) {
m_videoPlayer->hide();
emit hasVideoChanged(false);
}
} }
void PhononWidget::stop() void PhononWidget::stop()
{ {
if (m_media) { if (m_media) {
m_media->stop(); m_media->stop();
} m_videoPlayer->hide();
} emit hasVideoChanged(false);
void PhononWidget::slotHasVideoChanged(bool hasVideo)
{
emit hasVideoChanged(hasVideo);
if (hasVideo) {
m_videoPlayer->show();
} }
} }

View file

@ -43,14 +43,22 @@ class PhononWidget : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
enum MediaKind {
Video,
Audio
};
explicit PhononWidget(QWidget *parent = nullptr); explicit PhononWidget(QWidget *parent = nullptr);
void setUrl(const QUrl &url); void setUrl(const QUrl &url, MediaKind kind);
QUrl url() const; QUrl url() const;
void setVideoSize(const QSize& size); void setVideoSize(const QSize& size);
QSize videoSize() const; QSize videoSize() const;
void setAutoPlay(bool autoPlay);
signals: signals:
/** /**
* Is emitted whenever the video-state * Is emitted whenever the video-state
@ -62,15 +70,17 @@ class PhononWidget : public QWidget
*/ */
void hasVideoChanged(bool hasVideo); void hasVideoChanged(bool hasVideo);
public slots:
void play();
protected: protected:
void showEvent(QShowEvent *event) override; void showEvent(QShowEvent *event) override;
void hideEvent(QHideEvent *event) override; void hideEvent(QHideEvent *event) override;
private slots: private slots:
void stateChanged(Phonon::State); void stateChanged(Phonon::State newstate);
void play();
void stop(); void stop();
void slotHasVideoChanged(bool); void finished();
private: private:
void applyVideoSize(); void applyVideoSize();
@ -87,6 +97,8 @@ class PhononWidget : public QWidget
Phonon::SeekSlider *m_seekSlider; Phonon::SeekSlider *m_seekSlider;
Phonon::AudioOutput *m_audioOutput; Phonon::AudioOutput *m_audioOutput;
EmbeddedVideoPlayer *m_videoPlayer; EmbeddedVideoPlayer *m_videoPlayer;
bool m_autoPlay;
bool m_isVideo;
}; };
#endif // PHONONWIDGET_H #endif // PHONONWIDGET_H