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 is a query creator for skrooge
0008  *
0009  * @author Stephane MANKOWSKI / Guillaume DE BURE
0010  */
0011 #include "skgpredicatcreator.h"
0012 
0013 #include <qapplication.h>
0014 #include <qcheckbox.h>
0015 #include <qdom.h>
0016 #include <qlineedit.h>
0017 #include <qtablewidget.h>
0018 
0019 #include "skgcalculatoredit.h"
0020 #include "skgcombobox.h"
0021 #include "skgdateedit.h"
0022 #include "skgdocument.h"
0023 #include "skgmainpanel.h"
0024 #include "skgruleobject.h"
0025 #include "skgservices.h"
0026 
0027 SKGPredicatCreator::SKGPredicatCreator(QWidget* iParent, SKGDocument* document, const QString& attribute, bool iModeUpdate, const QStringList& iListAtt)
0028     : QWidget(iParent), m_updateMode(iModeUpdate), m_kValue1(nullptr), m_kValue2(nullptr), m_kAttributes(nullptr)
0029 {
0030     SKGServices::AttributeType attType = SKGServices::TEXT;
0031     if (document != nullptr) {
0032         attType = document->getAttributeType(attribute);
0033     }
0034 
0035     // Build
0036     this->setAutoFillBackground(true);
0037     this->resize(491, 25);
0038     auto horizontalLayout = new QHBoxLayout(this);
0039     horizontalLayout->setSpacing(2);
0040     horizontalLayout->setMargin(0);
0041     horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
0042     m_kOperator = new SKGComboBox(this);
0043     m_kOperator->setObjectName(QStringLiteral("kOperator"));
0044     m_kOperator->setSizeAdjustPolicy(KComboBox::AdjustToContentsOnFirstShow);
0045     QSizePolicy newSizePolicy2(QSizePolicy::Fixed, QSizePolicy::Fixed);
0046     newSizePolicy2.setHorizontalStretch(0);
0047     newSizePolicy2.setVerticalStretch(0);
0048     newSizePolicy2.setHeightForWidth(m_kOperator->sizePolicy().hasHeightForWidth());
0049     m_kOperator->setSizePolicy(newSizePolicy2);
0050 
0051     horizontalLayout->addWidget(m_kOperator);
0052     int nbAtt = iListAtt.count();
0053     if (nbAtt != 0) {
0054         m_kAttributes = new SKGComboBox(this);
0055         if (m_kAttributes != nullptr) {
0056             m_kAttributes->setObjectName(QStringLiteral("kAttributes"));
0057             m_kAttributes->setMinimumSize(QSize(100, 0));
0058             m_kAttributes->setEditable(false);
0059             QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
0060             newSizePolicy.setHorizontalStretch(0);
0061             newSizePolicy.setVerticalStretch(0);
0062             newSizePolicy.setHeightForWidth(m_kAttributes->sizePolicy().hasHeightForWidth());
0063             m_kAttributes->setSizePolicy(newSizePolicy);
0064 
0065             horizontalLayout->addWidget(m_kAttributes);
0066 
0067             for (const auto& att : qAsConst(iListAtt)) {
0068                 if (document != nullptr) {
0069                     m_kAttributes->addItem(document->getIcon(att), document->getDisplay(att), att);
0070                 }
0071             }
0072         }
0073     }
0074     if (attType == SKGServices::TEXT) {
0075         auto cmbVal1 = new SKGComboBox(this);
0076         if (cmbVal1 != nullptr) {
0077             cmbVal1->setObjectName(QStringLiteral("cmbVal1"));
0078             cmbVal1->setMinimumSize(QSize(100, 0));
0079             cmbVal1->setEditable(true);
0080             QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
0081             newSizePolicy.setHorizontalStretch(0);
0082             newSizePolicy.setVerticalStretch(0);
0083             newSizePolicy.setHeightForWidth(cmbVal1->sizePolicy().hasHeightForWidth());
0084             cmbVal1->setSizePolicy(newSizePolicy);
0085             cmbVal1->lineEdit()->setPlaceholderText(i18n("Value"));
0086 
0087             horizontalLayout->addWidget(cmbVal1);
0088             m_kValue1 = cmbVal1;
0089         }
0090         auto cmbVal2 = new SKGComboBox(this);
0091         if (cmbVal2 != nullptr) {
0092             cmbVal2->setObjectName(QStringLiteral("cmbVal2"));
0093             cmbVal2->setMinimumSize(QSize(100, 0));
0094             cmbVal2->setEditable(true);
0095             QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
0096             newSizePolicy.setHorizontalStretch(0);
0097             newSizePolicy.setVerticalStretch(0);
0098             newSizePolicy.setHeightForWidth(cmbVal2->sizePolicy().hasHeightForWidth());
0099             cmbVal2->setSizePolicy(newSizePolicy);
0100             cmbVal2->lineEdit()->setPlaceholderText(i18n("Value"));
0101 
0102             horizontalLayout->addWidget(cmbVal2);
0103             m_kValue2 = cmbVal2;
0104         }
0105 
0106         if (document != nullptr) {
0107             QString realTable = QStringLiteral("operation");
0108             QString realAtt = attribute;
0109             QString realCond = QLatin1String("");
0110             if (attribute == QStringLiteral("t_REALCATEGORY")) {
0111                 realTable = QStringLiteral("category");
0112                 realAtt = QStringLiteral("t_fullname");
0113             } else if (attribute == QStringLiteral("t_BANK")) {
0114                 realTable = QStringLiteral("bank");
0115                 realAtt = QStringLiteral("t_name");
0116             } else if (attribute == QStringLiteral("t_ACCOUNT") || attribute == QStringLiteral("t_TOACCOUNT")) {
0117                 realTable = QStringLiteral("account");
0118                 realAtt = QStringLiteral("t_name");
0119             } else if (attribute == QStringLiteral("t_UNIT")) {
0120                 realTable = QStringLiteral("unit");
0121                 realAtt = QStringLiteral("t_name");
0122             } else if (attribute == QStringLiteral("t_REALCOMMENT")) {
0123                 realTable = QStringLiteral("suboperation");
0124                 realAtt = QStringLiteral("t_comment");
0125             } else if (attribute == QStringLiteral("t_REALREFUND")) {
0126                 realTable = QStringLiteral("refund");
0127                 realAtt = QStringLiteral("t_name");
0128             } else if (attribute == QStringLiteral("t_PAYEE")) {
0129                 realTable = QStringLiteral("payee");
0130                 realAtt = QStringLiteral("t_name");
0131             } else if (attribute.startsWith(QLatin1String("p_"))) {
0132                 realTable = QStringLiteral("parameters");
0133                 realAtt = QStringLiteral("t_value");
0134                 realCond = "t_name='" % attribute.right(attribute.length() - 2) % '\'';
0135             }
0136             SKGMainPanel::fillWithDistinctValue(QList<QWidget*>() << cmbVal1 << cmbVal2, document, realTable, realAtt, realCond);
0137         }
0138     } else  if (attType == SKGServices::INTEGER || attType == SKGServices::FLOAT) {
0139         auto cmbVal1 = new SKGCalculatorEdit(this);
0140         if (cmbVal1 != nullptr) {
0141             cmbVal1->setObjectName(QStringLiteral("cmbVal1"));
0142             cmbVal1->setMode(SKGCalculatorEdit::EXPRESSION);
0143             cmbVal1->setMinimumSize(QSize(100, 0));
0144 
0145             horizontalLayout->addWidget(cmbVal1);
0146             m_kValue1 = cmbVal1;
0147         }
0148         auto cmbVal2 = new SKGCalculatorEdit(this);
0149         if (cmbVal2 != nullptr) {
0150             cmbVal2->setObjectName(QStringLiteral("cmbVal2"));
0151             cmbVal2->setMode(SKGCalculatorEdit::EXPRESSION);
0152             cmbVal2->setMinimumSize(QSize(100, 0));
0153 
0154             horizontalLayout->addWidget(cmbVal2);
0155             m_kValue2 = cmbVal2;
0156         }
0157     } else  if (attType == SKGServices::DATE) {
0158         if (iModeUpdate) {
0159             auto cmbVal1 = new SKGComboBox(this);
0160             if (cmbVal1 != nullptr) {
0161                 cmbVal1->setObjectName(QStringLiteral("cmbVal1"));
0162                 cmbVal1->setMinimumSize(QSize(100, 0));
0163                 cmbVal1->setEditable(true);
0164                 QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
0165                 newSizePolicy.setHorizontalStretch(0);
0166                 newSizePolicy.setVerticalStretch(0);
0167                 newSizePolicy.setHeightForWidth(cmbVal1->sizePolicy().hasHeightForWidth());
0168                 cmbVal1->setSizePolicy(newSizePolicy);
0169                 cmbVal1->lineEdit()->setPlaceholderText(i18n("Value"));
0170 
0171                 horizontalLayout->addWidget(cmbVal1);
0172                 m_kValue1 = cmbVal1;
0173             }
0174 
0175             auto cmbVal2 = new SKGComboBox(this);
0176             if (cmbVal2 != nullptr) {
0177                 cmbVal2->setObjectName(QStringLiteral("cmbVal2"));
0178                 cmbVal2->setMinimumSize(QSize(100, 0));
0179                 cmbVal2->setEditable(false);
0180                 QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
0181                 newSizePolicy.setHorizontalStretch(0);
0182                 newSizePolicy.setVerticalStretch(0);
0183                 newSizePolicy.setHeightForWidth(cmbVal2->sizePolicy().hasHeightForWidth());
0184                 cmbVal2->setSizePolicy(newSizePolicy);
0185                 cmbVal2->addItems(QStringList() << QStringLiteral("YYYYMMDD") << QStringLiteral("MMDDYYYY") << QStringLiteral("DDMMYYYY")
0186                                   << QStringLiteral("MM-DD-YY") << QStringLiteral("DD-MM-YY") << QStringLiteral("MM-DD-YYYY") << QStringLiteral("DD-MM-YYYY") << QStringLiteral("YYYY-MM-DD"));
0187                 horizontalLayout->addWidget(cmbVal2);
0188                 m_kValue2 = cmbVal2;
0189             }
0190         } else {
0191             auto cmbVal1 = new SKGDateEdit(this);
0192             if (cmbVal1 != nullptr) {
0193                 cmbVal1->setObjectName(QStringLiteral("cmbVal1"));
0194                 cmbVal1->setMinimumSize(QSize(100, 0));
0195 
0196                 horizontalLayout->addWidget(cmbVal1);
0197                 m_kValue1 = cmbVal1;
0198             }
0199 
0200             auto cmbVal2 = new SKGDateEdit(this);
0201             if (cmbVal2 != nullptr) {
0202                 cmbVal2->setObjectName(QStringLiteral("cmbVal2"));
0203                 cmbVal2->setMinimumSize(QSize(100, 0));
0204 
0205                 horizontalLayout->addWidget(cmbVal2);
0206                 m_kValue2 = cmbVal2;
0207             }
0208         }
0209     } else  if (attType == SKGServices::BOOL || attType == SKGServices::TRISTATE) {
0210         auto cmbVal1 = new QCheckBox(this);
0211         if (cmbVal1 != nullptr) {
0212             cmbVal1->setObjectName(QStringLiteral("cmbVal1"));
0213             cmbVal1->setMinimumSize(QSize(100, 0));
0214             cmbVal1->setTristate(attType == SKGServices::TRISTATE);
0215 
0216             horizontalLayout->addWidget(cmbVal1);
0217             m_kValue1 = cmbVal1;
0218         }
0219     }
0220 
0221     // Fill combo boxes
0222     m_kOperator->clear();
0223     m_kOperator->addItem(QLatin1String(""), "");
0224 
0225     if (m_kValue1 != nullptr) {
0226         m_kValue1->installEventFilter(this);
0227     }
0228     if (m_kValue2 != nullptr) {
0229         m_kValue2->installEventFilter(this);
0230     }
0231     if (m_kOperator != nullptr) {
0232         m_kOperator->installEventFilter(this);
0233     }
0234     if (m_kAttributes != nullptr) {
0235         m_kAttributes->installEventFilter(this);
0236     }
0237 
0238     QStringList listOps = SKGRuleObject::getListOfOperators(attType, m_updateMode ? SKGRuleObject::UPDATE : SKGRuleObject::SEARCH);
0239     int nb = listOps.count();
0240     if (iModeUpdate && attribute == QStringLiteral("t_REALCATEGORY") && nb > 1) {
0241         nb = 1;    // TODO(Stephane MANKOWSKI): unblock t_REALCATEGORY
0242     }
0243     for (int i = 0; i < nb; ++i) {
0244         const QString& op = listOps.at(i);
0245         QString nlsOp = SKGRuleObject::getDisplayForOperator(op,
0246                         i18nc("Default value", "…"),
0247                         i18nc("Default value", "…"),
0248                         i18nc("Noun, an item's attribute", "attribute"));
0249         if (m_kOperator != nullptr) {
0250             m_kOperator->addItem(nlsOp, op);
0251         }
0252     }
0253 
0254     connect(m_kOperator, static_cast<void (SKGComboBox::*)(const QString&)>(&SKGComboBox::currentTextChanged), this, &SKGPredicatCreator::onOperatorChanged);
0255     onOperatorChanged();
0256 }
0257 
0258 SKGPredicatCreator::~SKGPredicatCreator()
0259 {
0260     m_kOperator = nullptr;
0261     m_kValue1 = nullptr;
0262     m_kValue2 = nullptr;
0263     m_kAttributes = nullptr;
0264 }
0265 
0266 bool SKGPredicatCreator::eventFilter(QObject* iObject, QEvent* iEvent)
0267 {
0268     Q_UNUSED(iObject)
0269     if ((iEvent != nullptr) && (iEvent->type() == QEvent::FocusIn || iEvent->type() == QEvent::FocusOut)) {
0270         QObject* appliFocus = QApplication::focusWidget();
0271 
0272         while (appliFocus != nullptr) {
0273             if (appliFocus == this) {
0274                 break;
0275             }
0276             appliFocus = appliFocus->parent();
0277         }
0278         if (appliFocus == nullptr) {
0279             Q_EMIT editingFinished();
0280         }
0281     }
0282     return false;
0283 }
0284 
0285 void SKGPredicatCreator::onOperatorChanged()
0286 {
0287     QString req;
0288     if (m_kOperator != nullptr) {
0289         req = m_kOperator->itemData(m_kOperator->currentIndex()).toString();
0290 
0291         m_kOperator->setToolTip(SKGRuleObject::getToolTipForOperator(req));
0292     }
0293     if (m_kValue1 != nullptr) {
0294         m_kValue1->setVisible(req.contains(QStringLiteral("#V1S#")) || req.contains(QStringLiteral("#V1#")));
0295     }
0296     if (m_kValue2 != nullptr) {
0297         m_kValue2->setVisible(req.contains(QStringLiteral("#V2S#")) || req.contains(QStringLiteral("#V2#")) || req.contains(QStringLiteral("#DF#")));
0298     }
0299     if (m_kAttributes != nullptr) {
0300         m_kAttributes->setVisible(req.contains(QStringLiteral("#ATT2#")));
0301     }
0302 }
0303 
0304 QString SKGPredicatCreator::text()
0305 {
0306     return SKGPredicatCreator::getTextFromXml(xmlDescription());
0307 }
0308 
0309 QString SKGPredicatCreator::getTextFromXml(const QString& iXML)
0310 {
0311     QDomDocument doc(QStringLiteral("SKGML"));
0312     doc.setContent(iXML);
0313     QDomElement root = doc.documentElement();
0314     QString output = SKGRuleObject::getDisplayForOperator(root.attribute(QStringLiteral("operator")),
0315                      root.attribute(QStringLiteral("value")),
0316                      root.attribute(QStringLiteral("value2")),
0317                      root.attribute(QStringLiteral("att2s")));
0318     return output;
0319 }
0320 
0321 QString SKGPredicatCreator::xmlDescription()
0322 {
0323     QString output;
0324     if (m_kOperator != nullptr) {
0325         QString op = m_kOperator->itemData(m_kOperator->currentIndex()).toString();
0326         if (!op.isEmpty()) {
0327             QDomDocument doc(QStringLiteral("SKGML"));
0328             QDomElement root = doc.createElement(QStringLiteral("element"));
0329             doc.appendChild(root);
0330 
0331             // Condition
0332             root.setAttribute(QStringLiteral("operator"), op);
0333             if ((m_kValue1 != nullptr) && m_kValue1->isVisible()) {
0334                 auto* cmbVal1 = qobject_cast<SKGDateEdit*> (m_kValue1);
0335                 if (cmbVal1 != nullptr) {
0336                     root.setAttribute(QStringLiteral("value"), SKGServices::dateToSqlString(cmbVal1->date()));
0337                 } else {
0338                     auto* cmbVal12 = qobject_cast<SKGCalculatorEdit*> (m_kValue1);
0339                     if (cmbVal12 != nullptr) {
0340                         root.setAttribute(QStringLiteral("value"), cmbVal12->text());
0341                     } else {
0342                         auto* cmbVal13 = qobject_cast<QCheckBox*> (m_kValue1);
0343                         if (cmbVal13 != nullptr) {
0344                             root.setAttribute(QStringLiteral("value"), cmbVal13->checkState() == Qt::Checked ? QStringLiteral("Y") : cmbVal13->checkState() == Qt::Unchecked ? QStringLiteral("N") : QStringLiteral("P"));
0345                         } else {
0346                             auto* cmbVal14 = qobject_cast<SKGComboBox*> (m_kValue1);
0347                             if (cmbVal14 != nullptr) {
0348                                 root.setAttribute(QStringLiteral("value"), cmbVal14->text());
0349                             }
0350                         }
0351                     }
0352                 }
0353             }
0354             if ((m_kValue2 != nullptr) && m_kValue2->isVisible()) {
0355                 auto* cmbVal2 = qobject_cast<SKGDateEdit*> (m_kValue2);
0356                 if (cmbVal2 != nullptr) {
0357                     root.setAttribute(QStringLiteral("value2"), SKGServices::dateToSqlString(cmbVal2->date()));
0358                 } else {
0359                     auto* cmbVal21 = qobject_cast<SKGCalculatorEdit*> (m_kValue2);
0360                     if (cmbVal21 != nullptr) {
0361                         root.setAttribute(QStringLiteral("value2"), cmbVal21->text());
0362                     } else {
0363                         auto* cmbVal22 = qobject_cast<SKGComboBox*> (m_kValue2);
0364                         if (cmbVal22 != nullptr) {
0365                             root.setAttribute(QStringLiteral("value2"), cmbVal22->text());
0366                         }
0367                     }
0368                 }
0369             }
0370 
0371             if ((m_kAttributes != nullptr) && m_kAttributes->isVisible()) {
0372                 root.setAttribute(QStringLiteral("att2"), m_kAttributes->itemData(m_kAttributes->currentIndex()).toString());
0373                 root.setAttribute(QStringLiteral("att2s"), m_kAttributes->text());
0374             }
0375 
0376             output = doc.toString();
0377         }
0378     }
0379     return output;
0380 }
0381 
0382 void SKGPredicatCreator::setXmlDescription(const QString& iXML)
0383 {
0384     QDomDocument doc(QStringLiteral("SKGML"));
0385     doc.setContent(iXML);
0386     QDomElement root = doc.documentElement();
0387 
0388     // Condition
0389     if (m_kOperator != nullptr) {
0390         m_kOperator->setCurrentIndex(m_kOperator->findData(root.attribute(QStringLiteral("operator"))));
0391         auto* cmbVal1 = qobject_cast<SKGDateEdit*> (m_kValue1);
0392         if (cmbVal1 != nullptr) {
0393             cmbVal1->setDate(SKGServices::stringToTime(root.attribute(QStringLiteral("value"))).date());
0394         } else {
0395             auto* cmbVal12 = qobject_cast<SKGCalculatorEdit*> (m_kValue1);
0396             if (cmbVal12 != nullptr) {
0397                 cmbVal12->setText(root.attribute(QStringLiteral("value")));
0398             } else {
0399                 auto* cmbVal13 = qobject_cast<QCheckBox*> (m_kValue1);
0400                 if (cmbVal13 != nullptr) {
0401                     cmbVal13->setCheckState(root.attribute(QStringLiteral("value")) == QStringLiteral("Y") ? Qt::Checked : root.attribute(QStringLiteral("value")) == QStringLiteral("P") ? Qt::PartiallyChecked : Qt::Unchecked);
0402                 } else {
0403                     auto* cmbVal14 = qobject_cast<SKGComboBox*> (m_kValue1);
0404                     if (cmbVal14 != nullptr) {
0405                         cmbVal14->setText(root.attribute(QStringLiteral("value")));
0406                     }
0407                 }
0408             }
0409         }
0410 
0411         auto* cmbVal2 = qobject_cast<SKGDateEdit*> (m_kValue2);
0412         if (cmbVal2 != nullptr) {
0413             cmbVal2->setDate(SKGServices::stringToTime(root.attribute(QStringLiteral("value2"))).date());
0414         } else {
0415             auto* cmbVal22 = qobject_cast<SKGCalculatorEdit*> (m_kValue2);
0416             if (cmbVal22 != nullptr) {
0417                 cmbVal22->setText(root.attribute(QStringLiteral("value2")));
0418             } else {
0419                 auto* cmbVal23 = qobject_cast<SKGComboBox*> (m_kValue2);
0420                 if (cmbVal23 != nullptr) {
0421                     cmbVal23->setText(root.attribute(QStringLiteral("value2")));
0422                 }
0423             }
0424         }
0425 
0426         if (m_kAttributes != nullptr) {
0427             m_kAttributes->setCurrentIndex(m_kAttributes->findData(root.attribute(QStringLiteral("att2"))));
0428         }
0429     }
0430 
0431     emit xmlDescriptionChanged();
0432 }
0433 
0434 
0435