File indexing completed on 2024-04-28 16:43:19

0001 /*
0002  *   SPDX-FileCopyrightText: 2010 Alejandro Fiestas Olivares <alex@eyeos.org>
0003  *   SPDX-FileCopyrightText: 2010 Eduardo Robles Elvira <edulix@gmail.com>
0004  *   SPDX-FileCopyrightText: 2010 UFO Coders <info@ufocoders.com>
0005  *   SPDX-FileCopyrightText: 2014-2015 David Rosca <nowrep@gmail.com>
0006  *
0007  *   SPDX-License-Identifier: GPL-2.0-or-later
0008  */
0009 
0010 #include "requestpin.h"
0011 #include "bluedevil_kded.h"
0012 #include "ui_requestpin.h"
0013 
0014 #include <QDialog>
0015 #include <QIcon>
0016 #include <QPushButton>
0017 #include <QRegularExpressionValidator>
0018 
0019 #include <KLocalizedString>
0020 #include <KNotification>
0021 #include <KX11Extras>
0022 
0023 RequestPin::RequestPin(BluezQt::DevicePtr device, bool numeric, QObject *parent)
0024     : QObject(parent)
0025     , m_device(device)
0026     , m_numeric(numeric)
0027 {
0028     m_notification = new KNotification(QStringLiteral("RequestPin"), KNotification::Persistent, this);
0029 
0030     m_notification->setComponentName(QStringLiteral("bluedevil"));
0031     m_notification->setTitle(QStringLiteral("%1 (%2)").arg(m_device->name().toHtmlEscaped(), m_device->address().toHtmlEscaped()));
0032     m_notification->setText(
0033         i18nc("Shown in a notification to announce that a PIN is needed to accomplish a pair action,"
0034               "%1 is the name of the bluetooth device",
0035               "PIN needed to pair with %1",
0036               m_device->name().toHtmlEscaped()));
0037 
0038     QStringList actions;
0039     actions.append(i18nc("Notification button which once clicked, a dialog to introduce the PIN will be shown", "Introduce PIN"));
0040 
0041     m_notification->setActions(actions);
0042 
0043     connect(m_notification, &KNotification::action1Activated, this, &RequestPin::introducePin);
0044     connect(m_notification, &KNotification::closed, this, &RequestPin::quit);
0045     connect(m_notification, &KNotification::ignored, this, &RequestPin::quit);
0046     connect(parent, SIGNAL(agentCanceled()), this, SLOT(quit()));
0047 
0048     m_notification->sendEvent();
0049 }
0050 
0051 void RequestPin::introducePin()
0052 {
0053     m_notification->disconnect();
0054     m_notification->close();
0055     m_notification->deleteLater();
0056 
0057     QDialog *dialog = new QDialog;
0058     dialog->setAttribute(Qt::WA_DeleteOnClose);
0059     dialog->setWindowIcon(QIcon::fromTheme(QStringLiteral("preferences-system-bluetooth")));
0060 
0061     dialog->setWindowTitle(i18nc("Shown in the caption of a dialog where the user introduce the PIN", "Introduce PIN"));
0062 
0063     m_dialogWidget = new Ui::DialogWidget;
0064     m_dialogWidget->setupUi(dialog);
0065     m_dialogWidget->descLabel->setText(
0066         i18nc("Shown in a dialog which asks to introduce a PIN that will be used to pair a Bluetooth device,"
0067               "%1 is the name of the Bluetooth device",
0068               "In order to pair this computer with %1, you have to enter a PIN. Please do it below.",
0069               m_device->name()));
0070 
0071     m_dialogWidget->pixmap->setPixmap(QIcon::fromTheme(QStringLiteral("preferences-system-bluetooth")).pixmap(64));
0072     m_dialogWidget->pin->setFocus(Qt::ActiveWindowFocusReason);
0073 
0074     if (m_numeric) {
0075         QRegularExpression rx(QStringLiteral("[0-9]{1,6}"));
0076         m_dialogWidget->pin->setValidator(new QRegularExpressionValidator(rx, this));
0077     } else {
0078         QRegularExpression rx(QStringLiteral("[A-Za-z0-9]{1,16}"));
0079         m_dialogWidget->pin->setValidator(new QRegularExpressionValidator(rx, this));
0080     }
0081 
0082     m_dialogWidget->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
0083     dialog->setFixedSize(dialog->sizeHint());
0084 
0085     connect(dialog, &QDialog::finished, this, &RequestPin::dialogFinished);
0086     connect(m_dialogWidget->pin, &QLineEdit::textChanged, this, &RequestPin::checkPin);
0087     connect(m_dialogWidget->buttonBox, &QDialogButtonBox::accepted, dialog, &QDialog::accept);
0088     connect(m_dialogWidget->buttonBox, &QDialogButtonBox::rejected, dialog, &QDialog::reject);
0089 
0090     dialog->setWindowFlags(Qt::WindowStaysOnTopHint);
0091 
0092     dialog->show();
0093 
0094     KX11Extras::forceActiveWindow(dialog->winId());
0095 }
0096 
0097 void RequestPin::checkPin(const QString &pin)
0098 {
0099     m_dialogWidget->buttonBox->button(QDialogButtonBox::Ok)->setEnabled(!pin.isEmpty());
0100 }
0101 
0102 void RequestPin::dialogFinished(int result)
0103 {
0104     deleteLater();
0105 
0106     if (!result) {
0107         qCDebug(BLUEDEVIL_KDED_LOG) << "PIN dialog rejected:" << m_device->name() << m_device->address();
0108         Q_EMIT done(QString());
0109         return;
0110     }
0111 
0112     qCDebug(BLUEDEVIL_KDED_LOG) << "PIN dialog accepted:" << m_device->name() << m_device->address();
0113     Q_EMIT done(m_dialogWidget->pin->text().toLatin1().constData());
0114 }
0115 
0116 void RequestPin::quit()
0117 {
0118     qCDebug(BLUEDEVIL_KDED_LOG) << "Rejected to introduce PIN:" << m_device->name() << m_device->address();
0119 
0120     deleteLater();
0121     Q_EMIT done(QString());
0122 }