FreeDebks  1.0.3
 All Classes Files Functions Variables Friends Pages
FdSubWindow.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 "FdSubWindow.hpp"
21 
22 #include "FdMainWindow.hpp"
23 #include "FdDialogPrintOptions.hpp"
24 #include "../data/FdModelCoa.hpp"
25 #include "../data/FdModelJournal.hpp"
26 #include "../data/FdModelResults.hpp"
27 #include "widgets/FdViewCoa.hpp"
28 #include "widgets/FdViewJournal.hpp"
29 #include "widgets/FdViewResults.hpp"
30 #include "widgets/FdViewAccountSummary.hpp"
31 #include "../data/FdItemCoa.hpp"
32 
36 FdSubWindow::FdSubWindow(QString label,
37  QString currency,
38  QDate initialDate,
39  QDate finalDate,
40  QString corporation,
41  QString logo,
42  QString accountant) :
43  QMdiSubWindow(0),
44  mCurrency(currency),
45  mInitialDate(initialDate),
46  mFinalDate(finalDate),
47  mCorporation(corporation),
48  mLogo(logo),
49  mAccountant(accountant)
50 {
51  mFile = new QFile();
52 
53  setLabel(label);
54 
55  // Creates empty models
56  mJournal = 0;
57  mCoa = new FdModelCoa(this);
58  mJournal = new FdModelJournal(this);
59  mResults = new FdModelResults(this);
60 
61  init();
62 }
63 
67 FdSubWindow::FdSubWindow(QFile* file) : QMdiSubWindow(0), mFile(file)
68 {
69  // Parses data
70  QDomDocument document("freedebks");
71  mFile->open(QIODevice::ReadOnly | QIODevice::Text);
72  document.setContent(mFile);
73  mFile->close();
74 
75  QDomElement accounting = document.namedItem("Accounting").toElement();
76  setLabel(accounting.attribute("Label"));
77  mCurrency = accounting.attribute("Currency");
78  mInitialDate = QDate().fromString(accounting.attribute("InitialDate"), "yyyy.MM.dd");
79  mFinalDate = QDate().fromString(accounting.attribute("FinalDate"), "yyyy.MM.dd");
80  mCorporation = accounting.attribute("Corporation");
81  mLogo = accounting.attribute("Logo");
82  mAccountant = accounting.attribute("Accountant");
83 
84  QDomElement coa = accounting.namedItem("Coa").toElement();
85  QDomElement journal = accounting.namedItem("Journal").toElement();
86  QDomElement results = accounting.namedItem("Results").toElement();
87 
88  // Creates and populates model with file data
89  mCoa = new FdModelCoa(this, coa);
90  mJournal = new FdModelJournal(this, journal);
91  mResults = new FdModelResults(this, results);
92 
93  init();
94 }
95 
101 FdSubWindow::FdSubWindow(const FdSubWindow* previousYear) : QMdiSubWindow(0)
102 {
103  mFile = new QFile();
104 
105  setLabel(previousYear->label());
106  mCurrency = previousYear->currency();
107  QDate initial = previousYear->initialDate();
108  mInitialDate = QDate(initial.year()+1, initial.month(), initial.day());
109  QDate final = previousYear->finalDate();
110  mFinalDate = QDate(final.year()+1, final.month(), final.day());
111  mLogo = previousYear->logo();
112  mCorporation = previousYear->corporation();
113  mAccountant = previousYear->accountant();
114 
116  mCoa = new FdModelCoa(this, previousYear->coa());
117  mJournal = new FdModelJournal(this);
118  mResults = new FdModelResults(this, previousYear->results());
119 
120  init();
121 }
122 
123 void FdSubWindow::init()
124 {
126  mViewCoa = new FdViewCoa(this);
127  mViewJournal = new FdViewJournal(this);
128  mViewResults = new FdViewResults(this);
129  mViewCoa->setProperty("TabRole", TabRole(CoaRole));
130  mViewJournal->setProperty("TabRole", TabRole(JournalRole));
131  mViewResults->setProperty("TabRole", TabRole(ResultsRole));
132 
133  mViewCoa->expandAll();
134 
135  mTab = new QTabWidget;
136  mTab->setTabsClosable(true);
137  connect(mTab, SIGNAL(tabCloseRequested(int)), this, SLOT(closeTab(int)));
138  mTab->addTab(mViewCoa, tr("Chart of accounts", "Tab title."));
139  mTab->addTab(mViewJournal,tr("Journal", "Tab title."));
140  mTab->addTab(mViewResults,tr("Results", "Tab title."));
141  setWidget(mTab);
142 
143  connect(this, SIGNAL(aboutToActivate()), this, SLOT(newActiveTab()));
144  connect(mTab, SIGNAL(currentChanged(int)), this, SLOT(newActiveTab()));
145 
146  recomputeAll();
147 }
148 
150 {
151  return mCoa;
152 }
153 
155 {
156  return mJournal;
157 }
158 
160 {
161  return mResults;
162 }
163 
164 void FdSubWindow::setLabel(QString label)
165 {
166  mLabel = label;
167  setWindowTitle(mLabel+"[*]");
168 }
169 
170 void FdSubWindow::setCurrency(QString currency)
171 {
172  mCurrency = currency;
173 }
174 
175 void FdSubWindow::setInitialDate(QDate date)
176 {
177  mInitialDate = date;
178 }
179 
180 void FdSubWindow::setFinalDate(QDate date)
181 {
182  mFinalDate = date;
183 }
184 
185 void FdSubWindow::setCorporation(QString corporation)
186 {
188 }
189 
190 void FdSubWindow::setLogo(QString logo)
191 {
192  mLogo = logo;
193 }
194 
195 void FdSubWindow::setAccountant(QString accountant)
196 {
198 }
199 
200 QString FdSubWindow::label() const
201 {
202  return mLabel;
203 }
204 
205 QString FdSubWindow::currency() const
206 {
207  return mCurrency;
208 }
209 
210 QDate FdSubWindow::initialDate() const
211 {
212  return mInitialDate;
213 }
214 
215 QDate FdSubWindow::finalDate() const
216 {
217  return mFinalDate;
218 }
219 
220 QString FdSubWindow::corporation() const
221 {
222  return mCorporation;
223 }
224 
225 QString FdSubWindow::logo() const
226 {
227  return mLogo;
228 }
229 
230 QString FdSubWindow::accountant() const
231 {
232  return mAccountant;
233 }
234 
235 void FdSubWindow::save()
236 {
237  if(mFile->fileName() == "")
238  mainWindow->on_actionSaveAs_triggered();
239  else
240  {
241  QDomDocument document("freedebks");
242 
243  QDomElement accounting = document.createElement("Accounting");
244  accounting.setAttribute("Label", mLabel);
245  accounting.setAttribute("Currency", mCurrency);
246  accounting.setAttribute("InitialDate", mInitialDate.toString("yyyy.MM.dd"));
247  accounting.setAttribute("FinalDate", mFinalDate.toString("yyyy.MM.dd"));
248  accounting.setAttribute("Corporation", mCorporation);
249  accounting.setAttribute("Logo", mLogo);
250  accounting.setAttribute("Accountant", mAccountant);
251  document.appendChild(accounting);
252 
253  QDomElement coa = mCoa->toXml(document);
254  accounting.appendChild(coa);
255 
256  QDomElement journal = mJournal->toXml(document);
257  accounting.appendChild(journal);
258 
259  QDomElement results = mResults->toXml(document);
260  accounting.appendChild(results);
261 
262  mFile->open(QIODevice::WriteOnly | QIODevice::Text);
263  QTextStream stream(mFile);
264  document.save(stream, 4);
265  mFile->close();
266  }
267 
268  // Changes window title and clean state
269  setWindowModified(false);
270  mainWindow->enableSaveAction(false);
271 }
272 
273 void FdSubWindow::saveAs(QString file)
274 {
275  mFile->setFileName(file);
276  save();
277 }
278 
279 void FdSubWindow::print()
280 {
281  QPrinter printer(QPrinter::HighResolution);
282  QPrintDialog dialog(&printer, this);
283  dialog.setOption(QAbstractPrintDialog::PrintPageRange, false);
284 
285  if(dialog.exec() == QDialog::Accepted)
286  {
287  recomputeAll();
288  FdDialogPrintOptions options(this, mCoa);
289  if(options.exec() == QDialog::Accepted)
290  {
291  QStringList elements = options.selectedElements();
292  QPainter painter;
293 
294  printer.setPageMargins(10,10,10,10, QPrinter::Millimeter);
295 
296  if((elements[PrintJournal].toInt() || elements[PrintAccounts].toInt()) && !elements[PrintCoa].toInt() && !elements[PrintResults].toInt())
297  printer.setOrientation(QPrinter::Landscape);
298  else
299  printer.setOrientation(QPrinter::Portrait);
300 
301  painter.begin(&printer);
302 
303  QRect area = FdSubWindow::setPrintArea(printer);
304  QRect remainingArea;
305 
306  int pageNumber = 0;
307 
308  // Prints COA
309  if(elements[PrintCoa].toInt())
310  pageNumber = mViewCoa->print(printer, painter, area, remainingArea);
311 
312  // Prints Results
313  if(elements[PrintResults].toInt())
314  mViewResults->print(printer, painter, area, remainingArea, this, pageNumber);
315 
316  if((elements[PrintCoa].toInt() || elements[PrintResults].toInt()) && (elements[PrintJournal].toInt() || elements[PrintAccounts].toInt()))
317  {
318  printer.setOrientation(QPrinter::Landscape);
319  printer.newPage();
320  area = FdSubWindow::setPrintArea(printer);
321  }
322 
323  // Prints Journal
324  if(elements[PrintJournal].toInt())
325  mViewJournal->print(printer, painter, area);
326 
327  // Prints accounts summary
328  if(elements[PrintAccounts].toInt())
329  {
330  pageNumber = 0;
331  remainingArea = area;
332  if(elements[PrintCoa].toInt() || elements[PrintResults].toInt() || elements[PrintResults].toInt())
333  printer.newPage();
334 
335  FdSubWindow::printTitle(painter, remainingArea, tr("Accounts summaries", "Accounts summaries title on printed page."));
336 
337  FdViewAccountSummary* accountView;
338  FdItemCoa_p account;
339  for(int i = 4; i < elements.size(); ++i)
340  {
341  account = mCoa->itemById(elements[i]);
342 
343  if(mJournal->isUsed(account))
344  {
345  accountView = new FdViewAccountSummary(this, account);
346  pageNumber = accountView->print(printer, painter, area, remainingArea, this, pageNumber);
347  accountView->deleteLater();
348  }
349  }
350  }
351 
352  painter.end();
353  }
354 
355  }
356 }
357 
358 QRect FdSubWindow::setPrintArea(QPrinter &printer)
359 {
360  int x = printer.pageRect().x();
361  int y = printer.pageRect().y();
362  int width = printer.pageRect().width()-2*x;
363  int height = printer.pageRect().height()-2*y;
364  return QRect(x, y+700, width, height-700);
365 }
366 
367 void FdSubWindow::printHeaderFooter(QPrinter &printer, QPainter &painter, QString document, int page) const
368 {
369  int rowHeight = 200;
370 
371  int x = printer.pageRect().x();
372  int y = printer.pageRect().y();
373  int width = printer.pageRect().width()-2*x;
374  int height = printer.pageRect().height()-2*y;
375  QRect header(x, y-300, width, 600);
376  QRect footer(x, y+height+200, width, 200);
377  QRect rect;
378 
379  // Defines font
380  QFont textFont = painter.font();
381  textFont.setPointSize(10);
382  textFont.setBold(true);
383  painter.setFont(textFont);
384  painter.setPen(Qt::black);
385 
386  // Prints header
387  int logoWidth = 0;
388  if(!mLogo.isEmpty())
389  {
390  QImage logo;
391  logo.load(mLogo);
392  if(logo.isNull())
393  logo.load(QFileInfo(*mFile).path()+"/"+mLogo);
394 
395  if(!logo.isNull())
396  {
397  logo = logo.scaledToHeight(header.height(), Qt::SmoothTransformation);
398  logoWidth = logo.size().width();
399  rect.setRect(header.right()-logoWidth, header.y(), logoWidth, header.height());
400  painter.drawImage(rect, logo);
401  }
402  }
403 
404  rect.setRect(header.x(), header.y(), header.width()-logoWidth-100, rowHeight);
405  painter.drawText(rect, Qt::AlignRight, mCorporation);
406  rect.setRect(header.x(), header.y()+rowHeight, header.width()-logoWidth-100, rowHeight);
407  painter.drawText(rect, Qt::AlignRight, mLabel);
408  rect.setRect(header.x(), header.y()+2*rowHeight, header.width()-logoWidth-100, rowHeight);
409  painter.drawText(rect, Qt::AlignRight, mAccountant);
410 
411  textFont.setBold(false);
412  painter.setFont(textFont);
413  // Prints footer
414  painter.drawText(footer, Qt::AlignLeft, document);
415  painter.drawText(footer, Qt::AlignRight, QString::number(page));
416 
417 // painter.drawRect(header);
418 // painter.drawRect(footer);
419 }
420 
424 void FdSubWindow::printTitle(QPainter &painter, QRect& area, QString title)
425 {
426  QFont font = painter.font();
427  font.setPointSize(24);
428 
429  int x = area.x();
430  int y = area.y();
431  painter.setFont(font);
432  painter.setPen(Qt::black);
433  painter.drawText(QRect(x, y, area.width(), area.height()), Qt::AlignLeft, title);
434 
435  area.setRect(x, y+800, area.width(), area.height()-800);
436 }
437 
441 void FdSubWindow::printSubtitle(QPainter &painter, QRect& area, QString subtitle)
442 {
443  QFont font = painter.font();
444  font.setPointSize(16);
445 
446  int x = area.x();
447  int y = area.y();
448  painter.setFont(font);
449  painter.setPen(Qt::black);
450  painter.drawText(QRect(x, y, area.width(), area.height()), Qt::AlignLeft, subtitle);
451 
452  // This value must also be changed in FdViewAccountSummary::print, variable neededHeight.
453  area.setRect(x, y+350, area.width(), area.height()-350);
454 }
455 
456 void FdSubWindow::printColumnsHeader(QPainter &painter, QRect& area, QList<tableElement*> elements)
457 {
458  int x = area.x();
459  int y = area.y();
460  int rowHeight = 185;
461 
462  QFont font = painter.font();
463  font.setPointSize(10);
464  font.setBold(true);
465  painter.setFont(font);
466 
467  QRect rect(x, y, area.width(), rowHeight);
468  painter.fillRect(rect, QColor(Qt::lightGray));
469 
470  for(int i = 0; i < elements.size(); ++i)
471  {
472  rect.setRect(x, y, elements[i]->width, rowHeight);
473  painter.drawText(rect, elements[i]->alignement, elements[i]->text);
474  x += elements[i]->width;
475  }
476 
477  area.setRect(area.x(), area.y()+rowHeight, area.width(), area.height()-rowHeight);
478 }
479 
480 void FdSubWindow::printTableRow(QPainter &painter, QRect& area, QList<tableElement*> elements)
481 {
482  int x = area.x();
483  int y = area.y();
484  int rowHeight = 185;
485 
486  QFont font = painter.font();
487  font.setPointSize(10);
488  font.setBold(false);
489  painter.setFont(font);
490 
491  painter.setPen(Qt::black);
492  painter.drawLine(x, y+rowHeight, x+area.width(), y+rowHeight);
493 
494  QRect rect;
495  for(int i = 0; i < elements.size(); ++i)
496  {
497  rect.setRect(x, y, elements[i]->width, rowHeight);
498  painter.setPen(elements[i]->color);
499  painter.drawText(rect, elements[i]->alignement, elements[i]->text);
500  x += elements[i]->width;
501  }
502 
503  area.setRect(area.x(), area.y()+rowHeight, area.width(), area.height()-rowHeight);
504  if(area.height() < rowHeight)
505  area.setHeight(0);
506 }
507 
511 void FdSubWindow::closeEvent(QCloseEvent* event)
512 {
513  if(isWindowModified())
514  {
515  int ret = QMessageBox::question(this,
516  tr("%1 has been modified.", "Text displayed in a message box when trying to close an unsaved subwindow. The argument is a subwindow title, ie a bookkeeping label.").arg(mLabel),
517  tr("Do you want to save your changes ?"),
518  QMessageBox::Save | QMessageBox::Discard | QMessageBox::Cancel,
519  QMessageBox::Save);
520  switch(ret)
521  {
522  // Save
523  case 2048:
524  save();
525  closeEvent(event);
526  break;
527  // Discard
528  case 8388608:
529  setWindowModified(false);
530  closeEvent(event);
531  break;
532  // Cancel
533  case 4194304:
534  event->ignore();
535  break;
536  }
537  }
538  else
539  {
543  deleteLater();
544  mainWindow->subwindowAboutToClose();
546  }
547 }
548 
553 {
554  TabRole role = getCurrentTabRole();
555  if(role == CoaRole)
556  mViewCoa->edit(mCoa->addItem(mViewCoa->currentIndex()));
557  else if(role == JournalRole)
558  {
559  mViewJournal->setCurrentIndex(mJournal->addEntry(mViewJournal->currentIndex()));
561  }
562  else if(role == ResultsRole)
564 }
565 
567 {
568  TabRole role = getCurrentTabRole();
569  switch(role)
570  {
571  case CoaRole:
573  break;
574  case JournalRole:
576  break;
577  case ResultsRole:
579  break;
580  default:
581  break;
582  }
583 }
584 
585 void FdSubWindow::copy()
586 {
587  TabRole role = getCurrentTabRole();
588  QString text;
589 
590  switch(role)
591  {
592  case CoaRole:
593  text = mCoa->data(mViewCoa->currentIndex()).toString();
594  break;
595  case JournalRole:
596  text = mJournal->data(mViewCoa->currentIndex()).toString();
597  break;
598  case ResultsRole:
599  text = mResults->data(mViewResults->currentIndex()).toString();
600  break;
601  case AccountRole:
602  FdViewAccountSummary* view = qobject_cast<FdViewAccountSummary*>(mTab->currentWidget());
603  text = view->model()->data(view->currentIndex()).toString();
604  break;
605  }
606 
607  QApplication::clipboard()->setText(text);
608 }
609 
611 {
612  TabRole role = getCurrentTabRole();
613 
614  switch(role)
615  {
616  case CoaRole:
618  break;
619  case JournalRole:
621  break;
622  case ResultsRole:
624  break;
625  case AccountRole:
626  FdViewAccountSummary* view = qobject_cast<FdViewAccountSummary*>(mTab->currentWidget());
627  view->nextSearchResult();
628  break;
629  }
630 }
631 
633 {
634  FdItemCoa_p account;
635  TabRole role = getCurrentTabRole();
636  switch(role)
637  {
638  case CoaRole:
639  account = mCoa->item(mViewCoa->currentIndex());
640  break;
641  case JournalRole:
642  account = mJournal->selectedAccount(mViewJournal->currentIndex());
643  break;
644  case AccountRole:
645  FdViewAccountSummary* view = qobject_cast<FdViewAccountSummary*>(mTab->currentWidget());
646  account = view->currentCounterpart();
647  break;
648  }
649  FdViewAccountSummary* tab = new FdViewAccountSummary(this, account);
650  mTab->addTab(tab, QString(account->displayLabel()));
651  mTab->setCurrentIndex(mTab->indexOf(tab));
652 }
653 
655 {
656  if(getCurrentTabRole() == AccountRole)
657  {
658  FdItemJournal_p entry = qobject_cast<FdViewAccountSummary*>(mTab->currentWidget())->currentEntry();
659  mTab->setCurrentIndex(1);
660  mViewJournal->setCurrentIndex((mJournal->itemIndex(entry)));
661  }
662 }
663 
665 {
666  mainWindow->setDockText("<b>"+mCorporation+"<br />"+
667  mLabel+"<\b>");
668 }
669 
671 {
672  mJournal->orderByDate();
673  mCoa->orderItems();
676 }
677 
682 {
683  mJournal->orderByDate();
684 }
685 
692 {
693  QModelIndex selected = mViewJournal->currentIndex();
694  if(selected.isValid())
695  {
696  mJournal->copyFromPreviousLine(selected);
698  }
699  else
700  {
701  mJournal->addEntry();
702  selected = mJournal->index(mViewJournal->currentIndex().row(), JournalLabel);
703  mViewJournal->setCurrentIndex(selected);
704  mJournal->copyFromPreviousLine(mViewJournal->currentIndex());
705  }
706 }
707 
711 TabRole FdSubWindow::getCurrentTabRole() const
712 {
714  QWidget* tab = mTab->widget(mTab->currentIndex());
715  return TabRole(tab->property("TabRole").toInt());
716 }
717 
724 {
725  QAction* undo;
726  QAction* redo;
727  TabRole role = getCurrentTabRole();
728  switch(role)
729  {
730  case CoaRole:
731  redo = mCoa->redo();
732  undo = mCoa->undo();
734  mViewCoa->currentChanged(mViewCoa->currentIndex(), QModelIndex());
735  break;
736  case JournalRole:
737  redo = mJournal->redo();
738  undo = mJournal->undo();
739  mViewJournal->currentChanged(mViewJournal->currentIndex(), QModelIndex());
741  break;
742  case ResultsRole:
743  redo = mResults->redo();
744  undo = mResults->undo();
746  mViewResults->currentChanged(mViewResults->currentIndex(), QModelIndex());
747  break;
748  case AccountRole:
749  qobject_cast<FdViewAccountSummary*>(mTab->currentWidget())->refreshView();
750  qobject_cast<FdViewAccountSummary*>(mTab->currentWidget())->currentChanged();
751  qobject_cast<FdViewAccountSummary*>(mTab->currentWidget())->setDockText();
752  redo = new QAction(0);
753  undo = new QAction(0);
754  redo->setDisabled(true);
755  undo->setDisabled(true);
756  mainWindow->enableRemoveAction(false);
757  mainWindow->enableShowAccountAction(false);
758  }
759 
760  mainWindow->activeTabChanged(role, undo, redo, isWindowModified());
761 }
762 
766 void FdSubWindow::closeTab(int index)
767 {
768  TabRole role = TabRole(mTab->widget(index)->property("TabRole").toInt());
769  switch(role)
770  {
771  case AccountRole:
772  qobject_cast<FdViewAccountSummary*>(mTab->widget(index))->writeSettings();
773  mTab->widget(index)->deleteLater();
774  mTab->removeTab(index);
775  break;
776  default:
777  break;
778  }
779 }
780 
784 void FdSubWindow::cleanStateChanged(bool clean)
785 {
786  if(!isWindowModified() && !clean)
787  {
788  setWindowModified(true);
789  mainWindow->enableSaveAction(true);
790  }
791 }
792