[pitivi] Make Pitivi a GtkApplication
- From: Thibault Saunier <tsaunier src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] Make Pitivi a GtkApplication
- Date: Wed, 2 Apr 2014 15:29:07 +0000 (UTC)
commit f7e23b0955525a72e9e923940d8a766aa690d87d
Author: Alexandru Băluț <alexandru balut gmail com>
Date: Sun Mar 16 23:43:02 2014 +0100
Make Pitivi a GtkApplication
Fixes https://bugzilla.gnome.org/show_bug.cgi?id=693291
bin/pitivi.in | 32 ++--
pitivi/application.py | 369 +++++++++------------------------------
pitivi/clipproperties.py | 22 ++--
pitivi/dialogs/startupwizard.py | 35 ++--
pitivi/effects.py | 11 +-
pitivi/mainwindow.py | 106 ++++++------
pitivi/medialibrary.py | 30 ++--
pitivi/project.py | 19 ++-
pitivi/render.py | 12 +-
pitivi/timeline/timeline.py | 2 +-
pitivi/transitions.py | 6 +-
pitivi/viewer.py | 10 +-
tests/test_application.py | 7 +
13 files changed, 241 insertions(+), 420 deletions(-)
---
diff --git a/bin/pitivi.in b/bin/pitivi.in
index be68e43..c347fdf 100644
--- a/bin/pitivi.in
+++ b/bin/pitivi.in
@@ -123,27 +123,19 @@ def _check_requirements():
sys.exit(2)
def _run_pitivi():
- import pitivi.application as ptv
+ from pitivi import application
- # Make it easy for developers to debug the application startup.
- if os.environ.get('PITIVI_DEBUG_NO_UI') == '1':
- print('Starting Pitivi with no GUI.')
- ptv.GuiPitivi._showGui = lambda *args, **kargs : None
-
- # Start the real Pitivi, with given arguments.
- sys.exit(ptv.main(sys.argv))
+ app = application.Pitivi()
+ app.run(sys.argv)
if __name__ == "__main__":
- try:
- _add_pitivi_path()
- _initialize_modules()
- # Dep checks really have to happen here, not in application.py. Otherwise,
- # as soon as application.py starts, it will try importing all the code and
- # the classes in application.py will not even have the opportunity to run.
- # We do these checks on every startup (even outside the dev environment, for
- # soft deps); doing imports and gst registry checks has near-zero cost.
- _check_requirements()
- _run_pitivi()
- except KeyboardInterrupt:
- print("\tPitivi stopped by user with KeyboardInterrupt!")
+ _add_pitivi_path()
+ _initialize_modules()
+ # Dep checks really have to happen here, not in application.py. Otherwise,
+ # as soon as application.py starts, it will try importing all the code and
+ # the classes in application.py will not even have the opportunity to run.
+ # We do these checks on every startup (even outside the dev environment, for
+ # soft deps); doing imports and gst registry checks has near-zero cost.
+ _check_requirements()
+ _run_pitivi()
diff --git a/pitivi/application.py b/pitivi/application.py
index 1c87e38..c2095d8 100644
--- a/pitivi/application.py
+++ b/pitivi/application.py
@@ -1,10 +1,8 @@
# Pitivi video editor
#
-# pitivi/pitivi.py
+# pitivi/application.py
#
-# Copyright (c) 2005-2009 Edward Hervey <bilboed bilboed com>
-# Copyright (c) 2008-2009 Alessandro Decina <alessandro d gmail com>
-# Copyright (c) 2010 Google <aleb google com>
+# Copyright (c) 2014 <alexandru balut gmail com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
@@ -21,29 +19,13 @@
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-Main application
-
-Hierarchy of the whole thing:
-
-Pitivi
- InteractivePitivi
- GuiPitivi
- ProjectCreatorGuiPitivi
- ProjectLoaderGuiPitivi
- StartupWizardGuiPitivi
-"""
import os
-import sys
-from gi.repository import GES
+from gi.repository import GObject
+from gi.repository import GdkX11
from gi.repository import Gio
-from gi.repository import GLib
from gi.repository import Gtk
-from gettext import gettext as _
-from optparse import OptionParser
-
from pitivi.effects import EffectsHandler
from pitivi.configure import VERSION, RELEASES_URL
from pitivi.settings import GlobalSettings
@@ -54,77 +36,105 @@ from pitivi.undo.undo import UndoableActionLog, DebugActionLogObserver
from pitivi.dialogs.startupwizard import StartUpWizard
from pitivi.utils.misc import quote_uri
-from pitivi.utils.signal import Signallable
from pitivi.utils.system import getSystem
from pitivi.utils.loggable import Loggable
import pitivi.utils.loggable as log
-#FIXME GES port disabled it
-#from pitivi.undo.timeline import TimelineLogObserver
-class Pitivi(Loggable, Signallable):
+class Pitivi(Gtk.Application, Loggable):
"""
- 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{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.`
+ Pitivi's application.
+ @ivar gui: The main window of the app.
+ @type gui: L{PitiviMainWindow}
+ @type project_manager: L{ProjectManager}
@ivar settings: Application-wide settings.
@type settings: L{GlobalSettings}.
- @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"],
- "project-closed": ["project"],
- "missing-uri": ["formatter", "uri"],
- "version-info-received": ["versions"],
- "shutdown": None}
+ __gsignals__ = {
+ 'version-info-received': (GObject.SIGNAL_RUN_LAST, None, (object,))
+ }
def __init__(self):
+ Gtk.Application.__init__(self,
+ application_id="org.pitivi",
+ flags=Gio.ApplicationFlags.HANDLES_OPEN)
Loggable.__init__(self)
+ self.settings = None
+ self.threads = None
+ self.effects = None
+ self.system = None
+ self.project_manager = ProjectManager(self)
+ self.action_log = None
+ self.debug_action_log_observer = None
+ self.project_log_observer = None
+
+ self.gui = None
+ self.welcome_wizard = None
+
+ self._version_information = {}
+
+ self.connect("startup", self.startupCb)
+ self.connect("activate", self.activateCb)
+ self.connect("open", self.openCb)
+
+ def startupCb(self, unused_app):
# Init logging as early as possible so we can log startup code
enable_color = not os.environ.get('PITIVI_DEBUG_NO_COLOR', '0') in ('', '1')
- # Let's show a human-readable pitivi debug output by default, and only
+ # Let's show a human-readable Pitivi debug output by default, and only
# show a crazy unreadable mess when surrounded by gst debug statements.
enable_crack_output = "GST_DEBUG" in os.environ
log.init('PITIVI_DEBUG', enable_color, enable_crack_output)
self.info('starting up')
-
self.settings = GlobalSettings()
self.threads = ThreadMaster()
self.effects = EffectsHandler()
self.system = getSystem()
- self.current_project = None
- self.projectManager = ProjectManager(self)
- self._connectToProjectManager(self.projectManager)
-
self.action_log = UndoableActionLog()
self.debug_action_log_observer = DebugActionLogObserver()
self.debug_action_log_observer.startObserving(self.action_log)
- # TODO reimplement the observing after GES port
- #self.timelineLogObserver = TimelineLogObserver(self.action_log)
- self.projectLogObserver = ProjectLogObserver(self.action_log)
+ self.project_log_observer = ProjectLogObserver(self.action_log)
+
+ self.project_manager.connect("new-project-loaded", self._newProjectLoaded)
+ self.project_manager.connect("project-closed", self._projectClosed)
- self._version_information = {}
self._checkVersion()
+ def activateCb(self, unused_app):
+ if self.gui:
+ # The app is already started and the window already created.
+ # Present the already existing window.
+ # TODO: Use present() instead of present_with_time() when
+ # https://bugzilla.gnome.org/show_bug.cgi?id=688830 is fixed.
+ x11_server_time = GdkX11.x11_get_server_time(self.gui.get_window())
+ self.gui.present_with_time(x11_server_time)
+ # No need to show the welcome wizard.
+ return
+ self.createMainWindow()
+ self.welcome_wizard = StartUpWizard(self)
+ self.welcome_wizard.show()
+
+ def createMainWindow(self):
+ if self.gui:
+ return
+ self.gui = PitiviMainWindow(self)
+ self.add_window(self.gui)
+ # We might as well show it.
+ self.gui.show()
+
+ def openCb(self, unused_app, giofiles, unused_count, unused_hint):
+ assert giofiles
+ self.createMainWindow()
+ if len(giofiles) > 1:
+ self.warning("Can open only one project file at a time. Ignoring the rest!")
+ project_file = giofiles[0]
+ self.project_manager.loadProject(quote_uri(project_file.get_uri()))
+ return True
+
def shutdown(self):
"""
Close Pitivi.
@@ -133,56 +143,32 @@ class Pitivi(Loggable, Signallable):
@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_project and not self.projectManager.closeRunningProject():
+ # Refuse to close if we are not done with the current project.
+ if not self.project_manager.closeRunningProject():
self.warning("Not closing since running project doesn't want to close")
return False
+ if self.welcome_wizard:
+ self.welcome_wizard.hide()
+ if self.gui:
+ self.gui.destroy()
self.threads.stopAllThreads()
self.settings.storeSettings()
- self.current_project = None
- self.emit("shutdown")
+ self.quit()
return True
- def _connectToProjectManager(self, projectManager):
- pm = projectManager
- pm.connect("new-project-loading", self._projectManagerNewProjectLoading)
- pm.connect("new-project-created", self._projectManagerNewProjectCreated)
- pm.connect("new-project-loaded", self._projectManagerNewProjectLoaded)
- pm.connect("new-project-failed", self._projectManagerNewProjectFailed)
- pm.connect("project-closed", self._projectManagerProjectClosed)
-
- def _projectManagerNewProjectLoading(self, unused_project_manager, uri):
- self.emit("new-project-loading", uri)
-
- def _projectManagerNewProjectCreated(self, unused_project_manager, project):
- self.current_project = project
- self.emit("new-project-created", project)
-
- def _newProjectLoaded(self, unused_project):
- pass
-
- def _projectManagerNewProjectLoaded(self, unused_project_manager, project, unused_fully_loaded):
- self.current_project = project
+ def _newProjectLoaded(self, unused_project_manager, project, unused_fully_loaded):
self.action_log.clean()
- #self.timelineLogObserver.startObserving(project.timeline)
- self.projectLogObserver.startObserving(project)
- self._newProjectLoaded(project)
- self.emit("new-project-loaded", project)
-
- def _projectManagerNewProjectFailed(self, unused_project_manager, uri, exception):
- self.emit("new-project-failed", uri, exception)
+ self.project_log_observer.startObserving(project)
- def _projectManagerProjectClosed(self, unused_project_manager, project):
- #self.timelineLogObserver.stopObserving(project.timeline)
- self.projectLogObserver.stopObserving(project)
- self.current_project = None
- self.emit("project-closed", project)
+ def _projectClosed(self, unused_project_manager, project):
+ self.project_log_observer.stopObserving(project)
def _checkVersion(self):
- # Check online for release versions information
+ """
+ Check online for release versions information.
+ """
+ self.info("Requesting version information async")
giofile = Gio.File.new_for_uri(RELEASES_URL)
- self.info("Requesting version information")
giofile.load_contents_async(None, self._versionInfoReceivedCb, None)
def _versionInfoReceivedCb(self, giofile, result, user_data):
@@ -230,188 +216,3 @@ class Pitivi(Loggable, Signallable):
Get the latest version of the app or None.
"""
return self._version_information.get("current")
-
-
-class InteractivePitivi(Pitivi):
- """
- Base class to launch interactive Pitivi
- """
-
- def __init__(self, debug=False):
- Pitivi.__init__(self)
- self.mainloop = GLib.MainLoop()
- self.gui = None
- if debug:
- sys.excepthook = self._excepthook
-
- def _excepthook(self, unused_exc_type, unused_value, tback):
- import traceback
- import pdb
- traceback.print_tb(tback)
- pdb.post_mortem(tback)
-
- def run(self):
- """Runs the main loop."""
- self.mainloop.run()
-
-
-class GuiPitivi(InteractivePitivi):
- """
- Base class to launch a Pitivi instance with a graphical user interface
-
- This is called when we start the UI with a project passed as a parameter.
- It is also called by StartupWizardGuiPitivi.
- """
-
- def __init__(self, debug=False):
- InteractivePitivi.__init__(self, debug)
- self._showGui()
-
- def _showStartupError(self, message, detail):
- dialog = Gtk.MessageDialog(message_type=Gtk.MessageType.ERROR,
- buttons=Gtk.ButtonsType.OK)
- dialog.set_markup("<b>" + message + "</b>")
- dialog.format_secondary_text(detail)
- dialog.run()
-
- def _createGui(self):
- """Returns a Gtk.Widget which represents the UI."""
- return PitiviMainWindow(self)
-
- def _showGui(self):
- """Creates and shows the UI."""
- self.gui = self._createGui()
- self.gui.show()
-
- def shutdown(self):
- if Pitivi.shutdown(self):
- self.gui.destroy()
- self.mainloop.quit()
- return True
- return False
-
-
-class ProjectCreatorGuiPitivi(GuiPitivi):
- """
- Creates an instance of Pitivi with the UI and loading a list
- of clips, adding them to the timeline or not
- """
-
- def __init__(self, media_filenames, add_to_timeline=False, debug=False):
- GuiPitivi.__init__(self, debug)
- # load the passed filenames, optionally adding them to the timeline
- # (useful during development)
- self.projectManager.newBlankProject(emission=False)
- uris = [quote_uri(os.path.abspath(media_filename))
- for media_filename in media_filenames]
- lib = self.current_project.medialibrary
- lib.connect("source-added", self._sourceAddedCb, uris, add_to_timeline)
- lib.connect("discovery-error", self._discoveryErrorCb, uris)
- lib.addUris(uris)
-
- def _sourceAddedCb(self, unused_media_library, info, startup_uris, add_to_timeline):
- if self._maybePopStartupUri(startup_uris, info.get_uri()) \
- and add_to_timeline:
- self.action_log.begin("add clip")
- src = GES.UriClip(uri=info.get_uri())
- src.set_property("priority", 1)
- self.current_project.timeline.get_layers()[0].add_clip(src)
- self.action_log.commit()
-
- def _discoveryErrorCb(self, unused_media_library, uri, unused_error, unused_debug, startup_uris):
- self._maybePopStartupUri(startup_uris, uri)
-
- def _maybePopStartupUri(self, startup_uris, uri):
- try:
- startup_uris.remove(uri)
- except ValueError:
- # uri is not a startup uri. This can happen if the user starts
- # importing sources while sources specified at startup are still
- # being processed. In practice this will never happen.
- return False
-
- if not startup_uris:
- self.current_project.medialibrary.disconnect_by_function(self._sourceAddedCb)
- self.current_project.medialibrary.disconnect_by_function(self._discoveryErrorCb)
-
- return True
-
-
-class ProjectLoaderGuiPitivi(GuiPitivi):
- """
- Creates an instance of the UI and loads @project_filename
- """
-
- def __init__(self, project_filename, debug=False):
- GuiPitivi.__init__(self, debug)
- if not os.path.exists(project_filename):
- self.error("Project file does not exist: %s" % project_filename)
- sys.exit(1)
- self.projectManager.loadProject(quote_uri(os.path.abspath(project_filename)))
-
-
-class StartupWizardGuiPitivi(GuiPitivi):
- """
- Creates an instance of the Pitivi UI with the welcome dialog
-
- This is not called when a project is passed as a parameter.
- """
-
- def __init__(self, debug=False):
- GuiPitivi.__init__(self, debug)
- self.projectManager.newBlankProject(emission=False)
-
- def _createGui(self):
- return PitiviMainWindow(self)
-
- def _showGui(self):
- GuiPitivi._showGui(self)
- self.wizard = StartUpWizard(self)
- self.wizard.show()
-
-
-def _parse_options(argv):
- parser = OptionParser(
- usage=_("""
- %prog [PROJECT_FILE] # Start the video editor.
- %prog -i [-a] [MEDIA_FILE1 ...] # Start the editor and create a project."""))
-
- parser.add_option("-i", "--import", dest="import_sources",
- action="store_true", default=False,
- help=_("Import each MEDIA_FILE into a new project."))
- parser.add_option("-a", "--add-to-timeline",
- action="store_true", default=False,
- help=_("Add each imported MEDIA_FILE to the timeline."))
- parser.add_option("-d", "--debug",
- action="store_true", default=False,
- help=_("Run Pitivi in the Python Debugger."))
- options, args = parser.parse_args(argv[1:])
-
- # Validate options.
- if options.add_to_timeline and not options.import_sources:
- parser.error(_("-a requires -i"))
-
- # Validate args.
- if options.import_sources:
- # When no MEDIA_FILE is specified, we just create a new project.
- pass
- else:
- if len(args) > 1:
- parser.error(_("Cannot open more than one PROJECT_FILE"))
-
- return options, args
-
-
-def main(argv):
- options, args = _parse_options(argv)
- if options.import_sources:
- ptv = ProjectCreatorGuiPitivi(media_filenames=args,
- add_to_timeline=options.add_to_timeline,
- debug=options.debug)
- else:
- if args:
- ptv = ProjectLoaderGuiPitivi(project_filename=args[0],
- debug=options.debug)
- else:
- ptv = StartupWizardGuiPitivi(debug=options.debug)
- ptv.run()
diff --git a/pitivi/clipproperties.py b/pitivi/clipproperties.py
index 8d90c8f..f234363 100644
--- a/pitivi/clipproperties.py
+++ b/pitivi/clipproperties.py
@@ -144,7 +144,7 @@ class EffectProperties(Gtk.Expander, Loggable):
# Note: This should be inherited from Gtk.Expander when we get other things
# to put in ClipProperties, that is why this is done this way
- def __init__(self, instance, effects_properties_manager, clip_properties):
+ def __init__(self, app, effects_properties_manager, clip_properties):
# Set up the expander widget that will contain everything:
Gtk.Expander.__init__(self)
self.set_expanded(True)
@@ -152,8 +152,8 @@ class EffectProperties(Gtk.Expander, Loggable):
Loggable.__init__(self)
# Global variables related to effects
- self.app = instance
- self.settings = instance.settings
+ self.app = app
+ self.settings = app.settings
self.selected_effects = []
self.clips = []
@@ -244,11 +244,11 @@ class EffectProperties(Gtk.Expander, Loggable):
self.treeview.connect("query-tooltip", self._treeViewQueryTooltipCb)
self._vcontent.connect("notify", self._vcontentNotifyCb)
removeEffectButton.connect("clicked", self._removeEffectCb)
- self.app.connect("new-project-loaded", self._newProjectLoadedCb)
+ self.app.project_manager.connect("new-project-loaded", self._newProjectLoadedCb)
self.connect('notify::expanded', self._expandedCb)
self.connected = False
- def _newProjectLoadedCb(self, app, project):
+ def _newProjectLoadedCb(self, app, project, unused_fully_loaded):
self.clip_properties.project = project
self.selected_effects = self.timeline.selection.getSelectedEffects()
self.updateAll()
@@ -337,9 +337,9 @@ class EffectProperties(Gtk.Expander, Loggable):
effect = GES.Effect.new(bin_description=bin_desc)
clip.add(effect)
self.updateAll()
- self.app.current_project.timeline.commit()
+ self.app.project_manager.current_project.timeline.commit()
self.app.action_log.commit()
- self.app.current_project.pipeline.flushSeek()
+ self.app.project_manager.current_project.pipeline.flushSeek()
break
@@ -371,7 +371,7 @@ class EffectProperties(Gtk.Expander, Loggable):
tck_effect.set_active(not tck_effect.is_active())
cellrenderertoggle.set_active(tck_effect.is_active())
self._updateTreeview()
- self.app.current_project.timeline.commit()
+ self.app.project_manager.current_project.timeline.commit()
self.app.action_log.commit()
def _expandedCb(self, expander, params):
@@ -579,7 +579,7 @@ class TransformationProperties(Gtk.Expander):
box.update_from_effect(self.effect)
def _flushPipeLineCb(self, widget):
- self.app.current_project.pipeline.flushSeek()
+ self.app.project_manager.current_project.pipeline.flushSeek()
def _findEffect(self, name):
for effect in self._selected_clip.get_children(False):
@@ -593,7 +593,7 @@ class TransformationProperties(Gtk.Expander):
if not effect:
effect = GES.Effect.new(bin_description=name)
self._selected_clip.add(effect)
- tracks = self.app.projectManager.current_project.timeline.get_tracks()
+ tracks = self.app.project_manager.current_project.timeline.get_tracks()
effect = self._findEffect(name)
# disable the effect on default
a = self.effect.get_gnlobject()
@@ -620,7 +620,7 @@ class TransformationProperties(Gtk.Expander):
if self._selected_clip:
self._selected_clip = None
self.zoom_scale.set_value(1.0)
- self.app.current_project.pipeline.flushSeek()
+ self.app.project_manager.current_project.pipeline.flushSeek()
self.effect = None
self.hide()
self._updateBoxVisibility()
diff --git a/pitivi/dialogs/startupwizard.py b/pitivi/dialogs/startupwizard.py
index 2691f34..8ed3828 100644
--- a/pitivi/dialogs/startupwizard.py
+++ b/pitivi/dialogs/startupwizard.py
@@ -1,4 +1,3 @@
-""" This module implements a startup wizard"""
# Pitivi video editor
#
# pitivi/dialogs/startupwizard.py
@@ -28,9 +27,9 @@ from gi.repository import GES
from gettext import gettext as _
+from pitivi.check import missing_soft_deps
from pitivi.configure import get_ui_dir
from pitivi.dialogs.depsmanager import DepsManager
-from pitivi.check import missing_soft_deps
from pitivi.utils.misc import show_user_manual
@@ -79,9 +78,10 @@ class StartUpWizard(object):
if not missing_soft_deps:
missing_button.hide()
- self.app.projectManager.connect("new-project-failed", self._projectFailedCb)
- self.app.projectManager.connect("new-project-loaded", self._projectLoadedCb)
- self.app.projectManager.connect("new-project-loading", self._projectLoadingCb)
+ project_manager = self.app.project_manager
+ project_manager.connect("new-project-failed", self._projectFailedCb)
+ project_manager.connect("new-project-loaded", self._projectLoadedCb)
+ project_manager.connect("new-project-loading", self._projectLoadingCb)
vbox = self.builder.get_object("topvbox")
self.infobar = Gtk.InfoBar()
@@ -93,7 +93,8 @@ class StartUpWizard(object):
def _newProjectCb(self, unused_button):
"""Handle a click on the New (Project) button."""
- self.app.projectManager.newBlankProject()
+ self.app.project_manager.newBlankProject()
+ self.hide()
self.app.gui.showProjectSettingsDialog()
def _loadCb(self, unused_recent_chooser):
@@ -102,13 +103,14 @@ class StartUpWizard(object):
This calls the project manager to load the associated URI.
"""
uri = self.recent_chooser.get_current_uri()
- self.app.projectManager.loadProject(uri)
+ self.app.project_manager.loadProject(uri)
def _keyPressCb(self, unused_widget, event):
"""Handle a key press event on the dialog."""
if event.keyval == Gdk.KEY_Escape:
# The user pressed "Esc".
- self.app.projectManager.newBlankProject()
+ self.app.project_manager.newBlankProject()
+ self.hide()
def _onBrowseButtonClickedCb(self, unused_button6):
"""Handle a click on the Browse button."""
@@ -120,7 +122,8 @@ class StartUpWizard(object):
def _deleteCb(self, unused_widget, unused_event):
"""Handle a click on the X button of the dialog."""
- self.app.projectManager.newBlankProject()
+ self.app.project_manager.newBlankProject()
+ self.hide()
def show(self):
"""Will show the interal window and position the wizard"""
@@ -137,16 +140,16 @@ class StartUpWizard(object):
"""Handle the failure of a project open operation."""
self.show()
- def _projectLoadedCb(self, unused_project_manager, unused_project, fully_loaded):
- """Handle the success of a project load operation.
+ def _projectLoadedCb(self, project_manager, unused_project, fully_loaded):
+ """
+ Handle the success of a project load operation.
- All the create or load project usage scenarios must generate
- a new-project-loaded signal from self.app.projectManager!
+ @type project_manager: L{ProjectManager}
"""
if fully_loaded:
- self.app.projectManager.disconnect_by_function(self._projectFailedCb)
- self.app.projectManager.disconnect_by_function(self._projectLoadedCb)
- self.app.projectManager.disconnect_by_function(self._projectLoadingCb)
+ project_manager.disconnect_by_function(self._projectFailedCb)
+ project_manager.disconnect_by_function(self._projectLoadedCb)
+ project_manager.disconnect_by_function(self._projectLoadingCb)
def _projectLoadingCb(self, unused_project_manager, unused_project):
"""Handle the start of a project load operation."""
diff --git a/pitivi/effects.py b/pitivi/effects.py
index 89336fd..ebc49b4 100644
--- a/pitivi/effects.py
+++ b/pitivi/effects.py
@@ -609,12 +609,15 @@ PROPS_TO_IGNORE = ['name', 'qos', 'silent', 'message']
class EffectsPropertiesManager:
- def __init__(self, instance):
+ """
+ @type app: L{Pitivi}
+ """
+ def __init__(self, app):
self.cache_dict = {}
self._current_effect_setting_ui = None
self._current_element_values = {}
- self.action_log = instance.action_log
- self.app = instance
+ self.action_log = app.action_log
+ self.app = app
def getEffectConfigurationUI(self, effect):
"""Permit to get a configuration GUI for the effect
@@ -681,5 +684,5 @@ class EffectsPropertiesManager:
self._current_effect_setting_ui.element.set_child_property(prop.name, value)
self.action_log.commit()
- self.app.current_project.pipeline.flushSeek()
+ self.app.project_manager.current_project.pipeline.flushSeek()
self._current_element_values[prop.name] = value
diff --git a/pitivi/mainwindow.py b/pitivi/mainwindow.py
index d70ad64..23d2a26 100644
--- a/pitivi/mainwindow.py
+++ b/pitivi/mainwindow.py
@@ -176,7 +176,7 @@ class PitiviMainWindow(Gtk.Window, Loggable):
self.recent_manager = Gtk.RecentManager()
self._missingUriOnLoading = False
- pm = self.app.projectManager
+ pm = self.app.project_manager
pm.connect("new-project-loading", self._projectManagerNewProjectLoadingCb)
pm.connect("new-project-loaded", self._projectManagerNewProjectLoadedCb)
pm.connect("new-project-failed", self._projectManagerNewProjectFailedCb)
@@ -212,7 +212,7 @@ class PitiviMainWindow(Gtk.Window, Loggable):
self.timeline_ui.enableKeyboardAndMouseEvents()
def _renderCb(self, unused_button):
- self.showRenderDialog(self.app.current_project)
+ self.showRenderDialog(self.app.project_manager.current_project)
def _createUi(self):
"""
@@ -297,7 +297,7 @@ class PitiviMainWindow(Gtk.Window, Loggable):
# Now, the lower part: the timeline
self.timeline_ui = TimelineContainer(self, self.app, self.uimanager)
- self.timeline_ui.setProjectManager(self.app.projectManager)
+ self.timeline_ui.setProjectManager(self.app.project_manager)
self.vpaned.pack2(self.timeline_ui, resize=True, shrink=False)
# Enable our shortcuts for HeaderBar buttons and menu items:
@@ -502,33 +502,33 @@ class PitiviMainWindow(Gtk.Window, Loggable):
## Toolbar/Menu actions callback
def _newProjectMenuCb(self, unused_action):
- if self.app.projectManager.newBlankProject() is not False:
+ if self.app.project_manager.newBlankProject() is not False:
self.showProjectSettingsDialog()
def _openProjectCb(self, unused_action):
self.openProject()
def _saveProjectCb(self, unused_action):
- if not self.app.current_project.uri or self.app.projectManager.disable_save is True:
+ if not self.app.project_manager.current_project.uri or self.app.project_manager.disable_save:
self._saveProjectAsCb(unused_action)
else:
- self.app.projectManager.saveProject()
+ self.app.project_manager.saveProject()
def _saveProjectAsCb(self, unused_action):
- uri = self._showSaveAsDialog(self.app.current_project)
+ uri = self._showSaveAsDialog(self.app.project_manager.current_project)
if uri is not None:
- return self.app.projectManager.saveProject(uri)
+ return self.app.project_manager.saveProject(uri)
return False
def _revertToSavedProjectCb(self, unused_action):
- return self.app.projectManager.revertToSavedProject()
+ return self.app.project_manager.revertToSavedProject()
def _exportProjectAsTarCb(self, unused_action):
- uri = self._showExportDialog(self.app.current_project)
+ uri = self._showExportDialog(self.app.project_manager.current_project)
result = None
if uri:
- result = self.app.projectManager.exportProject(self.app.current_project, uri)
+ result = self.app.project_manager.exportProject(self.app.project_manager.current_project, uri)
if not result:
self.log("Project couldn't be exported")
@@ -539,7 +539,7 @@ class PitiviMainWindow(Gtk.Window, Loggable):
def showProjectSettingsDialog(self):
from pitivi.project import ProjectSettingsDialog
- ProjectSettingsDialog(self, self.app.current_project).window.run()
+ ProjectSettingsDialog(self, self.app.project_manager.current_project).window.run()
self.updateTitle()
def _userManualCb(self, unused_action):
@@ -605,7 +605,7 @@ class PitiviMainWindow(Gtk.Window, Loggable):
# Requesting project closure at this point in time prompts users about
# unsaved changes (if any); much better than having ProjectManager
# trigger this *after* the user already chose a new project to load...
- if not self.app.projectManager.closeRunningProject():
+ if not self.app.project_manager.closeRunningProject():
return # The user has not made a decision, don't do anything
chooser = Gtk.FileChooserDialog(title=_("Open File..."),
@@ -630,10 +630,10 @@ class PitiviMainWindow(Gtk.Window, Loggable):
response = chooser.run()
if response == Gtk.ResponseType.OK:
- self.app.projectManager.loadProject(chooser.get_uri())
+ self.app.project_manager.loadProject(chooser.get_uri())
else:
self.info("User cancelled loading a new project, but no other project is currently active.
Resetting")
- self.app.projectManager.newBlankProject()
+ self.app.project_manager.newBlankProject()
chooser.destroy()
return True
@@ -656,16 +656,16 @@ class PitiviMainWindow(Gtk.Window, Loggable):
self.prefsdialog.run()
## Project management callbacks
- def _projectManagerNewProjectLoadedCb(self, projectManager, unused_project, unused_fully_loaded):
+
+ def _projectManagerNewProjectLoadedCb(self, project_manager, unused_project, unused_fully_loaded):
"""
- Once a new project has been loaded, wait for media library's
- "ready" signal to populate the timeline.
+ @type project_manager: L{ProjectManager}
"""
self.log("A new project is loaded")
- self._connectToProject(self.app.current_project)
- self.app.current_project.timeline.connect("notify::duration",
+ self._connectToProject(self.app.project_manager.current_project)
+ self.app.project_manager.current_project.timeline.connect("notify::duration",
self._timelineDurationChangedCb)
- self.app.current_project.pipeline.activatePositionListener()
+ self.app.project_manager.current_project.pipeline.activatePositionListener()
self._setProject()
#FIXME GES we should re-enable this when possible
@@ -673,16 +673,16 @@ class PitiviMainWindow(Gtk.Window, Loggable):
self.updateTitle()
if self._missingUriOnLoading:
- self.app.current_project.setModificationState(True)
+ self.app.project_manager.current_project.setModificationState(True)
self.save_button.set_sensitive(True)
self._missingUriOnLoading = False
- if projectManager.disable_save is True:
+ if project_manager.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.save_button.set_sensitive(True)
- if self.app.current_project.timeline.props.duration != 0:
+ if self.app.project_manager.current_project.timeline.props.duration != 0:
self.render_button.set_sensitive(True)
def _projectManagerNewProjectLoadingCb(self, unused_project_manager, uri):
@@ -718,11 +718,15 @@ class PitiviMainWindow(Gtk.Window, Loggable):
if project.uri is None:
project.uri = uri
- def _projectManagerClosingProjectCb(self, projectManager, project):
+ def _projectManagerClosingProjectCb(self, project_manager, project):
+ """
+ @type project_manager: L{ProjectManager}
+ @type project: L{Project}
+ """
if not project.hasUnsavedModifications():
return True
- if project.uri and projectManager.disable_save is False:
+ if project.uri and not project_manager.disable_save:
save = Gtk.STOCK_SAVE
else:
save = Gtk.STOCK_SAVE_AS
@@ -755,7 +759,7 @@ class PitiviMainWindow(Gtk.Window, Loggable):
if project.uri:
path = unquote(project.uri).split("file://")[1]
- last_saved = max(os.path.getmtime(path), projectManager.time_loaded)
+ last_saved = max(os.path.getmtime(path), project_manager.time_loaded)
time_delta = time() - last_saved
secondary.props.label = _("If you don't save, "
"the changes from the last %s will be lost."
@@ -785,8 +789,8 @@ class PitiviMainWindow(Gtk.Window, Loggable):
response = dialog.run()
dialog.destroy()
if response == Gtk.ResponseType.YES:
- if project.uri is not None and projectManager.disable_save is False:
- res = self.app.projectManager.saveProject()
+ if project.uri is not None and project_manager.disable_save is False:
+ res = self.app.project_manager.saveProject()
else:
res = self._saveProjectAsCb(None)
elif response == Gtk.ResponseType.REJECT:
@@ -815,7 +819,7 @@ class PitiviMainWindow(Gtk.Window, Loggable):
return False
def _projectManagerRevertingToSavedCb(self, unused_project_manager, unused_project):
- if self.app.current_project.hasUnsavedModifications():
+ if self.app.project_manager.current_project.hasUnsavedModifications():
dialog = Gtk.MessageDialog(transient_for=self,
modal=True,
message_type=Gtk.MessageType.WARNING,
@@ -929,7 +933,7 @@ class PitiviMainWindow(Gtk.Window, Loggable):
if response == Gtk.ResponseType.OK:
self.log("User chose a new URI for the missing file")
new_uri = chooser.get_uri()
- self.app.current_project.setModificationState(False)
+ self.app.project_manager.current_project.setModificationState(False)
else:
# Even if the user clicks Cancel, the discoverer keeps trying to
# import the rest of the clips...
@@ -937,22 +941,22 @@ class PitiviMainWindow(Gtk.Window, Loggable):
# this async operation, or the filechooser will keep showing up
# and all sorts of weird things will happen.
# TODO: bugs #661059, 609136
- attempted_uri = self.app.current_project.uri
+ attempted_uri = self.app.project_manager.current_project.uri
reason = _('No replacement file was provided for "<i>%s</i>".\n\n'
'Pitivi does not currently support partial projects.'
% info_name(asset))
# Put an end to the async signals spamming us with dialogs:
- self.app.projectManager.disconnect_by_func(self._projectManagerMissingUriCb)
+ self.app.project_manager.disconnect_by_func(self._projectManagerMissingUriCb)
# Don't overlap the file chooser with our error dialog
# The chooser will be destroyed further below, so let's hide it now.
dialog.hide()
# Reset projectManager and disconnect all the signals:
- self.app.projectManager.newBlankProject(ignore_unsaved_changes=True)
+ self.app.project_manager.newBlankProject(ignore_unsaved_changes=True)
# Force the project load to fail:
# This will show an error using _projectManagerNewProjectFailedCb
# You have to do this *after* successfully creating a blank project,
# or the startupwizard will still be connected to that signal too.
- self.app.projectManager.emit("new-project-failed", attempted_uri, reason)
+ self.app.project_manager.emit("new-project-failed", attempted_uri, reason)
dialog.destroy()
return new_uri
@@ -986,9 +990,9 @@ class PitiviMainWindow(Gtk.Window, Loggable):
dirty = action_log.dirty()
self.save_button.set_sensitive(dirty)
- if self.app.current_project.uri is not None:
+ if self.app.project_manager.current_project.uri is not None:
self._menubutton_items["menu_revert_to_saved"].set_sensitive(dirty)
- self.app.current_project.setModificationState(dirty)
+ self.app.project_manager.current_project.setModificationState(dirty)
can_redo = bool(action_log.redo_stacks)
self.redo_button.set_sensitive(can_redo)
@@ -1000,28 +1004,28 @@ class PitiviMainWindow(Gtk.Window, Loggable):
"""
Disconnect and reconnect callbacks to the new current project
"""
- if not self.app.current_project:
+ if not self.app.project_manager.current_project:
self.warning("Current project instance does not exist")
return False
try:
- self.app.current_project.disconnect_by_func(self._renderingSettingsChangedCb)
+ self.app.project_manager.current_project.disconnect_by_func(self._renderingSettingsChangedCb)
except TypeError:
# When loading the first project, the signal has never been
# connected before.
pass
- self.app.current_project.connect("rendering-settings-changed", self._renderingSettingsChangedCb)
+ self.app.project_manager.current_project.connect("rendering-settings-changed",
self._renderingSettingsChangedCb)
- self.viewer.setPipeline(self.app.current_project.pipeline)
- self._renderingSettingsChangedCb(self.app.current_project)
+ self.viewer.setPipeline(self.app.project_manager.current_project.pipeline)
+ self._renderingSettingsChangedCb(self.app.project_manager.current_project)
if self.timeline_ui:
- self.clipconfig.project = self.app.current_project
+ self.clipconfig.project = self.app.project_manager.current_project
#FIXME GES port undo/redo
- #self.app.timelineLogObserver.pipeline = self.app.current_project.pipeline
+ #self.app.timelineLogObserver.pipeline = self.app.project_manager.current_project.pipeline
# When creating a blank project, medialibrary will eventually trigger
# this _setProject method, but there's no project URI yet.
- if self.app.current_project.uri:
- folder_path = os.path.dirname(path_from_uri(self.app.current_project.uri))
+ if self.app.project_manager.current_project.uri:
+ folder_path = os.path.dirname(path_from_uri(self.app.project_manager.current_project.uri))
self.settings.lastProjectFolder = folder_path
def _renderingSettingsChangedCb(self, project, unused_item=None, unused_value=None):
@@ -1139,7 +1143,7 @@ class PitiviMainWindow(Gtk.Window, Loggable):
foo = self._showSaveScreenshotDialog()
if foo:
path, mime = foo[0], foo[1]
- self.app.current_project.pipeline.save_thumbnail(-1, -1, mime, path)
+ self.app.project_manager.current_project.pipeline.save_thumbnail(-1, -1, mime, path)
def _showSaveScreenshotDialog(self):
"""
@@ -1178,12 +1182,12 @@ class PitiviMainWindow(Gtk.Window, Loggable):
def updateTitle(self):
name = touched = ""
- if self.app.current_project:
- if self.app.current_project.name:
- name = self.app.current_project.name
+ if self.app.project_manager.current_project:
+ if self.app.project_manager.current_project.name:
+ name = self.app.project_manager.current_project.name
else:
name = _("Untitled")
- if self.app.current_project.hasUnsavedModifications():
+ if self.app.project_manager.current_project.hasUnsavedModifications():
touched = "*"
title = "%s%s — %s" % (touched, name, APPNAME)
self._headerbar.set_title(title)
diff --git a/pitivi/medialibrary.py b/pitivi/medialibrary.py
index e48b856..9e06637 100644
--- a/pitivi/medialibrary.py
+++ b/pitivi/medialibrary.py
@@ -137,6 +137,7 @@ class MediaLibraryWidget(Gtk.VBox, Loggable):
builder.connect_signals(self)
self._welcome_infobar = builder.get_object("welcome_infobar")
self._import_warning_infobar = builder.get_object("warning_infobar")
+ self._import_warning_infobar.hide()
self._warning_label = builder.get_object("warning_label")
self._view_error_button = builder.get_object("view_error_button")
toolbar = builder.get_object("medialibrary_toolbar")
@@ -252,9 +253,10 @@ class MediaLibraryWidget(Gtk.VBox, Loggable):
# Connect to project. We must remove and reset the callbacks when
# changing project.
self.project_signals = SignalGroup()
- self.app.connect("new-project-created", self._newProjectCreatedCb)
- self.app.connect("new-project-loaded", self._newProjectLoadedCb)
- self.app.connect("new-project-failed", self._newProjectFailedCb)
+ project_manager = self.app.project_manager
+ project_manager.connect("new-project-created", self._newProjectCreatedCb)
+ project_manager.connect("new-project-loaded", self._newProjectLoadedCb)
+ project_manager.connect("new-project-failed", self._newProjectFailedCb)
# Drag and Drop
self.drag_dest_set(Gtk.DestDefaults.DROP | Gtk.DestDefaults.MOTION,
@@ -499,8 +501,8 @@ class MediaLibraryWidget(Gtk.VBox, Loggable):
# The clip iter has a +1 offset in the progressbar label (to refer to
# the actual # of the clip we're processing), but there is no offset
# in the progressbar itself (to reflect the process being incomplete).
- current_clip_iter = self.app.current_project.nb_imported_files
- total_clips = self.app.current_project.nb_remaining_file_to_import + current_clip_iter
+ current_clip_iter = self.app.project_manager.current_project.nb_imported_files
+ total_clips = self.app.project_manager.current_project.nb_remaining_file_to_import +
current_clip_iter
progressbar_text = _("Importing clip %(current_clip)d of %(total)d" %
{"current_clip": current_clip_iter + 1,
@@ -727,7 +729,7 @@ class MediaLibraryWidget(Gtk.VBox, Loggable):
self.app.settings.closeImportDialog = \
dialogbox.props.extra_widget.get_active()
filenames = dialogbox.get_uris()
- self.app.current_project.addUris(filenames)
+ self.app.project_manager.current_project.addUris(filenames)
if self.app.settings.closeImportDialog:
dialogbox.destroy()
self._importDialog = None
@@ -757,12 +759,12 @@ class MediaLibraryWidget(Gtk.VBox, Loggable):
self.app.action_log.begin("remove clip from source list")
for row in rows:
asset = model[row.get_path()][COL_ASSET]
- self.app.current_project.remove_asset(asset)
+ self.app.project_manager.current_project.remove_asset(asset)
self.app.action_log.commit()
def _sourceIsUsed(self, asset):
"""Check if a given URI is present in the timeline"""
- layers = self.app.current_project.timeline.get_layers()
+ layers = self.app.project_manager.current_project.timeline.get_layers()
for layer in layers:
for clip in layer.get_clips():
if clip.get_asset() == asset:
@@ -773,7 +775,7 @@ class MediaLibraryWidget(Gtk.VBox, Loggable):
"""
Select, in the media library, unused sources in the project.
"""
- assets = self.app.current_project.list_assets(GES.UriClip)
+ assets = self.app.project_manager.current_project.list_assets(GES.UriClip)
unused_sources_uris = []
model = self.treeview.get_model()
@@ -814,7 +816,7 @@ class MediaLibraryWidget(Gtk.VBox, Loggable):
# Only use the first item.
path = paths[0]
asset = self.storemodel[path][COL_ASSET]
- dialog = ClipMediaPropsDialog(self.app.current_project, asset)
+ dialog = ClipMediaPropsDialog(self.app.project_manager.current_project, asset)
dialog.run()
def _warningInfoBarDismissedCb(self, unused_button):
@@ -998,7 +1000,7 @@ class MediaLibraryWidget(Gtk.VBox, Loggable):
self._welcome_infobar.show_all()
self._connectToProject(project)
- def _newProjectLoadedCb(self, unused_pitivi, project):
+ def _newProjectLoadedCb(self, unused_app, project, unused_fully_ready):
if not self._project is project:
self._project = project
self.storemodel.clear()
@@ -1013,8 +1015,8 @@ class MediaLibraryWidget(Gtk.VBox, Loggable):
self._project = None
def _addUris(self, uris):
- if self.app.current_project:
- self.app.current_project.addUris(uris)
+ if self.app.project_manager.current_project:
+ self.app.project_manager.current_project.addUris(uris)
else:
self.warning("Adding uris to project, but the project has changed in the meantime")
return False
@@ -1049,7 +1051,7 @@ class MediaLibraryWidget(Gtk.VBox, Loggable):
# Recursively import from folders that were dragged into the library
self.app.threads.addThread(PathWalker, directories, self._addUris)
if filenames:
- self.app.current_project.addUris(filenames)
+ self.app.project_manager.current_project.addUris(filenames)
#used with TreeView and IconView
def _dndDragDataGetCb(self, unused_view, unused_context, data, unused_info, unused_timestamp):
diff --git a/pitivi/project.py b/pitivi/project.py
index 7ebfe8c..a5b6461 100644
--- a/pitivi/project.py
+++ b/pitivi/project.py
@@ -106,6 +106,12 @@ class ProjectLogObserver(UndoableAction):
class ProjectManager(Signallable, Loggable):
+ """
+ @type app: L{Pitivi}
+ @type current_project: L{Project}
+ @param disable_save: Whether saving is disabled to enforce using save-as.
+ """
+
__signals__ = {
"new-project-loading": ["uri"],
"new-project-created": ["project"],
@@ -119,12 +125,14 @@ class ProjectManager(Signallable, Loggable):
"reverting-to-saved": ["project"],
}
- def __init__(self, app_instance):
+ _instance = None
+
+ def __init__(self, app):
Signallable.__init__(self)
Loggable.__init__(self)
- self.app = app_instance
+ self.app = app
self.current_project = None
- self.disable_save = False # Enforce "Save as" for backup and xptv files
+ self.disable_save = False
self._backup_lock = 0
def loadProject(self, uri):
@@ -176,7 +184,6 @@ class ProjectManager(Signallable, Loggable):
_('This might be due to a bug or an unsupported project file format. '
'If you were trying to add a media file to your project, '
'use the "Import" button instead.'))
- # Reset projectManager and disconnect all the signals:
self.newBlankProject(ignore_unsaved_changes=True)
return False
@@ -426,6 +433,7 @@ class ProjectManager(Signallable, Loggable):
self.emit("new-project-created", project)
project.connect("project-changed", self._projectChangedCb)
+ project.setModificationState(False)
self.emit("new-project-loaded", self.current_project, emission)
self.time_loaded = time()
@@ -499,7 +507,8 @@ class ProjectManager(Signallable, Loggable):
class Project(Loggable, GES.Project):
- """The base class for Pitivi projects
+ """
+ The base class for Pitivi projects
@ivar name: The name of the project
@type name: C{str}
diff --git a/pitivi/render.py b/pitivi/render.py
index dd19f69..4b76b39 100644
--- a/pitivi/render.py
+++ b/pitivi/render.py
@@ -726,7 +726,7 @@ class RenderDialog(Loggable):
return None
current_filesize = os.stat(path_from_uri(self.outfile)).st_size
- length = self.app.current_project.timeline.props.duration
+ length = self.app.project_manager.current_project.timeline.props.duration
estimated_size = float(current_filesize * float(length) / self.current_position)
# Now let's make it human-readable (instead of octets).
# If it's in the giga range (10⁹) instead of mega (10⁶), use 2 decimals
@@ -842,7 +842,7 @@ class RenderDialog(Loggable):
else:
self._time_spent_paused += time.time() - self._last_timestamp_when_pausing
self.debug("Resuming render after %d seconds in pause", self._time_spent_paused)
- self.app.current_project.pipeline.togglePlayback()
+ self.app.project_manager.current_project.pipeline.togglePlayback()
def _destroyProgressWindow(self):
""" Handle the completion or the cancellation of the render process. """
@@ -855,7 +855,7 @@ class RenderDialog(Loggable):
obj.disconnect(id)
self._gstSigId = {}
try:
- self.app.current_project.pipeline.disconnect_by_func(self._updatePositionCb)
+ self.app.project_manager.current_project.pipeline.disconnect_by_func(self._updatePositionCb)
except TypeError:
# The render was successful, so this was already disconnected
pass
@@ -914,7 +914,7 @@ class RenderDialog(Loggable):
bus = self._pipeline.get_bus()
bus.add_signal_watch()
self._gstSigId[bus] = bus.connect('message', self._busMessageCb)
- self.app.current_project.pipeline.connect("position", self._updatePositionCb)
+ self.app.project_manager.current_project.pipeline.connect("position", self._updatePositionCb)
# Force writing the config now, or the path will be reset
# if the user opens the rendering dialog again
self.app.settings.lastExportFolder = self.filebutton.get_current_folder()
@@ -937,7 +937,7 @@ class RenderDialog(Loggable):
return True # Do nothing until we resume rendering
elif self._is_rendering:
timediff = time.time() - self._time_started - self._time_spent_paused
- length = self.app.current_project.timeline.props.duration
+ length = self.app.project_manager.current_project.timeline.props.duration
totaltime = (timediff * float(length) / float(self.current_position)) - timediff
time_estimate = beautify_ETA(int(totaltime * Gst.SECOND))
if time_estimate:
@@ -1006,7 +1006,7 @@ class RenderDialog(Loggable):
if not self.progress or not position:
return
- length = self.app.current_project.timeline.props.duration
+ length = self.app.project_manager.current_project.timeline.props.duration
fraction = float(min(position, length)) / float(length)
self.progress.updatePosition(fraction)
diff --git a/pitivi/timeline/timeline.py b/pitivi/timeline/timeline.py
index 1d45786..b7d8b31 100644
--- a/pitivi/timeline/timeline.py
+++ b/pitivi/timeline/timeline.py
@@ -603,7 +603,7 @@ class TimelineStage(Clutter.ScrollActor, Zoomable, Loggable):
def _trackAddedCb(self, unused_timeline, track):
self._connectTrack(track)
- self._container.app.current_project.update_restriction_caps()
+ self._container.app.project_manager.current_project.update_restriction_caps()
def _trackRemovedCb(self, unused_timeline, track):
self._disconnectTrack(track)
diff --git a/pitivi/transitions.py b/pitivi/transitions.py
index 1d7cecc..8c7f9d6 100644
--- a/pitivi/transitions.py
+++ b/pitivi/transitions.py
@@ -161,7 +161,7 @@ class TransitionsListWidget(Signallable, Gtk.VBox, Loggable):
self.props_widgets.set_sensitive(True)
self.element.get_parent().set_asset(transition_asset)
- self.app.current_project.seeker.flush(True)
+ self.app.project_manager.current_project.seeker.flush(True)
return True
@@ -169,13 +169,13 @@ class TransitionsListWidget(Signallable, Gtk.VBox, Loggable):
value = range_changed.get_value()
self.debug("User changed the border property to %s", value)
self.element.set_border(int(value))
- self.app.current_project.seeker.flush(True)
+ self.app.project_manager.current_project.seeker.flush(True)
def _invertCheckboxCb(self, widget):
value = widget.get_active()
self.debug("User changed the invert property to %s", value)
self.element.set_inverted(value)
- self.app.current_project.seeker.flush()
+ self.app.project_manager.current_project.seeker.flush()
def _borderTypeChangedCb(self, widget=None):
"""
diff --git a/pitivi/viewer.py b/pitivi/viewer.py
index c994dc2..cf50299 100644
--- a/pitivi/viewer.py
+++ b/pitivi/viewer.py
@@ -309,7 +309,7 @@ class ViewerContainer(Gtk.VBox, Loggable):
self.target.renderbox()
def _playButtonCb(self, unused_button, unused_playing):
- self.app.current_project.pipeline.togglePlayback()
+ self.app.project_manager.current_project.pipeline.togglePlayback()
self.app.gui.focusTimeline()
def _goToStartCb(self, unused_button):
@@ -327,7 +327,7 @@ class ViewerContainer(Gtk.VBox, Loggable):
self.app.gui.focusTimeline()
def _goToEndCb(self, unused_button):
- end = self.app.current_project.pipeline.getDuration()
+ end = self.app.project_manager.current_project.pipeline.getDuration()
self.seeker.seek(end)
self.app.gui.focusTimeline()
@@ -412,7 +412,7 @@ class ViewerContainer(Gtk.VBox, Loggable):
clip_uri = tl_obj.props.uri
cur_time = time()
- if self.pipeline == self.app.current_project.pipeline:
+ if self.pipeline == self.app.project_manager.current_project.pipeline:
self.debug("Creating temporary pipeline for clip %s, position %s",
clip_uri, format_ns(position))
self._oldTimelinePos = self.pipeline.getPosition()
@@ -428,11 +428,11 @@ class ViewerContainer(Gtk.VBox, Loggable):
"""
After trimming a clip, reset the project pipeline into the viewer.
"""
- if self.pipeline is not self.app.current_project.pipeline:
+ if self.pipeline is not self.app.project_manager.current_project.pipeline:
self.pipeline.setState(Gst.State.NULL)
# Using pipeline.getPosition() here does not work because for some
# reason it's a bit off, that's why we need self._oldTimelinePos.
- self.setPipeline(self.app.current_project.pipeline, self._oldTimelinePos)
+ self.setPipeline(self.app.project_manager.current_project.pipeline, self._oldTimelinePos)
self.debug("Back to the project's pipeline")
def _pipelineStateChangedCb(self, unused_pipeline, state):
diff --git a/tests/test_application.py b/tests/test_application.py
index 8ea2509..064c040 100644
--- a/tests/test_application.py
+++ b/tests/test_application.py
@@ -35,32 +35,39 @@ class TestPitivi(TestCase):
def testBasic(self):
app = application.Pitivi()
+ app.emit("startup")
self.assertTrue(app.shutdown())
def testVersionInfo(self):
app = application.Pitivi()
+ app.emit("startup")
self.assertTrue(app.isLatest())
app = application.Pitivi()
+ app.emit("startup")
app._versionInfoReceivedCb(MockGioFile(), "invalid", None)
self.assertTrue(app.isLatest())
app = application.Pitivi()
+ app.emit("startup")
app._versionInfoReceivedCb(MockGioFile(), "%s=CURRENT" % configure.VERSION, None)
self.assertTrue(app.isLatest())
self.assertEqual(configure.VERSION, app.getLatest())
app = application.Pitivi()
+ app.emit("startup")
app._versionInfoReceivedCb(MockGioFile(), "%s=current\n0=supported" % configure.VERSION, None)
self.assertTrue(app.isLatest())
self.assertEqual(configure.VERSION, app.getLatest())
app = application.Pitivi()
+ app.emit("startup")
app._versionInfoReceivedCb(MockGioFile(), "999.0=CURRENT", None)
self.assertFalse(app.isLatest())
self.assertEqual("999.0", app.getLatest())
app = application.Pitivi()
+ app.emit("startup")
app._versionInfoReceivedCb(MockGioFile(), "999.0=CURRENT\n%s=SUPPORTED" % configure.VERSION, None)
self.assertFalse(app.isLatest())
self.assertEqual("999.0", app.getLatest())
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]