[pitivi] effects: Use an inline toolbar for searching and categories
- From: Jean-FranÃois Fortin Tam <jfft src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] effects: Use an inline toolbar for searching and categories
- Date: Wed, 5 Sep 2012 03:06:57 +0000 (UTC)
commit 67aba117a801b69328704d48d813d540b3b3f989
Author: Jean-FranÃois Fortin Tam <nekohayo gmail com>
Date: Sun Sep 2 18:44:18 2012 -0400
effects: Use an inline toolbar for searching and categories
Port the filtering widgets to GtkBuilder and refactor the code.
data/ui/effectslibrary.ui | 94 ++++++++++++++++++++++++++
pitivi/effects.py | 162 ++++++++++++++++++++-------------------------
pitivi/titleeditor.py | 2 -
3 files changed, 165 insertions(+), 93 deletions(-)
---
diff --git a/data/ui/effectslibrary.ui b/data/ui/effectslibrary.ui
new file mode 100644
index 0000000..693d0c4
--- /dev/null
+++ b/data/ui/effectslibrary.ui
@@ -0,0 +1,94 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<interface>
+ <!-- interface-requires gtk+ 3.4 -->
+ <object class="GtkToolbar" id="effectslibrary_toolbar">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="show_arrow">False</property>
+ <property name="icon_size">1</property>
+ <child>
+ <object class="GtkToggleToolButton" id="video_togglebutton">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Show video effects</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">video-x-generic</property>
+ <property name="active">True</property>
+ <signal name="toggled" handler="_toggleViewTypeCb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToggleToolButton" id="audio_togglebutton">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="tooltip_text" translatable="yes">Show audio effects</property>
+ <property name="use_action_appearance">False</property>
+ <property name="use_underline">True</property>
+ <property name="icon_name">audio-x-generic</property>
+ <signal name="toggled" handler="_toggleViewTypeCb" swapped="no"/>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem" id="toolbutton1">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">False</property>
+ <child>
+ <object class="GtkComboBoxText" id="categories">
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="entry_text_column">0</property>
+ <property name="id_column">1</property>
+ <signal name="changed" handler="_categoryChangedCb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">False</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ <child>
+ <object class="GtkToolItem" id="toolbutton7">
+ <property name="use_action_appearance">False</property>
+ <property name="visible">True</property>
+ <property name="can_focus">False</property>
+ <property name="use_action_appearance">False</property>
+ <child>
+ <object class="GtkEntry" id="search_entry">
+ <property name="visible">True</property>
+ <property name="can_focus">True</property>
+ <property name="has_tooltip">True</property>
+ <property name="margin_left">3</property>
+ <property name="invisible_char">â</property>
+ <property name="invisible_char_set">True</property>
+ <property name="secondary_icon_name">edit-clear-symbolic</property>
+ <property name="secondary_icon_tooltip_text" translatable="yes">Clear the current search</property>
+ <property name="secondary_icon_tooltip_markup" translatable="yes">Clear the current search</property>
+ <property name="placeholder_text">Search...</property>
+ <signal name="changed" handler="_searchEntryChangedCb" swapped="no"/>
+ <signal name="focus-in-event" handler="_searchEntryFocusedCb" swapped="no"/>
+ <signal name="focus-out-event" handler="_searchEntryDefocusedCb" swapped="no"/>
+ <signal name="icon-release" handler="_searchEntryIconClickedCb" swapped="no"/>
+ </object>
+ </child>
+ </object>
+ <packing>
+ <property name="expand">True</property>
+ <property name="homogeneous">True</property>
+ </packing>
+ </child>
+ </object>
+</interface>
diff --git a/pitivi/effects.py b/pitivi/effects.py
index b6a6a93..264653d 100644
--- a/pitivi/effects.py
+++ b/pitivi/effects.py
@@ -48,7 +48,7 @@ from gi.repository import GdkPixbuf
from gettext import gettext as _
-from pitivi.configure import get_pixmap_dir
+from pitivi.configure import get_ui_dir, get_pixmap_dir
from pitivi.settings import GlobalSettings
import pitivi.utils.ui as dnd
@@ -217,8 +217,7 @@ class EffectsHandler(object):
"""
@ivar effect_name: the name of the effect for wich we want the category
@type effect_name: L{str}
- @returns: A C{list} of name C{str} of categories corresponding the
- effect
+ @returns: A C{list} of name C{str} of categories corresponding the effect
"""
categories = []
@@ -262,8 +261,7 @@ class EffectsHandler(object):
def getVideoCategories(self, aware=True):
"""
- @ivar aware: C{True} if you want it to return only categories on
- whichs
+ @ivar aware: C{True} if you want it to return only categories on which
there are effects on the system, else C{False}
@type aware: C{bool}
@returns: All video effect categories names C{str} that are available
@@ -313,8 +311,7 @@ class EffectsHandler(object):
effect_name = effect_name + ".png"
icon = None
try:
- icon = GdkPixbuf.Pixbuf.new_from_file(os.path.join(self._pixdir,
- effect_name))
+ icon = GdkPixbuf.Pixbuf.new_from_file(os.path.join(self._pixdir, effect_name))
# empty except clause is bad but load_icon raises Gio.Error.
## Right, *gio*.
except:
@@ -340,9 +337,6 @@ GlobalSettings.addConfigSection('effect-library')
COL_ELEMENT_NAME,
COL_ICON) = range(7)
-INVISIBLE = GdkPixbuf.Pixbuf.new_from_file(os.path.join(get_pixmap_dir(),
- "invisible.png"))
-
class EffectListWidget(Gtk.VBox, Loggable):
""" Widget for listing effects """
@@ -352,48 +346,33 @@ class EffectListWidget(Gtk.VBox, Loggable):
Loggable.__init__(self)
self.app = instance
- self.settings = instance.settings
self._draggedItems = None
-
- #Searchbox and combobox
- hfilters = Gtk.HBox()
- hfilters.set_spacing(SPACING)
- hfilters.set_border_width(3) # Prevents being flush against the notebook
- self.effectType = Gtk.ComboBoxText()
- self.effectType.append_text(_("Video effects"))
- self.effectType.append_text(_("Audio effects"))
- self.effectCategory = Gtk.ComboBoxText()
- self.effectType.set_active(VIDEO_EFFECT)
-
- hfilters.pack_start(self.effectType, True, True, 0)
- hfilters.pack_end(self.effectCategory, True, True, 0)
-
- hsearch = Gtk.HBox()
- hsearch.set_spacing(SPACING)
- hsearch.set_border_width(3) # Prevents being flush against the notebook
- searchStr = Gtk.Label(label=_("Search:"))
- self.searchEntry = Gtk.Entry()
- self.searchEntry.set_icon_from_stock(Gtk.EntryIconPosition.SECONDARY, "gtk-clear")
- hsearch.pack_start(searchStr, False, True, 0)
- hsearch.pack_end(self.searchEntry, True, True, 0)
+ self._effectType = VIDEO_EFFECT
+
+ builder = Gtk.Builder()
+ builder.add_from_file(os.path.join(get_ui_dir(), "effectslibrary.ui"))
+ builder.connect_signals(self)
+ toolbar = builder.get_object("effectslibrary_toolbar")
+ toolbar.get_style_context().add_class("inline-toolbar")
+ self.video_togglebutton = builder.get_object("video_togglebutton")
+ self.audio_togglebutton = builder.get_object("audio_togglebutton")
+ self.categoriesWidget = builder.get_object("categories")
+ self.searchEntry = builder.get_object("search_entry")
# Store
self.storemodel = Gtk.ListStore(str, str, int, object, object, str, GdkPixbuf.Pixbuf)
- scrollwin = Gtk.ScrolledWindow()
- scrollwin.props.hscrollbar_policy = Gtk.PolicyType.NEVER
- scrollwin.props.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC
- scrollwin.props.shadow_type = Gtk.ShadowType.ETCHED_IN
-
self.view = Gtk.TreeView(self.storemodel)
- scrollwin.add(self.view)
self.view.props.headers_visible = False
- tsel = self.view.get_selection()
- tsel.set_mode(Gtk.SelectionMode.SINGLE)
+ self.view.get_selection().set_mode(Gtk.SelectionMode.SINGLE)
+
+ # Create the filterModel for searching the storemodel
+ self.modelFilter = self.storemodel.filter_new()
+ self.modelFilter.set_visible_func(self._setRowVisible, data=None)
+ self.view.set_model(self.modelFilter)
icon_col = Gtk.TreeViewColumn()
- self.view.append_column(icon_col)
icon_col.props.spacing = SPACING
icon_col.set_sizing(Gtk.TreeViewColumnSizing.FIXED)
icon_col.props.fixed_width = 96
@@ -403,7 +382,6 @@ class EffectListWidget(Gtk.VBox, Loggable):
icon_col.add_attribute(icon_cell, "pixbuf", COL_ICON)
text_col = Gtk.TreeViewColumn()
- self.view.append_column(text_col)
text_col.set_expand(True)
text_col.set_spacing(SPACING)
text_col.set_sizing(Gtk.TreeViewColumnSizing.AUTOSIZE)
@@ -413,49 +391,37 @@ class EffectListWidget(Gtk.VBox, Loggable):
text_cell.props.xpad = 6
text_cell.set_property("ellipsize", Pango.EllipsizeMode.END)
text_col.pack_start(text_cell, True)
- text_col.set_cell_data_func(text_cell,
- self.view_description_cell_data_func,
- None)
-
- self.effectType.connect("changed", self._effectTypeChangedCb)
+ text_col.set_cell_data_func(text_cell, self.view_description_cell_data_func, None)
- self.effectCategory.connect("changed", self._effectCategoryChangedCb)
-
- self.searchEntry.connect("changed", self.searchEntryChangedCb)
- self.searchEntry.connect("focus-in-event", self.searchEntryActivateCb)
- self.searchEntry.connect("focus-out-event", self.searchEntryDesactvateCb)
- self.searchEntry.connect("icon-press", self.searchEntryIconClickedCb)
-
- self.view.connect("button-press-event", self._buttonPressEventCb)
- self.view.connect("select-cursor-row", self._enterPressEventCb)
+ self.view.append_column(icon_col)
+ self.view.append_column(text_col)
self.view.drag_source_set(0, [], Gdk.DragAction.COPY)
self.view.enable_model_drag_source(Gdk.ModifierType.BUTTON1_MASK, [("pitivi/effect", 0, TYPE_PITIVI_EFFECT)], Gdk.DragAction.COPY)
self.view.drag_source_set_target_list(None)
self.view.drag_source_add_text_targets()
+ self.view.connect("button-press-event", self._buttonPressEventCb)
+ self.view.connect("select-cursor-row", self._enterPressEventCb)
self.view.connect("drag_begin", self._dndDragBeginCb)
+ scrollwin = Gtk.ScrolledWindow()
+ scrollwin.props.hscrollbar_policy = Gtk.PolicyType.NEVER
+ scrollwin.props.vscrollbar_policy = Gtk.PolicyType.AUTOMATIC
+ scrollwin.add(self.view)
+
+ self.pack_start(scrollwin, True, True, 0)
+ self.pack_end(toolbar, expand=False)
+
# Delay the loading of the available effects so the application
# starts faster.
GObject.idle_add(self._loadAvailableEffectsCb)
-
- self.pack_start(hfilters, False, True, 0)
- self.pack_start(hsearch, False, True, 0)
- self.pack_end(scrollwin, True, True, 0)
-
- #create the filterModel
- self.modelFilter = self.storemodel.filter_new()
- self.modelFilter.set_visible_func(self._setRowVisible, data=None)
- self.view.set_model(self.modelFilter)
-
- self.show_categories(VIDEO_EFFECT)
+ self.populate_categories_widget()
# Individually show the tab's widgets.
# If you use self.show_all(), the tab will steal focus on startup.
- hfilters.show_all()
- hsearch.show_all()
scrollwin.show_all()
+ toolbar.show_all()
@staticmethod
def view_description_cell_data_func(column, cell, model, iter_, data):
@@ -482,21 +448,20 @@ class EffectListWidget(Gtk.VBox, Loggable):
self.app.effects.getEffectIcon(name)])
self.storemodel.set_sort_column_id(COL_NAME_TEXT, Gtk.SortType.ASCENDING)
- def show_categories(self, effectType):
- self.effectCategory.get_model().clear()
- self._effect_type_ref = effectType
+ def populate_categories_widget(self):
+ self.categoriesWidget.get_model().clear()
icon_column = self.view.get_column(0)
- if effectType is VIDEO_EFFECT:
- for categorie in self.app.effects.video_categories:
- self.effectCategory.append_text(categorie)
+ if self._effectType is VIDEO_EFFECT:
+ for category in self.app.effects.video_categories:
+ self.categoriesWidget.append_text(category)
icon_column.props.visible = True
else:
- for categorie in self.app.effects.audio_categories:
- self.effectCategory.append_text(categorie)
+ for category in self.app.effects.audio_categories:
+ self.categoriesWidget.append_text(category)
icon_column.props.visible = False
- self.effectCategory.set_active(0)
+ self.categoriesWidget.set_active(0)
def _dndDragBeginCb(self, view, context):
self.info("tree drag_begin")
@@ -553,30 +518,45 @@ class EffectListWidget(Gtk.VBox, Loggable):
return self.storemodel[path][COL_ELEMENT_NAME]
- def _effectTypeChangedCb(self, combobox):
+ def _toggleViewTypeCb(self, widget):
+ """
+ Handle the switching of the view mode between video and audio.
+ This makes the two togglebuttons behave like a group of radiobuttons.
+ """
+ if widget is self.video_togglebutton:
+ self.audio_togglebutton.set_active(not widget.get_active())
+ else:
+ assert widget is self.audio_togglebutton
+ self.video_togglebutton.set_active(not widget.get_active())
+
+ if self.video_togglebutton.get_active():
+ self._effectType = VIDEO_EFFECT
+ else:
+ self._effectType = AUDIO_EFFECT
+
+ self.populate_categories_widget()
self.modelFilter.refilter()
- self.show_categories(combobox.get_active())
- def _effectCategoryChangedCb(self, combobox):
+ def _categoryChangedCb(self, combobox):
self.modelFilter.refilter()
- def searchEntryChangedCb(self, entry):
+ def _searchEntryChangedCb(self, entry):
self.modelFilter.refilter()
- def searchEntryIconClickedCb(self, entry, unused, unsed1):
+ def _searchEntryIconClickedCb(self, entry, unused, unused1):
entry.set_text("")
- def searchEntryDesactvateCb(self, entry, event):
- self.app.gui.setActionsSensitive(True)
-
- def searchEntryActivateCb(self, entry, event):
+ def _searchEntryFocusedCb(self, entry, event):
self.app.gui.setActionsSensitive(False)
+ def _searchEntryDefocusedCb(self, entry, event):
+ self.app.gui.setActionsSensitive(True)
+
def _setRowVisible(self, model, iter, data):
- if self.effectType.get_active() == model.get_value(iter, COL_EFFECT_TYPE):
+ if self._effectType == model.get_value(iter, COL_EFFECT_TYPE):
if model.get_value(iter, COL_EFFECT_CATEGORIES) is None:
return False
- if self.effectCategory.get_active_text() in model.get_value(iter, COL_EFFECT_CATEGORIES):
+ if self.categoriesWidget.get_active_text() in model.get_value(iter, COL_EFFECT_CATEGORIES):
text = self.searchEntry.get_text().lower()
return text in model.get_value(iter, COL_DESC_TEXT).lower() or\
text in model.get_value(iter, COL_NAME_TEXT).lower()
@@ -589,7 +569,7 @@ class EffectListWidget(Gtk.VBox, Loggable):
return not bool(view.get_path_at_pos(int(event.x), int(event.y)))
def _getTargetEntries(self):
- if self.effectType.get_active() == VIDEO_EFFECT:
+ if self._effectType == VIDEO_EFFECT:
return [dnd.VIDEO_EFFECT_TARGET_ENTRY, dnd.EFFECT_TARGET_ENTRY]
else:
return [dnd.AUDIO_EFFECT_TARGET_ENTRY, dnd.EFFECT_TARGET_ENTRY]
diff --git a/pitivi/titleeditor.py b/pitivi/titleeditor.py
index 8fdc000..a0227cf 100644
--- a/pitivi/titleeditor.py
+++ b/pitivi/titleeditor.py
@@ -30,7 +30,6 @@ from gi.repository import Pango
from gi.repository import GES
from gi.repository import Gst
from gi.repository import GObject
-from gi.repository import GdkPixbuf
from gettext import gettext as _
from xml.sax import saxutils
@@ -40,7 +39,6 @@ from pitivi.configure import get_ui_dir, get_pixmap_dir
from pitivi.utils.loggable import Loggable
from pitivi.utils.signal import Signallable
from pitivi.utils.pipeline import Seeker
-INVISIBLE = GdkPixbuf.Pixbuf.new_from_file(os.path.join(get_pixmap_dir(), "invisible.png"))
# FIXME Fix Pango so we do NOT need that dirty reimplementation
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]