Fri, 28 Nov 2008 14:20:00 +0100
Added tag ASGUI_0.7.7 for changeset d64aaa7d146f
1 //
2 // OSSP asgui - Accounting system graphical user interface
3 // Copyright (c) 2002-2004 The OSSP Project (http://www.ossp.org/)
4 // Copyright (c) 2002-2004 Ralf S. Engelschall <rse@engelschall.com>
5 // Copyright (c) 2002-2004 Michael Schloh von Bennewitz <michael@schloh.com>
6 // Copyright (c) 2002-2004 Cable & Wireless Telecommunications Services GmbH
7 //
8 // This file is part of OSSP asgui, an accounting system graphical user
9 // interface which can be found at http://www.ossp.org/pkg/tool/asgui/.
10 //
11 // Permission to use, copy, modify, and distribute this software for
12 // any purpose with or without fee is hereby granted, provided that
13 // the above copyright notice and this permission notice appear in all
14 // copies.
15 //
16 // THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
17 // WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 // IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
20 // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 // USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24 // ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
25 // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
26 // OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 // SUCH DAMAGE.
28 //
29 // as_reportpanel.cpp: ISO C++ implementation
30 //
32 #include <qvariant.h>
33 #include <qpushbutton.h>
34 #include <qtextedit.h>
35 #include <qtoolbutton.h>
36 #include <qbuttongroup.h>
37 #include <qpopupmenu.h>
38 #include <qlayout.h>
39 #include <qtooltip.h>
40 #include <qwhatsthis.h>
41 #include <qtextstream.h>
42 #include <qfiledialog.h>
43 #include <qprinter.h>
44 #include <qpaintdevicemetrics.h>
45 #include <qpainter.h>
46 #include <qfile.h>
47 #include <qdir.h>
49 #include "as_reportpanel.h"
50 #include "as_numdial.h"
51 #include "as_table.h"
52 #include "as_pref.h"
53 #include "as_generic.h"
54 #include "as_const.h"
55 #include "as_except.h"
57 // Version information
58 #define _AS_VERSION_CPP_AS_HEADER_
59 #include "as_version.cpp"
60 #undef _AS_VERSION_CPP_AS_HEADER_
63 namespace AS {
65 //
66 // Constructs a Reportpanel as a child of 'pParent', with the
67 // name 'kszName' and widget flags set to 'Flags'.
68 //
69 // The dialog will by default be modal, unless you set 'bModal' to
70 // false to construct a modeless dialog.
71 //
72 Reportpanel::Reportpanel(TiTable *pTable, Preferences *pPreferences,
73 QWidget *pParent, const char *kszName,
74 bool bModal, WFlags Flags)
75 : QDialog(pParent, kszName, bModal, Flags)
76 {
77 // Boilerplate code to initialize the panel
78 if (!kszName)
79 this->setName("Reportpanel");
81 // Make panel resizeable
82 this->setSizeGripEnabled(true);
83 this->setSizePolicy(QSizePolicy((QSizePolicy::SizeType)5,
84 (QSizePolicy::SizeType)5, 0, 0, this->sizePolicy().hasHeightForWidth()));
86 // Store matrix and prefs members
87 m_pReptable = pTable;
88 m_pReprefs = pPreferences;
89 m_pPrinter = new QPrinter;
91 // Preset number of weeks and months to report
92 m_nWeeks = m_pReprefs->getNumber(TITRAQ_PREFREPORTWEEKS, TITRAQ_DEFREPORTWEEKS);
93 m_nMonths = m_pReprefs->getNumber(TITRAQ_PREFREPORTMONTHS, TITRAQ_DEFREPORTMONTHS);
95 // Build panel using already constructed widgets and layouts
96 m_pFormlay = new QVBoxLayout(this, 11, 6, "Formlayout");
97 m_pToolay = new QHBoxLayout(0, 0, 6, "Toolbuttonlay");
98 m_pPushlay = new QHBoxLayout(0, 0, 6, "Pushbuttonlay");
100 // Groupbox and its text display
101 m_pBrowser = new QTextEdit(this, "Reportbrowser");
102 m_pBrowser->setTextFormat(PlainText);
103 m_pBrowser->setReadOnly(true);
104 m_pBrowser->setFont(QFont("Courier", 10));
105 m_pFormlay->addWidget(m_pBrowser);
106 m_pFormlay->addSpacing(6);
107 m_pFormlay->addLayout(m_pToolay);
108 m_pFormlay->addSpacing(6);
109 m_pFormlay->addLayout(m_pPushlay);
111 // Tool button suite
112 m_pWeekmonthgroup = new QButtonGroup(this, "Weekmonthgroup");
113 m_pWeekmonthgroup->setColumnLayout(0, Qt::Horizontal);
114 m_pWeekmonthgroup->layout()->setSpacing(11);
115 m_pWeekmonthgroup->layout()->setMargin(0);
116 m_pWeekmonthlay = new QHBoxLayout(m_pWeekmonthgroup->layout());
117 m_pWeekmonthgroup->setFrameShape(QFrame::NoFrame);
118 m_pWeekmonthgroup->setExclusive(true);
119 m_pWeeklybutt = new QToolButton(m_pWeekmonthgroup, "Weeklybutton");
120 // m_pWeeklybutt->setPaletteBackgroundColor(QColor(198, 196, 186));
121 m_pWeeklybutt->setFocusPolicy(QWidget::TabFocus);
122 m_pWeeklybutt->setCursor(QCursor(13));
123 m_pWeeklybutt->setToggleButton(true);
124 m_pMonthlybutt = new QToolButton(m_pWeekmonthgroup, "Monthlybutton");
125 // m_pMonthlybutt->setPaletteBackgroundColor(QColor(198, 196, 186));
126 m_pMonthlybutt->setFocusPolicy(QWidget::TabFocus);
127 m_pMonthlybutt->setCursor(QCursor(13));
128 m_pMonthlybutt->setToggleButton(true);
130 // Popup for number of weeks
131 m_pWeekpop = new QPopupMenu(this);
132 if (m_pWeekpop == NULL) // Sanity check
133 throw Genexcept("Weekly toolbutton popup creation failed.");
134 m_pWeekpop->insertItem(trUtf8("One week"), this, SLOT(reportWeeks(int)));
135 m_pWeekpop->insertItem(trUtf8("Two weeks"), this, SLOT(reportWeeks(int)));
136 m_pWeekpop->insertItem(trUtf8("Three weeks"), this, SLOT(reportWeeks(int)));
137 m_pWeekpop->insertItem(trUtf8("Four weeks"), this, SLOT(reportWeeks(int)));
138 m_pWeekpop->insertItem(trUtf8("N... weeks"), this, SLOT(reportWeeks(int)));
139 m_pWeekpop->setCheckable(true);
140 m_pWeeklybutt->setPopup(m_pWeekpop);
141 m_pWeeklybutt->setPopupDelay(TITRAQ_POPUPMSECS);
143 { // Initialize check button correctly
144 int nPosition = (m_nWeeks < m_pWeekpop->count()) ? m_nWeeks : m_pWeekpop->count();
145 m_pWeekpop->setItemChecked(m_pWeekpop->idAt(--nPosition), true);
146 }
148 // Popup for number of months
149 m_pMonthpop = new QPopupMenu(this);
150 if (m_pMonthpop == NULL) // Sanity check
151 throw Genexcept("Monthly toolbutton popup creation failed.");
152 m_pMonthpop->insertItem(trUtf8("One month"), this, SLOT(reportMonths(int)));
153 m_pMonthpop->insertItem(trUtf8("Two months"), this, SLOT(reportMonths(int)));
154 m_pMonthpop->insertItem(trUtf8("Three months"), this, SLOT(reportMonths(int)));
155 m_pMonthpop->insertItem(trUtf8("Four months"), this, SLOT(reportMonths(int)));
156 m_pMonthpop->insertItem(trUtf8("N... months"), this, SLOT(reportMonths(int)));
157 m_pMonthpop->setCheckable(true);
158 m_pMonthlybutt->setPopup(m_pMonthpop);
159 m_pMonthlybutt->setPopupDelay(TITRAQ_POPUPMSECS);
161 { // Initialize check button correctly
162 int nPosition = (m_nMonths < m_pMonthpop->count()) ? m_nMonths : m_pMonthpop->count();
163 m_pMonthpop->setItemChecked(m_pMonthpop->idAt(--nPosition), true);
164 }
166 // Add our tool buttons
167 m_pWeekmonthlay->addWidget(m_pWeeklybutt);
168 m_pWeekmonthlay->addWidget(m_pMonthlybutt);
169 m_pToolay->addWidget(m_pWeekmonthgroup);
171 // Push button suite
172 m_pSavebutt = new QPushButton(this, "Savebutton");
173 m_pSavebutt->setPaletteBackgroundColor(QColor(202, 194, 182));
174 m_pSavebutt->setCursor(QCursor(13));
175 m_pPrintbutt = new QPushButton(this, "Printbutton");
176 m_pPrintbutt->setPaletteBackgroundColor(QColor(198, 196, 186));
177 m_pPrintbutt->setCursor(QCursor(13));
178 #ifdef QT_NO_PRINTER
179 m_pPrintbutt->setEnabled(false);
180 #endif
181 m_pDismissbutt = new QPushButton(this, "Dismissbutton");
182 m_pDismissbutt->setPaletteBackgroundColor(QColor(198, 196, 186));
183 m_pDismissbutt->setCursor(QCursor(13));
184 m_pDismissbutt->setDefault(true);
185 m_pPushlay->addWidget(m_pSavebutt);
186 m_pPushlay->addWidget(m_pPrintbutt);
187 m_pPushlay->addWidget(m_pDismissbutt);
189 // Connect signals to slots, accept() and reject() are Qt implicit
190 connect(m_pWeeklybutt, SIGNAL(clicked(void)), SLOT(reportWeeks(void)));
191 connect(m_pMonthlybutt, SIGNAL(clicked(void)), SLOT(reportMonths(void)));
192 connect(m_pSavebutt, SIGNAL(clicked(void)), SLOT(saveReport(void)));
193 connect(m_pPrintbutt, SIGNAL(clicked(void)), SLOT(printReport(void)));
194 connect(m_pDismissbutt, SIGNAL(clicked(void)), SLOT(accept(void)));
195 this->resize(QSize(464, 332).expandedTo(minimumSizeHint()));
196 this->textChange();
197 }
199 //
200 // Overload QDialog::exec(), and generate a report before executing modally
201 //
202 int Reportpanel::exec(void)
203 {
204 int nRet = 0;
205 int nPeriod = m_pReprefs->getNumber(TITRAQ_PREFREPORTYPE, TITRAQ_DEFREPORTYPE);
207 switch (nPeriod) {
208 case TITRAQ_REPORTWEEK:
209 this->reportWeeks(1);
210 m_pWeekmonthgroup->setButton(TITRAQ_REPORTWEEK);
211 break;
212 case TITRAQ_REPORTMONTH:
213 this->reportMonths(1);
214 m_pWeekmonthgroup->setButton(TITRAQ_REPORTMONTH);
215 break;
216 default:
217 throw Genexcept("Reportpanel: Modal event loop entered with no report period.");
218 break;
219 }
221 nRet = QDialog::exec(); // Blast off
223 // Before losing scope, the preferred report period
224 m_pReprefs->setNumber(TITRAQ_PREFREPORTYPE,
225 m_pWeekmonthgroup->id(m_pWeekmonthgroup->selected()));
226 m_pReprefs->setNumber(TITRAQ_PREFREPORTWEEKS, m_nWeeks);
227 m_pReprefs->setNumber(TITRAQ_PREFREPORTMONTHS, m_nMonths);
228 return nRet;
229 }
231 //
232 // Makes a new weekly report of so many weeks
233 //
234 void Reportpanel::reportWeeks(int nMenuid)
235 {
236 // Range of weeks to report
237 int nFirstweek, nLastweek;
239 // Menu index, first item is always 0
240 int nIndex = m_pWeekpop->indexOf(nMenuid); // Corresponds to weeks
241 int nLastid = 0; // Last menu id selected
243 if (m_nWeeks < m_pWeekpop->count())
244 nLastid = m_pWeekpop->idAt(m_nWeeks - 1); // Probably not last item
245 else
246 nLastid = m_pWeekpop->idAt(m_pWeekpop->count() - 1); // Last item selected
248 // Set the button in case from a menu selection
249 m_pWeekmonthgroup->setButton(TITRAQ_REPORTWEEK);
251 // Update m_nWeeks only if user prefers a different number
252 if (nIndex >= 0) {
253 // User selected N... to indicate an arbitrary number
254 if (nIndex == m_pWeekpop->count() - 1) {
255 Numdial Weeksinput;
256 Weeksinput.setNum(m_nWeeks);
257 if (Weeksinput.exec() == QDialog::Accepted) {
258 m_nWeeks = Weeksinput.getNum();
259 m_pWeekpop->setItemChecked(nLastid, false);
260 m_pWeekpop->setItemChecked(nMenuid, true);
261 }
262 else
263 return;
264 }
265 else { // User selected a preset menu item such as '2 weeks'
266 m_nWeeks = nIndex + 1;
267 m_pWeekpop->setItemChecked(nLastid, false);
268 m_pWeekpop->setItemChecked(nMenuid, true);
269 }
270 }
272 // Clear data window
273 m_pBrowser->setUpdatesEnabled(false);
274 m_pBrowser->clear();
276 // Determine first and last week numbers, then write header
277 nLastweek = QDate::currentDate().weekNumber();
278 if (m_nWeeks > 1) {
279 nFirstweek = QDate::currentDate().addDays(m_nWeeks * -7).weekNumber() + 1;
280 this->writeHeader(nFirstweek, nLastweek);
281 }
282 else
283 this->writeHeader(nLastweek);
285 // Write new contents to data window
286 m_pBrowser->append(this->getWeektotals(QDate::currentDate(), m_nWeeks));
287 if (m_pReprefs->getBool(TITRAQ_PREFDETAILON, TITRAQ_DEFDETAILON))
288 m_pBrowser->append(this->getWeekdetails(QDate::currentDate(), m_nWeeks));
289 this->writeFooter();
290 m_pBrowser->setCursorPosition(0, 0);
291 m_pBrowser->ensureCursorVisible();
292 m_pBrowser->setUpdatesEnabled(true);
293 m_pBrowser->repaint(false);
294 }
296 //
297 // Makes a new monthly report of so many months
298 //
299 void Reportpanel::reportMonths(int nMenuid)
300 {
301 // Range of months to report
302 QString Firstmonth, Lastmonth;
304 // Menu index, first item is always 0
305 int nIndex = m_pMonthpop->indexOf(nMenuid); // Corresponds to months
306 int nLastid = 0; // Last menu id selected
308 if (m_nMonths < m_pMonthpop->count())
309 nLastid = m_pMonthpop->idAt(m_nMonths - 1); // Probably not last item
310 else
311 nLastid = m_pMonthpop->idAt(m_pMonthpop->count() - 1); // Last item selected
313 // Set the button in case from a menu selection
314 m_pWeekmonthgroup->setButton(TITRAQ_REPORTMONTH);
316 // Update m_nMonths only if user prefers a different number
317 if (nIndex >= 0) {
318 // User selected N... to indicate an arbitrary number
319 if (nIndex == m_pMonthpop->count() - 1) {
320 Numdial Monthsinput;
321 Monthsinput.setNum(m_nMonths);
322 if (Monthsinput.exec() == QDialog::Accepted) {
323 m_nMonths = Monthsinput.getNum();
324 m_pMonthpop->setItemChecked(nLastid, false);
325 m_pMonthpop->setItemChecked(nMenuid, true);
326 }
327 else
328 return;
329 }
330 else { // User selected a preset menu item such as '2 months'
331 m_nMonths = nIndex + 1;
332 m_pMonthpop->setItemChecked(nLastid, false);
333 m_pMonthpop->setItemChecked(nMenuid, true);
334 }
335 }
337 // Clear data window
338 m_pBrowser->setUpdatesEnabled(false);
339 m_pBrowser->clear();
341 // Determine first and last month names, then write header
342 Lastmonth = QDate::longMonthName(QDate::currentDate().month());
343 if (m_nMonths > 1) {
344 int nMonth = (QDate::currentDate().addMonths(m_nMonths * -1).month() + 12) % 12 + 1;
345 Firstmonth = QDate::longMonthName(nMonth);
346 this->writeHeader(Firstmonth, Lastmonth);
347 }
348 else
349 this->writeHeader(Lastmonth);
351 // Write new contents to data window
352 m_pBrowser->append(this->getMonthtotals(QDate::currentDate(), m_nMonths));
353 if (m_pReprefs->getBool(TITRAQ_PREFDETAILON, TITRAQ_DEFDETAILON)) {
354 m_pBrowser->append(this->getMonthdetails(QDate::currentDate(), m_nMonths));
355 }
356 this->writeFooter();
357 m_pBrowser->setCursorPosition(0, 0);
358 m_pBrowser->ensureCursorVisible();
359 m_pBrowser->setUpdatesEnabled(true);
360 m_pBrowser->repaint(false);
361 }
363 //
364 // Writes a report header to the display window
365 //
366 void Reportpanel::writeHeader(int nWeeknum)
367 {
368 QString Header;
369 Header = QString("Accounting System ");
370 Header += QString(asgui_version.v_short);
371 Header += trUtf8("\nLocal report, username '");
372 Header += m_pReprefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER);
373 Header += QString("'\n");
374 Header += trUtf8("Date ");
375 Header += QDate::currentDate().toString(Qt::ISODate);
376 Header += trUtf8(", Time ");
377 Header += QTime::currentTime().toString(Qt::ISODate);
378 Header += trUtf8("\nReporting for week %1...").arg(nWeeknum);
379 Header += QString("\n\n");
380 m_pBrowser->setText(Header);
381 }
383 //
384 // Writes a report header to the display window
385 //
386 void Reportpanel::writeHeader(QString Month)
387 {
388 QString Header;
389 Header = QString("Accounting System ");
390 Header += QString(asgui_version.v_short);
391 Header += trUtf8("\nLocal report, username '");
392 Header += m_pReprefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER);
393 Header += QString("'\n");
394 Header += trUtf8("Date ");
395 Header += QDate::currentDate().toString(Qt::ISODate);
396 Header += trUtf8(", Time ");
397 Header += QTime::currentTime().toString(Qt::ISODate);
398 Header += trUtf8("\nReporting for month %1...").arg(Month);
399 Header += QString("\n\n");
400 m_pBrowser->setText(Header);
401 }
403 //
404 // Writes a report header to the display window
405 //
406 void Reportpanel::writeHeader(int nFirst, int nLast)
407 {
408 QString Header;
409 Header = QString("Accounting System ");
410 Header += QString(asgui_version.v_short);
411 Header += trUtf8("\nLocal report, username '");
412 Header += m_pReprefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER);
413 Header += QString("'\n");
414 Header += trUtf8("Date ");
415 Header += QDate::currentDate().toString(Qt::ISODate);
416 Header += trUtf8(", Time ");
417 Header += QTime::currentTime().toString(Qt::ISODate);
418 Header += trUtf8("\nReporting for weeks %1 through %2...").arg(nFirst).arg(nLast);
419 Header += QString("\n\n");
420 m_pBrowser->setText(Header);
421 }
423 //
424 // Writes a report header to the display window
425 //
426 void Reportpanel::writeHeader(QString First, QString Last)
427 {
428 QString Header;
429 Header = QString("Accounting System ");
430 Header += QString(asgui_version.v_short);
431 Header += trUtf8("\nLocal report, username '");
432 Header += m_pReprefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER);
433 Header += QString("'\n");
434 Header += trUtf8("Date ");
435 Header += QDate::currentDate().toString(Qt::ISODate);
436 Header += trUtf8(", Time ");
437 Header += QTime::currentTime().toString(Qt::ISODate);
438 Header += trUtf8("\nReporting months %1 through %2...").arg(First).arg(Last);
439 Header += QString("\n\n");
440 m_pBrowser->setText(Header);
441 }
443 //
444 // Writes a report footer to the display window
445 //
446 void Reportpanel::writeFooter(void)
447 {
448 if (m_pReprefs->getBool(TITRAQ_PREFSIGNATON, TITRAQ_DEFSIGNATON)) {
449 m_pBrowser->append(trUtf8("\n\nPrint name ________________________________________\n"));
450 m_pBrowser->append(trUtf8("\n\nSignature ________________________________________"));
451 }
452 }
454 //
455 // Returns one week of details data
456 //
457 QString Reportpanel::getWeekdetails(QDate Dayref, int nWeeks)
458 {
459 QString Data; // Output string
460 QString Tempstring; // Temp churning
461 int nRows = m_pReptable->numRows();
463 // Find range boundaries
464 Q_ASSERT(nWeeks > 0);
465 QDate Tempdate;
466 QDate Firstday;
467 QDate Lastday;
468 Firstday = Dayref.addDays(Dayref.dayOfWeek() * -1 + 1);
469 Firstday = Firstday.addDays((nWeeks - 1) * -7);
470 Lastday = Firstday.addDays(7 * nWeeks);
472 // Write some quick header text to the outgoing string
473 Data = trUtf8("\nDate Hours Account details\n");
474 Data += QString("---------- ----- ----------------------------------------\n");
476 // Build the long week data string
477 for (int nIter = nRows - 1; nIter >= 0; nIter--) {
478 // Work on this tuple only if it within the reporting range
479 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK);
480 Tempdate = QDate::fromString(m_pReptable->text(nIter, TITRAQ_IDXDATE), Qt::ISODate);
481 if (!Tempstring.isEmpty() && Firstday <= Tempdate && Tempdate < Lastday) {
482 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXDATE);
483 if (!Tempstring.isEmpty())
484 Data += Tempstring;
485 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXAMOUNT);
486 if (!Tempstring.isEmpty())
487 Data += QString(TITRAQ_SEPARATORTOK) + Tempstring;
488 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK);
489 if (!Tempstring.isEmpty())
490 Data += QString(TITRAQ_SEPARATORTOK) + Tempstring;
491 Data += QString("\n"); // Finish off line
492 }
493 }
495 return Data;
496 }
498 //
499 // Returns one week of totals data
500 //
501 QString Reportpanel::getWeektotals(QDate Dayref, int nWeeks)
502 {
503 using namespace std; // Needed for maps and hash
504 map<string, string> Hashtasks; // Hashtable to store tasks
505 multimap<string, string> Hashhours; // Hashtable to store hours
506 map<string, string>::iterator Taskiter; // Hashtable task iterator
507 multimap<string, string>::iterator Houriter; // Hashtable hour iterator
509 QString Totals; // Data totals to return for writing
510 QString Tempstring; // Temporary processing string
511 QDate Tempdate; // Temporary processing date
512 int nRows = m_pReptable->numRows();
514 // Find range boundaries
515 Q_ASSERT(nWeeks > 0);
516 QDate Firstday;
517 QDate Lastday;
518 Firstday = Dayref.addDays(Dayref.dayOfWeek() * -1 + 1);
519 Firstday = Firstday.addDays((nWeeks - 1) * -7);
520 Lastday = Firstday.addDays(7 * nWeeks);
522 // Parse the table for interesting values
523 for (int nIter = 0; nIter < nRows; nIter++) {
524 // Work on this tuple only if it within the reporting range
525 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK);
526 Tempdate = QDate::fromString(m_pReptable->text(nIter, TITRAQ_IDXDATE), Qt::ISODate);
527 if (!Tempstring.isEmpty() && Firstday <= Tempdate && Tempdate < Lastday) {
528 string Convstring = Tempstring; // Convert to string (can't cast?)
529 QTime Intable = QTime::fromString(m_pReptable->text(nIter, TITRAQ_IDXAMOUNT), Qt::ISODate);
530 int nTothours = QString(Hashtasks[Convstring]).section(':', 0, 0).toInt() + Intable.hour();
531 int nTotminut = QString(Hashtasks[Convstring]).section(':', 1, 1).toInt() + Intable.minute();
532 nTothours += nTotminut / 60;
533 nTotminut %= 60;
534 QString Hours = QString::number(nTothours).rightJustify(3, ' ');
535 QString Mins = QString::number(nTotminut).rightJustify(2, '0');
536 string Timestring = Hours + ':' + Mins; // Convert to string (can't cast?)
537 Hashtasks[Convstring] = Timestring; // Finally store in hashtable
538 }
539 }
541 // Reverse copy the tasks hashtable to both sort and index by amount key
542 for (Taskiter = Hashtasks.begin(); Taskiter != Hashtasks.end(); Taskiter++)
543 Hashhours.insert(pair<string, string>(Taskiter->second, Taskiter->first));
545 // Write the actual data totals to the outgoing string in reverse order
546 for (Houriter = Hashhours.begin(); Houriter != Hashhours.end(); Houriter++)
547 Totals = Houriter->first + ' ' + Houriter->second + '\n' + Totals;
549 // Write some quick header text to the outgoing string in reverse order
550 Totals = QString("------ ----------------------------------------\n") + Totals;
551 Totals = trUtf8("Total Account summary\n") + Totals;
553 return Totals; // The outgoing string... its finally gone, let's go to bed
554 }
556 //
557 // Returns one month of details data
558 //
559 QString Reportpanel::getMonthdetails(QDate Dayref, int nMonths)
560 {
561 QString Data; // Output string
562 QString Tempstring; // Temp churning
563 QDate Tempdate; // For comparing
564 QDate Firstday; // Minimum boundary
565 QDate Lastday; // Maximum boundary
566 int nRows = m_pReptable->numRows();
568 // Find range boundaries
569 Q_ASSERT(nMonths > 0);
570 int nYear = Dayref.year();
571 int nMonth = (Dayref.addMonths(nMonths * -1).month() + 12) % 12 + 1;
572 if (nMonth > Dayref.month())
573 nYear--;
574 Firstday = QDate(nYear, nMonth, 1);
575 Lastday = QDate(Dayref.year(), Dayref.month(), Dayref.daysInMonth());
577 // Write some quick header text to the outgoing string
578 Data = trUtf8("\nDate Hours Account details\n");
579 Data += QString("---------- ----- ----------------------------------------\n");
581 // Build the long week data string
582 for (int nIter = nRows - 1; nIter >= 0; nIter--) {
583 // Work on this tuple only if it within the reporting range
584 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK);
585 Tempdate = QDate::fromString(m_pReptable->text(nIter, TITRAQ_IDXDATE), Qt::ISODate);
586 if (!Tempstring.isEmpty() && Firstday <= Tempdate && Tempdate < Lastday) {
587 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXDATE);
588 if (!Tempstring.isEmpty())
589 Data += Tempstring;
590 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXAMOUNT);
591 if (!Tempstring.isEmpty())
592 Data += QString(TITRAQ_SEPARATORTOK) + Tempstring;
593 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK);
594 if (!Tempstring.isEmpty())
595 Data += QString(TITRAQ_SEPARATORTOK) + Tempstring;
596 Data += trUtf8("\n"); // Finish off line
597 }
598 }
600 return Data;
601 }
603 //
604 // Returns one month of totals data
605 //
606 QString Reportpanel::getMonthtotals(QDate Dayref, int nMonths)
607 {
608 using namespace std; // Needed for maps and hash
609 map<string, string> Hashtasks; // Hashtable to store tasks
610 multimap<string, string> Hashhours; // Hashtable to store hours
611 map<string, string>::iterator Taskiter; // Hashtable task iterator
612 multimap<string, string>::iterator Houriter; // Hashtable hour iterator
614 QString Totals; // Data totals to return for writing
615 QString Tempstring; // Temporary processing string
616 QDate Tempdate; // Temporary processing date
617 int nRows = m_pReptable->numRows();
619 // Find range boundaries
620 Q_ASSERT(nMonths > 0);
621 int nYear = Dayref.year();
622 int nMonth = (Dayref.addMonths(nMonths * -1).month() + 12) % 12 + 1;
623 if (nMonth > Dayref.month())
624 nYear--;
625 QDate Firstday = QDate(nYear, nMonth, 1);
626 QDate Lastday = QDate(Dayref.year(), Dayref.month(), Dayref.daysInMonth());
628 // Parse the table for interesting values
629 for (int nIter = 0; nIter < nRows; nIter++) {
630 // Work on this tuple only if it within the reporting range
631 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK);
632 Tempdate = QDate::fromString(m_pReptable->text(nIter, TITRAQ_IDXDATE), Qt::ISODate);
633 if (!Tempstring.isEmpty() && Firstday <= Tempdate && Tempdate < Lastday) {
634 string Convstring = Tempstring; // Convert to string (can't cast?)
635 QTime Intable = QTime::fromString(m_pReptable->text(nIter, TITRAQ_IDXAMOUNT), Qt::ISODate);
636 int nTothours = QString(Hashtasks[Convstring]).section(':', 0, 0).toInt() + Intable.hour();
637 int nTotminut = QString(Hashtasks[Convstring]).section(':', 1, 1).toInt() + Intable.minute();
638 nTothours += nTotminut / 60;
639 nTotminut %= 60;
640 QString Hours = QString::number(nTothours).rightJustify(3, ' ');
641 QString Mins = QString::number(nTotminut).rightJustify(2, '0');
642 string Timestring = Hours + ':' + Mins; // Convert to string (can't cast?)
643 Hashtasks[Convstring] = Timestring; // Finally store in hashtable
644 }
645 }
647 // Reverse copy the tasks hashtable to both sort and index by amount key
648 for (Taskiter = Hashtasks.begin(); Taskiter != Hashtasks.end(); Taskiter++)
649 Hashhours.insert(pair<string, string>(Taskiter->second, Taskiter->first));
651 // Write the actual data totals to the outgoing string in reverse order
652 for (Houriter = Hashhours.begin(); Houriter != Hashhours.end(); Houriter++)
653 Totals = Houriter->first + ' ' + Houriter->second + '\n' + Totals;
655 // Write some quick header text to the outgoing string in reverse order
656 Totals = QString("------ ----------------------------------------\n") + Totals;
657 Totals = trUtf8("Total Account summary\n") + Totals;
659 return Totals; // The outgoing string... its finally gone, let's go to bed
660 }
662 //
663 // Saves the currently displayed local report
664 //
665 void Reportpanel::saveReport(void)
666 {
667 int nResult = 0; // For checking user's answer
668 QFile Report; // The resulting report file
669 QString Filestring; // The user chosen file name to save
670 QString Openas = m_pReprefs->getString(TITRAQ_PREFHOME, TITRAQ_DEFHOME);
672 // And then get the name of the selected file to save to
673 Filestring = QFileDialog::getSaveFileName(Openas, trUtf8("Text files (*.txt);;All Files (*)"), this, trUtf8("ChooserDialog"), trUtf8("Choose a file to save"), NULL, false);
674 if (!Filestring.isEmpty()) {
675 if (QFile::exists(Filestring)) {
676 nResult = QMessageBox::warning(this, QString(TITRAQ_APPTITLE)
677 + ' ' + asgui_version.v_short, trUtf8(TITRAQ_OVERWRITE),
678 trUtf8("&Yes"), trUtf8("&No"), NULL, 1, 1);
679 if (nResult = QMessageBox::Ok) { // Overwrite a file
680 Report.setName(Filestring); // User wished name
681 Report.open(IO_WriteOnly | IO_Truncate); // Open report file
682 QTextStream Outstream(&Report); // Convert to stream
683 Outstream << m_pBrowser->text(); // Write the data
684 Report.close(); // Finish by closing
685 }
686 }
687 else { // User gave a file name, and there was no preexisting file there
688 Report.setName(Filestring); // User wished name
689 Report.open(IO_WriteOnly | IO_Truncate); // Open report file
690 QTextStream Outstream(&Report); // Convert to stream
691 Outstream << m_pBrowser->text(); // Write the data
692 Report.close(); // Finish by closing
693 }
694 }
695 // Otherwise, user did not select a valid file and push okay button
696 }
698 //
699 // Prints the currently displayed local report
700 //
701 void Reportpanel::printReport(void)
702 {
703 #ifndef QT_NO_PRINTER
704 if (m_pPrinter->setup(this)) { // Opens printer dialog
705 m_pPrinter->setFullPage(true); // Set our own margins
706 QPainter Paint; // Our painter (for pages)
707 Paint.begin(m_pPrinter); // Paint on printer
708 Paint.setFont(m_pBrowser->font());
709 QFontMetrics Fontmetrics = Paint.fontMetrics();
710 QPaintDeviceMetrics Devmetrics(m_pPrinter); // Need width/height of printer surface
711 const int knMargin = Devmetrics.logicalDpiX() / 2; // Half-inch margin
712 int nYpos = knMargin; // Y position for each line
713 int nPageno = 1; // The starting page number
715 for (int nIter = 0; nIter < m_pBrowser->lines() && !m_pPrinter->aborted(); nIter++) {
716 // See if there is some space on this page to paint on
717 if (nYpos + Fontmetrics.lineSpacing() > Devmetrics.height() - knMargin) {
718 // QString Printmsg(trUtf8("Printing page "))
719 // + QString::number(++nPageno) + QString("...");
720 // m_pStatus()->message(Printmsg); // Not in scope (crap)
721 if (!m_pPrinter->newPage()) // Start new page
722 break; // Some error
723 nYpos = knMargin; // Back to top of page
724 }
725 Paint.drawText(knMargin, nYpos, Devmetrics.width() - 2 * knMargin,
726 Fontmetrics.lineSpacing(), Qt::ExpandTabs, m_pBrowser->text(nIter));
727 nYpos += Fontmetrics.lineSpacing();
728 }
729 Paint.end(); // Send job to printer
730 // m_pStatus()->message(trUtf8("Printing completed"), 2000); // Not in scope
731 }
732 // m_pStatusBar()->message(trUtf8("Printing completed"), 2000); // Not in scope
733 #endif
734 }
736 //
737 // Sets the strings of the subwidgets using the current language
738 //
739 void Reportpanel::textChange(void)
740 {
741 this->setCaption(trUtf8("AS local report", "Local report using weekly or monthly data."));
743 // Top level push buttons associated with accept and save slots
744 m_pSavebutt->setText(trUtf8("Save As...", "Comment for Savebutton"));
745 QToolTip::add(m_pSavebutt, trUtf8("Saves the report text", "Comment for tooltip Savebutton"));
746 QWhatsThis::add(m_pSavebutt, trUtf8("The save button saves the report text to a file", "Comment for whatsThis Savebutton"));
747 m_pPrintbutt->setText(trUtf8("Print...", "Comment for Printbutton"));
748 QToolTip::add(m_pPrintbutt, trUtf8("Print the report text", "Comment for tooltip Printbutton"));
749 QWhatsThis::add(m_pPrintbutt, trUtf8("The print button prints the report text to a file", "Comment for whatsThis Printbutton"));
750 m_pDismissbutt->setText(trUtf8("Dismiss", "Comment for Dismissbutton"));
751 QToolTip::add(m_pDismissbutt, trUtf8("Closes the report panel", "Comment for tooltip Dismissbutton"));
752 QWhatsThis::add(m_pDismissbutt, trUtf8("The dismiss button dismisses the report panel", "Comment for whatsThis Dismissbutton"));
754 // Inner tool buttons for new local report generation
755 m_pWeeklybutt->setText(trUtf8("Weekly", "Comment for Weeklybutt"));
756 QToolTip::add(m_pWeeklybutt, trUtf8("Hold down for options", "Comment for tooltip Weeklybutt"));
757 QWhatsThis::add(m_pWeeklybutt, trUtf8("The Weekly button generates a new weekly report.\nHold this button down to specify many weeks.", "Comment for whatsThis Weeklybutt"));
758 m_pMonthlybutt->setText(trUtf8("Monthly", "Comment for Monthlybutt"));
759 QToolTip::add(m_pMonthlybutt, trUtf8("Hold down for options", "Comment for tooltip Monthlybutt"));
760 QWhatsThis::add(m_pMonthlybutt, trUtf8("The Monthly button makes a new monthly report.\nHold this button down to specify how many months.", "Comment for whatsThis Monthlybutt"));
761 }
762 } // namespace AS