kpassdlg.cpp
00001 // vi: ts=8 sts=4 sw=4 00002 /* This file is part of the KDE libraries 00003 Copyright (C) 1998 Pietro Iglio <iglio@fub.it> 00004 Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org> 00005 Copyright (C) 2004,2005 Andrew Coles <andrew_coles@yahoo.co.uk> 00006 00007 This library is free software; you can redistribute it and/or 00008 modify it under the terms of the GNU Library General Public 00009 License version 2 as published by the Free Software Foundation. 00010 00011 This library is distributed in the hope that it will be useful, 00012 but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 Library General Public License for more details. 00015 00016 You should have received a copy of the GNU Library General Public License 00017 along with this library; see the file COPYING.LIB. If not, write to 00018 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 00019 Boston, MA 02110-1301, USA. 00020 */ 00021 #include <unistd.h> 00022 00023 #include <tqwidget.h> 00024 #include <tqlineedit.h> 00025 #include <tqlabel.h> 00026 #include <tqlayout.h> 00027 #include <tqsize.h> 00028 #include <tqevent.h> 00029 #include <tqkeycode.h> 00030 #include <tqcheckbox.h> 00031 #include <tqregexp.h> 00032 #include <tqhbox.h> 00033 #include <tqwhatsthis.h> 00034 #include <tqptrdict.h> 00035 #include <tqtimer.h> 00036 00037 #include <tdeglobal.h> 00038 #include <kdebug.h> 00039 #include <tdeapplication.h> 00040 #include <tdelocale.h> 00041 #include <kiconloader.h> 00042 #include <tdemessagebox.h> 00043 #include <tdeaboutdialog.h> 00044 #include <tdeconfig.h> 00045 #include <kstandarddirs.h> 00046 #include <kprogress.h> 00047 00048 #include <sys/time.h> 00049 #include <sys/resource.h> 00050 00051 #include "kpassdlg.h" 00052 00053 #include "../tdesu/defaults.h" 00054 00055 /* 00056 * Password line editor. 00057 */ 00058 00059 const int KPasswordEdit::PassLen = 200; 00060 00061 class KPasswordDialog::KPasswordDialogPrivate 00062 { 00063 public: 00064 KPasswordDialogPrivate() 00065 : m_MatchLabel( 0 ), iconName( 0 ), allowEmptyPasswords( false ), 00066 minimumPasswordLength(0), maximumPasswordLength(KPasswordEdit::PassLen - 1), 00067 passwordStrengthWarningLevel(1), m_strengthBar(0), 00068 reasonablePasswordLength(8) 00069 {} 00070 TQLabel *m_MatchLabel; 00071 TQString iconName; 00072 bool allowEmptyPasswords; 00073 int minimumPasswordLength; 00074 int maximumPasswordLength; 00075 int passwordStrengthWarningLevel; 00076 KProgress* m_strengthBar; 00077 int reasonablePasswordLength; 00078 }; 00079 00080 00081 KPasswordEdit::KPasswordEdit(TQWidget *parent, const char *name) 00082 : TQLineEdit(parent, name) 00083 { 00084 init(); 00085 00086 TDEConfig* const cfg = TDEGlobal::config(); 00087 TDEConfigGroupSaver saver(cfg, "Passwords"); 00088 00089 const TQString val = cfg->readEntry("EchoMode", "OneStar"); 00090 if (val == "ThreeStars") { 00091 setEchoMode(PasswordThreeStars); 00092 } 00093 else if (val == "NoEcho") { 00094 setEchoMode(TQLineEdit::NoEcho); 00095 } 00096 else { 00097 setEchoMode(TQLineEdit::Password); 00098 } 00099 00100 setInputMethodEnabled( true ); 00101 } 00102 00103 KPasswordEdit::KPasswordEdit(TQWidget *parent, const char *name, int echoMode) 00104 : TQLineEdit(parent, name) 00105 { 00106 setEchoMode((TQLineEdit::EchoMode)echoMode); 00107 init(); 00108 } 00109 00110 KPasswordEdit::KPasswordEdit(EchoMode echoMode, TQWidget *parent, const char *name) 00111 : TQLineEdit(parent, name) 00112 { 00113 setEchoMode(echoMode); 00114 init(); 00115 } 00116 00117 KPasswordEdit::KPasswordEdit(EchoModes echoMode, TQWidget *parent, const char *name) 00118 : TQLineEdit(parent, name) 00119 { 00120 if (echoMode == KPasswordEdit::NoEcho) { 00121 setEchoMode(TQLineEdit::NoEcho); 00122 } 00123 else if (echoMode == KPasswordEdit::ThreeStars) { 00124 setEchoMode(TQLineEdit::PasswordThreeStars); 00125 } 00126 else if (echoMode == KPasswordEdit::OneStar) { 00127 setEchoMode(TQLineEdit::Password); 00128 } 00129 init(); 00130 } 00131 00132 void KPasswordEdit::init() 00133 { 00134 setAcceptDrops(false); 00135 } 00136 00137 KPasswordEdit::~KPasswordEdit() 00138 { 00139 } 00140 00141 TQString KPasswordEdit::password() const { 00142 return text(); 00143 } 00144 00145 void KPasswordEdit::erase() 00146 { 00147 setText(""); 00148 } 00149 00150 void KPasswordEdit::setMaxPasswordLength(int newLength) 00151 { 00152 setMaxLength(newLength); 00153 } 00154 00155 int KPasswordEdit::maxPasswordLength() const 00156 { 00157 return maxLength(); 00158 } 00159 00160 void KPasswordEdit::insert( const TQString &str) { 00161 TQLineEdit::insert(str); 00162 } 00163 00164 void KPasswordEdit::keyPressEvent(TQKeyEvent *e) { 00165 TQLineEdit::keyPressEvent(e); 00166 } 00167 00168 void KPasswordEdit::focusInEvent(TQFocusEvent *e) { 00169 TQLineEdit::focusInEvent(e); 00170 } 00171 00172 bool KPasswordEdit::event(TQEvent *e) { 00173 return TQLineEdit::event(e); 00174 } 00175 00176 /* 00177 * Password dialog. 00178 */ 00179 00180 KPasswordDialog::KPasswordDialog(Types type, bool enableKeep, int extraBttn, 00181 TQWidget *parent, const char *name) 00182 : KDialogBase(parent, name, true, "", Ok|Cancel|extraBttn, 00183 Ok, true), m_Keep(enableKeep? 1 : 0), m_Type(type), m_keepWarnLbl(0), d(new KPasswordDialogPrivate) 00184 { 00185 d->iconName = "password"; 00186 init(); 00187 } 00188 00189 KPasswordDialog::KPasswordDialog(Types type, bool enableKeep, int extraBttn, const TQString& icon, 00190 TQWidget *parent, const char *name ) 00191 : KDialogBase(parent, name, true, "", Ok|Cancel|extraBttn, 00192 Ok, true), m_Keep(enableKeep? 1 : 0), m_Type(type), m_keepWarnLbl(0), d(new KPasswordDialogPrivate) 00193 { 00194 if ( icon.stripWhiteSpace().isEmpty() ) 00195 d->iconName = "password"; 00196 else 00197 d->iconName = icon; 00198 init(); 00199 } 00200 00201 KPasswordDialog::KPasswordDialog(int type, TQString prompt, bool enableKeep, 00202 int extraBttn) 00203 : KDialogBase(0L, "Password Dialog", true, "", Ok|Cancel|extraBttn, 00204 Ok, true), m_Keep(enableKeep? 1 : 0), m_Type(type), m_keepWarnLbl(0), d(new KPasswordDialogPrivate) 00205 { 00206 d->iconName = "password"; 00207 init(); 00208 setPrompt(prompt); 00209 } 00210 00211 void KPasswordDialog::init() 00212 { 00213 m_Row = 0; 00214 00215 TDEConfig* const cfg = TDEGlobal::config(); 00216 const TDEConfigGroupSaver saver(cfg, "Passwords"); 00217 bool def = ( qstrcmp( tqAppName(), "tdesu" ) == 0 ? defKeep : false ); 00218 if (m_Keep && cfg->readBoolEntry("Keep", def)) 00219 ++m_Keep; 00220 00221 m_pMain = new TQWidget(this); 00222 setMainWidget(m_pMain); 00223 m_pGrid = new TQGridLayout(m_pMain, 10, 3, 0, 0); 00224 m_pGrid->addColSpacing(1, 10); 00225 00226 // Row 1: pixmap + prompt 00227 TQLabel *lbl; 00228 const TQPixmap pix( TDEGlobal::iconLoader()->loadIcon( d->iconName, TDEIcon::NoGroup, TDEIcon::SizeHuge, 0, 0, true)); 00229 if (!pix.isNull()) { 00230 lbl = new TQLabel(m_pMain); 00231 lbl->setPixmap(pix); 00232 lbl->setAlignment(AlignHCenter|AlignVCenter); 00233 lbl->setFixedSize(lbl->sizeHint()); 00234 m_pGrid->addWidget(lbl, 0, 0, (TQ_Alignment)AlignCenter); 00235 } 00236 00237 m_pHelpLbl = new TQLabel(m_pMain); 00238 m_pHelpLbl->setAlignment(AlignLeft|AlignVCenter|WordBreak); 00239 m_pGrid->addWidget(m_pHelpLbl, 0, 2, (TQ_Alignment)AlignLeft); 00240 m_pGrid->addRowSpacing(1, 10); 00241 m_pGrid->setRowStretch(1, 12); 00242 00243 // Row 2+: space for 4 extra info lines 00244 m_pGrid->addRowSpacing(6, 5); 00245 m_pGrid->setRowStretch(6, 12); 00246 00247 // Row 3: Password editor #1 00248 lbl = new TQLabel(m_pMain); 00249 lbl->setAlignment(AlignLeft|AlignVCenter); 00250 lbl->setText(i18n("&Password:")); 00251 lbl->setFixedSize(lbl->sizeHint()); 00252 m_pGrid->addWidget(lbl, 7, 0, (TQ_Alignment)AlignLeft); 00253 00254 TQHBoxLayout *h_lay = new TQHBoxLayout(); 00255 m_pGrid->addLayout(h_lay, 7, 2); 00256 m_pEdit = new KPasswordEdit(m_pMain); 00257 m_pEdit2 = 0; 00258 lbl->setBuddy(m_pEdit); 00259 TQSize size = m_pEdit->sizeHint(); 00260 m_pEdit->setFixedHeight(size.height()); 00261 m_pEdit->setMinimumWidth(size.width()); 00262 h_lay->addWidget(m_pEdit); 00263 00264 // Row 4: Password editor #2 or keep password checkbox 00265 00266 if ((m_Type == Password) && m_Keep) { 00267 m_pGrid->addRowSpacing(8, 10); 00268 m_pGrid->setRowStretch(8, 12); 00269 TQCheckBox* const cb = new TQCheckBox(i18n("&Keep password"), m_pMain); 00270 cb->setFixedSize(cb->sizeHint()); 00271 m_keepWarnLbl = new TQLabel(m_pMain); 00272 m_keepWarnLbl->setAlignment(AlignLeft|AlignVCenter|WordBreak); 00273 if (m_Keep > 1) { 00274 cb->setChecked(true); 00275 m_keepWarnLbl->show(); 00276 } 00277 else { 00278 m_Keep = 0; 00279 m_keepWarnLbl->hide(); 00280 } 00281 connect(cb, TQT_SIGNAL(toggled(bool)), TQT_SLOT(slotKeep(bool))); 00282 m_pGrid->addWidget(cb, 9, 2, (TQ_Alignment)(AlignLeft|AlignVCenter)); 00283 // m_pGrid->addWidget(m_keepWarnLbl, 13, 2, (TQ_Alignment)(AlignLeft|AlignVCenter)); 00284 m_pGrid->addMultiCellWidget(m_keepWarnLbl, 13, 13, 0, 3); 00285 } else if (m_Type == NewPassword) { 00286 m_pGrid->addRowSpacing(8, 10); 00287 lbl = new TQLabel(m_pMain); 00288 lbl->setAlignment(AlignLeft|AlignVCenter); 00289 lbl->setText(i18n("&Verify:")); 00290 lbl->setFixedSize(lbl->sizeHint()); 00291 m_pGrid->addWidget(lbl, 9, 0, (TQ_Alignment)AlignLeft); 00292 00293 h_lay = new TQHBoxLayout(); 00294 m_pGrid->addLayout(h_lay, 9, 2); 00295 m_pEdit2 = new KPasswordEdit(m_pMain); 00296 lbl->setBuddy(m_pEdit2); 00297 size = m_pEdit2->sizeHint(); 00298 m_pEdit2->setFixedHeight(size.height()); 00299 m_pEdit2->setMinimumWidth(size.width()); 00300 h_lay->addWidget(m_pEdit2); 00301 00302 // Row 6: Password strength meter 00303 m_pGrid->addRowSpacing(10, 10); 00304 m_pGrid->setRowStretch(10, 12); 00305 00306 TQHBox* const strengthBox = new TQHBox(m_pMain); 00307 strengthBox->setSpacing(10); 00308 m_pGrid->addMultiCellWidget(strengthBox, 11, 11, 0, 2); 00309 TQLabel* const passStrengthLabel = new TQLabel(strengthBox); 00310 passStrengthLabel->setAlignment(AlignLeft|AlignVCenter); 00311 passStrengthLabel->setText(i18n("Password strength meter:")); 00312 d->m_strengthBar = new KProgress(100, strengthBox, "PasswordStrengthMeter"); 00313 d->m_strengthBar->setPercentageVisible(false); 00314 00315 const TQString strengthBarWhatsThis(i18n("The password strength meter gives an indication of the security " 00316 "of the password you have entered. To improve the strength of " 00317 "the password, try:\n" 00318 " - using a longer password;\n" 00319 " - using a mixture of upper- and lower-case letters;\n" 00320 " - using numbers or symbols, such as #, as well as letters.")); 00321 TQWhatsThis::add(passStrengthLabel, strengthBarWhatsThis); 00322 TQWhatsThis::add(d->m_strengthBar, strengthBarWhatsThis); 00323 00324 // Row 6: Label saying whether the passwords match 00325 m_pGrid->addRowSpacing(12, 10); 00326 m_pGrid->setRowStretch(12, 12); 00327 00328 d->m_MatchLabel = new TQLabel(m_pMain); 00329 d->m_MatchLabel->setAlignment(AlignLeft|AlignVCenter|WordBreak); 00330 m_pGrid->addMultiCellWidget(d->m_MatchLabel, 13, 13, 0, 2); 00331 d->m_MatchLabel->setText(i18n("Passwords do not match")); 00332 00333 00334 connect( m_pEdit, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(enableOkBtn()) ); 00335 connect( m_pEdit2, TQT_SIGNAL(textChanged(const TQString&)), TQT_SLOT(enableOkBtn()) ); 00336 enableOkBtn(); 00337 } 00338 00339 erase(); 00340 } 00341 00342 00343 KPasswordDialog::~KPasswordDialog() 00344 { 00345 delete d; 00346 } 00347 00348 00349 void KPasswordDialog::clearPassword() 00350 { 00351 m_pEdit->erase(); 00352 } 00353 00354 /* KDE 4: Make it const TQString & */ 00355 void KPasswordDialog::setPrompt(TQString prompt) 00356 { 00357 m_pHelpLbl->setText(prompt); 00358 m_pHelpLbl->setFixedSize(275, m_pHelpLbl->heightForWidth(275)); 00359 } 00360 00361 void KPasswordDialog::setKeepWarning(TQString warn) 00362 { 00363 if (m_keepWarnLbl) { 00364 m_keepWarnLbl->setText(warn); 00365 } 00366 } 00367 00368 00369 TQString KPasswordDialog::prompt() const 00370 00371 { 00372 return m_pHelpLbl->text(); 00373 } 00374 00375 00376 /* KDE 4: Make them const TQString & */ 00377 void KPasswordDialog::addLine(TQString key, TQString value) 00378 { 00379 if (m_Row > 3) 00380 return; 00381 00382 TQLabel *lbl = new TQLabel(key, m_pMain); 00383 lbl->setAlignment(AlignLeft|AlignTop); 00384 lbl->setFixedSize(lbl->sizeHint()); 00385 m_pGrid->addWidget(lbl, m_Row+2, 0, (TQ_Alignment)AlignLeft); 00386 00387 lbl = new TQLabel(value, m_pMain); 00388 lbl->setAlignment(AlignTop|WordBreak); 00389 lbl->setFixedSize(275, lbl->heightForWidth(275)); 00390 m_pGrid->addWidget(lbl, m_Row+2, 2, (TQ_Alignment)AlignLeft); 00391 ++m_Row; 00392 } 00393 00394 00395 void KPasswordDialog::erase() 00396 { 00397 m_pEdit->erase(); 00398 m_pEdit->setFocus(); 00399 if (m_Type == NewPassword) 00400 m_pEdit2->erase(); 00401 } 00402 00403 00404 void KPasswordDialog::slotOk() 00405 { 00406 if (m_Type == NewPassword) { 00407 if (m_pEdit->password() != m_pEdit2->password()) { 00408 KMessageBox::sorry(this, i18n("You entered two different " 00409 "passwords. Please try again.")); 00410 erase(); 00411 return; 00412 } 00413 if (d->m_strengthBar && d->m_strengthBar->progress() < d->passwordStrengthWarningLevel) { 00414 int retVal = KMessageBox::warningContinueCancel(this, 00415 i18n( "The password you have entered has a low strength. " 00416 "To improve the strength of " 00417 "the password, try:\n" 00418 " - using a longer password;\n" 00419 " - using a mixture of upper- and lower-case letters;\n" 00420 " - using numbers or symbols as well as letters.\n" 00421 "\n" 00422 "Would you like to use this password anyway?"), 00423 i18n("Low Password Strength")); 00424 if (retVal == KMessageBox::Cancel) return; 00425 } 00426 } 00427 if (!checkPassword(m_pEdit->password())) { 00428 erase(); 00429 return; 00430 } 00431 accept(); 00432 } 00433 00434 00435 void KPasswordDialog::slotCancel() 00436 { 00437 reject(); 00438 } 00439 00440 00441 void KPasswordDialog::slotKeep(bool keep) 00442 { 00443 if (m_keepWarnLbl->text() != "") { 00444 if (keep) { 00445 m_keepWarnLbl->show(); 00446 } 00447 else { 00448 m_keepWarnLbl->hide(); 00449 } 00450 TQTimer::singleShot(0, this, SLOT(slotLayout())); 00451 } 00452 00453 m_Keep = keep; 00454 } 00455 00456 void KPasswordDialog::slotLayout() 00457 { 00458 resize(sizeHint()); 00459 } 00460 00461 00462 int KPasswordDialog::getPassword(TQString &password, TQString prompt, 00463 int *keep) 00464 { 00465 const bool enableKeep = (keep && *keep); 00466 KPasswordDialog* const dlg = new KPasswordDialog(int(Password), prompt, enableKeep); 00467 const int ret = dlg->exec(); 00468 if (ret == Accepted) { 00469 password = dlg->password(); 00470 if (enableKeep) 00471 *keep = dlg->keep(); 00472 } 00473 delete dlg; 00474 return ret; 00475 } 00476 00477 00478 // static . antlarr: KDE 4: Make it const TQString & prompt 00479 int KPasswordDialog::getNewPassword(TQString &password, TQString prompt) 00480 { 00481 KPasswordDialog* const dlg = new KPasswordDialog(NewPassword, prompt); 00482 const int ret = dlg->exec(); 00483 if (ret == Accepted) 00484 password = dlg->password(); 00485 delete dlg; 00486 return ret; 00487 } 00488 00489 00490 // static 00491 void KPasswordDialog::disableCoreDumps() 00492 { 00493 struct rlimit rlim; 00494 rlim.rlim_cur = rlim.rlim_max = 0; 00495 setrlimit(RLIMIT_CORE, &rlim); 00496 } 00497 00498 void KPasswordDialog::virtual_hook( int id, void* data ) 00499 { KDialogBase::virtual_hook( id, data ); } 00500 00501 void KPasswordDialog::enableOkBtn() 00502 { 00503 if (m_Type == NewPassword) { 00504 const bool match = (m_pEdit->password() == m_pEdit2->password()) 00505 && (d->allowEmptyPasswords || !m_pEdit->password().isEmpty()); 00506 00507 const TQString pass(m_pEdit->password()); 00508 00509 const int minPasswordLength = minimumPasswordLength(); 00510 00511 if ((int) pass.length() < minPasswordLength) { 00512 enableButtonOK(false); 00513 } else { 00514 enableButtonOK( match ); 00515 } 00516 00517 if ( match && d->allowEmptyPasswords && m_pEdit->password().isEmpty() ) { 00518 d->m_MatchLabel->setText( i18n("Password is empty") ); 00519 } else { 00520 if ((int) pass.length() < minPasswordLength) { 00521 d->m_MatchLabel->setText(i18n("Password must be at least 1 character long", "Password must be at least %n characters long", minPasswordLength)); 00522 } else { 00523 d->m_MatchLabel->setText( match? i18n("Passwords match") 00524 :i18n("Passwords do not match") ); 00525 } 00526 } 00527 00528 // Password strength calculator 00529 // Based on code in the Master Password dialog in Firefox 00530 // (pref-masterpass.js) 00531 // Original code triple-licensed under the MPL, GPL, and LGPL 00532 // so is license-compatible with this file 00533 00534 const double lengthFactor = d->reasonablePasswordLength / 8.0; 00535 00536 00537 int pwlength = (int) (pass.length() / lengthFactor); 00538 if (pwlength > 5) pwlength = 5; 00539 00540 const TQRegExp numRxp("[0-9]", true, false); 00541 int numeric = (int) (pass.contains(numRxp) / lengthFactor); 00542 if (numeric > 3) numeric = 3; 00543 00544 const TQRegExp symbRxp("\\W", false, false); 00545 int numsymbols = (int) (pass.contains(symbRxp) / lengthFactor); 00546 if (numsymbols > 3) numsymbols = 3; 00547 00548 const TQRegExp upperRxp("[A-Z]", true, false); 00549 int upper = (int) (pass.contains(upperRxp) / lengthFactor); 00550 if (upper > 3) upper = 3; 00551 00552 int pwstrength=((pwlength*10)-20) + (numeric*10) + (numsymbols*15) + (upper*10); 00553 00554 if ( pwstrength < 0 ) { 00555 pwstrength = 0; 00556 } 00557 00558 if ( pwstrength > 100 ) { 00559 pwstrength = 100; 00560 } 00561 d->m_strengthBar->setProgress(pwstrength); 00562 00563 } 00564 } 00565 00566 00567 void KPasswordDialog::setAllowEmptyPasswords(bool allowed) { 00568 d->allowEmptyPasswords = allowed; 00569 enableOkBtn(); 00570 } 00571 00572 00573 bool KPasswordDialog::allowEmptyPasswords() const { 00574 return d->allowEmptyPasswords; 00575 } 00576 00577 void KPasswordDialog::setMinimumPasswordLength(int minLength) { 00578 d->minimumPasswordLength = minLength; 00579 enableOkBtn(); 00580 } 00581 00582 int KPasswordDialog::minimumPasswordLength() const { 00583 return d->minimumPasswordLength; 00584 } 00585 00586 void KPasswordDialog::setMaximumPasswordLength(int maxLength) { 00587 00588 if (maxLength < 0) maxLength = 0; 00589 if (maxLength >= KPasswordEdit::PassLen) maxLength = KPasswordEdit::PassLen - 1; 00590 00591 d->maximumPasswordLength = maxLength; 00592 00593 m_pEdit->setMaxPasswordLength(maxLength); 00594 if (m_pEdit2) m_pEdit2->setMaxPasswordLength(maxLength); 00595 00596 } 00597 00598 int KPasswordDialog::maximumPasswordLength() const { 00599 return d->maximumPasswordLength; 00600 } 00601 00602 // reasonable password length code contributed by Steffen Mthing 00603 00604 void KPasswordDialog::setReasonablePasswordLength(int reasonableLength) { 00605 00606 if (reasonableLength < 1) reasonableLength = 1; 00607 if (reasonableLength >= maximumPasswordLength()) reasonableLength = maximumPasswordLength(); 00608 00609 d->reasonablePasswordLength = reasonableLength; 00610 00611 } 00612 00613 int KPasswordDialog::reasonablePasswordLength() const { 00614 return d->reasonablePasswordLength; 00615 } 00616 00617 00618 void KPasswordDialog::setPasswordStrengthWarningLevel(int warningLevel) { 00619 if (warningLevel < 0) warningLevel = 0; 00620 if (warningLevel > 99) warningLevel = 99; 00621 d->passwordStrengthWarningLevel = warningLevel; 00622 } 00623 00624 int KPasswordDialog::passwordStrengthWarningLevel() const { 00625 return d->passwordStrengthWarningLevel; 00626 } 00627 00628 #include "kpassdlg.moc"
Trinity API Reference