From fe9affeea1fc9f75cdbd8399736c8fcbbdc90c87 Mon Sep 17 00:00:00 2001
From: Craig Watson <craig@watsons.ch>
Date: Fri, 26 Feb 2016 15:00:31 +0100
Subject: [PATCH] Overhaul of UBGraphicsMediaItem class

- Removed inheritance of UBGraphicsProxyWidget; cleaned up related code
- Added two children classes: UBGraphicsVideoItem and
UBGraphicsAudioItem. UBGraphicsMediaItem is now an abstract class.
- Better encapsulation; the Scene and other external classes no longer
access the mediaObject directly

There is now less distinction between audio and video items to outside
code: apart from the UBSvgSubsetAdaptor, there is no need to know
whether a media item holds a video or audio file. Creation is handled
through the static function `UBGraphicsMediaItem::createMediaItem(URL,
parent)`
---
 src/adaptors/UBSvgSubsetAdaptor.cpp        |  48 +--
 src/adaptors/UBSvgSubsetAdaptor.h          |   6 +-
 src/board/UBBoardController.h              |   2 -
 src/core/UBPersistenceManager.cpp          |   2 +-
 src/domain/UBGraphicsItemDelegate.cpp      |   4 +-
 src/domain/UBGraphicsMediaItem.cpp         | 376 ++++++++++++++-------
 src/domain/UBGraphicsMediaItem.h           | 114 ++++---
 src/domain/UBGraphicsMediaItemDelegate.cpp | 102 ++----
 src/domain/UBGraphicsMediaItemDelegate.h   |  13 +-
 src/domain/UBGraphicsScene.cpp             |  20 +-
 src/domain/UBGraphicsScene.h               |   2 -
 11 files changed, 393 insertions(+), 296 deletions(-)

diff --git a/src/adaptors/UBSvgSubsetAdaptor.cpp b/src/adaptors/UBSvgSubsetAdaptor.cpp
index 064ca529..c28da1c6 100644
--- a/src/adaptors/UBSvgSubsetAdaptor.cpp
+++ b/src/adaptors/UBSvgSubsetAdaptor.cpp
@@ -661,9 +661,8 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene()
 
                     audioItem->show();
 
-                    //force start to load the video and display the first frame
-                    audioItem->mediaObject()->play();
-                    audioItem->mediaObject()->pause();
+                    audioItem->play();
+                    audioItem->pause();
                 }
             }
             else if (mXmlReader.name() == "video")
@@ -676,16 +675,12 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene()
                     videoItem->setFlag(QGraphicsItem::ItemIsSelectable, true);
 
                     mScene->addItem(videoItem);
-                    mScene->addItem(videoItem->videoItem());
-
-                    // Update the child QGraphicsVideoItem's transformation matrix
-                    videoItem->setMatrix(videoItem->matrix());
 
                     videoItem->show();
 
                     //force start to load the video and display the first frame
-                    videoItem->mediaObject()->play();
-                    videoItem->mediaObject()->pause();
+                    videoItem->play();
+                    videoItem->pause();
                 }
             }
             else if (mXmlReader.name() == "text")//This is for backward compatibility with proto text field prior to version 4.3
@@ -1210,14 +1205,17 @@ bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(int pageIndex)
             continue;
         }
 
-        UBGraphicsMediaItem *mediaItem = qgraphicsitem_cast<UBGraphicsMediaItem*> (item);
+        UBGraphicsVideoItem * videoItem = qgraphicsitem_cast<UBGraphicsVideoItem*> (item);
 
-        if (mediaItem && mediaItem->isVisible())
-        {
-            if (UBGraphicsMediaItem::mediaType_Video == mediaItem->getMediaType())
-                videoItemToLinkedVideo(mediaItem);
-            else
-                audioItemToLinkedAudio(mediaItem);
+        if (videoItem && videoItem->isVisible()) {
+            videoItemToLinkedVideo(videoItem);
+            continue;
+        }
+
+        UBGraphicsAudioItem * audioItem = qgraphicsitem_cast<UBGraphicsAudioItem*> (item);
+
+        if (audioItem && audioItem->isVisible()) {
+            audioItemToLinkedAudio(audioItem);
             continue;
         }
 
@@ -2019,15 +2017,16 @@ UBGraphicsPDFItem* UBSvgSubsetAdaptor::UBSvgSubsetReader::pdfItemFromPDF()
     return pdfItem;
 }
 
-void UBSvgSubsetAdaptor::UBSvgSubsetWriter::audioItemToLinkedAudio(UBGraphicsMediaItem* audioItem)
+void UBSvgSubsetAdaptor::UBSvgSubsetWriter::audioItemToLinkedAudio(UBGraphicsAudioItem *audioItem)
 {
     mXmlWriter.writeStartElement("audio");
 
     graphicsItemToSvg(audioItem);
 
-    if (audioItem->mediaObject()->state() == QMediaPlayer::PausedState && (audioItem->mediaObject()->duration() - audioItem->mediaObject()->position()) > 0)
+    if (audioItem->playerState() == QMediaPlayer::PausedState &&
+       (audioItem->mediaDuration() - audioItem->mediaPosition()) > 0)
     {
-        qint64 pos = audioItem->mediaObject()->position();
+        qint64 pos = audioItem->mediaPosition();
         mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "position", QString("%1").arg(pos));
     }
 
@@ -2038,7 +2037,7 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::audioItemToLinkedAudio(UBGraphicsMed
 }
 
 
-void UBSvgSubsetAdaptor::UBSvgSubsetWriter::videoItemToLinkedVideo(UBGraphicsMediaItem* videoItem)
+void UBSvgSubsetAdaptor::UBSvgSubsetWriter::videoItemToLinkedVideo(UBGraphicsVideoItem* videoItem)
 {
     /* w3c sample
      *
@@ -2051,9 +2050,10 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::videoItemToLinkedVideo(UBGraphicsMed
 
     graphicsItemToSvg(videoItem);
 
-    if (videoItem->mediaObject()->state() == QMediaPlayer::PausedState && (videoItem->mediaObject()->duration() - videoItem->mediaObject()->position()) > 0)
+    if (videoItem->playerState() == QMediaPlayer::PausedState &&
+       (videoItem->mediaDuration() - videoItem->mediaPosition()) > 0)
     {
-        qint64 pos = videoItem->mediaObject()->position();
+        qint64 pos = videoItem->mediaPosition();
         mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "position", QString("%1").arg(pos));
     }
 
@@ -2083,7 +2083,7 @@ UBGraphicsMediaItem* UBSvgSubsetAdaptor::UBSvgSubsetReader::audioItemFromSvg()
         href = mDocumentPath + "/" + href.right(href.length() - indexOfAudioDirectory);
     }
 
-    UBGraphicsMediaItem* audioItem = new UBGraphicsMediaItem(QUrl::fromLocalFile(href));
+    UBGraphicsMediaItem* audioItem = UBGraphicsMediaItem::createMediaItem(QUrl::fromLocalFile(href));
     if(audioItem)
         audioItem->connect(UBApplication::boardController, SIGNAL(activeSceneChanged()), audioItem, SLOT(activeSceneChanged()));
 
@@ -2118,7 +2118,7 @@ UBGraphicsMediaItem* UBSvgSubsetAdaptor::UBSvgSubsetReader::videoItemFromSvg()
         href = mDocumentPath + "/" + href.right(href.length() - indexOfAudioDirectory);
     }
 
-    UBGraphicsMediaItem* videoItem = new UBGraphicsMediaItem(QUrl::fromLocalFile(href));
+    UBGraphicsMediaItem* videoItem = UBGraphicsMediaItem::createMediaItem(QUrl::fromLocalFile(href));
     if(videoItem){
         videoItem->connect(UBApplication::boardController, SIGNAL(activeSceneChanged()), videoItem, SLOT(activeSceneChanged()));
     }
diff --git a/src/adaptors/UBSvgSubsetAdaptor.h b/src/adaptors/UBSvgSubsetAdaptor.h
index 7bc1c88b..91f61e94 100644
--- a/src/adaptors/UBSvgSubsetAdaptor.h
+++ b/src/adaptors/UBSvgSubsetAdaptor.h
@@ -40,6 +40,8 @@ class UBGraphicsPixmapItem;
 class UBGraphicsPDFItem;
 class UBGraphicsWidgetItem;
 class UBGraphicsMediaItem;
+class UBGraphicsVideoItem;
+class UBGraphicsAudioItem;
 class UBGraphicsAppleWidgetItem;
 class UBGraphicsW3CWidgetItem;
 class UBGraphicsTextItem;
@@ -232,8 +234,8 @@ class UBSvgSubsetAdaptor
                 void pixmapItemToLinkedImage(UBGraphicsPixmapItem *pixmapItem);
                 void svgItemToLinkedSvg(UBGraphicsSvgItem *svgItem);
                 void pdfItemToLinkedPDF(UBGraphicsPDFItem *pdfItem);
-                void videoItemToLinkedVideo(UBGraphicsMediaItem *videoItem);
-                void audioItemToLinkedAudio(UBGraphicsMediaItem *audioItem);
+                void videoItemToLinkedVideo(UBGraphicsVideoItem *videoItem);
+                void audioItemToLinkedAudio(UBGraphicsAudioItem *audioItem);
                 void graphicsItemToSvg(QGraphicsItem *item);
                 void graphicsAppleWidgetToSvg(UBGraphicsAppleWidgetItem *item);
                 void graphicsW3CWidgetToSvg(UBGraphicsW3CWidgetItem *item);
diff --git a/src/board/UBBoardController.h b/src/board/UBBoardController.h
index 4d796656..bc1481d5 100644
--- a/src/board/UBBoardController.h
+++ b/src/board/UBBoardController.h
@@ -51,8 +51,6 @@ class UBVersion;
 class UBSoftwareUpdate;
 class UBSoftwareUpdateDialog;
 class UBGraphicsMediaItem;
-class UBGraphicsVideoItem;
-class UBGraphicsAudioItem;
 class UBGraphicsWidgetItem;
 class UBBoardPaletteManager;
 class UBItem;
diff --git a/src/core/UBPersistenceManager.cpp b/src/core/UBPersistenceManager.cpp
index 60c271ef..7114bfae 100644
--- a/src/core/UBPersistenceManager.cpp
+++ b/src/core/UBPersistenceManager.cpp
@@ -566,7 +566,7 @@ void UBPersistenceManager::duplicateDocumentScene(UBDocumentProxy* proxy, int in
             QString fileName = QFileInfo(source).completeBaseName();
             destination = destination.replace(fileName,newUuid.toString());
             QFile::copy(source,destination);
-            mediaItem->mediaFileUrl(QUrl::fromLocalFile(destination));
+            mediaItem->setMediaFileUrl(QUrl::fromLocalFile(destination));
             continue;
         }
 
diff --git a/src/domain/UBGraphicsItemDelegate.cpp b/src/domain/UBGraphicsItemDelegate.cpp
index a8271e34..779ca9e9 100644
--- a/src/domain/UBGraphicsItemDelegate.cpp
+++ b/src/domain/UBGraphicsItemDelegate.cpp
@@ -1439,10 +1439,10 @@ void DelegateMediaControl::seekToMousePos(QPointF mousePos)
         mouseX = mSeecArea.width() - mSeecArea.height()/2;
 
     if (mTotalTimeInMs > 0 && length > 0 && mDelegate
-        && mDelegate->mediaObject() && mDelegate->mediaObject()->isSeekable())
+        && mDelegate->isMediaSeekable())
     {
         qint64 tickPos = (mTotalTimeInMs/length)* (mouseX - minX);
-        mDelegate->mediaObject()->setPosition(tickPos);
+        mDelegate->setMediaPos(tickPos);
 
         //OSX is a bit lazy
         updateTicker(tickPos);
diff --git a/src/domain/UBGraphicsMediaItem.cpp b/src/domain/UBGraphicsMediaItem.cpp
index beaa39c9..8c61a874 100644
--- a/src/domain/UBGraphicsMediaItem.cpp
+++ b/src/domain/UBGraphicsMediaItem.cpp
@@ -39,100 +39,107 @@
 
 bool UBGraphicsMediaItem::sIsMutedByDefault = false;
 
+/**
+ * @brief Create and return a UBGraphicsMediaItem instance. The type (audio or video) is determined from the URL.
+ * @param pMediaFileUrl The URL of the audio or video file
+ * @param parent (Optional) the parent item
+ * @return A pointer to the newly created instance.
+ */
+UBGraphicsMediaItem* UBGraphicsMediaItem::createMediaItem(const QUrl &pMediaFileUrl, QGraphicsItem* parent)
+{
+    UBGraphicsMediaItem * mediaItem;
+
+    QString mediaPath = pMediaFileUrl.toString();
+    if ("" == mediaPath)
+        mediaPath = pMediaFileUrl.toLocalFile();
+
+    if (mediaPath.toLower().contains("videos"))
+        mediaItem = new UBGraphicsVideoItem(pMediaFileUrl, parent);
+    else if (mediaPath.toLower().contains("audios"))
+        mediaItem = new UBGraphicsAudioItem(pMediaFileUrl, parent);
+
+    return mediaItem;
+}
+
 UBGraphicsMediaItem::UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsItem *parent)
-        : UBGraphicsProxyWidget(parent)
-        , mDummyVideoWidget(NULL)
-        , mVideoItem(NULL)
-        , mAudioWidget(NULL)
+        : QGraphicsRectItem(parent)
         , mMuted(sIsMutedByDefault)
         , mMutedByUserAction(sIsMutedByDefault)
         , mMediaFileUrl(pMediaFileUrl)
         , mLinkedImage(NULL)
         , mInitialPos(0)
 {
-    update();
-
 
     mMediaObject = new QMediaPlayer(this);
+    mMediaObject->setMedia(pMediaFileUrl);
 
-    QString mediaPath = pMediaFileUrl.toString();
-    if ("" == mediaPath)
-        mediaPath = pMediaFileUrl.toLocalFile();
+    setDelegate(new UBGraphicsMediaItemDelegate(this));
+    Delegate()->createControls();
 
-    if (mediaPath.toLower().contains("videos"))
-    {
-        mMediaType = mediaType_Video;
+    setData(UBGraphicsItemData::itemLayerType, QVariant(itemLayerType::ObjectItem));
+    setFlag(ItemIsMovable, true);
+    setFlag(ItemSendsGeometryChanges, true);
 
-        mMediaObject->setNotifyInterval(50);
+    setAcceptHoverEvents(true);
 
-        /* A dummy widget is used to keep the old functionality (when a Phonon video widget
-         * was used) with the current implementation, such as maintaining a clickable area
-         * above the video to move it around, etc.
-         * The whole class could be cleaned up, and the inheritance of QGraphicsProxyWidget
-         * abandoned, to make for a cleaner solution; for now, this works ok.
-        */
-        mDummyVideoWidget = new QWidget();
-        mDummyVideoWidget->resize(320,240);
-        mDummyVideoWidget->setMinimumSize(320, 240);
-        mDummyVideoWidget->setWindowOpacity(0.0);
-        
-        mVideoItem = new QGraphicsVideoItem(this);
+    connect(mMediaObject, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
+            Delegate(), SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus)));
 
-        // Necessary to allow the video to be displayed on secondary screen
-        mVideoItem->setData(UBGraphicsItemData::ItemLayerType, UBItemLayerType::Object);
-        mVideoItem->setFlag(ItemStacksBehindParent, true);
+    connect(mMediaObject, SIGNAL(stateChanged(QMediaPlayer::State)),
+            Delegate(), SLOT(mediaStateChanged(QMediaPlayer::State)));
 
-        mMediaObject->setVideoOutput(mVideoItem);
+    /*
+    connect(mMediaObject, static_cast<void(QMediaPlayer::*)(QMediaPlayer::Error)>(&QMediaPlayer::error),
+            Delegate(), &UBGraphicsMediaItemDelegate::mediaError);
+            */
 
-        mVideoItem->setSize(QSize(320,240));
+    connect(mMediaObject, SIGNAL(positionChanged(qint64)),
+            Delegate(), SLOT(updateTicker(qint64)));
 
-        haveLinkedImage = true;
-    }
-    else if (mediaPath.toLower().contains("audios"))
-    {
-        mMediaType = mediaType_Audio;
+    connect(mMediaObject, SIGNAL(durationChanged(qint64)),
+            Delegate(), SLOT(totalTimeChanged(qint64)));
 
-        mMediaObject->setNotifyInterval(1000);
-        mAudioWidget = new QWidget();
-        mAudioWidget->resize(320,26);
-        mAudioWidget->setMinimumSize(150,26);
+    connect(Delegate(), SIGNAL(showOnDisplayChanged(bool)),
+            this, SLOT(showOnDisplayChanged(bool)));
 
-        haveLinkedImage = false;
-    }
+    connect(mMediaObject, SIGNAL(videoAvailableChanged(bool)),
+            this, SLOT(hasMediaChanged(bool)));
+}
 
-     mMediaObject->setMedia(pMediaFileUrl);
+UBGraphicsAudioItem::UBGraphicsAudioItem(const QUrl &pMediaFileUrl, QGraphicsItem *parent)
+    :UBGraphicsMediaItem(pMediaFileUrl, parent)
+{
+    this->setSize(320, 26);
+    this->setMinimumSize(QSize(150, 26));
 
+    Delegate()->frame()->setOperationMode(UBGraphicsDelegateFrame::ResizingHorizontally);
 
-    // we should create delegate after media objects because delegate uses his properties at creation.
-    setDelegate(new UBGraphicsMediaItemDelegate(this, mMediaObject));
+    mMediaObject->setNotifyInterval(1000);
+    haveLinkedImage = false;
 
+}
 
-    // delegate should be created earler because we setWidget calls resize event for graphics proxy widgt.
-    // resize uses delegate.
-    if (mediaType_Video == mMediaType)
-        setWidget(mDummyVideoWidget);
-    else
-        setWidget(mAudioWidget);
+UBGraphicsVideoItem::UBGraphicsVideoItem(const QUrl &pMediaFileUrl, QGraphicsItem *parent)
+    :UBGraphicsMediaItem(pMediaFileUrl, parent)
+{
+    mVideoItem = new QGraphicsVideoItem(this);
 
-    // media widget should be created and placed on proxy widget here.
-    // TODO claudio remove this because in contrast with the fact the frame should be created on demand.
-    // but without forcing the control creation we do not have the frame and all the calculation
-    // for the different element of the interface will fail
-    Delegate()->createControls();
-    if (mediaType_Audio == mMediaType)
-        Delegate()->frame()->setOperationMode(UBGraphicsDelegateFrame::ResizingHorizontally);
-    else {
-        Delegate()->frame()->setOperationMode(UBGraphicsDelegateFrame::Resizing);
-        // Resize the widget as soon as the video's native size is known (it isn't at this stage)
-        connect(mVideoItem, SIGNAL(nativeSizeChanged(QSizeF)), this, SLOT(resize(QSizeF)));
-    }
+    mVideoItem->setData(UBGraphicsItemData::ItemLayerType, UBItemLayerType::Object);
+    mVideoItem->setFlag(ItemStacksBehindParent, true);
 
-    setData(UBGraphicsItemData::itemLayerType, QVariant(itemLayerType::ObjectItem)); //Necessary to set if we want z value to be assigned correctly
+    mMediaObject->setVideoOutput(mVideoItem);
+    mMediaObject->setNotifyInterval(50);
+
+    setMinimumSize(QSize(320, 240));
+    setSize(320, 240);
 
-    connect(Delegate(), SIGNAL(showOnDisplayChanged(bool)), this, SLOT(showOnDisplayChanged(bool)));
-    connect(mMediaObject, SIGNAL(videoAvailableChanged(bool)), this, SLOT(hasMediaChanged(bool)));
-}
 
+    connect(mVideoItem, SIGNAL(nativeSizeChanged(QSizeF)),
+            this, SLOT(videoSizeChanged(QSizeF)));
+
+    haveLinkedImage = true;
+    update();
+}
 
 UBGraphicsMediaItem::~UBGraphicsMediaItem()
 {
@@ -140,19 +147,6 @@ UBGraphicsMediaItem::~UBGraphicsMediaItem()
         mMediaObject->stop();
 }
 
-
-void UBGraphicsMediaItem::setSelected(bool selected)
-{
-    if(selected){
-        Delegate()->createControls();
-        if (mediaType_Audio == mMediaType)
-            Delegate()->frame()->setOperationMode(UBGraphicsDelegateFrame::ResizingHorizontally);
-        else
-            Delegate()->frame()->setOperationMode(UBGraphicsDelegateFrame::Resizing);
-    }
-    UBGraphicsProxyWidget::setSelected(selected);
-}
-
 QVariant UBGraphicsMediaItem::itemChange(GraphicsItemChange change, const QVariant &value)
 {
     if ((change == QGraphicsItem::ItemEnabledChange)
@@ -180,9 +174,91 @@ QVariant UBGraphicsMediaItem::itemChange(GraphicsItemChange change, const QVaria
         }
     }
 
-    return UBGraphicsProxyWidget::itemChange(change, value);
+    if (Delegate()) {
+        QVariant newValue = Delegate()->itemChange(change, value);
+        return QGraphicsRectItem::itemChange(change, newValue);
+    }
+
+    else
+        return QGraphicsRectItem::itemChange(change, value);
 }
 
+void UBGraphicsMediaItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
+{
+    painter->save();
+    painter->setCompositionMode(QPainter::CompositionMode_SourceOver);
+    Delegate()->postpaint(painter, option, widget);
+    painter->restore();
+}
+
+
+QMediaPlayer::State UBGraphicsMediaItem::playerState() const
+{
+    return mMediaObject->state();
+}
+
+qint64 UBGraphicsMediaItem::mediaDuration() const
+{
+    return mMediaObject->duration();
+}
+
+qint64 UBGraphicsMediaItem::mediaPosition() const
+{
+    return mMediaObject->position();
+}
+
+bool UBGraphicsMediaItem::isMediaSeekable() const
+{
+    return mMediaObject->isSeekable();
+}
+
+/**
+ * @brief Set the item's minimum size. If the current size is smaller, it will be resized.
+ * @param size The new minimum size
+ */
+void UBGraphicsMediaItem::setMinimumSize(const QSize& size)
+{
+    mMinimumSize = size;
+
+    QSizeF newSize = rect().size();
+    int width = newSize.width();
+    int height = newSize.height();
+
+    if (rect().width() < mMinimumSize.width())
+        width = mMinimumSize.width();
+
+    if (rect().height() < mMinimumSize.height())
+        height = mMinimumSize.height();
+
+    this->setSize(width, height);
+}
+
+void UBGraphicsMediaItem::setMediaFileUrl(QUrl url)
+{
+    mMediaFileUrl = url;
+}
+
+void UBGraphicsMediaItem::setInitialPos(qint64 p)
+{
+    mInitialPos = p;
+}
+
+void UBGraphicsMediaItem::setMediaPos(qint64 p)
+{
+    mMediaObject->setPosition(p);
+}
+
+void UBGraphicsMediaItem::setSelected(bool selected)
+{
+    if(selected){
+        Delegate()->createControls();
+        if (this->getMediaType() == mediaType_Audio)
+            Delegate()->frame()->setOperationMode(UBGraphicsDelegateFrame::ResizingHorizontally);
+        else
+            Delegate()->frame()->setOperationMode(UBGraphicsDelegateFrame::Resizing);
+    }
+    QGraphicsRectItem::setSelected(selected);
+}
 
 void UBGraphicsMediaItem::setSourceUrl(const QUrl &pSourceUrl)
 {
@@ -243,28 +319,65 @@ void UBGraphicsMediaItem::activeSceneChanged()
 
 void UBGraphicsMediaItem::showOnDisplayChanged(bool shown)
 {
-    if (!shown)
-    {
+    if (!shown) {
         mMuted = true;
         mMediaObject->setMuted(mMuted);
     }
-    else if (!mMutedByUserAction)
-    {
+    else if (!mMutedByUserAction) {
         mMuted = false;
         mMediaObject->setMuted(mMuted);
     }
 }
+void UBGraphicsMediaItem::play()
+{
+    mMediaObject->play();
+}
 
-UBItem* UBGraphicsMediaItem::deepCopy() const
+void UBGraphicsMediaItem::pause()
 {
-    QUrl url = this->mediaFileUrl();
-    UBGraphicsMediaItem *copy = new UBGraphicsMediaItem(url, parentItem());
+    mMediaObject->pause();
+}
 
-    copy->setUuid(this->uuid()); // this is OK for now as long as Widgets are imutable
+void UBGraphicsMediaItem::stop()
+{
+    mMediaObject->stop();
+}
 
-    copyItemParameters(copy);
+void UBGraphicsMediaItem::togglePlayPause()
+{
+
+    if (mMediaObject->state() == QMediaPlayer::StoppedState)
+        mMediaObject->play();
+
+    else if (mMediaObject->state() == QMediaPlayer::PlayingState) {
+
+        if ((mMediaObject->duration() - mMediaObject->position()) <= 0) {
+            mMediaObject->stop();
+            mMediaObject->play();
+        }
+
+        else {
+            mMediaObject->pause();
+            if(scene())
+                scene()->setModified(true);
+        }
+    }
+
+    else if (mMediaObject->state() == QMediaPlayer::PausedState) {
+        if ((mMediaObject->duration() - mMediaObject->position()) <= 0)
+            mMediaObject->stop();
+
+        mMediaObject->play();
+    }
+
+    else  if ( mMediaObject->mediaStatus() == QMediaPlayer::LoadingMedia) {
+        mMediaObject->setMedia(mediaFileUrl());
+        mMediaObject->play();
+    }
+
+    if (mMediaObject->error())
+        qDebug() << "Error appeared." << mMediaObject->errorString();
 
-    return copy;
 }
 
 void UBGraphicsMediaItem::copyItemParameters(UBItem *copy) const
@@ -279,7 +392,7 @@ void UBGraphicsMediaItem::copyItemParameters(UBItem *copy) const
         cp->setData(UBGraphicsItemData::ItemLayerType, this->data(UBGraphicsItemData::ItemLayerType));
         cp->setData(UBGraphicsItemData::ItemLocked, this->data(UBGraphicsItemData::ItemLocked));
         cp->setSourceUrl(this->sourceUrl());
-        cp->resize(this->size());
+        cp->setSize(rect().width(), rect().height());
 
         cp->setZValue(this->zValue());
 
@@ -322,59 +435,76 @@ void UBGraphicsMediaItem::mousePressEvent(QGraphicsSceneMouseEvent *event)
         event->accept();
         setSelected(true);
     }
+    QGraphicsRectItem::mousePressEvent(event);
+}
 
+QRectF UBGraphicsMediaItem::boundingRect() const
+{
+    return rect();
 }
 
-void UBGraphicsMediaItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
+void UBGraphicsMediaItem::setSize(int width, int height)
 {
-    if(mShouldMove && (event->buttons() & Qt::LeftButton))
-    {
-        QPointF offset = event->scenePos() - mMousePressPos;
+    QRectF r = rect();
+    r.setWidth(width);
+    r.setHeight(height);
+    setRect(r);
 
-        if (offset.toPoint().manhattanLength() > QApplication::startDragDistance())
-        {
-            QPointF mouseMovePos = mapFromScene(mMouseMovePos);
-            QPointF eventPos = mapFromScene( event->scenePos());
+    if (Delegate())
+        Delegate()->positionHandles();
+    if (scene())
+        scene()->setModified(true);
+}
 
-            QPointF translation = eventPos - mouseMovePos;
-            setPos(translation.x(), translation.y());
-        }
+UBItem* UBGraphicsAudioItem::deepCopy() const
+{
+    QUrl url = this->mediaFileUrl();
+    UBGraphicsMediaItem *copy = new UBGraphicsAudioItem(url, parentItem());
 
-        mMouseMovePos = event->scenePos();
-    }
+    copy->setUuid(this->uuid()); // this is OK for now as long as Widgets are imutable
+
+    copyItemParameters(copy);
+
+    return copy;
+}
+
+UBItem* UBGraphicsVideoItem::deepCopy() const
+{
+    QUrl url = this->mediaFileUrl();
+    UBGraphicsMediaItem *copy = new UBGraphicsVideoItem(url, parentItem());
 
-    event->accept();
+    copy->setUuid(this->uuid());
+    copyItemParameters(copy);
 
+    return copy;
 }
 
-void UBGraphicsMediaItem::resize(const QSizeF & pSize)
+void UBGraphicsVideoItem::setSize(int width, int height)
 {
     // Resize the video, then the rest of the Item
 
-    if (mVideoItem) {
-        qreal sizeX = 0;
-        qreal sizeY = 0;
+    int sizeX = 0;
+    int sizeY = 0;
 
-        QSizeF minimumItemSize(mDummyVideoWidget->minimumSize());
-        if (minimumItemSize.width() > pSize.width())
-            sizeX = minimumItemSize.width();
-        else
-            sizeX = pSize.width();
+    if (mMinimumSize.width() > width)
+        sizeX = mMinimumSize.width();
+    else
+        sizeX = width;
 
-        if (minimumItemSize.height() > pSize.height())
-            sizeY = minimumItemSize.height();
-        else
-            sizeY = pSize.height();
+    if (mMinimumSize.height() > height)
+        sizeY = mMinimumSize.height();
+    else
+        sizeY = height;
+
+    mVideoItem->setSize(QSize(sizeX, sizeY));
 
-        mVideoItem->setSize(QSizeF (sizeX, sizeY));
-    }
 
-    UBGraphicsProxyWidget::resize(pSize);
+    UBGraphicsMediaItem::setSize(sizeX, sizeY);
 }
 
-void UBGraphicsMediaItem::resize(qreal w, qreal h)
+void UBGraphicsVideoItem::videoSizeChanged(QSizeF newSize)
 {
-    UBGraphicsMediaItem::resize(QSizeF(w, h));
+    this->setSize(newSize.width(), newSize.height());
 }
 
 
diff --git a/src/domain/UBGraphicsMediaItem.h b/src/domain/UBGraphicsMediaItem.h
index 8014f85c..a7c4540c 100644
--- a/src/domain/UBGraphicsMediaItem.h
+++ b/src/domain/UBGraphicsMediaItem.h
@@ -45,7 +45,7 @@
 
 class QGraphicsVideoItem;
 
-class UBGraphicsMediaItem : public UBGraphicsProxyWidget
+class UBGraphicsMediaItem : public QObject, public UBItem, public UBGraphicsItem, public QGraphicsRectItem, public UBResizableGraphicsItem
 {
     Q_OBJECT
 
@@ -55,9 +55,6 @@ public:
         mediaType_Audio
     } mediaType;
 
-    UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsItem *parent = 0);
-    ~UBGraphicsMediaItem();
-
     enum { Type = UBGraphicsItemType::MediaItemType };
 
     virtual int type() const
@@ -65,48 +62,46 @@ public:
         return Type;
     }
 
-    virtual QUrl mediaFileUrl() const
-    {
-        return mMediaFileUrl;
-    }
+    static UBGraphicsMediaItem* createMediaItem(const QUrl& pMediaFileUrl, QGraphicsItem* parent = 0);
 
-    virtual void mediaFileUrl(QUrl url){mMediaFileUrl=url;}
+    UBGraphicsMediaItem(const QUrl& pMediaFileUrl, QGraphicsItem* parent = 0);
+    ~UBGraphicsMediaItem();
 
-    QMediaPlayer* mediaObject() const
-    {
-        return mMediaObject;
-    }
 
-    void setInitialPos(qint64 p) {
-        mInitialPos = p;
-    }
-    qint64 initialPos() {
-        return mInitialPos;
-    }
+    // Getters
 
-    bool isMuted() const
-    {
-        return mMuted;
-    }
+    virtual mediaType getMediaType() const = 0;
 
-    QGraphicsVideoItem * videoItem() const
-    {
-        return mVideoItem;
-    }
+    virtual UBGraphicsScene* scene();
+    bool hasLinkedImage() const             { return haveLinkedImage; }
+    virtual QUrl mediaFileUrl() const       { return mMediaFileUrl; }
+    bool isMuted() const                    { return mMuted; }
+    qint64 initialPos() const               { return mInitialPos; }
 
-    bool hasLinkedImage(){return haveLinkedImage;}
+    bool isMediaSeekable() const;
+    qint64 mediaDuration() const;
+    qint64 mediaPosition() const;
 
-    mediaType getMediaType() { return mMediaType; }
+    QMediaPlayer::State playerState() const;
 
-    virtual UBGraphicsScene* scene();
+    QRectF boundingRect() const;
 
-    virtual UBItem* deepCopy() const;
+    QSizeF size() const { return rect().size(); } 
+
+    // Setters
+    virtual void setMediaFileUrl(QUrl url);
+    void setInitialPos(qint64 p);
+    void setMediaPos(qint64 p);
+    virtual void setSourceUrl(const QUrl &pSourceUrl);
+    void setSelected(bool selected);
+    void setMinimumSize(const QSize& size);
 
     virtual void copyItemParameters(UBItem *copy) const;
 
-    virtual void setSourceUrl(const QUrl &pSourceUrl);
+    virtual void setSize(int width, int height);
+    void resize(qreal w, qreal h) { setSize(w, h); }
 
-    void setSelected(bool selected);
+    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
 
 
 public slots:
@@ -116,23 +111,22 @@ public slots:
     void activeSceneChanged();
     void hasMediaChanged(bool hasMedia);
     void showOnDisplayChanged(bool shown);
-    virtual void resize(qreal w, qreal h);
-    virtual void resize(const QSizeF & pSize);
+
+    virtual void play();
+    virtual void pause();
+    virtual void stop();
+    virtual void togglePlayPause();
 
 protected:
 
     virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
     virtual void mousePressEvent(QGraphicsSceneMouseEvent *event);
-    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
+
     virtual void clearSource();
 
     QMediaPlayer *mMediaObject;
-    QWidget *mDummyVideoWidget;
-    QGraphicsVideoItem *mVideoItem;
 
-    QWidget *mAudioWidget;
-
-private:
+    QSize mMinimumSize;
 
     bool mMuted;
     bool mMutedByUserAction;
@@ -141,8 +135,6 @@ private:
     QUrl mMediaFileUrl;
     QString mMediaSource;
 
-    mediaType mMediaType;
-
     bool mShouldMove;
     QPointF mMousePressPos;
     QPointF mMouseMovePos;
@@ -152,4 +144,40 @@ private:
 
     qint64 mInitialPos;
 };
+
+class UBGraphicsAudioItem: public UBGraphicsMediaItem
+{
+    Q_OBJECT
+
+public:
+
+    UBGraphicsAudioItem(const QUrl& pMediaFileUrl, QGraphicsItem *parent = 0);
+    mediaType getMediaType() const { return mediaType_Audio; }
+
+    virtual UBItem* deepCopy() const;
+};
+
+class UBGraphicsVideoItem: public UBGraphicsMediaItem
+{
+    Q_OBJECT
+
+public:
+
+    UBGraphicsVideoItem(const QUrl& pMediaFileUrl, QGraphicsItem *parent = 0);
+
+    mediaType getMediaType() const { return mediaType_Video; }
+
+    void setSize(int width, int height);
+
+    virtual UBItem* deepCopy() const;
+
+public slots:
+    void videoSizeChanged(QSizeF newSize);
+
+protected:
+
+    QGraphicsVideoItem *mVideoItem;
+};
+
+
 #endif // UBGRAPHICSMEDIAITEM_H
diff --git a/src/domain/UBGraphicsMediaItemDelegate.cpp b/src/domain/UBGraphicsMediaItemDelegate.cpp
index 8ad719ef..374c1336 100644
--- a/src/domain/UBGraphicsMediaItemDelegate.cpp
+++ b/src/domain/UBGraphicsMediaItemDelegate.cpp
@@ -43,42 +43,17 @@
 
 #include "core/memcheck.h"
 
-UBGraphicsMediaItemDelegate::UBGraphicsMediaItemDelegate(UBGraphicsMediaItem* pDelegated, QMediaPlayer* pMedia, QObject * parent)
+UBGraphicsMediaItemDelegate::UBGraphicsMediaItemDelegate(UBGraphicsMediaItem* pDelegated, QObject * parent)
     : UBGraphicsItemDelegate(pDelegated, parent, GF_COMMON
                              | GF_RESPECT_RATIO
                              | GF_TOOLBAR_USED)
     , mPlayPauseButton(NULL)
-    , mMedia(pMedia)
     , mToolBarShowTimer(NULL)
     , m_iToolBarShowingInterval(5000)
 {
     QPalette palette;
     palette.setBrush ( QPalette::Light, Qt::darkGray );
 
-    mMedia->setNotifyInterval(50);
-
-    connect(mMedia, SIGNAL(mediaStatusChanged(QMediaPlayer::MediaStatus)),
-            this, SLOT(mediaStatusChanged(QMediaPlayer::MediaStatus)));
-
-    connect(mMedia, SIGNAL(stateChanged(QMediaPlayer::State)),
-            this, SLOT(mediaStateChanged(QMediaPlayer::State)));
-
-    connect(mMedia, static_cast<void(QMediaPlayer::*)(QMediaPlayer::Error)>(&QMediaPlayer::error),
-        this, &UBGraphicsMediaItemDelegate::mediaError);
-
-    connect(mMedia, SIGNAL(positionChanged(qint64)),
-            this, SLOT(updateTicker(qint64)));
-
-    connect(mMedia, SIGNAL(durationChanged(qint64)),
-            this, SLOT(totalTimeChanged(qint64)));
-
-    if (delegated()->hasLinkedImage())
-    {
-        mToolBarShowTimer = new QTimer();
-        connect(mToolBarShowTimer, SIGNAL(timeout()), this, SLOT(hideToolBar()));
-        mToolBarShowTimer->setInterval(m_iToolBarShowingInterval);
-    }
-
     if (delegated()->isMuted())
         delegated()->setMute(true);
 
@@ -110,7 +85,7 @@ void UBGraphicsMediaItemDelegate::buildButtons()
 
         mStopButton = new DelegateButton(":/images/stop.svg", mDelegated, mToolBarItem, Qt::TitleBarArea);
         connect(mStopButton, SIGNAL(clicked(bool)),
-                mMedia, SLOT(stop()));
+                delegated(), SLOT(stop()));
 
         mMediaControl = new DelegateMediaControl(delegated(), mToolBarItem);
         mMediaControl->setFlag(QGraphicsItem::ItemIsSelectable, true);
@@ -132,8 +107,16 @@ void UBGraphicsMediaItemDelegate::buildButtons()
         mToolBarItem->setVisibleOnBoard(true);
         mToolBarItem->setShifting(false);
 
-        if (mToolBarShowTimer)
-        {
+        if (!mToolBarShowTimer) {
+
+            if (delegated()->hasLinkedImage()) {
+                mToolBarShowTimer = new QTimer();
+                connect(mToolBarShowTimer, SIGNAL(timeout()), this, SLOT(hideToolBar()));
+                mToolBarShowTimer->setInterval(m_iToolBarShowingInterval);
+            }
+        }
+
+        else {
             connect(mPlayPauseButton, SIGNAL(clicked(bool)),
                     mToolBarShowTimer, SLOT(start()));
 
@@ -195,13 +178,15 @@ void UBGraphicsMediaItemDelegate::positionHandles()
 
 void UBGraphicsMediaItemDelegate::remove(bool canUndo)
 {
-    if (delegated() && delegated()->mediaObject())
-        delegated()->mediaObject()->stop();
+    if (delegated())
+        delegated()->stop();
 
+    /*
     if (delegated()->videoItem()) {
         UBGraphicsScene* scene = dynamic_cast<UBGraphicsScene*>(mDelegated->scene());
         scene->removeItem(delegated()->videoItem());
     }
+    */
 
     UBGraphicsItemDelegate::remove(canUndo);
 }
@@ -223,43 +208,8 @@ UBGraphicsMediaItem* UBGraphicsMediaItemDelegate::delegated()
 
 void UBGraphicsMediaItemDelegate::togglePlayPause()
 {
-    if (delegated() && delegated()->mediaObject()) {
-
-        QMediaPlayer * media = delegated()->mediaObject();
-
-        if (media->state() == QMediaPlayer::StoppedState)
-            media->play();
-
-        else if (media->state() == QMediaPlayer::PlayingState) {
-
-            if ((media->duration() - media->position()) <= 0) {
-                media->stop();
-                media->play();
-            }
-
-            else {
-                media->pause();
-                if(delegated()->scene())
-                        delegated()->scene()->setModified(true);
-            }
-        }
-
-        else if (media->state() == QMediaPlayer::PausedState) {
-            if ((media->duration() - media->position()) <= 0)
-                media->stop();
-
-            media->play();
-        }
-
-        else  if ( media->mediaStatus() == QMediaPlayer::LoadingMedia) {
-            delegated()->mediaObject()->setMedia(delegated()->mediaFileUrl());
-            media->play();
-        }
-
-        if (media->error())
-            qDebug() << "Error appeared." << media->errorString();
-
-    }
+    if (delegated())
+        delegated()->togglePlayPause();
 }
 
 void UBGraphicsMediaItemDelegate::mediaStatusChanged(QMediaPlayer::MediaStatus status)
@@ -268,7 +218,7 @@ void UBGraphicsMediaItemDelegate::mediaStatusChanged(QMediaPlayer::MediaStatus s
     // StalledMedia, BufferingMedia, BufferedMedia, EndOfMedia, InvalidMedia
 
     if (status == QMediaPlayer::LoadedMedia)
-        mMediaControl->totalTimeChanged(delegated()->mediaObject()->duration());
+        mMediaControl->totalTimeChanged(delegated()->mediaDuration());
 
     // in most cases, the only necessary action is to update the play/pause state
     updatePlayPauseState();
@@ -288,15 +238,13 @@ void UBGraphicsMediaItemDelegate::mediaError(QMediaPlayer::Error error)
     // ServiceMissingError
     Q_UNUSED(error);
 
-    qDebug() << "Error appeared." << mMedia->errorString();
+    qDebug() << "Error appeared.";// << mMedia->errorString();
 }
 
 
 void UBGraphicsMediaItemDelegate::updatePlayPauseState()
 {
-    QMediaPlayer * media = delegated()->mediaObject();
-
-    if (media->state() == QMediaPlayer::PlayingState)
+    if (delegated()->playerState() == QMediaPlayer::PlayingState)
         mPlayPauseButton->setFileName(":/images/pause.svg");
     else
         mPlayPauseButton->setFileName(":/images/play.svg");
@@ -305,8 +253,10 @@ void UBGraphicsMediaItemDelegate::updatePlayPauseState()
 
 void UBGraphicsMediaItemDelegate::updateTicker(qint64 time)
 {
-    QMediaPlayer* media = delegated()->mediaObject();
-    mMediaControl->totalTimeChanged(media->duration());
+    // TODO: duration() getter for UBGMediaItem
+    // make sure that all delegate()->mediaObject() calls are removed. 'tis dirty.
+
+    mMediaControl->totalTimeChanged(delegated()->mediaDuration());
     mMediaControl->updateTicker(time);
 }
 
@@ -320,7 +270,7 @@ void UBGraphicsMediaItemDelegate::showHide(bool show)
 {
     QVariant showFlag = QVariant(show ? UBItemLayerType::Object : UBItemLayerType::Control);
     showHideRecurs(showFlag, mDelegated);
-    showHideRecurs(showFlag, delegated()->videoItem());
+    // TODO: call showHideRecurs on the videoItem too (from UBGMI?)
     mDelegated->update();
 
     emit showOnDisplayChanged(show);
diff --git a/src/domain/UBGraphicsMediaItemDelegate.h b/src/domain/UBGraphicsMediaItemDelegate.h
index 3031a738..f36c7343 100644
--- a/src/domain/UBGraphicsMediaItemDelegate.h
+++ b/src/domain/UBGraphicsMediaItemDelegate.h
@@ -43,7 +43,7 @@ class UBGraphicsMediaItemDelegate :  public UBGraphicsItemDelegate
     Q_OBJECT
 
     public:
-        UBGraphicsMediaItemDelegate(UBGraphicsMediaItem* pDelegated, QMediaPlayer* pMedia, QObject * parent = 0);
+        UBGraphicsMediaItemDelegate(UBGraphicsMediaItem* pDelegated, QObject * parent = 0);
         virtual ~UBGraphicsMediaItemDelegate();
 
         virtual void positionHandles();
@@ -56,6 +56,10 @@ class UBGraphicsMediaItemDelegate :  public UBGraphicsItemDelegate
         void updateTicker(qint64 time);
         virtual void showHide(bool show);
 
+        void mediaStatusChanged(QMediaPlayer::MediaStatus status);
+        void mediaStateChanged(QMediaPlayer::State state);
+        void mediaError(QMediaPlayer::Error error);
+
     protected slots:
 
         virtual void remove(bool canUndo = true);
@@ -68,11 +72,6 @@ class UBGraphicsMediaItemDelegate :  public UBGraphicsItemDelegate
 
         void hideToolBar();
 
-        void mediaStatusChanged(QMediaPlayer::MediaStatus status);
-
-        void mediaStateChanged(QMediaPlayer::State state);
-
-        void mediaError(QMediaPlayer::Error error);
 
     protected:
         virtual void buildButtons();
@@ -84,8 +83,6 @@ class UBGraphicsMediaItemDelegate :  public UBGraphicsItemDelegate
         DelegateButton* mMuteButton;
         DelegateMediaControl* mMediaControl;
 
-        QMediaPlayer* mMedia; // mMedia belongs to the associated UBGraphicsMediaItem (mDelegated)
-
         QTimer* mToolBarShowTimer;
         int m_iToolBarShowingInterval;
 };
diff --git a/src/domain/UBGraphicsScene.cpp b/src/domain/UBGraphicsScene.cpp
index ddb0a37a..5d86a2d0 100644
--- a/src/domain/UBGraphicsScene.cpp
+++ b/src/domain/UBGraphicsScene.cpp
@@ -1349,10 +1349,10 @@ UBGraphicsMediaItem* UBGraphicsScene::addMedia(const QUrl& pMediaFileUrl, bool s
     if (!QFile::exists(pMediaFileUrl.toString()))
         return NULL;
 
-    UBGraphicsMediaItem* mediaItem = new UBGraphicsMediaItem(pMediaFileUrl);
-    if(mediaItem){
+    UBGraphicsMediaItem * mediaItem = UBGraphicsMediaItem::createMediaItem(pMediaFileUrl);
+
+    if(mediaItem)
         connect(UBApplication::boardController, SIGNAL(activeSceneChanged()), mediaItem, SLOT(activeSceneChanged()));
-    }
 
     mediaItem->setPos(pPos);
 
@@ -1361,11 +1361,6 @@ UBGraphicsMediaItem* UBGraphicsScene::addMedia(const QUrl& pMediaFileUrl, bool s
 
     addItem(mediaItem);
 
-    if (mediaItem->videoItem()) {
-        addItem(mediaItem->videoItem());
-        mediaItem->videoItem()->show();
-    }
-
     mediaItem->show();
 
     if (mUndoRedoStackEnabled) { //should be deleted after scene own undo stack implemented
@@ -1373,12 +1368,11 @@ UBGraphicsMediaItem* UBGraphicsScene::addMedia(const QUrl& pMediaFileUrl, bool s
         UBApplication::undoStack->push(uc);
     }
 
-    mediaItem->mediaObject()->play();
+    mediaItem->play();
 
-    if (!shouldPlayAsap)
-    {
-        mediaItem->mediaObject()->pause();
-        mediaItem->mediaObject()->setPosition(0);
+    if (!shouldPlayAsap) {
+        mediaItem->pause();
+        mediaItem->setMediaPos(0);
     }
 
     setDocumentUpdated();
diff --git a/src/domain/UBGraphicsScene.h b/src/domain/UBGraphicsScene.h
index 1734df7e..1d2ae889 100644
--- a/src/domain/UBGraphicsScene.h
+++ b/src/domain/UBGraphicsScene.h
@@ -40,8 +40,6 @@ class UBGraphicsProxyWidget;
 class UBGraphicsSvgItem;
 class UBGraphicsPolygonItem;
 class UBGraphicsMediaItem;
-class UBGraphicsVideoItem;
-class UBGraphicsAudioItem;
 class UBGraphicsWidgetItem;
 class UBGraphicsW3CWidgetItem;
 class UBGraphicsAppleWidgetItem;
-- 
2.18.1