]>
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>
22 class EmbeddedVideoPlayer
: public QVideoWidget
27 EmbeddedVideoPlayer(QWidget
*parent
= nullptr)
28 : QVideoWidget(parent
)
32 void setSizeHint(const QSize
&size
)
38 QSize
sizeHint() const override
40 return m_sizeHint
.isValid() ? m_sizeHint
: QVideoWidget::sizeHint();
47 class SeekSlider
: public QSlider
52 SeekSlider(Qt::Orientation orientation
, QWidget
*parent
= nullptr)
53 : QSlider(orientation
, parent
)
58 // Function copied from qslider.cpp
59 inline int pick(const QPoint
&pt
) const
61 return orientation() == Qt::Horizontal
? pt
.x() : pt
.y();
64 // Function copied from qslider.cpp and modified to make it compile
65 int pixelPosToRangeValue(int pos
) const
67 QStyleOptionSlider opt
;
68 initStyleOption(&opt
);
69 QRect gr
= style()->subControlRect(QStyle::CC_Slider
, &opt
, QStyle::SC_SliderGroove
, this);
70 QRect sr
= style()->subControlRect(QStyle::CC_Slider
, &opt
, QStyle::SC_SliderHandle
, this);
71 int sliderMin
, sliderMax
, sliderLength
;
73 if (orientation() == Qt::Horizontal
) {
74 sliderLength
= sr
.width();
76 sliderMax
= gr
.right() - sliderLength
+ 1;
78 sliderLength
= sr
.height();
80 sliderMax
= gr
.bottom() - sliderLength
+ 1;
82 return QStyle::sliderValueFromPosition(minimum(), maximum(), pos
- sliderMin
, sliderMax
- sliderMin
, opt
.upsideDown
);
85 // Based on code from qslider.cpp
86 void mousePressEvent(QMouseEvent
*event
) override
88 if (event
->button() == Qt::LeftButton
) {
89 QStyleOptionSlider opt
;
90 initStyleOption(&opt
);
91 const QRect sliderRect
= style()->subControlRect(QStyle::CC_Slider
, &opt
, QStyle::SC_SliderHandle
, this);
92 const QPoint center
= sliderRect
.center() - sliderRect
.topLeft();
93 // to take half of the slider off for the setSliderPosition call we use the center - topLeft
95 if (!sliderRect
.contains(event
->pos())) {
98 int position
= pixelPosToRangeValue(pick(event
->pos() - center
));
99 setSliderPosition(position
);
100 triggerAction(SliderMove
);
101 setRepeatAction(SliderNoAction
);
103 Q_EMIT
sliderMoved(position
);
105 QSlider::mousePressEvent(event
);
108 QSlider::mousePressEvent(event
);
112 void keyPressEvent(QKeyEvent
*event
) override
114 int newPosition
= -1;
115 if (event
->key() == Qt::Key_Right
) {
117 newPosition
= std::min(maximum(), sliderPosition() + maximum() / 100);
118 } else if (event
->key() == Qt::Key_Left
) {
120 newPosition
= std::max(0, sliderPosition() - maximum() / 100);
123 if (newPosition
!= -1) {
126 if (newPosition
!= sliderPosition()) {
127 setSliderPosition(newPosition
);
128 triggerAction(SliderMove
);
129 setRepeatAction(SliderNoAction
);
131 Q_EMIT
sliderMoved(newPosition
);
134 QSlider::keyPressEvent(event
);
139 MediaWidget::MediaWidget(QWidget
*parent
)
142 , m_playButton(nullptr)
143 , m_pauseButton(nullptr)
144 , m_topLayout(nullptr)
146 , m_seekSlider(nullptr)
147 , m_videoWidget(nullptr)
151 void MediaWidget::setUrl(const QUrl
&url
, MediaKind kind
)
155 m_isVideo
= kind
== MediaKind::Video
;
156 m_seekSlider
->setValue(0);
165 void MediaWidget::setAutoPlay(bool autoPlay
)
167 m_autoPlay
= autoPlay
;
168 if (!m_url
.isEmpty() && (m_player
== nullptr || m_player
->playbackState() != QMediaPlayer::PlayingState
) && m_autoPlay
&& isVisible()) {
173 QUrl
MediaWidget::url() const
178 void MediaWidget::clearUrl()
183 void MediaWidget::togglePlayback()
185 if (m_player
&& m_player
->playbackState() == QMediaPlayer::PlayingState
) {
192 bool MediaWidget::eventFilter(QObject
*object
, QEvent
*event
)
195 if (event
->type() == QEvent::MouseButtonPress
) {
196 const QMouseEvent
*mouseEvent
= static_cast<QMouseEvent
*>(event
);
197 if (mouseEvent
->button() == Qt::LeftButton
) {
206 void MediaWidget::setVideoSize(const QSize
&size
)
208 if (m_videoSize
!= size
) {
214 QSize
MediaWidget::videoSize() const
219 void MediaWidget::showEvent(QShowEvent
*event
)
221 if (event
->spontaneous()) {
222 QWidget::showEvent(event
);
227 m_topLayout
= new QVBoxLayout(this);
228 m_topLayout
->setContentsMargins(0, 0, 0, 0);
230 QHBoxLayout
*controlsLayout
= new QHBoxLayout();
231 controlsLayout
->setContentsMargins(0, 0, 0, 0);
232 controlsLayout
->setSpacing(0);
234 m_playButton
= new QToolButton(this);
235 m_pauseButton
= new QToolButton(this);
236 m_seekSlider
= new SeekSlider(Qt::Orientation::Horizontal
, this);
237 connect(m_seekSlider
, &QAbstractSlider::sliderMoved
, this, &MediaWidget::setPosition
);
239 controlsLayout
->addWidget(m_playButton
);
240 controlsLayout
->addWidget(m_pauseButton
);
241 controlsLayout
->addWidget(m_seekSlider
);
243 m_topLayout
->addLayout(controlsLayout
);
245 const int smallIconSize
= style()->pixelMetric(QStyle::PM_SmallIconSize
);
246 const QSize
buttonSize(smallIconSize
, smallIconSize
);
248 m_playButton
->setToolTip(i18n("play"));
249 m_playButton
->setIconSize(buttonSize
);
250 m_playButton
->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-start")));
251 m_playButton
->setAutoRaise(true);
252 connect(m_playButton
, &QToolButton::clicked
, this, &MediaWidget::play
);
254 m_pauseButton
->setToolTip(i18n("pause"));
255 m_pauseButton
->setIconSize(buttonSize
);
256 m_pauseButton
->setIcon(QIcon::fromTheme(QStringLiteral("media-playback-pause")));
257 m_pauseButton
->setAutoRaise(true);
258 m_pauseButton
->hide();
259 connect(m_pauseButton
, &QToolButton::clicked
, this, &MediaWidget::togglePlayback
);
263 void MediaWidget::hideEvent(QHideEvent
*event
)
265 QWidget::hideEvent(event
);
266 if (!event
->spontaneous()) {
271 void MediaWidget::onStateChanged(QMediaPlayer::PlaybackState newState
)
273 setUpdatesEnabled(false);
275 case QMediaPlayer::PlaybackState::PlayingState
:
276 m_playButton
->hide();
277 m_pauseButton
->show();
280 m_pauseButton
->hide();
281 m_playButton
->show();
284 setUpdatesEnabled(true);
287 void MediaWidget::initPlayer()
290 m_player
= new QMediaPlayer
;
291 m_player
->setAudioOutput(new QAudioOutput
);
293 m_videoWidget
= new EmbeddedVideoPlayer(this);
294 m_videoWidget
->setCursor(Qt::PointingHandCursor
);
296 m_videoWidget
->installEventFilter(this);
297 m_player
->setVideoOutput(m_videoWidget
);
298 m_topLayout
->insertWidget(0, m_videoWidget
);
302 connect(m_player
, &QMediaPlayer::playbackStateChanged
, this, &MediaWidget::onStateChanged
);
303 connect(m_player
, &QMediaPlayer::positionChanged
, this, &MediaWidget::onPositionChanged
);
304 connect(m_player
, &QMediaPlayer::durationChanged
, this, &MediaWidget::onDurationChanged
);
307 if (m_url
!= m_player
->source()) {
308 m_player
->setSource(m_url
);
309 m_seekSlider
->setSliderPosition(0);
312 Q_EMIT
hasVideoChanged(m_isVideo
);
314 m_videoWidget
->setVisible(m_isVideo
);
317 void MediaWidget::play()
324 void MediaWidget::finished()
327 m_videoWidget
->hide();
328 Q_EMIT
hasVideoChanged(false);
332 QMediaPlayer::PlaybackState
MediaWidget::state() const
334 return m_player
== nullptr ? QMediaPlayer::PlaybackState::StoppedState
: m_player
->playbackState();
337 void MediaWidget::stop()
341 m_videoWidget
->hide();
342 Q_EMIT
hasVideoChanged(false);
346 void MediaWidget::applyVideoSize()
348 if ((m_videoWidget
) && m_videoSize
.isValid()) {
349 m_videoWidget
->setSizeHint(m_videoSize
);
353 void MediaWidget::setPosition(qint64 position
)
355 if (!m_player
|| m_player
->playbackState() == QMediaPlayer::StoppedState
) {
358 auto prevDuration
= m_seekSlider
->maximum();
362 &QMediaPlayer::mediaStatusChanged
,
364 [prevDuration
, position
, this](QMediaPlayer::MediaStatus status
) {
365 if (status
== QMediaPlayer::BufferedMedia
) {
366 m_player
->setPosition(float(position
) / prevDuration
* m_player
->duration());
370 Qt::SingleShotConnection
);
374 m_player
->setPosition(position
);
378 void MediaWidget::onPositionChanged(qint64 position
)
380 m_seekSlider
->setValue(static_cast<int>(position
));
383 void MediaWidget::onDurationChanged(qint64 duration
)
385 m_seekSlider
->setMaximum(static_cast<int>(duration
));
388 #include "mediawidget.moc"
389 #include "moc_mediawidget.cpp"