GUI: Handle packaged Workbenches and their icons
This commit is contained in:
@@ -100,10 +100,7 @@ def InitApplications():
|
||||
Lib64Dir = os.path.realpath(Lib64Dir)
|
||||
if os.path.exists(Lib64Dir):
|
||||
libpaths.append(Lib64Dir)
|
||||
if sys.version_info[0] == 3:
|
||||
LibPyDir = FreeCAD.getHomePath()+'lib-py3'
|
||||
else:
|
||||
LibPyDir = FreeCAD.getHomePath()+'lib-py2'
|
||||
LibPyDir = FreeCAD.getHomePath()+'lib-py3'
|
||||
LibPyDir = os.path.realpath(LibPyDir)
|
||||
if (os.path.exists(LibPyDir)):
|
||||
libpaths.append(LibPyDir)
|
||||
@@ -168,31 +165,45 @@ def InitApplications():
|
||||
# proper python modules this can eventuelly be removed.
|
||||
sys.path = [ModDir] + libpaths + [ExtDir] + sys.path
|
||||
|
||||
def RunInitPy(Dir):
|
||||
InstallFile = os.path.join(Dir,"Init.py")
|
||||
if (os.path.exists(InstallFile)):
|
||||
try:
|
||||
with open(file=InstallFile, encoding="utf-8") as f:
|
||||
exec(f.read())
|
||||
except Exception as inst:
|
||||
Log('Init: Initializing ' + Dir + '... failed\n')
|
||||
Log('-'*100+'\n')
|
||||
Log(traceback.format_exc())
|
||||
Log('-'*100+'\n')
|
||||
Err('During initialization the error "' + str(inst) + '" occurred in ' + InstallFile + '\n')
|
||||
Err('Please look into the log file for further information\n')
|
||||
else:
|
||||
Log('Init: Initializing ' + Dir + '... done\n')
|
||||
else:
|
||||
Log('Init: Initializing ' + Dir + '(Init.py not found)... ignore\n')
|
||||
|
||||
for Dir in ModDict.values():
|
||||
if ((Dir != '') & (Dir != 'CVS') & (Dir != '__init__.py')):
|
||||
sys.path.insert(0,Dir)
|
||||
PathExtension.append(Dir)
|
||||
InstallFile = os.path.join(Dir,"Init.py")
|
||||
if (os.path.exists(InstallFile)):
|
||||
try:
|
||||
# XXX: This looks scary securitywise...
|
||||
if sys.version_info.major < 3:
|
||||
with open(InstallFile) as f:
|
||||
exec(f.read())
|
||||
else:
|
||||
with open(file=InstallFile, encoding="utf-8") as f:
|
||||
exec(f.read())
|
||||
except Exception as inst:
|
||||
Log('Init: Initializing ' + Dir + '... failed\n')
|
||||
Log('-'*100+'\n')
|
||||
Log(traceback.format_exc())
|
||||
Log('-'*100+'\n')
|
||||
Err('During initialization the error "' + str(inst) + '" occurred in ' + InstallFile + '\n')
|
||||
Err('Please look into the log file for further information\n')
|
||||
MetadataFile = os.path.join(Dir, "package.xml")
|
||||
if os.path.exists(MetadataFile):
|
||||
meta = FreeCAD.Metadata(MetadataFile)
|
||||
content = meta.Content
|
||||
if "workbench" in content:
|
||||
workbenches = content["workbench"]
|
||||
for workbench in workbenches:
|
||||
subdirectory = workbench.Name if not workbench.Subdirectory else workbench.Subdirectory
|
||||
subdirectory = os.path.join(Dir, subdirectory)
|
||||
classname = workbench.Classname
|
||||
sys.path.insert(0,subdirectory)
|
||||
PathExtension.append(subdirectory)
|
||||
RunInitPy(subdirectory)
|
||||
else:
|
||||
Log('Init: Initializing ' + Dir + '... done\n')
|
||||
continue # The package content says there are no workbenches here, so just skip
|
||||
else:
|
||||
Log('Init: Initializing ' + Dir + '(Init.py not found)... ignore\n')
|
||||
RunInitPy(Dir)
|
||||
|
||||
extension_modules = []
|
||||
|
||||
|
||||
@@ -42,6 +42,7 @@ class Workbench:
|
||||
"""The workbench base class."""
|
||||
MenuText = ""
|
||||
ToolTip = ""
|
||||
Icon = None
|
||||
|
||||
def Initialize(self):
|
||||
"""Initializes this workbench."""
|
||||
@@ -117,30 +118,56 @@ def InitApplications():
|
||||
ModDirs = FreeCAD.__ModDirs__
|
||||
#print ModDirs
|
||||
Log('Init: Searching modules...\n')
|
||||
|
||||
def RunInitGuiPy(Dir):
|
||||
InstallFile = os.path.join(Dir,"InitGui.py")
|
||||
if (os.path.exists(InstallFile)):
|
||||
try:
|
||||
with open(file=InstallFile, encoding="utf-8") as f:
|
||||
exec(f.read())
|
||||
except Exception as inst:
|
||||
Log('Init: Initializing ' + Dir + '... failed\n')
|
||||
Log('-'*100+'\n')
|
||||
Log(traceback.format_exc())
|
||||
Log('-'*100+'\n')
|
||||
Err('During initialization the error "' + str(inst) + '" occurred in ' + InstallFile + '\n')
|
||||
Err('Please look into the log file for further information\n')
|
||||
else:
|
||||
Log('Init: Initializing ' + Dir + '... done\n')
|
||||
else:
|
||||
Log('Init: Initializing ' + Dir + '(InitGui.py not found)... ignore\n')
|
||||
|
||||
for Dir in ModDirs:
|
||||
if ((Dir != '') & (Dir != 'CVS') & (Dir != '__init__.py')):
|
||||
InstallFile = os.path.join(Dir,"InitGui.py")
|
||||
if (os.path.exists(InstallFile)):
|
||||
try:
|
||||
# XXX: This looks scary securitywise...
|
||||
if sys.version_info.major < 3:
|
||||
with open(InstallFile) as f:
|
||||
exec(f.read())
|
||||
else:
|
||||
with open(file=InstallFile, encoding="utf-8") as f:
|
||||
exec(f.read())
|
||||
except Exception as inst:
|
||||
Log('Init: Initializing ' + Dir + '... failed\n')
|
||||
Log('-'*100+'\n')
|
||||
Log(traceback.format_exc())
|
||||
Log('-'*100+'\n')
|
||||
Err('During initialization the error "' + str(inst) + '" occurred in ' + InstallFile + '\n')
|
||||
Err('Please look into the log file for further information\n')
|
||||
else:
|
||||
Log('Init: Initializing ' + Dir + '... done\n')
|
||||
else:
|
||||
Log('Init: Initializing ' + Dir + '(InitGui.py not found)... ignore\n')
|
||||
MetadataFile = os.path.join(Dir, "package.xml")
|
||||
if os.path.exists(MetadataFile):
|
||||
meta = FreeCAD.Metadata(MetadataFile)
|
||||
content = meta.Content
|
||||
if "workbench" in content:
|
||||
FreeCAD.Gui.addIconPath(Dir)
|
||||
workbenches = content["workbench"]
|
||||
for workbench_metadata in workbenches:
|
||||
subdirectory = workbench_metadata.Name if not workbench_metadata.Subdirectory else workbench_metadata.Subdirectory
|
||||
subdirectory = os.path.join(Dir, subdirectory)
|
||||
RunInitGuiPy(subdirectory)
|
||||
|
||||
# Brute force this for now:
|
||||
classname = workbench_metadata.Classname
|
||||
wb_handle = FreeCAD.Gui.getWorkbench(classname)
|
||||
if wb_handle:
|
||||
GeneratePackageIcon(dir, subdirectory, workbench_metadata, wb_handle)
|
||||
else:
|
||||
Log("Failed to get handle to {classname} -- no icon can be generated, check classname in package.xml\n")
|
||||
|
||||
|
||||
|
||||
|
||||
else:
|
||||
continue # The package content says there are no workbenches here, so just skip
|
||||
else:
|
||||
RunInitGuiPy(Dir)
|
||||
|
||||
extension_modules = []
|
||||
|
||||
try:
|
||||
import pkgutil
|
||||
@@ -169,6 +196,18 @@ def InitApplications():
|
||||
except ImportError as inst:
|
||||
Err('During initialization the error "' + str(inst) + '" occurred\n')
|
||||
|
||||
def GeneratePackageIcon(dir:str, subdirectory:str, workbench_metadata:FreeCAD.Metadata, wb_handle:Workbench) -> None:
|
||||
relative_filename = workbench_metadata.Icon
|
||||
if not relative_filename:
|
||||
# Although a required element, this content item does not have an icon. Just bail out
|
||||
return
|
||||
absolute_filename = os.path.join(subdirectory, relative_filename)
|
||||
if wb_handle.Icon:
|
||||
Wrn(f"Packaged workbench {workbench_metadata.Name} specified icon in class {workbench_metadata.Classname}:\n")
|
||||
Wrn(f" ... Overwriting that specification with package.xml data")
|
||||
wb_handle.Icon = absolute_filename
|
||||
|
||||
|
||||
Log ('Init: Running FreeCADGuiInit.py start script...\n')
|
||||
|
||||
|
||||
|
||||
@@ -176,8 +176,8 @@ using namespace Gui;
|
||||
* \section moredetails More details and limitations
|
||||
* One of the key concepts of the workbench framework is to load a module at runtime when the user needs some function that it
|
||||
* provides. So, if the user doesn't need a module it never gets loaded into RAM. This speeds up the startup procedure of
|
||||
|
||||
* FreeCAD and saves memory.
|
||||
*
|
||||
* At startup FreeCAD scans all module directories and invokes InitGui.py. So an item for a workbench gets created. If the user
|
||||
* clicks on such an item the matching module gets loaded, the C++ workbench gets registered and activated.
|
||||
*
|
||||
@@ -192,7 +192,7 @@ using namespace Gui;
|
||||
* w=Workbench() # creates a standard workbench (the same as StdWorkbench in C++)
|
||||
* w.MenuText = "My Workbench" # the text that will appear in the combo box
|
||||
* dir(w) # lists all available function of the object
|
||||
* FreeCADGui.addWorkbench(w) # Creates an item for our workbenmch now
|
||||
* FreeCADGui.addWorkbench(w) # Creates an item for our workbench now
|
||||
* # Note: We must first add the workbench to run some initialization code
|
||||
* # Then we are ready to customize the workbench
|
||||
* list = ["Std_Test1", "Std_Test2", "Std_Test3"] # creates a list of new functions
|
||||
|
||||
Reference in New Issue
Block a user