// Copyright (C) 2023 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 #include "passworddialog.h" #include "layoutbuilder.h" #include "stylehelper.h" #include "utilsicons.h" #include "utilstr.h" #include #include #include #include #include #include namespace Utils { ShowPasswordButton::ShowPasswordButton(QWidget *parent) : QAbstractButton(parent) { setAttribute(Qt::WA_Hover); setCheckable(true); setToolTip(Tr::tr("Show/Hide Password")); } void ShowPasswordButton::paintEvent(QPaintEvent *e) { Q_UNUSED(e) QIcon icon = isChecked() ? Utils::Icons::EYE_OPEN_TOOLBAR.icon() : Utils::Icons::EYE_CLOSED_TOOLBAR.icon(); QPainter p(this); QRect r(QPoint(), size()); if (m_containsMouse && isEnabled()) StyleHelper::drawPanelBgRect(&p, r, creatorColor(Theme::FancyToolButtonHoverColor)); QSize s = icon.actualSize(QSize(32, 16)); QPixmap px = icon.pixmap(s); QRect iRect(QPoint(), s); iRect.moveCenter(r.center()); p.drawPixmap(iRect, px); } void ShowPasswordButton::enterEvent(QEnterEvent *e) { m_containsMouse = true; e->accept(); update(); } void ShowPasswordButton::leaveEvent(QEvent *e) { m_containsMouse = false; e->accept(); update(); } QSize ShowPasswordButton::sizeHint() const { QSize s = Utils::Icons::EYE_OPEN_TOOLBAR.icon().actualSize(QSize(32, 16)) + QSize(8, 8); if (StyleHelper::toolbarStyle() == StyleHelper::ToolbarStyle::Relaxed) s += QSize(5, 5); return s; } class PasswordDialogPrivate { public: QLineEdit *m_userNameLineEdit{nullptr}; QLineEdit *m_passwordLineEdit{nullptr}; QCheckBox *m_checkBox{nullptr}; QDialogButtonBox *m_buttonBox{nullptr}; }; PasswordDialog::PasswordDialog(const QString &title, const QString &prompt, const QString &doNotAskAgainLabel, bool withUsername, QWidget *parent) : QDialog(parent) , d(new PasswordDialogPrivate) { setWindowTitle(title); d->m_passwordLineEdit = new QLineEdit(); d->m_passwordLineEdit->setEchoMode(QLineEdit::Password); if (withUsername) d->m_userNameLineEdit = new QLineEdit(); d->m_checkBox = new QCheckBox(); d->m_checkBox->setText(doNotAskAgainLabel); auto *showPasswordButton = new ShowPasswordButton; connect(showPasswordButton, &QAbstractButton::toggled, this, [this, showPasswordButton] { d->m_passwordLineEdit->setEchoMode(showPasswordButton->isChecked() ? QLineEdit::Normal : QLineEdit::Password); }); d->m_buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel); connect(d->m_buttonBox, &QDialogButtonBox::accepted, this, &QDialog::accept); connect(d->m_buttonBox, &QDialogButtonBox::rejected, this, &QDialog::reject); using namespace Layouting; // clang-format off Column { prompt, If (withUsername) >> Then { Form { Tr::tr("User:"), d->m_userNameLineEdit, br, Tr::tr("Password:"), Row { d->m_passwordLineEdit, showPasswordButton }, br, } } >> Else { Row { d->m_passwordLineEdit, showPasswordButton, }, }, Row { d->m_checkBox, d->m_buttonBox, } }.attachTo(this); // clang-format on d->m_passwordLineEdit->setMinimumWidth(d->m_passwordLineEdit->width() / 2); setFixedSize(sizeHint()); } PasswordDialog::~PasswordDialog() = default; void PasswordDialog::setUser(const QString &user) { QTC_ASSERT(d->m_userNameLineEdit, return); d->m_userNameLineEdit->setText(user); } QString PasswordDialog::user() const { QTC_ASSERT(d->m_userNameLineEdit, return {}); return d->m_userNameLineEdit->text(); } QString PasswordDialog::password() const { return d->m_passwordLineEdit->text(); } std::optional> PasswordDialog::getUserAndPassword( const QString &title, const QString &prompt, const QString &doNotAskAgainLabel, const QString &userName, const CheckableDecider &decider, QWidget *parent) { if (!decider.shouldAskAgain()) return std::nullopt; PasswordDialog dialog(title, prompt, doNotAskAgainLabel, true, parent); dialog.setUser(userName); if (dialog.exec() == QDialog::Accepted) return qMakePair(dialog.user(), dialog.password()); if (dialog.d->m_checkBox->isChecked()) decider.doNotAskAgain(); return std::nullopt; } std::optional PasswordDialog::getPassword(const QString &title, const QString &prompt, const QString &doNotAskAgainLabel, const CheckableDecider &decider, QWidget *parent) { if (!decider.shouldAskAgain()) return std::nullopt; PasswordDialog dialog(title, prompt, doNotAskAgainLabel, false, parent); if (dialog.exec() == QDialog::Accepted) return dialog.password(); if (dialog.d->m_checkBox->isChecked()) decider.doNotAskAgain(); return std::nullopt; } } // namespace Utils