Index: sources/gui/qml/pages/settings/SettingsExportLogs.qml =================================================================== diff -u -rac121d27e4b3c4ca5be931f7da167b93381dc0ba -r5687815256ae070a9a207107088e3f72dd464da0 --- sources/gui/qml/pages/settings/SettingsExportLogs.qml (.../SettingsExportLogs.qml) (revision ac121d27e4b3c4ca5be931f7da167b93381dc0ba) +++ sources/gui/qml/pages/settings/SettingsExportLogs.qml (.../SettingsExportLogs.qml) (revision 5687815256ae070a9a207107088e3f72dd464da0) @@ -1,13 +1,13 @@ /*! * - * Copyright (c) 2022-2022 Diality Inc. - All Rights Reserved. + * Copyright (c) 2022-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 SettingsExportLogs.qml * \author (last) Behrouz NematiPour - * \date (last) 08-Nov-2022 + * \date (last) 04-Apr-2024 * \author (original) Behrouz NematiPour * \date (original) 27-Jun-2022 * @@ -37,7 +37,8 @@ /*! * \brief SettingsExportLogs is used to Export logs, and display the SD-Card and USB device informaiton and list of files. */ -SettingsBase { id: _root +SettingsBase { id: _root + itemIndex : SettingsStack.ExportLogs //////////////////////////////////////////////////////////////////////////////// // FIXME: The model being used here is the QML FileListModel. // @@ -60,10 +61,12 @@ readonly property string typeLabelService : qsTr("Service" ) readonly property string typeLabelTreatment : qsTr("Treatment" ) - property bool isDevice : true //false // it has to be true to make it work on the devices. + property bool isDevice : _GuiView.runOnDevice readonly property string typePathClr : "" - readonly property string typePathSrc : isDevice ? "file:///media/sd-card" : "file:///home/denali/Desktop/sd-card" - readonly property string typePathDst : isDevice ? "file:///media/usb" : "file:///home/denali/Desktop/usb-disk" + readonly property string typePathPrefix : "file://" + readonly property string typePathTxr : typePathPrefix + (isDevice ? "/var/configurations" : "/home/denali/Desktop/sd-card" ) + 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" @@ -72,22 +75,26 @@ 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 typeFolderTreatmentSrc : typePathTxr + typeFolderTreatment readonly property string typeFolderTreatmentDst : typePathDst + typeFolderTreatment readonly property var typeFilterAll : ["*"] readonly property var typeFilterClr : [] + readonly property bool horizontalLayout : _GuiView.useLogLongName - itemIndex : SettingsStack.ExportLogs confirmVisible : false + notificationMargin : Variables.notificationHeight + bottomMarginContent : Variables.settingsContentBottomMargin - Variables.minVGap function refreshModels() { _usbFolderColumn.clearModel() _usbFolderColumn.updateModel() } function doExport() { + notificationText = _logTypeCombo.displayText + " " + + qsTr("log export to USB in progress ... ") refreshModels() switch (_logTypeCombo.currentIndex) { @@ -105,6 +112,12 @@ refreshModels() } + onVisibleChanged: { + if ( _root.visible ) { + updatePanels( _logTypeCombo.currentIndex ) + } + } + property bool isUpdatePanels: false function updatePanels (vIndex) { isUpdatePanels = true @@ -141,7 +154,9 @@ function onDidUSBDriveRemove ( ) { _usbFolderColumn. clearModel ( ) } function onDidExportLog ( vValue ) { _usbFolderColumn. clearModel ( ) } function onDidUSBDriveMount ( ) { _usbFolderColumn.updateModel ( ) } - function onDidExport ( ) { _usbFolderColumn.updateModel ( ) } + function onDidExport ( ) { _usbFolderColumn.updateModel ( ) + notificationText = _logTypeCombo.displayText + " " + + qsTr("log export to USB is complete") } } USBButton { id: _usbEjectButton @@ -163,9 +178,9 @@ anchors.horizontalCenter : parent.horizontalCenter readonly property int columnWidthProgress : 350 - readonly property int columnWidthFolder : 420 - readonly property int columnWidthFileName : 285 // 285 best combination - readonly property int columnWidthFileSize : 105 // 105 best combination + readonly property int columnWidthFolder : _root.horizontalLayout ? 840 : 420 + readonly property int columnWidthFileName : _root.horizontalLayout ? 685 : 285 // best combination + readonly property int columnWidthFileSize : _root.horizontalLayout ? 105 : 105 // best combination Column { id : _progressColumn property int progressWidth : 125 @@ -174,7 +189,6 @@ spacing : 10 width : _contentRect.columnWidthProgress height : parent.height - anchors.verticalCenter : parent.verticalCenter Row { id : _logTypeRow anchors.left : parent.left @@ -185,6 +199,7 @@ // FIXME: This combobox needs to be a global Component ComboBox { id : _logTypeCombo onCurrentIndexChanged : { + notificationText = "" _root.updatePanels(currentIndex) } enabled : ! _GuiView.exportRunning && ! isUpdatePanels @@ -301,129 +316,145 @@ 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 - } - + Grid { + columns : _root.horizontalLayout ? 1 : 2 spacing : 5 width : _contentRect.columnWidthFolder height : parent.height - anchors.verticalCenter : parent.verticalCenter - Label { id : _sdcLabel - text : _root.sdcLabel + ": %1 files"/*, %2 %3"*/.arg(_sdcFolderModel.count) + (_GuiView.exportCount ? " [Selected: %1]".arg(_GuiView.exportCount ) : "") //.arg("__").arg(_root.dvcUnit) - width : parent.width - height : _root.headetRowHight - verticalAlignment : Text.AlignVCenter - } - Rectangle { id : _sdcFolderRectangle - color : Colors.transparent - border.color : Colors.borderButton - radius : Variables.dialogRadius - anchors.left : parent.left - width : parent.width - height : parent.height - _sdcLabel.height + Column { id : _sdcFolderColumn + property string currentTypeFolderApplication : _root.typeFolderApplicationSrc - ScrollBar { - anchors.fill : _sdcFolderView - flickable : _sdcFolderView + // 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 + } - ListView { id : _sdcFolderView - clip : true - anchors.fill : parent - anchors.leftMargin : 5 - anchors.rightMargin : 5 - spacing : 3 - FolderListModel { id : _sdcFolderModel - showDirs : false - sortField : FolderListModel.Time - folder : _sdcFolderColumn.currentTypeFolderApplication // FIXME: there has to be a View for this which also get changed by log type. + spacing : 5 + width : _contentRect.columnWidthFolder + height : _root.horizontalLayout ? parent.height / 2 : parent.height + Label { id : _sdcLabel + text : _root.sdcLabel + ": %1 files"/*, %2 %3"*/.arg(_sdcFolderModel.count) + (_GuiView.exportCount ? " [Selected: %1]".arg(_GuiView.exportCount ) : "") //.arg("__").arg(_root.dvcUnit) + width : parent.width + height : _root.headetRowHight + verticalAlignment : Text.AlignVCenter + } + Rectangle { id : _sdcFolderRectangle + color : Colors.transparent + border.color : Colors.borderButton + radius : Variables.dialogRadius + anchors.left : parent.left + width : parent.width + height : parent.height - _sdcLabel.height + + ScrollBar { + anchors.fill : _sdcFolderView + flickable : _sdcFolderView + handleWidth : Variables.settingsExportLogsScrollBarWidth } - Component { id : _sdcFileDelegate - ProgressBar { id : _sdcItemBackground - // *** IMPORTANT *** - // QML kills the items when they get out of the view port in regards to the cacheBuffer, - // and the next time it gets in the view port will be created with all the properties in their defaults. - property bool inExportList : _GuiView.exportList [ index ] // I couldn't make it work and this always returns undefined, but has to be used to trigger the change. - ? _GuiView.exportList [ index ] // In case the issue fixes it should return true if it is true, obviously! - : _GuiView.doExportListSelect ( index ) // otherwise for now, it calls the contains() function of the list in C++ backend. - property int exportPercent : _GuiView.exportIndex === index - ? _GuiView.exportPercent - : 0 - onExportPercentChanged : console.log( "%", exportPercent) - //DEBUG: onInExportListChanged: console.debug(" * ", index, inExportList) - function exportListUpdate() { - if (_GuiView.doExportListSelect( index ) ) { - _GuiView.doExportListDelete( index ) + ListView { id : _sdcFolderView + enabled : !_GuiView.exportRunning && ! isUpdatePanels + clip : true + anchors.fill : parent + anchors.margins : 10 + anchors.leftMargin : 5 + anchors.rightMargin : 5 + spacing : 3 + FolderListModel { id : _sdcFolderModel + 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 + // *** IMPORTANT *** + // QML kills the items when they get out of the view port in regards to the cacheBuffer, + // and the next time it gets in the view port will be created with all the properties in their defaults. + property bool inExportList : _GuiView.exportList [ index ] // I couldn't make it work and this always returns undefined, but has to be used to trigger the change. + ? _GuiView.exportList [ index ] // In case the issue fixes it should return true if it is true, obviously! + : _GuiView.doExportListSelect ( index ) // otherwise for now, it calls the contains() function of the list in C++ backend. + property int exportPercent : _GuiView.exportIndex === index + ? _GuiView.exportPercent + : 0 + onExportPercentChanged : console.log( "%", exportPercent) + + property bool isShownInList : ! _GuiView.isPathSymLink(_sdcFolderColumn.currentTypeFolderApplication.replace(typePathPrefix, "") + "/" + fileName) + + //DEBUG: onInExportListChanged: console.debug(" * ", index, inExportList) + function exportListUpdate() { + if (_GuiView.doExportListSelect( index ) ) { + _GuiView.doExportListDelete( index ) + } + else { + _GuiView.doExportListInsert( index , fileName ) + } } - else { - _GuiView.doExportListInsert( index , fileName ) + + MouseArea { + anchors.fill : parent + onClicked : exportListUpdate() } - } + progress.z : 0 + minText.visible : false + maxText.visible : false + marker.visible : false + maximum : 100 // percent + value : maximum - exportPercent - MouseArea { - anchors.fill : parent - onClicked : exportListUpdate() - } - progress.z : 0 - minText.visible : false - maxText.visible : false - marker.visible : false - maximum : 100 // percent - value : maximum - exportPercent - width : _sdcFolderView.width - height : 40 - bgColor : Colors.transparent - color : inExportList ? Colors.borderButtonSelected : Colors.transparent - radius : 5 - Row { id : _sdcFileRow - width : parent.width - height : 40 - leftPadding : 5 - Text { id : _sdcFileNameText - x : 2 - clip : true - width : _contentRect.columnWidthFileName - 2 - text : fileName - color : Colors.textMain - font.pixelSize : Fonts.fontPixelTextRectExtra - verticalAlignment : Text.AlignVCenter - horizontalAlignment : Text.AlignLeft + // 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 + + 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 + + leftPadding : 5 + Text { id : _sdcFileNameText + x : 2 + clip : true + width : isShownInList ? (_contentRect.columnWidthFileName - 2) : 0 + text : fileName + color : Colors.textMain + font.pixelSize : Fonts.fontPixelTextRectExtra + verticalAlignment : Text.AlignVCenter + horizontalAlignment : Text.AlignLeft + } + Rectangle { id : _sdcColumnVerticalLine + color : Colors.borderButtonUnselected + width : isShownInList ? 1 : 0 + height : parent.height + _usbFolderColumn.spacing + } + Text { id : _sdcFileSizeText + clip : true + width : isShownInList ? _contentRect.columnWidthFileSize : 0 + text : Variables.sizeConverted( fileSize, 1000, 3) + color : Colors.textMain + font.pixelSize : Fonts.fontPixelTextRectExtra + verticalAlignment : Text.AlignVCenter + horizontalAlignment : Text.AlignRight + } } - Rectangle { id : _sdcColumnVerticalLine - color : Colors.borderButtonUnselected - width : 1 - height : parent.height + _usbFolderColumn.spacing - } - Text { id : _sdcFileSizeText - clip : true - width : _contentRect.columnWidthFileSize - text : Variables.sizeConverted( fileSize, 1000, 3) - color : Colors.textMain - font.pixelSize : Fonts.fontPixelTextRectExtra - verticalAlignment : Text.AlignVCenter - horizontalAlignment : Text.AlignRight - } } } + model : _sdcFolderModel + delegate : _sdcFileDelegate } - model : _sdcFolderModel - delegate : _sdcFileDelegate } } - } - - Column { id : _usbFolderColumn + 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. @@ -441,6 +472,15 @@ interval : 500 repeat : true running : _GuiView.exportRunning + onRunningChanged: { + if(!running) { + // do one last update to get the correct file size else the USB file size is displayed + // as being smaller than the same file on SD card + _usbFolderColumn. clearModel() + _usbFolderColumn.updateModel() + } + } + onTriggered : { _usbFolderColumn. clearModel() _usbFolderColumn.updateModel() @@ -449,9 +489,7 @@ spacing : 5 width : _contentRect.columnWidthFolder - height : parent.height - anchors.verticalCenter : parent.verticalCenter - + height : _root.horizontalLayout ? parent.height / 2 : parent.height Label { id : _usbLabel text : _root.usbLabel + ": %1 files"/*", %2 %3"*/.arg(_usbFolderModel.count)//.arg("__").arg(_root.dvcUnit) width : parent.width @@ -470,13 +508,18 @@ ScrollBar { anchors.fill : _usbFolderView flickable : _usbFolderView + handleWidth : Variables.settingsExportLogsScrollBarWidth } ListView { id : _usbFolderView clip : true anchors.fill : parent anchors.margins : 10 - spacing : 5 + spacing : 3 + + 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 @@ -516,5 +559,6 @@ } } } + } } }