[pitivi] Refactor GTK+ actions and keyboard shortcuts



commit 493c226870575e3775afc9c91672e990da5fb5bb
Author: Jean-FranÃois Fortin Tam <nekohayo gmail com>
Date:   Sat Jun 2 20:04:53 2012 -0400

    Refactor GTK+ actions and keyboard shortcuts
    
    Make the setActionsSensitive method simpler,
    actually use action groups as they were meant to be and
    remove cruft.
    
    This makes the code more robust and a lot simpler.

 pitivi/clipproperties.py    |    7 +--
 pitivi/effects.py           |    6 +--
 pitivi/mainwindow.py        |  102 +++++++++++++++++--------------------------
 pitivi/medialibrary.py      |    6 +--
 pitivi/timeline/timeline.py |   13 +++--
 pitivi/transitions.py       |    6 +--
 pitivi/viewer.py            |    8 +---
 7 files changed, 59 insertions(+), 89 deletions(-)
---
diff --git a/pitivi/clipproperties.py b/pitivi/clipproperties.py
index 26b4b89..79b7343 100644
--- a/pitivi/clipproperties.py
+++ b/pitivi/clipproperties.py
@@ -468,10 +468,10 @@ class EffectProperties(gtk.Expander, gtk.HBox):
 
     def _treeviewSelectionChangedCb(self, treeview):
         if self.selection.count_selected_rows() == 0 and self.timeline_objects:
-            self.app.gui.setActionsSensitive(['DeleteObj'], True)
+            self.app.gui.setActionsSensitive(True)
             self._removeEffectBt.set_sensitive(False)
         else:
-            self.app.gui.setActionsSensitive(['DeleteObj'], False)
+            self.app.gui.setActionsSensitive(False)
             self._removeEffectBt.set_sensitive(True)
 
         self._updateEffectConfigUi()
@@ -593,8 +593,7 @@ class TransformationProperties(gtk.Expander):
 
     def _getAndConnectToEffect(self, widget_name, property_name):
         spinbtn = self.builder.get_object(widget_name)
-        spinbtn.connect("output",
-                        self._onValueChangedCb, property_name)
+        spinbtn.connect("output", self._onValueChangedCb, property_name)
         self.spin_buttons[property_name] = spinbtn
         self.default_values[property_name] = spinbtn.get_value()
 
diff --git a/pitivi/effects.py b/pitivi/effects.py
index 16555c0..9809ed2 100644
--- a/pitivi/effects.py
+++ b/pitivi/effects.py
@@ -740,12 +740,10 @@ class EffectListWidget(gtk.VBox, Loggable):
         entry.set_text("")
 
     def searchEntryDesactvateCb(self, entry, event):
-        self.app.gui.setActionsSensitive("default", True)
-        self.app.gui.setActionsSensitive(['DeleteObj'], True)
+        self.app.gui.setActionsSensitive(True)
 
     def searchEntryActivateCb(self, entry, event):
-        self.app.gui.setActionsSensitive("default", False)
-        self.app.gui.setActionsSensitive(['DeleteObj'], False)
+        self.app.gui.setActionsSensitive(False)
 
     def _setRowVisible(self, model, iter, data):
         if self.effectType.get_active() == model.get_value(iter, COL_EFFECT_TYPE):
diff --git a/pitivi/mainwindow.py b/pitivi/mainwindow.py
index 3a0433f..0128f0a 100644
--- a/pitivi/mainwindow.py
+++ b/pitivi/mainwindow.py
@@ -183,9 +183,6 @@ class PitiviMainWindow(gtk.Window, Loggable):
         Loggable.__init__(self, "mainwindow")
         self.app = instance
         self.log("Creating MainWindow")
-        self.actions = None
-        self.toggleactions = None
-        self.actiongroup = None
         self.settings = instance.settings
         self.is_fullscreen = False
         self.prefsdialog = None
@@ -251,7 +248,7 @@ class PitiviMainWindow(gtk.Window, Loggable):
         #
         # name (required), stock ID, translatable label,
         # keyboard shortcut, translatable tooltip, callback function
-        self.actions = [
+        actions = [
             # In some cases we manually specify the translatable label,
             # because we want to have the "..." at the end, indicating
             # an action that requires "further interaction" from the user.
@@ -306,7 +303,7 @@ class PitiviMainWindow(gtk.Window, Loggable):
             ("Help", None, _("_Help")),
         ]
 
-        self.toggleactions = [
+        toggleactions = [
             ("FullScreen", gtk.STOCK_FULLSCREEN, None,
             "F11", _("View the main window on the whole screen"), self._fullScreenCb),
 
@@ -318,49 +315,41 @@ class PitiviMainWindow(gtk.Window, Loggable):
                 self.settings.mainWindowShowTimelineToolbar),
         ]
 
-        self.actiongroup = gtk.ActionGroup("mainwindow")
-        self.actiongroup.add_actions(self.actions)
-        self.actiongroup.add_toggle_actions(self.toggleactions)
+        self.main_actions = gtk.ActionGroup("mainwindow")
+        self.main_actions.add_actions(actions)
         self.undock_action = gtk.Action("WindowizeViewer", _("Undock Viewer"),
             _("Put the viewer in a separate window"), None)
-        self.actiongroup.add_action(self.undock_action)
+        self.main_actions.add_action(self.undock_action)
+        self.toggle_actions = gtk.ActionGroup("mainwindowtoggles")
+        self.toggle_actions.add_toggle_actions(toggleactions)
 
-        for action in self.actiongroup.list_actions():
+        important_actions = ("Undo", "SaveProject", "RenderProject")
+        for action in self.main_actions.list_actions():
             action_name = action.get_name()
+            if action_name in important_actions:
+                # Force showing a label alongside the action's toolbar button
+                action.props.is_important = True
             if action_name == "RenderProject":
                 # the button is set sensitive when the timeline duration changes
                 action.set_sensitive(False)
-                action.props.is_important = True
                 self.render_button = action
-            elif action_name in ["NewProject", "SaveProjectAs", "OpenProject"]:
-                if instance.settings.fileSupportEnabled:
-                    action.set_sensitive(True)
-            elif action_name == "SaveProject":
-                action.props.is_important = True
+            elif action_name in ["NewProject", "SaveProject", "SaveProjectAs", "OpenProject"]:
                 if instance.settings.fileSupportEnabled:
                     action.set_sensitive(True)
-                else:
-                    action.set_sensitive(False)
-            elif action_name == "Undo":
-                action.set_sensitive(True)
-                action.props.is_important = True
             elif action_name in [
                 "File", "Edit", "View", "Help",
-                "About", "Quit", "ImportSourcesFolder",
-                "FullScreen", "UserManual",
-                "ShowHideMainToolbar", "ShowHideTimelineToolbar",
-                "FrameForward", "FrameBackward",
-                "SecondForward", "SecondBackward",
-                "EdgeForward", "EdgeBackward",
+                "UserManual", "About", "Quit", "ImportSourcesFolder",
                 "Preferences", "Project", "ProjectSettings",
                 "Library", "Timeline", "Viewer", "WindowizeViewer"]:
                 action.set_sensitive(True)
             else:
                 action.set_sensitive(False)
+                self.log("%s has been made insensitive" % action_name)
 
         self.uimanager = gtk.UIManager()
         self.add_accel_group(self.uimanager.get_accel_group())
-        self.uimanager.insert_action_group(self.actiongroup, 0)
+        self.uimanager.insert_action_group(self.main_actions, 0)
+        self.uimanager.insert_action_group(self.toggle_actions, -1)
         self.uimanager.add_ui_from_file(os.path.join(get_ui_dir(), "mainwindow.xml"))
 
     def _createUi(self, instance, allow_full_screen):
@@ -464,14 +453,6 @@ class PitiviMainWindow(gtk.Window, Loggable):
         if not self.settings.mainWindowShowTimelineToolbar:
             ttb.props.visible = False
 
-        # Actions with key accelerators that will be made unsensitive while
-        # a gtk entry box is used to avoid conflicts.
-        self.sensitive_actions = []
-        for action in self.timeline_ui.playhead_actions:
-            self.sensitive_actions.append(action[0])
-        for action in self.toggleactions:
-            self.sensitive_actions.append(action[0])
-
         #application icon
         self.set_icon_name("pitivi")
 
@@ -507,30 +488,27 @@ class PitiviMainWindow(gtk.Window, Loggable):
             self.unfullscreen()
         self.is_fullscreen = fullscreen
 
-    #TODO check if it is the way to go
-    def setActionsSensitive(self, action_names, sensitive):
+    def setActionsSensitive(self, sensitive):
         """
         Grab (or release) keyboard letter keys focus/sensitivity
         for operations such as typing text in an entry.
 
-        @param action_names: The name of actions we want to set to (in)sensitive
-                             If set to "default", we use the default actions.
-        @type action_names: A {list} of action names
-        @param sensitive: %True if actions must be sensitive False otherwise
-        @type action_names: C{Bool}
-        """
-        if action_names == "default":
-            action_names = self.sensitive_actions
-
-        for action in self.actiongroup.list_actions():
-            if action.get_name() in action_names:
-                action.set_sensitive(sensitive)
+        This toggles the sensitivity of all actiongroups that might interfere.
+        This means mostly the timeline's actions.
 
+        This method does not need to be called when creating a separate window.
+        """
+        self.log("Setting actions sensitivity to %s" % sensitive)
+        # The mainwindow's actions don't prevent typing into entry widgets;
+        # Only timeline actions (ex: deleting and play/pause) are dangerous.
         if self.timeline_ui:
-            for action_group in self.timeline_ui.ui_manager.get_action_groups():
-                for action in action_group.list_actions():
-                    if action.get_name() in action_names:
-                        action.set_sensitive(sensitive)
+            # Don't loop in self.timeline_ui.ui_manager.get_action_groups()
+            # otherwise you'll get all the action groups of the application.
+            self.timeline_ui.playhead_actions.set_sensitive(sensitive)
+            selected = self.timeline_ui.timeline.selection.getSelectedTrackObjs()
+            if not sensitive or (sensitive and selected):
+                self.log("Setting timeline selection actions sensitivity to %s" % sensitive)
+                self.timeline_ui.selection_actions.set_sensitive(sensitive)
 
 ## Missing Plugin Support
 
@@ -561,8 +539,8 @@ class PitiviMainWindow(gtk.Window, Loggable):
         self.settings.mainWindowHPanePosition = self.hpaned.get_position()
         self.settings.mainWindowMainHPanePosition = self.mainhpaned.get_position()
         self.settings.mainWindowVPanePosition = self.vpaned.get_position()
-        mtb = self.actiongroup.get_action("ShowHideMainToolbar")
-        ttb = self.actiongroup.get_action("ShowHideTimelineToolbar")
+        mtb = self.toggle_actions.get_action("ShowHideMainToolbar")
+        ttb = self.toggle_actions.get_action("ShowHideTimelineToolbar")
         self.settings.mainWindowShowMainToolbar = mtb.props.active
         self.settings.mainWindowShowTimelineToolbar = ttb.props.active
 
@@ -757,11 +735,11 @@ class PitiviMainWindow(gtk.Window, Loggable):
         #self._syncDoUndo(self.app.action_log)
 
         # Enable export functionality
-        self.actiongroup.get_action("ExportProject").set_sensitive(True)
+        self.main_actions.get_action("ExportProject").set_sensitive(True)
 
         if self._missingUriOnLoading:
             self.app.current.setModificationState(True)
-            self.actiongroup.get_action("SaveProject").set_sensitive(True)
+            self.main_actions.get_action("SaveProject").set_sensitive(True)
             self._missingUriOnLoading = False
 
         if self.app.current.timeline.props.duration != 0:
@@ -1013,19 +991,19 @@ class PitiviMainWindow(gtk.Window, Loggable):
         self._syncDoUndo(action_log)
 
     def _syncDoUndo(self, action_log):
-        undo_action = self.actiongroup.get_action("Undo")
+        undo_action = self.main_actions.get_action("Undo")
         can_undo = bool(action_log.undo_stacks)
         undo_action.set_sensitive(can_undo)
 
         dirty = action_log.dirty()
-        save_action = self.actiongroup.get_action("SaveProject")
+        save_action = self.main_actions.get_action("SaveProject")
         save_action.set_sensitive(dirty)
         if self.app.current.uri is not None:
-            revert_action = self.actiongroup.get_action("RevertToSavedProject")
+            revert_action = self.main_actions.get_action("RevertToSavedProject")
             revert_action.set_sensitive(dirty)
         self.app.current.setModificationState(dirty)
 
-        redo_action = self.actiongroup.get_action("Redo")
+        redo_action = self.main_actions.get_action("Redo")
         can_redo = bool(action_log.redo_stacks)
         redo_action.set_sensitive(can_redo)
         self.updateTitle()
diff --git a/pitivi/medialibrary.py b/pitivi/medialibrary.py
index ca66f3c..a279e53 100644
--- a/pitivi/medialibrary.py
+++ b/pitivi/medialibrary.py
@@ -565,16 +565,14 @@ class MediaLibraryWidget(gtk.VBox, Loggable):
 
         This is used when focusing the search entry, icon on tree view widgets.
         """
-        self.app.gui.setActionsSensitive("default", False)
-        self.app.gui.setActionsSensitive(['DeleteObj'], False)
+        self.app.gui.setActionsSensitive(False)
 
     def _enableKeyboardShortcutsCb(self, *unused_args):
         """
         When focusing out of media library widgets,
         re-enable the timeline keyboard shortcuts.
         """
-        self.app.gui.setActionsSensitive("default", True)
-        self.app.gui.setActionsSensitive(['DeleteObj'], True)
+        self.app.gui.setActionsSensitive(True)
 
     def _trackObjectAddedCb(self, source, trackobj):
         """ After an object has been added to the first track, position it
diff --git a/pitivi/timeline/timeline.py b/pitivi/timeline/timeline.py
index 2542330..4deac36 100644
--- a/pitivi/timeline/timeline.py
+++ b/pitivi/timeline/timeline.py
@@ -732,7 +732,7 @@ class Timeline(gtk.Table, Loggable, Zoomable):
             "<Shift><Control>A", ALIGN, self.alignSelected),
         )
 
-        self.playhead_actions = (
+        playhead_actions = (
             ("PlayPause", gtk.STOCK_MEDIA_PLAY, None,
             "space", _("Start Playback"), self.playPause),
 
@@ -753,11 +753,14 @@ class Timeline(gtk.Table, Loggable, Zoomable):
         actiongroup.add_actions(actions)
         self.ui_manager.insert_action_group(actiongroup, 0)
 
-        actiongroup = gtk.ActionGroup("timelineselection")
-        actiongroup.add_actions(selection_actions)
-        actiongroup.add_actions(self.playhead_actions)
+        self.selection_actions = gtk.ActionGroup("timelineselection")
+        self.selection_actions.add_actions(selection_actions)
+        self.selection_actions.set_sensitive(False)
+        self.ui_manager.insert_action_group(self.selection_actions, -1)
+        self.playhead_actions = gtk.ActionGroup("timelineplayhead")
+        self.playhead_actions.add_actions(playhead_actions)
+        self.ui_manager.insert_action_group(self.playhead_actions, -1)
 
-        self.ui_manager.insert_action_group(actiongroup, -1)
         self.ui_manager.add_ui_from_string(ui)
 
         # drag and drop
diff --git a/pitivi/transitions.py b/pitivi/transitions.py
index 0ac6879..43f43e1 100644
--- a/pitivi/transitions.py
+++ b/pitivi/transitions.py
@@ -211,12 +211,10 @@ class TransitionsListWidget(Signallable, gtk.VBox, Loggable):
         entry.set_text("")
 
     def _searchEntryDeactivateCb(self, entry, event):
-        self.app.gui.setActionsSensitive("default", True)
-        self.app.gui.setActionsSensitive(['DeleteObj'], True)
+        self.app.gui.setActionsSensitive(True)
 
     def _searchEntryActivateCb(self, entry, event):
-        self.app.gui.setActionsSensitive("default", False)
-        self.app.gui.setActionsSensitive(['DeleteObj'], False)
+        self.app.gui.setActionsSensitive(False)
 
 # GES callbacks
 
diff --git a/pitivi/viewer.py b/pitivi/viewer.py
index 15d8bc3..f1b958f 100644
--- a/pitivi/viewer.py
+++ b/pitivi/viewer.py
@@ -266,14 +266,10 @@ class PitiviViewer(gtk.VBox, Loggable):
             self.warning("could not set ratio !")
 
     def _entryFocusInCb(self, entry, event):
-        sensitive_actions = self.app.gui.sensitive_actions
-        self.app.gui.setActionsSensitive(sensitive_actions, False)
-        self.app.gui.setActionsSensitive(['DeleteObj'], False)
+        self.app.gui.setActionsSensitive(False)
 
     def _entryFocusOutCb(self, entry, event):
-        sensitive_actions = self.app.gui.sensitive_actions
-        self.app.gui.setActionsSensitive(sensitive_actions, True)
-        self.app.gui.setActionsSensitive(['DeleteObj'], True)
+        self.app.gui.setActionsSensitive(True)
 
     ## active Timeline calllbacks
     def _durationChangedCb(self, unused_pipeline, duration):



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