File indexing completed on 2024-05-12 17:11:40
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 "fieldmodel.h" 0023 0024 #include <QDebug> 0025 #include <QGraphicsScene> 0026 #include <QJsonArray> 0027 0028 #include "canvas.h" 0029 #include "qmlgeneratorvisitor.h" 0030 #include <charactersheet_formula/formulamanager.h> 0031 0032 ////////////////////////////// 0033 // Column 0034 ///////////////////////////// 0035 Column::Column(QString name, TreeSheetItem::ColumnId pos) : m_name(name), m_pos(pos) {} 0036 0037 QString Column::getName() const 0038 { 0039 return m_name; 0040 } 0041 0042 void Column::setName(const QString& name) 0043 { 0044 m_name= name; 0045 } 0046 TreeSheetItem::ColumnId Column::getPos() const 0047 { 0048 return m_pos; 0049 } 0050 0051 void Column::setPos(const TreeSheetItem::ColumnId& pos) 0052 { 0053 m_pos= pos; 0054 } 0055 0056 ////////////////////////////// 0057 // FieldModel 0058 ///////////////////////////// 0059 FieldModel::FieldModel(QObject* parent) 0060 : QAbstractItemModel(parent), m_rootSection{new Section()}, m_formulaManager{new Formula::FormulaManager()} 0061 { 0062 m_colunm << new Column(tr("Id"), TreeSheetItem::ID) << new Column(tr("Label"), TreeSheetItem::LABEL) 0063 << new Column(tr("Value"), TreeSheetItem::VALUE) 0064 << new Column(tr("Possible Values"), TreeSheetItem::VALUES) << new Column(tr("Type"), TreeSheetItem::TYPE) 0065 << new Column(tr("x"), TreeSheetItem::X) << new Column(tr("y"), TreeSheetItem::Y) 0066 << new Column(tr("Width"), TreeSheetItem::WIDTH) << new Column(tr("Height"), TreeSheetItem::HEIGHT) 0067 << new Column(tr("Font Adaptation"), TreeSheetItem::FitFont) << new Column(tr("Font"), TreeSheetItem::FONT) 0068 << new Column(tr("Text-align"), TreeSheetItem::TEXT_ALIGN) 0069 << new Column(tr("Text Color"), TreeSheetItem::TEXTCOLOR) 0070 << new Column(tr("Bg Color"), TreeSheetItem::BGCOLOR) << new Column(tr("Border"), TreeSheetItem::BORDER) 0071 << new Column(tr("Page"), TreeSheetItem::PAGE) << new Column(tr("ToolTip"), TreeSheetItem::TOOLTIP); 0072 0073 m_alignList << tr("TopRight") << tr("TopMiddle") << tr("TopLeft") << tr("CenterRight") << tr("CenterMiddle") 0074 << tr("CenterLeft") << tr("BottomRight") << tr("BottomMiddle") << tr("BottomLeft"); 0075 } 0076 0077 FieldModel::~FieldModel()= default; 0078 0079 QVariant FieldModel::data(const QModelIndex& index, int role) const 0080 { 0081 if(!index.isValid()) 0082 return QVariant(); 0083 TreeSheetItem* treeitem= static_cast<TreeSheetItem*>(index.internalPointer()); 0084 0085 if(nullptr == treeitem) 0086 return {}; 0087 0088 auto item= dynamic_cast<CSItem*>(treeitem); 0089 0090 if(nullptr == item) 0091 { 0092 if(index.column() == 0 && role == Qt::DisplayRole) 0093 { 0094 return item->id(); 0095 } 0096 else 0097 return {}; 0098 } 0099 if((role == Qt::DisplayRole) || (Qt::EditRole == role)) 0100 { 0101 QVariant var; 0102 if(TreeSheetItem::VALUE == m_colunm[index.column()]->getPos() && role == Qt::EditRole) 0103 { 0104 0105 auto formula= item->formula(); 0106 var= formula.isEmpty() ? item->valueFrom(m_colunm[index.column()]->getPos(), role) : formula; 0107 } 0108 else 0109 var= item->valueFrom(m_colunm[index.column()]->getPos(), role); 0110 if((index.column() == TreeSheetItem::TEXT_ALIGN) && (Qt::DisplayRole == role)) 0111 { 0112 if((var.toInt() >= 0) && (var.toInt() < m_alignList.size())) 0113 { 0114 var= m_alignList.at(var.toInt()); 0115 } 0116 } 0117 return var; 0118 } 0119 if((role == Qt::BackgroundRole) 0120 && ((index.column() == TreeSheetItem::BGCOLOR) || (index.column() == TreeSheetItem::TEXTCOLOR))) 0121 { 0122 QVariant var= item->valueFrom(m_colunm[index.column()]->getPos(), Qt::EditRole); 0123 return var; 0124 } 0125 if(role == Qt::BackgroundRole) 0126 { 0127 auto field= dynamic_cast<FieldController*>(item); 0128 QVariant color; 0129 if(field && !field->generatedCode().isEmpty()) 0130 { 0131 color= QColor(Qt::green).lighter(); 0132 } 0133 if(field && field->isReadOnly() && (index.column() >= TreeSheetItem::X) 0134 && (index.column() <= TreeSheetItem::HEIGHT)) 0135 { 0136 color= QColor(Qt::gray); 0137 } 0138 return color; 0139 } 0140 if((Qt::FontRole == role) && (index.column() == TreeSheetItem::FONT)) 0141 { 0142 QVariant var= item->valueFrom(m_colunm[index.column()]->getPos(), Qt::DisplayRole); 0143 QFont font; 0144 font.fromString(var.toString()); 0145 return font; 0146 } 0147 return QVariant(); 0148 } 0149 0150 bool FieldModel::setData(const QModelIndex& index, const QVariant& value, int role) 0151 { 0152 if(!index.isValid() || Qt::EditRole != role) 0153 return false; 0154 0155 TreeSheetItem* treeitem= static_cast<TreeSheetItem*>(index.internalPointer()); 0156 0157 if(nullptr == treeitem) 0158 return false; 0159 0160 auto item= dynamic_cast<CSItem*>(treeitem); 0161 0162 if(!item && index.column() == 0 && role == Qt::DisplayRole) 0163 { 0164 treeitem->setId(value.toString()); 0165 return true; 0166 } 0167 if(nullptr == item) 0168 return false; 0169 0170 auto valStr= value.toString(); 0171 0172 if(TreeSheetItem::VALUE == m_colunm[index.column()]->getPos() && valStr.startsWith("=")) 0173 { 0174 QHash<QString, QString> hash= buildDicto(); 0175 m_formulaManager->setConstantHash(hash); 0176 auto valueAfterComputation= m_formulaManager->getValue(valStr).toString(); 0177 item->setFormula(valStr); 0178 item->setValueFrom(m_colunm[index.column()]->getPos(), valueAfterComputation); 0179 } 0180 else 0181 { 0182 item->setValueFrom(m_colunm[index.column()]->getPos(), value); 0183 } 0184 emit valuesChanged(item->valueFrom(TreeSheetItem::ID, Qt::DisplayRole).toString(), value.toString()); 0185 emit modelChanged(); 0186 return true; 0187 } 0188 0189 QHash<QString, QString> FieldModel::buildDicto() 0190 { 0191 QHash<QString, QString> dict; 0192 m_rootSection->setFieldInDictionnary(dict); 0193 return dict; 0194 } 0195 0196 QModelIndex FieldModel::index(int row, int column, const QModelIndex& parent) const 0197 { 0198 if(row < 0) 0199 return QModelIndex(); 0200 0201 TreeSheetItem* parentItem= nullptr; 0202 0203 // qDebug()<< "Index session " <<row << column << parent; 0204 if(!parent.isValid()) 0205 parentItem= m_rootSection.get(); 0206 else 0207 parentItem= static_cast<TreeSheetItem*>(parent.internalPointer()); 0208 0209 TreeSheetItem* childItem= parentItem->childAt(row); 0210 if(childItem) 0211 return createIndex(row, column, childItem); 0212 else 0213 return QModelIndex(); 0214 } 0215 0216 QModelIndex FieldModel::parent(const QModelIndex& child) const 0217 { 0218 if(!child.isValid()) 0219 return QModelIndex(); 0220 0221 TreeSheetItem* childItem= static_cast<TreeSheetItem*>(child.internalPointer()); 0222 TreeSheetItem* parentItem= childItem->parentTreeItem(); 0223 0224 if(parentItem == m_rootSection.get()) 0225 return QModelIndex(); 0226 0227 TreeSheetItem* grandParent= parentItem->parentTreeItem(); 0228 0229 return createIndex(grandParent->indexOfChild(parentItem), 0, parentItem); 0230 } 0231 0232 int FieldModel::rowCount(const QModelIndex& parent) const 0233 { 0234 if(!parent.isValid()) 0235 return m_rootSection->childrenCount(); 0236 0237 TreeSheetItem* childItem= static_cast<TreeSheetItem*>(parent.internalPointer()); 0238 if(childItem) 0239 return childItem->childrenCount(); 0240 else 0241 return 0; 0242 } 0243 0244 int FieldModel::columnCount(const QModelIndex& parent) const 0245 { 0246 Q_UNUSED(parent) 0247 return m_colunm.count(); 0248 } 0249 0250 QVariant FieldModel::headerData(int section, Qt::Orientation orientation, int role) const 0251 { 0252 if((role == Qt::DisplayRole) && (orientation == Qt::Horizontal)) 0253 { 0254 return m_colunm[section]->getName(); 0255 } 0256 else 0257 { 0258 return QVariant(); 0259 } 0260 } 0261 0262 void FieldModel::appendField(CSItem* f) 0263 { 0264 beginInsertRows(QModelIndex(), m_rootSection->childrenCount(), m_rootSection->childrenCount()); 0265 m_rootSection->appendChild(f); 0266 auto func= [this, f]() { emit updateItem(f); }; 0267 connect(f, &CSItem::characterSheetItemChanged, this, func); 0268 connect(f, &CSItem::xChanged, this, func); 0269 connect(f, &CSItem::yChanged, this, func); 0270 connect(f, &CSItem::widthChanged, this, func); 0271 connect(f, &CSItem::heightChanged, this, func); 0272 connect(f, &CSItem::borderChanged, this, func); 0273 connect(f, &CSItem::bgColorChanged, this, func); 0274 0275 connect(f, &CSItem::valueChanged, this, func); 0276 connect(f, &CSItem::textColorChanged, this, func); 0277 connect(f, &CSItem::textAlignChanged, this, func); 0278 connect(f, &CSItem::bgColorChanged, this, func); 0279 connect(f, &CSItem::valuesChanged, this, func); 0280 connect(f, &CSItem::pageChanged, this, func); 0281 connect(f, &CSItem::readOnlyChanged, this, func); 0282 connect(f, &CSItem::formulaChanged, this, func); 0283 connect(f, &CSItem::idChanged, this, func); 0284 connect(f, &CSItem::labelChanged, this, func); 0285 0286 endInsertRows(); 0287 emit modelChanged(); 0288 emit fieldAdded(f); 0289 } 0290 void FieldModel::insertField(CSItem* field, TreeSheetItem* parent, int pos) 0291 { 0292 beginInsertRows(QModelIndex(), pos, pos); 0293 if(parent == m_rootSection.get()) 0294 { 0295 m_rootSection->insertChild(field, pos); 0296 } 0297 endInsertRows(); 0298 emit modelChanged(); 0299 } 0300 Qt::ItemFlags FieldModel::flags(const QModelIndex& index) const 0301 { 0302 if(!index.isValid()) 0303 return Qt::ItemIsEnabled; 0304 0305 // TreeSheetItem* childItem = static_cast<TreeSheetItem*>(index.internalPointer()); 0306 if(m_colunm[index.column()]->getPos() == TreeSheetItem::ID) 0307 { 0308 return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable; 0309 } 0310 else if(m_colunm[index.column()]->getPos() == TreeSheetItem::TYPE) 0311 { 0312 return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable; 0313 } 0314 else if(m_colunm[index.column()]->getPos() == TreeSheetItem::FONT) 0315 { 0316 return Qt::ItemIsEnabled | Qt::ItemIsSelectable; 0317 } 0318 else // if(!childItem->mayHaveChildren()) 0319 { 0320 return Qt::ItemIsEnabled | Qt::ItemIsEditable | Qt::ItemIsSelectable /*| Qt::ItemIsUserCheckable */; 0321 } 0322 /*else 0323 return Qt::ItemIsEnabled | Qt::ItemIsSelectable | Qt::ItemIsUserCheckable ;*/ 0324 } 0325 void FieldModel::generateQML(QTextStream& out, int indentation, bool isTable) 0326 { 0327 QmlGeneratorVisitor visitor(out, m_rootSection.get()); 0328 visitor.setIndentation(indentation); 0329 visitor.setIsTable(isTable); 0330 visitor.generateTreeSheetItem(); 0331 // m_rootSection->generateQML(out,TreeSheetItem::FieldSec,0,isTable); 0332 } 0333 0334 QString FieldModel::getValue(const QString& key) 0335 { 0336 return key; 0337 } 0338 0339 QList<TreeSheetItem*> FieldModel::children() 0340 { 0341 QList<TreeSheetItem*> result; 0342 for(int i= 0; i < m_rootSection->childrenCount(); ++i) 0343 { 0344 result.append(m_rootSection->childAt(i)); 0345 } 0346 return result; 0347 } 0348 0349 QList<CSItem*> FieldModel::allChildren() const 0350 { 0351 return m_rootSection->allChildren(); 0352 } 0353 0354 QRectF FieldModel::childrenRect() const 0355 { 0356 QRectF res{0., 0., 1., 1.}; 0357 auto alls= allChildren(); 0358 for(auto field : alls) 0359 { 0360 if(!field) 0361 continue; 0362 res= res.united(QRectF{field->x(), field->y(), field->width(), field->height()}); 0363 } 0364 return res; 0365 } 0366 0367 void FieldModel::getFieldFromPage(int pagePos, QList<CSItem*>& list) 0368 { 0369 list= m_rootSection->fieldFromPage(pagePos); 0370 } 0371 0372 FieldController* FieldModel::getFieldFromIndex(const QModelIndex& index) 0373 { 0374 return static_cast<FieldController*>(index.internalPointer()); 0375 } 0376 0377 void FieldModel::updateItem(CSItem* item) 0378 { 0379 int ind= m_rootSection->indexOfChild(item); 0380 if(ind >= 0) 0381 { 0382 emit dataChanged(createIndex(ind, 0, item), createIndex(ind, m_colunm.size(), item)); 0383 emit modelChanged(); 0384 } 0385 else 0386 { 0387 TreeSheetItem* parent= item->parentTreeItem(); 0388 QList<TreeSheetItem*> list; 0389 while(parent != nullptr) 0390 { 0391 list.prepend(parent); 0392 parent= parent->parentTreeItem(); 0393 } 0394 0395 QModelIndex first; 0396 QModelIndex second; 0397 int i= 0; 0398 for(TreeSheetItem* itemtmp : list) 0399 { 0400 TreeSheetItem* next= nullptr; 0401 if(i + 1 > list.size()) 0402 { 0403 next= list[++i]; 0404 } 0405 else 0406 { 0407 next= item; 0408 } 0409 0410 if(itemtmp == m_rootSection.get()) 0411 { 0412 first= index(itemtmp->indexOfChild(next), 0, first); 0413 second= index(itemtmp->indexOfChild(next), m_colunm.size(), second); 0414 } 0415 } 0416 emit dataChanged(first, second); 0417 emit modelChanged(); 0418 } 0419 } 0420 0421 Section* FieldModel::getRootSection() const 0422 { 0423 return m_rootSection.get(); 0424 } 0425 0426 void FieldModel::setRootSection(Section* rootSection) 0427 { 0428 beginResetModel(); 0429 m_rootSection.reset(rootSection); 0430 endResetModel(); 0431 } 0432 void FieldModel::save(QJsonObject& json, bool exp) 0433 { 0434 m_rootSection->save(json, exp); 0435 } 0436 0437 void FieldModel::load(const QJsonObject& json) 0438 { 0439 beginResetModel(); 0440 m_rootSection->load(json); 0441 endResetModel(); 0442 } 0443 void FieldModel::removeItem(QModelIndex& index) 0444 { 0445 if(index.isValid()) 0446 { 0447 TreeSheetItem* childItem= static_cast<TreeSheetItem*>(index.internalPointer()); 0448 Section* parentSection= nullptr; 0449 if(index.parent().isValid()) 0450 { 0451 TreeSheetItem* parentItem= static_cast<TreeSheetItem*>(index.internalPointer()); 0452 parentSection= dynamic_cast<Section*>(parentItem); 0453 } 0454 else 0455 { 0456 parentSection= m_rootSection.get(); 0457 } 0458 0459 if(nullptr == parentSection) 0460 { 0461 return; 0462 } 0463 beginRemoveRows(index.parent(), parentSection->indexOfChild(childItem), parentSection->indexOfChild(childItem)); 0464 0465 parentSection->deleteChild(childItem); 0466 0467 endRemoveRows(); 0468 0469 emit modelChanged(); 0470 } 0471 } 0472 0473 void FieldModel::removeField(FieldController* field) 0474 { 0475 // int index = m_rootSection->indexOfChild(field); 0476 QList<TreeSheetItem*> ancestors; 0477 0478 // ancestors.append(field); 0479 TreeSheetItem* tmp= field; 0480 while(tmp != nullptr) 0481 { 0482 tmp= tmp->parentTreeItem(); 0483 if(nullptr != tmp) 0484 { 0485 ancestors.prepend(tmp); 0486 } 0487 } 0488 0489 QModelIndex parent; 0490 TreeSheetItem* parentSection= nullptr; 0491 for(const auto& ancestor : ancestors) 0492 { 0493 if(nullptr != parentSection) 0494 { 0495 parent= index(parentSection->indexOfChild(ancestor), 0, parent); 0496 // TODO check that 0497 // parent= parent.child(parentSection->indexOfChild(ancestor), 0); 0498 } 0499 parentSection= ancestor; 0500 } 0501 0502 beginRemoveRows(parent, parentSection->indexOfChild(field), parentSection->indexOfChild(field)); 0503 0504 parentSection->removeChild(field); 0505 0506 endRemoveRows(); 0507 emit modelChanged(); 0508 } 0509 void FieldModel::clearModel() 0510 { 0511 beginResetModel(); 0512 m_rootSection->removeAll(); 0513 endResetModel(); 0514 } 0515 0516 void FieldModel::setValueForAll(QModelIndex& index) 0517 { 0518 if(index.isValid()) 0519 { 0520 TreeSheetItem* childItem= static_cast<TreeSheetItem*>(index.internalPointer()); 0521 m_rootSection->setValueForAll(childItem, m_colunm[index.column()]->getPos()); 0522 } 0523 } 0524 0525 void FieldModel::resetAllId() 0526 { 0527 beginResetModel(); 0528 int i= 0; 0529 m_rootSection->resetAllId(i); 0530 FieldController::setCount(i); 0531 endResetModel(); 0532 }