7
7
import pitivi.configure as configure
8
8
from urllib import unquote
9
from gettext import gettext as _
9
10
from pitivi.receiver import receiver, handler
10
11
from view import View
12
13
from zoominterface import Zoomable
13
14
from pitivi.timeline.track import TrackError
14
from pitivi.timeline.timeline import SELECT, SELECT_ADD, UNSELECT
15
from pitivi.timeline.timeline import SELECT, SELECT_ADD, UNSELECT, \
16
MoveContext, TrimStartContext, TrimEndContext
15
17
from preview import Preview
18
from pitivi.ui.curve import Curve
17
20
from common import LAYER_HEIGHT_EXPANDED, LAYER_HEIGHT_COLLAPSED
18
21
from common import LAYER_SPACING, unpack_cairo_pattern, unpack_cairo_gradient
40
47
PreferencesDialog.addColorPreference('videoClipBg',
41
section = "Appearance",
42
label = "Clip Background (Video)",
43
description = "The background color for clips in video tracks.")
48
section = _("Appearance"),
49
label = _("Clip Background (Video)"),
50
description = _("The background color for clips in video tracks."))
45
52
GlobalSettings.addConfigOption('audioClipBg',
46
53
section = 'user-interface',
51
58
PreferencesDialog.addColorPreference('audioClipBg',
52
section = "Appearance",
53
label = "Clip Background (Audio)",
54
description = "The background color for clips in audio tracks.")
59
section = _("Appearance"),
60
label = _("Clip Background (Audio)"),
61
description = _("The background color for clips in audio tracks."))
56
63
GlobalSettings.addConfigOption('selectedColor',
57
64
section = 'user-interface',
62
69
PreferencesDialog.addColorPreference('selectedColor',
63
section = "Appearance",
64
label = "Selection Color",
65
description = "Selected clips will be tinted with this color.")
70
section = _("Appearance"),
71
label = _("Selection Color"),
72
description = _("Selected clips will be tinted with this color."))
67
74
GlobalSettings.addConfigOption('clipFontDesc',
68
75
section = 'user-interface',
73
80
PreferencesDialog.addFontPreference('clipFontDesc',
74
section = 'Appearance',
75
description = "The font to use for clip titles",
81
section = _('Appearance'),
82
label = _("Clip Font"),
83
description = _("The font to use for clip titles"))
78
85
GlobalSettings.addConfigOption('clipFontColor',
79
86
section = 'user-interface',
96
104
def leave(self, unused, unused2):
97
105
self._view.unfocus()
103
self._view.timeline.rebuildEdges()
107
def drag_start(self, item, target, event):
108
if not self._view.element.selected:
109
self._view.timeline.selection.setToObj(self._view.element, SELECT)
110
tx = self._view.props.parent.get_transform()
111
# store y offset for later priority calculation
112
self._y_offset = tx[5]
113
# zero y component of mousdown coordiante
114
self._mousedown = Point(self._mousedown[0], 0)
116
def drag_end(self, item, target, event):
117
self._context.finish()
119
self._view.app.action_log.commit()
121
def set_pos(self, item, pos):
123
position = Zoomable.pixelToNs(x)
124
priority = int((y - self._y_offset) // (LAYER_HEIGHT_EXPANDED + LAYER_SPACING))
125
self._context.setMode(self._getMode())
126
self._context.editTo(position, priority)
130
return self._context.RIPPLE
131
elif self._control_down:
132
return self._context.ROLL
133
return self._context.DEFAULT
135
def key_press(self, keyval):
137
self._context.setMode(self._getMode())
139
def key_release(self, keyval):
141
self._context.setMode(self._getMode())
105
143
class TrimHandle(View, goocanvas.Image, Zoomable):
110
148
element = receiver()
112
def __init__(self, element, timeline, **kwargs):
150
def __init__(self, instance, element, timeline, **kwargs):
113
152
self.element = element
114
153
self.timeline = timeline
115
154
goocanvas.Image.__init__(self,
135
174
_cursor = LEFT_SIDE
137
def set_pos(self, obj, pos):
138
new_start = max(self._view.pixelToNs(pos[0]), 0)
139
self._view.element.trimStart(new_start, snap=True)
176
def drag_start(self, item, target, event):
177
TimelineController.drag_start(self, item, target, event)
178
self._context = TrimStartContext(self._view.timeline,
180
self._view.timeline.selection.getSelectedTrackObjs())
181
self._view.app.action_log.begin("trim object")
141
183
class EndHandle(TrimHandle):
147
189
_cursor = RIGHT_SIDE
149
def set_pos(self, obj, pos):
150
start = self._view.element.start
151
abs_pos = self._view.pixelToNs(pos[0])
152
duration = max(abs_pos - start, 0)
153
self._view.element.setDuration(duration, snap=True)
191
def drag_start(self, item, target, event):
192
TimelineController.drag_start(self, item, target, event)
193
self._context = TrimEndContext(self._view.timeline,
195
self._view.timeline.selection.getSelectedTrackObjs())
196
self._view.app.action_log.begin("trim object")
155
198
class TrackObject(View, goocanvas.Group, Zoomable):
158
201
class Controller(TimelineController):
160
def drag_start(self):
161
TimelineController.drag_start(self)
162
self._view.timeline.disableUpdates()
203
def drag_start(self, item, target, event):
204
TimelineController.drag_start(self, item, target, event)
163
205
self._view.raise_(None)
164
tx = self._view.props.parent.get_transform()
165
self._y_offset = tx[5]
166
self._mousedown = Point(self._mousedown[0], 0)
167
element = self._view.element
168
timeline = self._view.timeline
172
# calculate offsets to selected clips
174
for obj in timeline.selection.getSelectedTrackObjs():
175
start = obj.start - element.start
177
self._min_start = max(self._min_start, -start)
178
priority = obj.priority - element.priority
180
self._min_pri = max(self._min_pri, -priority)
181
self._offsets[obj] = start, priority
182
del self._offsets[element]
206
self._context = MoveContext(self._view.timeline,
208
self._view.timeline.selection.getSelectedTrackObjs())
209
self._view.app.action_log.begin("move object")
185
TimelineController.drag_end(self)
186
self._view.timeline.enableUpdates()
213
return self._context.RIPPLE
214
return self._context.DEFAULT
188
216
def click(self, pos):
194
222
self._view.timeline.setSelectionToObj(
195
223
self._view.element, mode)
197
def set_pos(self, item, pos):
199
self._view.element.setStart(max(self._view.pixelToNs(x),
200
self._min_start), snap=True)
201
start = self._view.element.start
202
priority = int(max(self._min_pri, (y - self._y_offset) //
203
(LAYER_HEIGHT_EXPANDED + LAYER_SPACING)))
204
self._view.element.setObjectPriority(priority)
205
for obj, (s, p) in self._offsets.iteritems():
206
obj.setStart(start + s)
207
obj.setPriority(priority + p)
209
225
def __init__(self, instance, element, track, timeline):
210
226
goocanvas.Group.__init__(self)
211
227
View.__init__(self)
222
239
self.content = Preview(element)
224
241
self.name = goocanvas.Text(
242
x= NAME_HOFFSET + NAME_PADDING,
243
y= NAME_VOFFSET + NAME_PADDING,
228
244
operator = cairo.OPERATOR_ADD,
229
245
alignment=pango.ALIGN_LEFT)
230
246
self.namebg = goocanvas.Rect(
237
self.start_handle = StartHandle(element, timeline,
253
self.start_handle = StartHandle(self.app, element, timeline,
238
254
height=self.height)
239
self.end_handle = EndHandle(element, timeline,
255
self.end_handle = EndHandle(self.app, element, timeline,
240
256
height=self.height)
242
258
self.selection_indicator = goocanvas.Rect(
248
264
self.start_handle, self.end_handle, self.namebg, self.name):
249
265
self.add_child(thing)
267
for prop, interpolator in element.getInterpolators().itervalues():
268
self.add_child(Curve(instance, element, interpolator, 50))
251
270
self.element = element
252
271
self.settings = instance.settings
340
363
self.element.factory.name))
341
364
twidth, theight = text_size(self.name)
342
365
self.namewidth = twidth
343
self.namebg.props.width = twidth + 6.0
344
self.namebg.props.height = theight + 4.0
366
self.nameheight = theight
347
369
element = receiver(_setElement)
366
388
def _update(self):
367
x = self.nsToPixel(self.element.start)
390
x = self.nsToPixel(self.element.start)
392
print self.element.start
368
394
y = (self.height + LAYER_SPACING) * self.element.priority
369
395
self.set_simple_transform(x, y, 1, 0)
370
396
width = self.nsToPixel(self.element.duration)
375
401
self.selection_indicator.props.width = width
376
402
self.end_handle.props.x = w
377
403
if self.expanded:
379
self.namebg.props.width = min(w - 8, self.namewidth)
404
if w - NAME_HOFFSET > 0:
405
self.namebg.props.height = self.nameheight + NAME_PADDING2X
406
self.namebg.props.width = min(w - NAME_HOFFSET,
407
self.namewidth + NAME_PADDING2X)
380
408
self.namebg.props.visibility = goocanvas.ITEM_VISIBLE
382
410
self.namebg.props.visibility = goocanvas.ITEM_INVISIBLE