diff options
| author | Brianna Rainey | 2026-01-28 17:49:58 -0500 |
|---|---|---|
| committer | GitHub | 2026-01-28 17:49:58 -0500 |
| commit | f66eb99465c61232a7f649e66bee59504bb0e52c (patch) | |
| tree | 40d4f2e4e7cea033e4a68da025c7d91295e71cfb | |
| parent | 864898419e810055b51e3a32fccb00a62aab9a6b (diff) | |
v2.2.1 - fix #74, fix #92, add optional 64th bar to Classic Visualizer, improve Conway default (#93)
* update gitignore
ignore profiling and coverage data
* F1 opens help window, create appName variable, move undostack class
* fix kaleidoscope effect, increase default Y values by +4
the increased y values allow the cells to continue animating for more than 60 minutes instead of 30 (at default 60f/t)
* update version number
* add minimumWidth to undo history window
* Classic Visualizer: option to include 64th bar
* Waveform component: fix #74 - new animation speed option
* move shared visualizer code into toolkit
* Waveform component: compress audio by default
* Waveform component: fix 100% animation speed
* new components receive random color
* update to Qt 6
* fix pushbutton stylesheet
* fix #92: replace ok/cancel with save/discard/cancel
* remove obsolete PaintColor subclass
* mv common shadow code into addShadow func
* add 3rd option of ok/cancel back to showMessage
the 3 options are:
- ok
- ok/cancel
- save/discard/cancel
* Image component: add shadow option
* small test of rgbFromString
* fix color tuple string
* test another way to get comp names from CLI
* rename component tests, add some more
* Image component: scale shadow based on resolution
* catch AttributeError if previewRender returns None
* Text component: fix blur radius only able to increase
the relativeWidgets system causes QDoubleSpinbox to only allow increases, because it really only works with integeres, so I changed the blur radius into a normal QSpinBox. I noted where the problem exists within component.py for future reference. This commit also removes an unneeded VerticalLayout from the ui file
* remove unnecessary QVBoxLayout
* paste shadow at x,y instead of using offset method
* fix tests due to shadow change
* don't print warning in connectWidget due to QFontComboBox
36 files changed, 1556 insertions, 1270 deletions
| @@ -5,6 +5,7 @@ __pycache__ | |||
| 5 | build/ | 5 | build/ |
| 6 | dist/ | 6 | dist/ |
| 7 | env/ | 7 | env/ |
| 8 | prof/ | ||
| 8 | .venv/ | 9 | .venv/ |
| 9 | .env/ | 10 | .env/ |
| 10 | .vscode/ | 11 | .vscode/ |
| @@ -24,3 +25,5 @@ ffmpeg | |||
| 24 | *.goutput* | 25 | *.goutput* |
| 25 | *.kate-swp | 26 | *.kate-swp |
| 26 | *.code-workspace | 27 | *.code-workspace |
| 28 | .coverage | ||
| 29 | htmlcov/ \ No newline at end of file | ||
diff --git a/pyproject.toml b/pyproject.toml index a245e09..2f0647c 100644 --- a/pyproject.toml +++ b/pyproject.toml | |||
| @@ -6,7 +6,7 @@ build-backend = "uv_build" | |||
| 6 | name = "audio-visualizer-python" | 6 | name = "audio-visualizer-python" |
| 7 | description = "Create audio visualization videos from a GUI or commandline" | 7 | description = "Create audio visualization videos from a GUI or commandline" |
| 8 | readme = "README.md" | 8 | readme = "README.md" |
| 9 | version = "2.2.0" | 9 | version = "2.2.1" |
| 10 | requires-python = ">= 3.12" | 10 | requires-python = ">= 3.12" |
| 11 | license = "MIT" | 11 | license = "MIT" |
| 12 | classifiers=[ | 12 | classifiers=[ |
diff --git a/src/avp/__init__.py b/src/avp/__init__.py index ea32f26..a88bf10 100644 --- a/src/avp/__init__.py +++ b/src/avp/__init__.py | |||
| @@ -3,7 +3,7 @@ import os | |||
| 3 | import logging | 3 | import logging |
| 4 | 4 | ||
| 5 | 5 | ||
| 6 | __version__ = "2.2.0" | 6 | __version__ = "2.2.1" |
| 7 | 7 | ||
| 8 | 8 | ||
| 9 | class Logger(logging.getLoggerClass()): | 9 | class Logger(logging.getLoggerClass()): |
diff --git a/src/avp/component.py b/src/avp/component.py index 6c5e381..5906ab1 100644 --- a/src/avp/component.py +++ b/src/avp/component.py | |||
| @@ -18,6 +18,7 @@ from .toolkit import ( | |||
| 18 | setWidgetValue, | 18 | setWidgetValue, |
| 19 | connectWidget, | 19 | connectWidget, |
| 20 | rgbFromString, | 20 | rgbFromString, |
| 21 | randomColor, | ||
| 21 | blockSignals, | 22 | blockSignals, |
| 22 | ) | 23 | ) |
| 23 | 24 | ||
| @@ -635,9 +636,17 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass): | |||
| 635 | 636 | ||
| 636 | self._colorFuncs = {attr: makeColorFunc(attr) for attr in kwargs[kwarg]} | 637 | self._colorFuncs = {attr: makeColorFunc(attr) for attr in kwargs[kwarg]} |
| 637 | for attr, func in self._colorFuncs.items(): | 638 | for attr, func in self._colorFuncs.items(): |
| 639 | colorText = self._trackedWidgets[attr].text() | ||
| 640 | if colorText == "": | ||
| 641 | rndColor = randomColor() | ||
| 642 | self._trackedWidgets[attr].setText(str(rndColor)[1:-1]) | ||
| 638 | self._colorWidgets[attr].clicked.connect(func) | 643 | self._colorWidgets[attr].clicked.connect(func) |
| 639 | self._colorWidgets[attr].setStyleSheet( | 644 | self._colorWidgets[attr].setStyleSheet( |
| 640 | "QPushButton {" "background-color : #FFFFFF; outline: none; }" | 645 | "QPushButton {" |
| 646 | "background-color : %s; outline: none; }" | ||
| 647 | % QColor( | ||
| 648 | *rgbFromString(colorText) if colorText else rndColor | ||
| 649 | ).name() | ||
| 641 | ) | 650 | ) |
| 642 | 651 | ||
| 643 | if kwarg == "relativeWidgets": | 652 | if kwarg == "relativeWidgets": |
| @@ -798,6 +807,7 @@ class Component(QtCore.QObject, metaclass=ComponentMetaclass): | |||
| 798 | if oldUserValue == newUserValue and oldRelativeVal != newRelativeVal: | 807 | if oldUserValue == newUserValue and oldRelativeVal != newRelativeVal: |
| 799 | # Float changed without pixel value changing, which | 808 | # Float changed without pixel value changing, which |
| 800 | # means the pixel value needs to be updated | 809 | # means the pixel value needs to be updated |
| 810 | # TODO QDoubleSpinBox doesn't work with relativeWidgets because of this | ||
| 801 | log.debug( | 811 | log.debug( |
| 802 | "Updating %s #%s's relative widget: %s", | 812 | "Updating %s #%s's relative widget: %s", |
| 803 | self.__class__.name, | 813 | self.__class__.name, |
diff --git a/src/avp/components/color.py b/src/avp/components/color.py index 1f32c23..cb0960a 100644 --- a/src/avp/components/color.py +++ b/src/avp/components/color.py | |||
| @@ -2,7 +2,7 @@ from PyQt6 import QtGui | |||
| 2 | import logging | 2 | import logging |
| 3 | 3 | ||
| 4 | from ..component import Component | 4 | from ..component import Component |
| 5 | from ..toolkit.frame import BlankFrame, FloodFrame, FramePainter, PaintColor | 5 | from ..toolkit.frame import BlankFrame, FloodFrame, FramePainter |
| 6 | 6 | ||
| 7 | 7 | ||
| 8 | log = logging.getLogger("AVP.Components.Color") | 8 | log = logging.getLogger("AVP.Components.Color") |
| @@ -152,13 +152,13 @@ class Component(Component): | |||
| 152 | elif self.spread == 2: | 152 | elif self.spread == 2: |
| 153 | spread = QtGui.QGradient.Spread.RepeatSpread | 153 | spread = QtGui.QGradient.Spread.RepeatSpread |
| 154 | brush.setSpread(spread) | 154 | brush.setSpread(spread) |
| 155 | brush.setColorAt(0.0, PaintColor(*self.color1)) | 155 | brush.setColorAt(0.0, QtGui.QColor(*self.color1)) |
| 156 | if self.trans: | 156 | if self.trans: |
| 157 | brush.setColorAt(1.0, PaintColor(0, 0, 0, 0)) | 157 | brush.setColorAt(1.0, QtGui.QColor(0, 0, 0, 0)) |
| 158 | elif self.fillType == 1 and self.stretch: | 158 | elif self.fillType == 1 and self.stretch: |
| 159 | brush.setColorAt(0.2, PaintColor(*self.color2)) | 159 | brush.setColorAt(0.2, QtGui.QColor(*self.color2)) |
| 160 | else: | 160 | else: |
| 161 | brush.setColorAt(1.0, PaintColor(*self.color2)) | 161 | brush.setColorAt(1.0, QtGui.QColor(*self.color2)) |
| 162 | image.setBrush(brush) | 162 | image.setBrush(brush) |
| 163 | image.drawRect(self.x, self.y, self.sizeWidth, self.sizeHeight) | 163 | image.drawRect(self.x, self.y, self.sizeWidth, self.sizeHeight) |
| 164 | 164 | ||
diff --git a/src/avp/components/color.ui b/src/avp/components/color.ui index c1713fb..c36bdd8 100644 --- a/src/avp/components/color.ui +++ b/src/avp/components/color.ui | |||
| @@ -74,7 +74,7 @@ | |||
| 74 | </size> | 74 | </size> |
| 75 | </property> | 75 | </property> |
| 76 | <property name="text"> | 76 | <property name="text"> |
| 77 | <string>0,0,0</string> | 77 | <string/> |
| 78 | </property> | 78 | </property> |
| 79 | <property name="maxLength"> | 79 | <property name="maxLength"> |
| 80 | <number>12</number> | 80 | <number>12</number> |
| @@ -84,10 +84,10 @@ | |||
| 84 | <item> | 84 | <item> |
| 85 | <spacer name="horizontalSpacer_9"> | 85 | <spacer name="horizontalSpacer_9"> |
| 86 | <property name="orientation"> | 86 | <property name="orientation"> |
| 87 | <enum>Qt::Horizontal</enum> | 87 | <enum>Qt::Orientation::Horizontal</enum> |
| 88 | </property> | 88 | </property> |
| 89 | <property name="sizeType"> | 89 | <property name="sizeType"> |
| 90 | <enum>QSizePolicy::Fixed</enum> | 90 | <enum>QSizePolicy::Policy::Fixed</enum> |
| 91 | </property> | 91 | </property> |
| 92 | <property name="sizeHint" stdset="0"> | 92 | <property name="sizeHint" stdset="0"> |
| 93 | <size> | 93 | <size> |
| @@ -176,7 +176,7 @@ | |||
| 176 | <string>Width</string> | 176 | <string>Width</string> |
| 177 | </property> | 177 | </property> |
| 178 | <property name="alignment"> | 178 | <property name="alignment"> |
| 179 | <set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set> | 179 | <set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set> |
| 180 | </property> | 180 | </property> |
| 181 | </widget> | 181 | </widget> |
| 182 | </item> | 182 | </item> |
| @@ -246,10 +246,10 @@ | |||
| 246 | <item> | 246 | <item> |
| 247 | <spacer name="horizontalSpacer_7"> | 247 | <spacer name="horizontalSpacer_7"> |
| 248 | <property name="orientation"> | 248 | <property name="orientation"> |
| 249 | <enum>Qt::Horizontal</enum> | 249 | <enum>Qt::Orientation::Horizontal</enum> |
| 250 | </property> | 250 | </property> |
| 251 | <property name="sizeType"> | 251 | <property name="sizeType"> |
| 252 | <enum>QSizePolicy::Fixed</enum> | 252 | <enum>QSizePolicy::Policy::Fixed</enum> |
| 253 | </property> | 253 | </property> |
| 254 | <property name="sizeHint" stdset="0"> | 254 | <property name="sizeHint" stdset="0"> |
| 255 | <size> | 255 | <size> |
| @@ -370,7 +370,7 @@ | |||
| 370 | <number>-1</number> | 370 | <number>-1</number> |
| 371 | </property> | 371 | </property> |
| 372 | <property name="sizeAdjustPolicy"> | 372 | <property name="sizeAdjustPolicy"> |
| 373 | <enum>QComboBox::AdjustToContentsOnFirstShow</enum> | 373 | <enum>QComboBox::SizeAdjustPolicy::AdjustToContentsOnFirstShow</enum> |
| 374 | </property> | 374 | </property> |
| 375 | </widget> | 375 | </widget> |
| 376 | </item> | 376 | </item> |
| @@ -422,10 +422,10 @@ | |||
| 422 | <item> | 422 | <item> |
| 423 | <spacer name="horizontalSpacer_2"> | 423 | <spacer name="horizontalSpacer_2"> |
| 424 | <property name="orientation"> | 424 | <property name="orientation"> |
| 425 | <enum>Qt::Horizontal</enum> | 425 | <enum>Qt::Orientation::Horizontal</enum> |
| 426 | </property> | 426 | </property> |
| 427 | <property name="sizeType"> | 427 | <property name="sizeType"> |
| 428 | <enum>QSizePolicy::Minimum</enum> | 428 | <enum>QSizePolicy::Policy::Minimum</enum> |
| 429 | </property> | 429 | </property> |
| 430 | <property name="sizeHint" stdset="0"> | 430 | <property name="sizeHint" stdset="0"> |
| 431 | <size> | 431 | <size> |
| @@ -461,7 +461,7 @@ | |||
| 461 | <x>-1</x> | 461 | <x>-1</x> |
| 462 | <y>0</y> | 462 | <y>0</y> |
| 463 | <width>561</width> | 463 | <width>561</width> |
| 464 | <height>31</height> | 464 | <height>34</height> |
| 465 | </rect> | 465 | </rect> |
| 466 | </property> | 466 | </property> |
| 467 | <layout class="QHBoxLayout" name="horizontalLayout"> | 467 | <layout class="QHBoxLayout" name="horizontalLayout"> |
| @@ -503,7 +503,7 @@ | |||
| 503 | <string>End</string> | 503 | <string>End</string> |
| 504 | </property> | 504 | </property> |
| 505 | <property name="alignment"> | 505 | <property name="alignment"> |
| 506 | <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | 506 | <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> |
| 507 | </property> | 507 | </property> |
| 508 | </widget> | 508 | </widget> |
| 509 | </item> | 509 | </item> |
| @@ -523,7 +523,7 @@ | |||
| 523 | <item> | 523 | <item> |
| 524 | <spacer name="horizontalSpacer"> | 524 | <spacer name="horizontalSpacer"> |
| 525 | <property name="orientation"> | 525 | <property name="orientation"> |
| 526 | <enum>Qt::Horizontal</enum> | 526 | <enum>Qt::Orientation::Horizontal</enum> |
| 527 | </property> | 527 | </property> |
| 528 | <property name="sizeHint" stdset="0"> | 528 | <property name="sizeHint" stdset="0"> |
| 529 | <size> | 529 | <size> |
| @@ -543,7 +543,7 @@ | |||
| 543 | <x>-1</x> | 543 | <x>-1</x> |
| 544 | <y>-1</y> | 544 | <y>-1</y> |
| 545 | <width>561</width> | 545 | <width>561</width> |
| 546 | <height>31</height> | 546 | <height>34</height> |
| 547 | </rect> | 547 | </rect> |
| 548 | </property> | 548 | </property> |
| 549 | <layout class="QHBoxLayout" name="horizontalLayout_3"> | 549 | <layout class="QHBoxLayout" name="horizontalLayout_3"> |
| @@ -559,7 +559,7 @@ | |||
| 559 | <string>Start</string> | 559 | <string>Start</string> |
| 560 | </property> | 560 | </property> |
| 561 | <property name="alignment"> | 561 | <property name="alignment"> |
| 562 | <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | 562 | <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> |
| 563 | </property> | 563 | </property> |
| 564 | </widget> | 564 | </widget> |
| 565 | </item> | 565 | </item> |
| @@ -588,7 +588,7 @@ | |||
| 588 | <string>End</string> | 588 | <string>End</string> |
| 589 | </property> | 589 | </property> |
| 590 | <property name="alignment"> | 590 | <property name="alignment"> |
| 591 | <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | 591 | <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> |
| 592 | </property> | 592 | </property> |
| 593 | </widget> | 593 | </widget> |
| 594 | </item> | 594 | </item> |
| @@ -617,14 +617,14 @@ | |||
| 617 | <string>Centre</string> | 617 | <string>Centre</string> |
| 618 | </property> | 618 | </property> |
| 619 | <property name="alignment"> | 619 | <property name="alignment"> |
| 620 | <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | 620 | <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> |
| 621 | </property> | 621 | </property> |
| 622 | </widget> | 622 | </widget> |
| 623 | </item> | 623 | </item> |
| 624 | <item> | 624 | <item> |
| 625 | <widget class="QSpinBox" name="spinBox_radialGradient_spread"> | 625 | <widget class="QSpinBox" name="spinBox_radialGradient_spread"> |
| 626 | <property name="buttonSymbols"> | 626 | <property name="buttonSymbols"> |
| 627 | <enum>QAbstractSpinBox::PlusMinus</enum> | 627 | <enum>QAbstractSpinBox::ButtonSymbols::PlusMinus</enum> |
| 628 | </property> | 628 | </property> |
| 629 | <property name="minimum"> | 629 | <property name="minimum"> |
| 630 | <number>-10000</number> | 630 | <number>-10000</number> |
| @@ -640,7 +640,7 @@ | |||
| 640 | <item> | 640 | <item> |
| 641 | <spacer name="horizontalSpacer_3"> | 641 | <spacer name="horizontalSpacer_3"> |
| 642 | <property name="orientation"> | 642 | <property name="orientation"> |
| 643 | <enum>Qt::Horizontal</enum> | 643 | <enum>Qt::Orientation::Horizontal</enum> |
| 644 | </property> | 644 | </property> |
| 645 | <property name="sizeHint" stdset="0"> | 645 | <property name="sizeHint" stdset="0"> |
| 646 | <size> | 646 | <size> |
diff --git a/src/avp/components/image.py b/src/avp/components/image.py index bada15f..e012cec 100644 --- a/src/avp/components/image.py +++ b/src/avp/components/image.py | |||
| @@ -4,13 +4,13 @@ import os | |||
| 4 | from copy import copy | 4 | from copy import copy |
| 5 | 5 | ||
| 6 | from ..component import Component | 6 | from ..component import Component |
| 7 | from ..toolkit.frame import BlankFrame | 7 | from ..toolkit.frame import BlankFrame, addShadow |
| 8 | from .original import Component as Visualizer | 8 | from ..toolkit.visualizer import createSpectrumArray |
| 9 | 9 | ||
| 10 | 10 | ||
| 11 | class Component(Component): | 11 | class Component(Component): |
| 12 | name = "Image" | 12 | name = "Image" |
| 13 | version = "2.0.0" | 13 | version = "2.1.0" |
| 14 | 14 | ||
| 15 | def widget(self, *args): | 15 | def widget(self, *args): |
| 16 | super().widget(*args) | 16 | super().widget(*args) |
| @@ -35,6 +35,7 @@ class Component(Component): | |||
| 35 | "mirror": self.page.checkBox_mirror, | 35 | "mirror": self.page.checkBox_mirror, |
| 36 | "respondToAudio": self.page.checkBox_respondToAudio, | 36 | "respondToAudio": self.page.checkBox_respondToAudio, |
| 37 | "sensitivity": self.page.spinBox_sensitivity, | 37 | "sensitivity": self.page.spinBox_sensitivity, |
| 38 | "shadow": self.page.checkBox_shadow, | ||
| 38 | }, | 39 | }, |
| 39 | presetNames={ | 40 | presetNames={ |
| 40 | "imagePath": "image", | 41 | "imagePath": "image", |
| @@ -75,31 +76,16 @@ class Component(Component): | |||
| 75 | # Trigger creation of new base image | 76 | # Trigger creation of new base image |
| 76 | self.existingImage = None | 77 | self.existingImage = None |
| 77 | 78 | ||
| 78 | smoothConstantDown = 0.08 + 0 | 79 | self.spectrumArray = createSpectrumArray( |
| 79 | smoothConstantUp = 0.8 - 0 | 80 | self, |
| 80 | self.lastSpectrum = None | 81 | self.completeAudioArray, |
| 81 | self.spectrumArray = {} | 82 | self.sampleSize, |
| 82 | 83 | 0.08, | |
| 83 | for i in range(0, len(self.completeAudioArray), self.sampleSize): | 84 | 0.8, |
| 84 | if self.canceled: | 85 | self.sensitivity, |
| 85 | break | 86 | self.progressBarUpdate, |
| 86 | self.lastSpectrum = Visualizer.transformData( | 87 | self.progressBarSetText, |
| 87 | i, | 88 | ) |
| 88 | self.completeAudioArray, | ||
| 89 | self.sampleSize, | ||
| 90 | smoothConstantDown, | ||
| 91 | smoothConstantUp, | ||
| 92 | self.lastSpectrum, | ||
| 93 | self.sensitivity, | ||
| 94 | ) | ||
| 95 | self.spectrumArray[i] = copy(self.lastSpectrum) | ||
| 96 | |||
| 97 | progress = int(100 * (i / len(self.completeAudioArray))) | ||
| 98 | if progress >= 100: | ||
| 99 | progress = 100 | ||
| 100 | pStr = "Analyzing audio: " + str(progress) + "%" | ||
| 101 | self.progressBarSetText.emit(pStr) | ||
| 102 | self.progressBarUpdate.emit(int(progress)) | ||
| 103 | 89 | ||
| 104 | def frameRender(self, frameNo): | 90 | def frameRender(self, frameNo): |
| 105 | return self.drawFrame( | 91 | return self.drawFrame( |
| @@ -139,9 +125,16 @@ class Component(Component): | |||
| 139 | self.existingImage = image | 125 | self.existingImage = image |
| 140 | 126 | ||
| 141 | # Respond to audio | 127 | # Respond to audio |
| 128 | resolutionFactor = height / 1080 | ||
| 129 | shadX = int(resolutionFactor * 1) | ||
| 130 | shadY = int(resolutionFactor * -1) | ||
| 131 | shadBlur = resolutionFactor * 3.50 | ||
| 142 | scale = 0 | 132 | scale = 0 |
| 143 | if dynamicScale is not None: | 133 | if dynamicScale is not None: |
| 144 | scale = dynamicScale[36 * 4] / 4 | 134 | scale = dynamicScale[36 * 4] / 4 |
| 135 | shadX += int((scale / 4) * resolutionFactor) | ||
| 136 | shadY += int((scale / 2) * resolutionFactor) | ||
| 137 | shadBlur += (scale / 8) * resolutionFactor | ||
| 145 | image = ImageOps.contain( | 138 | image = ImageOps.contain( |
| 146 | image, | 139 | image, |
| 147 | ( | 140 | ( |
| @@ -161,6 +154,8 @@ class Component(Component): | |||
| 161 | ) | 154 | ) |
| 162 | if self.rotate != 0: | 155 | if self.rotate != 0: |
| 163 | frame = frame.rotate(self.rotate) | 156 | frame = frame.rotate(self.rotate) |
| 157 | if self.shadow: | ||
| 158 | frame = addShadow(frame, shadBlur, shadX, shadY) | ||
| 164 | 159 | ||
| 165 | return frame | 160 | return frame |
| 166 | 161 | ||
diff --git a/src/avp/components/image.ui b/src/avp/components/image.ui index 72593a3..b53c4b0 100644 --- a/src/avp/components/image.ui +++ b/src/avp/components/image.ui | |||
| @@ -307,6 +307,16 @@ | |||
| 307 | </spacer> | 307 | </spacer> |
| 308 | </item> | 308 | </item> |
| 309 | <item> | 309 | <item> |
| 310 | <widget class="QCheckBox" name="checkBox_shadow"> | ||
| 311 | <property name="layoutDirection"> | ||
| 312 | <enum>Qt::LayoutDirection::RightToLeft</enum> | ||
| 313 | </property> | ||
| 314 | <property name="text"> | ||
| 315 | <string>Shadow</string> | ||
| 316 | </property> | ||
| 317 | </widget> | ||
| 318 | </item> | ||
| 319 | <item> | ||
| 310 | <widget class="QLabel" name="label_3"> | 320 | <widget class="QLabel" name="label_3"> |
| 311 | <property name="sizePolicy"> | 321 | <property name="sizePolicy"> |
| 312 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | 322 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> |
diff --git a/src/avp/components/life.py b/src/avp/components/life.py index 9e5e202..a062617 100644 --- a/src/avp/components/life.py +++ b/src/avp/components/life.py | |||
| @@ -8,8 +8,8 @@ import logging | |||
| 8 | 8 | ||
| 9 | 9 | ||
| 10 | from ..component import Component | 10 | from ..component import Component |
| 11 | from ..toolkit.frame import BlankFrame, scale | 11 | from ..toolkit.frame import BlankFrame, scale, addShadow |
| 12 | from .original import Component as Visualizer | 12 | from ..toolkit.visualizer import createSpectrumArray |
| 13 | 13 | ||
| 14 | 14 | ||
| 15 | log = logging.getLogger("AVP.Component.Life") | 15 | log = logging.getLogger("AVP.Component.Life") |
| @@ -17,7 +17,7 @@ log = logging.getLogger("AVP.Component.Life") | |||
| 17 | 17 | ||
| 18 | class Component(Component): | 18 | class Component(Component): |
| 19 | name = "Conway's Game of Life" | 19 | name = "Conway's Game of Life" |
| 20 | version = "2.0.0" | 20 | version = "2.0.1" |
| 21 | 21 | ||
| 22 | def widget(self, *args): | 22 | def widget(self, *args): |
| 23 | super().widget(*args) | 23 | super().widget(*args) |
| @@ -27,26 +27,26 @@ class Component(Component): | |||
| 27 | # https://conwaylife.com/wiki/Queen_bee_shuttle | 27 | # https://conwaylife.com/wiki/Queen_bee_shuttle |
| 28 | self.startingGrid = set( | 28 | self.startingGrid = set( |
| 29 | [ | 29 | [ |
| 30 | (3, 7), | 30 | (3, 11), |
| 31 | (3, 8), | 31 | (3, 12), |
| 32 | (4, 7), | 32 | (4, 11), |
| 33 | (4, 8), | 33 | (4, 12), |
| 34 | (8, 7), | 34 | (8, 11), |
| 35 | (9, 6), | 35 | (9, 10), |
| 36 | (9, 8), | 36 | (9, 12), |
| 37 | (10, 5), | ||
| 38 | (10, 9), | 37 | (10, 9), |
| 39 | (11, 6), | 38 | (10, 13), |
| 40 | (11, 7), | 39 | (11, 10), |
| 41 | (11, 8), | 40 | (11, 11), |
| 42 | (12, 4), | 41 | (11, 12), |
| 43 | (12, 5), | 42 | (12, 8), |
| 44 | (12, 9), | 43 | (12, 9), |
| 45 | (12, 10), | 44 | (12, 13), |
| 46 | (23, 6), | 45 | (12, 14), |
| 47 | (23, 7), | 46 | (23, 10), |
| 48 | (24, 6), | 47 | (23, 11), |
| 49 | (24, 7), | 48 | (24, 10), |
| 49 | (24, 11), | ||
| 50 | ] | 50 | ] |
| 51 | ) | 51 | ) |
| 52 | 52 | ||
| @@ -163,41 +163,27 @@ class Component(Component): | |||
| 163 | def previewRender(self): | 163 | def previewRender(self): |
| 164 | image = self.drawGrid(self.startingGrid, self.color) | 164 | image = self.drawGrid(self.startingGrid, self.color) |
| 165 | image = self.addKaleidoscopeEffect(image) | 165 | image = self.addKaleidoscopeEffect(image) |
| 166 | image = self.addShadow(image) | 166 | if self.shadow: |
| 167 | image = addShadow(image, 5.00, -2, 2) | ||
| 167 | image = self.addGridLines(image) | 168 | image = self.addGridLines(image) |
| 168 | return image | 169 | return image |
| 169 | 170 | ||
| 170 | def preFrameRender(self, *args, **kwargs): | 171 | def preFrameRender(self, *args, **kwargs): |
| 171 | super().preFrameRender(*args, **kwargs) | 172 | super().preFrameRender(*args, **kwargs) |
| 172 | self.tickGrids = {0: self.startingGrid} | 173 | self.tickGrids = {0: self.startingGrid} |
| 173 | |||
| 174 | smoothConstantDown = 0.08 + 0 | ||
| 175 | smoothConstantUp = 0.8 - 0 | ||
| 176 | self.lastSpectrum = None | ||
| 177 | self.spectrumArray = {} | ||
| 178 | if self.sensitivity == 0: | 174 | if self.sensitivity == 0: |
| 179 | return | 175 | return |
| 180 | 176 | ||
| 181 | for i in range(0, len(self.completeAudioArray), self.sampleSize): | 177 | self.spectrumArray = createSpectrumArray( |
| 182 | if self.canceled: | 178 | self, |
| 183 | break | 179 | self.completeAudioArray, |
| 184 | self.lastSpectrum = Visualizer.transformData( | 180 | self.sampleSize, |
| 185 | i, | 181 | 0.08, |
| 186 | self.completeAudioArray, | 182 | 0.8, |
| 187 | self.sampleSize, | 183 | 20, |
| 188 | smoothConstantDown, | 184 | self.progressBarUpdate, |
| 189 | smoothConstantUp, | 185 | self.progressBarSetText, |
| 190 | self.lastSpectrum, | 186 | ) |
| 191 | self.sensitivity, | ||
| 192 | ) | ||
| 193 | self.spectrumArray[i] = copy(self.lastSpectrum) | ||
| 194 | |||
| 195 | progress = int(100 * (i / len(self.completeAudioArray))) | ||
| 196 | if progress >= 100: | ||
| 197 | progress = 100 | ||
| 198 | pStr = "Analyzing audio: " + str(progress) + "%" | ||
| 199 | self.progressBarSetText.emit(pStr) | ||
| 200 | self.progressBarUpdate.emit(int(progress)) | ||
| 201 | 187 | ||
| 202 | def properties(self): | 188 | def properties(self): |
| 203 | if self.customImg and (not self.image or not os.path.exists(self.image)): | 189 | if self.customImg and (not self.image or not os.path.exists(self.image)): |
| @@ -256,21 +242,11 @@ class Component(Component): | |||
| 256 | if not self.customImg: | 242 | if not self.customImg: |
| 257 | image = Image.alpha_composite(previousGridImage, image) | 243 | image = Image.alpha_composite(previousGridImage, image) |
| 258 | image = self.addKaleidoscopeEffect(image) | 244 | image = self.addKaleidoscopeEffect(image) |
| 259 | image = self.addShadow(image) | 245 | if self.shadow: |
| 246 | image = addShadow(image, 5.00, -2, 2) | ||
| 260 | image = self.addGridLines(image) | 247 | image = self.addGridLines(image) |
| 261 | return image | 248 | return image |
| 262 | 249 | ||
| 263 | def addShadow(self, frame): | ||
| 264 | if not self.shadow: | ||
| 265 | return frame | ||
| 266 | |||
| 267 | shadImg = ImageEnhance.Contrast(frame).enhance(0.0) | ||
| 268 | shadImg = shadImg.filter(ImageFilter.GaussianBlur(5.00)) | ||
| 269 | shadImg = ImageChops.offset(shadImg, -2, 2) | ||
| 270 | shadImg.paste(frame, box=(0, 0), mask=frame) | ||
| 271 | frame = shadImg | ||
| 272 | return frame | ||
| 273 | |||
| 274 | def addGridLines(self, frame): | 250 | def addGridLines(self, frame): |
| 275 | if not self.showGrid: | 251 | if not self.showGrid: |
| 276 | return frame | 252 | return frame |
| @@ -299,11 +275,6 @@ class Component(Component): | |||
| 299 | flippedImage = frame.transpose(Image.Transpose.FLIP_LEFT_RIGHT) | 275 | flippedImage = frame.transpose(Image.Transpose.FLIP_LEFT_RIGHT) |
| 300 | frame.paste(flippedImage, (0, 0), mask=flippedImage) | 276 | frame.paste(flippedImage, (0, 0), mask=flippedImage) |
| 301 | 277 | ||
| 302 | flippedImage = frame.transpose(Image.Transpose.ROTATE_90) | ||
| 303 | frame.paste(flippedImage, (0, 0), mask=flippedImage) | ||
| 304 | |||
| 305 | flippedImage = frame.transpose(Image.Transpose.ROTATE_270) | ||
| 306 | frame.paste(flippedImage, (0, 0), mask=flippedImage) | ||
| 307 | return frame | 278 | return frame |
| 308 | 279 | ||
| 309 | def drawGrid(self, grid, color, spectrumData=None, didntChange=None): | 280 | def drawGrid(self, grid, color, spectrumData=None, didntChange=None): |
| @@ -506,10 +477,10 @@ class Component(Component): | |||
| 506 | 477 | ||
| 507 | for x, y in grid: | 478 | for x, y in grid: |
| 508 | drawPtX = x * self.pxWidth | 479 | drawPtX = x * self.pxWidth |
| 509 | if drawPtX > self.width: | 480 | if drawPtX > self.width or drawPtX + self.pxWidth < 0: |
| 510 | continue | 481 | continue |
| 511 | drawPtY = y * self.pxHeight | 482 | drawPtY = y * self.pxHeight |
| 512 | if drawPtY > self.height: | 483 | if drawPtY > self.height or drawPtY + self.pxHeight < 0: |
| 513 | continue | 484 | continue |
| 514 | 485 | ||
| 515 | audioMorphWidth = ( | 486 | audioMorphWidth = ( |
diff --git a/src/avp/components/life.ui b/src/avp/components/life.ui index a0c8999..0070fa4 100644 --- a/src/avp/components/life.ui +++ b/src/avp/components/life.ui | |||
| @@ -68,7 +68,7 @@ | |||
| 68 | </size> | 68 | </size> |
| 69 | </property> | 69 | </property> |
| 70 | <property name="text"> | 70 | <property name="text"> |
| 71 | <string>255,255,255</string> | 71 | <string></string> |
| 72 | </property> | 72 | </property> |
| 73 | </widget> | 73 | </widget> |
| 74 | </item> | 74 | </item> |
diff --git a/src/avp/components/original.py b/src/avp/components/original.py index 64eba4d..0da78dc 100644 --- a/src/avp/components/original.py +++ b/src/avp/components/original.py | |||
| @@ -4,11 +4,12 @@ from copy import copy | |||
| 4 | 4 | ||
| 5 | from ..component import Component | 5 | from ..component import Component |
| 6 | from ..toolkit.frame import BlankFrame | 6 | from ..toolkit.frame import BlankFrame |
| 7 | from ..toolkit.visualizer import createSpectrumArray | ||
| 7 | 8 | ||
| 8 | 9 | ||
| 9 | class Component(Component): | 10 | class Component(Component): |
| 10 | name = "Classic Visualizer" | 11 | name = "Classic Visualizer" |
| 11 | version = "1.0.0" | 12 | version = "1.1.0" |
| 12 | 13 | ||
| 13 | def names(*args): | 14 | def names(*args): |
| 14 | return ["Original Audio Visualization"] | 15 | return ["Original Audio Visualization"] |
| @@ -18,6 +19,7 @@ class Component(Component): | |||
| 18 | 19 | ||
| 19 | def widget(self, *args): | 20 | def widget(self, *args): |
| 20 | self.scale = 20 | 21 | self.scale = 20 |
| 22 | self.bars = 63 | ||
| 21 | self.y = 0 | 23 | self.y = 0 |
| 22 | super().widget(*args) | 24 | super().widget(*args) |
| 23 | 25 | ||
| @@ -27,15 +29,14 @@ class Component(Component): | |||
| 27 | self.page.comboBox_visLayout.addItem("Top") | 29 | self.page.comboBox_visLayout.addItem("Top") |
| 28 | self.page.comboBox_visLayout.setCurrentIndex(0) | 30 | self.page.comboBox_visLayout.setCurrentIndex(0) |
| 29 | 31 | ||
| 30 | self.page.lineEdit_visColor.setText("255,255,255") | ||
| 31 | |||
| 32 | self.trackWidgets( | 32 | self.trackWidgets( |
| 33 | { | 33 | { |
| 34 | "visColor": self.page.lineEdit_visColor, | 34 | "visColor": self.page.lineEdit_visColor, |
| 35 | "layout": self.page.comboBox_visLayout, | 35 | "layout": self.page.comboBox_visLayout, |
| 36 | "scale": self.page.spinBox_scale, | 36 | "scale": self.page.spinBox_scale, |
| 37 | "y": self.page.spinBox_y, | 37 | "y": self.page.spinBox_y, |
| 38 | "smooth": self.page.spinBox_smooth, | 38 | "smooth": self.page.spinBox_sensitivity, |
| 39 | "bars": self.page.spinBox_bars, | ||
| 39 | }, | 40 | }, |
| 40 | colorWidgets={ | 41 | colorWidgets={ |
| 41 | "visColor": self.page.pushButton_visColor, | 42 | "visColor": self.page.pushButton_visColor, |
| @@ -59,29 +60,16 @@ class Component(Component): | |||
| 59 | super().preFrameRender(**kwargs) | 60 | super().preFrameRender(**kwargs) |
| 60 | smoothConstantDown = 0.08 if not self.smooth else self.smooth / 15 | 61 | smoothConstantDown = 0.08 if not self.smooth else self.smooth / 15 |
| 61 | smoothConstantUp = 0.8 if not self.smooth else self.smooth / 15 | 62 | smoothConstantUp = 0.8 if not self.smooth else self.smooth / 15 |
| 62 | self.lastSpectrum = None | 63 | self.spectrumArray = createSpectrumArray( |
| 63 | self.spectrumArray = {} | 64 | self, |
| 64 | 65 | self.completeAudioArray, | |
| 65 | for i in range(0, len(self.completeAudioArray), self.sampleSize): | 66 | self.sampleSize, |
| 66 | if self.canceled: | 67 | smoothConstantDown, |
| 67 | break | 68 | smoothConstantUp, |
| 68 | self.lastSpectrum = self.transformData( | 69 | self.scale, |
| 69 | i, | 70 | self.progressBarUpdate, |
| 70 | self.completeAudioArray, | 71 | self.progressBarSetText, |
| 71 | self.sampleSize, | 72 | ) |
| 72 | smoothConstantDown, | ||
| 73 | smoothConstantUp, | ||
| 74 | self.lastSpectrum, | ||
| 75 | self.scale, | ||
| 76 | ) | ||
| 77 | self.spectrumArray[i] = copy(self.lastSpectrum) | ||
| 78 | |||
| 79 | progress = int(100 * (i / len(self.completeAudioArray))) | ||
| 80 | if progress >= 100: | ||
| 81 | progress = 100 | ||
| 82 | pStr = "Analyzing audio: " + str(progress) + "%" | ||
| 83 | self.progressBarSetText.emit(pStr) | ||
| 84 | self.progressBarUpdate.emit(int(progress)) | ||
| 85 | 73 | ||
| 86 | def frameRender(self, frameNo): | 74 | def frameRender(self, frameNo): |
| 87 | arrayNo = frameNo * self.sampleSize | 75 | arrayNo = frameNo * self.sampleSize |
| @@ -93,60 +81,10 @@ class Component(Component): | |||
| 93 | self.layout, | 81 | self.layout, |
| 94 | ) | 82 | ) |
| 95 | 83 | ||
| 96 | @staticmethod | ||
| 97 | def transformData( | ||
| 98 | i, | ||
| 99 | completeAudioArray, | ||
| 100 | sampleSize, | ||
| 101 | smoothConstantDown, | ||
| 102 | smoothConstantUp, | ||
| 103 | lastSpectrum, | ||
| 104 | scale, | ||
| 105 | ): | ||
| 106 | if len(completeAudioArray) < (i + sampleSize): | ||
| 107 | sampleSize = len(completeAudioArray) - i | ||
| 108 | |||
| 109 | window = numpy.hanning(sampleSize) | ||
| 110 | data = completeAudioArray[i : i + sampleSize][::1] * window | ||
| 111 | paddedSampleSize = 2048 | ||
| 112 | paddedData = numpy.pad(data, (0, paddedSampleSize - sampleSize), "constant") | ||
| 113 | spectrum = numpy.fft.fft(paddedData) | ||
| 114 | sample_rate = 44100 | ||
| 115 | frequencies = numpy.fft.fftfreq(len(spectrum), 1.0 / sample_rate) | ||
| 116 | |||
| 117 | y = abs(spectrum[0 : int(paddedSampleSize / 2) - 1]) | ||
| 118 | |||
| 119 | # filter the noise away | ||
| 120 | # y[y<80] = 0 | ||
| 121 | |||
| 122 | with numpy.errstate(divide="ignore"): | ||
| 123 | y = scale * numpy.log10(y) | ||
| 124 | |||
| 125 | y[numpy.isinf(y)] = 0 | ||
| 126 | |||
| 127 | if lastSpectrum is not None: | ||
| 128 | lastSpectrum[y < lastSpectrum] = y[ | ||
| 129 | y < lastSpectrum | ||
| 130 | ] * smoothConstantDown + lastSpectrum[y < lastSpectrum] * ( | ||
| 131 | 1 - smoothConstantDown | ||
| 132 | ) | ||
| 133 | |||
| 134 | lastSpectrum[y >= lastSpectrum] = y[ | ||
| 135 | y >= lastSpectrum | ||
| 136 | ] * smoothConstantUp + lastSpectrum[y >= lastSpectrum] * ( | ||
| 137 | 1 - smoothConstantUp | ||
| 138 | ) | ||
| 139 | else: | ||
| 140 | lastSpectrum = y | ||
| 141 | |||
| 142 | x = frequencies[0 : int(paddedSampleSize / 2) - 1] | ||
| 143 | |||
| 144 | return lastSpectrum | ||
| 145 | |||
| 146 | def drawBars(self, width, height, spectrum, color, layout): | 84 | def drawBars(self, width, height, spectrum, color, layout): |
| 147 | bigYCoord = height - height / 8 | 85 | bigYCoord = height - height / 8 |
| 148 | smallYCoord = height / 1200 | 86 | smallYCoord = height / 1200 |
| 149 | bigXCoord = width / 64 | 87 | bigXCoord = width / (self.bars + 1) |
| 150 | middleXCoord = bigXCoord / 2 | 88 | middleXCoord = bigXCoord / 2 |
| 151 | smallXCoord = bigXCoord / 4 | 89 | smallXCoord = bigXCoord / 4 |
| 152 | 90 | ||
| @@ -155,7 +93,7 @@ class Component(Component): | |||
| 155 | r, g, b = color | 93 | r, g, b = color |
| 156 | color2 = (r, g, b, 125) | 94 | color2 = (r, g, b, 125) |
| 157 | 95 | ||
| 158 | for i in range(0, 63): | 96 | for i in range(self.bars): |
| 159 | x0 = middleXCoord + i * bigXCoord | 97 | x0 = middleXCoord + i * bigXCoord |
| 160 | y0 = bigYCoord + smallXCoord | 98 | y0 = bigYCoord + smallXCoord |
| 161 | y1 = bigYCoord + smallXCoord - spectrum[i * 4] * smallYCoord - middleXCoord | 99 | y1 = bigYCoord + smallXCoord - spectrum[i * 4] * smallYCoord - middleXCoord |
diff --git a/src/avp/components/original.ui b/src/avp/components/original.ui index c7b7e22..8dbdaa2 100644 --- a/src/avp/components/original.ui +++ b/src/avp/components/original.ui | |||
| @@ -44,10 +44,10 @@ | |||
| 44 | <item> | 44 | <item> |
| 45 | <spacer name="horizontalSpacer_5"> | 45 | <spacer name="horizontalSpacer_5"> |
| 46 | <property name="orientation"> | 46 | <property name="orientation"> |
| 47 | <enum>Qt::Horizontal</enum> | 47 | <enum>Qt::Orientation::Horizontal</enum> |
| 48 | </property> | 48 | </property> |
| 49 | <property name="sizeType"> | 49 | <property name="sizeType"> |
| 50 | <enum>QSizePolicy::Fixed</enum> | 50 | <enum>QSizePolicy::Policy::Fixed</enum> |
| 51 | </property> | 51 | </property> |
| 52 | <property name="sizeHint" stdset="0"> | 52 | <property name="sizeHint" stdset="0"> |
| 53 | <size> | 53 | <size> |
| @@ -84,15 +84,19 @@ | |||
| 84 | </widget> | 84 | </widget> |
| 85 | </item> | 85 | </item> |
| 86 | <item> | 86 | <item> |
| 87 | <widget class="QLineEdit" name="lineEdit_visColor"/> | 87 | <widget class="QLineEdit" name="lineEdit_visColor"> |
| 88 | <property name="text"> | ||
| 89 | <string></string> | ||
| 90 | </property> | ||
| 91 | </widget> | ||
| 88 | </item> | 92 | </item> |
| 89 | <item> | 93 | <item> |
| 90 | <spacer name="horizontalSpacer_4"> | 94 | <spacer name="horizontalSpacer_4"> |
| 91 | <property name="orientation"> | 95 | <property name="orientation"> |
| 92 | <enum>Qt::Horizontal</enum> | 96 | <enum>Qt::Orientation::Horizontal</enum> |
| 93 | </property> | 97 | </property> |
| 94 | <property name="sizeType"> | 98 | <property name="sizeType"> |
| 95 | <enum>QSizePolicy::Fixed</enum> | 99 | <enum>QSizePolicy::Policy::Fixed</enum> |
| 96 | </property> | 100 | </property> |
| 97 | <property name="sizeHint" stdset="0"> | 101 | <property name="sizeHint" stdset="0"> |
| 98 | <size> | 102 | <size> |
| @@ -112,7 +116,7 @@ | |||
| 112 | <item> | 116 | <item> |
| 113 | <widget class="QSpinBox" name="spinBox_y"> | 117 | <widget class="QSpinBox" name="spinBox_y"> |
| 114 | <property name="buttonSymbols"> | 118 | <property name="buttonSymbols"> |
| 115 | <enum>QAbstractSpinBox::UpDownArrows</enum> | 119 | <enum>QAbstractSpinBox::ButtonSymbols::UpDownArrows</enum> |
| 116 | </property> | 120 | </property> |
| 117 | <property name="minimum"> | 121 | <property name="minimum"> |
| 118 | <number>-5000</number> | 122 | <number>-5000</number> |
| @@ -131,7 +135,7 @@ | |||
| 131 | <item> | 135 | <item> |
| 132 | <spacer name="horizontalSpacer_2"> | 136 | <spacer name="horizontalSpacer_2"> |
| 133 | <property name="orientation"> | 137 | <property name="orientation"> |
| 134 | <enum>Qt::Horizontal</enum> | 138 | <enum>Qt::Orientation::Horizontal</enum> |
| 135 | </property> | 139 | </property> |
| 136 | <property name="sizeHint" stdset="0"> | 140 | <property name="sizeHint" stdset="0"> |
| 137 | <size> | 141 | <size> |
| @@ -158,7 +162,7 @@ | |||
| 158 | <item> | 162 | <item> |
| 159 | <widget class="QSpinBox" name="spinBox_scale"> | 163 | <widget class="QSpinBox" name="spinBox_scale"> |
| 160 | <property name="buttonSymbols"> | 164 | <property name="buttonSymbols"> |
| 161 | <enum>QAbstractSpinBox::PlusMinus</enum> | 165 | <enum>QAbstractSpinBox::ButtonSymbols::PlusMinus</enum> |
| 162 | </property> | 166 | </property> |
| 163 | <property name="minimum"> | 167 | <property name="minimum"> |
| 164 | <number>1</number> | 168 | <number>1</number> |
| @@ -169,12 +173,26 @@ | |||
| 169 | </widget> | 173 | </widget> |
| 170 | </item> | 174 | </item> |
| 171 | <item> | 175 | <item> |
| 176 | <widget class="QLabel" name="label_sensitivity"> | ||
| 177 | <property name="text"> | ||
| 178 | <string>Sensitivity</string> | ||
| 179 | </property> | ||
| 180 | </widget> | ||
| 181 | </item> | ||
| 182 | <item> | ||
| 183 | <widget class="QSpinBox" name="spinBox_sensitivity"> | ||
| 184 | <property name="maximum"> | ||
| 185 | <number>5</number> | ||
| 186 | </property> | ||
| 187 | </widget> | ||
| 188 | </item> | ||
| 189 | <item> | ||
| 172 | <spacer name="horizontalSpacer_3"> | 190 | <spacer name="horizontalSpacer_3"> |
| 173 | <property name="orientation"> | 191 | <property name="orientation"> |
| 174 | <enum>Qt::Horizontal</enum> | 192 | <enum>Qt::Orientation::Horizontal</enum> |
| 175 | </property> | 193 | </property> |
| 176 | <property name="sizeType"> | 194 | <property name="sizeType"> |
| 177 | <enum>QSizePolicy::Expanding</enum> | 195 | <enum>QSizePolicy::Policy::Expanding</enum> |
| 178 | </property> | 196 | </property> |
| 179 | <property name="sizeHint" stdset="0"> | 197 | <property name="sizeHint" stdset="0"> |
| 180 | <size> | 198 | <size> |
| @@ -189,29 +207,35 @@ | |||
| 189 | <item> | 207 | <item> |
| 190 | <layout class="QHBoxLayout" name="horizontalLayout"> | 208 | <layout class="QHBoxLayout" name="horizontalLayout"> |
| 191 | <property name="sizeConstraint"> | 209 | <property name="sizeConstraint"> |
| 192 | <enum>QLayout::SetDefaultConstraint</enum> | 210 | <enum>QLayout::SizeConstraint::SetDefaultConstraint</enum> |
| 193 | </property> | 211 | </property> |
| 194 | <property name="leftMargin"> | 212 | <property name="leftMargin"> |
| 195 | <number>4</number> | 213 | <number>4</number> |
| 196 | </property> | 214 | </property> |
| 197 | <item> | 215 | <item> |
| 198 | <widget class="QLabel" name="label_smooth"> | 216 | <widget class="QLabel" name="label_bars"> |
| 199 | <property name="text"> | 217 | <property name="text"> |
| 200 | <string>Sensitivity</string> | 218 | <string>Bars</string> |
| 201 | </property> | 219 | </property> |
| 202 | </widget> | 220 | </widget> |
| 203 | </item> | 221 | </item> |
| 204 | <item> | 222 | <item> |
| 205 | <widget class="QSpinBox" name="spinBox_smooth"> | 223 | <widget class="QSpinBox" name="spinBox_bars"> |
| 224 | <property name="minimum"> | ||
| 225 | <number>63</number> | ||
| 226 | </property> | ||
| 206 | <property name="maximum"> | 227 | <property name="maximum"> |
| 207 | <number>5</number> | 228 | <number>64</number> |
| 229 | </property> | ||
| 230 | <property name="value"> | ||
| 231 | <number>63</number> | ||
| 208 | </property> | 232 | </property> |
| 209 | </widget> | 233 | </widget> |
| 210 | </item> | 234 | </item> |
| 211 | <item> | 235 | <item> |
| 212 | <spacer name="horizontalSpacer"> | 236 | <spacer name="horizontalSpacer"> |
| 213 | <property name="orientation"> | 237 | <property name="orientation"> |
| 214 | <enum>Qt::Horizontal</enum> | 238 | <enum>Qt::Orientation::Horizontal</enum> |
| 215 | </property> | 239 | </property> |
| 216 | <property name="sizeHint" stdset="0"> | 240 | <property name="sizeHint" stdset="0"> |
| 217 | <size> | 241 | <size> |
| @@ -226,7 +250,7 @@ | |||
| 226 | <item> | 250 | <item> |
| 227 | <spacer name="verticalSpacer"> | 251 | <spacer name="verticalSpacer"> |
| 228 | <property name="orientation"> | 252 | <property name="orientation"> |
| 229 | <enum>Qt::Vertical</enum> | 253 | <enum>Qt::Orientation::Vertical</enum> |
| 230 | </property> | 254 | </property> |
| 231 | <property name="sizeHint" stdset="0"> | 255 | <property name="sizeHint" stdset="0"> |
| 232 | <size> | 256 | <size> |
diff --git a/src/avp/components/text.py b/src/avp/components/text.py index 40c981a..bee117e 100644 --- a/src/avp/components/text.py +++ b/src/avp/components/text.py | |||
| @@ -5,7 +5,7 @@ import os | |||
| 5 | import logging | 5 | import logging |
| 6 | 6 | ||
| 7 | from ..component import Component | 7 | from ..component import Component |
| 8 | from ..toolkit.frame import FramePainter, PaintColor | 8 | from ..toolkit.frame import FramePainter, addShadow |
| 9 | 9 | ||
| 10 | log = logging.getLogger("AVP.Components.Text") | 10 | log = logging.getLogger("AVP.Components.Text") |
| 11 | 11 | ||
| @@ -26,7 +26,6 @@ class Component(Component): | |||
| 26 | self.page.comboBox_textAlign.addItem("Right") | 26 | self.page.comboBox_textAlign.addItem("Right") |
| 27 | self.page.comboBox_textAlign.setCurrentIndex(int(self.alignment)) | 27 | self.page.comboBox_textAlign.setCurrentIndex(int(self.alignment)) |
| 28 | self.page.spinBox_fontSize.setValue(int(self.fontSize)) | 28 | self.page.spinBox_fontSize.setValue(int(self.fontSize)) |
| 29 | self.page.lineEdit_title.setText(self.title) | ||
| 30 | self.page.pushButton_center.clicked.connect(self.centerXY) | 29 | self.page.pushButton_center.clicked.connect(self.centerXY) |
| 31 | 30 | ||
| 32 | self.page.fontComboBox_titleFont.currentFontChanged.connect( | 31 | self.page.fontComboBox_titleFont.currentFontChanged.connect( |
| @@ -35,7 +34,7 @@ class Component(Component): | |||
| 35 | # The QFontComboBox must be connected directly to the Qt Signal | 34 | # The QFontComboBox must be connected directly to the Qt Signal |
| 36 | # which triggers the preview to update. | 35 | # which triggers the preview to update. |
| 37 | # This unfortunately makes changing the font into a non-undoable action. | 36 | # This unfortunately makes changing the font into a non-undoable action. |
| 38 | # Must be something broken in the conversion to a ComponentAction | 37 | # Fix requires updating ComponentAction to handle fonts |
| 39 | 38 | ||
| 40 | self.trackWidgets( | 39 | self.trackWidgets( |
| 41 | { | 40 | { |
| @@ -173,7 +172,7 @@ class Component(Component): | |||
| 173 | path.addText(x, y, font, self.title) | 172 | path.addText(x, y, font, self.title) |
| 174 | path = outliner.createStroke(path) | 173 | path = outliner.createStroke(path) |
| 175 | image.setPen(QtCore.Qt.PenStyle.NoPen) | 174 | image.setPen(QtCore.Qt.PenStyle.NoPen) |
| 176 | image.setBrush(PaintColor(*self.strokeColor)) | 175 | image.setBrush(QtGui.QColor(*self.strokeColor)) |
| 177 | image.drawPath(path) | 176 | image.drawPath(path) |
| 178 | 177 | ||
| 179 | image.setFont(font) | 178 | image.setFont(font) |
| @@ -183,11 +182,7 @@ class Component(Component): | |||
| 183 | # turn QImage into Pillow frame | 182 | # turn QImage into Pillow frame |
| 184 | frame = image.finalize() | 183 | frame = image.finalize() |
| 185 | if self.shadow: | 184 | if self.shadow: |
| 186 | shadImg = ImageEnhance.Contrast(frame).enhance(0.0) | 185 | frame = addShadow(frame, self.shadBlur / 10, self.shadX, self.shadY) |
| 187 | shadImg = shadImg.filter(ImageFilter.GaussianBlur(self.shadBlur)) | ||
| 188 | shadImg = ImageChops.offset(shadImg, self.shadX, self.shadY) | ||
| 189 | shadImg.paste(frame, box=(0, 0), mask=frame) | ||
| 190 | frame = shadImg | ||
| 191 | 186 | ||
| 192 | return frame | 187 | return frame |
| 193 | 188 | ||
diff --git a/src/avp/components/text.ui b/src/avp/components/text.ui index b62e0ed..ce961fe 100644 --- a/src/avp/components/text.ui +++ b/src/avp/components/text.ui | |||
| @@ -15,646 +15,645 @@ | |||
| 15 | </property> | 15 | </property> |
| 16 | <layout class="QVBoxLayout" name="verticalLayout_2"> | 16 | <layout class="QVBoxLayout" name="verticalLayout_2"> |
| 17 | <item> | 17 | <item> |
| 18 | <layout class="QVBoxLayout" name="verticalLayout"> | 18 | <layout class="QHBoxLayout" name="horizontalLayout"> |
| 19 | <property name="spacing"> | 19 | <item> |
| 20 | <number>6</number> | 20 | <widget class="QLabel" name="label_title"> |
| 21 | </property> | 21 | <property name="text"> |
| 22 | <property name="sizeConstraint"> | 22 | <string>Title</string> |
| 23 | <enum>QLayout::SetDefaultConstraint</enum> | 23 | </property> |
| 24 | </property> | 24 | </widget> |
| 25 | </item> | ||
| 26 | <item> | ||
| 27 | <widget class="QLineEdit" name="lineEdit_title"> | ||
| 28 | <property name="sizePolicy"> | ||
| 29 | <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> | ||
| 30 | <horstretch>0</horstretch> | ||
| 31 | <verstretch>0</verstretch> | ||
| 32 | </sizepolicy> | ||
| 33 | </property> | ||
| 34 | <property name="minimumSize"> | ||
| 35 | <size> | ||
| 36 | <width>0</width> | ||
| 37 | <height>0</height> | ||
| 38 | </size> | ||
| 39 | </property> | ||
| 40 | <property name="text"> | ||
| 41 | <string>Text</string> | ||
| 42 | </property> | ||
| 43 | </widget> | ||
| 44 | </item> | ||
| 45 | <item> | ||
| 46 | <widget class="QLabel" name="label"> | ||
| 47 | <property name="sizePolicy"> | ||
| 48 | <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> | ||
| 49 | <horstretch>0</horstretch> | ||
| 50 | <verstretch>0</verstretch> | ||
| 51 | </sizepolicy> | ||
| 52 | </property> | ||
| 53 | <property name="text"> | ||
| 54 | <string>Font</string> | ||
| 55 | </property> | ||
| 56 | </widget> | ||
| 57 | </item> | ||
| 58 | <item> | ||
| 59 | <widget class="QFontComboBox" name="fontComboBox_titleFont"> | ||
| 60 | <property name="sizePolicy"> | ||
| 61 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 62 | <horstretch>0</horstretch> | ||
| 63 | <verstretch>0</verstretch> | ||
| 64 | </sizepolicy> | ||
| 65 | </property> | ||
| 66 | <property name="minimumSize"> | ||
| 67 | <size> | ||
| 68 | <width>0</width> | ||
| 69 | <height>0</height> | ||
| 70 | </size> | ||
| 71 | </property> | ||
| 72 | </widget> | ||
| 73 | </item> | ||
| 74 | </layout> | ||
| 75 | </item> | ||
| 76 | <item> | ||
| 77 | <layout class="QHBoxLayout" name="horizontalLayout_7"> | ||
| 25 | <property name="leftMargin"> | 78 | <property name="leftMargin"> |
| 26 | <number>4</number> | 79 | <number>0</number> |
| 27 | </property> | 80 | </property> |
| 28 | <item> | 81 | <item> |
| 29 | <layout class="QHBoxLayout" name="horizontalLayout"> | 82 | <widget class="QLabel" name="label_textLayout"> |
| 30 | <item> | 83 | <property name="sizePolicy"> |
| 31 | <widget class="QLabel" name="label_title"> | 84 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> |
| 32 | <property name="text"> | 85 | <horstretch>0</horstretch> |
| 33 | <string>Title</string> | 86 | <verstretch>0</verstretch> |
| 34 | </property> | 87 | </sizepolicy> |
| 35 | </widget> | 88 | </property> |
| 36 | </item> | 89 | <property name="text"> |
| 37 | <item> | 90 | <string>Text Layout</string> |
| 38 | <widget class="QLineEdit" name="lineEdit_title"> | 91 | </property> |
| 39 | <property name="sizePolicy"> | 92 | </widget> |
| 40 | <sizepolicy hsizetype="Expanding" vsizetype="Fixed"> | 93 | </item> |
| 41 | <horstretch>0</horstretch> | 94 | <item> |
| 42 | <verstretch>0</verstretch> | 95 | <widget class="QComboBox" name="comboBox_textAlign"> |
| 43 | </sizepolicy> | 96 | <property name="sizePolicy"> |
| 44 | </property> | 97 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
| 45 | <property name="minimumSize"> | 98 | <horstretch>0</horstretch> |
| 46 | <size> | 99 | <verstretch>0</verstretch> |
| 47 | <width>0</width> | 100 | </sizepolicy> |
| 48 | <height>0</height> | 101 | </property> |
| 49 | </size> | 102 | <property name="maximumSize"> |
| 50 | </property> | 103 | <size> |
| 51 | <property name="text"> | 104 | <width>100</width> |
| 52 | <string>Testing New GUI</string> | 105 | <height>16777215</height> |
| 53 | </property> | 106 | </size> |
| 54 | </widget> | 107 | </property> |
| 55 | </item> | 108 | </widget> |
| 56 | <item> | 109 | </item> |
| 57 | <widget class="QLabel" name="label"> | 110 | <item> |
| 58 | <property name="sizePolicy"> | 111 | <spacer name="horizontalSpacer_2"> |
| 59 | <sizepolicy hsizetype="Minimum" vsizetype="Preferred"> | 112 | <property name="orientation"> |
| 60 | <horstretch>0</horstretch> | 113 | <enum>Qt::Orientation::Horizontal</enum> |
| 61 | <verstretch>0</verstretch> | 114 | </property> |
| 62 | </sizepolicy> | 115 | <property name="sizeType"> |
| 63 | </property> | 116 | <enum>QSizePolicy::Policy::Fixed</enum> |
| 64 | <property name="text"> | 117 | </property> |
| 65 | <string>Font</string> | 118 | <property name="sizeHint" stdset="0"> |
| 66 | </property> | 119 | <size> |
| 67 | </widget> | 120 | <width>5</width> |
| 68 | </item> | 121 | <height>20</height> |
| 69 | <item> | 122 | </size> |
| 70 | <widget class="QFontComboBox" name="fontComboBox_titleFont"> | 123 | </property> |
| 71 | <property name="sizePolicy"> | 124 | </spacer> |
| 72 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | 125 | </item> |
| 73 | <horstretch>0</horstretch> | 126 | <item> |
| 74 | <verstretch>0</verstretch> | 127 | <widget class="QPushButton" name="pushButton_center"> |
| 75 | </sizepolicy> | 128 | <property name="sizePolicy"> |
| 76 | </property> | 129 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
| 77 | <property name="minimumSize"> | 130 | <horstretch>0</horstretch> |
| 78 | <size> | 131 | <verstretch>0</verstretch> |
| 79 | <width>0</width> | 132 | </sizepolicy> |
| 80 | <height>0</height> | 133 | </property> |
| 81 | </size> | 134 | <property name="text"> |
| 82 | </property> | 135 | <string>Center Text</string> |
| 83 | </widget> | 136 | </property> |
| 84 | </item> | 137 | </widget> |
| 85 | </layout> | ||
| 86 | </item> | 138 | </item> |
| 87 | <item> | 139 | <item> |
| 88 | <layout class="QHBoxLayout" name="horizontalLayout_7"> | 140 | <spacer name="horizontalSpacer_6"> |
| 89 | <property name="leftMargin"> | 141 | <property name="orientation"> |
| 142 | <enum>Qt::Orientation::Horizontal</enum> | ||
| 143 | </property> | ||
| 144 | <property name="sizeType"> | ||
| 145 | <enum>QSizePolicy::Policy::Fixed</enum> | ||
| 146 | </property> | ||
| 147 | <property name="sizeHint" stdset="0"> | ||
| 148 | <size> | ||
| 149 | <width>5</width> | ||
| 150 | <height>20</height> | ||
| 151 | </size> | ||
| 152 | </property> | ||
| 153 | </spacer> | ||
| 154 | </item> | ||
| 155 | <item> | ||
| 156 | <widget class="QLabel" name="label_xTitleAlign"> | ||
| 157 | <property name="sizePolicy"> | ||
| 158 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 159 | <horstretch>0</horstretch> | ||
| 160 | <verstretch>0</verstretch> | ||
| 161 | </sizepolicy> | ||
| 162 | </property> | ||
| 163 | <property name="text"> | ||
| 164 | <string>X</string> | ||
| 165 | </property> | ||
| 166 | </widget> | ||
| 167 | </item> | ||
| 168 | <item> | ||
| 169 | <widget class="QSpinBox" name="spinBox_xTextAlign"> | ||
| 170 | <property name="sizePolicy"> | ||
| 171 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 172 | <horstretch>0</horstretch> | ||
| 173 | <verstretch>0</verstretch> | ||
| 174 | </sizepolicy> | ||
| 175 | </property> | ||
| 176 | <property name="maximumSize"> | ||
| 177 | <size> | ||
| 178 | <width>50</width> | ||
| 179 | <height>16777215</height> | ||
| 180 | </size> | ||
| 181 | </property> | ||
| 182 | <property name="baseSize"> | ||
| 183 | <size> | ||
| 184 | <width>0</width> | ||
| 185 | <height>0</height> | ||
| 186 | </size> | ||
| 187 | </property> | ||
| 188 | <property name="minimum"> | ||
| 90 | <number>0</number> | 189 | <number>0</number> |
| 91 | </property> | 190 | </property> |
| 92 | <item> | 191 | <property name="maximum"> |
| 93 | <widget class="QLabel" name="label_textLayout"> | 192 | <number>999999999</number> |
| 94 | <property name="sizePolicy"> | 193 | </property> |
| 95 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | 194 | <property name="value"> |
| 96 | <horstretch>0</horstretch> | 195 | <number>0</number> |
| 97 | <verstretch>0</verstretch> | 196 | </property> |
| 98 | </sizepolicy> | 197 | </widget> |
| 99 | </property> | ||
| 100 | <property name="text"> | ||
| 101 | <string>Text Layout</string> | ||
| 102 | </property> | ||
| 103 | </widget> | ||
| 104 | </item> | ||
| 105 | <item> | ||
| 106 | <widget class="QComboBox" name="comboBox_textAlign"> | ||
| 107 | <property name="sizePolicy"> | ||
| 108 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 109 | <horstretch>0</horstretch> | ||
| 110 | <verstretch>0</verstretch> | ||
| 111 | </sizepolicy> | ||
| 112 | </property> | ||
| 113 | <property name="maximumSize"> | ||
| 114 | <size> | ||
| 115 | <width>100</width> | ||
| 116 | <height>16777215</height> | ||
| 117 | </size> | ||
| 118 | </property> | ||
| 119 | </widget> | ||
| 120 | </item> | ||
| 121 | <item> | ||
| 122 | <spacer name="horizontalSpacer_2"> | ||
| 123 | <property name="orientation"> | ||
| 124 | <enum>Qt::Horizontal</enum> | ||
| 125 | </property> | ||
| 126 | <property name="sizeType"> | ||
| 127 | <enum>QSizePolicy::Fixed</enum> | ||
| 128 | </property> | ||
| 129 | <property name="sizeHint" stdset="0"> | ||
| 130 | <size> | ||
| 131 | <width>5</width> | ||
| 132 | <height>20</height> | ||
| 133 | </size> | ||
| 134 | </property> | ||
| 135 | </spacer> | ||
| 136 | </item> | ||
| 137 | <item> | ||
| 138 | <widget class="QPushButton" name="pushButton_center"> | ||
| 139 | <property name="sizePolicy"> | ||
| 140 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 141 | <horstretch>0</horstretch> | ||
| 142 | <verstretch>0</verstretch> | ||
| 143 | </sizepolicy> | ||
| 144 | </property> | ||
| 145 | <property name="text"> | ||
| 146 | <string>Center Text</string> | ||
| 147 | </property> | ||
| 148 | </widget> | ||
| 149 | </item> | ||
| 150 | <item> | ||
| 151 | <spacer name="horizontalSpacer_6"> | ||
| 152 | <property name="orientation"> | ||
| 153 | <enum>Qt::Horizontal</enum> | ||
| 154 | </property> | ||
| 155 | <property name="sizeType"> | ||
| 156 | <enum>QSizePolicy::Fixed</enum> | ||
| 157 | </property> | ||
| 158 | <property name="sizeHint" stdset="0"> | ||
| 159 | <size> | ||
| 160 | <width>5</width> | ||
| 161 | <height>20</height> | ||
| 162 | </size> | ||
| 163 | </property> | ||
| 164 | </spacer> | ||
| 165 | </item> | ||
| 166 | <item> | ||
| 167 | <widget class="QLabel" name="label_xTitleAlign"> | ||
| 168 | <property name="sizePolicy"> | ||
| 169 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 170 | <horstretch>0</horstretch> | ||
| 171 | <verstretch>0</verstretch> | ||
| 172 | </sizepolicy> | ||
| 173 | </property> | ||
| 174 | <property name="text"> | ||
| 175 | <string>X</string> | ||
| 176 | </property> | ||
| 177 | </widget> | ||
| 178 | </item> | ||
| 179 | <item> | ||
| 180 | <widget class="QSpinBox" name="spinBox_xTextAlign"> | ||
| 181 | <property name="sizePolicy"> | ||
| 182 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 183 | <horstretch>0</horstretch> | ||
| 184 | <verstretch>0</verstretch> | ||
| 185 | </sizepolicy> | ||
| 186 | </property> | ||
| 187 | <property name="maximumSize"> | ||
| 188 | <size> | ||
| 189 | <width>50</width> | ||
| 190 | <height>16777215</height> | ||
| 191 | </size> | ||
| 192 | </property> | ||
| 193 | <property name="baseSize"> | ||
| 194 | <size> | ||
| 195 | <width>0</width> | ||
| 196 | <height>0</height> | ||
| 197 | </size> | ||
| 198 | </property> | ||
| 199 | <property name="minimum"> | ||
| 200 | <number>0</number> | ||
| 201 | </property> | ||
| 202 | <property name="maximum"> | ||
| 203 | <number>999999999</number> | ||
| 204 | </property> | ||
| 205 | <property name="value"> | ||
| 206 | <number>0</number> | ||
| 207 | </property> | ||
| 208 | </widget> | ||
| 209 | </item> | ||
| 210 | <item> | ||
| 211 | <widget class="QLabel" name="label_yTitleAlign"> | ||
| 212 | <property name="sizePolicy"> | ||
| 213 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 214 | <horstretch>0</horstretch> | ||
| 215 | <verstretch>0</verstretch> | ||
| 216 | </sizepolicy> | ||
| 217 | </property> | ||
| 218 | <property name="text"> | ||
| 219 | <string>Y</string> | ||
| 220 | </property> | ||
| 221 | </widget> | ||
| 222 | </item> | ||
| 223 | <item> | ||
| 224 | <widget class="QSpinBox" name="spinBox_yTextAlign"> | ||
| 225 | <property name="sizePolicy"> | ||
| 226 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 227 | <horstretch>0</horstretch> | ||
| 228 | <verstretch>0</verstretch> | ||
| 229 | </sizepolicy> | ||
| 230 | </property> | ||
| 231 | <property name="maximumSize"> | ||
| 232 | <size> | ||
| 233 | <width>50</width> | ||
| 234 | <height>16777215</height> | ||
| 235 | </size> | ||
| 236 | </property> | ||
| 237 | <property name="maximum"> | ||
| 238 | <number>999999999</number> | ||
| 239 | </property> | ||
| 240 | </widget> | ||
| 241 | </item> | ||
| 242 | </layout> | ||
| 243 | </item> | 198 | </item> |
| 244 | <item> | 199 | <item> |
| 245 | <layout class="QHBoxLayout" name="horizontalLayout_8"> | 200 | <widget class="QLabel" name="label_yTitleAlign"> |
| 246 | <item> | 201 | <property name="sizePolicy"> |
| 247 | <widget class="QLabel" name="label_textColor"> | 202 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> |
| 248 | <property name="sizePolicy"> | 203 | <horstretch>0</horstretch> |
| 249 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | 204 | <verstretch>0</verstretch> |
| 250 | <horstretch>0</horstretch> | 205 | </sizepolicy> |
| 251 | <verstretch>0</verstretch> | 206 | </property> |
| 252 | </sizepolicy> | 207 | <property name="text"> |
| 253 | </property> | 208 | <string>Y</string> |
| 254 | <property name="maximumSize"> | 209 | </property> |
| 255 | <size> | 210 | </widget> |
| 256 | <width>16777215</width> | ||
| 257 | <height>16777215</height> | ||
| 258 | </size> | ||
| 259 | </property> | ||
| 260 | <property name="text"> | ||
| 261 | <string>Text Color</string> | ||
| 262 | </property> | ||
| 263 | </widget> | ||
| 264 | </item> | ||
| 265 | <item> | ||
| 266 | <widget class="QPushButton" name="pushButton_textColor"> | ||
| 267 | <property name="sizePolicy"> | ||
| 268 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 269 | <horstretch>0</horstretch> | ||
| 270 | <verstretch>0</verstretch> | ||
| 271 | </sizepolicy> | ||
| 272 | </property> | ||
| 273 | <property name="maximumSize"> | ||
| 274 | <size> | ||
| 275 | <width>32</width> | ||
| 276 | <height>32</height> | ||
| 277 | </size> | ||
| 278 | </property> | ||
| 279 | <property name="text"> | ||
| 280 | <string/> | ||
| 281 | </property> | ||
| 282 | <property name="MaximumSize" stdset="0"> | ||
| 283 | <size> | ||
| 284 | <width>32</width> | ||
| 285 | <height>32</height> | ||
| 286 | </size> | ||
| 287 | </property> | ||
| 288 | </widget> | ||
| 289 | </item> | ||
| 290 | <item> | ||
| 291 | <spacer name="horizontalSpacer_8"> | ||
| 292 | <property name="orientation"> | ||
| 293 | <enum>Qt::Horizontal</enum> | ||
| 294 | </property> | ||
| 295 | <property name="sizeType"> | ||
| 296 | <enum>QSizePolicy::Fixed</enum> | ||
| 297 | </property> | ||
| 298 | <property name="sizeHint" stdset="0"> | ||
| 299 | <size> | ||
| 300 | <width>5</width> | ||
| 301 | <height>20</height> | ||
| 302 | </size> | ||
| 303 | </property> | ||
| 304 | </spacer> | ||
| 305 | </item> | ||
| 306 | <item> | ||
| 307 | <widget class="QLabel" name="label_fontSize"> | ||
| 308 | <property name="sizePolicy"> | ||
| 309 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 310 | <horstretch>0</horstretch> | ||
| 311 | <verstretch>0</verstretch> | ||
| 312 | </sizepolicy> | ||
| 313 | </property> | ||
| 314 | <property name="text"> | ||
| 315 | <string>Font Size</string> | ||
| 316 | </property> | ||
| 317 | </widget> | ||
| 318 | </item> | ||
| 319 | <item> | ||
| 320 | <widget class="QSpinBox" name="spinBox_fontSize"> | ||
| 321 | <property name="sizePolicy"> | ||
| 322 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 323 | <horstretch>0</horstretch> | ||
| 324 | <verstretch>0</verstretch> | ||
| 325 | </sizepolicy> | ||
| 326 | </property> | ||
| 327 | <property name="suffix"> | ||
| 328 | <string/> | ||
| 329 | </property> | ||
| 330 | <property name="prefix"> | ||
| 331 | <string/> | ||
| 332 | </property> | ||
| 333 | <property name="minimum"> | ||
| 334 | <number>1</number> | ||
| 335 | </property> | ||
| 336 | <property name="maximum"> | ||
| 337 | <number>500</number> | ||
| 338 | </property> | ||
| 339 | </widget> | ||
| 340 | </item> | ||
| 341 | <item> | ||
| 342 | <spacer name="horizontalSpacer_7"> | ||
| 343 | <property name="orientation"> | ||
| 344 | <enum>Qt::Horizontal</enum> | ||
| 345 | </property> | ||
| 346 | <property name="sizeType"> | ||
| 347 | <enum>QSizePolicy::Fixed</enum> | ||
| 348 | </property> | ||
| 349 | <property name="sizeHint" stdset="0"> | ||
| 350 | <size> | ||
| 351 | <width>5</width> | ||
| 352 | <height>20</height> | ||
| 353 | </size> | ||
| 354 | </property> | ||
| 355 | </spacer> | ||
| 356 | </item> | ||
| 357 | <item> | ||
| 358 | <widget class="QLabel" name="label_3"> | ||
| 359 | <property name="sizePolicy"> | ||
| 360 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 361 | <horstretch>0</horstretch> | ||
| 362 | <verstretch>0</verstretch> | ||
| 363 | </sizepolicy> | ||
| 364 | </property> | ||
| 365 | <property name="text"> | ||
| 366 | <string>Font Style</string> | ||
| 367 | </property> | ||
| 368 | </widget> | ||
| 369 | </item> | ||
| 370 | <item> | ||
| 371 | <widget class="QComboBox" name="comboBox_fontStyle"> | ||
| 372 | <item> | ||
| 373 | <property name="text"> | ||
| 374 | <string>Normal</string> | ||
| 375 | </property> | ||
| 376 | </item> | ||
| 377 | <item> | ||
| 378 | <property name="text"> | ||
| 379 | <string>Semi-Bold</string> | ||
| 380 | </property> | ||
| 381 | </item> | ||
| 382 | <item> | ||
| 383 | <property name="text"> | ||
| 384 | <string>Bold</string> | ||
| 385 | </property> | ||
| 386 | </item> | ||
| 387 | <item> | ||
| 388 | <property name="text"> | ||
| 389 | <string>Italic</string> | ||
| 390 | </property> | ||
| 391 | </item> | ||
| 392 | <item> | ||
| 393 | <property name="text"> | ||
| 394 | <string>Bold Italic</string> | ||
| 395 | </property> | ||
| 396 | </item> | ||
| 397 | <item> | ||
| 398 | <property name="text"> | ||
| 399 | <string>Faux Italic</string> | ||
| 400 | </property> | ||
| 401 | </item> | ||
| 402 | <item> | ||
| 403 | <property name="text"> | ||
| 404 | <string>Small Caps</string> | ||
| 405 | </property> | ||
| 406 | </item> | ||
| 407 | </widget> | ||
| 408 | </item> | ||
| 409 | </layout> | ||
| 410 | </item> | 211 | </item> |
| 411 | <item> | 212 | <item> |
| 412 | <layout class="QHBoxLayout" name="horizontalLayout_12"> | 213 | <widget class="QSpinBox" name="spinBox_yTextAlign"> |
| 413 | <item> | 214 | <property name="sizePolicy"> |
| 414 | <widget class="QLineEdit" name="lineEdit_textColor"> | 215 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
| 415 | <property name="sizePolicy"> | 216 | <horstretch>0</horstretch> |
| 416 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | 217 | <verstretch>0</verstretch> |
| 417 | <horstretch>0</horstretch> | 218 | </sizepolicy> |
| 418 | <verstretch>0</verstretch> | 219 | </property> |
| 419 | </sizepolicy> | 220 | <property name="maximumSize"> |
| 420 | </property> | 221 | <size> |
| 421 | <property name="maximumSize"> | 222 | <width>50</width> |
| 422 | <size> | 223 | <height>16777215</height> |
| 423 | <width>0</width> | 224 | </size> |
| 424 | <height>16777215</height> | 225 | </property> |
| 425 | </size> | 226 | <property name="maximum"> |
| 426 | </property> | 227 | <number>999999999</number> |
| 427 | <property name="focusPolicy"> | 228 | </property> |
| 428 | <enum>Qt::NoFocus</enum> | 229 | </widget> |
| 429 | </property> | 230 | </item> |
| 430 | <property name="text"> | 231 | </layout> |
| 431 | <string>255,255,255</string> | 232 | </item> |
| 432 | </property> | 233 | <item> |
| 433 | </widget> | 234 | <layout class="QHBoxLayout" name="horizontalLayout_8"> |
| 434 | </item> | 235 | <item> |
| 435 | <item> | 236 | <widget class="QLabel" name="label_textColor"> |
| 436 | <widget class="QLabel" name="label_2"> | 237 | <property name="sizePolicy"> |
| 437 | <property name="sizePolicy"> | 238 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> |
| 438 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | 239 | <horstretch>0</horstretch> |
| 439 | <horstretch>0</horstretch> | 240 | <verstretch>0</verstretch> |
| 440 | <verstretch>0</verstretch> | 241 | </sizepolicy> |
| 441 | </sizepolicy> | 242 | </property> |
| 442 | </property> | 243 | <property name="maximumSize"> |
| 443 | <property name="text"> | 244 | <size> |
| 444 | <string>Stroke</string> | 245 | <width>16777215</width> |
| 445 | </property> | 246 | <height>16777215</height> |
| 446 | </widget> | 247 | </size> |
| 447 | </item> | 248 | </property> |
| 448 | <item> | 249 | <property name="text"> |
| 449 | <widget class="QSpinBox" name="spinBox_stroke"> | 250 | <string>Text Color</string> |
| 450 | <property name="sizePolicy"> | 251 | </property> |
| 451 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | 252 | </widget> |
| 452 | <horstretch>0</horstretch> | 253 | </item> |
| 453 | <verstretch>0</verstretch> | 254 | <item> |
| 454 | </sizepolicy> | 255 | <widget class="QPushButton" name="pushButton_textColor"> |
| 455 | </property> | 256 | <property name="sizePolicy"> |
| 456 | <property name="suffix"> | 257 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
| 457 | <string>px</string> | 258 | <horstretch>0</horstretch> |
| 458 | </property> | 259 | <verstretch>0</verstretch> |
| 459 | </widget> | 260 | </sizepolicy> |
| 460 | </item> | 261 | </property> |
| 461 | <item> | 262 | <property name="maximumSize"> |
| 462 | <widget class="QLabel" name="label_5"> | 263 | <size> |
| 463 | <property name="sizePolicy"> | 264 | <width>32</width> |
| 464 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | 265 | <height>32</height> |
| 465 | <horstretch>0</horstretch> | 266 | </size> |
| 466 | <verstretch>0</verstretch> | 267 | </property> |
| 467 | </sizepolicy> | 268 | <property name="text"> |
| 468 | </property> | 269 | <string/> |
| 469 | <property name="text"> | 270 | </property> |
| 470 | <string>Stroke Color</string> | 271 | <property name="MaximumSize" stdset="0"> |
| 471 | </property> | 272 | <size> |
| 472 | </widget> | 273 | <width>32</width> |
| 473 | </item> | 274 | <height>32</height> |
| 474 | <item> | 275 | </size> |
| 475 | <widget class="QLineEdit" name="lineEdit_strokeColor"> | 276 | </property> |
| 476 | <property name="sizePolicy"> | 277 | </widget> |
| 477 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | 278 | </item> |
| 478 | <horstretch>0</horstretch> | 279 | <item> |
| 479 | <verstretch>0</verstretch> | 280 | <spacer name="horizontalSpacer_8"> |
| 480 | </sizepolicy> | 281 | <property name="orientation"> |
| 481 | </property> | 282 | <enum>Qt::Orientation::Horizontal</enum> |
| 482 | <property name="maximumSize"> | 283 | </property> |
| 483 | <size> | 284 | <property name="sizeType"> |
| 484 | <width>0</width> | 285 | <enum>QSizePolicy::Policy::Fixed</enum> |
| 485 | <height>16777215</height> | 286 | </property> |
| 486 | </size> | 287 | <property name="sizeHint" stdset="0"> |
| 487 | </property> | 288 | <size> |
| 488 | <property name="focusPolicy"> | 289 | <width>5</width> |
| 489 | <enum>Qt::NoFocus</enum> | 290 | <height>20</height> |
| 490 | </property> | 291 | </size> |
| 491 | <property name="text"> | 292 | </property> |
| 492 | <string>0,0,0</string> | 293 | </spacer> |
| 493 | </property> | 294 | </item> |
| 494 | </widget> | 295 | <item> |
| 495 | </item> | 296 | <widget class="QLabel" name="label_fontSize"> |
| 496 | <item> | 297 | <property name="sizePolicy"> |
| 497 | <widget class="QPushButton" name="pushButton_strokeColor"> | 298 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> |
| 498 | <property name="sizePolicy"> | 299 | <horstretch>0</horstretch> |
| 499 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | 300 | <verstretch>0</verstretch> |
| 500 | <horstretch>0</horstretch> | 301 | </sizepolicy> |
| 501 | <verstretch>0</verstretch> | 302 | </property> |
| 502 | </sizepolicy> | 303 | <property name="text"> |
| 503 | </property> | 304 | <string>Font Size</string> |
| 504 | <property name="maximumSize"> | 305 | </property> |
| 505 | <size> | 306 | </widget> |
| 506 | <width>32</width> | 307 | </item> |
| 507 | <height>32</height> | 308 | <item> |
| 508 | </size> | 309 | <widget class="QSpinBox" name="spinBox_fontSize"> |
| 509 | </property> | 310 | <property name="sizePolicy"> |
| 510 | <property name="text"> | 311 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> |
| 511 | <string/> | 312 | <horstretch>0</horstretch> |
| 512 | </property> | 313 | <verstretch>0</verstretch> |
| 513 | <property name="MaximumSize" stdset="0"> | 314 | </sizepolicy> |
| 514 | <size> | 315 | </property> |
| 515 | <width>32</width> | 316 | <property name="suffix"> |
| 516 | <height>32</height> | 317 | <string/> |
| 517 | </size> | 318 | </property> |
| 518 | </property> | 319 | <property name="prefix"> |
| 519 | </widget> | 320 | <string/> |
| 520 | </item> | 321 | </property> |
| 521 | <item> | 322 | <property name="minimum"> |
| 522 | <spacer name="horizontalSpacer"> | 323 | <number>1</number> |
| 523 | <property name="orientation"> | 324 | </property> |
| 524 | <enum>Qt::Horizontal</enum> | 325 | <property name="maximum"> |
| 525 | </property> | 326 | <number>500</number> |
| 526 | <property name="sizeHint" stdset="0"> | 327 | </property> |
| 527 | <size> | 328 | </widget> |
| 528 | <width>40</width> | 329 | </item> |
| 529 | <height>20</height> | 330 | <item> |
| 530 | </size> | 331 | <spacer name="horizontalSpacer_7"> |
| 531 | </property> | 332 | <property name="orientation"> |
| 532 | </spacer> | 333 | <enum>Qt::Orientation::Horizontal</enum> |
| 533 | </item> | 334 | </property> |
| 534 | </layout> | 335 | <property name="sizeType"> |
| 336 | <enum>QSizePolicy::Policy::Fixed</enum> | ||
| 337 | </property> | ||
| 338 | <property name="sizeHint" stdset="0"> | ||
| 339 | <size> | ||
| 340 | <width>5</width> | ||
| 341 | <height>20</height> | ||
| 342 | </size> | ||
| 343 | </property> | ||
| 344 | </spacer> | ||
| 345 | </item> | ||
| 346 | <item> | ||
| 347 | <widget class="QLabel" name="label_3"> | ||
| 348 | <property name="sizePolicy"> | ||
| 349 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 350 | <horstretch>0</horstretch> | ||
| 351 | <verstretch>0</verstretch> | ||
| 352 | </sizepolicy> | ||
| 353 | </property> | ||
| 354 | <property name="text"> | ||
| 355 | <string>Font Style</string> | ||
| 356 | </property> | ||
| 357 | </widget> | ||
| 535 | </item> | 358 | </item> |
| 536 | <item> | 359 | <item> |
| 537 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | 360 | <widget class="QComboBox" name="comboBox_fontStyle"> |
| 538 | <item> | 361 | <item> |
| 539 | <widget class="QCheckBox" name="checkBox_shadow"> | 362 | <property name="text"> |
| 540 | <property name="sizePolicy"> | 363 | <string>Normal</string> |
| 541 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | 364 | </property> |
| 542 | <horstretch>0</horstretch> | ||
| 543 | <verstretch>0</verstretch> | ||
| 544 | </sizepolicy> | ||
| 545 | </property> | ||
| 546 | <property name="text"> | ||
| 547 | <string>Shadow</string> | ||
| 548 | </property> | ||
| 549 | </widget> | ||
| 550 | </item> | 365 | </item> |
| 551 | <item> | 366 | <item> |
| 552 | <widget class="QLabel" name="label_shadX"> | 367 | <property name="text"> |
| 553 | <property name="sizePolicy"> | 368 | <string>Semi-Bold</string> |
| 554 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | 369 | </property> |
| 555 | <horstretch>0</horstretch> | ||
| 556 | <verstretch>0</verstretch> | ||
| 557 | </sizepolicy> | ||
| 558 | </property> | ||
| 559 | <property name="text"> | ||
| 560 | <string>Shadow Offset</string> | ||
| 561 | </property> | ||
| 562 | </widget> | ||
| 563 | </item> | 370 | </item> |
| 564 | <item> | 371 | <item> |
| 565 | <widget class="QSpinBox" name="spinBox_shadX"> | 372 | <property name="text"> |
| 566 | <property name="sizePolicy"> | 373 | <string>Bold</string> |
| 567 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 374 | </property> |
| 568 | <horstretch>0</horstretch> | ||
| 569 | <verstretch>0</verstretch> | ||
| 570 | </sizepolicy> | ||
| 571 | </property> | ||
| 572 | <property name="minimum"> | ||
| 573 | <number>-1000</number> | ||
| 574 | </property> | ||
| 575 | <property name="maximum"> | ||
| 576 | <number>1000</number> | ||
| 577 | </property> | ||
| 578 | <property name="value"> | ||
| 579 | <number>-4</number> | ||
| 580 | </property> | ||
| 581 | </widget> | ||
| 582 | </item> | 375 | </item> |
| 583 | <item> | 376 | <item> |
| 584 | <widget class="QSpinBox" name="spinBox_shadY"> | 377 | <property name="text"> |
| 585 | <property name="sizePolicy"> | 378 | <string>Italic</string> |
| 586 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 379 | </property> |
| 587 | <horstretch>0</horstretch> | ||
| 588 | <verstretch>0</verstretch> | ||
| 589 | </sizepolicy> | ||
| 590 | </property> | ||
| 591 | <property name="minimum"> | ||
| 592 | <number>-1000</number> | ||
| 593 | </property> | ||
| 594 | <property name="maximum"> | ||
| 595 | <number>1000</number> | ||
| 596 | </property> | ||
| 597 | <property name="value"> | ||
| 598 | <number>8</number> | ||
| 599 | </property> | ||
| 600 | </widget> | ||
| 601 | </item> | 380 | </item> |
| 602 | <item> | 381 | <item> |
| 603 | <widget class="QLabel" name="label_shadBlur"> | 382 | <property name="text"> |
| 604 | <property name="sizePolicy"> | 383 | <string>Bold Italic</string> |
| 605 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | 384 | </property> |
| 606 | <horstretch>0</horstretch> | ||
| 607 | <verstretch>0</verstretch> | ||
| 608 | </sizepolicy> | ||
| 609 | </property> | ||
| 610 | <property name="text"> | ||
| 611 | <string>Shadow Blur</string> | ||
| 612 | </property> | ||
| 613 | </widget> | ||
| 614 | </item> | 385 | </item> |
| 615 | <item> | 386 | <item> |
| 616 | <widget class="QDoubleSpinBox" name="spinBox_shadBlur"> | 387 | <property name="text"> |
| 617 | <property name="sizePolicy"> | 388 | <string>Faux Italic</string> |
| 618 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | 389 | </property> |
| 619 | <horstretch>0</horstretch> | ||
| 620 | <verstretch>0</verstretch> | ||
| 621 | </sizepolicy> | ||
| 622 | </property> | ||
| 623 | <property name="maximum"> | ||
| 624 | <double>99.000000000000000</double> | ||
| 625 | </property> | ||
| 626 | <property name="singleStep"> | ||
| 627 | <double>0.100000000000000</double> | ||
| 628 | </property> | ||
| 629 | <property name="value"> | ||
| 630 | <double>5.000000000000000</double> | ||
| 631 | </property> | ||
| 632 | </widget> | ||
| 633 | </item> | 390 | </item> |
| 634 | <item> | 391 | <item> |
| 635 | <spacer name="horizontalSpacer_3"> | 392 | <property name="text"> |
| 636 | <property name="orientation"> | 393 | <string>Small Caps</string> |
| 637 | <enum>Qt::Horizontal</enum> | 394 | </property> |
| 638 | </property> | ||
| 639 | <property name="sizeType"> | ||
| 640 | <enum>QSizePolicy::Minimum</enum> | ||
| 641 | </property> | ||
| 642 | <property name="sizeHint" stdset="0"> | ||
| 643 | <size> | ||
| 644 | <width>40</width> | ||
| 645 | <height>20</height> | ||
| 646 | </size> | ||
| 647 | </property> | ||
| 648 | </spacer> | ||
| 649 | </item> | 395 | </item> |
| 650 | </layout> | 396 | </widget> |
| 397 | </item> | ||
| 398 | </layout> | ||
| 399 | </item> | ||
| 400 | <item> | ||
| 401 | <layout class="QHBoxLayout" name="horizontalLayout_12"> | ||
| 402 | <item> | ||
| 403 | <widget class="QLineEdit" name="lineEdit_textColor"> | ||
| 404 | <property name="sizePolicy"> | ||
| 405 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||
| 406 | <horstretch>0</horstretch> | ||
| 407 | <verstretch>0</verstretch> | ||
| 408 | </sizepolicy> | ||
| 409 | </property> | ||
| 410 | <property name="maximumSize"> | ||
| 411 | <size> | ||
| 412 | <width>0</width> | ||
| 413 | <height>16777215</height> | ||
| 414 | </size> | ||
| 415 | </property> | ||
| 416 | <property name="focusPolicy"> | ||
| 417 | <enum>Qt::FocusPolicy::NoFocus</enum> | ||
| 418 | </property> | ||
| 419 | <property name="text"> | ||
| 420 | <string/> | ||
| 421 | </property> | ||
| 422 | </widget> | ||
| 423 | </item> | ||
| 424 | <item> | ||
| 425 | <widget class="QLabel" name="label_2"> | ||
| 426 | <property name="sizePolicy"> | ||
| 427 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 428 | <horstretch>0</horstretch> | ||
| 429 | <verstretch>0</verstretch> | ||
| 430 | </sizepolicy> | ||
| 431 | </property> | ||
| 432 | <property name="text"> | ||
| 433 | <string>Stroke</string> | ||
| 434 | </property> | ||
| 435 | </widget> | ||
| 436 | </item> | ||
| 437 | <item> | ||
| 438 | <widget class="QSpinBox" name="spinBox_stroke"> | ||
| 439 | <property name="sizePolicy"> | ||
| 440 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 441 | <horstretch>0</horstretch> | ||
| 442 | <verstretch>0</verstretch> | ||
| 443 | </sizepolicy> | ||
| 444 | </property> | ||
| 445 | <property name="suffix"> | ||
| 446 | <string>px</string> | ||
| 447 | </property> | ||
| 448 | </widget> | ||
| 449 | </item> | ||
| 450 | <item> | ||
| 451 | <widget class="QLabel" name="label_5"> | ||
| 452 | <property name="sizePolicy"> | ||
| 453 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 454 | <horstretch>0</horstretch> | ||
| 455 | <verstretch>0</verstretch> | ||
| 456 | </sizepolicy> | ||
| 457 | </property> | ||
| 458 | <property name="text"> | ||
| 459 | <string>Stroke Color</string> | ||
| 460 | </property> | ||
| 461 | </widget> | ||
| 462 | </item> | ||
| 463 | <item> | ||
| 464 | <widget class="QLineEdit" name="lineEdit_strokeColor"> | ||
| 465 | <property name="sizePolicy"> | ||
| 466 | <sizepolicy hsizetype="Minimum" vsizetype="Fixed"> | ||
| 467 | <horstretch>0</horstretch> | ||
| 468 | <verstretch>0</verstretch> | ||
| 469 | </sizepolicy> | ||
| 470 | </property> | ||
| 471 | <property name="maximumSize"> | ||
| 472 | <size> | ||
| 473 | <width>0</width> | ||
| 474 | <height>16777215</height> | ||
| 475 | </size> | ||
| 476 | </property> | ||
| 477 | <property name="focusPolicy"> | ||
| 478 | <enum>Qt::FocusPolicy::NoFocus</enum> | ||
| 479 | </property> | ||
| 480 | <property name="text"> | ||
| 481 | <string>0,0,0</string> | ||
| 482 | </property> | ||
| 483 | </widget> | ||
| 484 | </item> | ||
| 485 | <item> | ||
| 486 | <widget class="QPushButton" name="pushButton_strokeColor"> | ||
| 487 | <property name="sizePolicy"> | ||
| 488 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 489 | <horstretch>0</horstretch> | ||
| 490 | <verstretch>0</verstretch> | ||
| 491 | </sizepolicy> | ||
| 492 | </property> | ||
| 493 | <property name="maximumSize"> | ||
| 494 | <size> | ||
| 495 | <width>32</width> | ||
| 496 | <height>32</height> | ||
| 497 | </size> | ||
| 498 | </property> | ||
| 499 | <property name="text"> | ||
| 500 | <string/> | ||
| 501 | </property> | ||
| 502 | <property name="MaximumSize" stdset="0"> | ||
| 503 | <size> | ||
| 504 | <width>32</width> | ||
| 505 | <height>32</height> | ||
| 506 | </size> | ||
| 507 | </property> | ||
| 508 | </widget> | ||
| 509 | </item> | ||
| 510 | <item> | ||
| 511 | <spacer name="horizontalSpacer"> | ||
| 512 | <property name="orientation"> | ||
| 513 | <enum>Qt::Orientation::Horizontal</enum> | ||
| 514 | </property> | ||
| 515 | <property name="sizeType"> | ||
| 516 | <enum>QSizePolicy::Policy::MinimumExpanding</enum> | ||
| 517 | </property> | ||
| 518 | <property name="sizeHint" stdset="0"> | ||
| 519 | <size> | ||
| 520 | <width>40</width> | ||
| 521 | <height>20</height> | ||
| 522 | </size> | ||
| 523 | </property> | ||
| 524 | </spacer> | ||
| 525 | </item> | ||
| 526 | </layout> | ||
| 527 | </item> | ||
| 528 | <item> | ||
| 529 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | ||
| 530 | <item> | ||
| 531 | <widget class="QCheckBox" name="checkBox_shadow"> | ||
| 532 | <property name="sizePolicy"> | ||
| 533 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 534 | <horstretch>0</horstretch> | ||
| 535 | <verstretch>0</verstretch> | ||
| 536 | </sizepolicy> | ||
| 537 | </property> | ||
| 538 | <property name="text"> | ||
| 539 | <string>Shadow</string> | ||
| 540 | </property> | ||
| 541 | </widget> | ||
| 542 | </item> | ||
| 543 | <item> | ||
| 544 | <spacer name="horizontalSpacer_3"> | ||
| 545 | <property name="orientation"> | ||
| 546 | <enum>Qt::Orientation::Horizontal</enum> | ||
| 547 | </property> | ||
| 548 | <property name="sizeType"> | ||
| 549 | <enum>QSizePolicy::Policy::Preferred</enum> | ||
| 550 | </property> | ||
| 551 | <property name="sizeHint" stdset="0"> | ||
| 552 | <size> | ||
| 553 | <width>40</width> | ||
| 554 | <height>20</height> | ||
| 555 | </size> | ||
| 556 | </property> | ||
| 557 | </spacer> | ||
| 558 | </item> | ||
| 559 | <item> | ||
| 560 | <widget class="QLabel" name="label_shadX"> | ||
| 561 | <property name="sizePolicy"> | ||
| 562 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 563 | <horstretch>0</horstretch> | ||
| 564 | <verstretch>0</verstretch> | ||
| 565 | </sizepolicy> | ||
| 566 | </property> | ||
| 567 | <property name="text"> | ||
| 568 | <string>Shadow Offset</string> | ||
| 569 | </property> | ||
| 570 | </widget> | ||
| 571 | </item> | ||
| 572 | <item> | ||
| 573 | <widget class="QSpinBox" name="spinBox_shadX"> | ||
| 574 | <property name="sizePolicy"> | ||
| 575 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 576 | <horstretch>0</horstretch> | ||
| 577 | <verstretch>0</verstretch> | ||
| 578 | </sizepolicy> | ||
| 579 | </property> | ||
| 580 | <property name="minimum"> | ||
| 581 | <number>-1000</number> | ||
| 582 | </property> | ||
| 583 | <property name="maximum"> | ||
| 584 | <number>1000</number> | ||
| 585 | </property> | ||
| 586 | <property name="value"> | ||
| 587 | <number>2</number> | ||
| 588 | </property> | ||
| 589 | </widget> | ||
| 590 | </item> | ||
| 591 | <item> | ||
| 592 | <widget class="QSpinBox" name="spinBox_shadY"> | ||
| 593 | <property name="sizePolicy"> | ||
| 594 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 595 | <horstretch>0</horstretch> | ||
| 596 | <verstretch>0</verstretch> | ||
| 597 | </sizepolicy> | ||
| 598 | </property> | ||
| 599 | <property name="minimum"> | ||
| 600 | <number>-1000</number> | ||
| 601 | </property> | ||
| 602 | <property name="maximum"> | ||
| 603 | <number>1000</number> | ||
| 604 | </property> | ||
| 605 | <property name="value"> | ||
| 606 | <number>-2</number> | ||
| 607 | </property> | ||
| 608 | </widget> | ||
| 609 | </item> | ||
| 610 | <item> | ||
| 611 | <widget class="QLabel" name="label_shadBlur"> | ||
| 612 | <property name="sizePolicy"> | ||
| 613 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 614 | <horstretch>0</horstretch> | ||
| 615 | <verstretch>0</verstretch> | ||
| 616 | </sizepolicy> | ||
| 617 | </property> | ||
| 618 | <property name="text"> | ||
| 619 | <string>Shadow Blur</string> | ||
| 620 | </property> | ||
| 621 | </widget> | ||
| 622 | </item> | ||
| 623 | <item> | ||
| 624 | <widget class="QSpinBox" name="spinBox_shadBlur"> | ||
| 625 | <property name="sizePolicy"> | ||
| 626 | <sizepolicy hsizetype="Preferred" vsizetype="Fixed"> | ||
| 627 | <horstretch>0</horstretch> | ||
| 628 | <verstretch>0</verstretch> | ||
| 629 | </sizepolicy> | ||
| 630 | </property> | ||
| 631 | <property name="buttonSymbols"> | ||
| 632 | <enum>QAbstractSpinBox::ButtonSymbols::PlusMinus</enum> | ||
| 633 | </property> | ||
| 634 | <property name="correctionMode"> | ||
| 635 | <enum>QAbstractSpinBox::CorrectionMode::CorrectToPreviousValue</enum> | ||
| 636 | </property> | ||
| 637 | <property name="maximum"> | ||
| 638 | <number>1000</number> | ||
| 639 | </property> | ||
| 640 | <property name="stepType"> | ||
| 641 | <enum>QAbstractSpinBox::StepType::DefaultStepType</enum> | ||
| 642 | </property> | ||
| 643 | <property name="value"> | ||
| 644 | <number>35</number> | ||
| 645 | </property> | ||
| 646 | <property name="displayIntegerBase"> | ||
| 647 | <number>10</number> | ||
| 648 | </property> | ||
| 649 | </widget> | ||
| 651 | </item> | 650 | </item> |
| 652 | </layout> | 651 | </layout> |
| 653 | </item> | 652 | </item> |
| 654 | <item> | 653 | <item> |
| 655 | <spacer name="verticalSpacer"> | 654 | <spacer name="verticalSpacer"> |
| 656 | <property name="orientation"> | 655 | <property name="orientation"> |
| 657 | <enum>Qt::Vertical</enum> | 656 | <enum>Qt::Orientation::Vertical</enum> |
| 658 | </property> | 657 | </property> |
| 659 | <property name="sizeHint" stdset="0"> | 658 | <property name="sizeHint" stdset="0"> |
| 660 | <size> | 659 | <size> |
diff --git a/src/avp/components/video.ui b/src/avp/components/video.ui index 08d15d3..72ecb0c 100644 --- a/src/avp/components/video.ui +++ b/src/avp/components/video.ui | |||
| @@ -27,168 +27,161 @@ | |||
| 27 | </property> | 27 | </property> |
| 28 | <layout class="QVBoxLayout" name="verticalLayout_2"> | 28 | <layout class="QVBoxLayout" name="verticalLayout_2"> |
| 29 | <item> | 29 | <item> |
| 30 | <layout class="QVBoxLayout" name="verticalLayout"> | 30 | <layout class="QHBoxLayout" name="horizontalLayout_8"> |
| 31 | <property name="leftMargin"> | 31 | <item> |
| 32 | <number>4</number> | 32 | <widget class="QLabel" name="label_textColor"> |
| 33 | </property> | 33 | <property name="sizePolicy"> |
| 34 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 35 | <horstretch>0</horstretch> | ||
| 36 | <verstretch>0</verstretch> | ||
| 37 | </sizepolicy> | ||
| 38 | </property> | ||
| 39 | <property name="minimumSize"> | ||
| 40 | <size> | ||
| 41 | <width>31</width> | ||
| 42 | <height>0</height> | ||
| 43 | </size> | ||
| 44 | </property> | ||
| 45 | <property name="text"> | ||
| 46 | <string>Video</string> | ||
| 47 | </property> | ||
| 48 | </widget> | ||
| 49 | </item> | ||
| 50 | <item> | ||
| 51 | <widget class="QLineEdit" name="lineEdit_video"> | ||
| 52 | <property name="minimumSize"> | ||
| 53 | <size> | ||
| 54 | <width>1</width> | ||
| 55 | <height>0</height> | ||
| 56 | </size> | ||
| 57 | </property> | ||
| 58 | </widget> | ||
| 59 | </item> | ||
| 60 | <item> | ||
| 61 | <widget class="QPushButton" name="pushButton_video"> | ||
| 62 | <property name="sizePolicy"> | ||
| 63 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 64 | <horstretch>0</horstretch> | ||
| 65 | <verstretch>0</verstretch> | ||
| 66 | </sizepolicy> | ||
| 67 | </property> | ||
| 68 | <property name="minimumSize"> | ||
| 69 | <size> | ||
| 70 | <width>1</width> | ||
| 71 | <height>0</height> | ||
| 72 | </size> | ||
| 73 | </property> | ||
| 74 | <property name="maximumSize"> | ||
| 75 | <size> | ||
| 76 | <width>32</width> | ||
| 77 | <height>32</height> | ||
| 78 | </size> | ||
| 79 | </property> | ||
| 80 | <property name="text"> | ||
| 81 | <string>...</string> | ||
| 82 | </property> | ||
| 83 | <property name="MaximumSize" stdset="0"> | ||
| 84 | <size> | ||
| 85 | <width>32</width> | ||
| 86 | <height>32</height> | ||
| 87 | </size> | ||
| 88 | </property> | ||
| 89 | </widget> | ||
| 90 | </item> | ||
| 91 | <item> | ||
| 92 | <spacer name="horizontalSpacer_9"> | ||
| 93 | <property name="orientation"> | ||
| 94 | <enum>Qt::Orientation::Horizontal</enum> | ||
| 95 | </property> | ||
| 96 | <property name="sizeType"> | ||
| 97 | <enum>QSizePolicy::Policy::Fixed</enum> | ||
| 98 | </property> | ||
| 99 | <property name="sizeHint" stdset="0"> | ||
| 100 | <size> | ||
| 101 | <width>5</width> | ||
| 102 | <height>20</height> | ||
| 103 | </size> | ||
| 104 | </property> | ||
| 105 | </spacer> | ||
| 106 | </item> | ||
| 107 | <item> | ||
| 108 | <widget class="QLabel" name="label_xTitleAlign"> | ||
| 109 | <property name="sizePolicy"> | ||
| 110 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 111 | <horstretch>0</horstretch> | ||
| 112 | <verstretch>0</verstretch> | ||
| 113 | </sizepolicy> | ||
| 114 | </property> | ||
| 115 | <property name="text"> | ||
| 116 | <string>X</string> | ||
| 117 | </property> | ||
| 118 | </widget> | ||
| 119 | </item> | ||
| 34 | <item> | 120 | <item> |
| 35 | <layout class="QHBoxLayout" name="horizontalLayout_8"> | 121 | <widget class="QSpinBox" name="spinBox_x"> |
| 36 | <item> | 122 | <property name="sizePolicy"> |
| 37 | <widget class="QLabel" name="label_textColor"> | 123 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> |
| 38 | <property name="sizePolicy"> | 124 | <horstretch>0</horstretch> |
| 39 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | 125 | <verstretch>0</verstretch> |
| 40 | <horstretch>0</horstretch> | 126 | </sizepolicy> |
| 41 | <verstretch>0</verstretch> | 127 | </property> |
| 42 | </sizepolicy> | 128 | <property name="maximumSize"> |
| 43 | </property> | 129 | <size> |
| 44 | <property name="minimumSize"> | 130 | <width>80</width> |
| 45 | <size> | 131 | <height>16777215</height> |
| 46 | <width>31</width> | 132 | </size> |
| 47 | <height>0</height> | 133 | </property> |
| 48 | </size> | 134 | <property name="minimum"> |
| 49 | </property> | 135 | <number>-10000</number> |
| 50 | <property name="text"> | 136 | </property> |
| 51 | <string>Video</string> | 137 | <property name="maximum"> |
| 52 | </property> | 138 | <number>10000</number> |
| 53 | </widget> | 139 | </property> |
| 54 | </item> | 140 | </widget> |
| 55 | <item> | 141 | </item> |
| 56 | <widget class="QLineEdit" name="lineEdit_video"> | 142 | <item> |
| 57 | <property name="minimumSize"> | 143 | <widget class="QLabel" name="label_yTitleAlign"> |
| 58 | <size> | 144 | <property name="sizePolicy"> |
| 59 | <width>1</width> | 145 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> |
| 60 | <height>0</height> | 146 | <horstretch>0</horstretch> |
| 61 | </size> | 147 | <verstretch>0</verstretch> |
| 62 | </property> | 148 | </sizepolicy> |
| 63 | </widget> | 149 | </property> |
| 64 | </item> | 150 | <property name="text"> |
| 65 | <item> | 151 | <string>Y</string> |
| 66 | <widget class="QPushButton" name="pushButton_video"> | 152 | </property> |
| 67 | <property name="sizePolicy"> | 153 | </widget> |
| 68 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 154 | </item> |
| 69 | <horstretch>0</horstretch> | 155 | <item> |
| 70 | <verstretch>0</verstretch> | 156 | <widget class="QSpinBox" name="spinBox_y"> |
| 71 | </sizepolicy> | 157 | <property name="sizePolicy"> |
| 72 | </property> | 158 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> |
| 73 | <property name="minimumSize"> | 159 | <horstretch>0</horstretch> |
| 74 | <size> | 160 | <verstretch>0</verstretch> |
| 75 | <width>1</width> | 161 | </sizepolicy> |
| 76 | <height>0</height> | 162 | </property> |
| 77 | </size> | 163 | <property name="maximumSize"> |
| 78 | </property> | 164 | <size> |
| 79 | <property name="maximumSize"> | 165 | <width>80</width> |
| 80 | <size> | 166 | <height>16777215</height> |
| 81 | <width>32</width> | 167 | </size> |
| 82 | <height>32</height> | 168 | </property> |
| 83 | </size> | 169 | <property name="baseSize"> |
| 84 | </property> | 170 | <size> |
| 85 | <property name="text"> | 171 | <width>0</width> |
| 86 | <string>...</string> | 172 | <height>0</height> |
| 87 | </property> | 173 | </size> |
| 88 | <property name="MaximumSize" stdset="0"> | 174 | </property> |
| 89 | <size> | 175 | <property name="minimum"> |
| 90 | <width>32</width> | 176 | <number>-10000</number> |
| 91 | <height>32</height> | 177 | </property> |
| 92 | </size> | 178 | <property name="maximum"> |
| 93 | </property> | 179 | <number>10000</number> |
| 94 | </widget> | 180 | </property> |
| 95 | </item> | 181 | <property name="value"> |
| 96 | <item> | 182 | <number>0</number> |
| 97 | <spacer name="horizontalSpacer_9"> | 183 | </property> |
| 98 | <property name="orientation"> | 184 | </widget> |
| 99 | <enum>Qt::Horizontal</enum> | ||
| 100 | </property> | ||
| 101 | <property name="sizeType"> | ||
| 102 | <enum>QSizePolicy::Fixed</enum> | ||
| 103 | </property> | ||
| 104 | <property name="sizeHint" stdset="0"> | ||
| 105 | <size> | ||
| 106 | <width>5</width> | ||
| 107 | <height>20</height> | ||
| 108 | </size> | ||
| 109 | </property> | ||
| 110 | </spacer> | ||
| 111 | </item> | ||
| 112 | <item> | ||
| 113 | <widget class="QLabel" name="label_xTitleAlign"> | ||
| 114 | <property name="sizePolicy"> | ||
| 115 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 116 | <horstretch>0</horstretch> | ||
| 117 | <verstretch>0</verstretch> | ||
| 118 | </sizepolicy> | ||
| 119 | </property> | ||
| 120 | <property name="text"> | ||
| 121 | <string>X</string> | ||
| 122 | </property> | ||
| 123 | </widget> | ||
| 124 | </item> | ||
| 125 | <item> | ||
| 126 | <widget class="QSpinBox" name="spinBox_x"> | ||
| 127 | <property name="sizePolicy"> | ||
| 128 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 129 | <horstretch>0</horstretch> | ||
| 130 | <verstretch>0</verstretch> | ||
| 131 | </sizepolicy> | ||
| 132 | </property> | ||
| 133 | <property name="maximumSize"> | ||
| 134 | <size> | ||
| 135 | <width>80</width> | ||
| 136 | <height>16777215</height> | ||
| 137 | </size> | ||
| 138 | </property> | ||
| 139 | <property name="minimum"> | ||
| 140 | <number>-10000</number> | ||
| 141 | </property> | ||
| 142 | <property name="maximum"> | ||
| 143 | <number>10000</number> | ||
| 144 | </property> | ||
| 145 | </widget> | ||
| 146 | </item> | ||
| 147 | <item> | ||
| 148 | <widget class="QLabel" name="label_yTitleAlign"> | ||
| 149 | <property name="sizePolicy"> | ||
| 150 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 151 | <horstretch>0</horstretch> | ||
| 152 | <verstretch>0</verstretch> | ||
| 153 | </sizepolicy> | ||
| 154 | </property> | ||
| 155 | <property name="text"> | ||
| 156 | <string>Y</string> | ||
| 157 | </property> | ||
| 158 | </widget> | ||
| 159 | </item> | ||
| 160 | <item> | ||
| 161 | <widget class="QSpinBox" name="spinBox_y"> | ||
| 162 | <property name="sizePolicy"> | ||
| 163 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 164 | <horstretch>0</horstretch> | ||
| 165 | <verstretch>0</verstretch> | ||
| 166 | </sizepolicy> | ||
| 167 | </property> | ||
| 168 | <property name="maximumSize"> | ||
| 169 | <size> | ||
| 170 | <width>80</width> | ||
| 171 | <height>16777215</height> | ||
| 172 | </size> | ||
| 173 | </property> | ||
| 174 | <property name="baseSize"> | ||
| 175 | <size> | ||
| 176 | <width>0</width> | ||
| 177 | <height>0</height> | ||
| 178 | </size> | ||
| 179 | </property> | ||
| 180 | <property name="minimum"> | ||
| 181 | <number>-10000</number> | ||
| 182 | </property> | ||
| 183 | <property name="maximum"> | ||
| 184 | <number>10000</number> | ||
| 185 | </property> | ||
| 186 | <property name="value"> | ||
| 187 | <number>0</number> | ||
| 188 | </property> | ||
| 189 | </widget> | ||
| 190 | </item> | ||
| 191 | </layout> | ||
| 192 | </item> | 185 | </item> |
| 193 | </layout> | 186 | </layout> |
| 194 | </item> | 187 | </item> |
| @@ -204,7 +197,7 @@ | |||
| 204 | <item> | 197 | <item> |
| 205 | <spacer name="horizontalSpacer"> | 198 | <spacer name="horizontalSpacer"> |
| 206 | <property name="orientation"> | 199 | <property name="orientation"> |
| 207 | <enum>Qt::Horizontal</enum> | 200 | <enum>Qt::Orientation::Horizontal</enum> |
| 208 | </property> | 201 | </property> |
| 209 | <property name="sizeHint" stdset="0"> | 202 | <property name="sizeHint" stdset="0"> |
| 210 | <size> | 203 | <size> |
| @@ -227,14 +220,14 @@ | |||
| 227 | <string>Scale</string> | 220 | <string>Scale</string> |
| 228 | </property> | 221 | </property> |
| 229 | <property name="alignment"> | 222 | <property name="alignment"> |
| 230 | <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | 223 | <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> |
| 231 | </property> | 224 | </property> |
| 232 | </widget> | 225 | </widget> |
| 233 | </item> | 226 | </item> |
| 234 | <item> | 227 | <item> |
| 235 | <widget class="QSpinBox" name="spinBox_scale"> | 228 | <widget class="QSpinBox" name="spinBox_scale"> |
| 236 | <property name="buttonSymbols"> | 229 | <property name="buttonSymbols"> |
| 237 | <enum>QAbstractSpinBox::UpDownArrows</enum> | 230 | <enum>QAbstractSpinBox::ButtonSymbols::UpDownArrows</enum> |
| 238 | </property> | 231 | </property> |
| 239 | <property name="suffix"> | 232 | <property name="suffix"> |
| 240 | <string>%</string> | 233 | <string>%</string> |
| @@ -296,7 +289,7 @@ | |||
| 296 | <item> | 289 | <item> |
| 297 | <spacer name="horizontalSpacer_2"> | 290 | <spacer name="horizontalSpacer_2"> |
| 298 | <property name="orientation"> | 291 | <property name="orientation"> |
| 299 | <enum>Qt::Horizontal</enum> | 292 | <enum>Qt::Orientation::Horizontal</enum> |
| 300 | </property> | 293 | </property> |
| 301 | <property name="sizeHint" stdset="0"> | 294 | <property name="sizeHint" stdset="0"> |
| 302 | <size> | 295 | <size> |
| @@ -311,7 +304,7 @@ | |||
| 311 | <item> | 304 | <item> |
| 312 | <spacer name="verticalSpacer"> | 305 | <spacer name="verticalSpacer"> |
| 313 | <property name="orientation"> | 306 | <property name="orientation"> |
| 314 | <enum>Qt::Vertical</enum> | 307 | <enum>Qt::Orientation::Vertical</enum> |
| 315 | </property> | 308 | </property> |
| 316 | <property name="sizeHint" stdset="0"> | 309 | <property name="sizeHint" stdset="0"> |
| 317 | <size> | 310 | <size> |
diff --git a/src/avp/components/waveform.py b/src/avp/components/waveform.py index 7dc0b99..e10dec2 100644 --- a/src/avp/components/waveform.py +++ b/src/avp/components/waveform.py | |||
| @@ -1,12 +1,12 @@ | |||
| 1 | from PIL import Image | 1 | from PIL import Image, ImageChops |
| 2 | from PyQt6 import QtGui, QtCore, QtWidgets | ||
| 3 | from PyQt6.QtGui import QColor | 2 | from PyQt6.QtGui import QColor |
| 4 | import os | 3 | import os |
| 5 | import math | ||
| 6 | import subprocess | 4 | import subprocess |
| 7 | import logging | 5 | import logging |
| 6 | from copy import copy | ||
| 8 | 7 | ||
| 9 | from ..component import Component | 8 | from ..component import Component |
| 9 | from ..toolkit.visualizer import transformData, createSpectrumArray | ||
| 10 | from ..toolkit.frame import BlankFrame, scale | 10 | from ..toolkit.frame import BlankFrame, scale |
| 11 | from ..toolkit import checkOutput | 11 | from ..toolkit import checkOutput |
| 12 | from ..toolkit.ffmpeg import ( | 12 | from ..toolkit.ffmpeg import ( |
| @@ -23,14 +23,20 @@ log = logging.getLogger("AVP.Components.Waveform") | |||
| 23 | 23 | ||
| 24 | class Component(Component): | 24 | class Component(Component): |
| 25 | name = "Waveform" | 25 | name = "Waveform" |
| 26 | version = "1.0.0" | 26 | version = "2.0.0" |
| 27 | |||
| 28 | @property | ||
| 29 | def updateInterval(self): | ||
| 30 | """How many frames from FFmpeg are ignored between each final frame""" | ||
| 31 | return 100 - self.speed | ||
| 32 | |||
| 33 | def properties(self): | ||
| 34 | return [] if self.speed == 100 else ["pcm"] | ||
| 27 | 35 | ||
| 28 | def widget(self, *args): | 36 | def widget(self, *args): |
| 29 | super().widget(*args) | 37 | super().widget(*args) |
| 30 | self._image = BlankFrame(self.width, self.height) | 38 | self._image = BlankFrame(self.width, self.height) |
| 31 | 39 | ||
| 32 | self.page.lineEdit_color.setText("255,255,255") | ||
| 33 | |||
| 34 | if hasattr(self.parent, "lineEdit_audioFile"): | 40 | if hasattr(self.parent, "lineEdit_audioFile"): |
| 35 | self.parent.lineEdit_audioFile.textChanged.connect(self.update) | 41 | self.parent.lineEdit_audioFile.textChanged.connect(self.update) |
| 36 | 42 | ||
| @@ -46,6 +52,7 @@ class Component(Component): | |||
| 46 | "opacity": self.page.spinBox_opacity, | 52 | "opacity": self.page.spinBox_opacity, |
| 47 | "compress": self.page.checkBox_compress, | 53 | "compress": self.page.checkBox_compress, |
| 48 | "mono": self.page.checkBox_mono, | 54 | "mono": self.page.checkBox_mono, |
| 55 | "speed": self.page.spinBox_speed, | ||
| 49 | }, | 56 | }, |
| 50 | colorWidgets={ | 57 | colorWidgets={ |
| 51 | "color": self.page.pushButton_color, | 58 | "color": self.page.pushButton_color, |
| @@ -65,6 +72,10 @@ class Component(Component): | |||
| 65 | return frame | 72 | return frame |
| 66 | 73 | ||
| 67 | def preFrameRender(self, **kwargs): | 74 | def preFrameRender(self, **kwargs): |
| 75 | self._fadingImage = None | ||
| 76 | self._prevImage = None | ||
| 77 | self._currImage = None | ||
| 78 | self._lastUpdatedFrame = 0 | ||
| 68 | super().preFrameRender(**kwargs) | 79 | super().preFrameRender(**kwargs) |
| 69 | self.updateChunksize() | 80 | self.updateChunksize() |
| 70 | w, h = scale(self.scale, self.width, self.height, str) | 81 | w, h = scale(self.scale, self.width, self.height, str) |
| @@ -79,11 +90,64 @@ class Component(Component): | |||
| 79 | component=self, | 90 | component=self, |
| 80 | debug=True, | 91 | debug=True, |
| 81 | ) | 92 | ) |
| 93 | if self.speed == 100: | ||
| 94 | return | ||
| 95 | self.spectrumArray = createSpectrumArray( | ||
| 96 | self, | ||
| 97 | self.completeAudioArray, | ||
| 98 | self.sampleSize, | ||
| 99 | 0.08, | ||
| 100 | 0.8, | ||
| 101 | 20, | ||
| 102 | self.progressBarUpdate, | ||
| 103 | self.progressBarSetText, | ||
| 104 | ) | ||
| 82 | 105 | ||
| 83 | def frameRender(self, frameNo): | 106 | def frameRender(self, frameNo): |
| 84 | if FfmpegVideo.threadError is not None: | 107 | if FfmpegVideo.threadError is not None: |
| 85 | raise FfmpegVideo.threadError | 108 | raise FfmpegVideo.threadError |
| 86 | return self.finalizeFrame(self.video.frame(frameNo)) | 109 | newFrame = self.finalizeFrame(self.video.frame(frameNo)) |
| 110 | if self.speed == 100: | ||
| 111 | return newFrame | ||
| 112 | frameDiff = 0 if frameNo == 0 else frameNo % self.updateInterval | ||
| 113 | peaks = [ | ||
| 114 | self.spectrumArray[frameNo * self.sampleSize][i * 4] for i in range(64) | ||
| 115 | ] | ||
| 116 | peakValue = 70 - (max(*peaks) - min(*peaks)) | ||
| 117 | isValidPeak = ( | ||
| 118 | peakValue > 27 | ||
| 119 | and frameNo - self._lastUpdatedFrame > self.updateInterval / 2 | ||
| 120 | ) | ||
| 121 | if frameDiff == 0 or isValidPeak: | ||
| 122 | self._lastUpdatedFrame = frameNo | ||
| 123 | self._fadingImage = self._prevImage | ||
| 124 | self._prevImage = self._image | ||
| 125 | self._currImage = newFrame | ||
| 126 | usualAlpha = 0.0 + (1 / self.updateInterval) * frameDiff | ||
| 127 | alpha = max( | ||
| 128 | 0.1 | ||
| 129 | + ( | ||
| 130 | 1 | ||
| 131 | / max( | ||
| 132 | 10, | ||
| 133 | peakValue, | ||
| 134 | ) | ||
| 135 | ), | ||
| 136 | usualAlpha, | ||
| 137 | ) | ||
| 138 | baseImage = self._prevImage | ||
| 139 | if self._fadingImage is not None: | ||
| 140 | # fade away the old previous frame from ages ago | ||
| 141 | baseImage = ImageChops.blend( | ||
| 142 | self._prevImage, self._fadingImage, max(0.0, 0.9 - usualAlpha) | ||
| 143 | ) | ||
| 144 | blendedImage = ImageChops.blend( | ||
| 145 | baseImage, | ||
| 146 | ImageChops.lighter(self._prevImage, newFrame), | ||
| 147 | alpha, | ||
| 148 | ) | ||
| 149 | baseImage.paste(blendedImage, (0, 0), mask=blendedImage) | ||
| 150 | return Image.alpha_composite(self._currImage, baseImage) | ||
| 87 | 151 | ||
| 88 | def postFrameRender(self): | 152 | def postFrameRender(self): |
| 89 | closePipe(self.video.pipe) | 153 | closePipe(self.video.pipe) |
| @@ -162,17 +226,17 @@ class Component(Component): | |||
| 162 | def makeFfmpegFilter(self, preview=False, startPt=0): | 226 | def makeFfmpegFilter(self, preview=False, startPt=0): |
| 163 | w, h = scale(self.scale, self.width, self.height, str) | 227 | w, h = scale(self.scale, self.width, self.height, str) |
| 164 | if self.amplitude == 0: | 228 | if self.amplitude == 0: |
| 165 | amplitude = "lin" | ||
| 166 | elif self.amplitude == 1: | ||
| 167 | amplitude = "log" | 229 | amplitude = "log" |
| 168 | elif self.amplitude == 2: | 230 | elif self.amplitude == 1: |
| 169 | amplitude = "sqrt" | 231 | amplitude = "sqrt" |
| 170 | elif self.amplitude == 3: | 232 | elif self.amplitude == 2: |
| 171 | amplitude = "cbrt" | 233 | amplitude = "cbrt" |
| 234 | elif self.amplitude == 3: | ||
| 235 | amplitude = "lin" | ||
| 172 | hexcolor = QColor(*self.color).name() | 236 | hexcolor = QColor(*self.color).name() |
| 173 | opacity = "{0:.1f}".format(self.opacity / 100) | 237 | opacity = "{0:.1f}".format(self.opacity / 100) |
| 174 | genericPreview = self.settings.value("pref_genericPreview") | 238 | genericPreview = self.settings.value("pref_genericPreview") |
| 175 | if self.mode < 3: | 239 | if self.mode > 1: |
| 176 | filter_ = ( | 240 | filter_ = ( |
| 177 | "showwaves=" | 241 | "showwaves=" |
| 178 | f'r={str(self.settings.value("outputFrameRate"))}:' | 242 | f'r={str(self.settings.value("outputFrameRate"))}:' |
| @@ -180,10 +244,10 @@ class Component(Component): | |||
| 180 | f'mode={self.page.comboBox_mode.currentText().lower() if self.mode != 3 else "p2p"}:' | 244 | f'mode={self.page.comboBox_mode.currentText().lower() if self.mode != 3 else "p2p"}:' |
| 181 | f"colors={hexcolor}@{opacity}:scale={amplitude}" | 245 | f"colors={hexcolor}@{opacity}:scale={amplitude}" |
| 182 | ) | 246 | ) |
| 183 | elif self.mode > 2: | 247 | elif self.mode < 2: |
| 184 | filter_ = ( | 248 | filter_ = ( |
| 185 | f'showfreqs=s={str(self.settings.value("outputWidth"))}x{str(self.settings.value("outputHeight"))}:' | 249 | f'showfreqs=s={str(self.settings.value("outputWidth"))}x{str(self.settings.value("outputHeight"))}:' |
| 186 | f'mode={"line" if self.mode == 4 else "bar"}:' | 250 | f'mode={"line" if self.mode == 0 else "bar"}:' |
| 187 | f"colors={hexcolor}@{opacity}" | 251 | f"colors={hexcolor}@{opacity}" |
| 188 | f":ascale={amplitude}:fscale={'log' if self.mono else 'lin'}" | 252 | f":ascale={amplitude}:fscale={'log' if self.mono else 'lin'}" |
| 189 | ) | 253 | ) |
diff --git a/src/avp/components/waveform.ui b/src/avp/components/waveform.ui index 5473f33..434ba62 100644 --- a/src/avp/components/waveform.ui +++ b/src/avp/components/waveform.ui | |||
| @@ -27,156 +27,144 @@ | |||
| 27 | </property> | 27 | </property> |
| 28 | <layout class="QVBoxLayout" name="verticalLayout_2"> | 28 | <layout class="QVBoxLayout" name="verticalLayout_2"> |
| 29 | <item> | 29 | <item> |
| 30 | <layout class="QVBoxLayout" name="verticalLayout"> | 30 | <layout class="QHBoxLayout" name="horizontalLayout_8"> |
| 31 | <property name="leftMargin"> | ||
| 32 | <number>4</number> | ||
| 33 | </property> | ||
| 34 | <item> | 31 | <item> |
| 35 | <layout class="QHBoxLayout" name="horizontalLayout_8"> | 32 | <widget class="QLabel" name="label_textColor"> |
| 36 | <item> | 33 | <property name="sizePolicy"> |
| 37 | <widget class="QLabel" name="label_textColor"> | 34 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> |
| 38 | <property name="sizePolicy"> | 35 | <horstretch>0</horstretch> |
| 39 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | 36 | <verstretch>0</verstretch> |
| 40 | <horstretch>0</horstretch> | 37 | </sizepolicy> |
| 41 | <verstretch>0</verstretch> | 38 | </property> |
| 42 | </sizepolicy> | 39 | <property name="minimumSize"> |
| 43 | </property> | 40 | <size> |
| 44 | <property name="minimumSize"> | 41 | <width>31</width> |
| 45 | <size> | 42 | <height>0</height> |
| 46 | <width>31</width> | 43 | </size> |
| 47 | <height>0</height> | 44 | </property> |
| 48 | </size> | 45 | <property name="text"> |
| 49 | </property> | 46 | <string>Mode</string> |
| 50 | <property name="text"> | 47 | </property> |
| 51 | <string>Mode</string> | 48 | </widget> |
| 52 | </property> | 49 | </item> |
| 53 | </widget> | 50 | <item> |
| 54 | </item> | 51 | <widget class="QComboBox" name="comboBox_mode"> |
| 55 | <item> | ||
| 56 | <widget class="QComboBox" name="comboBox_mode"> | ||
| 57 | <item> | ||
| 58 | <property name="text"> | ||
| 59 | <string>Cline</string> | ||
| 60 | </property> | ||
| 61 | </item> | ||
| 62 | <item> | ||
| 63 | <property name="text"> | ||
| 64 | <string>Line</string> | ||
| 65 | </property> | ||
| 66 | </item> | ||
| 67 | <item> | ||
| 68 | <property name="text"> | ||
| 69 | <string>Point</string> | ||
| 70 | </property> | ||
| 71 | </item> | ||
| 72 | <item> | ||
| 73 | <property name="text"> | ||
| 74 | <string>Frequency Bar</string> | ||
| 75 | </property> | ||
| 76 | </item> | ||
| 77 | <item> | ||
| 78 | <property name="text"> | ||
| 79 | <string>Frequency Line</string> | ||
| 80 | </property> | ||
| 81 | </item> | ||
| 82 | </widget> | ||
| 83 | </item> | ||
| 84 | <item> | ||
| 85 | <spacer name="horizontalSpacer_9"> | ||
| 86 | <property name="orientation"> | ||
| 87 | <enum>Qt::Horizontal</enum> | ||
| 88 | </property> | ||
| 89 | <property name="sizeType"> | ||
| 90 | <enum>QSizePolicy::Fixed</enum> | ||
| 91 | </property> | ||
| 92 | <property name="sizeHint" stdset="0"> | ||
| 93 | <size> | ||
| 94 | <width>5</width> | ||
| 95 | <height>20</height> | ||
| 96 | </size> | ||
| 97 | </property> | ||
| 98 | </spacer> | ||
| 99 | </item> | ||
| 100 | <item> | 52 | <item> |
| 101 | <widget class="QLabel" name="label_xTitleAlign"> | 53 | <property name="text"> |
| 102 | <property name="sizePolicy"> | 54 | <string>Frequency Line</string> |
| 103 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | 55 | </property> |
| 104 | <horstretch>0</horstretch> | ||
| 105 | <verstretch>0</verstretch> | ||
| 106 | </sizepolicy> | ||
| 107 | </property> | ||
| 108 | <property name="text"> | ||
| 109 | <string>X</string> | ||
| 110 | </property> | ||
| 111 | </widget> | ||
| 112 | </item> | 56 | </item> |
| 113 | <item> | 57 | <item> |
| 114 | <widget class="QSpinBox" name="spinBox_x"> | 58 | <property name="text"> |
| 115 | <property name="sizePolicy"> | 59 | <string>Frequency Bar</string> |
| 116 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 60 | </property> |
| 117 | <horstretch>0</horstretch> | ||
| 118 | <verstretch>0</verstretch> | ||
| 119 | </sizepolicy> | ||
| 120 | </property> | ||
| 121 | <property name="maximumSize"> | ||
| 122 | <size> | ||
| 123 | <width>80</width> | ||
| 124 | <height>16777215</height> | ||
| 125 | </size> | ||
| 126 | </property> | ||
| 127 | <property name="minimum"> | ||
| 128 | <number>-10000</number> | ||
| 129 | </property> | ||
| 130 | <property name="maximum"> | ||
| 131 | <number>10000</number> | ||
| 132 | </property> | ||
| 133 | </widget> | ||
| 134 | </item> | 61 | </item> |
| 135 | <item> | 62 | <item> |
| 136 | <widget class="QLabel" name="label_yTitleAlign"> | 63 | <property name="text"> |
| 137 | <property name="sizePolicy"> | 64 | <string>Cline</string> |
| 138 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | 65 | </property> |
| 139 | <horstretch>0</horstretch> | ||
| 140 | <verstretch>0</verstretch> | ||
| 141 | </sizepolicy> | ||
| 142 | </property> | ||
| 143 | <property name="text"> | ||
| 144 | <string>Y</string> | ||
| 145 | </property> | ||
| 146 | </widget> | ||
| 147 | </item> | 66 | </item> |
| 148 | <item> | 67 | <item> |
| 149 | <widget class="QSpinBox" name="spinBox_y"> | 68 | <property name="text"> |
| 150 | <property name="sizePolicy"> | 69 | <string>Line</string> |
| 151 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | 70 | </property> |
| 152 | <horstretch>0</horstretch> | ||
| 153 | <verstretch>0</verstretch> | ||
| 154 | </sizepolicy> | ||
| 155 | </property> | ||
| 156 | <property name="maximumSize"> | ||
| 157 | <size> | ||
| 158 | <width>80</width> | ||
| 159 | <height>16777215</height> | ||
| 160 | </size> | ||
| 161 | </property> | ||
| 162 | <property name="baseSize"> | ||
| 163 | <size> | ||
| 164 | <width>0</width> | ||
| 165 | <height>0</height> | ||
| 166 | </size> | ||
| 167 | </property> | ||
| 168 | <property name="minimum"> | ||
| 169 | <number>-10000</number> | ||
| 170 | </property> | ||
| 171 | <property name="maximum"> | ||
| 172 | <number>10000</number> | ||
| 173 | </property> | ||
| 174 | <property name="value"> | ||
| 175 | <number>0</number> | ||
| 176 | </property> | ||
| 177 | </widget> | ||
| 178 | </item> | 71 | </item> |
| 179 | </layout> | 72 | </widget> |
| 73 | </item> | ||
| 74 | <item> | ||
| 75 | <spacer name="horizontalSpacer_9"> | ||
| 76 | <property name="orientation"> | ||
| 77 | <enum>Qt::Orientation::Horizontal</enum> | ||
| 78 | </property> | ||
| 79 | <property name="sizeType"> | ||
| 80 | <enum>QSizePolicy::Policy::Fixed</enum> | ||
| 81 | </property> | ||
| 82 | <property name="sizeHint" stdset="0"> | ||
| 83 | <size> | ||
| 84 | <width>5</width> | ||
| 85 | <height>20</height> | ||
| 86 | </size> | ||
| 87 | </property> | ||
| 88 | </spacer> | ||
| 89 | </item> | ||
| 90 | <item> | ||
| 91 | <widget class="QLabel" name="label_xTitleAlign"> | ||
| 92 | <property name="sizePolicy"> | ||
| 93 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 94 | <horstretch>0</horstretch> | ||
| 95 | <verstretch>0</verstretch> | ||
| 96 | </sizepolicy> | ||
| 97 | </property> | ||
| 98 | <property name="text"> | ||
| 99 | <string>X</string> | ||
| 100 | </property> | ||
| 101 | </widget> | ||
| 102 | </item> | ||
| 103 | <item> | ||
| 104 | <widget class="QSpinBox" name="spinBox_x"> | ||
| 105 | <property name="sizePolicy"> | ||
| 106 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 107 | <horstretch>0</horstretch> | ||
| 108 | <verstretch>0</verstretch> | ||
| 109 | </sizepolicy> | ||
| 110 | </property> | ||
| 111 | <property name="maximumSize"> | ||
| 112 | <size> | ||
| 113 | <width>80</width> | ||
| 114 | <height>16777215</height> | ||
| 115 | </size> | ||
| 116 | </property> | ||
| 117 | <property name="minimum"> | ||
| 118 | <number>-10000</number> | ||
| 119 | </property> | ||
| 120 | <property name="maximum"> | ||
| 121 | <number>10000</number> | ||
| 122 | </property> | ||
| 123 | </widget> | ||
| 124 | </item> | ||
| 125 | <item> | ||
| 126 | <widget class="QLabel" name="label_yTitleAlign"> | ||
| 127 | <property name="sizePolicy"> | ||
| 128 | <sizepolicy hsizetype="Fixed" vsizetype="Preferred"> | ||
| 129 | <horstretch>0</horstretch> | ||
| 130 | <verstretch>0</verstretch> | ||
| 131 | </sizepolicy> | ||
| 132 | </property> | ||
| 133 | <property name="text"> | ||
| 134 | <string>Y</string> | ||
| 135 | </property> | ||
| 136 | </widget> | ||
| 137 | </item> | ||
| 138 | <item> | ||
| 139 | <widget class="QSpinBox" name="spinBox_y"> | ||
| 140 | <property name="sizePolicy"> | ||
| 141 | <sizepolicy hsizetype="Fixed" vsizetype="Fixed"> | ||
| 142 | <horstretch>0</horstretch> | ||
| 143 | <verstretch>0</verstretch> | ||
| 144 | </sizepolicy> | ||
| 145 | </property> | ||
| 146 | <property name="maximumSize"> | ||
| 147 | <size> | ||
| 148 | <width>80</width> | ||
| 149 | <height>16777215</height> | ||
| 150 | </size> | ||
| 151 | </property> | ||
| 152 | <property name="baseSize"> | ||
| 153 | <size> | ||
| 154 | <width>0</width> | ||
| 155 | <height>0</height> | ||
| 156 | </size> | ||
| 157 | </property> | ||
| 158 | <property name="minimum"> | ||
| 159 | <number>-10000</number> | ||
| 160 | </property> | ||
| 161 | <property name="maximum"> | ||
| 162 | <number>10000</number> | ||
| 163 | </property> | ||
| 164 | <property name="value"> | ||
| 165 | <number>0</number> | ||
| 166 | </property> | ||
| 167 | </widget> | ||
| 180 | </item> | 168 | </item> |
| 181 | </layout> | 169 | </layout> |
| 182 | </item> | 170 | </item> |
| @@ -192,7 +180,7 @@ | |||
| 192 | <item> | 180 | <item> |
| 193 | <widget class="QLineEdit" name="lineEdit_color"> | 181 | <widget class="QLineEdit" name="lineEdit_color"> |
| 194 | <property name="inputMethodHints"> | 182 | <property name="inputMethodHints"> |
| 195 | <set>Qt::ImhNone</set> | 183 | <set>Qt::InputMethodHint::ImhNone</set> |
| 196 | </property> | 184 | </property> |
| 197 | </widget> | 185 | </widget> |
| 198 | </item> | 186 | </item> |
| @@ -224,7 +212,7 @@ | |||
| 224 | <item> | 212 | <item> |
| 225 | <spacer name="horizontalSpacer"> | 213 | <spacer name="horizontalSpacer"> |
| 226 | <property name="orientation"> | 214 | <property name="orientation"> |
| 227 | <enum>Qt::Horizontal</enum> | 215 | <enum>Qt::Orientation::Horizontal</enum> |
| 228 | </property> | 216 | </property> |
| 229 | <property name="sizeHint" stdset="0"> | 217 | <property name="sizeHint" stdset="0"> |
| 230 | <size> | 218 | <size> |
| @@ -240,14 +228,14 @@ | |||
| 240 | <string>Opacity</string> | 228 | <string>Opacity</string> |
| 241 | </property> | 229 | </property> |
| 242 | <property name="alignment"> | 230 | <property name="alignment"> |
| 243 | <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | 231 | <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> |
| 244 | </property> | 232 | </property> |
| 245 | </widget> | 233 | </widget> |
| 246 | </item> | 234 | </item> |
| 247 | <item> | 235 | <item> |
| 248 | <widget class="QSpinBox" name="spinBox_opacity"> | 236 | <widget class="QSpinBox" name="spinBox_opacity"> |
| 249 | <property name="buttonSymbols"> | 237 | <property name="buttonSymbols"> |
| 250 | <enum>QAbstractSpinBox::UpDownArrows</enum> | 238 | <enum>QAbstractSpinBox::ButtonSymbols::UpDownArrows</enum> |
| 251 | </property> | 239 | </property> |
| 252 | <property name="suffix"> | 240 | <property name="suffix"> |
| 253 | <string>%</string> | 241 | <string>%</string> |
| @@ -269,14 +257,14 @@ | |||
| 269 | <string>Scale</string> | 257 | <string>Scale</string> |
| 270 | </property> | 258 | </property> |
| 271 | <property name="alignment"> | 259 | <property name="alignment"> |
| 272 | <set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set> | 260 | <set>Qt::AlignmentFlag::AlignRight|Qt::AlignmentFlag::AlignTrailing|Qt::AlignmentFlag::AlignVCenter</set> |
| 273 | </property> | 261 | </property> |
| 274 | </widget> | 262 | </widget> |
| 275 | </item> | 263 | </item> |
| 276 | <item> | 264 | <item> |
| 277 | <widget class="QSpinBox" name="spinBox_scale"> | 265 | <widget class="QSpinBox" name="spinBox_scale"> |
| 278 | <property name="buttonSymbols"> | 266 | <property name="buttonSymbols"> |
| 279 | <enum>QAbstractSpinBox::UpDownArrows</enum> | 267 | <enum>QAbstractSpinBox::ButtonSymbols::UpDownArrows</enum> |
| 280 | </property> | 268 | </property> |
| 281 | <property name="suffix"> | 269 | <property name="suffix"> |
| 282 | <string>%</string> | 270 | <string>%</string> |
| @@ -301,6 +289,9 @@ | |||
| 301 | <property name="text"> | 289 | <property name="text"> |
| 302 | <string>Compress</string> | 290 | <string>Compress</string> |
| 303 | </property> | 291 | </property> |
| 292 | <property name="checked"> | ||
| 293 | <bool>true</bool> | ||
| 294 | </property> | ||
| 304 | </widget> | 295 | </widget> |
| 305 | </item> | 296 | </item> |
| 306 | <item> | 297 | <item> |
| @@ -320,7 +311,7 @@ | |||
| 320 | <item> | 311 | <item> |
| 321 | <spacer name="horizontalSpacer_2"> | 312 | <spacer name="horizontalSpacer_2"> |
| 322 | <property name="orientation"> | 313 | <property name="orientation"> |
| 323 | <enum>Qt::Horizontal</enum> | 314 | <enum>Qt::Orientation::Horizontal</enum> |
| 324 | </property> | 315 | </property> |
| 325 | <property name="sizeHint" stdset="0"> | 316 | <property name="sizeHint" stdset="0"> |
| 326 | <size> | 317 | <size> |
| @@ -341,22 +332,22 @@ | |||
| 341 | <widget class="QComboBox" name="comboBox_amplitude"> | 332 | <widget class="QComboBox" name="comboBox_amplitude"> |
| 342 | <item> | 333 | <item> |
| 343 | <property name="text"> | 334 | <property name="text"> |
| 344 | <string>Linear</string> | 335 | <string>Logarithmic</string> |
| 345 | </property> | 336 | </property> |
| 346 | </item> | 337 | </item> |
| 347 | <item> | 338 | <item> |
| 348 | <property name="text"> | 339 | <property name="text"> |
| 349 | <string>Logarithmic</string> | 340 | <string>Square root</string> |
| 350 | </property> | 341 | </property> |
| 351 | </item> | 342 | </item> |
| 352 | <item> | 343 | <item> |
| 353 | <property name="text"> | 344 | <property name="text"> |
| 354 | <string>Square root</string> | 345 | <string>Cubic root</string> |
| 355 | </property> | 346 | </property> |
| 356 | </item> | 347 | </item> |
| 357 | <item> | 348 | <item> |
| 358 | <property name="text"> | 349 | <property name="text"> |
| 359 | <string>Cubic root</string> | 350 | <string>Linear</string> |
| 360 | </property> | 351 | </property> |
| 361 | </item> | 352 | </item> |
| 362 | </widget> | 353 | </widget> |
| @@ -364,9 +355,52 @@ | |||
| 364 | </layout> | 355 | </layout> |
| 365 | </item> | 356 | </item> |
| 366 | <item> | 357 | <item> |
| 358 | <layout class="QHBoxLayout" name="horizontalLayout"> | ||
| 359 | <item> | ||
| 360 | <widget class="QLabel" name="label_speed"> | ||
| 361 | <property name="text"> | ||
| 362 | <string>Animation Speed</string> | ||
| 363 | </property> | ||
| 364 | </widget> | ||
| 365 | </item> | ||
| 366 | <item> | ||
| 367 | <widget class="QSpinBox" name="spinBox_speed"> | ||
| 368 | <property name="suffix"> | ||
| 369 | <string>%</string> | ||
| 370 | </property> | ||
| 371 | <property name="minimum"> | ||
| 372 | <number>10</number> | ||
| 373 | </property> | ||
| 374 | <property name="maximum"> | ||
| 375 | <number>100</number> | ||
| 376 | </property> | ||
| 377 | <property name="singleStep"> | ||
| 378 | <number>10</number> | ||
| 379 | </property> | ||
| 380 | <property name="value"> | ||
| 381 | <number>50</number> | ||
| 382 | </property> | ||
| 383 | </widget> | ||
| 384 | </item> | ||
| 385 | <item> | ||
| 386 | <spacer name="horizontalSpacer_3"> | ||
| 387 | <property name="orientation"> | ||
| 388 | <enum>Qt::Orientation::Horizontal</enum> | ||
| 389 | </property> | ||
| 390 | <property name="sizeHint" stdset="0"> | ||
| 391 | <size> | ||
| 392 | <width>40</width> | ||
| 393 | <height>20</height> | ||
| 394 | </size> | ||
| 395 | </property> | ||
| 396 | </spacer> | ||
| 397 | </item> | ||
| 398 | </layout> | ||
| 399 | </item> | ||
| 400 | <item> | ||
| 367 | <spacer name="verticalSpacer"> | 401 | <spacer name="verticalSpacer"> |
| 368 | <property name="orientation"> | 402 | <property name="orientation"> |
| 369 | <enum>Qt::Vertical</enum> | 403 | <enum>Qt::Orientation::Vertical</enum> |
| 370 | </property> | 404 | </property> |
| 371 | <property name="sizeHint" stdset="0"> | 405 | <property name="sizeHint" stdset="0"> |
| 372 | <size> | 406 | <size> |
diff --git a/src/avp/core.py b/src/avp/core.py index 196cd7d..099b0b4 100644 --- a/src/avp/core.py +++ b/src/avp/core.py | |||
| @@ -12,7 +12,7 @@ import logging | |||
| 12 | 12 | ||
| 13 | from . import toolkit | 13 | from . import toolkit |
| 14 | 14 | ||
| 15 | 15 | appName = "Audio Visualizer Python" | |
| 16 | log = logging.getLogger("AVP.Core") | 16 | log = logging.getLogger("AVP.Core") |
| 17 | STDOUT_LOGLVL = logging.WARNING | 17 | STDOUT_LOGLVL = logging.WARNING |
| 18 | 18 | ||
diff --git a/src/avp/gui/mainwindow.py b/src/avp/gui/mainwindow.py index e7a5fe3..5a051fd 100644 --- a/src/avp/gui/mainwindow.py +++ b/src/avp/gui/mainwindow.py | |||
| @@ -7,7 +7,7 @@ projects and exporting the video at a later time. | |||
| 7 | 7 | ||
| 8 | from PyQt6 import QtCore, QtWidgets, uic | 8 | from PyQt6 import QtCore, QtWidgets, uic |
| 9 | import PyQt6.QtWidgets as QtWidgets | 9 | import PyQt6.QtWidgets as QtWidgets |
| 10 | from PyQt6.QtGui import QUndoStack, QShortcut | 10 | from PyQt6.QtGui import QShortcut |
| 11 | from PIL import Image | 11 | from PIL import Image |
| 12 | from queue import Queue | 12 | from queue import Queue |
| 13 | import sys | 13 | import sys |
| @@ -16,12 +16,16 @@ import signal | |||
| 16 | import filecmp | 16 | import filecmp |
| 17 | import time | 17 | import time |
| 18 | import logging | 18 | import logging |
| 19 | from textwrap import wrap | ||
| 19 | 20 | ||
| 20 | from ..core import Core | 21 | from ..__init__ import __version__ |
| 22 | from ..core import Core, appName | ||
| 23 | from .undostack import UndoStack | ||
| 21 | from . import preview_thread | 24 | from . import preview_thread |
| 22 | from .preview_win import PreviewWindow | 25 | from .preview_win import PreviewWindow |
| 23 | from .presetmanager import PresetManager | 26 | from .presetmanager import PresetManager |
| 24 | from .actions import * | 27 | from .actions import * |
| 28 | from ..toolkit.ffmpeg import createFfmpegCommand | ||
| 25 | from ..toolkit import ( | 29 | from ..toolkit import ( |
| 26 | disableWhenEncoding, | 30 | disableWhenEncoding, |
| 27 | disableWhenOpeningProject, | 31 | disableWhenOpeningProject, |
| @@ -30,25 +34,9 @@ from ..toolkit import ( | |||
| 30 | ) | 34 | ) |
| 31 | 35 | ||
| 32 | 36 | ||
| 33 | appName = "Audio Visualizer" | ||
| 34 | log = logging.getLogger("AVP.Gui.MainWindow") | 37 | log = logging.getLogger("AVP.Gui.MainWindow") |
| 35 | 38 | ||
| 36 | 39 | ||
| 37 | class MyQUndoStack(QUndoStack): | ||
| 38 | # FIXME move this class | ||
| 39 | @property | ||
| 40 | def encoding(self): | ||
| 41 | return self.parent().encoding | ||
| 42 | |||
| 43 | @disableWhenEncoding | ||
| 44 | def undo(self, *args, **kwargs): | ||
| 45 | super().undo(*args, **kwargs) | ||
| 46 | |||
| 47 | @disableWhenEncoding | ||
| 48 | def redo(self, *args, **kwargs): | ||
| 49 | super().redo(*args, **kwargs) | ||
| 50 | |||
| 51 | |||
| 52 | class MainWindow(QtWidgets.QMainWindow): | 40 | class MainWindow(QtWidgets.QMainWindow): |
| 53 | """ | 41 | """ |
| 54 | The MainWindow wraps many Core methods in order to update the GUI | 42 | The MainWindow wraps many Core methods in order to update the GUI |
| @@ -91,7 +79,7 @@ class MainWindow(QtWidgets.QMainWindow): | |||
| 91 | self.settings = Core.settings | 79 | self.settings = Core.settings |
| 92 | 80 | ||
| 93 | # Create stack of undoable user actions | 81 | # Create stack of undoable user actions |
| 94 | self.undoStack = MyQUndoStack(self) | 82 | self.undoStack = UndoStack(self) |
| 95 | undoLimit = self.settings.value("pref_undoLimit") | 83 | undoLimit = self.settings.value("pref_undoLimit") |
| 96 | self.undoStack.setUndoLimit(undoLimit) | 84 | self.undoStack.setUndoLimit(undoLimit) |
| 97 | 85 | ||
| @@ -102,6 +90,7 @@ class MainWindow(QtWidgets.QMainWindow): | |||
| 102 | layout = QtWidgets.QVBoxLayout() | 90 | layout = QtWidgets.QVBoxLayout() |
| 103 | layout.addWidget(undoView) | 91 | layout.addWidget(undoView) |
| 104 | self.undoDialog.setLayout(layout) | 92 | self.undoDialog.setLayout(layout) |
| 93 | self.undoDialog.setMinimumWidth(int(self.width() / 2)) | ||
| 105 | 94 | ||
| 106 | # Create Preset Manager | 95 | # Create Preset Manager |
| 107 | self.presetManager = PresetManager(self) | 96 | self.presetManager = PresetManager(self) |
| @@ -325,7 +314,11 @@ class MainWindow(QtWidgets.QMainWindow): | |||
| 325 | self.drawPreview(True) | 314 | self.drawPreview(True) |
| 326 | 315 | ||
| 327 | log.info("Pillow version %s", Image.__version__) | 316 | log.info("Pillow version %s", Image.__version__) |
| 328 | log.info("PyQt version %s (Qt version %s)", QtCore.PYQT_VERSION_STR, QtCore.QT_VERSION_STR) | 317 | log.info( |
| 318 | "PyQt version %s (Qt version %s)", | ||
| 319 | QtCore.PYQT_VERSION_STR, | ||
| 320 | QtCore.QT_VERSION_STR, | ||
| 321 | ) | ||
| 329 | 322 | ||
| 330 | # verify Ffmpeg version | 323 | # verify Ffmpeg version |
| 331 | if not self.core.FFMPEG_BIN: | 324 | if not self.core.FFMPEG_BIN: |
| @@ -408,6 +401,7 @@ class MainWindow(QtWidgets.QMainWindow): | |||
| 408 | activated=lambda: self.moveComponent("bottom"), | 401 | activated=lambda: self.moveComponent("bottom"), |
| 409 | ) | 402 | ) |
| 410 | 403 | ||
| 404 | QShortcut("F1", self, self.showHelpWindow) | ||
| 411 | QShortcut("Ctrl+Shift+F", self, self.showFfmpegCommand) | 405 | QShortcut("Ctrl+Shift+F", self, self.showFfmpegCommand) |
| 412 | QShortcut("Ctrl+Shift+U", self, self.showUndoStack) | 406 | QShortcut("Ctrl+Shift+U", self, self.showUndoStack) |
| 413 | 407 | ||
| @@ -422,6 +416,12 @@ class MainWindow(QtWidgets.QMainWindow): | |||
| 422 | if not self.core.selectedComponents: | 416 | if not self.core.selectedComponents: |
| 423 | self.core.insertComponent(0, 0, self) | 417 | self.core.insertComponent(0, 0, self) |
| 424 | self.core.insertComponent(1, 1, self) | 418 | self.core.insertComponent(1, 1, self) |
| 419 | # set colors to white and black to match classic appearance of program | ||
| 420 | self.core.selectedComponents[0].page.lineEdit_visColor.setText( | ||
| 421 | "255,255,255" | ||
| 422 | ) | ||
| 423 | self.core.selectedComponents[1].page.lineEdit_color1.setText("0,0,0") | ||
| 424 | self.undoStack.clear() | ||
| 425 | 425 | ||
| 426 | def __repr__(self): | 426 | def __repr__(self): |
| 427 | return ( | 427 | return ( |
| @@ -762,10 +762,10 @@ class MainWindow(QtWidgets.QMainWindow): | |||
| 762 | def showUndoStack(self): | 762 | def showUndoStack(self): |
| 763 | self.undoDialog.show() | 763 | self.undoDialog.show() |
| 764 | 764 | ||
| 765 | def showFfmpegCommand(self): | 765 | def showHelpWindow(self): |
| 766 | from textwrap import wrap | 766 | self.showMessage(msg=f"{appName} v{__version__}") |
| 767 | from ..toolkit.ffmpeg import createFfmpegCommand | ||
| 768 | 767 | ||
| 768 | def showFfmpegCommand(self): | ||
| 769 | command = createFfmpegCommand( | 769 | command = createFfmpegCommand( |
| 770 | self.lineEdit_audioFile.text(), | 770 | self.lineEdit_audioFile.text(), |
| 771 | self.lineEdit_outputFile.text(), | 771 | self.lineEdit_outputFile.text(), |
| @@ -899,7 +899,9 @@ class MainWindow(QtWidgets.QMainWindow): | |||
| 899 | @disableWhenEncoding | 899 | @disableWhenEncoding |
| 900 | def createNewProject(self, prompt=True): | 900 | def createNewProject(self, prompt=True): |
| 901 | if prompt: | 901 | if prompt: |
| 902 | self.openSaveChangesDialog("starting a new project") | 902 | ch = self.openSaveChangesDialog("starting a new project") |
| 903 | if ch is None: | ||
| 904 | return | ||
| 903 | 905 | ||
| 904 | self.clear() | 906 | self.clear() |
| 905 | self.currentProject = None | 907 | self.currentProject = None |
| @@ -919,18 +921,19 @@ class MainWindow(QtWidgets.QMainWindow): | |||
| 919 | 921 | ||
| 920 | def openSaveChangesDialog(self, phrase): | 922 | def openSaveChangesDialog(self, phrase): |
| 921 | success = True | 923 | success = True |
| 924 | ch = True | ||
| 922 | if self.autosaveExists(identical=False): | 925 | if self.autosaveExists(identical=False): |
| 923 | ch = self.showMessage( | 926 | ch = self.showMessage( |
| 924 | msg="You have unsaved changes in project '%s'. " | 927 | msg="You have unsaved changes in project '%s'. " |
| 925 | "Save before %s?" | 928 | "Save before %s?" |
| 926 | % (os.path.basename(self.currentProject)[:-4], phrase), | 929 | % (os.path.basename(self.currentProject)[:-4], phrase), |
| 927 | showCancel=True, | 930 | showDiscard=True, |
| 928 | ) | 931 | ) |
| 929 | if ch: | 932 | if ch: |
| 930 | success = self.saveProjectChanges() | 933 | success = self.saveProjectChanges() |
| 931 | 934 | if ch is not None and success and os.path.exists(self.autosavePath): | |
| 932 | if success and os.path.exists(self.autosavePath): | ||
| 933 | os.remove(self.autosavePath) | 935 | os.remove(self.autosavePath) |
| 936 | return success and ch | ||
| 934 | 937 | ||
| 935 | def openSaveProjectDialog(self): | 938 | def openSaveProjectDialog(self): |
| 936 | filename, _ = QtWidgets.QFileDialog.getSaveFileName( | 939 | filename, _ = QtWidgets.QFileDialog.getSaveFileName( |
| @@ -967,10 +970,12 @@ class MainWindow(QtWidgets.QMainWindow): | |||
| 967 | ): | 970 | ): |
| 968 | return | 971 | return |
| 969 | 972 | ||
| 970 | self.clear() | ||
| 971 | # ask to save any changes that are about to get deleted | 973 | # ask to save any changes that are about to get deleted |
| 972 | if prompt: | 974 | if prompt: |
| 973 | self.openSaveChangesDialog("opening another project") | 975 | ch = self.openSaveChangesDialog("opening another project") |
| 976 | if ch is None: | ||
| 977 | return | ||
| 978 | self.clear() | ||
| 974 | 979 | ||
| 975 | self.currentProject = filepath | 980 | self.currentProject = filepath |
| 976 | self.settings.setValue("currentProject", filepath) | 981 | self.settings.setValue("currentProject", filepath) |
| @@ -992,7 +997,13 @@ class MainWindow(QtWidgets.QMainWindow): | |||
| 992 | else QtWidgets.QMessageBox.Icon.Information | 997 | else QtWidgets.QMessageBox.Icon.Information |
| 993 | ) | 998 | ) |
| 994 | msg.setDetailedText(kwargs["detail"] if "detail" in kwargs else None) | 999 | msg.setDetailedText(kwargs["detail"] if "detail" in kwargs else None) |
| 995 | if "showCancel" in kwargs and kwargs["showCancel"]: | 1000 | if "showDiscard" in kwargs and kwargs["showDiscard"]: |
| 1001 | msg.setStandardButtons( | ||
| 1002 | QtWidgets.QMessageBox.StandardButton.Save | ||
| 1003 | | QtWidgets.QMessageBox.StandardButton.Discard | ||
| 1004 | | QtWidgets.QMessageBox.StandardButton.Cancel | ||
| 1005 | ) | ||
| 1006 | elif "showCancel" in kwargs and kwargs["showCancel"]: | ||
| 996 | msg.setStandardButtons( | 1007 | msg.setStandardButtons( |
| 997 | QtWidgets.QMessageBox.StandardButton.Ok | 1008 | QtWidgets.QMessageBox.StandardButton.Ok |
| 998 | | QtWidgets.QMessageBox.StandardButton.Cancel | 1009 | | QtWidgets.QMessageBox.StandardButton.Cancel |
| @@ -1000,9 +1011,14 @@ class MainWindow(QtWidgets.QMainWindow): | |||
| 1000 | else: | 1011 | else: |
| 1001 | msg.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Ok) | 1012 | msg.setStandardButtons(QtWidgets.QMessageBox.StandardButton.Ok) |
| 1002 | ch = msg.exec() | 1013 | ch = msg.exec() |
| 1003 | if ch == 1024: | 1014 | if ch == 1024 or ch == 2048: |
| 1015 | # OK or Save | ||
| 1004 | return True | 1016 | return True |
| 1005 | return False | 1017 | elif ch > 8000000: |
| 1018 | # Discard | ||
| 1019 | return False | ||
| 1020 | # Cancel | ||
| 1021 | return None | ||
| 1006 | 1022 | ||
| 1007 | @disableWhenEncoding | 1023 | @disableWhenEncoding |
| 1008 | def componentContextMenu(self, QPos): | 1024 | def componentContextMenu(self, QPos): |
diff --git a/src/avp/gui/presetmanager.py b/src/avp/gui/presetmanager.py index 980a969..ca0029d 100644 --- a/src/avp/gui/presetmanager.py +++ b/src/avp/gui/presetmanager.py | |||
| @@ -9,7 +9,7 @@ import os | |||
| 9 | import logging | 9 | import logging |
| 10 | 10 | ||
| 11 | from ..toolkit import badName | 11 | from ..toolkit import badName |
| 12 | from ..core import Core | 12 | from ..core import Core, appName |
| 13 | from .actions import * | 13 | from .actions import * |
| 14 | 14 | ||
| 15 | 15 | ||
| @@ -137,7 +137,7 @@ class PresetManager(QtWidgets.QDialog): | |||
| 137 | currentPreset = selectedComponents[index].currentPreset | 137 | currentPreset = selectedComponents[index].currentPreset |
| 138 | newName, OK = QtWidgets.QInputDialog.getText( | 138 | newName, OK = QtWidgets.QInputDialog.getText( |
| 139 | self.parent, | 139 | self.parent, |
| 140 | "Audio Visualizer", | 140 | appName, |
| 141 | "New Preset Name:", | 141 | "New Preset Name:", |
| 142 | QtWidgets.QLineEdit.EchoMode.Normal, | 142 | QtWidgets.QLineEdit.EchoMode.Normal, |
| 143 | currentPreset, | 143 | currentPreset, |
diff --git a/src/avp/gui/preview_thread.py b/src/avp/gui/preview_thread.py index 1d78516..a59652a 100644 --- a/src/avp/gui/preview_thread.py +++ b/src/avp/gui/preview_thread.py | |||
| @@ -65,17 +65,18 @@ class Worker(QtCore.QObject): | |||
| 65 | component.unlockSize() | 65 | component.unlockSize() |
| 66 | frame = Image.alpha_composite(frame, newFrame) | 66 | frame = Image.alpha_composite(frame, newFrame) |
| 67 | 67 | ||
| 68 | except ValueError as e: | 68 | except (AttributeError, ValueError) as e: |
| 69 | errMsg = ( | 69 | errMsg = ( |
| 70 | "Bad frame returned by %s's preview renderer. " | 70 | "Bad frame returned by %s's preview renderer. " |
| 71 | "%s. New frame size was %s*%s; should be %s*%s." | 71 | "%s. New frame %s." |
| 72 | % ( | 72 | % ( |
| 73 | str(component), | 73 | str(component), |
| 74 | str(e).capitalize(), | 74 | str(e).capitalize(), |
| 75 | newFrame.width, | 75 | "is None" if newFrame is None else "size was %s*%s; should be %s*%s" % ( |
| 76 | newFrame.height, | 76 | newFrame.width, |
| 77 | width, | 77 | newFrame.height, |
| 78 | height, | 78 | width, |
| 79 | height), | ||
| 79 | ) | 80 | ) |
| 80 | ) | 81 | ) |
| 81 | log.critical(errMsg) | 82 | log.critical(errMsg) |
diff --git a/src/avp/gui/undostack.py b/src/avp/gui/undostack.py new file mode 100644 index 0000000..fd1a3e9 --- /dev/null +++ b/src/avp/gui/undostack.py | |||
| @@ -0,0 +1,16 @@ | |||
| 1 | from PyQt6.QtGui import QUndoStack | ||
| 2 | from ..toolkit.common import disableWhenEncoding | ||
| 3 | |||
| 4 | |||
| 5 | class UndoStack(QUndoStack): | ||
| 6 | @property | ||
| 7 | def encoding(self): | ||
| 8 | return self.parent().encoding | ||
| 9 | |||
| 10 | @disableWhenEncoding | ||
| 11 | def undo(self, *args, **kwargs): | ||
| 12 | super().undo(*args, **kwargs) | ||
| 13 | |||
| 14 | @disableWhenEncoding | ||
| 15 | def redo(self, *args, **kwargs): | ||
| 16 | super().redo(*args, **kwargs) | ||
diff --git a/src/avp/toolkit/common.py b/src/avp/toolkit/common.py index e35aba2..a6195ed 100644 --- a/src/avp/toolkit/common.py +++ b/src/avp/toolkit/common.py | |||
| @@ -4,7 +4,7 @@ Common functions | |||
| 4 | 4 | ||
| 5 | from PyQt6 import QtWidgets | 5 | from PyQt6 import QtWidgets |
| 6 | import string | 6 | import string |
| 7 | import os | 7 | import random |
| 8 | import sys | 8 | import sys |
| 9 | import subprocess | 9 | import subprocess |
| 10 | import logging | 10 | import logging |
| @@ -135,7 +135,12 @@ def rgbFromString(string): | |||
| 135 | if i > 255 or i < 0: | 135 | if i > 255 or i < 0: |
| 136 | raise ValueError | 136 | raise ValueError |
| 137 | return tup | 137 | return tup |
| 138 | except: | 138 | except Exception as e: |
| 139 | log.warning( | ||
| 140 | "Could not parse '%s' as a color (encountered %s).", | ||
| 141 | string, | ||
| 142 | type(e).__name__, | ||
| 143 | ) | ||
| 139 | return (255, 255, 255) | 144 | return (255, 255, 255) |
| 140 | 145 | ||
| 141 | 146 | ||
| @@ -150,6 +155,7 @@ def formatTraceback(tb=None): | |||
| 150 | 155 | ||
| 151 | 156 | ||
| 152 | def connectWidget(widget, func): | 157 | def connectWidget(widget, func): |
| 158 | unsupportedWidgets = ["QtWidgets.QFontComboBox"] | ||
| 153 | if type(widget) == QtWidgets.QLineEdit: | 159 | if type(widget) == QtWidgets.QLineEdit: |
| 154 | widget.textChanged.connect(func) | 160 | widget.textChanged.connect(func) |
| 155 | elif type(widget) == QtWidgets.QSpinBox or type(widget) == QtWidgets.QDoubleSpinBox: | 161 | elif type(widget) == QtWidgets.QSpinBox or type(widget) == QtWidgets.QDoubleSpinBox: |
| @@ -158,6 +164,10 @@ def connectWidget(widget, func): | |||
| 158 | widget.stateChanged.connect(func) | 164 | widget.stateChanged.connect(func) |
| 159 | elif type(widget) == QtWidgets.QComboBox: | 165 | elif type(widget) == QtWidgets.QComboBox: |
| 160 | widget.currentIndexChanged.connect(func) | 166 | widget.currentIndexChanged.connect(func) |
| 167 | elif type(widget) in unsupportedWidgets: | ||
| 168 | log.info( | ||
| 169 | "Could not connect %s using connectWidget()", str(widget.__class__.__name__) | ||
| 170 | ) | ||
| 161 | else: | 171 | else: |
| 162 | log.warning("Failed to connect %s ", str(widget.__class__.__name__)) | 172 | log.warning("Failed to connect %s ", str(widget.__class__.__name__)) |
| 163 | return False | 173 | return False |
| @@ -190,3 +200,7 @@ def getWidgetValue(widget): | |||
| 190 | return widget.isChecked() | 200 | return widget.isChecked() |
| 191 | elif type(widget) == QtWidgets.QComboBox: | 201 | elif type(widget) == QtWidgets.QComboBox: |
| 192 | return widget.currentIndex() | 202 | return widget.currentIndex() |
| 203 | |||
| 204 | |||
| 205 | def randomColor(): | ||
| 206 | return (random.randint(0, 255), random.randint(0, 255), random.randint(0, 255)) | ||
diff --git a/src/avp/toolkit/frame.py b/src/avp/toolkit/frame.py index 94537a6..829b05b 100644 --- a/src/avp/toolkit/frame.py +++ b/src/avp/toolkit/frame.py | |||
| @@ -3,7 +3,7 @@ Common tools for drawing compatible frames in a Component's frameRender() | |||
| 3 | """ | 3 | """ |
| 4 | 4 | ||
| 5 | from PyQt6 import QtGui | 5 | from PyQt6 import QtGui |
| 6 | from PIL import Image | 6 | from PIL import Image, ImageEnhance, ImageChops, ImageFilter |
| 7 | from PIL.ImageQt import ImageQt | 7 | from PIL.ImageQt import ImageQt |
| 8 | from PyQt6 import QtCore | 8 | from PyQt6 import QtCore |
| 9 | import sys | 9 | import sys |
| @@ -30,7 +30,7 @@ class FramePainter(QtGui.QPainter): | |||
| 30 | 30 | ||
| 31 | def setPen(self, penStyle): | 31 | def setPen(self, penStyle): |
| 32 | if type(penStyle) is tuple: | 32 | if type(penStyle) is tuple: |
| 33 | super().setPen(PaintColor(*penStyle)) | 33 | super().setPen(QtGui.QColor(*penStyle)) |
| 34 | else: | 34 | else: |
| 35 | super().setPen(penStyle) | 35 | super().setPen(penStyle) |
| 36 | 36 | ||
| @@ -45,24 +45,14 @@ class FramePainter(QtGui.QPainter): | |||
| 45 | buffer.close() | 45 | buffer.close() |
| 46 | self.end() | 46 | self.end() |
| 47 | return frame | 47 | return frame |
| 48 | imBytes = self.image.bits().asstring(self.image.byteCount()) | ||
| 49 | frame = Image.frombytes( | ||
| 50 | "RGBA", (self.image.width(), self.image.height()), imBytes | ||
| 51 | ) | ||
| 52 | self.end() | ||
| 53 | return frame | ||
| 54 | |||
| 55 | 48 | ||
| 56 | class PaintColor(QtGui.QColor): | ||
| 57 | """ | ||
| 58 | Subclass of QtGui.QColor with an added scale() method | ||
| 59 | Previously this class reversed the painter colour to solve | ||
| 60 | hardware issues related to endianness, | ||
| 61 | but Qt appears to deal with this itself nowadays | ||
| 62 | """ | ||
| 63 | 49 | ||
| 64 | def __init__(self, r, g, b, a=255): | 50 | def addShadow(frame, blurRadius, blurOffsetX, blurOffsetY): |
| 65 | super().__init__(r, g, b, a) | 51 | shadImg = ImageEnhance.Contrast(frame).enhance(0.0) |
| 52 | shadImg = shadImg.filter(ImageFilter.GaussianBlur(blurRadius)) | ||
| 53 | frame = shadImg.paste(frame, box=(-blurOffsetX, -blurOffsetY), mask=frame) | ||
| 54 | frame = shadImg | ||
| 55 | return frame | ||
| 66 | 56 | ||
| 67 | 57 | ||
| 68 | def scale(scalePercent, width, height, returntype=None): | 58 | def scale(scalePercent, width, height, returntype=None): |
diff --git a/src/avp/toolkit/visualizer.py b/src/avp/toolkit/visualizer.py new file mode 100644 index 0000000..c55a3f3 --- /dev/null +++ b/src/avp/toolkit/visualizer.py | |||
| @@ -0,0 +1,87 @@ | |||
| 1 | """Functions used to transform and manipulate audio for use by visualizers""" | ||
| 2 | |||
| 3 | from copy import copy | ||
| 4 | import numpy | ||
| 5 | |||
| 6 | |||
| 7 | def createSpectrumArray( | ||
| 8 | component, | ||
| 9 | completeAudioArray, | ||
| 10 | sampleSize, | ||
| 11 | smoothConstantDown, | ||
| 12 | smoothConstantUp, | ||
| 13 | scale, | ||
| 14 | progressBarUpdate, | ||
| 15 | progressBarSetText, | ||
| 16 | ): | ||
| 17 | lastSpectrum = None | ||
| 18 | spectrumArray = {} | ||
| 19 | for i in range(0, len(completeAudioArray), sampleSize): | ||
| 20 | if component.canceled: | ||
| 21 | break | ||
| 22 | lastSpectrum = transformData( | ||
| 23 | i, | ||
| 24 | completeAudioArray, | ||
| 25 | sampleSize, | ||
| 26 | smoothConstantDown, | ||
| 27 | smoothConstantUp, | ||
| 28 | lastSpectrum, | ||
| 29 | scale, | ||
| 30 | ) | ||
| 31 | spectrumArray[i] = copy(lastSpectrum) | ||
| 32 | |||
| 33 | progress = int(100 * (i / len(completeAudioArray))) | ||
| 34 | if progress >= 100: | ||
| 35 | progress = 100 | ||
| 36 | progressText = f"Analyzing audio: {str(progress)}%" | ||
| 37 | progressBarSetText.emit(progressText) | ||
| 38 | progressBarUpdate.emit(int(progress)) | ||
| 39 | return spectrumArray | ||
| 40 | |||
| 41 | |||
| 42 | def transformData( | ||
| 43 | i, | ||
| 44 | completeAudioArray, | ||
| 45 | sampleSize, | ||
| 46 | smoothConstantDown, | ||
| 47 | smoothConstantUp, | ||
| 48 | lastSpectrum, | ||
| 49 | scale, | ||
| 50 | ): | ||
| 51 | if len(completeAudioArray) < (i + sampleSize): | ||
| 52 | sampleSize = len(completeAudioArray) - i | ||
| 53 | |||
| 54 | window = numpy.hanning(sampleSize) | ||
| 55 | data = completeAudioArray[i : i + sampleSize][::1] * window | ||
| 56 | paddedSampleSize = 2048 | ||
| 57 | paddedData = numpy.pad(data, (0, paddedSampleSize - sampleSize), "constant") | ||
| 58 | spectrum = numpy.fft.fft(paddedData) | ||
| 59 | sample_rate = 44100 | ||
| 60 | frequencies = numpy.fft.fftfreq(len(spectrum), 1.0 / sample_rate) | ||
| 61 | |||
| 62 | y = abs(spectrum[0 : int(paddedSampleSize / 2) - 1]) | ||
| 63 | |||
| 64 | # filter the noise away | ||
| 65 | # y[y<80] = 0 | ||
| 66 | |||
| 67 | with numpy.errstate(divide="ignore"): | ||
| 68 | y = scale * numpy.log10(y) | ||
| 69 | |||
| 70 | y[numpy.isinf(y)] = 0 | ||
| 71 | |||
| 72 | if lastSpectrum is not None: | ||
| 73 | lastSpectrum[y < lastSpectrum] = y[ | ||
| 74 | y < lastSpectrum | ||
| 75 | ] * smoothConstantDown + lastSpectrum[y < lastSpectrum] * ( | ||
| 76 | 1 - smoothConstantDown | ||
| 77 | ) | ||
| 78 | |||
| 79 | lastSpectrum[y >= lastSpectrum] = y[ | ||
| 80 | y >= lastSpectrum | ||
| 81 | ] * smoothConstantUp + lastSpectrum[y >= lastSpectrum] * (1 - smoothConstantUp) | ||
| 82 | else: | ||
| 83 | lastSpectrum = y | ||
| 84 | |||
| 85 | x = frequencies[0 : int(paddedSampleSize / 2) - 1] | ||
| 86 | |||
| 87 | return lastSpectrum | ||
diff --git a/tests/test_commandline_parser.py b/tests/test_commandline_parser.py index d092072..77836ce 100644 --- a/tests/test_commandline_parser.py +++ b/tests/test_commandline_parser.py | |||
| @@ -51,6 +51,11 @@ def test_commandline_parses_classic_by_alias(qtbot): | |||
| 51 | assert command.parseCompName("original") == "Classic Visualizer" | 51 | assert command.parseCompName("original") == "Classic Visualizer" |
| 52 | 52 | ||
| 53 | 53 | ||
| 54 | def test_commandline_parses_conway_by_name(qtbot): | 54 | def test_commandline_parses_conway_by_short_name(qtbot): |
| 55 | command = Command() | 55 | command = Command() |
| 56 | assert command.parseCompName("conway") == "Conway's Game of Life" | 56 | assert command.parseCompName("conway") == "Conway's Game of Life" |
| 57 | |||
| 58 | |||
| 59 | def test_commandline_parses_image_by_name(qtbot): | ||
| 60 | command = Command() | ||
| 61 | assert command.parseCompName("image") == "Image" | ||
diff --git a/tests/test_comp_color.py b/tests/test_comp_color.py new file mode 100644 index 0000000..6b82e4c --- /dev/null +++ b/tests/test_comp_color.py | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | from avp.command import Command | ||
| 2 | from pytestqt import qtbot | ||
| 3 | from pytest import fixture | ||
| 4 | from . import imageDataSum | ||
| 5 | |||
| 6 | |||
| 7 | @fixture | ||
| 8 | def coreWithColorComp(qtbot): | ||
| 9 | """Fixture providing a Command object with Color component added""" | ||
| 10 | command = Command() | ||
| 11 | command.settings.setValue("outputHeight", 1080) | ||
| 12 | command.settings.setValue("outputWidth", 1920) | ||
| 13 | command.core.insertComponent(0, command.core.moduleIndexFor("Color"), command) | ||
| 14 | yield command.core | ||
| 15 | |||
| 16 | |||
| 17 | def test_comp_color_set_color(coreWithColorComp): | ||
| 18 | "Set imagePath of Image component" | ||
| 19 | comp = coreWithColorComp.selectedComponents[0] | ||
| 20 | comp.page.lineEdit_color1.setText("111,111,111") | ||
| 21 | image = comp.previewRender() | ||
| 22 | assert imageDataSum(image) == 1219276800 | ||
diff --git a/tests/test_image_comp.py b/tests/test_comp_image.py index a4f05e1..a4f05e1 100644 --- a/tests/test_image_comp.py +++ b/tests/test_comp_image.py | |||
diff --git a/tests/test_comp_life.py b/tests/test_comp_life.py new file mode 100644 index 0000000..ad78e52 --- /dev/null +++ b/tests/test_comp_life.py | |||
| @@ -0,0 +1,23 @@ | |||
| 1 | from avp.command import Command | ||
| 2 | from pytestqt import qtbot | ||
| 3 | from pytest import fixture | ||
| 4 | from . import imageDataSum | ||
| 5 | |||
| 6 | |||
| 7 | @fixture | ||
| 8 | def coreWithLifeComp(qtbot): | ||
| 9 | """Fixture providing a Command object with Waveform component added""" | ||
| 10 | command = Command() | ||
| 11 | command.settings.setValue("outputHeight", 1080) | ||
| 12 | command.settings.setValue("outputWidth", 1920) | ||
| 13 | command.core.insertComponent( | ||
| 14 | 0, command.core.moduleIndexFor("Conway's Game of Life"), command | ||
| 15 | ) | ||
| 16 | yield command.core | ||
| 17 | |||
| 18 | |||
| 19 | def test_comp_life_previewRender(coreWithLifeComp): | ||
| 20 | comp = coreWithLifeComp.selectedComponents[0] | ||
| 21 | comp.page.lineEdit_color.setText("111,111,111") | ||
| 22 | image = comp.previewRender() | ||
| 23 | assert imageDataSum(image) == 339785512 | ||
diff --git a/tests/test_classic_visualizer.py b/tests/test_comp_original.py index e301263..6264644 100644 --- a/tests/test_classic_visualizer.py +++ b/tests/test_comp_original.py | |||
| @@ -1,4 +1,5 @@ | |||
| 1 | from avp.command import Command | 1 | from avp.command import Command |
| 2 | from avp.toolkit.visualizer import transformData | ||
| 2 | from pytestqt import qtbot | 3 | from pytestqt import qtbot |
| 3 | from pytest import fixture | 4 | from pytest import fixture |
| 4 | from . import audioData, MockSignal, imageDataSum | 5 | from . import audioData, MockSignal, imageDataSum |
| @@ -31,13 +32,9 @@ def test_comp_classic_removed(coreWithClassicComp): | |||
| 31 | def test_comp_classic_drawBars(coreWithClassicComp, audioData): | 32 | def test_comp_classic_drawBars(coreWithClassicComp, audioData): |
| 32 | """Call drawBars after creating audio spectrum data manually.""" | 33 | """Call drawBars after creating audio spectrum data manually.""" |
| 33 | 34 | ||
| 34 | spectrumArray = { | 35 | spectrumArray = {0: transformData(0, audioData[0], sampleSize, 0.08, 0.8, None, 20)} |
| 35 | 0: coreWithClassicComp.selectedComponents[0].transformData( | ||
| 36 | 0, audioData[0], sampleSize, 0.08, 0.8, None, 20 | ||
| 37 | ) | ||
| 38 | } | ||
| 39 | for i in range(sampleSize, len(audioData[0]), sampleSize): | 36 | for i in range(sampleSize, len(audioData[0]), sampleSize): |
| 40 | spectrumArray[i] = coreWithClassicComp.selectedComponents[0].transformData( | 37 | spectrumArray[i] = transformData( |
| 41 | i, | 38 | i, |
| 42 | audioData[0], | 39 | audioData[0], |
| 43 | sampleSize, | 40 | sampleSize, |
diff --git a/tests/test_comp_spectrum.py b/tests/test_comp_spectrum.py new file mode 100644 index 0000000..44fb257 --- /dev/null +++ b/tests/test_comp_spectrum.py | |||
| @@ -0,0 +1,20 @@ | |||
| 1 | from avp.command import Command | ||
| 2 | from pytestqt import qtbot | ||
| 3 | from pytest import fixture | ||
| 4 | from . import imageDataSum | ||
| 5 | |||
| 6 | |||
| 7 | @fixture | ||
| 8 | def coreWithSpectrumComp(qtbot): | ||
| 9 | """Fixture providing a Command object with Spectrum component added""" | ||
| 10 | command = Command() | ||
| 11 | command.settings.setValue("outputHeight", 1080) | ||
| 12 | command.settings.setValue("outputWidth", 1920) | ||
| 13 | command.core.insertComponent(0, command.core.moduleIndexFor("Spectrum"), command) | ||
| 14 | yield command.core | ||
| 15 | |||
| 16 | |||
| 17 | def test_comp_waveform_previewRender(coreWithSpectrumComp): | ||
| 18 | comp = coreWithSpectrumComp.selectedComponents[0] | ||
| 19 | image = comp.previewRender() | ||
| 20 | assert imageDataSum(image) == 71992628 | ||
diff --git a/tests/test_comp_text.py b/tests/test_comp_text.py new file mode 100644 index 0000000..e389ff9 --- /dev/null +++ b/tests/test_comp_text.py | |||
| @@ -0,0 +1,45 @@ | |||
| 1 | from avp.command import Command | ||
| 2 | from PyQt6.QtGui import QFont | ||
| 3 | from pytestqt import qtbot | ||
| 4 | from pytest import fixture, mark | ||
| 5 | from . import audioData, MockSignal, imageDataSum | ||
| 6 | |||
| 7 | |||
| 8 | @fixture | ||
| 9 | def coreWithTextComp(qtbot): | ||
| 10 | """Fixture providing a Command object with Title Text component added""" | ||
| 11 | command = Command() | ||
| 12 | command.core.insertComponent(0, command.core.moduleIndexFor("Title Text"), command) | ||
| 13 | yield command.core | ||
| 14 | |||
| 15 | |||
| 16 | def setTextSettings(comp): | ||
| 17 | comp.page.spinBox_fontSize.setValue(40) | ||
| 18 | comp.page.checkBox_shadow.setChecked(True) | ||
| 19 | comp.page.spinBox_shadBlur.setValue(0) | ||
| 20 | comp.page.spinBox_shadX.setValue(2) | ||
| 21 | comp.page.spinBox_shadY.setValue(-2) | ||
| 22 | comp.page.fontComboBox_titleFont.setCurrentFont(QFont("Noto Sans")) | ||
| 23 | comp.page.lineEdit_textColor.setText("255,255,255") | ||
| 24 | |||
| 25 | |||
| 26 | @mark.parametrize( | ||
| 27 | "width, height", | ||
| 28 | ((1920, 1080), (1280, 720)), | ||
| 29 | ) | ||
| 30 | def test_comp_text_renderFrame(coreWithTextComp, width, height): | ||
| 31 | """Call renderFrame of Title Text component added to Command object.""" | ||
| 32 | comp = coreWithTextComp.selectedComponents[0] | ||
| 33 | comp.parent.settings.setValue("outputWidth", width) | ||
| 34 | comp.parent.settings.setValue("outputHeight", height) | ||
| 35 | setTextSettings(comp) | ||
| 36 | comp.centerXY() | ||
| 37 | image = comp.frameRender(0) | ||
| 38 | assert comp.titleFont.family() == "Noto Sans" | ||
| 39 | assert comp.xPosition == width / 2 | ||
| 40 | assert image.width == width | ||
| 41 | assert comp.fontSize == 40 | ||
| 42 | assert comp.shadX == 2 | ||
| 43 | assert comp.shadY == -2 | ||
| 44 | assert comp.shadBlur == 0 | ||
| 45 | assert imageDataSum(image) == 727403 or 738586 | ||
diff --git a/tests/test_comp_waveform.py b/tests/test_comp_waveform.py new file mode 100644 index 0000000..a71040b --- /dev/null +++ b/tests/test_comp_waveform.py | |||
| @@ -0,0 +1,17 @@ | |||
| 1 | from avp.command import Command | ||
| 2 | from pytestqt import qtbot | ||
| 3 | from pytest import fixture | ||
| 4 | |||
| 5 | |||
| 6 | @fixture | ||
| 7 | def coreWithWaveformComp(qtbot): | ||
| 8 | """Fixture providing a Command object with Waveform component added""" | ||
| 9 | command = Command() | ||
| 10 | command.core.insertComponent(0, command.core.moduleIndexFor("Waveform"), command) | ||
| 11 | yield command.core | ||
| 12 | |||
| 13 | |||
| 14 | def test_comp_waveform_setColor(coreWithWaveformComp): | ||
| 15 | comp = coreWithWaveformComp.selectedComponents[0] | ||
| 16 | comp.page.lineEdit_color.setText("255,255,255") | ||
| 17 | assert comp.color == (255, 255, 255) | ||
diff --git a/tests/test_text_comp.py b/tests/test_text_comp.py deleted file mode 100644 index 23dd1fd..0000000 --- a/tests/test_text_comp.py +++ /dev/null | |||
| @@ -1,34 +0,0 @@ | |||
| 1 | from avp.command import Command | ||
| 2 | from PyQt6.QtGui import QFont | ||
| 3 | from pytestqt import qtbot | ||
| 4 | from pytest import fixture | ||
| 5 | from . import audioData, MockSignal, imageDataSum | ||
| 6 | |||
| 7 | |||
| 8 | @fixture | ||
| 9 | def coreWithTextComp(qtbot): | ||
| 10 | """Fixture providing a Command object with Title Text component added""" | ||
| 11 | command = Command() | ||
| 12 | command.core.insertComponent(0, command.core.moduleIndexFor("Title Text"), command) | ||
| 13 | yield command.core | ||
| 14 | |||
| 15 | |||
| 16 | def test_comp_text_renderFrame_resize(coreWithTextComp): | ||
| 17 | """Call renderFrame of Title Text component added to Command object.""" | ||
| 18 | comp = coreWithTextComp.selectedComponents[0] | ||
| 19 | comp.parent.settings.setValue("outputWidth", 1920) | ||
| 20 | comp.parent.settings.setValue("outputHeight", 1080) | ||
| 21 | comp.parent.core.updateComponent(0) | ||
| 22 | comp.titleFont = QFont("Noto Sans") | ||
| 23 | image = comp.frameRender(0) | ||
| 24 | assert imageDataSum(image) == 2957069 | ||
| 25 | |||
| 26 | |||
| 27 | def test_comp_text_renderFrame(coreWithTextComp): | ||
| 28 | """Call renderFrame of Title Text component added to Command object.""" | ||
| 29 | comp = coreWithTextComp.selectedComponents[0] | ||
| 30 | comp.parent.settings.setValue("outputWidth", 1280) | ||
| 31 | comp.parent.settings.setValue("outputHeight", 720) | ||
| 32 | comp.parent.core.updateComponent(0) | ||
| 33 | image = comp.frameRender(0) | ||
| 34 | assert imageDataSum(image) == 1412293 or 1379298 | ||
diff --git a/tests/test_toolkit_common.py b/tests/test_toolkit_common.py index d903842..8e9dca2 100644 --- a/tests/test_toolkit_common.py +++ b/tests/test_toolkit_common.py | |||
| @@ -1,6 +1,27 @@ | |||
| 1 | from pytest import fixture | ||
| 1 | from pytestqt import qtbot | 2 | from pytestqt import qtbot |
| 2 | from avp.command import Command | 3 | from avp.command import Command |
| 3 | from avp.toolkit import blockSignals | 4 | from avp.toolkit import blockSignals, rgbFromString |
| 5 | |||
| 6 | |||
| 7 | @fixture | ||
| 8 | def gotWarning(): | ||
| 9 | """Check if a function called log.warning""" | ||
| 10 | import avp.toolkit.common as tk | ||
| 11 | warning = False | ||
| 12 | def gotWarning(): | ||
| 13 | nonlocal warning | ||
| 14 | return warning | ||
| 15 | class log: | ||
| 16 | def warning(self, *args): | ||
| 17 | nonlocal warning | ||
| 18 | warning = True | ||
| 19 | oldLog = tk.log | ||
| 20 | tk.log = log() | ||
| 21 | try: | ||
| 22 | yield gotWarning | ||
| 23 | finally: | ||
| 24 | tk.log = oldLog | ||
| 4 | 25 | ||
| 5 | 26 | ||
| 6 | def test_blockSignals(qtbot): | 27 | def test_blockSignals(qtbot): |
| @@ -11,3 +32,13 @@ def test_blockSignals(qtbot): | |||
| 11 | with blockSignals(comp.page.spinBox_scale): | 32 | with blockSignals(comp.page.spinBox_scale): |
| 12 | assert comp.page.spinBox_scale.signalsBlocked() == True | 33 | assert comp.page.spinBox_scale.signalsBlocked() == True |
| 13 | assert comp.page.spinBox_scale.signalsBlocked() == False | 34 | assert comp.page.spinBox_scale.signalsBlocked() == False |
| 35 | |||
| 36 | |||
| 37 | def test_rgbFromString(gotWarning): | ||
| 38 | assert rgbFromString("255,255,255") == (255, 255, 255) | ||
| 39 | assert not gotWarning() | ||
| 40 | |||
| 41 | |||
| 42 | def test_rgbFromString_error(gotWarning): | ||
| 43 | assert rgbFromString("255,255,256") == (255, 255, 255) | ||
| 44 | assert gotWarning() \ No newline at end of file | ||
| @@ -4,7 +4,7 @@ requires-python = ">=3.12" | |||
| 4 | 4 | ||
| 5 | [[package]] | 5 | [[package]] |
| 6 | name = "audio-visualizer-python" | 6 | name = "audio-visualizer-python" |
| 7 | version = "2.2.0" | 7 | version = "2.2.1" |
| 8 | source = { editable = "." } | 8 | source = { editable = "." } |
| 9 | dependencies = [ | 9 | dependencies = [ |
| 10 | { name = "numpy" }, | 10 | { name = "numpy" }, |
