File indexing completed on 2024-05-05 17:18:50
0001 /*************************************************************************** 0002 * SPDX-FileCopyrightText: 2022 S. MANKOWSKI stephane@mankowski.fr 0003 * SPDX-FileCopyrightText: 2022 G. DE BURE support@mankowski.fr 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 ***************************************************************************/ 0006 /** @file 0007 * This file defines classes SKGObjectModel. 0008 * 0009 * @author Stephane MANKOWSKI / Guillaume DE BURE 0010 */ 0011 #include "skgobjectmodel.h" 0012 0013 #include <math.h> 0014 0015 #include <kconfiggroup.h> 0016 #include <klocalizedstring.h> 0017 0018 #include <qapplication.h> 0019 #include <qcolor.h> 0020 #include <qdir.h> 0021 #include <qfont.h> 0022 #include <qicon.h> 0023 #include <qmimedata.h> 0024 #include <qstandardpaths.h> 0025 0026 #include "skgaccountobject.h" 0027 #include "skgbudgetobject.h" 0028 #include "skgbudgetruleobject.h" 0029 #include "skgcategoryobject.h" 0030 #include "skgdocumentbank.h" 0031 #include "skgmainpanel.h" 0032 #include "skgoperationobject.h" 0033 #include "skgpayeeobject.h" 0034 #include "skgrecurrentoperationobject.h" 0035 #include "skgsuboperationobject.h" 0036 #include "skgtraces.h" 0037 #include "skgtrackerobject.h" 0038 #include "skgtransactionmng.h" 0039 #include "skgunitobject.h" 0040 #include "skgunitvalueobject.h" 0041 0042 SKGObjectModel:: 0043 SKGObjectModel(SKGDocumentBank* iDocument, 0044 const QString& iTable, 0045 const QString& iWhereClause, 0046 QWidget* iParent, 0047 const QString& iParentAttribute, 0048 bool iResetOnCreation) 0049 : SKGObjectModelBase(iDocument, iTable, iWhereClause, iParent, iParentAttribute, false) 0050 { 0051 SKGTRACEINFUNC(1) 0052 0053 m_operationTable = false; 0054 m_recurrentoperationTable = false; 0055 m_trackerTable = false; 0056 m_accountTable = false; 0057 m_unitTable = false; 0058 m_unitvalueTable = false; 0059 m_suboperationTable = false; 0060 m_categoryTable = false; 0061 m_ruleTable = false; 0062 m_interestTable = false; 0063 m_interestResultTable = false; 0064 m_payeeTable = false; 0065 m_budgetTable = false; 0066 m_budgetRuleTable = false; 0067 m_isResetRealyNeeded = iResetOnCreation; 0068 refresh(); 0069 } 0070 0071 void SKGObjectModel::buidCache() 0072 { 0073 SKGObjectModelBase::buidCache(); 0074 m_operationTable = (getRealTable() == QStringLiteral("operation") || getRealTable() == QStringLiteral("suboperation")); 0075 m_payeeTable = (getRealTable() == QStringLiteral("payee")); 0076 m_trackerTable = (getRealTable() == QStringLiteral("refund")); 0077 m_recurrentoperationTable = (getRealTable() == QStringLiteral("recurrentoperation")); 0078 m_accountTable = (getRealTable() == QStringLiteral("account")); 0079 m_unitTable = (getRealTable() == QStringLiteral("unit")); 0080 m_unitvalueTable = (getRealTable() == QStringLiteral("unitvalue")); 0081 m_suboperationTable = (getTable() == QStringLiteral("v_suboperation_consolidated")); 0082 m_ruleTable = (getRealTable() == QStringLiteral("rule")); 0083 m_categoryTable = (getRealTable() == QStringLiteral("category")); 0084 m_interestTable = (getRealTable() == QStringLiteral("interest")); 0085 m_interestResultTable = (getRealTable() == QStringLiteral("interest_result")); 0086 m_budgetTable = (getRealTable() == QStringLiteral("budget")); 0087 m_budgetRuleTable = (getRealTable() == QStringLiteral("budgetrule")); 0088 0089 if (m_unitvalueTable) { 0090 SKGUnitValueObject unitValObject(getObject(this->index(0, 0))); 0091 SKGUnitObject unitObject; 0092 unitValObject.getUnit(unitObject); 0093 SKGUnitObject parentUnit; 0094 unitObject.getUnit(parentUnit); 0095 if (parentUnit.exist()) { 0096 m_cacheUnit.Name = parentUnit.getName(); 0097 m_cacheUnit.Symbol = parentUnit.getSymbol(); 0098 m_cacheUnit.Value = 1; 0099 m_cacheUnit.NbDecimal = unitObject.getNumberDecimal(); 0100 } else { 0101 m_cacheUnit.Name = QLatin1String(""); 0102 m_cacheUnit.Symbol = QLatin1String(""); 0103 m_cacheUnit.Value = 1; 0104 m_cacheUnit.NbDecimal = unitObject.getNumberDecimal(); 0105 } 0106 if (m_cacheUnit.Symbol.isEmpty()) { 0107 m_cacheUnit.Symbol = ' '; 0108 } 0109 0110 // Bug 209672 vvvv 0111 if (unitObject.getType() == SKGUnitObject::INDEX) { 0112 m_cacheUnit.Symbol = ' '; 0113 m_cacheUnit.Name = ' '; 0114 } 0115 // Bug 209672 ^^^^ 0116 } 0117 0118 if (m_operationTable) { 0119 // Read Setting 0120 KSharedConfigPtr config = KSharedConfig::openConfig(); 0121 KConfigGroup pref = config->group("skrooge_operation"); 0122 m_fontFutureOperationsColor = QVariant::fromValue(pref.readEntry("fontFutureColor", QColor(Qt::gray))); 0123 m_fontNotValidatedOperationsColor = QVariant::fromValue(pref.readEntry("fontNotValidatedColor", QColor(Qt::blue))); 0124 m_fontSubOperationsColor = QVariant::fromValue(pref.readEntry("fontSubOperationColor", QColor(Qt::darkGreen))); 0125 } 0126 0127 if (m_recurrentoperationTable) { 0128 // Read Setting 0129 KSharedConfigPtr config = KSharedConfig::openConfig(); 0130 KConfigGroup pref = config->group("skrooge_scheduled"); 0131 m_fontDisabledScheduleColor = QVariant::fromValue(pref.readEntry("fontFutureColor", QColor(Qt::gray))); 0132 } 0133 0134 m_iconFavorite = SKGServices::fromTheme(QStringLiteral("bookmarks")); 0135 0136 if (m_operationTable || m_recurrentoperationTable) { 0137 m_iconTransfer = SKGServices::fromTheme(QStringLiteral("exchange-positions")); 0138 QStringList overlays; 0139 overlays.push_back(QStringLiteral("list-remove")); 0140 m_iconGroup = SKGServices::fromTheme(QStringLiteral("exchange-positions"), overlays); 0141 m_iconSplit = SKGServices::fromTheme(QStringLiteral("split")); 0142 m_iconImported = SKGServices::fromTheme(QStringLiteral("utilities-file-archiver")); 0143 { 0144 QStringList overlay; 0145 overlay.push_back(QStringLiteral("dialog-ok")); 0146 m_iconImportedChecked = SKGServices::fromTheme(QStringLiteral("utilities-file-archiver"), overlay); 0147 } 0148 0149 m_iconRecurrent = SKGServices::fromTheme(QStringLiteral("chronometer")); 0150 { 0151 QStringList overlay; 0152 overlay.push_back(QStringLiteral("bookmarks")); 0153 m_iconRecurrentMaster = SKGServices::fromTheme(QStringLiteral("chronometer"), overlay); 0154 } 0155 } 0156 0157 if (m_budgetTable) { 0158 m_iconGreen = SKGServices::fromTheme(QStringLiteral("security-high")); 0159 m_iconRed = SKGServices::fromTheme(QStringLiteral("security-low")); 0160 m_iconAnber = SKGServices::fromTheme(QStringLiteral("security-medium")); 0161 } 0162 0163 if (m_unitTable) { 0164 m_iconMuchMore = SKGServices::fromTheme(QStringLiteral("skrooge_much_more")); 0165 m_iconMuchLess = SKGServices::fromTheme(QStringLiteral("skrooge_much_less")); 0166 m_iconMore = SKGServices::fromTheme(QStringLiteral("skrooge_more")); 0167 m_iconLess = SKGServices::fromTheme(QStringLiteral("skrooge_less")); 0168 } 0169 0170 if (m_ruleTable) { 0171 m_iconSearch = SKGServices::fromTheme(QStringLiteral("edit-find")); 0172 m_iconUpdate = SKGServices::fromTheme(QStringLiteral("view-refresh")); 0173 m_iconAlarm = SKGServices::fromTheme(QStringLiteral("dialog-warning")); 0174 m_iconTemplate = SKGServices::fromTheme(QStringLiteral("edit-guides")); 0175 } 0176 m_iconClosed = SKGServices::fromTheme(QStringLiteral("dialog-close")); 0177 0178 if (m_categoryTable) { 0179 m_iconCategory = SKGServices::fromTheme(QStringLiteral("view-categories")); 0180 m_iconCategoryMoins = SKGServices::fromTheme(QStringLiteral("view-categories-expenditures")); 0181 m_iconCategoryPlus = SKGServices::fromTheme(QStringLiteral("view-categories-incomes")); 0182 } 0183 } 0184 0185 SKGObjectModel::~SKGObjectModel() 0186 { 0187 SKGTRACEINFUNC(1) 0188 } 0189 0190 QVariant SKGObjectModel::headerData(int section, Qt::Orientation orientation, int role) const 0191 { 0192 _SKGTRACEINFUNC(10) 0193 0194 if (orientation == Qt::Horizontal) { 0195 if (role == Qt::DisplayRole || role == Qt::ToolTipRole) { 0196 QString att; 0197 if (section >= 0 && section < m_listAttibutes.count()) { 0198 att = m_listAttibutes[section]; 0199 } else { 0200 att = SKGServices::intToString(section); 0201 } 0202 0203 if (att == QStringLiteral("t_bookmarked") || att == QStringLiteral("i_NBRECURRENT") || att == QStringLiteral("t_status") || att == QStringLiteral("t_close") || att == QStringLiteral("t_imported")) { 0204 return (role == Qt::ToolTipRole) ? SKGObjectModelBase::headerData(section, orientation, Qt::DisplayRole) : ""; 0205 } 0206 } 0207 } 0208 return SKGObjectModelBase::headerData(section, orientation, role); 0209 } 0210 0211 QString SKGObjectModel::getAttributeForGrouping(const SKGObjectBase& iObject, const QString& iAttribute) const 0212 { 0213 if (m_recurrentoperationTable && iAttribute == QStringLiteral("i_nb_times")) { 0214 if (iObject.getAttribute(QStringLiteral("t_times")) != QStringLiteral("Y")) { 0215 return QChar(8734); 0216 } 0217 } else if (m_ruleTable && iAttribute == QStringLiteral("t_action_type")) { 0218 QString val = iObject.getAttribute(iAttribute); 0219 if (val == QStringLiteral("S")) { 0220 val = i18nc("Noun, a search", "Search"); 0221 } else if (val == QStringLiteral("U")) { 0222 val = i18nc("Noun, a modification", "Update"); 0223 } else { 0224 val = i18nc("Noun, an alarm", "Alarm"); 0225 } 0226 return val; 0227 } else if (iAttribute == QStringLiteral("t_bookmarked") || iAttribute == QStringLiteral("t_close")) { 0228 QString val = iObject.getAttribute(iAttribute); 0229 return val == QStringLiteral("Y") ? i18n("Yes") : i18n("No"); 0230 } else if (iAttribute == QStringLiteral("t_status")) { 0231 QString val = iObject.getAttribute(iAttribute); 0232 return val == QStringLiteral("N") ? i18n("None") : val == QStringLiteral("P") ? i18n("Marked") : i18n("Checked"); 0233 } 0234 return SKGObjectModelBase::getAttributeForGrouping(iObject, iAttribute); 0235 } 0236 0237 QVariant SKGObjectModel::computeData(const QModelIndex& iIndex, int iRole) const 0238 { 0239 if (!iIndex.isValid()) { 0240 return QVariant(); 0241 } 0242 _SKGTRACEINFUNC(10) 0243 SKGObjectBase* obj = getObjectPointer(iIndex); 0244 if (obj == nullptr || obj->getTable().isEmpty()) { 0245 return SKGObjectModelBase::computeData(iIndex, iRole); 0246 } 0247 0248 switch (iRole) { 0249 case Qt::DisplayRole: 0250 case Qt::EditRole: 0251 case Qt::UserRole: { 0252 QString att = m_listAttibutes[iIndex.column()]; 0253 QString val = obj->getAttribute(att); 0254 if (att == QStringLiteral("i_NBRECURRENT")) { 0255 if (iRole == Qt::UserRole) { 0256 if (val != QStringLiteral("0")) { 0257 return QLatin1String("Y"); 0258 } 0259 if (obj->getAttribute(QStringLiteral("r_recurrentoperation_id")) != QStringLiteral("0")) { 0260 return QLatin1String("Y"); 0261 } 0262 return QLatin1String("N"); 0263 } 0264 return ""; 0265 } 0266 if (att == QStringLiteral("t_bookmarked") || 0267 att == QStringLiteral("t_status") || 0268 att == QStringLiteral("t_imported") || 0269 att == QStringLiteral("t_close") || 0270 att == QStringLiteral("t_action_type") 0271 ) { 0272 if (iRole == Qt::UserRole) { 0273 if (m_ruleTable && att == QStringLiteral("t_action_type")) { 0274 if (val == QStringLiteral("S")) { 0275 return i18nc("Noun, a search", "Search"); 0276 } 0277 if (val == QStringLiteral("U")) { 0278 return i18nc("Noun, a modification", "Update"); 0279 } 0280 return i18nc("Noun, an alarm", "Alarm"); 0281 } 0282 return val; 0283 } 0284 return ""; 0285 } 0286 if (m_interestTable && att == QStringLiteral("t_expenditure_value_date_mode")) { 0287 if (val == QStringLiteral("0")) { 0288 return i18nc("Noun", "Day -0"); 0289 } 0290 if (val == QStringLiteral("1")) { 0291 return i18nc("Noun", "Day -1"); 0292 } 0293 if (val == QStringLiteral("2")) { 0294 return i18nc("Noun", "Day -2"); 0295 } 0296 if (val == QStringLiteral("3")) { 0297 return i18nc("Noun", "Day -3"); 0298 } 0299 if (val == QStringLiteral("4")) { 0300 return i18nc("Noun", "Day -4"); 0301 } 0302 if (val == QStringLiteral("5")) { 0303 return i18nc("Noun", "Day -5"); 0304 } 0305 return i18nc("Noun", "Fifteen"); 0306 } 0307 if (m_accountTable && att == QStringLiteral("d_reconciliationdate")) { 0308 if (val.isEmpty() && iRole == Qt::DisplayRole) { 0309 return i18nc("Noun", "Never"); 0310 } 0311 } else if (m_interestTable && att == QStringLiteral("t_income_value_date_mode")) { 0312 if (val == QStringLiteral("0")) { 0313 return i18nc("Noun", "Day +0"); 0314 } 0315 if (val == QStringLiteral("1")) { 0316 return i18nc("Noun", "Day +1"); 0317 } 0318 if (val == QStringLiteral("2")) { 0319 return i18nc("Noun", "Day +2"); 0320 } 0321 if (val == QStringLiteral("3")) { 0322 return i18nc("Noun", "Day +3"); 0323 } 0324 if (val == QStringLiteral("4")) { 0325 return i18nc("Noun", "Day +4"); 0326 } 0327 if (val == QStringLiteral("5")) { 0328 return i18nc("Noun", "Day +5"); 0329 } 0330 return i18nc("Noun", "Fifteen"); 0331 } 0332 if (getAttributeType(iIndex.column()) == SKGServices::FLOAT) { 0333 double dval = SKGServices::stringToDouble(val); 0334 if (iRole == Qt::DisplayRole) { 0335 if (val.isEmpty()) { 0336 return ""; 0337 } 0338 if (att.endsWith(QLatin1String("_INCOME")) || 0339 att.endsWith(QLatin1String("_EXPENSE")) || 0340 (m_operationTable && obj->getAttribute(QStringLiteral("t_template")) == QStringLiteral("Y")) || 0341 (m_categoryTable && (att == QStringLiteral("f_REALCURRENTAMOUNT") || 0342 att == QStringLiteral("f_SUMCURRENTAMOUNT")))) { 0343 if (dval == 0) { 0344 return ""; 0345 } 0346 } 0347 0348 SKGServices::SKGUnitInfo unit; 0349 unit.Symbol = QLatin1String(""); 0350 unit.NbDecimal = 2; 0351 if (!att.contains(QStringLiteral("QUANTITY")) && !att.contains(QStringLiteral("f_BALANCE_ENTERED"))) { 0352 unit = qobject_cast<SKGDocumentBank*>(getDocument())->getPrimaryUnit(); 0353 unit.NbDecimal = SKGServices::stringToInt(obj->getAttribute(QStringLiteral("i_NBDEC"))); 0354 if (unit.NbDecimal == 0) { 0355 unit.NbDecimal = 2; 0356 } 0357 if (m_unitvalueTable && !m_cacheUnit.Symbol.isEmpty()) { 0358 unit = m_cacheUnit; 0359 } 0360 } else { 0361 unit.NbDecimal = SKGServices::stringToInt(obj->getAttribute(QStringLiteral("i_NBDEC"))); 0362 if (unit.NbDecimal == 0) { 0363 unit.NbDecimal = 2; 0364 } 0365 if (att != QStringLiteral("f_QUANTITYOWNED")) { 0366 unit.Symbol = obj->getAttribute(QStringLiteral("t_UNIT")); 0367 } 0368 } 0369 0370 // Bug 209672 vvvv 0371 if (m_unitTable) { 0372 if (obj->getAttribute(QStringLiteral("t_type")) == QStringLiteral("I")) { 0373 unit.Symbol = ' '; 0374 } 0375 } 0376 // Bug 209672 ^^^ 0377 0378 if (QString::compare(att, QStringLiteral("f_rate"), Qt::CaseInsensitive) == 0) { 0379 unit.Symbol = '%'; 0380 unit.NbDecimal = 2; 0381 } else if (att == QStringLiteral("f_coef")) { 0382 unit.Symbol = QLatin1String(""); 0383 unit.NbDecimal = 2; 0384 } 0385 0386 if (unit.Symbol.isEmpty()) { 0387 unit.Symbol = ' '; 0388 } 0389 0390 return SKGServices::toCurrencyString(dval, unit.Symbol, unit.NbDecimal); 0391 } 0392 return dval; 0393 } 0394 if (getAttributeType(iIndex.column()) == SKGServices::INTEGER) { 0395 if (m_recurrentoperationTable && att == QStringLiteral("i_nb_times")) { 0396 QString t_times = obj->getAttribute(QStringLiteral("t_times")); 0397 if (t_times != QStringLiteral("Y")) { 0398 return QChar(8734); 0399 } 0400 } else if ((att == QStringLiteral("i_NBOPERATIONS") || att == QStringLiteral("i_SUMNBOPERATIONS")) && val == QStringLiteral("0")) { 0401 return ""; 0402 } 0403 0404 return SKGServices::stringToInt(val); 0405 } 0406 if (m_suboperationTable && att.startsWith(QLatin1String("p_"))) { 0407 val = obj->getProperty(att.right(att.count() - 2)); 0408 if (val.isEmpty()) { 0409 val = obj->getDocument()->getParameter(att.right(att.count() - 2), obj->getAttribute(QStringLiteral("i_OPID")) % "-operation"); 0410 } 0411 return val; 0412 } 0413 if (m_payeeTable && att == QStringLiteral("t_CATEGORY") && val.isEmpty()) { 0414 auto c = qobject_cast<SKGDocumentBank*>(getDocument())->getCategoryForPayee(obj->getAttribute(QStringLiteral("t_name"))); 0415 if (!c.isEmpty()) { 0416 return i18n("Auto: %1", c); 0417 } 0418 } 0419 break; 0420 } 0421 case Qt::DecorationRole: { 0422 // decoration 0423 QString att = m_listAttibutes[iIndex.column()]; 0424 if (att == QStringLiteral("t_bookmarked")) { 0425 if (obj->getAttribute(QStringLiteral("t_bookmarked")) == QStringLiteral("Y")) { 0426 return m_iconFavorite; 0427 } 0428 } else if (m_operationTable || m_recurrentoperationTable) { 0429 if (att == QStringLiteral("t_mode")) { 0430 if (obj->getAttribute(QStringLiteral("t_TRANSFER")) == QStringLiteral("Y")) { 0431 return m_iconTransfer; 0432 } 0433 if (obj->getAttribute(QStringLiteral("i_group_id")) != QStringLiteral("0")) { 0434 return m_iconGroup; 0435 } 0436 } else if (att == QStringLiteral("t_CATEGORY")) { 0437 if (SKGServices::stringToInt(obj->getAttribute(QStringLiteral("i_NBSUBOPERATIONS"))) > 1) { 0438 return m_iconSplit; 0439 } 0440 } else if (att == QStringLiteral("i_NBRECURRENT") && m_operationTable) { 0441 if (obj->getAttribute(QStringLiteral("i_NBRECURRENT")) != QStringLiteral("0")) { 0442 return m_iconRecurrentMaster; 0443 } 0444 if (obj->getAttribute(QStringLiteral("r_recurrentoperation_id")) != QStringLiteral("0")) { 0445 return m_iconRecurrent; 0446 } 0447 } else if (att == QStringLiteral("t_imported")) { 0448 QString impStatus = obj->getAttribute(QStringLiteral("t_imported")); 0449 if (impStatus == QStringLiteral("Y")) { 0450 return m_iconImported; 0451 } 0452 if (impStatus == QStringLiteral("P")) { 0453 return m_iconImportedChecked; 0454 } 0455 } else if (att == QStringLiteral("t_REFUND") || att == QStringLiteral("t_REALREFUND") || att == QStringLiteral("t_REFUNDDISPLAY")) { 0456 if (att == QStringLiteral("t_REFUNDDISPLAY")) { 0457 if (obj->getAttribute(att).count(QStringLiteral("(")) > 1) { 0458 att.clear(); 0459 } else { 0460 att = QStringLiteral("t_REFUND"); 0461 } 0462 } 0463 if (!att.isEmpty()) { 0464 QString trackerName; 0465 trackerName = obj->getAttribute(att); 0466 if (!trackerName.isEmpty()) { 0467 SKGTrackerObject tracker(SKGObjectBase(getDocument(), QStringLiteral("refund"))); // Better performance if v_refund is not used 0468 tracker.setName(trackerName); 0469 tracker.load(); 0470 0471 if (tracker.isClosed()) { 0472 return m_iconClosed; 0473 } 0474 } 0475 } 0476 } 0477 } else if (m_ruleTable) { 0478 if (att == QStringLiteral("t_action_type")) { 0479 QString val = obj->getAttribute(att); 0480 if (val == QStringLiteral("S")) { 0481 return m_iconSearch; 0482 } 0483 if (val == QStringLiteral("U")) { 0484 return m_iconUpdate; 0485 } 0486 if (val == QStringLiteral("T")) { 0487 return m_iconTemplate; 0488 } 0489 return m_iconAlarm; 0490 } 0491 } else if (m_unitTable) { 0492 if (att == QStringLiteral("f_CURRENTAMOUNT")) { 0493 SKGUnitObject unit(*obj); 0494 double amountOneYearBefore = unit.getAmount(QDate::currentDate().addYears(-1)); 0495 double annualchange = 100.0 * (unit.getAmount() - amountOneYearBefore) / amountOneYearBefore; 0496 if (annualchange >= 10) { 0497 return m_iconMuchMore; 0498 } 0499 if (annualchange <= -10) { 0500 return m_iconMuchLess; 0501 } 0502 if (annualchange > 0) { 0503 return m_iconMore; 0504 } 0505 if (annualchange < 0) { 0506 return m_iconLess; 0507 } 0508 } 0509 } else if (m_accountTable) { 0510 SKGAccountObject act(*obj); 0511 if (att == QStringLiteral("t_BANK")) { 0512 const bool wallet = (act.getType() == SKGAccountObject::WALLET); 0513 QString t_icon = wallet ? QStringLiteral("wallet-closed") : obj->getAttribute(QStringLiteral("t_icon")); 0514 if (t_icon.isEmpty()) { 0515 t_icon = obj->getAttribute(QStringLiteral("t_ICON")); 0516 } 0517 if (!t_icon.isEmpty()) { 0518 QString fileName = QStandardPaths::locate(QStandardPaths::GenericDataLocation, "skrooge/images/logo/" % t_icon); 0519 if (fileName.isEmpty()) { 0520 fileName = t_icon; 0521 } 0522 return QVariant::fromValue(SKGServices::fromTheme(fileName)); 0523 } 0524 } else if (att == QStringLiteral("f_importbalance")) { 0525 QString val = obj->getAttribute(att); 0526 if (val.isEmpty()) { 0527 return ""; 0528 } 0529 0530 // Compute value 0531 auto soluces = act.getPossibleReconciliations(SKGServices::stringToDouble(val), false); 0532 return SKGServices::fromTheme(soluces.isEmpty() ? QStringLiteral("security-low") : QStringLiteral("security-high")); 0533 } else if (att == QStringLiteral("f_reconciliationbalance")) { 0534 QString val = obj->getAttribute(att); 0535 if (val.isEmpty()) { 0536 return ""; 0537 } 0538 0539 // Compute value 0540 auto soluces = act.getPossibleReconciliations(SKGServices::stringToDouble(val), false); 0541 return SKGServices::fromTheme(soluces.isEmpty() ? QStringLiteral("security-low") : QStringLiteral("security-high")); 0542 } 0543 } else if (m_categoryTable) { 0544 if (iIndex.column() == 0) { 0545 QString t_TYPEEXPENSE = obj->getAttribute(QStringLiteral("t_TYPEEXPENSE")); 0546 if (t_TYPEEXPENSE == QStringLiteral("-")) { 0547 return m_iconCategoryMoins; 0548 } 0549 if (t_TYPEEXPENSE == QStringLiteral("+")) { 0550 return m_iconCategoryPlus; 0551 } 0552 return m_iconCategory; 0553 } 0554 } else if (m_budgetTable) { 0555 if (att == QStringLiteral("f_DELTA") || att == QStringLiteral("f_DELTABEFORETRANSFER")) { 0556 double val = SKGServices::stringToDouble(obj->getAttribute(att)); 0557 if (val < -EPSILON) { 0558 return m_iconRed; 0559 } 0560 if (val > EPSILON) { 0561 return m_iconGreen; 0562 } 0563 double transferred = SKGServices::stringToDouble(obj->getAttribute(QStringLiteral("f_transferred"))); 0564 if (transferred < -EPSILON) { 0565 return m_iconAnber; 0566 } 0567 return m_iconGreen; 0568 } 0569 } 0570 break; 0571 } 0572 case Qt::TextColorRole: { 0573 // Text color 0574 QString att = m_listAttibutes[iIndex.column()]; 0575 if (m_recurrentoperationTable) { 0576 if (obj->getAttribute(QStringLiteral("i_nb_times")) == QStringLiteral("0")) { 0577 return m_fontDisabledScheduleColor; 0578 } 0579 if (att == QStringLiteral("d_date") && SKGServices::stringToTime(obj->getAttribute(QStringLiteral("d_date"))).date() <= QDate::currentDate()) { 0580 return m_fontNegativeColor; 0581 } 0582 } else if (m_operationTable) { 0583 if (SKGServices::stringToTime(obj->getAttribute(QStringLiteral("d_date"))).date() > QDate::currentDate()) { 0584 return m_fontFutureOperationsColor; 0585 } 0586 if (getAttributeType(iIndex.column()) != SKGServices::FLOAT) { 0587 if (obj->getAttribute(QStringLiteral("t_imported")) == QStringLiteral("P")) { 0588 return m_fontNotValidatedOperationsColor; 0589 } 0590 if (m_suboperationTable) { 0591 return m_fontSubOperationsColor; 0592 } 0593 } 0594 } 0595 break; 0596 } 0597 case Qt::TextAlignmentRole: { 0598 // Text alignment 0599 if (m_recurrentoperationTable) { 0600 QString att = m_listAttibutes[iIndex.column()]; 0601 0602 if (att == QStringLiteral("i_auto_write_days") || att == QStringLiteral("i_warn_days") || att == QStringLiteral("i_nb_times")) { 0603 return static_cast<int>(Qt::AlignVCenter | Qt::AlignLeft); 0604 } 0605 } 0606 break; 0607 } 0608 case Qt::CheckStateRole: { 0609 // CheckState 0610 QString att = m_listAttibutes[iIndex.column()]; 0611 if (m_operationTable && att == QStringLiteral("t_status")) { 0612 QString cond = obj->getAttribute(QStringLiteral("t_status")); 0613 if (cond == QStringLiteral("P")) { 0614 return static_cast<int>(Qt::PartiallyChecked); 0615 } 0616 if (cond == QStringLiteral("Y")) { 0617 return static_cast<int>(Qt::Checked); 0618 } 0619 if (cond == QStringLiteral("N")) { 0620 return static_cast<int>(Qt::Unchecked); 0621 } 0622 } else if (att == QStringLiteral("t_close")) { 0623 QString cond = obj->getAttribute(QStringLiteral("t_close")); 0624 if (cond == QStringLiteral("Y")) { 0625 return static_cast<int>(Qt::Checked); 0626 } 0627 return static_cast<int>(Qt::Unchecked); 0628 0629 } else if (m_recurrentoperationTable && att == QStringLiteral("i_auto_write_days")) { 0630 QString cond = obj->getAttribute(QStringLiteral("t_auto_write")); 0631 if (cond == QStringLiteral("Y")) { 0632 return static_cast<int>(Qt::Checked); 0633 } 0634 return static_cast<int>(Qt::Unchecked); 0635 0636 } else if (m_recurrentoperationTable && att == QStringLiteral("i_warn_days")) { 0637 QString cond = obj->getAttribute(QStringLiteral("t_warn")); 0638 if (cond == QStringLiteral("Y")) { 0639 return static_cast<int>(Qt::Checked); 0640 } 0641 return static_cast<int>(Qt::Unchecked); 0642 0643 } else if (m_recurrentoperationTable && att == QStringLiteral("i_nb_times")) { 0644 QString cond = obj->getAttribute(QStringLiteral("t_times")); 0645 if (cond == QStringLiteral("Y")) { 0646 return static_cast<int>(Qt::Checked); 0647 } 0648 return static_cast<int>(Qt::Unchecked); 0649 0650 } else if (m_budgetRuleTable && att == QStringLiteral("t_CATEGORYCONDITION")) { 0651 QString cond = obj->getAttribute(QStringLiteral("t_category_condition")); 0652 if (cond == QStringLiteral("Y")) { 0653 return static_cast<int>(Qt::Checked); 0654 } 0655 return static_cast<int>(Qt::Unchecked); 0656 0657 } else if (m_budgetRuleTable && att == QStringLiteral("i_year")) { 0658 QString cond = obj->getAttribute(QStringLiteral("t_year_condition")); 0659 if (cond == QStringLiteral("Y")) { 0660 return static_cast<int>(Qt::Checked); 0661 } 0662 return static_cast<int>(Qt::Unchecked); 0663 0664 } else if (m_budgetRuleTable && att == QStringLiteral("i_month")) { 0665 QString cond = obj->getAttribute(QStringLiteral("t_month_condition")); 0666 if (cond == QStringLiteral("Y")) { 0667 return static_cast<int>(Qt::Checked); 0668 } 0669 return static_cast<int>(Qt::Unchecked); 0670 0671 } else if (m_budgetRuleTable && att == QStringLiteral("t_CATEGORY")) { 0672 QString cond = obj->getAttribute(QStringLiteral("t_category_target")); 0673 if (cond == QStringLiteral("Y")) { 0674 return static_cast<int>(Qt::Checked); 0675 } 0676 return static_cast<int>(Qt::Unchecked); 0677 0678 } else if (m_budgetTable && att == QStringLiteral("t_CATEGORY")) { 0679 QString cond = obj->getAttribute(QStringLiteral("t_including_subcategories")); 0680 if (cond == QStringLiteral("Y")) { 0681 return static_cast<int>(Qt::Checked); 0682 } 0683 return static_cast<int>(Qt::Unchecked); 0684 } 0685 break; 0686 } 0687 case Qt::ToolTipRole: { 0688 // Tooltip 0689 QString toolTipString; 0690 QString att = m_listAttibutes[iIndex.column()]; 0691 if (getAttributeType(iIndex.column()) == SKGServices::FLOAT) { 0692 // Add secondary unit 0693 if (!att.contains(QStringLiteral("QUANTITY")) && att != QStringLiteral("f_coef") && att != QStringLiteral("f_rate")) { 0694 SKGServices::SKGUnitInfo secondaryUnit = qobject_cast<SKGDocumentBank*>(getDocument())->getSecondaryUnit(); 0695 if (!secondaryUnit.Symbol.isEmpty()) { 0696 double val = SKGServices::stringToDouble(obj->getAttribute(att)); 0697 if ((!att.endsWith(QLatin1String("_INCOME")) && !att.endsWith(QLatin1String("_EXPENSE"))) || val != 0) { 0698 if (secondaryUnit.Value != 0.0) { 0699 toolTipString = SKGServices::toCurrencyString(val / secondaryUnit.Value, secondaryUnit.Symbol, secondaryUnit.NbDecimal); 0700 } 0701 } 0702 } 0703 } 0704 0705 // Add balance 0706 if (m_operationTable && !m_suboperationTable) { 0707 SKGOperationObject op(*obj); 0708 if (!op.isTemplate()) { 0709 SKGServices::SKGUnitInfo primaryUnit = qobject_cast<SKGDocumentBank*>(getDocument())->getPrimaryUnit(); 0710 0711 // Add original amount 0712 QString originalAmount = obj->getProperty(QStringLiteral("SKG_OP_ORIGINAL_AMOUNT")); 0713 if (!originalAmount.isEmpty()) { 0714 if (!toolTipString.isEmpty()) { 0715 toolTipString += QStringLiteral("\n\n"); 0716 } 0717 double val1 = SKGServices::stringToDouble(obj->getAttribute(QStringLiteral("f_CURRENTAMOUNT"))); 0718 double val2 = SKGServices::stringToDouble(originalAmount); 0719 double gain = (val2 != 0 ? 100.0 * (val1 - val2) / val2 : 0); 0720 double gainperyear = gain; 0721 0722 int nbDays = op.getDate().daysTo(QDate::currentDate()); 0723 if (nbDays != 0 && val2 != 0) { 0724 double gainperday = 100.0 * expm1(log(val1 / val2) / static_cast<double>(nbDays)); 0725 gainperyear = 100.0 * (pow(1.0 + gainperday / 100.0, 365.0) - 1); 0726 } 0727 toolTipString += i18nc("Noun", "Original amount=%1 (%2 = %3 / year)", 0728 SKGServices::toCurrencyString(val2, primaryUnit.Symbol, primaryUnit.NbDecimal), 0729 (gain >= 0 ? "+" : "-") % SKGServices::toPercentageString(gain, 2), 0730 (gainperyear >= 0 ? "+" : "-") % SKGServices::toPercentageString(gainperyear, 2)); 0731 } else { 0732 if (!toolTipString.isEmpty()) { 0733 toolTipString += QStringLiteral("\n\n"); 0734 } 0735 double val1 = SKGServices::stringToDouble(obj->getAttribute(QStringLiteral("f_CURRENTAMOUNT"))); 0736 double val2 = op.getAmount(op.getDate()); 0737 double gain = (val2 != 0 ? 100.0 * (val1 - val2) / val2 : 0); 0738 double gainperyear = gain; 0739 0740 int nbDays = op.getDate().daysTo(QDate::currentDate()); 0741 if (nbDays != 0 && val2 != 0) { 0742 double gainperday = 100.0 * expm1(log(val1 / val2) / static_cast<double>(nbDays)); 0743 gainperyear = 100.0 * (pow(1.0 + gainperday / 100.0, 365.0) - 1); 0744 } 0745 0746 QString sval1 = SKGServices::toCurrencyString(val1, primaryUnit.Symbol, primaryUnit.NbDecimal); 0747 QString sval2 = SKGServices::toCurrencyString(val2, primaryUnit.Symbol, primaryUnit.NbDecimal); 0748 if (sval1 != sval2) { 0749 toolTipString += i18nc("Noun", "Amount at creation date=%1 (%2 = %3 / year)", 0750 sval2, 0751 (gain >= 0 ? "+" : "-") % SKGServices::toPercentageString(gain, 2), 0752 (gainperyear >= 0 ? "+" : "-") % SKGServices::toPercentageString(gainperyear, 2)); 0753 0754 toolTipString += '\n'; 0755 } 0756 } 0757 toolTipString += i18nc("Noun", "Account balance=%1", 0758 SKGServices::toCurrencyString(op.getBalance(), primaryUnit.Symbol, primaryUnit.NbDecimal)); 0759 } 0760 } 0761 0762 if (m_budgetTable) { 0763 if (att == QStringLiteral("f_DELTA")) { 0764 double val = SKGServices::stringToDouble(obj->getAttribute(QStringLiteral("f_DELTABEFORETRANSFER"))); 0765 0766 if (!toolTipString.isEmpty()) { 0767 toolTipString += QStringLiteral("\n\n"); 0768 } 0769 0770 SKGServices::SKGUnitInfo primaryUnit = qobject_cast<SKGDocumentBank*>(getDocument())->getPrimaryUnit(); 0771 toolTipString += i18nc("Noun", "Original delta=%1", 0772 SKGServices::toCurrencyString(val, primaryUnit.Symbol, primaryUnit.NbDecimal)); 0773 } else if (att == QStringLiteral("f_budgeted_modified")) { 0774 QString reasons = obj->getAttribute(QStringLiteral("t_modification_reasons")); 0775 if (!reasons.isEmpty()) { 0776 if (!toolTipString.isEmpty()) { 0777 toolTipString += QStringLiteral("\n\n"); 0778 } 0779 toolTipString += reasons; 0780 } 0781 } 0782 } 0783 0784 if (m_unitTable) { 0785 if (att == QStringLiteral("f_CURRENTAMOUNT")) { 0786 SKGUnitObject unit(*obj); 0787 double amountOneYearBefore = unit.getAmount(QDate::currentDate().addYears(-1)); 0788 double annualchange = 100.0 * (unit.getAmount() - amountOneYearBefore) / amountOneYearBefore; 0789 0790 double amount6MonthBefore = unit.getAmount(QDate::currentDate().addMonths(-6)); 0791 double sixMonthChange = 100.0 * (unit.getAmount() - amount6MonthBefore) / amount6MonthBefore; 0792 0793 double amount1MonthBefore = unit.getAmount(QDate::currentDate().addMonths(-1)); 0794 double oneMonthChange = 100.0 * (unit.getAmount() - amount1MonthBefore) / amount1MonthBefore; 0795 if (!toolTipString.isEmpty()) { 0796 toolTipString += QStringLiteral("\n\n"); 0797 } 0798 toolTipString += i18nc("Noun", "Variation on the last year = %1\n", SKGServices::toPercentageString(annualchange)); 0799 toolTipString += i18nc("Noun", "Variation on the last 6 months = %1 = %2 / year\n", SKGServices::toPercentageString(sixMonthChange), SKGServices::toPercentageString(100.0 * pow(1.0 + sixMonthChange / 100.0, 2.0) - 100.0)); 0800 toolTipString += i18nc("Noun", "Variation on the last month = %1 = %2 / year\n", SKGServices::toPercentageString(oneMonthChange), SKGServices::toPercentageString(100.0 * pow(1.0 + oneMonthChange / 100.0, 12.0) - 100.0)); 0801 } 0802 } 0803 } else if (m_operationTable || m_recurrentoperationTable) { 0804 if (att == QStringLiteral("t_imported")) { 0805 if (!m_suboperationTable) { 0806 SKGOperationObject op; 0807 if (m_recurrentoperationTable) { 0808 SKGRecurrentOperationObject rop(*obj); 0809 rop.getParentOperation(op); 0810 } else { 0811 op = *obj; 0812 } 0813 toolTipString = op.getImportID(); 0814 } 0815 } else if (att == QStringLiteral("t_REFUND") || att == QStringLiteral("t_REALREFUND") || att == QStringLiteral("t_REFUNDDISPLAY")) { 0816 if (att == QStringLiteral("t_REFUNDDISPLAY")) { 0817 if (obj->getAttribute(att).count(QStringLiteral("(")) > 1) { 0818 att.clear(); 0819 } else { 0820 att = QStringLiteral("t_REFUND"); 0821 } 0822 } 0823 if (!att.isEmpty()) { 0824 QString trackerName = obj->getAttribute(att); 0825 if (!trackerName.isEmpty()) { 0826 SKGTrackerObject tracker(getDocument()); 0827 tracker.setName(trackerName); 0828 tracker.load(); 0829 SKGServices::SKGUnitInfo unit = qobject_cast<SKGDocumentBank*>(getDocument())->getPrimaryUnit(); 0830 toolTipString = SKGServices::toCurrencyString(tracker.getCurrentAmount(), unit.Symbol, unit.NbDecimal); 0831 } 0832 } 0833 } else if (att == QStringLiteral("t_PAYEE")) { 0834 QString payeeName = obj->getAttribute(att); 0835 if (!payeeName.isEmpty()) { 0836 SKGPayeeObject payee(getDocument()); 0837 payee.setName(payeeName); 0838 payee.load(); 0839 0840 auto address = payee.getAddress(); 0841 if (!address.isEmpty()) { 0842 toolTipString += i18nc("Information", "Address= %1\n", address); 0843 } 0844 0845 auto c = payee.getAttribute(QStringLiteral("t_CATEGORY")); 0846 if (c.isEmpty()) { 0847 c = qobject_cast<SKGDocumentBank*>(getDocument())->getCategoryForPayee(payeeName, false); 0848 } 0849 if (!c.isEmpty()) { 0850 toolTipString += i18nc("Information", "Category= %1\n", c); 0851 } 0852 } 0853 } else if (att == QStringLiteral("t_ACCOUNT") || att == QStringLiteral("t_TOACCOUNT")) { 0854 QString accountName = obj->getAttribute(att); 0855 if (!accountName.isEmpty()) { 0856 SKGAccountObject account(getDocument()); 0857 account.setName(accountName); 0858 account.load(); 0859 0860 auto tmp = account.getAgencyNumber(); 0861 if (!tmp.isEmpty()) { 0862 toolTipString += i18nc("Information", "Agency number= %1\n", tmp); 0863 } 0864 0865 tmp = account.getNumber(); 0866 if (!tmp.isEmpty()) { 0867 toolTipString += i18nc("Information", "Number= %1\n", tmp); 0868 } 0869 0870 tmp = account.getAgencyAddress(); 0871 if (!tmp.isEmpty()) { 0872 toolTipString += i18nc("Information", "Address= %1\n", tmp); 0873 } 0874 0875 tmp = account.getComment(); 0876 if (!tmp.isEmpty()) { 0877 toolTipString += i18nc("Information", "Comment= %1\n", tmp); 0878 } 0879 } 0880 } else if (att == QStringLiteral("t_CATEGORY")) { 0881 SKGOperationObject op(*obj); 0882 if (m_recurrentoperationTable) { 0883 SKGRecurrentOperationObject rop(*obj); 0884 rop.getParentOperation(op); 0885 } 0886 if (SKGServices::stringToInt(op.getAttribute(QStringLiteral("i_NBSUBOPERATIONS"))) > 1) { 0887 SKGObjectBase::SKGListSKGObjectBase subOps; 0888 op.getSubOperations(subOps); 0889 for (const auto& subOp : qAsConst(subOps)) { 0890 toolTipString += subOp.getDisplayName() % '\n'; 0891 } 0892 } 0893 } else if (att == QStringLiteral("t_mode")) { 0894 SKGOperationObject op(*obj); 0895 if (m_recurrentoperationTable) { 0896 SKGRecurrentOperationObject rop(*obj); 0897 rop.getParentOperation(op); 0898 } 0899 if (op.getAttribute(QStringLiteral("i_group_id")) != QStringLiteral("0")) { 0900 SKGOperationObject gop; 0901 op.getGroupOperation(gop); 0902 0903 SKGObjectBase::SKGListSKGObjectBase gOps; 0904 op.getGroupedOperations(gOps); 0905 for (const auto& item : qAsConst(gOps)) { 0906 SKGOperationObject gOp(item); 0907 SKGAccountObject account; 0908 gOp.getParentAccount(account); 0909 toolTipString += account.getDisplayName() % '\n'; 0910 } 0911 } 0912 } 0913 0914 if (m_operationTable && !m_suboperationTable && toolTipString.isEmpty()) { 0915 SKGOperationObject op(*obj); 0916 if (op.getStatus() == SKGOperationObject::MARKED) { 0917 toolTipString = i18nc("A tool tip", "This transaction is marked but not checked yet."); 0918 toolTipString += '\n'; 0919 toolTipString += i18nc("A tool tip", "You can use the reconciliation mode to validate marked transactions."); 0920 toolTipString += '\n'; 0921 if (att == QStringLiteral("t_status")) { 0922 toolTipString += i18nc("A tool tip", "Click in this column to switch back status."); 0923 } else { 0924 toolTipString += i18nc("A tool tip", "Click in the Status (checkmark) column to switch back status."); 0925 } 0926 toolTipString += '\n'; 0927 toolTipString += i18nc("A tool tip", "Ctrl+click to force checked status."); 0928 } else if (op.getStatus() == SKGOperationObject::CHECKED) { 0929 toolTipString = i18nc("A tool tip", "This transaction is already checked."); 0930 } else if (op.getStatus() == SKGOperationObject::NONE) { 0931 toolTipString = i18nc("A tool tip", "This transaction is not marked yet."); 0932 toolTipString += '\n'; 0933 toolTipString += i18nc("A tool tip", "Click to set marked status."); 0934 toolTipString += '\n'; 0935 toolTipString += i18nc("A tool tip", "Ctrl+click to force checked status."); 0936 } 0937 } 0938 } else if (m_ruleTable && att == QStringLiteral("t_action_type")) { 0939 QString val = obj->getAttribute(att); 0940 if (val == QStringLiteral("S")) { 0941 toolTipString = i18nc("Noun, a search", "Search"); 0942 } else if (val == QStringLiteral("U")) { 0943 toolTipString = i18nc("Noun, a modification", "Update"); 0944 } else { 0945 toolTipString = i18nc("Noun, an alarm", "Alarm"); 0946 } 0947 } 0948 0949 QString toolTipStringBase = SKGObjectModelBase::computeData(iIndex, iRole).toString(); 0950 if (!toolTipStringBase.isEmpty()) { 0951 if (!toolTipString.isEmpty()) { 0952 toolTipString += QStringLiteral("\n\n"); 0953 } 0954 toolTipString += toolTipStringBase; 0955 } 0956 return toolTipString; 0957 } 0958 default: { 0959 } 0960 } 0961 return SKGObjectModelBase::computeData(iIndex, iRole); 0962 } 0963 0964 bool SKGObjectModel::setData(const QModelIndex& iIndex, const QVariant& iValue, int iRole) 0965 { 0966 if (!iIndex.isValid()) { 0967 return false; 0968 } 0969 0970 if (iRole == Qt::CheckStateRole) { 0971 SKGError err; 0972 { 0973 auto newState = static_cast<Qt::CheckState>(iValue.toInt()); 0974 if (m_accountTable) { 0975 SKGAccountObject obj(getObject(iIndex)); 0976 SKGBEGINLIGHTTRANSACTION(*getDocument(), 0977 (newState == Qt::Checked ? i18nc("Noun, name of the user action", "Close account '%1'", obj.getName()) : i18nc("Noun, name of the user action", "Open account '%1'", obj.getName())), err); 0978 if (qAbs(obj.getCurrentAmount()) > 0.01 && newState == Qt::Checked) { 0979 err = getDocument()->sendMessage(i18nc("An information message", "Warning, you closed an account with money"), SKGDocument::Warning); 0980 } 0981 IFOKDO(err, obj.setClosed(newState == Qt::Checked)) 0982 IFOKDO(err, obj.save()) 0983 } else if (m_trackerTable) { 0984 SKGTrackerObject obj(getObject(iIndex)); 0985 SKGBEGINLIGHTTRANSACTION(*getDocument(), 0986 (newState == Qt::Checked ? i18nc("Noun, name of the user action", "Close tracker '%1'", obj.getName()) : i18nc("Noun, name of the user action", "Open tracker '%1'", obj.getName())), err); 0987 err = obj.setClosed(newState == Qt::Checked); 0988 IFOKDO(err, obj.save()) 0989 } else if (m_categoryTable) { 0990 SKGCategoryObject obj(getObject(iIndex)); 0991 SKGBEGINLIGHTTRANSACTION(*getDocument(), 0992 (newState == Qt::Checked ? i18nc("Noun, name of the user action", "Close category '%1'", obj.getName()) : i18nc("Noun, name of the user action", "Open category '%1'", obj.getName())), err); 0993 err = obj.setClosed(newState == Qt::Checked); 0994 IFOKDO(err, obj.save()) 0995 } else if (m_payeeTable) { 0996 SKGPayeeObject obj(getObject(iIndex)); 0997 SKGBEGINLIGHTTRANSACTION(*getDocument(), 0998 (newState == Qt::Checked ? i18nc("Noun, name of the user action", "Close payee '%1'", obj.getName()) : i18nc("Noun, name of the user action", "Open payee '%1'", obj.getName())), err); 0999 err = obj.setClosed(newState == Qt::Checked); 1000 IFOKDO(err, obj.save()) 1001 } else if (m_operationTable && !m_suboperationTable) { 1002 // Get the real object, not the object from the view 1003 SKGObjectBase* objtmp = getObjectPointer(iIndex); 1004 if (objtmp != nullptr) { 1005 SKGOperationObject obj = SKGOperationObject(objtmp->getDocument(), objtmp->getID()); 1006 SKGBEGINLIGHTTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Change transaction status"), err) 1007 SKGOperationObject::OperationStatus statusinitial = obj.getStatus(); 1008 SKGOperationObject::OperationStatus t_status = statusinitial; 1009 if ((QApplication::keyboardModifiers() & Qt::ControlModifier) != 0u) { 1010 // 2747379: NONE ==> CHECKED, MARKED ==> CHECKED, CHECKED ==> CHECKED 1011 t_status = SKGOperationObject::CHECKED; 1012 // t_status= ( t_status==SKGOperationObject::MARKED ? SKGOperationObject::NONE : ( t_status==SKGOperationObject::CHECKED ? SKGOperationObject::MARKED : SKGOperationObject::NONE ) ); 1013 } else { 1014 // 2747379: NONE ==> MARKED, MARKED ==> NONE, CHECKED ==> MARKED 1015 t_status = (t_status == SKGOperationObject::NONE ? SKGOperationObject::MARKED : (t_status == SKGOperationObject::MARKED ? SKGOperationObject::NONE : SKGOperationObject::MARKED)); 1016 // t_status=(t_status==SKGOperationObject::MARKED ? SKGOperationObject::CHECKED : (t_status==SKGOperationObject::CHECKED ? SKGOperationObject::CHECKED : SKGOperationObject::MARKED )); 1017 } 1018 if (t_status != statusinitial) { 1019 err = obj.setStatus(t_status); 1020 IFOKDO(err, obj.save()) 1021 1022 // Send message 1023 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The status of the transaction '%1' has been changed", obj.getDisplayName()), SKGDocument::Hidden)) 1024 } 1025 } 1026 } else if (m_recurrentoperationTable) { 1027 QString att = m_listAttibutes[iIndex.column()]; 1028 1029 // Get the real object, not the object from the view 1030 SKGObjectBase* objtmp = getObjectPointer(iIndex); 1031 if (objtmp != nullptr) { 1032 SKGRecurrentOperationObject obj = SKGRecurrentOperationObject(objtmp->getDocument(), objtmp->getID()); 1033 1034 SKGBEGINLIGHTTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Recurrent transaction update"), err) 1035 if (att == QStringLiteral("i_warn_days")) { 1036 err = obj.warnEnabled(!obj.isWarnEnabled()); 1037 } else if (att == QStringLiteral("i_auto_write_days")) { 1038 err = obj.autoWriteEnabled(!obj.isAutoWriteEnabled()); 1039 } else if (att == QStringLiteral("i_nb_times")) { 1040 err = obj.timeLimit(!obj.hasTimeLimit()); 1041 } 1042 IFOKDO(err, obj.save()) 1043 1044 // Send message 1045 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The recurrent transaction '%1' has been updated", obj.getDisplayName()), SKGDocument::Hidden)) 1046 } 1047 } else if (m_budgetRuleTable) { 1048 QString att = m_listAttibutes[iIndex.column()]; 1049 1050 // Get the real object, not the object from the view 1051 SKGObjectBase* objtmp = getObjectPointer(iIndex); 1052 if (objtmp != nullptr) { 1053 SKGBudgetRuleObject obj = SKGBudgetRuleObject(objtmp->getDocument(), objtmp->getID()); 1054 1055 SKGBEGINLIGHTTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Budget rule update"), err) 1056 if (att == QStringLiteral("i_year")) { 1057 err = obj.enableYearCondition(!obj.isYearConditionEnabled()); 1058 } else if (att == QStringLiteral("i_month")) { 1059 err = obj.enableMonthCondition(!obj.isMonthConditionEnabled()); 1060 } else if (att == QStringLiteral("t_CATEGORYCONDITION")) { 1061 err = obj.enableCategoryCondition(!obj.isCategoryConditionEnabled()); 1062 } else if (att == QStringLiteral("t_CATEGORY")) { 1063 err = obj.enableCategoryChange(!obj.isCategoryChangeEnabled()); 1064 } 1065 IFOKDO(err, obj.save()) 1066 1067 // Send message 1068 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The budget rule '%1' has been updated", obj.getDisplayName()), SKGDocument::Hidden)) 1069 } 1070 } else if (m_budgetTable) { 1071 QString att = m_listAttibutes[iIndex.column()]; 1072 1073 // Get the real object, not the object from the view 1074 SKGObjectBase* objtmp = getObjectPointer(iIndex); 1075 if (objtmp != nullptr) { 1076 SKGBudgetObject obj = SKGBudgetObject(objtmp->getDocument(), objtmp->getID()); 1077 1078 SKGBEGINTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Budget update"), err) 1079 if (att == QStringLiteral("t_CATEGORY")) { 1080 IFOKDO(err, obj.enableSubCategoriesInclusion(!obj.isSubCategoriesInclusionEnabled())) 1081 IFOKDO(err, obj.save()) 1082 1083 // Send message 1084 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The budget '%1' have been updated", obj.getDisplayName()), SKGDocument::Hidden)) 1085 } 1086 } 1087 } 1088 } 1089 1090 SKGMainPanel::displayErrorMessage(err); 1091 return !err; 1092 } 1093 return SKGObjectModelBase::setData(iIndex, iValue, iRole); 1094 } 1095 1096 Qt::ItemFlags SKGObjectModel::flags(const QModelIndex& iIndex) const 1097 { 1098 _SKGTRACEINFUNC(10) 1099 1100 Qt::ItemFlags f = SKGObjectModelBase::flags(iIndex); 1101 1102 if (iIndex.isValid()) { 1103 QString att = m_listAttibutes[iIndex.column()]; 1104 if (att == QStringLiteral("t_bookmarked") || m_ruleTable || m_recurrentoperationTable || m_interestTable || m_interestResultTable) { 1105 f = f & ~Qt::ItemIsEditable; 1106 } 1107 } 1108 1109 if (m_categoryTable || m_payeeTable || m_accountTable || m_unitTable || m_trackerTable) { 1110 if (iIndex.isValid()) { 1111 f |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; 1112 } else { 1113 f |= Qt::ItemIsDropEnabled; 1114 } 1115 } 1116 1117 return f; 1118 } 1119 1120 Qt::DropActions SKGObjectModel::supportedDragActions() const 1121 { 1122 if (m_categoryTable || m_payeeTable || m_accountTable || m_unitTable || m_trackerTable) { 1123 return Qt::MoveAction; 1124 } 1125 return SKGObjectModelBase::supportedDragActions(); 1126 } 1127 1128 Qt::DropActions SKGObjectModel::supportedDropActions() const 1129 { 1130 return SKGObjectModelBase::supportedDropActions(); 1131 } 1132 1133 bool SKGObjectModel::dropMimeData(const QMimeData* iData, 1134 Qt::DropAction iAction, 1135 int iRow, int iColumn, 1136 const QModelIndex& iParent) 1137 { 1138 if (SKGObjectModelBase::dropMimeData(iData, iAction, iRow, iColumn, iParent)) { 1139 return true; 1140 } 1141 if (iAction == Qt::IgnoreAction) { 1142 return true; 1143 } 1144 if ((iData == nullptr) || !(iData->hasFormat(QStringLiteral("application/skg.category.ids")) || 1145 iData->hasFormat(QStringLiteral("application/skg.payee.ids")) || 1146 iData->hasFormat(QStringLiteral("application/skg.account.ids")) || 1147 iData->hasFormat(QStringLiteral("application/skg.refund.ids")) || 1148 iData->hasFormat(QStringLiteral("application/skg.unit.ids")))) { 1149 return false; 1150 } 1151 if (iColumn > 0) { 1152 return false; 1153 } 1154 1155 SKGError err; 1156 if (iData->hasFormat(QStringLiteral("application/skg.category.ids"))) { 1157 QByteArray encodedData = iData->data(QStringLiteral("application/skg.category.ids")); 1158 QDataStream stream(&encodedData, QIODevice::ReadOnly); 1159 QStringList newItems; 1160 1161 SKGCategoryObject parentCategory; 1162 if (iParent.isValid()) { 1163 parentCategory = getObject(iParent); 1164 } 1165 { 1166 SKGBEGINTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Move category"), err) 1167 1168 while (!stream.atEnd() && !err) { 1169 int o_id; 1170 QString o_table; 1171 stream >> o_table; 1172 stream >> o_id; 1173 1174 SKGCategoryObject child(getDocument(), o_id); 1175 err = child.load(); 1176 QString oldName = child.getDisplayName(); 1177 IFOK(err) { 1178 if (iParent.isValid()) { 1179 err = child.setParentCategory(parentCategory); 1180 } else { 1181 err = child.removeParentCategory(); 1182 } 1183 } 1184 IFOKDO(err, child.save()) 1185 1186 // Send message 1187 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The category '%1' has been moved to '%2'", oldName, child.getDisplayName()), SKGDocument::Hidden)) 1188 } 1189 } 1190 } else if (iData->hasFormat(QStringLiteral("application/skg.payee.ids"))) { 1191 QByteArray encodedData = iData->data(QStringLiteral("application/skg.payee.ids")); 1192 QDataStream stream(&encodedData, QIODevice::ReadOnly); 1193 QStringList newItems; 1194 1195 if (iParent.isValid()) { 1196 SKGBEGINTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Merge payees"), err) 1197 SKGPayeeObject parentPayee(getObject(iParent)); 1198 while (!stream.atEnd() && !err) { 1199 int o_id; 1200 QString o_table; 1201 stream >> o_table; 1202 stream >> o_id; 1203 1204 SKGPayeeObject child(getDocument(), o_id); 1205 err = child.load(); 1206 1207 // Send message 1208 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The payee '%1' has been merged with payee '%2'", child.getDisplayName(), parentPayee.getDisplayName()), SKGDocument::Hidden)) 1209 1210 IFOKDO(err, parentPayee.merge(child)) 1211 } 1212 } 1213 } else if (iData->hasFormat(QStringLiteral("application/skg.account.ids"))) { 1214 QByteArray encodedData = iData->data(QStringLiteral("application/skg.account.ids")); 1215 QDataStream stream(&encodedData, QIODevice::ReadOnly); 1216 QStringList newItems; 1217 1218 if (iParent.isValid()) { 1219 SKGBEGINTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Merge accounts"), err) 1220 SKGAccountObject parentAccount(getObject(iParent)); 1221 while (!stream.atEnd() && !err) { 1222 int o_id; 1223 QString o_table; 1224 stream >> o_table; 1225 stream >> o_id; 1226 1227 SKGAccountObject child(getDocument(), o_id); 1228 err = child.load(); 1229 1230 // Send message 1231 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The account '%1' has been merged with account '%2'", child.getDisplayName(), parentAccount.getDisplayName()), SKGDocument::Hidden)) 1232 1233 double balancebefore = 0.0; 1234 double balanceafter = 0.0; 1235 SKGUnitObject unit2; 1236 IFOKDO(err, parentAccount.getInitialBalance(balancebefore, unit2)) 1237 IFOKDO(err, parentAccount.merge(child, !(QApplication::keyboardModifiers() &Qt::ControlModifier))) 1238 IFOKDO(err, parentAccount.getInitialBalance(balanceafter, unit2)) 1239 if (balanceafter != balancebefore) { 1240 getDocument()->sendMessage(i18nc("Warning message", "The initial balance of the target account '%1' has been change to %2.\nIf you want to do the merge without changing the initial balance, you must keep the Ctrl key pressed.", parentAccount.getDisplayName(), balanceafter), SKGDocument::Warning); 1241 } 1242 } 1243 } 1244 } else if (iData->hasFormat(QStringLiteral("application/skg.unit.ids"))) { 1245 QByteArray encodedData = iData->data(QStringLiteral("application/skg.unit.ids")); 1246 QDataStream stream(&encodedData, QIODevice::ReadOnly); 1247 QStringList newItems; 1248 1249 if (iParent.isValid()) { 1250 SKGBEGINTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Merge units"), err) 1251 SKGUnitObject parentUnit(getObject(iParent)); 1252 while (!stream.atEnd() && !err) { 1253 int o_id; 1254 QString o_table; 1255 stream >> o_table; 1256 stream >> o_id; 1257 1258 SKGUnitObject child(getDocument(), o_id); 1259 err = child.load(); 1260 1261 // Send message 1262 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The unit '%1' has been merged with unit '%2'", child.getDisplayName(), parentUnit.getDisplayName()), SKGDocument::Hidden)) 1263 1264 IFOKDO(err, parentUnit.merge(child)) 1265 } 1266 } 1267 } else if (iData->hasFormat(QStringLiteral("application/skg.refund.ids"))) { 1268 QByteArray encodedData = iData->data(QStringLiteral("application/skg.refund.ids")); 1269 QDataStream stream(&encodedData, QIODevice::ReadOnly); 1270 QStringList newItems; 1271 1272 if (iParent.isValid()) { 1273 SKGBEGINTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Merge trackers"), err) 1274 SKGTrackerObject parentTracker(getObject(iParent)); 1275 while (!stream.atEnd() && !err) { 1276 int o_id; 1277 QString o_table; 1278 stream >> o_table; 1279 stream >> o_id; 1280 1281 SKGTrackerObject child(getDocument(), o_id); 1282 err = child.load(); 1283 1284 // Send message 1285 IFOKDO(err, parentTracker.getDocument()->sendMessage(i18nc("An information to the user", "The tracker '%1' has been merged with tracker '%2'", child.getDisplayName(), parentTracker.getDisplayName()), SKGDocument::Hidden)) 1286 1287 IFOKDO(err, parentTracker.merge(child)) 1288 } 1289 } 1290 } 1291 SKGMainPanel::displayErrorMessage(err); 1292 return !err; 1293 } 1294 1295 void SKGObjectModel::dataModified(const QString& iTableName, int iIdTransaction) 1296 { 1297 if (getRealTable() == iTableName || iTableName.isEmpty() || getRealTable() == QStringLiteral("doctransaction")) { 1298 SKGTRACEINFUNC(1) 1299 if (iTableName == QStringLiteral("category")) { 1300 // Full refresh 1301 m_isResetRealyNeeded = true; 1302 refresh(); 1303 } else { 1304 SKGObjectModelBase::dataModified(iTableName, iIdTransaction); 1305 } 1306 } else { 1307 SKGObjectModelBase::dataModified(iTableName, iIdTransaction); 1308 } 1309 } 1310 1311 QString SKGObjectModel::formatMoney(double iValue) const 1312 { 1313 return getDocument()->formatMoney(iValue, qobject_cast<SKGDocumentBank*>(getDocument())->getPrimaryUnit(), false); 1314 } 1315 1316 1317