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)
83 self.update_timer.start()
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))
153 if item_type ==
"effect":
155 parent_clip_id = Effect.get(id=clip.Id()).parent[
"id"]
158 clips =
get_app().window.timeline_sync.timeline.Clips()
160 if c.Id() == parent_clip_id:
166 fps =
get_app().project.get([
"fps"])
167 fps_float = float(fps[
"num"]) / float(fps[
"den"])
170 requested_time = float(frame_number - 1) / fps_float
173 time_diff = (requested_time - clip.Position()) + clip.Start()
177 min_frame_number = int((clip.Start() * fps_float)) + 1
178 max_frame_number = int((clip.End() * fps_float)) + 1
196 property = self.model.item(item.row(), 0).data()
197 property_name = property[1][
"name"]
198 property_type = property[1][
"type"]
199 closest_point_x = property[1][
"closest_point_x"]
200 property_type = property[1][
"type"]
201 property_key = property[0]
202 clip_id, item_type = item.data()
208 if item_type ==
"clip":
210 c = Clip.get(id=clip_id)
211 elif item_type ==
"transition":
213 c = Transition.get(id=clip_id)
214 elif item_type ==
"effect":
216 c = Effect.get(id=clip_id)
220 if property_key
in c.data:
221 log.info(
"remove keyframe: %s" % c.data)
225 if property_type ==
"color":
226 keyframe_list = [c.data[property_key][
"red"], c.data[property_key][
"blue"], c.data[property_key][
"green"]]
228 keyframe_list = [c.data[property_key]]
231 for keyframe
in keyframe_list:
236 point_to_delete =
None 237 for point
in keyframe[
"Points"]:
241 point_to_delete = point
243 if point[
"co"][
"X"] == closest_point_x:
244 closest_point = point
247 if not point_to_delete:
248 point_to_delete = closest_point
253 log.info(
"Found point to delete at X=%s" % point_to_delete[
"co"][
"X"])
254 keyframe[
"Points"].remove(point_to_delete)
257 c.data = {property_key: c.data[property_key]}
265 get_app().window.refreshFrameSignal.emit()
268 self.parent.clearSelection()
275 property = self.model.item(item.row(), 0).data()
276 property_type = property[1][
"type"]
277 closest_point_x = property[1][
"closest_point_x"]
278 property_key = property[0]
279 clip_id, item_type = item.data()
281 if property_type ==
"color":
286 if item_type ==
"clip":
288 c = Clip.get(id=clip_id)
289 elif item_type ==
"transition":
291 c = Transition.get(id=clip_id)
292 elif item_type ==
"effect":
294 c = Effect.get(id=clip_id)
298 if property_key
in c.data:
299 log.info(
"color update: %s" % c.data)
302 for color, new_value
in [(
"red", new_color.red()), (
"blue", new_color.blue()), (
"green", new_color.green())]:
307 for point
in c.data[property_key][color][
"Points"]:
308 log.info(
"looping points: co.X = %s" % point[
"co"][
"X"])
309 if interpolation == -1
and point[
"co"][
"X"] == self.
frame_number:
314 point[
"co"][
"Y"] = new_value
315 log.info(
"updating point: co.X = %s to value: %s" % (point[
"co"][
"X"], float(new_value)))
318 elif interpolation > -1
and point[
"co"][
"X"] == closest_point_x:
322 point[
"interpolation"] = interpolation
323 log.info(
"updating interpolation mode point: co.X = %s to %s" % (point[
"co"][
"X"], interpolation))
329 log.info(
"Created new point at X=%s" % self.
frame_number)
330 c.data[property_key][color][
"Points"].append({
'co': {
'X': self.
frame_number,
'Y': new_value},
'interpolation': 1})
333 c.data = {property_key: c.data[property_key]}
341 get_app().window.refreshFrameSignal.emit()
344 self.parent.clearSelection()
357 property = self.model.item(item.row(), 0).data()
358 property_name = property[1][
"name"]
359 closest_point_x = property[1][
"closest_point_x"]
360 property_type = property[1][
"type"]
361 property_key = property[0]
362 clip_id, item_type = item.data()
370 elif property_type ==
"string":
372 new_value = item.text()
373 elif property_type ==
"bool":
375 if item.text() == _(
"False"):
379 elif property_type ==
"int":
381 new_value = QLocale().system().toInt(item.text())[0]
384 new_value = QLocale().system().toFloat(item.text())[0]
388 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))
395 if item_type ==
"clip":
397 c = Clip.get(id=clip_id)
398 elif item_type ==
"transition":
400 c = Transition.get(id=clip_id)
401 elif item_type ==
"effect":
403 c = Effect.get(id=clip_id)
407 if property_key
in c.data:
408 log.info(
"value updated: %s" % c.data)
411 if type(c.data[property_key]) == dict:
415 point_to_delete =
None 416 for point
in c.data[property_key][
"Points"]:
417 log.info(
"looping points: co.X = %s" % point[
"co"][
"X"])
418 if interpolation == -1
and point[
"co"][
"X"] == self.
frame_number:
423 if new_value !=
None:
424 point[
"co"][
"Y"] = float(new_value)
425 log.info(
"updating point: co.X = %s to value: %s" % (point[
"co"][
"X"], float(new_value)))
427 point_to_delete = point
430 elif interpolation > -1
and point[
"co"][
"X"] == closest_point_x:
434 point[
"interpolation"] = interpolation
435 log.info(
"updating interpolation mode point: co.X = %s to %s" % (point[
"co"][
"X"], interpolation))
441 log.info(
"Found point to delete at X=%s" % point_to_delete[
"co"][
"X"])
442 c.data[property_key][
"Points"].remove(point_to_delete)
445 elif not found_point
and new_value !=
None:
447 log.info(
"Created new point at X=%s" % self.
frame_number)
448 c.data[property_key][
"Points"].append({
'co': {
'X': self.
frame_number,
'Y': new_value},
'interpolation': 1})
450 elif property_type ==
"int":
453 c.data[property_key] = int(new_value)
455 elif property_type ==
"float":
458 c.data[property_key] = new_value
460 elif property_type ==
"bool":
463 c.data[property_key] = bool(new_value)
465 elif property_type ==
"string":
468 c.data[property_key] = str(new_value)
472 c.data = {property_key: c.data.get(property_key)}
480 get_app().window.refreshFrameSignal.emit()
483 self.parent.clearSelection()
486 log.info(
"updating clip properties model.")
491 self.update_timer.stop()
503 raw_properties = json.loads(c.PropertiesJSON(self.
frame_number))
504 all_properties = OrderedDict(sorted(raw_properties.items(), key=
lambda x: x[1][
'name']))
505 log.info(
"Getting properties for frame %s: %s" % (self.
frame_number, str(all_properties)))
522 self.model.setHorizontalHeaderLabels([_(
"Property"), _(
"Value")])
526 for property
in all_properties.items():
527 label = property[1][
"name"]
529 value = property[1][
"value"]
530 type = property[1][
"type"]
531 memo = property[1][
"memo"]
532 readonly = property[1][
"readonly"]
533 keyframe = property[1][
"keyframe"]
534 points = property[1][
"points"]
535 interpolation = property[1][
"interpolation"]
536 closest_point_x = property[1][
"closest_point_x"]
537 choices = property[1][
"choices"]
540 transparency_label = _(
"Transparency")
542 selected_choice =
None 544 selected_choice = [c
for c
in choices
if c[
"selected"] ==
True][0][
"name"]
547 if filter
and filter.lower()
not in name.lower():
559 col = QStandardItem(
"Property")
560 col.setText(_(label))
561 col.setData(property)
562 if keyframe
and points > 1:
563 col.setBackground(QColor(
"green"))
565 col.setBackground(QColor(42, 130, 218))
567 col.setFlags(Qt.ItemIsEnabled)
569 col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable)
573 col = QStandardItem(
"Value")
575 col.setText(_(selected_choice))
576 elif type ==
"string":
582 col.setText(_(
"True"))
584 col.setText(_(
"False"))
585 elif type ==
"color":
589 col.setText(
"%d" % value)
592 col.setText(QLocale().system().toString(float(value),
"f", precision=2))
593 col.setData((c.Id(), item_type))
596 my_icon = QPixmap(os.path.join(info.IMAGES_PATH,
"keyframe-%s.png" % interpolation))
597 col.setData(my_icon, Qt.DecorationRole)
599 log.info(os.path.join(info.IMAGES_PATH,
"keyframe-%s.png" % interpolation))
603 col.setBackground(QColor(
"green"))
605 col.setBackground(QColor(42, 130, 218))
609 red = property[1][
"red"][
"value"]
610 green = property[1][
"green"][
"value"]
611 blue = property[1][
"blue"][
"value"]
612 col.setBackground(QColor(red, green, blue))
614 if readonly
or type ==
"color" or choices:
615 col.setFlags(Qt.ItemIsEnabled)
617 col.setFlags(Qt.ItemIsSelectable | Qt.ItemIsEnabled | Qt.ItemIsUserCheckable | Qt.ItemIsEditable)
621 self.model.appendRow(row)
626 col = self.
items[name][
"row"][0]
627 col.setData(property)
630 if keyframe
and points > 1:
631 col.setBackground(QColor(
"green"))
633 col.setBackground(QColor(42, 130, 218))
635 col.setBackground(QStandardItem(
"Empty").background())
641 col = self.
items[name][
"row"][1]
643 col.setText(_(selected_choice))
644 elif type ==
"string":
650 col.setText(_(
"True"))
652 col.setText(_(
"False"))
653 elif type ==
"color":
657 col.setText(
"%d" % value)
660 col.setText(QLocale().system().toString(float(value),
"f", precision=2))
664 my_icon = QPixmap(os.path.join(info.IMAGES_PATH,
"keyframe-%s.png" % interpolation))
665 col.setData(my_icon, Qt.DecorationRole)
669 col.setBackground(QColor(
"green"))
671 col.setBackground(QColor(42, 130, 218))
675 col.setBackground(QStandardItem(
"Empty").background())
679 col.setData(my_icon, Qt.DecorationRole)
683 red = property[1][
"red"][
"value"]
684 green = property[1][
"green"][
"value"]
685 blue = property[1][
"blue"][
"value"]
686 col.setBackground(QColor(red, green, blue))
692 self.
items[name] = {
"row": row,
"property": property}
705 self.model.setHorizontalHeaderLabels([_(
"Property"), _(
"Value")])
727 self.model.setColumnCount(2)
732 self.update_timer.setInterval(100)
734 self.update_timer.stop()
742 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 value_updated(self, item, interpolation=-1, value=None)
Table cell change event - also handles context menu to update interpolation value.
def color_update(self, item, new_color, interpolation=-1)
Insert/Update a color keyframe for the selected row.
def __init__(self, parent, args)
def changed(self, action)
def update_item_timeout(self)
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)
def update_frame(self, frame_number)