File indexing completed on 2024-05-12 16:43:54

0001 /*
0002     SPDX-FileCopyrightText: 2015 Thomas Baumgart <tbaumgart@kde.org>
0003     SPDX-License-Identifier: GPL-2.0-or-later
0004 */
0005 
0006 #include "simpleledgerview.h"
0007 
0008 // ----------------------------------------------------------------------------
0009 // QT Includes
0010 
0011 #include <QTabBar>
0012 #include <QToolButton>
0013 #include <QUrl>
0014 #include <QDesktopServices>
0015 
0016 // ----------------------------------------------------------------------------
0017 // KDE Includes
0018 
0019 
0020 // ----------------------------------------------------------------------------
0021 // Project Includes
0022 
0023 #include "kmymoneyviewbase_p.h"
0024 #include "ledgerviewpage.h"
0025 #include "models.h"
0026 #include "accountsmodel.h"
0027 #include "kmymoneyaccountcombo.h"
0028 #include "ui_simpleledgerview.h"
0029 #include "icons/icons.h"
0030 #include "mymoneyfile.h"
0031 #include "mymoneyaccount.h"
0032 #include "mymoneyinstitution.h"
0033 #include "mymoneyenums.h"
0034 #include "modelenums.h"
0035 
0036 using namespace Icons;
0037 
0038 class SimpleLedgerViewPrivate : public KMyMoneyViewBasePrivate
0039 {
0040     Q_DECLARE_PUBLIC(SimpleLedgerView)
0041 
0042 public:
0043     explicit SimpleLedgerViewPrivate(SimpleLedgerView* qq)
0044         : q_ptr(qq)
0045         , ui(new Ui_SimpleLedgerView)
0046         , accountsModel(nullptr)
0047         , newTabWidget(nullptr)
0048         , webSiteButton(nullptr)
0049         , lastIdx(-1)
0050         , inModelUpdate(false)
0051         , m_needLoad(true)
0052     {}
0053 
0054     ~SimpleLedgerViewPrivate()
0055     {
0056         delete ui;
0057     }
0058 
0059     void init()
0060     {
0061         Q_Q(SimpleLedgerView);
0062         m_needLoad = false;
0063         ui->setupUi(q);
0064         ui->ledgerTab->setTabIcon(0, Icons::get(Icon::ListAdd));
0065         ui->ledgerTab->setTabText(0, QString());
0066         newTabWidget = ui->ledgerTab->widget(0);
0067 
0068         accountsModel= new AccountNamesFilterProxyModel(q);
0069 
0070         // remove close button from new page
0071         QTabBar* bar = ui->ledgerTab->findChild<QTabBar*>();
0072         if(bar) {
0073             QTabBar::ButtonPosition closeSide = (QTabBar::ButtonPosition)q->style()->styleHint(QStyle::SH_TabBar_CloseButtonPosition, 0, newTabWidget);
0074             QWidget *w = bar->tabButton(0, closeSide);
0075             bar->setTabButton(0, closeSide, 0);
0076             w->deleteLater();
0077             q->connect(bar, SIGNAL(tabMoved(int,int)), q, SLOT(checkTabOrder(int,int)));
0078         }
0079 
0080         webSiteButton = new QToolButton;
0081         ui->ledgerTab->setCornerWidget(webSiteButton);
0082         q->connect(webSiteButton, &QToolButton::pressed, q,
0083         [=] {
0084             QDesktopServices::openUrl(webSiteUrl);
0085         });
0086 
0087         q->connect(ui->accountCombo, SIGNAL(accountSelected(QString)), q, SLOT(openNewLedger(QString)));
0088         q->connect(ui->ledgerTab, &QTabWidget::currentChanged, q, &SimpleLedgerView::tabSelected);
0089         q->connect(Models::instance(), &Models::modelsLoaded, q, &SimpleLedgerView::updateModels);
0090         q->connect(ui->ledgerTab, &QTabWidget::tabCloseRequested, q, &SimpleLedgerView::closeLedger);
0091         // we reload the icon if the institution data changed
0092         q->connect(Models::instance()->institutionsModel(), &InstitutionsModel::dataChanged, q, &SimpleLedgerView::setupCornerWidget);
0093 
0094         accountsModel->addAccountGroup(QVector<eMyMoney::Account::Type> {eMyMoney::Account::Type::Asset, eMyMoney::Account::Type::Liability, eMyMoney::Account::Type::Equity});
0095 
0096         accountsModel->setHideEquityAccounts(false);
0097         auto const model = Models::instance()->accountsModel();
0098         accountsModel->setSourceColumns(model->getColumns());
0099         accountsModel->setSourceModel(model);
0100         accountsModel->sort((int)eAccountsModel::Column::Account);
0101         ui->accountCombo->setModel(accountsModel);
0102 
0103         q->tabSelected(0);
0104         q->updateModels();
0105         q->openFavoriteLedgers();
0106     }
0107 
0108     SimpleLedgerView*             q_ptr;
0109     Ui_SimpleLedgerView*          ui;
0110     AccountNamesFilterProxyModel* accountsModel;
0111     QWidget*                      newTabWidget;
0112     QToolButton*                  webSiteButton;
0113     QUrl                          webSiteUrl;
0114     int                           lastIdx;
0115     bool                          inModelUpdate;
0116     bool                          m_needLoad;
0117 };
0118 
0119 
0120 SimpleLedgerView::SimpleLedgerView(QWidget *parent) :
0121     KMyMoneyViewBase(*new SimpleLedgerViewPrivate(this), parent)
0122 {
0123 }
0124 
0125 SimpleLedgerView::~SimpleLedgerView()
0126 {
0127 }
0128 
0129 void SimpleLedgerView::openNewLedger(QString accountId)
0130 {
0131     Q_D(SimpleLedgerView);
0132     if(d->inModelUpdate || accountId.isEmpty())
0133         return;
0134 
0135     LedgerViewPage* view = 0;
0136     // check if ledger is already opened
0137     for(int idx=0; idx < d->ui->ledgerTab->count()-1; ++idx) {
0138         view = qobject_cast<LedgerViewPage*>(d->ui->ledgerTab->widget(idx));
0139         if(view) {
0140             if(accountId == view->accountId()) {
0141                 d->ui->ledgerTab->setCurrentIndex(idx);
0142                 return;
0143             }
0144         }
0145     }
0146 
0147     // need a new tab, we insert it before the rightmost one
0148     QModelIndex index = Models::instance()->accountsModel()->accountById(accountId);
0149     if(index.isValid()) {
0150 
0151         // create new ledger view page
0152         MyMoneyAccount acc = Models::instance()->accountsModel()->data(index, (int)eAccountsModel::Role::Account).value<MyMoneyAccount>();
0153         view = new LedgerViewPage(this);
0154         view->setShowEntryForNewTransaction();
0155         view->setAccount(acc);
0156 
0157         /// @todo setup current global setting for form visibility
0158         // view->showTransactionForm(...);
0159 
0160         // insert new ledger view page in tab view
0161         int newIdx = d->ui->ledgerTab->insertTab(d->ui->ledgerTab->count()-1, view, acc.name());
0162         d->ui->ledgerTab->setCurrentIndex(d->ui->ledgerTab->count()-1);
0163         d->ui->ledgerTab->setCurrentIndex(newIdx);
0164     }
0165 }
0166 
0167 void SimpleLedgerView::tabSelected(int idx)
0168 {
0169     Q_D(SimpleLedgerView);
0170     // qDebug() << "tabSelected" << idx << (d->ui->ledgerTab->count()-1);
0171     if(idx != (d->ui->ledgerTab->count()-1)) {
0172         d->lastIdx = idx;
0173     }
0174     setupCornerWidget();
0175 }
0176 
0177 void SimpleLedgerView::updateModels()
0178 {
0179     Q_D(SimpleLedgerView);
0180     d->inModelUpdate = true;
0181     // d->ui->accountCombo->
0182     d->ui->accountCombo->expandAll();
0183     d->ui->accountCombo->setSelected(MyMoneyFile::instance()->asset().id());
0184     d->inModelUpdate = false;
0185 }
0186 
0187 void SimpleLedgerView::closeLedger(int idx)
0188 {
0189     Q_D(SimpleLedgerView);
0190     // don't react on the close request for the new ledger function
0191     if(idx != (d->ui->ledgerTab->count()-1)) {
0192         d->ui->ledgerTab->removeTab(idx);
0193     }
0194 }
0195 
0196 void SimpleLedgerView::checkTabOrder(int from, int to)
0197 {
0198     Q_D(SimpleLedgerView);
0199     if(d->inModelUpdate)
0200         return;
0201 
0202     QTabBar* bar = d->ui->ledgerTab->findChild<QTabBar*>();
0203     if(bar) {
0204         const int rightMostIdx = d->ui->ledgerTab->count()-1;
0205 
0206         if(from == rightMostIdx) {
0207             // someone tries to move the new account tab away from the rightmost position
0208             d->inModelUpdate = true;
0209             bar->moveTab(to, from);
0210             d->inModelUpdate = false;
0211         }
0212     }
0213 }
0214 
0215 void SimpleLedgerView::showTransactionForm(bool show)
0216 {
0217     emit showForms(show);
0218 }
0219 
0220 void SimpleLedgerView::closeLedgers()
0221 {
0222     Q_D(SimpleLedgerView);
0223     if (d->m_needLoad)
0224         return;
0225     auto tabCount = d->ui->ledgerTab->count();
0226     // check that we have a least one tab that can be closed
0227     if(tabCount > 1) {
0228         // we keep the tab with the selector open at all times
0229         // which is located in the right most position
0230         --tabCount;
0231         do {
0232             --tabCount;
0233             closeLedger(tabCount);
0234         } while(tabCount > 0);
0235     }
0236 }
0237 
0238 void SimpleLedgerView::openFavoriteLedgers()
0239 {
0240     Q_D(SimpleLedgerView);
0241     if (d->m_needLoad)
0242         return;
0243 
0244     AccountsModel* model = Models::instance()->accountsModel();
0245     QModelIndex start = model->index(0, 0);
0246     QModelIndexList indexes = model->match(start, (int)eAccountsModel::Role::Favorite, QVariant(true), -1, Qt::MatchRecursive);
0247 
0248     // indexes now has a list of favorite accounts but two entries for each.
0249     // that doesn't matter here, since openNewLedger() can handle duplicates
0250     Q_FOREACH(QModelIndex index, indexes) {
0251         openNewLedger(model->data(index, (int)eAccountsModel::Role::ID).toString());
0252     }
0253     d->ui->ledgerTab->setCurrentIndex(0);
0254 }
0255 
0256 void SimpleLedgerView::showEvent(QShowEvent* event)
0257 {
0258     if (MyMoneyFile::instance()->storageAttached()) {
0259         Q_D(SimpleLedgerView);
0260         if (d->m_needLoad)
0261             d->init();
0262     }
0263 
0264     // don't forget base class implementation
0265     QWidget::showEvent(event);
0266 }
0267 
0268 void SimpleLedgerView::setupCornerWidget()
0269 {
0270     Q_D(SimpleLedgerView);
0271 
0272     // check if we already have the button, quit if not
0273     if (!d->webSiteButton)
0274         return;
0275 
0276     d->webSiteButton->hide();
0277     auto view = qobject_cast<LedgerViewPage*>(d->ui->ledgerTab->currentWidget());
0278     if (view) {
0279         auto index = Models::instance()->accountsModel()->accountById(view->accountId());
0280         if(index.isValid()) {
0281             // get icon name and url via account and institution object
0282             const auto acc = Models::instance()->accountsModel()->data(index, (int)eAccountsModel::Role::Account).value<MyMoneyAccount>();
0283             if (!acc.institutionId().isEmpty()) {
0284                 index = Models::instance()->institutionsModel()->accountById(acc.institutionId());
0285                 const auto institution = Models::instance()->institutionsModel()->data(index, (int)eAccountsModel::Role::Account).value<MyMoneyInstitution>();
0286                 const auto url = institution.value(QStringLiteral("url"));
0287                 const auto iconName = institution.value(QStringLiteral("icon"));
0288                 if (!url.isEmpty() && !iconName.isEmpty()) {
0289                     const auto favIcon = Icons::loadIconFromApplicationCache(iconName);
0290                     if (!favIcon.isNull()) {
0291                         d->webSiteButton->show();
0292                         d->webSiteButton->setIcon(favIcon);
0293                         d->webSiteButton->setText(url);
0294                         d->webSiteButton->setToolTip(i18n("Open website of <b>%1</b> in your browser.", institution.name()));
0295                         d->webSiteUrl.setUrl(QString::fromLatin1("https://%1/").arg(url));
0296                     }
0297                 }
0298             }
0299         }
0300     }
0301 }
0302