File indexing completed on 2024-05-12 05:07:54

0001 /*
0002     SPDX-FileCopyrightText: 2008-2018 Thomas Baumgart <tbaumgart@kde.org>
0003     SPDX-FileCopyrightText: 2017 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "kaccounttemplateselector.h"
0008 
0009 // ----------------------------------------------------------------------------
0010 // QT Includes
0011 
0012 #include <QDomElement>
0013 #include <QTreeView>
0014 
0015 // ----------------------------------------------------------------------------
0016 // KDE Includes
0017 
0018 #include <KTextEdit>
0019 
0020 // ----------------------------------------------------------------------------
0021 // Project Includes
0022 
0023 #include "ui_kaccounttemplateselector.h"
0024 
0025 #include <mymoneytemplate.h>
0026 #include <templatesmodel.h>
0027 #include <mymoneyaccount.h>
0028 
0029 class KAccountTemplateSelectorPrivate : public QObject
0030 {
0031     Q_DISABLE_COPY(KAccountTemplateSelectorPrivate)
0032 
0033 public:
0034     Ui::KAccountTemplateSelector*     ui;
0035     TemplatesModel*                   model;
0036     QMap<QString, QTreeWidgetItem*>   templateHierarchy;
0037 
0038 public:
0039     KAccountTemplateSelectorPrivate(QObject* parent)
0040         : QObject(parent)
0041         , ui(new Ui::KAccountTemplateSelector)
0042         , model(nullptr)
0043     {
0044     }
0045 
0046     ~KAccountTemplateSelectorPrivate()
0047     {
0048         delete ui;
0049     }
0050 
0051 
0052     QTreeWidgetItem* hierarchyItem(const QString& parent, const QString& name)
0053     {
0054         if (!templateHierarchy.contains(parent)
0055                 || templateHierarchy[parent] == 0) {
0056             static const QRegularExpression hierarchyExp(QLatin1String("(.*):(.*)"));
0057             const auto hierarchyParts(hierarchyExp.match(parent));
0058             if (hierarchyParts.hasMatch())
0059                 templateHierarchy[parent] = hierarchyItem(hierarchyParts.captured(1), hierarchyParts.captured(2));
0060         }
0061         QTreeWidgetItem *item = new QTreeWidgetItem(templateHierarchy[parent]);
0062         item->setText(0, name);
0063         return item;
0064     }
0065 
0066     bool hierarchy(QMap<QString, QTreeWidgetItem*>& list, const QString& parent, QDomNode account)
0067     {
0068         bool rc = true;
0069         while (rc == true && !account.isNull()) {
0070             if (account.isElement()) {
0071                 QDomElement accountElement = account.toElement();
0072                 if (accountElement.tagName() == QLatin1String("account")) {
0073                     QString name = QString("%1:%2").arg(parent, accountElement.attribute("name"));
0074                     list[name] = 0;
0075                     hierarchy(list, name, account.firstChild());
0076                 }
0077             }
0078             account = account.nextSibling();
0079         }
0080         return rc;
0081     }
0082 
0083     void hierarchy(QDomNode accounts, QMap<QString, QTreeWidgetItem*>& list)
0084     {
0085         bool rc = !accounts.isNull();
0086         while (rc == true && !accounts.isNull() && accounts.isElement()) {
0087             QDomElement rootNode = accounts.toElement();
0088             QString name = rootNode.attribute(QLatin1String("name"));
0089             if (rootNode.tagName() == QLatin1String("account")) {
0090                 rootNode = rootNode.firstChild().toElement();
0091                 eMyMoney::Account::Type type = static_cast<eMyMoney::Account::Type>(accounts.toElement().attribute(QLatin1String("type")).toUInt());
0092                 switch (type) {
0093                 case eMyMoney::Account::Type::Asset:
0094                 case eMyMoney::Account::Type::Liability:
0095                 case eMyMoney::Account::Type::Income:
0096                 case eMyMoney::Account::Type::Expense:
0097                 case eMyMoney::Account::Type::Equity:
0098                     if (name.isEmpty())
0099                         name = MyMoneyAccount::accountTypeToString(type);
0100                     list[name] = 0;
0101                     rc = hierarchy(list, name, rootNode);
0102                     break;
0103 
0104                 default:
0105                     rc = false;
0106                     break;
0107                 }
0108             } else {
0109                 rc = false;
0110             }
0111             accounts = accounts.nextSibling();
0112         }
0113     }
0114 
0115     void loadHierarchy()
0116     {
0117         if (model == nullptr) {
0118             return;
0119         }
0120         templateHierarchy.clear();
0121         const auto selection = ui->m_groupList->selectionModel()->selectedIndexes();
0122         for (const auto& idx : qAsConst(selection)) {
0123             const auto tmpl = model->itemByIndex(idx);
0124             hierarchy(tmpl.accountTree(), templateHierarchy);
0125         }
0126 
0127         // I need to think about this some more. The code works and shows
0128         // the current account hierarchy. It might be useful, to show
0129         // existing accounts dimmed and the new ones in bold or so.
0130 #if 0
0131         // add the hierarchy from the MyMoneyFile object
0132         QList<MyMoneyAccount> aList;
0133         QList<MyMoneyAccount>::const_iterator it_a;
0134         auto file = MyMoneyFile::instance();
0135         file->accountList(aList);
0136         if (aList.count() > 0) {
0137             templateHierarchy[file->accountToCategory(file->asset().id(), true)] = 0;
0138             templateHierarchy[file->accountToCategory(file->liability().id(), true)] = 0;
0139             templateHierarchy[file->accountToCategory(file->income().id(), true)] = 0;
0140             templateHierarchy[file->accountToCategory(file->expense().id(), true)] = 0;
0141             templateHierarchy[file->accountToCategory(file->equity().id(), true)] = 0;
0142         }
0143 
0144         for (it_a = aList.begin(); it_a != aList.end(); ++it_a) {
0145             templateHierarchy[file->accountToCategory((*it_a).id(), true)] = 0;
0146         }
0147 #endif
0148 
0149         ui->m_accountList->clear();
0150 
0151         static const QRegularExpression hierarchyExp(QLatin1String("(.*):(.*)"));
0152         for (QMap<QString, QTreeWidgetItem*>::iterator it_h = templateHierarchy.begin(); it_h != templateHierarchy.end(); ++it_h) {
0153             const auto hierarchyParts(hierarchyExp.match(it_h.key()));
0154             if (!hierarchyParts.hasMatch()) {
0155                 (*it_h) = new QTreeWidgetItem(ui->m_accountList);
0156                 (*it_h)->setText(0, it_h.key());
0157             } else {
0158                 (*it_h) = hierarchyItem(hierarchyParts.captured(1), hierarchyParts.captured(2));
0159             }
0160             (*it_h)->setExpanded(true);
0161         }
0162 
0163         ui->m_description->clear();
0164         const auto idx = ui->m_groupList->currentIndex();
0165         if (idx.isValid()) {
0166             const auto desc = idx.data(eMyMoney::Model::TemplatesLongDescriptionRole).toString();
0167             ui->m_description->setText(desc);
0168         }
0169     }
0170 };
0171 
0172 KAccountTemplateSelector::KAccountTemplateSelector(QWidget* parent)
0173     : QWidget(parent)
0174     , d_ptr(new KAccountTemplateSelectorPrivate(this))
0175 {
0176     Q_D(KAccountTemplateSelector);
0177     d->ui->setupUi(this);
0178     d->ui->m_accountList->header()->hide();
0179     d->ui->m_groupList->setSelectionMode(QAbstractItemView::ExtendedSelection);
0180     d->ui->m_groupList->setFocus();
0181 }
0182 
0183 KAccountTemplateSelector::~KAccountTemplateSelector()
0184 {
0185     Q_D(KAccountTemplateSelector);
0186     delete d;
0187 }
0188 
0189 void KAccountTemplateSelector::setModel(TemplatesModel* model)
0190 {
0191     Q_D(KAccountTemplateSelector);
0192     d->model = model;
0193     d->ui->m_groupList->setModel(model);
0194     connect(d->ui->m_groupList->selectionModel(),
0195             &QItemSelectionModel::selectionChanged,
0196             d,
0197             &KAccountTemplateSelectorPrivate::loadHierarchy,
0198             Qt::UniqueConnection);
0199 }
0200 
0201 QList<MyMoneyTemplate> KAccountTemplateSelector::selectedTemplates() const
0202 {
0203     Q_D(const KAccountTemplateSelector);
0204     QList<MyMoneyTemplate> list;
0205     if (d->model != nullptr) {
0206         const auto selection = d->ui->m_groupList->selectionModel()->selectedIndexes();
0207         for (const auto& idx : qAsConst(selection)) {
0208             list << d->model->itemByIndex(idx);
0209         }
0210     }
0211     return list;
0212 }
0213 
0214 void KAccountTemplateSelector::setupInitialSelection()
0215 {
0216     Q_D(KAccountTemplateSelector);
0217     const auto defaultCountry = QLocale().country();
0218 
0219     const auto rows = d->model->rowCount();
0220     for (int row = 0; row < rows; ++row) {
0221         auto idx = d->model->index(row, 0);
0222         const auto locale = idx.data(eMyMoney::Model::TemplatesLocaleRole).toString();
0223 
0224         if (QLocale(locale).country() == defaultCountry) {
0225             d->ui->m_groupList->collapseAll();
0226             d->ui->m_groupList->setExpanded(idx, true);
0227             d->ui->m_groupList->scrollTo(idx, QAbstractItemView::PositionAtTop);
0228             d->ui->m_groupList->setCurrentIndex(idx);
0229             d->ui->m_groupList->resizeColumnToContents(0);
0230             break;
0231         }
0232     }
0233 }