/* This file is part of the KDE project Copyright (C) 2005 Dag Andersen kplato@kde.org> This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; version 2 of the License. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kptaccountsview.h" #include "kptaccountsviewconfigdialog.h" #include "kptcontext.h" #include "kptdatetime.h" #include "kptproject.h" #include "kptview.h" #include "kpteffortcostmap.h" #include <tqapplication.h> #include <tqcombobox.h> #include <tqdatetime.h> #include <tqdatetimeedit.h> #include <tqheader.h> #include <tqlabel.h> #include <tqlayout.h> #include <tqpainter.h> #include <tqpalette.h> #include <tqpushbutton.h> #include <tqvaluelist.h> #include <tqpopupmenu.h> #include <tqsizepolicy.h> #include <tqhbox.h> #include <tqpaintdevicemetrics.h> #include <kcalendarsystem.h> #include <tdeglobal.h> #include <tdelistview.h> #include <tdelocale.h> #include <kprinter.h> #include <kdebug.h> namespace KPlato { class Label : public TQLabel { public: Label(TQWidget *w) : TQLabel(w) {} void paintContents(TQPainter *p) { drawContents(p); } }; AccountsView::AccountItem::AccountItem(Account *a, TQListView *parent, bool highlight) : DoubleListViewBase::MasterListItem(parent, a->name(), highlight), account(a) { if (parent->columns() >= 3) { setText(2, a->description()); } //kdDebug()<<k_funcinfo<<endl; } AccountsView::AccountItem::AccountItem(Account *a, TQListViewItem *p, bool highlight) : DoubleListViewBase::MasterListItem(p, a->name(), highlight), account(a) { if (listView() && listView()->columns() >= 3) { setText(2, a->description()); } //kdDebug()<<k_funcinfo<<endl; } AccountsView::AccountItem::AccountItem(TQString text, Account *a, TQListViewItem *parent, bool highlight) : DoubleListViewBase::MasterListItem(parent, text, highlight), account(a) { //kdDebug()<<k_funcinfo<<endl; } void AccountsView::AccountItem::add(int col, const TQDate &date, const EffortCost &ec) { EffortCost &cm = costMap.add(date, ec); if (m_slaveItem) m_slaveItem->setText(col, TDEGlobal::locale()->formatMoney(cm.cost(), "", 0)); } AccountsView::AccountsView(Project &project, View *view, TQWidget *parent) : TQWidget(parent, "Accounts view"), m_mainview(view), m_project(project), m_accounts(project.accounts()) { m_date = TQDate::currentDate(); m_period = 0; m_periodTexts<<i18n("Day")<<i18n("Week")<<i18n("Month"); m_cumulative = false; TQVBoxLayout *lay1 = new TQVBoxLayout(this, 0, KDialog::spacingHint()); TQHBoxLayout *lay2 = new TQHBoxLayout(0, 0, KDialog::spacingHint()); m_label = new Label(this); m_label->setFrameShape(TQLabel::StyledPanel); m_label->setFrameShadow(TQLabel::Sunken); m_label->setAlignment(int(TQLabel::WordBreak | TQLabel::AlignVCenter)); lay2->addWidget(m_label); m_changeBtn = new TQPushButton(i18n("Configure..."), this); m_changeBtn->setSizePolicy(TQSizePolicy((TQSizePolicy::SizeType)0, (TQSizePolicy::SizeType)0, 0, 0, m_changeBtn->sizePolicy().hasHeightForWidth())); lay2->addWidget(m_changeBtn); lay1->addLayout(lay2); m_dlv = new DoubleListViewBase(this, true); m_dlv->setNameHeader(i18n("Account")); init(); lay1->addWidget(m_dlv); connect(this, TQT_SIGNAL(update()), TQT_SLOT(slotUpdate())); connect(m_changeBtn, TQT_SIGNAL(clicked()), TQT_SLOT(slotConfigure())); TQValueList<int> list = m_dlv->sizes(); int tot = list[0] + list[1]; list[0] = TQMIN(35, tot); list[1] = tot-list[0]; m_dlv->setSizes(list); } void AccountsView::zoom(double zoom) { Q_UNUSED(zoom); } void AccountsView::init() { m_date = TQDate::currentDate(); m_period = 0; initAccList(m_accounts.accountList()); } void AccountsView::draw() { //kdDebug()<<k_funcinfo<<endl; Context::Accountsview context; getContextClosedItems(context, m_dlv->masterListView()->firstChild()); initAccList(m_accounts.accountList()); setContextClosedItems(context); slotUpdate(); } void AccountsView::initAccList(const AccountList &list) { m_dlv->clearLists(); AccountListIterator it = list; for (it.toLast(); it.current(); --it) { AccountsView::AccountItem *a = new AccountsView::AccountItem(it.current(), m_dlv->masterListView()); a->setOpen(true); a->setExpandable(!it.current()->isElement()); initAccSubItems(it.current(), a); } createPeriods(); } void AccountsView::initAccSubItems(Account *acc, AccountsView::AccountItem *parent) { if (!acc->accountList().isEmpty()) { /* AccountsView::AccountItem *a = new AccountsView::AccountItem(i18n("Subaccounts"), acc, parent); DoubleListViewBase::SlaveListItem *i = new DoubleListViewBase::SlaveListItem(a, parent->period); a->period = i;*/ initAccList(acc->accountList(), parent); } // AccountsView::AccountItem *a = new AccountsView::AccountItem(i18n("Variance"), acc, parent, true); // DoubleListViewBase::SlaveListItem *i = new DoubleListViewBase::SlaveListItem(a, parent->period, true); // a->period = i; // // a = new AccountsView::AccountItem(i18n("Actual"), acc, parent); // i = new DoubleListViewBase::SlaveListItem(a, parent->period); // a->period = i; // // a = new AccountsView::AccountItem(i18n("Planned"), acc, parent); // i = new DoubleListViewBase::SlaveListItem(a, parent->period); // a->period = i; } void AccountsView::initAccList(const AccountList &list, AccountsView::AccountItem *parent) { AccountListIterator it = list; for (it.toLast(); it.current(); --it) { AccountsView::AccountItem *a = new AccountsView::AccountItem(it.current(), parent); a->setOpen(true); a->setExpandable(!it.current()->isElement()); initAccSubItems(it.current(), a); } } void AccountsView::clearPeriods() { m_dlv->clearSlaveList(); } void AccountsView::createPeriods() { m_dlv->createSlaveItems(); } void AccountsView::slotUpdate() { //kdDebug()<<k_funcinfo<<endl; TQApplication::setOverrideCursor(TQt::waitCursor); createPeriods(); TDELocale *locale = TDEGlobal::locale(); const KCalendarSystem *cal = locale->calendar(); TQString t; if (m_cumulative) { t += " <b>" + i18n("Cumulative") + "</b> "; } t += i18n("Cut-off date:%1").arg("<b>" + locale->formatDate(m_date, true) + "</b>"); t += " " + i18n("Periodicity:%1").arg("<b>" + periodText(m_period) + "</b>"); m_label->setText(t); // Add columns for selected period/periods TQDate start = m_project.startTime().date(); TQDate end = m_date; //kdDebug()<<k_funcinfo<<start.toString()<<" - "<<end.toString()<<endl; int c=0; if (m_period == 0) { //Daily for (TQDate dt = start; dt <= end; dt = cal->addDays(dt, 1), ++c) { TQString df = locale->formatDate(dt, true); m_dlv->addSlaveColumn(df); } TQListViewItemIterator it(m_dlv->masterListView()); for (;it.current(); ++it) { AccountsView::AccountItem *item = dynamic_cast<AccountsView::AccountItem*>(it.current()); if (!item || !item->account || !item->account->isElement()) { continue; } item->costMap = m_accounts.plannedCost(*(item->account), start, end); double cost = 0.0; int col=0; for (TQDate d=start; d <= end; d = cal->addDays(d, 1), ++col) { EffortCost &ec = item->costMap.effortCostOnDate(d); cost = (m_cumulative ? cost + ec.cost() : ec.cost()); item->setSlaveItem(col, cost); m_cumulative ? item->setTotal(cost) : item->addToTotal(cost); } } m_dlv->calculate(); TQApplication::restoreOverrideCursor(); return; } if (m_period == 1) { //Weekly //TODO make this user controlled int weekStartDay = locale->weekStartDay(); TQDate dt = start; TQDate pend = cal->addDays(dt, 7 + weekStartDay - 1 - cal->dayOfWeek(dt)); for (; pend <= end; ++c) { //kdDebug()<<k_funcinfo<<c<<": "<<dt<<"-"<<pend<<" : "<<end<<endl; int y; int w = cal->weekNumber(dt, &y); TQString t = i18n("<week>-<year>", "%1-%2").arg(w).arg(y); m_dlv->addSlaveColumn(t); dt = pend.addDays(1); pend = cal->addDays(pend, 7); if ((pend.year() == end.year()) && (pend.weekNumber() == end.weekNumber())) { pend = end; } } if (c == 0) { TQApplication::restoreOverrideCursor(); return; } TQListViewItemIterator it(m_dlv->masterListView()); for (;it.current(); ++it) { AccountsView::AccountItem *item = dynamic_cast<AccountsView::AccountItem*>(it.current()); if (!item || !item->account || !item->account->isElement()) { continue; } item->costMap = m_accounts.plannedCost(*(item->account), start, end); double cost = 0.0; TQDate d = start; TQDate pend = cal->addDays(d, 7 + weekStartDay - 1 - cal->dayOfWeek(d)); for (int col=0; pend <= end; ++col) { double cst = item->costMap.cost(d, d.daysTo(pend)+1); cost = (m_cumulative ? cost + cst : cst); item->setSlaveItem(col, cost); m_cumulative ? item->setTotal(cost) : item->addToTotal(cost); d = pend.addDays(1); // 1. next week pend = cal->addDays(pend, 7); if ((pend.year() == end.year()) && (pend.weekNumber() == end.weekNumber())) { pend = end; } } } m_dlv->calculate(); TQApplication::restoreOverrideCursor(); return; } if (m_period == 2) { //Monthly //TODO make this user controlled TQDate dt = start; TQDate pend; cal->setYMD(pend, dt.year(), dt.month(), dt.daysInMonth()); for (; pend <= end; ++c) { //kdDebug()<<k_funcinfo<<c<<": "<<dt<<"-"<<pend<<" : "<<end<<endl; TQString m = cal->monthName(dt, true) + TQString(" %1").arg( dt.year()); m_dlv->addSlaveColumn(m); dt = pend.addDays(1); // 1. next month pend = cal->addDays(pend, dt.daysInMonth()); if ((pend.year() == end.year()) && (pend.month() == end.month())) { pend = end; } } if (c == 0) { TQApplication::restoreOverrideCursor(); return; } TQListViewItemIterator it(m_dlv->masterListView()); for (;it.current(); ++it) { AccountsView::AccountItem *item = dynamic_cast<AccountsView::AccountItem*>(it.current()); if (!item || !item->account || !item->account->isElement()) { continue; } item->costMap = m_accounts.plannedCost(*(item->account), start, end); double cost = 0.0; TQDate d = start; cal->setYMD(pend, d.year(), d.month(), d.daysInMonth()); for (int col=0; pend <= end; ++col) { double cst = item->costMap.cost(d, d.daysTo(pend)+1); cost = (m_cumulative ? cost + cst : cst); item->setSlaveItem(col, cost); m_cumulative ? item->setTotal(cost) : item->addToTotal(cost); d = pend.addDays(1); // 1. next month pend = cal->addDays(pend, d.daysInMonth()); if ((pend.year() == end.year()) && (pend.month() == end.month())) { pend = end; } } } m_dlv->calculate(); TQApplication::restoreOverrideCursor(); return; } TQApplication::restoreOverrideCursor(); } void AccountsView::print(KPrinter &printer) { //kdDebug()<<k_funcinfo<<endl; TQPaintDeviceMetrics m = TQPaintDeviceMetrics ( &printer ); uint top, left, bottom, right; printer.margins(&top, &left, &bottom, &right); //kdDebug()<<m.width()<<"x"<<m.height()<<" : "<<top<<", "<<left<<", "<<bottom<<", "<<right<<" : "<<size()<<endl; TQPainter p; p.begin(&printer); p.setViewport(left, top, m.width()-left-right, m.height()-top-bottom); p.setClipRect(left, top, m.width()-left-right, m.height()-top-bottom); TQRect preg = p.clipRegion(TQPainter::CoordPainter).boundingRect(); //kdDebug()<<"p="<<preg<<endl; //p.drawRect(preg.x(), preg.y(), preg.width()-1, preg.height()-1); double scale = TQMIN((double)preg.width()/(double)size().width(), (double)preg.height()/(double)(size().height())); //kdDebug()<<"scale="<<scale<<endl; if (scale < 1.0) { p.scale(scale, scale); } m_label->paintContents(&p); p.translate(0, m_label->size().height()); m_dlv->paintContents(&p); p.end(); } bool AccountsView::setContext(Context::Accountsview &context) { //kdDebug()<<k_funcinfo<<"---->"<<endl; TQValueList<int> list; list << context.accountsviewsize << context.periodviewsize; //m_dlv->setSizes(list); //NOTE: This doesn't always work! m_date = context.date; if (!m_date.isValid()) m_date = TQDate::currentDate(); m_period = context.period; m_cumulative = context.cumulative; setContextClosedItems(context); //kdDebug()<<k_funcinfo<<"<----"<<endl; return true; } void AccountsView::setContextClosedItems(Context::Accountsview &context) { for (TQStringList::ConstIterator it = context.closedItems.begin(); it != context.closedItems.end(); ++it) { if (m_accounts.findAccount(*it)) { TQListViewItemIterator lit(m_dlv->masterListView()); for (; lit.current(); ++lit) { if (lit.current()->text(0) == (*it)) { m_dlv->setOpen(lit.current(), false); break; } } } } } void AccountsView::getContext(Context::Accountsview &context) const { //kdDebug()<<k_funcinfo<<endl; context.accountsviewsize = m_dlv->sizes()[0]; context.periodviewsize = m_dlv->sizes()[1]; context.date = m_date; context.period = m_period; context.cumulative = m_cumulative; //kdDebug()<<k_funcinfo<<"sizes="<<sizes()[0]<<","<<sizes()[1]<<endl; getContextClosedItems(context, m_dlv->masterListView()->firstChild()); } void AccountsView::getContextClosedItems(Context::Accountsview &context, TQListViewItem *item) const { if (item == 0) return; for (TQListViewItem *i = item; i; i = i->nextSibling()) { if (!i->isOpen()) { context.closedItems.append(i->text(0)); //kdDebug()<<k_funcinfo<<"add closed "<<i->text(0)<<endl; } getContextClosedItems(context, i->firstChild()); } } void AccountsView::slotConfigure() { //kdDebug()<<k_funcinfo<<endl; AccountsviewConfigDialog *dia = new AccountsviewConfigDialog(m_date, m_period, m_periodTexts, m_cumulative, this); if (dia->exec()) { m_date = dia->date(); m_period = dia->period(); m_cumulative = dia->isCumulative(); emit update(); } delete dia; } TQString AccountsView::periodText(int offset) { TQString s; TQStringList::const_iterator it = m_periodTexts.at(offset); if (it != m_periodTexts.constEnd()) { s = (*it); } return s; } } //KPlato namespace #include "kptaccountsview.moc"