File indexing completed on 2024-06-16 04:47:29
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 track transactions. 0008 * 0009 * @author Stephane MANKOWSKI 0010 */ 0011 #include "skgpayeepluginwidget.h" 0012 0013 #include <qaction.h> 0014 0015 #include <qdom.h> 0016 #include <qevent.h> 0017 0018 #include "skgcategoryobject.h" 0019 #include "skgdocumentbank.h" 0020 #include "skgmainpanel.h" 0021 #include "skgobjectmodel.h" 0022 #include "skgpayeeobject.h" 0023 #include "skgtraces.h" 0024 #include "skgtransactionmng.h" 0025 0026 SKGPayeePluginWidget::SKGPayeePluginWidget(QWidget* iParent, SKGDocument* iDocument) 0027 : SKGTabPage(iParent, iDocument) 0028 { 0029 SKGTRACEINFUNC(1) 0030 if (iDocument == nullptr) { 0031 return; 0032 } 0033 0034 ui.setupUi(this); 0035 0036 // Set show widget 0037 ui.kView->getShowWidget()->addGroupedItem(QStringLiteral("all"), i18n("All"), QLatin1String(""), QLatin1String(""), QLatin1String(""), Qt::META + Qt::Key_A); 0038 ui.kView->getShowWidget()->addGroupedItem(QStringLiteral("opened"), i18n("Opened"), QStringLiteral("vcs-normal"), QStringLiteral("t_close='N'"), QLatin1String(""), Qt::META + Qt::Key_O); 0039 ui.kView->getShowWidget()->addGroupedItem(QStringLiteral("closed"), i18n("Closed"), QStringLiteral("vcs-conflicting"), QStringLiteral("t_close='Y'"), QLatin1String(""), Qt::META + Qt::Key_C); 0040 ui.kView->getShowWidget()->addGroupedItem(QStringLiteral("highlighted"), i18n("Highlighted only"), QStringLiteral("bookmarks"), QStringLiteral("t_bookmarked='Y'"), QLatin1String(""), Qt::META + Qt::Key_H); 0041 ui.kView->getShowWidget()->addGroupedItem(QStringLiteral("income"), i18n("Income"), QStringLiteral("list-add"), QStringLiteral("f_CURRENTAMOUNT>=0"), QLatin1String(""), Qt::META + Qt::Key_Plus); 0042 ui.kView->getShowWidget()->addGroupedItem(QStringLiteral("expenditure"), i18n("Expenditure"), QStringLiteral("list-remove"), QStringLiteral("f_CURRENTAMOUNT<=0"), QLatin1String(""), Qt::META + Qt::Key_Minus); 0043 ui.kView->getShowWidget()->setDefaultState(QStringLiteral("all")); 0044 0045 0046 ui.kView->getShowWidget()->setDefaultState(QStringLiteral("all")); 0047 0048 ui.kNameLbl->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_name")))); 0049 ui.kAddressLabel->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_address")))); 0050 ui.kCategoryLabel->setText(i18n("%1:", iDocument->getDisplay(QStringLiteral("t_CATEGORY")))); 0051 0052 ui.kAddButton->setIcon(SKGServices::fromTheme(QStringLiteral("list-add"))); 0053 ui.kModifyButton->setIcon(SKGServices::fromTheme(QStringLiteral("dialog-ok"))); 0054 ui.kDeleteUnusedButton->setIcon(SKGServices::fromTheme(QStringLiteral("edit-delete"))); 0055 0056 ui.kView->setModel(new SKGObjectModel(qobject_cast<SKGDocumentBank*>(getDocument()), QStringLiteral("v_payee_display"), QStringLiteral("1=0"), this, QLatin1String(""), false)); 0057 ui.kView->getView()->resizeColumnToContents(0); 0058 0059 connect(getDocument(), &SKGDocument::tableModified, this, &SKGPayeePluginWidget::dataModified, Qt::QueuedConnection); 0060 connect(ui.kView->getView(), &SKGTreeView::clickEmptyArea, this, &SKGPayeePluginWidget::cleanEditor); 0061 connect(ui.kView->getView(), &SKGTreeView::doubleClicked, SKGMainPanel::getMainPanel()->getGlobalAction(QStringLiteral("open")).data(), &QAction::trigger); 0062 connect(ui.kView->getView(), &SKGTreeView::selectionChangedDelayed, this, [ = ] {this->onSelectionChanged();}); 0063 0064 connect(ui.kAddButton, &QPushButton::clicked, this, &SKGPayeePluginWidget::onAddPayee); 0065 connect(ui.kModifyButton, &QPushButton::clicked, this, &SKGPayeePluginWidget::onModifyPayee); 0066 connect(ui.kNameInput, &QLineEdit::textChanged, this, &SKGPayeePluginWidget::onEditorModified); 0067 connect(ui.kDeleteUnusedButton, &QPushButton::clicked, this, &SKGPayeePluginWidget::onDeleteUnused); 0068 0069 // Set Event filters to catch CTRL+ENTER or SHIFT+ENTER 0070 this->installEventFilter(this); 0071 0072 dataModified(QLatin1String(""), 0); 0073 } 0074 0075 SKGPayeePluginWidget::~SKGPayeePluginWidget() 0076 { 0077 SKGTRACEINFUNC(1) 0078 } 0079 0080 bool SKGPayeePluginWidget::eventFilter(QObject* iObject, QEvent* iEvent) 0081 { 0082 if ((iEvent != nullptr) && iEvent->type() == QEvent::KeyPress) { 0083 auto* keyEvent = dynamic_cast<QKeyEvent*>(iEvent); 0084 if (keyEvent && (keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) && iObject == this) { 0085 if ((QApplication::keyboardModifiers() & Qt::ControlModifier) != 0u && ui.kAddButton->isEnabled()) { 0086 ui.kAddButton->click(); 0087 } else if ((QApplication::keyboardModifiers() &Qt::ShiftModifier) != 0u && ui.kModifyButton->isEnabled()) { 0088 ui.kModifyButton->click(); 0089 } 0090 } 0091 } 0092 0093 return SKGTabPage::eventFilter(iObject, iEvent); 0094 } 0095 0096 void SKGPayeePluginWidget::onSelectionChanged() 0097 { 0098 SKGTRACEINFUNC(10) 0099 0100 int nbSelect = ui.kView->getView()->getNbSelectedObjects(); 0101 if (nbSelect == 1) { 0102 SKGPayeeObject obj(ui.kView->getView()->getFirstSelectedObject()); 0103 0104 ui.kNameInput->setText(obj.getName()); 0105 ui.kAddressEdit->setText(obj.getAddress()); 0106 ui.kCategoryEdit->setText(obj.getAttribute(QStringLiteral("t_CATEGORY"))); 0107 } else if (nbSelect > 1) { 0108 ui.kNameInput->setText(NOUPDATE); 0109 ui.kAddressEdit->setText(NOUPDATE); 0110 ui.kCategoryEdit->setText(NOUPDATE); 0111 } 0112 0113 onEditorModified(); 0114 Q_EMIT selectionChanged(); 0115 } 0116 0117 QString SKGPayeePluginWidget::getState() 0118 { 0119 SKGTRACEINFUNC(10) 0120 QDomDocument doc(QStringLiteral("SKGML")); 0121 QDomElement root = doc.createElement(QStringLiteral("parameters")); 0122 doc.appendChild(root); 0123 root.setAttribute(QStringLiteral("view"), ui.kView->getState()); 0124 return doc.toString(); 0125 } 0126 0127 void SKGPayeePluginWidget::setState(const QString& iState) 0128 { 0129 SKGTRACEINFUNC(10) 0130 QDomDocument doc(QStringLiteral("SKGML")); 0131 doc.setContent(iState); 0132 QDomElement root = doc.documentElement(); 0133 0134 ui.kView->setFilter(SKGServices::fromTheme(root.attribute(QStringLiteral("title_icon"))), root.attribute(QStringLiteral("title")), root.attribute(QStringLiteral("whereClause"))); 0135 ui.kView->setState(root.attribute(QStringLiteral("view"))); 0136 } 0137 0138 QString SKGPayeePluginWidget::getDefaultStateAttribute() 0139 { 0140 return QStringLiteral("SKGPAYEE_DEFAULT_PARAMETERS"); 0141 } 0142 0143 QWidget* SKGPayeePluginWidget::mainWidget() 0144 { 0145 return ui.kView->getView(); 0146 } 0147 0148 void SKGPayeePluginWidget::onEditorModified() 0149 { 0150 _SKGTRACEINFUNC(10) 0151 int nb = getNbSelectedObjects(); 0152 ui.kModifyButton->setEnabled(!ui.kNameInput->text().isEmpty() && nb >= 1); 0153 ui.kAddButton->setEnabled(!ui.kNameInput->text().isEmpty() && 0154 !ui.kNameInput->text().startsWith(QLatin1Char('='))); 0155 } 0156 0157 void SKGPayeePluginWidget::dataModified(const QString& iTableName, int iIdTransaction, bool iLightTransaction) 0158 { 0159 SKGTRACEINFUNC(10) 0160 Q_UNUSED(iIdTransaction) 0161 0162 if (!iLightTransaction) { 0163 if (iTableName == QStringLiteral("payee") || iTableName.isEmpty()) { 0164 // Set completions 0165 SKGMainPanel::fillWithDistinctValue(QList<QWidget*>() << ui.kNameInput, getDocument(), QStringLiteral("payee"), QStringLiteral("t_name"), QLatin1String(""), true); 0166 SKGMainPanel::fillWithDistinctValue(QList<QWidget*>() << ui.kAddressEdit, getDocument(), QStringLiteral("payee"), QStringLiteral("t_address"), QLatin1String(""), true); 0167 SKGMainPanel::fillWithDistinctValue(QList<QWidget*>() << ui.kCategoryEdit, getDocument(), QStringLiteral("category"), QStringLiteral("t_fullname"), QLatin1String("")); 0168 } 0169 } 0170 } 0171 0172 void SKGPayeePluginWidget::onAddPayee() 0173 { 0174 SKGError err; 0175 _SKGTRACEINFUNCRC(10, err) 0176 0177 QString name = ui.kNameInput->text(); 0178 SKGPayeeObject payee; 0179 { 0180 SKGBEGINTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Payee creation '%1'", name), err) 0181 0182 IFOKDO(err, SKGPayeeObject::createPayee(qobject_cast<SKGDocumentBank*>(getDocument()), name, payee)) 0183 IFOKDO(err, payee.setAddress(ui.kAddressEdit->text())) 0184 SKGCategoryObject cat; 0185 QString catName = ui.kCategoryEdit->text().trimmed(); 0186 if (!err && catName != NOUPDATE) { 0187 err = SKGCategoryObject::createPathCategory(qobject_cast<SKGDocumentBank*>(getDocument()), catName, cat, true); 0188 } 0189 IFOKDO(err, payee.setCategory(cat)) 0190 0191 IFOKDO(err, payee.save()) 0192 0193 // Send message 0194 IFOKDO(err, payee.getDocument()->sendMessage(i18nc("An information message", "The payee '%1' has been added", payee.getDisplayName()), SKGDocument::Hidden)) 0195 } 0196 // status bar 0197 IFOK(err) { 0198 err = SKGError(0, i18nc("Successful message after an user action", "Payee '%1' created", name)); 0199 ui.kView->getView()->selectObject(payee.getUniqueID()); 0200 } else { 0201 err.addError(ERR_FAIL, i18nc("Error message", "Payee creation failed")); 0202 } 0203 0204 // Display error 0205 SKGMainPanel::displayErrorMessage(err, true); 0206 } 0207 0208 void SKGPayeePluginWidget::onModifyPayee() 0209 { 0210 SKGError err; 0211 _SKGTRACEINFUNCRC(10, err) 0212 0213 // Get Selection 0214 SKGObjectBase::SKGListSKGObjectBase selection = getSelectedObjects(); 0215 0216 int nb = selection.count(); 0217 0218 { 0219 SKGBEGINPROGRESSTRANSACTION(*getDocument(), i18nc("Noun, name of the user action", "Payee update"), err, nb) 0220 auto name = ui.kNameInput->text(); 0221 if (name != NOUPDATE && !name.startsWith(QLatin1String("="))) { 0222 // Is this name already existing? 0223 bool messageSent = false; 0224 SKGPayeeObject p(getDocument()); 0225 p.setName(name); 0226 IFOK(p.load()) { 0227 if (selection.indexOf(p) == -1) { 0228 // We will have to merge with the existing payee 0229 selection.insert(0, p); 0230 nb++; 0231 0232 getDocument()->sendMessage(i18nc("Information message", "You tried to modify names of selected payees to an existing payee. Payees have been merged.")); 0233 messageSent = true; 0234 } 0235 } 0236 0237 // Is it a massive modification of payees to merge them ? 0238 if (nb > 1) { 0239 if (!messageSent) { 0240 getDocument()->sendMessage(i18nc("Information message", "You tried to modify all names of selected payees. Payees have been merged.")); 0241 } 0242 0243 // Do the merge 0244 SKGPayeeObject payeeObj1(selection[0]); 0245 for (int i = 1; !err && i < nb; ++i) { 0246 SKGPayeeObject payeeObj(selection.at(i)); 0247 0248 // Send message 0249 IFOKDO(err, payeeObj.getDocument()->sendMessage(i18nc("An information message", "The payee '%1' has been merged with payee '%2'", payeeObj1.getDisplayName(), payeeObj.getDisplayName()), SKGDocument::Hidden)) 0250 0251 err = payeeObj1.merge(payeeObj); 0252 } 0253 0254 // Change selection for the rest of the transaction 0255 selection.clear(); 0256 selection.push_back(payeeObj1); 0257 nb = 1; 0258 } 0259 } 0260 0261 for (int i = 0; !err && i < nb; ++i) { 0262 // Modification of object 0263 SKGPayeeObject payee(selection.at(i)); 0264 err = payee.setName(name); 0265 QString address = ui.kAddressEdit->text(); 0266 if (address != NOUPDATE) { 0267 IFOKDO(err, payee.setAddress(address)) 0268 } 0269 SKGCategoryObject cat; 0270 QString catName = ui.kCategoryEdit->text().trimmed(); 0271 if (!err && catName != NOUPDATE) { 0272 err = SKGCategoryObject::createPathCategory(qobject_cast<SKGDocumentBank*>(getDocument()), catName, cat, true); 0273 IFOKDO(err, payee.setCategory(cat)) 0274 } 0275 IFOKDO(err, payee.save()) 0276 0277 // Send message 0278 IFOKDO(err, payee.getDocument()->sendMessage(i18nc("An information message", "The payee '%1' has been updated", payee.getDisplayName()), SKGDocument::Hidden)) 0279 } 0280 } 0281 0282 // status bar 0283 IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Payee updated"))) 0284 else { 0285 err.addError(ERR_FAIL, i18nc("Error message", "Payee update failed")); 0286 } 0287 0288 // Display error 0289 SKGMainPanel::displayErrorMessage(err, true); 0290 0291 // Set focus on table 0292 ui.kView->getView()->setFocus(); 0293 } 0294 0295 void SKGPayeePluginWidget::cleanEditor() 0296 { 0297 if (getNbSelectedObjects() == 0) { 0298 ui.kNameInput->setText(QLatin1String("")); 0299 ui.kAddressEdit->setText(QLatin1String("")); 0300 } 0301 } 0302 0303 void SKGPayeePluginWidget::activateEditor() 0304 { 0305 ui.kNameInput->setFocus(); 0306 } 0307 0308 bool SKGPayeePluginWidget::isEditor() 0309 { 0310 return true; 0311 } 0312 0313 void SKGPayeePluginWidget::onDeleteUnused() 0314 { 0315 QAction* act = SKGMainPanel::getMainPanel()->getGlobalAction(QStringLiteral("clean_delete_unused_payees")); 0316 if (act != nullptr) { 0317 act->trigger(); 0318 } 0319 }