KDEUI
knewpassworddialog.cpp
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "knewpassworddialog.h"
00024
00025 #include <QtGui/QApplication>
00026 #include <QtGui/QProgressBar>
00027 #include <QtCore/QRegExp>
00028 #include <QtCore/QSize>
00029 #include <QtCore/QString>
00030
00031 #include <kapplication.h>
00032 #include <kglobal.h>
00033 #include <kicon.h>
00034 #include <klocale.h>
00035 #include <kmessagebox.h>
00036 #include <klineedit.h>
00037 #include <ktitlewidget.h>
00038
00039 #include "ui_knewpassworddialog.h"
00040
00041 class KNewPasswordDialog::KNewPasswordDialogPrivate
00042 {
00043 public:
00044 KNewPasswordDialogPrivate( KNewPasswordDialog *parent )
00045 : q( parent ),
00046 minimumPasswordLength(0), passwordStrengthWarningLevel(1),reasonablePasswordLength(8)
00047 {}
00048
00049 void init();
00050 void _k_textChanged();
00051
00052 KNewPasswordDialog *q;
00053
00054 int minimumPasswordLength;
00055 int passwordStrengthWarningLevel;
00056 int reasonablePasswordLength;
00057
00058 int effectivePasswordLength(const QString &password);
00059
00060 QString pass;
00061
00062 Ui::KNewPasswordDialog ui;
00063 };
00064
00065
00066 void KNewPasswordDialog::KNewPasswordDialogPrivate::init()
00067 {
00068 q->setButtons( Ok | Cancel );
00069 q->showButtonSeparator( true );
00070 q->setDefaultButton( Ok );
00071
00072 ui.setupUi( q->mainWidget() );
00073
00074 ui.labelIcon->setPixmap( KIcon("dialog-password").pixmap(96, 96) );
00075 ui.labelMatch->setHidden(true);
00076
00077 const QString strengthBarWhatsThis(i18n("The password strength meter gives an indication of the security "
00078 "of the password you have entered. To improve the strength of "
00079 "the password, try:\n"
00080 " - using a longer password;\n"
00081 " - using a mixture of upper- and lower-case letters;\n"
00082 " - using numbers or symbols, such as #, as well as letters."));
00083 ui.labelStrengthMeter->setWhatsThis(strengthBarWhatsThis);
00084 ui.strengthBar->setWhatsThis(strengthBarWhatsThis);
00085
00086 connect( ui.linePassword, SIGNAL(textChanged(const QString&)), q, SLOT(_k_textChanged()) );
00087 connect( ui.lineVerifyPassword, SIGNAL(textChanged(const QString&)), q, SLOT(_k_textChanged()) );
00088
00089 _k_textChanged();
00090 }
00091
00092
00093 int KNewPasswordDialog::KNewPasswordDialogPrivate::effectivePasswordLength(const QString &password)
00094 {
00095 enum Category {
00096 Digit,
00097 Upper,
00098 Vowel,
00099 Consonant,
00100 Special
00101 };
00102
00103 Category previousCategory = Vowel;
00104 QString vowels("aeiou");
00105 int count = 0;
00106
00107 for (int i = 0; i < password.length(); ++i) {
00108 QChar currentChar = password.at(i);
00109 if (!password.left(i).contains(currentChar)) {
00110 Category currentCategory;
00111 switch (currentChar.category()) {
00112 case QChar::Letter_Uppercase:
00113 currentCategory = Upper;
00114 break;
00115 case QChar::Letter_Lowercase:
00116 if (vowels.contains(currentChar)) {
00117 currentCategory = Vowel;
00118 } else {
00119 currentCategory = Consonant;
00120 }
00121 break;
00122 case QChar::Number_DecimalDigit:
00123 currentCategory = Digit;
00124 break;
00125 default:
00126 currentCategory = Special;
00127 break;
00128 }
00129 switch (currentCategory) {
00130 case Vowel:
00131 if (previousCategory != Consonant) {
00132 ++count;
00133 }
00134 break;
00135 case Consonant:
00136 if (previousCategory != Vowel) {
00137 ++count;
00138 }
00139 break;
00140 default:
00141 if (previousCategory != currentCategory) {
00142 ++count;
00143 }
00144 break;
00145 }
00146 previousCategory = currentCategory;
00147 }
00148 }
00149 return count;
00150 }
00151
00152
00153 void KNewPasswordDialog::KNewPasswordDialogPrivate::_k_textChanged()
00154 {
00155 const bool match = ui.linePassword->text() == ui.lineVerifyPassword->text();
00156
00157 const int minPasswordLength = q->minimumPasswordLength();
00158
00159 if ( ui.linePassword->text().length() < minPasswordLength) {
00160 q->enableButtonOk(false);
00161 } else {
00162 q->enableButtonOk( match );
00163 }
00164
00165 if ( match && !q->allowEmptyPasswords() && ui.linePassword->text().isEmpty()) {
00166 ui.labelMatch->setPixmap( KIcon("dialog-error") );
00167 ui.labelMatch->setText( i18n("Password is empty") );
00168 }
00169 else {
00170 if ( ui.linePassword->text().length() < minPasswordLength ) {
00171 ui.labelMatch->setPixmap( KIcon("dialog-error") );
00172 ui.labelMatch->setText(i18np("Password must be at least 1 character long", "Password must be at least %1 characters long", minPasswordLength));
00173 } else {
00174 ui.labelMatch->setPixmap( match ? KIcon("dialog-ok") : KIcon("dialog-error") );
00175
00176 ui.labelMatch->setText( match? i18n("Passwords match")
00177 :i18n("Passwords do not match") );
00178 }
00179 }
00180
00181
00182 int pwstrength = (20 * ui.linePassword->text().length() + 80 * effectivePasswordLength(ui.linePassword->text())) / qMax(reasonablePasswordLength, 2);
00183 if (pwstrength < 0) {
00184 pwstrength = 0;
00185 } else if (pwstrength > 100) {
00186 pwstrength = 100;
00187 }
00188 ui.strengthBar->setValue(pwstrength);
00189 }
00190
00191
00192
00193
00194
00195 KNewPasswordDialog::KNewPasswordDialog( QWidget *parent)
00196 : KDialog(parent), d(new KNewPasswordDialogPrivate(this))
00197 {
00198 d->init();
00199 }
00200
00201
00202 KNewPasswordDialog::~KNewPasswordDialog()
00203 {
00204 delete d;
00205 }
00206
00207
00208 void KNewPasswordDialog::setPrompt(const QString &prompt)
00209 {
00210 d->ui.labelPrompt->setText(prompt);
00211 }
00212
00213
00214 QString KNewPasswordDialog::prompt() const
00215 {
00216 return d->ui.labelPrompt->text();
00217 }
00218
00219
00220 void KNewPasswordDialog::setPixmap(const QPixmap &pixmap)
00221 {
00222 d->ui.labelIcon->setPixmap(pixmap);
00223 d->ui.labelIcon->setFixedSize( d->ui.labelIcon->sizeHint() );
00224 }
00225
00226
00227 QPixmap KNewPasswordDialog::pixmap() const
00228 {
00229 return *d->ui.labelIcon->pixmap();
00230 }
00231
00232 bool KNewPasswordDialog::checkAndGetPassword(QString *pwd)
00233 {
00234 pwd->clear();
00235 if ( d->ui.linePassword->text() != d->ui.lineVerifyPassword->text() ) {
00236 d->ui.labelMatch->setPixmap( KTitleWidget::ErrorMessage );
00237 d->ui.labelMatch->setText( i18n("You entered two different "
00238 "passwords. Please try again.") );
00239
00240 d->ui.linePassword->clear();
00241 d->ui.lineVerifyPassword->clear();
00242 return false;
00243 }
00244 if (d->ui.strengthBar && d->ui.strengthBar->value() < d->passwordStrengthWarningLevel) {
00245 int retVal = KMessageBox::warningYesNo(this,
00246 i18n( "The password you have entered has a low strength. "
00247 "To improve the strength of "
00248 "the password, try:\n"
00249 " - using a longer password;\n"
00250 " - using a mixture of upper- and lower-case letters;\n"
00251 " - using numbers or symbols as well as letters.\n"
00252 "\n"
00253 "Would you like to use this password anyway?"),
00254 i18n("Low Password Strength"));
00255 if (retVal == KMessageBox::No) return false;
00256 }
00257 if ( !checkPassword(d->ui.linePassword->text()) ) {
00258 return false;
00259 }
00260
00261 *pwd = d->ui.linePassword->text();
00262 return true;
00263 }
00264
00265 void KNewPasswordDialog::accept()
00266 {
00267 QString pwd;
00268 if (!checkAndGetPassword(&pwd)) {
00269 return;
00270 }
00271 d->pass = pwd;
00272 emit newPassword( d->pass );
00273 KDialog::accept();
00274 }
00275
00276
00277 void KNewPasswordDialog::setAllowEmptyPasswords(bool allowed)
00278 {
00279 setMinimumPasswordLength( allowed ? 0 : 1 );
00280 d->_k_textChanged();
00281 }
00282
00283
00284 bool KNewPasswordDialog::allowEmptyPasswords() const
00285 {
00286 return d->minimumPasswordLength == 0;
00287 }
00288
00289 void KNewPasswordDialog::setMinimumPasswordLength(int minLength)
00290 {
00291 d->minimumPasswordLength = minLength;
00292 d->_k_textChanged();
00293 }
00294
00295 int KNewPasswordDialog::minimumPasswordLength() const
00296 {
00297 return d->minimumPasswordLength;
00298 }
00299
00300 void KNewPasswordDialog::setMaximumPasswordLength(int maxLength)
00301 {
00302 d->ui.linePassword->setMaxLength(maxLength);
00303 d->ui.lineVerifyPassword->setMaxLength(maxLength);
00304 }
00305
00306 int KNewPasswordDialog::maximumPasswordLength() const
00307 {
00308 return d->ui.linePassword->maxLength();
00309 }
00310
00311
00312
00313 void KNewPasswordDialog::setReasonablePasswordLength(int reasonableLength)
00314 {
00315
00316 if (reasonableLength < 1) {
00317 reasonableLength = 1;
00318 }
00319 if (reasonableLength >= maximumPasswordLength()) {
00320 reasonableLength = maximumPasswordLength();
00321 }
00322
00323 d->reasonablePasswordLength = reasonableLength;
00324
00325 }
00326
00327 int KNewPasswordDialog::reasonablePasswordLength() const
00328 {
00329 return d->reasonablePasswordLength;
00330 }
00331
00332
00333 void KNewPasswordDialog::setPasswordStrengthWarningLevel(int warningLevel)
00334 {
00335 if (warningLevel < 0) {
00336 warningLevel = 0;
00337 }
00338 if (warningLevel > 99) {
00339 warningLevel = 99;
00340 }
00341 d->passwordStrengthWarningLevel = warningLevel;
00342 }
00343
00344 int KNewPasswordDialog::passwordStrengthWarningLevel() const
00345 {
00346 return d->passwordStrengthWarningLevel;
00347 }
00348
00349 QString KNewPasswordDialog::password() const
00350 {
00351 return d->pass;
00352 }
00353
00354 bool KNewPasswordDialog::checkPassword(const QString &)
00355 {
00356 return true;
00357 }
00358
00359 #include "knewpassworddialog.moc"
00360
00361