[pitivi] Add the clip configuration pane



commit d4db6686bedeca5b14051490894550d5f390f369
Author: Thibault Saunier <tsaunier gnome org>
Date:   Tue Jun 29 23:33:36 2010 -0400

    Add the clip configuration pane

 pitivi/timeline/timeline.py               |   11 +
 pitivi/ui/{projecttabs.py => basetabs.py} |    6 +-
 pitivi/ui/clipproperties.py               |  284 +++++++++++++++++++++++++++++
 pitivi/ui/mainwindow.py                   |   32 +++-
 4 files changed, 323 insertions(+), 10 deletions(-)
---
diff --git a/pitivi/timeline/timeline.py b/pitivi/timeline/timeline.py
index 89e096f..e5d95a8 100644
--- a/pitivi/timeline/timeline.py
+++ b/pitivi/timeline/timeline.py
@@ -531,6 +531,17 @@ class Selection(Signallable):
 
         return set(objects)
 
+    def getSelectedTrackEffects(self):
+        """
+        Returns the list of L{TrackObject} contained in this selection.
+        """
+        track_effects = []
+        for timeline_object in self.selected:
+            for track in timeline_object.track_objects:
+                if isinstance(track, TrackEffect):
+                    track_effects.append(track)
+
+        return set(track_effects)
 
     def __len__(self):
         return len(self.selected)
diff --git a/pitivi/ui/projecttabs.py b/pitivi/ui/basetabs.py
similarity index 95%
rename from pitivi/ui/projecttabs.py
rename to pitivi/ui/basetabs.py
index 8113656..ffa7430 100644
--- a/pitivi/ui/projecttabs.py
+++ b/pitivi/ui/basetabs.py
@@ -1,6 +1,6 @@
 # PiTiVi , Non-linear video editor
 #
-#       ui/projecttabs.py
+#       ui/basetabs.py
 #
 # Copyright (c) 2005, Edward Hervey <bilboed bilboed com>
 #
@@ -21,7 +21,7 @@
 
 import gtk
 
-class ProjectTabs(gtk.Notebook):
+class BaseTabs(gtk.Notebook):
     def __init__(self):
         """ initialize """
         gtk.Notebook.__init__(self)
@@ -42,7 +42,7 @@ class ProjectTabs(gtk.Notebook):
 
     def _set_child_properties(self, child, label):
         self.child_set_property(child, "detachable", True)
-        self.child_set_property(child, "tab-expand", True)
+        self.child_set_property(child, "tab-expand", False)
         self.child_set_property(child, "tab-fill", True)
         label.props.xalign = 0.0
 
diff --git a/pitivi/ui/clipproperties.py b/pitivi/ui/clipproperties.py
new file mode 100644
index 0000000..fd7235b
--- /dev/null
+++ b/pitivi/ui/clipproperties.py
@@ -0,0 +1,284 @@
+#!/usr/bin/env python
+#
+#       ui/clipproperties.py
+#
+# Copyright (C) 2010 Thibault Saunier <tsaunier gnome org>
+# 
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Lesser General Public
+# License as published by the Free Software Foundation; either
+# version 2.1 of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+# Lesser General Public License for more details.
+#
+# You should have received a copy of the GNU Lesser General Public
+# License along with this program; if not, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 02111-1307, USA.
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3, or (at your option)
+# any later version.
+
+import gtk
+import pango
+import dnd
+
+from gettext import gettext as _
+
+from pitivi.log.loggable import Loggable
+from pitivi.effects import AUDIO_EFFECT, VIDEO_EFFECT
+from pitivi.receiver import receiver, handler
+from pitivi.timeline.track import TrackEffect
+from pitivi.stream import AudioStream, VideoStream
+from pitivi.effects import getNiceEffectName, getNiceEffectDescription
+
+(COL_ACTIVATED,
+ COL_TYPE,
+ COL_NAME_TEXT,
+ COL_DESC_TEXT) = range(4)
+
+class ClipProperties(gtk.VBox, Loggable):
+    """
+    Widget for configuring clips properties
+    """
+
+    def __init__(self, instance, uiman):
+        gtk.VBox.__init__(self)
+        Loggable.__init__(self)
+
+        self.app = instance
+        self.settings = instance.settings
+        self.project = None
+
+        self.effectExpander = EffectProperties(instance)
+        self.pack_start(self.effectExpander, expand=True, fill=True)
+
+        self.effectExpander.show()
+
+    def _setProject(self):
+        if self.project:
+            self.effectExpander.connectTimelineSelection(self.project.timeline)
+
+    project = receiver(_setProject)
+
+class EffectProperties(gtk.Expander):
+    """
+    Widget for viewing and configuring effects
+    """
+
+    def __init__(self, instance):
+        gtk.Expander.__init__(self, "Effects")
+        self.set_expanded(True)
+
+        self.selected_effects = []
+        self.timeline_object = None
+        self.app = instance
+
+        self.VContent = gtk.VBox()
+        self.add(self.VContent)
+
+        self.table = gtk.Table(2, 1, False)
+        self.VContent.pack_start(self.table, expand=False, fill=True)
+
+        self.toolbar1 = gtk.Toolbar()
+        self.removeEffectBt = gtk.ToolButton("gtk-delete")
+        self.removeEffectBt.set_label("Remove effect")
+        self.removeEffectBt.set_use_underline(True)
+        self.removeEffectBt.set_is_important(True)
+        self.toolbar1.insert(self.removeEffectBt, 0)
+        self.table.attach(self.toolbar1, 0, 1, 0, 1)
+
+        #self.toolbar2 = gtk.Toolbar()
+        ##self.toolbar2.set_style(gtk.TOOLBAR_BOTH_HORIZ)
+        #self.removeKeyframeBt = gtk.ToolButton("gtk-remove")
+        #self.removeKeyframeBt.set_label("Remove keyframe")
+        #self.removeKeyframeBt.set_use_underline(True)
+        #self.removeKeyframeBt.set_is_important(True)
+        #self.toolbar2.insert(self.removeKeyframeBt, 0)
+        #self.table.attach(self.toolbar2, 1, 2, 0, 1)
+
+        self.storemodel = gtk.ListStore(bool, str, str, str)
+
+        #Treeview
+        self.treeview_scrollwin = gtk.ScrolledWindow()
+        self.treeview_scrollwin.set_policy(gtk.POLICY_NEVER, gtk.POLICY_AUTOMATIC)
+        self.treeview_scrollwin.set_shadow_type(gtk.SHADOW_ETCHED_IN)
+
+        # TreeView
+        # Displays name, description
+        self.treeview = gtk.TreeView(self.storemodel)
+        self.treeview_scrollwin.add(self.treeview)
+        self.treeview.set_property("rules_hint", True)
+        self.treeview.set_property("has_tooltip", True)
+        tsel = self.treeview.get_selection()
+        tsel.set_mode(gtk.SELECTION_SINGLE)
+
+        activatedcol = gtk.TreeViewColumn(_("Activated"))
+        activatedcol.set_sort_column_id(COL_TYPE)
+        self.treeview.append_column(activatedcol)
+        activatedcol.set_spacing(5)
+        activatedcol.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
+        activatedcol.set_min_width(15)
+        activatedcell = gtk.CellRendererToggle()
+        activatedcell.props.xpad = 6
+        activatedcol.pack_start(activatedcell)
+
+        activatedcell.connect("toggled",  self.effectActiveToggleCb)
+
+        desccol = gtk.TreeViewColumn(_("Type"))
+        desccol.set_sort_column_id(COL_TYPE)
+        self.treeview.append_column(desccol)
+        desccol.set_spacing(5)
+        desccol.set_sizing(gtk.TREE_VIEW_COLUMN_AUTOSIZE)
+        desccol.set_min_width(50)
+        desccell = gtk.CellRendererText()
+        desccell.props.xpad = 6
+        desccell.set_property("ellipsize", pango.ELLIPSIZE_END)
+        desccol.pack_start(desccell)
+        desccol.add_attribute(desccell, "text", COL_TYPE)
+
+        namecol = gtk.TreeViewColumn(_("Effect name"))
+        namecol.set_sort_column_id(COL_NAME_TEXT)
+        self.treeview.append_column(namecol)
+        namecol.set_spacing(5)
+        #namecol.set_sizing(gtk.TREE_VIEW_COLUMN_FIXED)
+        #namecol.set_fixed_width(40)
+        namecell = gtk.CellRendererText()
+        namecell.props.xpad = 6
+        namecell.set_property("ellipsize", pango.ELLIPSIZE_END)
+        namecol.pack_start(namecell)
+        namecol.add_attribute(namecell, "text", COL_NAME_TEXT)
+
+        #Explain how to configure effects
+        self.explain_box = gtk.EventBox()
+        self.explain_box.modify_bg(gtk.STATE_NORMAL, gtk.gdk.color_parse('white'))
+
+        self.explain_label = gtk.Label()
+        self.explain_label.set_padding(10, 10)
+        self.explain_label.set_line_wrap(True)
+        self.explain_label.set_line_wrap_mode(pango.WRAP_WORD)
+        self.explain_label.set_justify(gtk.JUSTIFY_CENTER)
+        self.explain_label.set_markup(
+            _("<span size='x-large'>You must select a clip on the timeline "
+              "to configure its associated effects</span>"))
+        self.explain_box.add(self.explain_label)
+
+        self.treeview.drag_dest_set(gtk.DEST_DEFAULT_MOTION,
+            [dnd.EFFECT_TUPLE],
+            gtk.gdk.ACTION_COPY)
+
+        self.treeview.connect("drag-data-received", self._dragDataReceivedCb)
+        self.treeview.connect("drag-leave", self._dragLeaveCb)
+        self.treeview.connect("drag-drop", self._dragDropCb)
+        self.treeview.connect("drag-motion", self._dragMotionCb)
+        self.treeview.connect("query-tooltip",
+                              self._treeViewQueryTooltipCb)
+
+        self.connect('notify::expanded', self.expandedcb)
+
+        self.table.attach(self.treeview_scrollwin, 0, 1, 1, 2)
+        self.VContent.pack_start(self.explain_box, expand=True, fill=True)
+
+        self._showExplainLabel()
+        self.VContent.show()
+
+    timeline = receiver()
+
+    @handler(timeline, "selection-changed")
+    def selectionChangedCb(self, timeline):
+        self.selected_effects = timeline.selection.getSelectedTrackEffects()
+        if timeline.selection.selected:
+            self.timeline_object = list(timeline.selection.selected)[0]
+        else:
+            self.timeline_object = None
+        print self.timeline_object
+        self._updateAll()
+
+    timeline_object = receiver()
+
+    @handler(timeline_object, "track-object-added")
+    def  trackAddedCb(self, unused_timeline_object, track_object):
+        if isinstance (track_object, TrackEffect):
+            self.selected_effects = self.timeline.selection.getSelectedTrackEffects()
+            print self.timeline.selection.getSelectedTrackEffects()
+            self._updateAll()
+
+    @handler(timeline_object, "track-object-removed")
+    def  trackAddedCb(self, track_object, unused):
+        if isinstance (track_object, TrackEffect):
+            self._updateAll()
+
+    def connectTimelineSelection(self, timeline):
+        self.timeline = timeline
+
+    def _dragDataReceivedCb(self, unused, context, x, y, timestamp):
+        print "Receive"
+
+    def _dragDropCb(self, unused, context, x, y, timestamp):
+        print "Drop"
+
+    def _dragLeaveCb(self, unused_layout, unused_context, unused_tstamp):
+        self.drag_unhighlight()
+
+    def _dragMotionCb(self, unused, context, x, y, timestamp):
+        self.drag_highlight()
+
+    def _timelineWatcherCb(self, timeline):
+        print timeline.selection
+
+    def effectActiveToggleCb(self, cellrenderertoggle, path):
+        cellrenderertoggle.set_active(not cellrenderertoggle.get_active())
+
+    def expandedcb(self, expander, params):
+        self._updateAll()
+
+    def _treeViewQueryTooltipCb(self, treeview, x, y, keyboard_mode, tooltip):
+        context = treeview.get_tooltip_context(x, y, keyboard_mode)
+
+        if context is None:
+            return False
+
+        treeview.set_tooltip_row (tooltip, context[1][0])
+        tooltip.set_text(self.storemodel.get_value(context[2], COL_DESC_TEXT))
+
+        return True
+
+    def _updateAll(self):
+        print "Updating"
+        if self.get_expanded():
+            if self.timeline_object:
+                self.table.show_all()
+                if not self.selected_effects:
+                    self.toolbar1.hide()
+                self.explain_box.hide()
+                self._updateTreeview()
+            else:
+                self.table.hide()
+                self._showExplainLabel()
+            self.VContent.show()
+        else:
+            self.VContent.hide()
+
+    def _updateTreeview(self):
+        self.storemodel.clear()
+        for effect in self.selected_effects:
+            to_append = [True]
+            if isinstance(effect.factory.getInputStreams()[0], VideoStream):
+                to_append.append("Video")
+                elem = self.app.effects.getElementFromFactoryName(effect.factory.name, VIDEO_EFFECT)
+            else:
+                to_append.append("Audio")
+                elem = self.app.effects.getElementFromFactoryName(effect.factory.name, AUDIO_EFFECT)
+
+            to_append.append(getNiceEffectName(elem))
+            to_append.append(getNiceEffectDescription(elem))
+
+            self.storemodel.append(to_append)
+
+    def _showExplainLabel(self):
+        self.explain_box.show()
+        self.explain_label.show()
diff --git a/pitivi/ui/mainwindow.py b/pitivi/ui/mainwindow.py
index 3b60d4d..c7d67f3 100644
--- a/pitivi/ui/mainwindow.py
+++ b/pitivi/ui/mainwindow.py
@@ -44,7 +44,7 @@ from gettext import gettext as _
 from pitivi.log.loggable import Loggable
 
 from pitivi.ui.timeline import Timeline
-from pitivi.ui.projecttabs import ProjectTabs
+from pitivi.ui.basetabs import BaseTabs
 from pitivi.ui.viewer import PitiviViewer
 from pitivi.configure import pitivi_version, APPNAME, get_pixmap_dir, \
      get_global_pixmap_dir, LIBDIR
@@ -57,6 +57,7 @@ import pitivi.formatters.format as formatter
 from pitivi.sourcelist import SourceListError
 from pitivi.ui.sourcelist import SourceList
 from pitivi.ui.effectlist import EffectList
+from pitivi.ui.clipproperties import ClipProperties
 from pitivi.ui.common import beautify_factory
 from pitivi.utils import beautify_length
 from pitivi.ui.zoominterface import Zoomable
@@ -396,12 +397,17 @@ class PitiviMainWindow(gtk.Window, Loggable):
         self.timeline = Timeline(instance, self.uimanager)
         self.timeline.project = self.project
 
-        vpaned.pack2(self.timeline, resize=False, shrink=False)
+        vpaned.pack2(self.timeline, resize=True, shrink=False)
         self.timeline.show()
+        hpanedprincipal = gtk.HPaned()
+        vpaned.pack1(hpanedprincipal, resize=True, shrink=False)
+
         hpaned = gtk.HPaned()
-        vpaned.pack1(hpaned, resize=True, shrink=False)
+        hpanedprincipal.pack1(hpaned, resize=True, shrink=False)
         hpaned.show()
-        self.projecttabs = ProjectTabs()
+        hpanedprincipal.show()
+
+        self.projecttabs = BaseTabs()
 
         self.sourcelist = SourceList(instance, self.uimanager)
         self.effectlist = EffectList(instance, self.uimanager)
@@ -414,6 +420,16 @@ class PitiviMainWindow(gtk.Window, Loggable):
         hpaned.pack1(self.projecttabs, resize=True, shrink=False)
         self.projecttabs.show()
 
+        #Clips properties
+        self.propertiestabs = BaseTabs()
+        self.clipconfig = ClipProperties(instance, self.uimanager)
+        self.clipconfig.project = self.project
+        self.propertiestabs.append_page(self.clipconfig, gtk.Label(_("Clip Properties")))
+        self.clipconfig.show()
+
+        hpaned.pack2(self.propertiestabs, resize= True, shrink=False)
+        self.propertiestabs.show()
+
         # Viewer
         self.viewer = PitiviViewer()
         # drag and drop
@@ -421,11 +437,12 @@ class PitiviMainWindow(gtk.Window, Loggable):
                            [dnd.FILESOURCE_TUPLE, dnd.URI_TUPLE],
                            gtk.gdk.ACTION_COPY)
         self.viewer.connect("drag_data_received", self._viewerDndDataReceivedCb)
-        hpaned.pack2(self.viewer, resize=False, shrink=False)
+        hpanedprincipal.pack2(self.viewer, resize=False, shrink=False)
         self.viewer.show()
         self.viewer.connect("expose-event", self._exposeEventCb)
 
         # window and pane position defaults
+        self.hpanedprincipal = hpanedprincipal
         self.hpaned = hpaned
         self.vpaned = vpaned
         height = -1
@@ -591,7 +608,7 @@ class PitiviMainWindow(gtk.Window, Loggable):
 
     def _revertToSavedProjectCb(self, unused_action):
         return self.app.projectManager.revertToSavedProject()
-            
+
 
     def _projectSettingsCb(self, unused_action):
         from projectsettings import ProjectSettingsDialog
@@ -851,7 +868,7 @@ class PitiviMainWindow(gtk.Window, Loggable):
             if response <> gtk.RESPONSE_YES:
                 return False
         return True
-        
+
 
     def _projectManagerNewProjectFailedCb(self, projectManager, uri, exception):
         # ungrey UI
@@ -965,6 +982,7 @@ class PitiviMainWindow(gtk.Window, Loggable):
             self.project_timeline = self.project.timeline
             if self.timeline:
                 self.timeline.project = self.project
+                self.clipconfig.project = self.project
 
     project = receiver(_setProject)
 



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