[users] enhance dialog
- multiple users management. - ability to set different shells based on configuration. - ability to select avatars from files and then copy them to a target location in the user's home directory. No specific location suggested due to differences between DEs on where to read avatars from.
This commit is contained in:
parent
0b4f015d3a
commit
09f6392173
@ -7,13 +7,16 @@ calamares_add_plugin( users
|
||||
TYPE viewmodule
|
||||
EXPORT_MACRO PLUGINDLLEXPORT_PRO
|
||||
SOURCES
|
||||
CreateUserJob.cpp
|
||||
SetPasswordJob.cpp
|
||||
jobs/CreateUserJob.cpp
|
||||
jobs/SetPasswordJob.cpp
|
||||
UsersViewStep.cpp
|
||||
UsersPage.cpp
|
||||
SetHostNameJob.cpp
|
||||
gui/UsersPage.cpp
|
||||
jobs/SetHostNameJob.cpp
|
||||
jobs/SetAvatarJob.cpp
|
||||
gui/AddUserDialog.cpp
|
||||
UI
|
||||
page_usersetup.ui
|
||||
gui/page_usersetup.ui
|
||||
gui/adduserdialog.ui
|
||||
RESOURCES
|
||||
users.qrc
|
||||
LINK_LIBRARIES
|
||||
|
16
src/modules/users/README.md
Normal file
16
src/modules/users/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# Users module
|
||||
|
||||
The users module take care of managing the users that will be created on the installed system.
|
||||
|
||||
## Configuration of the module
|
||||
|
||||
The following settings are available in **users.conf**:
|
||||
|
||||
- ```defaultGroups```: list of groups every user will be added to.
|
||||
- ```autologinGroup```: group to add the user with autologin to, if any.
|
||||
- ```doAutologin```: allow for users with autologin (at most one per system). Defaults to false.
|
||||
- ```sudoersGroup```: group for sudoers usage.
|
||||
- ```setRootPassword```: allow to set the root password in the installed system. Defaults to false.
|
||||
- ```availableShells```: comma-separated list of available shells for new users. If not present, new users will not have any explicit shell in /etc/passwd, therefore the system default (usually, /bin/bash) will be used.
|
||||
- ```avatarFilePath```: path where to copy user avatars to; ~ can be used to represent the user's home directory. If not present or empty, we won't allow users to set avatars.
|
||||
|
@ -1,440 +0,0 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2014-2015, Teo Mrnjavac <teo@kde.org>
|
||||
*
|
||||
* 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"
|
||||
#include "ui_page_usersetup.h"
|
||||
#include "CreateUserJob.h"
|
||||
#include "SetPasswordJob.h"
|
||||
#include "SetHostNameJob.h"
|
||||
#include "JobQueue.h"
|
||||
#include "GlobalStorage.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/CalamaresUtilsGui.h"
|
||||
#include "utils/Retranslator.h"
|
||||
|
||||
#include <QBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QRegExp>
|
||||
#include <QRegExpValidator>
|
||||
|
||||
|
||||
|
||||
UsersPage::UsersPage( QWidget* parent )
|
||||
: QWidget( parent )
|
||||
, ui( new Ui::Page_UserSetup )
|
||||
, m_readyFullName( false )
|
||||
, m_readyUsername( false )
|
||||
, m_readyHostname( false )
|
||||
, m_readyPassword( false )
|
||||
, m_readyRootPassword( false )
|
||||
, m_writeRootPassword( true )
|
||||
{
|
||||
ui->setupUi( this );
|
||||
|
||||
// Connect signals and slots
|
||||
connect( ui->textBoxFullName, &QLineEdit::textEdited,
|
||||
this, &UsersPage::onFullNameTextEdited );
|
||||
connect( ui->textBoxUsername, &QLineEdit::textEdited,
|
||||
this, &UsersPage::onUsernameTextEdited );
|
||||
connect( ui->textBoxHostname, &QLineEdit::textEdited,
|
||||
this, &UsersPage::onHostnameTextEdited );
|
||||
connect( ui->textBoxUserPassword, &QLineEdit::textChanged,
|
||||
this, &UsersPage::onPasswordTextChanged );
|
||||
connect( ui->textBoxUserVerifiedPassword, &QLineEdit::textChanged,
|
||||
this, &UsersPage::onPasswordTextChanged );
|
||||
connect( ui->textBoxRootPassword, &QLineEdit::textChanged,
|
||||
this, &UsersPage::onRootPasswordTextChanged );
|
||||
connect( ui->textBoxVerifiedRootPassword, &QLineEdit::textChanged,
|
||||
this, &UsersPage::onRootPasswordTextChanged );
|
||||
connect( ui->checkBoxReusePassword, &QCheckBox::stateChanged,
|
||||
this, [this]( int checked )
|
||||
{
|
||||
ui->labelChooseRootPassword->setVisible( !checked );
|
||||
ui->labelExtraRootPassword->setVisible( !checked );
|
||||
ui->labelRootPassword->setVisible( !checked );
|
||||
ui->labelRootPasswordError->setVisible( !checked );
|
||||
ui->textBoxRootPassword->setVisible( !checked );
|
||||
ui->textBoxVerifiedRootPassword->setVisible( !checked );
|
||||
checkReady( isReady() );
|
||||
} );
|
||||
|
||||
m_customUsername = false;
|
||||
m_customHostname = false;
|
||||
|
||||
setWriteRootPassword( true );
|
||||
ui->checkBoxReusePassword->setChecked( true );
|
||||
|
||||
CALAMARES_RETRANSLATE( ui->retranslateUi( this ); )
|
||||
}
|
||||
|
||||
|
||||
UsersPage::~UsersPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
UsersPage::isReady()
|
||||
{
|
||||
bool readyFields = m_readyFullName &&
|
||||
m_readyHostname &&
|
||||
m_readyPassword &&
|
||||
m_readyUsername;
|
||||
if ( !m_writeRootPassword || ui->checkBoxReusePassword->isChecked() )
|
||||
return readyFields;
|
||||
|
||||
return readyFields && m_readyRootPassword;
|
||||
}
|
||||
|
||||
|
||||
QList< Calamares::job_ptr >
|
||||
UsersPage::createJobs( const QStringList& defaultGroupsList )
|
||||
{
|
||||
QList< Calamares::job_ptr > list;
|
||||
if ( !isReady() )
|
||||
return list;
|
||||
|
||||
Calamares::Job* j;
|
||||
j = new CreateUserJob( ui->textBoxUsername->text(),
|
||||
ui->textBoxFullName->text().isEmpty() ?
|
||||
ui->textBoxUsername->text() :
|
||||
ui->textBoxFullName->text(),
|
||||
ui->checkBoxAutoLogin->isChecked(),
|
||||
defaultGroupsList );
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
|
||||
j = new SetPasswordJob( ui->textBoxUsername->text(),
|
||||
ui->textBoxUserPassword->text() );
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
|
||||
if ( m_writeRootPassword )
|
||||
{
|
||||
if ( ui->checkBoxReusePassword->isChecked() )
|
||||
j = new SetPasswordJob( "root",
|
||||
ui->textBoxUserPassword->text() );
|
||||
else
|
||||
j = new SetPasswordJob( "root",
|
||||
ui->textBoxRootPassword->text() );
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
}
|
||||
|
||||
j = new SetHostNameJob( ui->textBoxHostname->text() );
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
|
||||
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
gs->insert( "hostname", ui->textBoxHostname->text() );
|
||||
if ( ui->checkBoxAutoLogin->isChecked() )
|
||||
gs->insert( "autologinUser", ui->textBoxUsername->text() );
|
||||
|
||||
gs->insert( "username", ui->textBoxUsername->text() );
|
||||
gs->insert( "password", CalamaresUtils::obscure( ui->textBoxUserPassword->text() ) );
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersPage::onActivate()
|
||||
{
|
||||
ui->textBoxFullName->setFocus();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersPage::setWriteRootPassword( bool write )
|
||||
{
|
||||
ui->checkBoxReusePassword->setVisible( write );
|
||||
m_writeRootPassword = write;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersPage::onFullNameTextEdited( const QString& textRef )
|
||||
{
|
||||
if ( textRef.isEmpty() )
|
||||
{
|
||||
ui->labelFullNameError->clear();
|
||||
ui->labelFullName->clear();
|
||||
if ( !m_customUsername )
|
||||
ui->textBoxUsername->clear();
|
||||
if ( !m_customHostname )
|
||||
ui->textBoxHostname->clear();
|
||||
m_readyFullName = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labelFullName->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::Yes,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelFullName->size() ) );
|
||||
m_readyFullName = true;
|
||||
fillSuggestions();
|
||||
}
|
||||
checkReady( isReady() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersPage::fillSuggestions()
|
||||
{
|
||||
QString fullName = ui->textBoxFullName->text();
|
||||
QRegExp rx( "[^a-zA-Z0-9 ]", Qt::CaseInsensitive );
|
||||
QString cleanName = CalamaresUtils::removeDiacritics( fullName )
|
||||
.toLower().replace( rx, " " ).simplified();
|
||||
QStringList cleanParts = cleanName.split( ' ' );
|
||||
|
||||
if ( !m_customUsername )
|
||||
{
|
||||
if ( !cleanParts.isEmpty() && !cleanParts.first().isEmpty() )
|
||||
{
|
||||
QString usernameSuggestion = cleanParts.first();
|
||||
for ( int i = 1; i < cleanParts.length(); ++i )
|
||||
{
|
||||
if ( !cleanParts.value( i ).isEmpty() )
|
||||
usernameSuggestion.append( cleanParts.value( i ).at( 0 ) );
|
||||
}
|
||||
if ( USERNAME_RX.indexIn( usernameSuggestion ) != -1 )
|
||||
{
|
||||
ui->textBoxUsername->setText( usernameSuggestion );
|
||||
validateUsernameText( usernameSuggestion );
|
||||
m_customUsername = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( !m_customHostname )
|
||||
{
|
||||
if ( !cleanParts.isEmpty() && !cleanParts.first().isEmpty() )
|
||||
{
|
||||
QString hostnameSuggestion = QString( "%1-pc" ).arg( cleanParts.first() );
|
||||
if ( HOSTNAME_RX.indexIn( hostnameSuggestion ) != -1 )
|
||||
{
|
||||
ui->textBoxHostname->setText( hostnameSuggestion );
|
||||
validateHostnameText( hostnameSuggestion );
|
||||
m_customHostname = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersPage::onUsernameTextEdited( const QString& textRef )
|
||||
{
|
||||
m_customUsername = true;
|
||||
validateUsernameText( textRef );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersPage::validateUsernameText( const QString& textRef )
|
||||
{
|
||||
QString text( textRef );
|
||||
QRegExp rx( USERNAME_RX );
|
||||
QRegExpValidator val( rx );
|
||||
int pos = -1;
|
||||
|
||||
if ( text.isEmpty() )
|
||||
{
|
||||
ui->labelUsernameError->clear();
|
||||
ui->labelUsername->clear();
|
||||
m_readyUsername = false;
|
||||
}
|
||||
else if ( text.length() > USERNAME_MAX_LENGTH )
|
||||
{
|
||||
ui->labelUsername->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelUsername->size() ) );
|
||||
ui->labelUsernameError->setText(
|
||||
tr( "Your username is too long." ) );
|
||||
|
||||
m_readyUsername = false;
|
||||
}
|
||||
else if ( val.validate( text, pos ) == QValidator::Invalid )
|
||||
{
|
||||
ui->labelUsername->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelUsername->size() ) );
|
||||
ui->labelUsernameError->setText(
|
||||
tr( "Your username contains invalid characters. Only lowercase letters and numbers are allowed." ) );
|
||||
|
||||
m_readyUsername = false;
|
||||
}
|
||||
else {
|
||||
ui->labelUsername->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::Yes,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelUsername->size() ) );
|
||||
ui->labelUsernameError->clear();
|
||||
m_readyUsername = true;
|
||||
}
|
||||
|
||||
emit checkReady( isReady() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersPage::onHostnameTextEdited( const QString& textRef )
|
||||
{
|
||||
m_customHostname = true;
|
||||
validateHostnameText( textRef );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersPage::validateHostnameText( const QString& textRef )
|
||||
{
|
||||
QString text = textRef;
|
||||
QRegExp rx( HOSTNAME_RX );
|
||||
QRegExpValidator val( rx );
|
||||
int pos = -1;
|
||||
|
||||
if ( text.isEmpty() )
|
||||
{
|
||||
ui->labelHostnameError->clear();
|
||||
ui->labelHostname->clear();
|
||||
m_readyHostname= false;
|
||||
}
|
||||
else if ( text.length() < HOSTNAME_MIN_LENGTH )
|
||||
{
|
||||
ui->labelHostname->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelHostname->size() ) );
|
||||
ui->labelHostnameError->setText(
|
||||
tr( "Your hostname is too short." ) );
|
||||
|
||||
m_readyHostname = false;
|
||||
|
||||
}
|
||||
else if ( text.length() > HOSTNAME_MAX_LENGTH )
|
||||
{
|
||||
ui->labelHostname->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelHostname->size() ) );
|
||||
ui->labelHostnameError->setText(
|
||||
tr( "Your hostname is too long." ) );
|
||||
|
||||
m_readyHostname = false;
|
||||
|
||||
}
|
||||
else if ( val.validate( text, pos ) == QValidator::Invalid )
|
||||
{
|
||||
ui->labelHostname->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelHostname->size() ) );
|
||||
ui->labelHostnameError->setText(
|
||||
tr( "Your hostname contains invalid characters. Only letters, numbers and dashes are allowed." ) );
|
||||
|
||||
m_readyHostname = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labelHostname->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::Yes,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelHostname->size() ) );
|
||||
ui->labelHostnameError->clear();
|
||||
m_readyHostname = true;
|
||||
}
|
||||
|
||||
emit checkReady( isReady() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersPage::onPasswordTextChanged( const QString& )
|
||||
{
|
||||
QString pw1 = ui->textBoxUserPassword->text();
|
||||
QString pw2 = ui->textBoxUserVerifiedPassword->text();
|
||||
|
||||
if ( pw1.isEmpty() && pw2.isEmpty() )
|
||||
{
|
||||
ui->labelUserPasswordError->clear();
|
||||
ui->labelUserPassword->clear();
|
||||
m_readyPassword = false;
|
||||
}
|
||||
else if ( pw1 != pw2 )
|
||||
{
|
||||
ui->labelUserPasswordError->setText( tr( "Your passwords do not match!" ) );
|
||||
ui->labelUserPassword->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelUserPassword->size() ) );
|
||||
m_readyPassword = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labelUserPasswordError->clear();
|
||||
ui->labelUserPassword->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::Yes,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelUserPassword->size() ) );
|
||||
m_readyPassword = true;
|
||||
}
|
||||
|
||||
emit checkReady( isReady() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersPage::onRootPasswordTextChanged( const QString& )
|
||||
{
|
||||
QString pw1 = ui->textBoxRootPassword->text();
|
||||
QString pw2 = ui->textBoxVerifiedRootPassword->text();
|
||||
|
||||
if ( pw1.isEmpty() && pw2.isEmpty() )
|
||||
{
|
||||
ui->labelRootPasswordError->clear();
|
||||
ui->labelRootPassword->clear();
|
||||
m_readyRootPassword = false;
|
||||
}
|
||||
else if ( pw1 != pw2 )
|
||||
{
|
||||
ui->labelRootPasswordError->setText( tr( "Your passwords do not match!" ) );
|
||||
ui->labelRootPassword->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelRootPassword->size() ) );
|
||||
m_readyRootPassword = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labelRootPasswordError->clear();
|
||||
ui->labelRootPassword->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::Yes,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelRootPassword->size() ) );
|
||||
m_readyRootPassword = true;
|
||||
}
|
||||
|
||||
emit checkReady( isReady() );
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersPage::setAutologinDefault( bool checked )
|
||||
{
|
||||
ui->checkBoxAutoLogin->setChecked( checked );
|
||||
emit checkReady( isReady() );
|
||||
}
|
||||
|
||||
void
|
||||
UsersPage::setReusePasswordDefault( bool checked )
|
||||
{
|
||||
ui->checkBoxReusePassword->setChecked( checked );
|
||||
emit checkReady( isReady() );
|
||||
}
|
@ -1,84 +0,0 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2014-2015, Teo Mrnjavac <teo@kde.org>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef USERSPAGE_H
|
||||
#define USERSPAGE_H
|
||||
|
||||
#include "Typedefs.h"
|
||||
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class Page_UserSetup;
|
||||
}
|
||||
|
||||
class UsersPage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit UsersPage( QWidget* parent = nullptr );
|
||||
virtual ~UsersPage();
|
||||
|
||||
bool isReady();
|
||||
|
||||
QList< Calamares::job_ptr > createJobs( const QStringList& defaultGroupsList );
|
||||
|
||||
void onActivate();
|
||||
|
||||
void setWriteRootPassword( bool show );
|
||||
void setAutologinDefault( bool checked );
|
||||
void setReusePasswordDefault( bool checked );
|
||||
|
||||
protected slots:
|
||||
void onFullNameTextEdited( const QString& );
|
||||
void fillSuggestions();
|
||||
void onUsernameTextEdited( const QString& );
|
||||
void validateUsernameText( const QString& );
|
||||
void onHostnameTextEdited( const QString& );
|
||||
void validateHostnameText( const QString& );
|
||||
void onPasswordTextChanged( const QString& );
|
||||
void onRootPasswordTextChanged( const QString& );
|
||||
|
||||
signals:
|
||||
void checkReady( bool );
|
||||
|
||||
private:
|
||||
Ui::Page_UserSetup* ui;
|
||||
|
||||
const QRegExp USERNAME_RX = QRegExp( "^[a-z_][a-z0-9_-]*[$]?$" );
|
||||
const QRegExp HOSTNAME_RX = QRegExp( "^[a-zA-Z0-9][-a-zA-Z0-9_]*$" );
|
||||
const int USERNAME_MAX_LENGTH = 31;
|
||||
const int HOSTNAME_MIN_LENGTH = 2;
|
||||
const int HOSTNAME_MAX_LENGTH = 24;
|
||||
|
||||
bool m_readyFullName;
|
||||
bool m_readyUsername;
|
||||
bool m_customUsername;
|
||||
bool m_readyHostname;
|
||||
bool m_customHostname;
|
||||
bool m_readyPassword;
|
||||
bool m_readyRootPassword;
|
||||
|
||||
bool m_writeRootPassword;
|
||||
};
|
||||
|
||||
#endif // USERSPAGE_H
|
@ -18,7 +18,7 @@
|
||||
|
||||
#include "UsersViewStep.h"
|
||||
|
||||
#include "UsersPage.h"
|
||||
#include "gui/UsersPage.h"
|
||||
|
||||
#include "JobQueue.h"
|
||||
#include "GlobalStorage.h"
|
||||
@ -139,6 +139,12 @@ UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
configurationMap.value( "autologinGroup" ).toString() );
|
||||
}
|
||||
|
||||
if ( configurationMap.contains( "doAutologin" ) &&
|
||||
configurationMap.value( "doAutologin" ).type() == QVariant::Bool )
|
||||
{
|
||||
m_widget->setAutologin( configurationMap.value( "doAutologin" ).toBool() );
|
||||
}
|
||||
|
||||
if ( configurationMap.contains( "sudoersGroup" ) &&
|
||||
configurationMap.value( "sudoersGroup" ).type() == QVariant::String )
|
||||
{
|
||||
@ -151,19 +157,18 @@ UsersViewStep::setConfigurationMap( const QVariantMap& configurationMap )
|
||||
{
|
||||
Calamares::JobQueue::instance()->globalStorage()->insert( "setRootPassword",
|
||||
configurationMap.value( "setRootPassword" ).toBool() );
|
||||
m_widget->setWriteRootPassword( configurationMap.value( "setRootPassword" ).toBool() );
|
||||
m_widget->setHaveRootPassword( configurationMap.value( "setRootPassword" ).toBool() );
|
||||
}
|
||||
|
||||
if ( configurationMap.contains( "doAutologin" ) &&
|
||||
configurationMap.value( "doAutologin" ).type() == QVariant::Bool )
|
||||
if ( configurationMap.contains( "availableShells" ) &&
|
||||
configurationMap.value( "availableShells" ).type() == QVariant::List )
|
||||
{
|
||||
m_widget->setAutologinDefault( configurationMap.value( "doAutologin" ).toBool() );
|
||||
m_widget->setAvailableShells( configurationMap.value( "availableShells" ).toStringList() );
|
||||
}
|
||||
|
||||
if ( configurationMap.contains( "doReusePassword" ) &&
|
||||
configurationMap.value( "doReusePassword" ).type() == QVariant::Bool )
|
||||
|
||||
if ( configurationMap.contains( "avatarFilePath" ) &&
|
||||
configurationMap.value( "avatarFilePath").type() == QVariant::String )
|
||||
{
|
||||
m_widget->setReusePasswordDefault( configurationMap.value( "doReusePassword" ).toBool() );
|
||||
m_widget->setAvatarFilePath( configurationMap.value( "avatarFilePath" ).toString() );
|
||||
}
|
||||
}
|
||||
|
||||
|
217
src/modules/users/gui/AddUserDialog.cpp
Normal file
217
src/modules/users/gui/AddUserDialog.cpp
Normal file
@ -0,0 +1,217 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2016, Lisa Vitolo <shainer@chakralinux.org>
|
||||
*
|
||||
* Portions from Tribe (Chakra Linux)
|
||||
* by Dario Freddi, Drake Justice and Manuel Tortosa
|
||||
* Copyright (C) 2013 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 <functional>
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QDebug>
|
||||
#include <QDesktopWidget>
|
||||
#include <QFileDialog>
|
||||
#include <QRegExpValidator>
|
||||
|
||||
#include "AddUserDialog.h"
|
||||
#include "utils/CalamaresUtilsGui.h"
|
||||
|
||||
AddUserDialog::AddUserDialog(const QStringList& existingUsers, bool avatar, bool autologin, const QStringList& shells, bool haveRootPassword, QWidget* parent)
|
||||
: QDialog(parent),
|
||||
m_existingUsers(existingUsers)
|
||||
{
|
||||
m_badUsernames
|
||||
<< "root"
|
||||
<< "bin"
|
||||
<< "daemon"
|
||||
<< "mail"
|
||||
<< "ftp"
|
||||
<< "http"
|
||||
<< "nobody"
|
||||
<< "dbus"
|
||||
<< "avahi"
|
||||
<< "usbmux"
|
||||
<< "postgres"
|
||||
<< "quassel"
|
||||
<< "rtkit"
|
||||
<< "git"
|
||||
<< "polkitd"
|
||||
<< "nm-openconnect"
|
||||
<< "kdm"
|
||||
<< "uuidd"
|
||||
<< "ntp"
|
||||
<< "mysql"
|
||||
<< "clamav"
|
||||
<< "postfix"
|
||||
<< "lightdm";
|
||||
|
||||
ui.setupUi(this);
|
||||
|
||||
ui.passLine->setEchoMode(QLineEdit::Password);
|
||||
ui.confirmPassLine->setEchoMode(QLineEdit::Password);
|
||||
ui.labelUsernameError->setFont( QFont("Arial", 10) );
|
||||
|
||||
ui.loginShellSelection->setAutoCompletion(true);
|
||||
ui.loginShellSelection->addItems(shells);
|
||||
|
||||
connect(ui.userNameLine, &QLineEdit::textEdited, this,
|
||||
&AddUserDialog::validateUsername);
|
||||
|
||||
m_passwordsMatch = m_passwordsEmpty = true;
|
||||
connect(ui.passLine, &QLineEdit::textChanged, this, &AddUserDialog::passwordChanged);
|
||||
connect(ui.confirmPassLine, &QLineEdit::textChanged, this, &AddUserDialog::passwordChanged);
|
||||
|
||||
if (!haveRootPassword) {
|
||||
ui.rootUsesUserPwCheckBox->setEnabled(false);
|
||||
}
|
||||
|
||||
if (!autologin) {
|
||||
ui.autoLoginCheckBox->setEnabled(false);
|
||||
}
|
||||
|
||||
if (!avatar) {
|
||||
ui.avatarFileLine->setEnabled(false);
|
||||
ui.selectImageButton->setEnabled(false);
|
||||
}
|
||||
|
||||
connect(ui.selectImageButton, &QPushButton::clicked, this, &AddUserDialog::avatarClicked);
|
||||
|
||||
// Do not enable until valid information have been entered.
|
||||
ui.dialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
connect(ui.dialogButtonBox, &QDialogButtonBox::accepted, this, &AddUserDialog::accept);
|
||||
connect(ui.dialogButtonBox, &QDialogButtonBox::rejected, this, &AddUserDialog::reject);
|
||||
}
|
||||
|
||||
AddUserDialog::~AddUserDialog() {}
|
||||
|
||||
void AddUserDialog::accept() {
|
||||
// Store all the information from the dialog in member variables.
|
||||
login = ui.userNameLine->text();
|
||||
password = ui.passLine->text();
|
||||
shell = ui.loginShellSelection->currentText();
|
||||
fullName = ui.nameLine->text();
|
||||
|
||||
autoLogin = ui.autoLoginCheckBox->isEnabled();
|
||||
useUserPw = ui.rootUsesUserPwCheckBox->isChecked();
|
||||
|
||||
QDialog::accept();
|
||||
}
|
||||
|
||||
void AddUserDialog::validateUsername(const QString& username) {
|
||||
QRegExp rx( USERNAME_RX );
|
||||
QRegExpValidator val( rx );
|
||||
int pos = -1;
|
||||
|
||||
if ( username.isEmpty() )
|
||||
{
|
||||
ui.labelUsernameError->clear();
|
||||
ui.iconUsername->clear();
|
||||
m_validUsername = false;
|
||||
}
|
||||
else if ( username.length() > USERNAME_MAX_LENGTH )
|
||||
{
|
||||
ui.iconUsername->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui.iconUsername->size() ) );
|
||||
ui.labelUsernameError->setText(
|
||||
tr( "Your username is too long." ) );
|
||||
|
||||
m_validUsername = false;
|
||||
}
|
||||
else if ( val.validate( (QString &)username, pos ) == QValidator::Invalid )
|
||||
{
|
||||
ui.iconUsername->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui.iconUsername->size() ) );
|
||||
ui.labelUsernameError->setText(
|
||||
tr( "Only lowercase letters and numbers are allowed." ) );
|
||||
|
||||
m_validUsername = false;
|
||||
}
|
||||
else if ( m_existingUsers.contains(username) ) {
|
||||
ui.iconUsername->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui.iconUsername->size() ) );
|
||||
ui.labelUsernameError->setText(
|
||||
tr( "This username was already created." ) );
|
||||
|
||||
m_validUsername = false;
|
||||
}
|
||||
else if ( m_badUsernames.contains(username) ) {
|
||||
ui.iconUsername->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui.iconUsername->size() ) );
|
||||
ui.labelUsernameError->setText(
|
||||
tr( "Username is already in use in the system." ) );
|
||||
|
||||
m_validUsername = false;
|
||||
}
|
||||
else {
|
||||
ui.iconUsername->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::Yes,
|
||||
CalamaresUtils::Original,
|
||||
ui.iconUsername->size() ) );
|
||||
ui.labelUsernameError->setText("Username valid.");
|
||||
m_validUsername = true;
|
||||
}
|
||||
|
||||
updateValidityUi();
|
||||
}
|
||||
|
||||
void AddUserDialog::passwordChanged() {
|
||||
m_passwordsMatch = (ui.passLine->text() == ui.confirmPassLine->text());
|
||||
m_passwordsEmpty = (ui.passLine->text().length() == 0);
|
||||
|
||||
if (m_passwordsMatch && !m_passwordsEmpty) {
|
||||
ui.confirmPwCheck->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::Yes,
|
||||
CalamaresUtils::Original,
|
||||
ui.confirmPwCheck->size()) );
|
||||
} else {
|
||||
ui.confirmPwCheck->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui.confirmPwCheck->size()) );
|
||||
}
|
||||
|
||||
updateValidityUi();
|
||||
}
|
||||
|
||||
void AddUserDialog::updateValidityUi()
|
||||
{
|
||||
if (m_validUsername && !m_passwordsEmpty && m_passwordsMatch) {
|
||||
ui.dialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(true);
|
||||
} else {
|
||||
ui.dialogButtonBox->button(QDialogButtonBox::Ok)->setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: support getting the avatar from a URL too.
|
||||
void AddUserDialog::avatarClicked()
|
||||
{
|
||||
// Open a file dialog restricted to images.
|
||||
QFileDialog dlg( this );
|
||||
dlg.setNameFilter(tr("Images (*.png *.xpm *.jpg)"));
|
||||
dlg.setViewMode(QFileDialog::Detail);
|
||||
|
||||
// TODO: read this from configuration as we could have a
|
||||
// preferred directory to store avatars in the live installation.
|
||||
dlg.setDirectory("/home");
|
||||
|
||||
if ( dlg.exec() == QDialog::Accepted ) {
|
||||
avatarFile = dlg.selectedFiles().at(0);
|
||||
ui.avatarFileLine->setText(avatarFile);
|
||||
}
|
||||
}
|
82
src/modules/users/gui/AddUserDialog.h
Normal file
82
src/modules/users/gui/AddUserDialog.h
Normal file
@ -0,0 +1,82 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2016, Lisa Vitolo <shainer@chakralinux.org>
|
||||
*
|
||||
* Portions from Tribe (Chakra Linux)
|
||||
* by Dario Freddi, Drake Justice and Manuel Tortosa
|
||||
* Copyright (C) 2013 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/>.
|
||||
*/
|
||||
|
||||
#ifndef ADDUSERDIALOG_H
|
||||
#define ADDUSERDIALOG_H
|
||||
|
||||
#include "ui_adduserdialog.h"
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QValidator>
|
||||
#include <QRegExp>
|
||||
|
||||
class AddUserDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
/*
|
||||
* - existingUsers: username of the users that were already created.
|
||||
* This avoids us creating a second one with the same name.
|
||||
* - avatar: whether we should allow to choose an avatar.
|
||||
* - autologin: whether we should allow the autologin option.
|
||||
* - shells: the available login shells for users.
|
||||
*/
|
||||
AddUserDialog(const QStringList &existingUsers, bool avatar, bool autologin, const QStringList &shells, bool haveRootPassword, QWidget *parent = 0);
|
||||
virtual ~AddUserDialog();
|
||||
|
||||
QString login;
|
||||
QString shell;
|
||||
QString password;
|
||||
QString avatarFile;
|
||||
QString fullName;
|
||||
|
||||
bool autoLogin;
|
||||
bool useUserPw;
|
||||
|
||||
void validateUsername(const QString&);
|
||||
|
||||
public slots:
|
||||
void accept() override;
|
||||
|
||||
signals:
|
||||
void addUserClicked();
|
||||
|
||||
private slots:
|
||||
void avatarClicked();
|
||||
void passwordChanged();
|
||||
void updateValidityUi();
|
||||
|
||||
private:
|
||||
Ui::AddUserDialog ui;
|
||||
|
||||
QStringList m_existingUsers;
|
||||
QStringList m_badUsernames;
|
||||
bool m_validUsername;
|
||||
bool m_passwordsMatch;
|
||||
bool m_passwordsEmpty;
|
||||
|
||||
const QRegExp USERNAME_RX = QRegExp( "^[a-z_][a-z0-9_-]*[$]?$" );
|
||||
const int USERNAME_MAX_LENGTH = 31;
|
||||
};
|
||||
|
||||
#endif /* ADDUSERDIALOG_H */
|
428
src/modules/users/gui/UsersPage.cpp
Normal file
428
src/modules/users/gui/UsersPage.cpp
Normal file
@ -0,0 +1,428 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2014-2015, Teo Mrnjavac <teo@kde.org>
|
||||
*
|
||||
* 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"
|
||||
#include "ui_page_usersetup.h"
|
||||
#include "AddUserDialog.h"
|
||||
#include <jobs/CreateUserJob.h>
|
||||
#include <jobs/SetAvatarJob.h>
|
||||
#include <jobs/SetPasswordJob.h>
|
||||
#include <jobs/SetHostNameJob.h>
|
||||
#include "JobQueue.h"
|
||||
#include "GlobalStorage.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/CalamaresUtilsGui.h"
|
||||
#include "utils/Retranslator.h"
|
||||
|
||||
#include <QBoxLayout>
|
||||
#include <QMessageBox>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QItemSelectionModel>
|
||||
#include <QPointer>
|
||||
#include <QRegExp>
|
||||
#include <QRegExpValidator>
|
||||
|
||||
UsersListModel::~UsersListModel() {
|
||||
qDeleteAll(m_currentUsers);
|
||||
}
|
||||
|
||||
int UsersListModel::rowCount(const QModelIndex &parent) const {
|
||||
return m_currentUsers.size();
|
||||
}
|
||||
|
||||
int UsersListModel::columnCount(const QModelIndex &parent) const {
|
||||
return 4;
|
||||
}
|
||||
|
||||
QVariant UsersListModel::headerData(int section, Qt::Orientation orientation, int role) const {
|
||||
QVariant header;
|
||||
|
||||
if (role == Qt::DisplayRole && orientation == Qt::Horizontal) {
|
||||
switch (section) {
|
||||
case 0:
|
||||
header = QVariant(tr("User name"));
|
||||
break;
|
||||
|
||||
case 1:
|
||||
header = QVariant(tr("Full name"));
|
||||
break;
|
||||
|
||||
case 2:
|
||||
header = QVariant(tr("Shell"));
|
||||
break;
|
||||
|
||||
case 3:
|
||||
header = QVariant(tr("Autologin?"));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return header;
|
||||
}
|
||||
|
||||
QVariant UsersListModel::data(const QModelIndex &index, int role) const {
|
||||
if (role == Qt::DisplayRole) {
|
||||
User* user = m_currentUsers.at( index.row() );
|
||||
QVariant data;
|
||||
|
||||
switch (index.column()) {
|
||||
case 0:
|
||||
data = QVariant( user->toString() );
|
||||
break;
|
||||
|
||||
case 1:
|
||||
data = QVariant( user->fullname );
|
||||
break;
|
||||
|
||||
case 2:
|
||||
data = QVariant( user->shell );
|
||||
break;
|
||||
|
||||
case 3:
|
||||
data = (user->autologin ? "yes" : "no");
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
if (role == Qt::TextAlignmentRole) {
|
||||
return Qt::AlignCenter;
|
||||
}
|
||||
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
Qt::ItemFlags UsersListModel::flags(const QModelIndex & /*index*/) const {
|
||||
return Qt::ItemIsSelectable | Qt::ItemIsEnabled ;
|
||||
}
|
||||
|
||||
void UsersListModel::addUser(User* user) {
|
||||
beginInsertRows( QModelIndex(), 0, 0);
|
||||
m_currentUsers.append(user);
|
||||
endInsertRows();
|
||||
}
|
||||
|
||||
void UsersListModel::deleteUser(int index) {
|
||||
if (index < 0 || index >= m_currentUsers.size()) {
|
||||
return;
|
||||
}
|
||||
|
||||
beginRemoveRows(QModelIndex(), 0, 0);
|
||||
m_currentUsers.removeAt(index);
|
||||
endRemoveRows();
|
||||
}
|
||||
|
||||
QList<User *> UsersListModel::getUsers() const {
|
||||
return m_currentUsers;
|
||||
}
|
||||
|
||||
UsersPage::UsersPage( QWidget* parent )
|
||||
: QWidget( parent )
|
||||
, ui( new Ui::UserCreation )
|
||||
, m_readyHostname( false )
|
||||
, m_readyRootPassword( false )
|
||||
, m_haveRootPassword( true )
|
||||
{
|
||||
ui->setupUi( this );
|
||||
|
||||
connect(ui->addUser, &QPushButton::clicked, this, &UsersPage::addUserClicked);
|
||||
connect(ui->deleteUser, &QPushButton::clicked, this, &UsersPage::deleteUserClicked);
|
||||
|
||||
connect(ui->hostname, &QLineEdit::textChanged, this, &UsersPage::onHostnameTextEdited);
|
||||
|
||||
// The columns will occupy all the space available in the view.
|
||||
ui->usersView->horizontalHeader()->setSectionResizeMode(QHeaderView::Stretch);
|
||||
// You can only select entire rows, not single cells, i.e. you
|
||||
// always select the user as a whole.
|
||||
ui->usersView->setSelectionBehavior(QAbstractItemView::SelectRows);
|
||||
|
||||
ui->usersView->setModel(&m_userModel);
|
||||
ui->usersView->show();
|
||||
CALAMARES_RETRANSLATE( ui->retranslateUi( this ); );
|
||||
}
|
||||
|
||||
UsersPage::~UsersPage()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void
|
||||
UsersPage::addUserClicked() {
|
||||
QStringList existingUsers;
|
||||
bool userHasAutologin = false;
|
||||
|
||||
for (const User* user : m_userModel.getUsers()) {
|
||||
existingUsers.append( user->username );
|
||||
|
||||
if (user->autologin) {
|
||||
userHasAutologin = true;
|
||||
}
|
||||
}
|
||||
|
||||
// Only allow autologin if the module configuration allows it,
|
||||
// and there exists no other users with autologin enabled.
|
||||
bool allowAutologin = m_autologin && !userHasAutologin;
|
||||
|
||||
QPointer<AddUserDialog> dlg = new AddUserDialog(
|
||||
existingUsers, !m_avatarFilePath.isEmpty(), allowAutologin, m_availableShells, m_haveRootPassword, this );
|
||||
|
||||
if ( dlg->exec() == QDialog::Accepted ) {
|
||||
addUser(dlg->login, dlg->fullName, dlg->password, dlg->shell, dlg->avatarFile, dlg->autoLogin);
|
||||
|
||||
if (dlg->useUserPw && m_haveRootPassword) {
|
||||
ui->rootPw->setText(dlg->password);
|
||||
ui->confirmRootPw->setText(dlg->password);
|
||||
}
|
||||
}
|
||||
|
||||
delete dlg;
|
||||
}
|
||||
|
||||
void
|
||||
UsersPage::deleteUserClicked() {
|
||||
QItemSelectionModel* selectionModel = ui->usersView->selectionModel();
|
||||
|
||||
if (!selectionModel->hasSelection()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QModelIndex selectionIndex = selectionModel->currentIndex();
|
||||
if (!selectionIndex.isValid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_userModel.deleteUser(selectionIndex.row());
|
||||
}
|
||||
|
||||
void
|
||||
UsersPage::addUser(const QString &login, const QString &fullName, const QString &password, const QString &shell, const QString& avatarFile, bool autologin) {
|
||||
User* newUser = new User(login, fullName, password, shell, avatarFile, autologin);
|
||||
m_userModel.addUser(newUser);
|
||||
|
||||
ui->hostname->setText( login + "-pc" );
|
||||
|
||||
emit checkReady( isReady() );
|
||||
}
|
||||
|
||||
bool
|
||||
UsersPage::isReady()
|
||||
{
|
||||
return (m_readyHostname &&
|
||||
// At least one user should have been created.
|
||||
m_userModel.getUsers().size() > 0 &&
|
||||
(!m_haveRootPassword || m_readyRootPassword));
|
||||
}
|
||||
|
||||
|
||||
QList< Calamares::job_ptr >
|
||||
UsersPage::createJobs( const QStringList& defaultGroupsList )
|
||||
{
|
||||
QList< Calamares::job_ptr > list;
|
||||
if ( !isReady() )
|
||||
return list;
|
||||
|
||||
for (const User* user : m_userModel.getUsers()) {
|
||||
|
||||
Calamares::Job* j;
|
||||
j = new CreateUserJob( user->username,
|
||||
(!user->fullname.isEmpty()) ? user->fullname : user->username,
|
||||
user->shell,
|
||||
user->autologin,
|
||||
defaultGroupsList );
|
||||
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
|
||||
j = new SetPasswordJob( user->username, user->password );
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
|
||||
j = new SetHostNameJob( ui->hostname->text() );
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
|
||||
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
gs->insert( "hostname", ui->hostname->text() );
|
||||
|
||||
// Given the validation we do, we assume this is always true
|
||||
// for at most one user in the page.
|
||||
if ( user->autologin )
|
||||
gs->insert( "autologinUser", user->username );
|
||||
|
||||
if ( !user->avatarFile.isEmpty() ) {
|
||||
if (m_avatarFilePath.contains("~")) {
|
||||
QString home( "/home/" + user->username);
|
||||
m_avatarFilePath.replace("~", home);
|
||||
}
|
||||
|
||||
j = new SetAvatarJob( user->avatarFile, m_avatarFilePath );
|
||||
list.append( Calamares::job_ptr(j) );
|
||||
}
|
||||
}
|
||||
|
||||
if ( m_haveRootPassword )
|
||||
{
|
||||
Calamares::Job* j = new SetPasswordJob( "root", ui->rootPw->text() );
|
||||
list.append( Calamares::job_ptr( j ) );
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
UsersPage::onActivate()
|
||||
{
|
||||
emit checkReady( isReady() );
|
||||
|
||||
// If there is no user yet, open the dialog as soon as the
|
||||
// page is enabled. This makes it easy for people who want
|
||||
// to create one user.
|
||||
if (m_userModel.rowCount() == 0) {
|
||||
addUserClicked();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
UsersPage::onHostnameTextEdited( const QString& textRef )
|
||||
{
|
||||
validateHostnameText( textRef );
|
||||
}
|
||||
|
||||
void
|
||||
UsersPage::validateHostnameText( const QString& textRef )
|
||||
{
|
||||
QString text = textRef;
|
||||
QRegExp rx( HOSTNAME_RX );
|
||||
QRegExpValidator val( rx );
|
||||
int pos = -1;
|
||||
|
||||
if ( text.isEmpty() )
|
||||
{
|
||||
ui->labelHostnameError->clear();
|
||||
ui->labelHostname->clear();
|
||||
m_readyHostname= false;
|
||||
}
|
||||
else if ( text.length() < HOSTNAME_MIN_LENGTH )
|
||||
{
|
||||
ui->labelHostname->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelHostname->size() ) );
|
||||
ui->labelHostnameError->setText(
|
||||
tr( "Your hostname is too short." ) );
|
||||
|
||||
m_readyHostname = false;
|
||||
|
||||
}
|
||||
else if ( text.length() > HOSTNAME_MAX_LENGTH )
|
||||
{
|
||||
ui->labelHostname->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelHostname->size() ) );
|
||||
ui->labelHostnameError->setText(
|
||||
tr( "Your hostname is too long." ) );
|
||||
|
||||
m_readyHostname = false;
|
||||
|
||||
}
|
||||
else if ( val.validate( text, pos ) == QValidator::Invalid )
|
||||
{
|
||||
ui->labelHostname->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelHostname->size() ) );
|
||||
ui->labelHostnameError->setText(
|
||||
tr( "Your hostname contains invalid characters. Only letters, numbers and dashes are allowed." ) );
|
||||
|
||||
m_readyHostname = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labelHostname->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::Yes,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelHostname->size() ) );
|
||||
ui->labelHostnameError->clear();
|
||||
m_readyHostname = true;
|
||||
}
|
||||
|
||||
emit checkReady( isReady() );
|
||||
}
|
||||
|
||||
void
|
||||
UsersPage::onRootPasswordTextChanged( const QString& textRef )
|
||||
{
|
||||
QString pw1 = ui->rootPw->text();
|
||||
QString pw2 = ui->confirmRootPw->text();
|
||||
|
||||
if ( pw1.isEmpty() && pw2.isEmpty() )
|
||||
{
|
||||
ui->labelRootPwError->clear();
|
||||
ui->labelRootPwIcon->clear();
|
||||
m_readyRootPassword = false;
|
||||
}
|
||||
else if ( pw1 != pw2 )
|
||||
{
|
||||
ui->labelRootPwError->setText( tr( "Your passwords do not match!" ) );
|
||||
ui->labelRootPwIcon->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::No,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelRootPwIcon->size() ) );
|
||||
m_readyRootPassword = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
ui->labelRootPwError->clear();
|
||||
ui->labelRootPwIcon->setPixmap( CalamaresUtils::defaultPixmap( CalamaresUtils::Yes,
|
||||
CalamaresUtils::Original,
|
||||
ui->labelRootPwIcon->size() ) );
|
||||
m_readyRootPassword = true;
|
||||
}
|
||||
|
||||
emit checkReady( isReady() );
|
||||
}
|
||||
|
||||
void UsersPage::setAutologin(bool autologin) {
|
||||
m_autologin = autologin;
|
||||
}
|
||||
|
||||
void UsersPage::setHaveRootPassword(bool haveRootPassword) {
|
||||
m_haveRootPassword = haveRootPassword;
|
||||
|
||||
if (m_haveRootPassword) {
|
||||
ui->rootPw->show();
|
||||
ui->confirmRootPw->show();
|
||||
ui->labelRootPw->show();
|
||||
ui->labelConfirmRootPw->show();
|
||||
|
||||
connect(ui->rootPw, &QLineEdit::textChanged, this, &UsersPage::onRootPasswordTextChanged);
|
||||
connect(ui->confirmRootPw, &QLineEdit::textChanged, this, &UsersPage::onRootPasswordTextChanged);
|
||||
} else {
|
||||
ui->rootPw->hide();
|
||||
ui->confirmRootPw->hide();
|
||||
ui->labelRootPw->hide();
|
||||
ui->labelConfirmRootPw->hide();
|
||||
}
|
||||
}
|
||||
|
||||
void UsersPage::setAvatarFilePath(const QString &path) {
|
||||
m_avatarFilePath = path;
|
||||
}
|
||||
|
||||
void UsersPage::setAvailableShells(const QStringList &shells) {
|
||||
m_availableShells = shells;
|
||||
}
|
139
src/modules/users/gui/UsersPage.h
Normal file
139
src/modules/users/gui/UsersPage.h
Normal file
@ -0,0 +1,139 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2014-2015, Teo Mrnjavac <teo@kde.org>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef USERSPAGE_H
|
||||
#define USERSPAGE_H
|
||||
|
||||
#include "Typedefs.h"
|
||||
|
||||
#include <QAbstractListModel>
|
||||
#include <QtGlobal>
|
||||
#include <QItemSelection>
|
||||
#include <QVariant>
|
||||
#include <QWidget>
|
||||
|
||||
namespace Ui {
|
||||
class UserCreation;
|
||||
}
|
||||
|
||||
/*
|
||||
* Represents the properties of a user in the system.
|
||||
*
|
||||
* The fullname and avatar file can be empty and they will be ignored.
|
||||
* The password can technically be empty too, but that is of course
|
||||
* not recommended in general.
|
||||
*/
|
||||
struct User {
|
||||
User(const QString& username, const QString& fullname, const QString& password, const QString& shell, const QString& avatarFile, bool autologin)
|
||||
: username(username), fullname(fullname), password(password), shell(shell), avatarFile(avatarFile), autologin(autologin) {}
|
||||
|
||||
QString toString() const {
|
||||
return username;
|
||||
}
|
||||
|
||||
QString username;
|
||||
QString fullname;
|
||||
QString password;
|
||||
QString shell;
|
||||
QString avatarFile;
|
||||
bool autologin;
|
||||
};
|
||||
|
||||
/*
|
||||
* Model to contain the users created during the installation
|
||||
* process. This is associated to a QTableView in the main UI.
|
||||
*
|
||||
* Each row is a user and each column a property of the user.
|
||||
*/
|
||||
class UsersListModel : public QAbstractTableModel {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
virtual ~UsersListModel();
|
||||
|
||||
int rowCount(const QModelIndex &parent = QModelIndex()) const Q_DECL_OVERRIDE;
|
||||
int columnCount(const QModelIndex &parent) const Q_DECL_OVERRIDE;
|
||||
QVariant data(const QModelIndex &index, int role) const Q_DECL_OVERRIDE;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role) const Q_DECL_OVERRIDE;
|
||||
Qt::ItemFlags flags(const QModelIndex & /*index*/) const Q_DECL_OVERRIDE;
|
||||
|
||||
void addUser(User *user);
|
||||
void deleteUser(int index);
|
||||
QList<User *> getUsers() const;
|
||||
|
||||
private:
|
||||
QList<User *> m_currentUsers;
|
||||
};
|
||||
|
||||
class UsersPage : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit UsersPage( QWidget* parent = nullptr );
|
||||
virtual ~UsersPage();
|
||||
|
||||
bool isReady();
|
||||
|
||||
QList< Calamares::job_ptr > createJobs( const QStringList& defaultGroupsList );
|
||||
|
||||
void onActivate();
|
||||
|
||||
// Setters for properties of this page, usually from configuration.
|
||||
void setAutologin( bool autologin );
|
||||
void setAvatarFilePath( const QString& path );
|
||||
void setAvailableShells( const QStringList& shells);
|
||||
void setHaveRootPassword(bool);
|
||||
|
||||
protected slots:
|
||||
void onHostnameTextEdited( const QString& );
|
||||
void validateHostnameText( const QString& );
|
||||
void onRootPasswordTextChanged( const QString& );
|
||||
|
||||
void addUserClicked();
|
||||
void deleteUserClicked();
|
||||
|
||||
signals:
|
||||
void checkReady( bool );
|
||||
|
||||
private:
|
||||
void addUser(const QString& login, const QString& fullName, const QString& password, const QString& shell, const QString& avatarFile, bool autologin);
|
||||
|
||||
Ui::UserCreation* ui;
|
||||
UsersListModel m_userModel;
|
||||
|
||||
// Hostname validation.
|
||||
const QRegExp HOSTNAME_RX = QRegExp( "^[a-zA-Z0-9][-a-zA-Z0-9_]*$" );
|
||||
const int HOSTNAME_MIN_LENGTH = 2;
|
||||
const int HOSTNAME_MAX_LENGTH = 24;
|
||||
|
||||
// Are the following fields valid with their current value?
|
||||
bool m_readyHostname;
|
||||
bool m_readyRootPassword;
|
||||
|
||||
bool m_autologin;
|
||||
bool m_haveRootPassword;
|
||||
QString m_avatarFilePath;
|
||||
QStringList m_availableShells;
|
||||
};
|
||||
|
||||
#endif // USERSPAGE_H
|
382
src/modules/users/gui/adduserdialog.ui
Normal file
382
src/modules/users/gui/adduserdialog.ui
Normal file
@ -0,0 +1,382 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AddUserDialog</class>
|
||||
<widget class="QDialog" name="AddUserDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>712</width>
|
||||
<height>383</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="spacing">
|
||||
<number>3</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>4</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="title">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="spacing">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>2</number>
|
||||
</property>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="2" rowspan="3">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Password: </string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="3" rowspan="4">
|
||||
<spacer name="horizontalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>13</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="text">
|
||||
<string>Confirm Password:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0" rowspan="4">
|
||||
<layout class="QVBoxLayout" name="userNameLayout">
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="topMargin">
|
||||
<number>15</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>5</number>
|
||||
</property>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>45</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>User name:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="userNameLine">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string><html><head/><body><p>The user name may consist of a lowercase character or &quot;_&quot;, followed by up to 31 lowercase characters, digits or &quot;_&quot; and &quot;-&quot;.</p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="iconUsername">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelUsernameError">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item row="3" column="4" colspan="2">
|
||||
<widget class="QLineEdit" name="confirmPassLine">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="4" rowspan="3" colspan="2">
|
||||
<widget class="QLineEdit" name="passLine">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>150</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="6" rowspan="4" colspan="2">
|
||||
<widget class="QLabel" name="confirmPwCheck">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>32</width>
|
||||
<height>32</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1" rowspan="4">
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>5</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QWidget" name="extWidget" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="rootUsesUserPwCheckBox">
|
||||
<property name="text">
|
||||
<string>Select to use the above password
|
||||
as the Administrator password</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4" colspan="3">
|
||||
<widget class="QComboBox" name="loginShellSelection"/>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Advanced settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="text">
|
||||
<string> Full name: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="autoLoginCheckBox">
|
||||
<property name="text">
|
||||
<string>Login Automatically</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0" colspan="7">
|
||||
<widget class="QWidget" name="avatarSelectionWidget" native="true">
|
||||
<layout class="QGridLayout" name="gridLayout_4">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="font">
|
||||
<font>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Avatar selection</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLineEdit" name="avatarFileLine"/>
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<widget class="QPushButton" name="selectImageButton">
|
||||
<property name="text">
|
||||
<string>Image file...</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="text">
|
||||
<string>Login shell: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QLineEdit" name="nameLine">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>180</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QDialogButtonBox" name="dialogButtonBox">
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>5</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<tabstops>
|
||||
<tabstop>userNameLine</tabstop>
|
||||
<tabstop>passLine</tabstop>
|
||||
<tabstop>confirmPassLine</tabstop>
|
||||
</tabstops>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
277
src/modules/users/gui/page_usersetup.ui
Normal file
277
src/modules/users/gui/page_usersetup.ui
Normal file
@ -0,0 +1,277 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>UserCreation</class>
|
||||
<widget class="QWidget" name="UserCreation">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>694</width>
|
||||
<height>474</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string/>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Enter at least one login name and password.</string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addUser">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>48</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="toolTip">
|
||||
<string>Add another user account.</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Create user</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="deleteUser">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="baseSize">
|
||||
<size>
|
||||
<width>80</width>
|
||||
<height>48</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Delete user</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QScrollArea" name="scrollArea">
|
||||
<property name="widgetResizable">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<widget class="QTableView" name="usersView">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>678</width>
|
||||
<height>248</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Minimum" vsizetype="Minimum">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetNoConstraint</enum>
|
||||
</property>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="Line" name="line_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QGridLayout" name="_23">
|
||||
<property name="verticalSpacing">
|
||||
<number>11</number>
|
||||
</property>
|
||||
<item row="2" column="4">
|
||||
<widget class="QLabel" name="labelConfirmRootPw">
|
||||
<property name="text">
|
||||
<string>Confirm: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="3">
|
||||
<widget class="QLineEdit" name="hostname">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>250</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>700</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="5">
|
||||
<widget class="QLineEdit" name="confirmRootPw">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="2">
|
||||
<widget class="QLabel" name="labelRootPw">
|
||||
<property name="text">
|
||||
<string>Root password: </string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="2">
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>120</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Hostname:</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="3">
|
||||
<widget class="QLineEdit" name="rootPw">
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="5">
|
||||
<widget class="QLabel" name="labelHostnameError">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>230</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>230</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="4">
|
||||
<widget class="QLabel" name="labelHostname">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="2">
|
||||
<widget class="QLabel" name="labelRootPwIcon">
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>50</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="3">
|
||||
<widget class="QLabel" name="labelRootPwError">
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -16,7 +16,7 @@
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <CreateUserJob.h>
|
||||
#include <jobs/CreateUserJob.h>
|
||||
|
||||
#include "JobQueue.h"
|
||||
#include "GlobalStorage.h"
|
||||
@ -33,11 +33,13 @@
|
||||
|
||||
CreateUserJob::CreateUserJob( const QString& userName,
|
||||
const QString& fullName,
|
||||
const QString& shell,
|
||||
bool autologin,
|
||||
const QStringList& defaultGroups )
|
||||
: Calamares::Job()
|
||||
, m_userName( userName )
|
||||
, m_fullName( fullName )
|
||||
, m_shell( shell )
|
||||
, m_autologin( autologin )
|
||||
, m_defaultGroups( defaultGroups )
|
||||
{
|
||||
@ -151,7 +153,7 @@ CreateUserJob::exec()
|
||||
targetEnvCall( { "useradd",
|
||||
"-m",
|
||||
"-s",
|
||||
"/bin/bash",
|
||||
m_shell,
|
||||
"-U",
|
||||
"-c",
|
||||
m_fullName,
|
182
src/modules/users/jobs/CreateUserJob.cpp.orig
Normal file
182
src/modules/users/jobs/CreateUserJob.cpp.orig
Normal file
@ -0,0 +1,182 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2014-2016, Teo Mrnjavac <teo@kde.org>
|
||||
*
|
||||
* 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 <jobs/CreateUserJob.h>
|
||||
|
||||
#include "JobQueue.h"
|
||||
#include "GlobalStorage.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "utils/CalamaresUtilsSystem.h"
|
||||
|
||||
#include <QDateTime>
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QProcess>
|
||||
#include <QTextStream>
|
||||
|
||||
|
||||
CreateUserJob::CreateUserJob( const QString& userName,
|
||||
const QString& fullName,
|
||||
const QString& shell,
|
||||
bool autologin,
|
||||
const QStringList& defaultGroups )
|
||||
: Calamares::Job()
|
||||
, m_userName( userName )
|
||||
, m_fullName( fullName )
|
||||
, m_shell( shell )
|
||||
, m_autologin( autologin )
|
||||
, m_defaultGroups( defaultGroups )
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
CreateUserJob::prettyName() const
|
||||
{
|
||||
return tr( "Create user %1" ).arg( m_userName );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
CreateUserJob::prettyDescription() const
|
||||
{
|
||||
return tr( "Create user <strong>%1</strong>." ).arg( m_userName );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
CreateUserJob::prettyStatusMessage() const
|
||||
{
|
||||
return tr( "Creating user %1." ).arg( m_userName );
|
||||
}
|
||||
|
||||
|
||||
Calamares::JobResult
|
||||
CreateUserJob::exec()
|
||||
{
|
||||
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
QDir destDir( gs->value( "rootMountPoint" ).toString() );
|
||||
|
||||
if ( gs->contains( "sudoersGroup" ) &&
|
||||
!gs->value( "sudoersGroup" ).toString().isEmpty() )
|
||||
{
|
||||
QFileInfo sudoersFi( destDir.absoluteFilePath( "etc/sudoers.d/10-installer" ) );
|
||||
|
||||
if ( !sudoersFi.absoluteDir().exists() )
|
||||
return Calamares::JobResult::error( tr( "Sudoers dir is not writable." ) );
|
||||
|
||||
QFile sudoersFile( sudoersFi.absoluteFilePath() );
|
||||
if (!sudoersFile.open( QIODevice::WriteOnly | QIODevice::Text ) )
|
||||
return Calamares::JobResult::error( tr( "Cannot create sudoers file for writing." ) );
|
||||
|
||||
QString sudoersGroup = gs->value( "sudoersGroup" ).toString();
|
||||
|
||||
QTextStream sudoersOut( &sudoersFile );
|
||||
sudoersOut << QString( "%%1 ALL=(ALL) ALL\n" ).arg( sudoersGroup );
|
||||
|
||||
if ( QProcess::execute( "chmod", { "440", sudoersFi.absoluteFilePath() } ) )
|
||||
return Calamares::JobResult::error( tr( "Cannot chmod sudoers file." ) );
|
||||
}
|
||||
|
||||
QFileInfo groupsFi( destDir.absoluteFilePath( "etc/group" ) );
|
||||
QFile groupsFile( groupsFi.absoluteFilePath() );
|
||||
if ( !groupsFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
||||
return Calamares::JobResult::error( tr( "Cannot open groups file for reading." ) );
|
||||
QString groupsData = QString::fromLocal8Bit( groupsFile.readAll() );
|
||||
QStringList groupsLines = groupsData.split( '\n' );
|
||||
for ( QStringList::iterator it = groupsLines.begin();
|
||||
it != groupsLines.end(); ++it )
|
||||
{
|
||||
int indexOfFirstToDrop = it->indexOf( ':' );
|
||||
it->truncate( indexOfFirstToDrop );
|
||||
}
|
||||
|
||||
foreach ( const QString& group, m_defaultGroups )
|
||||
if ( !groupsLines.contains( group ) )
|
||||
CalamaresUtils::System::instance()->
|
||||
targetEnvCall( { "groupadd", group } );
|
||||
|
||||
QString defaultGroups = m_defaultGroups.join( ',' );
|
||||
if ( m_autologin )
|
||||
{
|
||||
QString autologinGroup;
|
||||
if ( gs->contains( "autologinGroup" ) &&
|
||||
!gs->value( "autologinGroup" ).toString().isEmpty() )
|
||||
autologinGroup = gs->value( "autologinGroup" ).toString();
|
||||
else
|
||||
autologinGroup = QStringLiteral( "autologin" );
|
||||
|
||||
CalamaresUtils::System::instance()->targetEnvCall( { "groupadd", autologinGroup } );
|
||||
defaultGroups.append( QString( ",%1" ).arg( autologinGroup ) );
|
||||
}
|
||||
|
||||
// If we're looking to reuse the contents of an existing /home
|
||||
if ( gs->value( "reuseHome" ).toBool() )
|
||||
{
|
||||
QString shellFriendlyHome = "/home/" + m_userName;
|
||||
QDir existingHome( destDir.absolutePath() + shellFriendlyHome );
|
||||
if ( existingHome.exists() )
|
||||
{
|
||||
QString backupDirName = "dotfiles_backup_" +
|
||||
QDateTime::currentDateTime()
|
||||
.toString( "yyyy-MM-dd_HH-mm-ss" );
|
||||
existingHome.mkdir( backupDirName );
|
||||
|
||||
CalamaresUtils::System::instance()->
|
||||
targetEnvCall( { "sh",
|
||||
"-c",
|
||||
"mv -f " +
|
||||
shellFriendlyHome + "/.* " +
|
||||
shellFriendlyHome + "/" +
|
||||
backupDirName
|
||||
} );
|
||||
}
|
||||
}
|
||||
|
||||
int ec = CalamaresUtils::System::instance()->
|
||||
targetEnvCall( { "useradd",
|
||||
"-m",
|
||||
"-s",
|
||||
m_shell,
|
||||
"-U",
|
||||
"-G",
|
||||
defaultGroups,
|
||||
"-c",
|
||||
m_fullName,
|
||||
m_userName } );
|
||||
if ( ec )
|
||||
return Calamares::JobResult::error( tr( "Cannot create user %1." )
|
||||
.arg( m_userName ),
|
||||
tr( "useradd terminated with error code %1." )
|
||||
.arg( ec ) );
|
||||
|
||||
ec = CalamaresUtils::System::instance()->
|
||||
targetEnvCall( { "chown",
|
||||
"-R",
|
||||
QString( "%1:%2" ).arg( m_userName )
|
||||
.arg( m_userName ),
|
||||
QString( "/home/%1" ).arg( m_userName ) } );
|
||||
if ( ec )
|
||||
return Calamares::JobResult::error( tr( "Cannot set home directory ownership for user %1." )
|
||||
.arg( m_userName ),
|
||||
tr( "chown terminated with error code %1." )
|
||||
.arg( ec ) );
|
||||
|
||||
return Calamares::JobResult::ok();
|
||||
}
|
@ -29,6 +29,7 @@ class CreateUserJob : public Calamares::Job
|
||||
public:
|
||||
CreateUserJob( const QString& userName,
|
||||
const QString& fullName,
|
||||
const QString& shell,
|
||||
bool autologin,
|
||||
const QStringList& defaultGroups );
|
||||
QString prettyName() const override;
|
||||
@ -39,6 +40,7 @@ public:
|
||||
private:
|
||||
QString m_userName;
|
||||
QString m_fullName;
|
||||
QString m_shell;
|
||||
bool m_autologin;
|
||||
QStringList m_defaultGroups;
|
||||
};
|
85
src/modules/users/jobs/SetAvatarJob.cpp
Normal file
85
src/modules/users/jobs/SetAvatarJob.cpp
Normal file
@ -0,0 +1,85 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2016, Lisa Vitolo <shainer@chakralinux.org>
|
||||
*
|
||||
* 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 <jobs/SetAvatarJob.h>
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "utils/Logger.h"
|
||||
#include "JobQueue.h"
|
||||
|
||||
#include <QFile>
|
||||
#include <QDir>
|
||||
|
||||
SetAvatarJob::SetAvatarJob(const QString &avatarFile, const QString &destPath)
|
||||
: Calamares::Job()
|
||||
, m_avatarFile(avatarFile)
|
||||
, m_destPath(destPath)
|
||||
{
|
||||
}
|
||||
|
||||
QString SetAvatarJob::prettyName() const
|
||||
{
|
||||
return tr( "Set avatar %1" ).arg( m_avatarFile );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
SetAvatarJob::prettyDescription() const
|
||||
{
|
||||
return tr( "Set avatar from <strong>%1</strong>." ).arg( m_avatarFile );
|
||||
}
|
||||
|
||||
|
||||
QString
|
||||
SetAvatarJob::prettyStatusMessage() const
|
||||
{
|
||||
return tr( "Setting avatar from %1." ).arg( m_avatarFile );
|
||||
}
|
||||
|
||||
Calamares::JobResult SetAvatarJob::exec()
|
||||
{
|
||||
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||
|
||||
if ( !gs || !gs->contains( "rootMountPoint" ) )
|
||||
{
|
||||
cLog() << "No rootMountPoint in global storage";
|
||||
return Calamares::JobResult::error( tr( "Internal Error" ) );
|
||||
}
|
||||
|
||||
QString destDir = gs->value( "rootMountPoint" ).toString();
|
||||
if ( !QDir( destDir ).exists() )
|
||||
{
|
||||
cLog() << "rootMountPoint points to a dir which does not exist";
|
||||
return Calamares::JobResult::error( tr( "Internal Error" ) );
|
||||
}
|
||||
|
||||
QString destination( destDir + m_destPath );
|
||||
QFile avatarFile( m_avatarFile );
|
||||
|
||||
if (!avatarFile.exists()) {
|
||||
cLog() << "Avatar file does not exist";
|
||||
return Calamares::JobResult::error( tr("Avatar file does not exist") );
|
||||
}
|
||||
|
||||
if (!avatarFile.copy(destination)) {
|
||||
cLog() << "Error copying:" << avatarFile.errorString();
|
||||
return Calamares::JobResult::error( tr("Error copying") );
|
||||
}
|
||||
|
||||
return Calamares::JobResult::ok();
|
||||
}
|
39
src/modules/users/jobs/SetAvatarJob.h
Normal file
39
src/modules/users/jobs/SetAvatarJob.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* === This file is part of Calamares - <http://github.com/calamares> ===
|
||||
*
|
||||
* Copyright 2016, Lisa Vitolo <shainer@chakralinux.org>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
#ifndef SETAVATARJOB_CPP_H
|
||||
#define SETAVATARJOB_CPP_H
|
||||
|
||||
#include <Job.h>
|
||||
|
||||
class SetAvatarJob : public Calamares::Job
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SetAvatarJob( const QString& avatarFile, const QString& destPath );
|
||||
QString prettyName() const override;
|
||||
QString prettyDescription() const override;
|
||||
QString prettyStatusMessage() const override;
|
||||
Calamares::JobResult exec() override;
|
||||
private:
|
||||
const QString m_avatarFile;
|
||||
const QString m_destPath;
|
||||
};
|
||||
|
||||
|
||||
#endif // SETAVATARJOB_CPP_H
|
@ -17,7 +17,7 @@
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "SetHostNameJob.h"
|
||||
#include <jobs/SetHostNameJob.h>
|
||||
|
||||
#include "GlobalStorage.h"
|
||||
#include "utils/Logger.h"
|
@ -16,7 +16,7 @@
|
||||
* along with Calamares. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <SetPasswordJob.h>
|
||||
#include <jobs/SetPasswordJob.h>
|
||||
|
||||
#include "JobQueue.h"
|
||||
#include "GlobalStorage.h"
|
@ -1,609 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>Page_UserSetup</class>
|
||||
<widget class="QWidget" name="Page_UserSetup">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>862</width>
|
||||
<height>683</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_12">
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>6</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelWhatIsYourName">
|
||||
<property name="text">
|
||||
<string>What is your name?</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textBoxFullName">
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelFullName">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string notr="true"/>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelFullNameError">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_2">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>6</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="username_label_2">
|
||||
<property name="text">
|
||||
<string>What name do you want to use to log in?</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textBoxUsername">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelUsername">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelUsernameError">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="username_extra_label_2">
|
||||
<property name="styleSheet">
|
||||
<string>font-weight: normal</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><small>If more than one person will use this computer, you can set up multiple accounts after installation.</small></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_4">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>6</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="hostname_label_2">
|
||||
<property name="text">
|
||||
<string>What is the name of this computer?</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_4">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textBoxHostname">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelHostname">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelHostnameError">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="hostname_extra_label_2">
|
||||
<property name="styleSheet">
|
||||
<string>font-weight: normal</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><small>This name will be used if you make the computer visible to others on a network.</small></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_3">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>6</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="password_label_2">
|
||||
<property name="text">
|
||||
<string>Choose a password to keep your account safe.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textBoxUserPassword">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textBoxUserVerifiedPassword">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelUserPassword">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelUserPasswordError">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="password_extra_label_3">
|
||||
<property name="styleSheet">
|
||||
<string>font-weight: normal</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><small>Enter the same password twice, so that it can be checked for typing errors. A good password will contain a mixture of letters, numbers and punctuation, should be at least eight characters long, and should be changed at regular intervals.</small></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxAutoLogin">
|
||||
<property name="text">
|
||||
<string>Log in automatically without asking for the password.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="checkBoxReusePassword">
|
||||
<property name="text">
|
||||
<string>Use the same password for the administrator account.</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_6">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Fixed</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>6</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelChooseRootPassword">
|
||||
<property name="text">
|
||||
<string>Choose a password for the administrator account.</string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_5">
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textBoxRootPassword">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLineEdit" name="textBoxVerifiedRootPassword">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="echoMode">
|
||||
<enum>QLineEdit::Password</enum>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelRootPassword">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>24</width>
|
||||
<height>24</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelRootPasswordError">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>100</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="labelExtraRootPassword">
|
||||
<property name="styleSheet">
|
||||
<string>font-weight: normal</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><small>Enter the same password twice, so that it can be checked for typing errors.</small></string>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer_7">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>1</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
@ -8,7 +8,7 @@ defaultGroups:
|
||||
- wheel
|
||||
- audio
|
||||
autologinGroup: autologin
|
||||
doAutologin: true
|
||||
doAutologin: false
|
||||
sudoersGroup: wheel
|
||||
setRootPassword: true
|
||||
doReusePassword: true
|
||||
setRootPassword: false
|
||||
availableShells: /bin/bash, /bin/zsh
|
||||
|
@ -2,5 +2,7 @@
|
||||
<qresource prefix="/">
|
||||
<file>images/invalid.png</file>
|
||||
<file>images/valid.png</file>
|
||||
<file>images/arrow-down.png</file>
|
||||
<file>images/arrow-up.png</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
Loading…
Reference in New Issue
Block a user