* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA *
***************************************************************************/
-#include <QGraphicsScene>
-#include <QGraphicsView>
-#include <QScrollBar>
-#include <QToolTip>
-
-#include <KDebug>
-#include <KLocale>
-
#include "abstractgroupitem.h"
#include "abstractclipitem.h"
#include "kdenlivesettings.h"
#include "customtrackscene.h"
+#include <KDebug>
+
+#include <QPainter>
+#include <QStyleOptionGraphicsItem>
+
+
AbstractGroupItem::AbstractGroupItem(double fps): QGraphicsItemGroup(), m_fps(fps) {
+ setZValue(2);
setFlags(QGraphicsItem::ItemClipsToShape | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
}
return GROUPWIDGET;
}
-CustomTrackScene* AbstractGroupItem::projectScene() {
- return static_cast <CustomTrackScene*>(scene());
+int AbstractGroupItem::track() const {
+ return (int)(scenePos().y() / KdenliveSettings::trackheight());
}
+CustomTrackScene* AbstractGroupItem::projectScene() {
+ if (scene()) return static_cast <CustomTrackScene*>(scene());
+ return NULL;
+}
QPainterPath AbstractGroupItem::groupShape(QPointF offset) {
- QList<QGraphicsItem *> children = childItems();
QPainterPath path;
+ QList<QGraphicsItem *> children = childItems();
for (int i = 0; i < children.count(); i++) {
- QRectF r = children.at(i)->sceneBoundingRect();
- //kDebug()<<"// GROUP CHild: "<<r;
- //r.translate(offset);
- path.addRect(r);
+ if (children.at(i)->type() == AVWIDGET) {
+ QRectF r(children.at(i)->sceneBoundingRect());
+ r.translate(offset);
+ path.addRect(r);
+ }
}
return path;
}
}
// virtual
-void AbstractGroupItem::paint(QPainter *p, const QStyleOptionGraphicsItem *, QWidget *) {
- p->fillRect(boundingRect(), QColor(200, 100, 100, 100));
+void AbstractGroupItem::paint(QPainter *p, const QStyleOptionGraphicsItem *option, QWidget *) {
+ p->fillRect(option->exposedRect, QColor(200, 100, 100, 100));
}
//virtual
QVariant AbstractGroupItem::itemChange(GraphicsItemChange change, const QVariant &value) {
if (change == ItemPositionChange && scene()) {
// calculate new position.
+ const int trackHeight = KdenliveSettings::trackheight();
QPointF newPos = value.toPointF();
- QPainterPath sceneShape = groupShape(newPos);
- QPointF start = sceneBoundingRect().topLeft();
- QPointF sc = mapToScene(pos());
- int posx = start.x() + newPos.x(); //projectScene()->getSnapPointForPos(start.x() + sc.x(), KdenliveSettings::snaptopoints());
- //int startx = projectScene()->getSnapPointForPos(start.x(), false);
- //int startx = projectScene()->getSnapPointForPos(start.x(), false);
- kDebug() << "------------------------------------";
- kDebug() << "BRect: " << start.x() << "diff: " << newPos.x() << ",mapd: " << start.x() - sc.x();
- return newPos;
- //kDebug()<<"BR: "<<start.x()<<",NP: "<<newPos.x()<<",MAPD: "<<sc.x()<<",POS: "<<pos().x();
- if (start.x() <= 0) {
- //kDebug()<<"/// GOING UNDER 0, POS: "<<posx<<", ADJUSTED: items.at(i)->sceneBoundingRect();
- return pos();
- }
- //else posx -= startx;
- //posx = qMax(posx, 0);
- newPos.setX(posx);
- //kDebug()<<"Y POS: "<<start.y() + newPos.y()<<"SCN MP: "<<sc;
- int newTrack = (start.y() + newPos.y()) / KdenliveSettings::trackheight();
- int oldTrack = (start.y() + pos().y()) / KdenliveSettings::trackheight();
- newPos.setY((newTrack) * KdenliveSettings::trackheight() - start.y() + 1);
-
-
- //if (start.y() + newPos.y() < 1) newTrack = oldTrack;
-
- return newPos;
-
- // Only one clip is moving
-
- QList<QGraphicsItem*> items = scene()->items(sceneShape, Qt::IntersectsItemShape);
-
+ int xpos = projectScene()->getSnapPointForPos((int) newPos.x(), KdenliveSettings::snaptopoints());
+ xpos = qMax(xpos, 0);
+ newPos.setX(xpos);
+
+ QPointF start = pos();
+ //int startTrack = (start.y() + trackHeight / 2) / trackHeight;
+ int newTrack = (newPos.y()) / trackHeight;
+ //kDebug()<<"// GROUP NEW T:"<<newTrack<<",START T:"<<startTrack<<",MAX:"<<projectScene()->tracksCount() - 1;
+ newTrack = qMin(newTrack, projectScene()->tracksCount() - (int)(boundingRect().height() + 5) / trackHeight);
+ newTrack = qMax(newTrack, 0);
+
+ // Check if top item is a clip or a transition
+ int offset = 0;
+ int topTrack = -1;
QList<QGraphicsItem *> children = childItems();
for (int i = 0; i < children.count(); i++) {
- items.removeAll(children.at(i));
+ int currentTrack = (int)(children.at(i)->scenePos().y() / trackHeight);
+ if (children.at(i)->type() == AVWIDGET) {
+ if (topTrack == -1 || currentTrack <= topTrack) {
+ offset = 0;
+ topTrack = currentTrack;
+ }
+ } else if (children.at(i)->type() == TRANSITIONWIDGET) {
+ if (topTrack == -1 || currentTrack < topTrack) {
+ offset = (int)(trackHeight / 3 * 2 - 1);
+ topTrack = currentTrack;
+ }
+ }
}
+ newPos.setY((int)((newTrack) * trackHeight) + offset);
+ if (newPos == start) return start;
+ if (newPos.x() < 0) {
+ // If group goes below 0, adjust position to 0
+ return QPointF(pos().x() - start.x(), pos().y());
+ }
-
- if (!items.isEmpty()) {
- for (int i = 0; i < items.count(); i++) {
- if (items.at(i)->type() == AVWIDGET) {
- // Collision!
- //kDebug()<<"/// COLLISION WITH ITEM: "<<items.at(i)->sceneBoundingRect();
- return pos();
- QPointF otherPos = items.at(i)->pos();
- if ((int) otherPos.y() != (int) pos().y()) return pos();
- if (pos().x() < otherPos.x()) {
- // move clip just before colliding clip
- int npos = (static_cast < AbstractClipItem* >(items.at(i))->startPos()).frames(m_fps) - sceneBoundingRect().width();
- newPos.setX(npos);
+ QPainterPath shape = groupShape(newPos - pos());
+ QList<QGraphicsItem*> collindingItems = scene()->items(shape, Qt::IntersectsItemShape);
+ for (int i = 0; i < children.count(); i++) {
+ collindingItems.removeAll(children.at(i));
+ }
+ if (collindingItems.isEmpty()) return newPos;
+ else {
+ bool forwardMove = newPos.x() > start.x();
+ int offset = 0;
+ for (int i = 0; i < collindingItems.count(); i++) {
+ QGraphicsItem *collision = collindingItems.at(i);
+ if (collision->type() == AVWIDGET) {
+ // Collision
+ //kDebug()<<"// COLLISION WIT:"<<collision->sceneBoundingRect();
+ if (newPos.y() != start.y()) {
+ // Track change results in collision, restore original position
+ return start;
+ }
+ AbstractClipItem *item = static_cast <AbstractClipItem *>(collision);
+ if (forwardMove) {
+ // Moving forward, determine best pos
+ QPainterPath clipPath;
+ clipPath.addRect(item->sceneBoundingRect());
+ QPainterPath res = shape.intersected(clipPath);
+ offset = qMax(offset, (int)(res.boundingRect().width() + 0.5));
} else {
- // get pos just after colliding clip
- int npos = static_cast < AbstractClipItem* >(items.at(i))->endPos().frames(m_fps);
- newPos.setX(npos);
+ // Moving backward, determine best pos
+ QPainterPath clipPath;
+ clipPath.addRect(item->sceneBoundingRect());
+ QPainterPath res = shape.intersected(clipPath);
+ offset = qMax(offset, (int)(res.boundingRect().width() + 0.5));
}
- return newPos;
}
}
+ if (offset > 0) {
+ if (forwardMove) {
+ newPos.setX(newPos.x() - offset);
+ } else {
+ newPos.setX(newPos.x() + offset);
+ }
+ // If there is still a collision after our position adjust, restore original pos
+ collindingItems = scene()->items(groupShape(newPos - pos()), Qt::IntersectsItemShape);
+ for (int i = 0; i < children.count(); i++) {
+ collindingItems.removeAll(children.at(i));
+ }
+ for (int i = 0; i < collindingItems.count(); i++)
+ if (collindingItems.at(i)->type() == AVWIDGET) return pos();
+ }
+ return newPos;
}
- return newPos;
}
- return QGraphicsItem::itemChange(change, value);
+ return QGraphicsItemGroup::itemChange(change, value);
}