]> git.sesse.net Git - kdenlive/blob - src/customtrackview.cpp
d986e0f47264145d5e4e1984eebe9931e196e443
[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 #include <KCursor>
30
31 #include "customtrackview.h"
32 #include "docclipbase.h"
33 #include "clipitem.h"
34 #include "definitions.h"
35 #include "moveclipcommand.h"
36 #include "movetransitioncommand.h"
37 #include "resizeclipcommand.h"
38 #include "addtimelineclipcommand.h"
39 #include "addeffectcommand.h"
40 #include "editeffectcommand.h"
41 #include "addtransitioncommand.h"
42 #include "edittransitioncommand.h"
43 #include "kdenlivesettings.h"
44 #include "transition.h"
45 #include "clipitem.h"
46 #include "customtrackview.h"
47 #include "clipmanager.h"
48 #include "renderer.h"
49 //TODO:
50 // disable animation if user asked it in KDE's global settings
51 // http://lists.kde.org/?l=kde-commits&m=120398724717624&w=2
52 // needs something like below (taken from dolphin)
53 // #include <kglobalsettings.h>
54 // const bool animate = KGlobalSettings::graphicEffectsLevel() & KGlobalSettings::SimpleAnimationEffects;
55 // const int duration = animate ? 1500 : 1;
56
57 CustomTrackView::CustomTrackView(KdenliveDoc *doc, QGraphicsScene * projectscene, QWidget *parent)
58         : QGraphicsView(projectscene, parent), m_cursorPos(0), m_dropItem(NULL), m_cursorLine(NULL), m_operationMode(NONE), m_dragItem(NULL), m_visualTip(NULL), m_moveOpMode(NONE), m_animation(NULL), m_projectDuration(0), m_scale(1.0), m_clickPoint(QPoint()), m_document(doc), m_autoScroll(KdenliveSettings::autoscroll()), m_tracksHeight(KdenliveSettings::trackheight()) {
59     if (doc) m_commandStack = doc->commandStack();
60     else m_commandStack == NULL;
61     setMouseTracking(true);
62     setAcceptDrops(true);
63     m_animationTimer = new QTimeLine(800);
64     m_animationTimer->setFrameRange(0, 5);
65     m_animationTimer->setUpdateInterval(100);
66     m_animationTimer->setLoopCount(0);
67     m_tipColor = QColor(0, 192, 0, 200);
68     QColor border = QColor(255, 255, 255, 100);
69     m_tipPen.setColor(border);
70     m_tipPen.setWidth(3);
71     setContentsMargins(0, 0, 0, 0);
72     if (projectscene) {
73         m_cursorLine = projectscene->addLine(0, 0, 0, m_tracksHeight);
74         m_cursorLine->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIgnoresTransformations);
75         m_cursorLine->setZValue(1000);
76     }
77 }
78
79 void CustomTrackView::setContextMenu(QMenu *timeline, QMenu *clip, QMenu *transition) {
80     m_timelineContextMenu = timeline;
81     m_timelineContextClipMenu = clip;
82     m_timelineContextTransitionMenu = transition;
83 }
84
85 void CustomTrackView::checkAutoScroll() {
86     m_autoScroll = KdenliveSettings::autoscroll();
87 }
88
89 QList <TrackInfo> CustomTrackView::tracksList() const {
90     return m_tracksList;
91 }
92
93 void CustomTrackView::checkTrackHeight() {
94     if (m_tracksHeight == KdenliveSettings::trackheight()) return;
95     m_tracksHeight = KdenliveSettings::trackheight();
96     emit trackHeightChanged();
97     QList<QGraphicsItem *> itemList = items();
98     ClipItem *item;
99     Transition *transitionitem;
100     for (int i = 0; i < itemList.count(); i++) {
101         if (itemList.at(i)->type() == AVWIDGET) {
102             item = (ClipItem*) itemList.at(i);
103             item->setRect(item->rect().x(), item->track() * m_tracksHeight, item->rect().width(), m_tracksHeight - 1);
104             item->resetThumbs();
105         } else if (itemList.at(i)->type() == TRANSITIONWIDGET) {
106             transitionitem = (Transition*) itemList.at(i);
107             transitionitem->setRect(transitionitem->rect().x(), transitionitem->track() * m_tracksHeight + m_tracksHeight / 2, transitionitem->rect().width(), m_tracksHeight - 1);
108         }
109     }
110     m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), m_tracksHeight * m_tracksList.count());
111     setSceneRect(0, 0, sceneRect().width(), m_tracksHeight * m_tracksList.count());
112     verticalScrollBar()->setMaximum(m_tracksHeight * m_tracksList.count());
113     update();
114 }
115
116 // virtual
117 void CustomTrackView::resizeEvent(QResizeEvent * event) {
118     QGraphicsView::resizeEvent(event);
119 }
120
121 // virtual
122 void CustomTrackView::wheelEvent(QWheelEvent * e) {
123     if (e->modifiers() == Qt::ControlModifier) {
124         if (e->delta() > 0) emit zoomIn();
125         else emit zoomOut();
126     } else {
127         if (e->delta() > 0) horizontalScrollBar()->setValue(horizontalScrollBar()->value() + horizontalScrollBar()->singleStep());
128         else  horizontalScrollBar()->setValue(horizontalScrollBar()->value() - horizontalScrollBar()->singleStep());
129     }
130 }
131
132 int CustomTrackView::getPreviousVideoTrack(int track) {
133     track = m_tracksList.count() - track - 1;
134     int videoTracksCount = 0;
135     track --;
136     for (int i = track; i > -1; i--) {
137         if (m_tracksList.at(i).type == VIDEOTRACK) return i + 1;
138     }
139     return 0;
140 }
141
142 // virtual
143 void CustomTrackView::mouseMoveEvent(QMouseEvent * event) {
144     int pos = event->x();
145     emit mousePosition((int)(mapToScene(event->pos()).x() / m_scale));
146     /*if (event->modifiers() == Qt::ControlModifier)
147       setDragMode(QGraphicsView::ScrollHandDrag);
148     else if (event->modifiers() == Qt::ShiftModifier)
149       setDragMode(QGraphicsView::RubberBandDrag);
150     else*/
151     {
152
153         if (m_dragItem) { //event->button() == Qt::LeftButton) {
154             // a button was pressed, delete visual tips
155             if (m_operationMode == MOVE) {
156                 double snappedPos = getSnapPointForPos(mapToScene(event->pos()).x() - m_clickPoint.x());
157                 //kDebug() << "///////  MOVE CLIP, EVENT Y: "<<m_clickPoint.y();//<<event->scenePos().y()<<", SCENE HEIGHT: "<<scene()->sceneRect().height();
158                 int moveTrack = (int)  mapToScene(event->pos() + QPoint(0, (m_dragItem->type() == TRANSITIONWIDGET ? m_tracksHeight - m_clickPoint.y() : 0))).y() / m_tracksHeight;
159                 int currentTrack = m_dragItem->track();
160
161                 if (moveTrack > m_tracksList.count() - 1) moveTrack = m_tracksList.count() - 1;
162                 else if (moveTrack < 0) moveTrack = 0;
163
164                 int offset = moveTrack - currentTrack;
165                 if (offset != 0) offset = m_tracksHeight * offset;
166                 m_dragItem->moveTo((int)(snappedPos / m_scale), m_scale, offset, moveTrack);
167             } else if (m_operationMode == RESIZESTART) {
168                 double snappedPos = getSnapPointForPos(mapToScene(event->pos()).x());
169                 m_dragItem->resizeStart((int)(snappedPos / m_scale), m_scale);
170             } else if (m_operationMode == RESIZEEND) {
171                 double snappedPos = getSnapPointForPos(mapToScene(event->pos()).x());
172                 m_dragItem->resizeEnd((int)(snappedPos / m_scale), m_scale);
173             } else if (m_operationMode == FADEIN) {
174                 int pos = (int)(mapToScene(event->pos()).x() / m_scale);
175                 m_dragItem->setFadeIn((int)(pos - m_dragItem->startPos().frames(m_document->fps())), m_scale);
176             } else if (m_operationMode == FADEOUT) {
177                 int pos = (int)(mapToScene(event->pos()).x() / m_scale);
178                 m_dragItem->setFadeOut((int)(m_dragItem->endPos().frames(m_document->fps()) - pos), m_scale);
179             }
180
181             if (m_animation) delete m_animation;
182             m_animation = NULL;
183             if (m_visualTip) delete m_visualTip;
184             m_visualTip = NULL;
185             QGraphicsView::mouseMoveEvent(event);
186             return;
187         }
188
189         QList<QGraphicsItem *> itemList = items(event->pos());
190         QGraphicsRectItem *item = NULL;
191         for (int i = 0; i < itemList.count(); i++) {
192             if (itemList.at(i)->type() == AVWIDGET || itemList.at(i)->type() == TRANSITIONWIDGET) {
193                 item = (QGraphicsRectItem*) itemList.at(i);
194                 break;
195             }
196         }
197         if (item && event->buttons() == Qt::NoButton) {
198             AbstractClipItem *clip = (AbstractClipItem*) item;
199             OPERATIONTYPE opMode = opMode = clip->operationMode(mapToScene(event->pos()), m_scale);
200             double size = 8;
201
202             if (opMode == m_moveOpMode) {
203                 QGraphicsView::mouseMoveEvent(event);
204                 return;
205             } else {
206                 if (m_visualTip) {
207                     if (m_animation) delete m_animation;
208                     m_animation = NULL;
209                     m_animationTimer->stop();
210                     delete m_visualTip;
211                     m_visualTip = NULL;
212                 }
213             }
214             m_moveOpMode = opMode;
215             if (opMode == MOVE) {
216                 setCursor(Qt::OpenHandCursor);
217             } else if (opMode == RESIZESTART) {
218                 setCursor(KCursor("left_side", Qt::SizeHorCursor));
219                 kDebug() << "********  RESIZE CLIP START; WIDTH: " << size;
220                 if (m_visualTip == NULL) {
221                     QPolygon polygon;
222                     polygon << QPoint((int)clip->rect().x(), (int)(clip->rect().y() + clip->rect().height() / 2 - size * 2));
223                     polygon << QPoint((int)(clip->rect().x() + size * 2), (int)(clip->rect().y() + clip->rect().height() / 2));
224                     polygon << QPoint((int)clip->rect().x(), (int)(clip->rect().y() + clip->rect().height() / 2 + size * 2));
225                     polygon << QPoint((int)clip->rect().x(), (int)(clip->rect().y() + clip->rect().height() / 2 - size * 2));
226
227                     m_visualTip = new QGraphicsPolygonItem(polygon);
228                     ((QGraphicsPolygonItem*) m_visualTip)->setBrush(m_tipColor);
229                     ((QGraphicsPolygonItem*) m_visualTip)->setPen(m_tipPen);
230                     m_visualTip->setZValue(100);
231                     m_animation = new QGraphicsItemAnimation;
232                     m_animation->setItem(m_visualTip);
233                     m_animation->setTimeLine(m_animationTimer);
234                     m_visualTip->setPos(0, 0);
235                     double scale = 2.0;
236                     m_animation->setScaleAt(.5, scale, 1);
237                     m_animation->setPosAt(.5, QPointF(clip->rect().x() - clip->rect().x() * scale, 0));
238                     scale = 1.0;
239                     m_animation->setScaleAt(1, scale, 1);
240                     m_animation->setPosAt(1, QPointF(clip->rect().x() - clip->rect().x() * scale, 0));
241                     scene()->addItem(m_visualTip);
242                     m_animationTimer->start();
243                 }
244             } else if (opMode == RESIZEEND) {
245                 setCursor(KCursor("right_side", Qt::SizeHorCursor));
246                 if (m_visualTip == NULL) {
247                     QPolygon polygon;
248                     polygon << QPoint((int)(clip->rect().x() + clip->rect().width()), (int)(clip->rect().y() + clip->rect().height() / 2 - size * 2));
249                     polygon << QPoint((int)(clip->rect().x() + clip->rect().width() - size * 2), (int)(clip->rect().y() + clip->rect().height() / 2));
250                     polygon << QPoint((int)(clip->rect().x() + clip->rect().width()), (int)(clip->rect().y() + clip->rect().height() / 2 + size * 2));
251                     polygon << QPoint((int)(clip->rect().x() + clip->rect().width()), (int)(clip->rect().y() + clip->rect().height() / 2 - size * 2));
252
253                     m_visualTip = new QGraphicsPolygonItem(polygon);
254                     ((QGraphicsPolygonItem*) m_visualTip)->setBrush(m_tipColor);
255                     ((QGraphicsPolygonItem*) m_visualTip)->setPen(m_tipPen);
256
257                     m_visualTip->setZValue(100);
258                     m_animation = new QGraphicsItemAnimation;
259                     m_animation->setItem(m_visualTip);
260                     m_animation->setTimeLine(m_animationTimer);
261                     m_visualTip->setPos(0, 0);
262                     double scale = 2.0;
263                     m_animation->setScaleAt(.5, scale, 1);
264                     m_animation->setPosAt(.5, QPointF(clip->rect().x() - clip->rect().x() * scale - clip->rect().width(), 0));
265                     scale = 1.0;
266                     m_animation->setScaleAt(1, scale, 1);
267                     m_animation->setPosAt(1, QPointF(clip->rect().x() - clip->rect().x() * scale, 0));
268                     scene()->addItem(m_visualTip);
269                     m_animationTimer->start();
270                 }
271             } else if (opMode == FADEIN) {
272                 if (m_visualTip == NULL) {
273                     m_visualTip = new QGraphicsEllipseItem(clip->rect().x() + clip->fadeIn() * m_scale - size, clip->rect().y() - 8, size * 2, 16);
274                     ((QGraphicsEllipseItem*) m_visualTip)->setBrush(m_tipColor);
275                     ((QGraphicsEllipseItem*) m_visualTip)->setPen(m_tipPen);
276                     m_visualTip->setZValue(100);
277                     m_animation = new QGraphicsItemAnimation;
278                     m_animation->setItem(m_visualTip);
279                     m_animation->setTimeLine(m_animationTimer);
280                     m_visualTip->setPos(0, 0);
281                     double scale = 2.0;
282                     m_animation->setScaleAt(.5, scale, scale);
283                     m_animation->setPosAt(.5, QPointF(clip->rect().x() - clip->rect().x() * scale -  clip->fadeIn() * m_scale, clip->rect().y() - clip->rect().y() * scale));
284                     scale = 1.0;
285                     m_animation->setScaleAt(1, scale, scale);
286                     m_animation->setPosAt(1, QPointF(clip->rect().x() - clip->rect().x() * scale, clip->rect().y() - clip->rect().y() * scale));
287                     scene()->addItem(m_visualTip);
288                     m_animationTimer->start();
289                 }
290                 setCursor(Qt::PointingHandCursor);
291             } else if (opMode == FADEOUT) {
292                 if (m_visualTip == NULL) {
293                     m_visualTip = new QGraphicsEllipseItem(clip->rect().x() + clip->rect().width() - clip->fadeOut() * m_scale - size, clip->rect().y() - 8, size*2, 16);
294                     ((QGraphicsEllipseItem*) m_visualTip)->setBrush(m_tipColor);
295                     ((QGraphicsEllipseItem*) m_visualTip)->setPen(m_tipPen);
296                     m_visualTip->setZValue(100);
297                     m_animation = new QGraphicsItemAnimation;
298                     m_animation->setItem(m_visualTip);
299                     m_animation->setTimeLine(m_animationTimer);
300                     m_visualTip->setPos(0, 0);
301                     double scale = 2.0;
302                     m_animation->setScaleAt(.5, scale, scale);
303                     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));
304                     scale = 1.0;
305                     m_animation->setScaleAt(1, scale, scale);
306                     m_animation->setPosAt(1, QPointF(clip->rect().x() - clip->rect().x() * scale, clip->rect().y() - clip->rect().y() * scale));
307                     scene()->addItem(m_visualTip);
308                     m_animationTimer->start();
309                 }
310                 setCursor(Qt::PointingHandCursor);
311             } else if (opMode == TRANSITIONSTART) {
312                 if (m_visualTip == NULL) {
313                     m_visualTip = new QGraphicsEllipseItem(-5, -5 , 10, 10);
314                     ((QGraphicsEllipseItem*) m_visualTip)->setBrush(m_tipColor);
315                     ((QGraphicsEllipseItem*) m_visualTip)->setPen(m_tipPen);
316                     m_visualTip->setZValue(100);
317                     m_animation = new QGraphicsItemAnimation;
318                     m_animation->setItem(m_visualTip);
319                     m_animation->setTimeLine(m_animationTimer);
320                     m_visualTip->setPos(clip->rect().x() + 15, clip->rect().y() + clip->rect().height() / 2);
321                     double scale = 2.0;
322                     m_animation->setScaleAt(.5, scale, scale);
323                     scale = 1.0;
324                     m_animation->setScaleAt(1, scale, scale);
325                     scene()->addItem(m_visualTip);
326                     m_animationTimer->start();
327                 }
328                 setCursor(Qt::PointingHandCursor);
329             } else if (opMode == TRANSITIONEND) {
330                 if (m_visualTip == NULL) {
331                     m_visualTip = new QGraphicsEllipseItem(-5, -5 , 10, 10);
332                     ((QGraphicsEllipseItem*) m_visualTip)->setBrush(m_tipColor);
333                     ((QGraphicsEllipseItem*) m_visualTip)->setPen(m_tipPen);
334                     m_visualTip->setZValue(100);
335                     m_animation = new QGraphicsItemAnimation;
336                     m_animation->setItem(m_visualTip);
337                     m_animation->setTimeLine(m_animationTimer);
338                     m_visualTip->setPos(clip->rect().x() + clip->rect().width() - 15 , clip->rect().y() + clip->rect().height() / 2);
339                     double scale = 2.0;
340                     m_animation->setScaleAt(.5, scale, scale);
341                     scale = 1.0;
342                     m_animation->setScaleAt(1, scale, scale);
343                     scene()->addItem(m_visualTip);
344                     m_animationTimer->start();
345                 }
346                 setCursor(Qt::PointingHandCursor);
347             }
348         } else {
349             m_moveOpMode = NONE;
350             if (event->buttons() != Qt::NoButton && event->modifiers() == Qt::NoModifier) {
351                 setCursorPos((int)(mapToScene(event->pos().x(), 0).x() / m_scale));
352             }
353             if (m_visualTip) {
354                 if (m_animation) delete m_animation;
355                 m_animationTimer->stop();
356                 m_animation = NULL;
357                 delete m_visualTip;
358                 m_visualTip = NULL;
359
360             }
361             setCursor(Qt::ArrowCursor);
362         }
363     }
364     QGraphicsView::mouseMoveEvent(event);
365 }
366
367 // virtual
368 void CustomTrackView::mousePressEvent(QMouseEvent * event) {
369     activateMonitor();
370     int pos = event->x();
371     if (event->modifiers() == Qt::ControlModifier) {
372         setDragMode(QGraphicsView::ScrollHandDrag);
373         QGraphicsView::mousePressEvent(event);
374         return;
375     } else if (event->modifiers() == Qt::ShiftModifier) {
376         setDragMode(QGraphicsView::RubberBandDrag);
377         QGraphicsView::mousePressEvent(event);
378         return;
379     } else {
380         bool collision = false;
381         m_dragItem = NULL;
382         QList<QGraphicsItem *> collisionList = items(event->pos());
383         for (int i = 0; i < collisionList.size(); ++i) {
384             QGraphicsItem *item = collisionList.at(i);
385             if (item->type() == AVWIDGET || item->type() == TRANSITIONWIDGET) {
386                 // select item
387                 if (!item->isSelected()) {
388                     QList<QGraphicsItem *> itemList = items();
389                     for (int i = 0; i < itemList.count(); i++)
390                         itemList.at(i)->setSelected(false);
391                     item->setSelected(true);
392                     update();
393                 }
394
395                 m_dragItem = (AbstractClipItem *) item;
396
397                 m_clickPoint = QPoint((int)(mapToScene(event->pos()).x() - m_dragItem->startPos().frames(m_document->fps()) * m_scale), (int)(event->pos().y() - m_dragItem->rect().top()));
398                 m_dragItemInfo.startPos = m_dragItem->startPos();
399                 m_dragItemInfo.endPos = m_dragItem->endPos();
400                 m_dragItemInfo.track = m_dragItem->track();
401
402                 m_operationMode = m_dragItem->operationMode(item->mapFromScene(mapToScene(event->pos())), m_scale);
403                 if (m_operationMode == MOVE) setCursor(Qt::ClosedHandCursor);
404                 if (m_operationMode == TRANSITIONSTART) {
405                     ItemInfo info;
406                     info.startPos = m_dragItem->startPos();
407                     info.endPos = info.startPos + GenTime(2.5);
408                     info.track = m_dragItem->track();
409                     int transitiontrack = getPreviousVideoTrack(info.track);
410                     slotAddTransition((ClipItem *) m_dragItem, info, transitiontrack);
411                 }
412                 if (m_operationMode == TRANSITIONEND) {
413                     ItemInfo info;
414                     info.endPos = m_dragItem->endPos();
415                     info.startPos = info.endPos - GenTime(2.5);
416                     info.track = m_dragItem->track();
417                     int transitiontrack = info.track - 1;
418                     slotAddTransition((ClipItem *) m_dragItem, info, transitiontrack);
419                 }
420                 updateSnapPoints(m_dragItem);
421                 collision = true;
422                 break;
423             }
424         }
425         if (m_dragItem) {
426             if (m_dragItem->type() == AVWIDGET) emit clipItemSelected((ClipItem*) m_dragItem);
427             else emit transitionItemSelected((Transition*) m_dragItem);
428         }
429         if (!collision) {
430             kDebug() << "//////// NO ITEM FOUND ON CLICK";
431             m_dragItem = NULL;
432             setCursor(Qt::ArrowCursor);
433             QList<QGraphicsItem *> itemList = items();
434             for (int i = 0; i < itemList.count(); i++)
435                 itemList.at(i)->setSelected(false);
436             //emit clipItemSelected(NULL);
437             if (event->button() == Qt::RightButton) {
438                 displayContextMenu(event->globalPos());
439             } else setCursorPos((int)(mapToScene(event->x(), 0).x() / m_scale));
440         } else if (event->button() == Qt::RightButton) {
441             m_operationMode = NONE;
442             displayContextMenu(event->globalPos(), (ClipItem *) m_dragItem);
443             m_dragItem = NULL;
444         }
445     }
446     //kDebug()<<pos;
447     //QGraphicsView::mousePressEvent(event);
448 }
449
450 void CustomTrackView::displayContextMenu(QPoint pos, ClipItem *clip) {
451     m_timelineContextClipMenu->popup(pos);
452 }
453
454 void CustomTrackView::activateMonitor() {
455     emit activateDocumentMonitor();
456 }
457
458 void CustomTrackView::dragEnterEvent(QDragEnterEvent * event) {
459     if (event->mimeData()->hasFormat("kdenlive/producerslist")) {
460         kDebug() << "///////////////  DRAG ENTERED, TEXT: " << event->mimeData()->data("kdenlive/producerslist");
461         QStringList ids = QString(event->mimeData()->data("kdenlive/producerslist")).split(";");
462         //TODO: drop of several clips
463         for (int i = 0; i < ids.size(); ++i) {
464         }
465         DocClipBase *clip = m_document->getBaseClip(ids.at(0).toInt());
466         if (clip == NULL) kDebug() << " WARNING))))))))) CLIP NOT FOUND : " << ids.at(0).toInt();
467         addItem(clip, event->pos());
468         event->acceptProposedAction();
469     } else QGraphicsView::dragEnterEvent(event);
470 }
471
472 void CustomTrackView::slotRefreshEffects(ClipItem *clip) {
473     int track = m_tracksList.count() - clip->track();
474     GenTime pos = clip->startPos();
475     m_document->renderer()->mltRemoveEffect(track, pos, "-1", false);
476     for (int i = 0; i < clip->effectsCount(); i++) {
477         m_document->renderer()->mltAddEffect(track, pos, clip->getEffectArgs(clip->effectAt(i)), false);
478     }
479     m_document->renderer()->doRefresh();
480 }
481
482 void CustomTrackView::addEffect(int track, GenTime pos, QDomElement effect) {
483     ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, m_tracksList.count() - track);
484     if (clip) {
485         QMap <QString, QString> effectParams = clip->addEffect(effect);
486         m_document->renderer()->mltAddEffect(track, pos, effectParams);
487         emit clipItemSelected(clip);
488     }
489 }
490
491 void CustomTrackView::deleteEffect(int track, GenTime pos, QDomElement effect) {
492     QString index = effect.attribute("kdenlive_ix");
493     m_document->renderer()->mltRemoveEffect(track, pos, index);
494     ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, m_tracksList.count() - track);
495     if (clip) {
496         clip->deleteEffect(index);
497         emit clipItemSelected(clip);
498     }
499 }
500
501 void CustomTrackView::slotAddEffect(QDomElement effect, GenTime pos, int track) {
502     QList<QGraphicsItem *> itemList;
503     if (track == -1)
504         itemList = items();
505     else {
506         ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, track);
507         if (clip) itemList.append(clip);
508         else kDebug() << "------   wrning, clip eff not found";
509     }
510     kDebug() << "// REQUESTING EFFECT ON CLIP: " << pos.frames(25) << ", TRK: " << track;
511     for (int i = 0; i < itemList.count(); i++) {
512         if (itemList.at(i)->type() == AVWIDGET && itemList.at(i)->isSelected()) {
513             ClipItem *item = (ClipItem *)itemList.at(i);
514             // the kdenlive_ix int is used to identify an effect in mlt's playlist, should
515             // not be changed
516             if (effect.attribute("kdenlive_ix").toInt() == 0)
517                 effect.setAttribute("kdenlive_ix", QString::number(item->effectsCounter()));
518             AddEffectCommand *command = new AddEffectCommand(this, m_tracksList.count() - item->track(), item->startPos(), effect, true);
519             m_commandStack->push(command);
520         }
521     }
522     m_document->setModified(true);
523 }
524
525 void CustomTrackView::slotDeleteEffect(ClipItem *clip, QDomElement effect) {
526     AddEffectCommand *command = new AddEffectCommand(this, m_tracksList.count() - clip->track(), clip->startPos(), effect, false);
527     m_commandStack->push(command);
528     m_document->setModified(true);
529 }
530
531 void CustomTrackView::updateEffect(int track, GenTime pos, QDomElement effect) {
532     ClipItem *clip = getClipItemAt((int)pos.frames(m_document->fps()) + 1, m_tracksList.count() - track);
533     if (clip) {
534         QMap <QString, QString> effectParams = clip->getEffectArgs(effect);
535         if (effectParams["disabled"] == "1") {
536             QString index = effectParams["kdenlive_ix"];
537             m_document->renderer()->mltRemoveEffect(track, pos, index);
538         } else m_document->renderer()->mltEditEffect(m_tracksList.count() - clip->track(), clip->startPos(), effectParams);
539     }
540     m_document->setModified(true);
541 }
542
543 void CustomTrackView::slotChangeEffectState(ClipItem *clip, QDomElement effect, bool disable) {
544     QDomElement oldEffect = effect.cloneNode().toElement();
545     effect.setAttribute("disabled", disable);
546     EditEffectCommand *command = new EditEffectCommand(this, m_tracksList.count() - clip->track(), clip->startPos(), oldEffect, effect, true);
547     m_commandStack->push(command);
548     m_document->setModified(true);
549 }
550
551 void CustomTrackView::slotUpdateClipEffect(ClipItem *clip, QDomElement oldeffect, QDomElement effect) {
552     EditEffectCommand *command = new EditEffectCommand(this, m_tracksList.count() - clip->track(), clip->startPos(), oldeffect, effect, true);
553     m_commandStack->push(command);
554 }
555
556 void CustomTrackView::slotAddTransition(ClipItem* clip, ItemInfo transitionInfo, int endTrack, QDomElement transition) {
557     AddTransitionCommand* command = new AddTransitionCommand(this, transitionInfo, endTrack, transition, true);
558     m_commandStack->push(command);
559     m_document->setModified(true);
560 }
561
562 void CustomTrackView::addTransition(ItemInfo transitionInfo, int endTrack, QDomElement params) {
563     Transition *tr = new Transition(transitionInfo, endTrack, m_scale, m_document->fps(), params);
564     scene()->addItem(tr);
565
566     //kDebug() << "---- ADDING transition " << e.attribute("tag") << ", on tracks " << m_tracksList.count() - e.attribute("transition_track").toInt() << " / " << getPreviousVideoTrack(e.attribute("transition_track").toInt());
567     m_document->renderer()->mltAddTransition(tr->transitionTag(), endTrack, m_tracksList.count() - transitionInfo.track, transitionInfo.startPos, transitionInfo.endPos, tr->toXML());
568     m_document->setModified(true);
569 }
570
571 void CustomTrackView::deleteTransition(ItemInfo transitionInfo, int endTrack, QDomElement params) {
572     Transition *item = getTransitionItemAt((int)transitionInfo.startPos.frames(m_document->fps()) + 1, transitionInfo.track);
573     m_document->renderer()->mltDeleteTransition(item->transitionTag(), endTrack, m_tracksList.count() - transitionInfo.track, transitionInfo.startPos, transitionInfo.endPos, item->toXML());
574     delete item;
575     m_document->setModified(true);
576 }
577
578 void CustomTrackView::slotTransitionUpdated(QDomElement old, QDomElement newEffect) {
579     EditTransitionCommand *command = new EditTransitionCommand(this, newEffect.attribute("a_track").toInt(), GenTime(newEffect.attribute("start").toInt(), m_document->fps()) , old, newEffect , true);
580     m_commandStack->push(command);
581     m_document->setModified(true);
582 }
583
584 void CustomTrackView::updateTransition(int track, GenTime pos, QDomElement oldTransition, QDomElement transition) {
585     m_document->renderer()->mltUpdateTransition(oldTransition.attribute("tag"), transition.attribute("tag"), transition.attribute("transitionb_track").toInt(), m_tracksList.count() - transition.attribute("transition_atrack").toInt() ,
586             GenTime(transition.attribute("start").toInt(), m_document->renderer()->fps()),
587             GenTime(transition.attribute("end").toInt(), m_document->renderer()->fps()),
588             transition);
589     repaint();
590     m_document->setModified(true);
591 }
592
593 void CustomTrackView::addItem(DocClipBase *clip, QPoint pos) {
594     ItemInfo info;
595     info.startPos = GenTime((int)(mapToScene(pos).x() / m_scale), m_document->fps());
596     info.endPos = info.startPos + clip->duration();
597     info.track = (int)(pos.y() / m_tracksHeight);
598     //kDebug()<<"------------  ADDING CLIP ITEM----: "<<info.startPos.frames(25)<<", "<<info.endPos.frames(25)<<", "<<info.track;
599     m_dropItem = new ClipItem(clip, info, m_scale, m_document->fps());
600     scene()->addItem(m_dropItem);
601 }
602
603
604 void CustomTrackView::dragMoveEvent(QDragMoveEvent * event) {
605     event->setDropAction(Qt::IgnoreAction);
606     kDebug() << "+++++++++++++   DRAG MOVE, : " << mapToScene(event->pos()).x() << ", SCAL: " << m_scale;
607     if (m_dropItem) {
608         int track = (int)(event->pos().y() / m_tracksHeight);  //) * (m_scale * 50) + m_scale;
609         m_dropItem->moveTo((int)(mapToScene(event->pos()).x() / m_scale), m_scale, (int)((track - m_dropItem->track()) * m_tracksHeight), track);
610         event->setDropAction(Qt::MoveAction);
611         if (event->mimeData()->hasFormat("kdenlive/producerslist")) {
612             event->acceptProposedAction();
613         }
614     } else {
615         QGraphicsView::dragMoveEvent(event);
616     }
617 }
618
619 void CustomTrackView::dragLeaveEvent(QDragLeaveEvent * event) {
620     if (m_dropItem) {
621         delete m_dropItem;
622         m_dropItem = NULL;
623     } else QGraphicsView::dragLeaveEvent(event);
624 }
625
626 void CustomTrackView::dropEvent(QDropEvent * event) {
627     if (m_dropItem) {
628         ItemInfo info;
629         info.startPos = m_dropItem->startPos();
630         info.endPos = m_dropItem->endPos();
631         info.track = m_dropItem->track();
632         AddTimelineClipCommand *command = new AddTimelineClipCommand(this, m_dropItem->xml(), m_dropItem->clipProducer(), info, false, false);
633         m_commandStack->push(command);
634         m_dropItem->baseClip()->addReference();
635         m_document->updateClip(m_dropItem->baseClip()->getId());
636         // kDebug()<<"IIIIIIIIIIIIIIIIIIIIIIII TRAX CNT: "<<m_tracksList.count()<<", DROP: "<<m_dropItem->track();
637         m_document->renderer()->mltInsertClip(m_tracksList.count() - m_dropItem->track(), m_dropItem->startPos(), m_dropItem->xml());
638         m_document->setModified(true);
639     } else QGraphicsView::dropEvent(event);
640     m_dropItem = NULL;
641 }
642
643
644 QStringList CustomTrackView::mimeTypes() const {
645     QStringList qstrList;
646     // list of accepted mime types for drop
647     qstrList.append("text/plain");
648     qstrList.append("kdenlive/producerslist");
649     return qstrList;
650 }
651
652 Qt::DropActions CustomTrackView::supportedDropActions() const {
653     // returns what actions are supported when dropping
654     return Qt::MoveAction;
655 }
656
657 void CustomTrackView::setDuration(int duration) {
658     kDebug() << "/////////////  PRO DUR: " << duration << ", SCALE. " << (m_projectDuration + 500) * m_scale << ", height: " << 50 * m_tracksList.count();
659     m_projectDuration = duration;
660     setSceneRect(0, 0, (m_projectDuration + 100) * m_scale, sceneRect().height());
661 }
662
663 int CustomTrackView::duration() const {
664     return m_projectDuration;
665 }
666
667 void CustomTrackView::addTrack(TrackInfo type) {
668     m_tracksList << type;
669     m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), m_tracksHeight * m_tracksList.count());
670     setSceneRect(0, 0, sceneRect().width(), m_tracksHeight * m_tracksList.count());
671     verticalScrollBar()->setMaximum(m_tracksHeight * m_tracksList.count());
672     //setFixedHeight(50 * m_tracksCount);
673 }
674
675 void CustomTrackView::removeTrack() {
676     // TODO: implement track deletion
677     //m_tracksCount--;
678     m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), m_tracksHeight * m_tracksList.count());
679 }
680
681
682 void CustomTrackView::slotSwitchTrackAudio(int ix) {
683     int tracknumber = m_tracksList.count() - ix;
684     kDebug() << "/////  MUTING TRK: " << ix << "; PL NUM: " << tracknumber;
685     m_tracksList[tracknumber - 1].isMute = !m_tracksList.at(tracknumber - 1).isMute;
686     m_document->renderer()->mltChangeTrackState(tracknumber, m_tracksList.at(tracknumber - 1).isMute, m_tracksList.at(tracknumber - 1).isBlind);
687 }
688
689 void CustomTrackView::slotSwitchTrackVideo(int ix) {
690     int tracknumber = m_tracksList.count() - ix;
691     m_tracksList[tracknumber - 1].isBlind = !m_tracksList.at(tracknumber - 1).isBlind;
692     m_document->renderer()->mltChangeTrackState(tracknumber, m_tracksList.at(tracknumber - 1).isMute, m_tracksList.at(tracknumber - 1).isBlind);
693 }
694
695 void CustomTrackView::deleteClip(int clipId) {
696     QList<QGraphicsItem *> itemList = items();
697     for (int i = 0; i < itemList.count(); i++) {
698         if (itemList.at(i)->type() == AVWIDGET) {
699             ClipItem *item = (ClipItem *)itemList.at(i);
700             if (item->clipProducer() == clipId) {
701                 ItemInfo info;
702                 info.startPos = item->startPos();
703                 info.endPos = item->endPos();
704                 info.track = item->track();
705                 AddTimelineClipCommand *command = new AddTimelineClipCommand(this, item->xml(), item->clipProducer(), info, true, true);
706                 m_commandStack->push(command);
707                 //delete item;
708             }
709         }
710     }
711 }
712
713 void CustomTrackView::setCursorPos(int pos, bool seek) {
714     emit cursorMoved((int)(m_cursorPos * m_scale), (int)(pos * m_scale));
715     m_cursorPos = pos;
716     m_cursorLine->setPos(pos * m_scale, 0);
717     if (seek) m_document->renderer()->seek(GenTime(pos, m_document->fps()));
718     else if (m_autoScroll && m_scale < 50) checkScrolling();
719 }
720
721 void CustomTrackView::updateCursorPos() {
722     m_cursorLine->setPos(m_cursorPos * m_scale, 0);
723 }
724
725 int CustomTrackView::cursorPos() {
726     return (int)(m_cursorPos * m_scale);
727 }
728
729 void CustomTrackView::checkScrolling() {
730     QRect rectInView = viewport()->rect();
731     int delta = rectInView.width() / 3;
732     int max = rectInView.right() + horizontalScrollBar()->value() - delta;
733     //kDebug() << "CURSOR POS: "<<m_cursorPos<< "Scale: "<<m_scale;
734     if (m_cursorPos * m_scale >= max) horizontalScrollBar()->setValue((int)(horizontalScrollBar()->value() + 1 + m_scale));
735 }
736
737 void CustomTrackView::mouseReleaseEvent(QMouseEvent * event) {
738     QGraphicsView::mouseReleaseEvent(event);
739     setDragMode(QGraphicsView::NoDrag);
740     if (m_dragItem == NULL) return;
741     ItemInfo info;
742     info.startPos = m_dragItem->startPos();
743     info.endPos = m_dragItem->endPos();
744     info.track = m_dragItem->track();
745
746     if (m_operationMode == MOVE) setCursor(Qt::OpenHandCursor);
747     if (m_operationMode == MOVE) {// && m_startPos.x() != m_dragItem->startPos().frames(m_document->fps())) {
748         // move clip
749         if (m_dragItem->type() == AVWIDGET) {
750             MoveClipCommand *command = new MoveClipCommand(this, m_dragItemInfo, info, false);
751             m_commandStack->push(command);
752             m_document->renderer()->mltMoveClip((int)(m_tracksList.count() - m_dragItemInfo.track), (int)(m_tracksList.count() - m_dragItem->track()), (int) m_dragItemInfo.startPos.frames(m_document->fps()), (int)(m_dragItem->startPos().frames(m_document->fps())));
753         }
754         if (m_dragItem->type() == TRANSITIONWIDGET) {
755             MoveTransitionCommand *command = new MoveTransitionCommand(this, m_dragItemInfo, info, false);
756             m_commandStack->push(command);
757             //kDebug()<<"/// MOVING TRS FROM: "<<(int)(m_tracksList.count() - m_startPos.y())<<", OFFSET: "<<(int) (m_dragItem->track() - m_startPos.y());
758             Transition *transition = (Transition *) m_dragItem;
759             m_document->renderer()->mltMoveTransition(transition->transitionTag(), (int)(m_tracksList.count() - m_dragItemInfo.track), (int)(m_dragItemInfo.track - m_dragItem->track()), m_dragItemInfo.startPos, m_dragItemInfo.endPos, info.startPos, info.endPos);
760         }
761
762     } else if (m_operationMode == RESIZESTART) {
763         // resize start
764         if (m_dragItem->type() == AVWIDGET) {
765             m_document->renderer()->mltResizeClipStart(m_tracksList.count() - m_dragItem->track(), m_dragItem->endPos(), m_dragItem->startPos(), m_dragItemInfo.startPos, m_dragItem->cropStart(), m_dragItem->cropStart() + m_dragItem->endPos() - m_dragItem->startPos());
766             ResizeClipCommand *command = new ResizeClipCommand(this, m_dragItemInfo, info, false);
767             m_commandStack->push(command);
768         } else if (m_dragItem->type() == TRANSITIONWIDGET) {
769             MoveTransitionCommand *command = new MoveTransitionCommand(this, m_dragItemInfo, info, false);
770             m_commandStack->push(command);
771             Transition *transition = (Transition *) m_dragItem;
772             m_document->renderer()->mltMoveTransition(transition->transitionTag(), (int)(m_tracksList.count() - m_dragItemInfo.track), 0, m_dragItemInfo.startPos, m_dragItemInfo.endPos, info.startPos, info.endPos);
773         }
774
775         m_document->renderer()->doRefresh();
776     } else if (m_operationMode == RESIZEEND) {
777         // resize end
778         if (m_dragItem->type() == AVWIDGET) {
779             ResizeClipCommand *command = new ResizeClipCommand(this, m_dragItemInfo, info, false);
780             m_document->renderer()->mltResizeClipEnd(m_tracksList.count() - m_dragItem->track(), m_dragItem->startPos(), m_dragItem->cropStart(), m_dragItem->cropStart() + m_dragItem->endPos() - m_dragItem->startPos());
781             m_commandStack->push(command);
782         } else if (m_dragItem->type() == TRANSITIONWIDGET) {
783
784             MoveTransitionCommand *command = new MoveTransitionCommand(this, m_dragItemInfo, info, false);
785             m_commandStack->push(command);
786             Transition *transition = (Transition *) m_dragItem;
787             m_document->renderer()->mltMoveTransition(transition->transitionTag(), (int)(m_tracksList.count() - m_dragItemInfo.track), 0, m_dragItemInfo.startPos, m_dragItemInfo.endPos, info.startPos, info.endPos);
788         }
789         m_document->renderer()->doRefresh();
790     }
791     m_document->setModified(true);
792     m_operationMode = NONE;
793     m_dragItem = NULL;
794 }
795
796 void CustomTrackView::deleteClip(ItemInfo info) {
797     ClipItem *item = getClipItemAt((int) info.startPos.frames(m_document->fps()), info.track);
798     if (!item) {
799         kDebug() << "----------------  ERROR, CANNOT find clip to move at...";// << rect.x();
800         return;
801     }
802     item->baseClip()->removeReference();
803     m_document->updateClip(item->baseClip()->getId());
804     delete item;
805     m_document->renderer()->mltRemoveClip(m_tracksList.count() - info.track, info.startPos);
806     m_document->renderer()->doRefresh();
807 }
808
809 void CustomTrackView::deleteSelectedClips() {
810     QList<QGraphicsItem *> itemList = items();
811     for (int i = 0; i < itemList.count(); i++) {
812         if (itemList.at(i)->type() == AVWIDGET && itemList.at(i)->isSelected()) {
813             ClipItem *item = (ClipItem *) itemList.at(i);
814             ItemInfo info;
815             info.startPos = item->startPos();
816             info.endPos = item->endPos();
817             info.track = item->track();
818             AddTimelineClipCommand *command = new AddTimelineClipCommand(this, item->xml(), item->clipProducer(), info, true, true);
819             m_commandStack->push(command);
820         }
821     }
822 }
823
824 void CustomTrackView::addClip(QDomElement xml, int clipId, ItemInfo info) {
825     DocClipBase *baseclip = m_document->clipManager()->getClipById(clipId);
826     ClipItem *item = new ClipItem(baseclip, info, m_scale, m_document->fps());
827     scene()->addItem(item);
828     baseclip->addReference();
829     m_document->updateClip(baseclip->getId());
830     m_document->renderer()->mltInsertClip(m_tracksList.count() - info.track, info.startPos, xml);
831     m_document->renderer()->doRefresh();
832 }
833
834 ClipItem *CustomTrackView::getClipItemAt(int pos, int track) {
835     QList<QGraphicsItem *> list = scene()->items(QPointF(pos * m_scale, track * m_tracksHeight + m_tracksHeight / 2));
836     ClipItem *clip = NULL;
837     for (int i = 0; i < list.size(); ++i) {
838         if (list.at(i)->type() == AVWIDGET) {
839             clip = static_cast <ClipItem *>(list.at(i));
840             break;
841         }
842     }
843     return clip;
844 }
845
846 ClipItem *CustomTrackView::getClipItemAt(GenTime pos, int track) {
847     int framepos = (int)(pos.frames(m_document->fps()) * m_scale);
848     return getClipItemAt(framepos, track);
849 }
850
851 Transition *CustomTrackView::getTransitionItemAt(int pos, int track) {
852     QList<QGraphicsItem *> list = scene()->items(QPointF(pos * m_scale, track * m_tracksHeight + m_tracksHeight / 2));
853     Transition *clip = NULL;
854     for (int i = 0; i < list.size(); ++i) {
855         if (list.at(i)->type() == TRANSITIONWIDGET) {
856             clip = static_cast <Transition *>(list.at(i));
857             break;
858         }
859     }
860     return clip;
861 }
862
863 Transition *CustomTrackView::getTransitionItemAt(GenTime pos, int track) {
864     int framepos = (int)(pos.frames(m_document->fps()) * m_scale);
865     return getTransitionItemAt(framepos, track);
866 }
867
868 void CustomTrackView::moveClip(const ItemInfo start, const ItemInfo end) {
869     ClipItem *item = getClipItemAt((int) start.startPos.frames(m_document->fps()) + 1, start.track);
870     if (!item) {
871         kDebug() << "----------------  ERROR, CANNOT find clip to move at.. ";// << startPos.x() * m_scale * FRAME_SIZE + 1 << ", " << startPos.y() * m_tracksHeight + m_tracksHeight / 2;
872         return;
873     }
874     //kDebug() << "----------------  Move CLIP FROM: " << startPos.x() << ", END:" << endPos.x() << ",TRACKS: " << startPos.y() << " TO " << endPos.y();
875     item->moveTo((int) end.startPos.frames(m_document->fps()), m_scale, (int)((end.track - start.track) * m_tracksHeight), end.track);
876     m_document->renderer()->mltMoveClip((int)(m_tracksList.count() - start.track), (int)(m_tracksList.count() - end.track), (int) start.startPos.frames(m_document->fps()), (int)end.startPos.frames(m_document->fps()));
877 }
878
879 void CustomTrackView::moveTransition(const ItemInfo start, const ItemInfo end) {
880     Transition *item = getTransitionItemAt((int)start.startPos.frames(m_document->fps()) + 1, start.track);
881     if (!item) {
882         kDebug() << "----------------  ERROR, CANNOT find transition to move... ";// << startPos.x() * m_scale * FRAME_SIZE + 1 << ", " << startPos.y() * m_tracksHeight + m_tracksHeight / 2;
883         return;
884     }
885     //kDebug() << "----------------  Move TRANSITION FROM: " << startPos.x() << ", END:" << endPos.x() << ",TRACKS: " << oldtrack << " TO " << newtrack;
886
887     //kDebug()<<"///  RESIZE TRANS START: ("<< startPos.x()<<"x"<< startPos.y()<<") / ("<<endPos.x()<<"x"<< endPos.y()<<")";
888     if (end.endPos - end.startPos == start.endPos - start.startPos) {
889         // Transition was moved
890         item->moveTo((int) end.startPos.frames(m_document->fps()), m_scale, (end.track - start.track) * m_tracksHeight, end.track);
891     } else if (end.endPos == start.endPos) {
892         // Transition start resize
893         item->resizeStart((int) end.startPos.frames(m_document->fps()), m_scale);
894     } else {
895         // Transition end resize;
896         item->resizeEnd((int) end.endPos.frames(m_document->fps()), m_scale);
897     }
898     //item->moveTransition(GenTime((int) (endPos.x() - startPos.x()), m_document->fps()));
899     m_document->renderer()->mltMoveTransition(item->transitionTag(), m_tracksList.count() - start.track, start.track - end.track, start.startPos, start.endPos, end.startPos, end.endPos);
900 }
901
902 void CustomTrackView::resizeClip(const ItemInfo start, const ItemInfo end) {
903     int offset;
904     bool resizeClipStart = true;
905     if (start.startPos == end.startPos) resizeClipStart = false;
906     if (resizeClipStart) offset = 1;
907     else offset = -1;
908     ClipItem *item = getClipItemAt((int)(start.startPos.frames(m_document->fps()) + offset), start.track);
909     if (!item) {
910         kDebug() << "----------------  ERROR, CANNOT find clip to resize at... "; // << startPos;
911         return;
912     }
913     if (resizeClipStart) {
914         m_document->renderer()->mltResizeClipStart(m_tracksList.count() - item->track(), item->endPos(), end.startPos, item->startPos(), item->cropStart() + end.startPos - start.startPos, item->cropStart() + end.startPos - start.startPos + item->endPos() - end.startPos);
915         item->resizeStart((int) end.startPos.frames(m_document->fps()), m_scale);
916     } else {
917         m_document->renderer()->mltResizeClipEnd(m_tracksList.count() - item->track(), item->startPos(), item->cropStart(), item->cropStart() + end.startPos - item->startPos());
918         item->resizeEnd((int) end.startPos.frames(m_document->fps()), m_scale);
919     }
920     m_document->renderer()->doRefresh();
921 }
922
923 double CustomTrackView::getSnapPointForPos(double pos) {
924     for (int i = 0; i < m_snapPoints.size(); ++i) {
925         if (abs((int)(pos - m_snapPoints.at(i).frames(m_document->fps()) * m_scale)) < 10) {
926             //kDebug()<<" FOUND SNAP POINT AT: "<<m_snapPoints.at(i)<<", current pos: "<<pos / m_scale;
927             return m_snapPoints.at(i).frames(m_document->fps()) * m_scale + 0.5;
928         }
929         if (m_snapPoints.at(i).frames(m_document->fps() * m_scale) > pos) break;
930     }
931     return pos;
932 }
933
934 void CustomTrackView::updateSnapPoints(AbstractClipItem *selected) {
935     m_snapPoints.clear();
936     GenTime offset;
937     if (selected) offset = selected->duration();
938     QList<QGraphicsItem *> itemList = items();
939     for (int i = 0; i < itemList.count(); i++) {
940         if (itemList.at(i)->type() == AVWIDGET && itemList.at(i) != selected) {
941             ClipItem *item = static_cast <ClipItem *>(itemList.at(i));
942             GenTime start = item->startPos();
943             GenTime end = item->endPos();
944             m_snapPoints.append(start);
945             m_snapPoints.append(end);
946             if (offset != GenTime()) {
947                 if (start > offset) m_snapPoints.append(start - offset);
948                 if (end > offset) m_snapPoints.append(end - offset);
949             }
950         } else if (itemList.at(i)->type() == TRANSITIONWIDGET) {
951             Transition *transition = static_cast <Transition*>(itemList.at(i));
952             GenTime start = transition->startPos();
953             GenTime end = transition->endPos();
954             m_snapPoints.append(start);
955             m_snapPoints.append(end);
956             if (offset != GenTime()) {
957                 if (start > offset) m_snapPoints.append(start - offset);
958                 if (end > offset) m_snapPoints.append(end - offset);
959             }
960         }
961     }
962     qSort(m_snapPoints);
963     //for (int i = 0; i < m_snapPoints.size(); ++i)
964     //    kDebug() << "SNAP POINT: " << m_snapPoints.at(i).frames(25);
965 }
966
967
968 void CustomTrackView::setScale(double scaleFactor) {
969     //scale(scaleFactor, scaleFactor);
970     double pos = cursorPos() / m_scale;
971     m_scale = scaleFactor;
972     kDebug() << " HHHHHHHH  SCALING: " << m_scale;
973     QList<QGraphicsItem *> itemList = items();
974
975     for (int i = 0; i < itemList.count(); i++) {
976         if (itemList.at(i)->type() == AVWIDGET || itemList.at(i)->type() == TRANSITIONWIDGET) {
977             AbstractClipItem *clip = (AbstractClipItem *)itemList.at(i);
978             clip->setRect(clip->startPos().frames(m_document->fps()) * m_scale, clip->rect().y(), clip->duration().frames(m_document->fps()) * m_scale, clip->rect().height());
979         }
980     }
981     updateCursorPos();
982     centerOn(QPointF(cursorPos(), m_tracksHeight));
983     setSceneRect(0, 0, (m_projectDuration + 100) * m_scale, sceneRect().height());
984 }
985
986 void CustomTrackView::drawBackground(QPainter * painter, const QRectF & rect) {
987     QRect rectInView = viewport()->rect();
988     rectInView.moveTo(horizontalScrollBar()->value(), verticalScrollBar()->value());
989
990     QColor base = palette().button().color();
991     painter->setClipRect(rect);
992     painter->drawLine(rectInView.left(), 0, rectInView.right(), 0);
993     uint max = m_tracksList.count();
994     for (uint i = 0; i < max;i++) {
995         if (m_tracksList.at(max - i - 1).type == AUDIOTRACK) painter->fillRect(rectInView.left(), m_tracksHeight * i + 1, rectInView.right() - rectInView.left() + 1, m_tracksHeight - 1, QBrush(QColor(240, 240, 255)));
996         painter->drawLine(rectInView.left(), m_tracksHeight * (i + 1), rectInView.right(), m_tracksHeight * (i + 1));
997         //painter->drawText(QRectF(10, 50 * i, 100, 50 * i + 49), Qt::AlignLeft, i18n(" Track ") + QString::number(i + 1));
998     }
999     int lowerLimit = m_tracksHeight * m_tracksList.count() + 1;
1000     if (height() > lowerLimit)
1001         painter->fillRect(QRectF(rectInView.left(), lowerLimit, rectInView.width(), height() - lowerLimit), QBrush(base));
1002 }
1003 /*
1004 void CustomTrackView::drawForeground ( QPainter * painter, const QRectF & rect )
1005 {
1006   //kDebug()<<"/////  DRAWING FB: "<<rect.x()<<", width: "<<rect.width();
1007   painter->fillRect(rect, QColor(50, rand() % 250,50,100));
1008   painter->drawLine(m_cursorPos, rect.y(), m_cursorPos, rect.y() + rect.height());
1009 }
1010 */
1011 #include "customtrackview.moc"