コード例 #1
0
class TestProjectManager(TestCase):
    def setUp(self):
        self.manager = ProjectManager()
        self.listener = ProjectManagerListener(self.manager)
        self.signals = self.listener.signals

    def testLoadProjectFailedUnknownFormat(self):
        """
        Check that new-project-failed is emitted when we don't have a suitable
        formatter.
        """
        uri = "file:///Untitled.meh"
        self.manager.loadProject(uri)
        self.failUnlessEqual(len(self.signals), 2)

        # loading
        name, args = self.signals[0]
        self.failUnlessEqual(args[0], uri)

        # failed
        name, args = self.signals[1]
        self.failUnlessEqual(name, "new-project-failed")
        signalUri, exception = args
        self.failUnlessEqual(uri, signalUri)
        self.failUnless(isinstance(exception, FormatterLoadError))

    def testLoadProjectFailedCloseCurrent(self):
        """
        Check that new-project-failed is emited if we can't close the current
        project instance.
        """
        state = {"tried-close": False}

        def close():
            state["tried-close"] = True
            return False
        self.manager.closeRunningProject = close

        uri = "file:///Untitled.xptv"
        self.manager.loadProject(uri)
        self.failUnlessEqual(len(self.signals), 2)

        # loading
        name, args = self.signals[0]
        self.failUnlessEqual(args[0], uri)

        # failed
        name, args = self.signals[1]
        self.failUnlessEqual(name, "new-project-failed")
        signalUri, exception = args
        self.failUnlessEqual(uri, signalUri)
        self.failUnless(isinstance(exception, FormatterLoadError))
        self.failUnless(state["tried-close"])

    def testLoadProjectFailedProxyFormatter(self):
        """
        Check that new-project-failed is proxied when a formatter emits it.
        """
        class FailFormatter(Formatter):
            def _validateUri(self, uri):
                pass

            def _loadProject(self, location, project=None):
                raise FormatterError()
        self.manager._getFormatterForUri = lambda uri: FailFormatter([])

        uri = "file:///Untitled.xptv"
        self.manager.loadProject(uri)
        self.failUnlessEqual(len(self.signals), 3)

        # loading
        name, args = self.signals[0]
        self.failUnlessEqual(name, "new-project-loading")
        self.failUnlessEqual(args[0], uri)

        # created
        name, args = self.signals[1]
        self.failUnlessEqual(name, "new-project-created")

        # failed
        name, args = self.signals[2]
        self.failUnlessEqual(name, "new-project-failed")
        signalUri, exception = args
        self.failUnlessEqual(uri, signalUri)
        self.failUnless(isinstance(exception, FormatterError))

    def testLoadProjectMissingUri(self):
        class MissingUriFormatter(Formatter):
            def _validateUri(self, uri):
                pass

            def _loadProject(self, location, project):
                self._finishLoadingProject(project)

            def _getSources(self):
                # this will emit missing-uri
                self.validateSourceURI("file:///icantpossiblyexist", None)
                return []

            def _fillTimeline(self):
                pass
        self.manager._getFormatterForUri = lambda uri: MissingUriFormatter([])

        uri = "file:///Untitled.xptv"
        self.manager.loadProject(uri)
        self.failUnlessEqual(len(self.signals), 4)

        # loading
        name, args = self.signals[0]
        self.failUnlessEqual(name, "new-project-loading")
        self.failUnlessEqual(args[0], uri)

        name, args = self.signals[1]
        self.failUnlessEqual(name, "new-project-created")
        self.failUnlessEqual(args[0].uri, uri)

        # failed
        name, args = self.signals[2]
        self.failUnlessEqual(name, "missing-uri")
        formatter, signalUri, unused_factory = args
        self.failUnlessEqual(signalUri, "file:///icantpossiblyexist")

    def testLoadProjectLoaded(self):
        class EmptyFormatter(Formatter):
            def _validateUri(self, uri):
                pass

            def _loadProject(self, location, project):
                self._finishLoadingProject(project)

            def _getSources(self):
                return []

            def _fillTimeline(self):
                pass
        self.manager._getFormatterForUri = lambda uri: EmptyFormatter([])

        uri = "file:///Untitled.xptv"
        self.manager.loadProject(uri)
        self.failUnlessEqual(len(self.signals), 3)

        # loading
        name, args = self.signals[0]
        self.failUnlessEqual(args[0], uri)

        name, args = self.signals[1]
        self.failUnlessEqual(name, "new-project-created")
        project = args[0]
        self.failUnlessEqual(uri, project.uri)

        name, args = self.signals[2]
        self.failUnlessEqual(name, "new-project-loaded")
        project = args[0]
        self.failUnlessEqual(uri, project.uri)

    def testCloseRunningProjectNoProject(self):
        self.failUnless(self.manager.closeRunningProject())
        self.failIf(self.signals)

    def testCloseRunningProjectRefuseFromSignal(self):
        def closing(manager, project):
            return False

        self.manager.current = MockProject()
        self.manager.current.has_mods = False
        self.manager.current.uri = "file:///ciao"
        self.manager.connect("closing-project", closing)

        self.failIf(self.manager.closeRunningProject())
        self.failUnlessEqual(len(self.signals), 1)
        name, args = self.signals[0]
        self.failUnlessEqual(name, "closing-project")
        project = args[0]
        self.failUnless(project is self.manager.current)

    def testCloseRunningProject(self):
        current = self.manager.current = MockProject()
        self.manager.current.has_mods = False
        self.failUnless(self.manager.closeRunningProject())
        self.failUnlessEqual(len(self.signals), 2)

        name, args = self.signals[0]
        self.failUnlessEqual(name, "closing-project")
        project = args[0]
        self.failUnless(project is current)

        name, args = self.signals[1]
        self.failUnlessEqual(name, "project-closed")
        project = args[0]
        self.failUnless(project is current)

        self.failUnlessEqual(self.manager.current, None)

    def testNewBlankProjectCantCloseCurrent(self):
        def closing(manager, project):
            return False

        self.manager.current = MockProject()
        self.manager.current.has_mods = False
        self.manager.current.uri = "file:///ciao"
        self.manager.connect("closing-project", closing)
        self.failIf(self.manager.newBlankProject())
        self.failUnlessEqual(len(self.signals), 1)
        signal, args = self.signals[0]
        self.failUnlessEqual(signal, "closing-project")

    def testNewBlankProject(self):
        self.failUnless(self.manager.newBlankProject())
        self.failUnlessEqual(len(self.signals), 3)

        name, args = self.signals[0]
        self.failUnlessEqual(name, "new-project-loading")
        uri = args[0]
        self.failUnlessEqual(uri, None)

        name, args = self.signals[1]
        self.failUnlessEqual(name, "new-project-created")
        project = args[0]
        self.failUnlessEqual(uri, project.uri)

        name, args = self.signals[2]
        self.failUnlessEqual(name, "new-project-loaded")
        project = args[0]
        self.failUnless(project is self.manager.current)

    def testSaveProject(self):
        uri = "file://" + os.path.abspath("testproject.xptv")
        uri2 = "file://" + os.path.abspath("testproject2.xptv")
        path = gst.uri_get_location(uri)
        path2 = gst.uri_get_location(uri2)

        # unlink any existing project files
        try:
            os.unlink(path)
            os.unlink(path2)
        except OSError:
            pass

        # save a project
        self.failUnless(self.manager.newBlankProject())
        self.failUnless(self.manager.saveProject(
            self.manager.current, uri, True))
        self.failUnless(uri_is_reachable(uri))

        # wait a bit
        time.sleep(1.0)

        # save project under new path
        self.failUnless(self.manager.saveProject(
            self.manager.current, uri2, True))
        self.failUnless(uri_is_reachable(uri2))

        # make sure the old path and the new path have different mtime
        mtime = os.path.getmtime(path)
        mtime2 = os.path.getmtime(path2)
        self.failUnless(mtime < mtime2)

        # wait a bit more
        time.sleep(1.0)

        # save project again under new path (by omitting uri arg)
        self.failUnless(self.manager.saveProject(
            self.manager.current, overwrite=True))

        # regression test for bug 594396
        # make sure we didn't save to the old URI
        self.failUnlessEqual(mtime, os.path.getmtime(path))
        # make sure we did save to the new URI
        self.failUnless(mtime2 < os.path.getmtime(path2))

        # unlink any existing project files
        try:
            os.unlink(path)
            os.unlink(path2)
        except OSError:
            pass

    def testBackupProject(self):
        uri = "file://" + os.path.abspath("testproject.xptv")

        # Create and save the project
        self.manager.newBlankProject()
        self.manager.saveProject(self.manager.current, uri, True)

        # Save the backup
        self.manager._saveBackupCb(self.manager.current, uri)
        backup_uri = self.manager._makeBackupURI(uri)
        self.failUnless(uri_is_reachable(uri))
        self.failUnless(uri_is_reachable(backup_uri))

        # When closing it should clean the backup
        self.manager.closeRunningProject()
        self.failUnless(not uri_is_reachable(backup_uri))

        # unlink any existing project files
        try:
            os.unlink(uri)
            os.unlink(backup_uri)
        except OSError:
            pass
コード例 #2
0
ファイル: application.py プロジェクト: bemasc/pitivi
class Pitivi(Loggable, Signallable):
    """
    Pitivi's main application class.

    Signals:
     - C{new-project} : A new C{Project} is loaded and ready to use.

     - C{new-project-loading} : Pitivi is attempting to load a new project.
     - C{new-project-loaded} : A new L{Project} has been loaded, and the UI should refresh it's view.
     - C{new-project-failed} : A new L{Project} failed to load.
     - C{closing-project} :  pitivi would like to close a project. handlers should return false
     if they do not want this project to close. by default, assumes
     true. This signal should only be used by classes that might want to abort
     the closing of a project.
     - C{project-closed} : The project is closed, it will be freed when the callback returns.
     Classes should connect to this instance when they want to know that
     data related to that project is no longer going to be used.
     - C{shutdown} : Used internally, do not use this signal.`

    @ivar settings: Application-wide settings.
    @type settings: L{GlobalSettings}.
    @ivar projects: List of used projects
    @type projects: List of L{Project}.
    @ivar current: Currently used project.
    @type current: L{Project}.
    """

    __signals__ = {
        "new-project": ["project"],
        "new-project-loading": ["uri"],
        "new-project-created": ["project"],
        "new-project-loaded": ["project"],
        "new-project-failed": ["uri", "exception"],
        "closing-project": ["project"],
        "project-closed": ["project"],
        "missing-uri": ["formatter", "uri"],
        "shutdown": None}

    def __init__(self):
        """
        initialize pitivi with the command line arguments
        """
        Loggable.__init__(self)

        # init logging as early as possible so we can log startup code
        enable_color = os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') in ('', '0')
        log.init('PITIVI_DEBUG', enable_color)

        self.info('starting up')

        # store ourself in the instance global
        if instance.PiTiVi:
            raise RuntimeWarning(
                _("There is already a %s instance, please inform the developers by filing a bug at http://bugzilla.gnome.org/enter_bug.cgi?product=pitivi")
                % APPNAME)
        instance.PiTiVi = self

        self.projects = []
        self.current = None

        # get settings
        self.settings = GlobalSettings()
        self.threads = ThreadMaster()
        #self.screencast = False

        self.plugin_manager = PluginManager(
            self.settings.get_local_plugin_path(),
            self.settings.get_plugin_settings_path())
        self.effects = EffectsHandler()

        self.projectManager = ProjectManager(self.effects)
        self._connectToProjectManager(self.projectManager)

        self.action_log = UndoableActionLog()
        self.debug_action_log_observer = DebugActionLogObserver()
        self.debug_action_log_observer.startObserving(self.action_log)
        self.timelineLogObserver = TimelineLogObserver(self.action_log)
        self.projectLogObserver = ProjectLogObserver(self.action_log)
        self.sourcelist_log_observer = SourceListLogObserver(self.action_log)

    def shutdown(self):
        """
        Close PiTiVi.

        @return: C{True} if PiTiVi was successfully closed, else C{False}.
        @rtype: C{bool}
        """
        self.debug("shutting down")
        # we refuse to close if we're running a user interface and the user
        # doesn't want us to close the current project.
        if self.current and not self.projectManager.closeRunningProject():
            self.warning("Not closing since running project doesn't want to close")
            return False
        self.threads.stopAllThreads()
        self.settings.storeSettings()
        self.current = None
        instance.PiTiVi = None
        self.emit("shutdown")
        return True

    def _connectToProjectManager(self, projectManager):
        projectManager.connect("new-project-loading",
                self._projectManagerNewProjectLoading)
        projectManager.connect("new-project-created",
                self._projectManagerNewProjectCreated)
        projectManager.connect("new-project-loaded",
                self._projectManagerNewProjectLoaded)
        projectManager.connect("new-project-failed",
                self._projectManagerNewProjectFailed)
        projectManager.connect("closing-project",
                self._projectManagerClosingProject)
        projectManager.connect("project-closed",
                self._projectManagerProjectClosed)

    def _projectManagerNewProjectLoading(self, projectManager, uri):
        self.emit("new-project-loading", uri)

    def _projectManagerNewProjectCreated(self, projectManager, project):
        self.current = project
        self.emit("new-project-created", project)

    def _newProjectLoaded(self, project):
        pass

    def _projectManagerNewProjectLoaded(self, projectManager, project):
        self.current = project
        self.action_log.clean()
        self.timelineLogObserver.startObserving(project.timeline)
        self.projectLogObserver.startObserving(project)
        self.sourcelist_log_observer.startObserving(project.sources)
        self._newProjectLoaded(project)
        self.emit("new-project-loaded", project)

    def _projectManagerNewProjectFailed(self, projectManager, uri, exception):
        self.emit("new-project-failed", uri, exception)

    def _projectManagerClosingProject(self, projectManager, project):
        return self.emit("closing-project", project)

    def _projectManagerProjectClosed(self, projectManager, project):
        self.timelineLogObserver.stopObserving(project.timeline)
        self.projectLogObserver.stopObserving(project)
        self.current = None
        self.emit("project-closed", project)
コード例 #3
0
class Pitivi(Loggable, Signallable):
    """
    Pitivi's main application class.

    Signals:
     - C{new-project} : A new C{Project} is loaded and ready to use.

     - C{new-project-loading} : Pitivi is attempting to load a new project.
     - C{new-project-loaded} : A new L{Project} has been loaded, and the UI should refresh it's view.
     - C{new-project-failed} : A new L{Project} failed to load.
     - C{closing-project} :  pitivi would like to close a project. handlers should return false
     if they do not want this project to close. by default, assumes
     true. This signal should only be used by classes that might want to abort
     the closing of a project.
     - C{project-closed} : The project is closed, it will be freed when the callback returns.
     Classes should connect to this instance when they want to know that
     data related to that project is no longer going to be used.
     - C{shutdown} : Used internally, do not use this signal.`

    @ivar settings: Application-wide settings.
    @type settings: L{GlobalSettings}.
    @ivar projects: List of used projects
    @type projects: List of L{Project}.
    @ivar current: Currently used project.
    @type current: L{Project}.
    """

    __signals__ = {
        "new-project": ["project"],
        "new-project-loading": ["uri"],
        "new-project-created": ["project"],
        "new-project-loaded": ["project"],
        "new-project-failed": ["uri", "exception"],
        "closing-project": ["project"],
        "project-closed": ["project"],
        "missing-uri": ["formatter", "uri"],
        "shutdown": None
    }

    def __init__(self):
        """
        initialize pitivi with the command line arguments
        """
        Loggable.__init__(self)

        # init logging as early as possible so we can log startup code
        enable_color = os.environ.get('PITIVI_DEBUG_NO_COLOR',
                                      '0') in ('', '0')
        log.init('PITIVI_DEBUG', enable_color)

        self.info('starting up')

        # store ourself in the instance global
        if instance.PiTiVi:
            raise RuntimeWarning(
                _("There is already a %s instance, please inform the developers by filing a bug at http://bugzilla.gnome.org/enter_bug.cgi?product=pitivi"
                  ) % APPNAME)
        instance.PiTiVi = self

        self.projects = []
        self.current = None

        # get settings
        self.settings = GlobalSettings()
        self.threads = ThreadMaster()
        #self.screencast = False

        self.plugin_manager = PluginManager(
            self.settings.get_local_plugin_path(),
            self.settings.get_plugin_settings_path())
        self.effects = Magician()
        self.deviceprobe = get_probe()

        self.projectManager = ProjectManager()
        self._connectToProjectManager(self.projectManager)

        self.action_log = UndoableActionLog()
        self.debug_action_log_observer = DebugActionLogObserver()
        self.debug_action_log_observer.startObserving(self.action_log)
        self.timelineLogObserver = TimelineLogObserver(self.action_log)
        self.sourcelist_log_observer = SourceListLogObserver(self.action_log)

    #{ Shutdown methods

    def shutdown(self):
        """
        Close PiTiVi.

        @return: C{True} if PiTiVi was successfully closed, else C{False}.
        @rtype: C{bool}
        """
        self.debug("shutting down")
        # we refuse to close if we're running a user interface and the user
        # doesn't want us to close the current project.
        if self.projectManager.current and not self.projectManager.closeRunningProject(
        ):
            self.warning(
                "Not closing since running project doesn't want to close")
            return False
        self.threads.stopAllThreads()
        self.settings.storeSettings()
        self.deviceprobe.release()
        self.deviceprobe = None
        self.current = None
        instance.PiTiVi = None
        self.emit("shutdown")
        return True

    #}

    def _connectToProjectManager(self, projectManager):
        projectManager.connect("new-project-loading",
                               self._projectManagerNewProjectLoading)
        projectManager.connect("new-project-created",
                               self._projectManagerNewProjectCreated)
        projectManager.connect("new-project-loaded",
                               self._projectManagerNewProjectLoaded)
        projectManager.connect("new-project-failed",
                               self._projectManagerNewProjectFailed)
        projectManager.connect("closing-project",
                               self._projectManagerClosingProject)
        projectManager.connect("project-closed",
                               self._projectManagerProjectClosed)

    def _projectManagerNewProjectLoading(self, projectManager, uri):
        self.emit("new-project-loading", uri)

    def _projectManagerNewProjectCreated(self, projectManager, project):
        self.current = project
        self.emit("new-project-created", project)

    def _projectManagerNewProjectLoaded(self, projectManager, project):
        self.current = project
        self.action_log.clean()
        self.timelineLogObserver.startObserving(project.timeline)
        self.sourcelist_log_observer.startObserving(project.sources)
        self.emit("new-project-loaded", project)

    def _projectManagerNewProjectFailed(self, projectManager, uri, exception):
        self.emit("new-project-failed", uri, exception)

    def _projectManagerClosingProject(self, projectManager, project):
        return self.emit("closing-project", project)

    def _projectManagerProjectClosed(self, projectManager, project):
        self.timelineLogObserver.stopObserving(project.timeline)
        self.current = None
        self.emit("project-closed", project)