Description |
---|
Gui front end for pip for installing/removing pypi packages in the FreeCAD Python environment. Macro version: 0.4 Last modified: 2025.01.18 FreeCAD version: 1.0 Download: ToolBar Icon Author: TheMarkster |
Author |
TheMarkster |
Download |
ToolBar Icon |
Links |
Macros recipes How to install macros How to customize toolbars |
Macro Version |
0.4 |
Date last modified |
2025.01.18 |
FreeCAD Version(s) |
1.0 |
Default shortcut |
None |
See also |
None |
This is a Gui front end for pip for installing pypi packages into the FreeCAD Python environment.
Packages screenshot
This macro will install pypi packages into a special folder called AdditionalPythonPackages. This is the same exact folder that is also used by the AddonManager for installing dependencies for various addons. Files in this folder might have been installed by the addon manager or by this macro. You can click the button in the bottom right corner to open the folder location in your default file browser. Note that if the folder does not yet exist it will be created for you. If the folder has to be created, then FreeCAD will not recognize packages installed into it until FreeCAD is restarted. After that, no FreeCAD restart should be required again. Packages are installed using pip. These are installed from pypi. Only the top 8000 most downloaded packages are listed, but you can use the search button to install those that are outside the top 8000 most popular packages. The apply filter button will use the filter line edit contents to filter the packages in the top 8000 list. The Sort checkbox toggles sorting between alphabetical and based on popularity (default unchecked state). The open url button opens the pypi page for the selected package in your default browser.
Note that a package might have additional dependencies, which will also be installed, and when you remove the package the dependencies that were installed with it will also be removed unless they were also installed as dependencies for another package. It is possible to delete the entire folder to remove all dependency packages installed with this macro and with the Addon Manager. But obviously doing so might break any addons that require these packages.
The installed packages will go into a subfolder based on the Python version in use. If FreeCAD is updated to a newer version of Python, then those packages will most likely need to be re-installed. You can simply copy them over to the new Python version folder, but it is better to use pip in case the newer Python version requires a newer version of the package.
packages.py
# packages.py # 2024, <TheMarkster> LGPL 2.1 or later # thanks to forum member hasecilu for help with setting pyside6 icons # a utility to install Python packages in FreeCAD __version__ = "0.4" from PySide import QtWidgets, QtGui, QtCore QDialog = QtWidgets.QDialog QVBoxLayout = QtWidgets.QVBoxLayout QHBoxLayout = QtWidgets.QHBoxLayout QLabel = QtWidgets.QLabel QLineEdit = QtWidgets.QLineEdit QSpinBox = QtWidgets.QSpinBox QPushButton = QtWidgets.QPushButton QListWidget = QtWidgets.QListWidget QMessageBox = QtWidgets.QMessageBox QCheckBox = QtWidgets.QCheckBox QApplication = QtGui.QApplication QFileDialog = QtGui.QFileDialog Qt = QtCore.Qt import requests import re import webbrowser import subprocess, sys, platform import freecad.utils as utils import addonmanager_utilities as amutils import shutil import json import importlib class Packages: def __init__(self): self.python_version = f"{sys.version_info.major}.{sys.version_info.minor}" self.pg = FreeCAD.ParamGet(f"User parameter:Plugins/Packages_Macro/{self.python_version}") layout = QVBoxLayout() self.mw = FreeCADGui.getMainWindow() self.pathEdit = QLineEdit() self.pathEdit.setToolTip("Path to python executable.") self.pathEdit.setText(self.findExecutable()) self.form = QtWidgets.QWidget() self.form.setLayout(layout) self.mode = "install" # can also be "uninstall" filterLayout = QHBoxLayout() self.filterEdit = QLineEdit() self.filterEdit.setPlaceholderText("Filter packages") self.filterEdit.returnPressed.connect(self.applyFilter) self.filterEdit.textChanged.connect(self.enableButtons) filterLayout.addWidget(QLabel("Filter:")) filterLayout.addWidget(self.filterEdit) self.sortedCheckBox = QCheckBox("Sort") self.sortedCheckBox.setToolTip(""" Default is sorting by popularity in terms of most downloads in the last 30 days. Checked = sort A to Z. Note toggling applies the filter.""") self.sortedCheckBox.setChecked(False) self.sortedCheckBox.stateChanged.connect(self.applyFilter) # this is to initialize stateChanged, otherwise first toggle does not update checked = self.sortedCheckBox.isChecked() filterLayout.addWidget(self.sortedCheckBox) self.filterButton = QPushButton("Apply Filter") self.filterButton.clicked.connect(self.applyFilter) filterLayout.addWidget(self.filterButton) self.searchButton = QPushButton("Search") self.searchButton.setIcon(FreeCADGui.getIcon("internet-web-browser")) self.searchButton.setToolTip("Search for filter on pypi.org in default browser") self.searchButton.setEnabled(False) filterLayout.addWidget(self.searchButton) self.searchButton.clicked.connect(self.search) self.packageList = QListWidget() self.packageList.itemSelectionChanged.connect(self.enableButtons) self.fetchButton = QPushButton("Fetch summary") self.fetchButton.setIcon(FreeCADGui.getIcon("internet-web-browser")) self.fetchButton.setEnabled(False) self.fetchButton.clicked.connect(self.fetchSummary) layout.addLayout(filterLayout) layout.addWidget(self.packageList) buttonLayout = QHBoxLayout() buttonLayout.addWidget(self.fetchButton) self.installButton = QPushButton("Install / Update") self.installButton.clicked.connect(self.install) self.installButton.setEnabled(False) self.installButton.setToolTip(""" If this is disabled with an active selection it means the package is a base package. You are allowed to install again an added package because there might be an update available for it.""") buttonLayout.addWidget(self.installButton) self.uninstallButton = QPushButton("Uninstall") style = self.form.style() try: trashIcon = style.standardIcon(style.SP_TrashIcon) except: trashIcon = style.standardIcon(style.StandardPixmap.SP_TrashIcon) self.uninstallButton.setIcon(trashIcon) self.uninstallButton.clicked.connect(self.uninstall) self.uninstallButton.setEnabled(False) self.uninstallButton.setToolTip(""" If this is disabled with an active selection it means the selected package is either not already installed or it is a base package included with the packaging or distribution.""") buttonLayout.addWidget(self.uninstallButton) self.openUrlButton = QPushButton("Open Url") self.openUrlButton.setIcon(FreeCADGui.getIcon("internet-web-browser")) self.openUrlButton.clicked.connect(self.openUrl) self.openUrlButton.setEnabled(False) buttonLayout.addWidget(self.openUrlButton) layout.addLayout(buttonLayout) pathLayout = QHBoxLayout() layout.addLayout(pathLayout) self.pathEdit.setPlaceholderText("Path to python executable") pathLayout.addWidget(QLabel("Python:")) pathLayout.addWidget(self.pathEdit) self.pathButton = QPushButton("...") try: self.pathButton.setIcon(style.standardIcon(style.SP_FileDialogStart)) except: self.pathButton.setIcon(style.standardIcon(style.StandardPixmap.SP_FileDialogStart)) self.pathButton.setFixedWidth(self.pathButton.sizeHint().width()) self.pathButton.setToolTip("Click to browse for python executable.") self.pathButton.clicked.connect(self.setupPath) pathLayout.addWidget(self.pathButton) additionalLayout = QHBoxLayout() layout.addLayout(additionalLayout) additionalLayout.addWidget(QLabel("AdditionalPythonPackages folder:")) self.additionalEdit = QLineEdit() self.additionalEdit.setPlaceholderText("AdditionalPythonPackages folder goes here") pathToPackages = self.pg.GetString("PathToPackages","") if not pathToPackages: pathToPackages = amutils.get_pip_target_directory() if not os.path.exists(pathToPackages): os.makedirs(pathToPackages) self.pg.SetString("PathToPackages", pathToPackages) FreeCAD.Console.PrintMessage("AdditionalPythonPackages folder has been created. You will likely need to restart FreeCAD to use any newly installed packages.\n") self.additionalEdit.setText(pathToPackages) self.additionalEdit.setReadOnly(True) additionalLayout.addWidget(self.additionalEdit) self.additionalButton = QPushButton("Open") try: self.additionalButton.setIcon(style.standardIcon(style.SP_DirOpenIcon)) except: self.additionalButton.setIcon(style.standardIcon(style.StandardPixmap.SP_DirOpenIcon)) self.additionalButton.clicked.connect(self.openAdditional) self.additionalButton.setToolTip(""" Opens the AdditionalPythonPackages folder. Note that the only things that should be in this folder are things installed using this macro or additional dependencies installed via the addon manager. It should be relatively safe to remove things from here. You should take note of what extra folders were added when you install something. These dependencies are not being tracked as pip doesn't support tracking packages added to custom folders. When we uninstall something we only install what we added, not the additional dependencies pip might have added.""") additionalLayout.addWidget(self.additionalButton) self.packages = self.loadPackageData() title = f"Packages {__version__} ({len(self.packages)} packages)" self.form.setWindowTitle(title) self.applyFilter() self.form.setWindowIcon(self.QIconFromXPMString(__icon__)) def loadPackageData(self): # would be faster to cache this locally, but this way it's always up to date url = "https://hugovk.github.io/top-pypi-packages/top-pypi-packages-30-days.json" try: response = requests.get(url) response.raise_for_status() data = response.json() return data["rows"] except requests.RequestException as e: QMessageBox.critical(self.mw, "Error", f"Could not load data: {e}") return [] def openAdditional(self): """ open the addtional python packages folder. note that this is a different folder for each version of python used by various freecad installations, for example if the user has multiple versions in simultaneous use. this folder is really for the addon manager to install dependencies when installing various addons, so we do not have exclusive use of it. but the advantage is the addon manager can also update these for use when updates are available. this folder is made available to python via initGui,py in src/App, which is how addons are able to import the packages installed here. """ sys = platform.system() userFolder = self.additionalEdit.text() if 'Windows' in sys: subprocess.Popen('start explorer.exe '+userFolder, shell=True) elif 'Linux' in sys: os.system("xdg-open '%s'" % userFolder) elif 'Darwin' in sys: subprocess.Popen(["open", userFolder]) else: msgBox = QtGui.QMessageBox() msg = "We were unable to determine your platform, and thus cannot open your '+userFolder+' for you, but you can still do it manually.\n" msgBox.exec_() def getStandardButtons(self): return (QtWidgets.QDialogButtonBox.Close) def setupPath(self): """ This is for the user to bre able to set a python that he wants to use rather than the default found with the freecad.utils function """ path, ok = QFileDialog.getOpenFileName(self.mw, "Select Python Executable", "", "Python Executable (python*);;All Files (*)") if path: self.pathEdit.setText(path) self.pg.SetString("PathToPython", path) def applyFilter(self): """ This is called when the user clicks the Apply filters button, and also when the user toggles the sort checkbox, and when the enter key is pressed in the filter line edit widget. If sorting is active, then the filtered packages are sorted alphabetically, otherwise they are sorted based on the popularity as measured by the number of downloads in the last 30 days. """ filter = self.filterEdit.text() try: filtered = [pkg for pkg in self.packages if re.search(filter, pkg["project"], re.IGNORECASE)] exactMatch = False self.packageList.clear() for pkg in filtered: self.packageList.addItem(pkg["project"]) if pkg == filter: exactMatch = True self.packageList.setSortingEnabled(self.sortedCheckBox.isChecked()) if filter and not exactMatch: description, version = self.getInfo(filter) if description: self.packageList.insertItem(0, filter + " (not in top 8000)") except re.error as e: QMessageBox.warning(self.mw, "Invalid Regex", f"Error in regular expression: {e}") self.form.setWindowTitle(f"Packages {__version__}") def enableButtons(self): """enables or disables buttons based on whether a package is selected in the list widget and whether that package is already installed.""" hasSelection = bool(self.packageList.selectedItems()) self.openUrlButton.setEnabled(hasSelection) self.fetchButton.setEnabled(hasSelection) hasFilter = bool(self.filterEdit.text()) self.searchButton.setEnabled(hasFilter) added, base = (False, False) if hasSelection: added, base = self.isInstalled() self.installButton.setEnabled(not base) self.uninstallButton.setEnabled(added) def install(self): self.mode = "install" self.managePackages() def uninstall(self): self.mode = "uninstall" self.managePackages() def findExecutable(self): """ find the python executable in use, luckily there is a function for this already in FreeCAD, but we still want to allow the user the flexibility of setting a different python executable if the function gets it wrong """ path = self.pg.GetString("PathToPython","") if path: return path pyEx = utils.get_python_exe() if os.path.exists(pyEx): self.pg.SetString("PathToPython", pyEx) return pyEx else: FreeCAD.Console.PrintError(f"Python executable not found. You may try to find it manually by clicking the '...' button at the bottom of the dialog.\n") return "Path to python executable" def managePackages(self): """ Here is where the installing and uninstalling happens. We track which packages we have installed and which dependencies were installed along with them. The caveat here is the AddonManager might also install stuff in our folder, but I don't think the AM tracks extra dependencies. """ package = self.packageList.currentItem().text().replace(" (not in top 8000)", "") python_exe = self.pathEdit.text() vendor_path = self.additionalEdit.text() if "APPIMAGE" in os.environ: os.environ['PYTHONHOME'] = '/usr' os.environ['PYTHONPATH'] = f"/usr/lib/python{self.python_version}/site-packages" if self.mode == "uninstall": added = self.loadAddedSubfolders(package) self.pg.RemString(f"{package}_Subfolders") for subfolder in added: item_path = os.path.join(vendor_path, subfolder) if os.path.exists(item_path): shutil.rmtree(item_path) print(f"{subfolder} removed\n") self.enableButtons() return existing = set(os.listdir(vendor_path)) command = [python_exe, "-m", "pip", self.mode, "--target", vendor_path, package] try: result = subprocess.run( command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True, check=True ) FreeCAD.Console.PrintMessage(f"{result.stdout}\n") new_folders = set(os.listdir(vendor_path)) - existing added = list(new_folders) self.saveAddedSubfolders(package, added) except subprocess.CalledProcessError as e: FreeCAD.Console.PrintError(f"Error: {e.stderr}\n") except Exception as e: FreeCAD.Console.PrintError(f"An unexpected error occurred: {e}\n") finally: self.enableButtons() def saveAddedSubfolders(self, package, added): """ Here we track the folders that we added to this AdditionalPythonPackages folder and removed them during uninstallation. The complication is that sometimes additional dependencies are also added, and when they are, we should also track them and remove them. Further complicating this is other packages might have also added the same dependencies. These we reconcile in the loadAddedSubfolders() method below. """ json_string = json.dumps(added) self.pg.SetString(f"{package}_Subfolders", json_string) def loadAddedSubfolders(self, package): """ We get all of the packages that were added by all installations, this is in allPackages list. The added list only includes the new subfolders that were added when this package was installed. Anything in added that is not also in allPackages can be safely removed during uninstallation. """ json_string = self.pg.GetString(f"{package}_Subfolders", "") added = json.loads(json_string) if json_string else [] allPackages = [] for key in self.pg.GetStrings(): if key.endswith("_Subfolders") and key != f"{package}_Subfolders": other_json = self.pg.GetString(key, "") try: otherPackages = json.loads(other_json) allPackages.extend(otherPackages) except json.JSONDecodeError: print(f"Error decoding subfolder list for {key}.") unique = [folder for folder in added if folder not in allPackages] return unique def isInstalled(self): """ Called only by the enable buttons function. We return a tuple (added, base) added = True means this was something we added to the additional packages folder. base = True means this is installed, but as a base package either through the packaging or user installed into the system environment, either way we don't try to install or uninstall anything we didn't add or that the addon manager didn't add as an additional dependency in our user addon folder """ added = False base = False package = self.packageList.currentItem().text().replace(" (not in top 8000)", "") python_exe = self.pathEdit.text() vendor_path = amutils.get_pip_target_directory() if not os.path.exists(vendor_path): os.makedirs(vendor_path) fullpath = os.path.join(vendor_path,package) if os.path.exists(fullpath): added = True try: importlib.import_module(package) if not added: # we didn't add this base = True except ImportError: # added might or might not be false because this might not yet be # available to import if the additionalpythonpackages folder was # only just created this FreeCAD session, so we don't set it False # here, but instead rely on the above test base = False return (added, base) def fetchSummary(self): selectedItem = self.packageList.currentItem() if not selectedItem: return package = selectedItem.text().replace(" (not in top 8000)","") description, version = self.getInfo(package) QMessageBox.information(self.mw, "Package Summary", f"{package} (v{version}): {description}") def getInfo(self, package): """ called by fetchSummary(), pops up a very brief description of the package in a message box. User can use the OpenUrl button to get more details. We also use this to check if a custom entered package is available outside the top 8000 list. """ url = f"https://pypi.org/pypi/{package}/json" try: response = requests.get(url) response.raise_for_status() data = response.json() description = data["info"].get("summary", "No description available.") version = data["info"].get("version", "Unknown version") return description, version except requests.RequestException: return "", "Unknown version" def search(self): filter = self.filterEdit.text() if not filter: return url = f"https://pypi.org/search/?q={filter}" try: webbrowser.open(url) except Exception as e: QMessageBox.critical(self.mw, "Error", f"Unable to open the browser. Error: {e}") def openUrl(self): package = self.packageList.currentItem().text().replace(" (not in top 8000)", "") url = f"https://pypi.org/pypi/{package}" try: webbrowser.open(url) except Exception as e: QMessageBox.critical(self.mw, "Error", f"Unable to open the browser. Error: {e}") def QIconFromXPMString(self, xpm_string): if "/*pixels*/" in xpm_string: xpm = xpm_string.replace("\"","").replace(',','').splitlines()[4:] else: xpm = xpm_string.replace("\"","").replace(',','').splitlines()[3:] for line in reversed(xpm): if line.startswith("/*") and line.endswith("*/"): xpm.pop(xpm.index(line)) pixmap = QtGui.QPixmap(xpm) icon = QtGui.QIcon(pixmap) return icon __icon__ = """ /* XPM */ static char *dummy[]={ "64 64 1050 2", "Qt c None", ".g c #010101", "br c #020202", "a3 c #030202", "h3 c #030303", "ej c #030304", ".I c #040404", "ao c #050504", ".# c #050505", "m9 c #060605", "dI c #060606", ".J c #070707", "a2 c #090907", "nl c #090909", "mW c #0a0a0a", "mV c #0b0a09", "aL c #0b0b09", "bh c #0b0b0b", ".s c #0b0c0c", "nz c #0c0b0b", "oj c #0c0c0c", "d3 c #0c0c0d", "n9 c #0d0c0c", "dJ c #0d0d0d", "#b c #0d0d0e", ".W c #0d0e0f", "mL c #0e0e0f", "eI c #0f0f10", "#T c #0f1317", "#x c #0f1417", "mK c #100f0d", "nN c #11100e", "nk c #11100f", "mA c #111111", "bM c #111112", "#a c #111417", "c# c #121212", "#U c #121415", "mo c #131313", ".t c #131315", "mU c #15130e", "nA c #151516", "aK c #16140d", "#y c #16181b", "mM c #171717", "fj c #181819", ".X c #181a1c", "gY c #191919", ".f c #191b1d", "h# c #1a1a1b", "#7 c #1a1e21", "m8 c #1c1a15", "an c #1d1b15", "oi c #1d1d1e", "ot c #1e1e1e", "mX c #202020", "ap c #212328", "aM c #212428", "nY c #22211c", "bs c #222223", "h4 c #232325", "#8 c #23252a", "#c c #23272e", "cx c #242425", ".H c #242629", "#z c #242b34", "o. c #252526", ".h c #25272a", "ek c #262627", ".K c #262a2f", "cP c #282729", "d# c #282829", "iM c #29292a", "du c #29292b", "#d c #2c3845", "#A c #2e3d4b", "am c #2f2919", "aJ c #2f2a1c", "m7 c #2f2a1d", "nO c #2f2f30", ".A c #2f6491", "mY c #303030", ".B c #306491", ".Q c #306591", "ib c #306592", "nj c #312d23", "ny c #312f2a", ".Y c #313942", "#E c #316591", "eS c #316592", "ja c #323233", "a5 c #326592", ".z c #326692", "mT c #332e21", "av c #336692", "#p c #336792", "dC c #336793", "a6 c #346792", ".R c #346793", "aw c #346893", "n. c #353536", ".Z c #354658", ".l c #35658f", ".m c #356792", ".6 c #356893", "ev c #356894", "os c #363637", ".u c #363d46", ".P c #366792", "#i c #366894", "dW c #366994", "bg c #373630", "mz c #373737", "#e c #374d61", "#h c #376893", "f. c #376994", "ax c #376a95", "#R c #3775a9", ".y c #386891", ".n c #386993", "ac c #386994", "ew c #386a95", "ba c #3875a9", "bA c #3876a9", "dl c #3876aa", ".o c #39678f", "lj c #3976a9", "c2 c #3977aa", "nm c #3a3a3c", ".x c #3a648a", "ab c #3a6a94", ".C c #3a6b95", "dB c #3a6b96", "aR c #3a6c96", "#Q c #3a77aa", "#Z c #3b6c96", "ad c #3b6c97", "ea c #3b6d96", "b# c #3b77aa", "dK c #3c3b3d", ".a c #3c4149", ".0 c #3c5974", "#Y c #3c6c94", "iw c #3c6c96", "aC c #3c78aa", "ht c #3c78ab", ".k c #3d6589", ".O c #3d688f", "#D c #3d6b94", "fw c #3d6d95", "b. c #3d78aa", "k2 c #3d79ab", "bi c #3e3e40", ".D c #3e6c93", "fr c #3e6c95", "eT c #3e6e98", "ae c #3e6f9a", "dX c #3e79ab", "iq c #3f3f42", ".w c #3f607d", "g# c #3f6c95", "gm c #3f6e96", ".7 c #3f6e98", "#F c #3f6f98", "lE c #3f79ab", "#5 c #3f7aab", "cH c #3f7aac", "nM c #403c30", "gQ c #406e96", "au c #406e97", "g4 c #406f96", "#o c #406f98", "cI c #407aab", "fY c #407aac", "#V c #414b56", "aq c #415c76", ".E c #416789", "ds c #417bab", "#v c #417bac", ".r c #42474d", "#B c #425a73", "a4 c #425c75", "aN c #425c76", ".S c #426f97", "ay c #42729b", "dD c #427bac", "b0 c #427dae", "jb c #434343", "mN c #434344", "#g c #436b91", "kk c #437199", "ic c #43719a", "hr c #43729a", "hV c #437cac", "iN c #444446", "#f c #446482", "fs c #446f96", "hd c #447299", "ia c #44729a", "aV c #447dad", "ok c #454547", "bN c #454548", ".v c #45576a", "fP c #456f97", "fx c #45739b", "iB c #457dad", ".i c #465161", ".T c #466e91", "hf c #467dad", "n8 c #474541", "a7 c #477198", "ft c #477298", "e9 c #477299", "k1 c #47739b", "eh c #477ead", "eZ c #477eae", "cn c #4780b0", "ar c #487197", "fR c #487298", "aa c #487398", "e6 c #487399", "dV c #48759c", "dE c #487fae", "nx c #49422f", "#C c #496c8e", "fQ c #497398", "iU c #49749a", "eu c #49759b", "gn c #4979a2", "c3 c #497fae", "bV c #4980ad", "nB c #4a4a4c", "fS c #4a7399", "j8 c #4a79a2", "g5 c #4a7aa3", "bz c #4a80ad", "go c #4a80ae", "eY c #4a80af", ".j c #4b647d", ".N c #4b6b87", "eR c #4b769b", "cp c #4b80ae", "bm c #4b81ae", "fu c #4c7398", "fv c #4c7499", "#M c #4c7ba2", "gS c #4c80aa", "#P c #4c82af", "nn c #4d4d4f", "d4 c #4d4d50", "e7 c #4d7499", "#j c #4d789e", "#q c #4d799f", "gC c #4d81ad", "bD c #4d84b2", "ca c #4e4e4f", "ex c #4e789e", "kl c #4e7ea6", "hs c #4e7ea8", "i2 c #4e83af", "he c #4f7ea7", "n# c #504f51", ".1 c #507495", "aQ c #50789c", ".5 c #507a9f", "#L c #507ca2", "by c #507fa6", "id c #5083b0", "lF c #5083b1", "ci c #5084b0", "dk c #5086b4", "#9 c #51667b", "hU c #517a9f", "ee c #517ea6", "ch c #517fa6", "dY c #5184b0", "fX c #5184b1", "aE c #5185b1", "aO c #527699", "e8 c #52779a", "eA c #527ba0", "af c #527ea3", "#s c #5280a8", "c8 c #5284b0", "fB c #5285b0", "aj c #5285b1", "bF c #5285b2", "nZ c #535355", ".L c #535c67", ".F c #536b81", ".p c #537390", "#X c #537697", "a. c #53789a", "e# c #53799b", "h9 c #537b9f", "eU c #537ca0", "#J c #537ca1", "fA c #5383ad", "fc c #5383ae", "k3 c #5385b1", "do c #5386b1", "l2 c #5386b2", "ni c #544e3b", "ga c #54799c", "iX c #547ca0", "fT c #547ca1", "f# c #547ea2", "#r c #5480a6", "fV c #5482aa", "cJ c #5485b1", "aB c #5487b1", "#I c #557da1", "fU c #5581a7", "eF c #5586b2", "cY c #5588b3", "iz c #567da1", "#K c #567ea1", "bl c #5681a7", "a9 c #5686af", "c4 c #5687b2", ".G c #57626e", "at c #577b9d", "eB c #5783a8", "#u c #5788b2", "al c #58543e", ".b c #586a80", "a# c #587b9c", "ix c #587da1", "#m c #5880a3", ".8 c #5881a6", "fb c #5886ad", "fW c #5887b0", "bB c #588cb7", "iA c #597fa2", "iy c #597fa3", "#l c #5980a3", ".9 c #5984a9", "fz c #5985ab", "cD c #598ab4", "c1 c #598cb7", "jf c #5a7fa2", "#t c #5a88b0", "iC c #5a89b3", "i# c #5b80a4", ".2 c #5b81a2", "gp c #5b89ae", "#4 c #5b8ab3", "eJ c #5c5c60", "iW c #5c80a4", "#G c #5c82a5", "#N c #5c88ad", "#. c #5c88ae", "ig c #5c8bb3", "ox c #5d5d61", ".U c #5d7386", "#W c #5d738c", ".c c #5d7c99", "as c #5d7c9c", ".3 c #5d82a4", "#n c #5d83a4", "fy c #5d85a8", "jj c #5d8bb3", "c5 c #5d8bb4", "nX c #5e5742", "l1 c #5e88ad", "cL c #5e8bb3", "fC c #5e8cb4", "gc c #5e8db4", "ir c #5f5f61", ".V c #5f6a75", "ed c #5f83a5", "aS c #5f86a8", "lk c #5f8cb5", "iD c #5f8db4", "m6 c #60563a", "i. c #6082a4", "iY c #6084a5", "l0 c #6085a5", "#k c #6185a6", "cK c #618db5", "#O c #618eb5", "oh c #626266", ".e c #626d78", ".M c #627181", ".q c #627384", "#0 c #6288a9", "h5 c #636366", "iV c #6385a5", "gb c #6388aa", "fe c #638fb5", "dp c #638fb6", "dn c #638fb7", "nP c #646467", "aP c #64819f", "gD c #648ea8", "bt c #656569", "fa c #658cae", "c6 c #658fb6", "i0 c #6590b6", "bW c #6594bd", "nL c #665b3c", "mJ c #666152", ".4 c #6688a8", "lG c #6692b9", "iO c #676768", "az c #678caf", "iZ c #678cb0", "ie c #6790b7", "if c #6791b7", "aU c #6792b7", "dS c #6888a7", "eb c #688aa9", "ef c #6891b8", "li c #698aa9", "a8 c #698cab", "ah c #6992b7", "i1 c #6992b8", "a1 c #6a6452", "nC c #6a6a6c", "dR c #6a87a4", "#H c #6a8baa", "dU c #6a8bab", "#S c #6a8fb1", "eC c #6a92b6", "dr c #6a93b7", "g. c #6b87a3", "#w c #6b90b1", "bk c #6c87a1", "fq c #6c87a3", "et c #6c89a6", "ag c #6c91b3", "#6 c #6c92b2", "gB c #6c94b8", "iT c #6d88a5", "je c #6d89a5", "jI c #6d89a6", "kj c #6d8aa6", "gR c #6d94b8", "eX c #6d95b8", ".d c #6e879f", "iv c #6e88a5", "gl c #6e89a5", "jv c #6e89a6", "hg c #6f94b7", "nw c #70623b", "bC c #709dc1", "c7 c #7197b9", "hc c #728da9", "gA c #728daa", "ey c #7290ae", "hI c #7296b6", "dj c #729ec2", "ou c #737376", "ez c #7391af", "dZ c #7397bb", "ak c #7398b6", "aA c #7398b9", "ji c #7398bb", "l3 c #739bbe", "no c #747474", "bO c #747477", "mn c #747478", "hH c #7499ba", "lU c #757578", "jg c #7591ad", "#3 c #7599b9", "eg c #7599ba", "mZ c #767676", "dq c #7699bb", "eV c #7795b1", "gT c #7797aa", "jh c #7896b5", "dt c #789cbc", "d2 c #789dbd", "e5 c #798fa8", "## c #7995af", "ff c #799dbd", "dA c #7a95ae", "lD c #7a97b1", "aF c #7a9cb3", "eG c #7a9fbf", "c9 c #7b9ebd", "aD c #7b9fbe", "ei c #7b9fbf", "fD c #7ba0bf", "aT c #7c9db9", "eD c #7c9dbe", "dH c #7c9ebd", "bn c #7c9fbf", "co c #7ca0c0", "dT c #7d96b2", "fd c #7d9ebc", "bE c #7d9fc0", "b1 c #7da0c0", "h8 c #7e94ac", "bx c #7e98b1", "eE c #7e9ebe", "ll c #7ea2c2", "cb c #7f7f80", "el c #7f7f83", "eQ c #7f97af", "dm c #7fa1c0", "e. c #8095ac", "di c #809ab3", "gq c #809b9f", "bU c #819cb4", "bj c #82858c", "ec c #829ab4", "k0 c #8398af", "#1 c #839eb9", "cG c #83aaca", "gd c #84a3bf", "mB c #858589", "g6 c #85a2bd", "bZ c #85aaca", "nW c #877748", "n0 c #88888a", "or c #88888d", "hT c #889bb1", "nQ c #89898a", "hu c #89a3b8", "cq c #89a5bb", "dG c #89a5c2", "dF c #89a6c0", "ai c #89a7c2", "n7 c #8a8884", "e1 c #8a898c", "d0 c #8aa5c1", "cM c #8aa6c0", "mc c #8b8b90", "j9 c #8ba2a8", "lZ c #8ba2b9", "jJ c #8ba3a8", "kL c #8ba3a9", "iE c #8ca4a8", "lH c #8dacc9", "is c #919192", "eK c #919195", "gE c #91a4a1", "jc c #929293", "#2 c #92a7bd", "hW c #92aabf", "nK c #938146", "bu c #949496", "ol c #949498", "eW c #94a9bf", "lh c #95abbe", "mS c #968964", "ih c #96aab3", "my c #999797", "g7 c #99acbb", "d1 c #9aafc6", "aI c #9b8c5f", "nD c #9b9a9b", "cy c #9b9a9e", "og c #9b9ba0", "es c #9ba9ba", "mg c #9bafc4", "cm c #9cbad4", "dQ c #9dabbb", "k4 c #9daeb4", "cj c #9dbbd5", "d5 c #9e9ea3", "hJ c #9eacaa", "nh c #9f9473", "l4 c #9fb6cf", "bf c #a09268", "o# c #a1a0a3", "bP c #a1a1a3", "hh c #a1b0b6", "eP c #a3acbb", "gU c #a3aeaa", "lC c #a3b3c4", "mf c #a4b2c3", "mO c #a5a5a8", "na c #a7a7aa", "lm c #a7bed3", "n1 c #a9a9a8", "cQ c #acabae", "n6 c #acacae", "da c #adacaf", "mm c #adadb2", "c0 c #adc6dc", "lg c #afb7c3", "dv c #b0afb3", "iP c #b0b0b2", "gr c #b1b9ad", "lY c #b1bcc9", "mh c #b1c1d4", "em c #b2b2b5", "js c #b3b3b6", "dz c #b3b9c4", "bX c #b3cade", "nv c #b49d59", "m5 c #b6a36a", "nV c #b6a573", "cc c #b6b6b6", "nR c #b6b6b7", "e2 c #b7b7b9", "ow c #b7b7bd", "lI c #b7c7d9", "cE c #b9cfe1", "gF c #baba9d", "np c #bbbabb", "mI c #bcaa78", "hv c #bcba99", "ov c #bcbcbf", "m0 c #bdbdc0", "gZ c #bdbdc2", "g8 c #bebea8", "fk c #bebec1", "d9 c #bec4cc", "hX c #bfbc98", "om c #bfbec0", "dL c #bfbec2", "eL c #bfbfbf", "gJ c #c0c0c2", "fK c #c0c0c3", "bv c #c1c1c0", "gk c #c1c5cc", "a0 c #c3ae6f", "it c #c3c3c5", "jd c #c3c3c6", "mC c #c4c3c8", "lB c #c4cad2", "bq c #c5b582", "oa c #c5c4c3", "mp c #c6c6c6", "me c #c6cbd1", "of c #c7c7c9", "l5 c #c7d1de", "d6 c #c8c7cb", "lT c #c8c8c9", "ln c #cacdc7", "dy c #cbccd1", "f9 c #cbd0d5", "ha c #cccccf", "bw c #cccfd3", "hK c #cdbf7a", "hl c #cdcccf", "jV c #cdccd0", "nE c #cdcdcd", "g0 c #cdcdd2", "ng c #ceb568", "hi c #cec9b0", "hC c #cecdcf", "h6 c #cecdd1", "nb c #ceced0", "j5 c #ceced2", "kf c #ceced3", "nJ c #cfb35b", "kE c #cfcdd1", "le c #cfced1", "lx c #cfced2", "bQ c #cfcfcf", "mx c #d0be88", "lz c #d0ced2", "iu c #d0cfd2", "jE c #d0cfd3", "md c #d0d0d3", "hS c #d0d2d7", "h7 c #d0d3d7", "gz c #d0d4da", "ms c #d1d0d4", "mE c #d1d0d5", "jt c #d1d1d3", "iS c #d1d1d4", "nc c #d1d1d5", "kK c #d1d5d8", "be c #d2b65c", "n2 c #d2d1d0", "jW c #d2d1d6", "dP c #d2d6d9", "j7 c #d2d6da", "ki c #d2d7da", "mR c #d3ba71", "m1 c #d3d2d4", "n5 c #d3d3d5", "gN c #d3d3d7", "jH c #d3d6da", "ju c #d3d7da", "bY c #d3e1ec", "jD c #d4d3d5", "eq c #d4d3d6", "cZ c #d4e1ed", "hY c #d5c270", "gV c #d5c78e", "d7 c #d5d4d6", "iQ c #d5d5d6", "lf c #d5d5d8", "hp c #d5d5d9", "er c #d5d8da", "ho c #d6d5d7", "de c #d6d6d8", "hG c #d6dbdf", "j6 c #d7d7d9", "lX c #d7dadb", "dh c #d7dadd", "cd c #d8d8d9", "fp c #d8dce0", "aH c #d9bc62", "cz c #d9d9d9", "g1 c #d9d9db", "cS c #dad9db", "kg c #dad9dd", "jC c #dadad9", "e4 c #dadee1", "g3 c #dadee2", "gP c #dadfe2", "jT c #dbdad9", "gx c #dbdadb", "lw c #dbdbd9", "gM c #dbdbdb", "f8 c #dbdbdc", "gy c #dbdbdd", "lJ c #dbe1e8", "on c #dcdbd8", "lV c #dcdbda", "en c #dcdcdb", "kI c #dcdcde", "m4 c #ddc67d", "j4 c #dddcdc", "fn c #dddcde", "ko c #ded0a6", "fL c #dedddd", "cT c #dedede", "hb c #dededf", "ob c #dfdedc", "dd c #dfdede", "kq c #dfdee1", "f7 c #dfdfde", "nu c #e0c162", "fi c #e0cd94", "kH c #e0dfdf", "mb c #e0e0e2", "bT c #e0e2e4", "cg c #e0e2e5", "mi c #e0e5ea", "bp c #e1c87e", "k5 c #e1cc87", "nU c #e1dbcd", "df c #e1e1e1", "gs c #e2cd86", "jZ c #e2cd8c", "ka c #e2ce94", "j0 c #e2ce95", "fM c #e2e1e1", "kZ c #e2e1e2", "eM c #e2e2e0", "fl c #e2e2e1", "fO c #e2e2e2", "oq c #e2e2e3", "eO c #e2e3e5", "hw c #e3c865", "ge c #e3cb75", "jP c #e3cd8f", "k# c #e3ce90", "jz c #e3cf93", "ip c #e3cf94", "jA c #e3dac3", "ly c #e3e2e1", "mD c #e3e2e2", "fm c #e3e3e2", "cA c #e3e3e3", "gO c #e3e3e4", "lA c #e3e4e2", "kM c #e4cc7b", "hQ c #e4e3e1", "hR c #e4e3e2", "kG c #e4e3e3", "dx c #e4e4e2", "fN c #e4e4e3", "kJ c #e4e4e4", "ii c #e5cd77", "kn c #e5ce88", "iL c #e5dfd1", "gj c #e5e4e2", "kh c #e5e4e4", "bR c #e5e5e4", "aG c #e6c550", "hL c #e6c960", "mq c #e6e5e1", "cR c #e6e5e3", "hF c #e6e5e4", "fo c #e6e5e5", "d8 c #e6e7e4", "dO c #e6e7e5", "gG c #e7cc70", "gw c #e7e6e4", "jF c #e7e6e6", "hn c #e7e7e4", "kp c #e7e7e5", "cU c #e7e7e6", "lS c #e7e7e9", "cN c #e8cd6d", "fJ c #e8cf82", "ky c #e8d28f", "jq c #e8e3d8", "hE c #e8e7e4", "nd c #e8e7e5", "ep c #e8e7e7", "gL c #e8e8e5", "cV c #e8e8e8", "oe c #e8e8e9", "cr c #e9ca5f", "hZ c #e9cb64", "mH c #e9cb6a", "jK c #e9cc6c", "ks c #e9cd6c", "hy c #e9d28a", "ke c #e9e8e5", "gv c #e9e8e6", "nF c #e9e8e7", "cB c #e9e8e8", "mt c #e9e8e9", "kr c #e9e9e7", "mF c #e9e9e9", "m2 c #e9e9ea", "iF c #eacd6c", "jQ c #eace7d", "kO c #eacf7a", "lo c #ead17f", "jR c #ead38a", "jp c #eadcb4", "nS c #eae8e7", "hm c #eae9e6", "gK c #eae9e7", "hq c #eaeae9", "oo c #eaeaec", "fG c #ebcf79", "ku c #ebcf7a", "kv c #ebd07f", "jm c #ebd286", "k. c #ebd287", "i8 c #ebe2c8", "j3 c #ebeae7", "dN c #ebebe7", "lW c #ebebe8", "dg c #ebebea", "jO c #ecce71", "fh c #ecce74", "gH c #ecd385", "mk c #ecd386", "mr c #eceae7", "nq c #eceae8", "dc c #ecebe7", "gi c #ecebe8", "nI c #edc95a", "gg c #edce72", "bL c #edd076", "hO c #edd384", "lp c #edd484", "kY c #edece8", "hD c #edece9", "ne c #edeced", "eo c #ededeb", "ce c #ededec", "n4 c #ededef", "l6 c #edf0f2", "aZ c #eec954", "d. c #eecc53", "fZ c #eecc54", "f2 c #eecf70", "gh c #eecf72", "i3 c #eed385", "j2 c #eed483", "ik c #eed484", "iG c #eed485", "ml c #eeebe3", "i9 c #eeede8", "dM c #eeede9", "jU c #eeedea", "cW c #eeeeed", "nr c #eeeeee", "nG c #eeeeef", "aW c #efc431", "b2 c #efc432", "mw c #efc84d", "nf c #efcb5d", "eH c #efcc53", "g9 c #efce60", "kN c #efcf6a", "km c #efcf6b", "f1 c #efcf6c", "f4 c #efd06e", "fH c #efd171", "iI c #efd172", "gX c #efd47f", "hA c #efd480", "lc c #efd483", "kX c #efd484", "iJ c #efd992", "mG c #efe7d3", "mP c #efe8d3", "lL c #efe9d3", "kF c #efedea", "dw c #efeee9", "db c #efeeea", "iR c #efefef", "cF c #eff4f8", "bd c #f0c12b", "bH c #f0cd5d", "io c #f0cf69", "kP c #f0d068", "k7 c #f0d069", "e0 c #f0d06a", "h2 c #f0d06b", "nH c #f0d379", "h1 c #f0d380", "im c #f0d480", "i7 c #f0dea8", "iK c #f0e4bf", "ns c #f0e7d3", "lv c #f0f0f3", "ck c #f0f5f9", "fF c #f1cf65", "k6 c #f1cf67", "bI c #f1cf68", "hj c #f1d064", "jY c #f1d066", "gf c #f1d067", "c. c #f1d16b", "cw c #f1d16c", "jo c #f1d98d", "e3 c #f1f1ef", "ld c #f1f1f2", "j# c #f1f1f3", "bo c #f2c848", "hx c #f2cd52", "b4 c #f2ce5e", "f3 c #f2cf63", "kb c #f2d16a", "i6 c #f2d478", "jG c #f2f2f0", "hM c #f3cf56", "i5 c #f3d062", "jn c #f3d26c", "jB c #f3f2f0", "bS c #f3f3f0", "cC c #f3f3f1", "ma c #f3f3f4", "mQ c #f4cf5a", "jy c #f4d05d", "fI c #f4d05f", "kQ c #f4d060", "kw c #f4d061", "m3 c #f4d370", "lM c #f4d470", "g2 c #f4f4f1", "b3 c #f5cb49", "b5 c #f5cf57", "bJ c #f5cf58", "iH c #f5d05b", "kt c #f5d05d", "kR c #f5d15e", "f5 c #f5d161", "eN c #f5f5f2", "op c #f5f5f6", "cs c #f6cf58", "f0 c #f6d057", "ct c #f6d260", "cX c #f6f6f3", "od c #f6f6f7", "nt c #f7d053", "b6 c #f7d157", "kx c #f7d158", "kz c #f7d25d", "cf c #f7f7f4", "lK c #f7f7f8", "gW c #f8d150", "jx c #f8d153", "k8 c #f8d154", "j1 c #f8d157", "b7 c #f8d259", "hP c #f8d25b", "hz c #f8d25c", "jX c #f8d25d", "jk c #f8d35b", "il c #f8d35c", "lR c #f8f8f9", "h0 c #f9d14e", "fg c #f9d151", "bK c #f9d153", "gt c #f9d256", "cu c #f9d257", "bc c #fac723", "mv c #facf46", "i4 c #fad14f", "jN c #fad151", "jr c #fafaf9", "n3 c #fafafb", "jw c #fbd14c", "kc c #fbd24d", "bG c #fcc925", "hk c #fcd147", "jM c #fcd14a", "in c #fcd24a", "gI c #fcd24b", "h. c #fcd24c", "b8 c #fcd24d", "jS c #fcf9f0", "mj c #fcfcfc", "m# c #fcfcfd", "mu c #fdd145", "fE c #fdd146", "jl c #fdd147", "jL c #fdd246", "hN c #fdd247", "kd c #fdd248", "cO c #fdd249", "hB c #fdd24c", "oc c #fdfdfd", "nT c #fdfdfe", "aY c #fec91f", "bb c #fec921", "gu c #fed243", "cv c #fed244", "ij c #fed246", "j. c #fefefe", "aX c #ffc91d", "b9 c #ffd242", "f6 c #ffd243", "m. c #ffd347", "kD c #ffd348", "l7 c #ffd449", "kS c #ffd44b", "kA c #ffd54f", "lu c #ffd654", "kW c #ffd757", "lb c #ffd85d", "l9 c #ffda65", "kC c #ffdc6c", "k9 c #ffdd71", "l8 c #ffde74", "lQ c #ffdf77", "lN c #ffdf78", "kB c #ffe07e", "lq c #ffe48e", "kT c #ffe9a2", "lt c #ffefbf", "kV c #fff2c6", "lO c #fff2c8", "lP c #fff3cc", "kU c #fff5d7", "l. c #fff7de", "la c #fffae9", "lr c #fffaec", "l# c #fffefd", "ls c #fffffe", "cl c #ffffff", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.#.a.b.c.d.e.f.gQtQtQtQtQtQtQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.g.h.i.j.k.l.m.n.o.p.q.r.sQtQtQtQtQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.t.u.v.w.x.y.z.A.A.A.B.C.D.E.F.G.H.IQtQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.J.K.L.M.N.O.P.Q.A.A.A.A.A.A.A.A.R.S.T.U.V.WQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.g.X.Y.Z.0.1.2.3.4.5.6.A.A.A.A.A.A.A.A.7.8.9#.###aQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#b#c#d#e#f#g#h.A#i#j#k#l#m#n#o.Q.A.A#p#q#r#s#t#u#v#w#xQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt.##y#z#A#B#C#D#E.A.A.A.A.A.A#F#G#H#I#J#K#L#M#N#O#P#Q#R#R#S#TQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#U#V#W#X#Y.A.A.A.A.A.A.A.A.A.A.A#Z#0#1#2#3#4#5#R#R#R#R#R#6#7.gQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt#8#9a.a#aaabac.z.A.A.A.A.A.zadaeafagahaiaj#R#R#R#R#R#R#RakalamanaoQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtapaq.A#parasatau.mav.QawaxayazaAaBaC#RaDaE#R#R#R#R#R#R#RaFaGaHaIaJaKaL.gQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtaMaN.A.A.A.AabaOaPaQaRaSaTaUaV#R#R#R#RaDaE#R#R#R#R#R#R#RaFaWaXaYaZa0a1a2a3.g", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtaMa4.A.A.A.A.Ba5a6a7a8a9b.b#ba#R#R#R#RaDaE#R#R#R#R#R#R#RaFaWaXaXbbbcbdbebfbg", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtbhbibjbk.A.A.A.A.A.A.A#hblbm#R#R#R#R#R#R#RbnaE#R#R#R#R#R#R#RaFaWaXaXaXaXaYbobpbq", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtbrbsbtbubvbwbx.A.A.A.A.A.A.A#pbybzbAbBbCbD#R#R#RbEbF#R#R#R#R#R#R#RaFaWaXaXbGbHbIbJbKbL", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtbMbNbObPbQbRbSbTbU.A.A.A.A.A.A.A#pbybVbWbXbYbZb0#R#Rb1bF#R#R#R#R#R#R#RaFb2b3b4b5b6b7b8b9c.", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtc#cacbcccdcecfcfcfcgbU.A.A.A.A.A.A.A#pchcicjckclcmcn#R#RcobF#R#R#R#R#Rbacpcqcrcsctcucvb9b9b9cw", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtcxcyczcAcBcCcfcfcfcgbU.A.A.A.A.A.A.A#pchcDcEclcFcGcH#R#RcobF#R#R#RcIcJcKcLcMcNcOb9b9b9b9b9b9cw", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtcPcQcRcScTcUcVcWcXbTbU.A.A.A.A.A.A.A#pbycYcjcZc0c1#R#R#Rb1bFc2c3c4c5c6c7c8c9d.b9b9b9b9b9b9b9c.", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtd#dadbdbdcdddedfdgdhdi.B.A.A.A.A.A.A#pbybzc1djdkdl#R#R#Rdmdndodpdqdrds#R#Rdtd.b9b9b9b9b9b9b9cw", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtdudvdbdbdbdbdwdxdydzdA#odBdC.A.A.A.A#pchbV#R#R#R#Rb#dDdEdFdGdHbmbA#R#R#R#Rdtd.b9b9b9b9b9b9b9cw", "QtQtQtQtQtQtQtQtQtQtQtQtQtQt.gdIdJdKdLdbdbdMdNdOdPdQdRdSdTdUdVdWav.B.A#pchbz#Rbab#dXdYdZd0d1do#R#R#R#R#R#R#Rd2d.b9b9b9b9b9b9b9cw", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtd3d4d5d6d7dbdbd8d9e.e#.6.B.B.QeaebeceddB.AdCeebV#RdDefd0egehbAeiaE#R#R#R#R#R#R#Rd2d.b9b9b9b9b9b9b9c.", "QtQtQtQtQtQtQtQtQtQtQtejekelemeneoepeqereseteuacav.A.A.A.A.QevewexeyezeAeBeCeDeEeF#vdXbA#ReGaE#R#R#R#R#R#R#Rd2eHb9b9b9b9b9b9b9cw", "QtQtQtQtQtQtQtQtQteIeJeKeLeMeoeNcfeOePeQeRaceS.A.A.A.A.A.A.A.A.A.6eTeUeVeWeXeYeZb.#R#R#R#ReGaE#R#R#R#R#R#R#Rd2d.b9b9b9b9b9b9b9e0", "QtQtQtQtQtQtQtQtbMe1e2cTe3cfcfcfcfe4e5e6e7e8e9eS.A.A.A.A.A.A.Af.f#fafbfcfdfebA#R#R#R#R#R#ReiaE#R#R#R#R#R#R#RffeHb9b9b9b9b9fgfhfi", "QtQtQtQtQtQtQtQtfjfkflfmfnfocXcfcffpfqavfrfsftfufvfw.A.A#EfxfyfzfAfBeh#QeXfC#R#R#R#R#R#R#RfDaE#R#R#R#R#R#R#Rd2d.b9b9fEfFfGfHfIfJ", "QtQtQtQtQtQtQtQtfjfKdMcRfLfMfNfOeofpfq.A.A.B#hfPfQfRfSfTfUfVfWfXfY#R#R#ReXfC#R#R#R#R#R#R#RfDaE#R#R#R#R#R#R#Rd2fZf0f1f2f3f4f5f6cw", "QtQtQtQtQtQtQtQtfjfKdbdbdbdcf7f8cAf9g..A.A.A.A.A.zg#gagb#4dEba#R#R#R#R#ReXgc#R#R#R#R#R#R#RfDaE#R#R#R#R#R#RdDgdgegfggghcOb9b9b9c.", "QtQtQtQtQtQtQtQtfjfKdbdbdbdbgigjddgkgl.A.A.A.A.A.A.Agmgn#R#R#R#R#R#R#R#ReXfC#R#R#R#R#R#R#RfDaE#R#R#Rb#gogpgqgrgsgtgub9b9b9b9b9cw", "QtQtQtQtQtQtQtQtfjfKdbdMgvgwcRgxgygzgA.A.A.A.A.A.A.Agmgn#R#R#R#R#R#R#R#RgBfC#R#R#R#R#R#R#ReiaEba#vgCgDgEgFgGgHgIb9b9b9b9b9b9b9c.", "QtQtQtQtQtQtQtQtfjgJgKgLgMgNgOcXcfgPgA.A.A.A.A.A.A.AgQgn#R#R#R#R#R#R#R#RgRfC#R#R#R#R#R#R#Rbn#4gSgTgUgVgWb9b9gXgIb9b9b9b9b9b9b9cw", "QtQtQtQtQtQtQtQtgYgZg0g1g2cfcfcfcfg3gA.A.A.A.A.A.A.Ag4g5#R#R#R#R#R#R#R#RgRfC#R#R#R#Rba#Qb.g6g7g8g9cvb9b9b9b9gXh.b9b9b9b9b9b9b9cw", "QtQtQtQtQtQtQtQth#d6hahbcfcfcfcfcfg3hc.A.A.A.A.A.A.Ahdhe#R#R#R#R#R#R#R#RgRfC#R#R#R#Rhfhghhhihjhkgub9b9b9b9b9gXh.b9b9b9b9b9b9b9cw", "QtQtQtQtQtQtQtQth#hlhmhnhohphqcfcfgPhc.A.A.A.A.A.A.Ahrhs#R#R#R#R#R#R#R#RgRfC#Rhtc5huhvhwhxhyhzb9b9b9b9b9b9b9hAhBb9b9b9b9b9b9b9cw", "QtQtQtQtQtQtQtQth#hCdbhDhEhFfOdehbhGhc.A.A.A.A.A.A.Ahrhs#R#R#R#R#R#R#R#ReXhHhIhJhKhLhMhNb9hOhPb9b9b9b9b9b9b9hAgIb9b9b9b9b9b9b9c.", "QtQtQtQtQtQtQtQth#hCdbdbdbdMgKhQhRhShThUaw.A.A.A.A.Ahrhs#R#R#R#R#R#RhVfChWhXhYhZh0f6b9b9b9hOhPb9b9b9b9b9b9b9h1h.b9b9b9b9b9b9b9h2", "QtQtQtQtQtQth3h4h5h6dbdbdbdbdbdbhDh7h8h9i.i#iaib.A.Aichs#R#R#RaCidieifigihiiijb9b9b9b9b9b9ikilb9b9b9b9b9b9b9imhBb9b9b9b9b9inioip", "QtQtQt.gdJiqirisitiudbdbdbdbdbdbdbdPiviwixiyiziAex.ChrhsbAiBiCdpiDcK#4dDiEiFb9b9b9b9b9b9b9iGhzb9b9b9b9b9b9b9imhBb9b9cviHiIiJiKiL", "QtbriMiNiOiPiQiRe3iSdbdbdbdbdbdbdbdPiT.A.AaviUiViWiXiYiZiCc5i0i1i2#R#R#RiEiFb9b9b9b9b9b9b9i3hzb9b9b9b9b9b9b9imh.i4i5i6i7i8i9j.j#", "jajbjcjdcUcfcfcfe3iSdbdbdbdbdbdbdbdPje.A.A.A.A.A.Cjfjgjhjijjb##R#R#R#R#RiEiFb9b9b9b9b9b9b9i3jkb9b9b9b9b9b9jljmjnjojpjqjrclclclj#", "jsjteog2cfcfcfcfe3iSdbdbdbdbdbdbdbjujv.A.A.A.A.A.A.Agmgn#R#R#R#R#R#R#R#RiEiFb9b9b9b9b9b9b9i3ilb9b9b9gujwjxjyjzjAjBj.clclclclclj#", "jCjDjEjFjGcCcXcfe3iSdbdbdbdbdbdbdbjHjI.A.A.A.A.A.A.Agmgn#R#R#R#R#R#R#R#RjJjKb9b9b9b9b9b9b9i3ilb9jLjMjNjOjPjQjRjSclclclclclclclj#", "jTdbjUgjjVjWe3cXe3iSdbdbdbdbdbdbdbjHjI.A.A.A.A.A.A.Agmgn#R#R#R#R#R#R#R#RjJjKb9b9b9b9b9b9b9i3jXcvjYjZj0j1f6b9j2jSclclclclclclclj#", "jTdbdbdMgij3j4j5j6iQdbdbdbdbdbdbdbj7jv.A.A.A.A.A.A.AgQj8#R#R#R#R#R#R#R#Rj9jKb9b9b9b9b9b9b9k.k#kakbkckdcvb9b9j2jSclclclclclclclj#", "jTdbdbdbdbdbj3kecRkfkgkhdMdbdbdbdbkikj.A.A.A.A.A.A.Akkkl#R#R#R#R#R#R#R#Rj9jKb9b9b9b9inkmknkokbfgcOf6b9b9b9b9j2jSclclclclclclclj#", "jTdbdbdbdbdbdbdbhmh6kpfNg1kqkrdbdbkikj.A.A.A.A.A.A.Ahrhs#R#R#R#R#R#R#R#Rj9ksb9cvktkukvkwkxkykzb9b9b9kAkBkCkDj2jSclclclclclclclj#", "jTdbdbdbdbdbdbdbhmkEkFj3kGkhkHkIkJkKjI.A.A.A.A.A.A.Ahrhs#R#R#R#R#R#R#R#RkLkMkNkOkPkQkRgIb9hOhPb9b9kSkTkUkVkWkXjSclclclclclclclj#", "jTdbdbdbdbdbdbdbhmkEdbdbdbkYcRkZkGbwk0k1eS.A.A.A.A.Ahrhs#R#R#R#R#R#Rk2k3k4k5k6k7k8gub9b9b9hOhPb9b9k9l.l#lalblcjSclclclclclclclld", "jTdbdbdbdbdbdbdbhmledbdbdbdbdbdbj3lflglhlihUiw.A.A.Ahrhs#R#R#RljeZlklllmlnloinb9b9b9b9b9b9lpilb9b9lqlrlsltlulcjSclclclclclj.lvj6", "lwdbdbdbdbdbdbdbhmlxdbdbdbdbdbdbdblylzlAlBlClD#Kia.6hrhs#RlElFlGlHlIlJlKlLlMb9b9b9b9b9b9b9iGjkb9b9lNlOlPlQkDkXjSclclcllRlSlTeKlU", "lVdbdbdbdbdbdbdbhmlxdbdbdbdbdbdbdblyiudbdblWlXlYlZl0#ll1l2l3l4l5l6j.clcllLlMb9b9b9b9b9b9b9i3hzb9b9l7l8l9m.b9lcjSm#mambjsmcd4.#Qt", "jTdbdbdbdbdbdbdbhmlxdbdbdbdbdbdbdblymddbdbdbdbdbcRmemfmgmhmimjclclclclcllLlMb9b9b9b9b9b9b9i3hzb9b9b9b9b9b9cvmkmliQmmmnmo.gQtQtQt", "mpmqmrdMdbdbdbdbhmlxdbdbdbdbdbdbdblymsdbdbdbdbdbdbdbgjmtclclclclclclclcllLlMb9b9b9b9b9b9b9i3hzb9b9b9b9mumvmwmxmymz.IQtQtQtQtQtQt", "mAmBmCkhdbdbdbdbhmlxdbdbdbdbdbdbdbmDmEdbdbdbdbdbdbdbcRmFclclclclclclclclmGlMb9b9b9b9b9b9b9i3ilb9b9b9cvmHmImJmKh3.gQtQtQtQtQtQtQt", "brmLmMmNmOd7gidbhmlxdbdbdbdbdbdbdbmDmEdbdbdbdbdbdbdbcRmFclclclclclclclclmPlMb9b9b9b9b9b9b9i3ilb9mQmRmSmTmUmV.gQtQtQtQtQtQtQtQtQt", "QtQtQtmWmXmYmZm0f8m1dbdbdbdbdbdbdbfmmsdbdbdbdbdbdbdbcRm2clclclclclclclclmPm3b9b9b9b9b9b9b9gHm4m5m6m7m8m9QtQtQtQtQtQtQtQtQtQtQtQt", "QtQtQtQtQtbrh#n.n#nanbkpdbdbdbdbdbmDncdbdbdbdbdbdbdbndneclclclclclclclclmPlMb9b9b9b9ijnfngnhninjnkbrQtQtQtQtQtQtQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtnlnmnnnonpgxnqdbdbfmncdbdbdbdbdbdbdbgKnrclclclclclclclclnsm3b9b9ntnunvnwnxnynzQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtbrnAnBnCnDnEhRlyncdbdbdbdbdbdbdbnFnGclclclclclclclclnsnHnInJnKnLnMnNQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQt.JnOnPnQnRh6gKdbdbdbdbdbdbnSnGclclclclclclnTlKnUnVnWnXnYh3QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtc#nZn0n1n2hQhDdbdbdbkrnGclclclcln3n4n5n6n7n8n9QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQth3o.bOo#oaobhmdMgKnGclocodoeofogohoiQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtojokolomonlyooopoqgZorosbrQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt", "QtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtotouovgNowoxmLQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQtQt"}; """ if __name__ == "__main__": dlg = Packages() if not FreeCADGui.Control.activeDialog(): FreeCADGui.Control.showDialog(dlg) else: FreeCAD.Console.PrintError("Already there is an active task dialog.\n")
The forum discussion Macro Packages