Merge lp:~fincha/openshot/andy-1.2 into lp:openshot/1.4

Proposed by Andy Finch
Status: Merged
Merge reported by: Jonathan Thomas
Merged at revision: not available
Proposed branch: lp:~fincha/openshot/andy-1.2
Merge into: lp:openshot/1.4
Diff against target: 939 lines (+627/-19) (has conflicts)
14 files modified
openshot/classes/clip.py (+76/-1)
openshot/classes/project.py (+21/-0)
openshot/classes/thumbnail.py (+19/-7)
openshot/effects/bass.xml (+23/-0)
openshot/effects/treble.xml (+22/-0)
openshot/windows/AddFiles.py (+53/-5)
openshot/windows/FileProperties.py (+13/-0)
openshot/windows/ImportTransitions.py (+138/-0)
openshot/windows/MainGTK.py (+75/-4)
openshot/windows/TreeTransitions.py (+28/-1)
openshot/windows/preferences.py (+3/-1)
openshot/windows/ui/ImportTransitions.ui (+134/-0)
openshot/windows/ui/Main.ui (+9/-0)
openshot/windows/ui/Main_clip_properties.ui (+13/-0)
Text conflict in openshot/classes/clip.py
Text conflict in openshot/classes/project.py
Text conflict in openshot/windows/FileProperties.py
To merge this branch: bzr merge lp:~fincha/openshot/andy-1.2
Reviewer Review Type Date Requested Status
Jonathan Thomas Pending
Review via email: mp+29753@code.launchpad.net

Description of the change

Includes the following fixes/changes:

#510755 - 'Replace Clip' option on the right click menu - replaces clip, but preserves current properties.
#510708 - Allow user to import new transitions (done via a gui)
#502861 - Dragging a clip on the Timeline shouldn't change the mute/visible properties (Couldn't actually prevent the change when dragging, but now you can't accidentally change them when right clicking or in razor mode).
#517068 - Add Frame snapshot. Keyboard shortcut 'f' extracts the current frame and adds to the project as an image.

Also added Bass & Treble audio effects - might replace these later with a proper equaliser, if I can get the ladspa audio effects working.

To post a comment you must log in.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'openshot/classes/clip.py'
--- openshot/classes/clip.py 2010-07-06 03:23:04 +0000
+++ openshot/classes/clip.py 2010-07-12 22:08:40 +0000
@@ -1308,7 +1308,7 @@
13081308
1309 def on_motion_notify_x (self, item, target, event):1309 def on_motion_notify_x (self, item, target, event):
1310 """this method allows the clip to be dragged and dropped on a track""" 1310 """this method allows the clip to be dragged and dropped on a track"""
13111311
1312 # get the new x,y coordinates from the mouse1312 # get the new x,y coordinates from the mouse
1313 new_x = float(event.x)1313 new_x = float(event.x)
1314 new_y = float(event.y) 1314 new_y = float(event.y)
@@ -1804,6 +1804,7 @@
1804 else:1804 else:
1805 # The clip has moved1805 # The clip has moved
1806 type_of_event = _("Moved clip")1806 type_of_event = _("Moved clip")
1807<<<<<<< TREE
1807 1808
1808 # Animate the clip to it's new position1809 # Animate the clip to it's new position
1809 item.animate(distance_from_clip, drop_track.y_top - item.get_bounds().y1 + 2, 1.0, 0.0, False, 200, 4, goocanvas.ANIMATE_FREEZE)1810 item.animate(distance_from_clip, drop_track.y_top - item.get_bounds().y1 + 2, 1.0, 0.0, False, 200, 4, goocanvas.ANIMATE_FREEZE)
@@ -1818,6 +1819,12 @@
1818 self.parent.parent.project.set_project_modified(is_modified=True, refresh_xml=True, type = type_of_event)1819 self.parent.parent.project.set_project_modified(is_modified=True, refresh_xml=True, type = type_of_event)
18191820
1820 1821
1822=======
1823
1824 self.parent.parent.project.set_project_modified(is_modified=True, refresh_xml=True, type = type_of_event)
1825
1826
1827>>>>>>> MERGE-SOURCE
1821 elif isResize:1828 elif isResize:
1822 1829
1823 # remove clip from goocanvas1830 # remove clip from goocanvas
@@ -1885,6 +1892,7 @@
1885 1892
1886 1893
1887 def on_visible_click (self, item, target, event):1894 def on_visible_click (self, item, target, event):
1895<<<<<<< TREE
1888 1896
1889 # get a reference to the language translate method1897 # get a reference to the language translate method
1890 _ = self.parent.parent.project.translate1898 _ = self.parent.parent.project.translate
@@ -1917,9 +1925,43 @@
1917 self.parent.parent.project.set_project_modified(is_modified=True, refresh_xml=True, type = _("Changed visibility of clip"))1925 self.parent.parent.project.set_project_modified(is_modified=True, refresh_xml=True, type = _("Changed visibility of clip"))
19181926
1919 return False1927 return False
1928=======
1929 #don't do this if in razor mode
1930 (isArrow, isRazor, isSnap, isResize) = self.parent.parent.project.form.get_toolbar_options()
1931 if isArrow:
1932 # get a reference to the 2 main canvas objects & theme
1933 theme = self.parent.parent.project.theme
1934
1935 # get the parent left group
1936 parent_group = item.get_parent()
1937 canvas = parent_group.get_canvas()
1938 canvas.pointer_ungrab (item, event.time)
1939
1940 if self.play_video == True:
1941 # Load Hover Over
1942 imgTrack_Visible = gtk.image_new_from_file("%s/openshot/themes/%s/not_visible_transparent.png" % (self.parent.parent.project.form.openshot_path, theme))
1943 item.set_properties(pixbuf = imgTrack_Visible.get_pixbuf())
1944
1945 # update play video variable
1946 self.play_video = False
1947
1948 else:
1949 # Load normal image
1950 imgTrack_Visible = gtk.image_new_from_file("%s/openshot/themes/%s/visible_transparent.png" % (self.parent.parent.project.form.openshot_path, theme))
1951 item.set_properties(pixbuf = imgTrack_Visible.get_pixbuf())
1952
1953 # update play video variable
1954 self.play_video = True
1955
1956 # mark project as modified
1957 self.parent.parent.project.set_project_modified(is_modified=True, refresh_xml=True, type = _("Changed visibility of clip"))
1958
1959 return False
1960>>>>>>> MERGE-SOURCE
1920 1961
1921 1962
1922 def on_audio_click (self, item, target, event):1963 def on_audio_click (self, item, target, event):
1964<<<<<<< TREE
1923 1965
1924 # get a reference to the language translate method1966 # get a reference to the language translate method
1925 _ = self.parent.parent.project.translate1967 _ = self.parent.parent.project.translate
@@ -1952,6 +1994,39 @@
1952 self.parent.parent.project.set_project_modified(is_modified=True, refresh_xml=True, type = _("Changed audio of clip"))1994 self.parent.parent.project.set_project_modified(is_modified=True, refresh_xml=True, type = _("Changed audio of clip"))
19531995
1954 return False1996 return False
1997=======
1998 #don't do this if in razor mode.
1999 (isArrow, isRazor, isSnap, isResize) = self.parent.parent.project.form.get_toolbar_options()
2000 if isArrow:
2001 # get a reference to the 2 main canvas objects & theme
2002 theme = self.parent.parent.project.theme
2003
2004 # get the parent left group
2005 parent_group = item.get_parent()
2006 canvas = parent_group.get_canvas()
2007 canvas.pointer_ungrab (item, event.time)
2008
2009 if self.play_audio == True:
2010 # Load Hover Over
2011 imgTrack_Visible = gtk.image_new_from_file("%s/openshot/themes/%s/speaker_mute_transparent.png" % (self.parent.parent.project.form.openshot_path, theme))
2012 item.set_properties(pixbuf = imgTrack_Visible.get_pixbuf())
2013
2014 # update play video variable
2015 self.play_audio = False
2016
2017 else:
2018 # Load normal image
2019 imgTrack_Visible = gtk.image_new_from_file("%s/openshot/themes/%s/speaker_transparent.png" % (self.parent.parent.project.form.openshot_path, theme))
2020 item.set_properties(pixbuf = imgTrack_Visible.get_pixbuf())
2021
2022 # update play video variable
2023 self.play_audio = True
2024
2025 # mark project as modified
2026 self.parent.parent.project.set_project_modified(is_modified=True, refresh_xml=True, type = _("Changed audio of clip"))
2027
2028 return False
2029>>>>>>> MERGE-SOURCE
1955 2030
1956 def on_effect_click (self, item, target, event):2031 def on_effect_click (self, item, target, event):
1957 pass2032 pass
19582033
=== modified file 'openshot/classes/project.py'
--- openshot/classes/project.py 2010-07-07 00:04:26 +0000
+++ openshot/classes/project.py 2010-07-12 22:08:40 +0000
@@ -55,6 +55,8 @@
55 self.USER_DIR = os.path.join(os.path.expanduser("~"), ".openshot")55 self.USER_DIR = os.path.join(os.path.expanduser("~"), ".openshot")
56 self.THEMES_DIR = os.path.join(self.BASE_DIR, "openshot", "themes")56 self.THEMES_DIR = os.path.join(self.BASE_DIR, "openshot", "themes")
57 self.USER_PROFILES_DIR = os.path.join(self.USER_DIR, "user_profiles")57 self.USER_PROFILES_DIR = os.path.join(self.USER_DIR, "user_profiles")
58 self.USER_TRANSITIONS_DIR = os.path.join(self.USER_DIR, "user_transitions")
59
5860
59 # only run the following code if we are really using 61 # only run the following code if we are really using
60 # this project file... 62 # this project file...
@@ -123,6 +125,7 @@
123 pidPath = os.path.join(path, "pid.lock")125 pidPath = os.path.join(path, "pid.lock")
124 pid=int(open(pidPath, 'r').read().strip())126 pid=int(open(pidPath, 'r').read().strip())
125 127
128<<<<<<< TREE
126 # list of folders that should not be deleted129 # list of folders that should not be deleted
127 safe_folders = ["blender", "queue", "user_profiles"]130 safe_folders = ["blender", "queue", "user_profiles"]
128 131
@@ -138,6 +141,23 @@
138 # remove folder141 # remove folder
139 os.removedirs(os.path.join(path, child_path))142 os.removedirs(os.path.join(path, child_path))
140 143
144=======
145 # list of folders that should not be deleted
146 safe_folders = ["blender", "queue", "user_profiles", "user_transitions"]
147
148 # loop through all folders in the USER_DIR
149 for child_path in os.listdir(path):
150 if os.path.isdir(os.path.join(path, child_path)):
151 if child_path not in safe_folders:
152 # clear all files / folders recursively in the thumbnail folder
153 if os.getpid() == pid:
154 # only clear this folder for the primary instance of OpenShot
155 self.remove_files(os.path.join(path, child_path))
156
157 # remove folder
158 os.removedirs(os.path.join(path, child_path))
159
160>>>>>>> MERGE-SOURCE
141 # thumbnail path161 # thumbnail path
142 thumbnail_path = os.path.join(path, "thumbnail")162 thumbnail_path = os.path.join(path, "thumbnail")
143 163
@@ -193,6 +213,7 @@
193 state['DESKTOP'] = empty_project.DESKTOP213 state['DESKTOP'] = empty_project.DESKTOP
194 state['THEMES_DIR'] = empty_project.THEMES_DIR214 state['THEMES_DIR'] = empty_project.THEMES_DIR
195 state['USER_PROFILES_DIR'] = empty_project.USER_PROFILES_DIR215 state['USER_PROFILES_DIR'] = empty_project.USER_PROFILES_DIR
216 state['USER_TRANSITIONS_DIR'] = empty_project.USER_TRANSITIONS_DIR
196 state['refresh_xml'] = True217 state['refresh_xml'] = True
197 state['mlt_profile'] = None218 state['mlt_profile'] = None
198219
199220
=== modified file 'openshot/classes/thumbnail.py'
--- openshot/classes/thumbnail.py 2010-02-27 19:51:35 +0000
+++ openshot/classes/thumbnail.py 2010-07-12 22:08:40 +0000
@@ -180,8 +180,10 @@
180 self.profile = None180 self.profile = None
181 self.f = None181 self.f = None
182 182
183 def get_thumb_at_frame(self, filename, frame=1):183 def get_thumb_at_frame(self, filename, frame=1, new_name=""):
184 184 '''by passing a value in new_name, this will extract a
185 full size frame (based on the project profile).'''
186
185 self.file_name = filename187 self.file_name = filename
186 188
187 project_path = self.project.folder189 project_path = self.project.folder
@@ -189,14 +191,15 @@
189 (dirName, fileName) = os.path.split(myPath)191 (dirName, fileName) = os.path.split(myPath)
190 (fileBaseName, fileExtension)=os.path.splitext(fileName)192 (fileBaseName, fileExtension)=os.path.splitext(fileName)
191 fileExtension = fileExtension.replace(".", "")193 fileExtension = fileExtension.replace(".", "")
192 194
193 mlt.Factory.init()195 mlt.Factory.init()
194 196
195 # just get 1 thumbnail frame197
196 self.thumbnail_path = project_path + "/thumbnail/" + fileBaseName + "_" + fileExtension + "_%d.png"
197
198 # set the profile198 # set the profile
199 self.profile = mlt.Profile("quarter_ntsc")199 if new_name == "":
200 self.profile = mlt.Profile("quarter_ntsc")
201 else:
202 self.profile = profiles.mlt_profiles(self.project).get_profile(self.project.project_type)
200 203
201 # Create the producer204 # Create the producer
202 self.p = mlt.Producer( self.profile, '%s' % self.file_name )205 self.p = mlt.Producer( self.profile, '%s' % self.file_name )
@@ -205,6 +208,15 @@
205 if self.p.is_valid() == False:208 if self.p.is_valid() == False:
206 return None209 return None
207 210
211
212 if new_name == "":
213 # just get 1 thumbnail frame
214 self.thumbnail_path = project_path + "/thumbnail/" + fileBaseName + "_" + fileExtension + "_%d.png"
215 else:
216 #for snapshots, use the new file name
217 #don't use the thumbnail path for the new file
218 self.thumbnail_path = project_path + "/" + new_name
219
208 # create the consumer220 # create the consumer
209 self.c = mlt.Consumer(self.profile, "avformat", self.thumbnail_path)221 self.c = mlt.Consumer(self.profile, "avformat", self.thumbnail_path)
210 222
211223
=== added file 'openshot/effects/bass.xml'
--- openshot/effects/bass.xml 1970-01-01 00:00:00 +0000
+++ openshot/effects/bass.xml 2010-07-12 22:08:40 +0000
@@ -0,0 +1,23 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!DOCTYPE openshot-effect>
3<effect>
4 <title translatable="True">Bass</title>
5 <description translatable="True">Sox Bass control</description>
6 <icon>audio.png</icon>
7 <category>Audio</category>
8 <service>sox:bass</service>
9
10 <param name="frequency" type="spinner" title="Frequency" description="">
11 <min>1</min>
12 <max>5000</max>
13 <default>100</default>
14 </param>
15
16 <param name="gain" type="spinner" title="Gain" description="">
17 <min>-20</min>
18 <max>20</max>
19 <default>10</default>
20 </param>
21
22
23</effect>
024
=== added file 'openshot/effects/treble.xml'
--- openshot/effects/treble.xml 1970-01-01 00:00:00 +0000
+++ openshot/effects/treble.xml 2010-07-12 22:08:40 +0000
@@ -0,0 +1,22 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!DOCTYPE openshot-effect>
3<effect>
4 <title translatable="True">Treble</title>
5 <description translatable="True">Sox Treble control</description>
6 <icon>audio.png</icon>
7 <category>Audio</category>
8 <service>sox:treble</service>
9
10 <param name="frequency" type="spinner" title="Frequency" description="">
11 <min>3000</min>
12 <max>22000</max>
13 <default>5000</default>
14 </param>
15
16 <param name="gain" type="spinner" title="Gain" description="">
17 <min>-20</min>
18 <max>20</max>
19 <default>8</default>
20 </param>
21
22</effect>
023
=== modified file 'openshot/windows/AddFiles.py'
--- openshot/windows/AddFiles.py 2010-04-03 18:52:42 +0000
+++ openshot/windows/AddFiles.py 2010-07-12 22:08:40 +0000
@@ -34,13 +34,10 @@
34 # Add language support34 # Add language support
35 _ = Language_Init.Translator(project).lang.gettext35 _ = Language_Init.Translator(project).lang.gettext
3636
37 self.frmAddFiles.set_title("OpenShot")
37 self.frmAddFiles.set_action(gtk.FILE_CHOOSER_ACTION_OPEN)38 self.frmAddFiles.set_action(gtk.FILE_CHOOSER_ACTION_OPEN)
38 self.frmAddFiles.set_select_multiple(True)39 self.frmAddFiles.set_select_multiple(True)
39 #if the video folder exists, default to this40
40 #video_dir = os.path.join(os.path.expanduser("~"), "Video")
41 #if video_dir:
42 # self.frmAddFiles.set_current_folder(video_dir)
43
44 self.form = form41 self.form = form
45 self.project = project42 self.project = project
46 43
@@ -81,6 +78,57 @@
81 #call the open project method when a file is double clicked78 #call the open project method when a file is double clicked
82 self.on_btnAdd_clicked(widget, *args)79 self.on_btnAdd_clicked(widget, *args)
83 80
81class frmReplaceFiles(SimpleGtkBuilderApp):
82
83 def __init__(self, path="AddFiles.ui", root="frmAddFiles", domain="OpenShot", form=None, project=None,clip=None, **kwargs):
84 SimpleGtkBuilderApp.__init__(self, os.path.join(project.UI_DIR, path), root, domain, **kwargs)
85
86 # Add language support
87 _ = Language_Init.Translator(project).lang.gettext
88
89 self.frmAddFiles.set_title("OpenShot")
90 self.frmAddFiles.set_action(gtk.FILE_CHOOSER_ACTION_OPEN)
91 self.frmAddFiles.set_select_multiple(False)
92
93 self.form = form
94 self.project = project
95 self.clip = clip
96
97 self.frmAddFiles.show_all()
98
99 def on_btnCancel_clicked(self, widget, *args):
100 self.frmAddFiles.destroy()
101
102 def on_btnAdd_clicked(self, widget, *args):
103 replace_clip_with = self.frmAddFiles.get_filename()
104 try:
105 #does the new file already exist in the project?
106 file_object = self.project.project_folder.FindFile(replace_clip_with)
107 if not file_object:
108 #add the file to the project
109 self.project.project_folder.AddFile(replace_clip_with)
110
111 #this method does the actual replacement and modifies the project
112 self.form.replace_clip(self.clip,replace_clip_with)
113
114 except:
115 messagebox.show(_("Error"), _("There was an error importing the selected files"))
116
117 #set the last used folder
118 preferences.Settings.app_state["import_folder"] = self.frmAddFiles.get_current_folder()
119
120
121 self.frmAddFiles.destroy()
122
123
124
125 def on_frmAddFiles_file_activated(self, widget, *args):
126 #call the open project method when a file is double clicked
127 self.on_btnAdd_clicked(widget, *args)
128
129 def get_replace_clip_with(self):
130 return self.replace_clip_with
131
84 132
85 133
86def main():134def main():
87135
=== modified file 'openshot/windows/FileProperties.py'
--- openshot/windows/FileProperties.py 2010-07-04 19:40:34 +0000
+++ openshot/windows/FileProperties.py 2010-07-12 22:08:40 +0000
@@ -39,8 +39,21 @@
39 39
40 #set the thumbnail - use the preview thumbnail40 #set the thumbnail - use the preview thumbnail
41 #for video & image files41 #for video & image files
42<<<<<<< TREE
42 pixbuf = file.get_thumbnail(112, 83)43 pixbuf = file.get_thumbnail(112, 83)
43 self.imgPreview.set_from_pixbuf(pixbuf)44 self.imgPreview.set_from_pixbuf(pixbuf)
45=======
46 if file.file_type != "audio":
47 if file.thumb_location != "":
48 pixbuf = gtk.gdk.pixbuf_new_from_file(file.thumb_location)
49 pixbuf = pixbuf.scale_simple(112,83,gtk.gdk.INTERP_BILINEAR)
50 self.imgPreview.set_from_pixbuf(pixbuf)
51 else:
52 #use the generic OpenShot audio thumbnail
53 pixbuf = gtk.gdk.pixbuf_new_from_file(os.path.join(self.project.IMAGE_DIR, "AudioThumbnail.png"))
54 pixbuf = pixbuf.scale_simple(112,83,gtk.gdk.INTERP_BILINEAR)
55 self.imgPreview.set_from_pixbuf(pixbuf)
56>>>>>>> MERGE-SOURCE
44 57
45 #set the file type 58 #set the file type
46 self.lblMimeType.set_label(file.file_type)59 self.lblMimeType.set_label(file.file_type)
4760
=== added file 'openshot/windows/ImportTransitions.py'
--- openshot/windows/ImportTransitions.py 1970-01-01 00:00:00 +0000
+++ openshot/windows/ImportTransitions.py 2010-07-12 22:08:40 +0000
@@ -0,0 +1,138 @@
1# OpenShot Video Editor is a program that creates, modifies, and edits video files.
2# Copyright (C) 2009 Jonathan Thomas
3#
4# This file is part of OpenShot Video Editor (http://launchpad.net/openshot/).
5#
6# OpenShot Video Editor is free software: you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation, either version 3 of the License, or
9# (at your option) any later version.
10#
11# OpenShot Video Editor is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with OpenShot Video Editor. If not, see <http://www.gnu.org/licenses/>.
18
19import os
20import gtk
21import shutil
22from windows.SimpleGtkBuilderApp import SimpleGtkBuilderApp
23from classes import project, messagebox
24from PIL import Image
25
26# init the foreign language
27from language import Language_Init
28
29
30class frmImportTransitions(SimpleGtkBuilderApp):
31
32 def __init__(self, path="ImportTransitions.ui", root="frmImportTransitions", domain="OpenShot", form=None, project=None, **kwargs):
33 SimpleGtkBuilderApp.__init__(self, os.path.join(project.UI_DIR, path), root, domain, **kwargs)
34
35 # Add language support
36 _ = Language_Init.Translator(project).lang.gettext
37
38 self.project = project
39
40 filter = gtk.FileFilter()
41 filter.set_name("PNG or PGM files")
42 filter.add_pattern("*.png")
43 filter.add_pattern("*.pgm")
44
45 self.fileTransition.add_filter(filter)
46 self.fileIcon.add_filter(filter)
47
48 self.transition_file = ""
49 self.icon_file = ""
50
51 self.frmImportTransitions.show_all()
52
53 def on_btnCancel_clicked(self, widget, *args):
54
55 self.frmImportTransitions.destroy()
56
57
58
59 def on_fileTransition_file_set(self, widget, *args):
60
61 self.transition_file = self.fileTransition.get_filename()
62
63 if self.icon_file:
64 if self.check_filename_ok():
65 self.btnOK.set_sensitive(True)
66 else:
67 messagebox.show("Openshot", _("The Transition and Icon file names must be the same."))
68
69
70
71 def on_fileIcon_file_set(self, widget, *args):
72
73 self.icon_file = self.fileIcon.get_filename()
74
75 if self.transition_file:
76 if self.check_filename_ok():
77 self.btnOK.set_sensitive(True)
78 else:
79 messagebox.show("Openshot", _("The Transition and Icon file names must be the same."))
80
81
82 def on_btnOK_clicked(self, widget, *args):
83 #check if a transition with this name exists
84 if self.check_icon_size():
85 (dirName, filename) = os.path.split(self.transition_file)
86 if os.path.exists(os.path.join(self.project.USER_TRANSITIONS_DIR,filename)):
87 messagebox.show("Openshot", _("A Transition with the filename %s already exists. Do you want to replace it?" % filename), gtk.BUTTONS_YES_NO, self.import_transition())
88 else:
89 #just import the transition
90 self.import_transition()
91 else:
92 messagebox.show("Openshot", _("The icon file must have a size of 80x62. The Transition will not be imported."))
93
94 def check_icon_size(self):
95 #check the icon is 80x62
96 try:
97 im = Image.open(self.icon_file)
98 except IOError:
99 print "failed to identify", self.icon_file
100 else:
101 w, h = im.size
102 if w != 80 or h != 62:
103 return False
104 else:
105 return True
106
107 def check_filename_ok(self):
108 #check both filenames match
109 (dirName, self.iconfilename) = os.path.split(self.icon_file)
110 (iconBaseName, fileExtension)=os.path.splitext(self.iconfilename)
111
112 (dirName, self.transfilename) = os.path.split(self.transition_file)
113 (transBaseName, fileExtension)=os.path.splitext(self.transfilename)
114 if iconBaseName == transBaseName:
115 return True
116 else:
117 return False
118
119
120 def import_transition(self):
121 if not os.path.exists(self.project.USER_TRANSITIONS_DIR):
122 os.makedirs(self.project.USER_TRANSITIONS_DIR)
123 os.makedirs(os.path.join(self.project.USER_TRANSITIONS_DIR, "icons"))
124 try:
125 shutil.copyfile(self.transition_file, os.path.join(self.project.USER_TRANSITIONS_DIR, self.transfilename))
126 shutil.copyfile(self.icon_file, os.path.join(self.project.USER_TRANSITIONS_DIR, "icons", self.iconfilename))
127 messagebox.show("Openshot", _("Transition Imported successfully! Restart Openshot for the changes to take effect."))
128 self.frmImportTransitions.destroy()
129 except:
130 messagebox.show("Openshot Error!", _("There was an error importing the Transition!"))
131
132
133def main():
134 import_transitions = frmImportTransitions()
135 import_transitions.run()
136
137if __name__ == "__main__":
138 main()
0\ No newline at end of file139\ No newline at end of file
1140
=== modified file 'openshot/windows/MainGTK.py'
--- openshot/windows/MainGTK.py 2010-07-07 06:25:46 +0000
+++ openshot/windows/MainGTK.py 2010-07-12 22:08:40 +0000
@@ -31,7 +31,7 @@
31from classes import files, lock, messagebox, open_project, project, timeline, tree, video, inputbox, av_formats, clip31from classes import files, lock, messagebox, open_project, project, timeline, tree, video, inputbox, av_formats, clip
32from windows import About, FileProperties, NewProject, OpenProject, preferences, Profiles32from windows import About, FileProperties, NewProject, OpenProject, preferences, Profiles
33from windows.SimpleGtkBuilderApp import SimpleGtkBuilderApp33from windows.SimpleGtkBuilderApp import SimpleGtkBuilderApp
34from windows import AddFiles, ClipProperties, ExportVideo, ImportImageSeq, Titles, TransitionProperties, TreeFiles, TreeTransitions, TreeEffects, TreeHistory, BlenderGenerator, AddToTimeline34from windows import AddFiles, ClipProperties, ExportVideo, ImportImageSeq, Titles, TransitionProperties, TreeFiles, TreeTransitions, TreeEffects, TreeHistory, BlenderGenerator, AddToTimeline, ImportTransitions
3535
36# init the foreign language36# init the foreign language
37from language import Language_Init37from language import Language_Init
@@ -519,8 +519,10 @@
519 # Strip 'file://' from the beginning519 # Strip 'file://' from the beginning
520 file_to_open = uri[7:]520 file_to_open = uri[7:]
521 521
522
522 # Open the project file523 # Open the project file
523 self.open_project(file_to_open)524 self.open_project(file_to_open)
525
524526
525 527
526 def open_project(self, file_to_open):528 def open_project(self, file_to_open):
@@ -541,6 +543,7 @@
541 # Update the main form543 # Update the main form
542 self.refresh()544 self.refresh()
543 545
546
544547
545 def new(self):548 def new(self):
546 print "A new %s has been created" % self.__class__.__name__549 print "A new %s has been created" % self.__class__.__name__
@@ -1156,6 +1159,9 @@
1156 1159
1157 # show import file dialog1160 # show import file dialog
1158 ImportImageSeq.frmImportImageSequence(form=self, project=self.project)1161 ImportImageSeq.frmImportImageSequence(form=self, project=self.project)
1162
1163 def on_mnuImportTransitions_activate(self, widget, *args):
1164 ImportTransitions.frmImportTransitions(form=self, project=self.project)
11591165
11601166
1161 def on_mnuSaveProject_activate(self, widget, *args):1167 def on_mnuSaveProject_activate(self, widget, *args):
@@ -1705,22 +1711,28 @@
1705 self.on_tlbNext_clicked(widget, event)1711 self.on_tlbNext_clicked(widget, event)
1706 1712
1707 elif keyname == "s":1713 elif keyname == "s":
1708 #go to the end of the clip1714 #save the project
1709 if (event.state == gtk.gdk.CONTROL_MASK) or (event.state == gtk.gdk.CONTROL_MASK | gtk.gdk.MOD2_MASK):1715 if (event.state == gtk.gdk.CONTROL_MASK) or (event.state == gtk.gdk.CONTROL_MASK | gtk.gdk.MOD2_MASK):
1710 # call the save button1716 # call the save button
1711 self.on_tlbSave_clicked(widget)1717 self.on_tlbSave_clicked(widget)
1712 1718
1713 elif keyname == "y":1719 elif keyname == "y":
1714 #go to the end of the clip1720 #redo
1715 if (event.state == gtk.gdk.CONTROL_MASK) or (event.state == gtk.gdk.CONTROL_MASK | gtk.gdk.MOD2_MASK):1721 if (event.state == gtk.gdk.CONTROL_MASK) or (event.state == gtk.gdk.CONTROL_MASK | gtk.gdk.MOD2_MASK):
1716 # Undo last action1722 # Undo last action
1717 self.redo_last()1723 self.redo_last()
1718 1724
1719 elif keyname == "z":1725 elif keyname == "z":
1720 #go to the end of the clip1726 #undo
1721 if (event.state == gtk.gdk.CONTROL_MASK) or (event.state == gtk.gdk.CONTROL_MASK | gtk.gdk.MOD2_MASK):1727 if (event.state == gtk.gdk.CONTROL_MASK) or (event.state == gtk.gdk.CONTROL_MASK | gtk.gdk.MOD2_MASK):
1722 # Undo last action1728 # Undo last action
1723 self.undo_last()1729 self.undo_last()
1730
1731 elif keyname == "f":
1732 #snapshot
1733 self.get_frame_snapshot()
1734
1735
1724 1736
1725 1737
1726 def toggle_mode(self):1738 def toggle_mode(self):
@@ -1757,6 +1769,48 @@
1757 canvas_item = clip.get_canvas_child(root_right, clip.unique_id)1769 canvas_item = clip.get_canvas_child(root_right, clip.unique_id)
1758 # divide clip1770 # divide clip
1759 clip.divide_clip(x, canvas_item)1771 clip.divide_clip(x, canvas_item)
1772
1773
1774 def get_frame_snapshot(self):
1775 '''Extracts a frame from each (non-audio) clip at the current
1776 playhead position'''
1777 # Get playhead position
1778 current_position = self.project.sequences[0].play_head_position
1779 # get frames per second
1780 fps = self.project.fps()
1781 # Loop through all tracks
1782 for track in self.project.sequences[0].tracks:
1783 # Loop through all clips on this track
1784 for clip in track.clips:
1785 # is playhead overlapping this clip
1786 if current_position > clip.position_on_track and current_position < (clip.position_on_track + clip.length()):
1787 #only extract frames from non-audio files
1788 if clip.file_object.file_type != "audio":
1789 clip_position = (current_position + clip.start_time) - clip.position_on_track
1790 frame_position = round(clip_position * fps)
1791 #when extracting a frame, it gets added to the
1792 #project as a new file.
1793 #Here we get the name of the existing clip, and
1794 #modify it to make it unique.
1795 filepath = clip.file_object.project.folder
1796 (fileBaseName, fileExtension)=os.path.splitext(clip.name)
1797 #add a number to the end of the filename.
1798 #get the next available number for the file
1799 blnFind = True
1800 intNum = 0
1801 while blnFind == True:
1802 intNum += 1
1803 blnFind = os.path.exists(os.path.join(filepath, fileBaseName + str(intNum) + ".png"))
1804
1805 #this will be the new name of the snapshot image file
1806 new_name = fileBaseName + str(intNum) + ".png"
1807 #extract the frame
1808 self.project.thumbnailer.get_thumb_at_frame(clip.file_object.name, int(frame_position), new_name)
1809 #add the file to the project in the project folder
1810 self.project.project_folder.AddFile(self.project.folder + "/" + new_name)
1811 #refresh the tree
1812 self.refresh()
1813
17601814
17611815
1762 def get_toolbar_options(self):1816 def get_toolbar_options(self):
@@ -3085,6 +3139,23 @@
3085 if is_title:3139 if is_title:
3086 self.form.refresh()3140 self.form.refresh()
3087 3141
3142
3143 def on_mnuReplaceClip_activate (self, event, *args):
3144 # show import file dialog to select replacement file
3145 AddFiles.frmReplaceFiles(form=self, project=self.project, clip=self.selected_clip)
3146
3147
3148 def replace_clip(self, selected_clip, new_clip):
3149 #this replaces the selected clip with a new clip
3150 (filepath, filename) = os.path.split(new_clip)
3151 file = self.project.project_folder.FindFile(filename)
3152 if file:
3153 selected_clip.file_object = file
3154 selected_clip.name = filename
3155 #force a refresh of the xml
3156 self.project.set_project_modified(is_modified=True, refresh_xml=True, type=_("Replaced Clip"))
3157 self.project.Render()
3158 self.form.refresh()
3088 3159
3089 def on_mnuSliceandShuffle_activate(self, event, *args):3160 def on_mnuSliceandShuffle_activate(self, event, *args):
3090 """ Cut a clip into many small pieces and shuffle them """3161 """ Cut a clip into many small pieces and shuffle them """
30913162
=== modified file 'openshot/windows/TreeTransitions.py'
--- openshot/windows/TreeTransitions.py 2010-05-31 21:31:32 +0000
+++ openshot/windows/TreeTransitions.py 2010-07-12 22:08:40 +0000
@@ -18,7 +18,7 @@
1818
19import os19import os
20import gtk, gobject, pango20import gtk, gobject, pango
21from classes import project21from classes import project, messagebox
2222
23# init the foreign language23# init the foreign language
24from language import Language_Init24from language import Language_Init
@@ -90,6 +90,33 @@
90 self.store.set_value(item, 1, _(trans_name))90 self.store.set_value(item, 1, _(trans_name))
91 self.store.set_value(item, 2, os.path.join(self.project.TRANSITIONS_DIR, file_name))91 self.store.set_value(item, 2, os.path.join(self.project.TRANSITIONS_DIR, file_name))
92 92
93 #get any user created transitions
94 if os.path.exists(self.project.USER_TRANSITIONS_DIR):
95 user_list = os.listdir(self.project.USER_TRANSITIONS_DIR)
96 try:
97 for fname in sorted(user_list):
98 (dirName, file_name) = os.path.split(fname)
99 (fileBaseName, fileExtension)=os.path.splitext(file_name)
100 file_path = os.path.join(self.project.USER_TRANSITIONS_DIR, "icons", fileBaseName + ".png")
101
102 if fileBaseName == "icons":
103 # ignore the 'icons' folder
104 continue
105
106 # get the pixbuf
107 pbThumb = gtk.gdk.pixbuf_new_from_file(file_path)
108
109 # get name of transition
110 trans_name = fileBaseName.replace("_", " ").capitalize()
111
112 # add transition to tree
113 item = self.store.append(None)
114 self.store.set_value(item, 0, pbThumb)
115 self.store.set_value(item, 1, _(trans_name))
116 self.store.set_value(item, 2, os.path.join(self.project.USER_TRANSITIONS_DIR, file_name))
117 except:
118 messagebox.show("Openshot Error!", _("There was an error loading user created transitions."))
119
93 120
94 # connect signals121 # connect signals
95 self.treeview.connect_after('drag_begin', self.on_treeTransition_drag_begin)122 self.treeview.connect_after('drag_begin', self.on_treeTransition_drag_begin)
96123
=== modified file 'openshot/windows/preferences.py'
--- openshot/windows/preferences.py 2010-07-06 03:23:04 +0000
+++ openshot/windows/preferences.py 2010-07-12 22:08:40 +0000
@@ -80,6 +80,7 @@
80 #populate the themes80 #populate the themes
81 for dir in os.listdir(self.project.THEMES_DIR):81 for dir in os.listdir(self.project.THEMES_DIR):
82 self.cmbThemes.append_text(dir)82 self.cmbThemes.append_text(dir)
83
83 84
84 # populate project file type combo85 # populate project file type combo
85 for file_type in ["binary", "ascii"]:86 for file_type in ["binary", "ascii"]:
@@ -190,7 +191,8 @@
190 def load_theme_image(self, theme_name):191 def load_theme_image(self, theme_name):
191 #loads the preview image for the selected theme.192 #loads the preview image for the selected theme.
192 themes_folder = os.path.join(self.project.THEMES_DIR, theme_name)193 themes_folder = os.path.join(self.project.THEMES_DIR, theme_name)
193 self.imgTheme.set_from_file(os.path.join(themes_folder, "play.png"))194 if os.path.exists(os.path.join(themes_folder, "play.png")):
195 self.imgTheme.set_from_file(os.path.join(themes_folder, "play.png"))
194 196
195 197
196 def on_icvCategories_selection_changed(self, icon_view, model=None):198 def on_icvCategories_selection_changed(self, icon_view, model=None):
197199
=== added file 'openshot/windows/ui/ImportTransitions.ui'
--- openshot/windows/ui/ImportTransitions.ui 1970-01-01 00:00:00 +0000
+++ openshot/windows/ui/ImportTransitions.ui 2010-07-12 22:08:40 +0000
@@ -0,0 +1,134 @@
1<?xml version="1.0"?>
2<interface>
3 <requires lib="gtk+" version="2.16"/>
4 <!-- interface-naming-policy project-wide -->
5 <object class="GtkWindow" id="frmImportTransitions">
6 <property name="width_request">400</property>
7 <property name="height_request">180</property>
8 <property name="title" translatable="yes">Import Transitions</property>
9 <property name="window_position">center</property>
10 <property name="icon">icons/openshot.png</property>
11 <child>
12 <object class="GtkVBox" id="vbox1">
13 <property name="visible">True</property>
14 <property name="orientation">vertical</property>
15 <child>
16 <object class="GtkLabel" id="label3">
17 <property name="visible">True</property>
18 <property name="label" translatable="yes">The Transition file and Icon file must have the same file name,
19and the Icon should be 80x62.</property>
20 </object>
21 <packing>
22 <property name="padding">6</property>
23 <property name="position">0</property>
24 </packing>
25 </child>
26 <child>
27 <object class="GtkTable" id="table1">
28 <property name="visible">True</property>
29 <property name="n_rows">2</property>
30 <property name="n_columns">2</property>
31 <child>
32 <object class="GtkLabel" id="label1">
33 <property name="visible">True</property>
34 <property name="xalign">0</property>
35 <property name="xpad">10</property>
36 <property name="label" translatable="yes">Select Transition:</property>
37 </object>
38 <packing>
39 <property name="x_options">GTK_FILL</property>
40 </packing>
41 </child>
42 <child>
43 <object class="GtkLabel" id="label2">
44 <property name="visible">True</property>
45 <property name="xalign">0</property>
46 <property name="xpad">12</property>
47 <property name="label" translatable="yes">Select Icon:</property>
48 </object>
49 <packing>
50 <property name="top_attach">1</property>
51 <property name="bottom_attach">2</property>
52 <property name="x_options">GTK_FILL</property>
53 </packing>
54 </child>
55 <child>
56 <object class="GtkFileChooserButton" id="fileTransition">
57 <property name="visible">True</property>
58 <property name="create_folders">False</property>
59 <signal name="file_set" handler="on_fileTransition_file_set"/>
60 </object>
61 <packing>
62 <property name="left_attach">1</property>
63 <property name="right_attach">2</property>
64 <property name="x_padding">12</property>
65 <property name="y_padding">12</property>
66 </packing>
67 </child>
68 <child>
69 <object class="GtkFileChooserButton" id="fileIcon">
70 <property name="visible">True</property>
71 <property name="create_folders">False</property>
72 <signal name="file_set" handler="on_fileIcon_file_set"/>
73 </object>
74 <packing>
75 <property name="left_attach">1</property>
76 <property name="right_attach">2</property>
77 <property name="top_attach">1</property>
78 <property name="bottom_attach">2</property>
79 <property name="x_padding">12</property>
80 <property name="y_padding">12</property>
81 </packing>
82 </child>
83 </object>
84 <packing>
85 <property name="position">2</property>
86 </packing>
87 </child>
88 <child>
89 <object class="GtkHButtonBox" id="hbuttonbox1">
90 <property name="visible">True</property>
91 <property name="layout_style">end</property>
92 <child>
93 <object class="GtkButton" id="btnCancel">
94 <property name="label">gtk-cancel</property>
95 <property name="visible">True</property>
96 <property name="can_focus">True</property>
97 <property name="receives_default">True</property>
98 <property name="use_stock">True</property>
99 <signal name="clicked" handler="on_btnCancel_clicked"/>
100 </object>
101 <packing>
102 <property name="expand">False</property>
103 <property name="fill">False</property>
104 <property name="position">0</property>
105 </packing>
106 </child>
107 <child>
108 <object class="GtkButton" id="btnOK">
109 <property name="label">gtk-ok</property>
110 <property name="visible">True</property>
111 <property name="sensitive">False</property>
112 <property name="can_focus">True</property>
113 <property name="receives_default">True</property>
114 <property name="use_stock">True</property>
115 <signal name="clicked" handler="on_btnOK_clicked"/>
116 </object>
117 <packing>
118 <property name="expand">False</property>
119 <property name="fill">False</property>
120 <property name="position">1</property>
121 </packing>
122 </child>
123 </object>
124 <packing>
125 <property name="fill">False</property>
126 <property name="padding">1</property>
127 <property name="pack_type">end</property>
128 <property name="position">1</property>
129 </packing>
130 </child>
131 </object>
132 </child>
133 </object>
134</interface>
0135
=== modified file 'openshot/windows/ui/Main.ui'
--- openshot/windows/ui/Main.ui 2010-07-04 20:03:37 +0000
+++ openshot/windows/ui/Main.ui 2010-07-12 22:08:40 +0000
@@ -77,6 +77,15 @@
77 </object>77 </object>
78 </child>78 </child>
79 <child>79 <child>
80 <object class="GtkImageMenuItem" id="mnuImportTransitions">
81 <property name="label" translatable="yes">Import New Transition...</property>
82 <property name="visible">True</property>
83 <property name="use_stock">False</property>
84 <property name="accel_group">accelgroup1</property>
85 <signal name="activate" handler="on_mnuImportTransitions_activate"/>
86 </object>
87 </child>
88 <child>
80 <object class="GtkSeparatorMenuItem" id="separatormenuitem3">89 <object class="GtkSeparatorMenuItem" id="separatormenuitem3">
81 <property name="visible">True</property>90 <property name="visible">True</property>
82 </object>91 </object>
8392
=== modified file 'openshot/windows/ui/Main_clip_properties.ui'
--- openshot/windows/ui/Main_clip_properties.ui 2010-05-03 05:51:49 +0000
+++ openshot/windows/ui/Main_clip_properties.ui 2010-07-12 22:08:40 +0000
@@ -69,6 +69,15 @@
69 </object>69 </object>
70 </child>70 </child>
71 <child>71 <child>
72 <object class="GtkImageMenuItem" id="mnuReplaceClip">
73 <property name="label" translatable="yes">Replace Clip</property>
74 <property name="visible">True</property>
75 <property name="image">image1</property>
76 <property name="use_stock">False</property>
77 <signal name="activate" handler="on_mnuReplaceClip_activate"/>
78 </object>
79 </child>
80 <child>
72 <object class="GtkImageMenuItem" id="mnuRemoveClip">81 <object class="GtkImageMenuItem" id="mnuRemoveClip">
73 <property name="label" translatable="yes">Remove Clip</property>82 <property name="label" translatable="yes">Remove Clip</property>
74 <property name="visible">True</property>83 <property name="visible">True</property>
@@ -94,4 +103,8 @@
94 </child>103 </child>
95 </object>104 </object>
96 <object class="GtkAccelGroup" id="accelgroup1"/>105 <object class="GtkAccelGroup" id="accelgroup1"/>
106 <object class="GtkImage" id="image1">
107 <property name="visible">True</property>
108 <property name="stock">gtk-missing-image</property>
109 </object>
97</interface>110</interface>

Subscribers

People subscribed via source and target branches

to status/vote changes: