1 /*
2     SPDX-FileCopyrightText: 2017 Montel Laurent <montel@kde.org>
3     SPDX-FileCopyrightText: 2015 Elvis Angelaccio <elvis.angelaccio@kde.org>
4 
5     SPDX-License-Identifier: LGPL-2.0-only OR LGPL-3.0-only OR LicenseRef-KDE-Accepted-LGPL
6 */
7 
8 #include "kpasswordlineedit.h"
9 
10 #include <QAction>
11 #include <QHBoxLayout>
12 #include <QIcon>
13 
14 class KPasswordLineEditPrivate
15 {
16 public:
KPasswordLineEditPrivate(KPasswordLineEdit * qq)17     KPasswordLineEditPrivate(KPasswordLineEdit *qq)
18         : q(qq)
19     {
20     }
21     void initialize();
22     void echoModeToggled();
23     void showToggleEchoModeAction(const QString &text);
24 
25     QIcon passwordIcon;
26     QIcon visibleIcon;
27 
28     QLineEdit *passwordLineEdit = nullptr;
29     QAction *toggleEchoModeAction = nullptr;
30     bool isToggleEchoModeAvailable = true;
31     bool revealPasswordAvailable = true;
32     KPasswordLineEdit *const q;
33 };
34 
initialize()35 void KPasswordLineEditPrivate::initialize()
36 {
37     QIcon visibilityIcon = QIcon::fromTheme(QStringLiteral("visibility"), QIcon(QStringLiteral(":/icons/visibility.svg")));
38     toggleEchoModeAction = passwordLineEdit->addAction(visibilityIcon, QLineEdit::TrailingPosition);
39     toggleEchoModeAction->setObjectName(QStringLiteral("visibilityAction"));
40     toggleEchoModeAction->setVisible(false);
41     toggleEchoModeAction->setToolTip(QObject::tr("Change the visibility of the password", "@info:tooltip"));
42     q->connect(toggleEchoModeAction, &QAction::triggered, q, [this]() {
43         echoModeToggled();
44     });
45     q->connect(passwordLineEdit, &QLineEdit::textChanged, q, [this](const QString &str) {
46         showToggleEchoModeAction(str);
47     });
48 }
49 
showToggleEchoModeAction(const QString & text)50 void KPasswordLineEditPrivate::showToggleEchoModeAction(const QString &text)
51 {
52     if (revealPasswordAvailable) {
53         toggleEchoModeAction->setVisible(isToggleEchoModeAvailable && (passwordLineEdit->echoMode() == QLineEdit::Normal || !text.isEmpty()));
54     } else {
55         toggleEchoModeAction->setVisible(false);
56     }
57 }
58 
echoModeToggled()59 void KPasswordLineEditPrivate::echoModeToggled()
60 {
61     if (passwordLineEdit->echoMode() == QLineEdit::Password) {
62         passwordLineEdit->setEchoMode(QLineEdit::Normal);
63         if (passwordIcon.isNull()) {
64             passwordIcon = QIcon::fromTheme(QStringLiteral("hint"), QIcon(QStringLiteral(":/icons/hint.svg")));
65         }
66         toggleEchoModeAction->setIcon(passwordIcon);
67     } else if (passwordLineEdit->echoMode() == QLineEdit::Normal) {
68         if (visibleIcon.isNull()) {
69             visibleIcon = QIcon::fromTheme(QStringLiteral("visibility"), QIcon(QStringLiteral(":/icons/visibility.svg")));
70         }
71         passwordLineEdit->setEchoMode(QLineEdit::Password);
72         toggleEchoModeAction->setIcon(visibleIcon);
73     }
74     Q_EMIT q->echoModeChanged(passwordLineEdit->echoMode());
75 }
76 
KPasswordLineEdit(QWidget * parent)77 KPasswordLineEdit::KPasswordLineEdit(QWidget *parent)
78     : QWidget(parent)
79     , d(new KPasswordLineEditPrivate(this))
80 {
81     QHBoxLayout *mainLayout = new QHBoxLayout(this);
82     mainLayout->setObjectName(QStringLiteral("mainlayout"));
83     mainLayout->setContentsMargins(0, 0, 0, 0);
84     d->passwordLineEdit = new QLineEdit(this);
85     d->passwordLineEdit->setObjectName(QStringLiteral("passwordlineedit"));
86     d->passwordLineEdit->setEchoMode(QLineEdit::Password);
87     connect(d->passwordLineEdit, &QLineEdit::textChanged, this, &KPasswordLineEdit::passwordChanged);
88     setFocusProxy(d->passwordLineEdit);
89     setFocusPolicy(d->passwordLineEdit->focusPolicy());
90     mainLayout->addWidget(d->passwordLineEdit);
91     d->initialize();
92 }
93 
94 KPasswordLineEdit::~KPasswordLineEdit() = default;
95 
setPassword(const QString & password)96 void KPasswordLineEdit::setPassword(const QString &password)
97 {
98     if (d->passwordLineEdit->text() != password) {
99         d->isToggleEchoModeAvailable = password.isEmpty();
100         d->passwordLineEdit->setText(password);
101     }
102 }
103 
password() const104 QString KPasswordLineEdit::password() const
105 {
106     return d->passwordLineEdit->text();
107 }
108 
clear()109 void KPasswordLineEdit::clear()
110 {
111     d->passwordLineEdit->clear();
112 }
113 
setClearButtonEnabled(bool clear)114 void KPasswordLineEdit::setClearButtonEnabled(bool clear)
115 {
116     d->passwordLineEdit->setClearButtonEnabled(clear);
117 }
118 
isClearButtonEnabled() const119 bool KPasswordLineEdit::isClearButtonEnabled() const
120 {
121     return d->passwordLineEdit->isClearButtonEnabled();
122 }
123 
setEchoMode(QLineEdit::EchoMode mode)124 void KPasswordLineEdit::setEchoMode(QLineEdit::EchoMode mode)
125 {
126     d->passwordLineEdit->setEchoMode(mode);
127 }
128 
echoMode() const129 QLineEdit::EchoMode KPasswordLineEdit::echoMode() const
130 {
131     return d->passwordLineEdit->echoMode();
132 }
133 
lineEdit() const134 QLineEdit *KPasswordLineEdit::lineEdit() const
135 {
136     return d->passwordLineEdit;
137 }
138 
setRevealPasswordAvailable(bool reveal)139 void KPasswordLineEdit::setRevealPasswordAvailable(bool reveal)
140 {
141     d->revealPasswordAvailable = reveal;
142     d->showToggleEchoModeAction(password());
143 }
144 
isRevealPasswordAvailable() const145 bool KPasswordLineEdit::isRevealPasswordAvailable() const
146 {
147     return d->revealPasswordAvailable;
148 }
149 
toggleEchoModeAction() const150 QAction *KPasswordLineEdit::toggleEchoModeAction() const
151 {
152     return d->toggleEchoModeAction;
153 }
154 
155 #include "moc_kpasswordlineedit.cpp"
156