|
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 // |
|
31 |
|
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> |
|
48 |
|
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" |
|
56 |
|
57 // Version information |
|
58 #define _AS_VERSION_CPP_AS_HEADER_ |
|
59 #include "as_version.cpp" |
|
60 #undef _AS_VERSION_CPP_AS_HEADER_ |
|
61 |
|
62 |
|
63 namespace AS { |
|
64 |
|
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"); |
|
80 |
|
81 // Make panel resizeable |
|
82 this->setSizeGripEnabled(true); |
|
83 this->setSizePolicy(QSizePolicy((QSizePolicy::SizeType)5, |
|
84 (QSizePolicy::SizeType)5, 0, 0, this->sizePolicy().hasHeightForWidth())); |
|
85 |
|
86 // Store matrix and prefs members |
|
87 m_pReptable = pTable; |
|
88 m_pReprefs = pPreferences; |
|
89 m_pPrinter = new QPrinter; |
|
90 |
|
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); |
|
94 |
|
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"); |
|
99 |
|
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); |
|
110 |
|
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); |
|
129 |
|
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); |
|
142 |
|
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 } |
|
147 |
|
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); |
|
160 |
|
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 } |
|
165 |
|
166 // Add our tool buttons |
|
167 m_pWeekmonthlay->addWidget(m_pWeeklybutt); |
|
168 m_pWeekmonthlay->addWidget(m_pMonthlybutt); |
|
169 m_pToolay->addWidget(m_pWeekmonthgroup); |
|
170 |
|
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); |
|
188 |
|
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 } |
|
198 |
|
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); |
|
206 |
|
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 } |
|
220 |
|
221 nRet = QDialog::exec(); // Blast off |
|
222 |
|
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 } |
|
230 |
|
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; |
|
238 |
|
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 |
|
242 |
|
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 |
|
247 |
|
248 // Set the button in case from a menu selection |
|
249 m_pWeekmonthgroup->setButton(TITRAQ_REPORTWEEK); |
|
250 |
|
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 } |
|
271 |
|
272 // Clear data window |
|
273 m_pBrowser->setUpdatesEnabled(false); |
|
274 m_pBrowser->clear(); |
|
275 |
|
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); |
|
284 |
|
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 } |
|
295 |
|
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; |
|
303 |
|
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 |
|
307 |
|
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 |
|
312 |
|
313 // Set the button in case from a menu selection |
|
314 m_pWeekmonthgroup->setButton(TITRAQ_REPORTMONTH); |
|
315 |
|
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 } |
|
336 |
|
337 // Clear data window |
|
338 m_pBrowser->setUpdatesEnabled(false); |
|
339 m_pBrowser->clear(); |
|
340 |
|
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); |
|
350 |
|
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 } |
|
362 |
|
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 } |
|
382 |
|
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 } |
|
402 |
|
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 } |
|
422 |
|
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 } |
|
442 |
|
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 } |
|
453 |
|
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(); |
|
462 |
|
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); |
|
471 |
|
472 // Write some quick header text to the outgoing string |
|
473 Data = trUtf8("\nDate Hours Account details\n"); |
|
474 Data += QString("---------- ----- ----------------------------------------\n"); |
|
475 |
|
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 } |
|
494 |
|
495 return Data; |
|
496 } |
|
497 |
|
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 |
|
508 |
|
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(); |
|
513 |
|
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); |
|
521 |
|
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 } |
|
540 |
|
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)); |
|
544 |
|
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; |
|
548 |
|
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; |
|
552 |
|
553 return Totals; // The outgoing string... its finally gone, let's go to bed |
|
554 } |
|
555 |
|
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(); |
|
567 |
|
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()); |
|
576 |
|
577 // Write some quick header text to the outgoing string |
|
578 Data = trUtf8("\nDate Hours Account details\n"); |
|
579 Data += QString("---------- ----- ----------------------------------------\n"); |
|
580 |
|
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 } |
|
599 |
|
600 return Data; |
|
601 } |
|
602 |
|
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 |
|
613 |
|
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(); |
|
618 |
|
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()); |
|
627 |
|
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 } |
|
646 |
|
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)); |
|
650 |
|
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; |
|
654 |
|
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; |
|
658 |
|
659 return Totals; // The outgoing string... its finally gone, let's go to bed |
|
660 } |
|
661 |
|
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); |
|
671 |
|
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 } |
|
697 |
|
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 |
|
714 |
|
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 } |
|
735 |
|
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.")); |
|
742 |
|
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")); |
|
753 |
|
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 |