diff --git a/UnitTest.qrc b/UnitTest.qrc index 2bfa5bb..4f29c94 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 fd5ea12..d7d5e2c 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 0000000..abcc8de --- /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 4ca1455..78101bb 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 2f2181e..c38ba29 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 7d02697..606f432 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 340144a..376348e 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 719f5e3..a99e1a3 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 f3a3c2d..a79cf2d 100644 --- a/src/FactSystem/FactMetaData.cc +++ b/src/FactSystem/FactMetaData.cc @@ -40,6 +40,7 @@ const qreal FactMetaData::UnitConsts_s::poundsToGrams = 453.592; 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"; @@ -1359,45 +1360,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 e63d307..c8435d3 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 @@ -190,6 +185,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; @@ -329,5 +326,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 1226035..aee59c1 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 9cca751..d647b66 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 4d47dac..2170b70 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 0000000..d243f13 --- /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 0000000..45c5962 --- /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 0000000..e94cf27 --- /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 9a035ce..4f0480f 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 363bc84..19e04df 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 941b0b6..0000000 --- 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 0e24869..0000000 --- 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 a486ae1..0000000 --- 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 12c5342..0000000 --- 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 2402c0f..0000000 --- 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 e719d6e..0000000 --- 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 e2d418e..0000000 --- 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 8657261..3182be6 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 0000000..836056d --- /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 ae9917c..cc37c64 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 0000000..2dde98e --- /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 0000000..632f92c --- /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 0000000..e03df84 --- /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 cdb2baf..9e70bff 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 2418d5a..8b370c1 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 61b8a74..5c5656a 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 fa7536e..bc4146e 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 2addaa8..36cf179 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 818a18d..16323cd 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/CameraSectionTest.cc b/src/MissionManager/CameraSectionTest.cc index f6dfb63..1e2f3c7 100644 --- a/src/MissionManager/CameraSectionTest.cc +++ b/src/MissionManager/CameraSectionTest.cc @@ -126,19 +126,19 @@ void CameraSectionTest::init(void) void CameraSectionTest::cleanup(void) { - delete _spyCamera; - delete _spySection; - delete _validGimbalItem; - delete _validDistanceItem; - delete _validTimeItem; - delete _validStartVideoItem; - delete _validStopVideoItem; - delete _validStopDistanceItem; - delete _validStopTimeItem; - delete _validTakePhotoItem; - delete _validCameraPhotoModeItem; - delete _validCameraVideoModeItem; - delete _validCameraSurveyPhotoModeItem; + _spyCamera->deleteLater(); + _spySection->deleteLater(); + _validGimbalItem->deleteLater(); + _validDistanceItem->deleteLater(); + _validTimeItem->deleteLater(); + _validStartVideoItem->deleteLater(); + _validStopVideoItem->deleteLater(); + _validStopDistanceItem->deleteLater(); + _validStopTimeItem->deleteLater(); + _validTakePhotoItem->deleteLater(); + _validCameraPhotoModeItem->deleteLater(); + _validCameraVideoModeItem->deleteLater(); + _validCameraSurveyPhotoModeItem->deleteLater(); SectionTest::cleanup(); } diff --git a/src/MissionManager/CameraSpec.FactMetaData.json b/src/MissionManager/CameraSpec.FactMetaData.json index f48ce28..da14024 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 78e0a7b..36a383c 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 61906dd..b34e159 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 56a42f9..4fca3c1 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 cb37109..8d0c406 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 90c4dec..da32439 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 41113db..59fd1d2 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 6320020..5839d2e 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 ffe4cac..22b59d8 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 f156212..5ca3713 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 433365e..5c62199 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 bee62b8..40f66b1 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 68b5837..2d822e2 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 aeffa6d..6fdd837 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 9357d63..f806167 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 09b3e9c..1695bcb 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 2f496fa..2183c0b 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 318f4ad..27fef77 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/SectionTest.cc b/src/MissionManager/SectionTest.cc index 2efe864..d633dc7 100644 --- a/src/MissionManager/SectionTest.cc +++ b/src/MissionManager/SectionTest.cc @@ -42,7 +42,7 @@ void SectionTest::init(void) void SectionTest::cleanup(void) { - delete _simpleItem; + _simpleItem->deleteLater(); VisualMissionItemTest::cleanup(); } diff --git a/src/MissionManager/SpeedSection.FactMetaData.json b/src/MissionManager/SpeedSection.FactMetaData.json index 0a6f436..ba4d6e7 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 8f3d1b2..ff8aa42 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 9cf5fcf..17eb154 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 d651168..2f24f10 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 a8a8385..0000000 --- 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 b372eb6..0000000 --- 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 e7060a8..0000000 --- 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 76010b5..c6dea22 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 f54c8c9..065e84a 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 0000000..869a911 --- /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 40d422f..e452c79 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 0000000..1b5a68c --- /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 0000000..1871340 --- /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 2ccd0a5..6715a7d 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/MissionManager/VisualMissionItemTest.cc b/src/MissionManager/VisualMissionItemTest.cc index 083dcf1..9b5b749 100644 --- a/src/MissionManager/VisualMissionItemTest.cc +++ b/src/MissionManager/VisualMissionItemTest.cc @@ -51,8 +51,8 @@ void VisualMissionItemTest::init(void) void VisualMissionItemTest::cleanup(void) { - _masterController->deleteLater(); UnitTest::cleanup(); + _masterController->deleteLater(); } void VisualMissionItemTest::_createSpy(SimpleMissionItem* simpleItem, MultiSignalSpy** visualSpy) diff --git a/src/PlanView/GeoFenceEditor.qml b/src/PlanView/GeoFenceEditor.qml index 667b6d3..a915638 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 34671d2..3c14a33 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 bf851fc..c8e054f 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 a6bbeef..d3583a4 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 c136759..76a19a2 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 63d3af9..e13cf5f 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 62500d7..82ff9fb 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 954b079..53c875e 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 f1312c9..3f212dd 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 abbec2d..2603c33 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 df61322..2b7c861 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 97711ac..8deb4d6 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 14135cd..89c089b 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 118f6ca..4773b56 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 48b7bad..8a3a124 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 dcb198b..402efd2 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 72b797d..928b807 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 0d4f101..9bdf731 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 c9cd28a..06dcc9b 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 9521501..cfca6c4 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 dc233f9..592a636 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 97f2837..3ef83db 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 6a1d3ce..99b10f9 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 3f7fe68..f8f44ae 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 638bebf..ad3abbe 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 58fea58..ec39e1c 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 527a14f..2c5961d 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 01cfb25..4eec68b 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 d290473..4c131c4 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 41aaf28..52bc3b9 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 e56b5ea..b05e306 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 ce20294..0a84368 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 488f641..4cf1914 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 46c29a3..fc085fb 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" }, diff --git a/src/qgcunittest/UnitTest.cc b/src/qgcunittest/UnitTest.cc index cb4c661..30cf1c4 100644 --- a/src/qgcunittest/UnitTest.cc +++ b/src/qgcunittest/UnitTest.cc @@ -136,9 +136,6 @@ void UnitTest::cleanup(void) _disconnectMockLink(); _closeMainWindow(); - // We add a slight delay here to allow for deleteLater and Qml cleanup - QTest::qWait(200); - // Keep in mind that any code below these QCOMPARE may be skipped if the compare fails if (_expectMissedMessageBox) { QEXPECT_FAIL("", "Expecting failure due internal testing", Continue);