port KAboutApplication -> KAboutApplicationDialog, KAboutKDE -> KAboutKDEDialog
[kdenetwork.git] / kppp / kpppwidget.cpp
blobdbb9a17758f01e445099a46dd36717c608b6eb57
1 /*
2 * kPPP: A pppd front end for the KDE project
5 * Copyright (C) 1997 Bernd Johannes Wuebben
6 * wuebben@math.cornell.edu
8 * Copyright (C) 1998-2002 Harri Porten <porten@kde.org>
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.
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.
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.
25 #include "kpppwidget.h"
26 #include <QtDBus>
27 #include <qapplication.h>
28 #include <qcombobox.h>
29 #include <qdir.h>
30 #include <qevent.h>
31 #include <qdialog.h>
32 #include <qlabel.h>
33 #include <qpushbutton.h>
34 #include <qregexp.h>
35 //Added by qt3to4:
36 #include <QGridLayout>
37 #include <QKeyEvent>
38 #include <QHBoxLayout>
39 #include <QVBoxLayout>
40 #include <Q3PopupMenu>
41 #include <kpagedialog.h>
43 #include <QMenu>
44 #include <kaboutdata.h>
45 #include <kapplication.h>
46 #include <kglobalsettings.h>
47 #include <kcmdlineargs.h>
48 #include <kconfig.h>
49 #include <kdebug.h>
50 #include <kiconloader.h> // For BarIcon
51 #include <klocale.h>
52 #include <kmessagebox.h>
53 #include <kseparator.h>
54 #include <kstandarddirs.h>
55 #include <kwin.h>
56 #include <khelpmenu.h>
57 #include <kpushbutton.h>
58 #include <kguiitem.h>
59 #include <KStandardGuiItem>
61 #include <stdlib.h>
62 #include <errno.h>
63 #include <ktoolinvocation.h>
65 #include "runtests.h"
67 #include "main.h"
68 #include "auth.h"
69 #include "modem.h"
70 #include "ppplog.h"
71 #include "opener.h"
72 #include "requester.h"
73 #include "pppstats.h"
74 #include "pppdata.h"
75 #include "general.h"
76 #include "modems.h"
78 #include "kpppadaptor.h"
80 // delay disconnection for a second
81 #define DISCONNECT_DELAY 1000
83 extern KPPPWidget *p_kppp;
85 KPPPWidget::KPPPWidget( QWidget *parent, const char *name )
86 : QWidget(parent)
87 , acct(0)
88 , m_bCmdlAccount (false)
89 , m_bCmdlModem (false)
91 KpppAdaptor *kpppAdaptor = new KpppAdaptor(this);
92 QDBusConnection::sessionBus().registerObject("/Kppp", this);
94 setObjectName( name );
96 connect( this, SIGNAL(sig_aboutToConnect()), kpppAdaptor, SIGNAL(aboutToConnect()) );
97 connect( this, SIGNAL(sig_aboutToDisconnect()), kpppAdaptor, SIGNAL(aboutToDisconnect()) );
98 connect( this, SIGNAL(sig_connected()), kpppAdaptor, SIGNAL(connected()) );
99 connect( this, SIGNAL(sig_disconnected()), kpppAdaptor, SIGNAL(disconnected()) );
102 tabWindow = 0;
104 // before doing anything else, run a few tests
106 int result = runTests();
107 if(result == TEST_CRITICAL)
108 exit(4);
110 installEventFilter(this);
112 QVBoxLayout *tl = new QVBoxLayout(this);
113 tl->setSpacing(10);
114 tl->setMargin(10);
116 l1 = new QGridLayout();
117 tl->addLayout(l1);
118 l1->addItem(new QSpacerItem(10, 0), 0, 0);
119 l1->addItem(new QSpacerItem(10, 0), 0, 3);
120 l1->setColumnStretch(1, 3);
121 l1->setColumnStretch(2, 4);
123 label1 = new QLabel(i18n("C&onnect to: "), this);
124 l1->addWidget(label1, 0, 1);
126 connectto_c = new QComboBox(this);
127 connectto_c->setEditable( false );
128 label1->setBuddy(connectto_c);
130 connect(connectto_c, SIGNAL(activated(int)),
131 SLOT(newdefaultaccount(int)));
132 l1->addWidget(connectto_c, 0, 2);
134 label7 = new QLabel(i18n("Use &modem: "), this);
135 // l1->addWidget(label7, 1, 1); (done in resetmodems())
136 modem_c = new QComboBox(this);
137 modem_c->setEditable( false );
138 label7->setBuddy(connectto_c);
139 m_bModemCShown = false;
141 connect(modem_c, SIGNAL(activated(int)),
142 SLOT(newdefaultmodem(int)));
143 // l1->addWidget(modem_c, 1, 2); (done in resetmodems())
145 ID_Label = new QLabel(i18n("&Login ID:"), this);
146 l1->addWidget(ID_Label, 2, 1);
148 // the entry line for usernames
149 ID_Edit = new QLineEdit(this);
150 ID_Label->setBuddy(ID_Edit);
151 l1->addWidget(ID_Edit, 2, 2);
152 connect(ID_Edit, SIGNAL(returnPressed()),
153 this, SLOT(enterPressedInID()));
154 QString tmp = i18n("<p>Type in the username that you got from your\n"
155 "ISP. This is especially important for PAP\n"
156 "and CHAP. You may omit this when you use\n"
157 "terminal-based or script-based authentication.\n"
158 "\n"
159 "<b>Important</b>: case is important here:\n"
160 "<i>myusername</i> is not the same as <i>MyUserName</i>.");
162 ID_Label->setWhatsThis(tmp);
163 ID_Edit->setWhatsThis(tmp);
165 PW_Label = new QLabel(i18n("&Password:"), this);
166 l1->addWidget(PW_Label, 3, 1);
168 PW_Edit= new QLineEdit(this);
169 PW_Label->setBuddy(PW_Edit);
170 PW_Edit->setEchoMode(QLineEdit::Password);
171 l1->addWidget(PW_Edit, 3, 2);
172 connect(PW_Edit, SIGNAL(returnPressed()),
173 this, SLOT(enterPressedInPW()));
175 tmp = i18n("<p>Type in the password that you got from your\n"
176 "ISP. This is especially important for PAP\n"
177 "and CHAP. You may omit this when you use\n"
178 "terminal-based or script-based authentication.\n"
179 "\n"
180 "<b>Important</b>: case is important here:\n"
181 "<i>mypassword</i> is not the same as <i>MyPassword</i>.");
183 PW_Label->setWhatsThis(tmp);
184 PW_Edit->setWhatsThis(tmp);
186 QHBoxLayout *l3 = new QHBoxLayout;
187 tl->addSpacing(5);
188 tl->addLayout(l3);
189 tl->addSpacing(5);
190 l3->addSpacing(10);
191 log = new QCheckBox(i18n("Show lo&g window"), this);
192 connect(log, SIGNAL(toggled(bool)),
193 this, SLOT(log_window_toggled(bool)));
194 log->setChecked(gpppdata.get_show_log_window());
195 l3->addWidget(log);
197 log->setWhatsThis(
198 i18n("<p>This controls whether a log window is shown.\n"
199 "A log window shows the communication between\n"
200 "<i>kppp</i> and your modem. This will help you\n"
201 "in tracking down problems.\n"
202 "\n"
203 "Turn it off if <i>kppp</i> routinely connects without\n"
204 "problems"));
206 fline = new KSeparator( Qt::Horizontal, this);
207 tl->addWidget(fline);
209 QHBoxLayout *l2 = new QHBoxLayout;
210 tl->addLayout(l2);
212 int minw = 0;
213 quit_b = new KPushButton(KStandardGuiItem::quit(), this);
214 connect( quit_b, SIGNAL(clicked()), SLOT(quitbutton()));
215 if(quit_b->sizeHint().width() > minw)
216 minw = quit_b->sizeHint().width();
218 setup_b = new KPushButton(KGuiItem(i18n("Co&nfigure..."), "configure"), this);
219 connect( setup_b, SIGNAL(clicked()), SLOT(expandbutton()));
220 if(setup_b->sizeHint().width() > minw)
221 minw = setup_b->sizeHint().width();
223 if(gpppdata.access() != KConfig::ReadWrite)
224 setup_b->setEnabled(false);
226 help_b = new KPushButton(KStandardGuiItem::help(), this);
227 connect( help_b, SIGNAL(clicked()), SLOT(helpbutton()));
229 KHelpMenu *helpMenu = new KHelpMenu(this, KGlobal::mainComponent().aboutData(), true);
230 help_b->setPopup((Q3PopupMenu*)helpMenu->menu());
231 #if 0 //After move kdelibs trunk to kdelibs-snapshot
232 help_b->setMenu(helpMenu->menu());
233 #endif
234 if(help_b->sizeHint().width() > minw)
235 minw = help_b->sizeHint().width();
237 connect_b = new QPushButton(i18n("&Connect"), this);
238 connect_b->setDefault(true);
239 connect_b->setFocus();
240 connect(connect_b, SIGNAL(clicked()), SLOT(beginConnect()));
241 if(connect_b->sizeHint().width() > minw)
242 minw = connect_b->sizeHint().width();
244 quit_b->setFixedWidth(minw);
245 setup_b->setFixedWidth(minw);
246 help_b->setFixedWidth(help_b->sizeHint().width());
247 connect_b->setFixedWidth(minw);
249 l2->addWidget(quit_b);
250 l2->addWidget(setup_b);
251 l2->addWidget(help_b);
252 l2->addSpacing(20);
253 l2->addWidget(connect_b);
255 setFixedSize(sizeHint());
257 (void)new Modem;
259 // we also connect cmld_start to the beginConnect so that I can run
260 // the dialer through a command line argument
261 connect(this,SIGNAL(cmdl_start()),this,SLOT(beginConnect()));
263 stats = new PPPStats;
265 KWin::setIcons(winId(), qApp->windowIcon().pixmap(IconSize(K3Icon::Desktop),IconSize(K3Icon::Desktop)), qApp->windowIcon().pixmap(IconSize(K3Icon::Small),IconSize(K3Icon::Small)));
267 // constructor of con_win reads position from config file
268 con_win = new ConWindow(0, "conw", this, stats);
269 KWin::setIcons(con_win->winId(), qApp->windowIcon().pixmap(IconSize(K3Icon::Desktop),IconSize(K3Icon::Desktop)), qApp->windowIcon().pixmap(IconSize(K3Icon::Small),IconSize(K3Icon::Small)));
271 statdlg = new PPPStatsDlg(0, "stats", this, stats);
272 statdlg->hide();
274 debugwindow = new DebugWidget(0);
275 debugwindow->setObjectName( "debugwindow" );
276 KWin::setIcons(debugwindow->winId(), qApp->windowIcon().pixmap(IconSize(K3Icon::Desktop),IconSize(K3Icon::Desktop)), qApp->windowIcon().pixmap(IconSize(K3Icon::Small),IconSize(K3Icon::Small)));
277 debugwindow->hide();
279 // load up the accounts combo box
281 resetaccounts();
282 resetmodems();
283 con = new ConnectWidget(0, "con", stats);
284 KWin::setIcons(con->winId(), qApp->windowIcon().pixmap(IconSize(K3Icon::Desktop),IconSize(K3Icon::Desktop)), qApp->windowIcon().pixmap(IconSize(K3Icon::Small),IconSize(K3Icon::Small)) );
285 connect(this, SIGNAL(begin_connect()),con, SLOT(preinit()));
287 QRect desk = KGlobalSettings::desktopGeometry(topLevelWidget());
288 con->setGeometry(desk.center().x()-175, desk.center().y()-55, 350,110);
290 // connect the ConnectWidgets various signals
291 connect(con, SIGNAL(closeDebugWindow()),
292 debugwindow, SLOT(hide()));
293 connect(con, SIGNAL(debugMessage(const QString &)),
294 debugwindow, SLOT(statusLabel(const QString &)));
295 connect(con, SIGNAL(toggleDebugWindow()),
296 debugwindow, SLOT(toggleVisibility()));
297 connect(con, SIGNAL(debugPutChar(unsigned char)),
298 debugwindow, SLOT(addChar(unsigned char)));
299 connect(con, SIGNAL(startAccounting()),
300 this, SLOT(startAccounting()));
301 connect(con, SIGNAL(stopAccounting()),
302 this, SLOT(stopAccounting()));
303 connect(KApplication::kApplication(), SIGNAL(saveYourself()),
304 this, SLOT(saveMyself()));
305 connect(KApplication::kApplication(), SIGNAL(aboutToQuit()),
306 this, SLOT(shutDown()));
308 debugwindow->setGeometry(desk.center().x()+190, desk.center().y()-55,
309 debugwindow->width(),debugwindow->height());
311 move(desk.center().x()-width()/2, desk.center().y()-height()/2);
314 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
316 m_strCmdlAccount = args->getOption("c");
317 m_strCmdlModem = args->getOption("m");
318 m_bQuitOnDisconnect = args->isSet("q");
320 if(!m_strCmdlAccount.isEmpty()) {
321 m_bCmdlAccount = true;
322 kDebug(5002) << "cmdl_account: " << m_bCmdlAccount << endl;
325 if(!m_strCmdlModem.isEmpty()) {
326 m_bCmdlModem = true;
327 kDebug(5002) << "cmdl_modem: " << m_bCmdlModem << endl;
330 if(m_bCmdlModem){
331 bool result = gpppdata.setModem(m_strCmdlModem);
332 if (!result){
333 QString string;
334 string = i18n("No such Modem:\n%1\nFalling back to default", m_strCmdlModem);
335 KMessageBox::error(this, string);
336 m_bCmdlModem = false;
340 if(m_bCmdlAccount){
341 bool result = gpppdata.setAccount(m_strCmdlAccount);
342 if (!result){
343 QString string;
344 string = i18n("No such Account:\n%1", m_strCmdlAccount);
345 KMessageBox::error(this, string);
346 m_bCmdlAccount = false;
347 show();
348 } else {
349 beginConnect();
351 } else
352 show();
355 //#define KPPP_SHOW_NEWS
356 #ifdef KPPP_SHOW_NEWS
357 // keep user informed about recent changes
358 if(!m_bCmdlAccount)
359 showNews();
360 #endif
361 #ifdef __GNUC__
362 #warning "kde4: port to dbus"
363 #endif
364 #if 0
365 // attach to the DCOP server, if possible
366 if (!kapp->dcopClient()->attach())
367 kDebug(5002) << "Error: Could not connect to the DCOP server" << endl;
368 else
369 kapp->dcopClient()->registerAs(kapp->name(), true);
370 #endif
371 // this timer will delay the actual disconnection DISCONNECTION_DELAY ms
372 // to give applications time to shutdown, logout, whatever..
373 disconnectTimer = new QTimer(this);
374 connect(disconnectTimer, SIGNAL(timeout()), this, SLOT(delayedDisconnect()));
377 KPPPWidget::~KPPPWidget()
379 delete stats;
382 bool KPPPWidget::eventFilter(QObject *o, QEvent *e) {
383 if(e->type() == QEvent::User) {
384 switch(((SignalEvent*)e)->sigType()) {
385 case SIGINT:
386 kDebug(5002) << "Received a SIGINT" << endl;
387 interruptConnection();
388 break;
389 case SIGCHLD:
390 sigChld();
391 break;
392 case SIGUSR1:
393 sigPPPDDied();
394 break;
396 return true;
399 if(o == connect_b) {
400 if(e->type() == QEvent::KeyPress) {
401 if(connect_b->hasFocus() && ((QKeyEvent *)e)->key() == Qt::Key_Return) {
402 beginConnect();
403 return true;
408 return false;
411 void KPPPWidget::prepareSetupDialog() {
412 if(tabWindow == 0) {
413 tabWindow = new KPageDialog( kapp->mainWidget());
414 tabWindow->setCaption( i18n("KPPP Configuration") );
415 tabWindow->setButtons( KDialog::Ok|KDialog::Cancel );
416 tabWindow->setDefaultButton( KDialog::Ok );
417 tabWindow->setFaceType( KPageDialog::Tabbed );
418 tabWindow->setModal( true );
420 KWin::setIcons(tabWindow->winId(), qApp->windowIcon().pixmap(IconSize(K3Icon::Desktop),IconSize(K3Icon::Desktop)), qApp->windowIcon().pixmap(IconSize(K3Icon::Small),IconSize(K3Icon::Small)));
422 // tabWindow->setFixedSize( 365, 375 );
423 QFrame *frame = new QFrame();
424 KPageWidgetItem *pageItem = new KPageWidgetItem( frame, i18n("&Accounts") );
425 pageItem->setHeader( i18n("Account Setup") );
426 tabWindow->addPage( pageItem );
427 accounts = new AccountWidget(frame);
428 connect(accounts, SIGNAL(resetaccounts()),
429 this, SLOT(resetaccounts()));
430 connect(accounts, SIGNAL(resetCosts(const QString &)),
431 this, SLOT(resetCosts(const QString &)));
432 connect(accounts, SIGNAL(resetVolume(const QString &)),
433 this, SLOT(resetVolume(const QString &)));
436 frame = new QFrame();
437 pageItem = new KPageWidgetItem( frame, i18n("&Modems") );
438 pageItem->setHeader( i18n("Modems Setup") );
439 tabWindow->addPage( pageItem );
440 modems = new ModemsWidget(frame);
441 connect(modems, SIGNAL(resetmodems()),
442 this, SLOT(resetmodems()));
444 frame = new QFrame();
445 pageItem = new KPageWidgetItem( frame, i18n("&Graph") );
446 pageItem->setHeader( i18n("Throughput Graph") );
447 tabWindow->addPage( pageItem );
449 graph = new GraphSetup( frame );
451 frame = new QFrame();
452 pageItem = new KPageWidgetItem( frame, i18n("M&isc") );
453 pageItem->setHeader( i18n("Miscellaneous Settings") );
454 tabWindow->addPage( pageItem );
455 general = new GeneralWidget( frame );
460 void KPPPWidget::enterPressedInID() {
461 PW_Edit->setFocus();
465 void KPPPWidget::enterPressedInPW() {
466 connect_b->setFocus();
469 // triggered by the session manager
470 void KPPPWidget::saveMyself() {
471 gpppdata.save();
474 void KPPPWidget::shutDown() {
475 interruptConnection();
476 saveMyself();
479 void KPPPWidget::log_window_toggled(bool on) {
480 gpppdata.set_show_log_window(on);
484 void KPPPWidget::setup() {
485 prepareSetupDialog();
487 if(tabWindow->exec())
488 gpppdata.save();
489 else
490 gpppdata.cancel();
494 void KPPPWidget::resetaccounts() {
495 connectto_c->clear();
497 int count = gpppdata.accountCount();
499 // enable/disable controls
500 connectto_c->setEnabled(count > 0);
501 setButtons();
503 //load the accounts
504 for(int i=0; i < count; i++) {
505 gpppdata.setAccountByIndex(i);
506 connectto_c->addItem(gpppdata.accname());
509 //set the default account
510 if(!gpppdata.defaultAccount().isEmpty()) {
511 for(int i=0; i < count; i++)
512 if(gpppdata.defaultAccount() == connectto_c->itemText(i)) {
513 connectto_c->setCurrentIndex(i);
514 gpppdata.setAccountByIndex(i);
516 ID_Edit->setText(gpppdata.storedUsername());
517 PW_Edit->setText(gpppdata.storedPassword());
520 else
521 if(count > 0) {
522 gpppdata.setDefaultAccount(connectto_c->itemText(0));
523 gpppdata.save();
524 ID_Edit->setText(gpppdata.storedUsername());
525 PW_Edit->setText(gpppdata.storedPassword());
528 connect(ID_Edit, SIGNAL(textChanged(const QString &)),
529 this, SLOT(usernameChanged(const QString &)));
531 connect(PW_Edit, SIGNAL(textChanged(const QString &)),
532 this, SLOT(passwordChanged(const QString &)));
534 if (ID_Edit->text().isEmpty())
535 ID_Edit->setFocus();
536 else if (PW_Edit->text().isEmpty())
537 PW_Edit->setFocus();
541 void KPPPWidget::resetmodems() {
542 modem_c->clear();
544 int count = gpppdata.modemCount();
546 // enable/disable controls
547 modem_c->setEnabled(count > 0);
548 setButtons();
550 //load the modems
551 for(int i=0; i < count; i++) {
552 gpppdata.setModemByIndex(i);
553 modem_c->addItem(gpppdata.modname());
556 if (count > 1 && !m_bModemCShown) {
557 l1->addWidget(label7, 1, 1);
558 l1->addWidget(modem_c, 1, 2);
559 m_bModemCShown = true;
560 } else if (count <= 1 && m_bModemCShown){
561 l1->removeWidget(label7);
562 l1->removeWidget(modem_c);
563 m_bModemCShown = false;
565 label7->setVisible(m_bModemCShown);
566 modem_c->setVisible(m_bModemCShown);
567 layout()->invalidate();
568 setFixedSize(sizeHint());
570 //set the default modem
571 if(!gpppdata.defaultModem().isEmpty()) {
572 for(int i=0; i < count; i++)
573 if(gpppdata.defaultModem() == modem_c->itemText(i)) {
574 modem_c->setCurrentIndex(i);
575 gpppdata.setModemByIndex(i);
579 else
580 if(count > 0) {
581 gpppdata.setDefaultModem(modem_c->itemText(0));
582 gpppdata.save();
586 void KPPPWidget::setButtons()
588 int acccount = gpppdata.accountCount();
589 int modcount = gpppdata.modemCount();
591 // enable/disable controls
592 connect_b->setEnabled(acccount > 0 && modcount > 0);
593 log->setEnabled(acccount > 0 && modcount > 0);
594 ID_Edit->setEnabled(acccount > 0 && modcount > 0);
595 PW_Edit->setEnabled(acccount > 0 && modcount > 0);
600 void KPPPWidget::interruptConnection() {
601 // interrupt dial up
602 if (con->isVisible())
603 emit con->cancelbutton();
605 // disconnect if online
606 if (gpppdata.pppdRunning())
607 emit disconnect(); /* FIXME: are we emitting a slot here!!!??? */
610 void KPPPWidget::sigPPPDDied() {
611 kDebug(5002) << "Received a SIGUSR1" << endl;
613 // if we are not connected pppdpid is -1 so have have to check for that
614 // in the followin line to make sure that we don't raise a false alarm
615 // such as would be the case when the log file viewer exits.
616 if(gpppdata.pppdRunning() || gpppdata.pppdError()) {
617 kDebug(5002) << "It was pppd that died" << endl;
619 // when we killpppd() on Cancel in ConnectWidget
620 // we set pppid to -1 so we won't
621 // enter this block
623 // just to be sure
624 Requester::rq->removeSecret(AUTH_PAP);
625 Requester::rq->removeSecret(AUTH_CHAP);
627 gpppdata.setpppdRunning(false);
629 // stop the disconnect timer (just in case)
630 disconnectTimer->stop();
631 // signal other applications that we are disconnected now
632 emit sig_disconnected();
633 kDebug(5002) << "Executing command on disconnect since pppd has died." << endl;
634 QApplication::flush();
635 execute_command(gpppdata.command_on_disconnect());
637 stopAccounting();
639 con_win->stopClock();
640 DockWidget::dock_widget->stop_stats();
641 DockWidget::dock_widget->hide();
643 if(!gpppdata.pppdError())
644 gpppdata.setpppdError(E_PPPD_DIED);
645 removedns();
646 Modem::modem->unlockdevice();
647 con->pppdDied();
649 Requester::rq->pppdExitStatus();
650 gpppdata.setWaitCallback(gpppdata.callbackType() && Requester::rq->lastStatus == E_CBCP_WAIT);
652 if(!gpppdata.automatic_redial() && !gpppdata.waitCallback()) {
653 quit_b->setFocus();
654 show();
655 con_win->stopClock();
656 stopAccounting();
657 con_win->hide();
658 con->hide();
660 gpppdata.setpppdRunning(false);
661 // // not in a signal handler !!! KNotifyClient::beep();
662 QString msg;
663 if (gpppdata.pppdError() == E_IF_TIMEOUT)
664 msg = i18n("Timeout expired while waiting for the PPP interface "
665 "to come up.");
666 else {
667 msg = i18n("<p>The pppd daemon died unexpectedly!</p>");
668 Requester::rq->pppdExitStatus();
669 if (Requester::rq->lastStatus != 99) { // more recent pppds only
670 msg += i18n("<p>Exit status: %1", Requester::rq->lastStatus);
671 msg += i18n("</p><p>See 'man pppd' for an explanation of the error "
672 "codes or take a look at the kppp FAQ on "
673 " <a href=\"%1\">%1</a></p>",
674 QString("http://developer.kde.org/~kppp/index.html"));
678 if(KMessageBox::warningYesNo(0, msg, i18n("Error"), KStandardGuiItem::ok(), KGuiItem(i18n("&Details"))) == KMessageBox::No)
679 PPPL_ShowLog();
680 } else { /* reconnect on disconnect */
681 if(gpppdata.waitCallback())
682 kDebug(5002) << "Waiting for callback... " << endl;
683 else
684 kDebug(5002) << "Trying to reconnect... " << endl;
686 if(gpppdata.authMethod() == AUTH_PAP ||
687 gpppdata.authMethod() == AUTH_CHAP ||
688 gpppdata.authMethod() == AUTH_PAPCHAP)
689 Requester::rq->setSecret(gpppdata.authMethod(),
690 encodeWord(gpppdata.storedUsername()),
691 encodeWord(gpppdata.password()));
693 con_win->hide();
694 con_win->stopClock();
695 stopAccounting();
696 gpppdata.setpppdRunning(false);
697 // not in a signal handler !!! KNotifyClient::beep();
698 emit cmdl_start();
701 gpppdata.setpppdError(0);
705 void KPPPWidget::sigChld() {
706 kDebug(5002) << "sigchld()" << endl;
707 // pid_t id = wait(0L);
708 // if(id == helperPid && helperPid != -1) {
709 // kDebug(5002) << "It was the setuid child that died" << endl;
710 // helperPid = -1;
711 QString msg = i18n("kppp's helper process just died.\n"
712 "Since further execution would be pointless, "
713 "kppp will shut down now.");
714 KMessageBox::error(0L, msg);
715 remove_pidfile();
716 exit(1);
717 // }
721 void KPPPWidget::newdefaultaccount(int i) {
722 gpppdata.setDefaultAccount(connectto_c->itemText(i));
723 gpppdata.save();
724 ID_Edit->setText(gpppdata.storedUsername());
725 PW_Edit->setText(gpppdata.storedPassword());
728 void KPPPWidget::newdefaultmodem(int i) {
729 gpppdata.setDefaultModem(modem_c->itemText(i));
730 gpppdata.save();
735 void KPPPWidget::expandbutton() {
736 setup();
740 void KPPPWidget::beginConnect() {
741 // make sure to connect to the account that is selected in the combo box
742 // (exeption: an account given by a command line argument)
743 if(!m_bCmdlAccount) {
744 gpppdata.setAccount(connectto_c->currentText());
745 gpppdata.setPassword(PW_Edit->text());
746 } else {
747 gpppdata.setPassword(gpppdata.storedPassword());
750 QFileInfo info(pppdPath());
752 if(!info.exists()){
753 KMessageBox::error(this, i18n("Cannot find the PPP daemon!\n"
754 "Make sure that pppd is installed and "
755 "that you have entered the correct path."));
756 return;
758 #if 0
759 if(!info.isExecutable()){
761 QString string;
762 string = i18n("kppp cannot execute:\n %1\n"
763 "Please make sure that you have given kppp "
764 "setuid permission and that "
765 "pppd is executable.", gpppdata.pppdPath());
766 KMessageBox::error(this, string);
767 return;
770 #endif
772 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
773 QString device = "";
774 if (args->isSet("dev"))
775 device = args->getOption("dev");
776 else
777 device = gpppdata.modemDevice();
779 QFileInfo info2(device);
781 if(!info2.exists()){
782 QString string;
783 string = i18n("kppp can not find:\n %1\nPlease make sure you have setup "
784 "your modem device properly "
785 "and/or adjust the location of the modem device on "
786 "the modem tab of "
787 "the setup dialog.", device);
788 KMessageBox::error(this, string);
789 return;
792 // if this is a PAP or CHAP account, ensure that username is
793 // supplied
794 if(gpppdata.authMethod() == AUTH_PAP ||
795 gpppdata.authMethod() == AUTH_CHAP ||
796 gpppdata.authMethod() == AUTH_PAPCHAP ) {
797 if(ID_Edit->text().isEmpty()) {
798 KMessageBox::error(this,
799 i18n(
800 "You have selected the authentication "
801 "method PAP or CHAP. This requires that you "
802 "supply a username and a password."));
803 return;
804 } else {
805 if(!Requester::rq->setSecret(gpppdata.authMethod(),
806 encodeWord(gpppdata.storedUsername()),
807 encodeWord(gpppdata.password()))) {
808 QString s;
809 s = i18n("Cannot create PAP/CHAP authentication\n"
810 "file \"%1\"", QString(PAP_AUTH_FILE));
811 KMessageBox::error(this, s);
812 return;
817 if (gpppdata.phonenumber().isEmpty()) {
818 QString s = i18n("You must specify a telephone number.");
819 KMessageBox::error(this, s);
820 return;
823 hide();
825 QString tit = i18n("Connecting to: %1", gpppdata.accname());
826 con->setWindowTitle(tit);
827 con->enableButtons();
828 con->show();
830 bool show_debug = gpppdata.get_show_log_window();
831 con->debug->setChecked(show_debug); // toggle button
832 debugwindow->clear();
833 if (!show_debug)
834 debugwindow->hide();
835 else {
836 debugwindow->show();
837 con->raise();
840 emit begin_connect();
843 void KPPPWidget::disconnect() {
844 if (disconnectTimer->isActive()) return; // you had already pressed disconnect before
846 // signal other applications that we are about to go offline now
847 emit sig_aboutToDisconnect();
849 con_win->hide();
850 con->show();
851 con->disableButtons(); // will reenable them later in delayedDisconnect()
852 con->setWindowTitle(i18n("Disconnecting..."));
854 if (!gpppdata.command_before_disconnect().isEmpty()) {
855 con->setMsg(i18n("Executing command before disconnection."));
857 kapp->processEvents();
858 QApplication::flush();
859 pid_t id = execute_command(gpppdata.command_before_disconnect());
860 int i, status;
862 do {
863 kapp->processEvents();
864 i = waitpid(id, &status, WNOHANG);
865 usleep(500000);
866 } while (i == 0 && errno == 0);
869 con->setMsg(i18n("Announcing disconnection."));
871 // this is no longer necessary since I'm delaying disconnection usign a QTimer
872 // kapp->processEvents();
874 // set the timer to call delayedDisconnect() in DISCONNECT_DELAY ms
875 disconnectTimer->setSingleShot(true);
876 disconnectTimer->start(DISCONNECT_DELAY);
879 void KPPPWidget::delayedDisconnect() {
880 // this is where the actual disconnection takes place
881 con->hide();
883 statdlg->stop_stats();
884 Requester::rq->killPPPDaemon();
886 // signal other applications that we are disconnected now
887 emit sig_disconnected();
888 QApplication::flush();
889 execute_command(gpppdata.command_on_disconnect());
891 Requester::rq->removeSecret(AUTH_PAP);
892 Requester::rq->removeSecret(AUTH_CHAP);
894 removedns();
895 Modem::modem->unlockdevice();
897 con_win->stopClock();
898 p_kppp->stopAccounting();
899 con_win->hide();
901 DockWidget::dock_widget->stop_stats();
902 DockWidget::dock_widget->hide();
904 if(m_bQuitOnDisconnect)
905 kapp->exit(0);
906 else {
907 quit_b->setFocus();
908 show();
913 void KPPPWidget::helpbutton() {
914 KToolInvocation::invokeHelp();
918 void KPPPWidget::quitbutton() {
919 if(gpppdata.pppdRunning()) {
920 int ok = KMessageBox::warningContinueCancel(this,
921 i18n("Exiting kPPP will close your PPP Session."),
922 i18n("Quit kPPP?"), KStandardGuiItem::quit());
923 if(ok == KMessageBox::Continue) {
924 Requester::rq->killPPPDaemon();
926 // stop the disconnect delay timer
927 disconnectTimer->stop();
929 // signal other applications that we are disconnected now
930 emit sig_disconnected();
931 QApplication::flush();
932 execute_command(gpppdata.command_on_disconnect());
933 removedns();
934 Modem::modem->unlockdevice();
936 } else {
937 if (!gpppdata.accname().isEmpty() && !gpppdata.storePassword())
938 gpppdata.setStoredPassword("");
940 gpppdata.save();
941 kapp->quit();
945 void KPPPWidget::rulesetLoadError() {
946 KMessageBox::error(this, ruleset_load_errmsg);
950 void KPPPWidget::startAccounting() {
951 // volume accounting
952 stats->totalbytes = 0;
954 kDebug(5002) << "AcctEnabled: " << gpppdata.AcctEnabled() << endl;
956 // load the ruleset
957 if(!gpppdata.AcctEnabled())
958 return;
960 QString d = AccountingBase::getAccountingFile(gpppdata.accountingFile());
961 // if(::access(d.data(), X_OK) != 0)
962 acct = new Accounting(this, stats);
963 // else
964 // acct = new ExecutableAccounting(this);
966 // connect to the accounting object
967 connect(acct, SIGNAL(changed(QString, QString)),
968 con_win, SLOT(slotAccounting(QString, QString)));
970 if(!acct->loadRuleSet(gpppdata.accountingFile())) {
971 QString s= i18n("Can not load the accounting "
972 "ruleset \"%1\".", gpppdata.accountingFile());
974 // starting the messagebox with a timer will prevent us
975 // from blocking the calling function ConnectWidget::timerEvent
976 ruleset_load_errmsg = s;
977 QTimer::singleShot(0, this, SLOT(rulesetLoadError()));
978 return;
979 } else
980 acct->slotStart();
983 void KPPPWidget::stopAccounting() {
984 // store volume accounting
985 if(stats->totalbytes != 0)
986 gpppdata.setTotalBytes(stats->totalbytes);
988 if(!gpppdata.AcctEnabled())
989 return;
991 if(acct != 0) {
992 acct->slotStop();
993 delete acct;
994 acct = 0;
999 void KPPPWidget::showStats() {
1000 if(statdlg) {
1001 statdlg->toCurrentDesktop();
1002 statdlg->show();
1003 statdlg->raise();
1008 void KPPPWidget::usernameChanged(const QString &) {
1009 // store username for later use
1010 gpppdata.setStoredUsername(ID_Edit->text());
1014 void KPPPWidget::passwordChanged(const QString &) {
1015 // store the password if so requested
1016 if(gpppdata.storePassword())
1017 gpppdata.setStoredPassword(PW_Edit->text());
1018 else
1019 gpppdata.setStoredPassword("");
1023 void KPPPWidget::setPW_Edit(const QString &pw) {
1024 PW_Edit->setText(pw);
1028 void KPPPWidget::resetCosts(const QString &s) {
1029 AccountingBase::resetCosts(s);
1033 void KPPPWidget::resetVolume(const QString &s) {
1034 AccountingBase::resetVolume(s);
1038 * pppd's getword() function knows about escape characters.
1039 * If we write the username and password to the secrets file
1040 * we'll therefore have to escape back slashes.
1042 QString KPPPWidget::encodeWord(const QString &s) {
1043 QString r = s;
1044 r.replace(QRegExp("\\"), "\\\\");
1045 return r;
1048 void KPPPWidget::setQuitOnDisconnect (bool b)
1050 m_bQuitOnDisconnect = b;
1053 void KPPPWidget::showNews() {
1054 #ifdef KPPP_SHOW_NEWS
1056 * Introduce the QuickHelp feature to new users of this version
1058 #define QUICKHELP_HINT "Hint_QuickHelp"
1059 if(gpppdata.readNumConfig(GENERAL_GRP, QUICKHELP_HINT, 0) == 0) {
1060 KDialog dlg();
1061 dlg.setCaption(i18n("Recent Changes in KPPP"));
1063 QVBoxLayout *tl = new QVBoxLayout(&dlg);
1064 tl->setSpacing(10);
1065 tl->setMargin(10);
1066 QHBoxLayout *l1 = new QHBoxLayout(10);
1067 QVBoxLayout *l2 = new QVBoxLayout(10);
1068 tl->addLayout(l1);
1070 QLabel *icon = new QLabel(&dlg);
1071 icon->setPixmap(BarIcon("exclamation"));
1072 icon->setFixedSize(icon->sizeHint());
1073 l1->addWidget(icon);
1074 l1->addLayout(l2);
1076 QLabel *l = new QLabel(i18n("From version 1.4.8 on, kppp has a new feature\n"
1077 "called \"Quickhelp\". It's similar to a tooltip,\n"
1078 "but you can activate it whenever you want.\n"
1079 "\n"
1080 "To activate it, simply click on a control like\n"
1081 "a button or a label with the right mouse button.\n"
1082 "If the item supports Quickhelp, a popup menu\n"
1083 "will appear leading to Quickhelp.\n"
1084 "\n"
1085 "To test it, right-click somewhere in this text."),
1086 &dlg);
1088 QCheckBox *cb = new QCheckBox(i18n("Do not show this hint again"), &dlg);
1089 cb->setFixedSize(cb->sizeHint());
1091 dlg.setButtons(Ok)
1093 l2->addWidget(l);
1094 l2->addWidget(cb);
1096 QString tmp = i18n("This is an example of <b>QuickHelp</b>.\n"
1097 "This window will stay open until you\n"
1098 "click a mouse button or a press a key.\n");
1100 cb->setWhatsThis(tmp);
1101 l->setWhatsThis( tmp);
1103 dlg.exec();
1104 if(cb->isChecked()) {
1105 gpppdata.writeConfig(GENERAL_GRP, QUICKHELP_HINT, 1);
1106 gpppdata.save();
1109 #endif
1113 #include "kpppwidget.moc"