From c6771c06689dfb49b8050e99b9c3572c27a8cb3e Mon Sep 17 00:00:00 2001 From: "A. Wilcox" Date: Fri, 29 Nov 2019 17:18:58 -0600 Subject: Qt UI: Add Accounts page, still in progress --- ui/qt5/CMakeLists.txt | 2 + ui/qt5/accountpage.cc | 53 ++++++++++++++++ ui/qt5/accountpage.hh | 30 ++++++++++ ui/qt5/horizonwizard.cc | 2 + ui/qt5/useraccountwidget.cc | 143 ++++++++++++++++++++++++++++++++++++++++++++ ui/qt5/useraccountwidget.hh | 57 ++++++++++++++++++ 6 files changed, 287 insertions(+) create mode 100644 ui/qt5/accountpage.cc create mode 100644 ui/qt5/accountpage.hh create mode 100644 ui/qt5/useraccountwidget.cc create mode 100644 ui/qt5/useraccountwidget.hh diff --git a/ui/qt5/CMakeLists.txt b/ui/qt5/CMakeLists.txt index 720fc4f..ab626b4 100644 --- a/ui/qt5/CMakeLists.txt +++ b/ui/qt5/CMakeLists.txt @@ -7,6 +7,7 @@ set(UI_SOURCES horizonhelpwindow.cc main.cc ${CMAKE_SOURCE_DIR}/3rdparty/Section.cpp + useraccountwidget.cc intropage.cc inputpage.cc @@ -19,6 +20,7 @@ set(UI_SOURCES pkgsimple.cc bootpage.cc rootpwpage.cc + accountpage.cc horizon.qrc) diff --git a/ui/qt5/accountpage.cc b/ui/qt5/accountpage.cc new file mode 100644 index 0000000..0541b60 --- /dev/null +++ b/ui/qt5/accountpage.cc @@ -0,0 +1,53 @@ +/* + * accountpage.cc - Implementation of the UI.Accounts.UserAcct page + * horizon-qt5, the Qt 5 user interface for + * Project Horizon + * + * Copyright (c) 2019 Adélie Linux and contributors. All rights reserved. + * This code is licensed under the AGPL 3.0 license, as noted in the + * LICENSE-code file in the root directory of this repository. + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +#include "accountpage.hh" + +#include +#include +#include + +AccountPage::AccountPage(QWidget *parent) : HorizonWizardPage(parent) { + setTitle(tr("User Accounts")); + loadWatermark("acct"); + QLabel *descLabel = new QLabel(tr( + "Enter the details of up to four people who will use this computer. " + "You can add more later with the User Manager. " + "For more information, consult the User's Handbook.")); + descLabel->setWordWrap(true); + + QVBoxLayout *layout = new QVBoxLayout; + layout->addWidget(descLabel); + + accountWidgets[0] = new UserAccountWidget; + accountWidgets[0]->setAdmin(true); + accountWidgets[1] = new UserAccountWidget; + accountWidgets[2] = new UserAccountWidget; + accountWidgets[3] = new UserAccountWidget; + + for(auto &widget : accountWidgets) { + connect(widget, &UserAccountWidget::validityChanged, + this, &AccountPage::completeChanged); + layout->addStretch(); + layout->addWidget(widget); + } + + setLayout(layout); +} + +bool AccountPage::isComplete() const { + return std::all_of(accountWidgets.begin(), accountWidgets.end(), + [](UserAccountWidget *widget) { + if(widget == nullptr) return true; + return widget->isValid(); + }); +} diff --git a/ui/qt5/accountpage.hh b/ui/qt5/accountpage.hh new file mode 100644 index 0000000..cd7783a --- /dev/null +++ b/ui/qt5/accountpage.hh @@ -0,0 +1,30 @@ +/* + * accountpage.hh - Definition of the UI.Accounts.UserAcct page + * horizon-qt5, the Qt 5 user interface for + * Project Horizon + * + * Copyright (c) 2019 Adélie Linux and contributors. All rights reserved. + * This code is licensed under the AGPL 3.0 license, as noted in the + * LICENSE-code file in the root directory of this repository. + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +#ifndef ACCOUNTPAGE_HH +#define ACCOUNTPAGE_HH + +#include "horizonwizardpage.hh" +#include "useraccountwidget.hh" + +#include + +class AccountPage : public HorizonWizardPage { +public: + AccountPage(QWidget *parent = nullptr); + + bool isComplete() const; +private: + std::array accountWidgets; +}; + +#endif /* !ACCOUNTPAGE_HH */ diff --git a/ui/qt5/horizonwizard.cc b/ui/qt5/horizonwizard.cc index 3002c19..cf2d5c9 100644 --- a/ui/qt5/horizonwizard.cc +++ b/ui/qt5/horizonwizard.cc @@ -43,6 +43,7 @@ extern "C" { #include "pkgsimple.hh" #include "bootpage.hh" #include "rootpwpage.hh" +#include "accountpage.hh" static std::map help_id_map = { {HorizonWizard::Page_Intro, "intro"}, @@ -197,6 +198,7 @@ HorizonWizard::HorizonWizard(QWidget *parent) : QWizard(parent) { setPage(Page_PkgSimple, new PkgSimplePage); setPage(Page_Boot, new BootPage); setPage(Page_Root, new RootPassphrasePage); + setPage(Page_Accounts, new AccountPage); QObject::connect(this, &QWizard::helpRequested, [=](void) { if(help_id_map.find(currentId()) == help_id_map.end()) { diff --git a/ui/qt5/useraccountwidget.cc b/ui/qt5/useraccountwidget.cc new file mode 100644 index 0000000..8caf6fb --- /dev/null +++ b/ui/qt5/useraccountwidget.cc @@ -0,0 +1,143 @@ +/* + * useraccountwidget.cc - Implementation of a widget for managing user accounts + * horizon-qt5, the Qt 5 user interface for + * Project Horizon + * + * Copyright (c) 2019 Adélie Linux and contributors. All rights reserved. + * This code is licensed under the AGPL 3.0 license, as noted in the + * LICENSE-code file in the root directory of this repository. + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +#include "useraccountwidget.hh" + +#include +#include + +UserAccountWidget::UserAccountWidget(QWidget *parent) + : QWidget(parent), acctEverTouched(false) { + QHBoxLayout *nameLayout = new QHBoxLayout; + + personalName = new QLineEdit; + QFont personalFont = personalName->font(); + personalFont.setPointSize(personalFont.pointSize() + 2); + personalName->setFont(personalFont); + personalName->setPlaceholderText(tr("Personal Name")); + personalName->setToolTip(tr("Used to address this user")); + personalName->setWhatsThis(tr("This name will be used to address this user. It may be their real name, or a nickname.")); + nameLayout->addWidget(personalName, 20); + + accountName = new QLineEdit; + accountName->setMaxLength(32); + accountName->setPlaceholderText(tr("Username")); + accountName->setToolTip(tr("Used to identify this user; letters and numbers only")); + accountName->setWhatsThis(tr("This name will be used to identify this user to the computer. It must contain only letters and numbers.")); + nameLayout->addWidget(accountName, 15); + + QHBoxLayout *passAdminLayout = new QHBoxLayout; + passphrase = new QLineEdit; + passphrase->setEchoMode(QLineEdit::Password); + passphrase->setPlaceholderText(tr("Passphrase")); + passphrase->setToolTip(tr("This user's passphrase")); + passphrase->setWhatsThis(tr("The passphrase will be used to log in to the computer.")); + passAdminLayout->addWidget(passphrase); + + adminTick = new QCheckBox(tr("Admin")); + adminTick->setToolTip(tr("Allows this user to perform administrative tasks")); + adminTick->setWhatsThis(tr("If ticked, allows this user to perform administrative tasks on the computer.")); + passAdminLayout->addWidget(adminTick); + + QVBoxLayout *detailLayout = new QVBoxLayout; + detailLayout->addLayout(nameLayout); + detailLayout->addLayout(passAdminLayout); + + QHBoxLayout *overallLayout = new QHBoxLayout; + aviButton = new QPushButton; + aviButton->setIcon(QIcon::fromTheme("user")); + aviButton->setIconSize(QSize(32, 32)); + aviButton->setToolTip(tr("Change this user's avatar")); + aviButton->setWhatsThis(tr("Allows you to choose the user's avatar, which will be shown on the log in screen.")); + overallLayout->addWidget(aviButton); + overallLayout->addLayout(detailLayout); + + setLayout(overallLayout); + + connect(accountName, &QLineEdit::textEdited, + [=]{ + emit validityChanged(); + this->acctEverTouched = true; + }); + connect(personalName, &QLineEdit::textEdited, + [=]{ + if(this->acctEverTouched) { + emit validityChanged(); + return; + } + + /* REQ: UI.Accounts.UserAcct.AcctName.Default */ + QString result = personalName->text() + /* NFKC */ + .normalized(QString::NormalizationForm_KC) + /* Casefold */ + .toLower(); + QStringList components = result.split(" "); + if(components.size() > 1) { + result = ""; + for(int next = 0; next < components.size() - 1; next++) { + result += components.at(next).left(1); + } + result += components.at(components.size() - 1); + } + accountName->setText(result.left(32)); + emit validityChanged(); + }); + connect(passphrase, &QLineEdit::textEdited, + [=]{ emit validityChanged(); }); +} + +QString UserAccountWidget::accountText(void) const { + return accountName->text(); +} + +void UserAccountWidget::setAccountText(QString account) { + accountName->setText(account); + accountName->textEdited(account); +} + +QString UserAccountWidget::passphraseText(void) const { + return passphrase->text(); +} + +QString UserAccountWidget::personalText(void) const { + return personalName->text(); +} + +void UserAccountWidget::setPersonalText(QString personal) { + personalName->setText(personal); + personalName->textEdited(personal); +} + +bool UserAccountWidget::isAdmin(void) const { + return adminTick->isChecked(); +} + +void UserAccountWidget::setAdmin(bool ticked) { + adminTick->setChecked(ticked); + /* adminTick being ticked can cause validity to change */ + emit validityChanged(); +} + +bool UserAccountWidget::isValid() const { + /* The widget is valid if absolutely no account information has been specified. */ + if(accountText().isEmpty() && personalText().isEmpty() && + passphraseText().isEmpty() && !adminTick->isChecked()) { + return true; + } + + if(accountText().isEmpty() || personalText().isEmpty()) { + return false; + } + + return true; +} diff --git a/ui/qt5/useraccountwidget.hh b/ui/qt5/useraccountwidget.hh new file mode 100644 index 0000000..71a23b7 --- /dev/null +++ b/ui/qt5/useraccountwidget.hh @@ -0,0 +1,57 @@ +/* + * useraccountwidget.cc - Implementation of a widget for managing user accounts + * horizon-qt5, the Qt 5 user interface for + * Project Horizon + * + * Copyright (c) 2019 Adélie Linux and contributors. All rights reserved. + * This code is licensed under the AGPL 3.0 license, as noted in the + * LICENSE-code file in the root directory of this repository. + * + * SPDX-License-Identifier: AGPL-3.0-only + */ + +#ifndef USERACCOUNTWIDGET_HH +#define USERACCOUNTWIDGET_HH + +#include +#include +#include +#include + +class UserAccountWidget : public QWidget { + Q_OBJECT +public: + /*! Constructs a new User Account widget. */ + UserAccountWidget(QWidget *parent = nullptr); + + /*! Returns the current text in the Account Name text entry. */ + QString accountText(void) const; + /*! Sets the current text in the Account Name text entry. */ + void setAccountText(QString); + /*! Returns the current text in the passphrase entry. */ + QString passphraseText(void) const; + /*! Returns the current text in the Personal Name text entry. */ + QString personalText(void) const; + /*! Sets the current text in the Personal Name text entry. */ + void setPersonalText(QString); + + /*! Returns whether the Admin tickbox is ticked or not. */ + bool isAdmin(void) const; + /*! Changes whether the Admin tickbox is ticked or not. */ + void setAdmin(bool); + + /*! Returns whether the widget defines a valid account. */ + bool isValid(void) const; +signals: + void validityChanged(); +private: + QLineEdit *accountName; + QLineEdit *personalName; + QLineEdit *passphrase; + QPushButton *aviButton; + QCheckBox *adminTick; + /*! When set, auto-update of accountName from personalName is prevented. */ + bool acctEverTouched; +}; + +#endif /* !USERACCOUNTWIDGET_HH */ -- cgit v1.2.3-60-g2f50