]> git.sesse.net Git - kdenlive/blobdiff - src/clipitem.cpp
Fix Coverity #980690
[kdenlive] / src / clipitem.cpp
index 46e2e21b6bc964fd7385ee094e1893583a5d7e81..54b640719ec84ef5c6fab13c58cdaa76d74ee05f 100644 (file)
@@ -90,7 +90,7 @@ ClipItem::ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, i
     setAcceptDrops(true);
     m_audioThumbReady = m_clip->audioThumbCreated();
     //setAcceptsHoverEvents(true);
-    connect(this , SIGNAL(prepareAudioThumb(double, int, int, int)) , this, SLOT(slotPrepareAudioThumb(double, int, int, int)));
+    connect(this , SIGNAL(prepareAudioThumb(double, int, int, int, int)) , this, SLOT(slotPrepareAudioThumb(double, int, int, int, int)));
 
     if (m_clipType == VIDEO || m_clipType == AV || m_clipType == SLIDESHOW || m_clipType == PLAYLIST) {
         m_baseColor = QColor(141, 166, 215);
@@ -212,7 +212,7 @@ void ClipItem::setEffectList(const EffectsList effectList)
             else if (fade < 0)
                 m_endFade = -fade;
         }
-        setSelectedEffect(0);
+        setSelectedEffect(1);
     }
 }
 
@@ -467,7 +467,7 @@ void ClipItem::setSelectedEffect(const int ix)
         QDomNodeList params = effect.elementsByTagName("parameter");
         for (int i = 0; i < params.count(); i++) {
             QDomElement e = params.item(i).toElement();
-            if (!e.isNull() && (e.attribute("type") == "keyframe" || e.attribute("type") == "simplekeyframe") && e.attribute("intimeline") == "1") {
+            if (!e.isNull() && (e.attribute("type") == "keyframe" || e.attribute("type") == "simplekeyframe") && (!e.hasAttribute("intimeline") || e.attribute("intimeline") == "1")) {
                 m_keyframes.clear();
                 m_limitedKeyFrames = e.attribute("type") == "keyframe";
                 m_visibleParam = i;
@@ -788,38 +788,50 @@ void ClipItem::paint(QPainter *painter,
         framePen.setColor(paintColor.darker());
     }
     const QRectF exposed = option->exposedRect;
-    const QRectF mappedExposed = painter->worldTransform().mapRect(exposed);
-    const QRectF mapped = painter->worldTransform().mapRect(rect());
-    painter->setWorldMatrixEnabled(false);
+    const QTransform transformation = painter->worldTransform();
+    const QRectF mappedExposed = transformation.mapRect(exposed);
+    const QRectF mapped = transformation.mapRect(rect());
+    painter->setWorldTransform(QTransform());
     QPainterPath p;
     p.addRect(mappedExposed);
     QPainterPath q;
     q.addRoundedRect(mapped, 3, 3);
+    painter->setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform, false);
     painter->setClipPath(p.intersected(q));
     painter->setPen(Qt::NoPen);
     painter->fillRect(mappedExposed, paintColor);
     painter->setPen(paintColor.darker());
     // draw thumbnails
     if (KdenliveSettings::videothumbnails() && !isAudioOnly()) {
+       QRectF thumbRect;
         if ((m_clipType == IMAGE || m_clipType == TEXT) && !m_startPix.isNull()) {
-            const QPointF top = mapped.topRight() - QPointF(m_startPix.width() - 1, 0);
-            painter->drawPixmap(top, m_startPix);
-            QLineF l2(top.x(), mapped.top(), top.x(), mapped.bottom());
-            painter->drawLine(l2);
+           if (thumbRect.isNull()) thumbRect = QRectF(0, 0, mapped.height() / m_startPix.height() * m_startPix.width(), mapped.height());
+           thumbRect.moveTopRight(mapped.topRight());
+           painter->drawPixmap(thumbRect, m_startPix, m_startPix.rect());
+           //const QPointF top = mapped.topRight() - QPointF(m_startPix.width() - 1, 0);
+            //painter->drawPixmap(top, m_startPix);
+            //QLineF l2(top.x(), mapped.top(), top.x(), mapped.bottom());
+            //painter->drawLine(l2);
         } else if (!m_endPix.isNull()) {
-            const QPointF top = mapped.topRight() - QPointF(m_endPix.width() - 1, 0);
-            painter->drawPixmap(top, m_endPix);
-            QLineF l2(top.x(), mapped.top(), top.x(), mapped.bottom());
-            painter->drawLine(l2);
+           if (thumbRect.isNull()) thumbRect = QRectF(0, 0, mapped.height() / m_endPix.height() * m_endPix.width(), mapped.height());
+           thumbRect.moveTopRight(mapped.topRight());
+           painter->drawPixmap(thumbRect, m_endPix, m_endPix.rect());
+           //const QPointF top = mapped.topRight() - QPointF(m_endPix.width() - 1, 0);
+            //painter->drawPixmap(top, m_endPix);
+            //QLineF l2(top.x(), mapped.top(), top.x(), mapped.bottom());
+            //painter->drawLine(l2);
         }
         if (!m_startPix.isNull()) {
-            painter->drawPixmap(mapped.topLeft(), m_startPix);
-            QLineF l2(mapped.left() + m_startPix.width(), mapped.top(), mapped.left() + m_startPix.width(), mapped.bottom());
-            painter->drawLine(l2);
+           if (thumbRect.isNull()) thumbRect = QRectF(0, 0, mapped.height() / m_startPix.height() * m_startPix.width(), mapped.height());
+           thumbRect.moveTopLeft(mapped.topLeft());
+           painter->drawPixmap(thumbRect, m_startPix, m_startPix.rect());
+            //painter->drawPixmap(mapped.topLeft(), m_startPix);
+            //QLineF l2(mapped.left() + m_startPix.width(), mapped.top(), mapped.left() + m_startPix.width(), mapped.bottom());
+            //painter->drawLine(l2);
         }
 
         // if we are in full zoom, paint thumbnail for every frame
-        if (m_clip->thumbProducer() && clipType() != COLOR && clipType() != AUDIO && !m_audioOnly && painter->worldTransform().m11() == FRAME_SIZE) {
+        if (m_clip->thumbProducer() && clipType() != COLOR && clipType() != AUDIO && !m_audioOnly && transformation.m11() == FRAME_SIZE) {
             int offset = (m_info.startPos - m_info.cropStart).frames(m_fps);
             int left = qMax((int) m_info.cropStart.frames(m_fps) + 1, (int) mapToScene(exposed.left(), 0).x() - offset);
             int right = qMin((int)(m_info.cropStart + m_info.cropDuration).frames(m_fps) - 1, (int) mapToScene(exposed.right(), 0).x() - offset);
@@ -842,7 +854,9 @@ void ClipItem::paint(QPainter *painter,
                         img = m_clip->thumbProducer()->findCachedThumb(path + QString::number(i));
                         QPointF xpos = startPos + QPointF(FRAME_SIZE *(i - startOffset), 0);
                         if (img.isNull()) missing << i;
-                        else painter->drawImage(xpos, img);
+                        else {
+                           painter->drawImage(xpos, img);
+                       }
                         painter->drawLine(xpos, xpos + QPointF(0, mapped.height()));
                     }
                     if (!missing.isEmpty()) {
@@ -854,7 +868,6 @@ void ClipItem::paint(QPainter *painter,
             }
         }
     }
-
     // draw audio thumbnails
     if (KdenliveSettings::audiothumbnails() && m_speed == 1.0 && !isVideoOnly() && ((m_clipType == AV && (exposed.bottom() > (rect().height() / 2) || isAudioOnly())) || m_clipType == AUDIO) && m_audioThumbReady) {
 
@@ -873,24 +886,28 @@ void ClipItem::paint(QPainter *painter,
             mappedRect.setTop(mappedRect.bottom() - mapped.height() / 2);
         } else mappedRect = mapped;
 
-        double scale = painter->worldTransform().m11();
+        double scale = transformation.m11();
         int channels = 0;
         if (isEnabled() && m_clip) channels = m_clip->getProperty("channels").toInt();
         if (scale != m_framePixelWidth)
             m_audioThumbCachePic.clear();
         double cropLeft = m_info.cropStart.frames(m_fps);
         const int clipStart = mappedRect.x();
-        const int mappedStartPixel =  painter->worldTransform().map(QPointF(startpixel + cropLeft, 0)).x() - clipStart;
-        const int mappedEndPixel =  painter->worldTransform().map(QPointF(endpixel + cropLeft, 0)).x() - clipStart;
+        const int mappedStartPixel =  transformation.map(QPointF(startpixel + cropLeft, 0)).x() - clipStart;
+        const int mappedEndPixel =  transformation.map(QPointF(endpixel + cropLeft, 0)).x() - clipStart;
         cropLeft = cropLeft * scale;
 
         if (channels >= 1) {
-            emit prepareAudioThumb(scale, mappedStartPixel, mappedEndPixel, channels);
+            emit prepareAudioThumb(scale, mappedStartPixel, mappedEndPixel, channels, (int) (mappedRect.height() + 0.5));
         }
-
+       QRectF pixmapRect(0, mappedRect.y(), 100, mappedRect.height());
         for (int startCache = mappedStartPixel - (mappedStartPixel) % 100; startCache < mappedEndPixel; startCache += 100) {
-            if (!m_audioThumbCachePic.value(startCache).isNull())
-                painter->drawPixmap(clipStart + startCache - cropLeft, mappedRect.y(),  m_audioThumbCachePic.value(startCache));
+            if (!m_audioThumbCachePic.value(startCache).isNull()) {
+                //painter->drawPixmap(clipStart + startCache - cropLeft, mappedRect.y(),  m_audioThumbCachePic.value(startCache));
+               QPixmap pix(m_audioThumbCachePic.value(startCache));
+               pixmapRect.moveLeft(clipStart + startCache - cropLeft);
+               painter->drawPixmap(pixmapRect,  pix, pix.rect());
+           }
         }
     }
     
@@ -949,7 +966,7 @@ void ClipItem::paint(QPainter *painter,
                 if (pos > GenTime()) {
                     if (pos > cropDuration()) break;
                     QLineF l(rect().x() + pos.frames(m_fps), rect().y(), rect().x() + pos.frames(m_fps), rect().bottom());
-                    QLineF l2 = painter->worldTransform().map(l);
+                    QLineF l2 = transformation.map(l);
                    pen.setColor(CommentedTime::markerColor((*it).markerType()));
                    pen.setStyle(Qt::DotLine);
                     painter->setPen(pen);
@@ -957,7 +974,7 @@ void ClipItem::paint(QPainter *painter,
                     if (KdenliveSettings::showmarkers()) {
                         framepos = rect().x() + pos.frames(m_fps);
                         const QRectF r1(framepos + 0.04, rect().height()/3, rect().width() - framepos - 2, rect().height() / 2);
-                        const QRectF r2 = painter->worldTransform().mapRect(r1);
+                        const QRectF r2 = transformation.mapRect(r1);
                         const QRectF txtBounding3 = painter->boundingRect(r2, Qt::AlignLeft | Qt::AlignTop, ' ' + (*it).comment() + ' ');
                         painter->setBrush(markerBrush);
                        pen.setStyle(Qt::SolidLine);
@@ -984,7 +1001,7 @@ void ClipItem::paint(QPainter *painter,
             fadeInPath.lineTo(0, rect().height());
             fadeInPath.lineTo(m_startFade, 0);
             fadeInPath.closeSubpath();
-            QPainterPath f1 = painter->worldTransform().map(fadeInPath);
+            QPainterPath f1 = transformation.map(fadeInPath);
             painter->fillPath(f1/*.intersected(resultClipPath)*/, fades);
             /*if (isSelected()) {
                 QLineF l(m_startFade * scale, 0, 0, itemHeight);
@@ -997,7 +1014,7 @@ void ClipItem::paint(QPainter *painter,
             fadeOutPath.lineTo(rect().width(), rect().height());
             fadeOutPath.lineTo(rect().width() - m_endFade, 0);
             fadeOutPath.closeSubpath();
-            QPainterPath f1 = painter->worldTransform().map(fadeOutPath);
+            QPainterPath f1 = transformation.map(fadeOutPath);
             painter->fillPath(f1/*.intersected(resultClipPath)*/, fades);
             /*if (isSelected()) {
                 QLineF l(itemWidth - m_endFade * scale, 0, itemWidth, itemHeight);
@@ -1008,7 +1025,7 @@ void ClipItem::paint(QPainter *painter,
 
         painter->setPen(QPen(Qt::lightGray));
         // draw effect or transition keyframes
-        drawKeyFrames(painter, m_limitedKeyFrames);
+        drawKeyFrames(painter, transformation, m_limitedKeyFrames);
     }
     
     // draw clip border
@@ -1041,10 +1058,32 @@ OPERATIONTYPE ClipItem::operationMode(QPointF pos)
     if (qAbs((int)(pos.x() - (rect.x() + m_startFade))) < maximumOffset  && qAbs((int)(pos.y() - rect.y())) < 6) {
         return FADEIN;
     } else if ((pos.x() <= rect.x() + rect.width() / 2) && pos.x() - rect.x() < maximumOffset && (rect.bottom() - pos.y() > addtransitionOffset)) {
+       // If we are in a group, allow resize only if all clips start at same position
+       if (parentItem()) {
+           QGraphicsItemGroup *dragGroup = static_cast <QGraphicsItemGroup *>(parentItem());
+           QList<QGraphicsItem *> list = dragGroup->childItems();
+           for (int i = 0; i < list.count(); i++) {
+               if (list.at(i)->type() == AVWIDGET) {
+                   ClipItem *c = static_cast <ClipItem*>(list.at(i));
+                   if (c->startPos() != startPos()) return MOVE;
+               }
+           }
+       }
         return RESIZESTART;
     } else if (qAbs((int)(pos.x() - (rect.x() + rect.width() - m_endFade))) < maximumOffset && qAbs((int)(pos.y() - rect.y())) < 6) {
         return FADEOUT;
     } else if ((pos.x() >= rect.x() + rect.width() / 2) && (rect.right() - pos.x() < maximumOffset) && (rect.bottom() - pos.y() > addtransitionOffset)) {
+       // If we are in a group, allow resize only if all clips end at same position
+       if (parentItem()) {
+           QGraphicsItemGroup *dragGroup = static_cast <QGraphicsItemGroup *>(parentItem());
+           QList<QGraphicsItem *> list = dragGroup->childItems();
+           for (int i = 0; i < list.count(); i++) {
+               if (list.at(i)->type() == AVWIDGET) {
+                   ClipItem *c = static_cast <ClipItem*>(list.at(i));
+                   if (c->endPos() != endPos()) return MOVE;
+               }
+           }
+       }
         return RESIZEEND;
     } else if ((pos.x() - rect.x() < 16 / scale) && (rect.bottom() - pos.y() <= addtransitionOffset)) {
         return TRANSITIONSTART;
@@ -1100,15 +1139,13 @@ QList <CommentedTime> ClipItem::commentedSnapMarkers() const
     return snaps;
 }
 
-void ClipItem::slotPrepareAudioThumb(double pixelForOneFrame, int startpixel, int endpixel, int channels)
+void ClipItem::slotPrepareAudioThumb(double pixelForOneFrame, int startpixel, int endpixel, int channels, int pixelHeight)
 {
     // Bail out, if caller provided invalid data
     if (channels <= 0) {
        kWarning() << "Unable to draw image with " << channels << "number of channels";
         return;
     }
-    QRectF re =  sceneBoundingRect();
-    if (m_clipType == AV && !isAudioOnly()) re.setTop(re.y() + re.height() / 2);
     int factor = 64;
     if (KdenliveSettings::normaliseaudiothumbs()) {
        factor = m_clip->getProperty("audio_max").toInt();
@@ -1121,7 +1158,7 @@ void ClipItem::slotPrepareAudioThumb(double pixelForOneFrame, int startpixel, in
     QPen audiopen;
     audiopen.setWidth(0);
     if (simplifiedAudio) channels = 1;
-    int channelHeight = re.height() / channels;
+    int channelHeight = pixelHeight / channels;
     QMap<int, QPainterPath > positiveChannelPaths;
     QMap<int, QPainterPath > negativeChannelPaths;
 
@@ -1129,7 +1166,7 @@ void ClipItem::slotPrepareAudioThumb(double pixelForOneFrame, int startpixel, in
         if (m_framePixelWidth == pixelForOneFrame && m_audioThumbCachePic.contains(startCache))
             continue;
         if (m_audioThumbCachePic.value(startCache).isNull() || m_framePixelWidth != pixelForOneFrame) {
-           QPixmap pix(100, (int)(re.height()));
+           QPixmap pix(100, pixelHeight);
            pix.fill(QColor(180, 180, 180, 150));
            m_audioThumbCachePic[startCache] = pix;
         }
@@ -1195,6 +1232,7 @@ void ClipItem::slotPrepareAudioThumb(double pixelForOneFrame, int startpixel, in
            pixpainter.setPen(audiopen);
            pixpainter.setBrush(Qt::NoBrush);
        }
+       pixpainter.setRenderHint(QPainter::Antialiasing, false);
         for (int i = 0; i < channels; i++) {
             if (fullAreaDraw) {
                 pixpainter.drawPath(positiveChannelPaths[i].united(negativeChannelPaths.value(i)));
@@ -1630,7 +1668,7 @@ EffectsParameterList ClipItem::addEffect(QDomElement effect, bool /*animate*/)
     else if (fade < 0) m_endFade = -fade;
 
     if (m_selectedEffect == -1) {
-        setSelectedEffect(0);
+        setSelectedEffect(1);
     } else if (m_selectedEffect == ix - 1) setSelectedEffect(m_selectedEffect);
     if (needRepaint) update(boundingRect());
     /*if (animate) {