kplato

kptdoublelistviewbase.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 "kptdoublelistviewbase.h"
00021 
00022 #include "kptproject.h"
00023 #include "kptview.h"
00024 
00025 #include <qheader.h>
00026 #include <qlayout.h>
00027 #include <qmap.h>
00028 #include <qpainter.h>
00029 #include <qpalette.h>
00030 #include <qptrvector.h>
00031 #include <qsplitter.h>
00032 #include <qstring.h>
00033 #include <qvaluelist.h>
00034 #include <qpoint.h>
00035 
00036 #include <kcalendarsystem.h>
00037 #include <kglobal.h>
00038 #include <klocale.h>
00039 #include <kprinter.h>
00040 #include <qrect.h>
00041 
00042 #include <kdebug.h>
00043 
00044 namespace KPlato
00045 {
00046 void ListView::paintToPrinter(QPainter * p, int cx, int cy, int cw, int ch) {
00047     //kdDebug()<<k_funcinfo<<QRect(cx, cy, cw, ch)<<endl;
00048     // draw header labels
00049     p->save();
00050     QRegion r = p->clipRegion(QPainter::CoordPainter);
00051     p->setClipRegion(r.intersect(QRegion(cx, 0, cw, ch)), QPainter::CoordPainter);
00052     QColor bgc(193, 223, 255);
00053     QBrush bg(bgc);
00054     p->setBackgroundMode(Qt::OpaqueMode);
00055     p->setBackgroundColor(bgc);
00056     QHeader *h = header();
00057     int hei = 0;
00058     for (int s = 0; s < h->count(); ++s) {
00059         QRect r = h->sectionRect(s);
00060         //kdDebug()<<s<<": "<<h->label(s)<<" "<<r<<endl;
00061         int x, y;
00062         viewportToContents(r.x(), r.y(), x, y);
00063         QRect sr(x, y, r.width(), r.height());
00064         //kdDebug()<<s<<": "<<h->label(s)<<" "<<sr<<endl;
00065         if (sr.x()+sr.width() <= cx || sr.x() >= cx+cw) {
00066             //kdDebug()<<s<<": "<<h->label(s)<<" "<<sr<<": continue"<<endl;
00067             continue;
00068         }
00069         QRect tr = sr;
00070         if (sr.x() < cx) {
00071             tr.setX(cx);
00072             //kdDebug()<<s<<": "<<h->label(s)<<" "<<tr<<endl;
00073         }
00074         p->eraseRect(tr);
00075         p->drawText(tr, columnAlignment(s)|Qt::AlignVCenter, h->label(s), -1);
00076         hei = QMAX(tr.height(), hei);
00077     }
00078     r = p->clipRegion(QPainter::CoordPainter);
00079     p->restore();
00080 //    p->drawRect(r.boundingRect());
00081     p->save();
00082     p->translate(0, hei+2);
00083     r = p->clipRegion(QPainter::CoordPainter);
00084     // FIXME: Doesn't clip correctly, haven't figured out why
00085     p->setClipRegion(r.intersect(QRegion(cx, cy, cw, ch)), QPainter::CoordPainter);
00086     drawContentsOffset(p, 0, 0, cx, cy, cw, ch);
00087 //    p->drawRect(r.boundingRect());
00088     p->restore();
00089 }
00090 
00091 DoubleListViewBase::SlaveListItem::SlaveListItem(DoubleListViewBase::MasterListItem *master, QListView *parent, QListViewItem *after, bool highlight)
00092     : KListViewItem(parent, after),
00093       m_masterItem(master),
00094       m_value(0.0),
00095       m_highlight(highlight),
00096       m_valueMap() {
00097     
00098     setFormat();
00099     setExpandable(master->isExpandable());
00100     setOpen(master->isOpen());
00101     //kdDebug()<<"DoubleListViewBase::SlaveListItem "<<master->text(0)<<" parent="<<static_cast<DoubleListViewBase::SlaveListItem*>(parent)->m_masterItem->text(0)<<endl;
00102 }
00103 DoubleListViewBase::SlaveListItem::SlaveListItem(DoubleListViewBase::MasterListItem *master, QListViewItem *parent, QListViewItem *after, bool highlight)
00104     : KListViewItem(parent, after),
00105       m_masterItem(master),
00106       m_value(0.0),
00107       m_highlight(highlight),
00108       m_valueMap() {
00109     
00110     setFormat();
00111     setExpandable(master->isExpandable());
00112     setOpen(master->isOpen());
00113     //kdDebug()<<"DoubleListViewBase::SlaveListItem "<<master->text(0)<<" parent="<<static_cast<DoubleListViewBase::SlaveListItem*>(parent)->m_masterItem->text(0)<<endl;
00114 }
00115 DoubleListViewBase::SlaveListItem::~SlaveListItem() {
00116     //kdDebug()<<k_funcinfo<<endl;
00117     if (m_masterItem)
00118         m_masterItem->slaveItemDeleted();
00119 }
00120 
00121 void DoubleListViewBase::SlaveListItem::clearColumn(int col) {
00122     if (col >= listView()->columns()) {
00123         return;
00124     }
00125     listView()->setColumnText(col, "");
00126     setText(col, "");
00127     m_valueMap[col] = 0;
00128 }
00129 void DoubleListViewBase::SlaveListItem::setColumn(int col, double value) {
00130     if (col < listView()->columns()) {
00131         //setText(col, QString("%1").arg(value, m_fieldwidth, m_fmt, m_prec));
00132         setText(col, KGlobal::locale()->formatNumber(value, m_prec));
00133         m_valueMap.replace(col, value);
00134         //kdDebug()<<k_funcinfo<<m_masterItem->text(0)<<": column["<<col<<"]="<<value<<endl;
00135     }
00136 }
00137 
00138 void DoubleListViewBase::SlaveListItem::setLimit(int col, double limit) {
00139     m_limitMap[col] = limit;
00140 }
00141 
00142 void DoubleListViewBase::SlaveListItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align) {
00143     //kdDebug()<<k_funcinfo<<"c="<<column<<endl;
00144     QColorGroup g = cg;
00145     if (m_highlight) {
00146         if (m_limitMap.contains(column)) {
00147             if (m_valueMap[column] > m_limitMap[column]) {
00148                 g.setColor(QColorGroup::Text, QColor(red));
00149             } else if (m_valueMap[column] < m_limitMap[column]) {
00150                 g.setColor(QColorGroup::Text, QColor(green));
00151             }
00152         }
00153     }
00154     KListViewItem::paintCell(p, g, column, width, align);
00155 }
00156 
00157 void DoubleListViewBase::SlaveListItem::setFormat(int fieldwidth, char fmt, int prec) {
00158     m_fieldwidth = fieldwidth;
00159     m_fmt = fmt;
00160     m_prec = prec;
00161 }
00162 
00163 //----------------------------
00164 DoubleListViewBase::MasterListItem::MasterListItem(QListView *parent, bool highlight)
00165     : KListViewItem(parent),
00166       m_slaveItem(0),
00167       m_value(0.0),
00168       m_limit(0.0),
00169       m_highlight(highlight) {
00170     
00171     setFormat();
00172     //kdDebug()<<k_funcinfo<<endl;
00173 }
00174 
00175 DoubleListViewBase::MasterListItem::MasterListItem(QListView *parent, QString text,   bool highlight)
00176     : KListViewItem(parent, text),
00177       m_slaveItem(0),
00178       m_value(0.0),
00179       m_limit(0.0),
00180       m_highlight(highlight) {
00181 
00182     setFormat();
00183     //kdDebug()<<k_funcinfo<<endl;
00184 }
00185 
00186 DoubleListViewBase::MasterListItem::MasterListItem(QListViewItem *parent, bool highlight)
00187     : KListViewItem(parent),
00188       m_slaveItem(0),
00189       m_value(0.0),
00190       m_limit(0.0),
00191       m_highlight(highlight) {
00192     
00193     setFormat();
00194     //kdDebug()<<k_funcinfo<<endl;
00195 }
00196 
00197 DoubleListViewBase::MasterListItem::MasterListItem(QListViewItem *parent, QString text,   bool highlight)
00198     : KListViewItem(parent, text),
00199       m_slaveItem(0),
00200       m_value(0.0),
00201       m_limit(0.0),
00202       m_highlight(highlight) {
00203 
00204     setFormat();
00205     //kdDebug()<<k_funcinfo<<endl;
00206 }
00207 
00208 DoubleListViewBase::MasterListItem::~MasterListItem() {
00209     if (m_slaveItem)
00210         m_slaveItem->masterItemDeleted();
00211 }
00212 
00213 void DoubleListViewBase::MasterListItem::createSlaveItems(QListView *lv, QListViewItem *after) {
00214     //kdDebug()<<k_funcinfo<<text(0)<<endl;
00215     if (m_slaveItem) {
00216         kdError()<<k_funcinfo<<"Slave item allready exists"<<endl;
00217     } else {
00218         if (parent() == 0) {
00219             m_slaveItem = new DoubleListViewBase::SlaveListItem(this, lv, after);
00220         } else {
00221             m_slaveItem = new DoubleListViewBase::SlaveListItem(this, static_cast<DoubleListViewBase::MasterListItem*>(parent())->m_slaveItem, after);
00222         }
00223     }
00224     DoubleListViewBase::SlaveListItem *prev = 0;
00225     for (QListViewItem *item = firstChild(); item; item = item->nextSibling()) {
00226         static_cast<DoubleListViewBase::MasterListItem*>(item)->createSlaveItems(lv, prev);
00227         prev = static_cast<DoubleListViewBase::MasterListItem*>(item)->m_slaveItem;
00228     }
00229 }
00230 
00231 void DoubleListViewBase::MasterListItem::setSlaveOpen(bool on) {
00232     if (m_slaveItem)
00233         m_slaveItem->setOpen(on);
00234 }
00235 
00236 void DoubleListViewBase::MasterListItem::slaveItemDeleted() {
00237     setTotal(0);
00238     m_slaveItem = 0;
00239 }
00240 
00241 void DoubleListViewBase::MasterListItem::setTotal(double tot) {
00242     m_value = tot;
00243     //setText(1, QString("%1").arg(tot, m_fieldwidth, m_fmt, m_prec));
00244     setText(1, KGlobal::locale()->formatNumber(tot, m_prec));
00245     //kdDebug()<<k_funcinfo<<text(0)<<"="<<tot<<endl;
00246 }
00247 
00248 void DoubleListViewBase::MasterListItem::addToTotal(double v) {
00249     m_value += v;
00250     //setText(1, QString("%1").arg(m_value, m_fieldwidth, m_fmt, m_prec));
00251     setText(1, KGlobal::locale()->formatNumber(m_value, m_prec));
00252 }
00253 
00254 double DoubleListViewBase::MasterListItem::calcTotal() {
00255     double tot=0.0;
00256     QListViewItem *item=firstChild();
00257     if (!item) {
00258         tot = m_value;
00259     } else {
00260         for (; item; item = item->nextSibling()) {
00261             tot += static_cast<DoubleListViewBase::MasterListItem*>(item)->calcTotal();
00262         }
00263     }
00264     setTotal(tot);
00265     return tot;
00266 }
00267 
00268 void DoubleListViewBase::MasterListItem::setSlaveItem(int col, double value) {
00269     if (m_slaveItem) {
00270         m_slaveItem->setColumn(col, value);
00271     }
00272 }
00273 
00274 void DoubleListViewBase::MasterListItem::clearColumn(int col) {
00275     for (QListViewItem *item=firstChild(); item; item=item->nextSibling()) {
00276         static_cast<DoubleListViewBase::MasterListItem*>(item)->clearColumn(col);
00277     }
00278     setTotal(0);
00279     if (m_slaveItem == 0) {
00280         kdError()<<k_funcinfo<<"No m_slaveItem"<<endl;
00281         return;
00282     }
00283     m_slaveItem->clearColumn(0);
00284 }
00285 
00286 void DoubleListViewBase::MasterListItem::calcSlaveItems() {
00287     if (m_slaveItem == 0 || m_slaveItem->listView() == 0) {
00288         kdError()<<k_funcinfo<<"No m_slaveItem or m_slaveItem->listView()"<<endl;
00289         return;
00290     }
00291     int cols = m_slaveItem->listView()->columns();
00292     for (int i = 0; i < cols; ++i) {
00293         calcSlaveItems(i);
00294     }
00295 }
00296 
00297 double DoubleListViewBase::MasterListItem::calcSlaveItems(int col) {
00298     if (m_slaveItem == 0)
00299         return 0.0;
00300     QListViewItem *item=firstChild();
00301     if (!item) {
00302         return m_slaveItem->value(col);
00303     }
00304     double tot=0.0;
00305     for (; item; item = item->nextSibling()) {
00306         tot += static_cast<DoubleListViewBase::MasterListItem*>(item)->calcSlaveItems(col);
00307     }
00308     //kdDebug()<<k_funcinfo<<text(0)<<" "<<col<<"="<<tot<<endl;
00309     setSlaveItem(col, tot);
00310     return tot;
00311 }
00312 
00313 void DoubleListViewBase::MasterListItem::setSlaveLimit(int col, double limit) {
00314     if (m_slaveItem) {
00315         m_slaveItem->setLimit(col, limit);
00316     }
00317 }
00318 
00319 void DoubleListViewBase::MasterListItem::setSlaveHighlight(bool on) {
00320     if (m_slaveItem) {
00321         m_slaveItem->setHighlight(on);
00322     }
00323 }
00324 
00325 void DoubleListViewBase::MasterListItem::paintCell(QPainter *p, const QColorGroup &cg, int column, int width, int align) {
00326     //kdDebug()<<k_funcinfo<<"c="<<column<<" value="<<m_value<<" limit="<<m_limit<<endl;
00327     QColorGroup g = cg;
00328     if (column == 1 && m_highlight) {
00329         if (m_value > m_limit) {
00330             g.setColor(QColorGroup::Text, QColor(red));
00331         } else if (m_value < m_limit) {
00332             g.setColor(QColorGroup::Text, QColor(green));
00333         }
00334     }
00335     KListViewItem::paintCell(p, g, column, width, align);
00336 }
00337 
00338 void DoubleListViewBase::MasterListItem::setFormat(int fieldwidth, char fmt, int prec) {
00339     m_fieldwidth = fieldwidth;
00340     m_fmt = fmt;
00341     m_prec = prec;
00342 }
00343 
00344 //-------------------------------------
00345 DoubleListViewBase::DoubleListViewBase(QWidget *parent, bool description)
00346     : QSplitter(parent),
00347       m_fieldwidth(0),
00348       m_fmt('f'),
00349       m_prec(0) {
00350     
00351     setOrientation(QSplitter::Horizontal);
00352     setHandleWidth(QMIN(2, handleWidth()));
00353     
00354     m_masterList = new ListView(this);
00355     m_masterList->setSelectionMode(QListView::NoSelection);
00356     m_masterList->setItemMargin(2);
00357     m_masterList->setRootIsDecorated(true);
00358 #if KDE_IS_VERSION(3,3,9)
00359     m_masterList->setShadeSortColumn(false);
00360 #endif
00361     m_masterList->setSortColumn(-1); // Disable sort!!
00362     m_masterList->addColumn(i18n("Name"));
00363     m_masterList->addColumn(i18n("Total"));
00364     m_masterList->setColumnAlignment(1, AlignRight);
00365     if (description) {
00366         m_masterList->addColumn(i18n("Description"));
00367         m_masterList->header()->moveSection(2, 1);
00368         m_masterList->header()->setStretchEnabled(true, 1);
00369     } else {
00370         m_masterList->header()->setStretchEnabled(true, 0);
00371     }
00372     m_masterList->setVScrollBarMode(QScrollView::AlwaysOff);
00373     m_masterList->setHScrollBarMode(QScrollView::AlwaysOn);
00374     
00375     m_slaveList = new ListView(this);
00376     m_slaveList->setSelectionMode(QListView::NoSelection);
00377     m_slaveList->setItemMargin(2);
00378     m_slaveList->setSortColumn(-1); // Disable sort!!
00379     m_slaveList->setTreeStepSize(0);
00380     m_slaveList->setHScrollBarMode(QScrollView::AlwaysOn);
00381     
00382     
00383     connect(m_slaveList->verticalScrollBar(), SIGNAL(valueChanged(int)),
00384             m_masterList->verticalScrollBar(), SLOT(setValue(int)));
00385     
00386     connect(m_masterList, SIGNAL(expanded(QListViewItem*)), SLOT(slotExpanded(QListViewItem*)));
00387     connect(m_masterList, SIGNAL(collapsed(QListViewItem*)), SLOT(slotCollapsed(QListViewItem*)));
00388     
00389 }
00390 
00391 QSize DoubleListViewBase::sizeHint() const {
00392     //kdDebug()<<k_funcinfo<<minimumSizeHint()<<endl;
00393     return minimumSizeHint();  //HACK: koshell splitter problem
00394 }
00395 
00396 void DoubleListViewBase::clearSlaveList() {
00397     while (m_slaveList->columns() > 0) {
00398         m_slaveList->removeColumn(0); // removing the last one clears the list!!!
00399     }
00400     m_slaveList->clear(); // to be safe
00401 }
00402 
00403 void DoubleListViewBase::createSlaveItems() {
00404     clearSlaveList();
00405     DoubleListViewBase::SlaveListItem *prev = 0;
00406     for (QListViewItem *item = m_masterList->firstChild(); item; item = item->nextSibling()) {
00407         static_cast<DoubleListViewBase::MasterListItem*>(item)->createSlaveItems(m_slaveList, prev);
00408         prev = static_cast<DoubleListViewBase::MasterListItem*>(item)->slaveItem();
00409     }
00410 }
00411 
00412 
00413 void DoubleListViewBase::print(KPrinter &printer) {
00414     kdDebug()<<k_funcinfo<<endl;
00415     Q_UNUSED(printer);
00416 }
00417 
00418 void DoubleListViewBase::setOpen(QListViewItem *item, bool open) {
00419     //kdDebug()<<k_funcinfo<<endl;
00420     m_masterList->setOpen(item, open);
00421 }
00422 
00423 void DoubleListViewBase::slotExpanded(QListViewItem* item) {
00424     //kdDebug()<<k_funcinfo<<endl;
00425     if (item) {
00426         static_cast<DoubleListViewBase::MasterListItem*>(item)->setSlaveOpen(true);
00427     }
00428 }
00429 
00430 void DoubleListViewBase::slotCollapsed(QListViewItem*item) {
00431     //kdDebug()<<k_funcinfo<<endl;
00432     if (item) {
00433         static_cast<DoubleListViewBase::MasterListItem*>(item)->setSlaveOpen(false);
00434     }
00435 }
00436 
00437 void DoubleListViewBase::setDescriptionHeader(QString text) {
00438     m_masterList->setColumnText(1, text);
00439 }
00440 
00441 void DoubleListViewBase::setNameHeader(QString text) {
00442     m_masterList->setColumnText(0, text);
00443 }
00444 
00445 void DoubleListViewBase::setTotalHeader(QString text) {
00446     m_masterList->setColumnText(2, text);
00447 }
00448 
00449 void DoubleListViewBase::addSlaveColumn(QString text) {
00450     m_slaveList->addColumn(text);
00451     m_slaveList->setColumnAlignment(m_slaveList->columns()-1, AlignRight);
00452 }
00453 
00454 void DoubleListViewBase::calculate() {
00455     for (QListViewItem *lvi=m_masterList->firstChild(); lvi; lvi = lvi->nextSibling()) {
00456         static_cast<DoubleListViewBase::MasterListItem *>(lvi)->calcSlaveItems();
00457         static_cast<DoubleListViewBase::MasterListItem *>(lvi)->calcTotal();
00458     }
00459 }
00460 
00461 void DoubleListViewBase::clearLists() {
00462     m_slaveList->clear();
00463     m_masterList->clear();
00464 }
00465 
00466 void DoubleListViewBase::setMasterFormat(int fieldwidth, char fmt, int prec) {
00467     QListViewItemIterator it = m_masterList;
00468     for (; it.current(); ++it) {
00469         static_cast<DoubleListViewBase::MasterListItem*>(it.current())->setFormat(fieldwidth, fmt, prec);
00470     }
00471 }
00472 void DoubleListViewBase::setSlaveFormat(int fieldwidth, char fmt, int prec) {
00473     QListViewItemIterator it = m_slaveList;
00474     for (; it.current(); ++it) {
00475         static_cast<DoubleListViewBase::SlaveListItem*>(it.current())->setFormat(fieldwidth, fmt, prec);
00476     }
00477 }
00478 
00479 void DoubleListViewBase::setFormat(int fieldwidth, char fmt, int prec) {
00480     m_fieldwidth = fieldwidth;
00481     m_fmt = fmt;
00482     m_prec = prec;
00483     setMasterFormat(fieldwidth, fmt, prec);
00484     setSlaveFormat(fieldwidth, fmt, prec);
00485 }
00486 
00487 void DoubleListViewBase::paintContents(QPainter *p) {
00488     //kdDebug()<<k_funcinfo<<endl;
00489     QRect cm = m_masterList->contentsRect();
00490     QRect cs = m_slaveList->contentsRect();
00491     int mx, my, sx, sy;
00492     m_masterList->contentsToViewport(cm.x(), cm.y(), mx, my);
00493     m_slaveList->contentsToViewport(cs.x(), cs.y(), sx, sy);
00494     if (sizes()[0] > 0) {
00495         p->save();
00496         p->translate(mx, my);
00497         m_masterList->paintToPrinter(p, -mx, -my, cm.width(), cm.height());
00498         p->restore();
00499     }
00500     if (sizes()[1] > 0) {
00501         p->save();
00502         p->translate(cm.width() + 8 + sx, sy);
00503         m_slaveList->paintToPrinter(p, -sx, -sy, cs.width(), cs.height());
00504         //p->fillRect(-8, 0, 0, sy, Qt::white);
00505         p->restore();
00506     }
00507 }
00508 
00509 }  //KPlato namespace
00510 
00511 #include "kptdoublelistviewbase.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys