# HG changeset patch # User Edouard Tisserant # Date 1553249437 -3600 # Node ID 02d09fc6eb906417e06ad237fc132e4110533236 # Parent 48ebcbe7f19b617949dd4ceb697e198ca123e705# Parent efb5322956079e3a64037a27fde7850757b4f89f Merged search in CTN branch diff -r 48ebcbe7f19b -r 02d09fc6eb90 BeremizIDE.py --- a/BeremizIDE.py Mon Mar 11 13:51:07 2019 +0100 +++ b/BeremizIDE.py Fri Mar 22 11:10:37 2019 +0100 @@ -1033,6 +1033,14 @@ else: IDEFrame.ProjectTreeItemSelect(self, select_item) + def GetProjectElementWindow(self, element, tagname): + is_a_CTN_tagname = len(tagname.split("::"))==1 + if is_a_CTN_tagname: + confnode = self.CTR.GetChildByName(tagname) + return confnode.GetView() + else : + return IDEFrame.GetProjectElementWindow(self, element, tagname) + def SelectProjectTreeItem(self, tagname): if self.ProjectTree is not None: root = self.ProjectTree.GetRootItem() diff -r 48ebcbe7f19b -r 02d09fc6eb90 CodeFileTreeNode.py --- a/CodeFileTreeNode.py Mon Mar 11 13:51:07 2019 +0100 +++ b/CodeFileTreeNode.py Fri Mar 22 11:10:37 2019 +0100 @@ -36,6 +36,9 @@ from PLCControler import UndoBuffer from ConfigTreeNode import XSDSchemaErrorMessage +from plcopen.plcopen import TestTextElement +from editors.CodeFileEditor import GetSectionsText + CODEFILE_XSD = """ @@ -209,6 +212,19 @@ if variable.getonchange()]) return ret + def CTNSearch(self, criteria): + variables = self.GetVariables() + results = [] + tagname = self.CTNFullName() + for index, var in enumerate(variables): + varname = var["Name"] + results.extend([((tagname, "var_inout", index, "name"),) + result + for result in TestTextElement(varname, criteria)]) + results.extend([((tagname, "body"),) + result + for result in TestTextElement( + GetSectionsText(self, lambda x:""), criteria)]) + return results + # ------------------------------------------------------------------------------- # Current Buffering Management Functions # ------------------------------------------------------------------------------- diff -r 48ebcbe7f19b -r 02d09fc6eb90 ConfigTreeNode.py --- a/ConfigTreeNode.py Mon Mar 11 13:51:07 2019 +0100 +++ b/ConfigTreeNode.py Fri Mar 22 11:10:37 2019 +0100 @@ -36,6 +36,7 @@ import traceback import types import shutil +from operator import add from builtins import str as text from past.builtins import execfile @@ -121,6 +122,12 @@ return parent + "." + self.CTNName() return self.BaseParams.getName() + def CTNSearch(self, criteria): + # TODO match config's fields name and fields contents + return reduce(add, [ + CTNChild.CTNSearch(criteria) + for CTNChild in self.IterChildren()]) + def GetIconName(self): return None @@ -464,20 +471,23 @@ def GetContextualMenuItems(self): return None + def GetView(self): + if self._View is None and self.EditorType is not None: + app_frame = self.GetCTRoot().AppFrame + self._View = self.EditorType(app_frame.TabsOpened, self, app_frame) + + return self._View + def _OpenView(self, name=None, onlyopened=False): - if self.EditorType is not None: + view = self.GetView() + + if view is not None: + if name is None: + name = self.CTNFullName() app_frame = self.GetCTRoot().AppFrame - if self._View is None and not onlyopened: - - self._View = self.EditorType(app_frame.TabsOpened, self, app_frame) - - if self._View is not None: - if name is None: - name = self.CTNFullName() - app_frame.EditProjectElement(self._View, name) - - return self._View - return None + app_frame.EditProjectElement(view, name) + + return view def _CloseView(self, view): app_frame = self.GetCTRoot().AppFrame diff -r 48ebcbe7f19b -r 02d09fc6eb90 IDEFrame.py --- a/IDEFrame.py Mon Mar 11 13:51:07 2019 +0100 +++ b/IDEFrame.py Fri Mar 22 11:10:37 2019 +0100 @@ -1819,6 +1819,47 @@ else: event.Skip() + def GetProjectElementWindow(self, element, tagname): + new_window = None + if self.Controler.GetEditedElement(tagname) is not None: + new_window = None + if element == ITEM_CONFIGURATION: + new_window = ConfigurationEditor(self.TabsOpened, tagname, self, self.Controler) + new_window.SetIcon(GetBitmap("CONFIGURATION")) + elif element == ITEM_RESOURCE: + new_window = ResourceEditor(self.TabsOpened, tagname, self, self.Controler) + new_window.SetIcon(GetBitmap("RESOURCE")) + elif element in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]: + bodytype = self.Controler.GetEditedElementBodyType(tagname) + if bodytype == "FBD": + new_window = Viewer(self.TabsOpened, tagname, self, self.Controler) + new_window.RefreshScaling(False) + elif bodytype == "LD": + new_window = LD_Viewer(self.TabsOpened, tagname, self, self.Controler) + new_window.RefreshScaling(False) + elif bodytype == "SFC": + new_window = SFC_Viewer(self.TabsOpened, tagname, self, self.Controler) + new_window.RefreshScaling(False) + else: + new_window = TextViewer(self.TabsOpened, tagname, self, self.Controler) + new_window.SetTextSyntax(bodytype) + if bodytype == "IL": + new_window.SetKeywords(IL_KEYWORDS) + else: + new_window.SetKeywords(ST_KEYWORDS) + if element == ITEM_POU: + pou_type = self.Controler.GetEditedElementType(tagname)[1].upper() + icon = GetBitmap(pou_type, bodytype) + elif element == ITEM_TRANSITION: + icon = GetBitmap("TRANSITION", bodytype) + elif element == ITEM_ACTION: + icon = GetBitmap("ACTION", bodytype) + new_window.SetIcon(icon) + elif element == ITEM_DATATYPE: + new_window = DataTypeEditor(self.TabsOpened, tagname, self, self.Controler) + new_window.SetIcon(GetBitmap("DATATYPE")) + return new_window + def EditProjectElement(self, element, tagname, onlyopened=False): openedidx = self.IsOpened(tagname) if openedidx is not None: @@ -1831,49 +1872,11 @@ elif not onlyopened: if isinstance(element, EditorPanel): new_window = element - self.AddPage(element, "") - elif self.Controler.GetEditedElement(tagname) is not None: - new_window = None - if element == ITEM_CONFIGURATION: - new_window = ConfigurationEditor(self.TabsOpened, tagname, self, self.Controler) - new_window.SetIcon(GetBitmap("CONFIGURATION")) - self.AddPage(new_window, "") - elif element == ITEM_RESOURCE: - new_window = ResourceEditor(self.TabsOpened, tagname, self, self.Controler) - new_window.SetIcon(GetBitmap("RESOURCE")) - self.AddPage(new_window, "") - elif element in [ITEM_POU, ITEM_TRANSITION, ITEM_ACTION]: - bodytype = self.Controler.GetEditedElementBodyType(tagname) - if bodytype == "FBD": - new_window = Viewer(self.TabsOpened, tagname, self, self.Controler) - new_window.RefreshScaling(False) - elif bodytype == "LD": - new_window = LD_Viewer(self.TabsOpened, tagname, self, self.Controler) - new_window.RefreshScaling(False) - elif bodytype == "SFC": - new_window = SFC_Viewer(self.TabsOpened, tagname, self, self.Controler) - new_window.RefreshScaling(False) - else: - new_window = TextViewer(self.TabsOpened, tagname, self, self.Controler) - new_window.SetTextSyntax(bodytype) - if bodytype == "IL": - new_window.SetKeywords(IL_KEYWORDS) - else: - new_window.SetKeywords(ST_KEYWORDS) - if element == ITEM_POU: - pou_type = self.Controler.GetEditedElementType(tagname)[1].upper() - icon = GetBitmap(pou_type, bodytype) - elif element == ITEM_TRANSITION: - icon = GetBitmap("TRANSITION", bodytype) - elif element == ITEM_ACTION: - icon = GetBitmap("ACTION", bodytype) - new_window.SetIcon(icon) - self.AddPage(new_window, "") - elif element == ITEM_DATATYPE: - new_window = DataTypeEditor(self.TabsOpened, tagname, self, self.Controler) - new_window.SetIcon(GetBitmap("DATATYPE")) - self.AddPage(new_window, "") + else: + new_window = self.GetProjectElementWindow(element, tagname) + if new_window is not None: + self.AddPage(new_window, "") openedidx = self.IsOpened(tagname) old_selected = self.TabsOpened.GetSelection() if old_selected != openedidx: diff -r 48ebcbe7f19b -r 02d09fc6eb90 PLCControler.py --- a/PLCControler.py Mon Mar 11 13:51:07 2019 +0100 +++ b/PLCControler.py Fri Mar 22 11:10:37 2019 +0100 @@ -2749,7 +2749,9 @@ # ------------------------------------------------------------------------------- def SearchInProject(self, criteria): - return self.Project.Search(criteria) + project_matches = self.Project.Search(criteria) + ctn_matches = self.CTNSearch(criteria) + return project_matches + ctn_matches def SearchInPou(self, tagname, criteria, debug=False): pou = self.GetEditedElement(tagname, debug) diff -r 48ebcbe7f19b -r 02d09fc6eb90 controls/SearchResultPanel.py --- a/controls/SearchResultPanel.py Mon Mar 11 13:51:07 2019 +0100 +++ b/controls/SearchResultPanel.py Fri Mar 22 11:10:37 2019 +0100 @@ -130,7 +130,9 @@ ("DATATYPE", ITEM_DATATYPE), ("ACTION", "action_block"), ("IL", "IL"), - ("ST", "ST")]: + ("ST", "ST"), + ("FILE", ITEM_CONFNODE), + ]: self.TreeImageDict[itemtype] = self.TreeImageList.Add(GetBitmap(imgname)) for itemtype in ["function", "functionBlock", "program", @@ -202,7 +204,12 @@ children = element_infos.setdefault("children", []) for infos, start, end, text in results: - if infos[1] == "name" or element_type == ITEM_DATATYPE: + if len(words) == 1: # CTN match + child_name = {"body":str(start[0])+":", + "var_inout":_("Variable:")}[infos[1]] + child_type = {"body":ITEM_CONFNODE, + "var_inout":"var_inout"}[infos[1]] + elif infos[1] == "name" or element_type == ITEM_DATATYPE: child_name = GenerateName(infos[1:]) child_type = element_type else: @@ -232,6 +239,7 @@ } children.append(child_infos) + # not Project node if len(words) > 2: for _element_infos in search_results_tree_children: if _element_infos["name"] == words[1]: @@ -240,7 +248,7 @@ break if element_type == ITEM_RESOURCE: search_results_tree_children.append(element_infos) - else: + else: # Project node or CTN search_results_tree_children.append(element_infos) if matches_number < 2: @@ -302,7 +310,7 @@ if text is not None: text_ctrl_style = wx.BORDER_NONE | wx.TE_READONLY | wx.TE_RICH2 if wx.Platform != '__WXMSW__' or len(text.splitlines()) > 1: - text_ctrl_style |= wx.TE_MULTILINE + text_ctrl_style |= wx.TE_MULTILINE | wx.TE_NO_VSCROLL text_ctrl = wx.TextCtrl(id=-1, parent=self.SearchResultsTree, pos=wx.Point(0, 0), value=text, style=text_ctrl_style) width, height = text_ctrl.GetTextExtent(text) diff -r 48ebcbe7f19b -r 02d09fc6eb90 editors/CodeFileEditor.py --- a/editors/CodeFileEditor.py Mon Mar 11 13:51:07 2019 +0100 +++ b/editors/CodeFileEditor.py Fri Mar 22 11:10:37 2019 +0100 @@ -56,6 +56,21 @@ EDGE_COLUMN = 80 +def GetSectionsText(controler, sections_headers): + parts = controler.GetTextParts() + text = "" + for section in controler.SECTIONS_NAMES: + text += sections_headers(section) + if parts[section] == "": + text += "\n" + else: + if not parts[section].startswith("\n"): + text += "\n" + text += parts[section] + if not parts[section].endswith("\n"): + text += "\n" + return text + class CodeEditor(CustomStyledTextCtrl): KEYWORDS = [] @@ -239,20 +254,9 @@ self.CurrentAction = None def GetCodeText(self): - parts = self.Controler.GetTextParts() - text = "" - for section in self.Controler.SECTIONS_NAMES: - section_comments = self.SectionsComments[section] - text += section_comments["comment"] - if parts[section] == "": - text += "\n" - else: - if not parts[section].startswith("\n"): - text += "\n" - text += parts[section] - if not parts[section].endswith("\n"): - text += "\n" - return text + return GetSectionsText( + self.Controler, + lambda section : self.SectionsComments[section]["comment"]) def RefreshView(self, scroll_to_highlight=False): self.ResetBuffer() @@ -644,6 +648,7 @@ """ for row in range(self.GetNumberRows()): + row_highlights = self.Highlights.get(row, {}) for col in range(self.GetNumberCols()): editor = None renderer = None @@ -656,7 +661,9 @@ grid.SetCellEditor(row, col, editor) grid.SetCellRenderer(row, col, renderer) - grid.SetCellBackgroundColour(row, col, wx.WHITE) + highlight_colours = row_highlights.get(colname.lower(), [(wx.WHITE, wx.BLACK)])[-1] + grid.SetCellBackgroundColour(row, col, highlight_colours[0]) + grid.SetCellTextColour(row, col, highlight_colours[1]) self.ResizeRow(grid, row) @@ -859,6 +866,20 @@ return event.Skip() + def AddVariableHighlight(self, infos, highlight_type): + self.Table.AddHighlight(infos, highlight_type) + cell_visible = infos[0] + colnames = [colname.lower() for colname in self.Table.colnames] + self.VariablesGrid.MakeCellVisible(cell_visible, colnames.index(infos[1])) + self.Table.ResetView(self.VariablesGrid) + + def RemoveVariableHighlight(self, infos, highlight_type): + self.Table.RemoveHighlight(infos, highlight_type) + self.Table.ResetView(self.VariablesGrid) + + def ClearHighlights(self, highlight_type=None): + self.Table.ClearHighlights(highlight_type) + self.Table.ResetView(self.VariablesGrid) # ------------------------------------------------------------------------------- # CodeFileEditor Main Frame Class @@ -914,3 +935,21 @@ def Find(self, direction, search_params): self.CodeEditor.Find(direction, search_params) + + def AddHighlight(self, infos, start, end, highlight_type): + if self.VariablesPanel is not None and infos[0] == "var_inout": + self.VariablesPanel.AddVariableHighlight(infos[1:], highlight_type) + else: + self.CodeEditor.AddHighlight(start, end, highlight_type) + + def RemoveHighlight(self, infos, start, end, highlight_type): + if self.VariablesPanel is not None and infos[0] == "var_inout": + self.VariablesPanel.RemoveVariableHighlight(infos[1:], highlight_type) + else: + self.CodeEditor.RemoveHighlight(start, end, highlight_type) + + def ClearHighlights(self, highlight_type=None): + if self.VariablesPanel is not None: + self.VariablesPanel.ClearHighlights(highlight_type) + else: + self.CodeEditor.ClearHighlights(highlight_type) diff -r 48ebcbe7f19b -r 02d09fc6eb90 plcopen/plcopen.py --- a/plcopen/plcopen.py Mon Mar 11 13:51:07 2019 +0100 +++ b/plcopen/plcopen.py Fri Mar 22 11:10:37 2019 +0100 @@ -856,6 +856,7 @@ setattr(cls, "removeVariableByFilter", _removeConfigurationResourceVariableByFilter) def Search(self, criteria, parent_infos=None): + # FIXME : two next lines are incompatible [][-1] raises exception ! parent_infos = [] if parent_infos is None else parent_infos parent_infos = parent_infos[:-1] + ["R::%s::%s" % (parent_infos[-1].split("::")[1], self.getname())] search_result = _SearchInConfigurationResource(self, criteria, parent_infos) diff -r 48ebcbe7f19b -r 02d09fc6eb90 plcopen/types_enums.py --- a/plcopen/types_enums.py Mon Mar 11 13:51:07 2019 +0100 +++ b/plcopen/types_enums.py Fri Mar 22 11:10:37 2019 +0100 @@ -117,6 +117,8 @@ def GetElementType(tagname): words = tagname.split("::") + if len(words) == 1: + return ITEM_CONFNODE return { "D": ITEM_DATATYPE, "P": ITEM_POU,