/* * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ #include "UBGraphicsScene.h" #include #include #include #include #include "frameworks/UBGeometryUtils.h" #include "frameworks/UBPlatformUtils.h" #include "core/UBApplication.h" #include "core/UBSettings.h" #include "core/UBApplicationController.h" #include "core/UBDisplayManager.h" #include "core/UBPersistenceManager.h" #include "gui/UBMagnifer.h" #include "tools/UBGraphicsRuler.h" #include "tools/UBGraphicsProtractor.h" #include "tools/UBGraphicsCompass.h" #include "tools/UBGraphicsTriangle.h" #include "tools/UBGraphicsCurtainItem.h" #include "tools/UBGraphicsCache.h" #include "document/UBDocumentProxy.h" #include "board/UBBoardController.h" #include "board/UBDrawingController.h" #include "UBGraphicsItemUndoCommand.h" #include "UBGraphicsTextItemUndoCommand.h" #include "UBGraphicsProxyWidget.h" #include "UBGraphicsPixmapItem.h" #include "UBGraphicsSvgItem.h" #include "UBGraphicsPolygonItem.h" #include "UBGraphicsVideoItem.h" #include "UBGraphicsAudioItem.h" #include "UBGraphicsWidgetItem.h" #include "UBGraphicsPDFItem.h" #include "UBGraphicsTextItem.h" #include "UBAppleWidget.h" #include "UBW3CWidget.h" #include "UBGraphicsStroke.h" #include "core/memcheck.h" #include "qtlogger.h" qreal UBGraphicsScene::backgroundLayerStart = -20000000.0; qreal UBGraphicsScene::objectLayerStart = -10000000.0; qreal UBGraphicsScene::drawingLayerStart = 0.0; qreal UBGraphicsScene::toolLayerStart = 10000000.0; qreal UBGraphicsScene::toolOffsetRuler = 100; qreal UBGraphicsScene::toolOffsetProtractor = 100; qreal UBGraphicsScene::toolOffsetTriangle = 100; qreal UBGraphicsScene::toolOffsetCompass = 100; qreal UBGraphicsScene::toolOffsetEraser = 200; qreal UBGraphicsScene::toolOffsetCurtain = 1000; qreal UBGraphicsScene::toolOffsetPointer = 1100; qreal UBGraphicsScene::toolOffsetCache = 1000;//Didier please define offset you want UBGraphicsScene::UBGraphicsScene(UBDocumentProxy* parent) : UBCoreGraphicsScene(parent) , mEraser(0) , mPointer(0) , mDocument(parent) , mDarkBackground(false) , mCrossedBackground(false) , mIsModified(true) , mBackgroundObject(0) , mPreviousWidth(0) , mInputDeviceIsPressed(false) , mArcPolygonItem(0) , mRenderingContext(Screen) , mCurrentStroke(0) , mShouldUseOMP(true) , mItemCount(0) , magniferControlViewWidget(0) , magniferDisplayViewWidget(0) { #ifdef __ppc__ mShouldUseOMP = false; #elif defined(Q_WS_MAC) mShouldUseOMP = QSysInfo::MacintoshVersion >= QSysInfo::MV_10_5; #endif setDocument(parent); mDrawingZIndex = drawingLayerStart; mObjectZIndex = objectLayerStart; mEraser = new QGraphicsEllipseItem(); // mem : owned and destroyed by the scene mEraser->setRect(QRect(0, 0, 0, 0)); mEraser->setVisible(false); mEraser->setZValue(/*toolLayerStart + toolOffsetEraser*/2); mEraser->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); mTools << mEraser; addItem(mEraser); mPointer = new QGraphicsEllipseItem(); // mem : owned and destroyed by the scene mPointer->setRect(QRect(0, 0, 20, 20)); mPointer->setVisible(false); mPointer->setPen(Qt::NoPen); mPointer->setBrush(QBrush(QColor(255, 0, 0, 186))); mPointer->setZValue( /*toolLayerStart + toolOffsetPointer*/ 2); mPointer->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); mTools << mPointer; addItem(mPointer); if (UBApplication::applicationController) { setViewState(SceneViewState(1, UBApplication::applicationController->initialHScroll(), UBApplication::applicationController->initialVScroll())); } connect(this, SIGNAL(selectionChanged()), this, SLOT(selectionChangedProcessing())); QtLogger::logger().start("/home/ilia/Documents/tmp/2/log.txt"); QtLogger::logger().finish(); } UBGraphicsScene::~UBGraphicsScene() { DisposeMagnifierQWidgets(); if (mCurrentStroke) if (mCurrentStroke->polygons().empty()) delete mCurrentStroke; } void UBGraphicsScene::selectionChangedProcessing() { QtLogger::logger().start("/home/ilia/Documents/tmp/2/log.txt"); QtLogger::logger() << "selection processing started\n" << endl; if (selectedItems().count()) UBApplication::showMessage("ZValue is " + QString::number(selectedItems().first()->zValue(), 'f')); QList allItemsList = items(); QtLogger::logger() << "=====all items searching...======" << endl; for( int i = 0; i < allItemsList.size(); i++ ) { QGraphicsItem *nextItem = allItemsList.at(i); //Temporary stub. Due to ugly z-order implementation I need to do this (sankore 360) //z-order behavior should be reimplemented and this stub should be deleted if (nextItem == mBackgroundObject) continue; //Temporary stub end (sankore 360) // qreal zValue = nextItem->zValue(); // nextItem->setZValue(nextItem->data(UBGraphicsItemData::ItemOwnZValue).toReal()); nextItem->setZValue(1); QtLogger::logger() << "own Z " << QString::number(nextItem->data(UBGraphicsItemData::ItemOwnZValue).toReal(), 'f') << " next Z " << QString::number(nextItem->zValue(), 'f')<< endl; // qDebug() << QString(" %1 ").arg(i) << QString(" %1 ").arg(zValue); } QList selItemsList = selectedItems(); QtLogger::logger() << "=====selected items searching...======" << endl; QGraphicsItem *nextItem; for( int i = 0; i < selItemsList.size(); i++ ) { nextItem = selItemsList.at(i); QtLogger::logger() << "own Z " << QString::number(nextItem->data(UBGraphicsItemData::ItemOwnZValue).toReal(), 'f') << " next Z " << QString::number(nextItem->zValue(), 'f')<< endl; // qreal zValue = nextItem->zValue(); nextItem->setZValue(2); // qDebug() << QString(" >>> %1 <<< ").arg(i) << QString(" >>> %1 <<< ").arg(zValue); } QtLogger::logger() << "\nselection processing finished" << endl; QtLogger::logger().finish(); } // MARK: - // MARK: Mouse/Tablet events handling bool UBGraphicsScene::inputDevicePress(const QPointF& scenePos, const qreal& pressure) { //mMesure1Ms = 0; //mMesure2Ms = 0; bool accepted = false; if (mInputDeviceIsPressed) { qWarning() << "scene received input device pressed, without input device release, muting event as input device move"; accepted = inputDeviceMove(scenePos, pressure); } else { mInputDeviceIsPressed = true; UBStylusTool::Enum currentTool = (UBStylusTool::Enum)UBDrawingController::drawingController()->stylusTool(); if (UBDrawingController::drawingController()->isDrawingTool()) { qreal width = 0; // delete current stroke, if not assigned to any polygon if (mCurrentStroke) if (mCurrentStroke->polygons().empty()) delete mCurrentStroke; mCurrentStroke = new UBGraphicsStroke(); if (currentTool != UBStylusTool::Line) width = UBDrawingController::drawingController()->currentToolWidth() * pressure; else width = UBDrawingController::drawingController()->currentToolWidth(); //ignore pressure for line tool width /= UBApplication::boardController->systemScaleFactor(); width /= UBApplication::boardController->currentZoom(); mAddedItems.clear(); mRemovedItems.clear(); if (UBDrawingController::drawingController()->mActiveRuler) { UBDrawingController::drawingController()->mActiveRuler->StartLine( scenePos, width); } else { moveTo(scenePos); drawLineTo(scenePos, width, UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); } accepted = true; } else if (currentTool == UBStylusTool::Eraser) { mAddedItems.clear(); mRemovedItems.clear(); moveTo(scenePos); qreal eraserWidth = UBSettings::settings()->currentEraserWidth(); eraserWidth /= UBApplication::boardController->systemScaleFactor(); eraserWidth /= UBApplication::boardController->currentZoom(); eraseLineTo(scenePos, eraserWidth); drawEraser(scenePos, true); accepted = true; } else if (currentTool == UBStylusTool::Pointer) { drawPointer(scenePos, true); accepted = true; } } return accepted; } bool UBGraphicsScene::inputDeviceMove(const QPointF& scenePos, const qreal& pressure) { bool accepted = false; UBDrawingController *dc = UBDrawingController::drawingController(); UBStylusTool::Enum currentTool = (UBStylusTool::Enum)dc->stylusTool(); QPointF position = QPointF(scenePos); if (currentTool == UBStylusTool::Eraser) { drawEraser(position); accepted = true; } if (mInputDeviceIsPressed) { if (dc->isDrawingTool()) { qreal width = 0; if (currentTool != UBStylusTool::Line) width = dc->currentToolWidth() * pressure; else width = dc->currentToolWidth();//ignore pressure for line tool width /= UBApplication::boardController->systemScaleFactor(); width /= UBApplication::boardController->currentZoom(); if (dc->mActiveRuler) { dc->mActiveRuler->DrawLine(position, width); } else { if (currentTool == UBStylusTool::Line) { // TODO: Verify this beautiful implementation and check if // it is possible to optimize it QLineF radius(mPreviousPoint, position); qreal angle = radius.angle(); angle = qRound(angle / 45) * 45; qreal radiusLength = radius.length(); QPointF newPosition( mPreviousPoint.x() + radiusLength * cos((angle * PI) / 180), mPreviousPoint.y() - radiusLength * sin((angle * PI) / 180)); QLineF chord(position, newPosition); if (chord.length() < qMin((int)16, (int)(radiusLength / 20))) position = newPosition; } drawLineTo(position, width, UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Line); } } else if (currentTool == UBStylusTool::Eraser) { qreal eraserWidth = UBSettings::settings()->currentEraserWidth(); eraserWidth /= UBApplication::boardController->systemScaleFactor(); eraserWidth /= UBApplication::boardController->currentZoom(); eraseLineTo(position, eraserWidth); } else if (currentTool == UBStylusTool::Pointer) { drawPointer(position); } accepted = true; } return accepted; } bool UBGraphicsScene::inputDeviceRelease() { /* if (mMesure1Ms > 0 || mMesure2Ms > 0) { qWarning() << "---------------------------"; qWarning() << "mMesure1Ms: " << mMesure1Ms; qWarning() << "mMesure2Ms: " << mMesure2Ms; mMesure1Ms = 0; mMesure2Ms = 0; } */ bool accepted = false; if (mPointer) { mPointer->hide(); accepted = true; } UBDrawingController *dc = UBDrawingController::drawingController(); if (dc->isDrawingTool()) { if (mCurrentStroke) { if (mCurrentStroke->polygons().empty()) delete mCurrentStroke; mCurrentStroke = 0; } } if (mRemovedItems.size() > 0 || mAddedItems.size() > 0) { UBGraphicsItemUndoCommand* udcmd = new UBGraphicsItemUndoCommand(this, mRemovedItems, mAddedItems); //deleted by the undoStack if(UBApplication::undoStack) UBApplication::undoStack->push(udcmd); mRemovedItems.clear(); mAddedItems.clear(); accepted = true; } mInputDeviceIsPressed = false; setDocumentUpdated(); return accepted; } // MARK: - void UBGraphicsScene::drawEraser(const QPointF &pPoint, bool isFirstDraw) { qreal eraserWidth = UBSettings::settings()->currentEraserWidth(); eraserWidth /= UBApplication::boardController->systemScaleFactor(); eraserWidth /= UBApplication::boardController->currentZoom(); qreal eraserRadius = eraserWidth / 2; // TODO UB 4.x optimize - no need to do that every time we move it if (mEraser) { mEraser->setRect(QRectF(pPoint.x() - eraserRadius, pPoint.y() - eraserRadius, eraserWidth, eraserWidth)); if(isFirstDraw) { QList allItemsList = items(); for( int i = 0; i < allItemsList.size(); i++ ) { QGraphicsItem *nextItem = allItemsList.at(i); qreal zValue = nextItem->zValue(); nextItem->setZValue(qreal(1)); qDebug() << QString(" %1 ").arg(i) << QString(" %1 ").arg(zValue); } mEraser->setZValue(2); mEraser->show(); } } } void UBGraphicsScene::drawPointer(const QPointF &pPoint, bool isFirstDraw) { qreal pointerDiameter = UBSettings::pointerDiameter / UBApplication::boardController->currentZoom(); qreal pointerRadius = pointerDiameter / 2; // TODO UB 4.x optimize - no need to do that every time we move it if (mPointer) { mPointer->setRect(QRectF(pPoint.x() - pointerRadius, pPoint.y() - pointerRadius, pointerDiameter, pointerDiameter)); if(isFirstDraw) { QList allItemsList = items(); for( int i = 0; i < allItemsList.size(); i++ ) { QGraphicsItem *nextItem = allItemsList.at(i); qreal zValue = nextItem->zValue(); nextItem->setZValue(qreal(1)); qDebug() << QString(" %1 ").arg(i) << QString(" %1 ").arg(zValue); } mPointer->setZValue(2); mPointer->show(); } } } // call this function when user release mouse button in Magnifier mode void UBGraphicsScene::DisposeMagnifierQWidgets() { if(magniferControlViewWidget) { magniferControlViewWidget->hide(); magniferControlViewWidget->setParent(0); delete magniferControlViewWidget; magniferControlViewWidget = NULL; } if(magniferDisplayViewWidget) { magniferDisplayViewWidget->hide(); magniferDisplayViewWidget->setParent(0); delete magniferDisplayViewWidget; magniferDisplayViewWidget = NULL; } // some time have crash here on access to app (when call from destructor when close sankore app) // so i just add try/catch section here try { UBApplication::app()->restoreOverrideCursor(); } catch (...) { } } void UBGraphicsScene::moveTo(const QPointF &pPoint) { mPreviousPoint = pPoint; mPreviousWidth = -1.0; mPreviousPolygonItems.clear(); mArcPolygonItem = 0; } void UBGraphicsScene::drawLineTo(const QPointF &pEndPoint, const qreal &pWidth, bool bLineStyle) { if (mPreviousWidth == -1.0) mPreviousWidth = pWidth; UBGraphicsPolygonItem *polygonItem = lineToPolygonItem(QLineF(mPreviousPoint, pEndPoint), pWidth); if (!polygonItem->brush().isOpaque()) { for (int i = 0; i < mPreviousPolygonItems.size(); i++) { UBGraphicsPolygonItem* previous = mPreviousPolygonItems.value(i); polygonItem->subtract(previous); } } if (bLineStyle) { QSetIterator itItems(mAddedItems); while (itItems.hasNext()) { QGraphicsItem* item = itItems.next(); removeItem(item); } mAddedItems.clear(); } mAddedItems.insert(polygonItem); if (mCurrentStroke) { polygonItem->setStroke(mCurrentStroke); } addItem(polygonItem); mPreviousPolygonItems.append(polygonItem); if (!bLineStyle) { mPreviousPoint = pEndPoint; mPreviousWidth = pWidth; } } void UBGraphicsScene::eraseLineTo(const QPointF &pEndPoint, const qreal &pWidth) { const QLineF line(mPreviousPoint, pEndPoint); const QPolygonF eraserPolygon = UBGeometryUtils::lineToPolygon(line, pWidth); const QRectF eraserBoundingRect = eraserPolygon.boundingRect(); const QRectF eraserInnerRect = UBGeometryUtils::lineToInnerRect(line, pWidth); QPainterPath eraserPathVar; eraserPathVar.addPolygon(eraserPolygon); const QPainterPath eraserPath = eraserPathVar; QList collidItems = items(eraserBoundingRect, Qt::IntersectsItemBoundingRect); QSet toBeAddedItems; QSet toBeRemovedItems; int collidItemsSize = collidItems.size(); toBeAddedItems.reserve(collidItemsSize); toBeRemovedItems.reserve(collidItemsSize); if (mShouldUseOMP) { #pragma omp parallel for for (int i = 0; i < collidItemsSize; i++) { UBGraphicsPolygonItem *collidingPolygonItem = qgraphicsitem_cast (collidItems.at(i)); if (collidingPolygonItem) { if(eraserInnerRect.contains(collidingPolygonItem->boundingRect())) { #pragma omp critical toBeRemovedItems << collidingPolygonItem; } else { QPolygonF collidingPolygon = collidingPolygonItem->polygon(); QPainterPath collidingPath; collidingPath.addPolygon(collidingPolygon); QPainterPath croppedPath = collidingPath.subtracted(eraserPath); QPainterPath croppedPathSimplified = croppedPath.simplified(); if (croppedPath == collidingPath) { // NOOP } else if (croppedPathSimplified.isEmpty()) { #pragma omp critical toBeRemovedItems << collidingPolygonItem; } else { foreach(const QPolygonF &pol, croppedPathSimplified.toFillPolygons()) { UBGraphicsPolygonItem* croppedPolygonItem = collidingPolygonItem->deepCopy(pol); #pragma omp critical toBeAddedItems << croppedPolygonItem; } #pragma omp critical toBeRemovedItems << collidingPolygonItem; } } } } } else { for (int i = 0; i < collidItemsSize; i++) { UBGraphicsPolygonItem *collidingPolygonItem = qgraphicsitem_cast (collidItems.at(i)); if (collidingPolygonItem) { if(eraserInnerRect.contains(collidingPolygonItem->boundingRect())) { toBeRemovedItems << collidingPolygonItem; } else { QPolygonF collidingPolygon = collidingPolygonItem->polygon(); QPainterPath collidingPath; collidingPath.addPolygon(collidingPolygon); QPainterPath croppedPath = collidingPath.subtracted(eraserPath); QPainterPath croppedPathSimplified = croppedPath.simplified(); if (croppedPath == collidingPath) { // NOOP } else if (croppedPathSimplified.isEmpty()) { toBeRemovedItems << collidingPolygonItem; } else { foreach(const QPolygonF &pol, croppedPathSimplified.toFillPolygons()) { UBGraphicsPolygonItem* croppedPolygonItem = collidingPolygonItem->deepCopy(pol); toBeAddedItems << croppedPolygonItem; } toBeRemovedItems << collidingPolygonItem; } } } } } addItems(toBeAddedItems); mAddedItems += toBeAddedItems; removeItems(toBeRemovedItems); mRemovedItems += toBeRemovedItems; mPreviousPoint = pEndPoint; } void UBGraphicsScene::drawArcTo(const QPointF& pCenterPoint, qreal pSpanAngle) { if (mArcPolygonItem) { mAddedItems.remove(mArcPolygonItem); removeItem(mArcPolygonItem); mArcPolygonItem = 0; } qreal penWidth = UBSettings::settings()->currentPenWidth(); penWidth /= UBApplication::boardController->systemScaleFactor(); penWidth /= UBApplication::boardController->currentZoom(); mArcPolygonItem = arcToPolygonItem(QLineF(pCenterPoint, mPreviousPoint), pSpanAngle, penWidth); mAddedItems.insert(mArcPolygonItem); addItem(mArcPolygonItem); setDocumentUpdated(); } qreal UBGraphicsScene::getNextDrawingZIndex() { mDrawingZIndex = mDrawingZIndex + 1.0; return mDrawingZIndex; } qreal UBGraphicsScene::getNextObjectZIndex() { mObjectZIndex = mObjectZIndex + 1.0; return mObjectZIndex; } void UBGraphicsScene::setBackground(bool pIsDark, bool pIsCrossed) { bool needRepaint = false; if (mDarkBackground != pIsDark) { mDarkBackground = pIsDark; if (mEraser) { if (mDarkBackground) { mEraser->setBrush(UBSettings::eraserBrushDarkBackground); mEraser->setPen(UBSettings::eraserPenDarkBackground); } else { mEraser->setBrush(UBSettings::eraserBrushLightBackground); mEraser->setPen(UBSettings::eraserPenLightBackground); } } recolorAllItems(); needRepaint = true; setModified(true); } if (mCrossedBackground != pIsCrossed) { mCrossedBackground = pIsCrossed; needRepaint = true; setModified(true); } if (needRepaint) { foreach(QGraphicsView* view, views()) { view->resetCachedContent(); } } } void UBGraphicsScene::recolorAllItems() { QMap previousUpdateModes; foreach(QGraphicsView* view, views()) { previousUpdateModes.insert(view, view->viewportUpdateMode()); view->setViewportUpdateMode(QGraphicsView::NoViewportUpdate); } for(int i = 0; i < mFastAccessItems.size(); i++) { UBGraphicsPolygonItem *polygonItem = qgraphicsitem_cast (mFastAccessItems.at(i)); if (polygonItem) { QColor color; if (mDarkBackground) { color = polygonItem->colorOnDarkBackground(); } else { color = polygonItem->colorOnLightBackground(); } polygonItem->setColor(color); continue; } } foreach(QGraphicsView* view, views()) { view->setViewportUpdateMode(previousUpdateModes.value(view)); } } UBGraphicsPolygonItem* UBGraphicsScene::lineToPolygonItem(const QLineF &pLine, const qreal &pWidth) { UBGraphicsPolygonItem *polygonItem = new UBGraphicsPolygonItem(pLine, pWidth); initPolygonItem(polygonItem); return polygonItem; } void UBGraphicsScene::initPolygonItem(UBGraphicsPolygonItem* polygonItem) { QColor colorOnDarkBG; QColor colorOnLightBG; if (UBDrawingController::drawingController()->stylusTool() == UBStylusTool::Marker) { colorOnDarkBG = UBApplication::boardController->markerColorOnDarkBackground(); colorOnLightBG = UBApplication::boardController->markerColorOnLightBackground(); } else // settings->stylusTool() == UBStylusTool::Pen + failsafe { colorOnDarkBG = UBApplication::boardController->penColorOnDarkBackground(); colorOnLightBG = UBApplication::boardController->penColorOnLightBackground(); } if (mDarkBackground) { polygonItem->setColor(colorOnDarkBG); } else { polygonItem->setColor(colorOnLightBG); } polygonItem->setColorOnDarkBackground(colorOnDarkBG); polygonItem->setColorOnLightBackground(colorOnLightBG); polygonItem->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Graphic)); // polygonItem->setZValue(getNextDrawingZIndex()); UBGraphicsItem::assignZValue(polygonItem, getNextDrawingZIndex()); } UBGraphicsPolygonItem* UBGraphicsScene::arcToPolygonItem(const QLineF& pStartRadius, qreal pSpanAngle, qreal pWidth) { QPolygonF polygon = UBGeometryUtils::arcToPolygon(pStartRadius, pSpanAngle, pWidth); return polygonToPolygonItem(polygon); } UBGraphicsPolygonItem* UBGraphicsScene::polygonToPolygonItem(const QPolygonF pPolygon) { UBGraphicsPolygonItem *polygonItem = new UBGraphicsPolygonItem(pPolygon); initPolygonItem(polygonItem); return polygonItem; } void UBGraphicsScene::hideEraser() { if (mEraser) mEraser->hide(); } void UBGraphicsScene::leaveEvent(QEvent * event) { Q_UNUSED(event); hideEraser(); } UBGraphicsScene* UBGraphicsScene::sceneDeepCopy() const { UBGraphicsScene* copy = new UBGraphicsScene(this->document()); copy->setBackground(this->isDarkBackground(), this->isCrossedBackground()); copy->mDrawingZIndex = this->mDrawingZIndex; copy->mObjectZIndex = this->mObjectZIndex; copy->setSceneRect(this->sceneRect()); if (this->mNominalSize.isValid()) copy->setNominalSize(this->mNominalSize); QListIterator itItems(this->mFastAccessItems); QMap groupClone; while (itItems.hasNext()) { QGraphicsItem* item = itItems.next(); QGraphicsItem* cloneItem = 0; UBItem* ubItem = dynamic_cast(item); UBGraphicsStroke* stroke = dynamic_cast(item); if (ubItem && !stroke) { cloneItem = dynamic_cast(ubItem->deepCopy()); } if (cloneItem) { copy->addItem(cloneItem); if (isBackgroundObject(item)) { copy->setAsBackgroundObject(cloneItem); } if (this->mTools.contains(item)) { copy->mTools << cloneItem; } UBGraphicsPolygonItem* polygon = dynamic_cast(item); if(polygon) { UBGraphicsStroke* stroke = dynamic_cast(item->parentItem()); if (stroke) { UBGraphicsStroke* cloneStroke = groupClone.value(stroke); if (!cloneStroke) { cloneStroke = stroke->deepCopy(); groupClone.insert(stroke, cloneStroke); } polygon->setStroke(cloneStroke); } } } } // TODO UB 4.7 ... complete all members ? return copy; } UBItem* UBGraphicsScene::deepCopy() const { return sceneDeepCopy(); } void UBGraphicsScene::clearItemsAndAnnotations() { deselectAllItems(); QSet emptyList; QSet removedItems; QListIterator itItems(mFastAccessItems); while (itItems.hasNext()) { QGraphicsItem* item = itItems.next(); if(!mTools.contains(item) && !isBackgroundObject(item)) { removeItem(item); removedItems << item; } } // force refresh, QT is a bit lazy and take a lot of time (nb item ^2 ?) to trigger repaint update(sceneRect()); UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, removedItems, emptyList); UBApplication::undoStack->push(uc); setDocumentUpdated(); } void UBGraphicsScene::clearItems() { deselectAllItems(); QSet emptyList; QSet removedItems; QListIterator itItems(mFastAccessItems); while (itItems.hasNext()) { QGraphicsItem* item = itItems.next(); if (!item->parentItem()) { UBGraphicsPolygonItem* pi = qgraphicsitem_cast(item); if(!pi && !mTools.contains(item) && !isBackgroundObject(item)) { removeItem(item); removedItems << item; } } } // force refresh, QT is a bit lazy and take a lot of time (nb item ^2 ?) to trigger repaint update(sceneRect()); UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, removedItems, emptyList); UBApplication::undoStack->push(uc); setDocumentUpdated(); } void UBGraphicsScene::clearAnnotations() { QSet emptyList; QSet removedItems; QListIterator itItems(mFastAccessItems); while (itItems.hasNext()) { QGraphicsItem* item = itItems.next(); UBGraphicsPolygonItem* pi = qgraphicsitem_cast(item); if (pi) { removeItem(item); removedItems << item; } } // force refresh, QT is a bit lazy and take a lot of time (nb item ^2 ?) to trigger repaint update(sceneRect()); UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, removedItems, emptyList); UBApplication::undoStack->push(uc); setDocumentUpdated(); } UBGraphicsPixmapItem* UBGraphicsScene::addPixmap(const QPixmap& pPixmap, const QPointF& pPos, qreal pScaleFactor, bool pUseAnimation) { UBGraphicsPixmapItem* pixmapItem = new UBGraphicsPixmapItem(); pixmapItem->setFlag(QGraphicsItem::ItemIsMovable, true); pixmapItem->setFlag(QGraphicsItem::ItemIsSelectable, true); // pixmapItem->setZValue(getNextObjectZIndex()); UBGraphicsItem::assignZValue(pixmapItem, getNextObjectZIndex()); pixmapItem->setPixmap(pPixmap); QPointF half(pPixmap.width() * pScaleFactor / 2, pPixmap.height() * pScaleFactor / 2); pixmapItem->setPos(pPos - half); addItem(pixmapItem); UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, pixmapItem); UBApplication::undoStack->push(uc); pixmapItem->scale(pScaleFactor, pScaleFactor); if (pUseAnimation) { pixmapItem->setOpacity(0); QPropertyAnimation *animation = new QPropertyAnimation(pixmapItem, "opacity"); animation->setDuration(1000); animation->setStartValue(0.0); animation->setEndValue(1.0); animation->start(); } pixmapItem->show(); setDocumentUpdated(); return pixmapItem; } void UBGraphicsScene::textUndoCommandAdded(UBGraphicsTextItem *textItem) { UBGraphicsTextItemUndoCommand* uc = new UBGraphicsTextItemUndoCommand(textItem); UBApplication::undoStack->push(uc); } UBGraphicsVideoItem* UBGraphicsScene::addVideo(const QUrl& pVideoFileUrl, bool shouldPlayAsap, const QPointF& pPos) { UBGraphicsVideoItem* videoItem = new UBGraphicsVideoItem(pVideoFileUrl); videoItem->setPos(pPos); videoItem->setFlag(QGraphicsItem::ItemIsMovable, true); videoItem->setFlag(QGraphicsItem::ItemIsSelectable, true); // videoItem->setZValue(getNextObjectZIndex()); UBGraphicsItem::assignZValue(videoItem, getNextObjectZIndex()); addItem(videoItem); videoItem->show(); UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, videoItem); UBApplication::undoStack->push(uc); videoItem->mediaObject()->play(); if (!shouldPlayAsap) { videoItem->mediaObject()->pause(); videoItem->mediaObject()->seek(0); } setDocumentUpdated(); return videoItem; } UBGraphicsAudioItem* UBGraphicsScene::addAudio(const QUrl& pAudioFileUrl, bool shouldPlayAsap, const QPointF& pPos) { UBGraphicsAudioItem* audioItem = new UBGraphicsAudioItem(pAudioFileUrl); audioItem->setPos(pPos); audioItem->setFlag(QGraphicsItem::ItemIsMovable, true); audioItem->setFlag(QGraphicsItem::ItemIsSelectable, true); // audioItem->setZValue(getNextObjectZIndex()); UBGraphicsItem::assignZValue(audioItem, getNextObjectZIndex()); addItem(audioItem); audioItem->show(); UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, audioItem); UBApplication::undoStack->push(uc); audioItem->mediaObject()->play(); if (!shouldPlayAsap) { audioItem->mediaObject()->pause(); audioItem->mediaObject()->seek(0); } setDocumentUpdated(); return audioItem; } UBGraphicsWidgetItem* UBGraphicsScene::addWidget(const QUrl& pWidgetUrl, const QPointF& pPos) { int widgetType = UBAbstractWidget::widgetType(pWidgetUrl); if(widgetType == UBWidgetType::Apple) { return addAppleWidget(pWidgetUrl, pPos); } else if(widgetType == UBWidgetType::W3C) { return addW3CWidget(pWidgetUrl, pPos); } else { qDebug() << "UBGraphicsScene::addWidget: Unknown widget Type"; return 0; } } UBGraphicsAppleWidgetItem* UBGraphicsScene::addAppleWidget(const QUrl& pWidgetUrl, const QPointF& pPos) { UBGraphicsAppleWidgetItem *appleWidget = new UBGraphicsAppleWidgetItem(pWidgetUrl); addGraphicsWidget(appleWidget, pPos); return appleWidget; } UBGraphicsW3CWidgetItem* UBGraphicsScene::addW3CWidget(const QUrl& pWidgetUrl, const QPointF& pPos, int widgetType) { UBGraphicsW3CWidgetItem *w3CWidget = new UBGraphicsW3CWidgetItem(pWidgetUrl, 0, widgetType); addGraphicsWidget(w3CWidget, pPos); return w3CWidget; } void UBGraphicsScene::addGraphicsWidget(UBGraphicsWidgetItem* graphicsWidget, const QPointF& pPos) { graphicsWidget->setFlag(QGraphicsItem::ItemIsSelectable, true); // graphicsWidget->setZValue(getNextObjectZIndex()); UBGraphicsItem::assignZValue(graphicsWidget, getNextObjectZIndex()); addItem(graphicsWidget); qreal ssf = 1 / UBApplication::boardController->systemScaleFactor(); graphicsWidget->scale(ssf, ssf); graphicsWidget->setPos(QPointF(pPos.x() - graphicsWidget->boundingRect().width() / 2, pPos.y() - graphicsWidget->boundingRect().height() / 2)); if (graphicsWidget->widgetWebView()->canBeContent()) { // graphicsWidget->widgetWebView()->loadMainHtml(); graphicsWidget->setSelected(true); UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, graphicsWidget); UBApplication::undoStack->push(uc); setDocumentUpdated(); } else { UBApplication::boardController->moveGraphicsWidgetToControlView(graphicsWidget); } } UBGraphicsW3CWidgetItem* UBGraphicsScene::addOEmbed(const QUrl& pContentUrl, const QPointF& pPos) { QStringList widgetPaths = UBPersistenceManager::persistenceManager()->allWidgets(UBSettings::settings()->uniboardInteractiveLibraryDirectory()); UBGraphicsW3CWidgetItem *widget = 0; foreach(QString widgetPath, widgetPaths) { if (widgetPath.contains("VideoPicker")) { widget = addW3CWidget(QUrl::fromLocalFile(widgetPath), pPos); if (widget) { widget->setPreference("oembedUrl", pContentUrl.toString()); setDocumentUpdated(); break; } } } return widget; } UBGraphicsSvgItem* UBGraphicsScene::addSvg(const QUrl& pSvgFileUrl, const QPointF& pPos) { QString path = pSvgFileUrl.toLocalFile(); UBGraphicsSvgItem *svgItem = new UBGraphicsSvgItem(path); svgItem->setFlag(QGraphicsItem::ItemIsMovable, true); svgItem->setFlag(QGraphicsItem::ItemIsSelectable, true); // svgItem->setZValue(getNextObjectZIndex()); UBGraphicsItem::assignZValue(svgItem, getNextObjectZIndex()); qreal sscale = 1 / UBApplication::boardController->systemScaleFactor(); svgItem->scale(sscale, sscale); QPointF half(svgItem->boundingRect().width() / 2, svgItem->boundingRect().height() / 2); svgItem->setPos(pPos - half); svgItem->show(); addItem(svgItem); UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, svgItem); UBApplication::undoStack->push(uc); setDocumentUpdated(); return svgItem; } UBGraphicsTextItem* UBGraphicsScene::addText(const QString& pString, const QPointF& pTopLeft) { return addTextWithFont(pString, pTopLeft, UBSettings::settings()->fontPixelSize() , UBSettings::settings()->fontFamily(), UBSettings::settings()->isBoldFont() , UBSettings::settings()->isItalicFont()); } UBGraphicsTextItem* UBGraphicsScene::addTextWithFont(const QString& pString, const QPointF& pTopLeft , int pointSize, const QString& fontFamily, bool bold, bool italic) { UBGraphicsTextItem *textItem = new UBGraphicsTextItem(); textItem->setPlainText(pString); // textItem->setZValue(getNextObjectZIndex()); UBGraphicsItem::assignZValue(textItem, getNextObjectZIndex()); QFont font = textItem->font(); if (fontFamily == "") { font = QFont(UBSettings::settings()->fontFamily()); } else { font = QFont(fontFamily); } if (pointSize < 1) { font.setPixelSize(UBSettings::settings()->fontPixelSize()); } else { font.setPointSize(pointSize); } font.setBold(bold); font.setItalic(italic); textItem->setFont(font); QFontMetrics fi(font); QRect br = fi.boundingRect(pString); textItem->setTextWidth(qMax((qreal)br.width() + 50, (qreal)200)); textItem->setTextHeight(br.height()); addItem(textItem); textItem->setPos(pTopLeft); textItem->show(); UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, textItem); UBApplication::undoStack->push(uc); connect(textItem, SIGNAL(textUndoCommandAdded(UBGraphicsTextItem *)), this, SLOT(textUndoCommandAdded(UBGraphicsTextItem *))); textItem->setSelected(true); textItem->setFocus(); setDocumentUpdated(); return textItem; } UBGraphicsTextItem *UBGraphicsScene::addTextHtml(const QString &pString, const QPointF& pTopLeft) { UBGraphicsTextItem *textItem = new UBGraphicsTextItem(); textItem->setPlainText(""); textItem->setHtml(pString); // textItem->setZValue(getNextObjectZIndex()); UBGraphicsItem::assignZValue(textItem, getNextObjectZIndex()); addItem(textItem); textItem->show(); UBGraphicsItemUndoCommand* uc = new UBGraphicsItemUndoCommand(this, 0, textItem); UBApplication::undoStack->push(uc); connect(textItem, SIGNAL(textUndoCommandAdded(UBGraphicsTextItem *)), this, SLOT(textUndoCommandAdded(UBGraphicsTextItem *))); textItem->setFocus(); setDocumentUpdated(); textItem->setPos(pTopLeft); return textItem; } void UBGraphicsScene::addItem(QGraphicsItem* item) { setModified(true); UBCoreGraphicsScene::addItem(item); if (!mTools.contains(item)) ++mItemCount; mFastAccessItems << item; } void UBGraphicsScene::addItems(const QSet& items) { setModified(true); foreach(QGraphicsItem* item, items) UBCoreGraphicsScene::addItem(item); mItemCount += items.size(); mFastAccessItems += items.toList(); } void UBGraphicsScene::removeItem(QGraphicsItem* item) { setModified(true); UBCoreGraphicsScene::removeItem(item); if (!mTools.contains(item)) --mItemCount; mFastAccessItems.removeAll(item); } void UBGraphicsScene::removeItems(const QSet& items) { setModified(true); foreach(QGraphicsItem* item, items) UBCoreGraphicsScene::removeItem(item); mItemCount -= items.size(); foreach(QGraphicsItem* item, items) mFastAccessItems.removeAll(item); } void UBGraphicsScene::deselectAllItems() { foreach(QGraphicsItem *gi, selectedItems ()) { gi->setSelected(false); } } bool UBGraphicsScene::isEmpty() const { return mItemCount == 0; } QGraphicsItem* UBGraphicsScene::setAsBackgroundObject(QGraphicsItem* item, bool pAdaptTransformation, bool pExpand) { if (mBackgroundObject) { removeItem(mBackgroundObject); mBackgroundObject = 0; } if (item) { item->setFlag(QGraphicsItem::ItemIsSelectable, false); item->setFlag(QGraphicsItem::ItemIsMovable, false); item->setAcceptedMouseButtons(Qt::NoButton); item->setData(UBGraphicsItemData::ItemLayerType, UBItemLayerType::FixedBackground); // item->setZValue(backgroundLayerStart); UBGraphicsItem::assignZValue(item, backgroundLayerStart); if (pAdaptTransformation) { item = scaleToFitDocumentSize(item, true, 0, pExpand); } if (item->scene() != this) addItem(item); mBackgroundObject = item; } return item; } QRectF UBGraphicsScene::normalizedSceneRect(qreal ratio) { QRectF normalizedRect(nominalSize().width() / -2, nominalSize().height() / -2, nominalSize().width(), nominalSize().height()); foreach(QGraphicsItem* gi, mFastAccessItems) { if(gi && gi->isVisible() && !mTools.contains(gi)) { normalizedRect = normalizedRect.united(gi->sceneBoundingRect()); } } if (ratio > 0.0) { qreal normalizedRectRatio = normalizedRect.width() / normalizedRect.height(); if (normalizedRectRatio > ratio) { //the normalized rect is too wide, we increase height qreal newHeight = normalizedRect.width() / ratio; qreal offset = (newHeight - normalizedRect.height()) / 2; normalizedRect.setY(normalizedRect.y() - offset); normalizedRect.setHeight(newHeight); } else if (normalizedRectRatio < ratio) { //the normalized rect is too high, we increase the width qreal newWidth = normalizedRect.height() * ratio; qreal offset = (newWidth - normalizedRect.width()) / 2; normalizedRect.setX(normalizedRect.x() - offset); normalizedRect.setWidth(newWidth); } } return normalizedRect; } void UBGraphicsScene::setDocument(UBDocumentProxy* pDocument) { if (pDocument != mDocument) { if (mDocument) { setModified(true); } mDocument = pDocument; setParent(pDocument); } } QGraphicsItem* UBGraphicsScene::scaleToFitDocumentSize(QGraphicsItem* item, bool center, int margin, bool expand) { int maxWidth = mNominalSize.width() - (margin * 2); int maxHeight = mNominalSize.height() - (margin * 2); QRectF size = item->sceneBoundingRect(); if (expand || size.width() > maxWidth || size.height() > maxHeight) { qreal ratio = qMin(maxWidth / size.width(), maxHeight / size.height()); item->scale(ratio, ratio); if(center) { item->setPos(item->sceneBoundingRect().width() / -2.0, item->sceneBoundingRect().height() / -2.0); } } return item; } void UBGraphicsScene::addRuler(QPointF center) { UBGraphicsRuler* ruler = new UBGraphicsRuler(); // mem : owned and destroyed by the scene mTools << ruler; QRectF rect = ruler->rect(); ruler->setRect(center.x() - rect.width()/2, center.y() - rect.height()/2, rect.width(), rect.height()); // ruler->setZValue(toolLayerStart + toolOffsetRuler); UBGraphicsItem::assignZValue(ruler, toolLayerStart + toolOffsetRuler); ruler->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); addItem(ruler); ruler->setVisible(true); setModified(true); } void UBGraphicsScene::addProtractor(QPointF center) { // Protractor UBGraphicsProtractor* protractor = new UBGraphicsProtractor(); // mem : owned and destroyed by the scene mTools << protractor; // protractor->setZValue(toolLayerStart + toolOffsetProtractor); UBGraphicsItem::assignZValue(protractor, toolLayerStart + toolOffsetProtractor); protractor->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); addItem(protractor); QPointF itemSceneCenter = protractor->sceneBoundingRect().center(); protractor->moveBy(center.x() - itemSceneCenter.x(), center.y() - itemSceneCenter.y()); protractor->setVisible(true); setModified(true); } void UBGraphicsScene::addTriangle(QPointF center) { // Triangle UBGraphicsTriangle* triangle = new UBGraphicsTriangle(); // mem : owned and destroyed by the scene mTools << triangle; // triangle->setZValue(toolLayerStart + toolOffsetProtractor); UBGraphicsItem::assignZValue(triangle, toolLayerStart + toolOffsetTriangle); triangle->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); addItem(triangle); QPointF itemSceneCenter = triangle->sceneBoundingRect().center(); triangle->moveBy(center.x() - itemSceneCenter.x(), center.y() - itemSceneCenter.y()); triangle->setVisible(true); setModified(true); } void UBGraphicsScene::addMagnifier(UBMagnifierParams params) { // can have only one magnifier at one time if(magniferControlViewWidget) return; QWidget *cContainer = (QWidget*)(UBApplication::boardController->controlContainer()); QGraphicsView *cView = (QGraphicsView*)UBApplication::boardController->controlView(); QGraphicsView *dView = (QGraphicsView*)UBApplication::boardController->displayView(); QPoint ccZeroPoint = cContainer->mapToGlobal(QPoint(0,0)); QPoint cvZeroPoint = cView->mapToGlobal(QPoint(0,0)); QPoint dvZeroPoint = dView->mapToGlobal(QPoint(0,0)); int cvW = cView->width(); int dvW = dView->width(); qreal wCoeff = (qreal)dvW / (qreal)cvW; int cvH = cView->height(); int dvH = dView->height(); qreal hCoeff = (qreal)dvH / (qreal)cvH; QPoint ccPoint(params.x,params.y); QPoint globalPoint = cContainer->mapToGlobal(ccPoint); QPoint cvPoint = cView->mapFromGlobal(globalPoint); QPoint dvPoint( cvPoint.x() * wCoeff + dvZeroPoint.x(), cvPoint.y() * hCoeff + dvZeroPoint.y()); magniferControlViewWidget = new UBMagnifier((QWidget*)(UBApplication::boardController->controlContainer()), true); magniferControlViewWidget->setGrabView((QGraphicsView*)UBApplication::boardController->controlView()); magniferControlViewWidget->setMoveView((QWidget*)(UBApplication::boardController->controlContainer())); magniferControlViewWidget->setSize(params.sizePercentFromScene); magniferControlViewWidget->setZoom(params.zoom); magniferDisplayViewWidget = new UBMagnifier((QWidget*)(UBApplication::boardController->displayView()), false); magniferDisplayViewWidget->setGrabView((QGraphicsView*)UBApplication::boardController->controlView()); magniferDisplayViewWidget->setMoveView((QGraphicsView*)UBApplication::boardController->displayView()); magniferDisplayViewWidget->setSize(params.sizePercentFromScene); magniferDisplayViewWidget->setZoom(params.zoom); magniferControlViewWidget->grabNMove(globalPoint, globalPoint, true); magniferDisplayViewWidget->grabNMove(globalPoint, dvPoint, true); magniferControlViewWidget->show(); magniferDisplayViewWidget->show(); connect(magniferControlViewWidget, SIGNAL(magnifierMoved_Signal(QPoint)), this, SLOT(moveMagnifier(QPoint))); connect(magniferControlViewWidget, SIGNAL(magnifierClose_Signal()), this, SLOT(closeMagnifier())); connect(magniferControlViewWidget, SIGNAL(magnifierZoomIn_Signal()), this, SLOT(zoomInMagnifier())); connect(magniferControlViewWidget, SIGNAL(magnifierZoomOut_Signal()), this, SLOT(zoomOutMagnifier())); connect(magniferControlViewWidget, SIGNAL(magnifierResized_Signal(qreal)), this, SLOT(resizedMagnifier(qreal))); setModified(true); } void UBGraphicsScene::moveMagnifier(QPoint newPos) { QWidget *cContainer = (QWidget*)(UBApplication::boardController->controlContainer()); QGraphicsView *cView = (QGraphicsView*)UBApplication::boardController->controlView(); QGraphicsView *dView = (QGraphicsView*)UBApplication::boardController->displayView(); QPoint ccZeroPoint = cContainer->mapToGlobal(QPoint(0,0)); QPoint cvZeroPoint = cView->mapToGlobal(QPoint(0,0)); QPoint dvZeroPoint = dView->mapToGlobal(QPoint(0,0)); int cvW = cView->width(); int dvW = dView->width(); qreal wCoeff = (qreal)dvW / (qreal)cvW; int cvH = cView->height(); int dvH = dView->height(); qreal hCoeff = (qreal)dvH / (qreal)cvH; QPoint globalPoint = cContainer->mapToGlobal(newPos); QPoint cvPoint = cView->mapFromGlobal(globalPoint); QPoint dvPoint( cvPoint.x() * wCoeff + dvZeroPoint.x(), cvPoint.y() * hCoeff + dvZeroPoint.y()); magniferControlViewWidget->grabNMove(globalPoint, globalPoint, false, false); magniferDisplayViewWidget->grabNMove(globalPoint, dvPoint, false, true); setModified(true); } void UBGraphicsScene::closeMagnifier() { DisposeMagnifierQWidgets(); } void UBGraphicsScene::zoomInMagnifier() { if(magniferControlViewWidget->params.zoom < 8) { magniferControlViewWidget->setZoom(magniferControlViewWidget->params.zoom + 0.5); magniferDisplayViewWidget->setZoom(magniferDisplayViewWidget->params.zoom + 0.5); } } void UBGraphicsScene::zoomOutMagnifier() { if(magniferControlViewWidget->params.zoom > 1) { magniferControlViewWidget->setZoom(magniferControlViewWidget->params.zoom - 0.5); magniferDisplayViewWidget->setZoom(magniferDisplayViewWidget->params.zoom - 0.5); } } void UBGraphicsScene::resizedMagnifier(qreal newPercent) { if(newPercent > 18 && newPercent < 50) { magniferControlViewWidget->setSize(newPercent); magniferControlViewWidget->grabPoint(); magniferDisplayViewWidget->setSize(newPercent); magniferDisplayViewWidget->grabPoint(); } } void UBGraphicsScene::addCompass(QPointF center) { UBGraphicsCompass* compass = new UBGraphicsCompass(); // mem : owned and destroyed by the scene mTools << compass; addItem(compass); QRectF rect = compass->rect(); compass->setRect(center.x() - rect.width() / 2, center.y() - rect.height() / 2, rect.width(), rect.height()); // compass->setZValue(toolLayerStart + toolOffsetCompass); UBGraphicsItem::assignZValue(compass, toolLayerStart + toolOffsetCompass); compass->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Tool)); compass->setVisible(true); setModified(true); } void UBGraphicsScene::addCache() { UBGraphicsCache* cache = new UBGraphicsCache(); mTools << cache; QGraphicsView* view; if(UBApplication::applicationController->displayManager()->hasDisplay()) { view = (QGraphicsView*)(UBApplication::boardController->displayView()); } else { view = (QGraphicsView*)(UBApplication::boardController->controlView()); } addItem(cache); cache->setVisible(true); cache->setSelected(true); UBApplication::boardController->notifyCache(true); UBApplication::boardController->notifyPageChanged(); } void UBGraphicsScene::addMask() { UBGraphicsCurtainItem* curtain = new UBGraphicsCurtainItem(); // mem : owned and destroyed by the scene mTools << curtain; QGraphicsView* view; if(UBApplication::applicationController->displayManager()->hasDisplay()) view = (QGraphicsView*)UBApplication::boardController->displayView(); else view = (QGraphicsView*)UBApplication::boardController->controlView(); QPolygonF polygon = view->mapToScene(view->rect()); // curtain->setZValue(toolLayerStart + toolOffsetCurtain); UBGraphicsItem::assignZValue(curtain, toolLayerStart + toolOffsetCurtain); QRectF rect = polygon.boundingRect(); qreal xScale = view->matrix().m11(); qreal yScale = view->matrix().m22(); rect.adjust(120 / xScale, 80 / yScale, -120 / xScale, -80 / yScale); curtain->setRect(rect); addItem(curtain); curtain->setVisible(true); curtain->setSelected(true); setModified(true); } void UBGraphicsScene::setRenderingQuality(UBItem::RenderingQuality pRenderingQuality) { QListIterator itItems(mFastAccessItems); while (itItems.hasNext()) { QGraphicsItem *gItem = itItems.next(); UBItem *ubItem = dynamic_cast(gItem); if (ubItem) { ubItem->setRenderingQuality(pRenderingQuality); } } } QList UBGraphicsScene::relativeDependencies() const { QList relativePathes; QListIterator itItems(mFastAccessItems); while (itItems.hasNext()) { UBGraphicsVideoItem *videoItem = qgraphicsitem_cast (itItems.next()); if (videoItem && videoItem->mediaFileUrl().isRelative()) { relativePathes << videoItem->mediaFileUrl(); } } return relativePathes; } QSize UBGraphicsScene::nominalSize() { if (mDocument && !mNominalSize.isValid()) { mNominalSize = mDocument->defaultDocumentSize(); } return mNominalSize; } void UBGraphicsScene::setNominalSize(const QSize& pSize) { if (nominalSize() != pSize) { mNominalSize = pSize; emit pageSizeChanged(); if(mDocument) mDocument->setDefaultDocumentSize(pSize); } } void UBGraphicsScene::setNominalSize(int pWidth, int pHeight) { setNominalSize(QSize(pWidth, pHeight)); } QGraphicsItem* UBGraphicsScene::rootItem(QGraphicsItem* item) const { QGraphicsItem* root = item; while (root->parentItem()) { root = root->parentItem(); } return root; } void UBGraphicsScene::drawItems (QPainter * painter, int numItems, QGraphicsItem * items[], const QStyleOptionGraphicsItem options[], QWidget * widget) { if (mRenderingContext == NonScreen || mRenderingContext == PdfExport) { int count = 0; QGraphicsItem** itemsFiltered = new QGraphicsItem*[numItems]; QStyleOptionGraphicsItem *optionsFiltered = new QStyleOptionGraphicsItem[numItems]; for (int i = 0; i < numItems; i++) { if (!mTools.contains(rootItem(items[i]))) { UBGraphicsPDFItem *pdfItem = qgraphicsitem_cast (items[i]); if(!pdfItem || mRenderingContext == NonScreen) { itemsFiltered[count] = items[i]; optionsFiltered[count] = options[i]; count++; } } } QGraphicsScene::drawItems(painter, count, itemsFiltered, optionsFiltered, widget); delete[] optionsFiltered; delete[] itemsFiltered; } else if (mRenderingContext == Podcast) { int count = 0; QGraphicsItem** itemsFiltered = new QGraphicsItem*[numItems]; QStyleOptionGraphicsItem *optionsFiltered = new QStyleOptionGraphicsItem[numItems]; for (int i = 0; i < numItems; i++) { bool ok; int itemLayerType = items[i]->data(UBGraphicsItemData::ItemLayerType).toInt(&ok); if (ok && (itemLayerType >= UBItemLayerType::FixedBackground && itemLayerType <= UBItemLayerType::Tool)) { itemsFiltered[count] = items[i]; optionsFiltered[count] = options[i]; count++; } } QGraphicsScene::drawItems(painter, count, itemsFiltered, optionsFiltered, widget); delete[] optionsFiltered; delete[] itemsFiltered; } else { QGraphicsScene::drawItems(painter, numItems, items, options, widget); } } void UBGraphicsScene::keyReleaseEvent(QKeyEvent * keyEvent) { QList si = selectedItems(); if (si.size() > 0 && !keyEvent->isAccepted()) { #ifdef Q_OS_MAC if (keyEvent->key() == Qt::Key_Backspace) #else if (keyEvent->matches(QKeySequence::Delete)) #endif { foreach(QGraphicsItem* item, si) { UBGraphicsItem *ubgi = dynamic_cast(item); if (ubgi) { ubgi->remove(); } } } keyEvent->accept(); } QGraphicsScene::keyReleaseEvent(keyEvent); } void UBGraphicsScene::setDocumentUpdated() { if (document()) document()->setMetaData(UBSettings::documentUpdatedAt , UBStringUtils::toUtcIsoDateTime(QDateTime::currentDateTime())); } void UBGraphicsScene::setToolCursor(int tool) { if (tool != (int)UBStylusTool::Selector && tool != (int)UBStylusTool::Text) { deselectAllItems(); } if (tool != (int)UBStylusTool::Eraser) { hideEraser(); } }