FreeCAD

Форк
0
/
FreeCADGuiInit.py 
319 строк · 13.4 Кб
1
#***************************************************************************
2
#*   Copyright (c) 2002,2003 Jürgen Riegel <juergen.riegel@web.de>         *
3
#*                                                                         *
4
#*   This file is part of the FreeCAD CAx development system.              *
5
#*                                                                         *
6
#*   This program is free software; you can redistribute it and/or modify  *
7
#*   it under the terms of the GNU Lesser General Public License (LGPL)    *
8
#*   as published by the Free Software Foundation; either version 2 of     *
9
#*   the License, or (at your option) any later version.                   *
10
#*   for detail see the LICENCE text file.                                 *
11
#*                                                                         *
12
#*   FreeCAD is distributed in the hope that it will be useful,            *
13
#*   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
14
#*   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
15
#*   GNU Lesser General Public License for more details.                   *
16
#*                                                                         *
17
#*   You should have received a copy of the GNU Library General Public     *
18
#*   License along with FreeCAD; if not, write to the Free Software        *
19
#*   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  *
20
#*   USA                                                                   *
21
#*                                                                         *
22
#***************************************************************************/
23

24
# FreeCAD gui init module
25
#
26
# Gathering all the information to start FreeCAD
27
# This is the second one of three init scripts, the third one
28
# runs when the gui is up
29

30
# imports the one and only
31
import FreeCAD, FreeCADGui
32
from enum import IntEnum
33

34
# shortcuts
35
Gui = FreeCADGui
36

37
# this is to keep old code working
38
Gui.listCommands = Gui.Command.listAll
39
Gui.isCommandActive = lambda cmd: Gui.Command.get(cmd).isActive()
40

41
# The values must match with that of the C++ enum class ResolveMode
42
class ResolveMode(IntEnum):
43
    NoResolve = 0
44
    OldStyleElement = 1
45
    NewStyleElement = 2
46
    FollowLink = 3
47

48
Gui.Selection.ResolveMode = ResolveMode
49

50
# The values must match with that of the C++ enum class SelectionStyle
51
class SelectionStyle(IntEnum):
52
    NormalSelection = 0
53
    GreedySelection = 1
54

55
Gui.Selection.SelectionStyle = SelectionStyle
56

57
# Important definitions
58
class Workbench:
59
    """The workbench base class."""
60
    MenuText = ""
61
    ToolTip = ""
62
    Icon = None
63

64
    def Initialize(self):
65
        """Initializes this workbench."""
66
        App.Console.PrintWarning(str(self) + ": Workbench.Initialize() not implemented in subclass!")
67
    def ContextMenu(self, recipient):
68
        pass
69
    def appendToolbar(self,name,cmds):
70
        self.__Workbench__.appendToolbar(name, cmds)
71
    def removeToolbar(self,name):
72
        self.__Workbench__.removeToolbar(name)
73
    def listToolbars(self):
74
        return self.__Workbench__.listToolbars()
75
    def getToolbarItems(self):
76
        return self.__Workbench__.getToolbarItems()
77
    def appendCommandbar(self,name,cmds):
78
        self.__Workbench__.appendCommandbar(name, cmds)
79
    def removeCommandbar(self,name):
80
        self.__Workbench__.removeCommandbar(name)
81
    def listCommandbars(self):
82
        return self.__Workbench__.listCommandbars()
83
    def appendMenu(self,name,cmds):
84
        self.__Workbench__.appendMenu(name, cmds)
85
    def removeMenu(self,name):
86
        self.__Workbench__.removeMenu(name)
87
    def listMenus(self):
88
        return self.__Workbench__.listMenus()
89
    def appendContextMenu(self,name,cmds):
90
        self.__Workbench__.appendContextMenu(name, cmds)
91
    def removeContextMenu(self,name):
92
        self.__Workbench__.removeContextMenu(name)
93
    def reloadActive(self):
94
        self.__Workbench__.reloadActive()
95
    def name(self):
96
        return self.__Workbench__.name()
97
    def GetClassName(self):
98
        """Return the name of the associated C++ class."""
99
        # as default use this to simplify writing workbenches in Python
100
        return "Gui::PythonWorkbench"
101

102

103
class StandardWorkbench ( Workbench ):
104
    """A workbench defines the tool bars, command bars, menus,
105
context menu and dockable windows of the main window.
106
    """
107
    def Initialize(self):
108
        """Initialize this workbench."""
109
        # load the module
110
        Log ('Init: Loading FreeCAD GUI\n')
111
    def GetClassName(self):
112
        """Return the name of the associated C++ class."""
113
        return "Gui::StdWorkbench"
114

115
class NoneWorkbench ( Workbench ):
116
    """An empty workbench."""
117
    MenuText = "<none>"
118
    ToolTip = "The default empty workbench"
119
    def Initialize(self):
120
        """Initialize this workbench."""
121
        # load the module
122
        Log ('Init: Loading FreeCAD GUI\n')
123
    def GetClassName(self):
124
        """Return the name of the associated C++ class."""
125
        return "Gui::NoneWorkbench"
126

127
def InitApplications():
128
    import sys,os,traceback
129
    import io as cStringIO
130
  
131
    # Searching modules dirs +++++++++++++++++++++++++++++++++++++++++++++++++++
132
    # (additional module paths are already cached)
133
    ModDirs = FreeCAD.__ModDirs__
134
    #print ModDirs
135
    Log('Init:   Searching modules...\n')
136

137
    def RunInitGuiPy(Dir) -> bool:
138
        InstallFile = os.path.join(Dir,"InitGui.py")
139
        if os.path.exists(InstallFile):
140
            try:
141
                with open(InstallFile, 'rt', encoding='utf-8') as f:
142
                    exec(compile(f.read(), InstallFile, 'exec'))
143
            except Exception as inst:
144
                Log('Init:      Initializing ' + Dir + '... failed\n')
145
                Log('-'*100+'\n')
146
                Log(traceback.format_exc())
147
                Log('-'*100+'\n')
148
                Err('During initialization the error "' + str(inst) + '" occurred in '\
149
                    + InstallFile + '\n')
150
                Err('Please look into the log file for further information\n')
151
            else:
152
                Log('Init:      Initializing ' + Dir + '... done\n')
153
                return True
154
        else:
155
            Log('Init:      Initializing ' + Dir + '(InitGui.py not found)... ignore\n')
156
        return False
157

158
    def processMetadataFile(Dir, MetadataFile):
159
        meta = FreeCAD.Metadata(MetadataFile)
160
        if not meta.supportsCurrentFreeCAD():
161
            return None
162
        content = meta.Content
163
        if "workbench" in content:
164
            FreeCAD.Gui.addIconPath(Dir)
165
            workbenches = content["workbench"]
166
            for workbench_metadata in workbenches:
167
                if not workbench_metadata.supportsCurrentFreeCAD():
168
                    return None
169
                subdirectory = workbench_metadata.Name\
170
                    if not workbench_metadata.Subdirectory\
171
                    else workbench_metadata.Subdirectory
172
                subdirectory = subdirectory.replace("/",os.path.sep)
173
                subdirectory = os.path.join(Dir, subdirectory)
174
                ran_init = RunInitGuiPy(subdirectory)
175

176
                if ran_init:
177
                    # Try to generate a new icon from the metadata-specified information
178
                    classname = workbench_metadata.Classname
179
                    if classname:
180
                        try:
181
                            wb_handle = FreeCAD.Gui.getWorkbench(classname)
182
                        except Exception:
183
                            Log(f"Failed to get handle to {classname} -- no icon\
184
                                can be generated,\n check classname in package.xml\n")
185
                        else:
186
                            GeneratePackageIcon(dir, subdirectory, workbench_metadata,
187
                                                wb_handle)
188

189
    def tryProcessMetadataFile(Dir, MetadataFile):
190
        try:
191
            processMetadataFile(Dir, MetadataFile)
192
        except Exception as exc:
193
            Err(str(exc))
194

195
    for Dir in ModDirs:
196
        if (Dir != '') & (Dir != 'CVS') & (Dir != '__init__.py'):
197
            stopFile = os.path.join(Dir, "ADDON_DISABLED")
198
            if os.path.exists(stopFile):
199
                Msg(f'NOTICE: Addon "{Dir}" disabled by presence of ADDON_DISABLED stopfile\n')
200
                continue
201
            MetadataFile = os.path.join(Dir, "package.xml")
202
            if os.path.exists(MetadataFile):
203
                tryProcessMetadataFile(Dir, MetadataFile)
204
            else:
205
                RunInitGuiPy(Dir)
206
    Log("All modules with GUIs using InitGui.py are now initialized\n")
207

208
    try:
209
        import pkgutil
210
        import importlib
211
        import freecad
212
        freecad.gui = FreeCADGui
213
        for _, freecad_module_name,\
214
            freecad_module_ispkg in pkgutil.iter_modules(freecad.__path__, "freecad."):
215
            # Check for a stopfile
216
            stopFile = os.path.join(FreeCAD.getUserAppDataDir(), "Mod",
217
                                    freecad_module_name[8:], "ADDON_DISABLED")
218
            if os.path.exists(stopFile):
219
                continue
220

221
            # Make sure that package.xml (if present) does not exclude this version of FreeCAD
222
            MetadataFile = os.path.join(FreeCAD.getUserAppDataDir(), "Mod",
223
                                        freecad_module_name[8:], "package.xml")
224
            if os.path.exists(MetadataFile):
225
                meta = FreeCAD.Metadata(MetadataFile)
226
                if not meta.supportsCurrentFreeCAD():
227
                    continue
228

229
            if freecad_module_ispkg:
230
                Log('Init: Initializing ' + freecad_module_name + '\n')
231
                try:
232
                    freecad_module = importlib.import_module(freecad_module_name)
233
                    if any (module_name == 'init_gui' for _, module_name,
234
                            ispkg in pkgutil.iter_modules(freecad_module.__path__)):
235
                        importlib.import_module(freecad_module_name + '.init_gui')
236
                        Log('Init: Initializing ' + freecad_module_name + '... done\n')
237
                    else:
238
                        Log('Init: No init_gui module found in ' + freecad_module_name\
239
                            + ', skipping\n')
240
                except Exception as inst:
241
                    Err('During initialization the error "' + str(inst) + '" occurred in '\
242
                        + freecad_module_name + '\n')
243
                    Err('-'*80+'\n')
244
                    Err(traceback.format_exc())
245
                    Err('-'*80+'\n')
246
                    Log('Init:      Initializing ' + freecad_module_name + '... failed\n')
247
                    Log('-'*80+'\n')
248
                    Log(traceback.format_exc())
249
                    Log('-'*80+'\n')
250
    except ImportError as inst:
251
        Err('During initialization the error "' + str(inst) + '" occurred\n')
252

253
    Log("All modules with GUIs initialized using pkgutil are now initialized\n")
254

255
def GeneratePackageIcon(dir:str, subdirectory:str, workbench_metadata:FreeCAD.Metadata,
256
                        wb_handle:Workbench) -> None:
257
    relative_filename = workbench_metadata.Icon
258
    if not relative_filename:
259
        # Although a required element, this content item does not have an icon. Just bail out
260
        return
261
    absolute_filename = os.path.join(subdirectory, relative_filename)
262
    if hasattr(wb_handle, "Icon") and wb_handle.Icon:
263
        Log(f"Init:      Packaged workbench {workbench_metadata.Name} specified icon\
264
            in class {workbench_metadata.Classname}")
265
        Log(f" ... replacing with icon from package.xml data.\n")
266
    wb_handle.__dict__["Icon"] = absolute_filename
267

268

269
Log ('Init: Running FreeCADGuiInit.py start script...\n')
270

271

272

273
# init the gui
274

275
# signal that the gui is up
276
App.GuiUp = 1
277
App.Gui = FreeCADGui
278
FreeCADGui.Workbench = Workbench
279

280
Gui.addWorkbench(NoneWorkbench())
281

282
# Monkey patching pivy.coin.SoGroup.removeAllChildren to work around a bug
283
# https://bitbucket.org/Coin3D/coin/pull-requests/119/fix-sochildlist-auditing/diff
284

285
def _SoGroup_init(self,*args):
286
    import types
287
    _SoGroup_init_orig(self,*args)
288
    self.removeAllChildren = \
289
        types.MethodType(FreeCADGui.coinRemoveAllChildren,self)
290
try:
291
    from pivy import coin
292
    _SoGroup_init_orig = coin.SoGroup.__init__
293
    coin.SoGroup.__init__ = _SoGroup_init
294
except Exception:
295
    pass
296

297
# init modules
298
InitApplications()
299

300
# set standard workbench (needed as fallback)
301
Gui.activateWorkbench("NoneWorkbench")
302

303
# Register .py, .FCScript and .FCMacro
304
FreeCAD.addImportType("Inventor V2.1 (*.iv *.IV)","FreeCADGui")
305
FreeCAD.addImportType("VRML V2.0 (*.wrl *.WRL *.vrml *.VRML *.wrz *.WRZ *.wrl.gz *.WRL.GZ)","FreeCADGui")
306
FreeCAD.addImportType("Python (*.py *.FCMacro *.FCScript *.fcmacro *.fcscript)","FreeCADGui")
307
FreeCAD.addExportType("Inventor V2.1 (*.iv)","FreeCADGui")
308
FreeCAD.addExportType("VRML V2.0 (*.wrl *.vrml *.wrz *.wrl.gz)","FreeCADGui")
309
FreeCAD.addExportType("X3D Extensible 3D (*.x3d *.x3dz)","FreeCADGui")
310
FreeCAD.addExportType("WebGL/X3D (*.xhtml)","FreeCADGui")
311
#FreeCAD.addExportType("IDTF (for 3D PDF) (*.idtf)","FreeCADGui")
312
#FreeCAD.addExportType("3D View (*.svg)","FreeCADGui")
313
FreeCAD.addExportType("Portable Document Format (*.pdf)","FreeCADGui")
314

315
del InitApplications
316
del NoneWorkbench
317
del StandardWorkbench
318

319
Log ('Init: Running FreeCADGuiInit.py start script... done\n')
320

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.