diff --git a/src/component.py b/src/component.py index 992a82e..0ff2fbd 100644 --- a/src/component.py +++ b/src/component.py @@ -40,7 +40,8 @@ class ComponentMetaclass(type(QtCore.QObject)): def renderWrapper(func): def renderWrapper(self, *args, **kwargs): try: - log.verbose('### %s #%s renders%s frame %s###', + log.verbose( + '### %s #%s renders%s frame %s###', self.__class__.name, str(self.compPos), '' if args else ' a preview', '' if not args else '%s ' % args[0], @@ -289,7 +290,6 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass): self._lockedSize = None # If set to a dict, values are used as basis to update relative widgets self.oldAttrs = None - # Stop lengthy processes in response to this variable self.canceled = False @@ -386,7 +386,8 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass): ''' self.parent = parent self.settings = parent.settings - log.verbose('Creating UI for %s #%s\'s widget', + log.verbose( + 'Creating UI for %s #%s\'s widget', self.name, self.compPos ) self.page = self.loadUi(self.__class__.ui) @@ -530,6 +531,7 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass): else: # Normal tracked widget setattr(self, attr, val) + log.verbose('Setting %s self.%s to %s' % (self.name, attr, val)) def setWidgetValues(self, attrDict): ''' @@ -669,12 +671,22 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass): def relativeWidgetAxis(func): def relativeWidgetAxis(self, attr, *args, **kwargs): + hasVerticalWords = ( + lambda attr: + 'height' in attr.lower() or + 'ypos' in attr.lower() or + attr == 'y' + ) if 'axis' not in kwargs: axis = self.width - if 'height' in attr.lower() \ - or 'ypos' in attr.lower() or attr == 'y': + if hasVerticalWords(attr): axis = self.height kwargs['axis'] = axis + if 'axis' in kwargs and type(kwargs['axis']) is tuple: + axis = kwargs['axis'][0] + if hasVerticalWords(attr): + axis = kwargs['axis'][1] + kwargs['axis'] = axis return func(self, attr, *args, **kwargs) return relativeWidgetAxis @@ -682,7 +694,12 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass): def pixelValForAttr(self, attr, val=None, **kwargs): if val is None: val = self._relativeValues[attr] - return math.ceil(kwargs['axis'] * val) + result = math.ceil(kwargs['axis'] * val) + log.verbose( + 'Converting %s: f%s to px%s using axis %s', + attr, val, result, kwargs['axis'] + ) + return result @relativeWidgetAxis def floatValForAttr(self, attr, val=None, **kwargs): @@ -693,7 +710,7 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass): def setRelativeWidget(self, attr, floatVal): '''Set a relative widget using a float''' pixelVal = self.pixelValForAttr(attr, floatVal) - with blockSignals(self._allWidgets): + with blockSignals(self._trackedWidgets[attr]): self._trackedWidgets[attr].setValue(pixelVal) self.update(auto=True) @@ -707,15 +724,15 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass): log.verbose('Using nonstandard oldAttr for %s', attr) return self.oldAttrs[attr] else: - return getattr(self, attr) + try: + return getattr(self, attr) + except AttributeError: + log.info('Using visible values instead of attrs') + return self._trackedWidgets[attr].value() def updateRelativeWidget(self, attr): '''Called by _preUpdate() for each relativeWidget before each update''' - try: - oldUserValue = self.getOldAttr(attr) - except (AttributeError, KeyError): - log.info('Using visible values as basis for relative widgets') - oldUserValue = self._trackedWidgets[attr].value() + oldUserValue = self.getOldAttr(attr) newUserValue = self._trackedWidgets[attr].value() newRelativeVal = self.floatValForAttr(attr, newUserValue) @@ -808,17 +825,25 @@ class ComponentUpdate(QtWidgets.QUndoCommand): ) ) self.undone = False + self.res = (int(parent.width), int(parent.height)) self.parent = parent self.oldWidgetVals = { attr: copy(val) + if attr not in self.parent._relativeWidgets + else self.parent.floatValForAttr(attr, val, axis=self.res) for attr, val in oldWidgetVals.items() if attr in modifiedVals } - self.modifiedVals = modifiedVals + self.modifiedVals = { + attr: val + if attr not in self.parent._relativeWidgets + else self.parent.floatValForAttr(attr, val, axis=self.res) + for attr, val in modifiedVals.items() + } # Because relative widgets change themselves every update based on # their previous value, we must store ALL their values in case of undo - self.redoRelativeWidgetVals = { + self.relativeWidgetValsAfterUndo = { attr: copy(getattr(self.parent, attr)) for attr in self.parent._relativeWidgets } @@ -843,17 +868,28 @@ class ComponentUpdate(QtWidgets.QUndoCommand): self.modifiedVals.update(other.modifiedVals) return True + def setWidgetValues(self, attrDict): + ''' + Mask the component's usual method to handle our + relative widgets in case the resolution has changed. + ''' + newAttrDict = { + attr: val if attr not in self.parent._relativeWidgets + else self.parent.pixelValForAttr(attr, val) + for attr, val in attrDict.items() + } + self.parent.setWidgetValues(newAttrDict) + def redo(self): if self.undone: log.debug('Redoing component update') - self.parent.setWidgetValues(self.modifiedVals) - self.parent.setAttrs(self.modifiedVals) - if self.undone: - self.parent.oldAttrs = self.redoRelativeWidgetVals + self.parent.oldAttrs = self.relativeWidgetValsAfterUndo + self.setWidgetValues(self.modifiedVals) self.parent.update(auto=True) self.parent.oldAttrs = None else: - self.undoRelativeWidgetVals = { + self.parent.setAttrs(self.modifiedVals) + self.relativeWidgetValsAfterRedo = { attr: copy(getattr(self.parent, attr)) for attr in self.parent._relativeWidgets } @@ -862,8 +898,7 @@ class ComponentUpdate(QtWidgets.QUndoCommand): def undo(self): log.debug('Undoing component update') self.undone = True - self.parent.oldAttrs = self.undoRelativeWidgetVals - self.parent.setWidgetValues(self.oldWidgetVals) - self.parent.setAttrs(self.oldWidgetVals) + self.parent.oldAttrs = self.relativeWidgetValsAfterRedo + self.setWidgetValues(self.oldWidgetVals) self.parent.update(auto=True) self.parent.oldAttrs = None diff --git a/src/components/life.py b/src/components/life.py index 76d2c5f..5d00987 100644 --- a/src/components/life.py +++ b/src/components/life.py @@ -70,7 +70,7 @@ class Component(Component): elif d == 3: newGrid = newGrid(1, 0) self.startingGrid = newGrid - self.sendUpdateSignal() + self._sendUpdateSignal() def update(self): self.updateGridSize() diff --git a/src/gui/mainwindow.py b/src/gui/mainwindow.py index 833d2d1..2841896 100644 --- a/src/gui/mainwindow.py +++ b/src/gui/mainwindow.py @@ -88,10 +88,13 @@ class MainWindow(QtWidgets.QMainWindow): self.previewWorker.imageCreated.connect(self.showPreviewImage) self.previewThread.start() - log.debug('Starting preview timer') + timeout = 500 + log.debug( + 'Preview timer set to trigger when idle for %sms' % str(timeout) + ) self.timer = QtCore.QTimer(self) self.timer.timeout.connect(self.processTask.emit) - self.timer.start(500) + self.timer.start(timeout) # Begin decorating the window and connecting events self.window.installEventFilter(self) diff --git a/src/gui/preview_thread.py b/src/gui/preview_thread.py index 33a9e7a..d3e0581 100644 --- a/src/gui/preview_thread.py +++ b/src/gui/preview_thread.py @@ -45,8 +45,6 @@ class Worker(QtCore.QObject): @pyqtSlot() def process(self): - width = int(self.settings.value('outputWidth')) - height = int(self.settings.value('outputHeight')) try: nextPreviewInformation = self.queue.get(block=False) while self.queue.qsize() >= 2: @@ -54,12 +52,14 @@ class Worker(QtCore.QObject): self.queue.get(block=False) except Empty: continue + width = int(self.settings.value('outputWidth')) + height = int(self.settings.value('outputHeight')) if self.background.width != width \ or self.background.height != height: self.background = Checkerboard(width, height) frame = self.background.copy() - log.debug('Creating new preview frame') + log.info('Creating new preview frame') components = nextPreviewInformation["components"] for component in reversed(components): try: diff --git a/src/toolkit/common.py b/src/toolkit/common.py index 95aeab3..2e800eb 100644 --- a/src/toolkit/common.py +++ b/src/toolkit/common.py @@ -84,6 +84,7 @@ def appendUppercase(lst): lst.append(form.upper()) return lst + def pipeWrapper(func): '''A decorator to insert proper kwargs into Popen objects.''' def pipeWrapper(commandList, **kwargs):