#include <QGraphicsScene>
#include <QMimeData>
-ClipItem::ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, int strobe, bool generateThumbs) :
+static int FRAME_SIZE;
+
+ClipItem::ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, int strobe, int frame_width, bool generateThumbs) :
AbstractClipItem(info, QRectF(), fps),
m_clip(clip),
m_startFade(0),
m_limitedKeyFrames(false)
{
setZValue(2);
+ FRAME_SIZE = frame_width;
setRect(0, 0, (info.endPos - info.startPos).frames(fps) - 0.02, (double) itemHeight());
setPos(info.startPos.frames(fps), (double)(info.track * KdenliveSettings::trackheight()) + 1 + itemOffset());
ClipItem *ClipItem::clone(ItemInfo info) const
{
- ClipItem *duplicate = new ClipItem(m_clip, info, m_fps, m_speed, m_strobe);
+ ClipItem *duplicate = new ClipItem(m_clip, info, m_fps, m_speed, m_strobe, FRAME_SIZE);
if (m_clipType == IMAGE || m_clipType == TEXT) duplicate->slotSetStartThumb(m_startPix);
else if (m_clipType != COLOR) {
if (info.cropStart == m_info.cropStart) duplicate->slotSetStartThumb(m_startPix);
QWidget *)
{
QColor paintColor;
+ QPen framePen;
if (parentItem()) paintColor = QColor(255, 248, 149);
else paintColor = m_baseColor;
- if (isSelected() || (parentItem() && parentItem()->isSelected())) paintColor = paintColor.darker();
+ if (isSelected() || (parentItem() && parentItem()->isSelected())) {
+ paintColor = paintColor.darker();
+ framePen.setColor(Qt::red);
+ framePen.setWidth(2);
+ }
+ else {
+ framePen.setColor(paintColor.darker());
+ }
- painter->setMatrixEnabled(false);
- const QRectF mapped = painter->matrix().mapRect(rect()).adjusted(0.5, 0, 0.5, 0);
const QRectF exposed = option->exposedRect;
- painter->setClipRect(mapped);
- painter->fillRect(mapped, paintColor);
-
+ painter->fillRect(exposed, paintColor);
+ painter->setClipRect(exposed);
+ painter->setMatrixEnabled(false);
+ const QRectF mapped = painter->matrix().mapRect(rect()).adjusted(0, 0, 1.0, 0.5);
// draw thumbnails
if (KdenliveSettings::videothumbnails() && !isAudioOnly()) {
QPen pen = painter->pen();
QLineF l2(mapped.left() + m_startPix.width(), mapped.top(), mapped.left() + m_startPix.width(), mapped.bottom());
painter->drawLine(l2);
}
- if (painter->matrix().m11() == FRAME_SIZE && m_clip->thumbProducer() && clipType() != COLOR && clipType() != AUDIO && !m_audioOnly) {
+
+ // if we are in full zoom, paint thumbnail for every frame
+ if (m_clip->thumbProducer() && clipType() != COLOR && clipType() != AUDIO && !m_audioOnly && painter->matrix().m11() == FRAME_SIZE) {
int offset = (m_info.startPos - m_info.cropStart).frames(m_fps);
- int left = qMax((int) m_info.startPos.frames(m_fps) + 1, (int) mapToScene(exposed.left(), 0).x()) - offset;
- int right = qMin((int)(m_info.startPos + m_info.cropDuration).frames(m_fps) - 1, (int) mapToScene(exposed.right(), 0).x()) - offset;
+ 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);
QPointF startPos = mapped.topLeft();
- int twidth = FRAME_SIZE;
int startOffset = m_info.cropStart.frames(m_fps);
if (clipType() == IMAGE || clipType() == TEXT) {
for (int i = left; i <= right; i++) {
- painter->drawPixmap(startPos + QPointF(twidth *(i - startOffset), 0), m_startPix);
+ painter->drawPixmap(startPos + QPointF(FRAME_SIZE *(i - startOffset), 0), m_startPix);
}
}
else {
#if KDE_IS_VERSION(4,5,0)
if (m_clip && m_clip->thumbProducer()) {
- m_clip->thumbProducer()->queryIntraThumbs(left, right);
- connect(m_clip->thumbProducer(), SIGNAL(thumbsCached()), this, SLOT(slotGotThumbsCache()));
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++) {
- painter->drawImage(startPos + QPointF(twidth *(i - startOffset), 0), m_clip->thumbProducer()->findCachedThumb(path + QString::number(i)));
+ 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);
+ painter->drawLine(xpos, xpos + QPointF(0, mapped.height()));
+ }
+ if (!missing.isEmpty()) {
+ m_clip->thumbProducer()->queryIntraThumbs(missing);
+ connect(m_clip->thumbProducer(), SIGNAL(thumbsCached()), this, SLOT(slotGotThumbsCache()));
}
}
#endif
const int mappedEndPixel = painter->matrix().map(QPointF(endpixel + cropLeft, 0)).x() - clipStart;
cropLeft = cropLeft * scale;
-
if (channels >= 1) {
emit prepareAudioThumb(scale, mappedStartPixel, mappedEndPixel, channels);
}
}
}
- // Draw effects names
- if (!m_effectNames.isEmpty() && mapped.width() > 40) {
- QRectF txtBounding = painter->boundingRect(mapped, Qt::AlignLeft | Qt::AlignTop, m_effectNames);
- QColor bgColor;
- 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);
- }
-
- // Draw clip name
- QColor frameColor(paintColor.darker());
- if (isSelected() || (parentItem() && parentItem()->isSelected())) {
- frameColor = QColor(Qt::red);
- }
- frameColor.setAlpha(160);
-
- const QRectF txtBounding2 = painter->boundingRect(mapped, Qt::AlignHCenter | Qt::AlignVCenter, ' ' + m_clipName + ' ');
- //painter->fillRect(txtBounding2, frameColor);
- painter->setBrush(frameColor);
- painter->setPen(Qt::NoPen);
- painter->drawRoundedRect(txtBounding2, 3, 3);
- painter->setBrush(QBrush(Qt::NoBrush));
-
- //painter->setPen(QColor(0, 0, 0, 180));
- //painter->drawText(txtBounding, Qt::AlignCenter, m_clipName);
- 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);
+ // only paint details if clip is big enough
+ if (mapped.width() > 20) {
+
+ // Draw effects names
+ if (!m_effectNames.isEmpty() && mapped.width() > 40) {
+ QRectF txtBounding = painter->boundingRect(mapped, Qt::AlignLeft | Qt::AlignTop, m_effectNames);
+ QColor bgColor;
+ 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);
+ }
+ 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);
+ painter->setBrush(QBrush(Qt::NoBrush));
- // draw markers
- if (isEnabled() && m_clip) {
- QList < CommentedTime > markers = m_clip->commentedSnapMarkers();
- QList < CommentedTime >::Iterator it = markers.begin();
- GenTime pos;
- double framepos;
- 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();
- 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->matrix().map(l);
- 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 r2 = painter->matrix().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));
- painter->setPen(Qt::white);
- painter->drawText(txtBounding3, Qt::AlignCenter, (*it).comment());
+ 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);
+
+
+ // draw markers
+ if (isEnabled() && m_clip) {
+ QList < CommentedTime > markers = m_clip->commentedSnapMarkers();
+ QList < CommentedTime >::Iterator it = markers.begin();
+ GenTime pos;
+ double framepos;
+ 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();
+ 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->matrix().map(l);
+ 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 r2 = painter->matrix().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));
+ painter->setPen(Qt::white);
+ painter->drawText(txtBounding3, Qt::AlignCenter, (*it).comment());
+ }
+ //painter->fillRect(QRect(br.x() + framepos, br.y(), 10, br.height()), QBrush(QColor(0, 0, 0, 150)));
}
- //painter->fillRect(QRect(br.x() + framepos, br.y(), 10, br.height()), QBrush(QColor(0, 0, 0, 150)));
}
}
- }
- // draw start / end fades
- QBrush fades;
- if (isSelected()) {
- fades = QBrush(QColor(200, 50, 50, 150));
- } else fades = QBrush(QColor(200, 200, 200, 200));
-
- if (m_startFade != 0) {
- QPainterPath fadeInPath;
- fadeInPath.moveTo(0, 0);
- fadeInPath.lineTo(0, rect().height());
- fadeInPath.lineTo(m_startFade, 0);
- fadeInPath.closeSubpath();
- QPainterPath f1 = painter->matrix().map(fadeInPath);
- painter->fillPath(f1/*.intersected(resultClipPath)*/, fades);
- /*if (isSelected()) {
- QLineF l(m_startFade * scale, 0, 0, itemHeight);
- painter->drawLine(l);
- }*/
- }
- if (m_endFade != 0) {
- QPainterPath fadeOutPath;
- fadeOutPath.moveTo(rect().width(), 0);
- fadeOutPath.lineTo(rect().width(), rect().height());
- fadeOutPath.lineTo(rect().width() - m_endFade, 0);
- fadeOutPath.closeSubpath();
- QPainterPath f1 = painter->matrix().map(fadeOutPath);
- painter->fillPath(f1/*.intersected(resultClipPath)*/, fades);
- /*if (isSelected()) {
- QLineF l(itemWidth - m_endFade * scale, 0, itemWidth, itemHeight);
- painter->drawLine(l);
- }*/
- }
-
-
- painter->setPen(QPen(Qt::lightGray));
- // draw effect or transition keyframes
- if (mapped.width() > 20) drawKeyFrames(painter, m_limitedKeyFrames);
+ // draw start / end fades
+ QBrush fades;
+ if (isSelected()) {
+ fades = QBrush(QColor(200, 50, 50, 150));
+ } else fades = QBrush(QColor(200, 200, 200, 200));
+
+ if (m_startFade != 0) {
+ QPainterPath fadeInPath;
+ fadeInPath.moveTo(0, 0);
+ fadeInPath.lineTo(0, rect().height());
+ fadeInPath.lineTo(m_startFade, 0);
+ fadeInPath.closeSubpath();
+ QPainterPath f1 = painter->matrix().map(fadeInPath);
+ painter->fillPath(f1/*.intersected(resultClipPath)*/, fades);
+ /*if (isSelected()) {
+ QLineF l(m_startFade * scale, 0, 0, itemHeight);
+ painter->drawLine(l);
+ }*/
+ }
+ if (m_endFade != 0) {
+ QPainterPath fadeOutPath;
+ fadeOutPath.moveTo(rect().width(), 0);
+ fadeOutPath.lineTo(rect().width(), rect().height());
+ fadeOutPath.lineTo(rect().width() - m_endFade, 0);
+ fadeOutPath.closeSubpath();
+ QPainterPath f1 = painter->matrix().map(fadeOutPath);
+ painter->fillPath(f1/*.intersected(resultClipPath)*/, fades);
+ /*if (isSelected()) {
+ QLineF l(itemWidth - m_endFade * scale, 0, itemWidth, itemHeight);
+ painter->drawLine(l);
+ }*/
+ }
- //painter->setMatrixEnabled(true);
+ painter->setPen(QPen(Qt::lightGray));
+ // draw effect or transition keyframes
+ drawKeyFrames(painter, m_limitedKeyFrames);
+ }
+
// draw clip border
// expand clip rect to allow correct painting of clip border
- QPen pen1(frameColor);
- painter->setPen(pen1);
painter->setClipping(false);
- painter->drawRect(painter->matrix().mapRect(rect()));
+ painter->setPen(framePen);
+ if (isSelected() || (parentItem() && parentItem()->isSelected())) {
+ painter->drawRect(mapped.adjusted(1.0, 0.5, -1.5, -0.5));
+ }
+ else {
+ painter->drawRect(mapped.adjusted(0, 0.5, -0.5, -0.5));
+ }
}
return KdenliveSettings::trackheight() - 2;
}
+void ClipItem::resetFrameWidth(int width)
+{
+ FRAME_SIZE = width;
+ update();
+}
+
QList <GenTime> ClipItem::snapMarkers() const
{
QList < GenTime > snaps;
Q_OBJECT
public:
- ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, int strobe, bool generateThumbs = true);
+ ClipItem(DocClipBase *clip, ItemInfo info, double fps, double speed, int strobe, int frame_width, bool generateThumbs = true);
virtual ~ ClipItem();
virtual void paint(QPainter *painter,
const QStyleOptionGraphicsItem *option,
* @return Fitting producer
* Which producer is returned depends on the type of this clip (audioonly, videoonly, normal) */
Mlt::Producer *getProducer(int track, bool trackSpecific = true);
+ void resetFrameWidth(int width);
protected:
//virtual void mouseMoveEvent(QGraphicsSceneMouseEvent * event);
connect(&m_modifiedTimer, SIGNAL(timeout()), this, SLOT(slotProcessModifiedClips()));
#if KDE_IS_VERSION(4,5,0)
+ KImageCache::deleteCache("kdenlive-thumbs");
pixmapCache = new KImageCache("kdenlive-thumbs", 1000000);
+ pixmapCache->setEvictionPolicy(KSharedDataCache::EvictOldest);
#endif
}
#endif
}
+void ClipManager::clearCache()
+{
+#if KDE_IS_VERSION(4,5,0)
+ pixmapCache->clear();
+#endif
+}
+
void ClipManager::checkAudioThumbs()
{
if (!KdenliveSettings::audiothumbnails()) {
void addFolder(const QString&, const QString&);
void deleteFolder(const QString&);
void clear();
+ void clearCache();
AbstractGroupItem *createGroup();
void removeGroup(AbstractGroupItem *group);
QDomElement groupsXml() const;
static const int LITTLE_MARK_X2 = LINE_END;
static const int LITTLE_MARK_X1 = (LITTLE_MARK_X2 - LITTLE_MARK_LENGTH);
+static int FRAME_SIZE;
static int LABEL_SIZE;
static const int END_LABEL_X = 4;
static const int END_LABEL_Y = (END_LABEL_X + LABEL_SIZE - 2);
m_duration(0),
m_offset(0),
m_clickedGuide(-1),
- m_mouseMove(NO_MOVE)
+ m_mouseMove(NO_MOVE),
+ m_rate(-1)
{
setFont(KGlobalSettings::toolBarFont());
QFontMetricsF fontMetrics(font());
LABEL_SIZE = fontMetrics.ascent() - 2;
+ updateFrameSize();
m_scale = 3;
m_zoneColor = KStatefulBrush(KColorScheme::View, KColorScheme::PositiveBackground, KSharedConfig::openConfig(KdenliveSettings::colortheme())).brush(this).color();
- littleMarkDistance = FRAME_SIZE;
- mediumMarkDistance = FRAME_SIZE * m_timecode.fps();
- bigMarkDistance = FRAME_SIZE * m_timecode.fps() * 60;
m_zoneStart = 0;
m_zoneEnd = 100;
m_contextMenu = new QMenu(this);
update();
}
+void CustomRuler::updateFrameSize()
+{
+ FRAME_SIZE = m_view->getFrameWidth();
+ kDebug()<<"// GOT FRM SZ: "<<FRAME_SIZE;
+ littleMarkDistance = FRAME_SIZE;
+ mediumMarkDistance = FRAME_SIZE * m_timecode.fps();
+ bigMarkDistance = FRAME_SIZE * m_timecode.fps() * 60;
+ updateProjectFps(m_timecode);
+ if (m_rate > 0) setPixelPerMark(m_rate);
+}
+
void CustomRuler::slotEditGuide()
{
m_view->slotEditGuide(m_clickedGuide);
void setZone(QPoint p);
int offset() const;
void updateProjectFps(Timecode t);
-
+ void updateFrameSize();
protected:
virtual void paintEvent(QPaintEvent * /*e*/);
virtual void wheelEvent(QWheelEvent * e);
return m_scene->m_tracksList;
}*/
-void CustomTrackView::checkTrackHeight()
+
+int CustomTrackView::getFrameWidth()
+{
+ return (int) (m_tracksHeight * m_document->mltProfile().display_aspect_num / m_document->mltProfile().display_aspect_den + 0.5);
+}
+
+void CustomTrackView::updateSceneFrameWidth()
+{
+ int frameWidth = getFrameWidth();
+ QList<QGraphicsItem *> itemList = items();
+ ClipItem *item;
+ for (int i = 0; i < itemList.count(); i++) {
+ if (itemList.at(i)->type() == AVWIDGET) {
+ item = (ClipItem*) itemList.at(i);
+ item->resetFrameWidth(frameWidth);
+ item->resetThumbs(true);
+ }
+ }
+}
+
+bool CustomTrackView::checkTrackHeight()
{
- if (m_tracksHeight == KdenliveSettings::trackheight()) return;
+ if (m_tracksHeight == KdenliveSettings::trackheight()) return false;
m_tracksHeight = KdenliveSettings::trackheight();
emit trackHeightChanged();
QList<QGraphicsItem *> itemList = items();
ClipItem *item;
Transition *transitionitem;
+ int frameWidth = getFrameWidth();
bool snap = KdenliveSettings::snaptopoints();
KdenliveSettings::setSnaptopoints(false);
for (int i = 0; i < itemList.count(); i++) {
item = (ClipItem*) itemList.at(i);
item->setRect(0, 0, item->rect().width(), m_tracksHeight - 1);
item->setPos((qreal) item->startPos().frames(m_document->fps()), (qreal) item->track() * m_tracksHeight + 1);
+ item->resetFrameWidth(frameWidth);
item->resetThumbs(true);
} else if (itemList.at(i)->type() == TRANSITIONWIDGET) {
transitionitem = (Transition*) itemList.at(i);
// verticalScrollBar()->setMaximum(m_tracksHeight * m_document->tracksCount());
KdenliveSettings::setSnaptopoints(snap);
viewport()->update();
+ return true;
}
/** Zoom or move viewport on mousewheel
// check item under mouse
QList<QGraphicsItem *> collisionList = items(m_clickEvent);
-
if (event->modifiers() == Qt::ControlModifier && m_tool != SPACERTOOL && collisionList.count() == 0) {
// Pressing Ctrl + left mouse button in an empty area scrolls the timeline
setDragMode(QGraphicsView::ScrollHandDrag);
} else {
setCursorPos((int)(mapToScene(event->x(), 0).x()));
}
- QGraphicsView::mousePressEvent(event);
+ //QGraphicsView::mousePressEvent(event);
+ event->ignore();
return;
}
return true;
}
m_selectionGroup = new AbstractGroupItem(m_document->fps());
- ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0, 1);
+ ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0, 1, getFrameWidth());
m_selectionGroup->addToGroup(item);
item->setFlag(QGraphicsItem::ItemIsMovable, false);
info.track = 0;
start += info.cropDuration;
offsetList.append(start);
- ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0, 1, false);
+ ClipItem *item = new ClipItem(clip, info, m_document->fps(), 1.0, 1, getFrameWidth(), false);
item->setFlag(QGraphicsItem::ItemIsMovable, false);
m_selectionGroup->addToGroup(item);
if (!clip->isPlaceHolder()) m_waitingThumbs.append(item);
m_mutex.unlock();
}
- ClipItem *item = new ClipItem(baseclip, info, m_document->fps(), xml.attribute("speed", "1").toDouble(), xml.attribute("strobe", "1").toInt());
+ ClipItem *item = new ClipItem(baseclip, info, m_document->fps(), xml.attribute("speed", "1").toDouble(), xml.attribute("strobe", "1").toInt(), getFrameWidth());
item->setEffectList(effects);
if (xml.hasAttribute("audio_only")) item->setAudioOnly(true);
else if (xml.hasAttribute("video_only")) item->setVideoOnly(true);
/** @brief Cuts all clips that are selected at the timeline cursor position. */
void cutSelectedClips();
void setContextMenu(QMenu *timeline, QMenu *clip, QMenu *transition, QActionGroup *clipTypeGroup, QMenu *markermenu);
- void checkTrackHeight();
+ bool checkTrackHeight();
+ void updateSceneFrameWidth();
//QList <TrackInfo> tracksList() const;
void setTool(PROJECTTOOL tool);
ClipItem *cutClip(ItemInfo info, GenTime cutTime, bool cut, bool execute = true);
* Check whether given track has a clip with audio in it. */
bool hasAudio(int track) const;
+ int getFrameWidth();
+
public slots:
void setCursorPos(int pos, bool seek = true);
void moveCursorPos(int delta);
#include <QTreeWidgetItem>
#include <KLocale>
-const int FRAME_SIZE = 90;
const int MAXCLIPDURATION = 15000;
enum OPERATIONTYPE { NONE = 0, MOVE = 1, RESIZESTART = 2, RESIZEEND = 3, FADEIN = 4, FADEOUT = 5, TRANSITIONSTART = 6, TRANSITIONEND = 7, MOVEGUIDE = 8, KEYFRAME = 9, SEEK = 10, SPACER = 11, RUBBERSELECTION = 12};
if (producer->is_blank() == false) {
int width = 45.0 * profile.dar();
+ int swidth = 45.0 * profile.width() / profile.height();
if (width % 2 == 1) width++;
- item->setIcon(0, QPixmap::fromImage(KThumb::getFrame(producer, 0, width, 45)));
+ item->setIcon(0, QPixmap::fromImage(KThumb::getFrame(producer, 0, swidth, width, 45)));
int playTime = producer->get_playtime();
item->setText(1, Timecode::getStringTimecode(playTime, profile.fps()));
item->setData(1, Qt::UserRole, playTime);
ItemInfo info;
m_effectedit->transferParamDesc(QDomElement(), info);
//m_ui.region_url->clear();
+ m_clipref = NULL;
m_ui.buttonShowComments->setEnabled(false);
m_ui.labelComment->setText(QString());
m_ui.effectlist->blockSignals(false);
m_url(url),
m_thumbFile(),
m_dar(1),
+ m_ratio(1),
m_producer(NULL),
m_clipManager(clipManager),
m_id(id),
m_producer = producer;
// FIXME: the profile() call leaks an object, but trying to free
// it leads to a double-free in Profile::~Profile()
- if (producer) m_dar = producer->profile()->dar();
+ if (producer) {
+ m_dar = producer->profile()->dar();
+ m_ratio = (double) producer->profile()->width() / producer->profile()->height();
+ }
+
}
void KThumb::clearProducer()
void KThumb::doGetThumbs()
{
const int theight = KdenliveSettings::trackheight();
- const int twidth = FRAME_SIZE;//(int)(theight * m_dar + 0.5);
+ const int swidth = (int)(theight * m_ratio + 0.5);
+ const int dwidth = (int)(theight * m_dar + 0.5);
while (!m_requestedThumbs.isEmpty()) {
int frame = m_requestedThumbs.takeFirst();
if (frame != -1) {
- QImage img = getFrame(m_producer, frame, twidth, theight);
+ QImage img = getFrame(m_producer, frame, swidth, dwidth, theight);
emit thumbReady(frame, img);
}
}
QPixmap KThumb::extractImage(int frame, int width, int height)
{
- return QPixmap::fromImage(getFrame(m_producer, frame, width, height));
+ return QPixmap::fromImage(getFrame(m_producer, frame, (int) (height * m_ratio + 0.5), width, height));
}
//static
//"<mlt><playlist><producer resource=\"" + url.path() + "\" /></playlist></mlt>");
//Mlt::Producer producer(profile, "xml-string", tmp);
Mlt::Producer *producer = new Mlt::Producer(profile, url.path().toUtf8().constData());
-
- pix = QPixmap::fromImage(getFrame(producer, frame, width, height));
+ double swidth = (double) profile.width() / profile.height();
+ pix = QPixmap::fromImage(getFrame(producer, frame, (int) (height * swidth + 0.5), width, height));
delete producer;
return pix;
}
//static
-QImage KThumb::getFrame(Mlt::Producer *producer, int framepos, int width, int height)
+QImage KThumb::getFrame(Mlt::Producer *producer, int framepos, int frameWidth, int displayWidth, int height)
{
- QImage p(width, height, QImage::Format_ARGB32_Premultiplied);
+ QImage p(displayWidth, height, QImage::Format_ARGB32_Premultiplied);
if (producer == NULL || !producer->is_valid()) {
p.fill(Qt::red);
return p;
producer->seek(framepos);
Mlt::Frame *frame = producer->get_frame();
- if (!frame) {
- kDebug() << "///// BROKEN FRAME";
+ p = getFrame(frame, frameWidth, displayWidth, height);
+ delete frame;
+ return p;
+}
+
+
+//static
+QImage KThumb::getFrame(Mlt::Frame *frame, int frameWidth, int displayWidth, int height)
+{
+ QImage p(displayWidth, height, QImage::Format_ARGB32_Premultiplied);
+ if (frame == NULL || !frame->is_valid()) {
p.fill(Qt::red);
return p;
}
- int ow = width;
+ int ow = frameWidth;
int oh = height;
mlt_image_format format = mlt_image_rgb24a;
uint8_t *data = frame->get_image(format, ow, oh, 0);
QImage image((uchar *)data, ow, oh, QImage::Format_ARGB32_Premultiplied);
- //mlt_service_unlock(service.get_service());
-
if (!image.isNull()) {
- if (ow > (2 * width)) {
+ if (ow > (2 * displayWidth)) {
// there was a scaling problem, do it manually
- QImage scaled = image.scaled(width, height);
- p = scaled.rgbSwapped();
- } else p = image.rgbSwapped();
+ QImage scaled = image.scaled(displayWidth, height);
+ image = scaled.rgbSwapped();
+ } else {
+ image = image.scaled(displayWidth, height, Qt::IgnoreAspectRatio).rgbSwapped();
+ }
+ QPainter painter(&p);
+ painter.fillRect(p.rect(), Qt::black);
+ painter.setCompositionMode(QPainter::CompositionMode_SourceOver);
+ painter.drawImage(p.rect(), image);
+ painter.end();
} else
p.fill(Qt::red);
-
- delete frame;
return p;
}
-
//static
uint KThumb::imageVariance(QImage image )
{
}
#if KDE_IS_VERSION(4,5,0)
-void KThumb::queryIntraThumbs(int start, int end)
+void KThumb::queryIntraThumbs(QList <int> missingFrames)
{
- for (int i = start; i <= end; i++) {
+ foreach (int i, missingFrames) {
if (!m_intraFramesQueue.contains(i)) m_intraFramesQueue.append(i);
}
qSort(m_intraFramesQueue);
void KThumb::slotGetIntraThumbs()
{
- int theight = KdenliveSettings::trackheight();
- int twidth = FRAME_SIZE;
+ const int theight = KdenliveSettings::trackheight();
+ const int frameWidth = (int)(theight * m_ratio + 0.5);
+ const int displayWidth = (int)(theight * m_dar + 0.5);
QString path = m_url.path() + "_";
- QImage img;
+ bool addedThumbs = false;
while (!m_intraFramesQueue.isEmpty()) {
int pos = m_intraFramesQueue.takeFirst();
if (!m_clipManager->pixmapCache->contains(path + QString::number(pos))) {
- m_clipManager->pixmapCache->insertImage(path + QString::number(pos), getFrame(m_producer, pos, twidth, theight));
+ if (m_clipManager->pixmapCache->insertImage(path + QString::number(pos), getFrame(m_producer, pos, frameWidth, displayWidth, theight))) {
+ addedThumbs = true;
+ }
+ else kDebug()<<"// INSERT FAILD FOR: "<<pos;
}
m_intraFramesQueue.removeAll(pos);
}
- emit thumbsCached();
+ if (addedThumbs) emit thumbsCached();
}
QImage KThumb::findCachedThumb(const QString path)
QPixmap extractImage(int frame, int width, int height);
#if KDE_IS_VERSION(4,5,0)
/** @brief Request thumbnails for the frame range. */
- void queryIntraThumbs(int start, int end);
+ void queryIntraThumbs(QList <int> missingFrames);
/** @brief Query cached thumbnail. */
QImage findCachedThumb(const QString path);
#endif
void removeAudioThumb();
void getAudioThumbs(int channel, double frame, double frameLength, int arrayWidth);
static QPixmap getImage(KUrl url, int frame, int width, int height);
- static QImage getFrame(Mlt::Producer *producer, int framepos, int width, int height);
+ static QImage getFrame(Mlt::Producer *producer, int framepos, int frameWidth, int displayWidth, int height);
+ static QImage getFrame(Mlt::Frame *frame, int frameWidth, int displayWidth, int height);
/** @brief Calculates image variance, useful to know if a thumbnail is interesting.
* @return an integer between 0 and 100. 0 means no variance, eg. black image while bigger values mean contrasted image
* */
KUrl m_url;
QString m_thumbFile;
double m_dar;
+ double m_ratio;
Mlt::Producer *m_producer;
ClipManager *m_clipManager;
QString m_id;
if (m_renderWidget) m_renderWidget->setProfile(m_activeDocument->mltProfile());
m_timelineArea->setTabText(m_timelineArea->currentIndex(), m_activeDocument->description());
if (updateFps) m_activeTimeline->updateProjectFps();
+ m_activeDocument->clipManager()->clearCache();
+ m_activeTimeline->updateProfile();
m_activeDocument->setModified(true);
m_commandStack->activeStack()->clear();
//Update the mouse position display so it will display in DF/NDF format by default based on the project setting.
if (m_activeTimeline) {
m_activeTimeline->refresh();
m_activeTimeline->projectView()->checkAutoScroll();
- m_activeTimeline->projectView()->checkTrackHeight();
+ m_activeTimeline->checkTrackHeight();
if (m_activeDocument)
m_activeDocument->clipManager()->checkAudioThumbs();
}
if (width % 2 == 1) width++;
QPixmap p(width, 100);
QString colour = clip->getProperty("colour");
+ int swidth = (int) (100.0 * m_profile->width() / m_profile->height() + 0.5);
switch (m_clip->clipType()) {
case VIDEO:
connect(this, SIGNAL(updateThumb()), m_previewTimer, SLOT(start()));
case IMAGE:
case TEXT:
- p = QPixmap::fromImage(KThumb::getFrame(m_producer, m_in->getValue(), width, 100));
+ p = QPixmap::fromImage(KThumb::getFrame(m_producer, m_in->getValue(), swidth, width, 100));
break;
case COLOR:
colour = colour.replace(0, 2, "#");
m_previewTimer->stop();
int pos = m_in->getValue();
int width = 100.0 * m_dar;
+ int swidth = (int) (100.0 * m_profile->width() / m_profile->height() + 0.5);
if (width % 2 == 1) width++;
- QPixmap p = QPixmap::fromImage(KThumb::getFrame(m_producer, pos, width, 100));
+ QPixmap p = QPixmap::fromImage(KThumb::getFrame(m_producer, pos, swidth, width, 100));
if (!p.isNull())
clip_thumb->setPixmap(p);
else
}
QPixmap pix;
int height = m_listView->iconSize().height();
- int width = (int)(height * m_render->dar());
+ int swidth = (int)(height * m_render->frameRenderWidth() / m_render->renderHeight()+ 0.5);
+ int dwidth = (int)(height * m_render->dar() + 0.5);
if (clip->clipType() == AUDIO)
- pix = KIcon("audio-x-generic").pixmap(QSize(width, height));
+ pix = KIcon("audio-x-generic").pixmap(QSize(dwidth, height));
else if (clip->clipType() == IMAGE)
- pix = QPixmap::fromImage(KThumb::getFrame(item->referencedClip()->producer(), 0, width, height));
+ pix = QPixmap::fromImage(KThumb::getFrame(item->referencedClip()->producer(), 0, swidth, dwidth, height));
else
- pix = item->referencedClip()->extractImage(frame, width, height);
+ pix = item->referencedClip()->extractImage(frame, dwidth, height);
if (!pix.isNull()) {
monitorItemEditing(false);
setenv("MLT_PROFILE", tmp, 1);
m_mltProfile = new Mlt::Profile(tmp);
m_mltProfile->set_explicit(true);
+ kDebug()<<"// ********* PROFILE AR: "<<m_mltProfile->dar();
delete[] tmp;
m_blackClip = new Mlt::Producer(*m_mltProfile, "colour", "black");
QImage Render::extractFrame(int frame_position, QString path, int width, int height)
{
if (width == -1) {
- width = renderWidth();
+ width = frameRenderWidth();
height = renderHeight();
} else if (width % 2 == 1) width++;
-
+ int dwidth = height * frameRenderWidth() / renderHeight();
if (!path.isEmpty()) {
Mlt::Producer *producer = new Mlt::Producer(*m_mltProfile, path.toUtf8().constData());
if (producer) {
if (producer->is_valid()) {
- QImage img = KThumb::getFrame(producer, frame_position, width, height);
+ QImage img = KThumb::getFrame(producer, frame_position, dwidth, width, height);
delete producer;
return img;
}
pix.fill(Qt::black);
return pix;
}
- return KThumb::getFrame(m_mltProducer, frame_position, width, height);
+ return KThumb::getFrame(m_mltProducer, frame_position, dwidth, width, height);
}
QPixmap Render::getImageThumbnail(KUrl url, int /*width*/, int /*height*/)
return;
}
- int width = (int)(imageHeight * m_mltProfile->dar() + 0.5);
+ int imageWidth = (int)((double) imageHeight * m_mltProfile->width() / m_mltProfile->height() + 0.5);
+ int fullWidth = (int)((double) imageHeight * m_mltProfile->dar() + 0.5);
QMap < QString, QString > filePropertyMap;
QMap < QString, QString > metadataPropertyMap;
int variance;
mlt_image_format format = mlt_image_rgb24a;
- int frame_width = width;
+ int frame_width = imageWidth;
int frame_height = imageHeight;
- QPixmap pix;
+ QImage img;
do {
variance = 100;
- uint8_t *data = frame->get_image(format, frame_width, frame_height, 0);
- QImage image((uchar *)data, frame_width, frame_height, QImage::Format_ARGB32_Premultiplied);
-
- if (!image.isNull()) {
- if (frame_width > (2 * width)) {
- // there was a scaling problem, do it manually
- QImage scaled = image.scaled(width, imageHeight);
- pix = QPixmap::fromImage(scaled.rgbSwapped());
- } else pix = QPixmap::fromImage(image.rgbSwapped());
- variance = KThumb::imageVariance(image);
- } else
- pix.fill(Qt::black);
-
+ img = KThumb::getFrame(frame, imageWidth, fullWidth, imageHeight);
+ variance = KThumb::imageVariance(img);
if (frameNumber == 0 && variance< 6) {
// Thumbnail is not interesting (for example all black, seek to fetch better thumb
frameNumber = 100;
variance = -1;
}
} while (variance == -1);
+ QPixmap pix = QPixmap::fromImage(img);
emit replyGetImage(clipId, pix);
} else if (frame->get_int("test_audio") == 0) {
- QPixmap pixmap = KIcon("audio-x-generic").pixmap(QSize(width, imageHeight));
+ QPixmap pixmap = KIcon("audio-x-generic").pixmap(QSize(fullWidth, imageHeight));
emit replyGetImage(clipId, pixmap);
filePropertyMap["type"] = "audio";
}
if (mute && trackProducer.get_int("hide") < 2 ) {
// We mute a track with sound
if (track == getLowestNonMutedAudioTrack(tractor)) audioMixingBroken = true;
+ kDebug()<<"Muting track: "<<track <<" / "<<getLowestNonMutedAudioTrack(tractor);
}
else if (!mute && trackProducer.get_int("hide") > 1 ) {
// We un-mute a previously muted track
void TrackView::slotChangeZoom(int horizontal, int vertical)
{
m_ruler->setPixelPerMark(horizontal);
- m_scale = (double) FRAME_SIZE / m_ruler->comboScale[horizontal];
+ m_scale = (double) m_trackview->getFrameWidth() / m_ruler->comboScale[horizontal];
if (vertical == -1) {
// user called zoom
int TrackView::fitZoom() const
{
- int zoom = (int)((duration() + 20 / m_scale) * FRAME_SIZE / m_trackview->width());
+ int zoom = (int)((duration() + 20 / m_scale) * m_trackview->getFrameWidth() / m_trackview->width());
int i;
for (i = 0; i < 13; i++)
if (m_ruler->comboScale[i] > zoom) break;
// parse track
int position = 0;
QMap <QString, QString> producerReplacementIds;
+ int frame_width = m_trackview->getFrameWidth();
QDomNodeList children = xml.childNodes();
for (int nodeindex = 0; nodeindex < children.count(); nodeindex++) {
QDomNode n = children.item(nodeindex);
clipinfo.track = ix;
//kDebug() << "// INSERTING CLIP: " << in << "x" << out << ", track: " << ix << ", ID: " << id << ", SCALE: " << m_scale << ", FPS: " << m_doc->fps();
- ClipItem *item = new ClipItem(clip, clipinfo, m_doc->fps(), speed, strobe, false);
+ ClipItem *item = new ClipItem(clip, clipinfo, m_doc->fps(), speed, strobe, frame_width, false);
if (idString.endsWith("_video")) item->setVideoOnly(true);
else if (idString.endsWith("_audio")) item->setAudioOnly(true);
m_scene->addItem(item);
img.save(path);
}
+void TrackView::updateProfile()
+{
+ m_ruler->updateFrameSize();
+ m_trackview->updateSceneFrameWidth();
+ slotChangeZoom(m_doc->zoom().x(), m_doc->zoom().y());
+ slotSetZone(m_doc->zone(), false);
+}
+
+void TrackView::checkTrackHeight()
+{
+ if (m_trackview->checkTrackHeight()) {
+ m_doc->clipManager()->clearCache();
+ m_ruler->updateFrameSize();
+ m_trackview->updateSceneFrameWidth();
+ slotChangeZoom(m_doc->zoom().x(), m_doc->zoom().y());
+ slotSetZone(m_doc->zone(), false);
+ }
+}
#include "trackview.moc"
* Parses all tracks to check if there is audio data. */
bool checkProjectAudio() const;
+ void checkTrackHeight();
+ void updateProfile();
+
protected:
virtual void keyPressEvent(QKeyEvent * event);
{
setZValue(3);
m_info.cropDuration = info.endPos - info.startPos;
- setPos(info.startPos.frames(fps), (qreal)(info.track * KdenliveSettings::trackheight() + itemOffset() + 1));
+ setPos(info.startPos.frames(fps), (int)(info.track * KdenliveSettings::trackheight() + itemOffset() + 1));
#if QT_VERSION >= 0x040600
m_startAnimation = new QPropertyAnimation(this, "rect");
const QRectF exposed = option->exposedRect;
painter->setClipRect(exposed);
const QRectF br = rect();
+ QPen framePen;
const QRectF mapped = painter->matrix().mapRect(br);
painter->fillRect(exposed, brush());
- //int top = (int)(br.y() + br.height() / 2 - 7);
QPointF p1(br.x(), br.y() + br.height() / 2 - 7);
painter->setMatrixEnabled(false);
- //painter->drawPixmap(painter->matrix().map(p1) + QPointF(5, 0), transitionPixmap());
const QString text = m_name + (m_forceTransitionTrack ? "|>" : QString());
// Draw clip name
- QColor frameColor(brush().color().darker());
if (isSelected() || (parentItem() && parentItem()->isSelected())) {
- frameColor = QColor(Qt::red);
+ framePen.setColor(Qt::red);
+ framePen.setWidthF(2.0);
+ }
+ else {
+ framePen.setColor(brush().color().darker());
}
- frameColor.setAlpha(160);
const QRectF txtBounding = painter->boundingRect(mapped, Qt::AlignHCenter | Qt::AlignVCenter, ' ' + text + ' ');
- //painter->fillRect(txtBounding2, frameColor);
- painter->setBrush(frameColor);
+ painter->setBrush(framePen.color());
painter->setPen(Qt::NoPen);
painter->drawRoundedRect(txtBounding, 3, 3);
painter->setBrush(QBrush(Qt::NoBrush));
painter->drawText(txtBounding, Qt::AlignCenter, text);
// Draw frame
- QPen pen = painter->pen();
- pen.setColor(frameColor);
- painter->setPen(pen);
+ painter->setPen(framePen);
painter->setClipping(false);
- painter->drawRect(painter->matrix().mapRect(rect()));
+ painter->drawRect(mapped.adjusted(1.0, 0, -1.0, 0));
}
int Transition::type() const
int newTrack = newPos.y() / KdenliveSettings::trackheight();
newTrack = qMin(newTrack, projectScene()->tracksCount() - 1);
newTrack = qMax(newTrack, 0);
- newPos.setY((int)(newTrack * KdenliveSettings::trackheight() + KdenliveSettings::trackheight() / 3 * 2));
+ newPos.setY((int)(newTrack * KdenliveSettings::trackheight() + itemOffset() + 1));
// Only one clip is moving
QRectF sceneShape = rect();
sceneShape.translate(newPos);