def remove(self): if self.tabWidget.currentIndex() == 0: # Tab "Workbenches". idx = self.listWorkbenches.currentRow() basedir = FreeCAD.getUserAppDataDir() moddir = basedir + os.sep + "Mod" clonedir = moddir + os.sep + self.repos[idx][0] if os.path.exists(clonedir): shutil.rmtree(clonedir, onerror=self.remove_readonly) self.labelDescription.setText( translate( "AddonsInstaller", "Addon successfully removed. Please restart FreeCAD")) else: self.labelDescription.setText( translate("AddonsInstaller", "Unable to remove this addon")) elif self.tabWidget.currentIndex() == 1: # Tab "Macros". macro = self.macros[self.listMacros.currentRow()] if remove_macro(macro): self.labelDescription.setText( translate('AddonsInstaller', 'Macro successfully removed.')) else: self.labelDescription.setText( translate('AddonsInstaller', 'Macro could not be removed.')) self.update_status()
def set_change_branch_button_state(self): """The change branch button is only available for installed Addons that have a .git directory and in runs where the GitPython import is available.""" self.ui.buttonChangeBranch.hide() pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons") show_switcher = pref.GetBool("ShowBranchSwitcher", False) if not show_switcher: return # Is this repo installed? If not, return. if self.repo.status() == AddonManagerRepo.UpdateStatus.NOT_INSTALLED: return # Is it a Macro? If so, return: if self.repo.repo_type == AddonManagerRepo.RepoType.MACRO: return # Can we actually switch branches? If not, return. if not have_git: return # Is there a .git subdirectory? If not, return. basedir = FreeCAD.getUserAppDataDir() path_to_git = os.path.join(basedir, "Mod", self.repo.name, ".git") if not os.path.isdir(path_to_git): return # If all four above checks passed, then it's possible for us to switch # branches, if there are any besides the one we are on: show the button self.ui.buttonChangeBranch.show()
def branch_changed(self, name: str) -> None: QMessageBox.information( self, translate("AddonsInstaller", "Success"), translate( "AddonsInstaller", "Branch change succeeded, please restart to use the new version.", ), ) # See if this branch has a package.xml file: basedir = FreeCAD.getUserAppDataDir() path_to_metadata = os.path.join(basedir, "Mod", self.repo.name, "package.xml") if os.path.isfile(path_to_metadata): self.repo.load_metadata_file(path_to_metadata) self.repo.installed_version = self.repo.metadata.Version else: self.repo.repo_type = AddonManagerRepo.RepoType.WORKBENCH self.repo.metadata = None self.repo.installed_version = None self.repo.updated_timestamp = QDateTime.currentDateTime( ).toSecsSinceEpoch() self.repo.branch = name self.repo.set_status(AddonManagerRepo.UpdateStatus.PENDING_RESTART) installed_version_string = "<h3>" installed_version_string += translate( "AddonsInstaller", "Changed to git ref '{}' -- please restart to use Addon.").format( name) installed_version_string += "</h3>" self.ui.labelPackageDetails.setText(installed_version_string) self.ui.labelPackageDetails.setStyleSheet( "color:" + utils.attention_color_string()) self.update_status.emit(self.repo)
def __init__(self,obj,mode): self._obj = obj self._btForm = _RailGuideDialog() self.form = [self._btForm] self._btForm.setWindowIcon(QtGui.QIcon(FreeCAD.getUserAppDataDir() + "Mod/Rocket/Resources/icons/Rocket_BodyTube.svg")) self._btForm.railGuideBaseTypeCombo.currentTextChanged.connect(self.onRailGuideBaseType) self._btForm.topWidthInput.textEdited.connect(self.onTopWidth) self._btForm.middleWidthInput.textEdited.connect(self.onMiddleWidth) self._btForm.baseWidthInput.textEdited.connect(self.onBaseWidth) self._btForm.topThicknessInput.textEdited.connect(self.onTopThickness) self._btForm.baseThicknessInput.textEdited.connect(self.onBaseThickness) self._btForm.thicknessInput.textEdited.connect(self.onThickness) self._btForm.lengthInput.textEdited.connect(self.onLength) self._btForm.diameterInput.textEdited.connect(self.onDiameter) self._btForm.autoDiameterCheckbox.stateChanged.connect(self.onAutoDiameter) self._btForm.vAngleInput.textEdited.connect(self.onVAngle) self._btForm.forwardSweepGroup.toggled.connect(self.onForwardSweep) self._btForm.forwardSweepInput.textEdited.connect(self.onForwardSweepAngle) self._btForm.aftSweepGroup.toggled.connect(self.onAftSweep) self._btForm.aftSweepInput.textEdited.connect(self.onAftSweepAngle) self._btForm.notchGroup.toggled.connect(self.onNotch) self._btForm.notchWidthInput.textEdited.connect(self.onNotchWidth) self._btForm.notchDepthInput.textEdited.connect(self.onNotchDepth) self.update() if mode == 0: # fresh created self._obj.Proxy.execute(self._obj) # calculate once FreeCAD.Gui.SendMsgToActiveView("ViewFit")
def remove(self): if self.tabWidget.currentIndex() == 0: # Tab "Workbenches". idx = self.listWorkbenches.currentRow() basedir = FreeCAD.getUserAppDataDir() moddir = basedir + os.sep + "Mod" clonedir = moddir + os.sep + self.repos[idx][0] if os.path.exists(clonedir): shutil.rmtree(clonedir, onerror=self.remove_readonly) self.labelDescription.setText(translate("AddonsInstaller", "Addon successfully removed. Please restart FreeCAD")) else: self.labelDescription.setText(translate("AddonsInstaller", "Unable to remove this addon")) elif self.tabWidget.currentIndex() == 1: # Tab "Macros". macro = self.macros[self.listMacros.currentRow()] if not macro.is_installed(): # Macro not installed, nothing to do. return macro_path = os.path.join(get_macro_dir(), macro.filename) macro_path_with_macro_prefix = os.path.join(get_macro_dir(), 'Macro_' + macro.filename) if os.path.exists(macro_path): os.remove(macro_path) self.labelDescription.setText(translate("AddonsInstaller", "Macro successfully removed.")) elif os.path.exists(macro_path_with_macro_prefix): os.remove(macro_path_with_macro_prefix) self.labelDescription.setText(translate("AddonsInstaller", "Macro successfully removed.")) self.update_status()
def import_materials(self): self.materials = {} self.pathList = [] self.form.cb_materials.clear() self.fem_preferences = FreeCAD.ParamGet( "User parameter:BaseApp/Preferences/Mod/Fem") use_built_in_materials = self.fem_preferences.GetBool( "UseBuiltInMaterials", True) if use_built_in_materials: system_mat_dir = FreeCAD.getResourceDir( ) + "/Mod/Material/StandardMaterial" self.add_mat_dir(system_mat_dir, ":/icons/freecad.svg") use_mat_from_config_dir = self.fem_preferences.GetBool( "UseMaterialsFromConfigDir", True) if use_mat_from_config_dir: user_mat_dirname = FreeCAD.getUserAppDataDir() + "Materials" self.add_mat_dir(user_mat_dirname, ":/icons/preferences-general.svg") use_mat_from_custom_dir = self.fem_preferences.GetBool( "UseMaterialsFromCustomDir", True) if use_mat_from_custom_dir: custom_mat_dir = self.fem_preferences.GetString( "CustomMaterialsDir", "") self.add_mat_dir(custom_mat_dir, ":/icons/user.svg")
def enable(self): stopfile = os.path.join(FreeCAD.getUserAppDataDir(), "Mod", self.name, "ADDON_DISABLED") try: os.unlink(stopfile) except Exception: pass
def change_branch_clicked(self) -> None: """Loads the branch-switching dialog""" basedir = FreeCAD.getUserAppDataDir() path_to_repo = os.path.join(basedir, "Mod", self.repo.name) change_branch_dialog = ChangeBranchDialog(path_to_repo, self) change_branch_dialog.branch_changed.connect(self.branch_changed) change_branch_dialog.exec()
def build(self, system): # a replacement function to parse xml that doesn't depend on expat preset = os.path.join(FreeCAD.getUserAppDataDir(), "BIM", "Classification", system + ".xml") if not os.path.exists(preset): return None import codecs, re d = Item(None) with codecs.open(preset, "r", "utf-8") as f: currentItem = d for l in f: if "<Item>" in l: currentItem = Item(currentItem) currentItem.parent.children.append(currentItem) if "</Item>" in l: currentItem = currentItem.parent elif currentItem and re.findall("<ID>(.*?)</ID>", l): currentItem.ID = re.findall("<ID>(.*?)</ID>", l)[0] elif currentItem and re.findall("<Name>(.*?)</Name>", l): currentItem.Name = re.findall("<Name>(.*?)</Name>", l)[0] elif currentItem and re.findall( "<Description>(.*?)</Description>", l) and not currentItem.Name: currentItem.Name = re.findall( "<Description>(.*?)</Description>", l)[0] return [self.listize(c) for c in d.children]
def __init__(self, repos: List[Addon]): QtCore.QThread.__init__(self) self.repos = repos self.current_thread = None self.basedir = FreeCAD.getUserAppDataDir() self.moddir = os.path.join(self.basedir, "Mod")
def build_ifc(self, system): # builds from ifc instead of xml preset = os.path.join(FreeCAD.getUserAppDataDir(), "BIM", "Classification", system + ".ifc") if not os.path.exists(preset): return None import ifcopenshell f = ifcopenshell.open(preset) classes = f.by_type("IfcClassificationReference") rootclass = f.by_type("IfcClassification") if rootclass: rootclass = rootclass[0] else: return None root = Item() classdict = {rootclass.id(): root} for cl in classes: currentItem = Item() currentItem.Name = cl.Name currentItem.Description = cl.Description currentItem.ID = cl.Identification if cl.ReferencedSource: if cl.ReferencedSource.id() in classdict: currentItem.parent = classdict[cl.ReferencedSource.id()] classdict[cl.ReferencedSource.id()].children.append( currentItem) classdict[cl.id()] = currentItem return [self.listize(c) for c in root.children]
def build_xml(self, system): class Item: def __init__(self, parent=None): self.parent = parent self.ID = None self.Name = None self.children = [] preset = os.path.join(FreeCAD.getUserAppDataDir(), "BIM", "Classification", system + ".xml") if not os.path.exists(preset): return None import codecs, re d = Item() with codecs.open(preset, "r", "utf-8") as f: currentItem = d for l in f: if "<Item>" in l: currentItem = Item(currentItem) currentItem.parent.children.append(currentItem) if "</Item>" in l: currentItem = currentItem.parent elif currentItem and re.findall("<ID>(.*?)</ID>", l): currentItem.ID = re.findall("<ID>(.*?)</ID>", l)[0] elif currentItem and re.findall("<Name>(.*?)</Name>", l): currentItem.Name = re.findall("<Name>(.*?)</Name>", l)[0] elif currentItem and re.findall( "<Description>(.*?)</Description>", l) and not currentItem.Name: currentItem.Name = re.findall( "<Description>(.*?)</Description>", l)[0] return [self.listize(c) for c in d.children]
def export_material(self): import os if self.obj.Category == 'Fluid': MaterialDir = 'FluidMaterial' else: MaterialDir = 'Material' _UseMaterialsFromCustomDir = self.fem_prefs.GetBool("UseMaterialsFromCustomDir", True) _dir = self.fem_prefs.GetString("CustomMaterialsDir", "") if _UseMaterialsFromCustomDir and _dir != "" and os.path.isdir(_dir): TargetDir = self.fem_prefs.GetString("CustomMaterialsDir", "") elif self.fem_prefs.GetBool("UseMaterialsFromConfigDir", True): TargetDir = FreeCAD.getUserAppDataDir() + os.path.sep + MaterialDir # $HOME/.FreeCAD else: FreeCAD.Console.PrintMessage("Customed material saving directory is not setup in Fem preference") if not os.path.exists(TargetDir): os.mkdir(TargetDir) saveName, Filter = QFileDialog.getSaveFileName(None, "Save a Material property file", TargetDir, "*.FCMat") if not saveName == "": print(saveName) knownMaterials = [self.form.cb_materials.itemText(i) for i in range(self.form.cb_materials.count())] material_name = os.path.basename(saveName[:-len('.FCMat')]) if material_name not in knownMaterials: self.export_FCMat(saveName, self.obj.Material) FreeCAD.Console.PrintMessage("Successfully save the Material property file: " + saveName + "\n") else: self.export_FCMat(saveName, self.obj.Material) FreeCAD.Console.PrintMessage("Successfully overwritren the Material property file: " + saveName + "\n") """
def run(self): self.progressbar_show.emit(True) self.info_label.emit(translate("AddonsInstaller", "Retrieving description...")) if len(self.repos[self.idx]) == 4: desc = self.repos[self.idx][3] else: url = self.repos[self.idx][1] self.info_label.emit(translate("AddonsInstaller", "Retrieving info from") + ' ' + str(url)) u = urlopen(url) p = u.read() if sys.version_info.major >= 3 and isinstance(p, bytes): p = p.decode("utf-8") u.close() desc = re.findall("<meta property=\"og:description\" content=\"(.*?)\"",p) if desc: desc = desc[0] if self.repos[self.idx][0] in OBSOLETE: desc += " <b>This add-on is marked as obsolete</b> - This usually means it is no longer maintained, and some more advanced add-on in this list provides the same functionality." else: desc = "Unable to retrieve addon description" self.repos[self.idx].append(desc) self.addon_repos.emit(self.repos) if self.repos[self.idx][2] == 1: upd = False # checking for updates if not NOGIT: try: import git except: pass else: repo = self.repos[self.idx] clonedir = FreeCAD.getUserAppDataDir() + os.sep + "Mod" + os.sep + repo[0] if os.path.exists(clonedir): if not os.path.exists(clonedir + os.sep + '.git'): # Repair addon installed with raw download bare_repo = git.Repo.clone_from(repo[1], clonedir + os.sep + '.git', bare=True) try: with bare_repo.config_writer() as cw: cw.set('core', 'bare', False) except AttributeError: FreeCAD.Console.PrintWarning(translate("AddonsInstaller", "Outdated GitPython detected, consider upgrading with pip.")+"\n") cw = bare_repo.config_writer() cw.set('core', 'bare', False) del cw repo = git.Repo(clonedir) repo.head.reset('--hard') gitrepo = git.Git(clonedir) gitrepo.fetch() if "git pull" in gitrepo.status(): upd = True if upd: message = "<strong>" + translate("AddonsInstaller", "An update is available for this addon.") + "</strong><br>" + desc + ' - <a href="' + self.repos[self.idx][1] + '"><span style="word-wrap: break-word;width:15em;text-decoration: underline; color:#0000ff;">' + self.repos[self.idx][1] + '</span></a>' else: message = "<strong>" + translate("AddonsInstaller", "This addon is already installed.") + "</strong><br>" + desc + ' - <a href="' + self.repos[self.idx][1] + '"><span style="word-wrap: break-word;width:15em;text-decoration: underline; color:#0000ff;">' + self.repos[self.idx][1] + '</span></a>' else: message = desc + ' - <a href="' + self.repos[self.idx][1] + '"><span style="word-wrap: break-word;width:15em;text-decoration: underline; color:#0000ff;">' + self.repos[self.idx][1] + '</span></a>' self.info_label.emit( message ) self.progressbar_show.emit(False) self.stop = True
def from_cache(self, cache_dict: Dict): """Load basic data from cached dict data. Does not include Macro or Metadata information, which must be populated separately.""" mod_dir = os.path.join(FreeCAD.getUserAppDataDir(), "Mod", cache_dict["name"]) if os.path.isdir(mod_dir): status = AddonManagerRepo.UpdateStatus.UNCHECKED else: status = AddonManagerRepo.UpdateStatus.NOT_INSTALLED instance = AddonManagerRepo(cache_dict["name"], cache_dict["url"], status, cache_dict["branch"]) for key, value in cache_dict.items(): instance.__dict__[key] = value instance.repo_type = AddonManagerRepo.RepoType(cache_dict["repo_type"]) if instance.repo_type == AddonManagerRepo.RepoType.PACKAGE: # There must be a cached metadata file, too cached_package_xml_file = os.path.join( FreeCAD.getUserCachePath(), "AddonManager", "PackageMetadata", instance.name, ) if os.path.isfile(cached_package_xml_file): instance.load_metadata_file(cached_package_xml_file) if "requires" in cache_dict: instance.requires = set(cache_dict["requires"]) instance.blocks = set(cache_dict["blocks"]) instance.python_requires = set(cache_dict["python_requires"]) instance.python_optional = set(cache_dict["python_optional"]) return instance
def initDB(self): self._connection = sqlite3.connect( "file:" + FreeCAD.getUserAppDataDir() + "Mod/Rocket/Resources/parts/Parts.db?mode=ro", uri=True) self._connection.row_factory = sqlite3.Row self._updateModel()
def __init__(self, vobj): print("init RibTaskPanel") self.obj = vobj path_to_ui = FreeCAD.getUserAppDataDir( ) + 'Mod/AirPlaneDesign/resources/airPlaneDesignEdit.ui' self.form = FreeCADGui.PySideUic.loadUi(path_to_ui) self.update(vobj)
def getWorkbenchFolder(): return (Design456Init.PYRAMID_PATH) import os.path from os import path import workbenchfolders basedir = str(App.getUserAppDataDir()) folder = "" for tryfolder in workbenchfolders.recommended_folders: if path.exists(basedir + tryfolder): folder = basedir + tryfolder return folder for tryfolder in workbenchfolders.user_chosen_folders: if path.exists(basedir + tryfolder): folder = basedir + tryfolder return folder if path.exists(tryfolder): folder = tryfolder return folder return ""
def run(self): "populates the list of addons" self.progressbar_show.emit(True) u = urlopen("https://github.com/FreeCAD/FreeCAD-addons") p = u.read() if sys.version_info.major >= 3 and isinstance(p, bytes): p = p.decode("utf-8") u.close() p = p.replace("\n"," ") p = re.findall("octicon-file-submodule(.*?)message",p) basedir = FreeCAD.getUserAppDataDir() moddir = basedir + os.sep + "Mod" repos = [] for l in p: #name = re.findall("data-skip-pjax=\"true\">(.*?)<",l)[0] name = re.findall("title=\"(.*?) @",l)[0] self.info_label.emit(name) #url = re.findall("title=\"(.*?) @",l)[0] url = "https://github.com/" + re.findall("href=\"\/(.*?)\/tree",l)[0] addondir = moddir + os.sep + name #print ("found:",name," at ",url) if not os.path.exists(addondir): state = 0 else: state = 1 repos.append([name,url,state]) if not repos: self.info_label.emit(translate("AddonsInstaller", "Unable to download addon list.")) else: repos = sorted(repos, key=lambda s: s[0].lower()) for repo in repos: self.addon_repo.emit(repo) self.info_label.emit(translate("AddonsInstaller", "Workbenches list was updated.")) self.progressbar_show.emit(False) self.stop = True
def export_material(self): import os if self.obj.Category == 'Fluid': MaterialDir = 'FluidMaterial' else: MaterialDir = 'Material' _UseMaterialsFromCustomDir = self.fem_prefs.GetBool("UseMaterialsFromCustomDir", True) _dir = self.fem_prefs.GetString("CustomMaterialsDir", "") if _UseMaterialsFromCustomDir and _dir != "" and os.path.isdir(_dir): TargetDir = self.fem_prefs.GetString("CustomMaterialsDir", "") elif self.fem_prefs.GetBool("UseMaterialsFromConfigDir", True): TargetDir = FreeCAD.getUserAppDataDir() + os.path.sep + MaterialDir # $HOME/.FreeCAD else: FreeCAD.Console.PrintMessage("Customed material saving directory is not setup in Fem preference") if not os.path.exists(TargetDir): os.mkdir(TargetDir) saveName, Filter = QFileDialog.getSaveFileName(None, "Save a Material property file", TargetDir, "*.FCMat") if not saveName == "": print(saveName) knownMaterials = [self.parameterWidget.cb_materials.itemText(i) for i in range(self.parameterWidget.cb_materials.count())] material_name = os.path.basename(saveName[:-len('.FCMat')]) if material_name not in knownMaterials: self.export_FCMat(saveName, self.material) FreeCAD.Console.PrintMessage("Successfully save the Material property file: " + saveName + "\n") else: self.export_FCMat(saveName, self.obj.Material) FreeCAD.Console.PrintMessage("Successfully overwritten the Material property file: " + saveName + "\n") """
def __init__(self, vobj): self.obj = vobj path_to_ui = FreeCAD.getUserAppDataDir( ) + 'Mod/AirPlaneDesign/resources/ribTaskPanel.ui' self.form = FreeCADGui.PySideUic.loadUi(path_to_ui) self.update(vobj) self.form.xfoilSimulation.clicked.connect(self.xfoilSimulation)
def __init__(self, lookup, parent=None): super().__init__(parent) self._database = PartDatabase(FreeCAD.getUserAppDataDir() + "Mod/Rocket/") # define our window self.setGeometry(250, 250, 400, 350) self.setWindowTitle(translate('Rocket', "Rocket Component Parameter")) self.manufacturerLabel = QtGui.QLabel( translate('Rocket', "Manufacturer"), self) self.manufacturerInput = QtGui.QLineEdit(self) self.manufacturerInput.setFixedWidth(80) self.partNumberLabel = QtGui.QLabel(translate('Rocket', "Part Number"), self) self.partNumberInput = QtGui.QLineEdit(self) self.partNumberInput.setFixedWidth(80) self.descriptionLabel = QtGui.QLabel( translate('Rocket', "Description"), self) self.descriptionInput = QtGui.QLineEdit(self) self.descriptionInput.setFixedWidth(80) self.materialLabel = QtGui.QLabel(translate('Rocket', "Material"), self) self.materialInput = QtGui.QLineEdit(self) self.materialInput.setFixedWidth(80) self.lookupButton = QtGui.QPushButton(translate('Rocket', "Lookup..."), self) layout = QGridLayout() n = 0 layout.addWidget(self.manufacturerLabel, n, 0, 1, 2) layout.addWidget(self.manufacturerInput, n, 1) n += 1 layout.addWidget(self.partNumberLabel, n, 0) layout.addWidget(self.partNumberInput, n, 1) n += 1 layout.addWidget(self.descriptionLabel, n, 0) layout.addWidget(self.descriptionInput, n, 1) n += 1 layout.addWidget(self.materialLabel, n, 0) layout.addWidget(self.materialInput, n, 1) n += 1 layout.addWidget(self.lookupButton, n, 1) n += 1 self.setLayout(layout)
def build(self, system): # try to load the IFC first preset = os.path.join(FreeCAD.getUserAppDataDir(), "BIM", "Classification", system + ".ifc") if os.path.exists(preset): return self.build_ifc(system) else: preset = os.path.join(FreeCAD.getUserAppDataDir(), "BIM", "Classification", system + ".xml") if os.path.exists(preset): return self.build_xml(system) else: FreeCAD.Console.PrintError( "Unable to find classification file:" + system + "\n") return []
def disable(self): stopfile = os.path.join(FreeCAD.getUserAppDataDir(), "Mod", self.name, "ADDON_DISABLED") with open(stopfile, "w") as f: f.write( "The existence of this file prevents FreeCAD from loading this Addon. To re-enable, delete the file." )
def Activated(self): # setting up a min reload interval of one hour libok = False self.librarypath = FreeCAD.ParamGet( 'User parameter:Plugins/parts_library').GetString( 'destination', '') if self.librarypath: if os.path.exists(self.librarypath): libok = True else: # check if the library is at the standard addon location addondir = os.path.join(FreeCAD.getUserAppDataDir(), "Mod", "parts_library") if os.path.exists(addondir): FreeCAD.ParamGet( 'User parameter:Plugins/parts_library').SetString( 'destination', addondir) libok = True if libok: FreeCADGui.Control.showDialog(BIM_Library_TaskPanel()) else: FreeCAD.Console.PrintError( translate("BIM", "The Parts Library could not be found.") + "\n")
def update(self): if (QMessageBox.question(None, "update", "update to latest version?!", QMessageBox.Yes | QMessageBox.No, QMessageBox.Yes) == QMessageBox.No): return if not internet(): msg = "You are not connected to the Internet, please check your internet connection." QMessageBox.warning(None, 'update', str(msg)) return civil_path = os.path.abspath( os.path.join(os.path.dirname(__file__), os.path.pardir, os.path.pardir)) user_data_dir = App.getUserAppDataDir() if not user_data_dir in civil_path: mod_path = os.path.join(App.getUserAppDataDir(), 'Mod') if not os.path.exists(mod_path): os.mkdir(mod_path) civil_path = os.path.join(mod_path, 'Civil') import git g = git.cmd.Git(civil_path) msg = '' try: msg = g.pull(env={'GIT_SSL_NO_VERIFY': '1'}) except: QMessageBox.information( None, "update", "update takes some minutes, please be patient.") import shutil import tempfile default_tmp_dir = tempfile._get_default_tempdir() name = next(tempfile._get_candidate_names()) punch_temp_dir = os.path.join(default_tmp_dir, 'Civil' + name) os.mkdir(punch_temp_dir) os.chdir(punch_temp_dir) git.Git('.').clone("https://github.com/ebrahimraeyat/Civil.git", env={'GIT_SSL_NO_VERIFY': '1'}) src_folder = os.path.join(punch_temp_dir, 'Civil') shutil.copytree(src_folder, civil_path) msg = 'update done successfully, please remove Civil folder from FreeCAD installation folder!, then restart FreeCAD.' else: if not msg: msg = 'error occurred during update\nplease contact with @roknabadi' # msg += '\n please restart the program.' QMessageBox.information(None, 'update', msg)
def resolveFileName(self, job): path = PathPreferences.defaultOutputFile() if job.PostProcessorOutputFile: path = job.PostProcessorOutputFile filename = path if '%D' in filename: D = FreeCAD.ActiveDocument.FileName if D: D = os.path.dirname(D) # in case the document is in the current working directory if not D: D = '.' else: FreeCAD.Console.PrintError("Please save document in order to resolve output path!\n") return None filename = filename.replace('%D', D) if '%d' in filename: d = FreeCAD.ActiveDocument.Label filename = filename.replace('%d', d) if '%j' in filename: j = job.Label filename = filename.replace('%j', j) if '%M' in filename: pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro") M = pref.GetString("MacroPath", FreeCAD.getUserAppDataDir()) filename = filename.replace('%M', M) policy = PathPreferences.defaultOutputPolicy() openDialog = policy == 'Open File Dialog' if os.path.isdir(filename) or not os.path.isdir(os.path.dirname(filename)): # Either the entire filename resolves into a directory or the parent directory doesn't exist. # Either way I don't know what to do - ask for help openDialog = True if os.path.isfile(filename) and not openDialog: if policy == 'Open File Dialog on conflict': openDialog = True elif policy == 'Append Unique ID on conflict': fn, ext = os.path.splitext(filename) nr = fn[-3:] n = 1 if nr.isdigit(): n = int(nr) while os.path.isfile("%s%03d%s" % (fn, n, ext)): n = n + 1 filename = "%s%03d%s" % (fn, n, ext) if openDialog: foo = QtGui.QFileDialog.getSaveFileName(QtGui.QApplication.activeWindow(), "Output File", filename) if foo: filename = foo[0] else: filename = None return filename
def run(self): "populates the list of addons" self.progressbar_show.emit(True) u = utils.urlopen("https://github.com/FreeCAD/FreeCAD-addons") if not u: self.progressbar_show.emit(False) self.done.emit() self.stop = True return p = u.read() if sys.version_info.major >= 3 and isinstance(p, bytes): p = p.decode("utf-8") u.close() p = p.replace("\n"," ") p = re.findall("octicon-file-submodule(.*?)message",p) basedir = FreeCAD.getUserAppDataDir() moddir = basedir + os.sep + "Mod" repos = [] # querying official addons for l in p: #name = re.findall("data-skip-pjax=\"true\">(.*?)<",l)[0] name = re.findall("title=\"(.*?) @",l)[0] self.info_label.emit(name) #url = re.findall("title=\"(.*?) @",l)[0] url = utils.getRepoUrl(l) if url: addondir = moddir + os.sep + name #print ("found:",name," at ",url) if os.path.exists(addondir) and os.listdir(addondir): # make sure the folder exists and it contains files! state = 1 else: state = 0 repos.append([name,url,state]) # querying custom addons customaddons = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Addons").GetString("CustomRepositories","").split("\n") for url in customaddons: if url: name = url.split("/")[-1] if name.lower().endswith(".git"): name = name[:-4] addondir = moddir + os.sep + name if not os.path.exists(addondir): state = 0 else: state = 1 repos.append([name,url,state]) if not repos: self.info_label.emit(translate("AddonsInstaller", "Unable to download addon list.")) else: repos = sorted(repos, key=lambda s: s[0].lower()) for repo in repos: self.addon_repo.emit(repo) self.info_label.emit(translate("AddonsInstaller", "Workbenches list was updated.")) self.progressbar_show.emit(False) self.done.emit() self.stop = True
def loadImages(self, message, url, wbName): "checks if the given page contains images and downloads them" # QTextBrowser cannot display online images. So we download them # here, and replace the image link in the html code with the # downloaded version imagepaths = re.findall("<img.*?src=\"(.*?)\"", message) if imagepaths: storedimages = [] store = os.path.join(FreeCAD.getUserAppDataDir(), "AddonManager", "Images") if not os.path.exists(store): os.makedirs(store) for path in imagepaths: origpath = path if "?" in path: # remove everything after the ? path = path.split("?")[0] if not path.startswith("http"): path = utils.getserver(url) + path name = path.split("/")[-1] if name and path.startswith("http"): storename = os.path.join(store, name) if len(storename) >= 260: remainChars = 259 - (len(store) + len(wbName) + 1) storename = os.path.join(store, wbName + name[-remainChars:]) if not os.path.exists(storename): try: u = utils.urlopen(path) imagedata = u.read() u.close() except: print( "AddonManager: Debug: Error retrieving image from", path) else: f = open(storename, "wb") f.write(imagedata) f.close() # resize the image to 300x300px if needed from PySide import QtCore, QtGui img = QtGui.QImage(storename) if (img.width() > 300) or (img.height() > 300): pix = QtGui.QPixmap() pix = pix.fromImage( img.scaled(300, 300, QtCore.Qt.KeepAspectRatio, QtCore.Qt.FastTransformation)) pix.save(storename, "jpeg", 100) message = message.replace( "src=\"" + origpath, "src=\"file:///" + storename.replace("\\", "/")) #print(message) return message return None
def resolveFileName(self, job): path = PathPreferences.defaultOutputFile() if job.OutputFile: path = job.OutputFile filename = path if '%D' in filename: D = FreeCAD.ActiveDocument.FileName if D: D = os.path.dirname(D) else: FreeCAD.Console.PrintError( "Please save document in order to resolve output path!\n") return None filename = filename.replace('%D', D) if '%d' in filename: d = FreeCAD.ActiveDocument.Label filename = filename.replace('%d', d) if '%j' in filename: j = job.Label filename = filename.replace('%j', j) if '%M' in filename: pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro") M = pref.GetString("MacroPath", FreeCAD.getUserAppDataDir()) filename = filename.replace('%M', M) policy = PathPreferences.defaultOutputPolicy() openDialog = policy == 'Open File Dialog' if os.path.isdir(filename) or not os.path.isdir( os.path.dirname(filename)): # Either the entire filename resolves into a directory or the parent directory doesn't exist. # Either way I don't know what to do - ask for help openDialog = True if os.path.isfile(filename) and not openDialog: if policy == 'Open File Dialog on conflict': openDialog = True elif policy == 'Append Unique ID on conflict': fn, ext = os.path.splitext(filename) nr = fn[-3:] n = 1 if nr.isdigit(): n = int(nr) while os.path.isfile("%s%03d%s" % (fn, n, ext)): n = n + 1 filename = "%s%03d%s" % (fn, n, ext) if openDialog: foo = QtGui.QFileDialog.getSaveFileName(QtGui.qApp.activeWindow(), "Output File", filename) if foo: filename = foo[0] else: filename = None return filename
def GetResources(self): iconpath = FreeCAD.getUserAppDataDir().encode("utf-8") + 'Mod/ehtecoptics/resources/absorber.svg.png' # iconpath ='/home/pi/.FreeCAD/Mod/ehtecoptics/resources/ehtec.svg' # print iconpath return {'Pixmap': iconpath, # the name of a svg file available in the resources 'Accel': "Shift+A", # a default shortcut (optional) 'MenuText': "Convert To Absorber", 'ToolTip': "Converts a solid to an absorber"}
def update_metadata(self): """Loads the package metadata from the Addon's downloaded package.xml file.""" basedir = FreeCAD.getUserAppDataDir() package_xml = os.path.join(basedir, "Mod", self.repo.name, "package.xml") if os.path.isfile(package_xml): self.repo.load_metadata_file(package_xml) self.repo.installed_version = self.repo.metadata.Version self.repo.updated_timestamp = os.path.getmtime(package_xml)
def resolveFileName(self, job): # print("resolveFileName(%s)" % job.Label) path = PathPreferences.defaultOutputFile() if job.OutputFile: path = job.OutputFile filename = path if "%D" in filename: D = FreeCAD.ActiveDocument.FileName if D: D = os.path.dirname(D) else: FreeCAD.Console.PrintError("Please save document in order to resolve output path!\n") return None filename = filename.replace("%D", D) if "%d" in filename: d = FreeCAD.ActiveDocument.Label filename = filename.replace("%d", d) if "%j" in filename: j = job.Label filename = filename.replace("%j", j) if "%M" in filename: pref = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro") M = pref.GetString("MacroPath", FreeCAD.getUserAppDataDir()) filename = filename.replace("%M", M) policy = PathPreferences.defaultOutputPolicy() openDialog = policy == "Open File Dialog" if os.path.isdir(filename) or not os.path.isdir(os.path.dirname(filename)): # Either the entire filename resolves into a directory or the parent directory doesn't exist. # Either way I don't know what to do - ask for help openDialog = True if os.path.isfile(filename) and not openDialog: if policy == "Open File Dialog on conflict": openDialog = True elif policy == "Append Unique ID on conflict": fn, ext = os.path.splitext(filename) nr = fn[-3:] n = 1 if nr.isdigit(): n = int(nr) while os.path.isfile("%s%03d%s" % (fn, n, ext)): n = n + 1 filename = "%s%03d%s" % (fn, n, ext) if openDialog: foo = QtGui.QFileDialog.getSaveFileName(QtGui.qApp.activeWindow(), "Output File", filename) if foo: filename = foo[0] else: filename = None # print("resolveFileName(%s, %s) -> '%s'" % (path, policy, filename)) return filename
def allAvailablePostProcessors(cls): path = FreeCAD.getHomePath() + ("Mod/Path/PathScripts/") posts = glob.glob(path + '/*_post.py') allposts = [ str(os.path.split(os.path.splitext(p)[0])[1][:-5]) for p in posts] grp = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro") path = grp.GetString("MacroPath", FreeCAD.getUserAppDataDir()) posts = glob.glob(path + '/*_post.py') allposts.extend([ str(os.path.split(os.path.splitext(p)[0])[1][:-5]) for p in posts]) allposts.sort() return allposts
def update_status(self,soft=False): """Updates the list of workbenches/macros. If soft is true, items are not recreated (and therefore display text isn't triggered)" """ moddir = FreeCAD.getUserAppDataDir() + os.sep + "Mod" if soft: for i in range(self.listWorkbenches.count()): txt = self.listWorkbenches.item(i).text().strip() ext = "" if txt.endswith(" (Installed)"): txt = txt[:-12] ext = " (Installed)" elif txt.endswith(" (Update available)"): txt = txt[:-19] ext = " (Update available)" elif txt.endswith(" (Restart required)"): txt = txt[:-19] ext = " (Restart required)" if os.path.exists(os.path.join(moddir,txt)): self.listWorkbenches.item(i).setText(txt+ext) else: self.listWorkbenches.item(i).setText(" "+txt) self.listWorkbenches.item(i).setIcon(QtGui.QIcon()) for i in range(self.listMacros.count()): txt = self.listMacros.item(i).text().strip() if txt.endswith(" (Installed)"): txt = txt[:-12] elif txt.endswith(" (Update available)"): txt = txt[:-19] if os.path.exists(os.path.join(moddir,txt)): self.listMacros.item(i).setText(txt+ext) else: self.listMacros.item(i).setText(" "+txt) self.listMacros.item(i).setIcon(QtGui.QIcon()) else: self.listWorkbenches.clear() self.listMacros.clear() for wb in self.repos: if os.path.exists(os.path.join(moddir,wb[0])): self.listWorkbenches.addItem(QtGui.QListWidgetItem(QtGui.QIcon(":/icons/button_valid.svg"),str(wb[0]) + str(" (Installed)"))) wb[2] = 1 else: self.listWorkbenches.addItem(" "+str(wb[0])) wb[2] = 0 for macro in self.macros: if macro.is_installed(): self.listMacros.addItem(QtGui.QListWidgetItem(QtGui.QIcon(":/icons/button_valid.svg"), macro.name + str(' (Installed)'))) else: self.listMacros.addItem(" "+macro.name)
def import_fluid_materials(self): # use_built_in_materials = self.fem_prefs.GetBool("UseBuiltInMaterials", True) # if use_built_in_materials: system_mat_dir = FreeCAD.getResourceDir() + "/Mod/Material/FluidMaterial" self.add_cards_from_a_dir(system_mat_dir, ":/icons/freecad.svg") use_mat_from_config_dir = self.fem_prefs.GetBool("UseMaterialsFromConfigDir", True) if use_mat_from_config_dir: user_mat_dirname = FreeCAD.getUserAppDataDir() + "FluidMaterial" self.add_cards_from_a_dir(user_mat_dirname, ":/icons/preferences-general.svg") use_mat_from_custom_dir = self.fem_prefs.GetBool("UseMaterialsFromCustomDir", True) if use_mat_from_custom_dir: custom_mat_dir = self.fem_prefs.GetString("CustomMaterialsDir", "") self.add_cards_from_a_dir(custom_mat_dir, ":/icons/user.svg")
def update_status(self): self.listWorkbenches.clear() self.listMacros.clear() moddir = FreeCAD.getUserAppDataDir() + os.sep + "Mod" for wb in self.repos: if os.path.exists(os.path.join(moddir,wb[0])): self.listWorkbenches.addItem(QtGui.QListWidgetItem(QtGui.QIcon.fromTheme("dialog-ok"),str(wb[0]) + str(" (Installed)"))) wb[2] = 1 else: self.listWorkbenches.addItem(" "+str(wb[0])) wb[2] = 0 for macro in self.macros: if macro.is_installed(): self.listMacros.addItem(QtGui.QListWidgetItem(QtGui.QIcon.fromTheme('dialog-ok'), macro.name + str(' (Installed)'))) else: self.listMacros.addItem(macro.name)
def run(self): if NOGIT: self.stop = True return try: import git except: self.stop = True return self.progressbar_show.emit(True) basedir = FreeCAD.getUserAppDataDir() moddir = basedir + os.sep + "Mod" self.info_label.emit(translate("AddonsInstaller", "Checking for new versions...")) upds = [] gitpython_warning = False for repo in self.repos: if repo[2] == 1: #installed self.info_label.emit(translate("AddonsInstaller","Checking repo")+" "+repo[0]+"...") clonedir = moddir + os.sep + repo[0] if os.path.exists(clonedir): if not os.path.exists(clonedir + os.sep + '.git'): # Repair addon installed with raw download bare_repo = git.Repo.clone_from(repo[1], clonedir + os.sep + '.git', bare=True) try: with bare_repo.config_writer() as cw: cw.set('core', 'bare', False) except AttributeError: if not gitpython_warning: FreeCAD.Console.PrintWarning(translate("AddonsInstaller", "Outdated GitPython detected, consider upgrading with pip.")+"\n") gitpython_warning = True cw = bare_repo.config_writer() cw.set('core', 'bare', False) del cw repo = git.Repo(clonedir) repo.head.reset('--hard') gitrepo = git.Git(clonedir) gitrepo.fetch() if "git pull" in gitrepo.status(): self.mark.emit(repo[0]) upds.append(repo[0]) self.progressbar_show.emit(False) if upds: self.info_label.emit(str(len(upds))+" "+translate("AddonsInstaller", "update(s) available")+": "+",".join(upds)+". "+translate("AddonsInstaller","Press the update button again to update them all at once.")) self.change_button.emit() else: self.info_label.emit(translate("AddonsInstaller","Everything is up to date")) self.stop = True
def import_materials(self): self.materials = {} self.pathList = [] self.form.cb_materials.clear() self.fem_preferences = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem") use_built_in_materials = self.fem_preferences.GetBool("UseBuiltInMaterials", True) if use_built_in_materials: system_mat_dir = FreeCAD.getResourceDir() + "/Mod/Material/StandardMaterial" self.add_mat_dir(system_mat_dir, ":/icons/freecad.svg") use_mat_from_config_dir = self.fem_preferences.GetBool("UseMaterialsFromConfigDir", True) if use_mat_from_config_dir: user_mat_dirname = FreeCAD.getUserAppDataDir() + "Materials" self.add_mat_dir(user_mat_dirname, ":/icons/preferences-general.svg") use_mat_from_custom_dir = self.fem_preferences.GetBool("UseMaterialsFromCustomDir", True) if use_mat_from_custom_dir: custom_mat_dir = self.fem_preferences.GetString("CustomMaterialsDir", "") self.add_mat_dir(custom_mat_dir, ":/icons/user.svg")
def remove(self): if self.tabWidget.currentIndex() == 0: # Tab "Workbenches". idx = self.listWorkbenches.currentRow() basedir = FreeCAD.getUserAppDataDir() moddir = basedir + os.sep + "Mod" clonedir = moddir + os.sep + self.repos[idx][0] if os.path.exists(clonedir): shutil.rmtree(clonedir, onerror=self.remove_readonly) self.labelDescription.setText(translate("AddonsInstaller", "Addon successfully removed. Please restart FreeCAD")) else: self.labelDescription.setText(translate("AddonsInstaller", "Unable to remove this addon")) elif self.tabWidget.currentIndex() == 1: # Tab "Macros". macro = self.macros[self.listMacros.currentRow()] if remove_macro(macro): self.labelDescription.setText(translate('AddonsInstaller', 'Macro successfully removed.')) else: self.labelDescription.setText(translate('AddonsInstaller', 'Macro could not be removed.')) self.update_status()
def __init__(self): self.form = FreeCADGui.PySideUic.loadUi(":/panels/JobEdit.ui") #self.form = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Path/JobEdit.ui") path = FreeCAD.getHomePath() + ("Mod/Path/PathScripts/") posts = glob.glob(path + '/*_post.py') allposts = [ str(os.path.split(os.path.splitext(p)[0])[1][:-5]) for p in posts] grp = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro") path = grp.GetString("MacroPath", FreeCAD.getUserAppDataDir()) posts = glob.glob(path + '/*_post.py') allposts.extend([ str(os.path.split(os.path.splitext(p)[0])[1][:-5]) for p in posts]) for post in allposts: self.form.cboPostProcessor.addItem(post) self.updating = False self.form.cboBaseObject.addItem("") for o in FreeCAD.ActiveDocument.Objects: if hasattr(o, "Shape"): self.form.cboBaseObject.addItem(o.Name)
def __init__(self, obj): path = FreeCAD.getHomePath() + ("Mod/Path/PathScripts/") posts = glob.glob(path + '/*_post.py') allposts = [ str(os.path.split(os.path.splitext(p)[0])[1][:-5]) for p in posts] grp = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro") path = grp.GetString("MacroPath", FreeCAD.getUserAppDataDir()) posts = glob.glob(path + '/*_post.py') allposts.extend([ str(os.path.split(os.path.splitext(p)[0])[1][:-5]) for p in posts]) # obj.addProperty("App::PropertyFile", "PostProcessor", "CodeOutput", "Select the Post Processor file for this project") obj.addProperty("App::PropertyFile", "OutputFile", "CodeOutput", QtCore.QT_TRANSLATE_NOOP("App::Property","The NC output file for this project")) obj.setEditorMode("OutputFile", 0) # set to default mode obj.addProperty("App::PropertyString", "Description", "Path", QtCore.QT_TRANSLATE_NOOP("App::Property","An optional description for this job")) obj.addProperty("App::PropertyEnumeration", "PostProcessor", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property","Select the Post Processor")) obj.PostProcessor = allposts obj.addProperty("App::PropertyString", "MachineName", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property","Name of the Machine that will use the CNC program")) obj.addProperty("Path::PropertyTooltable", "Tooltable", "Base", QtCore.QT_TRANSLATE_NOOP("App::Property","The tooltable used for this CNC program")) obj.addProperty("App::PropertyEnumeration", "MachineUnits", "Output", QtCore.QT_TRANSLATE_NOOP("App::Property","Units that the machine works in, ie Metric or Inch")) obj.MachineUnits = ['Metric', 'Inch'] obj.addProperty("App::PropertyDistance", "X_Max", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Maximum distance in X the machine can travel")) obj.addProperty("App::PropertyDistance", "Y_Max", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Maximum distance in X the machine can travel")) obj.addProperty("App::PropertyDistance", "Z_Max", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Maximum distance in X the machine can travel")) obj.addProperty("App::PropertyDistance", "X_Min", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Minimum distance in X the machine can travel")) obj.addProperty("App::PropertyDistance", "Y_Min", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Minimum distance in X the machine can travel")) obj.addProperty("App::PropertyDistance", "Z_Min", "Limits", QtCore.QT_TRANSLATE_NOOP("App::Property","The Minimum distance in X the machine can travel")) obj.addProperty("App::PropertyLink", "Base", "Base", "The base object for all operations") obj.Proxy = self if FreeCAD.GuiUp: ViewProviderJob(obj.ViewObject)
def macroFilePath(cls): grp = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro") return grp.GetString("MacroPath", FreeCAD.getUserAppDataDir())
def run(self): "installs or updates the selected addon" git = None try: import git except Exception as e: self.info_label.emit("GitPython not found.") print(e) FreeCAD.Console.PrintWarning(translate("AddonsInstaller","GitPython not found. Using standard download instead.")+"\n") try: import zipfile except: self.info_label.emit("no zip support.") FreeCAD.Console.PrintError(translate("AddonsInstaller","Your version of python doesn't appear to support ZIP files. Unable to proceed.")+"\n") return try: import StringIO as io except ImportError: # StringIO is not available with python3 import io if not isinstance(self.idx,list): self.idx = [self.idx] for idx in self.idx: if idx < 0: return if not self.repos: return if NOGIT: git = None basedir = FreeCAD.getUserAppDataDir() moddir = basedir + os.sep + "Mod" if not os.path.exists(moddir): os.makedirs(moddir) clonedir = moddir + os.sep + self.repos[idx][0] self.progressbar_show.emit(True) if os.path.exists(clonedir): self.info_label.emit("Updating module...") if git: if not os.path.exists(clonedir + os.sep + '.git'): # Repair addon installed with raw download bare_repo = git.Repo.clone_from(self.repos[idx][1], clonedir + os.sep + '.git', bare=True) try: with bare_repo.config_writer() as cw: cw.set('core', 'bare', False) except AttributeError: FreeCAD.Console.PrintWarning(translate("AddonsInstaller", "Outdated GitPython detected, consider upgrading with pip.")+"\n") cw = bare_repo.config_writer() cw.set('core', 'bare', False) del cw repo = git.Repo(clonedir) repo.head.reset('--hard') repo = git.Git(clonedir) answer = repo.pull() # Update the submodules for this repository repo_sms = git.Repo(clonedir) for submodule in repo_sms.submodules: submodule.update(init=True, recursive=True) else: answer = self.download(self.repos[idx][1],clonedir) else: self.info_label.emit("Checking module dependencies...") depsok,answer = self.checkDependencies(self.repos[idx][1]) if depsok: if git: self.info_label.emit("Cloning module...") repo = git.Repo.clone_from(self.repos[idx][1], clonedir, branch='master') # Make sure to clone all the submodules as well if repo.submodules: repo.submodule_update(recursive=True) else: self.info_label.emit("Downloading module...") self.download(self.repos[idx][1],clonedir) answer = translate("AddonsInstaller", "Workbench successfully installed. Please restart FreeCAD to apply the changes.") # symlink any macro contained in the module to the macros folder macro_dir = FreeCAD.getUserMacroDir(True) if not os.path.exists(macro_dir): os.makedirs(macro_dir) for f in os.listdir(clonedir): if f.lower().endswith(".fcmacro"): print("copying macro:",f) symlink(os.path.join(clonedir, f), os.path.join(macro_dir, f)) FreeCAD.ParamGet('User parameter:Plugins/'+self.repos[idx][0]).SetString("destination",clonedir) answer += translate("AddonsInstaller", "A macro has been installed and is available the Macros menu") + ": <b>" answer += f + "</b>" self.progressbar_show.emit(False) self.info_label.emit(answer) self.stop = True
def InitApplications(): try: import sys,os,traceback,io except ImportError: FreeCAD.Console.PrintError("\n\nSeems the python standard libs are not installed, bailing out!\n\n") raise # Checking on FreeCAD module path ++++++++++++++++++++++++++++++++++++++++++ ModDir = FreeCAD.getHomePath()+'Mod' ModDir = os.path.realpath(ModDir) ExtDir = FreeCAD.getHomePath()+'Ext' ExtDir = os.path.realpath(ExtDir) BinDir = FreeCAD.getHomePath()+'bin' BinDir = os.path.realpath(BinDir) LibDir = FreeCAD.getHomePath()+'lib' LibDir = os.path.realpath(LibDir) Lib64Dir = FreeCAD.getHomePath()+'lib64' Lib64Dir = os.path.realpath(Lib64Dir) AddPath = FreeCAD.ConfigGet("AdditionalModulePaths").split(";") HomeMod = FreeCAD.getUserAppDataDir()+"Mod" HomeMod = os.path.realpath(HomeMod) MacroDir = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Macro").GetString("MacroPath") MacroMod = os.path.realpath(MacroDir+"/Mod") SystemWideMacroDir = FreeCAD.getHomePath()+'Macro' SystemWideMacroDir = os.path.realpath(SystemWideMacroDir) #print FreeCAD.getHomePath() if os.path.isdir(FreeCAD.getHomePath()+'src\\Tools'): sys.path.append(FreeCAD.getHomePath()+'src\\Tools') # Searching for module dirs +++++++++++++++++++++++++++++++++++++++++++++++++++ # Use dict to handle duplicated module names ModDict = {} if os.path.isdir(ModDir): ModDirs = os.listdir(ModDir) for i in ModDirs: ModDict[i.lower()] = os.path.join(ModDir,i) else: Wrn ("No modules found in " + ModDir + "\n") # Search for additional modules in the home directory if os.path.isdir(HomeMod): HomeMods = os.listdir(HomeMod) for i in HomeMods: ModDict[i.lower()] = os.path.join(HomeMod,i) # Search for additional modules in the macro directory if os.path.isdir(MacroMod): MacroMods = os.listdir(MacroMod) for i in MacroMods: key = i.lower() if key not in ModDict: ModDict[key] = os.path.join(MacroMod,i) # Search for additional modules in command line for i in AddPath: if os.path.isdir(i): ModDict[i] = i #AddModPaths = App.ParamGet("System parameter:AdditionalModulePaths") #Err( AddModPaths) # add also this path so that all modules search for libraries # they depend on first here PathExtension = [] PathExtension.append(BinDir) # prepend all module paths to Python search path Log('Init: Searching for modules...\n') # to have all the module-paths available in FreeCADGuiInit.py: FreeCAD.__ModDirs__ = list(ModDict.values()) # this allows importing with: # from FreeCAD.Module import package FreeCAD.__path__ = [ModDir, Lib64Dir, LibDir, HomeMod] # also add these directories to the sys.path to # not change the old behaviour. once we have moved to # proper python modules this can eventuelly be removed. sys.path = [ModDir, Lib64Dir, LibDir, ExtDir] + sys.path 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... with open(InstallFile) 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') extension_modules = [] try: import pkgutil import importlib import freecad for _, freecad_module_name, freecad_module_ispkg in pkgutil.iter_modules(freecad.__path__, "freecad."): if freecad_module_ispkg: Log('Init: Initializing ' + freecad_module_name + '\n') freecad_module = importlib.import_module(freecad_module_name) extension_modules += [freecad_module_name] if any (module_name == 'init' for _, module_name, ispkg in pkgutil.iter_modules(freecad_module.__path__)): try: importlib.import_module(freecad_module_name + '.init') Log('Init: Initializing ' + freecad_module_name + '... done\n') except Exception as inst: Err('During initialization the error ' + str(inst) + ' occurred in ' + freecad_module_name + '\n') Err('-'*80+'\n') Err(traceback.format_exc()) Err('-'*80+'\n') Log('Init: Initializing ' + freecad_module_name + '... failed\n') Log('-'*80+'\n') Log(traceback.format_exc()) Log('-'*80+'\n') else: Log('Init: No init module found in ' + freecad_module_name + ', skipping\n') except ImportError as inst: Err('During initialization the error ' + str(inst) + ' occurred\n') Log("Using "+ModDir+" as module path!\n") # In certain cases the PathExtension list can contain invalid strings. We concatenate them to a single string # but check that the output is a valid string PathEnvironment = PathExtension.pop(0) + os.pathsep for path in PathExtension: try: PathEnvironment += path + os.pathsep except UnicodeDecodeError: Wrn('Filter invalid module path: u{}\n'.format(repr(path))) pass # new paths must be prepended to avoid to load a wrong version of a library try: os.environ["PATH"] = PathEnvironment + os.environ["PATH"] except UnicodeDecodeError: # See #0002238. FIXME: check again once ported to Python 3.x Log('UnicodeDecodeError was raised when concatenating unicode string with PATH. Try to remove non-ascii paths...\n') path = os.environ["PATH"].split(os.pathsep) cleanpath=[] for i in path: if test_ascii(i): cleanpath.append(i) os.environ["PATH"] = PathEnvironment + os.pathsep.join(cleanpath) Log('done\n') except UnicodeEncodeError: Log('UnicodeEncodeError was raised when concatenating unicode string with PATH. Try to replace non-ascii chars...\n') os.environ["PATH"] = PathEnvironment.encode(errors='replace') + os.environ["PATH"] Log('done\n') except KeyError: os.environ["PATH"] = PathEnvironment path = os.environ["PATH"].split(os.pathsep) Log("System path after init:\n") for i in path: Log(" " + i + "\n") # add MacroDir to path (RFE #0000504) sys.path.append(MacroDir) # add SystemWideMacroDir to path sys.path.append(SystemWideMacroDir) # add special path for MacOSX (bug #0000307) import platform if len(platform.mac_ver()[0]) > 0: sys.path.append(os.path.expanduser('~/Library/Application Support/FreeCAD/Mod'))