]> git.sesse.net Git - kdenlive/blob - src/customtrackview.cpp
1c216d530000ced52539fe4e8ce9fe9d89efa811
[kdenlive] / src / customtrackview.cpp
1 /***************************************************************************
2  *   Copyright (C) 2007 by Jean-Baptiste Mardelle (jb@kdenlive.org)        *
3  *                                                                         *
4  *   This program is free software; you can redistribute it and/or modify  *
5  *   it under the terms of the GNU General Public License as published by  *
6  *   the Free Software Foundation; either version 2 of the License, or     *
7  *   (at your option) any later version.                                   *
8  *                                                                         *
9  *   This program is distributed in the hope that it will be useful,       *
10  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
11  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
12  *   GNU General Public License for more details.                          *
13  *                                                                         *
14  *   You should have received a copy of the GNU General Public License     *
15  *   along with this program; if not, write to the                         *
16  *   Free Software Foundation, Inc.,                                       *
17  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA          *
18  ***************************************************************************/
19
20 #include <QMouseEvent>
21 #include <QStylePainter>
22 #include <QGraphicsItem>
23 #include <QDomDocument>
24 #include <QScrollBar>
25
26 #include <KDebug>
27 #include <KLocale>
28 #include <KUrl>
29
30 #include "customtrackview.h"
31 #include "clipitem.h"
32 #include "definitions.h"
33 #include "moveclipcommand.h"
34 #include "resizeclipcommand.h"
35 #include "addtimelineclipcommand.h"
36 #include "addeffectcommand.h"
37 #include "editeffectcommand.h"
38
39 CustomTrackView::CustomTrackView(KdenliveDoc *doc, QGraphicsScene * projectscene, QWidget *parent)
40     : QGraphicsView(projectscene, parent), m_tracksCount(0), m_cursorPos(0), m_dropItem(NULL), m_cursorLine(NULL), m_operationMode(NONE), m_startPos(QPointF()), m_dragItem(NULL), m_visualTip(NULL), m_moveOpMode(NONE), m_animation(NULL), m_projectDuration(0), m_scale(1.0), m_clickPoint(0), m_document(doc)
41 {
42   if (doc) m_commandStack = doc->commandStack();
43   else m_commandStack == NULL;
44   setMouseTracking(true);
45   setAcceptDrops(true);
46   m_animationTimer = new QTimeLine(800);
47   m_animationTimer->setFrameRange(0, 5);
48   m_animationTimer->setUpdateInterval(100);
49   m_animationTimer->setLoopCount(0);
50   m_tipColor = QColor(230, 50, 0, 150);
51   setContentsMargins(0, 0, 0, 0);
52   if (projectscene) {
53     m_cursorLine = projectscene->addLine(0, 0, 0, 50);
54     m_cursorLine->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIgnoresTransformations);
55     m_cursorLine->setZValue(1000);
56   }
57 }
58
59 void CustomTrackView::initView()
60 {
61
62 }
63
64 // virtual
65 void CustomTrackView::resizeEvent ( QResizeEvent * event )
66 {
67   QGraphicsView::resizeEvent(event);
68 }
69
70 // virtual
71 void CustomTrackView::wheelEvent ( QWheelEvent * e ) 
72 {
73   if (e->modifiers() == Qt::ControlModifier) {
74     if (e->delta() > 0) emit zoomIn();
75     else emit zoomOut();
76   }
77   else {
78     if (e->delta() > 0) horizontalScrollBar()->setValue (horizontalScrollBar()->value() + horizontalScrollBar()->singleStep ());
79     else  horizontalScrollBar()->setValue (horizontalScrollBar()->value() - horizontalScrollBar()->singleStep ());
80   }
81 }
82
83
84 // virtual 
85 void CustomTrackView::mouseMoveEvent ( QMouseEvent * event )
86 {
87   int pos = event->x();
88   emit mousePosition(mapToScene(event->pos()).x() / m_scale);
89   /*if (event->modifiers() == Qt::ControlModifier)
90     setDragMode(QGraphicsView::ScrollHandDrag);
91   else if (event->modifiers() == Qt::ShiftModifier) 
92     setDragMode(QGraphicsView::RubberBandDrag);
93   else*/ {
94
95       if (m_dragItem) { //event->button() == Qt::LeftButton) {
96         // a button was pressed, delete visual tips
97         if (m_operationMode == MOVE) {
98           double snappedPos = getSnapPointForPos(mapToScene(event->pos()).x() - m_clickPoint);
99           double moveX = snappedPos; //mapToScene(event->pos()).x();
100           //kDebug()<<"///////  MOVE CLIP, EVENT Y: "<<event->scenePos().y()<<", SCENE HEIGHT: "<<scene()->sceneRect().height();
101           int moveTrack = (int)  mapToScene(event->pos()).y() / 50;
102           int currentTrack = m_dragItem->track();
103
104           if (moveTrack > m_tracksCount - 1) moveTrack = m_tracksCount - 1;
105           else if (moveTrack < 0) moveTrack = 0;
106
107           int offset = moveTrack - currentTrack;
108           if (offset != 0) offset = 50 * offset;
109           m_dragItem->moveTo(moveX / m_scale, m_scale, offset, moveTrack);
110         }
111         else if (m_operationMode == RESIZESTART) {
112           int pos = mapToScene(event->pos()).x();
113           m_dragItem->resizeStart(pos / m_scale, m_scale);
114         }
115         else if (m_operationMode == RESIZEEND) {
116           int pos = mapToScene(event->pos()).x();
117           m_dragItem->resizeEnd(pos / m_scale, m_scale);
118         }
119         else if (m_operationMode == FADEIN) {
120           int pos = mapToScene(event->pos()).x() / m_scale;
121           m_dragItem->setFadeIn(pos - m_dragItem->startPos(), m_scale);
122         }
123         else if (m_operationMode == FADEOUT) {
124           int pos = mapToScene(event->pos()).x() / m_scale;
125           m_dragItem->setFadeOut(m_dragItem->endPos() - pos, m_scale);
126         }
127
128         if (m_animation) delete m_animation;
129         m_animation = NULL;
130         if (m_visualTip) delete m_visualTip;
131         m_visualTip = NULL;
132         QGraphicsView::mouseMoveEvent(event);
133         return;
134       }
135
136     QList<QGraphicsItem *> itemList = items( event->pos());
137     int i = 0;
138     QGraphicsItem *item = NULL;
139     for (int i = 0; i < itemList.count(); i++) {
140       if (itemList.at(i)->type() == 70000) {
141         item = itemList.at(i);
142         break;
143       }
144     }
145     if (item) {
146       ClipItem *clip = (ClipItem*) item;
147       double size = mapToScene(QPoint(8, 0)).x();
148       OPERATIONTYPE opMode = clip->operationMode(mapToScene(event->pos()), m_scale);
149       if (opMode == m_moveOpMode) {
150         QGraphicsView::mouseMoveEvent(event);
151         return;
152       }
153       else {
154       if (m_visualTip) {
155         if (m_animation) delete m_animation;
156         m_animation = NULL;
157         delete m_visualTip;
158         m_visualTip = NULL;
159       }
160       }
161       m_moveOpMode = opMode;
162       if (opMode == MOVE) {
163         setCursor(Qt::OpenHandCursor);
164       }
165       else if (opMode == RESIZESTART) {
166         kDebug()<<"********  RESIZE CLIP START; WIDTH: "<<size;
167         if (m_visualTip == NULL) {
168           m_visualTip = new QGraphicsRectItem(clip->rect().x(), clip->rect().y(), size, clip->rect().height());
169           ((QGraphicsRectItem*) m_visualTip)->setBrush(m_tipColor);
170           ((QGraphicsRectItem*) m_visualTip)->setPen(QPen(Qt::transparent));
171           m_visualTip->setZValue (100);
172           m_animation = new QGraphicsItemAnimation;
173           m_animation->setItem(m_visualTip);
174           m_animation->setTimeLine(m_animationTimer);
175           m_visualTip->setPos(0, 0);
176           double scale = 2.0;
177           m_animation->setScaleAt(.5, scale, 1);
178           m_animation->setPosAt(.5, QPointF(clip->rect().x() - clip->rect().x() * scale, 0));
179           scale = 1.0;
180           m_animation->setScaleAt(1, scale, 1);
181           m_animation->setPosAt(1, QPointF(clip->rect().x() - clip->rect().x() * scale, 0));
182           scene()->addItem(m_visualTip);
183           m_animationTimer->start();
184         }
185         setCursor(Qt::SizeHorCursor);
186       }
187       else if (opMode == RESIZEEND) {
188         if (m_visualTip == NULL) {
189           m_visualTip = new QGraphicsRectItem(clip->rect().x() + clip->rect().width() - size, clip->rect().y(), size, clip->rect().height());
190           ((QGraphicsRectItem*) m_visualTip)->setBrush(m_tipColor);
191           ((QGraphicsRectItem*) m_visualTip)->setPen(QPen(Qt::transparent));
192           m_visualTip->setZValue (100);
193           m_animation = new QGraphicsItemAnimation;
194           m_animation->setItem(m_visualTip);
195           m_animation->setTimeLine(m_animationTimer);
196           m_visualTip->setPos(0, 0);
197           double scale = 2.0;
198           m_animation->setScaleAt(.5, scale, 1);
199           m_animation->setPosAt(.5, QPointF(clip->rect().x() - clip->rect().x() * scale - clip->rect().width(), 0));
200           scale = 1.0;
201           m_animation->setScaleAt(1, scale, 1);
202           m_animation->setPosAt(1, QPointF(clip->rect().x() - clip->rect().x() * scale, 0));
203           scene()->addItem(m_visualTip);
204           m_animationTimer->start();
205         }
206         setCursor(Qt::SizeHorCursor);
207       }
208       else if (opMode == FADEIN) {
209         if (m_visualTip == NULL) {
210           m_visualTip = new QGraphicsEllipseItem(clip->rect().x() + clip->fadeIn() * m_scale - size, clip->rect().y() - 8, size * 2, 16);
211           ((QGraphicsEllipseItem*) m_visualTip)->setBrush(m_tipColor);
212           ((QGraphicsEllipseItem*) m_visualTip)->setPen(QPen(Qt::transparent));
213           m_visualTip->setZValue (100);
214           m_animation = new QGraphicsItemAnimation;
215           m_animation->setItem(m_visualTip);
216           m_animation->setTimeLine(m_animationTimer);
217           m_visualTip->setPos(0, 0);
218           double scale = 2.0;
219           m_animation->setScaleAt(.5, scale, scale);
220           m_animation->setPosAt(.5, QPointF(clip->rect().x() - clip->rect().x() * scale -  clip->fadeIn() * m_scale, clip->rect().y() - clip->rect().y() * scale));
221           scale = 1.0;
222           m_animation->setScaleAt(1, scale, scale);
223           m_animation->setPosAt(1, QPointF(clip->rect().x() - clip->rect().x() * scale, clip->rect().y() - clip->rect().y() * scale));
224           scene()->addItem(m_visualTip);
225           m_animationTimer->start();
226         }
227         setCursor(Qt::PointingHandCursor);
228       }
229       else if (opMode == FADEOUT) {
230         if (m_visualTip == NULL) {
231           m_visualTip = new QGraphicsEllipseItem(clip->rect().x() + clip->rect().width() - clip->fadeOut() * m_scale - size, clip->rect().y() - 8, size*2, 16);
232           ((QGraphicsEllipseItem*) m_visualTip)->setBrush(m_tipColor);
233           ((QGraphicsEllipseItem*) m_visualTip)->setPen(QPen(Qt::transparent));
234           m_visualTip->setZValue (100);
235           m_animation = new QGraphicsItemAnimation;
236           m_animation->setItem(m_visualTip);
237           m_animation->setTimeLine(m_animationTimer);
238           m_visualTip->setPos(0, 0);
239           double scale = 2.0;
240           m_animation->setScaleAt(.5, scale, scale);      
241           m_animation->setPosAt(.5, QPointF(clip->rect().x() - clip->rect().x() * scale - clip->rect().width() + clip->fadeOut() * m_scale, clip->rect().y() - clip->rect().y() * scale));
242           scale = 1.0;
243           m_animation->setScaleAt(1, scale, scale);
244           m_animation->setPosAt(1, QPointF(clip->rect().x() - clip->rect().x() * scale, clip->rect().y() - clip->rect().y() * scale));
245           scene()->addItem(m_visualTip);
246           m_animationTimer->start();
247         }
248         setCursor(Qt::PointingHandCursor);
249       }
250     }
251     else {
252       m_moveOpMode = NONE;
253       if (m_visualTip) {
254         if (m_animation) delete m_animation;
255         m_animation = NULL;
256         delete m_visualTip;
257         m_visualTip = NULL;
258       }
259       setCursor(Qt::ArrowCursor);
260     }
261   }
262   QGraphicsView::mouseMoveEvent(event);
263 }
264
265 // virtual 
266 void CustomTrackView::mousePressEvent ( QMouseEvent * event )
267 {
268   kDebug()<<"-- TIMELINE MSE PRESSED";
269   int pos = event->x();
270   if (event->modifiers() == Qt::ControlModifier) {
271     setDragMode(QGraphicsView::ScrollHandDrag);
272     QGraphicsView::mousePressEvent(event);
273     return;
274   }
275   else if (event->modifiers() == Qt::ShiftModifier) {
276     setDragMode(QGraphicsView::RubberBandDrag);
277     QGraphicsView::mousePressEvent(event);
278     return;
279   }
280   else {
281     bool collision = false;
282     QList<QGraphicsItem *> collisionList = items(event->pos());
283     for (int i = 0; i < collisionList.size(); ++i) {
284       QGraphicsItem *item = collisionList.at(i);
285       if (item->type() == 70000) {
286         // select item
287         if (!item->isSelected()) {
288           QList<QGraphicsItem *> itemList = items();
289           for (int i = 0; i < itemList.count(); i++)
290             itemList.at(i)->setSelected(false);
291           item->setSelected(true);
292           update();
293         }
294         m_dragItem = (ClipItem *) item;
295         emit clipItemSelected(m_dragItem);
296         m_clickPoint = mapToScene(event->pos()).x() - m_dragItem->startPos() * m_scale;
297         m_operationMode = m_dragItem->operationMode(item->mapFromScene(mapToScene(event->pos())), m_scale);
298         if (m_operationMode == MOVE || m_operationMode == RESIZESTART) 
299           m_startPos = QPointF(m_dragItem->startPos(), m_dragItem->track());
300         else if (m_operationMode == RESIZEEND) 
301           m_startPos = QPointF(m_dragItem->endPos(), m_dragItem->track());
302         kDebug()<<"//////// ITEM CLICKED: "<<m_startPos;
303         collision = true;
304         break;
305       }
306     }
307     if (!collision) {
308       kDebug()<<"//////// NO ITEM FOUND ON CLICK";
309       m_dragItem = NULL;
310       setCursor(Qt::ArrowCursor);
311       QList<QGraphicsItem *> itemList = items();
312       for (int i = 0; i < itemList.count(); i++)
313         itemList.at(i)->setSelected(false);
314       emit clipItemSelected(NULL);
315       setCursorPos((int) mapToScene(event->x(), 0).x());
316       emit cursorMoved(cursorPos());
317     }
318   }
319   updateSnapPoints(m_dragItem);
320   //kDebug()<<pos;
321   //QGraphicsView::mousePressEvent(event);
322 }
323
324 void CustomTrackView::dragEnterEvent ( QDragEnterEvent * event )
325 {
326   if (event->mimeData()->hasText()) {
327     kDebug()<<"///////////////  DRAG ENTERED, TEXT: "<<event->mimeData()->text();
328     QStringList ids = QString(event->mimeData()->text()).split(";");
329     //TODO: drop of several clips
330     for (int i = 0; i < ids.size(); ++i) {
331     }
332     DocClipBase *clip = m_document->getBaseClip(ids.at(0).toInt());
333     if (clip == NULL) kDebug()<<" WARNING))))))))) CLIP NOT FOUND : "<<ids.at(0).toInt();
334     addItem(clip, event->pos());
335     event->acceptProposedAction();
336   }
337 }
338
339 void CustomTrackView::slotRefreshEffects(ClipItem *clip)
340 {
341   int track = m_tracksCount - clip->track();
342   GenTime pos = GenTime(clip->startPos(), m_document->fps());
343   m_document->renderer()->mltRemoveEffect(track, pos, "-1", false);
344   for (int i = 0; i < clip->effectsCount(); i++) {
345     m_document->renderer()->mltAddEffect(track, pos, clip->getEffectArgs(clip->effectAt(i)), false);
346   }
347   m_document->renderer()->doRefresh();
348 }
349
350 void CustomTrackView::addEffect(int track, GenTime pos, QDomElement effect)
351 {
352   ClipItem *clip = getClipItemAt(pos.frames(m_document->fps()) + 1, m_tracksCount - track);
353   if (clip){ 
354     QMap <QString, QString> effectParams = clip->addEffect(effect);
355     m_document->renderer()->mltAddEffect(track, pos, effectParams);
356     emit clipItemSelected(clip);
357   }
358 }
359
360 void CustomTrackView::deleteEffect(int track, GenTime pos, QDomElement effect)
361 {
362   QString index = effect.attribute("kdenlive_ix");
363   m_document->renderer()->mltRemoveEffect(track, pos, index);  
364   ClipItem *clip = getClipItemAt(pos.frames(m_document->fps()) + 1, m_tracksCount - track);
365         if (clip){
366                 clip->deleteEffect(index);
367                 emit clipItemSelected(clip);
368         }
369 }
370
371 void CustomTrackView::slotAddEffect(QDomElement effect)
372 {
373   QList<QGraphicsItem *> itemList = items();
374   for (int i = 0; i < itemList.count(); i++) {
375     if (itemList.at(i)->type() == 70000 && itemList.at(i)->isSelected()) {
376       ClipItem *item = (ClipItem *)itemList.at(i);
377       // the kdenlive_ix int is used to identify an effect in mlt's playlist, should
378       // not be changed
379       effect.setAttribute("kdenlive_ix", QString::number(item->effectsCounter()));
380       AddEffectCommand *command = new AddEffectCommand(this, m_tracksCount - item->track(),GenTime(item->startPos(), m_document->fps()), effect, true);
381       m_commandStack->push(command);    
382     }
383   }
384 }
385
386 void CustomTrackView::slotDeleteEffect(ClipItem *clip, QDomElement effect)
387 {
388   AddEffectCommand *command = new AddEffectCommand(this, m_tracksCount - clip->track(), GenTime(clip->startPos(), m_document->fps()), effect, false);
389   m_commandStack->push(command);
390 }
391
392 void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement effect)
393 {
394   ClipItem *clip = getClipItemAt(pos.frames(m_document->fps()) + 1, m_tracksCount - track);
395   if (clip){
396     QMap <QString, QString> effectParams = clip->getEffectArgs(effect);
397     m_document->renderer()->mltEditEffect(m_tracksCount - clip->track(), GenTime(clip->startPos(), m_document->fps()), effectParams);
398   }
399 }
400
401
402 void CustomTrackView::slotUpdateClipEffect(ClipItem *clip, QDomElement oldeffect, QDomElement effect)
403 {
404   EditEffectCommand *command = new EditEffectCommand(this, m_tracksCount - clip->track(), GenTime(clip->startPos(), m_document->fps()), oldeffect, effect, true);
405   m_commandStack->push(command);
406 }
407
408
409 void CustomTrackView::addItem(DocClipBase *clip, QPoint pos)
410 {
411   int in =0;
412   int out = clip->duration().frames(m_document->fps());
413   //kdDebug()<<"- - - -CREATING CLIP, duration = "<<out<<", URL: "<<clip->fileURL();
414   int trackTop = ((int) mapToScene(pos).y()/50) * 50 + 1;
415   m_dropItem = new ClipItem(clip, ((int) mapToScene(pos).y()/50), in, QRectF(mapToScene(pos).x() * m_scale, trackTop, out * m_scale, 49), out);
416   scene()->addItem(m_dropItem);
417 }
418
419
420 void CustomTrackView::dragMoveEvent(QDragMoveEvent * event) {
421   event->setDropAction(Qt::IgnoreAction);
422   if (m_dropItem) {
423     int track = (int) mapToScene(event->pos()).y()/50; //) * (m_scale * 50) + m_scale;
424      kDebug()<<"+++++++++++++   DRAG MOVE, : "<<mapToScene(event->pos()).x()<<", SCAL: "<<m_scale;
425     m_dropItem->moveTo(mapToScene(event->pos()).x() / m_scale, m_scale, (track - m_dropItem->track()) * 50, track);
426   }
427        //if (item) {
428   event->setDropAction(Qt::MoveAction);
429   if (event->mimeData()->hasText()) {
430     event->acceptProposedAction();
431   }
432         //}
433 }
434
435 void CustomTrackView::dragLeaveEvent ( QDragLeaveEvent * event ) {
436   if (m_dropItem) {
437     delete m_dropItem;
438     m_dropItem = NULL;
439   }
440 }
441
442 void CustomTrackView::dropEvent ( QDropEvent * event ) {
443   if (m_dropItem) {
444     AddTimelineClipCommand *command = new AddTimelineClipCommand(this, m_dropItem->xml(), m_dropItem->clipProducer(), m_dropItem->track(), m_dropItem->startPos(), m_dropItem->rect(), m_dropItem->duration(), false, false);
445     m_commandStack->push(command);
446     m_dropItem->baseClip()->addReference();
447     m_document->updateClip(m_dropItem->baseClip()->getId());
448     kDebug()<<"IIIIIIIIIIIIIIIIIIIIIIII TRAX CNT: "<<m_tracksCount<<", DROP: "<<m_dropItem->track();
449     m_document->renderer()->mltInsertClip(m_tracksCount - m_dropItem->track(), GenTime(m_dropItem->startPos(), m_document->fps()), m_dropItem->xml());
450   }
451   m_dropItem = NULL;
452 }
453
454
455 QStringList CustomTrackView::mimeTypes () const
456 {
457     QStringList qstrList;
458     // list of accepted mime types for drop
459     qstrList.append("text/plain");
460     return qstrList;
461 }
462
463 Qt::DropActions CustomTrackView::supportedDropActions () const
464 {
465     // returns what actions are supported when dropping
466     return Qt::MoveAction;
467 }
468
469 void CustomTrackView::setDuration(int duration)
470 {
471   kDebug()<<"/////////////  PRO DUR: "<<duration<<", height: "<<50 * m_tracksCount;
472   m_projectDuration = duration;
473   scene()->setSceneRect(0, 0, (m_projectDuration + 500) * m_scale, scene()->sceneRect().height()); //50 * m_tracksCount);
474 }
475
476
477 void CustomTrackView::addTrack ()
478 {
479   m_tracksCount++;
480   m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), 50 * m_tracksCount);
481   //setSceneRect(0, 0, sceneRect().width(), 50 * m_tracksCount);
482   //verticalScrollBar()->setMaximum(50 * m_tracksCount); 
483   //setFixedHeight(50 * m_tracksCount);
484 }
485
486 void CustomTrackView::removeTrack ()
487 {
488   m_tracksCount--;
489   m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), 50 * m_tracksCount);
490 }
491
492 void CustomTrackView::deleteClip(int clipId)
493 {
494   QList<QGraphicsItem *> itemList = items();
495   for (int i = 0; i < itemList.count(); i++) {
496     if (itemList.at(i)->type() == 70000) {
497       ClipItem *item = (ClipItem *)itemList.at(i);
498       if (item->clipProducer() == clipId) {
499         AddTimelineClipCommand *command = new AddTimelineClipCommand(this, item->xml(), item->clipProducer(), item->track(), item->startPos(), item->rect(), item->duration(), true, true);
500         m_commandStack->push(command);
501         //delete item;
502       }
503     }
504   }
505 }
506
507 void CustomTrackView::setCursorPos(int pos, bool seek)
508 {
509   m_cursorPos = pos;
510   m_cursorLine->setPos(pos, 0);
511   int frame = mapToScene(QPoint(pos, 0)).x() / m_scale;
512   if (seek) m_document->renderer()->seek(GenTime(frame, m_document->fps()));
513 }
514
515 int CustomTrackView::cursorPos()
516 {
517   return m_cursorPos;
518 }
519
520 void CustomTrackView::mouseReleaseEvent ( QMouseEvent * event )
521 {
522   QGraphicsView::mouseReleaseEvent(event);
523   setDragMode(QGraphicsView::NoDrag);
524   if (m_dragItem == NULL) return;
525   //kDebug()<<"/// MOVING CLIP: "<<m_startPos<<", END: "<<QPoint(m_dragItem->rect().x(),m_dragItem->rect().y());
526   if (m_operationMode == MOVE && m_startPos.x() != m_dragItem->startPos()) {
527     // move clip
528     MoveClipCommand *command = new MoveClipCommand(this, m_startPos, QPointF(m_dragItem->startPos(), m_dragItem->track()), false);
529     m_commandStack->push(command);
530     m_document->renderer()->mltMoveClip(m_tracksCount - m_startPos.y(), m_tracksCount - m_dragItem->track(), m_startPos.x(), m_dragItem->startPos());
531   }
532   else if (m_operationMode == RESIZESTART) {
533     // resize start
534     ResizeClipCommand *command = new ResizeClipCommand(this, m_startPos, QPointF(m_dragItem->startPos(), m_dragItem->track()), true, false);
535
536     m_document->renderer()->mltResizeClipStart(m_tracksCount - m_dragItem->track(), GenTime(m_dragItem->endPos(), m_document->fps()), GenTime(m_dragItem->startPos(), m_document->fps()), GenTime(m_startPos.x(), m_document->fps()), GenTime(m_dragItem->cropStart(), m_document->fps()), GenTime(m_dragItem->cropStart(), m_document->fps()) + GenTime(m_dragItem->endPos(), m_document->fps()) - GenTime(m_dragItem->startPos(), m_document->fps()));
537     m_commandStack->push(command);
538     m_document->renderer()->doRefresh();
539   }
540   else if (m_operationMode == RESIZEEND) {
541     // resize end
542     ResizeClipCommand *command = new ResizeClipCommand(this, m_startPos, QPointF(m_dragItem->endPos(), m_dragItem->track()), false, false);
543
544     m_document->renderer()->mltResizeClipEnd(m_tracksCount - m_dragItem->track(), GenTime(m_dragItem->startPos(), m_document->fps()), GenTime(m_dragItem->cropStart(), m_document->fps()), GenTime(m_dragItem->cropStart(), m_document->fps()) + GenTime(m_dragItem->endPos(), m_document->fps()) - GenTime(m_dragItem->startPos(), m_document->fps()));
545     m_commandStack->push(command);
546     m_document->renderer()->doRefresh();
547   }
548   m_operationMode = NONE;
549   m_dragItem = NULL; 
550 }
551
552 void CustomTrackView::deleteClip (int track, int startpos, const QRectF &rect )
553 {
554   ClipItem *item = getClipItemAt(startpos, track);
555   if (!item) {
556     kDebug()<<"----------------  ERROR, CANNOT find clip to move at: "<<rect.x();
557     return;
558   }
559   item->baseClip()->removeReference();
560   m_document->updateClip(item->baseClip()->getId());
561   delete item;
562   m_document->renderer()->mltRemoveClip(m_tracksCount - track, GenTime(startpos, m_document->fps()));
563   m_document->renderer()->doRefresh();
564 }
565
566 void CustomTrackView::addClip ( QDomElement xml, int clipId, int track, int startpos, const QRectF &rect, int duration )
567 {
568   QRect r(startpos * m_scale, 50 * track, duration * m_scale, 49); 
569   DocClipBase *baseclip = m_document->clipManager()->getClipById(clipId);
570   ClipItem *item = new ClipItem(baseclip, track, startpos, r, duration);
571   scene()->addItem(item);
572   baseclip->addReference();
573   m_document->updateClip(baseclip->getId());
574   m_document->renderer()->mltInsertClip(m_tracksCount - track, GenTime(startpos, m_document->fps()), xml);
575   m_document->renderer()->doRefresh();
576 }
577
578 ClipItem *CustomTrackView::getClipItemAt(int pos, int track)
579 {
580   return (ClipItem *) scene()->itemAt(pos * m_scale, track * 50 + 25);
581 }
582
583 void CustomTrackView::moveClip ( const QPointF &startPos, const QPointF &endPos )
584 {
585   ClipItem *item = getClipItemAt(startPos.x() + 1, startPos.y());
586   if (!item) {
587     kDebug()<<"----------------  ERROR, CANNOT find clip to move at: "<<startPos.x() * m_scale * FRAME_SIZE + 1<<", "<<startPos.y() * 50 + 25;
588     return;
589   }
590   kDebug()<<"----------------  Move CLIP FROM: "<<startPos.x()<<", END:"<<endPos.x();
591   item->moveTo(endPos.x(), m_scale, (endPos.y() - startPos.y()) * 50, endPos.y());
592   m_document->renderer()->mltMoveClip(m_tracksCount - startPos.y(), m_tracksCount - endPos.y(), startPos.x(), endPos.x());
593 }
594
595 void CustomTrackView::resizeClip ( const QPointF &startPos, const QPointF &endPos, bool resizeClipStart )
596 {
597   int offset;
598   if (resizeClipStart) offset = 1;
599   else offset = -1;
600   ClipItem *item = getClipItemAt(startPos.x() + offset, startPos.y());
601   if (!item) {
602     kDebug()<<"----------------  ERROR, CANNOT find clip to resize at: "<<startPos;
603     return;
604   }
605   qreal diff = endPos.x() - startPos.x();
606   if (resizeClipStart) {
607     m_document->renderer()->mltResizeClipStart(m_tracksCount - item->track(), GenTime(item->endPos(), m_document->fps()), GenTime(endPos.x(), m_document->fps()), GenTime(item->startPos(), m_document->fps()), GenTime(item->cropStart() + diff, m_document->fps()), GenTime(item->cropStart() + diff, m_document->fps()) + GenTime(item->endPos(), m_document->fps()) - GenTime(endPos.x(), m_document->fps()));
608     item->resizeStart(endPos.x(), m_scale);
609   }
610   else {
611     m_document->renderer()->mltResizeClipEnd(m_tracksCount - item->track(), GenTime(item->startPos(), m_document->fps()), GenTime(item->cropStart(), m_document->fps()), GenTime(item->cropStart(), m_document->fps()) + GenTime(endPos.x(), m_document->fps()) - GenTime(item->startPos(), m_document->fps()));
612     item->resizeEnd(endPos.x(), m_scale);
613   }
614   m_document->renderer()->doRefresh();
615 }
616
617 double CustomTrackView::getSnapPointForPos(double pos)
618 {
619   for (int i = 0; i < m_snapPoints.size(); ++i) {
620     //kDebug()<<"SNAP POINT: "<<m_snapPoints.at(i);
621     if (abs(pos - m_snapPoints.at(i) * m_scale) < 6 * m_scale) {
622       //kDebug()<<" FOUND SNAP POINT AT: "<<m_snapPoints.at(i)<<", current pos: "<<pos / m_scale;
623       return m_snapPoints.at(i) * m_scale + 0.5;
624     }
625     if (m_snapPoints.at(i) > pos) break;
626   }
627   return pos;
628 }
629
630 void CustomTrackView::updateSnapPoints(ClipItem *selected)
631 {
632   m_snapPoints.clear();
633   int offset = 0;
634   if (selected) offset = selected->duration();
635   QList<QGraphicsItem *> itemList = items();
636   for (int i = 0; i < itemList.count(); i++) {
637     if (itemList.at(i)->type() == 70000 && itemList.at(i) != selected) {
638       ClipItem *item = (ClipItem *)itemList.at(i);
639       int start = item->startPos();
640       int fadein = item->fadeIn() + start;
641       int end = item->endPos();
642       int fadeout = end - item->fadeOut();
643       m_snapPoints.append(start);
644       if (fadein != start) m_snapPoints.append(fadein);
645       m_snapPoints.append(end);
646       if (fadeout != end) m_snapPoints.append(fadeout);
647       if (offset != 0) {
648         m_snapPoints.append(start - offset);
649         if (fadein != start) m_snapPoints.append(fadein - offset);
650         m_snapPoints.append(end - offset);
651         if (fadeout != end) m_snapPoints.append(fadeout - offset);
652       }
653     }
654   }
655   kDebug()<<" GOT SNAPPOINTS TOTAL: "<<m_snapPoints.count();
656   qSort(m_snapPoints);
657   for (int i = 0; i < m_snapPoints.size(); ++i)
658     kDebug()<<"SNAP POINT: "<<m_snapPoints.at(i);
659 }
660
661
662 void CustomTrackView::setScale(double scaleFactor)
663 {
664   //scale(scaleFactor, scaleFactor);
665   m_scale = scaleFactor;
666   kDebug()<<" HHHHHHHH  SCALING: "<<m_scale;
667   QList<QGraphicsItem *> itemList = items();
668   scene()->setSceneRect(0, 0, (m_projectDuration + 500) * m_scale, scene()->sceneRect().height()); //50 *
669
670   for (int i = 0; i < itemList.count(); i++) {
671       if (itemList.at(i)->type() == 70000) {
672         ClipItem *clip = (ClipItem *)itemList.at(i);
673         clip->setRect(clip->startPos() * m_scale, clip->rect().y(), clip->duration() * m_scale, clip->rect().height());
674       }
675       /*else if (itemList.at(i)->type() == 70001) {
676         LabelItem *label = (LabelItem *)itemList.at(i);
677         QGraphicsItem *parent = label->parentItem();
678         QRectF r = label->boundingRect();
679         QRectF p = parent->boundingRect();
680         label->setPos(p.x() + p.width() / 2 - r.width() / 2, p.y() + p.height() / 2 - r.height() / 2);
681         //label->setRect(clip->startPos() * m_scale, clip->rect().y(), clip->duration() * m_scale, clip->rect().height());
682       }*/
683     }
684 }
685
686 void CustomTrackView::drawBackground ( QPainter * painter, const QRectF & rect )  
687 {
688   QColor base = palette().button().color();
689   //painter->setPen(base);
690   painter->setClipRect(rect);
691   int width = scene()->sceneRect().width();
692   painter->drawLine(0, 0, width, 0);
693     for (uint i = 0; i < m_tracksCount;i++)
694     {
695       painter->drawLine(0, 50 * (i+1), width, 50 * (i+1));
696       painter->drawText(QRectF(10, 50 * i, 100, 50 * i + 49), Qt::AlignLeft, i18n(" Track ") + QString::number(i + 1));
697     }
698   int lowerLimit = 50 * m_tracksCount;
699   if (height() > lowerLimit)
700   painter->fillRect(QRectF(0, lowerLimit, rect.width(), height() - lowerLimit), QBrush(base));
701 }
702 /*
703 void CustomTrackView::drawForeground ( QPainter * painter, const QRectF & rect )  
704 {
705   //kDebug()<<"/////  DRAWING FB: "<<rect.x()<<", width: "<<rect.width();
706   painter->fillRect(rect, QColor(50, rand() % 250,50,100));
707   painter->drawLine(m_cursorPos, rect.y(), m_cursorPos, rect.y() + rect.height());
708 }
709 */
710 #include "customtrackview.moc"