/* * 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 #include #include #include "UBGraphicsItemDelegate.h" #include "UBGraphicsDelegateFrame.h" #include "UBGraphicsScene.h" #include "UBGraphicsItemUndoCommand.h" #include "UBGraphicsItemTransformUndoCommand.h" #include "board/UBBoardController.h" // TODO UB 4.x clean that dependency #include "board/UBBoardView.h" // TODO UB 4.x clean that dependency #include "core/UBApplication.h" #include "core/UBApplicationController.h" #include "core/UBDisplayManager.h" #include "core/UBSettings.h" #include "core/UBPersistenceManager.h" #include "document/UBDocumentProxy.h" #include "UBGraphicsWidgetItem.h" #include "domain/UBAbstractWidget.h" #include "web/UBWebController.h" #include "frameworks/UBFileSystemUtils.h" #include "board/UBDrawingController.h" #include "core/memcheck.h" class UBGraphicsParaschoolEditorWidgetItem; UBGraphicsItemDelegate::UBGraphicsItemDelegate(QGraphicsItem* pDelegated, QObject * parent, bool respectRatio, bool canRotate) : QObject(parent) , mDelegated(pDelegated) , mDeleteButton(NULL) , mDuplicateButton(NULL) , mMenuButton(NULL) , mMenu(0) , mLockAction(0) , mShowOnDisplayAction(0) , mGotoContentSourceAction(0) , mFrame(0) , mFrameWidth(UBSettings::settings()->objectFrameWidth) , mAntiScaleRatio(1.0) , mCanRotate(canRotate) , mCanDuplicate(true) , mRespectRatio(respectRatio) , mMimeData(NULL) { // NOOP } void UBGraphicsItemDelegate::init() { mFrame = new UBGraphicsDelegateFrame(this, QRectF(0, 0, 0, 0), mFrameWidth, mRespectRatio); mFrame->hide(); // mFrame->setZValue(UBGraphicsScene::toolLayerStart + 1); UBGraphicsItem::assignZValue(mFrame, UBGraphicsScene::toolLayerStart + 1); mFrame->setFlag(QGraphicsItem::ItemIsSelectable, true); mDeleteButton = new DelegateButton(":/images/close.svg", mDelegated, mFrame); mButtons << mDeleteButton; connect(mDeleteButton, SIGNAL(clicked()), this, SLOT(remove())); if (canDuplicate()){ mDuplicateButton = new DelegateButton(":/images/duplicate.svg", mDelegated, mFrame); connect(mDuplicateButton, SIGNAL(clicked(bool)), this, SLOT(duplicate())); mButtons << mDuplicateButton; } mMenuButton = new DelegateButton(":/images/menu.svg", mDelegated, mFrame); connect(mMenuButton, SIGNAL(clicked()), this, SLOT(showMenu())); mButtons << mMenuButton; buildButtons(); foreach(DelegateButton* button, mButtons) { button->hide(); // button->setZValue(UBGraphicsScene::toolLayerStart + 2); UBGraphicsItem::assignZValue(button, UBGraphicsScene::toolLayerStart + 2); button->setFlag(QGraphicsItem::ItemIsSelectable, true); } } UBGraphicsItemDelegate::~UBGraphicsItemDelegate() { qDeleteAll(mButtons); // do not release mMimeData. // the mMimeData is owned by QDrag since the setMimeData call as specified in the documentation } QVariant UBGraphicsItemDelegate::itemChange(QGraphicsItem::GraphicsItemChange change, const QVariant &value) { if ((change == QGraphicsItem::ItemSelectedHasChanged || change == QGraphicsItem::ItemPositionHasChanged || change == QGraphicsItem::ItemTransformHasChanged) && mDelegated->scene()) { mAntiScaleRatio = 1 / (UBApplication::boardController->systemScaleFactor() * UBApplication::boardController->currentZoom()); if (mDelegated->isSelected()) { QList items = mDelegated->scene()->selectedItems(); foreach(QGraphicsItem* item, items) { if (item != mDelegated) { item->setSelected(false); } } } positionHandles(); } if (change == QGraphicsItem::ItemPositionHasChanged || change == QGraphicsItem::ItemTransformHasChanged || change == QGraphicsItem::ItemZValueHasChanged) { UBGraphicsScene* ubScene = qobject_cast(mDelegated->scene()); if(ubScene) ubScene->setModified(true); } return value; } bool UBGraphicsItemDelegate::mousePressEvent(QGraphicsSceneMouseEvent *event) { if(NULL != mMimeData) { QDrag* mDrag = new QDrag(event->widget()); mDrag->setMimeData(mMimeData); mDrag->start(); } startUndoStep(); if (!mDelegated->isSelected()) { mDelegated->setSelected(true); UBGraphicsScene* scene = static_cast(mDelegated->scene()); qDebug() << mDelegated->zValue(); qDebug() << scene->currentObjectZIndex(); // To investigate. Z value behavior // if (mDelegated->zValue() < scene->currentObjectZIndex() && !isLocked()) // mDelegated->setZValue(scene->getNextObjectZIndex()); positionHandles(); return true; } else { return false; } } void UBGraphicsItemDelegate::setMimeData(QMimeData *mimeData) { mMimeData = mimeData; } bool UBGraphicsItemDelegate::mouseMoveEvent(QGraphicsSceneMouseEvent *event) { if(isLocked()) { event->accept(); return true; } else return false; } bool UBGraphicsItemDelegate::weelEvent(QGraphicsSceneWheelEvent *event) { Q_UNUSED(event); if( mDelegated->isSelected() ) { // event->accept(); return true; } else { // event->ignore(); return false; } } bool UBGraphicsItemDelegate::mouseReleaseEvent(QGraphicsSceneMouseEvent *event) { Q_UNUSED(event); commitUndoStep(); return true; } void UBGraphicsItemDelegate::positionHandles() { if (mDelegated->isSelected()) { if (mFrame && !mFrame->scene() && mDelegated->scene()) { mDelegated->scene()->addItem(mFrame); } mFrame->setAntiScale(mAntiScaleRatio); mFrame->positionHandles(); mFrame->show(); QTransform tr; tr.scale(mAntiScaleRatio, mAntiScaleRatio); mDeleteButton->setTransform(tr); qreal x = mFrame->rect().left()- mDeleteButton->renderer()->viewBox().width() * mAntiScaleRatio / 2; qreal y = mFrame->rect().top() - mDeleteButton->renderer()->viewBox().height() * mAntiScaleRatio / 2; mDeleteButton->setPos(x, y); if (!mDeleteButton->scene()) { mDeleteButton->setParentItem(mFrame);//update parent for the case the item has been previously removed from scene if (mDelegated->scene()) mDelegated->scene()->addItem(mDeleteButton); } mDeleteButton->show(); bool shownOnDisplay = mDelegated->data(UBGraphicsItemData::ItemLayerType).toInt() != UBItemLayerType::Control; showHide(shownOnDisplay); lock(isLocked()); for(int i = 1 ; i < mButtons.length(); i++) { DelegateButton* button = mButtons[i]; button->setTransform(tr); button->setPos(x + (i * 1.6 * mFrameWidth * mAntiScaleRatio), y); if (!button->scene()) { button->setParentItem(mFrame);//update parent for the case the item has been previously removed from scene if (mDelegated->scene()) mDelegated->scene()->addItem(button); } button->show(); } } else { foreach(DelegateButton* button, mButtons) button->hide(); mFrame->hide(); } } void UBGraphicsItemDelegate::remove(bool canUndo) { // QGraphicsScene* scene = mDelegated->scene(); UBGraphicsScene* scene = (UBGraphicsScene*)(mDelegated->scene()); if (scene) { foreach(DelegateButton* button, mButtons) scene->removeItem(button); scene->removeItem(mFrame); scene->removeItem(mDelegated); if (canUndo) { UBGraphicsItemUndoCommand *uc = new UBGraphicsItemUndoCommand((UBGraphicsScene*) scene, mDelegated, 0); UBApplication::undoStack->push(uc); } } } bool UBGraphicsItemDelegate::isLocked() { return mDelegated->data(UBGraphicsItemData::ItemLocked).toBool(); } void UBGraphicsItemDelegate::duplicate() { // TODO UB 4.x .. rewrite .. .this is absurde ... we know what we are duplicating UBApplication::boardController->copy(); UBApplication::boardController->paste(); } void UBGraphicsItemDelegate::lock(bool locked) { if (locked) { mDelegated->setData(UBGraphicsItemData::ItemLocked, QVariant(true)); } else { mDelegated->setData(UBGraphicsItemData::ItemLocked, QVariant(false)); } mDelegated->update(); mFrame->positionHandles(); } void UBGraphicsItemDelegate::showHide(bool show) { if (show) { mDelegated->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Object)); } else { mDelegated->setData(UBGraphicsItemData::ItemLayerType, QVariant(UBItemLayerType::Control)); } mDelegated->update(); emit showOnDisplayChanged(show); } void UBGraphicsItemDelegate::gotoContentSource(bool checked) { Q_UNUSED(checked) UBItem* item = dynamic_cast(mDelegated); if(item && !item->sourceUrl().isEmpty()) { UBApplication::applicationController->showInternet(); UBApplication::webController->loadUrl(item->sourceUrl()); } } void UBGraphicsItemDelegate::startUndoStep() { mPreviousPosition = mDelegated->pos(); mPreviousTransform = mDelegated->transform(); mPreviousZValue = mDelegated->zValue(); UBResizableGraphicsItem* resizableItem = dynamic_cast(mDelegated); if (resizableItem) mPreviousSize = resizableItem->size(); else mPreviousSize = QSizeF(); } void UBGraphicsItemDelegate::commitUndoStep() { UBResizableGraphicsItem* resizableItem = dynamic_cast(mDelegated); if (mDelegated->pos() != mPreviousPosition || mDelegated->transform() != mPreviousTransform || mDelegated->zValue() != mPreviousZValue || (resizableItem && resizableItem->size() != mPreviousSize)) { UBGraphicsItemTransformUndoCommand *uc = new UBGraphicsItemTransformUndoCommand(mDelegated, mPreviousPosition, mPreviousTransform, mPreviousZValue, mPreviousSize); UBApplication::undoStack->push(uc); } } void UBGraphicsItemDelegate::decorateMenu(QMenu* menu) { mLockAction = menu->addAction(tr("Locked"), this, SLOT(lock(bool))); QIcon lockIcon; lockIcon.addPixmap(QPixmap(":/images/locked.svg"), QIcon::Normal, QIcon::On); lockIcon.addPixmap(QPixmap(":/images/unlocked.svg"), QIcon::Normal, QIcon::Off); mLockAction->setIcon(lockIcon); mLockAction->setCheckable(true); mShowOnDisplayAction = mMenu->addAction(tr("Visible on Extended Screen"), this, SLOT(showHide(bool))); mShowOnDisplayAction->setCheckable(true); QIcon showIcon; showIcon.addPixmap(QPixmap(":/images/eyeOpened.svg"), QIcon::Normal, QIcon::On); showIcon.addPixmap(QPixmap(":/images/eyeClosed.svg"), QIcon::Normal, QIcon::Off); mShowOnDisplayAction->setIcon(showIcon); mGotoContentSourceAction = menu->addAction(tr("Go to Content Source"), this, SLOT(gotoContentSource(bool))); QIcon sourceIcon; sourceIcon.addPixmap(QPixmap(":/images/toolbar/internet.png"), QIcon::Normal, QIcon::On); mGotoContentSourceAction->setIcon(sourceIcon); } void UBGraphicsItemDelegate::updateMenuActionState() { if (mLockAction) mLockAction->setChecked(isLocked()); if (mShowOnDisplayAction) { bool isControl = mDelegated->data(UBGraphicsItemData::ItemLayerType) == UBItemLayerType::Control; mShowOnDisplayAction->setChecked(!isControl); } if (mGotoContentSourceAction) { UBItem* item = dynamic_cast(mDelegated); mGotoContentSourceAction->setEnabled(item && !item->sourceUrl().isEmpty()); } } void UBGraphicsItemDelegate::showMenu() { if (!mMenu) { mMenu = new QMenu(UBApplication::boardController->controlView()); decorateMenu(mMenu); } updateMenuActionState(); UBBoardView* cv = UBApplication::boardController->controlView(); QRect pinPos = cv->mapFromScene(mMenuButton->sceneBoundingRect()).boundingRect(); mMenu->exec(cv->mapToGlobal(pinPos.bottomRight())); }