* move Qt 3 support to subdirs which need it
[kdenetwork.git] / kppp / logview / monthly.cpp
blob7fed57fc574358d92ff3a7192d916e1ce1f7bdfb
1 /*
2 * kPPPlogview: a accounting log system for kPPP
4 * Copyright (C) 1998 Mario Weilguni <mweilguni@kde.org>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
16 * You should have received a copy of the GNU Library General Public
17 * License along with this program; if not, write to the Free
18 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 #include <qpainter.h>
22 #include <qcombobox.h>
23 #include <qfile.h>
24 #include <q3header.h>
26 #include <kcalendarsystem.h>
27 #include <klocale.h>
28 #include <kglobal.h>
29 #include <k3listview.h>
30 #include <kdebug.h>
31 #include <kmessagebox.h>
32 #include <kdialogbuttonbox.h>
34 #include "monthly.h"
35 #include "export.h"
36 #include <qstringlist.h>
38 static void formatBytes(int bytes, QString &result) {
39 if(bytes < 1024)
40 result.setNum(bytes);
41 else if(bytes < 1024*1024)
42 result = i18n("%1 KiB", KGlobal::locale()->formatNumber((float)bytes / 1024.0, 1));
43 else
44 result = i18n("%1 MiB", KGlobal::locale()->formatNumber((float)bytes / 1024.0 / 1024.0, 1));
47 static void formatBytesMonth(int bytes, QString &result) {
49 int day, days;
50 day = QDate::currentDate().day();
51 days = QDate::currentDate().daysInMonth();
53 bytes = (bytes / day) * days;
55 if(bytes < 1024)
56 result.setNum(bytes);
57 else if(bytes < 1024*1024)
58 result = i18n("%1 KiB", KGlobal::locale()->formatNumber((float)bytes / 1024.0, 1));
59 else
60 result = i18n("%1 MiB", KGlobal::locale()->formatNumber((float)bytes / 1024.0 / 1024.0, 1));
63 static void formatDuration(int seconds, QString &result) {
64 QString sec;
65 sec.sprintf("%02d", seconds%60);
66 if(seconds < 60)
67 // xgettext: no-c-format
68 result = i18n("%1s", sec);
69 else if(seconds < 3600)
70 // xgettext: no-c-format
71 result = i18n("%1m %2s", seconds/60, sec);
72 else
73 // xgettext: no-c-format
74 result = i18n("%1h %2m %3s",
75 seconds/3600,
76 (seconds % 3600)/60,
77 sec);
80 static void formatDurationMonth(int seconds, QString &result) {
82 int day, days;
83 day = QDate::currentDate().day();
84 days = QDate::currentDate().daysInMonth();
86 seconds = (seconds / day) * days;
88 QString sec;
89 sec.sprintf("%02d", seconds%60);
90 if(seconds < 60)
91 // xgettext: no-c-format
92 result = i18n("%1s", sec);
93 else if(seconds < 3600)
94 // xgettext: no-c-format
95 result = i18n("%1m %2s", seconds/60, sec);
96 else
97 // xgettext: no-c-format
98 result = i18n("%1h %2m %3s",
99 seconds/3600,
100 (seconds % 3600)/60,
101 sec);
104 static void costsMonth(double costs, double &result) {
106 int day, days;
107 day = QDate::currentDate().day();
108 days = QDate::currentDate().daysInMonth();
110 result = (costs / day) * days;
114 class LogListItem : public Q3ListViewItem {
115 public:
116 LogListItem(LogInfo *l,
117 Q3ListView * parent,
118 QString s1, QString s2,
119 QString s3, QString s4,
120 QString s5, QString s6,
121 QString s7, QString s8)
122 : Q3ListViewItem(parent, s1, s2, s3, s4, s5, s6, s7, s8),
123 li(l)
126 virtual void paintCell( QPainter *p, const QColorGroup & cg,
127 int column, int width, int alignment );
129 virtual QString key(int, bool) const;
131 LogInfo *li;
134 void LogListItem::paintCell( QPainter *p, const QColorGroup & cg,
135 int column, int width, int alignment )
137 Q3ListViewItem::paintCell(p, cg, column, width, alignment);
139 // double line above sum
140 //if(!li) {
141 // p->drawLine(0, 0, width, 0);
142 //p->drawLine(0, 2, width, 2);
146 QString LogListItem::key(int c, bool ascending) const
148 if (!li) // we want the sum to be always at the bottom
149 return ascending ? "z" : " ";
151 QString k;
152 switch (c) {
153 case 0:
154 k = li->connectionName();
155 break;
156 case 1:
157 case 2:
158 case 3:
159 k.sprintf("%012u", (uint)li->from_t());
160 break;
161 case 4:
162 k.sprintf("%012d", li->duration());
163 break;
164 case 5:
165 k.sprintf("%012.2f", li->sessionCosts());
166 break;
167 case 6:
168 k.sprintf("%012d", li->bytesIn());
169 break;
170 case 7:
171 k.sprintf("%012d", li->bytesOut());
172 break;
174 return k;
177 MonthlyWidget::MonthlyWidget(QWidget *parent) :
178 QWidget(parent)
180 tl = 0;
182 lv = new K3ListView(this);
183 lv->addColumn(i18n("Connection"));
184 lv->addColumn(i18n("Day"));
185 lv->addColumn(i18n("From"));
186 lv->addColumn(i18n("Until"));
187 lv->addColumn(i18n("Duration"));
188 lv->addColumn(i18n("Costs"));
189 lv->addColumn(i18n("Bytes In"));
190 lv->addColumn(i18n("Bytes Out"));
191 lv->setColumnAlignment(1, Qt::AlignRight);
192 lv->setColumnAlignment(2, Qt::AlignRight);
193 lv->setColumnAlignment(3, Qt::AlignRight);
194 lv->setColumnAlignment(4, Qt::AlignRight);
195 lv->setColumnAlignment(5, Qt::AlignRight);
196 lv->setColumnAlignment(6, Qt::AlignRight);
197 lv->setColumnAlignment(7, Qt::AlignRight);
198 lv->setAllColumnsShowFocus(true);
199 lv->setShowSortIndicator(true);
200 lv->setItemMargin(1);
201 lv->setSorting(1);
202 lv->setMinimumWidth(180);
203 lv->setMinimumHeight(280);
204 lv->setSelectionMode(Q3ListView::Extended);
205 selectionItem = 0L;
206 connect(lv, SIGNAL(selectionChanged()), SLOT(slotSelectionChanged()));
208 lv2 = new K3ListView(this);
209 lv2->addColumn(i18n("Connection"));
210 lv2->addColumn(i18n("Duration"));
211 lv2->addColumn(i18n("Costs"));
212 lv2->addColumn(i18n("Bytes In"));
213 lv2->addColumn(i18n("Bytes Out"));
214 lv2->setColumnAlignment(1, Qt::AlignRight);
215 lv2->setColumnAlignment(2, Qt::AlignRight);
216 lv2->setColumnAlignment(3, Qt::AlignRight);
217 lv2->setColumnAlignment(4, Qt::AlignRight);
218 lv2->setAllColumnsShowFocus(true);
219 lv2->setSorting(-1);
220 lv2->setItemMargin(2);
221 lv2->setMaximumHeight(100);
222 lv2->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
223 lv2->setSelectionMode(Q3ListView::NoSelection);
225 title = new QLabel("X", this);
226 QFont f = title->font();
227 f.setPointSize(f.pointSize() + 2);
228 f.setBold(true);
229 title->setFont(f);
230 title->setFixedHeight(title->sizeHint().height()*2);
232 cboConnections = new QComboBox(this); // add a combo box to select connections
233 cboConnections->setEditable( false );
234 cboConnections->setMaximumWidth(200); // a reasonable size
235 cboConnections->addItem(i18n("All Connections")); // default to all connections
236 connect(cboConnections, SIGNAL(activated(int)),
237 this, SLOT(slotConnections(int)));
239 bbox = new KDialogButtonBox(this, Qt::Vertical);
240 prev = bbox->addButton(i18n("&Prev Month"),QDialogButtonBox::ActionRole);
241 next = bbox->addButton(i18n("&Next Month"),QDialogButtonBox::ActionRole);
242 today = bbox->addButton(i18n("C&urrent Month"),QDialogButtonBox::ActionRole);
243 exportBttn = bbox->addButton(i18n("&Export..."),QDialogButtonBox::AcceptRole);
245 connect(prev, SIGNAL(released()),
246 this, SLOT(prevMonth()));
247 connect(next, SIGNAL(released()),
248 this, SLOT(nextMonth()));
249 connect(today, SIGNAL(released()),
250 this, SLOT(currentMonth()));
251 connect(exportBttn, SIGNAL(clicked()),
252 this, SLOT(exportWizard()));
254 currentMonth();
255 layoutWidget();
258 void MonthlyWidget::layoutWidget() {
259 delete tl;
261 tl = new QGridLayout(this );
262 tl->setMargin( 11 );
263 tl->setSpacing( 16 );
264 tl->setObjectName( "MainLayout");
265 tl->addWidget(title, 0, 0);
266 tl->addWidget(cboConnections, 0, 1);
267 QLabel *l = new QLabel(this);
268 l->setText(i18n("Statistics:"));
269 QFont f2 = l->font();
270 f2.setPointSize(f2.pointSize() + 1);
271 f2.setBold(true);
272 l->setFont(f2);
273 l->setFixedHeight(l->sizeHint().height());
274 l->setAlignment( Qt::AlignLeft );
275 tl->addWidget(l, 5, 0);
276 tl->addWidget(bbox, 1, 2);
277 tl->addWidget(lv, 1, 0, 4, 2);
278 tl->addWidget(lv2, 6, 0, 1, 2);
280 tl->activate();
283 int bestlen(QWidget *w, const char *s) {
284 return w->fontMetrics().boundingRect(s).width() + 8;
287 void MonthlyWidget::plotMonth() {
288 // name of the current connection
289 QString con;
291 // for collecting monthly statistics
292 int count = 0;
293 double costs = 0;
294 int bin = 0, bout = 0;
295 int duration = 0;
296 lv->clear();
297 selectionItem = 0L;
298 lv2->clear();
300 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
301 QDate startDate = periodeFirst();
303 for(int i = 0; i < (int)logList.count(); i++) {
304 LogInfo *li = logList.at(i);
306 QDate logDate = li->from().date();
307 if ( periodeFirst() <= logDate && periodeLast() >= logDate ) {
308 // get connection name for this line
309 con = li->connectionName();
311 // this connection name not in the list and combo box
312 if(lstConnections.indexOf(con) == -1) {
313 lstConnections.append(con);
314 cboConnections->addItem(con);
316 // if all connections or the selected one
317 if(cboConnections->currentText() != con &&
318 cboConnections->currentIndex() != 0)
319 continue;
320 count++;
321 costs += li->sessionCosts();
322 if(bin >= 0) {
323 if(li->bytesIn() < 0)
324 bin = -1;
325 else
326 bin += li->bytesIn();
329 if(bout >= 0) {
330 if(li->bytesOut() < 0)
331 bout = -1;
332 else
333 bout += li->bytesOut();
336 duration += li->from().secsTo(li->until());
338 QString _bin, _bout, b;
339 if(li->bytesIn() >= 0)
340 formatBytes(li->bytesIn(), _bin);
341 else
342 _bin = i18n("n/a");
344 if(li->bytesOut() >= 0)
345 formatBytes(li->bytesOut(), _bout);
346 else
347 _bout = i18n("n/a");
349 if(li->bytes() > 0)
350 formatBytes(li->bytes(), b);
351 else
352 b = i18n("n/a");
354 QString day;
355 day.sprintf("%2d", li->from().date().day());
357 QString s_duration;
358 formatDuration(li->from().secsTo(li->until()),
359 s_duration);
361 QString s_lifrom, s_liuntil, s_costs;
362 s_lifrom = KGlobal::locale()->formatTime(li->from().time(), false);
363 s_liuntil = KGlobal::locale()->formatTime(li->until().time(), false);
364 s_costs = KGlobal::locale()->formatMoney(li->sessionCosts());
366 (void) new LogListItem(li, lv, con, day, s_lifrom, s_liuntil, s_duration, s_costs, _bin, _bout);
370 if(count) {
371 QString _bin, _bout, _b;
373 if(bin < 0)
374 _bin = i18n("n/a");
375 else
376 formatBytes(bin, _bin);
378 if(bout < 0)
379 _bout = i18n("n/a");
380 else
381 formatBytes(bout, _bout);
383 if(bin < 0 || bout < 0)
384 _b = i18n("n/a");
385 else
386 formatBytes(bout + bin, _b);
388 QString s_duration;
389 formatDuration(duration,
390 s_duration);
392 QString s_costs(KGlobal::locale()->formatMoney(costs, QString(), 2));
394 selectionItem = new LogListItem(0, lv2,
395 i18np("Selection (%1 connection)", "Selection (%1 connections)", 0),
396 QString(), QString(), QString(),
397 QString(), QString(), QString(), QString());
398 (void) new LogListItem(0, lv2,
399 i18np("%1 connection", "%1 connections", count),
400 s_duration, s_costs, _bin, _bout, QString(), QString(), QString());
402 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
404 if(calendar->month(periodeFirst()) == calendar->month(QDate::currentDate())) {
406 QString m_bin, m_bout;
408 if(bin < 0)
409 _bin = i18n("n/a");
410 else
411 formatBytesMonth(bin, m_bin);
413 if(bout < 0)
414 _bout = i18n("n/a");
415 else
416 formatBytesMonth(bout, m_bout);
418 QString m_duration;
419 formatDurationMonth(duration, m_duration);
421 costsMonth(costs, costs);
422 QString m_costs(KGlobal::locale()->formatMoney(costs, QString(), 2));
424 (void) new Q3ListViewItem(lv2, selectionItem,
425 i18n("Monthly estimates"), m_duration, m_costs, m_bin, m_bout,
426 QString(), QString(), QString());
430 QString t;
431 if(lv->childCount() > 0) {
432 exportBttn->setEnabled(true); // export possibility
433 t = i18n("Connection log for %1 %2",
434 calendar->monthName(startDate),
435 calendar->year(startDate));
436 } else {
437 exportBttn->setEnabled(false); // nothing to export
438 t = i18n("No connection log for %1 %2 available",
439 calendar->monthName(startDate),
440 calendar->year(startDate));
443 title->setText(t);
446 void MonthlyWidget::slotConnections(int) {
447 plotMonth();
450 void MonthlyWidget::nextMonth() {
451 m_periodeFirst = KGlobal::locale()->calendar()->addMonths(m_periodeFirst, 1);
453 plotMonth();
456 void MonthlyWidget::prevMonth() {
457 m_periodeFirst = KGlobal::locale()->calendar()->addMonths(m_periodeFirst, -1);
459 plotMonth();
462 void MonthlyWidget::currentMonth() {
463 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
464 QDate dt = QDate::currentDate();
465 calendar->setYMD(m_periodeFirst, calendar->year(dt), calendar->month(dt), 1);
467 plotMonth();
470 void MonthlyWidget::exportWizard() {
471 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
472 QString date = QString::fromLatin1("%1-%2") // e.g.: June-2001
473 .arg(calendar->monthName(periodeFirst()))
474 .arg(calendar->year(periodeFirst()));
476 ExportWizard *wizard = new ExportWizard(0, date);
477 wizard->exec();
478 if (wizard->filename.isEmpty()) { // wizard aborted...
479 return;
481 if (QFile::exists(wizard->filename)) { // overwrite?
482 if (KMessageBox::Continue!=KMessageBox::warningContinueCancel(0, i18n("A document with this name already exists."), i18n("Overwrite file?"), KStandardGuiItem::overwrite() /*, true*/)) { // no
483 return;
487 // open file
488 Export *exportIFace = wizard->createExportFilter();
489 if (exportIFace == NULL) { // error
490 return;
493 if (!exportIFace->openFile()) { // error opening
494 KMessageBox::sorry(0, i18n("An error occurred while trying to open this file"), i18n("Sorry"), KMessageBox::Notify);
495 delete exportIFace;
496 return; // abort...
499 // start writing data
500 exportIFace->addHeadline(i18n("Connection"), i18n("Day"), i18n("From"), i18n("Until"),
501 i18n("Duration"), i18n("Costs"), i18n("Bytes In"), i18n("Bytes Out") );
503 // name of the current connection
504 QString con;
506 // for collecting monthly statistics
507 int count = 0;
508 double costs = 0;
509 int bin = 0, bout = 0;
510 int duration = 0;
512 for(int i = 0; i < (int)logList.count(); i++) {
513 LogInfo *li = logList.at(i);
515 QDate logDate = li->from().date();
516 if (periodeFirst() <= logDate && periodeLast() >= logDate ) {
517 // get connection name for this line
518 con = li->connectionName();
520 // this connection name not in the list and combo box
521 if(lstConnections.indexOf(con) == -1) {
522 lstConnections.append(con);
523 cboConnections->addItem(con);
525 // if all connections or the selected one
526 if(cboConnections->currentText() != con &&
527 cboConnections->currentIndex() != 0)
528 continue;
530 count++;
531 costs += li->sessionCosts();
532 if(bin >= 0) {
533 if(li->bytesIn() < 0)
534 bin = -1;
535 else
536 bin += li->bytesIn();
539 if(bout >= 0) {
540 if(li->bytesOut() < 0)
541 bout = -1;
542 else
543 bout += li->bytesOut();
546 duration += li->from().secsTo(li->until());
548 QString _bin, _bout, b;
549 if(li->bytesIn() >= 0)
550 formatBytes(li->bytesIn(), _bin);
551 else
552 _bin = i18n("n/a");
554 if(li->bytesOut() >= 0)
555 formatBytes(li->bytesOut(), _bout);
556 else
557 _bout = i18n("n/a");
559 if(li->bytes() > 0)
560 formatBytes(li->bytes(), b);
561 else
562 b = i18n("n/a");
564 QString day;
565 day.sprintf("%2d", li->from().date().day());
566 QString con = li->connectionName();
568 QString s_duration;
569 formatDuration(li->from().secsTo(li->until()),
570 s_duration);
572 QString s_lifrom, s_liuntil, s_costs;
573 s_lifrom = KGlobal::locale()->formatTime(li->from().time(), false);
574 s_liuntil = KGlobal::locale()->formatTime(li->until().time(), false);
575 s_costs = KGlobal::locale()->formatMoney(li->sessionCosts());
577 // call export method
578 exportIFace->addDataline(con, day, s_lifrom, s_liuntil, s_duration,
579 s_costs, _bin, _bout);
584 if(calendar->month(periodeFirst()) == calendar->month(QDate::currentDate())) {
586 QString m_bin, m_bout;
587 if(bin < 0)
588 m_bin = i18n("n/a");
589 else
590 formatBytesMonth(bin, m_bin);
592 if(bout < 0)
593 m_bout = i18n("n/a");
594 else
595 formatBytesMonth(bout, m_bout);
597 QString m_duration;
598 formatDurationMonth(duration, m_duration);
600 costsMonth(costs, costs);
601 QString m_costs(KGlobal::locale()->formatMoney(costs, QString(), 2));
603 QString datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(), KLocale::ShortDate);
605 exportIFace->addEmptyLine();
606 exportIFace->addDataline(i18n("Monthly estimates (%1)", datetime),
607 QString(), QString(), QString(), m_duration, m_costs, m_bin, m_bout);
610 if(count) {
611 QString _bin, _bout, _b;
613 if(bin < 0)
614 _bin = i18n("n/a");
615 else
616 formatBytes(bin, _bin);
618 if(bout < 0)
619 _bout = i18n("n/a");
620 else
621 formatBytes(bout, _bout);
623 if(bin < 0 || bout < 0)
624 _b = i18n("n/a");
625 else
626 formatBytes(bout + bin, _b);
628 QString s_duration;
629 formatDuration(duration,
630 s_duration);
632 QString s_costs(KGlobal::locale()->formatMoney(costs, QString(), 2));
634 // call export methods
635 exportIFace->addEmptyLine();
636 exportIFace->addDataline(i18np("%1 connection", "%1 connections", count), QString(), QString(), QString(), s_duration,
637 s_costs, _bin, _bout);
638 exportIFace->setFinishCode();
640 // write buffer to file and close file
641 if (!exportIFace->closeFile()) {
642 KMessageBox::sorry(0, i18n("An error occurred while trying to write to this file."), i18n("Sorry"), KMessageBox::Notify);
643 delete exportIFace;
644 return;
648 delete exportIFace;
651 QDate MonthlyWidget::periodeFirst() const
653 return m_periodeFirst;
656 QDate MonthlyWidget::periodeLast() const
658 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
660 // One month minus one day
661 return calendar->addDays(calendar->addMonths(m_periodeFirst, 1), -1);
664 void MonthlyWidget::slotSelectionChanged()
666 if (selectionItem)
668 int count = 0;
669 double costs = 0;
670 int bin = 0, bout = 0;
671 int duration = 0;
672 LogListItem *item;
673 LogInfo *li;
674 Q3ListViewItemIterator it(lv);
675 while ( it.current() )
677 item = dynamic_cast<LogListItem*>(it.current());
678 if ( item && item->isSelected() && item->li)
680 li = item->li;
681 costs += li->sessionCosts();
682 if(bin >= 0) {
683 if(li->bytesIn() < 0)
684 bin = -1;
685 else
686 bin += li->bytesIn();
689 if(bout >= 0) {
690 if(li->bytesOut() < 0)
691 bout = -1;
692 else
693 bout += li->bytesOut();
696 duration += li->from().secsTo(li->until());
697 count++;
699 ++it;
701 if(count)
703 QString _bin, _bout, _b;
705 if(bin < 0)
706 _bin = i18n("n/a");
707 else
708 formatBytes(bin, _bin);
710 if(bout < 0)
711 _bout = i18n("n/a");
712 else
713 formatBytes(bout, _bout);
715 if(bin < 0 || bout < 0)
716 _b = i18n("n/a");
717 else
718 formatBytes(bout + bin, _b);
720 QString s_duration;
721 formatDuration(duration,
722 s_duration);
724 QString s_costs(KGlobal::locale()->formatMoney(costs, QString(), 2));
725 selectionItem->setText(0, i18np("Selection (%1 connection)", "Selection (%1 connections)", count));
726 selectionItem->setText(1, s_duration);
727 selectionItem->setText(2, s_costs);
728 selectionItem->setText(3, _bin);
729 selectionItem->setText(4, _bout);
734 #include "monthly.moc"