VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/wizards/editors/UIUserNamePasswordEditor.cpp@ 100347

Last change on this file since 100347 was 100075, checked in by vboxsync, 21 months ago

FE/Qt: bugref:10450: Qt6 compatibility bits for QIcon; Good old QIcon::pixmap taking QWindow is deprecated in Qt6; Reworking a lot of calls to use devicePixelRatio acquired beforehand.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.0 KB
Line 
1/* $Id: UIUserNamePasswordEditor.cpp 100075 2023-06-05 16:38:02Z vboxsync $ */
2/** @file
3 * VBox Qt GUI - UIUserNamePasswordEditor class implementation.
4 */
5
6/*
7 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
8 *
9 * This file is part of VirtualBox base platform packages, as
10 * available from https://www.virtualbox.org.
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation, in version 3 of the
15 * License.
16 *
17 * This program is distributed in the hope that it will be useful, but
18 * WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 * General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, see <https://www.gnu.org/licenses>.
24 *
25 * SPDX-License-Identifier: GPL-3.0-only
26 */
27
28/* Qt includes: */
29#include <QGridLayout>
30#include <QLabel>
31#include <QStyle>
32#include <QVBoxLayout>
33#ifdef VBOX_IS_QT6_OR_LATER
34# include <QWindow>
35#endif
36
37/* GUI includes: */
38#include "QILineEdit.h"
39#include "QIRichTextLabel.h"
40#include "QIToolButton.h"
41#include "UICursor.h"
42#include "UIIconPool.h"
43#include "UIUserNamePasswordEditor.h"
44
45/* Other VBox includes: */
46#include "iprt/assert.h"
47
48
49UIPasswordLineEdit::UIPasswordLineEdit(QWidget *pParent /*= 0 */)
50 : QLineEdit(pParent)
51 , m_pTextVisibilityButton(0)
52 , m_pErrorIconLabel(0)
53 , m_fMarkForError(false)
54{
55 prepare();
56}
57
58void UIPasswordLineEdit::toggleTextVisibility(bool fTextVisible)
59{
60 AssertPtrReturnVoid(m_pTextVisibilityButton);
61
62 if (fTextVisible)
63 {
64 setEchoMode(QLineEdit::Normal);
65 if (m_pTextVisibilityButton)
66 m_pTextVisibilityButton->setIcon(UIIconPool::iconSet(":/eye_closed_10px.png"));
67 }
68 else
69 {
70 setEchoMode(QLineEdit::Password);
71 if (m_pTextVisibilityButton)
72 m_pTextVisibilityButton->setIcon(UIIconPool::iconSet(":/eye_10px.png"));
73 }
74}
75
76void UIPasswordLineEdit::mark(bool fError, const QString &strErrorToolTip)
77{
78 /* Check if something really changed: */
79 if (m_fMarkForError == fError && m_strErrorToolTip == strErrorToolTip)
80 return;
81
82 /* Save new values: */
83 m_fMarkForError = fError;
84 m_strErrorToolTip = strErrorToolTip;
85
86 /* Update accordingly: */
87 if (m_fMarkForError)
88 {
89 /* Create label if absent: */
90 if (!m_pErrorIconLabel)
91 m_pErrorIconLabel = new QLabel(this);
92
93 /* Update label content, visibility & position: */
94 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) * .625;
95 const int iShift = height() > iIconMetric ? (height() - iIconMetric) / 2 : 0;
96#ifndef VBOX_IS_QT6_OR_LATER /* QIcon::pixmap taking QWindow is deprecated in Qt6 */
97 m_pErrorIconLabel->setPixmap(m_markIcon.pixmap(windowHandle(), QSize(iIconMetric, iIconMetric)));
98#else
99 const qreal fDevicePixelRatio = window() && window()->windowHandle() ? window()->windowHandle()->devicePixelRatio() : 1;
100 m_pErrorIconLabel->setPixmap(m_markIcon.pixmap(QSize(iIconMetric, iIconMetric), fDevicePixelRatio));
101#endif
102 m_pErrorIconLabel->setToolTip(m_strErrorToolTip);
103 int iIconX = width() - iIconMetric - iShift;
104 if (m_pTextVisibilityButton)
105 iIconX -= m_pTextVisibilityButton->width() - iShift;
106 m_pErrorIconLabel->move(iIconX, iShift);
107 m_pErrorIconLabel->show();
108 }
109 else
110 {
111 /* Hide label: */
112 if (m_pErrorIconLabel)
113 m_pErrorIconLabel->hide();
114 }
115}
116
117void UIPasswordLineEdit::prepare()
118{
119 m_markIcon = UIIconPool::iconSet(":/status_error_16px.png");
120 /* Prepare text visibility button: */
121 m_pTextVisibilityButton = new QIToolButton(this);
122 if (m_pTextVisibilityButton)
123 {
124 m_pTextVisibilityButton->setIconSize(QSize(10, 10));
125 m_pTextVisibilityButton->setFocusPolicy(Qt::ClickFocus);
126 UICursor::setCursor(m_pTextVisibilityButton, Qt::ArrowCursor);
127 m_pTextVisibilityButton->show();
128 connect(m_pTextVisibilityButton, &QToolButton::clicked, this, &UIPasswordLineEdit::sltHandleTextVisibilityChange);
129 }
130 m_pErrorIconLabel = new QLabel(this);
131 toggleTextVisibility(false);
132 adjustTextVisibilityButtonGeometry();
133}
134
135void UIPasswordLineEdit::adjustTextVisibilityButtonGeometry()
136{
137 AssertPtrReturnVoid(m_pTextVisibilityButton);
138
139#ifdef VBOX_WS_MAC
140 /* Do not forget to update QIToolButton size on macOS, it's FIXED: */
141 m_pTextVisibilityButton->setFixedSize(m_pTextVisibilityButton->minimumSizeHint());
142 /* Calculate suitable position for a QIToolButton, it's FRAMELESS: */
143 const int iWidth = m_pTextVisibilityButton->width();
144 const int iMinHeight = qMin(height(), m_pTextVisibilityButton->height());
145 const int iMaxHeight = qMax(height(), m_pTextVisibilityButton->height());
146 const int iHalfHeightDiff = (iMaxHeight - iMinHeight) / 2;
147 m_pTextVisibilityButton->setGeometry(width() - iWidth - iHalfHeightDiff, iHalfHeightDiff, iWidth, iWidth);
148#else
149 int iFrameWidth = style()->pixelMetric(QStyle::PM_DefaultFrameWidth);
150 int iSize = height() - 2 * iFrameWidth;
151 m_pTextVisibilityButton->setGeometry(width() - iSize, iFrameWidth, iSize, iSize);
152#endif
153}
154
155void UIPasswordLineEdit::resizeEvent(QResizeEvent *pEvent)
156{
157 /* Call to base-class: */
158 QLineEdit::resizeEvent(pEvent);
159 adjustTextVisibilityButtonGeometry();
160
161 /* Update error label position: */
162 if (m_pErrorIconLabel)
163 {
164 const int iIconMetric = QApplication::style()->pixelMetric(QStyle::PM_SmallIconSize) * .625;
165 const int iShift = height() > iIconMetric ? (height() - iIconMetric) / 2 : 0;
166 int iIconX = width() - iIconMetric - iShift;
167 if (m_pTextVisibilityButton)
168 iIconX -= m_pTextVisibilityButton->width() - iShift;
169 m_pErrorIconLabel->move(iIconX, iShift);
170 }
171}
172
173void UIPasswordLineEdit::sltHandleTextVisibilityChange()
174{
175 bool fTextVisible = false;
176 if (echoMode() == QLineEdit::Normal)
177 fTextVisible = false;
178 else
179 fTextVisible = true;
180 toggleTextVisibility(fTextVisible);
181 emit sigTextVisibilityToggled(fTextVisible);
182}
183
184
185/*********************************************************************************************************************************
186* UIUserNamePasswordEditor implementation. *
187*********************************************************************************************************************************/
188
189UIUserNamePasswordEditor::UIUserNamePasswordEditor(QWidget *pParent /* = 0 */)
190 : QIWithRetranslateUI<QWidget>(pParent)
191 , m_pUserNameLineEdit(0)
192 , m_pPasswordLineEdit(0)
193 , m_pPasswordRepeatLineEdit(0)
194 , m_pUserNameLabel(0)
195 , m_pPasswordLabel(0)
196 , m_pPasswordRepeatLabel(0)
197 , m_fShowPlaceholderText(true)
198 , m_fLabelsVisible(true)
199{
200 prepare();
201}
202
203QString UIUserNamePasswordEditor::userName() const
204{
205 if (m_pUserNameLineEdit)
206 return m_pUserNameLineEdit->text();
207 return QString();
208}
209
210void UIUserNamePasswordEditor::setUserName(const QString &strUserName)
211{
212 if (m_pUserNameLineEdit)
213 return m_pUserNameLineEdit->setText(strUserName);
214}
215
216QString UIUserNamePasswordEditor::password() const
217{
218 if (m_pPasswordLineEdit)
219 return m_pPasswordLineEdit->text();
220 return QString();
221}
222
223void UIUserNamePasswordEditor::setPassword(const QString &strPassword)
224{
225 if (m_pPasswordLineEdit)
226 m_pPasswordLineEdit->setText(strPassword);
227 if (m_pPasswordRepeatLineEdit)
228 m_pPasswordRepeatLineEdit->setText(strPassword);
229}
230
231bool UIUserNamePasswordEditor::isUserNameComplete()
232{
233 bool fComplete = (m_pUserNameLineEdit && !m_pUserNameLineEdit->text().isEmpty());
234 if (m_pUserNameLineEdit)
235 m_pUserNameLineEdit->mark(!fComplete, UIUserNamePasswordEditor::tr("Invalid username"));
236 return fComplete;
237}
238
239bool UIUserNamePasswordEditor::isPasswordComplete()
240{
241 bool fPasswordOK = true;
242 if (m_pPasswordLineEdit && m_pPasswordRepeatLineEdit)
243 {
244 if (m_pPasswordLineEdit->text() != m_pPasswordRepeatLineEdit->text())
245 fPasswordOK = false;
246 if (m_pPasswordLineEdit->text().isEmpty())
247 fPasswordOK = false;
248 m_pPasswordLineEdit->mark(!fPasswordOK, m_strPasswordError);
249 m_pPasswordRepeatLineEdit->mark(!fPasswordOK, m_strPasswordError);
250 }
251 return fPasswordOK;
252}
253
254bool UIUserNamePasswordEditor::isComplete()
255{
256 bool fUserNameField = isUserNameComplete();
257 bool fPasswordField = isPasswordComplete();
258 return fUserNameField && fPasswordField;
259}
260
261void UIUserNamePasswordEditor::setPlaceholderTextEnabled(bool fEnabled)
262{
263 if (m_fShowPlaceholderText == fEnabled)
264 return;
265 m_fShowPlaceholderText = fEnabled;
266 retranslateUi();
267}
268
269void UIUserNamePasswordEditor::setLabelsVisible(bool fVisible)
270{
271 if (m_fLabelsVisible == fVisible)
272 return;
273 m_fLabelsVisible = fVisible;
274 m_pUserNameLabel->setVisible(fVisible);
275 m_pPasswordLabel->setVisible(fVisible);
276 m_pPasswordRepeatLabel->setVisible(fVisible);
277
278}
279
280void UIUserNamePasswordEditor::retranslateUi()
281{
282 QString strPassword = tr("Pass&word");
283 QString strRepeatPassword = tr("&Repeat Password");
284 QString strUsername = tr("U&sername");
285 if (m_pUserNameLabel)
286 m_pUserNameLabel->setText(QString("%1%2").arg(strUsername).arg(":"));
287
288 if (m_pPasswordLabel)
289 m_pPasswordLabel->setText(QString("%1%2").arg(strPassword).arg(":"));
290
291 if (m_pPasswordRepeatLabel)
292 m_pPasswordRepeatLabel->setText(QString("%1%2").arg(strRepeatPassword).arg(":"));
293
294 if (m_fShowPlaceholderText)
295 {
296 if(m_pUserNameLineEdit)
297 m_pUserNameLineEdit->setPlaceholderText(strUsername.remove('&'));
298 if (m_pPasswordLineEdit)
299 m_pPasswordLineEdit->setPlaceholderText(strPassword.remove('&'));
300 if (m_pPasswordRepeatLineEdit)
301 m_pPasswordRepeatLineEdit->setPlaceholderText(strRepeatPassword.remove('&'));
302 }
303 else
304 {
305 if(m_pUserNameLineEdit)
306 m_pUserNameLineEdit->setPlaceholderText(QString());
307 if (m_pPasswordLineEdit)
308 m_pPasswordLineEdit->setPlaceholderText(QString());
309 if (m_pPasswordRepeatLineEdit)
310 m_pPasswordRepeatLineEdit->setPlaceholderText(QString());
311 }
312 if(m_pUserNameLineEdit)
313 m_pUserNameLineEdit->setToolTip(tr("Holds username."));
314 if (m_pPasswordLineEdit)
315 m_pPasswordLineEdit->setToolTip(tr("Holds password."));
316 if (m_pPasswordRepeatLineEdit)
317 m_pPasswordRepeatLineEdit->setToolTip(tr("Holds the repeated password."));
318 m_strPasswordError = tr("Invalid password pair");
319}
320
321template <class T>
322void UIUserNamePasswordEditor::addLineEdit(int &iRow, QLabel *&pLabel, T *&pLineEdit, QGridLayout *pLayout)
323{
324 if (!pLayout || pLabel || pLineEdit)
325 return;
326 pLabel = new QLabel;
327 if (!pLabel)
328 return;
329 pLabel->setAlignment(Qt::AlignRight);
330 pLabel->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
331
332 pLayout->addWidget(pLabel, iRow, 0, 1, 1);
333
334 pLineEdit = new T;
335 if (!pLineEdit)
336 return;
337 pLayout->addWidget(pLineEdit, iRow, 1, 1, 3);
338
339 pLabel->setBuddy(pLineEdit);
340 ++iRow;
341 return;
342}
343
344void UIUserNamePasswordEditor::prepare()
345{
346 QGridLayout *pMainLayout = new QGridLayout;
347 pMainLayout->setColumnStretch(0, 0);
348 pMainLayout->setColumnStretch(1, 1);
349 if (!pMainLayout)
350 return;
351 setLayout(pMainLayout);
352 int iRow = 0;
353 addLineEdit<UIMarkableLineEdit>(iRow, m_pUserNameLabel, m_pUserNameLineEdit, pMainLayout);
354 addLineEdit<UIPasswordLineEdit>(iRow, m_pPasswordLabel, m_pPasswordLineEdit, pMainLayout);
355 addLineEdit<UIPasswordLineEdit>(iRow, m_pPasswordRepeatLabel, m_pPasswordRepeatLineEdit, pMainLayout);
356
357 connect(m_pPasswordLineEdit, &UIPasswordLineEdit::sigTextVisibilityToggled,
358 this, &UIUserNamePasswordEditor::sltHandlePasswordVisibility);
359 connect(m_pPasswordRepeatLineEdit, &UIPasswordLineEdit::sigTextVisibilityToggled,
360 this, &UIUserNamePasswordEditor::sltHandlePasswordVisibility);
361 connect(m_pPasswordLineEdit, &UIPasswordLineEdit::textChanged,
362 this, &UIUserNamePasswordEditor::sltPasswordChanged);
363 connect(m_pPasswordRepeatLineEdit, &UIPasswordLineEdit::textChanged,
364 this, &UIUserNamePasswordEditor::sltPasswordChanged);
365 connect(m_pUserNameLineEdit, &UIMarkableLineEdit::textChanged,
366 this, &UIUserNamePasswordEditor::sltUserNameChanged);
367
368 retranslateUi();
369}
370
371void UIUserNamePasswordEditor::sltHandlePasswordVisibility(bool fPasswordVisible)
372{
373 if (m_pPasswordLineEdit)
374 m_pPasswordLineEdit->toggleTextVisibility(fPasswordVisible);
375 if (m_pPasswordRepeatLineEdit)
376 m_pPasswordRepeatLineEdit->toggleTextVisibility(fPasswordVisible);
377}
378
379void UIUserNamePasswordEditor::sltUserNameChanged()
380{
381 isUserNameComplete();
382 emit sigUserNameChanged(m_pUserNameLineEdit->text());
383}
384
385void UIUserNamePasswordEditor::sltPasswordChanged()
386{
387 isPasswordComplete();
388 emit sigPasswordChanged(m_pPasswordLineEdit->text());
389}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette