• Skip to content
  • Skip to link menu
KDE 4.6 API Reference
  • KDE API Reference
  • kdelibs
  • KDE Home
  • Contact Us
 

Plasma

videowidget.cpp

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

Plasma

Skip menu "Plasma"
  • Main Page
  • Namespace List
  • Class Hierarchy
  • Alphabetical List
  • Class List
  • File List
  • Namespace Members
  • Class Members
  • Related Pages

kdelibs

Skip menu "kdelibs"
  • DNSSD
  • Interfaces
  •   KHexEdit
  •   KMediaPlayer
  •   KSpeech
  •   KTextEditor
  • Kate
  • kconf_update
  • KDE3Support
  •   KUnitTest
  • KDECore
  • KDED
  • KDEsu
  • KDEUI
  • KDEWebKit
  • KDocTools
  • KFile
  • KHTML
  • KImgIO
  • KInit
  • kio
  • KIOSlave
  • KJS
  •   KJS-API
  •   WTF
  • kjsembed
  • KNewStuff
  • KParts
  • KPty
  • Kross
  • KUnitConversion
  • KUtils
  • Nepomuk
  • Plasma
  • Solid
  • Sonnet
  • ThreadWeaver
Generated for kdelibs by doxygen 1.7.3
This website is maintained by Adriaan de Groot and Allen Winter.
KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal