author | laurent |
Sun, 01 Jul 2012 23:20:19 +0200 | |
changeset 784 | a1d970365e41 |
parent 783 | f5cea1a6851e |
child 785 | a9bdd7c2f063 |
Beremiz.py | file | annotate | diff | comparison | revisions | |
ConfigTreeNode.py | file | annotate | diff | comparison | revisions | |
ProjectController.py | file | annotate | diff | comparison | revisions | |
canfestival/canfestival.py | file | annotate | diff | comparison | revisions | |
features.py | file | annotate | diff | comparison | revisions | |
images/FILE.png | file | annotate | diff | comparison | revisions | |
images/icons.svg | file | annotate | diff | comparison | revisions | |
util/FileManagementPanel.py | file | annotate | diff | comparison | revisions |
--- 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 = []
--- 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)