File indexing completed on 2024-05-12 16:40:56

0001 /* This file is part of the KDE libraries
0002    Copyright (C) 2000 David Faure <faure@kde.org>
0003    Copyright (C) 2007 Olivier Goffart <ogoffart at kde.org>
0004    Copyright (C) 2013 Jarosław Staniek <staniek@kde.org>
0005 
0006    Based on kpasswordwidget.cpp from kdelibs
0007 
0008    This library is free software; you can redistribute it and/or
0009    modify it under the terms of the GNU Library General Public
0010    License version 2 as published by the Free Software Foundation.
0011 
0012    This library is distributed in the hope that it will be useful,
0013    but WITHOUT ANY WARRANTY; without even the implied warranty of
0014    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015    Library General Public License for more details.
0016 
0017    You should have received a copy of the GNU Library General Public License
0018    along with this library; see the file COPYING.LIB.  If not, write to
0019    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020    Boston, MA 02110-1301, USA.
0021 */
0022 #include "KexiPasswordWidget.h"
0023 #include <kexiutils/utils.h>
0024 
0025 #include <QCheckBox>
0026 #include <QLabel>
0027 #include <QLayout>
0028 #include <QPalette>
0029 #include <QLineEdit>
0030 #include <QApplication>
0031 #include <QDesktopWidget>
0032 
0033 #include <KComboBox>
0034 #include <KIconLoader>
0035 #include <KTitleWidget>
0036 
0037 #include "ui_KexiPasswordWidget.h"
0038 
0039 /** @internal */
0040 class Q_DECL_HIDDEN KexiPasswordWidget::Private
0041 {
0042 public:
0043     explicit Private(KexiPasswordWidget *q, KexiPasswordWidgetFlags flags);
0044 
0045     void init();
0046 
0047     KexiPasswordWidget * const q;
0048     KexiPasswordWidgetFlags flags;
0049     Ui_KexiPasswordWidget ui;
0050     QMap<QString,QString> knownLogins;
0051     KComboBox* userEditCombo;
0052     QLabel* pixmapLabel;
0053     unsigned int commentRow;
0054 };
0055 
0056 KexiPasswordWidget::Private::Private(KexiPasswordWidget *qq, KexiPasswordWidgetFlags flags)
0057     : q(qq),
0058       userEditCombo(0),
0059       pixmapLabel(0),
0060       commentRow(0)
0061 {
0062     this->flags = flags;
0063 }
0064 
0065 void KexiPasswordWidget::Private::init()
0066 {
0067     ui.setupUi( q );
0068     ui.errorMessage->setHidden(true);
0069 
0070     // Row 4: Username field
0071     if (flags & KexiPasswordWidget::ShowUsernameLine) {
0072         ui.userEdit->setFocus();
0073         QObject::connect(ui.userEdit, SIGNAL(returnPressed()), ui.passEdit, SLOT(setFocus()));
0074         q->setFocusProxy(ui.userEdit);
0075     }
0076     else {
0077         ui.userNameLabel->hide();
0078         ui.userEdit->hide();
0079         ui.passEdit->setFocus();
0080         q->setFocusProxy(ui.passEdit);
0081     }
0082 
0083     if (!(flags & KexiPasswordWidget::ShowAnonymousLoginCheckBox)) {
0084         ui.anonymousCheckBox->hide();
0085         ui.anonymousLabel->hide();
0086     }
0087     else {
0088         QObject::connect(ui.anonymousCheckBox, SIGNAL(stateChanged(int)), q, SLOT(updateFields()));
0089     }
0090 
0091     if (!(flags & KexiPasswordWidget::ShowDatabaseNameLine)) {
0092         q->showDatabaseName(false);
0093     }
0094 
0095     if (!(flags & KexiPasswordWidget::ShowDomainLine)) {
0096         ui.domainLabel->hide();
0097         ui.domainEdit->hide();
0098     }
0099 
0100     if (!(flags & KexiPasswordWidget::ShowKeepPassword)) {
0101         ui.keepCheckBox->hide();
0102         ui.keepCheckBoxLabel->hide();
0103     }
0104 
0105     q->updateFields();
0106 
0107     QRect desktop = QApplication::desktop()->screenGeometry(q->topLevelWidget());
0108     q->setMinimumWidth(qMin(1000, qMax(q->sizeHint().width(), desktop.width() / 4)));
0109     if ( ( flags & KexiPasswordWidget::ShowIcon ) ) {
0110         q->setPixmap(QIcon::fromTheme("dialog-password").pixmap(KIconLoader::SizeHuge));
0111     }
0112 
0113     QObject::connect(ui.userEdit, SIGNAL(returnPressed()), q, SIGNAL(returnPressed()));
0114     QObject::connect(ui.domainEdit, SIGNAL(returnPressed()), q, SIGNAL(returnPressed()));
0115     QObject::connect(ui.passEdit, SIGNAL(returnPressed()), q, SIGNAL(returnPressed()));
0116 }
0117 
0118 // ---
0119 
0120 KexiPasswordWidget::KexiPasswordWidget(QWidget* parent ,
0121                                        KexiPasswordWidgetFlags flags)
0122    : QWidget(parent), d(new Private(this, flags))
0123 {
0124     d->init();
0125 }
0126 
0127 KexiPasswordWidget::~KexiPasswordWidget()
0128 {
0129     delete d;
0130 }
0131 
0132 static void setLineEditReadOnly(QLineEdit *edit, bool readOnly)
0133 {
0134     QPalette p(edit->parentWidget()->palette());
0135     p.setColor(QPalette::Base, Qt::transparent);
0136 
0137     edit->setReadOnly(readOnly);
0138     edit->setFrame(!readOnly);
0139     edit->setPalette(readOnly ? p : edit->parentWidget()->palette());
0140     edit->setFocusPolicy(readOnly ? Qt::NoFocus : Qt::StrongFocus);
0141     edit->setClearButtonEnabled(!readOnly);
0142     QFont f = edit->font();
0143     f.setBold(readOnly);
0144     edit->setFont(f);
0145 }
0146 
0147 void KexiPasswordWidget::updateFields()
0148 {
0149     if (anonymousMode()) {
0150         d->ui.userEdit->setEnabled( false );
0151         d->ui.nameEdit->setEnabled( false );
0152         d->ui.domainEdit->setEnabled( false );
0153         d->ui.passEdit->setEnabled( false );
0154         d->ui.keepCheckBox->setEnabled( false );
0155     }
0156     else {
0157         setLineEditReadOnly(d->ui.userEdit, d->flags & KexiPasswordWidget::UsernameReadOnly);
0158         setLineEditReadOnly(d->ui.nameEdit, d->flags & KexiPasswordWidget::DatabaseNameReadOnly);
0159         setLineEditReadOnly(d->ui.domainEdit, d->flags & KexiPasswordWidget::DomainReadOnly);
0160         d->ui.passEdit->setEnabled( true );
0161         d->ui.keepCheckBox->setEnabled( true );
0162     }
0163 }
0164 
0165 void KexiPasswordWidget::setPixmap(const QPixmap &pixmap)
0166 {
0167     if ( !d->pixmapLabel )
0168     {
0169         d->pixmapLabel = new QLabel(this);
0170         d->pixmapLabel->setAlignment( Qt::AlignLeft | Qt::AlignTop );
0171         d->ui.hboxLayout->insertWidget( 0, d->pixmapLabel );
0172     }
0173 
0174     d->pixmapLabel->setPixmap( pixmap );
0175 }
0176 
0177 QPixmap KexiPasswordWidget::pixmap() const
0178 {
0179     if ( !d->pixmapLabel ) {
0180         return QPixmap();
0181     }
0182 
0183     return *d->pixmapLabel->pixmap();
0184 }
0185 
0186 
0187 void KexiPasswordWidget::setUsername(const QString& user)
0188 {
0189     d->ui.userEdit->setText(user);
0190     if ( user.isEmpty() )
0191         return;
0192 
0193     activated(user);
0194     if ( d->ui.userEdit->isVisibleTo( this ) )
0195     {
0196         d->ui.passEdit->setFocus();
0197     }
0198 }
0199 
0200 
0201 QString KexiPasswordWidget::username() const
0202 {
0203     return d->ui.userEdit->text();
0204 }
0205 
0206 QString KexiPasswordWidget::password() const
0207 {
0208     return d->ui.passEdit->text();
0209 }
0210 
0211 void KexiPasswordWidget::setDomain(const QString& domain)
0212 {
0213     d->ui.domainEdit->setText(domain);
0214 }
0215 
0216 QString KexiPasswordWidget::domain() const
0217 {
0218     return d->ui.domainEdit->text();
0219 }
0220 
0221 void KexiPasswordWidget::setAnonymousMode(bool anonymous)
0222 {
0223     d->ui.anonymousCheckBox->setChecked( anonymous );
0224 }
0225 
0226 bool KexiPasswordWidget::anonymousMode() const
0227 {
0228     return d->ui.anonymousCheckBox->isChecked();
0229 }
0230 
0231 
0232 void KexiPasswordWidget::setKeepPassword( bool b )
0233 {
0234     d->ui.keepCheckBox->setChecked( b );
0235 }
0236 
0237 bool KexiPasswordWidget::keepPassword() const
0238 {
0239     return d->ui.keepCheckBox->isChecked();
0240 }
0241 
0242 void KexiPasswordWidget::addCommentLine( const QString& label,
0243                                       const QString& comment )
0244 {
0245     int gridMarginLeft, gridMarginTop, gridMarginRight, gridMarginBottom;
0246     d->ui.formLayout->getContentsMargins(&gridMarginLeft, &gridMarginTop, &gridMarginRight, &gridMarginBottom);
0247 
0248     int spacing = d->ui.formLayout->horizontalSpacing();
0249     if (spacing < 0) {
0250         // same inter-column spacing for all rows, see comment in qformlayout.cpp
0251         spacing = style()->combinedLayoutSpacing(QSizePolicy::Label, QSizePolicy::LineEdit, Qt::Horizontal, 0, this);
0252     }
0253 
0254     QLabel* c = new QLabel(comment, this);
0255     c->setWordWrap(true);
0256 
0257     d->ui.formLayout->insertRow(d->commentRow, label, c);
0258     ++d->commentRow;
0259 
0260     // cycle through column 0 widgets and see the max width so we can set the minimum height of
0261     // column 2 wordwrapable labels
0262     int firstColumnWidth = 0;
0263     for (int i = 0; i < d->ui.formLayout->rowCount(); ++i) {
0264         QLayoutItem *li = d->ui.formLayout->itemAt(i, QFormLayout::LabelRole);
0265         if (li) {
0266             QWidget *w = li->widget();
0267             if (w && !w->isHidden()) {
0268                 firstColumnWidth = qMax(firstColumnWidth, w->sizeHint().width());
0269             }
0270         }
0271     }
0272     for (int i = 0; i < d->ui.formLayout->rowCount(); ++i) {
0273         QLayoutItem *li = d->ui.formLayout->itemAt(i, QFormLayout::FieldRole);
0274         if (li) {
0275             QLabel *l = qobject_cast<QLabel*>(li->widget());
0276             if (l && l->wordWrap()) {
0277                 int w = sizeHint().width() - firstColumnWidth - ( 2 * KexiUtils::marginHint() )
0278                         - gridMarginLeft - gridMarginRight - spacing;
0279                 l->setMinimumSize( w, l->heightForWidth(w) );
0280             }
0281         }
0282     }
0283 }
0284 
0285 void KexiPasswordWidget::showErrorMessage( const QString& message, const ErrorType type )
0286 {
0287     d->ui.errorMessage->setText( message, KTitleWidget::ErrorMessage );
0288 
0289     QFont bold = font();
0290     bold.setBold( true );
0291     switch ( type ) {
0292         case PasswordError:
0293             d->ui.passwordLabel->setFont( bold );
0294             d->ui.passEdit->clear();
0295             d->ui.passEdit->setFocus();
0296             break;
0297         case UsernameError:
0298             if ( d->ui.userEdit->isVisibleTo( this ) )
0299             {
0300                 d->ui.userNameLabel->setFont( bold );
0301                 d->ui.userEdit->setFocus();
0302             }
0303             break;
0304         case DomainError:
0305             if ( d->ui.domainEdit->isVisibleTo( this ) )
0306             {
0307                 d->ui.domainLabel->setFont( bold );
0308                 d->ui.domainEdit->setFocus();
0309             }
0310             break;
0311         case FatalError:
0312             d->ui.userNameLabel->setEnabled( false );
0313             d->ui.userEdit->setEnabled( false );
0314             d->ui.passwordLabel->setEnabled( false );
0315             d->ui.passEdit->setEnabled( false );
0316             d->ui.keepCheckBox->setEnabled( false );
0317             //enableButton( Ok, false );
0318             break;
0319         default:
0320             break;
0321     }
0322     adjustSize();
0323 }
0324 
0325 void KexiPasswordWidget::setPrompt(const QString& prompt)
0326 {
0327     d->ui.prompt->setVisible(!prompt.isEmpty());
0328     d->ui.prompt->setText( prompt );
0329     d->ui.prompt->setWordWrap( true );
0330     d->ui.prompt->setMinimumHeight(
0331                 d->ui.prompt->heightForWidth( width() -  ( 2 * KexiUtils::marginHint() ) ) );
0332 }
0333 
0334 QString KexiPasswordWidget::prompt() const
0335 {
0336     return d->ui.prompt->text();
0337 }
0338 
0339 void KexiPasswordWidget::setPassword(const QString &p)
0340 {
0341     d->ui.passEdit->setText(p);
0342 }
0343 
0344 void KexiPasswordWidget::setUsernameReadOnly(bool readOnly)
0345 {
0346     setLineEditReadOnly(d->ui.userEdit, readOnly);
0347     d->flags |= KexiPasswordWidget::UsernameReadOnly;
0348     if (readOnly) {
0349         d->flags ^= KexiPasswordWidget::UsernameReadOnly;
0350     }
0351 
0352     if ( readOnly && d->ui.userEdit->hasFocus() ) {
0353         d->ui.passEdit->setFocus();
0354     }
0355 }
0356 
0357 void KexiPasswordWidget::showDatabaseName(bool show)
0358 {
0359     d->ui.nameLabel->setVisible(show);
0360     d->ui.nameEdit->setVisible(show);
0361 }
0362 
0363 void KexiPasswordWidget::setDatabaseName(const QString& databaseName)
0364 {
0365     d->ui.nameEdit->setText(databaseName);
0366 }
0367 
0368 void KexiPasswordWidget::setDatabaseNameReadOnly(bool readOnly)
0369 {
0370     setLineEditReadOnly(d->ui.nameEdit, readOnly);
0371     d->flags |= KexiPasswordWidget::DatabaseNameReadOnly;
0372     if (readOnly) {
0373         d->flags ^= KexiPasswordWidget::DatabaseNameReadOnly;
0374     }
0375 
0376     if ( readOnly && d->ui.userEdit->hasFocus() ) {
0377         d->ui.passEdit->setFocus();
0378     }
0379 }
0380 
0381 void KexiPasswordWidget::setKnownLogins( const QMap<QString, QString>& knownLogins )
0382 {
0383     const int nr = knownLogins.count();
0384     if ( nr == 0 ) {
0385         return;
0386     }
0387 
0388     if ( nr == 1 ) {
0389         d->ui.userEdit->setText( knownLogins.begin().key() );
0390         setPassword( knownLogins.begin().value() );
0391         return;
0392     }
0393 
0394     Q_ASSERT( !d->ui.userEdit->isReadOnly() );
0395     if ( !d->userEditCombo ) {
0396         d->ui.formLayout->removeWidget(d->ui.userEdit);
0397         delete d->ui.userEdit;
0398         d->userEditCombo = new KComboBox(true, this);
0399         d->ui.userEdit = qobject_cast<KLineEdit*>(d->userEditCombo->lineEdit());
0400         d->ui.userNameLabel->setBuddy( d->userEditCombo );
0401         d->ui.formLayout->setWidget( d->commentRow, QFormLayout::FieldRole, d->userEditCombo );
0402         setTabOrder( d->ui.userEdit, d->ui.anonymousCheckBox );
0403         setTabOrder( d->ui.anonymousCheckBox, d->ui.domainEdit );
0404         setTabOrder( d->ui.domainEdit, d->ui.passEdit );
0405         setTabOrder( d->ui.passEdit, d->ui.keepCheckBox );
0406         connect( d->ui.userEdit, SIGNAL(returnPressed()), d->ui.passEdit, SLOT(setFocus()) );
0407     }
0408 
0409     d->knownLogins = knownLogins;
0410     d->userEditCombo->addItems( knownLogins.keys() );
0411     d->userEditCombo->setFocus();
0412 
0413     connect( d->userEditCombo, SIGNAL(activated(QString)),
0414              this, SLOT(activated(QString)) );
0415 }
0416 
0417 void KexiPasswordWidget::activated(const QString& userName)
0418 {
0419     QMap<QString, QString>::ConstIterator it = d->knownLogins.constFind( userName );
0420     if ( it != d->knownLogins.constEnd() ) {
0421         setPassword( it.value() );
0422     }
0423 }
0424 
0425 bool KexiPasswordWidget::checkPassword()
0426 {
0427     return true;
0428 }
0429