4
0
mirror of https://github.com/QuasarApp/QMLLoginView.git synced 2025-05-10 08:29:41 +00:00

Merge pull request from QuasarApp/HanoiTowerChanges

HanoiTowers patch
This commit is contained in:
Andrei Yankovich 2021-03-22 12:01:38 +03:00 committed by GitHub
commit 70caf44b5a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
27 changed files with 677 additions and 214 deletions

3
.gitignore vendored

@ -46,6 +46,9 @@ target_wrapper.*
# QtCreator CMake
CMakeLists.txt.user*
CMakeFiles
*_autogen
cmake_install.cmake
# QtCreator 4.8< compilation database
compile_commands.json

@ -1,5 +1,5 @@
#
# Copyright (C) 2018-2020 QuasarApp.
# Copyright (C) 2018-2021 QuasarApp.
# Distributed under the MIT software license, see the accompanying
# Everyone is permitted to copy and distribute verbatim copies
# of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
#
# Copyright (C) 2018-2020 QuasarApp.
# Copyright (C) 2018-2021 QuasarApp.
# Distributed under the lgplv3 software license, see the accompanying
# Everyone is permitted to copy and distribute verbatim copies
# of this license document, but changing it is not allowed.
@ -8,7 +8,13 @@
cmake_minimum_required(VERSION 3.5)
project(LoginViewMain)
if(NOT DEFINED LOGINVIEW_EXAMPLES)
set (LOGINVIEW_EXAMPLES ON)
endif()
# Add sub directories
add_subdirectory(LoginView)
add_subdirectory(example)
if (LOGINVIEW_EXAMPLES)
add_subdirectory(example)
endif()

@ -1,5 +1,5 @@
#
# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
# Distributed under the lgplv3 software license, see the accompanying
# Everyone is permitted to copy and distribute verbatim copies
# of this license document, but changing it is not allowed.
@ -19,7 +19,8 @@ add_definitions(-DLOGIN_VIEW_LIBRARY)
include(${CMAKE_CURRENT_SOURCE_DIR}/../CMake/ProjectOut.cmake)
find_package(Qt5 COMPONENTS Core Quick Xml REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core Quick Xml REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core Quick Xml REQUIRED)
file(GLOB SOURCE_CPP "src/*.cpp" "src/*.qrc")
@ -28,7 +29,7 @@ add_library(${PROJECT_NAME} SHARED ${SOURCE_CPP})
target_compile_definitions(LoginView
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(${PROJECT_NAME} PUBLIC Qt5::Core Qt5::Quick Qt5::Xml)
target_link_libraries(${PROJECT_NAME} PUBLIC Qt::Core Qt::Quick Qt::Xml)
target_include_directories(${PROJECT_NAME} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src)
set(QML_IMPORT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/src" CACHE STRING "Qt Creator extra qml import paths")

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
@ -52,9 +52,9 @@ Control {
anchors.bottomMargin: 15
anchors.left: parent.left
anchors.leftMargin: 15
anchors.leftMargin: 0
anchors.right: parent.right
anchors.rightMargin: 15
anchors.rightMargin: 0
}

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.

@ -1,38 +1,32 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
import QtQuick 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtQuick.Controls.Material 2.12
import QtQuick.Controls.Universal 2.12
import QtQuick 2.15
import QtQuick.Controls 2.15
import QtQuick.Layouts 1.15
import QtQuick.Controls.Material 2.15
import QtQuick.Controls.Universal 2.15
Page {
id: root;
height: 500
width: 400
header: LVMHeader{
id: header
withTitle: root.withTitle
title: (conntent.isRegisterNewUser)? qsTr("SignUp"): qsTr("LogIn")
help: (conntent.isRegisterNewUser)? qsTr('Please fill this form to create an account'):
withTitle: privateRoot.withTitle
title: (privateRoot.isRegisterNewUser)? qsTr("Create a new account"): qsTr("LogIn")
help: (privateRoot.isRegisterNewUser)? qsTr('Please fill this form to create an account'):
qsTr('Please fill this form to login in your account')
}
property bool withTitle: (lognViewModel)? lognViewModel.fTitle: false
property bool lastName: (lognViewModel)? lognViewModel.fLastName: false
property bool firstName: (lognViewModel)? lognViewModel.fFirstName: false
property bool nickName: (lognViewModel)? lognViewModel.fNickname: false
property bool email: (lognViewModel)? lognViewModel.fEMail: false
property var lognViewModel: null
property bool registerNewUser: true
signal loginClicked(var isregister);
function clear() {
countryInput.currentIndex = -1
@ -42,63 +36,41 @@ Page {
}
Connections {
target: userLogin
onClearView: {
target: lognViewModel
function clearView () {
clear();
}
}
leftPadding: 0
rightPadding: 0
contentItem:
Item {
id: conntent
property bool isRegisterNewUser: tabBar.currentIndex
property var errors: (lognViewModel)? lognViewModel.validationData : null
GridLayout {
rows: 8
columns: 2
rowSpacing: 15
columnSpacing: 15
columns: Math.ceil(conntent.width / childWidth)
id: content
function paswordValidation() {
if (lognViewModel) {
lognViewModel.data.rawPassword = pass1.text;
}
pass1.hasEdited = true
if (!conntent.isRegisterNewUser) {
return;
}
pass2.hasError = false;
pass2.tooltip = "";
if (pass1.text != pass2.text || pass1.length <= 0) {
pass2.hasError = true;
pass2.hasEdited = true;
pass2.tooltip = qsTr("Password must match the 1st field and the password cannot be empty");
}
}
property int childWidth: firstNameInput.height * 10
LVMTextInput {
id: firstNameInput
placeholderText: qsTr("First Name")
Layout.columnSpan: (content.width > 350)? 1 : 2;
Layout.fillWidth: true
visible: conntent.isRegisterNewUser && root.firstName
visible: privateRoot.isRegisterNewUser && privateRoot.firstName
tooltip: (hasError)? qsTr("Empy or incorrect name. Please enter yuor name."): ""
hasError: (conntent.errors && conntent.errors.firstName);
hasError: (privateRoot.errors && privateRoot.errors.firstName);
onTextChanged: {
if (lognViewModel) {
lognViewModel.data.firstName = text;
}
hasEdited = true
}
text: lognViewModel.data.firstName;
text: (lognViewModel)? lognViewModel.data.firstName: "";
}
@ -106,10 +78,9 @@ Page {
id: lastNameInput
placeholderText: qsTr("Last Name")
Layout.columnSpan: (content.width > 350)? 1 : 2;
Layout.fillWidth: true
visible: conntent.isRegisterNewUser && root.lastName
hasError: (conntent.errors && conntent.errors.lastName);
visible: privateRoot.isRegisterNewUser && privateRoot.lastName
hasError: (privateRoot.errors && privateRoot.errors.lastName);
onTextChanged: {
if (lognViewModel) {
@ -118,18 +89,24 @@ Page {
hasEdited = true
}
text: lognViewModel.data.lastName;
text: (lognViewModel)? lognViewModel.data.lastName: "";
}
Item {
// separator
Layout.preferredHeight: 0
Layout.fillWidth: true
Layout.columnSpan: Math.max(content.columns, 1)
}
LVMComboBox {
id: countryInput
placeholderText: qsTr("Select you country")
Layout.columnSpan: 2
Layout.fillWidth: true
visible: conntent.isRegisterNewUser && model.length
visible: privateRoot.isRegisterNewUser && model.length
onCurrentIndexChanged: {
if (lognViewModel) {
lognViewModel.data.country = lognViewModel.countryCodeList[currentIndex];
@ -138,14 +115,21 @@ Page {
}
Item {
// separator
Layout.preferredHeight: 0
Layout.fillWidth: true
Layout.columnSpan: Math.max(content.columns, 1)
}
LVMTextInput {
id: emailInput
placeholderText: qsTr("EMail")
Layout.columnSpan: (root.email && root.nickName)? (content.width > 350)? 1 : 2 : 2;
Layout.fillWidth: true
visible: root.email
hasError: (conntent.errors && conntent.errors.email);
visible: privateRoot.email
hasError: (privateRoot.errors && privateRoot.errors.email);
tooltip: (hasError)? qsTr("Empty or incorrect email address. Please enter yuor name.") : ""
onTextChanged: {
if (lognViewModel) {
@ -154,7 +138,7 @@ Page {
hasEdited = true
}
text: lognViewModel.data.email;
text: (lognViewModel)?lognViewModel.data.email: "";
}
@ -162,10 +146,9 @@ Page {
id: nicknameInput
placeholderText: qsTr("Nickname")
Layout.columnSpan: (root.email && root.nickName)? (content.width > 350)? 1 : 2 : 2;
Layout.fillWidth: true
visible: root.nickName
hasError: (conntent.errors && conntent.errors.nickname);
visible: privateRoot.nickName
hasError: (privateRoot.errors && privateRoot.errors.nickname);
tooltip: (hasError)? qsTr("Empty or incorrect Nickname. Please enter yuor name.") : ""
onTextChanged: {
if (lognViewModel) {
@ -175,20 +158,27 @@ Page {
}
text: lognViewModel.data.nickname;
text: (lognViewModel)? lognViewModel.data.nickname: "";
}
Item {
// separator
Layout.preferredHeight: 0
Layout.fillWidth: true
Layout.columnSpan: Math.max(content.columns, 1)
}
LVMTextInput {
id: pass1
placeholderText: qsTr("Pasword")
Layout.columnSpan: (conntent.isRegisterNewUser)? ((content.width > 350)? 1 : 2): 2;
Layout.fillWidth: true
hasError: (conntent.errors && conntent.errors.rawPassword);
hasError: (privateRoot.errors && privateRoot.errors.rawPassword);
tooltip: (hasError)? lognViewModel.passwordError : ""
onTextChanged: {
content.paswordValidation()
privateRoot.paswordValidation()
}
visible: privateRoot.password
echoMode: TextInput.Password
}
@ -196,58 +186,20 @@ Page {
LVMTextInput {
id: pass2
placeholderText: qsTr("Confirm pasword")
Layout.columnSpan: (content.width > 350)? 1 : 2;
Layout.fillWidth: true
visible: conntent.isRegisterNewUser
visible: privateRoot.isRegisterNewUser && privateRoot.password
onTextChanged: {
content.paswordValidation()
privateRoot.paswordValidation()
}
echoMode: TextInput.Password
}
LVMCheckBox {
id: termOfUse
text: qsTr("I accept the Terms of use")
Layout.columnSpan: (content.width > 350)? 1 : 2;
Layout.fillWidth: true
visible:conntent.isRegisterNewUser
}
LVMButton {
text: qsTr("Show terms of use")
visible: conntent.isRegisterNewUser
onClicked: {
if (lognViewModel) {
lognViewModel.showTermOfUseRequest();
}
}
}
LVMButton {
text: (conntent.isRegisterNewUser)? qsTr("SignUp") : qsTr("LogIn")
visible: true
enabled: (conntent.errors && conntent.errors.noError) &&
((conntent.isRegisterNewUser)? !pass2.hasError && termOfUse.checked: true)
onClicked: {
if (lognViewModel) {
if (conntent.isRegisterNewUser) {
lognViewModel.registerRequest();
} else {
lognViewModel.loginRequest();
}
}
loginClicked(conntent.isRegisterNewUser);
}
}
LVMButton {
text: qsTr("Forgot password")
visible: !conntent.isRegisterNewUser
enabled: !(conntent.errors && conntent.errors.email)
visible: !privateRoot.isRegisterNewUser
enabled: !(privateRoot.errors && privateRoot.errors.email)
onClicked: {
if (lognViewModel) {
@ -255,19 +207,76 @@ Page {
}
}
}
anchors.bottomMargin: 40
Item {
// separator
Layout.preferredHeight: 0
Layout.fillWidth: true
Layout.columnSpan: Math.max(content.columns, 1)
}
LVMCheckBox {
id: termOfUse
text: qsTr("I accept the Terms of use")
Layout.fillWidth: true
visible:privateRoot.isRegisterNewUser && privateRoot.termOfuse
}
LVMButton {
text: qsTr("Show terms of use")
visible: privateRoot.isRegisterNewUser && privateRoot.termOfuse
onClicked: {
if (lognViewModel) {
lognViewModel.showTermOfUseRequest();
}
}
}
Item {
// separator
Layout.preferredHeight: 0
Layout.fillWidth: true
Layout.fillHeight: true
Layout.columnSpan: Math.max(content.columns, 1)
}
LVMButton {
text: privateRoot.acceptButtonText.length?
privateRoot.acceptButtonText:
(privateRoot.isRegisterNewUser)?
qsTr("SignUp"):
qsTr("LogIn")
visible: true
enabled: privateRoot.enableAccept(privateRoot.errors, privateRoot.isRegisterNewUser,
privateRoot.password, pass2.hasError, termOfUse.checked,
privateRoot.termOfuse)
onClicked: {
if (lognViewModel) {
if (privateRoot.isRegisterNewUser) {
lognViewModel.registerRequest();
} else {
lognViewModel.loginRequest();
}
}
loginClicked(privateRoot.isRegisterNewUser);
}
}
anchors.bottomMargin: 0
anchors.leftMargin: 20
anchors.rightMargin: 20
anchors.fill: parent
}
}
footer: TabBar {
id: tabBar
width: parent.width
currentIndex: registerNewUser
visible: privateRoot.loginPage && privateRoot.registerPage
currentIndex: privateRoot.pageToIndex(privateRoot.currentPage)
TabButton {
text: qsTr("Login In")
}
@ -275,5 +284,82 @@ Page {
text: qsTr("Sign Up")
}
onCurrentIndexChanged: {
if (lognViewModel) {
if (currentIndex)
lognViewModel.setCurrentPage(ViewComponents.sigupPage)
else
lognViewModel.setCurrentPage(ViewComponents.loginPage)
}
}
}
Item {
id: privateRoot;
// Private propertyes
property bool isRegisterNewUser: pageSelector(tabBar.currentIndex, registerPage, loginPage)
property var errors: (lognViewModel)? lognViewModel.validationData : null
property bool withTitle: (lognViewModel)? lognViewModel.fTitle: false
property bool lastName: (lognViewModel)? lognViewModel.fLastName: false
property bool firstName: (lognViewModel)? lognViewModel.fFirstName: false
property bool nickName: (lognViewModel)? lognViewModel.fNickname: false
property bool email: (lognViewModel)? lognViewModel.fEMail: false
property bool password: (lognViewModel)? lognViewModel.fPassword: false
property bool loginPage: (lognViewModel)? lognViewModel.fLogin: false
property bool registerPage: (lognViewModel)? lognViewModel.fRegister: false
property bool termOfuse: (lognViewModel)? lognViewModel.fTermOfUse: false
property int currentPage: (lognViewModel)? lognViewModel.currentPage: 0
property string acceptButtonText: (lognViewModel)? lognViewModel.acceptButtonText: false
property int widgetsCount: lastName + firstName + nickName + email + password + withTitle
function pageSelector(toolBarIndex, registerPage, loginPage) {
if (registerPage && loginPage)
return toolBarIndex;
return registerPage;
}
function pageToIndex(currentPage) {
return currentPage === ViewComponents.sigupPage
}
function paswordValidation() {
if (lognViewModel) {
lognViewModel.data.rawPassword = pass1.text;
}
pass1.hasEdited = true
if (!privateRoot.isRegisterNewUser) {
return;
}
pass2.hasError = false;
pass2.tooltip = "";
if (pass1.text != pass2.text || pass1.length <= 0) {
pass2.hasError = true;
pass2.hasEdited = true;
pass2.tooltip = qsTr("Password must match the 1st field and the password cannot be empty");
}
}
function enableAccept(errors, isRegisterNewUser, fShowPassword,
passHasError, termOfUse, fShowTermOfUse) {
if (!(errors && errors.noError)) {
return false;
}
if (isRegisterNewUser && fShowPassword) {
return !passHasError && (termOfUse || !fShowTermOfUse)
}
return true;
}
}
}

@ -9,18 +9,17 @@ Popup {
id: root
property var lognViewModel: null
width: Math.min(100 * Screen.pixelDensity * (parent.width / parent.height),
width: Math.min(70 * Screen.pixelDensity * (parent.width / parent.height),
parent.width * 0.9);
height: Math.min(200 * Screen.pixelDensity, parent.height * 0.9);
height: Math.min(150 * Screen.pixelDensity, parent.height * 0.9);
x: parent.width / 2 - width / 2
y: parent.height / 2 - height / 2
LoginView {
contentItem: LoginView {
id: source
lognViewModel: root.lognViewModel
anchors.fill: parent
onLoginClicked: {
root.close();

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
@ -41,7 +41,7 @@ bool CountrysParser::parseXMLSource(const QString &xmlFile, QHash<int, QString>
break;
}
if (token == QXmlStreamReader::StartElement && xml.name() == "countries") {
if (token == QXmlStreamReader::StartElement && xml.name() == QString("countries")) {
success = parseCountries(xml, result);
break;
}
@ -81,20 +81,20 @@ bool CountrysParser::parseCountry(QXmlStreamReader& xml, QHash<int, QString>& re
int code = 0;
QString name;
while (!(xml.readNext() == QXmlStreamReader::EndElement && xml.name() == "country")) {
while (!(xml.readNext() == QXmlStreamReader::EndElement && xml.name() == QString("country"))) {
if (!isValidItem(xml)) {
return false;
}
if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == "code") {
if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == QString("code")) {
code = getCode(xml);
if (code < 0) {
qDebug() << "error parse, code of country is invalid: line "
<< xml.lineNumber();
return false;
}
} else if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == "name") {
} else if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == QString("name")) {
name = getName(xml);
if (name.isEmpty()) {
qDebug() << "error parse, name of country is empty: line "
@ -113,13 +113,13 @@ bool CountrysParser::parseCountries(QXmlStreamReader &xml, QHash<int, QString>&
if (xml.tokenType() != QXmlStreamReader::StartElement)
return false;
while (!(xml.readNext() == QXmlStreamReader::EndElement && xml.name() == "countries")) {
while (!(xml.readNext() == QXmlStreamReader::EndElement && xml.name() == QString("countries"))) {
if (!isValidItem(xml)) {
return false;
}
if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == "country" && !parseCountry(xml, result)) {
if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == QString("country") && !parseCountry(xml, result)) {
return false;
}
}

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
@ -11,6 +11,7 @@
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include <QDebug>
#include <QRegularExpression>
namespace LoginView {
@ -30,7 +31,7 @@ LVMainModel::~LVMainModel() {
}
}
bool LVMainModel::setCounrySource(const QString &path) {
bool LVMainModel::setCountriesSource(const QString &path) {
if (!m_countrysParser) {
m_countrysParser = new CountrysParser();
@ -58,6 +59,7 @@ bool LVMainModel::init( QQmlApplicationEngine *engine) {
engine->addImportPath(":/");
root->setContextProperty(m_modelName, this);
root->setContextProperty("ViewComponents", QVariant::fromValue(ViewComponentsQML{}));
qRegisterMetaType<LoginView::UserData>("UserData");
qRegisterMetaType<LoginView::UserViewValidationData>("UserViewValidationData");
@ -102,6 +104,14 @@ void LVMainModel::setData(const UserData& data) {
emit dataChanged(m_data);
}
void LVMainModel::setAcceptButtonText(const QString &acceptButtonText) {
if (m_acceptButtonText == acceptButtonText)
return;
m_acceptButtonText = acceptButtonText;
emit acceptButtonTextChanged(m_acceptButtonText);
}
void LVMainModel::setPasswordError(QString passwordError) {
if (m_passwordError == passwordError)
return;
@ -110,35 +120,51 @@ void LVMainModel::setPasswordError(QString passwordError) {
emit passwordErrorChanged(m_passwordError);
}
ShowExtraComponent LVMainModel::components() const {
return _components;
ViewComponents LVMainModel::components() const {
return m_components;
}
void LVMainModel::setComponents(const ShowExtraComponent &components) {
if (_components != components) {
_components = components;
void LVMainModel::setComponents(const ViewComponents &components) {
if (m_components != components) {
m_components = components;
emit showChanged();
}
}
bool LVMainModel::fTitle() const {
return _components & ShowExtraComponent::Title;
return m_components & ViewComponents::Title;
}
bool LVMainModel::fFirstName() const {
return _components & ShowExtraComponent::FirstName;
return m_components & ViewComponents::FirstName;
}
bool LVMainModel::fLastName() const {
return _components & ShowExtraComponent::LastName;
return m_components & ViewComponents::LastName;
}
bool LVMainModel::fNickname() const {
return _components & ShowExtraComponent::Nickname;
return m_components & ViewComponents::Nickname;
}
bool LVMainModel::fPassword() const {
return m_components & ViewComponents::Password;
}
bool LVMainModel::fEMail() const {
return _components & ShowExtraComponent::EMail;
return m_components & ViewComponents::EMail;
}
bool LVMainModel::fRegister() const {
return m_components & ViewComponents::SigupPage;
}
bool LVMainModel::fTermOfUse() const {
return m_components & ViewComponents::TermOfUse;
}
bool LVMainModel::fLogin() const {
return m_components & ViewComponents::LoginPage;
}
void LVMainModel::clear() {
@ -146,6 +172,27 @@ void LVMainModel::clear() {
setData({});
}
QString LVMainModel::acceptButtonText() const {
return m_acceptButtonText;
}
void LVMainModel::setCurrentPage(int page) {
if (page == m_currentPage) {
return;
}
if (!(page & m_components)) {
return;
}
m_currentPage = static_cast<ViewComponents>(page);
emit currentPageChanged(page);
}
ViewComponents LVMainModel::currentPage() const {
return m_currentPage;
}
void LVMainModel::setValidData(UserViewValidationData validationData) {
if (m_validationData == validationData)
return;
@ -183,36 +230,39 @@ void LVMainModel::checkValid(const UserData& data) {
UserViewValidationData result;
result.setNickname(fNickname() && (data.nickname().contains(" ") || data.nickname().isEmpty()));
result.setEmail(fEMail() && !data.email().contains(QRegExp("^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$")));
result.setEmail(fEMail() && !data.email().contains(QRegularExpression("^([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})$")));
result.setCountry(m_countryList.size() && !m_countryList.contains(data.country()));
result.setLastName(fLastName() && false);
result.setFirstName(fFirstName() && (data.firstName().contains(" ") || data.firstName().isEmpty()));
bool passwordValidation = true;
if (m_validLvl & PasswordValidationLvl::Size8andMore) {
passwordValidation = passwordValidation &&
data.rawPassword().length() >= 8;
}
if (fPassword()) {
if (m_validLvl & PasswordValidationLvl::Size8andMore) {
passwordValidation = passwordValidation &&
data.rawPassword().length() >= 8;
}
if (m_validLvl & PasswordValidationLvl::NumberChars) {
passwordValidation = passwordValidation &&
data.rawPassword().contains(QRegExp("[0-9]"));
}
if (m_validLvl & PasswordValidationLvl::NumberChars) {
passwordValidation = passwordValidation &&
data.rawPassword().contains(QRegularExpression("[0-9]"));
}
if (m_validLvl & PasswordValidationLvl::LitinSmallChars) {
passwordValidation = passwordValidation &&
data.rawPassword().contains(QRegExp("[a-z]"));
}
if (m_validLvl & PasswordValidationLvl::LitinSmallChars) {
passwordValidation = passwordValidation &&
data.rawPassword().contains(QRegularExpression("[a-z]"));
}
if (m_validLvl & PasswordValidationLvl::LatinLargeChars) {
passwordValidation = passwordValidation &&
data.rawPassword().contains(QRegExp("[A-Z]"));
}
if (m_validLvl & PasswordValidationLvl::LatinLargeChars) {
passwordValidation = passwordValidation &&
data.rawPassword().contains(QRegularExpression("[A-Z]"));
}
if (m_validLvl & PasswordValidationLvl::ExtraChars) {
passwordValidation = passwordValidation &&
data.rawPassword().contains(QRegularExpression("[!@#$%^&*]"));
}
if (m_validLvl & PasswordValidationLvl::ExtraChars) {
passwordValidation = passwordValidation &&
data.rawPassword().contains(QRegExp("[!@#$%^&*]"));
}
result.setRawPassword(!passwordValidation);

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
@ -11,6 +11,7 @@
#include <QHash>
#include <QObject>
#include "viewcomponents.h"
#include "loginview_global.h"
#include "userdata.h"
@ -28,29 +29,24 @@ namespace LoginView {
* by default: Size8andMore | LitinSmallChars | LatinLargeChars
*/
enum PasswordValidationLvl {
/// Skip all validation of password
NoValidation = 0x00,
/// Check size. Size must be large than 8 chars.
Size8andMore = 0x01,
/// Check chars. Password must be contains a numbers.
NumberChars = 0x02,
/// Check chars. Password must be contains small chars.
LitinSmallChars = 0x04,
/// Check chars. Password must be contains large chars.
LatinLargeChars = 0x08,
/// Check chars. Password must be contains extra chars. Example: (%.~*^#).
ExtraChars = 0x10
};
/**
* @brief The ShowExtraComponent enum
* default Title | FirstName | LastName
* @brief The LVMainModel class is main model of the qml login view.
*/
enum ShowExtraComponent {
NoShow = 0x00,
Title = 0x01,
FirstName = 0x02,
LastName = 0x04,
EMail = 0x08,
Nickname = 0x10,
All = EMail | Title | FirstName | LastName
};
class LOGINVIEW_EXPORT LVMainModel: public QObject
{
Q_OBJECT
@ -63,22 +59,28 @@ class LOGINVIEW_EXPORT LVMainModel: public QObject
Q_PROPERTY(bool fFirstName READ fFirstName NOTIFY showChanged)
Q_PROPERTY(bool fNickname READ fNickname NOTIFY showChanged)
Q_PROPERTY(bool fEMail READ fEMail NOTIFY showChanged)
Q_PROPERTY(bool fRegister READ fRegister NOTIFY showChanged)
Q_PROPERTY(bool fLogin READ fLogin NOTIFY showChanged)
Q_PROPERTY(bool fPassword READ fPassword NOTIFY showChanged)
Q_PROPERTY(bool fTermOfUse READ fTermOfUse NOTIFY showChanged)
Q_PROPERTY(int currentPage READ currentPage NOTIFY currentPageChanged)
Q_PROPERTY(int country READ country WRITE setCountry NOTIFY countryChanged)
Q_PROPERTY(UserData data READ data WRITE setData NOTIFY dataChanged)
Q_PROPERTY(UserViewValidationData validationData READ validData WRITE setValidData NOTIFY validDataChanged)
Q_PROPERTY(QString passwordError READ passwordError WRITE setPasswordError NOTIFY passwordErrorChanged)
Q_PROPERTY(QString acceptButtonText READ acceptButtonText WRITE setAcceptButtonText NOTIFY acceptButtonTextChanged)
public:
explicit LVMainModel(const QString modelName,
QObject *parent = nullptr);
~LVMainModel();
/**
* @brief setCounrySource - sets path to xml source file and extract list of countrys
* @param path
* @brief setCountriesSource This method sets path to xml source file and extract list of countrys
* @param path This is path to xml sources of countries
* @return true if the function finished successful
*/
Q_INVOKABLE bool setCounrySource(const QString &path);
Q_INVOKABLE bool setCountriesSource(const QString &path);
/**
* @brief init - prepare all items for use on qml.
@ -86,84 +88,256 @@ public:
* @return true if the function finished successful
*/
bool init(QQmlApplicationEngine *engine);
/**
* @brief country This method return current country id.
* @return current country id.
*/
int country() const;
/**
* @brief countryList This method retun list of availabel countries.
* @return string list of available countries.
*/
QStringList countryList() const;
/**
* @brief data This method return information of created or lofined user.
* @return return information of created or lofined user.
*/
UserData data() const;
/**
* @brief validData This method return structure that display valid data.
* @return information about last validation.
*/
UserViewValidationData validData() const;
/**
* @brief passwordError This method return text message about last password error.
* For get more information about password errors see the PasswordValidationLvl enum.
* @return Error message.
*/
QString passwordError() const;
/**
* @brief countryCodeList This method return the list of ids of the countries.
* @return countries ids.
*/
QList<int> countryCodeList() const;
/**
* @brief loginRequest This method invoked wjet user click the login button.
*/
Q_INVOKABLE void loginRequest();
/**
* @brief rememberPasswordRequest This method invoked when user click the forgetpassword button.
*/
Q_INVOKABLE void rememberPasswordRequest();
/**
* @brief registerRequest This method invoked when user click the signUp button.
*/
Q_INVOKABLE void registerRequest();
/**
* @brief showTermOfUseRequest This method invoked when user click the "show temr of use" button.
*/
Q_INVOKABLE void showTermOfUseRequest();
/**
* @brief components This method return visible comonents of this model.
* @return return information about visible companents of Qml View. for more information see the ViewComponents enum.
*/
ViewComponents components() const;
ShowExtraComponent components() const;
void setComponents(const ShowExtraComponent &components);
/**
* @brief setComponents This method sets visibel companents of the qml view.
* @param components This is enum with visible companents. For get more information see Thee ViewComponents enum class.
*/
void setComponents(const ViewComponents &components);
/**
* @brief fTitle This method return Title visible state.
* @return Title visible state.
*/
bool fTitle() const;
/**
* @brief fFirstName This method return first name visible state.
* @return first name visible state.
*/
bool fFirstName() const;
/**
* @brief fLastName This method return last name visible state.
* @return last name visible state.
*/
bool fLastName() const;
/**
* @brief fNickname This method return nickname visible state.
* @return nickname visible state.
*/
bool fNickname() const;
/**
* @brief fPassword This method return password visible state.
* @return password visible state.
*/
bool fPassword() const;
/**
* @brief fEMail This method return email visible state.
* @return email visible state.
*/
bool fEMail() const;
/**
* @brief fRegister This method return register page visible state.
* @return register page visible state.
*/
bool fRegister() const;
/**
* @brief fTermOfUse This method return term of use widgets visible state.
* @return term of use widgets visible state.
*/
bool fTermOfUse() const;
/**
* @brief fLogin This method return login page visible state.
* @return login page visible state.
*/
bool fLogin() const;
/**
* @brief fSigupDefaultPage return true if the default page is the sigup page.
* @return true if the default page is the sigup page.
*/
bool fSigupDefaultPage() const;
/**
* @brief clear - clear all data from view
*/
void clear();
/**
* @brief acceptButtonText This method return alternative text of the accept button.
* @return alternative text of the accept button
*/
QString acceptButtonText() const;
/**
* @brief setDefaultPage sets visible page page.
* @param page new default padge (RegisterPage or LoginPage)
*/
Q_INVOKABLE void setCurrentPage(int page);
/**
* @brief currentPage return id of the current page
* @return id of the current page
*/
ViewComponents currentPage() const;
public slots:
/**
* @brief setCountry This slot sets current contry. This method work with qml View and invoked when user change own country.
* @param country This is new country id.
*/
void setCountry(int country);
/**
* @brief setData set new data for view
* @param data
* @brief setData sets new data for view on qml page.
* @param data new user data.
*/
void setData(const UserData &data);
/**
* @brief setAcceptButtonText This method sets new test of the accept button. Use this method if you wnat change test on main button.
* @param acceptButtonText new text of the accept button.
*/
void setAcceptButtonText(const QString& acceptButtonText);
signals:
/**
* @brief countryChanged This signal emited when country on page is will be changed.
* @param country new country id.
*/
void countryChanged(int country);
/**
* @brief countryListChanged This method emited when available country list will be changed.
*/
void countryListChanged();
/**
* @brief countryCodeListChanged This method emited when available country list will be changed.
*/
void countryCodeListChanged();
/**
* @brief sigLoginRequest
* emited when user try login
* emited when user try login.
*/
void sigLoginRequest(const UserData&);
/**
* @brief sigRegisterRequest
* emited when user try create new accaunt
* emited when user try create new accaunt.
*/
void sigRegisterRequest(const UserData&);
/**
* @brief sigForgotPasswordRequest
* emited when user forgot own password
* emited when user forgot own password.
*/
void sigForgotPasswordRequest(const UserData&);
/**
* @brief sigShowTermOfUseRequest
* emited when user click on "Show term of use" button
* emited when user click on "Show term of use" button.
*/
void sigShowTermOfUseRequest();
/**
* @brief dataChanged emited when data of qml form will be changed.
* @param data new data of qml form.
*/
void dataChanged(UserData data);
/**
* @brief validDataChanged This method emited when model is finished validation of the accepted user data.
* @param validationData this is validation results.
*/
void validDataChanged(UserViewValidationData validationData);
/**
* @brief passwordErrorChanged This method will be emoted when user password have a any error.
* @param passwordError This is new erro message of user password.
*/
void passwordErrorChanged(QString passwordError);
/**
* @brief showChanged - emited when show components changed
* @param ftitle
* @brief showChanged This signal emited when rules of shows components will be changed
*/
void showChanged();
/**
* @brief clearView This signal emited when need to clear a view. for more ifnformation see The clear method.
*/
void clearView();
/**
* @brief acceptButtonTextChanged This signal emited when text of the accept button will be changed.
* @param acceptButtonText Tihs is new test of the accept button.
*/
void acceptButtonTextChanged(QString acceptButtonText);
void currentPageChanged(int currentPage);
private:
void checkValid(const UserData &data);
void setValidData(UserViewValidationData validationData);
@ -178,7 +352,9 @@ private:
UserViewValidationData m_validationData;
QString m_passwordError;
ShowExtraComponent _components = ShowExtraComponent::All;
ViewComponents m_components = ViewComponents::All;
ViewComponents m_currentPage = ViewComponents::SigupPage;
QString m_acceptButtonText;
};
}

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
@ -12,6 +12,9 @@
namespace LoginView {
/**
* @brief The UserData class This is base class for save user data.
*/
class LOGINVIEW_EXPORT UserData
{
Q_GADGET

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
@ -12,6 +12,9 @@
namespace LoginView {
/**
* @brief The UserViewValidationData class contains data of the last validation.
*/
class UserViewValidationData
{
Q_GADGET
@ -20,7 +23,7 @@ class UserViewValidationData
Q_PROPERTY(bool lastName READ lastName WRITE setLastName) // ValidationAddersses::LastName
Q_PROPERTY(bool rawPassword READ rawPassword WRITE setRawPassword) // ValidationAddersses::RawPassword
Q_PROPERTY(bool email READ email WRITE setEmail) // ValidationAddersses::Email
Q_PROPERTY(bool nickname READ nickname WRITE setNickname) // ValidationAddersses::Email
Q_PROPERTY(bool nickname READ nickname WRITE setNickname) // ValidationAddersses::nickname
Q_PROPERTY(bool noError READ noError)
public:

@ -0,0 +1,55 @@
#include "viewcomponents.h"
namespace LoginView {
int ViewComponentsQML::noShow() const
{
return ViewComponents::NoShow;
}
int ViewComponentsQML::title() const
{
return ViewComponents::Title;
}
int ViewComponentsQML::firstName() const
{
return ViewComponents::FirstName;
}
int ViewComponentsQML::lastName() const
{
return ViewComponents::LastName;
}
int ViewComponentsQML::eMail() const
{
return ViewComponents::EMail;
}
int ViewComponentsQML::nickname() const
{
return ViewComponents::Nickname;
}
int ViewComponentsQML::password() const
{
return ViewComponents::Password;
}
int ViewComponentsQML::sigupPage() const
{
return ViewComponents::SigupPage;
}
int ViewComponentsQML::loginPage() const
{
return ViewComponents::LoginPage;
}
int ViewComponentsQML::termOfUse() const
{
return ViewComponents::TermOfUse;
}
}

@ -0,0 +1,81 @@
//#
//# Copyright (C) 2020-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef VIEWCOMPONENTS_H
#define VIEWCOMPONENTS_H
#include <QObject>
namespace LoginView {
/**
* @brief The ViewComponents enum used for control of the components view.
* default is All
*/
enum ViewComponents {
/// No show any componets.
NoShow = 0x0000,
/// Show Title of the qml page.
Title = 0x0001,
/// Show first name input widget.
FirstName = 0x0002,
/// Show last name input widget.
LastName = 0x0004,
/// Show email name input widget.
EMail = 0x0008,
/// Show nickname input widget.
Nickname = 0x0010,
/// Show password input widget.
Password = 0x0020,
/// Show register page.
SigupPage = 0x0040,
/// Show login page.
LoginPage = 0x0080,
/// Show term of use button and accept term of use checkbox.
TermOfUse = 0x0100,
/// Show only one input widget with name.
RegNameOnly = Title | Nickname | SigupPage,
/// Show all widgets and pages.
All = EMail | Title | FirstName | LastName | Nickname | Password | SigupPage | LoginPage | TermOfUse
};
/**
* @brief The ViewComponentsQML class This is qml implementation of the ViewComponents enum.
*/
class ViewComponentsQML
{
Q_GADGET
Q_PROPERTY(int noShow READ noShow)
Q_PROPERTY(int title READ title)
Q_PROPERTY(int firstName READ firstName)
Q_PROPERTY(int lastName READ lastName)
Q_PROPERTY(int eMail READ eMail)
Q_PROPERTY(int nickname READ nickname)
Q_PROPERTY(int password READ password)
Q_PROPERTY(int sigupPage READ sigupPage)
Q_PROPERTY(int loginPage READ loginPage)
Q_PROPERTY(int termOfUse READ termOfUse)
public:
ViewComponentsQML() = default;
int noShow() const;
int title() const;
int firstName() const;
int lastName() const;
int eMail() const;
int nickname() const;
int password() const;
int sigupPage() const;
int loginPage() const;
int termOfUse() const;
};
}
Q_DECLARE_METATYPE(LoginView::ViewComponentsQML)
#endif // VIEWCOMPONENTS_H

@ -1,5 +1,5 @@
#
# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
# Distributed under the lgplv3 software license, see the accompanying
# Everyone is permitted to copy and distribute verbatim copies
# of this license document, but changing it is not allowed.
@ -20,8 +20,8 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON)
include(${CMAKE_CURRENT_SOURCE_DIR}/../CMake/ProjectOut.cmake)
find_package(Qt5 COMPONENTS Core QuickControls2 REQUIRED)
find_package(QT NAMES Qt6 Qt5 COMPONENTS Core QuickControls2 REQUIRED)
find_package(Qt${QT_VERSION_MAJOR} COMPONENTS Core QuickControls2 REQUIRED)
if(ANDROID)
add_library(${PROJECT_NAME} SHARED
@ -38,5 +38,5 @@ endif()
target_compile_definitions(${PROJECT_NAME}
PRIVATE $<$<OR:$<CONFIG:Debug>,$<CONFIG:RelWithDebInfo>>:QT_QML_DEBUG>)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt5::Core Qt5::QuickControls2 LoginView)
target_link_libraries(${PROJECT_NAME} PRIVATE Qt::Core Qt::QuickControls2 LoginView)

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
@ -32,7 +32,7 @@ int main(int argc, char *argv[])
pathXML = QString(argv[1]);
}
if (!loginModel.setCounrySource(pathXML)) {
if (!loginModel.setCountriesSource(pathXML)) {
return -2;
}

@ -1,5 +1,5 @@
//#
//# Copyright (C) 2018-2020 Yankovich Andrei (EndrII).
//# Copyright (C) 2018-2021 Yankovich Andrei (EndrII).
//# Distributed under the lgplv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.