fix major bugs in Find and Search in Project functionality.
authorSergey Surkov <surkovsv93@gmail.com>
Fri, 28 Oct 2016 18:11:43 +0300
changeset 1556 32e9d0ef30dc
parent 1555 dac6002ff58e
child 1557 52a78c90870f
fix major bugs in Find and Search in Project functionality.

fix case sensitive and regexp search, remove duplicating code

Signed-off-by: Andrey Skvortsov <andrej.skvortzov@gmail.com>
IDEFrame.py
controls/SearchResultPanel.py
dialogs/FindInPouDialog.py
dialogs/SearchInProjectDialog.py
editors/CodeFileEditor.py
editors/TextViewer.py
editors/Viewer.py
plcopen/plcopen.py
--- a/IDEFrame.py	Fri Oct 28 17:21:42 2016 +0300
+++ b/IDEFrame.py	Fri Oct 28 18:11:43 2016 +0300
@@ -1260,6 +1260,7 @@
     def OnFindMenu(self, event):
         if not self.FindDialog.IsShown():
             self.FindDialog.Show()
+            self.FindDialog.FindPattern.SetFocus()
 
     def CloseFindInPouDialog(self):
         selected = self.TabsOpened.GetSelection()
@@ -1284,10 +1285,11 @@
         dialog = SearchInProjectDialog(self)
         if dialog.ShowModal() == wx.ID_OK:
             criteria = dialog.GetCriteria()
-            result = self.Controler.SearchInProject(criteria)
-            self.ClearSearchResults()
-            self.SearchResultPanel.SetSearchResults(criteria, result)
-            self.SelectTab(self.SearchResultPanel)
+            if len(criteria) > 0:
+                result = self.Controler.SearchInProject(criteria)
+                self.ClearSearchResults()
+                self.SearchResultPanel.SetSearchResults(criteria, result)
+                self.SelectTab(self.SearchResultPanel)
 
 #-------------------------------------------------------------------------------
 #                             Display Menu Functions
--- a/controls/SearchResultPanel.py	Fri Oct 28 17:21:42 2016 +0300
+++ b/controls/SearchResultPanel.py	Fri Oct 28 18:11:43 2016 +0300
@@ -253,7 +253,7 @@
             else:
                 header_format = _("'%s' - %d matches in project")
             
-            self.HeaderLabel.SetLabel(header_format % (self.Criteria["raw_pattern"], matches_number))
+            self.HeaderLabel.SetLabel(header_format % (self.Criteria["find_pattern"], matches_number))
             self.ResetButton.Enable(True)
             
             if matches_number > 0:
--- a/dialogs/FindInPouDialog.py	Fri Oct 28 17:21:42 2016 +0300
+++ b/dialogs/FindInPouDialog.py	Fri Oct 28 18:11:43 2016 +0300
@@ -23,6 +23,7 @@
 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 import wx
+from plcopen.plcopen import *
 
 class FindInPouDialog(wx.Frame):
 
@@ -33,13 +34,14 @@
     
     def __init__(self, parent):
         wx.Frame.__init__(self, parent, title=_("Find"), 
-              size=wx.Size(400, 250), style=wx.CAPTION|
+              size=wx.Size(410, 250), style=wx.CAPTION|
                                             wx.CLOSE_BOX|
                                             wx.CLIP_CHILDREN|
                                             wx.RESIZE_BORDER|
                                             wx.STAY_ON_TOP)
         
         self._init_icon(parent)
+        self.CreateStatusBar(style=wx.SB_FLAT)
         panel = wx.Panel(self, style=wx.TAB_TRAVERSAL)
         
         main_sizer = wx.FlexGridSizer(cols=1, hgap=5, rows=2, vgap=5)
@@ -116,7 +118,8 @@
         self.ParentWindow = parent
         
         self.Bind(wx.EVT_CLOSE, self.OnCloseFrame)
-        
+        self.infosPrev = {}
+        self.criteria = {}
         self.FindPattern.SetFocus()
         self.RefreshButtonsState()
     
@@ -141,8 +144,21 @@
             "find_pattern": self.FindPattern.GetValue(),
             "wrap": self.WrapSearch.GetValue(),
             "case_sensitive": self.CaseSensitive.GetValue(),
-            "regular_expression": self.RegularExpressions.GetValue()}
-        wx.CallAfter(self.ParentWindow.FindInPou,
-            {True: 1, False:-1}[self.Forward.GetValue()],
-            infos)
+            "regular_expression": self.RegularExpressions.GetValue(),
+            "filter": "all"}
+
+        if self.infosPrev != infos:
+            self.infosPrev = infos
+            message = ""
+            try:
+                self.criteria = infos
+                CompilePattern(self.criteria)
+            except:
+                self.criteria.clear()
+                message = _("Syntax error in regular expression of pattern to search!")
+            self.SetStatusText(message)
+        if len(self.criteria) > 0:
+            wx.CallAfter(self.ParentWindow.FindInPou,
+                {True: 1, False:-1}[self.Forward.GetValue()],
+                self.criteria)
         event.Skip()
--- a/dialogs/SearchInProjectDialog.py	Fri Oct 28 17:21:42 2016 +0300
+++ b/dialogs/SearchInProjectDialog.py	Fri Oct 28 18:11:43 2016 +0300
@@ -23,17 +23,9 @@
 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
 import re
-
+from plcopen.plcopen import *
 import wx
 
-RE_ESCAPED_CHARACTERS = ".*+()[]?:|{}^$<>=-,"
-
-def EscapeText(text):
-    text = text.replace('\\', '\\\\')
-    for c in RE_ESCAPED_CHARACTERS:
-        text = text.replace(c, '\\' + c)
-    return text
-
 #-------------------------------------------------------------------------------
 #                          Search In Project Dialog
 #-------------------------------------------------------------------------------
@@ -68,6 +60,7 @@
         pattern_sizer.AddWindow(self.CaseSensitive, flag=wx.GROW)
         
         self.Pattern = wx.TextCtrl(self)
+        self.Bind(wx.EVT_TEXT, self.FindPatternChanged, self.Pattern)
         pattern_sizer.AddWindow(self.Pattern, flag=wx.GROW)
         
         self.RegularExpression = wx.CheckBox(self, label=_('Regular expression'))
@@ -99,58 +92,68 @@
         self.ElementsList.Enable(False)
         scope_sizer.AddWindow(self.ElementsList, 1, border=5, 
               flag=wx.GROW|wx.TOP|wx.RIGHT|wx.BOTTOM)
-        
-        self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE)
-        ok_button = self.ButtonSizer.GetAffirmativeButton()
-        ok_button.SetLabel(_('Search'))
-        self.Bind(wx.EVT_BUTTON, self.OnOK, ok_button)
-        main_sizer.AddSizer(self.ButtonSizer, border=20, 
-              flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT)
+
+        buttons_sizer = wx.BoxSizer(wx.HORIZONTAL)
+        main_sizer.AddSizer(buttons_sizer, border=20,
+                            flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.ALIGN_RIGHT)
+
+        self.FindButton = wx.Button(self, label=_("Find"))
+        self.FindButton.SetDefault()
+        self.Bind(wx.EVT_BUTTON, self.OnFindButton, self.FindButton)
+        buttons_sizer.AddWindow(self.FindButton, border=5, flag=wx.RIGHT)
+
+        self.CloseButton = wx.Button(self, label=_("Close"))
+        self.Bind(wx.EVT_BUTTON, self.OnCloseButton, self.CloseButton)
+        buttons_sizer.AddWindow(self.CloseButton)
         
         self.SetSizer(main_sizer)
         
         for name, label in GetElementsChoices():
             self.ElementsList.Append(_(label))
-        
+        self.infosPrev = {}
+        self.criteria = {}
         self.Pattern.SetFocus()
+        self.RefreshButtonsState()
+
+    def RefreshButtonsState(self):
+        find_pattern = self.Pattern.GetValue()
+        self.FindButton.Enable(find_pattern != "")
 
     def GetCriteria(self):
-        raw_pattern = pattern = self.Pattern.GetValue()
-        if not self.CaseSensitive.GetValue():
-            pattern = pattern.upper()
-        if not self.RegularExpression.GetValue():
-            pattern = EscapeText(pattern)
-        criteria = {
-            "raw_pattern": raw_pattern, 
-            "pattern": re.compile(pattern),
+        return self.criteria
+
+    def FindPatternChanged(self, event):
+        self.RefreshButtonsState()
+        event.Skip()
+    def OnScopeChanged(self, event):
+        self.ElementsList.Enable(self.OnlyElements.GetValue())
+        event.Skip()
+
+    def OnCloseButton(self, event):
+        self.EndModal(wx.ID_CANCEL)
+    
+    def OnFindButton(self, event):
+        message = None
+        infos = {
+            "find_pattern": self.Pattern.GetValue(),
             "case_sensitive": self.CaseSensitive.GetValue(),
             "regular_expression": self.RegularExpression.GetValue(),
         }
         if self.WholeProject.GetValue():
-            criteria["filter"] = "all"
+            infos["filter"] = "all"
         elif self.OnlyElements.GetValue():
-            criteria["filter"] = []
+            infos["filter"] = []
             for index, (name, label) in enumerate(GetElementsChoices()):
                 if self.ElementsList.IsChecked(index):
-                    criteria["filter"].append(name)
-        return criteria
-    
-    def OnScopeChanged(self, event):
-        self.ElementsList.Enable(self.OnlyElements.GetValue())
-        event.Skip()
-    
-    def OnOK(self, event):
-        message = None
-        if self.Pattern.GetValue() == "":
-            message = _("Form isn't complete. Pattern to search must be filled!")
-        else:
-            wrong_pattern = False
-            if self.RegularExpression.GetValue():
-                try:
-                    re.compile(self.Pattern.GetValue())
-                except:
-                    wrong_pattern = True
-            if wrong_pattern:
+                    infos["filter"].append(name)
+
+        if self.infosPrev != infos:
+            try:
+                self.criteria = infos
+                CompilePattern(self.criteria)
+                self.infosPrev = infos
+            except:
+                self.criteria.clear()
                 message = _("Syntax error in regular expression of pattern to search!")
         
         if message is not None:
--- a/editors/CodeFileEditor.py	Fri Oct 28 17:21:42 2016 +0300
+++ b/editors/CodeFileEditor.py	Fri Oct 28 18:11:43 2016 +0300
@@ -506,17 +506,11 @@
             self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
 
             self.SearchParams = search_params
-            criteria = {
-                "raw_pattern": search_params["find_pattern"],
-                "pattern": re.compile(search_params["find_pattern"]),
-                "case_sensitive": search_params["case_sensitive"],
-                "regular_expression": search_params["regular_expression"],
-                "filter": "all"}
 
             self.SearchResults = [
                 (start, end, SEARCH_RESULT_HIGHLIGHT)
                 for start, end, text in
-                TestTextElement(self.GetText(), criteria)]
+                TestTextElement(self.GetText(), search_params)]
             self.CurrentFindHighlight = None
 
         if len(self.SearchResults) > 0:
--- a/editors/TextViewer.py	Fri Oct 28 17:21:42 2016 +0300
+++ b/editors/TextViewer.py	Fri Oct 28 18:11:43 2016 +0300
@@ -810,17 +810,10 @@
             self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
 
             self.SearchParams = search_params
-            criteria = {
-                "raw_pattern": search_params["find_pattern"],
-                "pattern": re.compile(search_params["find_pattern"]),
-                "case_sensitive": search_params["case_sensitive"],
-                "regular_expression": search_params["regular_expression"],
-                "filter": "all"}
-
             self.SearchResults = [
                 (infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT)
                 for infos, start, end, text in
-                self.Search(criteria)]
+                self.Search(search_params)]
             self.CurrentFindHighlight = None
 
         if len(self.SearchResults) > 0:
--- a/editors/Viewer.py	Fri Oct 28 17:21:42 2016 +0300
+++ b/editors/Viewer.py	Fri Oct 28 18:11:43 2016 +0300
@@ -3408,16 +3408,9 @@
             self.ClearHighlights(SEARCH_RESULT_HIGHLIGHT)
 
             self.SearchParams = search_params
-            criteria = {
-                "raw_pattern": search_params["find_pattern"],
-                "pattern": re.compile(search_params["find_pattern"]),
-                "case_sensitive": search_params["case_sensitive"],
-                "regular_expression": search_params["regular_expression"],
-                "filter": "all"}
-
             self.SearchResults = []
             blocks = []
-            for infos, start, end, text in self.Controler.SearchInPou(self.TagName, criteria, self.Debug):
+            for infos, start, end, text in self.Controler.SearchInPou(self.TagName, search_params, self.Debug):
                 if infos[1] in ["var_local", "var_input", "var_output", "var_inout"]:
                     self.SearchResults.append((infos[1:], start, end, SEARCH_RESULT_HIGHLIGHT))
                 else:
--- a/plcopen/plcopen.py	Fri Oct 28 17:21:42 2016 +0300
+++ b/plcopen/plcopen.py	Fri Oct 28 18:11:43 2016 +0300
@@ -111,10 +111,15 @@
     lines = text.split("\n")
     return len(lines) - 1, len(lines[-1])
 
+def CompilePattern(criteria):
+    flag = 0 if criteria["case_sensitive"] else re.IGNORECASE
+    find_pattern = criteria["find_pattern"]
+    if not criteria["regular_expression"]:
+        find_pattern = re.escape(find_pattern)
+    criteria["pattern"] = re.compile(find_pattern, flag)
+
 def TestTextElement(text, criteria):
     lines = text.splitlines()
-    if not criteria["case_sensitive"]:
-        text = text.upper()
     test_result = []
     result = criteria["pattern"].search(text)
     while result is not None: