35
35
# Python module for libopenshot (required video editing module installed separately)
36
36
import openshot
37
37
38
+ from uuid import uuid4
38
39
from classes import info , ui_util
39
40
from classes .app import get_app
40
41
from classes .image_types import get_media_type
41
42
from classes .logger import log
42
43
from classes .metrics import track_metric_screen
44
+ from classes .query import Clip
43
45
44
46
45
47
class FileProperties (QDialog ):
@@ -78,6 +80,16 @@ def __init__(self, file):
78
80
# Dynamically load tabs from settings data
79
81
self .settings_data = self .s .get_all_settings ()
80
82
83
+ # Initialize Form
84
+ self .channel_layout_choices = []
85
+ self .initialize ()
86
+
87
+ def initialize (self ):
88
+ """Init all form elements / textboxes / etc..."""
89
+ # get translations
90
+ app = get_app ()
91
+ _ = app ._tr
92
+
81
93
# Get file properties
82
94
filename = os .path .basename (self .file .data ["path" ])
83
95
file_extension = os .path .splitext (filename )[1 ]
@@ -119,7 +131,7 @@ def __init__(self, file):
119
131
self .txtAudioBitRate .setValue (int (self .file .data ["audio_bit_rate" ]))
120
132
121
133
# Populate output field
122
- self .txtOutput .setText (json .dumps (file .data , sort_keys = True , indent = 2 ))
134
+ self .txtOutput .setText (json .dumps (self . file .data , sort_keys = True , indent = 2 ))
123
135
124
136
# Add channel layouts
125
137
selected_channel_layout_index = 0
@@ -213,6 +225,9 @@ def browsePath(self):
213
225
# verify path is valid (and prompt for image sequence if detected)
214
226
self .verifyPath (new_path )
215
227
228
+ # re-init form
229
+ self .initialize ()
230
+
216
231
def accept (self ):
217
232
new_path = self .txtFilePath .text ()
218
233
if new_path and self .file .data .get ("path" ) != new_path :
@@ -222,23 +237,57 @@ def accept(self):
222
237
# Update file details
223
238
self .file .data ["name" ] = self .txtFileName .text ()
224
239
self .file .data ["tags" ] = self .txtTags .text ()
225
-
226
- # Update Framerate
227
- self .file .data ["fps" ]["num" ] = self .txtFrameRateNum .value ()
228
- self .file .data ["fps" ]["den" ] = self .txtFrameRateDen .value ()
229
-
230
- # Update start / end frame
231
- fps_float = float (self .file .data ["fps" ]["num" ]) / float (self .file .data ["fps" ]["den" ])
232
- if self .txtStartFrame .value () != 1 or self .txtEndFrame .value () != int (self .file .data ["video_length" ]):
240
+
241
+ # Determine if FPS changed
242
+ fps_float = self .txtFrameRateNum .value () / self .txtFrameRateDen .value ()
243
+ if self .file .data ["fps" ]["num" ] != self .txtFrameRateNum .value () or \
244
+ self .file .data ["fps" ]["den" ] != self .txtFrameRateDen .value ():
245
+ original_fps_float = float (self .file .data ["fps" ]["num" ]) / float (self .file .data ["fps" ]["den" ])
246
+ # Update file 'fps' and 'video_timebase'
247
+ self .file .data ["fps" ]["num" ] = self .txtFrameRateNum .value ()
248
+ self .file .data ["fps" ]["den" ] = self .txtFrameRateDen .value ()
249
+ self .file .data ["video_timebase" ]["num" ] = self .txtFrameRateDen .value ()
250
+ self .file .data ["video_timebase" ]["den" ] = self .txtFrameRateNum .value ()
251
+
252
+ # Scale 'start' and 'end' properties by FPS difference
253
+ fps_diff = original_fps_float / fps_float
254
+ self .file .data ["duration" ] *= fps_diff
255
+ if "start" in self .file .data :
256
+ self .file .data ["start" ] *= fps_diff
257
+ if "end" in self .file .data :
258
+ self .file .data ["end" ] *= fps_diff
259
+
260
+ # Scale 'start' and 'end' file attributes (if changed)
261
+ elif self .txtStartFrame .value () != 1 or self .txtEndFrame .value () != int (self .file .data ["video_length" ]):
262
+ # Scale 'start' and 'end' properties by FPS difference
233
263
self .file .data ["start" ] = (self .txtStartFrame .value () - 1 ) / fps_float
234
264
self .file .data ["end" ] = (self .txtEndFrame .value () - 1 ) / fps_float
235
265
266
+ # Transaction id to group all updates together
267
+ tid = str (uuid4 ())
268
+ get_app ().updates .transaction_id = tid
269
+
236
270
# Save file object
237
271
self .file .save ()
238
272
239
273
# Update file info & thumbnail
240
274
get_app ().window .FileUpdated .emit (self .file .id )
241
275
276
+ # Update related clips
277
+ for clip in Clip .filter (file_id = self .file .id ):
278
+ clip .data ["reader" ] = self .file .data
279
+ clip .data ["duration" ] = self .file .data ["duration" ]
280
+ if clip .data ["end" ] > clip .data ["duration" ]:
281
+ clip .data ["end" ] = clip .data ["duration" ]
282
+ clip .save ()
283
+
284
+ # Emit thumbnail update signal (to update timeline thumb image)
285
+ thumbnail_frame = (clip .data ["start" ] * fps_float ) + 1
286
+ get_app ().window .ThumbnailUpdated .emit (clip .id , thumbnail_frame )
287
+
288
+ # Done grouping transactions
289
+ get_app ().updates .transaction_id = None
290
+
242
291
# Accept dialog
243
292
super (FileProperties , self ).accept ()
244
293
0 commit comments