def autoGenAndLayoutMetaItems(self): nodesDefData = loadJsonData('meta/nodes.json') if os.path.exists('meta/template.json'): self.templateData = loadJsonData('meta/template.json') else: self.templateData = {} leftMark = QPointF(-2000, -2050) topLeft = QPointF(-2000, -2050) lastCategory = None lastMaxHeight = 0 for nodeDef in nodesDefData: category = nodeDef['category'] if category != lastCategory: leftMark = leftMark + QPointF(0, lastMaxHeight + 50) topLeft = leftMark lastCategory = category lastMaxHeight = 0 item = self.addDiagramItem(nodeDef) itemRect = item.boundingRect() w, h = itemRect.width(), itemRect.height() item.setPos(topLeft + QPointF(w / 2, h / 2)) if h > lastMaxHeight: lastMaxHeight = h topLeft = topLeft + QPoint(w + 30, 0)
def __init__(self, cmd='list', levelDir=None): self.cmd = cmd if levelDir is not None: self.levelDir = levelDir else: self.prefs = loadJsonData('meta/prefs.json') self.levelDir = self.prefs['open_graph_dir'] self.nodesDefData = loadJsonData('meta/nodes.json')
def hasEditDiff(srcFn, destFn): """ 计算srcFn的文件和destFn的文件,是否有编辑上的区别 计算区别时,会忽略空格和换行符号 """ srcMetaData = loadJsonData(srcFn) destMetaData = loadJsonData(destFn) return srcMetaData != destMetaData
def applyValueChange(self): if not os.path.exists('value_change.py'): print('no value_change.py file exists') return import value_change changeRule = value_change.changeRule for entry in changeRule: for fn in entry['files']: fullname = os.path.join(self.levelDir, fn) if not os.path.exists(fullname): continue levelData = loadJsonData(fullname) nodesData = levelData['nodes'] hasUpdates = False for node in nodesData: if node['type'] != entry['node_type']: continue args = node['args'] attrType = entry['attr_type'] if attrType in args: handleFunc = getattr(value_change, entry['function']) args[attrType] = handleFunc(args[attrType]) hasUpdates = True if hasUpdates: dumpJsonData(fullname, levelData) print('update ', fn)
def listValues(self): if not os.path.exists('value_change.in'): print('no value_change.in file exists') return queryData = loadJsonData('value_change.in') avail_valuesList = [] for entry in queryData: opt_filenames = entry['files'] avail_values = [] for fn in opt_filenames: fullname = os.path.join(self.levelDir, fn) if not os.path.exists(fullname): continue levelData = loadJsonData(fullname) nodesData = levelData['nodes'] for node in nodesData: if node['type'] != entry['node_type']: continue args = node['args'] if entry['attr_type'] in args: avail_values.append(args[entry['attr_type']]) entry['avail_values'] = list(set(avail_values)) entry['function'] = ' type your function here ' # avail_valuesList.append(avail_values) print('please refer value_change.py for more information') leadingString = """ # define your change functions like this # def int2OtherInt(intVal): # return intVal*100 # # def string2OtherString(strVal): # return strVal + '-1' # # then fill these function names to the following changeRule # at last run: # python MetaCompatChecker.py -c %s -d <levelDir> # to apply the value change to all level files under graph directory """ % self.CMD_VALUE_CHANGE changeRuleString = json.dumps(queryData, indent=4) with open('value_change.py', 'w') as f: f.write('%s\n\n' % leadingString) f.write('changeRule = ') f.write('%s\n' % changeRuleString)
def single_file_export(editorData): current_dir = os.path.dirname(os.path.abspath(__file__)) nodeDefFilepath = '/'.join([current_dir, 'meta/nodes.json']) filename = os.path.basename(nodeDefFilepath).split('.')[0] # defData = json.loads(open(nodeDefFilepath, 'r').read()) defData = loadJsonData('meta/nodes.json') validate_def_data(defData) validate_editor_data(editorData) result = do_work(defData, editorData, filename) return result
def attachMetaToFile(self, levelFn): """ 给levelFn文件添加meta字段 """ levelData = loadJsonData(os.path.join(self.levelDir, levelFn)) if levelData.get('mets', None) is not None: return print('attach meta to file', levelFn) usedNodeKeys = set([node['type'] for node in levelData['nodes']]) metas = [] for nodeDef in self.nodesDefData: if nodeDef['name'][-1] in usedNodeKeys: metas.append(nodeDef) levelData['meta'] = metas # oldLevelData = loadJsonData(os.path.join(self.levelDir, levelFn)) # dumpJsonData(os.path.join(self.levelDir, '%s_old.json' % pureName(levelFn)), # oldLevelData) dumpJsonData(os.path.join(self.levelDir, levelFn), levelData)
def upgradeLevelFile(self, levelFn, changeRuleEntry, module): """ 更新某个给定的level文件, :param levelFn: 节点文件名称 :param nodeKeyOnlyInOld: 需要删除的节点key :param attrsUpdatePlans: 相同节点key,的节点属性更新计划 :return: """ logger = logging.getLogger('type_change') levelData = loadJsonData(os.path.join(self.levelDir, levelFn)) levelMeta = levelData['meta'] nodeKeyOnlyInOld, keysCommon = self.check(levelMeta, self.nodesDefData) attrsUpdatePlans = self.attributeUpdatePlans(keysCommon, levelMeta, self.nodesDefData) if len(attrsUpdatePlans) == 0 and len(nodeKeyOnlyInOld) == 0: return id2Type = dict([(node['id'], node['type']) for node in levelData['nodes']]) id2Pos = dict([(node['id'], node['pos']) for node in levelData['nodes']]) hasUpdates = False hasTypeChange = False if len(nodeKeyOnlyInOld) != 0: # 删除已经不用的节点,及其附带的边 self.removeNodesAndEdges(nodeKeyOnlyInOld, levelData) hasUpdates = True newNodesData = [] filterEdgesData = [] # 对新老共有的节点,增删属性 for node in levelData['nodes']: nodeKey = node['type'] if nodeKey in attrsUpdatePlans: deletes = attrsUpdatePlans[nodeKey].get('deletes', []) addPlans = attrsUpdatePlans[nodeKey].get('adds', []) updatePlans = attrsUpdatePlans[nodeKey].get('updates', []) args = node['args'] updatedArgs = {} for argKey in list(args.keys()): if argKey in deletes: hasUpdates = True continue updatedArgs[argKey] = args[argKey] for addPlan in addPlans: if 'default' in addPlan: hasUpdates = True updatedArgs[addPlan['attrId']] = addPlan['default'] for updatePlan in updatePlans: updateTypes = updatePlan['update_types'] argKey = updatePlan['attrId'] for updateType in updateTypes: if updateType == 'add_default': # 如果对应属性没有赋值,且没有入边,将这个默认值加到level数据中 if argKey not in args and \ not self.hasInEdge(levelData['edges'], node['id'], argKey): updatedArgs[argKey] = updatePlan['new_default'] elif updateType == 'delete_default': if argKey in updatedArgs and updatedArgs[ argKey] == updatePlan['old_default']: del updatedArgs[argKey] elif updateType == 'update_default': if argKey in args and args[argKey] == updatePlan[ 'old_default']: updatedArgs[argKey] = updatePlan['new_default'] elif updateType == 'type_change': assert changeRuleEntry is not None, 'no change rule for %s' % levelFn changeAttrType = changeRuleEntry['attr_type'] print('change attr', changeAttrType) if changeAttrType in args: # 被改变的数据具有参数值 handleFunc = getattr( module, changeRuleEntry['function']) # args[changeAttrType] = handleFunc(args[changeAttrType]) updatedArgs[changeAttrType] = handleFunc( args[changeAttrType]) hasTypeChange = True elif self.hasInEdge(levelData['edges'], node['id'], changeAttrType): # 检查该属性是否有附带的边 # 有附带的边, 删除该边 filterEdgesData.append({ 'toId': node['id'], 'toItemId': changeAttrType }) hasUpdates = True node['args'] = updatedArgs newNodesData.append(node) # 对于已经删除的属性构成的边,要删除所有附带边 newEdgesData = [] for edge in levelData['edges']: # 检验出边 startNodeKey = id2Type[edge['start']] startItemKey = edge['startItemId'] if startNodeKey in attrsUpdatePlans: deletes = attrsUpdatePlans[startNodeKey].get('deletes', []) if startItemKey in deletes: hasUpdates = True continue # 检验入边 endNodeKey = id2Type[edge['end']] endItemKey = edge['endItemId'] if endNodeKey in attrsUpdatePlans: deletes = attrsUpdatePlans[endNodeKey].get('deletes', []) if endItemKey in deletes: hasUpdates = True continue isFiltered = False for feData in filterEdgesData: if feData['toId'] == edge['end'] and feData[ 'toItemId'] == edge['endItemId']: startPos, endPos = id2Pos[edge['start']], id2Pos[ edge['end']] msg = 'delete edge of %s, %s|%s (%.1f,%.1f) --> %s|%s (%.1f, %.1f)' % ( levelFn, edge['startNodeName'], edge['startItemName'], startPos['x'], startPos['y'], edge['endNodeName'], edge['endItemName'], endPos['x'], endPos['y']) isFiltered = True logger.info(msg) break if not isFiltered: newEdgesData.append(edge) if not hasUpdates: return levelData['nodes'] = newNodesData levelData['edges'] = newEdgesData if hasUpdates: metas = [] usedNodeKeys = set([node['type'] for node in levelData['nodes']]) for nodeDef in self.nodesDefData: if nodeDef['name'][-1] in usedNodeKeys: metas.append(nodeDef) levelData['meta'] = metas # 将老文件进行备份,命名为XX_old.json # oldLevelData = loadJsonData(os.path.join(self.levelDir, levelFn)) # dumpJsonData(os.path.join(self.levelDir, '%s_old.json' % pureName(levelFn)), oldLevelData) # 将levelData写入到文件中 dumpJsonData(os.path.join(self.levelDir, levelFn), levelData) print('done', levelFn)
def listUpgradeInfos(self): """ 列出更新信息,但不对文件进行更新,由程序确定没有错误后,再进行更新 """ nodesDefData = loadJsonData('meta/nodes.json') levelFns = os.listdir(self.levelDir) id2Name = {} id2Name.update(self.extractId2NameMapping(nodesDefData)) print('discovered following updates:') hasTypeChange = False changeTable = [] for levelFn in levelFns: if not levelFn.endswith('.json') or levelFn.endswith('_old.json'): continue levelData = loadJsonData(os.path.join(self.levelDir, levelFn)) levelMeta = levelData['meta'] keysOnlyInOld, keysCommon = self.check(levelMeta, nodesDefData) id2Name.update(self.extractId2NameMapping(levelMeta)) attrsUpdatePlans = self.attributeUpdatePlans( keysCommon, levelMeta, nodesDefData) print('%s:' % levelFn) if len(keysOnlyInOld) != 0: print('nodes removed') for nodeKey in keysOnlyInOld: print(id2Name[nodeKey]) print() if len(attrsUpdatePlans) != 0: for nodeKey in attrsUpdatePlans: print('attr updates for node:', id2Name[nodeKey]) deletes = attrsUpdatePlans[nodeKey].get('deletes', []) if len(deletes) != 0: print('attribute deletes') for attrKey in deletes: print(id2Name[attrKey]) print() adds = attrsUpdatePlans[nodeKey].get('adds', []) if len(adds) != 0: print('attribute adds') for addEntry in adds: print(id2Name[addEntry['attrId']], end=' ') if 'default' in addEntry: print(':', addEntry['default']) else: print() updatePlans = attrsUpdatePlans[nodeKey].get('updates', []) if len(updatePlans) != 0: print('attribute updates') for updatePlan in updatePlans: for updateType in updatePlan['update_types']: if updateType == 'add_default': print('add default value', updatePlan['new_default'], 'for attr', id2Name[updatePlan['attrId']]) elif updateType == 'delete_default': print('remove default value', updatePlan['old_default'], 'for attr', id2Name[updatePlan['attrId']]) elif updateType == 'update_default': print('update default value', updatePlan['old_default'], '->', updatePlan['new_default'], 'for attr', id2Name[updatePlan['attrId']]) elif updateType == 'type_change': hasTypeChange = True print('change type', updatePlan['old_type'], '->', updatePlan['new_type'], 'for attr', id2Name[updatePlan['attrId']]) changeTableEntry = { 'level': levelFn, 'old_type': updatePlan['old_type'], 'new_type': updatePlan['new_type'], 'attr_type': updatePlan['attrId'], 'attr_name': id2Name[updatePlan['attrId']], 'node_type': nodeKey, 'node_name': id2Name[nodeKey] } # print 'before' self.fillWithAvailableValues( changeTableEntry, levelData) changeTable.append(changeTableEntry) print() print() if hasTypeChange: print('please refer type_change.py for more information') leadingString = """ # define your change functions like this # def string2Int(strVal): # return int(strVal) # # def bool2String(boolVal): # return str(boolVal) # # then fill these function names to the following changeRule # at last run: # python MetaCompatChecker.py %s # to apply the value change to all level files under graph directory # original version of level are saved as level_xxx_old.json """ % self.CMD_UPGRADE changeRuleString = json.dumps(changeTable, indent=4) with open('type_change.py', 'w') as f: f.write('%s\n\n' % leadingString) f.write('changeRule = ') f.write('%s\n' % changeRuleString) else: if os.path.exists('type_change.py'): os.remove('type_change.py')
def load_nodes_meta_information(): """右键菜单模板数据""" return loadJsonData(os.path.join('meta', 'nodes.json'))
def load_prefs(): return loadJsonData(os.path.join('meta', 'prefs.json'))
def load_color_config(): return loadJsonData(os.path.join('meta', 'colors.json'))
def load_graph_information(filename): return loadJsonData(filename)