Fixed pen strokes not being loaded in right position

- Modified UBvgSubsetAdaptor to correctly save and load strokes, so the
transform matrices that were saved are now loaded correctly.

- Added handling of mousePress / Move / Release events to
UBGraphicsStrokesGroup, so that the transform matrix is calculated and
stored after moving a pen stroke directly (by clicking on it, and not on
its frame). Note: this duplicates quite a bit of code that is in
UBGraphicsDelegateFrame. It may be best to go back and modify both
classes so that the same functions can be called when moving a stroke.
preferencesAboutTextFull
Craig Watson 9 years ago
parent 3171da0d39
commit 0879179c73
  1. 40
      src/adaptors/UBSvgSubsetAdaptor.cpp
  2. 5
      src/board/UBBoardView.cpp
  3. 123
      src/domain/UBGraphicsStrokesGroup.cpp
  4. 28
      src/domain/UBGraphicsStrokesGroup.h

@ -498,6 +498,18 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene()
{ {
mGroupLightBackgroundColor.setNamedColor(ubFillOnLightBackground.toString()); mGroupLightBackgroundColor.setNamedColor(ubFillOnLightBackground.toString());
} }
QStringRef ubUuid = mXmlReader.attributes().value(mNamespaceUri, "uuid");
if (!ubUuid.isNull())
strokesGroup->setUuid(ubUuid.toString());
else
strokesGroup->setUuid(QUuid::createUuid());
QString uuid_stripped = strokesGroup->uuid().toString().replace("}","").replace("{","");
if (!mStrokesList.contains(uuid_stripped))
mStrokesList.insert(uuid_stripped, strokesGroup);
} }
else if (mXmlReader.name() == "polygon" || mXmlReader.name() == "line") else if (mXmlReader.name() == "polygon" || mXmlReader.name() == "line")
{ {
@ -524,13 +536,15 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene()
if(!mStrokesList.contains(parentId)){ if(!mStrokesList.contains(parentId)){
group = new UBGraphicsStrokesGroup(); group = new UBGraphicsStrokesGroup();
mStrokesList.insert(parentId,group); mStrokesList.insert(parentId,group);
currentStroke = new UBGraphicsStroke();
group->setTransform(polygonItem->transform()); group->setTransform(polygonItem->transform());
UBGraphicsItem::assignZValue(group, polygonItem->zValue()); UBGraphicsItem::assignZValue(group, polygonItem->zValue());
} }
else else
group = mStrokesList.value(parentId); group = mStrokesList.value(parentId);
if (!currentStroke)
currentStroke = new UBGraphicsStroke();
if(polygonItem->transform().isIdentity()) if(polygonItem->transform().isIdentity())
polygonItem->setTransform(group->transform()); polygonItem->setTransform(group->transform());
@ -546,23 +560,33 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene()
{ {
QList<UBGraphicsPolygonItem*> polygonItems = polygonItemsFromPolylineSvg(mScene->isDarkBackground() ? Qt::white : Qt::black); QList<UBGraphicsPolygonItem*> polygonItems = polygonItemsFromPolylineSvg(mScene->isDarkBackground() ? Qt::white : Qt::black);
QString parentId = QUuid::createUuid().toString(); QString parentId = mXmlReader.attributes().value(mNamespaceUri, "parent").toString();
qDebug() << "parentID = " << parentId;
if(parentId.isEmpty() && strokesGroup)
parentId = strokesGroup->uuid().toString();
if(parentId.isEmpty())
parentId = QUuid::createUuid().toString();
foreach(UBGraphicsPolygonItem* polygonItem, polygonItems) foreach(UBGraphicsPolygonItem* polygonItem, polygonItems)
{ {
polygonItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Graphic)); polygonItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Graphic));
UBGraphicsStrokesGroup* group; UBGraphicsStrokesGroup* group;
if(!mStrokesList.contains(parentId)){ if(!mStrokesList.contains(parentId)){
group = new UBGraphicsStrokesGroup(); group = new UBGraphicsStrokesGroup();
mStrokesList.insert(parentId,group); mStrokesList.insert(parentId,group);
currentStroke = new UBGraphicsStroke();
group->setTransform(polygonItem->transform()); group->setTransform(polygonItem->transform());
UBGraphicsItem::assignZValue(group, polygonItem->zValue()); UBGraphicsItem::assignZValue(group, polygonItem->zValue());
} }
else else
group = mStrokesList.value(parentId); group = mStrokesList.value(parentId);
if (!currentStroke)
currentStroke = new UBGraphicsStroke();
if(polygonItem->transform().isIdentity()) if(polygonItem->transform().isIdentity())
polygonItem->setTransform(group->transform()); polygonItem->setTransform(group->transform());
@ -861,6 +885,8 @@ UBGraphicsScene* UBSvgSubsetAdaptor::UBSvgSubsetReader::loadScene()
mGroupHasInfo = false; mGroupHasInfo = false;
mGroupDarkBackgroundColor = QColor(); mGroupDarkBackgroundColor = QColor();
mGroupLightBackgroundColor = QColor(); mGroupLightBackgroundColor = QColor();
strokesGroup = NULL;
currentStroke = NULL;
} }
} }
} }
@ -1127,6 +1153,9 @@ bool UBSvgSubsetAdaptor::UBSvgSubsetWriter::persistScene(int pageIndex)
, "fill-on-dark-background", colorOnDarkBackground.name()); , "fill-on-dark-background", colorOnDarkBackground.name());
mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri
, "fill-on-light-background", colorOnLightBackground.name()); , "fill-on-light-background", colorOnLightBackground.name());
mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "uuid", UBStringUtils::toCanonicalUuid(sg->uuid()));
qDebug() << "Attributes written"; qDebug() << "Attributes written";
groupHoldsInfo = true; groupHoldsInfo = true;
@ -1442,6 +1471,11 @@ void UBSvgSubsetAdaptor::UBSvgSubsetWriter::strokeToSvgPolyline(UBGraphicsStroke
, "fill-on-light-background", firstPolygonItem->colorOnLightBackground().name()); , "fill-on-light-background", firstPolygonItem->colorOnLightBackground().name());
} }
mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "uuid", UBStringUtils::toCanonicalUuid(firstPolygonItem->uuid()));
if (firstPolygonItem->parentItem()) {
mXmlWriter.writeAttribute(UBSettings::uniboardDocumentNamespaceUri, "parent", UBStringUtils::toCanonicalUuid(UBGraphicsItem::getOwnUuid(firstPolygonItem->strokesGroup())));
}
mXmlWriter.writeEndElement(); mXmlWriter.writeEndElement();
} }
} }

@ -561,7 +561,7 @@ Here we determines cases when items should to get mouse press event at pressing
break; break;
case UBGraphicsItemType::StrokeItemType: case UBGraphicsItemType::StrokeItemType:
if (currentTool == UBStylusTool::Play) if (currentTool == UBStylusTool::Play || currentTool == UBStylusTool::Selector)
return true; return true;
break; break;
// Groups shouldn't reacts on any presses and moves for Play tool. // Groups shouldn't reacts on any presses and moves for Play tool.
@ -664,7 +664,7 @@ bool UBBoardView::itemShouldBeMoved(QGraphicsItem *item)
return false; return false;
case UBGraphicsMediaItem::Type: case UBGraphicsMediaItem::Type:
case UBGraphicsStrokesGroup::Type: case UBGraphicsStrokesGroup::Type:
return true; return false;
case UBGraphicsTextItem::Type: case UBGraphicsTextItem::Type:
return !item->isSelected(); return !item->isSelected();
} }
@ -1254,6 +1254,7 @@ void UBBoardView::mouseReleaseEvent (QMouseEvent *event)
if (isUBItem(movingItem) && if (isUBItem(movingItem) &&
DelegateButton::Type != movingItem->type() && DelegateButton::Type != movingItem->type() &&
UBGraphicsDelegateFrame::Type != movingItem->type() && UBGraphicsDelegateFrame::Type != movingItem->type() &&
UBGraphicsStrokesGroup::Type != movingItem->type() &&
UBGraphicsCache::Type != movingItem->type() && UBGraphicsCache::Type != movingItem->type() &&
QGraphicsWebView::Type != movingItem->type() && // for W3C widgets as Tools. QGraphicsWebView::Type != movingItem->type() && // for W3C widgets as Tools.
!(!isMultipleSelectionEnabled() && movingItem->parentItem() && UBGraphicsWidgetItem::Type == movingItem->type() && UBGraphicsGroupContainerItem::Type == movingItem->parentItem()->type())) !(!isMultipleSelectionEnabled() && movingItem->parentItem() && UBGraphicsWidgetItem::Type == movingItem->type() && UBGraphicsGroupContainerItem::Type == movingItem->parentItem()->type()))

@ -111,30 +111,44 @@ QColor UBGraphicsStrokesGroup::color(colorType pColorType) const
void UBGraphicsStrokesGroup::mousePressEvent(QGraphicsSceneMouseEvent *event) void UBGraphicsStrokesGroup::mousePressEvent(QGraphicsSceneMouseEvent *event)
{ {
if (Delegate()->mousePressEvent(event)) Delegate()->startUndoStep();
{
//NOOP mStartingPoint = event->scenePos();
}
else initializeTransform();
{
// QGraphicsItemGroup::mousePressEvent(event); mTranslateX = 0;
} mTranslateY = 0;
mAngleOffset = 0;
mInitialTransform = buildTransform();
event->accept();
} }
void UBGraphicsStrokesGroup::mouseMoveEvent(QGraphicsSceneMouseEvent *event) void UBGraphicsStrokesGroup::mouseMoveEvent(QGraphicsSceneMouseEvent *event)
{ {
if (Delegate()->mouseMoveEvent(event)) QLineF move = QLineF(mStartingPoint, event->scenePos());
{
// NOOP; mTranslateX = move.dx();
} mTranslateY = move.dy();
else //Delegate()->frame()->moveLinkedItems(move);
{
QGraphicsItemGroup::mouseMoveEvent(event); setTransform(buildTransform());
}
event->accept();
} }
void UBGraphicsStrokesGroup::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) void UBGraphicsStrokesGroup::mouseReleaseEvent(QGraphicsSceneMouseEvent *event)
{ {
Delegate()->commitUndoStep();
mTotalTranslateX += mTranslateX;
mTotalTranslateY += mTranslateY;
event->accept();
Delegate()->mouseReleaseEvent(event); Delegate()->mouseReleaseEvent(event);
QGraphicsItemGroup::mouseReleaseEvent(event); QGraphicsItemGroup::mouseReleaseEvent(event);
} }
@ -226,3 +240,80 @@ QPainterPath UBGraphicsStrokesGroup::shape() const
return path; return path;
} }
void UBGraphicsStrokesGroup::initializeTransform()
{
QTransform itemTransform = sceneTransform();
QRectF itemRect = boundingRect();
QPointF topLeft = itemTransform.map(itemRect.topLeft());
QPointF topRight = itemTransform.map(itemRect.topRight());
QPointF bottomLeft = itemTransform.map(itemRect.bottomLeft());
qreal horizontalFlip = (topLeft.x() > topRight.x()) ? -1 : 1;
mMirrorX = horizontalFlip < 0 ;
if(horizontalFlip < 0){
// why this is because of the way of calculating the translations that checks which side is the most is the
// nearest instead of checking which one is the left side.
QPointF tmp = topLeft;
topLeft = topRight;
topRight = tmp;
// because of the calculation of the height is done by lenght and not deltaY
bottomLeft = itemTransform.map(itemRect.bottomRight());
}
qreal verticalFlip = (bottomLeft.y() < topLeft.y()) ? -1 : 1;
// not sure that is usefull
mMirrorY = verticalFlip < 0;
if(verticalFlip < 0 && !mMirrorX){
topLeft = itemTransform.map(itemRect.bottomLeft());
topRight = itemTransform.map(itemRect.bottomRight());
bottomLeft = itemTransform.map(itemRect.topLeft());
}
QLineF topLine(topLeft, topRight);
QLineF leftLine(topLeft, bottomLeft);
qreal width = topLine.length();
qreal height = leftLine.length();
mAngle = topLine.angle();
// the fact the the length is used we loose the horizontalFlip information
// a better way to do this is using DeltaX that preserve the direction information.
mTotalScaleX = (width / itemRect.width()) * horizontalFlip;
mTotalScaleY = height / itemRect.height() * verticalFlip;
QTransform tr;
QPointF center = boundingRect().center();
tr.translate(center.x() * mTotalScaleX, center.y() * mTotalScaleY);
tr.rotate(-mAngle);
tr.translate(-center.x() * mTotalScaleX, -center.y() * mTotalScaleY);
tr.scale(mTotalScaleX, mTotalScaleY);
mTotalTranslateX = transform().dx() - tr.dx();
mTotalTranslateY = transform().dy() - tr.dy();
}
QTransform UBGraphicsStrokesGroup::buildTransform()
{
QTransform tr;
QPointF center = boundingRect().center();
// Translate
tr.translate(mTotalTranslateX + mTranslateX, mTotalTranslateY + mTranslateY);
// Set angle
tr.translate(center.x() * mTotalScaleX, center.y() * mTotalScaleY);
tr.rotate(-mAngle);
tr.translate(-center.x() * mTotalScaleX, -center.y() * mTotalScaleY);
// Scale
tr.scale(mTotalScaleX, mTotalScaleY );
return tr;
}

@ -66,6 +66,34 @@ protected:
virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); virtual void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value); virtual QVariant itemChange(GraphicsItemChange change, const QVariant &value);
private:
qreal mTranslateX;
qreal mTranslateY;
qreal mTotalTranslateX;
qreal mTotalTranslateY;
qreal mAngle;
qreal mAngleOffset;
qreal mTotalScaleX;
qreal mTotalScaleY;
qreal mScaleX;
qreal mScaleY;
bool mFlippedX;
bool mFlippedY;
bool mMirrorX;
bool mMirrorY;
bool mResizing;
bool mMirroredXAtStart;
bool mMirroredYAtStart;
QPointF mStartingPoint;
QTransform mInitialTransform;
QTransform buildTransform ();
void initializeTransform ();
}; };
#endif // UBGRAPHICSSTROKESGROUP_H #endif // UBGRAPHICSSTROKESGROUP_H

Loading…
Cancel
Save