[pitivi: 55/65] Changed ProjectSettingsDialog to show an error message if a preset is renamed and the new name alrea



commit 36c71e75858a90047d0445a3c7d3ebb0df7431c4
Author: Alex BÄluÈ <alexandru balut gmail com>
Date:   Mon Jun 13 21:09:34 2011 +0200

    Changed ProjectSettingsDialog to show an error message if a preset is renamed and the new name already belongs to another preset.
    Fixes bug 638799.

 data/ui/projectsettings.ui   |   84 ++++++++++++++++++++++++++++++++++++++++--
 pitivi/ui/preset.py          |   17 ++++++++
 pitivi/ui/projectsettings.py |   56 +++++++++++++++++++++++++++-
 tests/test_preset.py         |   21 ++++++++++-
 4 files changed, 171 insertions(+), 7 deletions(-)
---
diff --git a/data/ui/projectsettings.ui b/data/ui/projectsettings.ui
index db6f730..e82662d 100644
--- a/data/ui/projectsettings.ui
+++ b/data/ui/projectsettings.ui
@@ -142,6 +142,44 @@
                       </packing>
                     </child>
                     <child>
+                      <object class="GtkInfoBar" id="video-preset-infobar">
+                        <property name="app_paintable">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="message_type">error</property>
+                        <child internal-child="content_area">
+                          <object class="GtkBox" id="infobar-content_area2">
+                            <property name="can_focus">False</property>
+                            <child>
+                              <object class="GtkLabel" id="video-preset-error-label">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                          </object>
+                        </child>
+                        <child internal-child="action_area">
+                          <object class="GtkButtonBox" id="infobar-action_area2">
+                            <property name="can_focus">False</property>
+                            <property name="orientation">vertical</property>
+                            <property name="layout_style">center</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
                       <object class="GtkScrolledWindow" id="scrolledwindow2">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
@@ -159,7 +197,7 @@
                       <packing>
                         <property name="expand">True</property>
                         <property name="fill">True</property>
-                        <property name="position">1</property>
+                        <property name="position">2</property>
                       </packing>
                     </child>
                     <child>
@@ -220,7 +258,7 @@
                       <packing>
                         <property name="expand">False</property>
                         <property name="fill">False</property>
-                        <property name="position">2</property>
+                        <property name="position">3</property>
                       </packing>
                     </child>
                   </object>
@@ -509,6 +547,44 @@
                       </packing>
                     </child>
                     <child>
+                      <object class="GtkInfoBar" id="audio-preset-infobar">
+                        <property name="app_paintable">True</property>
+                        <property name="can_focus">False</property>
+                        <property name="message_type">error</property>
+                        <child internal-child="content_area">
+                          <object class="GtkBox" id="infobar-content_area3">
+                            <property name="can_focus">False</property>
+                            <child>
+                              <object class="GtkLabel" id="audio-preset-error-label">
+                                <property name="visible">True</property>
+                                <property name="can_focus">False</property>
+                              </object>
+                              <packing>
+                                <property name="expand">False</property>
+                                <property name="fill">True</property>
+                                <property name="position">0</property>
+                              </packing>
+                            </child>
+                          </object>
+                        </child>
+                        <child internal-child="action_area">
+                          <object class="GtkButtonBox" id="infobar-action_area3">
+                            <property name="can_focus">False</property>
+                            <property name="orientation">vertical</property>
+                            <property name="layout_style">center</property>
+                            <child>
+                              <placeholder/>
+                            </child>
+                          </object>
+                        </child>
+                      </object>
+                      <packing>
+                        <property name="expand">False</property>
+                        <property name="fill">True</property>
+                        <property name="position">1</property>
+                      </packing>
+                    </child>
+                    <child>
                       <object class="GtkScrolledWindow" id="scrolledwindow1">
                         <property name="visible">True</property>
                         <property name="can_focus">True</property>
@@ -526,7 +602,7 @@
                       <packing>
                         <property name="expand">True</property>
                         <property name="fill">True</property>
-                        <property name="position">1</property>
+                        <property name="position">2</property>
                       </packing>
                     </child>
                     <child>
@@ -588,7 +664,7 @@
                       <packing>
                         <property name="expand">False</property>
                         <property name="fill">False</property>
-                        <property name="position">2</property>
+                        <property name="position">3</property>
                       </packing>
                     </child>
                   </object>
diff --git a/pitivi/ui/preset.py b/pitivi/ui/preset.py
index f52be1b..ed2cffb 100644
--- a/pitivi/ui/preset.py
+++ b/pitivi/ui/preset.py
@@ -28,6 +28,10 @@ import gtk
 from pitivi.settings import xdg_data_home
 
 
+class DuplicatePresetNameException(Exception):
+    """Raised when an operation would result in a duplicated preset name."""
+    pass
+
 
 class PresetManager(object):
     """Abstract class for storing a list of presets.
@@ -132,6 +136,8 @@ class PresetManager(object):
         @param values: The values of the new preset.
         @type values: dict
         """
+        if self.hasPreset(name):
+            raise DuplicatePresetNameException(name)
         self.presets[name] = values
         # Note: This generates a "row-inserted" signal in the model.
         self.ordered.append((name, values))
@@ -154,11 +160,22 @@ class PresetManager(object):
         @type new_name: str
         """
         old_name = self.ordered[path][0]
+        assert old_name in self.presets
+        if old_name == new_name:
+            # Nothing to do.
+            return
+        if (not old_name.lower() == new_name.lower() and
+            self.hasPreset(new_name)):
+            raise DuplicatePresetNameException()
         self.ordered[path][0] = new_name
         self.presets[new_name] = self.presets.pop(old_name)
         if self.cur_preset == old_name:
             self.cur_preset = new_name
 
+    def hasPreset(self, name):
+        name = name.lower()
+        return any(name == preset.lower() for preset in self.getPresetNames())
+
     def getPresetNames(self):
         return (row[0] for row in self.ordered)
 
diff --git a/pitivi/ui/projectsettings.py b/pitivi/ui/projectsettings.py
index 0ef7ec2..28799cb 100644
--- a/pitivi/ui/projectsettings.py
+++ b/pitivi/ui/projectsettings.py
@@ -42,7 +42,8 @@ from pitivi.ui.common import\
     get_combo_value,\
     set_combo_value
 
-from pitivi.ui.preset import AudioPresetManager, VideoPresetManager
+from pitivi.ui.preset import AudioPresetManager, DuplicatePresetNameException,\
+    VideoPresetManager
 
 # FIXME: are we sure the following tables correct?
 
@@ -199,6 +200,12 @@ class ProjectSettingsDialog():
                 self.video_preset_treeview, self.video_presets,
                 self._updateVideoPresetButtons)
 
+        # A map which tells which infobar should be used when displaying
+        # an error for a preset manager.
+        self._infobarForPresetManager = {
+                self.audio_presets: self.audio_preset_infobar,
+                self.video_presets: self.video_preset_infobar}
+
         # Bind the widgets in the Video tab to the Video Presets Manager.
         self.bindSpinbutton(self.video_presets, "width", self.width_spinbutton)
         self.bindSpinbutton(self.video_presets, "height",
@@ -278,15 +285,29 @@ class ProjectSettingsDialog():
         model.connect("row-inserted", self._newPresetCb,
             column, renderer, treeview)
         renderer.connect("edited", self._presetNameEditedCb, mgr)
+        renderer.connect("editing-started", self._presetNameEditingStartedCb,
+            mgr)
         treeview.get_selection().connect("changed", self._presetChangedCb,
             mgr, update_buttons_func)
+        treeview.connect("focus-out-event", self._treeviewDefocusedCb, mgr)
 
     def _newPresetCb(self, model, path, iter_, column, renderer, treeview):
+        """Handle the addition of a preset to the model of the preset manager.
+        """
         treeview.set_cursor_on_cell(path, column, renderer, start_editing=True)
         treeview.grab_focus()
 
     def _presetNameEditedCb(self, renderer, path, new_text, mgr):
-        mgr.renamePreset(path, new_text)
+        """Handle the renaming of a preset."""
+        try:
+            mgr.renamePreset(path, new_text)
+        except DuplicatePresetNameException:
+            error_markup = _('"%s" already exists.') % new_text
+            self._showPresetManagerError(mgr, error_markup)
+
+    def _presetNameEditingStartedCb(self, renderer, editable, path, mgr):
+        """Handle the start of a preset renaming."""
+        self._hidePresetManagerError(mgr)
 
     def _presetChangedCb(self, selection, mgr, update_preset_buttons_func):
         """Handle the selection of a preset."""
@@ -297,6 +318,33 @@ class ProjectSettingsDialog():
             preset = None
         mgr.restorePreset(preset)
         update_preset_buttons_func()
+        self._hidePresetManagerError(mgr)
+
+    def _treeviewDefocusedCb(self, widget, event, mgr):
+        """Handle the treeview loosing the focus."""
+        self._hidePresetManagerError(mgr)
+
+    def _showPresetManagerError(self, mgr, error_markup):
+        """Show the specified error on the infobar associated with the manager.
+
+        @param mgr: The preset manager for which to show the error.
+        @type mgr: PresetManager
+        """
+        infobar = self._infobarForPresetManager[mgr]
+        # The infobar must contain exactly one object in the content area:
+        # a label for displaying the error.
+        label = infobar.get_content_area().children()[0]
+        label.set_markup(error_markup)
+        infobar.show()
+
+    def _hidePresetManagerError(self, mgr):
+        """Hide the error infobar associated with the manager.
+
+        @param mgr: The preset manager for which to hide the error infobar.
+        @type mgr: PresetManager
+        """
+        infobar = self._infobarForPresetManager[mgr]
+        infobar.hide()
 
     def constrained(self):
         return self.constrain_sar_button.props.active
@@ -346,6 +394,10 @@ class ProjectSettingsDialog():
             "constrain_sar_button")
         self.select_dar_radiobutton = self.builder.get_object(
             "select_dar_radiobutton")
+        self.video_preset_infobar = self.builder.get_object(
+            "video-preset-infobar")
+        self.audio_preset_infobar = self.builder.get_object(
+            "audio-preset-infobar")
 
     def _constrainSarButtonToggledCb(self, button):
         if button.props.active:
diff --git a/tests/test_preset.py b/tests/test_preset.py
index ce6301e..0a6e51b 100644
--- a/tests/test_preset.py
+++ b/tests/test_preset.py
@@ -24,7 +24,7 @@ import shutil
 import tempfile
 from unittest import TestCase
 
-from pitivi.ui.preset import PresetManager
+from pitivi.ui.preset import DuplicatePresetNameException, PresetManager
 
 
 class SimplePresetManager(PresetManager):
@@ -114,3 +114,22 @@ class TestProjectManager(TestCase):
         preset_one = other_manager.presets['preset one']
         self.assertEqual(1, len(preset_one))
         self.assertEqual('1A', preset_one['name1'])
+
+    def testAddPreset(self):
+        self.manager.addPreset('preseT onE', {'name1': '1A'})
+        self.assertRaises(DuplicatePresetNameException,
+                self.manager.addPreset, 'Preset One', {'name1': '2A'})
+
+    def testRenamePreset(self):
+        self.manager.addPreset('preseT onE', {'name1': '1A'})
+        self.manager.addPreset('Preset Two', {'name1': '2A'})
+
+        # Renaming 'preseT onE' to 'Preset One'.
+        self.manager.renamePreset('0', 'Preset One')
+
+        # Renaming 'Preset One' to 'Preset TWO'.
+        self.assertRaises(DuplicatePresetNameException,
+                self.manager.renamePreset, '0', 'Preset TWO')
+        # Renaming 'Preset One' to 'Preset two'.
+        self.assertRaises(DuplicatePresetNameException,
+                self.manager.renamePreset, '0', 'Preset two')



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