beremiz

Parents f5cea1a6851e
Children a9bdd7c2f063
Adding support for beremiz extensions to define custom file editors for project files
--- a/Beremiz.py Thu Jun 28 16:42:07 2012 +0200
+++ b/Beremiz.py Sun Jul 01 23:20:19 2012 +0200
@@ -605,12 +605,14 @@
if self.CTR is not None:
selected = self.TabsOpened.GetSelection()
if selected >= 0:
- graphic_viewer = isinstance(self.TabsOpened.GetPage(selected), Viewer)
+ window = self.TabsOpened.GetPage(selected)
+ viewer_is_modified = window.IsModified()
+ is_viewer = isinstance(window, Viewer)
else:
- graphic_viewer = False
+ viewer_is_modified = is_viewer = False
if self.TabsOpened.GetPageCount() > 0:
self.FileMenu.Enable(wx.ID_CLOSE, True)
- if graphic_viewer:
+ if is_viewer:
self.FileMenu.Enable(wx.ID_PREVIEW, True)
self.FileMenu.Enable(wx.ID_PRINT, True)
MenuToolBar.EnableTool(wx.ID_PRINT, True)
@@ -624,7 +626,7 @@
self.FileMenu.Enable(wx.ID_PRINT, False)
MenuToolBar.EnableTool(wx.ID_PRINT, False)
self.FileMenu.Enable(wx.ID_PAGE_SETUP, True)
- project_modified = self.CTR.ProjectTestModified()
+ project_modified = self.CTR.ProjectTestModified() or viewer_is_modified
self.FileMenu.Enable(wx.ID_SAVE, project_modified)
MenuToolBar.EnableTool(wx.ID_SAVE, project_modified)
self.FileMenu.Enable(wx.ID_SAVEAS, True)
@@ -876,12 +878,20 @@
self.RefreshAll()
def OnSaveProjectMenu(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ window = self.TabsOpened.GetPage(selected)
+ window.Save()
if self.CTR is not None:
self.CTR.SaveProject()
self.RefreshAll()
self._Refresh(TITLE, FILEMENU, EDITMENU, PAGETITLES)
def OnSaveProjectAsMenu(self, event):
+ selected = self.TabsOpened.GetSelection()
+ if selected != -1:
+ window = self.TabsOpened.GetPage(selected)
+ window.SaveAs()
if self.CTR is not None:
self.CTR.SaveProjectAs()
self.RefreshAll()
--- a/ConfigTreeNode.py Thu Jun 28 16:42:07 2012 +0200
+++ b/ConfigTreeNode.py Sun Jul 01 23:20:19 2012 +0200
@@ -408,15 +408,13 @@
def _OpenView(self, name=None, onlyopened=False):
if self.EditorType is not None:
app_frame = self.GetCTRoot().AppFrame
- if self._View is None:
+ if self._View is None and not onlyopened:
self._View = self.EditorType(app_frame.TabsOpened, self, app_frame)
-
+
+ if self._View is not None:
app_frame.EditProjectElement(self._View, self.CTNName())
- elif onlyopened:
- app_frame.EditProjectElement(self._View, self.CTNName(), onlyopened)
-
return self._View
return None
--- a/ProjectController.py Thu Jun 28 16:42:07 2012 +0200
+++ b/ProjectController.py Sun Jul 01 23:20:19 2012 +0200
@@ -939,6 +939,10 @@
def _OpenProjectFiles(self):
self._OpenView("Project files")
+ _FileEditors = {}
+ def _OpenFileEditor(self, filepath):
+ self._OpenView(filepath)
+
def _OpenView(self, name=None, onlyopened=False):
if name == "IEC code":
if self._IECCodeView is None:
@@ -955,11 +959,9 @@
self._IECCodeView.SetText(text = text)
self._IECCodeView.SetIcon(GetBitmap("ST"))
+ if self._IECCodeView is not None:
self.AppFrame.EditProjectElement(self._IECCodeView, name)
- elif onlyopened:
- self.AppFrame.EditProjectElement(self._IECCodeView, name, onlyopened)
-
return self._IECCodeView
elif name == "IEC raw code":
@@ -972,25 +974,56 @@
self._IECRawCodeView.SetKeywords(IEC_KEYWORDS)
self._IECRawCodeView.RefreshView()
self._IECRawCodeView.SetIcon(GetBitmap("ST"))
-
+
+ if self._IECRawCodeView is not None:
self.AppFrame.EditProjectElement(self._IECRawCodeView, name)
- elif onlyopened:
- self.AppFrame.EditProjectElement(self._IECRawCodeView, name, onlyopened)
-
return self._IECRawCodeView
elif name == "Project files":
if self._ProjectFilesView is None:
self._ProjectFilesView = FileManagementPanel(self.AppFrame.TabsOpened, self, name, self._getProjectFilesPath(), True)
+ extensions = []
+ for extension, name, editor in features.file_editors:
+ if extension not in extensions:
+ extensions.append(extension)
+ self._ProjectFilesView.SetEditableFileExtensions(extensions)
+
+ if self._ProjectFilesView is not None:
self.AppFrame.EditProjectElement(self._ProjectFilesView, name)
- elif onlyopened:
- self.AppFrame.EditProjectElement(self._ProjectFilesView, name, onlyopened)
+ return self._ProjectFilesView
+
+ elif name is not None and os.path.isfile(name):
+ if not self._FileEditors.has_key(name):
+ file_extension = os.path.splitext(name)[1]
+
+ editors = dict([(editor_name, editor)
+ for extension, editor_name, editor in features.file_editors
+ if extension == file_extension])
+
+ editor_name = None
+ if len(editors) == 1:
+ editor_name = editors.keys()[0]
+ elif len(editors) > 0:
+ names = editors.keys()
+ dialog = wx.SingleChoiceDialog(self.ParentWindow,
+ _("Select an editor:"), _("Editor selection"),
+ names, wx.OK|wx.CANCEL)
+ if dialog.ShowModal() == wx.ID_OK:
+ editor_name = names[dialog.GetSelection()]
+ dialog.Destroy()
+
+ if editor_name is not None:
+ editor = editors[editor_name]()
+ self._FileEditors[name] = editor(self.AppFrame.TabsOpened, self, name, self.AppFrame)
+ self._FileEditors[name].SetIcon(GetBitmap("FILE"))
+
+ if self._FileEditors.has_key(name):
+ self.AppFrame.EditProjectElement(self._FileEditors[name], name)
- return self._ProjectFilesView
-
+ return self._FileEditors[name]
else:
return ConfigTreeNode._OpenView(self, name, onlyopened)
@@ -1002,6 +1035,8 @@
self._IECRawCodeView = None
if self._ProjectFilesView == view:
self._ProjectFilesView = None
+ if view in self._FileEditors.values():
+ self._FileEditors.pop(view.GetTagName())
def _Clean(self):
self._CloseView(self._IECCodeView)
--- a/canfestival/canfestival.py Thu Jun 28 16:42:07 2012 +0200
+++ b/canfestival/canfestival.py Sun Jul 01 23:20:19 2012 +0200
@@ -108,8 +108,8 @@
def GetCanDevice(self):
return self.CanFestivalSlaveNode.getCan_Device()
- def _OpenView(self):
- ConfigTreeNode._OpenView(self)
+ def _OpenView(self, name=None, onlyopened=False):
+ ConfigTreeNode._OpenView(self, name, onlyopened)
if self._View is not None:
self._View.SetBusId(self.GetCurrentLocation())
return self._View
@@ -273,10 +273,8 @@
manager = MiniNodeManager(self, masterpath, self.CTNFullName() + ".generated_master")
self._GeneratedMasterView = MasterViewer(app_frame.TabsOpened, manager, app_frame)
- app_frame.EditProjectElement(self._GeneratedMasterView, name)
-
- elif onlyopened:
- app_frame.EditProjectElement(self._IECCodeView, name, onlyopened)
+ if self._GeneratedMasterView is not None:
+ app_frame.EditProjectElement(self._IECCodeView, name)
return self._GeneratedMasterView
else:
--- a/features.py Thu Jun 28 16:42:07 2012 +0200
+++ b/features.py Sun Jul 01 23:20:19 2012 +0200
@@ -1,5 +1,6 @@
-libraries = [('Python','py_ext.PythonLibrary'),
- ('SVGUI','svgui.SVGUILibrary')]
+libraries = [
+ ('Python', 'py_ext.PythonLibrary'),
+ ('SVGUI', 'svgui.SVGUILibrary')]
catalog = [
('canfestival', _('CANopen support'), _('Map located variables over CANopen'), 'canfestival.canfestival.RootClass'),
@@ -8,3 +9,4 @@
('wxglade_hmi', _('WxGlade GUI'), _('Add a simple WxGlade based GUI.'), 'wxglade_hmi.WxGladeHMI'),
('svgui', _('SVGUI'), _('Experimental web based HMI'), 'svgui.SVGUI')]
+file_editors = []
Binary file images/FILE.png has changed
--- a/images/icons.svg Thu Jun 28 16:42:07 2012 +0200
+++ b/images/icons.svg Sun Jul 01 23:20:19 2012 +0200
@@ -43,9 +43,9 @@
pagecolor="#ffffff"
id="base"
showgrid="false"
- inkscape:zoom="7.2407738"
- inkscape:cx="596.13887"
- inkscape:cy="800.65537"
+ inkscape:zoom="28.963095"
+ inkscape:cx="519.38634"
+ inkscape:cy="721.386"
inkscape:window-x="0"
inkscape:window-y="24"
inkscape:current-layer="svg2"
@@ -87871,6 +87871,164 @@
id="radialGradient3101"
xlink:href="#radialGradient8198"
inkscape:collect="always" />
+ <linearGradient
+ y2="16"
+ x2="15"
+ y1="1"
+ x1="0"
+ gradientTransform="translate(-40,0)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient17986-08"
+ xlink:href="#linearGradient5175-3-7-9-2-7-1"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient5175-3-7-9-2-7-1">
+ <stop
+ style="stop-color:#bdcccd;stop-opacity:1;"
+ offset="0"
+ id="stop5177-6-9-6-1-9-0" />
+ <stop
+ style="stop-color:#7979ff;stop-opacity:1;"
+ offset="1"
+ id="stop5179-73-8-3-1-8-7" />
+ </linearGradient>
+ <linearGradient
+ y2="16"
+ x2="15"
+ y1="1"
+ x1="0"
+ gradientTransform="translate(-40,0)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient18365"
+ xlink:href="#linearGradient5175-3-7-9-2-7-1"
+ inkscape:collect="always" />
+ <linearGradient
+ id="linearGradient3262-4"
+ y2="16"
+ gradientUnits="userSpaceOnUse"
+ x2="25"
+ gradientTransform="translate(-17.058,0)"
+ x1="25">
+ <stop
+ id="stop3311-1"
+ style="stop-color:#f6f6f6"
+ offset="0" />
+ <stop
+ id="stop3313-5"
+ style="stop-color:#ccc"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3264-6"
+ y2="16.004999"
+ gradientUnits="userSpaceOnUse"
+ x2="21"
+ gradientTransform="translate(-17.058,0)"
+ x1="21">
+ <stop
+ id="stop3399-07"
+ style="stop-color:#aaa"
+ offset="0" />
+ <stop
+ id="stop3401-2"
+ style="stop-color:#8c8c8c"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient3260-1"
+ y2="20.895"
+ gradientUnits="userSpaceOnUse"
+ x2="84.639"
+ gradientTransform="matrix(0.096142,0,0,0.096142,1.8469,1.943)"
+ y1="105.1"
+ x1="86.133003">
+ <stop
+ id="stop5130-5-8"
+ style="stop-color:#e5e5e5"
+ offset="0" />
+ <stop
+ id="stop5132-52"
+ style="stop-color:#ababab"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2517-1"
+ y2="47.013"
+ gradientUnits="userSpaceOnUse"
+ x2="25.132"
+ gradientTransform="matrix(0.31429,0,0,0.32593,0.45711,-0.32225)"
+ y1="0.98521"
+ x1="25.132">
+ <stop
+ id="stop3602-3"
+ style="stop-color:#f4f4f4"
+ offset="0" />
+ <stop
+ id="stop3604-1"
+ style="stop-color:#dbdbdb"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2519-4"
+ y2="2.9061999"
+ gradientUnits="userSpaceOnUse"
+ x2="-51.785999"
+ gradientTransform="matrix(0.25379,0,0,0.30502,19.129,-0.68549)"
+ y1="50.785999"
+ x1="-51.785999">
+ <stop
+ id="stop3106-86"
+ style="stop-color:#aaa"
+ offset="0" />
+ <stop
+ id="stop3108-5"
+ style="stop-color:#c8c8c8"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2511-5"
+ y2="46.016998"
+ gradientUnits="userSpaceOnUse"
+ x2="24"
+ gradientTransform="matrix(0.27273,0,0,0.30232,1.4546,0.7442)"
+ y1="2"
+ x1="24">
+ <stop
+ id="stop3213-2"
+ style="stop-color:#fff"
+ offset="0" />
+ <stop
+ id="stop3215-9"
+ style="stop-color:#fff;stop-opacity:0"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ id="linearGradient2507-51"
+ y2="5.4565001"
+ gradientUnits="userSpaceOnUse"
+ x2="36.358002"
+ gradientTransform="matrix(0.3092,0,0,0.37669,0.47615,0.10718)"
+ y1="8.059"
+ x1="32.891998">
+ <stop
+ id="stop8591-03"
+ style="stop-color:#fefefe"
+ offset="0" />
+ <stop
+ id="stop8593-1"
+ style="stop-color:#cbcbcb"
+ offset="1" />
+ </linearGradient>
+ <linearGradient
+ y2="5.4565001"
+ x2="36.358002"
+ y1="8.059"
+ x1="32.891998"
+ gradientTransform="matrix(0.3092,0,0,0.37669,0.47615,0.10718)"
+ gradientUnits="userSpaceOnUse"
+ id="linearGradient3039-9"
+ xlink:href="#linearGradient2507-51"
+ inkscape:collect="always" />
</defs>
<g
id="g19063"
@@ -91756,7 +91914,7 @@
y="318.55981"
x="166.52481"
id="tspan16195-0"
- sodipodi:role="line">%% Extension Cfile Pyfile wxGlade SVGUI FOLDER %%</tspan></text>
+ sodipodi:role="line">%% Extension Cfile Pyfile wxGlade SVGUI FOLDER FILE %%</tspan></text>
<use
style="display:inline"
inkscape:label="#use3839"
@@ -93398,4 +93556,64 @@
sodipodi:nodetypes="cccccccccc"
inkscape:label="#rect2160" />
</g>
+ <g
+ transform="matrix(0.83945151,0,0,0.83945151,496.66938,322.90098)"
+ id="layer1-50">
+ <path
+ inkscape:connector-curvature="0"
+ id="path4160-4"
+ style="fill:url(#linearGradient2517-1);stroke:url(#linearGradient2519-4);stroke-width:0.99992001;stroke-linejoin:round"
+ d="M 1.5,0.49997 H 9.9412 C 10.383,0.66176 12.88,2.63277 13.5,3.90907 v 11.591 h -12 v -15 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path2435-5"
+ style="opacity:0.6;fill:none;stroke:url(#linearGradient2511-5)"
+ d="m 12.5,4.2151 v 10.285 h -10 v -13 h 7.2363" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path3330-0"
+ style="fill:#c1c1c1;fill-rule:evenodd"
+ d="M 9.2941,0.8409 C 10.142,3.6448 9,5.0341 9,5.0341 c 0,0 1.893,-1.2514 4.171,-0.1023 1.943,0.9798 0.036,-1.008 -0.041,-1.129 C 12.587,2.9553 10.707,1.1697 10.025,0.8726 9.9696,0.84836 9.5814,0.8409 9.2941,0.8409 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path4474-14"
+ style="fill:url(#linearGradient3039-9);fill-rule:evenodd"
+ d="m 9.2941,0.8409 c 0.9879,0 0.7059,3.181 0.7059,3.181 0,0 2.272,-0.5007 3.171,0.9099 0.163,0.2556 0.036,-1.008 -0.041,-1.129 C 12.587,2.9553 10.707,1.1697 10.025,0.8726 9.9696,0.84836 9.5814,0.8409 9.2941,0.8409 z" />
+ </g>
+ <g
+ transform="translate(534.91586,321.71842)"
+ style="display:inline"
+ id="FILE"
+ inkscape:export-xdpi="90"
+ inkscape:export-ydpi="90">
+ <path
+ inkscape:connector-curvature="0"
+ style="fill:url(#linearGradient18365);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1;marker:none;visibility:visible;display:inline;overflow:visible"
+ d="m -40,0 0,16 16,0 0,-16 -16,0 z m 1,1 14,0 0,14 -14,0 0,-14 z"
+ id="path3806-1-6-1-9-0"
+ sodipodi:nodetypes="cccccccccc"
+ inkscape:label="#rect2160" />
+ </g>
+ <g
+ transform="matrix(0.39454693,0,0,0.39454693,503.03943,330.01484)"
+ id="layer1-6-4">
+ <g
+ id="g2479-4">
+ <path
+ inkscape:connector-curvature="0"
+ id="path2426-8"
+ style="fill:url(#linearGradient3262-4);stroke:url(#linearGradient3264-6);stroke-linejoin:round;display:block"
+ d="M 6.9375,0.5 C 6.6891,0.5 6.5,0.68908 6.5,0.9375 v 1.25 C 5.9461,2.3297 5.4488,2.5594 4.9688,2.8438 L 4.0625,1.9375 c -0.17566,-0.17566 -0.44934,-0.17566 -0.625,0 l -1.5,1.5 c -0.17566,0.17566 -0.17566,0.44934 0,0.625 L 2.8438,4.9688 C 2.5594,5.4488 2.3297,5.9461 2.1875,6.5 h -1.25 C 0.68908,6.5 0.5,6.6891 0.5,6.9375 v 2.125 c 1e-8,0.24842 0.18908,0.4375 0.4375,0.4375 h 1.25 c 0.1422,0.5539 0.37188,1.0512 0.65625,1.5312 l -0.9063,0.907 c -0.17566,0.17566 -0.17566,0.44934 0,0.625 l 1.5,1.5 c 0.17566,0.17566 0.44934,0.17566 0.625,0 l 0.9063,-0.907 c 0.48,0.285 0.9773,0.514 1.5312,0.656 v 1.25 c 1e-7,0.24842 0.18908,0.4375 0.4375,0.4375 h 2.125 c 0.2484,0 0.4375,-0.189 0.4375,-0.438 v -1.25 c 0.5539,-0.1422 1.0512,-0.37188 1.5312,-0.65625 l 0.90625,0.90625 c 0.17566,0.17566 0.44934,0.17566 0.625,0 l 1.5,-1.5 c 0.17566,-0.17566 0.17566,-0.44934 0,-0.625 l -0.906,-0.906 c 0.285,-0.48 0.514,-0.977 0.656,-1.531 h 1.25 c 0.249,0 0.438,-0.1891 0.438,-0.4375 v -2.125 c 0,-0.2484 -0.189,-0.4375 -0.438,-0.4375 h -1.25 c -0.142,-0.5539 -0.371,-1.0512 -0.656,-1.5312 l 0.906,-0.9063 c 0.17566,-0.17566 0.17566,-0.44934 0,-0.625 l -1.5,-1.5 c -0.17566,-0.17566 -0.44934,-0.17566 -0.625,0 l -0.906,0.9063 c -0.48,-0.2844 -0.977,-0.5141 -1.531,-0.6563 v -1.25 C 9.5004,0.68878 9.3113,0.4997 9.0629,0.4997 H 6.9379 z M 8,6 c 1.104,0 2,0.896 2,2 0,1.104 -0.896,2 -2,2 C 6.896,10 6,9.104 6,8 6,6.896 6.896,6 8,6 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path3315-1"
+ style="opacity:0.05"
+ d="M 8,3.4651 C 5.4994,3.4651 3.4651,5.4994 3.4651,8 c 0,2.501 2.0343,4.535 4.5349,4.535 2.501,0 4.535,-2.034 4.535,-4.535 C 12.535,5.4994 10.501,3.4651 8,3.4651 z m 0,2.093 c 1.3479,0 2.4419,1.094 2.4419,2.4419 0,1.3479 -1.094,2.4419 -2.4419,2.4419 -1.3479,0 -2.4419,-1.0941 -2.4419,-2.442 C 5.5581,6.652 6.6521,5.558 8,5.558 z" />
+ <path
+ inkscape:connector-curvature="0"
+ id="path28-7"
+ style="fill:none;stroke:url(#linearGradient3260-1)"
+ d="M 8,4 C 5.7944,4 4,5.7944 4,8 c 0,2.206 1.7944,4 4,4 2.206,0 4,-1.794 4,-4 C 12,5.7944 10.206,4 8,4 z" />
+ </g>
+ </g>
</svg>
--- a/util/FileManagementPanel.py Thu Jun 28 16:42:07 2012 +0200
+++ b/util/FileManagementPanel.py Sun Jul 01 23:20:19 2012 +0200
@@ -268,7 +268,8 @@
for idx, (name, bitmap, help) in enumerate([
("DeleteButton", "remove_element", _("Remove file from left folder")),
("LeftCopyButton", "LeftCopy", _("Copy file from right folder to left")),
- ("RightCopyButton", "RightCopy", _("copy file from left folder to right"))]):
+ ("RightCopyButton", "RightCopy", _("copy file from left folder to right")),
+ ("EditButton", "edit", _("Edit file"))]):
button = wx.lib.buttons.GenBitmapButton(self.Editor,
bitmap=GetBitmap(bitmap),
size=wx.Size(28, 28), style=wx.NO_BORDER)
@@ -311,6 +312,9 @@
self.Controler = controler
+ self.EditableFileExtensions = []
+ self.EditButton.Hide()
+
self.SetIcon(GetBitmap("FOLDER"))
def __del__(self):
@@ -319,6 +323,11 @@
def GetTitle(self):
return self.TagName
+ def SetEditableFileExtensions(self, extensions):
+ self.EditableFileExtensions = extensions
+ if len(self.EditableFileExtensions) > 0:
+ self.EditButton.Show()
+
def RefreshView(self):
self.ManagedDir.RefreshTree()
self.SystemDir.RefreshTree()
@@ -331,6 +340,10 @@
self.DeleteButton.Enable(os.path.isfile(managed_filepath))
self.LeftCopyButton.Enable(os.path.isfile(system_filepath))
self.RightCopyButton.Enable(os.path.isfile(managed_filepath))
+ if len(self.EditableFileExtensions) > 0:
+ self.EditButton.Enable(
+ os.path.isfile(managed_filepath) and
+ os.path.splitext(managed_filepath)[1] in self.EditableFileExtensions)
def OnTreeItemChanged(self, event):
self.RefreshButtonsState()
@@ -352,6 +365,13 @@
self.ManagedDir.RefreshTree()
event.Skip()
+ def OnEditButton(self, event):
+ filepath = self.ManagedDir.GetPath()
+ if (os.path.isfile(filepath) and
+ os.path.splitext(filepath)[1] in self.EditableFileExtensions):
+ self.Controler._OpenView(filepath)
+ event.Skip()
+
def CopyFile(self, src, dst):
if os.path.isfile(src):
src_folder, src_filename = os.path.split(src)