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

0001 #include "itemeditor.h"
0002 
0003 #include <QDebug>
0004 #include <QGraphicsPixmapItem>
0005 #include <QMenu>
0006 #include <QMouseEvent>
0007 
0008 #include "canvasfield.h"
0009 #include "charactersheet/controllers/fieldcontroller.h"
0010 #include "controllers/editorcontroller.h"
0011 
0012 QList<FieldController*> cleanSelection(const QList<QGraphicsItem*>& items, bool& locked, bool& allSame)
0013 {
0014     QList<FieldController*> res;
0015 
0016     auto func= [](QGraphicsItem* item) {
0017         auto field= dynamic_cast<CanvasField*>(item);
0018         if(nullptr == field)
0019             return false;
0020         return static_cast<bool>(field->flags() & QGraphicsItem::ItemIsMovable);
0021     };
0022 
0023     allSame= std::all_of(std::begin(items), std::end(items), [](QGraphicsItem* item) {
0024         auto field= dynamic_cast<CanvasField*>(item);
0025         if(nullptr == field)
0026             return false;
0027         return static_cast<bool>(field->flags() & QGraphicsItem::ItemIsMovable);
0028     });
0029 
0030     if(!items.isEmpty())
0031         locked= func(items.first());
0032     else
0033         locked= false;
0034 
0035     std::transform(std::begin(items), std::end(items), std::back_inserter(res),
0036                    [](QGraphicsItem* item) -> FieldController* {
0037                        auto field= dynamic_cast<CanvasField*>(item);
0038                        if(!field)
0039                            return nullptr;
0040 
0041                        return field->controller();
0042                    });
0043 
0044     res.removeAll(nullptr);
0045 
0046     return res;
0047 }
0048 
0049 ItemEditor::ItemEditor(QWidget* parent) : QGraphicsView(parent)
0050 {
0051     setAcceptDrops(true);
0052     setViewportUpdateMode(QGraphicsView::FullViewportUpdate);
0053     setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing | QPainter::SmoothPixmapTransform);
0054     setRubberBandSelectionMode(Qt::IntersectsItemBoundingRect);
0055     setOptimizationFlag(QGraphicsView::DontAdjustForAntialiasing);
0056     setAlignment((Qt::AlignLeft | Qt::AlignTop));
0057 
0058     m_fitInView.reset(new QAction(tr("Fit the view")));
0059     m_fitInView->setCheckable(true);
0060 
0061     m_lockItem.reset(new QAction(tr("Lock item")));
0062     m_lockItem->setCheckable(true);
0063     m_alignOnY.reset(new QAction(tr("Align on Y")));
0064     m_alignOnX.reset(new QAction(tr("Align on X")));
0065     m_sameWidth.reset(new QAction(tr("Same Width")));
0066     m_sameHeight.reset(new QAction(tr("Same Height")));
0067     m_dupplicate.reset(new QAction(tr("Dupplicate")));
0068     m_verticalEquaDistance.reset(new QAction(tr("Vertical equidistribution")));
0069     m_horizontalEquaDistance.reset(new QAction(tr("Horizontal equidistribution")));
0070 }
0071 
0072 void ItemEditor::setController(EditorController* editCtrl)
0073 {
0074     m_ctrl= editCtrl;
0075 
0076     connect(m_ctrl, &EditorController::dataChanged, this, [this]() { invalidateScene(); });
0077     connect(m_lockItem.get(), &QAction::triggered, this, [this](bool checked) {
0078         std::for_each(std::begin(m_selection), std::end(m_selection), [checked](FieldController* ctrl) {
0079             if(!ctrl)
0080                 return;
0081             ctrl->setReadOnly(checked);
0082         });
0083     });
0084     connect(m_fitInView.get(), &QAction::triggered, this, [this](bool checked) {
0085         if(checked)
0086         {
0087             const QPixmap& pix= m_ctrl->backgroundFromIndex(m_ctrl->currentPage());
0088             fitInView(QRectF(pix.rect()), Qt::KeepAspectRatioByExpanding);
0089         }
0090         else
0091         {
0092             fitInView(rect());
0093         }
0094     });
0095     connect(m_alignOnY.get(), &QAction::triggered, this,
0096             [this]() { m_ctrl->alignOn(false, m_selection, m_underCursorItem); });
0097     connect(m_alignOnX.get(), &QAction::triggered, this,
0098             [this]() { m_ctrl->alignOn(true, m_selection, m_underCursorItem); });
0099 
0100     connect(m_sameWidth.get(), &QAction::triggered, this,
0101             [this]() { m_ctrl->sameGeometry(true, m_selection, m_underCursorItem); });
0102     connect(m_sameHeight.get(), &QAction::triggered, this,
0103             [this]() { m_ctrl->sameGeometry(false, m_selection, m_underCursorItem); });
0104 
0105     connect(m_verticalEquaDistance.get(), &QAction::triggered, this,
0106             [this]() { m_ctrl->spreadItemEqualy(m_selection, false); });
0107     connect(m_horizontalEquaDistance.get(), &QAction::triggered, this,
0108             [this]() { m_ctrl->spreadItemEqualy(m_selection, true); });
0109 
0110     connect(m_ctrl, &EditorController::currentPageChanged, this, [this]() {
0111         if(m_ctrl->currentCanvas())
0112             setScene(m_ctrl->currentCanvas());
0113     });
0114     connect(m_ctrl, &EditorController::pageCountChanged, this, [this]() {
0115         auto c= m_ctrl->currentCanvas();
0116         if(!c)
0117             return;
0118 
0119         setScene(c);
0120     });
0121 
0122     if(m_ctrl->currentCanvas())
0123         setScene(m_ctrl->currentCanvas());
0124 }
0125 
0126 bool ItemEditor::handle() const
0127 {
0128     return m_handle;
0129 }
0130 
0131 void ItemEditor::setHandle(bool handle)
0132 {
0133     m_handle= handle;
0134 }
0135 
0136 void ItemEditor::mousePressEvent(QMouseEvent* event)
0137 {
0138     if(!m_handle)
0139     {
0140         setDragMode(QGraphicsView::NoDrag);
0141         event->ignore();
0142         // qDebug() << "mousePressEvent inside not handle" << event->isAccepted() << scene();
0143         QGraphicsView::mousePressEvent(event);
0144         return;
0145     }
0146 
0147     if(event->button() == Qt::RightButton)
0148         return;
0149 
0150     if(event->button() == Qt::LeftButton)
0151     {
0152         QList<QGraphicsItem*> list= items(event->pos());
0153 
0154         list.erase(std::remove_if(list.begin(), list.end(),
0155                                   [](QGraphicsItem* item) {
0156                                       static QGraphicsPixmapItem pix;
0157                                       return item->type() == pix.type();
0158                                   }),
0159                    list.end());
0160 
0161         if(!list.isEmpty())
0162         {
0163             setDragMode(QGraphicsView::NoDrag);
0164         }
0165         else
0166         {
0167             setDragMode(QGraphicsView::RubberBandDrag);
0168         }
0169     }
0170     // qDebug() << "mousePressEvent inside end ";
0171 
0172     QGraphicsView::mousePressEvent(event);
0173 }
0174 
0175 void ItemEditor::mouseReleaseEvent(QMouseEvent* event)
0176 {
0177     QGraphicsView::mouseReleaseEvent(event);
0178     if(dragMode() == QGraphicsView::ScrollHandDrag)
0179     {
0180         setDragMode(QGraphicsView::RubberBandDrag);
0181     }
0182 }
0183 
0184 void ItemEditor::contextMenuEvent(QContextMenuEvent* event)
0185 {
0186     m_selection.clear();
0187     auto pos= event->pos();
0188     QMenu menu(this);
0189 
0190     if(!scene())
0191         return;
0192 
0193     bool allSame;
0194     bool locked;
0195     m_selection= cleanSelection(scene()->selectedItems(), locked, allSame);
0196     auto list= cleanSelection(items(pos), locked, allSame);
0197 
0198     if(!list.isEmpty())
0199         m_underCursorItem= list.first();
0200 
0201     /*for(auto item : list)
0202     {
0203         auto field= dynamic_cast<CanvasField*>(item);
0204         if(nullptr != field)
0205         {
0206             field->setMenu(menu);
0207             menu.addSeparator();
0208         }
0209     }*/
0210     menu.addAction(m_fitInView.get());
0211     menu.addSeparator();
0212     menu.addAction(m_lockItem.get());
0213     if(allSame)
0214         m_lockItem->setChecked(locked);
0215     else
0216         m_lockItem->setChecked(false);
0217     menu.addAction(m_alignOnX.get());
0218     menu.addAction(m_alignOnY.get());
0219     menu.addAction(m_sameWidth.get());
0220     menu.addAction(m_sameHeight.get());
0221     menu.addAction(m_verticalEquaDistance.get());
0222     menu.addAction(m_horizontalEquaDistance.get());
0223     menu.addSeparator();
0224     menu.addAction(m_dupplicate.get());
0225 
0226     menu.exec(QCursor::pos());
0227 }