File indexing completed on 2024-05-12 16:42:09
0001 /* 0002 SPDX-FileCopyrightText: 2000-2002 Michael Edwardes <mte@users.sourceforge.net> 0003 SPDX-FileCopyrightText: 2017 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com> 0004 SPDX-License-Identifier: GPL-2.0-or-later 0005 */ 0006 0007 #include "knewbankdlg.h" 0008 0009 // ---------------------------------------------------------------------------- 0010 // QT Includes 0011 0012 #include <QPushButton> 0013 #include <QTemporaryFile> 0014 #include <QTimer> 0015 #include <QDesktopServices> 0016 #include <QRegularExpression> 0017 0018 // ---------------------------------------------------------------------------- 0019 // KDE Includes 0020 0021 #include <KMessageBox> 0022 #include <KLineEdit> 0023 #include <kguiutils.h> 0024 #include <KLocalizedString> 0025 #include <KIO/Scheduler> 0026 #include <KIO/Job> 0027 #include <KIOGui/KIO/FavIconRequestJob> 0028 0029 // ---------------------------------------------------------------------------- 0030 // Project Includes 0031 0032 #include "ui_knewbankdlg.h" 0033 0034 #include "mymoneyinstitution.h" 0035 #include "kmymoneyutils.h" 0036 #include "icons.h" 0037 0038 #include <errno.h> 0039 0040 class KNewBankDlgPrivate 0041 { 0042 Q_DISABLE_COPY(KNewBankDlgPrivate) 0043 0044 public: 0045 KNewBankDlgPrivate() : 0046 ui(new Ui::KNewBankDlg) 0047 { 0048 m_iconLoadTimer.setSingleShot(true); 0049 } 0050 0051 ~KNewBankDlgPrivate() 0052 { 0053 delete ui; 0054 } 0055 0056 Ui::KNewBankDlg* ui; 0057 MyMoneyInstitution m_institution; 0058 QTimer m_iconLoadTimer; 0059 QPointer<KIO::FavIconRequestJob> m_favIconJob; 0060 QIcon m_favIcon; 0061 QString m_iconName; 0062 QUrl m_url; 0063 }; 0064 0065 KNewBankDlg::KNewBankDlg(MyMoneyInstitution& institution, QWidget *parent) : 0066 QDialog(parent), 0067 d_ptr(new KNewBankDlgPrivate) 0068 { 0069 Q_D(KNewBankDlg); 0070 d->ui->setupUi(this); 0071 d->m_institution = institution; 0072 setModal(true); 0073 0074 d->ui->nameEdit->setFocus(); 0075 d->ui->nameEdit->setText(institution.name()); 0076 d->ui->cityEdit->setText(institution.city()); 0077 d->ui->streetEdit->setText(institution.street()); 0078 d->ui->postcodeEdit->setText(institution.postcode()); 0079 d->ui->telephoneEdit->setText(institution.telephone()); 0080 d->ui->sortCodeEdit->setText(institution.sortcode()); 0081 d->ui->bicEdit->setText(institution.value(QStringLiteral("bic"))); 0082 d->ui->urlEdit->setText(institution.value(QStringLiteral("url"))); 0083 0084 if (!institution.value(QStringLiteral("icon")).isEmpty()) { 0085 d->m_favIcon = Icons::loadIconFromApplicationCache(institution.value(QStringLiteral("icon"))); 0086 } 0087 if (!d->m_favIcon.isNull()) { 0088 d->ui->iconButton->setEnabled(true); 0089 d->ui->iconButton->setIcon(d->m_favIcon); 0090 } 0091 0092 d->ui->messageWidget->hide(); 0093 0094 connect(d->ui->buttonBox, &QDialogButtonBox::accepted, this, &KNewBankDlg::okClicked); 0095 connect(d->ui->buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); 0096 connect(d->ui->nameEdit, &QLineEdit::textChanged, this, &KNewBankDlg::institutionNameChanged); 0097 connect(d->ui->urlEdit, &QLineEdit::textChanged, this, &KNewBankDlg::slotUrlChanged); 0098 connect(&d->m_iconLoadTimer, &QTimer::timeout, this, &KNewBankDlg::slotLoadIcon); 0099 connect(d->ui->iconButton, &QToolButton::pressed, this, 0100 [=] { 0101 QUrl url; 0102 url.setUrl(QString::fromLatin1("https://%1").arg(d->ui->urlEdit->text())); 0103 QDesktopServices::openUrl(url); 0104 }); 0105 0106 institutionNameChanged(d->ui->nameEdit->text()); 0107 slotUrlChanged(d->ui->urlEdit->text()); 0108 0109 auto requiredFields = new KMandatoryFieldGroup(this); 0110 requiredFields->setOkButton(d->ui->buttonBox->button(QDialogButtonBox::Ok)); // button to be enabled when all fields present 0111 requiredFields->add(d->ui->nameEdit); 0112 } 0113 0114 void KNewBankDlg::institutionNameChanged(const QString &_text) 0115 { 0116 Q_D(KNewBankDlg); 0117 d->ui->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!_text.isEmpty()); 0118 } 0119 0120 KNewBankDlg::~KNewBankDlg() 0121 { 0122 Q_D(KNewBankDlg); 0123 delete d; 0124 } 0125 0126 void KNewBankDlg::okClicked() 0127 { 0128 Q_D(KNewBankDlg); 0129 if (d->ui->nameEdit->text().isEmpty()) { 0130 KMessageBox::information(this, i18n("The institution name field is empty. Please enter the name."), i18n("Adding New Institution")); 0131 d->ui->nameEdit->setFocus(); 0132 return; 0133 } 0134 0135 d->m_institution.setName(d->ui->nameEdit->text()); 0136 d->m_institution.setTown(d->ui->cityEdit->text()); 0137 d->m_institution.setStreet(d->ui->streetEdit->text()); 0138 d->m_institution.setPostcode(d->ui->postcodeEdit->text()); 0139 d->m_institution.setTelephone(d->ui->telephoneEdit->text()); 0140 d->m_institution.setSortcode(d->ui->sortCodeEdit->text()); 0141 d->m_institution.setValue(QStringLiteral("bic"), d->ui->bicEdit->text()); 0142 d->m_institution.setValue(QStringLiteral("url"), d->ui->urlEdit->text()); 0143 d->m_institution.deletePair(QStringLiteral("icon")); 0144 0145 if (d->ui->iconButton->isEnabled()) { 0146 d->m_institution.setValue(QStringLiteral("icon"), d->m_iconName); 0147 Icons::storeIconInApplicationCache(d->m_iconName, d->m_favIcon); 0148 } 0149 accept(); 0150 } 0151 0152 const MyMoneyInstitution& KNewBankDlg::institution() 0153 { 0154 Q_D(KNewBankDlg); 0155 return d->m_institution; 0156 } 0157 0158 void KNewBankDlg::newInstitution(MyMoneyInstitution& institution) 0159 { 0160 institution.clearId(); 0161 QPointer<KNewBankDlg> dlg = new KNewBankDlg(institution); 0162 if (dlg->exec() == QDialog::Accepted && dlg != 0) { 0163 institution = dlg->institution(); 0164 KMyMoneyUtils::newInstitution(institution); 0165 } 0166 delete dlg; 0167 } 0168 0169 void KNewBankDlg::slotUrlChanged(const QString& newUrl) 0170 { 0171 Q_D(KNewBankDlg); 0172 0173 // remove a possible leading protocol since we only provide https for now 0174 QRegularExpression protocol(QStringLiteral("^[a-zA-Z]+://(?<url>.*)"), QRegularExpression::CaseInsensitiveOption); 0175 QRegularExpressionMatch matcher = protocol.match(newUrl); 0176 if (matcher.hasMatch()) { 0177 d->ui->urlEdit->setText(matcher.captured(QStringLiteral("url"))); 0178 d->ui->messageWidget->setText(i18nc("@info:usagetip", "The protocol part has been removed by KMyMoney because it is fixed to https for security reasons.")); 0179 d->ui->messageWidget->setMessageType(KMessageWidget::Information); 0180 d->ui->messageWidget->animatedShow(); 0181 } 0182 d->m_iconLoadTimer.start(200); 0183 } 0184 0185 void KNewBankDlg::slotLoadIcon() 0186 { 0187 Q_D(KNewBankDlg); 0188 0189 // if currently a check is running, retry later 0190 if (d->m_favIconJob) { 0191 d->m_iconLoadTimer.start(200); 0192 return; 0193 } 0194 0195 const auto path = d->ui->urlEdit->text(); 0196 QRegularExpression urlRe(QStringLiteral("^(.*\\.)?[^\\.]{2,}\\.[a-z]{2,}"), QRegularExpression::CaseInsensitiveOption); 0197 QRegularExpressionMatch matcher = urlRe.match(path); 0198 d->ui->iconButton->setEnabled(false); 0199 0200 if (matcher.hasMatch()) { 0201 d->ui->iconButton->setEnabled(true); 0202 d->m_url = QUrl(QString::fromLatin1("https://%1").arg(path)); 0203 KIO::Scheduler::checkSlaveOnHold(true); 0204 d->m_favIconJob = new KIO::FavIconRequestJob(d->m_url); 0205 connect(d->m_favIconJob, &KIO::FavIconRequestJob::result, this, &KNewBankDlg::slotIconLoaded); 0206 // we force to end the job after 1 second to avoid blocking this mechanism in case the thing fails 0207 QTimer::singleShot(1000, this, &KNewBankDlg::killIconLoad); 0208 } 0209 } 0210 0211 void KNewBankDlg::killIconLoad() 0212 { 0213 Q_D(KNewBankDlg); 0214 if (d->m_favIconJob) { 0215 d->m_favIconJob->kill(); 0216 d->m_favIconJob->deleteLater(); 0217 } 0218 } 0219 0220 void KNewBankDlg::slotIconLoaded(KJob* job) 0221 { 0222 Q_D(KNewBankDlg); 0223 0224 switch(job->error()) { 0225 case ECONNREFUSED: 0226 // There is an answer from the server, but no favicon. In case we 0227 // already have one, we keep it 0228 d->ui->iconButton->setEnabled(true); 0229 d->m_favIcon = Icons::get(Icons::Icon::Bank); 0230 d->m_iconName = QStringLiteral("enum:Bank"); 0231 break; 0232 case 0: 0233 // There is an answer from the server, and the favicon is found 0234 d->ui->iconButton->setEnabled(true); 0235 d->m_favIcon = QIcon(dynamic_cast<KIO::FavIconRequestJob*>(job)->iconFile()); 0236 d->m_iconName = QStringLiteral("favicon:%1").arg(d->m_url.host()); 0237 break; 0238 default: 0239 // There is problem with the URL from 0240 qDebug() << "KIO::FavIconRequestJob error" << job->error(); 0241 // intentional fall through 0242 0243 case EALREADY: // invalid URL, no server response 0244 d->ui->iconButton->setEnabled(false); 0245 d->m_favIcon = QIcon(); 0246 d->m_iconName.clear(); 0247 break; 0248 } 0249 d->ui->iconButton->setIcon(d->m_favIcon); 0250 }