1 /***************************************************************************
2 * SPDX-FileCopyrightText: 2021 S. MANKOWSKI stephane@mankowski.fr
3 * SPDX-FileCopyrightText: 2021 G. DE BURE support@mankowski.fr
4 * SPDX-License-Identifier: GPL-3.0-or-later
5 ***************************************************************************/
6 /** @file
7 * This file is a query creator for skrooge
8 *
9 * @author Stephane MANKOWSKI / Guillaume DE BURE
10 */
11 #include "skgpredicatcreator.h"
12
13 #include <qapplication.h>
14 #include <qcheckbox.h>
15 #include <qdom.h>
16 #include <qlineedit.h>
17 #include <qtablewidget.h>
18
19 #include "skgcalculatoredit.h"
20 #include "skgcombobox.h"
21 #include "skgdateedit.h"
22 #include "skgdocument.h"
23 #include "skgmainpanel.h"
24 #include "skgruleobject.h"
25 #include "skgservices.h"
26
SKGPredicatCreator(QWidget * iParent,SKGDocument * document,const QString & attribute,bool iModeUpdate,const QStringList & iListAtt)27 SKGPredicatCreator::SKGPredicatCreator(QWidget* iParent, SKGDocument* document, const QString& attribute, bool iModeUpdate, const QStringList& iListAtt)
28 : QWidget(iParent), m_updateMode(iModeUpdate), m_kValue1(nullptr), m_kValue2(nullptr), m_kAttributes(nullptr)
29 {
30 SKGServices::AttributeType attType = SKGServices::TEXT;
31 if (document != nullptr) {
32 attType = document->getAttributeType(attribute);
33 }
34
35 // Build
36 this->setAutoFillBackground(true);
37 this->resize(491, 25);
38 auto horizontalLayout = new QHBoxLayout(this);
39 horizontalLayout->setSpacing(2);
40 horizontalLayout->setMargin(0);
41 horizontalLayout->setObjectName(QStringLiteral("horizontalLayout"));
42 m_kOperator = new SKGComboBox(this);
43 m_kOperator->setObjectName(QStringLiteral("kOperator"));
44 m_kOperator->setSizeAdjustPolicy(KComboBox::AdjustToContentsOnFirstShow);
45 QSizePolicy newSizePolicy2(QSizePolicy::Fixed, QSizePolicy::Fixed);
46 newSizePolicy2.setHorizontalStretch(0);
47 newSizePolicy2.setVerticalStretch(0);
48 newSizePolicy2.setHeightForWidth(m_kOperator->sizePolicy().hasHeightForWidth());
49 m_kOperator->setSizePolicy(newSizePolicy2);
50
51 horizontalLayout->addWidget(m_kOperator);
52 int nbAtt = iListAtt.count();
53 if (nbAtt != 0) {
54 m_kAttributes = new SKGComboBox(this);
55 if (m_kAttributes != nullptr) {
56 m_kAttributes->setObjectName(QStringLiteral("kAttributes"));
57 m_kAttributes->setMinimumSize(QSize(100, 0));
58 m_kAttributes->setEditable(false);
59 QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
60 newSizePolicy.setHorizontalStretch(0);
61 newSizePolicy.setVerticalStretch(0);
62 newSizePolicy.setHeightForWidth(m_kAttributes->sizePolicy().hasHeightForWidth());
63 m_kAttributes->setSizePolicy(newSizePolicy);
64
65 horizontalLayout->addWidget(m_kAttributes);
66
67 for (const auto& att : qAsConst(iListAtt)) {
68 if (document != nullptr) {
69 m_kAttributes->addItem(document->getIcon(att), document->getDisplay(att), att);
70 }
71 }
72 }
73 }
74 if (attType == SKGServices::TEXT) {
75 auto cmbVal1 = new SKGComboBox(this);
76 if (cmbVal1 != nullptr) {
77 cmbVal1->setObjectName(QStringLiteral("cmbVal1"));
78 cmbVal1->setMinimumSize(QSize(100, 0));
79 cmbVal1->setEditable(true);
80 QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
81 newSizePolicy.setHorizontalStretch(0);
82 newSizePolicy.setVerticalStretch(0);
83 newSizePolicy.setHeightForWidth(cmbVal1->sizePolicy().hasHeightForWidth());
84 cmbVal1->setSizePolicy(newSizePolicy);
85 cmbVal1->lineEdit()->setPlaceholderText(i18n("Value"));
86
87 horizontalLayout->addWidget(cmbVal1);
88 m_kValue1 = cmbVal1;
89 }
90 auto cmbVal2 = new SKGComboBox(this);
91 if (cmbVal2 != nullptr) {
92 cmbVal2->setObjectName(QStringLiteral("cmbVal2"));
93 cmbVal2->setMinimumSize(QSize(100, 0));
94 cmbVal2->setEditable(true);
95 QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
96 newSizePolicy.setHorizontalStretch(0);
97 newSizePolicy.setVerticalStretch(0);
98 newSizePolicy.setHeightForWidth(cmbVal2->sizePolicy().hasHeightForWidth());
99 cmbVal2->setSizePolicy(newSizePolicy);
100 cmbVal2->lineEdit()->setPlaceholderText(i18n("Value"));
101
102 horizontalLayout->addWidget(cmbVal2);
103 m_kValue2 = cmbVal2;
104 }
105
106 if (document != nullptr) {
107 QString realTable = QStringLiteral("operation");
108 QString realAtt = attribute;
109 QString realCond = QLatin1String("");
110 if (attribute == QStringLiteral("t_REALCATEGORY")) {
111 realTable = QStringLiteral("category");
112 realAtt = QStringLiteral("t_fullname");
113 } else if (attribute == QStringLiteral("t_BANK")) {
114 realTable = QStringLiteral("bank");
115 realAtt = QStringLiteral("t_name");
116 } else if (attribute == QStringLiteral("t_ACCOUNT") || attribute == QStringLiteral("t_TOACCOUNT")) {
117 realTable = QStringLiteral("account");
118 realAtt = QStringLiteral("t_name");
119 } else if (attribute == QStringLiteral("t_UNIT")) {
120 realTable = QStringLiteral("unit");
121 realAtt = QStringLiteral("t_name");
122 } else if (attribute == QStringLiteral("t_REALCOMMENT")) {
123 realTable = QStringLiteral("suboperation");
124 realAtt = QStringLiteral("t_comment");
125 } else if (attribute == QStringLiteral("t_REALREFUND")) {
126 realTable = QStringLiteral("refund");
127 realAtt = QStringLiteral("t_name");
128 } else if (attribute == QStringLiteral("t_PAYEE")) {
129 realTable = QStringLiteral("payee");
130 realAtt = QStringLiteral("t_name");
131 } else if (attribute.startsWith(QLatin1String("p_"))) {
132 realTable = QStringLiteral("parameters");
133 realAtt = QStringLiteral("t_value");
134 realCond = "t_name='" % attribute.right(attribute.length() - 2) % '\'';
135 }
136 SKGMainPanel::fillWithDistinctValue(QList<QWidget*>() << cmbVal1 << cmbVal2, document, realTable, realAtt, realCond);
137 }
138 } else if (attType == SKGServices::INTEGER || attType == SKGServices::FLOAT) {
139 auto cmbVal1 = new SKGCalculatorEdit(this);
140 if (cmbVal1 != nullptr) {
141 cmbVal1->setObjectName(QStringLiteral("cmbVal1"));
142 cmbVal1->setMode(SKGCalculatorEdit::EXPRESSION);
143 cmbVal1->setMinimumSize(QSize(100, 0));
144
145 horizontalLayout->addWidget(cmbVal1);
146 m_kValue1 = cmbVal1;
147 }
148 auto cmbVal2 = new SKGCalculatorEdit(this);
149 if (cmbVal2 != nullptr) {
150 cmbVal2->setObjectName(QStringLiteral("cmbVal2"));
151 cmbVal2->setMode(SKGCalculatorEdit::EXPRESSION);
152 cmbVal2->setMinimumSize(QSize(100, 0));
153
154 horizontalLayout->addWidget(cmbVal2);
155 m_kValue2 = cmbVal2;
156 }
157 } else if (attType == SKGServices::DATE) {
158 if (iModeUpdate) {
159 auto cmbVal1 = new SKGComboBox(this);
160 if (cmbVal1 != nullptr) {
161 cmbVal1->setObjectName(QStringLiteral("cmbVal1"));
162 cmbVal1->setMinimumSize(QSize(100, 0));
163 cmbVal1->setEditable(true);
164 QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
165 newSizePolicy.setHorizontalStretch(0);
166 newSizePolicy.setVerticalStretch(0);
167 newSizePolicy.setHeightForWidth(cmbVal1->sizePolicy().hasHeightForWidth());
168 cmbVal1->setSizePolicy(newSizePolicy);
169 cmbVal1->lineEdit()->setPlaceholderText(i18n("Value"));
170
171 horizontalLayout->addWidget(cmbVal1);
172 m_kValue1 = cmbVal1;
173 }
174
175 auto cmbVal2 = new SKGComboBox(this);
176 if (cmbVal2 != nullptr) {
177 cmbVal2->setObjectName(QStringLiteral("cmbVal2"));
178 cmbVal2->setMinimumSize(QSize(100, 0));
179 cmbVal2->setEditable(false);
180 QSizePolicy newSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
181 newSizePolicy.setHorizontalStretch(0);
182 newSizePolicy.setVerticalStretch(0);
183 newSizePolicy.setHeightForWidth(cmbVal2->sizePolicy().hasHeightForWidth());
184 cmbVal2->setSizePolicy(newSizePolicy);
185 cmbVal2->addItems(QStringList() << QStringLiteral("YYYYMMDD") << QStringLiteral("MMDDYYYY") << QStringLiteral("DDMMYYYY")
186 << QStringLiteral("MM-DD-YY") << QStringLiteral("DD-MM-YY") << QStringLiteral("MM-DD-YYYY") << QStringLiteral("DD-MM-YYYY") << QStringLiteral("YYYY-MM-DD"));
187 horizontalLayout->addWidget(cmbVal2);
188 m_kValue2 = cmbVal2;
189 }
190 } else {
191 auto cmbVal1 = new SKGDateEdit(this);
192 if (cmbVal1 != nullptr) {
193 cmbVal1->setObjectName(QStringLiteral("cmbVal1"));
194 cmbVal1->setMinimumSize(QSize(100, 0));
195
196 horizontalLayout->addWidget(cmbVal1);
197 m_kValue1 = cmbVal1;
198 }
199
200 auto cmbVal2 = new SKGDateEdit(this);
201 if (cmbVal2 != nullptr) {
202 cmbVal2->setObjectName(QStringLiteral("cmbVal2"));
203 cmbVal2->setMinimumSize(QSize(100, 0));
204
205 horizontalLayout->addWidget(cmbVal2);
206 m_kValue2 = cmbVal2;
207 }
208 }
209 } else if (attType == SKGServices::BOOL || attType == SKGServices::TRISTATE) {
210 auto cmbVal1 = new QCheckBox(this);
211 if (cmbVal1 != nullptr) {
212 cmbVal1->setObjectName(QStringLiteral("cmbVal1"));
213 cmbVal1->setMinimumSize(QSize(100, 0));
214 cmbVal1->setTristate(attType == SKGServices::TRISTATE);
215
216 horizontalLayout->addWidget(cmbVal1);
217 m_kValue1 = cmbVal1;
218 }
219 }
220
221 // Fill combo boxes
222 m_kOperator->clear();
223 m_kOperator->addItem(QLatin1String(""), "");
224
225 if (m_kValue1 != nullptr) {
226 m_kValue1->installEventFilter(this);
227 }
228 if (m_kValue2 != nullptr) {
229 m_kValue2->installEventFilter(this);
230 }
231 if (m_kOperator != nullptr) {
232 m_kOperator->installEventFilter(this);
233 }
234 if (m_kAttributes != nullptr) {
235 m_kAttributes->installEventFilter(this);
236 }
237
238 QStringList listOps = SKGRuleObject::getListOfOperators(attType, m_updateMode ? SKGRuleObject::UPDATE : SKGRuleObject::SEARCH);
239 int nb = listOps.count();
240 if (iModeUpdate && attribute == QStringLiteral("t_REALCATEGORY") && nb > 1) {
241 nb = 1; // TODO(Stephane MANKOWSKI): unblock t_REALCATEGORY
242 }
243 for (int i = 0; i < nb; ++i) {
244 const QString& op = listOps.at(i);
245 QString nlsOp = SKGRuleObject::getDisplayForOperator(op,
246 i18nc("Default value", "..."),
247 i18nc("Default value", "..."),
248 i18nc("Noun, an item's attribute", "attribute"));
249 if (m_kOperator != nullptr) {
250 m_kOperator->addItem(nlsOp, op);
251 }
252 }
253
254 connect(m_kOperator, static_cast<void (SKGComboBox::*)(const QString&)>(&SKGComboBox::currentTextChanged), this, &SKGPredicatCreator::onOperatorChanged);
255 onOperatorChanged();
256 }
257
~SKGPredicatCreator()258 SKGPredicatCreator::~SKGPredicatCreator()
259 {
260 m_kOperator = nullptr;
261 m_kValue1 = nullptr;
262 m_kValue2 = nullptr;
263 m_kAttributes = nullptr;
264 }
265
eventFilter(QObject * iObject,QEvent * iEvent)266 bool SKGPredicatCreator::eventFilter(QObject* iObject, QEvent* iEvent)
267 {
268 Q_UNUSED(iObject)
269 if ((iEvent != nullptr) && (iEvent->type() == QEvent::FocusIn || iEvent->type() == QEvent::FocusOut)) {
270 QObject* appliFocus = QApplication::focusWidget();
271
272 while (appliFocus != nullptr) {
273 if (appliFocus == this) {
274 break;
275 }
276 appliFocus = appliFocus->parent();
277 }
278 if (appliFocus == nullptr) {
279 Q_EMIT editingFinished();
280 }
281 }
282 return false;
283 }
284
onOperatorChanged()285 void SKGPredicatCreator::onOperatorChanged()
286 {
287 QString req;
288 if (m_kOperator != nullptr) {
289 req = m_kOperator->itemData(m_kOperator->currentIndex()).toString();
290
291 m_kOperator->setToolTip(SKGRuleObject::getToolTipForOperator(req));
292 }
293 if (m_kValue1 != nullptr) {
294 m_kValue1->setVisible(req.contains(QStringLiteral("#V1S#")) || req.contains(QStringLiteral("#V1#")));
295 }
296 if (m_kValue2 != nullptr) {
297 m_kValue2->setVisible(req.contains(QStringLiteral("#V2S#")) || req.contains(QStringLiteral("#V2#")) || req.contains(QStringLiteral("#DF#")));
298 }
299 if (m_kAttributes != nullptr) {
300 m_kAttributes->setVisible(req.contains(QStringLiteral("#ATT2#")));
301 }
302 }
303
text()304 QString SKGPredicatCreator::text()
305 {
306 return SKGPredicatCreator::getTextFromXml(xmlDescription());
307 }
308
getTextFromXml(const QString & iXML)309 QString SKGPredicatCreator::getTextFromXml(const QString& iXML)
310 {
311 QDomDocument doc(QStringLiteral("SKGML"));
312 doc.setContent(iXML);
313 QDomElement root = doc.documentElement();
314 QString output = SKGRuleObject::getDisplayForOperator(root.attribute(QStringLiteral("operator")),
315 root.attribute(QStringLiteral("value")),
316 root.attribute(QStringLiteral("value2")),
317 root.attribute(QStringLiteral("att2s")));
318 return output;
319 }
320
xmlDescription()321 QString SKGPredicatCreator::xmlDescription()
322 {
323 QString output;
324 if (m_kOperator != nullptr) {
325 QString op = m_kOperator->itemData(m_kOperator->currentIndex()).toString();
326 if (!op.isEmpty()) {
327 QDomDocument doc(QStringLiteral("SKGML"));
328 QDomElement root = doc.createElement(QStringLiteral("element"));
329 doc.appendChild(root);
330
331 // Condition
332 root.setAttribute(QStringLiteral("operator"), op);
333 if ((m_kValue1 != nullptr) && m_kValue1->isVisible()) {
334 auto* cmbVal1 = qobject_cast<SKGDateEdit*> (m_kValue1);
335 if (cmbVal1 != nullptr) {
336 root.setAttribute(QStringLiteral("value"), SKGServices::dateToSqlString(cmbVal1->date()));
337 } else {
338 auto* cmbVal12 = qobject_cast<SKGCalculatorEdit*> (m_kValue1);
339 if (cmbVal12 != nullptr) {
340 root.setAttribute(QStringLiteral("value"), cmbVal12->text());
341 } else {
342 auto* cmbVal13 = qobject_cast<QCheckBox*> (m_kValue1);
343 if (cmbVal13 != nullptr) {
344 root.setAttribute(QStringLiteral("value"), cmbVal13->checkState() == Qt::Checked ? QStringLiteral("Y") : cmbVal13->checkState() == Qt::Unchecked ? QStringLiteral("N") : QStringLiteral("P"));
345 } else {
346 auto* cmbVal14 = qobject_cast<SKGComboBox*> (m_kValue1);
347 if (cmbVal14 != nullptr) {
348 root.setAttribute(QStringLiteral("value"), cmbVal14->text());
349 }
350 }
351 }
352 }
353 }
354 if ((m_kValue2 != nullptr) && m_kValue2->isVisible()) {
355 auto* cmbVal2 = qobject_cast<SKGDateEdit*> (m_kValue2);
356 if (cmbVal2 != nullptr) {
357 root.setAttribute(QStringLiteral("value2"), SKGServices::dateToSqlString(cmbVal2->date()));
358 } else {
359 auto* cmbVal21 = qobject_cast<SKGCalculatorEdit*> (m_kValue2);
360 if (cmbVal21 != nullptr) {
361 root.setAttribute(QStringLiteral("value2"), cmbVal21->text());
362 } else {
363 auto* cmbVal22 = qobject_cast<SKGComboBox*> (m_kValue2);
364 if (cmbVal22 != nullptr) {
365 root.setAttribute(QStringLiteral("value2"), cmbVal22->text());
366 }
367 }
368 }
369 }
370
371 if ((m_kAttributes != nullptr) && m_kAttributes->isVisible()) {
372 root.setAttribute(QStringLiteral("att2"), m_kAttributes->itemData(m_kAttributes->currentIndex()).toString());
373 root.setAttribute(QStringLiteral("att2s"), m_kAttributes->text());
374 }
375
376 output = doc.toString();
377 }
378 }
379 return output;
380 }
381
setXmlDescription(const QString & iXML)382 void SKGPredicatCreator::setXmlDescription(const QString& iXML)
383 {
384 QDomDocument doc(QStringLiteral("SKGML"));
385 doc.setContent(iXML);
386 QDomElement root = doc.documentElement();
387
388 // Condition
389 if (m_kOperator != nullptr) {
390 m_kOperator->setCurrentIndex(m_kOperator->findData(root.attribute(QStringLiteral("operator"))));
391 auto* cmbVal1 = qobject_cast<SKGDateEdit*> (m_kValue1);
392 if (cmbVal1 != nullptr) {
393 cmbVal1->setDate(SKGServices::stringToTime(root.attribute(QStringLiteral("value"))).date());
394 } else {
395 auto* cmbVal12 = qobject_cast<SKGCalculatorEdit*> (m_kValue1);
396 if (cmbVal12 != nullptr) {
397 cmbVal12->setText(root.attribute(QStringLiteral("value")));
398 } else {
399 auto* cmbVal13 = qobject_cast<QCheckBox*> (m_kValue1);
400 if (cmbVal13 != nullptr) {
401 cmbVal13->setCheckState(root.attribute(QStringLiteral("value")) == QStringLiteral("Y") ? Qt::Checked : root.attribute(QStringLiteral("value")) == QStringLiteral("P") ? Qt::PartiallyChecked : Qt::Unchecked);
402 } else {
403 auto* cmbVal14 = qobject_cast<SKGComboBox*> (m_kValue1);
404 if (cmbVal14 != nullptr) {
405 cmbVal14->setText(root.attribute(QStringLiteral("value")));
406 }
407 }
408 }
409 }
410
411 auto* cmbVal2 = qobject_cast<SKGDateEdit*> (m_kValue2);
412 if (cmbVal2 != nullptr) {
413 cmbVal2->setDate(SKGServices::stringToTime(root.attribute(QStringLiteral("value2"))).date());
414 } else {
415 auto* cmbVal22 = qobject_cast<SKGCalculatorEdit*> (m_kValue2);
416 if (cmbVal22 != nullptr) {
417 cmbVal22->setText(root.attribute(QStringLiteral("value2")));
418 } else {
419 auto* cmbVal23 = qobject_cast<SKGComboBox*> (m_kValue2);
420 if (cmbVal23 != nullptr) {
421 cmbVal23->setText(root.attribute(QStringLiteral("value2")));
422 }
423 }
424 }
425
426 if (m_kAttributes != nullptr) {
427 m_kAttributes->setCurrentIndex(m_kAttributes->findData(root.attribute(QStringLiteral("att2"))));
428 }
429 }
430
431 emit xmlDescriptionChanged();
432 }
433
434
435
436