[pitivi] Update docstrings style
- From: Alexandru Băluț <alexbalut src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [pitivi] Update docstrings style
- Date: Fri, 17 Jun 2016 05:40:38 +0000 (UTC)
commit 94a9a033d72e82b11583067d50e908a29439b6d1
Author: Alexandru Băluț <alexandru balut gmail com>
Date: Wed Jun 8 11:06:17 2016 +0200
Update docstrings style
Should be Google's Python style now.
Differential Revision: https://phabricator.freedesktop.org/D1079
data/ui/titleeditor.ui | 8 +-
pitivi/__init__.py | 3 -
pitivi/application.py | 23 +--
pitivi/autoaligner.py | 5 +-
pitivi/check.py | 78 +++----
pitivi/clipproperties.py | 50 ++---
pitivi/configure.py.in | 20 +-
pitivi/dialogs/__init__.py | 3 -
pitivi/dialogs/clipmediaprops.py | 15 +-
pitivi/dialogs/depsmanager.py | 22 +--
pitivi/dialogs/filelisterrordialog.py | 23 +-
pitivi/dialogs/prefs.py | 198 ++++-------------
pitivi/dialogs/startupwizard.py | 21 +-
pitivi/effects.py | 87 ++++----
pitivi/mainwindow.py | 150 ++++++-------
pitivi/mediafilespreviewer.py | 18 +-
pitivi/medialibrary.py | 112 +++++-----
pitivi/preset.py | 67 +++---
pitivi/project.py | 186 ++++++++--------
pitivi/render.py | 156 ++++++-------
pitivi/settings.py | 129 +++++------
pitivi/tabsmanager.py | 29 +--
pitivi/timeline/__init__.py | 25 --
pitivi/timeline/elements.py | 31 ++--
pitivi/timeline/layer.py | 29 +--
pitivi/timeline/previewers.py | 236 +++++++------------
pitivi/timeline/ruler.py | 27 +--
pitivi/timeline/timeline.py | 129 +++++-------
pitivi/titleeditor.py | 21 +-
pitivi/transitions.py | 35 +---
pitivi/undo/__init__.py | 3 -
pitivi/undo/timeline.py | 12 +-
pitivi/undo/undo.py | 80 +++-----
pitivi/utils/__init__.py | 3 -
pitivi/utils/loggable.py | 401 ++++++++++++++++-----------------
pitivi/utils/misc.py | 80 ++++---
pitivi/utils/pipeline.py | 146 +++++--------
pitivi/utils/proxy.py | 10 +-
pitivi/utils/ripple_update_group.py | 57 +++---
pitivi/utils/system.py | 92 ++++----
pitivi/utils/threads.py | 28 ++--
pitivi/utils/timeline.py | 142 +++++-------
pitivi/utils/ui.py | 62 +++---
pitivi/utils/widgets.py | 117 ++++------
pitivi/viewer/move_scale_overlay.py | 10 +-
pitivi/viewer/overlay.py | 13 +-
pitivi/viewer/title_overlay.py | 5 +-
pitivi/viewer/viewer.py | 43 ++---
tests/test_log.py | 43 ----
49 files changed, 1379 insertions(+), 1904 deletions(-)
---
diff --git a/data/ui/titleeditor.ui b/data/ui/titleeditor.ui
index 5f8aa41..f592a8f 100644
--- a/data/ui/titleeditor.ui
+++ b/data/ui/titleeditor.ui
@@ -255,7 +255,7 @@
<object class="GtkComboBoxText" id="halignment">
<property name="visible">True</property>
<property name="can_focus">False</property>
- <signal name="changed" handler="_updateSource" swapped="no"/>
+ <signal name="changed" handler="_update_source_cb" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
@@ -267,7 +267,7 @@
<property name="visible">True</property>
<property name="can_focus">False</property>
<property name="active">1</property>
- <signal name="changed" handler="_updateSource" swapped="no"/>
+ <signal name="changed" handler="_update_source_cb" swapped="no"/>
</object>
<packing>
<property name="left_attach">1</property>
@@ -282,7 +282,7 @@
<property name="adjustment">position_x_adj</property>
<property name="digits">2</property>
<property name="numeric">True</property>
- <signal name="value-changed" handler="_updateSource" swapped="no"/>
+ <signal name="value-changed" handler="_update_source_cb" swapped="no"/>
</object>
<packing>
<property name="left_attach">2</property>
@@ -297,7 +297,7 @@
<property name="adjustment">position_y_adj</property>
<property name="digits">2</property>
<property name="numeric">True</property>
- <signal name="value-changed" handler="_updateSource" swapped="no"/>
+ <signal name="value-changed" handler="_update_source_cb" swapped="no"/>
</object>
<packing>
<property name="left_attach">2</property>
diff --git a/pitivi/__init__.py b/pitivi/__init__.py
index 7d2cfb4..e69de29 100644
--- a/pitivi/__init__.py
+++ b/pitivi/__init__.py
@@ -1,3 +0,0 @@
-"""
-Main Pitivi package
-"""
diff --git a/pitivi/application.py b/pitivi/application.py
index ed93a33..02a98bd 100644
--- a/pitivi/application.py
+++ b/pitivi/application.py
@@ -53,9 +53,7 @@ from pitivi.utils.timeline import Zoomable
class Pitivi(Gtk.Application, Loggable):
-
- """
- Pitivi's application.
+ """Pitivi's application.
Attributes:
action_log (UndoableActionLog): The undo/redo log for the current project.
@@ -227,11 +225,10 @@ class Pitivi(Gtk.Application, Loggable):
return True
def shutdown(self):
- """
- Close Pitivi.
+ """Closes the app.
- @return: C{True} if Pitivi was successfully closed, else C{False}.
- @rtype: C{bool}
+ Returns:
+ bool: True if successful, False otherwise.
"""
self.debug("shutting down")
# Refuse to close if we are not done with the current project.
@@ -298,9 +295,7 @@ class Pitivi(Gtk.Application, Loggable):
self._scenario_file = None
def _checkVersion(self):
- """
- Check online for release versions information.
- """
+ """Checks online for new versions of the app."""
self.info("Requesting version information async")
giofile = Gio.File.new_for_uri(RELEASES_URL)
giofile.load_contents_async(None, self._versionInfoReceivedCb, None)
@@ -344,16 +339,12 @@ class Pitivi(Gtk.Application, Loggable):
self.warning("Version info could not be read: %s", e)
def isLatest(self):
- """
- Whether the app's version is the latest as far as we know.
- """
+ """Whether the app's version is the latest as far as we know."""
status = self._version_information.get("status")
return status is None or status.upper() == "CURRENT"
def getLatest(self):
- """
- Get the latest version of the app or None.
- """
+ """Get the latest version of the app or None."""
return self._version_information.get("current")
def _quitCb(self, unused_action, unused_param):
diff --git a/pitivi/autoaligner.py b/pitivi/autoaligner.py
index d380f5d..42fc7e7 100644
--- a/pitivi/autoaligner.py
+++ b/pitivi/autoaligner.py
@@ -17,14 +17,11 @@
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
# TODO reimplement after GES port
-"""
-Classes for automatic alignment of L{Clip}s
-"""
+"""Automatic alignment of `Clip`s."""
import array
import os
import time
-from gi.repository import GObject
from gi.repository import Gst
from gi.repository import Gtk
diff --git a/pitivi/check.py b/pitivi/check.py
index f8345d4..4a61c98 100644
--- a/pitivi/check.py
+++ b/pitivi/check.py
@@ -16,15 +16,10 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-This file is run by bin/pitivi on startup. Its purpose is to ensure that all
-the important dependencies for running the pitivi UI can be imported and satisfy
-our version number requirements.
+"""Logic for ensuring important dependencies satisfy minimum requirements.
The checks here are supposed to take a negligible amount of time (< 0.2 seconds)
-and not impact startup. Module imports have no impact (they get imported later
-by the app anyway). For more complex checks, you can measure (with time.time()),
-when called from application.py instead of bin/pitivi, if it has an impact.
+and not impact startup.
Package maintainers should look at the bottom section of this file.
"""
@@ -45,14 +40,14 @@ def _string_to_list(version):
class Dependency(object):
-
- """
- This abstract class represents a module or component requirement.
- @param modulename: The string allowing for import or lookup of the component.
- @param version_required_string: A string in the format X.Y.Z or None if no version
- check is necessary.
- @param additional_message: A string that will be displayed to the user to further
- explain the purpose of the missing component.
+ """Represents a module or component requirement.
+
+ Args:
+ modulename (str): The name identifying the component.
+ version_required_string (Optional[str]): The minimum required version,
+ if any, formatted like "X.Y.Z".
+ additional_message (Optional[str]): Message displayed to the user to
+ further explain the purpose of the missing component.
"""
def __init__(self, modulename, version_required_string=None, additional_message=None):
@@ -64,8 +59,9 @@ class Dependency(object):
self.additional_message = additional_message
def check(self):
- """
- Sets the satisfied flag to True or False.
+ """Checks whether the dependency is satisfied.
+
+ Sets the `satisfied` field to True or False.
"""
self.component = self._try_importing_component()
@@ -81,18 +77,23 @@ class Dependency(object):
self.satisfied = True
def _try_importing_component(self):
- """
- Subclasses must implement that method to return an object
- on which version will be inspectable.
- Return None on failure to import.
+ """Performs the check.
+
+ Returns:
+ The dependent component.
"""
raise NotImplementedError
def _format_version(self, module):
- """
- Subclasses must return the version number split
- in an iterable of ints.
- For example "1.2.10" should return [1, 2, 10]
+ """Formats the version of the component.
+
+ Args:
+ module: The component returned by _try_importing_component.
+
+ Returns:
+ List[int]: The version number of the component.
+
+ For example "1.2.10" should return [1, 2, 10].
"""
raise NotImplementedError
@@ -151,11 +152,6 @@ class ClassicDependency(Dependency):
class GstPluginDependency(Dependency):
- """
- Don't call check on its instances before actually checking
- Gst is importable.
- """
-
def _try_importing_component(self):
try:
from gi.repository import Gst
@@ -253,6 +249,7 @@ class GICheck(ClassicDependency):
def check_requirements():
+ """Checks Pitivi's dependencies are satisfied."""
hard_dependencies_satisfied = True
for dependency in HARD_DEPENDENCIES:
@@ -307,8 +304,7 @@ def require_version(modulename, version):
def initialize_modules():
- """
- Initialize the modules.
+ """Initializes the modules.
This has to be done in a specific order otherwise the app
crashes on some systems.
@@ -380,13 +376,11 @@ HARD_DEPENDENCIES = [GICheck("3.14.0"),
ClassicDependency("matplotlib"),
]
-SOFT_DEPENDENCIES = \
- (
- ClassicDependency("pycanberra", None, _("enables sound notifications when rendering is complete")),
- GIDependency("GnomeDesktop", "3.0", None, _("file thumbnails provided by GNOME's thumbnailers")),
- GIDependency("Notify", "0.7", None, _("enables visual notifications when rendering is complete")),
- GstPluginDependency("libav", None, _("additional multimedia codecs through the GStreamer Libav
library")),
- GstPluginDependency("debugutilsbad", None, _("enables a watchdog in the GStreamer pipeline."
- " Use to detect errors happening in GStreamer"
- " and recover from them")),
- )
+SOFT_DEPENDENCIES = (
+ ClassicDependency("pycanberra", None, _("enables sound notifications when rendering is complete")),
+ GIDependency("GnomeDesktop", "3.0", None, _("file thumbnails provided by GNOME's thumbnailers")),
+ GIDependency("Notify", "0.7", None, _("enables visual notifications when rendering is complete")),
+ GstPluginDependency("libav", None, _("additional multimedia codecs through the GStreamer Libav
library")),
+ GstPluginDependency("debugutilsbad", None, _("enables a watchdog in the GStreamer pipeline."
+ " Use to detect errors happening in GStreamer"
+ " and recover from them")))
diff --git a/pitivi/clipproperties.py b/pitivi/clipproperties.py
index 0c269a2..c7f175c 100644
--- a/pitivi/clipproperties.py
+++ b/pitivi/clipproperties.py
@@ -16,9 +16,7 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-Widgets to control clips properties
-"""
+"""Widgets to control clips properties."""
import os
from gettext import gettext as _
@@ -50,15 +48,14 @@ from pitivi.utils.ui import SPACING
class ClipPropertiesError(Exception):
- """Base Exception for errors happening in L{ClipProperties}s or L{EffectProperties}s"""
pass
class ClipProperties(Gtk.ScrolledWindow, Loggable):
- """
- Widget for configuring the selected clip.
+ """Widget for configuring the selected clip.
- @type app: L{Pitivi}
+ Attributes:
+ app (Pitivi): The app.
"""
def __init__(self, app):
@@ -91,9 +88,7 @@ class ClipProperties(Gtk.ScrolledWindow, Loggable):
vbox.pack_start(self.effect_expander, False, False, 0)
def createInfoBar(self, text):
- """
- Create an infobar that is added at the beginning of the window
- """
+ """Creates an infobar to be displayed at the top."""
label = Gtk.Label(label=text)
label.set_line_wrap(True)
infobar = Gtk.InfoBar()
@@ -105,11 +100,10 @@ class ClipProperties(Gtk.ScrolledWindow, Loggable):
# pylint: disable=too-many-instance-attributes
class EffectProperties(Gtk.Expander, Loggable):
- """
- Widget for viewing a list of effects and configuring them.
+ """Widget for viewing a list of effects and configuring them.
- @type app: C{Pitivi}
- @type effects_properties_manager: C{EffectsPropertiesManager}
+ Attributes:
+ app (Pitivi): The app.
"""
# pylint: disable=too-many-statements
@@ -148,14 +142,12 @@ class EffectProperties(Gtk.Expander, Loggable):
# We need to specify Gtk.TreeDragSource because otherwise we are hitting
# bug https://bugzilla.gnome.org/show_bug.cgi?id=730740.
class EffectsListStore(Gtk.ListStore, Gtk.TreeDragSource):
- """
- Just a work around!
- """
+ """Just a work around!"""
# pylint: disable=non-parent-init-called
def __init__(self, *args):
Gtk.ListStore.__init__(self, *args)
- # Simply set the source index on the storemodrel directly
- # to avoid issues with the selection_data API
+ # Set the source index on the storemodel directly,
+ # to avoid issues with the selection_data API.
# FIXME: Work around
# https://bugzilla.gnome.org/show_bug.cgi?id=737587
self.source_index = None
@@ -336,12 +328,11 @@ class EffectProperties(Gtk.Expander, Loggable):
break
def addEffectToCurrentSelection(self, factory_name):
- """
- Add an effect to the current selection
+ """Adds an effect to the current selection.
Args:
- factory_name (str): The name of the GstElementFactory to creaye the
- effect from.
+ factory_name (str): The name of the GstElementFactory for creating
+ the effect.
"""
if not self.clips or len(self.clips) > 1:
return
@@ -433,9 +424,7 @@ class EffectProperties(Gtk.Expander, Loggable):
@staticmethod
def calculateEffectPriority(source_index, drop_index, drop_pos):
- """
- Return where the effect from source_index will end up
- """
+ """Calculates where the effect from source_index will end up."""
if drop_pos in (Gtk.TreeViewDropPosition.INTO_OR_BEFORE, Gtk.TreeViewDropPosition.INTO_OR_AFTER):
return drop_index
if drop_pos == Gtk.TreeViewDropPosition.BEFORE:
@@ -539,9 +528,7 @@ class EffectProperties(Gtk.Expander, Loggable):
class TransformationProperties(Gtk.Expander, Loggable):
- """
- Widget for viewing and configuring speed
- """
+ """Widget for configuring the placement and size of the clip."""
__signals__ = {
'selection-changed': []}
@@ -617,10 +604,7 @@ class TransformationProperties(Gtk.Expander, Loggable):
spinbtn.set_value(value)
def __setupSpinButton(self, widget_name, property_name):
- """
- Create a spinbutton widget and connect its signals to change property
- values. While focused, disable the timeline actions' sensitivity.
- """
+ """Creates a SpinButton for editing a property value."""
spinbtn = self.builder.get_object(widget_name)
spinbtn.connect("output", self._onValueChangedCb, property_name)
disable_scroll(spinbtn)
diff --git a/pitivi/configure.py.in b/pitivi/configure.py.in
index 33720f6..cb3cc9d 100644
--- a/pitivi/configure.py.in
+++ b/pitivi/configure.py.in
@@ -16,8 +16,8 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-Utilities for getting the location of various directories.
+"""Utilities for getting the location of various directories.
+
Enables identical use for installed and uninstalled versions.
"""
@@ -30,9 +30,7 @@ def _get_root_dir():
def in_devel():
- """
- Returns whether the app is run from a git checkout.
- """
+ """Returns whether the app is run from a git checkout."""
return os.environ.get("PITIVI_DEVELOPMENT", "0") != "0"
if "APPDIR" in os.environ:
@@ -68,29 +66,29 @@ def get_data_dir():
def get_pixmap_dir():
- """ Returns the directory for program-only pixmaps """
+ """Returns our directory with pixmaps."""
return os.path.join(get_data_dir(), 'pixmaps')
def get_ui_dir():
- """ Returns the directory for GtkBuilder/Glade files """
+ """Returns our directory with Gtk.Builder/Glade files."""
return os.path.join(get_data_dir(), 'ui')
def get_renderpresets_dir():
- """ Returns the directory for Render Presets files """
+ """Returns our directory with Render Presets files."""
return os.path.join(get_data_dir(), 'renderpresets')
def get_audiopresets_dir():
- """ Returns the directory for Audio Presets files """
+ """Returns our directory with Audio Presets files."""
return os.path.join(get_data_dir(), 'audiopresets')
def get_videopresets_dir():
- """ Returns the directory for Video Presets files """
+ """Returns our directory with Video Presets files."""
return os.path.join(get_data_dir(), 'videopresets')
def get_gstpresets_dir():
- """ Returns the directory for Video Presets files """
+ """Returns our directory with Gst Presets files."""
return os.path.join(get_data_dir(), 'gstpresets')
diff --git a/pitivi/dialogs/__init__.py b/pitivi/dialogs/__init__.py
index fb15aae..e69de29 100644
--- a/pitivi/dialogs/__init__.py
+++ b/pitivi/dialogs/__init__.py
@@ -1,3 +0,0 @@
-"""
-Gtk+ v2.x User Interface package
-"""
diff --git a/pitivi/dialogs/clipmediaprops.py b/pitivi/dialogs/clipmediaprops.py
index 9c4869f..6a6fb66 100644
--- a/pitivi/dialogs/clipmediaprops.py
+++ b/pitivi/dialogs/clipmediaprops.py
@@ -30,12 +30,13 @@ from pitivi.utils.ui import pixel_aspect_ratios
class ClipMediaPropsDialog(object):
+ """Displays the properties of an asset.
- """
- Displays the properties of an asset, and allows applying them to a project.
+ Allows applying them to the project.
- @type project: L{Project}
- @type asset: L{GES.UriClipAsset}
+ Attributes:
+ project (Project): The project.
+ asset (GES.UriClipAsset): The displayed asset.
"""
def __init__(self, project, asset):
@@ -73,7 +74,7 @@ class ClipMediaPropsDialog(object):
self.video_header_label = builder.get_object("label2")
def run(self):
- """Set up widgets and run the dialog"""
+ """Sets up widgets and run the dialog."""
# TODO: in "onApplyButtonClicked", we only use the first stream...
# If we have multiple audio or video streams, we should reflect that
# in the UI, instead of acting as if there was only one. But that means
@@ -137,7 +138,7 @@ class ClipMediaPropsDialog(object):
self.dialog.run()
def _applyButtonCb(self, unused_button):
- """Apply widget values to the project"""
+ """Applies the widgets values to the project."""
project = self.project
if self.has_video:
# This also handles the case where the video is a still image
@@ -160,7 +161,7 @@ class ClipMediaPropsDialog(object):
self.dialog.destroy()
def _cancelButtonCb(self, unused_button):
- """Destroy the dialog"""
+ """Destroys the dialog."""
self.dialog.destroy()
def _keyPressCb(self, unused_widget, event):
diff --git a/pitivi/dialogs/depsmanager.py b/pitivi/dialogs/depsmanager.py
index 1a49442..0fccfd2 100644
--- a/pitivi/dialogs/depsmanager.py
+++ b/pitivi/dialogs/depsmanager.py
@@ -16,7 +16,7 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-""" This module implements the notions of missing dependencies """
+"""Missing dependencies logic."""
import os
from gi.repository import Gtk
@@ -26,10 +26,7 @@ from pitivi.configure import get_ui_dir
class DepsManager(object):
-
- """Display a dialog listing missing soft dependencies.
- The sane way to query and install is by using PackageKit's InstallResource()
- """
+ """Manages a dialog listing missing soft dependencies."""
def __init__(self, app, parent_window=None):
self.app = app
@@ -54,11 +51,11 @@ class DepsManager(object):
self.show()
def _onCloseButtonClickedCb(self, unused_button):
- """ Hide on close """
+ """Hides the dialog."""
self.hide()
def _onInstallButtonClickedCb(self, unused_button):
- """ Hide on install and try to install dependencies """
+ """Hides on install and tries to install dependencies."""
self.hide()
# FIXME: this is not implemented properly.
# Here is some partially working code:
@@ -84,10 +81,7 @@ class DepsManager(object):
# TODO: catch exceptions/create callbacks to _installFailedCb
def _setDepsLabel(self):
- """
- Set the contents of the label containing the list of
- missing dependencies
- """
+ """Updates the UI to display the list of missing dependencies."""
label_contents = ""
for depname, dep in missing_soft_deps.items():
label_contents += "• %s (%s)\n" % (
@@ -95,13 +89,13 @@ class DepsManager(object):
self.builder.get_object("pkg_list").set_text(label_contents)
def show(self):
- """Show internal window"""
+ """Shows the dialog."""
self.window.show()
def hide(self):
- """Hide internal window"""
+ """Hides the dialog."""
self.window.hide()
def _installFailedCb(self, unused_exception):
- """Handle the failure of installing packages."""
+ """Handles the failure of installing packages."""
self.show()
diff --git a/pitivi/dialogs/filelisterrordialog.py b/pitivi/dialogs/filelisterrordialog.py
index d8e8185..0164301 100644
--- a/pitivi/dialogs/filelisterrordialog.py
+++ b/pitivi/dialogs/filelisterrordialog.py
@@ -16,9 +16,7 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-Dialog box listing files which had errors, and the reasons.
-"""
+"""Assets discovery errors."""
import os
from gettext import gettext as _
from urllib.parse import unquote
@@ -32,8 +30,7 @@ from pitivi.utils.loggable import Loggable
class FileListErrorDialog(GObject.Object, Loggable):
-
- """ Dialog box for showing errors in a list of files """
+ """Dialog for showing errors blocking importing media files."""
__gsignals__ = {
'close': (GObject.SIGNAL_RUN_LAST, None, ()),
@@ -55,9 +52,11 @@ class FileListErrorDialog(GObject.Object, Loggable):
self.errorvbox = self.builder.get_object("errorvbox")
def addFailedFile(self, uri, reason=_("Unknown reason"), extra=None):
- """Add the given uri to the list of failed files. You can optionnaly
- give a string identifying the reason why the file failed to be
- discovered
+ """Adds the specified URI to the list of failures.
+
+ Args:
+ uri (str): The URI of the asset which cannot be imported.
+ reason (Optional[str]): The reason of the file discovery failure.
"""
self.debug("Uri: %s, reason: %s, extra: %s", uri, reason, extra)
exp = self.__createFileExpander(uri, reason, extra)
@@ -105,19 +104,19 @@ class FileListErrorDialog(GObject.Object, Loggable):
return exp
def isVisible(self):
- """ returns True if this dialog is currently shown """
+ """Returns True if the dialog is currently shown."""
return self.window.get_property("visible")
def destroy(self):
- """Destroy internal window"""
+ """Destroys the dialog."""
self.window.destroy()
# Callbacks from glade
def _closeCb(self, unused_dialog):
- """Emit the close signal"""
+ """Emits the `close` signal."""
self.emit('close')
def _responseCb(self, unused_dialog, response):
- """Emit the response signal"""
+ """Emits the `response` signal."""
self.emit('response', response)
diff --git a/pitivi/dialogs/prefs.py b/pitivi/dialogs/prefs.py
index 4901789..4337223 100644
--- a/pitivi/dialogs/prefs.py
+++ b/pitivi/dialogs/prefs.py
@@ -16,9 +16,7 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-Dialog box for user preferences.
-"""
+"""User preferences."""
import os
from gettext import gettext as _
@@ -45,10 +43,7 @@ GlobalSettings.addConfigOption('prefsDialogHeight',
class PreferencesDialog(Loggable):
-
- """
- Preferences for how the app works.
- """
+ """Preferences for how the app works."""
prefs = {}
original_values = {}
@@ -84,31 +79,25 @@ class PreferencesDialog(Loggable):
self.dialog.set_default_size(width, height)
def run(self):
- """Run the internal dialog"""
+ """Runs the dialog."""
self.dialog.run()
# Public API
@classmethod
- def addPreference(cls, attrname, label, description, section=None,
- widget_class=None, **args):
- """
- Add a user preference. The preferences dialog will try
- to guess the appropriate widget to use based on the type of the
- option, but you can override this by specifying a custom class.
-
- @param attrname: the id of the setting holding the preference
- @type attrname: C{str}
- @param label: user-visible name for this option
- @type label: C{str}
- @param description: a user-visible description documenting this option
- (ignored unless prefs_label is non-null)
- @type description: C{str}
- @param : user-visible category to which this option
- belongs (ignored unless prefs_label is non-null)
- @type section: C{str}
- @param widget_class: overrides auto-detected widget
- @type widget_class: C{class}
+ def _add_preference(cls, attrname, label, description, section,
+ widget_class, **args):
+ """Adds a user preference.
+
+ Args:
+ attrname (str): The id of the setting holding the preference.
+ label (str): The user-visible name for this option.
+ description (str): The user-visible description explaining this
+ option. Ignored unless `label` is non-None.
+ section (str): The user-visible category to which this option
+ belongs. Ignored unless `label` is non-None.
+ widget_class (type): The class of the widget for displaying the
+ option.
"""
if not section:
section = "General"
@@ -118,143 +107,51 @@ class PreferencesDialog(Loggable):
@classmethod
def addPathPreference(cls, attrname, label, description, section=None):
- """
- Add an auto-generated user preference that will show up as a
- Gtk.FileChooserButton.
-
- @param label: user-visible name for this option
- @type label: C{str}
- @param description: a user-visible description documenting this option
- (ignored unless prefs_label is non-null)
- @type description: C{str}
- @param section: user-visible category to which this option
- belongs (ignored unless prefs_label is non-null)
- @type section: C{str}
- """
- cls.addPreference(attrname, label, description, section,
- widgets.PathWidget)
+ """Adds a user preference for a file path."""
+ cls._add_preference(attrname, label, description, section,
+ widgets.PathWidget)
@classmethod
def addNumericPreference(cls, attrname, label, description, section=None,
upper=None, lower=None):
+ """Adds a user preference for a number.
+
+ Show up as either a Gtk.SpinButton or a horizontal Gtk.Scale, depending
+ whether both the upper and lower limits are set.
"""
- Add an auto-generated user preference that will show up as either a
- Gtk.SpinButton or an horizontal Gtk.Scale, depending whether both the
- upper and lower limits are set.
-
- @param label: user-visible name for this option
- @type label: C{str}
- @param description: a user-visible description documenting this option
- (ignored unless prefs_label is non-null)
- @type description: C{str}
- @param section: user-visible category to which this option
- belongs (ignored unless prefs_label is non-null)
- @type section: C{str}
- @param upper: upper limit for this widget, or None
- @type upper: C{number}
- @param lower: lower limit for this widget, or None
- @type lower: C{number}
- """
- cls.addPreference(attrname, label, description, section,
- widgets.NumericWidget, upper=upper, lower=lower)
+ cls._add_preference(attrname, label, description, section,
+ widgets.NumericWidget, upper=upper, lower=lower)
@classmethod
def addTextPreference(cls, attrname, label, description, section=None, matches=None):
- """
- Add an auto-generated user preference that will show up as either a
- Gtk.SpinButton or an horizontal Gtk.Scale, depending on the upper and
- lower limits
-
- @param label: user-visible name for this option
- @type label: C{str}
- @param description: a user-visible description documenting this option
- (ignored unless prefs_label is non-null)
- @type description: C{str}
- @param section: user-visible category to which this option
- belongs (ignored unless prefs_label is non-null)
- @type section: C{str}
- """
- cls.addPreference(attrname, label, description, section,
- widgets.TextWidget, matches=matches)
+ """Adds a user preference for text."""
+ cls._add_preference(attrname, label, description, section,
+ widgets.TextWidget, matches=matches)
@classmethod
def addChoicePreference(cls, attrname, label, description, choices, section=None):
- """
- Add an auto-generated user preference that will show up as either a
- Gtk.ComboBox or a group of radio buttons, depending on the number of
- choices.
-
- @param label: user-visible name for this option
- @type label: C{str}
- @param description: a user-visible description documenting this option
- (ignored unless prefs_label is non-null)
- @type description: C{str}
- @param choices: a sequence of (<label>, <value>) pairs
- @type choices: C{[(str, pyobject), ...]}
- @param section: user-visible category to which this option
- belongs (ignored unless prefs_label is non-null)
- @type section: C{str}
- """
- cls.addPreference(attrname, label, description, section,
- widgets.ChoiceWidget, choices=choices)
+ """Adds a user preference for text options."""
+ cls._add_preference(attrname, label, description, section,
+ widgets.ChoiceWidget, choices=choices)
@classmethod
def addTogglePreference(cls, attrname, label, description, section=None):
- """
- Add an auto-generated user preference that will show up as a
- Gtk.CheckButton.
-
- @param label: user-visible name for this option
- @type label: C{str}
- @param description: a user-visible description documenting this option
- (ignored unless prefs_label is non-null)
- @type description: C{str}
- @param section: user-visible category to which this option
- belongs (ignored unless prefs_label is non-null)
- @type section: C{str}
- """
- cls.addPreference(attrname, label, description, section,
- widgets.ToggleWidget)
+ """Adds a user preference for an on/off option."""
+ cls._add_preference(attrname, label, description, section,
+ widgets.ToggleWidget)
@classmethod
def addColorPreference(cls, attrname, label, description, section=None, value_type=int):
- """
- Add an auto-generated user preference for specifying colors. The
- colors can be returned as either int, a string colorspec, or a
- Gdk.Color object. See the Gdk.color_parse() function for info
- on colorspecs.
-
- @param label: user-visible name for this option
- @type label: C{str}
- @param description: a user-visible description documenting this option
- (ignored unless prefs_label is non-null)
- @type description: C{str}
- @param section: user-visible category to which this option
- belongs (ignored unless prefs_label is non-null)
- @type section: C{str}
- """
- cls.addPreference(attrname, label, description, section,
- widgets.ColorWidget, value_type=value_type)
+ """Adds a user preference for a color."""
+ cls._add_preference(attrname, label, description, section,
+ widgets.ColorWidget, value_type=value_type)
@classmethod
def addFontPreference(cls, attrname, label, description, section=None):
- """
- Add an auto-generated user preference that will show up as a
- font selector.
-
- @param label: user-visible name for this option
- @type label: C{str}
- @param description: a user-visible description documenting this option
- (ignored unless prefs_label is non-null)
- @type description: C{str}
- @param section: user-visible category to which this option
- belongs (ignored unless prefs_label is non-null)
- @type section: C{str}
- """
- cls.addPreference(attrname, label, description, section,
- widgets.FontWidget)
+ """Adds a user preference for a font."""
+ cls._add_preference(attrname, label, description, section,
+ widgets.FontWidget)
-# Implementation
def __fillContents(self):
for section in sorted(self.prefs):
options = self.prefs[section]
@@ -323,7 +220,7 @@ class PreferencesDialog(Loggable):
self.factory_settings.set_sensitive(self._canReset())
def _treeSelectionChangedCb(self, selection):
- """ Update current when selection changed"""
+ """Updates current when selection changed."""
model, _iter = selection.get_selected()
section = self.sections[model[_iter][0]]
if self._current != section:
@@ -339,18 +236,13 @@ class PreferencesDialog(Loggable):
self.revert_button.set_sensitive(False)
def _factorySettingsButtonCb(self, unused_button):
- """
- Reset all settings to the defaults
- """
+ """Resets all settings to the defaults."""
for section in self.prefs.values():
for attrname in section:
self._resetOptionCb(self.resets[attrname], attrname)
def _revertButtonCb(self, unused_button):
- """
- Resets all settings to the values from before the user opened the
- preferences dialog.
- """
+ """Resets all settings to the values when the dialog was opened."""
for attrname, value in self.original_values.items():
self.widgets[attrname].setWidgetValue(value)
setattr(self.settings, attrname, value)
@@ -358,9 +250,7 @@ class PreferencesDialog(Loggable):
self.factory_settings.set_sensitive(self._canReset())
def _resetOptionCb(self, button, attrname):
- """
- Reset a particular setting to the factory default
- """
+ """Resets a particular setting to the factory default."""
if not self.settings.isDefault(attrname):
self.settings.setDefault(attrname)
self.widgets[attrname].setWidgetValue(getattr(self.settings, attrname))
diff --git a/pitivi/dialogs/startupwizard.py b/pitivi/dialogs/startupwizard.py
index a6c0a5b..ac8bc50 100644
--- a/pitivi/dialogs/startupwizard.py
+++ b/pitivi/dialogs/startupwizard.py
@@ -31,7 +31,6 @@ from pitivi.utils.misc import show_user_manual
class StartUpWizard(object):
-
"""A Wizard displaying recent projects.
Allows the user to:
@@ -48,7 +47,7 @@ class StartUpWizard(object):
show_user_manual()
def _cheatsheetCb(self, unused_button):
- """Shows the shortcuts cheatsheet"""
+ """Shows the shortcuts cheatsheet."""
show_shortcuts(self.app)
def __init__(self, app):
@@ -92,33 +91,33 @@ class StartUpWizard(object):
"version-info-received", self._appVersionInfoReceivedCb)
def _newProjectCb(self, unused_button):
- """Handle a click on the New (Project) button."""
+ """Handles a click on the New (Project) button."""
self.app.project_manager.newBlankProject()
def _loadCb(self, unused_recent_chooser):
- """
- Handle choosing a project on the recent chooser.
+ """Handles choosing a project on the recent chooser.
+
This calls the project manager to load the associated URI.
"""
uri = self.recent_chooser.get_current_uri()
self.app.project_manager.loadProject(uri)
def _keyPressCb(self, unused_widget, event):
- """Handle a key press event on the dialog."""
+ """Handles a key press event on the dialog."""
if event.keyval == Gdk.KEY_Escape:
# The user pressed "Esc".
self.app.project_manager.newBlankProject()
def _onBrowseButtonClickedCb(self, unused_button6):
- """Handle a click on the Browse button."""
+ """Handles a click on the Browse button."""
self.app.gui.openProject()
def _onMissingDepsButtonClickedCb(self, unused_button):
- """Handle a click on the Missing Deps button."""
+ """Handles a click on the Missing Deps button."""
DepsManager(self.app, parent_window=self.window)
def _deleteCb(self, unused_widget, unused_event):
- """Handle a click on the X button of the dialog."""
+ """Handles a click on the X button of the dialog."""
self.app.project_manager.newBlankProject()
return True
@@ -138,11 +137,11 @@ class StartUpWizard(object):
project_manager.disconnect_by_func(self._projectLoadingCb)
def _projectLoadingCb(self, unused_project_manager, unused_uri):
- """Handle the start of a project load operation."""
+ """Handles the start of a project load operation."""
self.hide()
def _appVersionInfoReceivedCb(self, app, unused_version_information):
- """Handle version info"""
+ """Handles new version info."""
if app.isLatest():
# current version, don't show message
return
diff --git a/pitivi/effects.py b/pitivi/effects.py
index 71e8bd8..964ffea 100644
--- a/pitivi/effects.py
+++ b/pitivi/effects.py
@@ -17,10 +17,7 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-Effects global handling
- Note: Some effects are available through the frei0r
- library and the libavfilter0 library
+"""Effects categorization and management.
There are different types of effects available:
_ Simple Audio/Video Effects
@@ -134,6 +131,11 @@ ICON_WIDTH = 48 + 2 * 6 # 48 pixels, plus a margin on each side
class EffectInfo(object):
+ """Info for displaying and using an effect.
+
+ Attributes:
+ effect_name (str): The bin_description identifying the effect.
+ """
def __init__(self, effect_name, media_type, categories,
human_name, description):
@@ -161,9 +163,11 @@ class EffectInfo(object):
class EffectsManager(object):
+ """Keeps info about effects and their categories.
- """
- Info about effects.
+ Attributes:
+ video_effects (List[Gst.ElementFactory]): The available video effects.
+ audio_effects (List[Gst.ElementFactory]): The available audio effects.
"""
def __init__(self):
@@ -215,31 +219,25 @@ class EffectsManager(object):
description=factory.get_description())
self._effects[name] = effect
- def getAllAudioEffects(self):
- """
- @return: the list of available audio effects elements
- """
- return self.audio_effects
+ def getInfo(self, name):
+ """Gets the info for an effect which can be applied.
- def getAllVideoEffects(self):
- """
- @return: the list of available video effects elements
- """
- return self.video_effects
+ Args:
+ name (str): The bin_description identifying the effect.
- def getInfo(self, name):
- """
- @param name: The bin_description of the effect.
- @type name: C{str}
- @return: The l{EffectInfo} corresponding to the name or None
+ Returns:
+ EffectInfo: The info corresponding to the name, or None.
"""
return self._effects.get(name)
def _getEffectCategories(self, effect_name):
- """
- @param effect_name: the name of the effect for wich we want the category
- @type effect_name: L{str}
- @return: A C{list} of name C{str} of categories corresponding the effect
+ """Gets the categories to which the specified effect belongs.
+
+ Args:
+ effect_name (str): The bin_description identifying the effect.
+
+ Returns:
+ List[str]: The categories which contain the effect.
"""
categories = []
for category_name, effects in AUDIO_EFFECTS_CATEGORIES:
@@ -249,23 +247,18 @@ class EffectsManager(object):
if effect_name in effects:
categories.append(category_name)
if not categories:
- uncategorized = _("Uncategorized")
- categories.append(uncategorized)
+ categories.append(_("Uncategorized"))
categories.insert(0, _("All effects"))
return categories
@property
def video_categories(self):
- """
- Get all video effect categories names.
- """
+ """Gets all video effect categories names."""
return EffectsManager._getCategoriesNames(VIDEO_EFFECTS_CATEGORIES)
@property
def audio_categories(self):
- """
- Get all audio effect categories names.
- """
+ """Gets all audio effect categories names."""
return EffectsManager._getCategoriesNames(AUDIO_EFFECTS_CATEGORIES)
@staticmethod
@@ -297,8 +290,7 @@ GlobalSettings.addConfigSection('effect-library')
class EffectListWidget(Gtk.Box, Loggable):
-
- """ Widget for listing effects """
+ """Widget for listing effects."""
def __init__(self, instance):
Gtk.Box.__init__(self)
@@ -405,8 +397,8 @@ class EffectListWidget(Gtk.Box, Loggable):
return "<b>%s</b>\n%s" % (escape(name), escape(desc))
def _loadAvailableEffectsCb(self):
- self._addFactories(self.app.effects.getAllVideoEffects(), VIDEO_EFFECT)
- self._addFactories(self.app.effects.getAllAudioEffects(), AUDIO_EFFECT)
+ self._addFactories(self.app.effects.video_effects, VIDEO_EFFECT)
+ self._addFactories(self.app.effects.audio_effects, AUDIO_EFFECT)
return False
def _addFactories(self, elements, effectType):
@@ -488,8 +480,8 @@ class EffectListWidget(Gtk.Box, Loggable):
return self.storemodel[path][COL_ELEMENT_NAME]
def _toggleViewTypeCb(self, widget):
- """
- Handle the switching of the view mode between video and audio.
+ """Switches the view mode between video and audio.
+
This makes the two togglebuttons behave like a group of radiobuttons.
"""
if widget is self.video_togglebutton:
@@ -502,7 +494,6 @@ class EffectListWidget(Gtk.Box, Loggable):
self._effectType = VIDEO_EFFECT
else:
self._effectType = AUDIO_EFFECT
-
self.populate_categories_widget()
self.modelFilter.refilter()
@@ -531,11 +522,10 @@ PROPS_TO_IGNORE = ['name', 'qos', 'silent', 'message', 'parent']
class EffectsPropertiesManager:
+ """Provides and caches UIs for editing effects.
- """
- Provides and caches UIs for editing effects.
-
- @type app: L{Pitivi}
+ Attributes:
+ app (Pitivi): The app.
"""
def __init__(self, app):
@@ -544,10 +534,13 @@ class EffectsPropertiesManager:
self.app = app
def getEffectConfigurationUI(self, effect):
- """Permit to get a configuration GUI for the effect
+ """Gets a configuration UI element for the effect.
+
+ Args:
+ effect (Gst.Element): The effect for which we want the UI.
- @param effect: The effect for which we want the configuration UI
- @type effect: C{Gst.Element}
+ Returns:
+ GstElementSettingsWidget: A container for configuring the effect.
"""
if effect not in self.cache_dict:
# Here we should handle special effects configuration UI
diff --git a/pitivi/mainwindow.py b/pitivi/mainwindow.py
index b56d705..ac9e2eb 100644
--- a/pitivi/mainwindow.py
+++ b/pitivi/mainwindow.py
@@ -112,12 +112,10 @@ GlobalSettings.addConfigOption('timelineAutoRipple',
class MainWindow(Gtk.ApplicationWindow, Loggable):
-
- """
- Pitivi's main window.
+ """Pitivi's main window.
Attributes:
- app (pitivi.application.Pitivi): The current app.
+ app (Pitivi): The app.
"""
def __init__(self, app):
@@ -172,15 +170,11 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
style_context.add_provider_for_screen(screen, css_provider,
Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
- def showRenderDialog(self, project):
- """
- Shows the L{RenderDialog} for the given project Timeline.
-
- @param project: The project
- @type project: L{Project}
- """
+ def showRenderDialog(self):
+ """Shows the RenderDialog for the current project."""
from pitivi.render import RenderDialog
+ project = self.app.project_manager.current_project
dialog = RenderDialog(self.app, project)
dialog.window.connect("destroy", self._renderDialogDestroyCb)
self.set_sensitive(False)
@@ -218,22 +212,18 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
self.timeline_ui.enableKeyboardAndMouseEvents()
def _renderCb(self, unused_button):
- self.showRenderDialog(self.app.project_manager.current_project)
+ self.showRenderDialog()
def _createUi(self):
- """
- Create the graphical interface with the following hierarchy:
- -- self.vpaned
- ---- self.mainhpaned (upper half)
- ------ self.secondaryhpaned (upper-left)
- -------- Primary tabs
- -------- Context tabs
- ------ Viewer (upper-right)
- ---- Timeline (bottom half)
-
- In the window titlebar, there is also a HeaderBar widget.
-
- The full hierarchy is visible with accessibility tools like "sniff".
+ """Creates the graphical interface.
+
+ The rough hierarchy is:
+ vpaned:
+ - mainhpaned(secondhpaned(main_tabs, context_tabs), viewer)
+ - timeline_ui
+
+ The full hierarchy can be admired by starting the GTK+ Inspector
+ with Ctrl+Shift+I.
"""
self.set_icon_name("pitivi")
@@ -370,9 +360,9 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
self.settings.mainWindowVPanePosition = value
def checkScreenConstraints(self):
- """
- Measure the approximate minimum size required by the main window
- and shrink some widgets to fit smaller screen resolutions.
+ """Measures the approximate minimum size required by the main window.
+
+ Shrinks some widgets to fit better on smaller screen resolutions.
"""
# This code works, but keep in mind get_preferred_size's output
# is only an approximation. As of 2015, GTK still does not have
@@ -381,24 +371,20 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
min_size, natural_size = self.get_preferred_size()
screen_width = self.get_screen().get_width()
screen_height = self.get_screen().get_height()
- self.debug("Minimum UI size is " +
- str(min_size.width) + "x" + str(min_size.height))
- self.debug("Screen size is " +
- str(screen_width) + "x" + str(screen_height))
+ self.debug("Minimum UI size is %sx%s", min_size.width, min_size.height)
+ self.debug("Screen size is %sx%s", screen_width, screen_height)
if min_size.width >= 0.9 * screen_width:
self.medialibrary.activateCompactMode()
self.viewer.activateCompactMode()
min_size, natural_size = self.get_preferred_size()
- self.info("Minimum UI size has been reduced to " +
- str(min_size.width) + "x" + str(min_size.height))
+ self.info("Minimum UI size has been reduced to %sx%s",
+ min_size.width, min_size.height)
def switchContextTab(self, ges_clip):
- """
- Switch the tab being displayed on the second set of tabs,
- depending on the context.
+ """Activates the appropriate tab on the second set of tabs.
- @param ges_clip: The clip which has been focused.
- @type ges_clip: GES.SourceClip
+ Args:
+ ges_clip (GES.SourceClip): The clip which has been focused.
"""
if isinstance(ges_clip, GES.TitleClip):
page = 2
@@ -512,9 +498,7 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
# UI Callbacks
def _configureCb(self, unused_widget, event):
- """
- Handle the main window being moved, resized or maximized
- """
+ """Handles the main window being moved, resized or maximized."""
# get_position() takes window manager decoration into account
position = self.get_position()
self.settings.mainWindowWidth = event.width
@@ -537,7 +521,8 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
self.settings.mainWindowVPanePosition = self.vpaned.get_position()
def _mediaLibraryPlayCb(self, unused_medialibrary, asset):
- """
+ """Previews the specified asset.
+
If the media library item to preview is an image, show it in the user's
favorite image viewer. Else, preview the video/sound in Pitivi.
"""
@@ -724,9 +709,11 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
# Project management callbacks
def _projectManagerNewProjectLoadedCb(self, project_manager, project):
- """
- @type project_manager: L{ProjectManager}
- @type project: L{Project}
+ """Starts connecting the UI to the specified project.
+
+ Args:
+ project_manager (ProjectManager): The project manager.
+ project (Project): The project which has been loaded.
"""
self.log("A new project has been loaded")
self._connectToProject(project)
@@ -777,9 +764,15 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
project.uri = uri
def _projectManagerClosingProjectCb(self, project_manager, project):
- """
- @type project_manager: L{ProjectManager}
- @type project: L{Project}
+ """Investigates whether it's possible to close the specified project.
+
+ Args:
+ project_manager (ProjectManager): The project manager.
+ project (Project): The project which has been closed.
+
+ Returns:
+ bool: True when it's OK to close it, False when the user chooses
+ to cancel the closing operation.
"""
if not project.hasUnsavedModifications():
return True
@@ -861,11 +854,15 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
return res
def _projectManagerProjectClosedCb(self, unused_project_manager, project):
- """
- This happens immediately when the user asks to load another project,
- after the user confirmed that unsaved changes can be discarded but
- before the filechooser to pick the new project to load appears...
- We can then expect another project to be loaded soon afterwards.
+ """Starts disconnecting the UI from the specified project.
+
+ This happens when the user closes the app or asks to load another
+ project, immediately after the user confirmed that unsaved changes,
+ if any, can be discarded but before the filechooser to pick the next
+ project to load appears.
+
+ Args:
+ project (Project): The project which has been closed.
"""
# We must disconnect from the project pipeline before it is released:
@@ -973,7 +970,7 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
previewer = PreviewWidget(self.settings)
chooser.set_preview_widget(previewer)
chooser.set_use_preview_label(False)
- chooser.connect('update-preview', previewer.add_preview_request)
+ chooser.connect('update-preview', previewer.update_preview_cb)
chooser.set_current_folder(self.settings.lastProjectFolder)
# Use a Gtk FileFilter to only show files with the same extension
# Note that splitext gives us the extension with the ".", no need to
@@ -1048,10 +1045,10 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
# Pitivi current project callbacks
def _setProject(self, project):
- """
- Disconnect and reconnect callbacks to the new current project
+ """Disconnects and then reconnects callbacks to the specified project.
- @type project: L{Project}
+ Args:
+ project (Project): The new current project.
"""
if not project:
self.warning("Current project instance does not exist")
@@ -1074,15 +1071,14 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
# Pitivi current project callbacks
def _renderingSettingsChangedCb(self, project, unused_item=None, unused_value=None):
- """
- When the project setting change, we reset the viewer aspect ratio
- """
+ """Resets the viewer aspect ratio."""
self.viewer.setDisplayAspectRatio(project.getDAR())
self.viewer.timecode_entry.setFramerate(project.videorate)
def _timelineDurationChangedCb(self, timeline, unused_duration):
- """
- When a clip is inserted into a blank timeline, enable the render button.
+ """Updates the render button.
+
+ This covers the case when a clip is inserted into a blank timeline.
This callback is not triggered by loading a project.
"""
duration = timeline.get_duration()
@@ -1186,9 +1182,7 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
return ret
def _screenshotCb(self, unused_action):
- """
- Export a snapshot of the current frame as an image file.
- """
+ """Exports a snapshot of the current frame as an image file."""
foo = self._showSaveScreenshotDialog()
if foo:
path, mime = foo[0], foo[1]
@@ -1196,12 +1190,10 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
-1, -1, mime, path)
def _showSaveScreenshotDialog(self):
- """
- Show a filechooser dialog asking the user where to save the snapshot
- of the current frame and what file type to use.
+ """Asks the user where to save the current frame.
- Returns a list containing the full path and the mimetype if successful,
- returns none otherwise.
+ Returns:
+ List[str]: The full path and the mimetype if successful, None otherwise.
"""
chooser = Gtk.FileChooserDialog(title=_("Save As..."),
transient_for=self, action=Gtk.FileChooserAction.SAVE)
@@ -1225,7 +1217,7 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
chosen_mime = chosen_format[0]
uri = os.path.join(
chooser.get_current_folder(), chooser.get_filename())
- ret = [uri + "." + chosen_ext, chosen_mime]
+ ret = ["%s.%s" % (uri, chosen_ext), chosen_mime]
else:
ret = None
chooser.destroy()
@@ -1291,13 +1283,11 @@ class MainWindow(Gtk.ApplicationWindow, Loggable):
class PreviewAssetWindow(Gtk.Window):
+ """Window for previewing a video or audio asset.
- """
- Window for previewing a video or audio asset.
-
- @ivar asset: The asset to be previewed.
- @type asset: L{GES.UriClipAsset}
- @type main_window: L{MainWindow}
+ Args:
+ asset (GES.UriClipAsset): The asset to be previewed.
+ main_window (MainWindow): The main window.
"""
def __init__(self, asset, main_window):
@@ -1318,9 +1308,7 @@ class PreviewAssetWindow(Gtk.Window):
self.connect("key-press-event", self._keyPressCb)
def preview(self):
- """
- Show the window and start the playback.
- """
+ """Shows the window and starts the playback."""
width, height = self._calculatePreviewWindowSize()
self.resize(width, height)
# Setting the position of the window only works if it's currently hidden
diff --git a/pitivi/mediafilespreviewer.py b/pitivi/mediafilespreviewer.py
index 4d049b3..7d64143 100644
--- a/pitivi/mediafilespreviewer.py
+++ b/pitivi/mediafilespreviewer.py
@@ -69,12 +69,10 @@ ACCEPTABLE_TAGS = [
class PreviewWidget(Gtk.Grid, Loggable):
+ """Widget for displaying a GStreamer sink with playback controls.
- """
- Widget for displaying a GStreamer sink with playback controls.
-
- @ivar settings: The settings of the app.
- @type settings: L{GlobalSettings}
+ Args:
+ settings (GlobalSettings): The settings of the app.
"""
def __init__(self, settings, minimal=False):
@@ -173,9 +171,13 @@ class PreviewWidget(Gtk.Grid, Loggable):
self.bbox.remove(self.b_zoom_in)
self.bbox.remove(self.b_zoom_out)
- def add_preview_request(self, dialogbox):
- """add a preview request """
- uri = dialogbox.get_preview_uri()
+ def update_preview_cb(self, file_chooser):
+ """Previews the URI of the specified file chooser.
+
+ Args:
+ file_chooser (Gtk.FileChooser): The file chooser providing the URI.
+ """
+ uri = file_chooser.get_preview_uri()
if uri is None or not uri_is_valid(uri):
return
self.previewUri(uri)
diff --git a/pitivi/medialibrary.py b/pitivi/medialibrary.py
index f6b5595..3e7f1cb 100644
--- a/pitivi/medialibrary.py
+++ b/pitivi/medialibrary.py
@@ -237,8 +237,11 @@ class ThumbnailsDecorator(Loggable):
class MediaLibraryWidget(Gtk.Box, Loggable):
+ """Widget for managing assets.
- """ Widget for listing sources """
+ Attributes:
+ app (Pitivi): The app.
+ """
__gsignals__ = {
'play': (GObject.SignalFlags.RUN_LAST, None,
@@ -489,8 +492,11 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
@staticmethod
def compare_basename(model, iter1, iter2, unused_user_data):
- """
- Compare the model elements identified by the L{Gtk.TreeIter} elements.
+ """Compares two model elements.
+
+ Args:
+ iter1 (Gtk.TreeIter): The iter identifying the first model element.
+ iter2 (Gtk.TreeIter): The iter identifying the second model element.
"""
uri1 = model[iter1][COL_URI]
uri2 = model[iter2][COL_URI]
@@ -533,10 +539,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
self._showImportSourcesDialog()
def _removeAssetsCb(self, unused_action, unused_parameter):
- """
- Determine which clips are selected in the icon or list view,
- and ask MediaLibrary to remove them from the project.
- """
+ """Removes the selected assets from the project."""
model = self.treeview.get_model()
paths = self.getSelectedPaths()
if not paths:
@@ -584,13 +587,11 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
self.iconview.grab_focus()
def _setRowVisible(self, model, iter, data):
- """
- Toggle the visibility of a liststore row.
- Used for the search box.
- """
+ """Toggles the visibility of a liststore row."""
text = data.get_text().lower()
if not text:
- return True # Avoid silly warnings
+ # Avoid silly warnings.
+ return True
# We must convert to markup form to be able to search for &, ', etc.
text = GLib.markup_escape_text(text)
return text in model.get_value(iter, COL_INFOTEXT).lower()
@@ -612,9 +613,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
return icon
def _connectToProject(self, project):
- """
- Connect signal handlers to a project.
- """
+ """Connects signal handlers to the specified project."""
project.connect("asset-added", self._assetAddedCb)
project.connect("asset-loading-progress", self._assetLoadingProgressCb)
project.connect("asset-removed", self._assetRemovedCb)
@@ -623,9 +622,10 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
project.connect("settings-set-from-imported-asset", self.__projectSettingsSetFromImportedAssetCb)
def _setClipView(self, view_type):
- """
- Set which clip view to use when medialibrary is showing clips.
- view_type: one of SHOW_TREEVIEW or SHOW_ICONVIEW
+ """Sets which clip view to use when medialibrary is showing clips.
+
+ Args:
+ view_type (int): One of SHOW_TREEVIEW or SHOW_ICONVIEW.
"""
self.app.settings.lastClipView = view_type
# Gather some info before switching views
@@ -665,7 +665,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
return True
def _showImportSourcesDialog(self):
- """Pop up the "Import Sources" dialog box"""
+ """Pops up the "Import Sources" dialog box."""
if self._importDialog:
return
@@ -690,7 +690,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
self._importDialog.set_preview_widget(previewer)
self._importDialog.set_use_preview_label(False)
self._importDialog.connect(
- 'update-preview', previewer.add_preview_request)
+ 'update-preview', previewer.update_preview_cb)
# Filter for the "known good" formats by default
filt_supported = Gtk.FileFilter()
filt_supported.set_name(_("Supported file formats"))
@@ -706,26 +706,30 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
self._importDialog.show()
def _getThumbnailInDir(self, dir, hash):
- """
- For a given thumbnail cache directory and file URI hash, see if there're
- thumbnails available and return them in resolutions that pitivi expects.
+ """Gets pixbufs for the specified thumbnail.
+
+ Args:
+ dir (str): The directory where the thumbnails can be found.
+ hash (str): The hash identifying the image.
- The cache dirs might have resolutions of 256 and/or 128,
- while we need 128 (for iconview) and 64 (for listview).
+ Returns:
+ List[GdkPixbuf.Pixbuf]: The thumb_64 and thumb_128 if available,
+ None otherwise.
"""
- path_256 = dir + "large/" + hash + ".png"
path_128 = dir + "normal/" + hash + ".png"
interpolation = GdkPixbuf.InterpType.BILINEAR
- # First, try the 128 version since that's the native resolution we
- # want:
+ # The cache dirs might have resolutions of 256 and/or 128,
+ # while we need 128 (for iconview) and 64 (for listview).
+ # First, try the 128 version since that's the native resolution we want.
try:
thumb_128 = GdkPixbuf.Pixbuf.new_from_file(path_128)
w, h = thumb_128.get_width(), thumb_128.get_height()
thumb_64 = thumb_128.scale_simple(w / 2, h / 2, interpolation)
return thumb_64, thumb_128
except GLib.GError:
- # path_128 doesn't exist, try the 256 version
+ # path_128 doesn't exist, try the 256 version.
+ path_256 = dir + "large/" + hash + ".png"
try:
thumb_256 = GdkPixbuf.Pixbuf.new_from_file(path_256)
w, h = thumb_256.get_width(), thumb_256.get_height()
@@ -895,8 +899,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
self.app.gui.timeline_ui.switchProxies(asset)
def _assetAddedCb(self, unused_project, asset):
- """ a file was added to the medialibrary """
-
+ """Checks whether the asset added to the project should be shown."""
if asset in [row[COL_ASSET] for row in self.storemodel]:
self.info("Asset %s already in!", asset.props.id)
return
@@ -906,8 +909,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
asset.connect("notify::proxy", self.__assetProxiedCb)
asset.connect("notify::proxy-target", self.__assetProxyingCb)
if asset.get_proxy():
- self.debug("Not adding asset %s "
- "as it is proxied by %s",
+ self.debug("Not adding asset %s, its proxy is used instead: %s",
asset.props.id,
asset.get_proxy().props.id)
return
@@ -921,9 +923,9 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
self.__removeAsset(asset)
def __removeAsset(self, asset):
- """ the given uri was removed from the medialibrary """
- # find the good line in the storemodel and remove it
+ """Removes the specified asset."""
uri = asset.get_id()
+ # Find the corresponding line in the storemodel and remove it.
found = False
for row in self.storemodel:
if uri == row[COL_URI]:
@@ -932,7 +934,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
break
if not found:
- self.info("Trying to removed %s but that was not found"
+ self.info("Failed to remove %s as it was not found"
"in the liststore", uri)
def _proxyingErrorCb(self, unused_project, asset):
@@ -940,8 +942,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
self._addAsset(asset)
def _errorCreatingAssetCb(self, unused_project, error, id, type):
- """ The given uri isn't a media file """
-
+ """Gathers asset loading errors."""
if GObject.type_is_a(type, GES.UriClip):
if self.app.proxy_manager.isProxyAsset(id):
self.debug("Error %s with a proxy"
@@ -1056,7 +1057,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
self._importDialog = None
def _sourceIsUsed(self, asset):
- """Check if a given URI is present in the timeline"""
+ """Checks whether the specified asset is present in the timeline."""
layers = self._project.ges_timeline.get_layers()
for layer in layers:
for clip in layer.get_clips():
@@ -1065,9 +1066,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
return False
def _selectUnusedSources(self):
- """
- Select the assets not used by any clip in the project's timeline.
- """
+ """Selects the assets not used by any clip in the project's timeline."""
unused_sources_uris = []
for asset in self._project.list_assets(GES.UriClip):
if not self._sourceIsUsed(asset):
@@ -1105,9 +1104,9 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
infobar.hide()
def _clipPropertiesCb(self, unused_widget=None):
- """
- Show the clip properties (resolution, framerate, audio channels...)
- and allow setting them as the new project settings.
+ """Shows the clip properties in a dialog.
+
+ Allows selecting and applying them as the new project settings.
"""
paths = self.getSelectedPaths()
if not paths:
@@ -1131,9 +1130,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
self._import_warning_infobar.hide()
def __showErrors(self):
- """
- Show a FileListErrorDialog to display import _errors.
- """
+ """Shows a dialog with the import errors."""
if len(self._errors) > 1:
msgs = (_("Error while analyzing files"),
_("The following files can not be used with Pitivi."))
@@ -1372,10 +1369,11 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
# Some actions can only be done on a single item at a time:
self._clipprops_button.set_sensitive(selected_count == 1)
- def _itemOrRowActivatedCb(self, unused_view, path, *unused_column):
- """
- When an item is double-clicked, or
- Space, Shift+Space, Return or Enter is pressed, preview the clip.
+ def _itemOrRowActivatedCb(self, unused_view, path, *unused_args):
+ """Plays the asset identified by the specified path.
+
+ This can happen when an item is double-clicked, or
+ Space, Shift+Space, Return or Enter is pressed.
This method is the same for both iconview and treeview.
"""
asset = self.modelFilter[path][COL_ASSET]
@@ -1515,7 +1513,11 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
self.dragged = False
def getSelectedPaths(self):
- """ Returns a list of selected treeview or iconview items """
+ """Gets which treeview or iconview items are selected.
+
+ Returns:
+ List[Gtk.TreePath]: The paths identifying the items.
+ """
if self.clip_view == SHOW_TREEVIEW:
return self._getSelectedPathsTreeView()
elif self.clip_view == SHOW_ICONVIEW:
@@ -1531,7 +1533,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
return paths
def getSelectedItems(self):
- """ Returns a list of selected items URIs """
+ """Gets the URIs of the selected items."""
if self._draggedPaths:
return [self.modelFilter[path][COL_URI]
for path in self._draggedPaths]
@@ -1539,7 +1541,7 @@ class MediaLibraryWidget(Gtk.Box, Loggable):
for path in self.getSelectedPaths()]
def getSelectedAssets(self):
- """ Returns a list of selected items URIs """
+ """Gets the selected assets."""
if self._draggedPaths:
return [self.modelFilter[path][COL_ASSET]
for path in self._draggedPaths]
diff --git a/pitivi/preset.py b/pitivi/preset.py
index 9114bff..0485e76 100644
--- a/pitivi/preset.py
+++ b/pitivi/preset.py
@@ -37,24 +37,18 @@ class DeserializeException(Exception):
class PresetManager(GObject.Object, Loggable):
-
"""Abstract class for storing a list of presets.
Subclasses must provide a filename attribute.
- @cvar filename: The name of the file where the presets will be stored.
- @type filename: str
-
- @ivar cur_preset: The currently selected preset. Note that a preset has to
- be selected before it can be changed.
- @type cur_preset: str
- @ivar ordered: A list holding (name, preset_dict) tuples.
- @type ordered: Gtk.ListStore
- @ivar presets: A (name -> preset_dict) map.
- @type presets: dict
- @ivar widget_map: A (propname -> (setter_func, getter_func)) map.
- These two functions are used when showing or saving a preset.
- @type widget_map: dict
+ Attributes:
+ filename (str): The name of the file where the presets will be stored.
+ cur_preset (str): The currently selected preset. Note that a preset
+ has to be selected before it can be changed.
+ ordered (Gtk.ListStore): A list holding (name, preset_dict) tuples.
+ presets (dict): A (name -> preset_dict) map.
+ widget_map (dict): A (propname -> (setter_func, getter_func)) map.
+ These two functions are used when showing or saving a preset.
"""
__gsignals__ = {
@@ -117,7 +111,7 @@ class PresetManager(GObject.Object, Loggable):
button.set_popup(menu)
def _presetChangedCb(self, combo):
- """Handle the selection of a preset."""
+ """Handles the selection of a preset."""
# Check whether the user selected a preset or editing the preset name.
preset_name = combo.get_active_id()
if preset_name:
@@ -193,7 +187,7 @@ class PresetManager(GObject.Object, Loggable):
self._addPreset(name, preset)
def saveAll(self):
- """Write changes to disk for all presets"""
+ """Writes changes to disk for all presets."""
for preset_name, values in self.ordered:
self._savePreset(preset_name)
@@ -217,7 +211,7 @@ class PresetManager(GObject.Object, Loggable):
return os.path.join(self.user_path, file_name)
def getNewPresetName(self):
- """Get a unique name for a new preset."""
+ """Gets a unique name for a new preset."""
name = _("New preset")
i = 1
while self.hasPreset(name):
@@ -226,12 +220,11 @@ class PresetManager(GObject.Object, Loggable):
return name
def createPreset(self, name, values=None):
- """Create a preset, overwriting the preset with the same name if any.
+ """Creates a preset, overwriting the preset with the same name if any.
- @param name: The name of the new preset.
- @type name: str
- @param values: The values of the new preset.
- @type values: dict
+ Args:
+ name (str): The name of the new preset.
+ values (dict): The values of the new preset.
"""
if not values:
values = {}
@@ -246,7 +239,7 @@ class PresetManager(GObject.Object, Loggable):
self.ordered.append((name, values))
def _renameCurrentPreset(self, new_name):
- """Change the name of the current preset."""
+ """Changes the name of the current preset."""
old_name = self.cur_preset
if old_name == new_name:
# Nothing to do.
@@ -280,11 +273,11 @@ class PresetManager(GObject.Object, Loggable):
return (row[0] for row in self.ordered)
def getModel(self):
- """Get the GtkModel used by the UI."""
+ """Gets the GtkModel used by the UI."""
return self.ordered
def updateValue(self, name, value):
- """Update a value in the current preset, if any."""
+ """Updates a value in the current preset, if any."""
if self.ignore_update_requests:
# This is caused by restorePreset, nothing to do.
return
@@ -292,14 +285,14 @@ class PresetManager(GObject.Object, Loggable):
self.presets[self.cur_preset][name] = value
def bindWidget(self, propname, setter_func, getter_func):
- """Link the specified functions to the specified preset property."""
+ """Links the specified functions to the specified preset property."""
self.widget_map[propname] = (setter_func, getter_func)
def restorePreset(self, preset):
- """Select a preset and copy the values from the preset to the widgets.
+ """Selects a preset and copies its values to the widgets.
- @param preset: The name of the preset to be selected.
- @type preset: str
+ Args:
+ preset (str): The name of the preset to be selected.
"""
if preset is None:
self.cur_preset = None
@@ -316,7 +309,7 @@ class PresetManager(GObject.Object, Loggable):
self.ignore_update_requests = False
def saveCurrentPreset(self, new_name=None):
- """Update the current preset values from the widgets and save it."""
+ """Updates the current preset values from the widgets and saves it."""
if new_name:
self._renameCurrentPreset(new_name)
values = self.presets[self.cur_preset]
@@ -324,12 +317,12 @@ class PresetManager(GObject.Object, Loggable):
self._savePreset(self.cur_preset)
def _updatePresetValues(self, values):
- """Copy the values from the widgets to the specified values dict."""
+ """Copies the values from the widgets to the specified values dict."""
for field, (setter, getter) in self.widget_map.items():
values[field] = getter()
def _isCurrentPresetChanged(self, name):
- """Return whether the widgets values differ from those of the preset."""
+ """Returns whether the widgets values differ from the preset values."""
if not self.cur_preset:
# There is no preset selected, nothing to do.
return False
@@ -375,10 +368,10 @@ class PresetManager(GObject.Object, Loggable):
self.ordered.prepend((name, values))
def isSaveButtonSensitive(self, name):
- """Whether the Save button should be enabled.
+ """Checks whether the Save button should be enabled.
- @param name: The new preset name.
- @type name: str
+ Args:
+ name (str): The new preset name.
"""
if self.cur_preset:
return self._isCurrentPresetChanged(name)
@@ -390,13 +383,13 @@ class PresetManager(GObject.Object, Loggable):
return False
def isRemoveButtonSensitive(self):
- """Whether the Remove button should be enabled"""
+ """Checks whether the Remove button should be enabled."""
if not self.cur_preset:
return False
return True
def isNewButtonSensitive(self):
- """Whether the New button should be enabled"""
+ """Checks whether the New button should be enabled."""
return bool(self.cur_preset)
def _projectToPreset(self, project):
diff --git a/pitivi/project.py b/pitivi/project.py
index 8c4ec51..8e9d969 100644
--- a/pitivi/project.py
+++ b/pitivi/project.py
@@ -17,9 +17,7 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-Project related classes
-"""
+"""Project related classes."""
import datetime
import os
import pwd
@@ -138,9 +136,7 @@ class ProjectManager(GObject.Object, Loggable):
return False
def _projectPipelineDiedCb(self, unused_pipeline):
- """
- Show an error dialog telling the user that everything went kaboom.
- """
+ """Shows an dialog telling the user that everything went kaboom."""
# GTK does not allow an empty string as the dialog title, so we use the
# same translatable one as render.py's pipeline error message dialog:
dialog = Gtk.Dialog(title=_("Sorry, something didn’t work right."),
@@ -206,10 +202,10 @@ class ProjectManager(GObject.Object, Loggable):
self.app.shutdown()
def loadProject(self, uri):
- """
- Load the given URI as a project. If a backup file exists, ask if it
- should be loaded instead, and if so, force the user to use "Save as"
- afterwards.
+ """Loads the specified URI as a project.
+
+ If a backup file exists, asks if it should be loaded instead, and if so,
+ forces the user to use "Save as" afterwards.
"""
if self.current_project is not None and not self.closeRunningProject():
return False
@@ -247,10 +243,10 @@ class ProjectManager(GObject.Object, Loggable):
return True
def _restoreFromBackupDialog(self, time_diff):
- """
- Ask if we need to load the autosaved project backup or not.
+ """Asks if we need to load the autosaved project backup.
- @param time_diff: the difference, in seconds, between file mtimes
+ Args:
+ time_diff (int): The difference, in seconds, between file mtimes.
"""
dialog = Gtk.Dialog(title="", transient_for=None)
dialog.add_buttons(_("Ignore backup"), Gtk.ResponseType.REJECT,
@@ -304,19 +300,21 @@ class ProjectManager(GObject.Object, Loggable):
return False
def saveProject(self, uri=None, formatter_type=None, backup=False):
- """
- Save the current project. All arguments are optional, but the behavior
- will differ depending on the combination of which ones are set.
+ """Saves the current project.
- If a URI is specified, this means we want to save to a new (different)
- location, so it will be used instead of the current project instance's
- existing URI.
-
- "backup=True" is for automatic backups: it ignores any "uri" arg, uses
- the current project instance to save to a special URI behind the scenes.
-
- "formatter_type" allows specifying a GES formatter type to use; if None,
- GES will default to GES.XmlFormatter.
+ Args:
+ uri (Optional[str]): If a URI is specified, this means we want to
+ save to a new (different) location, so it will be used instead
+ of the current project's existing URI.
+ formatter_type (Optional[GES.Formatter]): The formatter to use for
+ serializing the project. If None, GES defaults to
+ GES.XmlFormatter.
+ backup (Optional[bool]): Whether to ignore the `uri` arg and save
+ the project to a special backup URI built out of the current
+ project's URI. Intended for automatic backup behind the scenes.
+
+ Returns:
+ bool: Whether the project has been saved successfully.
"""
if self.disable_save is True and (backup is True or uri is None):
self.log(
@@ -375,11 +373,8 @@ class ProjectManager(GObject.Object, Loggable):
return saved
def exportProject(self, project, uri):
- """
- Export a project to a *.tar archive which includes the project file
- and all sources
- """
- # write project file to temporary file
+ """Exports a project and all its media files to a *.tar archive."""
+ # Save the project to a temporary file.
project_name = project.name if project.name else _("project")
asset = GES.Formatter.get_default()
project_extension = asset.get_meta(GES.META_FORMATTER_EXTENSION)
@@ -438,9 +433,7 @@ class ProjectManager(GObject.Object, Loggable):
return everything_ok
def _allSourcesInHomedir(self, sources):
- """
- Checks if all sources are located in the users home directory
- """
+ """Checks if all sources are located in the user's home directory."""
homedir = os.path.expanduser("~")
for source in sources:
@@ -450,7 +443,7 @@ class ProjectManager(GObject.Object, Loggable):
return True
def closeRunningProject(self):
- """ close the current project """
+ """Closes the current project."""
if self.current_project is None:
self.warning(
"Trying to close a project that was already closed/didn't exist")
@@ -485,12 +478,16 @@ class ProjectManager(GObject.Object, Loggable):
return True
def newBlankProject(self, ignore_unsaved_changes=False):
- """
- Start up a new blank project.
+ """Creates a new blank project and sets it as the current project.
+
+ Args:
+ ignore_unsaved_changes (Optional[bool]): If True, forces
+ the creation of a new project without prompting the user about
+ unsaved changes. This is an "extreme" way to reset Pitivi's
+ state.
- The ignore_unsaved_changes parameter is used in special cases to force
- the creation of a new project without prompting the user about unsaved
- changes. This is an "extreme" way to reset Pitivi's state.
+ Returns:
+ bool: Whether the project has been created successfully.
"""
self.debug("New blank project")
if self.current_project is not None:
@@ -520,9 +517,7 @@ class ProjectManager(GObject.Object, Loggable):
return True
def revertToSavedProject(self):
- """
- Discard all unsaved changes and reload current open project
- """
+ """Discards all unsaved changes and reloads the current open project."""
if self.current_project.uri is None or not self.current_project.hasUnsavedModifications():
return True
if not self.emit("reverting-to-saved", self.current_project):
@@ -568,12 +563,16 @@ class ProjectManager(GObject.Object, Loggable):
self.debug('Removed backup file: %s', path)
def _makeBackupURI(self, uri):
- """
- Returns a backup file URI (or path if the given arg is not a URI).
+ """Generates a corresponding backup URI or path.
+
This does not guarantee that the backup file actually exists or that
the file extension is actually a project file.
- @Param the project file path or URI
+ Args:
+ uri (str): The project URI or file path.
+
+ Returns:
+ str: The backup version of the `uri`.
"""
name, ext = os.path.splitext(uri)
return name + ext + "~"
@@ -605,9 +604,14 @@ class Project(Loggable, GES.Project):
pipeline (Pipeline): The timeline's pipeline.
loaded (bool): Whether the project is fully loaded.
+ Args:
+ name (Optional[str]): The name of the new empty project.
+ uri (Optional[str]): The URI of the file where the project should
+ be loaded from.
+
Signals:
- project-changed: Modifications were made to the project
- start-importing: Started to import files
+ project-changed: Modifications were made to the project.
+ start-importing: Started to import files.
"""
__gsignals__ = {
@@ -627,12 +631,6 @@ class Project(Loggable, GES.Project):
}
def __init__(self, app, name="", uri=None, scenario=None, **unused_kwargs):
- """
- Args:
- name (Optional[str]): The name of the new empty project.
- uri (Optional[str]): The URI of the file where the project should
- be loaded from.
- """
Loggable.__init__(self)
GES.Project.__init__(self, uri=uri, extractable_type=GES.Timeline)
self.log("name:%s, uri:%s", name, uri)
@@ -1069,10 +1067,7 @@ class Project(Loggable, GES.Project):
self.app.proxy_manager.cancelJob(asset)
def do_asset_added(self, asset):
- """
- When GES.Project emit "asset-added" this vmethod
- get calls
- """
+ """Handles `GES.Project::asset-added` emitted by self."""
self._maybeInitSettingsFromAsset(asset)
if asset and not GObject.type_is_a(asset.get_extractable_type(),
GES.UriClip):
@@ -1095,7 +1090,7 @@ class Project(Loggable, GES.Project):
self.__updateAssetLoadingProgress()
def do_loading_error(self, error, asset_id, unused_type):
- """ vmethod, get called on "asset-loading-error"""
+ """Handles `GES.Project::error-loading-asset` emitted by self."""
if not self.loaded:
self.info("Error loading asset %s while loading a project"
" not updating proxy creation progress", asset_id)
@@ -1115,8 +1110,7 @@ class Project(Loggable, GES.Project):
self.__updateAssetLoadingProgress()
def do_loaded(self, unused_timeline):
- """ vmethod, get called on "loaded" """
-
+ """Handles `GES.Project::loaded` emitted by self."""
if not self.ges_timeline:
return
@@ -1166,9 +1160,9 @@ class Project(Loggable, GES.Project):
# ------------------------------------------ #
def finalize(self):
- """
- Disconnect all signals and everything so that the project won't
- be doing anything after the call to the method.
+ """Disconnects all signals and everything.
+
+ Makes sure the project won't be doing anything after the call.
"""
if self._scenario:
self._scenario.disconnect_by_func(self._scenarioDoneCb)
@@ -1216,17 +1210,16 @@ class Project(Loggable, GES.Project):
return DEFAULT_NAME == self.name
def _commit(self):
- """
- Our override of the GES.Timeline.commit method, letting us
- scenarialize the action in the scenarios.
+ """Logs the operation and commits.
+
+ To be used as a replacement for the GES.Timeline.commit method, allowing
+ to scenarialize the action in the scenarios.
"""
self.app.write_action("commit")
GES.Timeline.commit(self.ges_timeline)
def createTimeline(self):
- """
- Load the project.
- """
+ """Loads the project's timeline."""
try:
# The project is loaded from the file in this call.
self.ges_timeline = self.extract()
@@ -1267,12 +1260,11 @@ class Project(Loggable, GES.Project):
self.pipeline.flushSeek()
def addUris(self, uris):
- """
- Add c{uris} asynchronously.
+ """Adds assets asynchronously.
- The uris will be analyzed before being added, so only valid ones pass.
+ Args:
+ uris (List[str]): The URIs of the assets.
"""
- # Do not try to reload URIS that we already have loaded
self.app.action_log.begin("Adding assets")
for uri in uris:
self.create_asset(quote_uri(uri), GES.UriClip)
@@ -1322,10 +1314,11 @@ class Project(Loggable, GES.Project):
return Gst.Fraction(self.videowidth, self.videoheight) * self.videopar
def getVideoWidthAndHeight(self, render=False):
- """ Returns the video width and height as a tuple
+ """Returns the video width and height as a tuple.
- @param render: Whether to apply self.render_scale to the returned values
- @type render: bool
+ Args:
+ render (bool): Whether to apply self.render_scale to the returned
+ values.
"""
if render:
if not self._has_rendering_values:
@@ -1341,7 +1334,11 @@ class Project(Loggable, GES.Project):
return self.videowidth, self.videoheight
def getVideoCaps(self, render=False):
- """ Returns the GstCaps corresponding to the video settings """
+ """Gets the caps corresponding to the video settings.
+
+ Returns:
+ Gst.Caps: The video settings caps.
+ """
videowidth, videoheight = self.getVideoWidthAndHeight(render=render)
vstr = "width=%d,height=%d,pixel-aspect-ratio=%d/%d,framerate=%d/%d" % (
videowidth, videoheight,
@@ -1352,16 +1349,18 @@ class Project(Loggable, GES.Project):
return video_caps
def getAudioCaps(self):
- """ Returns the GstCaps corresponding to the audio settings """
+ """Gets the caps corresponding to the audio settings.
+
+ Returns:
+ Gst.Caps: The audio settings caps.
+ """
astr = "rate=%d,channels=%d" % (self.audiorate, self.audiochannels)
caps_str = "audio/x-raw,%s" % (astr)
audio_caps = Gst.caps_from_string(caps_str)
return audio_caps
def setAudioProperties(self, nbchanns=-1, rate=-1):
- """
- Set the number of audio channels and the rate
- """
+ """Sets the number of audio channels and the rate."""
self.info("%d x %dHz %dbits", nbchanns, rate)
if not nbchanns == -1 and not nbchanns == self.audiochannels:
self.audiochannels = nbchanns
@@ -1369,7 +1368,7 @@ class Project(Loggable, GES.Project):
self.audiorate = rate
def setEncoders(self, muxer="", vencoder="", aencoder=""):
- """ Set the video/audio encoder and muxer """
+ """Sets the video and audio encoders and the muxer."""
if not muxer == "" and not muxer == self.muxer:
self.muxer = muxer
if not vencoder == "" and not vencoder == self.vencoder:
@@ -1442,7 +1441,11 @@ class Project(Loggable, GES.Project):
self.audiorate = 44100
def _maybeInitSettingsFromAsset(self, asset):
- """Update the project settings to match the specified asset."""
+ """Updates the project settings to match the specified asset.
+
+ Args:
+ asset (GES.UriClipAsset): The asset to copy the settings from.
+ """
if not (self._has_default_video_settings or
self._has_default_audio_settings):
# Both audio and video settings have been set already by the user.
@@ -1496,13 +1499,11 @@ class Project(Loggable, GES.Project):
# ---------------------- UI classes ----------------------------------------- #
class ProjectSettingsDialog(object):
-
- """
- UI for viewing and changing the project settings.
+ """Manager of a dialog for viewing and changing the project settings.
Attributes:
project (Project): The project who's settings are displayed.
- app (pitivi.application.Pitivi): The current app.
+ app (Pitivi): The current app.
"""
def __init__(self, parent_window, project, app):
@@ -1519,9 +1520,7 @@ class ProjectSettingsDialog(object):
self.video_presets.disconnect_by_func(self.__videoPresetLoadedCb)
def _createUi(self):
- """
- Initialize the static parts of the UI and set up various shortcuts
- """
+ """Initializes the static parts of the UI."""
self.builder = Gtk.Builder()
self.builder.add_from_file(
os.path.join(get_ui_dir(), "projectsettings.ui"))
@@ -1556,10 +1555,7 @@ class ProjectSettingsDialog(object):
self.audio_preset_menubutton)
def _setupUiConstraints(self):
- """
- Create dynamic widgets and
- set up the relationships between various widgets
- """
+ """Creates the dynamic widgets and connects other widgets."""
# Add custom fraction widgets for DAR and PAR.
aspect_ratio_grid = self.builder.get_object("aspect_ratio_grid")
self.dar_fraction_widget = FractionWidget()
@@ -1832,7 +1828,7 @@ class ProjectSettingsDialog(object):
self.project.audiorate = get_combo_value(self.sample_rate_combo)
def _responseCb(self, unused_widget, response):
- """Handle the dialog being closed."""
+ """Handles the dialog being closed."""
if response == Gtk.ResponseType.OK:
self.updateProject()
self.window.destroy()
diff --git a/pitivi/render.py b/pitivi/render.py
index c611c63..9170915 100644
--- a/pitivi/render.py
+++ b/pitivi/render.py
@@ -16,9 +16,7 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-Rendering-related utilities and classes
-"""
+"""Rendering-related classes and utilities."""
import os
import subprocess
import time
@@ -47,30 +45,26 @@ from pitivi.utils.widgets import GstElementSettingsDialog
class CachedEncoderList(object):
+ """Registry of avalaible Muxers, Audio encoders and Video Encoders.
- """
- Registry of avalaible Muxer/Audio encoder/Video Encoder. And
- avalaible combinations of those.
-
- You can acces directly the
-
- @aencoders: List of avalaible audio encoders
- @vencoders: List of avalaible video encoders
- @muxers: List of avalaible muxers
- @audio_combination: Dictionary from muxer names to compatible audio encoders ordered by Rank
- @video_combination: Dictionary from muxer names to compatible video encoders ordered by Rank
-
+ Also keeps the avalaible combinations of those.
It is a singleton.
+
+ Attributes:
+ aencoders (List[Gst.ElementFactory]): The avalaible audio encoders.
+ vencoders (List[Gst.ElementFactory]): The avalaible video encoders.
+ muxers (List[Gst.ElementFactory]): The avalaible muxers.
+ audio_combination (dict): Maps each muxer name to a list of compatible
+ audio encoders ordered by rank.
+ video_combination (dict): Maps each muxer name to a list of compatible
+ video encoders ordered by rank.
"""
_instance = None
def __new__(cls, *args, **kwargs):
- """
- Override the new method to return the singleton instance if available.
- Otherwise, create one.
- """
+ """Returns the singleton instance."""
if not cls._instance:
cls._instance = super(
CachedEncoderList, cls).__new__(cls, *args, **kwargs)
@@ -117,7 +111,7 @@ class CachedEncoderList(object):
self.muxers.remove(muxer)
def _findCompatibleEncoders(self, encoders, muxer, muxsinkcaps=[]):
- """ returns the list of encoders compatible with the given muxer """
+ """Returns the list of encoders compatible with the specified muxer."""
res = []
if muxsinkcaps == []:
muxsinkcaps = [x.get_caps() for x in muxer.get_static_pad_templates()
@@ -131,8 +125,14 @@ class CachedEncoderList(object):
return res
def _canSinkCaps(self, muxer, ocaps, muxsinkcaps=[]):
- """ returns True if the given caps intersect with some of the muxer's
- sink pad templates' caps.
+ """Checks whether the muxer's receptors match the specified caps.
+
+ Args:
+ ocaps (Gst.Caps): The output caps to match.
+
+ Returns:
+ bool: True if any of the muxer's sink pad templates's caps intersect
+ the specified output caps.
"""
# fast version
if muxsinkcaps != []:
@@ -147,24 +147,18 @@ class CachedEncoderList(object):
return True
return False
- # sinkcaps = (x.get_caps() for x in muxer.get_static_pad_templates() if x.direction ==
Gst.PadDirection.SINK)
- # for x in sinkcaps:
- # if not x.intersect(ocaps).is_empty():
- # return True
- # return False
-
def _registryFeatureAddedCb(self, registry, feature):
# TODO Check what feature has been added and update our lists
pass
def beautify_factoryname(factory):
+ """Returns a nice name for the specified Gst.ElementFactory instance.
+
+ Intended for removing redundant words and shorten the codec names.
"""
- Returns a nice name for the specified Gst.ElementFactory instance.
- This is intended to remove redundant words and shorten the codec names.
- """
- # only replace lowercase versions of "format", "video", "audio"
- # otherwise they might be part of a trademark name
+ # Only replace lowercase versions of "format", "video", "audio"
+ # otherwise they might be part of a trademark name.
words_to_remove = ["Muxer", "muxer", "Encoder", "encoder",
"format", "video", "audio", "instead",
# Incorrect naming for Sorenson Spark:
@@ -212,10 +206,13 @@ def extension_for_muxer(muxer):
def factorylist(factories):
- """Create a Gtk.ListStore() of sorted, beautified factory names.
+ """Creates a Gtk.ListStore() of sorted, beautified factory names.
+
+ Args:
+ factories (List[Gst.ElementFactory]): The factories for display.
- @param factories: The factories available for creating the list.
- @type factories: A sequence of Gst.ElementFactory instances.
+ Returns:
+ Gtk.ListStore: The model with to columns for name and factory.
"""
columns = (str, object)
data = [(beautify_factoryname(factory), factory)
@@ -292,7 +289,8 @@ class RenderingProgressDialog(GObject.Object):
self._filesize_est_value_label.show()
def _deleteEventCb(self, unused_dialog_widget, unused_event):
- """If the user closes the window by pressing Escape, stop rendering"""
+ """Stops the rendering."""
+ # The user closed the window by pressing Escape.
self.emit("cancel")
def _cancelButtonClickedCb(self, unused_button):
@@ -312,22 +310,21 @@ class RenderingProgressDialog(GObject.Object):
class RenderDialog(Loggable):
-
"""Render dialog box.
- @type app: L{pitivi.application.Pitivi}
- @ivar preferred_aencoder: The last audio encoder selected by the user.
- @type preferred_aencoder: str
- @ivar preferred_vencoder: The last video encoder selected by the user.
- @type preferred_vencoder: str
- @type project: L{pitivi.project.Project}
+ Args:
+ app (Pitivi): The app.
+ project (Project): The project to be rendered.
+
+ Attributes:
+ preferred_aencoder (str): The last audio encoder selected by the user.
+ preferred_vencoder (str): The last video encoder selected by the user.
"""
INHIBIT_REASON = _("Currently rendering")
_factory_formats = {}
def __init__(self, app, project):
-
from pitivi.preset import RenderPresetManager
Loggable.__init__(self)
@@ -534,8 +531,7 @@ class RenderDialog(Loggable):
self.muxercombobox.set_model(factorylist(CachedEncoderList().muxers))
def _displaySettings(self):
- """Display the settings that also change in the ProjectSettingsDialog.
- """
+ """Displays the settings also in the ProjectSettingsDialog."""
# Video settings
set_combo_value(self.frame_rate_combo, self.project.videorate)
# Audio settings
@@ -543,20 +539,17 @@ class RenderDialog(Loggable):
set_combo_value(self.sample_rate_combo, self.project.audiorate)
def _displayRenderSettings(self):
- """Display the settings which can be changed only in the RenderDialog.
- """
+ """Displays the settings available only in the RenderDialog."""
# Video settings
- # note: this will trigger an update of the video resolution label
+ # This will trigger an update of the video resolution label.
self.scale_spinbutton.set_value(self.project.render_scale)
# Muxer settings
- # note: this will trigger an update of the codec comboboxes
+ # This will trigger an update of the codec comboboxes.
set_combo_value(self.muxercombobox,
Gst.ElementFactory.find(self.project.muxer))
def _checkForExistingFile(self, *unused_args):
- """
- Display a warning icon and tooltip if the file path already exists.
- """
+ """Displays a warning if the file path already exists."""
path = self.filebutton.get_current_folder()
if not path:
# This happens when the window is initialized.
@@ -576,13 +569,14 @@ class RenderDialog(Loggable):
self.fileentry.set_icon_tooltip_text(1, tooltip_text)
def _getFilesizeEstimate(self):
- """
- Using the current render output's filesize and position in the timeline,
- return a human-readable (ex: "14 MB") estimate of the final filesize.
+ """Estimates the final file size.
Estimates in megabytes (over 30 MB) are rounded to the nearest 10 MB
to smooth out small variations. You'd be surprised how imprecision can
improve perceived accuracy.
+
+ Returns:
+ str: A human-readable (ex: "14 MB") estimate for the file size.
"""
if not self.current_position or self.current_position == 0:
return None
@@ -612,7 +606,7 @@ class RenderDialog(Loggable):
self.fileentry.set_text(name)
def updateAvailableEncoders(self):
- """Update the encoder comboboxes to show the available encoders."""
+ """Updates the encoder comboboxes to show the available encoders."""
encoders = CachedEncoderList()
vencoder_model = factorylist(
encoders.video_combination[self.project.muxer])
@@ -628,7 +622,7 @@ class RenderDialog(Loggable):
self.audio_encoder_combo, self.preferred_aencoder)
def _updateEncoderCombo(self, encoder_combo, preferred_encoder):
- """Select the specified encoder for the specified encoder combo."""
+ """Selects the specified encoder for the specified encoder combo."""
if preferred_encoder:
# A preference exists, pick it if it can be found in
# the current model of the combobox.
@@ -640,13 +634,11 @@ class RenderDialog(Loggable):
encoder_combo.set_active(0)
def _elementSettingsDialog(self, factory, settings_attr):
- """Open a dialog to edit the properties for the specified factory.
+ """Opens a dialog to edit the properties for the specified factory.
- @param factory: An element factory whose properties the user will edit.
- @type factory: Gst.ElementFactory
- @param settings_attr: The MultimediaSettings attribute holding
- the properties.
- @type settings_attr: str
+ Args:
+ factory (Gst.ElementFactory): The factory for editing.
+ settings_attr (str): The Project attribute holding the properties.
"""
properties = getattr(self.project, settings_attr)
self.dialog = GstElementSettingsDialog(factory, properties=properties,
@@ -671,7 +663,7 @@ class RenderDialog(Loggable):
dialog.destroy()
def startAction(self):
- """ Start the render process """
+ """Starts the render process."""
self._pipeline.set_state(Gst.State.NULL)
# FIXME: https://github.com/pitivi/gst-editing-services/issues/23
self._pipeline.set_mode(GES.PipelineFlags.RENDER)
@@ -690,7 +682,7 @@ class RenderDialog(Loggable):
self._destroyProgressWindow()
def _shutDown(self):
- """Shutdown the gstreamer pipeline and disconnect from its signals."""
+ """Shuts down the pipeline and disconnects from its signals."""
self._is_rendering = False
self._rendering_is_paused = False
self._time_spent_paused = 0
@@ -714,7 +706,7 @@ class RenderDialog(Loggable):
self.project.pipeline.togglePlayback()
def _destroyProgressWindow(self):
- """ Handle the completion or the cancellation of the render process. """
+ """Handles the completion or the cancellation of the render process."""
self.progress.window.destroy()
self.progress = None
self.window.show() # Show the rendering dialog again
@@ -788,10 +780,7 @@ class RenderDialog(Loggable):
self.dialog.window.destroy()
def _renderButtonClickedCb(self, unused_button):
- """
- The render button inside the render dialog has been clicked,
- start the rendering process.
- """
+ """Starts the rendering process."""
self.__maybeUseSourceAsset()
self.outfile = os.path.join(self.filebutton.get_uri(),
self.fileentry.get_text())
@@ -917,10 +906,10 @@ class RenderDialog(Loggable):
self.system.uninhibitSleep(RenderDialog.INHIBIT_REASON)
def _updatePositionCb(self, unused_pipeline, position):
- """
- Unlike other progression indicator callbacks, this one occurs every time
- the pipeline emits a position changed signal, which is *very* often.
- This should only be used for a smooth progressbar/percentage, not text.
+ """Updates the progress bar and triggers the update of the file size.
+
+ This one occurs every time the pipeline emits a position changed signal,
+ which is *very* often.
"""
self.current_position = position
if not self.progress or not position:
@@ -939,17 +928,14 @@ class RenderDialog(Loggable):
self._timeEstimateTimer = GLib.timeout_add_seconds(
3, self._updateTimeEstimateCb)
- # Filesize is trickier and needs more time to be meaningful:
+ # Filesize is trickier and needs more time to be meaningful.
if not self._filesizeEstimateTimer and (fraction > 0.33 or timediff > 180):
self._filesizeEstimateTimer = GLib.timeout_add_seconds(
5, self._updateFilesizeEstimateCb)
- def _elementAddedCb(self, unused_bin, element):
- """
- Setting properties on Gst.Element-s has they are added to the
- Gst.Encodebin
- """
- factory = element.get_factory()
+ def _elementAddedCb(self, unused_bin, gst_element):
+ """Sets properties on the specified Gst.Element."""
+ factory = gst_element.get_factory()
settings = {}
if factory == get_combo_value(self.video_encoder_combo):
settings = self.project.vcodecsettings
@@ -957,7 +943,7 @@ class RenderDialog(Loggable):
settings = self.project.acodecsettings
for propname, value in settings.items():
- element.set_property(propname, value)
+ gst_element.set_property(propname, value)
self.debug("Setting %s to %s", propname, value)
# Settings changed callbacks
@@ -1032,7 +1018,7 @@ class RenderDialog(Loggable):
self._elementSettingsDialog(factory, 'acodecsettings')
def _muxerComboChangedCb(self, muxer_combo):
- """Handle the changing of the container format combobox."""
+ """Handles the changing of the container format combobox."""
self.project.muxer = get_combo_value(muxer_combo).get_name()
# Update the extension of the filename.
diff --git a/pitivi/settings.py b/pitivi/settings.py
index 171cd2b..3c5775a 100644
--- a/pitivi/settings.py
+++ b/pitivi/settings.py
@@ -40,14 +40,14 @@ def get_bool_env(var):
def get_env_by_type(type_, var):
- """
- Returns the environment variable.
+ """Gets an environment variable.
+
+ Args:
+ type_ (type): The type of the variable.
+ var (str): The name of the environment variable.
- @arg type_: The type of the variable
- @type type_: C{type}
- @arg var: The name of the environment variable.
- @type var: C{str}
- @returns: Contents of the environment variable, or C{None} if it doesn't exist.
+ Returns:
+ The contents of the environment variable, or None if it doesn't exist.
"""
if var is None:
return None
@@ -66,27 +66,21 @@ def get_dir(path, autocreate=True):
def xdg_config_home(autocreate=True):
- """
- Get the directory for storing the user's pitivi configuration
- """
+ """Gets the directory for storing the user's Pitivi configuration."""
default = os.path.join(GLib.get_user_config_dir(), "pitivi")
path = os.getenv("PITIVI_USER_CONFIG_DIR", default)
return get_dir(path, autocreate)
def xdg_data_home(autocreate=True):
- """
- Get the directory for storing the user's data: presets, plugins, etc.
- """
+ """Gets the directory for storing the user's data: presets, plugins, etc."""
default = os.path.join(GLib.get_user_data_dir(), "pitivi")
path = os.getenv("PITIVI_USER_DATA_DIR", default)
return get_dir(path, autocreate)
def xdg_cache_home(autocreate=True):
- """
- Get the Pitivi cache directory
- """
+ """Gets the Pitivi cache directory."""
default = os.path.join(GLib.get_user_cache_dir(), "pitivi")
path = os.getenv("PITIVI_USER_CACHE_DIR", default)
return get_dir(path, autocreate)
@@ -97,8 +91,7 @@ class ConfigError(Exception):
class Notification(object):
-
- """A descriptor to help with the implementation of signals"""
+ """A descriptor which emits a signal when set."""
def __init__(self, attrname):
self.attrname = "_" + attrname
@@ -117,19 +110,18 @@ class Notification(object):
class GlobalSettings(GObject.Object, Loggable):
+ """Pitivi app settings.
- """
- Pitivi app settings.
-
- The settings object loads settings from different sources, currently:
+ Loads settings from different sources, currently:
- the local configuration file,
- environment variables.
Modules declare which settings they wish to access by calling the
addConfigOption() class method during initialization.
- @cvar options: A dictionnary of available settings.
- @cvar environment: A list of the controlled environment variables.
+ Attributes:
+ options (dict): The available settings.
+ environment (set): The controlled environment variables.
"""
options = {}
@@ -146,10 +138,7 @@ class GlobalSettings(GObject.Object, Loggable):
self._readSettingsFromEnvironmentVariables()
def _readSettingsFromConfigurationFile(self):
- """
- Read the configuration from the user configuration file.
- """
-
+ """Reads the settings from the user configuration file."""
try:
self._config.read(self.conf_file_path)
except UnicodeDecodeError as e:
@@ -181,14 +170,13 @@ class GlobalSettings(GObject.Object, Loggable):
@classmethod
def readSettingSectionFromFile(self, cls, section):
- """
- Force reading a particular section of the settings file.
+ """Reads a particular section of the settings file.
- Use this if you dynamically determine settings sections/keys at runtime
- (like in tabsmanager.py). Otherwise, the settings file would be read
- only once (at the initialization phase of your module) and your config
- sections would never be read, and thus values would be reset to defaults
- on every startup because GlobalSettings would think they don't exist.
+ Use this if you dynamically determine settings sections/keys at runtime.
+ Otherwise, the settings file would be read only once, at the
+ initialization phase of your module, and your config sections would
+ never be read, thus values would be reset to defaults on every startup
+ because GlobalSettings would think they don't exist.
"""
if cls._config.has_section(section):
for option in cls._config.options(section):
@@ -207,9 +195,7 @@ class GlobalSettings(GObject.Object, Loggable):
setattr(cls, section + option, value)
def _readSettingsFromEnvironmentVariables(self):
- """
- Override options values using their registered environment variables.
- """
+ """Reads settings from their registered environment variables."""
for section, attrname, typ, key, env, value in self.iterAllOptions():
if not env:
# This option does not have an environment variable name.
@@ -234,17 +220,15 @@ class GlobalSettings(GObject.Object, Loggable):
self.error("Failed to write to %s: %s", self.conf_file_path, e)
def storeSettings(self):
- """
- Write settings to the user's local configuration file. Note that only
- those settings which were added with a section and a key value are
+ """Writes settings to the user's local configuration file.
+
+ Only those settings which were added with a section and a key value are
stored.
"""
self._writeSettingsToConfigurationFile()
def iterAllOptions(self):
- """
- Iterate over all registered options
- """
+ """Iterates over all registered options."""
for section, options in list(self.options.items()):
for attrname, (typ, key, environment) in list(options.items()):
yield section, attrname, typ, key, environment, getattr(self, attrname)
@@ -253,39 +237,32 @@ class GlobalSettings(GObject.Object, Loggable):
return getattr(self, attrname) == self.defaults[attrname]
def setDefault(self, attrname):
- """
- Reset the specified setting to its default value.
- """
+ """Resets the specified setting to its default value."""
setattr(self, attrname, self.defaults[attrname])
@classmethod
def addConfigOption(cls, attrname, type_=None, section=None, key=None,
environment=None, default=None, notify=False,):
- """
- Add a configuration option.
+ """Adds a configuration option.
This function should be called during module initialization, before
the config file is actually read. By default, only options registered
beforehand will be loaded.
- See mainwindow.py and medialibrary.py for examples of usage.
If you want to add configuration options after initialization,
- use the readSettingSectionFromFile method to force reading later on.
- See tabsmanager.py for an example of such a scenario.
-
- @param attrname: the attribute of this class which represents the option
- @type attrname: C{str}
- @param type_: type of the attribute. Unnecessary if default is given.
- @type type_: a builtin or class
- @param section: The section of the config file under which this option is
- saved. This section must have been added with addConfigSection(). Not
- necessary if key is not given.
- @param key: the key under which this option is to be saved. Can be none if
- this option should not be saved.
- @type key: C{str}
- @param notify: whether or not this attribute should emit notification
- signals when modified (default is False).
- @type notify: C{boolean}
+ use the `readSettingSectionFromFile` method to force reading later on.
+
+ Args:
+ attrname (str): The attribute of this class for accessing the option.
+ type_ (Optional[type]): The type of the attribute. Unnecessary if a
+ `default` value is specified.
+ section (Optional[str]): The section of the config file under which
+ this option is saved. This section must have been added with
+ addConfigSection(). Not necessary if `key` is not given.
+ key (Optional[str]): The key under which this option is to be saved.
+ By default the option will not be saved.
+ notify (Optional[bool]): Whether this attribute should emit
+ signals when modified. By default signals are not emitted.
"""
if section and section not in cls.options:
raise ConfigError(
@@ -323,11 +300,13 @@ class GlobalSettings(GObject.Object, Loggable):
@classmethod
def addConfigSection(cls, section):
- """
- Add a section to the local config file.
+ """Adds a section to the local config file.
+
+ Args:
+ section (str): The section name.
- @param section: The section name. This section must not already exist.
- @type section: C{str}
+ Raises:
+ ConfigError: If the section already exists.
"""
if section in cls.options:
raise ConfigError("Duplicate Section \"%s\"." % section)
@@ -335,8 +314,14 @@ class GlobalSettings(GObject.Object, Loggable):
@classmethod
def notifiesConfigOption(cls, attrname):
- """
- Whether a changed signal is emitted for the specified setting.
+ """Checks whether a signal is emitted when the setting is changed.
+
+ Args:
+ attrname (str): The attribute name used to access the setting.
+
+ Returns:
+ bool: True when the setting emits a signal when changed,
+ False otherwise.
"""
signal_name = Notification.signalName(attrname)
return bool(GObject.signal_lookup(signal_name, cls))
diff --git a/pitivi/tabsmanager.py b/pitivi/tabsmanager.py
index 9ce71a5..d0420b2 100644
--- a/pitivi/tabsmanager.py
+++ b/pitivi/tabsmanager.py
@@ -16,9 +16,7 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-A helper object to work with Gtk.Notebook tabs
-"""
+"""Gtk.Notebook helpers."""
from gi.repository import Gdk
from gi.repository import Gtk
@@ -29,9 +27,12 @@ from pitivi.utils.ui import SPACING
class BaseTabs(Gtk.Notebook, Loggable):
+ """Notebook which can detach its tabs to new windows.
- """
- @type app: Pitivi
+ Persists which of its tabs are detached.
+
+ Attributes:
+ app (Pitivi): The app.
"""
def __init__(self, app):
@@ -40,7 +41,7 @@ class BaseTabs(Gtk.Notebook, Loggable):
self.set_border_width(SPACING)
self.set_scrollable(True)
self.connect("create-window", self.__create_window_cb)
- self.settings = app.settings # To save/restore states of detached tabs
+ self.settings = app.settings
notebook_widget_settings = self.get_settings()
notebook_widget_settings.props.gtk_dnd_drag_threshold = 1
@@ -113,7 +114,7 @@ class BaseTabs(Gtk.Notebook, Loggable):
window.show_all()
window.move(x, y)
window.connect(
- "configure-event", self._detached_window_configure_cb,
+ "configure-event", self.__detached_window_configure_cb,
child_name)
window.connect(
"destroy", self.__detached_window_destroyed_cb, child,
@@ -121,13 +122,8 @@ class BaseTabs(Gtk.Notebook, Loggable):
return notebook
- def _detached_window_configure_cb(self, window, event, child_name):
- """
- When the user configures the detached window
- (changes its size, position, etc.), save the settings.
-
- The config key's name depends on the name (label) of the tab widget.
- """
+ def __detached_window_configure_cb(self, window, event, child_name):
+ """Saves the position and size of the specified window."""
# get_position() takes the window manager's decorations into account
position = window.get_position()
setattr(self.settings, child_name + "width", event.width)
@@ -136,10 +132,7 @@ class BaseTabs(Gtk.Notebook, Loggable):
setattr(self.settings, child_name + "y", position[1])
def _create_default_config(self, child_name):
- """
- If they do not exist already, create default settings
- to save the state of a detachable widget.
- """
+ """Creates default settings to save the state of a detachable widget."""
try:
GlobalSettings.addConfigSection(child_name)
except ConfigError:
diff --git a/pitivi/timeline/__init__.py b/pitivi/timeline/__init__.py
index 52152fd..e69de29 100644
--- a/pitivi/timeline/__init__.py
+++ b/pitivi/timeline/__init__.py
@@ -1,25 +0,0 @@
-#!/usr/bin/env python3
-#
-# pitivi/timeline/__init__.py
-#
-# Copyright (C) 2012 Thibault Saunier <thibault saunier collabora com>
-#
-# This program is free software; you can redistribute it and/or
-# modify it under the terms of the GNU Lesser General Public
-# License as published by the Free Software Foundation; either
-# version 2.1 of the License, or (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Lesser General Public License for more details.
-#
-# You should have received a copy of the GNU Lesser General Public
-# License along with this program; if not, see <http://www.gnu.org/licenses/>.
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 3, or (at your option)
-# any later version.
-"""
-Timeline related classes
-"""
diff --git a/pitivi/timeline/elements.py b/pitivi/timeline/elements.py
index 1b55d6c..d436c25 100644
--- a/pitivi/timeline/elements.py
+++ b/pitivi/timeline/elements.py
@@ -211,9 +211,7 @@ class KeyframeCurve(FigureCanvas, Loggable):
self.__source.set(event.xdata, value)
def toggle_keyframe(self, offset):
- """
- Set or unset the keyframe at the given offset.
- """
+ """Sets or unsets the keyframe at the specified offset."""
items = self.__source.get_all()
if offset in (items[0].timestamp, items[-1].timestamp):
return
@@ -231,10 +229,8 @@ class KeyframeCurve(FigureCanvas, Loggable):
self.__timeline.ges_timeline.get_parent().commit_timeline()
def __gtkMotionEventCb(self, unused_widget, unused_event):
- """
- We need to do that here, because mpl's callbacks can't stop
- signal propagation.
- """
+ # We need to do this here, because Matplotlib's callbacks can't stop
+ # signal propagation.
if self.handling_motion:
return True
return False
@@ -587,24 +583,29 @@ class TimelineElement(Gtk.Layout, timelineUtils.Zoomable, Loggable):
# Virtual methods
def _getPreviewer(self):
- """
- Should return a GtkWidget offering a representation of the
- medium (waveforms for audio, thumbnails for video ..).
+ """Gets a Gtk.Widget to be used as previewer.
+
This previewer will be automatically scaled to the width and
height of the TimelineElement.
+
+ Returns:
+ Gtk.Widget: The widget showing thumbnails, waveforms, etc.
"""
return None
def _getBackground(self):
- """
- Should return a GtkWidget with a unique background color.
+ """Gets a Gtk.Widget to be used as background.
+
+ Returns:
+ Gtk.Widget: The widget identifying the clip type.
"""
return None
def _getDefaultMixingProperty(self):
- """
- Should return a controllable GObject.ParamSpec allowing to mix
- media on different layers.
+ """Gets the property controlled by default by the keyframes.
+
+ Returns:
+ GObject.ParamSpec: The param spec of the default property.
"""
return None
diff --git a/pitivi/timeline/layer.py b/pitivi/timeline/layer.py
index 46df60d..9b555f1 100644
--- a/pitivi/timeline/layer.py
+++ b/pitivi/timeline/layer.py
@@ -33,9 +33,7 @@ from pitivi.utils.timeline import Zoomable
class TwoStateButton(Gtk.Button):
- """
- Button with two states and according labels/images
- """
+ """Button with two states and according labels/images."""
__gsignals__ = {
"changed-state": (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_PYOBJECT,),)
@@ -62,10 +60,9 @@ class TwoStateButton(Gtk.Button):
class SpacedSeparator(Gtk.EventBox):
- """
- A Separator with vertical spacing
+ """A Separator with vertical spacing.
- Inherits from EventBox since we want to change background color
+ Inherits from EventBox since we want to change background color.
"""
def __init__(self, position):
@@ -232,44 +229,44 @@ class LayerControls(Gtk.EventBox, Loggable):
self.__move_layer_top_action = Gio.SimpleAction.new("move-layer-to-top", None)
action = self.__move_layer_top_action
- action.connect("activate", self._moveLayerCb, -2)
+ action.connect("activate", self.__move_layer_cb, -2)
action_group.add_action(action)
menu_model.append(_("Move layer to top"), "layer.%s" % action.get_name().replace(" ", "."))
self.__move_layer_up_action = Gio.SimpleAction.new("move-layer-up", None)
action = self.__move_layer_up_action
- action.connect("activate", self._moveLayerCb, -1)
+ action.connect("activate", self.__move_layer_cb, -1)
action_group.add_action(action)
menu_model.append(_("Move layer up"), "layer.%s" % action.get_name().replace(" ", "."))
self.__move_layer_down_action = Gio.SimpleAction.new("move-layer-down", None)
action = self.__move_layer_down_action
- action.connect("activate", self._moveLayerCb, 1)
+ action.connect("activate", self.__move_layer_cb, 1)
action_group.add_action(action)
menu_model.append(_("Move layer down"), "layer.%s" % action.get_name().replace(" ", "."))
self.__move_layer_bottom_action = Gio.SimpleAction.new("move-layer-to-bottom", None)
action = self.__move_layer_bottom_action
- action.connect("activate", self._moveLayerCb, 2)
+ action.connect("activate", self.__move_layer_cb, 2)
action_group.add_action(action)
menu_model.append(_("Move layer to bottom"), "layer.%s" % action.get_name().replace(" ", "."))
self.__delete_layer_action = Gio.SimpleAction.new("delete-layer", None)
action = self.__delete_layer_action
- action.connect("activate", self._deleteLayerCb)
+ action.connect("activate", self.__delete_layer_cb)
action_group.add_action(action)
menu_model.append(_("Delete layer"), "layer.%s" % action.get_name())
return menu_model, action_group
- def _deleteLayerCb(self, unused_action, unused_parametter):
+ def __delete_layer_cb(self, unused_action, unused_parameter):
pipeline = self.ges_timeline.get_asset().pipeline
with self.app.action_log.started("delete layer",
CommitTimelineFinalizingAction(pipeline)):
self.ges_timeline.remove_layer(self.ges_layer)
pipeline.commit_timeline()
- def _moveLayerCb(self, unused_simple_action, unused_parametter, step):
+ def __move_layer_cb(self, unused_simple_action, unused_parameter, step):
index = self.ges_layer.get_priority()
if abs(step) == 1:
index += step
@@ -294,10 +291,8 @@ class LayerControls(Gtk.EventBox, Loggable):
class LayerLayout(Gtk.Layout, Loggable):
- """
- A GtkLayout that exclusivly container Clips.
- This allows us to properly handle the z order of
- """
+ """Displays the clips of a layer."""
+
__gtype_name__ = "PitiviLayerLayout"
def __init__(self, timeline):
diff --git a/pitivi/timeline/previewers.py b/pitivi/timeline/previewers.py
index b5f791f..881cab2 100644
--- a/pitivi/timeline/previewers.py
+++ b/pitivi/timeline/previewers.py
@@ -16,11 +16,7 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-Classes to draw Audio and Video 'previewers', meaning computing
-waveforms from an audio file and thumbnails from a video, and
-drawing them on Cairo surfaces.
-"""
+"""Previewers for the timeline."""
import os
import pickle
import random
@@ -73,9 +69,7 @@ THUMB_HEIGHT = EXPANDED_SIZE - 2 * THUMB_MARGIN_PX
class PreviewerBin(Gst.Bin, Loggable):
- """
- A baseclass for element specialized in gathering datas to create previews
- """
+ """Baseclass for elements gathering datas to create previews."""
def __init__(self, bin_desc):
Gst.Bin.__init__(self)
Loggable.__init__(self)
@@ -86,16 +80,13 @@ class PreviewerBin(Gst.Bin, Loggable):
self.add_pad(Gst.GhostPad.new(None, self.internal_bin.srcpads[0]))
def finalize(self, proxy=None):
- """
- Finalize the previewer (saving data to file if needed)
- """
+ """Finalizes the previewer, saving data to the disk if needed."""
pass
class ThumbnailBin(PreviewerBin):
- """
- A bin to generate and save thumbnails to a sqlite database
- """
+ """Bin to generate and save thumbnails to an SQLite database."""
+
__gproperties__ = {
"uri": (str,
"uri of the media file",
@@ -136,9 +127,7 @@ class ThumbnailBin(PreviewerBin):
return Gst.Bin.do_post_message(self, message)
def finalize(self, proxy=None):
- """
- Finalize the previewer (saving data to file if needed)
- """
+ """Finalizes the previewer, saving data to file if needed."""
self.thumb_cache.commit()
if proxy:
self.thumb_cache.copy(proxy.get_id())
@@ -158,10 +147,8 @@ class ThumbnailBin(PreviewerBin):
class TeedThumbnailBin(ThumbnailBin):
- """
- A bin to generate and save thumbnails to a sqlite database and
- output the stream in another branch
- """
+ """Bin to generate and save thumbnails to as SQLite database."""
+
def __init__(self):
ThumbnailBin.__init__(
self, bin_desc="tee name=t ! queue "
@@ -175,9 +162,8 @@ class TeedThumbnailBin(ThumbnailBin):
# pylint: disable=too-many-instance-attributes
class WaveformPreviewer(PreviewerBin):
- """
- A bin to generate and save waveforms as pickle file
- """
+ """Bin to generate and save waveforms as a pickle file."""
+
__gproperties__ = {
"uri": (str,
"uri of the media file",
@@ -256,9 +242,7 @@ class WaveformPreviewer(PreviewerBin):
return Gst.Bin.do_post_message(self, message)
def finalize(self, proxy=None):
- """
- Finalize the previewer (saving data to file if needed)
- """
+ """Finalizes the previewer, saving data to file if needed."""
if not self.passthrough and self.peaks:
# Let's go mono.
if len(self.peaks) > 1:
@@ -287,112 +271,93 @@ Gst.Element.register(None, "teedthumbnailbin", Gst.Rank.NONE,
# pylint: disable=too-few-public-methods
class PreviewGeneratorManager():
- """
- Manage the execution of Previewers preview generation
- """
+ """Manager for running the previewers."""
def __init__(self):
# The current Previewer per GES.TrackType.
- self._cpipeline = {}
+ self._current_previewers = {}
# The queue of Previewers.
- self._pipelines = {
+ self._previewers = {
GES.TrackType.AUDIO: [],
GES.TrackType.VIDEO: []
}
- def addPipeline(self, pipeline):
- """
- Add a pipeline to the list of controlled pipelines
+ def add_previewer(self, previewer):
+ """Adds the specified previewer to the queue.
Args:
- pipeline (Gst.Pipeline): The pipeline to control
+ previewer (Previewer): The previewer to control.
"""
- track_type = pipeline.track_type
+ track_type = previewer.track_type
- current_pipeline = self._cpipeline.get(track_type)
- if pipeline in self._pipelines[track_type] or \
- pipeline is current_pipeline:
+ current = self._current_previewers.get(track_type)
+ if previewer in self._previewers[track_type] or previewer is current:
# Already in the queue or already processing.
return
- if not self._pipelines[track_type] and current_pipeline is None:
- self._setPipeline(pipeline)
+ if not self._previewers[track_type] and current is None:
+ self._start_previewer(previewer)
else:
- self._pipelines[track_type].insert(0, pipeline)
+ self._previewers[track_type].insert(0, previewer)
- def _setPipeline(self, pipeline):
- self._cpipeline[pipeline.track_type] = pipeline
- pipeline.connect("done", self._nextPipeline)
- pipeline.startGeneration()
+ def _start_previewer(self, previewer):
+ self._current_previewers[previewer.track_type] = previewer
+ previewer.connect("done", self.__previewer_done_cb)
+ previewer.startGeneration()
- def _nextPipeline(self, controlled):
- track_type = controlled.track_type
- pipeline = self._cpipeline.pop(track_type, None)
- if pipeline:
- pipeline.disconnect_by_func(self._nextPipeline)
+ def __previewer_done_cb(self, previewer):
+ track_type = previewer.track_type
+ next_previewer = self._current_previewers.pop(track_type, None)
+ if next_previewer:
+ next_previewer.disconnect_by_func(self.__previewer_done_cb)
- if self._pipelines[track_type]:
- self._setPipeline(self._pipelines[track_type].pop())
+ if self._previewers[track_type]:
+ self._start_previewer(self._previewers[track_type].pop())
class Previewer(Gtk.Layout):
+ """Base class for previewers.
- """
- Interface to be implemented by classes that generate previews
- It is need to implement it so PreviewGeneratorManager can manage
- those classes
+ Attributes:
+ track_type (GES.TrackType): The type of content.
"""
- # We only want one instance of PreviewGeneratorManager to be used for
- # all the generators.
+ # We only need one PreviewGeneratorManager to manage all previewers.
__manager = PreviewGeneratorManager()
def __init__(self, track_type):
- """
- @param track_type : GES.TrackType.*
- """
Gtk.Layout.__init__(self)
self.track_type = track_type
def startGeneration(self):
- """
- Start preview generation
- """
+ """Starts preview generation."""
raise NotImplementedError
def stopGeneration(self):
- """
- Stop preview generation
- """
+ """Stops preview generation."""
raise NotImplementedError
def becomeControlled(self):
- """
- Let the PreviewGeneratorManager control our execution
- """
- Previewer.__manager.addPipeline(self)
+ """Lets the PreviewGeneratorManager control our execution."""
+ Previewer.__manager.add_previewer(self)
def setSelected(self, selected):
- """
- Mark a previewer as being selected
- """
+ """Marks this instance as being selected."""
pass
class VideoPreviewer(Previewer, Zoomable, Loggable):
+ """A video previewer widget, drawing thumbnails.
+
+ Attributes:
+ ges_elem (GES.TrackElement): The previewed element.
"""
- A video previewer widget, drawing thumbnails
- """
- # We could define them in PreviewGenerator, but then for some reason they
- # are ignored.
+
+ # We could define them in Previewer, but for some reason they are ignored.
__gsignals__ = PREVIEW_GENERATOR_SIGNALS
def __init__(self, ges_elem):
- """
- @param ges_elem : the backend GES.TrackElement
- @param track : the track to which the ges_elem belongs
- """
Previewer.__init__(self, GES.TrackType.VIDEO)
Zoomable.__init__(self)
Loggable.__init__(self)
@@ -440,8 +405,7 @@ class VideoPreviewer(Previewer, Zoomable, Loggable):
# Internal API
def _setupPipeline(self):
- """
- Create the pipeline.
+ """Creates the pipeline.
It has the form "playbin ! thumbnailsink" where thumbnailsink
is a Bin made out of "videorate ! capsfilter ! gdkpixbufsink"
@@ -488,22 +452,23 @@ class VideoPreviewer(Previewer, Zoomable, Loggable):
self.pipeline.get_bus().connect("message", self.__bus_message_handler)
def _checkCPU(self):
- """
- Check the CPU usage and adjust the time interval (+10 or -10%) at
- which the next thumbnail will be generated. Even then, it will only
+ """Adjusts when the next thumbnail is generated.
+
+ Checks the CPU usage and adjusts the waiting time at which the next
+ thumbnail will be generated +/- 10%. Even then, it will only
happen when the gobject loop is idle to avoid blocking the UI.
"""
usage_percent = self.cpu_usage_tracker.usage()
if usage_percent < THUMBNAILS_CPU_USAGE:
self.interval *= 0.9
self.log(
- 'Thumbnailing sped up (+10%%) to a %.1f ms interval for "%s"' %
- (self.interval, filename_from_uri(self.uri)))
+ 'Thumbnailing sped up (+10%%) to a %.1f ms interval for "%s"',
+ self.interval, filename_from_uri(self.uri))
else:
self.interval *= 1.1
self.log(
- 'Thumbnailing slowed down (-10%%) to a %.1f ms interval for "%s"' %
- (self.interval, filename_from_uri(self.uri)))
+ 'Thumbnailing slowed down (-10%%) to a %.1f ms interval for "%s"',
+ self.interval, filename_from_uri(self.uri))
self.cpu_usage_tracker.reset()
self._thumb_cb_id = GLib.timeout_add(self.interval,
self._create_next_thumb,
@@ -602,9 +567,7 @@ class VideoPreviewer(Previewer, Zoomable, Loggable):
self.remove(child)
def _addVisibleThumbnails(self, rect):
- """
- Get the thumbnails to be displayed in the currently visible clip portion
- """
+ """Gets the thumbnails for the currently visible clip portion."""
if self.thumb_width is None:
return False
@@ -637,9 +600,7 @@ class VideoPreviewer(Previewer, Zoomable, Loggable):
return True
def _get_wish(self):
- """
- Returns a wish that is also in the queue, or None if no such wish exists
- """
+ """Returns a wish that is also in the queue, if any."""
while True:
if not self.wishlist:
return None
@@ -729,9 +690,7 @@ class VideoPreviewer(Previewer, Zoomable, Loggable):
self.emit("done")
def cleanup(self):
- """
- Stop preview generation and cleanup object
- """
+ """Stops preview generation and cleans the object."""
self.stopGeneration()
Zoomable.__del__(self)
@@ -752,9 +711,8 @@ class VideoPreviewer(Previewer, Zoomable, Loggable):
class Thumbnail(Gtk.Image):
- """
- Simple widget representing a Thumbnail
- """
+ """Simple widget representing a Thumbnail."""
+
def __init__(self, width, height):
Gtk.Image.__init__(self)
self.width = width
@@ -767,12 +725,14 @@ CACHES = {}
# pylint: disable=invalid-name
def getThumbnailCache(obj):
- """
- Get a ThumbnailCache for @obj
+ """Gets a ThumbnailCache for the specified object.
Args:
- obj: The object for which to get a ThumbnailCache, it can be a string or
- a GES.UriClipAsset
+ obj (str or GES.UriClipAsset): The object for which to get a cache,
+ it can be a string ora GES.UriClipAsset
+
+ Returns:
+ ThumbnailCache: The cache for the object.
"""
if isinstance(obj, str):
uri = obj
@@ -788,11 +748,11 @@ def getThumbnailCache(obj):
class ThumbnailCache(Loggable):
-
- """Caches thumbnails by key using LRU policy, implemented with heapq.
+ """Caches thumbnails by key using LRU policy.
Uses a two stage caching mechanism. A limited number of elements are
- held in memory, the rest is being cached on disk using an sqlite db."""
+ held in memory, the rest is being cached on disk in an SQLite db.
+ """
def __init__(self, uri):
Loggable.__init__(self)
@@ -807,8 +767,7 @@ class ThumbnailCache(Loggable):
Jpeg BLOB NOT NULL)")
def copy(self, uri):
- """
- Copy @self to @uri
+ """Copies `self` to the specified `uri`.
Args:
uri (str): The place where to copy/save the ThumbnailCache
@@ -820,11 +779,10 @@ class ThumbnailCache(Loggable):
os.symlink(self._dbfile, dbfile)
def getImagesSize(self):
- """
- Get the image size
+ """Gets the image size.
+
Returns:
- int: The width of the images contained in the cache
- int: The height of the images contained in the cache
+ List[int]: The width and height of the images in the cache.
"""
self._cur.execute("SELECT * FROM Thumbs LIMIT 1")
row = self._cur.fetchone()
@@ -835,9 +793,7 @@ class ThumbnailCache(Loggable):
return pixbuf.get_width(), pixbuf.get_height()
def getPreviewThumbnail(self):
- """
- Get a thumbnail contained 'at the middle' of the cache
- """
+ """Gets a thumbnail contained 'at the middle' of the cache."""
self._cur.execute("SELECT Time FROM Thumbs")
timestamps = self._cur.fetchall()
if not timestamps:
@@ -881,9 +837,7 @@ class ThumbnailCache(Loggable):
self._cur.execute("INSERT INTO Thumbs VALUES (?,?)", (key, blob,))
def commit(self):
- """
- Save the cache on disk (in the database)
- """
+ """Saves the cache on disk (in the database)."""
self.debug(
'Saving thumbnail cache file to disk for: %s', self._filename)
self._db.commit()
@@ -893,9 +847,8 @@ class ThumbnailCache(Loggable):
class PipelineCpuAdapter(Loggable):
+ """Pipeline manager modulating the rate of the provided pipeline.
- """
- This pipeline manager will modulate the rate of the provided pipeline.
It is the responsibility of the caller to set the sync of the sink to True,
disable QOS and provide a pipeline with a rate of 1.0.
Doing otherwise would be cheating. Cheating is bad.
@@ -914,18 +867,16 @@ class PipelineCpuAdapter(Loggable):
self._bus_cb_id = None
def start(self):
- """
- Start modulating the rate on the controlled pipeline to
- avoid using too much CPU
+ """Start modulating the rate on the controlled pipeline.
+
+ This avoid using too much CPU.
"""
GLib.timeout_add(200, self._modulateRate)
self._bus_cb_id = self.bus.connect("message", self._messageCb)
self.done = False
def stop(self):
- """
- Stop modulating the rate on the controlled pipeline
- """
+ """Stops modulating the rate on the controlled pipeline."""
if self._bus_cb_id is not None:
self.bus.disconnect(self._bus_cb_id)
self._bus_cb_id = None
@@ -933,9 +884,7 @@ class PipelineCpuAdapter(Loggable):
self.done = True
def _modulateRate(self):
- """
- Adapt the rate of audio playback (analysis) depending on CPU usage.
- """
+ """Adapts the rate of audio analysis depending on CPU usage."""
if self.done:
return False
@@ -1000,9 +949,7 @@ class PipelineCpuAdapter(Loggable):
def get_wavefile_location_for_uri(uri):
- """
- Compute the URI where the pickled wave file should be stored
- """
+ """Computes the URI where the pickled wave file should be stored."""
filename = hash_file(Gst.uri_get_location(uri)) + ".wave"
cache_dir = get_dir(os.path.join(xdg_cache_home(), "waves"))
@@ -1010,10 +957,7 @@ def get_wavefile_location_for_uri(uri):
class AudioPreviewer(Previewer, Zoomable, Loggable):
-
- """
- Audio previewer based on the results from the "level" gstreamer element.
- """
+ """Audio previewer using the results from the "level" GStreamer element."""
__gsignals__ = PREVIEW_GENERATOR_SIGNALS
@@ -1053,9 +997,7 @@ class AudioPreviewer(Previewer, Zoomable, Loggable):
self._force_redraw = True
def startLevelsDiscoveryWhenIdle(self):
- """
- Start processing waveform (whenever possible)
- """
+ """Starts processing waveform (whenever possible)."""
self.debug('Waiting for UI to become idle for: %s',
filename_from_uri(self._uri))
GLib.idle_add(self._startLevelsDiscovery, priority=GLib.PRIORITY_LOW)
@@ -1219,8 +1161,6 @@ class AudioPreviewer(Previewer, Zoomable, Loggable):
self.emit("done")
def cleanup(self):
- """
- Stop preview generation and cleanup object
- """
+ """Stops preview generation and cleans the object."""
self.stopGeneration()
Zoomable.__del__(self)
diff --git a/pitivi/timeline/ruler.py b/pitivi/timeline/ruler.py
index 9ccac12..38054f5 100644
--- a/pitivi/timeline/ruler.py
+++ b/pitivi/timeline/ruler.py
@@ -83,15 +83,15 @@ SMALL_FONT_SIZE = 11
class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable):
-
- """
- Widget for displaying the ruler.
+ """Widget for displaying the ruler.
Displays a series of consecutive intervals. For each interval its beginning
time is shown. If zoomed in enough, shows the frames in alternate colors.
- @type timeline: L{pitivi.timeline.timeline.TimelineContainer}
- @type _pipeline: L{pitivi.utils.pipeline.Pipeline}
+ Attributes:
+ timeline (TimelineContainer): The timeline container used to handle
+ scroll events.
+ _pipeline (Pipeline): The pipeline of the project.
"""
def __init__(self, timeline, hadj):
@@ -227,9 +227,7 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable):
self.timeline.timeline.do_scroll_event(event)
def setProjectFrameRate(self, rate):
- """
- Set the lowest scale based on project framerate
- """
+ """Sets the lowest scale based on the specified project framerate."""
self.frame_rate = rate
self.ns_per_frame = float(Gst.SECOND / self.frame_rate)
self.scales = (2 / rate, 5 / rate, 10 / rate) + SCALES
@@ -345,10 +343,12 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable):
context.set_font_size(NORMAL_FONT_SIZE)
def drawFrameBoundaries(self, context):
- """
- Draw the alternating rectangles that represent the project frames at
- high zoom levels. These are based on the framerate set in the project
- settings, not the actual frames on a video codec level.
+ """Draws the alternating rectangles that represent the project frames.
+
+ These are drawn only at high zoom levels.
+
+ These are based on the project's framerate settings, not the actual
+ frames on the assets.
"""
frame_width = self.nsToPixel(self.ns_per_frame)
if not frame_width >= FRAME_MIN_WIDTH_PIXELS:
@@ -373,8 +373,7 @@ class ScaleRuler(Gtk.DrawingArea, Zoomable, Loggable):
frame_num += 1
def drawPosition(self, context):
- """
- Draw the top part of the playhead.
+ """Draws the top part of the playhead.
This should be in sync with the playhead drawn by the timeline.
See Timeline.__draw_playhead().
diff --git a/pitivi/timeline/timeline.py b/pitivi/timeline/timeline.py
index 5e718ba..3a86172 100644
--- a/pitivi/timeline/timeline.py
+++ b/pitivi/timeline/timeline.py
@@ -104,21 +104,15 @@ PreferencesDialog.addTogglePreference('leftClickAlsoSeeks',
class Marquee(Gtk.Box, Loggable):
- """
- Marquee widget representing a selection area inside the timeline
- it should be drawn on top of the timeline layout.
+ """Widget representing a selection area inside the timeline.
- It provides an API that makes it easy to update its value directly
- from Gdk.Event
+ Attributes:
+ timeline (Timeline): The timeline containing the marquee.
"""
__gtype_name__ = "PitiviMarquee"
def __init__(self, timeline):
- """
- @timeline: The #Timeline on which the marquee will
- be used
- """
Gtk.Box.__init__(self)
Loggable.__init__(self)
@@ -200,11 +194,11 @@ class Marquee(Gtk.Box, Loggable):
class Timeline(Gtk.EventBox, Zoomable, Loggable):
- """
- Contains the layer controls and the layers representation.
+ """Container for the the layers controls and representation.
- @type parent: L{pitivi.timeline.timeline.TimelineContainer}
- @type _project: L{pitivi.project.Project}
+ Attributes:
+ parent (TimelineContainer): The parent widget.
+ _project (Project): The project.
"""
__gtype_name__ = "PitiviTimeline"
@@ -342,9 +336,7 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
self.current_group.props.serialize = False
def setProject(self, project):
- """
- Connects to the GES.Timeline holding the project.
- """
+ """Connects to the GES.Timeline holding the project."""
if self.ges_timeline is not None:
self.ges_timeline.disconnect_by_func(self._durationChangedCb)
self.ges_timeline.disconnect_by_func(self._layerAddedCb)
@@ -382,13 +374,13 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
self.queue_draw()
def scrollToPlayhead(self, align=None, when_not_in_view=False):
- """
- Scroll so that the playhead is in view.
+ """Scrolls so that the playhead is in view.
- @param align: Where the playhead should be post-scroll.
- @type align: L{Gtk.Align}
- @param when_not_in_view: Whether to scroll only if the playhead is not
- visible.
+ Args:
+ align (Optional[Gtk.Align]): Where the playhead should be
+ post-scroll.
+ when_not_in_view (Optional[bool]): When True, scrolls only if
+ the playhead is not in view.
"""
self.debug("Scrolling to playhead")
self.__setLayoutSize()
@@ -423,9 +415,7 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
# snapping indicator
def _snapCb(self, unused_timeline, unused_obj1, unused_obj2, position):
- """
- Display or hide a snapping indicator line
- """
+ """Displays or hides a snapping indicator line."""
self.__snap_position = self.nsToPixel(position)
self.queue_draw()
@@ -496,8 +486,11 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
return self.nsToPixel(self.ges_timeline.props.duration) + space_at_the_end
def _getParentOfType(self, widget, _type):
- """
- Get a clip from a child widget, if the widget is a child of the clip
+ """Gets a clip from a child widget.
+
+ Args:
+ widget (Gtk.Widget): A child of the clip.
+ _type (type): The type the clip should be.
"""
if isinstance(widget, _type):
return widget
@@ -511,10 +504,16 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
return None
def adjustCoords(self, coords=None, x=None, y=None):
- """
- Adjust coordinates passed as parametter that are raw
- coordinates from the whole timeline into sensible
- coordinates inside the visible area of the timeline.
+ """Adjusts timeline container coordinates to timeline view coordinates.
+
+ Args:
+ coords (Optional[List[int]]): The x and y to be adjusted.
+ x (Optional[int]): The x to be adjusted.
+ y (Optional[int]): The y to be adjusted.
+
+ Returns:
+ The specified coordinates adjusted for the visible area of the
+ timeline.
"""
if coords:
x = coords[0]
@@ -587,9 +586,10 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
return False
def get_sources_at_position(self, position):
- """
- Returns GES.VideoSource objects at current timeline position on all layers,
- in layer order.
+ """Gets video sources at the current position on all layers.
+
+ Returns:
+ List[GES.VideoSource]: The found video sources.
"""
sources = []
for layer in self.ges_timeline.layers:
@@ -968,7 +968,6 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
return [getattr(ges_layer.ui, sep_name), getattr(ges_layer.control_ui, sep_name)]
def _get_layer_at(self, y, prefer_ges_layer=None, past_middle_when_adjacent=False):
- """ Used in the testsuite """
ges_layers = self.ges_timeline.get_layers()
if y < 20:
# The cursor is at the top, above the first layer.
@@ -1024,7 +1023,6 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
return ges_layer, separators
def _setSeparatorsPrelight(self, light):
- """ Used in the testsuite """
for sep in self.__on_separators:
if light:
set_children_state_recurse(sep, Gtk.StateFlags.PRELIGHT)
@@ -1097,9 +1095,7 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
return new_ges_layer
def __update_layer(self, ges_layer):
- """
- Update the position child prop of the layer and layer control widgets.
- """
+ """Updates the position child prop of the layer and layer control."""
priority = ges_layer.props.priority
layer_box = ges_layer.ui.get_parent()
@@ -1110,9 +1106,7 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
priority)
def __getDroppedLayer(self):
- """
- Create the layer for a clip dropped on a separator.
- """
+ """Creates the layer for a clip dropped on a separator."""
priority = self._on_layer.props.priority
if self.__on_separators[0] == self._on_layer.ui.after_sep:
priority = self._on_layer.props.priority + 1
@@ -1153,7 +1147,7 @@ class Timeline(Gtk.EventBox, Zoomable, Loggable):
class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
- """Container for zoom box, ruler, timeline, scrollbars and toolbar."""
+ """Widget for zoom box, ruler, timeline, scrollbars and toolbar."""
def __init__(self, app):
Zoomable.__init__(self)
@@ -1212,16 +1206,12 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
self._project.pipeline.commit_timeline()
def insertAssets(self, assets, position=None):
- """
- Add assets to the timeline and create clips on the longest layer.
- """
+ """Creates clips out of the specified assets on the longest layer."""
layer = self._getLongestLayer()
self._insertClipsAndAssets(assets, position, layer)
def insertClips(self, clips, position=None):
- """
- Add clips to the timeline on the first layer.
- """
+ """Adds clips to the timeline on the first layer."""
layers = self.ges_timeline.get_layers()
layer = layers[0]
self._insertClipsAndAssets(clips, position, layer)
@@ -1275,7 +1265,7 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
return position
def purgeAsset(self, asset_id):
- """Remove all instances of an asset from the timeline."""
+ """Removes all instances of an asset from the timeline."""
layers = self.ges_timeline.get_layers()
for layer in layers:
for clip in layer.get_clips():
@@ -1373,9 +1363,7 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
self.timeline.disconnect_by_func(self._ignoreAllEventsCb)
def disableKeyboardAndMouseEvents(self):
- """
- A safety measure to prevent interacting with the timeline
- """
+ """A safety measure to prevent interacting with the timeline."""
self.info("Blocking timeline mouse and keyboard signals")
self.timeline.connect("event", self._ignoreAllEventsCb)
@@ -1383,9 +1371,7 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
return True
def _getLongestLayer(self):
- """
- Return the longest layer.
- """
+ """Returns the longest layer."""
layers = self.ges_timeline.get_layers()
if len(layers) == 1:
return layers[0]
@@ -1498,9 +1484,7 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
_("Add keyframe to the keyframe curve of selected clip"))
def _setBestZoomRatio(self, allow_zoom_in=False):
- """
- Set the zoom level so that the entire timeline is in view.
- """
+ """Sets the zoom level so that the entire timeline is in view."""
ruler_width = self.ruler.get_allocation().width
duration = 0 if not self.ges_timeline else self.ges_timeline.get_duration()
if not duration:
@@ -1662,7 +1646,8 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
progress_dialog.window.destroy()
def _splitCb(self, unused_action, unused_parameter):
- """
+ """Splits clips.
+
If clips are selected, split them at the current playhead position.
Otherwise, split all clips at the playhead position.
"""
@@ -1696,9 +1681,7 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
self._splitElements()
def _keyframe_cb(self, unused_action, unused_parameter):
- """
- Add or remove a keyframe at the current position of the selected clip.
- """
+ """Toggles a keyframe on the selected clip."""
ges_clip = self.timeline.selection.getSingleClip(GES.Clip)
if ges_clip is None:
return
@@ -1782,11 +1765,11 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
# Callbacks
def _renderingSettingsChangedCb(self, project, item, value):
- """
- Called when any Project metadata changes, we filter out the one
- we are interested in.
+ """Handles Project metadata changes.
- if @item is None, it mean we called it ourself, and want to force
+ We filter out the one we are not interested in.
+
+ If `item` is None, it means we called it ourself, and want to force
getting the project videorate value
"""
if item == "videorate" or item is None:
@@ -1805,9 +1788,7 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
Zoomable.pixelToNs(self._settings.edgeSnapDeadband))
def _projectLoadedCb(self, unused_app, project):
- """
- When a project is loaded, we connect to its pipeline
- """
+ """Connects to the project's pipeline."""
assert self._project is project
if self._project:
self.ruler.setPipeline(self._project.pipeline)
@@ -1822,9 +1803,7 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
Zoomable.pixelToNs(self._settings.edgeSnapDeadband))
def _projectCreatedCb(self, unused_app, project):
- """
- When a project is created, we connect to it timeline
- """
+ """Connects to the project's timeline."""
if self._project:
self._project.disconnect_by_func(self._renderingSettingsChangedCb)
try:
@@ -1849,9 +1828,7 @@ class TimelineContainer(Gtk.Grid, Zoomable, Loggable):
self.zoomFit()
def _selectionChangedCb(self, selection):
- """
- The selected clips on the timeline have changed.
- """
+ """Handles selection changing."""
self.updateActions()
def _gaplessmodeToggledCb(self, unused_action, unused_parameter):
diff --git a/pitivi/titleeditor.py b/pitivi/titleeditor.py
index 4b27759..86b45d1 100644
--- a/pitivi/titleeditor.py
+++ b/pitivi/titleeditor.py
@@ -39,12 +39,11 @@ DEFAULT_HALIGNMENT = GES.TextHAlign.CENTER
class TitleEditor(Loggable):
+ """Widget for configuring a title.
- """
- Widget for configuring the selected title.
-
- @type app: L{Pitivi}
- @type _project: L{pitivi.project.Project}
+ Attributes:
+ app (Pitivi): The app.
+ _project (Project): The project.
"""
def __init__(self, app):
@@ -154,10 +153,8 @@ class TitleEditor(Loggable):
self.log("Source text updated to %s", text)
self._setChildProperty("text", text)
- def _updateSource(self, updated_obj):
- """
- Handle changes in one of the advanced property widgets at the bottom
- """
+ def _update_source_cb(self, updated_obj):
+ """Handles changes in the advanced property widgets at the bottom."""
if not self.source:
# Nothing to update.
return
@@ -183,10 +180,10 @@ class TitleEditor(Loggable):
self.settings["x-absolute"].set_visible(visible)
def set_source(self, source):
- """
- Set the clip to be edited with this editor.
+ """Sets the clip to be edited with this editor.
- @type source: L{GES.TitleSource}
+ Args:
+ source (GES.TitleSource): The source of the clip.
"""
self.debug("Source set to %s", source)
if self._children_props_handler is not None:
diff --git a/pitivi/transitions.py b/pitivi/transitions.py
index 4bb80d6..8885ede 100644
--- a/pitivi/transitions.py
+++ b/pitivi/transitions.py
@@ -37,9 +37,7 @@ from pitivi.utils.ui import SPACING
class TransitionsListWidget(Gtk.Box, Loggable):
-
- """
- Widget for configuring the selected transition.
+ """Widget for configuring the selected transition.
@type app: L{Pitivi}
"""
@@ -198,10 +196,8 @@ class TransitionsListWidget(Gtk.Box, Loggable):
self.__updateBorderScale(widget == self.border_mode_loop)
def __updateBorderScale(self, loop=False, border=None):
- """
- The "border" property in gstreamer is unlimited, but if you go over
- 25 thousand it "loops" the transition instead of smoothing it.
- """
+ # The "border" property in gstreamer is unlimited, but if you go over
+ # 25 thousand it "loops" the transition instead of smoothing it.
if border is not None:
loop = border >= 50000
if loop:
@@ -229,9 +225,7 @@ class TransitionsListWidget(Gtk.Box, Loggable):
# UI methods
def _loadAvailableTransitionsCb(self):
- """
- Get the list of transitions from GES and load the associated thumbnails.
- """
+ """Loads the transitions types and icons into the storemodel."""
for trans_asset in GES.list_assets(GES.BaseTransitionClip):
trans_asset.icon = self._getIcon(trans_asset.get_id())
self.storemodel.append([trans_asset,
@@ -247,9 +241,7 @@ class TransitionsListWidget(Gtk.Box, Loggable):
COL_NAME_TEXT, Gtk.SortType.ASCENDING)
def activate(self, element):
- """
- Hide the infobar and show the transitions UI.
- """
+ """Hides the infobar and shows the transitions UI."""
if isinstance(element, GES.AudioTransition):
return
self.element = element
@@ -273,9 +265,7 @@ class TransitionsListWidget(Gtk.Box, Loggable):
self.infobar.hide()
def __selectTransition(self, transition_asset):
- """
- For a given transition type, select it in the iconview if available.
- """
+ """Selects the specified transition type in the iconview."""
model = self.iconview.get_model()
for row in model:
if transition_asset == row[COL_TRANSITION_ASSET]:
@@ -284,9 +274,7 @@ class TransitionsListWidget(Gtk.Box, Loggable):
self.iconview.scroll_to_path(path, False, 0, 0)
def deactivate(self):
- """
- Show the infobar and hide the transitions UI.
- """
+ """Shows the infobar and hides the transitions UI."""
self.__disconnectUi()
self.iconview.unselect_all()
self.iconview.hide()
@@ -295,11 +283,8 @@ class TransitionsListWidget(Gtk.Box, Loggable):
self.infobar.show()
def _getIcon(self, transition_nick):
- """
- If available, return an icon pixbuf for a given transition nickname.
- """
+ """Gets an icon pixbuf for the specified transition nickname."""
name = transition_nick + ".png"
- icon = None
try:
icon = GdkPixbuf.Pixbuf.new_from_file(
os.path.join(self._pixdir, name))
@@ -335,9 +320,7 @@ class TransitionsListWidget(Gtk.Box, Loggable):
return self.modelFilter[path[0]][COL_TRANSITION_ASSET]
def _setRowVisible(self, model, iter, unused_data):
- """
- Filters the icon view depending on the search results
- """
+ """Filters the icon view to show only the search results."""
text = self.searchEntry.get_text().lower()
return text in model.get_value(iter, COL_DESC_TEXT).lower() or\
text in model.get_value(iter, COL_NAME_TEXT).lower()
diff --git a/pitivi/undo/__init__.py b/pitivi/undo/__init__.py
index d8a2ccd..e69de29 100644
--- a/pitivi/undo/__init__.py
+++ b/pitivi/undo/__init__.py
@@ -1,3 +0,0 @@
-"""
-Undo classes and functions
-"""
diff --git a/pitivi/undo/timeline.py b/pitivi/undo/timeline.py
index 39b6256..c75c0e8 100644
--- a/pitivi/undo/timeline.py
+++ b/pitivi/undo/timeline.py
@@ -72,8 +72,9 @@ class TrackElementPropertyChanged(UndoableAction):
class TimelineElementObserver(Loggable):
- """
- Monitors the props of a GES.TimelineElement and all its children and reports UndoableActions.
+ """Monitors the props of an element and all its children.
+
+ Reports UndoableActions.
Attributes:
ges_timeline_element (GES.TimelineElement): The object to be monitored.
@@ -175,8 +176,7 @@ class EffectRemovedAction(TrackElementAction):
class ControlSourceObserver(GObject.Object):
- """
- Monitors a control source's props and reports UndoableActions.
+ """Monitors a control source's props and reports UndoableActions.
Attributes:
control_source (GstController.TimedValueControlSource): The object to be
@@ -582,9 +582,7 @@ class TimelineObserver(Loggable):
self.action_log.push(action)
def _trackElementActiveChangedCb(self, track_element, active, add_effect_action):
- """
- This happens when an effect is (de)activated on a clip in the timeline.
- """
+ """Handles an effect is (de)activated on a clip in the timeline."""
action = ActivePropertyChanged(add_effect_action, active)
self.action_log.push(action)
diff --git a/pitivi/undo/undo.py b/pitivi/undo/undo.py
index c3409b9..c021585 100644
--- a/pitivi/undo/undo.py
+++ b/pitivi/undo/undo.py
@@ -16,9 +16,7 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-Base classes for undo/redo.
-"""
+"""Undo/redo."""
import contextlib
from gi.repository import GObject
@@ -27,24 +25,20 @@ from pitivi.utils.loggable import Loggable
class UndoError(Exception):
- """
- Base class for undo/redo exceptions.
- """
+ """Base class for undo/redo exceptions."""
pass
class UndoWrongStateError(UndoError):
- """
- Exception related to the current state of the undo/redo stack.
- """
+ """Exception related to the current state of the undo/redo stack."""
pass
class UndoableAction(GObject.Object, Loggable):
- """
- An action that can be undone.
- In other words, when your object's state changes, create an UndoableAction
- to allow reverting the change if needed later on.
+ """An action that can be undone.
+
+ When your object's state changes, create an UndoableAction to allow
+ reverting the change later on.
"""
def __init__(self):
@@ -71,18 +65,14 @@ class SimpleUndoableAction(UndoableAction):
class FinalizingAction:
- """
- Base class for actions to happen when an UndoableActionStack is
- done or undone.
- """
+ """Base class for actions applied when an undo or redo is performed."""
+
def do(self):
raise NotImplementedError()
class UndoableActionStack(UndoableAction):
- """
- Simply a stack of UndoableAction objects.
- """
+ """A stack of UndoableAction objects."""
def __init__(self, action_group_name, finalizing_action=None):
UndoableAction.__init__(self)
@@ -118,8 +108,7 @@ class UndoableActionStack(UndoableAction):
class UndoableActionLog(GObject.Object, Loggable):
- """
- The undo/redo manager.
+ """The undo/redo manager.
A separate instance should be created for each Project instance.
"""
@@ -145,16 +134,19 @@ class UndoableActionLog(GObject.Object, Loggable):
@contextlib.contextmanager
def started(self, action_group_name, finalizing_action=None):
- """
- Returns a context manager which commits the transaction at the end.
- """
+ """Gets a context manager which commits the transaction at the end."""
self.begin(action_group_name, finalizing_action)
yield
self.commit(action_group_name)
def begin(self, action_group_name, finalizing_action=None):
- """
- Starts a transaction aka a high-level operation.
+ """Starts recording a high-level operation which later can be undone.
+
+ The recording can be stopped by calling the `commit` method or
+ canceled by calling the `rollback` method.
+
+ The operation will be composed of all the actions which have been
+ pushed and also of the committed sub-operations.
"""
if self.running:
self.debug("Abort because running")
@@ -167,9 +159,7 @@ class UndoableActionLog(GObject.Object, Loggable):
self.emit("begin", stack)
def push(self, action):
- """
- Adds an action to the current transaction.
- """
+ """Adds an action to the current operation."""
self.emit("pre-push", action)
if self.running:
@@ -187,9 +177,7 @@ class UndoableActionLog(GObject.Object, Loggable):
self.emit("push", stack, action)
def rollback(self):
- """
- Forgets about the last started transaction.
- """
+ """Forgets about the last started operation."""
if self.running:
self.debug("Ignore rollback because running")
return
@@ -202,9 +190,7 @@ class UndoableActionLog(GObject.Object, Loggable):
stack.undo()
def commit(self, action_group_name):
- """
- Commits the last started transaction.
- """
+ """Commits the last started operation."""
if self.running:
self.debug("Ignore commit because running")
return
@@ -229,9 +215,7 @@ class UndoableActionLog(GObject.Object, Loggable):
self.emit("commit", stack)
def undo(self):
- """
- Undo the last recorded operation.
- """
+ """Undoes the last recorded operation."""
if self.stacks:
raise UndoWrongStateError("Recording a transaction", self.stacks)
if not self.undo_stacks:
@@ -243,9 +227,7 @@ class UndoableActionLog(GObject.Object, Loggable):
self.emit("move", stack)
def redo(self):
- """
- Redo the last undone operation.
- """
+ """Redoes the last undone operation."""
if self.stacks:
raise UndoWrongStateError("Recording a transaction", self.stacks)
if not self.redo_stacks:
@@ -288,9 +270,7 @@ class UndoableActionLog(GObject.Object, Loggable):
return stack
def is_in_transaction(self):
- """
- Whether currently recording an operation.
- """
+ """Gets whether currently recording an operation."""
return bool(self.stacks)
@@ -311,13 +291,10 @@ class MetaChangedAction(UndoableAction):
class MetaContainerObserver(GObject.Object):
- """
- Monitors a MetaContainer's changes.
-
- Args:
- meta_container (GES.MetaContainer): The object to be monitored.
+ """Monitor for MetaContainer changes.
Attributes:
+ meta_container (GES.MetaContainer): The object to be monitored.
action_log (UndoableActionLog): The action log where to report actions.
"""
@@ -361,8 +338,7 @@ class PropertyChangedAction(UndoableAction):
class GObjectObserver(GObject.Object):
- """
- Monitors a GObject.Object's props and reports UndoableActions.
+ """Monitor for GObject.Object's props, reporting UndoableActions.
Attributes:
gobject (GObject.Object): The object to be monitored.
diff --git a/pitivi/utils/__init__.py b/pitivi/utils/__init__.py
index e6dd0f9..e69de29 100644
--- a/pitivi/utils/__init__.py
+++ b/pitivi/utils/__init__.py
@@ -1,3 +0,0 @@
-"""
-Timeline module
-"""
diff --git a/pitivi/utils/loggable.py b/pitivi/utils/loggable.py
index fd257a3..9ed389d 100644
--- a/pitivi/utils/loggable.py
+++ b/pitivi/utils/loggable.py
@@ -70,10 +70,7 @@ _LEVEL_NAMES = ['ERROR', 'WARN', 'FIXME', 'INFO', 'DEBUG', 'LOG']
class TerminalController:
-
- """
- A class that can be used to portably generate formatted output to
- a terminal.
+ """A class for generating formatted output to a terminal.
`TerminalController` defines a set of instance variables whose
values are initialized to the control sequence necessary to
@@ -81,13 +78,13 @@ class TerminalController:
output to the terminal:
>>> term = TerminalController()
- >>> print 'This is '+term.GREEN+'green'+term.NORMAL
+ >>> print('This is '+term.GREEN+'green'+term.NORMAL)
Alternatively, the `render()` method can used, which replaces
'${action}' with the string required to perform 'action':
>>> term = TerminalController()
- >>> print term.render('This is ${GREEN}green${NORMAL}')
+ >>> print(term.render('This is ${GREEN}green${NORMAL}'))
If the terminal doesn't support a given action, then the value of
the corresponding instance variable will be set to ''. As a
@@ -99,10 +96,15 @@ class TerminalController:
>>> term = TerminalController()
>>> if term.CLEAR_SCREEN:
- ... print 'This terminal supports clearning the screen.'
+ ... print('This terminal supports clearning the screen.')
Finally, if the width and height of the terminal are known, then
they will be stored in the `COLS` and `LINES` attributes.
+
+ Args:
+ term_stream (Optional): The stream that will be used for terminal
+ output; if this stream is not a tty, then the terminal is
+ assumed to be a dumb terminal (i.e., have no capabilities).
"""
# Cursor movement:
BOL = '' # : Move the cursor to the beginning of the line
@@ -148,13 +150,6 @@ class TerminalController:
_ANSICOLORS = "BLACK RED GREEN YELLOW BLUE MAGENTA CYAN WHITE".split()
def __init__(self, term_stream=sys.stdout):
- """
- Create a `TerminalController` and initialize its attributes
- with appropriate values for the current terminal.
- `term_stream` is the stream that will be used for terminal
- output; if this stream is not a tty, then the terminal is
- assumed to be a dumb terminal (i.e., have no capabilities).
- """
# Curses isn't available on all platforms
try:
import curses
@@ -211,10 +206,10 @@ class TerminalController:
return re.sub(r'\$<\d+>[/*]?', '', cap.decode()).encode()
def render(self, template):
- """
- Replace each $-substitutions in the given template string with
- the corresponding terminal control string (if it's defined) or
- '' (if it's not).
+ """Replaces each $-substitutions in the specified template string.
+
+ The placeholders are replaced with the corresponding terminal control
+ string (if it's defined) or '' (if it's not).
"""
return re.sub(r'\$\$|\${\w+}', self._render_sub, template)
@@ -231,9 +226,9 @@ class TerminalController:
class ProgressBar:
+ """A 3-line progress bar.
- """
- A 3-line progress bar, which looks like::
+ Looks like this:
Header
20% [===========----------------------------------]
@@ -242,6 +237,7 @@ class ProgressBar:
The progress bar is colored, if the terminal supports color
output; and adjusts to the width of the terminal.
"""
+
BAR = '%3d%% ${GREEN}[${BOLD}%s%s${NORMAL}${GREEN}]${NORMAL}\n'
HEADER = '${BOLD}${CYAN}%s${NORMAL}\n\n'
@@ -275,12 +271,13 @@ class ProgressBar:
def getLevelName(level):
- """
- Return the name of a log level.
- @param level: The level we want to know the name
- @type level: int
- @return: The name of the level
- @rtype: str
+ """Returns the name of the specified log level.
+
+ Args:
+ level (int): The level we want to know the name.
+
+ Returns:
+ str: The name of the level.
"""
assert isinstance(level, int) and level > 0 and level < 7, \
TypeError("Bad debug level")
@@ -288,21 +285,22 @@ def getLevelName(level):
def getLevelNames():
- """
- Return a list with the level names
- @return: A list with the level names
- @rtype: list of str
+ """Returns a list with the level names.
+
+ Returns:
+ List[str]: A list with the level names.
"""
return _LEVEL_NAMES
def getLevelInt(levelName):
- """
- Return the integer value of the levelName.
- @param levelName: The string value of the level name
- @type levelName: str
- @return: The value of the level name we are interested in.
- @rtype: int
+ """Returns the integer value of the levelName.
+
+ Args:
+ levelName (str): The string value of the level name.
+
+ Returns:
+ int: The value of the level name we are interested in.
"""
assert isinstance(levelName, str) and levelName in getLevelNames(), \
"Bad debug level name"
@@ -316,8 +314,8 @@ def getFormattedLevelName(level):
def registerCategory(category):
- """
- Register a given category in the debug system.
+ """Registers the specified category in the debug system.
+
A level will be assigned to it based on previous calls to setDebug.
"""
# parse what level it is set to based on _DEBUG
@@ -352,11 +350,13 @@ def registerCategory(category):
def getCategoryLevel(category):
- """
- @param category: string
+ """Gets the debug level at which the specified category is being logged.
+
+ Registers the category and thus assigns a log level if it wasn't registered
+ yet.
- Get the debug level at which this category is being logged, adding it
- if it wasn't registered yet.
+ Args:
+ category (string): The category we are interested in.
"""
global _categories
if category not in _categories:
@@ -365,10 +365,13 @@ def getCategoryLevel(category):
def setLogSettings(state):
- """Update the current log settings.
+ """Updates the current log settings.
+
This can restore an old saved log settings object returned by
- getLogSettings
- @param state: the settings to set
+ getLogSettings.
+
+ Args:
+ state: The settings to set.
"""
global _DEBUG
@@ -386,9 +389,12 @@ def setLogSettings(state):
def getLogSettings():
"""Fetches the current log settings.
+
The returned object can be sent to setLogSettings to restore the
returned settings
- @returns: the current settings
+
+ Returns:
+ The current settings.
"""
return (_DEBUG,
_categories,
@@ -419,18 +425,16 @@ def scrubFilename(filename):
def getFileLine(where=-1):
- """
- Return the filename and line number for the given location.
+ """Returns the filename and line number for the specified location.
- If where is a negative integer, look for the code entry in the current
- stack that is the given number of frames above this module.
- If where is a function, look for the code entry of the function.
+ Args:
+ where(int or function): If it's a (negative) integer, looks for
+ the code entry in the current stack that is the given number
+ of frames above this module.
+ If it's a function, look for the code entry of the function.
- @param where: how many frames to go back up, or function
- @type where: int (negative) or function
-
- @return: tuple of (file, line, function_name)
- @rtype: tuple of (str, int, str)
+ Returns:
+ str, int, str: file, line, function_name.
"""
co = None
lineno = None
@@ -462,9 +466,7 @@ def getFileLine(where=-1):
def ellipsize(o):
- """
- Ellipsize the representation of the given object.
- """
+ """Ellipsizes the representation of the given object."""
r = repr(o)
if len(r) < 800:
return r
@@ -474,8 +476,8 @@ def ellipsize(o):
def getFormatArgs(startFormat, startArgs, endFormat, endArgs, args, kwargs):
- """
- Helper function to create a format and args to use for logging.
+ """Creates a format and args to use for logging.
+
This avoids needlessly interpolating variables.
"""
debugArgs = startArgs[:]
@@ -494,22 +496,22 @@ def getFormatArgs(startFormat, startArgs, endFormat, endArgs, args, kwargs):
def doLog(level, object, category, format, args, where=-1, filePath=None, line=None):
- """
- @param where: what to log file and line number for;
- -1 for one frame above log.py; -2 and down for higher up;
- a function for a (future) code object
- @type where: int or callable
- @param filePath: file to show the message as coming from, if caller
- knows best
- @type filePath: str
- @param line: line to show the message as coming from, if caller
- knows best
- @type line: int
-
- @return: dict of calculated variables, if they needed calculating.
- currently contains file and line; this prevents us from
- doing this work in the caller when it isn't needed because
- of the debug level
+ """Logs something.
+
+ Args:
+ where (int or function): What to log file and line number for;
+ -1 for one frame above log.py; -2 and down for higher up;
+ a function for a (future) code object.
+ filePath (Optional[str]): The file to show the message as coming from,
+ if caller knows best.
+ line (Optional[int]): The line to show the message as coming from,
+ if caller knows best.
+
+ Returns:
+ A dict of calculated variables, if they needed calculating.
+ currently contains file and line; this prevents us from
+ doing this work in the caller when it isn't needed because
+ of the debug level.
"""
ret = {}
@@ -542,53 +544,49 @@ def doLog(level, object, category, format, args, where=-1, filePath=None, line=N
def errorObject(object, cat, format, *args):
- """
- Log a fatal error message in the given category.
- This will also raise a L{SystemExit}.
+ """Logs a fatal error message in the specified category.
+
+ This will also raise a `SystemExit`.
"""
doLog(ERROR, object, cat, format, args)
def warningObject(object, cat, format, *args):
- """
- Log a warning message in the given category.
+ """Logs a warning message in the specified category.
+
This is used for non-fatal problems.
"""
doLog(WARN, object, cat, format, args)
def fixmeObject(object, cat, format, *args):
- """
- Log a fixme message in the given category.
- This is used for not implemented codepaths or known issues in the code
+ """Logs a fixme message in the specified category.
+
+ This is used for not implemented codepaths or known issues in the code.
"""
doLog(FIXME, object, cat, format, args)
def infoObject(object, cat, format, *args):
- """
- Log an informational message in the given category.
- """
+ """Logs an informational message in the specified category."""
doLog(INFO, object, cat, format, args)
def debugObject(object, cat, format, *args):
- """
- Log a debug message in the given category.
- """
+ """Logs a debug message in the specified category."""
doLog(DEBUG, object, cat, format, args)
def logObject(object, cat, format, *args):
- """
- Log a log message. Used for debugging recurring events.
+ """Logs a log message.
+
+ Used for debugging recurring events.
"""
doLog(LOG, object, cat, format, args)
def safeprintf(file, format, *args):
- """Write to a file object, ignoring errors.
- """
+ """Writes to a file object, ignoring errors."""
try:
if args:
file.write(format % args)
@@ -603,15 +601,16 @@ def safeprintf(file, format, *args):
def printHandler(level, object, category, file, line, message):
- """
- A log handler that writes to stderr.
+ """Writes to stderr.
+
The output will be different depending the value of "_enableCrackOutput";
in Pitivi's case, that is True when the GST_DEBUG env var is defined.
- @type level: string
- @type object: string (or None)
- @type category: string
- @type message: string
+ Args:
+ level (str):
+ object (str): Can be None.
+ category (str):
+ message (str):
"""
global _outfile
@@ -671,10 +670,13 @@ def _preformatLevels(enableColorOutput):
def init(envVarName, enableColorOutput=True, enableCrackOutput=True):
- """
- Initialize the logging system and parse the environment variable
- of the given name.
- Needs to be called before starting the actual application.
+ """Initializes the logging system.
+
+ Needs to be called before using the log methods.
+
+ Args:
+ envVarName (str): The name of the environment variable with additional
+ settings.
"""
global _initialized
global _outfile
@@ -706,7 +708,10 @@ def init(envVarName, enableColorOutput=True, enableCrackOutput=True):
def setDebug(string):
- """Set the DEBUG string. This controls the log output."""
+ """Sets the DEBUG string.
+
+ This controls the log output.
+ """
global _DEBUG
global _ENV_VAR_NAME
global _categories
@@ -720,30 +725,26 @@ def setDebug(string):
def getDebug():
- """
- Returns the currently active DEBUG string.
- @rtype: str
- """
+ """Returns the currently active DEBUG string."""
global _DEBUG
return _DEBUG
def setPackageScrubList(*packages):
- """
- Set the package names to scrub from filenames.
+ """Sets the package names to scrub from filenames.
+
Filenames from these paths in log messages will be scrubbed to their
relative file path instead of the full absolute path.
- @type packages: list of str
+ Args:
+ *packages (List[str]): The packages names to scrub.
"""
global _PACKAGE_SCRUB_LIST
_PACKAGE_SCRUB_LIST = packages
def reset():
- """
- Resets the logging system, removing all log handlers.
- """
+ """Resets the logging system, removing all log handlers."""
global _log_handlers, _log_handlers_limited, _initialized
_log_handlers = []
@@ -752,16 +753,19 @@ def reset():
def addLogHandler(func):
- """
- Add a custom log handler.
+ """Adds a custom log handler.
+
+ The log handler receives all the log messages.
- @param func: a function object with prototype (level, object, category,
- message) where level is either ERROR, WARN, INFO, DEBUG, or
- LOG, and the rest of the arguments are strings or None. Use
- getLevelName(level) to get a printable name for the log level.
- @type func: a callable function
+ Args:
+ func (function): A function object with prototype
+ (level, object, category, message) where level is either
+ ERROR, WARN, INFO, DEBUG, or LOG, and the rest of the arguments are
+ strings or None. Use getLevelName(level) to get a printable name
+ for the log level.
- @raises TypeError: if func is not a callable
+ Raises:
+ TypeError: When func is not a callable.
"""
if not isinstance(func, collections.Callable):
@@ -772,16 +776,19 @@ def addLogHandler(func):
def addLimitedLogHandler(func):
- """
- Add a custom log handler.
+ """Adds a custom limited log handler.
- @param func: a function object with prototype (level, object, category,
- message) where level is either ERROR, WARN, INFO, DEBUG, or
- LOG, and the rest of the arguments are strings or None. Use
- getLevelName(level) to get a printable name for the log level.
- @type func: a callable function
+ The log handler receives only the messages passing the filter.
- @raises TypeError: TypeError if func is not a callable
+ Args:
+ func (function): A function object with prototype
+ (level, object, category, message) where level is either
+ ERROR, WARN, INFO, DEBUG, or LOG, and the rest of the arguments are
+ strings or None. Use getLevelName(level) to get a printable name
+ for the log level.
+
+ Raises:
+ TypeError: When func is not a callable.
"""
if not isinstance(func, collections.Callable):
raise TypeError("func must be callable")
@@ -791,31 +798,19 @@ def addLimitedLogHandler(func):
def removeLogHandler(func):
- """
- Remove a registered log handler.
-
- @param func: a function object with prototype (level, object, category,
- message) where level is either ERROR, WARN, INFO, DEBUG, or
- LOG, and the rest of the arguments are strings or None. Use
- getLevelName(level) to get a printable name for the log level.
- @type func: a callable function
+ """Removes a registered log handler.
- @raises ValueError: if func is not registered
+ Raises:
+ ValueError: When func is not registered.
"""
_log_handlers.remove(func)
def removeLimitedLogHandler(func):
- """
- Remove a registered limited log handler.
-
- @param func: a function object with prototype (level, object, category,
- message) where level is either ERROR, WARN, INFO, DEBUG, or
- LOG, and the rest of the arguments are strings or None. Use
- getLevelName(level) to get a printable name for the log level.
- @type func: a callable function
+ """Removes a registered limited log handler.
- @raises ValueError: if func is not registered
+ Raises:
+ ValueError: When func is not registered.
"""
_log_handlers_limited.remove(func)
@@ -849,8 +844,9 @@ def log(cat, format, *args):
def getExceptionMessage(exception, frame=-1, filename=None):
- """
- Return a short message based on an exception, useful for debugging.
+ """Returns a short message based on an exception.
+
+ Useful for debugging.
Tries to find where the exception was triggered.
"""
stack = traceback.extract_tb(sys.exc_info()[2])
@@ -870,10 +866,7 @@ def getExceptionMessage(exception, frame=-1, filename=None):
def reopenOutputFiles():
- """
- Reopens the stdout and stderr output files, as set by
- L{outputToFiles}.
- """
+ """Reopens the stdout and stderr output files, as set by `outputToFiles`."""
if not _stdout and not _stderr:
debug('log', 'told to reopen log files, but log files not set')
return
@@ -896,8 +889,7 @@ def reopenOutputFiles():
def outputToFiles(stdout=None, stderr=None):
- """
- Redirect stdout and stderr to named files.
+ """Redirects stdout and stderr to the specified files.
Records the file names so that a future call to reopenOutputFiles()
can open the same files. Installs a SIGHUP handler that will reopen
@@ -931,93 +923,93 @@ def outputToFiles(stdout=None, stderr=None):
class BaseLoggable(object):
+ """Base class for objects that want to be able to log messages.
- """
- Base class for objects that want to be able to log messages with
- different level of severity. The levels are, in order from least
+ The levels of severity for the messages are, in order from least
to most: log, debug, info, warning, error.
- @cvar logCategory: Implementors can provide a category to log their
- messages under.
+ Attributes:
+ logCategory (str): The category under which the messages will be filed.
+ Can be used to set a display filter.
"""
- def writeMarker(self, marker, level):
- """
- Sets a marker that written to the logs. Setting this
- marker to multiple elements at a time helps debugging.
- @param marker: A string write to the log.
- @type marker: str
- @param level: The log level. It can be log.ERROR, etc.
- @type level: int
- """
- logHandlers = {WARN: self.warning,
- INFO: self.info,
- DEBUG: self.debug,
- ERROR: self.error,
- LOG: self.log}
- logHandler = logHandlers.get(level)
- if logHandler:
- logHandler('%s', marker)
-
def error(self, *args):
- """Log an error. By default this will also raise an exception."""
+ """Logs an error.
+
+ By default this will also raise an exception.
+ """
if _canShortcutLogging(self.logCategory, ERROR):
return
errorObject(self.logObjectName(),
self.logCategory, *self.logFunction(*args))
def warning(self, *args):
- """Log a warning. Used for non-fatal problems."""
+ """Logs a warning.
+
+ Used for non-fatal problems.
+ """
if _canShortcutLogging(self.logCategory, WARN):
return
warningObject(
self.logObjectName(), self.logCategory, *self.logFunction(*args))
def fixme(self, *args):
- """Log a fixme. Used for FIXMEs ."""
+ """Logs a fixme.
+
+ Used for FIXMEs.
+ """
if _canShortcutLogging(self.logCategory, FIXME):
return
fixmeObject(self.logObjectName(),
self.logCategory, *self.logFunction(*args))
def info(self, *args):
- """Log an informational message. Used for normal operation."""
+ """Logs an informational message.
+
+ Used for normal operation.
+ """
if _canShortcutLogging(self.logCategory, INFO):
return
infoObject(self.logObjectName(),
self.logCategory, *self.logFunction(*args))
def debug(self, *args):
- """Log a debug message. Used for debugging."""
+ """Logs a debug message.
+
+ Used for debugging.
+ """
if _canShortcutLogging(self.logCategory, DEBUG):
return
debugObject(self.logObjectName(),
self.logCategory, *self.logFunction(*args))
def log(self, *args):
- """Log a log message. Used for debugging recurring events."""
+ """Logs a log message.
+
+ Used for debugging recurring events.
+ """
if _canShortcutLogging(self.logCategory, LOG):
return
logObject(self.logObjectName(),
self.logCategory, *self.logFunction(*args))
def doLog(self, level, where, format, *args, **kwargs):
- """
- Log a message at the given level, with the possibility of going
+ """Logs a message at the specified level, with the possibility of going
higher up in the stack.
- @param level: log level
- @type level: int
- @param where: how many frames to go back from the last log frame;
- or a function (to log for a future call)
- @type where: int (negative), or function
-
- @param kwargs: a dict of pre-calculated values from a previous
- doLog call
-
- @return: a dict of calculated variables, to be reused in a
- call to doLog that should show the same location
- @rtype: dict
+ Args:
+ level (int): The log level.
+ where (int or function): How many frames to go back from
+ the last log frame, must be negative; or a function
+ (to log for a future call).
+ format (str): The string template for the message.
+ *args: The arguments used when converting the `format`
+ string template to the message.
+ **kwargs: The pre-calculated values from a previous doLog call.
+
+ Returns:
+ dict: The calculated variables, to be reused in a
+ call to doLog that should show the same location.
"""
if _canShortcutLogging(self.logCategory, level):
return {}
@@ -1026,11 +1018,14 @@ class BaseLoggable(object):
format, args, where=where, **kwargs)
def logFunction(self, *args):
- """Overridable log function. Default just returns passed message."""
+ """Processes the arguments applied to the message template.
+
+ Default just returns the arguments unchanged.
+ """
return args
def logObjectName(self):
- """Overridable object name function."""
+ """Gets the name of this object."""
# cheat pychecker
for name in ['logName', 'name']:
if hasattr(self, name):
diff --git a/pitivi/utils/misc.py b/pitivi/utils/misc.py
index fd75d8e..19a6d29 100644
--- a/pitivi/utils/misc.py
+++ b/pitivi/utils/misc.py
@@ -66,14 +66,17 @@ def format_ns(timestamp):
def call_false(function, *args, **kwargs):
- """ Helper function for calling an arbitrary function once in the gobject
- mainloop. Any positional or keyword arguments after the function will
- be provided to the function.
-
- @param function: the function to call
- @type function: callable({any args})
- @returns: False
- @rtype: bool
+ """Calls the specified function and returns False.
+
+ Helper function for calling an arbitrary function once in the gobject
+ mainloop. Any positional or keyword arguments after the function will
+ be provided to the function.
+
+ Args:
+ function (function): The function to call.
+
+ Returns:
+ bool: False
"""
function(*args, **kwargs)
return False
@@ -97,9 +100,7 @@ def get_proxy_target(obj):
# ------------------------------ URI helpers --------------------------------
def isWritable(path):
- """
- Return whether the file/path is writable.
- """
+ """Returns whether the file/path is writable."""
try:
if os.path.isdir(path):
# The given path is an existing directory.
@@ -117,13 +118,12 @@ def isWritable(path):
def uri_is_valid(uri):
- """
- Checks if the given uri is a valid uri (of type file://)
+ """Checks if the specified URI is usable (of type file://).
Will also check if the size is valid (> 0).
- @param uri: The location to check
- @type uri: C{str}
+ Args:
+ uri (str): The location to check.
"""
return (Gst.uri_is_valid(uri) and
Gst.uri_get_protocol(uri) == "file" and
@@ -131,12 +131,13 @@ def uri_is_valid(uri):
def uri_is_reachable(uri):
- """
- Check whether the given uri is reachable by GStreamer.
+ """Checks whether the specified URI is reachable by GStreamer.
+
+ Args:
+ uri (str): The location to check.
- @param uri: The location to check
- @type uri: C{str}
- @return: Whether the uri is reachable.
+ Returns:
+ bool: True when the URI is reachable, False otherwise.
"""
if not uri_is_valid(uri):
raise NotImplementedError(
@@ -147,25 +148,26 @@ def uri_is_reachable(uri):
def path_from_uri(raw_uri):
- """
- Return a path that can be used with Python's os.path.
- """
+ """Returns a path that can be used with Python's os.path."""
uri = urlparse(raw_uri)
assert uri.scheme == "file"
return unquote(uri.path)
def filename_from_uri(uri):
- """
- Return a human-readable filename (excluding the path to the file) to be
- used in UI elements or to shorten debug statements
+ """Returns a filename for display.
+
+ Excludes the path to the file.
+
+ Can be used in UI elements or to shorten debug statements.
"""
return os.path.basename(path_from_uri(uri))
def quote_uri(uri):
- """
- Encode a URI/path according to RFC 2396, without touching the file:/// part.
+ """Encodes a URI according to RFC 2396.
+
+ Does not touch the file:/// part.
"""
# Split off the "file:///" part, if present.
parts = urlsplit(uri, allow_fragments=False)
@@ -177,14 +179,11 @@ def quote_uri(uri):
class PathWalker(Thread):
-
- """
- Thread for recursively searching in a list of directories
- """
+ """Thread for recursively searching in a list of directories."""
def __init__(self, paths, callback):
Thread.__init__(self)
- self.log("New PathWalker for %s" % paths)
+ self.log("New PathWalker for %s", paths)
self.paths = paths
self.callback = callback
self.stopme = threading.Event()
@@ -209,7 +208,7 @@ class PathWalker(Thread):
def hash_file(uri):
- """Hashes the first 256KB of the specified file"""
+ """Hashes the first 256KB of the specified file."""
sha256 = hashlib.sha256()
with open(uri, "rb") as file:
for _ in range(1024):
@@ -227,7 +226,8 @@ def quantize(input, interval):
def binary_search(elements, value):
"""Returns the index of the element closest to value.
- @param elements: A sorted list.
+ Args:
+ elements (List): A sorted list.
"""
if not elements:
return -1
@@ -247,9 +247,13 @@ def binary_search(elements, value):
def show_user_manual(page=None):
- """
- Display the user manual with Yelp.
- Optional: for contextual help, a page ID can be specified.
+ """Displays the user manual.
+
+ First tries with Yelp and then tries opening the online version.
+
+ Args:
+ page (Optional[str]): A page ID to display instead of the index page,
+ for contextual help.
"""
def get_page_uri(uri, page):
if page is not None:
diff --git a/pitivi/utils/pipeline.py b/pitivi/utils/pipeline.py
index 02ee061..5eeac9f 100644
--- a/pitivi/utils/pipeline.py
+++ b/pitivi/utils/pipeline.py
@@ -1,7 +1,5 @@
-#!/usr/bin/env python3
-#
-# pitivi/utils/pipeline.py
-#
+# -*- coding: utf-8 -*-
+# Pitivi video editor
# Copyright (C) 2012 Thibault Saunier <thibault saunier collabora com>
#
# This program is free software; you can redistribute it and/or
@@ -20,9 +18,7 @@
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3, or (at your option)
# any later version.
-"""
-High-level pipelines
-"""
+"""High-level pipelines."""
import os
from gi.repository import GES
@@ -58,21 +54,22 @@ class PipelineError(Exception):
class SimplePipeline(GObject.Object, Loggable):
+ """High-level pipeline.
- """
- The Pipeline is only responsible for:
+ The `SimplePipeline` is responsible for:
- State changes
- Position seeking
- - Position Querying
- - Along with an periodic callback (optional)
+ - Position querying
+ - Along with an periodic callback (optional)
Signals:
- - C{state-change} : The state of the pipeline changed.
- - C{position} : The current position of the pipeline changed.
- - C{eos} : The Pipeline has finished playing.
- - C{error} : An error happened.
+ state-change: The state of the pipeline changed.
+ position: The current position of the pipeline changed.
+ eos: The Pipeline has finished playing.
+ error: An error happened.
- @type _pipeline: L{Gst.Pipeline}
+ Attributes:
+ _pipeline (Gst.Pipeline): The low-level pipeline.
"""
__gsignals__ = PIPELINE_SIGNALS
@@ -122,14 +119,12 @@ class SimplePipeline(GObject.Object, Loggable):
self._force_position_listener = force
def release(self):
- """
- Release the L{Pipeline} and all used L{ObjectFactory} and
- L{Action}s.
+ """Releases the low-level pipeline.
- Call this method when the L{Pipeline} is no longer used. Forgetting to do
- so will result in memory loss.
+ Call this method when this instance is no longer used. Forgetting to do
+ so will result in memory leaks.
- @postcondition: The L{Pipeline} will no longer be usable.
+ The instance will no longer be usable.
"""
self.deactivatePositionListener()
self._bus.disconnect_by_func(self._busMessageCb)
@@ -150,11 +145,11 @@ class SimplePipeline(GObject.Object, Loggable):
pass
def setState(self, state):
- """
- Set the L{Pipeline} to the given state.
+ """Sets the low-level pipeline to the specified state.
- @raises PipelineError: If the C{Gst.Pipeline} could not be changed to
- the requested state.
+ Raises:
+ PipelineError: If the low-level pipeline could not be changed to
+ the requested state.
"""
self.debug("state set to: %r", state)
if state >= Gst.State.PAUSED:
@@ -177,14 +172,12 @@ class SimplePipeline(GObject.Object, Loggable):
"Failure changing state of the Gst.Pipeline to %r, currently reset to NULL" % state)
def getState(self):
- """
- Query the L{Pipeline} for the current state.
-
- @see: L{setState}
+ """Queries the low-level pipeline for the current state.
This will do an actual query to the underlying GStreamer Pipeline.
- @return: The current state.
- @rtype: C{State}
+
+ Returns:
+ State: The current state.
"""
# No timeout
change, state, pending = self._pipeline.get_state(timeout=0)
@@ -193,21 +186,15 @@ class SimplePipeline(GObject.Object, Loggable):
return state
def play(self):
- """
- Sets the L{Pipeline} to PLAYING
- """
+ """Sets the state to Gst.State.PLAYING."""
self.setState(Gst.State.PLAYING)
def pause(self):
- """
- Sets the L{Pipeline} to PAUSED
- """
+ """Sets the state to Gst.State.PAUSED."""
self.setState(Gst.State.PAUSED)
def stop(self):
- """
- Sets the L{Pipeline} to READY
- """
+ """Sets the state to Gst.State.READY."""
self.setState(Gst.State.READY)
def playing(self):
@@ -222,12 +209,13 @@ class SimplePipeline(GObject.Object, Loggable):
# Position and Seeking methods
def getPosition(self, fails=True):
- """
- Get the current position of the L{Pipeline}.
+ """Gets the current position of the low-level pipeline.
- @return: The current position or Gst.CLOCK_TIME_NONE
- @rtype: L{long}
- @raise PipelineError: If the position couldn't be obtained.
+ Returns:
+ int: The current position or Gst.CLOCK_TIME_NONE.
+
+ Raises:
+ PipelineError: If the position couldn't be obtained.
"""
try:
res, cur = self._pipeline.query_position(Gst.Format.TIME)
@@ -245,9 +233,7 @@ class SimplePipeline(GObject.Object, Loggable):
return cur
def getDuration(self):
- """
- Get the duration of the C{Pipeline}.
- """
+ """Gets the duration of the low-level pipeline."""
dur = self._getDuration()
self.log("Got duration %s", format_ns(dur))
if self._duration != dur:
@@ -256,17 +242,16 @@ class SimplePipeline(GObject.Object, Loggable):
return dur
def activatePositionListener(self, interval=DEFAULT_POSITION_LISTENNING_INTERVAL):
- """
- Activate the position listener.
+ """Activates the position listener.
- When activated, the Pipeline will emit the 'position' signal at the
+ When activated, the instance will emit the `position` signal at the
specified interval when it is the PLAYING or PAUSED state.
- @see: L{deactivatePositionListener}
- @param interval: Interval between position queries in milliseconds
- @type interval: L{int} milliseconds
- @return: Whether the position listener was activated or not
- @rtype: L{bool}
+ Args:
+ interval (int): Interval between position queries in milliseconds.
+
+ Returns:
+ bool: Whether the position listener was activated.
"""
if self._listening:
return True
@@ -277,11 +262,7 @@ class SimplePipeline(GObject.Object, Loggable):
return True
def deactivatePositionListener(self):
- """
- De-activates the position listener.
-
- @see: L{activatePositionListener}
- """
+ """De-activates the position listener."""
self._listenToPosition(False)
self._listening = False
@@ -330,12 +311,13 @@ class SimplePipeline(GObject.Object, Loggable):
self._waiting_for_async_done = True
def simple_seek(self, position):
- """
- Seeks in the L{Pipeline} to the given position.
+ """Seeks in the low-level pipeline to the specified position.
+
+ Args:
+ position (int): Position to seek to.
- @param position: Position to seek to
- @type position: L{long}
- @raise PipelineError: If seek failed
+ Raises:
+ PipelineError: When the seek fails.
"""
if self._waiting_for_async_done is True:
self._next_seek = position
@@ -506,10 +488,7 @@ class SimplePipeline(GObject.Object, Loggable):
class AssetPipeline(SimplePipeline):
-
- """
- Pipeline for playing a single clip.
- """
+ """Pipeline for playing a single clip."""
def __init__(self, clip=None, name=None):
bPipeline = Gst.ElementFactory.make("playbin", name)
@@ -530,10 +509,7 @@ class AssetPipeline(SimplePipeline):
class Pipeline(GES.Pipeline, SimplePipeline):
-
- """
- Helper to handle GES.Pipeline through the SimplePipeline API
- """
+ """Helper to handle GES.Pipeline through the SimplePipeline API."""
__gsignals__ = PIPELINE_SIGNALS
@@ -579,22 +555,14 @@ class Pipeline(GES.Pipeline, SimplePipeline):
raise PipelineError("Cannot set the timeline to the pipeline")
self._timeline = timeline
- def release(self):
- """
- Release the L{Pipeline} and all used L{ObjectFactory} and
- L{Action}s.
-
- Call this method when the L{Pipeline} is no longer used. Forgetting to do
- so will result in memory loss.
-
- @postcondition: The L{Pipeline} will no longer be usable.
- """
- SimplePipeline.release(self)
-
def stepFrame(self, framerate, frames_offset):
- """
- Seek backwards or forwards a certain amount of frames (frames_offset).
+ """Seeks backwards or forwards the specified amount of frames.
+
This clamps the playhead to the project frames.
+
+ Args:
+ frames_offsets (int): The number of frames to step. Negative number
+ for stepping backwards.
"""
try:
position = self.getPosition()
diff --git a/pitivi/utils/proxy.py b/pitivi/utils/proxy.py
index 5861ca5..574204d 100644
--- a/pitivi/utils/proxy.py
+++ b/pitivi/utils/proxy.py
@@ -72,9 +72,8 @@ def createEncodingProfileSimple(container_caps, audio_caps, video_caps):
class ProxyManager(GObject.Object, Loggable):
- """
- Transcodes assets and manages proxies
- """
+ """Transcodes assets and manages proxies."""
+
__gsignals__ = {
"progress": (GObject.SIGNAL_RUN_LAST, None, (object, int, int)),
"proxy-ready": (GObject.SIGNAL_RUN_LAST, None, (object, object)),
@@ -205,8 +204,9 @@ class ProxyManager(GObject.Object, Loggable):
return ".".join(proxy_asset.props.id.split(".")[:-3])
def getProxyUri(self, asset):
- """
- Returns the URI of a possible proxy file. The name looks like:
+ """Returns the URI of a possible proxy file.
+
+ The name looks like:
<filename>.<file_size>.<proxy_extension>
"""
asset_file = Gio.File.new_for_uri(asset.get_id())
diff --git a/pitivi/utils/ripple_update_group.py b/pitivi/utils/ripple_update_group.py
index 7865b03..d9d9634 100644
--- a/pitivi/utils/ripple_update_group.py
+++ b/pitivi/utils/ripple_update_group.py
@@ -19,9 +19,9 @@
class RippleUpdateGroup(object):
+ """Allows for event-driven spreadsheet-like ripple updates.
- """Allows for event-driven spreadsheet-like ripple updates without
- infinite loops.
+ Detects infinite loops.
This class allows you to express an event-driven sequence of operations in
terms of a directed graph. It is not a constraint solver: The goal is to
@@ -64,8 +64,10 @@ class RippleUpdateGroup(object):
cycle. this function will not be called if the condition function
returns False.
- @ivar arcs: A map from widget to a list of edges originating in the widget.
- @ivar update_funcs: A map from widget to a (callable, args) tuple.
+ Attributes:
+ arcs (dict): A map from widget to a list of edges originating in
+ the widget.
+ update_funcs (dict): A map from widget to a (callable, args) tuple.
"""
def __init__(self):
@@ -75,16 +77,15 @@ class RippleUpdateGroup(object):
def addVertex(self, widget, signal=None, update_func=None,
update_func_args=()):
- """Add a widget to the list of vertexes.
-
- @param widget: The vertex to be added.
- @type widget: Gtk.Widget
- @param signal: A signal of the widget to be monitored.
- @type signal: str
- @param update_func: A callable object called when the vertex is visited.
- @type update_func: function
- @param update_func_args: The arguments for calling update_func.
- @type update_func_args: tuple
+ """Adds a widget to the list of vertexes.
+
+ Args:
+ widget (Gtk.Widget): The vertex to be added.
+ signal (Optional[str]): A signal of the widget to be monitored.
+ update_func (Optional[function]): A callable object called when the
+ vertex is visited.
+ update_func_args (Optional[List]): The arguments for calling
+ update_func.
"""
if signal:
widget.connect(signal, self._widgetValueChanged)
@@ -92,30 +93,28 @@ class RippleUpdateGroup(object):
self.arcs[widget] = []
def addEdge(self, widget_a, widget_b, predicate=None, edge_func=None):
- """Add a directional edge from widget_a to widget_b.
-
- @param widget_a: The source vertex.
- @type widget_a: Gtk.Widget
- @param widget_b: The target vertex.
- @type widget_b: Gtk.Widget
- @param predicate: A callable object returning whether the edge may be
- traversed.
- @type predicate: function
- @param edge_func: A callable object called when the edge is traversed.
- @type edge_func: function
+ """Adds a directional edge from widget_a to widget_b.
+
+ Args:
+ widget_a (Gtk.Widget): The source vertex.
+ widget_b (Gtk.Widget): The target vertex.
+ predicate (Optional[function]): A callable object returning whether
+ the edge may be traversed.
+ edge_func (Optional[function]): A callable object called when the
+ edge is traversed.
"""
self.arcs[widget_a].append((widget_b, predicate, edge_func))
def addBiEdge(self, widget_a, widget_b, predicate=None, edge_func=None):
- """Add a bidirectional edge between the specified vertexes.
+ """Adds a bidirectional edge between the specified vertexes.
- @see: addEdge
+ See `addEdge`.
"""
self.addEdge(widget_a, widget_b, predicate, edge_func)
self.addEdge(widget_b, widget_a, predicate, edge_func)
def _widgetValueChanged(self, widget, *unused):
- """Handle an event generated by the specified widget."""
+ """Handles an event generated by the specified widget."""
if self.ignore_new_signals:
return
@@ -126,7 +125,7 @@ class RippleUpdateGroup(object):
self.ignore_new_signals = False
def _updateValues(self, widget):
- """Traverse the graph starting from the specified widget."""
+ """Traverses the graph starting from the specified vertex."""
# Initialize the list of (source_widget, arc) to be traversed.
queue = [(widget, arc) for arc in self.arcs[widget]]
visited = set([widget])
diff --git a/pitivi/utils/system.py b/pitivi/utils/system.py
index 83e7fbe..2ef7adf 100644
--- a/pitivi/utils/system.py
+++ b/pitivi/utils/system.py
@@ -28,10 +28,7 @@ from pitivi.utils.loggable import Loggable
class System(GObject.Object, Loggable):
-
- """
- A base class for systems in which Pitivi runs.
- """
+ """A base class for systems in which Pitivi runs."""
__gsignals__ = {
'update-power-inhibition': (GObject.SIGNAL_RUN_LAST, None, ()),
@@ -90,30 +87,35 @@ class System(GObject.Object, Loggable):
# screensaver
def inhibitScreensaver(self, key):
- """increase screensaver inhibitor count
- @arg key: C{str} a unique translated string, giving the reason for
- inhibiting sleep
- NOTE: it is safe to call this method with a key that is already
- inhibited
+ """Increases the screensaver inhibitor count.
+
+ It is safe to call this method with a key that is already inhibited.
+
+ Args:
+ key (str): A unique translated string, giving the reason for
+ inhibiting sleep
"""
self.info("Inhibiting the screensaver")
self._inhibit(self._screensaver_keys, key)
def uninhibitScreensaver(self, key):
- """decrease screensaver inhibitor count
- @arg key: C{str} a unique translated string, giving the reason for
- inhibiting sleep
- NOTE: it is safe to call this method with a key that is not inhibited.
+ """Decreases screensaver inhibitor count.
+
+ It is safe to call this method with a key that is not inhibited.
+
+ Args:
+ key (str): A unique translated string, giving the reason for
+ inhibiting sleep
"""
self.info("Uninhibiting the screensaver")
self._uninhibit(self._screensaver_keys, key)
def screensaverIsInhibited(self, key=None):
- """returns True if inhibited"""
+ """Checks whether inhibited."""
return self._isInhibited(self._screensaver_keys, key)
def getScreensaverInhibitors(self):
- """returns a comma seperated string of screensaver inhibitor keys"""
+ """Returns a comma separated string of screensaver inhibitor keys."""
return ", ".join(self._screensaver_keys)
def screensaverIsBlockable(self):
@@ -121,30 +123,35 @@ class System(GObject.Object, Loggable):
# Sleep
def inhibitSleep(self, key):
- """increase sleep inhibitor count
- @arg key: C{str} a unique translated string, giving the reason for
- inhibiting sleep
- NOTE: it is safe to call this method with a key that is already
- inhibited
+ """Increase the sleep inhibitor count.
+
+ It is safe to call this method with a key that is already inhibited.
+
+ Args:
+ key (str): A unique translated string, giving the reason for
+ inhibiting sleep
"""
self.info("Inhibiting sleep")
self._inhibit(self._sleep_keys, key)
def uninhibitSleep(self, key):
- """decrease sleep inhibitor count
- @arg key: C{str} a unique translated string, giving the reason for
- inhibiting sleep
- NOTE: it is safe to call this method with a key that is not inhibited.
+ """Decreases sleep inhibitor count.
+
+ It is safe to call this method with a key that is not inhibited.
+
+ Args:
+ key (str): A unique translated string, giving the reason for
+ inhibiting sleep
"""
self.info("Uninhibiting sleep")
self._uninhibit(self._sleep_keys, key)
def sleepIsInhibited(self, key=None):
- """returns true if inhibited"""
+ """Returns whether inhibited."""
return self._isInhibited(self._sleep_keys, key)
def getSleepInhibitors(self):
- """returns a comma seperated string of sleep inhibitor keys"""
+ """Returns a comma separated strinsg of sleep inhibitor keys."""
return ", ".join(self._sleep_keys)
def sleepIsBlockable(self):
@@ -156,26 +163,30 @@ class System(GObject.Object, Loggable):
self.emit('update-power-inhibition')
def desktopMessage(self, title, message, unused_icon=None):
- """send a message to the desktop to be displayed to the user
- @arg title: C{str} the title of the message
- @arg message: C{str} the body of the message
- @arg icon: C{str} icon to be shown with the message
+ """Sends a message to the desktop to be displayed to the user.
+
+ Args:
+ title (str): The title of the message.
+ message (str): The body of the message.
+ icon (str): The icon to be shown with the message
"""
self.debug("desktopMessage(): %s, %s", title, message)
return None
def getUniqueFilename(self, string):
- """Get a filename which can only be obtained from the specified string.
- @ivar string: the string to be translated.
- @type string: str
- @return: A filename which looks like the specified string.
+ """Gets a filename which can only be obtained from the specified string.
+
+ Args:
+ string (str): The string identifying the filename.
+
+ Returns:
+ str: A filename which looks like the specified string.
"""
return string.replace("%", "%37").replace("/", "%47")
class FreedesktopOrgSystem(System):
-
- """provides messaging capabilites for desktops that implement fd.o specs"""
+ """Provides messaging capabilites for desktops that implement fd.o specs."""
def __init__(self):
System.__init__(self)
@@ -277,24 +288,21 @@ class GnomeSystem(FreedesktopOrgSystem):
class DarwinSystem(System):
-
- """Apple OS X"""
+ """Apple OS X."""
def __init__(self):
System.__init__(self)
class WindowsSystem(System):
-
- """Microsoft Windows"""
+ """Microsoft Windows."""
def __init__(self):
System.__init__(self)
def get_system():
- """
- Create a System object.
+ """Creates a System object.
Returns:
System: A System object.
diff --git a/pitivi/utils/threads.py b/pitivi/utils/threads.py
index 2558c2e..27fad9c 100644
--- a/pitivi/utils/threads.py
+++ b/pitivi/utils/threads.py
@@ -29,10 +29,7 @@ from pitivi.utils.loggable import Loggable
class Thread(threading.Thread, GObject.Object, Loggable):
-
- """
- Event-powered thread
- """
+ """Event-powered thread."""
__gsignals__ = {
"done": (GObject.SIGNAL_RUN_LAST, None, ()),
@@ -44,36 +41,39 @@ class Thread(threading.Thread, GObject.Object, Loggable):
Loggable.__init__(self)
def stop(self):
- """ stop the thread, do not override """
+ """Stops the thread, do not override."""
self.abort()
self.emit("done")
def run(self):
- """ thread processing """
+ """Runs the thread."""
self.process()
self.emit("done")
def process(self):
- """ Implement this in subclasses """
+ """Processes the thread.
+
+ Implement this in subclasses.
+ """
raise NotImplementedError
def abort(self):
- """ Abort the thread. Subclass have to implement this method ! """
+ """Aborts the thread.
+
+ Subclass have to implement this method !
+ """
pass
class ThreadMaster(Loggable):
-
- """
- Controls all the threads existing in Pitivi.
- """
+ """Threads controller."""
def __init__(self):
Loggable.__init__(self)
self.threads = []
def addThread(self, threadclass, *args):
- """ Instantiate the specified Thread class and start it. """
+ """Instantiates the specified Thread class and starts it."""
assert issubclass(threadclass, Thread)
self.log("Adding thread of type %r", threadclass)
thread = threadclass(*args)
@@ -88,7 +88,7 @@ class ThreadMaster(Loggable):
self.threads.remove(thread)
def stopAllThreads(self):
- """ Stop all running Thread(s) controlled by this master """
+ """Stops all running Threads controlled by this master."""
self.log("stopping all threads")
joinedthreads = 0
while joinedthreads < len(self.threads):
diff --git a/pitivi/utils/timeline.py b/pitivi/utils/timeline.py
index f39a3c2..cb3076f 100644
--- a/pitivi/utils/timeline.py
+++ b/pitivi/utils/timeline.py
@@ -35,23 +35,16 @@ UNSELECT = 1
SELECT_ADD = 2
-# -------- Timeline Object management helper ---------#
-
class TimelineError(Exception):
-
- """Base Exception for errors happening in L{Timeline}s or L{Clip}s"""
+ """Base Exception for errors happening in `Timeline`s or `Clip`s."""
pass
class Selected(GObject.Object):
+ """Allows keeping track of the selection status for individual elements.
- """
- A simple class that let us emit a selected-changed signal
- when needed, and that can be check directly to know if the
- object is selected or not.
-
- This is meant only for individual elements, do not confuse this with
- utils.timeline's "Selection" class.
+ Signals:
+ selected-changed: Emitted when the selection is specified.
"""
__gsignals__ = {
@@ -63,10 +56,7 @@ class Selected(GObject.Object):
self._selected = False
def __bool__(self):
- """
- checking a Selected object is the same as checking its _selected
- property
- """
+ """Checks whether it's selected."""
return self._selected
@property
@@ -80,15 +70,13 @@ class Selected(GObject.Object):
class Selection(GObject.Object, Loggable):
+ """Manages a set of clips representing a selection.
- """
- A collection of L{GES.Clip}.
+ Attributes:
+ selected (List[GES.TrackElement]): Set of selected elements.
Signals:
- - C{selection-changed} : The contents of the L{GES.Selection} changed.
-
- @ivar selected: Set of selected L{GES.TrackElement}
- @type selected: C{list}
+ selection-changed: The contents of the selection changed.
"""
__gsignals__ = {
@@ -101,16 +89,16 @@ class Selection(GObject.Object, Loggable):
self.selected = set()
def setSelection(self, objs, mode):
- """
- Update the current selection.
-
- Depending on the value of C{mode}, the selection will be:
- - L{SELECT} : set to the provided selection.
- - L{UNSELECT} : the same minus the provided selection.
- - L{SELECT_ADD} : extended with the provided selection.
-
- @param objs: Timeline objects to update the selection with.
- @param mode: The type of update to apply. Can be C{SELECT}, C{UNSELECT} or C{SELECT_ADD}
+ """Updates the current selection.
+
+ Args:
+ objs (List[GES.TrackElement]): Timeline objects to update the
+ selection with.
+ mode (SELECT or UNSELECT or SELECT_ADD): The type of update to
+ apply. The selection will be:
+ - `SELECT` : set to the provided selection.
+ - `UNSELECT` : the same minus the provided selection.
+ - `SELECT_ADD` : extended with the provided selection.
"""
selection = set()
for obj in objs:
@@ -157,8 +145,10 @@ class Selection(GObject.Object, Loggable):
self.setSelection(objs, UNSELECT)
def getSelectedTrackElements(self):
- """
- Returns the list of L{TrackElement} contained in this selection.
+ """Returns the list of elements contained in this selection.
+
+ Returns:
+ List[GES.TrackElement]
"""
objects = []
for clip in self.selected:
@@ -178,8 +168,10 @@ class Selection(GObject.Object, Loggable):
return selected
def getSelectedEffects(self):
- """
- Returns the list of L{GES.BaseEffect} contained in this selection.
+ """Returns the list of effects contained in this selection.
+
+ Returns:
+ List[GES.BaseEffect]
"""
effects = []
for clip in self.selected:
@@ -189,10 +181,10 @@ class Selection(GObject.Object, Loggable):
return effects
def getSingleClip(self, clip_type):
- """
- Returns the single-selected clip, if any.
+ """Returns the single-selected clip, if any.
- @param clip_type: The class the clip must be an instance of.
+ Args:
+ clip_type (type): The class the clip must be an instance of.
"""
if len(self.selected) == 1:
clip = tuple(self.selected)[0]
@@ -207,40 +199,25 @@ class Selection(GObject.Object, Loggable):
return iter(self.selected)
-# -----------------------------------------------------------------------------#
-# Timeline edition modes helper #
-
class EditingContext(GObject.Object, Loggable):
-
- """
- Encapsulates interactive editing.
-
- This is the main class for interactive edition.
+ """Encapsulates interactive editing.
+
+ This is the main class for interactive editing.
+ Handles various timeline editing modes.
+
+ Attributes:
+ focus (GES.Clip or GES.TrackElement): The Clip or TrackElement which is
+ to be the main target of interactive editing, such as the object
+ directly under the mouse pointer.
+ timeline (GES.Timeline): The timeline to edit.
+ edge (GES.Edge): The edge on which the editing will happen, this
+ parameter can be changed while still using the same context.
+ mode (GES.EditMode): The mode in which the editing will happen, this
+ parameter can be changed while still using the same context.
+ app (Pitivi): The app.
"""
def __init__(self, focus, timeline, mode, edge, app, log_actions):
- """
- @param focus: the Clip or TrackElement which is to be the
- main target of interactive editing, such as the object directly under the
- mouse pointer
- @type focus: L{GES.Clip} or L{GES.TrackElement}
-
- @param timeline: the timeline to edit
- @type timeline: instance of L{GES.Timeline}
-
- @param edge: The edge on which the edition will happen, this parametter
- can be change during the time using the same context.
- @type edge: L{GES.Edge}
-
- @param mode: The mode in which the edition will happen, this parametter
- can be change during the time using the same context.
- @type mode: L{GES.EditMode}
-
- @param app: The Pitivi instance, for reporting actions.
- @type app: L{Pitivi}
-
- @returns: An instance of L{pitivi.utils.timeline.EditingContext}
- """
GObject.Object.__init__(self)
Loggable.__init__(self)
if isinstance(focus, GES.TrackElement):
@@ -274,8 +251,10 @@ class EditingContext(GObject.Object, Loggable):
self.timeline.ui.app.gui.viewer.clipTrimPreviewFinished()
def setMode(self, mode):
- """Set the current editing mode.
- @param mode: the editing mode. Must be a GES.EditMode
+ """Sets the current editing mode.
+
+ Args:
+ mode (GES.EditMode): The editing mode.
"""
self.mode = mode
@@ -309,10 +288,7 @@ class EditingContext(GObject.Object, Loggable):
class Zoomable(object):
-
- """
- Interface for managing tranformation between timeline timestamps and UI
- pixels.
+ """Base class for conversions between timeline timestamps and UI pixels.
Complex Timeline interfaces v2 (01 Jul 2008)
@@ -405,24 +381,17 @@ class Zoomable(object):
@classmethod
def pixelToNs(cls, pixel):
- """
- Returns the pixel equivalent in nanoseconds according to the zoomratio
- """
+ """Returns the duration equivalent of the specified pixel."""
return int(pixel * Gst.SECOND / cls.zoomratio)
@classmethod
def pixelToNsAt(cls, pixel, ratio):
- """
- Returns the pixel equivalent in nanoseconds according to the zoomratio
- """
+ """Returns the duration equivalent of the specified pixel."""
return int(pixel * Gst.SECOND / ratio)
@classmethod
def nsToPixel(cls, duration):
- """
- Returns the pixel equivalent of the given duration, according to the
- set zoom ratio
- """
+ """Returns the pixel equivalent of the specified duration"""
# Here, a long time ago (206f3a05), a pissed programmer said:
# DIE YOU CUNTMUNCH CLOCK_TIME_NONE UBER STUPIDITY OF CRACK BINDINGS !!
if duration == Gst.CLOCK_TIME_NONE:
@@ -431,10 +400,7 @@ class Zoomable(object):
@classmethod
def nsToPixelAccurate(cls, duration):
- """
- Returns the pixel equivalent of the given duration, according to the
- set zoom ratio
- """
+ """Returns the pixel equivalent of the specified duration."""
# Here, a long time ago (206f3a05), a pissed programmer said:
# DIE YOU CUNTMUNCH CLOCK_TIME_NONE UBER STUPIDITY OF CRACK BINDINGS !!
if duration == Gst.CLOCK_TIME_NONE:
diff --git a/pitivi/utils/ui.py b/pitivi/utils/ui.py
index 41cd6e9..22e220d 100644
--- a/pitivi/utils/ui.py
+++ b/pitivi/utils/ui.py
@@ -17,9 +17,7 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-UI constants and various functions and classes that help with UI drawing.
-"""
+"""UI constants and various functions and classes that help with UI drawing."""
import decimal
import os
import urllib.error
@@ -207,7 +205,8 @@ def pack_color_64(red, green, blue, alpha=0xFFFF):
def unpack_color(value):
"""Unpacks the specified RGBA value into four 16bit color values.
- @param value: A 32bit or 64bit RGBA value.
+ Args:
+ value (int): A 32bit or 64bit RGBA value.
"""
if not (value >> 32):
return unpack_color_32(value)
@@ -250,10 +249,10 @@ def set_cairo_color(context, color):
def beautify_asset(asset):
- """
- Formats the specified info for display.
+ """Formats the specified asset for display.
- @type info: L{DiscovererInfo}
+ Args:
+ asset (GES.Asset): The asset to display.
"""
ranks = {
DiscovererVideoInfo: 0,
@@ -290,10 +289,10 @@ def beautify_asset(asset):
def info_name(info):
- """
- Return a human-readable filename (without the path and quoting).
+ """Returns a human-readable filename (without the path and quoting).
- @type info: L{GES.Asset} or L{DiscovererInfo}
+ Args:
+ info (GES.Asset or DiscovererInfo): The info to display.
"""
if isinstance(info, GES.Asset):
filename = urllib.parse.unquote(os.path.basename(get_proxy_target(info).get_id()))
@@ -346,10 +345,12 @@ def beautify_stream(stream):
def time_to_string(value):
- """
- Converts the given time in nanoseconds to a human readable string
+ """Converts the specified time to a human readable string.
Format HH:MM:SS.XXX
+
+ Args:
+ value (int): The time in nanoseconds.
"""
if value == Gst.CLOCK_TIME_NONE:
return "--:--:--.---"
@@ -364,8 +365,10 @@ def time_to_string(value):
def beautify_length(length):
- """
- Converts the given time in nanoseconds to a human readable string
+ """Converts the specified duration to a human readable string.
+
+ Args:
+ length (int): The duration in nanoseconds.
"""
sec = length / Gst.SECOND
mins = int(sec / 60)
@@ -387,8 +390,7 @@ def beautify_length(length):
def beautify_time_delta(seconds):
- """
- Converts the given time in seconds to a human-readable estimate.
+ """Converts the specified time to a human-readable estimate.
This is intended for "Unsaved changes" and "Backup file found" dialogs.
"""
@@ -414,12 +416,12 @@ def beautify_time_delta(seconds):
return ", ".join(parts)
-def beautify_ETA(length):
- """
- Converts the given time in nanoseconds to a fuzzy estimate,
- intended for progress ETAs, not to indicate a clip's duration.
+def beautify_ETA(length_nanos):
+ """Converts the specified duration to a fuzzy estimate.
+
+ Intended for progress ETAs, not to indicate a clip's duration.
"""
- sec = length / Gst.SECOND
+ sec = length_nanos / Gst.SECOND
mins = sec / 60
sec = int(sec % 60)
hours = int(mins / 60)
@@ -440,10 +442,10 @@ def beautify_ETA(length):
# -------------------- Gtk widget helpers ----------------------------------- #
def clear_styles(widget):
- """
- Make sure the widget has no border, background or other decorations.
+ """Makes sure the widget has no border, background or other decorations.
- @type widget: L{Gtk.Widget}
+ Args:
+ widget (Gtk.Widget): The widget to clean up.
"""
style = widget.get_style_context()
for css_class in style.list_classes():
@@ -472,10 +474,12 @@ def get_combo_value(combo):
def get_value_from_model(model, key):
- """
- For a given key, search a gtk ListStore and return the value as a string.
+ """Searches a key in a model's second column.
- If not found and the key is a gst fraction, return a beautified form.
+ Returns:
+ str: The first column element on the matching row. If no row matches,
+ and the key is a `Gst.Fraction`, returns a beautified form.
+ Otherwise returns the key.
"""
for row in model:
if row[1] == key:
@@ -511,9 +515,7 @@ def unset_children_state_recurse(widget, state):
def disable_scroll(widget):
- """
- Make sure the specified widget does not react to scroll events.
- """
+ """Makes sure the specified widget does not react to scroll events."""
def scroll_event_cb(widget, unused_event):
GObject.signal_stop_emission_by_name(widget, "scroll-event")
return False
diff --git a/pitivi/utils/widgets.py b/pitivi/utils/widgets.py
index ef3514e..5c9b395 100644
--- a/pitivi/utils/widgets.py
+++ b/pitivi/utils/widgets.py
@@ -16,11 +16,7 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-A collection of helper classes and routines for:
- * dynamically creating user interfaces
- * Creating UI from GstElement-s
-"""
+"""Classes and routines for creating widgets from `Gst.Element`s."""
import math
import os
import re
@@ -52,9 +48,7 @@ ZOOM_SLIDER_PADDING = SPACING * 4 / 5
class DynamicWidget(object):
-
- """An interface which provides a uniform way to get, set, and observe
- widget properties"""
+ """Abstract widget providing a way to get, set and observe properties."""
def __init__(self, default):
self.default = default
@@ -77,7 +71,6 @@ class DynamicWidget(object):
class DefaultWidget(Gtk.Label):
-
"""When all hope fails...."""
def __init__(self, *unused, **unused_kwargs):
@@ -98,8 +91,8 @@ class DefaultWidget(Gtk.Label):
class TextWidget(Gtk.Box, DynamicWidget):
+ """Widget for entering text.
- """
A Gtk.Entry which emits a "value-changed" signal only when its input is
valid (matches the provided regex). If the input is invalid, a warning
icon is displayed.
@@ -115,9 +108,6 @@ class TextWidget(Gtk.Box, DynamicWidget):
"activate": (GObject.SignalFlags.RUN_LAST, None, (),)
}
- __INVALID__ = Gdk.Color(0xFFFF, 0, 0)
- __NORMAL__ = Gdk.Color(0, 0, 0)
-
def __init__(self, matches=None, choices=None, default=None):
if not default:
# In the case of text widgets, a blank default is an empty string
@@ -145,14 +135,14 @@ class TextWidget(Gtk.Box, DynamicWidget):
self.last_valid = None
self.valid = False
self.send_signal = True
- self.text.connect("changed", self._textChanged)
- self.text.connect("activate", self._activateCb)
+ self.text.connect("changed", self.__text_changed_cb)
+ self.text.connect("activate", self.__activate_cb)
if matches:
if type(matches) is str:
self.matches = re.compile(matches)
else:
self.matches = matches
- self._textChanged(None)
+ self.__text_changed_cb(None)
def connectValueChanged(self, callback, *args):
return self.connect("value-changed", callback, *args)
@@ -170,7 +160,7 @@ class TextWidget(Gtk.Box, DynamicWidget):
for choice in choices:
self.combo.append_text(choice)
- def _textChanged(self, unused_widget):
+ def __text_changed_cb(self, unused_widget):
text = self.text.get_text()
if self.matches:
if self._filter(text):
@@ -189,14 +179,7 @@ class TextWidget(Gtk.Box, DynamicWidget):
self.send_signal = True
- def _activateCb(self, unused_widget):
- """
- Similar to _textChanged, to account for the case where we connect to
- the "activate" signal instead of "text-changed".
-
- We don't need to set the icons or anything like that, as _textChanged
- does it already.
- """
+ def __activate_cb(self, unused_widget):
if self.matches and self.send_signal:
self.emit("activate")
@@ -212,10 +195,16 @@ class TextWidget(Gtk.Box, DynamicWidget):
class NumericWidget(Gtk.Box, DynamicWidget):
+ """Widget for entering a number.
- """An horizontal Gtk.Scale and a Gtk.SpinButton which share an adjustment.
+ Contains both a Gtk.Scale and a Gtk.SpinButton for adjusting the value.
The SpinButton is always displayed, while the Scale only appears if both
- lower and upper bounds are defined"""
+ lower and upper bounds are defined.
+
+ Args:
+ upper (Optional[int]): The upper limit for this widget.
+ lower (Optional[int]): The lower limit for this widget.
+ """
def __init__(self, upper=None, lower=None, default=None):
Gtk.Box.__init__(self)
@@ -290,11 +279,11 @@ class NumericWidget(Gtk.Box, DynamicWidget):
class TimeWidget(TextWidget, DynamicWidget):
+ """Widget for entering a time value.
+ Accepts timecode formats or a frame number (integer).
"""
- A widget that contains a time in nanoseconds. Accepts timecode formats
- or a frame number (integer).
- """
+
# The "frame number" match rule is ^([0-9]+)$ (with a + to require 1 digit)
# The "timecode" rule is ^([0-9]:[0-5][0-9]:[0-5][0-9])\.[0-9][0-9][0-9]$"
# Combining the two, we get:
@@ -351,8 +340,7 @@ class TimeWidget(TextWidget, DynamicWidget):
class FractionWidget(TextWidget, DynamicWidget):
-
- """A Gtk.ComboBoxEntry """
+ """Widget for entering a fraction."""
fraction_regex = re.compile(
"^([0-9]*(\.[0-9]+)?)(([:/][0-9]*(\.[0-9]+)?)|M)?$")
@@ -437,8 +425,7 @@ class FractionWidget(TextWidget, DynamicWidget):
class ToggleWidget(Gtk.CheckButton, DynamicWidget):
-
- """A Gtk.CheckButton which supports the DynamicWidget interface."""
+ """Widget for entering an on/off value."""
def __init__(self, default=None):
Gtk.CheckButton.__init__(self)
@@ -455,10 +442,7 @@ class ToggleWidget(Gtk.CheckButton, DynamicWidget):
class ChoiceWidget(Gtk.Box, DynamicWidget):
-
- """Abstractly, represents a choice between a list of named values. The
- association between value names and values is arbitrary. The current
- implementation uses a Gtk.ComboBoxText for simplicity."""
+ """Widget for making a choice between a list of named values."""
def __init__(self, choices, default=None):
Gtk.Box.__init__(self)
@@ -500,15 +484,12 @@ class ChoiceWidget(Gtk.Box, DynamicWidget):
class PathWidget(Gtk.FileChooserButton, DynamicWidget):
-
- """A Gtk.FileChooserButton which supports the DynamicWidget interface."""
+ """Widget for entering a path."""
__gtype_name__ = 'PathWidget'
__gsignals__ = {
- "value-changed": (GObject.SignalFlags.RUN_LAST,
- None,
- ()),
+ "value-changed": (GObject.SignalFlags.RUN_LAST, None, ()),
}
def __init__(self, action=Gtk.FileChooserAction.OPEN, default=None):
@@ -615,7 +596,7 @@ class GstElementSettingsWidget(Gtk.Box, Loggable):
self.set_orientation(Gtk.Orientation.VERTICAL)
def deactivate_keyframe_toggle_buttons(self):
- """Make sure the keyframe togglebuttons are deactivated."""
+ """Makes sure the keyframe togglebuttons are deactivated."""
self.log("Deactivating all keyframe toggle buttons")
for keyframe_button in self.__widgets_by_keyframe_button.keys():
if keyframe_button.get_active():
@@ -627,7 +608,7 @@ class GstElementSettingsWidget(Gtk.Box, Loggable):
def setElement(self, element, values={}, ignore=['name'],
with_reset_button=False):
- """Set the element to be edited.
+ """Sets the element to be edited.
Args:
values (dict): The current values of the element props, by name.
@@ -641,8 +622,7 @@ class GstElementSettingsWidget(Gtk.Box, Loggable):
self.__add_widgets(values, with_reset_button)
def __add_widgets(self, values, with_reset_button):
- """
- Prepare a Gtk.Grid containing the property widgets of an element.
+ """Prepares a Gtk.Grid containing the property widgets of an element.
Each property is on a separate row.
A row is typically a label followed by the widget and a reset button.
@@ -765,18 +745,21 @@ class GstElementSettingsWidget(Gtk.Box, Loggable):
keyframe_button)
return button
- def __set_keyframe_active(self, button, active):
- """
- This is meant for programmatically (un)pushing the provided keyframe
- togglebutton, without triggering its signals.
+ def __set_keyframe_active(self, toggle_button, active):
+ """Updates the specified button without triggering signals.
+
+ Args:
+ toggle_button (Gtk.ToggleButton): The toggle button enabling controlling
+ the property by keyframes.
+ active (bool): The desired status of the `toggle_button`.
"""
- self.log("Manually resetting the UI state of %s" % button)
- button.handler_block_by_func(self.__keyframes_toggled_cb)
- button.set_active(active)
- button.handler_unblock_by_func(self.__keyframes_toggled_cb)
+ self.log("Manually resetting the UI state of %s", toggle_button)
+ toggle_button.handler_block_by_func(self.__keyframes_toggled_cb)
+ toggle_button.set_active(active)
+ toggle_button.handler_unblock_by_func(self.__keyframes_toggled_cb)
def __display_controlled(self, toggle_button, controlled):
- """Display whether the prop is keyframed."""
+ """Displays whether the prop is keyframed."""
widget = self.__widgets_by_keyframe_button[toggle_button]
# The displayed value means nothing if the prop is controlled.
widget.set_sensitive(not controlled)
@@ -836,7 +819,7 @@ class GstElementSettingsWidget(Gtk.Box, Loggable):
return None
def getSettings(self, with_default=False):
- """Get a name/value dict with the properties."""
+ """Gets a name/value dict with the properties."""
values = {}
for prop, widget in self.properties.items():
if not prop.flags & GObject.PARAM_WRITABLE:
@@ -847,7 +830,7 @@ class GstElementSettingsWidget(Gtk.Box, Loggable):
return values
def _makePropertyWidget(self, prop, value=None):
- """ Creates a Widget for the specified element property """
+ """Creates a widget for the specified element property."""
type_name = GObject.type_name(prop.value_type.fundamental)
if type_name == "gchararray":
widget = TextWidget(default=prop.default_value)
@@ -883,8 +866,7 @@ class GstElementSettingsWidget(Gtk.Box, Loggable):
class GstElementSettingsDialog(Loggable):
- """Dialog window for viewing/modifying properties of a Gst.Element.
- """
+ """Dialog window for viewing/modifying properties of a Gst.Element."""
def __init__(self, elementfactory, properties, parent_window=None):
Loggable.__init__(self)
@@ -934,7 +916,10 @@ class GstElementSettingsDialog(Loggable):
self.window.show()
def getSettings(self):
- """ returns the property/value dictionnary of the selected settings """
+ """Gets the settings of the `element`.
+
+ Returns:
+ dict: A property name to value map."""
return self.elementsettings.getSettings()
def _resetValuesClickedCb(self, unused_button):
@@ -948,7 +933,6 @@ class GstElementSettingsDialog(Loggable):
class BaseTabs(Gtk.Notebook):
def __init__(self, app, hide_hpaned=False):
- """ initialize """
Gtk.Notebook.__init__(self)
self.set_border_width(SPACING)
@@ -958,7 +942,7 @@ class BaseTabs(Gtk.Notebook):
self._createUi()
def _createUi(self):
- """ set up the gui """
+ """Sets up the GUI."""
settings = self.get_settings()
settings.props.gtk_dnd_drag_threshold = 1
self.set_tab_pos(Gtk.PositionType.TOP)
@@ -1029,11 +1013,10 @@ class BaseTabs(Gtk.Notebook):
class ZoomBox(Gtk.Grid, Zoomable):
+ """Container holding the widgets for zooming.
- """
- Container holding the widgets for zooming.
-
- @type timeline: TimelineContainer
+ Attributes:
+ timeline (TimelineContainer): The timeline container this belongs to.
"""
def __init__(self, timeline):
diff --git a/pitivi/viewer/move_scale_overlay.py b/pitivi/viewer/move_scale_overlay.py
index 59d332b..99aee2c 100644
--- a/pitivi/viewer/move_scale_overlay.py
+++ b/pitivi/viewer/move_scale_overlay.py
@@ -21,7 +21,6 @@ from math import pi
import cairo
import numpy
-from gi.repository import Gdk
from pitivi.undo.timeline import CommitTimelineFinalizingAction
from pitivi.utils.misc import disconnectAllByFunc
@@ -108,8 +107,8 @@ class Handle:
return self.__window_position.tolist()
def get_source_position(self):
- """
- Returns a source translation when handles at TOP or LEFT are dragged.
+ """Returns a source translation when handles at TOP or LEFT are dragged.
+
The user is not translating here, but scaling.
This is needed to move the pivot point of the scale operation
from the TOP LEFT corner to the CENTER.
@@ -299,9 +298,8 @@ class EdgeHandle(Handle):
class MoveScaleOverlay(Overlay):
- """
- Viewer overlays class for GESVideoSource transformations
- """
+ """Viewer overlays for GES.VideoSource transformations."""
+
def __init__(self, stack, action_log, source):
Overlay.__init__(self, stack, source)
diff --git a/pitivi/viewer/overlay.py b/pitivi/viewer/overlay.py
index f6c04c8..6e316c1 100644
--- a/pitivi/viewer/overlay.py
+++ b/pitivi/viewer/overlay.py
@@ -16,9 +16,7 @@
# License along with this program; if not, write to the
# Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
# Boston, MA 02110-1301, USA.
-"""
-Base class for the video viewer overlays
-"""
+"""Video viewer overlays."""
import numpy
from gi.repository import GES
from gi.repository import Gtk
@@ -28,9 +26,8 @@ from pitivi.utils.timeline import SELECT
class Overlay(Gtk.DrawingArea, Loggable):
- """
- Abstract class for viewer overlays.
- """
+ """Abstract class for viewer overlays."""
+
def __init__(self, stack, source):
Gtk.DrawingArea.__init__(self)
Loggable.__init__(self)
@@ -73,9 +70,7 @@ class Overlay(Gtk.DrawingArea, Loggable):
self.stack.hovered_overlay = self
def unhover(self):
- """
- Mark @self as not over anymore
- """
+ """Marks `self` as not over anymore."""
self.stack.hovered_overlay = None
self.queue_draw()
diff --git a/pitivi/viewer/title_overlay.py b/pitivi/viewer/title_overlay.py
index ffbbbce..b3516f1 100644
--- a/pitivi/viewer/title_overlay.py
+++ b/pitivi/viewer/title_overlay.py
@@ -23,9 +23,8 @@ from pitivi.viewer.overlay import Overlay
class TitleOverlay(Overlay):
- """
- Viewer overlays class for GESTitleSource
- """
+ """Viewer overlays for GES.TitleSource."""
+
def __init__(self, stack, source):
Overlay.__init__(self, stack, source)
self.__corners = []
diff --git a/pitivi/viewer/viewer.py b/pitivi/viewer/viewer.py
index 0892f24..3edcfff 100644
--- a/pitivi/viewer/viewer.py
+++ b/pitivi/viewer/viewer.py
@@ -61,10 +61,10 @@ GlobalSettings.addConfigOption("pointColor", section="viewer",
class ViewerContainer(Gtk.Box, Loggable):
- """
- A wiget holding a viewer and the controls.
+ """Wiget holding a viewer and the controls.
- @type pipeline: L{pitivi.utils.pipeline.SimplePipeline}
+ Attributes:
+ pipeline (SimplePipeline): The displayed pipeline.
"""
__gtype_name__ = 'ViewerContainer'
@@ -103,14 +103,13 @@ class ViewerContainer(Gtk.Box, Loggable):
self.undock()
def setPipeline(self, pipeline, position=None):
- """
- Set the Viewer to the given Pipeline.
+ """Sets the displayed pipeline.
Properly switches the currently set action to that new Pipeline.
- @param pipeline: The Pipeline to switch to.
- @type pipeline: L{Pipeline}.
- @param position: Optional position to seek to initially.
+ Args:
+ pipeline (Pipeline): The Pipeline to switch to.
+ position (Optional[int]): The position to seek to initially.
"""
self._disconnectFromPipeline()
@@ -196,7 +195,7 @@ class ViewerContainer(Gtk.Box, Loggable):
self.settings.viewerY = event.y
def _createUi(self):
- """ Creates the Viewer GUI """
+ """Creates the Viewer GUI."""
self.set_orientation(Gtk.Orientation.VERTICAL)
self.external_window = Gtk.Window()
@@ -409,8 +408,7 @@ class ViewerContainer(Gtk.Box, Loggable):
self.external_window.show()
def _positionCb(self, unused_pipeline, position):
- """
- If the timeline position changed, update the viewer UI widgets.
+ """Updates the viewer UI widgets if the timeline position changed.
This is meant to be called either by the gobject timer when playing,
or by mainwindow's _timelineSeekCb when the timer is disabled.
@@ -418,9 +416,7 @@ class ViewerContainer(Gtk.Box, Loggable):
self.timecode_entry.setWidgetValue(position, False)
def clipTrimPreview(self, clip, position):
- """
- While a clip is being trimmed, show a live preview of it.
- """
+ """Shows a live preview of a clip being trimmed."""
if not hasattr(clip, "get_uri") or isinstance(clip, GES.TitleClip) or clip.props.is_image:
self.log(
"%s is an image or has no URI, so not previewing trim" % clip)
@@ -443,9 +439,7 @@ class ViewerContainer(Gtk.Box, Loggable):
self._lastClipTrimTime = cur_time
def clipTrimPreviewFinished(self):
- """
- After trimming a clip, reset the project pipeline into the viewer.
- """
+ """Switches back to the project pipeline following a clip trimming."""
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
@@ -456,12 +450,7 @@ class ViewerContainer(Gtk.Box, Loggable):
self.debug("Back to the project's pipeline")
def _pipelineStateChangedCb(self, unused_pipeline, state, old_state):
- """
- When playback starts/stops, update the viewer widget,
- play/pause button and (un)inhibit the screensaver.
-
- This is meant to be called by mainwindow.
- """
+ """Updates the widgets when the playback starts or stops."""
if int(state) == int(Gst.State.PLAYING):
st = Gst.Structure.new_empty("play")
self.app.write_action(st)
@@ -482,8 +471,7 @@ class ViewerContainer(Gtk.Box, Loggable):
class ViewerWidget(Gtk.AspectFrame, Loggable):
- """
- Widget for displaying a video sink.
+ """Widget for displaying a video sink.
Args:
sink_widget (Gtk.Widget): The widget doing the real work.
@@ -518,9 +506,8 @@ class ViewerWidget(Gtk.AspectFrame, Loggable):
class PlayPauseButton(Gtk.Button, Loggable):
- """
- Double state Gtk.Button which displays play/pause
- """
+ """Double state Gtk.Button which displays play/pause."""
+
__gsignals__ = {
"play": (GObject.SignalFlags.RUN_LAST, None, (GObject.TYPE_BOOLEAN,))
}
diff --git a/tests/test_log.py b/tests/test_log.py
index c455131..31a7714 100644
--- a/tests/test_log.py
+++ b/tests/test_log.py
@@ -209,49 +209,6 @@ class TestLogSettings(unittest.TestCase):
self.assertEqual(old, log.getLogSettings())
-class TestWriteMark(TestWithHandler):
-
- def testWriteMarkInDebug(self):
- loggable = log.Loggable()
- log.setDebug("%d" % log.DEBUG)
- log.addLogHandler(self.handler)
- marker = 'test'
- loggable.writeMarker(marker, log.DEBUG)
- self.assertEqual(self.message, marker)
-
- def testWriteMarkInWarn(self):
- loggable = log.Loggable()
- log.setDebug("%d" % log.WARN)
- log.addLogHandler(self.handler)
- marker = 'test'
- loggable.writeMarker(marker, log.WARN)
- self.assertEqual(self.message, marker)
-
- def testWriteMarkInInfo(self):
- loggable = log.Loggable()
- log.setDebug("%d" % log.INFO)
- log.addLogHandler(self.handler)
- marker = 'test'
- loggable.writeMarker(marker, log.INFO)
- self.assertEqual(self.message, marker)
-
- def testWriteMarkInLog(self):
- loggable = log.Loggable()
- log.setDebug("%d" % log.LOG)
- log.addLogHandler(self.handler)
- marker = 'test'
- loggable.writeMarker(marker, log.LOG)
- self.assertEqual(self.message, marker)
-
- def testWriteMarkInError(self):
- loggable = log.Loggable()
- log.setDebug("%d" % log.ERROR)
- log.addLogHandler(self.handler)
- marker = 'test'
- loggable.writeMarker(marker, log.ERROR)
- self.assertEqual(self.message, marker)
-
-
class TestLogNames(unittest.TestCase):
def testGetLevelNames(self):
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]