File indexing completed on 2024-05-12 05:39:37

0001 /***************************************************************************
0002  * Copyright (C) 2014 by Renaud Guezennec                                   *
0003  * http://www.rolisteam.org/                                                *
0004  *                                                                          *
0005  *  This file is part of rcse                                               *
0006  *                                                                          *
0007  * rcse is free software; you can redistribute it and/or modify             *
0008  * it under the terms of the GNU General Public License as published by     *
0009  * the Free Software Foundation; either version 2 of the License, or        *
0010  * (at your option) any later version.                                      *
0011  *                                                                          *
0012  * rcse is distributed in the hope that it will be useful,                  *
0013  * but WITHOUT ANY WARRANTY; without even the implied warranty of           *
0014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the             *
0015  * GNU General Public License for more details.                             *
0016  *                                                                          *
0017  * You should have received a copy of the GNU General Public License        *
0018  * along with this program; if not, write to the                            *
0019  * Free Software Foundation, Inc.,                                          *
0020  * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.                 *
0021  ***************************************************************************/
0022 #include "canvas.h"
0023 #include <QDebug>
0024 #include <QGraphicsSceneDragDropEvent>
0025 #include <QMimeData>
0026 #include <QUrl>
0027 #include <cmath>
0028 #include <QCryptographicHash>
0029 
0030 #include "undo/addfieldcommand.h"
0031 #include "undo/deletefieldcommand.h"
0032 #include "undo/movefieldcommand.h"
0033 #include "undo/setbackgroundimage.h"
0034 #include "utils/iohelper.h"
0035 #include "controllers/editorcontroller.h"
0036 #include "controllers/imagecontroller.h"
0037 
0038 #include "tablecanvasfield.h"
0039 
0040 //#include "charactersheetbutton.h"
0041 
0042 Canvas::Canvas(EditorController* ctrl, QObject* parent)
0043     : QGraphicsScene(parent), m_ctrl(ctrl), m_bg(new QGraphicsPixmapItem()), m_currentItem(nullptr), m_model(nullptr)
0044 {
0045     setSceneRect(QRect(0, 0, 800, 600));
0046     m_bg->setFlag(QGraphicsItem::ItemIsSelectable, false);
0047     m_bg->setFlag(QGraphicsItem::ItemSendsGeometryChanges, false);
0048     m_bg->setFlag(QGraphicsItem::ItemIsMovable, false);
0049     m_bg->setFlag(QGraphicsItem::ItemIsFocusable, false);
0050     m_bg->setAcceptedMouseButtons(Qt::NoButton);
0051 }
0052 
0053 void Canvas::dragEnterEvent(QGraphicsSceneDragDropEvent* event)
0054 {
0055     const QMimeData* mimeData= event->mimeData();
0056     if(mimeData->hasUrls())
0057     {
0058         event->acceptProposedAction();
0059     }
0060 }
0061 
0062 void Canvas::dragMoveEvent(QGraphicsSceneDragDropEvent* event)
0063 {
0064     event->acceptProposedAction();
0065 }
0066 void Canvas::dropEvent(QGraphicsSceneDragDropEvent* event)
0067 {
0068     const QMimeData* mimeData= event->mimeData();
0069     if(mimeData->hasUrls())
0070     {
0071         for(const QUrl& url : mimeData->urls())
0072         {
0073             if(url.isLocalFile())
0074             {
0075                 emit dropFileOnCanvas(url);
0076             }
0077         }
0078     }
0079 }
0080 
0081 void Canvas::setCurrentTool(Canvas::Tool tool)
0082 {
0083     m_currentTool= tool;
0084     if(nullptr != m_currentItem)
0085     {
0086         m_currentItem= nullptr;
0087     }
0088 }
0089 void Canvas::deleteItem(QGraphicsItem* item)
0090 {
0091     auto fieldItem= dynamic_cast<CanvasField*>(item);
0092     if(nullptr != fieldItem)
0093     {
0094         DeleteFieldCommand* deleteCommand= new DeleteFieldCommand(fieldItem->controller(), this, m_model, m_pageId);
0095         emit performCommand(deleteCommand);
0096     }
0097 }
0098 void Canvas::mousePressEvent(QGraphicsSceneMouseEvent* mouseEvent)
0099 {
0100     if(mouseEvent->button() == Qt::RightButton)
0101     {
0102         mouseEvent->accept();
0103         return;
0104     }
0105 
0106     if(mouseEvent->button() != Qt::LeftButton)
0107         QGraphicsScene::mousePressEvent(mouseEvent);
0108 
0109     if(forwardEvent())
0110     {
0111         m_oldPos.clear();
0112         QPointF mousePos(mouseEvent->buttonDownScenePos(Qt::LeftButton).x(),
0113                          mouseEvent->buttonDownScenePos(Qt::LeftButton).y());
0114         const QList<QGraphicsItem*> itemList= items(mousePos);
0115         m_movingItems.append(itemList.isEmpty() ? nullptr : itemList.first());
0116 
0117         if(m_movingItems.first() != nullptr && mouseEvent->button() == Qt::LeftButton)
0118         {
0119             m_oldPos.append(m_movingItems.first()->pos());
0120         }
0121 
0122         // clearSelection();
0123         QGraphicsScene::mousePressEvent(mouseEvent);
0124     }
0125     if(m_currentTool == Canvas::DELETETOOL)
0126     {
0127         QList<QGraphicsItem*> itemList= items(mouseEvent->scenePos());
0128         for(QGraphicsItem* item : itemList)
0129         {
0130             if(item != m_bg)
0131             {
0132                 deleteItem(item);
0133             }
0134         }
0135         mouseEvent->accept();
0136     }
0137     else if((m_currentTool <= Canvas::ADDCHECKBOX) || (m_currentTool == Canvas::BUTTON))
0138     {
0139         auto imageController= m_ctrl->imageController();
0140 
0141         charactersheet::ImageModel* model= nullptr;
0142         if(nullptr != imageController)
0143             model= imageController->model();
0144 
0145         AddFieldCommand* addCommand
0146             = new AddFieldCommand(m_currentTool, this, m_model, m_pageId, model, mouseEvent->scenePos());
0147 
0148         emit performCommand(addCommand);
0149         mouseEvent->accept();
0150     }
0151 
0152     QGraphicsScene::mousePressEvent(mouseEvent);
0153 }
0154 void Canvas::mouseMoveEvent(QGraphicsSceneMouseEvent* mouseEvent)
0155 {
0156     if(forwardEvent())
0157     {
0158         QGraphicsScene::mouseMoveEvent(mouseEvent);
0159     }
0160     else if(m_currentItem != nullptr)
0161     {
0162         m_currentItem->setNewEnd(m_currentItem->mapFromScene(mouseEvent->scenePos()));
0163         update();
0164     }
0165 }
0166 bool Canvas::forwardEvent()
0167 {
0168     return (Canvas::MOVE == m_currentTool) || (Canvas::NONE == m_currentTool);
0169 }
0170 
0171 void Canvas::mouseReleaseEvent(QGraphicsSceneMouseEvent* mouseEvent)
0172 {
0173     Q_UNUSED(mouseEvent);
0174 
0175     if(forwardEvent())
0176     {
0177         if(!m_movingItems.isEmpty())
0178         {
0179             if(m_movingItems.first() != nullptr && mouseEvent->button() == Qt::LeftButton)
0180             {
0181                 if(m_oldPos.first() != m_movingItems.first()->pos())
0182                 {
0183                     MoveFieldCommand* moveCmd= new MoveFieldCommand(m_movingItems, m_oldPos);
0184                     emit performCommand(moveCmd);
0185                 }
0186                 m_movingItems.clear();
0187                 m_oldPos.clear();
0188             }
0189         }
0190         QGraphicsScene::mouseReleaseEvent(mouseEvent);
0191     }
0192     else
0193     {
0194         adjustNewItem(m_currentItem);
0195         m_currentItem= nullptr;
0196     }
0197 }
0198 void Canvas::adjustNewItem(CanvasField* field)
0199 {
0200     if(nullptr == field)
0201         return;
0202 
0203     auto ctrl= field->controller();
0204     if(ctrl->width() < 0)
0205     {
0206         ctrl->setX(ctrl->x() + ctrl->width());
0207         ctrl->setWidth(fabs(ctrl->width()));
0208     }
0209 
0210     if(ctrl->height() < 0)
0211     {
0212         ctrl->setY(ctrl->y() + ctrl->height());
0213         ctrl->setHeight(fabs(ctrl->height()));
0214     }
0215 }
0216 
0217 void Canvas::addField(CSItem* itemCtrl)
0218 {
0219     CanvasField* cf= nullptr;
0220     switch(itemCtrl->itemType())
0221     {
0222     case TreeSheetItem::FieldItem:
0223         cf= new CanvasField(dynamic_cast<FieldController*>(itemCtrl));
0224         break;
0225     case TreeSheetItem::TableItem:
0226         cf= new TableCanvasField(dynamic_cast<FieldController*>(itemCtrl));
0227         break;
0228     default:
0229         break;
0230     }
0231     if(cf)
0232     {
0233         m_currentItem= cf;
0234         addItem(m_currentItem);
0235         m_currentItem->setPos({itemCtrl->x(), itemCtrl->y()});
0236     }
0237 }
0238 
0239 Canvas::Tool Canvas::currentTool() const
0240 {
0241     return m_currentTool;
0242 }
0243 
0244 int Canvas::pageId() const
0245 {
0246     return m_pageId;
0247 }
0248 
0249 void Canvas::setPageId(int pageId)
0250 {
0251     if(pageId == m_pageId)
0252         return;
0253     m_pageId= pageId;
0254     emit pageIdChanged();
0255 }
0256 FieldModel* Canvas::model() const
0257 {
0258     return m_model;
0259 }
0260 
0261 void Canvas::setModel(FieldModel* model)
0262 {
0263     m_model= model;
0264 }
0265 
0266 const QPixmap Canvas::pixmap() const
0267 {
0268     return m_bg ? m_bg->pixmap() : QPixmap();
0269 }
0270 void Canvas::setPixmap(const QPixmap& pix)
0271 {
0272     static QString md5;
0273     auto key = QCryptographicHash::hash(utils::IOHelper::imageToData(pix.toImage()), QCryptographicHash::Md5);
0274 
0275     if(md5 == key)
0276         return;
0277     m_bg->setPixmap(pix);
0278     emit pixmapChanged();
0279 
0280     if(pix.isNull())
0281         removeItem(m_bg);
0282     else
0283     {
0284         addItem(m_bg);
0285         setSceneRect(m_bg->boundingRect());
0286     }
0287     md5 = key;
0288 }