diff -r 27e940e8e5f3 -r d64aaa7d146f as_reportpanel.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/as_reportpanel.cpp Fri Nov 28 11:21:08 2008 +0100 @@ -0,0 +1,762 @@ +// +// OSSP asgui - Accounting system graphical user interface +// Copyright (c) 2002-2004 The OSSP Project (http://www.ossp.org/) +// Copyright (c) 2002-2004 Ralf S. Engelschall +// Copyright (c) 2002-2004 Michael Schloh von Bennewitz +// Copyright (c) 2002-2004 Cable & Wireless Telecommunications Services GmbH +// +// This file is part of OSSP asgui, an accounting system graphical user +// interface which can be found at http://www.ossp.org/pkg/tool/asgui/. +// +// Permission to use, copy, modify, and distribute this software for +// any purpose with or without fee is hereby granted, provided that +// the above copyright notice and this permission notice appear in all +// copies. +// +// THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +// IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR +// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF +// USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND +// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT +// OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +// SUCH DAMAGE. +// +// as_reportpanel.cpp: ISO C++ implementation +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "as_reportpanel.h" +#include "as_numdial.h" +#include "as_table.h" +#include "as_pref.h" +#include "as_generic.h" +#include "as_const.h" +#include "as_except.h" + +// Version information +#define _AS_VERSION_CPP_AS_HEADER_ +#include "as_version.cpp" +#undef _AS_VERSION_CPP_AS_HEADER_ + + +namespace AS { + +// +// Constructs a Reportpanel as a child of 'pParent', with the +// name 'kszName' and widget flags set to 'Flags'. +// +// The dialog will by default be modal, unless you set 'bModal' to +// false to construct a modeless dialog. +// +Reportpanel::Reportpanel(TiTable *pTable, Preferences *pPreferences, + QWidget *pParent, const char *kszName, + bool bModal, WFlags Flags) + : QDialog(pParent, kszName, bModal, Flags) +{ + // Boilerplate code to initialize the panel + if (!kszName) + this->setName("Reportpanel"); + + // Make panel resizeable + this->setSizeGripEnabled(true); + this->setSizePolicy(QSizePolicy((QSizePolicy::SizeType)5, + (QSizePolicy::SizeType)5, 0, 0, this->sizePolicy().hasHeightForWidth())); + + // Store matrix and prefs members + m_pReptable = pTable; + m_pReprefs = pPreferences; + m_pPrinter = new QPrinter; + + // Preset number of weeks and months to report + m_nWeeks = m_pReprefs->getNumber(TITRAQ_PREFREPORTWEEKS, TITRAQ_DEFREPORTWEEKS); + m_nMonths = m_pReprefs->getNumber(TITRAQ_PREFREPORTMONTHS, TITRAQ_DEFREPORTMONTHS); + + // Build panel using already constructed widgets and layouts + m_pFormlay = new QVBoxLayout(this, 11, 6, "Formlayout"); + m_pToolay = new QHBoxLayout(0, 0, 6, "Toolbuttonlay"); + m_pPushlay = new QHBoxLayout(0, 0, 6, "Pushbuttonlay"); + + // Groupbox and its text display + m_pBrowser = new QTextEdit(this, "Reportbrowser"); + m_pBrowser->setTextFormat(PlainText); + m_pBrowser->setReadOnly(true); + m_pBrowser->setFont(QFont("Courier", 10)); + m_pFormlay->addWidget(m_pBrowser); + m_pFormlay->addSpacing(6); + m_pFormlay->addLayout(m_pToolay); + m_pFormlay->addSpacing(6); + m_pFormlay->addLayout(m_pPushlay); + + // Tool button suite + m_pWeekmonthgroup = new QButtonGroup(this, "Weekmonthgroup"); + m_pWeekmonthgroup->setColumnLayout(0, Qt::Horizontal); + m_pWeekmonthgroup->layout()->setSpacing(11); + m_pWeekmonthgroup->layout()->setMargin(0); + m_pWeekmonthlay = new QHBoxLayout(m_pWeekmonthgroup->layout()); + m_pWeekmonthgroup->setFrameShape(QFrame::NoFrame); + m_pWeekmonthgroup->setExclusive(true); + m_pWeeklybutt = new QToolButton(m_pWeekmonthgroup, "Weeklybutton"); +// m_pWeeklybutt->setPaletteBackgroundColor(QColor(198, 196, 186)); + m_pWeeklybutt->setFocusPolicy(QWidget::TabFocus); + m_pWeeklybutt->setCursor(QCursor(13)); + m_pWeeklybutt->setToggleButton(true); + m_pMonthlybutt = new QToolButton(m_pWeekmonthgroup, "Monthlybutton"); +// m_pMonthlybutt->setPaletteBackgroundColor(QColor(198, 196, 186)); + m_pMonthlybutt->setFocusPolicy(QWidget::TabFocus); + m_pMonthlybutt->setCursor(QCursor(13)); + m_pMonthlybutt->setToggleButton(true); + + // Popup for number of weeks + m_pWeekpop = new QPopupMenu(this); + if (m_pWeekpop == NULL) // Sanity check + throw Genexcept("Weekly toolbutton popup creation failed."); + m_pWeekpop->insertItem(trUtf8("One week"), this, SLOT(reportWeeks(int))); + m_pWeekpop->insertItem(trUtf8("Two weeks"), this, SLOT(reportWeeks(int))); + m_pWeekpop->insertItem(trUtf8("Three weeks"), this, SLOT(reportWeeks(int))); + m_pWeekpop->insertItem(trUtf8("Four weeks"), this, SLOT(reportWeeks(int))); + m_pWeekpop->insertItem(trUtf8("N... weeks"), this, SLOT(reportWeeks(int))); + m_pWeekpop->setCheckable(true); + m_pWeeklybutt->setPopup(m_pWeekpop); + m_pWeeklybutt->setPopupDelay(TITRAQ_POPUPMSECS); + + { // Initialize check button correctly + int nPosition = (m_nWeeks < m_pWeekpop->count()) ? m_nWeeks : m_pWeekpop->count(); + m_pWeekpop->setItemChecked(m_pWeekpop->idAt(--nPosition), true); + } + + // Popup for number of months + m_pMonthpop = new QPopupMenu(this); + if (m_pMonthpop == NULL) // Sanity check + throw Genexcept("Monthly toolbutton popup creation failed."); + m_pMonthpop->insertItem(trUtf8("One month"), this, SLOT(reportMonths(int))); + m_pMonthpop->insertItem(trUtf8("Two months"), this, SLOT(reportMonths(int))); + m_pMonthpop->insertItem(trUtf8("Three months"), this, SLOT(reportMonths(int))); + m_pMonthpop->insertItem(trUtf8("Four months"), this, SLOT(reportMonths(int))); + m_pMonthpop->insertItem(trUtf8("N... months"), this, SLOT(reportMonths(int))); + m_pMonthpop->setCheckable(true); + m_pMonthlybutt->setPopup(m_pMonthpop); + m_pMonthlybutt->setPopupDelay(TITRAQ_POPUPMSECS); + + { // Initialize check button correctly + int nPosition = (m_nMonths < m_pMonthpop->count()) ? m_nMonths : m_pMonthpop->count(); + m_pMonthpop->setItemChecked(m_pMonthpop->idAt(--nPosition), true); + } + + // Add our tool buttons + m_pWeekmonthlay->addWidget(m_pWeeklybutt); + m_pWeekmonthlay->addWidget(m_pMonthlybutt); + m_pToolay->addWidget(m_pWeekmonthgroup); + + // Push button suite + m_pSavebutt = new QPushButton(this, "Savebutton"); + m_pSavebutt->setPaletteBackgroundColor(QColor(202, 194, 182)); + m_pSavebutt->setCursor(QCursor(13)); + m_pPrintbutt = new QPushButton(this, "Printbutton"); + m_pPrintbutt->setPaletteBackgroundColor(QColor(198, 196, 186)); + m_pPrintbutt->setCursor(QCursor(13)); +#ifdef QT_NO_PRINTER + m_pPrintbutt->setEnabled(false); +#endif + m_pDismissbutt = new QPushButton(this, "Dismissbutton"); + m_pDismissbutt->setPaletteBackgroundColor(QColor(198, 196, 186)); + m_pDismissbutt->setCursor(QCursor(13)); + m_pDismissbutt->setDefault(true); + m_pPushlay->addWidget(m_pSavebutt); + m_pPushlay->addWidget(m_pPrintbutt); + m_pPushlay->addWidget(m_pDismissbutt); + + // Connect signals to slots, accept() and reject() are Qt implicit + connect(m_pWeeklybutt, SIGNAL(clicked(void)), SLOT(reportWeeks(void))); + connect(m_pMonthlybutt, SIGNAL(clicked(void)), SLOT(reportMonths(void))); + connect(m_pSavebutt, SIGNAL(clicked(void)), SLOT(saveReport(void))); + connect(m_pPrintbutt, SIGNAL(clicked(void)), SLOT(printReport(void))); + connect(m_pDismissbutt, SIGNAL(clicked(void)), SLOT(accept(void))); + this->resize(QSize(464, 332).expandedTo(minimumSizeHint())); + this->textChange(); +} + +// +// Overload QDialog::exec(), and generate a report before executing modally +// +int Reportpanel::exec(void) +{ + int nRet = 0; + int nPeriod = m_pReprefs->getNumber(TITRAQ_PREFREPORTYPE, TITRAQ_DEFREPORTYPE); + + switch (nPeriod) { + case TITRAQ_REPORTWEEK: + this->reportWeeks(1); + m_pWeekmonthgroup->setButton(TITRAQ_REPORTWEEK); + break; + case TITRAQ_REPORTMONTH: + this->reportMonths(1); + m_pWeekmonthgroup->setButton(TITRAQ_REPORTMONTH); + break; + default: + throw Genexcept("Reportpanel: Modal event loop entered with no report period."); + break; + } + + nRet = QDialog::exec(); // Blast off + + // Before losing scope, the preferred report period + m_pReprefs->setNumber(TITRAQ_PREFREPORTYPE, + m_pWeekmonthgroup->id(m_pWeekmonthgroup->selected())); + m_pReprefs->setNumber(TITRAQ_PREFREPORTWEEKS, m_nWeeks); + m_pReprefs->setNumber(TITRAQ_PREFREPORTMONTHS, m_nMonths); + return nRet; +} + +// +// Makes a new weekly report of so many weeks +// +void Reportpanel::reportWeeks(int nMenuid) +{ + // Range of weeks to report + int nFirstweek, nLastweek; + + // Menu index, first item is always 0 + int nIndex = m_pWeekpop->indexOf(nMenuid); // Corresponds to weeks + int nLastid = 0; // Last menu id selected + + if (m_nWeeks < m_pWeekpop->count()) + nLastid = m_pWeekpop->idAt(m_nWeeks - 1); // Probably not last item + else + nLastid = m_pWeekpop->idAt(m_pWeekpop->count() - 1); // Last item selected + + // Set the button in case from a menu selection + m_pWeekmonthgroup->setButton(TITRAQ_REPORTWEEK); + + // Update m_nWeeks only if user prefers a different number + if (nIndex >= 0) { + // User selected N... to indicate an arbitrary number + if (nIndex == m_pWeekpop->count() - 1) { + Numdial Weeksinput; + Weeksinput.setNum(m_nWeeks); + if (Weeksinput.exec() == QDialog::Accepted) { + m_nWeeks = Weeksinput.getNum(); + m_pWeekpop->setItemChecked(nLastid, false); + m_pWeekpop->setItemChecked(nMenuid, true); + } + else + return; + } + else { // User selected a preset menu item such as '2 weeks' + m_nWeeks = nIndex + 1; + m_pWeekpop->setItemChecked(nLastid, false); + m_pWeekpop->setItemChecked(nMenuid, true); + } + } + + // Clear data window + m_pBrowser->setUpdatesEnabled(false); + m_pBrowser->clear(); + + // Determine first and last week numbers, then write header + nLastweek = QDate::currentDate().weekNumber(); + if (m_nWeeks > 1) { + nFirstweek = QDate::currentDate().addDays(m_nWeeks * -7).weekNumber() + 1; + this->writeHeader(nFirstweek, nLastweek); + } + else + this->writeHeader(nLastweek); + + // Write new contents to data window + m_pBrowser->append(this->getWeektotals(QDate::currentDate(), m_nWeeks)); + if (m_pReprefs->getBool(TITRAQ_PREFDETAILON, TITRAQ_DEFDETAILON)) + m_pBrowser->append(this->getWeekdetails(QDate::currentDate(), m_nWeeks)); + this->writeFooter(); + m_pBrowser->setCursorPosition(0, 0); + m_pBrowser->ensureCursorVisible(); + m_pBrowser->setUpdatesEnabled(true); + m_pBrowser->repaint(false); +} + +// +// Makes a new monthly report of so many months +// +void Reportpanel::reportMonths(int nMenuid) +{ + // Range of months to report + QString Firstmonth, Lastmonth; + + // Menu index, first item is always 0 + int nIndex = m_pMonthpop->indexOf(nMenuid); // Corresponds to months + int nLastid = 0; // Last menu id selected + + if (m_nMonths < m_pMonthpop->count()) + nLastid = m_pMonthpop->idAt(m_nMonths - 1); // Probably not last item + else + nLastid = m_pMonthpop->idAt(m_pMonthpop->count() - 1); // Last item selected + + // Set the button in case from a menu selection + m_pWeekmonthgroup->setButton(TITRAQ_REPORTMONTH); + + // Update m_nMonths only if user prefers a different number + if (nIndex >= 0) { + // User selected N... to indicate an arbitrary number + if (nIndex == m_pMonthpop->count() - 1) { + Numdial Monthsinput; + Monthsinput.setNum(m_nMonths); + if (Monthsinput.exec() == QDialog::Accepted) { + m_nMonths = Monthsinput.getNum(); + m_pMonthpop->setItemChecked(nLastid, false); + m_pMonthpop->setItemChecked(nMenuid, true); + } + else + return; + } + else { // User selected a preset menu item such as '2 months' + m_nMonths = nIndex + 1; + m_pMonthpop->setItemChecked(nLastid, false); + m_pMonthpop->setItemChecked(nMenuid, true); + } + } + + // Clear data window + m_pBrowser->setUpdatesEnabled(false); + m_pBrowser->clear(); + + // Determine first and last month names, then write header + Lastmonth = QDate::longMonthName(QDate::currentDate().month()); + if (m_nMonths > 1) { + int nMonth = (QDate::currentDate().addMonths(m_nMonths * -1).month() + 12) % 12 + 1; + Firstmonth = QDate::longMonthName(nMonth); + this->writeHeader(Firstmonth, Lastmonth); + } + else + this->writeHeader(Lastmonth); + + // Write new contents to data window + m_pBrowser->append(this->getMonthtotals(QDate::currentDate(), m_nMonths)); + if (m_pReprefs->getBool(TITRAQ_PREFDETAILON, TITRAQ_DEFDETAILON)) { + m_pBrowser->append(this->getMonthdetails(QDate::currentDate(), m_nMonths)); + } + this->writeFooter(); + m_pBrowser->setCursorPosition(0, 0); + m_pBrowser->ensureCursorVisible(); + m_pBrowser->setUpdatesEnabled(true); + m_pBrowser->repaint(false); +} + +// +// Writes a report header to the display window +// +void Reportpanel::writeHeader(int nWeeknum) +{ + QString Header; + Header = QString("Accounting System "); + Header += QString(asgui_version.v_short); + Header += trUtf8("\nLocal report, username '"); + Header += m_pReprefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER); + Header += QString("'\n"); + Header += trUtf8("Date "); + Header += QDate::currentDate().toString(Qt::ISODate); + Header += trUtf8(", Time "); + Header += QTime::currentTime().toString(Qt::ISODate); + Header += trUtf8("\nReporting for week %1...").arg(nWeeknum); + Header += QString("\n\n"); + m_pBrowser->setText(Header); +} + +// +// Writes a report header to the display window +// +void Reportpanel::writeHeader(QString Month) +{ + QString Header; + Header = QString("Accounting System "); + Header += QString(asgui_version.v_short); + Header += trUtf8("\nLocal report, username '"); + Header += m_pReprefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER); + Header += QString("'\n"); + Header += trUtf8("Date "); + Header += QDate::currentDate().toString(Qt::ISODate); + Header += trUtf8(", Time "); + Header += QTime::currentTime().toString(Qt::ISODate); + Header += trUtf8("\nReporting for month %1...").arg(Month); + Header += QString("\n\n"); + m_pBrowser->setText(Header); +} + +// +// Writes a report header to the display window +// +void Reportpanel::writeHeader(int nFirst, int nLast) +{ + QString Header; + Header = QString("Accounting System "); + Header += QString(asgui_version.v_short); + Header += trUtf8("\nLocal report, username '"); + Header += m_pReprefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER); + Header += QString("'\n"); + Header += trUtf8("Date "); + Header += QDate::currentDate().toString(Qt::ISODate); + Header += trUtf8(", Time "); + Header += QTime::currentTime().toString(Qt::ISODate); + Header += trUtf8("\nReporting for weeks %1 through %2...").arg(nFirst).arg(nLast); + Header += QString("\n\n"); + m_pBrowser->setText(Header); +} + +// +// Writes a report header to the display window +// +void Reportpanel::writeHeader(QString First, QString Last) +{ + QString Header; + Header = QString("Accounting System "); + Header += QString(asgui_version.v_short); + Header += trUtf8("\nLocal report, username '"); + Header += m_pReprefs->getString(TITRAQ_PREFUSER, TITRAQ_DEFUSER); + Header += QString("'\n"); + Header += trUtf8("Date "); + Header += QDate::currentDate().toString(Qt::ISODate); + Header += trUtf8(", Time "); + Header += QTime::currentTime().toString(Qt::ISODate); + Header += trUtf8("\nReporting months %1 through %2...").arg(First).arg(Last); + Header += QString("\n\n"); + m_pBrowser->setText(Header); +} + +// +// Writes a report footer to the display window +// +void Reportpanel::writeFooter(void) +{ + if (m_pReprefs->getBool(TITRAQ_PREFSIGNATON, TITRAQ_DEFSIGNATON)) { + m_pBrowser->append(trUtf8("\n\nPrint name ________________________________________\n")); + m_pBrowser->append(trUtf8("\n\nSignature ________________________________________")); + } +} + +// +// Returns one week of details data +// +QString Reportpanel::getWeekdetails(QDate Dayref, int nWeeks) +{ + QString Data; // Output string + QString Tempstring; // Temp churning + int nRows = m_pReptable->numRows(); + + // Find range boundaries + Q_ASSERT(nWeeks > 0); + QDate Tempdate; + QDate Firstday; + QDate Lastday; + Firstday = Dayref.addDays(Dayref.dayOfWeek() * -1 + 1); + Firstday = Firstday.addDays((nWeeks - 1) * -7); + Lastday = Firstday.addDays(7 * nWeeks); + + // Write some quick header text to the outgoing string + Data = trUtf8("\nDate Hours Account details\n"); + Data += QString("---------- ----- ----------------------------------------\n"); + + // Build the long week data string + for (int nIter = nRows - 1; nIter >= 0; nIter--) { + // Work on this tuple only if it within the reporting range + Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK); + Tempdate = QDate::fromString(m_pReptable->text(nIter, TITRAQ_IDXDATE), Qt::ISODate); + if (!Tempstring.isEmpty() && Firstday <= Tempdate && Tempdate < Lastday) { + Tempstring = m_pReptable->text(nIter, TITRAQ_IDXDATE); + if (!Tempstring.isEmpty()) + Data += Tempstring; + Tempstring = m_pReptable->text(nIter, TITRAQ_IDXAMOUNT); + if (!Tempstring.isEmpty()) + Data += QString(TITRAQ_SEPARATORTOK) + Tempstring; + Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK); + if (!Tempstring.isEmpty()) + Data += QString(TITRAQ_SEPARATORTOK) + Tempstring; + Data += QString("\n"); // Finish off line + } + } + + return Data; +} + +// +// Returns one week of totals data +// +QString Reportpanel::getWeektotals(QDate Dayref, int nWeeks) +{ + using namespace std; // Needed for maps and hash + map Hashtasks; // Hashtable to store tasks + multimap Hashhours; // Hashtable to store hours + map::iterator Taskiter; // Hashtable task iterator + multimap::iterator Houriter; // Hashtable hour iterator + + QString Totals; // Data totals to return for writing + QString Tempstring; // Temporary processing string + QDate Tempdate; // Temporary processing date + int nRows = m_pReptable->numRows(); + + // Find range boundaries + Q_ASSERT(nWeeks > 0); + QDate Firstday; + QDate Lastday; + Firstday = Dayref.addDays(Dayref.dayOfWeek() * -1 + 1); + Firstday = Firstday.addDays((nWeeks - 1) * -7); + Lastday = Firstday.addDays(7 * nWeeks); + + // Parse the table for interesting values + for (int nIter = 0; nIter < nRows; nIter++) { + // Work on this tuple only if it within the reporting range + Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK); + Tempdate = QDate::fromString(m_pReptable->text(nIter, TITRAQ_IDXDATE), Qt::ISODate); + if (!Tempstring.isEmpty() && Firstday <= Tempdate && Tempdate < Lastday) { + string Convstring = Tempstring; // Convert to string (can't cast?) + QTime Intable = QTime::fromString(m_pReptable->text(nIter, TITRAQ_IDXAMOUNT), Qt::ISODate); + int nTothours = QString(Hashtasks[Convstring]).section(':', 0, 0).toInt() + Intable.hour(); + int nTotminut = QString(Hashtasks[Convstring]).section(':', 1, 1).toInt() + Intable.minute(); + nTothours += nTotminut / 60; + nTotminut %= 60; + QString Hours = QString::number(nTothours).rightJustify(3, ' '); + QString Mins = QString::number(nTotminut).rightJustify(2, '0'); + string Timestring = Hours + ':' + Mins; // Convert to string (can't cast?) + Hashtasks[Convstring] = Timestring; // Finally store in hashtable + } + } + + // Reverse copy the tasks hashtable to both sort and index by amount key + for (Taskiter = Hashtasks.begin(); Taskiter != Hashtasks.end(); Taskiter++) + Hashhours.insert(pair(Taskiter->second, Taskiter->first)); + + // Write the actual data totals to the outgoing string in reverse order + for (Houriter = Hashhours.begin(); Houriter != Hashhours.end(); Houriter++) + Totals = Houriter->first + ' ' + Houriter->second + '\n' + Totals; + + // Write some quick header text to the outgoing string in reverse order + Totals = QString("------ ----------------------------------------\n") + Totals; + Totals = trUtf8("Total Account summary\n") + Totals; + + return Totals; // The outgoing string... its finally gone, let's go to bed +} + +// +// Returns one month of details data +// +QString Reportpanel::getMonthdetails(QDate Dayref, int nMonths) +{ + QString Data; // Output string + QString Tempstring; // Temp churning + QDate Tempdate; // For comparing + QDate Firstday; // Minimum boundary + QDate Lastday; // Maximum boundary + int nRows = m_pReptable->numRows(); + + // Find range boundaries + Q_ASSERT(nMonths > 0); + int nYear = Dayref.year(); + int nMonth = (Dayref.addMonths(nMonths * -1).month() + 12) % 12 + 1; + if (nMonth > Dayref.month()) + nYear--; + Firstday = QDate(nYear, nMonth, 1); + Lastday = QDate(Dayref.year(), Dayref.month(), Dayref.daysInMonth()); + + // Write some quick header text to the outgoing string + Data = trUtf8("\nDate Hours Account details\n"); + Data += QString("---------- ----- ----------------------------------------\n"); + + // Build the long week data string + for (int nIter = nRows - 1; nIter >= 0; nIter--) { + // Work on this tuple only if it within the reporting range + Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK); + Tempdate = QDate::fromString(m_pReptable->text(nIter, TITRAQ_IDXDATE), Qt::ISODate); + if (!Tempstring.isEmpty() && Firstday <= Tempdate && Tempdate < Lastday) { + Tempstring = m_pReptable->text(nIter, TITRAQ_IDXDATE); + if (!Tempstring.isEmpty()) + Data += Tempstring; + Tempstring = m_pReptable->text(nIter, TITRAQ_IDXAMOUNT); + if (!Tempstring.isEmpty()) + Data += QString(TITRAQ_SEPARATORTOK) + Tempstring; + Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK); + if (!Tempstring.isEmpty()) + Data += QString(TITRAQ_SEPARATORTOK) + Tempstring; + Data += trUtf8("\n"); // Finish off line + } + } + + return Data; +} + +// +// Returns one month of totals data +// +QString Reportpanel::getMonthtotals(QDate Dayref, int nMonths) +{ + using namespace std; // Needed for maps and hash + map Hashtasks; // Hashtable to store tasks + multimap Hashhours; // Hashtable to store hours + map::iterator Taskiter; // Hashtable task iterator + multimap::iterator Houriter; // Hashtable hour iterator + + QString Totals; // Data totals to return for writing + QString Tempstring; // Temporary processing string + QDate Tempdate; // Temporary processing date + int nRows = m_pReptable->numRows(); + + // Find range boundaries + Q_ASSERT(nMonths > 0); + int nYear = Dayref.year(); + int nMonth = (Dayref.addMonths(nMonths * -1).month() + 12) % 12 + 1; + if (nMonth > Dayref.month()) + nYear--; + QDate Firstday = QDate(nYear, nMonth, 1); + QDate Lastday = QDate(Dayref.year(), Dayref.month(), Dayref.daysInMonth()); + + // Parse the table for interesting values + for (int nIter = 0; nIter < nRows; nIter++) { + // Work on this tuple only if it within the reporting range + Tempstring = m_pReptable->text(nIter, TITRAQ_IDXTASK); + Tempdate = QDate::fromString(m_pReptable->text(nIter, TITRAQ_IDXDATE), Qt::ISODate); + if (!Tempstring.isEmpty() && Firstday <= Tempdate && Tempdate < Lastday) { + string Convstring = Tempstring; // Convert to string (can't cast?) + QTime Intable = QTime::fromString(m_pReptable->text(nIter, TITRAQ_IDXAMOUNT), Qt::ISODate); + int nTothours = QString(Hashtasks[Convstring]).section(':', 0, 0).toInt() + Intable.hour(); + int nTotminut = QString(Hashtasks[Convstring]).section(':', 1, 1).toInt() + Intable.minute(); + nTothours += nTotminut / 60; + nTotminut %= 60; + QString Hours = QString::number(nTothours).rightJustify(3, ' '); + QString Mins = QString::number(nTotminut).rightJustify(2, '0'); + string Timestring = Hours + ':' + Mins; // Convert to string (can't cast?) + Hashtasks[Convstring] = Timestring; // Finally store in hashtable + } + } + + // Reverse copy the tasks hashtable to both sort and index by amount key + for (Taskiter = Hashtasks.begin(); Taskiter != Hashtasks.end(); Taskiter++) + Hashhours.insert(pair(Taskiter->second, Taskiter->first)); + + // Write the actual data totals to the outgoing string in reverse order + for (Houriter = Hashhours.begin(); Houriter != Hashhours.end(); Houriter++) + Totals = Houriter->first + ' ' + Houriter->second + '\n' + Totals; + + // Write some quick header text to the outgoing string in reverse order + Totals = QString("------ ----------------------------------------\n") + Totals; + Totals = trUtf8("Total Account summary\n") + Totals; + + return Totals; // The outgoing string... its finally gone, let's go to bed +} + +// +// Saves the currently displayed local report +// +void Reportpanel::saveReport(void) +{ + int nResult = 0; // For checking user's answer + QFile Report; // The resulting report file + QString Filestring; // The user chosen file name to save + QString Openas = m_pReprefs->getString(TITRAQ_PREFHOME, TITRAQ_DEFHOME); + + // And then get the name of the selected file to save to + Filestring = QFileDialog::getSaveFileName(Openas, trUtf8("Text files (*.txt);;All Files (*)"), this, trUtf8("ChooserDialog"), trUtf8("Choose a file to save"), NULL, false); + if (!Filestring.isEmpty()) { + if (QFile::exists(Filestring)) { + nResult = QMessageBox::warning(this, QString(TITRAQ_APPTITLE) + + ' ' + asgui_version.v_short, trUtf8(TITRAQ_OVERWRITE), + trUtf8("&Yes"), trUtf8("&No"), NULL, 1, 1); + if (nResult = QMessageBox::Ok) { // Overwrite a file + Report.setName(Filestring); // User wished name + Report.open(IO_WriteOnly | IO_Truncate); // Open report file + QTextStream Outstream(&Report); // Convert to stream + Outstream << m_pBrowser->text(); // Write the data + Report.close(); // Finish by closing + } + } + else { // User gave a file name, and there was no preexisting file there + Report.setName(Filestring); // User wished name + Report.open(IO_WriteOnly | IO_Truncate); // Open report file + QTextStream Outstream(&Report); // Convert to stream + Outstream << m_pBrowser->text(); // Write the data + Report.close(); // Finish by closing + } + } + // Otherwise, user did not select a valid file and push okay button +} + +// +// Prints the currently displayed local report +// +void Reportpanel::printReport(void) +{ +#ifndef QT_NO_PRINTER + if (m_pPrinter->setup(this)) { // Opens printer dialog + m_pPrinter->setFullPage(true); // Set our own margins + QPainter Paint; // Our painter (for pages) + Paint.begin(m_pPrinter); // Paint on printer + Paint.setFont(m_pBrowser->font()); + QFontMetrics Fontmetrics = Paint.fontMetrics(); + QPaintDeviceMetrics Devmetrics(m_pPrinter); // Need width/height of printer surface + const int knMargin = Devmetrics.logicalDpiX() / 2; // Half-inch margin + int nYpos = knMargin; // Y position for each line + int nPageno = 1; // The starting page number + + for (int nIter = 0; nIter < m_pBrowser->lines() && !m_pPrinter->aborted(); nIter++) { + // See if there is some space on this page to paint on + if (nYpos + Fontmetrics.lineSpacing() > Devmetrics.height() - knMargin) { +// QString Printmsg(trUtf8("Printing page ")) +// + QString::number(++nPageno) + QString("..."); +// m_pStatus()->message(Printmsg); // Not in scope (crap) + if (!m_pPrinter->newPage()) // Start new page + break; // Some error + nYpos = knMargin; // Back to top of page + } + Paint.drawText(knMargin, nYpos, Devmetrics.width() - 2 * knMargin, + Fontmetrics.lineSpacing(), Qt::ExpandTabs, m_pBrowser->text(nIter)); + nYpos += Fontmetrics.lineSpacing(); + } + Paint.end(); // Send job to printer +// m_pStatus()->message(trUtf8("Printing completed"), 2000); // Not in scope + } +// m_pStatusBar()->message(trUtf8("Printing completed"), 2000); // Not in scope +#endif +} + +// +// Sets the strings of the subwidgets using the current language +// +void Reportpanel::textChange(void) +{ + this->setCaption(trUtf8("AS local report", "Local report using weekly or monthly data.")); + + // Top level push buttons associated with accept and save slots + m_pSavebutt->setText(trUtf8("Save As...", "Comment for Savebutton")); + QToolTip::add(m_pSavebutt, trUtf8("Saves the report text", "Comment for tooltip Savebutton")); + QWhatsThis::add(m_pSavebutt, trUtf8("The save button saves the report text to a file", "Comment for whatsThis Savebutton")); + m_pPrintbutt->setText(trUtf8("Print...", "Comment for Printbutton")); + QToolTip::add(m_pPrintbutt, trUtf8("Print the report text", "Comment for tooltip Printbutton")); + QWhatsThis::add(m_pPrintbutt, trUtf8("The print button prints the report text to a file", "Comment for whatsThis Printbutton")); + m_pDismissbutt->setText(trUtf8("Dismiss", "Comment for Dismissbutton")); + QToolTip::add(m_pDismissbutt, trUtf8("Closes the report panel", "Comment for tooltip Dismissbutton")); + QWhatsThis::add(m_pDismissbutt, trUtf8("The dismiss button dismisses the report panel", "Comment for whatsThis Dismissbutton")); + + // Inner tool buttons for new local report generation + m_pWeeklybutt->setText(trUtf8("Weekly", "Comment for Weeklybutt")); + QToolTip::add(m_pWeeklybutt, trUtf8("Hold down for options", "Comment for tooltip Weeklybutt")); + 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")); + m_pMonthlybutt->setText(trUtf8("Monthly", "Comment for Monthlybutt")); + QToolTip::add(m_pMonthlybutt, trUtf8("Hold down for options", "Comment for tooltip Monthlybutt")); + 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")); +} +} // namespace AS