diff --git a/UnitTest.qrc b/UnitTest.qrc index 2bfa5bbb8062a9838d5fd3351bc49e074e13939d..4f29c94a617896bb84db4e068536f9e6f46c1878 100644 --- a/UnitTest.qrc +++ b/UnitTest.qrc @@ -1,18 +1,18 @@ - src/MissionManager/UnitTest/SectionTest.plan - src/MissionManager/UnitTest/MavCmdInfoCommon.json - src/MissionManager/UnitTest/MavCmdInfoFixedWing.json - src/MissionManager/UnitTest/MavCmdInfoMultiRotor.json - src/MissionManager/UnitTest/MavCmdInfoRover.json - src/MissionManager/UnitTest/MavCmdInfoSub.json - src/MissionManager/UnitTest/MavCmdInfoVTOL.json + src/MissionManager/UnitTest/SectionTest.plan + src/MissionManager/UnitTest/UT-MavCmdInfoCommon.json + src/MissionManager/UnitTest/UT-MavCmdInfoFixedWing.json + src/MissionManager/UnitTest/UT-MavCmdInfoMultiRotor.json + src/MissionManager/UnitTest/UT-MavCmdInfoRover.json + src/MissionManager/UnitTest/UT-MavCmdInfoSub.json + src/MissionManager/UnitTest/UT-MavCmdInfoVTOL.json src/MissionManager/UnitTest/MissionPlanner.waypoints src/MissionManager/UnitTest/OldFileFormat.mission - src/MissionManager/UnitTest/PolygonAreaTest.kml - src/MissionManager/UnitTest/PolygonGood.kml - src/MissionManager/UnitTest/PolygonMissingNode.kml - src/MissionManager/UnitTest/PolygonBadXml.kml - src/MissionManager/UnitTest/PolygonBadCoordinatesNode.kml + src/MissionManager/UnitTest/PolygonAreaTest.kml + src/MissionManager/UnitTest/PolygonGood.kml + src/MissionManager/UnitTest/PolygonMissingNode.kml + src/MissionManager/UnitTest/PolygonBadXml.kml + src/MissionManager/UnitTest/PolygonBadCoordinatesNode.kml diff --git a/localization/README.md b/localization/README.md index fd5ea12dad396c8b2496aed85168647a6b696ba2..d7d5e2c682a6c5bbee8083c88ac7f3e8105cd449 100644 --- a/localization/README.md +++ b/localization/README.md @@ -1,5 +1,65 @@ -To generate (or update) a source translation file, use the `to-crowdin.sh` script in this directory. You will need to update the path to Qt within it. +# QGroundControl string translations + +QGC uses the standard Qt Linguist mechanisms for string translation. QGC uses crowd sourced string translation through a [Crowdin project](https://crowdin.com/project/qgroundcontrol for translation). + + +## C++ and Qml code strings +These are coded using the standard Qt tr() for C++ and qsTr() for Qml mechanisms. + +## Translating strings within Json files +QGC uses json files internally for metadata. These files need to be translated as well. There is a [python parser](https://github.com/mavlink/qgroundcontrol/blob/master/localization/qgc-lupdate-json.py) which is used to find all the json files in the source tree and pull all the strings out for translation. This parser outputs the localization file for json strings in Qt .ts file format. + +In order for the parser to know which strings must be translated additional keys must be available at the root object level. + +> Important: Json files which have the same name are not allowed. Since the name is used as the context for the translation lookup it must be unique. The parse will throw an error if it finds duplicate file names. + +> Important: The root file name for the json file must be the same as the root filename for the Qt resource alias. This due to the fact that the root filename is used as the translation context. The json parser reads files from the file system and sees file system names. Whereas the QGC C++ code reads json files from the QT resource system and see the file alias as the full path and root name. + +### Specifying known file type +The parser supports two known file types: "MAVCmdInfo" and "FactMetaData". If your json file is one of these types you should place a `fileType` key at the root with one of these values. This will cause the parser to use these defaults for instructions: + +#### MAVCmdInfo +``` + "translateKeys": "label,enumStrings,friendlyName,description", + "arrayIDKeys": "rawName,comment" +``` +#### FactMetaData +``` + "translateKeys": "shortDescription,longDescription,enumStrings" + "arrayIDKeys": "name" +``` + +### Manually specify parser instructions +For this case dont include the `fileType` key/value pair. And include the followings keys (as needed) in the root object: + +* `translateKeys` This key is a string which is a list of all the keys which should be translated. +* `arrayIDKeys` The json localization parser provides additional information to the translator about where this string came from in the json hierarchy. If there is an array in the json, just displaying an array index as to where this came from is not that helpful. In most cases there is a key within each array element for which the value is unique. If this is the case then specify this key name(s) as the value for `arrayIDKeys`. + +### Disambiguation +This is used when you have two strings in the same file which are equal, but there meaning ar different enough that when translated they may each have their own different translation. In order to specific that you include a special prefix marker in the string which includes comments to the translator to explain the specifics of the string. + +``` + "foo": "#loc.disambiguation#This is the foo version of baz#baz" + "bar": "#loc.disambiguation#This is the bar version of baz#baz" +``` + +In the example above "baz" is the string which is the same for two different keys. The prefix `#loc.disambiguation#` indicates a disambiguation is to follow which is the string between the next set of `#`s. + +## Uploading new strings to Crowdin +To generate (or update) a source translation file, use the [to-crowdin.sh](https://github.com/mavlink/qgroundcontrol/blob/master/localization/to-crowdin.sh) script in this directory. You will need to update the path to Qt within it. This will do the following steps: + +* Delete the current qgc.ts file +* Run the qt lupdate command to generate a new qgc.ts file +* Run the python json parser which will add the json strings to the qgc.ts file + +Once this is complete you can upload the new qgc.ts file to Crowdin. + +https://github.com/mavlink/qgroundcontrol/blob/master/localization/to-crowdin.sh + +## Download translations from Crowdin + +Once translations have been done/updated, within Crowdin "Build and Download". Extract the resulting qgroundcontro.zip here and run [from-crowdin.sh](https://github.com/mavlink/qgroundcontrol/blob/master/localization/from-crowdin.sh). This will parse all the source files and generate a language translation file called qgc.ts, which should be uploaded to crowdin. -Once translations have been done/updated, within Crowdin "Build and Download". Extract the resulting qgroundcontro.zip here and run `from-crowdin.py`. + diff --git a/localization/qgc-lupdate-json.py b/localization/qgc-lupdate-json.py new file mode 100755 index 0000000000000000000000000000000000000000..abcc8de76ed607de429fa3844e863497e77ec200 --- /dev/null +++ b/localization/qgc-lupdate-json.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python +import os +import json +from xml.dom.minidom import parse +import xml.dom.minidom +import codecs +import sys + +qgcFileTypeKey = "fileType" +translateKeysKey = "translateKeys" +arrayIDKeysKey = "arrayIDKeys" +disambiguationPrefix = "#loc.disambiguation#" + +def parseJsonObjectForTranslateKeys(jsonObjectHierarchy, jsonObject, translateKeys, arrayIDKeys, locStringDict): + for translateKey in translateKeys: + if (translateKey in jsonObject): + locStr = jsonObject[translateKey] + currentHierarchy = jsonObjectHierarchy + "." + translateKey + if locStr in locStringDict: + # Duplicate of an existing string + locStringDict[locStr].append(currentHierarchy) + else: + # First time we are seeing this string + locStringDict[locStr] = [ currentHierarchy ] + for key in jsonObject: + currentHierarchy = jsonObjectHierarchy + "." + key + if (type(jsonObject[key]) == type({})): + parseJsonObjectForTranslateKeys(currentHierarchy, jsonObject[key], translateKeys,arrayIDKeys, locStringDict) + elif (type(jsonObject[key]) == type([])): + parseJsonArrayForTranslateKeys(currentHierarchy, jsonObject[key], translateKeys, arrayIDKeys, locStringDict) + +def parseJsonArrayForTranslateKeys(jsonObjectHierarchy, jsonArray, translateKeys, arrayIDKeys, locStringDict): + for index in range(0, len(jsonArray)): + jsonObject = jsonArray[index] + arrayIndexStr = str(index) + for arrayIDKey in arrayIDKeys: + if arrayIDKey in jsonObject.keys(): + arrayIndexStr = jsonObject[arrayIDKey] + break + currentHierarchy = jsonObjectHierarchy + "[" + arrayIndexStr + "]" + parseJsonObjectForTranslateKeys(currentHierarchy, jsonObject, translateKeys, arrayIDKeys, locStringDict) + +def addLocKeysBasedOnQGCFileType(jsonPath, jsonDict): + # Instead of having to add the same keys over and over again in a pile of files we add them here automatically based on file type + if qgcFileTypeKey in jsonDict: + qgcFileType = jsonDict[qgcFileTypeKey] + translateKeyValue = "" + arrayIDKeysKeyValue = "" + if qgcFileType == "MavCmdInfo": + translateKeyValue = "label,enumStrings,friendlyName,description,category" + arrayIDKeysKeyValue = "rawName,comment" + elif qgcFileType == "FactMetaData": + translateKeyValue = "shortDescription,longDescription,enumStrings" + arrayIDKeysKeyValue = "name" + if translateKeysKey not in jsonDict and translateKeyValue != "": + jsonDict[translateKeysKey] = translateKeyValue + if arrayIDKeysKey not in jsonDict and arrayIDKeysKeyValue != "": + jsonDict[arrayIDKeysKey] = arrayIDKeysKeyValue + +def parseJson(jsonPath, locStringDict): + jsonFile = open(jsonPath) + jsonDict = json.load(jsonFile) + if (type(jsonDict) != type({})): + return + addLocKeysBasedOnQGCFileType(jsonPath, jsonDict) + if (not translateKeysKey in jsonDict): + return + translateKeys = jsonDict[translateKeysKey].split(",") + arrayIDKeys = jsonDict.get(arrayIDKeysKey, "").split(",") + parseJsonObjectForTranslateKeys("", jsonDict, translateKeys, arrayIDKeys, locStringDict) + +def walkDirectoryTreeForJsonFiles(dir, multiFileLocArray): + for filename in os.listdir(dir): + path = os.path.join(dir, filename) + if (os.path.isfile(path) and filename.endswith(".json")): + #print "json",path + singleFileLocStringDict = {} + parseJson(path, singleFileLocStringDict) + if len(singleFileLocStringDict.keys()): + # Check for duplicate file names + for entry in multiFileLocArray: + if entry[0] == filename: + print "Error: Duplicate filenames: %s paths: %s %s" % (filename, path, entry[1]) + sys.exit(1) + multiFileLocArray.append([filename, path, singleFileLocStringDict]) + if (os.path.isdir(path)): + walkDirectoryTreeForJsonFiles(path, multiFileLocArray) + +def appendToQGCTSFile(multiFileLocArray): + originalTSFile = codecs.open('qgc.ts', 'r', "utf-8") + newTSFile = codecs.open('qgc.ts.new', 'w', "utf-8") + line = originalTSFile.readline() + while (line != "\n"): + newTSFile.write(line); + line = originalTSFile.readline() + originalTSFile.close() + for entry in multiFileLocArray: + newTSFile.write("\n") + newTSFile.write(" %s\n" % entry[0]) + singleFileLocStringDict = entry[2] + for locStr in singleFileLocStringDict.keys(): + disambiguation = "" + if locStr.startswith(disambiguationPrefix): + workStr = locStr[len(disambiguationPrefix):] + terminatorIndex = workStr.find("#") + if terminatorIndex == -1: + print "Bad disambiguation %1 '%2'" % (entry[0], locStr) + sys.exit(1) + disambiguation = workStr[:terminatorIndex] + locStr = workStr[terminatorIndex+1:] + newTSFile.write(" \n") + if len(disambiguation): + newTSFile.write(" %s\n" % disambiguation) + extraCommentStr = "" + for jsonHierachy in singleFileLocStringDict[locStr]: + extraCommentStr += "%s, " % jsonHierachy + newTSFile.write(" %s\n" % extraCommentStr) + newTSFile.write(" \n" % entry[1]) + newTSFile.write(unicode(" %s\n") % locStr) + newTSFile.write(" \n") + newTSFile.write(" \n") + newTSFile.write("\n") + newTSFile.write("\n") + newTSFile.close() + +def main(): + multiFileLocArray = [] + walkDirectoryTreeForJsonFiles("../src", multiFileLocArray) + appendToQGCTSFile(multiFileLocArray) + +if __name__ == '__main__': + main() diff --git a/localization/to-crowdin.sh b/localization/to-crowdin.sh index 4ca1455bd391974b69507d239a9990b77304d321..78101bb7268f9d11e1480363f43a701b674add5f 100755 --- a/localization/to-crowdin.sh +++ b/localization/to-crowdin.sh @@ -1,5 +1,8 @@ #!/bin/bash # This is set to find lupdate in my particular installation. You will need to set the path # where you have Qt installed. -QT_PATH=~/Applications/Qt/5.12.3/clang_64/bin +QT_PATH=~//Qt/5.12.6/gcc_64/bin +rm qgc.ts $QT_PATH/lupdate ../src -ts qgc.ts +python qgc-lupdate-json.py +mv qgc.ts.new qgc.ts diff --git a/src/Airmap/AirMap.SettingsGroup.json b/src/Airmap/AirMap.SettingsGroup.json index 2f2181e0cfe23071ae3ea8ce6006f735b90970bd..c38ba29a96e09c5f29d9d4d64fc585cd48a3b71a 100644 --- a/src/Airmap/AirMap.SettingsGroup.json +++ b/src/Airmap/AirMap.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "usePersonalApiKey", @@ -48,3 +52,4 @@ "defaultValue": false } ] +} diff --git a/src/AutoPilotPlugins/APM/APMFollowComponent.FactMetaData.json b/src/AutoPilotPlugins/APM/APMFollowComponent.FactMetaData.json index 7d02697181a75e18333ba792e60be27b0d79594f..606f4320d78a24283d267dd21678b7b9977be541 100644 --- a/src/AutoPilotPlugins/APM/APMFollowComponent.FactMetaData.json +++ b/src/AutoPilotPlugins/APM/APMFollowComponent.FactMetaData.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "angle", @@ -28,3 +32,4 @@ "defaultValue": 5 } ] +} diff --git a/src/AutoPilotPlugins/APM/APMPowerComponent.qml b/src/AutoPilotPlugins/APM/APMPowerComponent.qml index 340144aa23a29540bdffe394eaec981db03e1880..376348e4cc676972b7f3e4781b737f885c6577c4 100644 --- a/src/AutoPilotPlugins/APM/APMPowerComponent.qml +++ b/src/AutoPilotPlugins/APM/APMPowerComponent.qml @@ -266,7 +266,7 @@ SetupPage { QGCLabel { text: qsTr("- The arming tone will be played (if the vehicle has a buzzer attached)") } QGCLabel { text: qsTr("- If using a flight controller with a safety button press it until it displays solid red") } QGCLabel { text: qsTr("- You will hear a musical tone then two beeps") } - QGCLabel { text: qsTr("- A few seconds later you should hear a number of beeps (one for each battery cell you’re using)") } + QGCLabel { text: qsTr("- A few seconds later you should hear a number of beeps (one for each battery cell you're using)") } QGCLabel { text: qsTr("- And finally a single long beep indicating the end points have been set and the ESC is calibrated") } QGCLabel { text: qsTr("- Disconnect the battery and power up again normally") } } diff --git a/src/AutoPilotPlugins/PX4/AirframeComponent.qml b/src/AutoPilotPlugins/PX4/AirframeComponent.qml index 719f5e3bb2b839a440394097d47730182860e6ab..a99e1a34cf6baf97bec9cee1c8ddddf590199cc6 100644 --- a/src/AutoPilotPlugins/PX4/AirframeComponent.qml +++ b/src/AutoPilotPlugins/PX4/AirframeComponent.qml @@ -111,7 +111,7 @@ SetupPage { QGCLabel { anchors.fill: parent wrapMode: Text.WordWrap - text: qsTr("Clicking “Apply” will save the changes you have made to your airframe configuration.

\ + text: qsTr("Clicking 'Apply' will save the changes you have made to your airframe configuration.

\ All vehicle parameters other than Radio Calibration will be reset.

\ Your vehicle will also be restarted in order to complete the process.") } @@ -130,7 +130,7 @@ Your vehicle will also be restarted in order to complete the process.") text: (controller.currentVehicleName != "" ? qsTr("You've connected a %1.").arg(controller.currentVehicleName) : qsTr("Airframe is not set.")) + - qsTr("To change this configuration, select the desired airframe below then click “Apply and Restart”.") + qsTr("To change this configuration, select the desired airframe below then click 'Apply and Restart'.") font.family: ScreenTools.demiboldFontFamily wrapMode: Text.WordWrap } diff --git a/src/FactSystem/FactMetaData.cc b/src/FactSystem/FactMetaData.cc index b4b8ce4de4272c4bfc1f66837dd99f085349a14a..4897e47a8f7fe7fc34bf1cfdbde16325aa7d5bba 100644 --- a/src/FactSystem/FactMetaData.cc +++ b/src/FactSystem/FactMetaData.cc @@ -35,6 +35,7 @@ const qreal FactMetaData::UnitConsts_s::inchesToCentimeters = 2.54; static const char* kDefaultCategory = QT_TRANSLATE_NOOP("FactMetaData", "Other"); static const char* kDefaultGroup = QT_TRANSLATE_NOOP("FactMetaData", "Misc"); +const char* FactMetaData::qgcFileType = "FactMetaData"; const char* FactMetaData::_jsonMetaDataDefinesName = "QGC.MetaData.Defines"; const char* FactMetaData::_jsonMetaDataFactsName = "QGC.MetaData.Facts"; @@ -1220,45 +1221,29 @@ QMap FactMetaData::createMapFromJsonFile(const QString& { QMap metaDataMap; - QFile jsonFile(jsonFilename); - if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - qWarning() << "Unable to open file" << jsonFilename << jsonFile.errorString(); - return metaDataMap; - } - - QByteArray bytes = jsonFile.readAll(); - jsonFile.close(); - QJsonParseError jsonParseError; - QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError); - if (jsonParseError.error != QJsonParseError::NoError) { - qWarning() << "Unable to parse json document filename:error:offset" << jsonFilename << jsonParseError.errorString() << jsonParseError.offset; + QString errorString; + int version; + QJsonObject jsonObject = JsonHelper::openInternalQGCJsonFile(jsonFilename, qgcFileType, 1, 1, version, errorString); + if (!errorString.isEmpty()) { + qWarning() << "Internal Error: " << errorString; return metaDataMap; } QJsonArray factArray; QMap defineMap; - if (doc.isObject()) { - // Check for Defines/Facts format - QString errorString; - QList keyInfoList = { - { FactMetaData::_jsonMetaDataDefinesName, QJsonValue::Object, true }, - { FactMetaData::_jsonMetaDataFactsName, QJsonValue::Array, true }, - }; - if (!JsonHelper::validateKeys(doc.object(), keyInfoList, errorString)) { - qWarning() << "Json document incorrect format:" << errorString; - return metaDataMap; - } - - _loadJsonDefines(doc.object()[FactMetaData::_jsonMetaDataDefinesName].toObject(), defineMap); - factArray = doc.object()[FactMetaData::_jsonMetaDataFactsName].toArray(); - } else if (doc.isArray()) { - factArray = doc.array(); - } else { - qWarning() << "Json document is neither array nor object"; + QList keyInfoList = { + { FactMetaData::_jsonMetaDataDefinesName, QJsonValue::Object, false }, + { FactMetaData::_jsonMetaDataFactsName, QJsonValue::Array, true }, + }; + if (!JsonHelper::validateKeys(jsonObject, keyInfoList, errorString)) { + qWarning() << "Json document incorrect format:" << errorString; return metaDataMap; } + _loadJsonDefines(jsonObject[FactMetaData::_jsonMetaDataDefinesName].toObject(), defineMap); + factArray = jsonObject[FactMetaData::_jsonMetaDataFactsName].toArray(); + return createMapFromJsonArray(factArray, defineMap, metaDataParent); } diff --git a/src/FactSystem/FactMetaData.h b/src/FactSystem/FactMetaData.h index c6c1484c2a7af43e7e63495de0f61010595091d3..e5a27a94d9a466833f6802f3866bed5277dc7a70 100644 --- a/src/FactSystem/FactMetaData.h +++ b/src/FactSystem/FactMetaData.h @@ -7,12 +7,7 @@ * ****************************************************************************/ - -/// @file -/// @author Don Gagne - -#ifndef FactMetaData_H -#define FactMetaData_H +#pragma once #include #include @@ -172,6 +167,8 @@ public: static ValueType_t stringToType(const QString& typeString, bool& unknownType); static size_t typeToSize(ValueType_t type); + static const char* qgcFileType; + private: QVariant _minForType(void) const; QVariant _maxForType(void) const; @@ -298,5 +295,3 @@ private: static const char* _jsonMetaDataDefinesName; static const char* _jsonMetaDataFactsName; }; - -#endif diff --git a/src/FirmwarePlugin/APM/MavCmdInfoCommon.json b/src/FirmwarePlugin/APM/APM-MavCmdInfoCommon.json similarity index 97% rename from src/FirmwarePlugin/APM/MavCmdInfoCommon.json rename to src/FirmwarePlugin/APM/APM-MavCmdInfoCommon.json index 1226035af76adf73ae086e9cb70ac2225e3e0065..aee59c1ad6ac00c8c7e91a55c3874b0eca98f12b 100644 --- a/src/FirmwarePlugin/APM/MavCmdInfoCommon.json +++ b/src/FirmwarePlugin/APM/APM-MavCmdInfoCommon.json @@ -1,7 +1,7 @@ { - "comment": "ArduPilot, Any Vehicle", - - "version": 1, + "comment": "ArduPilot, Any Vehicle", + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ { diff --git a/src/FirmwarePlugin/APM/MavCmdInfoFixedWing.json b/src/FirmwarePlugin/APM/APM-MavCmdInfoFixedWing.json similarity index 92% rename from src/FirmwarePlugin/APM/MavCmdInfoFixedWing.json rename to src/FirmwarePlugin/APM/APM-MavCmdInfoFixedWing.json index 9cca7514c414990bcf3f94092886c11c9716dc6a..d647b6654b1d3c9982d71af869de9c6337a0402f 100644 --- a/src/FirmwarePlugin/APM/MavCmdInfoFixedWing.json +++ b/src/FirmwarePlugin/APM/APM-MavCmdInfoFixedWing.json @@ -1,7 +1,7 @@ { - "comment": "ArduPilot, Fixed Wing", - - "version": 1, + "comment": "ArduPilot, Fixed Wing", + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ { diff --git a/src/FirmwarePlugin/APM/MavCmdInfoMultiRotor.json b/src/FirmwarePlugin/APM/APM-MavCmdInfoMultiRotor.json similarity index 91% rename from src/FirmwarePlugin/APM/MavCmdInfoMultiRotor.json rename to src/FirmwarePlugin/APM/APM-MavCmdInfoMultiRotor.json index 4d47dac8da010320abc4834b38ddd16a6a59fb11..2170b7038eb2dfb428af41d2e2dd669af25a2f5f 100644 --- a/src/FirmwarePlugin/APM/MavCmdInfoMultiRotor.json +++ b/src/FirmwarePlugin/APM/APM-MavCmdInfoMultiRotor.json @@ -1,7 +1,7 @@ { - "comment": "ArduPilot, Multi Rotor", - - "version": 1, + "comment": "ArduPilot, Multi Rotor", + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ { diff --git a/src/FirmwarePlugin/APM/APM-MavCmdInfoRover.json b/src/FirmwarePlugin/APM/APM-MavCmdInfoRover.json new file mode 100644 index 0000000000000000000000000000000000000000..d243f13f91270dff3e806c616a86160619192abc --- /dev/null +++ b/src/FirmwarePlugin/APM/APM-MavCmdInfoRover.json @@ -0,0 +1,8 @@ +{ + "comment": "ArduPilot, Rover", + "version": 1, + "fileType": "MavCmdInfo", + + "mavCmdInfo": [ + ] +} diff --git a/src/FirmwarePlugin/APM/APM-MavCmdInfoSub.json b/src/FirmwarePlugin/APM/APM-MavCmdInfoSub.json new file mode 100644 index 0000000000000000000000000000000000000000..45c5962d0b4ca2fc1fb48b202a4becc9ba8d7c2e --- /dev/null +++ b/src/FirmwarePlugin/APM/APM-MavCmdInfoSub.json @@ -0,0 +1,8 @@ +{ + "comment": "ArduPilot, Sub", + "version": 1, + "fileType": "MavCmdInfo", + + "mavCmdInfo": [ + ] +} diff --git a/src/FirmwarePlugin/APM/APM-MavCmdInfoVTOL.json b/src/FirmwarePlugin/APM/APM-MavCmdInfoVTOL.json new file mode 100644 index 0000000000000000000000000000000000000000..e94cf27d4d45a2d9db5583619b09e00f64774f96 --- /dev/null +++ b/src/FirmwarePlugin/APM/APM-MavCmdInfoVTOL.json @@ -0,0 +1,8 @@ +{ + "comment": "ArduPilot, VTOL", + "version": 1, + "fileType": "MavCmdInfo", + + "mavCmdInfo": [ + ] +} diff --git a/src/FirmwarePlugin/APM/APMFirmwarePlugin.cc b/src/FirmwarePlugin/APM/APMFirmwarePlugin.cc index 9a035ce5594355a5794f4ef88a9539d2b06eaf8d..4f0480fa7076e4c0e8c3b62ad438600c357b94a3 100644 --- a/src/FirmwarePlugin/APM/APMFirmwarePlugin.cc +++ b/src/FirmwarePlugin/APM/APMFirmwarePlugin.cc @@ -753,17 +753,17 @@ QString APMFirmwarePlugin::missionCommandOverrides(MAV_TYPE vehicleType) const { switch (vehicleType) { case MAV_TYPE_GENERIC: - return QStringLiteral(":/json/APM/MavCmdInfoCommon.json"); + return QStringLiteral(":/json/APM-MavCmdInfoCommon.json"); case MAV_TYPE_FIXED_WING: - return QStringLiteral(":/json/APM/MavCmdInfoFixedWing.json"); + return QStringLiteral(":/json/APM-MavCmdInfoFixedWing.json"); case MAV_TYPE_QUADROTOR: - return QStringLiteral(":/json/APM/MavCmdInfoMultiRotor.json"); + return QStringLiteral(":/json/APM-MavCmdInfoMultiRotor.json"); case MAV_TYPE_VTOL_QUADROTOR: - return QStringLiteral(":/json/APM/MavCmdInfoVTOL.json"); + return QStringLiteral(":/json/APM-MavCmdInfoVTOL.json"); case MAV_TYPE_SUBMARINE: - return QStringLiteral(":/json/APM/MavCmdInfoSub.json"); + return QStringLiteral(":/json/APM-MavCmdInfoSub.json"); case MAV_TYPE_GROUND_ROVER: - return QStringLiteral(":/json/APM/MavCmdInfoRover.json"); + return QStringLiteral(":/json/APM-MavCmdInfoRover.json"); default: qWarning() << "APMFirmwarePlugin::missionCommandOverrides called with bad MAV_TYPE:" << vehicleType; return QString(); diff --git a/src/FirmwarePlugin/APM/APMResources.qrc b/src/FirmwarePlugin/APM/APMResources.qrc index 363bc846b572fafb96e0a41b5f4814d35d517b87..19e04df90ea72e6c73ec3abc4ecba71a3dc7cbc0 100644 --- a/src/FirmwarePlugin/APM/APMResources.qrc +++ b/src/FirmwarePlugin/APM/APMResources.qrc @@ -33,12 +33,12 @@ QGroundControl.ArduPilot.qmldir - MavCmdInfoCommon.json - MavCmdInfoFixedWing.json - MavCmdInfoMultiRotor.json - MavCmdInfoRover.json - MavCmdInfoSub.json - MavCmdInfoVTOL.json + APM-MavCmdInfoCommon.json + APM-MavCmdInfoFixedWing.json + APM-MavCmdInfoMultiRotor.json + APM-MavCmdInfoRover.json + APM-MavCmdInfoSub.json + APM-MavCmdInfoVTOL.json ../../AutoPilotPlugins/APM/APMFollowComponent.FactMetaData.json diff --git a/src/FirmwarePlugin/APM/MavCmdInfoRover.json b/src/FirmwarePlugin/APM/MavCmdInfoRover.json deleted file mode 100644 index 941b0b6da99fb4ed4c79d8ffd053aecdb23f5042..0000000000000000000000000000000000000000 --- a/src/FirmwarePlugin/APM/MavCmdInfoRover.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "comment": "ArduPilot, Rover", - - "version": 1, - - "mavCmdInfo": [ - ] -} diff --git a/src/FirmwarePlugin/APM/MavCmdInfoSub.json b/src/FirmwarePlugin/APM/MavCmdInfoSub.json deleted file mode 100644 index 0e2486979cb420fcc9a2a50c0a8137bf7f4a38e6..0000000000000000000000000000000000000000 --- a/src/FirmwarePlugin/APM/MavCmdInfoSub.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "comment": "ArduPilot, Sub", - - "version": 1, - - "mavCmdInfo": [ - ] -} diff --git a/src/FirmwarePlugin/APM/MavCmdInfoVTOL.json b/src/FirmwarePlugin/APM/MavCmdInfoVTOL.json deleted file mode 100644 index a486ae1d3681e56813c519fd72088681959e0090..0000000000000000000000000000000000000000 --- a/src/FirmwarePlugin/APM/MavCmdInfoVTOL.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "comment": "ArduPilot, VTOL", - - "version": 1, - - "mavCmdInfo": [ - ] -} diff --git a/src/FirmwarePlugin/PX4/MavCmdInfoFixedWing.json b/src/FirmwarePlugin/PX4/MavCmdInfoFixedWing.json deleted file mode 100644 index 12c53425e3f0f205365e77aad3b3c463b127ed2d..0000000000000000000000000000000000000000 --- a/src/FirmwarePlugin/PX4/MavCmdInfoFixedWing.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "comment": "PX4 Pro, Fixed Wing", - - "version": 1, - - "mavCmdInfo": [ - ] -} diff --git a/src/FirmwarePlugin/PX4/MavCmdInfoRover.json b/src/FirmwarePlugin/PX4/MavCmdInfoRover.json deleted file mode 100644 index 2402c0fc24796661d88a71d71472ef41e7b35ef0..0000000000000000000000000000000000000000 --- a/src/FirmwarePlugin/PX4/MavCmdInfoRover.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "comment": "PX4 Pro, Rover", - - "version": 1, - - "mavCmdInfo": [ - ] -} diff --git a/src/FirmwarePlugin/PX4/MavCmdInfoSub.json b/src/FirmwarePlugin/PX4/MavCmdInfoSub.json deleted file mode 100644 index e719d6e9ee9be58c480a036fd1b10fe1f5400fef..0000000000000000000000000000000000000000 --- a/src/FirmwarePlugin/PX4/MavCmdInfoSub.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "comment": "PX4 Pro, Sub", - - "version": 1, - - "mavCmdInfo": [ - ] -} diff --git a/src/FirmwarePlugin/PX4/MavCmdInfoVTOL.json b/src/FirmwarePlugin/PX4/MavCmdInfoVTOL.json deleted file mode 100644 index e2d418eca48899f880d557e52d8167c33da8499c..0000000000000000000000000000000000000000 --- a/src/FirmwarePlugin/PX4/MavCmdInfoVTOL.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "comment": "PX4 Pro, VTOL", - - "version": 1, - - "mavCmdInfo": [ - ] -} diff --git a/src/FirmwarePlugin/PX4/MavCmdInfoCommon.json b/src/FirmwarePlugin/PX4/PX4-MavCmdInfoCommon.json similarity index 85% rename from src/FirmwarePlugin/PX4/MavCmdInfoCommon.json rename to src/FirmwarePlugin/PX4/PX4-MavCmdInfoCommon.json index 8657261895e728cd9fdf5aa479ab99e3d4d1e8c7..3182be6fb0dd0c42aca134bd103e4364e6955284 100644 --- a/src/FirmwarePlugin/PX4/MavCmdInfoCommon.json +++ b/src/FirmwarePlugin/PX4/PX4-MavCmdInfoCommon.json @@ -1,7 +1,7 @@ { - "comment": "PX4 Pro, Any Vehicle", - - "version": 1, + "comment": "PX4 Pro, Any Vehicle", + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ { diff --git a/src/FirmwarePlugin/PX4/PX4-MavCmdInfoFixedWing.json b/src/FirmwarePlugin/PX4/PX4-MavCmdInfoFixedWing.json new file mode 100644 index 0000000000000000000000000000000000000000..836056d92d847e8122084f8fe5b30b18f7b866b0 --- /dev/null +++ b/src/FirmwarePlugin/PX4/PX4-MavCmdInfoFixedWing.json @@ -0,0 +1,8 @@ +{ + "comment": "PX4 Pro, Fixed Wing", + "version": 1, + "fileType": "MavCmdInfo", + + "mavCmdInfo": [ + ] +} diff --git a/src/FirmwarePlugin/PX4/MavCmdInfoMultiRotor.json b/src/FirmwarePlugin/PX4/PX4-MavCmdInfoMultiRotor.json similarity index 90% rename from src/FirmwarePlugin/PX4/MavCmdInfoMultiRotor.json rename to src/FirmwarePlugin/PX4/PX4-MavCmdInfoMultiRotor.json index ae9917c290b57721ccf5eb142b165c756746fb06..cc37c64f9ef9e5632a6643fccdd046de3ed705bb 100644 --- a/src/FirmwarePlugin/PX4/MavCmdInfoMultiRotor.json +++ b/src/FirmwarePlugin/PX4/PX4-MavCmdInfoMultiRotor.json @@ -1,7 +1,7 @@ { - "comment": "PX4 Pro, Multi Rotor", - - "version": 1, + "comment": "PX4 Pro, Multi Rotor", + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ { diff --git a/src/FirmwarePlugin/PX4/PX4-MavCmdInfoRover.json b/src/FirmwarePlugin/PX4/PX4-MavCmdInfoRover.json new file mode 100644 index 0000000000000000000000000000000000000000..2dde98e8c540f73560f70e9cbd96b8e22bd63a27 --- /dev/null +++ b/src/FirmwarePlugin/PX4/PX4-MavCmdInfoRover.json @@ -0,0 +1,8 @@ +{ + "comment": "PX4 Pro, Rover", + "version": 1, + "fileType": "MavCmdInfo", + + "mavCmdInfo": [ + ] +} diff --git a/src/FirmwarePlugin/PX4/PX4-MavCmdInfoSub.json b/src/FirmwarePlugin/PX4/PX4-MavCmdInfoSub.json new file mode 100644 index 0000000000000000000000000000000000000000..632f92c01a7117123bd08b5d86bbe1ebce178f32 --- /dev/null +++ b/src/FirmwarePlugin/PX4/PX4-MavCmdInfoSub.json @@ -0,0 +1,8 @@ +{ + "comment": "PX4 Pro, Sub", + "version": 1, + "fileType": "MavCmdInfo", + + "mavCmdInfo": [ + ] +} diff --git a/src/FirmwarePlugin/PX4/PX4-MavCmdInfoVTOL.json b/src/FirmwarePlugin/PX4/PX4-MavCmdInfoVTOL.json new file mode 100644 index 0000000000000000000000000000000000000000..e03df84d9b8e8f2fb56b0a3aab5bf9b4cdcece74 --- /dev/null +++ b/src/FirmwarePlugin/PX4/PX4-MavCmdInfoVTOL.json @@ -0,0 +1,8 @@ +{ + "comment": "PX4 Pro, VTOL", + "version": 1, + "fileType": "MavCmdInfo", + + "mavCmdInfo": [ + ] +} diff --git a/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc b/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc index cdb2baf2ca5870d2cf1b4fb718e758ae954889ac..9e70bffece639fc6469e1269ae11ce75a0ab0b61 100644 --- a/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc +++ b/src/FirmwarePlugin/PX4/PX4FirmwarePlugin.cc @@ -312,17 +312,17 @@ QString PX4FirmwarePlugin::missionCommandOverrides(MAV_TYPE vehicleType) const { switch (vehicleType) { case MAV_TYPE_GENERIC: - return QStringLiteral(":/json/PX4/MavCmdInfoCommon.json"); + return QStringLiteral(":/json/PX4-MavCmdInfoCommon.json"); case MAV_TYPE_FIXED_WING: - return QStringLiteral(":/json/PX4/MavCmdInfoFixedWing.json"); + return QStringLiteral(":/json/PX4-MavCmdInfoFixedWing.json"); case MAV_TYPE_QUADROTOR: - return QStringLiteral(":/json/PX4/MavCmdInfoMultiRotor.json"); + return QStringLiteral(":/json/PX4-MavCmdInfoMultiRotor.json"); case MAV_TYPE_VTOL_QUADROTOR: - return QStringLiteral(":/json/PX4/MavCmdInfoVTOL.json"); + return QStringLiteral(":/json/PX4-MavCmdInfoVTOL.json"); case MAV_TYPE_SUBMARINE: - return QStringLiteral(":/json/PX4/MavCmdInfoSub.json"); + return QStringLiteral(":/json/PX4-MavCmdInfoSub.json"); case MAV_TYPE_GROUND_ROVER: - return QStringLiteral(":/json/PX4/MavCmdInfoRover.json"); + return QStringLiteral(":/json/PX4-MavCmdInfoRover.json"); default: qWarning() << "PX4FirmwarePlugin::missionCommandOverrides called with bad MAV_TYPE:" << vehicleType; return QString(); diff --git a/src/FirmwarePlugin/PX4/PX4Resources.qrc b/src/FirmwarePlugin/PX4/PX4Resources.qrc index 2418d5ab7d96858d8de53b623512ee2f5e3f3a88..8b370c1e2d9247f50547cd9a03e340349d989281 100644 --- a/src/FirmwarePlugin/PX4/PX4Resources.qrc +++ b/src/FirmwarePlugin/PX4/PX4Resources.qrc @@ -23,12 +23,12 @@ ../../QmlControls/QGroundControl/PX4/qmldir - MavCmdInfoCommon.json - MavCmdInfoFixedWing.json - MavCmdInfoMultiRotor.json - MavCmdInfoRover.json - MavCmdInfoSub.json - MavCmdInfoVTOL.json + PX4-MavCmdInfoCommon.json + PX4-MavCmdInfoFixedWing.json + PX4-MavCmdInfoMultiRotor.json + PX4-MavCmdInfoRover.json + PX4-MavCmdInfoSub.json + PX4-MavCmdInfoVTOL.json ../../AutoPilotPlugins/PX4/AirframeFactMetaData.xml diff --git a/src/JsonHelper.cc b/src/JsonHelper.cc index 61b8a747e00e065ab1c43194e1e8ee819a9a3bee..5c5656a6c7f66abbd68cb9a03a2dd833299f0df5 100644 --- a/src/JsonHelper.cc +++ b/src/JsonHelper.cc @@ -10,12 +10,17 @@ #include "JsonHelper.h" #include "QGCQGeoCoordinate.h" #include "QmlObjectListModel.h" +#include "MissionCommandList.h" +#include "FactMetaData.h" +#include "QGCApplication.h" #include #include #include #include #include +#include +#include const char* JsonHelper::_enumStringsJsonKey = "enumStrings"; const char* JsonHelper::_enumValuesJsonKey = "enumValues"; @@ -23,6 +28,8 @@ const char* JsonHelper::jsonVersionKey = "version"; const char* JsonHelper::jsonGroundStationKey = "groundStation"; const char* JsonHelper::jsonGroundStationValue = "QGroundControl"; const char* JsonHelper::jsonFileTypeKey = "fileType"; +const char* JsonHelper::_translateKeysKey = "translateKeys"; +const char* JsonHelper::_arrayIDKeysKey = "_arrayIDKeys"; bool JsonHelper::validateRequiredKeys(const QJsonObject& jsonObject, const QStringList& keys, QString& errorString) { @@ -215,22 +222,19 @@ bool JsonHelper::isJsonFile(const QByteArray& bytes, QJsonDocument& jsonDoc, QSt } } -bool JsonHelper::validateQGCJsonFile(const QJsonObject& jsonObject, - const QString& expectedFileType, - int minSupportedVersion, - int maxSupportedVersion, - int& version, - QString& errorString) +bool JsonHelper::validateInternalQGCJsonFile(const QJsonObject& jsonObject, + const QString& expectedFileType, + int minSupportedVersion, + int maxSupportedVersion, + int& version, + QString& errorString) { - // Check for required keys - QStringList requiredKeys = { jsonFileTypeKey, jsonGroundStationKey, jsonVersionKey }; - if (!validateRequiredKeys(jsonObject, requiredKeys, errorString)) { - return false; - } - - // Validate base key types - QList typeList = { QJsonValue::String, QJsonValue::String }; - if (!validateKeyTypes(jsonObject, requiredKeys, typeList, errorString)) { + // Validate required keys + QList requiredKeys = { + { jsonFileTypeKey, QJsonValue::String, true }, + { jsonVersionKey, QJsonValue::Double, true }, + }; + if (!JsonHelper::validateKeys(jsonObject, requiredKeys, errorString)) { return false; } @@ -241,18 +245,8 @@ bool JsonHelper::validateQGCJsonFile(const QJsonObject& jsonObject, return false; } - // Check version - support both old style v1 string and new style integer - - QJsonValue versionValue = jsonObject[jsonVersionKey]; - if (versionValue.type() == QJsonValue::String && versionValue.toString() == QStringLiteral("1.0")) { - version = 1; - } else { - if (versionValue.type() != QJsonValue::Double) { - errorString = QObject::tr("Incorrect type for version value, must be integer"); - return false; - } - version = versionValue.toInt(); - } + // Version check + version = jsonObject[jsonVersionKey].toInt(); if (version < minSupportedVersion) { errorString = QObject::tr("File version %1 is no longer supported").arg(version); return false; @@ -265,6 +259,143 @@ bool JsonHelper::validateQGCJsonFile(const QJsonObject& jsonObject, return true; } +bool JsonHelper::validateExternalQGCJsonFile(const QJsonObject& jsonObject, + const QString& expectedFileType, + int minSupportedVersion, + int maxSupportedVersion, + int& version, + QString& errorString) +{ + // Validate required keys + QList requiredKeys = { + { jsonGroundStationKey, QJsonValue::String, true }, + }; + if (!JsonHelper::validateKeys(jsonObject, requiredKeys, errorString)) { + return false; + } + + return validateInternalQGCJsonFile(jsonObject, expectedFileType, minSupportedVersion, maxSupportedVersion, version, errorString); +} + +QStringList JsonHelper::_addDefaultLocKeys(QJsonObject& jsonObject) +{ + QString translateKeys; + QString fileType = jsonObject[jsonFileTypeKey].toString(); + if (!fileType.isEmpty()) { + if (fileType == MissionCommandList::qgcFileType) { + if (jsonObject.contains(_translateKeysKey)) { + translateKeys = jsonObject[_translateKeysKey].toString(); + } else { + translateKeys = "label,enumStrings,friendlyName,description,category"; + jsonObject[_translateKeysKey] = translateKeys; + } + if (!jsonObject.contains(_arrayIDKeysKey)) { + jsonObject[_arrayIDKeysKey] = "rawName,comment"; + } + } else if (fileType == FactMetaData::qgcFileType) { + if (jsonObject.contains(_translateKeysKey)) { + translateKeys = jsonObject[_translateKeysKey].toString(); + } else { + translateKeys = "shortDescription,longDescription,enumStrings"; + jsonObject[_translateKeysKey] = "shortDescription,longDescription,enumStrings"; + } + if (!jsonObject.contains(_arrayIDKeysKey)) { + jsonObject[_arrayIDKeysKey] = "name"; + } + } + } + return translateKeys.split(","); +} + +QJsonObject JsonHelper::_translateObject(QJsonObject& jsonObject, const QString& translateContext, const QStringList& translateKeys) +{ + for (const QString& key: jsonObject.keys()) { + if (jsonObject[key].isString()) { + QString locString = jsonObject[key].toString(); + if (translateKeys.contains(key)) { + QString disambiguation; + QString disambiguationPrefix("#loc.disambiguation#"); + + if (locString.startsWith(disambiguationPrefix)) { + locString = locString.right(locString.length() - disambiguationPrefix.length()); + int commentEndIndex = locString.indexOf("#"); + if (commentEndIndex != -1) { + disambiguation = locString.left(commentEndIndex); + locString = locString.right(locString.length() - disambiguation.length() - 1); + } + } + + QString xlatString = qgcApp()->qgcTranslator().translate(translateContext.toUtf8().constData(), locString.toUtf8().constData(), disambiguation.toUtf8().constData()); + if (!xlatString.isNull()) { + jsonObject[key] = xlatString; + } + } + } else if (jsonObject[key].isArray()) { + QJsonArray childJsonArray = jsonObject[key].toArray(); + jsonObject[key] = _translateArray(childJsonArray, translateContext, translateKeys); + } else if (jsonObject[key].isObject()) { + QJsonObject childJsonObject = jsonObject[key].toObject(); + jsonObject[key] = _translateObject(childJsonObject, translateContext, translateKeys); + } + } + + return jsonObject; +} + +QJsonArray JsonHelper::_translateArray(QJsonArray& jsonArray, const QString& translateContext, const QStringList& translateKeys) +{ + for (int i=0; i #include #include +#include /// @file /// @author Don Gagne @@ -23,6 +23,8 @@ class QmlObjectListModel; /// Primarily used for parsing and processing Fact metadata. class JsonHelper { + Q_DECLARE_TR_FUNCTIONS(JsonHelper) + public: /// Determines is the specified data is a json file /// @return true: file is json, false: file is not json @@ -35,17 +37,38 @@ public: const QString& fileType, ///< file type for file int version); ///< version number for file - /// Validates the standard parts of a QGC json file: + /// Validates the standard parts of an external QGC json file (Plan file, ...): + /// jsonFileTypeKey - Required and checked to be equal to expectedFileType + /// jsonVersionKey - Required and checked to be below supportedMajorVersion, supportedMinorVersion + /// jsonGroundStationKey - Required and checked to be string type + /// @return false: validation failed, errorString set + static bool validateExternalQGCJsonFile(const QJsonObject& jsonObject, ///< json object to validate + const QString& expectedFileType, ///< correct file type for file + int minSupportedVersion, ///< minimum supported version + int maxSupportedVersion, ///< maximum supported major version + int &version, ///< returned file version + QString& errorString); ///< returned error string if validation fails + + /// Validates the standard parts of a internal QGC json file (FactMetaData, ...): /// jsonFileTypeKey - Required and checked to be equal to expectedFileType /// jsonVersionKey - Required and checked to be below supportedMajorVersion, supportedMinorVersion /// jsonGroundStationKey - Required and checked to be string type /// @return false: validation failed, errorString set - static bool validateQGCJsonFile(const QJsonObject& jsonObject, ///< json object to validate - const QString& expectedFileType, ///< correct file type for file - int minSupportedVersion, ///< minimum supported version - int maxSupportedVersion, ///< maximum supported major version - int &version, ///< returned file version - QString& errorString); ///< returned error string if validation fails + static bool validateInternalQGCJsonFile(const QJsonObject& jsonObject, ///< json object to validate + const QString& expectedFileType, ///< correct file type for file + int minSupportedVersion, ///< minimum supported version + int maxSupportedVersion, ///< maximum supported major version + int &version, ///< returned file version + QString& errorString); ///< returned error string if validation fails + + // Opens, validates and translates an internal QGC json file. + // @return Json root object for file. Empty QJsonObject if error. + static QJsonObject openInternalQGCJsonFile(const QString& jsonFilename, ///< Json file to open + const QString& expectedFileType, ///< correct file type for file + int minSupportedVersion, ///< minimum supported version + int maxSupportedVersion, ///< maximum supported major version + int &version, ///< returned file version + QString& errorString); ///< returned error string if validation fails /// Validates that the specified keys are in the object /// @return false: validation failed, errorString set @@ -149,9 +172,13 @@ private: QJsonValue& jsonValue, bool geoJsonFormat); static bool _parseEnumWorker(const QJsonObject& jsonObject, QMap& defineMap, QStringList& enumStrings, QStringList& enumValues, QString& errorString, QString valueName); + static QStringList _addDefaultLocKeys(QJsonObject& jsonObject); + static QJsonObject _translateRoot(QJsonObject& jsonObject, const QString& translateContext, const QStringList& translateKeys); + static QJsonObject _translateObject(QJsonObject& jsonObject, const QString& translateContext, const QStringList& translateKeys); + static QJsonArray _translateArray(QJsonArray& jsonArray, const QString& translateContext, const QStringList& translateKeys); static const char* _enumStringsJsonKey; static const char* _enumValuesJsonKey; + static const char* _translateKeysKey; + static const char* _arrayIDKeysKey; }; - -#endif diff --git a/src/MissionManager/BreachReturn.FactMetaData.json b/src/MissionManager/BreachReturn.FactMetaData.json index fa7536ee26e79f2e7ea61e492407ff1c8a87f839..bc4146ee94e0829559554e57b536a2a99a33fac2 100644 --- a/src/MissionManager/BreachReturn.FactMetaData.json +++ b/src/MissionManager/BreachReturn.FactMetaData.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "Latitude", @@ -19,3 +23,4 @@ "units": "m" } ] +} diff --git a/src/MissionManager/CameraCalc.FactMetaData.json b/src/MissionManager/CameraCalc.FactMetaData.json index 2addaa89c990419b58f481d0eba245f4507e8792..36cf179784a248465932b9d15596616079fcb94d 100644 --- a/src/MissionManager/CameraCalc.FactMetaData.json +++ b/src/MissionManager/CameraCalc.FactMetaData.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "CameraName", @@ -66,3 +70,4 @@ "defaultValue": 25 } ] +} diff --git a/src/MissionManager/CameraSection.FactMetaData.json b/src/MissionManager/CameraSection.FactMetaData.json index 818a18d42e9beb2e170fb13dd3853bbe4733ee02..16323cd30d137a9e962969f552f8a358bebba50e 100644 --- a/src/MissionManager/CameraSection.FactMetaData.json +++ b/src/MissionManager/CameraSection.FactMetaData.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "CameraAction", @@ -56,3 +60,4 @@ "defaultValue": 0 } ] +} diff --git a/src/MissionManager/CameraSpec.FactMetaData.json b/src/MissionManager/CameraSpec.FactMetaData.json index f48ce287f4045180cd6dda3ea610e5a82cdc374a..da1402412e33eab54961bdbd5d9e15f8e56ecbc6 100644 --- a/src/MissionManager/CameraSpec.FactMetaData.json +++ b/src/MissionManager/CameraSpec.FactMetaData.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "Name", @@ -69,3 +73,4 @@ "defaultValue": 1.0 } ] +} diff --git a/src/MissionManager/CorridorScan.SettingsGroup.json b/src/MissionManager/CorridorScan.SettingsGroup.json index 78e0a7bb017ce004f72a8829ae7aa6cf3efac4d4..36a383cd8c436392769caafd64cf8257270904f8 100644 --- a/src/MissionManager/CorridorScan.SettingsGroup.json +++ b/src/MissionManager/CorridorScan.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "Altitude", @@ -44,3 +48,4 @@ "defaultValue": 30 } ] +} diff --git a/src/MissionManager/FWLandingPattern.FactMetaData.json b/src/MissionManager/FWLandingPattern.FactMetaData.json index 61906dd2ee964d795b17965c1200b6b26de27325..b34e1590289a6bf412bf7f4324a2208df757dc38 100644 --- a/src/MissionManager/FWLandingPattern.FactMetaData.json +++ b/src/MissionManager/FWLandingPattern.FactMetaData.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "LandingDistance", @@ -72,3 +76,4 @@ "defaultValue": true } ] +} diff --git a/src/MissionManager/MavCmdInfoCommon.json b/src/MissionManager/MavCmdInfoCommon.json index 56a42f9b5927985c38623a122366e49c6db17a28..4fca3c147b48c648ecd546b130ea5e5a276d4390 100644 --- a/src/MissionManager/MavCmdInfoCommon.json +++ b/src/MissionManager/MavCmdInfoCommon.json @@ -1,7 +1,7 @@ { "comment": "Any Firmware, Any Vehicle", - - "version": 1, + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ { diff --git a/src/MissionManager/MavCmdInfoFixedWing.json b/src/MissionManager/MavCmdInfoFixedWing.json index cb37109cf7416665e9ac1c9266e0aad90f15b19b..8d0c406d268837ea00c142871d25c6f6f850bd24 100644 --- a/src/MissionManager/MavCmdInfoFixedWing.json +++ b/src/MissionManager/MavCmdInfoFixedWing.json @@ -1,7 +1,7 @@ { - "comment": "Any Firmware, Fixed Wing", - - "version": 1, + "comment": "Any Firmware, Fixed Wing", + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ { diff --git a/src/MissionManager/MavCmdInfoMultiRotor.json b/src/MissionManager/MavCmdInfoMultiRotor.json index 90c4dec6676ce7a398da3008a1744cdc7f483123..da324399d55f36480e466162e56a3692461f7e23 100644 --- a/src/MissionManager/MavCmdInfoMultiRotor.json +++ b/src/MissionManager/MavCmdInfoMultiRotor.json @@ -1,7 +1,7 @@ { - "comment": "Any Firmware, Multi Rotor", - - "version": 1, + "comment": "Any Firmware, Multi Rotor", + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ ] diff --git a/src/MissionManager/MavCmdInfoRover.json b/src/MissionManager/MavCmdInfoRover.json index 41113dbcb85d545094e5b44f72d09e5c2cee590b..59fd1d2999ff43dbf526c7100804abbc28f85a93 100644 --- a/src/MissionManager/MavCmdInfoRover.json +++ b/src/MissionManager/MavCmdInfoRover.json @@ -1,7 +1,7 @@ { - "comment": "Any Firmware, Rover", - - "version": 1, + "comment": "Any Firmware, Rover", + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ ] diff --git a/src/MissionManager/MavCmdInfoSub.json b/src/MissionManager/MavCmdInfoSub.json index 6320020696e96929cd81aa8f8f83db92556deaf3..5839d2e38bd4b65ee06ded0abf398ad51baa19f9 100644 --- a/src/MissionManager/MavCmdInfoSub.json +++ b/src/MissionManager/MavCmdInfoSub.json @@ -1,7 +1,7 @@ { - "comment": "Any Firmware, Sub", - - "version": 1, + "comment": "Any Firmware, Sub", + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ ] diff --git a/src/MissionManager/MavCmdInfoVTOL.json b/src/MissionManager/MavCmdInfoVTOL.json index ffe4cac74c25c078914c8a8e01405149353a4788..22b59d8f4e34b58fed8d58262036e3afa5bac29c 100644 --- a/src/MissionManager/MavCmdInfoVTOL.json +++ b/src/MissionManager/MavCmdInfoVTOL.json @@ -1,7 +1,7 @@ { - "comment": "Any Firmware, VTOL", - - "version": 1, + "comment": "Any Firmware, VTOL", + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ ] diff --git a/src/MissionManager/MissionCommandList.cc b/src/MissionManager/MissionCommandList.cc index f156212a438d7f56ef349ab71e5127b56962b42d..5ca37136c841ec346b05a9e8642153ff1dcf4fbb 100644 --- a/src/MissionManager/MissionCommandList.cc +++ b/src/MissionManager/MissionCommandList.cc @@ -22,6 +22,7 @@ #include #include +const char* MissionCommandList::qgcFileType = "MavCmdInfo"; const char* MissionCommandList::_versionJsonKey = "version"; const char* MissionCommandList::_mavCmdInfoJsonKey = "mavCmdInfo"; @@ -39,30 +40,15 @@ void MissionCommandList::_loadMavCmdInfoJson(const QString& jsonFilename, bool b qCDebug(MissionCommandsLog) << "Loading" << jsonFilename; - QFile jsonFile(jsonFilename); - if (!jsonFile.open(QIODevice::ReadOnly | QIODevice::Text)) { - qWarning() << "Unable to open file" << jsonFilename << jsonFile.errorString(); + QString errorString; + int version; + QJsonObject jsonObject = JsonHelper::openInternalQGCJsonFile(jsonFilename, qgcFileType, 1, 1, version, errorString); + if (!errorString.isEmpty()) { + qWarning() << "Internal Error: " << errorString; return; } - QByteArray bytes = jsonFile.readAll(); - jsonFile.close(); - QJsonParseError jsonParseError; - QJsonDocument doc = QJsonDocument::fromJson(bytes, &jsonParseError); - if (jsonParseError.error != QJsonParseError::NoError) { - qWarning() << jsonFilename << "Unable to open json document" << jsonParseError.errorString(); - return; - } - - QJsonObject json = doc.object(); - - int version = json.value(_versionJsonKey).toInt(); - if (version != 1) { - qWarning() << jsonFilename << "Invalid version" << version; - return; - } - - QJsonValue jsonValue = json.value(_mavCmdInfoJsonKey); + QJsonValue jsonValue = jsonObject.value(_mavCmdInfoJsonKey); if (!jsonValue.isArray()) { qWarning() << jsonFilename << "mavCmdInfo not array"; return; diff --git a/src/MissionManager/MissionCommandList.h b/src/MissionManager/MissionCommandList.h index 433365e254d94e846415b1e18db8f3b67d1bbbfc..5c62199ee1ae818b8694623974e488b0b2aa5f15 100644 --- a/src/MissionManager/MissionCommandList.h +++ b/src/MissionManager/MissionCommandList.h @@ -7,8 +7,7 @@ * ****************************************************************************/ -#ifndef MissionCommandList_H -#define MissionCommandList_H +#pragma once #include "QGCToolbox.h" #include "QGCMAVLink.h" @@ -40,6 +39,8 @@ public: const QList& commandIds(void) const { return _ids; } + static const char* qgcFileType; + private: void _loadMavCmdInfoJson(const QString& jsonFilename, bool baseCommandList); @@ -50,5 +51,3 @@ private: static const char* _versionJsonKey; static const char* _mavCmdInfoJsonKey; }; - -#endif diff --git a/src/MissionManager/MissionCommandTree.cc b/src/MissionManager/MissionCommandTree.cc index bee62b823a9e54ff5fdecad7ca9defe0dfa8314a..40f66b1f035f8eeda81871c0294fc023ac437fc6 100644 --- a/src/MissionManager/MissionCommandTree.cc +++ b/src/MissionManager/MissionCommandTree.cc @@ -37,12 +37,12 @@ void MissionCommandTree::setToolbox(QGCToolbox* toolbox) #ifdef UNITTEST_BUILD if (_unitTest) { // Load unit testing tree - _staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_GENERIC] = new MissionCommandList(":/unittest/MavCmdInfoCommon.json", true, this); - _staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_FIXED_WING] = new MissionCommandList(":/unittest/MavCmdInfoFixedWing.json", false, this); - _staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_QUADROTOR] = new MissionCommandList(":/unittest/MavCmdInfoMultiRotor.json", false, this); - _staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_VTOL_QUADROTOR] = new MissionCommandList(":/unittest/MavCmdInfoVTOL.json", false, this); - _staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_SUBMARINE] = new MissionCommandList(":/unittest/MavCmdInfoSub.json", false, this); - _staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_GROUND_ROVER] = new MissionCommandList(":/unittest/MavCmdInfoRover.json", false, this); + _staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_GENERIC] = new MissionCommandList(":/unittest/UT-MavCmdInfoCommon.json", true, this); + _staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_FIXED_WING] = new MissionCommandList(":/unittest/UT-MavCmdInfoFixedWing.json", false, this); + _staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_QUADROTOR] = new MissionCommandList(":/unittest/UT-MavCmdInfoMultiRotor.json", false, this); + _staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_VTOL_QUADROTOR] = new MissionCommandList(":/unittest/UT-MavCmdInfoVTOL.json", false, this); + _staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_SUBMARINE] = new MissionCommandList(":/unittest/UT-MavCmdInfoSub.json", false, this); + _staticCommandTree[MAV_AUTOPILOT_GENERIC][MAV_TYPE_GROUND_ROVER] = new MissionCommandList(":/unittest/UT-MavCmdInfoRover.json", false, this); } else { #endif // Load all levels of hierarchy diff --git a/src/MissionManager/MissionCommandUIInfo.cc b/src/MissionManager/MissionCommandUIInfo.cc index 68b58370e9050208011fb0c8fb480fca43f525f3..2d822e2d8f74839081d065470aba9293b2a145b5 100644 --- a/src/MissionManager/MissionCommandUIInfo.cc +++ b/src/MissionManager/MissionCommandUIInfo.cc @@ -417,7 +417,7 @@ bool MissionCommandUIInfo::loadJsonInfo(const QJsonObject& jsonObject, bool requ paramInfo->_enumValues << QVariant(value); } if (paramInfo->_enumValues.count() != paramInfo->_enumStrings.count()) { - internalError = QString("enum strings/values count mismatch: %1, %2").arg(paramInfo->_enumStrings.count()).arg(paramInfo->_enumValues.count()); + internalError = QString("enum strings/values count mismatch, label:'%1' enumStrings:'%2'").arg(paramInfo->_label).arg(paramInfo->_enumStrings.join(",")); errorString = _loadErrorString(internalError); return false; } diff --git a/src/MissionManager/MissionController.cc b/src/MissionManager/MissionController.cc index aeffa6db473438750f4e5f2dfed3bc37d0b2ed2e..6fdd837a1c3ce6c297cc29179d0eac9d30907f70 100644 --- a/src/MissionManager/MissionController.cc +++ b/src/MissionManager/MissionController.cc @@ -872,7 +872,7 @@ bool MissionController::_loadItemsFromJson(const QJsonObject& json, QmlObjectLis } int fileVersion; - JsonHelper::validateQGCJsonFile(json, + JsonHelper::validateExternalQGCJsonFile(json, _jsonFileTypeValue, // expected file type 1, // minimum supported version 2, // maximum supported version diff --git a/src/MissionManager/MissionSettings.FactMetaData.json b/src/MissionManager/MissionSettings.FactMetaData.json index 9357d636f8b2747f060db616808644433a7658d6..f80616714281a50ddc29e4fd2557a5d646e80b70 100644 --- a/src/MissionManager/MissionSettings.FactMetaData.json +++ b/src/MissionManager/MissionSettings.FactMetaData.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "PlannedHomePositionAltitude", @@ -8,3 +12,4 @@ "defaultValue": 0 } ] +} diff --git a/src/MissionManager/PlanMasterController.cc b/src/MissionManager/PlanMasterController.cc index 09b3e9c3cc2c401a7689c27ecc25e8aa7a1cab4d..1695bcbf792705e4ef8e2897a9bf70f725a1f524 100644 --- a/src/MissionManager/PlanMasterController.cc +++ b/src/MissionManager/PlanMasterController.cc @@ -362,7 +362,7 @@ void PlanMasterController::loadFromFile(const QString& filename) qgcApp()->toolbox()->corePlugin()->preLoadFromJson(this, json); int version; - if (!JsonHelper::validateQGCJsonFile(json, kPlanFileType, kPlanFileVersion, kPlanFileVersion, version, errorString)) { + if (!JsonHelper::validateExternalQGCJsonFile(json, kPlanFileType, kPlanFileVersion, kPlanFileVersion, version, errorString)) { qgcApp()->showAppMessage(errorMessage.arg(errorString)); return; } diff --git a/src/MissionManager/QGCMapCircle.Facts.json b/src/MissionManager/QGCMapCircle.Facts.json index 2f496fa1d48a4054595d39c758f136c9beea4c09..2183c0b7367d524b7d34ce0c2405b42eb3d3bcf4 100644 --- a/src/MissionManager/QGCMapCircle.Facts.json +++ b/src/MissionManager/QGCMapCircle.Facts.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "Radius", @@ -8,3 +12,4 @@ "units": "m" } ] +} diff --git a/src/MissionManager/RallyPoint.FactMetaData.json b/src/MissionManager/RallyPoint.FactMetaData.json index 318f4ad8531e3ad88fa8f1a40cc7df522844ce01..27fef7732ff7c7e6a8ed44edd8c5cb619bf30cbf 100644 --- a/src/MissionManager/RallyPoint.FactMetaData.json +++ b/src/MissionManager/RallyPoint.FactMetaData.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "Latitude", @@ -20,3 +24,4 @@ "defaultValue": 0.0 } ] +} diff --git a/src/MissionManager/SpeedSection.FactMetaData.json b/src/MissionManager/SpeedSection.FactMetaData.json index 0a6f4368d3e431f68ff9948632da6c026ad0c6bb..ba4d6e73885c32f2e4dfbbb43ab0ccc914aa9fdb 100644 --- a/src/MissionManager/SpeedSection.FactMetaData.json +++ b/src/MissionManager/SpeedSection.FactMetaData.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "FlightSpeed", @@ -9,3 +13,4 @@ "defaultValue": 0 } ] +} diff --git a/src/MissionManager/StructureScan.SettingsGroup.json b/src/MissionManager/StructureScan.SettingsGroup.json index 8f3d1b2b6b9ac9b4989133d075837e11da0c9b4c..ff8aa42cda4293976f1380d3d07b6df78057d24a 100644 --- a/src/MissionManager/StructureScan.SettingsGroup.json +++ b/src/MissionManager/StructureScan.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "GimbalPitch", @@ -48,3 +52,4 @@ "defaultValue": true } ] +} diff --git a/src/MissionManager/Survey.SettingsGroup.json b/src/MissionManager/Survey.SettingsGroup.json index 9cf5fcf58b9c974c568bb8aaa463328ece6ab674..17eb154a762398c8392e5e0b161c003262508df7 100644 --- a/src/MissionManager/Survey.SettingsGroup.json +++ b/src/MissionManager/Survey.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "GridAngle", @@ -22,3 +26,4 @@ "defaultValue": false } ] +} diff --git a/src/MissionManager/TransectStyle.SettingsGroup.json b/src/MissionManager/TransectStyle.SettingsGroup.json index d6511689402bb02c05172736007971f59c3f5903..2f24f1038149b3aa03743bde9af7b59f8c13c8b3 100644 --- a/src/MissionManager/TransectStyle.SettingsGroup.json +++ b/src/MissionManager/TransectStyle.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "TurnAroundDistance", @@ -63,3 +67,4 @@ "defaultValue": 0 } ] +} diff --git a/src/MissionManager/UnitTest/MavCmdInfoMultiRotor.json b/src/MissionManager/UnitTest/MavCmdInfoMultiRotor.json deleted file mode 100644 index a8a83852d60fb7e50afc2f1d1d7f80b17c6bf376..0000000000000000000000000000000000000000 --- a/src/MissionManager/UnitTest/MavCmdInfoMultiRotor.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "comment": "Any Firmware, Multi Rotor (unit test)", - - "version": 1, - - "mavCmdInfo": [ - ] -} diff --git a/src/MissionManager/UnitTest/MavCmdInfoSub.json b/src/MissionManager/UnitTest/MavCmdInfoSub.json deleted file mode 100644 index b372eb6f6b243a103fbb5d4540ae8f872c5cd2c9..0000000000000000000000000000000000000000 --- a/src/MissionManager/UnitTest/MavCmdInfoSub.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "comment": "Any Firmware, Sub (unit test)", - - "version": 1, - - "mavCmdInfo": [ - ] -} diff --git a/src/MissionManager/UnitTest/MavCmdInfoVTOL.json b/src/MissionManager/UnitTest/MavCmdInfoVTOL.json deleted file mode 100644 index e7060a893866aa96551a82c0415dbd9c07855320..0000000000000000000000000000000000000000 --- a/src/MissionManager/UnitTest/MavCmdInfoVTOL.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "comment": "Any Firmware, VTOL (unit test)", - - "version": 1, - - "mavCmdInfo": [ - ] -} diff --git a/src/MissionManager/UnitTest/MavCmdInfoCommon.json b/src/MissionManager/UnitTest/UT-MavCmdInfoCommon.json similarity index 98% rename from src/MissionManager/UnitTest/MavCmdInfoCommon.json rename to src/MissionManager/UnitTest/UT-MavCmdInfoCommon.json index 76010b56c0213b394cbe58a5afe98be97a2e6ea6..c6dea22a43368399f572278865102d87aba2ae2d 100644 --- a/src/MissionManager/UnitTest/MavCmdInfoCommon.json +++ b/src/MissionManager/UnitTest/UT-MavCmdInfoCommon.json @@ -1,7 +1,7 @@ { - "comment": "Any Firmware, Any Vehicle (unit test)", - - "version": 1, + "comment": "Any Firmware, Any Vehicle (unit test)", + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ { diff --git a/src/MissionManager/UnitTest/MavCmdInfoFixedWing.json b/src/MissionManager/UnitTest/UT-MavCmdInfoFixedWing.json similarity index 93% rename from src/MissionManager/UnitTest/MavCmdInfoFixedWing.json rename to src/MissionManager/UnitTest/UT-MavCmdInfoFixedWing.json index f54c8c9f16a13ffaa9bae0aa22d7fb847d1e7f97..065e84acbc0b197c5d7c4a7dbd5046327be231d1 100644 --- a/src/MissionManager/UnitTest/MavCmdInfoFixedWing.json +++ b/src/MissionManager/UnitTest/UT-MavCmdInfoFixedWing.json @@ -1,7 +1,7 @@ { - "comment": "Any Firmware, Fixed Wing (unit test)", - - "version": 1, + "comment": "Any Firmware, Fixed Wing (unit test)", + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ { diff --git a/src/MissionManager/UnitTest/UT-MavCmdInfoMultiRotor.json b/src/MissionManager/UnitTest/UT-MavCmdInfoMultiRotor.json new file mode 100644 index 0000000000000000000000000000000000000000..869a91143bae1da2522ff12e63e926b75b12a8eb --- /dev/null +++ b/src/MissionManager/UnitTest/UT-MavCmdInfoMultiRotor.json @@ -0,0 +1,8 @@ +{ + "comment": "Any Firmware, Multi Rotor (unit test)", + "version": 1, + "fileType": "MavCmdInfo", + + "mavCmdInfo": [ + ] +} diff --git a/src/MissionManager/UnitTest/MavCmdInfoRover.json b/src/MissionManager/UnitTest/UT-MavCmdInfoRover.json similarity index 62% rename from src/MissionManager/UnitTest/MavCmdInfoRover.json rename to src/MissionManager/UnitTest/UT-MavCmdInfoRover.json index 40d422fce7d510a05d4cfa0d17550cfa03983db4..e452c794cb73792c52408a54da3608a66b24b646 100644 --- a/src/MissionManager/UnitTest/MavCmdInfoRover.json +++ b/src/MissionManager/UnitTest/UT-MavCmdInfoRover.json @@ -1,7 +1,7 @@ { "comment": "Any Firmware, Rover (unit test)", - - "version": 1, + "version": 1, + "fileType": "MavCmdInfo", "mavCmdInfo": [ ] diff --git a/src/MissionManager/UnitTest/UT-MavCmdInfoSub.json b/src/MissionManager/UnitTest/UT-MavCmdInfoSub.json new file mode 100644 index 0000000000000000000000000000000000000000..1b5a68c2495bf22fc2d098007fe280bc84b15414 --- /dev/null +++ b/src/MissionManager/UnitTest/UT-MavCmdInfoSub.json @@ -0,0 +1,8 @@ +{ + "comment": "Any Firmware, Sub (unit test)", + "version": 1, + "fileType": "MavCmdInfo", + + "mavCmdInfo": [ + ] +} diff --git a/src/MissionManager/UnitTest/UT-MavCmdInfoVTOL.json b/src/MissionManager/UnitTest/UT-MavCmdInfoVTOL.json new file mode 100644 index 0000000000000000000000000000000000000000..18713408e784ecab3c4aa4c70ab11da297ec27d1 --- /dev/null +++ b/src/MissionManager/UnitTest/UT-MavCmdInfoVTOL.json @@ -0,0 +1,8 @@ +{ + "comment": "Any Firmware, VTOL (unit test)", + "version": 1, + "fileType": "MavCmdInfo", + + "mavCmdInfo": [ + ] +} diff --git a/src/MissionManager/VTOLLandingPattern.FactMetaData.json b/src/MissionManager/VTOLLandingPattern.FactMetaData.json index 2ccd0a5d83adb41afdbb6cc2569a9c00f9e03d25..6715a7dfbfacedb1124be350283a98779cb19802 100644 --- a/src/MissionManager/VTOLLandingPattern.FactMetaData.json +++ b/src/MissionManager/VTOLLandingPattern.FactMetaData.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "LandingDistance", @@ -56,3 +60,4 @@ "defaultValue": true } ] +} diff --git a/src/PlanView/GeoFenceEditor.qml b/src/PlanView/GeoFenceEditor.qml index 667b6d37d84d99a21bdf9698550d9d96e7c8c751..a9156388278726c57de7e8e6a890e457261b26b5 100644 --- a/src/PlanView/GeoFenceEditor.qml +++ b/src/PlanView/GeoFenceEditor.qml @@ -62,7 +62,7 @@ QGCFlickable { wrapMode: Text.WordWrap font.pointSize: myGeoFenceController.supported ? ScreenTools.smallFontPointSize : ScreenTools.defaultFontPointSize text: myGeoFenceController.supported ? - qsTr("GeoFencing allows you to set a virtual ‘fence’ around the area you want to fly in.") : + qsTr("GeoFencing allows you to set a virtual fence around the area you want to fly in.") : qsTr("This vehicle does not support GeoFence.") } diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 34671d22b14f835afaadd5496340c1da816df2fb..3c14a33ca36062f2bfdabb6c733019c2084289a0 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -356,7 +356,6 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) } #endif /* __mobile__ */ - setLanguage(); _checkForNewVersion(); } diff --git a/src/QGCApplication.h b/src/QGCApplication.h index bf851fcaa792e22d4c412500e23fa6f63e3640bd..c8e054f9eb158a10aa2983cbff0b1840e28f7e94 100644 --- a/src/QGCApplication.h +++ b/src/QGCApplication.h @@ -98,6 +98,8 @@ public: FactGroup* gpsRtkFactGroup(void) { return _gpsRtkFactGroup; } + QTranslator& qgcTranslator(void) { return _QGCTranslator; } + static QString cachedParameterMetaDataFile(void); static QString cachedAirframeMetaDataFile(void); diff --git a/src/QGCToolbox.cc b/src/QGCToolbox.cc index a6bbeef1a6f4027a9227361b9e5b12cc287cee8d..d3583a4729c1ecfd64ef67ecb205522736aee37a 100644 --- a/src/QGCToolbox.cc +++ b/src/QGCToolbox.cc @@ -98,6 +98,10 @@ void QGCToolbox::setChildToolboxes(void) { // SettingsManager must be first so settings are available to any subsequent tools _settingsManager->setToolbox(this); + + // We now know the language setting to setup the translators. This makes the translators available to the subsequence tools. + qgcApp()->setLanguage(); + _corePlugin->setToolbox(this); _audioOutput->setToolbox(this); _factSystem->setToolbox(this); diff --git a/src/QmlControls/EditPositionDialog.FactMetaData.json b/src/QmlControls/EditPositionDialog.FactMetaData.json index c136759e6847c069d008620442896f5db166d4d6..76a19a2c7f73bd30ebda901f6ad3f91389a7d378 100644 --- a/src/QmlControls/EditPositionDialog.FactMetaData.json +++ b/src/QmlControls/EditPositionDialog.FactMetaData.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "Latitude", @@ -47,3 +51,4 @@ "type": "string" } ] +} diff --git a/src/QmlControls/RCToParamDialog.FactMetaData.json b/src/QmlControls/RCToParamDialog.FactMetaData.json index 63d3af9a6fa0b0862c9be1f0c037735121186b99..e13cf5fde5b7a9920d17682f3c5ebb04387ff091 100644 --- a/src/QmlControls/RCToParamDialog.FactMetaData.json +++ b/src/QmlControls/RCToParamDialog.FactMetaData.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "Scale", @@ -29,3 +33,4 @@ "decimalPlaces": 7 } ] +} diff --git a/src/Settings/ADSBVehicleManager.SettingsGroup.json b/src/Settings/ADSBVehicleManager.SettingsGroup.json index 62500d7b4b8f33f3fcc1d3399849fba3025d0da4..82ff9fb465d3352a33b9d9e0eb68ce56006734e0 100644 --- a/src/Settings/ADSBVehicleManager.SettingsGroup.json +++ b/src/Settings/ADSBVehicleManager.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "adsbServerConnectEnabled", @@ -22,3 +26,4 @@ "qgcRebootRequired": true } ] +} diff --git a/src/Settings/APMMavlinkStreamRate.SettingsGroup.json b/src/Settings/APMMavlinkStreamRate.SettingsGroup.json index 954b079dc269972e80b104a1f93782ddabcde55c..53c875ed24a4aff946a89ca131299ba6e4cd345d 100644 --- a/src/Settings/APMMavlinkStreamRate.SettingsGroup.json +++ b/src/Settings/APMMavlinkStreamRate.SettingsGroup.json @@ -1,4 +1,7 @@ { + "version": 1, + "fileType": "FactMetaData", + "translateKeys": "StreamRateEnumStrings", "QGC.MetaData.Defines": { "StreamRateEnumStrings": "Controlled By Vehicle,0 hz,1 hz,2 hz,3 hz,4 hz,5 hz,6 hz,7 hz,8 hz,9 hz,10 hz,50 hz,100 hz", "StreamRateEnumValues": "-1,0,1,2,3,4,5,6,7,8,9,10,50,100" diff --git a/src/Settings/App.SettingsGroup.json b/src/Settings/App.SettingsGroup.json index f1312c92b069afbd76a1c9437c600937d1be3a84..3f212dd79e9358805237ee605248f4aa03a03f7a 100644 --- a/src/Settings/App.SettingsGroup.json +++ b/src/Settings/App.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "offlineEditingFirmwareType", @@ -285,3 +289,4 @@ "defaultValue": true } ] +} diff --git a/src/Settings/AutoConnect.SettingsGroup.json b/src/Settings/AutoConnect.SettingsGroup.json index abbec2da6b32272a373d5376cf831c21706f87c4..2603c3339cea61c78a880c31898a67b65f670ad6 100644 --- a/src/Settings/AutoConnect.SettingsGroup.json +++ b/src/Settings/AutoConnect.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "autoConnectUDP", @@ -80,3 +84,4 @@ "defaultValue": 14401 } ] +} diff --git a/src/Settings/BrandImage.SettingsGroup.json b/src/Settings/BrandImage.SettingsGroup.json index df61322da50b000ae74e7393a914ac030f8a14db..2b7c861d83fb44f118dba64ba55b222590a7a640 100644 --- a/src/Settings/BrandImage.SettingsGroup.json +++ b/src/Settings/BrandImage.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "userBrandImageIndoor", @@ -14,3 +18,4 @@ "defaultValue": "" } ] +} diff --git a/src/Settings/FirmwareUpgrade.SettingsGroup.json b/src/Settings/FirmwareUpgrade.SettingsGroup.json index 97711ac1210c27ee1d712dcbab1d5d804283ae1b..8deb4d6fe5c13eac869935e54aa082a68bb9bc87 100644 --- a/src/Settings/FirmwareUpgrade.SettingsGroup.json +++ b/src/Settings/FirmwareUpgrade.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "defaultFirmwareType", @@ -20,3 +24,4 @@ "defaultValue": 0 } ] +} diff --git a/src/Settings/FlightMap.SettingsGroup.json b/src/Settings/FlightMap.SettingsGroup.json index 14135cdddc4d133bab7130c9cc77cb297f7d5976..89c089be99375acea0c2696b5bc7bab1c6054610 100644 --- a/src/Settings/FlightMap.SettingsGroup.json +++ b/src/Settings/FlightMap.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "mapProvider", @@ -12,3 +16,4 @@ "defaultValue": "Hybrid" } ] +} diff --git a/src/Settings/FlyView.SettingsGroup.json b/src/Settings/FlyView.SettingsGroup.json index 118f6cadccd694055676bb0c23832a95dea493da..4773b5658419ea76035c2e640be7d9c88c3f8255 100644 --- a/src/Settings/FlyView.SettingsGroup.json +++ b/src/Settings/FlyView.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "guidedMinimumAltitude", @@ -52,3 +56,4 @@ "min": 1 } ] +} diff --git a/src/Settings/OfflineMaps.SettingsGroup.json b/src/Settings/OfflineMaps.SettingsGroup.json index 48b7bad5f3ab82188ee0ae69dca4600f9f70dcb0..8a3a12459bc0a90221763fce2d9ce00731aa42d3 100644 --- a/src/Settings/OfflineMaps.SettingsGroup.json +++ b/src/Settings/OfflineMaps.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "minZoomLevelDownload", @@ -22,3 +26,4 @@ "defaultValue": 100000 } ] +} diff --git a/src/Settings/PlanView.SettingsGroup.json b/src/Settings/PlanView.SettingsGroup.json index dcb198bc95f712442b53fdf7721a4586c52beeca..402efd25914a84b21599e63a9edf28f52b0248e9 100644 --- a/src/Settings/PlanView.SettingsGroup.json +++ b/src/Settings/PlanView.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "displayPresetsTabFirst", @@ -30,3 +34,4 @@ "defaultValue": false } ] +} diff --git a/src/Settings/RTK.SettingsGroup.json b/src/Settings/RTK.SettingsGroup.json index 72b797d3eba72134011dad03b00cc64368cb2a6c..928b807426ba0e3d5782726d9460891adc197de7 100644 --- a/src/Settings/RTK.SettingsGroup.json +++ b/src/Settings/RTK.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "surveyInAccuracyLimit", @@ -72,3 +76,4 @@ "qgcRebootRequired": true } ] +} diff --git a/src/Settings/Units.SettingsGroup.json b/src/Settings/Units.SettingsGroup.json index 0d4f101c7a37a4c875e6999bee1a287fdb733380..9bdf73105f3d6e6ef11e000b9bb8141b85e038cf 100644 --- a/src/Settings/Units.SettingsGroup.json +++ b/src/Settings/Units.SettingsGroup.json @@ -1,2 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ ] +} diff --git a/src/Settings/Video.SettingsGroup.json b/src/Settings/Video.SettingsGroup.json index c9cd28a0407e4290250394e2c70abca56880acfb..06dcc9b19ff0247bc78dc5df8c47d2fbe6429a21 100644 --- a/src/Settings/Video.SettingsGroup.json +++ b/src/Settings/Video.SettingsGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "videoSource", @@ -126,3 +130,4 @@ "defaultValue": false } ] +} diff --git a/src/Vehicle/BatteryFact.json b/src/Vehicle/BatteryFact.json index 9521501cf9bc300d3ee78f610013edb423c28fdb..cfca6c44a9f2a522a147e033e458a38dfbf530ca 100644 --- a/src/Vehicle/BatteryFact.json +++ b/src/Vehicle/BatteryFact.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "voltage", @@ -57,3 +61,4 @@ "decimalPlaces": 0 } ] +} diff --git a/src/Vehicle/ClockFact.json b/src/Vehicle/ClockFact.json index dc233f9ca1003d8285accc84a216f69d447671bd..592a636341c0e982b94f230b5434773b5ce710c8 100644 --- a/src/Vehicle/ClockFact.json +++ b/src/Vehicle/ClockFact.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "currentTime", @@ -10,3 +14,4 @@ "type": "string" } ] +} diff --git a/src/Vehicle/DistanceSensorFact.json b/src/Vehicle/DistanceSensorFact.json index 97f2837e49065a48f6f9ca939c641ea40e3eec78..3ef83db0f98f5086d515303d4280809615841d2c 100644 --- a/src/Vehicle/DistanceSensorFact.json +++ b/src/Vehicle/DistanceSensorFact.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "rotationNone", @@ -70,3 +74,4 @@ "units": "m" } ] +} diff --git a/src/Vehicle/EstimatorStatusFactGroup.json b/src/Vehicle/EstimatorStatusFactGroup.json index 6a1d3cea067d1dd3e0d60aeded756b1e37edf4c6..99b10f969e0bb5d9f116fe5120521239b8bc34e2 100644 --- a/src/Vehicle/EstimatorStatusFactGroup.json +++ b/src/Vehicle/EstimatorStatusFactGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "goodAttitudeEsimate", @@ -128,3 +132,4 @@ "default": null } ] +} diff --git a/src/Vehicle/GPSFact.json b/src/Vehicle/GPSFact.json index 3f7fe68437f25369a8b5a509c9648b397fd30d5f..f8f44aeda0b7f1b653b4c87b9f77a64559c9d7a3 100644 --- a/src/Vehicle/GPSFact.json +++ b/src/Vehicle/GPSFact.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "lat", @@ -49,3 +53,4 @@ "type": "uint32" } ] +} diff --git a/src/Vehicle/GPSRTKFact.json b/src/Vehicle/GPSRTKFact.json index 638bebf21ca04ab20eeb303ce1eb26b70c50c7cd..ad3abbe8f5009dc248e6f43077c4d6da2b862641 100644 --- a/src/Vehicle/GPSRTKFact.json +++ b/src/Vehicle/GPSRTKFact.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "connected", @@ -61,3 +65,4 @@ "default": 0 } ] +} diff --git a/src/Vehicle/SetpointFact.json b/src/Vehicle/SetpointFact.json index 58fea58334a8866ee4661454452bee925e16a99d..ec39e1c63831d5e96229d2f4f44cd6e5a60cd0c4 100644 --- a/src/Vehicle/SetpointFact.json +++ b/src/Vehicle/SetpointFact.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "roll", @@ -42,3 +46,4 @@ "units": "deg/s" } ] +} diff --git a/src/Vehicle/SubmarineFact.json b/src/Vehicle/SubmarineFact.json index 527a14f2a44575f6da98b48d27c263b49ab4c74c..2c5961dc9263220dc889077997c41f7f93906f0a 100644 --- a/src/Vehicle/SubmarineFact.json +++ b/src/Vehicle/SubmarineFact.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "camera tilt", @@ -43,3 +47,4 @@ "units": "meters" } ] +} diff --git a/src/Vehicle/TemperatureFact.json b/src/Vehicle/TemperatureFact.json index 01cfb25e7702b34dc28111e250374286cc3b9ae8..4eec68bbd5049444f19871e5e5cb22f8c840e01d 100644 --- a/src/Vehicle/TemperatureFact.json +++ b/src/Vehicle/TemperatureFact.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "temperature1", @@ -21,3 +25,4 @@ "units": "C" } ] +} diff --git a/src/Vehicle/TerrainFactGroup.json b/src/Vehicle/TerrainFactGroup.json index d29047346b0815233b72b68071814272f13615de..4c131c43a84e70caae743e737463ed4d1f767a53 100644 --- a/src/Vehicle/TerrainFactGroup.json +++ b/src/Vehicle/TerrainFactGroup.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "blocksPending", @@ -14,3 +18,4 @@ "default": 0 } ] +} diff --git a/src/Vehicle/VehicleFact.json b/src/Vehicle/VehicleFact.json index 41aaf28eaf1a95c994ba0a169ebcda9b7e3ba6ed..52bc3b9af7b05665035988b88d17fa166c1d06a8 100644 --- a/src/Vehicle/VehicleFact.json +++ b/src/Vehicle/VehicleFact.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "roll", @@ -134,3 +138,4 @@ "units": "%" } ] +} diff --git a/src/Vehicle/VibrationFact.json b/src/Vehicle/VibrationFact.json index e56b5ea5c8f6db7795724a41537797ddbfe2dd53..b05e306d83e88a1475616de6dd2275e774748907 100644 --- a/src/Vehicle/VibrationFact.json +++ b/src/Vehicle/VibrationFact.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "xAxis", @@ -33,3 +37,4 @@ "type": "uint32" } ] +} diff --git a/src/Vehicle/WindFact.json b/src/Vehicle/WindFact.json index ce2029406dbc015e64908d420bd6de88e4b2dadb..0a84368afd20691725dc3ae04c92bf372326ea95 100644 --- a/src/Vehicle/WindFact.json +++ b/src/Vehicle/WindFact.json @@ -1,3 +1,7 @@ +{ + "version": 1, + "fileType": "FactMetaData", + "QGC.MetaData.Facts": [ { "name": "direction", @@ -21,4 +25,4 @@ "units": "m/s" } ] - +} diff --git a/src/comm/QGCSerialPortInfo.cc b/src/comm/QGCSerialPortInfo.cc index 488f641c3e599fb3dadcb7239b0b4afdcab23726..4cf191454c77d3af75447b683ece018b010ea28e 100644 --- a/src/comm/QGCSerialPortInfo.cc +++ b/src/comm/QGCSerialPortInfo.cc @@ -80,12 +80,12 @@ void QGCSerialPortInfo::_loadJsonData(void) int fileVersion; QString errorString; - if (!JsonHelper::validateQGCJsonFile(json, - _jsonFileTypeValue, // expected file type - 1, // minimum supported version - 1, // maximum supported version - fileVersion, - errorString)) { + if (!JsonHelper::validateInternalQGCJsonFile(json, + _jsonFileTypeValue, // expected file type + 1, // minimum supported version + 1, // maximum supported version + fileVersion, + errorString)) { qWarning() << errorString; return; } diff --git a/src/comm/USBBoardInfo.json b/src/comm/USBBoardInfo.json index 46c29a3adbc3c88581f1a78c3f06e3ecdd9b53b6..fc085fbcbfaf82f173d2501058385fec44e56143 100644 --- a/src/comm/USBBoardInfo.json +++ b/src/comm/USBBoardInfo.json @@ -1,9 +1,7 @@ { "comment": "AutoConnect usb board info", - - "version": 1, - "fileType": "USBBoardInfo", - "groundStation": "QGroundControl", + "version": 1, + "fileType": "USBBoardInfo", "boardInfo": [ { "vendorID": 9900, "productID": 16, "boardClass": "Pixhawk", "name": "PX4 FMU V1" },