1 /*
2 * This file is part of KMyMoney, A Personal Finance Manager by KDE
3 * Copyright (C) 2013-2015 Christian Dávid <christian-david@web.de>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #include "onlinejobmodel.h"
20
21 #include <QIcon>
22 #include <QDateTime>
23
24 #include <KLocalizedString>
25
26 #include "mymoneyobject.h"
27 #include "mymoneyfile.h"
28 #include "mymoneyaccount.h"
29 #include "mymoneyutils.h"
30 #include "onlinetasks/interfaces/tasks/onlinetask.h"
31 #include "onlinetasks/interfaces/tasks/credittransfer.h"
32 #include "mymoney/onlinejobtyped.h"
33 #include "payeeidentifier.h"
34 #include "payeeidentifiertyped.h"
35 #include "payeeidentifier/ibanbic/ibanbic.h"
36 #include "icons/icons.h"
37 #include "mymoneyexception.h"
38 #include "mymoneyenums.h"
39 #include "mymoneymoney.h"
40 #include "mymoneysecurity.h"
41
42 using namespace Icons;
43
onlineJobModel(QObject * parent)44 onlineJobModel::onlineJobModel(QObject *parent) :
45 QAbstractTableModel(parent),
46 m_jobIdList(QStringList())
47 {
48 MyMoneyFile *const file = MyMoneyFile::instance();
49 connect(file, &MyMoneyFile::objectAdded,
50 this, &onlineJobModel::slotObjectAdded);
51 connect(file, &MyMoneyFile::objectModified,
52 this, &onlineJobModel::slotObjectModified);
53 connect(file, &MyMoneyFile::objectRemoved,
54 this, &onlineJobModel::slotObjectRemoved);
55 }
56
load()57 void onlineJobModel::load()
58 {
59 unload();
60 beginInsertRows(QModelIndex(), 0, 0);
61 foreach (const onlineJob job, MyMoneyFile::instance()->onlineJobList()) {
62 m_jobIdList.append(job.id());
63 }
64 endInsertRows();
65 }
66
unload()67 void onlineJobModel::unload()
68 {
69 if (!m_jobIdList.isEmpty()) {
70 beginResetModel();
71 m_jobIdList.clear();
72 endResetModel();
73 }
74 }
75
rowCount(const QModelIndex & parent) const76 int onlineJobModel::rowCount(const QModelIndex & parent) const
77 {
78 if (parent.isValid())
79 return 0;
80 return m_jobIdList.count();
81 }
82
columnCount(const QModelIndex & parent) const83 int onlineJobModel::columnCount(const QModelIndex & parent) const
84 {
85 if (parent.isValid())
86 return 0;
87 return 4;
88 }
89
headerData(int section,Qt::Orientation orientation,int role) const90 QVariant onlineJobModel::headerData(int section, Qt::Orientation orientation, int role) const
91 {
92 if (role != Qt::DisplayRole)
93 return QVariant();
94 if (orientation == Qt::Horizontal) {
95 switch (section) {
96 case columns::ColAccount: return i18n("Account");
97 case columns::ColAction: return i18n("Action");
98 case columns::ColDestination: return i18n("Destination");
99 case columns::ColValue: return i18n("Value");
100 }
101 }
102 return QVariant();
103 }
104
105 /**
106 * @todo LOW improve speed
107 * @todo use now onlineJob system
108 */
data(const QModelIndex & index,int role) const109 QVariant onlineJobModel::data(const QModelIndex & index, int role) const
110 {
111 if (index.parent().isValid())
112 return QVariant();
113
114 Q_ASSERT(m_jobIdList.length() > index.row());
115 onlineJob job;
116
117 try {
118 job = MyMoneyFile::instance()->getOnlineJob(m_jobIdList[index.row()]);
119 } catch (const MyMoneyException &) {
120 return QVariant();
121 }
122
123 // id of MyMoneyObject
124 if (role == roles::OnlineJobId)
125 return QVariant::fromValue(job.id());
126 else if (role == roles::OnlineJobRole)
127 return QVariant::fromValue(job);
128
129 // If job is null, display an error message and exit
130 if (job.isNull()) {
131 if (index.column() == columns::ColAction) {
132 switch (role) {
133 case Qt::DisplayRole: return i18n("Not able to display this job.");
134 case Qt::ToolTipRole: return i18n("Could not find a plugin to display this job or it does not contain any data.");
135 }
136 }
137 return QVariant();
138 }
139
140 // Show general information
141 if (index.column() == columns::ColAccount) {
142 // Account column
143 if (role == Qt::DisplayRole) {
144 return QVariant::fromValue(job.responsibleMyMoneyAccount().name());
145 } else if (role == Qt::DecorationRole) {
146 if (job.isLocked())
147 return Icons::get(Icon::TaskOngoing);
148
149 switch (job.bankAnswerState()) {
150 case eMyMoney::OnlineJob::sendingState::acceptedByBank: return Icons::get(Icon::TaskComplete);
151 case eMyMoney::OnlineJob::sendingState::sendingError:
152 case eMyMoney::OnlineJob::sendingState::abortedByUser:
153 case eMyMoney::OnlineJob::sendingState::rejectedByBank: return Icons::get(Icon::TaskReject);
154 case eMyMoney::OnlineJob::sendingState::noBankAnswer: break;
155 }
156 if (job.sendDate().isValid()) {
157 return Icons::get(Icon::TaskAccepted);
158 } else if (!job.isValid()) {
159 return Icons::get(Icon::Warning);
160 }
161 } else if (role == Qt::ToolTipRole) {
162 if (job.isLocked())
163 return i18n("Job is being processed at the moment.");
164
165 switch (job.bankAnswerState()) {
166 case eMyMoney::OnlineJob::sendingState::acceptedByBank: return i18nc("Arg 1 is a date/time", "This job was accepted by the bank on %1.", job.bankAnswerDate().toString(Qt::DefaultLocaleShortDate));
167 case eMyMoney::OnlineJob::sendingState::sendingError: return i18nc("Arg 1 is a date/time", "Sending this job failed (tried on %1).", job.sendDate().toString(Qt::DefaultLocaleShortDate));
168 case eMyMoney::OnlineJob::sendingState::abortedByUser: return i18n("Sending this job was manually aborted.");
169 case eMyMoney::OnlineJob::sendingState::rejectedByBank: return i18nc("Arg 1 is a date/time", "The bank rejected this job on %1.", job.bankAnswerDate().toString(Qt::DefaultLocaleShortDate));
170 case eMyMoney::OnlineJob::sendingState::noBankAnswer:
171 if (job.sendDate().isValid())
172 return i18nc("Arg 1 is a date/time", "The bank accepted this job on %1.", job.sendDate().toString(Qt::DefaultLocaleShortDate));
173 else if (!job.isValid())
174 return i18n("This job needs further editing and cannot be sent therefore.");
175 else
176 return i18n("This job is ready for sending.");
177 }
178 }
179
180 return QVariant();
181 } else if (index.column() == columns::ColAction) {
182 if (role == Qt::DisplayRole)
183 return QVariant::fromValue(job.task()->jobTypeName());
184 return QVariant();
185 }
186
187 // Show credit transfer data
188 try {
189 onlineJobTyped<creditTransfer> transfer(job);
190
191 if (index.column() == columns::ColValue) {
192 if (role == Qt::DisplayRole)
193 return QVariant::fromValue(MyMoneyUtils::formatMoney(transfer.task()->value(), transfer.task()->currency()));
194 if (role == Qt::TextAlignmentRole)
195 return int (Qt::AlignVCenter | Qt::AlignRight);
196 } else if (index.column() == columns::ColDestination) {
197 if (role == Qt::DisplayRole) {
198 const payeeIdentifierTyped<payeeIdentifiers::ibanBic> ibanBic(transfer.constTask()->beneficiary());
199 return QVariant(ibanBic->ownerName());
200 }
201 }
202 } catch (const MyMoneyException &) {
203 }
204
205 return QVariant();
206 }
207
reloadAll()208 void onlineJobModel::reloadAll()
209 {
210 emit dataChanged(index(rowCount() - 1, 0), index(rowCount() - 1, columnCount() - 1));
211 }
212
213 /**
214 * This method removes the rows from MyMoneyFile.
215 */
removeRow(int row,const QModelIndex & parent)216 bool onlineJobModel::removeRow(int row, const QModelIndex& parent)
217 {
218 if (parent.isValid())
219 return false;
220
221 Q_ASSERT(m_jobIdList.count() < row);
222 MyMoneyFile* file = MyMoneyFile::instance();
223 MyMoneyFileTransaction transaction;
224 const onlineJob job = file->getOnlineJob(m_jobIdList[row]);
225 file->removeOnlineJob(job);
226 transaction.commit();
227 return true;
228 }
229
230 /**
231 * This method removes the rows from MyMoneyFile.
232 */
removeRows(int row,int count,const QModelIndex & parent)233 bool onlineJobModel::removeRows(int row, int count, const QModelIndex & parent)
234 {
235 if (parent.isValid())
236 return false;
237
238 Q_ASSERT(m_jobIdList.count() > row);
239 Q_ASSERT(m_jobIdList.count() >= (row + count));
240
241 MyMoneyFile* file = MyMoneyFile::instance();
242 MyMoneyFileTransaction transaction;
243 for (int i = 0; i < count; ++i) {
244 const onlineJob job = file->getOnlineJob(m_jobIdList[row+i]);
245 file->removeOnlineJob(job);
246 }
247 transaction.commit();
248 return true;
249 }
250
slotObjectAdded(eMyMoney::File::Object objType,const QString & id)251 void onlineJobModel::slotObjectAdded(eMyMoney::File::Object objType, const QString& id)
252 {
253 if (Q_LIKELY(objType != eMyMoney::File::Object::OnlineJob))
254 return;
255 beginInsertRows(QModelIndex(), rowCount(), rowCount());
256 m_jobIdList.append(id);
257 endInsertRows();
258 }
259
slotObjectModified(eMyMoney::File::Object objType,const QString & id)260 void onlineJobModel::slotObjectModified(eMyMoney::File::Object objType, const QString& id)
261 {
262 if (Q_LIKELY(objType != eMyMoney::File::Object::OnlineJob))
263 return;
264
265 int row = m_jobIdList.indexOf(id);
266 if (row != -1)
267 emit dataChanged(index(row, 0), index(row, columnCount() - 1));
268 }
269
slotObjectRemoved(eMyMoney::File::Object objType,const QString & id)270 void onlineJobModel::slotObjectRemoved(eMyMoney::File::Object objType, const QString& id)
271 {
272 if (Q_LIKELY(objType != eMyMoney::File::Object::OnlineJob))
273 return;
274
275 int row = m_jobIdList.indexOf(id);
276 if (row != -1) {
277 m_jobIdList.removeAll(id);
278 beginRemoveRows(QModelIndex(), row, row);
279 endRemoveRows();
280 }
281 }
282