]> git.sesse.net Git - kdenlive/blob - src/customtrackview.cpp
progress in timeline widget
[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
37 CustomTrackView::CustomTrackView(KUndoStack *commandStack, QGraphicsScene * projectscene, QWidget *parent)
38     : QGraphicsView(projectscene, parent), m_commandStack(commandStack), 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)
39 {
40   setMouseTracking(true);
41   setAcceptDrops(true);
42   m_animationTimer = new QTimeLine(800);
43   m_animationTimer->setFrameRange(0, 5);
44   m_animationTimer->setUpdateInterval(100);
45   m_animationTimer->setLoopCount(0);
46   m_tipColor = QColor(230, 50, 0, 150);
47   setContentsMargins(0, 0, 0, 0);
48   if (projectscene) {
49     m_cursorLine = projectscene->addLine(0, 0, 0, 50);
50     m_cursorLine->setZValue(1000);
51   }
52 }
53
54 void CustomTrackView::initView()
55 {
56
57 }
58
59 // virtual
60 void CustomTrackView::resizeEvent ( QResizeEvent * event )
61 {
62   QGraphicsView::resizeEvent(event);
63 }
64
65 // virtual
66 void CustomTrackView::wheelEvent ( QWheelEvent * e ) 
67 {
68   if (e->modifiers() == Qt::ControlModifier) {
69     if (e->delta() > 0) emit zoomIn();
70     else emit zoomOut();
71   }
72   else {
73     if (e->delta() > 0) horizontalScrollBar()->setValue (horizontalScrollBar()->value() + horizontalScrollBar()->singleStep ());
74     else  horizontalScrollBar()->setValue (horizontalScrollBar()->value() - horizontalScrollBar()->singleStep ());
75   }
76 }
77
78
79 // virtual 
80 void CustomTrackView::mouseMoveEvent ( QMouseEvent * event )
81 {
82   int pos = event->x();
83   /*if (event->modifiers() == Qt::ControlModifier)
84     setDragMode(QGraphicsView::ScrollHandDrag);
85   else if (event->modifiers() == Qt::ShiftModifier) 
86     setDragMode(QGraphicsView::RubberBandDrag);
87   else*/ {
88
89       if (event->button() == Qt::LeftButton) {
90         // a button was pressed, delete visual tips
91         if (m_animation) delete m_animation;
92         m_animation = NULL;
93         if (m_visualTip) delete m_visualTip;
94         m_visualTip = NULL;
95         QGraphicsView::mouseMoveEvent(event);
96         return;
97       }
98
99     QList<QGraphicsItem *> itemList = items( event->pos());
100     int i = 0;
101     QGraphicsItem *item = NULL;
102     for (int i = 0; i < itemList.count(); i++) {
103       if (itemList.at(i)->type() == 70000) {
104         item = itemList.at(i);
105         break;
106       }
107     }
108     if (item) {
109       ClipItem *clip = (ClipItem*) item;
110       double size = mapToScene(QPoint(8, 0)).x();
111       OPERATIONTYPE opMode = clip->operationMode(mapToScene(event->pos()));
112       if (opMode == m_moveOpMode) {
113         QGraphicsView::mouseMoveEvent(event);
114         return;
115       }
116       else {
117       if (m_visualTip) {
118         if (m_animation) delete m_animation;
119         m_animation = NULL;
120         delete m_visualTip;
121         m_visualTip = NULL;
122       }
123       }
124       m_moveOpMode = opMode;
125       if (opMode == MOVE) {
126         setCursor(Qt::OpenHandCursor);
127       }
128       else if (opMode == RESIZESTART) {
129         kDebug()<<"********  RESIZE CLIP START; WIDTH: "<<size;
130         if (m_visualTip == NULL) {
131           m_visualTip = new QGraphicsRectItem(clip->rect().x(), clip->rect().y(), size, clip->rect().height());
132           ((QGraphicsRectItem*) m_visualTip)->setBrush(m_tipColor);
133           ((QGraphicsRectItem*) m_visualTip)->setPen(QPen(Qt::transparent));
134           m_visualTip->setZValue (100);
135           m_animation = new QGraphicsItemAnimation;
136           m_animation->setItem(m_visualTip);
137           m_animation->setTimeLine(m_animationTimer);
138           m_visualTip->setPos(0, 0);
139           double scale = 2.0;
140           m_animation->setScaleAt(.5, scale, 1);
141           m_animation->setPosAt(.5, QPointF(clip->rect().x() - clip->rect().x() * scale, 0));
142           scale = 1.0;
143           m_animation->setScaleAt(1, scale, 1);
144           m_animation->setPosAt(1, QPointF(clip->rect().x() - clip->rect().x() * scale, 0));
145           scene()->addItem(m_visualTip);
146           m_animationTimer->start();
147         }
148         setCursor(Qt::SizeHorCursor);
149       }
150       else if (opMode == RESIZEEND) {
151         if (m_visualTip == NULL) {
152           m_visualTip = new QGraphicsRectItem(clip->rect().x() + clip->rect().width() - size, clip->rect().y(), size, clip->rect().height());
153           ((QGraphicsRectItem*) m_visualTip)->setBrush(m_tipColor);
154           ((QGraphicsRectItem*) m_visualTip)->setPen(QPen(Qt::transparent));
155           m_visualTip->setZValue (100);
156           m_animation = new QGraphicsItemAnimation;
157           m_animation->setItem(m_visualTip);
158           m_animation->setTimeLine(m_animationTimer);
159           m_visualTip->setPos(0, 0);
160           double scale = 2.0;
161           m_animation->setScaleAt(.5, scale, 1);
162           m_animation->setPosAt(.5, QPointF(clip->rect().x() - clip->rect().x() * scale - clip->rect().width(), 0));
163           scale = 1.0;
164           m_animation->setScaleAt(1, scale, 1);
165           m_animation->setPosAt(1, QPointF(clip->rect().x() - clip->rect().x() * scale, 0));
166           scene()->addItem(m_visualTip);
167           m_animationTimer->start();
168         }
169         setCursor(Qt::SizeHorCursor);
170       }
171       else if (opMode == FADEIN) {
172         if (m_visualTip == NULL) {
173           m_visualTip = new QGraphicsEllipseItem(clip->rect().x() - size, clip->rect().y() - 8, size * 2, 16);
174           ((QGraphicsEllipseItem*) m_visualTip)->setBrush(m_tipColor);
175           ((QGraphicsEllipseItem*) m_visualTip)->setPen(QPen(Qt::transparent));
176           m_visualTip->setZValue (100);
177           m_animation = new QGraphicsItemAnimation;
178           m_animation->setItem(m_visualTip);
179           m_animation->setTimeLine(m_animationTimer);
180           m_visualTip->setPos(0, 0);
181           double scale = 2.0;
182           m_animation->setScaleAt(.5, scale, scale);
183           m_animation->setPosAt(.5, QPointF(clip->rect().x() - clip->rect().x() * scale, clip->rect().y() - clip->rect().y() * scale));
184           scale = 1.0;
185           m_animation->setScaleAt(1, scale, scale);
186           m_animation->setPosAt(1, QPointF(clip->rect().x() - clip->rect().x() * scale, clip->rect().y() - clip->rect().y() * scale));
187           scene()->addItem(m_visualTip);
188           m_animationTimer->start();
189         }
190         setCursor(Qt::PointingHandCursor);
191       }
192       else if (opMode == FADEOUT) {
193         if (m_visualTip == NULL) {
194           m_visualTip = new QGraphicsEllipseItem(clip->rect().x() + clip->rect().width() - size, clip->rect().y() - 8, size*2, 16);
195           ((QGraphicsEllipseItem*) m_visualTip)->setBrush(m_tipColor);
196           ((QGraphicsEllipseItem*) m_visualTip)->setPen(QPen(Qt::transparent));
197           m_visualTip->setZValue (100);
198           m_animation = new QGraphicsItemAnimation;
199           m_animation->setItem(m_visualTip);
200           m_animation->setTimeLine(m_animationTimer);
201           m_visualTip->setPos(0, 0);
202           double scale = 2.0;
203           m_animation->setScaleAt(.5, scale, scale);      
204           m_animation->setPosAt(.5, QPointF(clip->rect().x() - clip->rect().x() * scale - clip->rect().width(), clip->rect().y() - clip->rect().y() * scale));
205           scale = 1.0;
206           m_animation->setScaleAt(1, scale, scale);
207           m_animation->setPosAt(1, QPointF(clip->rect().x() - clip->rect().x() * scale, clip->rect().y() - clip->rect().y() * scale));
208           scene()->addItem(m_visualTip);
209           m_animationTimer->start();
210         }
211         setCursor(Qt::PointingHandCursor);
212       }
213     }
214     else {
215       m_moveOpMode = NONE;
216       if (m_visualTip) {
217         if (m_animation) delete m_animation;
218         m_animation = NULL;
219         delete m_visualTip;
220         m_visualTip = NULL;
221       }
222       setCursor(Qt::ArrowCursor);
223     }
224   }
225   QGraphicsView::mouseMoveEvent(event);
226 }
227
228 // virtual 
229 void CustomTrackView::mousePressEvent ( QMouseEvent * event )
230 {
231   int pos = event->x();
232   if (event->modifiers() == Qt::ControlModifier) 
233     setDragMode(QGraphicsView::ScrollHandDrag);
234   else if (event->modifiers() == Qt::ShiftModifier) 
235     setDragMode(QGraphicsView::RubberBandDrag);
236   else {
237     QGraphicsItem * item = itemAt(event->pos());
238     if (item && item->type() != 70000) item = item->parentItem();
239     if (item && item->type() == 70000) {
240       m_dragItem = (ClipItem *) item;
241       m_operationMode = m_dragItem->operationMode(item->mapFromScene(mapToScene(event->pos())));
242       if (m_operationMode == MOVE || m_operationMode == RESIZESTART) m_startPos = QPointF(m_dragItem->rect().x(), m_dragItem->rect().y());
243       else if (m_operationMode == RESIZEEND) m_startPos = QPointF(m_dragItem->rect().x() + m_dragItem->rect().width(), m_dragItem->rect().y());
244
245      kDebug()<<"//////// ITEM CLICKED: "<<m_startPos;
246       /*while (item->parentItem()) 
247         item = item->parentItem();
248
249         int cursorPos = event->x();
250         QRectF itemRect = item->sceneBoundingRect();
251         int itemStart = mapFromScene(itemRect.x(), 0).x();
252         int itemEnd = mapFromScene(itemRect.x() + itemRect.width(), 0).x();
253         if (abs(itemStart - cursorPos) < 6)
254           ((ClipItem *) item )->setResizeMode(1);
255         else if (abs(itemEnd - cursorPos) < 6)
256           ((ClipItem *) item )->setResizeMode(2);
257     */}
258     else {
259       kDebug()<<"//////// NO ITEM FOUND ON CLICK";
260       m_dragItem = NULL;
261       setCursor(Qt::ArrowCursor);
262       setCursorPos((int) mapToScene(event->x(), 0).x());
263       emit cursorMoved(cursorPos());
264     }
265   }
266   //kDebug()<<pos;
267   QGraphicsView::mousePressEvent(event);
268 }
269
270 void CustomTrackView::dragEnterEvent ( QDragEnterEvent * event )
271 {
272   if (event->mimeData()->hasText()) {
273     QString clip = event->mimeData()->text();
274     addItem(clip, event->pos());
275     event->acceptProposedAction();
276   }
277 }
278
279
280 void CustomTrackView::addItem(QString producer, QPoint pos)
281 {
282   QDomDocument doc;
283   doc.setContent(producer);
284   QDomElement elem = doc.documentElement();
285   int in = elem.attribute("in", 0).toInt();
286   int out = elem.attribute("duration", 0).toInt();
287   if (out == 0) out = elem.attribute("out", 0).toInt() - in;
288   kDebug()<<"ADDING CLIP: "<<producer<<", OUT: "<<out<<", POS: "<<mapToScene(pos);
289   int trackTop = ((int) mapToScene(pos).y()/50) * 50 + 1;
290   QString clipName = elem.attribute("name");
291   if (clipName.isEmpty()) clipName = KUrl(elem.attribute("resource")).fileName();
292   m_dropItem = new ClipItem(elem.attribute("type").toInt(), clipName, elem.attribute("id").toInt(), out, QRectF(mapToScene(pos).x(), trackTop, out, 49));
293   scene()->addItem(m_dropItem);
294 }
295
296
297 void CustomTrackView::dragMoveEvent(QDragMoveEvent * event) {
298   event->setDropAction(Qt::IgnoreAction);
299   if (m_dropItem) {
300     int trackTop = ((int) mapToScene(event->pos()).y()/50) * 50 + 1;
301     m_dropItem->moveTo(mapToScene(event->pos()).x(), trackTop - m_dropItem->rect().y());
302   }
303         //if (item) {
304                 event->setDropAction(Qt::MoveAction);
305                 if (event->mimeData()->hasText()) {
306                         event->acceptProposedAction();
307                 }
308         //}
309 }
310
311 void CustomTrackView::dragLeaveEvent ( QDragLeaveEvent * event ) {
312   if (m_dropItem) {
313     delete m_dropItem;
314     m_dropItem = NULL;
315   }
316 }
317
318 void CustomTrackView::dropEvent ( QDropEvent * event ) {
319   if (m_dropItem) {
320     AddTimelineClipCommand *command = new AddTimelineClipCommand(this, m_dropItem->clipType(), m_dropItem->clipName(), m_dropItem->clipProducer(), m_dropItem->maxDuration(), m_dropItem->rect(), false);
321     m_commandStack->push(command);
322   }
323   m_dropItem = NULL;
324 }
325
326
327 QStringList CustomTrackView::mimeTypes () const
328 {
329     QStringList qstrList;
330     // list of accepted mime types for drop
331     qstrList.append("text/plain");
332     return qstrList;
333 }
334
335 Qt::DropActions CustomTrackView::supportedDropActions () const
336 {
337     // returns what actions are supported when dropping
338     return Qt::MoveAction;
339 }
340
341 void CustomTrackView::setDuration(int duration)
342 {
343   kDebug()<<"/////////////  PRO DUR: "<<duration<<", height: "<<50 * m_tracksCount;
344   m_projectDuration = duration;
345   scene()->setSceneRect(0, 0, m_projectDuration + 500, scene()->sceneRect().height()); //50 * m_tracksCount);
346 }
347
348
349 void CustomTrackView::addTrack ()
350 {
351   m_tracksCount++;
352   m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), 50 * m_tracksCount);
353   //setSceneRect(0, 0, sceneRect().width(), 50 * m_tracksCount);
354   //verticalScrollBar()->setMaximum(50 * m_tracksCount); 
355   //setFixedHeight(50 * m_tracksCount);
356 }
357
358 void CustomTrackView::removeTrack ()
359 {
360   m_tracksCount--;
361   m_cursorLine->setLine(m_cursorLine->line().x1(), 0, m_cursorLine->line().x1(), 50 * m_tracksCount);
362 }
363
364 void CustomTrackView::setCursorPos(int pos)
365 {
366   m_cursorPos = pos;
367   m_cursorLine->setPos(pos, 0);
368 }
369
370 int CustomTrackView::cursorPos()
371 {
372   return m_cursorPos;
373 }
374
375 void CustomTrackView::mouseReleaseEvent ( QMouseEvent * event )
376 {
377   QGraphicsView::mouseReleaseEvent(event);
378   setDragMode(QGraphicsView::NoDrag);
379   if (m_dragItem == NULL) return;
380   //kDebug()<<"/// MOVING CLIP: "<<m_startPos<<", END: "<<QPoint(m_dragItem->rect().x(),m_dragItem->rect().y());
381   if (m_operationMode == MOVE) {
382     // move clip
383     MoveClipCommand *command = new MoveClipCommand(this, m_startPos, QPointF(m_dragItem->rect().x(), m_dragItem->rect().y()), false);
384     m_commandStack->push(command);
385   }
386   else if (m_operationMode == RESIZESTART) {
387     // resize start
388     ResizeClipCommand *command = new ResizeClipCommand(this, m_startPos, QPointF(m_dragItem->rect().x(), m_dragItem->rect().y()), true, false);
389     m_commandStack->push(command);
390   }
391   else if (m_operationMode == RESIZEEND) {
392     // resize end
393     ResizeClipCommand *command = new ResizeClipCommand(this, m_startPos, QPointF(m_dragItem->rect().x() + m_dragItem->rect().width(), m_dragItem->rect().y()), false, false);
394     m_commandStack->push(command);
395   }
396 }
397
398 void CustomTrackView::deleteClip ( const QRectF &rect )
399 {
400   ClipItem *item = (ClipItem *) scene()->itemAt(rect.x() + 1, rect.y() + 1);
401   if (!item) {
402     kDebug()<<"----------------  ERROR, CANNOT find clip to move at: "<<rect.x();
403     return;
404   }
405   delete item;
406 }
407
408 void CustomTrackView::addClip ( int clipType, QString clipName, int clipProducer, int maxDuration, const QRectF &rect )
409 {
410   ClipItem *item = new ClipItem(clipType, clipName, clipProducer, maxDuration, rect);
411   scene()->addItem(item);
412 }
413
414 void CustomTrackView::moveClip ( const QPointF &startPos, const QPointF &endPos )
415 {
416   ClipItem *item = (ClipItem *) scene()->itemAt(startPos.x() + 1, startPos.y() + 1);
417   if (!item) {
418     kDebug()<<"----------------  ERROR, CANNOT find clip to move at: "<<startPos;
419     return;
420   }
421   item->setRect(QRectF(endPos.x(), endPos.y(), item->rect().width(), item->rect().height()));
422   QList <QGraphicsItem *> childrenList = item->children();
423   for (int i = 0; i < childrenList.size(); ++i) {
424     childrenList.at(i)->moveBy(endPos.x() - startPos.x() , endPos.y() - startPos.y());
425   }
426 }
427
428 void CustomTrackView::resizeClip ( const QPointF &startPos, const QPointF &endPos, bool resizeClipStart )
429 {
430   int offset;
431   if (resizeClipStart) offset = 1;
432   else offset = -1;
433   ClipItem *item = (ClipItem *) scene()->itemAt(startPos.x() + offset, startPos.y() + 1);
434   if (!item) {
435     kDebug()<<"----------------  ERROR, CANNOT find clip to resize at: "<<startPos;
436     return;
437   }
438   qreal diff = endPos.x() - startPos.x();
439   if (resizeClipStart) {
440     item->setRect(QRectF(endPos.x(), endPos.y(), item->rect().width() - diff, item->rect().height()));
441     QList <QGraphicsItem *> childrenList = item->children();
442     for (int i = 0; i < childrenList.size(); ++i) {
443       childrenList.at(i)->moveBy(diff / 2 , endPos.y() - startPos.y());
444     }
445   }
446   else {
447     //kdDebug()<<"///////  RESIZE CLIP END: "<<item->rect().x()<<", "<<item->rect().width()<<", "<<startPos<<", "<<endPos;
448     item->setRect(QRectF(item->rect().x(), item->rect().y(), endPos.x() - item->rect().x(), item->rect().height()));
449     QList <QGraphicsItem *> childrenList = item->children();
450     for (int i = 0; i < childrenList.size(); ++i) {
451       childrenList.at(i)->moveBy(-diff/2, endPos.y() - startPos.y());
452     }
453   }
454 }
455
456
457 void CustomTrackView::drawBackground ( QPainter * painter, const QRectF & rect )  
458 {
459   kDebug()<<"/////  DRAWING BG TRACKS: "<<m_tracksCount;
460   QColor base = palette().button().color();
461   painter->setPen(base);
462   painter->setClipRect(rect);
463   painter->drawLine(0, 0, rect.width(), 0);
464     for (uint i = 0; i < m_tracksCount;i++)
465     {
466     painter->drawLine(0, 50 * (i+1), rect.width(), 50 * (i+1));
467       //painter->drawText(QRectF(10, 50 * i, 100, 50 * i + 49), Qt::AlignLeft, i18n(" Track ") + QString::number(i));
468     }
469   int lowerLimit = 50 * m_tracksCount;
470   if (height() > lowerLimit)
471   painter->fillRect(QRectF(0, lowerLimit - rect.y(), rect.width(), height() - lowerLimit - rect.y()), QBrush(base));
472 }
473 /*
474 void CustomTrackView::drawForeground ( QPainter * painter, const QRectF & rect )  
475 {
476   //kDebug()<<"/////  DRAWING FB: "<<rect.x()<<", width: "<<rect.width();
477   painter->fillRect(rect, QColor(50, rand() % 250,50,100));
478   painter->drawLine(m_cursorPos, rect.y(), m_cursorPos, rect.y() + rect.height());
479 }
480 */
481 #include "customtrackview.moc"