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