File indexing completed on 2024-06-16 04:47:25
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 * A skrooge plugin to manage budgets. 0008 * 0009 * @author Stephane MANKOWSKI 0010 */ 0011 #include "skgbudgetpluginwidget.h" 0012 0013 #include <qdom.h> 0014 #include <qevent.h> 0015 0016 #include "skgbudgetdelegate.h" 0017 #include "skgbudgetobject.h" 0018 #include "skgbudgetruleobject.h" 0019 #include "skgcategoryobject.h" 0020 #include "skgdocument.h" 0021 #include "skgmainpanel.h" 0022 #include "skgobjectmodel.h" 0023 #include "skgtraces.h" 0024 #include "skgtransactionmng.h" 0025 0026 SKGBudgetPluginWidget::SKGBudgetPluginWidget(QWidget* iParent, SKGDocument* iDocument) 0027 : SKGTabPage(iParent, iDocument), m_objectModel(nullptr) 0028 { 0029 SKGTRACEINFUNC(1) 0030 if (iDocument == nullptr) { 0031 return; 0032 } 0033 0034 ui.setupUi(this); 0035 0036 ui.kUseScheduledOperation->hide(); 0037 0038 ui.kTopBtn->setIcon(SKGServices::fromTheme(QStringLiteral("arrow-up-double"))); 0039 ui.kUpBtn->setIcon(SKGServices::fromTheme(QStringLiteral("arrow-up"))); 0040 ui.kDownBtn->setIcon(SKGServices::fromTheme(QStringLiteral("arrow-down"))); 0041 ui.kBottomBtn->setIcon(SKGServices::fromTheme(QStringLiteral("arrow-down-double"))); 0042 0043 ui.kPeriodLbl->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_period")))); 0044 ui.kYearLbl->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("i_year")))); 0045 ui.kMonthLbl->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("i_month")))); 0046 ui.kAmountLabel->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("f_value")))); 0047 ui.kCategoryLabel->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_category")))); 0048 ui.kYearCheck->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("i_year")))); 0049 ui.kMonthCheck->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("i_month")))); 0050 ui.kCategoryCheck->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_category")))); 0051 ui.kPeriodLbl2->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_period")))); 0052 ui.kAmountLabel2->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("f_value")))); 0053 ui.kCategoryTransferCheck->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_category")))); 0054 0055 ui.kYear->setValue(QDate::currentDate().year()); 0056 ui.kYearAutoBase->setValue(QDate::currentDate().year()); 0057 ui.kMonth->setValue(QDate::currentDate().month()); 0058 ui.kPeriod->addItem(i18nc("Noun, how to define a budget period", "Monthly")); 0059 ui.kPeriod->addItem(i18nc("Noun, how to define a budget period", "Yearly")); 0060 ui.kPeriod->addItem(i18nc("Noun, how to define a budget period", "Individual")); 0061 0062 0063 ui.kView->getShowWidget()->addItem(QStringLiteral("all"), i18nc("Noun, budget items to display", "All"), QLatin1String(""), 0064 QLatin1String(""), 0065 QStringLiteral("current;currentYear;currentMonth;previousYear;previousMonth"), 0066 QStringLiteral("none"), QLatin1String(""), QLatin1String(""), 0067 Qt::META + Qt::Key_A); 0068 ui.kView->getShowWidget()->addItem(QStringLiteral("none"), i18nc("Noun, budget items to display", "None"), QLatin1String(""), 0069 QStringLiteral("1=0"), 0070 QLatin1String(""), // Check when checked 0071 QStringLiteral("all;current;currentYear;currentMonth;previousYear;previousMonth"), // Uncheck when checked 0072 QLatin1String(""), // Check when unchecked 0073 QStringLiteral("all"), // Uncheck when unchecked 0074 Qt::META + Qt::Key_0); 0075 ui.kView->getShowWidget()->addSeparator(); 0076 ui.kView->getShowWidget()->addItem(QStringLiteral("current"), i18nc("Noun, budget items to display", "Current"), QStringLiteral("view-calendar-whatsnext"), 0077 QStringLiteral("t_PERIOD>=STRFTIME('%Y-%m', date('now', 'localtime')) OR t_PERIOD=STRFTIME('%Y', date('now', 'localtime'))"), 0078 QStringLiteral("currentMonth"), // Check when checked 0079 QStringLiteral("none"), // Uncheck when checked 0080 QLatin1String(""), // Check when unchecked 0081 QStringLiteral("all"), // Uncheck when unchecked 0082 Qt::META + Qt::Key_1); 0083 ui.kView->getShowWidget()->addSeparator(); 0084 ui.kView->getShowWidget()->addItem(QStringLiteral("currentYear"), i18nc("Noun, budget items to display", "Current year"), QStringLiteral("view-calendar-month"), 0085 QStringLiteral("t_PERIOD LIKE STRFTIME('%Y', date('now', 'localtime'))||'%'"), 0086 QLatin1String(""), 0087 QStringLiteral("none"), 0088 QLatin1String(""), 0089 QStringLiteral("all"), 0090 Qt::META + Qt::Key_3); 0091 ui.kView->getShowWidget()->addItem(QStringLiteral("currentMonth"), i18nc("Noun, budget items to display", "Current month"), QStringLiteral("view-calendar-week"), 0092 QStringLiteral("t_PERIOD=STRFTIME('%Y-%m', date('now', 'localtime'))"), 0093 QLatin1String(""), 0094 QStringLiteral("none"), 0095 QLatin1String(""), 0096 QStringLiteral("all;current"), 0097 Qt::META + Qt::Key_2); 0098 ui.kView->getShowWidget()->addSeparator(); 0099 ui.kView->getShowWidget()->addItem(QStringLiteral("previousYear"), i18nc("Noun, budget items to display", "Previous year"), QStringLiteral("view-calendar-month"), 0100 QStringLiteral("t_PERIOD LIKE STRFTIME('%Y', date('now', 'localtime','start of year','-1 day'))||'%'"), 0101 QLatin1String(""), 0102 QStringLiteral("none"), 0103 QLatin1String(""), 0104 QStringLiteral("all"), 0105 Qt::META + Qt::Key_5); 0106 ui.kView->getShowWidget()->addItem(QStringLiteral("previousMonth"), i18nc("Noun, budget items to display", "Previous month"), QStringLiteral("view-calendar-week"), 0107 QStringLiteral("t_PERIOD=STRFTIME('%Y-%m', date('now', 'localtime','start of month','-1 day'))"), 0108 QLatin1String(""), 0109 QStringLiteral("none"), 0110 QLatin1String(""), 0111 QStringLiteral("all"), 0112 Qt::META + Qt::Key_4); 0113 ui.kView->getShowWidget()->setDefaultState(QStringLiteral("current;currentMonth")); 0114 0115 m_timer.setSingleShot(true); 0116 connect(&m_timer, &QTimer::timeout, this, &SKGBudgetPluginWidget::refreshInfoZone, Qt::QueuedConnection); 0117 0118 ui.kConditionCmb->addItem(i18nc("Noun, condition item to a apply a transfer of budget", "All"), static_cast<int>(SKGBudgetRuleObject::ALL)); 0119 ui.kConditionCmb->addItem(i18nc("Noun, condition item to a apply a transfer of budget", "Negative"), static_cast<int>(SKGBudgetRuleObject::NEGATIVE)); 0120 ui.kConditionCmb->addItem(i18nc("Noun, condition item to a apply a transfer of budget", "Positive"), static_cast<int>(SKGBudgetRuleObject::POSITIVE)); 0121 0122 ui.kModeCmb->addItem(i18nc("Noun, mode item to a apply a transfer of budget", "Next"), static_cast<int>(SKGBudgetRuleObject::NEXT)); 0123 ui.kModeCmb->addItem(i18nc("Noun, mode item to a apply a transfer of budget", "Current"), static_cast<int>(SKGBudgetRuleObject::CURRENT)); 0124 ui.kModeCmb->addItem(i18nc("Noun, mode item to a apply a transfer of budget", "Current year"), static_cast<int>(SKGBudgetRuleObject::YEAR)); 0125 0126 ui.kView->getView()->setItemDelegate(new SKGBudgetDelegate(ui.kView->getView(), getDocument())); 0127 0128 auto* doc = qobject_cast<SKGDocumentBank*>(getDocument()); 0129 if (doc != nullptr) { 0130 ui.kUnitCmb->addItem(QStringLiteral("%")); 0131 ui.kUnitCmb->addItem(doc->getPrimaryUnit().Symbol); 0132 ui.kUnit->setText(doc->getPrimaryUnit().Symbol); 0133 0134 // Bind transaction view 0135 m_objectModel = new SKGObjectModel(doc, QStringLiteral("v_budget_display"), QStringLiteral("1=0"), this, QLatin1String(""), false); 0136 ui.kView->setModel(m_objectModel); 0137 ui.kSortButton->setVisible(false); 0138 } 0139 0140 connect(ui.kView->getView(), &SKGTreeView::doubleClicked, SKGMainPanel::getMainPanel()->getGlobalAction(QStringLiteral("open")).data(), &QAction::trigger); 0141 connect(ui.kView->getView(), &SKGTreeView::selectionChangedDelayed, this, [ = ] {this->onSelectionChanged();}); 0142 0143 // Add Standard KDE Icons to buttons to Transactions 0144 ui.kModifyBtn->setIcon(SKGServices::fromTheme(QStringLiteral("dialog-ok"))); 0145 ui.kAddBtn->setIcon(SKGServices::fromTheme(QStringLiteral("list-add"))); 0146 QAction* processAction = SKGMainPanel::getMainPanel()->getGlobalAction(QStringLiteral("tool_process_budget_rules")); 0147 if (processAction != nullptr) { 0148 ui.kProcessBtn->setIcon(processAction->icon()); 0149 connect(ui.kProcessBtn, &QPushButton::clicked, processAction, &QAction::trigger); 0150 } 0151 0152 { 0153 SKGWidgetSelector::SKGListQWidget list; 0154 list.push_back(ui.SKGManualSection); 0155 list.push_back(ui.SKGEditionButtonsSection); 0156 ui.kWidgetSelector->addButton(SKGServices::fromTheme(QStringLiteral("user-properties")), i18n("Manual"), i18n("Display the edit panel for standard budget"), list); 0157 } 0158 { 0159 SKGWidgetSelector::SKGListQWidget list; 0160 list.push_back(ui.SKGAutoSection); 0161 list.push_back(ui.SKGEditionButtonsSection); 0162 ui.kWidgetSelector->addButton(SKGServices::fromTheme(QStringLiteral("games-solve")), i18n("Auto"), i18n("Display the edit panel for automatic budgets"), list); 0163 } 0164 { 0165 SKGWidgetSelector::SKGListQWidget list; 0166 list.push_back(ui.SKGRuleSection); 0167 list.push_back(ui.SKGEditionButtonsSection); 0168 ui.kWidgetSelector->addButton(SKGServices::fromTheme(QStringLiteral("run-build")), i18n("Rules"), i18n("Display the edit panel for rules"), list); 0169 } 0170 connect(ui.kWidgetSelector, &SKGWidgetSelector::selectedModeChanged, this, &SKGBudgetPluginWidget::onBtnModeClicked, Qt::QueuedConnection); 0171 connect(ui.kAddBtn, &QPushButton::clicked, this, &SKGBudgetPluginWidget::onAddClicked); 0172 connect(ui.kModifyBtn, &QPushButton::clicked, this, &SKGBudgetPluginWidget::onUpdateClicked); 0173 connect(ui.kAmountEdit, &SKGCalculatorEdit::textChanged, this, &SKGBudgetPluginWidget::onCreatorModified); 0174 connect(ui.kPeriod, static_cast<void (SKGComboBox::*)(const QString&)>(&SKGComboBox::currentTextChanged), this, &SKGBudgetPluginWidget::onCreatorModified); 0175 connect(ui.kYearCheck, &QCheckBox::toggled, ui.kYearRule, &QSpinBox::setEnabled); 0176 connect(ui.kMonthCheck, &QCheckBox::toggled, ui.kMonthRule, &QSpinBox::setEnabled); 0177 connect(ui.kCategoryCheck, &QCheckBox::toggled, ui.kCategoryRule, &SKGComboBox::setEnabled); 0178 connect(ui.kCategoryTransferCheck, &QCheckBox::toggled, ui.kCategoryTransfer, &SKGComboBox::setEnabled); 0179 connect(ui.kModeCmb, static_cast<void (SKGComboBox::*)(int)>(&SKGComboBox::currentIndexChanged), this, &SKGBudgetPluginWidget::onCreatorModified); 0180 connect(ui.kAutoBudgetCheck, &QCheckBox::toggled, ui.kYearAutoBase, &QSpinBox::setEnabled); 0181 connect(ui.kAutoBudgetCheck, &QCheckBox::toggled, ui.kRemovePrevious, &QCheckBox::setEnabled); 0182 connect(ui.kAutoBudgetCheck, &QCheckBox::toggled, ui.kUseScheduledOperation, &QCheckBox::setEnabled); 0183 0184 connect(ui.kTopBtn, &QToolButton::clicked, this, &SKGBudgetPluginWidget::onTop); 0185 connect(ui.kUpBtn, &QToolButton::clicked, this, &SKGBudgetPluginWidget::onUp); 0186 connect(ui.kDownBtn, &QToolButton::clicked, this, &SKGBudgetPluginWidget::onDown); 0187 connect(ui.kBottomBtn, &QToolButton::clicked, this, &SKGBudgetPluginWidget::onBottom); 0188 #if QT_VERSION < QT_VERSION_CHECK(5, 14, 0) 0189 connect(ui.kYearAuto, static_cast<void (QSpinBox::*)(const QString&)>(&QSpinBox::valueChanged), this, [ = ](const QString & text) { 0190 ui.kRemovePrevious->setText(i18nc("Option", "Remove existing budgets for %1", text)); 0191 }); 0192 #else 0193 connect(ui.kYearAuto, &QSpinBox::textChanged, this, [ = ](const QString & text) { 0194 ui.kRemovePrevious->setText(i18nc("Option", "Remove existing budgets for %1", text)); 0195 }); 0196 #endif 0197 ui.kYearAuto->setValue(QDate::currentDate().year()); 0198 0199 ui.kWidgetSelector->setSelectedMode(0); 0200 0201 // Set Event filters to catch CTRL+ENTER or SHIFT+ENTER 0202 this->installEventFilter(this); 0203 0204 // Refresh 0205 connect(getDocument(), &SKGDocument::tableModified, this, &SKGBudgetPluginWidget::dataModified, Qt::QueuedConnection); 0206 dataModified(QLatin1String(""), 0); 0207 } 0208 0209 SKGBudgetPluginWidget::~SKGBudgetPluginWidget() 0210 { 0211 SKGTRACEINFUNC(1) 0212 m_objectModel = nullptr; 0213 } 0214 0215 bool SKGBudgetPluginWidget::eventFilter(QObject* iObject, QEvent* iEvent) 0216 { 0217 if ((iEvent != nullptr) && iEvent->type() == QEvent::KeyPress) { 0218 auto* keyEvent = dynamic_cast<QKeyEvent*>(iEvent); 0219 if (keyEvent && (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) && iObject == this) { 0220 if ((QApplication::keyboardModifiers() & Qt::ControlModifier) != 0u && ui.kAddBtn->isEnabled()) { 0221 ui.kAddBtn->click(); 0222 } else if ((QApplication::keyboardModifiers() &Qt::ShiftModifier) != 0u && ui.kModifyBtn->isEnabled()) { 0223 ui.kModifyBtn->click(); 0224 } 0225 } 0226 } 0227 0228 return SKGTabPage::eventFilter(iObject, iEvent); 0229 } 0230 0231 QString SKGBudgetPluginWidget::getState() 0232 { 0233 SKGTRACEINFUNC(10) 0234 QDomDocument doc(QStringLiteral("SKGML")); 0235 QDomElement root = doc.createElement(QStringLiteral("parameters")); 0236 doc.appendChild(root); 0237 0238 root.setAttribute(QStringLiteral("currentPage"), SKGServices::intToString(ui.kWidgetSelector->getSelectedMode())); 0239 if ((m_objectModel != nullptr) && m_objectModel->getRealTable() == QStringLiteral("budget")) { 0240 root.setAttribute(QStringLiteral("view"), ui.kView->getState()); 0241 root.setAttribute(QStringLiteral("viewRule"), m_viewRule); 0242 } else { 0243 root.setAttribute(QStringLiteral("view"), m_viewBudget); 0244 root.setAttribute(QStringLiteral("viewRule"), ui.kView->getState()); 0245 } 0246 0247 return doc.toString(); 0248 } 0249 0250 void SKGBudgetPluginWidget::setState(const QString& iState) 0251 { 0252 SKGTRACEINFUNC(10) 0253 QDomDocument doc(QStringLiteral("SKGML")); 0254 doc.setContent(iState); 0255 QDomElement root = doc.documentElement(); 0256 0257 QString currentPage = root.attribute(QStringLiteral("currentPage")); 0258 if (currentPage.isEmpty()) { 0259 currentPage = '0'; 0260 } 0261 0262 ui.kWidgetSelector->setSelectedMode(SKGServices::stringToInt(currentPage)); 0263 0264 m_viewBudget = root.attribute(QStringLiteral("view")); 0265 m_viewRule = root.attribute(QStringLiteral("viewRule")); 0266 if ((m_objectModel != nullptr) && m_objectModel->getRealTable() == QStringLiteral("budget")) { 0267 ui.kView->setState(m_viewBudget); 0268 } else { 0269 ui.kView->setState(m_viewRule); 0270 } 0271 } 0272 0273 QString SKGBudgetPluginWidget::getDefaultStateAttribute() 0274 { 0275 return QStringLiteral("SKGBUDGET_DEFAULT_PARAMETERS"); 0276 } 0277 0278 QWidget* SKGBudgetPluginWidget::mainWidget() 0279 { 0280 return ui.kView->getView(); 0281 } 0282 0283 void SKGBudgetPluginWidget::refresh() 0284 { 0285 SKGTRACEINFUNC(1) 0286 0287 QSqlDatabase* db = getDocument()->getMainDatabase(); 0288 setEnabled(db != nullptr); 0289 if (db != nullptr) { 0290 // Refresh yours widgets here 0291 } 0292 } 0293 0294 void SKGBudgetPluginWidget::dataModified(const QString& iTableName, int iIdTransaction, bool iLightTransaction) 0295 { 0296 SKGTRACEINFUNC(10) 0297 Q_UNUSED(iIdTransaction) 0298 0299 // Refresh widgets 0300 if (iTableName == QStringLiteral("budget") || iTableName.isEmpty()) { 0301 // Refresh info area 0302 m_timer.start(300); 0303 } 0304 0305 if (!iLightTransaction) { 0306 if (iTableName == QStringLiteral("category") || iTableName.isEmpty()) { 0307 // Set type category 0308 SKGMainPanel::fillWithDistinctValue(QList<QWidget*>() << ui.kCategoryEdit << ui.kCategoryRule << ui.kCategoryTransfer, getDocument(), QStringLiteral("category"), QStringLiteral("t_fullname"), QLatin1String("")); 0309 } 0310 } 0311 } 0312 0313 void SKGBudgetPluginWidget::onBtnModeClicked(int mode) 0314 { 0315 SKGTRACEINFUNC(10) 0316 if (m_objectModel == nullptr) { 0317 return; 0318 } 0319 0320 if (mode == 2 && m_objectModel->getTable() != QStringLiteral("v_budgetrule_display")) { 0321 ui.kView->getShowWidget()->setEnabled(false); 0322 m_viewBudget = ui.kView->getState(); 0323 m_objectModel->setFilter(QLatin1String("")); 0324 m_objectModel->setTable(QStringLiteral("v_budgetrule_display")); 0325 ui.kSortButton->setVisible(true); 0326 ui.kView->setState(m_viewRule); 0327 } else if (mode != 2 && m_objectModel->getTable() != QStringLiteral("v_budget_display")) { 0328 ui.kView->getShowWidget()->setEnabled(true); 0329 m_viewRule = ui.kView->getState(); 0330 m_objectModel->setTable(QStringLiteral("v_budget_display")); 0331 ui.kSortButton->setVisible(false); 0332 ui.kView->setState(m_viewBudget); 0333 } 0334 0335 onCreatorModified(); 0336 } 0337 0338 void SKGBudgetPluginWidget::onAddClicked() 0339 { 0340 SKGError err; 0341 _SKGTRACEINFUNCRC(10, err) 0342 0343 if (ui.kWidgetSelector->getSelectedMode() == 2) { 0344 // Creation of a rule 0345 QStringList uniqueIDs; 0346 { 0347 SKGBEGINTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Budget rule creation"), err) 0348 SKGBudgetRuleObject budgetRule(getDocument()); 0349 IFOKDO(err, updateBudgetRule(budgetRule)) 0350 IFOKDO(err, budgetRule.setOrder(-1)) 0351 IFOKDO(err, budgetRule.save()) 0352 uniqueIDs.push_back(budgetRule.getUniqueID()); 0353 0354 // Send message 0355 IFOKDO(err, budgetRule.getDocument()->sendMessage(i18nc("An information to the user", "The budget rule '%1' has been added", budgetRule.getDisplayName()), SKGDocument::Hidden)) 0356 } 0357 // status bar 0358 IFOK(err) { 0359 err = SKGError(0, i18nc("Successful message after an user action", "Budget rule created")); 0360 ui.kView->getView()->selectObjects(uniqueIDs); 0361 } else { 0362 err.addError(ERR_FAIL, i18nc("Error message", "Budget rule creation failed")); 0363 } 0364 } else { 0365 // Creation of a budget 0366 QStringList uniqueIDs; 0367 { 0368 SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Budget creation"), err, 2) 0369 if (ui.kWidgetSelector->getSelectedMode() == 0) { 0370 // Manual creation 0371 int mode = ui.kPeriod->currentIndex(); 0372 if (mode == 0) { // Monthly 0373 for (int m = 1; !err && m <= 12; ++m) { 0374 SKGBudgetObject budget(getDocument()); 0375 IFOKDO(err, updateBudget(budget, m)) 0376 0377 // Send message 0378 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The budget '%1' has been added", budget.getDisplayName()), SKGDocument::Hidden)) 0379 0380 uniqueIDs.push_back(budget.getUniqueID()); 0381 } 0382 } else if (mode == 1) { // Yearly 0383 SKGBudgetObject budget(getDocument()); 0384 0385 IFOKDO(err, updateBudget(budget, 0)) 0386 0387 // Send message 0388 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The budget '%1' has been added", budget.getDisplayName()), SKGDocument::Hidden)) 0389 0390 uniqueIDs.push_back(budget.getUniqueID()); 0391 } else { // Individual 0392 SKGBudgetObject budget(getDocument()); 0393 IFOKDO(err, updateBudget(budget)) 0394 0395 // Send message 0396 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The budget '%1' has been added", budget.getDisplayName()), SKGDocument::Hidden)) 0397 0398 uniqueIDs.push_back(budget.getUniqueID()); 0399 } 0400 } else { 0401 // Automatic creation 0402 if (ui.kAutoBudgetCheck->isChecked()) { 0403 err = SKGBudgetObject::createAutomaticBudget(qobject_cast<SKGDocumentBank*>(getDocument()), 0404 ui.kYearAuto->value(), 0405 ui.kYearAutoBase->value(), 0406 ui.kUseScheduledOperation->isChecked(), 0407 ui.kRemovePrevious->isChecked()); 0408 } 0409 IFOKDO(err, getDocument()->stepForward(1)) 0410 0411 IFOKDO(err, SKGBudgetObject::balanceBudget(qobject_cast<SKGDocumentBank*>(getDocument()), 0412 ui.kYearAuto->value(), (ui.kBalancingMonthly->isChecked() ? 0 : -1), 0413 ui.kBalancingAnnual->isChecked())); 0414 IFOKDO(err, getDocument()->stepForward(2)) 0415 } 0416 } 0417 0418 // status bar 0419 IFOK(err) { 0420 err = SKGError(0, i18nc("Successful message after an user action", "Budget created")); 0421 ui.kView->getView()->selectObjects(uniqueIDs); 0422 } else { 0423 err.addError(ERR_FAIL, i18nc("Error message", "Budget creation failed")); 0424 } 0425 } 0426 0427 // Display error 0428 SKGMainPanel::displayErrorMessage(err, true); 0429 } 0430 0431 void SKGBudgetPluginWidget::onUpdateClicked() 0432 { 0433 SKGError err; 0434 SKGTRACEINFUNCRC(10, err) 0435 // Get Selection 0436 SKGObjectBase::SKGListSKGObjectBase selection = getSelectedObjects(); 0437 if (ui.kWidgetSelector->getSelectedMode() == 2) { 0438 { 0439 SKGBEGINTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Budget rule update"), err) 0440 SKGBudgetRuleObject rule(selection.at(0)); 0441 IFOKDO(err, updateBudgetRule(rule)) 0442 0443 // Send message 0444 IFOKDO(err, rule.getDocument()->sendMessage(i18nc("An information to the user", "The budget rule '%1' has been updated", rule.getDisplayName()), SKGDocument::Hidden)) 0445 } 0446 0447 // status bar 0448 IFOK(err) { 0449 err = SKGError(0, i18nc("Successful message after an user action", "Budget rule updated")); 0450 } else { 0451 err.addError(ERR_FAIL, i18nc("Error message", "Budget rule update failed")); 0452 } 0453 } else { 0454 { 0455 int nb = selection.count(); 0456 SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Budget update"), err, nb) 0457 for (int i = 0; !err && i < nb; ++i) { 0458 SKGBudgetObject budget(selection.at(i)); 0459 int mode = ui.kPeriod->currentIndex(); 0460 if (mode == 1) { // Yearly 0461 err = updateBudget(budget, 0); 0462 } else { // Individual 0463 err = updateBudget(budget); 0464 } 0465 0466 IFOKDO(err, getDocument()->stepForward(i + 1)) 0467 } 0468 } 0469 0470 // status bar 0471 IFOK(err) { 0472 err = SKGError(0, i18nc("Successful message after an user action", "Budget updated")); 0473 } else { 0474 err.addError(ERR_FAIL, i18nc("Error message", "Budget update failed")); 0475 } 0476 } 0477 0478 0479 // Display error 0480 SKGMainPanel::displayErrorMessage(err, true); 0481 0482 // Set focus on table 0483 ui.kView->getView()->setFocus(); 0484 } 0485 0486 SKGError SKGBudgetPluginWidget::updateBudget(SKGBudgetObject& iBudget, int iMonth) 0487 { 0488 SKGError err; 0489 if (!err && ui.kYear->isEnabled()) { 0490 err = iBudget.setYear(ui.kYear->value()); 0491 } 0492 if (!err && ui.kMonth->isEnabled()) { 0493 err = iBudget.setMonth(iMonth != -1 ? iMonth : ui.kMonth->value()); 0494 } 0495 0496 SKGCategoryObject cat; 0497 QString catName = ui.kCategoryEdit->text().trimmed(); 0498 IFOKDO(err, SKGCategoryObject::createPathCategory(qobject_cast<SKGDocumentBank*>(getDocument()), catName, cat, true)) 0499 IFOKDO(err, iBudget.setCategory(cat)) 0500 IFOKDO(err, iBudget.enableSubCategoriesInclusion(ui.kIncludingSubCategories->isChecked())) 0501 0502 double val = ui.kAmountEdit->value(); 0503 // Is the sign forced ? 0504 if (ui.kAmountEdit->sign() == 0) { 0505 // No 0506 SKGObjectBase cat2(cat.getDocument(), QStringLiteral("v_category_display"), cat.getID()); 0507 0508 // Are we able to find to sign with the category ? 0509 if (cat2.getAttribute(QStringLiteral("t_TYPEEXPENSE")) == QStringLiteral("-")) { 0510 val = -val; 0511 } 0512 } 0513 IFOKDO(err, iBudget.setBudgetedAmount(val)) 0514 0515 IFOKDO(err, iBudget.save()) 0516 return err; 0517 } 0518 0519 SKGError SKGBudgetPluginWidget::updateBudgetRule(SKGBudgetRuleObject& iRule) 0520 { 0521 SKGError err; 0522 SKGCategoryObject cat; 0523 QString catName = ui.kCategoryRule->text().trimmed(); 0524 IFOKDO(err, SKGCategoryObject::createPathCategory(qobject_cast<SKGDocumentBank*>(getDocument()), catName, cat, true)) 0525 SKGCategoryObject catchange; 0526 QString catchangeName = ui.kCategoryTransfer->text().trimmed(); 0527 IFOKDO(err, SKGCategoryObject::createPathCategory(qobject_cast<SKGDocumentBank*>(getDocument()), catchangeName, catchange, true)) 0528 IFOKDO(err, iRule.enableCategoryCondition(ui.kCategoryCheck->isChecked())) 0529 IFOKDO(err, iRule.setBudgetCategory(cat)) 0530 IFOKDO(err, iRule.enableYearCondition(ui.kYearCheck->isChecked())) 0531 IFOKDO(err, iRule.setBudgetYear(ui.kYearRule->value())) 0532 IFOKDO(err, iRule.enableMonthCondition(ui.kMonthCheck->isChecked())) 0533 IFOKDO(err, iRule.setBudgetMonth(ui.kMonthRule->value())) 0534 IFOK(err) { 0535 bool absolute = (ui.kUnitCmb->currentIndex() == 1); 0536 double val = ui.kAmountEdit2->value(); 0537 if (!absolute) { 0538 val = qMin(qMax(static_cast<double>(0), val), static_cast<double>(100)); 0539 } 0540 err = iRule.setQuantity(val, absolute); 0541 } 0542 IFOKDO(err, iRule.setCondition(static_cast<SKGBudgetRuleObject::Condition>(ui.kConditionCmb->itemData(ui.kConditionCmb->currentIndex()).toInt()))) 0543 IFOKDO(err, iRule.enableCategoryChange(ui.kCategoryTransferCheck->isChecked())) 0544 IFOKDO(err, iRule.setTransfer(static_cast<SKGBudgetRuleObject::Mode>(ui.kModeCmb->itemData(ui.kModeCmb->currentIndex()).toInt()), catchange)) 0545 IFOKDO(err, iRule.save()) 0546 return err; 0547 } 0548 0549 void SKGBudgetPluginWidget::onCreatorModified() 0550 { 0551 bool test = !ui.kAmountEdit->text().isEmpty() && !ui.kYear->text().isEmpty(); 0552 ui.kAddBtn->setEnabled(test || ui.kWidgetSelector->getSelectedMode() != 0); 0553 ui.kModifyBtn->setEnabled((test && ui.kPeriod->currentIndex() != 0 && ui.kWidgetSelector->getSelectedMode() == 0 && (getNbSelectedObjects() != 0)) 0554 || (ui.kWidgetSelector->getSelectedMode() == 2 && getNbSelectedObjects() == 1)); 0555 0556 bool monthCondition = (ui.kPeriod->currentIndex() == 2 || ui.kWidgetSelector->getSelectedMode() == 2); 0557 ui.kMonthLbl->setVisible(monthCondition); 0558 ui.kMonth->setVisible(monthCondition); 0559 } 0560 0561 void SKGBudgetPluginWidget::onSelectionChanged() 0562 { 0563 SKGTRACEINFUNC(10) 0564 if (m_objectModel == nullptr) { 0565 return; 0566 } 0567 0568 SKGObjectBase::SKGListSKGObjectBase objs = getSelectedObjects(); 0569 int nb = objs.count(); 0570 int mode = ui.kWidgetSelector->getSelectedMode(); 0571 if (nb != 0) { 0572 if (m_objectModel->getRealTable() == QStringLiteral("budget")) { 0573 SKGBudgetObject budget(objs.at(0)); 0574 ui.kYear->setValue(budget.getYear()); 0575 ui.kMonth->setValue(budget.getMonth()); 0576 ui.kAmountEdit->setValue(budget.getBudgetedAmount()); 0577 ui.kCategoryEdit->setText(budget.getAttribute(QStringLiteral("t_CATEGORY"))); 0578 ui.kPeriod->setCurrentIndex(budget.getMonth() == 0 ? 1 : 2); // Set yearly or individual 0579 ui.kIncludingSubCategories->setChecked(budget.isSubCategoriesInclusionEnabled()); 0580 0581 if (mode > 0) { 0582 ui.kWidgetSelector->setSelectedMode(0); 0583 } 0584 } else { 0585 SKGBudgetRuleObject rule(objs.at(0)); 0586 ui.kYearCheck->setChecked(rule.isYearConditionEnabled()); 0587 ui.kYearRule->setValue(rule.getBudgetYear()); 0588 ui.kMonthCheck->setChecked(rule.isMonthConditionEnabled()); 0589 ui.kMonthRule->setValue(rule.getBudgetMonth()); 0590 ui.kCategoryCheck->setChecked(rule.isCategoryConditionEnabled()); 0591 ui.kCategoryRule->setText(rule.getAttribute(QStringLiteral("t_CATEGORYCONDITION"))); 0592 ui.kCategoryTransferCheck->setChecked(rule.isCategoryChangeEnabled()); 0593 ui.kCategoryTransfer->setText(rule.getAttribute(QStringLiteral("t_CATEGORY"))); 0594 ui.kUnitCmb->setCurrentIndex(rule.isAbolute() ? 1 : 0); 0595 ui.kAmountEdit2->setValue(rule.getQuantity()); 0596 ui.kModeCmb->setCurrentIndex(ui.kModeCmb->findData(static_cast<int>(rule.getTransferMode()))); 0597 ui.kConditionCmb->setCurrentIndex(ui.kConditionCmb->findData(static_cast<int>(rule.getCondition()))); 0598 } 0599 } 0600 0601 ui.kPeriod->setEnabled(nb <= 1); 0602 ui.kYear->setEnabled(nb <= 1); 0603 ui.kMonth->setEnabled(nb <= 1); 0604 0605 onCreatorModified(); 0606 refreshInfoZone(); 0607 Q_EMIT selectionChanged(); 0608 } 0609 0610 void SKGBudgetPluginWidget::activateEditor() 0611 { 0612 if (ui.kWidgetSelector->getSelectedMode() == -1) { 0613 ui.kWidgetSelector->setSelectedMode(0); 0614 } 0615 ui.kAmountEdit->setFocus(); 0616 } 0617 0618 bool SKGBudgetPluginWidget::isEditor() 0619 { 0620 return true; 0621 } 0622 0623 void SKGBudgetPluginWidget::refreshInfoZone() 0624 { 0625 SKGTRACEINFUNC(10) 0626 auto* doc = qobject_cast<SKGDocumentBank*>(getDocument()); 0627 if ((doc != nullptr) && ui.kWidgetSelector->getSelectedMode() != 2) { 0628 SKGServices::SKGUnitInfo primary = doc->getPrimaryUnit(); 0629 SKGServices::SKGUnitInfo secondary = doc->getSecondaryUnit(); 0630 // Refresh info area with selection 0631 SKGObjectBase::SKGListSKGObjectBase selection = getSelectedObjects(); 0632 0633 double budgeted = 0; 0634 double modified = 0; 0635 int nb = selection.count(); 0636 for (int i = 0; i < nb; ++i) { 0637 SKGBudgetObject budget(selection.at(i)); 0638 budgeted += budget.getBudgetedAmount(); 0639 modified += budget.getBudgetedModifiedAmount(); 0640 } 0641 0642 QString budgetedS = doc->formatMoney(budgeted, primary); 0643 QString modifiedS = doc->formatMoney(modified, primary); 0644 QString v = (budgetedS == modifiedS ? budgetedS : modifiedS % " <s><small>" % budgetedS % "</small></s>"); 0645 if (nb != 0) { 0646 ui.kInfo->setText(i18np("Selection: %1 budget for %2", "Selection: %1 budgets for %2", nb, v)); 0647 if (!secondary.Symbol.isEmpty() && (secondary.Value != 0.0)) { 0648 budgetedS = doc->formatMoney(budgeted, secondary); 0649 modifiedS = doc->formatMoney(modified, secondary); 0650 v = (budgetedS == modifiedS ? budgetedS : modifiedS % " <s><small>" % budgetedS % "</small></s>"); 0651 } 0652 ui.kInfo->setToolTip(i18np("Selection: %1 budget for %2", "Selection: %1 budgets for %2", nb, v)); 0653 } else { 0654 ui.kInfo->setText(i18nc("Noun", "Selection: none")); 0655 ui.kInfo->setToolTip(i18nc("Noun", "Selection: none")); 0656 } 0657 } 0658 } 0659 0660 void SKGBudgetPluginWidget::onTop() 0661 { 0662 SKGError err; 0663 SKGTRACEINFUNCRC(1, err) 0664 0665 // Get rules 0666 SKGObjectBase::SKGListSKGObjectBase rules = getSelectedObjects(); 0667 int nb = rules.count(); 0668 { 0669 SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Budget rule update"), err, nb) 0670 for (int i = nb - 1; !err && i >= 0; --i) { 0671 SKGBudgetRuleObject rule(rules.at(i)); 0672 0673 double order = 1; 0674 SKGStringListList result; 0675 err = getDocument()->executeSelectSqliteOrder(QStringLiteral("SELECT min(f_sortorder) from budgetrule"), result); 0676 if (!err && result.count() == 2) { 0677 order = SKGServices::stringToDouble(result.at(1).at(0)) - 1; 0678 } 0679 0680 IFOKDO(err, rule.setOrder(order)) 0681 IFOKDO(err, rule.save()) 0682 0683 // Send message 0684 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The budget rule '%1' has been updated", rule.getDisplayName()), SKGDocument::Hidden)) 0685 0686 IFOKDO(err, getDocument()->stepForward(i + 1)) 0687 } 0688 } 0689 0690 // status bar 0691 IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Budget rule updated"))) 0692 else { 0693 err.addError(ERR_FAIL, i18nc("Error message", "Budget rule update failed")); 0694 } 0695 0696 // Display error 0697 SKGMainPanel::displayErrorMessage(err); 0698 } 0699 0700 void SKGBudgetPluginWidget::onUp() 0701 { 0702 SKGError err; 0703 SKGTRACEINFUNCRC(1, err) 0704 0705 // Get rules 0706 SKGObjectBase::SKGListSKGObjectBase rules = getSelectedObjects(); 0707 int nb = rules.count(); 0708 { 0709 SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Budget rule update"), err, nb) 0710 for (int i = 0; !err && i < nb; ++i) { 0711 SKGBudgetRuleObject rule(rules.at(i)); 0712 0713 double order = rule.getOrder(); 0714 SKGStringListList result; 0715 err = getDocument()->executeSelectSqliteOrder("SELECT f_sortorder from budgetrule where f_sortorder<" % SKGServices::doubleToString(order) % " ORDER BY f_sortorder DESC", result); 0716 IFOK(err) { 0717 if (result.count() == 2) { 0718 order = SKGServices::stringToDouble(result.at(1).at(0)) - 1; 0719 } else if (result.count() >= 2) { 0720 order = (SKGServices::stringToDouble(result.at(1).at(0)) + SKGServices::stringToDouble(result.at(2).at(0))) / 2; 0721 } 0722 } 0723 0724 IFOKDO(err, rule.setOrder(order)) 0725 IFOKDO(err, rule.save()) 0726 0727 // Send message 0728 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The budget rule '%1' has been updated", rule.getDisplayName()), SKGDocument::Hidden)) 0729 0730 IFOKDO(err, getDocument()->stepForward(i + 1)) 0731 } 0732 } 0733 0734 // status bar 0735 IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Budget rule updated"))) 0736 else { 0737 err.addError(ERR_FAIL, i18nc("Error message", "Budget rule update failed")); 0738 } 0739 0740 // Display error 0741 SKGMainPanel::displayErrorMessage(err); 0742 } 0743 0744 void SKGBudgetPluginWidget::onDown() 0745 { 0746 SKGError err; 0747 SKGTRACEINFUNCRC(1, err) 0748 0749 // Get rules 0750 SKGObjectBase::SKGListSKGObjectBase rules = getSelectedObjects(); 0751 int nb = rules.count(); 0752 { 0753 SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Budget rule update"), err, nb) 0754 for (int i = nb - 1; !err && i >= 0; --i) { 0755 SKGBudgetRuleObject rule(rules.at(i)); 0756 0757 double order = rule.getOrder(); 0758 SKGStringListList result; 0759 err = getDocument()->executeSelectSqliteOrder("SELECT f_sortorder from budgetrule where f_sortorder>" % SKGServices::doubleToString(order) % " ORDER BY f_sortorder ASC", result); 0760 IFOK(err) { 0761 if (result.count() == 2) { 0762 order = SKGServices::stringToDouble(result.at(1).at(0)) + 1; 0763 } else if (result.count() >= 2) { 0764 order = (SKGServices::stringToDouble(result.at(1).at(0)) + SKGServices::stringToDouble(result.at(2).at(0))) / 2; 0765 } 0766 } 0767 0768 IFOKDO(err, rule.setOrder(order)) 0769 IFOKDO(err, rule.save()) 0770 0771 // Send message 0772 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The budget rule '%1' has been updated", rule.getDisplayName()), SKGDocument::Hidden)) 0773 0774 IFOKDO(err, getDocument()->stepForward(i + 1)) 0775 } 0776 } 0777 0778 // status bar 0779 IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Budget rule updated"))) 0780 else { 0781 err.addError(ERR_FAIL, i18nc("Error message", "Budget rule update failed")); 0782 } 0783 0784 // Display error 0785 SKGMainPanel::displayErrorMessage(err); 0786 } 0787 0788 void SKGBudgetPluginWidget::onBottom() 0789 { 0790 SKGError err; 0791 SKGTRACEINFUNCRC(1, err) 0792 0793 // Get rules 0794 SKGObjectBase::SKGListSKGObjectBase rules = getSelectedObjects(); 0795 int nb = rules.count(); 0796 { 0797 SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Budget rule update"), err, nb) 0798 for (int i = 0; !err && i < nb; ++i) { 0799 SKGBudgetRuleObject rule(rules.at(i)); 0800 0801 double order = 1; 0802 SKGStringListList result; 0803 err = getDocument()->executeSelectSqliteOrder(QStringLiteral("SELECT max(f_sortorder) from budgetrule"), result); 0804 if (!err && result.count() == 2) { 0805 order = SKGServices::stringToDouble(result.at(1).at(0)) + 1; 0806 } 0807 0808 IFOKDO(err, rule.setOrder(order)) 0809 IFOKDO(err, rule.save()) 0810 0811 // Send message 0812 IFOKDO(err, getDocument()->sendMessage(i18nc("An information to the user", "The budget rule '%1' has been updated", rule.getDisplayName()), SKGDocument::Hidden)) 0813 0814 IFOKDO(err, getDocument()->stepForward(i + 1)) 0815 } 0816 } 0817 0818 // status bar 0819 IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Budget rule updated"))) 0820 else { 0821 err.addError(ERR_FAIL, i18nc("Error message", "Budget rule update failed")); 0822 } 0823 0824 // Display error 0825 SKGMainPanel::displayErrorMessage(err); 0826 } 0827 0828 0829