aboutsummaryrefslogtreecommitdiff
path: root/src/avp/toolkit/common.py
diff options
context:
space:
mode:
authorBrianna Rainey2026-01-13 19:34:55 -0500
committerGitHub2026-01-13 19:34:55 -0500
commit50f5a76603a3f97f2c6f6a1d3cefea88ed3497aa (patch)
tree226fe223b31af6f217b1dd413629ab2cf26964d4 /src/avp/toolkit/common.py
parentb8703752ffc7768b0275897b3c2a869ff41504e5 (diff)
parentf975144f25d34f97329b2d4e52891061573cea08 (diff)
Merge pull request #85 from aeliton/add-pyproject
Use pyproject.toml + uv_build
Diffstat (limited to 'src/avp/toolkit/common.py')
-rw-r--r--src/avp/toolkit/common.py192
1 files changed, 192 insertions, 0 deletions
diff --git a/src/avp/toolkit/common.py b/src/avp/toolkit/common.py
new file mode 100644
index 0000000..e35aba2
--- /dev/null
+++ b/src/avp/toolkit/common.py
@@ -0,0 +1,192 @@
+"""
+Common functions
+"""
+
+from PyQt6 import QtWidgets
+import string
+import os
+import sys
+import subprocess
+import logging
+from copy import copy
+from collections import OrderedDict
+
+
+log = logging.getLogger("AVP.Toolkit.Common")
+
+
+class blockSignals:
+ """
+ Context manager to temporarily block list of QtWidgets from updating,
+ and guarantee restoring the previous state afterwards.
+ """
+
+ def __init__(self, widgets):
+ if type(widgets) is dict:
+ self.widgets = concatDictVals(widgets)
+ else:
+ self.widgets = widgets if hasattr(widgets, "__iter__") else [widgets]
+
+ def __enter__(self):
+ log.verbose(
+ "Blocking signals for %s",
+ ", ".join([str(w.__class__.__name__) for w in self.widgets]),
+ )
+ self.oldStates = [w.signalsBlocked() for w in self.widgets]
+ for w in self.widgets:
+ w.blockSignals(True)
+
+ def __exit__(self, *args):
+ log.verbose("Resetting blockSignals to %s", str(bool(sum(self.oldStates))))
+ for w, state in zip(self.widgets, self.oldStates):
+ w.blockSignals(state)
+
+
+def concatDictVals(d):
+ """Concatenates all values in given dict into one list."""
+ key, value = d.popitem()
+ d[key] = value
+ final = copy(value)
+ if type(final) is not list:
+ final = [final]
+ final.extend([val for val in d.values()])
+ else:
+ value.extend([item for val in d.values() for item in val])
+ return final
+
+
+def badName(name):
+ """Returns whether a name contains non-alphanumeric chars"""
+ return any([letter in string.punctuation for letter in name])
+
+
+def alphabetizeDict(dictionary):
+ """Alphabetizes a dict into OrderedDict"""
+ return OrderedDict(sorted(dictionary.items(), key=lambda t: t[0]))
+
+
+def presetToString(dictionary):
+ """Returns string repr of a preset"""
+ return repr(alphabetizeDict(dictionary))
+
+
+def presetFromString(string):
+ """Turns a string repr of OrderedDict into a regular dict"""
+ return dict(eval(string))
+
+
+def appendUppercase(lst):
+ for form, i in zip(lst, range(len(lst))):
+ lst.append(form.upper())
+ return lst
+
+
+def pipeWrapper(func):
+ """A decorator to insert proper kwargs into Popen objects."""
+
+ def pipeWrapper(commandList, **kwargs):
+ if sys.platform == "win32":
+ # Stop CMD window from appearing on Windows
+ startupinfo = subprocess.STARTUPINFO()
+ startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+ kwargs["startupinfo"] = startupinfo
+
+ if "bufsize" not in kwargs:
+ kwargs["bufsize"] = 10**8
+ if "stdin" not in kwargs:
+ kwargs["stdin"] = subprocess.DEVNULL
+ return func(commandList, **kwargs)
+
+ return pipeWrapper
+
+
+@pipeWrapper
+def checkOutput(commandList, **kwargs):
+ return subprocess.check_output(commandList, **kwargs)
+
+
+def disableWhenEncoding(func):
+ def decorator(self, *args, **kwargs):
+ if self.encoding:
+ return
+ else:
+ return func(self, *args, **kwargs)
+
+ return decorator
+
+
+def disableWhenOpeningProject(func):
+ def decorator(self, *args, **kwargs):
+ if self.core.openingProject:
+ return
+ else:
+ return func(self, *args, **kwargs)
+
+ return decorator
+
+
+def rgbFromString(string):
+ """Turns an RGB string like "255, 255, 255" into a tuple"""
+ try:
+ tup = tuple([int(i) for i in string.split(",")])
+ if len(tup) != 3:
+ raise ValueError
+ for i in tup:
+ if i > 255 or i < 0:
+ raise ValueError
+ return tup
+ except:
+ return (255, 255, 255)
+
+
+def formatTraceback(tb=None):
+ import traceback
+
+ if tb is None:
+ import sys
+
+ tb = sys.exc_info()[2]
+ return "Traceback:\n%s" % "\n".join(traceback.format_tb(tb))
+
+
+def connectWidget(widget, func):
+ if type(widget) == QtWidgets.QLineEdit:
+ widget.textChanged.connect(func)
+ elif type(widget) == QtWidgets.QSpinBox or type(widget) == QtWidgets.QDoubleSpinBox:
+ widget.valueChanged.connect(func)
+ elif type(widget) == QtWidgets.QCheckBox:
+ widget.stateChanged.connect(func)
+ elif type(widget) == QtWidgets.QComboBox:
+ widget.currentIndexChanged.connect(func)
+ else:
+ log.warning("Failed to connect %s ", str(widget.__class__.__name__))
+ return False
+ return True
+
+
+def setWidgetValue(widget, val):
+ """Generic setValue method for use with any typical QtWidget"""
+ log.verbose("Setting %s to %s" % (str(widget.__class__.__name__), val))
+ if type(widget) == QtWidgets.QLineEdit:
+ widget.setText(val)
+ elif type(widget) == QtWidgets.QSpinBox or type(widget) == QtWidgets.QDoubleSpinBox:
+ widget.setValue(val)
+ elif type(widget) == QtWidgets.QCheckBox:
+ widget.setChecked(val)
+ elif type(widget) == QtWidgets.QComboBox:
+ widget.setCurrentIndex(val)
+ else:
+ log.warning("Failed to set %s ", str(widget.__class__.__name__))
+ return False
+ return True
+
+
+def getWidgetValue(widget):
+ if type(widget) == QtWidgets.QLineEdit:
+ return widget.text()
+ elif type(widget) == QtWidgets.QSpinBox or type(widget) == QtWidgets.QDoubleSpinBox:
+ return widget.value()
+ elif type(widget) == QtWidgets.QCheckBox:
+ return widget.isChecked()
+ elif type(widget) == QtWidgets.QComboBox:
+ return widget.currentIndex()