kplato

kptaccountsview.cc

00001 /* This file is part of the KDE project
00002    Copyright (C) 2005 Dag Andersen kplato@kde.org>
00003 
00004    This library is free software; you can redistribute it and/or
00005    modify it under the terms of the GNU Library General Public
00006    License as published by the Free Software Foundation;
00007    version 2 of the License.
00008 
00009    This library is distributed in the hope that it will be useful,
00010    but WITHOUT ANY WARRANTY; without even the implied warranty of
00011    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012    Library General Public License for more details.
00013 
00014    You should have received a copy of the GNU Library General Public License
00015    along with this library; see the file COPYING.LIB.  If not, write to
00016    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017    Boston, MA 02110-1301, USA.
00018 */
00019 
00020 #include "kptaccountsview.h"
00021 
00022 #include "kptaccountsviewconfigdialog.h"
00023 #include "kptcontext.h"
00024 #include "kptdatetime.h"
00025 #include "kptproject.h"
00026 #include "kptview.h"
00027 #include "kpteffortcostmap.h"
00028 
00029 #include <qapplication.h>
00030 #include <qcombobox.h>
00031 #include <qdatetime.h>
00032 #include <qdatetimeedit.h>
00033 #include <qheader.h>
00034 #include <qlabel.h>
00035 #include <qlayout.h>
00036 #include <qpainter.h>
00037 #include <qpalette.h>
00038 #include <qpushbutton.h>
00039 #include <qvaluelist.h>
00040 #include <qpopupmenu.h>
00041 #include <qsizepolicy.h>
00042 #include <qhbox.h>
00043 #include <qpaintdevicemetrics.h>
00044 
00045 #include <kcalendarsystem.h>
00046 #include <kglobal.h>
00047 #include <klistview.h>
00048 #include <klocale.h>
00049 #include <kprinter.h>
00050 
00051 #include <kdebug.h>
00052 
00053 namespace KPlato
00054 {
00055 
00056 class Label : public QLabel
00057 {
00058 public:
00059     Label(QWidget *w)
00060     : QLabel(w)
00061     {}
00062     void paintContents(QPainter *p) {
00063         drawContents(p);
00064     }
00065 };
00066 
00067 AccountsView::AccountItem::AccountItem(Account *a, QListView *parent, bool highlight)
00068     : DoubleListViewBase::MasterListItem(parent, a->name(), highlight),
00069       account(a) {
00070     if (parent->columns() >= 3) {
00071         setText(2, a->description());
00072     }
00073     //kdDebug()<<k_funcinfo<<endl;
00074 }
00075 AccountsView::AccountItem::AccountItem(Account *a, QListViewItem *p, bool highlight)
00076     : DoubleListViewBase::MasterListItem(p, a->name(), highlight),
00077       account(a) {
00078     if (listView() && listView()->columns() >= 3) {
00079         setText(2, a->description());
00080     }
00081     //kdDebug()<<k_funcinfo<<endl;
00082 }
00083 
00084 AccountsView::AccountItem::AccountItem(QString text, Account *a, QListViewItem *parent, bool highlight)
00085     : DoubleListViewBase::MasterListItem(parent, text, highlight),
00086       account(a) {
00087     //kdDebug()<<k_funcinfo<<endl;
00088 }
00089 
00090 void AccountsView::AccountItem::add(int col, const QDate &date, const EffortCost &ec) {
00091     EffortCost &cm = costMap.add(date, ec);
00092     if (m_slaveItem)
00093         m_slaveItem->setText(col, KGlobal::locale()->formatMoney(cm.cost(), "", 0));
00094 }
00095 
00096 AccountsView::AccountsView(Project &project, View *view, QWidget *parent)
00097     : QWidget(parent, "Accounts view"),
00098       m_mainview(view),
00099       m_project(project),
00100       m_accounts(project.accounts()) {
00101     
00102     m_date = QDate::currentDate();
00103     m_period = 0;
00104     m_periodTexts<<i18n("Day")<<i18n("Week")<<i18n("Month");
00105     m_cumulative = false;
00106 
00107     QVBoxLayout *lay1 = new QVBoxLayout(this, 0, KDialog::spacingHint());
00108     
00109     QHBoxLayout *lay2 = new QHBoxLayout(0, 0, KDialog::spacingHint());
00110     m_label = new Label(this);
00111     m_label->setFrameShape(QLabel::StyledPanel);
00112     m_label->setFrameShadow(QLabel::Sunken);
00113     m_label->setAlignment(int(QLabel::WordBreak | QLabel::AlignVCenter));
00114     lay2->addWidget(m_label);
00115     m_changeBtn = new QPushButton(i18n("Configure..."), this);
00116     m_changeBtn->setSizePolicy(QSizePolicy((QSizePolicy::SizeType)0, (QSizePolicy::SizeType)0, 0, 0, m_changeBtn->sizePolicy().hasHeightForWidth()));
00117     lay2->addWidget(m_changeBtn);
00118     lay1->addLayout(lay2);
00119 
00120     m_dlv = new DoubleListViewBase(this, true);
00121     m_dlv->setNameHeader(i18n("Account"));
00122     
00123     init();
00124     
00125     lay1->addWidget(m_dlv);
00126     
00127     connect(this, SIGNAL(update()), SLOT(slotUpdate()));
00128     connect(m_changeBtn, SIGNAL(clicked()), SLOT(slotConfigure()));
00129     
00130     QValueList<int> list = m_dlv->sizes();
00131     int tot = list[0] + list[1];
00132     list[0] = QMIN(35, tot);
00133     list[1] = tot-list[0];
00134     m_dlv->setSizes(list);
00135 }
00136 
00137 void AccountsView::zoom(double zoom) {
00138     Q_UNUSED(zoom);
00139 }
00140 
00141 void AccountsView::init() {
00142     m_date = QDate::currentDate();
00143     m_period = 0;
00144     initAccList(m_accounts.accountList());
00145 }
00146 
00147 void AccountsView::draw() {
00148     //kdDebug()<<k_funcinfo<<endl;
00149     Context::Accountsview context;
00150     getContextClosedItems(context, m_dlv->masterListView()->firstChild());
00151     initAccList(m_accounts.accountList());
00152     setContextClosedItems(context);
00153     slotUpdate();
00154 }
00155 
00156 void AccountsView::initAccList(const AccountList &list) {
00157     m_dlv->clearLists();
00158     AccountListIterator it = list;
00159     for (it.toLast(); it.current(); --it) {
00160         AccountsView::AccountItem *a = new AccountsView::AccountItem(it.current(), m_dlv->masterListView());
00161         a->setOpen(true);
00162         a->setExpandable(!it.current()->isElement());
00163         initAccSubItems(it.current(), a);
00164     }
00165     createPeriods();
00166 }
00167 
00168 void AccountsView::initAccSubItems(Account *acc, AccountsView::AccountItem *parent) {
00169     if (!acc->accountList().isEmpty()) {
00170 /*        AccountsView::AccountItem *a = new AccountsView::AccountItem(i18n("Subaccounts"), acc, parent);
00171         DoubleListViewBase::SlaveListItem *i = new DoubleListViewBase::SlaveListItem(a, parent->period);
00172         a->period = i;*/
00173     
00174         initAccList(acc->accountList(), parent);
00175     }
00176 //     AccountsView::AccountItem *a = new AccountsView::AccountItem(i18n("Variance"), acc, parent, true);
00177 //     DoubleListViewBase::SlaveListItem *i = new DoubleListViewBase::SlaveListItem(a, parent->period, true);
00178 //     a->period = i;
00179 // 
00180 //     a = new AccountsView::AccountItem(i18n("Actual"), acc, parent);
00181 //     i = new DoubleListViewBase::SlaveListItem(a, parent->period);
00182 //     a->period = i;
00183 // 
00184 //     a = new AccountsView::AccountItem(i18n("Planned"), acc, parent);
00185 //     i = new DoubleListViewBase::SlaveListItem(a, parent->period);
00186 //     a->period = i;
00187 
00188 }
00189 
00190 void AccountsView::initAccList(const AccountList &list, AccountsView::AccountItem *parent) {
00191     AccountListIterator it = list;
00192     for (it.toLast(); it.current(); --it) {
00193         AccountsView::AccountItem *a = new AccountsView::AccountItem(it.current(), parent);
00194         a->setOpen(true);
00195         a->setExpandable(!it.current()->isElement());
00196         initAccSubItems(it.current(), a);
00197     }
00198 }
00199 
00200 void AccountsView::clearPeriods() {
00201     m_dlv->clearSlaveList();
00202 }
00203 
00204 void AccountsView::createPeriods() {
00205     m_dlv->createSlaveItems();
00206 }
00207 
00208 void AccountsView::slotUpdate() {
00209     //kdDebug()<<k_funcinfo<<endl;
00210     QApplication::setOverrideCursor(Qt::waitCursor);
00211     createPeriods();
00212     KLocale *locale = KGlobal::locale();
00213     const KCalendarSystem *cal = locale->calendar();
00214     
00215     QString t;
00216     if (m_cumulative) {
00217         t += " <b>" + i18n("Cumulative") + "</b>  ";
00218     }
00219     t += i18n("Cut-off date:%1").arg("<b>" + locale->formatDate(m_date, true) + "</b>");
00220     t += " " + i18n("Periodicity:%1").arg("<b>" + periodText(m_period) + "</b>");
00221     m_label->setText(t);
00222     
00223     // Add columns for selected period/periods
00224     QDate start = m_project.startTime().date();
00225     QDate end = m_date;
00226     //kdDebug()<<k_funcinfo<<start.toString()<<" - "<<end.toString()<<endl;
00227     int c=0;
00228     if (m_period == 0) { //Daily
00229         for (QDate dt = start; dt <= end; dt = cal->addDays(dt, 1), ++c) {
00230             QString df = locale->formatDate(dt, true);
00231             m_dlv->addSlaveColumn(df);
00232         }
00233         QListViewItemIterator it(m_dlv->masterListView());
00234         for (;it.current(); ++it) {
00235             AccountsView::AccountItem *item = dynamic_cast<AccountsView::AccountItem*>(it.current());
00236             if (!item || !item->account || !item->account->isElement()) {
00237                 continue;
00238             }
00239             item->costMap = m_accounts.plannedCost(*(item->account), start, end);
00240             double cost = 0.0;
00241             int col=0;
00242             for (QDate d=start; d <= end; d = cal->addDays(d, 1), ++col) {
00243                 EffortCost &ec = item->costMap.effortCostOnDate(d);
00244                 cost = (m_cumulative ? cost + ec.cost() : ec.cost());
00245                 item->setSlaveItem(col, cost);
00246                 m_cumulative ? item->setTotal(cost) : item->addToTotal(cost);
00247             }
00248         }
00249         m_dlv->calculate();
00250         QApplication::restoreOverrideCursor();
00251         return;
00252     }
00253     if (m_period == 1) { //Weekly
00254         //TODO make this user controlled
00255         int weekStartDay = locale->weekStartDay();
00256 
00257         QDate dt = start;
00258         QDate pend = cal->addDays(dt, 7 + weekStartDay - 1 - cal->dayOfWeek(dt));
00259         for (; pend <= end; ++c) {
00260             //kdDebug()<<k_funcinfo<<c<<": "<<dt<<"-"<<pend<<" : "<<end<<endl;
00261             int y;
00262             int w = cal->weekNumber(dt, &y);
00263             QString t = i18n("<week>-<year>", "%1-%2").arg(w).arg(y);
00264             m_dlv->addSlaveColumn(t);
00265             dt = pend.addDays(1);
00266             pend = cal->addDays(pend, 7);
00267             if ((pend.year() == end.year()) && (pend.weekNumber() == end.weekNumber())) {
00268                 pend = end;
00269             }
00270         }
00271         if (c == 0) {
00272             QApplication::restoreOverrideCursor();
00273             return;
00274         }
00275         QListViewItemIterator it(m_dlv->masterListView());
00276         for (;it.current(); ++it) {
00277             AccountsView::AccountItem *item = dynamic_cast<AccountsView::AccountItem*>(it.current());
00278             if (!item || !item->account || !item->account->isElement()) {
00279                 continue;
00280             }
00281             item->costMap = m_accounts.plannedCost(*(item->account), start, end);
00282             double cost = 0.0;
00283             QDate d = start;
00284             QDate pend = cal->addDays(d, 7 + weekStartDay - 1 - cal->dayOfWeek(d));
00285             for (int col=0; pend <= end; ++col) {
00286                 double cst = item->costMap.cost(d, d.daysTo(pend)+1);
00287                 cost = (m_cumulative ? cost + cst : cst);
00288                 item->setSlaveItem(col, cost);
00289                 m_cumulative ? item->setTotal(cost) : item->addToTotal(cost);
00290                 d = pend.addDays(1); // 1. next week
00291                 pend = cal->addDays(pend, 7);
00292                 if ((pend.year() == end.year()) && (pend.weekNumber() == end.weekNumber())) {
00293                     pend = end;
00294                 }
00295             }
00296         }
00297         m_dlv->calculate();
00298         QApplication::restoreOverrideCursor();
00299         return;
00300     }
00301     if (m_period == 2) { //Monthly
00302         //TODO make this user controlled
00303         QDate dt = start;
00304         QDate pend; 
00305         cal->setYMD(pend, dt.year(), dt.month(), dt.daysInMonth());
00306         for (; pend <= end; ++c) {
00307             //kdDebug()<<k_funcinfo<<c<<": "<<dt<<"-"<<pend<<" : "<<end<<endl;
00308             QString m = cal->monthName(dt, true) + QString(" %1").arg( dt.year());
00309             m_dlv->addSlaveColumn(m);
00310         
00311             dt = pend.addDays(1); // 1. next month
00312             pend = cal->addDays(pend, dt.daysInMonth());
00313             if ((pend.year() == end.year()) && (pend.month() == end.month())) {
00314                 pend = end;
00315             }
00316         }
00317         if (c == 0) {
00318             QApplication::restoreOverrideCursor();
00319             return;
00320         }
00321         QListViewItemIterator it(m_dlv->masterListView());
00322         for (;it.current(); ++it) {
00323             AccountsView::AccountItem *item = dynamic_cast<AccountsView::AccountItem*>(it.current());
00324             if (!item || !item->account || !item->account->isElement()) {
00325                 continue;
00326             }
00327             item->costMap = m_accounts.plannedCost(*(item->account), start, end);
00328             double cost = 0.0;
00329             QDate d = start;
00330             cal->setYMD(pend, d.year(), d.month(), d.daysInMonth());
00331             for (int col=0; pend <= end; ++col) {
00332                 double cst = item->costMap.cost(d, d.daysTo(pend)+1);
00333                 cost = (m_cumulative ? cost + cst : cst);
00334                 item->setSlaveItem(col, cost);
00335                 m_cumulative ? item->setTotal(cost) : item->addToTotal(cost);
00336                 d = pend.addDays(1); // 1. next month
00337                 pend = cal->addDays(pend, d.daysInMonth());
00338                 if ((pend.year() == end.year()) && (pend.month() == end.month())) {
00339                     pend = end;
00340                 }
00341             }
00342         }
00343         m_dlv->calculate();
00344         QApplication::restoreOverrideCursor();
00345         return;
00346     }
00347     QApplication::restoreOverrideCursor();
00348 }
00349 
00350 void AccountsView::print(KPrinter &printer) {
00351     //kdDebug()<<k_funcinfo<<endl;
00352     QPaintDeviceMetrics m = QPaintDeviceMetrics ( &printer );
00353     uint top, left, bottom, right;
00354     printer.margins(&top, &left, &bottom, &right);
00355     //kdDebug()<<m.width()<<"x"<<m.height()<<" : "<<top<<", "<<left<<", "<<bottom<<", "<<right<<" : "<<size()<<endl;
00356     QPainter p;
00357     p.begin(&printer);
00358     p.setViewport(left, top, m.width()-left-right, m.height()-top-bottom);
00359     p.setClipRect(left, top, m.width()-left-right, m.height()-top-bottom);
00360     QRect preg = p.clipRegion(QPainter::CoordPainter).boundingRect();
00361     //kdDebug()<<"p="<<preg<<endl;
00362     //p.drawRect(preg.x(), preg.y(), preg.width()-1, preg.height()-1);
00363     double scale = QMIN((double)preg.width()/(double)size().width(), (double)preg.height()/(double)(size().height()));
00364     //kdDebug()<<"scale="<<scale<<endl;
00365     if (scale < 1.0) {
00366         p.scale(scale, scale);
00367     }
00368     m_label->paintContents(&p);
00369     p.translate(0, m_label->size().height());
00370     m_dlv->paintContents(&p);
00371     p.end();
00372 }
00373 
00374 bool AccountsView::setContext(Context::Accountsview &context) {
00375     //kdDebug()<<k_funcinfo<<"---->"<<endl;
00376     QValueList<int> list;
00377     list << context.accountsviewsize << context.periodviewsize;
00378     //m_dlv->setSizes(list); //NOTE: This doesn't always work!
00379     m_date = context.date;
00380     if (!m_date.isValid())
00381         m_date = QDate::currentDate();
00382     m_period = context.period;
00383     m_cumulative = context.cumulative;
00384     setContextClosedItems(context);
00385     //kdDebug()<<k_funcinfo<<"<----"<<endl;
00386     return true;
00387 }
00388 
00389 void AccountsView::setContextClosedItems(Context::Accountsview &context) {
00390     for (QStringList::ConstIterator it = context.closedItems.begin(); it != context.closedItems.end(); ++it) {
00391         if (m_accounts.findAccount(*it)) {
00392             QListViewItemIterator lit(m_dlv->masterListView());
00393             for (; lit.current(); ++lit) {
00394                 if (lit.current()->text(0) == (*it)) {
00395                     m_dlv->setOpen(lit.current(), false);
00396                     break;
00397                 }
00398             }
00399         }
00400     }
00401 }
00402 
00403 void AccountsView::getContext(Context::Accountsview &context) const {
00404     //kdDebug()<<k_funcinfo<<endl;
00405     context.accountsviewsize = m_dlv->sizes()[0];
00406     context.periodviewsize = m_dlv->sizes()[1];
00407     context.date = m_date;
00408     context.period = m_period;
00409     context.cumulative = m_cumulative;
00410     //kdDebug()<<k_funcinfo<<"sizes="<<sizes()[0]<<","<<sizes()[1]<<endl;
00411     
00412     getContextClosedItems(context, m_dlv->masterListView()->firstChild());
00413 }
00414 
00415 
00416 void AccountsView::getContextClosedItems(Context::Accountsview &context, QListViewItem *item) const {
00417     if (item == 0)
00418         return;
00419     for (QListViewItem *i = item; i; i = i->nextSibling()) {
00420         if (!i->isOpen()) {
00421             context.closedItems.append(i->text(0));
00422             //kdDebug()<<k_funcinfo<<"add closed "<<i->text(0)<<endl;
00423         }
00424         getContextClosedItems(context, i->firstChild());
00425     }
00426 }
00427 
00428 void AccountsView::slotConfigure() {
00429     //kdDebug()<<k_funcinfo<<endl;
00430     AccountsviewConfigDialog *dia = new AccountsviewConfigDialog(m_date, m_period, m_periodTexts, m_cumulative, this);
00431     if (dia->exec()) {
00432         m_date = dia->date();
00433         m_period = dia->period();
00434         m_cumulative = dia->isCumulative();
00435         emit update();
00436     }
00437     delete dia;
00438 }
00439 
00440 QString AccountsView::periodText(int offset) {
00441     QString s;
00442     QStringList::const_iterator it = m_periodTexts.at(offset);
00443     if (it != m_periodTexts.constEnd()) {
00444         s = (*it);
00445     }
00446     return s;
00447 }
00448 
00449 }  //KPlato namespace
00450 
00451 #include "kptaccountsview.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys