FreeDebks  1.0.3
 All Classes Files Functions Variables Friends Pages
FdViewCoa.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 "FdViewCoa.hpp"
21 #include "../FdMainWindow.hpp"
22 #include "../FdSubWindow.hpp"
23 #include "../../data/FdModelCoa.hpp"
24 #include "../../data/FdItemCoa.hpp"
25 
27  QTreeView(0), mSubwindow(parent)
28 {
29  mModel = mSubwindow->coa();
30  setModel(mModel);
31 
32  setSelectionBehavior(QAbstractItemView::SelectRows);
33  setSelectionMode(QAbstractItemView::ExtendedSelection);
34  setDragDropMode(QAbstractItemView::InternalMove);
35  setDragEnabled(true);
36  setAcceptDrops(true);
37  setDropIndicatorShown(true);
38  setAlternatingRowColors(true);
39 
40  QSettings settings;
41  settings.beginGroup("ViewCoa");
42  setColumnWidth(CoaId, settings.value("id", 100).toInt());
43  setColumnWidth(CoaLabel, settings.value("label", 500).toInt());
44  setColumnWidth(CoaBalanceSheet, settings.value("balanceSheet", 110).toInt());
45  setColumnWidth(CoaSigns, settings.value("signs", 40).toInt());
46  setColumnWidth(CoaInitial, settings.value("initial", 90).toInt());
47  settings.endGroup();
48  header()->setResizeMode(CoaBalance, QHeaderView::Stretch);
49  header()->setDefaultAlignment(Qt::AlignCenter);
50 
51  mDelegate = new FdDelegateCoa(mModel);
52  setItemDelegate(mDelegate);
53 
54  setContextMenuPolicy(Qt::CustomContextMenu);
55  connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(contextMenu(const QPoint&)));
56 
57  mSearchTimer = new QTimer();
58  mSearchTimer->setInterval(qApp->keyboardInputInterval());
59  mSearchTimer->setSingleShot(true);
60  connect(mSearchTimer, SIGNAL(timeout()), this, SLOT(searchTimeout()));
61 }
62 
66 void FdViewCoa::mouseReleaseEvent(QMouseEvent* event)
67 {
68  if (event->button() == Qt::LeftButton && !(indexAt(event->pos()).isValid()))
69  setCurrentIndex(QModelIndex());
70 
72 }
73 
77 QModelIndex FdViewCoa::moveCursor(CursorAction cursorAction, Qt::KeyboardModifiers modifiers)
78 {
79  QModelIndex index = currentIndex();
80  if(index.isValid())
81  {
82  FdItemCoa_p item;
83  if(cursorAction == QAbstractItemView::MoveNext)
84  {
85  item = mModel->item(index);
86 
87  if(index.column() == CoaLabel && item->type() == AccountType)
88  return model()->index(index.row(), index.column()+2, index.parent());
89  else if(index.column() == CoaLabel && item->type() == CategoryType) {}
90  else if(index.column() != CoaInitial)
91  return model()->index(index.row(), index.column()+1, index.parent());
92 
93  return model()->index(index.row(), CoaId, index.parent());
94  }
95  else if(cursorAction == QAbstractItemView::MovePrevious)
96  {
97  item = mModel->item(index);
98 
99  if(index.column() == CoaSigns)
100  return model()->index(index.row(), index.column()-2, index.parent());
101  else if(index.column() != CoaId)
102  return model()->index(index.row(), index.column()-1, index.parent());
103 
104  if(item->type() == AccountType)
105  return model()->index(index.row(), CoaInitial, index.parent());
106  else if(item->type() == CategoryType)
107  return model()->index(index.row(), CoaLabel, index.parent());
108  }
109  else if(cursorAction == QAbstractItemView::MovePageUp)
110  {
111  item = mModel->item(index);
112  if(item->parent()->type() != RootType)
113  return mModel->index(item->parent());
114  else
115  return index;
116  }
117  else if(cursorAction == QAbstractItemView::MovePageDown)
118  {
119  item = mModel->item(index);
120  if(item->childrenCount())
121  return mModel->index(item->child(0));
122  else
123  return index;
124  }
125  }
126 
127  return QTreeView::moveCursor(cursorAction, modifiers);
128 }
129 
135 void FdViewCoa::keyboardSearch(const QString &search)
136 {
137  mSearchTimer->start();
138  mSearchText.append(search);
139  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));
140 }
141 
142 int FdViewCoa::print(QPrinter &printer, QPainter &painter, const QRect &area, QRect& remainingArea)
143 {
144  QFont font = painter.font();
145  // This controls accounts font size
146  font.setPointSize(12);
147  int rowHeight = 250;
148 
149  int pageNumber = print(printer,
150  painter,
151  area,
152  remainingArea,
153  font,
154  rowHeight,
155  200,
156  0.6*area.width(),
157  0.2*area.width(),
158  mModel->getRootItem());
159 
160 
161  remainingArea.setRect(area.x(), remainingArea.y()+2*rowHeight, area.width(), remainingArea.height()-2*rowHeight);
162  return pageNumber;
163 }
164 
165 int FdViewCoa::print(QPrinter &printer, QPainter &painter, const QRect &area, QRect &remainingArea, QFont font, int rowHeight, int tabulation, int widthLabel, int widthAmount, FdItemCoa_p parent, int pageNumber, int level)
166 {
167  QRect rect;
168  FdItemCoa_p item;
169  int x;
170  int rows;
171  QString text;
172 
173  for(int i = 0; i < parent->childrenCount(); ++i)
174  {
175  item = parent->child(i);
176  rows = item->childrenCount();
177  x = 0;
178 
179  if((pageNumber || level) && rows*rowHeight > remainingArea.height() && rows*rowHeight < area.height())
180  remainingArea.setHeight(0);
181 
182  if(remainingArea.height() < rowHeight)
183  {
184  remainingArea = area;
185 
186  if(pageNumber)
187  printer.newPage();
188  else
189  FdSubWindow::printTitle(painter, remainingArea, tr("Chart of accounts", "Chart of accounts printed page title."));
190 
191 // painter.drawRect(area);
192 
193  ++pageNumber;
194  mSubwindow->printHeaderFooter(printer, painter, tr("Chart of accounts", "Chart of accounts printed pages footer."), pageNumber);
195 
196  x += remainingArea.x()+widthLabel;
197  rect.setRect(x, remainingArea.y(), widthAmount, rowHeight);
198  painter.drawText(rect, Qt::AlignRight, tr("Previous year", "Chart of accounts printed pages column header."));
199  x += widthAmount;
200  rect.setRect(x, remainingArea.y(), widthAmount, rowHeight);
201  painter.drawText(rect, Qt::AlignRight, tr("Current year", "Chart of accounts printed pages column header."));
202 
203  remainingArea.setRect(remainingArea.x(), remainingArea.y()+rowHeight, remainingArea.width(), remainingArea.height()-rowHeight);
204  }
205 
206  if(item->type() == CategoryType)
207  {
208  remainingArea.setRect(remainingArea.x(), remainingArea.y()+rowHeight, remainingArea.width(), remainingArea.height()-rowHeight);
209  font.setBold(true);
210  }
211  else
212  font.setBold(false);
213 
214  painter.setFont(font);
215 
216  x = remainingArea.x()+level*tabulation;
217  rect.setRect(x, remainingArea.y(), widthLabel, rowHeight);
218  text = item->displayLabel();
219  painter.drawText(rect, Qt::AlignLeft, text);
220 
221  x -= level*tabulation;
222  x += widthLabel;
223  rect.setRect(x, remainingArea.y(), widthAmount, rowHeight);
224  if(item->onBalanceSheet())
225  {
226  if(item->initialBalance() < 0)
227  painter.setPen(Qt::red);
228 
229  text = mDelegate->displayText(item->initialBalance());
230  painter.drawText(rect, Qt::AlignRight, text);
231  }
232  else if(item->previousBalance())
233  {
234  if(item->previousBalance() < 0)
235  painter.setPen(Qt::red);
236 
237  text = mDelegate->displayText(item->previousBalance());
238  painter.drawText(rect, Qt::AlignRight, text);
239  }
240  painter.setPen(Qt::black);
241 
242  x += widthAmount;
243  rect.setRect(x, remainingArea.y(), widthAmount, rowHeight);
244  if(item->balance() < 0)
245  painter.setPen(Qt::red);
246  text = mDelegate->displayText(item->balance());
247  painter.drawText(rect, Qt::AlignRight, text);
248  painter.setPen(Qt::black);
249 
250  remainingArea.setRect(remainingArea.x(), remainingArea.y()+rowHeight, remainingArea.width(), remainingArea.height()-rowHeight);
251 
252  if(item->children().size())
253  pageNumber = print(printer,
254  painter,
255  area,
256  remainingArea,
257  font,
258  rowHeight,
259  tabulation,
260  widthLabel,
261  widthAmount,
262  item,
263  pageNumber,
264  level+1);
265  }
266  return pageNumber;
267 }
268 
272 QModelIndexList FdViewCoa::selectedItems() const
273 {
274  QModelIndexList selected = selectedIndexes();
275  QModelIndexList indexes;
276  for(int i = 0; i < selected.size(); ++i)
277  {
278  if(selected[i].column() == 0)
279  indexes << selected[i];
280  }
281 
282  for(int i = 0; i < indexes.size(); ++i)
283  {
284  QModelIndex index = indexes[i];
285  while(index.parent() != QModelIndex())
286  {
287  if(indexes.contains(index.parent()))
288  {
289  indexes.removeAt(i);
290  --i;
291  break;
292  }
293  index = index.parent();
294  }
295  }
296 
297  return indexes;
298 }
299 
301 {
302  QSettings settings;
303  settings.beginGroup("ViewCoa");
304  settings.setValue("id", columnWidth(CoaId));
305  settings.setValue("label", columnWidth(CoaLabel));
306  settings.setValue("balanceSheet", columnWidth(CoaBalanceSheet));
307  settings.setValue("signs", columnWidth(CoaSigns));
308  settings.setValue("initial", columnWidth(CoaInitial));
309  settings.endGroup();
310 }
311 
312 void FdViewCoa::edit(const QModelIndex &index)
313 {
314  setCurrentIndex(index);
315  QTreeView::edit(index);
316 }
317 
318 void FdViewCoa::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
319 {
320  if(!state())
321  setCurrentIndex(bottomRight);
322  QTreeView::dataChanged(topLeft, bottomRight);
323 }
324 
328 void FdViewCoa::setCurrentIndex(const QModelIndex &index)
329 {
330  clearSelection();
332 }
333 
334 void FdViewCoa::currentChanged(const QModelIndex &current, const QModelIndex &previous)
335 {
336  mainWindow->enableRemoveAction(mModel->isRemovable(current));
337 
338  if(mModel->item(current)->type() == AccountType)
339  mainWindow->enableShowAccountAction(true);
340  else
341  mainWindow->enableShowAccountAction(false);
342 
343  QTreeView::currentChanged(current, previous);
344 }
345 
346 void FdViewCoa::contextMenu(const QPoint &position)
347 {
348  QModelIndex index = currentIndex();
349  QMenu* menu = new QMenu();
350 
351  if(index.isValid())
352  {
353  menu->addActions(mainWindow->getContextMenuActionsEdit());
354  menu->addSeparator();
355  }
356  menu->addActions(mainWindow->getContextMenuActionsCoa());
357  menu->exec(mapToGlobal(position));
358 }
359 
365 {
367  if(mSearchResults.size())
368  {
369  mCurrentResult = -1;
371  }
372  else
373  mainWindow->setDockText(tr("Sorry, no matches found.", "No matches found when searching item by text."));
374 
375  mSearchText = QString();
376 }
377 
379 {
380  if(mSearchResults.size())
381  {
382  if(mCurrentResult < mSearchResults.size() - 1)
383  {
384  ++ mCurrentResult;
386  }
387  else
388  {
389  mCurrentResult = -1;
391  }
392  }
393  else
394  mainWindow->setDockText(tr("Sorry, no matches found.", "No matches found when searching item by text."));
395 }
396 
397 FdDelegateCoa::FdDelegateCoa(FdModelCoa *model) : QStyledItemDelegate(0), mModel(model)
398 {
399 }
400 
401 QString FdDelegateCoa::displayText(const QVariant &value) const
402 {
403  return displayText(value, QLocale::system());
404 }
405 
409 QString FdDelegateCoa::displayText(const QVariant &value, const QLocale &locale) const
410 {
411  if(value.type() == QVariant::Double)
412  return QLocale::system().toString(value.toDouble(), 'f', 2);
413 // QString balance = value.toString();
414 // QRegExp decimal("[.]");
415 // QRegExp one_decimal("[.]\\d$");
416 // if(!balance.contains(decimal))
417 // balance.append(".00");
418 // else if(balance.contains(one_decimal))
419 // balance.append("0");
420 
421 // return balance;
422 
423  return QStyledItemDelegate::displayText(value, locale);
424 }
425 
429 void FdDelegateCoa::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
430 {
431  QStyleOptionViewItem viewOption(option);
432  FdItemCoa_p item = mModel->item(index);
433 
434  if(item->type() == CategoryType)
435  viewOption.font.setBold(true);
436 
437  if((index.column() == CoaInitial && item->initialBalance() < 0) || (index.column() == CoaBalance && item->balance() < 0))
438  viewOption.palette.setColor(QPalette::Text, Qt::red);
439 
440  QStyledItemDelegate::paint(painter, viewOption, index);
441 }
442 
446 QWidget* FdDelegateCoa::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const
447 {
448  if(index.column() == CoaSigns)
449  {
450  QComboBox* box = new QComboBox(parent);
451  box->addItem("+-", PlusMinus);
452  box->addItem("-+", MinusPlus);
453  QVariant value = mModel->item(index)->signature();
454  box->setCurrentIndex(box->findData(value));
455  return box;
456  }
457 
458  return QStyledItemDelegate::createEditor(parent, option, index);
459 }
460 
464 void FdDelegateCoa::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const
465 {
466  if(index.column() == CoaSigns)
467  {
468  QComboBox* box = static_cast<QComboBox*>(editor);
469  QVariant value = box->itemData(box->currentIndex());
470  model->setData(index, value, Qt::EditRole);
471  }
472  else
473  QStyledItemDelegate::setModelData(editor, model, index);
474 }