Improve plugin json parsing and fix generate-plugininfo script
This commit is contained in:
parent
bb5826de87
commit
023a223908
@ -140,30 +140,20 @@
|
||||
"id": "uuid",
|
||||
"name": "deviceClassName",
|
||||
"displayName": "The name of the device class (translatable)",
|
||||
"o:createMethods": [ ],
|
||||
"o:setupMethod": "SetupMethod",
|
||||
"o:deviceIcon": "Icon",
|
||||
"o:interfaces": [ "interfacename" ],
|
||||
"o:basicTags": [
|
||||
"BasicTag"
|
||||
],
|
||||
"createMethods": [
|
||||
"CreateMethod"
|
||||
],
|
||||
"o:interfaces" [ "connectable" ],
|
||||
"o:setupMethod": "SetupMethod",
|
||||
"o:basicTags": [ ],
|
||||
"o:pairingInfo": "Information how to pair the device. (translatable)",
|
||||
"o:criticalStateTypeId": "uuid",
|
||||
"o:primaryStateTypeId": "uuid",
|
||||
"o:primaryActionTypeId": "uuid",
|
||||
"o:discoveryParamTypes": [
|
||||
],
|
||||
"paramTypes": [
|
||||
],
|
||||
"o:stateTypes": [
|
||||
],
|
||||
"o:actionTypes": [
|
||||
],
|
||||
"o:eventTypes": [
|
||||
]
|
||||
"o:discoveryParamTypes": [ ],
|
||||
"o:paramTypes": [ ],
|
||||
"o:stateTypes": [ ],
|
||||
"o:actionTypes": [ ],
|
||||
"o:eventTypes": [ ]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@ -302,15 +302,22 @@ void DevicePlugin::initPlugin(DeviceManager *deviceManager)
|
||||
|
||||
QPair<bool, QList<ParamType> > DevicePlugin::parseParamTypes(const QJsonArray &array) const
|
||||
{
|
||||
int index = 0;
|
||||
QList<ParamType> paramTypes;
|
||||
foreach (const QJsonValue ¶mTypesJson, array) {
|
||||
QJsonObject pt = paramTypesJson.toObject();
|
||||
|
||||
// Check fields
|
||||
int index = 0;
|
||||
QStringList missingFields = verifyFields(QStringList() << "id" << "name" << "displayName" << "type", pt);
|
||||
if (!missingFields.isEmpty()) {
|
||||
qCWarning(dcDeviceManager) << pluginName() << "Error parsing ParamType: missing fields" << missingFields.join(", ") << endl << pt;
|
||||
QPair<QStringList, QStringList> verificationResult = verifyFields(ParamType::jsonProperties(), ParamType::mandatoryJsonProperties(), pt);
|
||||
|
||||
// Check mandatory fields
|
||||
if (!verificationResult.first.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << pluginName() << "Error parsing ParamType: missing fields:" << verificationResult.first.join(", ") << endl << pt;
|
||||
return QPair<bool, QList<ParamType> >(false, QList<ParamType>());
|
||||
}
|
||||
|
||||
// Check if there are any unknown fields
|
||||
if (!verificationResult.second.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << pluginName() << "Error parsing ParamType: unknown fields:" << verificationResult.second.join(", ") << endl << pt;
|
||||
return QPair<bool, QList<ParamType> >(false, QList<ParamType>());
|
||||
}
|
||||
|
||||
@ -325,7 +332,7 @@ QPair<bool, QList<ParamType> > DevicePlugin::parseParamTypes(const QJsonArray &a
|
||||
|
||||
ParamType paramType(ParamTypeId(pt.value("id").toString()), pt.value("name").toString(), t, pt.value("defaultValue").toVariant());
|
||||
paramType.setDisplayName(translateValue(m_metaData.value("name").toString(), pt.value("displayName").toString()));
|
||||
paramType.setIndex(index);
|
||||
|
||||
|
||||
// Set allowed values
|
||||
QVariantList allowedValues;
|
||||
@ -361,12 +368,35 @@ QPair<bool, QList<ParamType> > DevicePlugin::parseParamTypes(const QJsonArray &a
|
||||
|
||||
paramType.setAllowedValues(allowedValues);
|
||||
paramType.setLimits(pt.value("minValue").toVariant(), pt.value("maxValue").toVariant());
|
||||
paramType.setIndex(index++);
|
||||
paramTypes.append(paramType);
|
||||
}
|
||||
|
||||
return QPair<bool, QList<ParamType> >(true, paramTypes);
|
||||
}
|
||||
|
||||
QPair<QStringList, QStringList> DevicePlugin::verifyFields(const QStringList &possibleFields, const QStringList &mandatoryFields, const QJsonObject &value) const
|
||||
{
|
||||
QStringList missingFields;
|
||||
QStringList unknownFields;
|
||||
|
||||
// Check if we have an unknown field
|
||||
foreach (const QString &property, value.keys()) {
|
||||
if (!possibleFields.contains(property)) {
|
||||
unknownFields << property;
|
||||
}
|
||||
}
|
||||
|
||||
// Check if a mandatory field is missing
|
||||
foreach (const QString &field, mandatoryFields) {
|
||||
if (!value.contains(field)) {
|
||||
missingFields << field;
|
||||
}
|
||||
}
|
||||
|
||||
return QPair<QStringList, QStringList>(missingFields, unknownFields);
|
||||
}
|
||||
|
||||
/*!
|
||||
Returns a map containing the plugin configuration.
|
||||
|
||||
@ -393,7 +423,7 @@ QVariant DevicePlugin::configValue(const ParamTypeId ¶mTypeId) const
|
||||
DeviceManager::DeviceError DevicePlugin::setConfiguration(const ParamList &configuration)
|
||||
{
|
||||
foreach (const Param ¶m, configuration) {
|
||||
qCDebug(dcDeviceManager) << "* Set plugin configuration" << param;
|
||||
qCDebug(dcDeviceManager()) << "* Set plugin configuration" << param;
|
||||
DeviceManager::DeviceError result = setConfigValue(param.paramTypeId(), param.value());
|
||||
if (result != DeviceManager::DeviceErrorNoError)
|
||||
return result;
|
||||
@ -418,7 +448,7 @@ DeviceManager::DeviceError DevicePlugin::setConfigValue(const ParamTypeId ¶m
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
qCWarning(dcDeviceManager) << QString("Could not find plugin parameter with the id %1.").arg(paramTypeId.toString());
|
||||
qCWarning(dcDeviceManager()) << QString("Could not find plugin parameter with the id %1.").arg(paramTypeId.toString());
|
||||
return DeviceManager::DeviceErrorInvalidParameter;
|
||||
}
|
||||
|
||||
@ -507,18 +537,45 @@ void DevicePlugin::loadMetaData()
|
||||
|
||||
}
|
||||
|
||||
QStringList missingFields = verifyFields(QStringList() << "id" << "name" << "displayName" << "vendors", m_metaData);
|
||||
if (!missingFields.isEmpty()) {
|
||||
qCWarning(dcDeviceManager) << "Skipping plugin because of missing" << missingFields.join(", ") << m_metaData;
|
||||
// Note: The DevicePlugin has no type class, so we define the json properties here
|
||||
QStringList pluginMandatoryJsonProperties = QStringList() << "id" << "name" << "displayName" << "vendors";
|
||||
QStringList pluginJsonProperties = QStringList() << "id" << "name" << "displayName" << "vendors" << "paramtypes";
|
||||
|
||||
QPair<QStringList, QStringList> verificationResult = verifyFields(pluginJsonProperties, pluginMandatoryJsonProperties, m_metaData);
|
||||
|
||||
// Check mandatory fields
|
||||
if (!verificationResult.first.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << pluginName() << "Skipping plugin because of missing fields:" << verificationResult.first.join(", ") << endl << m_metaData;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if there are any unknown fields
|
||||
if (!verificationResult.second.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << pluginName() << "Skipping plugin because of unknown fields:" << verificationResult.second.join(", ") << endl << m_metaData;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
foreach (const QJsonValue &vendorJson, m_metaData.value("vendors").toArray()) {
|
||||
bool broken = false;
|
||||
QJsonObject vendorObject = vendorJson.toObject();
|
||||
QStringList missingFields = verifyFields(QStringList() << "id" << "name" << "displayName", vendorObject);
|
||||
if (!missingFields.isEmpty()) {
|
||||
qCWarning(dcDeviceManager) << "Skipping vendor because of missing" << missingFields.join(", ") << vendorObject;
|
||||
|
||||
// Note: The Vendor has no type class, so we define the json properties here
|
||||
QStringList vendorMandatoryJsonProperties = QStringList() << "id" << "name" << "displayName";
|
||||
QStringList vendorJsonProperties = QStringList() << "id" << "name" << "displayName";
|
||||
|
||||
QPair<QStringList, QStringList> verificationResult = verifyFields(vendorJsonProperties, vendorMandatoryJsonProperties, vendorObject);
|
||||
|
||||
// Check mandatory fields
|
||||
if (!verificationResult.first.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << pluginName() << "Skipping vendor because of missing fields:" << verificationResult.first.join(", ") << endl << vendorObject;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if there are any unknown fields
|
||||
if (!verificationResult.second.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << pluginName() << "Skipping vendor because of unknown fields:" << verificationResult.second.join(", ") << endl << vendorObject;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
@ -526,9 +583,18 @@ void DevicePlugin::loadMetaData()
|
||||
VendorId vendorId = vendorObject.value("id").toString();
|
||||
foreach (const QJsonValue &deviceClassJson, vendorJson.toObject().value("deviceClasses").toArray()) {
|
||||
QJsonObject deviceClassObject = deviceClassJson.toObject();
|
||||
QStringList missingFields = verifyFields(QStringList() << "id" << "name" << "displayName" << "createMethods" << "paramTypes", deviceClassObject);
|
||||
if (!missingFields.isEmpty()) {
|
||||
qCWarning(dcDeviceManager) << "Skipping DeviceClass because of missing" << missingFields.join(", ") << deviceClassObject;
|
||||
QPair<QStringList, QStringList> verificationResult = verifyFields(DeviceClass::jsonProperties(), DeviceClass::mandatoryJsonProperties(), deviceClassObject);
|
||||
|
||||
// Check mandatory fields
|
||||
if (!verificationResult.first.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << pluginName() << "Skipping device class because of missing fields:" << verificationResult.first.join(", ") << endl << deviceClassObject;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if there are any unknown fields
|
||||
if (!verificationResult.second.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << pluginName() << "Skipping device class because of unknown fields:" << verificationResult.second.join(", ") << endl << deviceClassObject;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
@ -536,55 +602,80 @@ void DevicePlugin::loadMetaData()
|
||||
DeviceClass deviceClass(pluginId(), vendorId, deviceClassObject.value("id").toString());
|
||||
deviceClass.setName(deviceClassObject.value("name").toString());
|
||||
deviceClass.setDisplayName(translateValue(m_metaData.value("name").toString(), deviceClassObject.value("displayName").toString()));
|
||||
|
||||
// Read create methods
|
||||
DeviceClass::CreateMethods createMethods;
|
||||
foreach (const QJsonValue &createMethodValue, deviceClassObject.value("createMethods").toArray()) {
|
||||
if (createMethodValue.toString() == "discovery") {
|
||||
createMethods |= DeviceClass::CreateMethodDiscovery;
|
||||
} else if (createMethodValue.toString() == "auto") {
|
||||
createMethods |= DeviceClass::CreateMethodAuto;
|
||||
} else if (createMethodValue.toString() == "user") {
|
||||
createMethods |= DeviceClass::CreateMethodUser;
|
||||
} else {
|
||||
qCWarning(dcDeviceManager) << "Unknown createMehtod" << createMethodValue.toString() <<
|
||||
"in deviceClass " << deviceClass.name() << ". Falling back to CreateMethodUser.";
|
||||
createMethods |= DeviceClass::CreateMethodUser;
|
||||
if (!deviceClassObject.contains("createMethods")) {
|
||||
// Default if not specified
|
||||
createMethods |= DeviceClass::CreateMethodUser;
|
||||
} else {
|
||||
foreach (const QJsonValue &createMethodValue, deviceClassObject.value("createMethods").toArray()) {
|
||||
if (createMethodValue.toString() == "Discovery" || createMethodValue.toString() == "discovery") {
|
||||
createMethods |= DeviceClass::CreateMethodDiscovery;
|
||||
} else if (createMethodValue.toString() == "Auto" || createMethodValue.toString() == "auto") {
|
||||
createMethods |= DeviceClass::CreateMethodAuto;
|
||||
} else if (createMethodValue.toString() == "User" || createMethodValue.toString() == "user") {
|
||||
createMethods |= DeviceClass::CreateMethodUser;
|
||||
} else {
|
||||
qCWarning(dcDeviceManager()) << "Unknown createMehtod" << createMethodValue.toString() << "in deviceClass "
|
||||
<< deviceClass.name() << ". Falling back to CreateMethodUser.";
|
||||
createMethods |= DeviceClass::CreateMethodUser;
|
||||
}
|
||||
}
|
||||
}
|
||||
deviceClass.setCreateMethods(createMethods);
|
||||
|
||||
// Read device icon
|
||||
QPair<bool, DeviceClass::DeviceIcon> deviceIconVerification = loadAndVerifyDeviceIcon(deviceClassObject.value("deviceIcon").toString());
|
||||
if (!deviceIconVerification.first) {
|
||||
broken = true;
|
||||
break;
|
||||
} else {
|
||||
deviceClass.setDeviceIcon(deviceIconVerification.second);
|
||||
}
|
||||
|
||||
QPair<bool, QList<ParamType> > discoveryParamVerification = parseParamTypes(deviceClassObject.value("discoveryParamTypes").toArray());
|
||||
if (!discoveryParamVerification.first) {
|
||||
broken = true;
|
||||
} else {
|
||||
deviceClass.setDiscoveryParamTypes(discoveryParamVerification.second);
|
||||
}
|
||||
|
||||
QString setupMethod = deviceClassObject.value("setupMethod").toString();
|
||||
if (setupMethod == "pushButton") {
|
||||
deviceClass.setSetupMethod(DeviceClass::SetupMethodPushButton);
|
||||
} else if (setupMethod == "displayPin") {
|
||||
deviceClass.setSetupMethod(DeviceClass::SetupMethodDisplayPin);
|
||||
} else if (setupMethod == "enterPin") {
|
||||
deviceClass.setSetupMethod(DeviceClass::SetupMethodEnterPin);
|
||||
} else if (setupMethod == "justAdd") {
|
||||
qCWarning(dcDeviceManager) << "Unknown setupMehtod" << setupMethod <<
|
||||
"in deviceClass " << deviceClass.name() << ". Falling back to SetupMethodJustAdd.";
|
||||
deviceClass.setSetupMethod(DeviceClass::SetupMethodJustAdd);
|
||||
}
|
||||
deviceClass.setPairingInfo(translateValue(m_metaData.value("name").toString(), deviceClassObject.value("pairingInfo").toString()));
|
||||
// Read params
|
||||
QPair<bool, QList<ParamType> > paramTypesVerification = parseParamTypes(deviceClassObject.value("paramTypes").toArray());
|
||||
if (!paramTypesVerification.first) {
|
||||
broken = true;
|
||||
break;
|
||||
} else {
|
||||
deviceClass.setParamTypes(paramTypesVerification.second);
|
||||
}
|
||||
|
||||
// Read discover params
|
||||
QPair<bool, QList<ParamType> > discoveryParamVerification = parseParamTypes(deviceClassObject.value("discoveryParamTypes").toArray());
|
||||
if (!discoveryParamVerification.first) {
|
||||
broken = true;
|
||||
break;
|
||||
} else {
|
||||
deviceClass.setDiscoveryParamTypes(discoveryParamVerification.second);
|
||||
}
|
||||
|
||||
// Read setup method
|
||||
DeviceClass::SetupMethod setupMethod = DeviceClass::SetupMethodJustAdd;
|
||||
if (deviceClassObject.contains("setupMethod")) {
|
||||
QString setupMethodString = deviceClassObject.value("setupMethod").toString();
|
||||
if (setupMethodString == "PushButton" || setupMethodString == "pushButton") {
|
||||
setupMethod = DeviceClass::SetupMethodPushButton;
|
||||
} else if (setupMethodString == "DisplayPin" || setupMethodString == "displayPin") {
|
||||
setupMethod = DeviceClass::SetupMethodDisplayPin;
|
||||
} else if (setupMethodString == "EnterPin" || setupMethodString == "enterPin") {
|
||||
setupMethod = DeviceClass::SetupMethodEnterPin;
|
||||
} else if (setupMethodString == "JustAdd" || setupMethodString == "justAdd") {
|
||||
setupMethod = DeviceClass::SetupMethodJustAdd;
|
||||
} else {
|
||||
qCWarning(dcDeviceManager()) << "Unknown setupMehtod" << setupMethod << "in deviceClass"
|
||||
<< deviceClass.name() << ". Falling back to SetupMethodJustAdd.";
|
||||
setupMethod = DeviceClass::SetupMethodJustAdd;
|
||||
}
|
||||
}
|
||||
deviceClass.setSetupMethod(setupMethod);
|
||||
|
||||
// Read pairing info
|
||||
deviceClass.setPairingInfo(translateValue(m_metaData.value("name").toString(), deviceClassObject.value("pairingInfo").toString()));
|
||||
|
||||
// Read basic tags
|
||||
QList<DeviceClass::BasicTag> basicTags;
|
||||
foreach (const QJsonValue &basicTagJson, deviceClassObject.value("basicTags").toArray()) {
|
||||
QPair<bool, DeviceClass::BasicTag> basicTagVerification = loadAndVerifyBasicTag(basicTagJson.toString());
|
||||
@ -601,30 +692,44 @@ void DevicePlugin::loadMetaData()
|
||||
QList<StateType> stateTypes;
|
||||
QList<EventType> eventTypes;
|
||||
|
||||
// StateTypes
|
||||
// Read StateTypes
|
||||
int index = 0;
|
||||
foreach (const QJsonValue &stateTypesJson, deviceClassObject.value("stateTypes").toArray()) {
|
||||
QJsonObject st = stateTypesJson.toObject();
|
||||
bool writableState = false;
|
||||
QStringList requiredFields;
|
||||
requiredFields << "type" << "id" << "name" << "displayName" << "defaultValue" << "displayNameEvent";
|
||||
if (st.contains("writable") && st.value("writable").toBool()) {
|
||||
writableState = true;
|
||||
requiredFields << "displayNameAction";
|
||||
}
|
||||
QStringList missingFields = verifyFields(requiredFields, st);
|
||||
if (!missingFields.isEmpty()) {
|
||||
qCWarning(dcDeviceManager) << "Skipping device class" << deviceClass.name() << "because of missing" << missingFields.join(", ") << "in stateType" << st;
|
||||
|
||||
QPair<QStringList, QStringList> verificationResult = verifyFields(StateType::jsonProperties(), StateType::mandatoryJsonProperties(), st);
|
||||
|
||||
// Check mandatory fields
|
||||
if (!verificationResult.first.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << "Skipping device class" << deviceClass.name() << "because of missing" << verificationResult.first.join(", ") << "in stateType" << st;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if there are any unknown fields
|
||||
if (!verificationResult.second.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << "Skipping device class" << deviceClass.name() << "because of unknown properties" << verificationResult.second.join(", ") << "in stateType" << st;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
|
||||
if (st.contains("writable") && st.value("writable").toBool()) {
|
||||
writableState = true;
|
||||
if (!st.contains("displayNameAction")) {
|
||||
qCWarning(dcDeviceManager()) << "Skipping device class" << deviceClass.name() << ". The state is writable, but does not define the displayNameAction property" << st;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
QVariant::Type t = QVariant::nameToType(st.value("type").toString().toLatin1().data());
|
||||
if (t == QVariant::Invalid) {
|
||||
qCWarning(dcDeviceManager()) << "Invalid StateType type:" << st.value("type").toString();
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
|
||||
StateType stateType(st.value("id").toString());
|
||||
stateType.setName(st.value("name").toString());
|
||||
stateType.setDisplayName(translateValue(m_metaData.value("name").toString(), st.value("displayName").toString()));
|
||||
@ -637,6 +742,7 @@ void DevicePlugin::loadMetaData()
|
||||
} else {
|
||||
stateType.setUnit(unitVerification.second);
|
||||
}
|
||||
|
||||
stateType.setDefaultValue(st.value("defaultValue").toVariant());
|
||||
if (st.contains("minValue"))
|
||||
stateType.setMinValue(st.value("minValue").toVariant());
|
||||
@ -704,9 +810,19 @@ void DevicePlugin::loadMetaData()
|
||||
index = 0;
|
||||
foreach (const QJsonValue &actionTypesJson, deviceClassObject.value("actionTypes").toArray()) {
|
||||
QJsonObject at = actionTypesJson.toObject();
|
||||
QStringList missingFields = verifyFields(QStringList() << "id" << "name" << "displayName", at);
|
||||
if (!missingFields.isEmpty()) {
|
||||
qCWarning(dcDeviceManager) << "Skipping device class" << deviceClass.name() << "because of missing" << missingFields.join(", ") << "in actionTypes" << at;
|
||||
|
||||
QPair<QStringList, QStringList> verificationResult = verifyFields(ActionType::jsonProperties(), ActionType::mandatoryJsonProperties(), at);
|
||||
|
||||
// Check mandatory fields
|
||||
if (!verificationResult.first.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << pluginName() << "Skipping device class" << deviceClass.name() << "because of missing" << verificationResult.first.join(", ") << "in action type:" << endl << at;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if there are any unknown fields
|
||||
if (!verificationResult.second.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << pluginName() << "Skipping device class" << deviceClass.name() << "because of unknown fields:" << verificationResult.second.join(", ") << "in action type:" << endl << at;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
@ -715,6 +831,7 @@ void DevicePlugin::loadMetaData()
|
||||
actionType.setName(at.value("name").toString());
|
||||
actionType.setDisplayName(translateValue(m_metaData.value("name").toString(), at.value("displayName").toString()));
|
||||
actionType.setIndex(index++);
|
||||
|
||||
QPair<bool, QList<ParamType> > paramVerification = parseParamTypes(at.value("paramTypes").toArray());
|
||||
if (!paramVerification.first) {
|
||||
broken = true;
|
||||
@ -731,13 +848,24 @@ void DevicePlugin::loadMetaData()
|
||||
index = 0;
|
||||
foreach (const QJsonValue &eventTypesJson, deviceClassObject.value("eventTypes").toArray()) {
|
||||
QJsonObject et = eventTypesJson.toObject();
|
||||
QStringList missingFields = verifyFields(QStringList() << "id" << "name" << "displayName", et);
|
||||
if (!missingFields.isEmpty()) {
|
||||
qCWarning(dcDeviceManager) << "Skipping device class" << deviceClass.name() << "because of missing" << missingFields.join(", ") << "in eventTypes:" << et;
|
||||
|
||||
QPair<QStringList, QStringList> verificationResult = verifyFields(EventType::jsonProperties(), EventType::mandatoryJsonProperties(), et);
|
||||
|
||||
// Check mandatory fields
|
||||
if (!verificationResult.first.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << pluginName() << "Skipping device class" << deviceClass.name() << "because of missing" << verificationResult.first.join(", ") << "in event type:" << endl << et;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
|
||||
// Check if there are any unknown fields
|
||||
if (!verificationResult.second.isEmpty()) {
|
||||
qCWarning(dcDeviceManager()) << pluginName() << "Skipping device class" << deviceClass.name() << "because of unknown fields:" << verificationResult.second.join(", ") << "in event type:" << endl << et;
|
||||
broken = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
EventType eventType(et.value("id").toString());
|
||||
eventType.setName(et.value("name").toString());
|
||||
eventType.setDisplayName(translateValue(m_metaData.value("name").toString(), et.value("displayName").toString()));
|
||||
@ -764,11 +892,11 @@ void DevicePlugin::loadMetaData()
|
||||
if (deviceClassObject.contains("criticalStateTypeId")) {
|
||||
StateTypeId criticalStateTypeId = StateTypeId(deviceClassObject.value("criticalStateTypeId").toString());
|
||||
if (!deviceClass.hasStateType(criticalStateTypeId)) {
|
||||
qCWarning(dcDeviceManager) << "Skipping device class" << deviceClass.name() << ": the definend critical stateTypeId" << criticalStateTypeId.toString() << "does not match any StateType of this DeviceClass.";
|
||||
qCWarning(dcDeviceManager()) << "Skipping device class" << deviceClass.name() << ": the definend critical stateTypeId" << criticalStateTypeId.toString() << "does not match any StateType of this DeviceClass.";
|
||||
broken = true;
|
||||
} else if (deviceClass.getStateType(criticalStateTypeId).type() != QVariant::Bool) {
|
||||
// Make sure the critical stateType is a bool state
|
||||
qCWarning(dcDeviceManager) << "Skipping device class" << deviceClass.name() << ": the definend critical stateTypeId" << criticalStateTypeId.toString() << "is not a bool StateType.";
|
||||
qCWarning(dcDeviceManager()) << "Skipping device class" << deviceClass.name() << ": the definend critical stateTypeId" << criticalStateTypeId.toString() << "is not a bool StateType.";
|
||||
broken = true;
|
||||
} else {
|
||||
deviceClass.setCriticalStateTypeId(criticalStateTypeId);
|
||||
@ -778,7 +906,7 @@ void DevicePlugin::loadMetaData()
|
||||
if (deviceClassObject.contains("primaryStateTypeId")) {
|
||||
StateTypeId primaryStateTypeId = StateTypeId(deviceClassObject.value("primaryStateTypeId").toString());
|
||||
if (!deviceClass.hasStateType(primaryStateTypeId)) {
|
||||
qCWarning(dcDeviceManager) << "Skipping device class" << deviceClass.name() << ": the definend primary stateTypeId" << primaryStateTypeId.toString() << "does not match any StateType of this DeviceClass.";
|
||||
qCWarning(dcDeviceManager()) << "Skipping device class" << deviceClass.name() << ": the definend primary stateTypeId" << primaryStateTypeId.toString() << "does not match any StateType of this DeviceClass.";
|
||||
broken = true;
|
||||
} else {
|
||||
deviceClass.setPrimaryStateTypeId(primaryStateTypeId);
|
||||
@ -788,13 +916,14 @@ void DevicePlugin::loadMetaData()
|
||||
if (deviceClassObject.contains("primaryActionTypeId")) {
|
||||
ActionTypeId primaryActionTypeId = ActionTypeId(deviceClassObject.value("primaryActionTypeId").toString());
|
||||
if (!deviceClass.hasActionType(primaryActionTypeId)) {
|
||||
qCWarning(dcDeviceManager) << "Skipping device class" << deviceClass.name() << ": the definend primary actionTypeId" << primaryActionTypeId.toString() << "does not match any ActionType of this DeviceClass.";
|
||||
qCWarning(dcDeviceManager()) << "Skipping device class" << deviceClass.name() << ": the definend primary actionTypeId" << primaryActionTypeId.toString() << "does not match any ActionType of this DeviceClass.";
|
||||
broken = true;
|
||||
} else {
|
||||
deviceClass.setPrimaryActionTypeId(primaryActionTypeId);
|
||||
}
|
||||
}
|
||||
|
||||
// Read interfaces
|
||||
QStringList interfaces;
|
||||
foreach (const QJsonValue &value, deviceClassObject.value("interfaces").toArray()) {
|
||||
Interface iface = loadInterface(value.toString());
|
||||
@ -802,28 +931,29 @@ void DevicePlugin::loadMetaData()
|
||||
StateTypes stateTypes(deviceClass.stateTypes());
|
||||
ActionTypes actionTypes(deviceClass.actionTypes());
|
||||
EventTypes eventTypes(deviceClass.eventTypes());
|
||||
|
||||
bool valid = true;
|
||||
foreach (const StateType &ifaceStateType, iface.stateTypes()) {
|
||||
StateType stateType = stateTypes.findByName(ifaceStateType.name());
|
||||
if (stateType.id().isNull()) {
|
||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but doesn't implement state" << ifaceStateType.name();
|
||||
qCWarning(dcDeviceManager()) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but doesn't implement state" << ifaceStateType.name();
|
||||
valid = false;
|
||||
continue;
|
||||
}
|
||||
if (ifaceStateType.type() != stateType.type()) {
|
||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has not matching type" << stateType.type() << "!=" << ifaceStateType.type();
|
||||
qCWarning(dcDeviceManager()) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has not matching type" << stateType.type() << "!=" << ifaceStateType.type();
|
||||
valid = false;
|
||||
continue;
|
||||
}
|
||||
if (ifaceStateType.minValue().isValid() && !ifaceStateType.minValue().isNull()) {
|
||||
if (ifaceStateType.minValue().toString() == "any") {
|
||||
if (stateType.minValue().isNull()) {
|
||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has no minimum value defined.";
|
||||
qCWarning(dcDeviceManager()) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has no minimum value defined.";
|
||||
valid = false;
|
||||
continue;
|
||||
}
|
||||
} else if (ifaceStateType.minValue() != stateType.minValue()) {
|
||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has not matching minimum value:" << ifaceStateType.minValue() << "!=" << stateType.minValue();
|
||||
qCWarning(dcDeviceManager()) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has not matching minimum value:" << ifaceStateType.minValue() << "!=" << stateType.minValue();
|
||||
valid = false;
|
||||
continue;
|
||||
}
|
||||
@ -831,22 +961,23 @@ void DevicePlugin::loadMetaData()
|
||||
if (ifaceStateType.maxValue().isValid() && !ifaceStateType.maxValue().isNull()) {
|
||||
if (ifaceStateType.maxValue().toString() == "any") {
|
||||
if (stateType.maxValue().isNull()) {
|
||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has no maximum value defined.";
|
||||
qCWarning(dcDeviceManager()) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has no maximum value defined.";
|
||||
valid = false;
|
||||
continue;
|
||||
}
|
||||
} else if (ifaceStateType.maxValue() != stateType.maxValue()) {
|
||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has not matching maximum value:" << ifaceStateType.maxValue() << "!=" << stateType.minValue();
|
||||
qCWarning(dcDeviceManager()) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has not matching maximum value:" << ifaceStateType.maxValue() << "!=" << stateType.minValue();
|
||||
valid = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!ifaceStateType.possibleValues().isEmpty() && ifaceStateType.possibleValues() != stateType.possibleValues()) {
|
||||
qCWarning(dcDeviceManager) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has not matching allowed values" << ifaceStateType.possibleValues() << "!=" << stateType.possibleValues();
|
||||
qCWarning(dcDeviceManager()) << "DeviceClass" << deviceClass.name() << "claims to implement interface" << value.toString() << "but state" << stateType.name() << "has not matching allowed values" << ifaceStateType.possibleValues() << "!=" << stateType.possibleValues();
|
||||
valid = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
foreach (const ActionType &ifaceActionType, iface.actionTypes()) {
|
||||
ActionType actionType = actionTypes.findByName(ifaceActionType.name());
|
||||
if (actionType.id().isNull()) {
|
||||
@ -866,6 +997,7 @@ void DevicePlugin::loadMetaData()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
foreach (const EventType &ifaceEventType, iface.eventTypes()) {
|
||||
EventType eventType = eventTypes.findByName(ifaceEventType.name());
|
||||
if (!eventType.isValid()) {
|
||||
@ -902,17 +1034,6 @@ void DevicePlugin::loadMetaData()
|
||||
}
|
||||
}
|
||||
|
||||
QStringList DevicePlugin::verifyFields(const QStringList &fields, const QJsonObject &value) const
|
||||
{
|
||||
QStringList ret;
|
||||
foreach (const QString &field, fields) {
|
||||
if (!value.contains(field)) {
|
||||
ret << field;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
QString DevicePlugin::translateValue(const QString &context, const QString &string) const
|
||||
{
|
||||
QString translation = m_translator->translate(context.toUtf8().constData(), string.toUtf8().constData());
|
||||
|
||||
@ -108,7 +108,8 @@ private:
|
||||
|
||||
QPair<bool, QList<ParamType> > parseParamTypes(const QJsonArray &array) const;
|
||||
|
||||
QStringList verifyFields(const QStringList &fields, const QJsonObject &value) const;
|
||||
// Returns <missingFields, unknownFields>
|
||||
QPair<QStringList, QStringList> verifyFields(const QStringList &possibleFields, const QStringList &mandatoryFields, const QJsonObject &value) const;
|
||||
|
||||
QString translateValue(const QString &context, const QString &string) const;
|
||||
|
||||
|
||||
@ -104,6 +104,18 @@ void ActionType::setParamTypes(const ParamTypes ¶mTypes)
|
||||
m_paramTypes = paramTypes;
|
||||
}
|
||||
|
||||
/*! Returns a list of all valid JSON properties a ActionType JSON definition can have. */
|
||||
QStringList ActionType::jsonProperties()
|
||||
{
|
||||
return QStringList() << "id" << "name" << "displayName" << "paramTypes";
|
||||
}
|
||||
|
||||
/*! Returns a list of mandatory JSON properties a ActionType JSON definition must have. */
|
||||
QStringList ActionType::mandatoryJsonProperties()
|
||||
{
|
||||
return QStringList() << "id" << "name" << "displayName";
|
||||
}
|
||||
|
||||
ActionTypes::ActionTypes(const QList<ActionType> &other)
|
||||
{
|
||||
foreach (const ActionType &at, other) {
|
||||
|
||||
@ -49,6 +49,9 @@ public:
|
||||
ParamTypes paramTypes() const;
|
||||
void setParamTypes(const ParamTypes ¶mTypes);
|
||||
|
||||
static QStringList jsonProperties();
|
||||
static QStringList mandatoryJsonProperties();
|
||||
|
||||
private:
|
||||
ActionTypeId m_id;
|
||||
QString m_name;
|
||||
|
||||
@ -470,3 +470,18 @@ bool DeviceClass::operator==(const DeviceClass &deviceClass) const
|
||||
{
|
||||
return m_id == deviceClass.id();
|
||||
}
|
||||
|
||||
/*! Returns a list of all valid JSON properties a DeviceClass JSON definition can have. */
|
||||
QStringList DeviceClass::jsonProperties()
|
||||
{
|
||||
return QStringList() << "id" << "name" << "displayName" << "createMethods" << "setupMethod" << "deviceIcon"
|
||||
<< "interfaces" << "basicTags" << "pairingInfo" << "criticalStateTypeId"
|
||||
<< "primaryStateTypeId" << "primaryActionTypeId" << "discoveryParamTypes"
|
||||
<< "discoveryParamTypes" << "paramTypes" << "stateTypes" << "actionTypes" << "eventTypes";
|
||||
}
|
||||
|
||||
/*! Returns a list of mandatory JSON properties a DeviceClass JSON definition must have. */
|
||||
QStringList DeviceClass::mandatoryJsonProperties()
|
||||
{
|
||||
return QStringList() << "id" << "name" << "displayName";
|
||||
}
|
||||
|
||||
@ -180,6 +180,9 @@ public:
|
||||
|
||||
bool operator==(const DeviceClass &device) const;
|
||||
|
||||
static QStringList jsonProperties();
|
||||
static QStringList mandatoryJsonProperties();
|
||||
|
||||
private:
|
||||
DeviceClassId m_id;
|
||||
VendorId m_vendorId;
|
||||
|
||||
@ -130,6 +130,18 @@ bool EventType::isValid() const
|
||||
return !m_id.isNull() && !m_name.isEmpty();
|
||||
}
|
||||
|
||||
/*! Returns a list of all valid JSON properties a EventType JSON definition can have. */
|
||||
QStringList EventType::jsonProperties()
|
||||
{
|
||||
return QStringList() << "id" << "name" << "displayName" << "paramTypes" << "ruleRelevant" << "graphRelevant";
|
||||
}
|
||||
|
||||
/*! Returns a list of mandatory JSON properties a EventType JSON definition must have. */
|
||||
QStringList EventType::mandatoryJsonProperties()
|
||||
{
|
||||
return QStringList() << "id" << "name" << "displayName";
|
||||
}
|
||||
|
||||
EventTypes::EventTypes(const QList<EventType> &other)
|
||||
{
|
||||
foreach (const EventType &at, other) {
|
||||
|
||||
@ -56,6 +56,10 @@ public:
|
||||
void setGraphRelevant(const bool &graphRelevant);
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
static QStringList jsonProperties();
|
||||
static QStringList mandatoryJsonProperties();
|
||||
|
||||
private:
|
||||
EventTypeId m_id;
|
||||
QString m_name;
|
||||
|
||||
@ -211,7 +211,20 @@ bool ParamType::isValid() const
|
||||
return !m_id.isNull() && !m_name.isEmpty() && m_type != QVariant::Invalid;
|
||||
}
|
||||
|
||||
/*! Writes the name, type defaultValue, min value, max value and readOnly of the given \a paramType to \a dbg. */
|
||||
/*! Returns a list of all valid JSON properties a ParamType JSON definition can have. */
|
||||
QStringList ParamType::jsonProperties()
|
||||
{
|
||||
return QStringList() << "id" << "name" << "displayName" << "type" << "defaultValue" << "inputType"
|
||||
<< "unit" << "minValue" << "maxValue" << "allowedValues" << "readOnly";
|
||||
}
|
||||
|
||||
/*! Returns a list of mandatory JSON properties a ParamType JSON definition must have. */
|
||||
QStringList ParamType::mandatoryJsonProperties()
|
||||
{
|
||||
return QStringList() << "id" << "name" << "displayName" << "type" << "defaultValue";
|
||||
}
|
||||
|
||||
/*! Writes the name, type, defaultValue, min value, max value and readOnly of the given \a paramType to \a dbg. */
|
||||
QDebug operator<<(QDebug dbg, const ParamType ¶mType)
|
||||
{
|
||||
dbg.nospace() << "ParamType(Id" << paramType.id()
|
||||
|
||||
@ -76,6 +76,9 @@ public:
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
static QStringList jsonProperties();
|
||||
static QStringList mandatoryJsonProperties();
|
||||
|
||||
private:
|
||||
ParamTypeId m_id;
|
||||
QString m_name;
|
||||
|
||||
@ -196,6 +196,20 @@ void StateType::setCached(bool cached)
|
||||
m_cached = cached;
|
||||
}
|
||||
|
||||
/*! Returns a list of all valid JSON properties a DeviceClass JSON definition can have. */
|
||||
QStringList StateType::jsonProperties()
|
||||
{
|
||||
return QStringList() << "id" << "name" << "displayName" << "displayNameEvent" << "type" << "defaultValue"
|
||||
<< "cached" << "ruleRelevant" << "eventRuleRelevant" << "graphRelevant" << "unit"
|
||||
<< "minValue" << "maxValue" << "possibleValues" << "writable" << "displayNameAction";
|
||||
}
|
||||
|
||||
/*! Returns a list of mandatory JSON properties a DeviceClass JSON definition must have. */
|
||||
QStringList StateType::mandatoryJsonProperties()
|
||||
{
|
||||
return QStringList() << "id" << "name" << "displayName" << "displayNameEvent" << "type" << "defaultValue";
|
||||
}
|
||||
|
||||
StateTypes::StateTypes(const QList<StateType> &other)
|
||||
{
|
||||
foreach (const StateType &st, other) {
|
||||
|
||||
@ -73,6 +73,9 @@ public:
|
||||
bool cached() const;
|
||||
void setCached(bool cached);
|
||||
|
||||
static QStringList jsonProperties();
|
||||
static QStringList mandatoryJsonProperties();
|
||||
|
||||
private:
|
||||
StateTypeId m_id;
|
||||
QString m_name;
|
||||
|
||||
@ -4,7 +4,7 @@
|
||||
|
||||
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
|
||||
# #
|
||||
# Copyright (C) 2015-2017 Simon Stuerz <simon.stuerz@guh.io> #
|
||||
# Copyright (C) 2015-2018 Simon Stuerz <simon.stuerz@guh.io> #
|
||||
# Copyright (C) 2014 Michael Zanetti <michael_zanetti@gmx.net> #
|
||||
# #
|
||||
# This file is part of nymea. #
|
||||
@ -29,7 +29,7 @@ import json
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
__version__='1.0.1'
|
||||
__version__='1.0.2'
|
||||
|
||||
##################################################################################################################
|
||||
# Methods
|
||||
@ -63,11 +63,12 @@ def extractPlugin(pluginMap):
|
||||
printInfo('Define PluginId pluginId = %s' % (pluginMap['id']))
|
||||
if args.filetype is 'i':
|
||||
writeToFile('PluginId pluginId = PluginId(\"%s\");' % (pluginMap['id']))
|
||||
addTranslationString(pluginMap['name'], 'The name of the plugin %s (%s)' % (pluginMap['name'], pluginMap['id']))
|
||||
addTranslationString(pluginMap['displayName'], 'The name of the plugin %s (%s)' % (pluginMap['name'], pluginMap['id']))
|
||||
createExternDefinition('PluginId', variableName)
|
||||
|
||||
# Extract plugin params (configurations)
|
||||
if 'paramTypes' in pluginMap:
|
||||
extractParamTypes(pluginMap['paramTypes'], pluginMap['name'])
|
||||
extractParamTypes(pluginMap['paramTypes'], pluginMap['name'][0].lower() + pluginMap['name'][1:])
|
||||
|
||||
if 'vendors' in pluginMap:
|
||||
extractVendors(pluginMap['vendors'])
|
||||
@ -178,20 +179,21 @@ def extractStateTypes(stateTypes, deviceClassName):
|
||||
else:
|
||||
printWarning('Duplicated variable name \"%s\" for autocreated EventTypeId %s -> skipping' % (variableName, stateType['id']))
|
||||
|
||||
#ParamType for EventType/ActionType
|
||||
variableName = '%s%sStateParamTypeId' % (deviceClassName, stateType['name'][0].capitalize() + stateType['name'][1:])
|
||||
# ParamType for the autocreated EventType
|
||||
variableName = '%s%sEventParamTypeId' % (deviceClassName, stateType['name'][0].capitalize() + stateType['name'][1:])
|
||||
if not variableName in variableNames:
|
||||
variableNames.append(variableName)
|
||||
printInfo('Define ParamTypeId %s for StateType %s = %s' % (variableName, variableName, stateType['id']))
|
||||
addTranslationString(stateType['displayName'], 'The name of the ParamType of the autocreated EventType (%s) of DeviceClass %s' % (stateType['id'], deviceClassName))
|
||||
if args.filetype is 'i':
|
||||
writeToFile('ParamTypeId %s = ParamTypeId(\"%s\");' % (variableName, stateType['id']))
|
||||
createExternDefinition('ParamTypeId', variableName)
|
||||
addTranslationString(stateType['name'], 'The name of the ParamType of StateType (%s) of DeviceClass %s' % (stateType['id'], deviceClassName))
|
||||
else:
|
||||
printWarning('Duplicated variable name \"%s\" for ParamTypeId %s -> skipping' % (variableName, stateType['id']))
|
||||
|
||||
# Create ActionTypeId if the state is writable
|
||||
# Create ActionTypeId and ParamTypeId for action if the state is writable
|
||||
if 'writable' in stateType and stateType['writable']:
|
||||
# Create ActionType for the writable state
|
||||
variableName = '%s%sActionTypeId' % (deviceClassName, stateType['name'][0].capitalize() + stateType['name'][1:])
|
||||
if not variableName in variableNames:
|
||||
variableNames.append(variableName)
|
||||
@ -203,6 +205,18 @@ def extractStateTypes(stateTypes, deviceClassName):
|
||||
else:
|
||||
printWarning('Duplicated variable name \"%s\" for autocreated ActionTypeId %s -> skipping' % (variableName, stateType['id']))
|
||||
|
||||
# ParamType for the autocreated ActionType
|
||||
variableName = '%s%sActionParamTypeId' % (deviceClassName, stateType['name'][0].capitalize() + stateType['name'][1:])
|
||||
if not variableName in variableNames:
|
||||
variableNames.append(variableName)
|
||||
printInfo('Define ParamTypeId %s for autocreated ActionType %s = %s' % (variableName, variableName, stateType['id']))
|
||||
addTranslationString(stateType['displayName'], 'The name of the autocreated ParamType of the writable StateType (%s) of DeviceClass %s' % (stateType['$
|
||||
if args.filetype is 'i':
|
||||
writeToFile('ParamTypeId %s = ParamTypeId(\"%s\");' % (variableName, stateType['id']))
|
||||
createExternDefinition('ParamTypeId', variableName)
|
||||
else:
|
||||
printWarning('Duplicated variable name \"%s\" for ParamTypeId %s -> skipping' % (variableName, stateType['id']))
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
@ -288,7 +302,7 @@ def createTranslationFiles():
|
||||
path, fileName = os.path.split(translationFile)
|
||||
translationOutput = (path + '/' + pluginMap['id'] + '-' + os.path.splitext(fileName)[0] + '.qm')
|
||||
printInfo(' --> Translation update %s' % translationFile)
|
||||
printInfo(subprocess.check_output(['mkdir', '-p', path]))
|
||||
printInfo(subprocess.check_output(['mkdir', '-p', path]))
|
||||
printInfo(subprocess.check_output(['lupdate', '-recursive', '-no-obsolete', sourceDir, (args.builddir + '/' + args.output), '-ts', translationFile]))
|
||||
printInfo(' --> Translation release %s' % translationOutput)
|
||||
printInfo(subprocess.check_output(['lrelease', translationFile, '-qm', translationOutput]))
|
||||
@ -407,7 +421,7 @@ if __name__ == '__main__':
|
||||
except:
|
||||
printError('Could not open file \"%s\"' % (args.jsonfile))
|
||||
exit -1
|
||||
|
||||
|
||||
try:
|
||||
outputFile = open(args.builddir + '/' + args.output, 'w')
|
||||
except:
|
||||
|
||||
Reference in New Issue
Block a user