30
from decimal import Decimal
31
35
from gettext import ngettext, gettext as _
37
from gi.repository import Clutter
38
from gi.repository import Cogl
32
39
from gi.repository import GLib
33
40
from gi.repository import GES
41
from gi.repository import Gdk
42
from gi.repository import Gio
34
43
from gi.repository import Gst
35
44
from gi.repository import Gtk
36
45
from gi.repository.GstPbutils import DiscovererVideoInfo, DiscovererAudioInfo,\
37
DiscovererStreamInfo, DiscovererSubtitleInfo
38
from itertools import izip
39
from urllib import unquote
46
DiscovererStreamInfo, DiscovererSubtitleInfo, DiscovererInfo
48
from pitivi.utils.misc import path_from_uri
43
50
from pitivi.utils.loggable import doLog, ERROR
91
101
LAYER_CONTROL_TARGET_ENTRY = Gtk.TargetEntry.new("pitivi/layer-control", 0, TYPE_PITIVI_LAYER_CONTROL)
104
def _get_settings(schema):
105
if schema not in Gio.Settings.list_schemas():
107
return Gio.Settings(schema=schema)
110
def _get_font(font_spec, default):
112
settings = _get_settings("org.gnome.desktop.interface")
114
if font_spec in settings.list_keys():
115
raw_font = settings.get_string(font_spec)
116
face = raw_font.rsplit(" ", 1)[0]
117
return cairo.ToyFontFace(face)
119
NORMAL_FONT = _get_font("font-name", "Cantarell")
120
DOCUMENT_FONT = _get_font("document-font-name", "Sans")
121
MONOSPACE_FONT = _get_font("monospace-font-name", "Monospace")
94
124
# ---------------------- ARGB color helper-------------------------------------#
95
125
def pack_color_32(red, green, blue, alpha=0xFFFF):
96
126
"""Packs the specified 16bit color values in a 32bit RGBA value."""
169
199
return tuple(float(int(value[i:i + 2], 16)) / 255.0 for i in range(0, 6, 2))
172
#------ Helper to help beatify indos so they can be displayed in the UI -----#
202
def create_cogl_color(red, green, blue, alpha):
204
color.init_from_4ub(red, green, blue, alpha)
208
def set_cairo_color(context, color):
209
if type(color) is Clutter.Color:
210
color = (color.red, color.green, color.blue)
212
if type(color) is Gdk.RGBA:
213
cairo_color = (float(color.red), float(color.green), float(color.blue))
214
elif type(color) is tuple:
215
# Cairo's set_source_rgb function expects values from 0.0 to 1.0
216
cairo_color = map(lambda x: max(0, min(1, x / 255.0)), color)
218
raise Exception("Unexpected color parameter: %s, %s" % (type(color), color))
219
context.set_source_rgb(*cairo_color)
173
222
def beautify_info(info):
224
Formats the specified info for display.
226
@type info: L{DiscovererInfo}
175
229
DiscovererVideoInfo: 0,
176
230
DiscovererAudioInfo: 1,
190
244
beautified_string = beautify_stream(stream)
191
245
except NotImplementedError:
192
246
doLog(ERROR, "Beautify", "None", "Cannot beautify %s", stream)
194
if beautified_string is not None:
195
nice_streams_txts.append(beautified_string)
248
if beautified_string:
249
nice_streams_txts.append(beautified_string)
197
return ("<b>" + info_name(info) + "</b>\n" +
198
"\n".join((nice for nice in nice_streams_txts)))
251
return ("<b>" + path_from_uri(info.get_uri()) + "</b>\n" +
252
"\n".join(nice_streams_txts))
201
255
def info_name(info):
202
"""Return a human-readable filename (without the path and quoting)."""
257
Return a human-readable filename (without the path and quoting).
259
@type info: L{GES.Asset} or L{DiscovererInfo}
203
261
if isinstance(info, GES.Asset):
204
filename = unquote(os.path.basename(info.get_id()))
262
filename = urllib.unquote(os.path.basename(info.get_id()))
263
elif isinstance(info, DiscovererInfo):
264
filename = urllib.unquote(os.path.basename(info.get_uri()))
206
filename = unquote(os.path.basename(info.get_uri()))
266
raise Exception("Unsupported argument type: %s" % type(info))
207
267
return GLib.markup_escape_text(filename)
335
395
return ", ".join(parts)
338
#--------------------- UI drawing helper -------------------------------------#
339
# from http://cairographics.org/cookbook/roundedrectangles/
340
def roundedrec(context, x, y, w, h, r=10):
341
"Draw a rounded rectangle"
348
context.move_to(x + r, y) # Move to A
349
context.line_to(x + w - r, y) # Straight line to B
351
# Curve to C, Control points are both at Q
352
context.curve_to(x + w, y, x + w, y, x + w, y + r)
353
context.line_to(x + w, y + h - r) # Move to D
354
context.curve_to(x + w, y + h, x + w, y + h, x + w - r, y + h) # Curve to E
355
context.line_to(x + r, y + h) # Line to F
356
context.curve_to(x, y + h, x, y + h, x, y + h - r) # Curve to G
357
context.line_to(x, y + r) # Line to H
358
context.curve_to(x, y, x, y, x + r, y) # Curve to A
362
398
#--------------------- Gtk widget helpers ------------------------------------#
363
399
def model(columns, data):
364
400
ret = Gtk.ListStore(*columns)
391
427
if row[1] == key:
392
428
return str(row[0])
393
429
if isinstance(key, Gst.Fraction):
394
return "%.3f" % Decimal(float(key.num) / key.denom)
430
return "%.3f" % decimal.Decimal(float(key.num) / key.denom)
434
def alter_style_class(style_class, target_widget, css_style):
435
css_provider = Gtk.CssProvider()
436
toolbar_css = "%s { %s }" % (style_class, css_style)
437
css_provider.load_from_data(toolbar_css.encode('UTF-8'))
438
style_context = target_widget.get_style_context()
439
style_context.add_provider(css_provider, Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION)
397
442
#------------------------ encoding datas ----------------------------------------#
398
443
# FIXME This should into a special file
399
444
frame_rates = model((str, object), (
451
496
(_("Anamorphic (2.39)"), Gst.Fraction(239, 100)),
452
497
(_("Anamorphic (2.4)"), Gst.Fraction(24, 10)),
456
# ---------------------- Classes ---------------------------------------------#
459
def __new__(cls, x, y):
460
return tuple.__new__(cls, (x, y))
462
def __pow__(self, scalar):
463
"""Returns the scalar multiple self, scalar"""
464
return Point(self[0] * scalar, self[1] * scalar)
466
def __rpow__(self, scalar):
467
"""Returns the scalar multiple of self, scalar"""
468
return self ** scalar
470
def __mul__(self, p2):
471
return Point(*(a * b for a, b in izip(self, p2)))
473
def __div__(self, other):
474
return Point(*(a / b for a, b in izip(self, p2)))
476
def __floordiv__(self, scalar):
477
"""Returns the scalar division of self and scalar"""
478
return Point(self[0] / scalar, self[1] / scalar)
480
def __add__(self, p2):
481
"""Returns the 2d vector sum self + p2"""
482
return Point(*(a + b for a, b in izip(self, p2)))
484
def __sub__(self, p2):
485
"""Returns the 2-dvector difference self - p2"""
486
return Point(*(a - b for a, b in izip(self, p2)))
489
return Point(*(abs(a) for a in self))
492
def from_item_bounds(self, item):
493
bounds = item.get_bounds()
494
return Point(bounds.x1, bounds.y1), Point(bounds.x2, bounds.y2)
497
def from_widget_bounds(self, widget):
498
x1, y1, x2, y2 = widget.get_bounds()
499
return Point(x1, y1), Point(x2, y2)