/*! * * 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; }