def item_removeAction(self): print_debug("Remove {0}".format(self.actionNode.id), DEBUG_MMI) tabIndex = self.tabWidget.currentIndex() path = str(self.tabWidget.tabToolTip(tabIndex)) self.ddsReader[path].removeObject(self.actionNode.id) self.model[path].removeRow(self.actionIndex.row(), QModelIndex()) self.hasModifToSave[path] = True
def parse(self, path, fileName): if self.bFileParsed == False: # or path != self.filePath: print_debug( "PASDDSObjectParser.parse Parsing object {0} at {1}".format( fileName, path), DEBUG_DDS_OPT_PARSING) self.open(os.sep.join([path, fileName])) self.bFileParsed = True
def constructItemChildren(self, proxyIndex): """Creates the children of an object when we click on it""" path = str(self.tabWidget.tabToolTip(self.tabWidget.currentIndex())) index = self.proxyModel[path].mapToSource(proxyIndex) model = self.model[path] node = model.nodeFromIndex(index) if model.rowCount(index) == 0 and model.isChildOfRoot(index): objectId = node.id self.ddsReader[path].readObject(objectId) object = self.ddsReader[path].getObject(objectId) for j, field in enumerate(object.fields): if field.arraySize == 1: PASObjectNode(field.nameOfField, "byte {0} to {1}".format(field.range_[0], field.range_[1]), field.size, field.arraySize, object[field.nameOfField], node) else: #in case of array append each field of the array arrayNode = PASObjectNode(field.nameOfField, "byte {0} to {1}".format(field.range_[0][0], field.range_[-1][1]), field.size, field.arraySize, object[field.nameOfField], node) for i in range(0, field.arraySize): PASObjectNode(field.nameOfField + "[{0}]".format(i), "byte {0} to {1}".format(field.range_[i][0], field.range_[i][1]), field.size, field.arraySize, object[field.nameOfField], arrayNode) if model.insertRows(0, field.arraySize, model.index(i, 0, model.index(j, 0, index) )) == False: print("Failed to insert array rows to {0}".format(field.nameOfField)) if model.insertRows(0, object.nbFields(), index) == False: print("Failed to insert row to {0}".format(model.nodeFromIndex(index).id)) elif node.typeOfNode == ENUM_TYPE_NODE_OBJECT or node.typeOfNode == ENUM_TYPE_NODE_TYPE_IN_OBJECT: print_debug("Select node {0}".format(node.id), DEBUG_MMI) self.sidePanelModel[path].setCurrentNodeIndex(index) self.tableView.setModel(self.sidePanelModel[path]) self.tableView.setItemDelegate(self.itemDelegate[path])
def isDataValid(self, objectId, data): objectId = self.getStartIndexFromObjectIndex(objectId) if objectId not in self._XMLParsedObjects: xmlParsedObject = self.xmlParseObject(objectId) self._XMLParsedObjects[objectId] = xmlParsedObject spectrum = self._XMLParsedObjects[objectId].spectrum if spectrum == "" or spectrum == "Empty Spectrum": print("This Object was not correctly parsed") return False while data.endswith(' '): data = data[:-1] if len(data) != len(spectrum): print_debug("len(data) != len(spectrum)", DEBUG_DATA_CHECK) return False #Construct a regex to check data regexBase = "(?:[0-9]|[a-fA-F])" regexString = "" cursor = 0 for field in spectrum.split(' '): regexString += "(?:" + regexBase + "){" + "{0}".format( len(field)) + "} " while regexString.endswith(' '): regexString = regexString[:-1] # print(regexString) regMatch = re.compile(regexString) return regMatch.match(data) is not None
def appendDataId(self, newId): """ Adds a PAS_OD_WRITE block in the file Setting the ID of the new created block to 'newId' The new block is appended after last PAS_OD_WRITE block """ if newId in self._objectIdsList: print_debug( "PASDDSObjectParser.appendDataId Id {0} already exists cannot add it again" .format(newId), DEBUG_DDS_OPT_PARSING) else: print_debug("PASDDSParser.appendDataId {0}".format(newId), DEBUG_DDS_OPT_PARSING) iniBlock = INIBlock() iniBlock.name = "[PAS_OD_WRITE]" for optionName, optionValue in self._PAS_OD_WRITE_Blocks[ -1].iterate(): if optionName == "ID": optionValue = "{0:>08} 0000".format(newId) iniBlock.addItem(optionName, optionValue) if len(self._PAS_OD_WRITE_Blocks) > 0: iniBlock.setNextBlock( self._PAS_OD_WRITE_Blocks[-1].nextBlock()) self._PAS_OD_WRITE_Blocks[-1].setNextBlock(iniBlock) else: iniBlock.setNextBlock(self.blockBeforePAS_OD_WRITE.nextBlock()) self.blockBeforePAS_OD_WRITE.setNextBlock(iniBlock) self._PAS_OD_WRITE_Blocks.append( iniBlock ) #TODO test list _PAS_OD_WRITE_Blocks a little bit better in automatic tests self._objectIdsList.append(newId)
def __iter__(self): """Initializes iteration, this object iterates iniBlocks""" # iterates self.iniBlocks (type INIBlock) self.currentBlock = self.firstBlock print_debug("Init: {0}".format(self.currentBlock.name), DEBUG_DDS_OPT_PARSING) self.bIterating = True return self
def calculatePadding(position, dataPadding): padding = 0 while (position + padding) % dataPadding != 0: padding += 1 print_debug( "Padding {0} at position {1} equals {2}".format( dataPadding, position, padding), DEBUG_FLAG_PADDING) return padding
def parse(self, path, objectId): print_debug("Parsing object {0} at {1}".format(objectId, path), DEBUG_DDS_OPT_PARSING) startIndex = self.xmlObjectReader.getStartIndexFromObjectIndex( objectId) if objectId in self.parsedFiles: self.parsedFiles[startIndex].parse(path, objectId) else: self.parsedFiles[startIndex] = PASDDSObjectParser() self.parsedFiles[startIndex].parse(path, objectId)
def updateData(self, index, indexEnd): """Writes updated data in PAS DDS file""" path = str(self.tabWidget.tabToolTip(self.tabWidget.currentIndex())) node = self.model[path].nodeFromIndex(index) id = node.pasTypeOrObject.objectIndex self.ddsReader[path].updateObject(id) if node.nodeUpdated: self.hasModifToSave[path] = True if self.hasModifToSave[path] == False: print_debug("Data at id {0} for path {1} was not modified".format(id, path), DEBUG_MMI)
def setEditorData(self, editor, index): sourceIndex = self.proxyModel.mapToSource(index) pasType = self.sourceModel.nodeFromIndex(sourceIndex).pasTypeOrObject print_debug( "PASParserItemDelegate.setEditorData cat = {0}".format( pasType.cat), DEBUG_MMI) # if pasType.cat == "enum" and pasType.arraySize == 1: # editor.setCurrentIndex(int(pasType.value)) # else: # super(PASParserItemDelegate, self).setEditorData(editor, index) super(PASParserItemDelegate, self).setEditorData(editor, index)
def item_addAction(self): print_debug("PASParserMainWindow.item_addAction Add after {0}".format(self.actionNode.id), DEBUG_MMI) tabIndex = self.tabWidget.currentIndex() path = str(self.tabWidget.tabToolTip(tabIndex)) newId = self.ddsReader[path].copyObject(self.actionNode.id) print_debug("PASParserMainWindow.item_addAction newId = {0}".format(newId), DEBUG_MMI) node = PASObjectNode(newId, '', '', '', self.ddsReader[path].getObject(newId), self.model[path].root) self.model[path].insertRow(self.actionIndex.row(), QModelIndex()) self.hasModifToSave[path] = True
def next(self): # raise KeyError( "next") if self.bIterating == False: raise StopIteration() currentBlock = self.currentBlock print_debug("Next: {0}".format(self.currentBlock.name), DEBUG_DDS_OPT_PARSING) if self.currentBlock.nextBlock() is self.currentBlock: self.bIterating = False else: self.currentBlock = self.currentBlock.nextBlock() return currentBlock
def setModelData(self, editor, model, index): sourceIndex = model.mapToSource(index) pasType = self.sourceModel.nodeFromIndex(sourceIndex).pasTypeOrObject print_debug( "PASParserItemDelegate.setModelData cat = {0}".format( pasType.cat), DEBUG_MMI) if pasType.cat == "enum": self.sourceModel.setData(sourceIndex, QVariant(editor.currentIndex())) else: super(PASParserItemDelegate, self).setModelData(editor, model, index) del editor
def createEditor(self, parentWidget, option, index): #check QItemEditorFactory for help if index.isValid(): sourceIndex = self.proxyModel.mapToSource(index) pasType = self.sourceModel.nodeFromIndex( sourceIndex).pasTypeOrObject print_debug( "PASParserItemDelegate.createEditor objectIndex = {0}".format( pasType.objectIndex), DEBUG_MMI) print_debug( "PASParserItemDelegate.createEditor nameOfField = {0}".format( pasType.nameOfField), DEBUG_MMI) print_debug( "PASParserItemDelegate.createEditor typeName = {0}".format( pasType.typeName), DEBUG_MMI) print_debug( "PASParserItemDelegate.createEditor cat = {0}".format( pasType.cat), DEBUG_MMI) if pasType.cat == "enum": comboBox = QComboBox(parentWidget) for enumField in pasType.enumFields: comboBox.addItem(enumField) if pasType.arraySize == 1: comboBox.setCurrentIndex(int(pasType.value, 16)) else: comboBox.setCurrentIndex( int(pasType.value[sourceIndex.row()], 16)) return comboBox else: return super(PASParserItemDelegate, self).createEditor(parentWidget, option, index)
def removeDataAtId(self, objectId): """Removes the PAS_OD_WRITE block located at position offset raises IndexError if offset is invalid """ if objectId not in self._objectIdsList: print_debug( "PASDDSObjectParser.removeDataAtId Id {0} is missing, cannot remove it" .format(newId), DEBUG_DDS_OPT_PARSING) else: offset = self._objectIdsList.index( objectId) #raises IndexError if offset is invalid blockToRemove = self._PAS_OD_WRITE_Blocks.pop(offset) self._objectIdsList.pop(offset) blockToRemove.previousBlock().setNextBlock( blockToRemove.nextBlock()) return blockToRemove
def setInfos(self, startIndex, nameOfField, start_pos, arraySize, pasType): self.startIndex = startIndex self.nameOfField = nameOfField self.arraySize = arraySize self.pasType = pasType if arraySize == 1: print_debug( "adding index {0} {1} {2}".format(pasType.typeName, start_pos, start_pos + pasType.size), DEBUG_FLAG_RANGES) self.range_ = (start_pos, start_pos + pasType.size - 1) else: print_debug("adding array {0}".format(pasType.typeName), DEBUG_FLAG_RANGES) indexes = [] for i in range(0, arraySize): indexes.append((start_pos, start_pos + pasType.size - 1)) start_pos += pasType.size self.range_ = indexes
def insertDataId(self, newId, offset=0): """Adds a PAS_OD_WRITE block in the file Setting the ID of the new created block to 'newId', the new block is insered BEFORE the block at 'offset' and its content (exept data) is a copy of the block at 'offset'""" if newId in self._objectIdsList: print_debug( "PASDDSObjectParser.insertDataId Id {0} already exist cannot add it again" .format(newId), DEBUG_DDS_OPT_PARSING) else: iniBlock = INIBlock() iniBlock.name = "[PAS_OD_WRITE]" for optionName, optionValue in self._PAS_OD_WRITE_Blocks[ offset].iterate(): if optionName == "ID": optionValue = "{0:>08} 0000".format(newId) iniBlock.addItem(optionName, optionValue) iniBlock.setNextBlock(self._PAS_OD_WRITE_Blocks[offset]) self._PAS_OD_WRITE_Blocks.insert(offset, iniBlock) self._objectIdsList.insert(offset, newId)
def _parseValues(self): bFirstBlock = True for i, block in enumerate(self.iniBlockTexts): print_debug("\nAt {0}, block \n{1}".format(i, block), DEBUG_DDS_OPT_PARSING) iniBlock = INIBlock() iniBlock.name = self.iniBlockNames[i] iniBlock.textContent = block print_debug("*********** {0} *********".format(iniBlock.name), DEBUG_DDS_OPT_PARSING) optionLine = re.compile("^(\w[\w_]*)=(.*)$", flags=re.MULTILINE) for line in block.split("\n"): line = line.lstrip().rstrip() if line.rstrip().lstrip() == "": continue if optionLine.match(line) is None: raise PASDDSFileReadingException( "Line \"{0}\" is not in ini format".format(line)) else: opt = optionLine.search(line) optName = opt.group(1) optValue = opt.group(2) print_debug("OPT {0} : {1}".format(optName, optValue), DEBUG_DDS_OPT_PARSING) iniBlock.addItem(optName, optValue) print_debug("Block: '{0}'".format(iniBlock.name), DEBUG_DDS_OPT_PARSING) if bFirstBlock: self.firstBlock = iniBlock previousBlock = iniBlock bFirstBlock = False else: previousBlock.setNextBlock(iniBlock) previousBlock = iniBlock self.iniBlocks.append(iniBlock) self._PAS_OD_WRITE_Blocks = [ block for block in self.iniBlocks if block.name == "[PAS_OD_WRITE]" ] self._objectIdsList = [ self.getId(i) for i in range(0, self.nbDataId()) ] if len(self._PAS_OD_WRITE_Blocks) > 0: self.blockBeforePAS_OD_WRITE = self._PAS_OD_WRITE_Blocks[ 0].previousBlock()
def _readObjects(self): """ Reads OD.xml file and " initializes _PASObjXMLDict, _objectIndexRanges and PASObjectsString - PASObjectsString is a string that lists of all the objects with their 'name' and 'start_index' ex: "tDDS_ExtInfoELOA_t 0x70001" - _objectIndexRanges is a list of tuple that indicates for each object its address scale ex: For start_index=0x20000 (20000, 20800) because count = 2048 - _PASObjXMLDict is a list of xml node objects we are gonna need later when parsing object content through 'xmlParseObject' function """ elts = "" if len(self.PASObjectsString) > 0: print_debug( "self._readObjects PASObjectsString={0}".format( self.PASObjectsString), DEBUG_DATA_READING) elts = self.PASObjectsString else: for elt in self.OD.findall("group/object"): elt_id = elt.get('start_index').lower() if re.match(r'0x[0-9A-Fa-f]+', elt_id) is not None: elt_int_id = elt_id[2:] self._PASObjXMLDict[elt_int_id] = elt count = self.getCountForObjectNode(elt) self._objectIndexRanges.append( (int(elt_int_id, 16), int(elt_int_id, 16) + count)) print_debug( "Range : {0} to {1}".format( self._objectIndexRanges[-1][0], self._objectIndexRanges[-1][1]), DEBUG_FLAG_ADD_REMOVE_ELEMENTS) elts += elt.get('name') + " " + str(elt_id) + "\n" else: print_debug( "start_index id={0} is not in format 0x[0-9A-Fa-f]+". format(elt_id + " "), DEBUG_FLAG_ADD_REMOVE_ELEMENTS) if elts.endswith('\n'): elts = elts[:-1] self.PASObjectsString = elts return elts
def slot_TreeView_customContextMenuRequested(self, point): path = str(self.tabWidget.tabToolTip(self.tabWidget.currentIndex())) index = self.treeView[path].indexAt(point) index = self.proxyModel[path].mapToSource(index) print_debug("PASParserMainWindow.slot_TreeView_customContextMenuRequested at row: {0}".format(index.row()), DEBUG_MMI) if index.isValid(): contextMenu = QMenu("menu", self) node = self.model[path].nodeFromIndex(index) print_debug("PASParserMainWindow.slot_TreeView_customContextMenuRequested {0}".format(node.id), DEBUG_MMI) print_debug("PASParserMainWindow.slot_TreeView_customContextMenuRequested count: {0}".format(node.pasTypeOrObject.objectCount), DEBUG_MMI) if node.typeOfNode == ENUM_TYPE_NODE_OBJECT and node.pasTypeOrObject.objectCount > 1: actionAdd = QAction(tr("Add object"), self) actionRemove = QAction(tr("Remove object"), self) contextMenu.addAction(actionAdd) contextMenu.addAction(actionRemove) self.actionIndex = index self.actionNode = node actionAdd.triggered.connect(self.item_addAction) actionRemove.triggered.connect(self.item_removeAction) contextMenu.exec_(self.treeView[path].mapToGlobal(point))
def getCountForObjectNode(self, xmlNode): countNode = xmlNode.find('count') count = 1 if countNode is not None and countNode.get('value') != '': count = int(countNode.get('value')) else: elt_int_id = xmlNode.get('start_index')[2:].lower() joinGroup = xmlNode.find('joinGroup') if joinGroup is None: print_debug( "Object with id {0} has no objectCount (default value = 1)" .format(elt_int_id), DEBUG_DATA_READING) else: joinGroup = joinGroup.get('gid') print_debug( "XMLObjectReader._readObjects: StartIndex {0} JoinGroup = {1}" .format(elt_int_id, joinGroup), DEBUG_DATA_READING) xmlRequest = "//group/objectGroup[@gid='{0}']/count".format( joinGroup) print_debug( 'XMLObjectReader._readObjects: xml request "{0}"'.format( xmlRequest), DEBUG_DATA_READING) joinGroupNode = self.OD.xpath(xmlRequest) if len(joinGroupNode) > 0: count = joinGroupNode[0].get('value') if int(count) > 0: print_debug( "XMLObjectReader._readObjects: xml request found {0}" .format(count), DEBUG_DATA_READING) count = int(count) else: print_debug( "XMLObjectReader._readObjects: StartIndex {0} has JoinGroup = {1} with count but no value in the count" .format(elt_int_id, joinGroup), DEBUG_DATA_READING) else: print_debug( "XMLObjectReader._readObjects: StartIndex {0} has JoinGroup = {1} but no count on the joinGroup" .format(elt_int_id, joinGroup), DEBUG_DATA_READING) return count
def getObject(self, objectId): print_debug("DDSReader.getObject {0}".format(objectId), DEBUG_DATA_READING) return self.objContainer[objectId]
def xmlParseObject(self, objectId): """ Parses 'xmlNode' in order to construct a XMLParsedObject using data attributes contained in OD.xml Constructs an arborescence of the types contained in this object using the data in self.typeReader Calculates the position of each typed field in the final DATA representing this object Also constructs the spectrum of this object The "spectrum" is presentation of the way data of this type are presented in the file inside .dds export (file whose name is object's start_index) Example : aaaa 00 bb 00 = padding [a-z] = data (two successive data are named with a different letter) Returns the constructed XMLParsedObject object """ startIndex = self.getStartIndexFromObjectIndex(objectId) if startIndex in self._XMLParsedObjects: parsedObject = self._XMLParsedObjects[startIndex] else: letters = list("ABCDEFGHIJKLMNOPQRSTUVWXYZ") spectrum = "" l = 0 byteNumber = 0 xmlNode = self._PASObjXMLDict[startIndex] parsedObject = XMLParsedObject() parsedObject.groupName = xmlNode.getparent().get('name') parsedObject.objectName = xmlNode.get('name') parsedObject.startIndex = xmlNode.get('start_index')[2:] parsedObject.objectCount = self.getCountForObjectNode(xmlNode) print_debug( "Created a new parsedObj with id {} and startIndex {} count = {}" .format(objectId, parsedObject.startIndex, parsedObject.objectCount), DEBUG_FLAG_ADD_REMOVE_ELEMENTS) for typeNode in xmlNode.findall( 'subindex' ): #<subindex name="" type="type_0230" version="03150000"> nameOfField = typeNode.get('name') typeName = typeNode.get('type') count = int(typeNode.get('count')) #longueur du tableau pasType = self.typeReader.XMLPASTypesDict[typeName] print_debug( "DATA {4}:Type {0} size {1} count {2} padding {3}".format( typeName, pasType.size, count, pasType.padding, letters[l]), DEBUG_FLAG_PADDING) padding = self.calculatePadding(byteNumber, pasType.padding) #add padding for j in range(0, padding): spectrum += "00" if (padding > 0): byteNumber += padding spectrum += " " #fill in parsed object with the type we are currently parsing parsedObject.addField(nameOfField, byteNumber, count, pasType) while count > 0: spectrum += pasType.typeSpectrum.replace('X', letters[l]) count -= 1 spectrum += " " byteNumber += pasType.size l += 1 if spectrum.endswith(' '): spectrum = spectrum[:-1] parsedObject.spectrum = spectrum self._XMLParsedObjects[startIndex] = parsedObject return parsedObject
def readObject(self, objectId): print_debug("DDSReader.readObject {0}".format(objectId)) return self.objContainer[objectId].readData( self.ddsParser.getData(objectId))
def readData(self, data): """ Extracts the value of each field in the bit stream given in "data" Exemple object with start_index 0x30092 Object: 10000 sub0 = 1B eEquipType = 01 u8Number = 02 xBaseAddress = 0A eBoard_slot[0] = 14 eBoard_slot[1] = 0D eBoard_slot[2] = 09 eBoard_slot[3] = 00 eBoard_slot[4] = 00 eBoard_slot[5] = 00 eBoard_slot[6] = 00 eBoard_slot[7] = 00 eBoard_slot[8] = 00 eBoard_slot[9] = 00 eBoard_slot[10] = 00 eBoard_slot[11] = 00 eBoard_slot[12] = 00 eBoard_slot[13] = 00 eBoard_slot[14] = 00 xEAES_Used = 00 eVariant = 03 xSNTPMaster = 0B01010A tSubSlotType[0] = 010110 tSubSlotType[1] = 000000 tSubSlotType[2] = 000000 tSubSlotType[3] = 000000 tSubSlotType[4] = 000000 tSubSlotType[5] = 000000 This function returns a dict object as follows: {'sub0' : 07,'u8IndexBoard' : 01, etc...} """ print_debug( "Reading object {0} with data {1}".format(self.objectIndex, data), DEBUG_DATA_READING) self.formatedData = {} self.dataString = "" data = data.replace(' ', '') for field in self.xmlParsedObject.fields: if field.arraySize == 1: print_debug( "{0}\t\t = {1}".format( field.nameOfField, data[2 * field.range_[0]:2 * (field.range_[1] + 1)]), DEBUG_DATA_READING) self.formatedData[field.nameOfField] = data[2 * field.range_[0]:2 * (field.range_[1] + 1)] #we could convert into integer here, but we can leave it to the "display module" else: arrayContent = [] for i in range(0, field.arraySize): arrayContent.append(data[2 * field.range_[i][0]:2 * (field.range_[i][1] + 1)]) print_debug( "{0}[{1}]\t\t = {2}".format(field.nameOfField, i, arrayContent[i]), DEBUG_DATA_READING) self.formatedData[field.nameOfField] = arrayContent self.dataString = self.writeFormatedData(self.formatedData) return self.formatedData
def parseEnum(self): print_debug("parsing Enum {}".format(self.typeName), DEBUG_MMI) self.enumFields = [] for elt in self.xmlNode.findall("enum"): self.enumFields.append(elt.get('name'))