]> git.sesse.net Git - kdenlive/blobdiff - src/clipitem.cpp
Improve update of effect stack when resizing clip, start implementing merge of analys...
[kdenlive] / src / clipitem.cpp
index 7b95d695fcd774d49b5cad202f42bfbcfd4ac3f3..14389f9af6a91740de186186284beed4273dbdea 100644 (file)
@@ -188,21 +188,21 @@ void ClipItem::setEffectList(const EffectsList effectList)
                         }
                     } else if (effectId == "fadeout") {
                         if (m_effectList.hasEffect(QString(), "fade_to_black") == -1) {
-                            if (e.attribute("name") == "out") fade -= e.attribute("value").toInt();
-                            else if (e.attribute("name") == "in") fade += e.attribute("value").toInt();
+                            if (e.attribute("name") == "out") fade += e.attribute("value").toInt();
+                            else if (e.attribute("name") == "in") fade -= e.attribute("value").toInt();
                         } else {
                             QDomElement fadeout = m_effectList.getEffectByTag(QString(), "fade_to_black");
-                            if (fadeout.attribute("name") == "out") fade -= fadeout.attribute("value").toInt();
-                            else if (fadeout.attribute("name") == "in") fade += fadeout.attribute("value").toInt();
+                            if (fadeout.attribute("name") == "out") fade += fadeout.attribute("value").toInt();
+                            else if (fadeout.attribute("name") == "in") fade -= fadeout.attribute("value").toInt();
                         }
                     } else if (effectId == "fade_to_black") {
                         if (m_effectList.hasEffect(QString(), "fadeout") == -1) {
-                            if (e.attribute("name") == "out") fade -= e.attribute("value").toInt();
-                            else if (e.attribute("name") == "in") fade += e.attribute("value").toInt();
+                            if (e.attribute("name") == "out") fade += e.attribute("value").toInt();
+                            else if (e.attribute("name") == "in") fade -= e.attribute("value").toInt();
                         } else {
                             QDomElement fadeout = m_effectList.getEffectByTag(QString(), "fadeout");
-                            if (fadeout.attribute("name") == "out") fade -= fadeout.attribute("value").toInt();
-                            else if (fadeout.attribute("name") == "in") fade += fadeout.attribute("value").toInt();
+                            if (fadeout.attribute("name") == "out") fade += fadeout.attribute("value").toInt();
+                            else if (fadeout.attribute("name") == "in") fade -= fadeout.attribute("value").toInt();
                         }
                     }
                 }
@@ -768,29 +768,39 @@ void ClipItem::paint(QPainter *painter,
                      const QStyleOptionGraphicsItem *option,
                      QWidget *)
 {
+    QPalette palette = scene()->palette();
     QColor paintColor;
+    QColor textColor;
+    QColor textBgColor;
     QPen framePen;
     if (parentItem()) paintColor = QColor(255, 248, 149);
     else paintColor = m_baseColor;
     if (isSelected() || (parentItem() && parentItem()->isSelected())) {
+       textColor = palette.highlightedText().color();
+       textBgColor = palette.highlight().color();
         paintColor = paintColor.darker();
-        framePen.setColor(Qt::red);
-        framePen.setWidthF(2.0);
+        framePen.setColor(textBgColor);
     }
     else {
+       textColor = palette.text().color();
+       textBgColor = palette.window().color();
+       textBgColor.setAlpha(200);
         framePen.setColor(paintColor.darker());
     }
-
     const QRectF exposed = option->exposedRect;
-    painter->setClipRect(exposed);
-    painter->fillRect(exposed, paintColor);
-    painter->setWorldMatrixEnabled(false);;
+    const QRectF mappedExposed = painter->worldTransform().mapRect(exposed);
     const QRectF mapped = painter->worldTransform().mapRect(rect());
+    painter->setWorldMatrixEnabled(false);
+    QPainterPath p;
+    p.addRect(mappedExposed);
+    QPainterPath q;
+    q.addRoundedRect(mapped.adjusted(0, 0, -0.5, 0), 3, 3);
+    painter->setClipPath(p.intersected(q));
+    painter->setPen(Qt::NoPen);
+    painter->fillRect(mappedExposed, paintColor);
+    painter->setPen(paintColor.darker());
     // draw thumbnails
     if (KdenliveSettings::videothumbnails() && !isAudioOnly()) {
-        QPen pen = painter->pen();
-        pen.setColor(QColor(255, 255, 255, 150));
-        painter->setPen(pen);
         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);
@@ -823,11 +833,10 @@ void ClipItem::paint(QPainter *painter,
             else {
 #if KDE_IS_VERSION(4,5,0)
                 if (m_clip && m_clip->thumbProducer()) {
-                    QString path = m_clip->fileURL().path() + "_";
+                    QString path = m_clip->fileURL().path() + '_';
                     QImage img;
                     QPen pen(Qt::white);
                     pen.setStyle(Qt::DotLine);
-                    painter->setPen(pen);
                     QList <int> missing;
                     for (int i = left; i <= right; i++) {
                         img = m_clip->thumbProducer()->findCachedThumb(path + QString::number(i));
@@ -844,7 +853,6 @@ void ClipItem::paint(QPainter *painter,
 #endif
             }
         }
-        painter->setPen(Qt::black);
     }
 
     // draw audio thumbnails
@@ -892,36 +900,38 @@ void ClipItem::paint(QPainter *painter,
         // Draw effects names
         if (!m_effectNames.isEmpty() && mapped.width() > 40) {
             QRectF txtBounding = painter->boundingRect(mapped, Qt::AlignLeft | Qt::AlignTop, m_effectNames);
-            QColor bgColor;
+            QColor bColor = palette.window().color();
+           QColor tColor = palette.text().color();
+           tColor.setAlpha(220);
             if (m_timeLine && m_timeLine->state() == QTimeLine::Running) {
                 qreal value = m_timeLine->currentValue();
                 txtBounding.setWidth(txtBounding.width() * value);
-                bgColor.setRgb(50 + 200 *(1.0 - value), 50, 50, 100 + 50 * value);
-            } else bgColor.setRgb(50, 50, 90, 180);
-
-            QPainterPath rounded;
-            rounded.moveTo(txtBounding.bottomRight());
-            rounded.arcTo(txtBounding.right() - txtBounding.height() - 2, txtBounding.top() - txtBounding.height(), txtBounding.height() * 2, txtBounding.height() * 2, 270, 90);
-            rounded.lineTo(txtBounding.topLeft());
-            rounded.lineTo(txtBounding.bottomLeft());
-            painter->fillPath(rounded, bgColor);
-            painter->setPen(Qt::lightGray);
-            painter->drawText(txtBounding.adjusted(1, 0, 1, 0), Qt::AlignCenter, m_effectNames);
+                bColor.setAlpha(100 + 50 * value);
+            };
+
+           painter->setBrush(bColor);
+           painter->setPen(Qt::NoPen);
+           painter->drawRoundedRect(txtBounding.adjusted(-1, -2, 4, -1), 3, 3);
+            painter->setPen(tColor);
+            painter->drawText(txtBounding.adjusted(2, 0, 1, -1), Qt::AlignCenter, m_effectNames);
         }
 
-        const QRectF txtBounding2 = painter->boundingRect(mapped, Qt::AlignHCenter | Qt::AlignVCenter, ' ' + m_clipName + ' ');
-        painter->setBrush(framePen.color());
-        painter->setPen(Qt::NoPen);
-        painter->drawRoundedRect(txtBounding2, 3, 3);
+        // Draw clip name
+        const QRectF txtBounding2 = painter->boundingRect(mapped, Qt::AlignRight | Qt::AlignTop, m_clipName + ' ').adjusted(0, -1, 0, -1);
+       painter->setPen(Qt::NoPen);
+       if (m_isMainSelectedClip) {
+           framePen.setColor(Qt::red);
+           textBgColor = Qt::red;
+       }
+        painter->fillRect(txtBounding2.adjusted(-3, 0, 0, 0), textBgColor);
         painter->setBrush(QBrush(Qt::NoBrush));
-
+       painter->setPen(textColor);
         if (m_videoOnly) {
             painter->drawPixmap(txtBounding2.topLeft() - QPointF(17, -1), m_videoPix);
         } else if (m_audioOnly) {
             painter->drawPixmap(txtBounding2.topLeft() - QPointF(17, -1), m_audioPix);
         }
-        painter->setPen(Qt::white);
-        painter->drawText(txtBounding2, Qt::AlignCenter, m_clipName);
+        painter->drawText(txtBounding2, Qt::AlignLeft, m_clipName);
 
 
         // draw markers
@@ -930,10 +940,8 @@ void ClipItem::paint(QPainter *painter,
             QList < CommentedTime >::Iterator it = markers.begin();
             GenTime pos;
             double framepos;
-            QBrush markerBrush(QColor(120, 120, 0, 140));
+           QBrush markerBrush(QColor(120, 120, 0, 140));
             QPen pen = painter->pen();
-            pen.setColor(QColor(255, 255, 255, 200));
-            pen.setStyle(Qt::DotLine);
 
             for (; it != markers.end(); ++it) {
                 pos = GenTime((int)((*it).time().frames(m_fps) / qAbs(m_speed) + 0.5), m_fps) - cropStart();
@@ -941,17 +949,20 @@ void ClipItem::paint(QPainter *painter,
                     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);
+                   pen.setColor(CommentedTime::markerColor((*it).markerType()));
+                   pen.setStyle(Qt::DotLine);
                     painter->setPen(pen);
                     painter->drawLine(l2);
                     if (KdenliveSettings::showmarkers()) {
                         framepos = rect().x() + pos.frames(m_fps);
-                        const QRectF r1(framepos + 0.04, 10, rect().width() - framepos - 2, rect().height() - 10);
+                        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 txtBounding3 = painter->boundingRect(r2, Qt::AlignLeft | Qt::AlignTop, ' ' + (*it).comment() + ' ');
                         painter->setBrush(markerBrush);
-                        painter->setPen(Qt::NoPen);
-                        painter->drawRoundedRect(txtBounding3, 3, 3);
-                        painter->setBrush(QBrush(Qt::NoBrush));
+                       pen.setStyle(Qt::SolidLine);
+                        painter->setPen(pen);
+                        painter->drawRect(txtBounding3);
+                        painter->setBrush(Qt::NoBrush);
                         painter->setPen(Qt::white);
                         painter->drawText(txtBounding3, Qt::AlignCenter, (*it).comment());
                     }
@@ -1002,13 +1013,10 @@ void ClipItem::paint(QPainter *painter,
     // draw clip border
     // expand clip rect to allow correct painting of clip border
     painter->setClipping(false);
+    painter->setRenderHint(QPainter::Antialiasing, true);
+    framePen.setWidthF(1.5);
     painter->setPen(framePen);
-    if (isSelected() || (parentItem() && parentItem()->isSelected())) {
-        painter->drawRect(mapped.adjusted(0.5, 0.5, -0.5, -0.5));
-    }
-    else {
-        painter->drawRect(mapped.adjusted(0, 0, -0.5, 0));
-    }
+    painter->drawRoundedRect(mapped.adjusted(0, 0, -0.5, -0.5), 3, 3);
 }
 
 
@@ -1026,8 +1034,8 @@ OPERATIONTYPE ClipItem::operationMode(QPointF pos)
     }
     QRectF rect = sceneBoundingRect();
     int addtransitionOffset = 10;
-    // Don't allow add transition if track height is very small
-    if (rect.height() < 30) addtransitionOffset = 0;
+    // Don't allow add transition if track height is very small. No transitions for audio only clips
+    if (rect.height() < 30 || isAudioOnly() || m_clipType == AUDIO) addtransitionOffset = 0;
 
     if (qAbs((int)(pos.x() - (rect.x() + m_startFade))) < maximumOffset  && qAbs((int)(pos.y() - rect.y())) < 6) {
         return FADEIN;
@@ -1060,7 +1068,8 @@ void ClipItem::resetFrameWidth(int width)
 QList <GenTime> ClipItem::snapMarkers() const
 {
     QList < GenTime > snaps;
-    QList < GenTime > markers = baseClip()->snapMarkers();
+    if (!m_clip) return snaps;
+    QList < GenTime > markers = m_clip->snapMarkers();
     GenTime pos;
 
     for (int i = 0; i < markers.size(); i++) {
@@ -1076,14 +1085,15 @@ QList <GenTime> ClipItem::snapMarkers() const
 QList <CommentedTime> ClipItem::commentedSnapMarkers() const
 {
     QList < CommentedTime > snaps;
-    QList < CommentedTime > markers = baseClip()->commentedSnapMarkers();
+    if (!m_clip) return snaps;
+    QList < CommentedTime > markers = m_clip->commentedSnapMarkers();
     GenTime pos;
 
     for (int i = 0; i < markers.size(); i++) {
         pos = GenTime((int)(markers.at(i).time().frames(m_fps) / qAbs(m_speed) + 0.5), m_fps) - cropStart();
         if (pos > GenTime()) {
             if (pos > cropDuration()) break;
-            else snaps.append(CommentedTime(pos + startPos(), markers.at(i).comment()));
+            else snaps.append(CommentedTime(pos + startPos(), markers.at(i).comment(), markers.at(i).markerType()));
         }
     }
     return snaps;
@@ -1134,7 +1144,7 @@ void ClipItem::slotPrepareAudioThumb(double pixelForOneFrame, int startpixel, in
             int sample = (int)((frame - (int)(frame)) * 20);   // AUDIO_FRAME_SIZE
             if (frame < 0 || sample < 0 || sample > 19)
                 continue;
-            QMap<int, QByteArray> frame_channel_data = baseClip()->m_audioFrameCache[(int)frame];
+            QMap<int, QByteArray> frame_channel_data = baseClip()->audioFrameCache[(int)frame];
 
             for (int channel = 0; channel < channels && frame_channel_data[channel].size() > 0; channel++) {
 
@@ -1240,7 +1250,7 @@ void ClipItem::hoverLeaveEvent(QGraphicsSceneHoverEvent *)
 }
 */
 
-void ClipItem::resizeStart(int posx, bool /*size*/)
+void ClipItem::resizeStart(int posx, bool /*size*/, bool emitChange)
 {
     bool sizeLimit = false;
     if (clipType() != IMAGE && clipType() != COLOR && clipType() != TEXT) {
@@ -1263,9 +1273,10 @@ void ClipItem::resizeStart(int posx, bool /*size*/)
             m_startThumbTimer.start(150);
         }
     }
+    if (m_isMainSelectedClip && emitChange) emit updateRange();
 }
 
-void ClipItem::resizeEnd(int posx)
+void ClipItem::resizeEnd(int posx, bool emitChange)
 {
     const int max = (startPos() - cropStart() + maxDuration()).frames(m_fps);
     if (posx > max && maxDuration() != GenTime()) posx = max;
@@ -1284,6 +1295,7 @@ void ClipItem::resizeEnd(int posx)
             m_endThumbTimer.start(150);
         }
     }
+    if (m_isMainSelectedClip && emitChange) emit updateRange();
 }
 
 //virtual
@@ -1301,7 +1313,9 @@ QVariant ClipItem::itemChange(GraphicsItemChange change, const QVariant &value)
         int xpos = projectScene()->getSnapPointForPos((int) newPos.x(), KdenliveSettings::snaptopoints());
         xpos = qMax(xpos, 0);
         newPos.setX(xpos);
-        int newTrack = newPos.y() / KdenliveSettings::trackheight();
+       // Warning: newPos gives a position relative to the click event, so hack to get absolute pos
+       int yOffset = property("y_absolute").toInt() + newPos.y();
+        int newTrack = yOffset / KdenliveSettings::trackheight();
         newTrack = qMin(newTrack, projectScene()->tracksCount() - 1);
         newTrack = qMax(newTrack, 0);
         newPos.setY((int)(newTrack  * KdenliveSettings::trackheight() + 1));
@@ -1539,14 +1553,14 @@ EffectsParameterList ClipItem::addEffect(QDomElement effect, bool /*animate*/)
                 needInOutSync = true;
             }
             if (e.attribute("type") == "simplekeyframe") {
-                QStringList values = e.attribute("keyframes").split(";", QString::SkipEmptyParts);
+                QStringList values = e.attribute("keyframes").split(';', QString::SkipEmptyParts);
                 double factor = locale.toDouble(e.attribute("factor", "1"));
                 double offset = e.attribute("offset", "0").toDouble();
                 if (factor != 1 || offset != 0) {
                     for (int j = 0; j < values.count(); j++) {
                         QString pos = values.at(j).section(':', 0, 0);
                         double val = (locale.toDouble(values.at(j).section(':', 1, 1)) - offset) / factor;
-                        values[j] = pos + "=" + locale.toString(val);
+                        values[j] = pos + '=' + locale.toString(val);
                     }
                 }
                 parameters.addParam(e.attribute("name"), values.join(";"));
@@ -1650,8 +1664,8 @@ void ClipItem::setSpeed(const double speed, const int strobe)
     if (m_speed <= 0 && m_speed > -1)
         m_speed = -1.0;
     m_strobe = strobe;
-    if (m_speed == 1.0) m_clipName = baseClip()->name();
-    else m_clipName = baseClip()->name() + " - " + QString::number(speed * 100, 'f', 0) + '%';
+    if (m_speed == 1.0) m_clipName = m_clip->name();
+    else m_clipName = m_clip->name() + " - " + QString::number(speed * 100, 'f', 0) + '%';
     m_info.cropStart = GenTime((int)(m_speedIndependantInfo.cropStart.frames(m_fps) / qAbs(m_speed) + 0.5), m_fps);
     m_info.cropDuration = GenTime((int)(m_speedIndependantInfo.cropDuration.frames(m_fps) / qAbs(m_speed) + 0.5), m_fps);
     //update();
@@ -1797,18 +1811,18 @@ void ClipItem::insertKeyframe(QDomElement effect, int pos, int val)
                     newkfr.append(str);
                 } else if (!added) {
                     if (i == m_visibleParam)
-                        newkfr.append(QString::number(pos) + ":" + QString::number(val));
+                        newkfr.append(QString::number(pos) + ':' + QString::number(val));
                     else
-                        newkfr.append(QString::number(pos) + ":" + locale.toString(newval));
+                        newkfr.append(QString::number(pos) + ':' + locale.toString(newval));
                     if (kpos > pos) newkfr.append(str);
                     added = true;
                 } else newkfr.append(str);
             }
             if (!added) {
                 if (i == m_visibleParam)
-                    newkfr.append(QString::number(pos) + ":" + QString::number(val));
+                    newkfr.append(QString::number(pos) + ':' + QString::number(val));
                 else
-                    newkfr.append(QString::number(pos) + ":" + e.attribute("default"));
+                    newkfr.append(QString::number(pos) + ':' + e.attribute("default"));
             }
             e.setAttribute("keyframes", newkfr.join(";"));
         }
@@ -1836,9 +1850,9 @@ void ClipItem::movedKeyframe(QDomElement effect, int oldpos, int newpos, double
                     newpos = qMax(newpos, start);
                     newpos = qMin(newpos, end);
                     if (i == m_visibleParam)
-                        newkfr.append(QString::number(newpos) + ":" + locale.toString(value));
+                        newkfr.append(QString::number(newpos) + ':' + locale.toString(value));
                     else
-                        newkfr.append(QString::number(newpos) + ":" + str.section(':', 1, 1));
+                        newkfr.append(QString::number(newpos) + ':' + str.section(':', 1, 1));
                 }
             }
             e.setAttribute("keyframes", newkfr.join(";"));
@@ -1875,7 +1889,7 @@ Mlt::Producer *ClipItem::getProducer(int track, bool trackSpecific)
     if (isAudioOnly())
         return m_clip->audioProducer(track);
     else if (isVideoOnly())
-        return m_clip->videoProducer();
+        return m_clip->videoProducer(track);
     else
         return m_clip->getProducer(trackSpecific ? track : -1);
 }
@@ -2055,13 +2069,13 @@ void ClipItem::updateGeometryKeyframes(QDomElement effect, int paramIndex, int w
     if (offset > 0) {
         QStringList kfrs = data.split(';');
         data.clear();
-        foreach (QString keyframe, kfrs) {
+        foreach (const QString &keyframe, kfrs) {
             if (keyframe.contains('=')) {
                 int pos = keyframe.section('=', 0, 0).toInt();
                 pos += offset;
-                data.append(QString::number(pos) + "=" + keyframe.section('=', 1) + ";");
+                data.append(QString::number(pos) + '=' + keyframe.section('=', 1) + ";");
             }
-            else data.append(keyframe + ";");
+            else data.append(keyframe + ';');
         }
     }
     Mlt::Geometry geometry(data.toUtf8().data(), oldInfo.cropDuration.frames(m_fps), width, height);
@@ -2074,5 +2088,6 @@ void ClipItem::slotGotThumbsCache()
     update();
 }
 
+
 #include "clipitem.moc"