OSSP CVS Repository

ossp - ossp-pkg/as/as-gui/as_reportpanel.cpp
Not logged in
[Honeypot]  [Browse]  [Directory]  [Home]  [Login
[Reports]  [Search]  [Ticket]  [Timeline
  [Raw

ossp-pkg/as/as-gui/as_reportpanel.cpp
//
//  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 <rse@engelschall.com>
//  Copyright (c) 2002-2004 Michael Schloh von Bennewitz <michael@schloh.com>
//  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 <qvariant.h>
#include <qpushbutton.h>
#include <qtextedit.h>
#include <qtoolbutton.h>
#include <qbuttongroup.h>
#include <qpopupmenu.h>
#include <qlayout.h>
#include <qtooltip.h>
#include <qwhatsthis.h>
#include <qtextstream.h>
#include <qfiledialog.h>
#include <qprinter.h>
#include <qpaintdevicemetrics.h>
#include <qpainter.h>
#include <qfile.h>
#include <qdir.h>

#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<string, string> Hashtasks;                  // Hashtable to store tasks
    multimap<string, string> Hashhours;             // Hashtable to store hours
    map<string, string>::iterator Taskiter;         // Hashtable task iterator
    multimap<string, string>::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<string, string>(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<string, string> Hashtasks;                  // Hashtable to store tasks
    multimap<string, string> Hashhours;             // Hashtable to store hours
    map<string, string>::iterator Taskiter;         // Hashtable task iterator
    multimap<string, string>::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<string, string>(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

CVSTrac 2.0.1