#!/usr/bin/env python # -*- coding: UTF-8 -*- # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # Copyright (C) 2015-2016 Simon Stuerz # # Copyright (C) 2014 Michael Zanetti # # # # This file is part of guh. # # # # guh is free software: you can redistribute it and/or modify # # it under the terms of the GNU General Public License as published by # # the Free Software Foundation, version 2 of the License. # # # # guh is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # # GNU General Public License for more details. # # # # You should have received a copy of the GNU General Public License # # along with guh. If not, see . # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # import argparse import traceback import json import os import subprocess __version__="1.0.0" # Argument parser parser = argparse.ArgumentParser(description='The guh-generateplugininfo is a precompiler for building plugins. This precompiler will create a plugininfo.h containing the uuid definitions from the plugin json file and creates the translations for the plugin.') parser.add_argument('-j', '--jsonfile', help='The JSON input file name with the plugin description', metavar='jsonfile') parser.add_argument('-b', '--builddir', help='The path to the build directory of the plugin where the plugininfo.h file can be found.', metavar='buildpath') parser.add_argument('-o', '--output', help='The plugininfo.h outputFile with the uuid declarations', metavar='output') parser.add_argument('-t', '--translations', help='The translation files for the plugin.', nargs='*', type=str, metavar='*.ts') parser.add_argument('-v', '--version', action='version', version=__version__) args = parser.parse_args() # Get the source directors sourceDir = os.path.dirname(os.path.abspath(args.jsonfile)) print "Json file: %s" % args.jsonfile print "Output: %s/%s" % (args.builddir, args.output) print "Build directory: %s" % args.builddir print "Source directory: %s" % sourceDir print "Translations: %s" % args.translations # Tuple ('string to translate', 'comment for translater') translationStrings = [] variableNames = [] externDefinitions = [] # Open files inputFile = open(args.jsonfile, "r") outputFile = open(args.builddir + "/" + args.output, "w") outputFileExtern = open(args.builddir + "/" + "extern-" + args.output, "w") # Read json file try: pluginMap = json.loads(inputFile.read()) inputFile.close() except ValueError as error: print " --> Error loading input file \"%s\"" % (args.input) print " %s" % (error) inputFile.close() exit -1 ################################################################################################################## # Methods def writePluginInfo(line): outputFile.write("%s\n" % line) def writeExternPluginInfo(line): outputFileExtern.write("%s\n" % line) def extractVendors(pluginMap): for vendor in pluginMap['vendors']: try: print("define VendorId %sVendorId = %s" % (pluginMap["idName"], vendor["id"])) writePluginInfo("VendorId %sVendorId = VendorId(\"%s\");" % (vendor["idName"], vendor["id"])) addTranslationString(vendor['name'], 'The name of the vendor (%s)' % vendor['id']) createExternDefinition("VendorId", "%sVendorId" % (vendor["idName"])) except: pass extractDeviceClasses(vendor) def extractDeviceClasses(vendorMap): for deviceClass in vendorMap["deviceClasses"]: try: variableName = "%sDeviceClassId" % (deviceClass['idName']) addTranslationString(deviceClass['name'], 'The name of the deviceClass') if 'pairingInfo' in deviceClass: addTranslationString(deviceClass['pairingInfo'], 'The pairing info of deviceClass %s' % deviceClass['name']) if not variableName in variableNames: variableNames.append(variableName) print('define DeviceClassId %s = %s' % (variableName, deviceClass['deviceClassId'])) writePluginInfo('DeviceClassId %s = DeviceClassId(\"%s\");' % (variableName, deviceClass['deviceClassId'])) createExternDefinition('DeviceClassId', variableName) else: print("duplicated variable name \"%s\" for DeviceClassId %s -> skipping") % (variableName, deviceClass['deviceClassId']) except: pass extractActionTypes(deviceClass) extractStateTypes(deviceClass) extractEventTypes(deviceClass) def extractStateTypes(deviceClassMap): try: for stateType in deviceClassMap['stateTypes']: try: variableName = "%sStateTypeId" % (stateType["idName"]) addTranslationString(stateType['name'], 'The name of the stateType (%s) of deviceClass %s' % (stateType["id"], deviceClassMap['name'])) if not variableName in variableNames: variableNames.append(variableName) print("define StateTypeId %s = %s" % (variableName, stateType["id"])) writePluginInfo("StateTypeId %s = StateTypeId(\"%s\");" % (variableName, stateType["id"])) createExternDefinition("StateTypeId", variableName) else: print("duplicated variable name \"%s\" for StateTypeId %s -> skipping") % (variableName, stateType["id"]) # create ActionTypeId if the state is writable if 'writable' in stateType: if stateType['writable']: vName = "%sActionTypeId" % (stateType["idName"]) if not vName in variableNames: variableNames.append(vName) print("define ActionTypeId %s for writable StateType %s = %s" % (vName, variableName, stateType["id"])) writePluginInfo("ActionTypeId %s = ActionTypeId(\"%s\");" % (vName, stateType["id"])) createExternDefinition("ActionTypeId", vName) else: print("duplicated variable name \"%s\" for ActionTypeId %s -> skipping") % (variableName, stateType["id"]) except: pass except: pass def extractActionTypes(deviceClassMap): try: for actionType in deviceClassMap["actionTypes"]: try: variableName = "%sActionTypeId" % (actionType["idName"]) addTranslationString(actionType["name"], 'The name of the ActionType %s of deviceClass %s' % (actionType["id"], deviceClassMap['name'])) if not variableName in variableNames: variableNames.append(variableName) writePluginInfo("ActionTypeId %s = ActionTypeId(\"%s\");" % (variableName, actionType["id"])) createExternDefinition("ActionTypeId", variableName) else: print("duplicated variable name \"%s\" for ActionTypeId %s -> skipping") % (variableName, actionType["id"]) except: pass except: pass def extractEventTypes(deviceClassMap): try: for eventType in deviceClassMap["eventTypes"]: try: variableName = "%sEventTypeId" % (eventType["idName"]) addTranslationString(eventType["name"], 'The name of the EventType %s of deviceClass %s' % (eventType["id"], deviceClassMap['name'])) if not variableName in variableNames: variableNames.append(variableName) writePluginInfo("EventTypeId %s = EventTypeId(\"%s\");" % (variableName, eventType["id"])) createExternDefinition("EventTypeId", variableName) else: print("duplicated variable name \"%s\" for EventTypeId %s -> skipping") % (variableName, eventType["id"]) except: pass except: pass def createExternDefinition(type, name): definition = {} definition['type'] = type definition['variable'] = name externDefinitions.append(definition) def addTranslationString(string, comment): translationStrings.append([string, comment]) #translationStrings.append([unicode(string, "utf-8"), unicode(comment, "utf-8")]) def writeTranslationStrings(): if len(args.translations) is 0: return if len(translationStrings) is not 0: writePluginInfo("// Translation strings") writePluginInfo("const QString translations[] {") for index, value in enumerate(translationStrings): writePluginInfo(" //: %s" % value[1]) if index != len(translationStrings) - 1: writePluginInfo(" QT_TRANSLATE_NOOP(\"%s\", \"%s\"), \n" % (pluginMap["idName"], value[0])) else: writePluginInfo(" QT_TRANSLATE_NOOP(\"%s\", \"%s\")" % (pluginMap["idName"], value[0])) writePluginInfo("};") def createTranslationFiles(): for translation in args.translations: translationFile = (sourceDir + "/" + translation) path, fileName = os.path.split(translationFile) translationOutput = (path + "/" + pluginMap['id'] + '-' + os.path.splitext(fileName)[0] + '.qm') print(" --> Translation update %s" % translationFile) print(subprocess.check_output(['lupdate', '-recursive', '-no-obsolete', sourceDir, (args.builddir + "/" + args.output), '-ts', translationFile])) print(" --> Translation release %s" % translationOutput) print(subprocess.check_output(['lrelease', translationFile, '-qm', translationOutput])) print(" --> Copy translation files to build dir %s" % args.builddir + '/translations/') subprocess.check_output(['rsync', '-a', translationOutput, args.builddir + '/translations/']) ################################################################################################################## # write plugininfo.h print " --> generate plugininfo.h for plugin \"%s\" = %s" % (pluginMap['name'], pluginMap['id']) writePluginInfo("/* This file is generated by the guh build system. Any changes to this file will") writePluginInfo(" * be lost.") writePluginInfo(" *") writePluginInfo(" * If you want to change this file, edit the plugin's json file.") writePluginInfo(" */") writePluginInfo("") writePluginInfo("#ifndef PLUGININFO_H") writePluginInfo("#define PLUGININFO_H") writePluginInfo("") writePluginInfo("#include ") writePluginInfo("#include ") writePluginInfo("") writePluginInfo("#include \"typeutils.h\"") writePluginInfo("") writePluginInfo("// Id definitions") writePluginInfo("PluginId pluginId = PluginId(\"%s\");" % pluginMap['id']) extractVendors(pluginMap) writePluginInfo("") writePluginInfo("// Logging category") if 'idName' in pluginMap: writePluginInfo('Q_DECLARE_LOGGING_CATEGORY(dc%s)' % pluginMap['idName']) writePluginInfo('Q_LOGGING_CATEGORY(dc%s, \"%s\")' % (pluginMap['idName'], pluginMap['idName'])) print 'define logging category: \"dc%s\"' % pluginMap['idName'] writePluginInfo("") # Write translation strings writeTranslationStrings() writePluginInfo("") writePluginInfo("#endif // PLUGININFO_H") outputFile.close() print " --> generated successfully \"%s\"" % (args.output) ################################################################################################################## # Write extern-plugininfo.h print " --> generate extern-plugininfo.h for plugin \"%s\" = %s" % (pluginMap['name'], pluginMap['id']) writeExternPluginInfo("/* This file is generated by the guh build system. Any changes to this file will") writeExternPluginInfo(" * be lost.") writeExternPluginInfo(" *") writeExternPluginInfo(" * If you want to change this file, edit the plugin's json file and add") writeExternPluginInfo(" * idName tags where appropriate.") writeExternPluginInfo(" */") writeExternPluginInfo("") writeExternPluginInfo("#ifndef EXTERNPLUGININFO_H") writeExternPluginInfo("#define EXTERNPLUGININFO_H") writeExternPluginInfo("#include \"typeutils.h\"") writeExternPluginInfo("#include ") writeExternPluginInfo("") writeExternPluginInfo("// Id definitions") for externDefinition in externDefinitions: writeExternPluginInfo("extern %s %s;" % (externDefinition['type'], externDefinition['variable'])) writeExternPluginInfo("") writeExternPluginInfo("// Logging category definition") if 'idName' in pluginMap: writeExternPluginInfo("Q_DECLARE_LOGGING_CATEGORY(dc%s)" % pluginMap['idName']) writeExternPluginInfo("") writeExternPluginInfo("#endif // EXTERNPLUGININFO_H") outputFileExtern.close() print " --> generated successfully \"extern-%s\"" % (args.output) ################################################################################################################## # Translate if len(translationStrings) is not 0: createTranslationFiles()