port KAboutApplication -> KAboutApplicationDialog, KAboutKDE -> KAboutKDEDialog
[kdenetwork.git] / kppp / logview / monthly.cpp
blob8223e98737c230f4a4ccc8bd14644475faf07815
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 KB", KGlobal::locale()->formatNumber((float)bytes / 1024.0, 1));
43 else
44 result = i18n("%1 MB", 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 KB", KGlobal::locale()->formatNumber((float)bytes / 1024.0, 1));
59 else
60 result = i18n("%1 MB", 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 result = i18n("%1s", sec);
68 else if(seconds < 3600)
69 result = i18n("%1m %2s", seconds/60, sec);
70 else
71 result = i18n("%1h %2m %3s",
72 seconds/3600,
73 (seconds % 3600)/60,
74 sec);
77 static void formatDurationMonth(int seconds, QString &result) {
79 int day, days;
80 day = QDate::currentDate().day();
81 days = QDate::currentDate().daysInMonth();
83 seconds = (seconds / day) * days;
85 QString sec;
86 sec.sprintf("%02d", seconds%60);
87 if(seconds < 60)
88 result = i18n("%1s", sec);
89 else if(seconds < 3600)
90 result = i18n("%1m %2s", seconds/60, sec);
91 else
92 result = i18n("%1h %2m %3s",
93 seconds/3600,
94 (seconds % 3600)/60,
95 sec);
98 static void costsMonth(double costs, double &result) {
100 int day, days;
101 day = QDate::currentDate().day();
102 days = QDate::currentDate().daysInMonth();
104 result = (costs / day) * days;
108 class LogListItem : public Q3ListViewItem {
109 public:
110 LogListItem(LogInfo *l,
111 Q3ListView * parent,
112 QString s1, QString s2,
113 QString s3, QString s4,
114 QString s5, QString s6,
115 QString s7, QString s8)
116 : Q3ListViewItem(parent, s1, s2, s3, s4, s5, s6, s7, s8),
117 li(l)
120 virtual void paintCell( QPainter *p, const QColorGroup & cg,
121 int column, int width, int alignment );
123 virtual QString key(int, bool) const;
125 LogInfo *li;
128 void LogListItem::paintCell( QPainter *p, const QColorGroup & cg,
129 int column, int width, int alignment )
131 Q3ListViewItem::paintCell(p, cg, column, width, alignment);
133 // double line above sum
134 //if(!li) {
135 // p->drawLine(0, 0, width, 0);
136 //p->drawLine(0, 2, width, 2);
140 QString LogListItem::key(int c, bool ascending) const
142 if (!li) // we want the sum to be always at the bottom
143 return ascending ? "z" : " ";
145 QString k;
146 switch (c) {
147 case 0:
148 k = li->connectionName();
149 break;
150 case 1:
151 case 2:
152 case 3:
153 k.sprintf("%012u", (uint)li->from_t());
154 break;
155 case 4:
156 k.sprintf("%012d", li->duration());
157 break;
158 case 5:
159 k.sprintf("%012.2f", li->sessionCosts());
160 break;
161 case 6:
162 k.sprintf("%012d", li->bytesIn());
163 break;
164 case 7:
165 k.sprintf("%012d", li->bytesOut());
166 break;
168 return k;
171 MonthlyWidget::MonthlyWidget(QWidget *parent) :
172 QWidget(parent)
174 tl = 0;
176 lv = new K3ListView(this);
177 lv->addColumn(i18n("Connection"));
178 lv->addColumn(i18n("Day"));
179 lv->addColumn(i18n("From"));
180 lv->addColumn(i18n("Until"));
181 lv->addColumn(i18n("Duration"));
182 lv->addColumn(i18n("Costs"));
183 lv->addColumn(i18n("Bytes In"));
184 lv->addColumn(i18n("Bytes Out"));
185 lv->setColumnAlignment(1, Qt::AlignRight);
186 lv->setColumnAlignment(2, Qt::AlignRight);
187 lv->setColumnAlignment(3, Qt::AlignRight);
188 lv->setColumnAlignment(4, Qt::AlignRight);
189 lv->setColumnAlignment(5, Qt::AlignRight);
190 lv->setColumnAlignment(6, Qt::AlignRight);
191 lv->setColumnAlignment(7, Qt::AlignRight);
192 lv->setAllColumnsShowFocus(true);
193 lv->setShowSortIndicator(true);
194 lv->setItemMargin(1);
195 lv->setSorting(1);
196 lv->setMinimumWidth(180);
197 lv->setMinimumHeight(280);
198 lv->setSelectionMode(Q3ListView::Extended);
199 selectionItem = 0L;
200 connect(lv, SIGNAL(selectionChanged()), SLOT(slotSelectionChanged()));
202 lv2 = new K3ListView(this);
203 lv2->addColumn(i18n("Connection"));
204 lv2->addColumn(i18n("Duration"));
205 lv2->addColumn(i18n("Costs"));
206 lv2->addColumn(i18n("Bytes In"));
207 lv2->addColumn(i18n("Bytes Out"));
208 lv2->setColumnAlignment(1, Qt::AlignRight);
209 lv2->setColumnAlignment(2, Qt::AlignRight);
210 lv2->setColumnAlignment(3, Qt::AlignRight);
211 lv2->setColumnAlignment(4, Qt::AlignRight);
212 lv2->setAllColumnsShowFocus(true);
213 lv2->setSorting(-1);
214 lv2->setItemMargin(2);
215 lv2->setMaximumHeight(100);
216 lv2->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum);
217 lv2->setSelectionMode(Q3ListView::NoSelection);
219 title = new QLabel("X", this);
220 QFont f = title->font();
221 f.setPointSize(f.pointSize() + 2);
222 f.setBold(TRUE);
223 title->setFont(f);
224 title->setFixedHeight(title->sizeHint().height()*2);
226 cboConnections = new QComboBox(this); // add a combo box to select connections
227 cboConnections->setEditable( false );
228 cboConnections->setMaximumWidth(200); // a reasonable size
229 cboConnections->addItem(i18n("All Connections")); // default to all connections
230 connect(cboConnections, SIGNAL(activated(int)),
231 this, SLOT(slotConnections(int)));
233 bbox = new KDialogButtonBox(this, Qt::Vertical);
234 prev = bbox->addButton(i18n("&Prev Month"),QDialogButtonBox::ActionRole);
235 next = bbox->addButton(i18n("&Next Month"),QDialogButtonBox::ActionRole);
236 today = bbox->addButton(i18n("C&urrent Month"),QDialogButtonBox::ActionRole);
237 exportBttn = bbox->addButton(i18n("&Export..."),QDialogButtonBox::AcceptRole);
239 connect(prev, SIGNAL(released()),
240 this, SLOT(prevMonth()));
241 connect(next, SIGNAL(released()),
242 this, SLOT(nextMonth()));
243 connect(today, SIGNAL(released()),
244 this, SLOT(currentMonth()));
245 connect(exportBttn, SIGNAL(clicked()),
246 this, SLOT(exportWizard()));
248 currentMonth();
249 layoutWidget();
252 void MonthlyWidget::layoutWidget() {
253 delete tl;
255 tl = new QGridLayout(this );
256 tl->setMargin( 11 );
257 tl->setSpacing( 16 );
258 tl->setObjectName( "MainLayout");
259 tl->addWidget(title, 0, 0);
260 tl->addWidget(cboConnections, 0, 1);
261 QLabel *l = new QLabel(this);
262 l->setText(i18n("Statistics:"));
263 QFont f2 = l->font();
264 f2.setPointSize(f2.pointSize() + 1);
265 f2.setBold(TRUE);
266 l->setFont(f2);
267 l->setFixedHeight(l->sizeHint().height());
268 l->setAlignment( Qt::AlignLeft );
269 tl->addWidget(l, 5, 0);
270 tl->addWidget(bbox, 1, 2);
271 tl->addMultiCellWidget(lv, 1, 4, 0, 1);
272 tl->addMultiCellWidget(lv2, 6, 6, 0, 1);
274 tl->activate();
277 int bestlen(QWidget *w, const char *s) {
278 return w->fontMetrics().boundingRect(s).width() + 8;
281 void MonthlyWidget::plotMonth() {
282 // name of the current connection
283 QString con;
285 // for collecting monthly statistics
286 int count = 0;
287 double costs = 0;
288 int bin = 0, bout = 0;
289 int duration = 0;
290 lv->clear();
291 selectionItem = 0L;
292 lv2->clear();
294 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
295 QDate startDate = periodeFirst();
297 for(int i = 0; i < (int)logList.count(); i++) {
298 LogInfo *li = logList.at(i);
300 QDate logDate = li->from().date();
301 if ( periodeFirst() <= logDate && periodeLast() >= logDate ) {
302 // get connection name for this line
303 con = li->connectionName();
305 // this connection name not in the list and combo box
306 if(lstConnections.indexOf(con) == -1) {
307 lstConnections.append(con);
308 cboConnections->addItem(con);
310 // if all connections or the selected one
311 if(cboConnections->currentText() != con &&
312 cboConnections->currentIndex() != 0)
313 continue;
314 count++;
315 costs += li->sessionCosts();
316 if(bin >= 0) {
317 if(li->bytesIn() < 0)
318 bin = -1;
319 else
320 bin += li->bytesIn();
323 if(bout >= 0) {
324 if(li->bytesOut() < 0)
325 bout = -1;
326 else
327 bout += li->bytesOut();
330 duration += li->from().secsTo(li->until());
332 QString _bin, _bout, b;
333 if(li->bytesIn() >= 0)
334 formatBytes(li->bytesIn(), _bin);
335 else
336 _bin = i18n("n/a");
338 if(li->bytesOut() >= 0)
339 formatBytes(li->bytesOut(), _bout);
340 else
341 _bout = i18n("n/a");
343 if(li->bytes() > 0)
344 formatBytes(li->bytes(), b);
345 else
346 b = i18n("n/a");
348 QString day;
349 day.sprintf("%2d", li->from().date().day());
351 QString s_duration;
352 formatDuration(li->from().secsTo(li->until()),
353 s_duration);
355 QString s_lifrom, s_liuntil, s_costs;
356 s_lifrom = KGlobal::locale()->formatTime(li->from().time(), false);
357 s_liuntil = KGlobal::locale()->formatTime(li->until().time(), false);
358 s_costs = KGlobal::locale()->formatMoney(li->sessionCosts());
360 (void) new LogListItem(li, lv, con, day, s_lifrom, s_liuntil, s_duration, s_costs, _bin, _bout);
364 if(count) {
365 QString _bin, _bout, _b;
367 if(bin < 0)
368 _bin = i18n("n/a");
369 else
370 formatBytes(bin, _bin);
372 if(bout < 0)
373 _bout = i18n("n/a");
374 else
375 formatBytes(bout, _bout);
377 if(bin < 0 || bout < 0)
378 _b = i18n("n/a");
379 else
380 formatBytes(bout + bin, _b);
382 QString s_duration;
383 formatDuration(duration,
384 s_duration);
386 QString s_costs(KGlobal::locale()->formatMoney(costs, QString::null, 2));
388 selectionItem = new LogListItem(0, lv2,
389 i18np("Selection (%n connection)", "Selection (%n connections)", 0),
390 QString::null, QString::null, QString::null,
391 QString::null, QString::null, QString::null, QString::null);
392 (void) new LogListItem(0, lv2,
393 i18np("%n connection", "%n connections", count),
394 s_duration, s_costs, _bin, _bout, QString::null, QString::null, QString::null);
396 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
398 if(calendar->month(periodeFirst()) == calendar->month(QDate::currentDate())) {
400 QString m_bin, m_bout;
402 if(bin < 0)
403 _bin = i18n("n/a");
404 else
405 formatBytesMonth(bin, m_bin);
407 if(bout < 0)
408 _bout = i18n("n/a");
409 else
410 formatBytesMonth(bout, m_bout);
412 QString m_duration;
413 formatDurationMonth(duration, m_duration);
415 costsMonth(costs, costs);
416 QString m_costs(KGlobal::locale()->formatMoney(costs, QString::null, 2));
418 (void) new Q3ListViewItem(lv2, selectionItem,
419 i18n("Monthly estimates"), m_duration, m_costs, m_bin, m_bout,
420 QString::null, QString::null, QString::null);
424 QString t;
425 if(lv->childCount() > 0) {
426 exportBttn->setEnabled(true); // export possibility
427 t = i18n("Connection log for %1 %2",
428 calendar->monthName(startDate),
429 calendar->year(startDate));
430 } else {
431 exportBttn->setEnabled(false); // nothing to export
432 t = i18n("No connection log for %1 %2 available",
433 calendar->monthName(startDate),
434 calendar->year(startDate));
437 title->setText(t);
440 void MonthlyWidget::slotConnections(int) {
441 plotMonth();
444 void MonthlyWidget::nextMonth() {
445 m_periodeFirst = KGlobal::locale()->calendar()->addMonths(m_periodeFirst, 1);
447 plotMonth();
450 void MonthlyWidget::prevMonth() {
451 m_periodeFirst = KGlobal::locale()->calendar()->addMonths(m_periodeFirst, -1);
453 plotMonth();
456 void MonthlyWidget::currentMonth() {
457 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
458 QDate dt = QDate::currentDate();
459 calendar->setYMD(m_periodeFirst, calendar->year(dt), calendar->month(dt), 1);
461 plotMonth();
464 void MonthlyWidget::exportWizard() {
465 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
466 QString date = QString::fromLatin1("%1-%2") // e.g.: June-2001
467 .arg(calendar->monthName(periodeFirst()))
468 .arg(calendar->year(periodeFirst()));
470 ExportWizard *wizard = new ExportWizard(0, date);
471 wizard->exec();
472 if (wizard->filename.isEmpty()) { // wizard aborted...
473 return;
475 if (QFile::exists(wizard->filename)) { // overwrite?
476 if (KMessageBox::Continue!=KMessageBox::warningContinueCancel(0, i18n("A document with this name already exists."), i18n("Overwrite file?"), KStandardGuiItem::overwrite() /*, true*/)) { // no
477 return;
481 // open file
482 Export *exportIFace = wizard->createExportFilter();
483 if (exportIFace == NULL) { // error
484 return;
487 if (!exportIFace->openFile()) { // error opening
488 KMessageBox::sorry(0, i18n("An error occurred while trying to open this file"), i18n("Sorry"), KMessageBox::Notify);
489 delete exportIFace;
490 return; // abort...
493 // start writing data
494 exportIFace->addHeadline(i18n("Connection"), i18n("Day"), i18n("From"), i18n("Until"),
495 i18n("Duration"), i18n("Costs"), i18n("Bytes In"), i18n("Bytes Out") );
497 // name of the current connection
498 QString con;
500 // for collecting monthly statistics
501 int count = 0;
502 double costs = 0;
503 int bin = 0, bout = 0;
504 int duration = 0;
506 for(int i = 0; i < (int)logList.count(); i++) {
507 LogInfo *li = logList.at(i);
509 QDate logDate = li->from().date();
510 if (periodeFirst() <= logDate && periodeLast() >= logDate ) {
511 // get connection name for this line
512 con = li->connectionName();
514 // this connection name not in the list and combo box
515 if(lstConnections.indexOf(con) == -1) {
516 lstConnections.append(con);
517 cboConnections->addItem(con);
519 // if all connections or the selected one
520 if(cboConnections->currentText() != con &&
521 cboConnections->currentIndex() != 0)
522 continue;
524 count++;
525 costs += li->sessionCosts();
526 if(bin >= 0) {
527 if(li->bytesIn() < 0)
528 bin = -1;
529 else
530 bin += li->bytesIn();
533 if(bout >= 0) {
534 if(li->bytesOut() < 0)
535 bout = -1;
536 else
537 bout += li->bytesOut();
540 duration += li->from().secsTo(li->until());
542 QString _bin, _bout, b;
543 if(li->bytesIn() >= 0)
544 formatBytes(li->bytesIn(), _bin);
545 else
546 _bin = i18n("n/a");
548 if(li->bytesOut() >= 0)
549 formatBytes(li->bytesOut(), _bout);
550 else
551 _bout = i18n("n/a");
553 if(li->bytes() > 0)
554 formatBytes(li->bytes(), b);
555 else
556 b = i18n("n/a");
558 QString day;
559 day.sprintf("%2d", li->from().date().day());
560 QString con = li->connectionName();
562 QString s_duration;
563 formatDuration(li->from().secsTo(li->until()),
564 s_duration);
566 QString s_lifrom, s_liuntil, s_costs;
567 s_lifrom = KGlobal::locale()->formatTime(li->from().time(), false);
568 s_liuntil = KGlobal::locale()->formatTime(li->until().time(), false);
569 s_costs = KGlobal::locale()->formatMoney(li->sessionCosts());
571 // call export method
572 exportIFace->addDataline(con, day, s_lifrom, s_liuntil, s_duration,
573 s_costs, _bin, _bout);
578 if(calendar->month(periodeFirst()) == calendar->month(QDate::currentDate())) {
580 QString m_bin, m_bout;
581 if(bin < 0)
582 m_bin = i18n("n/a");
583 else
584 formatBytesMonth(bin, m_bin);
586 if(bout < 0)
587 m_bout = i18n("n/a");
588 else
589 formatBytesMonth(bout, m_bout);
591 QString m_duration;
592 formatDurationMonth(duration, m_duration);
594 costsMonth(costs, costs);
595 QString m_costs(KGlobal::locale()->formatMoney(costs, QString::null, 2));
597 QString datetime = KGlobal::locale()->formatDateTime( QDateTime::currentDateTime(), true);
599 exportIFace->addEmptyLine();
600 exportIFace->addDataline(i18n("Monthly estimates (%1)", datetime),
601 QString::null, QString::null, QString::null, m_duration, m_costs, m_bin, m_bout);
604 if(count) {
605 QString _bin, _bout, _b;
607 if(bin < 0)
608 _bin = i18n("n/a");
609 else
610 formatBytes(bin, _bin);
612 if(bout < 0)
613 _bout = i18n("n/a");
614 else
615 formatBytes(bout, _bout);
617 if(bin < 0 || bout < 0)
618 _b = i18n("n/a");
619 else
620 formatBytes(bout + bin, _b);
622 QString s_duration;
623 formatDuration(duration,
624 s_duration);
626 QString s_costs(KGlobal::locale()->formatMoney(costs, QString::null, 2));
628 // call export methods
629 exportIFace->addEmptyLine();
630 exportIFace->addDataline(i18np("%n connection", "%n connections", count), QString::null, QString::null, QString::null, s_duration,
631 s_costs, _bin, _bout);
632 exportIFace->setFinishCode();
634 // write buffer to file and close file
635 if (!exportIFace->closeFile()) {
636 KMessageBox::sorry(0, i18n("An error occurred while trying to write to this file."), i18n("Sorry"), KMessageBox::Notify);
637 delete exportIFace;
638 return;
642 delete exportIFace;
645 QDate MonthlyWidget::periodeFirst() const
647 return m_periodeFirst;
650 QDate MonthlyWidget::periodeLast() const
652 const KCalendarSystem * calendar = KGlobal::locale()->calendar();
654 // One month minus one day
655 return calendar->addDays(calendar->addMonths(m_periodeFirst, 1), -1);
658 void MonthlyWidget::slotSelectionChanged()
660 if (selectionItem)
662 int count = 0;
663 double costs = 0;
664 int bin = 0, bout = 0;
665 int duration = 0;
666 LogListItem *item;
667 LogInfo *li;
668 Q3ListViewItemIterator it(lv);
669 while ( it.current() )
671 item = dynamic_cast<LogListItem*>(it.current());
672 if ( item && item->isSelected() && item->li)
674 li = item->li;
675 costs += li->sessionCosts();
676 if(bin >= 0) {
677 if(li->bytesIn() < 0)
678 bin = -1;
679 else
680 bin += li->bytesIn();
683 if(bout >= 0) {
684 if(li->bytesOut() < 0)
685 bout = -1;
686 else
687 bout += li->bytesOut();
690 duration += li->from().secsTo(li->until());
691 count++;
693 ++it;
695 if(count)
697 QString _bin, _bout, _b;
699 if(bin < 0)
700 _bin = i18n("n/a");
701 else
702 formatBytes(bin, _bin);
704 if(bout < 0)
705 _bout = i18n("n/a");
706 else
707 formatBytes(bout, _bout);
709 if(bin < 0 || bout < 0)
710 _b = i18n("n/a");
711 else
712 formatBytes(bout + bin, _b);
714 QString s_duration;
715 formatDuration(duration,
716 s_duration);
718 QString s_costs(KGlobal::locale()->formatMoney(costs, QString::null, 2));
719 selectionItem->setText(0, i18np("Selection (%n connection)", "Selection (%n connections)", count));
720 selectionItem->setText(1, s_duration);
721 selectionItem->setText(2, s_costs);
722 selectionItem->setText(3, _bin);
723 selectionItem->setText(4, _bout);
728 #include "monthly.moc"