1 #!/usr/bin/env python |
1 #!/usr/bin/env python |
2 # -*- coding: utf-8 -*- |
2 # -*- coding: utf-8 -*- |
3 |
3 |
4 #This file is part of PLCOpenEditor, a library implementing an IEC 61131-3 editor |
4 # This file is part of Beremiz, a Integrated Development Environment for |
5 #based on the plcopen standard. |
5 # programming IEC 61131-3 automates supporting plcopen standard and CanFestival. |
6 # |
6 # |
7 #Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD |
7 # Copyright (C) 2007: Edouard TISSERANT and Laurent BESSARD |
8 # |
8 # |
9 #See COPYING file for copyrights details. |
9 # See COPYING file for copyrights details. |
10 # |
10 # |
11 #This library is free software; you can redistribute it and/or |
11 # This program is free software; you can redistribute it and/or |
12 #modify it under the terms of the GNU General Public |
12 # modify it under the terms of the GNU General Public License |
13 #License as published by the Free Software Foundation; either |
13 # as published by the Free Software Foundation; either version 2 |
14 #version 2.1 of the License, or (at your option) any later version. |
14 # of the License, or (at your option) any later version. |
15 # |
15 # |
16 #This library is distributed in the hope that it will be useful, |
16 # This program is distributed in the hope that it will be useful, |
17 #but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 #MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
18 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 #General Public License for more details. |
19 # GNU General Public License for more details. |
20 # |
20 # |
21 #You should have received a copy of the GNU General Public |
21 # You should have received a copy of the GNU General Public License |
22 #License along with this library; if not, write to the Free Software |
22 # along with this program; if not, write to the Free Software |
23 #Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
23 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. |
24 |
24 |
25 import re |
25 import re |
26 |
26 from plcopen.plcopen import * |
27 import wx |
27 import wx |
28 |
|
29 RE_ESCAPED_CHARACTERS = ".*+()[]?:|{}^$<>=-," |
|
30 |
|
31 def EscapeText(text): |
|
32 text = text.replace('\\', '\\\\') |
|
33 for c in RE_ESCAPED_CHARACTERS: |
|
34 text = text.replace(c, '\\' + c) |
|
35 return text |
|
36 |
28 |
37 #------------------------------------------------------------------------------- |
29 #------------------------------------------------------------------------------- |
38 # Search In Project Dialog |
30 # Search In Project Dialog |
39 #------------------------------------------------------------------------------- |
31 #------------------------------------------------------------------------------- |
40 |
32 |
66 |
58 |
67 self.CaseSensitive = wx.CheckBox(self, label=_('Case sensitive')) |
59 self.CaseSensitive = wx.CheckBox(self, label=_('Case sensitive')) |
68 pattern_sizer.AddWindow(self.CaseSensitive, flag=wx.GROW) |
60 pattern_sizer.AddWindow(self.CaseSensitive, flag=wx.GROW) |
69 |
61 |
70 self.Pattern = wx.TextCtrl(self) |
62 self.Pattern = wx.TextCtrl(self) |
|
63 self.Bind(wx.EVT_TEXT, self.FindPatternChanged, self.Pattern) |
71 pattern_sizer.AddWindow(self.Pattern, flag=wx.GROW) |
64 pattern_sizer.AddWindow(self.Pattern, flag=wx.GROW) |
72 |
65 self.Bind(wx.EVT_CHAR_HOOK, self.OnEscapeKey) |
73 self.RegularExpression = wx.CheckBox(self, label=_('Regular expression')) |
66 self.RegularExpression = wx.CheckBox(self, label=_('Regular expression')) |
74 pattern_sizer.AddWindow(self.RegularExpression, flag=wx.GROW) |
67 pattern_sizer.AddWindow(self.RegularExpression, flag=wx.GROW) |
75 |
68 |
76 scope_staticbox = wx.StaticBox(self, label=_('Scope')) |
69 scope_staticbox = wx.StaticBox(self, label=_('Scope')) |
77 scope_sizer = wx.StaticBoxSizer(scope_staticbox, wx.HORIZONTAL) |
70 scope_sizer = wx.StaticBoxSizer(scope_staticbox, wx.HORIZONTAL) |
97 |
90 |
98 self.ElementsList = wx.CheckListBox(self) |
91 self.ElementsList = wx.CheckListBox(self) |
99 self.ElementsList.Enable(False) |
92 self.ElementsList.Enable(False) |
100 scope_sizer.AddWindow(self.ElementsList, 1, border=5, |
93 scope_sizer.AddWindow(self.ElementsList, 1, border=5, |
101 flag=wx.GROW|wx.TOP|wx.RIGHT|wx.BOTTOM) |
94 flag=wx.GROW|wx.TOP|wx.RIGHT|wx.BOTTOM) |
102 |
95 |
103 self.ButtonSizer = self.CreateButtonSizer(wx.OK|wx.CANCEL|wx.CENTRE) |
96 buttons_sizer = wx.BoxSizer(wx.HORIZONTAL) |
104 ok_button = self.ButtonSizer.GetAffirmativeButton() |
97 main_sizer.AddSizer(buttons_sizer, border=20, |
105 ok_button.SetLabel(_('Search')) |
98 flag=wx.LEFT | wx.RIGHT | wx.BOTTOM | wx.ALIGN_RIGHT) |
106 self.Bind(wx.EVT_BUTTON, self.OnOK, ok_button) |
99 |
107 main_sizer.AddSizer(self.ButtonSizer, border=20, |
100 self.FindButton = wx.Button(self, label=_("Find")) |
108 flag=wx.ALIGN_RIGHT|wx.BOTTOM|wx.LEFT|wx.RIGHT) |
101 self.FindButton.SetDefault() |
|
102 self.Bind(wx.EVT_BUTTON, self.OnFindButton, self.FindButton) |
|
103 buttons_sizer.AddWindow(self.FindButton, border=5, flag=wx.RIGHT) |
|
104 |
|
105 self.CloseButton = wx.Button(self, label=_("Close")) |
|
106 self.Bind(wx.EVT_BUTTON, self.OnCloseButton, self.CloseButton) |
|
107 buttons_sizer.AddWindow(self.CloseButton) |
109 |
108 |
110 self.SetSizer(main_sizer) |
109 self.SetSizer(main_sizer) |
111 |
110 |
112 for name, label in GetElementsChoices(): |
111 for name, label in GetElementsChoices(): |
113 self.ElementsList.Append(_(label)) |
112 self.ElementsList.Append(_(label)) |
114 |
113 self.infosPrev = {} |
|
114 self.criteria = {} |
115 self.Pattern.SetFocus() |
115 self.Pattern.SetFocus() |
|
116 self.RefreshButtonsState() |
|
117 |
|
118 def RefreshButtonsState(self): |
|
119 find_pattern = self.Pattern.GetValue() |
|
120 self.FindButton.Enable(find_pattern != "") |
116 |
121 |
117 def GetCriteria(self): |
122 def GetCriteria(self): |
118 raw_pattern = pattern = self.Pattern.GetValue() |
123 return self.criteria |
119 if not self.CaseSensitive.GetValue(): |
124 |
120 pattern = pattern.upper() |
125 def FindPatternChanged(self, event): |
121 if not self.RegularExpression.GetValue(): |
126 self.RefreshButtonsState() |
122 pattern = EscapeText(pattern) |
127 event.Skip() |
123 criteria = { |
128 |
124 "raw_pattern": raw_pattern, |
129 def OnScopeChanged(self, event): |
125 "pattern": re.compile(pattern), |
130 self.ElementsList.Enable(self.OnlyElements.GetValue()) |
|
131 event.Skip() |
|
132 |
|
133 def OnCloseButton(self, event): |
|
134 self.EndModal(wx.ID_CANCEL) |
|
135 |
|
136 def OnEscapeKey(self, event): |
|
137 keycode = event.GetKeyCode() |
|
138 if keycode == wx.WXK_ESCAPE: |
|
139 self.OnCloseButton(event) |
|
140 else: |
|
141 event.Skip() |
|
142 |
|
143 def OnFindButton(self, event): |
|
144 message = None |
|
145 infos = { |
|
146 "find_pattern": self.Pattern.GetValue(), |
126 "case_sensitive": self.CaseSensitive.GetValue(), |
147 "case_sensitive": self.CaseSensitive.GetValue(), |
127 "regular_expression": self.RegularExpression.GetValue(), |
148 "regular_expression": self.RegularExpression.GetValue(), |
128 } |
149 } |
129 if self.WholeProject.GetValue(): |
150 if self.WholeProject.GetValue(): |
130 criteria["filter"] = "all" |
151 infos["filter"] = "all" |
131 elif self.OnlyElements.GetValue(): |
152 elif self.OnlyElements.GetValue(): |
132 criteria["filter"] = [] |
153 infos["filter"] = [] |
133 for index, (name, label) in enumerate(GetElementsChoices()): |
154 for index, (name, label) in enumerate(GetElementsChoices()): |
134 if self.ElementsList.IsChecked(index): |
155 if self.ElementsList.IsChecked(index): |
135 criteria["filter"].append(name) |
156 infos["filter"].append(name) |
136 return criteria |
157 |
137 |
158 if self.infosPrev != infos: |
138 def OnScopeChanged(self, event): |
159 try: |
139 self.ElementsList.Enable(self.OnlyElements.GetValue()) |
160 self.criteria = infos |
140 event.Skip() |
161 CompilePattern(self.criteria) |
141 |
162 self.infosPrev = infos |
142 def OnOK(self, event): |
163 except: |
143 message = None |
164 self.criteria.clear() |
144 if self.Pattern.GetValue() == "": |
|
145 message = _("Form isn't complete. Pattern to search must be filled!") |
|
146 else: |
|
147 wrong_pattern = False |
|
148 if self.RegularExpression.GetValue(): |
|
149 try: |
|
150 re.compile(self.Pattern.GetValue()) |
|
151 except: |
|
152 wrong_pattern = True |
|
153 if wrong_pattern: |
|
154 message = _("Syntax error in regular expression of pattern to search!") |
165 message = _("Syntax error in regular expression of pattern to search!") |
155 |
166 |
156 if message is not None: |
167 if message is not None: |
157 dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR) |
168 dialog = wx.MessageDialog(self, message, _("Error"), wx.OK|wx.ICON_ERROR) |
158 dialog.ShowModal() |
169 dialog.ShowModal() |