Index: sources/device/DeviceController.cpp =================================================================== diff -u -r8f4dcc80fadbccfc152b28ea09466a2ab2ee7333 -ra3eef4554f2619b7b89822e776032ce8a2b4ca1e --- sources/device/DeviceController.cpp (.../DeviceController.cpp) (revision 8f4dcc80fadbccfc152b28ea09466a2ab2ee7333) +++ sources/device/DeviceController.cpp (.../DeviceController.cpp) (revision a3eef4554f2619b7b89822e776032ce8a2b4ca1e) @@ -30,7 +30,7 @@ #include "Logger.h" #include "CloudSyncController.h" #include "ApplicationController.h" -#include "RxProfiles.h" +#include "RxProfilesController.h" #include "FileHandler.h" #include "Settings.h" #include "encryption.h" Index: sources/gui/qml/pages/ManagerStack.qml =================================================================== diff -u -r046fda9079b58d933faf0d4942c87c18bfdaa471 -ra3eef4554f2619b7b89822e776032ce8a2b4ca1e --- sources/gui/qml/pages/ManagerStack.qml (.../ManagerStack.qml) (revision 046fda9079b58d933faf0d4942c87c18bfdaa471) +++ sources/gui/qml/pages/ManagerStack.qml (.../ManagerStack.qml) (revision a3eef4554f2619b7b89822e776032ce8a2b4ca1e) @@ -176,47 +176,13 @@ model: _managerHome.treatmentFields[rxItem.index] delegate: RxProfileComponent{ // id: _comp1 - title : qsTr(modelData.title)//qsTr(rxItem.param1) + title : qsTr(modelData.title) height : 370 - (100 + Variables.defaultMargin * 2) width : parent.width / 10 - 5 - value : modelData.value//rxItem.value1 - unitText : modelData.units//rxItem.unit1 + value : modelData.value + unitText : modelData.units } } - - Repeater { - model: _managerHome.treatmentFields[rxItem.index] //10 - delegate: - Rectangle{ - width: parent.width / 10 - 5 - height: 370 - (100 + Variables.defaultMargin * 2) - color: "green" - } - Column { - anchors.centerIn: parent - spacing: 2 - - Text { - text: modelData.title - font.bold: true - visible: modelData.title !== "" - } - - Text { - text: modelData.value - font.pixelSize: 14 - color: "white" - visible: modelData.value !== "" - } - - Text { - text: modelData.units - font.pixelSize: 12 - color: "lightgray" - visible: modelData.units !== "" - } - } - } } Text { text: 'Last Modified: ' + rxItem.number @@ -228,8 +194,6 @@ } } } - -// PlaceHolderText {screenName: qsTr("Rx Profiles")} } onVisibleChanged: { Index: sources/model/rxmanager/MRxProfilesData.cpp =================================================================== diff -u --- sources/model/rxmanager/MRxProfilesData.cpp (revision 0) +++ sources/model/rxmanager/MRxProfilesData.cpp (revision a3eef4554f2619b7b89822e776032ce8a2b4ca1e) @@ -0,0 +1,29 @@ +/*! + * + * Copyright (c) 2022-2025 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file MRxProfilesData.cpp + * \author (last) Dara Navaei + * \date (last) 27-Feb-2024 + * \author (original) Michael Garthwaite + * \date (original) 23-Feb-2022 + * + */ +#include "MRxProfilesData.h" + +using namespace Model; + + +/*! + * \brief MRxProfilesData::data + * \details Provides model's Data from the received messages data values + * \return Data + */ +MRxProfilesData::Data MRxProfilesData::data() const{ + Data data; + data.rxProfileContent = _data; + return data; +} Index: sources/model/rxmanager/MRxProfilesData.h =================================================================== diff -u --- sources/model/rxmanager/MRxProfilesData.h (revision 0) +++ sources/model/rxmanager/MRxProfilesData.h (revision a3eef4554f2619b7b89822e776032ce8a2b4ca1e) @@ -0,0 +1,105 @@ +/*! + * + * Copyright (c) 2022-2025 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file MRxProfilesData.h + * \author (original) Tiffany Mejia + * \date (original) 07-May-2025 + * + */ +#pragma once + + +// Qt +#include + +// Project +#include "MAbstract.h" +#include "types.h" + +// forward declarations +class tst_models; + +namespace Model { + +/*! + * \brief The MRxProfilesData class + * \details The Rx Profiles data model + * + */ + + +enum RxProfilesIndex { + eBloodFlowRate , + eDialysateFlowRate , + eTreatmentDuration , + eAcidConcentrateType , + eBicarbonateConcentrateType , + eDialysateTemperature , + eDialyzerType , + eHeparinConcentration , + eHeparinBolusVolume , + eHeparinDispenseRate , + eHeparinStop , + eVitalSigns , + eRxContentIndexCount , // Mark end of rx profile content + eProfileName = eRxContentIndexCount , + eFavorite , + eLastModifiedDate , + eRecentlyUsedDate , + eRxProfilesIndexCount +}; + +const QStringList _titles { + "Qb" , // eBloodFlowRate + "Qd" , // eDialysateFlowRate + "Dur" , // eTreatmentDuration + "AC" , // eAcidConcentrateType + "Bicarb" , // eBicarbonateConcentrateType + "dT" , // eDialysateTemperature + "Dialyzer" , // eDialyzerType + "UFHConc" , // eHeparinConcentration + "UFHVol" , // eHeparinBolusVolume + "UFHRate" , // eHeparinDispenseRate + "UFHStop" , // eHeparinStop + "VS" , // eVitalSigns +}; + +static const QStringList _units { + "mL/min" , // eBloodFlowRate + "mL/min" , // eDialysateFlowRate + "min" , // eTreatmentDuration + "" , // eAcidConcentrateType + "" , // eBicarbonateConcentrateType + "C" , // eDialysateTemperature + "" , // eDialyzerType + "IU/mL" , // eHeparinConcentration + "mL" , // eHeparinBolusVolume + "mL/hr" , // eHeparinDispenseRate + "min" , // eHeparinStop + "min" , // eVitalSigns +}; + +class MRxProfilesData { + + +public: + + static const QStringList titles () { return _titles ; } + static const QStringList units () { return _units ; } + + + QStringList _data; + struct Data + { + QStringList rxProfileContent; + }; + + Data data ( ) const ; + +}; +} +typedef Model::MRxProfilesData::Data RxProfilesData; Fisheye: Tag a3eef4554f2619b7b89822e776032ce8a2b4ca1e refers to a dead (removed) revision in file `sources/storage/RxProfiles.cpp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag a3eef4554f2619b7b89822e776032ce8a2b4ca1e refers to a dead (removed) revision in file `sources/storage/RxProfiles.h'. Fisheye: No comparison available. Pass `N' to diff? Index: sources/storage/RxProfilesController.cpp =================================================================== diff -u --- sources/storage/RxProfilesController.cpp (revision 0) +++ sources/storage/RxProfilesController.cpp (revision a3eef4554f2619b7b89822e776032ce8a2b4ca1e) @@ -0,0 +1,346 @@ +/*! + * + * Copyright (c) 2021-2024 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file RxProfiles.cpp + * \author (last) Behrouz NematiPour + * \date (last) 13-Mar-2024 + * \author (original) Behrouz NematiPour + * \date (original) 04-May-2021 + * + */ +#include "RxProfilesController.h" + +// Qt +#include + +// Project +#include "StorageGlobals.h" +#include "FileHandler.h" +#include "ApplicationController.h" +#include "Logger.h" +#include "Settings.h" +#include "DeviceController.h" +#include "MRxProfilesData.h" + +using namespace Storage; + +#define NONE "N/A" +#define FLOAT3 0,'f',3 +#define ADDTITLE(vTITLE) logContent += QString("[%1]\n").arg(vTITLE) +#define ADDALINE(vTEXT ) logContent += QString("%1\n" ).arg(vTEXT ) +/* +#define ADDTOLOG( vINDEX ) index = vINDEX; logContent += title(index) + _sep + value(index) + _sep + unit(index) + "\n"; +#define ADDTOLOG_MT(vINDEX, vVALUE ) \ + index = vINDEX; \ + logContent += title(index) + _sep + \ + ( value(index).trimmed().isEmpty() ? vVALUE : value(index) ) + _sep + \ + unit(index) + "\n"; +*/ +/*! + * \brief RxProfiles::RxProfiles + * The constructor to initial the Treatment Log + * \param parent + */ +RxProfiles::RxProfiles(QObject *parent) : QObject(parent) { + initConnections(); +} + + +/*! \brief Connection Initializer + \details All the class signal/slot connections are defined here. +*/ +void RxProfiles::initConnections() { + + connect(&_exportWatcher , SIGNAL(finished()), + this , SLOT(onExport())); + + connect(&_saveWatcher , SIGNAL(finished()), + this , SLOT(onSave ())); + + connect(&_importWatcher , SIGNAL(finished()), + this , SLOT(onImport())); + + connect(&_DeviceController , SIGNAL(didReadFilesList(const QFileInfoList &)), + this , SLOT(onReceieveRxProfileList(const QFileInfoList &))); +// connect(&_DeviceController , SIGNAL(didReadFilesList(const QFileInfoList &)), +// this , SIGNAL(didRxProfileList(const QFileInfoList &))); +} + +void RxProfiles::doInitRxProfiles() +{ + emit didFilesList(rxProfilesPath(), { QString("*.%1").arg(_rxProfiles) }); +} + +QString RxProfiles::rxProfilesPath() +{ + if(_rxProfilesPath.trimmed().isEmpty()){ + _rxProfilesPath = QString("%1%2") + .arg(Storage::Rx_Folder_Base ) // TODO: Adjust to be real base path for RX + .arg(Storage::Rx_Folder_Profiles ); + } + + LOG_DEBUG(QString("Rx Profile folder has been set to %1" ).arg(_rxProfilesPath )); + + return _rxProfilesPath; +} + + + +RxProfilesData RxProfiles::initModel(const QFileInfo &rxProfile) +{ + RxProfilesData rxData; + QSettings rxSettings(rxProfile.absoluteFilePath(), QSettings::IniFormat); + for (int i = 0; i < Model::RxProfilesIndex::eRxContentIndexCount; i++){ + QString rxTitle = Model::MRxProfilesData::titles()[i]; + if ( rxSettings.contains(rxTitle) ){ + rxData.rxProfileContent.append(rxSettings.value(rxTitle).toString()); + } + else{ + qDebug() << "No Choochoob" << rxSettings.allKeys(); + } + } + //Order of the below does matter to match the enum index + rxData.rxProfileContent.append(rxProfile.baseName().replace("_", " ")); //eProfileName + rxData.rxProfileContent.append("false"); + rxData.rxProfileContent.append(rxProfile.lastModified().date().toString("MM-dd-yyyy")); + + return rxData; +} + +//void RxProfiles::readFavorite(const QString &vFile) +//{ +// QString content; +// QFileInfo rxProfile(vFile); +// Storage::FileHandler::read(vFile, content); +// QStringList lines = content.split('\n'); +// for ( const QString &line : lines ) { +// QStringList fields = line.split(','); +// if ( fields.count() >= Role::eCount ) { +// QString key = QString(fields[0].trimmed()); +// QString value = fields.mid(1).join(", ").trimmed(); // TODO: Remove comma adjustment when Acid and Bicarb structure change + +// //TODO: Add to model structure and add error checking +// _values[_rxKeyMap[key]] = QString(value); +// } +// } +// _values[eProfileName] = rxProfile.baseName(); +// _values[eFavorite] = false; // TODO: add conf file read here +// _values[eLastModifiedDate] = rxProfile.lastModified().date().toString("MM-dd-yyyy"); + +//} + +// ----- Save +/*! + * \brief RxProfiles::doSave + * The save slot to be exposed to the UI to be able to request for save + */ +void RxProfiles::doSave(const QString &fileName) +{ + if (_saveWatcher.isRunning()) return; + isIdle(false); + saveLogConcurrent(fileName); +} + +/*! + * \brief RxProfiles::saveLogConcurrent + * The treatment log save which is using a thread pool to run the save process. + */ +void RxProfiles::saveLogConcurrent(const QString &fileName) +{ + LOG_DEBUG("Save Treatment Log Started"); + QFuture mFuture = QtConcurrent::run(this, &RxProfiles::saveLog, fileName); + _saveWatcher.setFuture(mFuture); +} + +/*! + * \brief RxProfiles::saveLog + * The actual treatment log save function which does the save into the Prescription log + * \return true on successful save and false otherwise. + */ +bool RxProfiles::saveLog(const QString &fileName) +{ +// _lastTxInfo.clear(); + bool ok = (unsigned)_values.count() >= Model::RxProfilesIndex::eRxProfilesIndexCount; + if (!ok) return false; + + +// QString logContent ; +// QString csv = "%1" + _sep ; +// QString end = "%1" ; +// uint index = 0 ; + +// ADDTITLE("Treatment Parameters" ); +// ADDTOLOG( eTreatmentDuration ); +// ADDTOLOG( eBloodFlowRate ); +// ADDTOLOG( eDialysateFlowRate ); +// ADDTOLOG( eAcidConcentrateType ); +// ADDTOLOG( eBicarbonateConcentrateType ); +// ADDTOLOG( eDialysateTemperature ); +// ADDTOLOG( eDialyzerType ); +// ADDTOLOG( eHeparinConcentration ); +// ADDTOLOG( eHeparinBolusVolume ); +// ADDTOLOG( eHeparinDispenseRate ); +// ADDTOLOG( eHeparinStop ); + +// //DEBUG qDebug() << _lastTxInfo.mFileName; +// ok = Storage::FileHandler::makeFolder(_rxProfilesPath); +// if ( ! ok ) { LOG_DEBUG(QString("Cannot create folder %1").arg(_rxProfilesPath )); return ok; } +// ok = Storage::FileHandler::write(fileName, logContent, false); + if ( ! ok ) { LOG_DEBUG(QString("Cannot write to file %1").arg(fileName)); return ok; } + + return ok; +} + +/*! + * \brief RxProfiles::onSave + * The private save slot which is called after the save process is finished saving. + */ +void RxProfiles::onSave() +{ + LOG_DEBUG(QString("Save PresciptionLog Log Ended: %1").arg(_saveWatcher.result())); + isIdle(true); +} + +// ----- Export +/*! + * \brief RxProfiles::doExport + * The export treatment log slot to be exposed to the UI to be able to request for the export. + */ +void RxProfiles::doExport() +{ + if (_exportWatcher.isRunning()) return; + isIdle(false); + exportLogConcurrent(); +} + +/*! + * \brief RxProfiles::exportLogConcurrent + * The treatment log export which is using a thread pool to run the save process. + */ +void RxProfiles::exportLogConcurrent() +{ + LOG_DEBUG("Export Prescription Log Started"); + QFuture mFuture = QtConcurrent::run(this, &RxProfiles::exportLog); + _exportWatcher.setFuture(mFuture); +} + +/*! + * \brief RxProfiles::exportLog + * \details The actual treatment log export function which does the export of the treatment log into the USB drive. + * \return true on successful export. + */ +bool RxProfiles::exportLog() +{ + bool ok = true; + QString status = ""; + QString dstPath = Storage::USB_Mount_Point ; + dstPath += Storage::Rx_Folder_Profiles ; + QString srcFile = "meow.txr" ;//TODO: adjust for filename variable + QString srcFileName = QFileInfo(srcFile).fileName() ; + QString dstFile = dstPath + srcFileName; + // HERE: expose to the UI dialog as the rejection/notification result + if ( ! Storage::FileHandler::makeFolder ( dstPath ) ) { status = QString( "Couldn't create folder on USB drive to export TxLog" ); ok = false; goto lOut; } + if ( ! QFileInfo::exists ( srcFile ) ) { status = QString( "Prescription Log '%1' doesn't exist" ).arg( srcFile ); ok = false; goto lOut; } + if ( QFileInfo::exists ( dstFile ) ) { status = QString( "Prescription Log '%1' already exists" ).arg( dstFile ); ok = false; goto lOut; } + if ( ! QFile::copy (srcFile, dstFile ) ) { status = QString( "Unable to Export RxLog '%1' to '%2'" ).arg( srcFile ).arg( dstFile ); ok = false; goto lOut; } + +lOut: + if ( ! ok ) { + LOG_DEBUG(status); // The log debug order in this block is by design + status = "Unable to export Prescription log '" + srcFileName +"'"; + } + else { + status = "Prescription log '" + srcFileName + "' exported successfully"; + LOG_APPED_UI(status); + } + + emit didNotification(status); + return ok; +} + +/*! + * \brief RxProfiles::onExport + * The private export slot which is called after the export process is finished exporting. + */ +void RxProfiles::onExport() +{ + LOG_DEBUG(QString("Export Prescription Log Ended: %1").arg(_exportWatcher.result())); + isIdle(true); +} + + +// ----- Import +/*! + * \brief RxProfiles::doImport + * The export treatment log slot to be exposed to the UI to be able to request for the import. + */ +void RxProfiles::doImport() +{ + if (_importWatcher.isRunning()) return; + isIdle(false); + importLogConcurrent(); +} + +/*! + * \brief RxProfiles::importLogConcurrent + * The treatment log import which is using a thread pool to run the save process. + */ +void RxProfiles::importLogConcurrent() +{ + LOG_DEBUG("Import Prescription Log Started"); + QFuture mFuture = QtConcurrent::run(this, &RxProfiles::importLog); + _importWatcher.setFuture(mFuture); +} + +/*! + * \brief RxProfiles::importLog + * \details The actual treatment log import function which does the import of the treatment log into the USB drive. + * \return true on successful import. + */ +bool RxProfiles::importLog() +{ + bool ok = true; +// QString srcFile = Storage::USB_Mount_Point + Storage::Log_Folder_Rx; +// QString dstPath = _rxProfilesPath ; +// QString status = ""; + // TODO: implement import + return ok; +} + +/*! + * \brief RxProfiles::onImport + * The private import slot which is called after the import process is finished importing. + */ +void RxProfiles::onImport() +{ + LOG_DEBUG(QString("Import Prescription Log Ended: %1").arg(_exportWatcher.result())); + isIdle(true); +} + +void RxProfiles::onReceieveRxProfileList(const QFileInfoList &vRxProfileList) +{ + QList vRxProfileDataList; + for (const QFileInfo fileInfo:vRxProfileList){ + vRxProfileDataList.append(initModel(fileInfo)); + } + emit didRxProfileList(vRxProfileList); //TODO: change to vRxProfileDataList +} + +/*! + * \brief RxProfiles::filelimitReached + * The actual function that checks if RX file limit has been reached for Duplicate, Add, and import events + */ +bool RxProfiles::fileLimitReached() +{ QDir RxProfilesDir(_rxProfilesPath); + int fileCount = RxProfilesDir.count(); + if (fileCount != _RxLimit){ return false; } + LOG_DEBUG(QString("Rx Limit has been reached")); + return true; +} + + + Index: sources/storage/RxProfilesController.h =================================================================== diff -u --- sources/storage/RxProfilesController.h (revision 0) +++ sources/storage/RxProfilesController.h (revision a3eef4554f2619b7b89822e776032ce8a2b4ca1e) @@ -0,0 +1,122 @@ +/*! + * + * Copyright (c) 2021-2024 Diality Inc. - All Rights Reserved. + * \copyright + * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN + * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. + * + * \file RxProfiles.h + * \author (last) Behrouz NematiPour + * \date (last) 13-Mar-2024 + * \author (original) Behrouz NematiPour + * \date (original) 04-May-2021 + * + */ +#pragma once + +// Qt +#include +#include +#include + +// Project +#include "main.h" // Doxygen : do not remove +#include "Logger.h" +#include "MRxProfilesData.h" + +// define +#define _RxProfilesController Storage::RxProfiles::I() //TODO: Change name to be a controller + +namespace Storage { + + +/*! + * \brief The RxProfiles class + * This class is the controller which converts/saves/exports model to be used in the UI/RxProfiles + */ +class RxProfiles : public QObject +{ + Q_OBJECT + + const int _interval = 1000; // 1s + const int _pendingInterval= 60 ; // 1m + int _pendingCounter = 0 ; // + const int _RxLimit = 10 ; // SRS- + + const QString _sep = ","; + + QString _rxProfilesPath; + const char* _rxProfiles = "rxp"; + + QFutureWatcher _saveWatcher; + QFutureWatcher _exportWatcher; + QFutureWatcher _importWatcher; + + QString _dateFormat = "yyyy/MM/dd" ; + QString _timeFormat = "HH:mm" ; + QString _datetimeFormat = _dateFormat + " " + _timeFormat; + + enum Role { + eTitle, + eValue, + eCount + }; + + QString string(quint8 vIndex , const QStringList &vStringList) const { + QString str = ""; + if (vIndex < vStringList.count()) { + str = vStringList[vIndex]; + str.remove(_sep); + } + return str; + } + + QString value(quint8 vIndex) const { return string(vIndex, _values );} + + // Lists + QStringList _values; + + void initConnections(); + + bool saveLog (const QString &fileName); + void saveLogConcurrent (const QString &fileName); + bool exportLog (); + void exportLogConcurrent(); + bool importLog (); + void importLogConcurrent(); + + bool fileLimitReached (); + + + NOTIFIER(isIdle) + SINGLETON(RxProfiles) + +//protected: +// void timerEvent(QTimerEvent *) override; + +public: + RxProfilesData initModel(const QFileInfo &rxProfile); + void checkFavorite(const QFileInfo &rxProfile); + + QString rxProfilesPath () ; + +private slots: + void onSave (); + void onExport (); + void onImport (); + void onReceieveRxProfileList ( const QFileInfoList &vRxProfileList ); + +public slots: + // void doFavorite (); + void doSave (const QString &fileName); + void doExport (); + void doImport (); + void doInitRxProfiles(); +signals: + void didNotification ( const QString &vNotification ); + + void didFilesList ( const QString &vRxProfileList , const QStringList &vRxProfile ); + void didRxProfileList ( const QFileInfoList &vRxProfileList ); +}; + +} Index: sources/view/VRxProfiles.cpp =================================================================== diff -u -r4ac90c09e5697ef0239364a888191b7aacf19448 -ra3eef4554f2619b7b89822e776032ce8a2b4ca1e --- sources/view/VRxProfiles.cpp (.../VRxProfiles.cpp) (revision 4ac90c09e5697ef0239364a888191b7aacf19448) +++ sources/view/VRxProfiles.cpp (.../VRxProfiles.cpp) (revision a3eef4554f2619b7b89822e776032ce8a2b4ca1e) @@ -19,7 +19,7 @@ // Project #include "ApplicationController.h" -#include "RxProfiles.h" +#include "RxProfilesController.h" #include "FileHandler.h" #include "MsgDefs.h" #include "TreatmentLog.h" Index: sources/view/VRxProfiles.h =================================================================== diff -u -r4ac90c09e5697ef0239364a888191b7aacf19448 -ra3eef4554f2619b7b89822e776032ce8a2b4ca1e --- sources/view/VRxProfiles.h (.../VRxProfiles.h) (revision 4ac90c09e5697ef0239364a888191b7aacf19448) +++ sources/view/VRxProfiles.h (.../VRxProfiles.h) (revision a3eef4554f2619b7b89822e776032ce8a2b4ca1e) @@ -47,12 +47,12 @@ PROPERTY(QStringList , rxProfilesList , {}) - Q_PROPERTY(MListModel* rxProfiles READ rxProfiles NOTIFY alarm_AlarmIDChanged) +// Q_PROPERTY(MListModel* rxProfiles READ rxProfiles NOTIFY alarm_AlarmIDChanged) VIEW_DEC_CLASS(VRxProfiles) private: - MListModel* rxProfiles () { return &_rxProfilesModel; } ; - MListModel _rxProfilesModel; +// MListModel* rxProfiles () { return &_rxProfilesModel; } ; +// MListModel _rxProfilesModel; signals: