File indexing completed on 2024-12-01 11:13:11

0001 /*
0002     SPDX-FileCopyrightText: 2015 Jan Grulich <jgrulich@redhat.com>
0003 
0004     SPDX-License-Identifier: LGPL-2.1-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
0005 */
0006 
0007 #include "passwordfield.h"
0008 
0009 #include <QAction>
0010 #include <QIcon>
0011 
0012 #include <KAuthorized>
0013 #include <KLocalizedString>
0014 #include <KWallet>
0015 
0016 PasswordField::PasswordField(QWidget *parent, Qt::WindowFlags f)
0017     : QWidget(parent, f)
0018     , m_currentPasswordOption(StoreForUser)
0019     , m_layout(new QVBoxLayout(this))
0020     , m_passwordField(new QLineEdit(this))
0021     , m_passwordOptionsMenu(new QComboBox(this))
0022 {
0023     // The widget will be already in layout, thus reset content margins
0024     // to align it with the rest of widgets
0025     m_layout->setContentsMargins(0, 0, 0, 0);
0026 
0027     connect(m_passwordField, &QLineEdit::textChanged, this, &PasswordField::textChanged);
0028 
0029     if (KAuthorized::authorize(QStringLiteral("lineedit_reveal_password"))) {
0030         m_toggleEchoModeAction = m_passwordField->addAction(QIcon::fromTheme(QStringLiteral("visibility")), QLineEdit::TrailingPosition);
0031         m_toggleEchoModeAction->setVisible(false);
0032         m_toggleEchoModeAction->setToolTip(i18n("Change the visibility of the password"));
0033         connect(m_passwordField, &QLineEdit::textChanged, this, &PasswordField::showToggleEchoModeAction);
0034         connect(m_toggleEchoModeAction, &QAction::triggered, this, &PasswordField::toggleEchoMode);
0035     }
0036 
0037     m_layout->addWidget(m_passwordField);
0038 
0039     m_passwordOptionsMenu->setSizeAdjustPolicy(QComboBox::AdjustToContentsOnFirstShow);
0040 
0041     m_passwordOptionsMenu->addItem(QIcon::fromTheme(QStringLiteral("document-save")), i18n("Store password for this user only (encrypted)"), StoreForUser);
0042     m_passwordOptionsMenu->addItem(QIcon::fromTheme(QStringLiteral("document-save-all")),
0043                                    i18n("Store password for all users (not encrypted)"),
0044                                    StoreForAllUsers);
0045     m_passwordOptionsMenu->addItem(QIcon::fromTheme(QStringLiteral("dialog-messages")), i18n("Ask for this password every time"), AlwaysAsk);
0046     // Do not add by default
0047     // m_passwordOptionsMenu->addItem(QIcon::fromTheme(QStringLiteral("document-close")), i18n("This password is not required"), NotRequired);
0048 
0049     if (KWallet::Wallet::isEnabled()) {
0050         m_passwordOptionsMenu->setCurrentIndex(0);
0051     } else {
0052         m_passwordOptionsMenu->setCurrentIndex(1);
0053         m_currentPasswordOption = StoreForAllUsers;
0054     }
0055 
0056     connect(m_passwordOptionsMenu, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &PasswordField::changePasswordOption);
0057 
0058     // Disable by default
0059     m_passwordOptionsMenu->setVisible(false);
0060     // m_layout->addWidget(m_passwordOptionsMenu);
0061 
0062     setLayout(m_layout);
0063 }
0064 
0065 void PasswordField::setMaxLength(int maxLength)
0066 {
0067     m_passwordField->setMaxLength(maxLength);
0068 }
0069 
0070 void PasswordField::setPasswordModeEnabled(bool enable)
0071 {
0072     m_passwordField->setEchoMode(enable ? QLineEdit::Password : QLineEdit::Normal);
0073 }
0074 
0075 void PasswordField::setPasswordOptionsEnabled(bool enable)
0076 {
0077     if (enable) {
0078         m_layout->addWidget(m_passwordOptionsMenu);
0079         m_passwordOptionsMenu->setVisible(true);
0080     } else {
0081         m_layout->removeWidget(m_passwordOptionsMenu);
0082         m_passwordOptionsMenu->setVisible(false);
0083     }
0084 }
0085 
0086 void PasswordField::setPasswordNotSavedEnabled(bool enable)
0087 {
0088     if (enable) {
0089         const int index = m_passwordOptionsMenu->findData(AlwaysAsk);
0090         if (index == -1) {
0091             m_passwordOptionsMenu->addItem(QIcon::fromTheme(QStringLiteral("dialog-messages")), i18n("Ask for this password every time"), AlwaysAsk);
0092         }
0093     } else {
0094         const int index = m_passwordOptionsMenu->findData(AlwaysAsk);
0095         if (index != -1) {
0096             m_passwordOptionsMenu->removeItem(index);
0097         }
0098     }
0099 }
0100 
0101 void PasswordField::setPasswordNotRequiredEnabled(bool enable)
0102 {
0103     if (enable) {
0104         const int index = m_passwordOptionsMenu->findData(NotRequired);
0105         if (index == -1) {
0106             m_passwordOptionsMenu->addItem(QIcon::fromTheme(QStringLiteral("document-close")), i18n("This password is not required"), NotRequired);
0107         }
0108     } else {
0109         const int index = m_passwordOptionsMenu->findData(NotRequired);
0110         if (index != -1) {
0111             m_passwordOptionsMenu->removeItem(index);
0112         }
0113     }
0114 }
0115 
0116 void PasswordField::setText(const QString &text)
0117 {
0118     m_passwordField->setText(text);
0119 }
0120 
0121 QString PasswordField::text() const
0122 {
0123     return m_passwordField->text();
0124 }
0125 
0126 PasswordField::PasswordOption PasswordField::passwordOption() const
0127 {
0128     return m_currentPasswordOption;
0129 }
0130 
0131 void PasswordField::setPasswordOption(PasswordField::PasswordOption option)
0132 {
0133     const int index = m_passwordOptionsMenu->findData(option);
0134     if (index != -1) {
0135         m_passwordOptionsMenu->setCurrentIndex(index);
0136     }
0137 }
0138 
0139 void PasswordField::showToggleEchoModeAction(const QString &text)
0140 {
0141     m_toggleEchoModeAction->setVisible(!text.isEmpty());
0142 }
0143 
0144 void PasswordField::toggleEchoMode()
0145 {
0146     if (m_passwordField->echoMode() == QLineEdit::Password) {
0147         m_passwordField->setEchoMode(QLineEdit::Normal);
0148         m_toggleEchoModeAction->setIcon(QIcon::fromTheme(QStringLiteral("hint")));
0149     } else if (m_passwordField->echoMode() == QLineEdit::Normal) {
0150         m_passwordField->setEchoMode(QLineEdit::Password);
0151         m_toggleEchoModeAction->setIcon(QIcon::fromTheme(QStringLiteral("visibility")));
0152     }
0153 }
0154 
0155 void PasswordField::changePasswordOption(int index)
0156 {
0157     Q_UNUSED(index);
0158 
0159     m_currentPasswordOption = (PasswordOption)m_passwordOptionsMenu->currentData().toUInt();
0160 
0161     if (m_currentPasswordOption == PasswordField::NotRequired || m_currentPasswordOption == PasswordField::AlwaysAsk) {
0162         m_passwordField->clear();
0163         m_passwordField->setDisabled(true);
0164     } else {
0165         m_passwordField->setEnabled(true);
0166     }
0167 
0168     Q_EMIT passwordOptionChanged(m_currentPasswordOption);
0169 }