# HG changeset patch # User lbessard # Date 1197044898 -3600 # Node ID b904d9a99e285f66527c78f9d6c4d69b9b145109 # Parent 98a83c4194b52ede418e52a42c04ed2b242d26ee Adding DCFEditor Dialog to networkedit diff -r 98a83c4194b5 -r b904d9a99e28 objdictgen/commondialogs.py --- a/objdictgen/commondialogs.py Thu Dec 06 17:59:06 2007 +0100 +++ b/objdictgen/commondialogs.py Fri Dec 07 17:28:18 2007 +0100 @@ -25,6 +25,8 @@ import os +from node import BE_to_LE, LE_to_BE + ScriptDirectory = os.path.split(__file__)[0] #------------------------------------------------------------------------------- @@ -1257,3 +1259,297 @@ values["slaveNodeID"] = int(nodeid) values["edsFile"] = self.EDSFile.GetStringSelection() return values + +#------------------------------------------------------------------------------- +# Editing DCF Entry Dialog +#------------------------------------------------------------------------------- + +class DCFEntryValuesTable(wx.grid.PyGridTableBase): + + """ + A custom wxGrid Table using user supplied data + """ + def __init__(self, parent, data, colnames): + # The base class must be initialized *first* + wx.grid.PyGridTableBase.__init__(self) + self.data = data + self.colnames = colnames + self.Parent = parent + # XXX + # we need to store the row length and collength to + # see if the table has changed size + self._rows = self.GetNumberRows() + self._cols = self.GetNumberCols() + + def GetNumberCols(self): + return len(self.colnames) + + def GetNumberRows(self): + return len(self.data) + + def GetColLabelValue(self, col): + if col < len(self.colnames): + return self.colnames[col] + + def GetRowLabelValues(self, row): + return row + + def GetValue(self, row, col): + if row < self.GetNumberRows(): + return str(self.data[row].get(self.GetColLabelValue(col), "")) + + def GetEditor(self, row, col): + if row < self.GetNumberRows(): + return self.editors[row].get(self.GetColLabelValue(col), "") + + def GetValueByName(self, row, colname): + return self.data[row].get(colname) + + def SetValue(self, row, col, value): + if col < len(self.colnames): + self.data[row][self.GetColLabelValue(col)] = value + + def ResetView(self, grid): + """ + (wx.grid.Grid) -> Reset the grid view. Call this to + update the grid if rows and columns have been added or deleted + """ + grid.BeginBatch() + for current, new, delmsg, addmsg in [ + (self._rows, self.GetNumberRows(), wx.grid.GRIDTABLE_NOTIFY_ROWS_DELETED, wx.grid.GRIDTABLE_NOTIFY_ROWS_APPENDED), + (self._cols, self.GetNumberCols(), wx.grid.GRIDTABLE_NOTIFY_COLS_DELETED, wx.grid.GRIDTABLE_NOTIFY_COLS_APPENDED), + ]: + if new < current: + msg = wx.grid.GridTableMessage(self,delmsg,new,current-new) + grid.ProcessTableMessage(msg) + elif new > current: + msg = wx.grid.GridTableMessage(self,addmsg,new-current) + grid.ProcessTableMessage(msg) + self.UpdateValues(grid) + grid.EndBatch() + + self._rows = self.GetNumberRows() + self._cols = self.GetNumberCols() + # update the column rendering scheme + self._updateColAttrs(grid) + + # update the scrollbars and the displayed part of the grid + grid.AdjustScrollbars() + grid.ForceRefresh() + + + def UpdateValues(self, grid): + """Update all displayed values""" + # This sends an event to the grid table to update all of the values + msg = wx.grid.GridTableMessage(self, wx.grid.GRIDTABLE_REQUEST_VIEW_GET_VALUES) + grid.ProcessTableMessage(msg) + + def _updateColAttrs(self, grid): + """ + wx.grid.Grid -> update the column attributes to add the + appropriate renderer given the column name. + + Otherwise default to the default renderer. + """ + + for row in range(self.GetNumberRows()): + for col in range(self.GetNumberCols()): + editor = wx.grid.GridCellTextEditor() + renderer = wx.grid.GridCellStringRenderer() + + grid.SetCellEditor(row, col, editor) + grid.SetCellRenderer(row, col, renderer) + + grid.SetCellBackgroundColour(row, col, wx.WHITE) + + def SetData(self, data): + self.data = data + + def AppendRow(self, row_content): + self.data.append(row_content) + + def Empty(self): + self.data = [] + self.editors = [] + +[ID_DCFENTRYVALUESDIALOG, ID_DCFENTRYVALUESDIALOGVALUESGRID, + ID_DCFENTRYVALUESDIALOGADDBUTTON, ID_DCFENTRYVALUESDIALOGDELETEBUTTON, + ID_DCFENTRYVALUESDIALOGUPBUTTON, ID_DCFENTRYVALUESDIALOGDOWNBUTTON, + ID_VARIABLEEDITORPANELSTATICTEXT1, +] = [wx.NewId() for _init_ctrls in range(7)] + +class DCFEntryValuesDialog(wx.Dialog): + + if wx.VERSION < (2, 6, 0): + def Bind(self, event, function, id = None): + if id is not None: + event(self, id, function) + else: + event(self, function) + + def _init_coll_MainSizer_Items(self, parent): + parent.AddWindow(self.staticText1, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) + parent.AddWindow(self.ValuesGrid, 0, border=20, flag=wx.GROW|wx.TOP|wx.LEFT|wx.RIGHT) + parent.AddSizer(self.ButtonPanelSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.LEFT|wx.RIGHT) + parent.AddSizer(self.ButtonSizer, 0, border=20, flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) + + def _init_coll_MainSizer_Growables(self, parent): + parent.AddGrowableCol(0) + parent.AddGrowableRow(1) + + def _init_coll_ButtonPanelSizer_Items(self, parent): + parent.AddWindow(self.UpButton, 0, border=5, flag=wx.ALL) + parent.AddWindow(self.AddButton, 0, border=5, flag=wx.ALL) + parent.AddWindow(self.DownButton, 0, border=5, flag=wx.ALL) + parent.AddWindow(self.DeleteButton, 0, border=5, flag=wx.ALL) + + def _init_sizers(self): + self.MainSizer = wx.FlexGridSizer(cols=1, hgap=0, rows=3, vgap=0) + self.ButtonPanelSizer = wx.BoxSizer(wx.HORIZONTAL) + + self._init_coll_MainSizer_Items(self.MainSizer) + self._init_coll_MainSizer_Growables(self.MainSizer) + self._init_coll_ButtonPanelSizer_Items(self.ButtonPanelSizer) + + self.SetSizer(self.MainSizer) + + def _init_ctrls(self, prnt): + wx.Dialog.__init__(self, id=ID_DCFENTRYVALUESDIALOG, + name='DCFEntryValuesDialog', parent=prnt, pos=wx.Point(376, 223), + size=wx.Size(400, 300), style=wx.DEFAULT_DIALOG_STYLE|wx.RESIZE_BORDER, + title='Edit DCF Entry Values') + self.SetClientSize(wx.Size(400, 300)) + + self.staticText1 = wx.StaticText(id=ID_VARIABLEEDITORPANELSTATICTEXT1, + label='Entry Values:', name='staticText1', parent=self, + pos=wx.Point(0, 0), size=wx.Size(95, 17), style=0) + + self.ValuesGrid = wx.grid.Grid(id=ID_DCFENTRYVALUESDIALOGVALUESGRID, + name='ValuesGrid', parent=self, pos=wx.Point(0, 0), + size=wx.Size(0, 150), style=wx.VSCROLL) + self.ValuesGrid.SetFont(wx.Font(12, 77, wx.NORMAL, wx.NORMAL, False, + 'Sans')) + self.ValuesGrid.SetLabelFont(wx.Font(10, 77, wx.NORMAL, wx.NORMAL, + False, 'Sans')) + self.ValuesGrid.SetRowLabelSize(0) + self.ValuesGrid.SetSelectionBackground(wx.WHITE) + self.ValuesGrid.SetSelectionForeground(wx.BLACK) + if wx.VERSION >= (2, 6, 0): + self.ValuesGrid.Bind(wx.grid.EVT_GRID_CELL_CHANGE, self.OnValuesGridCellChange) + else: + wx.grid.EVT_GRID_CELL_CHANGE(self.ValuesGrid, self.OnValuesGridCellChange) + + self.AddButton = wx.Button(id=ID_DCFENTRYVALUESDIALOGADDBUTTON, label='Add', + name='AddButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(72, 32), style=0) + self.Bind(wx.EVT_BUTTON, self.OnAddButton, id=ID_DCFENTRYVALUESDIALOGADDBUTTON) + + self.DeleteButton = wx.Button(id=ID_DCFENTRYVALUESDIALOGDELETEBUTTON, label='Delete', + name='DeleteButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(72, 32), style=0) + self.Bind(wx.EVT_BUTTON, self.OnDeleteButton, id=ID_DCFENTRYVALUESDIALOGDELETEBUTTON) + + self.UpButton = wx.Button(id=ID_DCFENTRYVALUESDIALOGUPBUTTON, label='^', + name='UpButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(32, 32), style=0) + self.Bind(wx.EVT_BUTTON, self.OnUpButton, id=ID_DCFENTRYVALUESDIALOGUPBUTTON) + + self.DownButton = wx.Button(id=ID_DCFENTRYVALUESDIALOGDOWNBUTTON, label='v', + name='DownButton', parent=self, pos=wx.Point(0, 0), + size=wx.Size(32, 32), style=0) + self.Bind(wx.EVT_BUTTON, self.OnDownButton, id=ID_DCFENTRYVALUESDIALOGDOWNBUTTON) + + self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) + + self._init_sizers() + + def __init__(self, parent): + self._init_ctrls(parent) + + self.Values = [] + self.DefaultValue = {"Index" : 0, "Subindex" : 0, "Size" : 1, "Value" : 0} + + self.Table = DCFEntryValuesTable(self, [], ["Index", "Subindex", "Size", "Value"]) + self.ValuesGrid.SetTable(self.Table) + + def OnValuesGridCellChange(self, event): + row, col = event.GetRow(), event.GetCol() + colname = self.Table.GetColLabelValue(col) + value = self.Table.GetValue(row, col) + try: + self.Values[row][colname] = int(value, 16) + except: + message = wx.MessageDialog(self, "\"%s\" is not a valid value!"%value, "Error", wx.OK|wx.ICON_ERROR) + message.ShowModal() + message.Destroy() + finally: + wx.CallAfter(self.RefreshValues) + event.Skip() + + def OnAddButton(self, event): + new_row = self.DefaultValue.copy() + self.Values.append(new_row) + self.RefreshValues() + event.Skip() + + def OnDeleteButton(self, event): + row = self.Table.GetRow(self.ValuesGrid.GetGridCursorRow()) + self.Values.remove(row) + self.RefreshValues() + event.Skip() + + def OnUpButton(self, event): + self.MoveValue(self.ValuesGrid.GetGridCursorRow(), -1) + event.Skip() + + def OnDownButton(self, event): + self.MoveValue(self.ValuesGrid.GetGridCursorRow(), 1) + event.Skip() + + def MoveValue(self, value_index, move): + new_index = max(0, min(value_index + move, len(self.Values) - 1)) + if new_index != value_index: + self.Values.insert(new_index, self.Values.pop(value_index)) + self.RefreshValues() + self.ValuesGrid.SetGridCursor(new_index, self.ValuesGrid.GetGridCursorCol()) + else: + self.RefreshValues() + + def SetValues(self, values): + self.Values = [] + if values != "": + data = values[4:] + current = 0 + for i in xrange(BE_to_LE(values[:4])): + value = {} + value["Index"] = BE_to_LE(data[current:current+2]) + value["Subindex"] = BE_to_LE(data[current+2:current+3]) + size = BE_to_LE(data[current+3:current+7]) + value["Size"] = size + value["Value"] = BE_to_LE(data[current+7:current+7+size]) + current += 7 + size + self.Values.append(value) + self.RefreshValues() + + def GetValues(self): + value = LE_to_BE(len(self.Values), 4) + for row in self.Values: + value += LE_to_BE(row["Index"], 2) + value += LE_to_BE(row["Subindex"], 1) + value += LE_to_BE(row["Size"], 4) + value += LE_to_BE(row["Value"], row["Size"]) + return value + + def RefreshValues(self): + if len(self.Table.data) > 0: + self.ValuesGrid.SetGridCursor(0, 1) + data = [] + for value in self.Values: + row = {} + row["Index"] = "%04X"%value["Index"] + row["Subindex"] = "%02X"%value["Subindex"] + row["Size"] = "%08X"%value["Size"] + row["Value"] = ("%0"+"%d"%(value["Size"] * 2)+"X")%value["Value"] + data.append(row) + self.Table.SetData(data) + self.Table.ResetView(self.ValuesGrid) diff -r 98a83c4194b5 -r b904d9a99e28 objdictgen/networkedit.py --- a/objdictgen/networkedit.py Thu Dec 06 17:59:06 2007 +0100 +++ b/objdictgen/networkedit.py Fri Dec 07 17:28:18 2007 +0100 @@ -856,6 +856,10 @@ message.Destroy() dialog.Destroy() + def OpenMasterDCFDialog(self, node_id): + self.NetworkNodes.SetSelection(0) + self.NetworkNodes.GetPage(0).OpenDCFDIalog(node_id) + #------------------------------------------------------------------------------- # Exception Handler #------------------------------------------------------------------------------- diff -r 98a83c4194b5 -r b904d9a99e28 objdictgen/node.py --- a/objdictgen/node.py Thu Dec 06 17:59:06 2007 +0100 +++ b/objdictgen/node.py Fri Dec 07 17:28:18 2007 +0100 @@ -1054,4 +1054,17 @@ data = [char for char in value] data.reverse() return int("".join(["%2.2X"%ord(char) for char in data]), 16) - \ No newline at end of file + +def LE_to_BE(value, size): + """ + Convert Little Endian to Big Endian + @param value: value expressed in integer + @param size: number of bytes generated + @return: a string containing the value converted + """ + + data = ("%" + str(size * 2) + "." + str(size * 2) + "X") % value + list_car = [data[i:i+2] for i in xrange(0, len(data), 2)] + list_car.reverse() + return "".join([chr(int(car, 16)) for car in list_car]) + diff -r 98a83c4194b5 -r b904d9a99e28 objdictgen/nodelist.py --- a/objdictgen/nodelist.py Thu Dec 06 17:59:06 2007 +0100 +++ b/objdictgen/nodelist.py Fri Dec 07 17:28:18 2007 +0100 @@ -313,6 +313,14 @@ print "Can't find node" return [], [] + def AddToMasterDCF(self, node_id, index, subindex, size, value): + # Adding DCF entry into Master node + if not self.Manager.IsCurrentEntry(0x1F22): + self.Manager.AddCurrentEntry(0x1F22, 1, "") + self.Manager.AddSubentriesToCurrent(0x1F22, 127) + + self.Manager.AddToDCF(node_id, index, subindex, size, value) + if __name__ == "__main__": from nodemanager import * import os, sys, shutil diff -r 98a83c4194b5 -r b904d9a99e28 objdictgen/nodemanager.py --- a/objdictgen/nodemanager.py Thu Dec 06 17:59:06 2007 +0100 +++ b/objdictgen/nodemanager.py Fri Dec 07 17:28:18 2007 +0100 @@ -683,6 +683,8 @@ node.SetEntry(index, subIndex, value) except: pass + elif editor == "dcf": + node.SetEntry(index, subIndex, value) else: subentry_infos = self.GetSubentryInfos(index, subIndex) type = subentry_infos["type"] @@ -1048,7 +1050,10 @@ elif dic["type"] in ["TIME_OF_DAY","TIME_DIFFERENCE"]: editor["value"] = "time" elif dic["type"] == "DOMAIN": - editor["value"] = "domain" + if index == 0x1F22: + editor["value"] = "dcf" + else: + editor["value"] = "domain" dic["value"] = dic["value"].encode('hex_codec') elif dic["type"] == "BOOLEAN": editor["value"] = "bool" @@ -1080,6 +1085,14 @@ else: return None + def AddToDCF(self, node_id, index, subindex, size, value): + if self.CurrentNode.IsEntry(0x1F22, node_id): + dcf_value = self.CurrentNode.GetEntry(0x1F22, node_id) + nbparams = BE_to_LE(dcf_value[:4]) + new_value = LE_to_BE(nbparams + 1, 4) + dcf_value[4:] + new_value += LE_to_BE(index, 2) + LE_to_BE(subindex, 1) + LE_to_BE(size, 4) + LE_to_BE(value, size) + self.CurrentNode.SetEntry(0x1F22, node_id, new_value) + #------------------------------------------------------------------------------- # Node Informations Functions #------------------------------------------------------------------------------- diff -r 98a83c4194b5 -r b904d9a99e28 objdictgen/subindextable.py --- a/objdictgen/subindextable.py Thu Dec 06 17:59:06 2007 +0100 +++ b/objdictgen/subindextable.py Fri Dec 07 17:28:18 2007 +0100 @@ -209,6 +209,9 @@ elif editortype == "domain": editor = wx.grid.GridCellTextEditor() renderer = wx.grid.GridCellStringRenderer() + elif editortype == "dcf": + editor = wx.grid.GridCellTextEditor() + renderer = wx.grid.GridCellStringRenderer() else: grid.SetReadOnly(row, col, True) @@ -247,8 +250,8 @@ ] = [wx.NewId() for _init_coll_IndexListMenu_Items in range(3)] [ID_EDITINGPANELMENU1ITEMS0, ID_EDITINGPANELMENU1ITEMS1, - ID_EDITINGPANELMENU1ITEMS3, -] = [wx.NewId() for _init_coll_SubindexGridMenu_Items in range(3)] + ID_EDITINGPANELMENU1ITEMS3, ID_EDITINGPANELMENU1ITEMS4, +] = [wx.NewId() for _init_coll_SubindexGridMenu_Items in range(4)] class EditingPanel(wx.SplitterWindow): def _init_coll_AddToListSizer_Items(self, parent): @@ -282,12 +285,18 @@ parent.AppendSeparator() parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS3, kind=wx.ITEM_NORMAL, text='Default value') + if not self.Editable: + parent.Append(help='', id=ID_EDITINGPANELMENU1ITEMS4, + kind=wx.ITEM_NORMAL, text='Add to DCF') self.Bind(wx.EVT_MENU, self.OnAddSubindexMenu, id=ID_EDITINGPANELMENU1ITEMS0) self.Bind(wx.EVT_MENU, self.OnDeleteSubindexMenu, id=ID_EDITINGPANELMENU1ITEMS1) self.Bind(wx.EVT_MENU, self.OnDefaultValueSubindexMenu, id=ID_EDITINGPANELMENU1ITEMS3) + if not self.Editable: + self.Bind(wx.EVT_MENU, self.OnAddToDCFSubindexMenu, + id=ID_EDITINGPANELMENU1ITEMS4) def _init_coll_IndexListMenu_Items(self, parent): parent.Append(help='', id=ID_EDITINGPANELINDEXLISTMENUITEMS0, @@ -371,6 +380,8 @@ self.OnSubindexGridSelectCell) self.SubindexGrid.Bind(wx.grid.EVT_GRID_CELL_LEFT_CLICK, self.OnSubindexGridCellLeftClick) + self.SubindexGrid.Bind(wx.grid.EVT_GRID_EDITOR_SHOWN, + self.OnSubindexGridEditorShown) self.CallbackCheck = wx.CheckBox(id=ID_EDITINGPANELCALLBACKCHECK, label='Have Callbacks', name='CallbackCheck', @@ -399,13 +410,13 @@ self._init_sizers() def __init__(self, parent, window, manager, editable = True): + self.Editable = editable self._init_ctrls(parent) self.ParentWindow = window self.Manager = manager self.ListIndex = [] self.ChoiceIndex = [] self.FirstCall = False - self.Editable = editable self.Index = None for values in DictionaryOrganisation: @@ -579,6 +590,28 @@ # Editing Table value function #------------------------------------------------------------------------------- + def OnSubindexGridEditorShown(self, event): + row, col = event.GetRow(), event.GetCol() + if self.Table.GetEditor(row, col) == "dcf": + wx.CallAfter(self.ShowDCFEntryDialog, row, col) + event.Veto() + else: + event.Skip() + + def ShowDCFEntryDialog(self, row, col): + if self.Editable: + selected = self.IndexList.GetSelection() + if selected != wx.NOT_FOUND: + index = self.ListIndex[selected] + if self.Manager.IsCurrentEntry(index): + dialog = DCFEntryValuesDialog(self) + dialog.SetValues(self.Table.GetValue(row, col).decode("hex_codec")) + if dialog.ShowModal() == wx.ID_OK: + value = dialog.GetValues() + self.Manager.SetCurrentEntry(index, row, value, "value", "dcf") + self.ParentWindow.RefreshBufferState() + wx.CallAfter(self.RefreshTable) + def OnSubindexGridCellChange(self, event): if self.Editable: index = self.Table.GetCurrentIndex() @@ -654,7 +687,42 @@ self.SubindexGridMenu.FindItemByPosition(3).Enable(False) if showpopup: self.PopupMenu(self.SubindexGridMenu) - event.Skip() + elif self.Table.GetColLabelValue(event.GetCol()) == "value": + selected = self.IndexList.GetSelection() + if selected != wx.NOT_FOUND: + index = self.ListIndex[selected] + if self.Manager.IsCurrentEntry(index): + infos = self.Manager.GetEntryInfos(index) + if not infos["struct"] & OD_MultipleSubindexes or event.GetRow() > 0: + self.SubindexGridMenu.FindItemByPosition(0).Enable(False) + self.SubindexGridMenu.FindItemByPosition(1).Enable(False) + self.SubindexGridMenu.FindItemByPosition(3).Enable(False) + self.SubindexGridMenu.FindItemByPosition(4).Enable(True) + self.PopupMenu(self.SubindexGridMenu) + event.Skip() + + def OnAddToDCFSubindexMenu(self, event): + if not self.Editable: + selected = self.IndexList.GetSelection() + if selected != wx.NOT_FOUND: + index = self.ListIndex[selected] + subindex = self.SubindexGrid.GetGridCursorRow() + entry_infos = self.Manager.GetEntryInfos(index) + if not entry_infos["struct"] & OD_MultipleSubindexes or subindex != 0: + subentry_infos = self.Manager.GetSubentryInfos(index, subindex) + typeinfos = self.Manager.GetEntryInfos(subentry_infos["type"]) + if typeinfos: + node_id = self.ParentWindow.GetCurrentNodeId() + self.Manager.AddToMasterDCF(node_id, index, subindex, max(1, typeinfos["size"] / 8), int(self.Table.GetValueByName(subindex, "value"), 16)) + self.ParentWindow.OpenMasterDCFDialog(node_id) + + def OpenDCFDIalog(self, node_id): + self.PartList.SetSelection(7) + self.RefreshIndexList() + self.IndexList.SetSelection(self.ListIndex.index(0x1F22)) + self.RefreshTable() + self.SubindexGrid.SetGridCursor(node_id, 3) + self.ShowDCFEntryDialog(node_id, 3) def OnRenameIndexMenu(self, event): if self.Editable: @@ -755,4 +823,4 @@ self.Manager.SetCurrentEntryToDefault(index, row) self.ParentWindow.RefreshBufferState() self.RefreshIndexList() - event.Skip() \ No newline at end of file + event.Skip()