1/*
2 * kPPP: A pppd front end for the KDE project
3 *
4 * $Id$
5 *
6 * Copyright (C) 1997 Bernd Johannes Wuebben
7 * wuebben@math.cornell.edu
8 *
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Library General Public
12 * License as published by the Free Software Foundation; either
13 * version 2 of the License, or (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Library General Public License for more details.
19 *
20 * You should have received a copy of the GNU Library General Public
21 * License along with this program; if not, write to the Free
22 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
23 */
24
25
26#include <qlayout.h>
27#include <qpainter.h>
28#include <kguiitem.h>
29//Added by qt3to4:
30#include <QPixmap>
31#include <QGridLayout>
32#include <QCloseEvent>
33#include <QEvent>
34#include <QHBoxLayout>
35#include <QVBoxLayout>
36#include <QApplication>
37#include <kwindowsystem.h>
38#include <kiconloader.h>
39#include <klocale.h>
40#include <qlabel.h>
41#include <q3frame.h>
42#include <q3groupbox.h>
43#include <qlineedit.h>
44#include <qtimer.h>
45#include <kpushbutton.h>
46#include <KStandardGuiItem>
47
48#include "pppdata.h"
49#include "pppstatdlg.h"
50#include "iplined.h"
51#include "pppstats.h"
52
53extern PPPData gpppdata;
54
55PPPStatsDlg::PPPStatsDlg(QWidget *parent, const char *name, QWidget *,
56 PPPStats *st)
57 : QWidget(parent),
58 stats(st)
59{
60 int i;
61 max = 1024;
62
63 setObjectName(name);
64
65 setWindowTitle(i18n("kppp Statistics"));
66 KWindowSystem::setIcons(winId(), qApp->windowIcon().pixmap(IconSize(KIconLoader::Desktop),IconSize(KIconLoader::Desktop)), qApp->windowIcon().pixmap(IconSize(KIconLoader::Small),IconSize(KIconLoader::Small)));
67
68 QVBoxLayout *tl = new QVBoxLayout(this);
69 tl->setSpacing(10);
70 QGridLayout *l1 = new QGridLayout();
71 tl->addLayout(l1, 1);
72 box = new Q3GroupBox(i18n("Statistics"), this);
73 l1->addWidget(box, 0, 0, 4, 4);
74 l1->addItem(new QSpacerItem(0, fontMetrics().lineSpacing() - 10), 0, 0);
75 l1->setRowStretch(1, 1);
76 l1->setColumnStretch(1, 1);
77
78 // inner part of the grid
79 QVBoxLayout *l11 = new QVBoxLayout;
80 l1->addLayout(l11, 1, 1);
81
82 // modem pixmap and IP labels
83 QHBoxLayout *l111 = new QHBoxLayout;
84 l11->addLayout(l111);
85
86 big_modem_both_pixmap = UserIcon("modemboth");
87 big_modem_left_pixmap = UserIcon("modemleft");
88 big_modem_right_pixmap = UserIcon("modemright");
89 big_modem_none_pixmap = UserIcon("modemnone");
90
91 pixmap_l = new QLabel(this);
92 pixmap_l->setMinimumSize(big_modem_both_pixmap.size());
93 l111->addWidget(pixmap_l, 1);
94 pixmap_l->setAlignment(Qt::AlignVCenter|Qt::AlignLeft);
95
96 QGridLayout *l1112 = new QGridLayout();
97 l111->addLayout(l1112);
98
99 ip_address_label1 = new QLabel(this);
100 ip_address_label1->setText(i18n("Local Addr:"));
101
102 ip_address_label2 = new IPLineEdit(this);
103 ip_address_label2->setFocusPolicy(Qt::NoFocus);
104
105 ip_address_label3 = new QLabel(this);
106 ip_address_label3->setText(i18n("Remote Addr:"));
107
108 ip_address_label4 = new IPLineEdit(this);
109 ip_address_label4->setFocusPolicy(Qt::NoFocus);
110
111 l1112->addWidget(ip_address_label1, 0, 0);
112 l1112->addWidget(ip_address_label2, 0, 1);
113 l1112->addWidget(ip_address_label3, 1, 0);
114 l1112->addWidget(ip_address_label4, 1, 1);
115
116 // consumes space on bottom
117 l1112->setRowStretch(2, 1);
118
119 QGridLayout *l112 = new QGridLayout();
120 l11->addLayout(l112);
121 for(i =0 ; i < 5; i++) {
122 labela1[i] = new QLabel(this);
123
124 labela2[i] = new QLabel(this);
125 labela2[i]->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
126
127 labelb1[i] = new QLabel(this);
128
129 labelb2[i] = new QLabel(this);
130 labelb2[i]->setFrameStyle(QFrame::WinPanel | QFrame::Sunken);
131 }
132
133 labela1[0]->setText(i18n("bytes in"));
134 labelb1[0]->setText(i18n("bytes out"));
135
136 labela1[1]->setText(i18n("packets in"));
137 labelb1[1]->setText(i18n("packets out"));
138
139 labela1[2]->setText(i18n("vjcomp in"));
140 labelb1[2]->setText(i18n("vjcomp out"));
141
142 labela1[3]->setText(i18n("vjunc in"));
143 labelb1[3]->setText(i18n("vjunc out"));
144
145 labela1[4]->setText(i18n("vjerr"));
146 labelb1[4]->setText(i18n("non-vj"));
147
148 for(i = 0; i < 5; i++) {
149 labela2[i]->setText("888888888"); // TODO: resize automatically
150 labelb2[i]->setText("888888888");
151 labela2[i]->setAlignment(Qt::AlignRight);
152 labelb2[i]->setAlignment(Qt::AlignRight);
153 labela2[i]->setFixedSize(labela2[i]->sizeHint());
154 labelb2[i]->setFixedSize(labelb2[i]->sizeHint());
155 labela2[i]->setText("");
156 labelb2[i]->setText("");
157
158 // add to layout
159 l112->addWidget(labela1[i], i, 0);
160 l112->addWidget(labela2[i], i, 1);
161 l112->addWidget(labelb1[i], i, 2);
162 l112->addWidget(labelb2[i], i, 3);
163 }
164
165 l112->setColumnStretch(1, 1);
166 l112->setColumnStretch(3, 1);
167
168 tl->addSpacing(5);
169 QHBoxLayout *l12 = new QHBoxLayout;
170 tl->addLayout(l12);
171 l12->addStretch(1);
172
173 if(gpppdata.graphingEnabled()) {
174 bool dummy;
175
176 gpppdata.graphingOptions(dummy, bg, text, in, out);
177
178 graph = new QLabel(this);
179 graph->setFrameStyle(QFrame::Box | QFrame::Sunken);
180 l1->addWidget(graph, 2, 1, 1, 2);
181 graph->setMinimumWidth(300);
182 graph->setFixedHeight(76+4);
183
184 QPalette palette;
185 palette.setColor(graph->backgroundRole(), bg);
186 graph->setPalette(palette);
187 }
188
189 cancelbutton = new KPushButton(KStandardGuiItem::close(),this);
190 cancelbutton->setFocus();
191 connect(cancelbutton, SIGNAL(clicked()), this,SLOT(cancel()));
192 cancelbutton->setFixedHeight(cancelbutton->sizeHint().height());
193 cancelbutton->setMinimumWidth(qMax(cancelbutton->sizeHint().width(), 70));
194 l12->addWidget(cancelbutton);
195
196 if(gpppdata.graphingEnabled()) {
197 graphTimer = new QTimer(this);
198 connect(graphTimer, SIGNAL(timeout()), SLOT(updateGraph()));
199 }
200
201 setFixedSize(sizeHint());
202
203 connect(stats, SIGNAL(statsChanged(int)), SLOT(paintIcon(int)));
204
205 // read window position from config file
206 int p_x, p_y;
207 gpppdata.winPosStatWin(p_x, p_y);
208 move(p_x, p_y);
209}
210
211
212PPPStatsDlg::~PPPStatsDlg() {
213}
214
215
216// save window position when window was closed
217bool PPPStatsDlg::event(QEvent *e) {
218 if (e->type() == QEvent::Hide)
219 {
220 gpppdata.setWinPosStatWin(x(), y());
221 return true;
222 }
223 else
224 return QWidget::event(e);
225}
226
227void PPPStatsDlg::cancel() {
228 hide();
229}
230
231
232void PPPStatsDlg::take_stats() {
233 stats->initStats();
234 bin_last = stats->ibytes;
235 bout_last = stats->obytes;
236 ringIdx = 0;
237 for(int i = 0; i < MAX_GRAPH_WIDTH; i++) {
238 bin[i] = -1;
239 bout[i] = -1;
240 }
241
242 update_data();
243
244 stats->start();
245 if(gpppdata.graphingEnabled())
246 graphTimer->start(GRAPH_UPDATE_TIME);
247}
248
249
250void PPPStatsDlg::stop_stats() {
251 stats->stop();
252 if(gpppdata.graphingEnabled())
253 graphTimer->stop();
254}
255
256void PPPStatsDlg::paintGraph() {
257 // why draw that stuff if not visible?
258 if(!isVisible())
259 return;
260
261 QPixmap pm(graph->width() - 4, graph->height() - 4);
262 QPainter p;
263 pm.fill(graph->palette().color(graph->backgroundRole()));
264 p.begin(&pm);
265
266 int x;
267 int idx = ringIdx - pm.width() + 1;
268 if(idx < 0)
269 idx += MAX_GRAPH_WIDTH;
270
271 // find good scaling factor
272 int last_h_in =
273 pm.height() - (int)((float)bin[idx]/max * (pm.height() - 8))-1;
274 int last_h_out =
275 pm.height() - (int)((float)bout[idx]/max * (pm.height() - 8))-1;
276
277 // plot data
278 int last_idx = 0;
279 for(x = 1; x < pm.width(); x++) {
280 int h_in, h_out;
281
282 h_in = pm.height() - (int)((float)bin[idx]/max * (pm.height() - 8))-1;
283 h_out = pm.height() - (int)((float)bout[idx]/max * (pm.height() - 8))-1;
284
285 p.setPen(out);
286 if(bout[idx]!=-1)
287 p.drawLine(x-1, last_h_out, x, h_out);
288 p.setPen(in);
289 if(bin[idx]!=-1)
290 p.drawLine(x-1, last_h_in, x, h_in);
291 last_h_in = h_in;
292 last_h_out = h_out;
293
294 last_idx = idx;
295 idx = (idx + 1) % MAX_GRAPH_WIDTH;
296 }
297
298 // take last value
299 int last_max = bin[last_idx]>bout[last_idx] ? bin[last_idx] : bout[last_idx];
300
301 // plot scale line
302 p.setPen(text);
303 p.setFont(QFont(KGlobalSettings::fixedFont().family(), 8));
304
305 QRect r;
306 QString s = i18n("%1 (max. %2) kb/sec",
307 KGlobal::locale()->formatNumber((float)last_max / 1024.0, 1),
308 KGlobal::locale()->formatNumber((float)max / 1024.0, 1));
309 p.drawText(0, 0, pm.width(), 2*8, Qt::AlignRight|Qt::AlignVCenter, s, &r);
310 p.drawLine(0, 8, r.left() - 8, 8);
311
312 p.end();
313 graph->setPixmap(pm);
314}
315
316void PPPStatsDlg::updateGraph() {
317 bin[ringIdx] = stats->ibytes - bin_last;
318 bout[ringIdx] = stats->obytes - bout_last;
319 if(bin[ringIdx] > max)
320 max = ((bin[ringIdx] / 1024) + 1) * 1024;
321
322 if(bout[ringIdx] > max)
323 max = ((bout[ringIdx] / 1024) + 1) * 1024;
324
325 bin_last = stats->ibytes;
326 bout_last = stats->obytes;
327 ringIdx = (ringIdx + 1) % MAX_GRAPH_WIDTH;
328 paintGraph();
329}
330
331void PPPStatsDlg::paintIcon(int status) {
332 const QPixmap *pixmap;
333
334 switch(status)
335 {
336 case PPPStats::BytesIn:
337 pixmap = &big_modem_left_pixmap;
338 break;
339 case PPPStats::BytesOut:
340 pixmap = &big_modem_right_pixmap;
341 break;
342 case PPPStats::BytesBoth:
343 pixmap = &big_modem_both_pixmap;
344 break;
345 case PPPStats::BytesNone:
346 default:
347 pixmap = &big_modem_none_pixmap;
348 break;
349 }
350
351 pixmap_l->setPixmap(*pixmap);
352
353 update_data();
354}
355
356
357void PPPStatsDlg::timeclick() {
358 // volume accounting
359 switch(gpppdata.VolAcctEnabled()) {
360 case 0: // no accounting
361 break;
362
363 case 1: // bytes in
364 stats->totalbytes = gpppdata.totalBytes() + stats->ibytes;
365 break;
366
367 case 2:
368 stats->totalbytes = gpppdata.totalBytes() + stats->obytes;
369 break;
370
371 case 3:
372 stats->totalbytes = gpppdata.totalBytes() + stats->ibytes + stats->obytes;
373 break;
374 }
375}
376
377
378void PPPStatsDlg::closeEvent(QCloseEvent *) {
379 emit cancel();
380}
381
382
383void PPPStatsDlg::update_data() {
384 timeclick();
385
386 ibytes_string = KGlobal::locale()->formatNumber(stats->ibytes, 0);
387 ipackets_string.setNum(stats->ipackets);
388 compressedin_string.setNum(stats->compressedin);
389 uncompressedin_string.setNum(stats->uncompressedin);
390 errorin_string.setNum(stats->errorin);
391 obytes_string = KGlobal::locale()->formatNumber(stats->obytes, 0);
392 opackets_string.setNum(stats->opackets);
393 compressed_string.setNum(stats->compressed);
394 packetsunc_string.setNum(stats->packetsunc);
395 packetsoutunc_string.setNum(stats->packetsoutunc);
396
397 labela2[0]->setText(ibytes_string);
398 labela2[1]->setText(ipackets_string);
399 labela2[2]->setText(compressedin_string);
400 labela2[3]->setText(uncompressedin_string);
401 labela2[4]->setText(errorin_string);
402
403 labelb2[0]->setText(obytes_string);
404 labelb2[1]->setText(opackets_string);
405 labelb2[2]->setText(compressed_string);
406 labelb2[3]->setText(packetsunc_string);
407 labelb2[4]->setText(packetsoutunc_string);
408
409 // if I don't resort to this trick it is imposible to
410 // copy/paste the ip out of the lineedits due to
411 // reset of cursor position on setText()
412 QString local_addr = ( stats->local_ip_address.isEmpty() ?
413 i18n("unavailable") :
414 stats->local_ip_address );
415
416 if( ip_address_label2->text() != local_addr )
417 ip_address_label2->setText(local_addr);
418
419 QString remote_addr = ( stats->remote_ip_address.isEmpty() ?
420 i18n("unavailable") :
421 stats->remote_ip_address );
422
423 if( ip_address_label4->text() != remote_addr )
424 ip_address_label4->setText(remote_addr);
425}
426
427
428void PPPStatsDlg::toCurrentDesktop() {
429 KWindowSystem::setOnDesktop(winId(), KWindowSystem::currentDesktop());
430}
431
432#include "pppstatdlg.moc"
433
434