Merge lp:~nico-inattendu/luciole/dev_nico into lp:luciole/0.7

Proposed by NicoInattendu
Status: Merged
Merged at revision: not available
Proposed branch: lp:~nico-inattendu/luciole/dev_nico
Merge into: lp:luciole/0.7
Diff against target: None lines
To merge this branch: bzr merge lp:~nico-inattendu/luciole/dev_nico
Reviewer Review Type Date Requested Status
NicoInattendu Approve
Review via email: mp+5494@code.launchpad.net
To post a comment you must log in.
Revision history for this message
NicoInattendu (nico-inattendu) wrote :

Merge proposal for first luciole alpha

Revision history for this message
NicoInattendu (nico-inattendu) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2009-03-30 22:17:30 +0000
3+++ Makefile 2009-04-13 20:10:28 +0000
4@@ -73,7 +73,7 @@
5 mkdir -p $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole
6 mkdir -p $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib
7 mkdir -p $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/lucioExport
8- mkdir -p $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/lucioImageCapture
9+ mkdir -p $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/gui
10 mkdir -p $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/lucioWebCamDetect
11 mkdir -p $(DESTDIR)$(PREFIX)/share/
12 mkdir -p $(DESTDIR)$(PREFIX)/share/pixmaps
13@@ -88,13 +88,14 @@
14 install -m 644 $(CURDIR)/$(SOURCE_DIR)luciole.py $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole
15 install -m 644 $(CURDIR)/$(SOURCE_DIR)_version.py $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole
16 install -m 644 $(CURDIR)/$(SOURCE_DIR)images/luciole.glade $(DESTDIR)$(PREFIX)/share/luciole/images
17+ install -m 644 $(CURDIR)/$(SOURCE_DIR)images/luciole.xml $(DESTDIR)$(PREFIX)/share/luciole/images
18 install -m 644 $(CURDIR)/$(SOURCE_DIR)images/*.png $(DESTDIR)$(PREFIX)/share/luciole/images
19 install -m 644 $(CURDIR)/$(SOURCE_DIR)lucioLib/*.py $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/
20 -install -m 644 $(CURDIR)/$(SOURCE_DIR)lucioLib/*.py[co] $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/
21 install -m 644 $(CURDIR)/$(SOURCE_DIR)lucioLib/lucioExport/*.py $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/lucioExport
22 -install -m 644 $(CURDIR)/$(SOURCE_DIR)lucioLib/lucioExport/*.py[co] $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/lucioExport
23- install -m 644 $(CURDIR)/$(SOURCE_DIR)lucioLib/lucioImageCapture/*.py $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/lucioImageCapture
24- -install -m 644 $(CURDIR)/$(SOURCE_DIR)lucioLib/lucioImageCapture/*.py[co] $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/lucioImageCapture
25+ install -m 644 $(CURDIR)/$(SOURCE_DIR)lucioLib/gui/*.py $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/gui
26+ -install -m 644 $(CURDIR)/$(SOURCE_DIR)lucioLib/gui/*.py[co] $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/gui
27 install -m 644 $(CURDIR)/$(SOURCE_DIR)lucioLib/lucioWebCamDetect/*.py $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/lucioWebCamDetect
28 -install -m 644 $(CURDIR)/$(SOURCE_DIR)lucioLib/lucioWebCamDetect/*.py[co] $(DESTDIR)$(PREFIX)$(LIBDIR)/luciole/lucioLib/lucioWebCamDetect
29 install -m 644 $(CURDIR)/$(SOURCE_DIR)templates/*.xml $(DESTDIR)$(PREFIX)/share/luciole/templates
30
31=== modified file '_version.py'
32--- _version.py 2009-03-08 18:06:41 +0000
33+++ _version.py 2009-04-13 19:42:11 +0000
34@@ -1,36 +1,15 @@
35 #!/usr/bin/env python
36-#
37-#
38-# Copyright Nicolas Bertrand (nico@inattendu.org), 2009
39-#
40-# This file is part of Luciole.
41-#
42-# Luciole is free software: you can redistribute it and/or modify
43-# it under the terms of the GNU General Public License as published by
44-# the Free Software Foundation, either version 3 of the License, or
45-# (at your option) any later version.
46-#
47-# Luciole is distributed in the hope that it will be useful,
48-# but WITHOUT ANY WARRANTY; without even the implied warranty of
49-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
50-# GNU General Public License for more details.
51-#
52-# You should have received a copy of the GNU General Public License
53-# along with Luciole. If not, see <http://www.gnu.org/licenses/>.
54-#
55-#
56-
57 """This file is automatically generated by generate_version_info
58 It uses the current working tree to determine the revision.
59 So don't edit it. :)
60 """
61
62-version_info = {'branch_nick': u'luciole-0.6.1',
63- 'build_date': '2009-01-04 23:45:46 +0100',
64+version_info = {'branch_nick': u'dev_nico',
65+ 'build_date': '2009-04-13 21:40:48 +0200',
66 'clean': None,
67- 'date': '2009-01-04 23:42:58 +0100',
68- 'revision_id': 'nico@inattendu.org-20090104224258-d8qkwnr6766whnn3',
69- 'revno': 82}
70+ 'date': '2009-04-13 21:21:49 +0200',
71+ 'revision_id': 'nico@inattendu.org-20090413192149-hydd2h9a4p21pnbc',
72+ 'revno': 14}
73
74 revisions = {}
75
76
77=== modified file 'images/luciole.glade'
78--- images/luciole.glade 2009-04-10 20:10:44 +0000
79+++ images/luciole.glade 2009-04-13 19:42:11 +0000
80@@ -1,8 +1,10 @@
81 <?xml version="1.0" encoding="UTF-8" standalone="no"?>
82 <!DOCTYPE glade-interface SYSTEM "glade-2.0.dtd">
83-<!--Generated with glade3 3.4.5 on Fri Apr 10 22:06:52 2009 -->
84+<!--Generated with glade3 3.4.5 on Mon Apr 13 21:29:08 2009 -->
85 <glade-interface>
86 <widget class="GtkWindow" id="window1">
87+ <signal name="delete_event" handler="on_window1_delete_event"/>
88+ <signal name="destroy_event" handler="on_window1_destroy_event"/>
89 <child>
90 <widget class="GtkVBox" id="vbox1">
91 <property name="visible">True</property>
92@@ -36,6 +38,53 @@
93 </widget>
94 </child>
95 <child>
96+ <widget class="GtkMenuItem" id="menu_file_open_recent">
97+ <property name="visible">True</property>
98+ <property name="label" translatable="yes">Open recent</property>
99+ <property name="use_underline">True</property>
100+ <child>
101+ <widget class="GtkMenu" id="menu_test">
102+ <property name="visible">True</property>
103+ <child>
104+ <widget class="GtkMenuItem" id="recent1">
105+ <property name="visible">True</property>
106+ <property name="label" translatable="yes">project1</property>
107+ <property name="use_underline">True</property>
108+ </widget>
109+ </child>
110+ <child>
111+ <widget class="GtkMenuItem" id="recent2">
112+ <property name="visible">True</property>
113+ <property name="label" translatable="yes">project2</property>
114+ <property name="use_underline">True</property>
115+ </widget>
116+ </child>
117+ <child>
118+ <widget class="GtkMenuItem" id="recent3">
119+ <property name="visible">True</property>
120+ <property name="label" translatable="yes">project3</property>
121+ <property name="use_underline">True</property>
122+ </widget>
123+ </child>
124+ <child>
125+ <widget class="GtkMenuItem" id="recent4">
126+ <property name="visible">True</property>
127+ <property name="label" translatable="yes">project4</property>
128+ <property name="use_underline">True</property>
129+ </widget>
130+ </child>
131+ <child>
132+ <widget class="GtkMenuItem" id="recent5">
133+ <property name="visible">True</property>
134+ <property name="label" translatable="yes">project5</property>
135+ <property name="use_underline">True</property>
136+ </widget>
137+ </child>
138+ </widget>
139+ </child>
140+ </widget>
141+ </child>
142+ <child>
143 <widget class="GtkImageMenuItem" id="file_save">
144 <property name="visible">True</property>
145 <property name="label" translatable="yes">gtk-save</property>
146@@ -115,54 +164,30 @@
147 </widget>
148 </child>
149 <child>
150- <widget class="GtkMenuItem" id="menuitem2">
151- <property name="visible">True</property>
152- <property name="label" translatable="yes">_Edit</property>
153- <property name="use_underline">True</property>
154- <child>
155- <widget class="GtkMenu" id="menu2">
156- <property name="visible">True</property>
157- <child>
158- <widget class="GtkImageMenuItem" id="imagemenuitem6">
159- <property name="visible">True</property>
160- <property name="label" translatable="yes">gtk-cut</property>
161- <property name="use_underline">True</property>
162- <property name="use_stock">True</property>
163- </widget>
164- </child>
165- <child>
166- <widget class="GtkImageMenuItem" id="imagemenuitem7">
167- <property name="visible">True</property>
168- <property name="label" translatable="yes">gtk-copy</property>
169- <property name="use_underline">True</property>
170- <property name="use_stock">True</property>
171- </widget>
172- </child>
173- <child>
174- <widget class="GtkImageMenuItem" id="imagemenuitem8">
175- <property name="visible">True</property>
176- <property name="label" translatable="yes">gtk-paste</property>
177- <property name="use_underline">True</property>
178- <property name="use_stock">True</property>
179- </widget>
180- </child>
181- <child>
182- <widget class="GtkImageMenuItem" id="imagemenuitem9">
183- <property name="visible">True</property>
184- <property name="label" translatable="yes">gtk-delete</property>
185- <property name="use_underline">True</property>
186- <property name="use_stock">True</property>
187- </widget>
188- </child>
189- </widget>
190- </child>
191- </widget>
192- </child>
193- <child>
194 <widget class="GtkMenuItem" id="menuitem3">
195 <property name="visible">True</property>
196 <property name="label" translatable="yes">_View</property>
197 <property name="use_underline">True</property>
198+ <child>
199+ <widget class="GtkMenu" id="menu4">
200+ <property name="visible">True</property>
201+ <child>
202+ <widget class="GtkImageMenuItem" id="view_project">
203+ <property name="visible">True</property>
204+ <property name="tooltip" translatable="yes">Project Properties</property>
205+ <property name="label" translatable="yes">Project Properties</property>
206+ <property name="use_underline">True</property>
207+ <signal name="activate" handler="on_view_project_activate"/>
208+ <child internal-child="image">
209+ <widget class="GtkImage" id="menu-item-image3">
210+ <property name="visible">True</property>
211+ <property name="stock">gtk-properties</property>
212+ </widget>
213+ </child>
214+ </widget>
215+ </child>
216+ </widget>
217+ </child>
218 </widget>
219 </child>
220 <child>
221@@ -174,11 +199,13 @@
222 <widget class="GtkMenu" id="menu3">
223 <property name="visible">True</property>
224 <child>
225- <widget class="GtkImageMenuItem" id="imagemenuitem10">
226+ <widget class="GtkImageMenuItem" id="help_about">
227 <property name="visible">True</property>
228+ <property name="tooltip" translatable="yes">About</property>
229 <property name="label" translatable="yes">gtk-about</property>
230 <property name="use_underline">True</property>
231 <property name="use_stock">True</property>
232+ <signal name="activate" handler="on_help_about_activate"/>
233 </widget>
234 </child>
235 </widget>
236@@ -230,184 +257,191 @@
237 </packing>
238 </child>
239 <child>
240- <widget class="GtkHBox" id="hbox_acquisition">
241- <property name="height_request">51</property>
242+ <widget class="GtkAspectFrame" id="aspectframe2">
243 <property name="visible">True</property>
244- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
245- <child>
246- <widget class="GtkFixed" id="fixed8">
247- <property name="width_request">20</property>
248- <property name="visible">True</property>
249- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
250- </widget>
251- </child>
252- <child>
253- <widget class="GtkToggleButton" id="acquisition_button">
254- <property name="width_request">56</property>
255- <property name="height_request">46</property>
256- <property name="visible">True</property>
257- <property name="can_focus">True</property>
258- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
259- <property name="has_tooltip">True</property>
260- <property name="tooltip" translatable="yes">Activate/Deactivate camera preview</property>
261- <property name="focus_on_click">False</property>
262- <property name="response_id">0</property>
263- <signal name="toggled" handler="on_acquisition_button_toggled"/>
264- <child>
265- <widget class="GtkImage" id="acquisition_button_image">
266- <property name="visible">True</property>
267- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
268+ <property name="label_xalign">0</property>
269+ <property name="shadow_type">GTK_SHADOW_NONE</property>
270+ <child>
271+ <widget class="GtkHBox" id="hbox_acquisition">
272+ <property name="height_request">51</property>
273+ <property name="visible">True</property>
274+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
275+ <child>
276+ <widget class="GtkFixed" id="fixed8">
277+ <property name="width_request">20</property>
278+ <property name="visible">True</property>
279+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
280+ </widget>
281+ </child>
282+ <child>
283+ <widget class="GtkToggleButton" id="acquisition_button">
284+ <property name="width_request">56</property>
285+ <property name="height_request">46</property>
286+ <property name="visible">True</property>
287+ <property name="can_focus">True</property>
288+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
289+ <property name="has_tooltip">True</property>
290 <property name="tooltip" translatable="yes">Activate/Deactivate camera preview</property>
291- <property name="pixbuf">Luciole-dodo.png</property>
292- </widget>
293- </child>
294- </widget>
295- <packing>
296- <property name="expand">False</property>
297- <property name="fill">False</property>
298- <property name="position">1</property>
299- </packing>
300- </child>
301- <child>
302- <widget class="GtkFixed" id="fixed15">
303- <property name="width_request">20</property>
304- <property name="visible">True</property>
305- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
306- </widget>
307- <packing>
308- <property name="position">2</property>
309- </packing>
310- </child>
311- <child>
312- <widget class="GtkButton" id="snapshot_button">
313- <property name="visible">True</property>
314- <property name="can_focus">True</property>
315- <property name="receives_default">True</property>
316- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
317- <property name="has_tooltip">True</property>
318- <property name="tooltip" translatable="yes" comments="Capturer une image">make a snapshot</property>
319- <property name="response_id">0</property>
320- <signal name="clicked" handler="on_button_capture_clicked"/>
321- <accelerator key="c" modifiers="" signal="clicked"/>
322- <child>
323- <widget class="GtkImage" id="image5">
324- <property name="visible">True</property>
325- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
326- <property name="tooltip" translatable="yes">make a snapshot</property>
327- <property name="pixbuf">capture.png</property>
328- </widget>
329- </child>
330- </widget>
331- <packing>
332- <property name="expand">False</property>
333- <property name="fill">False</property>
334- <property name="position">3</property>
335- </packing>
336- </child>
337- <child>
338- <widget class="GtkFixed" id="fixed11">
339- <property name="width_request">20</property>
340- <property name="visible">True</property>
341- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
342- </widget>
343- <packing>
344- <property name="position">4</property>
345- </packing>
346- </child>
347- <child>
348- <widget class="GtkVBox" id="vbox9">
349- <property name="width_request">134</property>
350- <property name="visible">True</property>
351- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
352- <child>
353- <widget class="GtkCheckButton" id="mixer_checkbutton">
354- <property name="visible">True</property>
355- <property name="can_focus">True</property>
356- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
357- <property name="has_tooltip">True</property>
358- <property name="tooltip" translatable="yes">Mixer activation (onion skin)</property>
359- <property name="label" translatable="yes">Mixer</property>
360- <property name="relief">GTK_RELIEF_HALF</property>
361- <property name="response_id">0</property>
362- <property name="draw_indicator">True</property>
363- <signal name="toggled" handler="on_mixer_checkbutton_toggled"/>
364- </widget>
365- </child>
366- <child>
367- <widget class="GtkHScale" id="alpha_hscale">
368- <property name="visible">True</property>
369- <property name="can_focus">True</property>
370- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
371- <property name="has_tooltip">True</property>
372- <property name="tooltip" translatable="yes">Transparency level</property>
373- <property name="update_policy">GTK_UPDATE_DISCONTINUOUS</property>
374- <property name="adjustment">1 0 4 1 1 0</property>
375- <property name="digits">0</property>
376- <property name="value_pos">GTK_POS_LEFT</property>
377- <signal name="value_changed" handler="on_alpha_hscale_value_changed"/>
378- </widget>
379- <packing>
380- <property name="position">1</property>
381- </packing>
382- </child>
383- </widget>
384- <packing>
385- <property name="expand">False</property>
386- <property name="fill">False</property>
387- <property name="position">5</property>
388- </packing>
389- </child>
390- <child>
391- <widget class="GtkFixed" id="fixed22">
392- <property name="width_request">20</property>
393- <property name="visible">True</property>
394- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
395- </widget>
396- <packing>
397- <property name="position">6</property>
398- </packing>
399- </child>
400- <child>
401- <widget class="GtkVBox" id="vbox10">
402- <property name="visible">True</property>
403- <child>
404- <widget class="GtkLabel" id="label_fpi">
405- <property name="width_request">104</property>
406- <property name="visible">True</property>
407- <property name="label" translatable="yes">Image per seconds</property>
408- <property name="justify">GTK_JUSTIFY_CENTER</property>
409- </widget>
410- <packing>
411- <property name="fill">False</property>
412- </packing>
413- </child>
414- <child>
415- <widget class="GtkHScale" id="hscale_fps">
416- <property name="width_request">125</property>
417- <property name="visible">True</property>
418- <property name="can_focus">True</property>
419- <property name="adjustment">1 1 6 1 1 1</property>
420- <property name="digits">0</property>
421- <signal name="value_changed" handler="on_hscale_fps_value_changed"/>
422- <signal name="format_value" handler="on_hscale_fps_format_value"/>
423- </widget>
424- <packing>
425- <property name="fill">False</property>
426- <property name="position">1</property>
427- </packing>
428- </child>
429- </widget>
430- <packing>
431- <property name="position">7</property>
432- </packing>
433- </child>
434- <child>
435- <widget class="GtkFixed" id="fixed4">
436- <property name="visible">True</property>
437- </widget>
438- <packing>
439- <property name="position">8</property>
440- </packing>
441+ <property name="focus_on_click">False</property>
442+ <property name="response_id">0</property>
443+ <signal name="toggled" handler="on_acquisition_button_toggled"/>
444+ <child>
445+ <widget class="GtkImage" id="acquisition_button_image">
446+ <property name="visible">True</property>
447+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
448+ <property name="tooltip" translatable="yes">Activate/Deactivate camera preview</property>
449+ <property name="pixbuf">luciole-dodo.png</property>
450+ </widget>
451+ </child>
452+ </widget>
453+ <packing>
454+ <property name="expand">False</property>
455+ <property name="fill">False</property>
456+ <property name="position">1</property>
457+ </packing>
458+ </child>
459+ <child>
460+ <widget class="GtkFixed" id="fixed15">
461+ <property name="width_request">20</property>
462+ <property name="visible">True</property>
463+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
464+ </widget>
465+ <packing>
466+ <property name="position">2</property>
467+ </packing>
468+ </child>
469+ <child>
470+ <widget class="GtkButton" id="snapshot_button">
471+ <property name="visible">True</property>
472+ <property name="can_focus">True</property>
473+ <property name="receives_default">True</property>
474+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
475+ <property name="has_tooltip">True</property>
476+ <property name="tooltip" translatable="yes" comments="Capturer une image">make a snapshot</property>
477+ <property name="response_id">0</property>
478+ <signal name="clicked" handler="on_button_capture_clicked"/>
479+ <accelerator key="c" modifiers="" signal="clicked"/>
480+ <child>
481+ <widget class="GtkImage" id="image5">
482+ <property name="visible">True</property>
483+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
484+ <property name="tooltip" translatable="yes">make a snapshot</property>
485+ <property name="pixbuf">capture.png</property>
486+ </widget>
487+ </child>
488+ </widget>
489+ <packing>
490+ <property name="expand">False</property>
491+ <property name="fill">False</property>
492+ <property name="position">3</property>
493+ </packing>
494+ </child>
495+ <child>
496+ <widget class="GtkFixed" id="fixed11">
497+ <property name="width_request">20</property>
498+ <property name="visible">True</property>
499+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
500+ </widget>
501+ <packing>
502+ <property name="position">4</property>
503+ </packing>
504+ </child>
505+ <child>
506+ <widget class="GtkVBox" id="vbox9">
507+ <property name="width_request">134</property>
508+ <property name="visible">True</property>
509+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
510+ <child>
511+ <widget class="GtkCheckButton" id="mixer_checkbutton">
512+ <property name="visible">True</property>
513+ <property name="can_focus">True</property>
514+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
515+ <property name="has_tooltip">True</property>
516+ <property name="tooltip" translatable="yes">Mixer activation (onion skin)</property>
517+ <property name="label" translatable="yes">Mixer</property>
518+ <property name="relief">GTK_RELIEF_HALF</property>
519+ <property name="response_id">0</property>
520+ <property name="draw_indicator">True</property>
521+ <signal name="toggled" handler="on_mixer_checkbutton_toggled"/>
522+ </widget>
523+ </child>
524+ <child>
525+ <widget class="GtkHScale" id="alpha_hscale">
526+ <property name="visible">True</property>
527+ <property name="can_focus">True</property>
528+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
529+ <property name="has_tooltip">True</property>
530+ <property name="tooltip" translatable="yes">Transparency level</property>
531+ <property name="update_policy">GTK_UPDATE_DISCONTINUOUS</property>
532+ <property name="adjustment">1 0 4 1 1 0</property>
533+ <property name="digits">0</property>
534+ <property name="value_pos">GTK_POS_LEFT</property>
535+ <signal name="value_changed" handler="on_alpha_hscale_value_changed"/>
536+ </widget>
537+ <packing>
538+ <property name="position">1</property>
539+ </packing>
540+ </child>
541+ </widget>
542+ <packing>
543+ <property name="expand">False</property>
544+ <property name="fill">False</property>
545+ <property name="position">5</property>
546+ </packing>
547+ </child>
548+ <child>
549+ <widget class="GtkFixed" id="fixed22">
550+ <property name="width_request">20</property>
551+ <property name="visible">True</property>
552+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
553+ </widget>
554+ <packing>
555+ <property name="position">6</property>
556+ </packing>
557+ </child>
558+ <child>
559+ <widget class="GtkVBox" id="vbox10">
560+ <property name="visible">True</property>
561+ <child>
562+ <widget class="GtkLabel" id="label_fpi">
563+ <property name="width_request">104</property>
564+ <property name="visible">True</property>
565+ <property name="label" translatable="yes">Image per seconds</property>
566+ <property name="justify">GTK_JUSTIFY_CENTER</property>
567+ </widget>
568+ <packing>
569+ <property name="fill">False</property>
570+ </packing>
571+ </child>
572+ <child>
573+ <widget class="GtkHScale" id="hscale_fps">
574+ <property name="width_request">125</property>
575+ <property name="visible">True</property>
576+ <property name="can_focus">True</property>
577+ <property name="adjustment">1 1 6 1 1 1</property>
578+ <property name="digits">0</property>
579+ <signal name="value_changed" handler="on_hscale_fps_value_changed"/>
580+ <signal name="format_value" handler="on_hscale_fps_format_value"/>
581+ </widget>
582+ <packing>
583+ <property name="fill">False</property>
584+ <property name="position">1</property>
585+ </packing>
586+ </child>
587+ </widget>
588+ <packing>
589+ <property name="position">7</property>
590+ </packing>
591+ </child>
592+ <child>
593+ <widget class="GtkFixed" id="fixed4">
594+ <property name="visible">True</property>
595+ </widget>
596+ <packing>
597+ <property name="position">8</property>
598+ </packing>
599+ </child>
600+ </widget>
601 </child>
602 </widget>
603 <packing>
604@@ -831,12 +865,30 @@
605 </packing>
606 </child>
607 <child>
608- <widget class="GtkStatusbar" id="statusbar1">
609+ <widget class="GtkHBox" id="hbox3">
610 <property name="visible">True</property>
611- <property name="spacing">2</property>
612+ <child>
613+ <widget class="GtkStatusbar" id="statusbar1">
614+ <property name="visible">True</property>
615+ <property name="spacing">2</property>
616+ </widget>
617+ </child>
618+ <child>
619+ <widget class="GtkProgressBar" id="progressbar_status">
620+ <property name="width_request">200</property>
621+ <property name="height_request">10</property>
622+ </widget>
623+ <packing>
624+ <property name="expand">False</property>
625+ <property name="fill">False</property>
626+ <property name="padding">3</property>
627+ <property name="position">1</property>
628+ </packing>
629+ </child>
630 </widget>
631 <packing>
632 <property name="expand">False</property>
633+ <property name="padding">2</property>
634 <property name="position">2</property>
635 </packing>
636 </child>
637@@ -883,8 +935,8 @@
638 <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
639 <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
640 <property name="has_separator">False</property>
641- <property name="program_name">luciole</property>
642- <property name="version">0.5</property>
643+ <property name="program_name">Luciole</property>
644+ <property name="version">0.7</property>
645 <property name="comments" translatable="yes">
646 Tool for video capture, for making animated cartoon from image per image
647 </property>
648@@ -907,6 +959,7 @@
649 Inc., 59 Temple Place -
650 Suite 330, Boston, MA 02111-1307, USA.</property>
651 <property name="authors">nico : nico@inattendu.org</property>
652+ <property name="logo">luciole_logo.png</property>
653 <child internal-child="vbox">
654 <widget class="GtkVBox" id="dialog-vbox9">
655 <property name="visible">True</property>
656@@ -1199,9 +1252,9 @@
657 <widget class="GtkFileChooserButton" id="filechooserbutton1">
658 <property name="visible">True</property>
659 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
660+ <property name="do_overwrite_confirmation">True</property>
661 <property name="action">GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</property>
662 <property name="use_preview_label">False</property>
663- <property name="do_overwrite_confirmation">True</property>
664 <property name="title" translatable="yes">Select a folder</property>
665 </widget>
666 <packing>
667@@ -1403,4 +1456,38 @@
668 </widget>
669 </child>
670 </widget>
671+ <widget class="GtkDialog" id="dialog_project_properties">
672+ <property name="border_width">5</property>
673+ <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
674+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
675+ <property name="has_separator">False</property>
676+ <child internal-child="vbox">
677+ <widget class="GtkVBox" id="dialog-vbox4">
678+ <property name="visible">True</property>
679+ <property name="spacing">2</property>
680+ <child>
681+ <placeholder/>
682+ </child>
683+ <child internal-child="action_area">
684+ <widget class="GtkHButtonBox" id="dialog-action_area4">
685+ <property name="visible">True</property>
686+ <property name="layout_style">GTK_BUTTONBOX_END</property>
687+ <child>
688+ <placeholder/>
689+ </child>
690+ <child>
691+ <placeholder/>
692+ </child>
693+ <child>
694+ <placeholder/>
695+ </child>
696+ </widget>
697+ <packing>
698+ <property name="expand">False</property>
699+ <property name="pack_type">GTK_PACK_END</property>
700+ </packing>
701+ </child>
702+ </widget>
703+ </child>
704+ </widget>
705 </glade-interface>
706
707=== modified file 'images/luciole.xml'
708--- images/luciole.xml 2009-04-10 20:10:44 +0000
709+++ images/luciole.xml 2009-04-13 19:42:11 +0000
710@@ -1,5 +1,5 @@
711 <?xml version="1.0"?>
712-<!--Generated with glade3 3.4.5 on Fri Apr 10 22:06:52 2009 -->
713+<!--Generated with glade3 3.4.5 on Mon Apr 13 21:29:08 2009 -->
714 <interface>
715 <object class="GtkAdjustment" id="adjustment1">
716 <property name="upper">4</property>
717@@ -57,6 +57,42 @@
718 </object>
719 </child>
720 <child>
721+ <object class="GtkAction" id="menu_file_open_recent">
722+ <property name="name">menu_file_open_recent</property>
723+ <property name="label" translatable="yes">Open recent</property>
724+ </object>
725+ </child>
726+ <child>
727+ <object class="GtkAction" id="recent1">
728+ <property name="name">recent1</property>
729+ <property name="label" translatable="yes">project1</property>
730+ </object>
731+ </child>
732+ <child>
733+ <object class="GtkAction" id="recent2">
734+ <property name="name">recent2</property>
735+ <property name="label" translatable="yes">project2</property>
736+ </object>
737+ </child>
738+ <child>
739+ <object class="GtkAction" id="recent3">
740+ <property name="name">recent3</property>
741+ <property name="label" translatable="yes">project3</property>
742+ </object>
743+ </child>
744+ <child>
745+ <object class="GtkAction" id="recent4">
746+ <property name="name">recent4</property>
747+ <property name="label" translatable="yes">project4</property>
748+ </object>
749+ </child>
750+ <child>
751+ <object class="GtkAction" id="recent5">
752+ <property name="name">recent5</property>
753+ <property name="label" translatable="yes">project5</property>
754+ </object>
755+ </child>
756+ <child>
757 <object class="GtkAction" id="file_save">
758 <property name="stock_id" translatable="yes">gtk-save</property>
759 <property name="name">file_save</property>
760@@ -100,51 +136,32 @@
761 </object>
762 </child>
763 <child>
764- <object class="GtkAction" id="menuitem2">
765- <property name="name">menuitem2</property>
766- <property name="label" translatable="yes">_Edit</property>
767- </object>
768- </child>
769- <child>
770- <object class="GtkAction" id="imagemenuitem6">
771- <property name="stock_id" translatable="yes">gtk-cut</property>
772- <property name="name">imagemenuitem6</property>
773- </object>
774- </child>
775- <child>
776- <object class="GtkAction" id="imagemenuitem7">
777- <property name="stock_id" translatable="yes">gtk-copy</property>
778- <property name="name">imagemenuitem7</property>
779- </object>
780- </child>
781- <child>
782- <object class="GtkAction" id="imagemenuitem8">
783- <property name="stock_id" translatable="yes">gtk-paste</property>
784- <property name="name">imagemenuitem8</property>
785- </object>
786- </child>
787- <child>
788- <object class="GtkAction" id="imagemenuitem9">
789- <property name="stock_id" translatable="yes">gtk-delete</property>
790- <property name="name">imagemenuitem9</property>
791- </object>
792- </child>
793- <child>
794 <object class="GtkAction" id="menuitem3">
795 <property name="name">menuitem3</property>
796 <property name="label" translatable="yes">_View</property>
797 </object>
798 </child>
799 <child>
800+ <object class="GtkAction" id="view_project">
801+ <property name="stock_id">gtk-properties</property>
802+ <property name="name">view_project</property>
803+ <property name="tooltip" translatable="yes">Project Properties</property>
804+ <property name="label" translatable="yes">Project Properties</property>
805+ <signal handler="on_view_project_activate" name="activate"/>
806+ </object>
807+ </child>
808+ <child>
809 <object class="GtkAction" id="menuitem4">
810 <property name="name">menuitem4</property>
811 <property name="label" translatable="yes">_Help</property>
812 </object>
813 </child>
814 <child>
815- <object class="GtkAction" id="imagemenuitem10">
816+ <object class="GtkAction" id="help_about">
817 <property name="stock_id" translatable="yes">gtk-about</property>
818- <property name="name">imagemenuitem10</property>
819+ <property name="name">help_about</property>
820+ <property name="tooltip" translatable="yes">About</property>
821+ <signal handler="on_help_about_activate" name="activate"/>
822 </object>
823 </child>
824 </object>
825@@ -154,6 +171,13 @@
826 <menu action="menu_file">
827 <menuitem action="file_new"/>
828 <menuitem action="file_open"/>
829+ <menu action="menu_file_open_recent">
830+ <menuitem action="recent1"/>
831+ <menuitem action="recent2"/>
832+ <menuitem action="recent3"/>
833+ <menuitem action="recent4"/>
834+ <menuitem action="recent5"/>
835+ </menu>
836 <menuitem action="file_save"/>
837 <menuitem action="imagemenuitem4"/>
838 <separator/>
839@@ -163,20 +187,18 @@
840 <menuitem action="file_close"/>
841 <menuitem action="file_quit"/>
842 </menu>
843- <menu action="menuitem2">
844- <menuitem action="imagemenuitem6"/>
845- <menuitem action="imagemenuitem7"/>
846- <menuitem action="imagemenuitem8"/>
847- <menuitem action="imagemenuitem9"/>
848+ <menu action="menuitem3">
849+ <menuitem action="view_project"/>
850 </menu>
851- <menuitem action="menuitem3"/>
852 <menu action="menuitem4">
853- <menuitem action="imagemenuitem10"/>
854+ <menuitem action="help_about"/>
855 </menu>
856 </menubar>
857 </ui>
858 </object>
859 <object class="GtkWindow" id="window1">
860+ <signal handler="on_window1_delete_event" name="delete_event"/>
861+ <signal handler="on_window1_destroy_event" name="destroy_event"/>
862 <child>
863 <object class="GtkVBox" id="vbox1">
864 <property name="visible">True</property>
865@@ -228,181 +250,188 @@
866 </packing>
867 </child>
868 <child>
869- <object class="GtkHBox" id="hbox_acquisition">
870- <property name="height_request">51</property>
871+ <object class="GtkAspectFrame" id="aspectframe2">
872 <property name="visible">True</property>
873- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
874- <child>
875- <object class="GtkFixed" id="fixed8">
876- <property name="width_request">20</property>
877- <property name="visible">True</property>
878- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
879- </object>
880- </child>
881- <child>
882- <object class="GtkToggleButton" id="acquisition_button">
883- <property name="width_request">56</property>
884- <property name="height_request">46</property>
885- <property name="visible">True</property>
886- <property name="can_focus">True</property>
887- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
888- <property name="has_tooltip">True</property>
889- <property name="tooltip-text" translatable="yes">Activate/Deactivate camera preview</property>
890- <property name="focus_on_click">False</property>
891- <signal handler="on_acquisition_button_toggled" name="toggled"/>
892- <child>
893- <object class="GtkImage" id="acquisition_button_image">
894- <property name="visible">True</property>
895- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
896+ <property name="label_xalign">0</property>
897+ <property name="shadow_type">GTK_SHADOW_NONE</property>
898+ <child>
899+ <object class="GtkHBox" id="hbox_acquisition">
900+ <property name="height_request">51</property>
901+ <property name="visible">True</property>
902+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
903+ <child>
904+ <object class="GtkFixed" id="fixed8">
905+ <property name="width_request">20</property>
906+ <property name="visible">True</property>
907+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
908+ </object>
909+ </child>
910+ <child>
911+ <object class="GtkToggleButton" id="acquisition_button">
912+ <property name="width_request">56</property>
913+ <property name="height_request">46</property>
914+ <property name="visible">True</property>
915+ <property name="can_focus">True</property>
916+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
917+ <property name="has_tooltip">True</property>
918 <property name="tooltip-text" translatable="yes">Activate/Deactivate camera preview</property>
919- <property name="pixbuf">Luciole-dodo.png</property>
920- </object>
921- </child>
922- </object>
923- <packing>
924- <property name="expand">False</property>
925- <property name="fill">False</property>
926- <property name="position">1</property>
927- </packing>
928- </child>
929- <child>
930- <object class="GtkFixed" id="fixed15">
931- <property name="width_request">20</property>
932- <property name="visible">True</property>
933- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
934- </object>
935- <packing>
936- <property name="position">2</property>
937- </packing>
938- </child>
939- <child>
940- <object class="GtkButton" id="snapshot_button">
941- <property name="visible">True</property>
942- <property name="can_focus">True</property>
943- <property name="receives_default">True</property>
944- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
945- <property name="has_tooltip">True</property>
946- <property comments="Capturer une image" name="tooltip-text" translatable="yes">make a snapshot</property>
947- <signal handler="on_button_capture_clicked" name="clicked"/>
948- <accelerator key="c" modifiers="" signal="clicked"/>
949- <child>
950- <object class="GtkImage" id="image5">
951- <property name="visible">True</property>
952- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
953- <property name="tooltip-text" translatable="yes">make a snapshot</property>
954- <property name="pixbuf">capture.png</property>
955- </object>
956- </child>
957- </object>
958- <packing>
959- <property name="expand">False</property>
960- <property name="fill">False</property>
961- <property name="position">3</property>
962- </packing>
963- </child>
964- <child>
965- <object class="GtkFixed" id="fixed11">
966- <property name="width_request">20</property>
967- <property name="visible">True</property>
968- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
969- </object>
970- <packing>
971- <property name="position">4</property>
972- </packing>
973- </child>
974- <child>
975- <object class="GtkVBox" id="vbox9">
976- <property name="width_request">134</property>
977- <property name="visible">True</property>
978- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
979- <child>
980- <object class="GtkCheckButton" id="mixer_checkbutton">
981- <property name="visible">True</property>
982- <property name="can_focus">True</property>
983- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
984- <property name="has_tooltip">True</property>
985- <property name="tooltip-text" translatable="yes">Mixer activation (onion skin)</property>
986- <property name="label" translatable="yes">Mixer</property>
987- <property name="relief">GTK_RELIEF_HALF</property>
988- <property name="draw_indicator">True</property>
989- <signal handler="on_mixer_checkbutton_toggled" name="toggled"/>
990- </object>
991- </child>
992- <child>
993- <object class="GtkHScale" id="alpha_hscale">
994- <property name="visible">True</property>
995- <property name="can_focus">True</property>
996- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
997- <property name="has_tooltip">True</property>
998- <property name="tooltip-text" translatable="yes">Transparency level</property>
999- <property name="update_policy">GTK_UPDATE_DISCONTINUOUS</property>
1000- <property name="adjustment">adjustment1</property>
1001- <property name="digits">0</property>
1002- <property name="value_pos">GTK_POS_LEFT</property>
1003- <signal handler="on_alpha_hscale_value_changed" name="value_changed"/>
1004- </object>
1005- <packing>
1006- <property name="position">1</property>
1007- </packing>
1008- </child>
1009- </object>
1010- <packing>
1011- <property name="expand">False</property>
1012- <property name="fill">False</property>
1013- <property name="position">5</property>
1014- </packing>
1015- </child>
1016- <child>
1017- <object class="GtkFixed" id="fixed22">
1018- <property name="width_request">20</property>
1019- <property name="visible">True</property>
1020- <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
1021- </object>
1022- <packing>
1023- <property name="position">6</property>
1024- </packing>
1025- </child>
1026- <child>
1027- <object class="GtkVBox" id="vbox10">
1028- <property name="visible">True</property>
1029- <child>
1030- <object class="GtkLabel" id="label_fpi">
1031- <property name="width_request">104</property>
1032- <property name="visible">True</property>
1033- <property name="label" translatable="yes">Image per seconds</property>
1034- <property name="justify">GTK_JUSTIFY_CENTER</property>
1035- </object>
1036- <packing>
1037- <property name="fill">False</property>
1038- </packing>
1039- </child>
1040- <child>
1041- <object class="GtkHScale" id="hscale_fps">
1042- <property name="width_request">125</property>
1043- <property name="visible">True</property>
1044- <property name="can_focus">True</property>
1045- <property name="adjustment">adjustment2</property>
1046- <property name="digits">0</property>
1047- <signal handler="on_hscale_fps_value_changed" name="value_changed"/>
1048- <signal handler="on_hscale_fps_format_value" name="format_value"/>
1049- </object>
1050- <packing>
1051- <property name="fill">False</property>
1052- <property name="position">1</property>
1053- </packing>
1054- </child>
1055- </object>
1056- <packing>
1057- <property name="position">7</property>
1058- </packing>
1059- </child>
1060- <child>
1061- <object class="GtkFixed" id="fixed4">
1062- <property name="visible">True</property>
1063- </object>
1064- <packing>
1065- <property name="position">8</property>
1066- </packing>
1067+ <property name="focus_on_click">False</property>
1068+ <signal handler="on_acquisition_button_toggled" name="toggled"/>
1069+ <child>
1070+ <object class="GtkImage" id="acquisition_button_image">
1071+ <property name="visible">True</property>
1072+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
1073+ <property name="tooltip-text" translatable="yes">Activate/Deactivate camera preview</property>
1074+ <property name="pixbuf">luciole-dodo.png</property>
1075+ </object>
1076+ </child>
1077+ </object>
1078+ <packing>
1079+ <property name="expand">False</property>
1080+ <property name="fill">False</property>
1081+ <property name="position">1</property>
1082+ </packing>
1083+ </child>
1084+ <child>
1085+ <object class="GtkFixed" id="fixed15">
1086+ <property name="width_request">20</property>
1087+ <property name="visible">True</property>
1088+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
1089+ </object>
1090+ <packing>
1091+ <property name="position">2</property>
1092+ </packing>
1093+ </child>
1094+ <child>
1095+ <object class="GtkButton" id="snapshot_button">
1096+ <property name="visible">True</property>
1097+ <property name="can_focus">True</property>
1098+ <property name="receives_default">True</property>
1099+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
1100+ <property name="has_tooltip">True</property>
1101+ <property comments="Capturer une image" name="tooltip-text" translatable="yes">make a snapshot</property>
1102+ <signal handler="on_button_capture_clicked" name="clicked"/>
1103+ <accelerator key="c" modifiers="" signal="clicked"/>
1104+ <child>
1105+ <object class="GtkImage" id="image5">
1106+ <property name="visible">True</property>
1107+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
1108+ <property name="tooltip-text" translatable="yes">make a snapshot</property>
1109+ <property name="pixbuf">capture.png</property>
1110+ </object>
1111+ </child>
1112+ </object>
1113+ <packing>
1114+ <property name="expand">False</property>
1115+ <property name="fill">False</property>
1116+ <property name="position">3</property>
1117+ </packing>
1118+ </child>
1119+ <child>
1120+ <object class="GtkFixed" id="fixed11">
1121+ <property name="width_request">20</property>
1122+ <property name="visible">True</property>
1123+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
1124+ </object>
1125+ <packing>
1126+ <property name="position">4</property>
1127+ </packing>
1128+ </child>
1129+ <child>
1130+ <object class="GtkVBox" id="vbox9">
1131+ <property name="width_request">134</property>
1132+ <property name="visible">True</property>
1133+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
1134+ <child>
1135+ <object class="GtkCheckButton" id="mixer_checkbutton">
1136+ <property name="visible">True</property>
1137+ <property name="can_focus">True</property>
1138+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
1139+ <property name="has_tooltip">True</property>
1140+ <property name="tooltip-text" translatable="yes">Mixer activation (onion skin)</property>
1141+ <property name="label" translatable="yes">Mixer</property>
1142+ <property name="relief">GTK_RELIEF_HALF</property>
1143+ <property name="draw_indicator">True</property>
1144+ <signal handler="on_mixer_checkbutton_toggled" name="toggled"/>
1145+ </object>
1146+ </child>
1147+ <child>
1148+ <object class="GtkHScale" id="alpha_hscale">
1149+ <property name="visible">True</property>
1150+ <property name="can_focus">True</property>
1151+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
1152+ <property name="has_tooltip">True</property>
1153+ <property name="tooltip-text" translatable="yes">Transparency level</property>
1154+ <property name="update_policy">GTK_UPDATE_DISCONTINUOUS</property>
1155+ <property name="adjustment">adjustment1</property>
1156+ <property name="digits">0</property>
1157+ <property name="value_pos">GTK_POS_LEFT</property>
1158+ <signal handler="on_alpha_hscale_value_changed" name="value_changed"/>
1159+ </object>
1160+ <packing>
1161+ <property name="position">1</property>
1162+ </packing>
1163+ </child>
1164+ </object>
1165+ <packing>
1166+ <property name="expand">False</property>
1167+ <property name="fill">False</property>
1168+ <property name="position">5</property>
1169+ </packing>
1170+ </child>
1171+ <child>
1172+ <object class="GtkFixed" id="fixed22">
1173+ <property name="width_request">20</property>
1174+ <property name="visible">True</property>
1175+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
1176+ </object>
1177+ <packing>
1178+ <property name="position">6</property>
1179+ </packing>
1180+ </child>
1181+ <child>
1182+ <object class="GtkVBox" id="vbox10">
1183+ <property name="visible">True</property>
1184+ <child>
1185+ <object class="GtkLabel" id="label_fpi">
1186+ <property name="width_request">104</property>
1187+ <property name="visible">True</property>
1188+ <property name="label" translatable="yes">Image per seconds</property>
1189+ <property name="justify">GTK_JUSTIFY_CENTER</property>
1190+ </object>
1191+ <packing>
1192+ <property name="fill">False</property>
1193+ </packing>
1194+ </child>
1195+ <child>
1196+ <object class="GtkHScale" id="hscale_fps">
1197+ <property name="width_request">125</property>
1198+ <property name="visible">True</property>
1199+ <property name="can_focus">True</property>
1200+ <property name="adjustment">adjustment2</property>
1201+ <property name="digits">0</property>
1202+ <signal handler="on_hscale_fps_value_changed" name="value_changed"/>
1203+ <signal handler="on_hscale_fps_format_value" name="format_value"/>
1204+ </object>
1205+ <packing>
1206+ <property name="fill">False</property>
1207+ <property name="position">1</property>
1208+ </packing>
1209+ </child>
1210+ </object>
1211+ <packing>
1212+ <property name="position">7</property>
1213+ </packing>
1214+ </child>
1215+ <child>
1216+ <object class="GtkFixed" id="fixed4">
1217+ <property name="visible">True</property>
1218+ </object>
1219+ <packing>
1220+ <property name="position">8</property>
1221+ </packing>
1222+ </child>
1223+ </object>
1224 </child>
1225 </object>
1226 <packing>
1227@@ -820,12 +849,30 @@
1228 </packing>
1229 </child>
1230 <child>
1231- <object class="GtkStatusbar" id="statusbar1">
1232+ <object class="GtkHBox" id="hbox3">
1233 <property name="visible">True</property>
1234- <property name="spacing">2</property>
1235+ <child>
1236+ <object class="GtkStatusbar" id="statusbar1">
1237+ <property name="visible">True</property>
1238+ <property name="spacing">2</property>
1239+ </object>
1240+ </child>
1241+ <child>
1242+ <object class="GtkProgressBar" id="progressbar_status">
1243+ <property name="width_request">200</property>
1244+ <property name="height_request">10</property>
1245+ </object>
1246+ <packing>
1247+ <property name="expand">False</property>
1248+ <property name="fill">False</property>
1249+ <property name="padding">3</property>
1250+ <property name="position">1</property>
1251+ </packing>
1252+ </child>
1253 </object>
1254 <packing>
1255 <property name="expand">False</property>
1256+ <property name="padding">2</property>
1257 <property name="position">2</property>
1258 </packing>
1259 </child>
1260@@ -872,8 +919,8 @@
1261 <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
1262 <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
1263 <property name="has_separator">False</property>
1264- <property name="program_name">luciole</property>
1265- <property name="version">0.5</property>
1266+ <property name="program_name">Luciole</property>
1267+ <property name="version">0.7</property>
1268 <property name="comments" translatable="yes">
1269 Tool for video capture, for making animated cartoon from image per image
1270 </property>
1271@@ -896,6 +943,7 @@
1272 Inc., 59 Temple Place -
1273 Suite 330, Boston, MA 02111-1307, USA.</property>
1274 <property name="authors">nico : nico@inattendu.org</property>
1275+ <property name="logo">luciole_logo.png</property>
1276 <child internal-child="vbox">
1277 <object class="GtkVBox" id="dialog-vbox9">
1278 <property name="visible">True</property>
1279@@ -1192,9 +1240,9 @@
1280 <object class="GtkFileChooserButton" id="filechooserbutton1">
1281 <property name="visible">True</property>
1282 <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
1283+ <property name="do_overwrite_confirmation">True</property>
1284 <property name="action">GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER</property>
1285 <property name="use_preview_label">False</property>
1286- <property name="do_overwrite_confirmation">True</property>
1287 <property name="title" translatable="yes">Select a folder</property>
1288 </object>
1289 <packing>
1290@@ -1395,4 +1443,38 @@
1291 <action-widget response="-7">button18</action-widget>
1292 </action-widgets>
1293 </object>
1294+ <object class="GtkDialog" id="dialog_project_properties">
1295+ <property name="border_width">5</property>
1296+ <property name="window_position">GTK_WIN_POS_CENTER_ON_PARENT</property>
1297+ <property name="type_hint">GDK_WINDOW_TYPE_HINT_DIALOG</property>
1298+ <property name="has_separator">False</property>
1299+ <child internal-child="vbox">
1300+ <object class="GtkVBox" id="dialog-vbox4">
1301+ <property name="visible">True</property>
1302+ <property name="spacing">2</property>
1303+ <child>
1304+ <placeholder/>
1305+ </child>
1306+ <child internal-child="action_area">
1307+ <object class="GtkHButtonBox" id="dialog-action_area4">
1308+ <property name="visible">True</property>
1309+ <property name="layout_style">GTK_BUTTONBOX_END</property>
1310+ <child>
1311+ <placeholder/>
1312+ </child>
1313+ <child>
1314+ <placeholder/>
1315+ </child>
1316+ <child>
1317+ <placeholder/>
1318+ </child>
1319+ </object>
1320+ <packing>
1321+ <property name="expand">False</property>
1322+ <property name="pack_type">GTK_PACK_END</property>
1323+ </packing>
1324+ </child>
1325+ </object>
1326+ </child>
1327+ </object>
1328 </interface>
1329
1330=== modified file 'lucioLib/gui/dialog.py'
1331--- lucioLib/gui/dialog.py 2009-03-30 22:19:29 +0000
1332+++ lucioLib/gui/dialog.py 2009-04-11 16:56:47 +0000
1333@@ -48,17 +48,19 @@
1334 ErrorMessage = classmethod(ErrorMessage)
1335
1336 def QuestionMessage(cls,parent = None ,message = None ):
1337- """ Display a question message. return True if reponse is YES , False in other case """
1338+ """ Display a question message. return True if reponse is YES , FALSE if response is NO. None
1339+ if window closed without reponse. """
1340 dialog = gtk.MessageDialog(parent = parent,
1341 flags = gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
1342 type = gtk.MESSAGE_QUESTION,
1343- buttons = gtk.BUTTONS_YES_NO,
1344+ buttons = gtk.BUTTONS_YES_NO ,
1345 message_format = message)
1346 dialog.show_all()
1347 result = dialog.run()
1348+ r_val = None
1349 if result == gtk.RESPONSE_YES:
1350 r_val = True
1351- else :
1352+ elif result == gtk.RESPONSE_NO:
1353 r_val = False
1354 dialog.destroy()
1355 return r_val
1356@@ -108,4 +110,4 @@
1357 ImportDialog = classmethod(ImportDialog)
1358
1359
1360-
1361\ No newline at end of file
1362+
1363
1364=== added file 'lucioLib/gui/dialog_project_properties.py'
1365--- lucioLib/gui/dialog_project_properties.py 1970-01-01 00:00:00 +0000
1366+++ lucioLib/gui/dialog_project_properties.py 2009-04-13 19:21:49 +0000
1367@@ -0,0 +1,243 @@
1368+#!/usr/bin/env python
1369+# -*- coding: utf-8 -*-
1370+# -*- Mode: Python -*-
1371+# vi:si:ai:et:sw=4:sts=4:ts=4
1372+#
1373+# Copyright Nicolas Bertrand (nico@inattendu.org), 2009
1374+#
1375+# This file is part of Luciole.
1376+#
1377+# Luciole is free software: you can redistribute it and/or modify
1378+# it under the terms of the GNU General Public License as published by
1379+# the Free Software Foundation, either version 3 of the License, or
1380+# (at your option) any later version.
1381+#
1382+# Luciole is distributed in the hope that it will be useful,
1383+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1384+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1385+# GNU General Public License for more details.
1386+#
1387+# You should have received a copy of the GNU General Public License
1388+# along with Luciole. If not, see <http://www.gnu.org/licenses/>.
1389+#
1390+#
1391+"""
1392+ dialog_project_properties.py : Dialog who display the project properties
1393+"""
1394+from gettext import gettext as _
1395+import gtk
1396+import pango
1397+
1398+from .. import luciole_constants as LCONST
1399+
1400+(LABEL,ENTRY)=range(2)
1401+
1402+class Project_properties(object):
1403+
1404+ # This tow 2 tables descibes how to display project info
1405+ _PROJECT_PREFS = {
1406+ 'project_dir' : {
1407+ 'desc' : _('Project folder :'),
1408+ 'type' : LABEL
1409+ },
1410+ 'project_name' : {
1411+ 'desc' : _('Project name :'),
1412+ 'type' : LABEL
1413+ },
1414+ 'xml_filename' : {
1415+ 'desc' : _('XML file :'),
1416+ 'type' : LABEL
1417+ },
1418+
1419+ 'fpi' : {
1420+ 'desc' : _('Number of frames / image'),
1421+ 'type' : LABEL
1422+ },
1423+ 'hardtype' : {
1424+ 'desc' : _('Device type'),
1425+ 'type' : LABEL
1426+ },
1427+
1428+ }
1429+
1430+ _WEBCAM_PREFS = {
1431+ 'device' : {
1432+ 'desc' : _('Device :'),
1433+ 'type' : ENTRY
1434+ },
1435+ 'name' : {
1436+ 'desc' : _('Webcam name :'),
1437+ 'type' : LABEL
1438+ },
1439+
1440+ 'source_input' : {
1441+ 'desc' : _('Video capture driver :'),
1442+ 'type' : LABEL
1443+ },
1444+ 'width' : {
1445+ 'desc' : _('Video width :'),
1446+ 'type' : LABEL
1447+ },
1448+ 'height' : {
1449+ 'desc' : _('Video height :'),
1450+ 'type' : LABEL
1451+ },
1452+ }
1453+
1454+
1455+ _title = _('Project properties')
1456+
1457+ def __init__(self,main_window, project) :
1458+ """ create a Dialog with project properties and disqpay it"""
1459+
1460+ self._dialog = gtk.Dialog ( self._title,
1461+ main_window,
1462+ gtk.DIALOG_MODAL | gtk.DIALOG_DESTROY_WITH_PARENT,
1463+ ( gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL,
1464+ gtk.STOCK_CLOSE,gtk.RESPONSE_CLOSE,
1465+ gtk.STOCK_APPLY,gtk.RESPONSE_APPLY)
1466+ )
1467+ self._project = project
1468+
1469+ # make dialog displays
1470+ self.make_widget()
1471+ self._dialog.show_all()
1472+
1473+ # run dialog
1474+ result = self._dialog.run()
1475+
1476+ # wait for reponse
1477+ # nbd@grape : missing what to do when info changed
1478+ # probably add callback to update project
1479+ if result == gtk.RESPONSE_CANCEL :
1480+ self._dialog.destroy()
1481+ elif result == gtk.RESPONSE_CLOSE :
1482+ self._dialog.destroy()
1483+
1484+
1485+ def make_title_label(self, text) :
1486+ """ set a title label (i.e 1st column of table): play wiyh pango"""
1487+ label= gtk.Label()
1488+ label.set_text("%s"%text)
1489+ attrs = pango.AttrList()
1490+ attrs.insert( pango.AttrWeight(pango.WEIGHT_BOLD,0, -1))
1491+ label.set_attributes(attrs)
1492+
1493+ # positionning of label
1494+ label.set_alignment(xalign=0.0,yalign=0.5) # left justification of label
1495+ # Insert label into the upper left quadrant of the table
1496+ label.show()
1497+ return label
1498+
1499+ def make_table_title(self,title) :
1500+ """ set a Table title : play with pango"""
1501+ label= gtk.Label()
1502+ label.set_text(title)
1503+ attrs = pango.AttrList()
1504+ attrs.insert( pango.AttrWeight(pango.WEIGHT_BOLD,0, -1))
1505+ attrs.insert( pango.AttrSize(18000,0, -1))
1506+ label.set_attributes(attrs)
1507+
1508+ # positionning of label
1509+ label.set_alignment(xalign=0.5,yalign=0.5) # center
1510+ # Insert label into the upper left quadrant of the table
1511+ label.show()
1512+ return label
1513+
1514+
1515+
1516+ def make_table_row(self,table,row,key):
1517+ """ Craate the row for the gtk.Table used for project properties display """
1518+ label= self.make_title_label(self._PROJECT_PREFS[key]['desc'])
1519+ table.attach(label, 0, 1, row, row +1 ,xpadding = 10 )
1520+
1521+ widget = None
1522+ if key == 'hardtype' :
1523+ widget = gtk.Label(LCONST.HardTypeName[self._project[key]] )
1524+ else :
1525+ if self._PROJECT_PREFS[key]['type'] == LABEL :
1526+ widget = gtk.Label(self._project[key])
1527+
1528+ widget.set_alignment(xalign=0.0,yalign=0.5) # left justification of label
1529+ widget.show()
1530+ table.attach(widget, 1, 2, row, row+1,xpadding = 10 )
1531+
1532+ def make_table_webcam_row(self,table,row,key):
1533+ """ Craate the row for the gtk.Table used for webcam properties display """
1534+ label= self.make_title_label(self._WEBCAM_PREFS[key]['desc'])
1535+ table.attach(label, 0, 1, row, row +1 ,xpadding = 10 )
1536+
1537+ widget = None
1538+ if self._WEBCAM_PREFS[key]['type'] == ENTRY :
1539+ widget = gtk.Entry()
1540+ widget.set_alignment(xalign=0.0) # left justification of label
1541+ else:
1542+ widget = gtk.Label()
1543+ widget.set_alignment(xalign=0.0,yalign=0.5) # left justification of label
1544+ widget.set_text(self._project['webcam_data'][key])
1545+
1546+ widget.show()
1547+ table.attach(widget, 1, 2, row, row+1,xpadding = 10 )
1548+
1549+
1550+ def make_webcam_data(self) :
1551+ """ build widgets for display of webcam properties"""
1552+ self._dialog.vbox.pack_start( child = gtk.HSeparator(),
1553+ expand = True,
1554+ fill = True,
1555+ padding = 5
1556+ )
1557+
1558+ label = self.make_table_title(_('Webcam properties'))
1559+ self._dialog.vbox.pack_start( child = label,
1560+ expand = True,
1561+ fill = True,
1562+ padding = 10
1563+ )
1564+
1565+ table = gtk.Table()
1566+ table.set_homogeneous(False)
1567+ self.make_table_webcam_row(table,0,'name')
1568+ self.make_table_webcam_row(table,1,'width')
1569+ self.make_table_webcam_row(table,2,'height')
1570+ self.make_table_webcam_row(table,3,'source_input')
1571+ self.make_table_webcam_row(table,4,'device')
1572+
1573+ self._dialog.vbox.pack_start( child = table,
1574+ expand = True,
1575+ fill = True,
1576+ padding = 10
1577+ )
1578+
1579+ def make_widget(self) :
1580+ """ build widgets for display of project properties """
1581+ label = self.make_table_title(self._title)
1582+ self._dialog.vbox.pack_start( child = label,
1583+ expand = True,
1584+ fill = True,
1585+ padding = 10
1586+ )
1587+
1588+ table = gtk.Table(2, 2, True)
1589+ table.set_homogeneous(False)
1590+ self.make_table_row(table,0,'project_name')
1591+ self.make_table_row(table,1,'project_dir')
1592+ self.make_table_row(table,2,'xml_filename')
1593+ self.make_table_row(table,3,'fpi')
1594+ self.make_table_row(table,4,'hardtype')
1595+ table.show()
1596+ self._dialog.vbox.pack_start( child = table,
1597+ expand = True,
1598+ fill = True,
1599+ padding = 10
1600+ )
1601+
1602+ if self._project['hardtype'] == LCONST.WEBCAM :
1603+ # if webcam based project display webcam properties
1604+ self.make_webcam_data()
1605+
1606+
1607+
1608+
1609+
1610+
1611
1612=== modified file 'lucioLib/gui/gui_controller.py'
1613--- lucioLib/gui/gui_controller.py 2009-04-10 19:50:00 +0000
1614+++ lucioLib/gui/gui_controller.py 2009-04-13 19:42:11 +0000
1615@@ -45,8 +45,12 @@
1616 import dialog as GDIALOG
1617 import open_project as GOF
1618 import luciole_export_window as GEXPORT
1619+import open_project_widget as GOPEN
1620+import dialog_project_properties as GDIALOG_PROJ
1621 from .. import luciole_constants as LCONST
1622
1623+import _version
1624+
1625 # nbd@grape : APP NAME place to change
1626
1627 APP_NAME = "luciole"
1628@@ -57,6 +61,50 @@
1629 main file for gui management
1630 gui init and call backs
1631 """
1632+class Gui_status_controller(object) :
1633+
1634+ def __init__(self, status_bar, progress_bar=None) :
1635+ """ init gui status controller """
1636+ self._status_bar = status_bar
1637+ self._context_id = self._status_bar.get_context_id("Statusbar example")
1638+ self._progress_bar = progress_bar
1639+
1640+ def on_progress(self,msg,ratio) :
1641+ """ update status and progress bar """
1642+ self._status_bar.push(self._context_id, msg)
1643+ if self._progress_bar != None :
1644+ # if a ratio is given update progress bar with set fraction if not update with just a pulse
1645+ if ratio != None :
1646+ self._progress_bar.set_fraction(ratio)
1647+ else :
1648+ self._progress_bar.pulse()
1649+
1650+
1651+ def start(self,msg) :
1652+ """ Start progress/status bar """
1653+ self._status_bar.push(self._context_id, msg)
1654+ if self._progress_bar != None :
1655+ self._progress_bar.show()
1656+ self._progress_bar.set_fraction(0.0)
1657+
1658+ def stop(self,msg) :
1659+ """ Stop progress/status bar """
1660+ self._status_bar.push(self._context_id, msg)
1661+ if self._progress_bar != None :
1662+ self._progress_bar.set_fraction(1.0)
1663+ self._progress_bar.hide()
1664+
1665+ def display_message(self,msg) :
1666+ """ display a message on status bar """
1667+ self._status_bar.push(self._context_id, msg)
1668+
1669+ def clear_message(self,msg) :
1670+ """ clear a message on status bar """
1671+ self._status_bar.pop(self._context_id)
1672+
1673+
1674+
1675+
1676
1677 class Gui_controller(object):
1678 """ class handling interface with GUI/glade """
1679@@ -80,6 +128,11 @@
1680 self.PreviewObj.pixbufToDisplay = x
1681 pixbufToDisplay = property(f_get_pixbufToDisplay,f_set_pixbufToDisplay,None,"Pixbuf to display")
1682
1683+ def f_get_ui_manager(self) : return self.builder.get_object('uimanager1')
1684+ ui_manager = property(f_get_ui_manager,None,None, 'The GUI UI manager')
1685+
1686+ def f_get_status_progress_bar(self) : return Gui_status_controller(self._status_bar,self._status_progress_bar)
1687+ status_progress_bar = property(f_get_status_progress_bar,None,None, 'The status progress bar')
1688
1689 def __init__(self, ctrl_obj) :
1690
1691@@ -151,7 +204,6 @@
1692 'on_button_capture_to_montage_clicked' :self.on_button_capture_to_montage_clicked,
1693 'on_button_import_clicked' : self.on_button_import_clicked,
1694 'on_button_play_toggled' : self.on_button_play_toggled,
1695- 'on_button_clear_clicked' : self.on_button_clear_clicked, # test button
1696 'on_mixer_checkbutton_toggled' : self.on_mixer_checkbutton_toggled,
1697 'on_alpha_hscale_value_changed' : self.on_alpha_hscale_value_changed,
1698 'on_hscale_fps_value_changed' : self.on_hscale_fps_value_changed,
1699@@ -164,6 +216,12 @@
1700 'on_file_export_activate' : self.on_file_export_activate,
1701 'on_file_quit_activate' : self.on_file_quit_activate,
1702 'on_file_close_activate' : self.on_file_close_activate,
1703+ 'on_view_project_activate' : self.on_view_project_activate,
1704+ 'on_help_about_activate' : self.on_help_about_activate,
1705+
1706+ 'on_window1_delete_event' : self.on_window_delete_event,
1707+ 'on_window1_destroy_event' : self.on_window_delete_event,
1708+
1709
1710 }
1711 self.builder.connect_signals(callbacks)
1712@@ -190,17 +248,22 @@
1713 self._play_button = self.builder.get_object('button_play')
1714 self._play_pause_image = self.builder.get_object('image_play_pause')
1715
1716+ # widgets for project init
1717+ self._init_project_buttons()
1718+
1719 # acquistion buttons initialization
1720 self._init_acquistion_buttons()
1721
1722- # fpi widget init
1723- self._init_fpi_buttons()
1724+
1725+ #status bar
1726+ self._status_bar = self.builder.get_object('statusbar1')
1727+ self._status_progress_bar = self.builder.get_object('progressbar_status')
1728+
1729+
1730
1731 def _init_acquistion_buttons(self) :
1732 """ acquisition buttons init """
1733 #get objects from glade
1734- self._acq_button = self.builder.get_object('acquisition_button')
1735- self._acq_button_image = self.builder.get_object('acquisition_button_image')
1736 self._snapshot_button = self.builder.get_object('snapshot_button')
1737 self._mixer_checkbutton = self.builder.get_object('mixer_checkbutton')
1738 self._alpha_hscale = self.builder.get_object('alpha_hscale')
1739@@ -228,7 +291,6 @@
1740 """ Set acquisition for acquisition show """
1741 # wake up luciole; i.e. change acquisition button logo
1742 self._acq_button_image.set_from_pixbuf(self._pxb_luciole_wakedup)
1743-
1744 self._snapshot_button.show() # snapshot button hide by default
1745 self._mixer_checkbutton.show() # mixer checkbox hide by default
1746 # if toggle butoon not acive : acivate it
1747@@ -236,22 +298,51 @@
1748 # the set_active function cause the toggle button signal emitted
1749 self._acq_button.set_active(True)
1750
1751- def _init_fpi_buttons(self) :
1752+ def _init_project_buttons(self) :
1753 """ initialisation of fpi buttons """
1754+
1755+ # get Hbox with acquistion widgets nas prent of this box
1756+ self._hbox_acq = self.builder.get_object('hbox_acquisition')
1757+ self._parent_hbox_acq = self._hbox_acq.get_parent()
1758+
1759+ # create the open/new project widget
1760+ self._open_project_wdg = GOPEN.Gui_open_project_widget(self.on_file_new_activate,self.on_file_open_activate)
1761+
1762+ # set open/new project widgets
1763+ self.project_open_widgets()
1764+
1765 # get fpi hscale
1766+ self._acq_button = self.builder.get_object('acquisition_button')
1767+ self._acq_button_image = self.builder.get_object('acquisition_button_image')
1768 self._fpi_hscale = self.builder.get_object('hscale_fps')
1769 self._fpi_label = self.builder.get_object('label_fpi')
1770- self.fpi_widget_hide()
1771-
1772- def fpi_widget_hide(self) :
1773- """ hide fpi wigets """
1774- self._fpi_hscale.hide()
1775- self._fpi_label.hide()
1776-
1777- def fpi_widget_show(self) :
1778- """ show fpi widgets """
1779- self._fpi_hscale.show()
1780- self._fpi_label.show()
1781+
1782+
1783+ def project_open_widgets(self) :
1784+ """ When this function is called the project open/new buttons are dispalyed
1785+ The acquisistion buttons are hidden
1786+ """
1787+ child = self._parent_hbox_acq.get_child()
1788+ if child != None :
1789+ self._parent_hbox_acq.remove(child)
1790+ self._parent_hbox_acq.add(self._open_project_wdg)
1791+
1792+ #self._acq_button.hide()
1793+ #self._fpi_hscale.hide()
1794+ #self._fpi_label.hide()
1795+
1796+ def project_acquistion_widgets(self) :
1797+ """ When this function is called the acquisition widgets are displayed.
1798+ The open.new buttons are hidden
1799+ """
1800+ child = self._parent_hbox_acq.get_child()
1801+ if child != None :
1802+ self._parent_hbox_acq.remove(child)
1803+ self._parent_hbox_acq.add(self._hbox_acq)
1804+
1805+ #self._acq_button.show()
1806+ #self._fpi_hscale.show()
1807+ #self._fpi_label.show()
1808
1809
1810
1811@@ -373,7 +464,6 @@
1812 return filename
1813
1814 def set_programbar(self,text, isModified = False) :
1815-
1816 if isModified == True :
1817 self.window.set_title( "%s : %s (*)"%(APP_NAME,text ) )
1818 else :
1819@@ -414,7 +504,16 @@
1820 if l_fpi == fpi :
1821 index = k
1822 self._fpi_hscale.set_value(float(index))
1823-
1824+
1825+
1826+ def quit(self):
1827+ """ quit appluication/gui """
1828+ gtk.main_quit()
1829+
1830+
1831+ def display_project_properties(self,project) :
1832+ GDIALOG_PROJ.Project_properties(self.window,
1833+ project)
1834
1835 ############################################################################
1836 # glade/XML builder callbacks
1837@@ -538,8 +637,34 @@
1838 print "file close activate "
1839 self.ctrl_obj.close()
1840
1841- def on_button_clear_clicked(self,widget) :
1842- print "BUTTON clear clicked"
1843- self.PreviewObj.isDisplayAllowed = False
1844-
1845-
1846+ def on_file_close_activate(self,widget):
1847+ print "file close activate "
1848+ self.ctrl_obj.close()
1849+
1850+ def on_view_project_activate(self,widget):
1851+ print " view project ptoperties "
1852+ self.ctrl_obj.project_properties()
1853+
1854+
1855+ def __UpdateAbout(self, aboutWidget) :
1856+ """ Update with version of about window"""
1857+ strRev= '%(revno)d' % _version.version_info
1858+ strBranch = '%(branch_nick)s'% _version.version_info
1859+ strVersion = "\n %s (%s)"%(strBranch,strRev)
1860+ aboutWidget.set_version(strVersion)
1861+
1862+ def on_help_about_activate(self,widget):
1863+ print "On help about activate"
1864+ aboutdialog = self.builder.get_object('aboutdialog')
1865+ self.__UpdateAbout(aboutdialog)
1866+ aboutdialog.show_all()
1867+ result = aboutdialog.run()
1868+ aboutdialog.destroy()
1869+
1870+
1871+ def on_window_delete_event(self,widget,event):
1872+ print " destroy/delete event : ", event.type
1873+ self.ctrl_obj.quit()
1874+ # the 'return true' avoid the automatic close of application
1875+ return True
1876+
1877
1878=== modified file 'lucioLib/gui/luciole_drawaera.py'
1879--- lucioLib/gui/luciole_drawaera.py 2009-04-10 10:22:46 +0000
1880+++ lucioLib/gui/luciole_drawaera.py 2009-04-13 20:10:28 +0000
1881@@ -33,13 +33,11 @@
1882 @version 1
1883 """
1884
1885-from .. import luciole_global as MG
1886-from .. import luciole_acquisition as MA
1887-from .. import luciole_tools as MT
1888-from .. import luciole_exceptions as M_EXCEP
1889+from .. import luciole_tools as LT
1890+from .. import luciole_exceptions as L_EXCEP
1891 import gtk
1892
1893-class PreviewPixbuf(MT.Singleton) :
1894+class PreviewPixbuf(LT.Singleton) :
1895 """ Class for mamaging the display of image/pixbuf in the Preview window (drawing area)"""
1896
1897 def f_get_pixbufToDisplay(self) :
1898@@ -71,7 +69,7 @@
1899 """ init of module PreviewPixbuf"""
1900 if DAwidget == None :
1901 # raise exception no drawarea widget given
1902- raise M_EXCEP.LucioException,"No Drawing area defined"
1903+ raise L_EXCEP.LucioException,"No Drawing area defined"
1904 else :
1905 self.__DAwidget = DAwidget #drawingArea widget
1906 self.__DAwidget.connect("expose-event",self.on_expose_event)
1907@@ -118,34 +116,4 @@
1908 self.displayDefault()
1909
1910
1911-class CameraPixbuf(PreviewPixbuf) :
1912- """ Class for mamaging the display of image/pixbuf in the Camera window (drawing area). Inherited
1913- from PreviewPixbuf. """
1914-
1915- def __init__(self,DAwidget):
1916- """ init of module CameraPixbuf."""
1917- PreviewPixbuf.__init__(self,DAwidget)
1918-
1919- def _PreviewImage(self,pixbuf):
1920- """ Display of the pixbuf image in the Camera drawing area.
1921- An image can be displayed only when streaming display is not active."""
1922- #test if acquisition obj exist
1923- if not MA.luciole_acquisition.__name__ in MG.luciole_global.dico:
1924- # pas d object acquisition on peut afficher
1925- PreviewPixbuf._PreviewImage(self,pixbuf)
1926- elif not MG.luciole_global.dico[MA.luciole_acquisition.__name__].IsStreamingActive :
1927- # streaming is not active, Display is allowed
1928- PreviewPixbuf._PreviewImage(self,pixbuf)
1929-
1930- def displayDefault(self):
1931- """ When no image/pixbuf need to be displayed, a black background screen is displayed
1932- The background is dispalyed when streaming display is not active."""
1933- #test if acquisition obj exist
1934- if not MA.luciole_acquisition.__name__ in MG.luciole_global.dico:
1935- # pas d object acquisition on peut afficher
1936- PreviewPixbuf.displayDefault(self)
1937- elif not MG.luciole_global.dico[MA.luciole_acquisition.__name__].IsStreamingActive :
1938- # streaming is not active, Display is allowed
1939- PreviewPixbuf.displayDefault(self)
1940-
1941-
1942+
1943
1944=== added file 'lucioLib/gui/open_project_widget.py'
1945--- lucioLib/gui/open_project_widget.py 1970-01-01 00:00:00 +0000
1946+++ lucioLib/gui/open_project_widget.py 2009-04-13 11:02:22 +0000
1947@@ -0,0 +1,69 @@
1948+#!/usr/bin/env python
1949+# -*- coding: utf-8 -*-
1950+# -*- Mode: Python -*-
1951+# vi:si:ai:et:sw=4:sts=4:ts=4
1952+#
1953+# Copyright Nicolas Bertrand (nico@inattendu.org), 2009
1954+#
1955+# This file is part of Luciole.
1956+#
1957+# Luciole is free software: you can redistribute it and/or modify
1958+# it under the terms of the GNU General Public License as published by
1959+# the Free Software Foundation, either version 3 of the License, or
1960+# (at your option) any later version.
1961+#
1962+# Luciole is distributed in the hope that it will be useful,
1963+# but WITHOUT ANY WARRANTY; without even the implied warranty of
1964+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1965+# GNU General Public License for more details.
1966+#
1967+# You should have received a copy of the GNU General Public License
1968+# along with Luciole. If not, see <http://www.gnu.org/licenses/>.
1969+#
1970+#
1971+"""
1972+ widgets who propose open/new project when no project are loaded
1973+"""
1974+
1975+import gtk
1976+from gettext import gettext as _
1977+
1978+class Gui_open_project_widget(gtk.HButtonBox) :
1979+ """ widget for diplay New/open project buttons """
1980+
1981+ # some constants for widget
1982+ _WIDTH_REQUEST =-1
1983+ _HEIGHT_REQUEST = 51 # same value as hbox_acquisition in glade
1984+ _IMAGE_POS = gtk.POS_TOP
1985+
1986+ def __init__(self,cb_new,cb_open) :
1987+ super(Gui_open_project_widget,self).__init__()
1988+
1989+ # ste widget properties
1990+ self.set_name('hbox_open_project')
1991+ self.set_size_request(self._WIDTH_REQUEST, self._HEIGHT_REQUEST)
1992+ self.set_layout(gtk.BUTTONBOX_SPREAD)
1993+ self.set_spacing(25)
1994+ self.set_homogeneous(True)
1995+
1996+ # create New button project
1997+ msg = _('Create a new project')
1998+ Button = gtk.Button(msg)
1999+ Button.set_image(gtk.image_new_from_stock(gtk.STOCK_NEW,gtk.ICON_SIZE_BUTTON))
2000+ Button.set_property('image-position',self._IMAGE_POS)
2001+ Button.connect('clicked',cb_new)
2002+ self.pack_start(Button,expand = False, fill = False)
2003+ Button.show()
2004+
2005+ # create open button project
2006+ msg = _('Open an existing project')
2007+ Button = gtk.Button(msg)
2008+ Button.set_image(gtk.image_new_from_stock(gtk.STOCK_OPEN,gtk.ICON_SIZE_BUTTON))
2009+ Button.set_property('image-position',self._IMAGE_POS)
2010+ Button.connect('clicked',cb_open)
2011+ self.pack_start(Button,expand = False, fill = False)
2012+ Button.show()
2013+
2014+ # show widget
2015+ self.show()
2016+
2017
2018=== removed directory 'lucioLib/lucioImageCapture'
2019=== removed file 'lucioLib/lucioImageCapture/__init__.py'
2020--- lucioLib/lucioImageCapture/__init__.py 2009-03-08 18:06:41 +0000
2021+++ lucioLib/lucioImageCapture/__init__.py 1970-01-01 00:00:00 +0000
2022@@ -1,25 +0,0 @@
2023-#!/usr/bin/env python
2024-# -*- coding: utf-8 -*-
2025-# -*- Mode: Python -*-
2026-# vi:si:ai:et:sw=4:sts=4:ts=4
2027-#
2028-#
2029-# Copyright Nicolas Bertrand (nico@inattendu.org), 2009
2030-#
2031-# This file is part of Luciole.
2032-#
2033-# Luciole is free software: you can redistribute it and/or modify
2034-# it under the terms of the GNU General Public License as published by
2035-# the Free Software Foundation, either version 3 of the License, or
2036-# (at your option) any later version.
2037-#
2038-# Luciole is distributed in the hope that it will be useful,
2039-# but WITHOUT ANY WARRANTY; without even the implied warranty of
2040-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2041-# GNU General Public License for more details.
2042-#
2043-# You should have received a copy of the GNU General Public License
2044-# along with Luciole. If not, see <http://www.gnu.org/licenses/>.
2045-#
2046-#
2047-from luciole_capture_image import *
2048
2049=== removed file 'lucioLib/lucioImageCapture/luciole_capture_image.py'
2050--- lucioLib/lucioImageCapture/luciole_capture_image.py 2009-03-08 18:06:41 +0000
2051+++ lucioLib/lucioImageCapture/luciole_capture_image.py 1970-01-01 00:00:00 +0000
2052@@ -1,177 +0,0 @@
2053-#!/usr/bin/env python
2054-# -*- coding: utf-8 -*-
2055-#
2056-#
2057-# Copyright Nicolas Bertrand (nico@inattendu.org), 2009
2058-#
2059-# This file is part of Luciole.
2060-#
2061-# Luciole is free software: you can redistribute it and/or modify
2062-# it under the terms of the GNU General Public License as published by
2063-# the Free Software Foundation, either version 3 of the License, or
2064-# (at your option) any later version.
2065-#
2066-# Luciole is distributed in the hope that it will be useful,
2067-# but WITHOUT ANY WARRANTY; without even the implied warranty of
2068-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2069-# GNU General Public License for more details.
2070-#
2071-# You should have received a copy of the GNU General Public License
2072-# along with Luciole. If not, see <http://www.gnu.org/licenses/>.
2073-#
2074-#
2075-import os
2076-import sys
2077-import dircache
2078-import fnmatch
2079-import shutil
2080-import time
2081-import subprocess as SP
2082-import threading
2083-from .. import luciole_exceptions as M_EXCEP
2084-
2085-class luciole_capture_image(object) :
2086- """ class for acquiring and transformaing images from an external source"""
2087-
2088- class mythread(threading.Thread) :
2089- def __init__(self,myId,convert_cmd) :
2090- self.myId = myId
2091- self.convert_cmd = convert_cmd
2092- threading.Thread.__init__(self)
2093- def run(self):
2094- print " converting %s with id %s"%(self.convert_cmd,self.myId)
2095- pconvert =SP.call(self.convert_cmd,shell=True)
2096-
2097-
2098- ############################################################
2099- # PROPERTIES DECLARATION
2100- ############################################################
2101- def _get_ImageSourcePath(self) : return self._imageSourcePath
2102- def _set_ImageSourcePath(self,path) :
2103- try :
2104- self._imageSourcePath =self.mkdirs(path)
2105- except M_EXCEP.LucioException,err :
2106- raise M_EXCEP.LucioException, err.message
2107-
2108- imageSourcePath=property(_get_ImageSourcePath,_set_ImageSourcePath,doc ="Path from where the image souce is")
2109-
2110- def _get_rawImageStorePath(self) : return self._rawImageStorePath
2111- def _set_rawImageStorePath(self,path) :
2112- try :
2113- self._rawImageStorePath =self.mkdirs(path)
2114- except M_EXCEP.LucioException,err :
2115- raise M_EXCEP.LucioException, err.message
2116- rawImageStorePath=property(_get_rawImageStorePath,_set_rawImageStorePath,doc ="Path to store the raw images")
2117-
2118- def _get_scaledImageStorePath(self) : return self._scaledImageStorePath
2119- def _set_scaledImageStorePath(self,path) :
2120- try :
2121- self._scaledImageStorePath=self.mkdirs(path)
2122- except M_EXCEP.LucioException,err :
2123- raise M_EXCEP.LucioException, err.message
2124- scaledImageStorePath=property(_get_scaledImageStorePath,_set_scaledImageStorePath,doc ="Path to store the scaled images")
2125-
2126-
2127- ############################################################
2128- ### CONSTRUCTOR
2129- ############################################################
2130- def __init__(self,imageSourcePath,rawImageStorePath,scaledImageStorePath) :
2131- """ luciole_capture_image class_constructor"""
2132- # properties local variable init
2133- try :
2134- self._imageSourcePath =self.mkdirs(imageSourcePath)
2135- except M_EXCEP.LucioException,err :
2136- raise M_EXCEP.LucioException, err.message
2137- try :
2138- self._rawImageStorePath =self.mkdirs(rawImageStorePath)
2139- except M_EXCEP.LucioException,err :
2140- print err.message
2141- try :
2142- self._scaledImageStorePath =self.mkdirs(scaledImageStorePath)
2143- except M_EXCEP.LucioException,err :
2144- print err.message
2145-
2146-
2147- ############################################################
2148- ### PUBLIC METHODS
2149- ############################################################
2150-
2151- def test_image_source(self) :
2152- """ test if the image source is available.
2153- Return True if it is detected. """
2154- Valid = False
2155- if os.path.exists(self._imageSourcePath): Valid =True
2156- return Valid
2157-
2158- def get_images_from_source(self) :
2159- """ method to get all the images from the source"""
2160- fl = dircache.listdir(self._imageSourcePath)
2161- patternMatch="*.[Jj][Pp][GgeE]*"
2162- filterList =fnmatch.filter(fl,patternMatch)
2163- time_cpStart =time.time()
2164- for file in filterList :
2165- shutil.copy2(os.path.join(self._imageSourcePath,file),self._rawImageStorePath)
2166- time_cpStop =time.time()
2167- print " Copy duration %s s "%(time_cpStop-time_cpStart)
2168-
2169- #transform image
2170- t0 = os.times()
2171- #stdoutmutex = threading.Lock()
2172- threads=[]
2173- count = 0
2174- for file in filterList :
2175- convert_cmd = "convert "+os.path.join(self._rawImageStorePath,file) + " -resize 720x576\> -size 720x576 xc:black +swap -gravity center -composite "+os.path.join(self.scaledImageStorePath,file)
2176- #print convert_cmd
2177- #thread.start_new(self.image_conversion,(convert_cmd,))
2178- #self.image_conversion(convert_cmd)
2179- thread =self.mythread(count,convert_cmd)
2180- thread.start()
2181- threads.append(thread)
2182- count = count+1
2183- for thread in threads:
2184- thread.join()
2185- print " Main thread exiting"
2186- t1=os.times()
2187- print " Conversion duration %s s"%(t1[4] - t0[4])
2188- print " sub process time %s s"%(t1[2] - t0[2])
2189-
2190- filterList = map(lambda x:os.path.join(self.scaledImageStorePath,x),filterList)
2191- return filterList
2192-
2193-# def image_conversion(self,convert_cmd) :
2194-# pconvert =SP.call(convert_cmd,shell=True)
2195-
2196- ############################################################
2197- ### PRIVATE METHODS
2198- ############################################################
2199- def mkdirs(self,Path) :
2200- """ makedirs used for import"""
2201- if not os.path.exists(Path):
2202- try :
2203- os.makedirs(Path)
2204- except OSError,err :
2205- raise M_EXCEP.LucioException, err.strerror + " on : "+err.filename
2206- finally :
2207- ValidPath=Path
2208- else :
2209- ValidPath=Path
2210- print "chemin =", ValidPath
2211- return ValidPath
2212-
2213-
2214-#try :
2215-# X=luciole_capture_image('/var/log/photos','/var/log/src','/var/log/capture')
2216-#except M_EXCEP.LucioException,err :
2217-# print err.message
2218-
2219-#try :
2220-# X=luciole_capture_image('photos','src','capture')
2221-#except M_EXCEP.LucioException,err :
2222-# print err.message
2223-#else :
2224-# X.get_images_from_source()
2225-
2226-#while 1:
2227-# if raw_input() == 'q' : break
2228-
2229-
2230
2231=== modified file 'lucioLib/luciole_acquisition.py'
2232--- lucioLib/luciole_acquisition.py 2009-04-10 17:24:54 +0000
2233+++ lucioLib/luciole_acquisition.py 2009-04-13 20:10:28 +0000
2234@@ -30,7 +30,6 @@
2235 import luciole_constants as LCONST
2236 import luciole_exceptions as M_EXCEP
2237 import os.path
2238-import lucioImageCapture
2239
2240
2241 class luciole_acquisition(object) :
2242@@ -185,9 +184,7 @@
2243 luciole_acquisition.__init__(self,display,False,LCONST.DIGICAM,None)
2244 try :
2245 pass
2246- # WARNING the src dir object is missing !!!
2247- # to define coorectly
2248- # self.importObj = lucioImageCapture.luciole_capture_image(os.path.expandvars('$HOME'),self.ProjectObj.src_dir,self.ProjectObj.capture_dir)
2249+ # tbd
2250 except M_EXCEP.LucioException, err:
2251 print err.message
2252
2253
2254=== removed file 'lucioLib/luciole_class.py'
2255--- lucioLib/luciole_class.py 2009-03-08 18:06:41 +0000
2256+++ lucioLib/luciole_class.py 1970-01-01 00:00:00 +0000
2257@@ -1,794 +0,0 @@
2258-#!/usr/bin/env python
2259-# -*- coding: UTF-8 -*-
2260-#
2261-# Copyright Nicolas Bertrand (nico@inattendu.org), 2009
2262-#
2263-# This file is part of Luciole.
2264-#
2265-# Luciole is free software: you can redistribute it and/or modify
2266-# it under the terms of the GNU General Public License as published by
2267-# the Free Software Foundation, either version 3 of the License, or
2268-# (at your option) any later version.
2269-#
2270-# Luciole is distributed in the hope that it will be useful,
2271-# but WITHOUT ANY WARRANTY; without even the implied warranty of
2272-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2273-# GNU General Public License for more details.
2274-#
2275-# You should have received a copy of the GNU General Public License
2276-# along with Luciole. If not, see <http://www.gnu.org/licenses/>.
2277-#
2278-#
2279-
2280-#
2281-# Copyright Nicolas Bertrand (nico@inattendu.org), 2009
2282-#
2283-# This file is part of Luciole.
2284-#
2285-# Luciole is free software: you can redistribute it and/or modify
2286-# it under the terms of the GNU General Public License as published by
2287-# the Free Software Foundation, either version 3 of the License, or
2288-# (at your option) any later version.
2289-#
2290-# Luciole is distributed in the hope that it will be useful,
2291-# but WITHOUT ANY WARRANTY; without even the implied warranty of
2292-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2293-# GNU General Public License for more details.
2294-#
2295-# You should have received a copy of the GNU General Public License
2296-# along with Luciole. If not, see <http://www.gnu.org/licenses/>.
2297-#
2298-#
2299-
2300-import pygtk
2301-pygtk.require("2.0")
2302-
2303-import os.path
2304-import shutil
2305-import gtk
2306-import gtk.glade
2307-import luciole_global as MG
2308-import luciole_file_in_out as MF
2309-import luciole_constants as MCONST
2310-import luciole_tools as MT
2311-import luciole_exceptions as M_EXCEP
2312-import gobject
2313-import threading
2314-
2315-import time
2316-
2317-from gettext import gettext as _
2318-
2319-class MyThumbThread(threading.Thread):
2320- """ Thread class for genertion of a thumbnail"""
2321-
2322- def __init__(self,image,index,liststore):
2323- """ class creation for thread :
2324- inputs are ;
2325- image : image object to generate thumbnail
2326- index : position of image in image list
2327- liststore : treeview model
2328- """
2329- super(MyThumbThread, self).__init__()
2330- self.quit = False
2331- self.image = image
2332- self.index = index
2333- self.liststore = liststore
2334-
2335- def updateTreeview(self, liststore, image,index):
2336- """ callback to be executed when thread run is finished.
2337- Update the treeview with the generated thumnbnail"""
2338- iter = liststore.get_iter( (index,) ) # get iter from treeview
2339- liststore.set_value(iter,LucioleGtkTreeView.COL_PIXBUF,image.pixbuf_icon) # update of treeview
2340- return False
2341-
2342- def run(self):
2343- """ Thread execution --> generation of thumbnail"""
2344- self.image.load_pixbuf_icon()
2345- gobject.idle_add(self.updateTreeview, self.liststore,self.image, self.index)
2346-
2347-class ThumbTimer(object) :
2348- """
2349- This class schedule the generation of thumbnail with a timer.
2350- Periodically parse the imagelist for not generated thumbnail
2351- """
2352-
2353- def __init__(self, timeout_ms = 50 , startTimer = False,image_list =None, liststore=None) :
2354- """
2355- Class init.
2356- inputs :
2357- - timeout_ms : period of the timer in ms
2358- - startTimer : to start immediatly the timer after object creation
2359- - image_list : The image list to parse
2360- - liststore : Treeview model , used for update treeview with generated thumbnail
2361- """
2362- self._timer_id = None
2363- self._timeout_ms = timeout_ms
2364- self._image_list = image_list
2365- self._liststore = liststore
2366- self._nbThreadsMax=2 # nb of thread to start at the same time
2367-
2368- if (startTimer) : self._start_timer()
2369-
2370- def _start_timer(self) :
2371- """ start the timer """
2372- self._timer_id=gobject.timeout_add(self._timeout_ms,self._on_timeout)
2373- self._t0 = os.times()
2374- self.PJL = True
2375-
2376- def _on_timeout (self) :
2377- """
2378- callback called each timer time_out.
2379- Parse the image list looking for not generated pixbuf, when occurs start a thread for thumbnail generation.
2380- """
2381- nbThreads=0
2382- for index,image in enumerate(self._image_list) :
2383- if not image.is_icon_loaded :
2384- # launch thread for icon generation
2385- t = MyThumbThread(image,index,self._liststore)
2386- t.start()
2387- nbThreads += 1
2388- # stop the loop when max number of thread is reach
2389- if nbThreads >= self._nbThreadsMax : break
2390- return True
2391-
2392-class LucioleImage(object):
2393- """Managing Images inside luciole"""
2394-
2395- def __init__(self,imagePath,iconDefault,imageDefault):
2396- """ init of Luciole Image """
2397- #splash=gtk.gdk.pixbuf_new_from_file("images/black.png")
2398- self._iconPixbufDefault= iconDefault
2399- self._normalPixbufDefault= imageDefault
2400- self._load_from_file(imagePath)
2401-
2402- def _get_imageName(self): return self.__imageName
2403- def _set_imageName(self, value): self.__imageName = value
2404- def _del_imageName(self): del self.__imageName
2405- imageName = property(_get_imageName, _set_imageName, _del_imageName, "Image's name. ")
2406-
2407- def _get_imagePath(self): return self.__imagePath
2408- def _set_imagePath(self, value): self.__imagePath = value
2409- def _del_imagePath(self): del self.__imagePath
2410- imagePath = property(_get_imagePath, _set_imagePath, _del_imagePath, "Image's location/path.")
2411-
2412- def _get_fullName(self): return os.path.join(self.__imagePath,self.__imageName)
2413- fullName = property (_get_fullName,None,None," Image complete path")
2414-
2415- def get_pixbuf_icon(self): return self.__pixbuf_icon
2416- def set_pixbuf_icon(self, value): self.__pixbuf_icon = value
2417- def del_pixbuf_icon(self): del self.__pixbuf_icon
2418- pixbuf_icon = property(get_pixbuf_icon, set_pixbuf_icon, del_pixbuf_icon, "GtkPixbuf object of icon image.")
2419-
2420- def get_is_icon_loaded(self): return self.__is_icon_loaded
2421- def set_is_icon_loaded(self, value): self.__is_icon_loaded = value
2422- def del_is_icon_loaded(self): del self.__is_icon_loaded
2423- is_icon_loaded = property(get_is_icon_loaded, set_is_icon_loaded, del_is_icon_loaded, "True if the icon is computed (pixbuf Transformation)")
2424-
2425- def get_pixbuf_normal(self): return self.__pixbuf_normal
2426- def set_pixbuf_normal(self, value): self.__pixbuf_normal = value
2427- def del_pixbuf_normal(self): del self.__pixbuf_normal
2428- pixbuf_normal = property(get_pixbuf_normal, set_pixbuf_normal, del_pixbuf_normal, "GtkPixbuf object of icon image.")
2429-
2430- def get_is_normal_loaded(self): return self.__is_normal_loaded
2431- def set_is_normal_loaded(self, value): self.__is_normal_loaded = value
2432- def del_is_normal_loaded(self): del self.__is_normal_loaded
2433- is_normal_loaded = property(get_is_normal_loaded, set_is_normal_loaded, del_is_normal_loaded, " True if icon image is loaded")
2434-
2435- def load_pixbuf_icon(self):
2436- """Load pixbuf for thumbnail in treeview"""
2437- pixbuf=gtk.gdk.pixbuf_new_from_file(self.__imagePath+"/"+self.__imageName)
2438- self.__pixbuf_icon=pixbuf.scale_simple(MCONST.VIDEO_PAL_RES[0]/16, MCONST.VIDEO_PAL_RES[1]/16,gtk.gdk.INTERP_BILINEAR)
2439- # set as computed
2440- self.__is_icon_loaded = True
2441- return self.__pixbuf_icon
2442-
2443- def load_pixbuf_normal(self):
2444- """Load pixbuf for image to Display"""
2445- pixbuf=gtk.gdk.pixbuf_new_from_file(self.__imagePath+"/"+self.__imageName)
2446- self.__pixbuf_normal=pixbuf.scale_simple(MCONST.VIDEO_PAL_RES[0], MCONST.VIDEO_PAL_RES[1],gtk.gdk.INTERP_BILINEAR)
2447- self.__is_normal_loaded =True
2448- return self.__pixbuf_normal
2449-
2450- def load_from_file(self,imageLocation) :
2451- """load a luciole image from a file"""
2452- self._load_from_file(self,imageLocation)
2453-
2454- def _load_from_file(self,imageLocation) :
2455- """ Private function for loading images"""
2456- if os.path.isfile(imageLocation) :
2457- tsplit=os.path.split(imageLocation)
2458- self.__imagePath=tsplit[0]
2459- self.__imageName=tsplit[1]
2460- self.__pixbuf_icon = self._iconPixbufDefault
2461- self.__is_icon_loaded = False
2462- self.__pixbuf_normal=self._normalPixbufDefault
2463- self.__is_normal_loaded = False
2464- else :
2465- print " Not a file :",imageLocation
2466-
2467-
2468-class LucioleImageList(list):
2469- """ List of luciole image """
2470- def __init__(self):
2471- """ Init of luciole image list """
2472- list.__init__(self)
2473- splash =gtk.gdk.pixbuf_new_from_file("images/black.png")
2474- self._black_icon=splash.scale_simple(MCONST.VIDEO_PAL_RES[0]/16, MCONST.VIDEO_PAL_RES[1]/16,gtk.gdk.INTERP_BILINEAR)
2475- self._black_normal=splash.scale_simple(MCONST.VIDEO_PAL_RES[0], MCONST.VIDEO_PAL_RES[1],gtk.gdk.INTERP_BILINEAR)
2476-
2477-
2478- def move_after(self,src,dest) :
2479- """ Insert src element after dest element"""
2480- x = self[src]
2481- self.insert(dest+1,x)
2482- del self[src]
2483-
2484- def move_before(self,src,dest) :
2485- """ Insert src element before dest elemenst"""
2486- x = self[src]
2487- del self[src]
2488- self.insert(dest,x)
2489-
2490- def append_from_file(self,ImagePath) :
2491- """ Append a pixbuf from file """
2492- x=LucioleImage(ImagePath,self._black_icon,self._black_normal)
2493- self.append(x)
2494- return x
2495-
2496-class LucioleGtkTreeView(object) :
2497- """ gtk Treeview for handling the cpature Treeview"""
2498-
2499- ############################################################
2500- ### Class properties
2501- ############################################################
2502-
2503- def _get_widgetName(self): return self.__widgetName
2504- def _set_widgetName(self, value): self.__widgetName = value
2505- def _del_widgetName(self): del self.__widgetName
2506- widgetName = property(_get_widgetName, _set_widgetName, _del_widgetName, " Treeview name")
2507-
2508- def _get_imageFileIndex(self): return self.__imageFileIndex
2509- def _set_imageFileIndex(self, value): self.__imageFileIndex = value
2510- def _del_imageFileIndex(self): del self.__imageFileIndex
2511- imageFileIndex = property(_get_imageFileIndex, _set_imageFileIndex, _del_imageFileIndex, "Image file index ")
2512-
2513- __titreList = {
2514- "treeview_capture" : 'image',
2515- "treeview_montage" : 'image'
2516- }
2517-
2518- liststore=None
2519- (COL_NUM, COL_PIXBUF, COL_IMAGENAME, COL_TS ) = range(4)
2520-
2521- def __init__(self,TreeViewWidget, previsuArea,CameraArea) :
2522- if (TreeViewWidget.get_name() in self.__titreList) :
2523- #init of global dictionary
2524- if not self.__class__.__name__ in MG.luciole_global.dico :
2525- MG.luciole_global.dico[self.__class__.__name__] = self
2526- else :
2527- print "l objet",self.__class__.__name__," existe deja"
2528- return None
2529- #mode save (CAPTURE or CHRONO)
2530- self.mode = MG.luciole_global.CAPTURE
2531- #sauvergarde du widget de previsu
2532- self.__previewObj = previsuArea
2533- self.__CamPreviewObj = CameraArea
2534- # definition of Treeview wigdet
2535- self.TreeViewWidget = TreeViewWidget
2536- self.__widgetName = TreeViewWidget.get_name()
2537- # TreeView model init
2538- self.liststore = gtk.ListStore(int,gtk.gdk.Pixbuf,str,float)
2539- self.TreeViewWidget.set_model(self.liststore)
2540- #colonne Image et Icone
2541- __column = gtk.TreeViewColumn()
2542- __column.set_title(_('image'))
2543- self.TreeViewWidget.append_column(__column)
2544- __renderer = gtk.CellRendererPixbuf()
2545- __column.pack_start(__renderer, expand=False)
2546- __column.add_attribute(__renderer, 'pixbuf', self.COL_PIXBUF)
2547- __renderer = gtk.CellRendererText()
2548- __column.pack_start(__renderer, expand=True)
2549- __column.add_attribute(__renderer, 'text', self.COL_IMAGENAME)
2550- # settings de la fenetre TreeView
2551- # make treeview searchable
2552- self.TreeViewWidget.set_search_column(0)
2553- # Allow sorting on the column
2554- __column.set_sort_column_id(0)
2555- # Allow drag and drop reordering of rows
2556- self.TreeViewWidget.set_reorderable(True)
2557-
2558- # init de la list
2559- self.imageList = LucioleImageList()
2560-
2561- #on recuperere le widget treeSelection
2562- self.treeselection = self.TreeViewWidget.get_selection()
2563- # allow multiple selection
2564- self.treeselection.set_mode(gtk.SELECTION_MULTIPLE)
2565- # image File name index init
2566- self.__imageFileIndex = 0
2567-
2568- #tests sur le drag and drop
2569- self.TARGETS = [
2570- ('MY_TREE_MODEL_ROW', gtk.TARGET_SAME_WIDGET, 0),
2571- ('text/plain', 0, 1),
2572- ('TEXT', 0, 2),
2573- ('STRING', 0, 3),
2574- ]
2575- self.TreeViewWidget.enable_model_drag_source( gtk.gdk.BUTTON1_MASK,
2576- self.TARGETS,
2577- gtk.gdk.ACTION_DEFAULT|
2578- gtk.gdk.ACTION_COPY)
2579- #self.treeview.enable_model_drag_dest(self.TARGETS,
2580- #gtk.gdk.ACTION_DEFAULT)
2581- self.TreeViewWidget.connect("drag_data_get", self._drag_data_get_data)
2582- #self.treeview.connect("drag_data_received",
2583- #self.drag_data_received_data)
2584-
2585- # handle of "cursor-changed" signal
2586- self.TreeViewWidget.connect("cursor-changed",self.cb_cursor_changed)
2587-
2588- # start timer for generation of thumbs
2589- ThumbsTimer = ThumbTimer(startTimer=True,image_list=self.imageList,liststore=self.liststore)
2590- global _
2591-
2592- ############################################################
2593- ### CALLBACKS
2594- ############################################################
2595-
2596- def cb_cursor_changed(self,treeview):
2597- """ Call back on cursor change to allow display of an image when it is seleted """
2598-
2599- # get cursor position
2600- (path_cursor,col) = treeview.get_cursor()
2601- # display selected image
2602- self.previsualisation(self.liststore.get_iter(path_cursor))
2603-
2604-
2605- ############################################################
2606- ### PUBLIC METHODS
2607- ############################################################
2608-
2609- def AppendFromCapture(self,ImagePath) :
2610- """Append an image from a display capture. the last available number and save the pixbuf to file."""
2611-
2612- #get the listore len
2613- file_index= len( self.liststore) + 1
2614-
2615- # deplacement de l element
2616- Filename ="capture_%05d"%self.__imageFileIndex + ".jpeg"
2617- Path=MG.luciole_global.dico[MF.luciole_project_file.__name__].datas.capture_dir
2618- DestPath = os.path.join(Path,Filename)
2619- try :
2620- MT.movef(ImagePath,DestPath)
2621- except M_EXCEP.LucioException,err :
2622- raise M_EXCEP.LucioException,err
2623- DestPath = None
2624- else :
2625- # et on l ajoute a la liste
2626- self.append(DestPath)
2627- # affichage de l image captures dans la fenetre de previsu
2628- self.previsualisation(self.liststore.get_iter((file_index-1,)));
2629- # this function returns the Path of the image ; used for onion skin
2630-
2631- return DestPath
2632-
2633- def append(self,element,fromFile=False) :
2634- """Add an element to Treeview and luciole Image List.
2635- The fromFile boolean check if the append command is coming from the GUI (default),
2636- of from an append commande comoing from a file load"""
2637- if os.path.exists(element) :
2638- x = self.imageList.append_from_file(element)
2639- addedElem= self.liststore.append([len( self.liststore),x.pixbuf_icon,x.imageName,1.5])
2640-
2641- if not fromFile :
2642- # add on XML structure
2643- ProjectFileObj = MG.luciole_global.dico[MF.luciole_project_file.__name__]
2644- ProjectFileObj.append(self.mode,x.imageName)
2645- # increment image index
2646- self.__imageFileIndex =self.__imageFileIndex +1
2647-
2648- treeselection = self.TreeViewWidget.get_selection()
2649- treeselection.select_path((len(self.liststore) - 1,) )
2650- self.TreeViewWidget.scroll_to_cell((len(self.liststore)-1 ,))
2651- self.TreeViewWidget.set_cursor((len(self.liststore) -1 ,))
2652-
2653- def LoadImagesfromProject(self,imageList):
2654- """ Load a list of image from the project. ImageList is a list
2655- with the absolute path to the image. """
2656- for image in imageList :
2657- self.append(image,True)
2658- # start timer for generation of thumbs
2659- #ThumbsTimer = ThumbTimer(startTimer=True,image_list=self.imageList,liststore=self.liststore)
2660-
2661- def GetLastImagePath(self) :
2662- """ return the last image of the tree """
2663- n_rows = len(self.liststore)
2664- ImgPath = None
2665- if (n_rows) :
2666- iterL= self.liststore.get_iter( (n_rows-1,) )
2667- if (iterL) :
2668- Image = self.get_LucioleImage(iterL)
2669- ImgPath = os.path.join (Image.get_imagePath(),Image.get_imageName())
2670-
2671- return ImgPath
2672-
2673- def clear_all(self):
2674- """ Free all the elements in the list/tree """
2675- #remove all elements in imageList
2676- self.imageList[:] =[]
2677- self.liststore.clear()
2678- self.__previewObj.pixbufToDisplay=None
2679- return self.liststore
2680-
2681- def get_LucioleImage(self,iter):
2682- """ From an iter return the image relative to the iter in treeview."""
2683- path = self.liststore.get_path(iter)
2684- if (path) :
2685- return self.imageList[path[0]]
2686-
2687- def remove_selection(self) :
2688- """ remove selected items """
2689- (model, pathlist) = self.treeselection.get_selected_rows()
2690-
2691- # get the iter just after the selection
2692- nextIter = self.liststore.iter_next(self.liststore.get_iter(pathlist[-1]))
2693- iterList = map(lambda x : self.liststore.get_iter(x), pathlist)
2694- # remove items
2695- map(self._remove_iter,iterList)
2696- #Select the next image
2697- if (nextIter) :
2698- # select nextIter
2699- self.treeselection.select_iter(nextIter)
2700- # previsualize net iter
2701- self.previsualisation(nextIter)
2702- else :
2703- # lastitem was removed
2704- # try to display the last image of the tree if not empty
2705- if ( len(self.liststore) !=0 ) :
2706- lastIter = self.liststore.get_iter((len(self.liststore) -1,))
2707- self.treeselection.select_iter(lastIter)
2708- self.previsualisation(lastIter)
2709- else :
2710- # display nothing
2711- self.previsualisation(None)
2712-
2713- def previsualisation(self,iter,display=MCONST.SCREEN_PREVIEW) :
2714- """Preview of the image of a selected object in the treeview.
2715- This method returns the path to the image."""
2716- #test on screen to be used
2717- if (display == MCONST.SCREEN_CAMERA) :
2718- displayObj = self.__CamPreviewObj
2719- else :
2720- displayObj = self.__previewObj
2721- # recuperation du path de l'image puis display de l'image associé dans la liste
2722- ImgPath = None
2723- if (iter) :
2724- path = self.liststore.get_path(iter)
2725- if (path) :
2726- ImgPath = os.path.join ( self.imageList[path[0]].imagePath , self.imageList[path[0]].imageName)
2727- if(self.imageList[path[0]].pixbuf_normal) :
2728- # test on availability of image to Display, if not compute pixbuf
2729- if not self.imageList[path[0]].is_normal_loaded :
2730- # pixbuf not available compute_it
2731- self.imageList[path[0]].load_pixbuf_normal()
2732- displayObj.pixbufToDisplay =self.imageList[path[0]].pixbuf_normal
2733- else :
2734- displayObj.displayDefault()
2735- else :
2736- displayObj.displayDefault()
2737- else :
2738- displayObj.displayDefault()
2739- return ImgPath
2740-
2741- def GetImagePath(self,widget,iter) :
2742- """ Get the image path of a selected image in treeview."""
2743- ImgPath = None
2744- if (iter) :
2745- path = self.liststore.get_path(iter)
2746- if (path) :
2747- ImgPath = os.path.join ( self.imageList[path[0]].imagePath , self.imageList[path[0]].imageName)
2748- return ImgPath
2749-
2750-
2751- ############################################################
2752- ### PRIVATE METHODS
2753- ############################################################
2754- def _remove_iter(self,iter) :
2755- """ Remove the selected element in treeview."""
2756- path = self.liststore.get_path(iter)
2757- (imagePath,imageElement) =(self.imageList[path[0]].imagePath,self.imageList[path[0]].imageName)
2758- ProjectFileObj = MG.luciole_global.dico[MF.luciole_project_file.__name__]
2759- ProjectFileObj.remove(self.mode,path[0])
2760-
2761- #MF.luciole_file_tools.move_to_trash(imagePath,imageElement)
2762- # on la supprime d'image List
2763- del self.imageList[path[0]]
2764- # on la supprime de la treeview
2765- self.liststore.remove(iter)
2766-
2767- def _drag_data_get_data(self, treeview, context, selection, target_id,etime):
2768- """ Experrimental function for drag and drop . Not Implemented yet"""
2769- treeselection = treeview.get_selection()
2770- model, iter = treeselection.get_selected()
2771- data = model.get_value(iter, self.COL_IMAGENAME)
2772- selection.set('text/plain', 8, data)
2773-
2774- def _swap_iter(self,iter1,iter2) :
2775- """ Swap of 2 elements in treeview. Swap of Image and image Name. The project
2776- XML file is also updated"""
2777- path1 = self.liststore.get_path(iter1)
2778- path2 = self.liststore.get_path(iter2)
2779-
2780- pixbuf=self.liststore.get_value(iter1,self.COL_PIXBUF)
2781- imageName=self.liststore.get_value(iter1,self.COL_IMAGENAME)
2782- Lucioleimage = self.imageList[path1[0]]
2783- self.liststore.set_value(iter1,self.COL_PIXBUF,self.liststore.get_value(iter2,self.COL_PIXBUF))
2784- self.liststore.set_value(iter1,self.COL_IMAGENAME,self.liststore.get_value(iter2,self.COL_IMAGENAME))
2785- self.imageList[path1[0]] = self.imageList[path2[0]]
2786- self.liststore.set_value(iter2,self.COL_PIXBUF,pixbuf)
2787- self.liststore.set_value(iter2,self.COL_IMAGENAME,imageName)
2788- self.imageList[path2[0]] = Lucioleimage
2789-
2790- #on swap dans le fichier xml
2791- ProjectFileObj = MG.luciole_global.dico['luciole_project_file']
2792- ProjectFileObj.swap(self.mode,path1[0],path2[0])
2793-
2794-
2795- def _testIter(self):
2796- """ Test Function """
2797- treeiter = self.liststore.get_iter_first()
2798- path=self.liststore.get_path(treeiter)
2799- row =self.liststore[0]
2800- for value in self.liststore :
2801- print "coucou liststore " , value[0]
2802-
2803- def _dumpStore(self) :
2804- """Test function"""
2805- for value in self.liststore :
2806- print str(value[self.COL_NUM]),str(value[self.COL_PIXBUF]),str(value[self.COL_IMAGENAME])
2807-
2808- def _dumpImageList(self) :
2809- """Test function"""
2810- print "Image list "
2811- for image in self.imageList :
2812- print"\t",str(image.imageName)
2813-
2814- def treeview_idle(self) :
2815- """ Executed in background"""
2816- print "treeview_idle"
2817- # Try on cursor move
2818- #(dummy_model, iter) = self.treeselection.get_selected()
2819- #if(iter):
2820- # reucperation du chemin
2821- # path = self.liststore.get_path(iter)
2822-
2823-class LucioleGtkTreeViewChrono(LucioleGtkTreeView) :
2824- """ Manage The chrono TreeView . Inherited from LucioleGtkTreeView"""
2825- def __init__(self,TreeViewWidget,previsuArea,CameraArea) :
2826- """ init of LucioleGtkTreeViewChrono Module"""
2827- LucioleGtkTreeView.__init__(self,TreeViewWidget,previsuArea,CameraArea)
2828-
2829- # init du type de mode
2830- self.mode = MG.luciole_global.CHRONO
2831- #colonne numero
2832- __column = gtk.TreeViewColumn()
2833- __column.set_title(_('Number'))
2834- self.TreeViewWidget.insert_column(__column,self.COL_NUM)
2835- __renderer = gtk.CellRendererText()
2836- __column.pack_start(__renderer, expand=True)
2837- __column.add_attribute(__renderer, 'text', self.COL_NUM)
2838- # colonne timestamp
2839- __column = gtk.TreeViewColumn()
2840- __column.set_title(_('Timestamp'))
2841- self.TreeViewWidget.insert_column(__column,self.COL_TS)
2842- __renderer = gtk.CellRendererText()
2843- __column.pack_start(__renderer, expand=True)
2844- __column.add_attribute(__renderer, 'text', self.COL_TS)
2845- # recuperation du widget entry du fpi
2846- appGuiObj=MG.luciole_global.dico['appgui']
2847- self._fpi_widget=appGuiObj.wTree.get_widget('hscale1_fps')
2848-
2849- # callback tests
2850-# def cb_cursor_changed(self,treeview):
2851-# """ test """
2852-# print "chrono : cb_cursor_changed"
2853-# print treeview
2854-
2855- ############################################################
2856- ### PUBLIC METHODS
2857- ############################################################
2858-
2859- def append(self,element,fromFile=False) :
2860- """Add an element to Treeview and luciole Image List in chronologie"""
2861- if os.path.exists(element) :
2862- x=self.imageList.append_from_file(element)
2863- # calul de la durée fpi pour timeline
2864- ImageTime =float( len(self.imageList) -1) *float((1.0*MG.luciole_global.dico[MF.luciole_project_file.__name__].fpi)/MCONST.VIDEO_PAL_FPS)
2865- self.liststore.append([len( self.liststore),x.pixbuf_icon,x.imageName,ImageTime])
2866- if not fromFile :
2867- ProjectFileObj = MG.luciole_global.dico[MF.luciole_project_file.__name__]
2868- # add on XML structure
2869- ProjectFileObj.append(self.mode,x.imageName)
2870- # now that we removed the selection, play nice with
2871- # the user and select the last item
2872- treeselection = self.TreeViewWidget.get_selection()
2873- #(model, iter_list) = treeselection.get_selected_rows()
2874- treeselection.select_path((len(self.liststore) - 1,) )
2875- self.TreeViewWidget.set_cursor((len(self.liststore) - 1,))
2876- self.TreeViewWidget.scroll_to_cell((len(self.liststore) - 1,))
2877-
2878-
2879- def MoveToChrono(self,LucioTreeviewFrom):
2880- """ Move selection from capture in chrono treeview"""
2881- if ( LucioTreeviewFrom.treeselection.count_selected_rows() > 0):
2882- # almost one element is selected
2883- (model_capture, pathlist) = LucioTreeviewFrom.treeselection.get_selected_rows()
2884- # get original position for the selection of all the transfered images
2885- # after the transfer
2886- (initial_path,col) = self.TreeViewWidget.get_cursor()
2887- for mypath in pathlist :
2888- # loop on image selected in capture view
2889- iter_capture = LucioTreeviewFrom.liststore.get_iter(mypath)
2890- M_image_to_shift = LucioTreeviewFrom.get_LucioleImage(iter_capture)
2891- # copy from capture to chrono
2892- try :
2893- ProjectFileObj = MG.luciole_global.dico[MF.luciole_project_file.__name__]
2894- MT.copyf(M_image_to_shift.fullName,ProjectFileObj.chrono_dir )
2895- except M_EXCEP.LucioException,err :
2896- #raise M_EXCEP.LucioException,err
2897- print " exception dans MoveToChrono : \n " + err.message
2898- else :
2899- self.insert(M_image_to_shift)
2900-
2901-
2902- # select the transfered images
2903- if (initial_path) :
2904- self.treeselection.select_range((initial_path[0]+1,),(initial_path[0] + len(pathlist),))
2905- else :
2906- # if no data in chrono selected select the last images transfered
2907- start_path = len(self.liststore) -len(pathlist)
2908- end_path = len(self.liststore) -1
2909- self.treeselection.select_range( (start_path,), (end_path,) )
2910-
2911- def insert(self,element ) :
2912-
2913- if isinstance(element,LucioleImage) :
2914- (model, pathlist) = self.treeselection.get_selected_rows() # treeselection on chrono view
2915- (path_cursor,col) =self.TreeViewWidget.get_cursor() # cursor on chrono view
2916- if (path_cursor and isinstance(element,LucioleImage)) :
2917- iter_cursor = self.liststore.get_iter(path_cursor)
2918- # copy image in chrono dir and update xml file
2919- ProjectFileObj = MG.luciole_global.dico[MF.luciole_project_file.__name__]
2920- ProjectFileObj.insert(self.mode,path_cursor[0] +1, element.imageName)
2921- self.imageList.insert(path_cursor[0]+1,element)
2922- self.liststore.insert_after(iter_cursor,[0,element.pixbuf_icon,element.imageName,0])
2923- self.liststore.foreach(self._foreach_updateNumAndtime,MG.luciole_global.dico[MF.luciole_project_file.__name__].fpi)
2924-
2925- self.TreeViewWidget.set_cursor(path_cursor[0]+1 )
2926- else :
2927- #nothing is selected or treeview empty append element
2928- self.append(element.fullName)
2929-
2930-
2931- #def insert(self,i,x) :
2932- # """Add an element to Treeview and luciole Image List in chronologie"""
2933- # if isinstance(x,LucioleImage) :
2934- # #maj d'image Lis
2935- # self.imageList.append(i,x)
2936- # #maj du fichier xml
2937- # ProjectFileObj = MG.luciole_global.dico['luciole_project_file']
2938- # ProjectFileObj.insert(self.mode,i,element.imageName)
2939- # ImageTime =(1.*i) *float((1.0*MG.luciole_global.dico[MF.luciole_project_file.__name__].fpi)/MCONST.VIDEO_PAL_FPS)
2940- # return self.liststore.append([len( self.liststore),x.pixbuf_icon,x.imageName,ImageTime])
2941-
2942- def update_fpi_label(self,fpi) :
2943- """ Update the value of fpi in GUI"""
2944- pos = 1
2945- for (k,v) in MCONST.VIDEO_FPS_TABLE.iteritems() :
2946- # find the position
2947- (a,b) = v
2948- if b == fpi : pos=k
2949- self._fpi_widget.set_value(pos)
2950-
2951- def up(self) :
2952- """ Move up one position a selection in treeview"""
2953- (dummy_model, pathList) = self.treeselection.get_selected_rows()
2954- first_selected = pathList[0]
2955- last_selected = pathList[-1]
2956- if (not ( first_selected[0] == 0 )) :
2957- # the first element is not at the top level (i.e. position 0)
2958-
2959- # moving up is to put the previous sibling of the selection after the
2960- # last element of the selection
2961-
2962- # get previous iter
2963- prevIter = self.liststore.get_iter( (first_selected[0] -1,))
2964- #move it after last element of the selection
2965- self._move_after(prevIter,self.liststore.get_iter(last_selected))
2966-
2967- self._dumpImageList()
2968-
2969- # keep the same selected rows, move selection rage by -1
2970- self.treeselection.unselect_all()
2971- self.treeselection.select_range((first_selected[0] -1,),(last_selected[0] -1,))
2972- # scroll also to the first selected
2973- self.TreeViewWidget.scroll_to_cell((first_selected[0] -1,),None,True,0.5)
2974-
2975- def down(self) :
2976- """ Move down one position a selection in treeview"""
2977- (dummy_model, pathList) = self.treeselection.get_selected_rows()
2978- first_selected = pathList[0]
2979- last_selected = pathList[-1]
2980- if (last_selected[0] != ( len(self.liststore) -1 ) ):
2981- # the last element is not at the bottom of the list
2982-
2983- # moving down is to put the next sibling of the selection before the
2984- # first element of the selection
2985-
2986- # get next iter
2987- nextIter = self.liststore.get_iter( (last_selected[0] +1,))
2988- #move it before the first element of the selection
2989- self._move_before(nextIter,self.liststore.get_iter(first_selected))
2990- self._dumpImageList()
2991- # keep the same selected rows, move selection range by +1
2992- self.treeselection.unselect_all()
2993- self.treeselection.select_range((first_selected[0] +1,),(last_selected[0] +1,))
2994- # scroll also to the first selected
2995- self.TreeViewWidget.scroll_to_cell((last_selected[0] +1,),None,True,0.5)
2996-
2997- ############################################################
2998- ### PRIVATE METHODS
2999- ############################################################
3000-
3001- def _foreach_updateNumAndtime(self,model,path,iter,fpi) :
3002- """foreach handler of Gtk.treemodel for upate of timestamp and num of image."""
3003- ImageTime =(1.*path[0]) *float((1.0*MG.luciole_global.dico[MF.luciole_project_file.__name__].fpi)/MCONST.VIDEO_PAL_FPS)
3004- model.set_value(iter,self.COL_TS,ImageTime)
3005- model.set_value(iter,self.COL_NUM,path[0])
3006-
3007- def upadteTreeviewTime(self,fpi) :
3008- """ Update treeview time according fpi value. """
3009- self.liststore.foreach(self._foreach_update_time,fpi)
3010-
3011- def _foreach_update_time(self,model,path,iter,fpi) :
3012- """foreach handler of Gtk.treemodel for upate of image time."""
3013- ImageTime =(1.*path[0]) *float((1.0*MG.luciole_global.dico[MF.luciole_project_file.__name__].fpi)/MCONST.VIDEO_PAL_FPS)
3014- model.set_value(iter,self.COL_TS,ImageTime)
3015-
3016-
3017- def _move_after(self,iter_src,iter_dest):
3018- """ Move an element in treeview and update list, imageList and xml file """
3019- #get path
3020- path_src = self.liststore.get_path(iter_src)
3021- path_dest = self.liststore.get_path(iter_dest)
3022- #update imageList
3023- self.imageList.move_after(path_src[0],path_dest[0])
3024- #update XML project file
3025- ProjectFileObj = MG.luciole_global.dico[MF.luciole_project_file.__name__]
3026- ProjectFileObj.move_after(self.mode,path_src[0],path_dest[0])
3027-
3028- #update liststore
3029- self.liststore.move_after(iter_src,iter_dest)
3030- #update Numerotation and time
3031- self.liststore.foreach(self._foreach_updateNumAndtime,MG.luciole_global.dico[MF.luciole_project_file.__name__].fpi)
3032-
3033- def _move_before(self,iter_src,iter_dest):
3034- """ Move an element in treeview and update list, imageList and xml file """
3035- #get path
3036- path_src = self.liststore.get_path(iter_src)
3037- path_dest = self.liststore.get_path(iter_dest)
3038- #update imageList
3039- self.imageList.move_before(path_src[0],path_dest[0])
3040- #update XML project file
3041- ProjectFileObj = MG.luciole_global.dico[MF.luciole_project_file.__name__]
3042- ProjectFileObj.move_before(self.mode,path_src[0],path_dest[0])
3043-
3044- #update liststore
3045- self.liststore.move_before(iter_src,iter_dest)
3046- #update Numerotation and time
3047- self.liststore.foreach(self._foreach_updateNumAndtime,MG.luciole_global.dico[MF.luciole_project_file.__name__].fpi)
3048-
3049-
3050-
3051-
3052
3053=== modified file 'lucioLib/luciole_conf.py'
3054--- lucioLib/luciole_conf.py 2009-03-08 18:06:41 +0000
3055+++ lucioLib/luciole_conf.py 2009-04-11 16:57:27 +0000
3056@@ -26,9 +26,8 @@
3057 """ file lucio_conf.py """
3058
3059 import os.path
3060-from . import luciole_exceptions as M_EXCEP
3061+import luciole_exceptions as M_EXCEP
3062 import luciole_tools as MT
3063-import luciole_global as MG
3064
3065 from xml.sax.handler import ContentHandler
3066 from xml.sax import make_parser
3067@@ -39,8 +38,9 @@
3068 class LucioleConf(object):
3069 """ Manage the configuration file of luciole """
3070
3071- __USER_MYRTILLE_DIR = ".luciole"
3072+ __USER_LUCIOLE_DIR = ".luciole"
3073 __CONF_FILE_NAME = "lucioleConf.xml"
3074+ __ORIGINAL_DIR = "templates"
3075
3076 def _get_conf_options(self):
3077 """ get method for option dicrionary """
3078@@ -53,20 +53,12 @@
3079 - if conf file does not exist in user dir create it
3080 - parse xml conf file
3081 """
3082- # search for luciole conf if not create it
3083- # in /home/user/.luciole/luciole_conf.py
3084- if not self.__class__.__name__ in MG.luciole_global.dico :
3085- MG.luciole_global.dico[self.__class__.__name__] = self
3086- else :
3087- print "l objet", self.__class__.__name__, " existe deja"
3088- return None
3089-
3090 self._home_dir = os.path.expandvars('$HOME')
3091 self._option_dict = dict()
3092 self._option_dict["LastProjects"] = list()
3093 self._conf_et = None
3094 # verify if luciole confile exits
3095- conf_file_path = os.path.join(self.__USER_MYRTILLE_DIR, self.__CONF_FILE_NAME)
3096+ conf_file_path = os.path.join(self.__USER_LUCIOLE_DIR, self.__CONF_FILE_NAME)
3097 self._conf_file_path = os.path.join(self._home_dir, conf_file_path)
3098 if os.path.exists(self._conf_file_path) :
3099 # luciole file exist parse it
3100@@ -74,7 +66,7 @@
3101 else :
3102 try :
3103 # copy file to local dir
3104- self._copy_conf_file("/usr/share/luciole/templates/lucioleConf.xml")
3105+ self._copy_conf_file(os.path.join(self.__ORIGINAL_DIR,self.__CONF_FILE_NAME))
3106 # and parse it
3107 self._parse_conf_file()
3108
3109@@ -104,7 +96,7 @@
3110 def _copy_conf_file(self, source_conf_file) :
3111 """ copy config file to user dir """
3112 #check if user luciole dir exist
3113- ldir = os.path.join(self._home_dir, self.__USER_MYRTILLE_DIR)
3114+ ldir = os.path.join(self._home_dir, self.__USER_LUCIOLE_DIR)
3115 if os.path.exists(ldir) :
3116 if os.path.isdir(ldir) :
3117 # cp luciole_conf file
3118
3119=== modified file 'lucioLib/luciole_constants.py'
3120--- lucioLib/luciole_constants.py 2009-04-08 19:58:11 +0000
3121+++ lucioLib/luciole_constants.py 2009-04-12 15:53:50 +0000
3122@@ -74,5 +74,15 @@
3123 ########################################
3124 # IMAGE FORMATS
3125 ########################################
3126-THUMB_RATIO = 5.0 # ration normal/thumbnail. To set size ot thumbnail images in treeview.
3127+THUMB_RATIO = 5 # ration normal/thumbnail. To set size ot thumbnail images in treeview.
3128+# clor in rgb format muliply by 255 each level to go in gtk.gdk.Color format
3129+THUMB_COLOR_RATIO = 256
3130+THUMB_TEXT_COLOR = (
3131+ 191 * THUMB_COLOR_RATIO,
3132+ 244 * THUMB_COLOR_RATIO,
3133+ 75 * THUMB_COLOR_RATIO
3134+ )
3135+THUMB_TEXT_SIZE = 8200 # text size
3136+THUMB_TEXT_FAMILY = 'sans' # font family
3137+
3138
3139
3140=== modified file 'lucioLib/luciole_controller.py'
3141--- lucioLib/luciole_controller.py 2009-04-10 19:50:00 +0000
3142+++ lucioLib/luciole_controller.py 2009-04-13 19:21:49 +0000
3143@@ -33,9 +33,14 @@
3144 import luciole_constants as LCONST
3145 import luciole_exceptions as L_EXCEP
3146 import luciole_player as LPLAYER
3147+import luciole_conf as LCONF
3148+import luciole_manage_recent as LRECENT
3149+import luciole_controller_import as LC_IMAGE
3150
3151 import gui as LTK
3152-
3153+import gobject
3154+import threading
3155+import time
3156
3157 import re
3158 import os.path
3159@@ -45,7 +50,53 @@
3160
3161 # project type status
3162 (NO_PROJECT,ON_CONFIGURATION,LOADED,MODIFIED) = range(4)
3163-
3164+
3165+class rush_loader_thread(threading.Thread):
3166+ """ this thread is used to load the rush images, its take a while so this action is threaded """
3167+ def __init__(self,progress_bar_widget,cb_on_finish,project) :
3168+ """ initilise thread
3169+ progress_bar : the status/progres bar for diplay info about project load
3170+ cb_on_finish : The callback function when thread is finished, the rush_obj is returned by thread
3171+ project : the project dictionary
3172+ """
3173+ # init thread
3174+ super(rush_loader_thread, self).__init__()
3175+
3176+ self._progress_bar_widget = progress_bar_widget
3177+ self._cb_on_finish = cb_on_finish
3178+ self.project = project
3179+ self.rush_obj = None
3180+
3181+ def run(self) :
3182+ """ run thread """
3183+ self._progress_bar_clear() # clear progress bar
3184+
3185+ # create rush list object
3186+ rush_dir = os.path.join(self.project['project_dir'],self.project['rush_dir'])
3187+ rush_obj = LI.Rush_images(rush_dir,self.project['rush_images'],self._progress_bar_on_progress)
3188+
3189+ self._progress_bar_complete()
3190+ self._cb_on_finish(rush_obj) # Thread finished execute callback
3191+
3192+ def _progress_bar_clear(self):
3193+ """ Clear progress bar """
3194+ msg = _('Project Load started')
3195+ # use of idle_add because gui update not in the same thread
3196+ gobject.idle_add( self._progress_bar_widget.start,msg)
3197+
3198+ def _progress_bar_complete(self):
3199+ """ Progress bar full : Project loaded """
3200+ msg = _('Project %s is loaded'%self.project['project_name'])
3201+ # use of idle_add because gui update not in the same thread
3202+ gobject.idle_add( self._progress_bar_widget.stop,msg)
3203+
3204+ def _progress_bar_on_progress(self,ratio = None):
3205+ """ indicate that detection is going on """
3206+ msg = _('Project %s is loading'%self.project['project_name'])
3207+ # use of idle_add because gui update not in the same thread
3208+ gobject.idle_add( self._progress_bar_widget.on_progress,msg,ratio)
3209+
3210+
3211 class Luciole_controller(object) :
3212 __metaclass__ = LT.SingletonType
3213
3214@@ -57,6 +108,15 @@
3215 # init project object
3216 self.project_ctrller = LP.project_controller()
3217
3218+ # init Luciole conf obj
3219+ self.conf_obj = LCONF.LucioleConf()
3220+
3221+ # get the recent project list
3222+ self.recent_project_list = self.conf_obj.conf_options["LastProjects"]
3223+
3224+ # init the recent project manager
3225+ self.recent_project_obj = LRECENT.luciole_recent(self.recent_project_list, self.gui.ui_manager, self.open_project ,self.conf_obj)
3226+
3227 self.acq_obj = None
3228 self.rush_obj = None
3229 self.project = None
3230@@ -97,32 +157,31 @@
3231
3232 # 3. load created project in application
3233 self.__load_project_in_app()
3234-
3235- self.project['is_modified'] = LCONST.PROJECT_NOT_MODIFIED
3236
3237 def open_project(self,project_path = None) :
3238 """ open project if param projecet_path is None
3239 start a Gui dialog """
3240 if project_path == None :
3241+ # if no project_path as paramter open dialog to choose one
3242 project_path = self.gui.open_project()
3243-
3244- # management of modified project
3245- # save not save and ask for save shall be done here
3246
3247- if self.project != None : self.close()
3248+ if self.project != None :
3249+ # if a project is loaded close it
3250+ self.close()
3251
3252 self.project = self.project_ctrller.open(project_path)
3253
3254 # 3. load project in application
3255 self.__load_project_in_app()
3256
3257- self.project['is_modified'] = LCONST.PROJECT_NOT_MODIFIED
3258-
3259 def save_project(self):
3260 """ save the current project """
3261 self.project_ctrller.save(self.project)
3262 self.project['is_modified'] = LCONST.PROJECT_NOT_MODIFIED
3263 self.gui.set_programbar(self.project['project_name'],False)
3264+
3265+ # add project to recent list
3266+ self.recent_project_obj.add_project(os.path.join( self.project['project_dir'], self.project['xml_filename'] ))
3267
3268 def save_as_project(self,path):
3269 """ save into a new project"""
3270@@ -147,18 +206,29 @@
3271 def image_import(self) :
3272 """ import images from external source """
3273 if self.project != None :
3274- #import imges ony if a project is loaded
3275+ # import imges ony if a project is loaded
3276+
3277+ # open filename chooser dialog
3278 filenames = self.gui.import_dialog()
3279- for filename in filenames :
3280- #1. copy image to rush folder and resize it.
3281- l_image_name = self.__copy_import_to_rush_folder(filename)
3282-
3283- #2. add image to rush and capyure obj
3284- self.__append_image_to_project(l_image_name)
3285+
3286+ if filenames != [] :
3287+ # start import thread
3288+ import_thread = LC_IMAGE.import_controller_boss(
3289+ self.gui.status_progress_bar,
3290+ filenames,
3291+ self.project,
3292+ self.rush_index,
3293+ self.rush_obj,
3294+ self.__on_import_finish)
3295+ import_thread.start()
3296
3297 else :
3298 LTK.Dialog.ErrorMessage(self.gui.window, _('Image cannot be imported if a project is not open'))
3299
3300+
3301+
3302+
3303+
3304 def image_preview(self,image_obj) :
3305 """ image preview """
3306 # image preview when image is not in correct foramt not allowed when player is active
3307@@ -299,43 +369,64 @@
3308
3309 # 5. Clear program name bar
3310
3311- # 6. hide fpi widgets
3312- self.gui.fpi_widget_hide()
3313+ # 6. show open/new project widgets
3314+ self.gui.project_open_widgets()
3315
3316+ msg = _('Project %s is closed'%self.project['project_name'])
3317+ status_bar = self.gui.status_progress_bar
3318+ status_bar.display_message(msg)
3319+
3320 # 7.. Remove project obj
3321 self.project = None
3322
3323+
3324 def start_acquisition(self) :
3325 """ start the acquisition """
3326- # test if player is not active
3327- if self._player_active == False :
3328- if self.acq_obj != None :
3329- # acqusition is not active so it can be started
3330- if self._acquirer_active == False :
3331- self.acq_obj.start_acquisition()
3332- self.gui.acquisition_widget_show()
3333-
3334- self._set_acquirer(True) # set acquirer as active
3335- self._set_imager(False) # set imager as inactive
3336- self._set_player(False) # set player as inactive
3337- else :
3338- #acquisition yet started
3339- print "acquisition Yet started : Not expected event "
3340- # State not normal - stop acquirer
3341- self._set_acquirer(False) # stop acquirer
3342- self._set_imager(True) # allow imager
3343- self._set_player(False) # diasallow player
3344-
3345+
3346+ if self.project != None :
3347+ #a project is loaded
3348+ # test if player is not active
3349+ if self._player_active == False :
3350+ if self.acq_obj != None :
3351+ # acqusition is not active so it can be started
3352+ if self._acquirer_active == False :
3353+ self.acq_obj.start_acquisition()
3354+ self.gui.acquisition_widget_show()
3355+
3356+ self._set_acquirer(True) # set acquirer as active
3357+ self._set_imager(False) # set imager as inactive
3358+ self._set_player(False) # set player as inactive
3359+ else :
3360+ #acquisition yet started
3361+ print "acquisition Yet started : Not expected event "
3362+ # State not normal - stop acquirer
3363+ self._set_acquirer(False) # stop acquirer
3364+ self._set_imager(True) # allow imager
3365+ self._set_player(False) # diasallow player
3366+ else :
3367+ # deactivate acqusition button acquisition not allowed when palyer is active
3368+ self.gui.acquisition_widget_hide()
3369+ self._set_acquirer(False) # stop acquirer
3370+
3371+
3372+ else :
3373+ # deactivate acqusitionn button
3374+ self.gui.acquisition_widget_hide()
3375+ msg = _(' Can not start acquisition when no project are loaded.')
3376+ LTK.Dialog.ErrorMessage(self.gui.window, msg)
3377+ #robustness
3378+ self._set_acquirer(False) # stop acquirer
3379+ self._set_imager(True) # allow imager
3380+ self._set_player(False) # diasallow player
3381
3382 def stop_acquisition(self) :
3383 """ stop the acquisition """
3384- if self.acq_obj != None :
3385- # acqusition active so it can be stoped
3386- # check also used to avoid loopback problem with the toggle button of acquisition
3387- if self._acquirer_active == True :
3388- self._set_acquirer(False) # deactivate acquirer
3389- self._set_imager(True) # allow imager
3390- self._set_player(False) # Player not activated (robsutness)
3391+ # acqusition active so it can be stoped
3392+ # check also used to avoid loopback problem with the toggle button of acquisition
3393+ if self._acquirer_active == True :
3394+ self._set_acquirer(False) # deactivate acquirer
3395+ self._set_imager(True) # allow imager
3396+ self._set_player(False) # Player not activated (robsutness)
3397
3398 def move_to_chrono(self) :
3399 """ move selected images in capture view to Montage view """
3400@@ -413,8 +504,30 @@
3401 if self.project != None :
3402 # update fpi on projetct
3403 self.project_change('fpi',fpi)
3404-
3405
3406+ def quit(self) :
3407+ """ quit application """
3408+
3409+ if self.project != None :
3410+ # project exist
3411+ if self.project['is_modified'] == LCONST.PROJECT_MODIFIED :
3412+ # nbd@grape : ask for save if save set status as loaded
3413+ l_bRes = LTK.Dialog.QuestionMessage(self.gui.window, _('Project modified. Save project before exit ?'))
3414+ if l_bRes == True :
3415+ self.save_project()
3416+ self.gui.quit()
3417+ elif l_bRes == False :
3418+ self.gui.quit()
3419+ else :
3420+ self.gui.quit()
3421+ else :
3422+ self.gui.quit()
3423+
3424+ def project_properties(self) :
3425+ """ request Display of project properties """
3426+ if self.project != None :
3427+ self.gui.display_project_properties(self.project)
3428+
3429
3430 ####################################################################################################
3431 ##### PRIVATE METHODS
3432@@ -448,13 +561,20 @@
3433 # print "**%s** : %s "%(k,v)
3434 #print "---------------------------------------------------------------------"
3435
3436- # create rush list object
3437- rush_dir = os.path.join(self.project['project_dir'],self.project['rush_dir'])
3438- self.rush_obj = LI.Rush_images(rush_dir,self.project['rush_images'])
3439+ # Initilaisation of rush ogbj is threaded because its take a while (generation of images pixbufs)
3440+ # When rush load is finish : __on_rush_finish is called
3441+ rush_thread = rush_loader_thread(self.gui.status_progress_bar,self.__on_rush_finish,self.project)
3442+ rush_thread.start()
3443+
3444+
3445+ def __on_rush_finish(self,rush_obj):
3446+ """ callaback for rush tghread finsihed. Continue the project load """
3447+ if rush_obj != None :
3448+ self.rush_obj = rush_obj
3449
3450 # load treeviews
3451 self.gui.load_treeviews(self.rush_obj, self.project['capture_images'], self.project['chrono_images'])
3452-
3453+
3454 # update acquisition object
3455 if self.project['hardtype'] == LCONST.DIGICAM :
3456 # acquisition for digital camera
3457@@ -482,8 +602,6 @@
3458 # get rush image index
3459 self.rush_index = self.__get_rush_number_index()
3460
3461- # update project name on Main bar
3462- self.gui.set_programbar(self.project['project_name'],False)
3463
3464
3465 # for mixer initialisation set image to miw with the last image of the capture view. only if capture image is not empty
3466@@ -493,9 +611,20 @@
3467
3468 # update fpi on gui and show it
3469 self.gui.update_fpi(int(self.project['fpi']))
3470- self.gui.fpi_widget_show()
3471+
3472+ # show project acquisition widgets
3473+ self.gui.project_acquistion_widgets()
3474+
3475+ # add project to recent list
3476+ self.recent_project_obj.add_project(os.path.join( self.project['project_dir'], self.project['xml_filename'] ))
3477+
3478+ # set projetc as not modified
3479+ self.project['is_modified'] = LCONST.PROJECT_NOT_MODIFIED
3480+ # update project name on Main bar
3481+ self.gui.set_programbar(self.project['project_name'],False)
3482+
3483 else :
3484- msg = _("Failed to load project : %s"%project_path)
3485+ msg = _("Failed to load project ")
3486 LTK.Dialog.ErrorMessage(self.gui.window, msg)
3487
3488 def __move_capture_to_rush_folder(self):
3489@@ -537,44 +666,6 @@
3490 self.rush_index += 1
3491 return l_basename
3492
3493- def __copy_import_to_rush_folder(self,p_image_path):
3494- """ copy imported image to rush dir :
3495- 1. copy image to tmp dir.
3496- 2. resize it.
3497- 3. move it to rush image dir """
3498-
3499- # build temp impage path
3500- l_temp_dir = os.path.join(self.project['project_dir'], LCONST.TMP_DIR)
3501- # copy name
3502- l_ac_image_temp = os.path.join(l_temp_dir,LCONST.ACQUIRED_IMAGE_NAME)
3503- # resized copy name
3504- l_ac_image_temp_rz = os.path.join(l_temp_dir,LCONST.ACQUIRED_IMAGE_NAME_RZ)
3505-
3506- # build rush image name
3507- l_basename = LCONST.RUSH_FILENAME_TPL%self.rush_index
3508- l_rush_image = os.path.join(self.project['project_dir'], self.project['rush_dir'])
3509- l_rush_image = os.path.join(l_rush_image, l_basename)
3510-
3511- try :
3512- # 1. move image acquired image to tmp dir
3513- LT.copyf(p_image_path,l_ac_image_temp)
3514-
3515- # 2. resize image result is in l_ac_image_temp_rz
3516- l_rz_obj = LI.Image_resize(l_ac_image_temp,l_ac_image_temp_rz )
3517- l_rz_obj.convert()
3518-
3519- # 3. move resized image to rush dire
3520- LT.movef(l_ac_image_temp_rz,l_rush_image)
3521-
3522- except L_EXCEP.LucioException,err :
3523- raise L_EXCEP.LucioException,err
3524- l_basename = None
3525- else :
3526- # move and resize OK : increment rush index
3527- self.rush_index += 1
3528- return l_basename
3529-
3530-
3531
3532 def __append_image_to_project(self, p_image_name):
3533 """ append an imge to the project.
3534@@ -588,7 +679,22 @@
3535 # 2. append image object to capture list
3536 l_rush_image = self.rush_obj.get_image(p_image_name)
3537 self.gui.append_capture(l_rush_image)
3538-
3539+
3540+
3541+ def __on_import_finish(self, image_objs = None, rush_index = 0) :
3542+ """ call back for import finish """
3543+ if image_objs != None :
3544+ print self.rush_obj.dump_image_name()
3545+ self.project_change('rush_images',self.rush_obj.dump_image_name())
3546+
3547+ # update rush index
3548+ self.rush_index = rush_index
3549+
3550+ # This opeation is not done in thread because interacts whith gui treeview
3551+ for image_obj in image_objs :
3552+ self.gui.append_capture(image_obj)
3553+
3554+
3555 def _stop_acquisition(self):
3556 """ private stop acquisition method """
3557 if self.acq_obj != None :
3558@@ -625,3 +731,4 @@
3559 if (type(is_active) == bool) and (self._mixer_active != is_active) :
3560 self._mixer_active = is_active
3561
3562+
3563
3564=== added file 'lucioLib/luciole_controller_import.py'
3565--- lucioLib/luciole_controller_import.py 1970-01-01 00:00:00 +0000
3566+++ lucioLib/luciole_controller_import.py 2009-04-13 13:59:33 +0000
3567@@ -0,0 +1,182 @@
3568+#!/usr/bin/env python
3569+# -*- coding: utf-8 -*-
3570+# -*- Mode: Python -*-
3571+# vi:si:ai:et:sw=4:sts=4:ts=4
3572+#
3573+#
3574+# Copyright Nicolas Bertrand (nico@inattendu.org), 2009
3575+#
3576+# This file is part of Luciole.
3577+#
3578+# Luciole is free software: you can redistribute it and/or modify
3579+# it under the terms of the GNU General Public License as published by
3580+# the Free Software Foundation, either version 3 of the License, or
3581+# (at your option) any later version.
3582+#
3583+# Luciole is distributed in the hope that it will be useful,
3584+# but WITHOUT ANY WARRANTY; without even the implied warranty of
3585+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3586+# GNU General Public License for more details.
3587+#
3588+# You should have received a copy of the GNU General Public License
3589+# along with Luciole. If not, see <http://www.gnu.org/licenses/>.
3590+#
3591+#
3592+"""
3593+luciole_controller_import.py :
3594+ Manages the image import
3595+"""
3596+
3597+from gettext import gettext as _
3598+
3599+import gobject
3600+import threading
3601+import time
3602+import os.path
3603+
3604+import luciole_constants as LCONST
3605+import luciole_exceptions as L_EXCEP
3606+import luciole_image as LI
3607+import luciole_tools as LT
3608+
3609+class import_controller_boss(threading.Thread) :
3610+ """ Thread who manages the import work, schedule image import """
3611+
3612+ def __init__(self,progress_bar_widget, filenames, project, rush_index, rush_obj, cb_on_finish = None) :
3613+ """ init thread :
3614+ progress_bar_widget : widget for progress bar update
3615+ filenames : the image filenames list to import
3616+ project : The project dictionary
3617+ rush_index : the index of the last rush image
3618+ rush_obj : the rush image object
3619+ cb_on_finish : callback function when thread is finish
3620+ """
3621+
3622+ # init thread
3623+ super(import_controller_boss, self).__init__()
3624+
3625+ self._progress_bar_widget = progress_bar_widget
3626+ self._filenames = filenames
3627+ self._project = project
3628+ self._rush_index = rush_index
3629+ self._rush_obj = rush_obj
3630+ self._cb_on_finish = cb_on_finish
3631+ self._image_obj_list = []
3632+
3633+ def run(self) :
3634+ """ run thread """
3635+ self._progress_bar_clear() # clear progress bar
3636+ for (index,filename) in enumerate(self._filenames) :
3637+ # init worker thread
3638+ t_worker = import_controller_worker(filename,self._project, self._rush_index,self._rush_obj,self._cb_worker_finsih)
3639+
3640+ # start wrok
3641+ t_worker.start()
3642+
3643+ # wait worker finished
3644+ while t_worker.isAlive() :
3645+ time.sleep(0.1)
3646+
3647+ #update progress bar
3648+ ratio = (index +1.0) / len(self._filenames)
3649+ self._progress_bar_on_progress(ratio)
3650+
3651+
3652+ self._progress_bar_complete()
3653+ if self._cb_on_finish != None : self._cb_on_finish(self._image_obj_list,self._rush_index)
3654+
3655+ def _cb_worker_finsih(self,image_obj,rush_index) :
3656+ """ callback executed when worker as finished """
3657+ self._image_obj_list.append(image_obj)
3658+ self._rush_index = rush_index
3659+
3660+ def _progress_bar_clear(self):
3661+ """ Clear progress bar """
3662+ msg = _('Image import started')
3663+ # use of idle_add because gui update not in the same thread
3664+ gobject.idle_add( self._progress_bar_widget.start,msg)
3665+
3666+ def _progress_bar_complete(self):
3667+ """ Progress bar full : Project loaded """
3668+ msg = _('Image import finished')
3669+ # use of idle_add because gui update not in the same thread
3670+ gobject.idle_add( self._progress_bar_widget.stop,msg)
3671+
3672+ def _progress_bar_on_progress(self,ratio = None):
3673+ """ indicate that detection is going on """
3674+ msg = _('Importing images.')
3675+ # use of idle_add because gui update not in the same thread
3676+ gobject.idle_add( self._progress_bar_widget.on_progress,msg,ratio)
3677+
3678+
3679+
3680+class import_controller_worker(threading.Thread) :
3681+ """ Worker import thread : Do the job, i.e copy image to rush folder, resize it, and generate pixbufs """
3682+
3683+ def __init__(self, filename, project, rush_index, rush_obj,cb_on_finish = None) :
3684+ """ init thread :
3685+ filename : A image filename
3686+ project : The project dictionary
3687+ rush_index : the index of the last rush image
3688+ rush_obj : the rush image object
3689+ cb_on_finish : callback function when thread is finish
3690+ """
3691+
3692+ # init thread
3693+ super(import_controller_worker, self).__init__()
3694+ self._filename = filename
3695+ self._project = project
3696+ self._rush_index = rush_index
3697+ self._rush_obj = rush_obj
3698+ self._cb_on_finish = cb_on_finish
3699+
3700+ def run(self) :
3701+ """ run the thread """
3702+ # copy image to rush folder and resize it
3703+ l_rush_image_name = self.__copy_import_to_rush_folder(self._filename)
3704+
3705+ # append image to rush list : usage of append_threaded special for thread execution
3706+ image = self._rush_obj.append_threaded(l_rush_image_name)
3707+
3708+ # work finish : do callback
3709+ if self._cb_on_finish != None : self._cb_on_finish(image,self._rush_index)
3710+
3711+ def __copy_import_to_rush_folder(self,p_image_path):
3712+ """ copy imported image to rush dir :
3713+ 1. copy image to tmp dir.
3714+ 2. resize it.
3715+ 3. move it to rush image dir """
3716+
3717+ # build temp impage path
3718+ l_temp_dir = os.path.join(self._project['project_dir'], LCONST.TMP_DIR)
3719+ # copy name
3720+ l_ac_image_temp = os.path.join(l_temp_dir,LCONST.ACQUIRED_IMAGE_NAME)
3721+ # resized copy name
3722+ l_ac_image_temp_rz = os.path.join(l_temp_dir,LCONST.ACQUIRED_IMAGE_NAME_RZ)
3723+
3724+ # build rush image name
3725+ l_basename = LCONST.RUSH_FILENAME_TPL%self._rush_index
3726+ l_rush_image = os.path.join(self._project['project_dir'], self._project['rush_dir'])
3727+ l_rush_image = os.path.join(l_rush_image, l_basename)
3728+
3729+ try :
3730+ # 1. move image acquired image to tmp dir
3731+ LT.copyf(p_image_path,l_ac_image_temp)
3732+
3733+ # 2. resize image result is in l_ac_image_temp_rz
3734+ l_rz_obj = LI.Image_resize(l_ac_image_temp,l_ac_image_temp_rz )
3735+ l_rz_obj.convert()
3736+
3737+ # 3. move resized image to rush dire
3738+ LT.movef(l_ac_image_temp_rz,l_rush_image)
3739+
3740+ except L_EXCEP.LucioException,err :
3741+ raise L_EXCEP.LucioException,err
3742+ l_basename = None
3743+ else :
3744+ # move and resize OK : increment rush index
3745+ self._rush_index += 1
3746+ return l_basename
3747+
3748+
3749+
3750
3751=== removed file 'lucioLib/luciole_file_in_out.py'
3752--- lucioLib/luciole_file_in_out.py 2009-03-08 18:06:41 +0000
3753+++ lucioLib/luciole_file_in_out.py 1970-01-01 00:00:00 +0000
3754@@ -1,695 +0,0 @@
3755-#!/usr/bin/env python
3756-# -*- coding: utf-8 -*-
3757-# -*- Mode: Python -*-
3758-# vi:si:ai:et:sw=4:sts=4:ts=4
3759-#
3760-#
3761-# Copyright Nicolas Bertrand (nico@inattendu.org), 2009
3762-#
3763-# This file is part of Luciole.
3764-#
3765-# Luciole is free software: you can redistribute it and/or modify
3766-# it under the terms of the GNU General Public License as published by
3767-# the Free Software Foundation, either version 3 of the License, or
3768-# (at your option) any later version.
3769-#
3770-# Luciole is distributed in the hope that it will be useful,
3771-# but WITHOUT ANY WARRANTY; without even the implied warranty of
3772-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
3773-# GNU General Public License for more details.
3774-#
3775-# You should have received a copy of the GNU General Public License
3776-# along with Luciole. If not, see <http://www.gnu.org/licenses/>.
3777-#
3778-#
3779-
3780-import pygtk
3781-pygtk.require("2.0")
3782-
3783-import os.path
3784-import shutil
3785-import gtk
3786-
3787-import gtk.glade
3788-
3789-
3790-import luciole_class as MC
3791-import luciole_global as MG
3792-import luciole_acquisition as MACQ
3793-import luciole_constants as MCONST
3794-import luciole_tools as MT
3795-import luciole_manage_recent as MMR
3796-import string
3797-import copy
3798-#import elementtree.ElementTree as ET
3799-import xml.etree.ElementTree as ET #python 2.5
3800-import re
3801-from gettext import gettext as _
3802-
3803-
3804-class luciole_fileChooser(object) :
3805-
3806- open_project_filename = ""
3807- def __init__(self,gladefile) :
3808- """Init of object luciole_fileChooser."""
3809- self._gladefile=gladefile
3810- def load_file(self,windowname) :
3811- """Load a project file from GUI."""
3812- self.openFileWindow=gtk.glade.XML(self._gladefile,windowname)
3813- dialog = self.openFileWindow.get_widget(windowname)
3814- dic = {
3815- }
3816- self.openFileWindow.signal_autoconnect (dic)
3817- response = dialog.run()
3818- if response == gtk.RESPONSE_OK:
3819- self.open_project_filename = dialog.get_filename()
3820- projectObj = MG.luciole_global.dico[luciole_project_file.__name__]
3821- projectObj.load_from_file(self.open_project_filename)
3822- elif response == gtk.RESPONSE_CANCEL:
3823- print 'Closed, no files selected'
3824- #on ferme la fenetre
3825- dialog.destroy()
3826-
3827- ##### CALLBACKS
3828- def open_destroy(self,widget):
3829- pass
3830- def save(self) :
3831- """Save a project from GUI."""
3832- projectObj = MG.luciole_global.dico[luciole_project_file.__name__]
3833- projectObj.save_to_file()
3834- def save_as(self,windowname) :
3835- """Save as another project from GUI."""
3836- self.openFileWindow=gtk.glade.XML(self._gladefile,windowname)
3837- dialog = self.openFileWindow.get_widget(windowname)
3838- dic = {
3839- }
3840- self.openFileWindow.signal_autoconnect (dic)
3841- response = dialog.run()
3842- if response == gtk.RESPONSE_OK:
3843- # les folder se recupere aussi via filename
3844- self.open_project_folder = dialog.get_filename()
3845- projectObj = MG.luciole_global.dico[luciole_project_file.__name__]
3846- projectObj.save_to_new_project(self.open_project_folder)
3847- elif response == gtk.RESPONSE_CANCEL:
3848- print 'Closed, no files selected'
3849- #on ferme la fenetre
3850- dialog.destroy()
3851-
3852-class luciole_project_file(object):
3853- """Class used to manage the files saving/reading using element tree"""
3854-
3855- ### Class properties
3856- def get_filename(self):
3857- return self.__filename
3858- def set_filename(self,filename) :
3859- self.__filename=filename
3860- filename = property(get_filename,set_filename,None,"pathname to a luciole xml file")
3861-
3862- def get_capture_dir(self):
3863- return self.datas.capture_dir
3864- capture_dir=property(get_capture_dir,None,None,"Path to capture directory")
3865-
3866- def get_project_dir(self):
3867- return self.datas.project_dir
3868- project_dir=property(get_project_dir,None,None,"Path to project directory")
3869-
3870- def get_src_dir(self): return self.datas.src_dir
3871- src_dir=property(get_src_dir,None,None,"Path to project directory")
3872-
3873- def get_export_dir(self): return self.datas.export_dir
3874- export_dir=property(get_export_dir,None,None,"Path to export directory")
3875-
3876- def get_chrono_dir(self):return self.datas.chrono_dir
3877- chrono_dir=property(get_chrono_dir,None,None,"Path to chronology directory")
3878-
3879- def get_ProjectLoaded(self): return self.__ProjectLoaded
3880- ProjectLoaded=property(get_ProjectLoaded,None,None,"Project Loaded status")
3881-
3882- def get_acquisition(self): return self.__acquisition
3883- acquisition=property(get_acquisition,None,None,"Returns the acquisition object")
3884-
3885- def get_projectmodified(self): return self.datas.projectmodified
3886- projectmodified=property(get_projectmodified,None,None,"Returns the projectmodified object")
3887-
3888- def get_fpi(self) : return int(self.datas._fpi)
3889- def set_fpi(self,x) :
3890- self.datas._fpi=int(x)
3891- # if fpi is changed project is changed, update of XML file is needed
3892- elem=self.__doc_et.find("metas/fpi")
3893- elem.text=str(self.datas._fpi)
3894- self.datas.projectmodified = MCONST.PROJECT_MODIFIED
3895- self.__ChronoWidget.upadteTreeviewTime(self.datas._fpi)
3896- fpi = property(get_fpi,set_fpi,None,"Number of frame per Image")
3897-
3898- def __init__(self,filename=None) :
3899- """init function of luciole_project file"""
3900- #init du dictionnaire global d'objet
3901- if not self.__class__.__name__ in MG.luciole_global.dico :
3902- MG.luciole_global.dico[self.__class__.__name__] = self
3903- else :
3904- print "l objet",self.__class__.__name__," existe deja"
3905- return None
3906-
3907- #recuperation des objetsCapture et Chrono et appgui
3908- self.__CaptureWidget = MG.luciole_global.dico[MC.LucioleGtkTreeView.__name__]
3909- self.__ChronoWidget = MG.luciole_global.dico[MC.LucioleGtkTreeViewChrono.__name__]
3910-
3911- # init des datas
3912- self.datas=luciole_project_datas()
3913- self.datas.projectmodified = MCONST.PROJECT_NOT_MODIFIED
3914-
3915- #par defaut pas de projet
3916- self.__ProjectLoaded=False
3917-
3918- # list of file to suppress. Empty at startup
3919- self.__fileToSuppress=[]
3920- self.__filename = None
3921-
3922- if (filename):
3923- self.__load_from_file(filename)
3924- else :
3925- # pas de fichier on creer un structure vide
3926- self.__load_dummy()
3927-
3928- ### PUBLIC METHODS
3929- def load_from_file(self,infile,checkModified=False) :
3930- """Load a project from file. Interface method.
3931- if current project modified ask for loading
3932- """
3933- if checkModified :
3934- if self.datas.projectmodified == self.__filename :
3935- print "Project modified ask for keep or save"
3936- # build dialog to interaction with user
3937- # get appgui object for message display
3938- self._GuiObj = MG.luciole_global.dico['appgui']
3939- msg = _('Current open project has been modified.\n Save before opening new project ?')
3940- diaQuestion = self._GuiObj.buildDialog(msg,
3941- gtk.STOCK_DIALOG_WARNING,
3942- (gtk.STOCK_YES,gtk.RESPONSE_YES),
3943- (gtk.STOCK_NO,gtk.RESPONSE_NO) ,
3944- (gtk.STOCK_CANCEL,gtk.RESPONSE_CANCEL)
3945- )
3946- diaQuestion.show_all()
3947- resultQuestion= diaQuestion.run()
3948- if (resultQuestion == gtk.RESPONSE_YES) :
3949- # save project and load new one
3950- self.__save_to_file()
3951- self.__load_from_file(infile)
3952- if (resultQuestion == gtk.RESPONSE_NO) :
3953- # load new project without save
3954- self.__load_from_file(infile)
3955- diaQuestion.destroy()
3956- # load project only if project is not the same
3957- elif infile != self.__filename: self.__load_from_file(infile)
3958- # load project only if project is not the same
3959- elif infile != self.__filename: self.__load_from_file(infile)
3960-
3961- def save_to_file(self, file =None):
3962- """ Save Project to a file. Inerface Method."""
3963- self.__save_to_file(file)
3964-
3965- def save_to_new_project(self,projectdir):
3966- """ Save Luciole project to a new directory."""
3967- # get the name of the new dir
3968- newdir = os.path.basename(projectdir)
3969- newprojectXmlfile=newdir+".xml"
3970- # TODO :
3971- # copy images to new dir
3972- folders=["work","export","src"]
3973- for folder in folders :
3974- luciole_file_tools.copytree(os.path.join(self.datas.project_dir,folder),os.path.join(projectdir,folder))
3975- # update element tree file
3976- elem=self.__doc_et.find("metas/projectName")
3977- elem.text=newdir
3978- elem=self.__doc_et.find("metas/projectPath")
3979- elem.text=projectdir
3980- # update XML file with new dir
3981- # luciole_project_datas.project_dir is update here because method
3982- # __save_to_file use thi property as basename
3983- self.datas.project_dir=projectdir
3984- self.__save_to_file(newprojectXmlfile)
3985- # load in luciole saved project to update all datas in project
3986- self.__load_from_file(os.path.join(projectdir,newprojectXmlfile))
3987-
3988- def new_project(self,projectdir,projectData) :
3989- """ Set a new project."""
3990- #create the new dirrectory
3991- os.mkdir(projectdir)
3992- # create the directories structure
3993- folders=["work","work/capture","work/chrono","work/trash","export","src",]
3994- for folder in folders :
3995- os.mkdir(os.path.join(projectdir,folder))
3996-
3997- # get the name of the new dir
3998- newdir = os.path.basename(projectdir)
3999-
4000- # Full path to Xml project file
4001- newprojectXmlfile=newdir+".xml"
4002-
4003- #load element template elementreefile
4004- self.__doc_et=ET.parse("./templates/project_template.xml")
4005- # update element tree file
4006- elem=self.__doc_et.find("metas/projectName")
4007- elem.text = newdir
4008- elem=self.__doc_et.find("metas/projectPath")
4009- elem.text = projectdir
4010- #update fpi
4011- elem=self.__doc_et.find("metas/fpi")
4012- if (projectData['FPI']):
4013- elem.text=str(projectData['FPI'])
4014- else :
4015- elem.text=str(4)
4016- print " !!! No FPI selected, default value 5 frame per image is set "
4017-
4018- #update hardtype
4019- elem=self.__doc_et.find("metas/hardtype")
4020- if (projectData['HardType']):
4021- elem.attrib['id']=str(projectData['HardType'])
4022- hard_type_desc = ET.SubElement(elem, 'hard_type_desc')
4023- hard_type_desc.text=MCONST.HardTypeName[projectData['HardType']]
4024- # in case of webcam save specific data
4025- if projectData['HardType'] == MCONST.WEBCAM and projectData['webcam_bin_data'] != None :
4026- hard_type_data = ET.SubElement(elem, 'hard_type_data')
4027- # create new elements with same tage name as dictionary
4028- for k,v in projectData['webcam_bin_data'].iteritems() :
4029- t_elem = ET.SubElement(hard_type_data,k)
4030- t_elem.attrib['key'] = str(v)
4031- else :
4032- elem.attrib['id']=str(MCONST.FAKE)
4033- elem.text=MCONST.HardTypeName[MCONST.FAKE]
4034- print " !!! No hardware selected, FAKE hardware selected"
4035-
4036- self.datas.project_dir=projectdir
4037- self.__save_to_file(os.path.join(projectdir,newprojectXmlfile))
4038- # load in luciole saved project to update all datas in project
4039- self.__load_from_file(os.path.join(projectdir,newprojectXmlfile))
4040-
4041- def insert(self,type,i,file) :
4042- """Add an image to luciole file structure, acccording the type of image."""
4043-
4044- #on recupere les infos de type
4045- dico_type=self.__set_type_vars(type)
4046- (TagTypeName,TagImage) = (dico_type['TagTypeName'],dico_type['TagImage'])
4047-
4048- #on recupere l'element contenant les listes d'images
4049- ListImageTag=self.__doc_et.find(TagTypeName)
4050- ListImageTag.insert(i,luciole_project_file.__createImageElement(TagImage,file))
4051- self.datas.projectmodified = MCONST.PROJECT_MODIFIED
4052-
4053- def swap(self,type,pos1,pos2):
4054- """On swape 2 position d images."""
4055- #on recupere les infos de type
4056- dico_type=self.__set_type_vars(type)
4057- (TagTypeName,TagImage) = (dico_type['TagTypeName'],dico_type['TagImage'])
4058-
4059- #on recupere l'element contenant les listes d'images
4060- ListImageTag=self.__doc_et.find(TagTypeName)
4061-
4062- #on recupere l'element en position 1 et 2
4063- elem1 = ListImageTag.__getitem__(pos1)
4064- elem2 = ListImageTag.__getitem__(pos2)
4065-
4066- # puis on swappe
4067- ListImageTag.__setitem__(pos1,elem2)
4068- ListImageTag.__setitem__(pos2,elem1)
4069- self.datas.projectmodified = MCONST.PROJECT_MODIFIED
4070-
4071- def move_after(self,type,pos_src,pos_dest) :
4072- """ move image tag in pos_src after image tag in pos_dest"""
4073- # get type info
4074- dico_type=self.__set_type_vars(type)
4075- (TagTypeName,TagImage) = (dico_type['TagTypeName'],dico_type['TagImage'])
4076-
4077- # get image's list element
4078- ListImageTag=self.__doc_et.find(TagTypeName)
4079-
4080- # get src elem
4081- src_elem = ListImageTag.__getitem__(pos_src)
4082- # insert it after dest pos.
4083- ListImageTag.insert(pos_dest+1,src_elem)
4084- # remove src_elem
4085- ListImageTag.__delitem__(pos_src)
4086-
4087- self.datas.projectmodified = MCONST.PROJECT_MODIFIED
4088-
4089- def move_before(self,type,pos_src,pos_dest) :
4090- """ move image tag in pos_src before image tag in pos_dest"""
4091- # get type info
4092- if ( (pos_src > pos_dest) ) :
4093- dico_type=self.__set_type_vars(type)
4094- (TagTypeName,TagImage) = (dico_type['TagTypeName'],dico_type['TagImage'])
4095-
4096- # get image's list element
4097- ListImageTag=self.__doc_et.find(TagTypeName)
4098-
4099- # get src elem
4100- src_elem = ListImageTag.__getitem__(pos_src)
4101- # remove src_elem
4102- ListImageTag.__delitem__(pos_src)
4103- # insert it before dest pos.
4104- ListImageTag.insert(pos_dest,src_elem)
4105-
4106- self.datas.projectmodified = MCONST.PROJECT_MODIFIED
4107-
4108-
4109- def append(self,type,file) :
4110- """Add an image to luciole file structure, acccording the type of image."""
4111-
4112- #TBD: When image have to be stored . Here copied from source to data or during capture
4113-
4114- #on recupere les infos de type
4115- dico_type=self.__set_type_vars(type)
4116- (TagTypeName,TagImage) = (dico_type['TagTypeName'],dico_type['TagImage'])
4117-
4118- #on recupere l'element contenant les listes d'images
4119- ListImageTag=self.__doc_et.find(TagTypeName)
4120- ListImageTag.append(luciole_project_file.__createImageElement(TagImage,file))
4121- self.datas.projectmodified = MCONST.PROJECT_MODIFIED
4122-
4123- def remove(self,type,pos):
4124- """ Remove a file from the project."""
4125- #on recupere les infos de type
4126- dico_type=self.__set_type_vars(type)
4127- (TagTypeName,TagImage,BaseImagePath) = (dico_type['TagTypeName'],dico_type['TagImage'],dico_type['BaseImagePath'])
4128-
4129- ListImageTag=self.__doc_et.find(TagTypeName)
4130- # get the image name of the image to suppress and add it on list of file to suppress
4131- elemToSuppr = ListImageTag.__getitem__(pos)
4132- self.__fileToSuppress.append(os.path.join(BaseImagePath,elemToSuppr.findtext("name").strip()))
4133- # suppress the tag in XML file
4134- ListImageTag.__delitem__(pos)
4135- self.datas.projectmodified = MCONST.PROJECT_MODIFIED
4136-
4137-
4138- def ErrMessage(self,message) :
4139- messageToDisplay = message
4140- if (not message) :
4141- messageToDisplay="Troubles in loading the project"
4142- MG.luciole_global.dico['appgui'].ErrMessage(messageToDisplay)
4143-
4144- ### PRIVATE METHODS
4145- def __load_from_file(self,filename):
4146- """ Internal function for loading a project from file."""
4147- if os.path.isfile(filename) :
4148- #save name of previously loaded project
4149- if self.__ProjectLoaded :
4150- ManagerObj = MG.luciole_global.dico[MMR.luciole_recent.__name__]
4151- ManagerObj.add_project(self.__filename)
4152-
4153- self.__filename=filename
4154- self.__doc_et=ET.parse(self.filename)
4155- self.__doc_original = copy.copy(self.__doc_et) # make a copy , keep the original version
4156- self.datas.filename= os.path.basename(self.__filename)
4157- self.__parse_file()
4158- # update the Main window title
4159- MG.luciole_global.dico['appgui'].update_main_window_name(self.datas.project_name)
4160- # projet chargé
4161- self.__ProjectLoaded=True
4162- #project not modified yet
4163- self.datas.projectmodified = MCONST.PROJECT_NOT_MODIFIED
4164- # list of file to suppress. Empty when a project is loaded
4165- # clear displays
4166- MG.luciole_global.dico['appgui'].ClearDisplays(MCONST.SCREEN_BOTH)
4167- # stop acquisition if needed, deactive capture button
4168- MG.luciole_global.dico['appgui'].inactive_apercu()
4169- # active some menu
4170- MG.luciole_global.dico['appgui'].activate_project_menu()
4171- self.__fileToSuppress=[]
4172- else :
4173- self.__filename=""
4174- self.datas.filename= os.path.basename(self.__filename)
4175- print self.__class__.__name__," --- Not a file "
4176-
4177- def __load_dummy(self) :
4178- """Load a dummy file create the XML structure."""
4179- pass
4180-
4181- def __set_type_vars(self,type) :
4182- """Set xml tags according treeview to update.Returns a dictionary."""
4183- dico_type=dict()
4184- if type == MG.luciole_global.CAPTURE:
4185- dico_type['TagTypeName'] = "captureDatas"
4186- dico_type['TagImage'] = "capture_image"
4187- dico_type['BaseImagePath'] = str(self.datas.capture_dir)+"/"
4188- dico_type['ListType']= self.__CaptureWidget
4189- elif type == MG.luciole_global.CHRONO :
4190- dico_type['TagTypeName'] = "chronoDatas"
4191- dico_type['TagImage'] = "chrono_image"
4192- dico_type['BaseImagePath'] = str(self.datas.chrono_dir)+"/"
4193- dico_type['ListType']= self.__ChronoWidget
4194- elif type == MG.luciole_global.SRC :
4195- dico_type['TagTypeName'] = "srcDatas"
4196- dico_type['TagImage'] = "src_image"
4197- dico_type['BaseImagePath'] = str(self.datas.src_dir)+"/"
4198- dico_type['ListType']=""
4199- else:
4200- print "ERR -format inconnu dans", self.__loadImage.__name__, "(",__name__,")"
4201- return dico_type
4202-
4203- def __loadImage(self,type) :
4204- """Load images from xml file."""
4205-
4206- # on configure on fonction du type
4207- dico_type=self.__set_type_vars(type)
4208- (TagTypeName,TagImage,BaseImagePath,ListType) = (dico_type['TagTypeName'],dico_type['TagImage'],dico_type['BaseImagePath'],dico_type['ListType'])
4209-
4210- #d'abord on clear les images
4211- ListType.clear_all()
4212- #get an elemnttree iterator on images
4213- CaptureTag=self.__doc_et.find(TagTypeName)
4214- list_capture = CaptureTag.getiterator(TagImage)
4215- if (len(list_capture) != 0):
4216- #image exists
4217- imageLoaded=[]
4218- imageListTreeview =[]
4219- for image in list_capture :
4220- imageLoaded.append(image.findtext("name").strip())
4221- imagePath = BaseImagePath+(image.findtext("name").strip())
4222- if os.path.exists(imagePath) :
4223- imageListTreeview.append(imagePath)
4224- else :
4225- print "Image %s not in dir imagePath "%imagePath
4226-
4227- ListType.LoadImagesfromProject(imageListTreeview)
4228- # get the highest image name indice
4229- filelist = MT.filesInDir(BaseImagePath,'*.jpeg')
4230- # clean the image directory with the unused images for coherency between xml file and data in directory
4231- # for this operation sets are used
4232- diffImg = set(filelist).difference(set(imageLoaded))
4233- if diffImg :
4234- for imgToRemove in diffImg :
4235- #delete the unused images
4236- os.remove(os.path.join(os.path.normpath(BaseImagePath),imgToRemove))
4237- #update directory content
4238- filelist = MT.filesInDir(BaseImagePath,'*.jpeg')
4239- pattern = re.compile(r'\d+') # search sequence of number
4240- # filesInDir returns a sorted list from min to max so we get the last element :(filelist[-1])
4241- # and findall return a list with all the match, we have just one match we take the first element.
4242- MaxIndice = int(pattern.findall(filelist[-1])[0])
4243- ListType.imageFileIndex=MaxIndice+1 # update image index
4244- else :
4245- #No image to load
4246- ListType.imageFileIndex=0
4247-
4248- def __parse_file(self) :
4249- "parse the file for data retrieval from load_file"
4250-
4251- #recuperation du nom du projet et des path utilisees par le projet
4252- self.datas.project_name = self.__doc_et.findtext("metas/projectName")
4253- self.datas.project_dir = self.__doc_et.findtext("metas/projectPath")
4254- self.datas.export_dir = self.__doc_et.findtext("metas/export_dir")
4255- self.datas.capture_dir = self.datas.project_dir+"/"+self.__doc_et.findtext("metas/capture_dir")
4256- self.datas.chrono_dir = self.datas.project_dir+"/"+self.__doc_et.findtext("metas/chrono_dir")
4257- self.datas.project_trash = self.datas.project_dir+"/"+self.__doc_et.findtext("metas/trash_dir")
4258- # worlaround to be added in XML file .
4259- self.datas.src_dir = os.path.join(self.datas.project_dir,"src")
4260-
4261- # get hardtype
4262- elem=self.__doc_et.find("metas/hardtype")
4263- self.datas.hardtype = int(elem.attrib["id"])
4264-
4265- #update fpi in project and Gui
4266- self.datas.fpi = self.__doc_et.findtext("metas/fpi")
4267- self.__ChronoWidget.update_fpi_label(self.datas.fpi)
4268-
4269- self.__loadImage(MG.luciole_global.CAPTURE)
4270- self.__loadImage(MG.luciole_global.CHRONO)
4271-
4272-
4273- # create acquisition object
4274- display = MG.luciole_global.dico['appgui'].CameraArea
4275- if (self.datas.hardtype == MCONST.DIGICAM) :
4276- self.__acquisition = MACQ.luciole_acquisition_digicam(display)
4277- elif (self.datas.hardtype == MCONST.WEBCAM) :
4278- # loop on webcam datas
4279- et_webcam_data = self.__doc_et.find("//hard_type_data")
4280- if et_webcam_data != None :
4281- # loop on webcam data and save on data dictionary
4282- webcam_data={}
4283- for my_item in et_webcam_data.getchildren() :
4284- webcam_data[my_item.tag] = my_item.attrib.get("key")
4285- # create acquisition object
4286- self.__acquisition = MACQ.luciole_acquisition_webcam(
4287- display,
4288- data = webcam_data
4289- )
4290- else :
4291- print " No webcam data found "
4292- else :
4293- self.__acquisition = MACQ.luciole_acquisition(display,False,self.datas.hardtype)
4294-
4295- def __save_to_file(self,file=None):
4296- # si file et vide alors on sauve sur le fichier actuel
4297- if not file :
4298- # no file name given get stored filename
4299- file_temp = self.__filename
4300- else :
4301- file_temp = file
4302-
4303- #indentation du fichier pour meilleure presentation du fichier XML
4304- self.__indent(self.__doc_et.getroot())
4305- self.__doc_et.write(file_temp,"UTF-8")
4306- # remove the suppressed files from dir
4307- for filetoRemove in self.__fileToSuppress :
4308- print " file removed : ",filetoRemove
4309- if os.path.exists(filetoRemove) : os.remove(filetoRemove)
4310-
4311- # add saved project to history
4312- ManagerObj = MG.luciole_global.dico[MMR.luciole_recent.__name__]
4313- ManagerObj.add_project(file_temp)
4314-
4315- self.datas.projectmodified = MCONST.PROJECT_NOT_MODIFIED
4316-
4317- ### STATIC METHODS
4318- def __indent(elem, level=0):
4319- i = "\n" + level*" "
4320- if len(elem):
4321- if not elem.text or not elem.text.strip():
4322- elem.text = i + " "
4323- for elem in elem:
4324- luciole_project_file.__indent(elem, level+1)
4325- if not elem.tail or not elem.tail.strip():
4326- elem.tail = i
4327- else:
4328- if level and (not elem.tail or not elem.tail.strip()):
4329- elem.tail = i
4330- __indent=staticmethod(__indent)
4331-
4332- def __createImageElement(TagImage,text) :
4333- """Creation of image element"""
4334- #create image element
4335- el_image=ET.Element(TagImage)
4336- #create name elemnet
4337- el_name=ET.Element("name")
4338- el_name.text=text
4339- #insert name elmt. in image elmt.
4340- el_image.append(el_name)
4341- return el_image
4342- __createImageElement=staticmethod(__createImageElement)
4343-
4344-
4345-class luciole_project_datas(object):
4346- "storage of global project datas"
4347-
4348- def f_get_project_dir(self) :
4349- return self._project_dir
4350- def f_set_project_dir(self,x):
4351- if os.path.isdir(x):
4352- self._project_dir=x
4353- project_dir = property(f_get_project_dir,f_set_project_dir,None,"Path to project")
4354-
4355- def f_get_src_dir(self) :
4356- return self._src_dir
4357- def f_set_src_dir(self,x):
4358- if os.path.isdir(x):
4359- self._src_dir=x
4360- src_dir = property(f_get_src_dir,f_set_src_dir,None,"Src dir")
4361-
4362-
4363- def f_get_project_name(self) :
4364- return self._project_name
4365- def f_set_project_name(self,x) :
4366- self._project_name=x
4367- project_name = property(f_get_project_name,f_set_project_name,None,"Path to project")
4368-
4369- def f_get_project_trash(self) :
4370- return self._project_trash
4371- def f_set_project_trash(self,x) :
4372- self._project_trash=x
4373- project_trash = property(f_get_project_trash,f_set_project_trash,None,"Trash directory of project")
4374-
4375- def f_get_export_dir(self) :
4376- return self._export_dir
4377- def f_set_export_dir(self,x) :
4378- self._export_dir=x
4379- export_dir = property(f_get_export_dir,f_set_export_dir,None,"export directory of project")
4380-
4381-
4382- def f_get_filename(self) :
4383- return self._filename
4384- def f_set_filename(self,x) :
4385- self._filename=x
4386- filename = property(f_get_filename,f_set_filename,None,"Name of project file")
4387-
4388- def f_get_fpi(self) :
4389- return int(self._fpi)
4390- def f_set_fpi(self,x) :
4391- self._fpi=int(x)
4392- fpi = property(f_get_fpi,f_set_fpi,None,"Frame per second rate")
4393-
4394- def f_get_hardtype(self) :
4395- return self._hardtype
4396- def f_set_hardtype(self,x) :
4397- self._hardtype=x
4398- hardtype = property(f_get_hardtype,f_set_hardtype,None,"Hard type of the project")
4399-
4400- def f_get_projectmodified(self) :
4401- return self.__projectmodified
4402-
4403- def f_set_projectmodified(self,x) :
4404- if (self.__projectmodified != x ) :
4405- #the project as changed his state
4406- if ( x == MCONST.PROJECT_NOT_MODIFIED ) :
4407- #change to not modified
4408- self.__projectmodified = x
4409- # update the Main window title
4410- MG.luciole_global.dico['appgui'].update_main_window_name(self._project_name)
4411- elif ( x == MCONST.PROJECT_MODIFIED ) :
4412- #change to modified
4413- self.__projectmodified = x
4414- # update the Main window title
4415- MG.luciole_global.dico['appgui'].update_main_window_name(self._project_name+"(*)")
4416-
4417- projectmodified = property(f_get_projectmodified,f_set_projectmodified,None," project is modified or not")
4418-
4419-
4420- def __init__(self) :
4421- self.__projectmodified = MCONST.PROJECT_NOT_MODIFIED
4422- pass
4423-
4424-class luciole_file_tools(object) :
4425-
4426- def copy(cls,src,dest) :
4427- """ Copie de fichier."""
4428- return shutil.copy(src,dest)
4429- copy = classmethod(copy)
4430-
4431- def move(cls,src,dest) :
4432- """ move de fichier."""
4433- return shutil.move(src,dest)
4434- move = classmethod(move)
4435-
4436- def copytree(cls,src,dest) :
4437- """ Copie d arboresence."""
4438- return shutil.copytree(src,dest)
4439- copytree = classmethod(copytree)
4440-
4441- def move_to_trash(cls,path,file) :
4442- src= os.path.join(path,file)
4443- dest = os.path.join(MG.luciole_global.dico[luciole_project_file.__name__].datas.project_trash,file)
4444- luciole_file_tools.move(src,dest)
4445- move_to_trash = classmethod(move_to_trash)
4446-
4447- def __init__(self) :
4448- pass
4449-
4450
4451=== removed file 'lucioLib/luciole_global.py'
4452--- lucioLib/luciole_global.py 2009-03-29 21:48:15 +0000
4453+++ lucioLib/luciole_global.py 1970-01-01 00:00:00 +0000
4454@@ -1,41 +0,0 @@
4455-#!/usr/bin/env python
4456-# -*- coding: utf-8 -*-
4457-#
4458-#
4459-# Copyright Nicolas Bertrand (nico@inattendu.org), 2009
4460-#
4461-# This file is part of Luciole.
4462-#
4463-# Luciole is free software: you can redistribute it and/or modify
4464-# it under the terms of the GNU General Public License as published by
4465-# the Free Software Foundation, either version 3 of the License, or
4466-# (at your option) any later version.
4467-#
4468-# Luciole is distributed in the hope that it will be useful,
4469-# but WITHOUT ANY WARRANTY; without even the implied warranty of
4470-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4471-# GNU General Public License for more details.
4472-#
4473-# You should have received a copy of the GNU General Public License
4474-# along with Luciole. If not, see <http://www.gnu.org/licenses/>.
4475-#
4476-#
4477-
4478-class luciole_global(object):
4479- dico=dict()
4480-
4481- (CAPTURE,CHRONO,SRC)=range(3)
4482-
4483- def __init__(self) :
4484- print "ON passe par DICO"
4485- self.dico=dict()
4486- pass
4487-
4488- @classmethod
4489- def dump_dico(cls) :
4490- print "---------------------------------------------------------"
4491- print "dictionnaire de :", cls.__name__
4492- for cle,valeur in cls.dico.items() :
4493- print cle, ",",valeur
4494- print "---------------------------------------------------------"
4495-
4496
4497=== modified file 'lucioLib/luciole_gstreamer.py'
4498--- lucioLib/luciole_gstreamer.py 2009-04-08 19:59:23 +0000
4499+++ lucioLib/luciole_gstreamer.py 2009-04-13 20:10:28 +0000
4500@@ -35,9 +35,6 @@
4501 import gst.interfaces
4502 import gtk
4503
4504-import luciole_global as MG
4505-import luciole_file_in_out as MF
4506-import luciole_class as MC
4507 import luciole_constants as MCONST
4508 import luciole_tools as MT
4509 import os.path
4510
4511=== modified file 'lucioLib/luciole_image.py'
4512--- lucioLib/luciole_image.py 2009-04-10 15:37:06 +0000
4513+++ lucioLib/luciole_image.py 2009-04-13 13:59:33 +0000
4514@@ -5,15 +5,52 @@
4515
4516 import os.path
4517 import gtk
4518+import pango
4519 import subprocess as SP
4520+import threading
4521+import gobject
4522+import time
4523
4524 import luciole_tools as LT
4525 import luciole_constants as LCONST
4526
4527+
4528 #i18n support
4529 import gettext
4530 _ = gettext.gettext
4531
4532+class MyThumbThread(threading.Thread):
4533+ """ Thread class for genertion of thumbnails """
4534+
4535+ def __init__(self,image_list,cb_progression=None):
4536+ """
4537+ image_list : list of Image object
4538+ cb_progression : callback to indicate progression
4539+ """
4540+ super(MyThumbThread, self).__init__()
4541+ self._image_list = image_list
4542+ self.finish = False
4543+ self._cb_progression = cb_progression
4544+
4545+ def run(self):
4546+ """ Thread execution --> generation of thumbnail"""
4547+
4548+ #images are generated one by ons :
4549+ # the image.generate_pixbuf() is done with idle_add so in gui thread .
4550+ # pixbuf shall be made in gui thread to avoid lock problmes on gui
4551+ # the thread wait generaiotn of a pixbuf is done before generating a new one
4552+ # nbd : think about mulyople threads for this work (cf. old luciole_class)
4553+ for index,image in enumerate(self._image_list) :
4554+ image.generate_pixbuf_in_gui_thread()
4555+
4556+ #xait for pixbuf generation by gui thread
4557+ while image.generated == False :
4558+ time.sleep(0.05)
4559+ if self._cb_progression != None : self._cb_progression(index +1) # indicate progression
4560+ self.finish = True
4561+
4562+
4563+
4564 class Image(object):
4565
4566 # class attributes :
4567@@ -36,24 +73,81 @@
4568
4569
4570 def __init__(self, image_path = None, generate_pixbuf = False, thumb_ratio = LCONST.THUMB_RATIO ):
4571-
4572+ """ init Image object
4573+ image_path : absolute imapge path
4574+ generate_pixbuf : set to True to generate pixbuf during init
4575+ thumb_ratio : A thumb ratio from Normal size. Should be an integer value
4576+ """
4577 self._load_from_file(image_path)
4578
4579 self._pixbuf_normal = None
4580 self._pixbuf_thumb = None
4581 self._thumb_ratio = thumb_ratio
4582+ self.generated = False
4583+
4584 if generate_pixbuf == True :
4585- # generate normal and thumb pixbuf if requested
4586- self._pixbuf_normal = gtk.gdk.pixbuf_new_from_file(self._image_path)
4587-
4588- # generate thumbnail according the given ratio and image size
4589- width = self._pixbuf_normal.get_width() / self._thumb_ratio
4590- height = self._pixbuf_normal.get_height() / self._thumb_ratio
4591- self._pixbuf_thumb = self._pixbuf_normal.scale_simple( width ,
4592- height ,
4593- gtk.gdk.INTERP_BILINEAR)
4594-
4595-
4596+ # launch generation of poixbuf at init. Not threaded
4597+ self._generare_pixbuf()
4598+
4599+
4600+ def generate_pixbuf_in_gui_thread(self) :
4601+ """ generate pixbuf in gui thread : usage of idle_add"""
4602+ gobject.idle_add(self._generare_pixbuf)
4603+
4604+
4605+ def _generare_pixbuf(self) :
4606+ """ Generation of normal and thumbnail pixbuf """
4607+ self.generated = False
4608+ # generate normal and thumb pixbuf if requested
4609+ self._pixbuf_normal = gtk.gdk.pixbuf_new_from_file(self._image_path)
4610+
4611+ # generate thumbnail according the given ratio and image size
4612+ width = self._pixbuf_normal.get_width() / self._thumb_ratio
4613+ height = self._pixbuf_normal.get_height() / self._thumb_ratio
4614+
4615+ self._pixbuf_thumb = self._pixbuf_normal.scale_simple( width ,
4616+ height ,
4617+ gtk.gdk.INTERP_BILINEAR)
4618+
4619+
4620+ # This technique is used to compose image with text
4621+ # create a pixmap with the data of the pixbuf then insert text
4622+ # cf. pygtk FAQ How do I draw a text [or something else] on a gtk.gdk.pixbuf? for mor explication
4623+ # (http://faq.pygtk.org/index.py?req=show&file=faq08.020.htp )
4624+
4625+ pixmap,mask = self._pixbuf_thumb.render_pixmap_and_mask()
4626+
4627+ # graphic context and Drawarea any created to allow generation of pixbuf composition
4628+ gc = pixmap.new_gc()
4629+ area = gtk.DrawingArea()
4630+ # create pango layout
4631+ self.pangolayout = area.create_pango_layout("")
4632+
4633+ # extract only the image name without extenstion
4634+ text_buffer, ext = os.path.splitext(self._name)
4635+ text_buffer =" "+text_buffer+" "
4636+ self.pangolayout.set_text(text_buffer)
4637+ # set text attributes
4638+ attrs = pango.AttrList()
4639+ attrs.insert(pango.AttrFamily(LCONST.THUMB_TEXT_FAMILY,0,-1))
4640+ attrs.insert(pango.AttrStyle(pango.STYLE_ITALIC,0, -1))
4641+ attrs.insert(pango.AttrForeground(LCONST.THUMB_TEXT_COLOR[0],LCONST.THUMB_TEXT_COLOR[1],LCONST.THUMB_TEXT_COLOR[2],0,-1))
4642+ attrs.insert(pango.AttrBackground(0,0,0,0,-1))
4643+ attrs.insert(pango.AttrSize(LCONST.THUMB_TEXT_SIZE,0,-1))
4644+ self.pangolayout.set_attributes(attrs)
4645+
4646+ # compute text layout position and set it on pixmap
4647+ (w,h) = (self._pixbuf_thumb.get_width(),self._pixbuf_thumb.get_height())
4648+ (lw,lh) = self.pangolayout.get_pixel_size()
4649+ pixmap.draw_layout(gc, (w-lw)//2, (h -lh -2), self.pangolayout)
4650+
4651+ # function get_from_drawable gets the the pixbuf from the pixmap
4652+ # no need to affect resuly to a new pisbuf: self._pixbuf_thumb is changed whe get_from_drawable is used
4653+ self._pixbuf_thumb.get_from_drawable(pixmap, pixmap.get_colormap(), 0, 0, 0, 0, -1, -1)
4654+
4655+ self.generated =True
4656+
4657+
4658 def _load_from_file(self, image_path) :
4659 """ Private function for loading images"""
4660 if os.path.isfile(image_path) :
4661@@ -64,15 +158,47 @@
4662
4663 class Rush_images(list):
4664 """ list of images sources """
4665- # attributes :
4666- # rush_folder
4667
4668- def __init__(self,rush_folder,images_list=None) :
4669- if os.path.exists(rush_folder) :
4670+ def __init__(self,rush_folder,images_list=None,cb_progress = None) :
4671+ """ Warning : the init of Rush_images shall be done inside a thread or thread not in gui thead
4672+ rush_folder : folder whe re the images are :
4673+ images_list : list of image to generate
4674+ cb_progress : used to indicate rush_obj progress creation : (ie number of image object generated
4675+ """
4676+ if (os.path.exists(rush_folder)) :
4677 self._rush_folder = rush_folder
4678- for image in images_list :
4679- image_path = os.path.join(self._rush_folder,image)
4680- super(Rush_images,self).append(Image(image_path,True))
4681+
4682+ # if image list not empty generate images
4683+ if images_list != [] :
4684+
4685+ self._progression = 1
4686+ self._progression_ratio = 0.0
4687+ self._cb_progress = cb_progress
4688+
4689+ # the exection of pixbuf are threaded
4690+ # 1. create the image list
4691+ for image in images_list :
4692+ image_path = os.path.join(self._rush_folder,image)
4693+ super(Rush_images,self).append(Image(image_path,False))
4694+ # launch threaded generation of pixbuf
4695+ # 2. launch the thread for pixbuf generation
4696+ t_thumb = MyThumbThread(self,self._cb_on_progress)
4697+ t_thumb.start()
4698+
4699+ # 3 . Wait executiion of thread finished : means all the pixbuf where generated
4700+ while t_thumb.finish == False :
4701+ # the sleep can bemade because the executuiof rush_images is threaded
4702+ time.sleep(0.1)
4703+ else :
4704+ print _('rush folder not valid')
4705+
4706+ def _cb_on_progress(self,num) :
4707+ """ update progression number """
4708+ self._progression = num
4709+ self._progression_ratio = (self._progression*1.0)/len(self)
4710+
4711+ # indicate progression to upper level
4712+ if self._cb_progress != None : self._cb_progress(self._progression_ratio)
4713
4714 def get_image(self,image_name):
4715 """ return image object according image_name """
4716@@ -86,7 +212,24 @@
4717 def append(self,image_name) :
4718 """ append an image name : generater pixbuf """
4719 image_path = os.path.join(self._rush_folder,image_name)
4720+
4721+ # the generation of pixbuf in not threaded and made imedialtely
4722 super(Rush_images,self).append(Image(image_path,True))
4723+
4724+ def append_threaded(self,image_name) :
4725+ """ append an image name : generater pixbuf for threaded calls
4726+ Manage the iddle_add stuff for pixbuf generation
4727+ """
4728+ image_path = os.path.join(self._rush_folder,image_name)
4729+
4730+ # the generation of pixbuf in not threaded and made imedialtely
4731+ image = Image(image_path,False)
4732+ super(Rush_images,self).append(image )
4733+ image.generate_pixbuf_in_gui_thread()
4734+
4735+ while image.generated == False :
4736+ time.sleep(0.05)
4737+ return image
4738
4739 def dump_image_name(self) :
4740 """ test function display rush image """
4741
4742=== removed file 'lucioLib/luciole_import.py'
4743--- lucioLib/luciole_import.py 2009-03-08 18:06:41 +0000
4744+++ lucioLib/luciole_import.py 1970-01-01 00:00:00 +0000
4745@@ -1,136 +0,0 @@
4746-#!/usr/bin/env python
4747-# -*- coding: utf-8 -*-
4748-#
4749-#
4750-# Copyright Nicolas Bertrand (nico@inattendu.org), 2009
4751-#
4752-# This file is part of Luciole.
4753-#
4754-# Luciole is free software: you can redistribute it and/or modify
4755-# it under the terms of the GNU General Public License as published by
4756-# the Free Software Foundation, either version 3 of the License, or
4757-# (at your option) any later version.
4758-#
4759-# Luciole is distributed in the hope that it will be useful,
4760-# but WITHOUT ANY WARRANTY; without even the implied warranty of
4761-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4762-# GNU General Public License for more details.
4763-#
4764-# You should have received a copy of the GNU General Public License
4765-# along with Luciole. If not, see <http://www.gnu.org/licenses/>.
4766-#
4767-#
4768-
4769-"""
4770-luciole_import.py
4771-
4772-Started on ven 28 déc 2007 12:57:52 @USER-NAME@
4773-Last update ven 28 déc 2007 12:57:52 @USER-NAME@
4774-
4775-@Author Nico
4776-@version 1
4777-
4778-COMMENT : only PNG and JPEG are supportted.
4779-"""
4780-import gtk
4781-import gtk.glade
4782-import os.path
4783-import os
4784-import luciole_global as MG
4785-import luciole_file_in_out as MF
4786-import luciole_constants as MCONST
4787-import luciole_class as MC
4788-import Image
4789-
4790-class luciole_import(object) :
4791- """ Manage the import of images. COMMENT : only PNG and JPEG are supported.
4792-"""
4793-
4794- def __init__(self,gladefile,windowname):
4795- """ Init of module """
4796- self._gladefile=gladefile
4797- self._windowname=windowname
4798- self._tvCapture = MG.luciole_global.dico[MC.LucioleGtkTreeView.__name__]
4799-
4800- self._inputImageList =[]
4801- self._outputImageList =[]
4802- def gui_import(self) :
4803- """ Import from gui. """
4804- if ( (MF.luciole_project_file.__name__ in MG.luciole_global.dico)
4805- and
4806- ( MG.luciole_global.dico[MF.luciole_project_file.__name__].ProjectLoaded) ) :
4807- self._Project = MG.luciole_global.dico[MF.luciole_project_file.__name__]
4808- # clear imageList when a project is Loaded
4809- self._inputImageList =[]
4810- self._outputImageList =[]
4811- # a project exists and it loaded, the fileChosser Window can be opened
4812- self.openFileWindow=gtk.glade.XML(self._gladefile,self._windowname)
4813- dialog = self.openFileWindow.get_widget(self._windowname)
4814- # set user dir as default dir
4815- dialog.set_current_folder(os.path.expandvars('$HOME'))
4816-
4817- #set filters All files and all mime type images
4818- # Image filter
4819- filter = gtk.FileFilter()
4820- filter.add_mime_type("image/jpeg")
4821- filter.set_name("Images ( jpeg )")
4822- dialog.add_filter(filter)
4823-
4824- # all files
4825- filter = gtk.FileFilter()
4826- filter.add_pattern("*")
4827- filter.set_name("All files")
4828- dialog.add_filter(filter)
4829-
4830- response=dialog.run()
4831- # value 10 choosen in glade file th standard respone gtk.REPONSE_OK = -5
4832- # provides no result. It look like a bug in glade ...
4833- if response == 10 :
4834- print "Ok clicked files selected :"
4835- self._inputImageList = dialog.get_filenames()
4836- self.processImageList()
4837- elif response == gtk.RESPONSE_CANCEL:
4838- print 'Cancel clicked'
4839- #on ferme la fenetre
4840- dialog.destroy()
4841- else :
4842- # No Project Loaded send a message.
4843- message = "Opération non permise quand un projet n'est pas chargé. Veuillez créer un nouveau porojet ou en charger un."
4844- MG.luciole_global.dico['appgui'].ErrMessage(message)
4845-
4846- def processImageList(self) :
4847- """ Process the Image list , transform and Append it in capture treeview"""
4848- for image in self._inputImageList :
4849- #transform image
4850- imageTransformed = self.Transform(image)
4851- #append image in treview
4852- if imageTransformed :
4853- self._tvCapture.AppendFromCapture(imageTransformed)
4854-
4855- def Transform(self,imagePath) :
4856- """ Transform an image in jpeg format and defined size"""
4857- #open file
4858- print " Image Process : ",imagePath
4859- im = Image.open(imagePath)
4860- (base,ext) = os.path.splitext(imagePath)
4861- (rep,base) = os.path.split(base)
4862- print im.format, im.size, im.mode
4863- if im.format == "JPEG" and im.size == MCONST.VIDEO_PAL_RES :
4864- print " Nothing to do image ",imagePath," is in correct format"
4865- IsImageTransformed =False
4866- if im.size != MCONST.VIDEO_PAL_RES :
4867- # image need to be rescaled
4868- out = im.resize(MCONST.VIDEO_PAL_RES)
4869- IsImageTransformed = True
4870- # save image
4871- dirOut = os.path.join(self._Project.project_dir,"work")
4872- fileOut = base+".jpeg"
4873- fileOut = os.path.join(dirOut,fileOut)
4874- if IsImageTransformed :
4875- out.save(fileOut)
4876- else :
4877- #image not transformed just copy it
4878- MF.luciole_file_tools.copy(imagePath,fileOut)
4879- return fileOut
4880-
4881-
4882
4883=== modified file 'lucioLib/luciole_manage_recent.py'
4884--- lucioLib/luciole_manage_recent.py 2009-03-08 18:06:41 +0000
4885+++ lucioLib/luciole_manage_recent.py 2009-04-11 16:57:27 +0000
4886@@ -1,4 +1,7 @@
4887-#
4888+#!/usr/bin/env python
4889+# -*- coding: utf-8 -*-
4890+# -*- Mode: Python -*-
4891+# vi:si:ai:et:sw=4:sts=4:ts=4
4892 #
4893 # Copyright Nicolas Bertrand (nico@inattendu.org), 2009
4894 #
4895@@ -19,58 +22,53 @@
4896 #
4897 #
4898 import gtk
4899-import luciole_global as MG
4900-import luciole_file_in_out as MF
4901-import luciole_conf as MCONF
4902
4903 class luciole_recent(object):
4904 """ Manage recent projects, display
4905- 3 projects can be dsiplayed at max """
4906-
4907- __MAX_PROJECT = 3
4908-
4909- def __init__(self,ProjectList,MenuWidget) :
4910- """ Init of module """
4911- #init du dictionnaire global d'objet
4912- if not self.__class__.__name__ in MG.luciole_global.dico :
4913- MG.luciole_global.dico[self.__class__.__name__] = self
4914- else :
4915- print "l objet",self.__class__.__name__," existe deja"
4916- return None
4917-
4918- self.__ProjectList = list()
4919- self.__MenuWidget=MenuWidget
4920- if len(ProjectList) <= self.__MAX_PROJECT : self.__ProjectList.extend(ProjectList)
4921- self._displayRecentProject()
4922+ 5 projects can be dsiplayed at max """
4923+
4924+ __MAX_PROJECT = 5
4925+ __ui_recent_path = '/menubar1/menu_file/menu_file_open_recent'
4926+
4927+ def __init__(self,ProjectList,uiManager,cb_open,conf) :
4928+ """ Init of module """
4929+ self.__ProjectList = list()
4930+ self._uiManager = uiManager
4931+ self._cb_open = cb_open # callback for open project
4932+ self._conf = conf
4933+ if len(ProjectList) <= self.__MAX_PROJECT : self.__ProjectList.extend(ProjectList)
4934+
4935+ self._displayRecentProject()
4936
4937
4938 def add_project(self,project) :
4939- """ add a project ro recent used projects """
4940- # verify project is not yet present
4941- # count shall return 0
4942- if self.__ProjectList.count(project) == 0 :
4943- if len(self.__ProjectList) >= self.__MAX_PROJECT :
4944- # remove older project
4945- self.__ProjectList.pop()
4946- #insert project
4947- self.__ProjectList.insert(0,project)
4948- self._displayRecentProject()
4949- MG.luciole_global.dico[MCONF.LucioleConf.__name__].update_last_project(self.__ProjectList)
4950+ """ add a project ro recent used projects """
4951+ # verify project is not yet present
4952+ # count shall return 0
4953+ if self.__ProjectList.count(project) == 0 :
4954+ if len(self.__ProjectList) >= self.__MAX_PROJECT :
4955+ # remove older project
4956+ self.__ProjectList.pop()
4957+ #insert project
4958+ self.__ProjectList.insert(0,project)
4959+ self._displayRecentProject()
4960+ self._conf.update_last_project(self.__ProjectList)
4961
4962 def _displayRecentProject(self) :
4963- """ Update submenu widget with recently used projects """
4964- Menu = self.__MenuWidget.get_submenu()
4965- MenuChilds = Menu.get_children()
4966- # first clean menu by removing all menu childs
4967- for child in MenuChilds : Menu.remove(child)
4968- # then add menuItem for eachProject
4969- for project in self.__ProjectList :
4970- MenuItem = gtk.MenuItem(project)
4971- MenuItem.connect("activate",self.menu_activate,project)
4972- Menu.append(MenuItem)
4973- MenuItem.show()
4974+ """ Update submenu widget with recently used projects """
4975+ MenuW = self._uiManager.get_widget(self.__ui_recent_path)
4976+ Menu = MenuW.get_submenu()
4977+ MenuChilds = Menu.get_children()
4978+ # first clean menu by removing all menu childs
4979+ for child in MenuChilds : Menu.remove(child)
4980+ ## then add menuItem for eachProject
4981+ for project in self.__ProjectList :
4982+ MenuItem = gtk.MenuItem(project)
4983+ MenuItem.connect("activate",self.menu_activate,project)
4984+ Menu.append(MenuItem)
4985+ MenuItem.show()
4986
4987 def menu_activate(self,widget,project):
4988- """ Callback on menu activation. open selected project """
4989- projectObj = MG.luciole_global.dico[MF.luciole_project_file.__name__]
4990- projectObj.load_from_file(project,True)
4991+ """ Callback on menu activation. open selected project """
4992+ self._cb_open(project)
4993+
4994
4995=== removed file 'lucioLib/luciole_timer.py'
4996--- lucioLib/luciole_timer.py 2009-03-29 21:48:15 +0000
4997+++ lucioLib/luciole_timer.py 1970-01-01 00:00:00 +0000
4998@@ -1,84 +0,0 @@
4999-#!/usr/bin/env python
5000-# -*- coding: utf-8 -*-
The diff has been truncated for viewing.

Subscribers

People subscribed via source and target branches

to all changes: