Download src/Mod/Draft/draftutils/todo.py from AbdulElahGwaith/FreeCAD: direct link, hf CLI and curl.
- Browser
- Download file 10.9 kB
-
https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Draft/draftutils/todo.py
- Command line
-
hf download hf://AbdulElahGwaith/FreeCAD/src/Mod/Draft/draftutils/todo.py
-
curl -L -o todo.py https://huggingface.co/AbdulElahGwaith/FreeCAD/resolve/main/src/Mod/Draft/draftutils/todo.py
10.9 kB
| # SPDX-License-Identifier: LGPL-2.1-or-later | |
| # *************************************************************************** | |
| # * (c) 2009, Yorik van Havre <yorik@uncreated.net> * | |
| # * (c) 2019 Eliud Cabrera Castillo <e.cabrera-castillo@tum.de> * | |
| # * * | |
| # * This file is part of the FreeCAD CAx development system. * | |
| # * * | |
| # * This program is free software; you can redistribute it and/or modify * | |
| # * it under the terms of the GNU Lesser General Public License (LGPL) * | |
| # * as published by the Free Software Foundation; either version 2 of * | |
| # * the License, or (at your option) any later version. * | |
| # * for detail see the LICENCE text file. * | |
| # * * | |
| # * FreeCAD is distributed in the hope that it will be useful, * | |
| # * but WITHOUT ANY WARRANTY; without even the implied warranty of * | |
| # * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | |
| # * GNU Library General Public License for more details. * | |
| # * * | |
| # * You should have received a copy of the GNU Library General Public * | |
| # * License along with FreeCAD; if not, write to the Free Software * | |
| # * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * | |
| # * USA * | |
| # * * | |
| # *************************************************************************** | |
| """Provides the ToDo static class to run commands with a time delay. | |
| The `ToDo` class is used to delay the commit of commands for later execution. | |
| This is necessary when a GUI command needs to manipulate the 3D view | |
| in such a way that a callback would crash `Coin`. | |
| The `ToDo` class essentially calls `QtCore.QTimer.singleShot` | |
| to execute the instructions stored in internal lists. | |
| """ | |
| ## @package todo | |
| # \ingroup draftutils | |
| # \brief Provides the ToDo static class to run commands with a time delay. | |
| import traceback | |
| import sys | |
| import PySide.QtCore as QtCore | |
| import FreeCAD as App | |
| import FreeCADGui as Gui | |
| from draftutils.messages import _msg, _wrn, _err, _log | |
| __title__ = "FreeCAD Draft Workbench, Todo class" | |
| __author__ = "Yorik van Havre <yorik@uncreated.net>" | |
| __url__ = ["https://www.freecad.org"] | |
| _DEBUG = 0 | |
| _DEBUG_inner = 0 | |
| ## \addtogroup draftutils | |
| # @{ | |
| class ToDo: | |
| """A static class that delays execution of functions. | |
| It calls `QtCore.QTimer.singleShot(0, doTasks)` | |
| where `doTasks` is a static method which executes | |
| the commands stored in the list attributes. | |
| Attributes | |
| ---------- | |
| itinerary: list of tuples | |
| Each tuple is of the form `(name, arg)`. | |
| The `name` is a reference (pointer) to a function, | |
| and `arg` is the corresponding argument that is passed | |
| to that function. | |
| It then tries executing the function with the argument, | |
| if available, or without it, if not available. | |
| :: | |
| name(arg) | |
| name() | |
| commitlist: list of tuples | |
| Each tuple is of the form `(name, command_list)`. | |
| The `name` is a string identifier or description of the commands | |
| that will be run, and `command_list` is a list of strings | |
| that indicate the Python instructions that will be executed, | |
| or a reference to a single function that will be executed. | |
| If `command_list` is a list, the program opens a transaction, | |
| then runs all commands in the list in sequence, | |
| and finally commits the transaction. | |
| :: | |
| command_list = ["command1", "command2", "..."] | |
| App.activeDocument().openTransaction(name) | |
| Gui.doCommand("command1") | |
| Gui.doCommand("command2") | |
| Gui.doCommand("...") | |
| App.activeDocument().commitTransaction() | |
| If `command_list` is a reference to a function | |
| the function is executed directly. | |
| :: | |
| command_list = function | |
| App.activeDocument().openTransaction(name) | |
| function() | |
| App.activeDocument().commitTransaction() | |
| afteritinerary: list of tuples | |
| Each tuple is of the form `(name, arg)`. | |
| This list is used just like `itinerary`. | |
| Lists | |
| ----- | |
| The lists contain tuples. Each tuple contains a `name` which is just | |
| a string to identify the operation, and a `command_list` which is | |
| a list of strings, each string an individual Python instruction. | |
| """ | |
| itinerary = [] | |
| commitlist = [] | |
| afteritinerary = [] | |
| def doTasks(): | |
| """Execute the commands stored in the lists. | |
| The lists are `itinerary`, `commitlist` and `afteritinerary`. | |
| """ | |
| if _DEBUG: | |
| _msg( | |
| "Debug: doing delayed tasks.\n" | |
| "itinerary: {0}\n" | |
| "commitlist: {1}\n" | |
| "afteritinerary: {2}\n".format(todo.itinerary, todo.commitlist, todo.afteritinerary) | |
| ) | |
| try: | |
| for f, arg in ToDo.itinerary: | |
| try: | |
| if _DEBUG_inner: | |
| _msg("Debug: executing.\n" "function: {}\n".format(f)) | |
| if arg or (arg is False): | |
| f(arg) | |
| else: | |
| f() | |
| except Exception: | |
| _log(traceback.format_exc()) | |
| _err(traceback.format_exc()) | |
| wrn = ( | |
| "ToDo.doTasks, Unexpected error:\n" | |
| "{0}\n" | |
| "in {1}({2})".format(sys.exc_info()[0], f, arg) | |
| ) | |
| _wrn(wrn) | |
| except ReferenceError: | |
| _wrn("Debug: ToDo.doTasks: " "queue contains a deleted object, skipping") | |
| ToDo.itinerary = [] | |
| if ToDo.commitlist: | |
| commit_list = ToDo.commitlist | |
| ToDo.commitlist = [] # Reset immediately to avoid race condition. | |
| for name, func in commit_list: | |
| if _DEBUG_inner: | |
| _msg("Debug: committing.\n" "name: {}\n".format(name)) | |
| try: | |
| name = str(name) | |
| App.activeDocument().openTransaction(name) | |
| if isinstance(func, list): | |
| for string in func: | |
| Gui.doCommand(string) | |
| else: | |
| func() | |
| App.activeDocument().commitTransaction() | |
| except Exception: | |
| _log(traceback.format_exc()) | |
| _err(traceback.format_exc()) | |
| wrn = ( | |
| "ToDo.doTasks, Unexpected error:\n" | |
| "{0}\n" | |
| "in {1}".format(sys.exc_info()[0], func) | |
| ) | |
| _wrn(wrn) | |
| # Restack Draft screen widgets after creation | |
| if hasattr(Gui, "Snapper"): | |
| Gui.Snapper.restack() | |
| for f, arg in ToDo.afteritinerary: | |
| try: | |
| if _DEBUG_inner: | |
| _msg("Debug: executing after.\n" "function: {}\n".format(f)) | |
| if arg: | |
| f(arg) | |
| else: | |
| f() | |
| except Exception: | |
| _log(traceback.format_exc()) | |
| _err(traceback.format_exc()) | |
| wrn = ( | |
| "ToDo.doTasks, Unexpected error:\n" | |
| "{0}\n" | |
| "in {1}({2})".format(sys.exc_info()[0], f, arg) | |
| ) | |
| _wrn(wrn) | |
| ToDo.afteritinerary = [] | |
| def delay(f, arg): | |
| """Add the function and argument to the itinerary list. | |
| Schedule geometry manipulation that would crash Coin if done | |
| in the event callback. | |
| If the `itinerary` list is empty, it will call | |
| `QtCore.QTimer.singleShot(0, ToDo.doTasks)` | |
| to execute the commands in the other lists. | |
| Finally, it will build the tuple `(f, arg)` | |
| and append it to the `itinerary` list. | |
| Parameters | |
| ---------- | |
| f: function reference | |
| A reference (pointer) to a Python command | |
| which can be executed directly. | |
| :: | |
| f() | |
| arg: argument reference | |
| A reference (pointer) to the argument to the `f` function. | |
| :: | |
| f(arg) | |
| """ | |
| if _DEBUG: | |
| _msg("Debug: delaying.\n" "function: {}\n".format(f)) | |
| if ToDo.itinerary == []: | |
| QtCore.QTimer.singleShot(0, ToDo.doTasks) | |
| ToDo.itinerary.append((f, arg)) | |
| def delayCommit(cl): | |
| """Execute the other lists, and add to the commit list. | |
| Schedule geometry manipulation that would crash Coin if done | |
| in the event callback. | |
| First it calls | |
| `QtCore.QTimer.singleShot(0, ToDo.doTasks)` | |
| to execute the commands in all lists. | |
| Then the `cl` list is assigned as the new commit list. | |
| Parameters | |
| ---------- | |
| cl: list of tuples | |
| Each tuple is of the form `(name, command_list)`. | |
| The `name` is a string identifier or description of the commands | |
| that will be run, and `command_list` is a list of strings | |
| that indicate the Python instructions that will be executed. | |
| See the attributes of the `ToDo` class for more information. | |
| """ | |
| if _DEBUG: | |
| _msg("Debug: delaying commit.\n" "commitlist: {}\n".format(cl)) | |
| QtCore.QTimer.singleShot(0, ToDo.doTasks) | |
| ToDo.commitlist = cl | |
| def delayAfter(f, arg): | |
| """Add the function and argument to the afteritinerary list. | |
| Schedule geometry manipulation that would crash Coin if done | |
| in the event callback. | |
| Works the same as `delay`. | |
| If the `afteritinerary` list is empty, it will call | |
| `QtCore.QTimer.singleShot(0, ToDo.doTasks)` | |
| to execute the commands in the other lists. | |
| Finally, it will build the tuple `(f, arg)` | |
| and append it to the `afteritinerary` list. | |
| """ | |
| if _DEBUG: | |
| _msg("Debug: delaying after.\n" "function: {}\n".format(f)) | |
| if ToDo.afteritinerary == []: | |
| QtCore.QTimer.singleShot(0, ToDo.doTasks) | |
| ToDo.afteritinerary.append((f, arg)) | |
| # Alias for compatibility with v0.18 and earlier | |
| todo = ToDo | |
| ## @} | |