]> git.sesse.net Git - kdenlive/blob - src/graphicsscenerectmove.cpp
Many improvements to title clips (recreate when missing, fix text selection visible...
[kdenlive] / src / graphicsscenerectmove.cpp
1
2 #include <KDebug>
3 #include <QGraphicsSceneMouseEvent>
4 #include <QGraphicsRectItem>
5 #include <QGraphicsSvgItem>
6 #include <QGraphicsView>
7 #include <QCursor>
8 #include <QTextCursor>
9 #include <QList>
10 #include <QKeyEvent>
11 #include <QApplication>
12 #include <QTextBlock>
13
14 #include "graphicsscenerectmove.h"
15
16 GraphicsSceneRectMove::GraphicsSceneRectMove(QObject *parent): QGraphicsScene(parent), m_selectedItem(NULL), resizeMode(NoResize), m_tool(TITLE_RECTANGLE) {
17     //grabMouse();
18     zoom = 1.0;
19     setBackgroundBrush(QBrush(Qt::transparent));
20 }
21
22 void GraphicsSceneRectMove::setSelectedItem(QGraphicsItem *item) {
23     clearSelection();
24     m_selectedItem = item;
25     item->setSelected(true);
26     update();
27 }
28
29 TITLETOOL GraphicsSceneRectMove::tool() {
30     return m_tool;
31 }
32
33 void GraphicsSceneRectMove::setTool(TITLETOOL tool) {
34     m_tool = tool;
35     switch (m_tool) {
36     case TITLE_RECTANGLE:
37         setCursor(Qt::CrossCursor);
38         break;
39     case TITLE_TEXT:
40         setCursor(Qt::IBeamCursor);
41         break;
42     default:
43         setCursor(Qt::ArrowCursor);
44     }
45 }
46
47 //virtual
48 void GraphicsSceneRectMove::keyPressEvent(QKeyEvent * keyEvent) {
49     if (m_selectedItem == NULL) {
50         QGraphicsScene::keyPressEvent(keyEvent);
51         return;
52     }
53     int diff = 1;
54     if (m_selectedItem->type() == 8) {
55         QGraphicsTextItem *t = static_cast<QGraphicsTextItem *>(m_selectedItem);
56         if (t->textInteractionFlags() & Qt::TextEditorInteraction) {
57             QGraphicsScene::keyPressEvent(keyEvent);
58             return;
59         }
60     }
61     if (keyEvent->modifiers() & Qt::ControlModifier) diff = 10;
62     switch (keyEvent->key()) {
63     case Qt::Key_Left:
64         m_selectedItem->setPos(m_selectedItem->pos() - QPointF(diff, 0));
65         emit itemMoved();
66         break;
67     case Qt::Key_Right:
68         m_selectedItem->setPos(m_selectedItem->pos() + QPointF(diff, 0));
69         emit itemMoved();
70         break;
71     case Qt::Key_Up:
72         m_selectedItem->setPos(m_selectedItem->pos() - QPointF(0, diff));
73         emit itemMoved();
74         break;
75     case Qt::Key_Down:
76         m_selectedItem->setPos(m_selectedItem->pos() + QPointF(0, diff));
77         emit itemMoved();
78         break;
79     case Qt::Key_Delete:
80     case Qt::Key_Backspace:
81         delete m_selectedItem;
82         m_selectedItem = NULL;
83         emit selectionChanged();
84         break;
85     default:
86         QGraphicsScene::keyPressEvent(keyEvent);
87     }
88     emit actionFinished();
89 }
90
91 //virtual
92 void GraphicsSceneRectMove::mouseDoubleClickEvent(QGraphicsSceneMouseEvent* e) {
93     QPointF p = e->scenePos();
94     p += QPoint(-2, -2);
95     resizeMode = NoResize;
96     m_selectedItem = NULL;
97     QGraphicsItem* g = items(QRectF(p , QSizeF(4, 4)).toRect()).at(0);
98     if (g) {
99         if (g->type() == 8) {
100             QGraphicsTextItem *t = static_cast<QGraphicsTextItem *>(g);
101             m_selectedItem = g;
102             t->setTextInteractionFlags(Qt::TextEditorInteraction);
103         }
104     }
105     QGraphicsScene::mouseDoubleClickEvent(e);
106 }
107
108 void GraphicsSceneRectMove::mouseReleaseEvent(QGraphicsSceneMouseEvent *e) {
109     if (m_tool == TITLE_RECTANGLE && m_selectedItem) setSelectedItem(m_selectedItem);
110     emit actionFinished();
111     QGraphicsScene::mouseReleaseEvent(e);
112 }
113
114 void GraphicsSceneRectMove::mousePressEvent(QGraphicsSceneMouseEvent* e) {
115     m_clickPoint = e->screenPos();
116     QPointF p = e->scenePos();
117     p += QPoint(-2, -2);
118     resizeMode = NoResize;
119     const QList <QGraphicsItem *> list = items(QRectF(p , QSizeF(4, 4)).toRect());
120     QGraphicsItem *item = NULL;
121     bool hasSelected = false;
122
123     if (m_tool == TITLE_SELECT) {
124         foreach(QGraphicsItem *g, list) {
125             kDebug() << " - - CHECKING ITEM Z:" << g->zValue() << ", TYPE: " << g->type();
126             // check is there is a selected item in list
127             if (g->zValue() > -1000 && g->isSelected()) {
128                 hasSelected = true;
129                 item = g;
130                 break;
131             }
132         }
133         if (item == NULL) {
134             if (m_selectedItem && m_selectedItem->type() == 8) {
135                 // disable text editing
136                 QGraphicsTextItem *t = static_cast<QGraphicsTextItem *>(m_selectedItem);
137                 t->textCursor().setPosition(0);
138                 QTextBlock cur = t->textCursor().block();
139                 t->setTextCursor(QTextCursor(cur));
140                 t->setTextInteractionFlags(Qt::NoTextInteraction);
141             }
142             m_selectedItem = NULL;
143             foreach(QGraphicsItem* g, list) {
144                 if (g->zValue() > -1000) {
145                     item = g;
146                     break;
147                 }
148             }
149         }
150         if (item != NULL) {
151             m_sceneClickPoint = e->scenePos();
152             m_selectedItem = item;
153             kDebug() << "/////////  ITEM TYPE: " << item->type();
154             if (item->type() == 8) {
155                 QGraphicsTextItem *t = static_cast<QGraphicsTextItem *>(item);
156                 if (t->textInteractionFlags() == Qt::TextEditorInteraction) {
157                     QGraphicsScene::mousePressEvent(e);
158                     return;
159                 }
160                 t->setTextInteractionFlags(Qt::NoTextInteraction);
161                 setCursor(Qt::ClosedHandCursor);
162             } else if (item->type() == 3 || item->type() == 13 || item->type() == 7) {
163                 QRectF r;
164                 if (m_selectedItem->type() == 3) {
165                     r = ((QGraphicsRectItem*)m_selectedItem)->rect();
166                 } else r = m_selectedItem->boundingRect();
167
168                 r.translate(item->scenePos());
169                 if ((r.toRect().topLeft() - e->scenePos().toPoint()).manhattanLength() < 6 / zoom) {
170                     resizeMode = TopLeft;
171                 } else if ((r.toRect().bottomLeft() - e->scenePos().toPoint()).manhattanLength() < 6 / zoom) {
172                     resizeMode = BottomLeft;
173                 } else if ((r.toRect().topRight() - e->scenePos().toPoint()).manhattanLength() < 6 / zoom) {
174                     resizeMode = TopRight;
175                 } else if ((r.toRect().bottomRight() - e->scenePos().toPoint()).manhattanLength() < 6 / zoom) {
176                     resizeMode = BottomRight;
177                 } else if (qAbs(r.toRect().left() - e->scenePos().toPoint().x()) < 3 / zoom) {
178                     resizeMode = Left;
179                 } else if (qAbs(r.toRect().right() - e->scenePos().toPoint().x()) < 3 / zoom) {
180                     resizeMode = Right;
181                 } else if (qAbs(r.toRect().top() - e->scenePos().toPoint().y()) < 3 / zoom) {
182                     resizeMode = Up;
183                 } else if (qAbs(r.toRect().bottom() - e->scenePos().toPoint().y()) < 3 / zoom) {
184                     resizeMode = Down;
185                 } else setCursor(Qt::ClosedHandCursor);
186             }
187         }
188         QGraphicsScene::mousePressEvent(e);
189     } else if (m_tool == TITLE_RECTANGLE) {
190         m_sceneClickPoint = e->scenePos();
191         m_selectedItem = NULL;
192     } else if (m_tool == TITLE_TEXT) {
193         m_selectedItem = addText(QString());
194         emit newText((QGraphicsTextItem *) m_selectedItem);
195         m_selectedItem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
196         ((QGraphicsTextItem *)m_selectedItem)->setTextInteractionFlags(Qt::TextEditorInteraction);
197         m_selectedItem->setPos(e->scenePos());
198         QGraphicsScene::mousePressEvent(e);
199     }
200
201     kDebug() << "//////  MOUSE CLICK, RESIZE MODE: " << resizeMode;
202
203 }
204
205 void GraphicsSceneRectMove::clearTextSelection() {
206     if (m_selectedItem && m_selectedItem->type() == 8) {
207         // disable text editing
208         QGraphicsTextItem *t = static_cast<QGraphicsTextItem *>(m_selectedItem);
209         t->textCursor().setPosition(0);
210         QTextBlock cur = t->textCursor().block();
211         t->setTextCursor(QTextCursor(cur));
212         t->setTextInteractionFlags(Qt::NoTextInteraction);
213     }
214     m_selectedItem = NULL;
215     clearSelection();
216 }
217
218 //virtual
219 void GraphicsSceneRectMove::mouseMoveEvent(QGraphicsSceneMouseEvent* e) {
220     if ((e->screenPos() - m_clickPoint).manhattanLength() < QApplication::startDragDistance()) {
221         e->accept();
222         return;
223     }
224     if (m_selectedItem && e->buttons() & Qt::LeftButton) {
225         if (m_selectedItem->type() == 3 || m_selectedItem->type() == 13 || m_selectedItem->type() == 7) {
226             QRectF newrect;
227             if (m_selectedItem->type() == 3) {
228                 newrect = ((QGraphicsRectItem*)m_selectedItem)->rect();
229             } else newrect = m_selectedItem->boundingRect();
230
231             QPointF newpoint = e->scenePos();
232             //newpoint -= m_selectedItem->scenePos();
233             switch (resizeMode) {
234             case TopLeft:
235                 newrect.setBottomRight(newrect.bottomRight() + m_selectedItem->pos() - newpoint);
236                 m_selectedItem->setPos(newpoint);
237                 break;
238             case BottomLeft:
239                 newrect.setBottomRight(QPointF(newrect.bottomRight().x() + m_selectedItem->pos().x() - newpoint.x(), newpoint.y() - m_selectedItem->pos().y()));
240                 m_selectedItem->setPos(QPointF(newpoint.x(), m_selectedItem->pos().y()));
241                 break;
242             case TopRight:
243                 newrect.setBottomRight(QPointF(newpoint.x() - m_selectedItem->pos().x(), newrect.bottom() + m_selectedItem->pos().y() - newpoint.y()));
244                 m_selectedItem->setPos(QPointF(m_selectedItem->pos().x(), newpoint.y()));
245                 break;
246             case BottomRight:
247                 newrect.setBottomRight(newpoint - m_selectedItem->pos());
248                 break;
249             case Left:
250                 newrect.setRight(m_selectedItem->pos().x() + newrect.width() - newpoint.x());
251                 m_selectedItem->setPos(QPointF(newpoint.x(), m_selectedItem->pos().y()));
252                 break;
253             case Right:
254                 newrect.setRight(newpoint.x() - m_selectedItem->pos().x());
255                 break;
256             case Up:
257                 newrect.setBottom(m_selectedItem->pos().y() + newrect.bottom() - newpoint.y());
258                 m_selectedItem->setPos(QPointF(m_selectedItem->pos().x(), newpoint.y()));
259                 break;
260             case Down:
261                 newrect.setBottom(newpoint.y() - m_selectedItem->pos().y());
262                 break;
263             default:
264                 QPointF diff = e->scenePos() - m_sceneClickPoint;
265                 m_sceneClickPoint = e->scenePos();
266                 m_selectedItem->moveBy(diff.x(), diff.y());
267                 break;
268             }
269             if (m_selectedItem->type() == 3 && resizeMode != NoResize) {
270                 QGraphicsRectItem *gi = (QGraphicsRectItem*)m_selectedItem;
271                 gi->setRect(newrect);
272             }
273             /*else {
274             qreal s;
275             if (resizeMode == Left || resizeMode == Right ) s = m_selectedItem->boundingRect().width() / newrect.width();
276             else s = m_selectedItem->boundingRect().height() / newrect.height();
277             m_selectedItem->scale( 1 / s, 1 / s );
278             kDebug()<<"/// SCALING SVG, RESIZE MODE: "<<resizeMode<<", RECT:"<<m_selectedItem->boundingRect();
279             }*/
280             //gi->setPos(m_selectedItem->scenePos());
281             /*if (resizeMode == NoResize) {
282                 QGraphicsScene::mouseMoveEvent(e);
283                 return;
284             }*/
285         } else if (m_selectedItem->type() == 8) {
286             QGraphicsTextItem *t = static_cast<QGraphicsTextItem *>(m_selectedItem);
287             if (t->textInteractionFlags() & Qt::TextEditorInteraction) {
288                 QGraphicsScene::mouseMoveEvent(e);
289                 return;
290             }
291             QPointF diff = e->scenePos() - m_sceneClickPoint;
292             m_sceneClickPoint = e->scenePos();
293             m_selectedItem->moveBy(diff.x(), diff.y());
294         }
295         emit itemMoved();
296     } else if (m_tool == TITLE_SELECT) {
297         QPointF p = e->scenePos();
298         p += QPoint(-2, -2);
299         resizeMode = NoResize;
300         bool itemFound = false;
301         foreach(const QGraphicsItem* g, items(QRectF(p , QSizeF(4, 4)).toRect())) {
302             if ((g->type() == 13 || g->type() == 7) && g->zValue() > -1000) {
303                 // image or svg item
304                 setCursor(Qt::OpenHandCursor);
305                 break;
306             } else if (g->type() == 3 && g->zValue() > -1000) {
307                 QRectF r = ((QGraphicsRectItem*)g)->rect();
308                 r.translate(g->scenePos());
309                 itemFound = true;
310                 if ((r.toRect().topLeft() - e->scenePos().toPoint()).manhattanLength() < 6 / zoom) {
311                     setCursor(QCursor(Qt::SizeFDiagCursor));
312                 } else if ((r.toRect().bottomLeft() - e->scenePos().toPoint()).manhattanLength() < 6 / zoom) {
313                     setCursor(QCursor(Qt::SizeBDiagCursor));
314                 } else if ((r.toRect().topRight() - e->scenePos().toPoint()).manhattanLength() < 6 / zoom) {
315                     setCursor(QCursor(Qt::SizeBDiagCursor));
316                 } else if ((r.toRect().bottomRight() - e->scenePos().toPoint()).manhattanLength() < 6 / zoom) {
317                     setCursor(QCursor(Qt::SizeFDiagCursor));
318                 } else if (qAbs(r.toRect().left() - e->scenePos().toPoint().x()) < 3 / zoom) {
319                     setCursor(Qt::SizeHorCursor);
320                 } else if (qAbs(r.toRect().right() - e->scenePos().toPoint().x()) < 3 / zoom) {
321                     setCursor(Qt::SizeHorCursor);
322                 } else if (qAbs(r.toRect().top() - e->scenePos().toPoint().y()) < 3 / zoom) {
323                     setCursor(Qt::SizeVerCursor);
324                 } else if (qAbs(r.toRect().bottom() - e->scenePos().toPoint().y()) < 3 / zoom) {
325                     setCursor(Qt::SizeVerCursor);
326                 } else setCursor(Qt::OpenHandCursor);
327                 break;
328             }
329             if (!itemFound) setCursor(Qt::ArrowCursor);
330         }
331         QGraphicsScene::mouseMoveEvent(e);
332     } else if (m_tool == TITLE_RECTANGLE && e->buttons() & Qt::LeftButton) {
333         if (m_selectedItem == NULL && (m_clickPoint - e->screenPos()).manhattanLength() >= QApplication::startDragDistance()) {
334             // create new rect item
335             m_selectedItem = addRect(0, 0, e->scenePos().x() - m_sceneClickPoint.x(), e->scenePos().y() - m_sceneClickPoint.y());
336             emit newRect((QGraphicsRectItem *) m_selectedItem);
337             m_selectedItem->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
338             m_selectedItem->setPos(m_sceneClickPoint);
339             resizeMode = BottomRight;
340             QGraphicsScene::mouseMoveEvent(e);
341         }
342     }
343 }
344
345 void GraphicsSceneRectMove::wheelEvent(QGraphicsSceneWheelEvent * wheelEvent) {
346     QList<QGraphicsView*> viewlist = views();
347     //kDebug() << wheelEvent->delta() << " " << zoom;
348     double scale = 1.0;
349     if (viewlist.size() > 0) {
350         if (wheelEvent->delta() < 0) emit sceneZoom(true);
351         else emit sceneZoom(false);
352     }
353 }
354
355 void GraphicsSceneRectMove::setScale(double s) {
356     if (zoom < 1.0 / 7.0 && s < 1.0) return;
357     else if (zoom > 10.0 / 7.9 && s > 1.0) return;
358     QList<QGraphicsView*> viewlist = views();
359     if (viewlist.size() > 0) {
360         viewlist[0]->scale(s, s);
361         zoom = zoom * s;
362     }
363     //kDebug()<<"//////////  ZOOM: "<<zoom;
364 }
365
366 void GraphicsSceneRectMove::setZoom(double s) {
367     QList<QGraphicsView*> viewlist = views();
368     if (viewlist.size() > 0) {
369         viewlist[0]->resetTransform();
370         viewlist[0]->scale(s, s);
371         zoom = s;
372     }
373
374     //kDebug()<<"//////////  ZOOM: "<<zoom;
375 }
376
377 void GraphicsSceneRectMove::setCursor(QCursor c) {
378     const QList<QGraphicsView*> l = views();
379     foreach(QGraphicsView* v, l) {
380         v->setCursor(c);
381     }
382 }