Index: denali.pro =================================================================== diff -u -rff9c1810af33c01951d0639a48e9f6eb7152fa15 -r3c859e027546fa42ef215eb0d0d09e3f2bb953ab --- denali.pro (.../denali.pro) (revision ff9c1810af33c01951d0639a48e9f6eb7152fa15) +++ denali.pro (.../denali.pro) (revision 3c859e027546fa42ef215eb0d0d09e3f2bb953ab) @@ -288,6 +288,7 @@ sources/view/settings/VAdjustmentDGCleaningUsage.h \ sources/view/settings/VDuetRoWaterDG.h \ sources/view/settings/VCloudSync.h \ + sources/view/settings/VLogFileListModel.h \ \ # ---------- Views - Alarm sources/view/hd/alarm/VAlarmStatus.h \ sources/view/hd/alarm/VAlarmActiveList.h \ @@ -553,6 +554,7 @@ sources/view/settings/VDuetRoWaterDG.cpp \ sources/view/settings/VCloudSync.cpp \ sources/view/settings/VAdjustmentDGCleaningUsage.cpp \ + sources/view/settings/VLogFileListModel.cpp \ \ # ---------- Views - HD - Adjustment sources/view/VAdjustmentResponseBase.cpp \ \ # ---------- Views - HD - Adjustment - common Index: sources/gui/GuiGlobals.cpp =================================================================== diff -u -r159f2bb0317c7c3c0336e4cb80c7fef3f87e329a -r3c859e027546fa42ef215eb0d0d09e3f2bb953ab --- sources/gui/GuiGlobals.cpp (.../GuiGlobals.cpp) (revision 159f2bb0317c7c3c0336e4cb80c7fef3f87e329a) +++ sources/gui/GuiGlobals.cpp (.../GuiGlobals.cpp) (revision 3c859e027546fa42ef215eb0d0d09e3f2bb953ab) @@ -49,6 +49,7 @@ #include "VBluetooth.h" #include "VDuetRoWaterDG.h" #include "VCloudSync.h" +#include "VLogFileListModel.h" // states data #include "VHDOperationModeData.h" #include "VPreTreatmentStatesData.h" Index: sources/gui/qml/main.qml =================================================================== diff -u -rb9d5efd980be633f5d0bd92cc76295f3a0669db4 -r3c859e027546fa42ef215eb0d0d09e3f2bb953ab --- sources/gui/qml/main.qml (.../main.qml) (revision b9d5efd980be633f5d0bd92cc76295f3a0669db4) +++ sources/gui/qml/main.qml (.../main.qml) (revision 3c859e027546fa42ef215eb0d0d09e3f2bb953ab) @@ -46,6 +46,8 @@ import VBluetooth 0.1 import VDuetRoWaterDG 0.1 import VCloudSync 0.1 +import VSDCardLogFileListModel 0.1 +import VUSBLogFileListModel 0.1 // States views import VHDOperationMode 0.1 @@ -147,6 +149,8 @@ VBluetooth { id: vBluetooth } VDuetRoWaterDG { id: vDuetRoWaterDG } VCloudSync { id: vCloudSync } + VSDCardLogFileListModel { id: vSDCardListModel } + VUSBLogFileListModel { id: vUSBListModel } // ---- States VHDOperationMode { id: vHDOperationMode Index: sources/gui/qml/pages/settings/SettingsExportLogs.qml =================================================================== diff -u -r80b5e8f1ebb90c03c37d90d90cd2da3bd95d6803 -r3c859e027546fa42ef215eb0d0d09e3f2bb953ab --- sources/gui/qml/pages/settings/SettingsExportLogs.qml (.../SettingsExportLogs.qml) (revision 80b5e8f1ebb90c03c37d90d90cd2da3bd95d6803) +++ sources/gui/qml/pages/settings/SettingsExportLogs.qml (.../SettingsExportLogs.qml) (revision 3c859e027546fa42ef215eb0d0d09e3f2bb953ab) @@ -39,19 +39,11 @@ */ SettingsBase { id: _root itemIndex : SettingsStack.ExportLogs - - //////////////////////////////////////////////////////////////////////////////// - // FIXME: The model being used here is the QML FileListModel. // - // This model is so limited and do not update well. // - // This model definitely has to be replaced with a C++ one, // - // like the other MVC classes we have. // - //////////////////////////////////////////////////////////////////////////////// - readonly property string sdcLabel : qsTr("SD-Card") readonly property string devUnit : "MB" // no translation readonly property string devUnitLabel : " (" + devUnit + ")\n" // no translation readonly property string usbLabel : qsTr("USB Drive") - readonly property int headetRowHight : 50 + readonly property int headerRowHight : 50 readonly property int typeIndexApplication : 0 readonly property int typeIndexService : 1 @@ -62,25 +54,7 @@ readonly property string typeLabelTreatment : qsTr("Treatment" ) property bool isDevice : true //false // it has to be true to make it work on the devices. - readonly property string typePathClr : "" - readonly property string typePathPrefix : "file://" - readonly property string typePathSrc : typePathPrefix + (isDevice ? "/media/sd-card" : "/home/denali/Desktop/sd-card" ) - readonly property string typePathDst : typePathPrefix + (isDevice ? "/media/usb" : "/home/denali/Desktop/usb-disk") - readonly property string typeFolderApplication : "/log" - readonly property string typeFolderService : "/service" - readonly property string typeFolderTreatment : "/treatment" - readonly property string typeFolderApplicationSrc : typePathSrc + typeFolderApplication - readonly property string typeFolderApplicationDst : typePathDst + typeFolderApplication - readonly property string typeFolderServiceSrc : typePathSrc + typeFolderService - readonly property string typeFolderServiceDst : typePathDst + typeFolderService - readonly property string typeFolderTreatmentSrc : typePathSrc + typeFolderTreatment - readonly property string typeFolderTreatmentDst : typePathDst + typeFolderTreatment - - readonly property var typeFilterAll : ["*"] - readonly property var typeFilterClr : [] - - confirmVisible : false function refreshModels() { @@ -106,37 +80,7 @@ refreshModels() } - property bool isUpdatePanels: false - function updatePanels (vIndex) { - isUpdatePanels = true - - _GuiView.doExportListRemove() - _sdcFolderColumn.clearModel() - _usbFolderColumn.clearModel() - - switch (vIndex) { - case typeIndexApplication: - _sdcFolderColumn.currentTypeFolderApplication = typeFolderApplicationSrc - _usbFolderColumn.currentTypeFolderApplication = typeFolderApplicationDst - break - case typeIndexService: - _sdcFolderColumn.currentTypeFolderApplication = typeFolderServiceSrc - _usbFolderColumn.currentTypeFolderApplication = typeFolderServiceDst - break - case typeIndexTreatment: - _sdcFolderColumn.currentTypeFolderApplication = typeFolderTreatmentSrc - _usbFolderColumn.currentTypeFolderApplication = typeFolderTreatmentDst - break - } - - _sdcFolderColumn.updateModel() - _usbFolderColumn.updateModel() - - isUpdatePanels = false - } - Connections { target: _GuiView - function onSdIsReadyChanged ( vValue ) { _root.updatePanels() } function onDidExportStat ( vIndex, vFileName, vPercent ) { _sdcFolderView.positionViewAtIndex(vIndex, ListView.Center) } function onDidUSBDriveUmount ( ) { _usbFolderColumn. clearModel ( ) } function onDidUSBDriveRemove ( ) { _usbFolderColumn. clearModel ( ) } @@ -151,7 +95,7 @@ anchors.right : _root.right anchors.top : _root.top anchors.margins : Variables.headerButtonsMargin - enabled : _GuiView.usbIsReady && !_GuiView.exportRunning && ! isUpdatePanels + enabled : _GuiView.usbIsReady && !_GuiView.exportRunning } Row { id : _contentRect @@ -180,15 +124,20 @@ Row { id : _logTypeRow anchors.left : parent.left width : parent.width - height : _root.headetRowHight + height : _root.headerRowHight spacing : _logTypeCombo.width - _logTypeExportButton.width // FIXME: This combobox needs to be a global Component ComboBox { id : _logTypeCombo onCurrentIndexChanged : { - _root.updatePanels(currentIndex) +// _root.updatePanels(currentIndex) + + _GuiView.doExportListRemove() + + vUSBListModel.updateFolderWithType(currentIndex) + vSDCardListModel.updateFolderWithType(currentIndex) } - enabled : ! _GuiView.exportRunning && ! isUpdatePanels + enabled : ! _GuiView.exportRunning currentIndex : 0 displayText : currentText font.pixelSize : Fonts.fontPixelTextRectExtra @@ -298,31 +247,19 @@ height : Variables.touchRectHeight radius : Variables.touchRectRadius border.width : Variables.borderWidth - enabled : _GuiView.usbIsReady && !_GuiView.exportRunning && ! isUpdatePanels + enabled : _GuiView.usbIsReady && !_GuiView.exportRunning onClicked : doExport() } } Column { id : _sdcFolderColumn - property string currentTypeFolderApplication : _root.typeFolderApplicationSrc - - // FIXME: there has to be a View for this, and the timer should be removed and an event driven signal should be implemented there. - function updateModel() { - _sdcFolderModel.folder = currentTypeFolderApplication // FIXME: there has to be a View for this which also get changed by log type. - _sdcFolderModel.nameFilters = _root.typeFilterAll - } - function clearModel() { - _sdcFolderModel.folder = _root.typePathClr - _sdcFolderModel.nameFilters = _root.typeFilterClr - } - spacing : 5 width : _contentRect.columnWidthFolder height : parent.height anchors.verticalCenter : parent.verticalCenter Label { id : _sdcLabel - text : _root.sdcLabel + ": %1 files"/*, %2 %3"*/.arg(_sdcFolderView.visibleFileCounter) + (_GuiView.exportCount ? " [Selected: %1]".arg(_GuiView.exportCount ) : "") //.arg("__").arg(_root.dvcUnit) + text : _root.sdcLabel + ": %1 files"/*, %2 %3"*/.arg(_sdcFolderView.count) + (_GuiView.exportCount ? " [Selected: %1]".arg(_GuiView.exportCount ) : "") //.arg("__").arg(_root.dvcUnit) width : parent.width - height : _root.headetRowHight + height : _root.headerRowHight verticalAlignment : Text.AlignVCenter } Rectangle { id : _sdcFolderRectangle @@ -340,27 +277,13 @@ } ListView { id : _sdcFolderView - property int visibleFileCounter : 0 - enabled : !_GuiView.exportRunning && ! isUpdatePanels + enabled : !_GuiView.exportRunning clip : true anchors.fill : parent anchors.margins : 10 anchors.leftMargin : 5 anchors.rightMargin : 5 spacing : 3 - FolderListModel { id : _sdcFolderModel - onStatusChanged: { - // onFolderChanged does not get emitted when switching folders, but status change does. - // Reset the displayed file counter when the state of the model is null - if (_sdcFolderModel.status == FolderListModel.Null) - { - _sdcFolderView.visibleFileCounter = 0 - } - } - showDirs : false - sortField : FolderListModel.Time - folder : _sdcFolderColumn.currentTypeFolderApplication // FIXME: there has to be a View for this which also get changed by log type. - } Component { id : _sdcFileDelegate ProgressBar { id : _sdcItemBackground @@ -375,16 +298,13 @@ : 0 onExportPercentChanged : console.log( "%", exportPercent) - property bool isShownInList : !_GuiView.isPathSymLink(_sdcFolderColumn.currentTypeFolderApplication.replace(typePathPrefix, "") + "/" + fileName) - Component.onCompleted: if ( isShownInList ) _sdcFolderView.visibleFileCounter++ - //DEBUG: onInExportListChanged: console.debug(" * ", index, inExportList) function exportListUpdate() { if (_GuiView.doExportListSelect( index ) ) { _GuiView.doExportListDelete( index ) } else { - _GuiView.doExportListInsert( index , fileName ) + _GuiView.doExportListInsert( index , filePath ) } } @@ -399,25 +319,21 @@ maximum : 100 // percent value : maximum - exportPercent - // Setting height and width to 0 when the file is not shown in the list because - // it is a symlink or other conditions - width : isShownInList ? _sdcFolderView.width : 0 - height : isShownInList ? 40 : 0 + width : _sdcFolderView.width + height : 40 bgColor : Colors.transparent color : inExportList ? Colors.borderButtonSelected : Colors.transparent radius : 5 Row { id : _sdcFileRow - // Setting height and width to 0 when the file is not shown in the list because - // it is a symlink or other conditions - width : isShownInList ? parent.width : 0 - height : isShownInList ? 40 : 0 + width : parent.width + height : 40 leftPadding : 5 Text { id : _sdcFileNameText x : 2 clip : true - width : isShownInList ? (_contentRect.columnWidthFileName - 2) : 0 + width : _contentRect.columnWidthFileName - 2 text : fileName color : Colors.textMain font.pixelSize : Fonts.fontPixelTextRectExtra @@ -426,12 +342,12 @@ } Rectangle { id : _sdcColumnVerticalLine color : Colors.borderButtonUnselected - width : isShownInList ? 1 : 0 + width : 1 height : parent.height + _usbFolderColumn.spacing } Text { id : _sdcFileSizeText clip : true - width : isShownInList ? _contentRect.columnWidthFileSize : 0 + width : _contentRect.columnWidthFileSize text : Variables.sizeConverted( fileSize, 1000, 3) color : Colors.textMain font.pixelSize : Fonts.fontPixelTextRectExtra @@ -441,23 +357,19 @@ } } } - model : _sdcFolderModel + model : vSDCardListModel delegate : _sdcFileDelegate } } } Column { id : _usbFolderColumn - property string currentTypeFolderApplication : _root.typeFolderApplicationDst - // FIXME: there has to be a View for this, and the timer should be removed and an event driven signal should be implemented there. function updateModel() { - _usbFolderModel.folder = currentTypeFolderApplication // FIXME: there has to be a View for this which also get changed by log type. - _usbFolderModel.nameFilters = _root.typeFilterAll + vUSBListModel.refreshModel() } function clearModel() { - _usbFolderModel.folder = _root.typePathClr - _usbFolderModel.nameFilters = _root.typeFilterClr + vUSBListModel.removeAllRows() } // FIXME: there has to be a View for this, and the timer should be removed and an event driven signal should be implemented there. @@ -486,9 +398,9 @@ anchors.verticalCenter : parent.verticalCenter Label { id : _usbLabel - text : _root.usbLabel + ": %1 files"/*", %2 %3"*/.arg(_usbFolderModel.count)//.arg("__").arg(_root.dvcUnit) + text : _root.usbLabel + ": %1 files"/*", %2 %3"*/.arg(_usbFolderView.count)//.arg("__").arg(_root.dvcUnit) width : parent.width - height : _root.headetRowHight + height : _root.headerRowHight verticalAlignment : Text.AlignVCenter } @@ -514,12 +426,6 @@ anchors.leftMargin : 5 anchors.rightMargin : 5 - - FolderListModel { id : _usbFolderModel // FIXME: I don't like this model, it's too lazy and I don't have control over it. There has to be a Model for this. - showDirs : false - sortField : FolderListModel.Time - folder : _usbFolderColumn.currentTypeFolderApplication - } Component { id : _usbFileDelegate Row { id : _usbFileRow width : _usbFolderView.width @@ -549,7 +455,7 @@ } } } - model : _usbFolderModel + model : vUSBListModel delegate : _usbFileDelegate } } Index: sources/gui/qml/pages/settings/SettingsStack.qml =================================================================== diff -u -r689177edf29dee6f10bebfed42f6bbadeb7ce8a8 -r3c859e027546fa42ef215eb0d0d09e3f2bb953ab --- sources/gui/qml/pages/settings/SettingsStack.qml (.../SettingsStack.qml) (revision 689177edf29dee6f10bebfed42f6bbadeb7ce8a8) +++ sources/gui/qml/pages/settings/SettingsStack.qml (.../SettingsStack.qml) (revision 3c859e027546fa42ef215eb0d0d09e3f2bb953ab) @@ -214,6 +214,8 @@ break case SettingsStack.ExportLogs: + vSDCardListModel.doInit() + vUSBListModel.doInit() push( _settingsExportLogs ) break Index: sources/storage/Logger.cpp =================================================================== diff -u -r611bbf4dcba67768db87cf30f21fd2db788f677d -r3c859e027546fa42ef215eb0d0d09e3f2bb953ab --- sources/storage/Logger.cpp (.../Logger.cpp) (revision 611bbf4dcba67768db87cf30f21fd2db788f677d) +++ sources/storage/Logger.cpp (.../Logger.cpp) (revision 3c859e027546fa42ef215eb0d0d09e3f2bb953ab) @@ -645,8 +645,9 @@ it.next(); // qDebug() << it.key() << it.value() << mSource << mDestination; auto index = it.key (); - auto filename = it.value(); - result = FileHandler::copyFile(mSource, mDestination + _logBasePathNames[vLogType], filename, ¬ifier, index); + auto filePath = it.value(); + QFileInfo file(filePath); + result = FileHandler::copyFile(file.path()+"/", mDestination + _logBasePathNames[vLogType], file.fileName(), ¬ifier, index); } } return result >= 0; // refer to QProcess::execute(hit F1 on execute) doc. Index: sources/storage/Logger.h =================================================================== diff -u -rec31f94081864aec8b48a3cfa1e0aea80619714c -r3c859e027546fa42ef215eb0d0d09e3f2bb953ab --- sources/storage/Logger.h (.../Logger.h) (revision ec31f94081864aec8b48a3cfa1e0aea80619714c) +++ sources/storage/Logger.h (.../Logger.h) (revision 3c859e027546fa42ef215eb0d0d09e3f2bb953ab) @@ -91,6 +91,7 @@ eLogType_Count, }; Q_ENUM(LogType) + QHash getLogBasePathNames() { return _logBasePathNames; } private: Index: sources/view/VView.h =================================================================== diff -u -r159f2bb0317c7c3c0336e4cb80c7fef3f87e329a -r3c859e027546fa42ef215eb0d0d09e3f2bb953ab --- sources/view/VView.h (.../VView.h) (revision 159f2bb0317c7c3c0336e4cb80c7fef3f87e329a) +++ sources/view/VView.h (.../VView.h) (revision 3c859e027546fa42ef215eb0d0d09e3f2bb953ab) @@ -120,6 +120,8 @@ REGISTER_TYPE( VBluetooth ) \ REGISTER_TYPE( VDuetRoWaterDG ) \ REGISTER_TYPE( VCloudSync ) \ + REGISTER_TYPE( VSDCardLogFileListModel ) \ + REGISTER_TYPE( VUSBLogFileListModel ) \ /* Alarm */ \ REGISTER_TYPE( VAlarmStatus ) \ REGISTER_TYPE( VAlarmActiveList ) \ Index: sources/view/settings/VLogFileListModel.cpp =================================================================== diff -u --- sources/view/settings/VLogFileListModel.cpp (revision 0) +++ sources/view/settings/VLogFileListModel.cpp (revision 3c859e027546fa42ef215eb0d0d09e3f2bb953ab) @@ -0,0 +1,258 @@ +/*! + * + * Copyright (c) 2021-2023 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 VLogFileListModel.cpp + * \author (last) Vy + * \date (last) 10-Aug-2023 + * \author (original) Vy + * \date (original) 10-Aug-2023 + * + */ + +// Qt +#include +#include + +// Project +#include "VLogFileListModel.h" +#include "Logger.h" +#include "StorageGlobals.h" +#include "DeviceController.h" + +using namespace View; +using namespace Storage; + +/*! + * \brief VLogFileListModel::VLogFileListModel + * Constructor of the VLogFileListModel class + */ +VLogFileListModel::VLogFileListModel(QAbstractListModel *parent) : QAbstractListModel(parent) { + initConnections(); +} + +/*! + * \brief VLogFileListModel::initConnections + * Makes the necessary connections. Called inside VIEW_DEF_CLASS + */ +void VLogFileListModel::initConnections() +{ + connect(this, SIGNAL( folderChanged(const QString &)), + this, SLOT(updateModelWithFolder(const QString &))); + + connect(this, SIGNAL( includeSubFoldersChanged(bool)), + this, SLOT( refreshModel( ))); + + // Refresh the model when the logger had triggered a log clean up + connect(&_Logger , SIGNAL( didRemoveLogs (bool)), + this , SLOT( onLogsRemoved (bool))); +} + +/*! + * \brief VLogFileListModel::doInit + * \details Initializes the view or what needs to be done + */ +void VLogFileListModel::doInit() +{ + // initialize the model with the logs from type eLogAppED + updateFolderWithType(Logger::eLogAppED); +} + +/*! + * \brief VLogFileListModel::rowCount + * Gets the number of networks + * \param parent - (QModelIndex) the parent QModelIndex + * \return (int) - the number of networks + */ +int VLogFileListModel::rowCount(const QModelIndex & parent) const +{ + Q_UNUSED(parent); + return _logFiles.count(); +} + +/*! + * \brief VLogFileListModel::data + * Returns the sd card file properties at the specified index + * \param index (QModelIndex) contains the row of data to lookup + * \param role - (int) the property index to return. See SDCardFileDataRole + * \return (QVariant) - the value for the specified network property + */ +QVariant VLogFileListModel::data(const QModelIndex & index, int role) const +{ + if (index.row() < 0 || index.row() >= _logFiles.count()) return QVariant(); + + const QFileInfo &logFile = _logFiles[index.row()]; + switch (role) + { + case FilePathRole: + return logFile.filePath(); + case FileNameRole: + return logFile.fileName(); + case FileSizeRole: + return logFile.size(); + } + + return QVariant(); +} + +/*! + * \brief VLogFileListModel::roleNames + * Translates how to access specific properties of the data for QML from the NetworkDataRole enum + * \return (QHash) - maps enums to property names + */ +QHash VLogFileListModel::roleNames() const { + QHash roles; + roles[FilePathRole] = "filePath"; + roles[FileNameRole] = "fileName"; + roles[FileSizeRole] = "fileSize"; + return roles; +} + +/*! + * \brief VLogFileListModel::removeAllRows + * Clear the model of all its data + */ +void VLogFileListModel::removeAllRows() +{ + //DEBUG qDebug()<(vType)); + break; + default: + LOG_DEBUG(QString("SD - updateFolderWithType: Invalid log type index %1").arg(vType)); + }; + + updateModelWithFolder(path); +} + +/*! + * \brief VUSBLogFileListModel::VUSBLogFileListModel + * \details Constructor of the VUSBLogFileListModel class + */ +VUSBLogFileListModel::VUSBLogFileListModel(QAbstractListModel *parent) + : VLogFileListModel(parent) +{ + // no op +} + +/*! + * \brief VUSBLogFileListModel::updateFolderWithType + * \details Update the folder path and model based on the passed type of logs (see Logger::LogTypes) + * \param vType = the type of logs + */ +void VUSBLogFileListModel::updateFolderWithType(const int &vType) +{ + QString path = ""; + switch (vType) { + case Logger::eLogAppED: + case Logger::eLogDebug: + case Logger::eLogTrtmt: + { + QString baseName = _Logger.getLogBasePathNames().value(static_cast(vType)); + path = QString("%1\%2").arg(Storage::USB_Mount_Point).arg(baseName); + break; + } + default: + LOG_DEBUG(QString("USB : updateFolderWithType: Invalid log type index %1").arg(vType)); + }; + + updateModelWithFolder(path); +} Index: sources/view/settings/VLogFileListModel.h =================================================================== diff -u --- sources/view/settings/VLogFileListModel.h (revision 0) +++ sources/view/settings/VLogFileListModel.h (revision 3c859e027546fa42ef215eb0d0d09e3f2bb953ab) @@ -0,0 +1,101 @@ +/*! + * + * Copyright (c) 2021-2023 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 VLogFileListModel.h + * \author (last) Vy Duong + * \date (last) 10-Aug-2023 + * \author (original) Vy Duong + * \date (original) 10-Aug-2023 + * + */ +#pragma once + +// Qt +#include +#include +#include +#include + +// Project +#include "main.h" +#include "VView.h" +#include "Logger.h" + +// forward declarations +class tst_views; + +namespace View { + +/*! + * \brief The VLogFileListModel class + * Interface between QML and the log files + * \details Exposes log files to QML and provides an interface to list and select the files + * References: https://doc.qt.io/qt-5.12/qtquick-modelviewsdata-cppmodels.html + * + */ + +class VLogFileListModel : public QAbstractListModel +{ + Q_OBJECT + PROPERTY(QString , folder , "" ) + PROPERTY(bool , includeSubFolders , true ) + +public: + // Note: VIEW_DEC_CLASS(VLogFileListModel) requires QObject as the parent, so it's necessary to define it here + // Otherwise a VIEW_DEC_CLASS macro could allow specifying the parent class with QObject as the default + explicit VLogFileListModel(QAbstractListModel *parent = nullptr); + + enum LogFileDataRole { + FilePathRole = Qt::UserRole + 1 , + FileNameRole , + FileSizeRole , + }; + + int rowCount (const QModelIndex &parent = QModelIndex()) const; + QVariant data (const QModelIndex &index, int role = Qt::DisplayRole) const; + +public slots: + void doInit(); + void removeAllRows(); + void refreshModel(); + virtual void updateFolderWithType(const int &vType) = 0; + void updateModelWithFolder(const QString &vPath); + +private slots: + void onLogsRemoved(bool vInProgress); + +protected: + QHash roleNames() const; + +private: + void initConnections(); + QFileInfoList getLogListFromDir(const QString &vDirectory); + + QFileInfoList _logFiles; + QString _currentPath; +}; + +class VSDCardLogFileListModel : public VLogFileListModel +{ + Q_OBJECT +public: + explicit VSDCardLogFileListModel(QAbstractListModel *parent = nullptr); + +public slots: + virtual void updateFolderWithType(const int &vType) override; +}; + +class VUSBLogFileListModel : public VLogFileListModel +{ + Q_OBJECT +public: + explicit VUSBLogFileListModel(QAbstractListModel *parent = nullptr); + +public slots: + virtual void updateFolderWithType(const int &vType) override; +}; +}