00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "videowidget.h"
00021
00022 #include <QUrl>
00023 #include <QTimer>
00024 #include <QGraphicsLinearLayout>
00025 #include <QGraphicsSceneResizeEvent>
00026
00027 #include <kicon.h>
00028 #include <kfiledialog.h>
00029
00030 #include <phonon/videowidget.h>
00031 #include <phonon/mediaobject.h>
00032 #include <phonon/mediasource.h>
00033 #include <phonon/audiooutput.h>
00034
00035 #include <plasma/widgets/iconwidget.h>
00036 #include <plasma/widgets/slider.h>
00037 #include <plasma/widgets/frame.h>
00038
00039 namespace Plasma
00040 {
00041
00042 class VideoWidgetPrivate
00043 {
00044 public:
00045 VideoWidgetPrivate(VideoWidget *video)
00046 : q(video),
00047 ticking(false),
00048 forceControlsVisible(false),
00049 animId(0),
00050 hideTimer(0),
00051 shownControls(VideoWidget::NoControls),
00052 controlsWidget(0),
00053 previousButton(0),
00054 playButton(0),
00055 pauseButton(0),
00056 stopButton(0),
00057 playPauseButton(0),
00058 nextButton(0),
00059 progress(0),
00060 volume(0),
00061 openFileButton(0)
00062 {
00063 }
00064
00065 ~VideoWidgetPrivate()
00066 {
00067 }
00068
00069 void playPause();
00070 void ticked(qint64 progress);
00071 void totalTimeChanged(qint64 time);
00072 void setPosition(int newProgress);
00073 void setVolume(int value);
00074 void volumeChanged(qreal value);
00075 void showOpenFileDialog();
00076 void openFile(const QString &path);
00077 void stateChanged(Phonon::State newState, Phonon::State oldState);
00078 void animateControlWidget(bool show);
00079 void hideControlWidget();
00080 void slidingCompleted(QGraphicsItem *item);
00081 bool spaceForControlsAvailable();
00082
00083
00084 VideoWidget *q;
00085
00086 Phonon::VideoWidget *videoWidget;
00087 Phonon::AudioOutput *audioOutput;
00088 Phonon::MediaObject *media;
00089
00090 bool ticking;
00091 bool forceControlsVisible;
00092
00093
00094 int animId;
00095 QTimer *hideTimer;
00096 VideoWidget::Controls shownControls;
00097 Plasma::Frame *controlsWidget;
00098 IconWidget *previousButton;
00099 IconWidget *playButton;
00100 IconWidget *pauseButton;
00101 IconWidget *stopButton;
00102 IconWidget *playPauseButton;
00103 IconWidget *nextButton;
00104 Slider *progress;
00105 Slider *volume;
00106 IconWidget *openFileButton;
00107 };
00108
00109 void VideoWidgetPrivate::playPause()
00110 {
00111 if (media->state() == Phonon::PlayingState) {
00112 media->pause();
00113 } else {
00114 media->play();
00115 }
00116 }
00117
00118 void VideoWidgetPrivate::ticked(qint64 newProgress)
00119 {
00120 ticking = true;
00121 progress->setValue(newProgress);
00122 ticking = false;
00123 }
00124
00125 void VideoWidgetPrivate::totalTimeChanged(qint64 time)
00126 {
00127 ticking = true;
00128
00129 progress->setRange(0, time);
00130 ticking = false;
00131 }
00132
00133 void VideoWidgetPrivate::setPosition(int progress)
00134 {
00135 if (!ticking) {
00136 media->seek(progress);
00137 }
00138 }
00139
00140 void VideoWidgetPrivate::setVolume(int value)
00141 {
00142 audioOutput->setVolume(qreal(value)/100.0);
00143 }
00144
00145 void VideoWidgetPrivate::volumeChanged(qreal value)
00146 {
00147 volume->setValue(value*100);
00148 }
00149
00150 void VideoWidgetPrivate::showOpenFileDialog()
00151 {
00152 openFile(KFileDialog::getOpenFileName());
00153 }
00154
00155 void VideoWidgetPrivate::openFile(const QString &path)
00156 {
00157 media->setCurrentSource(Phonon::MediaSource(path));
00158 media->play();
00159 }
00160
00161 void VideoWidgetPrivate::stateChanged(Phonon::State newState, Phonon::State oldState)
00162 {
00163 Q_UNUSED(oldState)
00164
00165 if (playPauseButton) {
00166 if (newState == Phonon::PlayingState) {
00167 playPauseButton->setIcon("media-playback-pause");
00168 } else {
00169 playPauseButton->setIcon("media-playback-start");
00170 }
00171 }
00172 }
00173
00174 void VideoWidgetPrivate::animateControlWidget(bool show)
00175 {
00176 if (!controlsWidget || controlsWidget->isVisible() == show) {
00177 return;
00178 }
00179
00180 QPoint oldPos(0,0);
00181 QPoint newPos(0,0);
00182
00183 if (show) {
00184 oldPos = QPoint(0, -controlsWidget->size().height());
00185 } else {
00186 newPos = QPoint(0, -controlsWidget->size().height());
00187 }
00188
00189
00190 q->setFlags(q->flags()|QGraphicsItem::ItemClipsChildrenToShape);
00191
00192 controlsWidget->setPos(oldPos);
00193 controlsWidget->show();
00194
00195 animId = Animator::self()->moveItem(
00196 controlsWidget, Plasma::Animator::SlideOutMovement,
00197 newPos);
00198 }
00199
00200 void VideoWidgetPrivate::hideControlWidget()
00201 {
00202 animateControlWidget(false);
00203 }
00204
00205 void VideoWidgetPrivate::slidingCompleted(QGraphicsItem *item)
00206 {
00207 Q_UNUSED(item)
00208
00209 animId = 0;
00210
00211 if (!controlsWidget) {
00212 return;
00213 }
00214
00215
00216 q->setFlags(q->flags()^QGraphicsItem::ItemClipsChildrenToShape);
00217
00218 if (controlsWidget->pos().y() < 0) {
00219 controlsWidget->hide();
00220 } else if (!forceControlsVisible) {
00221 hideTimer->start(3000);
00222 }
00223 }
00224
00225 bool VideoWidgetPrivate::spaceForControlsAvailable()
00226 {
00227 if (controlsWidget) {
00228 QSize hint = controlsWidget->effectiveSizeHint(Qt::MinimumSize).toSize();
00229 return (q->size().width() >= hint.width()) &&
00230 (q->size().height() >= hint.height());
00231 } else {
00232 return true;
00233 }
00234 }
00235
00236
00237
00238 VideoWidget::VideoWidget(QGraphicsWidget *parent)
00239 : QGraphicsProxyWidget(parent),
00240 d(new VideoWidgetPrivate(this))
00241 {
00242 d->videoWidget = new Phonon::VideoWidget;
00243 d->audioOutput = new Phonon::AudioOutput(this);
00244 d->media = new Phonon::MediaObject(this);
00245
00246 Phonon::createPath(d->media, d->videoWidget);
00247 Phonon::createPath(d->media, d->audioOutput);
00248
00249
00250 setWidget(d->videoWidget);
00251 setAcceptHoverEvents(true);
00252
00253 connect(d->media, SIGNAL(tick(qint64)), this, SIGNAL(tick(qint64)));
00254 connect(d->media, SIGNAL(aboutToFinish()), this, SIGNAL(aboutToFinish()));
00255 connect(Plasma::Animator::self(), SIGNAL(movementFinished(QGraphicsItem*)),
00256 this, SLOT(slidingCompleted(QGraphicsItem*)));
00257 }
00258
00259 VideoWidget::~VideoWidget()
00260 {
00261 delete d;
00262 }
00263
00264 Phonon::MediaObject *VideoWidget::mediaObject() const
00265 {
00266 return d->media;
00267 }
00268
00269 Phonon::AudioOutput *VideoWidget::audioOutput() const
00270 {
00271 return d->audioOutput;
00272 }
00273
00274 void VideoWidget::setUrl(const QString &url)
00275 {
00276 d->media->setCurrentSource(Phonon::MediaSource(url));
00277 }
00278
00279 QString VideoWidget::url() const
00280 {
00281 return d->media->currentSource().url().toString();
00282 }
00283
00284 void VideoWidget::setUsedControls(const Controls controls)
00285 {
00286 d->shownControls = controls;
00287
00288
00289
00290 QGraphicsLinearLayout *controlsLayout = 0;
00291 if (controls != NoControls && d->controlsWidget == 0) {
00292 d->controlsWidget = new Plasma::Frame(this);
00293 d->controlsWidget->setFrameShadow(Plasma::Frame::Raised);
00294 controlsLayout = new QGraphicsLinearLayout(Qt::Horizontal, d->controlsWidget);
00295 d->hideTimer = new QTimer(this);
00296 connect(d->hideTimer, SIGNAL(timeout()), this, SLOT(hideControlWidget()));
00297
00298 } else if (d->controlsWidget != 0) {
00299 d->controlsWidget->deleteLater();
00300 d->hideTimer->deleteLater();
00301 d->controlsWidget = 0;
00302
00303
00304 disconnect(d->media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged(Phonon::State, Phonon::State)));
00305 disconnect(d->media, SIGNAL(tick(qint64)), this, SLOT(ticked(qint64)));
00306 disconnect(d->media, SIGNAL(totalTimeChanged(qint64)), this, SLOT(totalTimeChanged(qint64)));
00307 disconnect(d->audioOutput, SIGNAL(volumeChanged(qreal)), this, SLOT(volumeChanged(qreal)));
00308 return;
00309 }
00310
00311 Q_ASSERT(controlsLayout);
00312
00313
00314 while (controlsLayout->count() > 0) {
00315 controlsLayout->removeAt(0);
00316 }
00317
00318 if (controls&Previous) {
00319 if (!d->previousButton) {
00320 d->previousButton = new IconWidget(d->controlsWidget);
00321 d->previousButton->setIcon("media-playback-start");
00322 connect(d->playButton, SIGNAL(clicked()), this, SLOT(PreviousRequested()));
00323 }
00324 controlsLayout->addItem(d->previousButton);
00325 } else {
00326 d->previousButton->deleteLater();
00327 d->previousButton = 0;
00328 }
00329
00330 if (controls&Play) {
00331 if (!d->playButton) {
00332 d->playButton = new IconWidget(d->controlsWidget);
00333 d->playButton->setIcon("media-playback-start");
00334 connect(d->playButton, SIGNAL(clicked()), this, SLOT(play()));
00335 }
00336 controlsLayout->addItem(d->playButton);
00337 } else {
00338 d->playButton->deleteLater();
00339 d->playButton = 0;
00340 }
00341
00342 if (controls&Pause) {
00343 if (!d->pauseButton) {
00344 d->pauseButton = new IconWidget(d->controlsWidget);
00345 d->pauseButton->setIcon("media-playback-pause");
00346 connect(d->pauseButton, SIGNAL(clicked()), this, SLOT(pause()));
00347 }
00348 controlsLayout->addItem(d->pauseButton);
00349 } else {
00350 d->pauseButton->deleteLater();
00351 d->pauseButton = 0;
00352 }
00353
00354 if (controls&Stop) {
00355 if (!d->stopButton) {
00356 d->stopButton = new IconWidget(d->controlsWidget);
00357 d->stopButton->setIcon("media-playback-stop");
00358 connect(d->stopButton, SIGNAL(clicked()), this, SLOT(stop()));
00359 }
00360 controlsLayout->addItem(d->stopButton);
00361 } else {
00362 d->stopButton->deleteLater();
00363 d->stopButton = 0;
00364 }
00365
00366 if (controls&PlayPause) {
00367 if (!d->playPauseButton) {
00368 d->playPauseButton = new IconWidget(d->controlsWidget);
00369 d->playPauseButton->setIcon("media-playback-start");
00370 connect(d->playPauseButton, SIGNAL(clicked()), this, SLOT(playPause()));
00371 }
00372 controlsLayout->addItem(d->playPauseButton);
00373 } else {
00374 d->playPauseButton->deleteLater();
00375 d->playPauseButton = 0;
00376 }
00377
00378 if (controls&Next) {
00379 if (!d->nextButton) {
00380 d->nextButton = new IconWidget(d->nextButton);
00381 d->nextButton->setIcon("media-playback-start");
00382 connect(d->nextButton, SIGNAL(clicked()), this, SIGNAL(nextRequested()));
00383 }
00384 controlsLayout->addItem(d->nextButton);
00385 } else {
00386 d->nextButton->deleteLater();
00387 d->nextButton = 0;
00388 }
00389
00390 connect(d->media, SIGNAL(stateChanged(Phonon::State, Phonon::State)), this, SLOT(stateChanged(Phonon::State, Phonon::State)));
00391
00392
00393
00394
00395 if (controls&Progress) {
00396 if (!d->progress) {
00397 d->progress = new Slider(d->controlsWidget);
00398 d->progress->setMinimum(0);
00399 d->progress->setMaximum(100);
00400 d->progress->setOrientation(Qt::Horizontal);
00401 controlsLayout->setStretchFactor(d->progress, 4);
00402 d->progress->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Preferred);
00403
00404 connect(d->media, SIGNAL(tick(qint64)), this, SLOT(ticked(qint64)));
00405 connect(d->media, SIGNAL(totalTimeChanged(qint64)), SLOT(totalTimeChanged(qint64)));
00406 connect(d->progress, SIGNAL(valueChanged(int)), this, SLOT(setPosition(int)));
00407 }
00408 controlsLayout->addItem(d->progress);
00409 } else {
00410 d->progress->deleteLater();
00411 d->progress = 0;
00412 }
00413
00414
00415 if (controls&Volume) {
00416 if (!d->volume) {
00417 d->volume = new Slider(d->controlsWidget);
00418 d->volume->setMinimum(0);
00419 d->volume->setMaximum(100);
00420 d->volume->setValue(100);
00421 d->volume->setOrientation(Qt::Horizontal);
00422 d->volume->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Preferred);
00423
00424 connect(d->volume, SIGNAL(valueChanged(int)), SLOT(setVolume(int)));
00425 connect(d->audioOutput, SIGNAL(volumeChanged(qreal)), SLOT(volumeChanged(qreal)));
00426 }
00427 controlsLayout->addItem(d->volume);
00428 } else {
00429 d->volume->deleteLater();
00430 d->volume = 0;
00431 }
00432
00433
00434 if (controls&OpenFile) {
00435 if (!d->openFileButton) {
00436 d->openFileButton = new IconWidget(d->controlsWidget);
00437 d->openFileButton->setIcon(KIcon("document-open"));
00438 connect(d->openFileButton, SIGNAL(clicked()), this, SLOT(showOpenFileDialog()));
00439 }
00440 controlsLayout->addItem(d->openFileButton);
00441 } else {
00442 d->openFileButton->deleteLater();
00443 d->openFileButton = 0;
00444 }
00445
00446 controlsLayout->activate();
00447 d->controlsWidget->setPos(0,-d->controlsWidget->size().height());
00448 d->controlsWidget->resize(size().width(), d->controlsWidget->size().height());
00449 d->controlsWidget->hide();
00450 }
00451
00452 VideoWidget::Controls VideoWidget::usedControls() const
00453 {
00454 return d->shownControls;
00455 }
00456
00457 void VideoWidget::play()
00458 {
00459 d->media->play();
00460 }
00461
00462 void VideoWidget::pause()
00463 {
00464 d->media->pause();
00465 }
00466
00467 void VideoWidget::stop()
00468 {
00469 d->media->stop();
00470 }
00471
00472 void VideoWidget::seek(qint64 time)
00473 {
00474 d->media->seek(time);
00475 }
00476
00477 qint64 VideoWidget::currentTime() const
00478 {
00479 return d->media->currentTime();
00480 }
00481
00482 qint64 VideoWidget::totalTime() const
00483 {
00484 return d->media->totalTime();
00485 }
00486
00487 qint64 VideoWidget::remainingTime() const
00488 {
00489 return d->media->remainingTime();
00490 }
00491
00492 void VideoWidget::setControlsVisible(bool visible)
00493 {
00494 if (d->controlsWidget) {
00495 d->forceControlsVisible = visible;
00496 d->animateControlWidget(visible);
00497 }
00498 }
00499
00500 bool VideoWidget::controlsVisible() const
00501 {
00502 return d->controlsWidget != 0 && d->controlsWidget->isVisible();
00503 }
00504
00505 void VideoWidget::setStyleSheet(const QString &stylesheet)
00506 {
00507 d->videoWidget->setStyleSheet(stylesheet);
00508 }
00509
00510 QString VideoWidget::styleSheet()
00511 {
00512 return d->videoWidget->styleSheet();
00513 }
00514
00515 Phonon::VideoWidget *VideoWidget::nativeWidget() const
00516 {
00517 return d->videoWidget;
00518 }
00519
00520
00521 void VideoWidget::resizeEvent(QGraphicsSceneResizeEvent *event)
00522 {
00523 QGraphicsProxyWidget::resizeEvent(event);
00524
00525 if (d->controlsWidget) {
00526 QSize newControlsSize(event->newSize().width(), d->controlsWidget->size().height());
00527 int newHeight = event->newSize().height();
00528 qreal leftMargin, topMargin, rightMargin, bottomMargin;
00529 d->controlsWidget->getContentsMargins(&leftMargin, &topMargin, &rightMargin, &bottomMargin);
00530
00531 if (newHeight/5 >= KIconLoader::SizeEnormous) {
00532 newControlsSize.setHeight(KIconLoader::SizeEnormous+topMargin+bottomMargin);
00533 } else if (newHeight/5 >= KIconLoader::SizeHuge) {
00534 newControlsSize.setHeight(KIconLoader::SizeHuge+topMargin+bottomMargin);
00535 } else if (newHeight/5 >= KIconLoader::SizeLarge) {
00536 newControlsSize.setHeight(KIconLoader::SizeLarge+topMargin+bottomMargin);
00537 } else if (newHeight/5 >= KIconLoader::SizeMedium) {
00538 newControlsSize.setHeight(KIconLoader::SizeMedium+topMargin+bottomMargin);
00539 } else {
00540 newControlsSize.setHeight(KIconLoader::SizeSmallMedium+topMargin+bottomMargin);
00541 }
00542 d->controlsWidget->resize(newControlsSize);
00543
00544 if (d->spaceForControlsAvailable()) {
00545 d->animateControlWidget(false);
00546 }
00547 }
00548 }
00549
00550 void VideoWidget::hoverEnterEvent(QGraphicsSceneHoverEvent *event)
00551 {
00552 Q_UNUSED(event)
00553
00554 if (d->controlsWidget &&
00555 !d->forceControlsVisible &&
00556 d->spaceForControlsAvailable()) {
00557 d->animateControlWidget(true);
00558 }
00559 }
00560
00561 void VideoWidget::hoverLeaveEvent(QGraphicsSceneHoverEvent *event)
00562 {
00563 Q_UNUSED(event)
00564
00565 if (d->controlsWidget && !d->forceControlsVisible) {
00566 d->hideTimer->start(1000);
00567 }
00568 }
00569
00570 void VideoWidget::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
00571 {
00572 Q_UNUSED(event)
00573
00574 if (d->forceControlsVisible || !d->controlsWidget) {
00575 return;
00576 }
00577
00578 d->hideTimer->start(3000);
00579
00580 if (!d->controlsWidget->isVisible() &&
00581 d->spaceForControlsAvailable()) {
00582 d->animateControlWidget(true);
00583 }
00584 }
00585
00586 }
00587
00588 #include <videowidget.moc>
00589