* 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 "customtrackview.h"
+
+#include <KDebug>
+
+#include <QPainter>
+#include <QStyleOptionGraphicsItem>
+#include <QDomDocument>
+#include <QMimeData>
+
AbstractGroupItem::AbstractGroupItem(double fps): QGraphicsItemGroup(), m_fps(fps) {
+ setZValue(2);
setFlags(QGraphicsItem::ItemClipsToShape | QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable);
+ setAcceptDrops(true);
}
int AbstractGroupItem::type() const {
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;
}
}
}
+/*ItemInfo AbstractGroupItem::info() const {
+ ItemInfo itemInfo;
+ itemInfo.startPos = m_startPos;
+ itemInfo.track = m_track;
+ return itemInfo;
+}*/
+
// 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 *) {
+ const double scale = option->matrix.m11();
+ QRect clipRect = option->exposedRect.toRect();
+ clipRect.adjust(0, 0, 1 / scale + 0.5, 1);
+ p->fillRect(option->exposedRect, QColor(100, 100, 200, 100));
+ p->setClipRect(clipRect);
+ QPen pen = p->pen();
+ pen.setColor(QColor(200, 90, 90));
+ pen.setStyle(Qt::DashLine);
+ p->setPen(pen);
+ p->drawRect(boundingRect());
}
//virtual
QVariant AbstractGroupItem::itemChange(GraphicsItemChange change, const QVariant &value) {
if (change == ItemPositionChange && scene()) {
// calculate new position.
- QPointF newPos = value.toPointF();
- QPainterPath sceneShape = groupShape(newPos);
+ const int trackHeight = KdenliveSettings::trackheight();
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);
-
+ QPointF newPos = value.toPointF();
+ int xpos = projectScene()->getSnapPointForPos((int)(start.x() + newPos.x() - scenePos().x() + 0.5), KdenliveSettings::snaptopoints());
- //if (start.y() + newPos.y() < 1) newTrack = oldTrack;
+ xpos = qMax(xpos, 0);
+ newPos.setX((int)(scenePos().x() + xpos - (int) start.x()));
- return newPos;
+ //int startTrack = (start.y() + trackHeight / 2) / trackHeight;
- // Only one clip is moving
+ int newTrack = (start.y() + newPos.y() - scenePos().y()) / trackHeight;
+ int currTrack = start.y() / trackHeight;
+ int currTrack2 = newPos.y() / trackHeight;
- QList<QGraphicsItem*> items = scene()->items(sceneShape, Qt::IntersectsItemShape);
+ 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)((currTrack2) * 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());
+ }*/
+ 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 (!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);
+ if (collindingItems.isEmpty()) return newPos;
+ else {
+ bool forwardMove = xpos > 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() != pos().y()) {
+ // Track change results in collision, restore original position
+ return pos();
+ }
+ 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);
+}
+
+//virtual
+void AbstractGroupItem::dropEvent(QGraphicsSceneDragDropEvent * event) {
+ QString effects = QString(event->mimeData()->data("kdenlive/effectslist"));
+ QDomDocument doc;
+ doc.setContent(effects, true);
+ QDomElement e = doc.documentElement();
+ CustomTrackView *view = (CustomTrackView *) scene()->views()[0];
+ if (view) view->slotAddGroupEffect(e, this);
}
+//virtual
+void AbstractGroupItem::dragEnterEvent(QGraphicsSceneDragDropEvent *event) {
+ event->setAccepted(event->mimeData()->hasFormat("kdenlive/effectslist"));
+}
+
+void AbstractGroupItem::dragLeaveEvent(QGraphicsSceneDragDropEvent *event) {
+ Q_UNUSED(event);
+}