void-packages/srcpkgs/openshot/patches/0002-python3.10_int.patch
tibequadorian b9550a4537 openshot: update to 2.6.1.
enable for all archs and libc
patches are upstream
2022-02-25 23:52:29 +00:00

1993 lines
101 KiB
Diff

From a3088503500e79877ce985e4784f75478d9b792e Mon Sep 17 00:00:00 2001
From: "FeRD (Frank Dana)" <ferdnyc@gmail.com>
Date: Mon, 20 Sep 2021 05:36:19 -0400
Subject: [PATCH 1/6] Preferences: Fix logging calls
---
src/launch.py | 2 +-
src/windows/preferences.py | 18 +++++++++++-------
2 files changed, 12 insertions(+), 8 deletions(-)
diff --git a/src/launch.py b/src/launch.py
index 9fc600b23..b614e9bc7 100755
--- a/src/launch.py
+++ b/src/launch.py
@@ -41,7 +41,7 @@
"""
import sys
-import os.path
+import os
import argparse
from PyQt5.QtCore import Qt
diff --git a/src/windows/preferences.py b/src/windows/preferences.py
index bf7d67b0c..325f496b3 100644
--- a/src/windows/preferences.py
+++ b/src/windows/preferences.py
@@ -102,7 +102,7 @@ def __init__(self):
def txtSearch_changed(self):
"""textChanged event handler for search box"""
- log.info("Search for %s" % self.txtSearch.text())
+ log.info("Search for %s", self.txtSearch.text())
# Populate preferences
self.Populate(filter=self.txtSearch.text())
@@ -317,7 +317,7 @@ def Populate(self, filter=""):
value_list.remove(value_item)
# Remove hardware mode items which cannot decode the example video
- log.debug("Preparing to test hardware decoding: %s" % (value_list))
+ log.debug("Preparing to test hardware decoding: %s", value_list)
for value_item in list(value_list):
v = value_item["value"]
if (not self.testHardwareDecode(value_list, v, 0)
@@ -470,7 +470,7 @@ def bool_value_changed(self, widget, param, state):
# Trigger specific actions
if param["setting"] == "debug-mode":
# Update debug setting of timeline
- log.info("Setting debug-mode to %s" % (state == Qt.Checked))
+ log.info("Setting debug-mode to %s", state == Qt.Checked)
debug_enabled = (state == Qt.Checked)
# Enable / Disable logger
@@ -528,7 +528,9 @@ def text_value_changed(self, widget, param, value=None):
if param.get("category") == "Keyboard":
previous_value = value
value = QKeySequence(value).toString()
- log.info("Parsing keyboard mapping via QKeySequence from %s to %s" % (previous_value, value))
+ log.info(
+ "Parsing keyboard mapping via QKeySequence from %s to %s",
+ previous_value, value)
# Save setting
self.s.set(param["setting"], value)
@@ -604,11 +606,13 @@ def testHardwareDecode(self, all_decoders, decoder, decoder_card="0"):
if reader.GetFrame(0).CheckPixel(0, 0, 2, 133, 255, 255, 5):
is_supported = True
self.hardware_tests_cards[decoder_card].append(int(decoder))
- log.debug("Successful hardware decoder! %s (%s-%s)" % (decoder_name, decoder, decoder_card))
+ log.debug(
+ "Successful hardware decoder! %s (%s-%s)",
+ decoder_name, decoder, decoder_card)
else:
log.debug(
"CheckPixel failed testing hardware decoding (i.e. wrong color found): %s (%s-%s)",
- (decoder_name, decoder, decoder_card))
+ decoder_name, decoder, decoder_card)
reader.Close()
clip.Close()
@@ -616,7 +620,7 @@ def testHardwareDecode(self, all_decoders, decoder, decoder_card="0"):
except Exception:
log.debug(
"Exception trying to test hardware decoding (this is expected): %s (%s-%s)",
- (decoder_name, decoder, decoder_card))
+ decoder_name, decoder, decoder_card)
# Resume current settings
openshot.Settings.Instance().HARDWARE_DECODER = current_decoder
From 1b14896d2057df80b0b20ba22e1380ba9e9bd6e6 Mon Sep 17 00:00:00 2001
From: "FeRD (Frank Dana)" <ferdnyc@gmail.com>
Date: Thu, 4 Nov 2021 21:01:39 -0400
Subject: [PATCH 2/6] Enforce integer function arguments
---
src/windows/export.py | 8 +-
src/windows/models/properties_model.py | 34 +-
src/windows/process_effect.py | 2 +-
src/windows/video_widget.py | 596 ++++++++++++++--------
src/windows/views/effects_listview.py | 7 +-
src/windows/views/effects_treeview.py | 7 +-
src/windows/views/emojis_listview.py | 7 +-
src/windows/views/files_listview.py | 7 +-
src/windows/views/files_treeview.py | 7 +-
src/windows/views/properties_tableview.py | 38 +-
src/windows/views/transitions_listview.py | 7 +-
src/windows/views/transitions_treeview.py | 7 +-
src/windows/views/tutorial.py | 14 +-
13 files changed, 476 insertions(+), 265 deletions(-)
diff --git a/src/windows/export.py b/src/windows/export.py
index a624eb2e2..6461afb25 100644
--- a/src/windows/export.py
+++ b/src/windows/export.py
@@ -290,7 +290,7 @@ def updateProgressBar(self, title_message, start_frame, end_frame, current_frame
percentage_string = format_of_progress_string % (( current_frame - start_frame ) / ( end_frame - start_frame ) * 100)
else:
percentage_string = "100%"
- self.progressExportVideo.setValue(current_frame)
+ self.progressExportVideo.setValue(int(current_frame))
self.progressExportVideo.setFormat(percentage_string)
self.setWindowTitle("%s %s" % (percentage_string, title_message))
@@ -690,9 +690,9 @@ def titlestring(sec, fps, mess):
fps_encode = 0
# Init progress bar
- self.progressExportVideo.setMinimum(self.txtStartFrame.value())
- self.progressExportVideo.setMaximum(self.txtEndFrame.value())
- self.progressExportVideo.setValue(self.txtStartFrame.value())
+ self.progressExportVideo.setMinimum(int(self.txtStartFrame.value()))
+ self.progressExportVideo.setMaximum(int(self.txtEndFrame.value()))
+ self.progressExportVideo.setValue(int(self.txtStartFrame.value()))
# Prompt error message
if self.txtStartFrame.value() == self.txtEndFrame.value():
diff --git a/src/windows/models/properties_model.py b/src/windows/models/properties_model.py
index c3236ed84..40897f642 100644
--- a/src/windows/models/properties_model.py
+++ b/src/windows/models/properties_model.py
@@ -414,8 +414,8 @@ def value_updated(self, item, interpolation=-1, value=None, interpolation_detail
new_value = None
log.info(
- "%s for %s changed to %s at frame %s with interpolation: %s at closest x: %s"
- % (property_key, clip_id, new_value, self.frame_number, interpolation, closest_point_x))
+ "%s for %s changed to %s at frame %s with interpolation: %s at closest x: %s",
+ property_key, clip_id, new_value, self.frame_number, interpolation, closest_point_x)
# Find this clip
c = None
@@ -518,35 +518,35 @@ def value_updated(self, item, interpolation=-1, value=None, interpolation_detail
try:
clip_data[property_key] = int(new_value)
except Exception as ex:
- log.warn('Invalid Integer value passed to property: %s' % ex)
+ log.warn('Invalid Integer value passed to property', exc_info=1)
elif property_type == "float":
clip_updated = True
try:
clip_data[property_key] = float(new_value)
except Exception as ex:
- log.warn('Invalid Float value passed to property: %s' % ex)
+ log.warn('Invalid Float value passed to property', exc_info=1)
elif property_type == "bool":
clip_updated = True
try:
clip_data[property_key] = bool(new_value)
except Exception as ex:
- log.warn('Invalid Boolean value passed to property: %s' % ex)
+ log.warn('Invalid Boolean value passed to property', exc_info=1)
elif property_type == "string":
clip_updated = True
try:
clip_data[property_key] = str(new_value)
- except Exception as ex:
- log.warn('Invalid String value passed to property: %s' % ex)
+ except Exception:
+ log.warn('Invalid String value passed to property', exc_info=1)
elif property_type in ["font", "caption"]:
clip_updated = True
try:
clip_data[property_key] = str(new_value)
- except Exception as ex:
- log.warn('Invalid Font/Caption value passed to property: %s' % ex)
+ except Exception:
+ log.warn('Invalid Font/Caption value passed to property', exc_info=1)
elif property_type == "reader":
# Transition
@@ -557,8 +557,8 @@ def value_updated(self, item, interpolation=-1, value=None, interpolation_detail
clip_data[property_key] = json.loads(clip_object.Reader().Json())
clip_object.Close()
clip_object = None
- except Exception as ex:
- log.warn('Invalid Reader value passed to property: %s (%s)' % (value, ex))
+ except Exception:
+ log.warn('Invalid Reader value passed to property: %s (%s)', value, exc_info=1)
# Reduce # of clip properties we are saving (performance boost)
clip_data = {property_key: clip_data.get(property_key)}
@@ -688,9 +688,9 @@ def set_property(self, property, filter, c, item_type, object_id=None):
if type == "color":
# Color needs to be handled special
- red = property[1]["red"]["value"]
- green = property[1]["green"]["value"]
- blue = property[1]["blue"]["value"]
+ red = int(property[1]["red"]["value"])
+ green = int(property[1]["green"]["value"])
+ blue = int(property[1]["blue"]["value"])
col.setBackground(QColor(red, green, blue))
if readonly or type in ["color", "font", "caption"] or choices or label == "Track":
@@ -789,9 +789,9 @@ def set_property(self, property, filter, c, item_type, object_id=None):
if type == "color":
# Update the color based on the color curves
- red = property[1]["red"]["value"]
- green = property[1]["green"]["value"]
- blue = property[1]["blue"]["value"]
+ red = int(property[1]["red"]["value"])
+ green = int(property[1]["green"]["value"])
+ blue = int(property[1]["blue"]["value"])
col.setBackground(QColor(red, green, blue))
# Update helper dictionary
diff --git a/src/windows/process_effect.py b/src/windows/process_effect.py
index e4f3120c0..ea0c2946e 100644
--- a/src/windows/process_effect.py
+++ b/src/windows/process_effect.py
@@ -352,7 +352,7 @@ def accept(self):
while(not processing.IsDone() ):
# update progressbar
progressionStatus = processing.GetProgress()
- self.progressBar.setValue(progressionStatus)
+ self.progressBar.setValue(int(progressionStatus))
time.sleep(0.01)
# Process any queued events
diff --git a/src/windows/video_widget.py b/src/windows/video_widget.py
index d5c89a204..f33696c5c 100644
--- a/src/windows/video_widget.py
+++ b/src/windows/video_widget.py
@@ -25,8 +25,11 @@
along with OpenShot Library. If not, see <http://www.gnu.org/licenses/>.
"""
+import json
+
from PyQt5.QtCore import (
- Qt, QCoreApplication, QPointF, QPoint, QRect, QRectF, QSize, QMutex, QTimer
+ Qt, QCoreApplication, QMutex, QTimer,
+ QPoint, QPointF, QSize, QSizeF, QRect, QRectF,
)
from PyQt5.QtGui import (
QTransform, QPainter, QIcon, QColor, QPen, QBrush, QCursor, QImage, QRegion
@@ -41,8 +44,6 @@
from classes.app import get_app
from classes.query import Clip, Effect
-import json
-
class VideoWidget(QWidget, updates.UpdateInterface):
""" A QWidget used on the video display widget """
@@ -86,37 +87,68 @@ def changed(self, action):
self.pixel_ratio.ToFloat())
- def drawTransformHandler(self, painter, sx, sy, source_width, source_height, origin_x, origin_y,
- x1=None, y1=None, x2=None, y2=None, rotation = None):
+ def drawTransformHandler(
+ self, painter, sx, sy, source_width, source_height,
+ origin_x, origin_y,
+ x1=None, y1=None, x2=None, y2=None, rotation = None
+ ):
# Draw transform corners and center origin circle
# Corner size
cs = self.cs
os = 12.0
+ csx = cs / sx
+ csy = cs / sy
+
# Rotate the transform handler
if rotation:
- bbox_center_x = (((x1*source_width + x2*source_width) / 2.0) ) - ( (os/2) /sx)
- bbox_center_y = (((y1*source_height + y2*source_height) / 2.0) ) - ( (os/2) /sy)
+ bbox_center_x = ((x1*source_width + x2*source_width) / 2.0) - ((os / 2) / sx)
+ bbox_center_y = ((y1*source_height + y2*source_height) / 2.0) - ((os / 2) / sy)
painter.translate(bbox_center_x, bbox_center_y)
painter.rotate(rotation)
painter.translate(-bbox_center_x, -bbox_center_y)
- if(x1 and y1 and x2 and y2):
+ if all([x1, y1, x2, y2]):
# Calculate bounds of clip
- self.clipBounds = QRectF(QPointF(x1*source_width, y1*source_height), QPointF(x2*source_width, y2*source_height))
+ self.clipBounds = QRectF(
+ QPointF(x1 * source_width, y1 * source_height),
+ QPointF(x2 * source_width, y2 * source_height)
+ )
# Calculate 4 corners coordinates
- self.topLeftHandle = QRectF(x1*source_width -(cs/sx/2.0), y1*source_height-(cs/sy/2.0), cs/sx, cs/sy)
- self.topRightHandle = QRectF(x2*source_width-(cs/sx/2.0), y1*source_height-(cs/sy/2.0), cs/sx, cs/sy)
- self.bottomLeftHandle = QRectF(x1*source_width -(cs/sx/2.0), y2*source_height-(cs/sy/2.0), cs/sx, cs/sy)
- self.bottomRightHandle = QRectF(x2*source_width-(cs/sx/2.0), y2*source_height-(cs/sy/2.0), cs/sx, cs/sy)
+ self.topLeftHandle = QRectF(
+ x1 * source_width - (csx / 2.0),
+ y1 * source_height - (csy / 2.0),
+ csx,
+ csy)
+ self.topRightHandle = QRectF(
+ x2 * source_width - (csx / 2.0),
+ y1 * source_height - (csy / 2.0),
+ csx,
+ csy)
+ self.bottomLeftHandle = QRectF(
+ x1 * source_width - (csx / 2.0),
+ y2 * source_height - (csy / 2.0),
+ csx,
+ csy)
+ self.bottomRightHandle = QRectF(
+ x2 * source_width - (csx / 2.0),
+ y2 * source_height - (csy / 2.0),
+ csx,
+ csy)
else:
# Calculate bounds of clip
- self.clipBounds = QRectF(QPointF(0.0, 0.0), QPointF(source_width, source_height))
+ self.clipBounds = QRectF(
+ QPointF(0.0, 0.0),
+ QPointF(source_width, source_height))
# Calculate 4 corners coordinates
- self.topLeftHandle = QRectF(-cs/sx/2.0, -cs/sy/2.0, cs/sx, cs/sy)
- self.topRightHandle = QRectF(source_width - (cs/sx) + cs/sx/2.0, -cs/sy/2.0, cs/sx, cs/sy)
- self.bottomLeftHandle = QRectF(-cs/sx/2.0, source_height - (cs/sy) + cs/sy/2.0, cs/sx, cs/sy)
- self.bottomRightHandle = QRectF(source_width - (cs/sx) + cs/sx/2.0, source_height - (cs/sy) + cs/sy/2.0, cs/sx, cs/sy)
+ self.topLeftHandle = QRectF(
+ -csx / 2.0, -csy / 2.0, csx, csy)
+ self.topRightHandle = QRectF(
+ source_width - csx / 2.0, -csy / 2.0, csx, csy)
+ self.bottomLeftHandle = QRectF(
+ -csx / 2.0, source_height - csy / 2.0, csx, csy)
+ self.bottomRightHandle = QRectF(
+ source_width - csx / 2.0, source_height - csy / 2.0, csx, csy)
# Draw 4 corners
pen = QPen(QBrush(QColor("#53a0ed")), 1.5)
@@ -127,47 +159,110 @@ def drawTransformHandler(self, painter, sx, sy, source_width, source_height, ori
painter.drawRect(self.bottomLeftHandle)
painter.drawRect(self.bottomRightHandle)
- if(x1 and y1 and x2 and y2):
+ if all([x1, y1, x2, y2]):
# Calculate 4 side coordinates
- self.topHandle = QRectF(((x1*source_width+x2*source_width) / 2.0) - (cs/sx/2.0), (y1*source_height)-cs/sy/2.0, cs/sx, cs/sy)
- self.bottomHandle = QRectF(((x1*source_width+x2*source_width) / 2.0) - (cs/sx/2.0), (y2*source_height)-( cs/sy/2.0), cs/sx, cs/sy)
- self.leftHandle = QRectF((x1*source_width)-(cs/sx/2.0), ((y1*source_height+y2*source_height) / 2.0) - (cs/sy/2.0), cs/sx, cs/sy)
- self.rightHandle = QRectF((x2*source_width) - (cs/sx) + cs/sx/2.0, ((y1*source_height+y2*source_height) / 2.0) - (cs/sy/2.0), cs/sx, cs/sy)
+ self.topHandle = QRectF(
+ ((x1 + x2) * source_width - csx) / 2.0,
+ (y1 * source_height) - csy / 2.0,
+ csx,
+ csy)
+ self.bottomHandle = QRectF(
+ ((x1 + x2) * source_width - csx) / 2.0,
+ (y2 * source_height) - csy / 2.0,
+ csx,
+ csy)
+ self.leftHandle = QRectF(
+ (x1 * source_width) - csx / 2.0,
+ ((y1 + y2) * source_height - csy) / 2.0,
+ csx,
+ csy)
+ self.rightHandle = QRectF(
+ (x2 * source_width) - csx / 2.0,
+ ((y1 + y2) * source_height - csy) / 2.0,
+ csx, csy)
else:
# Calculate 4 side coordinates
- self.topHandle = QRectF((source_width / 2.0) - (cs/sx/2.0), -cs/sy/2.0, cs/sx, cs/sy)
- self.bottomHandle = QRectF((source_width / 2.0) - (cs/sx/2.0), source_height - (cs/sy) + cs/sy/2.0, cs/sx, cs/sy)
- self.leftHandle = QRectF(-cs/sx/2.0, (source_height / 2.0) - (cs/sy/2.0), cs/sx, cs/sy)
- self.rightHandle = QRectF(source_width - (cs/sx) + cs/sx/2.0, (source_height / 2.0) - (cs/sy/2.0), cs/sx, cs/sy)
+ self.topHandle = QRectF(
+ (source_width - csx) / 2.0,
+ -csy / 2.0,
+ csx,
+ csy)
+ self.bottomHandle = QRectF(
+ (source_width - csx) / 2.0,
+ source_height - (csy / 2.0),
+ csx,
+ csy)
+ self.leftHandle = QRectF(
+ -csx / 2.0,
+ (source_height - csy) / 2.0,
+ csx,
+ csy)
+ self.rightHandle = QRectF(
+ source_width - (csx / 2.0),
+ (source_height - csy) / 2.0,
+ csx,
+ csy)
# Calculate shear handles
- self.topShearHandle = QRectF(self.topLeftHandle.x(), self.topLeftHandle.y(), self.clipBounds.width(), self.topLeftHandle.height())
- self.leftShearHandle = QRectF(self.topLeftHandle.x(), self.topLeftHandle.y(), self.topLeftHandle.width(), self.clipBounds.height())
- self.rightShearHandle = QRectF(self.topRightHandle.x(), self.topRightHandle.y(), self.topRightHandle.width(), self.clipBounds.height())
- self.bottomShearHandle = QRectF(self.bottomLeftHandle.x(), self.bottomLeftHandle.y(), self.clipBounds.width(), self.topLeftHandle.height())
+ self.topShearHandle = QRectF(
+ self.topLeftHandle.x(),
+ self.topLeftHandle.y(),
+ self.clipBounds.width(),
+ self.topLeftHandle.height())
+ self.leftShearHandle = QRectF(
+ self.topLeftHandle.x(),
+ self.topLeftHandle.y(),
+ self.topLeftHandle.width(),
+ self.clipBounds.height())
+ self.rightShearHandle = QRectF(
+ self.topRightHandle.x(),
+ self.topRightHandle.y(),
+ self.topRightHandle.width(),
+ self.clipBounds.height())
+ self.bottomShearHandle = QRectF(
+ self.bottomLeftHandle.x(),
+ self.bottomLeftHandle.y(),
+ self.clipBounds.width(),
+ self.topLeftHandle.height())
# Draw 4 sides (centered)
- painter.drawRect(self.topHandle)
- painter.drawRect(self.bottomHandle)
- painter.drawRect(self.leftHandle)
- painter.drawRect(self.rightHandle)
- painter.drawRect(self.clipBounds)
+ painter.drawRects([
+ self.topHandle,
+ self.bottomHandle,
+ self.leftHandle,
+ self.rightHandle,
+ self.clipBounds,
+ ])
# Calculate center coordinate
- if(x1 and y1 and x2 and y2):
+ if all([x1, y1, x2, y2]):
cs = 5.0
os = 7.0
- self.centerHandle = QRectF( (((x1*source_width+x2*source_width) / 2.0) ) - (os/sx), (((y1*source_height+y2*source_height) / 2.0) ) - (os/sy), os/sx*2.0, os/sy*2.0)
+ self.centerHandle = QRectF(
+ ((x1 + x2) * source_width / 2.0) - (os / sx),
+ ((y1 + y2) * source_height / 2.0) - (os / sy),
+ os / sx * 2.0,
+ os / sy * 2.0
+ )
else:
- self.centerHandle = QRectF((source_width * origin_x) - (os/sx), (source_height * origin_y) - (os/sy), os/sx*2.0, os/sy*2.0)
+ self.centerHandle = QRectF(
+ source_width * origin_x - (os / sx),
+ source_height * origin_y - (os / sy),
+ os / sx * 2.0,
+ os / sy * 2.0)
# Draw origin
painter.drawEllipse(self.centerHandle)
- painter.drawLine(self.centerHandle.x() + (self.centerHandle.width()/2.0), self.centerHandle.y() + (self.centerHandle.height()/2.0) - self.centerHandle.height(),
- self.centerHandle.x() + (self.centerHandle.width()/2.0), self.centerHandle.y() + (self.centerHandle.height()/2.0) + self.centerHandle.height())
- painter.drawLine(self.centerHandle.x() + (self.centerHandle.width()/2.0) - self.centerHandle.width(), self.centerHandle.y() + (self.centerHandle.height()/2.0),
- self.centerHandle.x() + (self.centerHandle.width()/2.0) + self.centerHandle.width(), self.centerHandle.y() + (self.centerHandle.height()/2.0))
+
+ # Draw cross at origin center, extending beyond ellipse by 25%
+ center = self.centerHandle.center()
+ halfW = QPointF(self.centerHandle.width() * 0.75, 0)
+ halfH = QPointF(0, self.centerHandle.height() * 0.75)
+ painter.drawLines(
+ center - halfW, center + halfW,
+ center - halfH, center + halfH,
+ )
# Remove transform
painter.resetTransform()
@@ -179,7 +274,11 @@ def paintEvent(self, event, *args):
# Paint custom frame image on QWidget
painter = QPainter(self)
- painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform | QPainter.TextAntialiasing, True)
+ painter.setRenderHints(
+ QPainter.Antialiasing
+ | QPainter.SmoothPixmapTransform
+ | QPainter.TextAntialiasing,
+ True)
# Fill the whole widget with the solid color
painter.fillRect(event.rect(), QColor("#191919"))
@@ -191,7 +290,7 @@ def paintEvent(self, event, *args):
# DRAW FRAME
# Calculate new frame image size, maintaining aspect ratio
pixSize = self.current_image.size()
- pixSize.scale(event.rect().width(), event.rect().height(), Qt.KeepAspectRatio)
+ pixSize.scale(event.rect().size(), Qt.KeepAspectRatio)
self.curr_frame_size = pixSize
# Scale image (take into account display scaling for High DPI monitors)
@@ -223,13 +322,19 @@ def paintEvent(self, event, *args):
# Determine original size of clip's reader
source_width = self.transforming_clip.data['reader']['width']
source_height = self.transforming_clip.data['reader']['height']
- source_size = QSize(source_width, source_height * self.pixel_ratio.Reciprocal().ToDouble())
+ pixel_adjust = self.pixel_ratio.Reciprocal().ToDouble()
+ source_size = QSize(
+ int(source_width),
+ int(source_height * pixel_adjust))
# Determine scale of clip
scale = self.transforming_clip.data['scale']
# Set scale as STRETCH if the clip is attached to an object
- if (raw_properties.get('parentObjectId').get('memo') != 'None' and len(raw_properties.get('parentObjectId').get('memo')) > 0 ):
+ if (
+ raw_properties.get('parentObjectId').get('memo') != 'None'
+ and len(raw_properties.get('parentObjectId').get('memo')) > 0
+ ):
scale = openshot.SCALE_STRETCH
if scale == openshot.SCALE_FIT:
@@ -239,12 +344,7 @@ def paintEvent(self, event, *args):
source_size.scale(player_width, player_height, Qt.IgnoreAspectRatio)
elif scale == openshot.SCALE_CROP:
- width_size = QSize(player_width, round(player_width / (float(source_width) / float(source_height))))
- height_size = QSize(round(player_height / (float(source_height) / float(source_width))), player_height)
- if width_size.width() >= player_width and width_size.height() >= player_height:
- source_size.scale(width_size.width(), width_size.height(), Qt.KeepAspectRatio)
- else:
- source_size.scale(height_size.width(), height_size.height(), Qt.KeepAspectRatio)
+ source_size.scale(player_width, player_height, Qt.KeepAspectRatioByExpanding)
# Get new source width / height (after scaling mode applied)
source_width = source_size.width()
@@ -285,9 +385,6 @@ def paintEvent(self, event, *args):
x += player_width - scaled_source_width # right
y += (player_height - scaled_source_height) # bottom
- # Track gravity starting coordinate
- self.gravity_point = QPointF(x, y)
-
# Adjust x,y for location
x_offset = raw_properties.get('location_x').get('value')
y_offset = raw_properties.get('location_y').get('value')
@@ -329,7 +426,6 @@ def paintEvent(self, event, *args):
raw_properties_effect = json.loads(self.transforming_effect_object.PropertiesJSON(clip_frame_number))
# Get properties for the first object in dict. PropertiesJSON should return one object at the time
tmp = raw_properties_effect.get('objects')
- tmp2 = tmp.keys()
obj_id = list(tmp.keys())[0]
raw_properties_effect = raw_properties_effect.get('objects').get(obj_id)
@@ -342,10 +438,19 @@ def paintEvent(self, event, *args):
y1 = raw_properties_effect['y1']['value']
x2 = raw_properties_effect['x2']['value']
y2 = raw_properties_effect['y2']['value']
- self.drawTransformHandler(painter, sx, sy, source_width, source_height, origin_x, origin_y,
- x1, y1, x2, y2, rotation)
+ self.drawTransformHandler(
+ painter,
+ sx, sy,
+ source_width, source_height,
+ origin_x, origin_y,
+ x1, y1, x2, y2,
+ rotation)
else:
- self.drawTransformHandler(painter, sx, sy, source_width, source_height, origin_x, origin_y)
+ self.drawTransformHandler(
+ painter,
+ sx, sy,
+ source_width, source_height,
+ origin_x, origin_y)
if self.region_enabled:
# Paint region selector onto video preview
@@ -376,11 +481,21 @@ def paintEvent(self, event, *args):
pen = QPen(QBrush(QColor("#53a0ed")), 1.5)
pen.setCosmetic(True)
painter.setPen(pen)
- painter.drawRect(self.regionTopLeftHandle.x() - (cs/2.0/self.zoom), self.regionTopLeftHandle.y() - (cs/2.0/self.zoom), self.regionTopLeftHandle.width() / self.zoom, self.regionTopLeftHandle.height() / self.zoom)
- painter.drawRect(self.regionBottomRightHandle.x() - (cs/2.0/self.zoom), self.regionBottomRightHandle.y() - (cs/2.0/self.zoom), self.regionBottomRightHandle.width() / self.zoom, self.regionBottomRightHandle.height() / self.zoom)
- region_rect = QRectF(self.regionTopLeftHandle.x(), self.regionTopLeftHandle.y(),
- self.regionBottomRightHandle.x() - self.regionTopLeftHandle.x(),
- self.regionBottomRightHandle.y() - self.regionTopLeftHandle.y())
+ painter.drawRect(
+ self.regionTopLeftHandle.x() - (cs / 2.0 / self.zoom),
+ self.regionTopLeftHandle.y() - (cs / 2.0 / self.zoom),
+ self.regionTopLeftHandle.width() / self.zoom,
+ self.regionTopLeftHandle.height() / self.zoom)
+ painter.drawRect(
+ self.regionBottomRightHandle.x() - (cs / 2.0 / self.zoom),
+ self.regionBottomRightHandle.y() - (cs / 2.0 / self.zoom),
+ self.regionBottomRightHandle.width() / self.zoom,
+ self.regionBottomRightHandle.height() / self.zoom)
+ region_rect = QRectF(
+ self.regionTopLeftHandle.x(),
+ self.regionTopLeftHandle.y(),
+ self.regionBottomRightHandle.x() - self.regionTopLeftHandle.x(),
+ self.regionBottomRightHandle.y() - self.regionTopLeftHandle.y())
painter.drawRect(region_rect)
# Remove transform
@@ -394,23 +509,15 @@ def paintEvent(self, event, *args):
def centeredViewport(self, width, height):
""" Calculate size of viewport to maintain aspect ratio """
- # Calculate padding
- top_padding = (height - (height * self.zoom)) / 2.0
- left_padding = (width - (width * self.zoom)) / 2.0
+ window_size = QSizeF(width, height)
+ window_rect = QRectF(QPointF(0, 0), window_size)
- # Adjust parameters to zoom
- width = width * self.zoom
- height = height * self.zoom
+ aspectRatio = self.aspect_ratio.ToFloat() * self.pixel_ratio.ToFloat()
+ viewport_size = QSizeF(aspectRatio, 1).scaled(window_size, Qt.KeepAspectRatio)
+ viewport_rect = QRectF(QPointF(0, 0), viewport_size)
+ viewport_rect.moveCenter(window_rect.center())
- # Calculate which direction to scale (for perfect centering)
- aspectRatio = self.aspect_ratio.ToFloat()
- heightFromWidth = width / aspectRatio
- widthFromHeight = height * aspectRatio
-
- if heightFromWidth <= height:
- return QRect(left_padding, ((height - heightFromWidth) / 2) + top_padding, width, heightFromWidth)
- else:
- return QRect(((width - widthFromHeight) / 2.0) + left_padding, top_padding, widthFromHeight, height)
+ return viewport_rect.toRect()
def present(self, image, *args):
""" Present the current frame """
@@ -448,12 +555,16 @@ def mouseReleaseEvent(self, event):
# This can be used other widgets to display the selected region
if self.region_enabled:
# Get region coordinates
- region_rect = QRectF(self.regionTopLeftHandle.x(), self.regionTopLeftHandle.y(),
- self.regionBottomRightHandle.x() - self.regionTopLeftHandle.x(),
- self.regionBottomRightHandle.y() - self.regionTopLeftHandle.y()).normalized()
+ region_rect = QRectF(
+ self.regionTopLeftHandle.x(),
+ self.regionTopLeftHandle.y(),
+ self.regionBottomRightHandle.x() - self.regionTopLeftHandle.x(),
+ self.regionBottomRightHandle.y() - self.regionTopLeftHandle.y()
+ ).normalized()
# Map region (due to zooming)
- mapped_region_rect = self.region_transform.mapToPolygon(region_rect.toRect()).boundingRect()
+ mapped_region_rect = self.region_transform.mapToPolygon(
+ region_rect.toRect()).boundingRect()
# Render a scaled version of the region (as a QImage)
# TODO: Grab higher quality pixmap from the QWidget, as this method seems to be 1/2 resolution
@@ -461,14 +572,25 @@ def mouseReleaseEvent(self, event):
scale = 3.0
# Map rect to transform (for scaling video elements)
- mapped_region_rect = QRect(mapped_region_rect.x(), mapped_region_rect.y(), mapped_region_rect.width() * scale, mapped_region_rect.height() * scale)
+ mapped_region_rect = QRect(
+ mapped_region_rect.x(),
+ mapped_region_rect.y(),
+ int(mapped_region_rect.width() * scale),
+ int(mapped_region_rect.height() * scale))
# Render QWidget onto scaled QImage
- self.region_qimage = QImage(mapped_region_rect.width(), mapped_region_rect.height(), QImage.Format_RGBA8888)
+ self.region_qimage = QImage(
+ mapped_region_rect.size(), QImage.Format_RGBA8888)
region_painter = QPainter(self.region_qimage)
- region_painter.setRenderHints(QPainter.Antialiasing | QPainter.SmoothPixmapTransform | QPainter.TextAntialiasing, True)
+ region_painter.setRenderHints(
+ QPainter.Antialiasing
+ | QPainter.SmoothPixmapTransform
+ | QPainter.TextAntialiasing,
+ True)
region_painter.scale(scale, scale)
- self.render(region_painter, QPoint(0,0), QRegion(mapped_region_rect, QRegion.Rectangle))
+ self.render(
+ region_painter, QPoint(0, 0),
+ QRegion(mapped_region_rect, QRegion.Rectangle))
region_painter.end()
# Inform UpdateManager to accept updates, and only store our final update
@@ -484,7 +606,8 @@ def mouseReleaseEvent(self, event):
def rotateCursor(self, pixmap, rotation, shear_x, shear_y):
"""Rotate cursor based on the current transform"""
rotated_pixmap = pixmap.transformed(
- QTransform().rotate(rotation).shear(shear_x, shear_y).scale(0.8, 0.8), Qt.SmoothTransformation)
+ QTransform().rotate(rotation).shear(shear_x, shear_y).scale(0.8, 0.8),
+ Qt.SmoothTransformation)
return QCursor(rotated_pixmap)
def getTransformMode(self, rotation, shear_x, shear_y, event):
@@ -627,6 +750,10 @@ def mouseMoveEvent(self, event):
# Transform clip object
if self.transform_mode:
+
+ x_motion = event.pos().x() - self.mouse_position.x()
+ y_motion = event.pos().y() - self.mouse_position.y()
+
if self.transform_mode == 'origin':
# Get current keyframe value
origin_x = raw_properties.get('origin_x').get('value')
@@ -635,8 +762,8 @@ def mouseMoveEvent(self, event):
scale_y = raw_properties.get('scale_y').get('value')
# Calculate new location coordinates
- origin_x += (event.pos().x() - self.mouse_position.x()) / (self.clipBounds.width() * scale_x)
- origin_y += (event.pos().y() - self.mouse_position.y()) / (self.clipBounds.height() * scale_y)
+ origin_x += x_motion / (self.clipBounds.width() * scale_x)
+ origin_y += y_motion / (self.clipBounds.height() * scale_y)
# Constrain to clip
if origin_x < 0.0:
@@ -648,8 +775,13 @@ def mouseMoveEvent(self, event):
if origin_y > 1.0:
origin_y = 1.0
# Update keyframe value (or create new one)
- self.updateClipProperty(self.transforming_clip.id, clip_frame_number, 'origin_x', origin_x, refresh=False)
- self.updateClipProperty(self.transforming_clip.id, clip_frame_number, 'origin_y', origin_y)
+ self.updateClipProperty(
+ self.transforming_clip.id, clip_frame_number,
+ 'origin_x', origin_x,
+ refresh=False)
+ self.updateClipProperty(
+ self.transforming_clip.id, clip_frame_number,
+ 'origin_y', origin_y)
elif self.transform_mode == 'location':
# Get current keyframe value
@@ -657,12 +789,17 @@ def mouseMoveEvent(self, event):
location_y = raw_properties.get('location_y').get('value')
# Calculate new location coordinates
- location_x += (event.pos().x() - self.mouse_position.x()) / viewport_rect.width()
- location_y += (event.pos().y() - self.mouse_position.y()) / viewport_rect.height()
+ location_x += x_motion / viewport_rect.width()
+ location_y += y_motion / viewport_rect.height()
# Update keyframe value (or create new one)
- self.updateClipProperty(self.transforming_clip.id, clip_frame_number, 'location_x', location_x, refresh=False)
- self.updateClipProperty(self.transforming_clip.id, clip_frame_number, 'location_y', location_y)
+ self.updateClipProperty(
+ self.transforming_clip.id, clip_frame_number,
+ 'location_x', location_x,
+ refresh=False)
+ self.updateClipProperty(
+ self.transforming_clip.id, clip_frame_number,
+ 'location_y', location_y)
elif self.transform_mode == 'shear_top':
# Get current keyframe shear value
@@ -672,11 +809,13 @@ def mouseMoveEvent(self, event):
# Calculate new location coordinates
aspect_ratio = (self.clipBounds.width() / self.clipBounds.height()) * 2.0
shear_x -= (
- event.pos().x() - self.mouse_position.x()) / (
+ x_motion) / (
(self.clipBounds.width() * scale_x) / aspect_ratio)
# Update keyframe value (or create new one)
- self.updateClipProperty(self.transforming_clip.id, clip_frame_number, 'shear_x', shear_x)
+ self.updateClipProperty(
+ self.transforming_clip.id, clip_frame_number,
+ 'shear_x', shear_x)
elif self.transform_mode == 'shear_bottom':
# Get current keyframe shear value
@@ -686,11 +825,13 @@ def mouseMoveEvent(self, event):
# Calculate new location coordinates
aspect_ratio = (self.clipBounds.width() / self.clipBounds.height()) * 2.0
shear_x += (
- event.pos().x() - self.mouse_position.x()) / (
+ x_motion) / (
(self.clipBounds.width() * scale_x) / aspect_ratio)
# Update keyframe value (or create new one)
- self.updateClipProperty(self.transforming_clip.id, clip_frame_number, 'shear_x', shear_x)
+ self.updateClipProperty(
+ self.transforming_clip.id, clip_frame_number,
+ 'shear_x', shear_x)
elif self.transform_mode == 'shear_left':
# Get current keyframe shear value
@@ -701,11 +842,13 @@ def mouseMoveEvent(self, event):
aspect_ratio = (
self.clipBounds.height() / self.clipBounds.width()) * 2.0
shear_y -= (
- event.pos().y() - self.mouse_position.y()) / (
+ y_motion) / (
self.clipBounds.height() * scale_y / aspect_ratio)
# Update keyframe value (or create new one)
- self.updateClipProperty(self.transforming_clip.id, clip_frame_number, 'shear_y', shear_y)
+ self.updateClipProperty(
+ self.transforming_clip.id, clip_frame_number,
+ 'shear_y', shear_y)
elif self.transform_mode == 'shear_right':
# Get current keyframe shear value
@@ -713,13 +856,16 @@ def mouseMoveEvent(self, event):
shear_y = raw_properties.get('shear_y').get('value')
# Calculate new location coordinates
- aspect_ratio = (self.clipBounds.height() / self.clipBounds.width()) * 2.0
+ aspect_ratio = (
+ self.clipBounds.height() / self.clipBounds.width()) * 2.0
shear_y += (
- event.pos().y() - self.mouse_position.y()) / (
+ y_motion) / (
self.clipBounds.height() * scale_y / aspect_ratio)
# Update keyframe value (or create new one)
- self.updateClipProperty(self.transforming_clip.id, clip_frame_number, 'shear_y', shear_y)
+ self.updateClipProperty(
+ self.transforming_clip.id, clip_frame_number,
+ 'shear_y', shear_y)
elif self.transform_mode == 'rotation':
# Get current rotation keyframe value
@@ -728,71 +874,68 @@ def mouseMoveEvent(self, event):
scale_y = max(float(raw_properties.get('scale_y').get('value')), 0.001)
# Calculate new location coordinates
- is_on_left = event.pos().x() < self.originHandle.x()
+ is_on_right = event.pos().x() > self.originHandle.x()
is_on_top = event.pos().y() < self.originHandle.y()
- if is_on_top:
- rotation += (
- event.pos().x() - self.mouse_position.x()) / (
- (self.clipBounds.width() * scale_x) / 90)
- else:
- rotation -= (
- event.pos().x() - self.mouse_position.x()) / (
- (self.clipBounds.width() * scale_x) / 90)
-
- if is_on_left:
- rotation -= (
- event.pos().y() - self.mouse_position.y()) / (
- (self.clipBounds.height() * scale_y) / 90)
- else:
- rotation += (
- event.pos().y() - self.mouse_position.y()) / (
- (self.clipBounds.height() * scale_y) / 90)
+ x_adjust = x_motion / ((self.clipBounds.width() * scale_x) / 90)
+ rotation += (x_adjust if is_on_top else -x_adjust)
+
+ y_adjust = y_motion / ((self.clipBounds.height() * scale_y) / 90)
+ rotation += (y_adjust if is_on_right else -y_adjust)
# Update keyframe value (or create new one)
- self.updateClipProperty(self.transforming_clip.id, clip_frame_number, 'rotation', rotation)
+ self.updateClipProperty(
+ self.transforming_clip.id,
+ clip_frame_number,
+ 'rotation', rotation)
elif self.transform_mode.startswith('scale_'):
# Get current scale keyframe value
scale_x = max(float(raw_properties.get('scale_x').get('value')), 0.001)
scale_y = max(float(raw_properties.get('scale_y').get('value')), 0.001)
+ half_w = self.clipBounds.width() / 2.0
+ half_h = self.clipBounds.height() / 2.0
+
if self.transform_mode == 'scale_top_right':
- scale_x += (event.pos().x() - self.mouse_position.x()) / (self.clipBounds.width() / 2.0)
- scale_y -= (event.pos().y() - self.mouse_position.y()) / (self.clipBounds.height() / 2.0)
+ scale_x += x_motion / half_w
+ scale_y -= y_motion / half_h
elif self.transform_mode == 'scale_bottom_right':
- scale_x += (event.pos().x() - self.mouse_position.x()) / (self.clipBounds.width() / 2.0)
- scale_y += (event.pos().y() - self.mouse_position.y()) / (self.clipBounds.height() / 2.0)
+ scale_x += x_motion / half_w
+ scale_y += y_motion / half_h
elif self.transform_mode == 'scale_top_left':
- scale_x -= (event.pos().x() - self.mouse_position.x()) / (self.clipBounds.width() / 2.0)
- scale_y -= (event.pos().y() - self.mouse_position.y()) / (self.clipBounds.height() / 2.0)
+ scale_x -= x_motion / half_w
+ scale_y -= y_motion / half_h
elif self.transform_mode == 'scale_bottom_left':
- scale_x -= (event.pos().x() - self.mouse_position.x()) / (self.clipBounds.width() / 2.0)
- scale_y += (event.pos().y() - self.mouse_position.y()) / (self.clipBounds.height() / 2.0)
+ scale_x -= x_motion / half_w
+ scale_y += y_motion / half_h
elif self.transform_mode == 'scale_top':
- scale_y -= (event.pos().y() - self.mouse_position.y()) / (self.clipBounds.height() / 2.0)
+ scale_y -= y_motion / half_h
elif self.transform_mode == 'scale_bottom':
- scale_y += (event.pos().y() - self.mouse_position.y()) / (self.clipBounds.height() / 2.0)
+ scale_y += y_motion / half_h
elif self.transform_mode == 'scale_left':
- scale_x -= (event.pos().x() - self.mouse_position.x()) / (self.clipBounds.width() / 2.0)
+ scale_x -= x_motion / half_w
elif self.transform_mode == 'scale_right':
- scale_x += (event.pos().x() - self.mouse_position.x()) / (self.clipBounds.width() / 2.0)
+ scale_x += x_motion / half_w
if int(QCoreApplication.instance().keyboardModifiers() & Qt.ControlModifier) > 0:
# If CTRL key is pressed, fix the scale_y to the correct aspect ration
- if scale_x and scale_y:
+ if scale_x:
scale_y = scale_x
elif scale_y:
scale_x = scale_y
- elif scale_x:
- scale_y = scale_x
# Update keyframe value (or create new one)
both_scaled = scale_x != 0.001 and scale_y != 0.001
if scale_x != 0.001:
- self.updateClipProperty(self.transforming_clip.id, clip_frame_number, 'scale_x', scale_x, refresh=(not both_scaled))
+ self.updateClipProperty(
+ self.transforming_clip.id, clip_frame_number,
+ 'scale_x', scale_x,
+ refresh=(not both_scaled))
if scale_y != 0.001:
- self.updateClipProperty(self.transforming_clip.id, clip_frame_number, 'scale_y', scale_y)
+ self.updateClipProperty(
+ self.transforming_clip.id, clip_frame_number,
+ 'scale_y', scale_y)
# Force re-paint
self.update()
@@ -803,16 +946,29 @@ def mouseMoveEvent(self, event):
cs = self.cs
# Adjust existing region coordinates (if any)
- if not self.mouse_dragging and self.resize_button.isVisible() and self.resize_button.rect().contains(event.pos()):
+ if (not self.mouse_dragging
+ and self.resize_button.isVisible()
+ and self.resize_button.rect().contains(event.pos())
+ ):
# Mouse over resize button (and not currently dragging)
self.setCursor(Qt.ArrowCursor)
- elif self.region_transform and self.regionTopLeftHandle and self.region_transform.mapToPolygon(self.regionTopLeftHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
+ elif (
+ self.region_transform
+ and self.regionTopLeftHandle
+ and self.region_transform.mapToPolygon(
+ self.regionTopLeftHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill)
+ ):
if not self.region_mode or self.region_mode == 'scale_top_left':
self.setCursor(self.rotateCursor(self.cursors.get('resize_fdiag'), 0, 0, 0))
# Set the region mode
if self.mouse_dragging and not self.region_mode:
self.region_mode = 'scale_top_left'
- elif self.region_transform and self.regionBottomRightHandle and self.region_transform.mapToPolygon(self.regionBottomRightHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
+ elif (
+ self.region_transform
+ and self.regionBottomRightHandle
+ and self.region_transform.mapToPolygon(
+ self.regionBottomRightHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill)
+ ):
if not self.region_mode or self.region_mode == 'scale_bottom_right':
self.setCursor(self.rotateCursor(self.cursors.get('resize_fdiag'), 0, 0, 0))
# Set the region mode
@@ -824,13 +980,25 @@ def mouseMoveEvent(self, event):
# Initialize new region coordinates at current event.pos()
if self.mouse_dragging and not self.region_mode:
self.region_mode = 'scale_bottom_right'
- self.regionTopLeftHandle = QRectF(self.region_transform_inverted.map(event.pos()).x(), self.region_transform_inverted.map(event.pos()).y(), cs, cs)
- self.regionBottomRightHandle = QRectF(self.region_transform_inverted.map(event.pos()).x(), self.region_transform_inverted.map(event.pos()).y(), cs, cs)
+ self.regionTopLeftHandle = QRectF(
+ self.region_transform_inverted.map(event.pos()).x(),
+ self.region_transform_inverted.map(event.pos()).y(),
+ cs, cs)
+ self.regionBottomRightHandle = QRectF(
+ self.region_transform_inverted.map(event.pos()).x(),
+ self.region_transform_inverted.map(event.pos()).y(),
+ cs, cs)
# Move existing region coordinates
if self.mouse_dragging:
- diff_x = self.region_transform_inverted.map(event.pos()).x() - self.region_transform_inverted.map(self.mouse_position).x()
- diff_y = self.region_transform_inverted.map(event.pos()).y() - self.region_transform_inverted.map(self.mouse_position).y()
+ diff_x = int(
+ self.region_transform_inverted.map(event.pos()).x()
+ - self.region_transform_inverted.map(self.mouse_position).x()
+ )
+ diff_y = int(
+ self.region_transform_inverted.map(event.pos()).y()
+ - self.region_transform_inverted.map(self.mouse_position).y()
+ )
if self.region_mode == 'scale_top_left':
self.regionTopLeftHandle.adjust(diff_x, diff_y, diff_x, diff_y)
elif self.region_mode == 'scale_bottom_right':
@@ -859,12 +1027,11 @@ def mouseMoveEvent(self, event):
if self.mouse_dragging and not self.transform_mode:
self.original_clip_data = self.transforming_clip.data
-
-
if self.transforming_effect_object.info.has_tracked_object:
# Get properties of effect at current frame
raw_properties = json.loads(self.transforming_effect_object.PropertiesJSON(clip_frame_number))
- # Get properties for the first object in dict. PropertiesJSON should return one object at the time
+ # Get properties for the first object in dict.
+ # PropertiesJSON should return one object at the time
obj_id = list(raw_properties.get('objects').keys())[0]
raw_properties = raw_properties.get('objects').get(obj_id)
@@ -878,18 +1045,28 @@ def mouseMoveEvent(self, event):
# Transform effect object
if self.transform_mode:
+ x_motion = event.pos().x() - self.mouse_position.x()
+ y_motion = event.pos().y() - self.mouse_position.y()
+
if self.transform_mode == 'location':
# Get current keyframe value
location_x = raw_properties.get('delta_x').get('value')
location_y = raw_properties.get('delta_y').get('value')
# Calculate new location coordinates
- location_x += (event.pos().x() - self.mouse_position.x()) / viewport_rect.width()
- location_y += (event.pos().y() - self.mouse_position.y()) / viewport_rect.height()
+ location_x += x_motion / viewport_rect.width()
+ location_y += y_motion / viewport_rect.height()
# Update keyframe value (or create new one)
- self.updateEffectProperty(self.transforming_effect.id, clip_frame_number, obj_id, 'delta_x', location_x, refresh=False)
- self.updateEffectProperty(self.transforming_effect.id, clip_frame_number, obj_id, 'delta_y', location_y)
+ self.updateEffectProperty(
+ self.transforming_effect.id, clip_frame_number,
+ obj_id,
+ 'delta_x', location_x,
+ refresh=False)
+ self.updateEffectProperty(
+ self.transforming_effect.id, clip_frame_number,
+ obj_id,
+ 'delta_y', location_y)
elif self.transform_mode == 'rotation':
# Get current rotation keyframe value
@@ -898,63 +1075,70 @@ def mouseMoveEvent(self, event):
scale_y = max(float(raw_properties.get('scale_y').get('value')), 0.001)
# Calculate new location coordinates
- is_on_left = event.pos().x() < self.originHandle.x()
+ is_on_right = event.pos().x() > self.originHandle.x()
is_on_top = event.pos().y() < self.originHandle.y()
- if is_on_top:
- rotation += (event.pos().x() - self.mouse_position.x()) / ((self.clipBounds.width() * scale_x) / 90)
- else:
- rotation -= (event.pos().x() - self.mouse_position.x()) / ((self.clipBounds.width() * scale_x) / 90)
+ x_adjust = x_motion / (self.clipBounds.width() * scale_x / 90)
+ rotation += (x_adjust if is_on_top else -x_adjust)
- if is_on_left:
- rotation -= (event.pos().y() - self.mouse_position.y()) / ((self.clipBounds.height() * scale_y) / 90)
- else:
- rotation += (event.pos().y() - self.mouse_position.y()) / ((self.clipBounds.height() * scale_y) / 90)
+ y_adjust = y_motion / (self.clipBounds.height() * scale_y / 90)
+ rotation += (y_adjust if is_on_right else -y_adjust)
# Update keyframe value (or create new one)
- self.updateEffectProperty(self.transforming_effect.id, clip_frame_number, obj_id, 'rotation', rotation)
+ self.updateEffectProperty(
+ self.transforming_effect.id,
+ clip_frame_number, obj_id,
+ 'rotation', rotation)
elif self.transform_mode.startswith('scale_'):
# Get current scale keyframe value
scale_x = max(float(raw_properties.get('scale_x').get('value')), 0.001)
scale_y = max(float(raw_properties.get('scale_y').get('value')), 0.001)
+ half_w = self.clipBounds.width() / 2.0
+ half_h = self.clipBounds.height() / 2.0
+
if self.transform_mode == 'scale_top_right':
- scale_x += (event.pos().x() - self.mouse_position.x()) / (self.clipBounds.width() / 2.0)
- scale_y -= (event.pos().y() - self.mouse_position.y()) / (self.clipBounds.height() / 2.0)
+ scale_x += x_motion / half_w
+ scale_y -= y_motion / half_h
elif self.transform_mode == 'scale_bottom_right':
- scale_x += (event.pos().x() - self.mouse_position.x()) / (self.clipBounds.width() / 2.0)
- scale_y += (event.pos().y() - self.mouse_position.y()) / (self.clipBounds.height() / 2.0)
+ scale_x += x_motion / half_w
+ scale_y += y_motion / half_h
elif self.transform_mode == 'scale_top_left':
- scale_x -= (event.pos().x() - self.mouse_position.x()) / (self.clipBounds.width() / 2.0)
- scale_y -= (event.pos().y() - self.mouse_position.y()) / (self.clipBounds.height() / 2.0)
+ scale_x -= x_motion / half_w
+ scale_y -= y_motion / half_h
elif self.transform_mode == 'scale_bottom_left':
- scale_x -= (event.pos().x() - self.mouse_position.x()) / (self.clipBounds.width() / 2.0)
- scale_y += (event.pos().y() - self.mouse_position.y()) / (self.clipBounds.height() / 2.0)
+ scale_x -= x_motion / half_w
+ scale_y += y_motion / half_h
elif self.transform_mode == 'scale_top':
- scale_y -= (event.pos().y() - self.mouse_position.y()) / (self.clipBounds.height() / 2.0)
+ scale_y -= y_motion / half_h
elif self.transform_mode == 'scale_bottom':
- scale_y += (event.pos().y() - self.mouse_position.y()) / (self.clipBounds.height() / 2.0)
+ scale_y += y_motion / half_h
elif self.transform_mode == 'scale_left':
- scale_x -= (event.pos().x() - self.mouse_position.x()) / (self.clipBounds.width() / 2.0)
+ scale_x -= x_motion / half_w
elif self.transform_mode == 'scale_right':
- scale_x += (event.pos().x() - self.mouse_position.x()) / (self.clipBounds.width() / 2.0)
+ scale_x += x_motion / half_w
if int(QCoreApplication.instance().keyboardModifiers() & Qt.ControlModifier) > 0:
- # If CTRL key is pressed, fix the scale_y to the correct aspect ration
- if scale_x and scale_y:
+ # If CTRL key is pressed, fix the scale_y to the correct aspect ratio
+ if scale_x:
scale_y = scale_x
elif scale_y:
scale_x = scale_y
- elif scale_x:
- scale_y = scale_x
# Update keyframe value (or create new one)
both_scaled = scale_x != 0.001 and scale_y != 0.001
if scale_x != 0.001:
- self.updateEffectProperty(self.transforming_effect.id, clip_frame_number, obj_id, 'scale_x', scale_x, refresh=(not both_scaled))
+ self.updateEffectProperty(
+ self.transforming_effect.id,
+ clip_frame_number, obj_id,
+ 'scale_x', scale_x,
+ refresh=(not both_scaled))
if scale_y != 0.001:
- self.updateEffectProperty(self.transforming_effect.id, clip_frame_number, obj_id, 'scale_y', scale_y)
+ self.updateEffectProperty(
+ self.transforming_effect.id,
+ clip_frame_number, obj_id,
+ 'scale_y', scale_y)
# Force re-paint
self.update()
@@ -1012,8 +1196,15 @@ def updateEffectProperty(self, effect_id, frame_number, obj_id, property_key, ne
# No clip found
return
- for point in c.data['objects'][obj_id][property_key]["Points"]:
- log.info("looping points: co.X = %s" % point["co"]["X"])
+ try:
+ props = c.data['objects'][obj_id]
+ points_list = props[property_key]["Points"]
+ except (TypeError, KeyError):
+ log.error("Corrupted project data!", exc_info=1)
+ return
+
+ for point in points_list:
+ log.info("looping points: co.X = %s", point["co"]["X"])
if point["co"]["X"] == frame_number:
found_point = True
@@ -1023,12 +1214,15 @@ def updateEffectProperty(self, effect_id, frame_number, obj_id, property_key, ne
if not found_point and new_value != None:
effect_updated = True
- log.info("Created new point at X=%s" % frame_number)
- c.data['objects'][obj_id][property_key]["Points"].append({'co': {'X': frame_number, 'Y': new_value}, 'interpolation': openshot.BEZIER})
+ log.info("Created new point at X=%s", frame_number)
+ points_list.append({
+ 'co': { 'X': frame_number, 'Y': new_value },
+ 'interpolation': openshot.BEZIER,
+ })
# Reduce # of clip properties we are saving (performance boost)
#TODO: This is too slow when draging transform handlers
- c.data = {'objects': {obj_id: c.data.get('objects').get(obj_id)}}
+ c.data = {'objects': {obj_id: c.data.get('objects', {}).get(obj_id)}}
if effect_updated:
c.save()
@@ -1040,10 +1234,10 @@ def refreshTriggered(self):
"""Signal to refresh viewport (i.e. a property might have changed that effects the preview)"""
# Update reference to clip
- if self and self.transforming_clip:
+ if self.transforming_clip:
self.transforming_clip = Clip.get(id=self.transforming_clip.id)
- if self and self.transforming_effect:
+ if self.transforming_effect:
self.transforming_effect = Effect.get(id=self.transforming_effect.id)
def transformTriggered(self, clip_id):
@@ -1053,7 +1247,7 @@ def transformTriggered(self, clip_id):
# Disable Transform UI
# Is this the same clip_id already being transformed?
- if self and self.transforming_clip and not clip_id:
+ if self.transforming_clip and not clip_id:
# Clear transform
self.transforming_clip = None
need_refresh = True
@@ -1078,7 +1272,7 @@ def keyFrameTransformTriggered(self, effect_id, clip_id):
# Disable Transform UI
# Is this the same clip_id already being transformed?
- if self and self.transforming_effect and not effect_id:
+ if self.transforming_effect and not effect_id:
# Clear transform
self.transforming_effect = None
self.transforming_clip = None
@@ -1102,12 +1296,8 @@ def keyFrameTransformTriggered(self, effect_id, clip_id):
def regionTriggered(self, clip_id):
"""Handle the 'select region' signal when it's emitted"""
- if self and not clip_id:
- # Clear transform
- self.region_enabled = False
- else:
- self.region_enabled = True
-
+ # Clear transform
+ self.region_enabled = bool(not clip_id)
get_app().window.refreshFrameSignal.emit()
def resizeEvent(self, event):
@@ -1135,7 +1325,7 @@ def delayed_resize_callback(self):
ratio = float(project_size.width()) / float(project_size.height())
even_width = round(project_size.width() / 2.0) * 2
even_height = round(round(even_width / ratio) / 2.0) * 2
- project_size = QSize(even_width, even_height)
+ project_size = QSize(int(even_width), int(even_height))
# Emit signal that video widget changed size
self.win.MaxSizeChanged.emit(project_size)
@@ -1199,7 +1389,6 @@ def __init__(self, watch_project=True, *args):
self.mouse_dragging = False
self.mouse_position = None
self.transform_mode = None
- self.gravity_point = None
self.original_clip_data = None
self.region_qimage = None
self.region_transform = None
@@ -1208,8 +1397,8 @@ def __init__(self, watch_project=True, *args):
self.regionTopLeftHandle = None
self.regionBottomRightHandle = None
self.curr_frame_size = None # Frame size
- self.zoom = 1.0 # Zoom of widget (does not affect video, only workspace)
- self.cs = 14.0 # Corner size of Transform Handler rectangles
+ self.zoom = 1.0 # Zoom of widget (does not affect video, only workspace)
+ self.cs = 14.0 # Corner size of Transform Handler rectangles
self.resize_button = QPushButton(_('Reset Zoom'), self)
self.resize_button.hide()
self.resize_button.setStyleSheet('QPushButton { margin: 10px; padding: 2px; }')
@@ -1251,7 +1440,6 @@ def __init__(self, watch_project=True, *args):
# Show Property timer
# Timer to use a delay before sending MaxSizeChanged signals (so we don't spam libopenshot)
- self.delayed_size = None
self.delayed_resize_timer = QTimer(self)
self.delayed_resize_timer.setInterval(200)
self.delayed_resize_timer.setSingleShot(True)
diff --git a/src/windows/views/effects_listview.py b/src/windows/views/effects_listview.py
index b7da28dc4..3ce3b4164 100644
--- a/src/windows/views/effects_listview.py
+++ b/src/windows/views/effects_listview.py
@@ -36,7 +36,8 @@
class EffectsListView(QListView):
""" A TreeView QWidget used on the main window """
- drag_item_size = 48
+ drag_item_size = QSize(48, 48)
+ drag_item_center = QPoint(24, 24)
def contextMenuEvent(self, event):
# Set context menu mode
@@ -69,8 +70,8 @@ def startDrag(self, event):
# Start drag operation
drag = QDrag(self)
drag.setMimeData(self.model().mimeData(selected))
- drag.setPixmap(icon.pixmap(QSize(self.drag_item_size, self.drag_item_size)))
- drag.setHotSpot(QPoint(self.drag_item_size / 2, self.drag_item_size / 2))
+ drag.setPixmap(icon.pixmap(self.drag_item_size))
+ drag.setHotSpot(self.drag_item_center)
drag.exec_()
def filter_changed(self):
diff --git a/src/windows/views/effects_treeview.py b/src/windows/views/effects_treeview.py
index 6a5ab79f4..910593524 100644
--- a/src/windows/views/effects_treeview.py
+++ b/src/windows/views/effects_treeview.py
@@ -36,7 +36,8 @@
class EffectsTreeView(QTreeView):
""" A TreeView QWidget used on the main window """
- drag_item_size = 48
+ drag_item_size = QSize(48, 48)
+ drag_item_center = QPoint(24, 24)
def contextMenuEvent(self, event):
# Set context menu mode
@@ -70,8 +71,8 @@ def startDrag(self, supportedActions):
# Start drag operation
drag = QDrag(self)
drag.setMimeData(self.model().mimeData(selected))
- drag.setPixmap(icon.pixmap(QSize(self.drag_item_size, self.drag_item_size)))
- drag.setHotSpot(QPoint(self.drag_item_size / 2, self.drag_item_size / 2))
+ drag.setPixmap(icon.pixmap(self.drag_item_size))
+ drag.setHotSpot(self.drag_item_center)
drag.exec_()
def refresh_columns(self):
diff --git a/src/windows/views/emojis_listview.py b/src/windows/views/emojis_listview.py
index 6f09bc562..cb13c35a7 100644
--- a/src/windows/views/emojis_listview.py
+++ b/src/windows/views/emojis_listview.py
@@ -39,7 +39,8 @@
class EmojisListView(QListView):
""" A QListView QWidget used on the main window """
- drag_item_size = 48
+ drag_item_size = QSize(48, 48)
+ drag_item_center = QPoint(24, 24)
def dragEnterEvent(self, event):
# If dragging urls onto widget, accept
@@ -57,8 +58,8 @@ def startDrag(self, event):
drag = QDrag(self)
drag.setMimeData(self.model.mimeData(selected))
icon = self.model.data(selected[0], Qt.DecorationRole)
- drag.setPixmap(icon.pixmap(QSize(self.drag_item_size, self.drag_item_size)))
- drag.setHotSpot(QPoint(self.drag_item_size / 2, self.drag_item_size / 2))
+ drag.setPixmap(icon.pixmap(self.drag_item_size))
+ drag.setHotSpot(self.drag_item_center)
# Create emoji file before drag starts
data = json.loads(drag.mimeData().text())
diff --git a/src/windows/views/files_listview.py b/src/windows/views/files_listview.py
index 83cdd0272..0e67306ae 100644
--- a/src/windows/views/files_listview.py
+++ b/src/windows/views/files_listview.py
@@ -38,7 +38,8 @@
class FilesListView(QListView):
""" A ListView QWidget used on the main window """
- drag_item_size = 48
+ drag_item_size = QSize(48, 48)
+ drag_item_center = QPoint(24, 24)
def contextMenuEvent(self, event):
event.accept()
@@ -113,8 +114,8 @@ def startDrag(self, supportedActions):
# Start drag operation
drag = QDrag(self)
drag.setMimeData(self.model().mimeData(selected))
- drag.setPixmap(icon.pixmap(QSize(self.drag_item_size, self.drag_item_size)))
- drag.setHotSpot(QPoint(self.drag_item_size / 2, self.drag_item_size / 2))
+ drag.setPixmap(icon.pixmap(self.drag_item_size))
+ drag.setHotSpot(self.drag_item_center)
drag.exec_()
# Without defining this method, the 'copy' action doesn't show with cursor
diff --git a/src/windows/views/files_treeview.py b/src/windows/views/files_treeview.py
index d3fe74d88..776b71cc2 100644
--- a/src/windows/views/files_treeview.py
+++ b/src/windows/views/files_treeview.py
@@ -41,7 +41,8 @@
class FilesTreeView(QTreeView):
""" A TreeView QWidget used on the main window """
- drag_item_size = 48
+ drag_item_size = QSize(48, 48)
+ drag_item_center = QPoint(24, 24)
def contextMenuEvent(self, event):
@@ -114,8 +115,8 @@ def startDrag(self, supportedActions):
# Start drag operation
drag = QDrag(self)
drag.setMimeData(self.model().mimeData(selected))
- drag.setPixmap(icon.pixmap(QSize(self.drag_item_size, self.drag_item_size)))
- drag.setHotSpot(QPoint(self.drag_item_size / 2, self.drag_item_size / 2))
+ drag.setPixmap(icon.pixmap(self.drag_item_size))
+ drag.setHotSpot(self.drag_item_center)
drag.exec_()
# Without defining this method, the 'copy' action doesn't show with cursor
diff --git a/src/windows/views/properties_tableview.py b/src/windows/views/properties_tableview.py
index e79b13644..fdaa7ee24 100644
--- a/src/windows/views/properties_tableview.py
+++ b/src/windows/views/properties_tableview.py
@@ -53,8 +53,13 @@
class PropertyDelegate(QItemDelegate):
- def __init__(self, parent=None, *args):
- QItemDelegate.__init__(self, parent, *args)
+ def __init__(self, parent=None, *args, **kwargs):
+
+ self.model = kwargs.pop("model", None)
+ if not self.model:
+ log.error("Cannot create delegate without data model!")
+
+ super().__init__(parent, *args, **kwargs)
# pixmaps for curve icons
self.curve_pixmaps = {
@@ -68,7 +73,7 @@ def paint(self, painter, option, index):
painter.setRenderHint(QPainter.Antialiasing)
# Get data model and selection
- model = get_app().window.propertyTableView.clip_properties_model.model
+ model = self.model
row = model.itemFromIndex(index).row()
selected_label = model.item(row, 0)
selected_value = model.item(row, 1)
@@ -104,16 +109,16 @@ def paint(self, painter, option, index):
painter.setPen(QPen(Qt.NoPen))
if property_type == "color":
# Color keyframe
- red = cur_property[1]["red"]["value"]
- green = cur_property[1]["green"]["value"]
- blue = cur_property[1]["blue"]["value"]
- painter.setBrush(QBrush(QColor(QColor(red, green, blue))))
+ red = int(cur_property[1]["red"]["value"])
+ green = int(cur_property[1]["green"]["value"])
+ blue = int(cur_property[1]["blue"]["value"])
+ painter.setBrush(QColor(red, green, blue))
else:
# Normal Keyframe
if option.state & QStyle.State_Selected:
- painter.setBrush(QBrush(QColor("#575757")))
+ painter.setBrush(QColor("#575757"))
else:
- painter.setBrush(QBrush(QColor("#3e3e3e")))
+ painter.setBrush(QColor("#3e3e3e"))
if readonly:
# Set text color for read only fields
@@ -146,7 +151,10 @@ def paint(self, painter, option, index):
if points > 1:
# Draw interpolation icon on top
- painter.drawPixmap(option.rect.x() + option.rect.width() - 30.0, option.rect.y() + 4, self.curve_pixmaps[interpolation])
+ painter.drawPixmap(
+ int(option.rect.x() + option.rect.width() - 30.0),
+ int(option.rect.y() + 4),
+ self.curve_pixmaps[interpolation])
# Set text color
painter.setPen(QPen(Qt.white))
@@ -818,9 +826,9 @@ def Color_Picker_Triggered(self, cur_property):
_ = get_app()._tr
# Get current value of color
- red = cur_property[1]["red"]["value"]
- green = cur_property[1]["green"]["value"]
- blue = cur_property[1]["blue"]["value"]
+ red = int(cur_property[1]["red"]["value"])
+ green = int(cur_property[1]["green"]["value"])
+ blue = int(cur_property[1]["blue"]["value"])
# Show color dialog
currentColor = QColor(red, green, blue)
@@ -865,7 +873,7 @@ def __init__(self, *args):
self.files_model = self.win.files_model.model
# Connect to update signals, so our menus stay current
- self.win.files_model.ModelRefreshed.connect(self.refresh_menu)
+ self.files_model.dataChanged.connect(self.refresh_menu)
self.win.transition_model.ModelRefreshed.connect(self.refresh_menu)
self.menu_reset = False
@@ -890,7 +898,7 @@ def __init__(self, *args):
self.setWordWrap(True)
# Set delegate
- delegate = PropertyDelegate()
+ delegate = PropertyDelegate(model=self.clip_properties_model.model)
self.setItemDelegateForColumn(1, delegate)
self.previous_x = -1
diff --git a/src/windows/views/transitions_listview.py b/src/windows/views/transitions_listview.py
index 09af86b2b..3ba3346f5 100644
--- a/src/windows/views/transitions_listview.py
+++ b/src/windows/views/transitions_listview.py
@@ -36,7 +36,8 @@
class TransitionsListView(QListView):
""" A QListView QWidget used on the main window """
- drag_item_size = 48
+ drag_item_size = QSize(48, 48)
+ drag_item_center = QPoint(24, 24)
def contextMenuEvent(self, event):
event.accept()
@@ -70,8 +71,8 @@ def startDrag(self, supportedActions):
# Start drag operation
drag = QDrag(self)
drag.setMimeData(self.model().mimeData(selected))
- drag.setPixmap(icon.pixmap(QSize(self.drag_item_size, self.drag_item_size)))
- drag.setHotSpot(QPoint(self.drag_item_size / 2, self.drag_item_size / 2))
+ drag.setPixmap(icon.pixmap(self.drag_item_size))
+ drag.setHotSpot(self.drag_item_center)
drag.exec_()
def filter_changed(self):
diff --git a/src/windows/views/transitions_treeview.py b/src/windows/views/transitions_treeview.py
index 6f903e913..7aa0cd481 100644
--- a/src/windows/views/transitions_treeview.py
+++ b/src/windows/views/transitions_treeview.py
@@ -36,7 +36,8 @@
class TransitionsTreeView(QTreeView):
""" A TreeView QWidget used on the main window """
- drag_item_size = 48
+ drag_item_size = QSize(48, 48)
+ drag_item_center = QPoint(24, 24)
def contextMenuEvent(self, event):
# Set context menu mode
@@ -68,8 +69,8 @@ def startDrag(self, event):
# Start drag operation
drag = QDrag(self)
drag.setMimeData(self.model().mimeData(selected))
- drag.setPixmap(icon.pixmap(QSize(self.drag_item_size, self.drag_item_size)))
- drag.setHotSpot(QPoint(self.drag_item_size / 2, self.drag_item_size / 2))
+ drag.setPixmap(icon.pixmap(self.drag_item_size))
+ drag.setHotSpot(self.drag_item_center)
drag.exec_()
def refresh_columns(self):
diff --git a/src/windows/views/tutorial.py b/src/windows/views/tutorial.py
index e2d7fb861..24124799f 100644
--- a/src/windows/views/tutorial.py
+++ b/src/windows/views/tutorial.py
@@ -53,7 +53,12 @@ def paintEvent(self, event, *args):
painter.setPen(QPen(frameColor, 2))
painter.setBrush(self.palette().color(QPalette.Window))
- painter.drawRoundedRect(QRectF(31, 0, self.width() - 31, self.height()), 10, 10)
+ painter.drawRoundedRect(
+ QRectF(31, 0,
+ self.width() - 31,
+ self.height()
+ ),
+ 10, 10)
# Paint blue triangle (if needed)
if self.arrow:
@@ -61,7 +66,8 @@ def paintEvent(self, event, *args):
path = QPainterPath()
path.moveTo(0, 35)
path.lineTo(31, 35 - arrow_height)
- path.lineTo(31, (35 - arrow_height) + (arrow_height * 2))
+ path.lineTo(
+ 31, int((35 - arrow_height) + (arrow_height * 2)))
path.lineTo(0, 35)
painter.fillPath(path, frameColor)
@@ -199,7 +205,9 @@ def process(self, parent_name=None):
# Create tutorial
self.position_widget = tutorial_object
- self.offset = QPoint(tutorial_details["x"], tutorial_details["y"])
+ self.offset = QPoint(
+ int(tutorial_details["x"]),
+ int(tutorial_details["y"]))
tutorial_dialog = TutorialDialog(tutorial_id, tutorial_details["text"], tutorial_details["arrow"], self)
# Connect signals
From 9fc55120f36c36b2b6b67e499128993c25e535cf Mon Sep 17 00:00:00 2001
From: "FeRD (Frank Dana)" <ferdnyc@gmail.com>
Date: Thu, 4 Nov 2021 21:02:56 -0400
Subject: [PATCH 3/6] VideoWidget: New checkTransformMode
Replacement for getTransformMode with less repetitious code
---
src/windows/video_widget.py | 160 ++++++++++++++----------------------
1 file changed, 61 insertions(+), 99 deletions(-)
diff --git a/src/windows/video_widget.py b/src/windows/video_widget.py
index f33696c5c..1b9c35b54 100644
--- a/src/windows/video_widget.py
+++ b/src/windows/video_widget.py
@@ -610,106 +610,68 @@ def rotateCursor(self, pixmap, rotation, shear_x, shear_y):
Qt.SmoothTransformation)
return QCursor(rotated_pixmap)
- def getTransformMode(self, rotation, shear_x, shear_y, event):
+ def checkTransformMode(self, rotation, shear_x, shear_y, event):
+ handle_uis = [
+ {"handle": self.centerHandle, "mode": 'origin', "cursor": 'hand'},
+ {"handle": self.topRightHandle, "mode": 'scale_top_right', "cursor": 'resize_bdiag'},
+ {"handle": self.topHandle, "mode": 'scale_top', "cursor": 'resize_y'},
+ {"handle": self.topLeftHandle, "mode": 'scale_top_left', "cursor": 'resize_fdiag'},
+ {"handle": self.leftHandle, "mode": 'scale_left', "cursor": 'resize_x'},
+ {"handle": self.rightHandle, "mode": 'scale_right', "cursor": 'resize_x'},
+ {"handle": self.bottomLeftHandle, "mode": 'scale_bottom_left', "cursor": 'resize_bdiag'},
+ {"handle": self.bottomHandle, "mode": 'scale_bottom', "cursor": 'resize_y'},
+ {"handle": self.bottomRightHandle, "mode": 'scale_bottom_right', "cursor": 'resize_fdiag'},
+ {"handle": self.topShearHandle, "mode": 'shear_top', "cursor": 'shear_x'},
+ {"handle": self.leftShearHandle, "mode": 'shear_left', "cursor": 'shear_y'},
+ {"handle": self.rightShearHandle, "mode": 'shear_right', "cursor": 'shear_y'},
+ {"handle": self.bottomShearHandle, "mode": 'shear_bottom', "cursor": 'shear_x'},
+ ]
+ non_handle_uis = {
+ "region": self.clipBounds,
+ "inside": {"mode": 'location', "cursor": 'move'},
+ "outside": {"mode": 'rotation', "cursor": "rotate"}
+ }
+
# Mouse over resize button (and not currently dragging)
- if not self.mouse_dragging and self.resize_button.isVisible() and self.resize_button.rect().contains(event.pos()):
+ if (not self.mouse_dragging
+ and self.resize_button.isVisible()
+ and self.resize_button.rect().contains(event.pos()
+ ):
self.setCursor(Qt.ArrowCursor)
- # Determine if cursor is over a handle
- elif self.transform.mapToPolygon(self.centerHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'origin':
- self.setCursor(self.rotateCursor(self.cursors.get('hand'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'origin'
- elif self.transform.mapToPolygon(self.topRightHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'scale_top_right':
- self.setCursor(self.rotateCursor(self.cursors.get('resize_bdiag'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'scale_top_right'
- elif self.transform.mapToPolygon(self.topHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'scale_top':
- self.setCursor(self.rotateCursor(self.cursors.get('resize_y'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'scale_top'
- elif self.transform.mapToPolygon(self.topLeftHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'scale_top_left':
- self.setCursor(self.rotateCursor(self.cursors.get('resize_fdiag'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'scale_top_left'
- elif self.transform.mapToPolygon(self.leftHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'scale_left':
- self.setCursor(self.rotateCursor(self.cursors.get('resize_x'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'scale_left'
- elif self.transform.mapToPolygon(self.rightHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'scale_right':
- self.setCursor(self.rotateCursor(self.cursors.get('resize_x'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'scale_right'
- elif self.transform.mapToPolygon(self.bottomLeftHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'scale_bottom_left':
- self.setCursor(self.rotateCursor(self.cursors.get('resize_bdiag'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'scale_bottom_left'
- elif self.transform.mapToPolygon(self.bottomHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'scale_bottom':
- self.setCursor(self.rotateCursor(self.cursors.get('resize_y'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'scale_bottom'
- elif self.transform.mapToPolygon(self.bottomRightHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'scale_bottom_right':
- self.setCursor(self.rotateCursor(self.cursors.get('resize_fdiag'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'scale_bottom_right'
- elif self.transform.mapToPolygon(self.topShearHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'shear_top':
- self.setCursor(self.rotateCursor(self.cursors.get('shear_x'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'shear_top'
- elif self.transform.mapToPolygon(self.leftShearHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'shear_left':
- self.setCursor(self.rotateCursor(self.cursors.get('shear_y'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'shear_left'
- elif self.transform.mapToPolygon(self.rightShearHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'shear_right':
- self.setCursor(self.rotateCursor(self.cursors.get('shear_y'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'shear_right'
- elif self.transform.mapToPolygon(self.bottomShearHandle.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'shear_bottom':
- self.setCursor(self.rotateCursor(self.cursors.get('shear_x'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'shear_bottom'
- elif self.transform.mapToPolygon(self.clipBounds.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'location':
- self.setCursor(self.rotateCursor(self.cursors.get('move'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'location'
- elif not self.transform.mapToPolygon(self.clipBounds.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
- if not self.transform_mode or self.transform_mode == 'rotation':
- self.setCursor(self.rotateCursor(self.cursors.get('rotate'), rotation, shear_x, shear_y))
- # Set the transform mode
- if self.mouse_dragging and not self.transform_mode:
- self.transform_mode = 'rotation'
- elif not self.transform_mode:
- # Reset cursor when not over a handle
- self.setCursor(QCursor(Qt.ArrowCursor))
+ self.transform_mode = None
+ return
+
+ # If mouse is over a handle, set corresponding pointer/mode
+ for h in handle_uis:
+ if self.transform.mapToPolygon(
+ h["handle"].toRect()
+ ).containsPoint(event.pos(), Qt.OddEvenFill):
+ # Handle contains cursor
+ if self.transform_mode and self.transform_mode != h["mode"]:
+ # We're in different xform mode, skip
+ continue
+ if self.mouse_dragging:
+ self.transform_mode = h["mode"]
+ self.setCursor(self.rotateCursor(
+ self.cursors.get(h["cursor"]), rotation, shear_x, shear_y))
+ return
+
+ # If not over any handles, determne inside/outside clip rectangle
+ r = non_handle_uis.get("region")
+ if self.transform.mapToPolygon(r.toRect()).containsPoint(event.pos(), Qt.OddEvenFill):
+ nh = non_handle_uis.get("inside", {})
+ else:
+ nh = non_handle_uis.get("outside", {})
+ if self.mouse_dragging and not self.transform_mode:
+ self.transform_mode = nh.get("mode")
+ if not self.transform_mode or self.transform_mode == nh.get("mode"):
+ self.setCursor(self.rotateCursor(
+ self.cursors.get(nh.get("cursor")), rotation, shear_x, shear_y))
- return True
+
+ # If we got this far and we don't have a transform mode, reset the cursor
+ if not self.transform_mode:
+ self.setCursor(QCursor(Qt.ArrowCursor))
def mouseMoveEvent(self, event):
"""Capture mouse events on video preview window """
@@ -746,7 +708,7 @@ def mouseMoveEvent(self, event):
if self.mouse_dragging and not self.transform_mode:
self.original_clip_data = self.transforming_clip.data
- _ = self.getTransformMode(rotation, shear_x, shear_y, event)
+ self.checkTransformMode(rotation, shear_x, shear_y, event)
# Transform clip object
if self.transform_mode:
@@ -1040,7 +1002,7 @@ def mouseMoveEvent(self, event):
self.mutex.unlock()
return
- _ = self.getTransformMode(0, 0, 0, event)
+ self.checkTransformMode(0, 0, 0, event)
# Transform effect object
if self.transform_mode:
From 1f058f730bb36068bce5c645ecea45b98279b614 Mon Sep 17 00:00:00 2001
From: "FeRD (Frank Dana)" <ferdnyc@gmail.com>
Date: Thu, 4 Nov 2021 21:42:48 -0400
Subject: [PATCH 4/6] VideoWidget: Protect property accesses
---
src/windows/video_widget.py | 61 +++++++++++++++++++++----------------
1 file changed, 34 insertions(+), 27 deletions(-)
diff --git a/src/windows/video_widget.py b/src/windows/video_widget.py
index 1b9c35b54..a4d42969f 100644
--- a/src/windows/video_widget.py
+++ b/src/windows/video_widget.py
@@ -635,7 +635,7 @@ def checkTransformMode(self, rotation, shear_x, shear_y, event):
# Mouse over resize button (and not currently dragging)
if (not self.mouse_dragging
and self.resize_button.isVisible()
- and self.resize_button.rect().contains(event.pos()
+ and self.resize_button.rect().contains(event.pos())
):
self.setCursor(Qt.ArrowCursor)
self.transform_mode = None
@@ -668,11 +668,6 @@ def checkTransformMode(self, rotation, shear_x, shear_y, event):
self.setCursor(self.rotateCursor(
self.cursors.get(nh.get("cursor")), rotation, shear_x, shear_y))
-
- # If we got this far and we don't have a transform mode, reset the cursor
- if not self.transform_mode:
- self.setCursor(QCursor(Qt.ArrowCursor))
-
def mouseMoveEvent(self, event):
"""Capture mouse events on video preview window """
self.mutex.lock()
@@ -1121,27 +1116,37 @@ def updateClipProperty(self, clip_id, frame_number, property_key, new_value, ref
# No clip found
return
- for point in c.data[property_key]["Points"]:
- log.info("looping points: co.X = %s" % point["co"]["X"])
+ # Property missing? Create it!
+ if property_key not in c.data:
+ c.data[property_key] = {"Points": []}
+ log.warning(
+ "%s: Added missing '%s' to property data",
+ clip_id, property_key)
- if point["co"]["X"] == frame_number:
+ points = c.data.get(property_key).get("Points")
+ for point in points:
+ co = point.get("co", {})
+ log.info("looping points: co.X = %s" % co.get("X"))
+
+ if co.get("X") == frame_number:
found_point = True
clip_updated = True
- point["interpolation"] = openshot.BEZIER
- point["co"]["Y"] = float(new_value)
+ point.update({
+ "co": {"X": frame_number, "Y": float(new_value)},
+ "interpolation": openshot.BEZIER,
+ })
if not found_point and new_value is not None:
clip_updated = True
- log.info("Created new point at X=%s", frame_number)
+ log.info("Creating new point at X=%s", frame_number)
c.data[property_key]["Points"].append({
- 'co': {'X': frame_number, 'Y': new_value},
+ 'co': {'X': frame_number, 'Y': float(new_value)},
'interpolation': openshot.BEZIER
})
- # Reduce # of clip properties we are saving (performance boost)
- c.data = {property_key: c.data.get(property_key)}
-
if clip_updated:
+ # Reduce # of clip properties we are saving (performance boost)
+ c.data = {property_key: c.data.get(property_key)}
c.save()
# Update the preview
if refresh:
@@ -1166,27 +1171,29 @@ def updateEffectProperty(self, effect_id, frame_number, obj_id, property_key, ne
return
for point in points_list:
- log.info("looping points: co.X = %s", point["co"]["X"])
+ co = point.get("co", {})
+ log.info("looping points: co.X = %s", co.get("X"))
- if point["co"]["X"] == frame_number:
+ if co.get("X") == frame_number:
found_point = True
effect_updated = True
- point["interpolation"] = openshot.BEZIER
- point["co"]["Y"] = float(new_value)
+ point.update({
+ "co": {"X": frame_number, "Y": float(new_value)},
+ "interpolation": openshot.BEZIER,
+ })
- if not found_point and new_value != None:
+ if not found_point and new_value is not None:
effect_updated = True
- log.info("Created new point at X=%s", frame_number)
+ log.info("Creating new point at X=%s", frame_number)
points_list.append({
- 'co': { 'X': frame_number, 'Y': new_value },
+ 'co': {'X': frame_number, 'Y': float(new_value)},
'interpolation': openshot.BEZIER,
})
- # Reduce # of clip properties we are saving (performance boost)
- #TODO: This is too slow when draging transform handlers
- c.data = {'objects': {obj_id: c.data.get('objects', {}).get(obj_id)}}
-
if effect_updated:
+ # Reduce # of clip properties we are saving (performance boost)
+ #TODO: This is too slow when draging transform handlers
+ c.data = {'objects': {obj_id: c.data.get('objects', {}).get(obj_id)}}
c.save()
# Update the preview
if refresh:
From 7df87ddc189c5e5031fbb19df13378428fab951e Mon Sep 17 00:00:00 2001
From: "FeRD (Frank Dana)" <ferdnyc@gmail.com>
Date: Thu, 4 Nov 2021 21:52:19 -0400
Subject: [PATCH 5/6] classes/thumbnail: Fix dangling filehandles
---
src/classes/thumbnail.py | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/src/classes/thumbnail.py b/src/classes/thumbnail.py
index cca47d68f..dac7422a1 100644
--- a/src/classes/thumbnail.py
+++ b/src/classes/thumbnail.py
@@ -209,13 +209,13 @@ def do_GET(self):
# Send message back to client
if os.path.exists(thumb_path):
- if not only_path:
- self.wfile.write(open(thumb_path, 'rb').read())
- else:
+ if only_path:
self.wfile.write(bytes(thumb_path, "utf-8"))
+ else:
+ with open(thumb_path, 'rb') as f:
+ self.wfile.write(f.read())
# Pause processing of request (since we don't currently use thread pooling, this allows
# the threads to be processed without choking the CPU as much
# TODO: Make HTTPServer work with a limited thread pool and remove this sleep() hack.
time.sleep(0.01)
-
From 33cf68ca0b1ea57edd5dec3dbb8ba06d6a3f8fa4 Mon Sep 17 00:00:00 2001
From: "FeRD (Frank Dana)" <ferdnyc@gmail.com>
Date: Thu, 25 Nov 2021 02:18:32 -0500
Subject: [PATCH 6/6] properties_model: Fix bad logging call, Codacy flags
---
src/windows/models/properties_model.py | 10 +++++-----
1 file changed, 5 insertions(+), 5 deletions(-)
diff --git a/src/windows/models/properties_model.py b/src/windows/models/properties_model.py
index 40897f642..695e9f39c 100644
--- a/src/windows/models/properties_model.py
+++ b/src/windows/models/properties_model.py
@@ -444,7 +444,7 @@ def value_updated(self, item, interpolation=-1, value=None, interpolation_detail
log.debug("%s: update property %s. %s", log_id, property_key, clip_data.get(property_key))
# Check the type of property (some are keyframe, and some are not)
- if property_type != "reader" and type(clip_data[property_key]) == dict:
+ if property_type != "reader" and isinstance(clip_data[property_key], dict):
# Keyframe
# Loop through points, find a matching points on this frame
found_point = False
@@ -517,21 +517,21 @@ def value_updated(self, item, interpolation=-1, value=None, interpolation_detail
clip_updated = True
try:
clip_data[property_key] = int(new_value)
- except Exception as ex:
+ except Exception:
log.warn('Invalid Integer value passed to property', exc_info=1)
elif property_type == "float":
clip_updated = True
try:
clip_data[property_key] = float(new_value)
- except Exception as ex:
+ except Exception:
log.warn('Invalid Float value passed to property', exc_info=1)
elif property_type == "bool":
clip_updated = True
try:
clip_data[property_key] = bool(new_value)
- except Exception as ex:
+ except Exception:
log.warn('Invalid Boolean value passed to property', exc_info=1)
elif property_type == "string":
@@ -558,7 +558,7 @@ def value_updated(self, item, interpolation=-1, value=None, interpolation_detail
clip_object.Close()
clip_object = None
except Exception:
- log.warn('Invalid Reader value passed to property: %s (%s)', value, exc_info=1)
+ log.warn('Invalid Reader value passed to property: %s', value, exc_info=1)
# Reduce # of clip properties we are saving (performance boost)
clip_data = {property_key: clip_data.get(property_key)}