]>
cloud.milkyroute.net Git - dolphin.git/blob - src/panels/information/mediawidget.cpp
2 SPDX-FileCopyrightText: 2007 Matthias Kretz <kretz@kde.org>
4 SPDX-License-Identifier: GPL-2.0-or-later
7 #include "mediawidget.h"
9 #include <KLocalizedString>
11 #include <QAudioOutput>
12 #include <QMediaPlayer>
13 #include <QVideoWidget>
18 #include <QStyleOptionSlider>
19 #include <QToolButton>
20 #include <QVBoxLayout>
21 #include <qnamespace.h>
24 class EmbeddedVideoPlayer
: public QVideoWidget
29 EmbeddedVideoPlayer(QWidget
*parent
= nullptr)
30 : QVideoWidget(parent
)
34 void setSizeHint(const QSize
&size
)
40 QSize
sizeHint() const override
42 return m_sizeHint
.isValid() ? m_sizeHint
: QVideoWidget::sizeHint();
49 class SeekSlider
: public QSlider
54 SeekSlider(Qt::Orientation orientation
, QWidget
*parent
= nullptr)
55 : QSlider(orientation
, parent
)
60 // Function copied from qslider.cpp
61 inline int pick(const QPoint
&pt
) const
63 return orientation() == Qt::Horizontal
? pt
.x() : pt
.y();
66 // Function copied from qslider.cpp and modified to make it compile
67 int pixelPosToRangeValue(int pos
) const
69 QStyleOptionSlider opt
;
70 initStyleOption(&opt
);
71 QRect gr
= style()->subControlRect(QStyle::CC_Slider
, &opt
, QStyle::SC_SliderGroove
, this);
72 QRect sr
= style()->subControlRect(QStyle::CC_Slider
, &opt
, QStyle::SC_SliderHandle
, this);
73 int sliderMin
, sliderMax
, sliderLength
;
75 if (orientation() == Qt::Horizontal
) {
76 sliderLength
= sr
.width();
78 sliderMax
= gr
.right() - sliderLength
+ 1;
80 sliderLength
= sr
.height();
82 sliderMax
= gr
.bottom() - sliderLength
+ 1;
84 return QStyle::sliderValueFromPosition(minimum(), maximum(), pos
- sliderMin
, sliderMax
- sliderMin
, opt
.upsideDown
);
87 // Based on code from qslider.cpp
88 void mousePressEvent(QMouseEvent
*event
) override
90 if (event
->button() == Qt::LeftButton
) {
91 QStyleOptionSlider opt
;
92 initStyleOption(&opt
);
93 const QRect sliderRect
= style()->subControlRect(QStyle::CC_Slider
, &opt
, QStyle::SC_SliderHandle
, this);
94 const QPoint center
= sliderRect
.center() - sliderRect
.topLeft();
95 // to take half of the slider off for the setSliderPosition call we use the center - topLeft
97 if (!sliderRect
.contains(event
->pos())) {
100 int position
= pixelPosToRangeValue(pick(event
->pos() - center
));
101 setSliderPosition(position
);
102 triggerAction(SliderMove
);
103 setRepeatAction(SliderNoAction
);
105 Q_EMIT
sliderMoved(position
);
107 QSlider::mousePressEvent(event
);
110 QSlider::mousePressEvent(event
);
114 void keyPressEvent(QKeyEvent
*event
) override
116 int newPosition
= -1;
117 if (event
->key() == Qt::Key_Right
) {
119 newPosition
= std::min(maximum(), sliderPosition() + maximum() / 100);
120 } else if (event
->key() == Qt::Key_Left
) {
122 newPosition
= std::max(0, sliderPosition() - maximum() / 100);
125 if (newPosition
!= -1) {
128 if (newPosition
!= sliderPosition()) {
129 setSliderPosition(newPosition
);
130 triggerAction(SliderMove
);
131 setRepeatAction(SliderNoAction
);
133 Q_EMIT
sliderMoved(newPosition
);
136 QSlider::keyPressEvent(event
);
141 MediaWidget::MediaWidget(QWidget
*parent
)
144 , m_playButton(nullptr)
145 , m_pauseButton(nullptr)
146 , m_topLayout(nullptr)
148 , m_seekSlider(nullptr)
149 , m_videoWidget(nullptr)
153 void MediaWidget::setUrl(const QUrl
&url
, MediaKind kind
)
157 m_isVideo
= kind
== MediaKind::Video
;
158 m_seekSlider
->setValue(0);
167 void MediaWidget::setAutoPlay(bool autoPlay
)
169 m_autoPlay
= autoPlay
;
170 if (!m_url
.isEmpty() && (m_player
== nullptr || m_player
->playbackState() != QMediaPlayer::PlayingState
) && m_autoPlay
&& isVisible()) {
175 QUrl
MediaWidget::url() const
180 void MediaWidget::clearUrl()
185 void MediaWidget::togglePlayback()
187 if (m_player
&& m_player
->playbackState() == QMediaPlayer::PlayingState
) {
194 bool MediaWidget::eventFilter(QObject
*object
, QEvent
*event
)
197 if (event
->type() == QEvent::MouseButtonPress
) {
198 const QMouseEvent
*mouseEvent
= static_cast<QMouseEvent
*>(event
);
199 if (mouseEvent
->button() == Qt::LeftButton
) {
208 void MediaWidget::setVideoSize(const QSize
&size
)
210 if (m_videoSize
!= size
) {
216 QSize
MediaWidget::videoSize() const
221 void MediaWidget::showEvent(QShowEvent
*event
)
223 if (event
->spontaneous()) {
224 QWidget::showEvent(event
);
229 m_topLayout
= new QVBoxLayout(this);
230 m_topLayout
->setContentsMargins(0, 0, 0, 0);
232 QHBoxLayout
*controlsLayout
= new QHBoxLayout();
233 controlsLayout
->setContentsMargins(0, 0, 0, 0);
234 controlsLayout
->setSpacing(0);
236 m_playButton
= new QToolButton(this);
237 m_pauseButton
= new QToolButton(this);
238 m_seekSlider
= new SeekSlider(Qt::Orientation::Horizontal
, this);
239 connect(m_seekSlider
, &QAbstractSlider::sliderMoved
, this, &MediaWidget::setPosition
);
241 controlsLayout
->addWidget(m_playButton
);
242 controlsLayout
->addWidget(m_pauseButton
);
243 controlsLayout
->addWidget(m_seekSlider
);
245 m_topLayout
->addLayout(controlsLayout
);
247 const int smallIconSize
= style()->pixelMetric(QStyle::PM_SmallIconSize
);
248 const QSize
buttonSize(smallIconSize
, smallIconSize
);
250 m_playButton
->setToolTip(i18n("play"));
251 m_playButton
->setIconSize(buttonSize
);
252 m_playButton
->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start")));
253 m_playButton
->setAutoRaise(true);
254 connect(m_playButton
, &QToolButton::clicked
, this, &MediaWidget::play
);
256 m_pauseButton
->setToolTip(i18n("pause"));
257 m_pauseButton
->setIconSize(buttonSize
);
258 m_pauseButton
->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-pause")));
259 m_pauseButton
->setAutoRaise(true);
260 m_pauseButton
->hide();
261 connect(m_pauseButton
, &QToolButton::clicked
, this, &MediaWidget::togglePlayback
);
265 void MediaWidget::hideEvent(QHideEvent
*event
)
267 QWidget::hideEvent(event
);
268 if (!event
->spontaneous()) {
273 void MediaWidget::onStateChanged(QMediaPlayer::PlaybackState newState
)
275 setUpdatesEnabled(false);
277 case QMediaPlayer::PlaybackState::PlayingState
:
278 m_playButton
->hide();
279 m_pauseButton
->show();
282 m_pauseButton
->hide();
283 m_playButton
->show();
286 setUpdatesEnabled(true);
289 void MediaWidget::initPlayer()
292 m_player
= new QMediaPlayer
;
293 m_player
->setAudioOutput(new QAudioOutput
);
295 m_videoWidget
= new EmbeddedVideoPlayer(this);
296 m_videoWidget
->setCursor(Qt::PointingHandCursor
);
298 m_videoWidget
->installEventFilter(this);
299 m_player
->setVideoOutput(m_videoWidget
);
300 m_topLayout
->insertWidget(0, m_videoWidget
);
304 connect(m_player
, &QMediaPlayer::playbackStateChanged
, this, &MediaWidget::onStateChanged
);
305 connect(m_player
, &QMediaPlayer::positionChanged
, this, &MediaWidget::onPositionChanged
);
306 connect(m_player
, &QMediaPlayer::durationChanged
, this, &MediaWidget::onDurationChanged
);
309 if (m_url
!= m_player
->source()) {
310 m_player
->setSource(m_url
);
311 m_seekSlider
->setSliderPosition(0);
314 Q_EMIT
hasVideoChanged(m_isVideo
);
316 m_videoWidget
->setVisible(m_isVideo
);
319 void MediaWidget::play()
326 void MediaWidget::finished()
329 m_videoWidget
->hide();
330 Q_EMIT
hasVideoChanged(false);
334 QMediaPlayer::PlaybackState
MediaWidget::state() const
336 return m_player
== nullptr ? QMediaPlayer::PlaybackState::StoppedState
: m_player
->playbackState();
339 void MediaWidget::stop()
343 m_videoWidget
->hide();
344 Q_EMIT
hasVideoChanged(false);
348 void MediaWidget::applyVideoSize()
350 if ((m_videoWidget
) && m_videoSize
.isValid()) {
351 m_videoWidget
->setSizeHint(m_videoSize
);
355 void MediaWidget::setPosition(qint64 position
)
357 if (!m_player
|| m_player
->playbackState() == QMediaPlayer::StoppedState
) {
360 auto prevDuration
= m_seekSlider
->maximum();
364 &QMediaPlayer::mediaStatusChanged
,
366 [prevDuration
, position
, this](QMediaPlayer::MediaStatus status
) {
367 if (status
== QMediaPlayer::BufferedMedia
) {
368 m_player
->setPosition(float(position
) / prevDuration
* m_player
->duration());
372 Qt::SingleShotConnection
);
376 m_player
->setPosition(position
);
380 void MediaWidget::onPositionChanged(qint64 position
)
382 m_seekSlider
->setValue(static_cast<int>(position
));
385 void MediaWidget::onDurationChanged(qint64 duration
)
387 m_seekSlider
->setMaximum(static_cast<int>(duration
));
390 #include "mediawidget.moc"
391 #include "moc_mediawidget.cpp"