Index: sources/view/settings/VSettings.cpp =================================================================== diff -u -r57ea732311e6f4c746974f5a52316f63dec23ca8 -rbf9223700613ced6c377f3e3a7b4de8367c30474 --- sources/view/settings/VSettings.cpp (.../VSettings.cpp) (revision 57ea732311e6f4c746974f5a52316f63dec23ca8) +++ sources/view/settings/VSettings.cpp (.../VSettings.cpp) (revision bf9223700613ced6c377f3e3a7b4de8367c30474) @@ -37,10 +37,13 @@ { static bool init = false; if ( init ) return; - PROPERTY_POST_CONNECTION(VSettings, servicePass ); - PROPERTY_POST_CONNECTION(VSettings, alarmVolume ); - PROPERTY_POST_CONNECTION(VSettings, roWaterMode ); - + PROPERTY_POST_CONNECTION(VSettings, servicePass ); + PROPERTY_POST_CONNECTION(VSettings, alarmVolume ); + PROPERTY_POST_CONNECTION(VSettings, roWaterMode ); + PROPERTY_POST_CONNECTION(VSettings, integratedBPCuff ); + PROPERTY_POST_CONNECTION(VSettings, heparinSyringePump ); + PROPERTY_POST_CONNECTION(VSettings, chemicalDisinfection); + PROPERTY_POST_CONNECTION(VSettings, advancedMode); init = true; } @@ -60,6 +63,36 @@ } } +void VSettings::advancedMode_post(const bool &vadvancedMode_post) { + //TODO The Settings shall be the Singleton SettingsController and modify the MSettings like the others. + if ( Storage::Settings::save(advancedModeGroup(), advancedModeKey(), QString::number(vadvancedMode_post)) != 0 ) { + advancedMode(false); + } +} +void VSettings::integratedBPCuff_post(const bool &vintegratedBPCuff_post) { + //TODO The Settings shall be the Singleton SettingsController and modify the MSettings like the others. + if ( Storage::Settings::save(integratedBPCuffGroup(), integratedBPCuffKey(), QString::number(vintegratedBPCuff_post)) != 0 ) { + integratedBPCuff(false); + // FIXME: Notify UI with a message + } +} + +void VSettings::heparinSyringePump_post(const bool &vheparinSyringePump_post) { + //TODO The Settings shall be the Singleton SettingsController and modify the MSettings like the others. + if ( Storage::Settings::save(heparinSyringePumpGroup(), heparinSyringePumpKey(), QString::number(vheparinSyringePump_post)) != 0 ) { + heparinSyringePump(false); + // FIXME: Notify UI with a message + } +} + +void VSettings::chemicalDisinfection_post(const bool &vchemicalDisinfection_post) { + //TODO The Settings shall be the Singleton SettingsController and modify the MSettings like the others. + if ( Storage::Settings::save(chemicalDisinfectionGroup(), chemicalDisinfectionKey(), QString::number(vchemicalDisinfection_post)) != 0 ) { + chemicalDisinfection(false); + // FIXME: Notify UI with a message + } +} + void VSettings::alarmVolume_post(const quint8 &valarmVolume) { //TODO The Settings shall be the Singleton SettingsController and modify the MSettings like the others. Storage::Settings::save(alarmVolumeGroup(), alarmVolumeKey(), QString::number(valarmVolume)); @@ -73,15 +106,28 @@ for (const auto &category : mCategorys) { QStringList groups = _Settings.groups(category); for (const auto &group : groups) { - QStringList keys = _Settings.keys (category, group); - QVariantList values = _Settings.values (category, group); + QStringList keys ; + QVariantList values ; + QString title = ""; + for (const QString &key : _Settings.keys(category, group)) { + if (Storage::Settings::isKeyTitle ( key ) ) { + title = _Settings.value(category, group, key).toString(); + } else { + const QString imagePath = QStringLiteral("%1%2").arg(_location) + .arg(_Settings.value(category, group, key).toString()); + QFileInfo fileInfo(imagePath); + values.append(fileInfo.exists() && fileInfo.isFile() ? "file:" + imagePath : ""); + keys.append(key); + } + } + if ( Storage::Settings::isCategoryInstructions( category ) ) { - TKeysList keysList = updateReplacements(group, keys ); - updateInstructions(group, keysList, values ); - updateInstructions(group ); + TKeysList keysList = updateReplacements(group, keys ); + updateInstructions(group, keysList, values, title ); + updateInstructions(group ); } else { //TODO: Since it is global system settings, move this to the settings controller so the C++ backend can also use it. like Date/Time formats. - for (const auto &key : std::as_const(keys)) { + for (const auto &key : qAsConst(keys)) { // DEBUG: qDebug() << " ~~~~~~~~~~ " << category << group << key << _Settings.value(category, group, key).toString (); QVariantMap keyValue; if ( isservicePass (category, group, key) ) { @@ -96,6 +142,30 @@ keyValue[key] = mRoWaterMode ; roWaterMode ( mRoWaterMode); } + else if ( isadvancedMode(category, group, key) ) { + bool mAdvancedMode; + mAdvancedMode = _Settings.value(category, group, key).toBool (); + keyValue[key] = mAdvancedMode ; + advancedMode ( mAdvancedMode ); + } + else if ( isintegratedBPCuff (category, group, key) ) { + bool mIntegratedBPCuff; + mIntegratedBPCuff = _Settings.value(category, group, key).toBool (); + keyValue[key] = mIntegratedBPCuff ; + integratedBPCuff ( mIntegratedBPCuff ); + } + else if ( isheparinSyringePump (category, group, key) ) { + bool mHeparinSyringePump; + mHeparinSyringePump = _Settings.value(category, group, key).toBool (); + keyValue[key] = mHeparinSyringePump ; + heparinSyringePump ( mHeparinSyringePump ); + } + else if ( ischemicalDisinfection (category, group, key) ) { + bool mChemicalDisinfection; + mChemicalDisinfection = _Settings.value(category, group, key).toBool (); + keyValue[key] = mChemicalDisinfection ; + chemicalDisinfection ( mChemicalDisinfection ); + } else if ( isalarmVolume (category, group, key) ) { quint8 mAlarmVolume; mAlarmVolume = _Settings.value(category, group, key).toInt (); // returns 0 if fails, so no error checking needed. @@ -118,6 +188,7 @@ servicePass ( _servicePass ); alarmVolume ( _alarmVolume ); roWaterMode ( _roWaterMode ); + advancedMode( _advancedMode ); //DEBUG qDebug() << servicePass() << roWaterMode() << alarmVolume(); adjustment(true); @@ -129,18 +200,17 @@ { TKeysList keysList; for ( quint16 keyIndex = 0; keyIndex < vKeys.count(); keyIndex++ ) { - QRegularExpression regx("\\{\\s*\\d+\\s*:\\s*\\d+\\s*:\\s*\\w*\\s*:\\s*\\d*\\s*\\}"); + QRegExp regx("\\{\\s*\\d+\\s*:\\s*\\d+\\s*:\\s*\\w*\\s*:\\s*\\d*\\s*\\}"); QString key = vKeys[keyIndex]; - QRegularExpressionMatch regxMatch = regx.match(key); int replacementCount = key.count(regx); QStringList keyList; for ( int j = 0; j < replacementCount; j++ ) { int pos = key.indexOf(regx); - int len = regxMatch.captured(j).length(); + int len = regx.matchedLength(); QString blk = key.mid(pos+1, len-2); keyList += key.mid(0, pos); keyList += ""; // value placeholder - key.remove(0, pos + len); + key.remove(0, pos + regx.matchedLength()); QStringList lst = blk.split(":"); quint16 id = lst[0].toUInt(); quint16 ix = lst[1].toUInt(); @@ -162,10 +232,10 @@ return keysList; } -void VSettings::updateInstructions(const QString &vGroup, const TKeysList &vKeysList, const QVariantList &vValues) +void VSettings::updateInstructions(const QString &vGroup, const TKeysList &vKeysList, const QVariantList &vValues, const QString &vTitle) { TInstruction mInstruction; - mInstruction.location = _location; + mInstruction.title = vTitle; mInstruction.keys = vKeysList; mInstruction.values = vValues ; _instructionMap[vGroup] = mInstruction; @@ -176,12 +246,13 @@ //TODO: this function or even the structure may need to update to send less data to qml and only the updated part. TKeysList keysList = _instructionMap[vGroup].keys ; QVariantList values = _instructionMap[vGroup].values; + QString title = _instructionMap[vGroup].title; QStringList keyList; for ( const auto &keys : keysList) { keyList += keys.join(""); } QVariantMap details; - details["location"] = _location ; + details["title"] = title ; details["keys" ] = keyList ; details["values" ] = values ; _instructions[vGroup] = details ; @@ -226,47 +297,69 @@ } /*! - * \brief VSettings::isPasswordValid - * \details Validates the passed string for conforming to the - * - at least one capital letter, - * - at least one digit, - * - at least one symbol - * rule - * \param vPassword - the string to check - * \returns true if string pass conforms, false otherwise + * \brief Return whether the password has the minimum character limit + * \param[in] password password to check + * \return true if the password contains requirement */ -bool View::VSettings::isPasswordValid(const QString &vPassword) { - int minLen = 10 ; // in the SRS the max is required to be 12 which seems incorrect and I didn't set it here. - QString pla = "(?=.*[%1])" ; // positive look ahead - QString regSntnc = "^%1$" ; // regular expression sentence with has a start/end - QString regUpper = "A-Z" ; - QString regLower = "a-z" ; - QString regDigit = "0-9" ; - QString regSymbl = "!\"#$%&'()*+,\\-./:;<=>?@[\\\\\\]^_`{\\|}~"; - QString rln = "[%1]{%2,}" ; +bool View::VSettings::passwordContainsCharacterLimit(const QString &vPassword) const +{ + return vPassword.size() >= 10; +} - // "^(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{\|}~])[A-Za-z0-9!"#$%&'()*+,\-./:;<=>?@[\\\]^_`{\|}~]{10,}$" - // !"#$%&'()*+,\\-./:;<=>?@[\\\\\\]^_`{\\|}~ - QString regStr = regSntnc.arg( - pla.arg(regUpper) + - pla.arg(regLower) + - pla.arg(regDigit) + - pla.arg(regSymbl) + - rln.arg(regUpper + - regLower + - regDigit + - regSymbl) - .arg(minLen ) - ); - QRegularExpression passwordRegex(regStr); - bool ok; +/*! + * \brief Return whether the password has a upper case letter + * \param[in] password password to check + * \return true if the password contains requirement + */ +bool View::VSettings::passwordContainsUpperCase(const QString &vPassword) const +{ + static const QRegularExpression upperCaseLetter("[A-Z]"); + return vPassword.contains(upperCaseLetter); +} - //DEBUG: !"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ - //DEBUG: vPassword = "Ab0!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" - ok = passwordRegex.match(vPassword).hasMatch(); - return ok; +/*! + * \brief Return whether the password has a lower case letter + * \param[in] password password to check + * \return true if the password contains requirement + */ +bool View::VSettings::passwordContainsLowerCase(const QString &vPassword) const +{ + static const QRegularExpression lowerCaseLetter("[a-z]"); + return vPassword.contains(lowerCaseLetter); } +/*! + * \brief Return whether the password has a digit + * \param[in] password password to check + * \return true if the password contains requirement + */ +bool View::VSettings::passwordContainsDigit(const QString &vPassword) const +{ + static const QRegularExpression number("[0-9]"); + return vPassword.contains(number); +} + +bool View::VSettings::passwordContainsSymbol(const QString &vPassword) const +{ + static const QRegularExpression symbol( + QStringLiteral("[%1]").arg(QRegularExpression::escape("{}[],.<>;:'\"?/|\\`~!@#$%^&*()_-+="))); + return vPassword.contains(symbol); +} + +/*! + * \brief Return whether the password is high strength. + * \param[in] password password to check + * \return true if the password is high strength and false otherwise. + */ +bool View::VSettings::isPasswordHighStrength(const QString &vPassword) const +{ + return passwordContainsUpperCase(vPassword) && + passwordContainsLowerCase(vPassword) && + passwordContainsDigit(vPassword) && + passwordContainsSymbol(vPassword) && + passwordContainsCharacterLimit(vPassword); +} + QString View::VSettings::hashedPassword(const QString &vPassword, bool vIsService) { bool ok;