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 KiB", KGlobal::locale()->formatNumber((float)bytes
/ 1024.0, 1));
44 result
= i18n("%1 MiB", 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 KiB", KGlobal::locale()->formatNumber((float)bytes
/ 1024.0, 1));
60 result
= i18n("%1 MiB", 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 // 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
);
73 // xgettext: no-c-format
74 result
= i18n("%1h %2m %3s",
80 static void formatDurationMonth(int seconds
, QString
&result
) {
83 day
= QDate::currentDate().day();
84 days
= QDate::currentDate().daysInMonth();
86 seconds
= (seconds
/ day
) * days
;
89 sec
.sprintf("%02d", 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
);
97 // xgettext: no-c-format
98 result
= i18n("%1h %2m %3s",
104 static void costsMonth(double costs
, double &result
) {
107 day
= QDate::currentDate().day();
108 days
= QDate::currentDate().daysInMonth();
110 result
= (costs
/ day
) * days
;
114 class LogListItem
: public Q3ListViewItem
{
116 LogListItem(LogInfo
*l
,
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
),
126 virtual void paintCell( QPainter
*p
, const QColorGroup
& cg
,
127 int column
, int width
, int alignment
);
129 virtual QString
key(int, bool) const;
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
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" : " ";
154 k
= li
->connectionName();
159 k
.sprintf("%012u", (uint
)li
->from_t());
162 k
.sprintf("%012d", li
->duration());
165 k
.sprintf("%012.2f", li
->sessionCosts());
168 k
.sprintf("%012d", li
->bytesIn());
171 k
.sprintf("%012d", li
->bytesOut());
177 MonthlyWidget::MonthlyWidget(QWidget
*parent
) :
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);
202 lv
->setMinimumWidth(180);
203 lv
->setMinimumHeight(280);
204 lv
->setSelectionMode(Q3ListView::Extended
);
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);
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);
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()));
258 void MonthlyWidget::layoutWidget() {
261 tl
= new QGridLayout(this );
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);
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);
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
291 // for collecting monthly statistics
294 int bin
= 0, bout
= 0;
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)
321 costs
+= li
->sessionCosts();
323 if(li
->bytesIn() < 0)
326 bin
+= li
->bytesIn();
330 if(li
->bytesOut() < 0)
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
);
344 if(li
->bytesOut() >= 0)
345 formatBytes(li
->bytesOut(), _bout
);
350 formatBytes(li
->bytes(), b
);
355 day
.sprintf("%2d", li
->from().date().day());
358 formatDuration(li
->from().secsTo(li
->until()),
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
);
371 QString _bin
, _bout
, _b
;
376 formatBytes(bin
, _bin
);
381 formatBytes(bout
, _bout
);
383 if(bin
< 0 || bout
< 0)
386 formatBytes(bout
+ bin
, _b
);
389 formatDuration(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
;
411 formatBytesMonth(bin
, m_bin
);
416 formatBytesMonth(bout
, m_bout
);
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());
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
));
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
));
446 void MonthlyWidget::slotConnections(int) {
450 void MonthlyWidget::nextMonth() {
451 m_periodeFirst
= KGlobal::locale()->calendar()->addMonths(m_periodeFirst
, 1);
456 void MonthlyWidget::prevMonth() {
457 m_periodeFirst
= KGlobal::locale()->calendar()->addMonths(m_periodeFirst
, -1);
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);
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
);
478 if (wizard
->filename
.isEmpty()) { // wizard aborted...
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
488 Export
*exportIFace
= wizard
->createExportFilter();
489 if (exportIFace
== NULL
) { // error
493 if (!exportIFace
->openFile()) { // error opening
494 KMessageBox::sorry(0, i18n("An error occurred while trying to open this file"), i18n("Sorry"), KMessageBox::Notify
);
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
506 // for collecting monthly statistics
509 int bin
= 0, bout
= 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)
531 costs
+= li
->sessionCosts();
533 if(li
->bytesIn() < 0)
536 bin
+= li
->bytesIn();
540 if(li
->bytesOut() < 0)
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
);
554 if(li
->bytesOut() >= 0)
555 formatBytes(li
->bytesOut(), _bout
);
560 formatBytes(li
->bytes(), b
);
565 day
.sprintf("%2d", li
->from().date().day());
566 QString con
= li
->connectionName();
569 formatDuration(li
->from().secsTo(li
->until()),
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
;
590 formatBytesMonth(bin
, m_bin
);
593 m_bout
= i18n("n/a");
595 formatBytesMonth(bout
, m_bout
);
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
);
611 QString _bin
, _bout
, _b
;
616 formatBytes(bin
, _bin
);
621 formatBytes(bout
, _bout
);
623 if(bin
< 0 || bout
< 0)
626 formatBytes(bout
+ bin
, _b
);
629 formatDuration(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
);
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()
670 int bin
= 0, bout
= 0;
674 Q3ListViewItemIterator
it(lv
);
675 while ( it
.current() )
677 item
= dynamic_cast<LogListItem
*>(it
.current());
678 if ( item
&& item
->isSelected() && item
->li
)
681 costs
+= li
->sessionCosts();
683 if(li
->bytesIn() < 0)
686 bin
+= li
->bytesIn();
690 if(li
->bytesOut() < 0)
693 bout
+= li
->bytesOut();
696 duration
+= li
->from().secsTo(li
->until());
703 QString _bin
, _bout
, _b
;
708 formatBytes(bin
, _bin
);
713 formatBytes(bout
, _bout
);
715 if(bin
< 0 || bout
< 0)
718 formatBytes(bout
+ bin
, _b
);
721 formatDuration(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"