]> cloud.milkyroute.net Git - dolphin.git/commitdiff
InformationPanel: Port from Phonon to QtMultimedia
authorMéven Car <meven29@gmail.com>
Sun, 23 Jun 2019 15:36:38 +0000 (17:36 +0200)
committerMéven Car <meven@kde.org>
Sat, 28 Jun 2025 09:55:38 +0000 (11:55 +0200)
.kde-ci.yml
CMakeLists.txt
src/CMakeLists.txt
src/panels/information/informationpanelcontent.cpp
src/panels/information/informationpanelcontent.h
src/panels/information/mediawidget.cpp [new file with mode: 0644]
src/panels/information/mediawidget.h [moved from src/panels/information/phononwidget.h with 70% similarity]
src/panels/information/phononwidget.cpp [deleted file]

index 60ce73499b61a17acd2d2100bcc5ee67926ce490..66f1007b947f3d191f2b23c9b48f7f25011da43e 100644 (file)
@@ -26,7 +26,6 @@ Dependencies:
     'frameworks/kcodecs': '@latest-kf6'
     'frameworks/kuserfeedback': '@latest-kf6'
     'frameworks/kcolorscheme': '@latest-kf6'
-    'libraries/phonon': '@latest-kf6'
 
  - 'on': ['Linux/Qt6', 'Linux/Qt6Next', 'FreeBSD/Qt6']
    'require':
index 2a074067e05505f9f9160eebf935f215ce6158ab..e3b966eb8ef9b874b85db9bf3a8eb320953d4496 100644 (file)
@@ -103,8 +103,6 @@ find_package(KF6 ${KF6_MIN_VERSION} OPTIONAL_COMPONENTS
     DocTools
 )
 
-find_package(Phonon4Qt6 CONFIG REQUIRED)
-
 find_package(PackageKitQt6)
 set_package_properties(PackageKitQt6
         PROPERTIES DESCRIPTION "Software Manager integration"
@@ -138,7 +136,12 @@ set_package_properties(KF6BalooWidgets PROPERTIES DESCRIPTION "Baloos Widgets"
 if (KF6Baloo_FOUND AND KF6BalooWidgets_FOUND)
     message(STATUS "Baloo packages are found")
     set(HAVE_BALOO TRUE)
-else()
+
+    find_package(Qt6 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS
+        Multimedia
+        MultimediaWidgets
+    )
+else ()
     message(WARNING "Baloo packages not found. They are needed for the metadata features of Dolphin (including the information panel).")
 endif()
 
index bf1ed0101e1e18734caf4182b0a5cc20278993d4..6e982fce81eef943a3e2d5285ea646d11edd4fde 100644 (file)
@@ -425,12 +425,12 @@ if(HAVE_BALOO)
         panels/information/informationpanel.cpp
         panels/information/informationpanelcontent.cpp
         panels/information/pixmapviewer.cpp
-        panels/information/phononwidget.cpp
+        panels/information/mediawidget.cpp
         settings/interface/panelsettingspage.cpp
         panels/information/informationpanel.h
         panels/information/informationpanelcontent.h
         panels/information/pixmapviewer.h
-        panels/information/phononwidget.h
+        panels/information/mediawidget.h
         settings/interface/panelsettingspage.h
     )
 
@@ -438,6 +438,10 @@ if(HAVE_BALOO)
         panels/information/dolphin_informationpanelsettings.kcfgc
     )
 
+    target_link_libraries(dolphinstatic
+        Qt::Multimedia
+        Qt::MultimediaWidgets
+    )
 endif()
 
 if(HAVE_KUSERFEEDBACK)
@@ -477,7 +481,6 @@ target_sources(dolphinstatic PRIVATE
     ${dolphin_dbus_SRCS}
 )
 
-target_include_directories(dolphinstatic SYSTEM PRIVATE ${PHONON_INCLUDES})
 target_link_libraries(dolphinstatic
     dolphinprivate
     KF6::CoreAddons
@@ -486,7 +489,6 @@ target_link_libraries(dolphinstatic
     KF6::DBusAddons
     KF6::Notifications
     KF6::BookmarksWidgets
-    Phonon::phonon4qt6
 )
 
 if(HAVE_PACKAGEKIT)
index 14a470b116178d7bee7b98c11d73a10af3ef9596..1ab57c0e78f7c46ad67fd87b7f3167b39653b988 100644 (file)
@@ -24,9 +24,6 @@
 
 #include <Baloo/FileMetaDataWidget>
 
-#include <phonon/BackendCapabilities>
-#include <phonon/MediaObject>
-
 #include <QDialogButtonBox>
 #include <QGesture>
 #include <QLabel>
@@ -40,7 +37,7 @@
 #include <QVBoxLayout>
 
 #include "dolphin_informationpanelsettings.h"
-#include "phononwidget.h"
+#include "mediawidget.h"
 #include "pixmapviewer.h"
 
 const int PLAY_ARROW_SIZE = 24;
@@ -52,7 +49,7 @@ InformationPanelContent::InformationPanelContent(QWidget *parent)
     , m_previewJob(nullptr)
     , m_outdatedPreviewTimer(nullptr)
     , m_preview(nullptr)
-    , m_phononWidget(nullptr)
+    , m_mediaWidget(nullptr)
     , m_nameLabel(nullptr)
     , m_metaDataWidget(nullptr)
     , m_metaDataArea(nullptr)
@@ -77,11 +74,11 @@ InformationPanelContent::InformationPanelContent(QWidget *parent)
     m_preview->setMinimumWidth(minPreviewWidth);
     m_preview->setMinimumHeight(KIconLoader::SizeEnormous);
 
-    m_phononWidget = new PhononWidget(parent);
-    m_phononWidget->hide();
-    m_phononWidget->setMinimumWidth(minPreviewWidth);
-    m_phononWidget->setAutoPlay(InformationPanelSettings::previewsAutoPlay());
-    connect(m_phononWidget, &PhononWidget::hasVideoChanged, this, &InformationPanelContent::slotHasVideoChanged);
+    m_mediaWidget = new MediaWidget(parent);
+    m_mediaWidget->hide();
+    m_mediaWidget->setMinimumWidth(minPreviewWidth);
+    m_mediaWidget->setAutoPlay(InformationPanelSettings::previewsAutoPlay());
+    connect(m_mediaWidget, &MediaWidget::hasVideoChanged, this, &InformationPanelContent::slotHasVideoChanged);
 
     // name
     m_nameLabel = new QLabel(parent);
@@ -132,7 +129,7 @@ InformationPanelContent::InformationPanelContent(QWidget *parent)
     viewport->installEventFilter(this);
 
     layout->addWidget(m_preview);
-    layout->addWidget(m_phononWidget);
+    layout->addWidget(m_mediaWidget);
     layout->addWidget(m_nameLabel);
     layout->addWidget(new KSeparator());
     layout->addWidget(m_configureLabel);
@@ -203,7 +200,7 @@ void InformationPanelContent::refreshPreview()
         const bool isSearchUrl = itemUrl.scheme().contains(QLatin1String("search")) && m_item.localPath().isEmpty();
         if (isSearchUrl) {
             m_preview->show();
-            m_phononWidget->hide();
+            m_mediaWidget->hide();
 
             // in the case of a search-URL the URL is not readable for humans
             // (at least not useful to show in the Information Panel)
@@ -219,16 +216,17 @@ void InformationPanelContent::refreshPreview()
             if (usePhonon) {
                 // change the cursor of the preview
                 m_preview->setCursor(Qt::PointingHandCursor);
-                m_preview->installEventFilter(m_phononWidget);
-                m_phononWidget->show();
+                m_preview->installEventFilter(m_mediaWidget);
+
+                m_mediaWidget->show();
 
                 // if the video is playing, has been paused or stopped
                 // we don't need to update the preview/phonon widget states
                 // unless the previewed file has changed,
                 // or the setting previewshown has changed
-                if ((m_phononWidget->state() != Phonon::State::PlayingState && m_phononWidget->state() != Phonon::State::PausedState
-                     && m_phononWidget->state() != Phonon::State::StoppedState)
-                    || m_item.targetUrl() != m_phononWidget->url() || (!m_preview->isVisible() && !m_phononWidget->isVisible())) {
+                if ((m_mediaWidget->state() != QMediaPlayer::PlayingState && m_mediaWidget->state() != QMediaPlayer::PausedState
+                     && m_mediaWidget->state() != QMediaPlayer::StoppedState)
+                    || m_item.targetUrl() != m_mediaWidget->url() || (!m_preview->isVisible() && !m_mediaWidget->isVisible())) {
                     if (InformationPanelSettings::previewsAutoPlay() && m_isVideo) {
                         // hides the preview now to avoid flickering when the autoplay video starts
                         m_preview->hide();
@@ -237,7 +235,7 @@ void InformationPanelContent::refreshPreview()
                         m_preview->show();
                     }
 
-                    m_phononWidget->setUrl(m_item.targetUrl(), m_isVideo ? PhononWidget::MediaKind::Video : PhononWidget::MediaKind::Audio);
+                    m_mediaWidget->setUrl(m_item.targetUrl(), m_isVideo ? MediaWidget::MediaKind::Video : MediaWidget::MediaKind::Audio);
                     adjustWidgetSizes(parentWidget()->width());
                 }
             } else {
@@ -245,16 +243,16 @@ void InformationPanelContent::refreshPreview()
                     m_preview->setAnimatedImageFileName(itemUrl.toLocalFile());
                 }
                 // When we don't need it, hide the phonon widget first to avoid flickering
-                m_phononWidget->hide();
+                m_mediaWidget->hide();
                 m_preview->show();
-                m_preview->removeEventFilter(m_phononWidget);
-                m_phononWidget->clearUrl();
+                m_preview->removeEventFilter(m_mediaWidget);
+                m_mediaWidget->clearUrl();
             }
         }
     } else {
         m_preview->stopAnimatedImage();
         m_preview->hide();
-        m_phononWidget->hide();
+        m_mediaWidget->hide();
     }
 }
 
@@ -287,7 +285,7 @@ void InformationPanelContent::showItems(const KFileItemList &items)
 
     m_metaDataWidget->setItems(items);
 
-    m_phononWidget->hide();
+    m_mediaWidget->hide();
 
     m_item = KFileItem();
 }
@@ -451,7 +449,7 @@ void InformationPanelContent::slotHasVideoChanged(bool hasVideo)
 
 void InformationPanelContent::setPreviewAutoPlay(bool autoPlay)
 {
-    m_phononWidget->setAutoPlay(autoPlay);
+    m_mediaWidget->setAutoPlay(autoPlay);
 }
 
 void InformationPanelContent::setNameLabelText(const QString &text)
@@ -502,9 +500,9 @@ void InformationPanelContent::adjustWidgetSizes(int width)
     // try to increase the preview as large as possible
     m_preview->setSizeHint(QSize(maxWidth, maxWidth));
 
-    if (m_phononWidget->isVisible()) {
+    if (m_mediaWidget->isVisible()) {
         // assure that the size of the video player is the same as the preview size
-        m_phononWidget->setVideoSize(QSize(maxWidth, maxWidth));
+        m_mediaWidget->setVideoSize(QSize(maxWidth, maxWidth));
     }
 }
 
index 0ea05d99038087c5b789bb3d8d220d6a2cb6d08a..333b2660879e6d3f70c53721a558d3c07981b6fa 100644 (file)
@@ -15,7 +15,7 @@
 #include <QWidget>
 
 class KFileItemList;
-class PhononWidget;
+class MediaWidget;
 class PixmapViewer;
 class QPixmap;
 class QDialogButtonBox;
@@ -145,7 +145,7 @@ private:
     QTimer *m_outdatedPreviewTimer;
 
     PixmapViewer *m_preview;
-    PhononWidget *m_phononWidget;
+    MediaWidget *m_mediaWidget;
     QLabel *m_nameLabel;
     Baloo::FileMetaDataWidget *m_metaDataWidget;
     QScrollArea *m_metaDataArea;
diff --git a/src/panels/information/mediawidget.cpp b/src/panels/information/mediawidget.cpp
new file mode 100644 (file)
index 0000000..345cb02
--- /dev/null
@@ -0,0 +1,368 @@
+/*
+  SPDX-FileCopyrightText: 2007 Matthias Kretz <kretz@kde.org>
+
+  SPDX-License-Identifier: GPL-2.0-or-later
+*/
+
+#include "mediawidget.h"
+
+#include <KLocalizedString>
+
+#include <QAudioOutput>
+#include <QMediaPlayer>
+#include <QVideoWidget>
+
+#include <QShowEvent>
+#include <QSlider>
+#include <QStyle>
+#include <QStyleOptionSlider>
+#include <QToolButton>
+#include <QVBoxLayout>
+
+class EmbeddedVideoPlayer : public QVideoWidget
+{
+    Q_OBJECT
+
+public:
+    EmbeddedVideoPlayer(QWidget *parent = nullptr)
+        : QVideoWidget(parent)
+    {
+    }
+
+    void setSizeHint(const QSize &size)
+    {
+        m_sizeHint = size;
+        updateGeometry();
+    }
+
+    QSize sizeHint() const override
+    {
+        return m_sizeHint.isValid() ? m_sizeHint : QVideoWidget::sizeHint();
+    }
+
+private:
+    QSize m_sizeHint;
+};
+
+class SeekSlider : public QSlider
+{
+    Q_OBJECT
+
+public:
+    SeekSlider(Qt::Orientation orientation, QWidget *parent = nullptr)
+        : QSlider(orientation, parent)
+    {
+    }
+
+protected:
+    // Function copied from qslider.cpp
+    inline int pick(const QPoint &pt) const
+    {
+        return orientation() == Qt::Horizontal ? pt.x() : pt.y();
+    }
+
+    // Function copied from qslider.cpp and modified to make it compile
+    int pixelPosToRangeValue(int pos) const
+    {
+        QStyleOptionSlider opt;
+        initStyleOption(&opt);
+        QRect gr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderGroove, this);
+        QRect sr = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
+        int sliderMin, sliderMax, sliderLength;
+
+        if (orientation() == Qt::Horizontal) {
+            sliderLength = sr.width();
+            sliderMin = gr.x();
+            sliderMax = gr.right() - sliderLength + 1;
+        } else {
+            sliderLength = sr.height();
+            sliderMin = gr.y();
+            sliderMax = gr.bottom() - sliderLength + 1;
+        }
+        return QStyle::sliderValueFromPosition(minimum(), maximum(), pos - sliderMin, sliderMax - sliderMin, opt.upsideDown);
+    }
+
+    // Based on code from qslider.cpp
+    void mousePressEvent(QMouseEvent *event) override
+    {
+        if (event->button() == Qt::LeftButton) {
+            QStyleOptionSlider opt;
+            initStyleOption(&opt);
+            const QRect sliderRect = style()->subControlRect(QStyle::CC_Slider, &opt, QStyle::SC_SliderHandle, this);
+            const QPoint center = sliderRect.center() - sliderRect.topLeft();
+            // to take half of the slider off for the setSliderPosition call we use the center - topLeft
+
+            if (!sliderRect.contains(event->pos())) {
+                event->accept();
+
+                int position = pixelPosToRangeValue(pick(event->pos() - center));
+                setSliderPosition(position);
+                triggerAction(SliderMove);
+                setRepeatAction(SliderNoAction);
+
+                Q_EMIT sliderMoved(position);
+            } else {
+                QSlider::mousePressEvent(event);
+            }
+        } else {
+            QSlider::mousePressEvent(event);
+        }
+    }
+};
+
+MediaWidget::MediaWidget(QWidget *parent)
+    : QWidget(parent)
+    , m_url()
+    , m_playButton(nullptr)
+    , m_pauseButton(nullptr)
+    , m_topLayout(nullptr)
+    , m_player(nullptr)
+    , m_seekSlider(nullptr)
+    , m_videoWidget(nullptr)
+{
+}
+
+void MediaWidget::setUrl(const QUrl &url, MediaKind kind)
+{
+    if (m_url != url) {
+        m_url = url;
+        m_isVideo = kind == MediaKind::Video;
+        m_seekSlider->setValue(0);
+    }
+    if (m_autoPlay) {
+        play();
+    } else {
+        stop();
+    }
+}
+
+void MediaWidget::setAutoPlay(bool autoPlay)
+{
+    m_autoPlay = autoPlay;
+    if (!m_url.isEmpty() && (m_player == nullptr || m_player->playbackState() != QMediaPlayer::PlayingState) && m_autoPlay && isVisible()) {
+        play();
+    }
+}
+
+QUrl MediaWidget::url() const
+{
+    return m_url;
+}
+
+void MediaWidget::clearUrl()
+{
+    m_url.clear();
+}
+
+void MediaWidget::togglePlayback()
+{
+    if (m_player && m_player->playbackState() == QMediaPlayer::PlayingState) {
+        m_player->pause();
+    } else {
+        play();
+    }
+}
+
+bool MediaWidget::eventFilter(QObject *object, QEvent *event)
+{
+    Q_UNUSED(object)
+    if (event->type() == QEvent::MouseButtonPress) {
+        const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
+        if (mouseEvent->button() == Qt::LeftButton) {
+            // toggle playback
+            togglePlayback();
+            return true;
+        }
+    }
+    return false;
+}
+
+void MediaWidget::setVideoSize(const QSize &size)
+{
+    if (m_videoSize != size) {
+        m_videoSize = size;
+        applyVideoSize();
+    }
+}
+
+QSize MediaWidget::videoSize() const
+{
+    return m_videoSize;
+}
+
+void MediaWidget::showEvent(QShowEvent *event)
+{
+    if (event->spontaneous()) {
+        QWidget::showEvent(event);
+        return;
+    }
+
+    if (!m_topLayout) {
+        m_topLayout = new QVBoxLayout(this);
+        m_topLayout->setContentsMargins(0, 0, 0, 0);
+
+        QHBoxLayout *controlsLayout = new QHBoxLayout();
+        controlsLayout->setContentsMargins(0, 0, 0, 0);
+        controlsLayout->setSpacing(0);
+
+        m_playButton = new QToolButton(this);
+        m_pauseButton = new QToolButton(this);
+        m_seekSlider = new SeekSlider(Qt::Orientation::Horizontal, this);
+        connect(m_seekSlider, &QAbstractSlider::sliderMoved, this, &MediaWidget::setPosition);
+
+        controlsLayout->addWidget(m_playButton);
+        controlsLayout->addWidget(m_pauseButton);
+        controlsLayout->addWidget(m_seekSlider);
+
+        m_topLayout->addLayout(controlsLayout);
+
+        const int smallIconSize = style()->pixelMetric(QStyle::PM_SmallIconSize);
+        const QSize buttonSize(smallIconSize, smallIconSize);
+
+        m_playButton->setToolTip(i18n("play"));
+        m_playButton->setIconSize(buttonSize);
+        m_playButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start")));
+        m_playButton->setAutoRaise(true);
+        connect(m_playButton, &QToolButton::clicked, this, &MediaWidget::play);
+
+        m_pauseButton->setToolTip(i18n("pause"));
+        m_pauseButton->setIconSize(buttonSize);
+        m_pauseButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-pause")));
+        m_pauseButton->setAutoRaise(true);
+        m_pauseButton->hide();
+        connect(m_pauseButton, &QToolButton::clicked, this, &MediaWidget::togglePlayback);
+
+        // Creating an audio player or video player instance might take up to
+        // 2 seconds when doing it the first time. To prevent that the user
+        // interface gets noticeable blocked, the creation is delayed until
+        // the play button has been pressed (see PhononWidget::play()).
+    }
+}
+
+void MediaWidget::hideEvent(QHideEvent *event)
+{
+    QWidget::hideEvent(event);
+    if (!event->spontaneous()) {
+        stop();
+    }
+}
+
+void MediaWidget::onStateChanged(QMediaPlayer::PlaybackState newState)
+{
+    setUpdatesEnabled(false);
+    switch (newState) {
+    case QMediaPlayer::PlaybackState::PlayingState:
+        m_playButton->hide();
+        m_pauseButton->show();
+        break;
+    default:
+        m_pauseButton->hide();
+        m_playButton->show();
+        break;
+    }
+    setUpdatesEnabled(true);
+}
+
+void MediaWidget::initPlayer()
+{
+    if (!m_player) {
+        m_player = new QMediaPlayer;
+        m_player->setAudioOutput(new QAudioOutput);
+
+        m_videoWidget = new EmbeddedVideoPlayer(this);
+        m_videoWidget->setCursor(Qt::PointingHandCursor);
+
+        m_videoWidget->installEventFilter(this);
+        m_player->setVideoOutput(m_videoWidget);
+        m_topLayout->insertWidget(0, m_videoWidget);
+
+        applyVideoSize();
+
+        connect(m_player, &QMediaPlayer::playbackStateChanged, this, &MediaWidget::onStateChanged);
+        connect(m_player, &QMediaPlayer::positionChanged, this, &MediaWidget::onPositionChanged);
+        connect(m_player, &QMediaPlayer::durationChanged, this, &MediaWidget::onDurationChanged);
+    }
+
+    if (m_url != m_player->source()) {
+        m_player->setSource(m_url);
+        m_seekSlider->setSliderPosition(0);
+    }
+
+    Q_EMIT hasVideoChanged(m_isVideo);
+
+    m_videoWidget->setVisible(m_isVideo);
+}
+
+void MediaWidget::play()
+{
+    initPlayer();
+
+    m_player->play();
+}
+
+void MediaWidget::finished()
+{
+    if (m_isVideo) {
+        m_videoWidget->hide();
+        Q_EMIT hasVideoChanged(false);
+    }
+}
+
+QMediaPlayer::PlaybackState MediaWidget::state() const
+{
+    return m_player == nullptr ? QMediaPlayer::PlaybackState::StoppedState : m_player->playbackState();
+}
+
+void MediaWidget::stop()
+{
+    if (m_player) {
+        m_player->stop();
+        m_videoWidget->hide();
+        Q_EMIT hasVideoChanged(false);
+    }
+}
+
+void MediaWidget::applyVideoSize()
+{
+    if ((m_videoWidget) && m_videoSize.isValid()) {
+        m_videoWidget->setSizeHint(m_videoSize);
+    }
+}
+
+void MediaWidget::setPosition(qint64 position)
+{
+    if (!m_player || m_player->playbackState() == QMediaPlayer::StoppedState) {
+        initPlayer();
+
+        auto prevDuration = m_seekSlider->maximum();
+
+        connect(
+            m_player,
+            &QMediaPlayer::mediaStatusChanged,
+            this,
+            [prevDuration, position, this](QMediaPlayer::MediaStatus status) {
+                if (status == QMediaPlayer::BufferedMedia) {
+                    m_player->setPosition(float(position) / prevDuration * m_player->duration());
+                    m_player->pause();
+                }
+            },
+            Qt::SingleShotConnection);
+
+        m_player->play();
+    } else {
+        m_player->setPosition(position);
+    }
+}
+
+void MediaWidget::onPositionChanged(qint64 position)
+{
+    m_seekSlider->setValue(static_cast<int>(position));
+}
+
+void MediaWidget::onDurationChanged(qint64 duration)
+{
+    m_seekSlider->setMaximum(static_cast<int>(duration));
+}
+
+#include "mediawidget.moc"
+#include "moc_mediawidget.cpp"
similarity index 70%
rename from src/panels/information/phononwidget.h
rename to src/panels/information/mediawidget.h
index a0a913b4fac746d47353848e4349be972893efb8..bd04266e6b3bd98e07b85ee91ba67fdcb0f4ccc4 100644 (file)
@@ -4,34 +4,30 @@
   SPDX-License-Identifier: GPL-2.0-or-later
 */
 
-#ifndef PHONONWIDGET_H
-#define PHONONWIDGET_H
-
-#include <phonon/Global>
+#ifndef MEDIAWIDGET_H
+#define MEDIAWIDGET_H
 
 #include <QSize>
+#include <QSlider>
 #include <QUrl>
 #include <QWidget>
 
-namespace Phonon
-{
-class AudioOutput;
-class MediaObject;
+#include <QMediaPlayer>
+
+class QMediaPlayer;
 class SeekSlider;
-class VideoPlayer;
-} // namespace Phonon
 
 class EmbeddedVideoPlayer;
 class QToolButton;
 class QVBoxLayout;
 
-class PhononWidget : public QWidget
+class MediaWidget : public QWidget
 {
     Q_OBJECT
 public:
     enum MediaKind { Video, Audio };
 
-    explicit PhononWidget(QWidget *parent = nullptr);
+    explicit MediaWidget(QWidget *parent = nullptr);
 
     void setUrl(const QUrl &url, MediaKind kind);
     QUrl url() const;
@@ -39,7 +35,7 @@ public:
 
     void setVideoSize(const QSize &size);
     QSize videoSize() const;
-    Phonon::State state() const;
+    QMediaPlayer::PlaybackState state() const;
 
     void setAutoPlay(bool autoPlay);
     bool eventFilter(QObject *object, QEvent *event) override;
@@ -63,15 +59,17 @@ protected:
     void hideEvent(QHideEvent *event) override;
 
 private Q_SLOTS:
-    void stateChanged(Phonon::State newstate);
     void stop();
     void finished();
+    void setPosition(qint64 position);
+    void onStateChanged(QMediaPlayer::PlaybackState newState);
+    void onPositionChanged(qint64 position);
+    void onDurationChanged(qint64 position);
 
 private:
     void applyVideoSize();
-
-private:
     void togglePlayback();
+    void initPlayer();
 
     QUrl m_url;
     QSize m_videoSize;
@@ -80,12 +78,11 @@ private:
     QToolButton *m_pauseButton;
 
     QVBoxLayout *m_topLayout;
-    Phonon::MediaObject *m_media;
-    Phonon::SeekSlider *m_seekSlider;
-    Phonon::AudioOutput *m_audioOutput;
-    EmbeddedVideoPlayer *m_videoPlayer;
+    QMediaPlayer *m_player;
+    QSlider *m_seekSlider;
+    EmbeddedVideoPlayer *m_videoWidget;
     bool m_autoPlay;
     bool m_isVideo;
 };
 
-#endif // PHONONWIDGET_H
+#endif // MEDIAWIDGET_H
diff --git a/src/panels/information/phononwidget.cpp b/src/panels/information/phononwidget.cpp
deleted file mode 100644 (file)
index 3365998..0000000
+++ /dev/null
@@ -1,265 +0,0 @@
-/*
-  SPDX-FileCopyrightText: 2007 Matthias Kretz <kretz@kde.org>
-
-  SPDX-License-Identifier: GPL-2.0-or-later
-*/
-
-#include "phononwidget.h"
-
-#include <KLocalizedString>
-#include <phonon/AudioOutput>
-#include <phonon/MediaObject>
-#include <phonon/SeekSlider>
-#include <phonon/VideoWidget>
-
-#include <QShowEvent>
-#include <QStyle>
-#include <QToolButton>
-#include <QVBoxLayout>
-
-class EmbeddedVideoPlayer : public Phonon::VideoWidget
-{
-    Q_OBJECT
-
-public:
-    EmbeddedVideoPlayer(QWidget *parent = nullptr)
-        : Phonon::VideoWidget(parent)
-    {
-    }
-
-    void setSizeHint(const QSize &size)
-    {
-        m_sizeHint = size;
-        updateGeometry();
-    }
-
-    QSize sizeHint() const override
-    {
-        return m_sizeHint.isValid() ? m_sizeHint : Phonon::VideoWidget::sizeHint();
-    }
-
-private:
-    QSize m_sizeHint;
-};
-
-PhononWidget::PhononWidget(QWidget *parent)
-    : QWidget(parent)
-    , m_url()
-    , m_playButton(nullptr)
-    , m_pauseButton(nullptr)
-    , m_topLayout(nullptr)
-    , m_media(nullptr)
-    , m_seekSlider(nullptr)
-    , m_audioOutput(nullptr)
-    , m_videoPlayer(nullptr)
-{
-}
-
-void PhononWidget::setUrl(const QUrl &url, MediaKind kind)
-{
-    if (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();
-    }
-}
-
-QUrl PhononWidget::url() const
-{
-    return m_url;
-}
-
-void PhononWidget::clearUrl()
-{
-    m_url.clear();
-}
-
-void PhononWidget::togglePlayback()
-{
-    if (m_media && m_media->state() == Phonon::State::PlayingState) {
-        m_media->pause();
-    } else {
-        play();
-    }
-}
-
-bool PhononWidget::eventFilter(QObject *object, QEvent *event)
-{
-    Q_UNUSED(object)
-    if (event->type() == QEvent::MouseButtonPress) {
-        const QMouseEvent *mouseEvent = static_cast<QMouseEvent *>(event);
-        if (mouseEvent->button() == Qt::LeftButton) {
-            // toggle playback
-            togglePlayback();
-            return true;
-        }
-    }
-    return false;
-}
-
-void PhononWidget::setVideoSize(const QSize &size)
-{
-    if (m_videoSize != size) {
-        m_videoSize = size;
-        applyVideoSize();
-    }
-}
-
-QSize PhononWidget::videoSize() const
-{
-    return m_videoSize;
-}
-
-void PhononWidget::showEvent(QShowEvent *event)
-{
-    if (event->spontaneous()) {
-        QWidget::showEvent(event);
-        return;
-    }
-
-    if (!m_topLayout) {
-        m_topLayout = new QVBoxLayout(this);
-        m_topLayout->setContentsMargins(0, 0, 0, 0);
-
-        QHBoxLayout *controlsLayout = new QHBoxLayout();
-        controlsLayout->setContentsMargins(0, 0, 0, 0);
-        controlsLayout->setSpacing(0);
-
-        m_playButton = new QToolButton(this);
-        m_pauseButton = new QToolButton(this);
-        m_seekSlider = new Phonon::SeekSlider(this);
-
-        controlsLayout->addWidget(m_playButton);
-        controlsLayout->addWidget(m_pauseButton);
-        controlsLayout->addWidget(m_seekSlider);
-
-        m_topLayout->addLayout(controlsLayout);
-
-        const int smallIconSize = style()->pixelMetric(QStyle::PM_SmallIconSize);
-        const QSize buttonSize(smallIconSize, smallIconSize);
-
-        m_playButton->setToolTip(i18n("play"));
-        m_playButton->setIconSize(buttonSize);
-        m_playButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start")));
-        m_playButton->setAutoRaise(true);
-        connect(m_playButton, &QToolButton::clicked, this, &PhononWidget::play);
-
-        m_pauseButton->setToolTip(i18n("pause"));
-        m_pauseButton->setIconSize(buttonSize);
-        m_pauseButton->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-pause")));
-        m_pauseButton->setAutoRaise(true);
-        m_pauseButton->hide();
-        connect(m_pauseButton, &QToolButton::clicked, this, &PhononWidget::togglePlayback);
-
-        m_seekSlider->setIconVisible(false);
-
-        // Creating an audio player or video player instance might take up to
-        // 2 seconds when doing it the first time. To prevent that the user
-        // interface gets noticeable blocked, the creation is delayed until
-        // the play button has been pressed (see PhononWidget::play()).
-    }
-}
-
-void PhononWidget::hideEvent(QHideEvent *event)
-{
-    QWidget::hideEvent(event);
-    if (!event->spontaneous()) {
-        stop();
-    }
-}
-
-void PhononWidget::stateChanged(Phonon::State newstate)
-{
-    setUpdatesEnabled(false);
-    switch (newstate) {
-    case Phonon::PlayingState:
-    case Phonon::BufferingState:
-        m_playButton->hide();
-        m_pauseButton->show();
-        break;
-    default:
-        m_pauseButton->hide();
-        m_playButton->show();
-        break;
-    }
-    setUpdatesEnabled(true);
-}
-
-void PhononWidget::play()
-{
-    if (!m_media) {
-        m_media = new Phonon::MediaObject(this);
-        connect(m_media, &Phonon::MediaObject::stateChanged, this, &PhononWidget::stateChanged);
-        connect(m_media, &Phonon::MediaObject::finished, this, &PhononWidget::finished);
-        m_seekSlider->setMediaObject(m_media);
-    }
-
-    if (!m_videoPlayer) {
-        m_videoPlayer = new EmbeddedVideoPlayer(this);
-        m_videoPlayer->setCursor(Qt::PointingHandCursor);
-        m_videoPlayer->installEventFilter(this);
-        m_topLayout->insertWidget(0, m_videoPlayer);
-        Phonon::createPath(m_media, m_videoPlayer);
-        applyVideoSize();
-    }
-
-    if (!m_audioOutput) {
-        m_audioOutput = new Phonon::AudioOutput(Phonon::MusicCategory, this);
-        Phonon::createPath(m_media, m_audioOutput);
-    }
-
-    if (m_isVideo) {
-        Q_EMIT hasVideoChanged(true);
-    }
-
-    if (m_url != m_media->currentSource().url()) {
-        m_media->setCurrentSource(m_url);
-    }
-    m_media->play();
-
-    m_videoPlayer->setVisible(m_isVideo);
-}
-
-void PhononWidget::finished()
-{
-    if (m_isVideo) {
-        m_videoPlayer->hide();
-        Q_EMIT hasVideoChanged(false);
-    }
-}
-
-Phonon::State PhononWidget::state() const
-{
-    return m_media == nullptr ? Phonon::State::StoppedState : m_media->state();
-}
-
-void PhononWidget::stop()
-{
-    if (m_media) {
-        m_media->stop();
-        m_videoPlayer->hide();
-        Q_EMIT hasVideoChanged(false);
-    }
-}
-
-void PhononWidget::applyVideoSize()
-{
-    if ((m_videoPlayer) && m_videoSize.isValid()) {
-        m_videoPlayer->setSizeHint(m_videoSize);
-    }
-}
-
-#include "moc_phononwidget.cpp"
-#include "phononwidget.moc"