FreeDebks  1.0.3
 All Classes Files Functions Variables Friends Pages
FdViewJournal.cpp
Go to the documentation of this file.
1 // --------------------------------------------------------------------
2 // Copyright © 2011-2013 Mathieu Schopfer
3 //
4 // This file is part of FreeDebks.
5 //
6 // FreeDebks is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // FreeDebks is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with FreeDebks. If not, see <http://www.gnu.org/licenses/>.
18 // --------------------------------------------------------------------
19 
20 #include "FdViewJournal.hpp"
21 #include "../../data/FdModelJournal.hpp"
22 #include "../../data/FdModelCoa.hpp"
23 #include "../FdMainWindow.hpp"
24 #include "../FdSubWindow.hpp"
25 #include "../../data/FdItemCoa.hpp"
26 
27 FdViewJournal::FdViewJournal(FdSubWindow *parent) : QTableView(0), mSubwindow(parent)
28 {
29  mModel = mSubwindow->journal();
30  setModel(mModel);
31 
32  connect(mModel, SIGNAL(error(QModelIndex)), this, SLOT(setCurrentIndex(QModelIndex)));
33 
34  setSelectionBehavior(QAbstractItemView::SelectRows);
35  setSelectionMode(QAbstractItemView::ExtendedSelection);
36  QHeaderView* header = verticalHeader();
37  header->setDefaultSectionSize(16);
38  setVerticalHeader(header);
39  setEditTriggers(DoubleClicked | EditKeyPressed);
40 
41  setAlternatingRowColors(true);
42 
43  QSettings settings;
44  settings.beginGroup("ViewJournal");
45  setColumnWidth(JournalDate, settings.value("date", 70).toInt());
46  setColumnWidth(JournalObject, settings.value("object", 50).toInt());
47  setColumnWidth(JournalLabel, settings.value("label", 300).toInt());
48  setColumnWidth(JournalDebitId, settings.value("debitId", 50).toInt());
49  setColumnWidth(JournalCreditId, settings.value("debitLabel", 225).toInt());
50  setColumnWidth(JournalDebitLabel, settings.value("creditId", 50).toInt());
51  setColumnWidth(JournalCreditLabel, settings.value("creditLabel", 225).toInt());
52  settings.endGroup();
53  horizontalHeader()->setResizeMode(JournalAmount, QHeaderView::Stretch);
54 
55  mDelegate = new FdDelegateJournal(mModel, mSubwindow, this);
56  setItemDelegate(mDelegate);
57 
58  setContextMenuPolicy(Qt::CustomContextMenu);
59  connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(contextMenu(const QPoint&)));
60 
61  mSearchTimer = new QTimer();
62  mSearchTimer->setInterval(qApp->keyboardInputInterval());
63  mSearchTimer->setSingleShot(true);
64  connect(mSearchTimer, SIGNAL(timeout()), this, SLOT(searchTimeout()));
65 
66  openEditor = false;
67 }
68 
72 void FdViewJournal::mouseReleaseEvent(QMouseEvent* event)
73 {
74  if(event->button() == Qt::LeftButton && !(indexAt(event->pos()).isValid()))
75  setCurrentIndex(QModelIndex());
76 
78 }
79 
83 QModelIndex FdViewJournal::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
84 {
85  if(cursorAction == QAbstractItemView::MoveNext)
86  {
87  if(state() == QAbstractItemView::EditingState)
88  openEditor = true;
89 
90  QModelIndex index = currentIndex();
91  int col = index.column();
92  if(col == JournalLabel || col == JournalDebitId || col == JournalDebitLabel || col == JournalCreditId)
93  return mModel->index(index.row(), col+2);
94  if(index.column() == JournalColumnCount-1 && index.row() == model()->rowCount()-1)
95  return mModel->addEntry(index);
96  }
97  else if(cursorAction == QAbstractItemView::MoveHome && modifiers == Qt::ControlModifier)
98  setCurrentIndex(mModel->index(0, 0));
99  else if(cursorAction == QAbstractItemView::MoveEnd && modifiers == Qt::ControlModifier)
100  setCurrentIndex(mModel->index(mModel->rowCount()-1, JournalColumnCount-1));
101 
102 
103  return QTableView::moveCursor(cursorAction, modifiers);
104 }
105 
111 void FdViewJournal::keyboardSearch(const QString &search)
112 {
113  mSearchTimer->start();
114  mSearchText.append(search);
115  mainWindow->setDockText(tr("Searched string : %1", "Text displayed in the dock widget while keyboardsearching in views. The argument is the user input string to search.").arg(mSearchText));
116 }
117 
119 {
120  if(currentIndex().isValid() && state() != QAbstractItemView::EditingState)
121  edit(currentIndex());
122 }
123 
124 void FdViewJournal::print(QPrinter &printer, QPainter &painter, const QRect &area)
125 {
126  const int rows = model()->rowCount();
127 
128  int pageNumber = 0;
129 
130  struct tableElement dateHeader;
131  dateHeader.width = 0.075*area.width();
132  dateHeader.text = tr("Date", "Journal printed pages column header.");
133  dateHeader.alignement = Qt::AlignLeft;
134  dateHeader.color = Qt::black;
135 
136  struct tableElement objectHeader;
137  objectHeader.width = 0.025*area.width();
138  objectHeader.text = "";
139  objectHeader.alignement = Qt::AlignLeft;
140  objectHeader.color = Qt::black;
141 
142  struct tableElement labelHeader;
143  labelHeader.width = 0.31*area.width();
144  labelHeader.text = tr("Label", "Journal printed pages column header.");
145  labelHeader.alignement = Qt::AlignLeft;
146  labelHeader.color = Qt::black;
147 
148  struct tableElement debitHeader;
149  debitHeader.width = 0.26*area.width();
150  debitHeader.text = tr("Debit account", "Journal printed pages column header.");
151  debitHeader.alignement = Qt::AlignLeft;
152  debitHeader.color = Qt::black;
153 
154  struct tableElement creditHeader;
155  creditHeader.width = 0.26*area.width();
156  creditHeader.text = tr("Credit account", "Journal printed pages column header.");
157  creditHeader.alignement = Qt::AlignLeft;
158  creditHeader.color = Qt::black;
159 
160  struct tableElement amountHeader;
161  amountHeader.width = 0.07*area.width();
162  amountHeader.text = tr("Amount", "Journal printed pages column header.");
163  amountHeader.alignement = Qt::AlignRight;
164  amountHeader.color = Qt::black;
165 
166  QList<tableElement*> header;
167  header << &dateHeader << &objectHeader << &labelHeader << &debitHeader << &creditHeader << &amountHeader;
168 
169  struct tableElement date = dateHeader;
170  struct tableElement object = objectHeader;
171  struct tableElement label = labelHeader;
172  struct tableElement debit = debitHeader;
173  struct tableElement credit = creditHeader;
174  struct tableElement amount = amountHeader;
175  QList<tableElement*> row;
176  row << &date << &object << &label << &debit << &credit << &amount;
177 
178  QRect remainingArea;
179  QModelIndex index;
180  QString text;
181 
182  for(int i = 0; i < rows; ++i)
183  {
184  if(remainingArea.height() == 0)
185  {
186  remainingArea = area;
187 
188  if(pageNumber)
189  printer.newPage();
190  else
191  FdSubWindow::printTitle(painter, remainingArea, tr("Journal", "Journal printed page title."));
192 
193 // painter.drawRect(area);
194 
195  ++pageNumber;
196 
197  mSubwindow->printHeaderFooter(printer, painter, tr("Journal", "Journal printed pages footer."), pageNumber);
198  FdSubWindow::printColumnsHeader(painter, remainingArea, header);
199  }
200 
201  index = model()->index(i, JournalDate);
202  date.text = mDelegate->displayText(model()->data(index));
203 
204  index = model()->index(i, JournalObject);
205  object.text = model()->data(index).toString();
206 
207  index = model()->index(i, JournalLabel);
208  label.text = model()->data(index).toString();
209 
210  index = model()->index(i, JournalDebitId);
211  text = model()->data(index).toString();
212  index = model()->index(i, JournalDebitLabel);
213  debit.text = text+" "+model()->data(index).toString();
214 
215  index = model()->index(i, JournalCreditId);
216  text = model()->data(index).toString();
217  index = model()->index(i, JournalCreditLabel);
218  credit.text = text+" "+model()->data(index).toString();
219 
220  index = model()->index(i, JournalAmount);
221  amount.text = mDelegate->displayText(model()->data(index));
222 
223  FdSubWindow::printTableRow(painter, remainingArea, row);
224  }
225 }
226 
230 QList<int> FdViewJournal::selectedRows() const
231 {
232  QModelIndexList indexes = selectedIndexes();
233  QList<int> rows;
234  for(int i = 0; i < indexes.size(); ++i)
235  {
236  if(indexes[i].column() == 0)
237  rows << indexes[i].row();
238  }
239  return rows;
240 }
241 
242 void FdViewJournal::setDockText() const
243 {
244  QList<int> rows = selectedRows();
245  QString text;
246  if(rows.size() == 0)
248  else if(rows.size() == 1)
249  {
250  text = mModel->data(mModel->index(rows[0], JournalDebitId)).toString();
251  FdItemCoa_p debit = mSubwindow->coa()->itemById(text);
252  text = mModel->data(mModel->index(rows[0], JournalCreditId)).toString();
253  FdItemCoa_p credit = mSubwindow->coa()->itemById(text);
254 
255  if(!debit.isNull())
256  text = debit->displayLabel()+" : "+mDelegate->displayText(debit->balance())+"<br />";
257  if(!credit.isNull())
258  text += credit->displayLabel()+" : "+mDelegate->displayText(credit->balance());
259 
260  mainWindow->setDockText(text);
261  }
262  else
263  {
264  double sum = 0;
265  for(int i = 0; i < rows.size(); ++i)
266  {
267  sum += mModel->data(mModel->index(rows[i], JournalAmount)).toDouble();
268  }
269  text = tr("Sum : %1", "Text displayed in the dock widget when the user selects two rows or more in the journal. The argument is the sum of all entries amounts.").arg(mDelegate->displayText(sum));
270  mainWindow->setDockText(text);
271  }
272 }
273 
275 {
276  QSettings settings;
277  settings.beginGroup("ViewJournal");
278  settings.setValue("date", columnWidth(JournalDate));
279  settings.setValue("object", columnWidth(JournalObject));
280  settings.setValue("label", columnWidth(JournalLabel));
281  settings.setValue("debitId", columnWidth(JournalDebitId));
282  settings.setValue("debitLabel", columnWidth(JournalCreditId));
283  settings.setValue("creditId", columnWidth(JournalDebitLabel));
284  settings.setValue("creditLabel", columnWidth(JournalCreditLabel));
285  settings.endGroup();
286 }
287 
288 void FdViewJournal::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
289 {
290  if(!state())
291  setCurrentIndex(bottomRight);
292  QTableView::dataChanged(topLeft, bottomRight);
293 }
294 
298 void FdViewJournal::setCurrentIndex(const QModelIndex &index)
299 {
300  clearSelection();
302 }
303 
304 void FdViewJournal::currentChanged(const QModelIndex &current, const QModelIndex &previous)
305 {
306  mainWindow->enableRemoveAction(current.isValid());
307 
308  int col = current.column();
309  if(col == JournalDebitId || col == JournalDebitLabel || col == JournalCreditId || col == JournalCreditLabel)
310  mainWindow->enableShowAccountAction();
311  else
312  mainWindow->enableShowAccountAction(false);
313 
314  QTableView::currentChanged(current, previous);
315 }
316 
317 void FdViewJournal::selectionChanged(const QItemSelection &selected, const QItemSelection &deselected)
318 {
319  setDockText();
320  QTableView::selectionChanged(selected, deselected);
321 }
322 
324 {
325  if(openEditor)
326  {
327  openEditor = false;
328  editCurrentItem();
329  }
330 }
331 
332 void FdViewJournal::contextMenu(const QPoint &position)
333 {
334  QModelIndex index = currentIndex();
335  QMenu* menu = new QMenu();
336 
337  if(index.isValid())
338  {
339  menu->addActions(mainWindow->getContextMenuActionsEdit());
340  menu->addSeparator();
341  }
342  menu->addActions(mainWindow->getContextMenuActionsJournal());
343  menu->exec(mapToGlobal(position));
344 }
345 
351 {
353  if(mSearchResults.size())
354  {
355  mCurrentResult = -1;
357  }
358  else
359  mainWindow->setDockText(tr("Sorry, no matches found.", "No matches found when searching item by text."));
360 
361  mSearchText = QString();
362 }
363 
365 {
366  if(mSearchResults.size())
367  {
368  if(mCurrentResult < mSearchResults.size() - 1)
369  {
370  ++ mCurrentResult;
372  }
373  else
374  {
375  mCurrentResult = -1;
377  }
378  }
379  else
380  mainWindow->setDockText(tr("Sorry, no matches found.", "No matches found when searching item by text."));
381 }
382 
384  QStyledItemDelegate(0), mModel(model), mSubwindow(subwindow), mView(view)
385 {
386 }
387 
388 QString FdDelegateJournal::displayText(const QVariant &value) const
389 {
390  return displayText(value, QLocale::system());
391 }
392 
396 QString FdDelegateJournal::displayText(const QVariant &value, const QLocale &locale) const
397 {
398  if(value.type() == QVariant::Date)
399  return value.toDate().toString(Qt::SystemLocaleShortDate);
400  else if(value.type() == QVariant::Double)
401  return QLocale::system().toString(value.toDouble(), 'f', 2);
402 
403  return QStyledItemDelegate::displayText(value, locale);
404 }
405 
411 void FdDelegateJournal::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
412 {
413 
414  if(!mModel->data(index, ValidityRole).toBool())
415  {
416  QStyleOptionViewItem viewOption(option);
417  viewOption.palette.setColor(QPalette::Highlight, Qt::red);
418  QStyledItemDelegate::paint(painter, viewOption, index);
419  }
420  else
421  QStyledItemDelegate::paint(painter, option, index);
422 
423 }
424 
428 QWidget* FdDelegateJournal::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
429 {
430  int column = index.column();
431 
432  if(column == JournalDate || column == JournalObject || column == JournalAmount)
433  return QStyledItemDelegate::createEditor(parent, option, index);
434 
435  QStringList list;
436 
437  if(column == JournalLabel)
438  list = mModel->labels();
439  else if(column == JournalDebitId || column == JournalCreditId)
440  list = mSubwindow->coa()->accountsIds();
441  else if(column == JournalDebitLabel || column == JournalCreditLabel)
442  list = mSubwindow->coa()->accountsLabels();
443 
444  QLineEdit* line = dynamic_cast<QLineEdit*>(QStyledItemDelegate::createEditor(parent, option, index));
445  connect(line, SIGNAL(destroyed()), mView, SLOT(lineEditDestroyed()));
446  QCompleter* completer = new QCompleter(list, line);
447  completer->setCaseSensitivity(Qt::CaseInsensitive);
448  line->setCompleter(completer);
449  return line;
450 }