[pitivi] UI: file load and save actions now hook into formatter code



commit f8c6d8d4643fe70b9de9d769eded487a1e30cd40
Author: Brandon Lewis <brandon_lewis berkeley edu>
Date:   Thu Apr 2 12:11:42 2009 -0700

    UI: file load and save actions now hook into formatter code
---
 pitivi/application.py       |   11 +++++++----
 pitivi/formatters/base.py   |   15 +++++++--------
 pitivi/formatters/format.py |   20 ++++++++++++++++++++
 pitivi/project.py           |   23 +----------------------
 pitivi/ui/mainwindow.py     |   38 +++++++++++++++++++++++---------------
 5 files changed, 58 insertions(+), 49 deletions(-)

diff --git a/pitivi/application.py b/pitivi/application.py
index 1a39221..25e8c52 100644
--- a/pitivi/application.py
+++ b/pitivi/application.py
@@ -35,7 +35,6 @@ import pitivi.instance as instance
 
 from pitivi.check import initial_checks
 from pitivi.device import get_probe
-from pitivi.project import Project, file_is_project
 from pitivi.effects import Magician
 from pitivi.configure import APPNAME
 from pitivi.settings import GlobalSettings
@@ -44,6 +43,7 @@ from pitivi.pluginmanager import PluginManager
 from pitivi.signalinterface import Signallable
 from pitivi.log.loggable import Loggable
 from pitivi.log import log
+from pitivi.project import Project
 
 # FIXME : Speedup loading time
 # Currently we load everything in one go
@@ -122,6 +122,8 @@ class Pitivi(object, Loggable, Signallable):
             self.settings.get_local_plugin_path(),
             self.settings.get_plugin_settings_path())
 
+        # FIXME: don't assume the user wishes to create  the default project
+        # class
         self.current = Project(_("New Project"))
         self.effects = Magician()
 
@@ -172,16 +174,17 @@ class Pitivi(object, Loggable, Signallable):
                 return
             uri = "file://" + filepath
         # is the given filepath a valid pitivi project
-        if not file_is_project(uri):
+        formatter = get_formatter_for_uri(uri)
+        if not formatter:
             self.emit("new-project-failed", _("Not a valid project file."),
                 uri)
             return
         # if current project, try to close it
         if self._closeRunningProject():
-            project = Project(uri=uri)
+            project = formatter.newProject()
             self.emit("new-project-loading", project)
             try:
-                project.load()
+                formater.load_project(uri, project)
                 self.current = project
                 self.emit("new-project-loaded", self.current)
             except:
diff --git a/pitivi/formatters/base.py b/pitivi/formatters/base.py
index 3ae0fa0..53601f1 100644
--- a/pitivi/formatters/base.py
+++ b/pitivi/formatters/base.py
@@ -45,10 +45,6 @@ class FormatterSaveError(FormatterError):
 class FormatterOverwriteError(FormatterSaveError):
     """A project can't be saved because it will be overwritten"""
 
-# FIXME : How do we handle interaction with the UI ??
-# Do we blindly load everything and let the UI figure out what's missing from
-# the loaded project ?
-
 class Formatter(object, Signallable):
     """
     Provides convenience methods for storing and loading
@@ -68,6 +64,7 @@ class Formatter(object, Signallable):
         }
 
     description = "Description of the format"
+    ProjectClass = Project
 
     def __init__(self):
         # mapping of directory changes
@@ -79,7 +76,10 @@ class Formatter(object, Signallable):
 
     #{ Load/Save methods
 
-    def loadProject(self, location):
+    def newProject(self):
+        return self.ProjectClass()
+
+    def loadProject(self, location, project=None):
         """
         Loads the project from the given location.
 
@@ -104,9 +104,8 @@ class Formatter(object, Signallable):
         # FIXME : maybe have a convenience method for opening a location
         self.parse(location)
 
-        # create a NewProject
-        # FIXME : allow subclasses to create their own Project subclass
-        project = Project()
+        if not project:
+            project = self.newProject()
 
         # ask for all sources being used
         uris = []
diff --git a/pitivi/formatters/format.py b/pitivi/formatters/format.py
index 53d9d7a..dc51182 100644
--- a/pitivi/formatters/format.py
+++ b/pitivi/formatters/format.py
@@ -81,4 +81,24 @@ def can_handle_location(uri):
     @return: Whether the location contains a valid L{Project}.
     @rtype: L{bool}
     """
+    return False
+
+def list_formats():
+    """
+    Returns a sequence of available project file formats
+
+    @return: a sequence of 2-tuples (name, extensions) representing available
+    file formats, where name is a user-readable name, and extensions is a
+    sequence of extensions for this format ('.' omitted).
+    """
+    return []
+
+def get_formatter_for_uri(uri):
+    """
+    Returns an Formatter object that can parse the given project file
+
+    @type uri:L{str}
+    @param uri: The location of the project file
+    @return: an instance of a Formatter, or None
+    """
     raise NotImplementedError
diff --git a/pitivi/project.py b/pitivi/project.py
index c55e4a8..880f519 100644
--- a/pitivi/project.py
+++ b/pitivi/project.py
@@ -39,6 +39,7 @@ from pitivi.settings import ExportSettings
 from pitivi.configure import APPNAME
 from pitivi.signalinterface import Signallable
 from pitivi.action import ViewAction
+from pitivi.formatters.format import save_project
 
 class ProjectError(Exception):
     """Project error"""
@@ -74,8 +75,6 @@ class Project(object, Signallable, Loggable):
     """
 
     __signals__ = {
-        "save-uri-requested" : None,
-        "confirm-overwrite" : ["location"],
         "settings-changed" : None,
         "missing-plugins": ["uri", "detail", "description"],
         "loaded" : None
@@ -99,9 +98,6 @@ class Project(object, Signallable, Loggable):
         self.settingssigid = 0
         self._dirty = False
 
-        # formatter instance used for loading project.
-        self._formatter = None
-
         self.sources.connect('missing-plugins', self._sourceListMissingPluginsCb)
 
         self.timeline = Timeline()
@@ -131,23 +127,6 @@ class Project(object, Signallable, Loggable):
     def _settingsChangedCb(self, unused_settings):
         self.emit('settings-changed')
 
-    def setUri(self, uri, format=None):
-        """ Set the location to which this project will be stored """
-        self.log("uri:%s, format:%s", uri, format)
-        if not self.uri == uri:
-            self.log("updating self.uri, previously:%s", self.uri)
-            self.uri = uri
-            self.urichanged = True
-
-        if not format or not self.format == format:
-            self.log("updating save format, previously:%s", self.format)
-            if not format:
-                path = gst.uri_get_location(uri)
-                ext = os.path.splitext(path)[1]
-                self.log("Based on file extension, format is %s", format)
-                format = ProjectSaver.getFormat(ext)
-            self.format = format
-
     def getSettings(self):
         """
         return the currently configured settings.
diff --git a/pitivi/ui/mainwindow.py b/pitivi/ui/mainwindow.py
index 6ef4d0d..73263cd 100644
--- a/pitivi/ui/mainwindow.py
+++ b/pitivi/ui/mainwindow.py
@@ -49,6 +49,7 @@ from pitivi.ui import dnd
 from pitivi.pipeline import Pipeline
 from pitivi.action import ViewAction
 from pitivi.settings import GlobalSettings
+import pitivi.formatters.format as formatter
 
 if HAVE_GCONF:
     D_G_INTERFACE = "/desktop/gnome/interface"
@@ -95,6 +96,9 @@ GlobalSettings.addConfigOption('mainWindowShowTimelineToolbar',
     key="show-timeline-toolbar",
     default=True)
 
+def supported(info):
+    return formatter.can_handle_location(info[1])
+
 def create_stock_icons():
     """ Creates the pitivi-only stock icons """
     gtk.stock_add([
@@ -158,8 +162,6 @@ class PitiviMainWindow(gtk.Window, Loggable):
         self.app.connect("new-project-loading", self._newProjectLoadingCb)
         self.app.connect("closing-project", self._closingProjectCb)
         self.app.connect("new-project-failed", self._notProjectCb)
-        self.app.current.connect("save-uri-requested", self._saveAsDialogCb)
-        self.app.current.connect("confirm-overwrite", self._confirmOverwriteCb)
         self.project.pipeline.connect("error", self._pipelineErrorCb)
         self.app.current.sources.connect("file_added", self._sourcesFileAddedCb)
         self.app.current.connect("settings-changed", self._settingsChangedCb)
@@ -325,7 +327,7 @@ class PitiviMainWindow(gtk.Window, Loggable):
                 action.set_sensitive(True)
             elif action_name in ["SaveProject", "SaveProjectAs",
                     "NewProject", "OpenProject"]:
-                if not self.app.settings.fileSupportEnabled:
+                if self.app.settings.fileSupportEnabled:
                     action.set_sensitive(True)
             else:
                 action.set_sensitive(False)
@@ -566,6 +568,7 @@ class PitiviMainWindow(gtk.Window, Loggable):
         self.app.newBlankProject()
 
     def _openProjectCb(self, unused_action):
+
         chooser = gtk.FileChooserDialog(_("Open File..."),
             self,
             action=gtk.FILE_CHOOSER_ACTION_OPEN,
@@ -573,7 +576,7 @@ class PitiviMainWindow(gtk.Window, Loggable):
                 gtk.STOCK_OPEN, gtk.RESPONSE_OK))
         chooser.set_select_multiple(False)
         chooser.set_current_folder(self.settings.lastProjectFolder)
-        formats = ProjectSaver.listFormats()
+        formats = formatter.list_formats()
         for format in formats:
             filt = gtk.FileFilter()
             filt.set_name(format[0])
@@ -581,24 +584,29 @@ class PitiviMainWindow(gtk.Window, Loggable):
                 filt.add_pattern("*%s" % ext)
             chooser.add_filter(filt)
         default = gtk.FileFilter()
-        default.set_name("All")
-        default.add_pattern("*")
+        default.set_name(_("All Supported Formats"))
+        default.add_custom(gtk.FILE_FILTER_URI, supported)
         chooser.add_filter(default)
 
         response = chooser.run()
         self.settings.lastProjectFolder = chooser.get_current_folder()
         if response == gtk.RESPONSE_OK:
-            path = chooser.get_filename()
-            self.app.loadProject(filepath = path)
+            uri = chooser.get_uri()
+            self.app.loadProject(uri = uri)
 
         chooser.destroy()
         return True
 
     def _saveProjectCb(self, unused_action):
-        self.app.current.save()
+        if not self.app.current.uri:
+            self._saveProjectAsCb(unused_action)
+        else:
+            self.app.current.save()
 
     def _saveProjectAsCb(self, unused_action):
-        self.app.current.saveAs()
+        uri = self._showSaveAsDialog(self.app.current)
+        if uri:
+            self.app.current.save(uri)
 
     def _projectSettingsCb(self, unused_action):
         from projectsettings import ProjectSettingsDialog
@@ -768,7 +776,7 @@ class PitiviMainWindow(gtk.Window, Loggable):
             return True
         return False
 
-    def _saveAsDialogCb(self, project):
+    def _showSaveAsDialog(self, project):
         self.log("Save URI requested")
         chooser = gtk.FileChooserDialog(_("Save As..."),
             self,
@@ -779,7 +787,8 @@ class PitiviMainWindow(gtk.Window, Loggable):
         chooser.set_select_multiple(False)
         chooser.set_current_name(_("Untitled.pptv"))
         chooser.set_current_folder(self.settings.lastProjectFolder)
-        formats = ProjectSaver.listFormats()
+        chooser.props.do_overwrite_confirmation = True
+        formats = formatter.list_formats()
         for format in formats:
             filt = gtk.FileFilter()
             filt.set_name(format[0])
@@ -803,11 +812,10 @@ class PitiviMainWindow(gtk.Window, Loggable):
             if format == _("Detect Automatically"):
                 format = None
             self.log("uri:%s , format:%s", uri, format)
-            project.setUri(uri, format)
-            ret = True
+            ret = uri
         else:
             self.log("User didn't choose a URI to save project to")
-            ret = False
+            ret = None
 
         chooser.destroy()
         return ret



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