2017-12-20 14:39:09 +01:00
|
|
|
/* === This file is part of Calamares - <https://github.com/calamares> ===
|
2014-07-31 14:52:05 +02:00
|
|
|
*
|
2017-01-12 13:44:11 +01:00
|
|
|
* Copyright 2014-2017, Teo Mrnjavac <teo@kde.org>
|
2018-06-15 11:59:11 +02:00
|
|
|
* Copyright 2017-2018, Adriaan de Groot <groot@kde.org>
|
2019-04-08 18:02:23 +02:00
|
|
|
* Copyright 2019, Collabora Ltd <arnaud.ferraris@collabora.com>
|
2017-11-02 16:35:53 +01:00
|
|
|
* Copyright 2020, Gabriel Craciunescu <crazy@frugalware.org>
|
2014-07-31 14:52:05 +02:00
|
|
|
*
|
|
|
|
* Portions from the Manjaro Installation Framework
|
|
|
|
* by Roland Singer <roland@manjaro.org>
|
|
|
|
* Copyright (C) 2007 Free Software Foundation, Inc.
|
|
|
|
*
|
|
|
|
* Calamares is free software: you can redistribute it and/or modify
|
|
|
|
* it under the terms of the GNU General Public License as published by
|
|
|
|
* the Free Software Foundation, either version 3 of the License, or
|
|
|
|
* (at your option) any later version.
|
|
|
|
*
|
|
|
|
* Calamares is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
* GNU General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU General Public License
|
|
|
|
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "UsersPage.h"
|
2019-04-29 12:48:01 +02:00
|
|
|
|
2020-07-27 16:09:29 +02:00
|
|
|
#include "Config.h"
|
2020-07-28 12:16:03 +02:00
|
|
|
#include "ui_page_usersetup.h"
|
2019-04-29 12:48:01 +02:00
|
|
|
|
2014-07-31 19:06:31 +02:00
|
|
|
#include "GlobalStorage.h"
|
2019-04-29 12:48:01 +02:00
|
|
|
#include "JobQueue.h"
|
|
|
|
#include "Settings.h"
|
2014-08-26 15:26:30 +02:00
|
|
|
#include "utils/CalamaresUtilsGui.h"
|
2019-04-29 12:48:01 +02:00
|
|
|
#include "utils/Logger.h"
|
2014-11-13 17:42:02 +01:00
|
|
|
#include "utils/Retranslator.h"
|
2019-04-29 12:48:01 +02:00
|
|
|
#include "utils/String.h"
|
2014-07-31 14:52:05 +02:00
|
|
|
|
|
|
|
#include <QBoxLayout>
|
2017-11-02 16:35:53 +01:00
|
|
|
#include <QFile>
|
2014-07-31 14:52:05 +02:00
|
|
|
#include <QLabel>
|
|
|
|
#include <QLineEdit>
|
|
|
|
|
2019-11-01 14:48:46 +01:00
|
|
|
/** @brief How bad is the error for labelError() ? */
|
|
|
|
enum class Badness
|
|
|
|
{
|
|
|
|
Fatal,
|
|
|
|
Warning
|
|
|
|
};
|
|
|
|
|
2017-09-19 09:41:28 +02:00
|
|
|
/** Add an error message and pixmap to a label. */
|
|
|
|
static inline void
|
2020-08-05 12:24:39 +02:00
|
|
|
labelError( QLabel* pix, QLabel* label, const QString& message, Badness bad )
|
2017-09-18 16:08:21 +02:00
|
|
|
{
|
2017-09-19 09:41:28 +02:00
|
|
|
label->setText( message );
|
2019-11-01 14:48:46 +01:00
|
|
|
pix->setPixmap( CalamaresUtils::defaultPixmap( ( bad == Badness::Fatal ) ? CalamaresUtils::StatusError
|
|
|
|
: CalamaresUtils::StatusWarning,
|
|
|
|
CalamaresUtils::Original,
|
|
|
|
label->size() ) );
|
2017-09-19 09:41:28 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/** Clear error, indicate OK on a label. */
|
|
|
|
static inline void
|
|
|
|
labelOk( QLabel* pix, QLabel* label )
|
|
|
|
{
|
|
|
|
label->clear();
|
|
|
|
pix->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::Yes, CalamaresUtils::Original, label->size() ) );
|
2017-09-18 16:08:21 +02:00
|
|
|
}
|
2014-07-31 14:52:05 +02:00
|
|
|
|
2020-07-28 10:45:38 +02:00
|
|
|
/** Indicate error, update @p ok based on @p status */
|
|
|
|
static inline void
|
|
|
|
labelStatus( QLabel* pix, QLabel* label, const QString& value, const QString& status, bool& ok )
|
|
|
|
{
|
|
|
|
if ( status.isEmpty() )
|
|
|
|
{
|
|
|
|
if ( value.isEmpty() )
|
|
|
|
{
|
|
|
|
// This is different from labelOK() because no checkmark is shown
|
|
|
|
label->clear();
|
|
|
|
pix->clear();
|
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
labelOk( pix, label );
|
|
|
|
ok = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-08-05 12:24:39 +02:00
|
|
|
labelError( pix, label, status, Badness::Fatal );
|
2020-07-28 10:45:38 +02:00
|
|
|
ok = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-07-25 15:21:04 +02:00
|
|
|
UsersPage::UsersPage( Config* config, QWidget* parent )
|
2014-07-31 14:52:05 +02:00
|
|
|
: QWidget( parent )
|
|
|
|
, ui( new Ui::Page_UserSetup )
|
2020-07-25 15:21:04 +02:00
|
|
|
, m_config( config )
|
2014-08-13 17:16:54 +02:00
|
|
|
, m_readyFullName( false )
|
2014-07-31 14:52:05 +02:00
|
|
|
, m_readyUsername( false )
|
|
|
|
, m_readyHostname( false )
|
|
|
|
, m_readyPassword( false )
|
|
|
|
, m_readyRootPassword( false )
|
|
|
|
{
|
|
|
|
ui->setupUi( this );
|
|
|
|
|
2020-08-04 22:16:48 +02:00
|
|
|
ui->checkBoxReusePassword->setVisible( m_config->writeRootPassword() );
|
|
|
|
ui->checkBoxReusePassword->setChecked( m_config->reuseUserPasswordForRoot() );
|
|
|
|
|
|
|
|
ui->checkBoxValidatePassword->setVisible( m_config->permitWeakPasswords() );
|
|
|
|
ui->checkBoxValidatePassword->setChecked( m_config->requireStrongPasswords() );
|
|
|
|
|
2014-07-31 14:52:05 +02:00
|
|
|
// Connect signals and slots
|
2020-08-17 15:01:35 +02:00
|
|
|
ui->textBoxUserPassword->setText( config->userPassword() );
|
|
|
|
connect( ui->textBoxUserPassword, &QLineEdit::textChanged, config, &Config::setUserPassword );
|
|
|
|
connect( config, &Config::userPasswordChanged, ui->textBoxUserPassword, &QLineEdit::setText );
|
|
|
|
ui->textBoxUserVerifiedPassword->setText( config->userPasswordSecondary() );
|
|
|
|
connect( ui->textBoxUserVerifiedPassword, &QLineEdit::textChanged, config, &Config::setUserPasswordSecondary );
|
|
|
|
connect( config, &Config::userPasswordSecondaryChanged, ui->textBoxUserVerifiedPassword, &QLineEdit::setText );
|
|
|
|
connect( config, &Config::userPasswordStatusChanged, this, &UsersPage::reportUserPasswordStatus );
|
|
|
|
|
|
|
|
ui->textBoxRootPassword->setText( config->rootPassword() );
|
|
|
|
connect( ui->textBoxRootPassword, &QLineEdit::textChanged, config, &Config::setRootPassword );
|
|
|
|
connect( config, &Config::rootPasswordChanged, ui->textBoxRootPassword, &QLineEdit::setText );
|
|
|
|
ui->textBoxVerifiedRootPassword->setText( config->rootPasswordSecondary() );
|
|
|
|
connect( ui->textBoxVerifiedRootPassword, &QLineEdit::textChanged, config, &Config::setRootPasswordSecondary );
|
|
|
|
connect( config, &Config::rootPasswordSecondaryChanged, ui->textBoxVerifiedRootPassword, &QLineEdit::setText );
|
|
|
|
connect( config, &Config::rootPasswordStatusChanged, this, &UsersPage::reportRootPasswordStatus );
|
|
|
|
|
|
|
|
connect( ui->checkBoxValidatePassword, &QCheckBox::stateChanged, this, [this]( int checked ) {
|
|
|
|
m_config->setRequireStrongPasswords( checked != Qt::Unchecked );
|
2019-08-28 17:14:00 +02:00
|
|
|
} );
|
2014-08-13 17:16:54 +02:00
|
|
|
|
2020-07-27 17:52:46 +02:00
|
|
|
connect( ui->textBoxFullName, &QLineEdit::textEdited, config, &Config::setFullName );
|
|
|
|
connect( config, &Config::fullNameChanged, this, &UsersPage::onFullNameTextEdited );
|
|
|
|
|
|
|
|
connect( ui->textBoxHostName, &QLineEdit::textEdited, config, &Config::setHostName );
|
2020-07-27 16:09:29 +02:00
|
|
|
connect( config, &Config::hostNameChanged, ui->textBoxHostName, &QLineEdit::setText );
|
2020-07-28 10:45:38 +02:00
|
|
|
connect( config, &Config::hostNameStatusChanged, this, &UsersPage::reportHostNameStatus );
|
2020-07-27 16:09:29 +02:00
|
|
|
|
|
|
|
connect( ui->textBoxLoginName, &QLineEdit::textEdited, config, &Config::setLoginName );
|
|
|
|
connect( config, &Config::loginNameChanged, ui->textBoxLoginName, &QLineEdit::setText );
|
2020-07-28 10:21:23 +02:00
|
|
|
connect( config, &Config::loginNameStatusChanged, this, &UsersPage::reportLoginNameStatus );
|
2014-11-13 17:42:02 +01:00
|
|
|
|
2020-07-28 11:41:52 +02:00
|
|
|
connect( ui->checkBoxDoAutoLogin, &QCheckBox::stateChanged, this, [this]( int checked ) {
|
|
|
|
m_config->setAutoLogin( checked != Qt::Unchecked );
|
|
|
|
} );
|
|
|
|
connect( config, &Config::autoLoginChanged, ui->checkBoxDoAutoLogin, &QCheckBox::setChecked );
|
|
|
|
|
2020-08-04 22:16:48 +02:00
|
|
|
if ( m_config->writeRootPassword() )
|
|
|
|
{
|
|
|
|
connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged, this, [this]( int checked ) {
|
|
|
|
m_config->setReuseUserPasswordForRoot( checked != Qt::Unchecked );
|
|
|
|
} );
|
|
|
|
connect( config, &Config::reuseUserPasswordForRootChanged, ui->checkBoxReusePassword, &QCheckBox::setChecked );
|
2020-08-17 15:01:35 +02:00
|
|
|
connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged, this, &UsersPage::onReuseUserPasswordChanged );
|
2020-08-04 22:16:48 +02:00
|
|
|
}
|
2019-11-01 13:46:07 +01:00
|
|
|
|
2020-08-04 22:16:48 +02:00
|
|
|
if ( m_config->permitWeakPasswords() )
|
|
|
|
{
|
|
|
|
connect( ui->checkBoxValidatePassword, &QCheckBox::stateChanged, this, [this]( int checked ) {
|
|
|
|
m_config->setRequireStrongPasswords( checked != Qt::Unchecked );
|
|
|
|
} );
|
|
|
|
connect( config, &Config::requireStrongPasswordsChanged, ui->checkBoxValidatePassword, &QCheckBox::setChecked );
|
|
|
|
}
|
2015-06-11 04:02:06 +02:00
|
|
|
|
2020-08-17 12:16:41 +02:00
|
|
|
CALAMARES_RETRANSLATE_SLOT( &UsersPage::retranslate )
|
2020-08-04 22:16:48 +02:00
|
|
|
|
|
|
|
onReuseUserPasswordChanged( m_config->reuseUserPasswordForRoot() );
|
2014-07-31 14:52:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
UsersPage::~UsersPage()
|
|
|
|
{
|
|
|
|
delete ui;
|
|
|
|
}
|
|
|
|
|
2019-11-01 13:46:07 +01:00
|
|
|
void
|
|
|
|
UsersPage::retranslate()
|
|
|
|
{
|
|
|
|
ui->retranslateUi( this );
|
|
|
|
if ( Calamares::Settings::instance()->isSetupMode() )
|
|
|
|
{
|
2020-07-27 16:09:29 +02:00
|
|
|
ui->textBoxLoginName->setToolTip( tr( "<small>If more than one person will "
|
2020-07-27 17:52:46 +02:00
|
|
|
"use this computer, you can create multiple "
|
|
|
|
"accounts after setup.</small>" ) );
|
2019-11-01 13:46:07 +01:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2020-07-27 16:09:29 +02:00
|
|
|
ui->textBoxLoginName->setToolTip( tr( "<small>If more than one person will "
|
2020-07-27 17:52:46 +02:00
|
|
|
"use this computer, you can create multiple "
|
|
|
|
"accounts after installation.</small>" ) );
|
2019-11-01 13:46:07 +01:00
|
|
|
}
|
2020-08-17 15:01:35 +02:00
|
|
|
|
|
|
|
const auto up = m_config->userPasswordStatus();
|
|
|
|
reportUserPasswordStatus( up.first, up.second );
|
|
|
|
const auto rp = m_config->rootPasswordStatus();
|
|
|
|
reportRootPasswordStatus( rp.first, rp.second );
|
2019-11-01 13:46:07 +01:00
|
|
|
}
|
|
|
|
|
2014-07-31 14:52:05 +02:00
|
|
|
|
|
|
|
bool
|
2020-07-28 12:16:03 +02:00
|
|
|
UsersPage::isReady() const
|
2014-07-31 14:52:05 +02:00
|
|
|
{
|
2019-10-21 17:21:33 +02:00
|
|
|
bool readyFields = m_readyFullName && m_readyHostname && m_readyPassword && m_readyUsername;
|
2020-07-28 11:59:53 +02:00
|
|
|
// If we're going to write a root password, we need a valid one (or reuse the user's password)
|
|
|
|
readyFields
|
|
|
|
&= m_config->writeRootPassword() ? ( m_readyRootPassword || ui->checkBoxReusePassword->isChecked() ) : true;
|
|
|
|
return readyFields;
|
2014-07-31 14:52:05 +02:00
|
|
|
}
|
|
|
|
|
2014-07-31 19:06:31 +02:00
|
|
|
|
2014-11-14 18:21:04 +01:00
|
|
|
void
|
2014-11-26 18:40:30 +01:00
|
|
|
UsersPage::onActivate()
|
2014-11-14 18:21:04 +01:00
|
|
|
{
|
|
|
|
ui->textBoxFullName->setFocus();
|
2020-08-17 15:01:35 +02:00
|
|
|
const auto up = m_config->userPasswordStatus();
|
|
|
|
reportUserPasswordStatus( up.first, up.second );
|
|
|
|
const auto rp = m_config->rootPasswordStatus();
|
|
|
|
reportRootPasswordStatus( rp.first, rp.second );
|
2014-11-14 18:21:04 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-07-31 14:52:05 +02:00
|
|
|
void
|
2020-07-28 11:18:07 +02:00
|
|
|
UsersPage::onFullNameTextEdited( const QString& fullName )
|
2014-07-31 14:52:05 +02:00
|
|
|
{
|
2020-07-28 11:18:07 +02:00
|
|
|
labelStatus( ui->labelFullName, ui->labelFullNameError, fullName, QString(), m_readyFullName );
|
2014-08-13 17:16:54 +02:00
|
|
|
checkReady( isReady() );
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-07-28 10:21:23 +02:00
|
|
|
UsersPage::reportLoginNameStatus( const QString& status )
|
2014-08-13 17:16:54 +02:00
|
|
|
{
|
2020-07-28 10:45:38 +02:00
|
|
|
labelStatus( ui->labelUsername, ui->labelUsernameError, m_config->loginName(), status, m_readyUsername );
|
2014-07-31 14:52:05 +02:00
|
|
|
emit checkReady( isReady() );
|
|
|
|
}
|
|
|
|
|
2014-08-13 17:16:54 +02:00
|
|
|
void
|
2020-07-28 10:45:38 +02:00
|
|
|
UsersPage::reportHostNameStatus( const QString& status )
|
2014-07-31 14:52:05 +02:00
|
|
|
{
|
2020-07-28 10:45:38 +02:00
|
|
|
labelStatus( ui->labelHostname, ui->labelHostnameError, m_config->hostName(), status, m_readyHostname );
|
2014-07-31 14:52:05 +02:00
|
|
|
emit checkReady( isReady() );
|
|
|
|
}
|
|
|
|
|
2020-08-17 15:01:35 +02:00
|
|
|
static inline void
|
|
|
|
passwordStatus( QLabel* iconLabel, QLabel* messageLabel, int validity, const QString& message )
|
2014-07-31 14:52:05 +02:00
|
|
|
{
|
2020-08-17 15:01:35 +02:00
|
|
|
switch ( validity )
|
2014-07-31 14:52:05 +02:00
|
|
|
{
|
2020-08-17 15:01:35 +02:00
|
|
|
case Config::PasswordValidity::Valid:
|
|
|
|
messageLabel->clear();
|
|
|
|
iconLabel->setPixmap(
|
|
|
|
CalamaresUtils::defaultPixmap( CalamaresUtils::Yes, CalamaresUtils::Original, messageLabel->size() ) );
|
|
|
|
break;
|
|
|
|
case Config::PasswordValidity::Weak:
|
|
|
|
messageLabel->setText( message );
|
|
|
|
iconLabel->setPixmap( CalamaresUtils::defaultPixmap(
|
|
|
|
CalamaresUtils::StatusWarning, CalamaresUtils::Original, messageLabel->size() ) );
|
|
|
|
break;
|
|
|
|
case Config::PasswordValidity::Invalid:
|
|
|
|
default:
|
|
|
|
messageLabel->setText( message );
|
|
|
|
iconLabel->setPixmap( CalamaresUtils::defaultPixmap(
|
|
|
|
CalamaresUtils::StatusError, CalamaresUtils::Original, messageLabel->size() ) );
|
|
|
|
break;
|
2014-07-31 14:52:05 +02:00
|
|
|
}
|
2019-11-01 13:38:14 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-08-17 15:01:35 +02:00
|
|
|
UsersPage::reportRootPasswordStatus( int validity, const QString& message )
|
2019-11-01 13:38:14 +01:00
|
|
|
{
|
2020-08-17 15:01:35 +02:00
|
|
|
passwordStatus( ui->labelRootPassword, ui->labelRootPasswordError, validity, message );
|
2014-07-31 14:52:05 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void
|
2020-08-17 15:01:35 +02:00
|
|
|
UsersPage::reportUserPasswordStatus( int validity, const QString& message )
|
2014-07-31 14:52:05 +02:00
|
|
|
{
|
2020-08-17 15:01:35 +02:00
|
|
|
passwordStatus( ui->labelUserPassword, ui->labelUserPasswordError, validity, message );
|
2014-07-31 14:52:05 +02:00
|
|
|
}
|
2015-08-19 12:51:06 +02:00
|
|
|
|
2020-08-17 15:01:35 +02:00
|
|
|
|
2015-11-09 01:53:11 +01:00
|
|
|
void
|
2020-08-04 22:16:48 +02:00
|
|
|
UsersPage::onReuseUserPasswordChanged( const int checked )
|
2015-11-09 01:53:11 +01:00
|
|
|
{
|
2020-08-04 22:16:48 +02:00
|
|
|
/* When "reuse" is checked, hide the fields for explicitly
|
|
|
|
* entering the root password. However, if we're going to
|
|
|
|
* disable the root password anyway, hide them all regardless of
|
|
|
|
* the checkbox -- so when writeRoot is false, visible needs
|
|
|
|
* to be false, to hide them all.
|
|
|
|
*
|
|
|
|
* In principle this is only connected when writeRootPassword is @c true,
|
|
|
|
* but it is **always** called at least once in the constructor
|
|
|
|
* to set up initial visibility.
|
|
|
|
*/
|
|
|
|
const bool visible = m_config->writeRootPassword() ? !checked : false;
|
|
|
|
ui->labelChooseRootPassword->setVisible( visible );
|
|
|
|
ui->labelRootPassword->setVisible( visible );
|
|
|
|
ui->labelRootPasswordError->setVisible( visible );
|
|
|
|
ui->textBoxRootPassword->setVisible( visible );
|
|
|
|
ui->textBoxVerifiedRootPassword->setVisible( visible );
|
|
|
|
checkReady( isReady() );
|
2015-11-09 01:53:11 +01:00
|
|
|
}
|