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.
22 #include <qcombobox.h>
26 #include <kcalendarsystem.h>
29 #include <k3listview.h>
31 #include <kmessagebox.h>
32 #include <kdialogbuttonbox.h>
36 #include <qstringlist.h>
38 static void formatBytes(int bytes
, QString
&result
) {
41 else if(bytes
< 1024*1024)
42 result
= i18n("%1 KB", KGlobal::locale()->formatNumber((float)bytes
/ 1024.0, 1));
44 result
= i18n("%1 MB", KGlobal::locale()->formatNumber((float)bytes
/ 1024.0 / 1024.0, 1));
47 static void formatBytesMonth(int bytes
, QString
&result
) {
50 day
= QDate::currentDate().day();
51 days
= QDate::currentDate().daysInMonth();
53 bytes
= (bytes
/ day
) * days
;
57 else if(bytes
< 1024*1024)
58 result
= i18n("%1 KB", KGlobal::locale()->formatNumber((float)bytes
/ 1024.0, 1));
60 result
= i18n("%1 MB", KGlobal::locale()->formatNumber((float)bytes
/ 1024.0 / 1024.0, 1));
63 static void formatDuration(int seconds
, QString
&result
) {
65 sec
.sprintf("%02d", seconds
%60);
67 result
= i18n("%1s", sec
);
68 else if(seconds
< 3600)
69 result
= i18n("%1m %2s", seconds
/60, sec
);
71 result
= i18n("%1h %2m %3s",
77 static void formatDurationMonth(int seconds
, QString
&result
) {
80 day
= QDate::currentDate().day();
81 days
= QDate::currentDate().daysInMonth();
83 seconds
= (seconds
/ day
) * days
;
86 sec
.sprintf("%02d", seconds
%60);
88 result
= i18n("%1s", sec
);
89 else if(seconds
< 3600)
90 result
= i18n("%1m %2s", seconds
/60, sec
);
92 result
= i18n("%1h %2m %3s",
98 static void costsMonth(double costs
, double &result
) {
101 day
= QDate::currentDate().day();
102 days
= QDate::currentDate().daysInMonth();
104 result
= (costs
/ day
) * days
;
108 class LogListItem
: public Q3ListViewItem
{
110 LogListItem(LogInfo
*l
,
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
),
120 virtual void paintCell( QPainter
*p
, const QColorGroup
& cg
,
121 int column
, int width
, int alignment
);
123 virtual QString
key(int, bool) const;
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
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" : " ";
148 k
= li
->connectionName();
153 k
.sprintf("%012u", (uint
)li
->from_t());
156 k
.sprintf("%012d", li
->duration());
159 k
.sprintf("%012.2f", li
->sessionCosts());
162 k
.sprintf("%012d", li
->bytesIn());
165 k
.sprintf("%012d", li
->bytesOut());
171 MonthlyWidget::MonthlyWidget(QWidget
*parent
) :
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);
196 lv
->setMinimumWidth(180);
197 lv
->setMinimumHeight(280);
198 lv
->setSelectionMode(Q3ListView::Extended
);
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);
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);
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()));
252 void MonthlyWidget::layoutWidget() {
255 tl
= new QGridLayout(this );
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);
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);
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
285 // for collecting monthly statistics
288 int bin
= 0, bout
= 0;
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)
315 costs
+= li
->sessionCosts();
317 if(li
->bytesIn() < 0)
320 bin
+= li
->bytesIn();
324 if(li
->bytesOut() < 0)
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
);
338 if(li
->bytesOut() >= 0)
339 formatBytes(li
->bytesOut(), _bout
);
344 formatBytes(li
->bytes(), b
);
349 day
.sprintf("%2d", li
->from().date().day());
352 formatDuration(li
->from().secsTo(li
->until()),
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
);
365 QString _bin
, _bout
, _b
;
370 formatBytes(bin
, _bin
);
375 formatBytes(bout
, _bout
);
377 if(bin
< 0 || bout
< 0)
380 formatBytes(bout
+ bin
, _b
);
383 formatDuration(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
;
405 formatBytesMonth(bin
, m_bin
);
410 formatBytesMonth(bout
, m_bout
);
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
);
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
));
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
));
440 void MonthlyWidget::slotConnections(int) {
444 void MonthlyWidget::nextMonth() {
445 m_periodeFirst
= KGlobal::locale()->calendar()->addMonths(m_periodeFirst
, 1);
450 void MonthlyWidget::prevMonth() {
451 m_periodeFirst
= KGlobal::locale()->calendar()->addMonths(m_periodeFirst
, -1);
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);
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
);
472 if (wizard
->filename
.isEmpty()) { // wizard aborted...
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
482 Export
*exportIFace
= wizard
->createExportFilter();
483 if (exportIFace
== NULL
) { // error
487 if (!exportIFace
->openFile()) { // error opening
488 KMessageBox::sorry(0, i18n("An error occurred while trying to open this file"), i18n("Sorry"), KMessageBox::Notify
);
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
500 // for collecting monthly statistics
503 int bin
= 0, bout
= 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)
525 costs
+= li
->sessionCosts();
527 if(li
->bytesIn() < 0)
530 bin
+= li
->bytesIn();
534 if(li
->bytesOut() < 0)
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
);
548 if(li
->bytesOut() >= 0)
549 formatBytes(li
->bytesOut(), _bout
);
554 formatBytes(li
->bytes(), b
);
559 day
.sprintf("%2d", li
->from().date().day());
560 QString con
= li
->connectionName();
563 formatDuration(li
->from().secsTo(li
->until()),
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
;
584 formatBytesMonth(bin
, m_bin
);
587 m_bout
= i18n("n/a");
589 formatBytesMonth(bout
, m_bout
);
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
);
605 QString _bin
, _bout
, _b
;
610 formatBytes(bin
, _bin
);
615 formatBytes(bout
, _bout
);
617 if(bin
< 0 || bout
< 0)
620 formatBytes(bout
+ bin
, _b
);
623 formatDuration(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
);
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()
664 int bin
= 0, bout
= 0;
668 Q3ListViewItemIterator
it(lv
);
669 while ( it
.current() )
671 item
= dynamic_cast<LogListItem
*>(it
.current());
672 if ( item
&& item
->isSelected() && item
->li
)
675 costs
+= li
->sessionCosts();
677 if(li
->bytesIn() < 0)
680 bin
+= li
->bytesIn();
684 if(li
->bytesOut() < 0)
687 bout
+= li
->bytesOut();
690 duration
+= li
->from().secsTo(li
->until());
697 QString _bin
, _bout
, _b
;
702 formatBytes(bin
, _bin
);
707 formatBytes(bout
, _bout
);
709 if(bin
< 0 || bout
< 0)
712 formatBytes(bout
+ bin
, _b
);
715 formatDuration(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"