[pitivi] pitivi: Implement the notion of "read-only" projects



commit d276be27c12bea58f005b7e64d1449b2c803f6eb
Author: Jean-François Fortin Tam <nekohayo gmail com>
Date:   Sat Aug 31 21:33:28 2013 -0400

    pitivi: Implement the notion of "read-only" projects
    
    This fixes loading backup projects (their assets wouldn't load anymore),
    and ensures that users can't overwrite legacy ".xptv" files.
    
    Clicking "Save" in those cases will now trigger a "Save As" dialog.
    
    This commit also adds a dogtail test that ensures that clicking "Save"
    after loading a backup project actually triggers the "Save As" dialog.

 pitivi/mainwindow.py                  |   11 ++++++++---
 pitivi/project.py                     |   24 +++++++++++++++---------
 tests/dogtail_scripts/test_project.py |   12 ++++++++++--
 3 files changed, 33 insertions(+), 14 deletions(-)
---
diff --git a/pitivi/mainwindow.py b/pitivi/mainwindow.py
index cd9543a..b4cccfe 100644
--- a/pitivi/mainwindow.py
+++ b/pitivi/mainwindow.py
@@ -671,7 +671,7 @@ class PitiviMainWindow(Gtk.Window, Loggable):
         self.openProject()
 
     def _saveProjectCb(self, unused_action):
-        if not self.app.current.uri:
+        if not self.app.current.uri or self.app.projectManager.disable_save is True:
             self._saveProjectAsCb(unused_action)
         else:
             self.app.projectManager.saveProject()
@@ -856,6 +856,11 @@ class PitiviMainWindow(Gtk.Window, Loggable):
             self.main_actions.get_action("SaveProject").set_sensitive(True)
             self._missingUriOnLoading = False
 
+        if projectManager.disable_save is True:
+            # Special case: we enforce "Save as", but the normal "Save" button
+            # redirects to it if needed, so we still want it to be enabled:
+            self.main_actions.get_action("SaveProject").set_sensitive(True)
+
         if self.app.current.timeline.props.duration != 0:
             self.render_button.set_sensitive(True)
 
@@ -896,7 +901,7 @@ class PitiviMainWindow(Gtk.Window, Loggable):
         if not project.hasUnsavedModifications():
             return True
 
-        if project.uri:
+        if project.uri and projectManager.disable_save is False:
             save = Gtk.STOCK_SAVE
         else:
             save = Gtk.STOCK_SAVE_AS
@@ -960,7 +965,7 @@ class PitiviMainWindow(Gtk.Window, Loggable):
         response = dialog.run()
         dialog.destroy()
         if response == Gtk.ResponseType.YES:
-            if project.uri is not None:
+            if project.uri is not None and projectManager.disable_save is False:
                 res = self.app.projectManager.saveProject()
             else:
                 res = self._saveProjectAsCb(None)
diff --git a/pitivi/project.py b/pitivi/project.py
index 2c39e78..dbd84ff 100644
--- a/pitivi/project.py
+++ b/pitivi/project.py
@@ -126,6 +126,7 @@ class ProjectManager(Signallable, Loggable):
         self.app = app_instance
         # Current project:
         self.current = None
+        self.disable_save = False  # Enforce "Save as" for backup and xptv files
         self._backup_lock = 0
 
     def loadProject(self, uri):
@@ -151,17 +152,19 @@ class ProjectManager(Signallable, Loggable):
         else:
             if time_diff > 0:
                 use_backup = self._restoreFromBackupDialog(time_diff)
+
         if use_backup:
             uri = self._makeBackupURI(uri)
             self.debug('Loading project from backup "%s"' % uri)
-            # Make a new project instance, but don't specify the URI.
-            # That way, we force the user to "Save as" (which ensures that the
-            # changes in the loaded backup file are approved by the user).
-            self.current = Project()
+
+        # Load the project:
+        self.current = Project(uri=uri)
+        # For backup files and legacy formats, force the user to use "Save as"
+        if use_backup or path.endswith(".xptv"):
+            self.debug("Enforcing read-only mode")
+            self.disable_save = True
         else:
-            # Load the project normally.
-            # The "old" backup file will eventually be deleted or overwritten.
-            self.current = Project(uri=uri)
+            self.disable_save = False
 
         self.current.connect("missing-uri", self._missingURICb)
         self.current.connect("loaded", self._projectLoadedCb)
@@ -248,6 +251,10 @@ class ProjectManager(Signallable, Loggable):
         "formatter_type" allows specifying a GES formatter type to use; if None,
         GES will default to GES.XmlFormatter.
         """
+        if self.disable_save is True and (backup is True or uri is None):
+            self.log("Read-only mode is enforced and no new URI was specified, ignoring save request")
+            return
+
         if backup:
             if self.current is not None and self.current.uri is not None:
                 # Ignore whatever URI that is passed on to us. It's a trap.
@@ -291,6 +298,7 @@ class ProjectManager(Signallable, Loggable):
                 # otherwise, subsequent saves will be to the old uri.
                 self.info("Setting the project instance's URI to %s" % uri)
                 self.current.uri = uri
+                self.disable_save = False
             else:
                 self.debug('Saved backup "%s"' % uri)
 
@@ -512,8 +520,6 @@ class Project(Loggable, GES.Project):
         self.pipeline = None
         self.timeline = None
         self.seeker = Seeker()
-
-        # FIXME Remove our URI and work more closely with GES.Project URI handling
         self.uri = uri
 
         # Follow imports
diff --git a/tests/dogtail_scripts/test_project.py b/tests/dogtail_scripts/test_project.py
index 2d5ef0a..aca9762 100644
--- a/tests/dogtail_scripts/test_project.py
+++ b/tests/dogtail_scripts/test_project.py
@@ -1,6 +1,8 @@
 #!/usr/bin/env python2
 from helper_functions import HelpFunc
 from dogtail.predicate import IsATextEntryNamed, GenericPredicate
+from dogtail.tree import SearchError
+import dogtail.rawinput
 from time import time, sleep
 import os
 
@@ -222,6 +224,7 @@ class ProjectPropertiesTest(HelpFunc):
 
         # After another "crash", try loading from the backup.
         self.setUp()
+        seektime = self.viewer.child(name="timecode_entry").child(roleName="text")
         welcome_dialog = self.pitivi.child(name="Welcome", roleName="frame", recursive=False)
         welcome_dialog.child(name=filename).doubleClick()
         self.pitivi.child(name="restore from backup dialog", roleName="dialog", 
recursive=False).button("Restore from backup").click()
@@ -232,9 +235,14 @@ class ProjectPropertiesTest(HelpFunc):
         self.goToEnd_button = self.viewer.child(name="goToEnd_button")
         self.goToEnd_button.click()
         self.assertEqual(seektime.text, DURATION_OF_TWO_CLIPS)
-        # ...and that the user can't save without using Save As:
+        # ...and that clicking "Save" actually triggers "Save As":
         self.menubar.menu("Project").click()
-        self.assertFalse(self.menubar.menu("Project").menuItem("Save").sensitive)
+        self.menubar.menu("Project").menuItem("Save").click()
+        try:
+            _save_as_dialog = self.pitivi.child(name="Save As...", roleName="file chooser", recursive=False, 
retry=False)
+            dogtail.rawinput.pressKey("Esc")  # Dismiss the dialog
+        except SearchError:
+            self.fail('Clicking "Save" after loading a backup project should have triggered the "Save As" 
dialog')
         # Do not save, kill once more - the backup should be preserved
         # and the user should be prompted again on the next startup
         self.tearDown(clean=False, kill=True)


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