3 from xml.dom import minidom |
3 from xml.dom import minidom |
4 import cPickle |
4 import cPickle |
5 |
5 |
6 from xmlclass import * |
6 from xmlclass import * |
7 |
7 |
8 from plugger import PlugTemplate |
8 from plugger import PlugTemplate, opjimg |
9 from CFileEditor import CFileEditor |
9 from CFileEditor import CFileEditor |
10 from PLCControler import PLCControler, LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY |
10 from PLCControler import PLCControler, UndoBuffer, LOCATION_PLUGIN, LOCATION_MODULE, LOCATION_GROUP, LOCATION_VAR_INPUT, LOCATION_VAR_OUTPUT, LOCATION_VAR_MEMORY |
11 |
11 |
12 CFileClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "cext_xsd.xsd")) |
12 CFileClasses = GenerateClassesFromXSD(os.path.join(os.path.dirname(__file__), "cext_xsd.xsd")) |
13 |
|
14 #------------------------------------------------------------------------------- |
|
15 # Undo Buffer for CFile |
|
16 #------------------------------------------------------------------------------- |
|
17 |
|
18 # Length of the buffer |
|
19 UNDO_BUFFER_LENGTH = 20 |
|
20 |
|
21 """ |
|
22 Class implementing a buffer of changes made on the current editing model |
|
23 """ |
|
24 class UndoBuffer: |
|
25 |
|
26 # Constructor initialising buffer |
|
27 def __init__(self, currentstate, issaved = False): |
|
28 self.Buffer = [] |
|
29 self.CurrentIndex = -1 |
|
30 self.MinIndex = -1 |
|
31 self.MaxIndex = -1 |
|
32 # if current state is defined |
|
33 if currentstate: |
|
34 self.CurrentIndex = 0 |
|
35 self.MinIndex = 0 |
|
36 self.MaxIndex = 0 |
|
37 # Initialising buffer with currentstate at the first place |
|
38 for i in xrange(UNDO_BUFFER_LENGTH): |
|
39 if i == 0: |
|
40 self.Buffer.append(currentstate) |
|
41 else: |
|
42 self.Buffer.append(None) |
|
43 # Initialising index of state saved |
|
44 if issaved: |
|
45 self.LastSave = 0 |
|
46 else: |
|
47 self.LastSave = -1 |
|
48 |
|
49 # Add a new state in buffer |
|
50 def Buffering(self, currentstate): |
|
51 self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH |
|
52 self.Buffer[self.CurrentIndex] = currentstate |
|
53 # Actualising buffer limits |
|
54 self.MaxIndex = self.CurrentIndex |
|
55 if self.MinIndex == self.CurrentIndex: |
|
56 # If the removed state was the state saved, there is no state saved in the buffer |
|
57 if self.LastSave == self.MinIndex: |
|
58 self.LastSave = -1 |
|
59 self.MinIndex = (self.MinIndex + 1) % UNDO_BUFFER_LENGTH |
|
60 self.MinIndex = max(self.MinIndex, 0) |
|
61 |
|
62 # Return current state of buffer |
|
63 def Current(self): |
|
64 return self.Buffer[self.CurrentIndex] |
|
65 |
|
66 # Change current state to previous in buffer and return new current state |
|
67 def Previous(self): |
|
68 if self.CurrentIndex != self.MinIndex: |
|
69 self.CurrentIndex = (self.CurrentIndex - 1) % UNDO_BUFFER_LENGTH |
|
70 return self.Buffer[self.CurrentIndex] |
|
71 return None |
|
72 |
|
73 # Change current state to next in buffer and return new current state |
|
74 def Next(self): |
|
75 if self.CurrentIndex != self.MaxIndex: |
|
76 self.CurrentIndex = (self.CurrentIndex + 1) % UNDO_BUFFER_LENGTH |
|
77 return self.Buffer[self.CurrentIndex] |
|
78 return None |
|
79 |
|
80 # Return True if current state is the first in buffer |
|
81 def IsFirst(self): |
|
82 return self.CurrentIndex == self.MinIndex |
|
83 |
|
84 # Return True if current state is the last in buffer |
|
85 def IsLast(self): |
|
86 return self.CurrentIndex == self.MaxIndex |
|
87 |
|
88 # Note that current state is saved |
|
89 def CurrentSaved(self): |
|
90 self.LastSave = self.CurrentIndex |
|
91 |
|
92 # Return True if current state is saved |
|
93 def IsCurrentSaved(self): |
|
94 return self.LastSave == self.CurrentIndex |
|
95 |
|
96 |
13 |
97 TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L", |
14 TYPECONVERSION = {"BOOL" : "X", "SINT" : "B", "INT" : "W", "DINT" : "D", "LINT" : "L", |
98 "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L", |
15 "USINT" : "B", "UINT" : "W", "UDINT" : "D", "ULINT" : "L", "REAL" : "D", "LREAL" : "L", |
99 "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"} |
16 "STRING" : "B", "BYTE" : "B", "WORD" : "W", "DWORD" : "D", "LWORD" : "L", "WSTRING" : "W"} |
100 |
17 |
125 self.CFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"]) |
42 self.CFile.loadXMLTree(child, ["xmlns", "xmlns:xsi", "xsi:schemaLocation"]) |
126 self.CFileBuffer = UndoBuffer(self.Copy(self.CFile), True) |
43 self.CFileBuffer = UndoBuffer(self.Copy(self.CFile), True) |
127 else: |
44 else: |
128 self.OnPlugSave() |
45 self.OnPlugSave() |
129 |
46 |
|
47 def GetIconPath(self, name): |
|
48 return opjimg(name) |
|
49 |
130 def CFileName(self): |
50 def CFileName(self): |
131 return os.path.join(self.PlugPath(), "cfile.xml") |
51 return os.path.join(self.PlugPath(), "cfile.xml") |
132 |
52 |
133 def GetFilename(self): |
53 def GetFilename(self): |
134 if self.CFileBuffer.IsCurrentSaved(): |
54 return self.MandatoryParams[1].getName() |
135 return "cfile" |
|
136 else: |
|
137 return "~cfile~" |
|
138 |
55 |
139 def GetBaseTypes(self): |
56 def GetBaseTypes(self): |
140 return self.GetPlugRoot().GetBaseTypes() |
57 return self.GetPlugRoot().GetBaseTypes() |
141 |
58 |
142 def GetDataTypes(self, basetypes = False, only_locatables = False): |
59 def GetDataTypes(self, basetypes = False, only_locatables = False): |
225 return self.CFile.retrieveFunction.gettext() |
142 return self.CFile.retrieveFunction.gettext() |
226 elif name == "Publish": |
143 elif name == "Publish": |
227 return self.CFile.publishFunction.gettext() |
144 return self.CFile.publishFunction.gettext() |
228 return "" |
145 return "" |
229 |
146 |
230 _View = None |
|
231 def _OpenView(self): |
147 def _OpenView(self): |
232 if not self._View: |
148 app_frame = self.GetPlugRoot().AppFrame |
233 open_cfileeditor = True |
149 |
234 has_permissions = self.GetPlugRoot().CheckProjectPathPerm() |
150 cfileeditor = CFileEditor(app_frame.TabsOpened, self, app_frame) |
235 if not has_permissions: |
151 |
236 dialog = wx.MessageDialog(self.GetPlugRoot().AppFrame, |
152 app_frame.EditProjectElement(cfileeditor, self.GetFilename()) |
237 _("You don't have write permissions.\nOpen CFileEditor anyway ?"), |
153 |
238 _("Open CFileEditor"), |
|
239 wx.YES_NO|wx.ICON_QUESTION) |
|
240 open_cfileeditor = dialog.ShowModal() == wx.ID_YES |
|
241 dialog.Destroy() |
|
242 if open_cfileeditor: |
|
243 def _onclose(): |
|
244 self._View = None |
|
245 if has_permissions: |
|
246 def _onsave(): |
|
247 self.GetPlugRoot().SaveProject() |
|
248 else: |
|
249 def _onsave(): |
|
250 pass |
|
251 self._View = CFileEditor(self.GetPlugRoot().AppFrame, self) |
|
252 self._View._onclose = _onclose |
|
253 self._View._onsave = _onsave |
|
254 self._View.Show() |
|
255 |
|
256 PluginMethods = [ |
154 PluginMethods = [ |
257 {"bitmap" : os.path.join("images", "EditCfile"), |
155 {"bitmap" : os.path.join("images", "EditCfile"), |
258 "name" : _("Edit C File"), |
156 "name" : _("Edit C File"), |
259 "tooltip" : _("Edit C File"), |
157 "tooltip" : _("Edit C File"), |
260 "method" : "_OpenView"}, |
158 "method" : "_OpenView"}, |
261 ] |
159 ] |
|
160 |
|
161 def PlugTestModified(self): |
|
162 return self.ChangesToSave or not self.CFileIsSaved() |
262 |
163 |
263 def OnPlugSave(self): |
164 def OnPlugSave(self): |
264 filepath = self.CFileName() |
165 filepath = self.CFileName() |
265 |
166 |
266 text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" |
167 text = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" |