fix use after free of movingItem

preferencesAboutTextFull
Victor "multun" Collod 4 years ago
parent 6edebf9632
commit fb25c17e4e
  1. 149
      src/board/UBBoardView.cpp
  2. 30
      src/board/UBBoardView.h

@ -95,6 +95,7 @@ UBBoardView::UBBoardView (UBBoardController* pController, QWidget* pParent, bool
, mLongPressInterval(1000)
, mIsDragInProgress(false)
, mMultipleSelectionIsEnabled(false)
, _movingItem(nullptr)
, bIsControl(isControl)
, bIsDesktop(isDesktop)
{
@ -119,6 +120,7 @@ UBBoardView::UBBoardView (UBBoardController* pController, int pStartLayer, int p
, mLongPressInterval(1000)
, mIsDragInProgress(false)
, mMultipleSelectionIsEnabled(false)
, _movingItem(nullptr)
, bIsControl(isControl)
, bIsDesktop(isDesktop)
{
@ -178,7 +180,7 @@ void UBBoardView::init ()
unsetCursor();
movingItem = NULL;
setMovingItem(NULL);
mWidgetMoved = false;
}
@ -482,7 +484,7 @@ void UBBoardView::handleItemsSelection(QGraphicsItem *item)
if (item)
{
// item has group as first parent - it is any item or UBGraphicsStrokesGroup.
if(item->parentItem() && UBGraphicsGroupContainerItem::Type == movingItem->parentItem()->type())
if(item->parentItem() && UBGraphicsGroupContainerItem::Type == getMovingItem()->parentItem()->type())
return;
// delegate buttons shouldn't selected
@ -578,7 +580,7 @@ Here we determines cases when items should to get mouse press event at pressing
case UBGraphicsGroupContainerItem::Type:
if(currentTool == UBStylusTool::Play)
{
movingItem = NULL;
setMovingItem(NULL);
return true;
}
return false;
@ -648,10 +650,10 @@ bool UBBoardView::itemShouldBeMoved(QGraphicsItem *item)
if (!(mMouseButtonIsPressed || mTabletStylusIsPressed))
return false;
if (movingItem->data(UBGraphicsItemData::ItemLocked).toBool())
if (getMovingItem()->data(UBGraphicsItemData::ItemLocked).toBool())
return false;
if (movingItem->parentItem() && UBGraphicsGroupContainerItem::Type == movingItem->parentItem()->type() && !movingItem->isSelected() && movingItem->parentItem()->isSelected())
if (getMovingItem()->parentItem() && UBGraphicsGroupContainerItem::Type == getMovingItem()->parentItem()->type() && !getMovingItem()->isSelected() && getMovingItem()->parentItem()->isSelected())
return false;
UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController()->stylusTool();
@ -759,13 +761,13 @@ void UBBoardView::handleItemMousePress(QMouseEvent *event)
// Determining item who will take mouse press event
//all other items will be deselected and if all item will be deselected, then
// wrong item can catch mouse press. because selected items placed on the top
movingItem = determineItemToPress(movingItem);
handleItemsSelection(movingItem);
setMovingItem(determineItemToPress(getMovingItem()));
handleItemsSelection(getMovingItem());
if (isMultipleSelectionEnabled())
return;
if (itemShouldReceiveMousePressEvent(movingItem)){
if (itemShouldReceiveMousePressEvent(getMovingItem())){
QGraphicsView::mousePressEvent (event);
QGraphicsItem* item = determineItemToPress(scene()->itemAt(this->mapToScene(event->localPos().toPoint()), transform()));
@ -780,17 +782,17 @@ void UBBoardView::handleItemMousePress(QMouseEvent *event)
if ((*it)->pos().x() < 0 || (*it)->pos().y() < 0)
(*it)->setPos(0,item->boundingRect().size().height());
}
movingItem = item;
setMovingItem(item);
}
else
{
if (movingItem)
if (getMovingItem())
{
UBGraphicsItem *graphicsItem = dynamic_cast<UBGraphicsItem*>(movingItem);
UBGraphicsItem *graphicsItem = dynamic_cast<UBGraphicsItem*>(getMovingItem());
if (graphicsItem)
graphicsItem->Delegate()->startUndoStep();
movingItem->clearFocus();
getMovingItem()->clearFocus();
}
if (suspendedMousePressEvent)
@ -799,7 +801,7 @@ void UBBoardView::handleItemMousePress(QMouseEvent *event)
suspendedMousePressEvent = NULL;
}
if (itemShouldReceiveSuspendedMousePressEvent(movingItem))
if (itemShouldReceiveSuspendedMousePressEvent(getMovingItem()))
{
suspendedMousePressEvent = new QMouseEvent(event->type(), event->pos(), event->button(), event->buttons(), event->modifiers());
}
@ -809,14 +811,14 @@ void UBBoardView::handleItemMousePress(QMouseEvent *event)
void UBBoardView::handleItemMouseMove(QMouseEvent *event)
{
// determine item to move (maybee we need to move group of item or his parent.
movingItem = determineItemToMove(movingItem);
setMovingItem(determineItemToMove(getMovingItem()));
// items should be moved not every mouse move.
if (movingItem && itemShouldBeMoved(movingItem) && (mMouseButtonIsPressed || mTabletStylusIsPressed))
if (getMovingItem() && itemShouldBeMoved(getMovingItem()) && (mMouseButtonIsPressed || mTabletStylusIsPressed))
{
QPointF scenePos = mapToScene(event->pos());
QPointF newPos = movingItem->pos() + scenePos - mLastPressedMousePos;
movingItem->setPos(newPos);
QPointF newPos = getMovingItem()->pos() + scenePos - mLastPressedMousePos;
getMovingItem()->setPos(newPos);
mLastPressedMousePos = scenePos;
mWidgetMoved = true;
event->accept();
@ -826,21 +828,21 @@ void UBBoardView::handleItemMouseMove(QMouseEvent *event)
QPointF posBeforeMove;
QPointF posAfterMove;
if (movingItem)
posBeforeMove = movingItem->pos();
if (getMovingItem())
posBeforeMove = getMovingItem()->pos();
QGraphicsView::mouseMoveEvent (event);
if (movingItem)
posAfterMove = movingItem->pos();
if (getMovingItem())
posAfterMove = getMovingItem()->pos();
mWidgetMoved = ((posAfterMove-posBeforeMove).manhattanLength() != 0);
// a cludge for terminate moving of w3c widgets.
// in some cases w3c widgets catches mouse move and doesn't sends that events to web page,
// at simple - in google map widget - mouse move events doesn't comes to web page from rectangle of wearch bar on bottom right corner of widget.
if (movingItem && mWidgetMoved && UBGraphicsW3CWidgetItem::Type == movingItem->type())
movingItem->setPos(posBeforeMove);
if (getMovingItem() && mWidgetMoved && UBGraphicsW3CWidgetItem::Type == getMovingItem()->type())
getMovingItem()->setPos(posBeforeMove);
}
}
@ -992,7 +994,7 @@ void UBBoardView::mousePressEvent (QMouseEvent *event)
}
mMouseDownPos = event->pos ();
movingItem = scene()->itemAt(this->mapToScene(event->localPos().toPoint()), QTransform());
setMovingItem(scene()->itemAt(this->mapToScene(event->localPos().toPoint()), QTransform()));
if (event->button () == Qt::LeftButton && isInteractive())
{
@ -1024,11 +1026,11 @@ void UBBoardView::mousePressEvent (QMouseEvent *event)
return;
}
if (scene()->backgroundObject() == movingItem)
movingItem = NULL;
if (scene()->backgroundObject() == getMovingItem())
setMovingItem(NULL);
connect(&mLongPressTimer, SIGNAL(timeout()), this, SLOT(longPressEvent()));
if (!movingItem && !mController->cacheIsVisible())
if (!getMovingItem() && !mController->cacheIsVisible())
mLongPressTimer.start();
handleItemMousePress(event);
@ -1143,7 +1145,7 @@ void UBBoardView::mouseMoveEvent (QMouseEvent *event)
bool rubberMove = (currentTool != (UBStylusTool::Play))
&& (mMouseButtonIsPressed || mTabletStylusIsPressed)
&& !movingItem;
&& !getMovingItem();
if (rubberMove) {
QRect bandRect(mMouseDownPos, event->pos());
@ -1229,6 +1231,11 @@ void UBBoardView::mouseMoveEvent (QMouseEvent *event)
}
void UBBoardView::movingItemDestroyed(QObject*)
{
setMovingItem(nullptr);
}
void UBBoardView::mouseReleaseEvent (QMouseEvent *event)
{
UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController ()->stylusTool ();
@ -1245,60 +1252,60 @@ void UBBoardView::mouseReleaseEvent (QMouseEvent *event)
return;
}
UBGraphicsItem *graphicsItem = dynamic_cast<UBGraphicsItem*>(movingItem);
UBGraphicsItem *graphicsItem = dynamic_cast<UBGraphicsItem*>(getMovingItem());
if (graphicsItem)
graphicsItem->Delegate()->commitUndoStep();
bool bReleaseIsNeed = true;
if (movingItem != determineItemToPress(scene()->itemAt(this->mapToScene(event->localPos().toPoint()), QTransform())))
if (getMovingItem() != determineItemToPress(scene()->itemAt(this->mapToScene(event->localPos().toPoint()), QTransform())))
{
movingItem = NULL;
setMovingItem(nullptr);
bReleaseIsNeed = false;
}
if (mWidgetMoved)
{
mWidgetMoved = false;
movingItem = NULL;
setMovingItem(nullptr);
}
else
if (movingItem && (!isCppTool(movingItem) || UBGraphicsCurtainItem::Type == movingItem->type()))
if (getMovingItem() && (!isCppTool(getMovingItem()) || UBGraphicsCurtainItem::Type == getMovingItem()->type()))
{
if (suspendedMousePressEvent)
{
QGraphicsView::mousePressEvent(suspendedMousePressEvent); // suspendedMousePressEvent is deleted by old Qt event loop
movingItem = NULL;
setMovingItem(NULL);
delete suspendedMousePressEvent;
suspendedMousePressEvent = NULL;
bReleaseIsNeed = true;
}
else
{
if (isUBItem(movingItem) &&
DelegateButton::Type != movingItem->type() &&
UBGraphicsDelegateFrame::Type != movingItem->type() &&
UBGraphicsCache::Type != movingItem->type() &&
QGraphicsWebView::Type != movingItem->type() && // for W3C widgets as Tools.
!(!isMultipleSelectionEnabled() && movingItem->parentItem() && UBGraphicsWidgetItem::Type == movingItem->type() && UBGraphicsGroupContainerItem::Type == movingItem->parentItem()->type()))
if (isUBItem(getMovingItem()) &&
DelegateButton::Type != getMovingItem()->type() &&
UBGraphicsDelegateFrame::Type != getMovingItem()->type() &&
UBGraphicsCache::Type != getMovingItem()->type() &&
QGraphicsWebView::Type != getMovingItem()->type() && // for W3C widgets as Tools.
!(!isMultipleSelectionEnabled() && getMovingItem()->parentItem() && UBGraphicsWidgetItem::Type == getMovingItem()->type() && UBGraphicsGroupContainerItem::Type == getMovingItem()->parentItem()->type()))
{
bReleaseIsNeed = false;
if (movingItem->isSelected() && isMultipleSelectionEnabled())
movingItem->setSelected(false);
if (getMovingItem()->isSelected() && isMultipleSelectionEnabled())
getMovingItem()->setSelected(false);
else
if (movingItem->parentItem() && movingItem->parentItem()->isSelected() && isMultipleSelectionEnabled())
movingItem->parentItem()->setSelected(false);
if (getMovingItem()->parentItem() && getMovingItem()->parentItem()->isSelected() && isMultipleSelectionEnabled())
getMovingItem()->parentItem()->setSelected(false);
else
{
if (movingItem->isSelected())
if (getMovingItem()->isSelected())
bReleaseIsNeed = true;
UBGraphicsTextItem* textItem = dynamic_cast<UBGraphicsTextItem*>(movingItem);
UBGraphicsMediaItem* movieItem = dynamic_cast<UBGraphicsMediaItem*>(movingItem);
UBGraphicsTextItem* textItem = dynamic_cast<UBGraphicsTextItem*>(getMovingItem());
UBGraphicsMediaItem* movieItem = dynamic_cast<UBGraphicsMediaItem*>(getMovingItem());
if(textItem)
textItem->setSelected(true);
else if(movieItem)
movieItem->setSelected(true);
else
movingItem->setSelected(true);
getMovingItem()->setSelected(true);
}
}
@ -1315,20 +1322,20 @@ void UBBoardView::mouseReleaseEvent (QMouseEvent *event)
else if (currentTool == UBStylusTool::Text)
{
bool bReleaseIsNeed = true;
if (movingItem != determineItemToPress(scene()->itemAt(this->mapToScene(event->localPos().toPoint()), QTransform())))
if (getMovingItem() != determineItemToPress(scene()->itemAt(this->mapToScene(event->localPos().toPoint()), QTransform())))
{
movingItem = NULL;
setMovingItem(NULL);
bReleaseIsNeed = false;
}
UBGraphicsItem *graphicsItem = dynamic_cast<UBGraphicsItem*>(movingItem);
UBGraphicsItem *graphicsItem = dynamic_cast<UBGraphicsItem*>(getMovingItem());
if (graphicsItem)
graphicsItem->Delegate()->commitUndoStep();
if (mWidgetMoved)
{
mWidgetMoved = false;
movingItem = NULL;
setMovingItem(NULL);
if (scene () && mRubberBand && mIsCreatingTextZone) {
QRect rubberRect = mRubberBand->geometry ();
@ -1343,37 +1350,37 @@ void UBBoardView::mouseReleaseEvent (QMouseEvent *event)
textItem->setFocus();
}
}
else if (movingItem && (!isCppTool(movingItem) || UBGraphicsCurtainItem::Type == movingItem->type()))
else if (getMovingItem() && (!isCppTool(getMovingItem()) || UBGraphicsCurtainItem::Type == getMovingItem()->type()))
{
if (suspendedMousePressEvent)
{
QGraphicsView::mousePressEvent(suspendedMousePressEvent); // suspendedMousePressEvent is deleted by old Qt event loop
movingItem = NULL;
setMovingItem(NULL);
delete suspendedMousePressEvent;
suspendedMousePressEvent = NULL;
bReleaseIsNeed = true;
}
else{
if (isUBItem(movingItem) &&
DelegateButton::Type != movingItem->type() &&
QGraphicsSvgItem::Type != movingItem->type() &&
UBGraphicsDelegateFrame::Type != movingItem->type() &&
UBGraphicsCache::Type != movingItem->type() &&
QGraphicsWebView::Type != movingItem->type() && // for W3C widgets as Tools.
!(!isMultipleSelectionEnabled() && movingItem->parentItem() && UBGraphicsWidgetItem::Type == movingItem->type() && UBGraphicsGroupContainerItem::Type == movingItem->parentItem()->type()))
if (isUBItem(getMovingItem()) &&
DelegateButton::Type != getMovingItem()->type() &&
QGraphicsSvgItem::Type != getMovingItem()->type() &&
UBGraphicsDelegateFrame::Type != getMovingItem()->type() &&
UBGraphicsCache::Type != getMovingItem()->type() &&
QGraphicsWebView::Type != getMovingItem()->type() && // for W3C widgets as Tools.
!(!isMultipleSelectionEnabled() && getMovingItem()->parentItem() && UBGraphicsWidgetItem::Type == getMovingItem()->type() && UBGraphicsGroupContainerItem::Type == getMovingItem()->parentItem()->type()))
{
bReleaseIsNeed = false;
if (movingItem->isSelected() && isMultipleSelectionEnabled())
movingItem->setSelected(false);
if (getMovingItem()->isSelected() && isMultipleSelectionEnabled())
getMovingItem()->setSelected(false);
else
if (movingItem->parentItem() && movingItem->parentItem()->isSelected() && isMultipleSelectionEnabled())
movingItem->parentItem()->setSelected(false);
if (getMovingItem()->parentItem() && getMovingItem()->parentItem()->isSelected() && isMultipleSelectionEnabled())
getMovingItem()->parentItem()->setSelected(false);
else
{
if (movingItem->isSelected())
if (getMovingItem()->isSelected())
bReleaseIsNeed = true;
movingItem->setSelected(true);
getMovingItem()->setSelected(true);
}
}
@ -1394,14 +1401,14 @@ void UBBoardView::mouseReleaseEvent (QMouseEvent *event)
}
if (mWidgetMoved) {
movingItem->setSelected(false);
movingItem = NULL;
getMovingItem()->setSelected(false);
setMovingItem(NULL);
mWidgetMoved = false;
}
else {
if (suspendedMousePressEvent) {
QGraphicsView::mousePressEvent(suspendedMousePressEvent); // suspendedMousePressEvent is deleted by old Qt event loop
movingItem = NULL;
setMovingItem(NULL);
delete suspendedMousePressEvent;
suspendedMousePressEvent = NULL;
}
@ -1453,7 +1460,7 @@ void UBBoardView::mouseReleaseEvent (QMouseEvent *event)
mMouseButtonIsPressed = false;
mPendingStylusReleaseEvent = false;
mTabletStylusIsPressed = false;
movingItem = NULL;
setMovingItem(NULL);
mLongPressTimer.stop();
emit mouseReleased();

@ -156,7 +156,32 @@ private:
bool mWidgetMoved;
QPointF mLastPressedMousePos;
QGraphicsItem *movingItem;
/* when an item is moved around, the tracking must stop if the object is deleted */
QGraphicsItem *_movingItem;
QGraphicsItem *getMovingItem() {
return _movingItem;
}
void setMovingItem(QGraphicsItem *item) {
// if the current moving item is a qobject, it MUST be disconnected
if (_movingItem) {
QObject *moving_item_obj = dynamic_cast<QObject*>(_movingItem);
if (moving_item_obj != nullptr)
disconnect(moving_item_obj, &QObject::destroyed, this, &UBBoardView::movingItemDestroyed);
}
// attach the new moving item if relevant
if (item) {
QObject *item_obj = dynamic_cast<QObject*>(item);
if (item_obj != nullptr)
connect(item_obj, &QObject::destroyed, this, &UBBoardView::movingItemDestroyed);
}
_movingItem = item;
}
QMouseEvent *suspendedMousePressEvent;
bool moveRubberBand;
@ -177,11 +202,10 @@ private:
static bool hasSelectedParents(QGraphicsItem * item);
private slots:
void settingChanged(QVariant newValue);
void movingItemDestroyed(QObject* item = nullptr);
public slots:
void virtualKeyboardActivated(bool b);
void longPressEvent();

Loading…
Cancel
Save