6import QGroundControl.Controls
7import QGroundControl.FactControls
11 pageComponent: pageComponent
19 spacing: ScreenTools.defaultFontPixelHeight * 0.75
21 readonly property string scriptRoot: "/APM/scripts/"
22 readonly property var luaNameFilters: [ qsTr("Lua Scripts (*.lua)"), qsTr("All Files (*)") ]
23 readonly property Fact scriptingEnabledFact: factController.getParameterFact(-1, "SCR_ENABLE", false)
25 readonly property var filteredEntries: {
26 let rawEntries = ftpController.directoryEntries.filter(function(entry) {
27 if (!entry || entry.length < 2) {
30 var kind = entry.charAt(0)
36 let filenameEntries = []
37 for (let i=0; i<rawEntries.length; i++) {
38 filenameEntries.push(rawEntries[i].slice(1).split("\t")[0])
40 return filenameEntries
43 function fullRemotePath(filename) {
44 return scriptRoot + filename
47 function fileNameFromPath(path) {
51 // Handle both forward slashes and backslashes
52 var normalizedPath = path.replace(/\\/g, "/")
53 var parts = normalizedPath.split("/")
54 return parts[parts.length - 1]
57 function refreshDirectoryList() {
58 ftpController.listDirectory(scriptRoot)
61 Component.onCompleted: {
62 if (scriptingEnabledFact && scriptingEnabledFact.rawValue) {
63 ftpController.listDirectory(root.scriptRoot)
68 target: scriptingEnabledFact
71 if (scriptingEnabledFact.rawValue) {
72 ftpController.listDirectory(root.scriptRoot)
82 onUploadComplete: (remotePath, error) => {
83 if (error.length > 0) {
84 statusText.text = error
86 statusText.text = qsTr("Upload succeeded: %1").arg(remotePath)
87 refreshDirectoryList()
91 onDownloadComplete: (filePath, error) => {
92 if (error.length > 0) {
93 statusText.text = error
95 statusText.text = qsTr("Download succeeded: %1").arg(filePath)
99 onDeleteComplete: (remotePath, error) => {
100 if (error.length > 0) {
101 statusText.text = error
103 statusText.text = qsTr("Delete succeeded: %1").arg(remotePath)
104 refreshDirectoryList()
109 FactPanelController {
113 QGCPalette { id: qgcPal; colorGroupEnabled: true }
116 text: qsTr("Enable Scripting")
117 fact: scriptingEnabledFact
118 enabled: scriptingEnabledFact !== null
123 Layout.fillWidth: true
124 text: ftpController.errorString
130 Layout.fillWidth: true
131 spacing: ScreenTools.defaultFontPixelHeight
132 enabled: !ftpController.busy && scriptingEnabledFact && scriptingEnabledFact.rawValue
136 iconSource: "/res/Upload.svg"
137 enabled: !ftpController.busy
139 uploadDialog.folder = QGroundControl.settingsManager.appSettings.missionSavePath
140 uploadDialog.openForLoad()
145 model: root.filteredEntries
148 width: button.checked ? deleteIcon.x + deleteIcon.width + button.rightPadding : button.width
149 height: button.height
150 radius: button.backRadius
151 border.width: button.showBorder ? 1 : 0
152 border.color: button.background.border.color
153 color: qgcPal.buttonHighlight
157 anchors.leftMargin: button.leftPadding
158 anchors.left: parent.left
159 anchors.verticalCenter: button.verticalCenter
161 height: button._iconHeight
162 fillMode: Image.PreserveAspectFit
163 source: "/res/Download.svg"
164 color: button.textColor
165 visible: button.checked
170 downloadDialog.defaultSuffix = "lua"
171 downloadDialog.title = qsTr("Download %1").arg(modelData)
172 downloadDialog.fileToDownload = modelData
173 downloadDialog.folder = QGroundControl.settingsManager.appSettings.missionSavePath
174 downloadDialog.openForLoad()
181 anchors.left: checked ? downloadIcon.right : parent.left
182 anchors.leftMargin: checked ? leftPadding : 0
189 anchors.left: button.right
190 anchors.leftMargin: button.rightPadding
191 anchors.verticalCenter: button.verticalCenter
193 height: button._iconHeight
194 fillMode: Image.PreserveAspectFit
195 source: "/res/TrashCan.svg"
196 color: button.textColor
197 visible: button.checked
202 var confirm = qsTr("Are you sure you want to delete the script \"%1\"? This action cannot be undone.").arg(modelData)
203 QGroundControl.showMessageDialog(scriptingPage, qsTr("Delete Lua Script"), confirm, Dialog.Ok | Dialog.Cancel, function() {
204 var remotePath = root.fullRemotePath(modelData)
205 if (!ftpController.deleteFile(remotePath)) {
206 var deleteError = ftpController.errorString.length > 0 ? ftpController.errorString : qsTr("Delete failed")
207 QGroundControl.showMessageDialog(scriptingPage, qsTr("Lua Delete"), deleteError)
218 Layout.fillWidth: true
219 spacing: ScreenTools.defaultFontPixelHeight * 0.5
222 text: qsTr("Cancel Operation")
223 visible: ftpController.busy
224 onClicked: ftpController.cancelActiveOperation()
227 Item { Layout.fillWidth: true }
230 text: qsTr("Transferring... %1%" ).arg(Math.round(ftpController.progress * 100))
231 visible: ftpController.busy
237 title: qsTr("Select Lua script to upload")
238 nameFilters: root.luaNameFilters
240 onAcceptedForLoad: (file) => {
245 var fileName = root.fileNameFromPath(file)
246 if (fileName.length === 0) {
250 if (!fileName.toLowerCase().endsWith(".lua")) {
251 fileName = fileName + ".lua"
253 var remotePath = root.fullRemotePath(fileName)
254 if (!ftpController.uploadFile(file, remotePath)) {
255 var uploadError = ftpController.errorString.length > 0 ? ftpController.errorString : qsTr("Upload failed")
256 QGroundControl.showMessageDialog(scriptingPage, qsTr("Lua Upload"), uploadError)
264 title: qsTr("Save Lua Script")
265 nameFilters: root.luaNameFilters
268 property string fileToDownload
270 onAcceptedForLoad: (folder) => {
275 if (!ftpController.downloadFile(root.fullRemotePath(fileToDownload), folder, fileToDownload)) {
276 var downloadError = ftpController.errorString.length > 0 ? ftpController.errorString : qsTr("Download failed")
277 QGroundControl.showMessageDialog(scriptingPage, qsTr("Lua Download"), downloadError)
284 Layout.fillWidth: true
285 Layout.preferredHeight: availableHeight
287 visible: scriptingEnabledFact === null
290 anchors.centerIn: parent
291 text: qsTr("Scripting is not supported by this version of firmware.")
293 horizontalAlignment: Text.AlignHCenter
294 verticalAlignment: Text.AlignVCenter