[pitivi] previewers: Add Title clip Previewer



commit ebf36119f153cefdd71c56cd9af6ed83b0d8f1f4
Author: Diego Garcia Gangl <dnicolas gmail com>
Date:   Sat May 4 20:59:39 2019 -0300

    previewers: Add Title clip Previewer
    
    Fixes #2311

 pitivi/check.py               |  1 +
 pitivi/timeline/elements.py   | 10 +++--
 pitivi/timeline/previewers.py | 99 ++++++++++++++++++++++++++++++++++++++++++-
 pitivi/utils/ui.py            |  7 +--
 4 files changed, 108 insertions(+), 9 deletions(-)
---
diff --git a/pitivi/check.py b/pitivi/check.py
index 41daec7d..193f5301 100644
--- a/pitivi/check.py
+++ b/pitivi/check.py
@@ -444,6 +444,7 @@ HARD_DEPENDENCIES = [GICheck(version_required="3.20.0"),
                      GstPluginDependency("gdkpixbuf"),
                      ClassicDependency("matplotlib"),
                      GIDependency("Peas", apiversion="1.0"),
+                     GIDependency("PangoCairo", apiversion="1.0"),
                      ]
 
 SOFT_DEPENDENCIES = (
diff --git a/pitivi/timeline/elements.py b/pitivi/timeline/elements.py
index c2abdbd3..6f70041d 100644
--- a/pitivi/timeline/elements.py
+++ b/pitivi/timeline/elements.py
@@ -33,6 +33,7 @@ from pitivi.configure import get_pixmap_dir
 from pitivi.effects import ALLOWED_ONLY_ONCE_EFFECTS
 from pitivi.timeline.previewers import AudioPreviewer
 from pitivi.timeline.previewers import ImagePreviewer
+from pitivi.timeline.previewers import TitlePreviewer
 from pitivi.timeline.previewers import VideoPreviewer
 from pitivi.undo.timeline import CommitTimelineFinalizingAction
 from pitivi.utils.loggable import Loggable
@@ -964,6 +965,11 @@ class TitleSource(VideoSource):
                 return spec
             return None
 
+    def _get_previewer(self):
+        previewer = TitlePreviewer(self._ges_elem)
+        previewer.get_style_context().add_class("TitleSource")
+        return previewer
+
     def _get_default_position(self):
         return {"posx": 0,
                 "posy": 0,
@@ -984,8 +990,6 @@ class VideoUriSource(VideoSource):
             previewer = ImagePreviewer(self._ges_elem, self.timeline.app.settings.previewers_max_cpu)
         else:
             previewer = VideoPreviewer(self._ges_elem, self.timeline.app.settings.previewers_max_cpu)
-        previewer.get_style_context().add_class("VideoUriSource")
-
         return previewer
 
     def _get_default_mixing_property(self):
@@ -1012,8 +1016,6 @@ class AudioUriSource(TimelineElement):
 
     def _get_previewer(self):
         previewer = AudioPreviewer(self._ges_elem, self.timeline.app.settings.previewers_max_cpu)
-        previewer.get_style_context().add_class("AudioPreviewer")
-
         return previewer
 
     def _get_background(self):
diff --git a/pitivi/timeline/previewers.py b/pitivi/timeline/previewers.py
index 78a33e96..6641f56e 100644
--- a/pitivi/timeline/previewers.py
+++ b/pitivi/timeline/previewers.py
@@ -20,6 +20,7 @@ import hashlib
 import os
 import random
 import sqlite3
+from gettext import gettext as _
 
 import cairo
 import numpy
@@ -30,6 +31,8 @@ from gi.repository import GLib
 from gi.repository import GObject
 from gi.repository import Gst
 from gi.repository import Gtk
+from gi.repository import Pango
+from gi.repository import PangoCairo
 
 from pitivi.settings import GlobalSettings
 from pitivi.settings import xdg_cache_home
@@ -368,11 +371,9 @@ class Previewer(GObject.Object):
 
     def start_generation(self):
         """Starts preview generation."""
-        raise NotImplementedError
 
     def stop_generation(self):
         """Stops preview generation."""
-        raise NotImplementedError
 
     def become_controlled(self):
         """Lets the PreviewGeneratorManager control our execution."""
@@ -414,6 +415,8 @@ class ImagePreviewer(Gtk.Layout, Previewer, Zoomable, Loggable):
         Zoomable.__init__(self)
         Loggable.__init__(self)
 
+        self.get_style_context().add_class("VideoPreviewer")
+
         self.ges_elem = ges_elem
 
         # Guard against malformed URIs
@@ -810,6 +813,8 @@ class VideoPreviewer(Gtk.Layout, AssetPreviewer, Zoomable):
         Zoomable.__init__(self)
         AssetPreviewer.__init__(self, get_proxy_target(ges_elem), max_cpu_usage)
 
+        self.get_style_context().add_class("VideoPreviewer")
+
         self.ges_elem = ges_elem
         self.thumbs = {}
 
@@ -905,6 +910,9 @@ class Thumbnail(Gtk.Image):
 
     def __init__(self, width, height):
         Gtk.Image.__init__(self)
+
+        self.get_style_context().add_class("Thumbnail")
+
         self.props.width_request = width
         self.props.height_request = height
 
@@ -1117,6 +1125,8 @@ class AudioPreviewer(Gtk.Layout, Previewer, Zoomable, Loggable):
         Zoomable.__init__(self)
         Loggable.__init__(self)
 
+        self.get_style_context().add_class("AudioPreviewer")
+
         self.pipeline = None
         self._wavebin = None
 
@@ -1313,3 +1323,88 @@ class AudioPreviewer(Gtk.Layout, Previewer, Zoomable, Loggable):
         """Stops preview generation and cleans the object."""
         self.stop_generation()
         Zoomable.__del__(self)
+
+
+class TitlePreviewer(Gtk.Layout, Previewer, Zoomable, Loggable):
+    """Title Clip previewer using Pango to draw text on the clip."""
+
+    __gsignals__ = PREVIEW_GENERATOR_SIGNALS
+
+    def __init__(self, ges_elem):
+        Gtk.Layout.__init__(self)
+        Previewer.__init__(self, GES.TrackType.VIDEO, None)
+        Zoomable.__init__(self)
+        Loggable.__init__(self)
+
+        self.get_style_context().add_class("TitlePreviewer")
+
+        self.ges_elem = ges_elem
+        font = Gtk.Settings.get_default().get_property("gtk-font-name")
+        self._font_desc = Pango.font_description_from_string(font)
+        self._selected = False
+
+        self.ges_elem.connect("deep-notify", self._ges_elem_deep_notify_cb)
+
+    def _ges_elem_deep_notify_cb(self, ges_element, gst_element, pspec):
+        """Forces a redraw when the clip's text is changed."""
+        if pspec.name == "text":
+            self.queue_draw()
+
+    def do_draw(self, context):
+        rect = Gdk.cairo_get_clip_rectangle(context)[1]
+        context.set_source_rgb(1, 1, 1)
+
+        # Get text
+        res, text = self.ges_elem.get_child_property("text")
+        if res:
+            text = text.strip().split("\n", 1)[0]
+        if not res or not text:
+            text = _("Title Clip")
+
+        # Adapt to RTL/LTR direction
+        direction = Pango.unichar_direction(text[0])
+        if direction in (Pango.Direction.LTR, Pango.Direction.NEUTRAL):
+            stops = (0, 1)
+            x_pos = 10
+            grad = cairo.LinearGradient(rect.width * 0.66, 0,
+                                        rect.width * 0.91, 0)
+        else:
+            stops = (1, 0)
+            x_pos = -10
+            grad = cairo.LinearGradient(rect.width * 0.09, 0,
+                                        rect.width * 0.34, 0)
+
+        # Gradient to make text "fade out"
+        if self._selected:
+            color = (0.14, 0.133, 0.15)
+        else:
+            color = (0.368, 0.305, 0.4)
+
+        grad.add_color_stop_rgba(stops[0], color[0], color[1], color[2], 0)
+        grad.add_color_stop_rgba(stops[1], color[0], color[1], color[2], 1)
+
+        # Setup Pango layout
+        layout = PangoCairo.create_layout(context)
+        layout.set_auto_dir(True)
+        layout.set_font_description(self._font_desc)
+        layout.set_width(rect.width * Pango.SCALE)
+
+        # Prevent lines from being wrapped
+        layout.set_ellipsize(Pango.EllipsizeMode.END)
+
+        # Draw text
+        layout.set_text(text, -1)
+        context.move_to(x_pos, (rect.height / 2) - 11)
+        PangoCairo.show_layout(context, layout)
+
+        # Draw gradient
+        context.rectangle(0, 0, rect.width, rect.height)
+        context.set_source(grad)
+        context.fill()
+
+    def set_selected(self, select):
+        self._selected = select
+
+    def release(self):
+        # Nothing to release
+        pass
diff --git a/pitivi/utils/ui.py b/pitivi/utils/ui.py
index 0afb07cc..ffdbb43d 100644
--- a/pitivi/utils/ui.py
+++ b/pitivi/utils/ui.py
@@ -210,13 +210,14 @@ EDITOR_PERSPECTIVE_CSS = """
     }
 
 
-    .VideoUriSource image {
+    .Thumbnail {
         transition: opacity 200ms linear;
         opacity: 1;
      }
 
-    .VideoUriSource:selected image,
-    .AudioUriSource:selected .AudioPreviewer {
+    .VideoPreviewer:selected,
+    .AudioPreviewer:selected,
+    .TitlePreviewer:selected {
         opacity: 0.15;
     }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]