30 from collections
import OrderedDict
35 from classes
import updates
36 from classes
import info
37 from classes.query
import Clip, Transition, Effect
38 from classes.logger
import log
39 from classes.app
import get_app
44 import simplejson
as json
49 QStandardItemModel.__init__(self)
58 selected_row = self.itemFromIndex(item).row()
59 property_names.append(self.item(selected_row, 0).data())
60 data.setText(json.dumps(property_names))
71 if action.key
and action.key[0]
in [
"clips",
"effects"]
and action.type
in [
"update",
"insert"]:
72 log.info(action.values)
95 log.info(
"Update item: %s" % item_type)
97 if item_type ==
"clip":
99 clips =
get_app().window.timeline_sync.timeline.Clips()
101 if clip.Id() == item_id:
106 self.
selected.append((c, item_type))
108 if item_type ==
"transition":
110 trans =
get_app().window.timeline_sync.timeline.Effects()
112 if tran.Id() == item_id:
117 self.
selected.append((t, item_type))
119 if item_type ==
"effect":
121 clips =
get_app().window.timeline_sync.timeline.Clips()
123 for effect
in clip.Effects():
124 if effect.Id() == item_id:
132 self.
selected.append((e, item_type))
156 if item_type ==
"effect":
158 effect = Effect.get(id=clip.Id())
163 parent_clip_id = effect.parent[
"id"]
166 clips =
get_app().window.timeline_sync.timeline.Clips()
168 if c.Id() == parent_clip_id:
174 fps =
get_app().project.get([
"fps"])
175 fps_float = float(fps[
"num"]) / float(fps[
"den"])
178 requested_time = float(frame_number - 1) / fps_float
181 time_diff = (requested_time - clip.Position()) + clip.Start()
185 min_frame_number = round((clip.Start() * fps_float)) + 1
186 max_frame_number = round((clip.End() * fps_float)) + 1
205 property = self.
model.item(item.row(), 0).data()
206 property_name = property[1][
"name"]
207 property_type = property[1][
"type"]
208 closest_point_x = property[1][
"closest_point_x"]
209 property_type = property[1][
"type"]
210 property_key = property[0]
211 clip_id, item_type = item.data()
217 if item_type ==
"clip":
219 c = Clip.get(id=clip_id)
220 elif item_type ==
"transition":
222 c = Transition.get(id=clip_id)
223 elif item_type ==
"effect":
225 c = Effect.get(id=clip_id)
229 if property_key
in c.data:
230 log.info(
"remove keyframe: %s" % c.data)
234 if property_type ==
"color":
235 keyframe_list = [c.data[property_key][
"red"], c.data[property_key][
"blue"], c.data[property_key][
"green"]]
237 keyframe_list = [c.data[property_key]]
240 for keyframe
in keyframe_list:
245 point_to_delete =
None 246 for point
in keyframe[
"Points"]:
250 point_to_delete = point
252 if point[
"co"][
"X"] == closest_point_x:
253 closest_point = point
256 if not point_to_delete:
257 point_to_delete = closest_point
262 log.info(
"Found point to delete at X=%s" % point_to_delete[
"co"][
"X"])
263 keyframe[
"Points"].remove(point_to_delete)
266 c.data = {property_key: c.data[property_key]}
274 get_app().window.refreshFrameSignal.emit()
277 self.
parent.clearSelection()
281 def color_update(self, item, new_color, interpolation=-1, interpolation_details=[]):
284 property = self.
model.item(item.row(), 0).data()
285 property_type = property[1][
"type"]
286 closest_point_x = property[1][
"closest_point_x"]
287 previous_point_x = property[1][
"previous_point_x"]
288 property_key = property[0]
289 clip_id, item_type = item.data()
291 if property_type ==
"color":
296 if item_type ==
"clip":
298 c = Clip.get(id=clip_id)
299 elif item_type ==
"transition":
301 c = Transition.get(id=clip_id)
302 elif item_type ==
"effect":
304 c = Effect.get(id=clip_id)
308 if property_key
in c.data:
309 log.info(
"color update: %s" % c.data)
312 for color, new_value
in [(
"red", new_color.red()), (
"blue", new_color.blue()), (
"green", new_color.green())]:
317 for point
in c.data[property_key][color][
"Points"]:
318 log.info(
"looping points: co.X = %s" % point[
"co"][
"X"])
319 if interpolation == -1
and point[
"co"][
"X"] == self.
frame_number:
324 point[
"co"][
"Y"] = new_value
325 log.info(
"updating point: co.X = %s to value: %s" % (point[
"co"][
"X"], float(new_value)))
328 elif interpolation > -1
and point[
"co"][
"X"] == previous_point_x:
332 point[
"interpolation"] = interpolation
333 if interpolation == 0:
334 point[
"handle_right"] = point.get(
"handle_right")
or {
"Y": 0.0,
"X": 0.0}
335 point[
"handle_right"][
"X"] = interpolation_details[0]
336 point[
"handle_right"][
"Y"] = interpolation_details[1]
338 log.info(
"updating interpolation mode point: co.X = %s to %s" % (point[
"co"][
"X"], interpolation))
339 log.info(
"use interpolation preset: %s" % str(interpolation_details))
341 elif interpolation > -1
and point[
"co"][
"X"] == closest_point_x:
345 point[
"interpolation"] = interpolation
346 if interpolation == 0:
347 point[
"handle_left"] = point.get(
"handle_left")
or {
"Y": 0.0,
"X": 0.0}
348 point[
"handle_left"][
"X"] = interpolation_details[2]
349 point[
"handle_left"][
"Y"] = interpolation_details[3]
351 log.info(
"updating interpolation mode point: co.X = %s to %s" % (point[
"co"][
"X"], interpolation))
352 log.info(
"use interpolation preset: %s" % str(interpolation_details))
357 log.info(
"Created new point at X=%s" % self.
frame_number)
358 c.data[property_key][color][
"Points"].append({
'co': {
'X': self.
frame_number,
'Y': new_value},
'interpolation': 1})
361 c.data = {property_key: c.data[property_key]}
369 get_app().window.refreshFrameSignal.emit()
372 self.
parent.clearSelection()
376 def value_updated(self, item, interpolation=-1, value=None, interpolation_details=[]):
385 property = self.
model.item(item.row(), 0).data()
386 property_name = property[1][
"name"]
387 closest_point_x = property[1][
"closest_point_x"]
388 previous_point_x = property[1][
"previous_point_x"]
389 property_type = property[1][
"type"]
390 property_key = property[0]
391 clip_id, item_type = item.data()
399 elif property_type ==
"string":
401 new_value = item.text()
402 elif property_type ==
"bool":
404 if item.text() == _(
"False"):
408 elif property_type ==
"int":
410 new_value = QLocale().system().toInt(item.text())[0]
413 new_value = QLocale().system().toFloat(item.text())[0]
417 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))
424 if item_type ==
"clip":
426 c = Clip.get(id=clip_id)
427 elif item_type ==
"transition":
429 c = Transition.get(id=clip_id)
430 elif item_type ==
"effect":
432 c = Effect.get(id=clip_id)
436 if property_key
in c.data:
437 log.info(
"value updated: %s" % c.data)
440 if type(c.data[property_key]) == dict:
444 point_to_delete =
None 445 for point
in c.data[property_key][
"Points"]:
446 log.info(
"looping points: co.X = %s" % point[
"co"][
"X"])
447 if interpolation == -1
and point[
"co"][
"X"] == self.
frame_number:
452 if new_value !=
None:
453 point[
"co"][
"Y"] = float(new_value)
454 log.info(
"updating point: co.X = %s to value: %s" % (point[
"co"][
"X"], float(new_value)))
456 point_to_delete = point
459 elif interpolation > -1
and point[
"co"][
"X"] == previous_point_x:
463 point[
"interpolation"] = interpolation
464 if interpolation == 0:
465 point[
"handle_right"] = point.get(
"handle_right")
or {
"Y": 0.0,
"X": 0.0}
466 point[
"handle_right"][
"X"] = interpolation_details[0]
467 point[
"handle_right"][
"Y"] = interpolation_details[1]
469 log.info(
"updating interpolation mode point: co.X = %s to %s" % (point[
"co"][
"X"], interpolation))
470 log.info(
"use interpolation preset: %s" % str(interpolation_details))
472 elif interpolation > -1
and point[
"co"][
"X"] == closest_point_x:
476 point[
"interpolation"] = interpolation
477 if interpolation == 0:
478 point[
"handle_left"] = point.get(
"handle_left")
or {
"Y": 0.0,
"X": 0.0}
479 point[
"handle_left"][
"X"] = interpolation_details[2]
480 point[
"handle_left"][
"Y"] = interpolation_details[3]
482 log.info(
"updating interpolation mode point: co.X = %s to %s" % (point[
"co"][
"X"], interpolation))
483 log.info(
"use interpolation preset: %s" % str(interpolation_details))
488 log.info(
"Found point to delete at X=%s" % point_to_delete[
"co"][
"X"])
489 c.data[property_key][
"Points"].remove(point_to_delete)
492 elif not found_point
and new_value !=
None:
494 log.info(
"Created new point at X=%s" % self.
frame_number)
495 c.data[property_key][
"Points"].append({
'co': {
'X': self.
frame_number,
'Y': new_value},
'interpolation': 1})
499 if property_type ==
"int":
502 c.data[property_key] = int(new_value)
504 elif property_type ==
"float":
507 c.data[property_key] = new_value
509 elif property_type ==
"bool":
512 c.data[property_key] = bool(new_value)
514 elif property_type ==
"string":
517 c.data[property_key] = str(new_value)
521 c.data = {property_key: c.data.get(property_key)}
529 get_app().window.refreshFrameSignal.emit()
532 self.
parent.clearSelection()
535 log.info(
"updating clip properties model.")
552 raw_properties = json.loads(c.PropertiesJSON(self.
frame_number))
553 all_properties = OrderedDict(sorted(raw_properties.items(), key=
lambda x: x[1][
'name']))
554 log.info(
"Getting properties for frame %s: %s" % (self.
frame_number, str(all_properties)))
571 self.
model.setHorizontalHeaderLabels([_(
"Property"), _(
"Value")])
575 for property
in all_properties.items():
576 label = property[1][
"name"]
578 value = property[1][
"value"]
579 type = property[1][
"type"]
580 memo = property[1][
"memo"]
581 readonly = property[1][
"readonly"]
582 keyframe = property[1][
"keyframe"]
583 points = property[1][
"points"]
584 interpolation = property[1][
"interpolation"]
585 closest_point_x = property[1][
"closest_point_x"]
586 choices = property[1][
"choices"]
589 transparency_label = _(
"Transparency")
591 selected_choice =
None 593 selected_choice = [c
for c
in choices
if c[
"selected"] ==
True][0][
"name"]
596 if filter
and filter.lower()
not in name.lower():
608 col = QStandardItem(
"Property")
609 col.setText(_(label))
610 col.setData(property)
611 if keyframe
and points > 1:
612 col.setBackground(QColor(
"green"))
614 col.setBackground(QColor(42, 130, 218))
616 col.setFlags(Qt.ItemIsEnabled)
618 col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
622 col = QStandardItem(
"Value")
624 col.setText(_(selected_choice))
625 elif type ==
"string":
631 col.setText(_(
"True"))
633 col.setText(_(
"False"))
634 elif type ==
"color":
638 col.setText(
"%d" % value)
641 col.setText(QLocale().system().toString(float(value),
"f", precision=2))
642 col.setData((c.Id(), item_type))
645 my_icon = QPixmap(os.path.join(info.IMAGES_PATH,
"keyframe-%s.png" % interpolation))
646 col.setData(my_icon, Qt.DecorationRole)
650 col.setBackground(QColor(
"green"))
652 col.setBackground(QColor(42, 130, 218))
656 red = property[1][
"red"][
"value"]
657 green = property[1][
"green"][
"value"]
658 blue = property[1][
"blue"][
"value"]
659 col.setBackground(QColor(red, green, blue))
661 if readonly
or type ==
"color" or choices:
662 col.setFlags(Qt.ItemIsEnabled)
664 col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsEditable)
668 self.
model.appendRow(row)
673 col = self.
items[name][
"row"][0]
674 col.setData(property)
677 if keyframe
and points > 1:
678 col.setBackground(QColor(
"green"))
680 col.setBackground(QColor(42, 130, 218))
682 col.setBackground(QStandardItem(
"Empty").background())
688 col = self.
items[name][
"row"][1]
690 col.setText(_(selected_choice))
691 elif type ==
"string":
697 col.setText(_(
"True"))
699 col.setText(_(
"False"))
700 elif type ==
"color":
704 col.setText(
"%d" % value)
707 col.setText(QLocale().system().toString(float(value),
"f", precision=2))
711 my_icon = QPixmap(os.path.join(info.IMAGES_PATH,
"keyframe-%s.png" % interpolation))
712 col.setData(my_icon, Qt.DecorationRole)
716 col.setBackground(QColor(
"green"))
718 col.setBackground(QColor(42, 130, 218))
722 col.setBackground(QStandardItem(
"Empty").background())
726 col.setData(my_icon, Qt.DecorationRole)
730 red = property[1][
"red"][
"value"]
731 green = property[1][
"green"][
"value"]
732 blue = property[1][
"blue"][
"value"]
733 col.setBackground(QColor(red, green, blue))
739 self.
items[name] = {
"row": row,
"property": property}
752 self.
model.setHorizontalHeaderLabels([_(
"Property"), _(
"Value")])
774 self.
model.setColumnCount(2)
789 get_app().updates.add_listener(self)
def mimeData(self, indexes)
def get_app()
Returns the current QApplication instance of OpenShot.
def update_model(self, filter="")
def color_update(self, item, new_color, interpolation=-1, interpolation_details=[])
Insert/Update a color keyframe for the selected row.
def update_frame(self, frame_number, reload_model=True)
def __init__(self, parent, args)
def changed(self, action)
def update_item_timeout(self)
def value_updated(self, item, interpolation=-1, value=None, interpolation_details=[])
Table cell change event - also handles context menu to update interpolation value.
def remove_keyframe(self, item)
Remove an existing keyframe (if any)
Interface for classes that listen for changes (insert, update, and delete).
def __init__(self, parent=None)
def update_item(self, item_id, item_type)