summaryrefslogtreecommitdiffstats
path: root/kmymoney2/dialogs/transactioneditor.h
blob: bf47598a00d42c3d9d70b3fc80b193be80dac079 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
/***************************************************************************
                             transactioneditor.h
                             ----------
    begin                : Wed Jun 07 2006
    copyright            : (C) 2006 by Thomas Baumgart
    email                : Thomas Baumgart <ipwizard@users.sourceforge.net>
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/

#ifndef TRANSACTIONEDITOR_H
#define TRANSACTIONEDITOR_H

// ----------------------------------------------------------------------------
// QT Includes

#include <qobject.h>
#include <qwidgetlist.h>

// ----------------------------------------------------------------------------
// KDE Includes


// ----------------------------------------------------------------------------
// Project Includes

#include <kmymoney/mymoneyscheduled.h>
#include <kmymoney/transactioneditorcontainer.h>
#include <kmymoney/register.h>

class KCurrencyExchange;
class KMyMoneyCategory;

class TransactionEditor : public QObject
{
  Q_OBJECT
public:
  TransactionEditor() {}
  TransactionEditor(TransactionEditorContainer* regForm, KMyMoneyRegister::Transaction* item, const KMyMoneyRegister::SelectedTransactions& list, const QDate& lastPostDate);
  virtual ~TransactionEditor();

  /**
    * This method is used as a helper because virtual methods cannot be
    * called within a constructor. Thus setup() should be called immediately
    * after a TransactionEditor() object or one of its derivatives is
    * constructed. The parameter @a account identifies the account that
    * is currently opened in the calling ledger view.
    *
    * This account will not be included in category sets. The default is
    * no account so all will be shown. I have no idea anymore, what I
    * tried to say with the first sentence above. :(  Maybe this is crap.
    *
    * @param tabOrderWidgets QWidgetList which will be filled with the pointers
    *                        to the editWidgets in their tab order
    * @param account account that is currently shown in the calling ledger view
    * @param action default action (defaults to ActionNone).
    */
  void setup(QWidgetList& tabOrderWidgets, const MyMoneyAccount& account = MyMoneyAccount(), KMyMoneyRegister::Action action = KMyMoneyRegister::ActionNone);

  /**
    * Enter the transactions into the ledger. In case of a newly created
    * transaction @a newId contains the assigned id. In case @a askForSchedule
    * is true (the default), the user will be asked if he wants to enter new
    * transactions with a post date in the future into the ledger or rather
    * create a schedule for them. In case  @a suppressBalanceWarnings is @p false
    * (the default) a warning will be displayed when the balance crosses the minimum
    * or maximum balance settings for the account.
    */
  virtual bool enterTransactions(QString& newId, bool askForSchedule = true, bool suppressBalanceWarnings = false);

  /**
    * This method creates a transaction based on the contents of the current widgets,
    * the splits in m_split in single selection mode or an existing transaction/split
    * and the contents of the widgets in multi selection mode.
    *
    * The split referencing the current account is returned as the first split in the
    * transaction's split list.
    *
    * @param t reference to created transaction
    * @param torig the original transaction
    * @param sorig the original split
    * @param skipPriceDialog if @p true the user will not be requested for price information
    *                        (defaults to @p false)
    *
    * @return @p false if aborted by user, @p true otherwise
    *
    * @note Usually not used directly. If unsure, use enterTransactions() instead.
    */
  virtual bool createTransaction(MyMoneyTransaction& t, const MyMoneyTransaction& torig, const MyMoneySplit& sorig, bool skipPriceDialog = false) = 0;

  /**
    * This method returns information about the completeness of the data
    * entered. This can be used to control the availability of the
    * 'Enter transaction' action.
    *
    * @retval true if entering the transaction into the engine
    * @retval false if not enough information is present to enter the
    * transaction into the engine
    *
    * @param reason will be filled with a string about the reason why the
    *               completeness is not reached.  Empty if the return value
    *               is @c true.
    *
    * @sa transactionDataSufficient()
    */
  virtual bool isComplete(QString& reason) const = 0;

  /**
    * This method returns information if the editor is started with multiple transactions
    * being selected or not.
    *
    * @retval false only a single transaction was selected when the editor was started
    * @retval true multiple transactions were selected when the editor was started
    */
  virtual bool isMultiSelection(void) const { return m_transactions.count() > 1; }

  virtual bool fixTransactionCommodity(const MyMoneyAccount& account);

  virtual bool canAssignNumber(void) const;
  virtual void assignNextNumber(void);

  /**
    * Returns a pointer to the widget that should receive
    * the focus after the editor has been started.
    */
  virtual QWidget* firstWidget(void) const = 0;

  /**
    * Returns a pointer to a widget by name
    */
  QWidget* haveWidget(const QString& name) const;

  void setTransaction(const MyMoneyTransaction& t, const MyMoneySplit& s);

  bool eventFilter(QObject* o, QEvent* e);

  const MyMoneyAccount& account(void) const { return m_account; }

  void clearFinalWidgets(void);

  void addFinalWidget(const QWidget*);

public slots:
  void slotReloadEditWidgets(void);

  /**
    * The default implementation returns QDialog::Rejected
    */
  virtual int slotEditSplits(void);

  /**
    * Modify the account which the transaction should be based on. The
    * initial value for the account is passed during setup().
    *
    * @param id of the account to be used
    */
  void slotUpdateAccount(const QString& id);

protected:
  virtual void createEditWidgets(void) = 0;
  virtual void setupFinalWidgets(void) = 0;
  virtual void loadEditWidgets(KMyMoneyRegister::Action action = KMyMoneyRegister::ActionNone) = 0;
  void setupCategoryWidget(KMyMoneyCategory* category, const QValueList<MyMoneySplit>& splits, QString& categoryId, const char* splitEditSlot, bool allowObjectCreation = true);

  /**
   * This method sets the precision of the value widgets to reflect
   * the account in m_account. If m_account has no id, the precision
   * defaults to 2.
   */
  void setupPrecision(void);

protected slots:
  virtual void slotUpdateButtonState(void);
  virtual void slotUpdateAccount(void);
  virtual void slotNumberChanged(const QString&);

signals:
  /**
    * This signal is sent out by the destructor to inform other entities
    * that editing has been finished. The parameter @a t contains the list
    * of transactions that were processed.
    */
  void finishEdit(const KMyMoneyRegister::SelectedTransactions& t);

  /**
    * This signal is sent out whenever enough data is present to enter the
    * transaction into the ledger. This signal can be used to control the
    * KAction which implements entering the transaction.
    *
    * @sa isComplete()
    *
    * @param state @a true if enough data is present, @a false otherwise.
    */
  void transactionDataSufficient(bool state);

  /**
    * This signal is sent out, when a new payee needs to be created
    * @sa KMyMoneyCombo::createItem()
    *
    * @param txt The name of the payee to be created
    * @param id A connected slot should store the id of the created object in this variable
    */
  void createPayee(const QString& txt, QString& id);

  /**
    * This signal is sent out, when a new category needs to be created
    * Depending on the setting of either a payment or deposit, the parent
    * account will be preset to Expense or Income.
    *
    * @param account reference to account info. Will be filled by called slot
    * @param parent reference to parent account
    */
  void createCategory(MyMoneyAccount& account, const MyMoneyAccount& parent);

  /**
    * This signal is sent out, when a new security (e.g. stock )needs to be created
    * @a Parent should be the investment account under which the security account
    * will be created.
    *
    * @param account reference to account info. Will be filled by called slot
    * @param parent reference to parent account
    */
  void createSecurity(MyMoneyAccount& account, const MyMoneyAccount& parent);

  /**
    * Signal is emitted, if any of the widgets enters (@a state equals @a true)
    *  or leaves (@a state equals @a false) object creation mode.
    *
    * @param state Enter (@a true) or leave (@a false) object creation
    */
  void objectCreation(bool state);

  void statusMsg(const QString& txt);

  void statusProgress(int cnt, int base);

  /**
    * This signal is sent out for each newly added transaction
    *
    * @param date the post date of the newly created transaction
    */
  void lastPostDateUsed(const QDate& date);

  /**
    * This signal is sent out, if the user decides to schedule the transaction @a t
    * rather then adding it to the ledger right away.
    */
  void scheduleTransaction(const MyMoneyTransaction& t, MyMoneySchedule::occurenceE occurence);

  /**
   * This signal is sent out, if the user double clicks the number field
   */
  void assignNumber(void);

  /**
   * This signal is sent out, if the user has pressed the ESC key.
   */
  void escapePressed(void);

  /**
   * This signal is sent out, if the user has pressed the Return or Enter
   * key and asks to end editing the transaction
   */
  void returnPressed(void);

  /**
   * This signal is sent out, if any of the balance warning levels
   * for @p account has been reached. @p msg contains the message text.
   * @p parent points to the parent widget to be used for the warning message box.
   */
  void balanceWarning(QWidget* parent, const MyMoneyAccount& account, const QString& msg);

protected:
  QValueList<MyMoneySplit>                          m_splits;
  KMyMoneyRegister::SelectedTransactions            m_transactions;
  QValueList<const QWidget*>                        m_finalEditWidgets;
  TransactionEditorContainer*                       m_regForm;
  KMyMoneyRegister::Transaction*                    m_item;
  KMyMoneyRegister::QWidgetContainer                m_editWidgets;
  MyMoneyAccount                                    m_account;
  MyMoneyTransaction                                m_transaction;
  MyMoneySplit                                      m_split;
  QDate                                             m_lastPostDate;
  QMap<QString, MyMoneyMoney>                       m_priceInfo;
  KMyMoneyRegister::Action                          m_initialAction;
  bool                                              m_openEditSplits;
};


class StdTransactionEditor : public TransactionEditor
{
  Q_OBJECT
public:
  StdTransactionEditor();
  StdTransactionEditor(TransactionEditorContainer* regForm, KMyMoneyRegister::Transaction* item, const KMyMoneyRegister::SelectedTransactions& list, const QDate& lastPostDate);
  ~StdTransactionEditor();

  bool isComplete(QString& reason) const;
  QWidget* firstWidget(void) const;

  bool eventFilter(QObject* o, QEvent* e);

  /**
    * This method creates a transaction based on the contents of the current widgets,
    * the splits in m_split in single selection mode or an existing transaction/split
    * and the contents of the widgets in multi selection mode.
    *
    * The split referencing the current account is returned as the first split in the
    * transaction's split list.
    *
    * @param t reference to created transaction
    * @param torig the original transaction
    * @param sorig the original split
    * @param skipPriceDialog if @p true the user will not be requested for price information
    *                        (defaults to @p false)
    *
    * @return @p false if aborted by user, @p true otherwise
    *
    * @note Usually not used directly. If unsure, use enterTransactions() instead.
    */
  bool createTransaction(MyMoneyTransaction& t, const MyMoneyTransaction& torig, const MyMoneySplit& sorig, bool skipPriceDialog = false);

public slots:
  int slotEditSplits(void);
  void slotUpdateAmount(const QString&);

protected slots:
  void slotReloadEditWidgets(void);
  void slotUpdatePayment(const QString&);
  void slotUpdateDeposit(const QString&);
  void slotUpdateCategory(const QString&);
  void slotUpdatePayee(const QString&);
  void slotUpdateCashFlow(KMyMoneyRegister::CashFlowDirection);
  void slotCreateCategory(const QString&, QString&);
  void slotUpdateAction(int action);
  void slotUpdateAccount(const QString& id);

protected:
  /**
    * This method creates all necessary widgets for this transaction editor.
    * All signals will be connected to the relevant slots.
    */
  void createEditWidgets(void);

  /**
    * This method (re-)loads the widgets with the transaction information
    * contained in @a m_transaction and @a m_split.
    *
    * @param action preset the edit wigdets for @a action if no transaction
    *               is present
    */
  void loadEditWidgets(KMyMoneyRegister::Action action = KMyMoneyRegister::ActionNone);

  void setupCategoryWidget(QString&);
  void updateAmount(const MyMoneyMoney& value);
  bool isTransfer(const QString& accId1, const QString& accId2) const;

  void checkPayeeInSplit(MyMoneySplit& s, const QString& payeeId);

  /**
    * This method fills the editor widgets with the last transaction
    * that can be found for payee @a payeeId in the account @a m_account.
    */
  void autoFill(const QString& payeeId);

  /**
    * Extracts the amount of the transaction from the widgets depending
    * if form or register based input method is used.
    * Returns if an amount has been found in @a update.
    *
    * @param update pointer to update information flag
    * @return amount of transaction (deposit positive, payment negative)
    */
  MyMoneyMoney amountFromWidget(bool* update = 0) const;

  /**
    * Create or update a VAT split
    */
  void updateVAT(bool amountChanged = true);

  MyMoneyMoney removeVatSplit(void);

  /**
    * This method adds a VAT split to transaction @a tr if necessary.
    *
    * @param tr transaction that the split should be added to
    * @param amount Amount to be used for the calculation. Depending upon the
    *               setting of the resp. category, this value is treated as
    *               either gross or net value.
    * @retval false VAT split has not been added
    * @retval true VAT split has been added
    */
  bool addVatSplit(MyMoneyTransaction& tr, const MyMoneyMoney& amount);

  void setupFinalWidgets(void);

  /**
   * This method returns the sum of all splits of transaction @a t that
   * reference account m_account.
   */
  MyMoneyMoney shares(const MyMoneyTransaction& t) const;

private:
  MyMoneyMoney        m_shares;
  bool                m_inUpdateVat;
};


#endif