File indexing completed on 2024-04-28 05:38:12

0001 /***************************************************************************
0002  *      Copyright (C) 2010 by Renaud Guezennec                             *
0003  *                                                                         *
0004  *                                                                         *
0005  *   rolisteam is free software; you can redistribute it and/or modify     *
0006  *   it under the terms of the GNU General Public License as published by  *
0007  *   the Free Software Foundation; either version 2 of the License, or     *
0008  *   (at your option) any later version.                                   *
0009  *                                                                         *
0010  *   This program is distributed in the hope that it will be useful,       *
0011  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0012  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0013  *   GNU General Public License for more details.                          *
0014  *                                                                         *
0015  *   You should have received a copy of the GNU General Public License     *
0016  *   along with this program; if not, write to the                         *
0017  *   Free Software Foundation, Inc.,                                       *
0018  *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
0019  ***************************************************************************/
0020 #include "visualitem.h"
0021 #include <QActionGroup>
0022 #include <QCursor>
0023 #include <QDebug>
0024 #include <QGraphicsSceneHoverEvent>
0025 #include <QGuiApplication>
0026 #include <QKeyEvent>
0027 #include <QMenu>
0028 #include <QUuid>
0029 #include <cmath>
0030 
0031 #include <QGraphicsScene>
0032 
0033 #include "controller/item_controllers/visualitemcontroller.h"
0034 #include "controller/view_controller/vectorialmapcontroller.h"
0035 
0036 QColor VisualItem::m_highlightColor= QColor(Qt::red);
0037 QColor VisualItem::m_selectedColor= QColor(Qt::blue);
0038 int VisualItem::m_highlightWidth= 6;
0039 
0040 QStringList VisualItem::s_type2NameList
0041     = QStringList() << QObject::tr("Path") << QObject::tr("Line") << QObject::tr("Ellipse") << QObject::tr("Character")
0042                     << QObject::tr("Text") << QObject::tr("Rect") << QObject::tr("Rule") << QObject::tr("Image");
0043 
0044 VisualItem::VisualItem(vmap::VisualItemController* ctrl) : QGraphicsObject(), m_ctrl(ctrl)
0045 {
0046     if(!m_ctrl)
0047         return;
0048 
0049     connect(m_ctrl, &vmap::VisualItemController::posChanged, this, [this]() { setPos(m_ctrl->pos()); });
0050     connect(m_ctrl, &vmap::VisualItemController::removeItem, this,
0051             [this]()
0052             {
0053                 auto sceneP = scene();
0054                 if(sceneP)
0055                     sceneP->removeItem(this);
0056                 deleteLater();
0057             });
0058     connect(m_ctrl, &vmap::VisualItemController::destroyed, this,
0059             [this]()
0060             {
0061                 auto sceneP = scene();
0062                 if(sceneP)
0063                     sceneP->removeItem(this);
0064                 deleteLater();
0065             });
0066     auto func= [this]()
0067     {
0068         if(m_ctrl->editable())
0069             m_ctrl->setPos(pos());
0070     };
0071     connect(this, &VisualItem::xChanged, this, func);
0072     connect(this, &VisualItem::yChanged, this, func);
0073 
0074     // connect(this, &VisualItem::rotationChanged, this, [this]() { m_ctrl->setRotation(rotation()); });
0075 
0076     connect(m_ctrl, &vmap::VisualItemController::colorChanged, this, [this]() { update(); });
0077     connect(m_ctrl, &vmap::VisualItemController::editableChanged, this, &VisualItem::updateItemFlags);
0078     connect(m_ctrl, &vmap::VisualItemController::rotationChanged, this, [this]() { setRotation(m_ctrl->rotation()); });
0079     connect(m_ctrl, &vmap::VisualItemController::selectedChanged, this, [this](bool b) { setSelected(b); });
0080     connect(m_ctrl, &vmap::VisualItemController::selectableChanged, this, &VisualItem::updateItemFlags);
0081 
0082     connect(m_ctrl, &vmap::VisualItemController::visibleChanged, this, &VisualItem::evaluateVisible);
0083     connect(m_ctrl, &vmap::VisualItemController::visibilityChanged, this, &VisualItem::evaluateVisible);
0084     connect(m_ctrl, &vmap::VisualItemController::opacityChanged, this, [this]() { setOpacity(m_ctrl->opacity()); });
0085     connect(m_ctrl, &vmap::VisualItemController::layerChanged, this,
0086             [this]() { setOpacity(m_ctrl->layer() == Core::Layer::GAMEMASTER_LAYER ? 0.5 : 1.0); });
0087 
0088     init();
0089 
0090     connect(m_ctrl, &vmap::VisualItemController::zOrderChanged, this, [this](qreal z) { setZValue(z); });
0091 
0092     setPos(m_ctrl->pos());
0093     evaluateVisible();
0094 
0095     updateItemFlags();
0096     setOpacity(m_ctrl->layer() == Core::Layer::GAMEMASTER_LAYER ? 0.5 : 1.0);
0097 }
0098 
0099 VisualItem::~VisualItem() {}
0100 
0101 void VisualItem::evaluateVisible()
0102 {
0103     // qDebug() << "debug item visibility: Item is visible:" << m_ctrl->visible() << "local is gm:" <<
0104     // m_ctrl->localIsGM()
0105     //        << "visiblitiy:" << m_ctrl->visibility() << m_ctrl->tool() << m_ctrl->itemType();
0106     auto localIsGM= m_ctrl->localIsGM();
0107     auto visibleFromPermission= localIsGM || m_ctrl->visibility() != Core::HIDDEN;
0108     auto visibleLayer= localIsGM || m_ctrl->layer() != Core::Layer::GAMEMASTER_LAYER;
0109     setVisible(m_ctrl->visible() && visibleFromPermission && visibleLayer);
0110 }
0111 void VisualItem::init()
0112 {
0113 
0114     setAcceptHoverEvents(true);
0115     setFlag(QGraphicsItem::ItemUsesExtendedStyleOption, true);
0116     /*QActionGroup* group= new QActionGroup(this);
0117     m_putGroundLayer= new QAction(m_ctrl->getLayerText(Core::Layer::GROUND), this);
0118     m_putGroundLayer->setData(static_cast<int>(Core::Layer::GROUND));
0119     m_putObjectLayer= new QAction(m_ctrl->getLayerText(Core::Layer::OBJECT), this);
0120     m_putObjectLayer->setData(static_cast<int>(Core::Layer::OBJECT));
0121     m_putCharacterLayer= new QAction(m_ctrl->getLayerText(Core::Layer::CHARACTER_LAYER), this);
0122     m_putCharacterLayer->setData(static_cast<int>(Core::Layer::CHARACTER_LAYER));
0123 
0124     m_putGameMasterLayer= new QAction(m_ctrl->getLayerText(Core::Layer::GAMEMASTER_LAYER), this);
0125     m_putGameMasterLayer->setData(static_cast<int>(Core::Layer::GAMEMASTER_LAYER));
0126 
0127     m_putGroundLayer->setCheckable(true);
0128     m_putObjectLayer->setCheckable(true);
0129     m_putCharacterLayer->setCheckable(true);
0130     m_putGameMasterLayer->setCheckable(true);
0131 
0132     m_putGroundLayer->setChecked(true);
0133 
0134     group->addAction(m_putGroundLayer);
0135     group->addAction(m_putObjectLayer);
0136     group->addAction(m_putCharacterLayer);
0137     group->addAction(m_putGameMasterLayer);*/
0138 }
0139 vmap::VisualItemController* VisualItem::controller() const
0140 {
0141     return m_ctrl;
0142 }
0143 
0144 vmap::VisualItemController::ItemType VisualItem::getType() const
0145 {
0146     return m_ctrl->itemType();
0147 }
0148 
0149 void VisualItem::updateItemFlags()
0150 {
0151     GraphicsItemFlags flags= QGraphicsItem::ItemIsFocusable;
0152     Qt::MouseButtons buttons= Qt::NoButton;
0153 
0154     if(m_ctrl->editable())
0155     {
0156         flags
0157             |= QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemSendsGeometryChanges | QGraphicsItem::ItemIsMovable;
0158         buttons= Qt::AllButtons;
0159     }
0160 
0161     setAcceptedMouseButtons(buttons);
0162     setFlags(flags);
0163 
0164     for(auto& itemChild : m_children)
0165     {
0166         itemChild->setEditableItem(m_ctrl->editable());
0167     }
0168 }
0169 
0170 QColor VisualItem::color() const
0171 {
0172     return m_ctrl->color();
0173 }
0174 
0175 void VisualItem::setColor(QColor color)
0176 {
0177     m_ctrl->setColor(color);
0178 }
0179 
0180 void VisualItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
0181 {
0182     QGraphicsItem::mousePressEvent(event);
0183     update();
0184 }
0185 void VisualItem::mouseMoveEvent(QGraphicsSceneMouseEvent* event)
0186 {
0187     QGraphicsItem::mouseMoveEvent(event);
0188     update();
0189 }
0190 void VisualItem::mouseReleaseEvent(QGraphicsSceneMouseEvent* event)
0191 {
0192     QGraphicsItem::mouseReleaseEvent(event);
0193     update();
0194     endOfGeometryChange(ChildPointItem::Moving);
0195 }
0196 
0197 QVariant VisualItem::itemChange(GraphicsItemChange change, const QVariant& value)
0198 {
0199     if(change == ItemPositionChange)
0200     {
0201         QPointF newPos= computeClosePoint(value.toPointF());
0202         if(newPos != value.toPointF())
0203         {
0204             return newPos;
0205         }
0206     }
0207     return QGraphicsItem::itemChange(change, value);
0208 }
0209 
0210 QString VisualItem::uuid() const
0211 {
0212     return m_ctrl ? m_ctrl->uuid() : QString();
0213 }
0214 
0215 QPointF VisualItem::computeClosePoint(QPointF pos)
0216 {
0217     if(Qt::AltModifier & QGuiApplication::keyboardModifiers())
0218     {
0219         int size= m_ctrl->gridSize();
0220         pos.setX(std::round(pos.x() / size) * size);
0221         pos.setY(std::round(pos.y() / size) * size);
0222     }
0223     return pos;
0224 }
0225 void VisualItem::keyPressEvent(QKeyEvent* event)
0226 {
0227     if((event->key() == Qt::Key_Delete) && (isSelected()) && canBeMoved())
0228     {
0229         // m_ctrl->rem
0230     }
0231     else if((event->key() == Qt::Key_C) && (event->modifiers() == Qt::ControlModifier) && (isSelected()))
0232     {
0233         // emit duplicateItem(this);
0234         event->accept();
0235     }
0236     QGraphicsItem::keyPressEvent(event);
0237 }
0238 
0239 void VisualItem::resizeContents(const QRectF& rect, int pointId, Core::TransformType transformType)
0240 {
0241     /*    if(!rect.isValid() || isHoldSize())
0242         {
0243             return;
0244         }
0245         prepareGeometryChange();
0246         auto width= m_ctrl->rect().width();
0247         auto height= m_ctrl->rect().height();
0248         // sendRectGeometryMsg();
0249         m_resizing= true;
0250         m_rect= rect;
0251         if(transformType == VisualItem::KeepRatio)
0252         {
0253             auto hfw= height * rect.width() / width;
0254             if(hfw > 1)
0255             {
0256                 m_rect.setTop(-hfw / 2);
0257                 m_rect.setHeight(hfw);
0258             }
0259         }
0260 
0261         updateChildPosition();*/
0262 }
0263 void VisualItem::updateChildPosition() {}
0264 
0265 void VisualItem::addPromoteItemMenu(QMenu* menu)
0266 {
0267     for(auto& type : m_promoteTypeList)
0268     {
0269         QAction* action= menu->addAction(s_type2NameList[type]);
0270         action->setData(type);
0271         connect(action, SIGNAL(triggered()), this, SLOT(promoteItem()));
0272     }
0273 }
0274 void VisualItem::promoteItem()
0275 {
0276     QAction* act= qobject_cast<QAction*>(sender());
0277     if(nullptr != act)
0278     {
0279         auto type= static_cast<vmap::VisualItemController::ItemType>(act->data().toInt());
0280         emit promoteItemTo(this, type);
0281     }
0282 }
0283 
0284 void VisualItem::addActionContextMenu(QMenu& menu) {}
0285 
0286 bool VisualItem::hasFocusOrChild()
0287 {
0288     if(!m_ctrl)
0289         return false;
0290 
0291     if(!m_ctrl->editable())
0292         return false;
0293 
0294     auto result= isSelected();
0295     for(auto const& child : qAsConst(m_children))
0296     {
0297         if(nullptr == child)
0298             continue;
0299 
0300         if(child->isSelected())
0301         {
0302             result= true;
0303         }
0304     }
0305     return result;
0306 }
0307 
0308 bool VisualItem::isLocal() const
0309 {
0310     return !m_ctrl->remote();
0311 }
0312 
0313 void VisualItem::endOfGeometryChange(ChildPointItem::Change change)
0314 {
0315     if(change == ChildPointItem::Resizing)
0316     {
0317         auto oldScenePos= scenePos();
0318         setTransformOriginPoint(m_ctrl->rect().center());
0319         auto newScenePos= scenePos();
0320         auto oldPos= pos();
0321         m_ctrl->setPos(QPointF(oldPos.x() + (oldScenePos.x() - newScenePos.x()),
0322                                oldPos.y() + (oldScenePos.y() - newScenePos.y())));
0323     }
0324     m_ctrl->endGeometryChange();
0325 }
0326 
0327 void VisualItem::setModifiers(Qt::KeyboardModifiers modifiers)
0328 {
0329     Q_UNUSED(modifiers)
0330     /// @brief must be implemented in child classes.
0331     return;
0332 }
0333 VisualItem* VisualItem::promoteTo(vmap::VisualItemController::ItemType type)
0334 {
0335     Q_UNUSED(type)
0336     /// @brief must be implemented in child classes.
0337     return nullptr;
0338 }
0339 
0340 void VisualItem::setChildrenVisible(bool b)
0341 {
0342     if(!b)
0343     {
0344         std::for_each(std::begin(m_children), std::end(m_children),
0345                       [](ChildPointItem* item) { item->setVisible(false); });
0346         return;
0347     }
0348 
0349     if(!canBeMoved())
0350         return;
0351 
0352     for(auto& item : m_children)
0353     {
0354         bool isVision= item->control() == ChildPointItem::Control::Vision;
0355         bool hasFog= m_ctrl->visibility() == Core::FOGOFWAR;
0356         bool isGeometry= item->control() == ChildPointItem::Control::Geometry;
0357 
0358         item->setVisible(isGeometry || (isVision && hasFog));
0359     }
0360 }
0361 
0362 bool VisualItem::canBeMoved() const
0363 {
0364     return m_ctrl->editable();
0365 }
0366 
0367 QColor VisualItem::getHighlightColor()
0368 {
0369     return m_highlightColor;
0370 }
0371 
0372 void VisualItem::setHighlightColor(const QColor& highlightColor)
0373 {
0374     m_highlightColor= highlightColor;
0375 }
0376 
0377 int VisualItem::getHighlightWidth()
0378 {
0379     return m_highlightWidth;
0380 }
0381 
0382 void VisualItem::setHighlightWidth(int highlightWidth)
0383 {
0384     m_highlightWidth= highlightWidth;
0385 }
0386 
0387 void VisualItem::setSize(QSizeF size)
0388 {
0389     updateChildPosition();
0390     update();
0391 }