Thu, 06 Aug 2009 13:04:50 +0200
Correct cursor method signatures and explicitly require XML linkage.
1 //
2 // OSSP asgui - Accounting system graphical user interface
3 // Copyright (c) 2002-2009 The OSSP Project (http://www.ossp.org/)
4 // Copyright (c) 2002-2009 Ralf S. Engelschall <rse@engelschall.com>
5 // Copyright (c) 2002-2009 Michael Schloh von Bennewitz <michael@schloh.com>
6 // Copyright (c) 2002-2009 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://asgui.europalab.com/.
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 #define QT3_SUPPORT
34 #include <qvariant.h>
35 #include <qpushbutton.h>
36 #include <q3textedit.h>
37 #include <qtoolbutton.h>
38 #include <q3buttongroup.h>
39 #include <q3popupmenu.h>
40 #include <qlayout.h>
41 #include <qtooltip.h>
42 #include <q3whatsthis.h>
43 #include <q3textstream.h>
44 #include <q3filedialog.h>
45 #include <qprinter.h>
46 #include <q3paintdevicemetrics.h>
47 #include <qpainter.h>
48 #include <qfile.h>
49 #include <qdir.h>
51 //Added by qt3to4:
52 #include <Q3HBoxLayout>
53 #include <Q3Frame>
54 #include <Q3VBoxLayout>
56 #include "as_reportpanel.h"
57 #include "as_numdial.h"
58 #include "as_table.h"
59 #include "as_pref.h"
60 #include "as_generic.h"
61 #include "as_const.h"
62 #include "as_except.h"
64 // Version information
65 #define _AS_VERSION_CPP_AS_HEADER_
66 #include "as_version.cpp"
67 #undef _AS_VERSION_CPP_AS_HEADER_
70 namespace AS {
72 //
73 // Constructs a Reportpanel as a child of 'pParent', with the
74 // name 'kszName' and widget flags set to 'Flags'.
75 //
76 // The dialog will by default be modal, unless you set 'bModal' to
77 // false to construct a modeless dialog.
78 //
79 Reportpanel::Reportpanel(TiTable *pTable, Preferences *pPreferences,
80 QWidget *pParent, const char *kszName,
81 bool bModal, Qt::WFlags Flags)
82 : QDialog(pParent, kszName, bModal, Flags)
83 {
84 // Boilerplate code to initialize the panel
85 if (!kszName)
86 this->setName("Reportpanel");
88 // Make panel resizeable
89 this->setSizeGripEnabled(true);
90 this->setSizePolicy(QSizePolicy((QSizePolicy::SizeType)5,
91 (QSizePolicy::SizeType)5, 0, 0, this->sizePolicy().hasHeightForWidth()));
93 // Store matrix and prefs members
94 m_pReptable = pTable;
95 m_pReprefs = pPreferences;
96 m_pPrinter = new QPrinter;
98 // Preset number of weeks and months to report
99 m_nWeeks = m_pReprefs->getNumber(TITRAQ_PREFREPORTWEEKS, TITRAQ_DEFREPORTWEEKS);
100 m_nMonths = m_pReprefs->getNumber(TITRAQ_PREFREPORTMONTHS, TITRAQ_DEFREPORTMONTHS);
102 // Build panel using already constructed widgets and layouts
103 m_pFormlay = new Q3VBoxLayout(this, 11, 6, "Formlayout");
104 m_pToolay = new Q3HBoxLayout(0, 0, 6, "Toolbuttonlay");
105 m_pPushlay = new Q3HBoxLayout(0, 0, 6, "Pushbuttonlay");
107 // Groupbox and its text display
108 m_pBrowser = new Q3TextEdit(this, "Reportbrowser");
109 m_pBrowser->setTextFormat(Qt::PlainText);
110 m_pBrowser->setReadOnly(true);
111 m_pBrowser->setFont(QFont("Courier", 10));
112 m_pFormlay->addWidget(m_pBrowser);
113 m_pFormlay->addSpacing(6);
114 m_pFormlay->addLayout(m_pToolay);
115 m_pFormlay->addSpacing(6);
116 m_pFormlay->addLayout(m_pPushlay);
118 // Tool button suite
119 m_pWeekmonthgroup = new Q3ButtonGroup(this, "Weekmonthgroup");
120 m_pWeekmonthgroup->setColumnLayout(0, Qt::Horizontal);
121 m_pWeekmonthgroup->layout()->setSpacing(11);
122 m_pWeekmonthgroup->layout()->setMargin(0);
123 m_pWeekmonthlay = new Q3HBoxLayout(m_pWeekmonthgroup->layout());
124 //m_pWeekmonthgroup->setFrameShape(QFrame::NoFrame);
125 m_pWeekmonthgroup->setExclusive(true);
126 m_pWeeklybutt = new QToolButton(m_pWeekmonthgroup, "Weeklybutton");
127 // m_pWeeklybutt->setPaletteBackgroundColor(QColor(198, 196, 186));
128 m_pWeeklybutt->setFocusPolicy(Qt::TabFocus);
129 m_pWeeklybutt->setCursor(QCursor(Qt::PointingHandCursor));
130 m_pWeeklybutt->setToggleButton(true);
131 m_pMonthlybutt = new QToolButton(m_pWeekmonthgroup, "Monthlybutton");
132 // m_pMonthlybutt->setPaletteBackgroundColor(QColor(198, 196, 186));
133 m_pMonthlybutt->setFocusPolicy(Qt::TabFocus);
134 m_pMonthlybutt->setCursor(QCursor(Qt::PointingHandCursor));
135 m_pMonthlybutt->setToggleButton(true);
137 // Popup for number of weeks
138 m_pWeekpop = new Q3PopupMenu(this);
139 if (m_pWeekpop == NULL) // Sanity check
140 throw Genexcept("Weekly toolbutton popup creation failed.");
141 m_pWeekpop->insertItem(trUtf8("One week"), this, SLOT(reportWeeks(int)));
142 m_pWeekpop->insertItem(trUtf8("Two weeks"), this, SLOT(reportWeeks(int)));
143 m_pWeekpop->insertItem(trUtf8("Three weeks"), this, SLOT(reportWeeks(int)));
144 m_pWeekpop->insertItem(trUtf8("Four weeks"), this, SLOT(reportWeeks(int)));
145 m_pWeekpop->insertItem(trUtf8("N... weeks"), this, SLOT(reportWeeks(int)));
146 m_pWeekpop->setCheckable(true);
147 m_pWeeklybutt->setPopup(m_pWeekpop);
148 m_pWeeklybutt->setPopupDelay(TITRAQ_POPUPMSECS);
150 { // Initialize check button correctly
151 int nPosition = (m_nWeeks < m_pWeekpop->count()) ? m_nWeeks : m_pWeekpop->count();
152 m_pWeekpop->setItemChecked(m_pWeekpop->idAt(--nPosition), true);
153 }
155 // Popup for number of months
156 m_pMonthpop = new Q3PopupMenu(this);
157 if (m_pMonthpop == NULL) // Sanity check
158 throw Genexcept("Monthly toolbutton popup creation failed.");
159 m_pMonthpop->insertItem(trUtf8("One month"), this, SLOT(reportMonths(int)));
160 m_pMonthpop->insertItem(trUtf8("Two months"), this, SLOT(reportMonths(int)));
161 m_pMonthpop->insertItem(trUtf8("Three months"), this, SLOT(reportMonths(int)));
162 m_pMonthpop->insertItem(trUtf8("Four months"), this, SLOT(reportMonths(int)));
163 m_pMonthpop->insertItem(trUtf8("N... months"), this, SLOT(reportMonths(int)));
164 m_pMonthpop->setCheckable(true);
165 m_pMonthlybutt->setPopup(m_pMonthpop);
166 m_pMonthlybutt->setPopupDelay(TITRAQ_POPUPMSECS);
168 { // Initialize check button correctly
169 int nPosition = (m_nMonths < m_pMonthpop->count()) ? m_nMonths : m_pMonthpop->count();
170 m_pMonthpop->setItemChecked(m_pMonthpop->idAt(--nPosition), true);
171 }
173 // Add our tool buttons
174 m_pWeekmonthlay->addWidget(m_pWeeklybutt);
175 m_pWeekmonthlay->addWidget(m_pMonthlybutt);
176 m_pToolay->addWidget(m_pWeekmonthgroup);
178 // Push button suite
179 m_pSavebutt = new QPushButton(this, "Savebutton");
180 m_pSavebutt->setPaletteBackgroundColor(QColor(202, 194, 182));
181 m_pSavebutt->setCursor(QCursor(Qt::PointingHandCursor));
182 m_pPrintbutt = new QPushButton(this, "Printbutton");
183 m_pPrintbutt->setPaletteBackgroundColor(QColor(198, 196, 186));
184 m_pPrintbutt->setCursor(QCursor(Qt::PointingHandCursor));
185 #ifdef QT_NO_PRINTER
186 m_pPrintbutt->setEnabled(false);
187 #endif
188 m_pDismissbutt = new QPushButton(this, "Dismissbutton");
189 m_pDismissbutt->setPaletteBackgroundColor(QColor(198, 196, 186));
190 m_pDismissbutt->setCursor(QCursor(Qt::PointingHandCursor));
191 m_pDismissbutt->setDefault(true);
192 m_pPushlay->addWidget(m_pSavebutt);
193 m_pPushlay->addWidget(m_pPrintbutt);
194 m_pPushlay->addWidget(m_pDismissbutt);
196 // Connect signals to slots, accept() and reject() are Qt implicit
197 connect(m_pWeeklybutt, SIGNAL(clicked(void)), SLOT(reportWeeks(void)));
198 connect(m_pMonthlybutt, SIGNAL(clicked(void)), SLOT(reportMonths(void)));
199 connect(m_pSavebutt, SIGNAL(clicked(void)), SLOT(saveReport(void)));
200 connect(m_pPrintbutt, SIGNAL(clicked(void)), SLOT(printReport(void)));
201 connect(m_pDismissbutt, SIGNAL(clicked(void)), SLOT(accept(void)));
202 this->resize(QSize(464, 332).expandedTo(minimumSizeHint()));
203 this->textChange();
204 }
206 //
207 // Overload QDialog::exec(), and generate a report before executing modally
208 //
209 int Reportpanel::exec(void)
210 {
211 int nRet = 0;
212 int nPeriod = m_pReprefs->getNumber(TITRAQ_PREFREPORTYPE, TITRAQ_DEFREPORTYPE);
214 switch (nPeriod) {
215 case TITRAQ_REPORTWEEK:
216 this->reportWeeks(1);
217 m_pWeekmonthgroup->setButton(TITRAQ_REPORTWEEK);
218 break;
219 case TITRAQ_REPORTMONTH:
220 this->reportMonths(1);
221 m_pWeekmonthgroup->setButton(TITRAQ_REPORTMONTH);
222 break;
223 default:
224 throw Genexcept("Reportpanel: Modal event loop entered with no report period.");
225 break;
226 }
228 nRet = QDialog::exec(); // Blast off
230 // Before losing scope, the preferred report period
231 m_pReprefs->setNumber(TITRAQ_PREFREPORTYPE,
232 m_pWeekmonthgroup->id(m_pWeekmonthgroup->selected()));
233 m_pReprefs->setNumber(TITRAQ_PREFREPORTWEEKS, m_nWeeks);
234 m_pReprefs->setNumber(TITRAQ_PREFREPORTMONTHS, m_nMonths);
235 return nRet;
236 }
238 //
239 // Makes a new weekly report of so many weeks
240 //
241 void Reportpanel::reportWeeks(int nMenuid)
242 {
243 // Range of weeks to report
244 int nFirstweek, nLastweek;
246 // Menu index, first item is always 0
247 int nIndex = m_pWeekpop->indexOf(nMenuid); // Corresponds to weeks
248 int nLastid = 0; // Last menu id selected
250 if (m_nWeeks < m_pWeekpop->count())
251 nLastid = m_pWeekpop->idAt(m_nWeeks - 1); // Probably not last item
252 else
253 nLastid = m_pWeekpop->idAt(m_pWeekpop->count() - 1); // Last item selected
255 // Set the button in case from a menu selection
256 m_pWeekmonthgroup->setButton(TITRAQ_REPORTWEEK);
258 // Update m_nWeeks only if user prefers a different number
259 if (nIndex >= 0) {
260 // User selected N... to indicate an arbitrary number
261 if (nIndex == m_pWeekpop->count() - 1) {
262 Numdial Weeksinput;
263 Weeksinput.setNum(m_nWeeks);
264 if (Weeksinput.exec() == QDialog::Accepted) {
265 m_nWeeks = Weeksinput.getNum();
266 m_pWeekpop->setItemChecked(nLastid, false);
267 m_pWeekpop->setItemChecked(nMenuid, true);
268 }
269 else
270 return;
271 }
272 else { // User selected a preset menu item such as '2 weeks'
273 m_nWeeks = nIndex + 1;
274 m_pWeekpop->setItemChecked(nLastid, false);
275 m_pWeekpop->setItemChecked(nMenuid, true);
276 }
277 }
279 // Clear data window
280 m_pBrowser->setUpdatesEnabled(false);
281 m_pBrowser->clear();
283 // Determine first and last week numbers, then write header
284 nLastweek = QDate::currentDate().weekNumber();
285 if (m_nWeeks > 1) {
286 nFirstweek = QDate::currentDate().addDays(m_nWeeks * -7).weekNumber() + 1;
287 this->writeHeader(nFirstweek, nLastweek);
288 }
289 else
290 this->writeHeader(nLastweek);
292 // Write new contents to data window
293 m_pBrowser->append(this->getWeektotals(QDate::currentDate(), m_nWeeks));
294 if (m_pReprefs->getBool(TITRAQ_PREFDETAILON, TITRAQ_DEFDETAILON))
295 m_pBrowser->append(this->getWeekdetails(QDate::currentDate(), m_nWeeks));
296 this->writeFooter();
297 m_pBrowser->setCursorPosition(0, 0);
298 m_pBrowser->ensureCursorVisible();
299 m_pBrowser->setUpdatesEnabled(true);
300 m_pBrowser->repaint(false);
301 }
303 //
304 // Makes a new monthly report of so many months
305 //
306 void Reportpanel::reportMonths(int nMenuid)
307 {
308 // Range of months to report
309 QString Firstmonth, Lastmonth;
311 // Menu index, first item is always 0
312 int nIndex = m_pMonthpop->indexOf(nMenuid); // Corresponds to months
313 int nLastid = 0; // Last menu id selected
315 if (m_nMonths < m_pMonthpop->count())
316 nLastid = m_pMonthpop->idAt(m_nMonths - 1); // Probably not last item
317 else
318 nLastid = m_pMonthpop->idAt(m_pMonthpop->count() - 1); // Last item selected
320 // Set the button in case from a menu selection
321 m_pWeekmonthgroup->setButton(TITRAQ_REPORTMONTH);
323 // Update m_nMonths only if user prefers a different number
324 if (nIndex >= 0) {
325 // User selected N... to indicate an arbitrary number
326 if (nIndex == m_pMonthpop->count() - 1) {
327 Numdial Monthsinput;
328 Monthsinput.setNum(m_nMonths);
329 if (Monthsinput.exec() == QDialog::Accepted) {
330 m_nMonths = Monthsinput.getNum();
331 m_pMonthpop->setItemChecked(nLastid, false);
332 m_pMonthpop->setItemChecked(nMenuid, true);
333 }
334 else
335 return;
336 }
337 else { // User selected a preset menu item such as '2 months'
338 m_nMonths = nIndex + 1;
339 m_pMonthpop->setItemChecked(nLastid, false);
340 m_pMonthpop->setItemChecked(nMenuid, true);
341 }
342 }
344 // Clear data window
345 m_pBrowser->setUpdatesEnabled(false);
346 m_pBrowser->clear();
348 // Determine first and last month names, then write header
349 Lastmonth = QDate::longMonthName(QDate::currentDate().month());
350 if (m_nMonths > 1) {
351 int nMonth = (QDate::currentDate().addMonths(m_nMonths * -1).month() + 12) % 12 + 1;
352 Firstmonth = QDate::longMonthName(nMonth);
353 this->writeHeader(Firstmonth, Lastmonth);
354 }
355 else
356 this->writeHeader(Lastmonth);
358 // Write new contents to data window
359 m_pBrowser->append(this->getMonthtotals(QDate::currentDate(), m_nMonths));
360 if (m_pReprefs->getBool(TITRAQ_PREFDETAILON, TITRAQ_DEFDETAILON)) {
361 m_pBrowser->append(this->getMonthdetails(QDate::currentDate(), m_nMonths));
362 }
363 this->writeFooter();
364 m_pBrowser->setCursorPosition(0, 0);
365 m_pBrowser->ensureCursorVisible();
366 m_pBrowser->setUpdatesEnabled(true);
367 m_pBrowser->repaint(false);
368 }
370 //
371 // Writes a report header to the display window
372 //
373 void Reportpanel::writeHeader(int nWeeknum)
374 {
375 QString Header;
376 Header = QString("Accounting System ");
377 Header += QString(asgui_version.v_short);
378 Header += trUtf8("\nLocal report, username '");
379 Header += m_pReprefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER);
380 Header += QString("'\n");
381 Header += trUtf8("Date ");
382 Header += QDate::currentDate().toString(Qt::ISODate);
383 Header += trUtf8(", Time ");
384 Header += QTime::currentTime().toString(Qt::ISODate);
385 Header += trUtf8("\nReporting for week %1...").arg(nWeeknum);
386 Header += QString("\n\n");
387 m_pBrowser->setText(Header);
388 }
390 //
391 // Writes a report header to the display window
392 //
393 void Reportpanel::writeHeader(QString Month)
394 {
395 QString Header;
396 Header = QString("Accounting System ");
397 Header += QString(asgui_version.v_short);
398 Header += trUtf8("\nLocal report, username '");
399 Header += m_pReprefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER);
400 Header += QString("'\n");
401 Header += trUtf8("Date ");
402 Header += QDate::currentDate().toString(Qt::ISODate);
403 Header += trUtf8(", Time ");
404 Header += QTime::currentTime().toString(Qt::ISODate);
405 Header += trUtf8("\nReporting for month %1...").arg(Month);
406 Header += QString("\n\n");
407 m_pBrowser->setText(Header);
408 }
410 //
411 // Writes a report header to the display window
412 //
413 void Reportpanel::writeHeader(int nFirst, int nLast)
414 {
415 QString Header;
416 Header = QString("Accounting System ");
417 Header += QString(asgui_version.v_short);
418 Header += trUtf8("\nLocal report, username '");
419 Header += m_pReprefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER);
420 Header += QString("'\n");
421 Header += trUtf8("Date ");
422 Header += QDate::currentDate().toString(Qt::ISODate);
423 Header += trUtf8(", Time ");
424 Header += QTime::currentTime().toString(Qt::ISODate);
425 Header += trUtf8("\nReporting for weeks %1 through %2...").arg(nFirst).arg(nLast);
426 Header += QString("\n\n");
427 m_pBrowser->setText(Header);
428 }
430 //
431 // Writes a report header to the display window
432 //
433 void Reportpanel::writeHeader(QString First, QString Last)
434 {
435 QString Header;
436 Header = QString("Accounting System ");
437 Header += QString(asgui_version.v_short);
438 Header += trUtf8("\nLocal report, username '");
439 Header += m_pReprefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER);
440 Header += QString("'\n");
441 Header += trUtf8("Date ");
442 Header += QDate::currentDate().toString(Qt::ISODate);
443 Header += trUtf8(", Time ");
444 Header += QTime::currentTime().toString(Qt::ISODate);
445 Header += trUtf8("\nReporting months %1 through %2...").arg(First).arg(Last);
446 Header += QString("\n\n");
447 m_pBrowser->setText(Header);
448 }
450 //
451 // Writes a report footer to the display window
452 //
453 void Reportpanel::writeFooter(void)
454 {
455 if (m_pReprefs->getBool(TITRAQ_PREFSIGNATON, TITRAQ_DEFSIGNATON)) {
456 m_pBrowser->append(trUtf8("\n\nPrint name ________________________________________\n"));
457 m_pBrowser->append(trUtf8("\n\nSignature ________________________________________"));
458 }
459 }
461 //
462 // Returns one week of details data
463 //
464 QString Reportpanel::getWeekdetails(QDate Dayref, int nWeeks)
465 {
466 QString Data; // Output string
467 QString Tempstring; // Temp churning
468 int nRows = m_pReptable->numRows();
470 // Find range boundaries
471 Q_ASSERT(nWeeks > 0);
472 QDate Tempdate;
473 QDate Firstday;
474 QDate Lastday;
475 Firstday = Dayref.addDays(Dayref.dayOfWeek() * -1 + 1);
476 Firstday = Firstday.addDays((nWeeks - 1) * -7);
477 Lastday = Firstday.addDays(7 * nWeeks);
479 // Write some quick header text to the outgoing string
480 Data = trUtf8("\nDate Hours Account details\n");
481 Data += QString("---------- ----- ----------------------------------------\n");
483 // Build the long week data string
484 for (int nIter = nRows - 1; nIter >= 0; nIter--) {
485 // Work on this tuple only if it within the reporting range
486 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK);
487 Tempdate = QDate::fromString(m_pReptable->text(nIter, TITRAQ_IDXDATE), Qt::ISODate);
488 if (!Tempstring.isEmpty() && Firstday <= Tempdate && Tempdate < Lastday) {
489 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXDATE);
490 if (!Tempstring.isEmpty())
491 Data += Tempstring;
492 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXAMOUNT);
493 if (!Tempstring.isEmpty())
494 Data += QString(TITRAQ_SEPARATORTOK) + Tempstring;
495 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK);
496 if (!Tempstring.isEmpty())
497 Data += QString(TITRAQ_SEPARATORTOK) + Tempstring;
498 Data += QString("\n"); // Finish off line
499 }
500 }
502 return Data;
503 }
505 //
506 // Returns one week of totals data
507 //
508 QString Reportpanel::getWeektotals(QDate Dayref, int nWeeks)
509 {
510 using namespace std; // Needed for maps and hash
511 map<string, string> Hashtasks; // Hashtable to store tasks
512 multimap<string, string> Hashhours; // Hashtable to store hours
513 map<string, string>::iterator Taskiter; // Hashtable task iterator
514 multimap<string, string>::iterator Houriter; // Hashtable hour iterator
516 QString Totals; // Data totals to return for writing
517 QString Tempstring; // Temporary processing string
518 QDate Tempdate; // Temporary processing date
519 int nRows = m_pReptable->numRows();
521 // Find range boundaries
522 Q_ASSERT(nWeeks > 0);
523 QDate Firstday;
524 QDate Lastday;
525 Firstday = Dayref.addDays(Dayref.dayOfWeek() * -1 + 1);
526 Firstday = Firstday.addDays((nWeeks - 1) * -7);
527 Lastday = Firstday.addDays(7 * nWeeks);
529 // Parse the table for interesting values
530 for (int nIter = 0; nIter < nRows; nIter++) {
531 // Work on this tuple only if it within the reporting range
532 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK);
533 Tempdate = QDate::fromString(m_pReptable->text(nIter, TITRAQ_IDXDATE), Qt::ISODate);
534 if (!Tempstring.isEmpty() && Firstday <= Tempdate && Tempdate < Lastday) {
535 string Convstring = Tempstring.toStdString(); // Convert to string (can't cast?)
536 QTime Intable = QTime::fromString(m_pReptable->text(nIter, TITRAQ_IDXAMOUNT), Qt::ISODate);
537 string Gethashed = Hashtasks[Convstring];
538 int nTothours = QString::fromStdString(Gethashed).section(':', 0, 0).toInt() + Intable.hour();;
539 int nTotminut = QString::fromStdString(Gethashed).section(':', 1, 1).toInt() + Intable.minute();
540 nTothours += nTotminut / 60;
541 nTotminut %= 60;
542 QString Hours = QString::number(nTothours).rightJustify(3, ' ');
543 QString Mins = QString::number(nTotminut).rightJustify(2, '0');
544 string Timestring = Hours.toStdString() + ':' + Mins.toStdString(); // Convert to string (can't cast?)
545 Hashtasks[Convstring] = Timestring; // Finally store in hashtable
546 }
547 }
549 // Reverse copy the tasks hashtable to both sort and index by amount key
550 for (Taskiter = Hashtasks.begin(); Taskiter != Hashtasks.end(); Taskiter++)
551 Hashhours.insert(pair<string, string>(Taskiter->second, Taskiter->first));
553 // Write the actual data totals to the outgoing string in reverse order
554 for (Houriter = Hashhours.begin(); Houriter != Hashhours.end(); Houriter++)
555 Totals = QString::fromStdString(Houriter->first + ' ' + Houriter->second + '\n' + Totals.toStdString());
557 // Write some quick header text to the outgoing string in reverse order
558 Totals = QString("------ ----------------------------------------\n") + Totals;
559 Totals = trUtf8("Total Account summary\n") + Totals;
561 return Totals; // The outgoing string... its finally gone, let's go to bed
562 }
564 //
565 // Returns one month of details data
566 //
567 QString Reportpanel::getMonthdetails(QDate Dayref, int nMonths)
568 {
569 QString Data; // Output string
570 QString Tempstring; // Temp churning
571 QDate Tempdate; // For comparing
572 QDate Firstday; // Minimum boundary
573 QDate Lastday; // Maximum boundary
574 int nRows = m_pReptable->numRows();
576 // Find range boundaries
577 Q_ASSERT(nMonths > 0);
578 int nYear = Dayref.year();
579 int nMonth = (Dayref.addMonths(nMonths * -1).month() + 12) % 12 + 1;
580 if (nMonth > Dayref.month())
581 nYear--;
582 Firstday = QDate(nYear, nMonth, 1);
583 Lastday = QDate(Dayref.year(), Dayref.month(), Dayref.daysInMonth());
585 // Write some quick header text to the outgoing string
586 Data = trUtf8("\nDate Hours Account details\n");
587 Data += QString("---------- ----- ----------------------------------------\n");
589 // Build the long week data string
590 for (int nIter = nRows - 1; nIter >= 0; nIter--) {
591 // Work on this tuple only if it within the reporting range
592 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK);
593 Tempdate = QDate::fromString(m_pReptable->text(nIter, TITRAQ_IDXDATE), Qt::ISODate);
594 if (!Tempstring.isEmpty() && Firstday <= Tempdate && Tempdate < Lastday) {
595 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXDATE);
596 if (!Tempstring.isEmpty())
597 Data += Tempstring;
598 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXAMOUNT);
599 if (!Tempstring.isEmpty())
600 Data += QString(TITRAQ_SEPARATORTOK) + Tempstring;
601 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK);
602 if (!Tempstring.isEmpty())
603 Data += QString(TITRAQ_SEPARATORTOK) + Tempstring;
604 Data += trUtf8("\n"); // Finish off line
605 }
606 }
608 return Data;
609 }
611 //
612 // Returns one month of totals data
613 //
614 QString Reportpanel::getMonthtotals(QDate Dayref, int nMonths)
615 {
616 using namespace std; // Needed for maps and hash
617 map<string, string> Hashtasks; // Hashtable to store tasks
618 multimap<string, string> Hashhours; // Hashtable to store hours
619 map<string, string>::iterator Taskiter; // Hashtable task iterator
620 multimap<string, string>::iterator Houriter; // Hashtable hour iterator
622 QString Totals; // Data totals to return for writing
623 QString Tempstring; // Temporary processing string
624 QDate Tempdate; // Temporary processing date
625 int nRows = m_pReptable->numRows();
627 // Find range boundaries
628 Q_ASSERT(nMonths > 0);
629 int nYear = Dayref.year();
630 int nMonth = (Dayref.addMonths(nMonths * -1).month() + 12) % 12 + 1;
631 if (nMonth > Dayref.month())
632 nYear--;
633 QDate Firstday = QDate(nYear, nMonth, 1);
634 QDate Lastday = QDate(Dayref.year(), Dayref.month(), Dayref.daysInMonth());
636 // Parse the table for interesting values
637 for (int nIter = 0; nIter < nRows; nIter++) {
638 // Work on this tuple only if it within the reporting range
639 Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK);
640 Tempdate = QDate::fromString(m_pReptable->text(nIter, TITRAQ_IDXDATE), Qt::ISODate);
641 if (!Tempstring.isEmpty() && Firstday <= Tempdate && Tempdate < Lastday) {
642 string Convstring = Tempstring.toStdString(); // Convert to string (can't cast?)
643 QTime Intable = QTime::fromString(m_pReptable->text(nIter, TITRAQ_IDXAMOUNT), Qt::ISODate);
644 string Gethashed = Hashtasks[Convstring];
645 int nTothours = QString::fromStdString(Gethashed).section(':', 0, 0).toInt() + Intable.hour();;
646 int nTotminut = QString::fromStdString(Gethashed).section(':', 1, 1).toInt() + Intable.minute();
647 nTothours += nTotminut / 60;
648 nTotminut %= 60;
649 QString Hours = QString::number(nTothours).rightJustify(3, ' ');
650 QString Mins = QString::number(nTotminut).rightJustify(2, '0');
651 QString Timestring = Hours + ':' + Mins; // Convert to string (can't cast?)
652 Hashtasks[Convstring] = Timestring.toStdString(); // Finally store in hashtable
653 }
654 }
656 // Reverse copy the tasks hashtable to both sort and index by amount key
657 for (Taskiter = Hashtasks.begin(); Taskiter != Hashtasks.end(); Taskiter++)
658 Hashhours.insert(pair<string, string>(Taskiter->second, Taskiter->first));
660 // Write the actual data totals to the outgoing string in reverse order
661 for (Houriter = Hashhours.begin(); Houriter != Hashhours.end(); Houriter++)
662 Totals = QString::fromStdString(Houriter->first + ' ' + Houriter->second + '\n' + Totals.toStdString());
664 // Write some quick header text to the outgoing string in reverse order
665 Totals = QString("------ ----------------------------------------\n") + Totals;
666 Totals = trUtf8("Total Account summary\n") + Totals;
668 return Totals; // The outgoing string... its finally gone, let's go to bed
669 }
671 //
672 // Saves the currently displayed local report
673 //
674 void Reportpanel::saveReport(void)
675 {
676 int nResult = 0; // For checking user's answer
677 QFile Report; // The resulting report file
678 QString Filestring; // The user chosen file name to save
679 QString Openas = m_pReprefs->getString(TITRAQ_PREFHOME, TITRAQ_DEFHOME);
681 // And then get the name of the selected file to save to
682 Filestring = Q3FileDialog::getSaveFileName(Openas, trUtf8("Text files (*.txt);;All Files (*)"), this, trUtf8("ChooserDialog"), trUtf8("Choose a file to save"), NULL, false);
683 if (!Filestring.isEmpty()) {
684 if (QFile::exists(Filestring)) {
685 nResult = QMessageBox::warning(this, QString(TITRAQ_APPTITLE)
686 + ' ' + asgui_version.v_short, trUtf8(TITRAQ_OVERWRITE),
687 trUtf8("&Yes"), trUtf8("&No"), NULL, 1, 1);
688 if (nResult = QMessageBox::Ok) { // Overwrite a file
689 Report.setName(Filestring); // User wished name
690 Report.open(QIODevice::WriteOnly | QIODevice::Truncate); // Open report file
691 Q3TextStream Outstream(&Report); // Convert to stream
692 Outstream << m_pBrowser->text(); // Write the data
693 Report.close(); // Finish by closing
694 }
695 }
696 else { // User gave a file name, and there was no preexisting file there
697 Report.setName(Filestring); // User wished name
698 Report.open(QIODevice::WriteOnly | QIODevice::Truncate); // Open report file
699 Q3TextStream Outstream(&Report); // Convert to stream
700 Outstream << m_pBrowser->text(); // Write the data
701 Report.close(); // Finish by closing
702 }
703 }
704 // Otherwise, user did not select a valid file and push okay button
705 }
707 //
708 // Prints the currently displayed local report
709 //
710 void Reportpanel::printReport(void)
711 {
712 #ifndef QT_NO_PRINTER
713 if (m_pPrinter->setup(this)) { // Opens printer dialog
714 m_pPrinter->setFullPage(true); // Set our own margins
715 QPainter Paint; // Our painter (for pages)
716 Paint.begin(m_pPrinter); // Paint on printer
717 Paint.setFont(m_pBrowser->font());
718 QFontMetrics Fontmetrics = Paint.fontMetrics();
719 Q3PaintDeviceMetrics Devmetrics(m_pPrinter); // Need width/height of printer surface
720 const int knMargin = Devmetrics.logicalDpiX() / 2; // Half-inch margin
721 int nYpos = knMargin; // Y position for each line
722 int nPageno = 1; // The starting page number
724 for (int nIter = 0; nIter < m_pBrowser->lines() && !m_pPrinter->aborted(); nIter++) {
725 // See if there is some space on this page to paint on
726 if (nYpos + Fontmetrics.lineSpacing() > Devmetrics.height() - knMargin) {
727 // QString Printmsg(trUtf8("Printing page "))
728 // + QString::number(++nPageno) + QString("...");
729 // m_pStatus()->message(Printmsg); // Not in scope (crap)
730 if (!m_pPrinter->newPage()) // Start new page
731 break; // Some error
732 nYpos = knMargin; // Back to top of page
733 }
734 Paint.drawText(knMargin, nYpos, Devmetrics.width() - 2 * knMargin,
735 Fontmetrics.lineSpacing(), Qt::ExpandTabs, m_pBrowser->text(nIter));
736 nYpos += Fontmetrics.lineSpacing();
737 }
738 Paint.end(); // Send job to printer
739 // m_pStatus()->message(trUtf8("Printing completed"), 2000); // Not in scope
740 }
741 // m_pStatusBar()->message(trUtf8("Printing completed"), 2000); // Not in scope
742 #endif
743 }
745 //
746 // Sets the strings of the subwidgets using the current language
747 //
748 void Reportpanel::textChange(void)
749 {
750 this->setCaption(trUtf8("AS local report", "Local report using weekly or monthly data."));
752 // Top level push buttons associated with accept and save slots
753 m_pSavebutt->setText(trUtf8("Save As...", "Comment for Savebutton"));
754 QToolTip::add(m_pSavebutt, trUtf8("Saves the report text", "Comment for tooltip Savebutton"));
755 Q3WhatsThis::add(m_pSavebutt, trUtf8("The save button saves the report text to a file", "Comment for whatsThis Savebutton"));
756 m_pPrintbutt->setText(trUtf8("Print...", "Comment for Printbutton"));
757 QToolTip::add(m_pPrintbutt, trUtf8("Print the report text", "Comment for tooltip Printbutton"));
758 Q3WhatsThis::add(m_pPrintbutt, trUtf8("The print button prints the report text to a file", "Comment for whatsThis Printbutton"));
759 m_pDismissbutt->setText(trUtf8("Dismiss", "Comment for Dismissbutton"));
760 QToolTip::add(m_pDismissbutt, trUtf8("Closes the report panel", "Comment for tooltip Dismissbutton"));
761 Q3WhatsThis::add(m_pDismissbutt, trUtf8("The dismiss button dismisses the report panel", "Comment for whatsThis Dismissbutton"));
763 // Inner tool buttons for new local report generation
764 m_pWeeklybutt->setText(trUtf8("Weekly", "Comment for Weeklybutt"));
765 QToolTip::add(m_pWeeklybutt, trUtf8("Hold down for options", "Comment for tooltip Weeklybutt"));
766 Q3WhatsThis::add(m_pWeeklybutt, trUtf8("The Weekly button generates a new weekly report.\nHold this button down to specify many weeks.", "Comment for whatsThis Weeklybutt"));
767 m_pMonthlybutt->setText(trUtf8("Monthly", "Comment for Monthlybutt"));
768 QToolTip::add(m_pMonthlybutt, trUtf8("Hold down for options", "Comment for tooltip Monthlybutt"));
769 Q3WhatsThis::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"));
770 }
771 } // namespace AS