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 <QContextMenuEvent>
12#include <QHBoxLayout>
13#include <QIcon>
14#include <QMenu>
15
16class KPasswordLineEditPrivate
17{
18public:
19 KPasswordLineEditPrivate(KPasswordLineEdit *qq)
20 : q(qq)
21 {
22 }
23 void initialize();
24 void echoModeToggled();
25 void showToggleEchoModeAction(const QString &text);
26 void slotCustomContextMenuRequested(const QPoint &pos);
27
28 QIcon passwordIcon;
29 QIcon visibleIcon;
30
31 QLineEdit *passwordLineEdit = nullptr;
32 QAction *toggleEchoModeAction = nullptr;
33 bool isToggleEchoModeAvailable = true;
34 KPassword::RevealMode revealPasswordMode = KPassword::RevealMode::OnlyNew;
35 KPasswordLineEdit *const q;
36};
37
38void KPasswordLineEditPrivate::initialize()
39{
40 QIcon visibilityIcon = QIcon::fromTheme(QStringLiteral("visibility"), fallback: QIcon(QStringLiteral(":/icons/visibility.svg")));
41 toggleEchoModeAction = passwordLineEdit->addAction(icon: visibilityIcon, position: QLineEdit::TrailingPosition);
42 toggleEchoModeAction->setObjectName(QStringLiteral("visibilityAction"));
43 toggleEchoModeAction->setVisible(false);
44 toggleEchoModeAction->setToolTip(QObject::tr(s: "Change the visibility of the password", c: "@info:tooltip"));
45 q->connect(sender: toggleEchoModeAction, signal: &QAction::triggered, context: q, slot: [this]() {
46 echoModeToggled();
47 });
48 q->connect(sender: passwordLineEdit, signal: &QLineEdit::textChanged, context: q, slot: [this](const QString &str) {
49 showToggleEchoModeAction(text: str);
50 });
51}
52
53void KPasswordLineEditPrivate::showToggleEchoModeAction(const QString &text)
54{
55 if (revealPasswordMode != KPassword::RevealMode::Never) {
56 toggleEchoModeAction->setVisible(isToggleEchoModeAvailable && (passwordLineEdit->echoMode() == QLineEdit::Normal || !text.isEmpty()));
57 } else {
58 toggleEchoModeAction->setVisible(false);
59 }
60}
61
62void KPasswordLineEditPrivate::echoModeToggled()
63{
64 if (passwordLineEdit->echoMode() == QLineEdit::Password) {
65 passwordLineEdit->setEchoMode(QLineEdit::Normal);
66 if (passwordIcon.isNull()) {
67 passwordIcon = QIcon::fromTheme(QStringLiteral("hint"), fallback: QIcon(QStringLiteral(":/icons/hint.svg")));
68 }
69 toggleEchoModeAction->setIcon(passwordIcon);
70 } else if (passwordLineEdit->echoMode() == QLineEdit::Normal) {
71 if (visibleIcon.isNull()) {
72 visibleIcon = QIcon::fromTheme(QStringLiteral("visibility"), fallback: QIcon(QStringLiteral(":/icons/visibility.svg")));
73 }
74 passwordLineEdit->setEchoMode(QLineEdit::Password);
75 toggleEchoModeAction->setIcon(visibleIcon);
76 }
77 Q_EMIT q->echoModeChanged(echoMode: passwordLineEdit->echoMode());
78}
79
80void KPasswordLineEditPrivate::slotCustomContextMenuRequested(const QPoint &pos)
81{
82 auto popup = std::unique_ptr<QMenu>(passwordLineEdit->createStandardContextMenu());
83 if (popup) {
84 if (toggleEchoModeAction->isVisible()) {
85 popup->addSeparator();
86
87 toggleEchoModeAction->setText(passwordLineEdit->echoMode() == QLineEdit::Password ? QObject::tr(s: "Show Password", c: "@action:inmenu")
88 : QObject::tr(s: "Hide Password", c: "@action:inmenu"));
89 popup->addAction(action: toggleEchoModeAction);
90 }
91 popup->exec(pos);
92 }
93}
94
95KPasswordLineEdit::KPasswordLineEdit(QWidget *parent)
96 : QWidget(parent)
97 , d(new KPasswordLineEditPrivate(this))
98{
99 QHBoxLayout *mainLayout = new QHBoxLayout(this);
100 mainLayout->setObjectName(QStringLiteral("mainlayout"));
101 mainLayout->setContentsMargins(left: 0, top: 0, right: 0, bottom: 0);
102 d->passwordLineEdit = new QLineEdit(this);
103 d->passwordLineEdit->setObjectName(QStringLiteral("passwordlineedit"));
104 d->passwordLineEdit->setEchoMode(QLineEdit::Password);
105 d->passwordLineEdit->setContextMenuPolicy(Qt::CustomContextMenu);
106 connect(sender: d->passwordLineEdit, signal: &QWidget::customContextMenuRequested, context: this, slot: [this](const QPoint &pos) {
107 d->slotCustomContextMenuRequested(pos);
108 });
109 connect(sender: d->passwordLineEdit, signal: &QLineEdit::textChanged, context: this, slot: &KPasswordLineEdit::passwordChanged);
110 setFocusProxy(d->passwordLineEdit);
111 setFocusPolicy(d->passwordLineEdit->focusPolicy());
112 mainLayout->addWidget(d->passwordLineEdit);
113 d->initialize();
114}
115
116KPasswordLineEdit::~KPasswordLineEdit() = default;
117
118void KPasswordLineEdit::setPassword(const QString &password)
119{
120 if (d->passwordLineEdit->text() != password) {
121 if (d->revealPasswordMode == KPassword::RevealMode::OnlyNew) {
122 d->isToggleEchoModeAvailable = password.isEmpty();
123 }
124 d->passwordLineEdit->setText(password);
125 }
126}
127
128QString KPasswordLineEdit::password() const
129{
130 return d->passwordLineEdit->text();
131}
132
133void KPasswordLineEdit::clear()
134{
135 d->passwordLineEdit->clear();
136}
137
138void KPasswordLineEdit::setClearButtonEnabled(bool clear)
139{
140 d->passwordLineEdit->setClearButtonEnabled(clear);
141}
142
143bool KPasswordLineEdit::isClearButtonEnabled() const
144{
145 return d->passwordLineEdit->isClearButtonEnabled();
146}
147
148void KPasswordLineEdit::setEchoMode(QLineEdit::EchoMode mode)
149{
150 d->passwordLineEdit->setEchoMode(mode);
151}
152
153QLineEdit::EchoMode KPasswordLineEdit::echoMode() const
154{
155 return d->passwordLineEdit->echoMode();
156}
157
158void KPasswordLineEdit::setReadOnly(bool readOnly)
159{
160 d->passwordLineEdit->setReadOnly(readOnly);
161}
162
163bool KPasswordLineEdit::isReadOnly() const
164{
165 return d->passwordLineEdit->isReadOnly();
166}
167
168QLineEdit *KPasswordLineEdit::lineEdit() const
169{
170 return d->passwordLineEdit;
171}
172
173#if KWIDGETSADDONS_ENABLE_DEPRECATED_SINCE(6, 0)
174void KPasswordLineEdit::setRevealPasswordAvailable(bool reveal)
175{
176 d->revealPasswordMode = reveal ? KPassword::RevealMode::OnlyNew : KPassword::RevealMode::Never;
177 d->showToggleEchoModeAction(text: password());
178}
179
180bool KPasswordLineEdit::isRevealPasswordAvailable() const
181{
182 return d->revealPasswordMode != KPassword::RevealMode::Never;
183}
184#endif
185
186void KPasswordLineEdit::setRevealPasswordMode(KPassword::RevealMode mode)
187{
188 d->revealPasswordMode = mode;
189 d->showToggleEchoModeAction(text: password());
190}
191
192KPassword::RevealMode KPasswordLineEdit::revealPasswordMode() const
193{
194 return d->revealPasswordMode;
195}
196
197QAction *KPasswordLineEdit::toggleEchoModeAction() const
198{
199 return d->toggleEchoModeAction;
200}
201
202#include "moc_kpasswordlineedit.cpp"
203

source code of kwidgetsaddons/src/kpasswordlineedit.cpp