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

0001 /***************************************************************************
0002  * Copyright (C) 2018 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 "tablecanvasfield.h"
0023 #include <QDebug>
0024 #include <QGraphicsSceneMouseEvent>
0025 #include <QJsonArray>
0026 #include <QPainter>
0027 #include <QStyle>
0028 #include <QStyleOptionGraphicsItem>
0029 
0030 #include "charactersheet/controllers/fieldcontroller.h"
0031 #include "charactersheet/controllers/tablefield.h"
0032 #define SQUARE_SIZE 12
0033 
0034 //////////////////////////////////////////////////////
0035 //
0036 //
0037 //
0038 /////////////////////////////////////////////////////
0039 bool compareHandles(HandleItem* first, HandleItem* two)
0040 {
0041     return (first->pos().x() < two->pos().x());
0042 }
0043 
0044 TableCanvasField::TableCanvasField(FieldController* field)
0045     : CanvasField(field), m_colunmCount(1), m_lineCount(1), m_dataReset(true)
0046 {
0047     m_addColumn= new ButtonCanvas();
0048     m_addColumn->setParentItem(this);
0049 
0050     m_dialog.reset(new ColumnDefinitionDialog());
0051 
0052     connect(m_dialog.get(), &ColumnDefinitionDialog::columnCountChanged, this, [=](int i) {
0053         while(i > m_colunmCount)
0054         {
0055             addColumn();
0056         }
0057         while(i < m_colunmCount)
0058         {
0059             removeColumn();
0060         }
0061     });
0062 
0063     connect(m_dialog.get(), &ColumnDefinitionDialog::lineCountChanged, this, [=](int i) {
0064         m_lineCount= i;
0065         update();
0066     });
0067 
0068     m_addLine= new ButtonCanvas();
0069     m_addLine->setParentItem(this);
0070 
0071     m_defineColumns= new QAction(tr("Properties"), this);
0072     //    m_properties = new QAction(tr("Properties"),this);
0073 
0074     connect(m_defineColumns, &QAction::triggered, this, &TableCanvasField::defineColumns);
0075 
0076     m_addLine->setMsg("+");
0077     m_addColumn->setMsg("+");
0078 
0079     m_addLine->setPos(24, 200);
0080     m_addColumn->setPos(200, 24);
0081 
0082     connect(m_addColumn, SIGNAL(clicked()), this, SLOT(addColumn()));
0083     connect(m_addLine, SIGNAL(clicked()), this, SLOT(addLine()));
0084 }
0085 TableCanvasField::~TableCanvasField() {}
0086 void TableCanvasField::addColumn()
0087 {
0088     m_colunmCount++;
0089 
0090     HandleItem* item= new HandleItem(this);
0091     m_handles.append(item);
0092 
0093     qreal colW= boundingRect().width() / (m_handles.size() + 1);
0094     for(auto item : m_handles)
0095     {
0096         item->setPos(colW * (m_handles.indexOf(item) + 1), boundingRect().height() / 2);
0097     }
0098     if(m_columnDefined)
0099     {
0100         m_dataReset= true;
0101         defineColumns();
0102     }
0103     update();
0104 }
0105 void TableCanvasField::removeColumn()
0106 {
0107     m_colunmCount--;
0108     if(m_handles.isEmpty())
0109         return;
0110 
0111     m_handles.removeLast();
0112 
0113     qreal colW= boundingRect().width() / (m_handles.size() + 1);
0114     for(auto item : m_handles)
0115     {
0116         item->setPos(colW * (m_handles.indexOf(item) + 1), boundingRect().height() / 2);
0117     }
0118     if(m_columnDefined)
0119     {
0120         m_dataReset= true;
0121         defineColumns();
0122     }
0123     update();
0124 }
0125 
0126 void TableCanvasField::addLine()
0127 {
0128     m_lineCount++;
0129     update();
0130 }
0131 
0132 void TableCanvasField::defineColumns()
0133 {
0134     std::sort(m_handles.begin(), m_handles.end(), compareHandles);
0135 
0136     if(m_dataReset)
0137     {
0138         m_dialog->setData(m_handles, boundingRect().width(), m_lineCount, boundingRect().height());
0139         m_dataReset= false;
0140     }
0141 
0142     if(m_dialog->isHidden())
0143     {
0144         m_dialog->exec();
0145         update();
0146         m_columnDefined= true;
0147     }
0148 }
0149 
0150 void TableCanvasField::setMenu(QMenu& menu)
0151 {
0152     menu.addAction(m_defineColumns);
0153 }
0154 
0155 int TableCanvasField::lineCount() const
0156 {
0157     return m_lineCount;
0158 }
0159 
0160 void TableCanvasField::setLineCount(int lineCount)
0161 {
0162     m_lineCount= lineCount;
0163 }
0164 
0165 int TableCanvasField::colunmCount() const
0166 {
0167     return m_colunmCount;
0168 }
0169 
0170 void TableCanvasField::setColunmCount(int colunmCount)
0171 {
0172     m_colunmCount= colunmCount;
0173 }
0174 
0175 void TableCanvasField::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*)
0176 {
0177     if(nullptr == m_ctrl)
0178         return;
0179     auto rect= boundingRect();
0180     painter->save();
0181     painter->fillRect(rect, m_ctrl->bgColor());
0182     painter->setPen(Qt::black);
0183     painter->drawRect(rect);
0184 
0185     m_addLine->setPos(0, boundingRect().height() / 2);
0186     m_addColumn->setPos(boundingRect().width() / 2, 0);
0187 
0188     if(hasFocusOrChild())
0189     {
0190         painter->save();
0191         QPen pen= painter->pen();
0192         pen.setColor(Qt::red);
0193         pen.setWidth(5);
0194         painter->setPen(pen);
0195         painter->drawRect(rect);
0196         painter->restore();
0197     }
0198 
0199     for(auto handle : m_handles)
0200     {
0201         painter->drawLine(handle->pos().x(), 0, handle->pos().x(), boundingRect().height());
0202         handle->setVisible(hasFocusOrChild());
0203     }
0204 
0205     auto yStep= boundingRect().height() / (m_lineCount);
0206 
0207     if(!m_dataReset)
0208     {
0209         auto model= m_dialog->model();
0210         if(nullptr != model)
0211         {
0212             auto list= model->children();
0213             for(int x= 0; x < std::min(m_colunmCount, static_cast<int>(list.size())); ++x)
0214             {
0215                 auto field= list.at(x);
0216                 qreal xPos= 0;
0217                 if(x != 0)
0218                 {
0219                     xPos= m_handles.at(x - 1)->pos().x();
0220                 }
0221                 qreal xEnd= boundingRect().width() - xPos;
0222                 if(x < m_colunmCount - 1)
0223                 {
0224                     xEnd= m_handles.at(x)->pos().x() - xPos;
0225                 }
0226                 auto itemType= m_ctrl->itemType();
0227                 auto fieldH= boundingRect().height() / m_lineCount;
0228                 for(int y= 0; y < m_lineCount; ++y)
0229                 {
0230                     QRectF rect(xPos, y * yStep, xEnd, fieldH);
0231                     QPixmap map= QPixmap(m_pictureMap[itemType]);
0232                     m_pix= map.scaled(32, 32);
0233                     if((!m_pix.isNull()) && m_showImageField)
0234                     {
0235                         painter->drawPixmap(rect.center(), m_pix, m_pix.rect()); //-m_pix.rect().center()
0236                     }
0237                     painter->save();
0238                     painter->setPen(Qt::green);
0239                     painter->drawRect(rect);
0240                     painter->restore();
0241                 }
0242             }
0243         }
0244     }
0245 
0246     for(int i= 0; i < m_lineCount; ++i)
0247     {
0248         painter->drawLine(0, i * yStep, boundingRect().width(), i * yStep);
0249     }
0250     painter->drawText(QPoint(0, 0), m_ctrl->id());
0251     painter->restore();
0252 }
0253 bool TableCanvasField::hasFocusOrChild()
0254 {
0255     if(isSelected())
0256     {
0257         return true;
0258     }
0259     else
0260     {
0261         if(m_handles.isEmpty())
0262         {
0263             return false;
0264         }
0265         for(int i= 0; i < m_handles.size(); ++i)
0266         {
0267             if((m_handles.at(i) != nullptr) && (m_handles.at(i)->isSelected()))
0268             {
0269                 return true;
0270             }
0271         }
0272     }
0273 
0274     return false;
0275 }
0276 void TableCanvasField::generateSubFields(QTextStream& out)
0277 {
0278     auto model= m_dialog->model();
0279     if(nullptr != model)
0280     {
0281         model->generateQML(out, 1, true);
0282     }
0283 }
0284 
0285 TreeSheetItem* TableCanvasField::getRoot()
0286 {
0287     auto model= m_dialog->model();
0288     Section* sec= nullptr;
0289     if(nullptr != model)
0290     {
0291         sec= model->getRootSection();
0292     }
0293     return sec;
0294 }
0295 void TableCanvasField::fillLineModel(LineModel* lineModel, TableField* parent)
0296 {
0297     auto model= m_dialog->model();
0298     for(int i= 0; i < m_lineCount; ++i)
0299     {
0300         LineFieldItem* line= new LineFieldItem();
0301         for(TreeSheetItem* child : model->children())
0302         {
0303             auto field= dynamic_cast<FieldController*>(child);
0304             if(nullptr != field)
0305             {
0306                 auto newField= new FieldController(TreeSheetItem::FieldItem, true);
0307                 newField->copyField(field, true, false);
0308                 newField->setParent(parent);
0309                 line->insertField(newField);
0310             }
0311         }
0312         lineModel->insertLine(line);
0313     }
0314 }
0315 
0316 void TableCanvasField::load(QJsonObject& json)
0317 {
0318     m_lineCount= json["lineCount"].toInt();
0319     m_colunmCount= json["colunmCount"].toInt();
0320     m_dataReset= json["dataReset"].toBool();
0321     m_columnDefined= json["columnDefined"].toBool();
0322 
0323     QJsonArray handles= json["handles"].toArray();
0324     for(auto handle : handles)
0325     {
0326         auto handleItem= new HandleItem(this);
0327         auto obj= handle.toObject();
0328         handleItem->load(obj);
0329         m_handles.append(handleItem);
0330     }
0331 
0332     QJsonObject dialog= json["dialog"].toObject();
0333     m_dialog->load(dialog);
0334 }
0335 void TableCanvasField::save(QJsonObject& json)
0336 {
0337     json["lineCount"]= m_lineCount;
0338     json["colunmCount"]= m_colunmCount;
0339     json["dataReset"]= m_dataReset;
0340     json["columnDefined"]= m_columnDefined;
0341 
0342     QJsonArray handles;
0343     for(auto handle : m_handles)
0344     {
0345         QJsonObject obj;
0346         handle->save(obj);
0347         handles.push_back(obj);
0348     }
0349     json["handles"]= handles;
0350 
0351     QJsonObject dialog;
0352     m_dialog->save(dialog);
0353     json["dialog"]= dialog;
0354 }
0355 
0356 //////////////////////////////////////////////////////
0357 //
0358 //
0359 //
0360 /////////////////////////////////////////////////////
0361 ButtonCanvas::ButtonCanvas() : m_rect(QRectF(0, 0, SQUARE_SIZE * 2, SQUARE_SIZE * 2))
0362 {
0363     setAcceptedMouseButtons(Qt::LeftButton);
0364     setFlags(QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
0365 }
0366 
0367 QRectF ButtonCanvas::boundingRect() const
0368 {
0369     return m_rect;
0370 }
0371 
0372 void ButtonCanvas::paint(QPainter* painter, const QStyleOptionGraphicsItem*, QWidget*)
0373 {
0374     painter->save();
0375     painter->fillRect(boundingRect(), Qt::cyan);
0376     painter->setPen(Qt::black);
0377     painter->drawRect(boundingRect());
0378     painter->drawText(boundingRect(), Qt::AlignCenter, m_msg);
0379     painter->restore();
0380 }
0381 
0382 QString ButtonCanvas::msg() const
0383 {
0384     return m_msg;
0385 }
0386 
0387 void ButtonCanvas::setMsg(const QString& msg)
0388 {
0389     m_msg= msg;
0390 }
0391 
0392 void ButtonCanvas::mousePressEvent(QGraphicsSceneMouseEvent* event)
0393 {
0394     if(event->buttons() & Qt::LeftButton)
0395     {
0396         if(boundingRect().contains(event->pos()))
0397         {
0398             emit clicked();
0399         }
0400     }
0401     else
0402     {
0403         QGraphicsObject::mousePressEvent(event);
0404     }
0405 }
0406 
0407 QRectF ButtonCanvas::rect() const
0408 {
0409     return m_rect;
0410 }
0411 
0412 void ButtonCanvas::setRect(const QRectF& rect)
0413 {
0414     m_rect= rect;
0415 }