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