File indexing completed on 2024-05-19 05:41:19

0001 #include "customrulemodel.h"
0002 #include <QColor>
0003 
0004 #define PERMANENT_COL_COUNT 2
0005 
0006 namespace std
0007 {
0008 #ifndef _MSC_VER
0009 template <>
0010 pair<GMTOOL::Unit, GMTOOL::Unit>&
0011 pair<GMTOOL::Unit, GMTOOL::Unit>::operator=(const pair<GMTOOL::Unit, GMTOOL::Unit>& pairB)
0012 {
0013     this->first= std::move(pairB.first);
0014     this->second= std::move(pairB.second);
0015     return *this;
0016 }
0017 #endif
0018 } // namespace std
0019 
0020 namespace GMTOOL
0021 {
0022 using UnitPair= std::pair<Unit, Unit>;
0023 using ConvertionItem= std::pair<UnitPair, ConvertorOperator*>;
0024 
0025 CustomRuleModel::CustomRuleModel(QObject* parent) : CategoryModel(parent) {}
0026 
0027 QVariant CustomRuleModel::headerData(int section, Qt::Orientation orientation, int role) const
0028 {
0029     if((orientation == Qt::Horizontal) && (Qt::DisplayRole == role))
0030     {
0031         switch(section)
0032         {
0033         case 0:
0034             return tr("Unit");
0035         case 1:
0036             return tr("Symbol");
0037         default:
0038         {
0039             if(rowCount() > section - PERMANENT_COL_COUNT)
0040             {
0041                 QModelIndex index= createIndex(section - PERMANENT_COL_COUNT, 0);
0042                 return data(index);
0043             }
0044         }
0045         }
0046     }
0047     return {};
0048 }
0049 
0050 bool CustomRuleModel::setHeaderData(int section, Qt::Orientation orientation, const QVariant& value, int role)
0051 {
0052     if(value != headerData(section, orientation, role))
0053     {
0054         emit headerDataChanged(orientation, section, section);
0055         return true;
0056     }
0057     return false;
0058 }
0059 
0060 void CustomRuleModel::setCurrentCategoryId(const QString& cat, int currentCateId)
0061 {
0062     beginResetModel();
0063     m_currentCatId= currentCateId;
0064     CategoryModel::setCurrentCategory(cat);
0065     endResetModel();
0066 }
0067 
0068 QHash<QPair<const Unit*, const Unit*>, ConvertorOperator*>* CustomRuleModel::convertionRules() const
0069 {
0070     return m_convertionRules;
0071 }
0072 
0073 void CustomRuleModel::setConvertionRules(QHash<QPair<const Unit*, const Unit*>, ConvertorOperator*>* convertionRules)
0074 {
0075     m_convertionRules= convertionRules;
0076 }
0077 
0078 int CustomRuleModel::columnCount(const QModelIndex& parent) const
0079 {
0080     if(parent.isValid())
0081         return 0;
0082 
0083     return rowCount() + PERMANENT_COL_COUNT;
0084 }
0085 bool operator==(const Unit& unitA, const Unit& unitB)
0086 {
0087     return unitA.name() == unitB.name();
0088 }
0089 bool operator==(Unit& unitA, const Unit& unitB)
0090 {
0091     return unitA.name() == unitB.name();
0092 }
0093 
0094 bool sameUnit(QPair<const Unit*, const Unit*> pair)
0095 {
0096     return (pair.first == pair.second);
0097 }
0098 
0099 QPair<const Unit*, const Unit*> CustomRuleModel::makePair(const QModelIndex& indexPair) const
0100 {
0101     auto idx= CategoryModel::index(indexPair.row(), 0, QModelIndex());
0102     auto idx2= CategoryModel::index(indexPair.column() - PERMANENT_COL_COUNT, 0, QModelIndex());
0103 
0104     Unit* xUnit= CategoryModel::data(idx, UnitModel::UnitRole).value<Unit*>();
0105     Unit* yUnit= CategoryModel::data(idx2, UnitModel::UnitRole).value<Unit*>();
0106     QPair<const Unit*, const Unit*> pair(xUnit, yUnit);
0107     return pair;
0108 }
0109 
0110 QModelIndex CustomRuleModel::buddy(const QModelIndex& index) const
0111 {
0112     return index;
0113 }
0114 
0115 QVariant CustomRuleModel::data(const QModelIndex& idx, int role) const
0116 {
0117     if(!idx.isValid())
0118         return QVariant();
0119 
0120     if(idx.column() < PERMANENT_COL_COUNT)
0121     {
0122         if(Qt::DisplayRole == role || Qt::EditRole == role)
0123         {
0124             const Unit* xUnit
0125                 = CategoryModel::data(CategoryModel::index(idx.row(), 0, QModelIndex()), UnitModel::UnitRole)
0126                       .value<Unit*>();
0127             if(nullptr != xUnit)
0128             {
0129                 if(idx.column() == 0)
0130                 {
0131                     return xUnit->name();
0132                 }
0133                 else if(idx.column() == 1)
0134                 {
0135                     return xUnit->symbol();
0136                 }
0137             }
0138         }
0139     }
0140     else
0141     {
0142         const auto& pair= makePair(idx);
0143         if(Qt::BackgroundRole == role)
0144         {
0145             if(sameUnit(pair))
0146             {
0147                 return QColor(Qt::red).lighter();
0148             }
0149         }
0150         else if(Qt::DisplayRole == role || Qt::EditRole == role)
0151         {
0152             if(m_convertionRules->contains(pair))
0153             {
0154                 auto convertor= m_convertionRules->value(pair);
0155                 return QString("%1x+%2").arg(convertor->a()).arg(convertor->b());
0156             }
0157             else
0158                 return QVariant();
0159         }
0160     }
0161     return QVariant();
0162 }
0163 
0164 bool CustomRuleModel::setData(const QModelIndex& idx, const QVariant& value, int role)
0165 {
0166     if(data(idx, role) != value)
0167     {
0168         Unit* xUnit= CategoryModel::data(CategoryModel::index(idx.row(), 0, QModelIndex()), UnitModel::UnitRole)
0169                          .value<Unit*>();
0170         if(idx.column() == 0)
0171         {
0172             xUnit->setName(value.toString());
0173         }
0174         else if(idx.column() == 1)
0175         {
0176             xUnit->setSymbol(value.toString());
0177         }
0178         else
0179         {
0180             const auto& pair= makePair(idx);
0181             auto valueStr= value.toString();
0182             auto pos= valueStr.indexOf("x+");
0183             bool ok, ok1;
0184             auto a= QStringView{valueStr}.left(pos).toDouble(&ok);
0185 
0186             auto b= QStringView{valueStr}.right(valueStr.length() - pos).toDouble(&ok1);
0187 
0188             ConvertorOperator* convertor= nullptr;
0189 
0190             if(m_convertionRules->contains(pair))
0191             {
0192                 convertor= m_convertionRules->value(pair);
0193                 if(ok)
0194                     convertor->setA(a);
0195                 if(ok1)
0196                     convertor->setB(b);
0197             }
0198             else
0199             {
0200                 if(!sameUnit(pair))
0201                 {
0202                     convertor= new ConvertorOperator(a, b, false, false);
0203                     m_convertionRules->insert(pair, convertor);
0204                 }
0205             }
0206         }
0207         emit dataChanged(idx, idx, QVector<int>() << role);
0208         return true;
0209     }
0210     return false;
0211 }
0212 
0213 Qt::ItemFlags CustomRuleModel::flags(const QModelIndex& idx) const
0214 {
0215     if(!idx.isValid())
0216         return Qt::NoItemFlags;
0217 
0218     Unit* xUnit
0219         = CategoryModel::data(CategoryModel::index(idx.row(), 0, QModelIndex()), UnitModel::UnitRole).value<Unit*>();
0220 
0221     if(nullptr == xUnit)
0222         return Qt::NoItemFlags;
0223 
0224     auto flag= Qt::ItemIsEnabled | Qt::ItemIsSelectable;
0225 
0226     if((idx.column() - PERMANENT_COL_COUNT) == idx.row())
0227     {
0228         flag= Qt::ItemIsEnabled | Qt::ItemIsSelectable;
0229     }
0230     else if(!xUnit->readOnly())
0231     {
0232         flag= Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
0233     }
0234     else if(idx.column() - PERMANENT_COL_COUNT >= 0)
0235     {
0236         Unit* yUnit= CategoryModel::data(CategoryModel::index(idx.column() - PERMANENT_COL_COUNT, 0, QModelIndex()),
0237                                          UnitModel::UnitRole)
0238                          .value<Unit*>();
0239 
0240         if(!yUnit->readOnly())
0241             flag= Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
0242     }
0243 
0244     return flag;
0245 }
0246 
0247 QModelIndex CustomRuleModel::parent(const QModelIndex&) const
0248 {
0249     return {};
0250 }
0251 
0252 QModelIndex CustomRuleModel::index(int row, int column, const QModelIndex&) const
0253 {
0254     if(rowCount() > row && column < rowCount() + PERMANENT_COL_COUNT)
0255     {
0256         return createIndex(row, column);
0257     }
0258     else
0259     {
0260         return {};
0261     }
0262 }
0263 
0264 bool CustomRuleModel::insertUnit()
0265 {
0266     beginResetModel();
0267 
0268     auto unit= new Unit(tr("New Unit"), "", static_cast<Unit::Category>(m_currentCatId));
0269     unit->setReadOnly(false);
0270     addUnit(unit);
0271     invalidateFilter();
0272     setFilterFixedString(m_currentCategory);
0273 
0274     endResetModel();
0275 
0276     return true;
0277 }
0278 
0279 bool CustomRuleModel::removeUnit(const QModelIndex& index)
0280 {
0281     beginRemoveRows(QModelIndex(), rowCount(), rowCount());
0282     beginRemoveColumns(QModelIndex(), rowCount() + PERMANENT_COL_COUNT, rowCount() + PERMANENT_COL_COUNT);
0283 
0284     const auto unit= data(index, UnitModel::UnitRole).value<Unit*>();
0285     const auto& keys= m_convertionRules->keys();
0286     for(auto key : keys)
0287     {
0288         if((key.first == unit) || (key.second == unit))
0289         {
0290             if(!m_convertionRules->value(key)->isReadOnly())
0291                 m_convertionRules->remove(key);
0292         }
0293     }
0294 
0295     endRemoveColumns();
0296     endRemoveRows();
0297     return true;
0298 }
0299 
0300 qreal CustomRuleModel::convert(QPair<const Unit*, const Unit*> pair, qreal value) const
0301 {
0302     const auto rule= m_convertionRules->value(pair);
0303     return rule->convert(value);
0304 }
0305 
0306 } // namespace GMTOOL