kplato

kptdoublelistviewbase.cpp
1/* This file is part of the KDE project
2 Copyright (C) 2005 Dag Andersen kplato@kde.org>
3
4 This library is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Library General Public
6 License as published by the Free Software Foundation;
7 version 2 of the License.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Library General Public License for more details.
13
14 You should have received a copy of the GNU Library General Public License
15 along with this library; see the file COPYING.LIB. If not, write to
16 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 Boston, MA 02110-1301, USA.
18*/
19
20#include "kptdoublelistviewbase.h"
21
22#include "kptproject.h"
23#include "kptview.h"
24
25#include <tqheader.h>
26#include <tqlayout.h>
27#include <tqmap.h>
28#include <tqpainter.h>
29#include <tqpalette.h>
30#include <tqptrvector.h>
31#include <tqsplitter.h>
32#include <tqstring.h>
33#include <tqvaluelist.h>
34#include <tqpoint.h>
35
36#include <kcalendarsystem.h>
37#include <tdeglobal.h>
38#include <tdelocale.h>
39#include <kprinter.h>
40#include <tqrect.h>
41
42#include <kdebug.h>
43
44namespace KPlato
45{
46void ListView::paintToPrinter(TQPainter * p, int cx, int cy, int cw, int ch) {
47 //kdDebug()<<k_funcinfo<<TQRect(cx, cy, cw, ch)<<endl;
48 // draw header labels
49 p->save();
50 TQRegion r = p->clipRegion(TQPainter::CoordPainter);
51 p->setClipRegion(r.intersect(TQRegion(cx, 0, cw, ch)), TQPainter::CoordPainter);
52 TQColor bgc(193, 223, 255);
53 TQBrush bg(bgc);
54 p->setBackgroundMode(TQt::OpaqueMode);
55 p->setBackgroundColor(bgc);
56 TQHeader *h = header();
57 int hei = 0;
58 for (int s = 0; s < h->count(); ++s) {
59 TQRect r = h->sectionRect(s);
60 //kdDebug()<<s<<": "<<h->label(s)<<" "<<r<<endl;
61 int x, y;
62 viewportToContents(r.x(), r.y(), x, y);
63 TQRect sr(x, y, r.width(), r.height());
64 //kdDebug()<<s<<": "<<h->label(s)<<" "<<sr<<endl;
65 if (sr.x()+sr.width() <= cx || sr.x() >= cx+cw) {
66 //kdDebug()<<s<<": "<<h->label(s)<<" "<<sr<<": continue"<<endl;
67 continue;
68 }
69 TQRect tr = sr;
70 if (sr.x() < cx) {
71 tr.setX(cx);
72 //kdDebug()<<s<<": "<<h->label(s)<<" "<<tr<<endl;
73 }
74 p->eraseRect(tr);
75 p->drawText(tr, columnAlignment(s)|TQt::AlignVCenter, h->label(s), -1);
76 hei = TQMAX(tr.height(), hei);
77 }
78 r = p->clipRegion(TQPainter::CoordPainter);
79 p->restore();
80// p->drawRect(r.boundingRect());
81 p->save();
82 p->translate(0, hei+2);
83 r = p->clipRegion(TQPainter::CoordPainter);
84 // FIXME: Doesn't clip correctly, haven't figured out why
85 p->setClipRegion(r.intersect(TQRegion(cx, cy, cw, ch)), TQPainter::CoordPainter);
86 drawContentsOffset(p, 0, 0, cx, cy, cw, ch);
87// p->drawRect(r.boundingRect());
88 p->restore();
89}
90
91DoubleListViewBase::SlaveListItem::SlaveListItem(DoubleListViewBase::MasterListItem *master, TQListView *parent, TQListViewItem *after, bool highlight)
92 : TDEListViewItem(parent, after),
93 m_masterItem(master),
94 m_value(0.0),
95 m_highlight(highlight),
96 m_valueMap() {
97
98 setFormat();
99 setExpandable(master->isExpandable());
100 setOpen(master->isOpen());
101 //kdDebug()<<"DoubleListViewBase::SlaveListItem "<<master->text(0)<<" parent="<<static_cast<DoubleListViewBase::SlaveListItem*>(parent)->m_masterItem->text(0)<<endl;
102}
103DoubleListViewBase::SlaveListItem::SlaveListItem(DoubleListViewBase::MasterListItem *master, TQListViewItem *parent, TQListViewItem *after, bool highlight)
104 : TDEListViewItem(parent, after),
105 m_masterItem(master),
106 m_value(0.0),
107 m_highlight(highlight),
108 m_valueMap() {
109
110 setFormat();
111 setExpandable(master->isExpandable());
112 setOpen(master->isOpen());
113 //kdDebug()<<"DoubleListViewBase::SlaveListItem "<<master->text(0)<<" parent="<<static_cast<DoubleListViewBase::SlaveListItem*>(parent)->m_masterItem->text(0)<<endl;
114}
115DoubleListViewBase::SlaveListItem::~SlaveListItem() {
116 //kdDebug()<<k_funcinfo<<endl;
117 if (m_masterItem)
118 m_masterItem->slaveItemDeleted();
119}
120
121void DoubleListViewBase::SlaveListItem::clearColumn(int col) {
122 if (col >= listView()->columns()) {
123 return;
124 }
125 listView()->setColumnText(col, "");
126 setText(col, "");
127 m_valueMap[col] = 0;
128}
129void DoubleListViewBase::SlaveListItem::setColumn(int col, double value) {
130 if (col < listView()->columns()) {
131 //setText(col, TQString("%1").arg(value, m_fieldwidth, m_fmt, m_prec));
132 setText(col, TDEGlobal::locale()->formatNumber(value, m_prec));
133 m_valueMap.replace(col, value);
134 //kdDebug()<<k_funcinfo<<m_masterItem->text(0)<<": column["<<col<<"]="<<value<<endl;
135 }
136}
137
138void DoubleListViewBase::SlaveListItem::setLimit(int col, double limit) {
139 m_limitMap[col] = limit;
140}
141
142void DoubleListViewBase::SlaveListItem::paintCell(TQPainter *p, const TQColorGroup &cg, int column, int width, int align) {
143 //kdDebug()<<k_funcinfo<<"c="<<column<<endl;
144 TQColorGroup g = cg;
145 if (m_highlight) {
146 if (m_limitMap.contains(column)) {
147 if (m_valueMap[column] > m_limitMap[column]) {
148 g.setColor(TQColorGroup::Text, TQColor(red));
149 } else if (m_valueMap[column] < m_limitMap[column]) {
150 g.setColor(TQColorGroup::Text, TQColor(green));
151 }
152 }
153 }
154 TDEListViewItem::paintCell(p, g, column, width, align);
155}
156
157void DoubleListViewBase::SlaveListItem::setFormat(int fieldwidth, char fmt, int prec) {
158 m_fieldwidth = fieldwidth;
159 m_fmt = fmt;
160 m_prec = prec;
161}
162
163//----------------------------
164DoubleListViewBase::MasterListItem::MasterListItem(TQListView *parent, bool highlight)
165 : TDEListViewItem(parent),
166 m_slaveItem(0),
167 m_value(0.0),
168 m_limit(0.0),
169 m_highlight(highlight) {
170
171 setFormat();
172 //kdDebug()<<k_funcinfo<<endl;
173}
174
175DoubleListViewBase::MasterListItem::MasterListItem(TQListView *parent, TQString text, bool highlight)
176 : TDEListViewItem(parent, text),
177 m_slaveItem(0),
178 m_value(0.0),
179 m_limit(0.0),
180 m_highlight(highlight) {
181
182 setFormat();
183 //kdDebug()<<k_funcinfo<<endl;
184}
185
186DoubleListViewBase::MasterListItem::MasterListItem(TQListViewItem *parent, bool highlight)
187 : TDEListViewItem(parent),
188 m_slaveItem(0),
189 m_value(0.0),
190 m_limit(0.0),
191 m_highlight(highlight) {
192
193 setFormat();
194 //kdDebug()<<k_funcinfo<<endl;
195}
196
197DoubleListViewBase::MasterListItem::MasterListItem(TQListViewItem *parent, TQString text, bool highlight)
198 : TDEListViewItem(parent, text),
199 m_slaveItem(0),
200 m_value(0.0),
201 m_limit(0.0),
202 m_highlight(highlight) {
203
204 setFormat();
205 //kdDebug()<<k_funcinfo<<endl;
206}
207
208DoubleListViewBase::MasterListItem::~MasterListItem() {
209 if (m_slaveItem)
210 m_slaveItem->masterItemDeleted();
211}
212
213void DoubleListViewBase::MasterListItem::createSlaveItems(TQListView *lv, TQListViewItem *after) {
214 //kdDebug()<<k_funcinfo<<text(0)<<endl;
215 if (m_slaveItem) {
216 kdError()<<k_funcinfo<<"Slave item allready exists"<<endl;
217 } else {
218 if (parent() == 0) {
219 m_slaveItem = new DoubleListViewBase::SlaveListItem(this, lv, after);
220 } else {
221 m_slaveItem = new DoubleListViewBase::SlaveListItem(this, static_cast<DoubleListViewBase::MasterListItem*>(parent())->m_slaveItem, after);
222 }
223 }
224 DoubleListViewBase::SlaveListItem *prev = 0;
225 for (TQListViewItem *item = firstChild(); item; item = item->nextSibling()) {
226 static_cast<DoubleListViewBase::MasterListItem*>(item)->createSlaveItems(lv, prev);
227 prev = static_cast<DoubleListViewBase::MasterListItem*>(item)->m_slaveItem;
228 }
229}
230
231void DoubleListViewBase::MasterListItem::setSlaveOpen(bool on) {
232 if (m_slaveItem)
233 m_slaveItem->setOpen(on);
234}
235
236void DoubleListViewBase::MasterListItem::slaveItemDeleted() {
237 setTotal(0);
238 m_slaveItem = 0;
239}
240
241void DoubleListViewBase::MasterListItem::setTotal(double tot) {
242 m_value = tot;
243 //setText(1, TQString("%1").arg(tot, m_fieldwidth, m_fmt, m_prec));
244 setText(1, TDEGlobal::locale()->formatNumber(tot, m_prec));
245 //kdDebug()<<k_funcinfo<<text(0)<<"="<<tot<<endl;
246}
247
248void DoubleListViewBase::MasterListItem::addToTotal(double v) {
249 m_value += v;
250 //setText(1, TQString("%1").arg(m_value, m_fieldwidth, m_fmt, m_prec));
251 setText(1, TDEGlobal::locale()->formatNumber(m_value, m_prec));
252}
253
254double DoubleListViewBase::MasterListItem::calcTotal() {
255 double tot=0.0;
256 TQListViewItem *item=firstChild();
257 if (!item) {
258 tot = m_value;
259 } else {
260 for (; item; item = item->nextSibling()) {
261 tot += static_cast<DoubleListViewBase::MasterListItem*>(item)->calcTotal();
262 }
263 }
264 setTotal(tot);
265 return tot;
266}
267
268void DoubleListViewBase::MasterListItem::setSlaveItem(int col, double value) {
269 if (m_slaveItem) {
270 m_slaveItem->setColumn(col, value);
271 }
272}
273
274void DoubleListViewBase::MasterListItem::clearColumn(int col) {
275 for (TQListViewItem *item=firstChild(); item; item=item->nextSibling()) {
276 static_cast<DoubleListViewBase::MasterListItem*>(item)->clearColumn(col);
277 }
278 setTotal(0);
279 if (m_slaveItem == 0) {
280 kdError()<<k_funcinfo<<"No m_slaveItem"<<endl;
281 return;
282 }
283 m_slaveItem->clearColumn(0);
284}
285
286void DoubleListViewBase::MasterListItem::calcSlaveItems() {
287 if (m_slaveItem == 0 || m_slaveItem->listView() == 0) {
288 kdError()<<k_funcinfo<<"No m_slaveItem or m_slaveItem->listView()"<<endl;
289 return;
290 }
291 int cols = m_slaveItem->listView()->columns();
292 for (int i = 0; i < cols; ++i) {
293 calcSlaveItems(i);
294 }
295}
296
297double DoubleListViewBase::MasterListItem::calcSlaveItems(int col) {
298 if (m_slaveItem == 0)
299 return 0.0;
300 TQListViewItem *item=firstChild();
301 if (!item) {
302 return m_slaveItem->value(col);
303 }
304 double tot=0.0;
305 for (; item; item = item->nextSibling()) {
306 tot += static_cast<DoubleListViewBase::MasterListItem*>(item)->calcSlaveItems(col);
307 }
308 //kdDebug()<<k_funcinfo<<text(0)<<" "<<col<<"="<<tot<<endl;
309 setSlaveItem(col, tot);
310 return tot;
311}
312
313void DoubleListViewBase::MasterListItem::setSlaveLimit(int col, double limit) {
314 if (m_slaveItem) {
315 m_slaveItem->setLimit(col, limit);
316 }
317}
318
319void DoubleListViewBase::MasterListItem::setSlaveHighlight(bool on) {
320 if (m_slaveItem) {
321 m_slaveItem->setHighlight(on);
322 }
323}
324
325void DoubleListViewBase::MasterListItem::paintCell(TQPainter *p, const TQColorGroup &cg, int column, int width, int align) {
326 //kdDebug()<<k_funcinfo<<"c="<<column<<" value="<<m_value<<" limit="<<m_limit<<endl;
327 TQColorGroup g = cg;
328 if (column == 1 && m_highlight) {
329 if (m_value > m_limit) {
330 g.setColor(TQColorGroup::Text, TQColor(red));
331 } else if (m_value < m_limit) {
332 g.setColor(TQColorGroup::Text, TQColor(green));
333 }
334 }
335 TDEListViewItem::paintCell(p, g, column, width, align);
336}
337
338void DoubleListViewBase::MasterListItem::setFormat(int fieldwidth, char fmt, int prec) {
339 m_fieldwidth = fieldwidth;
340 m_fmt = fmt;
341 m_prec = prec;
342}
343
344//-------------------------------------
345DoubleListViewBase::DoubleListViewBase(TQWidget *parent, bool description)
346 : TQSplitter(parent),
347 m_fieldwidth(0),
348 m_fmt('f'),
349 m_prec(0) {
350
351 setOrientation(TQt::Horizontal);
352 setHandleWidth(TQMIN(2, handleWidth()));
353
354 m_masterList = new ListView(this);
355 m_masterList->setSelectionMode(TQListView::NoSelection);
356 m_masterList->setItemMargin(2);
357 m_masterList->setRootIsDecorated(true);
358#if KDE_IS_VERSION(3,3,9)
359 m_masterList->setShadeSortColumn(false);
360#endif
361 m_masterList->setSortColumn(-1); // Disable sort!!
362 m_masterList->addColumn(i18n("Name"));
363 m_masterList->addColumn(i18n("Total"));
364 m_masterList->setColumnAlignment(1, AlignRight);
365 if (description) {
366 m_masterList->addColumn(i18n("Description"));
367 m_masterList->header()->moveSection(2, 1);
368 m_masterList->header()->setStretchEnabled(true, 1);
369 } else {
370 m_masterList->header()->setStretchEnabled(true, 0);
371 }
372 m_masterList->setVScrollBarMode(TQScrollView::AlwaysOff);
373 m_masterList->setHScrollBarMode(TQScrollView::AlwaysOn);
374
375 m_slaveList = new ListView(this);
376 m_slaveList->setSelectionMode(TQListView::NoSelection);
377 m_slaveList->setItemMargin(2);
378 m_slaveList->setSortColumn(-1); // Disable sort!!
379 m_slaveList->setTreeStepSize(0);
380 m_slaveList->setHScrollBarMode(TQScrollView::AlwaysOn);
381
382
383 connect(m_slaveList->verticalScrollBar(), TQ_SIGNAL(valueChanged(int)),
384 m_masterList->verticalScrollBar(), TQ_SLOT(setValue(int)));
385
386 connect(m_masterList, TQ_SIGNAL(expanded(TQListViewItem*)), TQ_SLOT(slotExpanded(TQListViewItem*)));
387 connect(m_masterList, TQ_SIGNAL(collapsed(TQListViewItem*)), TQ_SLOT(slotCollapsed(TQListViewItem*)));
388
389}
390
391TQSize DoubleListViewBase::sizeHint() const {
392 //kdDebug()<<k_funcinfo<<minimumSizeHint()<<endl;
393 return minimumSizeHint(); //HACK: koshell splitter problem
394}
395
396void DoubleListViewBase::clearSlaveList() {
397 while (m_slaveList->columns() > 0) {
398 m_slaveList->removeColumn(0); // removing the last one clears the list!!!
399 }
400 m_slaveList->clear(); // to be safe
401}
402
403void DoubleListViewBase::createSlaveItems() {
404 clearSlaveList();
405 DoubleListViewBase::SlaveListItem *prev = 0;
406 for (TQListViewItem *item = m_masterList->firstChild(); item; item = item->nextSibling()) {
407 static_cast<DoubleListViewBase::MasterListItem*>(item)->createSlaveItems(m_slaveList, prev);
408 prev = static_cast<DoubleListViewBase::MasterListItem*>(item)->slaveItem();
409 }
410}
411
412
413void DoubleListViewBase::print(KPrinter &printer) {
414 kdDebug()<<k_funcinfo<<endl;
415 Q_UNUSED(printer);
416}
417
418void DoubleListViewBase::setOpen(TQListViewItem *item, bool open) {
419 //kdDebug()<<k_funcinfo<<endl;
420 m_masterList->setOpen(item, open);
421}
422
423void DoubleListViewBase::slotExpanded(TQListViewItem* item) {
424 //kdDebug()<<k_funcinfo<<endl;
425 if (item) {
426 static_cast<DoubleListViewBase::MasterListItem*>(item)->setSlaveOpen(true);
427 }
428}
429
430void DoubleListViewBase::slotCollapsed(TQListViewItem*item) {
431 //kdDebug()<<k_funcinfo<<endl;
432 if (item) {
433 static_cast<DoubleListViewBase::MasterListItem*>(item)->setSlaveOpen(false);
434 }
435}
436
437void DoubleListViewBase::setDescriptionHeader(TQString text) {
438 m_masterList->setColumnText(1, text);
439}
440
441void DoubleListViewBase::setNameHeader(TQString text) {
442 m_masterList->setColumnText(0, text);
443}
444
445void DoubleListViewBase::setTotalHeader(TQString text) {
446 m_masterList->setColumnText(2, text);
447}
448
449void DoubleListViewBase::addSlaveColumn(TQString text) {
450 m_slaveList->addColumn(text);
451 m_slaveList->setColumnAlignment(m_slaveList->columns()-1, AlignRight);
452}
453
454void DoubleListViewBase::calculate() {
455 for (TQListViewItem *lvi=m_masterList->firstChild(); lvi; lvi = lvi->nextSibling()) {
456 static_cast<DoubleListViewBase::MasterListItem *>(lvi)->calcSlaveItems();
457 static_cast<DoubleListViewBase::MasterListItem *>(lvi)->calcTotal();
458 }
459}
460
461void DoubleListViewBase::clearLists() {
462 m_slaveList->clear();
463 m_masterList->clear();
464}
465
466void DoubleListViewBase::setMasterFormat(int fieldwidth, char fmt, int prec) {
467 TQListViewItemIterator it = m_masterList;
468 for (; it.current(); ++it) {
469 static_cast<DoubleListViewBase::MasterListItem*>(it.current())->setFormat(fieldwidth, fmt, prec);
470 }
471}
472void DoubleListViewBase::setSlaveFormat(int fieldwidth, char fmt, int prec) {
473 TQListViewItemIterator it = m_slaveList;
474 for (; it.current(); ++it) {
475 static_cast<DoubleListViewBase::SlaveListItem*>(it.current())->setFormat(fieldwidth, fmt, prec);
476 }
477}
478
479void DoubleListViewBase::setFormat(int fieldwidth, char fmt, int prec) {
480 m_fieldwidth = fieldwidth;
481 m_fmt = fmt;
482 m_prec = prec;
483 setMasterFormat(fieldwidth, fmt, prec);
484 setSlaveFormat(fieldwidth, fmt, prec);
485}
486
487void DoubleListViewBase::paintContents(TQPainter *p) {
488 //kdDebug()<<k_funcinfo<<endl;
489 TQRect cm = m_masterList->contentsRect();
490 TQRect cs = m_slaveList->contentsRect();
491 int mx, my, sx, sy;
492 m_masterList->contentsToViewport(cm.x(), cm.y(), mx, my);
493 m_slaveList->contentsToViewport(cs.x(), cs.y(), sx, sy);
494 if (sizes()[0] > 0) {
495 p->save();
496 p->translate(mx, my);
497 m_masterList->paintToPrinter(p, -mx, -my, cm.width(), cm.height());
498 p->restore();
499 }
500 if (sizes()[1] > 0) {
501 p->save();
502 p->translate(cm.width() + 8 + sx, sy);
503 m_slaveList->paintToPrinter(p, -sx, -sy, cs.width(), cs.height());
504 //p->fillRect(-8, 0, 0, sy, TQt::white);
505 p->restore();
506 }
507}
508
509} //KPlato namespace
510
511#include "kptdoublelistviewbase.moc"